ZipApp.pas 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. (* ***** BEGIN LICENSE BLOCK *****
  2. * Version: MPL 1.1
  3. *
  4. * The contents of this file are subject to the Mozilla Public License Version
  5. * 1.1 (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. * http://www.mozilla.org/MPL/
  8. *
  9. * Software distributed under the License is distributed on an "AS IS" basis,
  10. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11. * for the specific language governing rights and limitations under the
  12. * License.
  13. *
  14. * The Original Code is TurboPower Abbrevia
  15. *
  16. * The Initial Developer of the Original Code is
  17. * TurboPower Software
  18. *
  19. * Portions created by the Initial Developer are Copyright (C) 1997-2002
  20. * the Initial Developer. All Rights Reserved.
  21. *
  22. * Contributor(s):
  23. *
  24. * ***** END LICENSE BLOCK ***** *)
  25. {*********************************************************}
  26. {* ABBREVIA: ZipApp.pas *}
  27. {*********************************************************}
  28. {* ABBREVIA: Additional classes and routines *}
  29. {*********************************************************}
  30. unit ZipApp;
  31. {$mode objfpc}{$H+}
  32. interface
  33. uses
  34. Classes, SysUtils, AbArcTyp, AbZipKit, AbUtils;
  35. const
  36. {$IF DEFINED(MSWINDOWS)}
  37. faFolder = faDirectory;
  38. {$ELSE}
  39. faFolder = AB_FMODE_DIR or AB_FPERMISSION_GENERIC or AB_FPERMISSION_OWNEREXECUTE;
  40. {$ENDIF}
  41. type
  42. { TAbArchiveItemHelper }
  43. TAbArchiveItemHelper = class helper for TAbArchiveItem
  44. function MatchesPath(const Path : String; Recursive : Boolean = False) : Boolean;
  45. function MatchesPathEx(const Paths : String; Recursive : Boolean = False) : Boolean;
  46. end;
  47. { TAbArchiveAccess }
  48. TAbArchiveAccess = class(TAbArchive)
  49. end;
  50. { TAbZipKit }
  51. TAbZipKit = class(TAbCustomZipKit)
  52. public
  53. {en
  54. Delete one file from archive
  55. }
  56. procedure DeleteFile(const aFileName : String);
  57. {en
  58. Get the normalized file name
  59. }
  60. function GetFileName(aFileIndex: Integer): String;
  61. {en
  62. Delete directory entry and all file and directory entries matching
  63. the same path recursively
  64. }
  65. procedure DeleteDirectoriesRecursively(const Paths : String);
  66. {en
  67. Test specific item in the archive
  68. }
  69. procedure TestItemAt(Index : Integer);
  70. end;
  71. {en
  72. See if DirPath matches PathToMatch.
  73. If Recursive=True it is allowed for DirPath to point to a subdirectory of PathToMatch,
  74. for example: PathToMatch = 'dir/', DirPath = 'dir/subdir' - Result is True.
  75. }
  76. function AbDirMatch(DirPath : String; PathToMatch : String; Recursive : Boolean) : Boolean;
  77. {en
  78. From a list of paths separated with AbPathSep (';') extracts a path from
  79. the position StartPos (counted from 1) and modifies StartPos to point to next entry.
  80. When no more entries are found, returns empty string.
  81. }
  82. function AbExtractEntry(const Entries : String; var StartPos : Integer) : String;
  83. implementation
  84. uses
  85. AbExcept, DCStrUtils;
  86. { TAbArchiveItemHelper }
  87. function TAbArchiveItemHelper.MatchesPath(const Path: String; Recursive: Boolean): Boolean;
  88. var
  89. Value : string;
  90. Drive, Dir, Name : string;
  91. begin
  92. Value := Path;
  93. if (Value <> '') and (RightStr(Value, 1) <> AbPathDelim) then
  94. Value := Value + AbPathDelim;
  95. AbUnfixName(Value);
  96. AbParseFileName(Path, Drive, Dir, Name);
  97. Value := Dir + Name;
  98. Name := FileName;
  99. AbUnfixName(Name);
  100. Result := AbDirMatch(Name, Value, Recursive);
  101. end;
  102. function TAbArchiveItemHelper.MatchesPathEx(const Paths: String; Recursive: Boolean): Boolean;
  103. var
  104. Position: Integer;
  105. Path: String;
  106. begin
  107. Result := True;
  108. Position := 1;
  109. while True do
  110. begin
  111. Path := AbExtractEntry(Paths, Position);
  112. if Path = '' then Break;
  113. if MatchesPath(Path, Recursive) then Exit;
  114. end;
  115. Result := False;
  116. end;
  117. { TAbZipKit }
  118. procedure TAbZipKit.DeleteFile(const aFileName: String);
  119. var
  120. I : Integer;
  121. begin
  122. TAbArchiveAccess(Archive).CheckValid;
  123. if Count > 0 then
  124. begin
  125. for I := Pred(Count) downto 0 do
  126. begin
  127. with Archive.ItemList[I] do
  128. begin
  129. if CompareStr(GetFileName(I), aFileName) = 0 then
  130. begin
  131. DeleteAt(I);
  132. Break;
  133. end;
  134. end;
  135. end;
  136. end;
  137. end;
  138. function TAbZipKit.GetFileName(aFileIndex: Integer): String;
  139. begin
  140. Result := Items[aFileIndex].FileName;
  141. if (ArchiveType in [atGzip, atGzippedTar]) and (Result = 'unknown') then
  142. begin
  143. Result := ExtractOnlyFileName(FileName);
  144. if (ArchiveType = atGzippedTar) then
  145. begin
  146. if (TarAutoHandle = False) and (ExtractOnlyFileExt(Result) <> 'tar') then
  147. Result := Result + '.tar';
  148. end;
  149. end;
  150. DoDirSeparators(Result);
  151. Result := ExcludeFrontPathDelimiter(Result);
  152. Result := ExcludeTrailingPathDelimiter(Result);
  153. while StrBegins(Result, '..' + PathDelim) do
  154. begin
  155. Result := Copy(Result, 4, MaxInt);
  156. Result := ExcludeFrontPathDelimiter(Result);
  157. end;
  158. if StrEnds(Result, PathDelim + '..') then
  159. begin
  160. Result[Length(Result)] := '_';
  161. Result[Length(Result) - 1] := '_';
  162. end;
  163. Result := StringReplace(Result, PathDelim + '..' + PathDelim, PathDelim + '__' + PathDelim, [rfReplaceAll]);
  164. end;
  165. procedure TAbZipKit.DeleteDirectoriesRecursively(const Paths: String);
  166. var
  167. I : Integer;
  168. begin
  169. TAbArchiveAccess(Archive).CheckValid;
  170. if Count > 0 then
  171. begin
  172. for I := Pred(Count) downto 0 do
  173. begin
  174. with Archive.ItemList[I] do
  175. if MatchesPathEx(Paths, True) then
  176. DeleteAt(I);
  177. end;
  178. end;
  179. end;
  180. procedure TAbZipKit.TestItemAt(Index: Integer);
  181. begin
  182. if (Archive <> nil) then
  183. TAbArchiveAccess(Archive).TestAt(Index)
  184. else
  185. raise EAbNoArchive.Create;
  186. end;
  187. function AbDirMatch(DirPath : String; PathToMatch : String; Recursive : Boolean) : Boolean;
  188. begin
  189. if Recursive then
  190. PathToMatch := PathToMatch + '*'; // append wildcard
  191. Result := AbPatternMatch(DirPath, 1, PathToMatch, 1);
  192. end;
  193. function AbExtractEntry(const Entries : String; var StartPos : Integer) : String;
  194. var
  195. I : Integer;
  196. Len: Integer;
  197. begin
  198. Result := '';
  199. Len := Length(Entries);
  200. I := StartPos;
  201. if (I >= 1) and (I <= Len) then
  202. begin
  203. while (I <= Len) and (Entries[I] <> AbPathSep) do Inc(I);
  204. Result := Copy(Entries, StartPos, I - StartPos);
  205. if (I <= Len) and (Entries[I] = AbPathSep) then Inc(I);
  206. StartPos := I;
  207. end;
  208. end;
  209. end.