You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3344 rivejä
116 KiB

  1. {
  2. KAZip (C) Kiril Antonov, http://kadao.dir.bg/
  3. Slightly modified.
  4. }
  5. {$WARNINGS OFF}
  6. {$HINTS OFF}
  7. {$NOTES OFF}
  8. unit KAZip;
  9. interface
  10. {$IFDEF FPC}
  11. {$mode delphi}
  12. {$ENDIF}
  13. {.$DEFINE USE_BZIP2}
  14. {$DEFINE USE_BUFFERED_IO}
  15. uses
  16. Windows,
  17. SysUtils,
  18. Classes,
  19. Masks,
  20. TypInfo,
  21. {$IFDEF USE_BZIP2}
  22. BZip2,
  23. {$ENDIF}
  24. ZLib
  25. {$IFDEF FPC},
  26. dzlib
  27. {$ENDIF}
  28. {$IFDEF USE_BUFFERED_IO},
  29. uutlStreamHelper
  30. {$ENDIF};
  31. type
  32. TKAZipEntries = class;
  33. TKAZip = class;
  34. TBytes = Array of Byte;
  35. TZipSaveMethod = (FastSave, RebuildAll);
  36. TZipCompressionType = (ctNormal, ctMaximum, ctFast, ctSuperFast, ctNone, ctUnknown);
  37. TZipCompressionMethod = (cmStored, cmShrunk, cmReduced1, cmReduced2, cmReduced3, cmReduced4, cmImploded, cmTokenizingReserved, cmDeflated, cmDeflated64, cmDCLImploding, cmPKWAREReserved);
  38. TOverwriteAction = (oaSkip,oaSkipAll,oaOverwrite,oaOverwriteAll);
  39. TOnDecompressFile=Procedure(Sender:TObject; Current, Total : Integer) of Object;
  40. TOnCompressFile=Procedure(Sender:TObject; Current, Total : Integer) of Object;
  41. TOnZipOpen=Procedure(Sender:TObject; Current, Total : Integer) of Object;
  42. TOnZipChange=Procedure(Sender:TObject; ChangeType : Integer) of Object;
  43. TOnAddItem=Procedure(Sender:TObject; ItemName : String) of Object;
  44. TOnRebuildZip=Procedure(Sender:TObject; Current, Total : Integer) of Object;
  45. TOnRemoveItems=Procedure(Sender:TObject; Current, Total : Integer) of Object;
  46. TOnOverwriteFile=Procedure(Sender:TObject; Var FileName : String; Var Action : TOverwriteAction) of Object;
  47. {
  48. 0 - The file is stored (no compression)
  49. 1 - The file is Shrunk
  50. 2 - The file is Reduced with compression factor 1
  51. 3 - The file is Reduced with compression factor 2
  52. 4 - The file is Reduced with compression factor 3
  53. 5 - The file is Reduced with compression factor 4
  54. 6 - The file is Imploded
  55. 7 - Reserved for Tokenizing compression algorithm
  56. 8 - The file is Deflated
  57. 9 - Enhanced Deflating using Deflate64(tm)
  58. 10 - PKWARE Data Compression Library Imploding
  59. 11 - Reserved by PKWARE
  60. 12 - File is compressed using BZIP2 algorithm
  61. }
  62. {DoChange Events
  63. 0 - Zip is Closed;
  64. 1 - Zip is Opened;
  65. 2 - Item is added to the zip
  66. 3 - Item is removed from the Zip
  67. 4 - Item comment changed
  68. 5 - Item name changed
  69. 6 - Item name changed
  70. }
  71. TZLibStreamHeader = packed record
  72. CMF : Byte;
  73. FLG : Byte;
  74. end;
  75. TLocalFile = packed record
  76. LocalFileHeaderSignature : Cardinal; // 4 bytes (0x04034b50)
  77. VersionNeededToExtract : WORD; // 2 bytes
  78. GeneralPurposeBitFlag : WORD; // 2 bytes
  79. CompressionMethod : WORD; // 2 bytes
  80. LastModFileTimeDate : Cardinal; // 4 bytes
  81. Crc32 : Cardinal; // 4 bytes
  82. CompressedSize : Cardinal; // 4 bytes
  83. UncompressedSize : Cardinal; // 4 bytes
  84. FilenameLength : WORD; // 2 bytes
  85. ExtraFieldLength : WORD; // 2 bytes
  86. FileName : AnsiString; // variable size
  87. ExtraField : AnsiString; // variable size
  88. CompressedData : AnsiString; // variable size
  89. end;
  90. TDataDescriptor = packed record
  91. DescriptorSignature : Cardinal; // 4 bytes UNDOCUMENTED 0x08074B50
  92. Crc32 : Cardinal; // 4 bytes
  93. CompressedSize : Cardinal; // 4 bytes
  94. UncompressedSize : Cardinal; // 4 bytes
  95. End;
  96. TCentralDirectoryFile = packed record
  97. CentralFileHeaderSignature : Cardinal; // 4 bytes (0x02014b50)
  98. VersionMadeBy : WORD; // 2 bytes
  99. VersionNeededToExtract : WORD; // 2 bytes
  100. GeneralPurposeBitFlag : WORD; // 2 bytes
  101. CompressionMethod : WORD; // 2 bytes
  102. LastModFileTimeDate : Cardinal; // 4 bytes
  103. Crc32 : Cardinal; // 4 bytes
  104. CompressedSize : Cardinal; // 4 bytes
  105. UncompressedSize : Cardinal; // 4 bytes
  106. FilenameLength : WORD; // 2 bytes
  107. ExtraFieldLength : WORD; // 2 bytes
  108. FileCommentLength : WORD; // 2 bytes
  109. DiskNumberStart : WORD; // 2 bytes
  110. InternalFileAttributes : WORD; // 2 bytes
  111. ExternalFileAttributes : Cardinal; // 4 bytes
  112. RelativeOffsetOfLocalHeader : Cardinal; // 4 bytes
  113. FileName : AnsiString; // variable size
  114. ExtraField : AnsiString; // variable size
  115. FileComment : AnsiString; // variable size
  116. end;
  117. TEndOfCentralDir = packed record
  118. EndOfCentralDirSignature : Cardinal; // 4 bytes (0x06054b50)
  119. NumberOfThisDisk : WORD; // 2 bytes
  120. NumberOfTheDiskWithTheStart : WORD; // 2 bytes
  121. TotalNumberOfEntriesOnThisDisk : WORD; // 2 bytes
  122. TotalNumberOfEntries : WORD; // 2 bytes
  123. SizeOfTheCentralDirectory : Cardinal; // 4 bytes
  124. OffsetOfStartOfCentralDirectory : Cardinal; // 4 bytes
  125. ZipfileCommentLength : WORD; // 2 bytes
  126. end;
  127. TKAZipEntriesEntry = Class(TCollectionItem)
  128. private
  129. { Private declarations }
  130. FParent : TKAZipEntries;
  131. FCentralDirectoryFile : TCentralDirectoryFile;
  132. FLocalFile : TLocalFile;
  133. FIsEncrypted : Boolean;
  134. FIsFolder : Boolean;
  135. FDate : TDateTime;
  136. FCompressionType : TZipCompressionType;
  137. FSelected : Boolean;
  138. procedure SetSelected(const Value: Boolean);
  139. function GetLocalEntrySize: Cardinal;
  140. function GetCentralEntrySize: Cardinal;
  141. procedure SetComment(const Value: String);
  142. procedure SetFileName(const Value: String);
  143. protected
  144. { Protected declarations }
  145. public
  146. { Public declarations }
  147. constructor Create(aCollection: TCollection); override;
  148. destructor Destroy; override;
  149. Function GetCompressedData : String;Overload;
  150. Function GetCompressedData(Stream : TStream) : Integer;Overload;
  151. procedure ExtractToFile(FileName: String);
  152. procedure ExtractToStream(Stream: TStream);
  153. procedure SaveToFile(FileName: String);
  154. procedure SaveToStream(Stream: TStream);
  155. Function Test:Boolean;
  156. Property FileName : String Read FCentralDirectoryFile.FileName Write SetFileName;
  157. Property Comment : String Read FCentralDirectoryFile.FileComment Write SetComment;
  158. Property SizeUncompressed : Cardinal Read FCentralDirectoryFile.UncompressedSize;
  159. Property SizeCompressed : Cardinal Read FCentralDirectoryFile.CompressedSize;
  160. Property Date : TDateTime Read FDate;
  161. Property CRC32 : Cardinal Read FCentralDirectoryFile.CRC32;
  162. Property Attributes : Cardinal Read FCentralDirectoryFile.ExternalFileAttributes;
  163. Property LocalOffset : Cardinal Read FCentralDirectoryFile.RelativeOffsetOfLocalHeader;
  164. Property IsEncrypted : Boolean Read FIsEncrypted;
  165. Property IsFolder : Boolean Read FIsFolder;
  166. Property BitFlag : Word Read FCentralDirectoryFile.GeneralPurposeBitFlag;
  167. Property CompressionMethod : Word Read FCentralDirectoryFile.CompressionMethod;
  168. Property CompressionType : TZipCompressionType Read FCompressionType;
  169. Property LocalEntrySize : Cardinal Read GetLocalEntrySize;
  170. Property CentralEntrySize : Cardinal Read GetCentralEntrySize;
  171. Property Selected : Boolean Read FSelected Write SetSelected;
  172. End;
  173. TKAZipEntries = class(TCollection)
  174. private
  175. { Private declarations }
  176. FParent : TKAZip;
  177. FIsZipFile : Boolean;
  178. FLocalHeaderNumFiles : Integer;
  179. function GetHeaderEntry(Index: Integer): TKAZipEntriesEntry;
  180. procedure SetHeaderEntry(Index: Integer; const Value: TKAZipEntriesEntry);
  181. protected
  182. { Protected declarations }
  183. Function ReadBA(MS: TStream;Sz,Poz:Integer): TBytes;
  184. function Adler32(adler : uLong; buf : pByte; len : uInt) : uLong;
  185. function CalcCRC32(const UncompressedData : string): Cardinal;
  186. function CalculateCRCFromStream(Stream: TStream): Cardinal;
  187. Function RemoveRootName(Const FileName, RootName : String):String;
  188. Procedure SortList(List : TList);
  189. function FileTime2DateTime(FileTime: TFileTime): TDateTime;
  190. //**************************************************************************
  191. Function FindCentralDirectory(MS:TStream):Boolean;
  192. function ParseCentralHeaders(MS: TStream): Boolean;
  193. function GetLocalEntry(MS: TStream; Offset : Integer; HeaderOnly : Boolean): TLocalFile;
  194. Procedure LoadLocalHeaders(MS: TStream);
  195. Function ParseLocalHeaders(MS:TStream):Boolean;
  196. //**************************************************************************
  197. procedure Remove(ItemIndex: Integer; Flush : Boolean);Overload;
  198. procedure RemoveBatch(Files : TList);
  199. procedure InternalExtractToFile(Item: TKAZipEntriesEntry; FileName: String);
  200. //**************************************************************************
  201. Function AddStreamFast(ItemName:String; FileAttr : Word; FileDate : TDateTime; Stream:TStream):TKAZipEntriesEntry;Overload;
  202. Function AddStreamRebuild(ItemName:String; FileAttr : Word; FileDate : TDateTime; Stream:TStream):TKAZipEntriesEntry;
  203. Function AddFolderChain(ItemName:String):Boolean;Overload;
  204. Function AddFolderChain(ItemName:String; FileAttr : Word; FileDate : TDateTime):Boolean;Overload;
  205. Function AddFolderEx(FolderName:String; RootFolder:String; WildCard:String; WithSubFolders : Boolean):Boolean;
  206. //**************************************************************************
  207. public
  208. { Public declarations }
  209. Procedure ParseZip(MS:TStream);
  210. Constructor Create(AOwner : TKAZip; MS : TStream);Overload;
  211. Constructor Create(AOwner : TKAZip);Overload;
  212. Destructor Destroy; Override;
  213. //**************************************************************************
  214. Function IndexOf(Const FileName:String):Integer;
  215. //**************************************************************************
  216. Function AddFile(FileName, NewFileName: String):TKAZipEntriesEntry;Overload;
  217. Function AddFile(FileName:String):TKAZipEntriesEntry;Overload;
  218. Function AddFiles(FileNames:TStrings):Boolean;
  219. Function AddFolder(FolderName:String; RootFolder:String; WildCard:String; WithSubFolders : Boolean):Boolean;
  220. Function AddFilesAndFolders(FileNames:TStrings; RootFolder:String; WithSubFolders : Boolean):Boolean;
  221. Function AddStream(FileName:String; FileAttr : Word; FileDate : TDateTime; Stream:TStream):TKAZipEntriesEntry;Overload;
  222. Function AddStream(FileName: String; Stream : TStream):TKAZipEntriesEntry;Overload;
  223. //**************************************************************************
  224. Procedure Remove(ItemIndex:Integer);Overload;
  225. Procedure Remove(Item:TKAZipEntriesEntry);Overload;
  226. Procedure Remove(FileName:String);Overload;
  227. Procedure RemoveFiles(List : TList);
  228. Procedure RemoveSelected;
  229. Procedure Rebuild;
  230. //**************************************************************************
  231. Procedure Select(WildCard : String);
  232. Procedure SelectAll;
  233. Procedure DeSelectAll;
  234. Procedure InvertSelection;
  235. //**************************************************************************
  236. Procedure Rename(Item : TKAZipEntriesEntry; NewFileName: String);Overload;
  237. Procedure Rename(ItemIndex : Integer; NewFileName: String);Overload;
  238. Procedure Rename(FileName: String; NewFileName: String);Overload;
  239. procedure CreateFolder(FolderName: String; FolderDate: TDateTime);
  240. procedure RenameFolder(FolderName : String; NewFolderName : String);
  241. procedure RenameMultiple(Names : TStringList; NewNames : TStringList);
  242. //**************************************************************************
  243. procedure ExtractToFile (Item : TKAZipEntriesEntry; FileName: String);Overload;
  244. procedure ExtractToFile (ItemIndex : Integer; FileName: String);Overload;
  245. procedure ExtractToFile (FileName, DestinationFileName:String);Overload;
  246. procedure ExtractToStream(Item : TKAZipEntriesEntry; Stream: TStream);
  247. procedure ExtractAll(TargetDirectory:String);
  248. procedure ExtractSelected(TargetDirectory:String);
  249. //**************************************************************************
  250. Property Items[Index : Integer] : TKAZipEntriesEntry read GetHeaderEntry write SetHeaderEntry;
  251. end;
  252. TKAZip = class(TComponent)
  253. private
  254. { Private declarations }
  255. FZipHeader : TKAZipEntries;
  256. FIsDirty : Boolean;
  257. FEndOfCentralDirPos : Cardinal;
  258. FEndOfCentralDir : TEndOfCentralDir;
  259. FZipCommentPos : Cardinal;
  260. FZipComment : TStringList;
  261. FRebuildECDP : Cardinal;
  262. FRebuildCP : Cardinal;
  263. FIsZipFile : Boolean;
  264. FHasBadEntries : Boolean;
  265. FFileName : String;
  266. FFileNames : TStringList;
  267. FZipSaveMethod : TZipSaveMethod;
  268. FExternalStream : Boolean;
  269. FStoreRelativePath : Boolean;
  270. FZipCompressionType : TZipCompressionType;
  271. FCurrentDFS : Cardinal;
  272. FOnDecompressFile : TOnDecompressFile;
  273. FOnCompressFile : TOnCompressFile;
  274. FOnZipChange : TOnZipChange;
  275. FBatchMode : Boolean;
  276. NewLHOffsets : Array of Cardinal;
  277. NewEndOfCentralDir : TEndOfCentralDir;
  278. FOnZipOpen : TOnZipOpen;
  279. FUseTempFiles : Boolean;
  280. FStoreFolders : Boolean;
  281. FOnAddItem : TOnAddItem;
  282. FComponentVersion : String;
  283. FOnRebuildZip : TOnRebuildZip;
  284. FOnRemoveItems : TOnRemoveItems;
  285. FOverwriteAction : TOverwriteAction;
  286. FOnOverwriteFile : TOnOverwriteFile;
  287. FReadOnly : Boolean;
  288. FApplyAttributes : Boolean;
  289. procedure SetFileName(const Value: String);
  290. procedure SetIsZipFile(const Value: Boolean);
  291. function GetComment: TStrings;
  292. procedure SetComment(const Value: TStrings);
  293. procedure SetZipSaveMethod(const Value: TZipSaveMethod);
  294. procedure SetActive(const Value: Boolean);
  295. procedure SetZipCompressionType(const Value: TZipCompressionType);
  296. function GetFileNames: TStrings;
  297. procedure SetFileNames(const Value: TStrings);
  298. procedure SetUseTempFiles(const Value: Boolean);
  299. procedure SetStoreFolders(const Value: Boolean);
  300. procedure SetOnAddItem(const Value: TOnAddItem);
  301. procedure SetComponentVersion(const Value: String);
  302. procedure SetOnRebuildZip(const Value: TOnRebuildZip);
  303. procedure SetOnRemoveItems(const Value: TOnRemoveItems);
  304. procedure SetOverwriteAction(const Value: TOverwriteAction);
  305. procedure SetOnOverwriteFile(const Value: TOnOverwriteFile);
  306. procedure SetReadOnly(const Value: Boolean);
  307. procedure SetApplyAtributes(const Value: Boolean);
  308. protected
  309. { Protected declarations }
  310. FZipStream : TStream;
  311. //**************************************************************************
  312. Procedure LoadFromFile(FileName:String);
  313. Procedure LoadFromStream(MS : TStream);
  314. //**************************************************************************
  315. Procedure RebuildLocalFiles(MS : TStream);
  316. Procedure RebuildCentralDirectory(MS : TStream);
  317. Procedure RebuildEndOfCentralDirectory(MS : TStream);
  318. //**************************************************************************
  319. procedure OnDecompress(Sender:TObject);
  320. procedure OnCompress(Sender:TObject);
  321. Procedure DoChange(Sender:TObject; Const ChangeType : Integer);Virtual;
  322. //**************************************************************************
  323. public
  324. { Public declarations }
  325. Constructor Create(AOwner:TComponent);Override;
  326. Destructor Destroy; Override;
  327. //**************************************************************************
  328. function GetDelphiTempFileName: String;
  329. function GetFileName(S: String): String;
  330. function GetFilePath(S: String): String;
  331. //**************************************************************************
  332. Procedure CreateZip(Stream:TStream);Overload;
  333. Procedure CreateZip(FileName:String);Overload;
  334. Procedure Open(FileName:String);Overload;
  335. Procedure Open(MS : TStream);Overload;
  336. Procedure SaveToStream(Stream:TStream);
  337. Procedure Rebuild;
  338. Procedure FixZip(MS : TStream);
  339. Procedure Close;
  340. //**************************************************************************
  341. Function AddFile(FileName, NewFileName: String):TKAZipEntriesEntry;Overload;
  342. Function AddFile(FileName:String):TKAZipEntriesEntry;Overload;
  343. Function AddFiles(FileNames:TStrings):Boolean;
  344. Function AddFolder(FolderName:String; RootFolder:String; WildCard:String; WithSubFolders : Boolean):Boolean;
  345. Function AddFilesAndFolders(FileNames:TStrings; RootFolder:String; WithSubFolders : Boolean):Boolean;
  346. Function AddStream(FileName:String; FileAttr : Word; FileDate : TDateTime; Stream:TStream):TKAZipEntriesEntry;Overload;
  347. Function AddStream(FileName: String; Stream : TStream):TKAZipEntriesEntry;Overload;
  348. //**************************************************************************
  349. Procedure Remove(ItemIndex:Integer);Overload;
  350. Procedure Remove(Item:TKAZipEntriesEntry);Overload;
  351. Procedure Remove(FileName:String);Overload;
  352. Procedure RemoveFiles(List : TList);
  353. Procedure RemoveSelected;
  354. //**************************************************************************
  355. Procedure Select(WildCard : String);
  356. Procedure SelectAll;
  357. Procedure DeSelectAll;
  358. Procedure InvertSelection;
  359. //**************************************************************************
  360. Procedure Rename(Item : TKAZipEntriesEntry; NewFileName: String);Overload;
  361. Procedure Rename(ItemIndex : Integer; NewFileName: String);Overload;
  362. Procedure Rename(FileName : String; NewFileName: String);Overload;
  363. Procedure CreateFolder(FolderName : String; FolderDate : TDateTime);
  364. Procedure RenameFolder(FolderName : String; NewFolderName : String);
  365. procedure RenameMultiple(Names : TStringList; NewNames : TStringList);
  366. //**************************************************************************
  367. procedure ExtractToFile (Item : TKAZipEntriesEntry; FileName: String);Overload;
  368. procedure ExtractToFile (ItemIndex : Integer; FileName: String);Overload;
  369. procedure ExtractToFile (FileName, DestinationFileName:String);Overload;
  370. procedure ExtractToStream(Item : TKAZipEntriesEntry; Stream: TStream);
  371. procedure ExtractAll(TargetDirectory: String);
  372. procedure ExtractSelected(TargetDirectory: String);
  373. //**************************************************************************
  374. Property Entries : TKAZipEntries Read FZipHeader;
  375. Property HasBadEntries : Boolean Read FHasBadEntries;
  376. published
  377. { Published declarations }
  378. Property FileName : String Read FFileName Write SetFileName;
  379. Property IsZipFile : Boolean Read FIsZipFile Write SetIsZipFile;
  380. Property SaveMethod : TZipSaveMethod Read FZipSaveMethod Write SetZipSaveMethod;
  381. Property StoreRelativePath : Boolean Read FStoreRelativePath Write FStoreRelativePath;
  382. Property StoreFolders : Boolean read FStoreFolders write SetStoreFolders;
  383. Property CompressionType : TZipCompressionType Read FZipCompressionType Write SetZipCompressionType;
  384. Property Comment : TStrings Read GetComment Write SetComment;
  385. Property FileNames : TStrings Read GetFileNames Write SetFileNames;
  386. Property UseTempFiles : Boolean read FUseTempFiles write SetUseTempFiles;
  387. Property OverwriteAction : TOverwriteAction read FOverwriteAction write SetOverwriteAction;
  388. Property ComponentVersion : String read FComponentVersion write SetComponentVersion;
  389. Property ReadOnly : Boolean read FReadOnly write SetReadOnly;
  390. Property ApplyAtributes : Boolean read FApplyAttributes write SetApplyAtributes;
  391. Property OnDecompressFile : TOnDecompressFile Read FOnDecompressFile Write FOnDecompressFile;
  392. Property OnCompressFile : TOnCompressFile Read FOnCompressFile Write FOnCompressFile;
  393. Property OnZipChange : TOnZipChange Read FOnZipChange Write FOnZipChange;
  394. Property OnZipOpen : TOnZipOpen Read FOnZipOpen Write FOnZipOpen;
  395. Property OnAddItem : TOnAddItem read FOnAddItem write SetOnAddItem;
  396. Property OnRebuildZip : TOnRebuildZip read FOnRebuildZip write SetOnRebuildZip;
  397. Property OnRemoveItems : TOnRemoveItems read FOnRemoveItems write SetOnRemoveItems;
  398. Property OnOverwriteFile : TOnOverwriteFile read FOnOverwriteFile write SetOnOverwriteFile;
  399. Property Active : Boolean Read FIsZipFile Write SetActive;
  400. end;
  401. procedure Register;
  402. Function ToZipName(FileName:String):String;
  403. Function ToDosName(FileName:String):String;
  404. implementation
  405. Const
  406. ZL_DEF_COMPRESSIONMETHOD = $8; { Deflate }
  407. ZL_ENCH_COMPRESSIONMETHOD = $9; { Enchanced Deflate }
  408. ZL_DEF_COMPRESSIONINFO = $7; { 32k window for Deflate }
  409. ZL_PRESET_DICT = $20;
  410. ZL_FASTEST_COMPRESSION = $0;
  411. ZL_FAST_COMPRESSION = $1;
  412. ZL_DEFAULT_COMPRESSION = $2;
  413. ZL_MAXIMUM_COMPRESSION = $3;
  414. ZL_FCHECK_MASK = $1F;
  415. ZL_CINFO_MASK = $F0; { mask out leftmost 4 bits }
  416. ZL_FLEVEL_MASK = $C0; { mask out leftmost 2 bits }
  417. ZL_CM_MASK = $0F; { mask out rightmost 4 bits }
  418. ZL_MULTIPLE_DISK_SIG = $08074b50; // 'PK'#7#8
  419. ZL_DATA_DESCRIPT_SIG = $08074b50; // 'PK'#7#8
  420. ZL_LOCAL_HEADERSIG = $04034b50; // 'PK'#3#4
  421. ZL_CENTRAL_HEADERSIG = $02014b50; // 'PK'#1#2
  422. ZL_EOC_HEADERSIG = $06054b50; // 'PK'#5#6
  423. const
  424. CRCTable: array[0..255] of Cardinal = (
  425. $00000000, $77073096, $EE0E612C, $990951BA, $076DC419, $706AF48F, $E963A535,
  426. $9E6495A3, $0EDB8832, $79DCB8A4, $E0D5E91E, $97D2D988, $09B64C2B, $7EB17CBD,
  427. $E7B82D07, $90BF1D91, $1DB71064, $6AB020F2, $F3B97148, $84BE41DE, $1ADAD47D,
  428. $6DDDE4EB, $F4D4B551, $83D385C7, $136C9856, $646BA8C0, $FD62F97A, $8A65C9EC,
  429. $14015C4F, $63066CD9, $FA0F3D63, $8D080DF5, $3B6E20C8, $4C69105E, $D56041E4,
  430. $A2677172, $3C03E4D1, $4B04D447, $D20D85FD, $A50AB56B, $35B5A8FA, $42B2986C,
  431. $DBBBC9D6, $ACBCF940, $32D86CE3, $45DF5C75, $DCD60DCF, $ABD13D59, $26D930AC,
  432. $51DE003A, $C8D75180, $BFD06116, $21B4F4B5, $56B3C423, $CFBA9599, $B8BDA50F,
  433. $2802B89E, $5F058808, $C60CD9B2, $B10BE924, $2F6F7C87, $58684C11, $C1611DAB,
  434. $B6662D3D, $76DC4190, $01DB7106, $98D220BC, $EFD5102A, $71B18589, $06B6B51F,
  435. $9FBFE4A5, $E8B8D433, $7807C9A2, $0F00F934, $9609A88E, $E10E9818, $7F6A0DBB,
  436. $086D3D2D, $91646C97, $E6635C01, $6B6B51F4, $1C6C6162, $856530D8, $F262004E,
  437. $6C0695ED, $1B01A57B, $8208F4C1, $F50FC457, $65B0D9C6, $12B7E950, $8BBEB8EA,
  438. $FCB9887C, $62DD1DDF, $15DA2D49, $8CD37CF3, $FBD44C65, $4DB26158, $3AB551CE,
  439. $A3BC0074, $D4BB30E2, $4ADFA541, $3DD895D7, $A4D1C46D, $D3D6F4FB, $4369E96A,
  440. $346ED9FC, $AD678846, $DA60B8D0, $44042D73, $33031DE5, $AA0A4C5F, $DD0D7CC9,
  441. $5005713C, $270241AA, $BE0B1010, $C90C2086, $5768B525, $206F85B3, $B966D409,
  442. $CE61E49F, $5EDEF90E, $29D9C998, $B0D09822, $C7D7A8B4, $59B33D17, $2EB40D81,
  443. $B7BD5C3B, $C0BA6CAD, $EDB88320, $9ABFB3B6, $03B6E20C, $74B1D29A, $EAD54739,
  444. $9DD277AF, $04DB2615, $73DC1683, $E3630B12, $94643B84, $0D6D6A3E, $7A6A5AA8,
  445. $E40ECF0B, $9309FF9D, $0A00AE27, $7D079EB1, $F00F9344, $8708A3D2, $1E01F268,
  446. $6906C2FE, $F762575D, $806567CB, $196C3671, $6E6B06E7, $FED41B76, $89D32BE0,
  447. $10DA7A5A, $67DD4ACC, $F9B9DF6F, $8EBEEFF9, $17B7BE43, $60B08ED5, $D6D6A3E8,
  448. $A1D1937E, $38D8C2C4, $4FDFF252, $D1BB67F1, $A6BC5767, $3FB506DD, $48B2364B,
  449. $D80D2BDA, $AF0A1B4C, $36034AF6, $41047A60, $DF60EFC3, $A867DF55, $316E8EEF,
  450. $4669BE79, $CB61B38C, $BC66831A, $256FD2A0, $5268E236, $CC0C7795, $BB0B4703,
  451. $220216B9, $5505262F, $C5BA3BBE, $B2BD0B28, $2BB45A92, $5CB36A04, $C2D7FFA7,
  452. $B5D0CF31, $2CD99E8B, $5BDEAE1D, $9B64C2B0, $EC63F226, $756AA39C, $026D930A,
  453. $9C0906A9, $EB0E363F, $72076785, $05005713, $95BF4A82, $E2B87A14, $7BB12BAE,
  454. $0CB61B38, $92D28E9B, $E5D5BE0D, $7CDCEFB7, $0BDBDF21, $86D3D2D4, $F1D4E242,
  455. $68DDB3F8, $1FDA836E, $81BE16CD, $F6B9265B, $6FB077E1, $18B74777, $88085AE6,
  456. $FF0F6A70, $66063BCA, $11010B5C, $8F659EFF, $F862AE69, $616BFFD3, $166CCF45,
  457. $A00AE278, $D70DD2EE, $4E048354, $3903B3C2, $A7672661, $D06016F7, $4969474D,
  458. $3E6E77DB, $AED16A4A, $D9D65ADC, $40DF0B66, $37D83BF0, $A9BCAE53, $DEBB9EC5,
  459. $47B2CF7F, $30B5FFE9, $BDBDF21C, $CABAC28A, $53B39330, $24B4A3A6, $BAD03605,
  460. $CDD70693, $54DE5729, $23D967BF, $B3667A2E, $C4614AB8, $5D681B02, $2A6F2B94,
  461. $B40BBE37, $C30C8EA1, $5A05DF1B, $2D02EF8D);
  462. procedure Register;
  463. begin
  464. RegisterComponents('KA', [TKAZip]);
  465. end;
  466. Function ToZipName(FileName:String):String;
  467. Var
  468. P : Integer;
  469. Begin
  470. Result := FileName;
  471. Result := StringReplace(Result,'\','/',[rfReplaceAll]);
  472. P := Pos(':/',Result);
  473. if P > 0 Then
  474. Begin
  475. System.Delete(Result,1,P+1);
  476. End;
  477. P := Pos('//',Result);
  478. if P > 0 Then
  479. Begin
  480. System.Delete(Result,1,P+1);
  481. P := Pos('/',Result);
  482. if P > 0 Then
  483. Begin
  484. System.Delete(Result,1,P);
  485. P := Pos('/',Result);
  486. if P > 0 Then System.Delete(Result,1,P);
  487. End;
  488. End;
  489. End;
  490. Function ToDosName(FileName:String):String;
  491. Var
  492. P : Integer;
  493. Begin
  494. Result := FileName;
  495. Result := StringReplace(Result,'\','/',[rfReplaceAll]);
  496. P := Pos(':/',Result);
  497. if P > 0 Then
  498. Begin
  499. System.Delete(Result,1,P+1);
  500. End;
  501. P := Pos('//',Result);
  502. if P > 0 Then
  503. Begin
  504. System.Delete(Result,1,P+1);
  505. P := Pos('/',Result);
  506. if P > 0 Then
  507. Begin
  508. System.Delete(Result,1,P);
  509. P := Pos('/',Result);
  510. if P > 0 Then System.Delete(Result,1,P);
  511. End;
  512. End;
  513. Result := StringReplace(Result,'/','\',[rfReplaceAll]);
  514. End;
  515. { TKAZipEntriesEntry }
  516. constructor TKAZipEntriesEntry.Create(aCollection: TCollection);
  517. begin
  518. inherited Create(aCollection);
  519. FParent := TKAZipEntries(aCollection);
  520. FSelected := False;
  521. end;
  522. destructor TKAZipEntriesEntry.Destroy;
  523. begin
  524. inherited Destroy;
  525. end;
  526. procedure TKAZipEntriesEntry.ExtractToFile(FileName: String);
  527. begin
  528. FParent.ExtractToFile(Self,FileName);
  529. end;
  530. procedure TKAZipEntriesEntry.ExtractToStream(Stream: TStream);
  531. begin
  532. FParent.ExtractToStream(Self,Stream);
  533. end;
  534. procedure TKAZipEntriesEntry.SaveToFile(FileName: String);
  535. begin
  536. ExtractToFile(FileName);
  537. end;
  538. procedure TKAZipEntriesEntry.SaveToStream(Stream: TStream);
  539. begin
  540. ExtractToStream(Stream);
  541. end;
  542. function TKAZipEntriesEntry.GetCompressedData(Stream: TStream): Integer;
  543. Var
  544. FZLHeader : TZLibStreamHeader;
  545. BA : TLocalFile;
  546. ZLH : Word;
  547. Compress : Byte;
  548. begin
  549. Result := 0;
  550. if (CompressionMethod=8) Then
  551. Begin
  552. FZLHeader.CMF := (ZL_DEF_COMPRESSIONINFO shl 4); { 32k Window size }
  553. FZLHeader.CMF := FZLHeader.CMF or ZL_DEF_COMPRESSIONMETHOD; { Deflate }
  554. Compress := ZL_DEFAULT_COMPRESSION;
  555. Case BitFlag AND 6 of
  556. 0 : Compress := ZL_DEFAULT_COMPRESSION;
  557. 2 : Compress := ZL_MAXIMUM_COMPRESSION;
  558. 4 : Compress := ZL_FAST_COMPRESSION;
  559. 6 : Compress := ZL_FASTEST_COMPRESSION;
  560. End;
  561. FZLHeader.FLG := FZLHeader.FLG or (Compress shl 6);
  562. FZLHeader.FLG := FZLHeader.FLG and not ZL_PRESET_DICT; { no preset dictionary}
  563. FZLHeader.FLG := FZLHeader.FLG and not ZL_FCHECK_MASK;
  564. ZLH := (FZLHeader.CMF * 256) + FZLHeader.FLG;
  565. Inc(FZLHeader.FLG, 31 - (ZLH mod 31));
  566. Result := Result + Stream.Write(FZLHeader,SizeOf(FZLHeader));
  567. End;
  568. BA := FParent.GetLocalEntry(FParent.FParent.FZipStream,LocalOffset,False);
  569. if BA.LocalFileHeaderSignature<>$04034b50 Then
  570. Begin
  571. Result := 0;
  572. Exit;
  573. End;
  574. if SizeCompressed > 0 Then
  575. Result := Result + Stream.Write(BA.CompressedData[1],SizeCompressed);
  576. end;
  577. function TKAZipEntriesEntry.GetCompressedData: String;
  578. Var
  579. BA : TLocalFile;
  580. FZLHeader : TZLibStreamHeader;
  581. ZLH : Word;
  582. Compress : Byte;
  583. begin
  584. Result := '';
  585. if (CompressionMethod=0) or (CompressionMethod=8) Then
  586. Begin
  587. BA := FParent.GetLocalEntry(FParent.FParent.FZipStream,LocalOffset,False);
  588. if BA.LocalFileHeaderSignature<>$04034b50 Then Exit;
  589. if (CompressionMethod=8) Then
  590. Begin
  591. FZLHeader.CMF := (ZL_DEF_COMPRESSIONINFO shl 4); { 32k Window size }
  592. FZLHeader.CMF := FZLHeader.CMF or ZL_DEF_COMPRESSIONMETHOD; { Deflate }
  593. Compress := ZL_DEFAULT_COMPRESSION;
  594. Case BitFlag AND 6 of
  595. 0 : Compress := ZL_DEFAULT_COMPRESSION;
  596. 2 : Compress := ZL_MAXIMUM_COMPRESSION;
  597. 4 : Compress := ZL_FAST_COMPRESSION;
  598. 6 : Compress := ZL_FASTEST_COMPRESSION;
  599. End;
  600. FZLHeader.FLG := FZLHeader.FLG or (Compress shl 6);
  601. FZLHeader.FLG := FZLHeader.FLG and not ZL_PRESET_DICT; { no preset dictionary}
  602. FZLHeader.FLG := FZLHeader.FLG and not ZL_FCHECK_MASK;
  603. ZLH := (FZLHeader.CMF * 256) + FZLHeader.FLG;
  604. Inc(FZLHeader.FLG, 31 - (ZLH mod 31));
  605. SetLength(Result,SizeOf(FZLHeader));
  606. SetString(Result,PChar(@FZLHeader),SizeOf(FZLHeader));
  607. End;
  608. Result := Result + BA.CompressedData;
  609. End
  610. Else
  611. Begin
  612. SetLength(Result,0);
  613. End;
  614. End;
  615. procedure TKAZipEntriesEntry.SetSelected(const Value: Boolean);
  616. begin
  617. FSelected := Value;
  618. end;
  619. function TKAZipEntriesEntry.GetLocalEntrySize: Cardinal;
  620. begin
  621. Result := SizeOf(TLocalFile) - 3*SizeOf(String)+
  622. FCentralDirectoryFile.CompressedSize+
  623. FCentralDirectoryFile.FilenameLength+
  624. FCentralDirectoryFile.ExtraFieldLength;
  625. if (FCentralDirectoryFile.GeneralPurposeBitFlag And (1 SHL 3)) > 0 Then
  626. Begin
  627. Result := Result + SizeOf(TDataDescriptor);
  628. End;
  629. end;
  630. function TKAZipEntriesEntry.GetCentralEntrySize: Cardinal;
  631. begin
  632. Result := SizeOf(TCentralDirectoryFile) - 3*SizeOf(String)+
  633. FCentralDirectoryFile.FilenameLength+
  634. FCentralDirectoryFile.ExtraFieldLength+
  635. FCentralDirectoryFile.FileCommentLength;
  636. end;
  637. function TKAZipEntriesEntry.Test: Boolean;
  638. Var
  639. FS : TFileStream;
  640. MS : TMemoryStream;
  641. FN : String;
  642. begin
  643. Result := True;
  644. Try
  645. if NOT FIsEncrypted Then
  646. Begin
  647. if FParent.FParent.FUseTempFiles Then
  648. Begin
  649. FN := FParent.FParent.GetDelphiTempFileName;
  650. FS := TFileStream.Create(FN,fmOpenReadWrite or FmCreate);
  651. Try
  652. ExtractToStream(FS);
  653. FS.Position := 0;
  654. Result := FParent.CalculateCRCFromStream(FS) = CRC32;
  655. Finally
  656. FS.Free;
  657. DeleteFile(FN);
  658. End;
  659. End
  660. Else
  661. Begin
  662. MS := TMemoryStream.Create;
  663. Try
  664. ExtractToStream(MS);
  665. MS.Position := 0;
  666. Result := FParent.CalculateCRCFromStream(MS) = CRC32;
  667. Finally
  668. MS.Free;
  669. End;
  670. End;
  671. End;
  672. Except
  673. Result := False;
  674. End;
  675. end;
  676. procedure TKAZipEntriesEntry.SetComment(const Value: String);
  677. begin
  678. FCentralDirectoryFile.FileComment := Value;
  679. FCentralDirectoryFile.FileCommentLength := Length(FCentralDirectoryFile.FileComment);
  680. FParent.Rebuild;
  681. if NOT FParent.FParent.FBatchMode Then
  682. Begin
  683. FParent.FParent.DoChange(FParent,4);
  684. End;
  685. end;
  686. procedure TKAZipEntriesEntry.SetFileName(const Value: String);
  687. Var
  688. FN : String;
  689. begin
  690. FN := ToZipName(Value);
  691. if FParent.IndexOf(FN) > -1 Then Raise Exception.Create('File with same name already exists in Archive!');
  692. FCentralDirectoryFile.FileName := ToZipName(Value);
  693. FCentralDirectoryFile.FilenameLength := Length(FCentralDirectoryFile.FileName);
  694. if NOT FParent.FParent.FBatchMode Then
  695. Begin
  696. FParent.Rebuild;
  697. FParent.FParent.DoChange(FParent,5);
  698. End;
  699. end;
  700. { TKAZipEntries }
  701. constructor TKAZipEntries.Create(AOwner : TKAZip);
  702. begin
  703. Inherited Create(TKAZipEntriesEntry);
  704. FParent := AOwner;
  705. FIsZipFile := False;
  706. end;
  707. constructor TKAZipEntries.Create(AOwner : TKAZip; MS : TStream);
  708. begin
  709. Inherited Create(TKAZipEntriesEntry);
  710. FParent := AOwner;
  711. FIsZipFile := False;
  712. FLocalHeaderNumFiles := 0;
  713. ParseZip(MS);
  714. end;
  715. destructor TKAZipEntries.Destroy;
  716. begin
  717. inherited Destroy;
  718. end;
  719. function TKAZipEntries.Adler32(adler : uLong; buf : pByte; len : uInt) : uLong;
  720. const
  721. BASE = uLong(65521);
  722. NMAX = 3854;
  723. var
  724. s1, s2 : uLong;
  725. k : Integer;
  726. begin
  727. s1 := adler and $ffff;
  728. s2 := (adler shr 16) and $ffff;
  729. if not Assigned(buf) then
  730. begin
  731. adler32 := uLong(1);
  732. exit;
  733. end;
  734. while (len > 0) do
  735. begin
  736. if len < NMAX then
  737. k := len
  738. else
  739. k := NMAX;
  740. Dec(len, k);
  741. while (k > 0) do
  742. begin
  743. Inc(s1, buf^);
  744. Inc(s2, s1);
  745. Inc(buf);
  746. Dec(k);
  747. end;
  748. s1 := s1 mod BASE;
  749. s2 := s2 mod BASE;
  750. end;
  751. adler32 := (s2 shl 16) or s1;
  752. end;
  753. function TKAZipEntries.CalcCRC32(const UncompressedData : string): Cardinal;
  754. var
  755. X : Integer;
  756. begin
  757. Result := $FFFFFFFF;
  758. for X := 0 to Length(UncompressedData) - 1 do
  759. Begin
  760. Result := (Result SHR 8) XOR (CRCTable[Byte(Result) XOR Ord(UncompressedData[X+1])]);
  761. End;
  762. Result := Result XOR $FFFFFFFF;
  763. end;
  764. function TKAZipEntries.CalculateCRCFromStream(Stream: TStream): Cardinal;
  765. var
  766. Buffer: array[1..8192] of Byte;
  767. I, ReadCount: Integer;
  768. TempResult: Longword;
  769. begin
  770. TempResult := $FFFFFFFF;
  771. while (Stream.Position <> Stream.Size) do begin
  772. ReadCount := Stream.Read(Buffer, SizeOf(Buffer));
  773. for I := 1 to ReadCount do
  774. TempResult := ((TempResult shr 8) and $FFFFFF) xor CRCTable[(TempResult xor Longword(Buffer[I])) and $FF];
  775. end;
  776. Result := not TempResult;
  777. end;
  778. Function TKAZipEntries.RemoveRootName(Const FileName, RootName : String):String;
  779. Var
  780. P : Integer;
  781. S : String;
  782. Begin
  783. Result := FileName;
  784. P := Pos(AnsiLowerCase(RootName),AnsiLowerCase(FileName));
  785. if P=1 Then
  786. Begin
  787. System.Delete(Result,1,Length(RootName));
  788. S := Result;
  789. if (Length(S) > 0) AND (S[1]='\') Then
  790. Begin
  791. System.Delete(S,1,1);
  792. Result := S;
  793. End;
  794. End;
  795. End;
  796. Procedure TKAZipEntries.SortList(List : TList);
  797. Var
  798. X : Integer;
  799. I1 : Cardinal;
  800. I2 : Cardinal;
  801. NoChange : Boolean;
  802. Begin
  803. if List.Count=1 Then Exit;
  804. Repeat
  805. NoChange := True;
  806. For X := 0 To List.Count-2 Do
  807. Begin
  808. I1 := Integer(List.Items[X]);
  809. I2 := Integer(List.Items[X+1]);
  810. if I1 > I2 Then
  811. Begin
  812. List.Exchange(X,X+1);
  813. NoChange := False;
  814. End;
  815. End;
  816. Until NoChange;
  817. End;
  818. function TKAZipEntries.FileTime2DateTime(FileTime: TFileTime): TDateTime;
  819. var
  820. LocalFileTime: TFileTime;
  821. SystemTime: TSystemTime;
  822. begin
  823. FileTimeToLocalFileTime(FileTime, LocalFileTime) ;
  824. FileTimeToSystemTime(LocalFileTime, SystemTime) ;
  825. Result := SystemTimeToDateTime(SystemTime) ;
  826. end;
  827. function TKAZipEntries.GetHeaderEntry(Index: Integer): TKAZipEntriesEntry;
  828. begin
  829. Result := TKAZipEntriesEntry(Inherited Items[Index]);
  830. end;
  831. procedure TKAZipEntries.SetHeaderEntry(Index: Integer; const Value: TKAZipEntriesEntry);
  832. begin
  833. Inherited Items[Index] := TCollectionItem(Value);
  834. end;
  835. Function TKAZipEntries.ReadBA(MS: TStream; Sz, Poz:Integer): TBytes;
  836. Begin
  837. SetLength(Result,SZ);
  838. MS.Position := Poz;
  839. MS.Read(Result[0],SZ);
  840. End;
  841. function TKAZipEntries.FindCentralDirectory(MS: TStream): Boolean;
  842. Var
  843. SeekStart : Integer;
  844. Poz : Integer;
  845. BR : Integer;
  846. Byte_ : Array[0..3] of Byte;
  847. begin
  848. Result := False;
  849. if MS.Size < 22 Then Exit;
  850. if MS.Size < 256 Then
  851. SeekStart := MS.Size
  852. Else
  853. SeekStart := 256;
  854. Poz := MS.Size-22;
  855. BR := SeekStart;
  856. Repeat
  857. MS.Position := Poz;
  858. MS.Read(Byte_,4);
  859. If Byte_[0]=$50 Then
  860. Begin
  861. if (Byte_[1]=$4B)
  862. And (Byte_[2]=$05)
  863. And (Byte_[3]=$06) Then
  864. Begin
  865. MS.Position := Poz;
  866. FParent.FEndOfCentralDirPos := MS.Position;
  867. MS.Read(FParent.FEndOfCentralDir,SizeOf(FParent.FEndOfCentralDir));
  868. FParent.FZipCommentPos := MS.Position;
  869. FParent.FZipComment.Clear;
  870. Result := True;
  871. End
  872. Else
  873. Begin
  874. Dec(Poz,4);
  875. Dec(BR ,4);
  876. End;
  877. End
  878. Else
  879. Begin
  880. Dec(Poz);
  881. Dec(BR)
  882. End;
  883. if BR < 0 Then
  884. Begin
  885. Case SeekStart of
  886. 256 : Begin
  887. SeekStart := 1024;
  888. Poz := MS.Size-(256+22);
  889. BR := SeekStart;
  890. End;
  891. 1024 : Begin
  892. SeekStart := 65536;
  893. Poz := MS.Size-(1024+22);
  894. BR := SeekStart;
  895. End;
  896. 65536 : Begin
  897. SeekStart := -1;
  898. End;
  899. End;
  900. End;
  901. if BR < 0 Then SeekStart := -1;
  902. if MS.Size < SeekStart Then SeekStart := -1;
  903. Until (Result) or (SeekStart=-1);
  904. end;
  905. function TKAZipEntries.ParseCentralHeaders(MS: TStream): Boolean;
  906. Var
  907. X : Integer;
  908. Entry : TKAZipEntriesEntry;
  909. CDFile : TCentralDirectoryFile;
  910. begin
  911. Result := False;
  912. Try
  913. MS.Position := FParent.FEndOfCentralDir.OffsetOfStartOfCentralDirectory;
  914. For X := 0 To FParent.FEndOfCentralDir.TotalNumberOfEntriesOnThisDisk-1 do
  915. Begin
  916. FillChar(CDFile,SizeOf(TCentralDirectoryFile)-3*SizeOf(String),0);
  917. MS.Read(CDFile,SizeOf(TCentralDirectoryFile)-3*SizeOf(String));
  918. Entry := TKAZipEntriesEntry.Create(Self);
  919. Entry.FDate := FileDateToDateTime(CDFile.LastModFileTimeDate);
  920. if (CDFile.GeneralPurposeBitFlag And 1) > 0 Then
  921. Entry.FIsEncrypted := True
  922. Else
  923. Entry.FIsEncrypted := False;
  924. If CDFile.FilenameLength > 0 Then
  925. Begin
  926. SetLength(CDFile.FileName,CDFile.FilenameLength);
  927. MS.Read(CDFile.FileName[1], CDFile.FilenameLength)
  928. End;
  929. If CDFile.ExtraFieldLength > 0 Then
  930. Begin
  931. SetLength(CDFile.ExtraField,CDFile.ExtraFieldLength);
  932. MS.Read(CDFile.ExtraField[1], CDFile.ExtraFieldLength);
  933. End;
  934. If CDFile.FileCommentLength > 0 Then
  935. Begin
  936. SetLength(CDFile.FileComment,CDFile.FileCommentLength);
  937. MS.Read(CDFile.FileComment[1],CDFile.FileCommentLength);
  938. End;
  939. Entry.FIsFolder := (CDFile.ExternalFileAttributes and faDirectory) > 0;
  940. Entry.FCompressionType := ctUnknown;
  941. if (CDFile.CompressionMethod=8) or (CDFile.CompressionMethod=9) Then
  942. Begin
  943. Case CDFile.GeneralPurposeBitFlag AND 6 of
  944. 0 : Entry.FCompressionType := ctNormal;
  945. 2 : Entry.FCompressionType := ctMaximum;
  946. 4 : Entry.FCompressionType := ctFast;
  947. 6 : Entry.FCompressionType := ctSuperFast
  948. End;
  949. End;
  950. Entry.FCentralDirectoryFile := CDFile;
  951. If Assigned(FParent.FOnZipOpen) Then FParent.FOnZipOpen(FParent,X,FParent.FEndOfCentralDir.TotalNumberOfEntriesOnThisDisk);
  952. End;
  953. Except
  954. Exit;
  955. End;
  956. Result := Count=FParent.FEndOfCentralDir.TotalNumberOfEntriesOnThisDisk;
  957. end;
  958. procedure TKAZipEntries.ParseZip(MS: TStream);
  959. begin
  960. FIsZipFile := False;
  961. Clear;
  962. if FindCentralDirectory(MS) Then
  963. Begin
  964. if ParseCentralHeaders(MS) Then
  965. Begin
  966. FIsZipFile := True;
  967. LoadLocalHeaders(MS);
  968. End;
  969. End
  970. Else
  971. Begin
  972. if ParseLocalHeaders(MS) Then
  973. Begin
  974. FIsZipFile := Count > 0;
  975. if FIsZipFile Then FParent.FHasBadEntries := True;
  976. End;
  977. End;
  978. end;
  979. function TKAZipEntries.GetLocalEntry(MS: TStream; Offset : Integer; HeaderOnly : Boolean): TLocalFile;
  980. Var
  981. Byte_ : Array[0..4] of Byte;
  982. DataDescriptor : TDataDescriptor;
  983. ddvalid : boolean;
  984. fp,fp2 : Int64;
  985. begin
  986. FillChar(Result,SizeOf(Result),0);
  987. MS.Position := Offset;
  988. MS.Read(Byte_,4);
  989. if (Byte_[0] = $50)
  990. And (Byte_[1] = $4B)
  991. And (Byte_[2] = $03)
  992. And (Byte_[3] = $04) Then
  993. Begin
  994. MS.Position := Offset;
  995. MS.Read(Result,SizeOf(Result)-3*SizeOf(AnsiString));
  996. if Result.FilenameLength > 0 Then
  997. Begin
  998. SetLength(Result.FileName,Result.FilenameLength);
  999. MS.Read(Result.FileName[1],Result.FilenameLength);
  1000. End;
  1001. if Result.ExtraFieldLength > 0 Then
  1002. Begin
  1003. SetLength(Result.ExtraField,Result.ExtraFieldLength);
  1004. MS.Read(Result.ExtraField[1],Result.ExtraFieldLength);
  1005. End;
  1006. if (Result.GeneralPurposeBitFlag And (1 SHL 3)) > 0 Then
  1007. Begin
  1008. fp:= MS.Position;
  1009. ddvalid:= false;
  1010. repeat
  1011. MS.Read(Byte_,4);
  1012. if (Byte_[0] = $50) And (Byte_[1] = $4B) And (Byte_[2] = $07) And (Byte_[3] = $08) then begin
  1013. MS.Seek(-4, soFromCurrent);
  1014. fp2:= MS.Position;
  1015. MS.Read(DataDescriptor,SizeOf(TDataDescriptor));
  1016. if DataDescriptor.CompressedSize=fp2-fp then begin
  1017. ddvalid:= true;
  1018. break;
  1019. end else
  1020. MS.Position:= fp2+4;
  1021. end;
  1022. MS.Seek(-3,soFromCurrent);
  1023. until MS.position=MS.Size;
  1024. MS.Position:= fp;
  1025. if ddvalid then begin
  1026. Result.Crc32 := DataDescriptor.Crc32;
  1027. Result.CompressedSize := DataDescriptor.CompressedSize;
  1028. Result.UnCompressedSize := DataDescriptor.UnCompressedSize;
  1029. end else
  1030. raise Exception.CreateFmt('Missing data descriptor for file "%s"',[Result.FileName]);
  1031. End;
  1032. if Not HeaderOnly Then
  1033. Begin
  1034. if Result.CompressedSize > 0 Then
  1035. Begin
  1036. SetLength(Result.CompressedData,Result.CompressedSize);
  1037. MS.Read(Result.CompressedData[1],Result.CompressedSize);
  1038. End;
  1039. End;
  1040. End
  1041. Else
  1042. Begin
  1043. End;
  1044. end;
  1045. procedure TKAZipEntries.LoadLocalHeaders(MS: TStream);
  1046. Var
  1047. X : Integer;
  1048. begin
  1049. FParent.FHasBadEntries := False;
  1050. For X := 0 To Count-1 do
  1051. Begin
  1052. If Assigned(FParent.FOnZipOpen) Then FParent.FOnZipOpen(FParent,X,FParent.FEndOfCentralDir.TotalNumberOfEntriesOnThisDisk);
  1053. Items[X].FLocalFile := GetLocalEntry(MS,Items[X].FCentralDirectoryFile.RelativeOffsetOfLocalHeader,True);
  1054. if Items[X].FLocalFile.LocalFileHeaderSignature<>$04034b50 Then FParent.FHasBadEntries := True;
  1055. End;
  1056. end;
  1057. function TKAZipEntries.ParseLocalHeaders(MS: TStream): Boolean;
  1058. Var
  1059. Poz : Integer;
  1060. NLE : Integer;
  1061. Byte_ : Array[0..4] of Byte;
  1062. LocalFile : TLocalFile;
  1063. DataDescriptor : TDataDescriptor;
  1064. Entry : TKAZipEntriesEntry;
  1065. CDFile : TCentralDirectoryFile;
  1066. CDSize : Cardinal;
  1067. L : Integer;
  1068. NoMore : Boolean;
  1069. fp, fp2 : Int64;
  1070. ddvalid : boolean;
  1071. begin
  1072. Result := False;
  1073. FLocalHeaderNumFiles := 0;
  1074. Clear;
  1075. Try
  1076. Poz := 0;
  1077. NLE := 0;
  1078. CDSize := 0;
  1079. Repeat
  1080. NoMore := True;
  1081. MS.Position := Poz;
  1082. MS.Read(Byte_,4);
  1083. if (Byte_[0] = $50)
  1084. And (Byte_[1] = $4B)
  1085. And (Byte_[2] = $03)
  1086. And (Byte_[3] = $04) Then
  1087. Begin
  1088. Result := True;
  1089. Inc(FLocalHeaderNumFiles);
  1090. NoMore := False;
  1091. MS.Position := Poz;
  1092. MS.Read(LocalFile,SizeOf(TLocalFile)-3*SizeOf(String));
  1093. if LocalFile.FilenameLength > 0 Then
  1094. Begin
  1095. SetLength(LocalFile.FileName,LocalFile.FilenameLength);
  1096. MS.Read(LocalFile.FileName[1],LocalFile.FilenameLength);
  1097. End;
  1098. if LocalFile.ExtraFieldLength > 0 Then
  1099. Begin
  1100. SetLength(LocalFile.ExtraField,LocalFile.ExtraFieldLength);
  1101. MS.Read(LocalFile.ExtraField[1],LocalFile.ExtraFieldLength);
  1102. End;
  1103. if (LocalFile.GeneralPurposeBitFlag And (1 SHL 3)) > 0 Then
  1104. Begin
  1105. fp:= MS.Position;
  1106. ddvalid:= false;
  1107. repeat
  1108. MS.Read(Byte_,4);
  1109. if (Byte_[0] = $50) And (Byte_[1] = $4B) And (Byte_[2] = $07) And (Byte_[3] = $08) then begin
  1110. MS.Seek(-4, soFromCurrent);
  1111. fp2:= MS.Position;
  1112. MS.Read(DataDescriptor,SizeOf(TDataDescriptor));
  1113. if DataDescriptor.CompressedSize=fp2-fp then begin
  1114. ddvalid:= true;
  1115. break;
  1116. end else
  1117. MS.Position:= fp2+4;
  1118. end;
  1119. MS.Seek(-3,soFromCurrent);
  1120. until MS.position=MS.Size;
  1121. MS.Position:= fp;
  1122. if ddvalid then begin
  1123. LocalFile.Crc32 := DataDescriptor.Crc32;
  1124. LocalFile.CompressedSize := DataDescriptor.CompressedSize;
  1125. LocalFile.UnCompressedSize := DataDescriptor.UnCompressedSize;
  1126. end else
  1127. raise Exception.CreateFmt('Missing data descriptor for file "%s"',[LocalFile.FileName]);
  1128. End;
  1129. MS.Position := MS.Position+LocalFile.CompressedSize;
  1130. FillChar(CDFile,SizeOf(TCentralDirectoryFile)-3*Sizeof(String),0);
  1131. CDFile.CentralFileHeaderSignature := $02014B50;
  1132. CDFile.VersionMadeBy := 20;
  1133. CDFile.VersionNeededToExtract := LocalFile.VersionNeededToExtract;
  1134. CDFile.GeneralPurposeBitFlag := LocalFile.GeneralPurposeBitFlag;
  1135. CDFile.CompressionMethod := LocalFile.CompressionMethod;
  1136. CDFile.LastModFileTimeDate := LocalFile.LastModFileTimeDate;
  1137. CDFile.Crc32 := LocalFile.Crc32;
  1138. CDFile.CompressedSize := LocalFile.CompressedSize;
  1139. CDFile.UncompressedSize := LocalFile.UncompressedSize;
  1140. CDFile.FilenameLength := LocalFile.FilenameLength;
  1141. CDFile.ExtraFieldLength := LocalFile.ExtraFieldLength;
  1142. CDFile.FileCommentLength := 0;
  1143. CDFile.DiskNumberStart := 0;
  1144. CDFile.InternalFileAttributes := LocalFile.VersionNeededToExtract;
  1145. CDFile.ExternalFileAttributes := faArchive;
  1146. CDFile.RelativeOffsetOfLocalHeader := Poz;
  1147. CDFile.FileName := LocalFile.FileName;
  1148. L := Length(CDFile.FileName);
  1149. if L > 0 Then
  1150. Begin
  1151. if CDFile.FileName[L]='/' Then CDFile.ExternalFileAttributes := faDirectory;
  1152. End;
  1153. CDFile.ExtraField := LocalFile.ExtraField;
  1154. CDFile.FileComment := '';
  1155. Entry := TKAZipEntriesEntry.Create(Self);
  1156. Entry.FDate := FileDateToDateTime(CDFile.LastModFileTimeDate);
  1157. if (CDFile.GeneralPurposeBitFlag And 1) > 0 Then
  1158. Entry.FIsEncrypted := True
  1159. Else
  1160. Entry.FIsEncrypted := False;
  1161. Entry.FIsFolder := (CDFile.ExternalFileAttributes and faDirectory) > 0;
  1162. Entry.FCompressionType := ctUnknown;
  1163. if (CDFile.CompressionMethod=8) or (CDFile.CompressionMethod=9) Then
  1164. Begin
  1165. Case CDFile.GeneralPurposeBitFlag AND 6 of
  1166. 0 : Entry.FCompressionType := ctNormal;
  1167. 2 : Entry.FCompressionType := ctMaximum;
  1168. 4 : Entry.FCompressionType := ctFast;
  1169. 6 : Entry.FCompressionType := ctSuperFast
  1170. End;
  1171. End;
  1172. Entry.FCentralDirectoryFile := CDFile;
  1173. Poz := MS.Position;
  1174. Inc(NLE);
  1175. CDSize := CDSize+Entry.CentralEntrySize;
  1176. End;
  1177. Until NoMore;
  1178. FParent.FEndOfCentralDir.EndOfCentralDirSignature := $06054b50;
  1179. FParent.FEndOfCentralDir.NumberOfThisDisk := 0;
  1180. FParent.FEndOfCentralDir.NumberOfTheDiskWithTheStart := 0;
  1181. FParent.FEndOfCentralDir.TotalNumberOfEntriesOnThisDisk := NLE;
  1182. FParent.FEndOfCentralDir.SizeOfTheCentralDirectory := CDSize;
  1183. FParent.FEndOfCentralDir.OffsetOfStartOfCentralDirectory := MS.Position;
  1184. FParent.FEndOfCentralDir.ZipfileCommentLength := 0;
  1185. Except
  1186. Exit;
  1187. End;
  1188. end;
  1189. procedure TKAZipEntries.Remove(ItemIndex: Integer; Flush : Boolean);
  1190. Var
  1191. TempStream : TFileStream;
  1192. TempMSStream : TMemoryStream;
  1193. TempFileName : String;
  1194. BUF : String;
  1195. ZipComment : String;
  1196. OSL : Cardinal;
  1197. //*********************************************
  1198. X : Integer;
  1199. TargetPos : Cardinal;
  1200. Border : Cardinal;
  1201. NR : Integer;
  1202. NW : Integer;
  1203. BufStart : Integer;
  1204. BufLen : Integer;
  1205. ShiftSize : Cardinal;
  1206. NewSize : Cardinal;
  1207. begin
  1208. TargetPos := Items[ItemIndex].FCentralDirectoryFile.RelativeOffsetOfLocalHeader;
  1209. ShiftSize := Items[ItemIndex].LocalEntrySize;
  1210. BufStart := TargetPos+ShiftSize;
  1211. BufLen := FParent.FZipStream.Size-BufStart;
  1212. Border := TargetPos;
  1213. Delete(ItemIndex);
  1214. if (FParent.FZipSaveMethod=FastSave) AND (Count > 0) Then
  1215. Begin
  1216. ZipComment := FParent.Comment.Text;
  1217. SetLength(BUF,BufLen);
  1218. FParent.FZipStream.Position := BufStart;
  1219. NR := FParent.FZipStream.Read(BUF[1],BufLen);
  1220. FParent.FZipStream.Position := TargetPos;
  1221. NW := FParent.FZipStream.Write(BUF[1],BufLen);
  1222. SetLength(BUF,0);
  1223. For X := 0 to Count-1 do
  1224. Begin
  1225. if Items[X].FCentralDirectoryFile.RelativeOffsetOfLocalHeader > Border Then
  1226. Begin
  1227. Dec(Items[X].FCentralDirectoryFile.RelativeOffsetOfLocalHeader, ShiftSize);
  1228. TargetPos := TargetPos+Items[X].LocalEntrySize;
  1229. End
  1230. End;
  1231. FParent.FZipStream.Position := TargetPos;
  1232. //************************************ MARK START OF CENTRAL DIRECTORY
  1233. FParent.FEndOfCentralDir.OffsetOfStartOfCentralDirectory := FParent.FZipStream.Position;
  1234. //************************************ SAVE CENTRAL DIRECTORY
  1235. For X := 0 To Count-1 do
  1236. Begin
  1237. FParent.FZipStream.Write(Self.Items[X].FCentralDirectoryFile,SizeOf(Self.Items[X].FCentralDirectoryFile)-3*SizeOf(String));
  1238. if Self.Items[X].FCentralDirectoryFile.FilenameLength > 0 Then
  1239. FParent.FZipStream.Write(Self.Items[X].FCentralDirectoryFile.FileName[1],Self.Items[X].FCentralDirectoryFile.FilenameLength);
  1240. if Self.Items[X].FCentralDirectoryFile.ExtraFieldLength > 0 Then
  1241. FParent.FZipStream.Write(Self.Items[X].FCentralDirectoryFile.ExtraField[1],Self.Items[X].FCentralDirectoryFile.ExtraFieldLength);
  1242. if Self.Items[X].FCentralDirectoryFile.FileCommentLength > 0 Then
  1243. FParent.FZipStream.Write(Self.Items[X].FCentralDirectoryFile.FileComment[1],Self.Items[X].FCentralDirectoryFile.FileCommentLength);
  1244. End;
  1245. //************************************ SAVE END CENTRAL DIRECTORY RECORD
  1246. FParent.FEndOfCentralDirPos := FParent.FZipStream.Position;
  1247. FParent.FEndOfCentralDir.SizeOfTheCentralDirectory := FParent.FEndOfCentralDirPos-FParent.FEndOfCentralDir.OffsetOfStartOfCentralDirectory;
  1248. Dec(FParent.FEndOfCentralDir.TotalNumberOfEntriesOnThisDisk);
  1249. Dec(FParent.FEndOfCentralDir.TotalNumberOfEntries);
  1250. FParent.FZipStream.Write(FParent.FEndOfCentralDir, SizeOf(TEndOfCentralDir));
  1251. //************************************ SAVE ZIP COMMENT IF ANY
  1252. FParent.FZipCommentPos := FParent.FZipStream.Position;
  1253. if Length(ZipComment) > 0 Then
  1254. Begin
  1255. FParent.FZipStream.Write(ZipComment[1],Length(ZipComment));
  1256. End;
  1257. FParent.FZipStream.Size := FParent.FZipStream.Position;
  1258. End
  1259. Else
  1260. Begin
  1261. if FParent.FUseTempFiles Then
  1262. Begin
  1263. TempFileName := FParent.GetDelphiTempFileName;
  1264. TempStream := TFileStream.Create(TempFileName,fmOpenReadWrite or FmCreate);
  1265. Try
  1266. FParent.SaveToStream(TempStream);
  1267. TempStream.Position := 0;
  1268. OSL := FParent.FZipStream.Size;
  1269. Try
  1270. FParent.FZipStream.Size := TempStream.Size;
  1271. Except
  1272. FParent.FZipStream.Size := OSL;
  1273. Raise;
  1274. End;
  1275. FParent.FZipStream.Position := 0;
  1276. FParent.FZipStream.CopyFrom(TempStream,TempStream.Size);
  1277. //*********************************************************************
  1278. FParent.FZipHeader.ParseZip(FParent.FZipStream);
  1279. //*********************************************************************
  1280. Finally
  1281. TempStream.Free;
  1282. DeleteFile(TempFileName)
  1283. End;
  1284. End
  1285. Else
  1286. Begin
  1287. NewSize := 0;
  1288. For X := 0 To Count-1 do
  1289. Begin
  1290. NewSize := NewSize+Items[X].LocalEntrySize+Items[X].CentralEntrySize;
  1291. if Assigned(FParent.FOnRemoveItems) Then FParent.FOnRemoveItems(FParent,X,Count-1);
  1292. End;
  1293. NewSize := NewSize+SizeOf(FParent.FEndOfCentralDir)+FParent.FEndOfCentralDir.ZipfileCommentLength;
  1294. TempMSStream := TMemoryStream.Create;
  1295. Try
  1296. TempMSStream.SetSize(NewSize);
  1297. TempMSStream.Position := 0;
  1298. FParent.SaveToStream(TempMSStream);
  1299. TempMSStream.Position := 0;
  1300. OSL := FParent.FZipStream.Size;
  1301. Try
  1302. FParent.FZipStream.Size := TempMSStream.Size;
  1303. Except
  1304. FParent.FZipStream.Size := OSL;
  1305. Raise;
  1306. End;
  1307. FParent.FZipStream.Position := 0;
  1308. FParent.FZipStream.CopyFrom(TempMSStream,TempMSStream.Size);
  1309. //*********************************************************************
  1310. FParent.FZipHeader.ParseZip(FParent.FZipStream);
  1311. //*********************************************************************
  1312. Finally
  1313. TempMSStream.Free;
  1314. End;
  1315. End;
  1316. End;
  1317. FParent.FIsDirty := True;
  1318. if NOT FParent.FBatchMode Then
  1319. Begin
  1320. FParent.DoChange(FParent,3);
  1321. End;
  1322. end;
  1323. procedure TKAZipEntries.Remove(ItemIndex: Integer);
  1324. Begin
  1325. Remove(ItemIndex,True);
  1326. End;
  1327. procedure TKAZipEntries.Remove(Item: TKAZipEntriesEntry);
  1328. Var
  1329. X : Integer;
  1330. begin
  1331. For X := 0 To Count-1 do
  1332. Begin
  1333. if Self.Items[X]=Item Then
  1334. Begin
  1335. Remove(X);
  1336. Exit;
  1337. End;
  1338. End;
  1339. end;
  1340. procedure TKAZipEntries.Remove(FileName: String);
  1341. Var
  1342. I : Integer;
  1343. begin
  1344. I := IndexOf(FileName);
  1345. if I <> -1 Then Remove(I);
  1346. end;
  1347. procedure TKAZipEntries.RemoveBatch(Files:TList);
  1348. Var
  1349. X : Integer;
  1350. OSL : Integer;
  1351. NewSize : Cardinal;
  1352. TempStream : TFileStream;
  1353. TempMSStream : TMemoryStream;
  1354. TempFileName : String;
  1355. Begin
  1356. For X := Files.Count-1 DownTo 0 do
  1357. Begin
  1358. Delete(Integer(Files.Items[X]));
  1359. if Assigned(FParent.FOnRemoveItems) Then FParent.FOnRemoveItems(FParent,Files.Count-X,Files.Count);
  1360. End;
  1361. NewSize := 0;
  1362. if FParent.FUseTempFiles Then
  1363. Begin
  1364. TempFileName := FParent.GetDelphiTempFileName;
  1365. TempStream := TFileStream.Create(TempFileName,fmOpenReadWrite or FmCreate);
  1366. Try
  1367. FParent.SaveToStream(TempStream);
  1368. TempStream.Position := 0;
  1369. OSL := FParent.FZipStream.Size;
  1370. Try
  1371. FParent.FZipStream.Size := TempStream.Size;
  1372. Except
  1373. FParent.FZipStream.Size := OSL;
  1374. Raise;
  1375. End;
  1376. FParent.FZipStream.Position := 0;
  1377. FParent.FZipStream.CopyFrom(TempStream,TempStream.Size);
  1378. //*********************************************************************
  1379. FParent.FZipHeader.ParseZip(FParent.FZipStream);
  1380. //*********************************************************************
  1381. Finally
  1382. TempStream.Free;
  1383. DeleteFile(TempFileName)
  1384. End;
  1385. End
  1386. Else
  1387. Begin
  1388. For X := 0 To Count-1 do
  1389. Begin
  1390. NewSize := NewSize+Items[X].LocalEntrySize+Items[X].CentralEntrySize;
  1391. if Assigned(FParent.FOnRemoveItems) Then FParent.FOnRemoveItems(FParent,X,Count-1);
  1392. End;
  1393. NewSize := NewSize+SizeOf(FParent.FEndOfCentralDir)+FParent.FEndOfCentralDir.ZipfileCommentLength;
  1394. TempMSStream := TMemoryStream.Create;
  1395. Try
  1396. TempMSStream.SetSize(NewSize);
  1397. TempMSStream.Position := 0;
  1398. FParent.SaveToStream(TempMSStream);
  1399. TempMSStream.Position := 0;
  1400. OSL := FParent.FZipStream.Size;
  1401. Try
  1402. FParent.FZipStream.Size := TempMSStream.Size;
  1403. Except
  1404. FParent.FZipStream.Size := OSL;
  1405. Raise;
  1406. End;
  1407. FParent.FZipStream.Position := 0;
  1408. FParent.FZipStream.CopyFrom(TempMSStream,TempMSStream.Size);
  1409. //*********************************************************************
  1410. FParent.FZipHeader.ParseZip(FParent.FZipStream);
  1411. //*********************************************************************
  1412. Finally
  1413. TempMSStream.Free;
  1414. End;
  1415. End;
  1416. End;
  1417. Function TKAZipEntries.IndexOf(Const FileName:String):Integer;
  1418. Var
  1419. X : Integer;
  1420. FN : String;
  1421. Begin
  1422. Result := -1;
  1423. FN := ToZipName(FileName);
  1424. For X := 0 To Count-1 do
  1425. Begin
  1426. if AnsiCompareText(FN,ToZipName(Items[X].FCentralDirectoryFile.FileName))=0 Then
  1427. Begin
  1428. Result := X;
  1429. Exit;
  1430. End;
  1431. End;
  1432. End;
  1433. Function TKAZipEntries.AddStreamFast( ItemName : String;
  1434. FileAttr : Word;
  1435. FileDate : TDateTime;
  1436. Stream : TStream):TKAZipEntriesEntry;
  1437. Var
  1438. Compressor : TCompressionStream;
  1439. CS : TStringStream;
  1440. CM : WORD;
  1441. S : String;
  1442. X : Integer;
  1443. I : Integer;
  1444. UL : Integer;
  1445. CL : Integer;
  1446. FCRC32 : Cardinal;
  1447. SizeToAppend : Integer;
  1448. ZipComment : String;
  1449. Level : TCompressionLevel;
  1450. OBM : Boolean;
  1451. begin
  1452. //*********************************** COMPRESS DATA
  1453. ZipComment := FParent.Comment.Text;
  1454. if NOT FParent.FStoreRelativePath Then
  1455. ItemName := ExtractFileName(ItemName);
  1456. ItemName := ToZipName(ItemName);
  1457. I := IndexOf(ItemName);
  1458. if I > -1 Then
  1459. Begin
  1460. OBM := FParent.FBatchMode;
  1461. Try
  1462. if OBM=False Then FParent.FBatchMode := True;
  1463. Remove(I);
  1464. Finally
  1465. FParent.FBatchMode := OBM;
  1466. End;
  1467. End;
  1468. CS := TStringStream.Create('');
  1469. CS.Position := 0;
  1470. Try
  1471. UL := Stream.Size-Stream.Position;
  1472. SetLength(S,UL);
  1473. CM := 0;
  1474. if UL > 0 Then
  1475. Begin
  1476. Stream.Read(S[1],UL);
  1477. CM := 8;
  1478. End;
  1479. FCRC32 := CalcCRC32(S);
  1480. FParent.FCurrentDFS := UL;
  1481. Level := clDefault;
  1482. Case FParent.FZipCompressionType of
  1483. ctNormal : Level := clDefault;
  1484. ctMaximum : Level := clMax;
  1485. ctFast : Level := clFastest;
  1486. ctSuperFast : Level := clFastest;
  1487. ctNone : Level := clNone;
  1488. End;
  1489. if CM = 8 Then
  1490. Begin
  1491. Compressor := TCompressionStream.Create(Level,CS);
  1492. Try
  1493. Compressor.OnProgress := FParent.OnCompress;
  1494. Compressor.Write(S[1],UL);
  1495. Finally
  1496. Compressor.Free;
  1497. End;
  1498. S := Copy(CS.DataString, 3, Length(CS.DataString)-6);
  1499. End;
  1500. Finally
  1501. CS.Free;
  1502. End;
  1503. //***********************************
  1504. CL := Length(S);
  1505. //*********************************** FILL RECORDS
  1506. Result := TKAZipEntriesEntry(Self.Add);
  1507. With Result.FLocalFile do
  1508. Begin
  1509. LocalFileHeaderSignature := $04034B50;
  1510. VersionNeededToExtract := 20;
  1511. GeneralPurposeBitFlag := 0;
  1512. CompressionMethod := CM;
  1513. LastModFileTimeDate := DateTimeToFileDate(FileDate);
  1514. Crc32 := FCRC32;
  1515. CompressedSize := CL;
  1516. UncompressedSize := UL;
  1517. FilenameLength := Length(ItemName);
  1518. ExtraFieldLength := 0;
  1519. FileName := ItemName;
  1520. ExtraField := '';
  1521. CompressedData := '';
  1522. End;
  1523. With Result.FCentralDirectoryFile Do
  1524. Begin
  1525. CentralFileHeaderSignature := $02014B50;
  1526. VersionMadeBy := 20;
  1527. VersionNeededToExtract := 20;
  1528. GeneralPurposeBitFlag := 0;
  1529. CompressionMethod := CM;
  1530. LastModFileTimeDate := DateTimeToFileDate(FileDate);
  1531. Crc32 := FCRC32;
  1532. CompressedSize := CL;
  1533. UncompressedSize := UL;
  1534. FilenameLength := Length(ItemName);
  1535. ExtraFieldLength := 0;
  1536. FileCommentLength := 0;
  1537. DiskNumberStart := 0;
  1538. InternalFileAttributes := 0;
  1539. ExternalFileAttributes := FileAttr;
  1540. RelativeOffsetOfLocalHeader := FParent.FEndOfCentralDir.OffsetOfStartOfCentralDirectory;
  1541. FileName := ItemName;
  1542. ExtraField := '';
  1543. FileComment := '';
  1544. End;
  1545. //************************************ EXPAND ZIP STREAM SIZE
  1546. SizeToAppend := 0;
  1547. SizeToAppend := SizeToAppend+SizeOf(Result.FLocalFile)-3*SizeOf(String);
  1548. SizeToAppend := SizeToAppend+Result.FLocalFile.FilenameLength;
  1549. SizeToAppend := SizeToAppend+CL;
  1550. SizeToAppend := SizeToAppend+SizeOf(Result.FCentralDirectoryFile)-3*SizeOf(String);
  1551. SizeToAppend := SizeToAppend+Result.FCentralDirectoryFile.FilenameLength;
  1552. FParent.FZipStream.Size := FParent.FZipStream.Size+SizeToAppend;
  1553. //************************************ SAVE LOCAL HEADER AND COMPRESSED DATA
  1554. FParent.FZipStream.Position := Result.FCentralDirectoryFile.RelativeOffsetOfLocalHeader;
  1555. FParent.FZipStream.Write(Result.FLocalFile,SizeOf(Result.FLocalFile)-3*SizeOf(String));
  1556. if Result.FLocalFile.FilenameLength > 0 Then FParent.FZipStream.Write(Result.FLocalFile.FileName[1],Result.FLocalFile.FilenameLength);
  1557. if CL > 0 Then FParent.FZipStream.Write(S[1],CL);
  1558. //************************************ MARK START OF CENTRAL DIRECTORY
  1559. FParent.FEndOfCentralDir.OffsetOfStartOfCentralDirectory := FParent.FZipStream.Position;
  1560. //************************************ SAVE CENTRAL DIRECTORY
  1561. For X := 0 To Count-1 do
  1562. Begin
  1563. FParent.FZipStream.Write(Self.Items[X].FCentralDirectoryFile,SizeOf(Self.Items[X].FCentralDirectoryFile)-3*SizeOf(String));
  1564. if Self.Items[X].FCentralDirectoryFile.FilenameLength > 0 Then
  1565. FParent.FZipStream.Write(Self.Items[X].FCentralDirectoryFile.FileName[1],Self.Items[X].FCentralDirectoryFile.FilenameLength);
  1566. if Self.Items[X].FCentralDirectoryFile.ExtraFieldLength > 0 Then
  1567. FParent.FZipStream.Write(Self.Items[X].FCentralDirectoryFile.ExtraField[1],Self.Items[X].FCentralDirectoryFile.ExtraFieldLength);
  1568. if Self.Items[X].FCentralDirectoryFile.FileCommentLength > 0 Then
  1569. FParent.FZipStream.Write(Self.Items[X].FCentralDirectoryFile.FileComment[1],Self.Items[X].FCentralDirectoryFile.FileCommentLength);
  1570. End;
  1571. //************************************ SAVE END CENTRAL DIRECTORY RECORD
  1572. FParent.FEndOfCentralDirPos := FParent.FZipStream.Position;
  1573. FParent.FEndOfCentralDir.SizeOfTheCentralDirectory := FParent.FEndOfCentralDirPos-FParent.FEndOfCentralDir.OffsetOfStartOfCentralDirectory;
  1574. Inc(FParent.FEndOfCentralDir.TotalNumberOfEntriesOnThisDisk);
  1575. Inc(FParent.FEndOfCentralDir.TotalNumberOfEntries);
  1576. FParent.FZipStream.Write(FParent.FEndOfCentralDir, SizeOf(TEndOfCentralDir));
  1577. //************************************ SAVE ZIP COMMENT IF ANY
  1578. FParent.FZipCommentPos := FParent.FZipStream.Position;
  1579. if Length(ZipComment) > 0 Then
  1580. Begin
  1581. FParent.FZipStream.Write(ZipComment[1],Length(ZipComment));
  1582. End;
  1583. Result.FDate := FileDate;
  1584. if (Result.FCentralDirectoryFile.GeneralPurposeBitFlag And 1) > 0 Then
  1585. Result.FIsEncrypted := True
  1586. Else
  1587. Result.FIsEncrypted := False;
  1588. Result.FIsFolder := (Result.FCentralDirectoryFile.ExternalFileAttributes and faDirectory) > 0;
  1589. Result.FCompressionType := ctUnknown;
  1590. if (Result.FCentralDirectoryFile.CompressionMethod=8) or (Result.FCentralDirectoryFile.CompressionMethod=9) Then
  1591. Begin
  1592. Case Result.FCentralDirectoryFile.GeneralPurposeBitFlag AND 6 of
  1593. 0 : Result.FCompressionType := ctNormal;
  1594. 2 : Result.FCompressionType := ctMaximum;
  1595. 4 : Result.FCompressionType := ctFast;
  1596. 6 : Result.FCompressionType := ctSuperFast
  1597. End;
  1598. End;
  1599. FParent.FIsDirty := True;
  1600. if NOT FParent.FBatchMode Then
  1601. Begin
  1602. FParent.DoChange(FParent,2);
  1603. End;
  1604. end;
  1605. Function TKAZipEntries.AddStreamRebuild( ItemName : String;
  1606. FileAttr : Word;
  1607. FileDate : TDateTime;
  1608. Stream : TStream):TKAZipEntriesEntry;
  1609. Var
  1610. Compressor : TCompressionStream;
  1611. CS : TStringStream;
  1612. CM : Word;
  1613. S : String;
  1614. UL : Integer;
  1615. CL : Integer;
  1616. I : Integer;
  1617. X : Integer;
  1618. FCRC32 : Cardinal;
  1619. OSL : Cardinal;
  1620. NewSize : Cardinal;
  1621. ZipComment : String;
  1622. TempStream : TFileStream;
  1623. TempMSStream : TMemoryStream;
  1624. TempFileName : String;
  1625. Level : TCompressionLevel;
  1626. OBM : Boolean;
  1627. Begin
  1628. if FParent.FUseTempFiles Then
  1629. Begin
  1630. TempFileName := FParent.GetDelphiTempFileName;
  1631. TempStream := TFileStream.Create(TempFileName,fmOpenReadWrite or FmCreate);
  1632. Try
  1633. //*********************************** SAVE ALL OLD LOCAL ITEMS
  1634. FParent.RebuildLocalFiles(TempStream);
  1635. //*********************************** COMPRESS DATA
  1636. ZipComment := FParent.Comment.Text;
  1637. if NOT FParent.FStoreRelativePath Then
  1638. ItemName := ExtractFileName(ItemName);
  1639. ItemName := ToZipName(ItemName);
  1640. I := IndexOf(ItemName);
  1641. if I > -1 Then
  1642. Begin
  1643. OBM := FParent.FBatchMode;
  1644. Try
  1645. if OBM=False Then FParent.FBatchMode := True;
  1646. Remove(I);
  1647. Finally
  1648. FParent.FBatchMode := OBM;
  1649. End;
  1650. End;
  1651. CM := 0;
  1652. CS := TStringStream.Create('');
  1653. CS.Position := 0;
  1654. Try
  1655. UL := Stream.Size-Stream.Position;
  1656. SetLength(S,UL);
  1657. if UL > 0 Then
  1658. Begin
  1659. Stream.Read(S[1],UL);
  1660. CM := 8;
  1661. End;
  1662. FCRC32 := CalcCRC32(S);
  1663. FParent.FCurrentDFS := UL;
  1664. Level := clDefault;
  1665. Case FParent.FZipCompressionType of
  1666. ctNormal : Level := clDefault;
  1667. ctMaximum : Level := clMax;
  1668. ctFast : Level := clFastest;
  1669. ctSuperFast : Level := clFastest;
  1670. ctNone : Level := clNone;
  1671. End;
  1672. if CM=8 Then
  1673. Begin
  1674. Compressor := TCompressionStream.Create(Level,CS);
  1675. Try
  1676. Compressor.OnProgress := FParent.OnCompress;
  1677. Compressor.Write(S[1],UL);
  1678. Finally
  1679. Compressor.Free;
  1680. End;
  1681. S := Copy(CS.DataString, 3, Length(CS.DataString)-6);
  1682. End;
  1683. Finally
  1684. CS.Free;
  1685. End;
  1686. //************************************************************************
  1687. CL := Length(S);
  1688. //*********************************** FILL RECORDS
  1689. Result := TKAZipEntriesEntry(Self.Add);
  1690. With Result.FLocalFile do
  1691. Begin
  1692. LocalFileHeaderSignature := $04034B50;
  1693. VersionNeededToExtract := 20;
  1694. GeneralPurposeBitFlag := 0;
  1695. CompressionMethod := CM;
  1696. LastModFileTimeDate := DateTimeToFileDate(FileDate);
  1697. Crc32 := FCRC32;
  1698. CompressedSize := CL;
  1699. UncompressedSize := UL;
  1700. FilenameLength := Length(ItemName);
  1701. ExtraFieldLength := 0;
  1702. FileName := ItemName;
  1703. ExtraField := '';
  1704. CompressedData := '';
  1705. End;
  1706. With Result.FCentralDirectoryFile Do
  1707. Begin
  1708. CentralFileHeaderSignature := $02014B50;
  1709. VersionMadeBy := 20;
  1710. VersionNeededToExtract := 20;
  1711. GeneralPurposeBitFlag := 0;
  1712. CompressionMethod := CM;
  1713. LastModFileTimeDate := DateTimeToFileDate(FileDate);
  1714. Crc32 := FCRC32;
  1715. CompressedSize := CL;
  1716. UncompressedSize := UL;
  1717. FilenameLength := Length(ItemName);
  1718. ExtraFieldLength := 0;
  1719. FileCommentLength := 0;
  1720. DiskNumberStart := 0;
  1721. InternalFileAttributes := 0;
  1722. ExternalFileAttributes := FileAttr;
  1723. RelativeOffsetOfLocalHeader := TempStream.Position;
  1724. FileName := ItemName;
  1725. ExtraField := '';
  1726. FileComment := '';
  1727. End;
  1728. //************************************ SAVE LOCAL HEADER AND COMPRESSED DATA
  1729. TempStream.Write(Result.FLocalFile,SizeOf(Result.FLocalFile)-3*SizeOf(String));
  1730. if Result.FLocalFile.FilenameLength > 0 Then TempStream.Write(Result.FLocalFile.FileName[1],Result.FLocalFile.FilenameLength);
  1731. if CL > 0 Then TempStream.Write(S[1],CL);
  1732. //************************************
  1733. FParent.NewLHOffsets[Count-1] := Result.FCentralDirectoryFile.RelativeOffsetOfLocalHeader;
  1734. FParent.RebuildCentralDirectory(TempStream);
  1735. FParent.RebuildEndOfCentralDirectory(TempStream);
  1736. //************************************
  1737. TempStream.Position := 0;
  1738. OSL := FParent.FZipStream.Size;
  1739. Try
  1740. FParent.FZipStream.Size := TempStream.Size;
  1741. Except
  1742. FParent.FZipStream.Size := OSL;
  1743. Raise;
  1744. End;
  1745. FParent.FZipStream.Position := 0;
  1746. FParent.FZipStream.CopyFrom(TempStream,TempStream.Size);
  1747. Finally
  1748. TempStream.Free;
  1749. DeleteFile(TempFileName)
  1750. End;
  1751. End
  1752. Else
  1753. Begin
  1754. TempMSStream := TMemoryStream.Create;
  1755. NewSize := 0;
  1756. For X := 0 To Count-1 do
  1757. Begin
  1758. NewSize := NewSize+Items[X].LocalEntrySize+Items[X].CentralEntrySize;
  1759. if Assigned(FParent.FOnRemoveItems) Then FParent.FOnRemoveItems(FParent,X,Count-1);
  1760. End;
  1761. NewSize := NewSize+SizeOf(FParent.FEndOfCentralDir)+FParent.FEndOfCentralDir.ZipfileCommentLength;
  1762. Try
  1763. TempMSStream.SetSize(NewSize);
  1764. TempMSStream.Position := 0;
  1765. //*********************************** SAVE ALL OLD LOCAL ITEMS
  1766. FParent.RebuildLocalFiles(TempMSStream);
  1767. //*********************************** COMPRESS DATA
  1768. ZipComment := FParent.Comment.Text;
  1769. if NOT FParent.FStoreRelativePath Then
  1770. ItemName := ExtractFileName(ItemName);
  1771. ItemName := ToZipName(ItemName);
  1772. I := IndexOf(ItemName);
  1773. if I > -1 Then
  1774. Begin
  1775. OBM := FParent.FBatchMode;
  1776. Try
  1777. if OBM=False Then FParent.FBatchMode := True;
  1778. Remove(I);
  1779. Finally
  1780. FParent.FBatchMode := OBM;
  1781. End;
  1782. End;
  1783. CM := 0;
  1784. CS := TStringStream.Create('');
  1785. CS.Position := 0;
  1786. Try
  1787. UL := Stream.Size-Stream.Position;
  1788. SetLength(S,UL);
  1789. if UL > 0 Then
  1790. Begin
  1791. Stream.Read(S[1],UL);
  1792. CM := 8;
  1793. End;
  1794. FCRC32 := CalcCRC32(S);
  1795. FParent.FCurrentDFS := UL;
  1796. Level := clDefault;
  1797. Case FParent.FZipCompressionType of
  1798. ctNormal : Level := clDefault;
  1799. ctMaximum : Level := clMax;
  1800. ctFast : Level := clFastest;
  1801. ctSuperFast : Level := clFastest;
  1802. ctNone : Level := clNone;
  1803. End;
  1804. if CM=8 Then
  1805. Begin
  1806. Compressor := TCompressionStream.Create(Level,CS);
  1807. Try
  1808. Compressor.OnProgress := FParent.OnCompress;
  1809. Compressor.Write(S[1],UL);
  1810. Finally
  1811. Compressor.Free;
  1812. End;
  1813. S := Copy(CS.DataString, 3, Length(CS.DataString)-6);
  1814. End;
  1815. Finally
  1816. CS.Free;
  1817. End;
  1818. //************************************************************************
  1819. CL := Length(S);
  1820. //*********************************** FILL RECORDS
  1821. Result := TKAZipEntriesEntry(Self.Add);
  1822. With Result.FLocalFile do
  1823. Begin
  1824. LocalFileHeaderSignature := $04034B50;
  1825. VersionNeededToExtract := 20;
  1826. GeneralPurposeBitFlag := 0;
  1827. CompressionMethod := CM;
  1828. LastModFileTimeDate := DateTimeToFileDate(FileDate);
  1829. Crc32 := FCRC32;
  1830. CompressedSize := CL;
  1831. UncompressedSize := UL;
  1832. FilenameLength := Length(ItemName);
  1833. ExtraFieldLength := 0;
  1834. FileName := ItemName;
  1835. ExtraField := '';
  1836. CompressedData := '';
  1837. End;
  1838. With Result.FCentralDirectoryFile Do
  1839. Begin
  1840. CentralFileHeaderSignature := $02014B50;
  1841. VersionMadeBy := 20;
  1842. VersionNeededToExtract := 20;
  1843. GeneralPurposeBitFlag := 0;
  1844. CompressionMethod := CM;
  1845. LastModFileTimeDate := DateTimeToFileDate(FileDate);
  1846. Crc32 := FCRC32;
  1847. CompressedSize := CL;
  1848. UncompressedSize := UL;
  1849. FilenameLength := Length(ItemName);
  1850. ExtraFieldLength := 0;
  1851. FileCommentLength := 0;
  1852. DiskNumberStart := 0;
  1853. InternalFileAttributes := 0;
  1854. ExternalFileAttributes := FileAttr;
  1855. RelativeOffsetOfLocalHeader := TempMSStream.Position;
  1856. FileName := ItemName;
  1857. ExtraField := '';
  1858. FileComment := '';
  1859. End;
  1860. //************************************ SAVE LOCAL HEADER AND COMPRESSED DATA
  1861. TempMSStream.Write(Result.FLocalFile,SizeOf(Result.FLocalFile)-3*SizeOf(String));
  1862. if Result.FLocalFile.FilenameLength > 0 Then TempMSStream.Write(Result.FLocalFile.FileName[1],Result.FLocalFile.FilenameLength);
  1863. if CL > 0 Then TempMSStream.Write(S[1],CL);
  1864. //************************************
  1865. FParent.NewLHOffsets[Count-1] := Result.FCentralDirectoryFile.RelativeOffsetOfLocalHeader;
  1866. FParent.RebuildCentralDirectory(TempMSStream);
  1867. FParent.RebuildEndOfCentralDirectory(TempMSStream);
  1868. //************************************
  1869. TempMSStream.Position := 0;
  1870. OSL := FParent.FZipStream.Size;
  1871. Try
  1872. FParent.FZipStream.Size := TempMSStream.Size;
  1873. Except
  1874. FParent.FZipStream.Size := OSL;
  1875. Raise;
  1876. End;
  1877. FParent.FZipStream.Position := 0;
  1878. FParent.FZipStream.CopyFrom(TempMSStream,TempMSStream.Size);
  1879. Finally
  1880. TempMSStream.Free;
  1881. End;
  1882. End;
  1883. Result.FDate := FileDateToDateTime(Result.FCentralDirectoryFile.LastModFileTimeDate);
  1884. if (Result.FCentralDirectoryFile.GeneralPurposeBitFlag And 1) > 0 Then
  1885. Result.FIsEncrypted := True
  1886. Else
  1887. Result.FIsEncrypted := False;
  1888. Result.FIsFolder := (Result.FCentralDirectoryFile.ExternalFileAttributes and faDirectory) > 0;
  1889. Result.FCompressionType := ctUnknown;
  1890. if (Result.FCentralDirectoryFile.CompressionMethod=8) or (Result.FCentralDirectoryFile.CompressionMethod=9) Then
  1891. Begin
  1892. Case Result.FCentralDirectoryFile.GeneralPurposeBitFlag AND 6 of
  1893. 0 : Result.FCompressionType := ctNormal;
  1894. 2 : Result.FCompressionType := ctMaximum;
  1895. 4 : Result.FCompressionType := ctFast;
  1896. 6 : Result.FCompressionType := ctSuperFast
  1897. End;
  1898. End;
  1899. FParent.FIsDirty := True;
  1900. if NOT FParent.FBatchMode Then
  1901. Begin
  1902. FParent.DoChange(FParent,2);
  1903. End;
  1904. End;
  1905. function TKAZipEntries.AddFolderChain(ItemName: String; FileAttr: Word;
  1906. FileDate: TDateTime): Boolean;
  1907. Var
  1908. FN : String;
  1909. TN : String;
  1910. INCN : String;
  1911. P : Integer;
  1912. MS : TMemoryStream;
  1913. NoMore : Boolean;
  1914. Begin
  1915. Result := False;
  1916. FN := ExtractFilePath(ToDosName(ToZipName(ItemName)));
  1917. TN := FN;
  1918. INCN := '';
  1919. MS := TMemoryStream.Create;
  1920. Try
  1921. Repeat
  1922. NoMore := True;
  1923. P := Pos('\',TN);
  1924. if P > 0 Then
  1925. Begin
  1926. INCN := INCN+Copy(TN,1,P);
  1927. System.Delete(TN,1,P);
  1928. MS.Position := 0;
  1929. MS.Size := 0;
  1930. If IndexOf(INCN) = -1 Then
  1931. Begin
  1932. if FParent.FZipSaveMethod = FastSave Then
  1933. AddStreamFast(INCN,FileAttr,FileDate,MS)
  1934. Else
  1935. if FParent.FZipSaveMethod = RebuildAll Then
  1936. AddStreamRebuild(INCN,FileAttr,FileDate,MS);
  1937. End;
  1938. NoMore := False;
  1939. End;
  1940. Until NoMore;
  1941. Result := True;
  1942. Finally
  1943. MS.Free;
  1944. End;
  1945. End;
  1946. Function TKAZipEntries.AddFolderChain(ItemName : String):Boolean;
  1947. begin
  1948. Result := AddFolderChain(ItemName,faDirectory,Now);
  1949. end;
  1950. function TKAZipEntries.AddStream(FileName : String; FileAttr : Word; FileDate : TDateTime; Stream : TStream):TKAZipEntriesEntry;
  1951. Begin
  1952. Result := Nil;
  1953. if (FParent.FStoreFolders) AND (FParent.FStoreRelativePath) Then AddFolderChain(FileName);
  1954. if FParent.FZipSaveMethod = FastSave Then
  1955. Result := AddStreamFast(FileName,FileAttr,FileDate,Stream)
  1956. Else
  1957. if FParent.FZipSaveMethod = RebuildAll Then
  1958. Result := AddStreamRebuild(FileName,FileAttr,FileDate,Stream);
  1959. if Assigned(FParent.FOnAddItem) Then FParent.FOnAddItem(FParent,FileName);
  1960. End;
  1961. Function TKAZipEntries.AddStream(FileName: String; Stream : TStream):TKAZipEntriesEntry;
  1962. begin
  1963. Result := AddStream(FileName,faArchive,Now,Stream);
  1964. end;
  1965. Function TKAZipEntries.AddFile(FileName, NewFileName: String):TKAZipEntriesEntry;
  1966. Var
  1967. FS : TFileStream;
  1968. Dir : TSearchRec;
  1969. Res : Integer;
  1970. begin
  1971. Result := Nil;
  1972. Res := FindFirst(FileName,faAnyFile,Dir);
  1973. if Res=0 Then
  1974. Begin
  1975. FS := TFileStream.Create(FileName,fmOpenRead or fmShareDenyNone);
  1976. Try
  1977. FS.Position := 0;
  1978. Result := AddStream(NewFileName,Dir.Attr,FileDateToDateTime(Dir.Time),FS)
  1979. Finally
  1980. FS.Free;
  1981. End;
  1982. End;
  1983. FindClose(Dir);
  1984. end;
  1985. Function TKAZipEntries.AddFile(FileName: String):TKAZipEntriesEntry;
  1986. begin
  1987. Result := AddFile(FileName,FileName);
  1988. end;
  1989. function TKAZipEntries.AddFiles(FileNames: TStrings): Boolean;
  1990. Var
  1991. X : Integer;
  1992. begin
  1993. Result := False;
  1994. FParent.FBatchMode := True;
  1995. Try
  1996. For X := 0 To FileNames.Count-1 do AddFile(FileNames.Strings[X]);
  1997. Except
  1998. FParent.FBatchMode := False;
  1999. FParent.DoChange(FParent,2);
  2000. Exit;
  2001. End;
  2002. FParent.FBatchMode := False;
  2003. FParent.DoChange(FParent,2);
  2004. Result := True;
  2005. end;
  2006. Function TKAZipEntries.AddFolderEx(FolderName:String; RootFolder:String; WildCard : String; WithSubFolders : Boolean):Boolean;
  2007. Var
  2008. Res : Integer;
  2009. Dir : TSearchRec;
  2010. FN : String;
  2011. Begin
  2012. Res := FindFirst(FolderName+'\*.*',faAnyFile,Dir);
  2013. While Res=0 Do
  2014. Begin
  2015. if (Dir.Attr and faDirectory) > 0 Then
  2016. Begin
  2017. if (Dir.Name <> '..') And (Dir.Name <> '.') Then
  2018. Begin
  2019. FN := FolderName+'\'+Dir.Name;
  2020. if (FParent.FStoreFolders) AND (FParent.FStoreRelativePath) Then
  2021. AddFolderChain(RemoveRootName(FN+'\',RootFolder),Dir.Attr,FileDateToDateTime(Dir.Time));
  2022. if WithSubFolders Then
  2023. Begin
  2024. AddFolderEx(FN, RootFolder, WildCard, WithSubFolders);
  2025. End;
  2026. End
  2027. Else
  2028. Begin
  2029. if (Dir.Name = '.') Then AddFolderChain(RemoveRootName(FolderName+'\',RootFolder),Dir.Attr,FileDateToDateTime(Dir.Time));
  2030. End;
  2031. End
  2032. Else
  2033. Begin
  2034. FN := FolderName+'\'+Dir.Name;
  2035. if MatchesMask(FN,WildCard) Then
  2036. Begin
  2037. AddFile(FN,RemoveRootName(FN,RootFolder));
  2038. End;
  2039. End;
  2040. Res := FindNext(Dir);
  2041. End;
  2042. FindClose(Dir);
  2043. Result := True;
  2044. End;
  2045. Function TKAZipEntries.AddFolder(FolderName:String; RootFolder:String; WildCard : String; WithSubFolders : Boolean):Boolean;
  2046. Begin
  2047. FParent.FBatchMode := True;
  2048. Try
  2049. Result := AddFolderEx(FolderName,RootFolder,WildCard,WithSubFolders);
  2050. Finally
  2051. FParent.FBatchMode := False;
  2052. FParent.DoChange(FParent,2);
  2053. End;
  2054. End;
  2055. Function TKAZipEntries.AddFilesAndFolders(FileNames:TStrings; RootFolder:String; WithSubFolders : Boolean):Boolean;
  2056. Var
  2057. X : Integer;
  2058. Res : Integer;
  2059. Dir : TSearchRec;
  2060. Begin
  2061. FParent.FBatchMode := True;
  2062. Try
  2063. For X := 0 To FileNames.Count-1 do
  2064. Begin
  2065. Res := FindFirst(FileNames.Strings[X],faAnyFile,Dir);
  2066. if Res=0 Then
  2067. Begin
  2068. if (Dir.Attr and faDirectory) > 0 Then
  2069. Begin
  2070. if (Dir.Name <> '..') And (Dir.Name <> '.') Then
  2071. Begin
  2072. AddFolderEx(FileNames.Strings[X],RootFolder,'*.*',WithSubFolders);
  2073. End;
  2074. End
  2075. Else
  2076. Begin
  2077. AddFile(FileNames.Strings[X],RemoveRootName(FileNames.Strings[X],RootFolder));
  2078. End;
  2079. End;
  2080. FindClose(Dir);
  2081. End;
  2082. Finally
  2083. FParent.FBatchMode := False;
  2084. FParent.DoChange(FParent,2);
  2085. End;
  2086. Result := True;
  2087. End;
  2088. procedure TKAZipEntries.RemoveFiles(List: TList);
  2089. begin
  2090. if List.Count=1 Then
  2091. Begin
  2092. Remove(Integer(List.Items[0]));
  2093. End
  2094. Else
  2095. Begin
  2096. SortList(List);
  2097. FParent.FBatchMode := True;
  2098. Try
  2099. RemoveBatch(List);
  2100. Finally
  2101. FParent.FBatchMode := False;
  2102. FParent.DoChange(Self,3);
  2103. End;
  2104. End;
  2105. end;
  2106. Procedure TKAZipEntries.RemoveSelected;
  2107. Var
  2108. X : Integer;
  2109. List : TList;
  2110. Begin
  2111. FParent.FBatchMode := True;
  2112. List := TList.Create;
  2113. Try
  2114. For X := 0 to Count-1 do
  2115. Begin
  2116. if Self.Items[X].Selected Then List.Add(Pointer(X));
  2117. End;
  2118. RemoveBatch(List);
  2119. Finally
  2120. List.Free;
  2121. FParent.FBatchMode := False;
  2122. FParent.DoChange(Self,3);
  2123. End;
  2124. End;
  2125. procedure TKAZipEntries.ExtractToStream(Item : TKAZipEntriesEntry; Stream: TStream);
  2126. Var
  2127. SFS : TMemoryStream;
  2128. TFS : TStream;
  2129. BUF : String;
  2130. NR : Cardinal;
  2131. Decompressor : TDecompressionStream;
  2132. {$IFDEF USE_BZIP2}
  2133. DecompressorBZ2 : TBZDecompressionStream;
  2134. {$ENDIF}
  2135. begin
  2136. if (
  2137. (Item.CompressionMethod=8) or
  2138. {$IFDEF USE_BZIP2}
  2139. (Item.CompressionMethod=12) or
  2140. {$ENDIF}
  2141. (Item.CompressionMethod=0)
  2142. )
  2143. And (NOT Item.FIsEncrypted) Then
  2144. Begin
  2145. SFS := TMemoryStream.Create;
  2146. TFS := Stream;
  2147. Try
  2148. if Item.GetCompressedData(SFS) > 0 Then
  2149. Begin
  2150. SFS.Position := 0;
  2151. FParent.FCurrentDFS := Item.SizeUncompressed;
  2152. //****************************************************** DEFLATE
  2153. if (Item.CompressionMethod=8) Then
  2154. Begin
  2155. Decompressor := TDecompressionStream.Create(SFS);
  2156. Decompressor.OnProgress := FParent.OnDecompress;
  2157. SetLength(BUF,FParent.FCurrentDFS);
  2158. Try
  2159. NR := Decompressor.Read(BUF[1],FParent.FCurrentDFS);
  2160. if NR=FParent.FCurrentDFS Then TFS.Write(BUF[1],FParent.FCurrentDFS);
  2161. Finally
  2162. Decompressor.Free;
  2163. End;
  2164. End
  2165. //******************************************************* BZIP2
  2166. {$IFDEF USE_BZIP2}
  2167. Else
  2168. If Item.CompressionMethod=12 Then
  2169. Begin
  2170. DecompressorBZ2 := TBZDecompressionStream.Create(SFS);
  2171. DecompressorBZ2.OnProgress := FParent.OnDecompress;
  2172. SetLength(BUF,FParent.FCurrentDFS);
  2173. Try
  2174. NR := DecompressorBZ2.Read(BUF[1],FParent.FCurrentDFS);
  2175. if NR=FParent.FCurrentDFS Then TFS.Write(BUF[1],FParent.FCurrentDFS);
  2176. Finally
  2177. DecompressorBZ2.Free;
  2178. End;
  2179. End
  2180. {$ENDIF}
  2181. //****************************************************** STORED
  2182. Else
  2183. If Item.CompressionMethod=0 Then
  2184. Begin
  2185. TFS.CopyFrom(SFS,FParent.FCurrentDFS);
  2186. End;
  2187. End;
  2188. Finally
  2189. SFS.Free;
  2190. End;
  2191. End
  2192. Else
  2193. Begin
  2194. Raise Exception.Create('Cannot process this file: '+Item.FileName+' ');
  2195. End;
  2196. end;
  2197. procedure TKAZipEntries.InternalExtractToFile(Item: TKAZipEntriesEntry;
  2198. FileName: String);
  2199. Var
  2200. TFS : TFileStream;
  2201. Attr : Integer;
  2202. begin
  2203. if Item.IsFolder Then
  2204. Begin
  2205. ForceDirectories(FileName);
  2206. End
  2207. Else
  2208. Begin
  2209. TFS := TFileStream.Create(FileName,fmCreate or fmOpenReadWrite or fmShareDenyNone);
  2210. Try
  2211. ExtractToStream(Item,TFS);
  2212. Finally
  2213. TFS.Free;
  2214. End;
  2215. If FParent.FApplyAttributes Then
  2216. Begin
  2217. Attr := faArchive;
  2218. if Item.FCentralDirectoryFile.ExternalFileAttributes And faHidden > 0 Then Attr := Attr Or faHidden;
  2219. if Item.FCentralDirectoryFile.ExternalFileAttributes And faSysFile > 0 Then Attr := Attr Or faSysFile;
  2220. if Item.FCentralDirectoryFile.ExternalFileAttributes And faReadOnly > 0 Then Attr := Attr Or faReadOnly;
  2221. FileSetAttr(FileName,Attr);
  2222. End;
  2223. End;
  2224. end;
  2225. procedure TKAZipEntries.ExtractToFile(Item: TKAZipEntriesEntry; FileName: String);
  2226. var
  2227. Can : Boolean;
  2228. OA : TOverwriteAction;
  2229. Begin
  2230. OA := FParent.FOverwriteAction;
  2231. Can := True;
  2232. if ((OA<>oaOverwriteAll) And (OA<>oaSkipAll)) And (Assigned(FParent.FOnOverwriteFile)) Then
  2233. Begin
  2234. if FileExists(FileName) Then
  2235. Begin
  2236. FParent.FOnOverwriteFile(FParent,FileName,OA);
  2237. End
  2238. Else
  2239. Begin
  2240. OA := oaOverwrite;
  2241. End;
  2242. End;
  2243. Case OA Of
  2244. oaSkip : Can := False;
  2245. oaSkipAll : Can := False;
  2246. oaOverwrite : Can := True;
  2247. oaOverwriteAll : Can := True;
  2248. End;
  2249. if Can Then InternalExtractToFile(Item, FileName);
  2250. End;
  2251. procedure TKAZipEntries.ExtractToFile(ItemIndex: Integer; FileName: String);
  2252. var
  2253. Can : Boolean;
  2254. OA : TOverwriteAction;
  2255. Begin
  2256. OA := FParent.FOverwriteAction;
  2257. Can := True;
  2258. if ((OA<>oaOverwriteAll) And (OA<>oaSkipAll)) And (Assigned(FParent.FOnOverwriteFile)) Then
  2259. Begin
  2260. if FileExists(FileName) Then
  2261. Begin
  2262. FParent.FOnOverwriteFile(FParent,FileName,OA);
  2263. End
  2264. Else
  2265. Begin
  2266. OA := oaOverwrite;
  2267. End;
  2268. End;
  2269. Case OA Of
  2270. oaSkip : Can := False;
  2271. oaSkipAll : Can := False;
  2272. oaOverwrite : Can := True;
  2273. oaOverwriteAll : Can := True;
  2274. End;
  2275. if Can Then InternalExtractToFile(Items[ItemIndex],FileName);
  2276. end;
  2277. procedure TKAZipEntries.ExtractToFile(FileName, DestinationFileName: String);
  2278. Var
  2279. I : Integer;
  2280. Can : Boolean;
  2281. OA : TOverwriteAction;
  2282. Begin
  2283. OA := FParent.FOverwriteAction;
  2284. Can := True;
  2285. if ((OA<>oaOverwriteAll) And (OA<>oaSkipAll)) And (Assigned(FParent.FOnOverwriteFile)) Then
  2286. Begin
  2287. if FileExists(DestinationFileName) Then
  2288. Begin
  2289. FParent.FOnOverwriteFile(FParent,DestinationFileName,OA);
  2290. End
  2291. Else
  2292. Begin
  2293. OA := oaOverwrite;
  2294. End;
  2295. End;
  2296. Case OA Of
  2297. oaSkip : Can := False;
  2298. oaSkipAll : Can := False;
  2299. oaOverwrite : Can := True;
  2300. oaOverwriteAll : Can := True;
  2301. End;
  2302. if Can Then
  2303. Begin
  2304. I := IndexOf(FileName);
  2305. InternalExtractToFile(Items[I],DestinationFileName);
  2306. End;
  2307. end;
  2308. procedure TKAZipEntries.ExtractAll(TargetDirectory: String);
  2309. Var
  2310. FN : String;
  2311. DN : String;
  2312. X : Integer;
  2313. Can : Boolean;
  2314. OA : TOverwriteAction;
  2315. FileName : String;
  2316. begin
  2317. OA := FParent.FOverwriteAction;
  2318. Can := True;
  2319. Try
  2320. For X := 0 To Count-1 do
  2321. Begin
  2322. FN := FParent.GetFileName(Items[X].FileName);
  2323. DN := FParent.GetFilePath(Items[X].FileName);
  2324. if DN <> '' Then ForceDirectories(TargetDirectory+'\'+DN);
  2325. FileName := TargetDirectory+'\'+DN+FN;
  2326. if ((OA<>oaOverwriteAll) And (OA<>oaSkipAll)) And (Assigned(FParent.FOnOverwriteFile)) Then
  2327. Begin
  2328. if FileExists(FileName) Then
  2329. Begin
  2330. FParent.FOnOverwriteFile(FParent,FileName,OA);
  2331. End;
  2332. End;
  2333. Case OA Of
  2334. oaSkip : Can := False;
  2335. oaSkipAll : Can := False;
  2336. oaOverwrite : Can := True;
  2337. oaOverwriteAll : Can := True;
  2338. End;
  2339. if Can Then InternalExtractToFile(Items[X],FileName);
  2340. End;
  2341. Finally
  2342. End;
  2343. end;
  2344. procedure TKAZipEntries.ExtractSelected(TargetDirectory: String);
  2345. Var
  2346. FN : String;
  2347. DN : String;
  2348. X : Integer;
  2349. OA : TOverwriteAction;
  2350. Can : Boolean;
  2351. FileName : String;
  2352. begin
  2353. OA := FParent.FOverwriteAction;
  2354. Can := True;
  2355. Try
  2356. For X := 0 To Count-1 do
  2357. Begin
  2358. if Items[X].FSelected Then
  2359. Begin
  2360. FN := FParent.GetFileName(Items[X].FileName);
  2361. DN := FParent.GetFilePath(Items[X].FileName);
  2362. if DN <> '' Then ForceDirectories(TargetDirectory+'\'+DN);
  2363. FileName := TargetDirectory+'\'+DN+FN;
  2364. if ((OA<>oaOverwriteAll) And (OA<>oaSkipAll)) And (Assigned(FParent.FOnOverwriteFile)) Then
  2365. Begin
  2366. if FileExists(FileName) Then
  2367. Begin
  2368. FParent.FOnOverwriteFile(FParent,FileName,OA);
  2369. End;
  2370. End;
  2371. Case OA Of
  2372. oaSkip : Can := False;
  2373. oaSkipAll : Can := False;
  2374. oaOverwrite : Can := True;
  2375. oaOverwriteAll : Can := True;
  2376. End;
  2377. if Can Then InternalExtractToFile(Items[X],TargetDirectory+'\'+DN+FN);
  2378. End;
  2379. End;
  2380. Finally
  2381. End;
  2382. end;
  2383. procedure TKAZipEntries.DeSelectAll;
  2384. Var
  2385. X : Integer;
  2386. begin
  2387. For X := 0 To Count-1 do Items[X].Selected := False;
  2388. end;
  2389. procedure TKAZipEntries.InvertSelection;
  2390. Var
  2391. X : Integer;
  2392. begin
  2393. For X := 0 To Count-1 do Items[X].Selected := Not Items[X].Selected;
  2394. end;
  2395. procedure TKAZipEntries.SelectAll;
  2396. Var
  2397. X : Integer;
  2398. begin
  2399. For X := 0 To Count-1 do Items[X].Selected := True;
  2400. end;
  2401. procedure TKAZipEntries.Select(WildCard: String);
  2402. Var
  2403. X : Integer;
  2404. begin
  2405. For X := 0 To Count-1 do
  2406. Begin
  2407. if MatchesMask(ToDosName(Items[X].FileName),WildCard) Then
  2408. Items[X].Selected := True;
  2409. End;
  2410. end;
  2411. procedure TKAZipEntries.Rebuild;
  2412. begin
  2413. FParent.Rebuild;
  2414. end;
  2415. procedure TKAZipEntries.Rename(Item: TKAZipEntriesEntry; NewFileName: String);
  2416. begin
  2417. Item.FileName := NewFileName;
  2418. end;
  2419. procedure TKAZipEntries.Rename(ItemIndex: Integer; NewFileName: String);
  2420. begin
  2421. Rename(Items[ItemIndex],NewFileName);
  2422. end;
  2423. procedure TKAZipEntries.Rename(FileName, NewFileName: String);
  2424. Var
  2425. I : Integer;
  2426. begin
  2427. I := IndexOf(FileName);
  2428. Rename(I,NewFileName);
  2429. end;
  2430. procedure TKAZipEntries.CreateFolder(FolderName: String; FolderDate: TDateTime);
  2431. Var
  2432. FN : String;
  2433. begin
  2434. FN := IncludeTrailingPathDelimiter(FolderName);
  2435. AddFolderChain(FN,faDirectory,FolderDate);
  2436. FParent.FIsDirty := True;
  2437. end;
  2438. procedure TKAZipEntries.RenameFolder(FolderName : String; NewFolderName : String);
  2439. Var
  2440. FN : String;
  2441. NFN : String;
  2442. S : String;
  2443. X : Integer;
  2444. L : Integer;
  2445. begin
  2446. FN := ToZipName(IncludeTrailingPathDelimiter(FolderName));
  2447. NFN := ToZipName(IncludeTrailingPathDelimiter(NewFolderName));
  2448. L := Length(FN);
  2449. if IndexOf(NFN) = -1 Then
  2450. Begin
  2451. For X := 0 To Count-1 do
  2452. Begin
  2453. S := Items[X].FileName;
  2454. if Pos(FN,S) = 1 Then
  2455. Begin
  2456. System.Delete(S,1,L);
  2457. S := NFN+S;
  2458. Items[X].FileName := S;
  2459. FParent.FIsDirty := True;
  2460. End;
  2461. End;
  2462. If (FParent.FIsDirty) And (FParent.FBatchMode=False) Then Rebuild;
  2463. End;
  2464. end;
  2465. procedure TKAZipEntries.RenameMultiple(Names : TStringList; NewNames : TStringList);
  2466. Var
  2467. X : Integer;
  2468. BR : Integer;
  2469. L : Integer;
  2470. Begin
  2471. If Names.Count <> NewNames.Count Then
  2472. Begin
  2473. Raise Exception.Create('Names and NewNames must have equal count');
  2474. End
  2475. Else
  2476. Begin
  2477. FParent.FBatchMode := True;
  2478. Try
  2479. For X := 0 To Names.Count-1 do
  2480. Begin
  2481. L := Length(Names.Strings[X]);
  2482. if (L>0) And ((Names.Strings[X][L]='\') or (Names.Strings[X][L]='/')) Then
  2483. Begin
  2484. RenameFolder(Names.Strings[X],NewNames.Strings[X]);
  2485. Inc(BR);
  2486. End
  2487. Else
  2488. Begin
  2489. Rename(Names.Strings[X],NewNames.Strings[X]);
  2490. Inc(BR);
  2491. End;
  2492. End;
  2493. Finally
  2494. FParent.FBatchMode := False;
  2495. End;
  2496. If BR > 0 Then
  2497. Begin
  2498. Rebuild;
  2499. FParent.DoChange(FParent,6);
  2500. End;
  2501. End;
  2502. End;
  2503. { TKAZip }
  2504. constructor TKAZip.Create(AOwner: TComponent);
  2505. begin
  2506. Inherited Create(AOwner);
  2507. FZipStream := Nil;
  2508. FOnDecompressFile := Nil;
  2509. FOnCompressFile := Nil;
  2510. FOnZipChange := Nil;
  2511. FOnZipOpen := Nil;
  2512. FOnAddItem := Nil;
  2513. FOnOverwriteFile := Nil;
  2514. FComponentVersion := '2.0';
  2515. FBatchMode := False;
  2516. FFileNames := TStringList.Create;
  2517. FZipHeader := TKAZipEntries.Create(Self);
  2518. FZipComment := TStringList.Create;
  2519. FIsZipFile := False;
  2520. FFileName := '';
  2521. FCurrentDFS := 0;
  2522. FExternalStream := False;
  2523. FIsDirty := True;
  2524. FHasBadEntries := False;
  2525. FReadOnly := False;
  2526. FApplyAttributes := True;
  2527. FOverwriteAction := oaSkip;
  2528. FZipSaveMethod := FastSave;
  2529. FUseTempFiles := False;
  2530. FStoreRelativePath := True;
  2531. FStoreFolders := True;
  2532. FZipCompressionType := ctMaximum;
  2533. end;
  2534. destructor TKAZip.Destroy;
  2535. begin
  2536. if Assigned(FZipStream) AND (NOT FExternalStream) Then FZipStream.Free;
  2537. FZipHeader.Free;
  2538. FZipComment.Free;
  2539. FFileNames.Free;
  2540. inherited Destroy;
  2541. end;
  2542. procedure TKAZip.DoChange(Sender: TObject; Const ChangeType : Integer);
  2543. begin
  2544. if Assigned(FOnZipChange) Then FOnZipChange(Self, ChangeType);
  2545. end;
  2546. function TKAZip.GetFileName(S: String): String;
  2547. Var
  2548. FN : String;
  2549. P : Integer;
  2550. begin
  2551. FN := S;
  2552. FN := StringReplace(FN,'//','\',[rfReplaceAll]);
  2553. FN := StringReplace(FN,'/','\',[rfReplaceAll]);
  2554. P := Pos(':\',FN);
  2555. if P > 0 Then System.Delete(FN,1,P+1);
  2556. Result := ExtractFileName(StringReplace(FN,'/','\',[rfReplaceAll]));
  2557. end;
  2558. function TKAZip.GetFilePath(S: String): String;
  2559. Var
  2560. FN : String;
  2561. P : Integer;
  2562. begin
  2563. FN := S;
  2564. FN := StringReplace(FN,'//','\',[rfReplaceAll]);
  2565. FN := StringReplace(FN,'/','\',[rfReplaceAll]);
  2566. P := Pos(':\',FN);
  2567. if P > 0 Then System.Delete(FN,1,P+1);
  2568. Result := ExtractFilePath(StringReplace(FN,'/','\',[rfReplaceAll]));
  2569. end;
  2570. procedure TKAZip.LoadFromFile(FileName: String);
  2571. Var
  2572. Res : Integer;
  2573. Dir : TSearchRec;
  2574. begin
  2575. Res := FindFirst(FileName,faAnyFile,Dir);
  2576. If Res=0 Then
  2577. Begin
  2578. if Dir.Attr And faReadOnly > 0 Then
  2579. Begin
  2580. FZipStream := TFileStream.Create(FileName,fmOpenRead or fmShareDenyNone);
  2581. FReadOnly := True;
  2582. End
  2583. Else
  2584. Begin
  2585. FZipStream := TFileStream.Create(FileName,fmOpenReadWrite or fmShareDenyNone);
  2586. FReadOnly := False;
  2587. End;
  2588. {$IFDEF USE_BUFFERED_IO}
  2589. FZipStream:= TutlPagedBufferStream.Create(FZipStream, 64*1024, true); // Martok: Buffer for TOC reads
  2590. {$ENDIF}
  2591. LoadFromStream(FZipStream);
  2592. FindClose(Dir);
  2593. End
  2594. Else
  2595. Begin
  2596. Raise Exception.Create('File "'+FileName+'" not found!');
  2597. End;
  2598. end;
  2599. procedure TKAZip.LoadFromStream(MS : TStream);
  2600. begin
  2601. FZipStream := MS;
  2602. FZipHeader.ParseZip(MS);
  2603. FIsZipFile := FZipHeader.FIsZipFile;
  2604. if Not FIsZipFile Then Close;
  2605. FIsDirty := True;
  2606. DoChange(Self,1);
  2607. end;
  2608. procedure TKAZip.Close;
  2609. begin
  2610. Entries.Clear;
  2611. if Assigned(FZipStream) AND (NOT FExternalStream) Then FZipStream.Free;
  2612. FExternalStream := False;
  2613. FZipStream := Nil;
  2614. FIsZipFile := False;
  2615. FIsDirty := True;
  2616. FReadOnly := False;
  2617. DoChange(Self,0);
  2618. end;
  2619. procedure TKAZip.SetFileName(const Value: String);
  2620. begin
  2621. FFileName := Value;
  2622. end;
  2623. procedure TKAZip.Open(FileName: String);
  2624. begin
  2625. Close;
  2626. LoadFromFile(FileName);
  2627. FFileName := FileName;
  2628. end;
  2629. procedure TKAZip.Open(MS: TStream);
  2630. begin
  2631. Try
  2632. Close;
  2633. LoadFromStream(MS);
  2634. Finally
  2635. FExternalStream := True;
  2636. End;
  2637. end;
  2638. procedure TKAZip.SetIsZipFile(const Value: Boolean);
  2639. begin
  2640. //****************************************************************************
  2641. end;
  2642. function TKAZip.GetDelphiTempFileName: String;
  2643. Var
  2644. TmpDir, TmpFn: AnsiString;
  2645. Begin
  2646. Result := GetCurrentDir;
  2647. SetLength(TmpDir, GetTempPath(0,nil)+2);
  2648. SetLength(TmpDir, GetTempPath(Length(TmpDir)-1, PAnsiChar(TmpDir)));
  2649. if TmpDir>'' then begin
  2650. SetLength(TmpFn, Length(Tmpdir)+30);
  2651. if GetTempFileName(PAnsiChar(TmpDir),'',0,PAnsiChar(TmpFN)) <> 0 Then
  2652. Result := StrPas(PAnsiChar(TmpFN));
  2653. End;
  2654. End;
  2655. procedure TKAZip.OnDecompress(Sender: TObject);
  2656. Var
  2657. DS : TStream;
  2658. begin
  2659. DS := TStream(Sender);
  2660. if Assigned(FOnDecompressFile) Then FOnDecompressFile(Self,DS.Position,FCurrentDFS);
  2661. end;
  2662. procedure TKAZip.OnCompress(Sender: TObject);
  2663. Var
  2664. CS : TStream;
  2665. begin
  2666. CS := TStream(Sender);
  2667. if Assigned(FOnCompressFile) Then FOnCompressFile(Self,CS.Position,FCurrentDFS);
  2668. end;
  2669. procedure TKAZip.ExtractToFile(Item : TKAZipEntriesEntry; FileName: String);
  2670. begin
  2671. Entries.ExtractToFile(Item,FileName);
  2672. end;
  2673. procedure TKAZip.ExtractToFile(ItemIndex: Integer; FileName: String);
  2674. begin
  2675. Entries.ExtractToFile(ItemIndex,FileName);
  2676. end;
  2677. procedure TKAZip.ExtractToFile(FileName, DestinationFileName: String);
  2678. begin
  2679. Entries.ExtractToFile(FileName,DestinationFileName);
  2680. end;
  2681. procedure TKAZip.ExtractToStream(Item : TKAZipEntriesEntry; Stream: TStream);
  2682. begin
  2683. Entries.ExtractToStream(Item,Stream);
  2684. end;
  2685. procedure TKAZip.ExtractAll(TargetDirectory: String);
  2686. begin
  2687. Entries.ExtractAll(TargetDirectory);
  2688. end;
  2689. procedure TKAZip.ExtractSelected(TargetDirectory: String);
  2690. Begin
  2691. Entries.ExtractSelected(TargetDirectory);
  2692. End;
  2693. function TKAZip.AddFile(FileName, NewFileName: String): TKAZipEntriesEntry;
  2694. begin
  2695. Result := Entries.AddFile(FileName, NewFileName);
  2696. end;
  2697. function TKAZip.AddFile(FileName: String): TKAZipEntriesEntry;
  2698. begin
  2699. Result := Entries.AddFile(FileName);
  2700. end;
  2701. function TKAZip.AddFiles(FileNames: TStrings): Boolean;
  2702. begin
  2703. Result := Entries.AddFiles(FileNames);
  2704. end;
  2705. function TKAZip.AddFolder(FolderName, RootFolder, WildCard: String;
  2706. WithSubFolders: Boolean): Boolean;
  2707. begin
  2708. Result := Entries.AddFolder(FolderName,RootFolder,WildCard,WithSubFolders);
  2709. end;
  2710. function TKAZip.AddFilesAndFolders(FileNames: TStrings; RootFolder: String;
  2711. WithSubFolders: Boolean): Boolean;
  2712. begin
  2713. Result := Entries.AddFilesAndFolders(FileNames,RootFolder,WithSubFolders);
  2714. end;
  2715. function TKAZip.AddStream(FileName: String; FileAttr: Word; FileDate: TDateTime; Stream: TStream): TKAZipEntriesEntry;
  2716. begin
  2717. Result := Entries.AddStream(FileName,FileAttr,FileDate,Stream);
  2718. end;
  2719. function TKAZip.AddStream(FileName: String; Stream: TStream): TKAZipEntriesEntry;
  2720. begin
  2721. Result := Entries.AddStream(FileName,Stream);
  2722. end;
  2723. procedure TKAZip.Remove(Item: TKAZipEntriesEntry);
  2724. begin
  2725. Entries.Remove(Item);
  2726. end;
  2727. procedure TKAZip.Remove(ItemIndex: Integer);
  2728. begin
  2729. Entries.Remove(ItemIndex);
  2730. end;
  2731. procedure TKAZip.Remove(FileName: String);
  2732. begin
  2733. Entries.Remove(FileName);
  2734. end;
  2735. procedure TKAZip.RemoveFiles(List: TList);
  2736. begin
  2737. Entries.RemoveFiles(List);
  2738. end;
  2739. procedure TKAZip.RemoveSelected;
  2740. begin
  2741. Entries.RemoveSelected;;
  2742. end;
  2743. function TKAZip.GetComment: TStrings;
  2744. Var
  2745. S : String;
  2746. begin
  2747. Result := FZipComment;
  2748. FZipComment.Clear;
  2749. if FIsZipFile Then
  2750. Begin
  2751. if FEndOfCentralDir.ZipfileCommentLength > 0 Then
  2752. Begin
  2753. FZipStream.Position := FZipCommentPos;
  2754. SetLength(S,FEndOfCentralDir.ZipfileCommentLength);
  2755. FZipStream.Read(S[1],FEndOfCentralDir.ZipfileCommentLength);
  2756. FZipComment.Text := S;
  2757. End;
  2758. End;
  2759. end;
  2760. procedure TKAZip.SetComment(const Value: TStrings);
  2761. Var
  2762. Comment : String;
  2763. L : Integer;
  2764. begin
  2765. //****************************************************************************
  2766. if FZipComment.Text=Value.Text Then Exit;
  2767. FZipComment.Clear;
  2768. if FIsZipFile Then
  2769. Begin
  2770. FZipComment.Assign(Value);
  2771. Comment := FZipComment.Text;
  2772. L := Length(Comment);
  2773. FEndOfCentralDir.ZipfileCommentLength := L;
  2774. FZipStream.Position := FEndOfCentralDirPos;
  2775. FZipStream.Write(FEndOfCentralDir,SizeOf(TEndOfCentralDir));
  2776. FZipCommentPos := FZipStream.Position;
  2777. if L > 0 Then
  2778. Begin
  2779. FZipStream.Write(Comment[1],L)
  2780. End
  2781. Else
  2782. Begin
  2783. FZipStream.Size := FZipStream.Position;
  2784. End;
  2785. End;
  2786. end;
  2787. procedure TKAZip.DeSelectAll;
  2788. begin
  2789. Entries.DeSelectAll;
  2790. end;
  2791. procedure TKAZip.Select(WildCard : String);
  2792. begin
  2793. Entries.Select(WildCard);
  2794. end;
  2795. procedure TKAZip.InvertSelection;
  2796. begin
  2797. Entries.InvertSelection;
  2798. end;
  2799. procedure TKAZip.SelectAll;
  2800. begin
  2801. Entries.SelectAll;
  2802. end;
  2803. procedure TKAZip.RebuildLocalFiles(MS: TStream);
  2804. Var
  2805. X : Integer;
  2806. LF : TLocalFile;
  2807. begin
  2808. //************************************************* RESAVE ALL LOCAL BLOCKS
  2809. SetLength(NewLHOffsets,Entries.Count+1);
  2810. For X := 0 To Entries.Count-1 do
  2811. Begin
  2812. NewLHOffsets[X] := MS.Position;
  2813. LF := Entries.GetLocalEntry(FZipStream,Entries.Items[X].LocalOffset,False);
  2814. MS.Write(LF, SizeOf(LF)-3*SizeOf(String));
  2815. if LF.FilenameLength > 0 Then MS.Write(LF.FileName[1] ,LF.FilenameLength);
  2816. if LF.ExtraFieldLength > 0 Then MS.Write(LF.ExtraField[1],LF.ExtraFieldLength);
  2817. if LF.CompressedSize > 0 Then MS.Write(LF.CompressedData[1],LF.CompressedSize);
  2818. if Assigned(FOnRebuildZip) Then FOnRebuildZip(Self,X,Entries.Count-1);
  2819. End;
  2820. end;
  2821. procedure TKAZip.RebuildCentralDirectory(MS: TStream);
  2822. Var
  2823. X : Integer;
  2824. CDF : TCentralDirectoryFile;
  2825. begin
  2826. NewEndOfCentralDir := FEndOfCentralDir;
  2827. NewEndOfCentralDir.TotalNumberOfEntriesOnThisDisk := Entries.Count;
  2828. NewEndOfCentralDir.TotalNumberOfEntries := Entries.Count;
  2829. NewEndOfCentralDir.OffsetOfStartOfCentralDirectory := MS.Position;
  2830. For X := 0 To Entries.Count-1 do
  2831. Begin
  2832. CDF := Entries.Items[X].FCentralDirectoryFile;
  2833. CDF.RelativeOffsetOfLocalHeader := NewLHOffsets[X];
  2834. MS.Write(CDF,SizeOf(CDF)-3*SizeOf(String));
  2835. if CDF.FilenameLength > 0 Then
  2836. MS.Write(CDF.FileName[1],CDF.FilenameLength);
  2837. if CDF.ExtraFieldLength > 0 Then
  2838. MS.Write(CDF.ExtraField[1],CDF.ExtraFieldLength);
  2839. if CDF.FileCommentLength > 0 Then
  2840. MS.Write(CDF.FileComment[1],CDF.FileCommentLength);
  2841. if Assigned(FOnRebuildZip) Then FOnRebuildZip(Self,X,Entries.Count-1);
  2842. End;
  2843. NewEndOfCentralDir.SizeOfTheCentralDirectory := MS.Position-NewEndOfCentralDir.OffsetOfStartOfCentralDirectory;
  2844. end;
  2845. procedure TKAZip.RebuildEndOfCentralDirectory(MS: TStream);
  2846. Var
  2847. ZipComment : String;
  2848. begin
  2849. ZipComment := Comment.Text;
  2850. FRebuildECDP := MS.Position;
  2851. MS.Write(NewEndOfCentralDir,SizeOf(NewEndOfCentralDir));
  2852. FRebuildCP := MS.Position;
  2853. if NewEndOfCentralDir.ZipfileCommentLength > 0 Then
  2854. Begin
  2855. MS.Write(ZipComment[1],NewEndOfCentralDir.ZipfileCommentLength);
  2856. End;
  2857. if Assigned(FOnRebuildZip) Then FOnRebuildZip(Self,100,100);
  2858. end;
  2859. Procedure TKAZip.FixZip(MS : TStream);
  2860. Var
  2861. X : Integer;
  2862. Y : Integer;
  2863. NewCount : Integer;
  2864. LF : TLocalFile;
  2865. CDF : TCentralDirectoryFile;
  2866. ZipComment : String;
  2867. Begin
  2868. ZipComment := Comment.Text;
  2869. Y := 0;
  2870. SetLength(NewLHOffsets,Entries.Count+1);
  2871. For X := 0 To Entries.Count-1 do
  2872. Begin
  2873. LF := Entries.GetLocalEntry(FZipStream,Entries.Items[X].LocalOffset,False);
  2874. if (LF.LocalFileHeaderSignature=$04034b50) And (Entries.Items[X].Test) Then
  2875. Begin
  2876. NewLHOffsets[Y] := MS.Position;
  2877. MS.Write(LF, SizeOf(LF)-3*SizeOf(String));
  2878. if LF.FilenameLength > 0 Then MS.Write(LF.FileName[1] ,LF.FilenameLength);
  2879. if LF.ExtraFieldLength > 0 Then MS.Write(LF.ExtraField[1],LF.ExtraFieldLength);
  2880. if LF.CompressedSize > 0 Then MS.Write(LF.CompressedData[1],LF.CompressedSize);
  2881. if Assigned(FOnRebuildZip) Then FOnRebuildZip(Self,X,Entries.Count-1);
  2882. Inc(Y);
  2883. End
  2884. Else
  2885. Begin
  2886. Entries.Items[X].FCentralDirectoryFile.CentralFileHeaderSignature := 0;
  2887. if Assigned(FOnRebuildZip) Then FOnRebuildZip(Self,X,Entries.Count-1);
  2888. End;
  2889. End;
  2890. NewCount := Y;
  2891. Y := 0;
  2892. NewEndOfCentralDir := FEndOfCentralDir;
  2893. NewEndOfCentralDir.TotalNumberOfEntriesOnThisDisk := NewCount;
  2894. NewEndOfCentralDir.TotalNumberOfEntries := NewCount;
  2895. NewEndOfCentralDir.OffsetOfStartOfCentralDirectory := MS.Position;
  2896. For X := 0 To Entries.Count-1 do
  2897. Begin
  2898. CDF := Entries.Items[X].FCentralDirectoryFile;
  2899. if CDF.CentralFileHeaderSignature=$02014b50 Then
  2900. Begin
  2901. CDF.RelativeOffsetOfLocalHeader := NewLHOffsets[Y];
  2902. MS.Write(CDF,SizeOf(CDF)-3*SizeOf(String));
  2903. if CDF.FilenameLength > 0 Then
  2904. MS.Write(CDF.FileName[1],CDF.FilenameLength);
  2905. if CDF.ExtraFieldLength > 0 Then
  2906. MS.Write(CDF.ExtraField[1],CDF.ExtraFieldLength);
  2907. if CDF.FileCommentLength > 0 Then
  2908. MS.Write(CDF.FileComment[1],CDF.FileCommentLength);
  2909. if Assigned(FOnRebuildZip) Then FOnRebuildZip(Self,X,Entries.Count-1);
  2910. Inc(Y);
  2911. End;
  2912. End;
  2913. NewEndOfCentralDir.SizeOfTheCentralDirectory := MS.Position-NewEndOfCentralDir.OffsetOfStartOfCentralDirectory;
  2914. FRebuildECDP := MS.Position;
  2915. MS.Write(NewEndOfCentralDir,SizeOf(NewEndOfCentralDir));
  2916. FRebuildCP := MS.Position;
  2917. if NewEndOfCentralDir.ZipfileCommentLength > 0 Then
  2918. Begin
  2919. MS.Write(ZipComment[1],NewEndOfCentralDir.ZipfileCommentLength);
  2920. End;
  2921. if Assigned(FOnRebuildZip) Then FOnRebuildZip(Self,100,100);
  2922. End;
  2923. Procedure TKAZip.SaveToStream(Stream:TStream);
  2924. Begin
  2925. RebuildLocalFiles(Stream);
  2926. RebuildCentralDirectory(Stream);
  2927. RebuildEndOfCentralDirectory(Stream);
  2928. End;
  2929. Procedure TKAZip.Rebuild;
  2930. var
  2931. TempStream : TFileStream;
  2932. TempMSStream : TMemoryStream;
  2933. TempFileName : String;
  2934. Begin
  2935. if FUseTempFiles Then
  2936. Begin
  2937. TempFileName := GetDelphiTempFileName;
  2938. TempStream := TFileStream.Create(TempFileName,fmOpenReadWrite or FmCreate);
  2939. Try
  2940. SaveToStream(TempStream);
  2941. FZipStream.Position := 0;
  2942. FZipStream.Size := 0;
  2943. TempStream.Position := 0;
  2944. FZipStream.CopyFrom(TempStream,TempStream.Size);
  2945. Entries.ParseZip(FZipStream);
  2946. Finally
  2947. TempStream.Free;
  2948. DeleteFile(TempFileName)
  2949. End;
  2950. End
  2951. Else
  2952. Begin
  2953. TempMSStream := TMemoryStream.Create;
  2954. Try
  2955. SaveToStream(TempMSStream);
  2956. FZipStream.Position := 0;
  2957. FZipStream.Size := 0;
  2958. TempMSStream.Position := 0;
  2959. FZipStream.CopyFrom(TempMSStream,TempMSStream.Size);
  2960. Entries.ParseZip(FZipStream);
  2961. Finally
  2962. TempMSStream.Free;
  2963. End;
  2964. End;
  2965. FIsDirty := True;
  2966. End;
  2967. Procedure TKAZip.CreateZip(Stream:TStream);
  2968. Var
  2969. ECD : TEndOfCentralDir;
  2970. Begin
  2971. ECD.EndOfCentralDirSignature := $06054b50;
  2972. ECD.NumberOfThisDisk := 0;
  2973. ECD.NumberOfTheDiskWithTheStart := 0;
  2974. ECD.TotalNumberOfEntriesOnThisDisk := 0;
  2975. ECD.TotalNumberOfEntries := 0;
  2976. ECD.SizeOfTheCentralDirectory := 0;
  2977. ECD.OffsetOfStartOfCentralDirectory := 0;
  2978. ECD.ZipfileCommentLength := 0;
  2979. Stream.Write(ECD,SizeOf(ECD));
  2980. End;
  2981. Procedure TKAZip.CreateZip(FileName:String);
  2982. var
  2983. FS : TFileStream;
  2984. Begin
  2985. FS := TFileStream.Create(FileName,fmOpenReadWrite or FmCreate);
  2986. Try
  2987. CreateZip(FS);
  2988. Finally
  2989. FS.Free;
  2990. End;
  2991. End;
  2992. procedure TKAZip.SetZipSaveMethod(const Value: TZipSaveMethod);
  2993. begin
  2994. FZipSaveMethod := Value;
  2995. end;
  2996. procedure TKAZip.SetActive(const Value: Boolean);
  2997. begin
  2998. if FFileName='' Then Exit;
  2999. if Value Then Open(FFileName) Else Close;
  3000. end;
  3001. procedure TKAZip.SetZipCompressionType(const Value: TZipCompressionType);
  3002. begin
  3003. FZipCompressionType := Value;
  3004. if FZipCompressionType = ctUnknown Then FZipCompressionType := ctNormal;
  3005. end;
  3006. function TKAZip.GetFileNames: TStrings;
  3007. Var
  3008. X : Integer;
  3009. begin
  3010. if FIsDirty Then
  3011. Begin
  3012. FFileNames.Clear;
  3013. For X := 0 To Entries.Count-1 do
  3014. Begin
  3015. FFileNames.Add(GetFilePath(Entries.Items[X].FileName)+GetFileName(Entries.Items[X].FileName));
  3016. End;
  3017. FIsDirty := False;
  3018. End;
  3019. Result := FFileNames;
  3020. end;
  3021. procedure TKAZip.SetFileNames(const Value: TStrings);
  3022. begin
  3023. //*************************************************** READ ONLY
  3024. end;
  3025. procedure TKAZip.SetUseTempFiles(const Value: Boolean);
  3026. begin
  3027. FUseTempFiles := Value;
  3028. end;
  3029. procedure TKAZip.Rename(Item: TKAZipEntriesEntry; NewFileName: String);
  3030. begin
  3031. Entries.Rename(Item,NewFileName);
  3032. end;
  3033. procedure TKAZip.Rename(ItemIndex: Integer; NewFileName: String);
  3034. begin
  3035. Entries.Rename(ItemIndex,NewFileName);
  3036. end;
  3037. procedure TKAZip.Rename(FileName, NewFileName: String);
  3038. begin
  3039. Entries.Rename(FileName, NewFileName);
  3040. end;
  3041. procedure TKAZip.RenameMultiple(Names, NewNames: TStringList);
  3042. begin
  3043. Entries.RenameMultiple(Names, NewNames);
  3044. end;
  3045. procedure TKAZip.SetStoreFolders(const Value: Boolean);
  3046. begin
  3047. FStoreFolders := Value;
  3048. end;
  3049. procedure TKAZip.SetOnAddItem(const Value: TOnAddItem);
  3050. begin
  3051. FOnAddItem := Value;
  3052. end;
  3053. procedure TKAZip.SetComponentVersion(const Value: String);
  3054. begin
  3055. //****************************************************************************
  3056. end;
  3057. procedure TKAZip.SetOnRebuildZip(const Value: TOnRebuildZip);
  3058. begin
  3059. FOnRebuildZip := Value;
  3060. end;
  3061. procedure TKAZip.SetOnRemoveItems(const Value: TOnRemoveItems);
  3062. begin
  3063. FOnRemoveItems := Value;
  3064. end;
  3065. procedure TKAZip.SetOverwriteAction(const Value: TOverwriteAction);
  3066. begin
  3067. FOverwriteAction := Value;
  3068. end;
  3069. procedure TKAZip.SetOnOverwriteFile(const Value: TOnOverwriteFile);
  3070. begin
  3071. FOnOverwriteFile := Value;
  3072. end;
  3073. procedure TKAZip.CreateFolder(FolderName: String; FolderDate: TDateTime);
  3074. begin
  3075. Entries.CreateFolder(FolderName,FolderDate);
  3076. end;
  3077. procedure TKAZip.RenameFolder(FolderName : String; NewFolderName : String);
  3078. begin
  3079. Entries.RenameFolder(FolderName,NewFolderName);
  3080. end;
  3081. procedure TKAZip.SetReadOnly(const Value: Boolean);
  3082. begin
  3083. FReadOnly := Value;
  3084. end;
  3085. procedure TKAZip.SetApplyAtributes(const Value: Boolean);
  3086. begin
  3087. FApplyAttributes := Value;
  3088. end;
  3089. end.