• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2011 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef THIRD_PARTY_ZLIB_GOOGLE_ZIP_H_
6 #define THIRD_PARTY_ZLIB_GOOGLE_ZIP_H_
7 
8 #include <cstdint>
9 #include <ostream>
10 #include <utility>
11 #include <vector>
12 
13 #include "base/containers/span.h"
14 #include "base/files/file_path.h"
15 #include "base/files/platform_file.h"
16 #include "base/functional/callback.h"
17 #include "base/time/time.h"
18 #include "build/build_config.h"
19 
20 namespace base {
21 class File;
22 }
23 
24 namespace zip {
25 
26 class WriterDelegate;
27 
28 // Paths passed as span to avoid copying them.
29 using Paths = base::span<const base::FilePath>;
30 
31 // Abstraction for file access operation required by Zip().
32 //
33 // Can be passed to the ZipParams for providing custom access to the files,
34 // for example over IPC.
35 //
36 // All parameters paths are expected to be relative to the source directory.
37 class FileAccessor {
38  public:
39   virtual ~FileAccessor() = default;
40 
41   struct Info {
42     bool is_directory = false;
43     base::Time last_modified;
44   };
45 
46   // Opens files specified in |paths|.
47   // Directories should be mapped to invalid files.
48   virtual bool Open(Paths paths, std::vector<base::File>* files) = 0;
49 
50   // Lists contents of a directory at |path|.
51   virtual bool List(const base::FilePath& path,
52                     std::vector<base::FilePath>* files,
53                     std::vector<base::FilePath>* subdirs) = 0;
54 
55   // Gets info about a file or directory.
56   virtual bool GetInfo(const base::FilePath& path, Info* info) = 0;
57 };
58 
59 // Progress of a ZIP creation operation.
60 struct Progress {
61   // Total number of bytes read from files getting zipped so far.
62   std::int64_t bytes = 0;
63 
64   // Number of file entries added to the ZIP so far.
65   // A file entry is added after its bytes have been processed.
66   int files = 0;
67 
68   // Number of directory entries added to the ZIP so far.
69   // A directory entry is added before items in it.
70   int directories = 0;
71 
72   // Number of errors encountered so far (files that cannot be opened,
73   // directories that cannot be listed).
74   int errors = 0;
75 };
76 
77 // Prints Progress to output stream.
78 std::ostream& operator<<(std::ostream& out, const Progress& progress);
79 
80 // Callback reporting the progress of a ZIP creation operation.
81 //
82 // This callback returns a boolean indicating whether the ZIP creation operation
83 // should continue. If it returns false once, then the ZIP creation operation is
84 // immediately cancelled and the callback won't be called again.
85 using ProgressCallback = base::RepeatingCallback<bool(const Progress&)>;
86 
87 using FilterCallback = base::RepeatingCallback<bool(const base::FilePath&)>;
88 
89 // ZIP creation parameters and options.
90 struct ZipParams {
91   // Source directory. Ignored if |file_accessor| is set.
92   base::FilePath src_dir;
93 
94   // Abstraction around file system access used to read files.
95   // If left null, an implementation that accesses files directly is used.
96   FileAccessor* file_accessor = nullptr;  // Not owned
97 
98   // Destination file path.
99   // Either dest_file or dest_fd should be set, but not both.
100   base::FilePath dest_file;
101 
102 #if defined(OS_POSIX) || defined(OS_FUCHSIA)
103   // Destination file passed a file descriptor.
104   // Either dest_file or dest_fd should be set, but not both.
105   int dest_fd = base::kInvalidPlatformFile;
106 #endif
107 
108   // The relative paths to the files and directories that should be included in
109   // the ZIP file. If this is empty, the whole contents of |src_dir| are
110   // included.
111   //
112   // These paths must be relative to |src_dir| and will be used as the file
113   // names in the created ZIP file. All files must be under |src_dir| in the
114   // file system hierarchy.
115   //
116   // All the paths in |src_files| are included in the created ZIP file,
117   // irrespective of |include_hidden_files| and |filter_callback|.
118   Paths src_files;
119 
120   // Filter used to exclude files from the ZIP file. This is only taken in
121   // account when recursively adding subdirectory contents.
122   FilterCallback filter_callback;
123 
124   // Optional progress reporting callback.
125   ProgressCallback progress_callback;
126 
127   // Progress reporting period. The final callback is always called when the ZIP
128   // creation operation completes.
129   base::TimeDelta progress_period;
130 
131   // Should add hidden files? This is only taken in account when recursively
132   // adding subdirectory contents.
133   bool include_hidden_files = true;
134 
135   // Should recursively add subdirectory contents?
136   bool recursive = false;
137 
138   // Should ignore errors when discovering files and zipping them?
139   bool continue_on_error = false;
140 };
141 
142 // Zip files specified into a ZIP archives. The source files and ZIP destination
143 // files (as well as other settings) are specified in |params|.
144 bool Zip(const ZipParams& params);
145 
146 // Zip the contents of src_dir into dest_file. src_path must be a directory.
147 // An entry will *not* be created in the zip for the root folder -- children
148 // of src_dir will be at the root level of the created zip. For each file in
149 // src_dir, include it only if the callback |filter_cb| returns true. Otherwise
150 // omit it.
151 bool ZipWithFilterCallback(const base::FilePath& src_dir,
152                            const base::FilePath& dest_file,
153                            FilterCallback filter_cb);
154 
155 // Convenience method for callers who don't need to set up the filter callback.
156 // If |include_hidden_files| is true, files starting with "." are included.
157 // Otherwise they are omitted.
158 bool Zip(const base::FilePath& src_dir,
159          const base::FilePath& dest_file,
160          bool include_hidden_files);
161 
162 #if defined(OS_POSIX) || defined(OS_FUCHSIA)
163 // Zips files listed in |src_relative_paths| to destination specified by file
164 // descriptor |dest_fd|, without taking ownership of |dest_fd|. The paths listed
165 // in |src_relative_paths| are relative to the |src_dir| and will be used as the
166 // file names in the created zip file. All source paths must be under |src_dir|
167 // in the file system hierarchy.
168 bool ZipFiles(const base::FilePath& src_dir,
169               Paths src_relative_paths,
170               int dest_fd);
171 #endif  // defined(OS_POSIX) || defined(OS_FUCHSIA)
172 
173 // Callback reporting the number of bytes written during Unzip.
174 using UnzipProgressCallback = base::RepeatingCallback<void(uint64_t bytes)>;
175 
176 // Options of the Unzip function, with valid default values.
177 struct UnzipOptions {
178   // Encoding of entry paths in the ZIP archive. By default, paths are assumed
179   // to be in UTF-8.
180   std::string encoding;
181 
182   // Only extract the entries for which |filter_cb| returns true. By default,
183   // everything gets extracted.
184   FilterCallback filter;
185 
186   // Callback to report bytes extracted from the ZIP.
187   UnzipProgressCallback progress;
188 
189   // Password to decrypt the encrypted files.
190   std::string password;
191 
192   // Should ignore errors when extracting files?
193   bool continue_on_error = false;
194 };
195 
196 typedef base::RepeatingCallback<std::unique_ptr<WriterDelegate>(
197     const base::FilePath&)>
198     WriterFactory;
199 
200 typedef base::RepeatingCallback<bool(const base::FilePath&)> DirectoryCreator;
201 
202 // Unzips the contents of |zip_file|, using the writers provided by
203 // |writer_factory|.
204 bool Unzip(const base::PlatformFile& zip_file,
205            WriterFactory writer_factory,
206            DirectoryCreator directory_creator,
207            UnzipOptions options = {});
208 
209 // Unzips the contents of |zip_file| into |dest_dir|.
210 // This function does not overwrite any existing file.
211 // A filename collision will result in an error.
212 // Therefore, |dest_dir| should initially be an empty directory.
213 bool Unzip(const base::FilePath& zip_file,
214            const base::FilePath& dest_dir,
215            UnzipOptions options = {});
216 
217 }  // namespace zip
218 
219 #endif  // THIRD_PARTY_ZLIB_GOOGLE_ZIP_H_
220