hfs 0.52.0 → 0.52.2
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/{index-rGlrl8rO.js → index-SdT-xAgy.js} +162 -161
- package/admin/assets/index-sCDewjON.css +1 -0
- package/admin/assets/{sha512-fCExUX1S.js → sha512-wLBxKmAg.js} +1 -1
- package/admin/index.html +2 -2
- package/frontend/assets/{index-UuOYZhm8.css → index-_JmRmWgy.css} +1 -1
- package/frontend/assets/index-f_a4EAov.js +101 -0
- package/frontend/assets/{sha512-Ts3TzEDU.js → sha512-eHY6kymX.js} +1 -1
- package/frontend/index.html +2 -2
- package/package.json +1 -1
- package/src/api.accounts.js +7 -1
- package/src/apiMiddleware.js +1 -1
- package/src/consoleLog.js +2 -0
- package/src/const.js +1 -1
- package/src/frontEndApis.js +5 -0
- package/src/langs/hfs-lang-fr.json +35 -3
- package/src/langs/hfs-lang-ko.json +70 -14
- package/src/langs/hfs-lang-zh-tw.json +63 -10
- package/src/log.js +2 -4
- package/src/perm.js +1 -0
- package/src/roots.js +1 -1
- package/admin/assets/index-4CQRk-yB.css +0 -1
- package/frontend/assets/index-VGPvrfXn.js +0 -101
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{g as OF,c as UF}from"./index-
|
|
1
|
+
import{g as OF,c as UF}from"./index-f_a4EAov.js";function gF(sF,hF){for(var eF=0;eF<hF.length;eF++){const tF=hF[eF];if(typeof tF!="string"&&!Array.isArray(tF)){for(const w in tF)if(w!=="default"&&!(w in sF)){const lF=Object.getOwnPropertyDescriptor(tF,w);lF&&Object.defineProperty(sF,w,lF.get?lF:{enumerable:!0,get:()=>tF[w]})}}}return Object.freeze(Object.defineProperty(sF,Symbol.toStringTag,{value:"Module"}))}var dF={exports:{}};/*
|
|
2
2
|
* [js-sha512]{@link https://github.com/emn178/js-sha512}
|
|
3
3
|
*
|
|
4
4
|
* @version 0.8.0
|
package/frontend/index.html
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="utf-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=0" />
|
|
6
6
|
<link href="/fontello.css" rel="stylesheet" />
|
|
7
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
7
|
+
<script type="module" crossorigin src="/assets/index-f_a4EAov.js"></script>
|
|
8
|
+
<link rel="stylesheet" crossorigin href="/assets/index-_JmRmWgy.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
11
11
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
package/package.json
CHANGED
package/src/api.accounts.js
CHANGED
|
@@ -9,6 +9,7 @@ const perm_1 = require("./perm");
|
|
|
9
9
|
const lodash_1 = __importDefault(require("lodash"));
|
|
10
10
|
const const_1 = require("./const");
|
|
11
11
|
const auth_1 = require("./auth");
|
|
12
|
+
const misc_1 = require("./misc");
|
|
12
13
|
function prepareAccount(ac) {
|
|
13
14
|
return ac && {
|
|
14
15
|
...lodash_1.default.omit(ac, ['password', 'hashed_password', 'srp']),
|
|
@@ -34,6 +35,7 @@ exports.default = {
|
|
|
34
35
|
},
|
|
35
36
|
async set_account({ username, changes }, ctx) {
|
|
36
37
|
var _a;
|
|
38
|
+
(0, misc_1.apiAssertTypes)({ string: { username } });
|
|
37
39
|
const acc = (0, perm_1.getAccount)(username);
|
|
38
40
|
if (!acc)
|
|
39
41
|
return new apiMiddleware_1.ApiError(const_1.HTTP_BAD_REQUEST);
|
|
@@ -43,9 +45,10 @@ exports.default = {
|
|
|
43
45
|
return lodash_1.default.pick(acc, 'username');
|
|
44
46
|
},
|
|
45
47
|
async add_account({ overwrite, username, ...rest }) {
|
|
48
|
+
(0, misc_1.apiAssertTypes)({ string: { username } });
|
|
46
49
|
const existing = (0, perm_1.getAccount)(username);
|
|
47
50
|
if (existing) {
|
|
48
|
-
if (overwrite)
|
|
51
|
+
if (!overwrite)
|
|
49
52
|
return new apiMiddleware_1.ApiError(const_1.HTTP_CONFLICT);
|
|
50
53
|
await (0, perm_1.updateAccount)(existing, rest);
|
|
51
54
|
return lodash_1.default.pick(existing, 'username');
|
|
@@ -54,13 +57,16 @@ exports.default = {
|
|
|
54
57
|
return acc ? lodash_1.default.pick(acc, 'username') : new apiMiddleware_1.ApiError(const_1.HTTP_BAD_REQUEST);
|
|
55
58
|
},
|
|
56
59
|
del_account({ username }) {
|
|
60
|
+
(0, misc_1.apiAssertTypes)({ string: { username } });
|
|
57
61
|
return (0, perm_1.delAccount)(username) ? {} : new apiMiddleware_1.ApiError(const_1.HTTP_BAD_REQUEST);
|
|
58
62
|
},
|
|
59
63
|
invalidate_sessions({ username }) {
|
|
64
|
+
(0, misc_1.apiAssertTypes)({ string: { username } });
|
|
60
65
|
auth_1.invalidSessions.add(username);
|
|
61
66
|
return {};
|
|
62
67
|
},
|
|
63
68
|
async change_srp({ username, salt, verifier }) {
|
|
69
|
+
(0, misc_1.apiAssertTypes)({ string: { username, salt, verifier } });
|
|
64
70
|
const a = (0, perm_1.getAccount)(username);
|
|
65
71
|
return a ? (0, perm_1.changeSrpHelper)(a, salt, verifier)
|
|
66
72
|
: new apiMiddleware_1.ApiError(const_1.HTTP_NOT_FOUND);
|
package/src/apiMiddleware.js
CHANGED
|
@@ -29,7 +29,7 @@ function apiMiddleware(apis) {
|
|
|
29
29
|
const safe = isPost && ctx.get('x-hfs-anti-csrf') // POST is safe because browser will enforce SameSite cookie
|
|
30
30
|
|| apiName.startsWith('get_'); // "get_" apis are safe because they make no change
|
|
31
31
|
if (!safe)
|
|
32
|
-
return send(const_1.HTTP_FOOL);
|
|
32
|
+
return send(const_1.HTTP_FOOL, "missing header x-hfs-anti-csrf=1");
|
|
33
33
|
const apiFun = apis.hasOwnProperty(apiName) && apis[apiName];
|
|
34
34
|
if (!apiFun)
|
|
35
35
|
return send(const_1.HTTP_NOT_FOUND, 'invalid api');
|
package/src/consoleLog.js
CHANGED
|
@@ -11,6 +11,8 @@ for (const k of ['log', 'warn', 'error']) {
|
|
|
11
11
|
console[k] = (...args) => {
|
|
12
12
|
const rec = { ts: new Date(), k, msg: args.join(' ') };
|
|
13
13
|
exports.consoleLog.push(rec);
|
|
14
|
+
if (exports.consoleLog.length > 100000) // limit to avoid infinite space
|
|
15
|
+
exports.consoleLog.splice(0, 1000);
|
|
14
16
|
events_1.default.emit('console', rec);
|
|
15
17
|
return original(...args);
|
|
16
18
|
};
|
package/src/const.js
CHANGED
|
@@ -45,7 +45,7 @@ exports.DEV = process.env.DEV || exports.argv.dev ? 'DEV' : '';
|
|
|
45
45
|
exports.ORIGINAL_CWD = process.cwd();
|
|
46
46
|
exports.HFS_STARTED = new Date();
|
|
47
47
|
const PKG_PATH = (0, path_1.join)(__dirname, '..', 'package.json');
|
|
48
|
-
exports.BUILD_TIMESTAMP = "2024-04-
|
|
48
|
+
exports.BUILD_TIMESTAMP = "2024-04-20T19:09:36.991Z";
|
|
49
49
|
const pkg = JSON.parse(fs.readFileSync(PKG_PATH, 'utf8'));
|
|
50
50
|
exports.VERSION = pkg.version;
|
|
51
51
|
exports.RUNNING_BETA = exports.VERSION.includes('-');
|
package/src/frontEndApis.js
CHANGED
|
@@ -71,6 +71,7 @@ exports.frontEndApis = {
|
|
|
71
71
|
},
|
|
72
72
|
async create_folder({ uri, name }, ctx) {
|
|
73
73
|
(0, misc_1.apiAssertTypes)({ string: { uri, name } });
|
|
74
|
+
ctx.logExtra(null, { name, target: decodeURI(uri) });
|
|
74
75
|
if (!(0, util_files_1.isValidFileName)(name))
|
|
75
76
|
return new apiMiddleware_1.ApiError(const_1.HTTP_BAD_REQUEST, 'bad name');
|
|
76
77
|
const parentNode = await (0, vfs_1.urlToNode)(uri, ctx);
|
|
@@ -89,6 +90,7 @@ exports.frontEndApis = {
|
|
|
89
90
|
},
|
|
90
91
|
async delete({ uri }, ctx) {
|
|
91
92
|
(0, misc_1.apiAssertTypes)({ string: { uri } });
|
|
93
|
+
ctx.logExtra(null, { target: decodeURI(uri) });
|
|
92
94
|
const node = await (0, vfs_1.urlToNode)(uri, ctx);
|
|
93
95
|
if (!node)
|
|
94
96
|
throw new apiMiddleware_1.ApiError(const_1.HTTP_NOT_FOUND);
|
|
@@ -107,6 +109,7 @@ exports.frontEndApis = {
|
|
|
107
109
|
},
|
|
108
110
|
async rename({ uri, dest }, ctx) {
|
|
109
111
|
(0, misc_1.apiAssertTypes)({ string: { uri, dest } });
|
|
112
|
+
ctx.logExtra(null, { target: decodeURI(uri), destination: decodeURI(dest) });
|
|
110
113
|
if (dest.includes('/') || (0, util_files_1.dirTraversal)(dest))
|
|
111
114
|
throw new apiMiddleware_1.ApiError(const_1.HTTP_FORBIDDEN);
|
|
112
115
|
const node = await (0, vfs_1.urlToNode)(uri, ctx);
|
|
@@ -137,6 +140,7 @@ exports.frontEndApis = {
|
|
|
137
140
|
},
|
|
138
141
|
async move_files({ uri_from, uri_to }, ctx) {
|
|
139
142
|
(0, misc_1.apiAssertTypes)({ array: { uri_from }, string: { uri_to } });
|
|
143
|
+
ctx.logExtra(null, { target: uri_from.map(decodeURI), destination: decodeURI(uri_to) });
|
|
140
144
|
const destNode = await (0, vfs_1.urlToNode)(uri_to, ctx);
|
|
141
145
|
const code = !destNode ? const_1.HTTP_NOT_FOUND : (0, vfs_1.statusCodeForMissingPerm)(destNode, 'can_upload', ctx);
|
|
142
146
|
if (code)
|
|
@@ -162,6 +166,7 @@ exports.frontEndApis = {
|
|
|
162
166
|
},
|
|
163
167
|
async comment({ uri, comment }, ctx) {
|
|
164
168
|
(0, misc_1.apiAssertTypes)({ string: { uri, comment } });
|
|
169
|
+
ctx.logExtra(null, { target: decodeURI(uri) });
|
|
165
170
|
const node = await (0, vfs_1.urlToNode)(uri, ctx);
|
|
166
171
|
if (!node)
|
|
167
172
|
throw new apiMiddleware_1.ApiError(const_1.HTTP_NOT_FOUND);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"author": "Club Microtel Vernon",
|
|
3
|
-
"version": 1.
|
|
4
|
-
"hfs_version": "0.
|
|
3
|
+
"version": "1.5",
|
|
4
|
+
"hfs_version": "0.52.1",
|
|
5
5
|
"translate": {
|
|
6
6
|
"Select": "Selectionner",
|
|
7
7
|
"n_files": "{n,plural, one{# fichier} other{# fichiers}}",
|
|
@@ -126,6 +126,38 @@
|
|
|
126
126
|
"showHelp_space_body": "Sélectionner",
|
|
127
127
|
"showHelp_D_body": "Télécharger",
|
|
128
128
|
"showHelp_Z_body": "Modes de zoom",
|
|
129
|
-
"showHelp_F_body": "Plein écran"
|
|
129
|
+
"showHelp_F_body": "Plein écran",
|
|
130
|
+
"Destination": "Destination",
|
|
131
|
+
"in_queue": "{n} en file d'attente",
|
|
132
|
+
"enter_comment": "Saisissez un commentaire pour ce fichier",
|
|
133
|
+
"Comment": "Commentaire",
|
|
134
|
+
"upload_dd_hint": "Vous pouvez télé-verser des fichiers en les faisant glisser vers la liste principale",
|
|
135
|
+
"Upload not available": "Télé-versement non disponible",
|
|
136
|
+
"Cut": "Couper",
|
|
137
|
+
"n_items": "{n,plural, one{# élément dans le presse-papiers} other{# éléments dans le presse-papiers}}",
|
|
138
|
+
"good_bad": "{good} transféré, {bad} en échec",
|
|
139
|
+
"after_cut": "Votre sélection est maintenant dans le presse-papiers.\nAllez dans le dossier de destination pour coller.",
|
|
140
|
+
"Cancel clipboard": "Annuler le presse-papiers",
|
|
141
|
+
"to_clipboard_source": "Retour au dossier source",
|
|
142
|
+
"Paste": "Coller",
|
|
143
|
+
"clipboard_list": "Eléments dans le presse-papiers:",
|
|
144
|
+
"Close": "Fermer",
|
|
145
|
+
"Folder": "Dossier",
|
|
146
|
+
"Web page": "Page Web",
|
|
147
|
+
"Link": "Lien",
|
|
148
|
+
"Auto-play": "Lecture automatique",
|
|
149
|
+
"autoplay_seconds": "Secondes d’attente pour afficher les images",
|
|
150
|
+
"Select all": "Tout sélectionner",
|
|
151
|
+
"go_first": "Remonter au début",
|
|
152
|
+
"go_last": "Aller à la fin",
|
|
153
|
+
"Shuffle": "Lecture aléatoire",
|
|
154
|
+
"Repeat": "Répéter",
|
|
155
|
+
"showHelpListShortcut": "Afficher le raccourci de la liste d’aide",
|
|
156
|
+
"Invalid value": "Valeur non valide",
|
|
157
|
+
"upload_skipped": "{n} télé-versement(s)ignoré(s)",
|
|
158
|
+
"Overwrite policy": "Stratégie de remplacement",
|
|
159
|
+
"Rename to avoid overwriting": "Renommer pour éviter l'écrasement",
|
|
160
|
+
"Overwrite existing files": "Écraser les fichiers existants",
|
|
161
|
+
"Menu": "Menu"
|
|
130
162
|
}
|
|
131
163
|
}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
|
-
"author": "
|
|
3
|
-
"version": 1.
|
|
4
|
-
"hfs_version": "0.
|
|
2
|
+
"author": "배서연, Hawk1335",
|
|
3
|
+
"version": 1.1,
|
|
4
|
+
"hfs_version": "0.52.0",
|
|
5
5
|
"translate": {
|
|
6
6
|
"Select": "선택",
|
|
7
7
|
"n_files": "{n,plural,one{1개의 파일} =2 =3{파일 #개} other{#개 파일}}",
|
|
8
8
|
"n_folders": "{n,plural,one{1 폴더} =2 =3 =4 {#개의 폴더} other{#개 폴더}",
|
|
9
|
-
"filter_count": "{n}개
|
|
10
|
-
"select_count": "{n}
|
|
9
|
+
"filter_count": "{n}개 찾음",
|
|
10
|
+
"select_count": "{n} 선택",
|
|
11
11
|
"filter_placeholder": "아래 목록을 필터링하려면 여기에 입력하세요.",
|
|
12
|
-
"Select some files": "
|
|
12
|
+
"Select some files": "파일 선택",
|
|
13
13
|
"zip_checkboxes": "파일을 선택한 후 압축하기를 클릭해 주세요.",
|
|
14
14
|
"zip_tooltip_selected": "선택한 요소를 하나의 ZIP 파일로 다운로드",
|
|
15
15
|
"zip_tooltip_whole": "전체 목록(필터링되지 않은)을 하나의 ZIP 파일로 다운로드합니다. 항목을 선택한 경우 선택한 항목만 다운로드됩니다.",
|
|
@@ -17,14 +17,14 @@
|
|
|
17
17
|
"zip_confirm_folder": "전체 폴더를 ZIP 아카이브로 다운로드하시겠습니까?",
|
|
18
18
|
"select_tooltip": "압축하기 및 삭제하기(사용 가능한 경우)에 선택이 적용됩니다. 목록을 필터링할 수도 있습니다.",
|
|
19
19
|
"delete_hint": "삭제하려면 먼저 항목을 선택하세요.",
|
|
20
|
-
"delete_confirm": "{n
|
|
20
|
+
"delete_confirm": "{n}개 항목을 삭제하시겠습니까?",
|
|
21
21
|
"delete_completed": "{n}개의 항목이 삭제되었습니다.",
|
|
22
|
-
"delete_failed": ", {n
|
|
22
|
+
"delete_failed": ", {n}개 항목이 실패했습니다",
|
|
23
23
|
"delete_select": "삭제할 항목을 선택하세요.",
|
|
24
24
|
"Delete": "삭제",
|
|
25
25
|
"Options": "옵션",
|
|
26
26
|
"Search": "검색",
|
|
27
|
-
"Zip": "Zip
|
|
27
|
+
"Zip": "Zip 압축",
|
|
28
28
|
"search_msg": "검색",
|
|
29
29
|
"Searching": "검색 중",
|
|
30
30
|
"Searched": "검색 완료",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"Interrupted": "중단됨",
|
|
33
33
|
"stopped_before": "이미 중단된 작업입니다.",
|
|
34
34
|
"empty_list": "목록이 비어 있습니다.",
|
|
35
|
-
"filter_none": "
|
|
35
|
+
"filter_none": "입력한 필터와 일치하는 항목이 없습니다.",
|
|
36
36
|
"Admin-panel": "관리자 패널",
|
|
37
37
|
"Login": "로그인",
|
|
38
38
|
"Username": "사용자명",
|
|
@@ -51,8 +51,9 @@
|
|
|
51
51
|
"Full timestamp:": "전체 타임스탬프:",
|
|
52
52
|
"Search was interrupted": "검색이 중단되었습니다.",
|
|
53
53
|
"Stop list": "중지 목록",
|
|
54
|
-
"upload_starting": "
|
|
54
|
+
"upload_starting": "이제 다운로드가 시작됩니다.",
|
|
55
55
|
"wrong_account": "계정 {u}은(는) 접근 권한이 없습니다. 다른 계정을 시도해보십시오.",
|
|
56
|
+
"no_upload_here": "현재 폴더에 대한 업로드 권한이 없습니다.",
|
|
56
57
|
"Create folder": "폴더 생성",
|
|
57
58
|
"Pick files": "파일 선택",
|
|
58
59
|
"Pick folder": "폴더 선택",
|
|
@@ -60,9 +61,10 @@
|
|
|
60
61
|
"Clear": "지우기",
|
|
61
62
|
"failed_upload": "{name} 업로드에 실패했습니다.",
|
|
62
63
|
"confirm_resume": "업로드를 재시도 하시겠습니까?",
|
|
64
|
+
"file too large": "파일이 너무 큽니다.",
|
|
63
65
|
"Enter folder name": "폴더 이름 입력",
|
|
64
66
|
"Successfully created": "성공적으로 생성되었습니다.",
|
|
65
|
-
"enter_folder": "
|
|
67
|
+
"enter_folder": "생성한 폴더로 이동",
|
|
66
68
|
"folder_exists": "동일한 이름의 폴더가 이미 존재합니다.",
|
|
67
69
|
"Sort by": "정렬 기준",
|
|
68
70
|
"name": "이름",
|
|
@@ -93,11 +95,65 @@
|
|
|
93
95
|
"upload_finished": "{n}개 파일 완료 ({size})",
|
|
94
96
|
"upload_errors": "{n}개 파일 실패",
|
|
95
97
|
"upload_file_rejected": "일부 파일은 업로드되지 않았습니다.",
|
|
96
|
-
"download counter": "다운로드 횟수",
|
|
97
98
|
"File menu": "파일 메뉴",
|
|
99
|
+
"Folder menu": "폴더 메뉴",
|
|
98
100
|
"Name": "이름",
|
|
99
101
|
"file_open": "열기",
|
|
100
102
|
"Download": "다운로드",
|
|
101
|
-
"Missing permission": "권한이 존재하지 않습니다."
|
|
103
|
+
"Missing permission": "권한이 존재하지 않습니다.",
|
|
104
|
+
"Reload": "새로고침",
|
|
105
|
+
"Get list": "목록으로 출력",
|
|
106
|
+
"Skip existing files": "기존 파일 건너뛰기",
|
|
107
|
+
"Size": "크기",
|
|
108
|
+
"Timestamp": "수정한 날짜",
|
|
109
|
+
"Show": "보기",
|
|
110
|
+
"Loading failed": "불러오기 실패",
|
|
111
|
+
"Rename": "이름 바꾸기",
|
|
112
|
+
"Tiles mode:": "표시 모드:",
|
|
113
|
+
"off": "꺼짐",
|
|
114
|
+
"Operation successful": "작업 성공",
|
|
115
|
+
"Uploader": "업로더",
|
|
116
|
+
"Download counter": "다운로드 횟수",
|
|
117
|
+
"Switch zoom mode": "확대/축소 모드 전환",
|
|
118
|
+
"Full screen": "전체 화면",
|
|
119
|
+
"File Show help": "파일 도움말 표시",
|
|
120
|
+
"showHelpMain": "일부 작업에는 키보드를 사용할 수 있습니다:",
|
|
121
|
+
"showHelp_←/→": "←/→",
|
|
122
|
+
"showHelp_↑/↓": "↑/↓",
|
|
123
|
+
"showHelp_space": "스페이스 바",
|
|
124
|
+
"showHelp_←/→_body": "이전/다음 파일로 이동",
|
|
125
|
+
"showHelp_↑/↓_body": "이미지 스크롤",
|
|
126
|
+
"Destination": "목적지",
|
|
127
|
+
"in_queue": "{n}이 대기열에 있습니다.",
|
|
128
|
+
"enter_comment": "{name}의 댓글",
|
|
129
|
+
"Comment": "댓글",
|
|
130
|
+
"upload_dd_hint": "파일 목록 화면에서 드래그 앤 드롭으로 파일을 업로드할 수 있습니다.",
|
|
131
|
+
"Upload not available": "업로드할 수 없습니다.",
|
|
132
|
+
"Cut": "잘라내기",
|
|
133
|
+
"n_items": "{n} 항목",
|
|
134
|
+
"good_bad": "{good} 항목 이동됨, {bad} 항목 실패",
|
|
135
|
+
"after_cut": "이제 선택한 항목이 클립보드에 있습니다.\n붙여넣으려면 대상 폴더로 이동하세요.",
|
|
136
|
+
"Cancel clipboard": "클립보드 취소",
|
|
137
|
+
"to_clipboard_source": "원본 폴더로 돌아가기",
|
|
138
|
+
"Paste": "붙여넣기",
|
|
139
|
+
"clipboard_list": "클립보드의 항목:",
|
|
140
|
+
"Close": "닫기",
|
|
141
|
+
"Folder": "폴더",
|
|
142
|
+
"Web page": "웹 페이지",
|
|
143
|
+
"Link": "링크",
|
|
144
|
+
"Auto-play": "자동 재생",
|
|
145
|
+
"autoplay_seconds": "이미지 재생 속도(초)",
|
|
146
|
+
"Select all": "모두 선택",
|
|
147
|
+
"go_first": "첫 번째 항목으로 이동",
|
|
148
|
+
"go_last": "마지막 항목으로 이동",
|
|
149
|
+
"Shuffle": "섞기",
|
|
150
|
+
"Repeat": "반복",
|
|
151
|
+
"showHelpListShortcut": "파일 목록을 빠르게 넘기려면 {key}를 길게 클릭하세요.",
|
|
152
|
+
"Invalid value": "잘못된 값",
|
|
153
|
+
"upload_skipped": "{n} 건너뜀",
|
|
154
|
+
"Overwrite policy": "덮어쓰기 정책",
|
|
155
|
+
"Rename to avoid overwriting": "덮어쓰지 않도록 이름 바꾸기",
|
|
156
|
+
"Overwrite existing files": "기존 파일 덮어쓰기",
|
|
157
|
+
"Menu": "메뉴"
|
|
102
158
|
}
|
|
103
159
|
}
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"author": "Phoenix",
|
|
3
3
|
"version": 1.0,
|
|
4
|
-
"hfs_version": "0.
|
|
4
|
+
"hfs_version": "0.52.0",
|
|
5
5
|
"translate": {
|
|
6
6
|
"Select": "選擇",
|
|
7
7
|
"n_files": "{n,plural,one{# 個檔案} other{# 個檔案}}",
|
|
8
8
|
"n_folders": "{n,plural,one{# 個資料夾} other{# 個資料夾}}",
|
|
9
9
|
"filter_count": "{n,plural, one{# 已過濾} other{# 已過濾}}",
|
|
10
10
|
"select_count": "{n,plural, one{# 已選擇} other{# 已選擇}}",
|
|
11
|
-
"filter_placeholder": "
|
|
12
|
-
"Select some files": "
|
|
11
|
+
"filter_placeholder": "輸入內容,過濾下方清單",
|
|
12
|
+
"Select some files": "選擇檔案",
|
|
13
13
|
"zip_checkboxes": "使用選擇來複選檔案,然後再次使用Zip壓縮",
|
|
14
14
|
"zip_tooltip_selected": "將所選檔案下載為單一Zip壓縮檔",
|
|
15
|
-
"zip_tooltip_whole": "
|
|
15
|
+
"zip_tooltip_whole": "將整個清單(未過濾)作為單一Zip壓縮檔下載.如果選擇了一些檔案,則只會下載那些檔案",
|
|
16
16
|
"zip_confirm_search": "將此搜尋的所有結果下載為Zip壓縮檔?",
|
|
17
17
|
"zip_confirm_folder": "確認將整個資料夾下載為Zip壓縮檔?",
|
|
18
|
-
"select_tooltip": "選擇適用於\"Zip\"和\"刪除\"(如果有的話)
|
|
18
|
+
"select_tooltip": "選擇適用於\"Zip\"和\"刪除\"(如果有的話),也可以過濾清單",
|
|
19
19
|
"delete_hint": "請先點擊“選擇”某些項目,才能執行刪除.",
|
|
20
20
|
"delete_confirm": "確認刪除 {n,plural, one{# 項} other{# 項}}?",
|
|
21
21
|
"delete_completed": "刪除: {n} 完成",
|
|
22
|
-
"delete_failed": ", {n,plural, one{#
|
|
22
|
+
"delete_failed": ", {n,plural, one{# 個失敗} other{# 個失敗}}",
|
|
23
23
|
"delete_select": "選擇要刪除的項目",
|
|
24
24
|
"Delete": "刪除",
|
|
25
25
|
"Options": "選項",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"Clear search": "清除搜尋條件",
|
|
32
32
|
"Interrupted": "中止",
|
|
33
33
|
"stopped_before": "已停止",
|
|
34
|
-
"empty_list": "
|
|
34
|
+
"empty_list": "空清單",
|
|
35
35
|
"filter_none": "過濾後無找到",
|
|
36
36
|
"Admin-panel": "管理面板",
|
|
37
37
|
"Login": "登入",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"Create folder": "建立資料夾",
|
|
58
58
|
"Pick files": "選擇檔案",
|
|
59
59
|
"Pick folder": "選擇資料夾",
|
|
60
|
-
"send_files": "開始上傳 {n,plural,one{#
|
|
60
|
+
"send_files": "開始上傳 {n,plural,one{# 個檔案} other{# 個檔案}}, {size}",
|
|
61
61
|
"Clear": "清空",
|
|
62
62
|
"failed_upload": "無法上傳 {name}",
|
|
63
63
|
"confirm_resume": "繼續上傳?",
|
|
@@ -95,12 +95,65 @@
|
|
|
95
95
|
"upload_finished": "{n} 個檔案完成 ({size})",
|
|
96
96
|
"upload_errors": "{n} 失敗",
|
|
97
97
|
"upload_file_rejected": "部分檔案不被允許",
|
|
98
|
-
"download counter": "下載次數",
|
|
99
98
|
"File menu": "檔案選單",
|
|
100
99
|
"Folder menu": "資料夾選單",
|
|
101
100
|
"Name": "名稱",
|
|
102
101
|
"file_open": "開啟",
|
|
103
102
|
"Download": "下載",
|
|
104
|
-
"Missing permission": "
|
|
103
|
+
"Missing permission": "缺少權限",
|
|
104
|
+
"Reload": "重新載入",
|
|
105
|
+
"Get list": "取得清單",
|
|
106
|
+
"Skip existing files": "跳過已存在的檔案",
|
|
107
|
+
"Size": "大小",
|
|
108
|
+
"Timestamp": "時間戳",
|
|
109
|
+
"Show": "顯示",
|
|
110
|
+
"Loading failed": "載入失敗",
|
|
111
|
+
"Rename": "重新命名",
|
|
112
|
+
"Tiles mode:": "平鋪模式:",
|
|
113
|
+
"off": "關閉",
|
|
114
|
+
"Operation successful": "操作成功",
|
|
115
|
+
"Uploader": "上傳者",
|
|
116
|
+
"Download counter": "下載次數",
|
|
117
|
+
"Switch zoom mode": "切換縮放模式",
|
|
118
|
+
"Full screen": "全螢幕",
|
|
119
|
+
"File Show help": "檔案幫助",
|
|
120
|
+
"showHelpMain": "您可以使用鍵盤執行以下操作:",
|
|
121
|
+
"showHelp_←/→": "←/→",
|
|
122
|
+
"showHelp_↑/↓": "↑/↓",
|
|
123
|
+
"showHelp_space": "空白",
|
|
124
|
+
"showHelp_←/→_body": "上一個/下一個檔案",
|
|
125
|
+
"showHelp_↑/↓_body": "滾動長圖片",
|
|
126
|
+
"Destination": "目的地",
|
|
127
|
+
"in_queue": "{n} 在隊列中",
|
|
128
|
+
"enter_comment": "對 {name} 檔案評論",
|
|
129
|
+
"Comment": "評論",
|
|
130
|
+
"upload_dd_hint": "將檔案拖放到這裡即可上傳到此清單",
|
|
131
|
+
"Upload not available": "無法上傳",
|
|
132
|
+
"Cut": "剪下",
|
|
133
|
+
"n_items": "{n,plural, one{# 項} other{# 項}}",
|
|
134
|
+
"good_bad": "{good} 個已移動, {bad} 個失敗",
|
|
135
|
+
"after_cut": "您的選擇現在已在剪貼簿中\n到目標資料夾貼上",
|
|
136
|
+
"Cancel clipboard": "取消剪貼簿",
|
|
137
|
+
"to_clipboard_source": "返回來源資料夾",
|
|
138
|
+
"Paste": "貼上",
|
|
139
|
+
"clipboard_list": "剪貼簿中的項目:",
|
|
140
|
+
"Close": "關閉",
|
|
141
|
+
"Folder": "資料夾",
|
|
142
|
+
"Web page": "網頁",
|
|
143
|
+
"Link": "連結",
|
|
144
|
+
"Auto-play": "自動播放",
|
|
145
|
+
"autoplay_seconds": "自動播放間隔秒數",
|
|
146
|
+
"Select all": "全選",
|
|
147
|
+
"go_first": "第一項",
|
|
148
|
+
"go_last": "最後一項",
|
|
149
|
+
"Shuffle": "隨機播放",
|
|
150
|
+
"Repeat": "重複播放",
|
|
151
|
+
"showHelpListShortcut": "在檔案清單中,按一下 {key} 即可快速顯示",
|
|
152
|
+
"Invalid value": "無效值",
|
|
153
|
+
"upload_skipped": "{n} 跳過",
|
|
154
|
+
"Overwrite policy": "覆蓋規則",
|
|
155
|
+
"Rename to avoid overwriting": "重新命名以避免覆蓋",
|
|
156
|
+
"Overwrite existing files": "覆蓋已存在的檔案",
|
|
157
|
+
"Menu": "選單"
|
|
105
158
|
}
|
|
106
159
|
}
|
package/src/log.js
CHANGED
|
@@ -148,10 +148,8 @@ const logMw = async (ctx, next) => {
|
|
|
148
148
|
};
|
|
149
149
|
exports.logMw = logMw;
|
|
150
150
|
events_1.default.on('app', () => {
|
|
151
|
-
index_1.app.context.logExtra = function (
|
|
152
|
-
|
|
153
|
-
if (o)
|
|
154
|
-
Object.assign((_a = this.state).logExtra || (_a.logExtra = {}), o);
|
|
151
|
+
index_1.app.context.logExtra = function (anything, params) {
|
|
152
|
+
lodash_1.default.merge(this.state, { logExtra: { ...anything, params } }); // params will be considered as parameters of the API
|
|
155
153
|
};
|
|
156
154
|
});
|
|
157
155
|
function doubleDigit(n) {
|
package/src/perm.js
CHANGED
|
@@ -132,6 +132,7 @@ function addAccount(username, props) {
|
|
|
132
132
|
return;
|
|
133
133
|
const copy = (0, misc_1.setHidden)(lodash_1.default.pickBy(props, Boolean), { username }); // have the field in the object but hidden so that stringification won't include it
|
|
134
134
|
exports.accountsConfig.set(accounts => Object.assign(accounts, { [username]: copy }));
|
|
135
|
+
saveAccountsAsap();
|
|
135
136
|
return copy;
|
|
136
137
|
}
|
|
137
138
|
exports.addAccount = addAccount;
|
package/src/roots.js
CHANGED
|
@@ -41,7 +41,7 @@ const rootsMiddleware = (ctx, next) => (() => {
|
|
|
41
41
|
if (root === undefined) {
|
|
42
42
|
if (ctx.state.skipFilters || !rootsMandatory.get() || (0, misc_1.isLocalHost)(ctx))
|
|
43
43
|
return;
|
|
44
|
-
(0, connections_1.disconnect)(ctx, '
|
|
44
|
+
(0, connections_1.disconnect)(ctx, 'bad-domain');
|
|
45
45
|
return true; // true will avoid calling next
|
|
46
46
|
}
|
|
47
47
|
if (!params) {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.ariaOnly{position:absolute;clip-path:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}:root{height:100dvh;--success: #5c5}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;height:100vh;background:#000}#root{min-height:100%;display:flex}main{word-break:break-word}code{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}img.flag{width:1.5em;height:1em;vertical-align:text-top;margin-top:1px}.icon-w-text{margin-right:.5em}form{max-width:100%}.MuiSvgIcon-root{vertical-align:bottom}.MuiTreeItem-content{box-sizing:border-box}.MuiDataGrid-columnHeaders{background-color:#8882}.MuiDataGrid-cell{line-height:1.1em}.wrap[role=cell]{white-space:normal!important}ol,ul{margin-top:.2em;margin-bottom:.2em;padding-left:1.5em}h2.MuiDialogTitle-root{padding-top:2px;padding-bottom:2px}.dialog-alert .MuiDialogContent-root{max-width:45em;padding:.5em 1em}.animated-dashed-line{width:100%;height:2px;background-image:linear-gradient(to right,currentColor 50%,transparent 50%);background-size:10px 100%;animation:animate-dash 1s alternate linear infinite}@keyframes animate-dash{to{background-position:20px 0}}@keyframes blink{0%{opacity:1}50%{opacity:.2}}@keyframes success{50%{transform:scale(1.5);color:var(--success)}to{transform:inherit;color:inherit}}
|