diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000..993c76d
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1 @@
+views/**/*.handlebars
diff --git a/Dockerfile.env b/Dockerfile.env
deleted file mode 100644
index 3d7aef3..0000000
--- a/Dockerfile.env
+++ /dev/null
@@ -1,12 +0,0 @@
-FROM serverwentdown/env:alpine-node
-
-COPY . /usr/local/share/file-manager
-RUN cd /usr/local/share/file-manager \
- && sudo npm install .
-
-USER ambrose
-
-ENV SHELL="zsh -l"
-ENV NODE_ENV=production
-
-CMD ["node", "/usr/local/share/file-manager/index.js"]
diff --git a/assets/cmd.css b/assets/cmd.css
index 5f26890..6f59ce5 100644
--- a/assets/cmd.css
+++ b/assets/cmd.css
@@ -1,7 +1,7 @@
.cmd {
- word-wrap: break-word;
+ word-wrap: break-word;
}
pre {
- background-color: #eee;
- min-height: 1.5em;
+ background-color: #eee;
+ min-height: 1.5em;
}
diff --git a/assets/list.css b/assets/list.css
index d508986..0967b43 100644
--- a/assets/list.css
+++ b/assets/list.css
@@ -1,23 +1,23 @@
.name {
- overflow: hidden;
- word-wrap: break-word;
+ overflow: hidden;
+ word-wrap: break-word;
}
.badge-alignment {
- margin-top: 0.25em;
+ margin-top: 0.25em;
}
.stretched-invisible-label {
- display: block;
+ display: block;
}
.stretched-invisible-label > * {
- position: relative;
- z-index: 1;
+ position: relative;
+ z-index: 1;
}
.stretched-invisible-label::after {
- content: "";
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- z-index: 0;
+ content: "";
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 0;
}
diff --git a/assets/login.css b/assets/login.css
index 8d2cab9..2b1e0e1 100644
--- a/assets/login.css
+++ b/assets/login.css
@@ -1,22 +1,21 @@
.input-group-digits .form-control {
- font-size: 2rem;
- padding: 0.5rem 0;
+ font-size: 2rem;
+ padding: 0.5rem 0;
- width: 2.75rem;
- text-align: center;
- font-weight: 300;
+ width: 2.75rem;
+ text-align: center;
+ font-weight: 300;
}
-.input-group-digits input[type=number] {
- -moz-appearance: textfield;
+.input-group-digits input[type="number"] {
+ -moz-appearance: textfield;
}
-.input-group-digits input[type=number]::-webkit-inner-spin-button,
-.input-group-digits input[type=number]::-webkit-outer-spin-button {
- -webkit-appearance: none;
- margin: 0;
+.input-group-digits input[type="number"]::-webkit-inner-spin-button,
+.input-group-digits input[type="number"]::-webkit-outer-spin-button {
+ -webkit-appearance: none;
+ margin: 0;
}
.login {
- width: 19.2em;
+ width: 19.2em;
}
-
diff --git a/assets/login.js b/assets/login.js
index 1b04c7a..0ac9b7a 100644
--- a/assets/login.js
+++ b/assets/login.js
@@ -2,51 +2,52 @@
let $inputs = $(".input-group-digits");
$inputs.each((i, input) => {
- let cleanup = () => {
- $(input).find("input").each((i, ele) => {
- let cleaned = $(ele).val().replace(/[^0-9]/, "");
- $(ele).val(cleaned);
- });
- };
- let update = (e) => {
- $digits = $(input).find("input");
+ let cleanup = () => {
+ $(input)
+ .find("input")
+ .each((i, ele) => {
+ let cleaned = $(ele)
+ .val()
+ .replace(/[^0-9]/, "");
+ $(ele).val(cleaned);
+ });
+ };
+ let update = (e) => {
+ $digits = $(input).find("input");
- // Cleanup
- cleanup();
+ // Cleanup
+ cleanup();
- // Shift characters
- let excess = "";
- $digits.each((i, ele) => {
- let now = excess + $(ele).val();
- $(ele).val(now.charAt(0));
- excess = now.substr(1);
- });
+ // Shift characters
+ let excess = "";
+ $digits.each((i, ele) => {
+ let now = excess + $(ele).val();
+ $(ele).val(now.charAt(0));
+ excess = now.substr(1);
+ });
- // Move cursor to empty
- $digits.each((i, ele) => {
- if (!$(ele).val()) {
- $(ele).focus();
- if (e.which == 8) {
- $(ele).prev().focus().val("");
- }
- return false;
- }
- });
+ // Move cursor to empty
+ $digits.each((i, ele) => {
+ if (!$(ele).val()) {
+ $(ele).focus();
+ if (e.which == 8) {
+ $(ele).prev().focus().val("");
+ }
+ return false;
+ }
+ });
- // Submit if last digit is filled
- if ($($digits[$digits.length - 1]).val()) {
- let token = $.map(
- $digits,
- d => $(d).val()
- ).join("");
- let $value = $(input).parent().find("#login-token-value");
- $value.val(token);
- $value.closest("form").submit();
- }
- };
+ // Submit if last digit is filled
+ if ($($digits[$digits.length - 1]).val()) {
+ let token = $.map($digits, (d) => $(d).val()).join("");
+ let $value = $(input).parent().find("#login-token-value");
+ $value.val(token);
+ $value.closest("form").submit();
+ }
+ };
- $digits = $(input).find("input");
- $digits.on("keyup", update);
- $digits.on("change", update);
- $digits.on("input", update);
+ $digits = $(input).find("input");
+ $digits.on("keyup", update);
+ $digits.on("change", update);
+ $digits.on("input", update);
});
diff --git a/assets/multi.js b/assets/multi.js
index 71330d4..4cd13cc 100644
--- a/assets/multi.js
+++ b/assets/multi.js
@@ -1,51 +1,64 @@
/* jshint esversion: 6 */
function htmlEscape(text) {
- const p = document.createElement('p');
- p.innerText = text;
- return p.innerHTML;
+ const p = document.createElement("p");
+ p.innerText = text;
+ return p.innerHTML;
}
let $select = $(".multi-select");
let setSelected = (files) => {
- $(".multi-files-value").val(JSON.stringify(files.map(f => f.name)));
- if (files.length == 0) {
- $(".multi-files").html(`
No files selected`);
- return
- }
- $(".multi-files").html(
- files.map(f => {
- return `
+ $(".multi-files-value").val(JSON.stringify(files.map((f) => f.name)));
+ if (files.length == 0) {
+ $(".multi-files").html(
+ `No files selected`
+ );
+ return;
+ }
+ $(".multi-files").html(
+ files
+ .map((f) => {
+ return `
${htmlEscape(f.name)}
- ${f.type == "directory" ? `` : `${filesize(f.size)}`}
+ ${
+ f.type == "directory"
+ ? ``
+ : `${filesize(
+ f.size
+ )}`
+ }
`;
- }).join("")
- );
- const hasDirectory = files.reduce((a, f) => a || f.type == "directory", false);
- const totalSize = files.map(f => f.size).reduce((a, b) => a + b);
- if (hasDirectory) {
- $(".multi-files-total").val("");
- } else {
- $(".multi-files-total").val(filesize(totalSize));
- }
+ })
+ .join("")
+ );
+ const hasDirectory = files.reduce(
+ (a, f) => a || f.type == "directory",
+ false
+ );
+ const totalSize = files.map((f) => f.size).reduce((a, b) => a + b);
+ if (hasDirectory) {
+ $(".multi-files-total").val("");
+ } else {
+ $(".multi-files-total").val(filesize(totalSize));
+ }
};
const updateSelected = () => {
- let $selected = $(".multi-select:checked");
- let files = [];
- $selected.each((i, ele) => {
- files.push({
- name: $(ele).data("select"),
- type: $(ele).data("select-type"),
- size: $(ele).data("select-size")
- });
- });
+ let $selected = $(".multi-select:checked");
+ let files = [];
+ $selected.each((i, ele) => {
+ files.push({
+ name: $(ele).data("select"),
+ type: $(ele).data("select-type"),
+ size: $(ele).data("select-size"),
+ });
+ });
- setSelected(files);
-}
+ setSelected(files);
+};
$select.on("change", updateSelected);
updateSelected();
diff --git a/assets/navbar.css b/assets/navbar.css
index a17b84d..14ed39e 100644
--- a/assets/navbar.css
+++ b/assets/navbar.css
@@ -1,6 +1,6 @@
#navbar {
- overflow-x: auto;
+ overflow-x: auto;
}
.nav-link {
- white-space: nowrap;
+ white-space: nowrap;
}
diff --git a/assets/shell.js b/assets/shell.js
index 9293e52..b411786 100644
--- a/assets/shell.js
+++ b/assets/shell.js
@@ -4,53 +4,62 @@ const $shell = $("#shell");
const $close = $("#shell-close");
if ($shell.length > 0) {
+ const ws = new WebSocket(
+ "ws" +
+ (window.location.protocol === "https:" ? "s" : "") +
+ "://" +
+ window.location.host +
+ "/websocket?path=" +
+ encodeURIComponent($shell.data("path"))
+ );
- const ws = new WebSocket("ws" + (window.location.protocol === "https:" ? "s" : "") + "://" + window.location.host + "/websocket?path=" + encodeURIComponent($shell.data("path")));
+ const term = new Terminal();
+ const attachAddon = new AttachAddon.AttachAddon(ws, { bidirectional: true });
+ term.loadAddon(attachAddon);
+ const fitAddon = new FitAddon.FitAddon();
+ term.loadAddon(fitAddon);
+ term.open($shell[0]);
- const term = new Terminal();
- const attachAddon = new AttachAddon.AttachAddon(ws, { bidirectional: true });
- term.loadAddon(attachAddon);
- const fitAddon = new FitAddon.FitAddon();
- term.loadAddon(fitAddon);
- term.open($shell[0]);
-
- ws.addEventListener("open", () => {
-
- // resize
- term.onResize(({ cols, rows }) => {
- console.debug(cols, rows);
- const buf = Uint16Array.of(0, cols, rows);
- ws.send(buf);
- });
- $(window).on("resize", () => {
- fitAddon.fit();
- });
- fitAddon.fit();
-
- // close
- let closeTimeout = null;
- $close.on("click", (e) => {
- e.preventDefault();
- if (ws.readyState !== 1) {
- window.location.pathname = window.location.pathname.replace("@shell", "");
- } else {
- ws.close();
- }
- });
- ws.addEventListener("close", () => {
- term.write("\r\n\r\nclosing shell in 2 seconds...");
- closeTimeout = setTimeout(() => {
- window.location.pathname = window.location.pathname.replace("@shell", "");
- }, 2000);
- });
- term.onData(() => {
- if (closeTimeout != null) {
- clearTimeout(closeTimeout);
- term.write("\r\nkeyboard input detected. timeout canceled");
- closeTimeout = null;
- }
- });
-
- });
+ ws.addEventListener("open", () => {
+ // resize
+ term.onResize(({ cols, rows }) => {
+ console.debug(cols, rows);
+ const buf = Uint16Array.of(0, cols, rows);
+ ws.send(buf);
+ });
+ $(window).on("resize", () => {
+ fitAddon.fit();
+ });
+ fitAddon.fit();
+ // close
+ let closeTimeout = null;
+ $close.on("click", (e) => {
+ e.preventDefault();
+ if (ws.readyState !== 1) {
+ window.location.pathname = window.location.pathname.replace(
+ "@shell",
+ ""
+ );
+ } else {
+ ws.close();
+ }
+ });
+ ws.addEventListener("close", () => {
+ term.write("\r\n\r\nclosing shell in 2 seconds...");
+ closeTimeout = setTimeout(() => {
+ window.location.pathname = window.location.pathname.replace(
+ "@shell",
+ ""
+ );
+ }, 2000);
+ });
+ term.onData(() => {
+ if (closeTimeout != null) {
+ clearTimeout(closeTimeout);
+ term.write("\r\nkeyboard input detected. timeout canceled");
+ closeTimeout = null;
+ }
+ });
+ });
}
diff --git a/assets/tooltip.js b/assets/tooltip.js
index 579a680..ecc71db 100644
--- a/assets/tooltip.js
+++ b/assets/tooltip.js
@@ -1,7 +1,7 @@
/* jshint esversion: 6 */
-document.querySelectorAll("[title]").forEach(element => {
- new bootstrap.Tooltip(element, {
- delay: 500,
- });
+document.querySelectorAll("[title]").forEach((element) => {
+ new bootstrap.Tooltip(element, {
+ delay: 500,
+ });
});
diff --git a/assets/upload.css b/assets/upload.css
index 493985a..88d13e3 100644
--- a/assets/upload.css
+++ b/assets/upload.css
@@ -1,6 +1,6 @@
.custom-file-label {
- white-space: nowrap;
- text-overflow: ellipsis;
- overflow: hidden;
- padding-right: 5.4em;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ padding-right: 5.4em;
}
diff --git a/assets/upload.js b/assets/upload.js
index 5165d03..5e5f21c 100644
--- a/assets/upload.js
+++ b/assets/upload.js
@@ -1,22 +1,22 @@
/* jshint esversion: 6 */
const $form = $("form[action='@upload']");
-const $file = $("#upload-file");
+const $file = $("#upload-file");
$(".upload-unhide").fadeOut();
$file.on("change", () => {
- const file = $file[0].files[0];
- const fnElement = $file.parent().find(".custom-file-label");
- fnElement.addClass("file-selected");
- fnElement.text(file.name);
+ const file = $file[0].files[0];
+ const fnElement = $file.parent().find(".custom-file-label");
+ fnElement.addClass("file-selected");
+ fnElement.text(file.name);
- $form.find("#upload-file-size").val(filesize(file.size));
- $form.find("[name=saveas]").val(file.name);
- $(".upload-unhide").fadeIn();
+ $form.find("#upload-file-size").val(filesize(file.size));
+ $form.find("[name=saveas]").val(file.name);
+ $(".upload-unhide").fadeIn();
});
$form.on("submit", () => {
- let putresource = $form.find("[name=saveas]").val();
- // TODO: do XHR to PUT at putresource
+ let putresource = $form.find("[name=saveas]").val();
+ // TODO: do XHR to PUT at putresource
});
diff --git a/index.js b/index.js
index 0abc313..9aa0caa 100755
--- a/index.js
+++ b/index.js
@@ -5,7 +5,7 @@
"use strict";
const express = require("express");
-const hbs = require("express-handlebars");
+const { engine: hbs } = require("express-handlebars");
const bodyparser = require("body-parser");
const session = require("express-session");
const busboy = require("connect-busboy");
@@ -25,541 +25,615 @@ const filesize = require("filesize");
const octicons = require("octicons");
const handlebars = require("handlebars");
+const port = +process.env.PORT || 8080;
+
let app = express();
-let http = app.listen(process.env.PORT || 8080);
+let http = app.listen(port);
app.set("views", path.join(__dirname, "views"));
-app.engine("handlebars", hbs({
- partialsDir: path.join(__dirname, "views", "partials"),
- layoutsDir: path.join(__dirname, "views", "layouts"),
- defaultLayout: "main",
- helpers: {
- either: function(a, b, options) {
- if (a || b) {
- return options.fn(this);
- }
- },
- filesize: filesize,
- octicon: function(i, options) {
- if (!octicons[i]) {
- return new handlebars.SafeString(octicons.question.toSVG());
- }
- return new handlebars.SafeString(octicons[i].toSVG());
- },
- eachpath: function (path, options) {
- if (typeof path != "string") {
- return "";
- }
- let out = "";
- path = path.split("/");
- path.splice(path.length - 1, 1);
- path.unshift("");
- path.forEach((folder, index) => {
- out += options.fn({
- name: folder + "/",
- path: "/" + path.slice(1, index + 1).join("/"),
- current: index === path.length - 1
- });
- });
- return out;
- },
- }
-}));
+app.engine(
+ "handlebars",
+ hbs({
+ partialsDir: path.join(__dirname, "views", "partials"),
+ layoutsDir: path.join(__dirname, "views", "layouts"),
+ defaultLayout: "main",
+ helpers: {
+ either: function (a, b, options) {
+ if (a || b) {
+ return options.fn(this);
+ }
+ },
+ filesize: filesize,
+ octicon: function (i, options) {
+ if (!octicons[i]) {
+ return new handlebars.SafeString(octicons.question.toSVG());
+ }
+ return new handlebars.SafeString(octicons[i].toSVG());
+ },
+ eachpath: function (path, options) {
+ if (typeof path != "string") {
+ return "";
+ }
+ let out = "";
+ path = path.split("/");
+ path.splice(path.length - 1, 1);
+ path.unshift("");
+ path.forEach((folder, index) => {
+ out += options.fn({
+ name: folder + "/",
+ path: "/" + path.slice(1, index + 1).join("/"),
+ current: index === path.length - 1,
+ });
+ });
+ return out;
+ },
+ },
+ })
+);
app.set("view engine", "handlebars");
app.use("/@assets", express.static(path.join(__dirname, "assets")));
-app.use("/@assets/bootstrap", express.static(path.join(__dirname, "node_modules/bootstrap/dist")));
-app.use("/@assets/octicons", express.static(path.join(__dirname, "node_modules/octicons/build")));
-app.use("/@assets/jquery", express.static(path.join(__dirname, "node_modules/jquery/dist")));
-app.use("/@assets/filesize", express.static(path.join(__dirname, "node_modules/filesize/lib")));
-app.use("/@assets/xterm", express.static(path.join(__dirname, "node_modules/xterm")));
-app.use("/@assets/xterm-addon-attach", express.static(path.join(__dirname, "node_modules/xterm-addon-attach")));
-app.use("/@assets/xterm-addon-fit", express.static(path.join(__dirname, "node_modules/xterm-addon-fit")));
+app.use(
+ "/@assets/bootstrap",
+ express.static(path.join(__dirname, "node_modules/bootstrap/dist"))
+);
+app.use(
+ "/@assets/octicons",
+ express.static(path.join(__dirname, "node_modules/octicons/build"))
+);
+app.use(
+ "/@assets/jquery",
+ express.static(path.join(__dirname, "node_modules/jquery/dist"))
+);
+app.use(
+ "/@assets/filesize",
+ express.static(path.join(__dirname, "node_modules/filesize/lib"))
+);
+app.use(
+ "/@assets/xterm",
+ express.static(path.join(__dirname, "node_modules/xterm"))
+);
+app.use(
+ "/@assets/xterm-addon-attach",
+ express.static(path.join(__dirname, "node_modules/xterm-addon-attach"))
+);
+app.use(
+ "/@assets/xterm-addon-fit",
+ express.static(path.join(__dirname, "node_modules/xterm-addon-fit"))
+);
-app.use(session({
- secret: process.env.SESSION_KEY || "meowmeow"
-}));
+app.use(
+ session({
+ secret: process.env.SESSION_KEY || "meowmeow",
+ })
+);
app.use(flash());
app.use(busboy());
app.use(bodyparser.urlencoded());
// AUTH
-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) => {
- if (KEY) {
- req.session.login = false;
- req.flash("success", "Signed out.");
- res.redirect("/@login");
- return
- }
- req.flash("error", "You were never logged in...");
- res.redirect("back");
+ if (KEY) {
+ req.session.login = false;
+ req.flash("success", "Signed out.");
+ res.redirect("/@login");
+ return;
+ }
+ req.flash("error", "You were never logged in...");
+ res.redirect("back");
});
app.get("/@login", (req, res) => {
- res.render("login", flashify(req, {}));
+ res.render("login", flashify(req, {}));
});
app.post("/@login", (req, res) => {
- let pass = notp.totp.verify(req.body.token.replace(" ", ""), KEY);
- if (pass) {
- req.session.login = true;
- res.redirect("/");
- return;
- }
- req.flash("error", "Bad token.");
- res.redirect("/@login");
+ let pass = notp.totp.verify(req.body.token.replace(" ", ""), KEY);
+ if (pass) {
+ req.session.login = true;
+ res.redirect("/");
+ return;
+ }
+ req.flash("error", "Bad token.");
+ res.redirect("/@login");
});
app.use((req, res, next) => {
- if (!KEY) {
- return next();
- }
- if (req.session.login === true) {
- return next();
- }
- req.flash("error", "Please sign in.");
- res.redirect("/@login");
+ if (!KEY) {
+ return next();
+ }
+ if (req.session.login === true) {
+ return next();
+ }
+ req.flash("error", "Please sign in.");
+ res.redirect("/@login");
});
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) {
- let error = req.flash("error");
- if (error && error.length > 0) {
- if (!obj.errors) {
- obj.errors = [];
- }
- obj.errors.push(error);
- }
- let success = req.flash("success");
- if (success && success.length > 0) {
- if (!obj.successes) {
- obj.successes = [];
- }
- obj.successes.push(success);
- }
- obj.isloginenabled = !!KEY;
- return obj;
+ let error = req.flash("error");
+ if (error && error.length > 0) {
+ if (!obj.errors) {
+ obj.errors = [];
+ }
+ obj.errors.push(error);
+ }
+ let success = req.flash("success");
+ if (success && success.length > 0) {
+ if (!obj.successes) {
+ obj.successes = [];
+ }
+ obj.successes.push(success);
+ }
+ obj.isloginenabled = !!KEY;
+ return obj;
}
app.all("/*", (req, res, next) => {
- res.filename = req.params[0];
+ res.filename = req.params[0];
- let fileExists = new Promise((resolve, reject) => {
- // check if file exists
- fs.stat(relative(res.filename), (err, stats) => {
- if (err) {
- return reject(err);
- }
- return resolve(stats);
- });
- });
+ let fileExists = new Promise((resolve, reject) => {
+ // check if file exists
+ fs.stat(relative(res.filename), (err, stats) => {
+ if (err) {
+ return reject(err);
+ }
+ return resolve(stats);
+ });
+ });
- fileExists.then((stats) => {
- res.stats = stats;
- next();
- }).catch((err) => {
- res.stats = { error: err };
- next();
- });
+ fileExists
+ .then((stats) => {
+ res.stats = stats;
+ next();
+ })
+ .catch((err) => {
+ res.stats = { error: err };
+ next();
+ });
});
app.post("/*@upload", (req, res) => {
- res.filename = req.params[0];
+ res.filename = req.params[0];
- let buff = null;
- let saveas = null;
- req.busboy.on("file", (key, stream, filename) => {
- if (key == "file") {
- let buffs = [];
- stream.on("data", (d) => {
- buffs.push(d);
- });
- stream.on("end", () => {
- buff = Buffer.concat(buffs);
- buffs = null;
- });
- }
- });
- req.busboy.on("field", (key, value) => {
- if (key == "saveas") {
- saveas = value;
- }
- });
- req.busboy.on("finish", () => {
- if (!buff || !saveas) {
- return res.status(400).end();
- }
- let fileExists = new Promise((resolve, reject) => {
- // check if file exists
- fs.stat(relative(res.filename, saveas), (err, stats) => {
- if (err) {
- return reject(err);
- }
- return resolve(stats);
- });
- });
+ let buff = null;
+ let saveas = null;
+ req.busboy.on("file", (key, stream, filename) => {
+ if (key == "file") {
+ let buffs = [];
+ stream.on("data", (d) => {
+ buffs.push(d);
+ });
+ stream.on("end", () => {
+ buff = Buffer.concat(buffs);
+ buffs = null;
+ });
+ }
+ });
+ req.busboy.on("field", (key, value) => {
+ if (key == "saveas") {
+ saveas = value;
+ }
+ });
+ req.busboy.on("finish", () => {
+ if (!buff || !saveas) {
+ return res.status(400).end();
+ }
+ let fileExists = new Promise((resolve, reject) => {
+ // check if file exists
+ fs.stat(relative(res.filename, saveas), (err, stats) => {
+ if (err) {
+ return reject(err);
+ }
+ return resolve(stats);
+ });
+ });
- fileExists.then((stats) => {
- console.warn("file exists, cannot overwrite");
- req.flash("error", "File exists, cannot overwrite. ");
- res.redirect("back");
- }).catch((err) => {
- const saveName = relative(res.filename, saveas);
- console.log("saving file to " + saveName);
- let save = fs.createWriteStream(saveName);
- save.on("close", () => {
- if (res.headersSent) {
- return;
- }
- if (buff.length === 0) {
- req.flash("success", "File saved. Warning: empty file.");
- }
- else {
- buff = null;
- req.flash("success", "File saved. ");
- }
- res.redirect("back");
- });
- save.on("error", (err) => {
- console.warn(err);
- req.flash("error", err.toString());
- res.redirect("back");
- });
- save.write(buff);
- save.end();
- });
- });
- req.pipe(req.busboy);
+ fileExists
+ .then((stats) => {
+ console.warn("file exists, cannot overwrite");
+ req.flash("error", "File exists, cannot overwrite. ");
+ res.redirect("back");
+ })
+ .catch((err) => {
+ const saveName = relative(res.filename, saveas);
+ console.log("saving file to " + saveName);
+ let save = fs.createWriteStream(saveName);
+ save.on("close", () => {
+ if (res.headersSent) {
+ return;
+ }
+ if (buff.length === 0) {
+ req.flash("success", "File saved. Warning: empty file.");
+ } else {
+ buff = null;
+ req.flash("success", "File saved. ");
+ }
+ res.redirect("back");
+ });
+ save.on("error", (err) => {
+ console.warn(err);
+ req.flash("error", err.toString());
+ res.redirect("back");
+ });
+ save.write(buff);
+ save.end();
+ });
+ });
+ req.pipe(req.busboy);
});
app.post("/*@mkdir", (req, res) => {
- res.filename = req.params[0];
+ res.filename = req.params[0];
- let folder = req.body.folder;
- if (!folder || folder.length < 1) {
- return res.status(400).end();
- }
+ let folder = req.body.folder;
+ if (!folder || folder.length < 1) {
+ return res.status(400).end();
+ }
- let fileExists = new Promise((resolve, reject) => {
- // Check if file exists
- fs.stat(relative(res.filename, folder), (err, stats) => {
- if (err) {
- return reject(err);
- }
- return resolve(stats);
- });
- });
+ let fileExists = new Promise((resolve, reject) => {
+ // Check if file exists
+ fs.stat(relative(res.filename, folder), (err, stats) => {
+ if (err) {
+ return reject(err);
+ }
+ return resolve(stats);
+ });
+ });
- fileExists.then((stats) => {
- req.flash("error", "Folder exists, cannot overwrite. ");
- res.redirect("back");
- }).catch((err) => {
- fs.mkdir(relative(res.filename, folder), (err) => {
- if (err) {
- console.warn(err);
- req.flash("error", err.toString());
- res.redirect("back");
- return;
- }
- req.flash("success", "Folder created. ");
- res.redirect("back");
- });
- });
+ fileExists
+ .then((stats) => {
+ req.flash("error", "Folder exists, cannot overwrite. ");
+ res.redirect("back");
+ })
+ .catch((err) => {
+ fs.mkdir(relative(res.filename, folder), (err) => {
+ if (err) {
+ console.warn(err);
+ req.flash("error", err.toString());
+ res.redirect("back");
+ return;
+ }
+ req.flash("success", "Folder created. ");
+ res.redirect("back");
+ });
+ });
});
app.post("/*@delete", (req, res) => {
- res.filename = req.params[0];
+ res.filename = req.params[0];
- let files = JSON.parse(req.body.files);
- if (!files || !files.map) {
- req.flash("error", "No files selected.");
- res.redirect("back");
- return; // res.status(400).end();
- }
+ let files = JSON.parse(req.body.files);
+ if (!files || !files.map) {
+ req.flash("error", "No files selected.");
+ res.redirect("back");
+ return; // res.status(400).end();
+ }
- let promises = files.map(f => {
- return new Promise((resolve, reject) => {
- fs.stat(relative(res.filename, f), (err, stats) => {
- if (err) {
- return reject(err);
- }
- resolve({
- name: f,
- isdirectory: stats.isDirectory(),
- isfile: stats.isFile()
- });
- });
- });
- });
- Promise.all(promises).then((files) => {
- let promises = files.map(f => {
- return new Promise((resolve, reject) => {
- let op = null;
- if (f.isdirectory) {
- op = (dir, cb) => rimraf(dir, {
- glob: false
- }, cb);
- }
- else if (f.isfile) {
- op = fs.unlink;
- }
- if (op) {
- op(relative(res.filename, f.name), (err) => {
- if (err) {
- return reject(err);
- }
- resolve();
- });
- }
- });
- });
- Promise.all(promises).then(() => {
- req.flash("success", "Files deleted. ");
- res.redirect("back");
- }).catch((err) => {
- console.warn(err);
- req.flash("error", "Unable to delete some files: " + err);
- res.redirect("back");
- });
- }).catch((err) => {
- console.warn(err);
- req.flash("error", err.toString());
- res.redirect("back");
- });
+ let promises = files.map((f) => {
+ return new Promise((resolve, reject) => {
+ fs.stat(relative(res.filename, f), (err, stats) => {
+ if (err) {
+ return reject(err);
+ }
+ resolve({
+ name: f,
+ isdirectory: stats.isDirectory(),
+ isfile: stats.isFile(),
+ });
+ });
+ });
+ });
+ Promise.all(promises)
+ .then((files) => {
+ let promises = files.map((f) => {
+ return new Promise((resolve, reject) => {
+ let op = null;
+ if (f.isdirectory) {
+ op = (dir, cb) =>
+ rimraf(
+ dir,
+ {
+ glob: false,
+ },
+ cb
+ );
+ } else if (f.isfile) {
+ op = fs.unlink;
+ }
+ if (op) {
+ op(relative(res.filename, f.name), (err) => {
+ if (err) {
+ return reject(err);
+ }
+ resolve();
+ });
+ }
+ });
+ });
+ Promise.all(promises)
+ .then(() => {
+ req.flash("success", "Files deleted. ");
+ res.redirect("back");
+ })
+ .catch((err) => {
+ console.warn(err);
+ req.flash("error", "Unable to delete some files: " + err);
+ res.redirect("back");
+ });
+ })
+ .catch((err) => {
+ console.warn(err);
+ req.flash("error", err.toString());
+ res.redirect("back");
+ });
});
app.get("/*@download", (req, res) => {
- res.filename = req.params[0];
+ res.filename = req.params[0];
- let files = null;
- try {
- files = JSON.parse(req.query.files);
- } catch (e) {}
- if (!files || !files.map) {
- req.flash("error", "No files selected.");
- res.redirect("back");
- return; // res.status(400).end();
- }
+ let files = null;
+ try {
+ files = JSON.parse(req.query.files);
+ } catch (e) {}
+ if (!files || !files.map) {
+ req.flash("error", "No files selected.");
+ res.redirect("back");
+ return; // res.status(400).end();
+ }
- let promises = files.map(f => {
- return new Promise((resolve, reject) => {
- fs.stat(relative(res.filename, f), (err, stats) => {
- if (err) {
- return reject(err);
- }
- resolve({
- name: f,
- isdirectory: stats.isDirectory(),
- isfile: stats.isFile()
- });
- });
- });
- });
- Promise.all(promises).then((files) => {
- let zip = archiver("zip", {});
- zip.on("error", function(err) {
- console.warn(err);
- res.status(500).send({
- error: err.message
- });
- });
+ let promises = files.map((f) => {
+ return new Promise((resolve, reject) => {
+ fs.stat(relative(res.filename, f), (err, stats) => {
+ if (err) {
+ return reject(err);
+ }
+ resolve({
+ name: f,
+ isdirectory: stats.isDirectory(),
+ isfile: stats.isFile(),
+ });
+ });
+ });
+ });
+ Promise.all(promises)
+ .then((files) => {
+ let zip = archiver("zip", {});
+ zip.on("error", function (err) {
+ console.warn(err);
+ res.status(500).send({
+ error: err.message,
+ });
+ });
- files.filter(f => f.isfile).forEach((f) => {
- zip.file(relative(res.filename, f.name), { name: f.name });
- });
- files.filter(f => f.isdirectory).forEach((f) => {
- zip.directory(relative(res.filename, f.name), f.name);
- });
+ files
+ .filter((f) => f.isfile)
+ .forEach((f) => {
+ zip.file(relative(res.filename, f.name), { name: f.name });
+ });
+ files
+ .filter((f) => f.isdirectory)
+ .forEach((f) => {
+ zip.directory(relative(res.filename, f.name), f.name);
+ });
- res.attachment("Archive.zip");
- zip.pipe(res);
+ res.attachment("Archive.zip");
+ zip.pipe(res);
- zip.finalize();
- }).catch((err) => {
- console.warn(err);
- req.flash("error", err.toString());
- res.redirect("back");
- });
+ zip.finalize();
+ })
+ .catch((err) => {
+ console.warn(err);
+ req.flash("error", err.toString());
+ res.redirect("back");
+ });
});
const shellable = process.env.SHELL != "false" && process.env.SHELL;
const cmdable = process.env.CMD != "false" && process.env.CMD;
if (shellable || cmdable) {
- const shellArgs = process.env.SHELL.split(" ");
- const exec = process.env.SHELL == "login" ? "/usr/bin/env" : shellArgs[0];
- const args = process.env.SHELL == "login" ? ["login"] : shellArgs.slice(1);
+ const shellArgs = process.env.SHELL.split(" ");
+ const exec = process.env.SHELL == "login" ? "/usr/bin/env" : shellArgs[0];
+ const args = process.env.SHELL == "login" ? ["login"] : shellArgs.slice(1);
- const child_process = require("child_process");
+ const child_process = require("child_process");
- app.post("/*@cmd", (req, res) => {
- res.filename = req.params[0];
+ app.post("/*@cmd", (req, res) => {
+ res.filename = req.params[0];
- let cmd = req.body.cmd;
- if (!cmd || cmd.length < 1) {
- return res.status(400).end();
- }
- console.log("running command " + cmd);
+ let cmd = req.body.cmd;
+ if (!cmd || cmd.length < 1) {
+ return res.status(400).end();
+ }
+ console.log("running command " + cmd);
- child_process.exec(cmd, {
- cwd: relative(res.filename),
- timeout: 60 * 1000,
- }, (err, stdout, stderr) => {
- if (err) {
- console.log("command run failed: " + JSON.stringify(err));
- req.flash("error", "Command failed due to non-zero exit code");
- }
- res.render("cmd", flashify(req, {
- path: res.filename,
- cmd: cmd,
- stdout: stdout,
- stderr: stderr,
- }));
- });
- });
+ child_process.exec(
+ cmd,
+ {
+ cwd: relative(res.filename),
+ timeout: 60 * 1000,
+ },
+ (err, stdout, stderr) => {
+ if (err) {
+ console.log("command run failed: " + JSON.stringify(err));
+ req.flash("error", "Command failed due to non-zero exit code");
+ }
+ res.render(
+ "cmd",
+ flashify(req, {
+ path: res.filename,
+ cmd: cmd,
+ stdout: stdout,
+ stderr: stderr,
+ })
+ );
+ }
+ );
+ });
- const pty = require("node-pty");
- const WebSocket = require("ws");
+ const pty = require("node-pty");
+ const WebSocket = require("ws");
- app.get("/*@shell", (req, res) => {
- res.filename = req.params[0];
+ app.get("/*@shell", (req, res) => {
+ res.filename = req.params[0];
- res.render("shell", flashify(req, {
- path: res.filename,
- }));
- });
+ res.render(
+ "shell",
+ flashify(req, {
+ path: res.filename,
+ })
+ );
+ });
- const ws = new WebSocket.Server({ server: http });
- ws.on("connection", (socket, request) => {
- const { path } = querystring.parse(request.url.split("?")[1]);
- let cwd = relative(path);
- let term = pty.spawn(exec, args, {
- name: "xterm-256color",
- cols: 80,
- rows: 30,
- cwd: cwd,
- });
- console.log("pid " + term.pid + " shell " + process.env.SHELL + " started in " + cwd);
+ const ws = new WebSocket.Server({ server: http });
+ ws.on("connection", (socket, request) => {
+ const { path } = querystring.parse(request.url.split("?")[1]);
+ let cwd = relative(path);
+ let term = pty.spawn(exec, args, {
+ name: "xterm-256color",
+ cols: 80,
+ rows: 30,
+ cwd: cwd,
+ });
+ console.log(
+ "pid " + term.pid + " shell " + process.env.SHELL + " started in " + cwd
+ );
- term.on("data", (data) => {
- socket.send(data, { binary: true });
- });
- term.on("exit", (code) => {
- console.log("pid " + term.pid + " ended")
- socket.close();
- });
- socket.on("message", (data) => {
- // special messages should decode to Buffers
- if (Buffer.isBuffer(data)) {
- switch (data.readUInt16BE(0)) {
- case 0:
- term.resize(data.readUInt16BE(1), data.readUInt16BE(2));
- return;
- }
- }
- term.write(data);
- });
- socket.on("close", () => {
- term.end();
- });
- });
+ term.on("data", (data) => {
+ socket.send(data, { binary: true });
+ });
+ term.on("exit", (code) => {
+ console.log("pid " + term.pid + " ended");
+ socket.close();
+ });
+ socket.on("message", (data) => {
+ // special messages should decode to Buffers
+ if (Buffer.isBuffer(data)) {
+ switch (data.readUInt16BE(0)) {
+ case 0:
+ term.resize(data.readUInt16BE(1), data.readUInt16BE(2));
+ return;
+ }
+ }
+ term.write(data);
+ });
+ socket.on("close", () => {
+ term.end();
+ });
+ });
}
-const SMALL_IMAGE_MAX_SIZE = 750 * 1024; // 750 KB
+const SMALL_IMAGE_MAX_SIZE = 750 * 1024; // 750 KB
const EXT_IMAGES = [".jpg", ".jpeg", ".png", ".webp", ".svg", ".gif", ".tiff"];
function isimage(f) {
- for (const ext of EXT_IMAGES) {
- if (f.endsWith(ext)) {
- return true;
- }
- }
- return false;
+ for (const ext of EXT_IMAGES) {
+ if (f.endsWith(ext)) {
+ return true;
+ }
+ }
+ return false;
}
app.get("/*", (req, res) => {
- if (res.stats.error) {
- res.render("list", flashify(req, {
- shellable: shellable,
- cmdable: cmdable,
- path: res.filename,
- errors: [
- res.stats.error
- ]
- }));
- }
- else if (res.stats.isDirectory()) {
- if (!req.url.endsWith("/")) {
- return res.redirect(req.url + "/");
- }
+ if (res.stats.error) {
+ res.render(
+ "list",
+ flashify(req, {
+ shellable: shellable,
+ cmdable: cmdable,
+ path: res.filename,
+ errors: [res.stats.error],
+ })
+ );
+ } else if (res.stats.isDirectory()) {
+ if (!req.url.endsWith("/")) {
+ return res.redirect(req.url + "/");
+ }
- let readDir = new Promise((resolve, reject) => {
- fs.readdir(relative(res.filename), (err, filenames) => {
- if (err) {
- return reject(err);
- }
- return resolve(filenames);
- });
- });
+ let readDir = new Promise((resolve, reject) => {
+ fs.readdir(relative(res.filename), (err, filenames) => {
+ if (err) {
+ return reject(err);
+ }
+ return resolve(filenames);
+ });
+ });
- readDir.then((filenames) => {
- const promises = filenames.map(f => new Promise((resolve, reject) => {
- fs.stat(relative(res.filename, f), (err, stats) => {
- if (err) {
- console.warn(err);
- return resolve({
- name: f,
- error: err
- });
- }
- resolve({
- name: f,
- isdirectory: stats.isDirectory(),
- issmallimage: isimage(f) && stats.size < SMALL_IMAGE_MAX_SIZE,
- size: stats.size
- });
- });
- }));
+ readDir
+ .then((filenames) => {
+ const promises = filenames.map(
+ (f) =>
+ new Promise((resolve, reject) => {
+ fs.stat(relative(res.filename, f), (err, stats) => {
+ if (err) {
+ console.warn(err);
+ return resolve({
+ name: f,
+ error: err,
+ });
+ }
+ resolve({
+ name: f,
+ isdirectory: stats.isDirectory(),
+ issmallimage: isimage(f) && stats.size < SMALL_IMAGE_MAX_SIZE,
+ size: stats.size,
+ });
+ });
+ })
+ );
- Promise.all(promises).then((files) => {
- res.render("list", flashify(req, {
- shellable: shellable,
- cmdable: cmdable,
- path: res.filename,
- files: files,
- }));
- }).catch((err) => {
- console.error(err);
- res.render("list", flashify(req, {
- shellable: shellable,
- cmdable: cmdable,
- path: res.filename,
- errors: [
- err
- ]
- }));
- });
- }).catch((err) => {
- console.warn(err);
- res.render("list", flashify(req, {
- shellable: shellable,
- cmdable: cmdable,
- path: res.filename,
- errors: [
- err
- ]
- }));
- });
- }
- else if (res.stats.isFile()) {
- res.sendFile(relative(res.filename), {
- headers: {
- "Content-Security-Policy": "default-src 'self'; script-src 'none'; sandbox"
- },
- dotfiles: "allow"
- });
- }
+ Promise.all(promises)
+ .then((files) => {
+ res.render(
+ "list",
+ flashify(req, {
+ shellable: shellable,
+ cmdable: cmdable,
+ path: res.filename,
+ files: files,
+ })
+ );
+ })
+ .catch((err) => {
+ console.error(err);
+ res.render(
+ "list",
+ flashify(req, {
+ shellable: shellable,
+ cmdable: cmdable,
+ path: res.filename,
+ errors: [err],
+ })
+ );
+ });
+ })
+ .catch((err) => {
+ console.warn(err);
+ res.render(
+ "list",
+ flashify(req, {
+ shellable: shellable,
+ cmdable: cmdable,
+ path: res.filename,
+ errors: [err],
+ })
+ );
+ });
+ } else if (res.stats.isFile()) {
+ res.sendFile(relative(res.filename), {
+ headers: {
+ "Content-Security-Policy":
+ "default-src 'self'; script-src 'none'; sandbox",
+ },
+ dotfiles: "allow",
+ });
+ }
});
+console.log(`Listening on port ${port}`);
diff --git a/package-lock.json b/package-lock.json
index 6dab7da..6bc5128 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "file-manager",
- "version": "0.0.7a",
+ "version": "0.1.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "file-manager",
- "version": "0.0.7a",
+ "version": "0.1.0",
"dependencies": {
"archiver": "^5.3.0",
"body-parser": "^1.19.0",
@@ -14,9 +14,9 @@
"connect-busboy": "^0.0.2",
"connect-flash": "^0.1.1",
"express": "^4.17.1",
- "express-handlebars": "^5.3.2",
- "express-session": "^1.17.1",
- "filesize": "^6.3.0",
+ "express-handlebars": "^6.0.1",
+ "express-session": "^1.17.2",
+ "filesize": "^8.0.6",
"jquery": "^3.6.0",
"node-pty": "^0.10.1",
"notp": "^2.0.3",
@@ -30,12 +30,15 @@
},
"bin": {
"file-manager": "index.js"
+ },
+ "devDependencies": {
+ "prettier": "^2.4.1"
}
},
"node_modules/@popperjs/core": {
- "version": "2.9.2",
- "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.9.2.tgz",
- "integrity": "sha512-VZMYa7+fXHdwIq1TDhSXoVmSPEGM/aa+6Aiq3nVVJ9bXr24zScr+NlKFKC3iPljA7ho/GAZr+d2jOf5GIRC30Q==",
+ "version": "2.10.2",
+ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.10.2.tgz",
+ "integrity": "sha512-IXf3XA7+XyN7CP9gGh/XB0UxVMlvARGEgGXLubFICsUMGz6Q+DU+i4gGlpOxTjKvXjkJDJC8YdqdKkDj9qZHEQ==",
"peer": true,
"funding": {
"type": "opencollective",
@@ -119,9 +122,9 @@
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
},
"node_modules/async": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz",
- "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw=="
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.2.tgz",
+ "integrity": "sha512-H0E+qZaDEfx/FY4t7iLRv1W2fFI6+pyCeTw1uN20AQPiwqwM6ojPxHxdLv4z8hi2DtnW9BOckSspLucW7pIE5g=="
},
"node_modules/balanced-match": {
"version": "1.0.2",
@@ -178,15 +181,15 @@
}
},
"node_modules/bootstrap": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.0.0.tgz",
- "integrity": "sha512-tmhPET9B9qCl8dCofvHeiIhi49iBt0EehmIsziZib65k1erBW1rHhj2s/2JsuQh5Pq+xz2E9bEbzp9B7xHG+VA==",
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.1.3.tgz",
+ "integrity": "sha512-fcQztozJ8jToQWXxVuEyXWW+dSo8AiXWKwiSSrKWsRB/Qt+Ewwza+JWoLKiTuQLaEPhdNAJ7+Dosc9DOIqNy7Q==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/bootstrap"
},
"peerDependencies": {
- "@popperjs/core": "^2.9.2"
+ "@popperjs/core": "^2.10.2"
}
},
"node_modules/brace-expansion": {
@@ -249,12 +252,12 @@
}
},
"node_modules/compress-commons": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.0.tgz",
- "integrity": "sha512-ofaaLqfraD1YRTkrRKPCrGJ1pFeDG/MVCkVVV2FNGeWquSlqw5wOrwOfPQ1xF2u+blpeWASie5EubHz+vsNIgA==",
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.1.tgz",
+ "integrity": "sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==",
"dependencies": {
"buffer-crc32": "^0.2.13",
- "crc32-stream": "^4.0.1",
+ "crc32-stream": "^4.0.2",
"normalize-path": "^3.0.0",
"readable-stream": "^3.6.0"
},
@@ -319,9 +322,9 @@
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
},
"node_modules/core-util-is": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
- "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
},
"node_modules/crc-32": {
"version": "1.2.0",
@@ -465,36 +468,44 @@
}
},
"node_modules/express-handlebars": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/express-handlebars/-/express-handlebars-5.3.2.tgz",
- "integrity": "sha512-iGR7HXP+x+SfJQo9m00ocqcr7hU8ZzcssTLE/4wBX+jsqcblO6sFJEbEAEFjiNze3XMz9Y26Zs1WN5Bb4zxivQ==",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/express-handlebars/-/express-handlebars-6.0.1.tgz",
+ "integrity": "sha512-K3Lemki5jkD3sZwDhgBEBk+oAl1xg4nsMJAfpq1AUl5K187/mU1/xKVWt+4RZAHAxlyQFk4YBfX5+00AzLNfWg==",
"dependencies": {
- "glob": "^7.1.7",
- "graceful-fs": "^4.2.6",
+ "glob": "^7.2.0",
+ "graceful-fs": "^4.2.8",
"handlebars": "^4.7.7"
},
"engines": {
- "node": ">=v10.24.1"
+ "node": ">=v12.22.7"
}
},
"node_modules/express-session": {
- "version": "1.17.1",
- "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.1.tgz",
- "integrity": "sha512-UbHwgqjxQZJiWRTMyhvWGvjBQduGCSBDhhZXYenziMFjxst5rMV+aJZ6hKPHZnPyHGsrqRICxtX8jtEbm/z36Q==",
+ "version": "1.17.2",
+ "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.2.tgz",
+ "integrity": "sha512-mPcYcLA0lvh7D4Oqr5aNJFMtBMKPLl++OKKxkHzZ0U0oDq1rpKBnkR5f5vCHR26VeArlTOEF9td4x5IjICksRQ==",
"dependencies": {
- "cookie": "0.4.0",
+ "cookie": "0.4.1",
"cookie-signature": "1.0.6",
"debug": "2.6.9",
"depd": "~2.0.0",
"on-headers": "~1.0.2",
"parseurl": "~1.3.3",
- "safe-buffer": "5.2.0",
+ "safe-buffer": "5.2.1",
"uid-safe": "~2.1.5"
},
"engines": {
"node": ">= 0.8.0"
}
},
+ "node_modules/express-session/node_modules/cookie": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
+ "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
"node_modules/express-session/node_modules/depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
@@ -504,14 +515,28 @@
}
},
"node_modules/express-session/node_modules/safe-buffer": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
- "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
},
"node_modules/filesize": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/filesize/-/filesize-6.3.0.tgz",
- "integrity": "sha512-ytx0ruGpDHKWVoiui6+BY/QMNngtDQ/pJaFwfBpQif0J63+E8DLdFyqS3NkKQn7vIruUEpoGD9JUJSg7Kp+I0g==",
+ "version": "8.0.6",
+ "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.6.tgz",
+ "integrity": "sha512-sHvRqTiwdmcuzqet7iVwsbwF6UrV3wIgDf2SHNdY1Hgl8PC45HZg/0xtdw6U2izIV4lccnrY9ftl6wZFNdjYMg==",
"engines": {
"node": ">= 0.4.0"
}
@@ -534,9 +559,9 @@
}
},
"node_modules/forwarded": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
- "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=",
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
"engines": {
"node": ">= 0.6"
}
@@ -560,9 +585,9 @@
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"node_modules/glob": {
- "version": "7.1.7",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
- "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
+ "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@@ -579,9 +604,9 @@
}
},
"node_modules/graceful-fs": {
- "version": "4.2.6",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
- "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ=="
+ "version": "4.2.8",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz",
+ "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg=="
},
"node_modules/handlebars": {
"version": "4.7.7",
@@ -686,9 +711,9 @@
"integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw=="
},
"node_modules/lazystream": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz",
- "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=",
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz",
+ "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==",
"dependencies": {
"readable-stream": "^2.0.5"
},
@@ -776,19 +801,19 @@
}
},
"node_modules/mime-db": {
- "version": "1.47.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz",
- "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==",
+ "version": "1.51.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
+ "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
- "version": "2.1.30",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz",
- "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==",
+ "version": "2.1.34",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
+ "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
"dependencies": {
- "mime-db": "1.47.0"
+ "mime-db": "1.51.0"
},
"engines": {
"node": ">= 0.6"
@@ -816,9 +841,9 @@
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"node_modules/nan": {
- "version": "2.14.2",
- "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz",
- "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ=="
+ "version": "2.15.0",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz",
+ "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ=="
},
"node_modules/negotiator": {
"version": "0.6.2",
@@ -923,6 +948,18 @@
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
},
+ "node_modules/prettier": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.4.1.tgz",
+ "integrity": "sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA==",
+ "dev": true,
+ "bin": {
+ "prettier": "bin-prettier.js"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
"node_modules/printj": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz",
@@ -940,11 +977,11 @@
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
},
"node_modules/proxy-addr": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
- "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==",
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
+ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
"dependencies": {
- "forwarded": "~0.1.2",
+ "forwarded": "0.2.0",
"ipaddr.js": "1.9.1"
},
"engines": {
@@ -1176,9 +1213,9 @@
}
},
"node_modules/uglify-js": {
- "version": "3.13.5",
- "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.5.tgz",
- "integrity": "sha512-xtB8yEqIkn7zmOyS2zUNBsYCBRhDkvlNxMMY2smuJ/qA8NCHeQvKCF3i9Z4k8FJH4+PJvZRtMrPynfZ75+CSZw==",
+ "version": "3.14.3",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.14.3.tgz",
+ "integrity": "sha512-mic3aOdiq01DuSVx0TseaEzMIVqebMZ0Z3vaeDhFEh9bsc24hV1TFvN74reA2vs08D0ZWfNjAcJ3UbVLaBss+g==",
"optional": true,
"bin": {
"uglifyjs": "bin/uglifyjs"
@@ -1238,9 +1275,9 @@
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"node_modules/ws": {
- "version": "7.4.6",
- "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
- "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
+ "version": "7.5.5",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz",
+ "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==",
"engines": {
"node": ">=8.3.0"
},
@@ -1258,9 +1295,9 @@
}
},
"node_modules/xterm": {
- "version": "4.11.0",
- "resolved": "https://registry.npmjs.org/xterm/-/xterm-4.11.0.tgz",
- "integrity": "sha512-NeJH909WTO2vth/ZlC0gkP3AGzupbvVHVlmtrpBw56/sGFXaF9bNdKgqKa3tf8qbGvXMzL2JhCcHVklqFztIRw=="
+ "version": "4.15.0",
+ "resolved": "https://registry.npmjs.org/xterm/-/xterm-4.15.0.tgz",
+ "integrity": "sha512-Ik1GoSq1yqKZQ2LF37RPS01kX9t4TP8gpamUYblD09yvWX5mEYuMK4CcqH6+plgiNEZduhTz/UrcaWs97gOlOw=="
},
"node_modules/xterm-addon-attach": {
"version": "0.6.0",
@@ -1294,9 +1331,9 @@
},
"dependencies": {
"@popperjs/core": {
- "version": "2.9.2",
- "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.9.2.tgz",
- "integrity": "sha512-VZMYa7+fXHdwIq1TDhSXoVmSPEGM/aa+6Aiq3nVVJ9bXr24zScr+NlKFKC3iPljA7ho/GAZr+d2jOf5GIRC30Q==",
+ "version": "2.10.2",
+ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.10.2.tgz",
+ "integrity": "sha512-IXf3XA7+XyN7CP9gGh/XB0UxVMlvARGEgGXLubFICsUMGz6Q+DU+i4gGlpOxTjKvXjkJDJC8YdqdKkDj9qZHEQ==",
"peer": true
},
"accepts": {
@@ -1369,9 +1406,9 @@
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
},
"async": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz",
- "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw=="
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.2.tgz",
+ "integrity": "sha512-H0E+qZaDEfx/FY4t7iLRv1W2fFI6+pyCeTw1uN20AQPiwqwM6ojPxHxdLv4z8hi2DtnW9BOckSspLucW7pIE5g=="
},
"balanced-match": {
"version": "1.0.2",
@@ -1411,9 +1448,9 @@
}
},
"bootstrap": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.0.0.tgz",
- "integrity": "sha512-tmhPET9B9qCl8dCofvHeiIhi49iBt0EehmIsziZib65k1erBW1rHhj2s/2JsuQh5Pq+xz2E9bEbzp9B7xHG+VA==",
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.1.3.tgz",
+ "integrity": "sha512-fcQztozJ8jToQWXxVuEyXWW+dSo8AiXWKwiSSrKWsRB/Qt+Ewwza+JWoLKiTuQLaEPhdNAJ7+Dosc9DOIqNy7Q==",
"requires": {}
},
"brace-expansion": {
@@ -1453,12 +1490,12 @@
"integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
},
"compress-commons": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.0.tgz",
- "integrity": "sha512-ofaaLqfraD1YRTkrRKPCrGJ1pFeDG/MVCkVVV2FNGeWquSlqw5wOrwOfPQ1xF2u+blpeWASie5EubHz+vsNIgA==",
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.1.tgz",
+ "integrity": "sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==",
"requires": {
"buffer-crc32": "^0.2.13",
- "crc32-stream": "^4.0.1",
+ "crc32-stream": "^4.0.2",
"normalize-path": "^3.0.0",
"readable-stream": "^3.6.0"
}
@@ -1505,9 +1542,9 @@
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
},
"core-util-is": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
- "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
},
"crc-32": {
"version": "1.2.0",
@@ -1624,46 +1661,51 @@
}
},
"express-handlebars": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/express-handlebars/-/express-handlebars-5.3.2.tgz",
- "integrity": "sha512-iGR7HXP+x+SfJQo9m00ocqcr7hU8ZzcssTLE/4wBX+jsqcblO6sFJEbEAEFjiNze3XMz9Y26Zs1WN5Bb4zxivQ==",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/express-handlebars/-/express-handlebars-6.0.1.tgz",
+ "integrity": "sha512-K3Lemki5jkD3sZwDhgBEBk+oAl1xg4nsMJAfpq1AUl5K187/mU1/xKVWt+4RZAHAxlyQFk4YBfX5+00AzLNfWg==",
"requires": {
- "glob": "^7.1.7",
- "graceful-fs": "^4.2.6",
+ "glob": "^7.2.0",
+ "graceful-fs": "^4.2.8",
"handlebars": "^4.7.7"
}
},
"express-session": {
- "version": "1.17.1",
- "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.1.tgz",
- "integrity": "sha512-UbHwgqjxQZJiWRTMyhvWGvjBQduGCSBDhhZXYenziMFjxst5rMV+aJZ6hKPHZnPyHGsrqRICxtX8jtEbm/z36Q==",
+ "version": "1.17.2",
+ "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.2.tgz",
+ "integrity": "sha512-mPcYcLA0lvh7D4Oqr5aNJFMtBMKPLl++OKKxkHzZ0U0oDq1rpKBnkR5f5vCHR26VeArlTOEF9td4x5IjICksRQ==",
"requires": {
- "cookie": "0.4.0",
+ "cookie": "0.4.1",
"cookie-signature": "1.0.6",
"debug": "2.6.9",
"depd": "~2.0.0",
"on-headers": "~1.0.2",
"parseurl": "~1.3.3",
- "safe-buffer": "5.2.0",
+ "safe-buffer": "5.2.1",
"uid-safe": "~2.1.5"
},
"dependencies": {
+ "cookie": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
+ "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA=="
+ },
"depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
},
"safe-buffer": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
- "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
}
}
},
"filesize": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/filesize/-/filesize-6.3.0.tgz",
- "integrity": "sha512-ytx0ruGpDHKWVoiui6+BY/QMNngtDQ/pJaFwfBpQif0J63+E8DLdFyqS3NkKQn7vIruUEpoGD9JUJSg7Kp+I0g=="
+ "version": "8.0.6",
+ "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.6.tgz",
+ "integrity": "sha512-sHvRqTiwdmcuzqet7iVwsbwF6UrV3wIgDf2SHNdY1Hgl8PC45HZg/0xtdw6U2izIV4lccnrY9ftl6wZFNdjYMg=="
},
"finalhandler": {
"version": "1.1.2",
@@ -1680,9 +1722,9 @@
}
},
"forwarded": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
- "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="
},
"fresh": {
"version": "0.5.2",
@@ -1700,9 +1742,9 @@
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"glob": {
- "version": "7.1.7",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
- "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
+ "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@@ -1713,9 +1755,9 @@
}
},
"graceful-fs": {
- "version": "4.2.6",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
- "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ=="
+ "version": "4.2.8",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz",
+ "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg=="
},
"handlebars": {
"version": "4.7.7",
@@ -1791,9 +1833,9 @@
"integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw=="
},
"lazystream": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz",
- "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=",
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz",
+ "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==",
"requires": {
"readable-stream": "^2.0.5"
},
@@ -1868,16 +1910,16 @@
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
},
"mime-db": {
- "version": "1.47.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz",
- "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw=="
+ "version": "1.51.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
+ "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g=="
},
"mime-types": {
- "version": "2.1.30",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz",
- "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==",
+ "version": "2.1.34",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
+ "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
"requires": {
- "mime-db": "1.47.0"
+ "mime-db": "1.51.0"
}
},
"minimatch": {
@@ -1899,9 +1941,9 @@
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"nan": {
- "version": "2.14.2",
- "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz",
- "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ=="
+ "version": "2.15.0",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz",
+ "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ=="
},
"negotiator": {
"version": "0.6.2",
@@ -1980,6 +2022,12 @@
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
},
+ "prettier": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.4.1.tgz",
+ "integrity": "sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA==",
+ "dev": true
+ },
"printj": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz",
@@ -1991,11 +2039,11 @@
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
},
"proxy-addr": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
- "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==",
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
+ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
"requires": {
- "forwarded": "~0.1.2",
+ "forwarded": "0.2.0",
"ipaddr.js": "1.9.1"
}
},
@@ -2166,9 +2214,9 @@
}
},
"uglify-js": {
- "version": "3.13.5",
- "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.5.tgz",
- "integrity": "sha512-xtB8yEqIkn7zmOyS2zUNBsYCBRhDkvlNxMMY2smuJ/qA8NCHeQvKCF3i9Z4k8FJH4+PJvZRtMrPynfZ75+CSZw==",
+ "version": "3.14.3",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.14.3.tgz",
+ "integrity": "sha512-mic3aOdiq01DuSVx0TseaEzMIVqebMZ0Z3vaeDhFEh9bsc24hV1TFvN74reA2vs08D0ZWfNjAcJ3UbVLaBss+g==",
"optional": true
},
"uid-safe": {
@@ -2210,15 +2258,15 @@
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"ws": {
- "version": "7.4.6",
- "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
- "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
+ "version": "7.5.5",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz",
+ "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==",
"requires": {}
},
"xterm": {
- "version": "4.11.0",
- "resolved": "https://registry.npmjs.org/xterm/-/xterm-4.11.0.tgz",
- "integrity": "sha512-NeJH909WTO2vth/ZlC0gkP3AGzupbvVHVlmtrpBw56/sGFXaF9bNdKgqKa3tf8qbGvXMzL2JhCcHVklqFztIRw=="
+ "version": "4.15.0",
+ "resolved": "https://registry.npmjs.org/xterm/-/xterm-4.15.0.tgz",
+ "integrity": "sha512-Ik1GoSq1yqKZQ2LF37RPS01kX9t4TP8gpamUYblD09yvWX5mEYuMK4CcqH6+plgiNEZduhTz/UrcaWs97gOlOw=="
},
"xterm-addon-attach": {
"version": "0.6.0",
diff --git a/package.json b/package.json
index efdfa26..3f3e992 100644
--- a/package.json
+++ b/package.json
@@ -2,8 +2,12 @@
"name": "file-manager",
"description": "A simple file manager",
"version": "0.1.0",
+ "scripts": {
+ "format": "prettier --write .",
+ "start": "node index.js"
+ },
"bin": {
- "file-manager": "./index.js"
+ "file-manager": "index.js"
},
"dependencies": {
"archiver": "^5.3.0",
@@ -12,9 +16,9 @@
"connect-busboy": "^0.0.2",
"connect-flash": "^0.1.1",
"express": "^4.17.1",
- "express-handlebars": "^5.3.2",
- "express-session": "^1.17.1",
- "filesize": "^6.3.0",
+ "express-handlebars": "^6.0.1",
+ "express-session": "^1.17.2",
+ "filesize": "^8.0.6",
"jquery": "^3.6.0",
"node-pty": "^0.10.1",
"notp": "^2.0.3",
@@ -25,5 +29,8 @@
"xterm": "^4.11.0",
"xterm-addon-attach": "^0.6.0",
"xterm-addon-fit": "^0.5.0"
+ },
+ "devDependencies": {
+ "prettier": "^2.4.1"
}
}