var currentDir = "/";
var listElements;
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 = "
";
// empty list
result += "
"
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 = "";
if (listElements.length == 0) {
result += " | (empty) |
";
} else {
for (var i = 0; i < listElements.length; i++) {
var type = listElements[i].getAttribute("type");
var filename = listElements[i].textContent;
var mouse_click =
"onclick=\"entryMouse('" + filename + "')\"";
var full_path = currentDir + "/" + filename;
if (full_path.substr(0, 2) == "//") {
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 = "";
name_td = "" + filename + " | ";
} else if (type == "dir") {
type = "";
name_td = "" + filename + " | ";
} else {
type = "";
}
var selector = " | ";
if (filename != "..") {
selector = "☐ | ";
}
result += "" +
selector +
"" + type + " | " +
name_td +
"
";
}
}
result += "
"
var listElement = document.getElementById("list");
listElement.innerHTML = result;
}
xhr.open("GET", relativePath(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;
}
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--;
}
var selectorElement = row.getElementsByClassName("selector")[0];
selectorElement.innerHTML = "☐";
}
function setSelection(filename) {
if (filename == "..") { // don't select ".."
return;
}
var row = getRow(filename);
if (!row.classList.contains("selectedrow")) {
row.classList.add("selectedrow");
numberOfSelectedRows++;
}
var selectorElement = row.getElementsByClassName("selector")[0];
selectorElement.innerHTML = "☑";
}
function toggleSelection(filename) {
if (filename == "..") { // don't select ".."
return;
}
var row = getRow(filename);
var selector_sign;
if (row.classList.contains("selectedrow")) {
row.classList.remove("selectedrow");
numberOfSelectedRows--;
selector_sign = "☐"
} else {
row.classList.add("selectedrow");
numberOfSelectedRows++;
selector_sign = "☑"
}
var selectorElement = row.getElementsByClassName("selector")[0];
selectorElement.innerHTML = selector_sign;
}
function entryMouse(filename) {
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);
}
}
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", "?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", "?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("", "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", relativePath(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", relativePath(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("", "text/xml");
var dirElement = xmlDocument.getElementsByTagName("dirname")[0];
dirElement.appendChild(document.createTextNode(document.getElementById("newdir").value));
xhr.open("POST", relativePath(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", relativePath(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?
";
for (var i = 0; i < files.length; i++) {
message += files[i] + "
";
}
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("", "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", relativePath(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] + "
";
}
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("", "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", relativePath(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("", "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", relativePath(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("", "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", relativePath(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";
}