const fs = require("fs"); const path = require("path"); const { ENOENT, ECONNRESET } = require("constants"); const Koa = require("koa"); const koaPug = require("koa-pug"); const koaRouter = require("koa-router"); const config = require("./config"); const util = require("../shared/util"); const SIZE_UNITS = [ "B", "KiB", "MiB", "GiB" ]; function addFileSizeUnit(size) { let i = 0; for (; size > 1024; size /= 1024) ++i; return [i > 0 ? size.toFixed(2) : size, SIZE_UNITS[i]]; } function buildCurrentPathLink(path) { let currentPath = `root`; if (path.endsWith("/")) path = path.slice(1, path.length-1); const path_parts = path.split("/"); for (let i = 0; i < path_parts.length; ++i) { let lnk = ""; for (let j = 0; j < i+1; ++j) lnk += `/${path_parts[j]}`; currentPath += `/${path_parts[i]}`; } return currentPath; } function sortFuncByNameField(a, b) { return (a.name > b.name) ? 1 : (a.name < b.name) ? -1 : 0; } async function getDirectoryList(dir_path, orig_url) { let directories = []; let files = []; let total_files_size = 0; let directory = await fs.promises.opendir(dir_path); for await (const dirent of directory) { const stat = await fs.promises.stat(path.join(dir_path, dirent.name)); const [s, u] = addFileSizeUnit(stat.size); if (stat.isDirectory()) directories.push({ name: dirent.name, link: `${encodeURIComponent(dirent.name)}/`, datetime: stat.mtime, size: "DIR" }); else { total_files_size += stat.size; files.push({ name: dirent.name, link: `/files${orig_url}${encodeURIComponent(dirent.name)}`, datetime: stat.mtime, size: `${s} ${u}` }); } } directories.sort(sortFuncByNameField); files.sort(sortFuncByNameField); return [directories.concat(files), directories.length, files.length, addFileSizeUnit(total_files_size).join(' ')]; } function setRoutes() { return koaRouter().get('/(.*)?', async ctx => { const file_path = path.join(config.share_path, decodeURI(ctx.originalUrl)); let stat = await fs.promises.stat(file_path); if (stat.isDirectory()) { const [items, total_directories, total_files, total_files_size] = await getDirectoryList(file_path, decodeURI(ctx.originalUrl)); await ctx.render('index', { title: "/ Files", description: "File share.", clientTZ: util.getClientTimezone(ctx), main_site: util.getServiceByHost(ctx.header.host), current_path: buildCurrentPathLink(decodeURI(ctx.originalUrl)), total_files: total_files, total_files_size: total_files_size, total_directories: total_directories, items: items }); } }); } const app = new Koa(); const pug = new koaPug({ viewPath: path.join(__dirname, "views"), locals: { moment: (date, tz) => util.datetime(date, util.formats.file_date, tz), }, app: app }); app.proxy = true; app .use(setRoutes().routes()) // .on("error", err => { if (!err.code == ECONNRESET || !err.code == ENOENT) console.log(err.code); }) .listen(config.port, config.host); console.log("Arav's dwelling / Files is up.");