fix(developer): URL parameters should be UTF-8

Fixes #7628.

Indy components do not treat URLs as UTF-8. Our legacy EncodeURL
function (sourced from Indy components) was the same. Discovered we
needed to fixup the parsing of URLs as well as the construction of them;
there may be other places we need to fix, although I did do a search for
the relevant types in TIKE source.
This commit is contained in:
Marc Durdin 2022-11-05 07:19:31 +11:00
parent 2afde0cc9d
commit 0f2fbd443d
3 changed files with 12 additions and 74 deletions

View file

@ -27,9 +27,10 @@ unit utilhttp; // I3306 // I3308 // I3309
interface
uses
System.Classes,
System.SysUtils,
System.WideStrUtils;
System.Classes,
System.SysUtils,
System.WideStrUtils,
System.NetEncoding;
function GetParamsFromURL(URL: WideString; var Params: TStringList): Boolean;
function GetParamsFromURLEx(URL: WideString; var Params: TStringList): Boolean;
@ -42,77 +43,14 @@ function ConvertPathToFileURL(s: WideString): WideString;
implementation
function CharIsInSet(const AString: string; const ACharPos: Integer; ASet: TSysCharSet): Boolean;
begin
if ACharPos > Length(AString) then begin
Result := False;
end else begin
{$IFDEF DotNet}
Result := AnsiString(AString[ACharPos])[1] in ASet;
{$ELSE}
Result := CharInSet(AString[ACharPos], ASet);
{$ENDIF}
end;
end;
function URLEncode(ASrc: string): string;
var
i: Integer;
const
UnsafeChars = ['*', '#', '%', '<', '>', ' ','[',']', '{', '}', '?', '&']; {do not localize}
begin
Result := ''; {Do not Localize}
for i := 1 to Length(ASrc) do
begin
// S.G. 27/11/2002: Changed the parameter encoding: Even in parameters, a space
// S.G. 27/11/2002: is much more likely to be meaning "space" than "this is
// S.G. 27/11/2002: a new parameter"
// S.G. 27/11/2002: ref: Message-ID: <3de30169@newsgroups.borland.com> borland.public.delphi.internet.winsock
// S.G. 27/11/2002: Most low-ascii is actually Ok in parameters encoding.
if ((CharIsInSet(ASrc, i, UnsafeChars)) or (not (CharIsInSet(ASrc, i, [#33..#128])))) then
begin {do not localize}
Result := Result + '%' + IntToHex(Ord(ASrc[i]), 2); {do not localize}
end
else
begin
Result := Result + ASrc[i];
end;
end;
Result := TNetEncoding.URL.Encode(ASrc);
end;
function URLDecode(ASrc: AnsiString): string;
var
i: integer;
s: ansistring;
ESC: ansistring;
CharCode: integer;
begin
Result := ''; {Do not Localize}
// S.G. 27/11/2002: Spaces is NOT to be encoded as "+".
// S.G. 27/11/2002: "+" is a field separator in query parameter, space is...
// S.G. 27/11/2002: well, a space
// ASrc := StringReplace(ASrc, '+', ' ', [rfReplaceAll]); {do not localize}
i := 1;
while i <= Length(ASrc) do
begin
if ASrc[i] <> '%' then
begin {do not localize}
S := S + ASrc[i]
end
else
begin
Inc(i); // skip the % char
ESC := Copy(ASrc, i, 2); // Copy the escape code
Inc(i, 1); // Then skip it.
try
CharCode := StrToInt('$' + string(ESC)); {do not localize}
S := S + AnsiChar(CharCode);
except
end;
end;
Inc(i);
end;
Result := UTF8ToString(S);
Result := TNetEncoding.URL.Decode(ASrc);
end;
procedure DecodeAndSetParams(const AValue: WideString; Params: TStringList);

View file

@ -102,7 +102,7 @@ procedure TAppHttpResponder.RespondProject(doc: string; AContext: TIdContext;
Exit;
end;
path := ARequestInfo.Params.Values['path'];
path := UTF8ToString(AnsiString(ARequestInfo.Params.Values['path']));
if (Path <> '') and (not FileExists(path) or not SameText(ExtractFileExt(path), Ext_ProjectSource)) then
begin
@ -132,7 +132,7 @@ procedure TAppHttpResponder.RespondProject(doc: string; AContext: TIdContext;
Exit;
end;
path := ARequestInfo.Params.Values['path'];
path := UTF8ToString(AnsiString(ARequestInfo.Params.Values['path']));
if not FileExists(path) or (
not SameText(ExtractFileExt(path), '.ico') and

View file

@ -96,7 +96,7 @@ begin
if ARequestInfo.Document = '/app/source/file' then
begin
// TODO: We should be passing a token to the browser for future POST security
Filename := ARequestInfo.Params.Values['Filename'];
Filename := UTF8ToString(AnsiString(ARequestInfo.Params.Values['Filename']));
if ARequestInfo.CommandType = hcGET then
begin
@ -112,12 +112,12 @@ begin
else if ARequestInfo.Document = '/app/source/toucheditor' then
begin
// Respond files?
Filename := ARequestInfo.Params.Values['Filename'];
Filename := UTF8ToString(AnsiString(ARequestInfo.Params.Values['Filename']));
RespondTouchEditor(Filename, AContext, ARequestInfo, AResponseInfo);
end
else if ARequestInfo.Document = '/app/source/toucheditor/state' then
begin
Filename := ARequestInfo.Params.Values['Filename'];
Filename := UTF8ToString(AnsiString(ARequestInfo.Params.Values['Filename']));
RespondTouchEditorState(Filename, AContext, ARequestInfo, AResponseInfo);
end
else if ARequestInfo.Document.StartsWith('/app/source/toucheditor/lib/') then
@ -147,7 +147,7 @@ begin
end
else if ARequestInfo.CommandType = hcPOST then
begin
FData := ARequestInfo.Params.Values['State'];
FData := UTF8ToString(AnsiString(ARequestInfo.Params.Values['State']));
RegisterSource(AFilename + '#state', FData, True);
end;
end;