added "get list" in folder menu #231

Massimo Melina committed May 7, 2023 at 23:12 UTC e6fd1b9691ed5883c2ff7db3703b0400cbc8cd0b
4 files changed +26 -5
frontend/src/Breadcrumbs.ts
+1 -1
@@ -38,7 +38,7 @@ function Breadcrumb({ path, label, current }:{ current?: boolean, path?: string,
38 to: path || '/',
39 async onClick(ev) {
40 if (!current) return
41 - const asEntry = { n: path!, uri: path!, name: label as string, ext: '', isFolder: true, cantOpen: false }
41 + const asEntry = { n: '', uri: '', name: label as string, ext: '', isFolder: true, cantOpen: false }
42 openFileMenu(asEntry, ev as any as MouseEvent, [
43 {
44 label: t`Reload`,
frontend/src/fileMenu.ts
+1
@@ -17,6 +17,7 @@ export function openFileMenu(entry: DirEntry, ev: MouseEvent, addToMenu: FileMen
17 const menu = [
18 !cantDownload && { label: t`Download`, href: uri + (isFolder ? '?get=zip' : '?dl'), icon: 'download' },
19 ...addToMenu,
20 + isFolder && { label: t`Get list`, href: uri + '?get=list&folders=*', icon: 'menu' }
21 ]
22 const props = [
23 [t(`Name`), entry.name]
src/middlewares.ts
+22 -2
@@ -9,8 +9,16 @@ import {
9 HTTP_FORBIDDEN, HTTP_NOT_FOUND, HTTP_FOOL,
10 } from './const'
11 import { FRONTEND_URI } from './const'
12 -import { statusCodeForMissingPerm, nodeIsDirectory, urlToNode, vfs } from './vfs'
13 -import { dirTraversal, isLocalHost, newObj, stream2string, tryJson } from './misc'
12 +import { statusCodeForMissingPerm, nodeIsDirectory, urlToNode, vfs, walkNode, VfsNode } from './vfs'
13 +import {
14 + asyncGeneratorToReadable,
15 + dirTraversal,
16 + filterMapGenerator,
17 + isLocalHost,
18 + newObj,
19 + stream2string,
20 + tryJson
21 +} from './misc'
22 import { zipStreamFromFolder } from './zip'
23 import { serveFile, serveFileNode } from './serveFile'
24 import { serveGuiFiles } from './serveGuiFiles'
@@ -137,9 +145,21 @@ export const serveGuiAndSharedFiles: Koa.Middleware = async (ctx, next) => {
145 }
146 ctx.set({ server:'HFS '+BUILD_TIMESTAMP })
147 return ctx.query.get === 'zip' ? zipStreamFromFolder(node, ctx)
148 + : ctx.query.get === 'list' ? sendFolderList(node, ctx)
149 : serveFrontendFiles(ctx, next)
150 }
151
152 +async function sendFolderList(node: VfsNode, ctx: Koa.Context) {
153 + const { depth=0, folders } = ctx.query
154 + ctx.type = 'text'
155 + const walker = walkNode(node, ctx, depth === '*' ? Infinity : Number(depth))
156 + ctx.body = asyncGeneratorToReadable(filterMapGenerator(walker, async el => {
157 + const isFolder = await nodeIsDirectory(el)
158 + return !folders && isFolder ? undefined
159 + : el.name + (isFolder ? '/' : '') + '\n'
160 + }))
161 +}
162 +
163 let proxyDetected: undefined | Koa.Context
164 export const someSecurity: Koa.Middleware = async (ctx, next) => {
165 ctx.request.ip = normalizeIp(ctx.ip)
src/util-files.ts
+2 -2
@@ -75,13 +75,13 @@ export function adjustStaticPathForGlob(path: string) {
75 return glob.escapePath(path.replace(/\\/g, '/'))
76 }
77
78 -export async function* dirStream(path: string, deep?: number) {
78 +export async function* dirStream(path: string, deep=0) {
79 if (!await isDirectory(path))
80 throw Error('ENOTDIR')
81 const dirStream = glob.stream(deep ? '**/*' : '*', {
82 cwd: path,
83 dot: true,
84 - deep,
84 + deep: deep + 1,
85 onlyFiles: false,
86 suppressErrors: true,
87 objectMode: true,