197 lines
4.9 KiB
Plaintext
197 lines
4.9 KiB
Plaintext
|
unit httpprothandler;
|
||
|
interface
|
||
|
{$IFDEF FPC}
|
||
|
{$mode delphi}{$H+}
|
||
|
{$ENDIF}
|
||
|
{$ifdef unix}
|
||
|
{$define usezlib}
|
||
|
{$define useopenssl}
|
||
|
{$endif}
|
||
|
{$IFDEF POSIX}
|
||
|
{$define usezlib}
|
||
|
{$define useopenssl}
|
||
|
{$ENDIF}
|
||
|
{$ifdef win32}
|
||
|
{$define usezlib}
|
||
|
{$define useopenssl}
|
||
|
{$endif}
|
||
|
{$ifdef win64}
|
||
|
{$define usezlib}
|
||
|
{$define useopenssl}
|
||
|
{$endif}
|
||
|
|
||
|
uses
|
||
|
{$IFNDEF NO_HTTP}
|
||
|
{$ifdef usezlib}
|
||
|
IdCompressorZLib, //for deflate and gzip content encoding
|
||
|
{$endif}
|
||
|
IdAuthenticationDigest, //MD5-Digest authentication
|
||
|
{$ifdef useopenssl}
|
||
|
IdSSLOpenSSL, //ssl
|
||
|
IdAuthenticationNTLM, //NTLM - uses OpenSSL libraries
|
||
|
{$endif}
|
||
|
Classes, SysUtils,
|
||
|
IdHTTPHeaderInfo, //for HTTP request and response info.
|
||
|
IdHTTP,
|
||
|
{$ENDIF}
|
||
|
prothandler,
|
||
|
IdURI;
|
||
|
|
||
|
type
|
||
|
THTTPProtHandler = class(TProtHandler)
|
||
|
protected
|
||
|
{$IFNDEF NO_HTTP}
|
||
|
function GetTargetFileName(AHTTP : TIdHTTP; AURI : TIdURI) : String;
|
||
|
{$ENDIF}
|
||
|
public
|
||
|
class function CanHandleURL(AURL : TIdURI) : Boolean; override;
|
||
|
procedure GetFile(AURL : TIdURI); override;
|
||
|
end;
|
||
|
|
||
|
implementation
|
||
|
|
||
|
class function THTTPProtHandler.CanHandleURL(AURL : TIdURI) : Boolean;
|
||
|
begin
|
||
|
{$IFNDEF NO_HTTP}
|
||
|
Result := UpperCase(AURL.Protocol)='HTTP';
|
||
|
{$ifdef useopenssl}
|
||
|
if not Result then
|
||
|
begin
|
||
|
Result := UpperCase(AURL.Protocol)='HTTPS';
|
||
|
end;
|
||
|
{$endif}
|
||
|
{$ELSE}
|
||
|
Result := False;
|
||
|
{$ENDIF}
|
||
|
end;
|
||
|
|
||
|
procedure THTTPProtHandler.GetFile(AURL : TIdURI);
|
||
|
{$IFNDEF NO_HTTP}
|
||
|
var
|
||
|
{$ifdef useopenssl}
|
||
|
LIO : TIdSSLIOHandlerSocketOpenSSL;
|
||
|
{$endif}
|
||
|
LHTTP : TIdHTTP;
|
||
|
LStr : TMemoryStream;
|
||
|
i : Integer;
|
||
|
LHE : EIdHTTPProtocolException;
|
||
|
LFName : String;
|
||
|
{$ifdef usezlib}
|
||
|
LC : TIdCompressorZLib;
|
||
|
{$endif}
|
||
|
begin
|
||
|
{$ifdef useopenssl}
|
||
|
LIO := TIdSSLIOHandlerSocketOpenSSL.Create;
|
||
|
{$endif}
|
||
|
{$ifdef usezlib}
|
||
|
LC := TIdCompressorZLib.Create;
|
||
|
{$endif}
|
||
|
try
|
||
|
LHTTP := TIdHTTP.Create;
|
||
|
try
|
||
|
{$ifdef useopenssl}
|
||
|
LHTTP.Compressor := LC;
|
||
|
{$endif}
|
||
|
//set to false if you want this to simply raise an exception on redirects
|
||
|
LHTTP.HandleRedirects := True;
|
||
|
{
|
||
|
Note that you probably should set the UserAgent because some servers now screen out requests from
|
||
|
our default string "Mozilla/3.0 (compatible; Indy Library)" to prevent address harvesters
|
||
|
and Denial of Service attacks. SOme people have used Indy for these.
|
||
|
|
||
|
Note that you do need a Mozilla string for the UserAgent property. The format is like this:
|
||
|
|
||
|
Mozilla/4.0 (compatible; MyProgram)
|
||
|
}
|
||
|
LHTTP.Request.UserAgent := 'Mozilla/4.0 (compatible; httpget)';
|
||
|
LStr := TMemoryStream.Create;
|
||
|
{$ifdef useopenssl}
|
||
|
LHTTP.IOHandler := LIO;
|
||
|
{$endif}
|
||
|
for i := 0 to LHTTP.Request.RawHeaders.Count -1 do
|
||
|
begin
|
||
|
FLogData.Add(LHTTP.Request.RawHeaders[i]);
|
||
|
if FVerbose then
|
||
|
begin
|
||
|
WriteLn({$IFDEF FPC}stdout{$ELSE}output{$ENDIF},LHTTP.Request.RawHeaders[i]);
|
||
|
end;
|
||
|
end;
|
||
|
LHTTP.Get(AURL.URI,LStr);
|
||
|
for i := 0 to LHTTP.Response.RawHeaders.Count -1 do
|
||
|
begin
|
||
|
FLogData.Add(LHTTP.Response.RawHeaders[i]);
|
||
|
if FVerbose then
|
||
|
begin
|
||
|
WriteLn({$IFDEF FPC}stdout{$ELSE}output{$ENDIF},LHTTP.Response.RawHeaders[i]);
|
||
|
end;
|
||
|
end;
|
||
|
LFName := GetTargetFileName(LHTTP,AURL);
|
||
|
if LFName <> '' then
|
||
|
begin
|
||
|
LStr.SaveToFile(LFName);
|
||
|
end;
|
||
|
|
||
|
except
|
||
|
on E : Exception do
|
||
|
begin
|
||
|
if E is EIdHTTPProtocolException then
|
||
|
begin
|
||
|
LHE := E as EIdHTTPProtocolException;
|
||
|
WriteLn({$IFDEF FPC}stderr{$ELSE}ErrOutput {$ENDIF},'HTTP Protocol Error - '+IntToStr(LHE.ErrorCode));
|
||
|
WriteLn({$IFDEF FPC}stderr{$ELSE}ErrOutput {$ENDIF},LHE.ErrorMessage);
|
||
|
if Verbose = False then
|
||
|
begin
|
||
|
for i := 0 to FLogData.Count -1 do
|
||
|
begin
|
||
|
Writeln({$IFDEF FPC}stderr{$ELSE}ErrOutput {$ENDIF},FLogData[i]);
|
||
|
end;
|
||
|
end;
|
||
|
end
|
||
|
else
|
||
|
begin
|
||
|
Writeln({$IFDEF FPC}stderr{$ELSE}ErrOutput {$ENDIF},E.Message);
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
FreeAndNil(LHTTP);
|
||
|
FreeAndNil(LStr);
|
||
|
finally
|
||
|
{$ifdef useopenssl}
|
||
|
FreeAndNil(LIO);
|
||
|
{$endif}
|
||
|
{$ifdef usezlib}
|
||
|
FreeAndNil(LC);
|
||
|
{$endif}
|
||
|
end;
|
||
|
{$ELSE}
|
||
|
begin
|
||
|
{$ENDIF}
|
||
|
end;
|
||
|
|
||
|
{$IFNDEF NO_HTTP}
|
||
|
function THTTPProtHandler.GetTargetFileName(AHTTP : TIdHTTP; AURI : TIdURI) : String;
|
||
|
|
||
|
begin
|
||
|
{
|
||
|
We do things this way in case the server gave you a specific document type
|
||
|
in response to a request.
|
||
|
|
||
|
eg.
|
||
|
|
||
|
Request: http://www.indyproject.org/
|
||
|
Response: http://www.indyproject.org/index.html
|
||
|
}
|
||
|
if AHTTP.Response.Location <> '' then
|
||
|
begin
|
||
|
AURI.URI := AHTTP.Response.Location;
|
||
|
end;
|
||
|
Result := AURI.Document;
|
||
|
if Result = '' then
|
||
|
begin
|
||
|
Result := 'index.html';
|
||
|
end;
|
||
|
end;
|
||
|
{$ENDIF}
|
||
|
|
||
|
end.
|