diff options
author | Roland Reichwein <mail@reichwein.it> | 2020-05-10 16:51:20 +0200 |
---|---|---|
committer | Roland Reichwein <mail@reichwein.it> | 2020-05-10 16:51:20 +0200 |
commit | 5b32a4415c9776dd6cae859c8d718b5e68f01d81 (patch) | |
tree | 9c9684367a1d415b1d836065daca2e8789fcd1a5 | |
parent | eb7c96f1ee9cf3eff2dd86f2a1b6ea46a80e41c8 (diff) |
Move webbox to root to make index
-rw-r--r-- | README.txt | 7 | ||||
-rw-r--r-- | plugins/fcgi/fcgi.cpp | 11 | ||||
-rw-r--r-- | plugins/webbox/html/index.html | 9 | ||||
-rw-r--r-- | plugins/webbox/html/webbox.js | 33 | ||||
-rw-r--r-- | plugins/webbox/webbox.cpp | 94 | ||||
-rw-r--r-- | webserver.conf | 12 |
6 files changed, 125 insertions, 41 deletions
@@ -172,16 +172,9 @@ Configuration example: Plugin: webbox ~~~~~~~~~~~~~~ -This plugin needs a combination of static-files (for statically served parts) -and webbox plugins (for dynamic contents). - Configuration example: <path requested="/webbox1"> - <plugin>static-files</plugin> - <target>/usr/lib/webbox/html</target> - </path> - <path requested="/webbox1/bin"> <plugin>webbox</plugin> <target>/home/rr/testbox</target> <WEBBOX_NAME>Testbox1</WEBBOX_NAME> diff --git a/plugins/fcgi/fcgi.cpp b/plugins/fcgi/fcgi.cpp index f9d8a4d..a97f1c0 100644 --- a/plugins/fcgi/fcgi.cpp +++ b/plugins/fcgi/fcgi.cpp @@ -314,16 +314,6 @@ namespace { return status + " " + message; } - void DumpAppValues(const std::unordered_map<std::string, std::string>& app_values) - { - std::cout << "App properties:" << std::endl; - if (app_values.size() == 0) - std::cout << " (empty)" << std::endl; - else for (auto&[key, value]: app_values) { - std::cout << " " << key << "=" << value << std::endl; - } - } - } // anonymous namespace std::string fcgi_plugin::fcgiQuery(FCGIContext& context) @@ -448,7 +438,6 @@ std::string fcgi_plugin::fcgiQuery(FCGIContext& context) std::cerr << "FCGI STDERR: " << r.getContent() << std::endl; } else if (r.getType() == FCGI_GET_VALUES_RESULT) { FCGI_DecodeEnv(r.getContent(), app_values); - //DumpAppValues(app_values); } else throw std::runtime_error("Unhandled FCGI type: "s + std::to_string(r.getType())); } catch (const std::length_error& ex) { diff --git a/plugins/webbox/html/index.html b/plugins/webbox/html/index.html index e9ea819..cc1cf12 100644 --- a/plugins/webbox/html/index.html +++ b/plugins/webbox/html/index.html @@ -4,22 +4,23 @@ <meta charset="utf-8"/> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Webbox</title> - <link rel="stylesheet" type="text/css" href="webbox.css"/> - <script src="webbox.js"></script> + <link rel="stylesheet" type="text/css" href="webbox-html/webbox.css"/> + <link rel="shortcut icon" href="webbox-html/favicon.ico" type="image/x-icon"/> + <script src="webbox-html/webbox.js"></script> </head> <body onload="initMainpage();"> <div> <table> <tr> <td class="title">Webbox</td> - <td class="menusymbol" onclick="showMenu();"><img src="menu.png" alt=""/></td> + <td class="menusymbol" onclick="showMenu();"><img src="webbox-html/menu.png" alt=""/></td> </tr> </table> <input id="uploadfile" type="file" onchange="onUploadFile();" multiple hidden/> <table class="menu"> <tr> <td class="firsttd"></td> - <td class="entry" onclick="refresh();"><img src="refresh-inverted.png" alt=""/></td> + <td class="entry" onclick="refresh();"><img src="webbox-html/refresh-inverted.png" alt=""/></td> </tr> </table> </div> diff --git a/plugins/webbox/html/webbox.js b/plugins/webbox/html/webbox.js index 9a38051..602f76d 100644 --- a/plugins/webbox/html/webbox.js +++ b/plugins/webbox/html/webbox.js @@ -4,6 +4,13 @@ var numberOfSelectedRows = 0; var username = "notaname"; var password = "password"; +function relativePath(path) { + if (path.startsWith("/")) + return path.substr(1); + else + return path; +} + function clearContents() { var result = "<table class=\"list\">"; // empty list @@ -35,9 +42,9 @@ function loadContents(dir) { for (var i = 0; i < listElements.length; i++) { var type = listElements[i].getAttribute("type"); if (type == "file") { - type = "<img src=\"file.png\"/>"; + type = "<img src=\"webbox-html/file.png\"/>"; } else if (type == "dir") { - type = "<img src=\"directory.png\"/>"; + type = "<img src=\"webbox-html/directory.png\"/>"; } else { type = ""; } @@ -57,7 +64,7 @@ function loadContents(dir) { } - xhr.open("GET", "bin" + dir + "?command=list", true); + xhr.open("GET", relativePath(dir) + "?command=list", true); xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password)); xhr.send(); } @@ -329,7 +336,7 @@ function initMainpage() { initMainpage2(); } - xhrTitle.open("GET", "bin?command=server-info", true); + xhrTitle.open("GET", "?command=server-info", true); xhrTitle.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password)); xhrTitle.send(); @@ -350,7 +357,7 @@ function initMainpage2() { document.getElementsByClassName("footer")[0].innerHTML = xhrFooter.responseText; } - xhrFooter.open("GET", "bin?command=version", true); + xhrFooter.open("GET", "?command=version", true); xhrFooter.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password)); xhrFooter.send(); @@ -431,7 +438,7 @@ function download(filename) { filesElement.appendChild(fileElement); } - xhr.open("POST", "bin" + currentDir + "?command=download-zip", true); + xhr.open("POST", relativePath(currentDir) + "?command=download-zip", true); xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password)); xhr.setRequestHeader("Content-type", "text/xml"); xhr.responseType = 'blob'; @@ -458,7 +465,7 @@ function download(filename) { dir += "/" } progressOn(); - xhr.open("GET", "bin" + dir + filename, true); + xhr.open("GET", relativePath(dir) + filename, true); xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password)); xhr.responseType = 'blob'; xhr.send(); @@ -493,7 +500,7 @@ function createDir() { dirElement.appendChild(document.createTextNode(document.getElementById("newdir").value)); - xhr.open("POST", "bin" + currentDir + "?command=newdir", true); + xhr.open("POST", relativePath(currentDir) + "?command=newdir", true); xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password)); xhr.setRequestHeader("Content-type", "text/xml"); xhr.send(xmlDocument); @@ -557,7 +564,7 @@ function onUploadFile() { formData.append("uploadfile", uploadfile.files[i]); } - xhr.open("POST", "bin" + currentDir + "?command=upload", true); + xhr.open("POST", relativePath(currentDir) + "?command=upload", true); xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password)); xhr.send(formData); } @@ -607,7 +614,7 @@ function deleteItems() { filesElement.appendChild(fileElement); } - xhr.open("POST", "bin" + currentDir + "?command=delete", true); + xhr.open("POST", relativePath(currentDir) + "?command=delete", true); xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password)); xhr.setRequestHeader("Content-type", "text/xml"); xhr.send(xmlDocument); @@ -672,7 +679,7 @@ function move() { filesElement.appendChild(fileElement); } - xhr.open("POST", "bin" + currentDir + "?command=move", true); + xhr.open("POST", relativePath(currentDir) + "?command=move", true); xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password)); xhr.setRequestHeader("Content-type", "text/xml"); xhr.send(xmlDocument); @@ -736,7 +743,7 @@ function rename() { newnameElement.appendChild(document.createTextNode(document.getElementById("renamenew").value)); filesElement.appendChild(newnameElement); - xhr.open("POST", "bin" + currentDir + "?command=rename", true); + xhr.open("POST", relativePath(currentDir) + "?command=rename", true); xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password)); xhr.setRequestHeader("Content-type", "text/xml"); xhr.send(xmlDocument); @@ -784,7 +791,7 @@ function info() { filesElement.appendChild(fileElement); } - xhr.open("POST", "bin" + currentDir + "?command=info", true); + xhr.open("POST", relativePath(currentDir) + "?command=info", true); xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password)); xhr.setRequestHeader("Content-type", "text/xml"); xhr.send(xmlDocument); diff --git a/plugins/webbox/webbox.cpp b/plugins/webbox/webbox.cpp index 7d15ee9..c58bd0c 100644 --- a/plugins/webbox/webbox.cpp +++ b/plugins/webbox/webbox.cpp @@ -30,6 +30,11 @@ namespace { static const std::string PROGRAMVERSION{"Webbox 2.0"}; static const std::string DOWNLOAD_FILENAME{"webbox-download.zip"}; + // STATIC_HTML_TARGET: no leading slash because comparision is done with relative path; + // trailing slash because of path comparison + static const std::string STATIC_HTML_TARGET{"webbox-html/"}; + static const fs::path STATIC_HTML_DOC_ROOT{"/usr/lib/webbox/html"}; + // TODO: separate out class Tempfile { @@ -109,6 +114,8 @@ namespace { result[urlDecode(i.substr(0, pos))] = urlDecode(i.substr(pos + 1)); } } + } else if (s == "/" || s == "" || boost::algorithm::starts_with(s, STATIC_HTML_TARGET)) { + result["command"] = "static-html"; } return result; @@ -125,6 +132,7 @@ namespace { std::string webboxPath; std::string webboxName; bool webboxReadOnly; + fs::path webboxStaticHtml; CommandParameters( std::function<std::string(const std::string& key)>& GetServerParam, @@ -138,7 +146,10 @@ namespace { , webboxPath(m_GetRequestParam("doc_root")) , webboxName(m_GetRequestParam("WEBBOX_NAME")) , webboxReadOnly(m_GetRequestParam("WEBBOX_READONLY") == "1") + , webboxStaticHtml(m_GetRequestParam("WEBBOX_STATIC_HTML")) { + if (webboxStaticHtml == "") + webboxStaticHtml = STATIC_HTML_DOC_ROOT; } }; @@ -780,7 +791,83 @@ protected: return result; } catch (const std::exception& ex) { - return HttpStatus("500", "Bad file: "s + m_path.filename().string(), p); + return HttpStatus("404", "Bad file: "s + m_path.filename().string(), p); + } + } +}; + +// Return a reasonable mime type based on the extension of a file. +static std::string +mime_type(fs::path path) +{ + using boost::algorithm::iequals; + auto const ext = [&path] + { + size_t pos = path.string().rfind("."); + if (pos == std::string::npos) + return std::string{}; + return path.string().substr(pos); + }(); + if(iequals(ext, ".htm")) return "text/html"; // TODO: unordered_map + if(iequals(ext, ".html")) return "text/html"; + if(iequals(ext, ".php")) return "text/html"; + if(iequals(ext, ".css")) return "text/css"; + if(iequals(ext, ".txt")) return "text/plain"; + if(iequals(ext, ".js")) return "application/javascript"; + if(iequals(ext, ".json")) return "application/json"; + if(iequals(ext, ".xml")) return "application/xml"; + if(iequals(ext, ".swf")) return "application/x-shockwave-flash"; + if(iequals(ext, ".flv")) return "video/x-flv"; + if(iequals(ext, ".png")) return "image/png"; + if(iequals(ext, ".jpe")) return "image/jpeg"; + if(iequals(ext, ".jpeg")) return "image/jpeg"; + if(iequals(ext, ".jpg")) return "image/jpeg"; + if(iequals(ext, ".gif")) return "image/gif"; + if(iequals(ext, ".bmp")) return "image/bmp"; + if(iequals(ext, ".ico")) return "image/vnd.microsoft.icon"; + if(iequals(ext, ".tiff")) return "image/tiff"; + if(iequals(ext, ".tif")) return "image/tiff"; + if(iequals(ext, ".svg")) return "image/svg+xml"; + if(iequals(ext, ".svgz")) return "image/svg+xml"; + return "application/text"; +} + +class StaticHtmlCommand: public GetCommand +{ +public: + StaticHtmlCommand() + { + m_commandName = "static-html"; + m_isWriteCommand = false; + } + +protected: + virtual std::string start(CommandParameters& p) + { + // redirect to xyz/ if xyz was requested + std::string target = p.m_GetRequestParam("target"); + if (m_pathInfo == "" && !target.empty() && target.back() != '/') { + p.m_SetResponseHeader("location", target + "/"); + return HttpStatus("301", "Use correct index: /"s, p); + } + + try { + + fs::path file_path; + if (m_pathInfo == "/" || m_pathInfo == "") { + file_path = p.webboxStaticHtml / "index.html"; + } else if (boost::algorithm::starts_with(m_pathInfo, STATIC_HTML_TARGET)) { + file_path = p.webboxStaticHtml / m_pathInfo.substr(STATIC_HTML_TARGET.size()); + } else { + return HttpStatus("500", "Bad request: "s + m_pathInfo, p); + } + + p.m_SetResponseHeader("content_type", mime_type(file_path)); + std::string result{File::getFile(file_path)}; + return result; + + } catch (const std::exception& ex) { + return HttpStatus("500", "Server error: "s + m_pathInfo, p); } } }; @@ -805,6 +892,7 @@ webbox_plugin::webbox_plugin() registerCommand(std::make_shared<RenameCommand>()); registerCommand(std::make_shared<UploadCommand>()); registerCommand(std::make_shared<DownloadCommand>()); + registerCommand(std::make_shared<StaticHtmlCommand>()); } webbox_plugin::~webbox_plugin() @@ -818,8 +906,10 @@ std::string webbox_plugin::generate_page( std::function<void(const std::string& key, const std::string& value)>& SetResponseHeader // to be added to result string ) { - CommandParameters commandParameters(GetServerParam, GetRequestParam, SetResponseHeader); + // Queries under STATIC_HTML_TARGET will be served statically from STATIC_HTML_DOC_ROOT + CommandParameters commandParameters(GetServerParam, GetRequestParam, SetResponseHeader); + std::string commandName; auto it {commandParameters.paramHash.find("command")}; diff --git a/webserver.conf b/webserver.conf index efc1a69..4901578 100644 --- a/webserver.conf +++ b/webserver.conf @@ -23,16 +23,20 @@ </path> <path requested="/webbox1"> - <plugin>static-files</plugin> - <target>/home/ernie/code/webserver/plugins/webbox/html</target> - </path> - <path requested="/webbox1/bin"> <plugin>webbox</plugin> <target>/home/ernie/testbox</target> <WEBBOX_NAME>Testbox1</WEBBOX_NAME> <WEBBOX_READONLY>0</WEBBOX_READONLY> + <WEBBOX_STATIC_HTML>/home/ernie/code/webserver/plugins/webbox/html</WEBBOX_STATIC_HTML> <auth login="abc" password="p3p0Jka3YM5Fk"/> </path> + <path requested="/webbox2"> + <plugin>webbox</plugin> + <target>/home/ernie/testbox</target> + <WEBBOX_NAME>Testbox1</WEBBOX_NAME> + <WEBBOX_READONLY>1</WEBBOX_READONLY> + <WEBBOX_STATIC_HTML>/home/ernie/code/webserver/plugins/webbox/html</WEBBOX_STATIC_HTML> + </path> <path requested="/blog"> <plugin>weblog</plugin> <target>/home/ernie/testblog</target> |