Refactor tabs to spaces
parent
812130e22a
commit
fe78962db0
|
@ -1,53 +1,53 @@
|
||||||
/* jshint esversion: 6 */
|
/* jshint esversion: 6 */
|
||||||
|
|
||||||
$(document).ready(() => {
|
$(document).ready(() => {
|
||||||
let $inputs = $(".input-group-digits");
|
let $inputs = $(".input-group-digits");
|
||||||
$inputs.each((i, input) => {
|
$inputs.each((i, input) => {
|
||||||
let cleanup = () => {
|
let cleanup = () => {
|
||||||
$(input).find("input").each((i, ele) => {
|
$(input).find("input").each((i, ele) => {
|
||||||
let cleaned = $(ele).val().replace(/[^0-9]/, "");
|
let cleaned = $(ele).val().replace(/[^0-9]/, "");
|
||||||
$(ele).val(cleaned);
|
$(ele).val(cleaned);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
let update = (e) => {
|
let update = (e) => {
|
||||||
$digits = $(input).find("input");
|
$digits = $(input).find("input");
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
cleanup();
|
cleanup();
|
||||||
|
|
||||||
// Shift characters
|
// Shift characters
|
||||||
let excess = "";
|
let excess = "";
|
||||||
$digits.each((i, ele) => {
|
$digits.each((i, ele) => {
|
||||||
let now = excess + $(ele).val();
|
let now = excess + $(ele).val();
|
||||||
$(ele).val(now.charAt(0));
|
$(ele).val(now.charAt(0));
|
||||||
excess = now.substr(1);
|
excess = now.substr(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Move cursor to empty
|
// Move cursor to empty
|
||||||
$digits.each((i, ele) => {
|
$digits.each((i, ele) => {
|
||||||
if (!$(ele).val()) {
|
if (!$(ele).val()) {
|
||||||
$(ele).focus();
|
$(ele).focus();
|
||||||
if (e.which == 8) {
|
if (e.which == 8) {
|
||||||
$(ele).prev().focus().val("");
|
$(ele).prev().focus().val("");
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Submit if last digit is filled
|
// Submit if last digit is filled
|
||||||
if ($($digits[$digits.length - 1]).val()) {
|
if ($($digits[$digits.length - 1]).val()) {
|
||||||
let token = $.map(
|
let token = $.map(
|
||||||
$digits,
|
$digits,
|
||||||
d => $(d).val()
|
d => $(d).val()
|
||||||
).join("");
|
).join("");
|
||||||
let $value = $(input).parent().find("#login-token-value");
|
let $value = $(input).parent().find("#login-token-value");
|
||||||
$value.val(token);
|
$value.val(token);
|
||||||
$value.closest("form").submit();
|
$value.closest("form").submit();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
$digits = $(input).find("input");
|
$digits = $(input).find("input");
|
||||||
$digits.on("keyup", update);
|
$digits.on("keyup", update);
|
||||||
$digits.on("change", update);
|
$digits.on("change", update);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,30 +1,30 @@
|
||||||
/* jshint esversion: 6 */
|
/* jshint esversion: 6 */
|
||||||
|
|
||||||
$(document).ready(() => {
|
$(document).ready(() => {
|
||||||
let $select = $(".multi-select");
|
let $select = $(".multi-select");
|
||||||
|
|
||||||
let setSelected = (files) => {
|
let setSelected = (files) => {
|
||||||
$(".multi-files-value").val(JSON.stringify(files.map(f => f.name)));
|
$(".multi-files-value").val(JSON.stringify(files.map(f => f.name)));
|
||||||
$(".multi-files").html(
|
$(".multi-files").html(
|
||||||
files.map(f => {
|
files.map(f => {
|
||||||
return `<li class="list-group-item d-flex align-items-start justify-content-between"><span class="name">${f.name}</span> <span class="badge badge-pill badge-secondary">${f.size}</span></li>`;
|
return `<li class="list-group-item d-flex align-items-start justify-content-between"><span class="name">${f.name}</span> <span class="badge badge-pill badge-secondary">${f.size}</span></li>`;
|
||||||
}).join("")
|
}).join("")
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
let updateSelected = () => {
|
let updateSelected = () => {
|
||||||
let $selected = $(".multi-select:checked");
|
let $selected = $(".multi-select:checked");
|
||||||
let files = [];
|
let files = [];
|
||||||
$selected.each((i, ele) => {
|
$selected.each((i, ele) => {
|
||||||
files.push({
|
files.push({
|
||||||
name: $(ele).data("select"),
|
name: $(ele).data("select"),
|
||||||
size: $(ele).data("select-size")
|
size: $(ele).data("select-size")
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
setSelected(files);
|
setSelected(files);
|
||||||
}
|
}
|
||||||
|
|
||||||
$select.on("change", updateSelected);
|
$select.on("change", updateSelected);
|
||||||
updateSelected();
|
updateSelected();
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* jshint esversion: 6 */
|
/* jshint esversion: 6 */
|
||||||
|
|
||||||
$(document).ready(() => {
|
$(document).ready(() => {
|
||||||
let $shell = $("#shell");
|
let $shell = $("#shell");
|
||||||
if (!$shell) {
|
if (!$shell) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
/* jshint esversion: 6 */
|
/* jshint esversion: 6 */
|
||||||
|
|
||||||
$(document).ready(() => {
|
$(document).ready(() => {
|
||||||
let $form = $("form[action='@upload']");
|
let $form = $("form[action='@upload']");
|
||||||
let $file = $("#upload-file");
|
let $file = $("#upload-file");
|
||||||
|
|
||||||
$(".upload-unhide").fadeOut();
|
$(".upload-unhide").fadeOut();
|
||||||
|
|
||||||
$file.on("change", () => {
|
$file.on("change", () => {
|
||||||
let file = $file[0].files[0];
|
let file = $file[0].files[0];
|
||||||
let fnElement = $file.parent().find(".custom-file-label");
|
let fnElement = $file.parent().find(".custom-file-label");
|
||||||
fnElement.addClass("file-selected");
|
fnElement.addClass("file-selected");
|
||||||
fnElement.text(file.name);
|
fnElement.text(file.name);
|
||||||
|
|
||||||
$form.find("#upload-file-size").val(filesize(file.size));
|
$form.find("#upload-file-size").val(filesize(file.size));
|
||||||
$form.find("[name=saveas]").val(file.name);
|
$form.find("[name=saveas]").val(file.name);
|
||||||
$(".upload-unhide").fadeIn();
|
$(".upload-unhide").fadeIn();
|
||||||
});
|
});
|
||||||
|
|
||||||
$form.on("submit", () => {
|
$form.on("submit", () => {
|
||||||
let putresource = $form.find("[name=saveas]").val();
|
let putresource = $form.find("[name=saveas]").val();
|
||||||
// TODO: do XHR to PUT at putresource
|
// TODO: do XHR to PUT at putresource
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
833
index.js
833
index.js
|
@ -26,28 +26,28 @@ let http = app.listen(process.env.PORT || 8080);
|
||||||
|
|
||||||
app.set("views", path.join(__dirname, "views"));
|
app.set("views", path.join(__dirname, "views"));
|
||||||
app.engine("handlebars", hbs({
|
app.engine("handlebars", hbs({
|
||||||
partialsDir: path.join(__dirname, "views", "partials"),
|
partialsDir: path.join(__dirname, "views", "partials"),
|
||||||
layoutsDir: path.join(__dirname, "views", "layouts"),
|
layoutsDir: path.join(__dirname, "views", "layouts"),
|
||||||
defaultLayout: "main",
|
defaultLayout: "main",
|
||||||
helpers: {
|
helpers: {
|
||||||
eachpath: (path, options) => {
|
eachpath: (path, options) => {
|
||||||
if (typeof path != "string") {
|
if (typeof path != "string") {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
let out = "";
|
let out = "";
|
||||||
path = path.split("/");
|
path = path.split("/");
|
||||||
path.splice(path.length - 1, 1);
|
path.splice(path.length - 1, 1);
|
||||||
path.unshift("");
|
path.unshift("");
|
||||||
path.forEach((folder, index) => {
|
path.forEach((folder, index) => {
|
||||||
out += options.fn({
|
out += options.fn({
|
||||||
name: folder + "/",
|
name: folder + "/",
|
||||||
path: "/" + path.slice(1, index + 1).join("/"),
|
path: "/" + path.slice(1, index + 1).join("/"),
|
||||||
current: index === path.length - 1
|
current: index === path.length - 1
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
app.set("view engine", "handlebars");
|
app.set("view engine", "handlebars");
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ app.use("/filesize", express.static(path.join(__dirname, "node_modules/filesize/
|
||||||
app.use("/assets", express.static(path.join(__dirname, "assets")));
|
app.use("/assets", express.static(path.join(__dirname, "assets")));
|
||||||
|
|
||||||
app.use(session({
|
app.use(session({
|
||||||
secret: "meowmeow"
|
secret: "meowmeow"
|
||||||
}));
|
}));
|
||||||
app.use(flash());
|
app.use(flash());
|
||||||
app.use(busboy());
|
app.use(busboy());
|
||||||
|
@ -69,462 +69,467 @@ app.use(bodyparser.urlencoded());
|
||||||
const KEY = process.env.KEY ? base32.decode(process.env.KEY.replace(/ /g, "")) : null;
|
const KEY = process.env.KEY ? base32.decode(process.env.KEY.replace(/ /g, "")) : null;
|
||||||
|
|
||||||
app.get("/@logout", (req, res) => {
|
app.get("/@logout", (req, res) => {
|
||||||
if (KEY) {
|
if (KEY) {
|
||||||
req.session.login = false;
|
req.session.login = false;
|
||||||
req.flash("success", "Signed out.");
|
req.flash("success", "Signed out.");
|
||||||
res.redirect("/@login");
|
res.redirect("/@login");
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
req.flash("error", "You were never logged in...");
|
req.flash("error", "You were never logged in...");
|
||||||
res.redirect("back");
|
res.redirect("back");
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get("/@login", (req, res) => {
|
app.get("/@login", (req, res) => {
|
||||||
res.render("login", flashify(req, {}));
|
res.render("login", flashify(req, {}));
|
||||||
});
|
});
|
||||||
app.post("/@login", (req, res) => {
|
app.post("/@login", (req, res) => {
|
||||||
let pass = notp.totp.verify(req.body.token.replace(" ", ""), KEY);
|
let pass = notp.totp.verify(req.body.token.replace(" ", ""), KEY);
|
||||||
console.log(pass, req.body.token.replace(" ", ""));
|
console.log(pass, req.body.token.replace(" ", ""));
|
||||||
if (pass) {
|
if (pass) {
|
||||||
req.session.login = true;
|
req.session.login = true;
|
||||||
res.redirect("/");
|
res.redirect("/");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
req.flash("error", "Bad token.");
|
req.flash("error", "Bad token.");
|
||||||
res.redirect("/@login");
|
res.redirect("/@login");
|
||||||
});
|
});
|
||||||
|
|
||||||
app.use((req, res, next) => {
|
app.use((req, res, next) => {
|
||||||
if (!KEY) {
|
if (!KEY) {
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
if (req.session.login === true) {
|
if (req.session.login === true) {
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
req.flash("error", "Please sign in.");
|
req.flash("error", "Please sign in.");
|
||||||
res.redirect("/@login");
|
res.redirect("/@login");
|
||||||
});
|
});
|
||||||
|
|
||||||
function relative(...paths) {
|
function relative(...paths) {
|
||||||
return paths.reduce((a, b) => path.join(a, b), process.cwd());
|
return paths.reduce((a, b) => path.join(a, b), process.cwd());
|
||||||
}
|
}
|
||||||
function flashify(req, obj) {
|
function flashify(req, obj) {
|
||||||
let error = req.flash("error");
|
let error = req.flash("error");
|
||||||
if (error && error.length > 0) {
|
if (error && error.length > 0) {
|
||||||
if (!obj.errors) {
|
if (!obj.errors) {
|
||||||
obj.errors = [];
|
obj.errors = [];
|
||||||
}
|
}
|
||||||
obj.errors.push(error);
|
obj.errors.push(error);
|
||||||
}
|
}
|
||||||
let success = req.flash("success");
|
let success = req.flash("success");
|
||||||
if (success && success.length > 0) {
|
if (success && success.length > 0) {
|
||||||
if (!obj.successes) {
|
if (!obj.successes) {
|
||||||
obj.successes = [];
|
obj.successes = [];
|
||||||
}
|
}
|
||||||
obj.successes.push(success);
|
obj.successes.push(success);
|
||||||
}
|
}
|
||||||
obj.isloginenabled = !!KEY;
|
obj.isloginenabled = !!KEY;
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
app.all("/*", (req, res, next) => {
|
app.all("/*", (req, res, next) => {
|
||||||
res.filename = req.params[0];
|
res.filename = req.params[0];
|
||||||
|
|
||||||
let fileExists = new Promise((resolve, reject) => {
|
let fileExists = new Promise((resolve, reject) => {
|
||||||
// check if file exists
|
// check if file exists
|
||||||
fs.stat(relative(res.filename), (err, stats) => {
|
fs.stat(relative(res.filename), (err, stats) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return reject(err);
|
return reject(err);
|
||||||
}
|
}
|
||||||
return resolve(stats);
|
return resolve(stats);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
fileExists.then((stats) => {
|
fileExists.then((stats) => {
|
||||||
res.stats = stats;
|
res.stats = stats;
|
||||||
next();
|
next();
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
res.stats = { error: err };
|
res.stats = { error: err };
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// currently unused
|
// currently unused
|
||||||
app.put("/*", (req, res) => {
|
app.put("/*", (req, res) => {
|
||||||
if (res.stats.error) {
|
if (res.stats.error) {
|
||||||
req.busboy.on("file", (key, file, filename) => {
|
req.busboy.on("file", (key, file, filename) => {
|
||||||
if (key == "file") {
|
if (key == "file") {
|
||||||
let save = fs.createWriteStream(relative(res.filename));
|
let save = fs.createWriteStream(relative(res.filename));
|
||||||
file.pipe(save);
|
file.pipe(save);
|
||||||
save.on("close", () => {
|
save.on("close", () => {
|
||||||
res.flash("success", "File saved. ");
|
res.flash("success", "File saved. ");
|
||||||
res.redirect("back");
|
res.redirect("back");
|
||||||
});
|
});
|
||||||
save.on("error", (err) => {
|
save.on("error", (err) => {
|
||||||
res.flash("error", err);
|
res.flash("error", err);
|
||||||
res.redirect("back");
|
res.redirect("back");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
req.busboy.on("field", (key, value) => {
|
req.busboy.on("field", (key, value) => {
|
||||||
|
|
||||||
});
|
});
|
||||||
req.pipe(req.busboy);
|
req.pipe(req.busboy);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
req.flash("error", "File exists, cannot overwrite. ");
|
req.flash("error", "File exists, cannot overwrite. ");
|
||||||
res.redirect("back");
|
res.redirect("back");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post("/*@upload", (req, res) => {
|
app.post("/*@upload", (req, res) => {
|
||||||
res.filename = req.params[0];
|
res.filename = req.params[0];
|
||||||
|
|
||||||
let buff = null;
|
let buff = null;
|
||||||
let saveas = null;
|
let saveas = null;
|
||||||
req.busboy.on("file", (key, stream, filename) => {
|
req.busboy.on("file", (key, stream, filename) => {
|
||||||
if (key == "file") {
|
if (key == "file") {
|
||||||
let buffs = [];
|
let buffs = [];
|
||||||
stream.on("data", (d) => {
|
stream.on("data", (d) => {
|
||||||
buffs.push(d);
|
buffs.push(d);
|
||||||
});
|
});
|
||||||
stream.on("end", () => {
|
stream.on("end", () => {
|
||||||
buff = Buffer.concat(buffs);
|
buff = Buffer.concat(buffs);
|
||||||
buffs = null;
|
buffs = null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
req.busboy.on("field", (key, value) => {
|
req.busboy.on("field", (key, value) => {
|
||||||
if (key == "saveas") {
|
if (key == "saveas") {
|
||||||
saveas = value;
|
saveas = value;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
req.busboy.on("finish", () => {
|
req.busboy.on("finish", () => {
|
||||||
if (!buff || !saveas) {
|
if (!buff || !saveas) {
|
||||||
return res.status(400).end();
|
return res.status(400).end();
|
||||||
}
|
}
|
||||||
let fileExists = new Promise((resolve, reject) => {
|
let fileExists = new Promise((resolve, reject) => {
|
||||||
// check if file exists
|
// check if file exists
|
||||||
fs.stat(relative(res.filename, saveas), (err, stats) => {
|
fs.stat(relative(res.filename, saveas), (err, stats) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return reject(err);
|
return reject(err);
|
||||||
}
|
}
|
||||||
return resolve(stats);
|
return resolve(stats);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
fileExists.then((stats) => {
|
fileExists.then((stats) => {
|
||||||
req.flash("error", "File exists, cannot overwrite. ");
|
req.flash("error", "File exists, cannot overwrite. ");
|
||||||
res.redirect("back");
|
res.redirect("back");
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
console.log("saving");
|
console.log("saving");
|
||||||
let save = fs.createWriteStream(relative(res.filename, saveas));
|
let save = fs.createWriteStream(relative(res.filename, saveas));
|
||||||
save.on("close", () => {
|
save.on("close", () => {
|
||||||
if (buff.length === 0) {
|
if (buff.length === 0) {
|
||||||
req.flash("success", "File saved. Warning: empty file.");
|
req.flash("success", "File saved. Warning: empty file.");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
buff = null;
|
buff = null;
|
||||||
req.flash("success", "File saved. ");
|
req.flash("success", "File saved. ");
|
||||||
}
|
}
|
||||||
res.redirect("back");
|
res.redirect("back");
|
||||||
});
|
});
|
||||||
save.on("error", (err) => {
|
save.on("error", (err) => {
|
||||||
req.flash("error", err);
|
req.flash("error", err);
|
||||||
res.redirect("back");
|
res.redirect("back");
|
||||||
});
|
});
|
||||||
save.write(buff);
|
save.write(buff);
|
||||||
save.end();
|
save.end();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
req.pipe(req.busboy);
|
req.pipe(req.busboy);
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post("/*@mkdir", (req, res) => {
|
app.post("/*@mkdir", (req, res) => {
|
||||||
res.filename = req.params[0];
|
res.filename = req.params[0];
|
||||||
|
|
||||||
let folder = req.body.folder;
|
let folder = req.body.folder;
|
||||||
if (!folder || folder.length < 1) {
|
if (!folder || folder.length < 1) {
|
||||||
return res.status(400).end();
|
return res.status(400).end();
|
||||||
}
|
}
|
||||||
|
|
||||||
let fileExists = new Promise((resolve, reject) => {
|
let fileExists = new Promise((resolve, reject) => {
|
||||||
// Check if file exists
|
// Check if file exists
|
||||||
fs.stat(relative(res.filename, folder), (err, stats) => {
|
fs.stat(relative(res.filename, folder), (err, stats) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return reject(err);
|
return reject(err);
|
||||||
}
|
}
|
||||||
return resolve(stats);
|
return resolve(stats);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
fileExists.then((stats) => {
|
fileExists.then((stats) => {
|
||||||
req.flash("error", "Folder exists, cannot overwrite. ");
|
req.flash("error", "Folder exists, cannot overwrite. ");
|
||||||
res.redirect("back");
|
res.redirect("back");
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
fs.mkdir(relative(res.filename, folder), (err) => {
|
fs.mkdir(relative(res.filename, folder), (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
req.flash("error", err);
|
req.flash("error", err);
|
||||||
res.redirect("back");
|
res.redirect("back");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
req.flash("success", "Folder created. ");
|
req.flash("success", "Folder created. ");
|
||||||
res.redirect("back");
|
res.redirect("back");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post("/*@delete", (req, res) => {
|
app.post("/*@delete", (req, res) => {
|
||||||
res.filename = req.params[0];
|
res.filename = req.params[0];
|
||||||
|
|
||||||
let files = JSON.parse(req.body.files);
|
let files = JSON.parse(req.body.files);
|
||||||
if (!files || !files.map) {
|
if (!files || !files.map) {
|
||||||
req.flash("error", "No files selected.");
|
req.flash("error", "No files selected.");
|
||||||
res.redirect("back");
|
res.redirect("back");
|
||||||
return; // res.status(400).end();
|
return; // res.status(400).end();
|
||||||
}
|
}
|
||||||
|
|
||||||
let promises = files.map(f => {
|
let promises = files.map(f => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
fs.stat(relative(res.filename, f), (err, stats) => {
|
fs.stat(relative(res.filename, f), (err, stats) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return reject(err);
|
return reject(err);
|
||||||
}
|
}
|
||||||
resolve({
|
resolve({
|
||||||
name: f,
|
name: f,
|
||||||
isdirectory: stats.isDirectory(),
|
isdirectory: stats.isDirectory(),
|
||||||
isfile: stats.isFile()
|
isfile: stats.isFile()
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
Promise.all(promises).then((files) => {
|
Promise.all(promises).then((files) => {
|
||||||
let promises = files.map(f => {
|
let promises = files.map(f => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let op = null;
|
let op = null;
|
||||||
if (f.isdirectory) {
|
if (f.isdirectory) {
|
||||||
op = fs.rmdir;
|
op = fs.rmdir;
|
||||||
}
|
}
|
||||||
else if (f.isfile) {
|
else if (f.isfile) {
|
||||||
op = fs.unlink;
|
op = fs.unlink;
|
||||||
}
|
}
|
||||||
if (op) {
|
if (op) {
|
||||||
op(relative(res.filename, f.name), (err) => {
|
op(relative(res.filename, f.name), (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return reject(err);
|
return reject(err);
|
||||||
}
|
}
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
Promise.all(promises).then(() => {
|
Promise.all(promises).then(() => {
|
||||||
req.flash("success", "Files deleted. ");
|
req.flash("success", "Files deleted. ");
|
||||||
res.redirect("back");
|
res.redirect("back");
|
||||||
}).catch((err) => { // TODO: recursive rmdir https://github.com/isaacs/rimraf
|
}).catch((err) => { // TODO: recursive rmdir https://github.com/isaacs/rimraf
|
||||||
req.flash("error", "Unable to delete some files: " + err);
|
req.flash("error", "Unable to delete some files: " + err);
|
||||||
res.redirect("back");
|
res.redirect("back");
|
||||||
});
|
});
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
req.flash("error", err);
|
req.flash("error", err);
|
||||||
res.redirect("back");
|
res.redirect("back");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get("/*@download", (req, res) => {
|
app.get("/*@download", (req, res) => {
|
||||||
res.filename = req.params[0];
|
res.filename = req.params[0];
|
||||||
|
|
||||||
let files = null;
|
let files = null;
|
||||||
try {
|
try {
|
||||||
files = JSON.parse(req.query.files);
|
files = JSON.parse(req.query.files);
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
if (!files || !files.map) {
|
if (!files || !files.map) {
|
||||||
req.flash("error", "No files selected.");
|
req.flash("error", "No files selected.");
|
||||||
res.redirect("back");
|
res.redirect("back");
|
||||||
return; // res.status(400).end();
|
return; // res.status(400).end();
|
||||||
}
|
}
|
||||||
|
|
||||||
let promises = files.map(f => {
|
let promises = files.map(f => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
fs.stat(relative(res.filename, f), (err, stats) => {
|
fs.stat(relative(res.filename, f), (err, stats) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return reject(err);
|
return reject(err);
|
||||||
}
|
}
|
||||||
resolve({
|
resolve({
|
||||||
name: f,
|
name: f,
|
||||||
isdirectory: stats.isDirectory(),
|
isdirectory: stats.isDirectory(),
|
||||||
isfile: stats.isFile()
|
isfile: stats.isFile()
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
Promise.all(promises).then((files) => {
|
Promise.all(promises).then((files) => {
|
||||||
let zip = archiver.create("zip", {});
|
let zip = archiver.create("zip", {});
|
||||||
zip.on("error", function(err) {
|
zip.on("error", function(err) {
|
||||||
res.status(500).send({
|
res.status(500).send({
|
||||||
error: err.message
|
error: err.message
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
files.filter(f => f.isfile).forEach((f) => {
|
files.filter(f => f.isfile).forEach((f) => {
|
||||||
zip.file(relative(res.filename, f.name), { name: f.name });
|
zip.file(relative(res.filename, f.name), { name: f.name });
|
||||||
});
|
});
|
||||||
files.filter(f => f.isdirectory).forEach((f) => {
|
files.filter(f => f.isdirectory).forEach((f) => {
|
||||||
zip.directory(relative(res.filename, f.name), f.name);
|
zip.directory(relative(res.filename, f.name), f.name);
|
||||||
});
|
});
|
||||||
|
|
||||||
res.attachment("Archive.zip");
|
res.attachment("Archive.zip");
|
||||||
zip.pipe(res);
|
zip.pipe(res);
|
||||||
|
|
||||||
zip.finalize();
|
zip.finalize();
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
req.flash("error", err);
|
req.flash("error", err);
|
||||||
res.redirect("back");
|
res.redirect("back");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const shellable = process.env.SHELL != "false" && process.env.SHELL;
|
const shellable = process.env.SHELL != "false" && process.env.SHELL;
|
||||||
if (shellable) {
|
const cmdable = process.env.CMD != "false" && process.env.CMD;
|
||||||
const exec = process.env.SHELL == "login" ? "/usr/bin/env" : process.env.SHELL;
|
if (shellable || cmdable) {
|
||||||
const args = process.env.SHELL == "login" ? ["login"] : [];
|
const exec = process.env.SHELL == "login" ? "/usr/bin/env" : process.env.SHELL;
|
||||||
|
const args = process.env.SHELL == "login" ? ["login"] : [];
|
||||||
|
|
||||||
const child_process = require("child_process");
|
const child_process = require("child_process");
|
||||||
|
|
||||||
// currently unused
|
// currently unused
|
||||||
app.post("/*@cmd", (req, res) => {
|
app.post("/*@cmd", (req, res) => {
|
||||||
res.filename = req.params[0];
|
res.filename = req.params[0];
|
||||||
|
|
||||||
let cmd = req.body.cmd;
|
let cmd = req.body.cmd;
|
||||||
if (!cmd || cmd.length < 1) {
|
if (!cmd || cmd.length < 1) {
|
||||||
return res.status(400).end();
|
return res.status(400).end();
|
||||||
}
|
}
|
||||||
|
|
||||||
child_process.exec(cmd, {
|
child_process.exec(cmd, {
|
||||||
shell: shell,
|
shell: shell,
|
||||||
cwd: res.filename,
|
cwd: res.filename,
|
||||||
timeout: 60 * 1000,
|
timeout: 60 * 1000,
|
||||||
}, (err, stdout, stderr) => {
|
}, (err, stdout, stderr) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
req.flash("error", "Command failed due to non-zero exit code");
|
req.flash("error", "Command failed due to non-zero exit code");
|
||||||
}
|
}
|
||||||
res.render("cmd", flashify(req, {
|
res.render("cmd", flashify(req, {
|
||||||
path: res.filename,
|
path: res.filename,
|
||||||
cmd: cmd,
|
cmd: cmd,
|
||||||
stdout: stdout,
|
stdout: stdout,
|
||||||
stderr: stderr,
|
stderr: stderr,
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const pty = require("pty.js");
|
const pty = require("pty.js");
|
||||||
const io = require("socket.io")(http);
|
const io = require("socket.io")(http);
|
||||||
|
|
||||||
app.get("/*@shell", (req, res) => {
|
app.get("/*@shell", (req, res) => {
|
||||||
res.filename = req.params[0];
|
res.filename = req.params[0];
|
||||||
|
|
||||||
res.render("shell", flashify(req, {
|
res.render("shell", flashify(req, {
|
||||||
path: res.filename,
|
path: res.filename,
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
io.on("connection", (socket) => {
|
io.on("connection", (socket) => {
|
||||||
let cwd = socket.handshake.query.path;
|
let cwd = socket.handshake.query.path;
|
||||||
|
|
||||||
let term = pty.spawn(exec, args, {
|
let term = pty.spawn(exec, args, {
|
||||||
name: "xterm-256color",
|
name: "xterm-256color",
|
||||||
cols: 80,
|
cols: 80,
|
||||||
rows: 30,
|
rows: 30,
|
||||||
cwd: cwd,
|
cwd: cwd,
|
||||||
});
|
});
|
||||||
console.log("pid " + term.pid + " shell " + process.env.SHELL + " started in " + cwd);
|
console.log("pid " + term.pid + " shell " + process.env.SHELL + " started in " + cwd);
|
||||||
|
|
||||||
term.on("data", (data) => {
|
term.on("data", (data) => {
|
||||||
socket.emit("output", data);
|
socket.emit("output", data);
|
||||||
});
|
});
|
||||||
term.on("exit", (code) => {
|
term.on("exit", (code) => {
|
||||||
console.log("pid " + term.pid + " ended")
|
console.log("pid " + term.pid + " ended")
|
||||||
socket.disconnect();
|
socket.disconnect();
|
||||||
});
|
});
|
||||||
socket.on("resize", (data) => {
|
socket.on("resize", (data) => {
|
||||||
term.resize(data.col, data.row);
|
term.resize(data.col, data.row);
|
||||||
});
|
});
|
||||||
socket.on("input", (data) => {
|
socket.on("input", (data) => {
|
||||||
term.write(data);
|
term.write(data);
|
||||||
});
|
});
|
||||||
socket.on("disconnect", () => {
|
socket.on("disconnect", () => {
|
||||||
term.end();
|
term.end();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
app.get("/*", (req, res) => {
|
app.get("/*", (req, res) => {
|
||||||
if (res.stats.error) {
|
if (res.stats.error) {
|
||||||
res.render("list", flashify(req, {
|
res.render("list", flashify(req, {
|
||||||
shellable: shellable,
|
shellable: shellable,
|
||||||
path: res.filename,
|
cmdable: cmdable,
|
||||||
errors: [
|
path: res.filename,
|
||||||
res.stats.error
|
errors: [
|
||||||
]
|
res.stats.error
|
||||||
}));
|
]
|
||||||
}
|
}));
|
||||||
else if (res.stats.isDirectory()) {
|
}
|
||||||
if (!req.url.endsWith("/")) {
|
else if (res.stats.isDirectory()) {
|
||||||
return res.redirect(req.url + "/");
|
if (!req.url.endsWith("/")) {
|
||||||
}
|
return res.redirect(req.url + "/");
|
||||||
|
}
|
||||||
|
|
||||||
let readDir = new Promise((resolve, reject) => {
|
let readDir = new Promise((resolve, reject) => {
|
||||||
fs.readdir(relative(res.filename), (err, filenames) => {
|
fs.readdir(relative(res.filename), (err, filenames) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return reject(err);
|
return reject(err);
|
||||||
}
|
}
|
||||||
return resolve(filenames);
|
return resolve(filenames);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
readDir.then((filenames) => {
|
readDir.then((filenames) => {
|
||||||
let promises = filenames.map(f => {
|
let promises = filenames.map(f => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
fs.stat(relative(res.filename, f), (err, stats) => {
|
fs.stat(relative(res.filename, f), (err, stats) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return reject(err);
|
return reject(err);
|
||||||
}
|
}
|
||||||
resolve({
|
resolve({
|
||||||
name: f,
|
name: f,
|
||||||
isdirectory: stats.isDirectory(),
|
isdirectory: stats.isDirectory(),
|
||||||
size: filesize(stats.size)
|
size: filesize(stats.size)
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
Promise.all(promises).then((files) => {
|
Promise.all(promises).then((files) => {
|
||||||
res.render("list", flashify(req, {
|
res.render("list", flashify(req, {
|
||||||
shellable: shellable,
|
shellable: shellable,
|
||||||
path: res.filename,
|
cmdable: cmdable,
|
||||||
files: files,
|
path: res.filename,
|
||||||
}));
|
files: files,
|
||||||
}).catch((err) => {
|
}));
|
||||||
res.render("list", flashify(req, {
|
}).catch((err) => {
|
||||||
shellable: shellable,
|
res.render("list", flashify(req, {
|
||||||
path: res.filename,
|
shellable: shellable,
|
||||||
errors: [
|
cmdable: cmdable,
|
||||||
err
|
path: res.filename,
|
||||||
]
|
errors: [
|
||||||
}));
|
err
|
||||||
});
|
]
|
||||||
}).catch((err) => {
|
}));
|
||||||
res.render("list", flashify(req, {
|
});
|
||||||
shellable: shellable,
|
}).catch((err) => {
|
||||||
path: res.filename,
|
res.render("list", flashify(req, {
|
||||||
errors: [
|
shellable: shellable,
|
||||||
err
|
cmdable: cmdable,
|
||||||
]
|
path: res.filename,
|
||||||
}));
|
errors: [
|
||||||
});
|
err
|
||||||
}
|
]
|
||||||
else if (res.stats.isFile()) {
|
}));
|
||||||
res.download(relative(res.filename));
|
});
|
||||||
}
|
}
|
||||||
|
else if (res.stats.isFile()) {
|
||||||
|
res.download(relative(res.filename));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,29 +1,29 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width" />
|
<meta name="viewport" content="width=device-width" />
|
||||||
<title>File Manager</title>
|
<title>File Manager</title>
|
||||||
<link rel="stylesheet" href="/octicons/font/octicons.min.css" />
|
<link rel="stylesheet" href="/octicons/font/octicons.min.css" />
|
||||||
<link rel="stylesheet" href="/bootstrap/css/bootstrap.min.css" />
|
<link rel="stylesheet" href="/bootstrap/css/bootstrap.min.css" />
|
||||||
<script src="/jquery/jquery.min.js"></script>
|
<script src="/jquery/jquery.min.js"></script>
|
||||||
<script src="/bootstrap/js/bootstrap.min.js"></script>
|
<script src="/bootstrap/js/bootstrap.min.js"></script>
|
||||||
<script src="/filesize/filesize.js"></script>
|
<script src="/filesize/filesize.js"></script>
|
||||||
|
|
||||||
<link rel="stylesheet" href="/assets/fonts.css" />
|
<link rel="stylesheet" href="/assets/fonts.css" />
|
||||||
<link rel="stylesheet" href="/assets/list.css" />
|
<link rel="stylesheet" href="/assets/list.css" />
|
||||||
<script src="/assets/multi.js"></script>
|
<script src="/assets/multi.js"></script>
|
||||||
<link rel="stylesheet" href="/assets/upload.css" />
|
<link rel="stylesheet" href="/assets/upload.css" />
|
||||||
<script src="/assets/upload.js"></script>
|
<script src="/assets/upload.js"></script>
|
||||||
<link rel="stylesheet" href="/assets/login.css" />
|
<link rel="stylesheet" href="/assets/login.css" />
|
||||||
<script src="/assets/login.js"></script>
|
<script src="/assets/login.js"></script>
|
||||||
<link rel="stylesheet" href="/assets/cmd.css" />
|
<link rel="stylesheet" href="/assets/cmd.css" />
|
||||||
<link rel="stylesheet" href="/assets/shell.css" />
|
<link rel="stylesheet" href="/assets/shell.css" />
|
||||||
<script src="/socket.io/socket.io.js"></script>
|
<script src="/socket.io/socket.io.js"></script>
|
||||||
<script src="/assets/hterm_all.js"></script>
|
<script src="/assets/hterm_all.js"></script>
|
||||||
<script src="/assets/shell.js"></script>
|
<script src="/assets/shell.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
{{{body}}}
|
{{{body}}}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -2,21 +2,21 @@
|
||||||
|
|
||||||
<div style="padding-top: 56px; padding-bottom: 56px;">
|
<div style="padding-top: 56px; padding-bottom: 56px;">
|
||||||
<main class="container my-4">
|
<main class="container my-4">
|
||||||
{{#each errors as |error|}}
|
{{#each errors as |error|}}
|
||||||
<div class="alert alert-danger" role="alert">
|
<div class="alert alert-danger" role="alert">
|
||||||
{{error}}
|
{{error}}
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
{{#each successes as |success|}}
|
{{#each successes as |success|}}
|
||||||
<div class="alert alert-success" role="alert">
|
<div class="alert alert-success" role="alert">
|
||||||
{{success}}
|
{{success}}
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
<ul class="list-group">
|
<ul class="list-group">
|
||||||
{{#each files}}
|
{{#each files}}
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<div class="custom-control custom-checkbox">
|
<div class="custom-control custom-checkbox">
|
||||||
<input type="checkbox" class="custom-control-input multi-select" data-select="{{name}}" data-select-size="{{size}}" id="check{{@index}}">
|
<input type="checkbox" class="custom-control-input multi-select" data-select="{{name}}" data-select-size="{{size}}" id="check{{@index}}">
|
||||||
<label class="custom-control-label d-flex align-items-start justify-content-between" for="check{{@index}}">
|
<label class="custom-control-label d-flex align-items-start justify-content-between" for="check{{@index}}">
|
||||||
{{#if isdirectory}}
|
{{#if isdirectory}}
|
||||||
<a href="{{name}}/" class="name">{{name}}/</a>
|
<a href="{{name}}/" class="name">{{name}}/</a>
|
||||||
|
@ -25,14 +25,14 @@
|
||||||
<span class="badge badge-pill badge-secondary">{{size}}</span>
|
<span class="badge badge-pill badge-secondary">{{size}}</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
{{else}}
|
{{else}}
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
No files
|
No files
|
||||||
</li>
|
</li>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</ul>
|
</ul>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -2,17 +2,17 @@
|
||||||
|
|
||||||
<div style="padding-top: 56px; padding-bottom: 56px;">
|
<div style="padding-top: 56px; padding-bottom: 56px;">
|
||||||
<main class="container my-4">
|
<main class="container my-4">
|
||||||
<div class="login mx-auto">
|
<div class="login mx-auto">
|
||||||
{{#each errors as |error|}}
|
{{#each errors as |error|}}
|
||||||
<div class="alert alert-danger" role="alert">
|
<div class="alert alert-danger" role="alert">
|
||||||
{{error}}
|
{{error}}
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
{{#each successes as |success|}}
|
{{#each successes as |success|}}
|
||||||
<div class="alert alert-success" role="alert">
|
<div class="alert alert-success" role="alert">
|
||||||
{{success}}
|
{{success}}
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
<form class="py-4" action="/@login" method="post">
|
<form class="py-4" action="/@login" method="post">
|
||||||
<h4>One-time token:</h4>
|
<h4>One-time token:</h4>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
@ -27,6 +27,6 @@
|
||||||
<input name="token" id="login-token-value" type="hidden" />
|
<input name="token" id="login-token-value" type="hidden" />
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
<form action="@cmd" method="post">
|
<form action="@cmd" method="post">
|
||||||
<div id="cmd" class="modal fade" tabindex="-1" role="dialog" aria-hidden="true">
|
<div id="cmd" class="modal fade" tabindex="-1" role="dialog" aria-hidden="true">
|
||||||
<div class="modal-dialog modal-sm">
|
<div class="modal-dialog modal-sm">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 class="modal-title">Run command</h5>
|
<h5 class="modal-title">Run command</h5>
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
<span aria-hidden="true">×</span>
|
<span aria-hidden="true">×</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="cmd-cmd">Command: </label>
|
<label for="cmd-cmd">Command: </label>
|
||||||
<input name="cmd" class="form-control" type="text" id="cmd-cmd" placeholder="g++ sort.c" required />
|
<input name="cmd" class="form-control" type="text" id="cmd-cmd" placeholder="g++ sort.c" required />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="reset" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
|
<button type="reset" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
|
||||||
<button type="submit" class="btn btn-primary">Run</button>
|
<button type="submit" class="btn btn-primary">Run</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -1,25 +1,25 @@
|
||||||
<form action="@delete" method="post">
|
<form action="@delete" method="post">
|
||||||
<div id="delete" class="modal fade" tabindex="-1" role="dialog" aria-hidden="true">
|
<div id="delete" class="modal fade" tabindex="-1" role="dialog" aria-hidden="true">
|
||||||
<div class="modal-dialog modal-sm">
|
<div class="modal-dialog modal-sm">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 class="modal-title">Are you sure?</h5>
|
<h5 class="modal-title">Are you sure?</h5>
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
<span aria-hidden="true">×</span>
|
<span aria-hidden="true">×</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<p>You are deleting the following files: </p>
|
<p>You are deleting the following files: </p>
|
||||||
<ul class="list-group multi-files">
|
<ul class="list-group multi-files">
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
<input type="hidden" name="files" value="" class="multi-files-value" />
|
<input type="hidden" name="files" value="" class="multi-files-value" />
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="reset" class="btn btn-primary" data-dismiss="modal">Cancel</button>
|
<button type="reset" class="btn btn-primary" data-dismiss="modal">Cancel</button>
|
||||||
<button type="submit" class="btn btn-danger">Delete</button>
|
<button type="submit" class="btn btn-danger">Delete</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -1,25 +1,25 @@
|
||||||
<form action="@download" method="get">
|
<form action="@download" method="get">
|
||||||
<div id="download" class="modal fade" tabindex="-1" role="dialog" aria-hidden="true">
|
<div id="download" class="modal fade" tabindex="-1" role="dialog" aria-hidden="true">
|
||||||
<div class="modal-dialog modal-sm">
|
<div class="modal-dialog modal-sm">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 class="modal-title">Download file archive?</h5>
|
<h5 class="modal-title">Download file archive?</h5>
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
<span aria-hidden="true">×</span>
|
<span aria-hidden="true">×</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<p>Your archive will contain the following files: </p>
|
<p>Your archive will contain the following files: </p>
|
||||||
<ul class="list-group multi-files">
|
<ul class="list-group multi-files">
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
<input type="hidden" name="files" value="" class="multi-files-value" />
|
<input type="hidden" name="files" value="" class="multi-files-value" />
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="reset" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
|
<button type="reset" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
|
||||||
<button type="submit" class="btn btn-primary">Download</button>
|
<button type="submit" class="btn btn-primary">Download</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
<form action="@mkdir" method="post">
|
<form action="@mkdir" method="post">
|
||||||
<div id="mkdir" class="modal fade" tabindex="-1" role="dialog" aria-hidden="true">
|
<div id="mkdir" class="modal fade" tabindex="-1" role="dialog" aria-hidden="true">
|
||||||
<div class="modal-dialog modal-sm">
|
<div class="modal-dialog modal-sm">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 class="modal-title">Create a folder</h5>
|
<h5 class="modal-title">Create a folder</h5>
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
<span aria-hidden="true">×</span>
|
<span aria-hidden="true">×</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="mkdir-folder">Folder name: </label>
|
<label for="mkdir-folder">Folder name: </label>
|
||||||
<input name="folder" class="form-control" type="text" id="mkdir-folder" placeholder="folder" required />
|
<input name="folder" class="form-control" type="text" id="mkdir-folder" placeholder="folder" required />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="reset" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
|
<button type="reset" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
|
||||||
<button type="submit" class="btn btn-primary">Create</button>
|
<button type="submit" class="btn btn-primary">Create</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -1,34 +1,34 @@
|
||||||
<form action="@upload" method="post" enctype="multipart/form-data">
|
<form action="@upload" method="post" enctype="multipart/form-data">
|
||||||
<div id="upload" class="modal fade" tabindex="-1" role="dialog" aria-hidden="true">
|
<div id="upload" class="modal fade" tabindex="-1" role="dialog" aria-hidden="true">
|
||||||
<div class="modal-dialog modal-sm">
|
<div class="modal-dialog modal-sm">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 class="modal-title">Upload a file</h5>
|
<h5 class="modal-title">Upload a file</h5>
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
<span aria-hidden="true">×</span>
|
<span aria-hidden="true">×</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="custom-file">
|
<div class="custom-file">
|
||||||
<input name="file" type="file" id="upload-file" class="custom-file-input">
|
<input name="file" type="file" id="upload-file" class="custom-file-input">
|
||||||
<label class="custom-file-label" for="upload-file">Choose file</label>
|
<label class="custom-file-label" for="upload-file">Choose file</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group upload-unhide">
|
<div class="form-group upload-unhide">
|
||||||
<label for="upload-file-size">Filesize: </label>
|
<label for="upload-file-size">Filesize: </label>
|
||||||
<input class="form-control" type="text" disabled id="upload-file-size" placeholder="0B" />
|
<input class="form-control" type="text" disabled id="upload-file-size" placeholder="0B" />
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group upload-unhide">
|
<div class="form-group upload-unhide">
|
||||||
<label for="upload-file-saveas">Save as: </label>
|
<label for="upload-file-saveas">Save as: </label>
|
||||||
<input name="saveas" class="form-control" type="text" id="upload-file-saveas" placeholder="filename" />
|
<input name="saveas" class="form-control" type="text" id="upload-file-saveas" placeholder="filename" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="reset" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
|
<button type="reset" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
|
||||||
<button type="submit" class="btn btn-primary">Upload</button>
|
<button type="submit" class="btn btn-primary">Upload</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<nav class="navbar navbar-dark bg-primary fixed-top navbar-expand-sm">
|
<nav class="navbar navbar-dark bg-primary fixed-top navbar-expand-sm">
|
||||||
<a class="navbar-brand" href="/">File Manager</a>
|
<a class="navbar-brand" href="/">File Manager</a>
|
||||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbar" aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation">
|
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbar" aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
<span class="navbar-toggler-icon"></span>
|
<span class="navbar-toggler-icon"></span>
|
||||||
</button>
|
</button>
|
||||||
|
|
Loading…
Reference in New Issue