hfs 3.2.2 → 3.3.0-beta2

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 (268) hide show
  1. package/admin/assets/AccountsPage-DB7ljNHT.js +3 -0
  2. package/admin/assets/ArrayField-Qj2iHD7I.js +2 -0
  3. package/admin/assets/ConfigFilePage-TErmt0PK.js +4 -0
  4. package/admin/assets/CustomHtmlPage-CVmk-_JS.js +2 -0
  5. package/admin/assets/DataTable-DmnQXyFO.js +119 -0
  6. package/admin/assets/DateTimeField-BUWd2w9-.js +1 -0
  7. package/admin/assets/EventManager-9vwKg8as.js +1 -0
  8. package/admin/assets/FileField-DoBaSTxF.js +117 -0
  9. package/admin/assets/InternetPage-Biuer1tb.js +8 -0
  10. package/admin/assets/LangPage-Vd24DNK5.js +2 -0
  11. package/admin/assets/LogsPage-BdvttEqM.js +3 -0
  12. package/admin/assets/MenuButton-CHLgqU5W.js +1 -0
  13. package/admin/assets/MonitorPage-DlXkZUmT.js +2 -0
  14. package/admin/assets/OptionsPage-Zi8FmrjE.js +3 -0
  15. package/admin/assets/PluginsPage-BzwEIFt5.js +1 -0
  16. package/admin/assets/Tabs-CVipqhB9.js +1 -0
  17. package/admin/assets/TextEditor-BeS-mR2I.css +1 -0
  18. package/admin/assets/TextEditor-clbVugYM.js +34 -0
  19. package/admin/assets/VfsPathField-YUCV9PfL.js +1 -0
  20. package/admin/assets/{af-BDoqNBMg.js → af-B1Gi_bpo.js} +1 -1
  21. package/admin/assets/agentIcons-DW9QViyx.js +1 -0
  22. package/admin/assets/{am-DXBvKJ3X.js → am-B-dZnhsM.js} +1 -1
  23. package/admin/assets/{ar-BJIoxKTh.js → ar-DsQGp6kZ.js} +1 -1
  24. package/admin/assets/{ar-dz-C9l3uc_3.js → ar-dz-CxlYiKtP.js} +1 -1
  25. package/admin/assets/{ar-iq-DKH8u2lX.js → ar-iq-y4_Puo4B.js} +1 -1
  26. package/admin/assets/{ar-kw-D3gJalQp.js → ar-kw-DTOZ0VC7.js} +1 -1
  27. package/admin/assets/{ar-ly-BZJzWFeR.js → ar-ly-lPV9gApv.js} +1 -1
  28. package/admin/assets/{ar-ma-DabiOCr0.js → ar-ma-DZqLSpeB.js} +1 -1
  29. package/admin/assets/{ar-sa-C7suzSCY.js → ar-sa-v-5vsIOR.js} +1 -1
  30. package/admin/assets/{ar-tn-BvBucEx0.js → ar-tn-a4q8lhXy.js} +1 -1
  31. package/admin/assets/{az-CPUppH2M.js → az-Cj4yq-j-.js} +1 -1
  32. package/admin/assets/baseUrl-Do5CYuBZ.js +2 -0
  33. package/admin/assets/{be-vzvhX2dl.js → be-B-3QlFM8.js} +1 -1
  34. package/admin/assets/{bg-09Xbj_Y3.js → bg-A8-93xdK.js} +1 -1
  35. package/admin/assets/{bi-CvhiuiE9.js → bi-bwwEWGG2.js} +1 -1
  36. package/admin/assets/{bm-DtJAZAkZ.js → bm-DpLmtYXC.js} +1 -1
  37. package/admin/assets/{bn-Dnzh2x6I.js → bn-DPL_BgLw.js} +1 -1
  38. package/admin/assets/{bn-bd-xEy4797g.js → bn-bd-DukmY_R5.js} +1 -1
  39. package/admin/assets/{bo-vuPmptG3.js → bo-68KDEKGI.js} +1 -1
  40. package/admin/assets/{br-C9xH4OD3.js → br-gA86uwqY.js} +1 -1
  41. package/admin/assets/{bs-BB_uCUp1.js → bs-SfthSp42.js} +1 -1
  42. package/admin/assets/{ca-D7LKaf98.js → ca-8qUtZKFe.js} +1 -1
  43. package/admin/assets/{cs-DMFTNdNC.js → cs-CTHcqPCX.js} +1 -1
  44. package/admin/assets/{cv-DNUjJwnO.js → cv-BhBW7hcO.js} +1 -1
  45. package/admin/assets/{cy-qmAOTPwC.js → cy-BYTS4PNY.js} +1 -1
  46. package/admin/assets/{da-DDX54iM9.js → da-BiwfOrRd.js} +1 -1
  47. package/admin/assets/{de-BBmlsfbM.js → de-BFqyDxvo.js} +1 -1
  48. package/admin/assets/{de-at-CuMZqYfu.js → de-at-C7zUXXVL.js} +1 -1
  49. package/admin/assets/{de-ch-s8OXKb-5.js → de-ch-BVHosAzt.js} +1 -1
  50. package/admin/assets/dist-DC2A6cD2.js +1 -0
  51. package/admin/assets/{dv-Cjs3QDBN.js → dv-dvig99nB.js} +1 -1
  52. package/admin/assets/{el-BsAOrUDP.js → el-BtJcYjoT.js} +1 -1
  53. package/admin/assets/en-B26lXzkx.js +1 -0
  54. package/admin/assets/{en-au-8tMHM2OT.js → en-au-CWzJ565h.js} +1 -1
  55. package/admin/assets/{en-ca-c9jM4M_8.js → en-ca-nou5bZ6q.js} +1 -1
  56. package/admin/assets/{en-in-D2ULzXMp.js → en-gb-kl3giCnh.js} +1 -1
  57. package/admin/assets/{en-ie-D4_e3kV6.js → en-ie-C55e3apX.js} +1 -1
  58. package/admin/assets/{en-il-BoaZOven.js → en-il-HYabE6j7.js} +1 -1
  59. package/admin/assets/{en-tt-Cn72OR4N.js → en-in-Bri93cNM.js} +1 -1
  60. package/admin/assets/{en-nz-grrmB3dg.js → en-nz-BqhpzeuX.js} +1 -1
  61. package/admin/assets/{en-sg-Cmqxpoir.js → en-sg-q8xv-C8V.js} +1 -1
  62. package/admin/assets/{en-gb-unFIXx9f.js → en-tt-BqzQXPA5.js} +1 -1
  63. package/admin/assets/{eo-Cqxmc0TT.js → eo-5Y962E4S.js} +1 -1
  64. package/admin/assets/{es-CkjKdFZ3.js → es-DOQ7swrW.js} +1 -1
  65. package/admin/assets/{es-do-CTcTshup.js → es-do-Diob7juh.js} +1 -1
  66. package/admin/assets/{es-mx-DMXgMMxs.js → es-mx-miy7RFDh.js} +1 -1
  67. package/admin/assets/{es-pr-DNCV91L3.js → es-pr-CZa5Iw2n.js} +1 -1
  68. package/admin/assets/{es-us-C7o2mlIH.js → es-us-BX03CBQf.js} +1 -1
  69. package/admin/assets/{esm-DvUbRuYx.js → esm-Dtaf0rWK.js} +1 -1
  70. package/admin/assets/{et-DaPpH-gK.js → et-DGWOmMlC.js} +1 -1
  71. package/admin/assets/{eu-DfKyFruu.js → eu-D1Qj8RMh.js} +1 -1
  72. package/admin/assets/{fa-xWrBjePb.js → fa--TfwKnl9.js} +1 -1
  73. package/admin/assets/{fi-BOWDMsDS.js → fi-Dcbkv925.js} +1 -1
  74. package/admin/assets/{fo-B3FupW8R.js → fo-BPGX_WF4.js} +1 -1
  75. package/admin/assets/{fr-DZBDBkwp.js → fr-CNsDHzNh.js} +1 -1
  76. package/admin/assets/{fr-ca-CRePPJJ5.js → fr-ca-BsNs3KIJ.js} +1 -1
  77. package/admin/assets/{fr-ch-pFKvYU8D.js → fr-ch-BBmdtvlB.js} +1 -1
  78. package/admin/assets/{fy-0k7RzHUH.js → fy-q3UE-mqp.js} +1 -1
  79. package/admin/assets/{ga-D31rB2ys.js → ga-C-DOgnYh.js} +1 -1
  80. package/admin/assets/{gd-CbgY-FFE.js → gd-mLMfry_l.js} +1 -1
  81. package/admin/assets/{gl-DrtvS9gt.js → gl-CO8Bj9I_.js} +1 -1
  82. package/admin/assets/{gom-latn-Dkke3GyE.js → gom-latn-myglMmHV.js} +1 -1
  83. package/admin/assets/{gu-BlEipYhR.js → gu-Bdz1OpMU.js} +1 -1
  84. package/admin/assets/{he-BrHT6OLB.js → he-C4lqk2AA.js} +1 -1
  85. package/admin/assets/{hi-Bx0zlAgr.js → hi-h0Byc_UN.js} +1 -1
  86. package/admin/assets/{hr-CoFYGbr6.js → hr-CZV7Za1n.js} +1 -1
  87. package/admin/assets/{ht-Df5xKo4a.js → ht-Dg2blNvl.js} +1 -1
  88. package/admin/assets/{hu-BFTN3q6-.js → hu-DbOVhd9K.js} +1 -1
  89. package/admin/assets/{hy-am-DuZTJQed.js → hy-am-E48Q7kWE.js} +1 -1
  90. package/admin/assets/icons-3rupj9Xr.js +1 -0
  91. package/admin/assets/{id-DBZ5nPkf.js → id-Cd4yWevW.js} +1 -1
  92. package/admin/assets/{index-eeRX25da.css → index-11n5z0Ez.css} +1 -1
  93. package/admin/assets/index-Dsq-sVu9.js +477 -0
  94. package/admin/assets/{is-CmeHm47B.js → is-BJZYSfrA.js} +1 -1
  95. package/admin/assets/{it-Cv3fjOA9.js → it-BRaqqFz4.js} +1 -1
  96. package/admin/assets/{it-ch-DCTyHA3T.js → it-ch-BkLqxaff.js} +1 -1
  97. package/admin/assets/{ja-DHNVXAM5.js → ja-X_I-25cD.js} +1 -1
  98. package/admin/assets/{jv-BdNIxhWv.js → jv-BBBx3R3v.js} +1 -1
  99. package/admin/assets/{ka-D-joD0QB.js → ka-D9Yrujqk.js} +1 -1
  100. package/admin/assets/{kk-8wRNNjxz.js → kk-Bz450_o8.js} +1 -1
  101. package/admin/assets/{km-dUWOg1uK.js → km-CKOAqvHM.js} +1 -1
  102. package/admin/assets/{kn-CwQbzel0.js → kn-k2xTBR7a.js} +1 -1
  103. package/admin/assets/{ko-D_gn9Sfw.js → ko-BCvoCYib.js} +1 -1
  104. package/admin/assets/{ku-Dh3MRML3.js → ku-D6Rloctr.js} +1 -1
  105. package/admin/assets/{ky-CWYuRvil.js → ky-C54qnEzk.js} +1 -1
  106. package/admin/assets/{lb-Cc2xsSIx.js → lb-y3rkrWB2.js} +1 -1
  107. package/admin/assets/{lo-CkwNFDBz.js → lo-nA_dPnOU.js} +1 -1
  108. package/admin/assets/{lt-HWyFDLXu.js → lt-hjPmCCML.js} +1 -1
  109. package/admin/assets/{lv-C7Zx3OLO.js → lv-Bh4qmUa_.js} +1 -1
  110. package/admin/assets/{me-DH3AqnfF.js → me-e32suC_n.js} +1 -1
  111. package/admin/assets/{mi-DMmUry6m.js → mi-Dwbsuyr9.js} +1 -1
  112. package/admin/assets/{mk-D6MNZrzX.js → mk-DjUXwKRn.js} +1 -1
  113. package/admin/assets/{ml-B_ur8Zqf.js → ml-CWjFAViF.js} +1 -1
  114. package/admin/assets/{mn-DeL8Ry7x.js → mn-BU4qTvEl.js} +1 -1
  115. package/admin/assets/{mr-C01qRXFL.js → mr-Bvnduzfb.js} +1 -1
  116. package/admin/assets/{ms-DFUZJzOm.js → ms-XuKVAni7.js} +1 -1
  117. package/admin/assets/{ms-my-CUYHkebs.js → ms-my-CDbnYp0g.js} +1 -1
  118. package/admin/assets/{mt-CE8t5jSj.js → mt-PDuxJf8J.js} +1 -1
  119. package/admin/assets/{my-Df96A8jZ.js → my-7N6SHnsD.js} +1 -1
  120. package/admin/assets/{nb-D0837ewu.js → nb-Cu3KUtTR.js} +1 -1
  121. package/admin/assets/{ne-BdK5TR0R.js → ne-CYW0uI2a.js} +1 -1
  122. package/admin/assets/{nl-oYKmSma6.js → nl-DL7cw699.js} +1 -1
  123. package/admin/assets/{nl-be-BfVC0cur.js → nl-be-B3NSF-2w.js} +1 -1
  124. package/admin/assets/{nn-IEUPnyc8.js → nn-BHITVkGB.js} +1 -1
  125. package/admin/assets/{oc-lnc-g_wSIROr.js → oc-lnc-dp3c4Bty.js} +1 -1
  126. package/admin/assets/{pa-in-gWhcLmZE.js → pa-in-BxgIlP1T.js} +1 -1
  127. package/admin/assets/{pl-H3-LoxVn.js → pl-GrG6yjkB.js} +1 -1
  128. package/admin/assets/{pt-br-B8UcNR6_.js → pt-br-BxTgeF95.js} +1 -1
  129. package/admin/assets/{pt-hiX8RqVw.js → pt-cVbj6hL6.js} +1 -1
  130. package/admin/assets/{rn-BKupViLr.js → rn-DiVJ2_Jy.js} +1 -1
  131. package/admin/assets/{ro-DmhgIvml.js → ro-D1WeRyXR.js} +1 -1
  132. package/admin/assets/rolldown-runtime-CacB07dV.js +1 -0
  133. package/admin/assets/routing-Cjyek7O_.js +1 -0
  134. package/admin/assets/{ru-CcpO-b8g.js → ru-DZCu4V9W.js} +1 -1
  135. package/admin/assets/{rw-DWX_5ZK0.js → rw-DfFpVc_g.js} +1 -1
  136. package/admin/assets/{sd-Dat8YgLw.js → sd-yDyBYxtQ.js} +1 -1
  137. package/admin/assets/{se-nTBYCwx3.js → se-EJKibocp.js} +1 -1
  138. package/admin/assets/sha512-DJtGRwVu.js +1 -0
  139. package/admin/assets/{si-DG88w5El.js → si-BCBV00rO.js} +1 -1
  140. package/admin/assets/{sk-s5FxW36J.js → sk-B2VvG_mo.js} +1 -1
  141. package/admin/assets/{sl-B-HyGrpA.js → sl-BTYmt65M.js} +1 -1
  142. package/admin/assets/{sq-DPFtfEC8.js → sq-BaLGKAHu.js} +1 -1
  143. package/admin/assets/{sr-bBPg1zz4.js → sr-DarE-95b.js} +1 -1
  144. package/admin/assets/{sr-cyrl-cXkYHMcP.js → sr-cyrl-CrwXFtkw.js} +1 -1
  145. package/admin/assets/{ss-7nSqXJN7.js → ss-CbBe1RUs.js} +1 -1
  146. package/admin/assets/{sv-B8mG1QK4.js → sv-Baw7Je9j.js} +1 -1
  147. package/admin/assets/{sv-fi-CotGRXSH.js → sv-fi-CVHORXkw.js} +1 -1
  148. package/admin/assets/{sw-fAxU-Uck.js → sw-k1H_OzIi.js} +1 -1
  149. package/admin/assets/{ta-Dl0Z1pan.js → ta-Bc4ZaZT9.js} +1 -1
  150. package/admin/assets/{te-DmcKasFF.js → te-ClciACZi.js} +1 -1
  151. package/admin/assets/{tet-D6mmvYpQ.js → tet-B75w1oSG.js} +1 -1
  152. package/admin/assets/{tg-39Hf2-oO.js → tg-CuH2ARRk.js} +1 -1
  153. package/admin/assets/{th-BSmTJSFN.js → th-LvExAoJ6.js} +1 -1
  154. package/admin/assets/{tk-m85E5igC.js → tk-2CFwTMKo.js} +1 -1
  155. package/admin/assets/{tl-ph-BlYxVvNt.js → tl-ph-CNJ_lViV.js} +1 -1
  156. package/admin/assets/{tlh-D1POnIeE.js → tlh-9UbKQkHo.js} +1 -1
  157. package/admin/assets/{tr-BurtfrLy.js → tr-Cu4P4OMe.js} +1 -1
  158. package/admin/assets/{tzl-BvyD0lOf.js → tzl-D97WsZW-.js} +1 -1
  159. package/admin/assets/{tzm-DZHS0dK6.js → tzm-CURkYgMY.js} +1 -1
  160. package/admin/assets/{tzm-latn-yNW7CNCH.js → tzm-latn-BRGsWK-9.js} +1 -1
  161. package/admin/assets/{ug-cn-rxs2pf5Y.js → ug-cn-Cd4exKOc.js} +1 -1
  162. package/admin/assets/{uk-CgZM-NnA.js → uk-DEXM3PIH.js} +1 -1
  163. package/admin/assets/{ur-YxIR8yYD.js → ur-DpUycj07.js} +1 -1
  164. package/admin/assets/{uz-CE9QsQMG.js → uz-CznjzufA.js} +1 -1
  165. package/admin/assets/{uz-latn-DiVdSW6G.js → uz-latn-Baga58FN.js} +1 -1
  166. package/admin/assets/{vi-DKARV6qf.js → vi-BrZWcL2C.js} +1 -1
  167. package/admin/assets/{x-pseudo-BuAdOrXQ.js → x-pseudo-BY6J4I7_.js} +1 -1
  168. package/admin/assets/{yo-BcB85DhC.js → yo-Dkeaym0x.js} +1 -1
  169. package/admin/assets/{zh-DLmxfxzl.js → zh-C2fOZUKR.js} +1 -1
  170. package/admin/assets/{zh-cn-ILRADZJi.js → zh-cn-CiA7hMZm.js} +1 -1
  171. package/admin/assets/{zh-hk-fT7fQk9_.js → zh-hk-EkoniWh0.js} +1 -1
  172. package/admin/assets/{zh-tw-NqRXGP6v.js → zh-tw-KDgos-kB.js} +1 -1
  173. package/admin/index.html +3 -2
  174. package/frontend/assets/{dist-legacy-BPToXNXu.js → dist-legacy-BNFW04Ss.js} +1 -1
  175. package/frontend/assets/index-legacy-2akkos6t.js +1 -0
  176. package/frontend/assets/{lib-legacy-CBk-_G90.js → lib-legacy-CO5spnaN.js} +1 -1
  177. package/frontend/assets/{sha512-legacy-CWrR2rkQ.js → sha512-legacy-BuJAJxVV.js} +1 -1
  178. package/frontend/index.html +1 -1
  179. package/npm-shrinkwrap.json +6 -6
  180. package/package.json +1 -1
  181. package/src/AsapStream.js +18 -14
  182. package/src/SendList.js +42 -16
  183. package/src/ThrottledStream.js +3 -3
  184. package/src/acme.js +23 -10
  185. package/src/adminApis.js +7 -6
  186. package/src/api.accounts.js +11 -7
  187. package/src/api.auth.js +8 -5
  188. package/src/api.cert.js +1 -1
  189. package/src/api.get_file_list.js +14 -11
  190. package/src/api.lang.js +3 -2
  191. package/src/api.monitor.js +1 -1
  192. package/src/api.net.js +3 -1
  193. package/src/api.plugins.js +2 -0
  194. package/src/api.vfs.js +9 -12
  195. package/src/apiMiddleware.js +5 -1
  196. package/src/basicWeb.js +3 -2
  197. package/src/block.js +1 -1
  198. package/src/commands.js +6 -5
  199. package/src/comments.js +29 -13
  200. package/src/config.js +7 -4
  201. package/src/consoleLog.js +14 -12
  202. package/src/const.js +1 -1
  203. package/src/cross-const.js +27 -1
  204. package/src/cross.js +37 -34
  205. package/src/ddns.js +1 -4
  206. package/src/events.js +1 -4
  207. package/src/fileAttr.js +1 -1
  208. package/src/frontEndApis.js +7 -3
  209. package/src/geo.js +8 -2
  210. package/src/github.js +10 -9
  211. package/src/index.js +2 -1
  212. package/src/ips.js +24 -3
  213. package/src/langs/hfs-lang-ar.json +1 -0
  214. package/src/langs/hfs-lang-bg.json +1 -0
  215. package/src/langs/hfs-lang-de.json +1 -0
  216. package/src/langs/hfs-lang-el.json +1 -0
  217. package/src/langs/hfs-lang-es.json +1 -0
  218. package/src/langs/hfs-lang-fi.json +1 -0
  219. package/src/langs/hfs-lang-fr.json +1 -0
  220. package/src/langs/hfs-lang-hu.json +1 -0
  221. package/src/langs/hfs-lang-it.json +1 -0
  222. package/src/langs/hfs-lang-ja.json +1 -0
  223. package/src/langs/hfs-lang-ko.json +1 -0
  224. package/src/langs/hfs-lang-lt.json +1 -0
  225. package/src/langs/hfs-lang-ms.json +1 -0
  226. package/src/langs/hfs-lang-nl.json +1 -0
  227. package/src/langs/hfs-lang-pl.json +1 -0
  228. package/src/langs/hfs-lang-pt-br.json +1 -0
  229. package/src/langs/hfs-lang-ro.json +1 -0
  230. package/src/langs/hfs-lang-ru.json +1 -0
  231. package/src/langs/hfs-lang-sr-latn.json +1 -0
  232. package/src/langs/hfs-lang-sr.json +1 -0
  233. package/src/langs/hfs-lang-th.json +1 -0
  234. package/src/langs/hfs-lang-tr.json +1 -0
  235. package/src/langs/hfs-lang-uk.json +1 -0
  236. package/src/langs/hfs-lang-vi.json +1 -0
  237. package/src/langs/hfs-lang-zh-tw.json +1 -0
  238. package/src/langs/hfs-lang-zh.json +1 -0
  239. package/src/listen.js +17 -13
  240. package/src/log.js +11 -2
  241. package/src/middlewares.js +4 -4
  242. package/src/misc.js +3 -3
  243. package/src/multipartUpload.js +1 -2
  244. package/src/nat.js +1 -1
  245. package/src/outboundProxy.js +7 -0
  246. package/src/perm.js +5 -3
  247. package/src/plugins.js +60 -37
  248. package/src/selfCheck.js +4 -3
  249. package/src/serveFile.js +3 -3
  250. package/src/serveGuiAndSharedFiles.js +7 -6
  251. package/src/serveGuiFiles.js +15 -2
  252. package/src/serverCode.js +27 -0
  253. package/src/throttler.js +3 -2
  254. package/src/update.js +9 -3
  255. package/src/upload.js +29 -11
  256. package/src/uploadOwners.js +95 -0
  257. package/src/util-files.js +4 -2
  258. package/src/util-http.js +3 -1
  259. package/src/vfs.js +67 -30
  260. package/src/walkDir.js +24 -11
  261. package/src/watchLoad.js +13 -2
  262. package/src/webdav.js +33 -31
  263. package/src/zip.js +1 -1
  264. package/admin/assets/dist-CHP3cW_n.js +0 -1
  265. package/admin/assets/en-DQ460ET7.js +0 -1
  266. package/admin/assets/index-BGIe1xaR.js +0 -760
  267. package/admin/assets/sha512-CZz40GwW.js +0 -1
  268. package/frontend/assets/index-legacy-CmusDwvl.js +0 -1
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.VFS_STORED_KEYS = exports.PERM_KEYS = exports.defaultPerms = exports.WHO_ADMIN = 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_ADMIN = exports.WHO_ANY_ACCOUNT = exports.WHO_NO_ONE = exports.WHO_ANYONE = exports.LIST = 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;
@@ -26,6 +26,7 @@ exports.join = join;
26
26
  exports.wait = wait;
27
27
  exports.haveTimeout = haveTimeout;
28
28
  exports.objFromKeys = objFromKeys;
29
+ exports.hasFinalSlash = hasFinalSlash;
29
30
  exports.enforceFinal = enforceFinal;
30
31
  exports.removeFinal = removeFinal;
31
32
  exports.enforceStarting = enforceStarting;
@@ -92,6 +93,7 @@ exports.safeDecodeURIComponent = safeDecodeURIComponent;
92
93
  exports.popKey = popKey;
93
94
  exports.patchKey = patchKey;
94
95
  exports.retry = retry;
96
+ exports.callAsPromise = callAsPromise;
95
97
  exports.toMutable = toMutable;
96
98
  exports.shortenAgent = shortenAgent;
97
99
  // This file is part of HFS - Copyright 2021-2023, Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt
@@ -108,26 +110,21 @@ exports.HOUR = 60 * exports.MINUTE;
108
110
  exports.DAY = 24 * exports.HOUR;
109
111
  exports.MAX_TILE_SIZE = 10;
110
112
  exports.FRONTEND_OPTIONS = {
111
- file_menu_on_link: true,
112
- tile_size: 0,
113
- page_size: 100,
114
- sort_by: 'name',
115
- invert_order: false,
116
- folders_first: true,
117
- sort_numerics: false,
118
- title_with_path: true,
119
- theme: '',
120
- auto_play_seconds: 5,
121
- disableTranslation: false,
113
+ [cross_const_1.CFG.file_menu_on_link]: true,
114
+ [cross_const_1.CFG.menu_at_top]: false,
115
+ [cross_const_1.CFG.tile_size]: 0,
116
+ [cross_const_1.CFG.page_size]: 100,
117
+ [cross_const_1.CFG.sort_by]: 'name',
118
+ [cross_const_1.CFG.invert_order]: false,
119
+ [cross_const_1.CFG.folders_first]: true,
120
+ [cross_const_1.CFG.sort_numerics]: false,
121
+ [cross_const_1.CFG.title_with_path]: true,
122
+ [cross_const_1.CFG.theme]: '',
123
+ [cross_const_1.CFG.auto_play_seconds]: 5,
124
+ [cross_const_1.CFG.disableTranslation]: false,
122
125
  };
123
126
  exports.SORT_BY_OPTIONS = ['name', 'extension', 'size', 'time', 'creation'];
124
127
  exports.THEME_OPTIONS = { auto: '', light: 'light', dark: 'dark' };
125
- // had found an interesting way to infer a type from all the calls to defineConfig (by the literals passed), but would not be usable also by admin-panel
126
- exports.CFG = constMap(['geo_enable', 'geo_allow', 'geo_list', 'geo_allow_unknown', 'dynamic_dns_url',
127
- 'log', 'error_log', 'log_rotation', 'dont_log_net', 'log_gui', 'log_api', 'log_ua', 'log_spam', 'track_ips',
128
- 'max_downloads', 'max_downloads_per_ip', 'max_downloads_per_account', 'roots', 'force_address', 'split_uploads',
129
- 'force_lang', 'suspend_plugins', 'base_url', 'size_1024', 'disable_custom_html', 'comments_storage',
130
- 'force_webdav_login', 'webdav_initial_auth', 'outbound_proxy', 'mapped_port', 'upnp_enabled', 'show_uploader']);
131
128
  exports.LIST = { add: '+', remove: '-', update: '=', props: 'props', ready: 'ready', error: 'e' };
132
129
  exports.WHO_ANYONE = true;
133
130
  exports.WHO_NO_ONE = false;
@@ -143,10 +140,7 @@ exports.defaultPerms = {
143
140
  };
144
141
  exports.PERM_KEYS = typedKeys(exports.defaultPerms);
145
142
  exports.VFS_STORED_KEYS = ['name', 'source', 'masks', 'default', 'accept', 'rename',
146
- 'mime', 'url', 'target', 'comment', 'icon', 'order', 'children', ...exports.PERM_KEYS];
147
- function constMap(a) {
148
- return Object.fromEntries(a.map(x => [x, x]));
149
- }
143
+ 'mime', 'url', 'target', 'comment', 'icon', 'order', 'see_without_probing', 'children', ...exports.PERM_KEYS];
150
144
  function isWhoObject(v) {
151
145
  return v !== null && typeof v === 'object' && !Array.isArray(v);
152
146
  }
@@ -190,13 +184,16 @@ function haveTimeout(ms, job, error) {
190
184
  function objFromKeys(src, getValue) {
191
185
  return Object.fromEntries(src.map(k => [k, getValue(k)]));
192
186
  }
193
- function enforceFinal(sub, s, evenEmpty = false) {
187
+ function hasFinalSlash(s) {
188
+ return /[\\/]$/.test(s);
189
+ }
190
+ function enforceFinal(sub, s = '', evenEmpty = false) {
194
191
  return (s ? !s.endsWith(sub) : evenEmpty) ? s + sub : s;
195
192
  }
196
193
  function removeFinal(sub, s) {
197
194
  return s.endsWith(sub) ? s.slice(0, -sub.length) : s;
198
195
  }
199
- function enforceStarting(sub, s, evenEmpty = false) {
196
+ function enforceStarting(sub, s = '', evenEmpty = false) {
200
197
  return (s ? !s.startsWith(sub) : evenEmpty) ? sub + s : s;
201
198
  }
202
199
  function removeStarting(sub, s) {
@@ -451,7 +448,7 @@ function xlate(input, table) {
451
448
  }
452
449
  // remove brackets and port (if any)
453
450
  function normalizeHost(host) {
454
- return host[0] === '[' ? host.slice(1, host.indexOf(']')) : host?.split(':')[0];
451
+ return host[0] === '[' ? host.slice(1, host.indexOf(']')) : host.split(':')[0];
455
452
  }
456
453
  function isIpLocalHost(ip) {
457
454
  return ip === '::1' || ip.endsWith('127.0.0.1');
@@ -565,16 +562,22 @@ function patchKey(o, k, replacer) {
565
562
  o[k] = replacer(o[k]);
566
563
  return o;
567
564
  }
568
- // consider the callback successful if it returns a truthy value
565
+ // retry rejected operations because filesystem resources may be released late
569
566
  async function retry(cb, delay = 1000) {
570
- let retry = 3;
571
- while (true) {
572
- if (await cb())
573
- break;
574
- if (!retry--)
575
- break;
576
- await wait(delay);
577
- }
567
+ let retries = 3;
568
+ while (true)
569
+ try {
570
+ return await cb();
571
+ }
572
+ catch (e) {
573
+ if (!retries--)
574
+ throw e;
575
+ await wait(delay);
576
+ }
577
+ }
578
+ // normalize callback results and synchronous throws into a promise
579
+ function callAsPromise(callback) {
580
+ return Promise.resolve().then(callback);
578
581
  }
579
582
  function toMutable(value) {
580
583
  return Array.isArray(value) ? value.slice() : { ...value };
package/src/ddns.js CHANGED
@@ -73,10 +73,7 @@ async function get_dynamic_dns_error() {
73
73
  if (last)
74
74
  this.push(last); // start by sending current state
75
75
  unsub = events_1.default.on('dynamicDnsError', x => this.push(x)); // send updates, if any. This simplified way to manage the data stream is acceptable for this case of extremely low throughput
76
- },
77
- async destroy() {
78
- unsub();
79
- this.push(null);
76
+ this.once('close', unsub);
80
77
  }
81
78
  });
82
79
  }
package/src/events.js CHANGED
@@ -19,10 +19,7 @@ class BetterEventEmitter {
19
19
  this.emit(e + LISTENERS_SUFFIX, cbs, listener);
20
20
  }
21
21
  if (callNow)
22
- try {
23
- listener();
24
- }
25
- catch { }
22
+ Promise.resolve().then(listener).catch(console.error);
26
23
  return () => {
27
24
  for (const e of event) {
28
25
  const cbs = this.listeners.get(e);
package/src/fileAttr.js CHANGED
@@ -35,7 +35,7 @@ async function storeFileAttr(path, k, v) {
35
35
  return true;
36
36
  }
37
37
  // fallback to our kv-storage
38
- return await exports.fileAttrDb.put(fileAttrKey(path, k), v)?.catch((e) => {
38
+ return await exports.fileAttrDb.put(fileAttrKey(path, k), v)?.then(() => true, (e) => {
39
39
  console.error("Couldn't store metadata on", path, String(e.message || e));
40
40
  return false;
41
41
  }) ?? true; // if put is undefined, the value was already there
@@ -20,6 +20,7 @@ const promises_1 = require("fs/promises");
20
20
  const path_1 = require("path");
21
21
  const upload_1 = require("./upload");
22
22
  const misc_1 = require("./misc");
23
+ const uploadOwners_1 = require("./uploadOwners");
23
24
  const config_1 = require("./config");
24
25
  const comments_1 = require("./comments");
25
26
  const SendList_1 = require("./SendList");
@@ -99,7 +100,7 @@ exports.frontEndApis = {
99
100
  throw new apiMiddleware_1.ApiError(const_1.HTTP_NOT_FOUND);
100
101
  if ((0, vfs_1.isRoot)(node) || !(0, util_files_1.isValidFileName)(dest))
101
102
  return new apiMiddleware_1.ApiError(const_1.HTTP_FORBIDDEN);
102
- await requestedRename(node, dest, ctx);
103
+ await requestedRename(node, dest, ctx, uri);
103
104
  return {};
104
105
  },
105
106
  async move_files({ uri_from, uri_to }, ctx) {
@@ -126,7 +127,8 @@ exports.frontEndApis = {
126
127
  return new apiMiddleware_1.ApiError(const_1.HTTP_UNAUTHORIZED);
127
128
  if (!node.source)
128
129
  return new apiMiddleware_1.ApiError(const_1.HTTP_FAILED_DEPENDENCY);
129
- await (0, comments_1.setCommentFor)(node.source, comment);
130
+ if (!await (0, comments_1.setCommentFor)(node.source, comment))
131
+ return new apiMiddleware_1.ApiError(const_1.HTTP_SERVER_ERROR);
130
132
  return {};
131
133
  },
132
134
  async get_folder_size_partial({ id }) {
@@ -199,11 +201,12 @@ async function moveFiles(uri_from, uri_to, ctx, override) {
199
201
  await (0, promises_1.copyFile)(src, dest);
200
202
  await (0, promises_1.unlink)(src);
201
203
  }).then(() => (0, misc_1.moveStoredFileAttrs)(src, dest))
204
+ .then(() => (0, uploadOwners_1.moveUploadOwner)(from1, (0, misc_1.join)(uri_to, destName)))
202
205
  .catch(e => e.code || String(e));
203
206
  }))
204
207
  };
205
208
  }
206
- async function requestedRename(node, newName, ctx) {
209
+ async function requestedRename(node, newName, ctx, uri = ctx.path) {
207
210
  if (!node)
208
211
  throw new apiMiddleware_1.ApiError(const_1.HTTP_NOT_FOUND);
209
212
  // requestedRename is exported, so keep disk rename confinement here even when callers pre-validate
@@ -223,6 +226,7 @@ async function requestedRename(node, newName, ctx) {
223
226
  const destSource = (0, path_1.join)((0, path_1.dirname)(node.source), newName);
224
227
  await (0, promises_1.rename)(node.source, destSource);
225
228
  await (0, misc_1.moveStoredFileAttrs)(node.source, destSource);
229
+ await (0, uploadOwners_1.moveUploadOwner)(uri, (0, misc_1.join)((0, path_1.dirname)(uri), (0, misc_1.pathEncode)(newName)));
226
230
  (0, comments_1.getCommentFor)(node.source).then(c => {
227
231
  if (!c)
228
232
  return;
package/src/geo.js CHANGED
@@ -15,12 +15,18 @@ const enabled = (0, config_1.defineConfig)(misc_1.CFG.geo_enable, false);
15
15
  const allow = (0, config_1.defineConfig)(misc_1.CFG.geo_allow, null);
16
16
  const list = (0, config_1.defineConfig)(misc_1.CFG.geo_list, []);
17
17
  const allowUnknown = (0, config_1.defineConfig)(misc_1.CFG.geo_allow_unknown, false);
18
- enabled.sub(checkFiles);
18
+ const ignoreNet = (0, config_1.defineConfig)(misc_1.CFG.geo_ignore_net, '', v => (0, misc_1.makeNetMatcher)(v));
19
+ let filesCheck = Promise.resolve();
20
+ enabled.sub(() => {
21
+ filesCheck = checkFiles().catch((e) => console.error('Failed to load geo-ip db:', e?.message || String(e)));
22
+ });
19
23
  setInterval(checkFiles, misc_1.DAY); // keep updated at run-time
20
24
  // benchmark: memoize can make this 44x faster
21
25
  exports.ip2country = lodash_1.default.memoize((ip) => ip2location.getCountryShortAsync(ip).then(v => v === '-' ? '' : v, () => ''));
22
26
  const geoFilter = async (ctx, next) => {
23
- if (enabled.get() && !(0, misc_1.isLocalHost)(ctx) && !(0, misc_1.isIpLan)(ctx.ip)) {
27
+ if (enabled.get() && !(0, misc_1.isLocalHost)(ctx) && !(0, misc_1.isIpLan)(ctx.ip) && !ignoreNet.compiled()(ctx.ip)) {
28
+ if (!isOpen()) // keep startup independent of the geo db download, but don't classify external requests before the db had a chance to load
29
+ await filesCheck;
24
30
  const { connection } = ctx.state;
25
31
  const country = connection.country ??= await (0, exports.ip2country)(ctx.ip);
26
32
  if (country)
package/src/github.js CHANGED
@@ -122,18 +122,19 @@ async function downloadPlugin(repo, { branch = '', overwrite = false } = {}) {
122
122
  if (wasRunning)
123
123
  await (0, plugins_1.stopPlugin)(folder); // stop old
124
124
  // move data, and consider late release of the resource, up to a few seconds
125
- await (0, misc_1.retry)(() => (0, promises_1.rename)((0, path_1.join)(installPath, plugins_1.STORAGE_FOLDER), (0, path_1.join)(tempInstallPath, plugins_1.STORAGE_FOLDER))
126
- .then(() => 1, e => e.code === 'ENOENT'));
125
+ await (0, misc_1.retry)(() => (0, promises_1.rename)((0, path_1.join)(installPath, plugins_1.STORAGE_FOLDER), (0, path_1.join)(tempInstallPath, plugins_1.STORAGE_FOLDER)).catch(e => {
126
+ if (e.code !== 'ENOENT')
127
+ throw e;
128
+ }));
127
129
  // delete old folder (if any), but it may fail in the presence of .node files, so we rename it first as a precaution (clearing require.cache doesn't help). Especially on Windows, it may be impossible to delete dll files until our process is terminated (in which case, retrying is useless).
128
130
  const deleteMe = installPath + plugins_1.DELETE_ME_SUFFIX;
129
- await (0, misc_1.retry)(() => (0, promises_1.rename)(installPath, deleteMe).then(() => 1, (e) => {
130
- if (e.code === 'ENOENT')
131
- return 1; // nothing to do
132
- console.warn("Error renaming old plugin folder:", String(e));
133
- }));
134
- await (0, misc_1.retry)(() => (0, promises_1.rm)(deleteMe, { recursive: true, force: true /*ignore ENOENT*/ }).then(() => 1, e => {
135
- console.warn("Error deleting old plugin folder:", String(e));
131
+ await (0, misc_1.retry)(() => (0, promises_1.rename)(installPath, deleteMe).catch(e => {
132
+ if (e.code !== 'ENOENT')
133
+ throw e;
136
134
  }));
135
+ // a disabled leftover cannot block replacement and will be cleaned at startup
136
+ await (0, misc_1.retry)(() => (0, promises_1.rm)(deleteMe, { recursive: true, force: true /*ignore ENOENT*/ }))
137
+ .catch(e => console.warn("Error deleting old plugin folder:", String(e)));
137
138
  // final replace
138
139
  await (0, promises_1.rename)(tempInstallPath, installPath)
139
140
  .catch(e => { throw e.code !== 'ENOENT' ? e : new apiMiddleware_1.ApiError(const_1.HTTP_NOT_ACCEPTABLE, "missing main file"); });
package/src/index.js CHANGED
@@ -72,6 +72,7 @@ function errorHandler(err) {
72
72
  || code === 'ERR_STREAM_WRITE_AFTER_END' // happens disconnecting uploads, don't care
73
73
  || code === 'ERR_STREAM_PREMATURE_CLOSE' // happens when many files are sent (not locally), but I checked that the files are written completely. Introduced after node18.5.0 and is thrown by pipeline() used by PUT method handler.
74
74
  || code === 'ERR_SSL_SSL/TLS_ALERT_BAD_RECORD_MAC' // tls peers/proxies can abort encrypted streams after headers are already sent
75
+ || code === 'ERR_SSL_DECRYPTION_FAILED_OR_BAD_RECORD_MAC' // corrupted TLS records come from the peer/network, not server logic
75
76
  || code?.startsWith('HPE'))
76
77
  return; // malformed client/probe HTTP parser errors, not internal failures
77
78
  console.error('Server error', err);
@@ -86,7 +87,7 @@ process.on('uncaughtException', (err) => {
86
87
  // this warning is scaring users, and has been removed in node 20.12.0 https://github.com/nodejs/node/pull/51204
87
88
  const original = process.emitWarning;
88
89
  process.emitWarning = warn => String(warn).startsWith('An error event has already been emitted') || original.call(process, warn);
89
- (0, config_1.defineConfig)('proxies', 0).sub(n => {
90
+ (0, config_1.defineConfig)(misc_1.CFG.proxies, 0).sub(n => {
90
91
  exports.app.proxy = n > 0;
91
92
  exports.app.maxIpsCount = n;
92
93
  });
package/src/ips.js CHANGED
@@ -14,9 +14,30 @@ exports.ips = new kvstorage_1.KvStorage({
14
14
  });
15
15
  (0, first_1.onProcessExit)(() => exports.ips.close());
16
16
  const trackIpsMw = async (ctx, next) => {
17
- if (exports.ips.isOpen() && !(0, misc_1.isLocalHost)(ctx))
18
- exports.ips.put(ctx.ip, { ts: new Date, country: ctx.state.connection.country });
19
- await next();
17
+ const tracking = exports.ips.isOpen() && !(0, misc_1.isLocalHost)(ctx);
18
+ const ts = new Date;
19
+ const country = ctx.state.connection.country;
20
+ let failed = false;
21
+ // defer storage update until downstream middlewares have assigned status or thrown
22
+ try {
23
+ await next();
24
+ }
25
+ catch (e) {
26
+ failed = true;
27
+ throw e;
28
+ }
29
+ finally {
30
+ if (tracking) {
31
+ // keep the counter update here so failures from downstream middlewares are counted with the final status
32
+ const was = exports.ips.getSync(ctx.ip);
33
+ void exports.ips.put(ctx.ip, {
34
+ ts,
35
+ country,
36
+ served: (was?.served || 0) + (failed || ctx.status >= 400 ? 0 : 1),
37
+ failed: (was?.failed || 0) + (failed || ctx.status >= 400 ? 1 : 0),
38
+ }).catch(e => console.error("Couldn't track IP", ctx.ip, String(e)));
39
+ }
40
+ }
20
41
  };
21
42
  exports.trackIpsMw = trackIpsMw;
22
43
  trackIps.sub(v => {
@@ -96,6 +96,7 @@
96
96
  "upload_finished": "{n} تم رفعه ({size})",
97
97
  "upload_errors": "{n} فشلوا",
98
98
  "upload_file_rejected": "بعض الملفات لم تُقبل",
99
+ "delete_unfinished_upload": "هل تريد إزالة الرفع غير المكتمل؟",
99
100
  "File menu": "قائمة الملف",
100
101
  "Folder menu": "قائمة المجلد",
101
102
  "Name": "الاسم",
@@ -94,6 +94,7 @@
94
94
  "upload_finished": "{n} завършени ({size})",
95
95
  "upload_errors": "{n} неуспешни",
96
96
  "upload_file_rejected": "Някои файлове не бяха приети",
97
+ "delete_unfinished_upload": "Премахване на незавършеното качване?",
97
98
  "File menu": "Меню на файл",
98
99
  "Folder menu": "Меню на папка",
99
100
  "Name": "Име",
@@ -96,6 +96,7 @@
96
96
  "upload_finished": "{n} fertig ({size})",
97
97
  "upload_errors": "{n} fehlgeschlagen",
98
98
  "upload_file_rejected": "Einige Dateien wurden nicht akzeptiert",
99
+ "delete_unfinished_upload": "Unvollständigen Upload entfernen?",
99
100
  "File menu": "Dateimenü",
100
101
  "Folder menu": "Ordnermenü",
101
102
  "Name": "Name",
@@ -96,6 +96,7 @@
96
96
  "upload_finished": "{n} ολοκληρώθηκαν ({size})",
97
97
  "upload_errors": "{n} απέτυχαν",
98
98
  "upload_file_rejected": "Κάποια αρχεία δεν γίνονται δεκτά",
99
+ "delete_unfinished_upload": "Να αφαιρεθεί η ημιτελής μεταφόρτωση;",
99
100
  "File menu": "Μενού αρχείου",
100
101
  "Folder menu": "Μενού φακέλου",
101
102
  "Name": "Όνομα",
@@ -96,6 +96,7 @@
96
96
  "upload_finished": "{n} completado ({size})",
97
97
  "upload_errors": "{n} fallido",
98
98
  "upload_file_rejected": "Algunos archivos no fueron aceptados",
99
+ "delete_unfinished_upload": "¿Eliminar la subida sin terminar?",
99
100
  "File menu": "Archivo",
100
101
  "Folder menu": "Carpeta",
101
102
  "Name": "Nombre",
@@ -96,6 +96,7 @@
96
96
  "upload_finished": "{n} tiedostoa tai kansiota lähetetty onnistuneesti ({size})",
97
97
  "upload_errors": "{n} epäonnistui",
98
98
  "upload_file_rejected": "Joitakin tiedostoja ei hyväksytty",
99
+ "delete_unfinished_upload": "Poistetaanko keskeneräinen lähetys?",
99
100
  "File menu": "Tiedostovalikko",
100
101
  "Folder menu": "Kansiovalikko",
101
102
  "Name": "Nimi",
@@ -96,6 +96,7 @@
96
96
  "upload_finished": "{n} terminé(s) ({size})",
97
97
  "upload_errors": "{n} échoués",
98
98
  "upload_file_rejected": "Certains fichiers ont été refusés",
99
+ "delete_unfinished_upload": "Supprimer l'envoi inachevé ?",
99
100
  "File menu": "Menu du fichier",
100
101
  "Folder menu": "Menu du dossier",
101
102
  "Name": "Nom",
@@ -97,6 +97,7 @@
97
97
  "upload_finished": "{n} kész ({size})",
98
98
  "upload_errors": "{n} sikertelen",
99
99
  "upload_file_rejected": "Egyes fájlokat nem sikerült feltölteni",
100
+ "delete_unfinished_upload": "Eltávolítja a befejezetlen feltöltést?",
100
101
  "download counter": "letöltés számláló",
101
102
  "File menu": "Fájl menü",
102
103
  "Folder menu": "Mappa menü",
@@ -89,6 +89,7 @@
89
89
  "upload_finished": "{n,plural, one{# riuscito} other{# riusciti}} ({size})",
90
90
  "upload_errors": "{n,plural, one{# fallito} other{# falliti}}",
91
91
  "upload_file_rejected": "Alcuni file non sono stati accettati",
92
+ "delete_unfinished_upload": "Rimuovere l'upload incompleto?",
92
93
  "File menu": "Menu file",
93
94
  "Folder menu": "Menu cartella",
94
95
  "Name": "Nome",
@@ -96,6 +96,7 @@
96
96
  "upload_finished": "{n}個完了 ({size})",
97
97
  "upload_errors": "{n} 失敗",
98
98
  "upload_file_rejected": "一部のファイルは受け入れられませんでした",
99
+ "delete_unfinished_upload": "未完了のアップロードを削除しますか?",
99
100
  "File menu": "ファイルメニュー",
100
101
  "Folder menu": "フォルダメニュー",
101
102
  "Name": "名前",
@@ -96,6 +96,7 @@
96
96
  "upload_finished": "{n}개 파일 완료 ({size})",
97
97
  "upload_errors": "{n}개 파일 실패",
98
98
  "upload_file_rejected": "일부 파일은 업로드되지 않았습니다.",
99
+ "delete_unfinished_upload": "완료되지 않은 업로드를 제거할까요?",
99
100
  "File menu": "파일 메뉴",
100
101
  "Folder menu": "폴더 메뉴",
101
102
  "Name": "이름",
@@ -95,6 +95,7 @@
95
95
  "upload_finished": "{n} baigta ({size})",
96
96
  "upload_errors": "{n} nepavyko",
97
97
  "upload_file_rejected": "Kai kurie failai nebuvo priimti",
98
+ "delete_unfinished_upload": "Pašalinti nebaigtą įkėlimą?",
98
99
  "File menu": "Failo meniu",
99
100
  "Folder menu": "Aplanko meniu",
100
101
  "Name": "Pavadinimas",
@@ -59,6 +59,7 @@
59
59
  "upload_finished": "{n} selesai ({size})",
60
60
  "upload_errors": "{n} gagal",
61
61
  "upload_file_rejected": "Beberapa fail tidak diterima",
62
+ "delete_unfinished_upload": "Alih keluar muat naik yang belum selesai?",
62
63
  "ready_to_upload": "{n,plural,one{# fail} other{# fail}}, {size}, sedia untuk dimuat naik",
63
64
  "Send": "Hantar",
64
65
  "download counter": "pengira muat turun",
@@ -95,6 +95,7 @@
95
95
  "upload_finished": "{n} voltooid ({size})",
96
96
  "upload_errors": "{n} niet voltooid",
97
97
  "upload_file_rejected": "Sommige bestanden zijn niet geaccepteerd",
98
+ "delete_unfinished_upload": "Onvoltooide upload verwijderen?",
98
99
  "File menu": "Bestand menu",
99
100
  "Folder menu": "Map menu",
100
101
  "Name": "Naam",
@@ -95,6 +95,7 @@
95
95
  "upload_finished": "{n} zakończonych ({size})",
96
96
  "upload_errors": "{n} nieudanych",
97
97
  "upload_file_rejected": "Niektóre pliki nie zostały zaakceptowane",
98
+ "delete_unfinished_upload": "Usunąć niedokończone przesyłanie?",
98
99
  "File menu": "Menu pliku",
99
100
  "Folder menu": "Menu folderu",
100
101
  "Name": "Nazwa",
@@ -95,6 +95,7 @@
95
95
  "upload_finished": "{n} finalizado ({size})",
96
96
  "upload_errors": "{n} faliu",
97
97
  "upload_file_rejected": "Alguns arquivos não foram aceitos",
98
+ "delete_unfinished_upload": "Remover o envio inacabado?",
98
99
  "File menu": "Menu de arquivo",
99
100
  "Folder menu": "Menu de Pasta",
100
101
  "Name": "Nome",
@@ -96,6 +96,7 @@
96
96
  "upload_finished": "{n} terminat ({size})",
97
97
  "upload_errors": "{n} eșuat",
98
98
  "upload_file_rejected": "Unele fișiere nu au fost acceptate",
99
+ "delete_unfinished_upload": "Eliminați încărcarea neterminată?",
99
100
  "File menu": "Meniu fișier",
100
101
  "Folder menu": "Meniu folder",
101
102
  "Name": "Nume",
@@ -96,6 +96,7 @@
96
96
  "upload_finished": "{n,plural, one{# файл загружен} few{# файла загружено} many{# файлов загружено}} ({size})",
97
97
  "upload_errors": "{n,plural, one{# файл} few{# файла} many{# файлов}} неуспешно",
98
98
  "upload_file_rejected": "Некоторые файлы не были приняты",
99
+ "delete_unfinished_upload": "Удалить незавершённую загрузку?",
99
100
  "File menu": "Меню файла",
100
101
  "Folder menu": "Меню папки",
101
102
  "Name": "Имя",
@@ -95,6 +95,7 @@
95
95
  "upload_finished": "{n} završeno ({size})",
96
96
  "upload_errors": "{n,plural, one{# nije uspeo} other{# neuspešna}}",
97
97
  "upload_file_rejected": "Neke datoteke nisu prihvaćene",
98
+ "delete_unfinished_upload": "Ukloniti nedovršeno otpremanje?",
98
99
  "File menu": "Meni datoteke",
99
100
  "Folder menu": "Meni fascikle",
100
101
  "Name": "Ime",
@@ -98,6 +98,7 @@
98
98
  "upload_finished": "{n} пребачен(о) ({size})",
99
99
  "upload_errors": "{n} неуспешно пребачен(их)",
100
100
  "upload_file_rejected": "Нека документа нису прихваћена",
101
+ "delete_unfinished_upload": "Уклонити недовршено отпремање?",
101
102
  "download counter": "бројач преузимања",
102
103
  "File menu": "Мени документа",
103
104
  "Folder menu": "Мени фолдера",
@@ -96,6 +96,7 @@
96
96
  "upload_finished": "{n} เสร็จสิ้น ({size})",
97
97
  "upload_errors": "{n} ล้มเหลว",
98
98
  "upload_file_rejected": "บางไฟล์ไม่ได้รับการยอมรับ",
99
+ "delete_unfinished_upload": "ลบการอัปโหลดที่ยังไม่เสร็จหรือไม่?",
99
100
  "File menu": "เมนูไฟล์",
100
101
  "Folder menu": "เมนูโฟลเดอร์",
101
102
  "Name": "ชื่อ",
@@ -96,6 +96,7 @@
96
96
  "upload_finished": "{n} tamamlandı ({size})",
97
97
  "upload_errors": "{n} başarısız",
98
98
  "upload_file_rejected": "Bazı dosyalar kabul edilmiyor",
99
+ "delete_unfinished_upload": "Tamamlanmamış yüklemeyi kaldır?",
99
100
  "File menu": "Dosya Menüsü",
100
101
  "Folder menu": "Klasör Menüsü",
101
102
  "Name": "İsim",
@@ -96,6 +96,7 @@
96
96
  "upload_finished": "{n,plural, one{# файл завантажено} few{# файли завантажено} many{# файлів завантажено}} ({size})",
97
97
  "upload_errors": "{n,plural, one{# файл} few{# файли} many{# файлів}} неуспішно",
98
98
  "upload_file_rejected": "Деякі файли не були прийняті",
99
+ "delete_unfinished_upload": "Видалити незавершене завантаження?",
99
100
  "File menu": "Меню файлу",
100
101
  "Folder menu": "Меню теки",
101
102
  "Name": "Назва",
@@ -97,6 +97,7 @@
97
97
  "upload_finished": "{n} thành công ({size})",
98
98
  "upload_errors": "{n} thất bại",
99
99
  "upload_file_rejected": "Một số file bị cấm...",
100
+ "delete_unfinished_upload": "Xóa bản upload chưa hoàn tất?",
100
101
  "Download counter": "Bộ đếm download",
101
102
  "File menu": "Menu",
102
103
  "Folder menu": "Menu",
@@ -96,6 +96,7 @@
96
96
  "upload_finished": "{n} 個檔案完成 ({size})",
97
97
  "upload_errors": "{n} 失敗",
98
98
  "upload_file_rejected": "部分檔案不被允許",
99
+ "delete_unfinished_upload": "要移除未完成的上傳嗎?",
99
100
  "File menu": "檔案選單",
100
101
  "Folder menu": "資料夾選單",
101
102
  "Name": "名稱",
@@ -96,6 +96,7 @@
96
96
  "upload_finished": "上传{n} 完成 ({size})",
97
97
  "upload_errors": "上传失败{n} 次",
98
98
  "upload_file_rejected": "部分文件被服务器拒绝接收",
99
+ "delete_unfinished_upload": "要移除未完成的上传吗?",
99
100
  "File menu": "文件菜单",
100
101
  "Folder menu": "文件夹菜单",
101
102
  "Name": "名称",