pkgdownload.pp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. {
  2. This file is part of the fppkg package manager
  3. Copyright (c) 1999-2022 by the Free Pascal development team
  4. See the file COPYING.FPC, included in this distribution,
  5. for details about the copyright.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. **********************************************************************}
  10. unit pkgDownload;
  11. {$mode objfpc}{$H+}
  12. interface
  13. uses
  14. Classes, SysUtils, pkghandler, pkgFppkg;
  15. Type
  16. { TBaseDownloader }
  17. TBaseDownloader = Class(TComponent)
  18. Private
  19. FBackupFile : Boolean;
  20. Protected
  21. // Needs overriding.
  22. function FTPDownload(Const URL : String; Dest : TStream): Boolean; Virtual;
  23. function HTTPDownload(Const URL : String; Dest : TStream): Boolean; Virtual;
  24. function FileDownload(Const URL : String; Dest : TStream): Boolean; Virtual;
  25. Public
  26. function Download(Const URL,DestFileName : String): Boolean;
  27. function Download(Const URL : String; Dest : TStream): Boolean;
  28. Property BackupFiles : Boolean Read FBackupFile Write FBackupFile;
  29. end;
  30. TBaseDownloaderClass = Class of TBaseDownloader;
  31. { TDownloadPackage }
  32. TDownloadPackage = Class(TPackagehandler)
  33. Public
  34. function Execute: Boolean;override;
  35. end;
  36. procedure RegisterDownloader(const AName:string;Downloaderclass:TBaseDownloaderClass);
  37. function GetDownloader(const AName:string):TBaseDownloaderClass;
  38. function DownloadFile(const RemoteFile,LocalFile:String; PackageManager: TpkgFPpkg): Boolean;
  39. implementation
  40. uses
  41. contnrs,
  42. uriparser,
  43. fprepos,
  44. pkgglobals,
  45. pkgoptions,
  46. pkgmessages,
  47. pkgrepos;
  48. var
  49. DownloaderList : TFPHashList;
  50. procedure RegisterDownloader(const AName:string;Downloaderclass:TBaseDownloaderClass);
  51. begin
  52. if DownloaderList.Find(AName)<>nil then
  53. begin
  54. Error('Downloader already registered');
  55. exit;
  56. end;
  57. DownloaderList.Add(AName,Downloaderclass);
  58. end;
  59. function GetDownloader(const AName:string):TBaseDownloaderClass;
  60. begin
  61. result:=TBaseDownloaderClass(DownloaderList.Find(AName));
  62. if result=nil then
  63. Error('Downloader %s not supported',[AName]);
  64. end;
  65. function DownloadFile(const RemoteFile,LocalFile:String; PackageManager: TpkgFPpkg): Boolean;
  66. var
  67. DownloaderClass : TBaseDownloaderClass;
  68. begin
  69. DownloaderClass:=GetDownloader(PackageManager.Options.GlobalSection.Downloader);
  70. with DownloaderClass.Create(nil) do
  71. try
  72. Result := Download(RemoteFile,LocalFile);
  73. finally
  74. Free;
  75. end;
  76. end;
  77. { TBaseDownloader }
  78. function TBaseDownloader.FTPDownload(Const URL: String; Dest: TStream): Boolean;
  79. begin
  80. Error(SErrNoFTPDownload);
  81. Result := False;
  82. end;
  83. function TBaseDownloader.HTTPDownload(Const URL: String; Dest: TStream): Boolean;
  84. begin
  85. Error(SErrNoHTTPDownload);
  86. Result := False;
  87. end;
  88. function TBaseDownloader.FileDownload(Const URL: String; Dest: TStream): Boolean;
  89. Var
  90. FN : String;
  91. F : TFileStream;
  92. begin
  93. Result := False;
  94. URIToFilename(URL,FN);
  95. If Not FileExists(FN) then
  96. Error(SErrNoSuchFile,[FN]);
  97. F:=TFileStream.Create(FN,fmOpenRead);
  98. Try
  99. Dest.CopyFrom(F,0);
  100. Result := True;
  101. Finally
  102. F.Free;
  103. end;
  104. end;
  105. function TBaseDownloader.Download(Const URL, DestFileName: String): Boolean;
  106. Var
  107. F : TFileStream;
  108. begin
  109. Result := False;
  110. If FileExists(DestFileName) and BackupFiles then
  111. BackupFile(DestFileName);
  112. try
  113. F:=TFileStream.Create(DestFileName,fmCreate);
  114. try
  115. Result := Download(URL,F);
  116. finally
  117. F.Free;
  118. end;
  119. finally
  120. if not Result then
  121. DeleteFile(DestFileName);
  122. end;
  123. end;
  124. function TBaseDownloader.Download(Const URL: String; Dest: TStream): Boolean;
  125. Var
  126. URI : TURI;
  127. P : String;
  128. begin
  129. Result := False;
  130. URI:=ParseURI(URL);
  131. P:=URI.Protocol;
  132. If CompareText(P,'ftp')=0 then
  133. Result := FTPDownload(URL,Dest)
  134. else if (CompareText(P,'http')=0) or (CompareText(P,'https')=0) then
  135. Result := HTTPDownload(URL,Dest)
  136. else if CompareText(P,'file')=0 then
  137. Result := FileDownload(URL,Dest)
  138. else
  139. begin
  140. Error(SErrUnknownProtocol,[P, URL]);
  141. Result := False;
  142. end;
  143. end;
  144. { TDownloadPackage }
  145. function TDownloadPackage.Execute: Boolean;
  146. var
  147. DownloaderClass : TBaseDownloaderClass;
  148. P : TFPPackage;
  149. RemoteArchive: string;
  150. begin
  151. Result := False;
  152. P:=PackageManager.PackageByName(PackageName, pkgpkAvailable);
  153. DownloaderClass:=GetDownloader(PackageManager.Options.GlobalSection.Downloader);
  154. if Assigned(DownloaderClass) then
  155. begin
  156. with DownloaderClass.Create(nil) do
  157. try
  158. RemoteArchive := PackageManager.PackageRemoteArchive(P);
  159. if RemoteArchive <> '' then
  160. begin
  161. Log(llCommands,SLogDownloading,[RemoteArchive,PackageManager.PackageLocalArchive(P)]);
  162. pkgglobals.log(llProgress,SProgrDownloadPackage,[P.Name, P.Version.AsString]);
  163. // Force the existing of the archives-directory if it is being used
  164. if (P.Name<>CurrentDirPackageName) and (P.Name<>CmdLinePackageName) then
  165. ForceDirectories(PackageManager.Options.GlobalSection.ArchivesDir);
  166. Download(RemoteArchive,PackageManager.PackageLocalArchive(P));
  167. Result := True;
  168. end
  169. else
  170. Error(SErrDownloadPackageFailed);
  171. finally
  172. Free;
  173. end;
  174. end;
  175. end;
  176. initialization
  177. DownloaderList:=TFPHashList.Create;
  178. RegisterDownloader('base',TBaseDownloader);
  179. RegisterPkgHandler('downloadpackage',TDownloadPackage);
  180. finalization
  181. FreeAndNil(DownloaderList);
  182. end.