Compare commits

...

173 Commits

Author SHA1 Message Date
Massimo Melina
6ff458fb73
Merge pull request #41 from divinity76/patch-1
warning about Delphi 10.4 Community being incompatible
2025-01-22 22:25:18 +01:00
divinity76
0d71b9946a
warning about Delphi 10.4 Community being incompatible 2023-03-25 12:45:10 +01:00
Massimo Melina
140528bac8
Create README.md 2023-03-12 17:42:10 +01:00
Massimo Melina
29f6bac31c default speed limit 50MBps 2020-08-30 23:26:11 +02:00
Massimo Melina
e233f6d29a fix: search and archive recently broken 2020-08-23 13:45:47 +02:00
Massimo Melina
6e4dcf5b56 fix: avoid dupe files in archive in case of ?search=* 2020-08-04 21:16:37 +02:00
Massimo Melina
61f1a14be6 updated .lng 2020-08-02 18:31:17 +02:00
Massimo Melina
2d1187b6a3 tpl: moved archive button to "selection" sub-menu 2020-08-02 17:44:02 +02:00
Massimo Melina
ca7caab85d fix: account dialog recently broken 2020-08-02 17:43:13 +02:00
Massimo Melina
9e662960e1 usability: standard ok/cancel buttons for "ask" dialog 2020-08-02 13:10:38 +02:00
Massimo Melina
21349e5c04 experiental ?mode=thumb to append to jpg files 2020-08-01 20:46:46 +02:00
Massimo Melina
db2ad83c77 new tpl syntax [^section] will prepend to [section] 2020-08-01 20:46:07 +02:00
Massimo Melina
a47541286a fix: unicode support with {.exec|out.} 2020-07-27 23:29:23 +02:00
Massimo Melina
62c30c8de1 fix: a {.command.} resulting in an empty string could actually produce a false error 2020-07-27 23:27:52 +02:00
Massimo Melina
ad439fa65f fix: some headers were not customizable with {.add header.} 2020-07-27 12:17:49 +02:00
Massimo Melina
2d131f2c5f fix: malformed non-ascii post variables when not url-encoded 2020-07-27 11:37:18 +02:00
Massimo Melina
ba2df13122 removed jquery dependency from default tpl 2020-07-08 15:22:35 +02:00
Massimo Melina
da294807ca removed 'append macros log' option 2020-07-08 13:26:28 +02:00
Massimo Melina
6625f08419 Revert "apply 1 minute timeout to file listing"
This reverts commit d43983e9
2020-07-08 13:24:27 +02:00
Massimo Melina
d43983e986 apply 1 minute timeout to file listing 2020-06-29 00:03:38 +02:00
Massimo Melina
4b5bffbd83 fix: possible CSRF 2020-06-29 00:02:20 +02:00
Massimo Melina
cf3761b7ed fix: 2 resource strings with same name 2020-06-28 20:31:25 +02:00
Massimo Melina
b5dc45f214 smarter displaying of 'status' columns (details moved to tooltip) 2020-06-28 14:12:24 +02:00
Massimo Melina
b1a95cd319 introduced 1 minute timeout for archive's files list building 2020-06-28 13:57:53 +02:00
Massimo Melina
6c5139d552 optimization: avoid resetting the array length when unnecessary 2020-06-28 11:34:07 +02:00
Massimo Melina
863c667f1b fix: apply anti-dos also to archives 2020-06-27 20:46:11 +02:00
Massimo Melina
44f37f92cf prevent macros coming from commands convert, base64decode, decodeuri 2020-06-23 20:16:12 +02:00
Massimo Melina
308561090f fix: {.dialog||yesno.} was not working 2020-06-23 20:14:24 +02:00
Massimo Melina
26ddc2b126 fix: {.calc.} not working with very small numbers (because rendered with exponential syntax) 2020-06-16 23:14:45 +02:00
Massimo Melina
65d4a142e4 new 'init' section for events file, executed at each reload 2020-06-16 23:13:22 +02:00
Massimo Melina
07f5f2ca6b fix: {.disconnect.} and {.disconnection reason.} not working in event 'pre-filter-request' 2020-06-16 23:12:36 +02:00
Massimo Melina
cba235c7b0 fix: {.set table.} duplicating keys instead of updating values 2020-06-16 00:39:11 +02:00
Massimo Melina
9220d33aa4 trigger 'unauthorized' event for new login and url-auth. Also added 'login' event in case of success. 2020-06-16 00:37:31 +02:00
Massimo Melina
efa99e7cbc new 'public' section flag in place of 'private', inverting logic 2020-06-16 00:35:15 +02:00
Massimo Melina
6729be221a without this people will have problems editing the tpl 2020-06-14 10:40:26 +02:00
Massimo Melina
8ab5b318a8 tpl must declare api level 2 2020-06-14 09:24:44 +02:00
Massimo Melina
db092e5eab back to 'selection' for submitting files, to facilitate tpls compatible with 2.3 2020-06-13 21:07:23 +02:00
Massimo Melina
d6d5b8f493 tpl: missing few tooltips 2020-06-13 20:49:53 +02:00
Massimo Melina
151cddad5b no need to invalidate session in this case, it was not compromised 2020-06-13 20:36:00 +02:00
Massimo Melina
18f0da77d4 fix: (recent) broken ajax() calls 2020-06-13 20:34:19 +02:00
Massimo Melina
70947f179c tpl: moved changePwd() to lib.js 2020-06-13 17:07:22 +02:00
Massimo Melina
7cc712a245 fix: (recent) broke ajax() calls 2020-06-13 17:06:35 +02:00
Massimo Melina
1e7bf6cfc4 amend previous commit 2020-06-13 17:05:01 +02:00
Massimo Melina
18f7e5177f fix: problems downloading files with a comma with firefox77 2020-06-13 00:37:58 +02:00
Massimo Melina
6b933acdef added few mime-types 2020-06-11 23:42:01 +02:00
Massimo Melina
f69251a482 fix: [file.EXT] not working 2020-06-11 23:39:38 +02:00
Massimo Melina
1f713f706e {.convert|utf-8|dec/hex.} 2020-06-11 11:40:12 +02:00
Massimo Melina
4b5e0205a5 fix: empty tpl sections were not overriding 2020-06-11 11:35:53 +02:00
Massimo Melina
7634b96744 tpl: using HFS.sid we can move ajax() where it belongs 2020-06-10 20:34:15 +02:00
Massimo Melina
7facca0306 tpl: save options to localStorage and avoid extra traffic 2020-06-10 16:08:13 +02:00
Massimo Melina
1fab68e4fa build 315 2020-06-10 16:07:27 +02:00
Massimo Melina
1d9d6fd100 new section flag: ver=MASK 2020-06-10 13:22:31 +02:00
Massimo Melina
7e66a94e37 new section flag: template=MASK 2020-06-10 13:11:58 +02:00
Massimo Melina
5e5122edba new section flag: build=MIN-MAX 2020-06-10 12:45:32 +02:00
Massimo Melina
6d91b0da6e fix: 'no list' section flag should be inherited 2020-06-10 12:18:54 +02:00
Massimo Melina
e29e86c0bd tpl: defaults to dark theme if the OS says so 2020-06-09 00:07:31 +02:00
Massimo Melina
de7f157390 new {.sha256.} 2020-06-08 20:23:29 +02:00
Massimo Melina
1e21013b96 copyright update 2020-06-08 18:50:18 +02:00
Massimo Melina
b028c47f10 added 'no log' section flag to support SAP themes like 'mobil-light' 2020-06-08 12:40:34 +02:00
Massimo Melina
782702c192 smarter DoS-preventing grace period 2020-06-08 12:40:00 +02:00
Massimo Melina
1fc5894204 fix: (recent) error trying to load a VFS with an empty recent-files list 2020-06-08 12:36:05 +02:00
Massimo Melina
33d4d16b0b
better format 2020-06-08 11:00:08 +02:00
Massimo Melina
801ceead5b build 313 2020-06-08 10:26:38 +02:00
Massimo Melina
a3056ccfd4 fix: possible DoS, as reported by John Page (aka hyp3rlinx) ApparitionSec (CVE-2020-13432) 2020-06-07 12:10:56 +02:00
Massimo Melina
16744d7c6c tpl: added warning for low-security change-password action 2020-06-07 11:30:40 +02:00
Massimo Melina
7c3f5929fa fix: chrome fails downloading filenames with commas 2020-06-07 10:59:41 +02:00
Massimo Melina
bdc5991fa1 fix: display ipv6 address with brackets in log 2020-06-06 19:59:10 +02:00
Massimo Melina
74a5710f99 fix: conflicting resource text for translation
http://rejetto.com/forum/index.php?topic=13313.msg1065920#msg1065920
2020-06-06 19:32:14 +02:00
Massimo Melina
71b76e3240 updated url 2020-06-05 18:41:42 +02:00
Massimo Melina
30740e372b build 312 2020-06-04 10:33:01 +02:00
Massimo Melina
23ea63a19e fix: error hovering VFS file. http://rejetto.com/forum/index.php?topic=13060.msg1065899#msg1065899 2020-06-03 17:23:08 +02:00
Massimo Melina
474e95315a i18n: moved strings to resources 2020-06-02 14:12:56 +02:00
Massimo Melina
b4ca9f113a fix: unicode problems on chinese systems with single-char chinese strings 2020-06-02 12:50:49 +02:00
Massimo Melina
60c7674dc5 fix: many resource strings had the same ID 2020-06-01 11:24:32 +02:00
Massimo Melina
e8a2e281ec usability improvement for 'ban this address' 2020-05-31 00:35:21 +02:00
Massimo Melina
8be3ff6331 fix: log > ban ip address, not working with AM/PM time locale 2020-05-30 17:28:43 +02:00
Massimo Melina
df5fa09ba9 fix: utf-8 decoding for {.load.} 2020-05-30 17:14:40 +02:00
Massimo Melina
469acc3fb7 fix: unicode filenames with comments 2020-05-30 16:49:47 +02:00
Massimo Melina
0f365a3f65 tpl: nicer 2020-05-30 16:46:47 +02:00
Massimo Melina
82e971bc47 fix: login randomly broken (when 'D' in SID) 2020-05-30 15:48:28 +02:00
Massimo Melina
ebf997951f better code 2020-05-30 15:47:07 +02:00
Massimo Melina
983b184a0f fix legacy problems 2020-05-30 15:46:09 +02:00
Massimo Melina
71b8ca4ee6 build 309 2020-05-28 17:00:49 +02:00
Massimo Melina
4a44d5daa4 sounder session ID (fix possible session problem) 2020-05-28 16:51:42 +02:00
Massimo Melina
5fa867e194 fix: ipv6 support for forwarded-mask 2020-05-28 15:19:36 +02:00
Massimo Melina
1546a41fb9 fix: right click on the log didn't recognize IPv6 addresses to offer 'ban this address' 2020-05-28 14:55:10 +02:00
Massimo Melina
75d3d8e5e1 tpl: workaround for chrome83 glitch 2020-05-28 13:22:40 +02:00
Massimo Melina
0a5710ec55 tpl: move normalize.css to section for possible usage by custom tpl 2020-05-28 13:22:13 +02:00
Massimo Melina
64b3f5b906 tpl: warn the user if the current credentials are not enough 2020-05-28 13:21:00 +02:00
Massimo Melina
ad33cbf263 fix: account redirection not working if loggin in from a forbidden folder 2020-05-28 12:43:34 +02:00
Massimo Melina
c4ca0d2188 https client support 2020-05-28 12:30:58 +02:00
Massimo Melina
18b7961d29 fix: auth URL is preventing logout 2020-05-27 20:34:06 +02:00
Massimo Melina
e1f489d340 fix: english 2020-05-27 12:39:10 +02:00
Massimo Melina
57a83ec9f8 nicer (consistency) 2020-05-27 12:14:59 +02:00
Massimo Melina
b877d6853b offer "copy url with password" also for upload/delete restriction 2020-05-27 12:12:00 +02:00
Massimo Melina
0483032439 fix: link-with-password, if the account has a redirect, it will make it to the second request (often css) 2020-05-27 11:51:29 +02:00
Massimo Melina
1c0ff4e75a fix: update not working 2020-05-27 11:02:26 +02:00
Massimo Melina
d8a426f63b removed useless files 2020-05-26 19:10:01 +02:00
Massimo Melina
f318745b1d fix: ipv6 links format in the address bar 2020-05-26 18:54:13 +02:00
Massimo Melina
d220ec1c70 small optimization 2020-05-26 16:37:29 +02:00
Massimo Melina
f8877304ee fix: recently broken unicode support in comments 2020-05-26 16:30:39 +02:00
Massimo Melina
a7b45ed515 fix: tpl: option.move not working 2020-05-26 16:29:08 +02:00
Massimo Melina
cc8ed99392 fix: upload not working on a folder linked 'with password' 2020-05-26 15:33:38 +02:00
Massimo Melina
e35221c3f7 nicer 2020-05-26 15:17:57 +02:00
Massimo Melina
a9a009260e fix: server doesn't start on systems lacking ipv6 support 2020-05-26 15:15:55 +02:00
Massimo Melina
bfe0265119 {.for line.} and {.if|var.} 2020-05-26 12:09:27 +02:00
Massimo Melina
d1a4b8574a fix: broken format for macros log 2020-05-26 12:07:29 +02:00
Massimo Melina
69573c1a69 attempt to support non-utf8 url requests 2020-05-26 12:05:23 +02:00
Massimo Melina
922253c56f tpl: moved sha256 to section for others to use 2020-05-25 20:05:38 +02:00
Massimo Melina
d3d04c4935 build 306 2020-05-25 20:05:01 +02:00
Massimo Melina
2c03f14766 fix: stopping the server twice led to inconsistent state 2020-05-25 18:15:27 +02:00
Massimo Melina
d2675b9028 fix: connections broken 2020-05-25 18:03:45 +02:00
Massimo Melina
f1f5446b0d quit if 'shell' dialog is closed at start 2020-05-25 16:57:50 +02:00
Massimo Melina
fdef1fe319 enabled localization via hfs.lng 2020-05-24 20:12:02 +02:00
Massimo Melina
17cd8140f5 disabled main tray icon by default 2020-05-24 17:57:44 +02:00
Massimo Melina
0f720b8a25 fix: switching off the server was not stopping the IPv6 part 2020-05-24 17:57:08 +02:00
Massimo Melina
dd0fc4e448 fix: sometimes address in "connections" panel was empty 2020-05-24 17:56:32 +02:00
Massimo Melina
8f1965f863 tpl to be treated as diff tpl, inheriting the default tpl 2020-05-24 17:03:31 +02:00
Massimo Melina
0884a2434a nicer 2020-05-24 16:59:29 +02:00
Massimo Melina
320f2230f6 fix: ipv6 range ban rules malfunctioning on ipv4 connections 2020-05-24 14:46:52 +02:00
Massimo Melina
f87d18bf4e build 304 2020-05-24 00:17:10 +02:00
Massimo Melina
0b6035eb30 nicer 2020-05-24 00:16:41 +02:00
Massimo Melina
eec130248c useless file 2020-05-24 00:16:08 +02:00
Massimo Melina
45f389691d better ipv6 support 2020-05-23 21:49:10 +02:00
Massimo Melina
72b28af2e1 nicer 2020-05-22 14:38:01 +02:00
Massimo Melina
b8ebfc4e22 limit URL parameters to 1000 characters 2020-05-22 13:38:15 +02:00
Massimo Melina
bb1e2fa782 removed 'Leave disconnected connections' 2020-05-22 12:29:35 +02:00
Massimo Melina
9bfec9beaa initial ipv6 support 2020-05-22 12:22:54 +02:00
Massimo Melina
6367b5675d fix: *.diff.tpl 2020-05-21 19:47:37 +02:00
Massimo Melina
2e6bd51e00 use brcc32 for data.res 2020-05-21 19:47:15 +02:00
Massimo Melina
cdfdc11d8d small usability improv 2020-05-21 19:45:20 +02:00
Massimo Melina
b44270c214 fix: auth URL not working 2020-05-20 17:57:35 +02:00
Massimo Melina
455e8be673 proper readme 2020-05-18 11:29:28 +02:00
Massimo Melina
23cc729d3d ready for beta stage 2020-05-17 19:51:20 +02:00
Massimo Melina
3b708d91f6 fix: missing icon 2020-05-17 19:48:10 +02:00
Massimo Melina
32b90d2e50 dismissed 3rd party's gif lib 2020-05-17 19:15:01 +02:00
Massimo Melina
08062c8325 fix: ctrl+c renaming a tree item 2020-05-17 18:09:38 +02:00
Massimo Melina
24666f4dab fix: transparency of icons (web side) 2020-05-17 17:48:39 +02:00
Massimo Melina
592607e23e tpl: added 'clear search' button, for better usability 2020-05-17 15:51:49 +02:00
Massimo Melina
90a0cc0cee fix: 'about' message 2020-05-17 15:18:31 +02:00
Massimo Melina
79078cebe7 better code 2020-05-17 13:37:53 +02:00
Massimo Melina
926bdfc85b fix: 'password in pages' option now using new system 2020-05-17 00:31:31 +02:00
Massimo Melina
0a7c30dd06 new version of copy url with password 2020-05-15 16:15:31 +02:00
Massimo Melina
6125e8a63b fix: session could expire during long download/upload 2020-05-15 13:07:45 +02:00
Massimo Melina
993f75214f fix: account redirection with new login system 2020-05-15 12:05:05 +02:00
Massimo Melina
12c3804dcf fix: program stuck after display change 2020-05-15 11:47:41 +02:00
Massimo Melina
c77912c94e better code 2020-05-14 20:01:12 +02:00
Massimo Melina
bf2237d5f9 fix: layout problem in accounts tab 2020-05-14 13:04:35 +02:00
Massimo Melina
f68b6c23b5 temporary debugging instruction 2020-05-14 13:03:58 +02:00
Massimo Melina
ef4340fc59 limit session to original IP 2020-05-14 13:03:31 +02:00
Massimo Melina
8a622be58d accept session/cookie through URL 2020-05-14 11:40:24 +02:00
Massimo Melina
34d4adf0c3 fix: login not working if root is protected 2020-05-13 23:49:31 +02:00
Massimo Melina
8d6a51157e better code 2020-05-13 23:48:35 +02:00
Massimo Melina
219a131dd5 XHR error handling 2020-05-13 22:19:57 +02:00
Massimo Melina
1b59836f4e use new login when accessing protected files directly 2020-05-13 19:53:59 +02:00
Massimo Melina
20097bc715
Create SECURITY.md 2020-05-13 15:40:30 +02:00
Massimo Melina
494a941220 fix: new login working only from localhost and ascii-only 2020-05-13 13:54:22 +02:00
Massimo Melina
3b01699f86 bit shifting operators [ and ] for {.calc.} 2020-05-13 11:03:13 +02:00
Massimo Melina
6b2a852ca5 easier diff tpl mask 2020-05-13 11:01:02 +02:00
Massimo Melina
5700a2edd6 attempt to fix winXP compatibility 2020-05-12 23:43:34 +02:00
Massimo Melina
fe0ca1d542 fontello config, in case we need to add/change icons 2020-05-12 20:15:41 +02:00
Massimo Melina
4c4200ab68 new login system 2020-05-12 20:13:28 +02:00
Massimo Melina
b681fd506e updated license 2020-05-11 21:17:51 +02:00
Massimo Melina
fe1fefbb1f solved many compilation warnings 2020-05-11 17:06:25 +02:00
Massimo Melina
62bb5f87bb parentfont for main form 2020-05-11 16:38:23 +02:00
Massimo Melina
c45cfb7ab5 use new delphi's gif support 2020-05-11 16:05:00 +02:00
Massimo Melina
28b1919ffd fix: login with MD5 2020-05-11 16:00:14 +02:00
Massimo Melina
b33136e3b0 attempt to fix winXP problem 2020-05-10 20:28:43 +02:00
Massimo Melina
4b16de3fb7 attempt to solve the problem reported at http://rejetto.com/forum/index.php?topic=13288.msg1065650#msg1065650 2020-05-10 20:26:56 +02:00
Massimo Melina
9d65d35c3c loading hfs.diff.*.tpl in exe's folder 2020-05-10 19:23:13 +02:00
Massimo Melina
3bea9cd72d support SHA256 authentication 2020-05-10 15:41:41 +02:00
Massimo Melina
82de213059 fix: sessions not expiring 2020-05-10 00:16:56 +02:00
Massimo Melina
8ff8a9ca22 fix: session logout not working 2020-05-09 22:53:10 +02:00
40 changed files with 6102 additions and 3932 deletions

4
.gitignore vendored
View File

@ -3,11 +3,13 @@ __history/
__recovery/
win32/
.vscode/
.idea/
*.vfs
*.dcu
*.exe
*.map
*.tmp
*.dll
*.bak
*.*-
*.corrupted
@ -15,3 +17,5 @@ hfs.ini
hfs.identcache
hfs.tpl
hfs_project.tvsconfig
data.res
macros-log.html

View File

@ -1,2 +1,26 @@
Work in progress.
Currently porting version 2.4 to Delphi 10.
# Obsolete
This is the repository of the old HFS.
I'm working on HFS 3 on another repository. Check it out!
https://github.com/rejetto/hfs
## Introduction
You can use HFS (HTTP File Server) to send and receive files.
It's different from classic file sharing because it uses web technology.
It also differs from classic web servers because it's very easy to use and runs "right out-of-the box".
The virtual file system will allow you to easily share even one single file.
## Dev notes
Initially developed in 2002 with Delphi 6, now with Delphi 10.3.3 (Community Edition).
Icons are generated at http://fontello.com/ . Use fontello.json for further modifications.
For the default template we are targeting compatibility with Chrome 49 as it's the latest version running on Windows XP.
Warning: Delphi Community Edition 10.4 removed support for command-line compilation, and is thus unable to compile JEDI Code Library, and is thus unable to compile HFS2, ref [Community Edition no longer includes the command-line compilers](https://blogs.embarcadero.com/delphi-cbuilder-community-editions-now-available-in-version-10-4-2/#comment-1339) - meaning the last version of Community Edition cabale of compiling HFS2 is Delphi 10.3.x
## Libs used
- [ICS v8.64](http://www.overbyte.be) by François PIETTE
- [TRegExpr v0.952b](https://github.com/andgineer/TRegExpr/releases) by Andrey V. Sorokin
- [JEDI Code Library v2.7](https://github.com/project-jedi/jcl)
- [Kryvich's Delphi Localizer v4.1](http://sites.google.com/site/kryvich)

15
SECURITY.md Normal file
View File

@ -0,0 +1,15 @@
# Security Policy
## Supported Versions
| Version | Supported |
| ------- | ------------------ |
| 2.4.x | :white_check_mark: |
| 2.3.x | :white_check_mark: |
| < 2.3 | :x: |
## Reporting a Vulnerability
Please report directly via email to a@rejetto.com for Responsible disclosure.
I should normally reply within 2 days, so we can agree on timings.

View File

@ -1,5 +1,5 @@
{
Copyright (C) 2002-2012 Massimo Melina (www.rejetto.com)
Copyright (C) 2002-2020 Massimo Melina (www.rejetto.com)
This file is part of HFS ~ HTTP File Server.
@ -23,9 +23,20 @@ unit classesLib;
interface
uses
iniFiles, types, hslib, strUtils, sysUtils, classes, math;
iniFiles, types, hslib, strUtils, sysUtils, classes, math, system.Generics.Collections,
OverbyteIcsWSocket, OverbyteIcshttpProt;
type
TantiDos = class
protected
accepted: boolean;
Paddress: string;
public
constructor create;
destructor Destroy; override;
function accept(conn:ThttpConn; address:string=''):boolean;
end;
TfastStringAppend = class
protected
buff: string;
@ -39,7 +50,7 @@ type
PcachedIcon = ^TcachedIcon;
TcachedIcon = record
data: ansistring;
data: string;
idx: integer;
time: Tdatetime;
end;
@ -47,11 +58,11 @@ type
TiconsCache = class
n: integer;
icons: array of TcachedIcon;
function get(data:ansistring):PcachedIcon;
procedure put(data:ansistring; idx:integer; time:Tdatetime);
function get(data:string):PcachedIcon;
procedure put(data:string; idx:integer; time:Tdatetime);
procedure clear();
procedure purge(olderThan:Tdatetime);
function idxOf(data:shortstring):integer;
function idxOf(data:string):integer;
end;
TusersInVFS = class
@ -88,6 +99,7 @@ type
constructor create;
destructor Destroy; override;
function addFile(src:string; dst:string=''; data:Tobject=NIL):boolean; virtual;
function contains(src:string):boolean;
function count():integer;
procedure reset(); virtual;
property totalSize:int64 read getTotal;
@ -105,7 +117,7 @@ type
function fsInit():boolean;
procedure headerInit(); // fill block with header
procedure padInit(full:boolean=FALSE); // fill block with pad
function headerLengthForFilename(fn:ansistring):integer;
function headerLengthForFilename(ufn:string):integer;
procedure calculate(); override;
public
fileNamesOEM: boolean;
@ -123,6 +135,10 @@ type
function getHashFor(fn:string):string;
end;
Tint2int = Tdictionary<integer,integer>;
Tstr2str = Tdictionary<string,string>;
Tstr2pointer = Tdictionary<string,pointer>;
TstringToIntHash = class(ThashedStringList)
constructor create;
function getInt(s:string):integer;
@ -134,7 +150,7 @@ type
PtplSection = ^TtplSection;
TtplSection = record
name, txt: string;
nolog, nourl, cache: boolean;
nolog, public, noList, cache: boolean;
ts: Tdatetime;
end;
@ -143,17 +159,15 @@ type
src: string;
lastExt, // cache for getTxtByExt()
last: record section:string; idx:integer; end; // cache for getIdx()
fileExts: TStringDynArray;
strTable: THashedStringList;
fOver: Ttpl;
function getIdx(section:string):integer;
sections: Tstr2pointer;
function getTxt(section:string):string;
function newSection(section:string):PtplSection;
procedure fromString(txt:string);
procedure setOver(v:Ttpl);
public
onChange: TNotifyEvent;
sections: array of TtplSection;
constructor create(txt:string=''; over:Ttpl=NIL);
destructor Destroy; override;
property txt[section:string]:string read getTxt; default;
@ -161,7 +175,7 @@ type
property over:Ttpl read fOver write setOver;
function sectionExist(section:string):boolean;
function getTxtByExt(fileExt:string):string;
function getSection(section:string):PtplSection;
function getSection(section:string; inherit:boolean=TRUE):PtplSection;
function getSections():TStringDynArray;
procedure appendString(txt:string);
function getStrByID(id:string):string;
@ -187,6 +201,12 @@ type
destructor Destroy; override;
end;
ThttpClient = class(TSslHttpCli)
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
class function createURL(url:string):ThttpClient;
end;
Ttlv = class
protected
cur, bound: integer;
@ -212,6 +232,94 @@ implementation
uses
utilLib, main, windows, dateUtils, forms;
const folderConcurrents: integer = 0;
const MAX_CONCURRENTS = 3;
const ip2availability: Tdictionary<string,Tdatetime> = NIL;
constructor TantiDos.create();
begin
accepted:=FALSE;
end;
function TantiDos.accept(conn:ThttpConn; address:string=''):boolean;
procedure reject();
resourcestring
MSG_ANTIDOS_REPLY = 'Please wait, server busy';
begin
conn.reply.mode:=HRM_OVERLOAD;
conn.addHeader(ansistring('Refresh: '+intToStr(1+random(2)))); // random for less collisions
conn.reply.body:=UTF8Encode(MSG_ANTIDOS_REPLY);
end;
begin
if address= '' then
address:=conn.address;
if ip2availability = NIL then
ip2availability:=Tdictionary<string,Tdatetime>.create();
try
if ip2availability[address] > now() then // this specific address has to wait?
begin
reject();
exit(FALSE);
end;
except
end;
if folderConcurrents >= MAX_CONCURRENTS then // max number of concurrent folder loading, others are postponed
begin
reject();
exit(FALSE);
end;
inc(folderConcurrents);
Paddress:=address;
ip2availability.AddOrSetValue(address, now()+1/HOURS);
accepted:=TRUE;
Result:=TRUE;
end;
destructor TantiDos.Destroy;
var
pair: Tpair<string,Tdatetime>;
t: Tdatetime;
begin
if not accepted then
exit;
t:=now();
if folderConcurrents = MAX_CONCURRENTS then // serving multiple addresses at max capacity, let's give a grace period for others
ip2availability[Paddress]:=t + 1/SECONDS
else
ip2availability.Remove(Paddress);
dec(folderConcurrents);
// purge leftovers
for pair in ip2availability do
if pair.Value < t then
ip2availability.Remove(pair.Key);
end;
class function ThttpClient.createURL(url:string):ThttpClient;
begin
if startsText('https://', url)
and not httpsCanWork() then
exit(NIL);
result:=ThttpClient.Create(NIL);
result.URL:=url;
end;
constructor ThttpClient.create(AOwner: TComponent);
begin
inherited;
followRelocation:=TRUE;
agent:=HFS_HTTP_AGENT;
SslContext := TSslContext.Create(NIL);
end; // create
destructor ThttpClient.Destroy;
begin
SslContext.free;
SslContext:=NIl;
inherited destroy;
end;
constructor TperIp.create();
begin
limiter:=TspeedLimiter.create();
@ -316,7 +424,7 @@ end; // match
//////////// TiconsCache
function TiconsCache.idxOf(data:shortstring):integer;
function TiconsCache.idxOf(data:string):integer;
var
b, e, c: integer;
begin
@ -335,7 +443,7 @@ e:=n-1;
result:=b;
end; // idxOf
function TiconsCache.get(data:ansistring):PcachedIcon;
function TiconsCache.get(data:string):PcachedIcon;
var
i: integer;
begin
@ -345,7 +453,7 @@ if (i >= 0) and (i < n) and (icons[i].data = data) then
result:=@icons[i];
end; // get
procedure TiconsCache.put(data:ansistring; idx:integer; time:Tdatetime);
procedure TiconsCache.put(data:string; idx:integer; time:Tdatetime);
var
i, w: integer;
begin
@ -417,6 +525,16 @@ if cachedTotal < 0 then calculate();
result:=cachedTotal;
end; // getTotal
function TarchiveStream.contains(src:string):boolean;
var
i: integer;
begin
for i:=0 to Length(flist)-1 do
if flist[i].src = src then
exit(TRUE);
result:=FALSE;
end;
function TarchiveStream.addFile(src:string; dst:string=''; data:Tobject=NIL):boolean;
function getMtime(fh:Thandle):int64;
@ -502,10 +620,7 @@ end; // reset
function TtarStream.fsInit():boolean;
begin
if assigned(fs) and (fs.FileName = flist[cur].src) then
begin
result:=TRUE;
exit;
end;
exit(TRUE);
result:=FALSE;
try
freeAndNIL(fs);
@ -569,7 +684,7 @@ var
begin
ufn:=replaceStr(flist[cur].dst,'\','/');
if fileNamesOEM then
CharToOem(pWideChar(ufn), pAnsiChar(fn))
fn:=strToOem(ufn)
else
fn:=UTF8encode(ufn);
pre:='';
@ -612,8 +727,14 @@ block.WriteString(dupeString(#0, if_(full,512,gap512(pos)) ));
block.Seek(0, soBeginning);
end; // padInit
function TtarStream.headerLengthForFilename(fn:ansistring):integer;
function TtarStream.headerLengthForFilename(ufn:string):integer;
var
fn: ansistring;
begin
if fileNamesOEM then
fn:=strToOem(ufn)
else
fn:=UTF8encode(ufn);
result:=length(fn);
result:=512*if_(result<100, 1, 3+result div 512);
end; // headerLengthForFilename
@ -738,10 +859,12 @@ var
var
i, posBak: int64;
n: integer;
begin
posBak:=pos;
p:=@buffer;
while (count > 0) and (cur < length(flist)) do
n:=length(flist);
while (count > 0) and (cur < n) do
case where of
TW_HEADER:
begin
@ -863,13 +986,14 @@ end; // autoupdatedFiles_getCounter
constructor Ttpl.create(txt:string=''; over:Ttpl=NIL);
begin
sections:=Tstr2pointer.Create();
fullText:=txt;
self.over:=over;
end;
destructor Ttpl.destroy;
begin
freeAndNIL(strTable);
fullText:=''; // this will cause the disposing
inherited;
end; // destroy
@ -885,106 +1009,50 @@ if (result = '') and assigned(over) then
result:=over.getStrByID(id)
end; // getStrByID
function Ttpl.getIdx(section:string):integer;
begin
if section <> last.section then
begin
last.section:=section;
for result:=0 to length(sections)-1 do
if sameText(sections[result].name, section) then
begin
last.idx:=result;
exit;
end;
last.idx:=-1;
end;
result:=last.idx
end; // getIdx
function Ttpl.newSection(section:string):PtplSection;
var
i: integer;
begin
// add
i:=length(sections);
setLength(sections, i+1);
result:=@sections[i];
result.name:=section;
// getIdx just filled 'last' with not-found, so we must update
last.section:=section;
last.idx:=i;
// manage file.EXT sections
if not ansiStartsText('file.', section) then exit;
i:=length(fileExts);
setLength(fileExts, i+2);
delete(section, 1, 4);
fileExts[i]:=section;
fileExts[i+1]:=str_(last.idx);
lastExt.section:=section;
lastExt.idx:=last.idx;
new(result);
sections.Add(section, result);
end; // newSection
function Ttpl.sectionExist(section:string):boolean;
begin
result:=getIdx(section)>=0;
result:=assigned(getSection(section));
if not result and assigned(over) then
result:=over.sectionExist(section);
end;
function Ttpl.getSection(section:string):PtplSection;
var
i: integer;
function Ttpl.getSection(section:string; inherit:boolean=TRUE):PtplSection;
begin
if sections.containsKey(section) then
result:=sections[section]
else
result:=NIL;
i:=getIdx(section);
if i >= 0 then result:=@sections[i];
if assigned(over) and ((result = NIL) or (trim(result.txt) = '')) then
if inherit and assigned(over) and (result = NIL) then
result:=over.getSection(section);
end; // getSection
function Ttpl.getTxt(section:string):string;
var
i: integer;
var p: PtplSection;
begin
i:=getIdx(section);
if i >= 0 then
result:=sections[i].txt
else if assigned(over) then
result:=over[section]
else
p:=getSection(section);
if p = NIL then
result:=''
else
result:=p.txt
end; // getTxt
function Ttpl.getTxtByExt(fileExt:string):string;
var
i: integer;
begin
result:='';
if (lastExt.section > '') and (fileExt = lastExt.section) then
begin
if lastExt.idx >= 0 then result:=sections[lastExt.idx].txt;
exit;
end;
i:=idxOf(fileExt, fileExts);
if (i < 0) and assigned(over) then
begin
result:=over.getTxtByExt(fileExt);
if result > '' then exit;
end;
lastExt.section:=fileExt;
lastExt.idx:=i;
if i < 0 then exit;
i:=int_(ansistring(fileExts[i+1]));
lastExt.idx:=i;
result:=sections[i].txt;
end; // getTxtByExt
begin result:=getTxt('file'+fileExt) end;
procedure Ttpl.fromString(txt:string);
var
p: PtplSection;
begin
src:='';
sections:=NIL;
fileExts:=NIL;
last.section:=#255'null'; // '' is a valid (and often used) section name. This is a better null value.
for p in sections.values do
dispose(p);
sections.clear();
freeAndNIL(strTable); // mod by mars
appendString(txt);
@ -1025,12 +1093,52 @@ var
procedure saveInSection();
var
ss: TStringDynArray;
s: string;
i, si: integer;
base: TtplSection;
function parseFlagsAndAcceptSection(flags:TStringDynArray):boolean;
var
f, k, v, s: string;
i: integer;
begin
for f in flags do
begin
i:=pos('=',f);
if i = 0 then
begin
if f='no log' then
base.nolog:=TRUE
else if f='public' then
base.public:=TRUE
else if f='no list' then
base.noList:=TRUE
else if f='cache' then
base.cache:=TRUE;
Continue;
end;
k:=copy(f,1,i-1);
v:=copy(f,i+1,MAXINT);
if k = 'build' then
begin
s:=chop('-',v);
if (v > '') and (VERSION_BUILD > v) // max
or (s > '') and (VERSION_BUILD < s) then // min
exit(FALSE);
end
else if k = 'ver' then
if fileMatch(v, VERSION) then continue
else exit(FALSE)
else if k = 'template' then
if fileMatch(v, getTill(#13,getTxt('template id'))) then continue
else exit(FALSE)
end;
result:=TRUE;
end;
var
ss: TStringDynArray;
s, si: string;
till: pchar;
append: boolean;
append, prepend, add: boolean;
sect, from: PtplSection;
begin
till:=pred(bos);
@ -1038,47 +1146,49 @@ var
if till^ = #10 then dec(till);
if till^ = #13 then dec(till);
base:=default(TtplSection);
base.txt:=getStr(ptxt, till);
// there may be flags after |
s:=cur_section;
cur_section:=chop('|', s);
base.nolog:=ansiPos('no log', s) > 0;
base.nourl:=ansiPos('private', s) > 0;
base.cache:=ansiPos('cache', s) > 0;
base.ts:=now();
ss:=split('|',cur_section);
cur_section:=popString(ss);
if not parseFlagsAndAcceptSection(ss) then
exit;
s:=cur_section;
append:=ansiStartsStr('+', s);
if append then
delete(s,1,1);
prepend:=startsStr('^', cur_section);
append:=startsStr('+', cur_section);
add:=prepend or append;
if add then
delete(cur_section,1,1);
// there may be several section names separated by =
ss:=split('=', s);
ss:=split('=', cur_section);
// handle the main section specific case
if ss = NIL then addString('', ss);
if ss = NIL then
addString('', ss);
// assign to every name the same txt
for i:=0 to length(ss)-1 do
for si in ss do
begin
s:=trim(ss[i]);
si:=getIdx(s);
s:=trim(si);
sect:=getSection(s, FALSE);
from:=NIL;
if si < 0 then // not found
if sect = NIL then // not found
begin
if append then
if add then
from:=getSection(s);
sect:=newSection(s);
end
else
begin
sect:=@sections[si];
if append then
if add then
from:=sect;
end;
if from<>NIL then
begin // inherit from it
sect.txt:=from.txt+base.txt;
if append then
sect.txt:=from.txt+base.txt
else
sect.txt:=base.txt+CRLF+from.txt;
sect.nolog:=from.nolog or base.nolog;
sect.nourl:=from.nourl or base.nourl;
sect.public:=from.public or base.public;
sect.noList:=from.noList or base.noList;
continue;
end;
sect^:=base;
@ -1087,13 +1197,12 @@ var
end; // saveInSection
const
BOM = #$EF#$BB#$BF;
UTF8_BOM = #$EF#$BB#$BF;
var
first: boolean;
begin
// this is used by some unicode files. at the moment we just ignore it.
if ansiStartsStr(BOM, txt) then
delete(txt, 1, length(BOM));
if ansiStartsStr(UTF8_BOM, txt) then
delete(txt, 1, length(UTF8_BOM));
if txt = '' then exit;
src:=src+txt;
@ -1120,14 +1229,7 @@ fOver:=v;
end; // setOver
function Ttpl.getSections():TStringDynArray;
var
i: integer;
begin
i:=length(sections);
setLength(result, i);
for i:=0 to i-1 do
result[i]:=sections[i].name;
end;
begin result:=sections.Keys.ToArray() end;
function Ttpl.me():Ttpl;
begin result:=self end;
@ -1146,8 +1248,8 @@ function Ttlv.pop(var value:string; var raw:ansistring):integer;
var
n: integer;
begin
result:=-1;
if isOver() then exit; // finished
if isOver() then
exit(-1); // finished
result:=integer((@whole[cur])^);
n:=Pinteger(@whole[cur+4])^;
raw:=copy(whole, cur+8, n);
@ -1166,10 +1268,7 @@ function Ttlv.down():boolean;
begin
// do we have anything to recur on?
if (cur = 1) then
begin
result:=false;
exit;
end;
exit(FALSE);
// push into the stack
if (stackTop = length(stack)) then // space over
setLength(stack, stackTop+10); // make space
@ -1186,10 +1285,7 @@ end; // down
function Ttlv.up():boolean;
begin
if stackTop = 0 then
begin
result:=false;
exit;
end;
exit(FALSE);
dec(stackTop);
bound:=stack[stackTop];
dec(stackTop);

View File

@ -1,6 +1,674 @@
HFS version %s, Copyright (C) 2002-2020 Massimo Melina (www.rejetto.com)
HFS comes with ABSOLUTELY NO WARRANTY; for details click Menu -> Web links -> License
This is FREE software, and you are welcome to redistribute it
under certain conditions.
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Build #%s
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

View File

@ -1 +0,0 @@
127.0.0.1=(Private Address) (XX)

BIN
data.RES

Binary file not shown.

View File

@ -1,12 +1,7 @@
1 24 "WindowsXP.manifest"
defaultTpl TEXT default.tpl
copyright TEXT copyright.txt
dmBrowserTpl TEXT dmBrowser.tpl
invertban TEXT invertban.txt
filelistTpl TEXT filelist.tpl
uploadDisabled TEXT upload_disabled.txt
uploadHowTo TEXT upload_how.txt
alias TEXT alias.txt
shell GIF shell.gif
IPservices TEXT ipservices.txt
jquery TEXT jquery.min.js

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,6 @@
{$DEFINE STABLE }
{$A+,B-,C+,E-,F-,G+,H+,I-,J+,K-,L+,M-,N+,O+,P+,Q-,R-,S-,T-,U-,V+,X+,Y+,Z1}
{$DEFINE NOT STABLE }
{$IFDEF STABLE }
{$ASSERTIONS OFF}
{$ELSE}

View File

@ -1,29 +0,0 @@
=== LIBS USED
ICS v7 by François PIETTE http://www.overbyte.be
GIFimage v2.2r5 by Anders Melander http://www.tolderlund.eu/delphi/
delphi zlib v1.2.3 by base2 technologies http://www.base2ti.com
TRegExpr v0.952 by Andrey V. Sorokin http://www.regexpstudio.com/TRegExpr/TRegExpr.html
fastMM v4 by Pierre le Riche http://fastmm.sourceforge.net
Kryvich's Delphi Localizer v3.2 https://sites.google.com/site/kryvich/
=== CGI
see python\Lib\CGIHTTPServer.py
=== CAPABILITIES OF A SCRIPTING SYSTEMS
- skip limits on some files
=== UNICODE FILENAMES
widgets required:
- treeview (vfs)
- listbox (connections)
- richedit (log)
code to adapt
- TfileListing.fromFolder()
- getVFS()
- setVFS()
=== DEFAULT TEMPLATE
- detect mobile and use special template

View File

@ -33,6 +33,10 @@ object filepropFrm: TfilepropFrm
object permTab: TTabSheet
Caption = 'Permissions'
ImageIndex = 1
ExplicitLeft = 0
ExplicitTop = 0
ExplicitWidth = 0
ExplicitHeight = 0
object actionTabs: TTabControl
Left = 0
Top = 0
@ -124,6 +128,10 @@ object filepropFrm: TfilepropFrm
object flagsTab: TTabSheet
Caption = 'Flags'
ImageIndex = 2
ExplicitLeft = 0
ExplicitTop = 0
ExplicitWidth = 0
ExplicitHeight = 0
object hiddenChk: TCheckBox
Left = 32
Top = 24
@ -210,6 +218,10 @@ object filepropFrm: TfilepropFrm
object diffTab: TTabSheet
Caption = 'Diff template'
ImageIndex = 3
ExplicitLeft = 0
ExplicitTop = 0
ExplicitWidth = 0
ExplicitHeight = 0
object difftplBox: TMemo
Left = 0
Top = 0
@ -227,6 +239,10 @@ object filepropFrm: TfilepropFrm
object commentTab: TTabSheet
Caption = 'Comment'
ImageIndex = 4
ExplicitLeft = 0
ExplicitTop = 0
ExplicitWidth = 0
ExplicitHeight = 0
object commentBox: TMemo
Left = 0
Top = 0
@ -241,6 +257,10 @@ object filepropFrm: TfilepropFrm
object maskTab: TTabSheet
Caption = 'File masks'
ImageIndex = 5
ExplicitLeft = 0
ExplicitTop = 0
ExplicitWidth = 0
ExplicitHeight = 0
DesignSize = (
385
338)
@ -321,6 +341,10 @@ object filepropFrm: TfilepropFrm
object otherTab: TTabSheet
Caption = 'Other'
ImageIndex = 5
ExplicitLeft = 0
ExplicitTop = 0
ExplicitWidth = 0
ExplicitHeight = 0
DesignSize = (
385
338)
@ -356,7 +380,6 @@ object filepropFrm: TfilepropFrm
Height = 22
ItemsEx = <>
Style = csExDropDownList
ItemHeight = 16
TabOrder = 1
Images = mainFrm.images
end

View File

@ -160,7 +160,7 @@ end;
procedure TfilepropFrm.FormKeyPress(Sender: TObject; var Key: Char);
begin
if pages.focused then
if key in ['1'..'9'] then
if charInSet(key, ['1'..'9']) then
try pages.TabIndex:=ord(key)-ord('0')-1
except end;
end;

196
fontello.json Normal file
View File

@ -0,0 +1,196 @@
{
"name": "",
"css_prefix_text": "fa-",
"css_use_suffix": false,
"hinting": true,
"units_per_em": 1000,
"ascent": 850,
"glyphs": [
{
"uid": "823a9e02e643318116fea40a00190e4e",
"css": "asterisk",
"code": 59392,
"src": "fontawesome"
},
{
"uid": "43ab845088317bd348dee1d975700c48",
"css": "check-circled",
"code": 59393,
"src": "fontawesome"
},
{
"uid": "8b80d36d4ef43889db10bc1f0dc9a862",
"css": "user",
"code": 59394,
"src": "fontawesome"
},
{
"uid": "598a5f2bcf3521d1615de8e1881ccd17",
"css": "clock",
"code": 59395,
"src": "fontawesome"
},
{
"uid": "9a76bc135eac17d2c8b8ad4a5774fc87",
"css": "download",
"code": 59396,
"src": "fontawesome"
},
{
"uid": "eeec3208c90b7b48e804919d0d2d4a41",
"css": "upload",
"code": 59397,
"src": "fontawesome"
},
{
"uid": "98d9c83c1ee7c2c25af784b518c522c5",
"css": "ban",
"code": 59398,
"src": "fontawesome"
},
{
"uid": "d35a1d35efeb784d1dc9ac18b9b6c2b6",
"css": "edit",
"code": 59399,
"src": "fontawesome"
},
{
"uid": "dd6c6b221a1088ff8a9b9cd32d0b3dd5",
"css": "check",
"code": 59400,
"src": "fontawesome"
},
{
"uid": "f8aa663c489bcbd6e68ec8147dca841e",
"css": "folder",
"code": 59401,
"src": "fontawesome"
},
{
"uid": "197375a3cea8cb90b02d06e4ddf1433d",
"css": "globe",
"code": 59402,
"src": "fontawesome"
},
{
"uid": "d7271d490b71df4311e32cdacae8b331",
"css": "home",
"code": 59403,
"src": "fontawesome"
},
{
"uid": "f2aa28a2548ed3d2be718d087b65ee21",
"css": "key",
"code": 59404,
"src": "fontawesome"
},
{
"uid": "c1f1975c885aa9f3dad7810c53b82074",
"css": "lock",
"code": 59405,
"src": "fontawesome"
},
{
"uid": "a73c5deb486c8d66249811642e5d719a",
"css": "refresh",
"code": 59406,
"src": "fontawesome"
},
{
"uid": "09feb4465d9bd1364f4e301c9ddbaa92",
"css": "retweet",
"code": 59407,
"src": "fontawesome"
},
{
"uid": "474656633f79ea2f1dad59ff63f6bf07",
"css": "star",
"code": 59408,
"src": "fontawesome"
},
{
"uid": "0f4cae16f34ae243a6144c18a003f2d8",
"css": "cancel-circled",
"code": 59409,
"src": "fontawesome"
},
{
"uid": "7f3d8ff1d5f6ee019f0c00ed7a86caec",
"css": "truck",
"code": 59410,
"src": "fontawesome"
},
{
"uid": "559647a6f430b3aeadbecd67194451dd",
"css": "menu",
"code": 61641,
"src": "fontawesome"
},
{
"uid": "3a26448b711645ba1abfc86c1a6e2f30",
"css": "coffee",
"code": 61684,
"src": "fontawesome"
},
{
"uid": "ab95e1351ebaec5850101097cbf7097f",
"css": "quote-left",
"code": 61709,
"src": "fontawesome"
},
{
"uid": "e80ae555c1413a4ec18b33fb348b4049",
"css": "file-archive",
"code": 61894,
"src": "fontawesome"
},
{
"uid": "bbfb51903f40597f0b70fd75bc7b5cac",
"css": "trash",
"code": 61944,
"src": "fontawesome"
},
{
"uid": "818981e2ad316f18ae61cfa805d41309",
"css": "user-circle",
"code": 62141,
"src": "fontawesome"
},
{
"uid": "5278ef7773e948d56c4d442c8c8c98cf",
"css": "lightbulb",
"code": 61675,
"src": "fontawesome"
},
{
"uid": "56a21935a5d4d79b2e91ec00f760b369",
"css": "sort",
"code": 61660,
"src": "fontawesome"
},
{
"uid": "0cd2582b8c93719d066ee0affd02ac78",
"css": "sort-alt-up",
"code": 61792,
"src": "fontawesome"
},
{
"uid": "27b13eff5eb0ca15e01a6e65ffe6eeec",
"css": "sort-alt-down",
"code": 61793,
"src": "fontawesome"
},
{
"uid": "9dd9e835aebe1060ba7190ad2b2ed951",
"css": "search",
"code": 59411,
"src": "fontawesome"
},
{
"uid": "0d20938846444af8deb1920dc85a29fb",
"css": "logout",
"code": 59412,
"src": "fontawesome"
}
]
}

133
hfs.dof
View File

@ -1,133 +0,0 @@
[FileVersion]
Version=6.0
[Compiler]
A=8
B=0
C=1
D=1
E=0
F=0
G=1
H=1
I=1
J=0
K=0
L=1
M=0
N=1
O=1
P=1
Q=0
R=0
S=0
T=0
U=0
V=1
W=1
X=1
Y=2
Z=1
ShowHints=1
ShowWarnings=1
UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
[Linker]
MapFile=3
OutputObjs=0
ConsoleApp=1
DebugInfo=0
RemoteSymbols=0
MinStackSize=16384
MaxStackSize=1048576
ImageBase=4194304
ExeDescription=Http File Server - www.rejetto.com/hfs
[Directories]
OutputDir=
UnitOutputDir=
PackageDLLOutputDir=
PackageDCPOutputDir=
SearchPath=$(DELPHI)\Lib\Debug;C:\code\other\compiled
Packages=vcl;rtl;vclx;VclSmp;DJCL60;IcsDel60
Conditionals=
DebugSourceDirs=C:\code\other\ics\Delphi\Vc32\
UsePackages=0
[Parameters]
RunParams=
HostApplication=
Launcher=
UseLauncher=0
DebugCWD=
[Version Info]
IncludeVerInfo=0
AutoIncBuild=0
MajorVer=1
MinorVer=6
Release=0
Build=0
Debug=0
PreRelease=0
Special=0
Private=0
DLL=0
Locale=1040
CodePage=1252
[Version Info Keys]
CompanyName=rejetto
FileDescription=
FileVersion=1.6.0.0
InternalName=HFS
LegalCopyright=Copyright (C) 2002-2004 Massimo Melina (www.rejetto.com)
LegalTrademarks=
OriginalFilename=hfs.exe
ProductName=Http File Server
ProductVersion=1.0.0.0
Comments=
[Excluded Packages]
c:\programmi\borland\delphi6\Bin\dclshlctrls60.bpl=Shell Control Property and Component Editors
c:\programmi\borland\delphi6\Projects\Bpl\dclusr60.bpl=Borland User Components
C:\PROGRA~1\Borland\Delphi6\Projects\Bpl\JclBaseExpertD60.bpl=JCL Package containing common units for JCL Experts
C:\PROGRA~1\Borland\Delphi6\Projects\Bpl\JclDebugExpertD60.bpl=JCL Debug IDE extension
C:\PROGRA~1\Borland\Delphi6\Projects\Bpl\JclProjectAnalysisExpertD60.bpl=JCL Project Analyzer
C:\PROGRA~1\Borland\Delphi6\Projects\Bpl\JclFavoriteFoldersExpertD60.bpl=JCL Open and Save IDE dialogs with favorite folders
C:\PROGRA~1\Borland\Delphi6\Projects\Bpl\JclThreadNameExpertD60.bpl=JCL Thread Name IDE expert
C:\PROGRA~1\Borland\Delphi6\Projects\Bpl\JclUsesExpertD60.bpl=JCL Uses Wizard
C:\PROGRA~1\Borland\Delphi6\Projects\Bpl\JclSIMDViewExpertD60.bpl=JCL Debug Window of XMM registers
C:\Programmi\Borland\Delphi6\Projects\Bpl\JvAppFrmD6D.bpl=JVCL Application and Form Components
C:\PROGRA~1\Borland\Delphi6\Projects\Bpl\JvCoreD6D.bpl=JVCL Core Components
C:\Programmi\Borland\Delphi6\Projects\Bpl\JvBandsD6D.bpl=JVCL Band Objects
C:\Programmi\Borland\Delphi6\Projects\Bpl\JvCmpD6D.bpl=JVCL Non-Visual Components
C:\Programmi\Borland\Delphi6\Projects\Bpl\JvCryptD6D.bpl=JVCL Encryption and Compression Components
C:\Programmi\Borland\Delphi6\Projects\Bpl\JvCtrlsD6D.bpl=JVCL Visual Controls
C:\Programmi\Borland\Delphi6\Projects\Bpl\JvCustomD6D.bpl=JVCL Custom Controls
C:\Programmi\Borland\Delphi6\Projects\Bpl\JvDlgsD6D.bpl=JVCL Dialog Components
C:\Programmi\Borland\Delphi6\Projects\Bpl\JvDockingD6D.bpl=JVCL Docking Components
C:\Programmi\Borland\Delphi6\Projects\Bpl\JvDotNetCtrlsD6D.bpl=JVCL DotNet Controls
C:\Programmi\Borland\Delphi6\Projects\Bpl\JvGlobusD6D.bpl=JVCL Globus Components
C:\Programmi\Borland\Delphi6\Projects\Bpl\JvHMID6D.bpl=JVCL HMI Controls design time unit
C:\Programmi\Borland\Delphi6\Projects\Bpl\JvInterpreterD6D.bpl=JVCL Interpreter Components
C:\Programmi\Borland\Delphi6\Projects\Bpl\JvJansD6D.bpl=JVCL Jans Components
C:\Programmi\Borland\Delphi6\Projects\Bpl\JvManagedThreadsD6D.bpl=JVCL Managed Threads
C:\Programmi\Borland\Delphi6\Projects\Bpl\JvMMD6D.bpl=JVCL Multimedia and Image Components
C:\Programmi\Borland\Delphi6\Projects\Bpl\JvNetD6D.bpl=JVCL Network Components
C:\Programmi\Borland\Delphi6\Projects\Bpl\JvPageCompsD6D.bpl=JVCL Page Style Components
C:\Programmi\Borland\Delphi6\Projects\Bpl\JvPluginD6D.bpl=JVCL Plugin Components
C:\Programmi\Borland\Delphi6\Projects\Bpl\JvPrintPreviewD6D.bpl=JVCL Print Preview Components
C:\Programmi\Borland\Delphi6\Projects\Bpl\JvRuntimeDesignD6D.bpl=JVCL Runtime Design Components
C:\Programmi\Borland\Delphi6\Projects\Bpl\JvStdCtrlsD6D.bpl=JVCL Standard Controls
C:\Programmi\Borland\Delphi6\Projects\Bpl\JvSystemD6D.bpl=JVCL System Components
C:\Programmi\Borland\Delphi6\Projects\Bpl\JvTimeFrameworkD6D.bpl=JVCL Time Framework
C:\Programmi\Borland\Delphi6\Projects\Bpl\JvUIBD6D.bpl=JVCL Unified Interbase Components
C:\Programmi\Borland\Delphi6\Projects\Bpl\JvValidatorsD6D.bpl=JVCL Validators and Error Provider Components
C:\Programmi\Borland\Delphi6\Projects\Bpl\JvWizardD6D.bpl=JVCL Wizard Design Time Package
C:\Programmi\Borland\Delphi6\Projects\Bpl\JvXPCtrlsD6D.bpl=JVCL XP Controls
C:\PROGRAMMI\BORLAND\DELPHI6\Bin\PDIFac60.bpl=Interface for ProDelphi viewer
c:\programmi\borland\delphi6\Bin\dcl31w60.bpl=Delphi 1.0 Compatibility Components
c:\programmi\borland\delphi6\Projects\Bpl\VirtualTreesD6D.bpl=Virtual Treeview
[HistoryLists\hlDebugSourcePath]
Count=1
Item0=C:\code\other\ics\Delphi\Vc32\
[HistoryLists\hlUnitAliases]
Count=1
Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
[HistoryLists\hlSearchPath]
Count=1
Item0=$(DELPHI)\Lib\Debug;C:\code\other\compiled

View File

@ -25,6 +25,7 @@ uses
{$IFDEF EX_DEBUG}
ftmExceptionForm,
{$ENDIF }
uFreeLocalizer,
monoLib,
Forms,
windows,
@ -94,14 +95,14 @@ begin
end;
{$IFDEF EX_DEBUG}initErrorHandler(format('HFS %s (%s)', [VERSION, VERSION_BUILD]));{$ENDIF}
Application.Initialize();
{
if fileExists('hfs.lng') then
begin
FreeLocalizer.AutoTranslate := True;
try FreeLocalizer.LanguageFile := 'hfs.lng';
except msgDlg('Localization not supporting your codepage', MB_ICONERROR+MB_OK) end;
end;
}
Application.CreateForm(TmainFrm, mainFrm);
Application.CreateForm(TnewuserpassFrm, newuserpassFrm);
Application.CreateForm(ToptionsFrm, optionsFrm);

View File

@ -206,12 +206,6 @@
</Platforms>
<ModelSupport>False</ModelSupport>
<Deployment Version="3">
<DeployFile LocalName="hfs.exe" Configuration="Release" Class="ProjectOutput">
<Platform Name="Win32">
<RemoteName>hfs.exe</RemoteName>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="hfs.dpr" Configuration="Release" Class="ProjectFile">
<Platform Name="Win32">
<RemoteDir>.\</RemoteDir>
@ -225,6 +219,12 @@
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="hfs.exe" Configuration="Release" Class="ProjectOutput">
<Platform Name="Win32">
<RemoteName>hfs.exe</RemoteName>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="hfs.dpr" Configuration="Debug" Class="ProjectFile">
<Platform Name="Win32">
<RemoteDir>.\</RemoteDir>

View File

@ -31,11 +31,7 @@
<File Path="shellExtDlg.dfm"/>
<File Path="utillib.pas"/>
<File Path="traylib.pas"/>
<File Path="inputDialogs.pas"/>
<File Path="inputDialogs.dfm"/>
</ProjectSortOrder> <Transactions>
<Transaction>2020/05/06 23:30:42.800,=C:\code\mine\hfs\Unit1.pas</Transaction>
<Transaction>2020/05/06 23:38:14.406,C:\code\mine\hfs\inputDialogs.dfm=C:\code\mine\hfs\Unit1.dfm</Transaction>
<Transaction>2020/05/06 23:38:14.406,C:\code\mine\hfs\inputDialogs.pas=C:\code\mine\hfs\Unit1.pas</Transaction>
</ProjectSortOrder>
<Transactions>
</Transactions>
</BorlandProject>

1842
hfs.drc

File diff suppressed because it is too large Load Diff

185
hfs.dsk
View File

@ -1,185 +0,0 @@
[Closed Files]
File_0=SourceModule,'C:\code\mine\hfs\whatsnew.txt',0,1,13,28,45,0,0
File_1=SourceModule,'C:\code\mine\hslib\hslib.pas',0,1,901,26,924,0,0
File_2=SourceModule,'C:\code\mine\hfs\utillib.pas',0,1,46,1,80,0,0
File_3=SourceModule,'C:\code\mine\hfs\todo.txt',0,1,1,1,1,0,0
File_4=SourceModule,'C:\code\other\ics\Delphi\Vc32\WSocket.pas',0,1,2948,36,2957,0,0
File_5=SourceModule,'C:\code\other\ics\Delphi\Vc32\WSocketS.pas',0,1,48,46,265,0,0
File_6=SourceModule,'C:\code\other\ics\Delphi\Vc32\UUEncode.pas',0,1,64,21,82,0,0
File_7=SourceModule,'C:\code\mine\andrq\utilLib.pas',0,1,3737,25,3767,0,0
File_8=SourceModule,'C:\code\mine\andrq\prefDlg.pas',0,1,570,27,590,1,0
[Modules]
Module0=C:\code\mine\hfs\main.pas
Count=1
EditWindowCount=1
[C:\code\mine\hfs\main.pas]
ModuleType=SourceModule
FormState=1
FormOnTop=0
[C:\Programmi\Borland\Delphi6\Projects\ProjectGroup1.bpg]
FormState=0
FormOnTop=0
[C:\code\mine\hfs\hfs.dpr]
FormState=0
FormOnTop=0
[EditWindow0]
ViewCount=1
CurrentView=0
View0=0
MessageView=MessageView@EditWindow0
Create=1
Visible=1
State=0
Left=190
Top=101
Width=834
Height=639
MaxLeft=-4
MaxTop=97
ClientWidth=826
ClientHeight=612
LeftPanelSize=0
RightPanelSize=0
BottomPanelSize=0
BottomPanelClients=MessageView@EditWindow0
BottomPanelData=00000400010000000B0000004D6573736167655669657700000000000000000000000000000000000100000000000000000B0000004D65737361676556696577FFFFFFFF
[View0]
Module=C:\code\mine\hfs\main.pas
CursorX=33
CursorY=63
TopLine=41
LeftCol=1
[Watches]
Count=1
Watch0='h',256,0,18,1,0
[Breakpoints]
Count=0
[AddressBreakpoints]
Count=0
[Main Window]
Create=1
Visible=1
State=2
Left=0
Top=0
Width=1024
Height=105
MaxLeft=-4
MaxTop=-4
MaxWidth=1032
MaxHeight=105
ClientWidth=1024
ClientHeight=78
[ProjectManager]
Create=1
Visible=0
State=0
Left=369
Top=372
Width=438
Height=303
MaxLeft=-1
MaxTop=-1
ClientWidth=430
ClientHeight=279
TBDockHeight=303
LRDockWidth=438
Dockable=1
[CPUWindow]
Create=1
Visible=0
State=0
Left=245
Top=207
Width=533
Height=353
MaxLeft=-1
MaxTop=-1
ClientWidth=525
ClientHeight=326
DumpPane=79
DisassemblyPane=187
RegisterPane=231
FlagPane=64
[AlignmentPalette]
Create=1
Visible=0
State=0
Left=200
Top=107
Width=156
Height=82
MaxLeft=-1
MaxTop=-1
ClientWidth=150
ClientHeight=60
[PropertyInspector]
Create=1
Visible=1
State=0
Left=0
Top=119
Width=190
Height=621
MaxLeft=-1
MaxTop=-1
ClientWidth=182
ClientHeight=597
TBDockHeight=621
LRDockWidth=190
Dockable=1
SplitPos=85
ArrangeBy=Name
SelectedItem=Caption
ExpandedItems=
HiddenCategories=
[ObjectTree]
Create=1
Visible=1
State=0
Left=1
Top=99
Width=190
Height=252
MaxLeft=-1
MaxTop=-1
ClientWidth=182
ClientHeight=228
TBDockHeight=252
LRDockWidth=190
Dockable=1
[MessageView@EditWindow0]
Create=1
Visible=0
State=0
Left=12
Top=0
Width=814
Height=52
MaxLeft=-1
MaxTop=-1
ClientWidth=814
ClientHeight=52
TBDockHeight=52
LRDockWidth=443
Dockable=1
[DockHosts]
DockHostCount=0

View File

@ -1,3 +0,0 @@
[+download]
{.remove header|ETag.}
{.remove header|Set-cookie.}

763
hfs.lng Normal file
View File

@ -0,0 +1,763 @@
; Kryvich's Delphi Localizer Language File.
; Generated by K.D.L. Scanner, 02/08/2020 18:30:32
Humanize=1
HumanizedCR=\^
HumanizedCRLF=\+
HumanizedLF=\#10
[TdiffFrm]
Caption=Customized options
[TfilepropFrm]
Caption=filepropFrm
pages.permTab.Caption=Permissions
pages.permTab.actionTabs.newaccBtn.Caption=New account
pages.permTab.actionTabs.anyAccChk.Caption=Any account
pages.permTab.actionTabs.anonChk.Caption=Anonymous
pages.permTab.actionTabs.allBtn.Caption=All / None
pages.permTab.actionTabs.anyoneChk.Caption=Anyone
pages.permTab.actionTabs.goToAccountsBtn.Caption=Manage accounts
pages.flagsTab.Caption=Flags
pages.flagsTab.hiddenChk.Hint=Test
pages.flagsTab.hiddenChk.Caption=Hidden
pages.flagsTab.hidetreeChk.Caption=Recursively hidden
pages.flagsTab.archivableChk.Caption=Archivable
pages.flagsTab.browsableChk.Caption=Browsable
pages.flagsTab.dontlogChk.Caption=Don't log
pages.flagsTab.nodlChk.Caption=No download
pages.flagsTab.dontconsiderChk.Caption=Don't consider as download
pages.flagsTab.hideemptyChk.Caption=Auto-hide empty folders
pages.flagsTab.hideextChk.Caption=Hide file extension in listing
pages.diffTab.Caption=Diff template
pages.diffTab.difftplBox.Hint=Here you can put a partial template that will overlap the main one.
pages.commentTab.Caption=Comment
pages.maskTab.Caption=File masks
pages.maskTab.filesfilterBox.EditLabel.Caption=Files filter
pages.maskTab.foldersfilterBox.EditLabel.Caption=Folders filter
pages.maskTab.deffileBox.Hint=When a folder is browsed, the default file mask is used to find a file to serve in place of the folder page. If no file is found, the folder page is served.
pages.maskTab.deffileBox.EditLabel.Caption=Default file mask
pages.maskTab.uploadfilterBox.Hint=Uploaded files are allowed only complying with this file mask
pages.maskTab.uploadfilterBox.EditLabel.Caption=Upload filter mask
pages.maskTab.dontconsiderBox.Hint=Files matching this filemask are not considered for global downloads counter. Moreover they never get tray icon.
pages.maskTab.dontconsiderBox.EditLabel.Caption=Don't consider as download (mask)
pages.otherTab.Caption=Other
pages.otherTab.Label1.Caption=Icon
pages.otherTab.realmBox.Hint=The realm string is shown on the user/pass dialog of the browser. This realm will be used for selected files and their descendants.
pages.otherTab.realmBox.EditLabel.Caption=Realm
pages.otherTab.addiconBtn.Caption=Add new...
Panel1.okBtn.Caption=&OK
Panel1.cancelBtn.Caption=Cancel
Panel1.applyBtn.Caption=&Apply
[TfolderKindFrm]
Caption=What kind of folder do you want?
realLbl.Caption=A real folder is faster, good for big folders
virtuaLbl.Caption=A virtual folder is easier, good for small folders
hintLbl.Caption=Not sure? Hint: most time you need real folders!
realBtn.Caption=&Real folder
virtuaBtn.Caption=&Virtual folder
[TipsEverFrm]
Caption=Addresses ever connected
totalLbl.Caption=Total label...
resetBtn.Caption=&Reset
editBtn.Caption=&Open in editor
[TlistSelectFrm]
Panel1.okBtn.Caption=&OK
Panel1.cancelBtn.Caption=&Cancel
[TlonginputFrm]
Caption=longinputFrm
bottomPnl.okBtn.Caption=&OK
bottomPnl.cancelBtn.Caption=&Cancel
topPnl.msgLbl.Caption=test
inputBox.Lines.Strings=Memo1
[TmainFrm]
Caption=HFS ~ HTTP File Server
graphBox.Hint=Pink = Out\+Yellow = In
topToolbar.Caption=topToolbar
topToolbar.menuBtn.Hint=Hit ALT or F10 to pop it up
topToolbar.menuBtn.Caption=Menu
topToolbar.ToolButton4.Caption=ToolButton4
topToolbar.portBtn.Caption=Port: any
topToolbar.ToolButton2.Caption=ToolButton2
topToolbar.modeBtn.Hint=Click to switch\+F5 on keyboard
topToolbar.modeBtn.Caption=You are in Easy mode
topToolbar.ToolButton1.Caption=ToolButton1
topToolbar.startBtn.Hint=Click to switch ON\^F4 on keyboard
topToolbar.startBtn.Caption=Server is currently OFF
topToolbar.abortBtn.Caption=Abort file addition
topToolbar.restoreCfgBtn.Caption=Restore my options
topToolbar.updateBtn.Caption=Update now
urlToolbar.browseBtn.Caption=Open in browser
urlToolbar.copyBtn.Caption=Copy to clipboard
centralPnl.logPnl.logTitle.titlePnl.Caption=Log
centralPnl.logPnl.logTitle.logToolbar.collapsedPnl.expandBtn.Hint=Expand toolbar
centralPnl.logPnl.logTitle.logToolbar.expandedPnl.openFilteredLog.Hint=Copy to editor only lines matched by the search pattern
centralPnl.logPnl.logTitle.logToolbar.expandedPnl.openLogBtn.Hint=Copy to editor
centralPnl.logPnl.logTitle.logToolbar.expandedPnl.collapseBtn.Hint=Collapse toolbar
centralPnl.logPnl.logTitle.logToolbar.expandedPnl.searchPnl.logSearchBox.Hint=Wildcards allowed
centralPnl.logPnl.logTitle.logToolbar.expandedPnl.searchPnl.logSearchBox.EditLabel.Caption=Search
centralPnl.filesPnl.Caption=filesPnl
centralPnl.filesPnl.filesTitle.Caption=Virtual File System
centralPnl.connPnl.connBox.Columns.(0).Caption=IP address
centralPnl.connPnl.connBox.Columns.(1).Caption=File
centralPnl.connPnl.connBox.Columns.(2).Caption=Status
centralPnl.connPnl.connBox.Columns.(3).Caption=Speed
centralPnl.connPnl.connBox.Columns.(4).Caption=Time left
centralPnl.connPnl.connBox.Columns.(5).Caption=Progress
filemenu.Addfiles1.Caption=Add files...
filemenu.Addfolder1.Caption=Add folder from disk...
filemenu.newfolder1.Caption=New empty folder
filemenu.Newlink1.Caption=New link
filemenu.Remove1.Caption=Remove
filemenu.Rename1.Caption=Rename
filemenu.Paste1.Caption=Paste
filemenu.Editresource1.Caption=Edit resource...
filemenu.CopyURL1.Caption=Copy URL address
filemenu.CopyURL1.Hint=just double click!
filemenu.CopyURLwithpassword1.Caption=Copy URL with password
filemenu.CopyURLwithdifferentaddress1.Caption=Copy URL with different host address
filemenu.CopyURLwithfingerprint1.Caption=Copy URL with fingerprint
filemenu.Browseit1.Caption=Browse it
filemenu.SetURL1.Caption=Set URL...
filemenu.Openit1.Caption=Open it
filemenu.Flagasnew1.Caption=Flag as new
filemenu.Resetnewflag1.Caption=Reset <new> flag
filemenu.Setuserpass1.Caption=Set user/pass...
filemenu.Resetuserpass1.Caption=Reset user/pass
filemenu.Purge1.Caption=Purge...
filemenu.Switchtovirtual1.Caption=Change to virtual-folder
filemenu.Switchtorealfolder1.Caption=Change to real-folder
filemenu.Bindroottorealfolder1.Caption=Bind root to real-folder
filemenu.Unbindroot1.Caption=Unbind root
filemenu.Defaultpointtoaddfiles1.Caption=Default point to add files
filemenu.Properties1.Caption=Properties...
menu.SelfTest1.Caption=Self Test
menu.Showbandwidthgraph1.Caption=Show bandwidth graph
menu.Otheroptions1.Caption=Other options
menu.Otheroptions1.switchMode.Caption=Switch to expert mode
menu.Otheroptions1.Accounts1.Caption=User accounts...
menu.Otheroptions1.Shellcontextmenu1.Caption=Integrate in shell context menu
menu.Otheroptions1.AutocopyURLonadditionChk.Caption=Auto-copy URL on addition
menu.Otheroptions1.alwaysontopChk.Caption=Always on top
menu.Otheroptions1.sendHFSidentifierChk.Caption=Send HFS identifier
menu.Otheroptions1.persistentconnectionsChk.Caption=Persistent connections
menu.Otheroptions1.DMbrowserTplChk.Caption=Specific HTML for download managers
menu.Otheroptions1.Graphrefreshrate1.Caption=Graph refresh rate...
menu.Otheroptions1.MIMEtypes1.Caption=MIME types...
menu.Otheroptions1.Opendirectlyinbrowser1.Caption=Open directly in browser...
menu.Otheroptions1.freeLoginChk.Caption=Accept any login for unprotected resources
menu.Otheroptions1.usecommentasrealmChk.Caption=Use comment as realm
menu.Otheroptions1.Loginrealm1.Caption=Login realm...
menu.Otheroptions1.HintsfornewcomersChk.Caption=Hints for newcomers
menu.Otheroptions1.compressedbrowsingChk.Caption=Compressed browsing
menu.Otheroptions1.modalOptionsChk.Caption=Modal dialog for options
menu.Otheroptions1.useISOdateChk.Caption=Use ISO date format
menu.Otheroptions1.browseUsingLocalhostChk.Caption=Browse using localhost
menu.Otheroptions1.enableNoDefaultChk.Caption=Enable ~nodefault
menu.Otheroptions1.preventStandbyChk.Caption=Prevent system standby on network activity
menu.Otheroptions1.Addicons1.Caption=Add icons...
menu.Otheroptions1.Changeport1.Caption=Change port...
menu.Otheroptions1.autoCommentChk.Caption=Input comment on file addition
menu.Otheroptions1.Defaultsorting1.Caption=Default sorting
menu.Otheroptions1.Defaultsorting1.Name1.Caption=Name
menu.Otheroptions1.Defaultsorting1.Extension1.Caption=Extension
menu.Otheroptions1.Defaultsorting1.Size1.Caption=Size
menu.Otheroptions1.Defaultsorting1.Time1.Caption=Time
menu.Otheroptions1.Defaultsorting1.Hits1.Caption=Hits
menu.Otheroptions1.Editeventscripts1.Caption=Edit event scripts...
menu.Otheroptions1.oemTarChk.Caption=OEM file names for TAR archives
menu.HTMLtemplate1.Caption=HTML template
menu.HTMLtemplate1.Edit1.Caption=Edit...
menu.HTMLtemplate1.Changefile1.Caption=Change file...
menu.HTMLtemplate1.Changeeditor1.Caption=Change editor...
menu.HTMLtemplate1.Restoredefault1.Caption=Restore default
menu.HTMLtemplate1.enableMacrosChk.Caption=Enable macros
menu.Upload2.Caption=Upload
menu.Upload2.Howto1.Caption=How to?
menu.Upload2.deletePartialUploadsChk.Caption=Delete partial uploads
menu.Upload2.Renamepartialuploads1.Caption=Rename partial uploads...
menu.Upload2.numberFilesOnUploadChk.Caption=Number files on upload instead of overwriting
menu.StartExit1.Caption=Start/Exit
menu.StartExit1.autocopyURLonstartChk.Caption=Auto-copy URL on start
menu.StartExit1.startminimizedChk.Caption=Start minimized
menu.StartExit1.reloadonstartupChk.Caption=Reload on startup VFS file previously open
menu.StartExit1.saveTotalsChk.Caption=Save totals
menu.StartExit1.autosaveVFSchk.Caption=Auto-save VFS on exit
menu.StartExit1.Autoclose1.Caption=Auto-close
menu.StartExit1.Autoclose1.Nodownloadtimeout1.Caption=No download timeout...
menu.StartExit1.only1instanceChk.Caption=Only 1 instance
menu.StartExit1.confirmexitChk.Caption=Confirm exit
menu.StartExit1.findExtOnStartupChk.Caption=Find external address on startup
menu.StartExit1.RunHFSwhenWindowsstarts1.Caption=Run HFS when Windows starts
menu.StartExit1.trayInsteadOfQuitChk.Caption=Minimize to tray clicking the close button [ X ]
menu.StartExit1.quitWithoutAskingToSaveChk.Caption=Force quitting (no dialogs)
menu.VirtualFileSystem1.Caption=Virtual File System
menu.VirtualFileSystem1.foldersbeforeChk.Caption=Folders before
menu.VirtualFileSystem1.linksBeforeChk.Caption=Links before
menu.VirtualFileSystem1.usesystemiconsChk.Caption=Use system icons
menu.VirtualFileSystem1.loadSingleCommentsChk.Caption=Load single comment files
menu.VirtualFileSystem1.supportDescriptionChk.Caption=Support DESCRIPT.ION
menu.VirtualFileSystem1.oemForIonChk.Caption=Use OEM for DESCRIPT.ION
menu.VirtualFileSystem1.recursiveListingChk.Caption=Enable recursive listing
menu.VirtualFileSystem1.deleteDontAskChk.Caption=Skip confirmation on deletion
menu.VirtualFileSystem1.listfileswithhiddenattributeChk.Caption=List files with <hidden> attribute
menu.VirtualFileSystem1.listfileswithsystemattributeChk.Caption=List files with <system> attribute
menu.VirtualFileSystem1.hideProtectedItemsChk.Caption=List protected items only for allowed users
menu.VirtualFileSystem1.Iconmasks1.Caption=Icon masks...
menu.VirtualFileSystem1.Flagfilesaddedrecently1.Caption=Flag files added recently...
menu.VirtualFileSystem1.Autosaveevery1.Caption=Auto-save every...
menu.VirtualFileSystem1.backupSavingChk.Caption=Backup on save
menu.VirtualFileSystem1.Addingfolder1.Caption=Adding folder
menu.VirtualFileSystem1.Addingfolder1.askFolderKindChk.Caption=Ask
menu.VirtualFileSystem1.Addingfolder1.defaultToVirtualChk.Caption=Default to virtual-folder
menu.VirtualFileSystem1.Addingfolder1.defaultToRealChk.Caption=Default to real-folder
menu.VirtualFileSystem1.Resetfileshits1.Caption=Reset files hits
menu.VirtualFileSystem1.Resettotals1.Caption=Reset totals
menu.Limits1.Caption=Limits
menu.Limits1.Speedlimit1.Caption=Speed limit (disabled)...
menu.Limits1.Speedlimitforsingleaddress1.Caption=Speed limit for single address...
menu.Limits1.Pausestreaming1.Caption=Pause streaming
menu.Limits1.Pausestreaming1.Hint=Sets speed limit temporarily to zero
menu.Limits1.maxDLs1.Caption=Max simultaneous downloads...
menu.Limits1.maxDLsIP1.Caption=Max simultaneous downloads from single address...
menu.Limits1.maxIPs1.Caption=Max simultaneous addresses...
menu.Limits1.maxIPsDLing1.Caption=Max simultaneous addresses downloading...
menu.Limits1.Maxconnections1.Caption=Max connections...
menu.Limits1.Maxconnectionsfromsingleaddress1.Caption=Max connections from single address...
menu.Limits1.Connectionsinactivitytimeout1.Caption=Connections inactivity timeout...
menu.Limits1.BannedIPaddresses1.Caption=Bans...
menu.Limits1.Minimumdiskspace1.Caption=Minimum disk space...
menu.Limits1.preventLeechingChk.Caption=Prevent leeching (download accelerators)
menu.Limits1.Allowedreferer1.Caption=Allowed referer...
menu.Limits1.stopSpidersChk.Caption=Stop spiders
menu.Flashtaskbutton1.Caption=Flash taskbutton
menu.Flashtaskbutton1.onDownloadChk.Caption=On download
menu.Flashtaskbutton1.onconnectionChk.Caption=On connection
menu.Flashtaskbutton1.never1.Caption=Never
menu.Flashtaskbutton1.beepChk.Caption=Also beep
menu.Fingerprints1.Caption=Fingerprints
menu.Fingerprints1.fingerprintsChk.Caption=Enabled
menu.Fingerprints1.saveNewFingerprintsChk.Caption=Save new calculated fingerprints
menu.Fingerprints1.Createfingerprintonaddition1.Caption=Create fingerprint on file addition...
menu.trayicons1.Caption=Tray icons
menu.trayicons1.MinimizetotrayChk.Caption=Minimize to tray
menu.trayicons1.showmaintrayiconChk.Caption=Show main tray icon
menu.trayicons1.hetrayiconshows1.Caption=Main icon shows
menu.trayicons1.hetrayiconshows1.Numberofcurrentconnections1.Caption=Number of current connections
menu.trayicons1.hetrayiconshows1.Numberofloggeddownloads1.Caption=Number of logged downloads
menu.trayicons1.hetrayiconshows1.Numberofloggeduploads1.Caption=Number of logged uploads
menu.trayicons1.hetrayiconshows1.Numberofloggedhits1.Caption=Number of logged hits
menu.trayicons1.hetrayiconshows1.NumberofdifferentIPaddresses1.Caption=Number of different IP addresses now connected
menu.trayicons1.hetrayiconshows1.NumberofdifferentIPaddresseseverconnected1.Caption=Number of different IP addresses ever connected
menu.trayicons1.traymessage1.Caption=Tray message...
menu.trayicons1.trayfordownloadChk.Caption=Tray icon for each download
menu.IPaddress1.Caption=&IP address
menu.IPaddress1.hisIPaddressisusedforURLbuilding1.Caption=This IP address is used only for URL building
menu.IPaddress1.Custom1.Caption=Custom...
menu.IPaddress1.noPortInUrlChk.Caption=Don't include port in URL
menu.IPaddress1.Findexternaladdress1.Caption=Find external address
menu.IPaddress1.searchbetteripChk.Caption=Constantly search for better address
menu.Acceptconnectionson1.Caption=Accept connections on
menu.Acceptconnectionson1.Anyaddress1.Caption=Any address
menu.DynamicDNSupdater1.Caption=Dynamic DNS updater
menu.DynamicDNSupdater1.CJBtemplate1.Caption=CJB wizard...
menu.DynamicDNSupdater1.NoIPtemplate1.Caption=No-IP wizard...
menu.DynamicDNSupdater1.DynDNStemplate1.Caption=DynDNS wizard...
menu.DynamicDNSupdater1.Custom2.Caption=Custom...
menu.DynamicDNSupdater1.Seelastserverresponse1.Caption=See last server response...
menu.DynamicDNSupdater1.Disable1.Caption=Disable
menu.URLencoding1.Caption=URL encoding
menu.URLencoding1.encodeSpacesChk.Caption=Encode spaces
menu.URLencoding1.encodenonasciiChk.Caption=Encode non-ASCII characters
menu.URLencoding1.pwdInPagesChk.Caption=Include password in pages (for download managers)
menu.URLencoding1.httpsUrlsChk.Caption=URLs starting with https instead of http
menu.Debug1.Caption=De&bug
menu.Debug1.resetOptions1.Caption=Temporarily reset options
menu.Debug1.dumpTrafficChk.Caption=Dump traffic
menu.Debug1.Showcustomizedoptions1.Caption=Show customized options...
menu.Debug1.highSpeedChk.Caption=Experimental high speed handling
menu.Debug1.macrosLogChk.Caption=Enable macros.log
menu.Debug1.Runscript1.Caption=Run script...
menu.Debug1.showMemUsageChk.Caption=Show memory usage
menu.Debug1.noContentdispositionChk.Caption=No Content-disposition
menu.Updates1.Caption=Updates
menu.Updates1.Checkforupdates1.Caption=Check for news/updates
menu.Updates1.updateDailyChk.Caption=Auto check every day
menu.Updates1.keepBakUpdatingChk.Caption=Keep old version
menu.Updates1.testerUpdatesChk.Caption=Updates from official to beta versions
menu.Updates1.updateAutomaticallyChk.Caption=Update automatically
menu.Updates1.delayUpdateChk.Caption=Delay update to serve last requests
menu.Updates1.Reverttopreviousversion1.Caption=Revert to previous version
menu.Donate1.Caption=Donate!
menu.Addfiles2.Caption=Add files...
menu.Addfolder2.Caption=Add folder from disk...
menu.Loadfilesystem1.Caption=Load file system...
menu.Loadrecentfiles1.Caption=Load recent files
menu.Savefilesystem1.Caption=Save file system...
menu.Clearfilesystem1.Caption=Clear file system
menu.Saveoptions1.Caption=Save options
menu.Saveoptions1.tofile1.Caption=to file
menu.Saveoptions1.toregistrycurrentuser1.Caption=to registry (current user)
menu.Saveoptions1.toregistryallusers1.Caption=to registry (all users)
menu.Saveoptions1.Clearoptionsandquit1.Caption=Clear options and quit
menu.Saveoptions1.autoSaveOptionsChk.Caption=Auto-save options
menu.Help1.Caption=Help
menu.Help1.Introduction1.Caption=Introduction
menu.Help1.Guide1.Caption=Full Guide
menu.Help1.FAQ1.Caption=F.A.Q.
menu.Weblinks1.Caption=Web links
menu.Weblinks1.Officialwebsite1.Caption=Official website
menu.Weblinks1.Forum1.Caption=Forum
menu.Weblinks1.License1.Caption=License
menu.UninstallHFS1.Caption=Uninstall HFS
menu.About1.Caption=About...
menu.SwitchON1.Caption=Switch ON
menu.Restore1.Caption=Restore
menu.Exit1.Caption=Exit
connmenu.Kickconnection1.Caption=Kick connection
connmenu.KickIPaddress1.Caption=Kick IP address
connmenu.Kickallconnections1.Caption=Kick all connections
connmenu.Kickidleconnections1.Caption=Kick idle connections
connmenu.BanIPaddress1.Caption=Ban IP address
connmenu.Pause1.Caption=Pause (download-only)
connmenu.Viewhttprequest1.Caption=View http request
connmenu.trayiconforeachdownload1.Caption=Tray icon for each download
logmenu.Logwhat1.Caption=Log what
logmenu.Logwhat1.LogtimeChk.Caption=Time
logmenu.Logwhat1.LogdateChk.Caption=Date
logmenu.Logwhat1.logBrowsingChk.Caption=Browsing
logmenu.Logwhat1.LogiconsChk.Caption=Icons
logmenu.Logwhat1.logProgressChk.Caption=Progress
logmenu.Logwhat1.logBannedChk.Caption=Banned
logmenu.Logwhat1.logOnlyServedChk.Caption=Only served requests
logmenu.Logwhat1.logOtherEventsChk.Caption=Other events
logmenu.Logwhat1.logOtherEventsChk.Hint=Like dynamic dns updating...
logmenu.Logwhat1.logconnectionsChk.Caption=Connections
logmenu.Logwhat1.logDisconnectionsChk.Caption=Disconnections
logmenu.Logwhat1.logRequestsChk.Caption=Requests
logmenu.Logwhat1.DumprequestsChk.Caption=Requests dump
logmenu.Logwhat1.logRepliesChk.Caption=Replies
logmenu.Logwhat1.logFulldownloadsChk.Caption=Full downloads
logmenu.Logwhat1.logUploadsChk.Caption=Uploads
logmenu.Logwhat1.logDeletionsChk.Caption=Deletions
logmenu.Logwhat1.logBytesreceivedChk.Caption=Bytes received
logmenu.Logwhat1.logBytessentChk.Caption=Bytes sent
logmenu.Logwhat1.logServerstartChk.Caption=Server start
logmenu.Logwhat1.logServerstopChk.Caption=Server stop
logmenu.logOnVideoChk.Caption=Log to screen
logmenu.Logfile1.Caption=Log to file...
logmenu.Maxlinesonscreen1.Caption=Max lines on screen...
logmenu.Apachelogfileformat1.Caption=Apache log file format...
logmenu.Donotlogaddress1.Caption=Do not log address...
logmenu.Dontlogsomefiles1.Caption=Do not log some files...
logmenu.Address2name1.Caption=Assign name to address...
logmenu.Font1.Caption=Font...
logmenu.tabOnLogFileChk.Caption=Tabbed instead of multi-line for the log file
logmenu.Readonly1.Caption=Read-only
logmenu.Banthisaddress1.Caption=Ban this address
logmenu.Copy1.Caption=Copy
logmenu.Clear1.Caption=Clear
logmenu.Clearandresettotals1.Caption=Clear and reset totals
logmenu.Save1.Caption=Save
logmenu.Saveas1.Caption=Save as...
logmenu.Addresseseverconnected1.Caption=Addresses ever connected...
graphMenu.Reset1.Caption=Reset
graphMenu.Hide.Caption=Hide
[TnewuserpassFrm]
Caption=Insert the requested user/pass
userBox.EditLabel.Caption=Username
pwdBox.EditLabel.Caption=Password
pwd2Box.EditLabel.Caption=Re-type password
okBtn.Caption=&Ok
resetBtn.Caption=&Reset
[ToptionsFrm]
Caption=Options
pageCtrl.bansPage.Caption=Bans
pageCtrl.bansPage.Panel1.addBtn.Caption=Add row
pageCtrl.bansPage.Panel1.deleteBtn.Caption=Delete row
pageCtrl.bansPage.Panel1.sortBanBtn.Caption=Sort
pageCtrl.bansPage.bansBox.TitleCaptions.Strings=IP address mask\^Comment
pageCtrl.bansPage.Panel3.noreplybanChk.Caption=Disconnect with no reply
pageCtrl.bansPage.Panel3.Button1.Caption=How to invert the logic?
pageCtrl.accountsPage.Caption=Accounts
pageCtrl.accountsPage.Label1.Caption=Account list
pageCtrl.accountsPage.Label7.Hint=You also need to right click on the folder, then restrict access
pageCtrl.accountsPage.Label7.Caption=WARNING: creating an account is not enough to protect your files...
pageCtrl.accountsPage.accountpropGrp.Caption=Account properties
pageCtrl.accountsPage.accountpropGrp.Label3.Caption=Here you can see protected resources this user can access...
pageCtrl.accountsPage.accountpropGrp.Label8.Caption=Notes
pageCtrl.accountsPage.accountpropGrp.accountenabledChk.Caption=&Enabled
pageCtrl.accountsPage.accountpropGrp.ignoreLimitsChk.Caption=&Ignore limits
pageCtrl.accountsPage.accountpropGrp.pwdBox.EditLabel.Caption=&Password
pageCtrl.accountsPage.accountpropGrp.redirBox.EditLabel.Caption{1}=After login, redirect to
pageCtrl.accountsPage.accountpropGrp.accountLinkBox.EditLabel.Caption=Member of
pageCtrl.accountsPage.accountpropGrp.groupChk.Caption=&Group
pageCtrl.accountsPage.accountpropGrp.groupsBtn.Caption=Choose...
pageCtrl.accountsPage.accountpropGrp.notesWrapChk.Caption=Wrap
pageCtrl.accountsPage.deleteaccountBtn.Caption=de&lete
pageCtrl.accountsPage.renaccountBtn.Caption=&rename
pageCtrl.accountsPage.addaccountBtn.Caption=ad&d
pageCtrl.accountsPage.upBtn.Caption=&up
pageCtrl.accountsPage.downBtn.Caption=do&wn
pageCtrl.accountsPage.sortBtn.Caption=sort
pageCtrl.mimePage.Caption=MIME types
pageCtrl.mimePage.mimeBox.TitleCaptions.Strings=File Mask\^MIME Description
pageCtrl.mimePage.Panel5.addMimeBtn.Caption=Add row
pageCtrl.mimePage.Panel5.deleteMimeBtn.Caption=Delete row
pageCtrl.mimePage.Panel5.inBrowserIfMIMEchk.Caption=Open directly in browser when MIME type is defined
pageCtrl.trayPage.Caption=Tray Message
pageCtrl.trayPage.Label2.Caption=You can customize the message in the tray icon tip. \+The message length is determined by your Windows version\+(in XP the limit is 127 characters including spaces).\+Available symbols:\+\+ %uptime% - server uptime\+ %url% - server main URL\+ %ip% - IP address set as default\+ %port% - Port on which the server is listening\+ %hits% - number of requests made to the server\+ %downloads% - number of files downloaded\+ %version% - HFS version
pageCtrl.trayPage.Label10.Caption=Preview
pageCtrl.trayPage.traymsgBox.Lines.Strings=traymsgBox
pageCtrl.a2nPage.Caption=Address2name
pageCtrl.a2nPage.Panel4.Label4.Caption=You can associate a label to an address (or many addresses). It will be used in the log.
pageCtrl.a2nPage.Panel4.deleteA2Nbtn.Caption=&Delete row
pageCtrl.a2nPage.Panel4.addA2Nbtn.Caption=Add &row
pageCtrl.a2nPage.a2nBox.TitleCaptions.Strings=Name\^IP Mask
pageCtrl.iconsPage.Caption=Icon masks
pageCtrl.iconsPage.Label5.Caption=Each line is a file-mask associated with an icon
pageCtrl.iconsPage.Label6.Caption=Icon associated
Panel2.okBtn.Caption=&OK
Panel2.applyBtn.Caption=&Apply
Panel2.cancelBtn.Caption=&Cancel
[TpurgeFrm]
Caption=Purge options
Label1.Caption=Choose what to remove...
rmFilesChk.Caption=Non-existent files
rmRealFoldersChk.Caption=Non-existent real folders
rmEmptyFoldersChk.Caption=Empty folders
Button1.Caption=&Ok
Button2.Caption=&Cancel
[TrunScriptFrm]
Caption=Run script
resultBox.Lines.Strings=Write your script in the external editor, then click Run.\^In this box will see the result of the script you run.
Panel1.sizeLbl.Caption=Size: 0
Panel1.runBtn.Caption=&Run
Panel1.autorunChk.Caption=&Auto run at every saving
[TshellExtFrm]
Caption=Option...
Panel1.Label1.Caption=Do you want HFS in your shell context menu?
Panel1.Button1.Caption=&Yes
Panel1.Button2.Caption=&No
[ResourceStrings]
64656_main_MSG_NUM_ADDR=In this moment there are %d different addresses
64657_main_MSG_NUM_ADDR_DL=In this moment there are %d different addresses downloading
64658_main_MSG_MAX_LINES=Max lines on screen.
64659_main_MSG_APACHE_LOG_FMT=Apache log file format
64660_main_MSG_APACHE_LOG_FMT_LONG=Here you can specify how to format the log file complying Apache standard.\^Leave blank to get bare copy of screen on file.\^\^Example:\^ %h %l %u %t "%r" %>s %b
64661_main_MSG_ICONS_ADDED=%d new icons added
64662_main_MSG_DDNS_DISABLED=Dynamic DNS updater disabled
64663_main_MSG_MD5_WARN=This option creates an .md5 file for every new calculated fingerprint.\^Use with care to get not your disk invaded by these files.
64664_main_MSG_AUTO_MD5=Auto fingerprint
64665_main_MSG_AUTO_MD5_LONG=When you add files and no fingerprint is found, it is calculated.\^To avoid long waitings, set a limit to file size (in KiloBytes).\^Leave empty to disable, and have no fingerprint created.
64666_main_MSG_UPL_HOWTO=1. Add a folder (choose "real folder")\^\^You should now see a RED folder in your virtual file sytem, inside HFS\^\^2. Right click on this folder\^3. Properties -> Permissions -> Upload\^4. Check on "Anyone"\^5. Ok\^\^Now anyone who has access to your HFS server can upload files to you.
64672_main_MSG_EVENTS_HLP=For help on how to use this file please refer http://www.rejetto.com/wiki/?title=HFS:_Event_scripts
64673_main_MSG_EDIT_RES=Edit resource
64674_main_MSG_TPL_USE_MACROS=The current template is using macros.\^Do you want to cancel this action?
64675_main_REMOVE_SHELL=Remove from shell context menu
64676_main_S_OFF=Switch OFF
64677_main_S_ON{1}=Switch ON
64678_main_LOG=Log
64679_main_MSG_RE_NOIP=You are invited to re-insert your No-IP configuration, otherwise the updater won't work as expected.
64680_main_MSG_TRAY_DEF=%ip%\^Uptime: %uptime%\^Downloads: %downloads%
64681_main_MSG_CLEAN_START=Clean start
64682_main_MSG_RESTORE_BAK=A file system backup has been created for a system shutdown.\^Do you want to restore this backup?
64683_main_MSG_EXT_ADDR_FAIL=Search for external address failed
64684_main_MSG_TO_EXPERT=Switch to expert mode.
64685_main_MSG_DONT_LOG_HINT=Select the files/folder you don't want to be logged,\^then right click and select "Don't log".
64686_main_MSG_DL_PERC=Downloading %d%%
64687_main_MSG_UNINSTALL_WARN=Delete HFS and all settings?
64688_main_MSG_SELF_3=You may be behind a router or firewall.
64689_main_MSG_SELF_6=You are behind a router.\^Ensure it is configured to forward port %s to your computer.
64690_main_MSG_SELF_7=You may be behind a firewall.\^Ensure nothing is blocking HFS.
64691_main_MSG_RET_EXT=Retrieving external address...
64692_main_MSG_SELF_CANT_ON=Unable to switch the server on
64693_main_MSG_SELF_CANT_LIST=Self test cannot be performed because HFS was configured to accept connections only on 127.0.0.1
64694_main_MSG_SELF_CANT_S=Self test doesn't support HTTPS.\^It's likely it won't work.
64695_main_MSG_SELF_ING=Self testing...
64696_main_MSG_TEST_CANC=Test cancelled
64697_main_MSG_TEST_INET=Testing internet connection...
64698_main_MSG_SELF_UNAV=Sorry, the test is unavailable at the moment
64699_main_MSG_SELF_NO_INET=Your internet connection does not work
64700_main_MSG_SELF_NO_ANSWER=The test failed: server does not answer.
64701_main_MSG_OPEN_BROW=Open directly in browser
64702_main_MSG_OPEN_BROW_LONG="Suggest" the browser to open directly the specified files.\^Other files should pop up a save dialog.
64703_main_MSG_HIDE_PORT=You should not use this option unless you really know its meaning.\^Continue?
64704_main_MSG_RESET_TOT=Do you want to reset total in/out?
64705_main_MSG_DISAB_FIND_EXT=This option makes pointless the option "Find external address at startup", which has now been disabled for your convenience.
64706_main_MSG_ENT_URL=Enter URL
64707_main_MSG_ENT_URL_LONG=Enter URL for updating.\^%ip% will be translated to your external IP.
64708_main_MSG_ENT_USR=Enter user
64709_main_MSG_ENT_PWD=Enter password
64710_main_MSG_ENT_HOST=Enter host
64711_main_MSG_ENT_HOST_LONG=Enter domain (full form!)
64712_main_MSG_HOST_FORM=Please, enter it in the FULL form, with dots
64713_main_MSG_MIN_SPACE=Min disk space
64714_main_MSG_MIN_SPACE_LONG=The upload will fail if your disk has less than the specified amount of free MegaBytes.
64715_main_MSG_REN_PART=Rename partial uploads
64716_main_MSG_REN_PART_LONG=This string will be appended to the filename.\^\^If you need more control, enter a string with %name% in it, and this symbol will be replaced by the original filename.
64717_main_MSG_SELF_BEFORE=Here you can test if your server does work on the Internet.\^If you are not interested in serving files over the Internet, this is NOT for you.\^\^We'll now perform a test involving network activity.\^In order to complete this test, you may need to allow HFS's activity in your firewall, by clicking Allow on the warning prompt.\^\^WARNING: for the duration of the test, all ban rules and limits on the number of connections won't apply.
64718_main_MSG_SELF_OK=The test is successful. The server should be working fine.
64719_main_MSG_SELF_OK_PORT=Port %s is not working, but another working port has been found and set: %s.
64720_main_MSG_LOG_FILE=Log file
64721_main_MSG_LOG_FILE_LONG=This function does not save any previous information to the log file.\^Instead, it saves all information that appears in the log box in real-time (from when you click "OK", below).\^Specify a filename for the log.\^If you leave the filename blank, no log file is saved.\^\^Here are some symbols you can use in the filename to split the log:\^ %d% -- day of the month (1..31)\^ %m% -- month (1..12)\^ %y% -- year (2000..)\^ %dow% -- day of the week (0..6)\^ %w% -- week of the year (1..53)\^ %user% -- username surrounded by parenthesis
64722_main_MSG_SET_URL=Set URL
64723_main_MSG_SET_URL_LONG=Please insert an URL for the link\^\^Do not forget to specify http:// or whatever.\^%%ip%% will be translated to your address
64724_main_MSG_REALM=Login realm
64725_main_MSG_REALM_LONG=The realm string is shown on the user/pass dialog of the browser.\^Here you can customize the realm for the login button
64726_main_MSG_INACT_TIMEOUT=Connection inactivity timeout
64727_main_MSG_INACT_TIMEOUT_LONG=The connection is kicked after a timeout.\^Specify in seconds.\^Leave blank to get no timeout.
64728_main_MSG_CHANGES_LOST=All changes will be lost\^Continue?
64729_main_MSG_FLAG_NEW=Flag new files
64730_main_MSG_FLAG_NEW_LONG=Enter the number of MINUTES files stay flagged from their addition.\^Leave blank to disable.
64731_main_MSG_DONT_LOG_MASK=Do not log address
64732_main_MSG_DONT_LOG_MASK_LONG=Any event from the following IP address mask will be not logged.
64733_main_MSG_CUST_IP=Custom IP addresses
64734_main_MSG_CUST_IP_LONG=Specify your addresses, each per line
64735_main_MSG_NO_EXT_IP=Can't find external address\^( %s )
64736_main_MSG_TENTH_SEC=Tenths of second
64737_main_MSG_LOADING_VFS=Loading VFS
64738_main_MSG_VFS_OLD=This file is old and uses different settings.\^The "let browse" folder option will be reset.\^Re-saving the file will update its format.
64739_main_MSG_UNK_FK=This file has been created with a newer version.\^Some data was discarded because unknown.\^If you save the file now, the discarded data will NOT be saved.
64740_main_MSG_VIS_ONLY_ANON=This VFS file uses the "Visible only to anonymous users" feature.\^This feature is not available anymore.\^You can achieve similar results by restricting access to @anonymous,\^then enabling "List protected items only for allowed users".
64741_main_MSG_AUTO_DISABLED=Because of the problems encountered in loading,\^automatic saving has been disabled\^until you save manually or load another one.
64742_main_MSG_CORRUPTED=This file does not contain valid data.
64743_main_MSG_MACROS_FOUND=!!!!!!!!! DANGER !!!!!!!!!\^This file contains macros.\^Don't accept macros from people you don't trust.\^\^Trust this file?
64744_main_MSG_UPD_INFO=Last stable version: %s\^\^Last untested version: %s\^
64745_main_MSG_NEWER=There's a new version available online: %s
64746_main_MSG_SRC_UPD=Searching for updates...
64747_main_ARE_EXPERT{1}=You are in Expert mode
64748_main_ARE_EASY=You are in Easy mode
64749_main_SW2EXPERT=Switch to Expert mode
64750_main_SW2EASY=Switch to Easy mode
64751_main_MSG_DL_TIMEOUT_LONG=Enter the number of MINUTES with no download after which the program automatically shuts down.\^Leave blank to get no timeout.
64752_main_MSG_NEWER_INCOMP=This file has been created with a newer and incompatible version.
64753_main_MSG_ZLIB=This file is corrupted (ZLIB).
64754_main_MSG_BAKAVAILABLE=This file is corrupted but a backup is available.\^Continue with backup?
64755_main_MSG_CANT_LOAD_SAVE=Cannot load or save while adding files
64756_main_MSG_OPEN_VFS=Open VFS file
64757_main_LIMIT{2}=Limit
64758_main_TOP_SPEED=Top speed
64759_main_MSG_MAX_BW=Max bandwidth (KB/s).
64760_main_MSG_LIM0=Zero is an effective limit.\^To disable instead, leave empty.
64761_main_MSG_MAX_BW_1=Max bandwidth for single address (KB/s).
64762_main_MSG_GRAPH_RATE_MENU=Graph refresh rate: %d (tenths of second)
64763_main_MSG_MAX_CON_LONG=Max simultaneous connections to serve.\^Most people don't know this function well, and have problems. If you are unsure, please use the "Max simultaneous downloads".
64764_main_MSG_WARN_CONN=In this moment there are %d active connections
64765_main_MSG_WARN_ACT_DL=In this moment there are %d active downloads
64766_main_MSG_MAX_CON_SING_LONG=Max simultaneous connections to accept from a single IP address.\^Most people don't know this function well, and have problems. If you are unsure, please use the "Max simultaneous downloads from a single IP address".
64767_main_MSG_GRAPH_RATE{1}=Graph refresh rate
64768_main_MSG_VFS_DONT_CONS_DL_MASK=Don't consider as download (mask): %s
64769_main_MSG_VFS_INHERITED= [inherited]
64770_main_MSG_VFS_EXTERNAL= [external]
64771_main_MSG_CON_HINT=Connection time: %s\^Last request time: %s\^Agent: %s
64772_main_MSG_CON_STATE_IDLE=idle
64773_main_MSG_CON_STATE_REQ=requesting
64774_main_MSG_CON_STATE_RCV=receiving
64775_main_MSG_CON_STATE_THINK=thinking
64776_main_MSG_CON_STATE_REP=replying
64777_main_MSG_CON_STATE_SEND=sending
64778_main_MSG_CON_STATE_DISC=disconnected
64779_main_MSG_TPL_RESET=The template has been reset
64780_main_MSG_ALLO_REF=Allowed referer
64781_main_MSG_ALLO_REF_LONG=Leave empty to disable this feature.\^Here you can specify a mask.\^When a file is requested, if the mask doesn't match the "Referer" HTTP field, the request is rejected.
64782_main_MSG_BETTERSTOP=\^Going on may lead to problems.\^It is adviced to stop loading.\^Stop?
64783_main_MSG_BADCRC=This file is corrupted (CRC).
64784_main_MSG_VFS_HIDE_EMPTY=Hidden if empty
64785_main_MSG_VFS_NOT_BROW=Not browsable
64786_main_MSG_VFS_HIDE_EMPTY_FLD=Hide empty folders
64787_main_MSG_VFS_HIDE_EXT=Hide extention
64788_main_MSG_VFS_ARCABLE=Archivable
64789_main_MSG_VFS_DEF_MASK=Default file mask: %s
64790_main_MSG_VFS_ACCESS=Access for
64791_main_MSG_VFS_UPLOAD=Upload allowed for
64792_main_MSG_VFS_DELETE=Delete allowed for
64793_main_MSG_VFS_COMMENT=Comment: %s
64794_main_MSG_VFS_REALM=Realm: %s
64795_main_MSG_VFS_DIFF_TPL=Diff template: %s
64796_main_MSG_VFS_FILES_FLT=Files filter: %s
64797_main_MSG_VFS_FLD_FLT=Folders filter: %s
64798_main_MSG_VFS_UPL_FLT=Upload filter: %s
64799_main_MSG_VFS_DONT_CONS_DL=Don't consider as download
64800_main_IN_SPEED=In: %.1f KB/s
64801_main_BANS=Ban rules: %d
64802_main_MEMORY=Mem
64803_main_CUST_TPL=Customized template
64804_main_VFS_ITEMS=VFS: %d items
64805_main_MSG_ITEM_EXISTS=%s item(s) already exists:\^%s\^\^Continue?
64806_main_MSG_INSTALL_TPL=Install this template?
64807_main_MSG_FOLDER_UPLOAD=Do you want ANYONE to be able to upload to this folder?
64808_main_MSG_VFS_DRAG_INVIT=Drag your files here
64809_main_MSG_VFS_URL=URL: %s
64810_main_MSG_VFS_PATH=Path: %s
64811_main_MSG_VFS_SIZE=Size: %s
64812_main_MSG_VFS_DLS=Downloads: %s
64813_main_MSG_VFS_INVISIBLE=Invisible
64814_main_MSG_VFS_DL_FORB=Download forbidden
64815_main_MSG_VFS_DONT_LOG=Don't log
64816_main_MSG_UPD_DL=Downloading new version...
64817_main_MSG_UPDATE=You are invited to use the new version.\^\^Update now?
64818_main_MSG_REQUESTING=Requesting...
64819_main_MSG_CHK_UPD=Checking for updates
64820_main_MSG_CHK_UPD_FAIL=Check update: failed
64821_main_MSG_CHK_UPD_HEAD=Check update:
64822_main_MSG_CHK_UPD_VER=new version found: %s
64823_main_MSG_CHK_UPD_VER_EXT=Build #%s (current is #%s)
64824_main_MSG_CHK_UPD_NONE=no new version
64825_main_TO_CLIP=Copy to clipboard
64826_main_ALREADY_CLIP=Already in clipboard
64827_main_MSG_NO_SPACE=Out of space
64828_main_CONN=Connections: %d
64829_main_TOT_IN=Total In: %s
64830_main_TOT_OUT{1}=Total Out: %s
64831_main_OUT_SPEED=Out: %.1f KB/s
64832_main_MSG_FILE_ADD_ABORT=File addition was aborted.\^The list of files is incomplete.
64833_main_MSG_ADDING=Adding item #%d
64834_main_MSG_INV_FILENAME=Invalid filename
64835_main_MSG_DELETE=Delete?
64836_main_AUTOSAVE=Auto save every:
64837_main_SECONDS=%d seconds
64838_main_MSG_SPD_LIMIT_SING=Speed limit for single address
64839_main_MSG_SPD_LIMIT=Speed limit
64840_main_MSG_AUTO_SAVE=Auto-save %s
64841_main_MSG_AUTO_SAVE_LONG=Auto-save %s.\^Specify in seconds.\^Leave blank to disable.
64842_main_MSG_MIN=We don't accept less than %d
64843_main_MSG_BAN=Your ban configuration may have been screwed up.\^Please verify it.
64844_main_MSG_CANT_SAVE_OPT=Can't save options there.\^Should I try to save to user registry?
64845_main_MSG_UPD_SAVE_ERROR=Cannot save the update
64846_main_MSG_UPD_REQ_ONLY1=The auto-update feature cannot work because it requires the "Only 1 instance" option enabled.\^\^Your browser will now be pointed to the update, so you can install it manually.
64847_main_MSG_UPD_WAIT=Waiting for last requests to be served, then we'll update
64848_main_MSG_LOG_HEAD=Served head
64849_main_MSG_LOG_NOT_MOD=Not modified, use cache
64850_main_MSG_LOG_REDIR=Redirected to %s
64851_main_MSG_LOG_NOT_SERVED=Not served: %d - %s
64852_main_MSG_LOG_UPL=Uploading %s
64853_main_MSG_LOG_UPLOADED=Fully uploaded %s - %s @ %sB/s
64854_main_MSG_LOG_UPL_FAIL=Upload failed %s
64855_main_MSG_LOG_DL=Fully downloaded - %s @ %sB/s - %s
64856_main_MSG_LOGIN_FAILED=Login failed
64857_main_MSG_MIN_DISK_REACHED=Minimum disk space reached.
64858_main_MSG_UPL_NAME_FORB=File name or extension forbidden.
64859_main_MSG_UPL_CANT_CREATE=Error creating file.
64860_main_FINGERPRINT=Create fingerprint on addition under %d KB
64861_main_NO_FINGERPRINT=Create fingerprint on addition: disabled
64862_main_MSG_SAVE_VFS=Your current file system is not saved.\^Save it?
64863_main_MSG_INP_COMMENT=Please insert a comment for "%s".\^You should use HTML: <br> for break line.
64864_main_MSG_BAN_CMT=Ban comment
64865_main_MSG_BAN_CMT_LONG=A comment for this ban...
64866_main_MSG_BREAK_DYN_DNS=This option is NOT compatible with "dynamic dns updater".\^Continue?
64867_main_MSG_CANT_OPEN_PORT=Cannot open port.
64868_main_MSG_PORT_USED_BY=It is already used by %s
64869_main_MSG_PORT_BLOCKED=Something is blocking, maybe your system firewall.
64870_main_MSG_KICK_ALL=There are %d connections open.\^Do you want to close them now?
64871_main_MSG_TPL_INCOMPATIBLE=The template you are trying to load is not compatible with current HFS version.\^HFS will now use default template.\^Ask on the forum if you need further help.
64872_main_MSG_LOG_SERVER_START=Server start
64873_main_MSG_LOG_SERVER_STOP=Server stop
64874_main_MSG_LOG_CONNECTED=Connected
64875_main_MSG_LOG_DISC_SRV=Disconnected by server
64876_main_MSG_LOG_DISC=Disconnected
64877_main_MSG_LOG_GOT=Got %d bytes
64878_main_MSG_LOG_BYTES_SENT=%s bytes sent
64879_main_MSG_LOG_SERVED=Served %s
64880_main_MSG_DDNS_FAIL=DNS update failed: %s\^User intervention is required.
64881_main_MSG_DDNS_REPLY_SIZE=%d bytes reply
64882_main_MSG_DDNS_badauth=invalid user/password
64883_main_MSG_DDNS_notfqdn=incomplete hostname, required form aaa.bbb.com
64884_main_MSG_DDNS_nohost=specified hostname does not exist
64885_main_MSG_DDNS_notyours=specified hostname belongs to another username
64886_main_MSG_DDNS_numhost=too many or too few hosts found
64887_main_MSG_DDNS_abuse=specified hostname is blocked for update abuse
64888_main_MSG_DDNS_dnserr=server error
64889_main_MSG_DDNS_911=server error
64890_main_MSG_DDNS_notdonator=an option specified requires payment
64891_main_MSG_DDNS_badagent=banned client
64892_main_MSG_BAN_MASK=Ban IP mask
64893_main_MSG_IP_MASK_LONG=You can edit the address.\^Masks and ranges are allowed.
64894_main_MSG_KICK_ADDR=There are %d open connections from this address.\^Do you want to kick them all now?
64895_main_MSG_BAN_ALREADY=This IP address is already banned
64896_main_MSG_ADDRESSES_EXCEED=The following addresses exceed the limit:\^%s
64897_main_MSG_NO_TEMP=Cannot save temporary file
64898_main_MSG_ERROR_REGISTRY=Can't write to registry.\^You may lack necessary rights.
64899_main_MSG_MANY_ITEMS=You are putting many files.\^Try using real folders instead of virtual folders.\^Read documentation or ask on the forum for help.
64900_main_MSG_ADD_TO_HFS="Add to HFS" has been added to your Window's Explorer right-click menu.
64901_main_MSG_SINGLE_INSTANCE=Sorry, this feature only works with the "Only 1 instance" option enabled.\^\^You can find this option under Menu -> Start/Exit\^(only in expert mode)
64902_main_MSG_COMM_ERROR=Network error. Request failed.
64903_main_MSG_CON_PAUSED=paused
64904_main_MSG_CON_SENT=%s / %s sent
64905_main_MSG_CON_RECEIVED=%s / %s received
64906_main_MSG_DDNS_NO_REPLY=no reply
64907_main_MSG_DDNS_OK=successful
64908_main_MSG_DDNS_UNK=unknown reply: %s
64909_main_MSG_DDNS_ERR=error: %s
64910_main_MSG_DDNS_REQ=DNS update requested for %s: %s
64911_main_MSG_DDNS_DOING=Updating dynamic DNS...
64912_main_MSG_MAX_CON_SING=Max connections from single address
64913_main_MSG_MAX_SIM_ADDR{1}=Max simultaneous addresses
64914_main_MSG_MAX_SIM_ADDR_DL=Max simultaneous addresses downloading
64915_main_MSG_MAX_SIM_DL_SING{2}=Max simultaneous downloads from single address
64916_main_MSG_MAX_SIM_DL=Max simultaneous downloads
64917_main_MSG_SET_LIMIT=Set limit
64918_main_MSG_UNPROTECTED_LINKS=Links are NOT actually protected.\^The feature is there to be used with the "list protected items only..." option.\^Continue?
64919_main_MSG_SAME_NAME=An item with the same name is already present in this folder.\^Continue?
64920_main_MSG_CONTINUE=Continue?
64921_main_MSG_PROCESSING=Processing...
64922_main_MSG_SPEED_KBS=%.1f kB/s
64923_main_MSG_OPTIONS_SAVED=Options saved
64924_main_MSG_SOME_LOCKED=Some items were not affected because locked
64925_main_MSG_ITEM_LOCKED=The item is locked
64926_main_MSG_INVALID_VALUE=Invalid value
64927_main_MSG_EMPTY_NO_LIMIT=Leave blank to get no limits.
64935_classesLib_MSG_ANTIDOS_REPLY=Please wait, server busy
64936_optionsDlg_MSG_INVERT_BAN=Normal behavior of the Ban is to prevent access to the addresses you specify (also called black-list).\^If you want the opposite, to allow the addresses that you specify (white-list), enter all addresses in a single row preceded by a \ character.\^\^Let say you want to allow all your 192.168 local network plus your office at 1.1.1.1.\^Just put this IP address mask: \192.168.*;1.1.1.1\^The opening \ character inverts the logic, so everything else is banned.\^\^If you want to know more about address masks, check the guide.
64937_main_S_PORT_LABEL=Port: %s
64938_main_S_PORT_ANY=any
64939_main_DISABLED=disabled
64940_main_S_OK=Ok
64941_main_MSG_MENU_VAL= (%s)
64942_main_MSG_DL_TIMEOUT{1}=No downloads timeout
64943_main_MSG_MAX_CON=Max connections
65046_OverbyteIcsHttpContCod_ERR_GETCODING_OVERRIDE=GetCoding must be overridden in %s
65088_OverbyteIcsCharsetUtils_sHebrewISOVisual=Hebrew (ISO-Visual)
65089_OverbyteIcsCharsetUtils_sHebrewWindows=Hebrew (Windows)
65090_OverbyteIcsCharsetUtils_sJapaneseJIS=Japanese (JIS)
65091_OverbyteIcsCharsetUtils_sKorean=Korean
65092_OverbyteIcsCharsetUtils_sKoreanEUC=Korean (EUC)
65093_OverbyteIcsCharsetUtils_sLatin9=Latin 9 (ISO)
65094_OverbyteIcsCharsetUtils_sThaiWindows=Thai (Windows)
65095_OverbyteIcsCharsetUtils_sTurkishISO=Turkish (ISO)
65096_OverbyteIcsCharsetUtils_sTurkishWindows=Turkish (Windows)
65097_OverbyteIcsCharsetUtils_sUnicodeUTF7=Unicode (UTF-7)
65098_OverbyteIcsCharsetUtils_sUnicodeUTF8=Unicode (UTF-8)
65099_OverbyteIcsCharsetUtils_sVietnameseWindows=Vietnamese (Windows)
65100_OverbyteIcsCharsetUtils_sWesternEuropeanISO=Western European (ISO)
65101_OverbyteIcsCharsetUtils_sWesternEuropeanWindows=Western European (Windows)
65104_OverbyteIcsCharsetUtils_sBalticISO=Baltic (ISO)
65105_OverbyteIcsCharsetUtils_sBalticWindows=Baltic (Windows)
65106_OverbyteIcsCharsetUtils_sCentralEuropeanISO=Central European (ISO)
65107_OverbyteIcsCharsetUtils_sCentralEuropeanWindows=Central European (Windows)
65108_OverbyteIcsCharsetUtils_sChineseTraditionalBig5=Chinese Traditional (Big5)
65109_OverbyteIcsCharsetUtils_sChineseSimplifiedGB18030=Chinese Simplified (GB18030)
65110_OverbyteIcsCharsetUtils_sChineseSimplifiedGB2312=Chinese Simplified (GB2312)
65111_OverbyteIcsCharsetUtils_sChineseSimplifiedHZ=Chinese Simplified (HZ)
65112_OverbyteIcsCharsetUtils_sCyrillicISO=Cyrillic (ISO)
65113_OverbyteIcsCharsetUtils_sCyrillicKOI8R=Cyrillic (KOI8-R)
65114_OverbyteIcsCharsetUtils_sCyrillicKOI8U=Cyrillic (KOI8-U)
65115_OverbyteIcsCharsetUtils_sCyrillicWindows=Cyrillic (Windows)
65116_OverbyteIcsCharsetUtils_sEstonianISO=Estonian (ISO)
65117_OverbyteIcsCharsetUtils_sGreekISO=Greek (ISO)
65118_OverbyteIcsCharsetUtils_sGreekWindows=Greek (Windows)
65119_OverbyteIcsCharsetUtils_sHebrewISOLogical=Hebrew (ISO-Logical)
65134_OverbyteIcsCharsetUtils_sArabicISO=Arabic (ISO)
65135_OverbyteIcsCharsetUtils_sArabicWindows=Arabic (Windows)

272
hslib.pas
View File

@ -1,5 +1,5 @@
{
Copyright (C) 2002-2014 Massimo Melina (www.rejetto.com)
Copyright (C) 2002-2020 Massimo Melina (www.rejetto.com)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -19,6 +19,7 @@ Copyright (C) 2002-2014 Massimo Melina (www.rejetto.com)
HTTP Server Lib
==== TO DO
* https
* upload bandwidth control (can it be done without multi-threading?)
}
@ -29,7 +30,7 @@ unit HSlib;
interface
uses
OverbyteIcsWSocket, classes, messages, winprocs, forms, extctrls, sysutils, contnrs, strUtils, winsock, inifiles, types;
OverbyteIcsWSocket, classes, messages, winprocs, forms, extctrls, sysutils, system.contnrs, strUtils, winsock, inifiles, types;
const
VERSION = '2.11.0';
@ -105,9 +106,9 @@ type
bodyFile: string;
bodyStream: Tstream; // note: the stream is automatically freed
firstByte, lastByte: int64; // body interval for partial replies (206)
realm: ansistring; // this will appear in the authentication dialog
url: ansistring; // used for redirections
reason: ansistring; // customized reason phrase
realm, // this will appear in the authentication dialog
reason, // customized reason phrase
url: string; // used for redirections
resumeForbidden: boolean;
end;
@ -156,6 +157,7 @@ type
P_requestCount: integer;
P_destroying: boolean; // destroying is in progress
P_sndBuf: integer;
P_v6: boolean;
persistent: boolean;
disconnecting: boolean; // disconnected() has been called
lockCount: integer; // prevent freeing of the object
@ -204,19 +206,22 @@ type
eventData: ansistring;
ignoreSpeedLimit: boolean;
limiters: TobjectList; // every connection can be bound to a number of TspeedLimiter
constructor create(server:ThttpSrv);
constructor create(server:ThttpSrv; acceptingSock:Twsocket);
destructor Destroy; override;
procedure disconnect();
procedure addHeader(s:ansistring; overwrite:boolean=TRUE); // set an additional header line. If overwrite=false will always append.
function setHeaderIfNone(s:string):boolean; // set header if not already existing
function setHeaderIfNone(s:ansistring):boolean; // set header if not already existing
procedure removeHeader(name:ansistring);
function getHeader(h:string):string; // extract the value associated to the specified header field
function getHeader(h:ansistring):string; // extract the value associated to the specified header field
function getHeaderA(h:ansistring):ansistring; // extract the value associated to the specified header field
function getCookie(k:string):string;
procedure setCookie(k, v:string; pairs:array of string; extra:string='');
procedure delCookie(k:string);
function getBuffer():ansistring;
function initInputStream():boolean;
property address:string read P_address; // other peer ip address
property port:string read P_port; // other peer port
property v6:boolean read P_v6;
property requestCount:integer read P_requestCount;
property bytesToSend:int64 read getBytesToSend;
property bytesToPost:int64 read getBytesToPost;
@ -259,7 +264,7 @@ type
procedure calculateSpeed();
procedure processDisconnecting();
public
sock: Twsocket; // listening socket
sock, sock6: Twsocket; // listening socket
conns, // full list of connected clients
disconnecting, // list of pending disconnections
offlines, // disconnected clients to be freed
@ -288,7 +293,7 @@ const
MINIMUM_CHUNK_SIZE = 2*1024;
MAXIMUM_CHUNK_SIZE = 1024*1024;
HRM2CODE: array [ThttpReplyMode] of integer = (200, 200, 403, 401, 404, 400,
500, 0, 0, 405, 302, 503, 413, 301, 304 );
500, 0, 0, 405, 302, 429, 413, 301, 304 );
METHOD2STR: array [ThttpMethod] of ansistring = ('UNK','GET','POST','HEAD');
HRM2STR: array [ThttpReplyMode] of ansistring = ('Head+Body', 'Head only', 'Deny',
'Unauthorized', 'Not found', 'Bad request', 'Internal error', 'Close',
@ -309,7 +314,7 @@ function chopLine(var s:string):string; overload;
// decode/decode url
function decodeURL(url:ansistring; utf8:boolean=TRUE):string;
function encodeURL(url:string; nonascii:boolean=TRUE; spaces:boolean=TRUE;
unicode:boolean=FALSE):string;
htmlEncoding:boolean=FALSE):string;
// returns true if address is not suitable for the internet
function isLocalIP(ip:string):boolean;
// base64 encoding
@ -329,9 +334,10 @@ function ipos(ss, s:string; ofs:integer=1):integer; overload;
implementation
uses
Windows;
Windows, ansistrings;
const
CRLF = #13#10;
HEADER_LIMITER: ansistring = CRLF+CRLF;
MAX_REQUEST_LENGTH = 64*1024;
MAX_INPUT_BUFFER_LENGTH = 256*1024;
// used as body content when the user did not specify any
@ -347,7 +353,7 @@ const
'',
'405 - Method not allowed',
'<html><head><meta http-equiv="refresh" content="url=%url%" /></head><body onload=''window.location="%url%"''>302 - <a href="%url%">Redirection to %url%</a></body></html>',
'503 - Server is overloaded, retry later',
'429 - Server is overloaded, retry later',
'413 - The request has exceeded the max length allowed',
'301 - Moved permanently to <a href="%url%">%url%</a>',
'' // RFC2616: The 304 response MUST NOT contain a message-body
@ -368,6 +374,8 @@ function isLocalIP(ip:string):boolean;
var
r: record d,c,b,a:byte end;
begin
if ip = '::1' then
exit(TRUE);
dword(r):=WSocket_ntohl(WSocket_inet_addr(ansiString(ip)));
result:=(r.a in [0,10,23,127])
or (r.a = 192) and ((r.b = 168) or (r.b = 0) and (r.c = 2))
@ -381,28 +389,11 @@ begin if c then result:=a else result:=b end;
function min(a,b:integer):integer;
begin if a < b then result:=a else result:=b end;
// this table is to be used by ipos(), to be calculated once
var
upcaseTab: array [char] of char;
function ipos(ss, s: string; ofs:integer=1):integer; overload;
procedure initTab();
var
i: char;
tmp: string;
begin
for i:=#0 to #255 do
begin
tmp:=ansiUppercase(i);
upcaseTab[i]:=tmp[1];
end;
end;
var
rss, rs, rss1, p: pchar;
l: integer;
begin
if upcaseTab[#1] = #0 then initTab();
result:=0;
l:=length(s);
if (l < ofs) or (l = 0) or (ss = '') then exit;
@ -414,7 +405,7 @@ for result:=ofs to l do
begin
rss:=rss1;
p:=rs;
while (rss^ <> #0) and (rss^ = upcaseTab[p^]) do
while (rss^ <> #0) and (rss^ = upcase(p^)) do
begin
inc(rss);
inc(p);
@ -476,6 +467,15 @@ else
end; // base64encode
function base64decode(s:ansistring):ansistring;
function if_(cond:boolean; c:ansichar):ansistring;
begin
if cond then
result:=c
else
result:=''
end;
const
TABLE:array[#43..#122] of byte=(
62,0,0,0,63,52,53,54,55,56,57,58,59,60,61,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,
@ -483,19 +483,59 @@ const
29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51);
var
i: integer;
p1, p2: byte;
begin
result:='';
i:=1;
while i <= length(s) do
begin
p1:=TABLE[s[i+1]];
p2:=TABLE[s[i+2]];
result:=result
+ansichar(TABLE[s[i]] shl 2+TABLE[s[i+1]] shr 4)
+ifThen(s[i+2]<>'=', ansichar(TABLE[s[i+1]] shl 4+TABLE[s[i+2]] shr 2))
+ifThen(s[i+3]<>'=', ansichar(TABLE[s[i+2]] shl 6+TABLE[s[i+3]]));
+ansichar(TABLE[s[i]] shl 2+p1 shr 4)
+if_(s[i+2]<>'=', ansichar(p1 shl 4+p2 shr 2))
+if_(s[i+3]<>'=', ansichar(p2 shl 6+TABLE[s[i+3]]));
inc(i,4);
end;
end; // base64decode
function validUTF8(s:rawbytestring):boolean;
var
i, more, len: integer;
c: byte;
begin
len:=length(s);
i:=0;
while i < len do
begin
inc(i);
c:=ord(s[i]);
if c < $80 then
continue;
if c >= $FE then
exit(FALSE);
if c >= $F0 then
more:=3
else if c >= $E0 then
more:=2
else if c >= $C0 then
more:=1
else
exit(FALSE);
if i+more > len then
exit(FALSE);
while more > 0 do
begin
inc(i);
c:=ord(s[i]);
if (c < $80) or (c > $C0) then
exit(FALSE);
dec(more);
end;
end;
result:=TRUE;
end; // validUTF8
function decodeURL(url:ansistring; utf8:boolean=TRUE):string;
var
i, j: integer;
@ -515,10 +555,11 @@ while i<length(url) do
url[j]:=url[i];
end;
setLength(url, j);
if utf8 then
if utf8 and validUTF8(url) then
begin
result:=utf8ToString(url);
if result='' then // if the string is not UTF8 compliant, the result is empty
// if the string is not UTF8 compliant, the result is empty, or sometimes same length (but ruined)
if (result='') or (length(result)=length(url)) then
result:=url;
end
else
@ -526,24 +567,26 @@ else
end; // decodeURL
function encodeURL(url:string; nonascii:boolean=TRUE; spaces:boolean=TRUE;
unicode:boolean=FALSE):string;
htmlEncoding:boolean=FALSE):string;
var
i: integer;
encodePerc, encodeUni: set of char;
encodePerc, encodeHTML: set of char;
a: ansistring;
begin
result:='';
if url = '' then
exit;
encodeUni:=[];
if nonascii then encodeUni:=[#128..#255];
encodePerc:=[#0..#31,'#','%','?','"','''','&','<','>',':'];
encodeHTML:=[];
if nonascii then
encodeHTML:=[#128..#255];
encodePerc:=[#0..#31,'#','%','?','"','''','&','<','>',':',
',',';']; // these for content-disposition
// actually ':' needs encoding only in relative url
if spaces then include(encodePerc,' ');
if not unicode then
if not htmlEncoding then
begin
encodePerc:=encodePerc+encodeUni;
encodeUni:=[];
encodePerc:=encodePerc+encodeHTML;
encodeHTML:=[];
end;
if nonascii then
begin
@ -556,7 +599,7 @@ if nonascii then
for i:=1 to length(url) do
if charInSet(url[i], encodePerc) then
result:=result+'%'+intToHex(ord(url[i]),2)
else if charInSet(url[i], encodeUni) then
else if charInSet(url[i], encodeHTML) then
result:=result+'&#'+intToStr(charToUnicode(url[i]))+';'
else
result:=result+url[i];
@ -582,7 +625,8 @@ end; // getIP
function replyHeader_IntPositive(name:ansistring; int:int64):ansistring;
begin
result:='';
if int >= 0 then result:=name+': '+intToStr(int)+CRLF;
if int >= 0 then
result:=name+': '+ansistring(intToStr(int))+CRLF;
end;
function replyHeader_Str(name:ansistring; str:ansistring):ansistring;
@ -633,7 +677,7 @@ end; // chopline
function chopLine(var s:ansistring):ansistring; overload;
begin
result:=chop(pos(#10,s),1,s);
result:=chop(#10,s);
if (result>'') and (result[length(result)]=#13) then
setlength(result, length(result)-1);
end; // chopline
@ -645,15 +689,22 @@ begin
result:=FALSE;
if active or not assigned(sock) then exit;
try
if onAddress = '' then onAddress:='*';
if (onAddress = '') or (onAddress = '*') then sock.addr:='0.0.0.0'
else sock.addr:=onAddress;
if onAddress = '' then
onAddress:='*';
sock.addr:=ifThen(onAddress = '*', '0.0.0.0', onAddress);
sock.port:=port;
sock.proto:='6';
sock.listen();
if port = '0' then
P_port:=sock.getxport();
result:=TRUE;
if onAddress = '*' then
with sock6 do
begin
addr:='::';
Port:=sock.port;
try listen except end;
end;
notify(HE_OPEN, NIL);
except
end;
@ -661,12 +712,13 @@ end; // start
procedure ThttpSrv.stop();
begin
if assigned(sock) then
if sock = NIL then exit;
try sock.Close() except end;
try sock6.Close() except end;
end;
procedure ThttpSrv.connected(Sender: TObject; Error: Word);
begin if error=0 then ThttpConn.create(self) end;
begin if error=0 then ThttpConn.create(self, sender as Twsocket) end;
procedure ThttpSrv.disconnected(Sender: TObject; Error: Word);
begin notify(HE_CLOSE, NIL) end;
@ -677,6 +729,9 @@ sock:=TWSocket.create(NIL);
sock.OnSessionAvailable:=connected;
sock.OnSessionClosed:=disconnected;
sock.OnBgException:=bgexception;
sock6:=TWSocket.create(NIL);
sock6.OnSessionAvailable:=connected;
sock6.OnBgException:=bgexception;
conns:=TobjectList.create;
conns.OwnsObjects:=FALSE;
@ -822,7 +877,6 @@ end; // timerEvent
procedure ThttpSrv.notify(ev:ThttpEvent; conn:ThttpConn);
begin
if not assigned(onEvent) then exit;
//if assigned(sock) then sock.pause();
if assigned(conn) then
begin
inc(conn.lockCount);
@ -908,13 +962,13 @@ begin canClose:=FALSE end;
////////// CLIENT
constructor ThttpConn.create(server:ThttpSrv);
constructor ThttpConn.create(server:ThttpSrv; acceptingSock:Twsocket);
var
i: integer;
begin
// init socket
sock:=Twsocket.create(NIL);
sock.Dup(server.sock.Accept);
sock.Dup(acceptingSock.accept());
sock.OnDataAvailable:=dataavailable;
sock.OnSessionClosed:=disconnected;
sock.onSendData:=senddata;
@ -927,6 +981,7 @@ limiters:=TObjectList.create;
limiters.ownsObjects:=FALSE;
P_address:=sock.GetPeerAddr();
P_port:=sock.GetPeerPort();
P_v6:=pos(':', address) > 0;
state:=HCS_IDLE;
srv:=server;
srv.conns.add(self);
@ -992,13 +1047,20 @@ state:=HCS_DISCONNECTED;
srv.disconnecting.Add(self);
end;
function ThttpConn.getHeader(h:string):string;
function ThttpConn.getHeader(h:ansistring):string;
begin
result:='';
if request.method = HM_UNK then exit;
result:=trim(request.headers.values[h]);
if request.method <> HM_UNK then
result:=trim(UTF8toString(rawByteString(request.headers.values[h])));
end; // getHeader
function ThttpConn.getHeaderA(h:ansistring):ansistring;
begin
result:='';
if request.method <> HM_UNK then
result:=ansistrings.trim(ansistring(request.headers.values[h]));
end; // getHeaderA
function ThttpConn.getBuffer():ansistring;
begin result:=buffer end;
@ -1016,6 +1078,9 @@ if request.cookies = NIL then
result:=decodeURL(ansistring(trim(request.cookies.values[k])));
end; // getCookie
procedure ThttpConn.delCookie(k:string);
begin setCookie(k,'', ['expires','Thu, 01-Jan-70 00:00:01 GMT']) end;
procedure ThttpConn.setCookie(k, v:string; pairs:array of string; extra:string='');
var
i: integer;
@ -1027,7 +1092,7 @@ while i < length(pairs)-1 do
v:=v+lowerCase(pairs[i])+'='+pairs[i+1]+'; ';
inc(i,2);
end;
addHeader(v+extra);
addHeader(UTF8encode(v+extra));
end; // setCookie
procedure ThttpConn.clearRequest();
@ -1083,13 +1148,13 @@ procedure ThttpConn.processInputBuffer();
request.url:=chop(' ', r);
s:=uppercase(chopLine(r));
s:=ansiUppercase(chopLine(r));
// if 'HTTP/' is not found, chop returns S
if chop('HTTP/',s) = '' then request.ver:=s;
request.headers.text:=r;
s:=getHeader('Range');
s:=getHeaderA('Range');
if ansiStartsText('bytes=',s) then
begin
delete(s,1,6);
@ -1100,20 +1165,20 @@ procedure ThttpConn.processInputBuffer();
except end;
end;
s:=getHeader('Authorization');
s:=getHeaderA('Authorization');
if AnsiStartsText('Basic',s) then
begin
delete(s,1,6);
u:=UTF8decode(base64decode(s));
u:=UTF8toString(base64decode(s));
request.user:=trim(chop(':',u));
request.pwd:=u;
end;
s:=getHeader('Connection');
s:=getHeaderA('Connection');
persistent:=srv.persistentConnections and
(ansiStartsText('Keep-Alive',s) or (request.ver >= '1.1') and (ipos('close',s)=0));
s:=getHeader('Content-Type');
s:=ansistring(getHeader('Content-Type'));
if ansiStartsText('application/x-www-form-urlencoded', s) then
post.mode:=PM_URLENCODED
else if ansiStartsText('multipart/form-data', s) then
@ -1149,8 +1214,8 @@ procedure ThttpConn.processInputBuffer();
var
i: integer;
s, l, k, c: string;
s, l, k, v: ansistring;
ws: widestring;
begin
repeat
{ When the buffer is stuffed with file bytes only, we can avoid calling pos() and chop().
@ -1191,11 +1256,12 @@ procedure ThttpConn.processInputBuffer();
break;
end;
// we wait for the header to be complete
if posEx(CRLF+CRLF, buffer, i+length(post.boundary)) = 0 then break;
if posEx(HEADER_LIMITER, buffer, i+length(post.boundary)) = 0 then
break;
handleLeftData(i);
post.filename:='';
post.data:='';
post.header:=chop(CRLF+CRLF, buffer);
post.header:=chop(HEADER_LIMITER, buffer);
chopLine(post.header);
// parse the header part
s:=post.header;
@ -1204,25 +1270,28 @@ procedure ThttpConn.processInputBuffer();
l:=chopLine(s);
if l = '' then continue;
k:=chop(':', l);
if not sameText(k, 'Content-Disposition') then continue; // we are not interested in other fields
if not sameText(k, 'Content-Disposition') then // we are only interested in content-disposition: form-data
continue;
k:=trim(chop(';', l));
if not sameText(k, 'form-data') then continue;
if not sameText(k, 'form-data') then
continue;
while l > '' do
begin
c:=chop(nonQuotedPos(';', l), l);
k:=UTF8decode(trim(chop('=', c)));
c:=UTF8decode(ansiDequotedStr(c,'"'));
v:=chop(nonQuotedPos(';', l), 1, l);
k:=trim(chop('=', v));
ws:=UTF8toString(ansiDequotedStr(v,'"'));
if sameText(k, 'filename') then
begin
delete(c, 1, lastDelimiter('/\',c));
post.filename:=c;
end;
if sameText(k, 'name') then
post.varname:=c;
delete(ws, 1, lastDelimiter('/\',ws));
post.filename:=ws;
end
else if sameText(k, 'name') then
post.varname:=ws;
end;
end;
lastPostItemPos:=bytesPosted-length(buffer);
if post.filename = '' then continue;
if post.filename = '' then
continue;
firstPostFile:=FALSE;
tryNotify(HE_POST_FILE);
until false;
@ -1288,17 +1357,17 @@ procedure ThttpConn.processInputBuffer();
handlePostData();
end; // handleHeaderData
function replyHeader_OK(contentLength:int64=-1):string;
function replyHeader_OK(contentLength:int64=-1):ansistring;
begin
result:=replyheader_code(200)
+format('Content-Length: %d'+CRLF, [contentLength]);
+ansistring(format('Content-Length: %d'+CRLF, [contentLength]));
end; // replyHeader_OK
function replyHeader_PARTIAL( firstB, lastB, totalB:int64):string;
function replyHeader_PARTIAL( firstB, lastB, totalB:int64):ansistring;
begin
result:=replyheader_code(206)
+format('Content-Range: bytes %d-%d/%d'+CRLF+'Content-Length: %d'+CRLF,
[firstB, lastB, totalB, lastB-firstB+1 ])
+ansistring(format('Content-Range: bytes %d-%d/%d'+CRLF+'Content-Length: %d'+CRLF,
[firstB, lastB, totalB, lastB-firstB+1 ]))
end; // replyheader_PARTIAL
begin
@ -1306,7 +1375,7 @@ if buffer = '' then exit;
if state = HCS_IDLE then
begin
state:=HCS_REQUESTING;
reply.contentType:='text/html';
reply.contentType:='text/html; charset=utf-8';
notify(HE_REQUESTING);
end;
case state of
@ -1324,7 +1393,7 @@ notify(HE_REQUESTED);
if not initInputStream() then
begin
reply.mode:=HRM_INTERNAL_ERROR;
reply.contentType:='text/html';
reply.contentType:='text/html; charset=utf-8';
notify(HE_CANT_OPEN_FILE);
end;
notify(HE_STREAM_READY);
@ -1340,9 +1409,9 @@ case reply.mode of
HRM_DENY: sendHeader( replyheader_mode(reply.mode) );
HRM_UNAUTHORIZED:
sendHeader(replyheader_mode(reply.mode)
+replyHeader_Str('WWW-Authenticate','Basic realm="'+reply.realm+'"') );
+replyHeader_Str('WWW-Authenticate','Basic realm="'+UTF8encode(reply.realm)+'"') );
HRM_REDIRECT, HRM_MOVED:
sendHeader(replyheader_mode(reply.mode)+'Location: '+reply.url );
sendHeader(replyheader_mode(reply.mode)+'Location: '+UTF8encode(reply.url) );
HRM_REPLY, HRM_REPLY_HEADER:
if stream = NIL then
sendHeader( replyHeader_code(404) )
@ -1360,7 +1429,7 @@ end; // processInputBuffer
procedure ThttpConn.dataavailable(Sender: TObject; Error: Word);
var
s: string;
s: ansistring;
begin
if error <> 0 then exit;
s:=sock.ReceiveStrA();
@ -1422,9 +1491,9 @@ if (state = HCS_REPLYING_HEADER) and (reply.mode <> HRM_REPLY_HEADER) then
if ((stream = NIL) or (stream.size = 0)) and (reply.mode <> HRM_REPLY) then
begin
reply.bodyMode:=RBM_STRING;
reply.body:=HRM2BODY[reply.mode];
reply.body:=UTF8encode(HRM2BODY[reply.mode]);
if reply.mode in [HRM_REDIRECT, HRM_MOVED] then
reply.body:=replaceStr(reply.body, '%url%', reply.url);
reply.body:=ansistrings.replaceStr(reply.body, '%url%', UTF8encode(reply.url));
initInputStream();
end;
end;
@ -1487,7 +1556,6 @@ end; // partialBodySize
function ThttpConn.initInputStream():boolean;
var
i: integer;
buf: ansistring;
begin
result:=FALSE;
FreeAndNil(stream);
@ -1531,7 +1599,7 @@ end; // initInputStream
function ThttpConn.sendNextChunk(max:integer=MAXINT):integer;
var
n: int64;
n, toSend: int64;
buf: ansistring;
begin
result:=0;
@ -1543,7 +1611,8 @@ if (n = 0) or (bytesSentLastItem = 0) then n:=max;
if n > MAXIMUM_CHUNK_SIZE then n:=MAXIMUM_CHUNK_SIZE;
if n < MINIMUM_CHUNK_SIZE then n:=MINIMUM_CHUNK_SIZE;
if n > max then n:=max;
if n > bytesToSend then n:=bytesToSend;
toSend:=bytesToSend;
if n > toSend then n:=toSend;
if n = 0 then exit;
setLength(buf, n);
n:=stream.read(buf[1], n);
@ -1601,15 +1670,16 @@ end; // replycode2reason
function ThttpConn.replyHeader_code(code:integer):ansistring;
begin
if reply.reason = '' then reply.reason:=replycode2reason(code);
result:=format('HTTP/1.1 %d %s'+CRLF, [code,reply.reason])
if reply.reason = '' then
reply.reason:=replycode2reason(code);
result:=UTF8encode(format('HTTP/1.1 %d %s'+CRLF, [code,reply.reason]))
+ replyHeader_Str('Content-Type',reply.contentType)
end;
function ThttpConn.replyHeader_mode(mode:ThttpReplyMode):ansistring;
begin result:=replyHeader_code(HRM2CODE[mode]) end;
function getNameOf(s:ansistring):string; // colon included
function getNameOf(s:ansistring):ansistring; // colon included
begin result:=copy(s, 1, pos(':', s)) end;
// return 0 if not found
@ -1623,9 +1693,9 @@ result:=from;
end; // namePos
// return true if the operation succeded
function ThttpConn.setHeaderIfNone(s:string):boolean;
function ThttpConn.setHeaderIfNone(s:ansistring):boolean;
var
name: string;
name: ansistring;
begin
name:=getNameOf(s);
if name = '' then

View File

@ -1,8 +0,0 @@
Normal behavior of the Ban is to prevent access to the addresses you specify (also called black-list).
If you want the opposite, to allow the addresses that you specify (white-list), enter all addresses in a single row preceded by a \ character.
Let say you want to allow all your 192.168 local network plus your office at 1.1.1.1.
Just put this IP address mask: \192.168.*;1.1.1.1
The opening \ character inverts the logic, so everything else is banned.
If you want to know more about address masks, check the guide.

File diff suppressed because one or more lines are too long

166
main.dfm
View File

@ -2,14 +2,14 @@ object mainFrm: TmainFrm
Left = 293
Top = 219
Caption = 'HFS ~ HTTP File Server'
ClientHeight = 391
ClientWidth = 783
ClientHeight = 436
ClientWidth = 879
Color = clBtnFace
Constraints.MinHeight = 260
Constraints.MinWidth = 390
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Height = -12
Font.Name = 'Tahoma'
Font.Style = []
KeyPreview = True
@ -23,11 +23,11 @@ object mainFrm: TmainFrm
OnResize = FormResize
OnShow = FormShow
PixelsPerInch = 96
TextHeight = 13
TextHeight = 14
object graphSplitter: TSplitter
Left = 0
Top = 78
Width = 783
Width = 879
Height = 5
Cursor = crVSplit
Align = alTop
@ -42,10 +42,16 @@ object mainFrm: TmainFrm
object graphBox: TPaintBox
Left = 0
Top = 48
Width = 783
Width = 879
Height = 30
Hint = 'Pink = Out'#13#10'Yellow = In'
Align = alTop
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -12
Font.Name = 'Tahoma'
Font.Style = []
ParentFont = False
ParentShowHint = False
PopupMenu = graphMenu
ShowHint = True
@ -56,14 +62,20 @@ object mainFrm: TmainFrm
object topToolbar: TToolBar
Left = 0
Top = 0
Width = 783
Width = 879
Height = 24
AutoSize = True
ButtonWidth = 138
ButtonWidth = 150
Caption = 'topToolbar'
EdgeBorders = [ebBottom]
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -12
Font.Name = 'Tahoma'
Font.Style = []
Images = images
List = True
ParentFont = False
ShowCaptions = True
TabOrder = 1
object menuBtn: TToolButton
@ -78,7 +90,7 @@ object mainFrm: TmainFrm
OnClick = menuBtnClick
end
object ToolButton4: TToolButton
Left = 57
Left = 61
Top = 0
Width = 9
Caption = 'ToolButton4'
@ -86,7 +98,7 @@ object mainFrm: TmainFrm
Style = tbsSeparator
end
object portBtn: TToolButton
Left = 66
Left = 70
Top = 0
AutoSize = True
Caption = 'Port: any'
@ -94,7 +106,7 @@ object mainFrm: TmainFrm
OnClick = portBtnClick
end
object ToolButton2: TToolButton
Left = 142
Left = 151
Top = 0
Width = 8
Caption = 'ToolButton2'
@ -102,7 +114,7 @@ object mainFrm: TmainFrm
Style = tbsSeparator
end
object modeBtn: TToolButton
Left = 150
Left = 159
Top = 0
Hint = 'Click to switch'#13#10'F5 on keyboard'
AutoSize = True
@ -113,7 +125,7 @@ object mainFrm: TmainFrm
OnClick = modeBtnClick
end
object ToolButton1: TToolButton
Left = 284
Left = 309
Top = 0
Width = 9
Caption = 'ToolButton1'
@ -121,7 +133,7 @@ object mainFrm: TmainFrm
Style = tbsSeparator
end
object startBtn: TToolButton
Left = 293
Left = 318
Top = 0
Hint = 'Click to switch ON'#13'F4 on keyboard'
AutoSize = True
@ -132,7 +144,7 @@ object mainFrm: TmainFrm
OnClick = startBtnClick
end
object abortBtn: TToolButton
Left = 435
Left = 472
Top = 0
AutoSize = True
Caption = 'Abort file addition'
@ -141,7 +153,7 @@ object mainFrm: TmainFrm
OnClick = abortBtnClick
end
object restoreCfgBtn: TToolButton
Left = 551
Left = 600
Top = 0
Caption = 'Restore my options'
ImageIndex = 34
@ -149,7 +161,7 @@ object mainFrm: TmainFrm
OnClick = restoreCfgBtnClick
end
object updateBtn: TToolButton
Left = 689
Left = 750
Top = 0
AutoSize = True
Caption = 'Update now'
@ -161,13 +173,19 @@ object mainFrm: TmainFrm
object urlToolbar: TToolBar
Left = 0
Top = 24
Width = 783
Width = 879
Height = 24
AutoSize = True
ButtonWidth = 111
ButtonWidth = 122
EdgeBorders = [ebBottom]
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -12
Font.Name = 'Tahoma'
Font.Style = []
Images = images
List = True
ParentFont = False
ShowCaptions = True
TabOrder = 2
Wrapable = False
@ -180,7 +198,7 @@ object mainFrm: TmainFrm
OnClick = browseBtnClick
end
object urlBox: TEdit
Left = 110
Left = 122
Top = 0
Width = 433
Height = 22
@ -188,7 +206,7 @@ object mainFrm: TmainFrm
OnChange = urlBoxChange
end
object copyBtn: TToolButton
Left = 543
Left = 555
Top = 0
AutoSize = True
Caption = 'Copy to clipboard'
@ -199,15 +217,21 @@ object mainFrm: TmainFrm
object centralPnl: TPanel
Left = 0
Top = 83
Width = 783
Height = 308
Width = 879
Height = 353
Align = alClient
BevelOuter = bvNone
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -12
Font.Name = 'Tahoma'
Font.Style = []
ParentFont = False
TabOrder = 0
object splitV: TSplitter
Left = 313
Top = 0
Height = 197
Height = 242
Beveled = True
Constraints.MaxWidth = 3
Constraints.MinWidth = 3
@ -217,8 +241,8 @@ object mainFrm: TmainFrm
end
object splitH: TSplitter
Left = 0
Top = 197
Width = 783
Top = 242
Width = 879
Height = 5
Cursor = crVSplit
Align = alBottom
@ -232,20 +256,20 @@ object mainFrm: TmainFrm
object logPnl: TPanel
Left = 316
Top = 0
Width = 467
Height = 197
Width = 563
Height = 242
Align = alClient
BevelOuter = bvNone
TabOrder = 1
object logBox: TRichEdit
Left = 0
Top = 23
Width = 467
Height = 174
Width = 563
Height = 219
Align = alClient
Font.Charset = ANSI_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Height = -12
Font.Name = 'Tahoma'
Font.Style = []
HideSelection = False
@ -262,7 +286,7 @@ object mainFrm: TmainFrm
object logTitle: TPanel
Left = 0
Top = 0
Width = 467
Width = 563
Height = 23
Align = alTop
BevelOuter = bvNone
@ -270,7 +294,7 @@ object mainFrm: TmainFrm
object titlePnl: TPanel
Left = 0
Top = 0
Width = 211
Width = 303
Height = 23
Align = alClient
BevelOuter = bvNone
@ -278,9 +302,9 @@ object mainFrm: TmainFrm
TabOrder = 0
end
object logToolbar: TPanel
Left = 211
Left = 303
Top = 0
Width = 256
Width = 260
Height = 23
Align = alRight
AutoSize = True
@ -329,14 +353,14 @@ object mainFrm: TmainFrm
object expandedPnl: TPanel
Left = 21
Top = 0
Width = 235
Width = 239
Height = 23
Align = alRight
AutoSize = True
BevelOuter = bvNone
TabOrder = 1
object openFilteredLog: TSpeedButton
Left = 209
Left = 213
Top = 0
Width = 26
Height = 23
@ -401,7 +425,7 @@ object mainFrm: TmainFrm
OnClick = openLogBtnClick
end
object openLogBtn: TSpeedButton
Left = 183
Left = 187
Top = 0
Width = 26
Height = 23
@ -486,7 +510,7 @@ object mainFrm: TmainFrm
object searchPnl: TPanel
Left = 23
Top = 0
Width = 160
Width = 164
Height = 23
Align = alRight
AutoSize = True
@ -494,17 +518,17 @@ object mainFrm: TmainFrm
Padding.Left = 5
TabOrder = 0
DesignSize = (
160
164
23)
object logSearchBox: TLabeledEdit
Left = 41
Left = 45
Top = 1
Width = 103
Height = 21
Height = 22
Hint = 'Wildcards allowed'
Anchors = [akTop, akRight]
EditLabel.Width = 33
EditLabel.Height = 13
EditLabel.Width = 37
EditLabel.Height = 14
EditLabel.Caption = 'Search'
LabelPosition = lpLeft
ParentShowHint = False
@ -514,7 +538,7 @@ object mainFrm: TmainFrm
OnKeyPress = logSearchBoxKeyPress
end
object logUpDown: TUpDown
Left = 144
Left = 148
Top = 0
Width = 16
Height = 24
@ -533,7 +557,7 @@ object mainFrm: TmainFrm
Left = 0
Top = 0
Width = 313
Height = 197
Height = 242
Align = alLeft
BevelOuter = bvNone
Caption = 'filesPnl'
@ -542,7 +566,7 @@ object mainFrm: TmainFrm
Left = 0
Top = 23
Width = 313
Height = 174
Height = 219
Align = alClient
BevelInner = bvLowered
BevelOuter = bvSpace
@ -592,8 +616,8 @@ object mainFrm: TmainFrm
end
object connPnl: TPanel
Left = 0
Top = 202
Width = 783
Top = 247
Width = 879
Height = 106
Align = alBottom
BevelOuter = bvNone
@ -601,7 +625,7 @@ object mainFrm: TmainFrm
object sbar: TStatusBar
Left = 0
Top = 87
Width = 783
Width = 879
Height = 19
Panels = <
item
@ -613,7 +637,7 @@ object mainFrm: TmainFrm
object connBox: TListView
Left = 0
Top = 0
Width = 783
Width = 879
Height = 87
Align = alClient
Columns = <
@ -636,6 +660,7 @@ object mainFrm: TmainFrm
item
Alignment = taCenter
Caption = 'Speed'
Width = 100
end
item
Alignment = taCenter
@ -724,6 +749,13 @@ object mainFrm: TmainFrm
AutoHotkeys = maManual
Caption = 'Copy URL with password'
end
object CopyURLwithdifferentaddress1: TMenuItem
Caption = 'Copy URL with different host address'
end
object CopyURLwithfingerprint1: TMenuItem
Caption = 'Copy URL with fingerprint'
OnClick = CopyURLwithfingerprint1Click
end
object Browseit1: TMenuItem
Caption = 'Browse it'
ImageIndex = 26
@ -760,13 +792,6 @@ object mainFrm: TmainFrm
object N11: TMenuItem
Caption = '-'
end
object CopyURLwithdifferentaddress1: TMenuItem
Caption = 'Copy URL with different host address'
end
object CopyURLwithfingerprint1: TMenuItem
Caption = 'Copy URL with fingerprint'
OnClick = CopyURLwithfingerprint1Click
end
object Purge1: TMenuItem
Caption = 'Purge...'
OnClick = Purge1Click
@ -2769,12 +2794,10 @@ object mainFrm: TmainFrm
object MinimizetotrayChk: TMenuItem
AutoCheck = True
Caption = 'Minimize to tray'
Checked = True
end
object showmaintrayiconChk: TMenuItem
AutoCheck = True
Caption = 'Show main tray icon'
Checked = True
OnClick = showmaintrayiconChkClick
end
object hetrayiconshows1: TMenuItem
@ -2908,15 +2931,9 @@ object mainFrm: TmainFrm
AutoCheck = True
Caption = 'Encode non-ASCII characters'
end
object encodePwdUrlChk: TMenuItem
AutoCheck = True
Caption = 'Unreadable passwords in URLs'
Checked = True
end
object pwdInPagesChk: TMenuItem
AutoCheck = True
Caption = 'Include password in pages (for download managers)'
OnClick = pwdInPagesChkClick
end
object httpsUrlsChk: TMenuItem
AutoCheck = True
@ -2946,10 +2963,6 @@ object mainFrm: TmainFrm
AutoCheck = True
Caption = 'Enable macros.log'
end
object Appendmacroslog1: TMenuItem
AutoCheck = True
Caption = 'Append macros.log'
end
object Runscript1: TMenuItem
Caption = 'Run script...'
OnClick = Runscript1Click
@ -3135,8 +3148,8 @@ object mainFrm: TmainFrm
object connmenu: TPopupMenu
Images = images
OnPopup = connmenuPopup
Left = 248
Top = 320
Left = 264
Top = 408
object Kickconnection1: TMenuItem
Caption = 'Kick connection'
OnClick = Kickconnection1Click
@ -3169,11 +3182,6 @@ object mainFrm: TmainFrm
Caption = 'View http request'
OnClick = Viewhttprequest1Click
end
object leavedisconnectedconnectionsChk: TMenuItem
AutoCheck = True
Caption = 'Leave disconnected connections'
OnClick = leavedisconnectedconnectionsChkClick
end
object trayiconforeachdownload1: TMenuItem
Caption = 'Tray icon for each download'
Checked = True
@ -3191,7 +3199,8 @@ object mainFrm: TmainFrm
OnMinimize = appEventsMinimize
OnRestore = appEventsRestore
OnShowHint = appEventsShowHint
Left = 592
Left = 688
Top = 8
end
object logmenu: TPopupMenu
Images = images
@ -3259,7 +3268,6 @@ object mainFrm: TmainFrm
object logRequestsChk: TMenuItem
AutoCheck = True
Caption = 'Requests'
Checked = True
end
object DumprequestsChk: TMenuItem
AutoCheck = True

2167
main.pas

File diff suppressed because it is too large Load Diff

View File

@ -1,62 +0,0 @@
=== 4GB+ FILES DOWNLOAD SUPPORT
Reget Deluxe 4.1
MetaProducts Download Express 1.7
Getright
Firefox 2.0
=== 2GB+ FILES UPLOAD SUPPORT
firefox 3.0: no
=== HOW TO CREATE BIG FILES
fsutil file createnew <filename> <filesize>
=== HOW TO DOWNLOAD WITH NO DISK ACTIVITY (SPEED TEST)
create a big file as above
then download this way: wget -q -O nul http://localhost/big
=== SUBMITTED TO
www.nonags.com
www.sharewareconnection.com
=== LISTED ON
www.sofotex.com
www.download3000.com
www.onekit.com
www.all4you.dk/FreewareWorld
www.snapfiles.com
sourceforge
www.freedownloadscenter.com
download.freenet.de
www.softonic.com
www.portablefreeware.com
www.download.com
www.freewarepub.org
www.handyarchive.com
www.softpedia.com
www.acidfiles.com
www.fileedge.com
www.freewarepark.com
=== REVIEWS
http://www.technospot.net/blogs/host-a-web-server-on-your-home-pc/
http://www.snapfiles.com/get/hfs.html
http://www.downloadsquad.com/2006/05/24/hft-quick-and-easy-http-file-server/
http://www.caseytech.com/how-to-host-a-web-site-from-your-computer/
http://www.chip.de/downloads/c1_downloads_29480524.html
http://blog.pcserenity.com/2009/01/easy-conten-sharing-with-windows.html
http://hfs.onehelp.ch
http://www.lanacion.com.ar/nota.asp?nota_id=1148507
http://blogmotion.fr/systeme/partage-windows-hfs-3947
ita
http://lafabbricadibyte.wordpress.com/2007/05/01/hfs-file-server-http-gratuito-per-windows/
http://server.html.it/articoli/leggi/2335/hfs-file-sharing-via-http/
=== OTHER SOFTWARE BASED ON HFS
http://www.wrinx.com/products/pfs/
commercial, licensed
http://www.powernetservers.com/pnwfs.php
commercial, probably unlicensed
=== INSTALLABLE PLUGINS
log links usage
http://www.rejetto.com/forum/index.php/topic,7765.msg1047258.html#msg1047258

View File

@ -154,7 +154,7 @@ object optionsFrm: ToptionsFrm
object Label3: TLabel
Left = 11
Top = 173
Width = 257
Width = 312
Height = 28
Caption = 'Here you can see protected resources this user can access...'
FocusControl = accountAccessBox
@ -222,9 +222,9 @@ object optionsFrm: ToptionsFrm
Top = 106
Width = 198
Height = 22
EditLabel.Width = 111
EditLabel.Width = 105
EditLabel.Height = 14
EditLabel.Caption = 'After ~login, redirect to'
EditLabel.Caption = 'After login, redirect to'
TabOrder = 4
OnChange = redirBoxChange
end

View File

@ -759,7 +759,7 @@ begin
if renamingAccount then
exit;
key:=upcase(key);
if key in ['0'..'9','A'..'Z'] then
if charInSet(key, ['0'..'9','A'..'Z']) then
begin
s:=accountsBox.ItemIndex;
n:=length(tempAccounts);
@ -834,7 +834,16 @@ procedure ToptionsFrm.okBtnClick(Sender: TObject);
begin if saveValues() then close() end;
procedure ToptionsFrm.Button1Click(Sender: TObject);
begin msgDlg(getRes('invertBan')) end;
resourcestring MSG_INVERT_BAN =
'Normal behavior of the Ban is to prevent access to the addresses you specify (also called black-list).'
+#13'If you want the opposite, to allow the addresses that you specify (white-list), enter all addresses in a single row preceded by a \ character.'
+#13
+#13'Let say you want to allow all your 192.168 local network plus your office at 1.1.1.1.'
+#13'Just put this IP address mask: \192.168.*;1.1.1.1'
+#13'The opening \ character inverts the logic, so everything else is banned.'
+#13
+#13'If you want to know more about address masks, check the guide.';
begin msgDlg(MSG_INVERT_BAN) end;
procedure ToptionsFrm.groupsBtnClick(Sender: TObject);
var

View File

@ -1,2 +1,2 @@
brcc32 data.rc
dcc32 hfs -U\code\mine\libs;\code\other\ics\delphi\vc32;\code\other\compiled;c:\code\other\jcl\source\windows\;c:\code\other\jcl\source\common\;C:\progs\Borland\BDS\4.0\lib
dcc32.exe hfs.dpr -$W+ --no-config -M -Q -TX.exe -AForms=VCL.Forms;Generics.Collections=System.Generics.Collections;Generics.Defaults=System.Generics.Defaults;WinTypes=Winapi.Windows;WinProcs=Winapi.Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE -DDEBUG -I"c:\program files (x86)\embarcadero\studio\20.0\Lib\Debug";"c:\program files (x86)\embarcadero\studio\20.0\lib\Win32\release";C:\Users\rejetto\Documents\Embarcadero\Studio\20.0\Imports;"c:\program files (x86)\embarcadero\studio\20.0\Imports"; C:\Users\Public\Documents\Embarcadero\Studio\20.0\Dcp;"c:\program files (x86)\embarcadero\studio\20.0\include";Presbylutheran;C:\code\other\compiled; C:\code\other\fastmm4;uFreeLocalizer;C:\code\other\kdl;c:\code\other\ics8\source;c:\code\other\GifImage;c:\code\other\DelphiZLib; c:\code\other\regexp\Source;c:\code\other\jcl\source\windows;c:\code\other\jcl\source\include;c:\code\other\jcl\source\common -LEC:\Users\Public\Documents\Embarcadero\Studio\20.0\Bpl -LNC:\Users\Public\Documents\Embarcadero\Studio\20.0\Dcp -NSData.Win;Datasnap.Win;Web.Win; Soap.Win;Xml.Win;Bde;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;Winapi;System.Win; -O"c:\program files (x86)\embarcadero\studio\20.0\Lib\Debug";"c:\program files (x86)\embarcadero\studio\20.0\lib\Win32\release";"c:\program files (x86)\embarcadero\studio\20.0\Imports"; C:\Users\Public\Documents\Embarcadero\Studio\20.0\Dcp;"c:\program files (x86)\embarcadero\studio\20.0\include";Presbylutheran;C:\code\other\compiled; C:\code\other\fastmm4;uFreeLocalizer;C:\code\other\kdl;c:\code\other\ics8\source;c:\code\other\GifImage;c:\code\other\DelphiZLib; c:\code\other\regexp\Source;c:\code\other\jcl\source\windows;c:\code\other\jcl\source\include;c:\code\other\jcl\source\common -R"c:\program files (x86)\embarcadero\studio\20.0\Lib\Debug";"c:\program files (x86)\embarcadero\studio\20.0\lib\Win32\release";"c:\program files (x86)\embarcadero\studio\20.0\Imports"; C:\Users\Public\Documents\Embarcadero\Studio\20.0\Dcp;"c:\program files (x86)\embarcadero\studio\20.0\include";Presbylutheran;C:\code\other\compiled; C:\code\other\fastmm4;uFreeLocalizer;C:\code\other\kdl;c:\code\other\ics8\source;c:\code\other\GifImage;c:\code\other\DelphiZLib; c:\code\other\regexp\Source;c:\code\other\jcl\source\windows;c:\code\other\jcl\source\include;c:\code\other\jcl\source\common -U"c:\program files (x86)\embarcadero\studio\20.0\Lib\Debug";"c:\program files (x86)\embarcadero\studio\20.0\lib\Win32\release";"c:\program files (x86)\embarcadero\studio\20.0\Imports"; C:\Users\Public\Documents\Embarcadero\Studio\20.0\Dcp;"c:\program files (x86)\embarcadero\studio\20.0\include";Presbylutheran;C:\code\other\compiled; C:\code\other\fastmm4;uFreeLocalizer;C:\code\other\kdl;c:\code\other\ics8\source;c:\code\other\GifImage;c:\code\other\DelphiZLib; c:\code\other\regexp\Source;c:\code\other\jcl\source\windows;c:\code\other\jcl\source\include;c:\code\other\jcl\source\common -K00400000 --description:"HFS ~ HTTP File Server - www.rejetto.com/hfs" -GD -NBC:\Users\Public\Documents\Embarcadero\Studio\20.0\Dcp -NHC:\Users\Public\Documents\Embarcadero\Studio\20.0\hpp\Win32

View File

@ -1,5 +1,5 @@
{
Copyright (C) 2002-2012 Massimo Melina (www.rejetto.com)
Copyright (C) 2002-2020 Massimo Melina (www.rejetto.com)
This file is part of HFS ~ HTTP File Server.
@ -48,7 +48,7 @@ procedure resetLog();
implementation
uses windows, utilLib, trayLib, parserLib, graphics, classes, sysutils, StrUtils,
hslib, comctrls, math, controls, forms, clipbrd, MMsystem, OverbyteicsMD5, OverbyteIcsSha1;
hslib, comctrls, math, controls, forms, clipbrd, MMsystem;
const
HEADER = '<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><style>'
@ -58,7 +58,6 @@ const
var
stopOnMacroRename: boolean; // this ugly global var is used to avoid endless recursion on a renaming rename event. this method won't work on a multithreaded system, but i opted for it because otherwise the changes would have been big.
cachedTpls: TcachedTpls;
flog: ^file;
function macrosLog(textIn, textOut:string; ts:boolean=FALSE):boolean;
var
@ -68,26 +67,13 @@ s:='';
if ts then
s:='<hr>'+dateTimeToStr(now())+CRLF;
s:=s+#13'<dt>'+htmlEncode(textIn)+'</dt><dd>'+htmlEncode(textOut)+'</dd>';
if flog = NIL then
begin
new(flog);
assignFile(flog^, MACROS_LOG_FILE);
reset(flog^, 1);
if IOresult() <> 0 then rewrite(flog^,1)
else seek(flog^,fileSize(flog^));
end;
result:=saveFile(flog^, s)
if sizeOfFile(MACROS_LOG_FILE) = 0 then
s:=HEADER+s;
result:=appendTextFile(MACROS_LOG_FILE, s);
end; // macrosLog
procedure resetLog();
begin
try
closeFile(flog^);
dispose(flog);
flog:=NIL;
except end;
deleteFile(MACROS_LOG_FILE);
end; // resetLog
begin saveFile(MACROS_LOG_FILE, '') end;
function expandLinkedAccounts(account:Paccount):TStringDynArray;
var
@ -175,16 +161,18 @@ var
procedure deprecatedMacro(what:string=''; instead:string='');
begin mainfrm.add2log('WARNING, deprecated macro: '+first(what, name)+nonEmptyConcat(' - Use instead: ',instead), NIL, clRed) end;
procedure unsatisfied(b:boolean=TRUE);
begin
if b then
macroError('cannot be used here')
end;
function satisfied(p:pointer):boolean;
begin
result:=assigned(p);
if not result then
macroError('cannot be used here');
unsatisfied(not result);
end;
procedure unsatisfied(b:boolean=TRUE);
begin if b then macroError('cannot be used here') end;
function parEx(idx:integer; name:string=''; doTrim:boolean=TRUE):string; overload;
var
i: integer;
@ -276,9 +264,9 @@ var
result:=staticVars;
delete(varname,1,length(G_VAR_PREFIX));
end
else if satisfied(md.cd) then
else if assigned(md.cd) then
result:=md.cd.vars
else if satisfied(md.tempVars) then
else if assigned(md.tempVars) then
result:=md.tempVars
else
raise Exception.create('no namespace available');
@ -307,7 +295,7 @@ var
if not satisfied(space) then exit;
i:=space.indexOfName(varname);
if i < 0 then
if value = '' then exit // all is good the way it is
if value = '' then exit(TRUE) // all is good the way it is
else i:=space.add(varname+'='+value)
else
if value > '' then // in case of empty value, there's no need to assign, because we are going to delete it (after we cleared the bound object)
@ -471,7 +459,8 @@ var
vars: Tstrings;
s: string;
begin
if not satisfied(md.cd) then exit;
if not satisfied(md.cd) then
exit;
try
result:=md.cd.conn.request.url;
if pars.count < 2 then exit;
@ -673,14 +662,40 @@ var
procedure inc_(v:integer=+1);
begin
try
setVar(p, intToStr(strToIntDef(getVar(p),0)+v*parI(1,1)));
result:='';
try setVar(p, intToStr(strToIntDef(getVar(p),0)+v*parI(1,1))) except end;
except
end;
end; // inc_
procedure convert();
var
dst, s: string;
c: ansichar;
begin
if sameText(p, 'ansi') and sameText(par(1), 'utf-8') then result:=ansiToUTF8(par(2))
else if sameText(p, 'utf-8') and sameText(par(1), 'ansi') then result:=utf8ToAnsi(par(2))
dst:=par(1);
s:=par(2);
if sameText(p, 'ansi') and sameText(dst, 'utf-8') then
result:=string(ansiToUTF8(ansistring(s)))
else if sameText(p, 'utf-8') then
if sameText(dst, 'ansi') then
result:=utf8ToAnsi(ansistring(s))
else if dst='dec' then
begin
result:='';
for c in UTF8encode(s) do
result:=result+intToStr(ord(c))+',';
setLength(result, length(result)-1);
end
else if dst='hex' then
begin
result:='';
for c in UTF8encode(s) do
result:=result+intToHex(ord(c));
end;
if isFalse(par('macros')) then
result:=noMacrosAllowed(result);
end; // convert
procedure encodeuri();
@ -695,7 +710,7 @@ var
-strToCharset(par('add'))+strToCharset(par('not'));
end;
for i:=1 to length(p) do
if p[i] in cs then
if charInSet(p[i], cs) then
result:=result+p[i]
else
result:=result+'%'+intToHex(ord(p[i]),2)
@ -935,6 +950,37 @@ var
finally free end;
end; // foreach
procedure forLine();
var
lines: TStringList;
line, code, run: string;
i: integer;
begin
code:=macroDequote(par(pars.count-1));
lines:=TStringList.create();
with TfastStringAppend.create do
try
lines.text:= getVar(par('var'));
for line in lines do
begin
i:=pos('=',line);
if i > 0 then
begin
setVar('line-key', Copy(line, 1, i-1));
setVar('line-value', Copy(line, i+1, MAXINT));
end;
setVar('line', line);
run:=code;
applyMacrosAndSymbols(run, cbMacros, cbData);
append(run);
end;
result:=reset();
finally
Free;
lines.Free;
end;
end; //forLine
procedure for_();
var
b, e, i, d: integer;
@ -1058,6 +1104,7 @@ var
procedure load(fn:string; varname:string='');
var
from, size: int64;
s: ansistring;
begin
result:='';
from:=parI('from', 0);
@ -1076,11 +1123,17 @@ var
try result:=httpGet(fn, from, size)
except result:='' end
else
result:=loadFile(uri2diskMaybe(fn), from, size);
begin
s:=loadFile(uri2diskMaybe(fn), from, size);
result:=UTF8ToString(s);
if result = '' then
result:=s;
end;
if varname = '' then
begin
if anyCharIn('/\',fn) then result:=macroQuote(result);
if anyCharIn('/\',fn) then
result:=macroQuote(result);
exit;
end;
if ansiStartsStr(ENCODED_TABLE_HEADER, result) then
@ -1120,7 +1173,7 @@ var
if not satisfied(space) then exit;
i:=space.indexOfName(s);
if i < 0 then exit; // this var doesn't exit. won't write.
if i < 0 then exit; // this var doesn't exit. don't write.
encode:=FALSE;
// if this is used as table, and has newlines, we must encode it to preserve associations
h:=space.objects[i] as THashedStringList;
@ -1143,7 +1196,7 @@ var
finally free end;
end;
// now we have in 's' the content to be saved
spaceIf(saveFile(uri2diskMaybeFolder(p), s, name='append'));
spaceIf(saveTextFile(uri2diskMaybeFolder(p), s, name='append'));
end; // save
procedure replace();
@ -1179,19 +1232,19 @@ var
'information=64'
);
var
i, j, code: integer;
code: integer;
decode: TStringDynArray;
s: string;
s, d: string;
buttons, icon: boolean;
begin
decode:=split(' ',par(1));
code:=0;
for i:=0 to length(decode)-1 do
for j:=1 to length(STR2CODE) do
for d in decode do
for s in STR2CODE do
if startsStr(d+'=', s) then
begin
s:=STR2CODE[j];
if ansiStartsStr(decode[i], s) then
inc(code, strToIntDef(substr(s, 1+pos('=',s)), 0));
inc(code, strToIntDef(substr(s, 2+d.length), 0));
Break
end;
buttons:=code AND 15 > 0;
icon:=code SHR 4 > 0;
@ -1321,19 +1374,20 @@ var
if not satisfied(space) then exit;
// set the table variable as text
v:=par(1);
space.values[p]:=nonEmptyConcat('', space.values[p], CRLF)+v;
// access the table object
i:=space.indexOfName(p);
h:=space.objects[i] as THashedStringList;
if h = NIL then
if i < 0 then
begin
h:=ThashedStringList.create();
space.objects[i]:=h;
end;
space.AddPair(p, v, h);
end
else
h:=space.objects[i] as THashedStringList;
// fill the object
k:=chop('=',v);
v:=macroDequote(v);
h.values[k]:=v;
space.values[p]:=h.text;
end; // setTable
procedure disconnect();
@ -1426,7 +1480,8 @@ var
exit;
end;
a:=findEnabledLinkedAccount(a, split(';',s));
if assigned(a) then result:=a.user;
if assigned(a) then
result:=a.user;
end; // memberOf
procedure canArchive(f:Tfile);
@ -1459,7 +1514,7 @@ var
t: Tdatetime;
begin
try
if getFirstChar(v) in ['+','-'] then
if charInSet(getFirstChar(v), ['+','-']) then
t:=now()+strToFloat(v)
else
try t:=maybeUnixTime(strToFloat(v));
@ -1642,7 +1697,7 @@ var
if assigned(md.cd) then
begin
usr:=md.cd.usr;
usr:=md.cd.user;
if name = '%host%' then
result:=getSafeHost(md.cd)
else if name = '%ip%' then
@ -1797,10 +1852,7 @@ try
end;
if not mainfrm.enableMacrosChk.checked then
begin
result:=fullMacro;
exit;
end;
exit(fullMacro);
if pars.count = 0 then exit;
// extract first parameter as 'name'
@ -1889,9 +1941,15 @@ try
disconnect();
if name = 'stop server' then
begin
stopServer();
exit('');
end;
if name = 'start server' then
begin
startServer();
exit('');
end;
if name = 'focus' then
@ -1908,10 +1966,7 @@ try
begin
try
if isFalse(parEx('if')) then
begin
result:='';
exit;
end;
exit('');
except end;
result:=md.cd.disconnectReason; // return the previous state
if pars.count > 0 then md.cd.disconnectReason:=p;
@ -1946,13 +2001,19 @@ try
result:=jsEncode(p, first(par(1),'''"'));
if name = 'base64' then
result:=base64encode(p);
result:=string(base64encode(UTF8encode(p)));
if name = 'base64decode' then
result:=base64decode(p);
begin
result:=utf8ToString(base64decode(ansistring(p)));
if isFalse(par('macros')) then
result:=noMacrosAllowed(result);
end;
if name = 'md5' then
result:=strMD5(p);
if name = 'sha1' then
result:=SHA1toHex(sha1OfStr(p));
result:=strSHA1(p);
if name = 'sha256' then
result:=strSHA256(p);
if name = 'vfs select' then
if pars.count = 0 then
@ -2025,7 +2086,7 @@ try
encodeuri();
if name = 'decodeuri' then
result:=decodeURL(p);
result:=noMacrosAllowed(decodeURL(ansistring(p)));
if name = 'set cfg' then
trueIf(mainfrm.setcfg(p));
@ -2101,7 +2162,7 @@ try
if name = 'header' then
if satisfied(md.cd) then
try result:=noMacrosAllowed(md.cd.conn.getHeader(p)) except end;
try result:=noMacrosAllowed(md.cd.conn.getHeader(ansistring(p))) except end;
if name = 'urlvar' then
result:=urlvar(p);
@ -2233,7 +2294,8 @@ try
if name = 'mime' then
begin
result:='';
if satisfied(md.cd) then md.cd.conn.reply.contentType:=p;
if satisfied(md.cd) then
md.cd.conn.reply.contentType:=ansistring(p);
end;
if name = 'calc' then
@ -2292,22 +2354,22 @@ try
result:='';
// macro 'mime' should be used for content-type, but this test will save precious time to those who will be fooled by the presence this macro
if ansiStartsText('Content-Type:', p) then
md.cd.conn.reply.contentType:=trim(substr(p, ':'))
md.cd.conn.reply.contentType:=ansistring(trim(substr(p, ':')))
else if ansiStartsText('Location:', p) then
with md.cd.conn.reply do
begin
mode:=HRM_REDIRECT;
url:=trim(substr(p, ':'))
url:=UTF8encode(trim(substr(p, ':')))
end
else
md.cd.conn.addHeader(p, isTrue(par('overwrite',true,'1')));
md.cd.conn.addHeader(ansistring(p), isTrue(par('overwrite',true,'1')));
end;
if name = 'remove header' then
if satisfied(md.cd) then
begin
result:='';
md.cd.conn.removeHeader(p);
md.cd.conn.removeHeader(ansistring(p));
end;
if name = 'get ini' then
@ -2441,8 +2503,12 @@ try
minOrMax();
if stringExists(name, ['if','if not']) then
if isFalse(p) xor (length(name) > 2) then result:=macroDequote(par(2))
begin
try p:=getVar(parEx('var'));
except end;
if isTrue(p) xor (length(name) = 2) then result:=macroDequote(par(2))
else result:=macroDequote(par(1));
end;
if stringExists(name, ['=','>','>=','<','<=','<>','!=']) then
trueIf(compare(name, p, par(1)));
@ -2458,6 +2524,9 @@ try
if name = 'cut' then
cut();
if name ='for line' then
forLine();
if pars.count < 3 then exit; // from here, only macros with at least 3 parameters
if name ='for each' then
@ -2480,7 +2549,7 @@ try
if mainfrm.macrosLogChk.checked then
begin
if not fileExists(MACROS_LOG_FILE) then
saveFile(MACROS_LOG_FILE, HEADER);
saveTextFile(MACROS_LOG_FILE, HEADER);
macrosLog(fullMacro, result, md.logTS);
md.logTS:=FALSE;
end;
@ -2571,10 +2640,5 @@ freeAndNIL(eventScripts);
freeAndNIL(defaultAlias);
freeAndNIL(currentCFGhashed);
staticVars.free;
if assigned(flog) then
begin
closeFile(flog^);
dispose(flog);
end;
end.

BIN
shell.gif

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

View File

@ -5,14 +5,9 @@ object shellExtFrm: TshellExtFrm
ClientHeight = 265
ClientWidth = 388
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
ParentFont = True
OldCreateOrder = False
Position = poDesktopCenter
OnCreate = FormCreate
PixelsPerInch = 96
TextHeight = 13
object Image1: TImage
@ -22,6 +17,199 @@ object shellExtFrm: TshellExtFrm
Height = 169
Align = alTop
AutoSize = True
Picture.Data = {
0954474946496D6167654749463839618301A900B300000000000033660066CC
3333663333996600006666666699CC99999999CCFFCC9933CCCC99CCCCCCFFCC
99FFFFFF00000021F904000000FF002C000000008301A9008300000000336600
66CC3333663333996600006666666699CC99999999CCFFCC9933CCCC99CCCCCC
FFCC99FFFFFF00000004FFD0C949ABBD38EBCDBBFF60288E64699E68AAAE2CC8
B4702CCF746DDF789E31C7612C08C68241D4198FC8A472C9641D180647742A7D
35AFD8AC76CBD5202CC5CBB74B2E9BCFE8120331B03C31E3B47C9E6C140080C3
A441903400087778091C767800010B040B512E560D7A1206840E050167446B6D
156F069E56551F0D8D74A5A6210D940894900E0D03097C7E7D1BAD15B2B591AF
939284B8BB945D999A6EA01506A0AF0503AB0E0A87B17D0D5699B7067ACF88B1
B0AEB0D900C1A7E24BBCAE8BDCBF02859113417A86E016B80A07F412F6B6F4F6
C245C49C2F9E3E494A862E40B00602F82C8065079B3A0AB8FCA8C3F750E2B88B
756875E3E64A50BC5A1EFF132D22C0009DC63DB42635B8E46A2225952CB90CF3
47E1CD056428FD1488252891255FB45E859305EF124267BE7A625C9AC3CE4166
2C7F9DC410D19CA20521C399DBEAB41B14A01DB55E99497342A7805670CED2C9
06A82205EA7E719CB510AC1445DDEC32DD2BA36B4EB85BF3D63AA970A40659DF
F2DC43402B31BB2C64D914C3A036F04ABCCE443A3BD0D0595C939815B054702D
B068BEA85B08BD45AB00E7A03133542DCC60A7EC4BB65D45FD987BA5CC9992FF
85A250B928A16C060C3734645030623CC9FD70443E35B575128ED77634D053AC
3CC2CA95EA1C14B1EBEAF2B92103DF54D3181104F0935527E1FBBAFDFBF8AB39
88CC9EC21A0401C11704FF44F3A1728777F825A8E029D59055D604FF91B5E084
1456B88183EB59A8E1861C5E886126C1B523E088027668E2897C7D08627F0E04
81218028C62863292ABEC7621C167C41CA8C3CF6A8458D0FE25801809EF868E4
914A0019A2045F903822005078501592543655608A2A2ED9628B018816C0975F
0220859457B256E575F0C425C83B7734A7DD1F8140534848575DE9111ED81CA2
C79D082E51A3964D8229680062EE785899049E695D2ABD30EA946DF571C55050
880696E8A1139CC62444B1A9F721A05B8251A8746B3A030D51E030A7D59A45D5
A6A7A2A7AC360132E870A49049160D46205EF068F54B7A1001EBE98B376EA940
0112A8C3C0A8CEB9D9D2FFAD3C39646667E5750A6B1A3F1158DB4BAC0C60AB47
7DEE41E74825E9F56681FBFCF669B15F1480AC000708B0EC9896ED541456CDC9
359434944A17EEB564F8655E77D2211055BFBAA274555697E2D2A61FD60EEB20
A86320EBC097F336F26B5B56110098BE89D6E7F06300CFA14052BE6A84585C41
CD45157875CA16546FD208FB6396EC62C8EC2F9A6586173D9D7D5C2B4F600156
B21C2787252B05AEE554C96B1017023349366B97D95AE9F2B3EE900E1CE2F521
F41A672A00C9F1EA9AAA8299CAD9213EE1E1ECD101CBE9D81F8A396D07776EFF
6B69C71DB96D66A67AC2A38DBAC472BD81C695967014DC8C2F88F39040220E43
366F376EB9758F1317D0FFE69C1B7AF9E700670EFAE8A45F207AE9A8937EFA3D
0AB4AE40EAB0875E3805AF378040030DBC1EFBEE546E9DE902402C0BBCEBAEF3
6E7C8CBEDFB3A998B72CC03CA61D4C9985F4851D7F46F57324EF8C2B410080FB
F7B83B2F35995C254E3E7DD5611F3DA2D29F6F06F56D2685879A725A0608B852
1E52D1CB17A89F86F6B55B1603C0F73DF1256C7CED5B02F50CE3BE0D3DC35A49
FB18B796B616A148A503A2A144D264D63F06CA0180AE0084F708D800032A034F
7D43C4D862221545B88A6CE7B8C3016438B68F7483551E13C9426448C36F0C45
29BDAA1EDA0087881772267E7C108DD9F034C40978A46C0328D516A6741EC230
C46556C1554B3A500E22FFA62A87460CA2617C182CF220318A7938D009BFA8A9
14CC4E79D30802094BC8BCF3F8E41DE72044395AC8AF2CC62255B1595CB3B082
C7BAFC211681AC08B5F2D8B18549CB5F528846471CB2C8DAE8A26946BB850E0B
A2372350716812C8163CD8F18A6FD5EF3058DC434268E69C91602657A164856D
E0624140D6453758E9E407DEB83D388D9080269C1963E8922DBB29875FBCEA63
51EC568061F28D2835F3DBB9B0C2B63A61465676701334A5734D0F820C2293BA
66D5143895F3CCC52F6129D8C1ACC6C15BF4E4954419D712556835B924936F1D
71660354C0CB00CA9184C1640BC2B2C90A4ADD5388C8D462BDF4794C3F5A8A8F
BB62200509BACD6E7413FF9E2D5B552167A64B2BDD42A1F708C71EFBF0B18C82
6428A051591F15C6C8F2A8949BCA94683383C2CF89F5A776229C63407139CB44
44628FDC50A234C219D3D0B01036172D6A6358D85342B2D4A999B4854A1882C9
8450CA923A91D66A8C86BD484DCFA4117489D27C61ABD6404D37187493028C0A
4FAA1EC4954B659A2C8F63D5F25DB36735B529ED80C7D7BEF6B58E04A35BD9A4
780FE830F019658BE9D8A2331E6D40749BD481886153A8C3683A6B94853DA263
FB354AB459F09D8B2098167C789EF8857010297CAB4EF036380CEA6FB11E54DB
BDC63859719971B376ED4E558C3102ED75ED6BC0C5033B9590400A15D77A2B38
2E0A7C0B02E5E2C0B909FF822E724D205D123077BAD89DD175B3CB5D13F9D649
24EAAE78EFF3DD4F796EBCE8BDC87733A0A3F4BA1723EB854340DE4B5F53AC17
BCF081D279F7C682EAD6970EFE1DC77DBB342842D1EB3B7D299072033C5DBAB1
6970987DD3FD4E291B79DAE96B7942219FC830E0021B78BF0C6E202ACC97DD95
0423ACAE4059052735DC0E22187A57DBD41E228685FB9A6E6768CC4312999863
CEF498B235941F227698461D8F241B2463554F5E5837EC6EB095C728E82DD331
3E96A6F66FE80C56478F60E363256B3F38F6C51D715990298F7936AB2C24436C
19DA77742A9E789C317705B70DB2AA563AA6442D48AA492E905A065D24DB828D
DDE50078C96B67C23468FFA2055A41D0D245A9DD9CD64053793C73962B6DE87C
85C1CE55E54753336F0D6B0D3DBDAA35FE70AD6212C018A2198D4F3BE8B30006
38D89425DAD0C2443A64EB7C5A7765452BBB64796596A1F4A53C7DA55F15349D
66B8AFCEC286544543ECAEB9C4A7129B0A69CE0ECD3C24DD5F76F1E10DBAA6CD
6967834DA73BB62DFEDD639D59E3302FB7145CB0694CB706D56D60D906DBD326
D6AEB44EDB33D6E6B64F570EB982905F73B2532FD6FEFBC58F06F2B06BA85950
973A431410D24D5ABCF0040AF20617FFAFF1CA5B23C9B573B894DB720942AE71
E4FAB67328DF6FC957EEA7FFE097452C8F391D82E0AD9ADBDC5B43C22F7C64CE
73894928E2E6EDB9D05BFFFE21C389E1C0434F3A0E6A64F41CCD57E950AF01D3
23DE22FCEA37EA670AB17D55746A020F8A59AA41980DB40EBB34A5F023BF98B0
9E0F63E10D7C634F5E137992B84E75837918ECFD157B0DC89E3A464592829292
247F5DFC370CB41147A44E36DDDB11AA0A648C544CCC214F200CC48057024F4A
762C1A67A818D2364DD39F77D99A482BF93216D123816E9C05B1082DCB689BF0
09EF95B8BC9365C52F7E535FF072A1C11CB6327FBEAA8B9CF59F27E9995A2212
229FF98A57BA385C84742658718EDAE84449D852CA92C254B1F0A55D6AF8D4AB
FBF65B6AD7BBE2F5F8854EFAA259B9A03D15BB4CB5012ED0BFEA77FA262D772A
65BA3750E1F4011BC9B0FFC03C0CADD933758C876A171300E5B73193A629FE33
7CEB67575AF407A4D464395145AF2467FEE77D96F3649184352C034930D648F3
213035537F73077E4DB26C1E771933434990D266E06467415357D06454160529
03106DE6247842B5076EB51599E4734012844238844458844678844898843F67
0240C235ED265CEF9637E80161F4D67EFB265B48A458D4E15497F17906212BFB
B6852A830ED5245A63817537D08454773814570BAF670A19F723FBA184745887
76788778588773B85C02C82491D386174072E22088C230877978888898888A88
848678026A382B29C7393CF7028B588996788995D8884CD887680806868889A0
188AA238841210066AD0FF873D908AAAB88A3D207394388AB0188BB2480DBC25
028FE8008F9100BA28162468729F3884067008CC308BC4588C45B7879B787BB9
B88B362101BD683DAF4884C12820030025C6788DD7588AA6D85BA8588A09C000
DFC80307100CCF783CD13884789009D3188C06508DC308057830006B00000310
8C64838DF8A887DA788ADD088EBB4804F1D28A0E20167C573AE72884E94804EB
488FF9258F084036ECF89080B01080908F16798410528BBB748B91300CBA082F
3D400804091E85C73B07198409398F9E5091CB0225D5388FCC708FF0E8221759
93419891FCA88CDA4804BAA88AEA3092FBB73B27092429C98ED34804D5E83C5F
F390C8309336F99402B8FF8D21709366E18D9990003E098E8535641E13796F61
80D5B77932B4460F464FBDF38B28698D3379942D591213093C4CA9902C099574
391338695D1CB993E2E893BA28183FE0858ED47C6B864866C68524D62143D971
15C906FA758FC1E890F7C80671E994755999A628958ED087B5F802BBA88B4540
507F1633CDA754AC56908E839641688F0C098FC2A88E87905F4DC99696599777
C98D9AE991B8388E00A99BE2D233B6F65221834C33136B80A85DA87984B2399B
CA49959A688BB7C800044012D1C90001700004D003D7F90652C550A2E91C2C36
8348D5826792982AD26ED54893CB999EC7D89C53798B0E109DF09900D5799DD5
D9032FD0598A5681FB66FF4145356FD27496EA19A09898911AD901CC2901F469
9DD4699FD969803460716FD823E429A014AA8FFB689BB7079D9C4912060890F0
59A02A3025848824135AA1268A913B89A1195A8A19699FFDE08AC779A2325A84
FE01A21A20849DB803311A8A9F30A3C4C8A29869A0070A0201B012465AA4487A
A44A9AA44CBAA44EDAA450FAA4521AA5543AA5565AA5587AA5565AA22F228CE8
899C4DE9A3B208A436BA03432A059B731B1EB6A66CDAA66EFAA6701AA7723AA7
745AA718B3A35D8A0040D0A349C8A7621A8BB599999C6800F041A8307201769A
A88ABAA88CDAA88ECAA564E1A736E22D2E628FF2B839F3880744528D32F9A7A1
B81FC8D89EB7C83910D9FF3910E3A8A89AAAAABAAA740AA9C00108E809004320
4044003C80D08E41E03C7A3A04D3080473E9A99708AA41CA01383A2B85FA90E0
158C05C8AACCDAA6F2320072FA1008F0ACCDDAA8AE3A13AA19047C4AA8C380A9
5010A6DFAA8EE00AAC9978A1A2DA8786BA92C92A260851128C4AAD6002AF702A
AF6FFAACF24AAF82421206202F2401ADD5CAA6F83A28D74A16BE0A205F830CED
081D3DEAA7DB3AAEE4AA88812AA8EB2905854A36EBBAAC8D4AAF019BAAF6EAAE
F3EAB11BFBAF723AB00EB2397D358F7AEAAD0C1BA692FAB08998A22A8A21C401
9BB04A22CADAAEFEDAB1D09A0003C00EFBAA955C42090B0026425B11FEFA258A
249DEEDAAF15116B44ABFF8DAAF0ACBAE0AF04F05625D1B482E2B33A6B103D3B
2B066130FA2A28C1100424A10A028BA725CBADC8BA1095EA0990891642F08EE1
AA90081B9B76EBB2FAA81FCE5974C690AE9E70B10100AFFDFA048CE1B1817B14
06931003A0B12551B506C31960E2B881ABA1B090B87CE0AEF77AB55C6255945B
9D47DBB14A0BAD01CBB93DBB06FD1AAF2B911087EB619CDB07B1A60E47EBA046
C8989A6A23D08194F4588F7C2A91B7CAB2754BB7C08BB74A68AE7B2BB37D4BB3
178BB360E203D6B9000230B4498BB9576BB893BBB8D29BB3D2CBB42BE103DAF6
B9D32BBA1A5AB50E10BBD5CBAFD059019FCB83CCBB08CF1BB83CD8AF09607782
A20E3F7BBA610B26242BFFBC154ABCE7EA20A06AAC4462A8362B26D5BBBC648B
95D32A05937BBA5B1BAFDF5BC0870BBEA79B004C4BBD0E6CBD12BCB484E0BDD6
1BBA0546BFD57B00072CC2204CADF16BC15FBBC04B0B058292BFFA2BA0FC2BB1
1272BC4C59B32372B3993BB44FF0B3D0FA1AD7CBB80320B990FB25616BBE3D2C
040120B91FFCC0E64B007697004E5BBEE11BBF4BDCC3AF202F3A0C05D4EA63EE
3BB4053CC4461CC12D8CB62F2CA331BC917CAB39911810042CAF45FC0A6E4204
0CECAE84E0C55F52C7463BBF2871BD48CB83623B87192CBE0E60C752CCB47E7C
C7DA18C42CACB871ECB1508CB48D1B0CD24901E4EBC2659C9E67EC0143FA845F
A31B223BAF2BF1C9A28CFFB470ECA6216BC997AC9C992CA4693C02A3CCA6C140
BEAFDCAC545CAF287CA7D439CBBABCCBBC3C2841F02539E9BF65AAA6BD5CCCC6
3CA79478CCCABCCCAA8A0CC08C979CF801593ACD5A4ACDD65CCDD87CCDDA9CCD
529ACCCCFCCDE05CA74F10003027C34B98A38EB71F1C6BB8211BCEEE6CA70450
9D609B8C138BCE10A2CE75BA0D8392B91C0CB0207BBE945C1184FCCEB35C8FF5
19002AC7CAF56CCFC25AA7F2C2C2F3CBCE122DCB170CC9A74BC42CBC0804CDCB
06DD03D549CF32CBD0FE81CF737A000B90005EAC488B7BC86EE2BC13D0CF2A7C
B417BDD11C7D0001C018370DD2FE2BD2F79CCB730AC58A2BB9FC4AC5FC2CC4A1
ECBE0B37BE6246D3BC1CFFCFFE3ACC371ACDF6ECCDD1DAB85A9CBD7C0CC9180C
C1F01AC6FBECC94CFDCAB10BD551BDD0534DD271FA18CE8BD5E0CBC1D4DAD5FF
3CD3F97ACB61FDC9E5DCBFE72CD2541DA7B5CCB9B1E6C37F5DCAD56BD4151DD3
F19AD274FD7575BDAA24A1D376C9D3403AA782ABC589FC1048F9C72E2D0130ED
D5882C0971EA358B8DAA9551BC3B0DD97B1DDA757AA96C83DA893A20C1FCD8A6
8DD6708AA861FD3CACC9DA754AD6661AD2B1EDD3B83DA75032249CFADB6F3ADA
313B0C901DD9C44DA712C724ABBDDC02ABDB18007E0C7DDAD0EDA6775D8AAA79
DD492CDDD36DD6E88CCAE9F93C37FA985FAACA6E04DE392ADECB298FC4CA98F5
18A0794516D9DD89ECADFF9C45623A066BB1263A035A52DD646C930B4184FFDD
22F4F8032A32E09699DEA696DC24AB9478228A033EE1F248B06C3313E44D1C37
58E19900E1CFCBE14408E11D1A84D434E246C8870DDEDB215EE10A3E8A14EE20
0A2E1AC3C00C6B88A6204E4842F003203E84316EE21F82E332CE888EFD20005E
843DBE4306A894492E8F138E0C9423047AD2E14CCEE4847A8382E02D6B22E5B5
2A8FDF400AC8FAD2F3B3E5C340647900E54544E64F20E671CB069660E626AEE0
2D8EA2D00C712ACEE35E63D2650EE489C0E5D7B0100AAEE36A1EB70C401A26BD
E182EE3C4F10E4823EE826FE0C2FFD922F0DAE6D52AB653E6D899E08953EE247
9EE7AEC1E81DDEE9382EFFE422905F5EB322C92DAC2BBEE570CEE297EA038CB1
301D0AE145A48EAEEE4A53BEE82D2EE2947E089408250F090ABF3AE843C6EAAB
CE06B5DAE9667EE6AC1EE8C9EEE3273E0212F992A6EEE001AEE56BBEEC824E0F
376800F470EC37BDE399A0ED8C400F2FBEEAD64EE94FC0B652608DC1480DC1CE
B6C4CEEAC62E04C81EE7E6BEE83311E772EE02BFB5E3051EDED5AEE64AC4E29D
2EE30B212F84BE00E9DE4CC89EEFD69BF0B77EEFF8BEE8A21105F4B8E5B63D91
2411B7ABAEE73D7EEEB85EF0CE8E150F3DBCBDA596D35EE742A8EBB9EE36C77E
E9F41EE6BAFEE930AFE077E02D81AEEF57FE92171FB7ED08216A9707E6AEE4CD
3EE637CEE1443F0CD950FFF2264FDA29CFD3F79D9EDEE2B03FEFDCB3BAF2E08E
8D4E3F0CFFBEDE014F04C0959EEDEE20F5D80E280F24FA8E8F5BFFF47AFDF527
3AEF644F0AED78A2E64CE750EFF66FAF22342E09598FDE1FA0732352DF6818F5
7F0A08564FA121C00637B7F8828F75842FA6CE338FFD8DD7A95CF98F2FA60FD9
F77E5FF7965FC678AFBFE7BDE0C84DF99D7FC99F7F89695FFAA4F8896BAFFAFA
FBF5700E6B9A9FEA2F6EE1775E231E4EE2B34F9BA34FFAAE2FBCB00FEABB7F84
B5EFF03C0EEA0E0BE3C33F9BC7FDFBC06F847031E81F9EEC857EE8615AEE55FE
69581EE1CC8EE6319F07479FE544FF694C2FDFAFEDFC2EEBF632EE1A7E1EEF83
DEE748CFE7855EEE99DEFFE1A08DE88C1EEAAE12EB99AEE7130F014C4E5AEDC5
596FEAFC0743D1E34AF344537565DBD6519761311879017220608CC340101604
8A0F28140E6C4A99A4E9544E9EB72845B19B160CD1E6D3F5054B4663322C7C46
A7D5EB9539653010A915C56166A85BEDB47A97C9ADF25A8212941A40E0D2021C
644B73C3288B246BA4ACB4BCDC783CB93A585A28E834146050F0A190192D3DF0
63F4129C9A017522F28C5208F8ECBC65C484942461009EF82516E93D464E7E59
81B5D1E1C925E53995DD7D2A00185874D2C9D98272CE39C016C7C999369F66C0
1E4D2E1EE978970F51AEB7BFD7BCEF2DD4BF98FF0718A9DF408267F271E896A3
A0097EEE3404841851E248C48515591CC4F7EBC4187B1F1E4E041952E44812C0
4AC210669112C61428CD9084C9F1584C9A356DDEC49953E7CE916A78FE041A54
E850A245CB042B6154E952A64D9D3E851A3102003B}
ExplicitTop = -6
end
object Panel1: TPanel
Left = 0
@ -34,7 +222,7 @@ object shellExtFrm: TshellExtFrm
object Label1: TLabel
Left = 16
Top = 16
Width = 215
Width = 217
Height = 13
Caption = 'Do you want HFS in your shell context menu?'
end

View File

@ -4,7 +4,7 @@ interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls, GIFImage, utilLib;
Dialogs, ExtCtrls, StdCtrls, utilLib, Vcl.Imaging.GIFImg;
type
TshellExtFrm = class(TForm)
@ -13,7 +13,6 @@ type
Label1: TLabel;
Button1: TButton;
Button2: TButton;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
@ -27,14 +26,4 @@ implementation
{$R *.dfm}
procedure TshellExtFrm.FormCreate(Sender: TObject);
var
gif: TGIFImage;
begin
// turbo delphi doesn't allow me to load a gif from the form designer, so i do it run-time
gif:=stringToGif(getRes('shell', 'GIF'));
try image1.picture.assign(gif);
finally gif.free end;
end;
end.

View File

@ -1,15 +1,20 @@
- update doesn't work without 'only 1 instance' (it's the -q)
+ replace shellExtDlg.gif with transparent png (english system)
+ self-test supporting https
+ expiring links
* dismiss regexp lib http://docwiki.embarcadero.com/Libraries/Rio/en/System.RegularExpressions.TRegEx
+ load *.events
+ url auth limited to resource
+ global limit speed for downloads (browsing excluded)
* consider letting comment "protected" files. Can it really cause harm?
* flag to enable lnk files in a folder (disabled by default)
experiment session login in place of http authentication
+ add mkv mime type http://www.rejetto.com/forum/html-templates/online-video-mkv-player/msg1061237/?topicseen#msg1061237
+ sign exe http://www.rejetto.com/forum/hfs-~-http-file-server/'unsafe'/msg1061437/#msg1061437
cache reReplace
- comments are not updated when moving or renaming files http://www.rejetto.com/forum/bug-reports/descript-ion-and-comment-not-cleaned-up-after-moving-file/
* cache reReplace
+ {.calc.} to have a third numeric parameter that becomes 'x' symbol
+ hash&salt passwords
- setInterval > setTimeout
+ target=_blank as an option on links
- an unsaved VFS will be asked twice if a restart is caused by an update
- while renaming a file, CTRL+C/V doesn't work on the text but is handled by the context menu action
+ more macros http://www.rejetto.com/forum/index.php/topic,10631.0.html
- long folder names are overflowing the tree-box http://www.rejetto.com/forum/index.php/topic,10631.0.html
+ {.vfs delete.}
@ -19,13 +24,20 @@ cache reReplace
+ macros missing to cache a folder: {.reply|content=|var=|code=|filename=|mime=.}
- unexpected scripting behavior http://www.rejetto.com/forum/index.php/topic,9728.msg1054517.html#msg1054517
in handleItem() translate only symbols, and run all macros at the end
document: [section|ver=MASK|build=MIN-MAX|template=MASK]
document: {.if|var}
document: {.exec|out|timeout|exitcode.}
document: [+section]
document: {.set item|diff template.}
document: single line diff templates
document: disconnection reason|if=XXX
document: {.add header|overwrite=0.}
document: {.calc| ][ }
document: single line diff templates (file path)
document: {.disconnection reason|if=XXX.}
document: %url%
document: commands returning white space: add folder, save, set account, exec, mkdir, chdir, delete, rename, move copy, set
document: dir, disk free, filetime, file changed, load tpl
document: pipe, base64, base64decode, dir, disk free, filetime, file changed, load tpl, sha256, for line
document {.convert|macros|dec|hex.}
document: new event [login]
+ event to filter logging http://www.rejetto.com/forum/index.php/topic,9784.0.html
- wrong browser http://www.rejetto.com/forum/index.php/topic,9710.0.html
solution:
@ -36,18 +48,14 @@ document: dir, disk free, filetime, file changed, load tpl
+ upload to non-browsable folder
- android doesn't upload http://www.rejetto.com/forum/index.php/topic,9699.0/topicseen.html#msg1054287
- android doesn't work with passwords http://www.rejetto.com/forum/index.php/topic,9575.msg1054029.html#msg1054029
? default tpl: check with IE6
? default tpl: consider css data uri http://www.nczonline.net/blog/2010/07/06/data-uris-make-css-sprites-obsolete/
+ default tpl: support for rawr thumbnails
+ next VFS file format version should be XML-based
+ next VFS file format version should be text (yaml or json)
+ remove the "progress" from "log what", and use [progress|no log] instead
? {.rename.} should update descript.ion
+ folder archive depth limit http://www.rejetto.com/forum/index.php/topic,8546.msg1050027.html#msg1050027
? in getPage() many %symbols% are translated in a way incompatible with {.section.}
? Windows Script Interfaces
? {.image|src=file|width=x|dst=outfile.}
+ replace /~imgXX with ?mode=icon&id=XX
+ user input through {.dialog.}
+ user input through {.dialog.} or similar
+ show missing files in VFS http://www.rejetto.com/forum/index.php/topic,8203.new.html
* {.cache.} should be able to work on a simple variable
+ plugins system http://www.rejetto.com/wiki/index.php/HFS:_plugins_design
@ -61,8 +69,6 @@ document: dir, disk free, filetime, file changed, load tpl
+ log event to filter www.rejetto.com/forum/?topic=7332.0
? integration with mediainfo.dll www.rejetto.com/forum/?topic=7329
+ folder archive log, just as for deletion http://www.rejetto.com/forum/index.php?topic=6904.msg1042974;topicseen#msg1042974
- upload doesn't work on chinese folders with uneven length www.rejetto.com/forum/?topic=5382
- chinese problems since #161 www.rejetto.com/forum/?topic=5344
- AV with RealVNC on hints by mouse hovering www.rejetto.com/forum/?topic=5261
- N-Stalker can locally crash HFS
- AV in #179 http://www.rejetto.com/forum/index.php?topic=5653.msg1033457#msg1033457 www.rejetto.com/forum/?topic=5681
@ -89,7 +95,6 @@ document: dir, disk free, filetime, file changed, load tpl
+ make %list% available in every page
+ support for ALT+F4 with option "Minimize to tray clicking the close button" www.rejetto.com/forum/?topic=6351
+ replace and delete icons http://www.rejetto.com/forum/index.php?topic=6317.msg1038157#msg1038157
+ self-test supporting https
? currently the delete permission is only inside a folder. you can't mark a file or delete the marked folder. is this ok?
+ when a link is protected (no access for this user) it may be displayed as a link to the %item-name%, then 401, and if login is successful provide a redirection
+ change folder/link/generic-file icons (via GUI, without editing the template)

View File

@ -1,5 +0,0 @@
You selected a virtual folder.
Upload is NOT available for virtual folders, only for real folders.
=== How to get a real folder?
Add a folder from your disk, then click on "Real Folder".

View File

@ -1,10 +0,0 @@
1. Add a folder (choose "real folder")
You should now see a RED folder in your virtual file sytem, inside HFS
2. Right click on this folder
3. Properties -> Permissions -> Upload
4. Check on "Anyone"
5. Ok
Now anyone who has access to your HFS server can upload files to you.

View File

@ -1,5 +1,5 @@
{
Copyright (C) 2002-2012 Massimo Melina (www.rejetto.com)
Copyright (C) 2002-2020 Massimo Melina (www.rejetto.com)
This file is part of HFS ~ HTTP File Server.
@ -24,7 +24,7 @@ unit utilLib;
interface
uses
IOUtils, main, hslib, regexpr, types, windows, graphics, dialogs, registry, classes, dateUtils, gifimage,
IOUtils, main, hslib, regexpr, types, windows, graphics, dialogs, registry, classes, dateUtils, Vcl.Imaging.GIFImg,
shlobj, shellapi, activex, comobj, strutils, forms, stdctrls, controls, psAPI, menus, math,
longinputDlg, OverbyteIcsWSocket, OverbyteIcshttpProt, comCtrls, iniFiles, richedit, sysutils, classesLib{, fastmm4};
@ -44,6 +44,7 @@ type
TnameExistsFun = function(user:string):boolean;
procedure doNothing(); inline; // useful for readability
function httpsCanWork():boolean;
function accountExists(user:string; evenGroups:boolean=FALSE):boolean;
function getAccount(user:string; evenGroups:boolean=FALSE):Paccount;
function nodeToFile(n:TtreeNode):Tfile;
@ -82,11 +83,10 @@ function smartsize(size:int64):string;
function httpGet(url:string; from:int64=0; size:int64=-1):string;
function httpGetFile(url, filename:string; tryTimes:integer=1; notify:TdocDataEvent=NIL):boolean;
function httpFileSize(url:string):int64;
function getIPs():TStringDynArray;
function getPossibleAddresses():TstringDynArray;
function whatStatusPanel(statusbar:Tstatusbar; x:integer):integer;
function getExternalAddress(var res:string; provider:Pstring=NIL):boolean;
function checkAddressSyntax(address:string; wildcards:boolean=TRUE):boolean;
function checkAddressSyntax(address:string; mask:boolean=TRUE):boolean;
function inputQueryLong(const caption, msg:string; var value:string; ofs:integer=0):boolean;
procedure purgeVFSaccounts();
function exec(cmd:string; pars:string=''; showCmd:integer=SW_SHOW):boolean;
@ -100,6 +100,7 @@ function compare_(i1,i2:int64):integer; overload;
function compare_(i1,i2:integer):integer; overload;
function msgDlg(msg:string; code:integer=0; title:string=''):integer;
function if_(v:boolean; v1:string; v2:string=''):string; overload; inline;
function if_(v:boolean; v1:ansistring; v2:ansistring=''):ansistring; overload; inline;
function if_(v:boolean; v1:int64; v2:int64=0):int64; overload; inline;
function if_(v:boolean; v1:integer; v2:integer=0):integer; overload; inline;
function if_(v:boolean; v1:Tobject; v2:Tobject=NIL):Tobject; overload; inline;
@ -123,13 +124,14 @@ function createShellLink(linkFN:WideString; destFN:string):boolean;
function readShellLink(linkFN:WideString):string;
function getShellFolder(id:string):string;
function getTempFilename():string;
function saveTempFile(data:ansistring):string;
function saveTempFile(data:ansistring):string; overload;
function saveTempFile(data:string):string; overload;
function fileOrDirExists(fn:string):boolean;
function sizeOfFile(fn:string):int64; overload;
function sizeOfFile(fh:Thandle):int64; overload;
function loadFile(fn:string; from:int64=0; size:int64=-1):ansistring;
function loadTextFile(fn:string):string;
function saveTextFile(fn:string; text:string):boolean;
function saveTextFile(fn:string; text:string; append:boolean=FALSE):boolean;
function saveFile(fn:string; data:ansistring; append:boolean=FALSE):boolean; overload;
function saveFile(var f:file; data:ansistring):boolean; overload;
function moveFile(src, dst:string; op:UINT=FO_MOVE):boolean;
@ -140,6 +142,7 @@ function validFilepath(fn:string; acceptUnits:boolean=TRUE):boolean;
function match(mask, txt:pchar; fullMatch:boolean=TRUE; charsNotWildcard:Tcharset=[]):integer;
function filematch(mask, fn:string):boolean;
function appendFile(fn:string; data:ansistring):boolean;
function appendTextFile(fn:string; text:string):boolean;
function getFilename(var f:file):string;
function filenameToDriveByte(fn:string):byte;
function selectFile(var fn:string; title:string=''; filter:string=''; options:TOpenOptions=[]):boolean;
@ -163,19 +166,19 @@ function replaceString(var ss:TStringDynArray; old, new:string):integer;
function popString(var ss:TstringDynArray):string;
procedure insertString(s:string; idx:integer; var ss:TStringDynArray);
function removeString(var a:TStringDynArray; idx:integer; l:integer=1):boolean; overload;
function removeString(find:string; var a:TStringDynArray):boolean; overload;
function removeString(s:string; var a:TStringDynArray; onlyOnce:boolean=TRUE; ci:boolean=TRUE; keepOrder:boolean=TRUE):boolean; overload;
procedure removeStrings(find:string; var a:TStringDynArray);
procedure toggleString(s:string; var ss:TStringDynArray);
function onlyString(s:string; ss:TStringDynArray):boolean;
function addArray(var dst:TstringDynArray; src:array of string; where:integer=-1; srcOfs:integer=0; srcLn:integer=-1):integer;
function removeArray(var src:TstringDynArray; toRemove:array of string):integer;
function addUniqueArray(var a:TstringDynArray; b:array of string):integer;
procedure uniqueStrings(var a:TstringDynArray);
procedure uniqueStrings(var a:TstringDynArray; ci:Boolean=TRUE);
function idxOf(s:string; a:array of string; isSorted:boolean=FALSE):integer;
function stringExists(s:string; a:array of string; isSorted:boolean=FALSE):boolean;
function listToArray(l:Tstrings):TstringDynArray;
function arrayToList(a:TStringDynArray; list:TstringList=NIL):TstringList;
procedure sortArray(var a:TStringDynArray);
function sortArray(a:TStringDynArray):TStringDynArray;
// convert
function boolToPtr(b:boolean):pointer;
function strToCharset(s:string):Tcharset;
@ -221,6 +224,7 @@ function first(a,b:integer):integer; overload;
function first(a,b:double):double; overload;
function first(a,b:pointer):pointer; overload;
function first(a,b:string):string; overload;
function first(a,b:ansistring):ansistring; overload;
function first(a:array of string):string; overload;
function stripChars(s:string; cs:Tcharset; invert:boolean=FALSE):string;
function isOnlyDigits(s:string):boolean;
@ -231,7 +235,7 @@ function reduceSpaces(s:string; replacement:string=' '; spaces:TcharSet=[]):stri
function replace(var s:string; ss:string; start,upTo:integer):integer;
function countSubstr(ss:string; s:string):integer;
function trim2(s:string; chars:Tcharset):string;
procedure urlToStrings(s:string; sl:Tstrings);
procedure urlToStrings(s:ansistring; sl:Tstrings);
function reCB(expr, subj:string; cb:TreCB; data:pointer=NIL):string;
function reMatch(s, exp:string; mods:string='m'; ofs:integer=1; subexp:PstringDynArray=NIL):integer;
function reReplace(subj, exp, repl:string; mods:string='m'):string;
@ -247,16 +251,36 @@ function escapeNL(s:string):string;
function unescapeNL(s:string):string;
function htmlEncode(s:string):string;
procedure enforceNUL(var s:string);
function strSHA256(s:string):string;
function strSHA1(s:string):string;
function strMD5(s:string):string;
function strToOem(s:string):ansistring;
function strToBytes(s:ansistring):Tbytes;
implementation
uses
clipbrd, JclNTFS, JclWin32, parserLib, newuserpassDlg, winsock, OverbyteicsMD5;
clipbrd, JclNTFS, JclWin32, parserLib, newuserpassDlg, winsock, System.Hash, ansistrings;
var
ipToInt_cache: ThashedStringList;
onlyDotsRE: TRegExpr;
function strSHA256(s:string):string;
begin result:=THashSHA2.GetHashString(UTF8encode(s)) end;
function strSHA1(s:string):string;
begin result:=THashSHA1.GetHashString(UTF8encode(s)) end;
function strMD5(s:string):string;
begin result:=THashMD5.GetHashString(UTF8encode(s)) end;
function strToOem(s:string):ansistring;
begin
setLength(result, length(s));
CharToOemBuff(pWideChar(s), pAnsiChar(result), length(s));
end; // strToOem
// method TregExpr.ReplaceEx does the same thing, but doesn't allow the extra data field (sometimes necessary).
// Moreover, here i use the TfastStringAppend that will give us good performance with many replacements.
function reCB(expr, subj:string; cb:TreCB; data:pointer=NIL):string;
@ -617,13 +641,14 @@ if i < 0 then addString(s, ss)
else removeString(ss, i);
end; // toggleString
procedure uniqueStrings(var a:TstringDynArray);
procedure uniqueStrings(var a:TstringDynArray; ci:Boolean=TRUE);
var
i, j: integer;
begin
for i:=length(a)-1 downto 1 do
for j:=i-1 downto 0 do
if ansiCompareText(a[i], a[j]) = 0 then
if ci and SameText(a[i], a[j])
or not ci and (a[i] = a[j]) then
begin
removeString(a, i);
break;
@ -644,10 +669,6 @@ begin
until false;
end; // removeStrings
// remove first instance of the specified string
function removeString(find:string; var a:TStringDynArray):boolean;
begin result:=removeString(a, idxOf(find,a)) end;
function removeArray(var src:TstringDynArray; toRemove:array of string):integer;
var
i, l, ofs: integer;
@ -721,6 +742,35 @@ while idx+l < length(a) do
setLength(a, idx);
end; // removestring
function removeString(s:string; var a:TStringDynArray; onlyOnce:boolean=TRUE; ci:boolean=TRUE; keepOrder:boolean=TRUE):boolean; overload;
var i, lessen:integer;
begin
result:=FALSE;
if a = NIL then
exit;
lessen:=0;
try
for i:=length(a)-1 to 0 do
if ci and sameText(a[i], s)
or not ci and (a[i]=s) then
begin
result:=TRUE;
if keepOrder then
removeString(a, i)
else
begin
inc(lessen);
a[i]:=a[length(a)-lessen];
end;
if onlyOnce then
exit;
end;
finally
if lessen > 0 then
setLength(a, length(a)-lessen);
end;
end;
function dotted(i:int64):string;
begin
result:=intToStr(i);
@ -749,7 +799,7 @@ setLength(ansi, l);
move(p^, ansi[1], l);
UnlockResource(h2);
FreeResource(h2);
result:=ansi;
result:=UTF8toString(ansi);
end; // getRes
function compare_(i1,i2:int64):integer; overload;
@ -929,12 +979,7 @@ result:=(fn > '')
end;
function loadTextFile(fn:string):string;
begin
try result:=IOUtils.TFile.ReadAllText(fn)
except result:='' end;
try result:=UTF8decode(result)
except end;
end;
begin result:=UTF8toString(loadfile(fn)) end;
function loadFile(fn:string; from:int64=0; size:int64=-1):ansistring;
var
@ -1023,15 +1068,21 @@ try
except end;
end; // saveFile
function saveTextFile(fn:string; text:string):boolean;
begin result:=saveFile(fn, UTF8encode(text)) end;
function saveTextFile(fn:string; text:string; append:boolean=FALSE):boolean;
begin result:=saveFile(fn, UTF8encode(text), append) end;
function appendFile(fn:string; data:ansistring):boolean;
begin result:=saveFile(fn, data, TRUE) end;
function appendTextFile(fn:string; text:string):boolean;
begin result:=saveTextFile(fn, text, TRUE) end;
function getTempFilename():string;
begin result:=TPath.GetRandomFileName() end;
function saveTempFile(data:string):string;
begin result:=saveTempFile(UTF8encode(data)) end;
function saveTempFile(data:ansistring):string;
begin
result:=getTempFilename();
@ -1189,14 +1240,8 @@ end;
// exec but does not wait for the process to end
function execNew(cmd:string):boolean;
var
si: TStartupInfo;
pi: TProcessInformation;
begin
fillchar(si, sizeOf(si), 0);
fillchar(pi, sizeOf(pi), 0);
si.cb:=sizeOf(si);
result:=createProcess(NIL,pchar(cmd),NIL,NIL,FALSE,0,NIL,NIL,si,pi)
result:=32 < ShellExecute(0, nil, 'cmd.exe', pchar('/C '+cmd), nil, SW_SHOW);
end; // execNew
function addArray(var dst:TstringDynArray; src:array of string; where:integer=-1; srcOfs:integer=0; srcLn:integer=-1):integer;
@ -1264,6 +1309,9 @@ begin if v then result:=v1 else result:=v2 end;
function if_(v:boolean; v1, v2:string):string;
begin if v then result:=v1 else result:=v2 end;
function if_(v:boolean; v1:ansistring; v2:ansistring=''):ansistring; overload; inline;
begin if v then result:=v1 else result:=v2 end;
function if_(v:boolean; v1,v2:int64):int64;
begin if v then result:=v1 else result:=v2 end;
@ -1351,56 +1399,72 @@ while mask > '' do
result:=result xor odd(invert);
end; // filematch
function checkAddressSyntax(address:string; wildcards:boolean=TRUE):boolean;
function checkAddressSyntax(address:string; mask:boolean=TRUE):boolean;
var
a1, a2: string;
i, dots, lastDot: integer;
wildcardsMet: boolean;
function validNumber():boolean;
begin result:=strToIntDef(substr(a1,lastDot+1,i-1), 0) <= 255 end;
sf: TSocketFamily;
begin
if not mask then
exit(WSocketIsIPEx(address, sf));
result:=FALSE;
if address = '' then exit;
while (address > '') and (address[1] = '\') do delete(address,1,1);
while (address > '') and (address[1] = '\') do
delete(address,1,1);
while address > '' do
begin
a2:=chop(';', address);
if sameText(a2, 'lan') then continue;
if sameText(a2, 'lan') then
continue;
a1:=chop('-', a2);
if a2 > '' then
if not checkAddressSyntax(a1, FALSE)
or not checkAddressSyntax(a2, FALSE) then
exit;
wildcardsMet:=FALSE;
dots:=0;
lastDot:=0;
for i:=1 to length(a1) do
case a1[i] of
'.':
begin
if not validNumber() then exit;
lastDot:=i;
inc(dots);
if reMatch(a1, '^[?*a-f0-9\.:]+$', '!') = 0 then
exit;
end;
'0'..'9': ;
'?','*' : if wildcards then wildcardsMet:=TRUE else exit;
else exit;
end;
if (dots > 3) or not wildcardsMet and (dots <> 3) then exit;
end;
result:=validNumber();
result:=TRUE;
end; // checkAddressSyntax
function ipv6hex(ip:TIcsIPv6Address):string;
begin
setLength(result, 4*8);
binToHex(@ip.words[0], pchar(result), sizeOf(ip))
end;
function addressMatch(mask, address:string):boolean;
var
invert: boolean;
part1, part2: string;
addrInt: dword;
ofs, i, bits: integer;
masks: TStringDynArray;
mode: (SINGLE, BITMASK, RANGE);
addr4: dword;
addr6: string;
bits: integer;
a: TStringDynArray;
function ipv6fix(s:string):string;
var
ok: boolean;
r: TIcsIPv6Address;
begin
if length(s) = 39 then
exit(replaceStr(s,':',''));
r:=wsocketStrToipv6(s, ok);
if ok then
exit(ipv6hex(r));
exit('');
end;
function ipv6range():boolean;
var
min, max: string;
begin
min:=ipv6fix(a[0]);
if min = ''then
exit(FALSE);
max:=ipv6fix(a[1]);
if max = '' then
exit(FALSE);
result:=(min <= addr6) and (max >= addr6)
end; // ipv6range
begin
result:=FALSE;
invert:=FALSE;
@ -1409,39 +1473,45 @@ while (mask > '') and (mask[1] = '\') do
delete(mask,1,1);
invert:=not invert;
end;
addrInt:=ipToInt(address);
masks:=split(';',mask);
ofs:=1;
while not result and (ofs <= length(mask)) do
addr6:=ipv6fix(address);
addr4:=0;
if addr6 = '' then
addr4:=ipToInt(address);
for mask in split(';',mask) do
begin
mode:=SINGLE;
part1:=trim(substr(mask, ofs, max(0,posEx(';', mask, ofs)-1) ));
inc(ofs, length(part1)+1);
if sameText(part1, 'lan') then
if result then
break;
if sameText(mask, 'lan') then
begin
result:=isLocalIP(address);
continue;
end;
i:=lastDelimiter('-/', part1);
if i > 0 then
// range?
a:=split('-', mask);
if length(a) = 2 then
begin
if part1[i] = '-' then mode:=RANGE
else mode:=BITMASK;
part2:=part1;
part1:=chop(i, 1, part2);
if addr6 > '' then
result:=ipv6range()
else
result:=(pos(':',a[0]) = 0) and (addr4 >= ipToInt(a[0])) and (addr4 <= ipToInt(a[1]));
continue;
end;
case mode of
SINGLE: result:=match( pchar(part1), pchar(address) ) > 0;
RANGE: result:=(addrInt >= ipToInt(part1)) and (addrInt <= ipToInt(part2));
BITMASK:
// bitmask? ipv4 only
a:=split('/', mask);
if (addr6='') and (length(a) = 2) then
begin
try
bits:=32-strToInt(part2);
result:=addrInt shr bits = ipToInt(part1) shr bits;
except end;
bits:=32-strToInt(a[1]);
result:=addr4 shr bits = ipToInt(a[0]) shr bits;
except
end;
continue;
end;
// single
result:=match( pchar(mask), pchar(address) ) > 0;
end;
result:=result xor invert;
end; // addressMatch
@ -1608,71 +1678,103 @@ result:=inputQueryLongdlg.ShowModal() = mrOk;
if result then value:=inputQueryLongdlg.inputBox.Text;
end; // inputQueryLong
function dllIsPresent(name:string):boolean;
var h: HMODULE;
begin
h:=LoadLibrary(@name);
result:= h<>0;
FreeLibrary(h);
end;
function httpsCanWork():boolean;
const
files: array of string = ['libcrypto-1_1.dll','libssl-1_1.dll'];
baseUrl = 'http://rejetto.com/hfs/';
// these should be made resourcestring but then a runtime error is raised
MSG = 'An HTTPS action is required but some files are missing. Download them?';
MSG_OK = 'Download completed';
MSG_KO = 'Download failed';
var
s: string;
missing: TStringDynArray;
begin
missing:=NIL;
for s in files do
if not FileExists(s) and not dllIsPresent(s) then
addString(s, missing);
if missing=NIL then
exit(TRUE);
if msgDlg(MSG, MB_OKCANCEL+MB_ICONQUESTION) <> MROK then
exit(FALSE);
for s in missing do
if not httpGetFile(baseUrl+s, s, 2, mainfrm.statusBarHttpGetUpdate) then
begin
msgDlg(MSG_KO, MB_ICONERROR);
exit(FALSE);
end;
mainfrm.setStatusBarText(MSG_OK);
result:=TRUE;
end; // httpsCanWork
function httpGet(url:string; from:int64=0; size:int64=-1):string;
var
http: THttpCli;
reply: Tstringstream;
begin
if size = 0 then
begin
result:='';
exit;
end;
exit('');
reply:=TStringStream.Create('');
with ThttpClient.createURL(url) do
try
http:=Thttpcli.create(NIL);
try
http.URL:=url;
http.followRelocation:=TRUE;
http.rcvdStream:=reply;
http.agent:=HFS_HTTP_AGENT;
rcvdStream:=reply;
if (from <> 0) or (size > 0) then
http.contentRangeBegin:=intToStr(from);
contentRangeBegin:=intToStr(from);
if size > 0 then
http.contentRangeEnd:=intToStr(from+size-1);
http.get();
contentRangeEnd:=intToStr(from+size-1);
get();
result:=reply.dataString;
finally http.free end
finally reply.free end
if sameText('utf-8', reGet(ContentType, '; *charset=(.+) *($|;)')) then
Result:=UTF8ToString(result);
finally
reply.free;
Free;
end
end; // httpGet
function httpFileSize(url:string):int64;
var
http: THttpCli;
begin
http:=Thttpcli.create(NIL);
with ThttpClient.createURL(url) do
try
http.URL:=url;
http.Agent:=HFS_HTTP_AGENT;
try
http.head();
result:=http.contentLength
except result:=-1 end;
finally http.free end
head();
result:=contentLength
except result:=-1
end;
finally free
end;
end; // httpFileSize
function httpGetFile(url, filename:string; tryTimes:integer=1; notify:TdocDataEvent=NIL):boolean;
var
http: THttpCli;
reply: Tfilestream;
supposed: integer;
reply: Tfilestream;
begin
reply:=TfileStream.Create(filename, fmCreate);
with ThttpClient.createURL(url) do
try
http:=Thttpcli.create(NIL);
try
http.URL:=url;
http.RcvdStream:=reply;
http.Agent:=HFS_HTTP_AGENT;
http.OnDocData:=notify;
rcvdStream:=reply;
onDocData:=notify;
result:=TRUE;
try http.get()
except result:=FALSE end;
supposed:=http.ContentLength;
finally http.free end
finally reply.free end;
try get()
except result:=FALSE
end;
supposed:=ContentLength;
finally
reply.free;
free;
end;
result:= result and (sizeOfFile(filename)=supposed);
if not result then deleteFile(filename);
if not result then
deleteFile(filename);
if not result and (tryTimes > 1) then
result:=httpGetFile(url, filename, tryTimes-1, notify);
@ -1730,10 +1832,12 @@ s:=trim(s);
if s = '' then exit;
// try to determine length
i:=1;
while (i < length(s)) and (i < 15) and charInSet(s[i+1], ['0'..'9','.']) do inc(i);
while (i > 0) and (s[i] = '.') do dec(i);
while (i < length(s)) and (i < 15) and charInSet(s[i+1], ['0'..'9','.']) do
inc(i);
while (i > 0) and (s[i] = '.') do
dec(i);
setLength(s,i);
result:= checkAddressSyntax(s) and not HSlib.isLocalIP(s);
result:= checkAddressSyntax(s, FALSE) and not HSlib.isLocalIP(s);
if not result then exit;
if (res <> s) and mainFrm.logOtherEventsChk.checked then
mainFrm.add2log('New external address: '+s+' via '+hostFromURL(addr));
@ -1753,17 +1857,13 @@ while (x > x1) and (result < statusbar.Panels.Count-1) do
end;
end; // whatStatusPanel
function getIPs():TStringDynArray;
begin
try result:=listToArray(localIPlist) except result:=NIL end;
end;
function getPossibleAddresses():TstringDynArray;
begin // next best
result:=toSA([defaultIP, dyndns.host]);
addArray(result, customIPs);
addString(externalIP, result);
addArray(result, getIPs());
try addArray(result, listToArray(localIPlist(sfAny)))
except end;
removeStrings('', result);
uniqueStrings(result);
end; // getPossibleAddresses
@ -1932,7 +2032,7 @@ begin
i:=ipToInt_cache.Add(ip);
result:=dword(ipToInt_cache.Objects[i]);
if result <> 0 then exit;
result:=WSocket_ntohl(WSocket_inet_addr(pchar(ip)));
result:=WSocket_ntohl(WSocket_inet_addr(ansistring(ip)));
ipToInt_cache.Objects[i]:=Tobject(result);
end; // ipToInt
@ -2016,7 +2116,8 @@ if to_ = NIL then
end;
l:=to_-from+1;
setLength(result, l);
if l > 0 then strLcopy(@result[1], from, l);
if l > 0 then
strLcopy(@result[1], from, l);
end; // getStr
function poss(chars:TcharSet; s:string; ofs:integer=1):integer;
@ -2100,6 +2201,9 @@ end; // first
function first(a,b:string):string;
begin if a = '' then result:=b else result:=a end;
function first(a,b:ansistring):ansistring;
begin if a = '' then result:=b else result:=a end;
function first(a,b:integer):integer;
begin if a = 0 then result:=b else result:=a end;
@ -2116,7 +2220,7 @@ const
var
sa : TSecurityAttributes;
ReadPipe,WritePipe : THandle;
start : TStartUpInfoA;
start : TStartUpInfoW;
ProcessInfo : TProcessInformation;
Buffer : Pansichar;
TotalBytesRead,
@ -2147,7 +2251,7 @@ else
timeout:=now()+timeout/SECONDS;
// Create a Console Child Process with redirected input and output
try
if CreateProcessA(nil, PansiChar(ansistring(DosApp)), @sa, @sa, true, CREATE_NO_WINDOW or NORMAL_PRIORITY_CLASS, nil, nil, start, ProcessInfo) then
if CreateProcess(nil, PChar(dosApp), @sa, @sa, true, CREATE_NO_WINDOW or NORMAL_PRIORITY_CLASS, nil, nil, start, ProcessInfo) then
repeat
result:=TRUE;
// wait for end of child process
@ -2157,16 +2261,22 @@ try
// so that the pipe is not blocked by an overflow. New information
// can be written from the console app to the pipe only if there is
// enough buffer space.
if not PeekNamedPipe(ReadPipe, @Buffer[TotalBytesRead], ReadBuffer,
@BytesRead, @TotalBytesAvail, @BytesLeftThisMessage ) then
break
else if BytesRead > 0 then
ReadFile(ReadPipe, Buffer[TotalBytesRead], BytesRead, BytesRead, nil );
if not PeekNamedPipe(ReadPipe, @Buffer[TotalBytesRead], ReadBuffer, @BytesRead, @TotalBytesAvail, @BytesLeftThisMessage )
or (BytesRead > 0) and not ReadFile(ReadPipe, Buffer[TotalBytesRead], BytesRead, BytesRead, nil ) then
break;
inc(TotalBytesRead, BytesRead);
until (Apprunning <> WAIT_TIMEOUT) or (now() >= timeout);
if IsTextUnicode(Buffer, TotalBytesRead, NIL) then
begin
Pchar(@Buffer[TotalBytesRead])^:= #0;
output:=pchar(Buffer)
end
else
begin
Buffer[TotalBytesRead]:= #0;
OemToCharA(PansiChar(Buffer),Buffer);
output:=strPas(Buffer);
OemToCharA(Buffer,Buffer);
output:=string(ansistrings.strPas(Buffer));
end;
finally
GetExitCodeProcess(ProcessInfo.hProcess, exitcode);
TerminateProcess(ProcessInfo.hProcess, 0);
@ -2398,17 +2508,20 @@ end; // trim2
function boolOnce(var b:boolean):boolean;
begin result:=b; b:=FALSE end;
procedure urlToStrings(s:string; sl:Tstrings);
procedure urlToStrings(s:ansistring; sl:Tstrings);
var
i, l, p: integer;
t: string;
a: ansistring;
begin
i:=1;
l:=length(s);
while i <= l do
begin
p:=posEx('&',s,i);
t:=decodeURL(replaceStr(substr(s,i,if_(p=0,0,p-1)), '+',' ')); // TODO should we instead try to decode utf-8? doing so may affect calls to {.force ansi.} in the template
p:=ansistrings.posEx('&',s,i);
a:=copy(s,i,if_(p=0,length(s),p-i));
a:=ansistrings.replaceStr(a, '+',' ');
t:=decodeURL(a); // TODO should we instead try to decode utf-8? doing so may affect calls to {.force ansi.} in the template
sl.add(t);
if p = 0 then exit;
i:=p+1;
@ -2462,14 +2575,15 @@ var
left, right: real;
leftS, rightS: string;
function getOperate(dir:integer):string;
function getOperand(dir:integer):string;
var
j: integer;
begin
i:=mImp+dir;
repeat
j:=i+dir;
if (j > 0) and (j <= length(s)) and charInSet(s[j], ['0'..'9','.']) then
if (j > 0) and (j <= length(s))
and (charInSet(s[j], ['0'..'9','.','E']) or (j>1) and charInSet(s[j],['+','-']) and (s[j-1]='E')) then
i:=j
else
break;
@ -2478,7 +2592,7 @@ var
swapMem(i, j, sizeOf(i), dir > 0);
j:=j-i+1;
result:=copy(s, i, j);
end; // getOperate
end; // getOperand
begin
repeat
@ -2492,13 +2606,14 @@ begin
ch:=s[i];
v:=0;
case ch of
'*','/','%': v:=5+ofsImp;
'*','/','%','[',']': v:=5+ofsImp;
'+','-': v:=3+ofsImp;
'(': inc(ofsImp, PAR_VAL);
')': dec(ofsImp, PAR_VAL);
end;
if (i = 1) // a starting operator is not an operator
or (s[i-1]='E') // exponential syntax
or (v <= mImpV) // left-to-right precedence
then continue;
// we got a better one, record it
@ -2513,8 +2628,8 @@ begin
exit;
end;
// determine operates
leftS:=getOperate(-1);
rightS:=getOperate(+1);
leftS:=getOperand(-1);
rightS:=getOperand(+1);
left:=StrToFloatDef(trim(leftS), 0);
right:=strToFloat(trim(rightS));
// calculate
@ -2529,6 +2644,8 @@ begin
'%':
if right <> 0 then result:=trunc(left) mod trunc(right)
else raise Exception.create('division by zero');
'[': result:=round(left) shl round(right);
']': result:=round(left) shr round(right);
else raise Exception.create('operator not supported: '+ch);
end;
// replace sub-expression with result
@ -2604,7 +2721,7 @@ accounts[i]:=acc;
result:=@accounts[i];
end; // createAccountOnTheFly
procedure sortArray(var a:TStringDynArray);
function sortArray(a:TStringDynArray):TStringDynArray;
var
i, j, l: integer;
begin
@ -2612,6 +2729,7 @@ l:=length(a);
for i:=0 to l-2 do
for j:=i+1 to l-1 do
swapMem(a[i], a[j], sizeof(a[i]), ansiCompareText(a[i], a[j]) > 0);
result:=a;
end; // sortArray
procedure onlyForExperts(controls:array of Tcontrol);
@ -2825,7 +2943,7 @@ finally
end;
end; // deltree
function str2bytes(s:ansistring):Tbytes;
function strToBytes(s:ansistring):Tbytes;
begin
setLength(result, length(s));
move(s[1], result[0], length(result));
@ -2835,7 +2953,7 @@ function stringToGif(s:ansistring; gif:TgifImage=NIL):TgifImage;
var
ss: Tbytesstream;
begin
ss:=Tbytesstream.create(str2bytes(s));
ss:=Tbytesstream.create(strToBytes(s));
try
if gif = NIL then
gif:=TGIFImage.Create();
@ -2960,6 +3078,8 @@ var
i: integer;
begin
result:=NIL;
if user = '' then
exit;
for i:=0 to length(accounts)-1 do
if sameText(user, accounts[i].user) then
begin

View File

@ -1,4 +1,4 @@
HFS - what's new
HFS - what's new
LEGEND
! very important
@ -9,20 +9,35 @@ AV access violation
VER 2.4
propaganda
New mobile-friendly template
Mobile-friendly template
Unicode support
Encrypted login, and logout
DoS protection
IPv6
/propaganda
+ new default template
+ new login system, session based, with logout
+ IPv6 support
+ DoS protection https://rejetto.com/forum/index.php?topic=13060.msg1065962#msg1065962
+ {.set item|name.}
+ {.get item|icon.}
+ {.set cfg.}
+ {.for line.}
+ {.if|var}
+ cache for jquery and template sections
+ new template commands: base64, base64decode, md5, sha1
+ new template commands: base64, base64decode, md5, sha1, sha256
+ *.diff.tpl in exe's folder
+ default mime-type for mkv
+ 'no list' section flag
+ https client support (not server)
- fixed template handling of section names with both '+' and '=' present
- fixed LNK files to deleted items
- fixed comments files were not updated upon deletion of files
- fixed "requesting" forever with empty cookies http://rejetto.com/forum/index.php?topic=13112.0
- fixed double "Content-Length" header on compressed pages
- fixed log text base color not matching system settings http://rejetto.com/forum/index.php?topic=13233.0
- fixed while renaming a file in the GUI, CTRL+C/V didn't work on the text
- fixed diff tpl logic: an empty section will now override the inherited one
VER 2.3m
propaganda
@ -849,7 +864,7 @@ ver: 1.5 rc5
+ support for persistent connections (HTTP 1.1)
* moved many options to Menu -> "Other options"
* when drag&dropping a folder, the dialog for autoupdate is set foreground
- problems with url-encoding for … Š <20> • — (IE, Opera)
- problems with url-encoding for <EFBFBD> <20> <20> <20> <20> (IE, Opera)
- problems saving a template to registry
- sometimes "check for update" was not working after a failure
- CRITICAL: directory crossing was possible on autoupdating folders
@ -902,7 +917,7 @@ ver: 1.3 beta6
ver: 1.3 beta5
+ "Custom ip", now you can use yourowndomain.com
- autoupdate folders was not applying the "Folders before" setting
- there were problems with url-encoding for blank-space, ø and "
- there were problems with url-encoding for blank-space, <EFBFBD> and "
- some crashes may have been fixed
ver: 1.3 beta4