hfs 3.3.0-beta3 → 3.3.0-rc5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/admin/assets/{AccountsPage-DB7ljNHT.js → AccountsPage-Cq0xZ11q.js} +2 -2
- package/admin/assets/{ArrayField-Qj2iHD7I.js → ArrayField-DlXwGcRi.js} +1 -1
- package/admin/assets/{ConfigFilePage-TErmt0PK.js → ConfigFilePage-CS1DHLl9.js} +1 -1
- package/admin/assets/{CustomHtmlPage-CVmk-_JS.js → CustomHtmlPage-D2bJwsUf.js} +1 -1
- package/admin/assets/{DataTable-DmnQXyFO.js → DataTable--J_wIcuM.js} +1 -1
- package/admin/assets/{DateTimeField-BUWd2w9-.js → DateTimeField-DWeCPNja.js} +1 -1
- package/admin/assets/{EventManager-9vwKg8as.js → EventManager-DrRWt_JH.js} +1 -1
- package/admin/assets/{FileField-DoBaSTxF.js → FileField-mNPkd3y3.js} +1 -1
- package/admin/assets/{InternetPage-Biuer1tb.js → InternetPage--PzizUL_.js} +1 -1
- package/admin/assets/{LangPage-Vd24DNK5.js → LangPage-B4rQVR1J.js} +1 -1
- package/admin/assets/{LogsPage-BdvttEqM.js → LogsPage-Cf8QzZqj.js} +2 -2
- package/admin/assets/{MenuButton-CHLgqU5W.js → MenuButton-DMz8eU4k.js} +1 -1
- package/admin/assets/{MonitorPage-DlXkZUmT.js → MonitorPage-BfEEqSB9.js} +1 -1
- package/admin/assets/{OptionsPage-Zi8FmrjE.js → OptionsPage-Di4sYyHk.js} +1 -1
- package/admin/assets/{PluginsPage-BzwEIFt5.js → PluginsPage-C1AwIVck.js} +1 -1
- package/admin/assets/{Tabs-CVipqhB9.js → Tabs-B8NzzlRi.js} +1 -1
- package/admin/assets/{TextEditor-clbVugYM.js → TextEditor-BF5GhCMi.js} +1 -1
- package/admin/assets/{VfsPathField-YUCV9PfL.js → VfsPathField-BKblqejE.js} +1 -1
- package/admin/assets/{agentIcons-DW9QViyx.js → agentIcons-xvHQBkKp.js} +1 -1
- package/admin/assets/{baseUrl-Do5CYuBZ.js → baseUrl-Cp5EQLCd.js} +1 -1
- package/admin/assets/icons-BfdCXZin.js +1 -0
- package/admin/assets/{index-Dsq-sVu9.js → index-CSmjBo2G.js} +2 -2
- package/admin/assets/{routing-Cjyek7O_.js → routing-BQgmPveQ.js} +1 -1
- package/admin/index.html +1 -1
- package/frontend/assets/{dist-legacy-BNFW04Ss.js → dist-legacy-BwOLCt69.js} +1 -1
- package/frontend/assets/index-legacy-BrUKT6jx.js +1 -0
- package/frontend/assets/{lib-legacy-CO5spnaN.js → lib-legacy-Dtus09cI.js} +1 -1
- package/frontend/assets/{sha512-legacy-BuJAJxVV.js → sha512-legacy-CBENfTz7.js} +1 -1
- package/frontend/index.html +1 -1
- package/npm-shrinkwrap.json +135 -85
- package/package.json +1 -1
- package/plugins/antibrute/plugin.js +23 -14
- package/src/api.accounts.js +1 -1
- package/src/api.auth.js +1 -0
- package/src/api.monitor.js +1 -1
- package/src/config.js +7 -6
- package/src/cross.js +1 -1
- package/src/customHtml.js +1 -6
- package/src/frontEndApis.js +2 -1
- package/src/log.js +1 -1
- package/src/middlewares.js +6 -0
- package/src/multipartUpload.js +1 -1
- package/src/perm.js +19 -7
- package/src/serveFile.js +6 -2
- package/src/serveGuiAndSharedFiles.js +1 -1
- package/src/serveGuiFiles.js +5 -1
- package/src/uploadOwners.js +1 -1
- package/src/vfs.js +5 -6
- package/src/webdav.js +34 -19
- package/src/zip.js +3 -1
- package/admin/assets/icons-3rupj9Xr.js +0 -1
- package/frontend/assets/index-legacy-2akkos6t.js +0 -1
|
@@ -16,10 +16,10 @@ exports.configDialog = {
|
|
|
16
16
|
maxWidth: 'xs',
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
const byIp =
|
|
20
|
-
const byAccount =
|
|
21
|
-
const laneByIp =
|
|
22
|
-
const laneByAccount =
|
|
19
|
+
const byIp = new Map()
|
|
20
|
+
const byAccount = new Map()
|
|
21
|
+
const laneByIp = new Map()
|
|
22
|
+
const laneByAccount = new Map()
|
|
23
23
|
const UNKNOWN_ACCOUNT = 'unknown\t'
|
|
24
24
|
|
|
25
25
|
exports.init = api => {
|
|
@@ -107,7 +107,12 @@ exports.init = api => {
|
|
|
107
107
|
})
|
|
108
108
|
|
|
109
109
|
function getRecord(container, key) {
|
|
110
|
-
|
|
110
|
+
let rec = container.get(key)
|
|
111
|
+
if (!rec) {
|
|
112
|
+
rec = { failures: 0, next: 0, waiting: 0 }
|
|
113
|
+
container.set(key, rec)
|
|
114
|
+
}
|
|
115
|
+
return rec
|
|
111
116
|
}
|
|
112
117
|
|
|
113
118
|
function increasePenalty(rec, now) {
|
|
@@ -124,7 +129,7 @@ exports.init = api => {
|
|
|
124
129
|
// keep records while there are in-flight admissions, otherwise later releases may touch deleted state
|
|
125
130
|
if (rec.waiting)
|
|
126
131
|
return armCleanup(records, key, rec)
|
|
127
|
-
delete
|
|
132
|
+
records.delete(key)
|
|
128
133
|
}, 24 * HOUR) // no memory leak
|
|
129
134
|
}
|
|
130
135
|
|
|
@@ -138,7 +143,12 @@ exports.init = api => {
|
|
|
138
143
|
}
|
|
139
144
|
|
|
140
145
|
function getLane(container, key) {
|
|
141
|
-
|
|
146
|
+
let lane = container.get(key)
|
|
147
|
+
if (!lane) {
|
|
148
|
+
lane = makeQ(1)
|
|
149
|
+
container.set(key, lane)
|
|
150
|
+
}
|
|
151
|
+
return lane
|
|
142
152
|
}
|
|
143
153
|
|
|
144
154
|
function runInLane(q, job) {
|
|
@@ -151,13 +161,13 @@ exports.init = api => {
|
|
|
151
161
|
}
|
|
152
162
|
|
|
153
163
|
function dropLaneIfIdle(container, key) {
|
|
154
|
-
const q = container
|
|
164
|
+
const q = container.get(key)
|
|
155
165
|
if (q?.isWorking() || q?.queueSize()) return
|
|
156
|
-
delete
|
|
166
|
+
container.delete(key)
|
|
157
167
|
}
|
|
158
168
|
|
|
159
169
|
function resetRecord(container, key) {
|
|
160
|
-
const rec = container
|
|
170
|
+
const rec = container.get(key)
|
|
161
171
|
if (!rec) return
|
|
162
172
|
if (rec.waiting) {
|
|
163
173
|
// successful login must clear penalties without dropping admission counters still needed by concurrent requests
|
|
@@ -165,14 +175,13 @@ exports.init = api => {
|
|
|
165
175
|
rec.next = 0
|
|
166
176
|
return
|
|
167
177
|
}
|
|
168
|
-
delete
|
|
178
|
+
container.delete(key)
|
|
169
179
|
}
|
|
170
180
|
|
|
171
181
|
function getAccountKey(username) {
|
|
172
182
|
// fold unknown usernames together to avoid unbounded memory growth from random names
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
return String(username).toLowerCase()
|
|
183
|
+
const account = username && api.getAccount(String(username))
|
|
184
|
+
return account ? account.username : UNKNOWN_ACCOUNT
|
|
176
185
|
}
|
|
177
186
|
|
|
178
187
|
function isExcluded(ip) {
|
package/src/api.accounts.js
CHANGED
|
@@ -61,7 +61,7 @@ exports.default = {
|
|
|
61
61
|
return new apiMiddleware_1.ApiError(const_1.HTTP_BAD_REQUEST);
|
|
62
62
|
await (0, perm_1.updateAccount)(acc, (0, api_vfs_1.pickProps)(changes, ALLOWED_KEYS));
|
|
63
63
|
if (changes.username && ctx.session?.username === (0, perm_1.normalizeUsername)(username)) // update session if necessary
|
|
64
|
-
ctx.session.username =
|
|
64
|
+
ctx.session.username = acc.username;
|
|
65
65
|
return lodash_1.default.pick(acc, 'username');
|
|
66
66
|
},
|
|
67
67
|
async add_account({ overwrite, username, ...rest }) {
|
package/src/api.auth.js
CHANGED
|
@@ -80,6 +80,7 @@ exports.authApis = {
|
|
|
80
80
|
const sid = (0, node_crypto_1.randomUUID)();
|
|
81
81
|
ongoingLogins[sid] = srpServer;
|
|
82
82
|
setTimeout(() => delete ongoingLogins[sid], 60_000); // client must complete api sequence (loginSrp2) within 1 minute or will be discarded to avoid memory leaks
|
|
83
|
+
// 60-second expiry bounded 5k challenges to ~37 MB in a local saturation test, so an additional cap isn't justified
|
|
83
84
|
ctx.session.loggingIn = { username, sid }; // temporarily store until process is complete
|
|
84
85
|
return rest;
|
|
85
86
|
}
|
package/src/api.monitor.js
CHANGED
|
@@ -108,7 +108,7 @@ function inferOperation(ctx) {
|
|
|
108
108
|
: s.uploadPath ? { op: 'upload', path: (0, misc_1.safeDecodeURIComponent)(s.uploadPath) }
|
|
109
109
|
: {
|
|
110
110
|
op: !s.considerAsGui && (ctx.state.archive || ctx.state.vfsNode) ? 'download' : undefined,
|
|
111
|
-
path: (0, misc_1.safeDecodeURIComponent)(
|
|
111
|
+
path: (0, misc_1.safeDecodeURIComponent)(s.safeUrl),
|
|
112
112
|
},
|
|
113
113
|
opProgress: lodash_1.default.isNumber(s.opProgress) ? lodash_1.default.round(s.opProgress, 3) : undefined,
|
|
114
114
|
opTotal: s.opTotal,
|
package/src/config.js
CHANGED
|
@@ -80,13 +80,13 @@ function defineConfig(k, defaultValue, compiler) {
|
|
|
80
80
|
},
|
|
81
81
|
sub(cb) {
|
|
82
82
|
if (started) // initial event already passed, we'll make the first call
|
|
83
|
-
cb(getConfig(k), { k, was: defaultValue, defaultValue, version: configVersion.compiled(), object });
|
|
83
|
+
cb(getConfig(k), { k, was: defaultValue, defaultValue, version: configVersion.compiled(), set, object });
|
|
84
84
|
return events_1.default.on(CONFIG_CHANGE_EVENT_PREFIX + k, (v, was, version, onlyCompileChanged) => {
|
|
85
85
|
if (stack.includes(cb))
|
|
86
86
|
return; // avoid infinite loop in case a subscriber changes the value
|
|
87
87
|
stack.push(cb);
|
|
88
88
|
try {
|
|
89
|
-
return cb(v, { k, was, version, defaultValue, object, onlyCompileChanged });
|
|
89
|
+
return cb(v, { k, was, version, set, defaultValue, object, onlyCompileChanged });
|
|
90
90
|
}
|
|
91
91
|
finally {
|
|
92
92
|
stack.pop();
|
|
@@ -109,7 +109,8 @@ function defineConfig(k, defaultValue, compiler) {
|
|
|
109
109
|
},
|
|
110
110
|
dontStore() { dontStore.push(k); },
|
|
111
111
|
};
|
|
112
|
-
|
|
112
|
+
const set = object.set.bind(object);
|
|
113
|
+
let compiled = compiler?.(defaultValue, { k, version: exports.currentVersion, set, defaultValue, object });
|
|
113
114
|
if (compiler)
|
|
114
115
|
object.sub((v, more) => {
|
|
115
116
|
if (!more.onlyCompileChanged)
|
|
@@ -154,13 +155,13 @@ async function setConfig(newCfg, save) {
|
|
|
154
155
|
return;
|
|
155
156
|
}
|
|
156
157
|
// first time we emit also for the default values
|
|
157
|
-
await Promise.allSettled(Object.keys(configProps).map(k => newCfg.hasOwnProperty(k) || apply(k, undefined
|
|
158
|
+
await Promise.allSettled(Object.keys(configProps).map(k => newCfg.hasOwnProperty(k) || apply(k, undefined)));
|
|
158
159
|
started = true;
|
|
159
160
|
events_1.default.emit('configReady', startedWithoutConfig);
|
|
160
161
|
if (version?.valueOf() !== const_1.VERSION) // be sure to save the new version in the file
|
|
161
162
|
(0, exports.saveConfigAsap)();
|
|
162
|
-
function apply(k, newV
|
|
163
|
-
return setConfig1(k, newV, save === undefined, argCfg
|
|
163
|
+
function apply(k, newV) {
|
|
164
|
+
return setConfig1(k, newV, save === undefined, !lodash_1.default.has(argCfg, k) && version || exports.currentVersion);
|
|
164
165
|
}
|
|
165
166
|
}
|
|
166
167
|
async function setConfig1(k, newV, saveChanges = true, valueVersion) {
|
package/src/cross.js
CHANGED
|
@@ -356,7 +356,7 @@ function randomId(len = 10) {
|
|
|
356
356
|
.replace(/l/g, 'L'); // avoid confusion reading l1
|
|
357
357
|
}
|
|
358
358
|
function objRenameKey(o, from, to) {
|
|
359
|
-
if (!o || !
|
|
359
|
+
if (!o || !Object.hasOwn(o, from) || from === to)
|
|
360
360
|
return;
|
|
361
361
|
o[to] = o[from];
|
|
362
362
|
delete o[from];
|
package/src/customHtml.js
CHANGED
|
@@ -11,7 +11,6 @@ exports.saveCustomHtml = saveCustomHtml;
|
|
|
11
11
|
const misc_1 = require("./misc");
|
|
12
12
|
const watchLoad_1 = require("./watchLoad");
|
|
13
13
|
const config_1 = require("./config");
|
|
14
|
-
const promises_1 = require("fs/promises");
|
|
15
14
|
const plugins_1 = require("./plugins");
|
|
16
15
|
const lodash_1 = __importDefault(require("lodash"));
|
|
17
16
|
const FILE = 'custom.html';
|
|
@@ -50,9 +49,5 @@ function getAllSections() {
|
|
|
50
49
|
}
|
|
51
50
|
async function saveCustomHtml(sections) {
|
|
52
51
|
const text = Object.entries(sections).filter(([k, v]) => v?.trim()).map(([k, v]) => `[${k}]\n${v}\n\n`).join('');
|
|
53
|
-
await
|
|
54
|
-
exports.customHtml.sections.clear();
|
|
55
|
-
for (const [k, v] of Object.entries(sections))
|
|
56
|
-
if (v)
|
|
57
|
-
exports.customHtml.sections.set(k, v);
|
|
52
|
+
await exports.customHtml.save(text, { reparse: true });
|
|
58
53
|
}
|
package/src/frontEndApis.js
CHANGED
|
@@ -80,6 +80,7 @@ exports.frontEndApis = {
|
|
|
80
80
|
return new apiMiddleware_1.ApiError(err);
|
|
81
81
|
try {
|
|
82
82
|
await (0, promises_1.mkdir)((0, path_1.join)(parentNode.source, name));
|
|
83
|
+
await (0, uploadOwners_1.setUploadOwner)((0, misc_1.join)(uri, (0, misc_1.pathEncode)(name)), ctx);
|
|
83
84
|
return {};
|
|
84
85
|
}
|
|
85
86
|
catch (e) {
|
|
@@ -219,7 +220,7 @@ async function requestedRename(node, newName, ctx, uri = ctx.path) {
|
|
|
219
220
|
else {
|
|
220
221
|
if (!node.source)
|
|
221
222
|
throw new apiMiddleware_1.ApiError(const_1.HTTP_FAILED_DEPENDENCY);
|
|
222
|
-
const destNode = await (0, vfs_1.urlToNode)((0, misc_1.pathEncode)(newName), ctx, node.parent);
|
|
223
|
+
const destNode = await (0, vfs_1.urlToNode)((0, misc_1.pathEncode)(newName), ctx, node.parent, { includeHidden: true });
|
|
223
224
|
if (destNode && (0, vfs_1.statusCodeForMissingPerm)(destNode, 'can_delete', ctx)) // if destination exists, you need delete permission
|
|
224
225
|
throw new apiMiddleware_1.ApiError(ctx.status);
|
|
225
226
|
try {
|
package/src/log.js
CHANGED
|
@@ -169,7 +169,7 @@ const logMw = async (ctx, next) => {
|
|
|
169
169
|
const date = `${a[2]}/${a[1]}/${a[3]}:${a[4]} ${a[5]?.slice(3)}`;
|
|
170
170
|
const user = (0, auth_1.getCurrentUsername)(ctx) || userAtStart;
|
|
171
171
|
const length = ctx.state.length ?? ctx.length;
|
|
172
|
-
const uri = ctx.
|
|
172
|
+
const uri = ctx.state.safeUrl;
|
|
173
173
|
const duration = (Number(reqEnd) - Number(reqStart)) / 1000;
|
|
174
174
|
ctx.logExtra(ctx.vfsNode && {
|
|
175
175
|
speed: Math.round(length / duration),
|
package/src/middlewares.js
CHANGED
|
@@ -92,6 +92,12 @@ function getProxyDetected() {
|
|
|
92
92
|
const prepareState = async (ctx, next) => {
|
|
93
93
|
// normalize once so auth, filters and logging agree on the same client address
|
|
94
94
|
ctx.request.ip = (0, connections_1.normalizeIp)(ctx.ip);
|
|
95
|
+
ctx.state.safeUrl = ctx.originalUrl;
|
|
96
|
+
if (ctx.query.login) {
|
|
97
|
+
const query = new URLSearchParams(ctx.querystring);
|
|
98
|
+
query.set('login', '...');
|
|
99
|
+
ctx.state.safeUrl = `${ctx.path}?${query}`;
|
|
100
|
+
}
|
|
95
101
|
const s = ctx.session;
|
|
96
102
|
if (s?.username) {
|
|
97
103
|
if (s.ts < auth_1.invalidateSessionBefore.get(s?.username))
|
package/src/multipartUpload.js
CHANGED
|
@@ -77,7 +77,7 @@ async function handleMultipartUpload(ctx, node) {
|
|
|
77
77
|
const prefix = (0, path_1.dirname)(fn.replaceAll('\\', '/'));
|
|
78
78
|
if (prefix === '.') // no subdir
|
|
79
79
|
return false;
|
|
80
|
-
const subfolderNode = await (0, vfs_1.urlToNode)(prefix + '/', ctx, node, true); // final slash = explicitly a folder even if it doesn't exist on disk
|
|
80
|
+
const subfolderNode = await (0, vfs_1.urlToNode)(prefix + '/', ctx, node, { allowMissing: true }); // final slash = explicitly a folder even if it doesn't exist on disk
|
|
81
81
|
return subfolderNode && !(0, vfs_1.hasPermission)(subfolderNode, 'can_upload', ctx);
|
|
82
82
|
}
|
|
83
83
|
}
|
package/src/perm.js
CHANGED
|
@@ -54,7 +54,8 @@ function getUsernames() {
|
|
|
54
54
|
function getAccount(username, normalize = true) {
|
|
55
55
|
if (normalize)
|
|
56
56
|
username = normalizeUsername(username);
|
|
57
|
-
|
|
57
|
+
const all = exports.accounts.get();
|
|
58
|
+
return username && Object.hasOwn(all, username) ? all[username] : undefined;
|
|
58
59
|
}
|
|
59
60
|
function saveSrpInfo(account, salt, verifier) {
|
|
60
61
|
account.srp = String(salt) + '|' + String(verifier);
|
|
@@ -79,10 +80,13 @@ async function updateAccount(account, change) {
|
|
|
79
80
|
await change?.(account);
|
|
80
81
|
else {
|
|
81
82
|
const u = normalizeUsername(change.username || '');
|
|
82
|
-
if (!u)
|
|
83
|
+
if (!u || isPrototypeKey(u))
|
|
83
84
|
delete change.username;
|
|
84
|
-
else
|
|
85
|
-
|
|
85
|
+
else {
|
|
86
|
+
if (u !== usernameWas && getAccount(u))
|
|
87
|
+
throw "username already exists";
|
|
88
|
+
change.username = u;
|
|
89
|
+
}
|
|
86
90
|
Object.assign(account, lodash_1.default.mapValues(change, x => x || undefined));
|
|
87
91
|
}
|
|
88
92
|
for (const [k, v] of (0, misc_1.typedEntries)(account))
|
|
@@ -98,7 +102,7 @@ async function updateAccount(account, change) {
|
|
|
98
102
|
if (account.belongs) {
|
|
99
103
|
account.belongs = (0, misc_1.wantArray)(account.belongs);
|
|
100
104
|
lodash_1.default.remove(account.belongs, b => {
|
|
101
|
-
if (exports.accounts.get()
|
|
105
|
+
if (Object.hasOwn(exports.accounts.get(), b))
|
|
102
106
|
return;
|
|
103
107
|
console.error(`Account ${username} belongs to non-existing ${b}`);
|
|
104
108
|
return true;
|
|
@@ -118,6 +122,11 @@ exports.accounts.sub(lodash_1.default.debounce(obj => {
|
|
|
118
122
|
// consider some validation here, in case of manual edit of the config
|
|
119
123
|
lodash_1.default.each(obj, (rec, k) => {
|
|
120
124
|
const norm = normalizeUsername(k);
|
|
125
|
+
if (isPrototypeKey(norm)) {
|
|
126
|
+
delete obj[k];
|
|
127
|
+
saveAccountsAsap();
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
121
130
|
if (rec?.username !== norm) {
|
|
122
131
|
if (!rec) // an empty object in yaml is parsed as null
|
|
123
132
|
rec = obj[norm] = { username: norm };
|
|
@@ -154,11 +163,14 @@ exports.accounts.sub(lodash_1.default.debounce(obj => {
|
|
|
154
163
|
function normalizeUsername(username) {
|
|
155
164
|
return username.toLocaleLowerCase();
|
|
156
165
|
}
|
|
166
|
+
function isPrototypeKey(username) {
|
|
167
|
+
return username === '__proto__' || username === 'constructor';
|
|
168
|
+
}
|
|
157
169
|
function renameAccount(from, to) {
|
|
158
170
|
from = normalizeUsername(from);
|
|
159
171
|
const as = exports.accounts.get();
|
|
160
172
|
to = normalizeUsername(to);
|
|
161
|
-
if (!to || !as
|
|
173
|
+
if (!to || isPrototypeKey(to) || !Object.hasOwn(as, from) || Object.hasOwn(as, to))
|
|
162
174
|
return false;
|
|
163
175
|
if (to === from)
|
|
164
176
|
return true;
|
|
@@ -177,7 +189,7 @@ function renameAccount(from, to) {
|
|
|
177
189
|
}
|
|
178
190
|
function addAccount(username, props, updateExisting = false) {
|
|
179
191
|
username = normalizeUsername(username);
|
|
180
|
-
if (!username)
|
|
192
|
+
if (!username || isPrototypeKey(username))
|
|
181
193
|
return;
|
|
182
194
|
let account = getAccount(username, false);
|
|
183
195
|
if (account && !updateExisting)
|
package/src/serveFile.js
CHANGED
|
@@ -7,6 +7,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
7
7
|
exports.forceDownload = forceDownload;
|
|
8
8
|
exports.disposition = disposition;
|
|
9
9
|
exports.serveFileNode = serveFileNode;
|
|
10
|
+
exports.enforceDownloadLimits = enforceDownloadLimits;
|
|
10
11
|
exports.serveFile = serveFile;
|
|
11
12
|
exports.monitorAsDownload = monitorAsDownload;
|
|
12
13
|
exports.applyRange = applyRange;
|
|
@@ -63,8 +64,11 @@ async function serveFileNode(ctx, node) {
|
|
|
63
64
|
// legacy clients often send Accept: */* for archive downloads, so the served mime is a safer signal than request headers here
|
|
64
65
|
: GUI_ASSET_MIME.test(mimeString || mime_types_1.default.lookup(source || '') || ''));
|
|
65
66
|
await serveFile(ctx, source || '', mimeString);
|
|
66
|
-
|
|
67
|
-
|
|
67
|
+
await enforceDownloadLimits(ctx);
|
|
68
|
+
}
|
|
69
|
+
async function enforceDownloadLimits(ctx) {
|
|
70
|
+
return await maxDownloadsPerAccount(ctx)
|
|
71
|
+
?? (await maxDownloads(ctx) || await maxDownloadsPerIp(ctx)); // a configured account limit overrides the global and IP limits
|
|
68
72
|
}
|
|
69
73
|
const mimeCfg = (0, config_1.defineConfig)(misc_1.CFG.mime, {}, obj => {
|
|
70
74
|
const matchers = Object.keys(obj).map(k => (0, misc_1.makeMatcher)(k));
|
|
@@ -71,7 +71,7 @@ const serveSharedFiles = async (ctx, next) => {
|
|
|
71
71
|
const decPath = (0, misc_1.safeDecodeURIComponent)(path, '');
|
|
72
72
|
const fn = (0, path_1.basename)(decPath);
|
|
73
73
|
const folderUri = (0, misc_1.pathEncode)((0, path_1.dirname)(decPath)); // re-encode to get readable urls
|
|
74
|
-
const folder = await (0, vfs_1.urlToNode)(folderUri, ctx, vfs_1.vfs.compiled(), true); // we don't require the folder to already exist, but to be mapped on disk AND to have proper permissions
|
|
74
|
+
const folder = await (0, vfs_1.urlToNode)(folderUri, ctx, vfs_1.vfs.compiled(), { allowMissing: true }); // we don't require the folder to already exist, but to be mapped on disk AND to have proper permissions
|
|
75
75
|
if (!folder)
|
|
76
76
|
return (0, errorPages_1.sendErrorPage)(ctx, cross_const_1.HTTP_NOT_FOUND);
|
|
77
77
|
ctx.state.uploadPath = decPath;
|
package/src/serveGuiFiles.js
CHANGED
|
@@ -22,10 +22,14 @@ const lang_1 = require("./lang");
|
|
|
22
22
|
const upload_1 = require("./upload");
|
|
23
23
|
const icons_1 = require("./icons");
|
|
24
24
|
const middlewares_1 = require("./middlewares");
|
|
25
|
+
(0, config_1.defineConfig)(misc_1.CFG.menu_at_top, misc_1.FRONTEND_OPTIONS[misc_1.CFG.menu_at_top]).sub((v, { version, set }) => {
|
|
26
|
+
if (!v && version?.olderThan('3.3.0-alpha1')) // preserve the layout used before this option existed for upgraded installations
|
|
27
|
+
set(true);
|
|
28
|
+
});
|
|
25
29
|
const size1024 = (0, config_1.defineConfig)(misc_1.CFG.size_1024, false, x => misc_1.formatBytes.k = x ? 1024 : 1000); // we both configure formatBytes, and also provide a compiled version (number instead of boolean)
|
|
26
30
|
const splitUploads = (0, config_1.defineConfig)(misc_1.CFG.split_uploads, 0);
|
|
27
31
|
exports.logGui = (0, config_1.defineConfig)(misc_1.CFG.log_gui, false);
|
|
28
|
-
lodash_1.default.each(misc_1.FRONTEND_OPTIONS, (v, k) => (0, config_1.defineConfig)(k, v)); // define default values
|
|
32
|
+
lodash_1.default.each(misc_1.FRONTEND_OPTIONS, (v, k) => k !== misc_1.CFG.menu_at_top && (0, config_1.defineConfig)(k, v)); // define default values
|
|
29
33
|
function serveStatic(uri) {
|
|
30
34
|
const folder = (const_1.DEV ? 'dist/' : '') + uri.slice(2, -1);
|
|
31
35
|
const root = (0, path_1.join)(__dirname, '..', folder);
|
package/src/uploadOwners.js
CHANGED
|
@@ -88,7 +88,7 @@ function getSessionId(ctx) {
|
|
|
88
88
|
return ctx.session.sessionId ||= (0, misc_1.randomId)(30);
|
|
89
89
|
}
|
|
90
90
|
function cleanVfsPath(path) {
|
|
91
|
-
return '/' + path.replace(/^\/+|\/+$/g, '');
|
|
91
|
+
return (0, misc_1.pathDecodeSegments)('/' + path.replace(/^\/+|\/+$/g, ''), misc_1.pathEncode);
|
|
92
92
|
}
|
|
93
93
|
function isSameOrInside(parent, path) {
|
|
94
94
|
return path === parent || path.startsWith(parent + '/');
|
package/src/vfs.js
CHANGED
|
@@ -108,8 +108,7 @@ async function applyParentToChild(child, parent, name) {
|
|
|
108
108
|
inheritFromParent(ret);
|
|
109
109
|
return ret;
|
|
110
110
|
}
|
|
111
|
-
async function urlToNode(url, ctx, parent = exports.vfs.compiled(),
|
|
112
|
-
) {
|
|
111
|
+
async function urlToNode(url, ctx, parent = exports.vfs.compiled(), options = {}) {
|
|
113
112
|
let initialSlashes = 0;
|
|
114
113
|
while (url[initialSlashes] === '/')
|
|
115
114
|
initialSlashes++;
|
|
@@ -122,16 +121,16 @@ async function urlToNode(url, ctx, parent = exports.vfs.compiled(), allowMissing
|
|
|
122
121
|
return;
|
|
123
122
|
const hasTrailingSlash = url.endsWith('/');
|
|
124
123
|
const rest = nextSlash < 0 ? '' : url.slice(nextSlash + 1, hasTrailingSlash ? -1 : undefined);
|
|
125
|
-
const assumeFolder = allowMissing && (rest > '' || hasTrailingSlash);
|
|
124
|
+
const assumeFolder = options.allowMissing && (rest > '' || hasTrailingSlash);
|
|
126
125
|
const ret = await getNodeByName(name, parent, assumeFolder);
|
|
127
126
|
if (!ret)
|
|
128
127
|
return;
|
|
129
128
|
setVfsPath(ret, name, parent);
|
|
130
129
|
if (rest || ret?.original)
|
|
131
|
-
return urlToNode(rest, ctx, ret,
|
|
130
|
+
return urlToNode(rest, ctx, ret, options);
|
|
132
131
|
if (ret.source)
|
|
133
|
-
if (!showHiddenFiles.get() && await isHiddenFile(ret.source)
|
|
134
|
-
|| !allowMissing && await setIsFolder(ret) === undefined) // undefined = not found on disk
|
|
132
|
+
if (!options.includeHidden && !showHiddenFiles.get() && await isHiddenFile(ret.source)
|
|
133
|
+
|| !options.allowMissing && await setIsFolder(ret) === undefined) // undefined = not found on disk
|
|
135
134
|
return;
|
|
136
135
|
return ret;
|
|
137
136
|
}
|
package/src/webdav.js
CHANGED
|
@@ -53,20 +53,22 @@ const WINDOWS_FILE_ATTRIBUTE_FLAGS = {
|
|
|
53
53
|
const canOverwrite = new Set();
|
|
54
54
|
const locks = new Map();
|
|
55
55
|
function releaseWebdavLock(path) {
|
|
56
|
-
const
|
|
56
|
+
const key = webdavPathKey(path);
|
|
57
|
+
const lock = locks.get(key);
|
|
57
58
|
if (!lock)
|
|
58
59
|
return false;
|
|
59
60
|
clearTimeout(lock.timeout);
|
|
60
|
-
locks.delete(
|
|
61
|
+
locks.delete(key);
|
|
61
62
|
return true;
|
|
62
63
|
}
|
|
63
64
|
async function isLocked(path, ctx) {
|
|
64
|
-
const
|
|
65
|
+
const key = webdavPathKey(path);
|
|
66
|
+
const lock = locks.get(key);
|
|
65
67
|
if (!lock)
|
|
66
68
|
return false;
|
|
67
69
|
// if the resource is gone, keeping the lock only creates fake 423 responses
|
|
68
|
-
if (!await (0, vfs_1.urlToNode)(
|
|
69
|
-
releaseWebdavLock(
|
|
70
|
+
if (!await (0, vfs_1.urlToNode)(key, ctx)) {
|
|
71
|
+
releaseWebdavLock(key);
|
|
70
72
|
return false;
|
|
71
73
|
}
|
|
72
74
|
const ifHeader = ctx.get('If');
|
|
@@ -81,6 +83,10 @@ function hasToken(header, token) {
|
|
|
81
83
|
return false;
|
|
82
84
|
return header.includes(`<${token}>`) || header.split(/[,;\s]+/).includes(token);
|
|
83
85
|
}
|
|
86
|
+
function webdavPathKey(path) {
|
|
87
|
+
const key = (0, cross_1.pathEncode)((0, cross_1.safeDecodeURIComponent)(path, ''));
|
|
88
|
+
return (0, misc_1.hasDirTraversal)(key) ? '' : key;
|
|
89
|
+
}
|
|
84
90
|
function getWebdavUsername(ctx) {
|
|
85
91
|
return (0, auth_1.getCurrentUsername)(ctx) || '';
|
|
86
92
|
}
|
|
@@ -107,6 +113,9 @@ const webdav = async (ctx, next) => {
|
|
|
107
113
|
webdavDetectedAgents.try(webdavAgentKey(ctx, ua), () => true);
|
|
108
114
|
if (isCorsPreflight)
|
|
109
115
|
return next();
|
|
116
|
+
const pathKey = webdavPathKey(path); // state must converge for equivalent encodings without changing client-visible paths
|
|
117
|
+
if (!pathKey && (isWebdavAuthRequest || ctx.method === 'PUT' || ctx.method === 'DELETE'))
|
|
118
|
+
return ctx.status = cross_1.HTTP_BAD_REQUEST;
|
|
110
119
|
if (isWebdavAuthRequest && shouldChallengeWebdav())
|
|
111
120
|
return;
|
|
112
121
|
if (ctx.method === 'OPTIONS')
|
|
@@ -143,7 +152,7 @@ const webdav = async (ctx, next) => {
|
|
|
143
152
|
async function handlePut() {
|
|
144
153
|
if (await isLocked(path, ctx))
|
|
145
154
|
return;
|
|
146
|
-
const overwriteGraceKey =
|
|
155
|
+
const overwriteGraceKey = pathKey + (0, cross_1.prefix)('|', (0, auth_1.getCurrentUsername)(ctx)); // bind temporary overwrite grace to the authenticated user so accounts cannot reuse each other's grace window
|
|
147
156
|
// Finder first creates an empty file (a test?) then wants to overwrite it, which requires deletion permission, but the user may not have it, causing a renamed upload. To solve, so we give it special permission for a few seconds.
|
|
148
157
|
const x = ctx.get('x-expected-entity-length'); // field used by Finder's webdav on actual upload, after
|
|
149
158
|
if (isKnownWebdavAgent && canOverwrite.has(overwriteGraceKey)) {
|
|
@@ -160,7 +169,7 @@ const webdav = async (ctx, next) => {
|
|
|
160
169
|
if (isKnownWebdavAgent)
|
|
161
170
|
ctx.query.existing ??= 'overwrite'; // with webdav this is our default
|
|
162
171
|
await next();
|
|
163
|
-
if (isKnownWebdavAgent && ctx.body?.uri ===
|
|
172
|
+
if (isKnownWebdavAgent && ctx.body?.uri && webdavPathKey(ctx.body.uri) === pathKey) // the upload middleware reports the final uri that can be different from the initial request
|
|
164
173
|
allowWebdavOverwrite(overwriteGraceKey);
|
|
165
174
|
}
|
|
166
175
|
async function handleMkcol() {
|
|
@@ -195,27 +204,33 @@ const webdav = async (ctx, next) => {
|
|
|
195
204
|
setWebdavHeaders();
|
|
196
205
|
if (await isLocked(path, ctx))
|
|
197
206
|
return;
|
|
198
|
-
const node = await (0, vfs_1.urlToNode)(
|
|
207
|
+
const node = await (0, vfs_1.urlToNode)(pathKey, ctx);
|
|
199
208
|
if (!node)
|
|
200
209
|
return next();
|
|
201
210
|
let dest = ctx.get('destination');
|
|
202
211
|
const i = dest.indexOf('//');
|
|
203
212
|
if (i >= 0)
|
|
204
213
|
dest = dest.slice(dest.indexOf('/', i + 2));
|
|
205
|
-
dest = (0, cross_1.join)(ctx.state.root || '', dest); // on Windows, we must use / as the delimiter to
|
|
214
|
+
dest = webdavPathKey((0, cross_1.join)(ctx.state.root || '', dest)); // on Windows, we must use / as the delimiter to compare URL paths
|
|
215
|
+
if (!dest)
|
|
216
|
+
return ctx.status = cross_1.HTTP_BAD_REQUEST;
|
|
206
217
|
if (await isLocked(dest, ctx))
|
|
207
218
|
return;
|
|
208
|
-
if ((0, path_1.dirname)(
|
|
219
|
+
if ((0, path_1.dirname)(pathKey) === (0, path_1.dirname)(dest))
|
|
209
220
|
try {
|
|
210
221
|
// decode the single path segment so reserved chars like %2C become their real name on rename
|
|
211
|
-
await (0, frontEndApis_1.requestedRename)(node, (0, cross_1.safeDecodeURIComponent)((0, path_1.basename)(dest), ''), ctx,
|
|
222
|
+
await (0, frontEndApis_1.requestedRename)(node, (0, cross_1.safeDecodeURIComponent)((0, path_1.basename)(dest), ''), ctx, pathKey);
|
|
212
223
|
releaseWebdavLock(path); // RFC 4918 says MOVE must not carry locks to destination, so clear source lock on success
|
|
213
224
|
return ctx.status = cross_1.HTTP_CREATED;
|
|
214
225
|
}
|
|
215
226
|
catch (e) {
|
|
216
227
|
return ctx.status = e.status || cross_1.HTTP_SERVER_ERROR;
|
|
217
228
|
}
|
|
218
|
-
const
|
|
229
|
+
const actualDest = (0, cross_1.join)((0, path_1.dirname)(dest), (0, path_1.basename)(pathKey));
|
|
230
|
+
// moveFiles keeps the source basename for cross-directory moves, so check the lock it will actually touch
|
|
231
|
+
if (actualDest !== dest && await isLocked(actualDest, ctx))
|
|
232
|
+
return;
|
|
233
|
+
const moveRes = await (0, frontEndApis_1.moveFiles)([pathKey], (0, path_1.dirname)(dest), ctx);
|
|
219
234
|
if (moveRes instanceof Error)
|
|
220
235
|
return ctx.status = moveRes.status || cross_1.HTTP_SERVER_ERROR;
|
|
221
236
|
const err = moveRes?.errors?.[0];
|
|
@@ -234,7 +249,7 @@ const webdav = async (ctx, next) => {
|
|
|
234
249
|
async function handleUnlock() {
|
|
235
250
|
setWebdavHeaders();
|
|
236
251
|
const x = ctx.get(TOKEN_HEADER).slice(1, -1);
|
|
237
|
-
const lock = locks.get(
|
|
252
|
+
const lock = locks.get(pathKey);
|
|
238
253
|
if (x !== lock?.token)
|
|
239
254
|
return ctx.status = cross_1.HTTP_BAD_REQUEST;
|
|
240
255
|
// with force_webdav_login disabled a client may silently fall back to anonymous; keep lock ownership on the original username
|
|
@@ -253,7 +268,7 @@ const webdav = async (ctx, next) => {
|
|
|
253
268
|
const permissionNode = node || await (0, vfs_1.urlToNode)((0, path_1.dirname)(path), ctx);
|
|
254
269
|
if (!permissionNode)
|
|
255
270
|
return ctx.status = cross_1.HTTP_CONFLICT;
|
|
256
|
-
const missingWritePerm = node && canOverwrite.has(
|
|
271
|
+
const missingWritePerm = node && canOverwrite.has(pathKey + (0, cross_1.prefix)('|', (0, auth_1.getCurrentUsername)(ctx))) ? 0
|
|
257
272
|
: (0, vfs_1.statusCodeForMissingPerm)(permissionNode, node ? 'can_delete' : 'can_upload', ctx);
|
|
258
273
|
if (missingWritePerm) {
|
|
259
274
|
if (ctx.status === cross_1.HTTP_UNAUTHORIZED)
|
|
@@ -268,7 +283,7 @@ const webdav = async (ctx, next) => {
|
|
|
268
283
|
// Finder and similar clients refresh an existing lock by sending LOCK without a body
|
|
269
284
|
if (!token)
|
|
270
285
|
return ctx.status = cross_1.HTTP_BAD_REQUEST;
|
|
271
|
-
const lock = locks.get(
|
|
286
|
+
const lock = locks.get(pathKey);
|
|
272
287
|
if (token !== lock?.token)
|
|
273
288
|
return ctx.status = cross_1.HTTP_PRECONDITION_FAILED;
|
|
274
289
|
// same-token refresh from another username would make abandoned locks effectively persistent
|
|
@@ -278,7 +293,7 @@ const webdav = async (ctx, next) => {
|
|
|
278
293
|
clearTimeout(lock.timeout);
|
|
279
294
|
lock.timeout = setTimeout(() => releaseWebdavLock(path), seconds * 1000);
|
|
280
295
|
lock.seconds = seconds;
|
|
281
|
-
locks.set(
|
|
296
|
+
locks.set(pathKey, lock);
|
|
282
297
|
ctx.set(TOKEN_HEADER, lock.token);
|
|
283
298
|
ctx.body = renderLockResponse(lock.token, lock.seconds);
|
|
284
299
|
return;
|
|
@@ -292,11 +307,11 @@ const webdav = async (ctx, next) => {
|
|
|
292
307
|
return ctx.status = cross_1.HTTP_CONFLICT;
|
|
293
308
|
if (scope !== 'exclusive' || type !== 'write')
|
|
294
309
|
return ctx.status = cross_1.HTTP_CONFLICT;
|
|
295
|
-
if (locks.has(
|
|
310
|
+
if (locks.has(pathKey))
|
|
296
311
|
return ctx.status = cross_1.HTTP_LOCKED;
|
|
297
312
|
const newToken = 'urn:uuid:' + (0, node_crypto_1.randomUUID)();
|
|
298
313
|
const timeout = setTimeout(() => releaseWebdavLock(path), seconds * 1000);
|
|
299
|
-
locks.set(
|
|
314
|
+
locks.set(pathKey, { token: newToken, timeout, seconds, username: getWebdavUsername(ctx) });
|
|
300
315
|
ctx.set(TOKEN_HEADER, newToken);
|
|
301
316
|
ctx.body = renderLockResponse(newToken, seconds);
|
|
302
317
|
}
|
|
@@ -365,7 +380,7 @@ const webdav = async (ctx, next) => {
|
|
|
365
380
|
return ctx.status = cross_1.HTTP_BAD_REQUEST;
|
|
366
381
|
const statuses = [];
|
|
367
382
|
for (const prop of props)
|
|
368
|
-
statuses.push({ prop: prop.name, status: await applyProppatchProp(prop, node,
|
|
383
|
+
statuses.push({ prop: prop.name, status: await applyProppatchProp(prop, node, pathKey, ctx) });
|
|
369
384
|
const outPath = webdavHrefPath(path, node, ctx);
|
|
370
385
|
ctx.type = 'xml';
|
|
371
386
|
ctx.status = 207;
|
package/src/zip.js
CHANGED
|
@@ -82,6 +82,9 @@ async function zipStreamFromFolder(node, ctx) {
|
|
|
82
82
|
catch { }
|
|
83
83
|
});
|
|
84
84
|
const zip = new QuickZipStream_1.QuickZipStream(mappedWalker);
|
|
85
|
+
ctx.body = zip;
|
|
86
|
+
if (await (0, serveFile_1.enforceDownloadLimits)(ctx))
|
|
87
|
+
return;
|
|
85
88
|
const time = 1000 * zipSeconds.get();
|
|
86
89
|
const size = await zip.calculateSize(time);
|
|
87
90
|
const range = (0, serveFile_1.applyRange)(ctx, size); // keep var size as ctx.response.length won't preserve a NaN
|
|
@@ -89,7 +92,6 @@ async function zipStreamFromFolder(node, ctx) {
|
|
|
89
92
|
return;
|
|
90
93
|
if (range)
|
|
91
94
|
zip.applyRange(range.start, range.end);
|
|
92
|
-
ctx.body = zip;
|
|
93
95
|
ctx.req.on('close', () => zip.destroy());
|
|
94
96
|
ctx.state.archive = 'zip';
|
|
95
97
|
(0, serveFile_1.monitorAsDownload)(ctx, size, range?.start);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{Xi as e,ga as t}from"./index-Dsq-sVu9.js";var n=t(),r=e((0,n.jsx)(`path`,{d:`M10 6 8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z`}),`ChevronRight`),i=e((0,n.jsx)(`path`,{d:`M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6zM19 4h-3.5l-1-1h-5l-1 1H5v2h14z`}),`Delete`),a=e((0,n.jsx)(`path`,{d:`M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2m0 18c-4.42 0-8-3.58-8-8 0-1.85.63-3.55 1.69-4.9L16.9 18.31C15.55 19.37 13.85 20 12 20m6.31-3.1L7.1 5.69C8.45 4.63 10.15 4 12 4c4.42 0 8 3.58 8 8 0 1.85-.63 3.55-1.69 4.9`}),`DoNotDisturb`),o=e((0,n.jsx)(`path`,{d:`M16.59 8.59 12 13.17 7.41 8.59 6 10l6 6 6-6z`}),`ExpandMore`),s=e((0,n.jsx)(`path`,{d:`M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5s-3 1.34-3 3 1.34 3 3 3m-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5 5 6.34 5 8s1.34 3 3 3m0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5m8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5`}),`Group`),c=e((0,n.jsx)(`path`,{d:`M17 10.43V2H7v8.43c0 .35.18.68.49.86l4.18 2.51-.99 2.34-3.41.29 2.59 2.24L9.07 22 12 20.23 14.93 22l-.78-3.33 2.59-2.24-3.41-.29-.99-2.34 4.18-2.51c.3-.18.48-.5.48-.86m-4 1.8-1 .6-1-.6V3h2z`}),`MilitaryTech`),l=e((0,n.jsx)(`path`,{d:`M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4m0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4`}),`Person`),u=e((0,n.jsx)(`path`,{d:`M15 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4m-9-2V7H4v3H1v2h3v3h2v-3h3v-2zm9 4c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4`}),`PersonAdd`),d=e([(0,n.jsx)(`path`,{d:`M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2M12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8`},`0`),(0,n.jsx)(`path`,{d:`M12.5 7H11v6l5.25 3.15.75-1.23-4.5-2.67z`},`1`)],`Schedule`),f=e([(0,n.jsx)(`path`,{d:`M15 2h-3.5l-1-1h-5l-1 1H1v2h14zm1 7c-.7 0-1.37.1-2 .29V5H2v12c0 1.1.9 2 2 2h5.68c1.12 2.36 3.53 4 6.32 4 3.87 0 7-3.13 7-7s-3.13-7-7-7m0 12c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5`},`0`),(0,n.jsx)(`path`,{d:`M16.5 12H15v5l3.6 2.1.8-1.2-2.9-1.7z`},`1`)],`AutoDelete`),p=e((0,n.jsx)(`path`,{d:`M5 20h14v-2H5zm0-10h4v6h6v-6h4l-7-7z`}),`Upload`),m=e((0,n.jsx)(`path`,{d:`M3 17.25V21h3.75L17.81 9.94l-3.75-3.75zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34a.996.996 0 0 0-1.41 0l-1.83 1.83 3.75 3.75z`}),`Edit`),h=e((0,n.jsx)(`path`,{d:`M5 20h14v-2H5zM19 9h-4V3H9v6H5l7 7z`}),`Download`),g=e((0,n.jsx)(`path`,{d:`M20 13H4c-.55 0-1 .45-1 1v6c0 .55.45 1 1 1h16c.55 0 1-.45 1-1v-6c0-.55-.45-1-1-1M7 19c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2M20 3H4c-.55 0-1 .45-1 1v6c0 .55.45 1 1 1h16c.55 0 1-.45 1-1V4c0-.55-.45-1-1-1M7 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2`}),`Dns`),_=e([(0,n.jsx)(`path`,{d:`M17 11h2v2h-2v2h2v2h-2v2h4V5h-9v1.4l5 3.57zm0-4h2v2h-2z`,opacity:`.3`},`0`),(0,n.jsx)(`path`,{d:`M10 3v1.97l.96.69L12 6.4V5h9v14h-4v2h6V3z`},`1`),(0,n.jsx)(`path`,{d:`M3 12v7h2v-5h6v5h2v-7L8 8.5z`,opacity:`.3`},`2`),(0,n.jsx)(`path`,{d:`M17 7h2v2h-2zm0 4h2v2h-2zm0 4h2v2h-2zM1 11v10h6v-5h2v5h6V11L8 6zm12 8h-2v-5H5v5H3v-7l5-3.5 5 3.5z`},`3`)],`HomeWorkTwoTone`),v=e((0,n.jsx)(`path`,{d:`M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2m-6 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2m3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1s3.1 1.39 3.1 3.1z`}),`Lock`),y=e([(0,n.jsx)(`path`,{d:`M14.99 4.59V5c0 1.1-.9 2-2 2h-2v2c0 .55-.45 1-1 1h-2v2h6c.55 0 1 .45 1 1v3h1c.89 0 1.64.59 1.9 1.4C19.19 15.98 20 14.08 20 12c0-3.35-2.08-6.23-5.01-7.41M8.99 16v-1l-4.78-4.78C4.08 10.79 4 11.39 4 12c0 4.07 3.06 7.43 6.99 7.93V18c-1.1 0-2-.9-2-2`,opacity:`.3`},`0`),(0,n.jsx)(`path`,{d:`M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2m-1.01 17.93C7.06 19.43 4 16.07 4 12c0-.61.08-1.21.21-1.78L8.99 15v1c0 1.1.9 2 2 2zm6.9-2.53c-.26-.81-1-1.4-1.9-1.4h-1v-3c0-.55-.45-1-1-1h-6v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41C17.92 5.77 20 8.65 20 12c0 2.08-.81 3.98-2.11 5.4`},`1`)],`PublicTwoTone`),b=e([(0,n.jsx)(`path`,{d:`M15 15H5v4h14v-4zm-7 3H6v-2h2zm3.5 0h-2v-2h2zm3.5 0h-2v-2h2z`,opacity:`.3`},`0`),(0,n.jsx)(`path`,{d:`M16 4.2c1.5 0 3 .6 4.2 1.7l.8-.8C19.6 3.7 17.8 3 16 3s-3.6.7-5 2.1l.8.8C13 4.8 14.5 4.2 16 4.2m-3.3 2.5.8.8c.7-.7 1.6-1 2.5-1s1.8.3 2.5 1l.8-.8c-.9-.9-2.1-1.4-3.3-1.4s-2.4.5-3.3 1.4M19 13h-2V9h-2v4H5c-1.1 0-2 .9-2 2v4c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2v-4c0-1.1-.9-2-2-2m0 6H5v-4h14zM6 16h2v2H6zm3.5 0h2v2h-2zm3.5 0h2v2h-2z`},`1`)],`RouterTwoTone`),x=e((0,n.jsx)(`path`,{d:`M2.01 21 23 12 2.01 3 2 10l15 2-15 2z`}),`Send`),S=e((0,n.jsx)(`path`,{d:`M2 20h20v-4H2zm2-3h2v2H4zM2 4v4h20V4zm4 3H4V5h2zm-4 7h20v-4H2zm2-3h2v2H4z`}),`Storage`),C=e((0,n.jsx)(`path`,{d:`M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14`}),`Search`),w=e((0,n.jsx)(`path`,{d:`M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6z`}),`Add`),T=e((0,n.jsx)(`path`,{d:`m4 12 1.41 1.41L11 7.83V20h2V7.83l5.58 5.59L20 12l-8-8z`}),`ArrowUpward`),E=e((0,n.jsx)(`path`,{d:`m20 12-1.41-1.41L13 16.17V4h-2v12.17l-5.58-5.59L4 12l8 8z`}),`ArrowDownward`),D=e((0,n.jsx)(`path`,{d:`M12.5 8c-2.65 0-5.05.99-6.9 2.6L2 7v9h9l-3.62-3.62c1.39-1.16 3.16-1.88 5.12-1.88 3.54 0 6.55 2.31 7.6 5.5l2.37-.78C21.08 11.03 17.15 8 12.5 8`}),`Undo`),O=e((0,n.jsx)(`path`,{d:`M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39c.51-.66.04-1.61-.79-1.61H5.04c-.83 0-1.3.95-.79 1.61`}),`FilterAlt`),k=e((0,n.jsx)(`path`,{d:`M17 7h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1 0 1.43-.98 2.63-2.31 2.98l1.46 1.46C20.88 15.61 22 13.95 22 12c0-2.76-2.24-5-5-5m-1 4h-2.19l2 2H16zM2 4.27l3.11 3.11C3.29 8.12 2 9.91 2 12c0 2.76 2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1 0-1.59 1.21-2.9 2.76-3.07L8.73 11H8v2h2.73L13 15.27V17h1.73l4.01 4L20 19.74 3.27 3z`}),`LinkOff`),A=e((0,n.jsx)(`path`,{d:`M5 13h14v-2H5zm-2 4h14v-2H3zM7 7v2h14V7z`}),`ClearAll`),ee=e((0,n.jsx)(`path`,{d:`M20 9V7c0-1.1-.9-2-2-2h-3c0-1.66-1.34-3-3-3S9 3.34 9 5H6c-1.1 0-2 .9-2 2v2c-1.66 0-3 1.34-3 3s1.34 3 3 3v4c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2v-4c1.66 0 3-1.34 3-3s-1.34-3-3-3M7.5 11.5c0-.83.67-1.5 1.5-1.5s1.5.67 1.5 1.5S9.83 13 9 13s-1.5-.67-1.5-1.5M16 17H8v-2h8zm-1-4c-.83 0-1.5-.67-1.5-1.5S14.17 10 15 10s1.5.67 1.5 1.5S15.83 13 15 13`}),`SmartToy`),j=e((0,n.jsx)(`path`,{d:`M20 4H4c-1.11 0-2 .9-2 2v12c0 1.1.89 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.89-2-2-2m0 14H4V8h16zm-2-1h-6v-2h6zM7.5 17l-1.41-1.41L8.67 13l-2.59-2.59L7.5 9l4 4z`}),`Terminal`),M=e((0,n.jsx)(`path`,{d:`M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2m0 16H8V7h11z`}),`ContentCopy`),N=e((0,n.jsx)(`path`,{d:`M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2M4 12c0-4.42 3.58-8 8-8 1.85 0 3.55.63 4.9 1.69L5.69 16.9C4.63 15.55 4 13.85 4 12m8 8c-1.85 0-3.55-.63-4.9-1.69L18.31 7.1C19.37 8.45 20 10.15 20 12c0 4.42-3.58 8-8 8`}),`Block`),P=e((0,n.jsx)(`path`,{d:`M20 6h-8l-2-2H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2m-2 6h-2v2h2v2h-2v2h-2v-2h2v-2h-2v-2h2v-2h-2V8h2v2h2z`}),`FolderZip`),F=e((0,n.jsx)(`path`,{d:`M15.41 7.41 14 6l-6 6 6 6 1.41-1.41L10.83 12z`}),`ChevronLeft`),I=e((0,n.jsx)(`path`,{d:`M3 10h11v2H3zm0-2h11V6H3zm0 8h7v-2H3zm15.01-3.13.71-.71c.39-.39 1.02-.39 1.41 0l.71.71c.39.39.39 1.02 0 1.41l-.71.71zm-.71.71-5.3 5.3V21h2.12l5.3-5.3z`}),`EditNote`),L=e((0,n.jsx)(`path`,{d:`M5 17h14v2H5zm7-12L5.33 15h13.34z`}),`Eject`),R=e((0,n.jsx)(`path`,{d:`M20 6h-8l-2-2H4c-1.11 0-1.99.89-1.99 2L2 18c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-1.11-.89-2-2-2m-1 8h-3v3h-2v-3h-3v-2h3V9h2v3h3z`}),`CreateNewFolder`),z=e((0,n.jsx)(`path`,{d:`M8 11h3v10h2V11h3l-4-4zM4 3v2h16V3z`}),`VerticalAlignTop`),B=e([(0,n.jsx)(`path`,{d:`M2 16.5C2 19.54 4.46 22 7.5 22s5.5-2.46 5.5-5.5V10H2zm5.5 2C6.12 18.5 5 17.83 5 17h5c0 .83-1.12 1.5-2.5 1.5M10 13c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1m-5 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1`},`0`),(0,n.jsx)(`path`,{d:`M11 3v6h3v2.5c0-.83 1.12-1.5 2.5-1.5s2.5.67 2.5 1.5h-5v2.89c.75.38 1.6.61 2.5.61 3.04 0 5.5-2.46 5.5-5.5V3zm3 5.08c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1c0 .56-.45 1-1 1m5 0c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1c0 .56-.45 1-1 1`},`1`)],`TheaterComedy`),V=e((0,n.jsx)(`path`,{d:`M10 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8z`}),`Folder`),H=e((0,n.jsx)(`path`,{d:`M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1M8 13h8v-2H8zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5`}),`Link`),U=e((0,n.jsx)(`path`,{d:`M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8zM6 20V4h7v5h5v11z`}),`InsertDriveFileOutlined`),W=e((0,n.jsx)(`path`,{d:`M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5M12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5m0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3`}),`RemoveRedEye`),G=e((0,n.jsx)(`path`,{d:`M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2m-5 14H4v-4h11zm0-5H4V9h11zm5 5h-4V9h4z`}),`Web`),K=e((0,n.jsx)(`path`,{d:`M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96`}),`Cloud`),q=e((0,n.jsx)(`path`,{d:`M14.59 8 12 10.59 9.41 8 8 9.41 10.59 12 8 14.59 9.41 16 12 13.41 14.59 16 16 14.59 13.41 12 16 9.41zM12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2m0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8`}),`HighlightOff`),J=e((0,n.jsx)(`path`,{d:`M12 5.83 15.17 9l1.41-1.41L12 3 7.41 7.59 8.83 9zm0 12.34L8.83 15l-1.41 1.41L12 21l4.59-4.59L15.17 15z`}),`UnfoldMore`),Y=e((0,n.jsx)(`path`,{d:`M7.41 18.59 8.83 20 12 16.83 15.17 20l1.41-1.41L12 14zm9.18-13.18L15.17 4 12 7.17 8.83 4 7.41 5.41 12 10z`}),`UnfoldLess`),X=e((0,n.jsx)(`path`,{d:`M9.64 7.64c.23-.5.36-1.05.36-1.64 0-2.21-1.79-4-4-4S2 3.79 2 6s1.79 4 4 4c.59 0 1.14-.13 1.64-.36L10 12l-2.36 2.36C7.14 14.13 6.59 14 6 14c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4c0-.59-.13-1.14-.36-1.64L12 14l7 7h3v-1zM6 8c-1.1 0-2-.89-2-2s.9-2 2-2 2 .89 2 2-.9 2-2 2m0 12c-1.1 0-2-.89-2-2s.9-2 2-2 2 .89 2 2-.9 2-2 2m6-7.5c-.28 0-.5-.22-.5-.5s.22-.5.5-.5.5.22.5.5-.22.5-.5.5M19 3l-6 6 2 2 7-7V3z`}),`ContentCut`),Z=e((0,n.jsx)(`path`,{d:`M19 2h-4.18C14.4.84 13.3 0 12 0S9.6.84 9.18 2H5c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2m-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1m7 18H5V4h2v3h10V4h2z`}),`ContentPaste`),Q=e((0,n.jsx)(`path`,{d:`M15 21h-2v-2h2zm-2-7h-2v5h2zm8-2h-2v4h2zm-2-2h-2v2h2zM7 12H5v2h2zm-2-2H3v2h2zm7-5h2V3h-2zm-7.5-.5v3h3v-3zM9 9H3V3h6zm-4.5 7.5v3h3v-3zM9 21H3v-6h6zm7.5-16.5v3h3v-3zM21 9h-6V3h6zm-2 10v-3h-4v2h2v3h4v-2zm-2-7h-4v2h4zm-4-2H7v2h2v2h2v-2h2zm1-1V7h-2V5h-2v4zM6.75 5.25h-1.5v1.5h1.5zm0 12h-1.5v1.5h1.5zm12-12h-1.5v1.5h1.5z`}),`QrCode2`),$=e((0,n.jsx)(`path`,{d:`M18 4V3c0-.55-.45-1-1-1H5c-.55 0-1 .45-1 1v4c0 .55.45 1 1 1h12c.55 0 1-.45 1-1V6h1v4H9v11c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-9h8V4z`}),`FormatPaint`),te=e((0,n.jsx)(`path`,{d:`M19 5v14H5V5zm1.1-2H3.9c-.5 0-.9.4-.9.9v16.2c0 .4.4.9.9.9h16.2c.4 0 .9-.5.9-.9V3.9c0-.5-.5-.9-.9-.9M11 7h6v2h-6zm0 4h6v2h-6zm0 4h6v2h-6zM7 7h2v2H7zm0 4h2v2H7zm0 4h2v2H7z`}),`ListAlt`),ne=e((0,n.jsx)(`path`,{d:`M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2m4 14H8V8h8z`}),`StopCircle`),re=e((0,n.jsx)(`path`,{d:`M16 18v2H8v-2zM11 7.99V16h2V7.99h3L12 4 8 7.99z`}),`Upgrade`),ie=e((0,n.jsx)(`path`,{d:`M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z`}),`Clear`),ae=e((0,n.jsx)(`path`,{d:`M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20z`}),`ArrowBack`),oe=e((0,n.jsx)(`path`,{d:`m12 4-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z`}),`ArrowForward`);export{c as $,ee as A,x as B,L as C,N as D,P as E,E as F,g as G,y as H,T as I,p as J,h as K,w as L,k as M,O as N,M as O,D as P,l as Q,C as R,R as S,F as T,v as U,b as V,_ as W,d as X,f as Y,u as Z,U as _,ne as a,B as b,Q as c,Y as d,s as et,J as f,W as g,G as h,re as i,r as it,A as j,j as k,Z as l,K as m,ae as n,a as nt,te as o,q as p,m as q,ie as r,i as rt,$ as s,oe as t,o as tt,X as u,H as v,I as w,z as x,V as y,S as z};
|