Url encode / decode

Hoy comienzo con una serie de funciones destinadas a montar un pequeño servidor web. Y cuando digo pequeño, me refiero a que sera pequeño de verdad, menos de 100kb. Pero vamos a ir poco a poco, las dos primeras funciones que vamos a ver son URLEncode y URLDecode. Estas funciones permiten codificar una cadena de texto según se describe en RFC 1738, es decir, los caracteres no alfanuméricos son sustituidos por el símbolo % seguido de dos números hexadecimales.

function URLEncode(Str: string): string;
var
  i: integer;
begin
  Result:= '';
  for i:= 1 to Length(Str) do
    if Str[i] in ['A'..'Z','a'..'z','0'..'9','-','_','.'] then
      Result:= Result + Str[ i ]
    else
      Result:= Result + '%' + IntToHex(Ord(Str[ i ]),2);
end;
 
function URLDecode(Str: string): string;
var
  i: integer;
begin
  Result:= '';
  while Length(Str) > 0 do
  begin
    if Copy(Str, 1, 1) = '%' then
    begin
      if not TryStrToInt('$' + Copy(Str, 2, 2),i) then
      begin
        Result:= '';
        Exit;
      end;
      Result:= Result + Char(i);
      Delete(Str, 1, 2);
    end else Result:= Result + Copy(Str, 1, 1);
    Delete(Str,1,1);
  end;
end;

Por razones historicas a veces se sigue utilizando el caractrer '+' para sustituir los espacio en blanco en vez de utilizar '%20' como dice el estandar. Si queremos seguir usando esta forma utilizaremos algo como esto:

function URLEncode(Str: string): string;
var
  i: integer;
begin
  Result:= '';
  for i:= 1 to Length(Str) do
    if Str[ i ] in ['A'..'Z','a'..'z','0'..'9','-','_','.'] then
      Result:= Result + Str[i]
    else if Str[ i ] = ' ' then
      Result:= Result + '+'
    else
      Result:= Result + '%' + IntToHex(Ord(Str[ i ]),2);
end;
 
function URLDecode(Str: string): string;
var
  i: integer;
begin
  Result:= '';
  Str:= StringReplace(Str, '+', ' ', [rfReplaceAll]);
  while Length(Str) > 0 do
  begin
    if Copy(Str, 1, 1) = '%' then
    begin
      if not TryStrToInt('$' + Copy(Str, 2, 2),i) then
      begin
        Result:= '';
        Exit;
      end;
      Result:= Result + Char(i);
      Delete(Str, 1, 2);
    end else Result:= Result + Copy(Str, 1, 1);
    Delete(Str,1,1);
  end;
end;

Por razones obvias, cuando montemos nuestro servidor codificaremos las cadenas ajustándonos al estándar, pero, por compatibilidad, a la hora de descodificar tendremos en cuenta el símbolo '+'.