pkglnet.pp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. {$mode objfpc}
  2. {$h+}
  3. unit pkglnet;
  4. interface
  5. uses
  6. SysUtils, Classes,
  7. uriparser,
  8. lnet, lftp, lhttp, pkgdownload,pkgoptions, fprepos;
  9. Type
  10. { TLNetDownloader }
  11. TLNetDownloader = Class(TBaseDownloader)
  12. private
  13. FQuit: Boolean;
  14. FFTP: TLFTPClient;
  15. FHTTP: TLHTTPClient;
  16. FOutStream: TStream;
  17. URI: TURI;
  18. protected
  19. // callbacks
  20. function OnHttpClientInput(ASocket: TLHTTPClientSocket; ABuffer: pchar;
  21. ASize: Integer): Integer;
  22. procedure OnLNetDisconnect(aSocket: TLSocket);
  23. procedure OnHttpDoneInput(aSocket: TLHTTPClientSocket);
  24. procedure OnLNetError(const msg: string; aSocket: TLSocket);
  25. procedure OnFTPControl(aSocket: TLSocket);
  26. procedure OnFTPReceive(aSocket: TLSocket);
  27. procedure OnFTPSuccess(aSocket: TLSocket; const aStatus: TLFTPStatus);
  28. procedure OnFTPFailure(aSocket: TLSocket; const aStatus: TLFTPStatus);
  29. // overrides
  30. function FTPDownload(Const URL : String; Dest : TStream): Boolean; override;
  31. function HTTPDownload(Const URL: String; Dest: TStream): Boolean; override;
  32. public
  33. constructor Create(AOwner : TComponent); override;
  34. end;
  35. implementation
  36. uses
  37. pkgglobals,
  38. pkgmessages;
  39. { TLNetDownloader }
  40. function TLNetDownloader.OnHttpClientInput(ASocket: TLHTTPClientSocket;
  41. ABuffer: pchar; ASize: Integer): Integer;
  42. begin
  43. Result:=FOutStream.Write(aBuffer[0], aSize);
  44. end;
  45. procedure TLNetDownloader.OnLNetDisconnect(aSocket: TLSocket);
  46. begin
  47. FQuit:=True;
  48. end;
  49. procedure TLNetDownloader.OnHttpDoneInput(aSocket: TLHTTPClientSocket);
  50. begin
  51. ASocket.Disconnect;
  52. FQuit:=True;
  53. end;
  54. procedure TLNetDownloader.OnLNetError(const msg: string; aSocket: TLSocket);
  55. begin
  56. Error(msg);
  57. FQuit:=True;
  58. end;
  59. procedure TLNetDownloader.OnFTPControl(aSocket: TLSocket);
  60. var
  61. s: string;
  62. begin
  63. FFTP.GetMessage(s); // have to empty OS buffer, write the info if you wish to debug
  64. end;
  65. procedure TLNetDownloader.OnFTPReceive(aSocket: TLSocket);
  66. const
  67. BUF_SIZE = 65536; // standard OS recv buffer size
  68. var
  69. Buf: array[1..BUF_SIZE] of Byte;
  70. begin
  71. FOutStream.Write(Buf[1], FFTP.GetData(Buf[1], BUF_SIZE));
  72. end;
  73. procedure TLNetDownloader.OnFTPSuccess(aSocket: TLSocket;
  74. const aStatus: TLFTPStatus);
  75. begin
  76. FFTP.Disconnect;
  77. FQuit:=True;
  78. end;
  79. procedure TLNetDownloader.OnFTPFailure(aSocket: TLSocket;
  80. const aStatus: TLFTPStatus);
  81. begin
  82. FFTP.Disconnect;
  83. Error(SErrDownloadFailed,['FTP',EncodeURI(URI),'']);
  84. FQuit:=True;
  85. end;
  86. function TLNetDownloader.FTPDownload(Const URL: String; Dest: TStream): Boolean;
  87. begin
  88. Result := False;
  89. FOutStream:=Dest;
  90. Try
  91. { parse URL }
  92. URI:=ParseURI(URL);
  93. if URI.Port = 0 then
  94. URI.Port := 21;
  95. FFTP.Connect(URI.Host, URI.Port);
  96. while not FFTP.Connected and not FQuit do
  97. FFTP.CallAction;
  98. if not FQuit then begin
  99. Result := FFTP.Authenticate(URI.Username, URI.Password);
  100. if Result then
  101. Result := FFTP.ChangeDirectory(URI.Path);
  102. if Result then
  103. Result := FFTP.Retrieve(URI.Document);
  104. while not FQuit do
  105. FFTP.CallAction;
  106. end;
  107. finally
  108. FOutStream:=nil;
  109. end;
  110. end;
  111. function TLNetDownloader.HTTPDownload(Const URL: String; Dest: TStream): Boolean;
  112. begin
  113. Result := False;
  114. FOutStream:=Dest;
  115. Try
  116. { parse aURL }
  117. URI := ParseURI(URL);
  118. if URI.Port = 0 then
  119. URI.Port := 80;
  120. FHTTP.Host := URI.Host;
  121. FHTTP.Method := hmGet;
  122. FHTTP.Port := URI.Port;
  123. FHTTP.URI := URI.Path + URI.Document;
  124. FHTTP.SendRequest;
  125. FQuit:=False;
  126. while not FQuit do
  127. FHTTP.CallAction;
  128. if FHTTP.Response.Status<>HSOK then
  129. Error(SErrDownloadFailed,['HTTP',EncodeURI(URI),FHTTP.Response.Reason])
  130. else
  131. Result := True;
  132. Finally
  133. FOutStream:=nil; // to be sure
  134. end;
  135. end;
  136. constructor TLNetDownloader.Create(AOwner: TComponent);
  137. begin
  138. inherited;
  139. FFTP:=TLFTPClient.Create(Self);
  140. FFTP.Timeout:=1000;
  141. FFTP.StatusSet:=[fsRetr]; // watch for success/failure of retreives only
  142. FFTP.OnError:=@OnLNetError;
  143. FFTP.OnControl:=@OnFTPControl;
  144. FFTP.OnReceive:=@OnFTPReceive;
  145. FFTP.OnSuccess:=@OnFTPSuccess;
  146. FFTP.OnFailure:=@OnFTPFailure;
  147. FHTTP:=TLHTTPClient.Create(Self);
  148. FHTTP.Timeout := 1000; // go by 1s times if nothing happens
  149. FHTTP.OnDisconnect := @OnLNetDisconnect;
  150. FHTTP.OnDoneInput := @OnHttpDoneInput;
  151. FHTTP.OnError := @OnLNetError;
  152. FHTTP.OnInput := @OnHttpClientInput;
  153. end;
  154. initialization
  155. RegisterDownloader('lnet',TLNetDownloader);
  156. end.