resourcezipper.pas 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. unit resourcezipper;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils, zipper;
  6. type
  7. { TResourceZipper }
  8. TResourceZipper = class(TObject)
  9. private
  10. FZipDir: string; {Includes trailing dir separator}
  11. FTargetExecutable: string;
  12. FZipSourceDir: string;
  13. { Indicates whether the resource zip has been written yet }
  14. FCheckRideZipWritten: boolean;
  15. FCheckRideHelperZipWritten: boolean;
  16. { Add file to zip; strip out path part }
  17. procedure AddToZip(var Zip: TZipper; const FileName: string);
  18. procedure SetOutputDirectory(Value: string);
  19. procedure SetOutputFiles;
  20. procedure SetZipSourceDir(AValue: string);
  21. public
  22. { Directory where zip will be written }
  23. property ZipDirectory: string read FZipDir write Setoutputdirectory;
  24. { Executable where resource will be written/read }
  25. property Executable: string read FTargetExecutable write FTargetExecutable;
  26. { Write out helped resource to Executable, overwriting any resources present }
  27. procedure WriteCheckRideResource;
  28. { Write out helper resource to Executable, overwriting any resources present }
  29. procedure WriteCheckRideHelperResource;
  30. { Write out CheckRide zip for inclusion in resources etc. }
  31. procedure WriteCheckRideZip;
  32. { Write out CheckRide helper zip for inclusion in resources etc. }
  33. procedure WriteCheckRideHelperZip;
  34. { Directory where source files of resource zip are located. Can be empty for current dir.}
  35. property ZipSourceDir: string read FZipSourceDir write SetZipSourceDir;
  36. constructor Create;
  37. destructor Destroy; override;
  38. end;
  39. implementation
  40. uses poormansresource, checkrideutil;
  41. const
  42. HelpedResourceName = 'helped.zip';
  43. HelperResourceName = 'helper.zip';
  44. var
  45. FHelpedResourceZip: string; //Zip file with resource for helped program (CheckRide)
  46. FHelperResourceZip: string;
  47. //Zip file with resource for helper program (CheckRideHelper)
  48. procedure Tresourcezipper.Setoutputdirectory(Value: string);
  49. begin
  50. FZipDir := Value;
  51. if (RightStr(FZipDir, 1) <> DirectorySeparator) and (Value <> EmptyStr) then
  52. begin
  53. FZipDir := FZipDir + DirectorySeparator;
  54. end;
  55. Setoutputfiles;
  56. end;
  57. procedure TResourceZipper.AddToZip(var Zip: TZipper;
  58. const FileName: string);
  59. begin
  60. if FileExists(FileName)=false then
  61. begin
  62. {$IFDEF CONSOLE}
  63. writeln('Error adding '+FileName+' to zip file. Could not find file.');
  64. {$ENDIF CONSOLE}
  65. raise Exception.Create('Cannot find file');
  66. end;
  67. Zip.Entries.AddFileEntry(FileName, ExtractFileName(FileName));
  68. end;
  69. procedure Tresourcezipper.Setoutputfiles;
  70. begin
  71. FHelpedResourceZip := FZipDir + HelpedResourceName;
  72. FHelperResourceZip := FZipDir + HelperResourceName;
  73. end;
  74. procedure TResourceZipper.SetZipSourceDir(AValue: string);
  75. begin
  76. // Make sure trailing / or \
  77. FZipSourceDir := AValue;
  78. if (RightStr(AValue, 1) <> DirectorySeparator) and (AValue <> EmptyStr) then
  79. begin
  80. FZipSourceDir := AValue + DirectorySeparator;
  81. end;
  82. end;
  83. procedure TResourceZipper.WriteCheckRideHelperResource;
  84. var
  85. Resource: TPayload;
  86. begin
  87. if Executable = EmptyStr then
  88. raise Exception.Create('Executable property is required.');
  89. ;
  90. if FCheckRideHelperZipWritten = False then
  91. WriteCheckRideHelperZip;
  92. Resource := TPayload.Create(Executable);
  93. try
  94. try
  95. Resource.FileIntoPayload(FZipDir + HelperResourceName);
  96. writeln('Wrote resource ' + FZipDir + HelperResourceName + ' to ' + Executable);
  97. except
  98. on E: Exception do
  99. begin
  100. {$IFDEF CONSOLE}
  101. writeln('An error occurred writing CheckRideHelper resource. Technical details: ',
  102. E.ClassName, '/', E.message);
  103. writeln('Resource ' + FZipDir + HelpedResourceName);
  104. writeln('Output exe: ' + Executable);
  105. {$ENDIF CONSOLE}
  106. raise Exception.Create(
  107. 'Error writing CheckRideHelper resource. Technical details: ' +
  108. E.ClassName + '/' + E.message);
  109. halt(1); //stop with error
  110. end;
  111. end;
  112. finally
  113. Resource.Free;
  114. end;
  115. end;
  116. procedure TResourceZipper.WriteCheckRideResource;
  117. var
  118. Resource: TPayload;
  119. begin
  120. if Executable = EmptyStr then
  121. raise Exception.Create('Executable property is required.');
  122. ;
  123. if FCheckRideZipWritten = False then
  124. WriteCheckRideZip;
  125. Resource := TPayload.Create(Executable);
  126. try
  127. try
  128. Resource.FileIntoPayload(FZipDir + HelpedResourceName);
  129. {$IFDEF CONSOLE}
  130. writeln('Wrote resource ' + FZipDir + HelpedResourceName + ' to ' + Executable);
  131. {$ENDIF CONSOLE}
  132. except
  133. on E: Exception do
  134. begin
  135. {$IFDEF CONSOLE}
  136. writeln('An error occurred writing CheckRide resource. Technical details: ',
  137. E.ClassName, '/', E.message);
  138. writeln('Resource ' + FZipDir + HelpedResourceName);
  139. writeln('Output exe: ' + Executable);
  140. {$ENDIF CONSOLE}
  141. raise Exception.Create('Error writing CheckRide resource. Technical details: ' +
  142. E.ClassName + '/' + E.message);
  143. halt(1); //stop with error
  144. end;
  145. end;
  146. finally
  147. Resource.Free;
  148. end;
  149. end;
  150. { TResourceZipper }
  151. procedure Tresourcezipper.WriteCheckRideZip;
  152. var
  153. ExternalDirPrefix: string;
  154. RootDirTrail: string; {Includes trailing directoryseparator}
  155. Zip: TZipper;
  156. begin
  157. RootDirTrail := ZipSourceDir; //May be empty for current path
  158. if DirectoryExists(RootDirTrail + 'external') then
  159. begin
  160. ExternalDirPrefix := RootDirTrail + 'external' + DirectorySeparator;
  161. end
  162. else
  163. begin
  164. ExternalDirPrefix := RootDirTrail;
  165. end;
  166. // Preparation: create output directory, delete existing file.
  167. if trim(FZipDir) <> '' then
  168. try
  169. ForceDirectories(FZipDir);
  170. except
  171. on E: Exception do
  172. begin
  173. {
  174. writeln('Warning: could not create output directory ' + FZipDir);
  175. writeln('Technical details: ',
  176. E.ClassName, '/', E.message);
  177. }
  178. raise; //just pass it on
  179. end;//E: Exception
  180. end;
  181. try
  182. DeleteFile(FHelpedResourceZip);
  183. except
  184. on E: Exception do
  185. begin
  186. writeln('Warning: Could not delete file ' + FHelpedResourceZip);
  187. Writeln('Technical details: ',
  188. E.ClassName, '/', E.message);
  189. end;//E: Exception
  190. end;
  191. // Actual work
  192. Zip := TZipper.Create;
  193. try
  194. try
  195. Zip.FileName := FHelpedResourceZip;
  196. // My build environment has an external directory with dlls/exes. Directory layout in
  197. // CheckRideHelper install dir is flat though
  198. AddToZip(Zip,ExternalDirPrefix+'libeay32.dll');
  199. AddToZip(Zip,ExternalDirPrefix+'sas.dll');
  200. AddToZip(Zip,ExternalDirPrefix+'schook.dll');
  201. AddToZip(Zip,ExternalDirPrefix+'ssleay32.dll');
  202. AddToZip(Zip,ExternalDirPrefix+'stunnel.exe');
  203. AddToZip(Zip,ExternalDirPrefix+'stunnel.pem');
  204. AddToZip(Zip,ExternalDirPrefix+'ultravnc.ini');
  205. //See https://forum.ultravnc.net/viewtopic.php?f=9&t=15864
  206. //we already have schook.dll so presumably that is used, no need for vnchooks.
  207. AddToZip(Zip,ExternalDirPrefix+'winvnc.exe');
  208. AddToZip(Zip,ExternalDirPrefix+'zlib1.dll');
  209. AddToZip(Zip,RootDirTrail+'stunnelhelped.conf.template');
  210. AddToZip(Zip,RootDirTrail+'CheckRide.conf');
  211. if FileExists(RootDirTrail+'..'+DirectorySeparator+'Readme.txt') then
  212. begin
  213. AddToZip(Zip,RootDirTrail+'..'+DirectorySeparator+'Readme.txt');
  214. end
  215. else
  216. begin
  217. // Otherwise assume in current directory.
  218. AddToZip(Zip,RootDirTrail+'Readme.txt');
  219. end;
  220. if FileExists(RootDirTrail+'..'+DirectorySeparator+'License.txt') then
  221. begin
  222. AddToZip(Zip,RootDirTrail+'..'+DirectorySeparator+'License.txt');
  223. end
  224. else
  225. begin
  226. // Otherwise assume in current directory.
  227. AddToZip(Zip,RootDirTrail+'License.txt');
  228. end;
  229. Zip.ZipAllFiles;
  230. {$IFDEF CONSOLE}
  231. writeln('Done writing ' + HelpedResourceName);
  232. {$ENDIF CONSOLE}
  233. except
  234. on E: Exception do
  235. begin
  236. {$IFDEF CONSOLE}
  237. Writeln('Error creating ' + Zip.Filename + '. Details: ',
  238. E.ClassName, '/', E.message);
  239. {$ENDIF CONSOLE}
  240. //Writeln('Fatal error: aborting.');
  241. Halt(1); //Exit status: error.
  242. end;//E: Exception
  243. end;
  244. finally
  245. Zip.Free;
  246. end;
  247. FCheckRideZipWritten := True;
  248. end;
  249. procedure Tresourcezipper.WriteCheckRideHelperZip;
  250. var
  251. RootDirTrail: string; {Includes trailing directoryseparator}
  252. Zip: TZipper;
  253. begin
  254. RootDirTrail := ZipSourceDir; //May be empty for current path
  255. // Preparation: create output directory, delete existing file.
  256. if trim(FZipDir) <> '' then
  257. try
  258. ForceDirectories(FZipDir);
  259. except
  260. on E: Exception do
  261. begin
  262. {$IFDEF CONSOLE}
  263. writeln('Warning: could not create output directory ' + FZipDir);
  264. writeln('Technical details: ',
  265. E.ClassName, '/', E.message);
  266. {$ENDIF CONSOLE}
  267. raise; //just pass it on
  268. end;//E: Exception
  269. end;
  270. try
  271. DeleteFile(FHelperResourceZip);
  272. except
  273. on E: Exception do
  274. begin
  275. {$IFDEF CONSOLE}
  276. writeln('Warning: Could not delete file ' + FHelperResourceZip);
  277. Writeln('Technical details: ',
  278. E.ClassName, '/', E.message);
  279. {$ENDIF CONSOLE}
  280. end;//E: Exception
  281. end;
  282. // Actual work
  283. Zip := TZipper.Create;
  284. try
  285. try
  286. Zip.FileName := FHelperResourceZip;
  287. AddToZip(Zip,RootDirTrail+'stunnelhelper.conf.template');
  288. AddToZip(Zip,RootDirTrail+'CheckRide.conf');
  289. Zip.ZipAllFiles;
  290. writeln('Done writing ' + HelperResourceName);
  291. except
  292. on E: Exception do
  293. begin
  294. Writeln('Error creating ' + Zip.Filename + '. Details: ',
  295. E.ClassName, '/', E.message);
  296. {$IFDEF CONSOLE}
  297. Writeln('Fatal error: aborting.');
  298. {$ENDIF CONSOLE}
  299. Halt(1); //Exit status: error.
  300. end;//E: Exception
  301. end;
  302. finally
  303. Zip.Free;
  304. end;
  305. FCheckRideHelperZipWritten := True;
  306. end;
  307. constructor Tresourcezipper.Create;
  308. begin
  309. FCheckRideHelperZipWritten := False;
  310. FCheckRideZipWritten := False;
  311. FZipDir := EmptyStr;
  312. FTargetExecutable := CheckRideExe; //no path
  313. FZipSourceDir := EmptyStr;
  314. SetOutputFiles;
  315. end;
  316. destructor Tresourcezipper.Destroy;
  317. begin
  318. inherited Destroy;
  319. end;
  320. end.