From 1ce0bb7ad50129fbab6c0a75f18eee6149ca1be3 Mon Sep 17 00:00:00 2001
From: Roland Reichwein <mail@reichwein.it>
Date: Wed, 15 Apr 2020 15:35:58 +0200
Subject: Minify css/html/js

---
 plugins/webbox/html/directory.png        | Bin 0 -> 683 bytes
 plugins/webbox/html/favicon.ico          | Bin 0 -> 2238 bytes
 plugins/webbox/html/file.png             | Bin 0 -> 530 bytes
 plugins/webbox/html/index.html           | 108 ++++
 plugins/webbox/html/menu.png             | Bin 0 -> 456 bytes
 plugins/webbox/html/refresh-inverted.png | Bin 0 -> 771 bytes
 plugins/webbox/html/webbox.css           | 289 ++++++++++
 plugins/webbox/html/webbox.js            | 889 +++++++++++++++++++++++++++++++
 8 files changed, 1286 insertions(+)
 create mode 100644 plugins/webbox/html/directory.png
 create mode 100644 plugins/webbox/html/favicon.ico
 create mode 100644 plugins/webbox/html/file.png
 create mode 100644 plugins/webbox/html/index.html
 create mode 100644 plugins/webbox/html/menu.png
 create mode 100644 plugins/webbox/html/refresh-inverted.png
 create mode 100644 plugins/webbox/html/webbox.css
 create mode 100644 plugins/webbox/html/webbox.js

(limited to 'plugins/webbox/html')

diff --git a/plugins/webbox/html/directory.png b/plugins/webbox/html/directory.png
new file mode 100644
index 0000000..5b4dc10
Binary files /dev/null and b/plugins/webbox/html/directory.png differ
diff --git a/plugins/webbox/html/favicon.ico b/plugins/webbox/html/favicon.ico
new file mode 100644
index 0000000..e8cbddb
Binary files /dev/null and b/plugins/webbox/html/favicon.ico differ
diff --git a/plugins/webbox/html/file.png b/plugins/webbox/html/file.png
new file mode 100644
index 0000000..a5c92e6
Binary files /dev/null and b/plugins/webbox/html/file.png 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
Binary files /dev/null and b/plugins/webbox/html/menu.png differ
diff --git a/plugins/webbox/html/refresh-inverted.png b/plugins/webbox/html/refresh-inverted.png
new file mode 100644
index 0000000..fd51afd
Binary files /dev/null and b/plugins/webbox/html/refresh-inverted.png 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";
+}
+
-- 
cgit v1.2.3