summaryrefslogtreecommitdiffhomepage
path: root/plugins/webbox
diff options
context:
space:
mode:
authorRoland Reichwein <mail@reichwein.it>2020-05-14 18:21:04 +0200
committerRoland Reichwein <mail@reichwein.it>2020-05-14 18:21:04 +0200
commitdef52539028cb024b4e9e9767796face08d645f6 (patch)
tree184797e14fc0bb1d625bd336094ade543d7df05e /plugins/webbox
parent72fbf82cd8ca1794fde0b1348956892fd87f2f12 (diff)
Webbox: Support subdirectory via URL. This makes webbox viable as index page
Diffstat (limited to 'plugins/webbox')
-rw-r--r--plugins/webbox/TODO14
-rw-r--r--plugins/webbox/html/webbox.js69
-rw-r--r--plugins/webbox/webbox.cpp31
3 files changed, 70 insertions, 44 deletions
diff --git a/plugins/webbox/TODO b/plugins/webbox/TODO
deleted file mode 100644
index 2ce1274..0000000
--- a/plugins/webbox/TODO
+++ /dev/null
@@ -1,14 +0,0 @@
-Prio 1 (for next version)
-======
-
-provide index for nested directories, also if requested via url
-gallery
-
-Prio 2 (for future versions)
-======
-
-google pagespeed insights https://developers.google.com/speed/pagespeed/insights/?url=http%3A%2F%2Fwww.kneipenband.com%2Fwebbox%2F&tab=mobile
-chromecast
-player
-i18n
-list: more info if appropriate, number of files, limit(?)
diff --git a/plugins/webbox/html/webbox.js b/plugins/webbox/html/webbox.js
index f1c01f5..b262f6f 100644
--- a/plugins/webbox/html/webbox.js
+++ b/plugins/webbox/html/webbox.js
@@ -1,4 +1,5 @@
var currentDir = "/";
+var rootDir = "/";
var listElements;
var numberOfSelectedRows = 0;
var username = "notaname";
@@ -11,6 +12,24 @@ function relativePath(path) {
return path;
}
+function absolutePath(path) {
+ var result = rootDir + "/" + relativePath(path);
+
+ if (rootDir.startsWith("//")) {
+ rootDir = rootDir.substr(1);
+ }
+
+ if (rootDir != "/" && rootDir.endsWith("/")) {
+ rootDir = rootDir.substr(0, rootDir.length - 1);
+ }
+
+ return result;
+}
+
+function setRootDir(dir) {
+ rootDir = dir;
+}
+
function clearContents() {
var result = "<table class=\"list\">";
// empty list
@@ -50,15 +69,10 @@ function loadContents(dir) {
full_path = full_path.substr(1);
}
- // make relative path
- while (full_path.substr(0, 1) == "/") {
- full_path = full_path.substr(1);
- }
-
var name_td;
if (type == "file") {
type = "<img src=\"webbox-html/file.png\"/>";
- name_td = "<td><a href=\"" + full_path + "\"><div class=\"name\">" + filename + "</div></a></td>";
+ name_td = "<td><a href=\"" + absolutePath(full_path) + "\"><div class=\"name\">" + filename + "</div></a></td>";
} else if (type == "dir") {
type = "<img src=\"webbox-html/directory.png\"/>";
name_td = "<td class=\"name\" " + mouse_click + ">" + filename + "</td>";
@@ -87,7 +101,7 @@ function loadContents(dir) {
}
- xhr.open("GET", relativePath(dir) + "?command=list", true);
+ xhr.open("GET", absolutePath(dir) + "?command=list", true);
xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password));
xhr.send();
}
@@ -337,6 +351,12 @@ function initMainpage() {
var readOnly = serverInfo.getElementsByTagName("readonly")[0].textContent;
prepareReadOnly(readOnly);
+ var rootDir = serverInfo.getElementsByTagName("rootdir")[0].textContent;
+ setRootDir(rootDir);
+
+ // fill file list initially
+ setCurrentDir(serverInfo.getElementsByTagName("currentdir")[0].textContent);
+
// if successful: continue loading
initMainpage2();
}
@@ -349,8 +369,6 @@ function initMainpage() {
// deferred initialization after successful login
function initMainpage2() {
- // fill file list initially
- setCurrentDir("/");
// load footer
var xhrFooter = new XMLHttpRequest();
@@ -404,6 +422,13 @@ function addDirectoryLinks(path) {
}
function setCurrentDir(newDir) {
+ if (newDir.endsWith("/")) {
+ newDir = newDir.substr(0, newDir.length - 1);
+ }
+ if (!newDir.startsWith("/")) {
+ newDir = "/" + newDir;
+ }
+
currentDir = newDir;
loadContents(newDir);
@@ -462,7 +487,7 @@ function download(filename) {
filesElement.appendChild(fileElement);
}
- xhr.open("POST", relativePath(currentDir) + "?command=download-zip", true);
+ xhr.open("POST", absolutePath(currentDir) + "?command=download-zip", true);
xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password));
xhr.setRequestHeader("Content-type", "text/xml");
xhr.responseType = 'blob';
@@ -489,7 +514,7 @@ function download(filename) {
dir += "/"
}
progressOn();
- xhr.open("GET", relativePath(dir) + filename, true);
+ xhr.open("GET", absolutePath(dir) + filename, true);
xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password));
xhr.responseType = 'blob';
xhr.send();
@@ -524,7 +549,7 @@ function createDir() {
dirElement.appendChild(document.createTextNode(document.getElementById("newdir").value));
- xhr.open("POST", relativePath(currentDir) + "?command=newdir", true);
+ xhr.open("POST", absolutePath(currentDir) + "?command=newdir", true);
xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password));
xhr.setRequestHeader("Content-type", "text/xml");
xhr.send(xmlDocument);
@@ -588,7 +613,7 @@ function onUploadFile() {
formData.append("uploadfile", uploadfile.files[i]);
}
- xhr.open("POST", relativePath(currentDir) + "?command=upload", true);
+ xhr.open("POST", absolutePath(currentDir) + "?command=upload", true);
xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password));
xhr.send(formData);
}
@@ -638,7 +663,7 @@ function deleteItems() {
filesElement.appendChild(fileElement);
}
- xhr.open("POST", relativePath(currentDir) + "?command=delete", true);
+ xhr.open("POST", absolutePath(currentDir) + "?command=delete", true);
xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password));
xhr.setRequestHeader("Content-type", "text/xml");
xhr.send(xmlDocument);
@@ -703,7 +728,7 @@ function copy() {
filesElement.appendChild(fileElement);
}
- xhr.open("POST", relativePath(currentDir) + "?command=copy", true);
+ xhr.open("POST", absolutePath(currentDir) + "?command=copy", true);
xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password));
xhr.setRequestHeader("Content-type", "text/xml");
xhr.send(xmlDocument);
@@ -768,7 +793,7 @@ function move() {
filesElement.appendChild(fileElement);
}
- xhr.open("POST", relativePath(currentDir) + "?command=move", true);
+ xhr.open("POST", absolutePath(currentDir) + "?command=move", true);
xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password));
xhr.setRequestHeader("Content-type", "text/xml");
xhr.send(xmlDocument);
@@ -832,7 +857,7 @@ function rename() {
newnameElement.appendChild(document.createTextNode(document.getElementById("renamenew").value));
filesElement.appendChild(newnameElement);
- xhr.open("POST", relativePath(currentDir) + "?command=rename", true);
+ xhr.open("POST", absolutePath(currentDir) + "?command=rename", true);
xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password));
xhr.setRequestHeader("Content-type", "text/xml");
xhr.send(xmlDocument);
@@ -878,12 +903,14 @@ function info() {
var filesElement = xmlDocument.getElementsByTagName("files")[0];
for (var i = 0; i < files.length; i++) {
- var fileElement = xmlDocument.createElement("file");
- fileElement.appendChild(document.createTextNode(files[i]));
- filesElement.appendChild(fileElement);
+ if (files[i] != "..") {
+ var fileElement = xmlDocument.createElement("file");
+ fileElement.appendChild(document.createTextNode(files[i]));
+ filesElement.appendChild(fileElement);
+ }
}
- xhr.open("POST", relativePath(currentDir) + "?command=info", true);
+ xhr.open("POST", absolutePath(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 4abb2bf..09ac7c5 100644
--- a/plugins/webbox/webbox.cpp
+++ b/plugins/webbox/webbox.cpp
@@ -32,7 +32,7 @@ namespace {
static const std::string DOWNLOAD_FILENAME{"webbox-download.zip"};
- // STATIC_HTML_TARGET: no leading slash because comparision is done with relative path;
+ // STATIC_HTML_TARGET: no leading slash because comparison 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"};
@@ -75,7 +75,7 @@ namespace {
return result;
}
- std::unordered_map<std::string, std::string> ParseQueryString(std::string s)
+ std::unordered_map<std::string, std::string> ParseQueryString(const std::string& s, const std::string& webboxPath)
{
std::unordered_map<std::string, std::string> result;
@@ -88,7 +88,10 @@ namespace {
result[urlDecode(i.substr(0, pos))] = urlDecode(i.substr(pos + 1));
}
}
- } else if (s == "/" || s == "" || boost::algorithm::starts_with(s, STATIC_HTML_TARGET)) {
+ } else if (s.empty() || s.back() == '/' || boost::algorithm::starts_with(s, STATIC_HTML_TARGET) ||
+ boost::algorithm::contains(s, "/"s + STATIC_HTML_TARGET) ||
+ (s.back() != '/' && fs::exists(webboxPath + "/" + s) && fs::is_directory(webboxPath + "/" + s)))
+ {
result["command"] = "static-html";
}
@@ -104,12 +107,13 @@ namespace {
std::string m_pathInfo; // path inside webbox, derived from request
fs::path m_path; // local filesystem path
- std::unordered_map<std::string, std::string> paramHash;
-
std::string webboxPath;
std::string webboxName;
bool webboxReadOnly;
fs::path webboxStaticHtml;
+ std::string m_rootdir;
+
+ std::unordered_map<std::string, std::string> paramHash;
CommandParameters(
std::function<std::string(const std::string& key)>& GetServerParam,
@@ -119,11 +123,12 @@ namespace {
: m_GetServerParam(GetServerParam)
, m_GetRequestParam(GetRequestParam)
, m_SetResponseHeader(SetResponseHeader)
- , paramHash(ParseQueryString(GetRequestParam("rel_target"))) // rel_target contains query string
, webboxPath(m_GetRequestParam("doc_root"))
, webboxName(m_GetRequestParam("WEBBOX_NAME"))
, webboxReadOnly(m_GetRequestParam("WEBBOX_READONLY") == "1")
, webboxStaticHtml(m_GetRequestParam("WEBBOX_STATIC_HTML"))
+ , m_rootdir(m_GetRequestParam("plugin_path"))
+ , paramHash(ParseQueryString(GetRequestParam("rel_target"), webboxPath)) // rel_target contains query string
{
if (webboxStaticHtml == "")
webboxStaticHtml = STATIC_HTML_DOC_ROOT;
@@ -327,6 +332,7 @@ protected:
// Retrieve from Server:
// Title
// ReadOnly flag
+// Root directory: Where in the HTTP URL is the webbox root located, e.g. /webbox1
class ServerInfoCommand: public GetCommand
{
public:
@@ -344,6 +350,8 @@ protected:
pt::ptree tree;
tree.put("serverinfo.title", p.webboxName);
tree.put("serverinfo.readonly", p.webboxReadOnly ? "1" : "0");
+ tree.put("serverinfo.rootdir", p.m_rootdir);
+ tree.put("serverinfo.currentdir", p.m_pathInfo);
std::ostringstream ss;
pt::xml_parser::write_xml(ss, tree);
return ss.str();
@@ -400,6 +408,7 @@ protected:
}
};
+// Info about single or multiple files
class InfoCommand: public PostCommand
{
public:
@@ -838,8 +847,10 @@ protected:
virtual std::string start(CommandParameters& p)
{
// redirect to xyz/ if xyz was requested
- std::string target = p.m_GetRequestParam("target");
- if (p.m_pathInfo == "" && !target.empty() && target.back() != '/') {
+ std::string target { p.m_GetRequestParam("target") };
+ if (!target.empty() && target.back() != '/' &&
+ (p.m_pathInfo.empty() || (fs::exists(p.webboxPath + "/" + p.m_pathInfo) && fs::is_directory(p.webboxPath + "/" + p.m_pathInfo))))
+ {
p.m_SetResponseHeader("location", target + "/");
return HttpStatus("301", "Use correct index: /"s, p);
}
@@ -847,10 +858,12 @@ protected:
try {
fs::path file_path;
- if (p.m_pathInfo == "/" || p.m_pathInfo == "") {
+ if (p.m_pathInfo.empty() || p.m_pathInfo.back() == '/') {
file_path = p.webboxStaticHtml / "index.html";
} else if (boost::algorithm::starts_with(p.m_pathInfo, STATIC_HTML_TARGET)) {
file_path = p.webboxStaticHtml / p.m_pathInfo.substr(STATIC_HTML_TARGET.size());
+ } else if (boost::algorithm::contains(p.m_pathInfo, "/"s + STATIC_HTML_TARGET)) {
+ file_path = p.webboxStaticHtml / p.m_pathInfo.substr(p.m_pathInfo.find("/"s + STATIC_HTML_TARGET) + STATIC_HTML_TARGET.size() + 1);
} else {
return HttpStatus("500", "Bad request: "s + p.m_pathInfo, p);
}