mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-07 06:08:22 +02:00
185 lines
4.3 KiB
ObjectPascal
185 lines
4.3 KiB
ObjectPascal
{$mode objfpc}
|
|
{$h+}
|
|
unit pkglnet;
|
|
|
|
interface
|
|
|
|
uses
|
|
SysUtils, Classes,
|
|
uriparser,
|
|
lnet, lftp, lhttp, pkgdownload,pkgoptions, fprepos;
|
|
|
|
Type
|
|
|
|
{ TLNetDownloader }
|
|
|
|
TLNetDownloader = Class(TBaseDownloader)
|
|
private
|
|
FQuit: Boolean;
|
|
FFTP: TLFTPClient;
|
|
FHTTP: TLHTTPClient;
|
|
FOutStream: TStream;
|
|
URI: TURI;
|
|
protected
|
|
// callbacks
|
|
function OnHttpClientInput(ASocket: TLHTTPClientSocket; ABuffer: pchar;
|
|
ASize: Integer): Integer;
|
|
procedure OnLNetDisconnect(aSocket: TLSocket);
|
|
procedure OnHttpDoneInput(aSocket: TLHTTPClientSocket);
|
|
procedure OnLNetError(const msg: string; aSocket: TLSocket);
|
|
procedure OnFTPControl(aSocket: TLSocket);
|
|
procedure OnFTPReceive(aSocket: TLSocket);
|
|
procedure OnFTPSuccess(aSocket: TLSocket; const aStatus: TLFTPStatus);
|
|
procedure OnFTPFailure(aSocket: TLSocket; const aStatus: TLFTPStatus);
|
|
// overrides
|
|
function FTPDownload(Const URL : String; Dest : TStream): Boolean; override;
|
|
function HTTPDownload(Const URL: String; Dest: TStream): Boolean; override;
|
|
public
|
|
constructor Create(AOwner : TComponent); override;
|
|
end;
|
|
|
|
implementation
|
|
|
|
uses
|
|
pkgglobals,
|
|
pkgmessages;
|
|
|
|
{ TLNetDownloader }
|
|
|
|
function TLNetDownloader.OnHttpClientInput(ASocket: TLHTTPClientSocket;
|
|
ABuffer: pchar; ASize: Integer): Integer;
|
|
begin
|
|
Result:=FOutStream.Write(aBuffer[0], aSize);
|
|
end;
|
|
|
|
procedure TLNetDownloader.OnLNetDisconnect(aSocket: TLSocket);
|
|
begin
|
|
FQuit:=True;
|
|
end;
|
|
|
|
procedure TLNetDownloader.OnHttpDoneInput(aSocket: TLHTTPClientSocket);
|
|
begin
|
|
ASocket.Disconnect;
|
|
FQuit:=True;
|
|
end;
|
|
|
|
procedure TLNetDownloader.OnLNetError(const msg: string; aSocket: TLSocket);
|
|
begin
|
|
Error(msg);
|
|
FQuit:=True;
|
|
end;
|
|
|
|
procedure TLNetDownloader.OnFTPControl(aSocket: TLSocket);
|
|
var
|
|
s: string;
|
|
begin
|
|
FFTP.GetMessage(s); // have to empty OS buffer, write the info if you wish to debug
|
|
end;
|
|
|
|
procedure TLNetDownloader.OnFTPReceive(aSocket: TLSocket);
|
|
const
|
|
BUF_SIZE = 65536; // standard OS recv buffer size
|
|
var
|
|
Buf: array[1..BUF_SIZE] of Byte;
|
|
begin
|
|
FOutStream.Write(Buf[1], FFTP.GetData(Buf[1], BUF_SIZE));
|
|
end;
|
|
|
|
procedure TLNetDownloader.OnFTPSuccess(aSocket: TLSocket;
|
|
const aStatus: TLFTPStatus);
|
|
begin
|
|
FFTP.Disconnect;
|
|
FQuit:=True;
|
|
end;
|
|
|
|
procedure TLNetDownloader.OnFTPFailure(aSocket: TLSocket;
|
|
const aStatus: TLFTPStatus);
|
|
begin
|
|
FFTP.Disconnect;
|
|
Error(SErrDownloadFailed,['FTP',EncodeURI(URI),'']);
|
|
FQuit:=True;
|
|
end;
|
|
|
|
function TLNetDownloader.FTPDownload(Const URL: String; Dest: TStream): Boolean;
|
|
begin
|
|
Result := False;
|
|
FOutStream:=Dest;
|
|
Try
|
|
{ parse URL }
|
|
URI:=ParseURI(URL);
|
|
|
|
if URI.Port = 0 then
|
|
URI.Port := 21;
|
|
|
|
FFTP.Connect(URI.Host, URI.Port);
|
|
while not FFTP.Connected and not FQuit do
|
|
FFTP.CallAction;
|
|
|
|
if not FQuit then begin
|
|
Result := FFTP.Authenticate(URI.Username, URI.Password);
|
|
if Result then
|
|
Result := FFTP.ChangeDirectory(URI.Path);
|
|
if Result then
|
|
Result := FFTP.Retrieve(URI.Document);
|
|
while not FQuit do
|
|
FFTP.CallAction;
|
|
end;
|
|
finally
|
|
FOutStream:=nil;
|
|
end;
|
|
end;
|
|
|
|
function TLNetDownloader.HTTPDownload(Const URL: String; Dest: TStream): Boolean;
|
|
begin
|
|
Result := False;
|
|
FOutStream:=Dest;
|
|
Try
|
|
{ parse aURL }
|
|
URI := ParseURI(URL);
|
|
|
|
if URI.Port = 0 then
|
|
URI.Port := 80;
|
|
|
|
FHTTP.Host := URI.Host;
|
|
FHTTP.Method := hmGet;
|
|
FHTTP.Port := URI.Port;
|
|
FHTTP.URI := URI.Path + URI.Document;
|
|
FHTTP.SendRequest;
|
|
|
|
FQuit:=False;
|
|
while not FQuit do
|
|
FHTTP.CallAction;
|
|
if FHTTP.Response.Status<>HSOK then
|
|
Error(SErrDownloadFailed,['HTTP',EncodeURI(URI),FHTTP.Response.Reason])
|
|
else
|
|
Result := True;
|
|
Finally
|
|
FOutStream:=nil; // to be sure
|
|
end;
|
|
end;
|
|
|
|
constructor TLNetDownloader.Create(AOwner: TComponent);
|
|
begin
|
|
inherited;
|
|
|
|
FFTP:=TLFTPClient.Create(Self);
|
|
FFTP.Timeout:=1000;
|
|
FFTP.StatusSet:=[fsRetr]; // watch for success/failure of retreives only
|
|
FFTP.OnError:=@OnLNetError;
|
|
FFTP.OnControl:=@OnFTPControl;
|
|
FFTP.OnReceive:=@OnFTPReceive;
|
|
FFTP.OnSuccess:=@OnFTPSuccess;
|
|
FFTP.OnFailure:=@OnFTPFailure;
|
|
|
|
FHTTP:=TLHTTPClient.Create(Self);
|
|
FHTTP.Timeout := 1000; // go by 1s times if nothing happens
|
|
FHTTP.OnDisconnect := @OnLNetDisconnect;
|
|
FHTTP.OnDoneInput := @OnHttpDoneInput;
|
|
FHTTP.OnError := @OnLNetError;
|
|
FHTTP.OnInput := @OnHttpClientInput;
|
|
end;
|
|
|
|
initialization
|
|
RegisterDownloader('lnet',TLNetDownloader);
|
|
end.
|