solved many compilation warnings

This commit is contained in:
Massimo Melina 2020-05-11 16:55:48 +02:00
parent 62bb5f87bb
commit fe1fefbb1f
7 changed files with 201 additions and 158 deletions

View File

@ -39,7 +39,7 @@ type
PcachedIcon = ^TcachedIcon; PcachedIcon = ^TcachedIcon;
TcachedIcon = record TcachedIcon = record
data: ansistring; data: string;
idx: integer; idx: integer;
time: Tdatetime; time: Tdatetime;
end; end;
@ -47,11 +47,11 @@ type
TiconsCache = class TiconsCache = class
n: integer; n: integer;
icons: array of TcachedIcon; icons: array of TcachedIcon;
function get(data:ansistring):PcachedIcon; function get(data:string):PcachedIcon;
procedure put(data:ansistring; idx:integer; time:Tdatetime); procedure put(data:string; idx:integer; time:Tdatetime);
procedure clear(); procedure clear();
procedure purge(olderThan:Tdatetime); procedure purge(olderThan:Tdatetime);
function idxOf(data:shortstring):integer; function idxOf(data:string):integer;
end; end;
TusersInVFS = class TusersInVFS = class
@ -105,7 +105,7 @@ type
function fsInit():boolean; function fsInit():boolean;
procedure headerInit(); // fill block with header procedure headerInit(); // fill block with header
procedure padInit(full:boolean=FALSE); // fill block with pad procedure padInit(full:boolean=FALSE); // fill block with pad
function headerLengthForFilename(fn:ansistring):integer; function headerLengthForFilename(ufn:string):integer;
procedure calculate(); override; procedure calculate(); override;
public public
fileNamesOEM: boolean; fileNamesOEM: boolean;
@ -316,7 +316,7 @@ end; // match
//////////// TiconsCache //////////// TiconsCache
function TiconsCache.idxOf(data:shortstring):integer; function TiconsCache.idxOf(data:string):integer;
var var
b, e, c: integer; b, e, c: integer;
begin begin
@ -335,7 +335,7 @@ e:=n-1;
result:=b; result:=b;
end; // idxOf end; // idxOf
function TiconsCache.get(data:ansistring):PcachedIcon; function TiconsCache.get(data:string):PcachedIcon;
var var
i: integer; i: integer;
begin begin
@ -345,7 +345,7 @@ if (i >= 0) and (i < n) and (icons[i].data = data) then
result:=@icons[i]; result:=@icons[i];
end; // get end; // get
procedure TiconsCache.put(data:ansistring; idx:integer; time:Tdatetime); procedure TiconsCache.put(data:string; idx:integer; time:Tdatetime);
var var
i, w: integer; i, w: integer;
begin begin
@ -569,7 +569,7 @@ var
begin begin
ufn:=replaceStr(flist[cur].dst,'\','/'); ufn:=replaceStr(flist[cur].dst,'\','/');
if fileNamesOEM then if fileNamesOEM then
CharToOem(pWideChar(ufn), pAnsiChar(fn)) fn:=strToOem(ufn)
else else
fn:=UTF8encode(ufn); fn:=UTF8encode(ufn);
pre:=''; pre:='';
@ -612,8 +612,14 @@ block.WriteString(dupeString(#0, if_(full,512,gap512(pos)) ));
block.Seek(0, soBeginning); block.Seek(0, soBeginning);
end; // padInit end; // padInit
function TtarStream.headerLengthForFilename(fn:ansistring):integer; function TtarStream.headerLengthForFilename(ufn:string):integer;
var
fn: ansistring;
begin begin
if fileNamesOEM then
fn:=strToOem(ufn)
else
fn:=UTF8encode(ufn);
result:=length(fn); result:=length(fn);
result:=512*if_(result<100, 1, 3+result div 512); result:=512*if_(result<100, 1, 3+result div 512);
end; // headerLengthForFilename end; // headerLengthForFilename

View File

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

118
hslib.pas
View File

@ -29,7 +29,7 @@ unit HSlib;
interface interface
uses 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 const
VERSION = '2.11.0'; VERSION = '2.11.0';
@ -105,9 +105,9 @@ type
bodyFile: string; bodyFile: string;
bodyStream: Tstream; // note: the stream is automatically freed bodyStream: Tstream; // note: the stream is automatically freed
firstByte, lastByte: int64; // body interval for partial replies (206) firstByte, lastByte: int64; // body interval for partial replies (206)
realm: ansistring; // this will appear in the authentication dialog realm, // this will appear in the authentication dialog
url: ansistring; // used for redirections reason, // customized reason phrase
reason: ansistring; // customized reason phrase url: string; // used for redirections
resumeForbidden: boolean; resumeForbidden: boolean;
end; end;
@ -208,9 +208,10 @@ type
destructor Destroy; override; destructor Destroy; override;
procedure disconnect(); procedure disconnect();
procedure addHeader(s:ansistring; overwrite:boolean=TRUE); // set an additional header line. If overwrite=false will always append. 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); 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; function getCookie(k:string):string;
procedure setCookie(k, v:string; pairs:array of string; extra:string=''); procedure setCookie(k, v:string; pairs:array of string; extra:string='');
procedure delCookie(k:string); procedure delCookie(k:string);
@ -310,7 +311,7 @@ function chopLine(var s:string):string; overload;
// decode/decode url // decode/decode url
function decodeURL(url:ansistring; utf8:boolean=TRUE):string; function decodeURL(url:ansistring; utf8:boolean=TRUE):string;
function encodeURL(url:string; nonascii:boolean=TRUE; spaces:boolean=TRUE; 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 // returns true if address is not suitable for the internet
function isLocalIP(ip:string):boolean; function isLocalIP(ip:string):boolean;
// base64 encoding // base64 encoding
@ -330,7 +331,7 @@ function ipos(ss, s:string; ofs:integer=1):integer; overload;
implementation implementation
uses uses
Windows; Windows, ansistrings;
const const
CRLF = #13#10; CRLF = #13#10;
MAX_REQUEST_LENGTH = 64*1024; MAX_REQUEST_LENGTH = 64*1024;
@ -477,6 +478,15 @@ else
end; // base64encode end; // base64encode
function base64decode(s:ansistring):ansistring; function base64decode(s:ansistring):ansistring;
function if_(cond:boolean; c:ansichar):ansistring;
begin
if cond then
result:=c
else
result:=''
end;
const const
TABLE:array[#43..#122] of byte=( 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, 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,
@ -484,15 +494,18 @@ const
29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51); 29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51);
var var
i: integer; i: integer;
p1, p2: byte;
begin begin
result:=''; result:='';
i:=1; i:=1;
while i <= length(s) do while i <= length(s) do
begin begin
p1:=TABLE[s[i+1]];
p2:=TABLE[s[i+2]];
result:=result result:=result
+ansichar(TABLE[s[i]] shl 2+TABLE[s[i+1]] shr 4) +ansichar(TABLE[s[i]] shl 2+p1 shr 4)
+ifThen(s[i+2]<>'=', ansichar(TABLE[s[i+1]] shl 4+TABLE[s[i+2]] shr 2)) +if_(s[i+2]<>'=', ansichar(p1 shl 4+p2 shr 2))
+ifThen(s[i+3]<>'=', ansichar(TABLE[s[i+2]] shl 6+TABLE[s[i+3]])); +if_(s[i+3]<>'=', ansichar(p2 shl 6+TABLE[s[i+3]]));
inc(i,4); inc(i,4);
end; end;
end; // base64decode end; // base64decode
@ -527,24 +540,25 @@ else
end; // decodeURL end; // decodeURL
function encodeURL(url:string; nonascii:boolean=TRUE; spaces:boolean=TRUE; function encodeURL(url:string; nonascii:boolean=TRUE; spaces:boolean=TRUE;
unicode:boolean=FALSE):string; htmlEncoding:boolean=FALSE):string;
var var
i: integer; i: integer;
encodePerc, encodeUni: set of char; encodePerc, encodeHTML: set of char;
a: ansistring; a: ansistring;
begin begin
result:=''; result:='';
if url = '' then if url = '' then
exit; exit;
encodeUni:=[]; encodeHTML:=[];
if nonascii then encodeUni:=[#128..#255]; if nonascii then
encodeHTML:=[#128..#255];
encodePerc:=[#0..#31,'#','%','?','"','''','&','<','>',':']; encodePerc:=[#0..#31,'#','%','?','"','''','&','<','>',':'];
// actually ':' needs encoding only in relative url // actually ':' needs encoding only in relative url
if spaces then include(encodePerc,' '); if spaces then include(encodePerc,' ');
if not unicode then if not htmlEncoding then
begin begin
encodePerc:=encodePerc+encodeUni; encodePerc:=encodePerc+encodeHTML;
encodeUni:=[]; encodeHTML:=[];
end; end;
if nonascii then if nonascii then
begin begin
@ -557,7 +571,7 @@ if nonascii then
for i:=1 to length(url) do for i:=1 to length(url) do
if charInSet(url[i], encodePerc) then if charInSet(url[i], encodePerc) then
result:=result+'%'+intToHex(ord(url[i]),2) 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]))+';' result:=result+'&#'+intToStr(charToUnicode(url[i]))+';'
else else
result:=result+url[i]; result:=result+url[i];
@ -583,7 +597,8 @@ end; // getIP
function replyHeader_IntPositive(name:ansistring; int:int64):ansistring; function replyHeader_IntPositive(name:ansistring; int:int64):ansistring;
begin begin
result:=''; result:='';
if int >= 0 then result:=name+': '+intToStr(int)+CRLF; if int >= 0 then
result:=name+': '+ansistring(intToStr(int))+CRLF;
end; end;
function replyHeader_Str(name:ansistring; str:ansistring):ansistring; function replyHeader_Str(name:ansistring; str:ansistring):ansistring;
@ -993,13 +1008,20 @@ state:=HCS_DISCONNECTED;
srv.disconnecting.Add(self); srv.disconnecting.Add(self);
end; end;
function ThttpConn.getHeader(h:string):string; function ThttpConn.getHeader(h:ansistring):string;
begin begin
result:=''; result:='';
if request.method = HM_UNK then exit; if request.method <> HM_UNK then
result:=trim(request.headers.values[h]); result:=trim(UTF8toString(rawByteString(request.headers.values[h])));
end; // getHeader 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; function ThttpConn.getBuffer():ansistring;
begin result:=buffer end; begin result:=buffer end;
@ -1031,7 +1053,7 @@ while i < length(pairs)-1 do
v:=v+lowerCase(pairs[i])+'='+pairs[i+1]+'; '; v:=v+lowerCase(pairs[i])+'='+pairs[i+1]+'; ';
inc(i,2); inc(i,2);
end; end;
addHeader(v+extra); addHeader(UTF8encode(v+extra));
end; // setCookie end; // setCookie
procedure ThttpConn.clearRequest(); procedure ThttpConn.clearRequest();
@ -1087,13 +1109,13 @@ procedure ThttpConn.processInputBuffer();
request.url:=chop(' ', r); request.url:=chop(' ', r);
s:=uppercase(chopLine(r)); s:=ansiUppercase(chopLine(r));
// if 'HTTP/' is not found, chop returns S // if 'HTTP/' is not found, chop returns S
if chop('HTTP/',s) = '' then request.ver:=s; if chop('HTTP/',s) = '' then request.ver:=s;
request.headers.text:=r; request.headers.text:=r;
s:=getHeader('Range'); s:=getHeaderA('Range');
if ansiStartsText('bytes=',s) then if ansiStartsText('bytes=',s) then
begin begin
delete(s,1,6); delete(s,1,6);
@ -1104,20 +1126,20 @@ procedure ThttpConn.processInputBuffer();
except end; except end;
end; end;
s:=getHeader('Authorization'); s:=getHeaderA('Authorization');
if AnsiStartsText('Basic',s) then if AnsiStartsText('Basic',s) then
begin begin
delete(s,1,6); delete(s,1,6);
u:=UTF8decode(base64decode(s)); u:=UTF8toString(base64decode(s));
request.user:=trim(chop(':',u)); request.user:=trim(chop(':',u));
request.pwd:=u; request.pwd:=u;
end; end;
s:=getHeader('Connection'); s:=getHeaderA('Connection');
persistent:=srv.persistentConnections and persistent:=srv.persistentConnections and
(ansiStartsText('Keep-Alive',s) or (request.ver >= '1.1') and (ipos('close',s)=0)); (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 if ansiStartsText('application/x-www-form-urlencoded', s) then
post.mode:=PM_URLENCODED post.mode:=PM_URLENCODED
else if ansiStartsText('multipart/form-data', s) then else if ansiStartsText('multipart/form-data', s) then
@ -1214,8 +1236,8 @@ procedure ThttpConn.processInputBuffer();
while l > '' do while l > '' do
begin begin
c:=chop(nonQuotedPos(';', l), l); c:=chop(nonQuotedPos(';', l), l);
k:=UTF8decode(trim(chop('=', c))); k:=UTF8toString(rawByteString(trim(chop('=', c))));
c:=UTF8decode(ansiDequotedStr(c,'"')); c:=UTF8toString(rawByteString(ansiDequotedStr(c,'"')));
if sameText(k, 'filename') then if sameText(k, 'filename') then
begin begin
delete(c, 1, lastDelimiter('/\',c)); delete(c, 1, lastDelimiter('/\',c));
@ -1292,17 +1314,17 @@ procedure ThttpConn.processInputBuffer();
handlePostData(); handlePostData();
end; // handleHeaderData end; // handleHeaderData
function replyHeader_OK(contentLength:int64=-1):string; function replyHeader_OK(contentLength:int64=-1):ansistring;
begin begin
result:=replyheader_code(200) result:=replyheader_code(200)
+format('Content-Length: %d'+CRLF, [contentLength]); +ansistring(format('Content-Length: %d'+CRLF, [contentLength]));
end; // replyHeader_OK end; // replyHeader_OK
function replyHeader_PARTIAL( firstB, lastB, totalB:int64):string; function replyHeader_PARTIAL( firstB, lastB, totalB:int64):ansistring;
begin begin
result:=replyheader_code(206) result:=replyheader_code(206)
+format('Content-Range: bytes %d-%d/%d'+CRLF+'Content-Length: %d'+CRLF, +ansistring(format('Content-Range: bytes %d-%d/%d'+CRLF+'Content-Length: %d'+CRLF,
[firstB, lastB, totalB, lastB-firstB+1 ]) [firstB, lastB, totalB, lastB-firstB+1 ]))
end; // replyheader_PARTIAL end; // replyheader_PARTIAL
begin begin
@ -1344,9 +1366,9 @@ case reply.mode of
HRM_DENY: sendHeader( replyheader_mode(reply.mode) ); HRM_DENY: sendHeader( replyheader_mode(reply.mode) );
HRM_UNAUTHORIZED: HRM_UNAUTHORIZED:
sendHeader(replyheader_mode(reply.mode) 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: 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: HRM_REPLY, HRM_REPLY_HEADER:
if stream = NIL then if stream = NIL then
sendHeader( replyHeader_code(404) ) sendHeader( replyHeader_code(404) )
@ -1364,7 +1386,7 @@ end; // processInputBuffer
procedure ThttpConn.dataavailable(Sender: TObject; Error: Word); procedure ThttpConn.dataavailable(Sender: TObject; Error: Word);
var var
s: string; s: ansistring;
begin begin
if error <> 0 then exit; if error <> 0 then exit;
s:=sock.ReceiveStrA(); s:=sock.ReceiveStrA();
@ -1426,9 +1448,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 if ((stream = NIL) or (stream.size = 0)) and (reply.mode <> HRM_REPLY) then
begin begin
reply.bodyMode:=RBM_STRING; reply.bodyMode:=RBM_STRING;
reply.body:=HRM2BODY[reply.mode]; reply.body:=UTF8encode(HRM2BODY[reply.mode]);
if reply.mode in [HRM_REDIRECT, HRM_MOVED] then 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(); initInputStream();
end; end;
end; end;
@ -1491,7 +1513,6 @@ end; // partialBodySize
function ThttpConn.initInputStream():boolean; function ThttpConn.initInputStream():boolean;
var var
i: integer; i: integer;
buf: ansistring;
begin begin
result:=FALSE; result:=FALSE;
FreeAndNil(stream); FreeAndNil(stream);
@ -1605,15 +1626,16 @@ end; // replycode2reason
function ThttpConn.replyHeader_code(code:integer):ansistring; function ThttpConn.replyHeader_code(code:integer):ansistring;
begin begin
if reply.reason = '' then reply.reason:=replycode2reason(code); if reply.reason = '' then
result:=format('HTTP/1.1 %d %s'+CRLF, [code,reply.reason]) reply.reason:=replycode2reason(code);
result:=UTF8encode(format('HTTP/1.1 %d %s'+CRLF, [code,reply.reason]))
+ replyHeader_Str('Content-Type',reply.contentType) + replyHeader_Str('Content-Type',reply.contentType)
end; end;
function ThttpConn.replyHeader_mode(mode:ThttpReplyMode):ansistring; function ThttpConn.replyHeader_mode(mode:ThttpReplyMode):ansistring;
begin result:=replyHeader_code(HRM2CODE[mode]) end; 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; begin result:=copy(s, 1, pos(':', s)) end;
// return 0 if not found // return 0 if not found
@ -1627,9 +1649,9 @@ result:=from;
end; // namePos end; // namePos
// return true if the operation succeded // return true if the operation succeded
function ThttpConn.setHeaderIfNone(s:string):boolean; function ThttpConn.setHeaderIfNone(s:ansistring):boolean;
var var
name: string; name: ansistring;
begin begin
name:=getNameOf(s); name:=getNameOf(s);
if name = '' then if name = '' then

View File

@ -357,7 +357,7 @@ type
postVars // as $_POST in php postVars // as $_POST in php
: THashedStringList; : THashedStringList;
tplCounters: TstringToIntHash; tplCounters: TstringToIntHash;
workaroundForIEutf8: (toDetect, yes, no); workaroundForIEutf8: (WI_toDetect, WI_yes, WI_no);
{ here we put just a pointer because the file type would triplicate { here we put just a pointer because the file type would triplicate
{ the size of this record, while it is NIL for most connections } { the size of this record, while it is NIL for most connections }
f: ^file; // uploading file handle f: ^file; // uploading file handle
@ -1937,12 +1937,6 @@ while i < srv.conns.count do
result:=length(ips); result:=length(ips);
end; // countIPs end; // countIPs
function strSHA256(s:string):string;
begin result:=upperCase( THashSHA2.GetHashString(s) ) end;
function strMD5(s:string):string;
begin result:=uppercase( THashMD5.GetHashString(s) ) end;
function idx_img2ico(i:integer):integer; function idx_img2ico(i:integer):integer;
begin begin
if (i < startingImagesCount) or (i >= USER_ICON_MASKS_OFS) then result:=i if (i < startingImagesCount) or (i >= USER_ICON_MASKS_OFS) then result:=i
@ -2688,10 +2682,10 @@ else
result:=ICON_FILE; result:=ICON_FILE;
end; // getIconForTreeview end; // getIconForTreeview
function encodeURL(s:string; fullEncode:boolean=FALSE):string; function encodeURL(s:string; forceEncodedSpaces:boolean=FALSE):string;
begin begin
result:=HSlib.encodeURL(s, mainFrm.encodeNonasciiChk.checked, result:=HSlib.encodeURL(s, mainFrm.encodeNonasciiChk.checked,
fullEncode or mainFrm.encodeSpacesChk.checked) forceEncodedSpaces or mainFrm.encodeSpacesChk.checked)
end; // encodeURL end; // encodeURL
function protoColon():string; function protoColon():string;
@ -3464,7 +3458,6 @@ var
buildTime: Tdatetime; buildTime: Tdatetime;
listing: TfileListing; listing: TfileListing;
diffTpl: Ttpl; diffTpl: Ttpl;
isDMbrowser: boolean;
hasher: Thasher; hasher: Thasher;
fullEncode, recur, oneAccessible: boolean; fullEncode, recur, oneAccessible: boolean;
md: TmacroData; md: TmacroData;
@ -3632,7 +3625,6 @@ try
if otpl <> filelistTpl then if otpl <> filelistTpl then
diffTpl.fullText:=folder.getRecursiveDiffTplAsStr(); diffTpl.fullText:=folder.getRecursiveDiffTplAsStr();
isDMbrowser:= otpl = dmBrowserTpl;
fullEncode:=FALSE; fullEncode:=FALSE;
ofsRelUrl:=length(folder.url(fullEncode))+1; ofsRelUrl:=length(folder.url(fullEncode))+1;
ofsRelItemUrl:=length(folder.pathTill())+1; ofsRelItemUrl:=length(folder.pathTill())+1;
@ -3920,7 +3912,7 @@ try
else s:=first(data.banReason, data.disconnectReason); else s:=first(data.banReason, data.disconnectReason);
addArray(md.table, ['%reason%', s]); addArray(md.table, ['%reason%', s]);
data.conn.reply.contentType:=name2mimetype(sectionName, 'text/html'); data.conn.reply.contentType:=ansistring(name2mimetype(sectionName, 'text/html'));
if sectionName = 'ban' then data.conn.reply.mode:=HRM_DENY; if sectionName = 'ban' then data.conn.reply.mode:=HRM_DENY;
if sectionName = 'deny' then data.conn.reply.mode:=HRM_DENY; if sectionName = 'deny' then data.conn.reply.mode:=HRM_DENY;
if sectionName = 'not found' then data.conn.reply.mode:=HRM_NOT_FOUND; if sectionName = 'not found' then data.conn.reply.mode:=HRM_NOT_FOUND;
@ -3976,9 +3968,9 @@ if result then
conn.reply.mode:=HRM_NOT_MODIFIED; conn.reply.mode:=HRM_NOT_MODIFIED;
exit; exit;
end; end;
conn.addHeader('ETag: '+etag); conn.addHeader('ETag: '+UTF8encode(etag));
if ts > '' then if ts > '' then
conn.addHeader('Last-Modified: '+ts); conn.addHeader('Last-Modified: '+UTF8encode(ts));
end; // notModified end; // notModified
function notModified(conn:ThttpConn; f:string):boolean; overload; function notModified(conn:ThttpConn; f:string):boolean; overload;
@ -4194,7 +4186,7 @@ if (logFile.filename > '') and (logFile.apacheFormat = '') then
else s:=s+CRLF+rest; else s:=s+CRLF+rest;
includeTrailingString(s,CRLF); includeTrailingString(s,CRLF);
appendFile(getDynLogFilename(cd), s); appendTextFile(getDynLogFilename(cd), s);
end; end;
if not logOnVideoChk.checked then exit; if not logOnVideoChk.checked then exit;
@ -4382,7 +4374,7 @@ try
's': res:=code; 's': res:=code;
'B': res:=intToStr(cd.conn.bytesSentLastItem); 'B': res:=intToStr(cd.conn.bytesSentLastItem);
'b': if cd.conn.bytesSentLastItem = 0 then res:='-' else res:=intToStr(cd.conn.bytesSentLastItem); 'b': if cd.conn.bytesSentLastItem = 0 then res:='-' else res:=intToStr(cd.conn.bytesSentLastItem);
'i': res:=cd.conn.getHeader(par); 'i': res:=cd.conn.getHeader(ansistring(par));
'm': res:=METHOD2STR[cd.conn.request.method]; 'm': res:=METHOD2STR[cd.conn.request.method];
'c': if (cd.conn.bytesToSend > 0) and (cd.conn.state = HCS_DISCONNECTED) then res:='X' 'c': if (cd.conn.bytesToSend > 0) and (cd.conn.state = HCS_DISCONNECTED) then res:='X'
else if cd.disconnectAfterReply then res:='-' else if cd.disconnectAfterReply then res:='-'
@ -4746,7 +4738,7 @@ var
'\\', '\' '\\', '\'
]); ]);
s:=reCB('%(!?[0-9,]+)?(\{([^}]+)\})?>?([a-z])', s, apacheLogCb, data); s:=reCB('%(!?[0-9,]+)?(\{([^}]+)\})?>?([a-z])', s, apacheLogCb, data);
appendFile(getDynLogFilename(data), s+CRLF); appendTextFile(getDynLogFilename(data), s+CRLF);
end; // doLog end; // doLog
function limitsExceededOnConnection():boolean; function limitsExceededOnConnection():boolean;
@ -4795,7 +4787,7 @@ var
s:=replaceStr(s,'+',' '); s:=replaceStr(s,'+',' ');
data.urlvars.text:=s; data.urlvars.text:=s;
for i:=0 to data.urlvars.count-1 do for i:=0 to data.urlvars.count-1 do
data.urlvars[i]:=decodeURL(data.urlvars[i]); data.urlvars[i]:=decodeURL(ansistring(data.urlvars[i]));
end; // extractParams end; // extractParams
procedure closeUploadingFile(); procedure closeUploadingFile();
@ -4840,7 +4832,7 @@ var
result:=trim(stripChars(runEventScript(event, table), [TAB,#10,#13])); result:=trim(stripChars(runEventScript(event, table), [TAB,#10,#13]));
// turn illegal chars into underscores // turn illegal chars into underscores
for i:=1 to length(result) do for i:=1 to length(result) do
if result[i] in ILLEGAL_FILE_CHARS-[':','\'] then if charInSet(result[i], ILLEGAL_FILE_CHARS-[':','\']) then
result[i]:='_'; result[i]:='_';
end; // eventToFilename end; // eventToFilename
@ -4884,9 +4876,9 @@ var
procedure addContentDisposition(attach:boolean=TRUE); procedure addContentDisposition(attach:boolean=TRUE);
var s:ansistring; var s:ansistring;
begin begin
s:=HSlib.encodeURL(data.lastFN); s:=ansistring(HSlib.encodeURL(data.lastFN));
conn.addHeader( 'Content-Disposition: '+if_(attach, 'attachment; ') conn.addHeader( ansistring('Content-Disposition: '+if_(attach, 'attachment; ')
+'filename*=UTF-8'''''+s+'; filename='+s); +'filename*=UTF-8'''''+s+'; filename='+s));
end; end;
procedure sessionSetup(); procedure sessionSetup();
@ -5124,7 +5116,7 @@ var
end; end;
if conn.reply.contentType = '' then if conn.reply.contentType = '' then
conn.reply.contentType:=if_(trim(getTill('<', s))='', 'text/html', 'text/plain'); conn.reply.contentType:=ansistring(if_(trim(getTill('<', s))='', 'text/html', 'text/plain'));
conn.reply.mode:=HRM_REPLY; conn.reply.mode:=HRM_REPLY;
conn.reply.bodyMode:=RBM_STRING; conn.reply.bodyMode:=RBM_STRING;
conn.reply.body:=UTF8encode(s); conn.reply.body:=UTF8encode(s);
@ -5147,11 +5139,9 @@ var
for i:=0 to data.postvars.count-1 do for i:=0 to data.postvars.count-1 do
if sameText('selection', data.postvars.names[i]) then if sameText('selection', data.postvars.names[i]) then
begin begin
asUrl:=decodeURL(getTill('#', data.postvars.valueFromIndex[i])); // omit #anchors asUrl:=getTill('#', data.postvars.valueFromIndex[i]); // omit #anchors
s:=uri2disk(asUrl, f); s:=uri2disk(asUrl, f);
if s = '' then continue; if (s = '') or not fileOrDirExists(s) then continue; // ignore
if not fileOrDirExists(s) then continue; // ignore
runEventScript('file deleting', ['%item-deleting%', s]); runEventScript('file deleting', ['%item-deleting%', s]);
moveToBin(toSA([s, s+'.md5', s+COMMENT_FILE_EXT]) , TRUE); moveToBin(toSA([s, s+'.md5', s+COMMENT_FILE_EXT]) , TRUE);
@ -5279,7 +5269,7 @@ var
url:=conn.request.url; url:=conn.request.url;
extractParams(); extractParams();
url:=decodeURL(url); url:=decodeURL(ansistring(url));
data.lastFN:=extractFileName( replaceStr(url,'/','\') ); data.lastFN:=extractFileName( replaceStr(url,'/','\') );
data.agent:=getAgentID(conn); data.agent:=getAgentID(conn);
@ -5437,7 +5427,8 @@ var
if conn.request.user = '' then if conn.request.user = '' then
begin // issue a login dialog begin // issue a login dialog
getPage('unauthorized', data); getPage('unauthorized', data);
if loginRealm > '' then conn.reply.realm:=loginRealm; if loginRealm > '' then
conn.reply.realm:=loginRealm;
exit; exit;
end end
else else
@ -5578,7 +5569,7 @@ var
setupDownloadIcon(data); setupDownloadIcon(data);
data.eta.idx:=0; data.eta.idx:=0;
conn.reply.contentType:=name2mimetype(f.name, DEFAULT_MIME); conn.reply.contentType:=ansistring(name2mimetype(f.name, DEFAULT_MIME));
conn.reply.bodyMode:=RBM_FILE; conn.reply.bodyMode:=RBM_FILE;
conn.reply.bodyFile:=f.resource; conn.reply.bodyFile:=f.resource;
data.downloadingWhat:=DW_FILE; data.downloadingWhat:=DW_FILE;
@ -6409,10 +6400,13 @@ if act then startServer();
end; // changePort end; // changePort
function b64utf8(const s:string):ansistring; function b64utf8(const s:string):ansistring;
begin result:=base64encode(UTF8encode(s)); end; begin result:=base64encode(UTF8encode(s)) end;
function decodeB64utf8(const s:ansistring):string; function decodeB64utf8(const s:ansistring):string; overload;
begin result:=UTF8decode(base64decode(s)); end; begin result:=UTF8toString(base64decode(s)) end;
function decodeB64utf8(const s:string):string; overload;
begin result:=decodeB64utf8(ansistring(s)) end;
function zCompressStr(const s: ansistring; level:TCompressionLevel=clMax; type_:TzStreamType=zsZlib): ansistring; function zCompressStr(const s: ansistring; level:TCompressionLevel=clMax; type_:TzStreamType=zsZlib): ansistring;
var var
@ -6459,16 +6453,17 @@ type
Tencoding=(E_PLAIN,E_B64,E_ZIP); Tencoding=(E_PLAIN,E_B64,E_ZIP);
function encode(s:string; encoding:Tencoding):string; function encode(s:string; encoding:Tencoding):string;
var
a, c: ansistring;
begin begin
case encoding of case encoding of
E_PLAIN: result:=s; E_PLAIN: result:=s;
E_B64: result:=b64utf8(s); E_B64: result:=b64utf8(s);
E_ZIP: E_ZIP:
begin begin
result:=zCompressStr(s, clMax); a:=UTF8encode(s);
if length(result) > round(0.9*length(s)) then c:=zCompressStr(a, clMax);
result:=s; result:=base64encode(if_( length(c) < round(0.8*length(a)), c, a));
result:=base64encode(result);
end; end;
end; end;
end; end;
@ -6831,7 +6826,7 @@ var
else if p = 'link' then else if p = 'link' then
a.link:=split(':',t) a.link:=split(':',t)
else if p = 'notes' then else if p = 'notes' then
a.notes:=UTF8ToString(unzipCfgProp(t)) a.notes:=UTF8ToString(unzipCfgProp(ansistring(t)))
end; end;
end; end;
end; // strToAccounts end; // strToAccounts
@ -6857,7 +6852,7 @@ var
while l > '' do while l > '' do
begin begin
iFrom:=strTointDef(chop(':', l), -1); iFrom:=strTointDef(chop(':', l), -1);
iTo:=str2pic(unzipCfgProp(chop('|', l))); iTo:=str2pic(unzipCfgProp(ansistring(chop('|', l))));
for i:=0 to length(iconMasks)-1 do for i:=0 to length(iconMasks)-1 do
if iconMasks[i].int = iFrom then if iconMasks[i].int = iFrom then
iconMasks[i].int:=iTo; iconMasks[i].int:=iTo;
@ -10961,13 +10956,13 @@ s:=cd.conn.reply.body;
if s = '' then exit; if s = '' then exit;
if ipos('gzip', cd.conn.getHeader('Accept-Encoding')) = 0 then exit; if ipos('gzip', cd.conn.getHeader('Accept-Encoding')) = 0 then exit;
// workaround for IE6 pre-SP2 bug // workaround for IE6 pre-SP2 bug
if (cd.workaroundForIEutf8 = toDetect) and (cd.agent > '') then if (cd.workaroundForIEutf8 = WI_toDetect) and (cd.agent > '') then
if reMatch(cd.agent, '^MSIE [4-6]\.', '!') > 0 then // version 6 and before if reMatch(cd.agent, '^MSIE [4-6]\.', '!') > 0 then // version 6 and before
cd.workaroundForIEutf8:=yes cd.workaroundForIEutf8:=WI_yes
else else
cd.workaroundForIEutf8:=no; cd.workaroundForIEutf8:=WI_no;
s:=ZcompressStr(s, clFastest, zsGzip); s:=ZcompressStr(s, clFastest, zsGzip);
if (cd.workaroundForIEutf8 = yes) and (length(s) < BAD_IE_THRESHOLD) then exit; if (cd.workaroundForIEutf8 = WI_yes) and (length(s) < BAD_IE_THRESHOLD) then exit;
cd.conn.addHeader('Content-Encoding: gzip'); cd.conn.addHeader('Content-Encoding: gzip');
//cd.conn.addHeader('Content-Length: '+intToStr(length(s))); //cd.conn.addHeader('Content-Length: '+intToStr(length(s)));
cd.conn.reply.body:=s; cd.conn.reply.body:=s;
@ -12205,7 +12200,7 @@ if ipos('<html>', dyndns.lastResult) = 0 then
msgDlg(dyndns.lastResult); msgDlg(dyndns.lastResult);
exit; exit;
end; end;
fn:=saveTempFile(UTF8encode(dyndns.lastResult)); fn:=saveTempFile(dyndns.lastResult);
if fn = '' then if fn = '' then
begin begin
msgDlg(MSG_NO_TEMP, MB_ICONERROR); msgDlg(MSG_NO_TEMP, MB_ICONERROR);
@ -12240,7 +12235,7 @@ while current > '' do
if defV = v then continue; if defV = v then continue;
if k = 'dynamic-dns-updater' then if k = 'dynamic-dns-updater' then
begin // remove login data begin // remove login data
v:=decodeB64utf8(v); v:=decodeB64utf8(ansistring(v));
chop('//',v); chop('//',v);
v:=chop('/',v); v:=chop('/',v);
if ansiContainsStr(v, '@') then chop('@',v); if ansiContainsStr(v, '@') then chop('@',v);

View File

@ -759,7 +759,7 @@ begin
if renamingAccount then if renamingAccount then
exit; exit;
key:=upcase(key); key:=upcase(key);
if key in ['0'..'9','A'..'Z'] then if charInSet(key, ['0'..'9','A'..'Z']) then
begin begin
s:=accountsBox.ItemIndex; s:=accountsBox.ItemIndex;
n:=length(tempAccounts); n:=length(tempAccounts);

View File

@ -48,7 +48,7 @@ procedure resetLog();
implementation implementation
uses windows, utilLib, trayLib, parserLib, graphics, classes, sysutils, StrUtils, 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 const
HEADER = '<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><style>' HEADER = '<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><style>'
@ -58,7 +58,6 @@ const
var 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. 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; cachedTpls: TcachedTpls;
flog: ^file;
function macrosLog(textIn, textOut:string; ts:boolean=FALSE):boolean; function macrosLog(textIn, textOut:string; ts:boolean=FALSE):boolean;
var var
@ -68,26 +67,11 @@ s:='';
if ts then if ts then
s:='<hr>'+dateTimeToStr(now())+CRLF; s:='<hr>'+dateTimeToStr(now())+CRLF;
s:=s+#13'<dt>'+htmlEncode(textIn)+'</dt><dd>'+htmlEncode(textOut)+'</dd>'; s:=s+#13'<dt>'+htmlEncode(textIn)+'</dt><dd>'+htmlEncode(textOut)+'</dd>';
if flog = NIL then result:=appendTextFile(MACROS_LOG_FILE, s);
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)
end; // macrosLog end; // macrosLog
procedure resetLog(); procedure resetLog();
begin begin deleteFile(MACROS_LOG_FILE) end;
try
closeFile(flog^);
dispose(flog);
flog:=NIL;
except end;
deleteFile(MACROS_LOG_FILE);
end; // resetLog
function expandLinkedAccounts(account:Paccount):TStringDynArray; function expandLinkedAccounts(account:Paccount):TStringDynArray;
var var
@ -679,8 +663,10 @@ var
procedure convert(); procedure convert();
begin begin
if sameText(p, 'ansi') and sameText(par(1), 'utf-8') then result:=ansiToUTF8(par(2)) if sameText(p, 'ansi') and sameText(par(1), 'utf-8') then
else if sameText(p, 'utf-8') and sameText(par(1), 'ansi') then result:=utf8ToAnsi(par(2)) result:=ansiToUTF8(ansistring(par(2)))
else if sameText(p, 'utf-8') and sameText(par(1), 'ansi') then
result:=utf8ToAnsi(ansistring(par(2)))
end; // convert end; // convert
procedure encodeuri(); procedure encodeuri();
@ -695,7 +681,7 @@ var
-strToCharset(par('add'))+strToCharset(par('not')); -strToCharset(par('add'))+strToCharset(par('not'));
end; end;
for i:=1 to length(p) do for i:=1 to length(p) do
if p[i] in cs then if charInSet(p[i], cs) then
result:=result+p[i] result:=result+p[i]
else else
result:=result+'%'+intToHex(ord(p[i]),2) result:=result+'%'+intToHex(ord(p[i]),2)
@ -1120,7 +1106,7 @@ var
if not satisfied(space) then exit; if not satisfied(space) then exit;
i:=space.indexOfName(s); 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; encode:=FALSE;
// if this is used as table, and has newlines, we must encode it to preserve associations // if this is used as table, and has newlines, we must encode it to preserve associations
h:=space.objects[i] as THashedStringList; h:=space.objects[i] as THashedStringList;
@ -1143,7 +1129,7 @@ var
finally free end; finally free end;
end; end;
// now we have in 's' the content to be saved // 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 end; // save
procedure replace(); procedure replace();
@ -1459,7 +1445,7 @@ var
t: Tdatetime; t: Tdatetime;
begin begin
try try
if getFirstChar(v) in ['+','-'] then if charInSet(getFirstChar(v), ['+','-']) then
t:=now()+strToFloat(v) t:=now()+strToFloat(v)
else else
try t:=maybeUnixTime(strToFloat(v)); try t:=maybeUnixTime(strToFloat(v));
@ -1946,13 +1932,13 @@ try
result:=jsEncode(p, first(par(1),'''"')); result:=jsEncode(p, first(par(1),'''"'));
if name = 'base64' then if name = 'base64' then
result:=base64encode(p); result:=base64encode(UTF8encode(p));
if name = 'base64decode' then if name = 'base64decode' then
result:=base64decode(p); result:=utf8ToString(base64decode(ansistring(p)));
if name = 'md5' then if name = 'md5' then
result:=strMD5(p); result:=strMD5(p);
if name = 'sha1' then if name = 'sha1' then
result:=SHA1toHex(sha1OfStr(p)); result:=strSHA1(p);
if name = 'vfs select' then if name = 'vfs select' then
if pars.count = 0 then if pars.count = 0 then
@ -2025,7 +2011,7 @@ try
encodeuri(); encodeuri();
if name = 'decodeuri' then if name = 'decodeuri' then
result:=decodeURL(p); result:=decodeURL(ansistring(p));
if name = 'set cfg' then if name = 'set cfg' then
trueIf(mainfrm.setcfg(p)); trueIf(mainfrm.setcfg(p));
@ -2101,7 +2087,7 @@ try
if name = 'header' then if name = 'header' then
if satisfied(md.cd) 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 if name = 'urlvar' then
result:=urlvar(p); result:=urlvar(p);
@ -2233,7 +2219,8 @@ try
if name = 'mime' then if name = 'mime' then
begin begin
result:=''; 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; end;
if name = 'calc' then if name = 'calc' then
@ -2292,22 +2279,22 @@ try
result:=''; 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 // 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 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 else if ansiStartsText('Location:', p) then
with md.cd.conn.reply do with md.cd.conn.reply do
begin begin
mode:=HRM_REDIRECT; mode:=HRM_REDIRECT;
url:=trim(substr(p, ':')) url:=UTF8encode(trim(substr(p, ':')))
end end
else else
md.cd.conn.addHeader(p, isTrue(par('overwrite',true,'1'))); md.cd.conn.addHeader(ansistring(p), isTrue(par('overwrite',true,'1')));
end; end;
if name = 'remove header' then if name = 'remove header' then
if satisfied(md.cd) then if satisfied(md.cd) then
begin begin
result:=''; result:='';
md.cd.conn.removeHeader(p); md.cd.conn.removeHeader(ansistring(p));
end; end;
if name = 'get ini' then if name = 'get ini' then
@ -2571,10 +2558,5 @@ freeAndNIL(eventScripts);
freeAndNIL(defaultAlias); freeAndNIL(defaultAlias);
freeAndNIL(currentCFGhashed); freeAndNIL(currentCFGhashed);
staticVars.free; staticVars.free;
if assigned(flog) then
begin
closeFile(flog^);
dispose(flog);
end;
end. end.

View File

@ -100,6 +100,7 @@ function compare_(i1,i2:int64):integer; overload;
function compare_(i1,i2:integer):integer; overload; function compare_(i1,i2:integer):integer; overload;
function msgDlg(msg:string; code:integer=0; title:string=''):integer; 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: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:int64; v2:int64=0):int64; overload; inline;
function if_(v:boolean; v1:integer; v2:integer=0):integer; 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; 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 readShellLink(linkFN:WideString):string;
function getShellFolder(id:string):string; function getShellFolder(id:string):string;
function getTempFilename():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 fileOrDirExists(fn:string):boolean;
function sizeOfFile(fn:string):int64; overload; function sizeOfFile(fn:string):int64; overload;
function sizeOfFile(fh:Thandle):int64; overload; function sizeOfFile(fh:Thandle):int64; overload;
function loadFile(fn:string; from:int64=0; size:int64=-1):ansistring; function loadFile(fn:string; from:int64=0; size:int64=-1):ansistring;
function loadTextFile(fn:string):string; 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(fn:string; data:ansistring; append:boolean=FALSE):boolean; overload;
function saveFile(var f:file; data:ansistring):boolean; overload; function saveFile(var f:file; data:ansistring):boolean; overload;
function moveFile(src, dst:string; op:UINT=FO_MOVE):boolean; 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 match(mask, txt:pchar; fullMatch:boolean=TRUE; charsNotWildcard:Tcharset=[]):integer;
function filematch(mask, fn:string):boolean; function filematch(mask, fn:string):boolean;
function appendFile(fn:string; data:ansistring):boolean; function appendFile(fn:string; data:ansistring):boolean;
function appendTextFile(fn:string; text:string):boolean;
function getFilename(var f:file):string; function getFilename(var f:file):string;
function filenameToDriveByte(fn:string):byte; function filenameToDriveByte(fn:string):byte;
function selectFile(var fn:string; title:string=''; filter:string=''; options:TOpenOptions=[]):boolean; function selectFile(var fn:string; title:string=''; filter:string=''; options:TOpenOptions=[]):boolean;
@ -221,6 +224,7 @@ function first(a,b:integer):integer; overload;
function first(a,b:double):double; overload; function first(a,b:double):double; overload;
function first(a,b:pointer):pointer; overload; function first(a,b:pointer):pointer; overload;
function first(a,b:string):string; overload; function first(a,b:string):string; overload;
function first(a,b:ansistring):ansistring; overload;
function first(a:array of string):string; overload; function first(a:array of string):string; overload;
function stripChars(s:string; cs:Tcharset; invert:boolean=FALSE):string; function stripChars(s:string; cs:Tcharset; invert:boolean=FALSE):string;
function isOnlyDigits(s:string):boolean; 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 replace(var s:string; ss:string; start,upTo:integer):integer;
function countSubstr(ss:string; s:string):integer; function countSubstr(ss:string; s:string):integer;
function trim2(s:string; chars:Tcharset):string; 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 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 reMatch(s, exp:string; mods:string='m'; ofs:integer=1; subexp:PstringDynArray=NIL):integer;
function reReplace(subj, exp, repl:string; mods:string='m'):string; function reReplace(subj, exp, repl:string; mods:string='m'):string;
@ -247,16 +251,35 @@ function escapeNL(s:string):string;
function unescapeNL(s:string):string; function unescapeNL(s:string):string;
function htmlEncode(s:string):string; function htmlEncode(s:string):string;
procedure enforceNUL(var s: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;
implementation implementation
uses uses
clipbrd, JclNTFS, JclWin32, parserLib, newuserpassDlg, winsock, OverbyteicsMD5; clipbrd, JclNTFS, JclWin32, parserLib, newuserpassDlg, winsock, System.Hash, ansistrings;
var var
ipToInt_cache: ThashedStringList; ipToInt_cache: ThashedStringList;
onlyDotsRE: TRegExpr; onlyDotsRE: TRegExpr;
function strSHA256(s:string):string;
begin result:=upperCase( THashSHA2.GetHashString(s) ) end;
function strSHA1(s:string):string;
begin result:=upperCase( THashSHA1.GetHashString(s) ) end;
function strMD5(s:string):string;
begin result:=UpperCase( THashMD5.GetHashString(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). // 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. // 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; function reCB(expr, subj:string; cb:TreCB; data:pointer=NIL):string;
@ -749,7 +772,7 @@ setLength(ansi, l);
move(p^, ansi[1], l); move(p^, ansi[1], l);
UnlockResource(h2); UnlockResource(h2);
FreeResource(h2); FreeResource(h2);
result:=ansi; result:=UTF8toString(ansi);
end; // getRes end; // getRes
function compare_(i1,i2:int64):integer; overload; function compare_(i1,i2:int64):integer; overload;
@ -929,7 +952,7 @@ result:=(fn > '')
end; end;
function loadTextFile(fn:string):string; function loadTextFile(fn:string):string;
begin result:=UTF8decode(loadfile(fn)) end; begin result:=UTF8toString(loadfile(fn)) end;
function loadFile(fn:string; from:int64=0; size:int64=-1):ansistring; function loadFile(fn:string; from:int64=0; size:int64=-1):ansistring;
var var
@ -1018,15 +1041,21 @@ try
except end; except end;
end; // saveFile end; // saveFile
function saveTextFile(fn:string; text:string):boolean; function saveTextFile(fn:string; text:string; append:boolean=FALSE):boolean;
begin result:=saveFile(fn, UTF8encode(text)) end; begin result:=saveFile(fn, UTF8encode(text), append) end;
function appendFile(fn:string; data:ansistring):boolean; function appendFile(fn:string; data:ansistring):boolean;
begin result:=saveFile(fn, data, TRUE) end; begin result:=saveFile(fn, data, TRUE) end;
function appendTextFile(fn:string; text:string):boolean;
begin result:=saveTextFile(fn, text, TRUE) end;
function getTempFilename():string; function getTempFilename():string;
begin result:=TPath.GetRandomFileName() end; begin result:=TPath.GetRandomFileName() end;
function saveTempFile(data:string):string;
begin result:=saveTempFile(UTF8encode(data)) end;
function saveTempFile(data:ansistring):string; function saveTempFile(data:ansistring):string;
begin begin
result:=getTempFilename(); result:=getTempFilename();
@ -1259,6 +1288,9 @@ begin if v then result:=v1 else result:=v2 end;
function if_(v:boolean; v1, v2:string):string; function if_(v:boolean; v1, v2:string):string;
begin if v then result:=v1 else result:=v2 end; 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; function if_(v:boolean; v1,v2:int64):int64;
begin if v then result:=v1 else result:=v2 end; begin if v then result:=v1 else result:=v2 end;
@ -1927,7 +1959,7 @@ begin
i:=ipToInt_cache.Add(ip); i:=ipToInt_cache.Add(ip);
result:=dword(ipToInt_cache.Objects[i]); result:=dword(ipToInt_cache.Objects[i]);
if result <> 0 then exit; 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); ipToInt_cache.Objects[i]:=Tobject(result);
end; // ipToInt end; // ipToInt
@ -2095,6 +2127,9 @@ end; // first
function first(a,b:string):string; function first(a,b:string):string;
begin if a = '' then result:=b else result:=a end; 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; function first(a,b:integer):integer;
begin if a = 0 then result:=b else result:=a end; begin if a = 0 then result:=b else result:=a end;
@ -2161,7 +2196,7 @@ try
until (Apprunning <> WAIT_TIMEOUT) or (now() >= timeout); until (Apprunning <> WAIT_TIMEOUT) or (now() >= timeout);
Buffer[TotalBytesRead]:= #0; Buffer[TotalBytesRead]:= #0;
OemToCharA(PansiChar(Buffer),Buffer); OemToCharA(PansiChar(Buffer),Buffer);
output:=strPas(Buffer); output:=string(ansistrings.strPas(Buffer));
finally finally
GetExitCodeProcess(ProcessInfo.hProcess, exitcode); GetExitCodeProcess(ProcessInfo.hProcess, exitcode);
TerminateProcess(ProcessInfo.hProcess, 0); TerminateProcess(ProcessInfo.hProcess, 0);
@ -2393,17 +2428,20 @@ end; // trim2
function boolOnce(var b:boolean):boolean; function boolOnce(var b:boolean):boolean;
begin result:=b; b:=FALSE end; begin result:=b; b:=FALSE end;
procedure urlToStrings(s:string; sl:Tstrings); procedure urlToStrings(s:ansistring; sl:Tstrings);
var var
i, l, p: integer; i, l, p: integer;
t: string; t: string;
a: ansistring;
begin begin
i:=1; i:=1;
l:=length(s); l:=length(s);
while i <= l do while i <= l do
begin begin
p:=posEx('&',s,i); p:=ansistrings.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 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); sl.add(t);
if p = 0 then exit; if p = 0 then exit;
i:=p+1; i:=p+1;