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,