Is there a Delphi equivalent of this .net\'s method:
Url.UrlEncode()
Note
I haven\'t worked with Delphi for several years now.
As I
I'd like to point out that if you care much more about correctness than about efficiency, the simplest you can do is hex encode every character, even if it's not strictly necessary.
Just today I needed to encode a few parameters for a basic HTML login form submission. After going through all the options, each with their own caveats, I decided to write this naive version that works perfectly:
function URLEncode(const AStr: string): string;
var
LBytes: TBytes;
LIndex: Integer;
begin
Result := '';
LBytes := TEncoding.UTF8.GetBytes(AStr);
for LIndex := Low(LBytes) to High(LBytes) do
Result := Result + '%' + IntToHex(LBytes[LIndex], 2);
end;
In recent versions of Delphi (tested with XE5), use the URIEncode function in the REST.Utils unit.
Look at indy IdURI unit, it has two static methods in the TIdURI class for Encode/Decode the URL.
uses
IdURI;
..
begin
S := TIdURI.URLEncode(str);
//
S := TIdURI.URLDecode(str);
end;
Update 2018: the code shown below seems to be outdated. see Remy's comment.
class function TIdURI.ParamsEncode(const ASrc: string): string;
var
i: Integer;
const
UnsafeChars = '*#%<> []'; {do not localize}
begin
Result := ''; {Do not Localize}
for i := 1 to Length(ASrc) do
begin
if CharIsInSet(ASrc, i, UnsafeChars) or (not CharIsInSet(ASrc, i, CharRange(#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;
end;
From Indy.
Anyway Indy is not working properly so YOU NEED TO SEE THIS ARTICLE:
http://marc.durdin.net/2012/07/indy-tiduri-pathencode-urlencode-and-paramsencode-and-more/
TIdUri or HTTPEncode has problems with unicode charactersets. Function below will do correct encoding for you.
function EncodeURIComponent(const ASrc: string): UTF8String;
const
HexMap: UTF8String = '0123456789ABCDEF';
function IsSafeChar(ch: Integer): Boolean;
begin
if (ch >= 48) and (ch <= 57) then Result := True // 0-9
else if (ch >= 65) and (ch <= 90) then Result := True // A-Z
else if (ch >= 97) and (ch <= 122) then Result := True // a-z
else if (ch = 33) then Result := True // !
else if (ch >= 39) and (ch <= 42) then Result := True // '()*
else if (ch >= 45) and (ch <= 46) then Result := True // -.
else if (ch = 95) then Result := True // _
else if (ch = 126) then Result := True // ~
else Result := False;
end;
var
I, J: Integer;
ASrcUTF8: UTF8String;
begin
Result := ''; {Do not Localize}
ASrcUTF8 := UTF8Encode(ASrc);
// UTF8Encode call not strictly necessary but
// prevents implicit conversion warning
I := 1; J := 1;
SetLength(Result, Length(ASrcUTF8) * 3); // space to %xx encode every byte
while I <= Length(ASrcUTF8) do
begin
if IsSafeChar(Ord(ASrcUTF8[I])) then
begin
Result[J] := ASrcUTF8[I];
Inc(J);
end
else if ASrcUTF8[I] = ' ' then
begin
Result[J] := '+';
Inc(J);
end
else
begin
Result[J] := '%';
Result[J+1] := HexMap[(Ord(ASrcUTF8[I]) shr 4) + 1];
Result[J+2] := HexMap[(Ord(ASrcUTF8[I]) and 15) + 1];
Inc(J,3);
end;
Inc(I);
end;
SetLength(Result, J-1);
end;
AFAIK you need to make your own.
Here is an example.