summaryrefslogtreecommitdiffhomepage
path: root/plugins/webbox
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/webbox')
-rw-r--r--plugins/webbox/Makefile16
-rw-r--r--plugins/webbox/html/directory.pngbin0 -> 683 bytes
-rw-r--r--plugins/webbox/html/favicon.icobin0 -> 2238 bytes
-rw-r--r--plugins/webbox/html/file.pngbin0 -> 530 bytes
-rw-r--r--plugins/webbox/html/index.html108
-rw-r--r--plugins/webbox/html/menu.pngbin0 -> 456 bytes
-rw-r--r--plugins/webbox/html/refresh-inverted.pngbin0 -> 771 bytes
-rw-r--r--plugins/webbox/html/webbox.css289
-rw-r--r--plugins/webbox/html/webbox.js889
9 files changed, 1296 insertions, 6 deletions
diff --git a/plugins/webbox/Makefile b/plugins/webbox/Makefile
index 2ddec0e..1850018 100644
--- a/plugins/webbox/Makefile
+++ b/plugins/webbox/Makefile
@@ -94,14 +94,18 @@ googletest/src/%.o: googletest/src/%.cc
ADD_DEP=Makefile
install:
- mkdir -p $(DESTDIR)/usr/bin
- cp webserver $(DESTDIR)/usr/bin
-
mkdir -p $(DESTDIR)/usr/lib/webserver/plugins
- mkdir -p $(DESTDIR)/usr/local/lib/webserver/plugins
+ cp $(PROJECTNAME).so $(DESTDIR)/usr/lib/webserver/plugins
+
+ mkdir -p $(DESTDIR)/var/www/webbox
+ cp -r html/* $(DESTDIR)/var/www/webbox/
+
+ # Minify, conditionally
+ command -v uglifyjs && uglifyjs html/webbox.js -m -c > $(DESTDIR)/var/www/webbox/webbox.js || true
+ command -v htmlmin && \
+ htmlmin html/index.html $(DESTDIR)/var/www/webbox/index.html || true
+ command -v cleancss && cleancss -o $(DESTDIR)/var/www/webbox/webbox.css html/webbox.css || true
- mkdir -p $(DESTDIR)/etc
- cp webserver.conf $(DESTDIR)/etc/webserver.conf
# misc ---------------------------------------------------
deb:
diff --git a/plugins/webbox/html/directory.png b/plugins/webbox/html/directory.png
new file mode 100644
index 0000000..5b4dc10
--- /dev/null
+++ b/plugins/webbox/html/directory.png
Binary files differ
diff --git a/plugins/webbox/html/favicon.ico b/plugins/webbox/html/favicon.ico
new file mode 100644
index 0000000..e8cbddb
--- /dev/null
+++ b/plugins/webbox/html/favicon.ico
Binary files differ
diff --git a/plugins/webbox/html/file.png b/plugins/webbox/html/file.png
new file mode 100644
index 0000000..a5c92e6
--- /dev/null
+++ b/plugins/webbox/html/file.png
Binary files differ
diff --git a/plugins/webbox/html/index.html b/plugins/webbox/html/index.html
new file mode 100644
index 0000000..e9ea819
--- /dev/null
+++ b/plugins/webbox/html/index.html
@@ -0,0 +1,108 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <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>
+ </head>
+ <body onload="initMainpage();">
+ <div>
+ <table>
+ <tr>
+ <td class="title">Webbox</td>
+ <td class="menusymbol" onclick="showMenu();"><img src="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>
+ </tr>
+ </table>
+ </div>
+ <div id="list">
+ </div>
+
+ <div class="greyout fullscreen" id="greyout" hidden>
+ </div>
+
+ <div class="dialogwindow" id="dialogwindow" hidden>
+ <div id="dialog" class="dialog">
+ </div>
+ <button class="button leftbutton" id="cancelbutton">Cancel</button>
+ <button class="button rightbutton" id="okbutton">OK</button>
+ </div>
+
+ <div class="menuwindow" id="menuwindow" hidden>
+ <div class="menudiv">
+ <table class="menudialog">
+ <tr class="writecommand"><td class="entry" onclick="hideMenu(); createDir();">New Folder</td></tr>
+ <tr><td class="entry" onclick="hideMenu(); download();">Download</td></tr>
+ <tr class="writecommand"><td class="entry" onclick="hideMenu(); upload();">Upload</td></tr>
+ <tr class="writecommand"><td class="entry" onclick="hideMenu(); deleteItems();">Delete</td></tr>
+ <tr class="writecommand"><td class="entry" onclick="hideMenu(); move();">Move</td></tr>
+ <tr class="writecommand"><td class="entry" onclick="hideMenu(); rename();">Rename</td></tr>
+ <tr><td class="entry" onclick="hideMenu(); info();">Info</td></tr>
+ <tr><td class="entry" onclick="hideMenu(); selectAll();">Select/Unselect All</td></tr>
+ <tr id="logoutcommand" hidden><td class="entry" onclick="hideMenu(); logout();">Logout</td></tr>
+ <tr><td class="entry" onclick="hideMenu();">Close Menu</td></tr>
+ </table>
+ </div>
+ </div>
+
+ <div class="progresswindow" id="progresswindow" hidden>
+ <canvas id="progresscanvas" class="progresscanvas" width="100" height="100"></canvas>
+ </div>
+
+ <div id="create-dir-dialog" hidden>
+ New folder:<br>
+ <input type="text" id="newdir" class="textinput"></input>
+ </div>
+
+ <div id="download-zip-dialog" hidden>
+ Download multiple files as ZIP?<br>
+ </div>
+
+ <div id="move-dialog" hidden>
+ Moving files to folder:<br>
+ <input type="text" id="movedir" class="textinput"></input>
+ <br/>
+ Files to move:
+ <br/>
+ <div id="movefiles"></div>
+ </div>
+
+ <div id="rename-dialog" hidden>
+ Old name:
+ <br/>
+ <div id="renameold"></div>
+ <br/>
+ New name:<br>
+ <input type="text" id="renamenew" class="textinput"></input>
+ <br/>
+ </div>
+
+ <div id="login-dialog" hidden>
+ <span id="logintitle">Webbox</span><br/>
+ <br/>
+ Username:<br/>
+ <input type="text" id="loginusername" class="textinput"></input>
+ Password:<br/>
+ <input type="password" id="loginpassword" class="textinput"></input>
+ </div>
+
+ <div id="logout-dialog" hidden>
+ Are you sure you want to log out?
+ </div>
+
+ <a id="download-a" hidden></a>
+
+ <div class="footer">
+ </div>
+
+ </body>
+</html>
+
diff --git a/plugins/webbox/html/menu.png b/plugins/webbox/html/menu.png
new file mode 100644
index 0000000..907434c
--- /dev/null
+++ b/plugins/webbox/html/menu.png
Binary files differ
diff --git a/plugins/webbox/html/refresh-inverted.png b/plugins/webbox/html/refresh-inverted.png
new file mode 100644
index 0000000..fd51afd
--- /dev/null
+++ b/plugins/webbox/html/refresh-inverted.png
Binary files differ
diff --git a/plugins/webbox/html/webbox.css b/plugins/webbox/html/webbox.css
new file mode 100644
index 0000000..89f4885
--- /dev/null
+++ b/plugins/webbox/html/webbox.css
@@ -0,0 +1,289 @@
+div, td, h1 {
+ font-family: "sans-serif";
+}
+
+.title {
+ font-size: 16pt;
+ width: 100%;
+}
+
+.greyout {
+ opacity: 0.7;
+ background-color: #FFFFFF;
+ z-index: 9; /* behind dialog window which is 10 */
+}
+
+.button {
+ background-color: #303060;
+ border: none;
+ color: white;
+ padding: 18px;
+ text-align: center;
+ text-decoration: none;
+ display: inline-block;
+ font-size: 16px;
+ margin: 2px 2px;
+ border-radius: 6px;
+ cursor: pointer;
+}
+
+.leftbutton {
+ position: absolute;
+ left: 20px;
+ bottom: 20px;
+}
+
+.rightbutton {
+ position: absolute;
+ right: 20px;
+ bottom: 20px;
+}
+
+.menuwindow {
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ width: 400px;
+ height: 400px;
+ margin-top: -200px;
+ margin-left: -200px;
+ background-color: #FFFFFF;
+ opacity: 1;
+ z-index: 10;
+ border-width: 3px;
+ border-style: solid;
+ border-color: #808080;
+ padding: 10pt;
+ box-sizing: border-box;
+}
+
+.menusymbol {
+ cursor: pointer;
+}
+
+.dialogwindow {
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ width: 400px;
+ height: 400px;
+ margin-top: -200px;
+ margin-left: -200px;
+ background-color: #FFFFFF;
+ opacity: 1;
+ z-index: 10;
+ border-width: 3px;
+ border-style: solid;
+ border-color: #808080;
+ padding: 10pt;
+ box-sizing: border-box;
+}
+
+
+.progresswindow {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background-color: rgba(0, 0, 0, 0);
+ opacity: 1;
+ z-index: 20;
+ border-width: 0;
+ border-collapse: collapse;
+ box-sizing: border-box;
+}
+
+.progresscanvas {
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ transform: translate(-50%, -50%);
+ background-color: rgba(0, 0, 0, 0);
+}
+table.menudialog {
+ width: 100%;
+}
+
+.menudiv {
+ height: 100%;
+ overflow-y: scroll;
+}
+
+table.menudialog td.entry {
+ cursor: pointer;
+ border-width: 0;
+ border-bottom-width: 1px;
+ border-style: solid;
+ border-color: #808080;
+ padding: 10px;
+}
+
+.dialog {
+ height: calc(100% - 85px);
+ overflow-y: scroll;
+}
+
+.textinput {
+ width: calc(100% - 20px);
+}
+
+.fullscreen {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ border: 0;
+}
+
+div.footer {
+ font-size: 8pt;
+ padding-top: 30pt;
+ text-align: center;
+}
+
+table.menu {
+ border: 0; /* 1px solid #000000; */
+ border-collapse: collapse;
+ margin: 0;
+ padding: 0;
+ table-layout: fixed;
+}
+
+table.menu tr {
+ border: 0; /* 1px solid #000000; */
+ margin: 0;
+ padding: 0;
+}
+
+table.menu td.firsttd {
+ width: 100%;
+ border: 0; /* 1px solid #000000; */
+ color: #FFFFFF;
+ background-color: #404070;
+ margin: 0;
+ padding: 0 5px 0 5px;
+}
+
+table.menu td.entry {
+ border: 0; /* 1px solid #000000; */
+ color: #FFFFFF;
+ background-color: #404070;
+ padding: 9px;
+ margin: 0;
+ cursor: pointer;
+}
+
+table.list {
+ width: 100%;
+ table-layout: fixed;
+ border: 0; /* 1px solid #000000; */
+ cursor: pointer;
+ background-color: #FFFFFF;
+ border-collapse: collapse;
+}
+
+table.list tr {
+ background-color: #FFFFFF;
+}
+
+table.list tr.selectedrow {
+ background-color: #CCCCFF;
+}
+
+table.list td {
+ border-width: 0;
+ border-bottom-width: 1px;
+ border-style: solid;
+ border-color: #808080;
+}
+
+table.list td.type {
+ width: 30px;
+}
+
+table.list td.name {
+ width: 100%;
+ color: #0000FF;
+ white-space: pre;
+ overflow: hidden;
+}
+
+@media only screen and (min-width: 1px) and (max-width: 630px) {
+ .menuwindow {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ margin: 0;
+ }
+
+ .dialogwindow {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ margin: 0;
+ }
+
+ .progresswindow {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ margin: 0;
+ }
+
+ table.list td {
+ padding: 5px;
+ }
+}
+
+/* Tooltip container */
+.tooltip {
+ position: relative;
+ display: inline-block;
+}
+
+/* Tooltip text */
+.tooltip .tooltiptext {
+ visibility: hidden;
+ background-color: #FFFFDD;
+ color: #000000;
+ text-align: center;
+ padding: 5px;
+ border-style: solid;
+ border-width: 1px;
+ border-color: #000000;
+ position: fixed;
+ right: 20px;
+ bottom: 20px;
+ z-index: 1;
+}
+
+/* Show the tooltip text when you mouse over the tooltip container */
+.tooltip:hover .tooltiptext {
+ visibility: visible;
+}
+
+.fullwidth {
+ width: 100%;
+ border: 0;
+ margin: 0;
+ padding: 0;
+ border-collapse: collapse;
+}
+
+::-moz-selection { /* Firefox */
+ color: #000000;
+ background: #FFFFFF;
+}
+
+::selection {
+ color: #000000;
+ background: #FFFFFF;
+}
diff --git a/plugins/webbox/html/webbox.js b/plugins/webbox/html/webbox.js
new file mode 100644
index 0000000..9a38051
--- /dev/null
+++ b/plugins/webbox/html/webbox.js
@@ -0,0 +1,889 @@
+var currentDir = "/";
+var listElements;
+var numberOfSelectedRows = 0;
+var username = "notaname";
+var password = "password";
+
+function clearContents() {
+ var result = "<table class=\"list\">";
+ // empty list
+ result += "</table>"
+
+ var listElement = document.getElementById("list");
+
+ listElement.innerHTML = result;
+}
+
+function loadContents(dir) {
+ numberOfSelectedRows = 0;
+
+ var xhr = new XMLHttpRequest();
+
+ xhr.onreadystatechange = function() {
+ if (this.readyState != 4 || this.status != 200) {
+ return;
+ }
+
+ var list = xhr.responseXML;
+ listElements = list.getElementsByTagName("listentry");
+
+ var result = "<div class=\"fullwidth tooltip\"><table class=\"list\">";
+
+ if (listElements.length == 0) {
+ result += "<tr><td class=\"type\"></td><td class=\"name\">(empty)</td></tr>";
+ } else {
+ for (var i = 0; i < listElements.length; i++) {
+ var type = listElements[i].getAttribute("type");
+ if (type == "file") {
+ type = "<img src=\"file.png\"/>";
+ } else if (type == "dir") {
+ type = "<img src=\"directory.png\"/>";
+ } else {
+ type = "";
+ }
+
+ result += "<tr " +
+ "onmousedown=\"entryMouseDown('" + listElements[i].textContent + "')\" " +
+ "onmouseup=\"entryMouseUp('" + listElements[i].textContent + "')\"" +
+ "><td class=\"type\">" + type + "</td><td class=\"name\">" + listElements[i].textContent + "</td></tr>";
+ }
+ }
+
+ result += "</table><div class=\"tooltiptext\">To select entry,<br/>click and hold</div></div>"
+
+ var listElement = document.getElementById("list");
+
+ listElement.innerHTML = result;
+
+ }
+
+ xhr.open("GET", "bin" + dir + "?command=list", true);
+ xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password));
+ xhr.send();
+}
+
+// return list of file names
+function getFileList() {
+ var result = [];
+
+ for (var i = 0; i < listElements.length; i++) {
+ result.push(listElements[i].childNodes[0].nodeValue);
+ }
+
+ return result;
+}
+
+function getFileType(filename) {
+ for (var i = 0; i < listElements.length; i++) {
+ if (listElements[i].childNodes[0].nodeValue == filename) {
+ return listElements[i].getAttribute("type");
+ }
+ }
+ return "";
+}
+
+function getRow(filename) {
+ var list = document.getElementById("list");
+ var rows = list.getElementsByTagName("tr");
+
+ for (var i = 0; i < rows.length; i++) {
+ var nameElement = rows[i].getElementsByClassName("name")[0];
+ if (nameElement.childNodes[0].nodeValue == filename) {
+ return rows[i];
+ }
+ }
+ return "";
+}
+
+// return list of files
+function getSelectedFiles() {
+ var result = [];
+ var list = document.getElementById("list");
+ var rows = list.getElementsByTagName("tr");
+
+ for (var i = 0; i < rows.length; i++) {
+ if (rows[i].classList.contains("selectedrow")) {
+ result.push(rows[i].getElementsByClassName("name")[0].childNodes[0].nodeValue);
+ }
+ }
+
+ return result;
+}
+
+// As long as this is 1, the mouse was pressed less than 1 second ago
+var mouseShortFlag = 0;
+var mouseTimeout = undefined;
+
+function getSelection(filename) {
+ var row = getRow(filename);
+
+ if (row.classList.contains("selectedrow")) {
+ return true;
+ }
+ return false;
+}
+
+function clearSelection(filename) {
+ var row = getRow(filename);
+
+ if (row.classList.contains("selectedrow")) {
+ row.classList.remove("selectedrow");
+ numberOfSelectedRows--;
+ }
+}
+
+function setSelection(filename) {
+ if (filename == "..") { // don't select ".."
+ return;
+ }
+
+ var row = getRow(filename);
+
+ if (!row.classList.contains("selectedrow")) {
+ row.classList.add("selectedrow");
+ numberOfSelectedRows++;
+ }
+}
+
+function toggleSelection(filename) {
+ if (filename == "..") { // don't select ".."
+ return;
+ }
+
+ var row = getRow(filename);
+
+ if (row.classList.contains("selectedrow")) {
+ row.classList.remove("selectedrow");
+ numberOfSelectedRows--;
+ } else {
+ row.classList.add("selectedrow");
+ numberOfSelectedRows++;
+ }
+}
+
+function mouseTimeoutFunction(filename) {
+ mouseShortFlag = 0;
+ toggleSelection(filename);
+}
+
+function entryMouseDown(filename) {
+ if (mouseTimeout !== undefined) {
+ clearTimeout(mouseTimeout);
+ }
+
+ if (numberOfSelectedRows > 0) {
+ toggleSelection(filename);
+ } else {
+ mouseShortFlag = 1;
+ mouseTimeout = setTimeout(function(){ mouseTimeoutFunction(filename); }, 1000);
+ }
+}
+
+function entryMouseUp(filename) {
+ if (mouseTimeout !== undefined) {
+ clearTimeout(mouseTimeout);
+ }
+
+ // short click: download / change dir
+ if (mouseShortFlag) {
+ var type = getFileType(filename);
+ if (type == "file") {
+ download(filename);
+ } else if (type == "dir") {
+ if (filename == "..") {
+ if (!currentDir.includes("/")) {
+ // error: this shouldn't happen
+ alert("Bad path " + currentDir + " for " + filename);
+ return;
+ }
+ currentDir = currentDir.substr(0, currentDir.lastIndexOf("/"));
+
+ if (currentDir == "") {
+ currentDir = "/";
+ }
+
+ setCurrentDir(currentDir);
+ return;
+ }
+
+ if (!currentDir.endsWith("/")) {
+ currentDir += "/";
+ }
+ setCurrentDir(currentDir + filename);
+ }
+ }
+
+ mouseShortFlag = 0;
+}
+
+function showDialog() {
+ document.getElementById("greyout").style.display = 'block';
+ document.getElementById("dialogwindow").style.display = 'block';
+ document.getElementById("okbutton").focus();
+}
+
+function hideDialog() {
+ document.getElementById("greyout").style.display = 'none';
+ document.getElementById("dialogwindow").style.display = 'none';
+}
+
+function showMenu() {
+ document.getElementById("greyout").style.display = 'block';
+ document.getElementById("menuwindow").style.display = 'block';
+}
+
+function hideMenu() {
+ document.getElementById("greyout").style.display = 'none';
+ document.getElementById("menuwindow").style.display = 'none';
+}
+
+// if readOnly = "1", disable respective controls since this setting is global and constant
+function prepareReadOnly(readOnly) {
+ if (readOnly == "1") {
+ var writecommands = document.getElementsByClassName("writecommand");
+ for (var i = 0; i < writecommands.length; i++) {
+ writecommands[i].style.display = "none";
+ }
+ }
+}
+
+function login(title) {
+ showDialog();
+
+ document.getElementById("okbutton").onclick = function() {
+ // restore dialog buttons
+ document.getElementById("cancelbutton").style.display = "block";
+ document.getElementById("okbutton").childNodes[0].nodeValue = "OK";
+ hideDialog();
+
+ username = document.getElementById("loginusername").value;
+ password = document.getElementById("loginpassword").value;
+
+ initMainpage();
+ }
+
+ // rearrange dialog buttons
+ document.getElementById("cancelbutton").style.display = "none";
+ document.getElementById("okbutton").childNodes[0].nodeValue = "Login";
+
+ document.getElementById("dialog").innerHTML = document.getElementById("login-dialog").innerHTML;
+
+ document.getElementById("logintitle").childNodes[0].nodeValue = title;
+
+ document.getElementById("loginusername").focus();
+
+ document.getElementById("loginusername").onkeydown = function(evt) {
+ if (evt.key == "Enter") {
+ document.getElementById("okbutton").click();
+ }
+ }
+
+ document.getElementById("loginpassword").onkeydown = function(evt) {
+ if (evt.key == "Enter") {
+ document.getElementById("okbutton").click();
+ }
+ }
+}
+
+function initMainpage() {
+ // load title
+ var xhrTitle = new XMLHttpRequest();
+
+ xhrTitle.onreadystatechange = function() {
+ if (this.readyState != 4) {
+ return;
+ }
+ if (this.status == 401) { // login error: goto login page
+ var authheader = this.getResponseHeader("WWW-Authenticate");
+ var title = "Webbox";
+ // For web servers with standard AUTH BASIC, triggering problems in
+ // client browsers, popping up the browser's "Authenticate" window
+ // but we want our own
+ if (authheader.startsWith("Basic realm=\"") && authheader.endsWith("\"")) {
+ title = authheader.substr(13, authheader.length - 14);
+ } else
+ // Fixed up Apache server
+ if (authheader.startsWith("SR_Basic realm=\"") && authheader.endsWith("\"")) {
+ title = authheader.substr(16, authheader.length - 17);
+ }
+
+ // enable logout function if logging in
+ document.getElementById("logoutcommand").style.display = "table-row";
+
+ login(title);
+ return;
+ } else
+ if (this.status != 200) {
+ document.getElementsByClassName("title")[0].innerHTML = "HTTP error";
+ return;
+ }
+
+ var serverInfo = xhrTitle.responseXML;
+ var title = serverInfo.getElementsByTagName("title")[0].textContent;
+ document.getElementsByClassName("title")[0].innerHTML = title;
+
+ var readOnly = serverInfo.getElementsByTagName("readonly")[0].textContent;
+ prepareReadOnly(readOnly);
+
+ // if successful: continue loading
+ initMainpage2();
+ }
+
+ xhrTitle.open("GET", "bin?command=server-info", true);
+ xhrTitle.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password));
+ xhrTitle.send();
+
+}
+
+// deferred initialization after successful login
+function initMainpage2() {
+ // fill file list initially
+ setCurrentDir("/");
+
+ // load footer
+ var xhrFooter = new XMLHttpRequest();
+
+ xhrFooter.onreadystatechange = function() {
+ if (this.readyState != 4 || this.status != 200) {
+ return;
+ }
+ document.getElementsByClassName("footer")[0].innerHTML = xhrFooter.responseText;
+ }
+
+ xhrFooter.open("GET", "bin?command=version", true);
+ xhrFooter.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password));
+ xhrFooter.send();
+
+ // default action for "Cancel" button: hide dialog window
+ document.getElementById("cancelbutton").onclick = hideDialog;
+
+ // on click outside of menu, close menu
+ document.getElementById("greyout").onclick = function() {
+ hideDialog();
+ hideMenu();
+ }
+
+ // on Escape, globally hide dialog and menu window
+ document.onkeydown = function(evt) {
+ if (evt.key == "Escape") {
+ hideDialog();
+ hideMenu();
+ }
+ }
+}
+
+function setCurrentDir(newDir) {
+ currentDir = newDir;
+ loadContents(newDir);
+
+ var menu = document.getElementsByClassName("menu")[0];
+ var firsttd = menu.getElementsByClassName("firsttd")[0];
+ firsttd.innerHTML = newDir;
+}
+
+function download(filename) {
+ var files = getSelectedFiles();
+
+ // if activated via menu, download directly (not as zip)
+ if (files.length == 1 && filename === undefined) {
+ filename = files[0];
+ }
+
+ if (filename === undefined) { // download selection as ZIP
+ showDialog();
+
+ if (files.length == 0) {
+ document.getElementById("dialog").innerHTML = "No files selected.";
+ document.getElementById("okbutton").onclick = hideDialog;
+ return;
+ }
+
+ document.getElementById("dialog").innerHTML = document.getElementById("download-zip-dialog").innerHTML;
+
+ document.getElementById("okbutton").onclick = function() {
+ hideDialog();
+
+ // send info request for files
+ var xhr = new XMLHttpRequest();
+
+ xhr.onreadystatechange = function() {
+ if (this.readyState != 4 || this.status != 200) {
+ return;
+ }
+
+ var a = document.getElementById("download-a");
+ a.setAttribute("download", "webbox-download.zip");
+ var file = new Blob([this.response]);
+ a.href = window.URL.createObjectURL(file);
+ a.click();
+ progressOff();
+ }
+
+ progressOn();
+ var files = getSelectedFiles();
+ var parser = new DOMParser();
+ var xmlDocument = parser.parseFromString("<files></files>", "text/xml");
+ 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);
+ }
+
+ xhr.open("POST", "bin" + currentDir + "?command=download-zip", true);
+ xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password));
+ xhr.setRequestHeader("Content-type", "text/xml");
+ xhr.responseType = 'blob';
+ xhr.send(xmlDocument);
+ }
+ } else { // single file download
+ var xhr = new XMLHttpRequest();
+
+ xhr.onreadystatechange = function() {
+ if (this.readyState != 4 || this.status != 200) {
+ return;
+ }
+
+ var a = document.getElementById("download-a");
+ a.setAttribute("download", filename);
+ var file = new Blob([this.response]);
+ a.href = window.URL.createObjectURL(file);
+ a.click();
+ progressOff();
+ }
+
+ var dir = currentDir;
+ if (dir != "/") {
+ dir += "/"
+ }
+ progressOn();
+ xhr.open("GET", "bin" + dir + filename, true);
+ xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password));
+ xhr.responseType = 'blob';
+ xhr.send();
+ }
+}
+
+function createDir() {
+ showDialog();
+
+ // hide dialog when done
+ document.getElementById("okbutton").onclick = function() {
+ // send new folder request for directory
+ var xhr = new XMLHttpRequest();
+
+ xhr.onreadystatechange = function() {
+ if (this.readyState != 4) {
+ return;
+ }
+ if (this.status != 200) {
+ document.getElementById("dialog").innerHTML = "HTTP error";
+ } else {
+ document.getElementById("dialog").innerHTML = xhr.responseText;
+ }
+ document.getElementById("okbutton").onclick = hideDialog;
+ document.getElementById("okbutton").focus();
+ loadContents(currentDir); // load new file list with new dir
+ }
+
+ var parser = new DOMParser();
+ var xmlDocument = parser.parseFromString("<dirname></dirname>", "text/xml");
+ var dirElement = xmlDocument.getElementsByTagName("dirname")[0];
+
+ dirElement.appendChild(document.createTextNode(document.getElementById("newdir").value));
+
+ xhr.open("POST", "bin" + currentDir + "?command=newdir", true);
+ xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password));
+ xhr.setRequestHeader("Content-type", "text/xml");
+ xhr.send(xmlDocument);
+ }
+
+ document.getElementById("dialog").innerHTML = document.getElementById("create-dir-dialog").innerHTML;
+ document.getElementById("newdir").focus();
+
+ document.getElementById("newdir").onkeydown = function(evt) {
+ if (evt.key == "Enter") {
+ document.getElementById("okbutton").click();
+ }
+ }
+}
+
+function upload() {
+ var uploadfile = document.getElementById("uploadfile");
+
+ uploadfile.click();
+}
+
+// Callback on selected and uploaded file
+function onUploadFile() {
+ var xhr = new XMLHttpRequest();
+
+ xhr.onreadystatechange = function() {
+ if (this.readyState != 4) {
+ return;
+ }
+
+ showDialog();
+ var message = "";
+
+ if (this.status != 200) {
+ message = "HTTP error";
+ } else {
+ if (xhr.responseText == "") {
+ message = "Upload successful.";
+ loadContents(currentDir); // load new file list with uploaded file
+ } else {
+ message = xhr.responseText;
+ }
+ }
+
+ document.getElementById("dialog").innerHTML = message;
+ document.getElementById("cancelbutton").style.display = "none";
+ document.getElementById("okbutton").onclick = function() {
+ hideDialog();
+ document.getElementById("cancelbutton").style.display = "block";
+ }
+ document.getElementById("okbutton").focus();
+ progressOff();
+ }
+
+ progressOn();
+
+ var uploadfile = document.getElementById("uploadfile");
+ var formData = new FormData();
+
+ for (var i = 0; i < uploadfile.files.length; i++) {
+ formData.append("uploadfile", uploadfile.files[i]);
+ }
+
+ xhr.open("POST", "bin" + currentDir + "?command=upload", true);
+ xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password));
+ xhr.send(formData);
+}
+
+function deleteItems() {
+ showDialog();
+
+ var files = getSelectedFiles();
+ if (files.length == 0) {
+ document.getElementById("dialog").innerHTML = "No files selected.";
+ document.getElementById("okbutton").onclick = hideDialog;
+ return;
+ }
+
+ var message = "Are sure to delete the following files and directories?<br/><br/>";
+
+ for (var i = 0; i < files.length; i++) {
+ message += files[i] + "<br/>";
+ }
+
+ document.getElementById("dialog").innerHTML = message;
+
+ document.getElementById("okbutton").onclick = function() {
+
+ var xhr = new XMLHttpRequest();
+
+ xhr.onreadystatechange = function() {
+ if (this.readyState != 4) {
+ return;
+ }
+ if (this.status != 200) {
+ document.getElementById("dialog").innerHTML = "HTTP error";
+ } else {
+ document.getElementById("dialog").innerHTML = xhr.responseText;
+ }
+ document.getElementById("okbutton").onclick = hideDialog;
+ loadContents(currentDir); // load new file list with deleted items
+ }
+
+ var parser = new DOMParser();
+ var xmlDocument = parser.parseFromString("<files></files>", "text/xml");
+ 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);
+ }
+
+ xhr.open("POST", "bin" + currentDir + "?command=delete", true);
+ xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password));
+ xhr.setRequestHeader("Content-type", "text/xml");
+ xhr.send(xmlDocument);
+ }
+}
+
+function move() {
+ showDialog();
+
+ var files = getSelectedFiles();
+ if (files.length == 0) {
+ document.getElementById("dialog").innerHTML = "No files selected.";
+ document.getElementById("okbutton").onclick = hideDialog;
+ return;
+ }
+
+ var message = "";
+ for (var i = 0; i < files.length; i++) {
+ message += files[i] + "<br/>";
+ }
+
+ document.getElementById("dialog").innerHTML = document.getElementById("move-dialog").innerHTML;
+ document.getElementById("movedir").focus();
+ document.getElementById("movedir").onkeydown = function(evt) {
+ if (evt.key == "Enter") {
+ document.getElementById("okbutton").click();
+ }
+ }
+
+ document.getElementById("movefiles").innerHTML = message;
+
+ document.getElementById("okbutton").onclick = function() {
+
+ var xhr = new XMLHttpRequest();
+
+ xhr.onreadystatechange = function() {
+ if (this.readyState != 4) {
+ return;
+ }
+ if (this.status != 200) {
+ document.getElementById("dialog").innerHTML = "HTTP error";
+ } else {
+ document.getElementById("dialog").innerHTML = xhr.responseText;
+ }
+
+ document.getElementById("okbutton").onclick = hideDialog;
+ document.getElementById("okbutton").focus();
+ loadContents(currentDir); // load new file list with deleted items
+ }
+
+ var parser = new DOMParser();
+ var xmlDocument = parser.parseFromString("<request></request>", "text/xml");
+ var filesElement = xmlDocument.getElementsByTagName("request")[0];
+
+ var targetElement = xmlDocument.createElement("target");
+ targetElement.appendChild(document.createTextNode(document.getElementById("movedir").value));
+ filesElement.appendChild(targetElement);
+
+ for (var i = 0; i < files.length; i++) {
+ var fileElement = xmlDocument.createElement("file");
+ fileElement.appendChild(document.createTextNode(files[i]));
+ filesElement.appendChild(fileElement);
+ }
+
+ xhr.open("POST", "bin" + currentDir + "?command=move", true);
+ xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password));
+ xhr.setRequestHeader("Content-type", "text/xml");
+ xhr.send(xmlDocument);
+ }
+}
+
+function rename() {
+ showDialog();
+
+ var files = getSelectedFiles();
+ if (files.length == 0) {
+ document.getElementById("dialog").innerHTML = "No files selected.";
+ document.getElementById("okbutton").onclick = hideDialog;
+ return;
+ }
+ if (files.length > 1) {
+ document.getElementById("dialog").innerHTML = "Only one file can be renamed at once.";
+ document.getElementById("okbutton").onclick = hideDialog;
+ return;
+ }
+
+ document.getElementById("renameold").innerHTML = files[0];
+
+ document.getElementById("dialog").innerHTML = document.getElementById("rename-dialog").innerHTML;
+ document.getElementById("renamenew").value = files[0];
+ document.getElementById("renamenew").focus();
+ document.getElementById("renamenew").onkeydown = function(evt) {
+ if (evt.key == "Enter") {
+ document.getElementById("okbutton").click();
+ }
+ }
+
+ document.getElementById("okbutton").onclick = function() {
+
+ var xhr = new XMLHttpRequest();
+
+ xhr.onreadystatechange = function() {
+ if (this.readyState != 4) {
+ return;
+ }
+ if (this.status != 200) {
+ document.getElementById("dialog").innerHTML = "HTTP error";
+ } else {
+ document.getElementById("dialog").innerHTML = xhr.responseText;
+ }
+
+ document.getElementById("okbutton").onclick = hideDialog;
+ document.getElementById("okbutton").focus();
+ loadContents(currentDir); // load new file list with deleted items
+ }
+
+ var parser = new DOMParser();
+ var xmlDocument = parser.parseFromString("<request></request>", "text/xml");
+ var filesElement = xmlDocument.getElementsByTagName("request")[0];
+
+ var oldnameElement = xmlDocument.createElement("oldname");
+ oldnameElement.appendChild(document.createTextNode(document.getElementById("renameold").childNodes[0].nodeValue));
+ filesElement.appendChild(oldnameElement);
+
+ var newnameElement = xmlDocument.createElement("newname");
+ newnameElement.appendChild(document.createTextNode(document.getElementById("renamenew").value));
+ filesElement.appendChild(newnameElement);
+
+ xhr.open("POST", "bin" + currentDir + "?command=rename", true);
+ xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password));
+ xhr.setRequestHeader("Content-type", "text/xml");
+ xhr.send(xmlDocument);
+ }
+}
+
+// File info: date, size, type
+function info() {
+ showDialog();
+ document.getElementById("cancelbutton").style.display = "none"; // hide "cancel" button in info dialog, only provide "OK"
+
+ // hide dialog when done
+ document.getElementById("okbutton").onclick = function() {
+ hideDialog();
+ document.getElementById("cancelbutton").style.display = "block";
+ }
+
+ var files = getSelectedFiles();
+ if (files.length == 0) {
+ document.getElementById("dialog").innerHTML = "No files selected.";
+ return;
+ }
+
+ // send info request for files
+ var xhr = new XMLHttpRequest();
+
+ xhr.onreadystatechange = function() {
+ if (this.readyState != 4) {
+ return;
+ }
+ if (this.status != 200) {
+ document.getElementById("dialog").innerHTML = "HTTP error";
+ } else {
+ document.getElementById("dialog").innerHTML = xhr.responseText;
+ }
+ }
+
+ var parser = new DOMParser();
+ var xmlDocument = parser.parseFromString("<files></files>", "text/xml");
+ 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);
+ }
+
+ xhr.open("POST", "bin" + currentDir + "?command=info", true);
+ xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password));
+ xhr.setRequestHeader("Content-type", "text/xml");
+ xhr.send(xmlDocument);
+}
+
+// select all files, except if all are selected, unselect all
+function selectAll() {
+ var files = getFileList();
+
+ var allSelected = true;
+
+ for (var i = 0; i < files.length; i++) {
+ if (getSelection(files[i]) === false && files[i] != "..") {
+ allSelected = false;
+ }
+ }
+
+ for (var i = 0; i < files.length; i++) {
+ if (allSelected) {
+ clearSelection(files[i]);
+ } else {
+ setSelection(files[i]);
+ }
+ }
+}
+
+function refresh() {
+ loadContents(currentDir); // load new file list
+}
+
+function logout() {
+ showDialog();
+
+ document.getElementById("okbutton").onclick = function() {
+ hideDialog();
+
+ var menu = document.getElementsByClassName("menu")[0];
+ var firsttd = menu.getElementsByClassName("firsttd")[0];
+ firsttd.innerHTML = "/";
+
+ clearContents();
+
+ username = "notaname";
+ password = "password";
+ initMainpage();
+ }
+
+ document.getElementById("dialog").innerHTML = document.getElementById("logout-dialog").innerHTML;
+}
+
+// Progress indication
+
+function drawDot(c, offsetx, offsety, radius, distance, phase) {
+ c.beginPath();
+ c.arc(distance * Math.sin(phase) + offsetx,
+ - distance * Math.cos(phase) + offsety, radius, 0, 2 * Math.PI);
+ c.fill();
+}
+
+function drawLogo(canvasid, rotation) {
+ var canvas = document.getElementById(canvasid);
+
+ var height = canvas.height;
+ var width = canvas.width;
+ var radius = height * 0.1;
+ var distance = height * 0.1 * 4 / 3;
+
+ var c = canvas.getContext("2d");
+
+ c.clearRect(0, 0, width, height);
+ c.fillStyle = "#1132A7";
+ drawDot(c, width / 2, height / 2, radius, distance, rotation);
+ drawDot(c, width / 2, height / 2, radius, distance, rotation + 2 * Math.PI / 3);
+ drawDot(c, width / 2, height / 2, radius, distance, rotation + 2 * Math.PI / 3 * 2);
+ drawDot(c, width / 2, height / 2, radius, distance * 2, rotation + Math.PI);
+ drawDot(c, width / 2, height / 2, radius, distance * 2, rotation + Math.PI + 2 * Math.PI / 3);
+ drawDot(c, width / 2, height / 2, radius, distance * 2, rotation + Math.PI + 2 * Math.PI / 3 * 2);
+}
+
+var progressState = 0;
+
+function drawAni(timeStamp) {
+ var rotation = timeStamp / 1000 * 6;
+
+ drawLogo("progresscanvas", rotation);
+
+ if (progressState == 1) {
+ requestAnimationFrame(drawAni);
+ }
+}
+
+function progressOn() {
+ progressState = 1;
+ document.getElementById("progresswindow").style.display = "block";
+ requestAnimationFrame(drawAni);
+}
+
+function progressOff() {
+ progressState = 0;
+ document.getElementById("progresswindow").style.display = "none";
+}
+