Bueno, como alternativa a Indy podemos usar Wininet. Podemos hacer Get, podemos hacer Post y maneja las cookies perfectamente incluso las de sesión. No tengo nada en contra de las Indy, es solo por dar alternativas, además no se pueden usar en el Turbo
, aunque eso no es culpa suya.
Bueno, un poco de código para animar la cosa:
Código Delphi
[-]
uses Windows, SysUtils, Classes,Wininet;
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:= '';
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;
function Get(Url: string; Stream: TStream): Boolean;
var
hNet: HINTERNET;
hUrl: HINTERNET;
Buffer: array[0..10240] of Char;
BytesRead: Cardinal;
begin
Result:= FALSE;
hNet:= InternetOpen('Agente', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
if (hNet <> nil) then
begin
hUrl:= InternetOpenUrl(hNet, PChar(Url), nil, 0,
INTERNET_FLAG_RELOAD, 0);
if (hUrl <> nil) then
begin
while (InternetReadFile(hUrl, @Buffer, sizeof(Buffer), BytesRead)) do
begin
if (BytesRead = 0) then
begin
Result:= TRUE;
break;
end;
Stream.Write(Buffer,BytesRead);
end;
InternetCloseHandle(hUrl);
end;
InternetCloseHandle(hNet);
end;
end;
function Post(Servidor, Pagina: string; Puerto: Word;
PostStrings: TStringList; Stream: TStream): Boolean;
var
hNet: HINTERNET;
hCon: HINTERNET;
hReq: HINTERNET;
Context: DWORD;
Str: string;
i: integer;
Buffer: array[0..10240] of Char;
BytesRead: DWORD;
begin
Context:= 0;
Result := FALSE;
Str:= '';
hNet := InternetOpen('Agente', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
if (hNet <> nil) then
begin
hCon:= InternetConnect(hNet,PChar(Servidor),Puerto,nil,nil,
INTERNET_SERVICE_HTTP,0,Context);
if (hCon <> nil) then
begin
hReq:= HttpOpenRequest(hCon,'POST',PChar(Pagina),nil,nil,nil,
INTERNET_FLAG_RELOAD,Context);
if (hReq <> nil) then
begin
for i:= 0 to PostStrings.Count - 1 do
begin
Str:= Str + '&' + URLEncode(PostStrings.Names[i]) + '=' +
URLEncode(PostStrings.ValueFromIndex[i]);
end;
Delete(Str,1,1);
try
if HttpSendRequest(hReq,
'Content-Type: application/x-www-form-urlencoded',Cardinal(-1),
PChar(Str),Length(Str)) then
begin
while (InternetReadFile(hReq,@Buffer,sizeof(Buffer),BytesRead)) do
begin
if (BytesRead = 0) then
begin
Result := TRUE;
break;
end;
Stream.Write(Buffer,BytesRead);
end;
end;
except end;
InternetCloseHandle(hReq);
end;
InternetCloseHandle(hCon);
end;
InternetCloseHandle(hNet);
end;
end;
Ahora que ya podemos hacer Get y Post solo nos falta analizar las paginas que obtenemos
¿voy por buen camino?
EDITO:
Modifico la función
Post para incluir la cabecera Content-Type, que al parecer es necesaria, al menos para el siguiente ejemplo:
Entrar al ClubDelphi, iniciar sesión y obtener la pagina principal de los foros:
Código Delphi
[-]
procedure Ejemplo;
var
Campos: TStringlist;
Stream: TMemoryStream;
begin
Campos:= TStringList.Create;
Stream:= TMemoryStream.Create;
try
Campos.Values['vb_login_username']:= 'usuario';
Campos.Values['vb_login_password']:= 'password';
Campos.Values['submit']:= 'Ingresar';
Campos.Values['s']:= '';
Campos.Values['do']:= 'login';
Post('www.clubdelphi.com','/foros/login.php',80,Campos,Stream);
Stream.Clear;
Get('http://www.clubdelphi.com/foros/',Stream);
Stream.SaveToFile('d:\1.txt');
finally
Campos.Free;
Stream.Free;
end;
end;