hfs 3.0.7 → 3.1.0-alpha2

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.
Files changed (317) hide show
  1. package/README.md +1 -1
  2. package/admin/assets/index-CDiYkO8j.css +1 -0
  3. package/admin/assets/index-Dm5BN1iZ.js +1 -0
  4. package/admin/assets/index-P5i8LyWl.js +822 -0
  5. package/admin/assets/{sha512-gDcjPgJS.js → sha512-DG-ElrDe.js} +1 -1
  6. package/admin/flags/freakflags.css +284 -0
  7. package/admin/flags/sprite.png +0 -0
  8. package/admin/index.html +3 -2
  9. package/frontend/assets/index-legacy-CG_og8xL.js +1 -0
  10. package/frontend/assets/index-legacy-DDLKWGcm.js +9 -0
  11. package/frontend/assets/{sha512-legacy-BBwwadDl.js → sha512-legacy-D1zEZzDe.js} +1 -1
  12. package/frontend/fontello.css +3 -1
  13. package/frontend/fontello.woff2 +0 -0
  14. package/frontend/index.html +1 -1
  15. package/npm-shrinkwrap.json +16409 -0
  16. package/package.json +12 -11
  17. package/plugins/antibrute/plugin.js +14 -3
  18. package/src/AsapStream.js +49 -0
  19. package/src/ThrottledStream.js +1 -1
  20. package/src/adminApis.js +16 -5
  21. package/src/api.accounts.js +1 -6
  22. package/src/api.auth.js +103 -100
  23. package/src/api.get_file_list.js +7 -0
  24. package/src/api.lang.js +1 -0
  25. package/src/api.log.js +5 -3
  26. package/src/api.monitor.js +5 -0
  27. package/src/api.net.js +5 -0
  28. package/src/api.plugins.js +13 -2
  29. package/src/api.vfs.js +41 -28
  30. package/src/apiMiddleware.js +5 -4
  31. package/src/auth.js +39 -6
  32. package/src/commands.js +16 -27
  33. package/src/comments.js +4 -4
  34. package/src/config.js +5 -2
  35. package/src/const.js +2 -16
  36. package/src/cross-const.js +5 -2
  37. package/src/cross.js +21 -15
  38. package/src/expiringCache.js +16 -5
  39. package/src/fileAttr.js +1 -1
  40. package/src/first.js +7 -4
  41. package/src/frontEndApis.js +88 -102
  42. package/src/github.js +32 -21
  43. package/src/ips.js +1 -1
  44. package/src/log.js +5 -3
  45. package/src/middlewares.js +2 -1
  46. package/src/misc.js +2 -20
  47. package/src/perm.js +27 -12
  48. package/src/persistence.js +1 -1
  49. package/src/plugins.js +12 -6
  50. package/src/serveFile.js +3 -3
  51. package/src/serveGuiAndSharedFiles.js +3 -0
  52. package/src/serveGuiFiles.js +2 -1
  53. package/src/srp.js +5 -6
  54. package/src/stat.js +4 -1
  55. package/src/update.js +18 -25
  56. package/src/upload.js +4 -3
  57. package/src/util-files.js +2 -1
  58. package/src/util-http.js +3 -3
  59. package/src/vfs.js +4 -2
  60. package/src/webdav.js +297 -0
  61. package/admin/assets/index-Bj9Dk3JN.js +0 -822
  62. package/admin/assets/index-Byv1_NxP.css +0 -1
  63. package/admin/flags/ad.png +0 -0
  64. package/admin/flags/ae.png +0 -0
  65. package/admin/flags/af.png +0 -0
  66. package/admin/flags/ag.png +0 -0
  67. package/admin/flags/ai.png +0 -0
  68. package/admin/flags/al.png +0 -0
  69. package/admin/flags/am.png +0 -0
  70. package/admin/flags/ao.png +0 -0
  71. package/admin/flags/aq.png +0 -0
  72. package/admin/flags/ar.png +0 -0
  73. package/admin/flags/as.png +0 -0
  74. package/admin/flags/at.png +0 -0
  75. package/admin/flags/au.png +0 -0
  76. package/admin/flags/aw.png +0 -0
  77. package/admin/flags/ax.png +0 -0
  78. package/admin/flags/az.png +0 -0
  79. package/admin/flags/ba.png +0 -0
  80. package/admin/flags/bb.png +0 -0
  81. package/admin/flags/bd.png +0 -0
  82. package/admin/flags/be.png +0 -0
  83. package/admin/flags/bf.png +0 -0
  84. package/admin/flags/bg.png +0 -0
  85. package/admin/flags/bh.png +0 -0
  86. package/admin/flags/bi.png +0 -0
  87. package/admin/flags/bj.png +0 -0
  88. package/admin/flags/bl.png +0 -0
  89. package/admin/flags/bm.png +0 -0
  90. package/admin/flags/bn.png +0 -0
  91. package/admin/flags/bo.png +0 -0
  92. package/admin/flags/bq.png +0 -0
  93. package/admin/flags/br.png +0 -0
  94. package/admin/flags/bs.png +0 -0
  95. package/admin/flags/bt.png +0 -0
  96. package/admin/flags/bv.png +0 -0
  97. package/admin/flags/bw.png +0 -0
  98. package/admin/flags/by.png +0 -0
  99. package/admin/flags/bz.png +0 -0
  100. package/admin/flags/ca.png +0 -0
  101. package/admin/flags/cc.png +0 -0
  102. package/admin/flags/cd.png +0 -0
  103. package/admin/flags/cf.png +0 -0
  104. package/admin/flags/cg.png +0 -0
  105. package/admin/flags/ch.png +0 -0
  106. package/admin/flags/ci.png +0 -0
  107. package/admin/flags/ck.png +0 -0
  108. package/admin/flags/cl.png +0 -0
  109. package/admin/flags/cm.png +0 -0
  110. package/admin/flags/cn.png +0 -0
  111. package/admin/flags/co.png +0 -0
  112. package/admin/flags/cr.png +0 -0
  113. package/admin/flags/cu.png +0 -0
  114. package/admin/flags/cv.png +0 -0
  115. package/admin/flags/cw.png +0 -0
  116. package/admin/flags/cx.png +0 -0
  117. package/admin/flags/cy.png +0 -0
  118. package/admin/flags/cz.png +0 -0
  119. package/admin/flags/de.png +0 -0
  120. package/admin/flags/dj.png +0 -0
  121. package/admin/flags/dk.png +0 -0
  122. package/admin/flags/dm.png +0 -0
  123. package/admin/flags/do.png +0 -0
  124. package/admin/flags/dz.png +0 -0
  125. package/admin/flags/ec.png +0 -0
  126. package/admin/flags/ee.png +0 -0
  127. package/admin/flags/eg.png +0 -0
  128. package/admin/flags/eh.png +0 -0
  129. package/admin/flags/er.png +0 -0
  130. package/admin/flags/es.png +0 -0
  131. package/admin/flags/et.png +0 -0
  132. package/admin/flags/fi.png +0 -0
  133. package/admin/flags/fj.png +0 -0
  134. package/admin/flags/fk.png +0 -0
  135. package/admin/flags/fm.png +0 -0
  136. package/admin/flags/fo.png +0 -0
  137. package/admin/flags/fr.png +0 -0
  138. package/admin/flags/ga.png +0 -0
  139. package/admin/flags/gb-eng.png +0 -0
  140. package/admin/flags/gb-nir.png +0 -0
  141. package/admin/flags/gb-sct.png +0 -0
  142. package/admin/flags/gb-wls.png +0 -0
  143. package/admin/flags/gb.png +0 -0
  144. package/admin/flags/gd.png +0 -0
  145. package/admin/flags/ge.png +0 -0
  146. package/admin/flags/gf.png +0 -0
  147. package/admin/flags/gg.png +0 -0
  148. package/admin/flags/gh.png +0 -0
  149. package/admin/flags/gi.png +0 -0
  150. package/admin/flags/gl.png +0 -0
  151. package/admin/flags/gm.png +0 -0
  152. package/admin/flags/gn.png +0 -0
  153. package/admin/flags/gp.png +0 -0
  154. package/admin/flags/gq.png +0 -0
  155. package/admin/flags/gr.png +0 -0
  156. package/admin/flags/gs.png +0 -0
  157. package/admin/flags/gt.png +0 -0
  158. package/admin/flags/gu.png +0 -0
  159. package/admin/flags/gw.png +0 -0
  160. package/admin/flags/gy.png +0 -0
  161. package/admin/flags/hk.png +0 -0
  162. package/admin/flags/hm.png +0 -0
  163. package/admin/flags/hn.png +0 -0
  164. package/admin/flags/hr.png +0 -0
  165. package/admin/flags/ht.png +0 -0
  166. package/admin/flags/hu.png +0 -0
  167. package/admin/flags/id.png +0 -0
  168. package/admin/flags/ie.png +0 -0
  169. package/admin/flags/il.png +0 -0
  170. package/admin/flags/im.png +0 -0
  171. package/admin/flags/in.png +0 -0
  172. package/admin/flags/io.png +0 -0
  173. package/admin/flags/iq.png +0 -0
  174. package/admin/flags/ir.png +0 -0
  175. package/admin/flags/is.png +0 -0
  176. package/admin/flags/it.png +0 -0
  177. package/admin/flags/je.png +0 -0
  178. package/admin/flags/jm.png +0 -0
  179. package/admin/flags/jo.png +0 -0
  180. package/admin/flags/jp.png +0 -0
  181. package/admin/flags/ke.png +0 -0
  182. package/admin/flags/kg.png +0 -0
  183. package/admin/flags/kh.png +0 -0
  184. package/admin/flags/ki.png +0 -0
  185. package/admin/flags/km.png +0 -0
  186. package/admin/flags/kn.png +0 -0
  187. package/admin/flags/kp.png +0 -0
  188. package/admin/flags/kr.png +0 -0
  189. package/admin/flags/kw.png +0 -0
  190. package/admin/flags/ky.png +0 -0
  191. package/admin/flags/kz.png +0 -0
  192. package/admin/flags/la.png +0 -0
  193. package/admin/flags/lb.png +0 -0
  194. package/admin/flags/lc.png +0 -0
  195. package/admin/flags/li.png +0 -0
  196. package/admin/flags/lk.png +0 -0
  197. package/admin/flags/lr.png +0 -0
  198. package/admin/flags/ls.png +0 -0
  199. package/admin/flags/lt.png +0 -0
  200. package/admin/flags/lu.png +0 -0
  201. package/admin/flags/lv.png +0 -0
  202. package/admin/flags/ly.png +0 -0
  203. package/admin/flags/ma.png +0 -0
  204. package/admin/flags/mc.png +0 -0
  205. package/admin/flags/md.png +0 -0
  206. package/admin/flags/me.png +0 -0
  207. package/admin/flags/mf.png +0 -0
  208. package/admin/flags/mg.png +0 -0
  209. package/admin/flags/mh.png +0 -0
  210. package/admin/flags/mk.png +0 -0
  211. package/admin/flags/ml.png +0 -0
  212. package/admin/flags/mm.png +0 -0
  213. package/admin/flags/mn.png +0 -0
  214. package/admin/flags/mo.png +0 -0
  215. package/admin/flags/mp.png +0 -0
  216. package/admin/flags/mq.png +0 -0
  217. package/admin/flags/mr.png +0 -0
  218. package/admin/flags/ms.png +0 -0
  219. package/admin/flags/mt.png +0 -0
  220. package/admin/flags/mu.png +0 -0
  221. package/admin/flags/mv.png +0 -0
  222. package/admin/flags/mw.png +0 -0
  223. package/admin/flags/mx.png +0 -0
  224. package/admin/flags/my.png +0 -0
  225. package/admin/flags/mz.png +0 -0
  226. package/admin/flags/na.png +0 -0
  227. package/admin/flags/nc.png +0 -0
  228. package/admin/flags/ne.png +0 -0
  229. package/admin/flags/nf.png +0 -0
  230. package/admin/flags/ng.png +0 -0
  231. package/admin/flags/ni.png +0 -0
  232. package/admin/flags/nl.png +0 -0
  233. package/admin/flags/no.png +0 -0
  234. package/admin/flags/np.png +0 -0
  235. package/admin/flags/nr.png +0 -0
  236. package/admin/flags/nu.png +0 -0
  237. package/admin/flags/nz.png +0 -0
  238. package/admin/flags/om.png +0 -0
  239. package/admin/flags/pa.png +0 -0
  240. package/admin/flags/pe.png +0 -0
  241. package/admin/flags/pf.png +0 -0
  242. package/admin/flags/pg.png +0 -0
  243. package/admin/flags/ph.png +0 -0
  244. package/admin/flags/pk.png +0 -0
  245. package/admin/flags/pl.png +0 -0
  246. package/admin/flags/pm.png +0 -0
  247. package/admin/flags/pn.png +0 -0
  248. package/admin/flags/pr.png +0 -0
  249. package/admin/flags/ps.png +0 -0
  250. package/admin/flags/pt.png +0 -0
  251. package/admin/flags/pw.png +0 -0
  252. package/admin/flags/py.png +0 -0
  253. package/admin/flags/qa.png +0 -0
  254. package/admin/flags/re.png +0 -0
  255. package/admin/flags/ro.png +0 -0
  256. package/admin/flags/rs.png +0 -0
  257. package/admin/flags/ru.png +0 -0
  258. package/admin/flags/rw.png +0 -0
  259. package/admin/flags/sa.png +0 -0
  260. package/admin/flags/sb.png +0 -0
  261. package/admin/flags/sc.png +0 -0
  262. package/admin/flags/sd.png +0 -0
  263. package/admin/flags/se.png +0 -0
  264. package/admin/flags/sg.png +0 -0
  265. package/admin/flags/sh.png +0 -0
  266. package/admin/flags/si.png +0 -0
  267. package/admin/flags/sj.png +0 -0
  268. package/admin/flags/sk.png +0 -0
  269. package/admin/flags/sl.png +0 -0
  270. package/admin/flags/sm.png +0 -0
  271. package/admin/flags/sn.png +0 -0
  272. package/admin/flags/so.png +0 -0
  273. package/admin/flags/sr.png +0 -0
  274. package/admin/flags/ss.png +0 -0
  275. package/admin/flags/st.png +0 -0
  276. package/admin/flags/sv.png +0 -0
  277. package/admin/flags/sx.png +0 -0
  278. package/admin/flags/sy.png +0 -0
  279. package/admin/flags/sz.png +0 -0
  280. package/admin/flags/tc.png +0 -0
  281. package/admin/flags/td.png +0 -0
  282. package/admin/flags/tf.png +0 -0
  283. package/admin/flags/tg.png +0 -0
  284. package/admin/flags/th.png +0 -0
  285. package/admin/flags/tj.png +0 -0
  286. package/admin/flags/tk.png +0 -0
  287. package/admin/flags/tl.png +0 -0
  288. package/admin/flags/tm.png +0 -0
  289. package/admin/flags/tn.png +0 -0
  290. package/admin/flags/to.png +0 -0
  291. package/admin/flags/tr.png +0 -0
  292. package/admin/flags/tt.png +0 -0
  293. package/admin/flags/tv.png +0 -0
  294. package/admin/flags/tw.png +0 -0
  295. package/admin/flags/tz.png +0 -0
  296. package/admin/flags/ua.png +0 -0
  297. package/admin/flags/ug.png +0 -0
  298. package/admin/flags/um.png +0 -0
  299. package/admin/flags/us.png +0 -0
  300. package/admin/flags/uy.png +0 -0
  301. package/admin/flags/uz.png +0 -0
  302. package/admin/flags/va.png +0 -0
  303. package/admin/flags/vc.png +0 -0
  304. package/admin/flags/ve.png +0 -0
  305. package/admin/flags/vg.png +0 -0
  306. package/admin/flags/vi.png +0 -0
  307. package/admin/flags/vn.png +0 -0
  308. package/admin/flags/vu.png +0 -0
  309. package/admin/flags/wf.png +0 -0
  310. package/admin/flags/ws.png +0 -0
  311. package/admin/flags/xk.png +0 -0
  312. package/admin/flags/ye.png +0 -0
  313. package/admin/flags/yt.png +0 -0
  314. package/admin/flags/za.png +0 -0
  315. package/admin/flags/zm.png +0 -0
  316. package/admin/flags/zw.png +0 -0
  317. package/frontend/assets/index-legacy-COBT1YmS.js +0 -50
@@ -7,7 +7,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.checkDependencies = checkDependencies;
8
8
  const plugins_1 = require("./plugins");
9
9
  const lodash_1 = __importDefault(require("lodash"));
10
- const assert_1 = __importDefault(require("assert"));
11
10
  const misc_1 = require("./misc");
12
11
  const apiMiddleware_1 = require("./apiMiddleware");
13
12
  const promises_1 = require("fs/promises");
@@ -72,6 +71,7 @@ const apis = {
72
71
  });
73
72
  },
74
73
  async start_plugin({ id }) {
74
+ assertPluginId(id);
75
75
  if ((0, plugins_1.isPluginRunning)(id))
76
76
  return { msg: 'already running' };
77
77
  if (plugins_1.suspendPlugins.get())
@@ -80,13 +80,14 @@ const apis = {
80
80
  return (0, plugins_1.startPlugin)(id).then(() => ({}), e => new apiMiddleware_1.ApiError(const_1.HTTP_SERVER_ERROR, e.message));
81
81
  },
82
82
  async stop_plugin({ id }) {
83
+ assertPluginId(id);
83
84
  if (!(0, plugins_1.isPluginRunning)(id))
84
85
  return { msg: 'already stopped' };
85
86
  await (0, plugins_1.stopPlugin)(id);
86
87
  return {};
87
88
  },
88
89
  async set_plugin({ id, enabled, config }) {
89
- (0, assert_1.default)(id, 'id');
90
+ assertPluginId(id);
90
91
  if (config)
91
92
  (0, plugins_1.setPluginConfig)(id, config);
92
93
  if (enabled !== undefined)
@@ -94,6 +95,7 @@ const apis = {
94
95
  return {};
95
96
  },
96
97
  async get_plugin({ id }) {
98
+ assertPluginId(id);
97
99
  return {
98
100
  enabled: plugins_1.enablePlugins.get().includes(id),
99
101
  config: {
@@ -103,6 +105,8 @@ const apis = {
103
105
  };
104
106
  },
105
107
  get_online_plugins({ text }, ctx) {
108
+ if (text !== undefined && !lodash_1.default.isString(text))
109
+ return new apiMiddleware_1.ApiError(const_1.HTTP_BAD_REQUEST, 'bad text');
106
110
  return new SendList_1.SendListReadable({
107
111
  async doAtStart(list) {
108
112
  const repos = [];
@@ -142,6 +146,7 @@ const apis = {
142
146
  });
143
147
  },
144
148
  async download_plugin({ id, branch, stop }) {
149
+ assertPluginId(id);
145
150
  await checkDependencies(await (0, github_1.readOnlinePlugin)(id, branch));
146
151
  const folder = await (0, github_1.downloadPlugin)(id, { branch });
147
152
  if (stop) // be sure this is not automatically started
@@ -150,6 +155,7 @@ const apis = {
150
155
  || new apiMiddleware_1.ApiError(const_1.HTTP_SERVER_ERROR);
151
156
  },
152
157
  async update_plugin({ id }) {
158
+ assertPluginId(id);
153
159
  const found = (0, plugins_1.getPluginInfo)(id);
154
160
  if (!found)
155
161
  return new apiMiddleware_1.ApiError(const_1.HTTP_NOT_FOUND);
@@ -161,6 +167,7 @@ const apis = {
161
167
  return {};
162
168
  },
163
169
  async uninstall_plugin({ id, deleteConfig }) {
170
+ assertPluginId(id);
164
171
  await (0, plugins_1.stopPlugin)(id);
165
172
  await (0, promises_1.rm)(plugins_1.PATH + '/' + id, { recursive: true, force: true });
166
173
  if (deleteConfig)
@@ -168,6 +175,7 @@ const apis = {
168
175
  return {};
169
176
  },
170
177
  get_plugin_log({ id }, ctx) {
178
+ assertPluginId(id);
171
179
  const p = (0, plugins_1.getPluginInfo)(id);
172
180
  if (!p)
173
181
  return new apiMiddleware_1.ApiError(const_1.HTTP_NOT_FOUND);
@@ -178,6 +186,9 @@ const apis = {
178
186
  },
179
187
  };
180
188
  exports.default = apis;
189
+ function assertPluginId(id) {
190
+ (0, misc_1.apiAssertTypes)({ string: { id } });
191
+ }
181
192
  function serialize(p) {
182
193
  let o = 'getData' in p ? Object.assign(lodash_1.default.pick(p, ['id', 'started']), p.getData())
183
194
  : { ...p }; // _.defaults mutates object, and we don't want that
package/src/api.vfs.js CHANGED
@@ -22,8 +22,6 @@ async function urlToNodeOriginal(uri) {
22
22
  const n = await (0, vfs_1.urlToNode)(uri);
23
23
  return n?.isTemp ? n.original : n;
24
24
  }
25
- const ALLOWED_KEYS = ['name', 'source', 'masks', 'default', 'accept', 'rename', 'mime', 'url',
26
- 'target', 'comment', 'icon', 'order', ...misc_1.PERM_KEYS];
27
25
  exports.default = {
28
26
  async get_vfs() {
29
27
  return { root: await recur() };
@@ -44,7 +42,7 @@ exports.default = {
44
42
  ...node.original || node,
45
43
  inherited,
46
44
  byMasks: lodash_1.default.isEmpty(byMasks) ? undefined : byMasks,
47
- website: Boolean(node.children?.find((0, vfs_1.isSameFilenameAs)('index.html')))
45
+ website: node.children?.some((0, vfs_1.isSameFilenameAs)('index.html'))
48
46
  || isFolder && source && await (0, misc_1.statWithTimeout)((0, path_1.join)(source, 'index.html')).then(() => true, () => undefined)
49
47
  || undefined,
50
48
  name: (0, vfs_1.getNodeName)(node),
@@ -53,6 +51,25 @@ exports.default = {
53
51
  };
54
52
  }
55
53
  },
54
+ async set_vfs({ uri, props }) {
55
+ const n = uri && await urlToNodeOriginal(uri);
56
+ if (!n)
57
+ return new apiMiddleware_1.ApiError(const_1.HTTP_NOT_FOUND, 'path not found');
58
+ if (props.name && props.name !== (0, vfs_1.getNodeName)(n)) {
59
+ if (!(0, misc_1.isValidFileName)(props.name))
60
+ return new apiMiddleware_1.ApiError(const_1.HTTP_BAD_REQUEST, 'bad name');
61
+ // check for siblings with the same name
62
+ const parent = await urlToNodeOriginal((0, path_1.dirname)(uri));
63
+ if (parent?.children?.find(x => (0, vfs_1.getNodeName)(x) === props.name))
64
+ return new apiMiddleware_1.ApiError(const_1.HTTP_CONFLICT, 'name already present');
65
+ }
66
+ Object.assign(n, sanitizeVfsProps(props));
67
+ simplifyName(n);
68
+ n.isFolder = undefined; // reset field, it will be set by saveVfs
69
+ await (0, vfs_1.saveVfs)();
70
+ return n;
71
+ },
72
+ // legacy – not currently used by the UI
56
73
  async move_vfs({ from, parent }) {
57
74
  if (!from || !parent)
58
75
  return new apiMiddleware_1.ApiError(const_1.HTTP_BAD_REQUEST);
@@ -71,35 +88,19 @@ exports.default = {
71
88
  return new apiMiddleware_1.ApiError(const_1.HTTP_CONFLICT, 'item with same name already present in destination');
72
89
  const oldParent = await urlToNodeOriginal((0, path_1.dirname)(from));
73
90
  lodash_1.default.pull(oldParent.children, fromNode);
74
- if (lodash_1.default.isEmpty(oldParent.children))
91
+ if (lodash_1.default.isEmpty(oldParent.children)) {
75
92
  delete oldParent.children;
93
+ }
94
+ ;
76
95
  (parentNode.children ||= []).push(fromNode);
77
96
  await (0, vfs_1.saveVfs)();
78
97
  return {};
79
98
  },
80
- async set_vfs({ uri, props }) {
81
- const n = await urlToNodeOriginal(uri);
82
- if (!n)
83
- return new apiMiddleware_1.ApiError(const_1.HTTP_NOT_FOUND, 'path not found');
84
- if (props.name && props.name !== (0, vfs_1.getNodeName)(n)) {
85
- if (!(0, misc_1.isValidFileName)(props.name))
86
- return new apiMiddleware_1.ApiError(const_1.HTTP_BAD_REQUEST, 'bad name');
87
- const parent = await urlToNodeOriginal((0, path_1.dirname)(uri));
88
- if (parent?.children?.find(x => (0, vfs_1.getNodeName)(x) === props.name))
89
- return new apiMiddleware_1.ApiError(const_1.HTTP_CONFLICT, 'name already present');
90
- }
91
- if (props.masks && typeof props.masks !== 'object')
92
- delete props.masks;
93
- Object.assign(n, pickProps(props, ALLOWED_KEYS));
94
- simplifyName(n);
95
- n.isFolder = undefined; // reset field, it will be set by saveVfs
96
- await (0, vfs_1.saveVfs)();
97
- return n;
98
- },
99
+ // legacy not currently used by the UI
99
100
  async add_vfs({ parent, source, name, ...rest }) {
100
101
  if (!source && !name)
101
102
  return new apiMiddleware_1.ApiError(const_1.HTTP_BAD_REQUEST, 'name or source required');
102
- if (!(0, misc_1.isValidFileName)(name))
103
+ if (name && !(0, misc_1.isValidFileName)(name))
103
104
  return new apiMiddleware_1.ApiError(const_1.HTTP_BAD_REQUEST, 'bad name');
104
105
  const parentNode = parent ? await urlToNodeOriginal(parent) : vfs_1.vfs;
105
106
  if (!parentNode)
@@ -111,7 +112,7 @@ exports.default = {
111
112
  const isFolder = source && await (0, misc_1.isDirectory)(source);
112
113
  if (source && isFolder === undefined)
113
114
  return new apiMiddleware_1.ApiError(const_1.HTTP_NOT_FOUND, 'source not found');
114
- const child = { source, name, ...pickProps(rest, ALLOWED_KEYS) };
115
+ const child = { source, name, ...sanitizeVfsProps(rest) };
115
116
  name = (0, vfs_1.getNodeName)(child); // could be not given as input
116
117
  const ext = (0, path_1.extname)(name);
117
118
  const noExt = ext ? name.slice(0, -ext.length) : name;
@@ -128,6 +129,7 @@ exports.default = {
128
129
  + (isFolder ? '/' : '');
129
130
  return { name, link };
130
131
  },
132
+ // legacy – not currently used by the UI
131
133
  async del_vfs({ uris }) {
132
134
  if (!uris || !Array.isArray(uris))
133
135
  return new apiMiddleware_1.ApiError(const_1.HTTP_BAD_REQUEST, 'bad uris');
@@ -169,7 +171,7 @@ exports.default = {
169
171
  return {};
170
172
  },
171
173
  get_disk_spaces: util_os_1.getDiskSpaces,
172
- get_ls({ path, files, fileMask }, ctx) {
174
+ get_ls({ path, files = true, fileMask }, ctx) {
173
175
  return new SendList_1.SendListReadable({
174
176
  async doAtStart(list) {
175
177
  if (!path && const_1.IS_WINDOWS) {
@@ -253,11 +255,22 @@ exports.default = {
253
255
  function pickProps(o, keys) {
254
256
  const ret = {};
255
257
  if (o && typeof o === 'object')
256
- for (const k of keys)
257
- if (k in o)
258
+ for (const k in o)
259
+ if (keys.includes(k))
258
260
  ret[k] = o[k] === null || o[k] === '' ? undefined : o[k];
259
261
  return ret;
260
262
  }
263
+ function sanitizeVfsProps(props) {
264
+ const ret = pickProps(props, misc_1.VFS_STORED_KEYS);
265
+ if (ret.masks && typeof ret.masks !== 'object')
266
+ ret.masks = undefined;
267
+ if (props?.children === null)
268
+ delete ret.children;
269
+ else if (Array.isArray(props?.children))
270
+ ret.children = !props.children.length ? undefined
271
+ : props.children.map(sanitizeVfsProps);
272
+ return ret;
273
+ }
261
274
  function simplifyName(node) {
262
275
  const { name, ...noName } = node;
263
276
  if ((0, vfs_1.getNodeName)(noName) === name)
@@ -29,10 +29,11 @@ function apiMiddleware(apis) {
29
29
  const params = isPost ? ctx.state.params || {} : ctx.query;
30
30
  const apiName = ctx.path;
31
31
  console.debug('API', ctx.method, apiName, { ...params });
32
- const noBrowser = ctx.get('user-agent')?.startsWith('curl');
33
- const safe = noBrowser || isPost && ctx.get('x-hfs-anti-csrf') // POST is safe because browser will enforce SameSite cookie
34
- || apiName.startsWith('get_'); // "get_" apis are safe because they make no change
35
- if (!safe)
32
+ const csrfSafe = !isPost
33
+ || ctx.get('x-hfs-anti-csrf') // automatic browser actions won't carry this header
34
+ || apiName.startsWith('get_') // "get_" apis are safe because they make no change
35
+ || /^(curl|wget|python|go-|java|axios|postman|httpie|insomnia|bruno)/i.test(ctx.get('user-agent') || ''); // only browser are subject to CSRF
36
+ if (!csrfSafe)
36
37
  return send(const_1.HTTP_FOOL, "missing header x-hfs-anti-csrf=1");
37
38
  const customApiRest = apiName.startsWith(const_1.PLUGIN_CUSTOM_REST_PREFIX) && apiName.slice(const_1.PLUGIN_CUSTOM_REST_PREFIX.length);
38
39
  const apiFun = customApiRest && (0, plugins_1.firstPlugin)(pl => pl.getData().customRest?.[customApiRest])
package/src/auth.js CHANGED
@@ -1,4 +1,37 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
37
  };
@@ -11,20 +44,20 @@ exports.clearTextLogin = clearTextLogin;
11
44
  exports.setLoggedIn = setLoggedIn;
12
45
  const perm_1 = require("./perm");
13
46
  const cross_const_1 = require("./cross-const");
14
- const tssrp6a_1 = require("tssrp6a");
47
+ const srp = __importStar(require("tssrp6a"));
15
48
  const srp_1 = require("./srp");
16
49
  const cross_1 = require("./cross");
17
50
  const expiringCache_1 = require("./expiringCache");
18
51
  const node_crypto_1 = require("node:crypto");
19
52
  const events_1 = __importDefault(require("./events"));
20
- const srp6aNimbusRoutines = new tssrp6a_1.SRPRoutines(new tssrp6a_1.SRPParameters());
53
+ const srp6aNimbusRoutines = new srp.SRPRoutines(new srp.SRPParameters());
21
54
  async function srpServerStep1(account) {
22
55
  if (!account.srp)
23
56
  throw cross_const_1.HTTP_NOT_ACCEPTABLE;
24
57
  const [salt, verifier] = account.srp.split('|');
25
58
  if (!salt || !verifier)
26
59
  throw Error("malformed account");
27
- const srpSession = new tssrp6a_1.SRPServerSession(srp6aNimbusRoutines);
60
+ const srpSession = new srp.SRPServerSession(srp6aNimbusRoutines);
28
61
  const srpServer = await srpSession.step1(account.username, BigInt(salt), BigInt(verifier));
29
62
  return { srpServer, salt, pubKey: String(srpServer.B) }; // cast to string cause bigint can't be jsonized
30
63
  }
@@ -36,7 +69,7 @@ async function srpCheck(username, password) {
36
69
  const k = (0, node_crypto_1.createHash)('sha256').update(username + password + account.srp).digest("hex");
37
70
  const good = await cache.try(k, async () => {
38
71
  const { srpServer, salt, pubKey } = await srpServerStep1(account);
39
- const client = await (0, srp_1.srpClientPart)(username, password, salt, pubKey);
72
+ const client = await (0, srp_1.srpClientPart)(srp, username, password, salt, pubKey);
40
73
  return srpServer.step2(client.A, client.M1).then(() => true, () => false);
41
74
  });
42
75
  return good ? account : undefined;
@@ -65,10 +98,10 @@ async function setLoggedIn(ctx, username) {
65
98
  if (s.username)
66
99
  events_1.default.emit('logout', ctx);
67
100
  delete ctx.state.account;
68
- delete s.username;
69
- delete s.allowNet;
101
+ ctx.session = null;
70
102
  return;
71
103
  }
104
+ delete s.loggingIn; // clear pending SRP handshake state
72
105
  const a = ctx.state.account = (0, perm_1.getAccount)(username);
73
106
  if (!a)
74
107
  return;
package/src/commands.js CHANGED
@@ -19,8 +19,7 @@ const github_1 = require("./github");
19
19
  const cross_1 = require("./cross");
20
20
  const api_monitor_1 = __importDefault(require("./api.monitor"));
21
21
  const argv_1 = require("./argv");
22
- const consoleLog_1 = require("./consoleLog");
23
- const debounceAsync_1 = require("./debounceAsync");
22
+ const listen_2 = require("./listen");
24
23
  if (!argv_1.argv.updating && !config_1.showHelp) {
25
24
  try {
26
25
  // Not sure if the try is necessary for when stdin is unavailable, but someone reported a problem using nohup https://github.com/rejetto/hfs/issues/74 and I've found this example try-catching https://github.com/DefinitelyTyped/DefinitelyTyped/blob/dda83a906914489e09ca28afea12948529015d4a/types/node/readline.d.ts#L489
@@ -29,55 +28,43 @@ if (!argv_1.argv.updating && !config_1.showHelp) {
29
28
  .on('line', x => parseCommandLine(x).then(showPrompt))
30
29
  .on('SIGINT', () => process.emit('SIGINT')); // readline swallows the first ctrl+c unless we forward it to process-level handlers
31
30
  let isClean = true;
32
- let cleaning;
33
- const showPrompt = tty && (0, debounceAsync_1.debounceAsync)(async () => {
34
- await cleaning;
31
+ const showPrompt = tty && lodash_1.default.debounce(() => {
35
32
  if (first_1.quitting || !tty)
36
33
  return;
37
34
  prompter.prompt(true);
38
35
  isClean = false;
39
- }, { wait: 100 });
36
+ }, 100);
40
37
  function clean() {
41
38
  if (isClean)
42
39
  return;
43
- return cleaning ||= new Promise(resolve => {
44
- (0, node_readline_1.cursorTo)(process.stdout, 0, undefined, () => {
45
- resolve();
46
- cleaning = undefined;
47
- isClean = true;
48
- });
49
- });
40
+ // keep console methods synchronous: reposition the cursor immediately and let stream ordering preserve output sequence
41
+ (0, node_readline_1.cursorTo)(process.stdout, 0); // we don't need to clean as long as the prompt is never longer than the printed line
42
+ isClean = true;
50
43
  }
51
44
  showPrompt?.();
52
- // print this hint when we have not been printing anything else for a while, to not get mixed too much
53
- let printHintOnce = tty && lodash_1.default.debounce(() => {
54
- (0, consoleLog_1.consoleHint)("this is an interactive console, you can enter commands");
55
- printHintOnce = undefined; // never more
56
- }, 2000);
57
- setTimeout(() => lodash_1.default.each(console, (v, k) => {
58
- if (!lodash_1.default.isFunction(v))
59
- return;
60
- console[k] = async (...args) => {
45
+ for (const k of ['log', 'warn', 'error', 'debug']) {
46
+ const v = console[k];
47
+ console[k] = (...args) => {
61
48
  if (!first_1.quitting && tty)
62
- await clean();
49
+ clean();
63
50
  try {
64
51
  v(...args);
65
52
  }
66
53
  finally {
67
54
  showPrompt?.();
68
- printHintOnce?.();
69
55
  }
70
56
  };
71
- }), 1000); // avoid messing in making console methods async too soon and so preventing fatal errors to be printed before process.exit – TODO investigate how to avoid this async thing at all
57
+ }
72
58
  }
73
59
  catch {
74
60
  console.log("console commands not available");
75
61
  }
76
62
  }
77
63
  async function parseCommandLine(line) {
78
- if (!line)
64
+ const tokens = Array.from(line.trim().matchAll(/"((?:\\.|[^"\\])*)"|'((?:\\.|[^'\\])*)'|((?:\\.|[^\s"'\\])+)/g)).map(m => (m[1] ?? m[2] ?? m[3] ?? '').replace(/\\([\\ "'"])/g, '$1')); // unescape
65
+ if (!tokens.length)
79
66
  return;
80
- let [name, ...params] = line.trim().split(/ +/);
67
+ let [name, ...params] = tokens;
81
68
  name = aliases[name] || name;
82
69
  let cmd = commands[name];
83
70
  if (cmd?.alias)
@@ -195,6 +182,8 @@ const commands = {
195
182
  status: {
196
183
  params: '',
197
184
  async cb() {
185
+ const ports = await (0, listen_2.getServerStatus)(false);
186
+ console.log(lodash_1.default.map(ports, (x, k) => `${k.toUpperCase()} ${x.configuredPort < 0 ? "disabled" : x.listening ? `on port ${x.port}` : (x.error || "not working")}`).join(" – "));
198
187
  const conn = (await api_monitor_1.default.get_connection_stats().next()).value;
199
188
  if (conn) {
200
189
  const { sent_got: sg } = conn;
package/src/comments.js CHANGED
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.DESCRIPT_ION = void 0;
6
+ exports.DESCRIPT_ION_ALT = exports.DESCRIPT_ION = void 0;
7
7
  exports.usingDescriptIon = usingDescriptIon;
8
8
  exports.getCommentFor = getCommentFor;
9
9
  exports.setCommentFor = setCommentFor;
@@ -17,7 +17,7 @@ const lodash_1 = __importDefault(require("lodash"));
17
17
  const iconv_lite_1 = __importDefault(require("iconv-lite"));
18
18
  const promises_1 = require("node:fs/promises");
19
19
  exports.DESCRIPT_ION = 'descript.ion';
20
- const DESCRIPT_ION_ALT = 'DESCRIPT.ION';
20
+ exports.DESCRIPT_ION_ALT = 'DESCRIPT.ION';
21
21
  const commentsStorage = (0, config_1.defineConfig)(cross_1.CFG.comments_storage, '', v => ['', 'attr+ion'].includes(v)); // compiled tell us if we are using descript.ion
22
22
  (0, config_1.defineConfig)('descript_ion', true, (v, more) => {
23
23
  if (!v && more.version?.olderThan('0.57.0-alpha1'))
@@ -77,7 +77,7 @@ function areCommentsEnabled() {
77
77
  }
78
78
  async function filePathHelper(folder) {
79
79
  const main = (0, path_1.join)(folder, exports.DESCRIPT_ION);
80
- const alt = (0, path_1.join)(folder, DESCRIPT_ION_ALT);
80
+ const alt = (0, path_1.join)(folder, exports.DESCRIPT_ION_ALT);
81
81
  return await (0, util_files_1.exists)(alt) && !await (0, util_files_1.exists)(main) ? alt : main;
82
82
  }
83
83
  const MULTILINE_SUFFIX = Buffer.from([4, 0xC2]);
@@ -102,6 +102,6 @@ async function readDescriptIon(path) {
102
102
  }
103
103
  descriptIonEncoding.sub(() => {
104
104
  for (const k of util_files_1.parseFileCache.keys())
105
- if (k.endsWith(exports.DESCRIPT_ION) || k.endsWith(DESCRIPT_ION_ALT))
105
+ if (k.endsWith(exports.DESCRIPT_ION) || k.endsWith(exports.DESCRIPT_ION_ALT))
106
106
  util_files_1.parseFileCache.delete(k);
107
107
  });
package/src/config.js CHANGED
@@ -181,8 +181,11 @@ const saveDebounced = (0, debounceAsync_1.debounceAsync)(async () => {
181
181
  const aWeekAgo = Date.now() - cross_1.DAY * 7;
182
182
  if (await (0, util_files_1.statWithTimeout)(bak).then(x => aWeekAgo > x.mtimeMs, () => true))
183
183
  await (0, promises_1.copyFile)(filePath, bak).catch(() => { }); // ignore errors
184
- await exports.configFile.save(stringify({ ...state, version: const_1.VERSION }))
185
- .catch(err => console.error('Failed at saving config file, please ensure it is writable.', String(err)));
184
+ await exports.configFile.save(stringify({
185
+ ...state,
186
+ version: const_1.VERSION,
187
+ platform: `${process.platform}-${process.arch}${(0, cross_1.prefix)('-', !const_1.IS_BINARY && (0, path_1.basename)(process.execPath))}`,
188
+ })).catch(err => console.error('Failed at saving config file, please ensure it is writable.', String(err)));
186
189
  });
187
190
  const saveConfigAsap = () => void saveDebounced();
188
191
  exports.saveConfigAsap = saveConfigAsap;
package/src/const.js CHANGED
@@ -36,30 +36,16 @@ var __importStar = (this && this.__importStar) || (function () {
36
36
  var __exportStar = (this && this.__exportStar) || function(m, exports) {
37
37
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
38
38
  };
39
- var __importDefault = (this && this.__importDefault) || function (mod) {
40
- return (mod && mod.__esModule) ? mod : { "default": mod };
41
- };
42
39
  Object.defineProperty(exports, "__esModule", { value: true });
43
- exports.CONFIG_FILE = exports.MIME_AUTO = exports.APP_PATH = exports.IS_BINARY = exports.IS_MAC = exports.IS_WINDOWS = exports.RUNNING_BETA = exports.VERSION = exports.BUILD_TIMESTAMP = exports.HFS_STARTED = exports.ORIGINAL_CWD = exports.DEV = exports.ARGS_FILE = exports.COMPATIBLE_API_VERSION = exports.API_VERSION = void 0;
44
- const minimist_1 = __importDefault(require("minimist"));
40
+ exports.CONFIG_FILE = exports.MIME_AUTO = exports.APP_PATH = exports.IS_BINARY = exports.IS_MAC = exports.IS_WINDOWS = exports.RUNNING_BETA = exports.VERSION = exports.BUILD_TIMESTAMP = exports.HFS_STARTED = exports.ORIGINAL_CWD = exports.DEV = exports.COMPATIBLE_API_VERSION = exports.API_VERSION = void 0;
45
41
  const fs = __importStar(require("fs"));
46
42
  const os_1 = require("os");
47
- const lodash_1 = __importDefault(require("lodash"));
48
43
  const path_1 = require("path");
49
44
  const cross_1 = require("./cross");
50
45
  const argv_1 = require("./argv");
51
46
  __exportStar(require("./cross-const"), exports);
52
- exports.API_VERSION = 12.97;
47
+ exports.API_VERSION = 13;
53
48
  exports.COMPATIBLE_API_VERSION = 1; // the day we break with the past, we'll update this
54
- // you can add arguments with this file, currently used for the update process on mac/linux
55
- exports.ARGS_FILE = (0, path_1.join)((0, os_1.homedir)(), 'hfs-args');
56
- try {
57
- const s = fs.readFileSync(exports.ARGS_FILE, 'utf-8');
58
- console.log('additional arguments', s);
59
- lodash_1.default.defaults(argv_1.argv, (0, minimist_1.default)(JSON.parse(s)));
60
- fs.unlinkSync(exports.ARGS_FILE);
61
- }
62
- catch { }
63
49
  exports.DEV = process.env.DEV ? 'DEV' : '';
64
50
  exports.ORIGINAL_CWD = process.cwd();
65
51
  exports.HFS_STARTED = new Date();
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.HTTP_MESSAGES = exports.HTTP_INSUFFICIENT_STORAGE = exports.HTTP_SERVICE_UNAVAILABLE = exports.HTTP_SERVER_ERROR = exports.HTTP_TOO_MANY_REQUESTS = exports.HTTP_FAILED_DEPENDENCY = exports.HTTP_FOOL = exports.HTTP_RANGE_NOT_SATISFIABLE = exports.HTTP_PAYLOAD_TOO_LARGE = exports.HTTP_PRECONDITION_FAILED = exports.HTTP_CONFLICT = exports.HTTP_NOT_ACCEPTABLE = exports.HTTP_METHOD_NOT_ALLOWED = exports.HTTP_NOT_FOUND = exports.HTTP_FORBIDDEN = exports.HTTP_UNAUTHORIZED = exports.HTTP_BAD_REQUEST = exports.HTTP_NOT_MODIFIED = exports.HTTP_TEMPORARY_REDIRECT = exports.HTTP_MOVED_PERMANENTLY = exports.HTTP_PARTIAL_CONTENT = exports.HTTP_NO_CONTENT = exports.HTTP_OK = exports.EMBEDDED_LANGUAGE = exports.HIDE_IN_TESTS = exports.ALLOW_SESSION_IP_CHANGE = exports.PREVIOUS_TAG = exports.MTIME_CHECK = exports.UPLOAD_TEMP_HASH = exports.HFS_REPO = exports.PLUGIN_CUSTOM_REST_PREFIX = exports.NBSP = exports.PORT_DISABLED = exports.ICONS_URI = exports.PLUGINS_PUB_URI = exports.API_URI = exports.ADMIN_URI = exports.FRONTEND_URI = exports.SPECIAL_URI = void 0;
3
+ exports.HTTP_MESSAGES = exports.HTTP_INSUFFICIENT_STORAGE = exports.HTTP_SERVICE_UNAVAILABLE = exports.HTTP_SERVER_ERROR = exports.HTTP_TOO_MANY_REQUESTS = exports.HTTP_FAILED_DEPENDENCY = exports.HTTP_LOCKED = exports.HTTP_FOOL = exports.HTTP_RANGE_NOT_SATISFIABLE = exports.HTTP_PAYLOAD_TOO_LARGE = exports.HTTP_PRECONDITION_FAILED = exports.HTTP_CONFLICT = exports.HTTP_NOT_ACCEPTABLE = exports.HTTP_METHOD_NOT_ALLOWED = exports.HTTP_NOT_FOUND = exports.HTTP_FORBIDDEN = exports.HTTP_UNAUTHORIZED = exports.HTTP_BAD_REQUEST = exports.HTTP_NOT_MODIFIED = exports.HTTP_TEMPORARY_REDIRECT = exports.HTTP_MOVED_PERMANENTLY = exports.HTTP_PARTIAL_CONTENT = exports.HTTP_NO_CONTENT = exports.HTTP_CREATED = exports.HTTP_OK = exports.EMBEDDED_LANGUAGE = exports.MASK_IN_TESTS = exports.HIDE_IN_TESTS = exports.ALLOW_SESSION_IP_CHANGE = exports.PREVIOUS_TAG = exports.MTIME_CHECK = exports.UPLOAD_TEMP_HASH = exports.HFS_REPO = exports.PLUGIN_CUSTOM_REST_PREFIX = exports.NBSP = exports.PORT_DISABLED = exports.ICONS_URI = exports.PLUGINS_PUB_URI = exports.API_URI = exports.ADMIN_URI = exports.FRONTEND_URI = exports.SPECIAL_URI = void 0;
4
4
  exports.SPECIAL_URI = '/~/';
5
5
  exports.FRONTEND_URI = exports.SPECIAL_URI + 'frontend/';
6
6
  exports.ADMIN_URI = exports.SPECIAL_URI + 'admin/';
@@ -16,8 +16,10 @@ exports.MTIME_CHECK = 'x-mtime-check';
16
16
  exports.PREVIOUS_TAG = 'previous';
17
17
  exports.ALLOW_SESSION_IP_CHANGE = 'allow_session_ip_change';
18
18
  exports.HIDE_IN_TESTS = 'hideInTests'; // elements that have variable size, where masking would produce changes, must be hidden
19
- exports.EMBEDDED_LANGUAGE = 'en'; // frontend includes this language in the code, and not need to import the translation json
19
+ exports.MASK_IN_TESTS = 'maskInTests';
20
+ exports.EMBEDDED_LANGUAGE = 'en'; // frontend includes this language in the code, and not need to import the translation-json
20
21
  exports.HTTP_OK = 200;
22
+ exports.HTTP_CREATED = 201;
21
23
  exports.HTTP_NO_CONTENT = 204;
22
24
  exports.HTTP_PARTIAL_CONTENT = 206;
23
25
  exports.HTTP_MOVED_PERMANENTLY = 301;
@@ -34,6 +36,7 @@ exports.HTTP_PRECONDITION_FAILED = 412;
34
36
  exports.HTTP_PAYLOAD_TOO_LARGE = 413;
35
37
  exports.HTTP_RANGE_NOT_SATISFIABLE = 416;
36
38
  exports.HTTP_FOOL = 418;
39
+ exports.HTTP_LOCKED = 423;
37
40
  exports.HTTP_FAILED_DEPENDENCY = 424;
38
41
  exports.HTTP_TOO_MANY_REQUESTS = 429;
39
42
  exports.HTTP_SERVER_ERROR = 500;
package/src/cross.js CHANGED
@@ -17,7 +17,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
17
17
  return (mod && mod.__esModule) ? mod : { "default": mod };
18
18
  };
19
19
  Object.defineProperty(exports, "__esModule", { value: true });
20
- exports.PERM_KEYS = exports.defaultPerms = exports.WHO_ANY_ACCOUNT = exports.WHO_NO_ONE = exports.WHO_ANYONE = exports.LIST = exports.CFG = exports.THEME_OPTIONS = exports.SORT_BY_OPTIONS = exports.FRONTEND_OPTIONS = exports.MAX_TILE_SIZE = exports.DAY = exports.HOUR = exports.MINUTE = exports.WIKI_URL = exports.REPO_URL = exports.WEBSITE = void 0;
20
+ exports.VFS_STORED_KEYS = exports.PERM_KEYS = exports.defaultPerms = exports.WHO_ANY_ACCOUNT = exports.WHO_NO_ONE = exports.WHO_ANYONE = exports.LIST = exports.CFG = exports.THEME_OPTIONS = exports.SORT_BY_OPTIONS = exports.FRONTEND_OPTIONS = exports.MAX_TILE_SIZE = exports.DAY = exports.HOUR = exports.MINUTE = exports.WIKI_URL = exports.REPO_URL = exports.WEBSITE = void 0;
21
21
  exports.isWhoObject = isWhoObject;
22
22
  exports.formatBytes = formatBytes;
23
23
  exports.formatSpeed = formatSpeed;
@@ -44,8 +44,6 @@ exports.wantArray = wantArray;
44
44
  exports._log = _log;
45
45
  exports._dbg = _dbg;
46
46
  exports.pendingPromise = pendingPromise;
47
- exports.basename = basename;
48
- exports.dirname = dirname;
49
47
  exports.tryJson = tryJson;
50
48
  exports.swap = swap;
51
49
  exports.isOrderedEqual = isOrderedEqual;
@@ -59,6 +57,7 @@ exports.typedKeys = typedKeys;
59
57
  exports.typedEntries = typedEntries;
60
58
  exports.hasProp = hasProp;
61
59
  exports.throw_ = throw_;
60
+ exports.isAsyncIterable = isAsyncIterable;
62
61
  exports.filterMapGenerator = filterMapGenerator;
63
62
  exports.asyncGeneratorToArray = asyncGeneratorToArray;
64
63
  exports.repeat = repeat;
@@ -109,6 +108,7 @@ exports.MAX_TILE_SIZE = 10;
109
108
  exports.FRONTEND_OPTIONS = {
110
109
  file_menu_on_link: true,
111
110
  tile_size: 0,
111
+ page_size: 100,
112
112
  sort_by: 'name',
113
113
  invert_order: false,
114
114
  folders_first: true,
@@ -125,7 +125,7 @@ exports.CFG = constMap(['geo_enable', 'geo_allow', 'geo_list', 'geo_allow_unknow
125
125
  'log', 'error_log', 'log_rotation', 'dont_log_net', 'log_gui', 'log_api', 'log_ua', 'log_spam', 'track_ips',
126
126
  'max_downloads', 'max_downloads_per_ip', 'max_downloads_per_account', 'roots', 'force_address', 'split_uploads',
127
127
  'force_lang', 'suspend_plugins', 'base_url', 'size_1024', 'disable_custom_html', 'comments_storage',
128
- 'outbound_proxy']);
128
+ 'force_webdav_login', 'webdav_initial_auth', 'outbound_proxy']);
129
129
  exports.LIST = { add: '+', remove: '-', update: '=', props: 'props', ready: 'ready', error: 'e' };
130
130
  exports.WHO_ANYONE = true;
131
131
  exports.WHO_NO_ONE = false;
@@ -139,6 +139,8 @@ exports.defaultPerms = {
139
139
  can_archive: 'can_read'
140
140
  };
141
141
  exports.PERM_KEYS = typedKeys(exports.defaultPerms);
142
+ exports.VFS_STORED_KEYS = ['name', 'source', 'masks', 'default', 'accept', 'rename',
143
+ 'mime', 'url', 'target', 'comment', 'icon', 'order', 'children', ...exports.PERM_KEYS];
142
144
  function constMap(a) {
143
145
  return Object.fromEntries(a.map(x => [x, x]));
144
146
  }
@@ -256,12 +258,6 @@ function pendingPromise() {
256
258
  const ret = new Promise((resolve, reject) => takeOut = { resolve, reject });
257
259
  return Object.assign(ret, takeOut);
258
260
  }
259
- function basename(path) {
260
- return path.match(/([^\\/]+)[\\/]*$/)?.[1] || '';
261
- }
262
- function dirname(path) {
263
- return path.slice(0, Math.max(0, path.lastIndexOf('/', path.length - 1)));
264
- }
265
261
  function tryJson(s, except) {
266
262
  try {
267
263
  return s && JSON.parse(s);
@@ -328,6 +324,9 @@ async function waitFor(cb, { interval = 200, timeout = Infinity } = {}) {
328
324
  }
329
325
  }
330
326
  function getOrSet(o, k, creator) {
327
+ if (o instanceof Map)
328
+ return o.get(k)
329
+ || with_(creator(), x => o.set(k, x) && x);
331
330
  return k in o ? o[k]
332
331
  : (o[k] = creator());
333
332
  }
@@ -359,6 +358,9 @@ function hasProp(obj, key) {
359
358
  function throw_(err) {
360
359
  throw err;
361
360
  }
361
+ function isAsyncIterable(iterable) {
362
+ return Symbol.asyncIterator in iterable;
363
+ }
362
364
  async function* filterMapGenerator(generator, filterMap) {
363
365
  for await (const x of generator) {
364
366
  const res = await filterMap(x);
@@ -449,8 +451,8 @@ async function promiseBestEffort(promises) {
449
451
  return res.filter(x => x.status === 'fulfilled').map((x) => x.value);
450
452
  }
451
453
  // encode paths leaving / separator unencoded (not like encodeURIComponent), but still encode #
452
- function pathEncode(s) {
453
- return s.replace(/[:&#'"% ?\\]/g, escape); // escape() is not utf8, but we are encoding only ascii chars
454
+ function pathEncode(s, all = false) {
455
+ return all ? encodeURI(s).replace(/#/g, escape) : s.replace(/[:&#'"% ?\\]/g, escape); // escape() is not utf8, but we are encoding only ascii chars
454
456
  }
455
457
  function pathDecode(s) { return decodeURI(s).replace(/%23/g, '#'); }
456
458
  // run at a specific point in time, also solving the limit of setTimeout, which doesn't work with +32bit delays
@@ -498,11 +500,12 @@ function inCommon(a, b) {
498
500
  i++;
499
501
  return i;
500
502
  }
501
- function mapFilter(arr, map, filter = (x) => x === undefined, invert = false) {
503
+ function mapFilter(arr, map, filter, invert = false) {
504
+ const keep = filter ?? ((x) => x !== undefined);
502
505
  return arr[invert ? 'reduceRight' : 'reduce']((ret, x, idx) => {
503
506
  const y = map(x, idx);
504
- if (filter(y))
505
- ret.push(y); // push is much faster than unshift, therefore invert using reduceRight https://measurethat.net/Benchmarks/Show/29/0/array-push-vs-unshift
507
+ if (keep(y))
508
+ ret.push(y); // push is much faster than unshift, therefore, invert using reduceRight https://measurethat.net/Benchmarks/Show/29/0/array-push-vs-unshift
506
509
  return ret;
507
510
  }, []);
508
511
  }
@@ -573,4 +576,7 @@ const BROWSERS = {
573
576
  PS: /playstation/i,
574
577
  Xbox: /xbox/i,
575
578
  UC: /UCBrowser/i,
579
+ Finder: /WebDAVFS.+Darwin|WebDAVLib/,
580
+ Cyberduck: /^Cyberduck/,
581
+ ForkLift: /^ForkLift/,
576
582
  };