xref: /aosp_15_r20/external/zlib/google/zip_reader.h (revision 86ee64e75fa5f8bce2c8c356138035642429cd05)
1*86ee64e7SAndroid Build Coastguard Worker // Copyright 2011 The Chromium Authors
2*86ee64e7SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*86ee64e7SAndroid Build Coastguard Worker // found in the LICENSE file.
4*86ee64e7SAndroid Build Coastguard Worker #ifndef THIRD_PARTY_ZLIB_GOOGLE_ZIP_READER_H_
5*86ee64e7SAndroid Build Coastguard Worker #define THIRD_PARTY_ZLIB_GOOGLE_ZIP_READER_H_
6*86ee64e7SAndroid Build Coastguard Worker 
7*86ee64e7SAndroid Build Coastguard Worker #include <stddef.h>
8*86ee64e7SAndroid Build Coastguard Worker #include <stdint.h>
9*86ee64e7SAndroid Build Coastguard Worker 
10*86ee64e7SAndroid Build Coastguard Worker #include <limits>
11*86ee64e7SAndroid Build Coastguard Worker #include <memory>
12*86ee64e7SAndroid Build Coastguard Worker #include <string>
13*86ee64e7SAndroid Build Coastguard Worker 
14*86ee64e7SAndroid Build Coastguard Worker #include "base/files/file.h"
15*86ee64e7SAndroid Build Coastguard Worker #include "base/files/file_path.h"
16*86ee64e7SAndroid Build Coastguard Worker #include "base/functional/callback.h"
17*86ee64e7SAndroid Build Coastguard Worker #include "base/memory/weak_ptr.h"
18*86ee64e7SAndroid Build Coastguard Worker #include "base/numerics/safe_conversions.h"
19*86ee64e7SAndroid Build Coastguard Worker #include "base/time/time.h"
20*86ee64e7SAndroid Build Coastguard Worker 
21*86ee64e7SAndroid Build Coastguard Worker #if defined(USE_SYSTEM_MINIZIP)
22*86ee64e7SAndroid Build Coastguard Worker #include <minizip/unzip.h>
23*86ee64e7SAndroid Build Coastguard Worker #else
24*86ee64e7SAndroid Build Coastguard Worker #include "third_party/zlib/contrib/minizip/unzip.h"
25*86ee64e7SAndroid Build Coastguard Worker #endif
26*86ee64e7SAndroid Build Coastguard Worker 
27*86ee64e7SAndroid Build Coastguard Worker namespace zip {
28*86ee64e7SAndroid Build Coastguard Worker 
29*86ee64e7SAndroid Build Coastguard Worker // A delegate interface used to stream out an entry; see
30*86ee64e7SAndroid Build Coastguard Worker // ZipReader::ExtractCurrentEntry.
31*86ee64e7SAndroid Build Coastguard Worker class WriterDelegate {
32*86ee64e7SAndroid Build Coastguard Worker  public:
~WriterDelegate()33*86ee64e7SAndroid Build Coastguard Worker   virtual ~WriterDelegate() {}
34*86ee64e7SAndroid Build Coastguard Worker 
35*86ee64e7SAndroid Build Coastguard Worker   // Invoked once before any data is streamed out to pave the way (e.g., to open
36*86ee64e7SAndroid Build Coastguard Worker   // the output file). Return false on failure to cancel extraction.
PrepareOutput()37*86ee64e7SAndroid Build Coastguard Worker   virtual bool PrepareOutput() { return true; }
38*86ee64e7SAndroid Build Coastguard Worker 
39*86ee64e7SAndroid Build Coastguard Worker   // Invoked to write the next chunk of data. Return false on failure to cancel
40*86ee64e7SAndroid Build Coastguard Worker   // extraction.
WriteBytes(const char * data,int num_bytes)41*86ee64e7SAndroid Build Coastguard Worker   virtual bool WriteBytes(const char* data, int num_bytes) { return true; }
42*86ee64e7SAndroid Build Coastguard Worker 
43*86ee64e7SAndroid Build Coastguard Worker   // Sets the last-modified time of the data.
SetTimeModified(const base::Time & time)44*86ee64e7SAndroid Build Coastguard Worker   virtual void SetTimeModified(const base::Time& time) {}
45*86ee64e7SAndroid Build Coastguard Worker 
46*86ee64e7SAndroid Build Coastguard Worker   // Called with the POSIX file permissions of the data; POSIX implementations
47*86ee64e7SAndroid Build Coastguard Worker   // may apply some of the permissions (for example, the executable bit) to the
48*86ee64e7SAndroid Build Coastguard Worker   // output file.
SetPosixFilePermissions(int mode)49*86ee64e7SAndroid Build Coastguard Worker   virtual void SetPosixFilePermissions(int mode) {}
50*86ee64e7SAndroid Build Coastguard Worker 
51*86ee64e7SAndroid Build Coastguard Worker   // Called if an error occurred while extracting the file. The WriterDelegate
52*86ee64e7SAndroid Build Coastguard Worker   // can then remove and clean up the partially extracted data.
OnError()53*86ee64e7SAndroid Build Coastguard Worker   virtual void OnError() {}
54*86ee64e7SAndroid Build Coastguard Worker };
55*86ee64e7SAndroid Build Coastguard Worker 
56*86ee64e7SAndroid Build Coastguard Worker // This class is used for reading ZIP archives. A typical use case of this class
57*86ee64e7SAndroid Build Coastguard Worker // is to scan entries in a ZIP archive and extract them. The code will look
58*86ee64e7SAndroid Build Coastguard Worker // like:
59*86ee64e7SAndroid Build Coastguard Worker //
60*86ee64e7SAndroid Build Coastguard Worker //   ZipReader reader;
61*86ee64e7SAndroid Build Coastguard Worker //   if (!reader.Open(zip_path)) {
62*86ee64e7SAndroid Build Coastguard Worker //     // Cannot open
63*86ee64e7SAndroid Build Coastguard Worker //     return;
64*86ee64e7SAndroid Build Coastguard Worker //   }
65*86ee64e7SAndroid Build Coastguard Worker //
66*86ee64e7SAndroid Build Coastguard Worker //   while (const ZipReader::entry* entry = reader.Next()) {
67*86ee64e7SAndroid Build Coastguard Worker //     auto writer = CreateFilePathWriterDelegate(extract_dir, entry->path);
68*86ee64e7SAndroid Build Coastguard Worker //     if (!reader.ExtractCurrentEntry(writer)) {
69*86ee64e7SAndroid Build Coastguard Worker //           // Cannot extract
70*86ee64e7SAndroid Build Coastguard Worker //           return;
71*86ee64e7SAndroid Build Coastguard Worker //     }
72*86ee64e7SAndroid Build Coastguard Worker //   }
73*86ee64e7SAndroid Build Coastguard Worker //
74*86ee64e7SAndroid Build Coastguard Worker //   if (!reader.ok()) {
75*86ee64e7SAndroid Build Coastguard Worker //     // Error while enumerating entries
76*86ee64e7SAndroid Build Coastguard Worker //     return;
77*86ee64e7SAndroid Build Coastguard Worker //   }
78*86ee64e7SAndroid Build Coastguard Worker //
79*86ee64e7SAndroid Build Coastguard Worker class ZipReader {
80*86ee64e7SAndroid Build Coastguard Worker  public:
81*86ee64e7SAndroid Build Coastguard Worker   // A callback that is called when the operation is successful.
82*86ee64e7SAndroid Build Coastguard Worker   using SuccessCallback = base::OnceClosure;
83*86ee64e7SAndroid Build Coastguard Worker   // A callback that is called when the operation fails.
84*86ee64e7SAndroid Build Coastguard Worker   using FailureCallback = base::OnceClosure;
85*86ee64e7SAndroid Build Coastguard Worker   // A callback that is called periodically during the operation with the number
86*86ee64e7SAndroid Build Coastguard Worker   // of bytes that have been processed so far.
87*86ee64e7SAndroid Build Coastguard Worker   using ProgressCallback = base::RepeatingCallback<void(int64_t)>;
88*86ee64e7SAndroid Build Coastguard Worker   // A callback that is called periodically during the operation with the number
89*86ee64e7SAndroid Build Coastguard Worker   // of bytes that have been processed since the previous call (i.e. delta).
90*86ee64e7SAndroid Build Coastguard Worker   using ListenerCallback = base::RepeatingCallback<void(uint64_t)>;
91*86ee64e7SAndroid Build Coastguard Worker 
92*86ee64e7SAndroid Build Coastguard Worker   // Information of an entry (file or directory) in a ZIP archive.
93*86ee64e7SAndroid Build Coastguard Worker   struct Entry {
94*86ee64e7SAndroid Build Coastguard Worker     // Path of this entry, in its original encoding as it is stored in the ZIP
95*86ee64e7SAndroid Build Coastguard Worker     // archive. The encoding is not specified here. It might or might not be
96*86ee64e7SAndroid Build Coastguard Worker     // UTF-8, and the caller needs to use other means to determine the encoding
97*86ee64e7SAndroid Build Coastguard Worker     // if it wants to interpret this path correctly.
98*86ee64e7SAndroid Build Coastguard Worker     std::string path_in_original_encoding;
99*86ee64e7SAndroid Build Coastguard Worker 
100*86ee64e7SAndroid Build Coastguard Worker     // Path of the entry, converted to Unicode. This path is relative (eg
101*86ee64e7SAndroid Build Coastguard Worker     // "foo/bar.txt"). Absolute paths (eg "/foo/bar.txt") or paths containing
102*86ee64e7SAndroid Build Coastguard Worker     // ".." or "." components (eg "../foo/bar.txt") are converted to safe
103*86ee64e7SAndroid Build Coastguard Worker     // relative paths. Eg:
104*86ee64e7SAndroid Build Coastguard Worker     // (In ZIP) -> (Entry.path)
105*86ee64e7SAndroid Build Coastguard Worker     // /foo/bar -> ROOT/foo/bar
106*86ee64e7SAndroid Build Coastguard Worker     // ../a     -> UP/a
107*86ee64e7SAndroid Build Coastguard Worker     // ./a      -> DOT/a
108*86ee64e7SAndroid Build Coastguard Worker     base::FilePath path;
109*86ee64e7SAndroid Build Coastguard Worker 
110*86ee64e7SAndroid Build Coastguard Worker     // Size of the original uncompressed file, or 0 if the entry is a directory.
111*86ee64e7SAndroid Build Coastguard Worker     // This value should not be trusted, because it is stored as metadata in the
112*86ee64e7SAndroid Build Coastguard Worker     // ZIP archive and can be different from the real uncompressed size.
113*86ee64e7SAndroid Build Coastguard Worker     int64_t original_size;
114*86ee64e7SAndroid Build Coastguard Worker 
115*86ee64e7SAndroid Build Coastguard Worker     // Last modified time. If the timestamp stored in the ZIP archive is not
116*86ee64e7SAndroid Build Coastguard Worker     // valid, the Unix epoch will be returned.
117*86ee64e7SAndroid Build Coastguard Worker     //
118*86ee64e7SAndroid Build Coastguard Worker     // The timestamp stored in the ZIP archive uses the MS-DOS date and time
119*86ee64e7SAndroid Build Coastguard Worker     // format.
120*86ee64e7SAndroid Build Coastguard Worker     //
121*86ee64e7SAndroid Build Coastguard Worker     // http://msdn.microsoft.com/en-us/library/ms724247(v=vs.85).aspx
122*86ee64e7SAndroid Build Coastguard Worker     //
123*86ee64e7SAndroid Build Coastguard Worker     // As such the following limitations apply:
124*86ee64e7SAndroid Build Coastguard Worker     // * Only years from 1980 to 2107 can be represented.
125*86ee64e7SAndroid Build Coastguard Worker     // * The timestamp has a 2-second resolution.
126*86ee64e7SAndroid Build Coastguard Worker     // * There is no timezone information, so the time is interpreted as UTC.
127*86ee64e7SAndroid Build Coastguard Worker     base::Time last_modified;
128*86ee64e7SAndroid Build Coastguard Worker 
129*86ee64e7SAndroid Build Coastguard Worker     // True if the entry is a directory.
130*86ee64e7SAndroid Build Coastguard Worker     // False if the entry is a file.
131*86ee64e7SAndroid Build Coastguard Worker     bool is_directory = false;
132*86ee64e7SAndroid Build Coastguard Worker 
133*86ee64e7SAndroid Build Coastguard Worker     // True if the entry path cannot be converted to a safe relative path. This
134*86ee64e7SAndroid Build Coastguard Worker     // happens if a file entry (not a directory) has a filename "." or "..".
135*86ee64e7SAndroid Build Coastguard Worker     bool is_unsafe = false;
136*86ee64e7SAndroid Build Coastguard Worker 
137*86ee64e7SAndroid Build Coastguard Worker     // True if the file content is encrypted.
138*86ee64e7SAndroid Build Coastguard Worker     bool is_encrypted = false;
139*86ee64e7SAndroid Build Coastguard Worker 
140*86ee64e7SAndroid Build Coastguard Worker     // True if the encryption scheme is AES.
141*86ee64e7SAndroid Build Coastguard Worker     bool uses_aes_encryption = false;
142*86ee64e7SAndroid Build Coastguard Worker 
143*86ee64e7SAndroid Build Coastguard Worker     // Entry POSIX permissions (POSIX systems only).
144*86ee64e7SAndroid Build Coastguard Worker     int posix_mode;
145*86ee64e7SAndroid Build Coastguard Worker   };
146*86ee64e7SAndroid Build Coastguard Worker 
147*86ee64e7SAndroid Build Coastguard Worker   ZipReader();
148*86ee64e7SAndroid Build Coastguard Worker 
149*86ee64e7SAndroid Build Coastguard Worker   ZipReader(const ZipReader&) = delete;
150*86ee64e7SAndroid Build Coastguard Worker   ZipReader& operator=(const ZipReader&) = delete;
151*86ee64e7SAndroid Build Coastguard Worker 
152*86ee64e7SAndroid Build Coastguard Worker   ~ZipReader();
153*86ee64e7SAndroid Build Coastguard Worker 
154*86ee64e7SAndroid Build Coastguard Worker   // Opens the ZIP archive specified by |zip_path|. Returns true on
155*86ee64e7SAndroid Build Coastguard Worker   // success.
156*86ee64e7SAndroid Build Coastguard Worker   bool Open(const base::FilePath& zip_path);
157*86ee64e7SAndroid Build Coastguard Worker 
158*86ee64e7SAndroid Build Coastguard Worker   // Opens the ZIP archive referred to by the platform file |zip_fd|, without
159*86ee64e7SAndroid Build Coastguard Worker   // taking ownership of |zip_fd|. Returns true on success.
160*86ee64e7SAndroid Build Coastguard Worker   bool OpenFromPlatformFile(base::PlatformFile zip_fd);
161*86ee64e7SAndroid Build Coastguard Worker 
162*86ee64e7SAndroid Build Coastguard Worker   // Opens the zip data stored in |data|. This class uses a weak reference to
163*86ee64e7SAndroid Build Coastguard Worker   // the given sring while extracting files, i.e. the caller should keep the
164*86ee64e7SAndroid Build Coastguard Worker   // string until it finishes extracting files.
165*86ee64e7SAndroid Build Coastguard Worker   bool OpenFromString(const std::string& data);
166*86ee64e7SAndroid Build Coastguard Worker 
167*86ee64e7SAndroid Build Coastguard Worker   // Closes the currently opened ZIP archive. This function is called in the
168*86ee64e7SAndroid Build Coastguard Worker   // destructor of the class, so you usually don't need to call this.
169*86ee64e7SAndroid Build Coastguard Worker   void Close();
170*86ee64e7SAndroid Build Coastguard Worker 
171*86ee64e7SAndroid Build Coastguard Worker   // Sets the encoding of entry paths in the ZIP archive.
172*86ee64e7SAndroid Build Coastguard Worker   // By default, paths are assumed to be in UTF-8.
SetEncoding(std::string encoding)173*86ee64e7SAndroid Build Coastguard Worker   void SetEncoding(std::string encoding) { encoding_ = std::move(encoding); }
174*86ee64e7SAndroid Build Coastguard Worker 
175*86ee64e7SAndroid Build Coastguard Worker   // Sets the decryption password that will be used to decrypt encrypted file in
176*86ee64e7SAndroid Build Coastguard Worker   // the ZIP archive.
SetPassword(std::string password)177*86ee64e7SAndroid Build Coastguard Worker   void SetPassword(std::string password) { password_ = std::move(password); }
178*86ee64e7SAndroid Build Coastguard Worker 
179*86ee64e7SAndroid Build Coastguard Worker   // Gets the next entry. Returns null if there is no more entry, or if an error
180*86ee64e7SAndroid Build Coastguard Worker   // occurred while scanning entries. The returned Entry is owned by this
181*86ee64e7SAndroid Build Coastguard Worker   // ZipReader, and is valid until Next() is called again or until this
182*86ee64e7SAndroid Build Coastguard Worker   // ZipReader is closed.
183*86ee64e7SAndroid Build Coastguard Worker   //
184*86ee64e7SAndroid Build Coastguard Worker   // This function should be called before operations over the current entry
185*86ee64e7SAndroid Build Coastguard Worker   // like ExtractCurrentEntryToFile().
186*86ee64e7SAndroid Build Coastguard Worker   //
187*86ee64e7SAndroid Build Coastguard Worker   // while (const ZipReader::Entry* entry = reader.Next()) {
188*86ee64e7SAndroid Build Coastguard Worker   //   // Do something with the current entry here.
189*86ee64e7SAndroid Build Coastguard Worker   //   ...
190*86ee64e7SAndroid Build Coastguard Worker   // }
191*86ee64e7SAndroid Build Coastguard Worker   //
192*86ee64e7SAndroid Build Coastguard Worker   // // Finished scanning entries.
193*86ee64e7SAndroid Build Coastguard Worker   // // Check if the scanning stopped because of an error.
194*86ee64e7SAndroid Build Coastguard Worker   // if (!reader.ok()) {
195*86ee64e7SAndroid Build Coastguard Worker   //   // There was an error.
196*86ee64e7SAndroid Build Coastguard Worker   //   ...
197*86ee64e7SAndroid Build Coastguard Worker   // }
198*86ee64e7SAndroid Build Coastguard Worker   const Entry* Next();
199*86ee64e7SAndroid Build Coastguard Worker 
200*86ee64e7SAndroid Build Coastguard Worker   // Returns true if the enumeration of entries was successful, or false if it
201*86ee64e7SAndroid Build Coastguard Worker   // stopped because of an error.
ok()202*86ee64e7SAndroid Build Coastguard Worker   bool ok() const { return ok_; }
203*86ee64e7SAndroid Build Coastguard Worker 
204*86ee64e7SAndroid Build Coastguard Worker   // Extracts |num_bytes_to_extract| bytes of the current entry to |delegate|,
205*86ee64e7SAndroid Build Coastguard Worker   // starting from the beginning of the entry.
206*86ee64e7SAndroid Build Coastguard Worker   //
207*86ee64e7SAndroid Build Coastguard Worker   // Returns true if the entire file was extracted without error.
208*86ee64e7SAndroid Build Coastguard Worker   //
209*86ee64e7SAndroid Build Coastguard Worker   // Precondition: Next() returned a non-null Entry.
210*86ee64e7SAndroid Build Coastguard Worker   bool ExtractCurrentEntry(WriterDelegate* delegate,
211*86ee64e7SAndroid Build Coastguard Worker                            uint64_t num_bytes_to_extract =
212*86ee64e7SAndroid Build Coastguard Worker                                std::numeric_limits<uint64_t>::max()) const;
213*86ee64e7SAndroid Build Coastguard Worker 
214*86ee64e7SAndroid Build Coastguard Worker   // Extracts the current entry to |delegate|, starting from the beginning
215*86ee64e7SAndroid Build Coastguard Worker   // of the entry, calling |listener_callback| regularly with the number of
216*86ee64e7SAndroid Build Coastguard Worker   // bytes extracted.
217*86ee64e7SAndroid Build Coastguard Worker   //
218*86ee64e7SAndroid Build Coastguard Worker   // Returns true if the entire file was extracted without error.
219*86ee64e7SAndroid Build Coastguard Worker   //
220*86ee64e7SAndroid Build Coastguard Worker   // Precondition: Next() returned a non-null Entry.
221*86ee64e7SAndroid Build Coastguard Worker   bool ExtractCurrentEntryWithListener(
222*86ee64e7SAndroid Build Coastguard Worker       WriterDelegate* delegate,
223*86ee64e7SAndroid Build Coastguard Worker       ListenerCallback listener_callback) const;
224*86ee64e7SAndroid Build Coastguard Worker 
225*86ee64e7SAndroid Build Coastguard Worker   // Asynchronously extracts the current entry to the given output file path. If
226*86ee64e7SAndroid Build Coastguard Worker   // the current entry is a directory it just creates the directory
227*86ee64e7SAndroid Build Coastguard Worker   // synchronously instead.
228*86ee64e7SAndroid Build Coastguard Worker   //
229*86ee64e7SAndroid Build Coastguard Worker   // |success_callback| will be called on success and |failure_callback| will be
230*86ee64e7SAndroid Build Coastguard Worker   // called on failure. |progress_callback| will be called at least once.
231*86ee64e7SAndroid Build Coastguard Worker   // Callbacks will be posted to the current MessageLoop in-order.
232*86ee64e7SAndroid Build Coastguard Worker   //
233*86ee64e7SAndroid Build Coastguard Worker   // Precondition: Next() returned a non-null Entry.
234*86ee64e7SAndroid Build Coastguard Worker   void ExtractCurrentEntryToFilePathAsync(
235*86ee64e7SAndroid Build Coastguard Worker       const base::FilePath& output_file_path,
236*86ee64e7SAndroid Build Coastguard Worker       SuccessCallback success_callback,
237*86ee64e7SAndroid Build Coastguard Worker       FailureCallback failure_callback,
238*86ee64e7SAndroid Build Coastguard Worker       ProgressCallback progress_callback);
239*86ee64e7SAndroid Build Coastguard Worker 
240*86ee64e7SAndroid Build Coastguard Worker   // Extracts the current entry into memory. If the current entry is a
241*86ee64e7SAndroid Build Coastguard Worker   // directory, |*output| is set to the empty string. If the current entry is a
242*86ee64e7SAndroid Build Coastguard Worker   // file, |*output| is filled with its contents.
243*86ee64e7SAndroid Build Coastguard Worker   //
244*86ee64e7SAndroid Build Coastguard Worker   // The value in |Entry::original_size| cannot be trusted, so the real size of
245*86ee64e7SAndroid Build Coastguard Worker   // the uncompressed contents can be different. |max_read_bytes| limits the
246*86ee64e7SAndroid Build Coastguard Worker   // amount of memory used to carry the entry.
247*86ee64e7SAndroid Build Coastguard Worker   //
248*86ee64e7SAndroid Build Coastguard Worker   // Returns true if the entire content is read without error. If the content is
249*86ee64e7SAndroid Build Coastguard Worker   // bigger than |max_read_bytes|, this function returns false and |*output| is
250*86ee64e7SAndroid Build Coastguard Worker   // filled with |max_read_bytes| of data. If an error occurs, this function
251*86ee64e7SAndroid Build Coastguard Worker   // returns false and |*output| contains the content extracted so far, which
252*86ee64e7SAndroid Build Coastguard Worker   // might be garbage data.
253*86ee64e7SAndroid Build Coastguard Worker   //
254*86ee64e7SAndroid Build Coastguard Worker   // Precondition: Next() returned a non-null Entry.
255*86ee64e7SAndroid Build Coastguard Worker   bool ExtractCurrentEntryToString(uint64_t max_read_bytes,
256*86ee64e7SAndroid Build Coastguard Worker                                    std::string* output) const;
257*86ee64e7SAndroid Build Coastguard Worker 
ExtractCurrentEntryToString(std::string * output)258*86ee64e7SAndroid Build Coastguard Worker   bool ExtractCurrentEntryToString(std::string* output) const {
259*86ee64e7SAndroid Build Coastguard Worker     return ExtractCurrentEntryToString(
260*86ee64e7SAndroid Build Coastguard Worker         base::checked_cast<uint64_t>(output->max_size()), output);
261*86ee64e7SAndroid Build Coastguard Worker   }
262*86ee64e7SAndroid Build Coastguard Worker 
263*86ee64e7SAndroid Build Coastguard Worker   // Returns the number of entries in the ZIP archive.
264*86ee64e7SAndroid Build Coastguard Worker   //
265*86ee64e7SAndroid Build Coastguard Worker   // Precondition: one of the Open() methods returned true.
num_entries()266*86ee64e7SAndroid Build Coastguard Worker   int num_entries() const { return num_entries_; }
267*86ee64e7SAndroid Build Coastguard Worker 
268*86ee64e7SAndroid Build Coastguard Worker  private:
269*86ee64e7SAndroid Build Coastguard Worker   // Common code used both in Open and OpenFromFd.
270*86ee64e7SAndroid Build Coastguard Worker   bool OpenInternal();
271*86ee64e7SAndroid Build Coastguard Worker 
272*86ee64e7SAndroid Build Coastguard Worker   // Resets the internal state.
273*86ee64e7SAndroid Build Coastguard Worker   void Reset();
274*86ee64e7SAndroid Build Coastguard Worker 
275*86ee64e7SAndroid Build Coastguard Worker   // Opens the current entry in the ZIP archive. On success, returns true and
276*86ee64e7SAndroid Build Coastguard Worker   // updates the current entry state |entry_|.
277*86ee64e7SAndroid Build Coastguard Worker   //
278*86ee64e7SAndroid Build Coastguard Worker   // Note that there is no matching CloseEntry(). The current entry state is
279*86ee64e7SAndroid Build Coastguard Worker   // reset automatically as needed.
280*86ee64e7SAndroid Build Coastguard Worker   bool OpenEntry();
281*86ee64e7SAndroid Build Coastguard Worker 
282*86ee64e7SAndroid Build Coastguard Worker   // Normalizes the given path passed as UTF-16 string piece. Sets entry_.path,
283*86ee64e7SAndroid Build Coastguard Worker   // entry_.is_directory and entry_.is_unsafe.
284*86ee64e7SAndroid Build Coastguard Worker   void Normalize(base::StringPiece16 in);
285*86ee64e7SAndroid Build Coastguard Worker 
286*86ee64e7SAndroid Build Coastguard Worker   // Runs the ListenerCallback at a throttled rate.
287*86ee64e7SAndroid Build Coastguard Worker   void ReportProgress(ListenerCallback listener_callback, uint64_t bytes) const;
288*86ee64e7SAndroid Build Coastguard Worker 
289*86ee64e7SAndroid Build Coastguard Worker   // Extracts |num_bytes_to_extract| bytes of the current entry to |delegate|,
290*86ee64e7SAndroid Build Coastguard Worker   // starting from the beginning of the entry calling |listener_callback| if
291*86ee64e7SAndroid Build Coastguard Worker   // its supplied.
292*86ee64e7SAndroid Build Coastguard Worker   //
293*86ee64e7SAndroid Build Coastguard Worker   // Returns true if the entire file was extracted without error.
294*86ee64e7SAndroid Build Coastguard Worker   //
295*86ee64e7SAndroid Build Coastguard Worker   // Precondition: Next() returned a non-null Entry.
296*86ee64e7SAndroid Build Coastguard Worker   bool ExtractCurrentEntry(WriterDelegate* delegate,
297*86ee64e7SAndroid Build Coastguard Worker                            ListenerCallback listener_callback,
298*86ee64e7SAndroid Build Coastguard Worker                            uint64_t num_bytes_to_extract =
299*86ee64e7SAndroid Build Coastguard Worker                                std::numeric_limits<uint64_t>::max()) const;
300*86ee64e7SAndroid Build Coastguard Worker 
301*86ee64e7SAndroid Build Coastguard Worker   // Extracts a chunk of the file to the target.  Will post a task for the next
302*86ee64e7SAndroid Build Coastguard Worker   // chunk and success/failure/progress callbacks as necessary.
303*86ee64e7SAndroid Build Coastguard Worker   void ExtractChunk(base::File target_file,
304*86ee64e7SAndroid Build Coastguard Worker                     SuccessCallback success_callback,
305*86ee64e7SAndroid Build Coastguard Worker                     FailureCallback failure_callback,
306*86ee64e7SAndroid Build Coastguard Worker                     ProgressCallback progress_callback,
307*86ee64e7SAndroid Build Coastguard Worker                     const int64_t offset);
308*86ee64e7SAndroid Build Coastguard Worker 
309*86ee64e7SAndroid Build Coastguard Worker   std::string encoding_;
310*86ee64e7SAndroid Build Coastguard Worker   std::string password_;
311*86ee64e7SAndroid Build Coastguard Worker   unzFile zip_file_;
312*86ee64e7SAndroid Build Coastguard Worker   int num_entries_;
313*86ee64e7SAndroid Build Coastguard Worker   int next_index_;
314*86ee64e7SAndroid Build Coastguard Worker   bool reached_end_;
315*86ee64e7SAndroid Build Coastguard Worker   bool ok_;
316*86ee64e7SAndroid Build Coastguard Worker   Entry entry_;
317*86ee64e7SAndroid Build Coastguard Worker 
318*86ee64e7SAndroid Build Coastguard Worker   // Next time to report progress.
319*86ee64e7SAndroid Build Coastguard Worker   mutable base::TimeTicks next_progress_report_time_ = base::TimeTicks::Now();
320*86ee64e7SAndroid Build Coastguard Worker 
321*86ee64e7SAndroid Build Coastguard Worker   // Progress time delta.
322*86ee64e7SAndroid Build Coastguard Worker   // TODO(crbug.com/953256) Add this as parameter to the unzip options.
323*86ee64e7SAndroid Build Coastguard Worker   base::TimeDelta progress_period_ = base::Milliseconds(1000);
324*86ee64e7SAndroid Build Coastguard Worker 
325*86ee64e7SAndroid Build Coastguard Worker   // Number of bytes read since last progress report callback executed.
326*86ee64e7SAndroid Build Coastguard Worker   mutable uint64_t delta_bytes_read_ = 0;
327*86ee64e7SAndroid Build Coastguard Worker 
328*86ee64e7SAndroid Build Coastguard Worker   base::WeakPtrFactory<ZipReader> weak_ptr_factory_{this};
329*86ee64e7SAndroid Build Coastguard Worker };
330*86ee64e7SAndroid Build Coastguard Worker 
331*86ee64e7SAndroid Build Coastguard Worker // A writer delegate that writes to a given File. It is recommended that this
332*86ee64e7SAndroid Build Coastguard Worker // file be initially empty.
333*86ee64e7SAndroid Build Coastguard Worker class FileWriterDelegate : public WriterDelegate {
334*86ee64e7SAndroid Build Coastguard Worker  public:
335*86ee64e7SAndroid Build Coastguard Worker   // Constructs a FileWriterDelegate that manipulates |file|. The delegate will
336*86ee64e7SAndroid Build Coastguard Worker   // not own |file|, therefore the caller must guarantee |file| will outlive the
337*86ee64e7SAndroid Build Coastguard Worker   // delegate.
338*86ee64e7SAndroid Build Coastguard Worker   explicit FileWriterDelegate(base::File* file);
339*86ee64e7SAndroid Build Coastguard Worker 
340*86ee64e7SAndroid Build Coastguard Worker   // Constructs a FileWriterDelegate that takes ownership of |file|.
341*86ee64e7SAndroid Build Coastguard Worker   explicit FileWriterDelegate(base::File owned_file);
342*86ee64e7SAndroid Build Coastguard Worker 
343*86ee64e7SAndroid Build Coastguard Worker   FileWriterDelegate(const FileWriterDelegate&) = delete;
344*86ee64e7SAndroid Build Coastguard Worker   FileWriterDelegate& operator=(const FileWriterDelegate&) = delete;
345*86ee64e7SAndroid Build Coastguard Worker 
346*86ee64e7SAndroid Build Coastguard Worker   ~FileWriterDelegate() override;
347*86ee64e7SAndroid Build Coastguard Worker 
348*86ee64e7SAndroid Build Coastguard Worker   // Returns true if the file handle passed to the constructor is valid.
349*86ee64e7SAndroid Build Coastguard Worker   bool PrepareOutput() override;
350*86ee64e7SAndroid Build Coastguard Worker 
351*86ee64e7SAndroid Build Coastguard Worker   // Writes |num_bytes| bytes of |data| to the file, returning false on error or
352*86ee64e7SAndroid Build Coastguard Worker   // if not all bytes could be written.
353*86ee64e7SAndroid Build Coastguard Worker   bool WriteBytes(const char* data, int num_bytes) override;
354*86ee64e7SAndroid Build Coastguard Worker 
355*86ee64e7SAndroid Build Coastguard Worker   // Sets the last-modified time of the data.
356*86ee64e7SAndroid Build Coastguard Worker   void SetTimeModified(const base::Time& time) override;
357*86ee64e7SAndroid Build Coastguard Worker 
358*86ee64e7SAndroid Build Coastguard Worker   // On POSIX systems, sets the file to be executable if the source file was
359*86ee64e7SAndroid Build Coastguard Worker   // executable.
360*86ee64e7SAndroid Build Coastguard Worker   void SetPosixFilePermissions(int mode) override;
361*86ee64e7SAndroid Build Coastguard Worker 
362*86ee64e7SAndroid Build Coastguard Worker   // Empties the file to avoid leaving garbage data in it.
363*86ee64e7SAndroid Build Coastguard Worker   void OnError() override;
364*86ee64e7SAndroid Build Coastguard Worker 
365*86ee64e7SAndroid Build Coastguard Worker   // Gets the number of bytes written into the file.
file_length()366*86ee64e7SAndroid Build Coastguard Worker   int64_t file_length() { return file_length_; }
367*86ee64e7SAndroid Build Coastguard Worker 
368*86ee64e7SAndroid Build Coastguard Worker  protected:
369*86ee64e7SAndroid Build Coastguard Worker   // The delegate can optionally own the file it modifies, in which case
370*86ee64e7SAndroid Build Coastguard Worker   // owned_file_ is set and file_ is an alias for owned_file_.
371*86ee64e7SAndroid Build Coastguard Worker   base::File owned_file_;
372*86ee64e7SAndroid Build Coastguard Worker 
373*86ee64e7SAndroid Build Coastguard Worker   // The file the delegate modifies.
374*86ee64e7SAndroid Build Coastguard Worker   base::File* const file_ = &owned_file_;
375*86ee64e7SAndroid Build Coastguard Worker 
376*86ee64e7SAndroid Build Coastguard Worker   int64_t file_length_ = 0;
377*86ee64e7SAndroid Build Coastguard Worker };
378*86ee64e7SAndroid Build Coastguard Worker 
379*86ee64e7SAndroid Build Coastguard Worker // A writer delegate that creates and writes a file at a given path. This does
380*86ee64e7SAndroid Build Coastguard Worker // not overwrite any existing file.
381*86ee64e7SAndroid Build Coastguard Worker class FilePathWriterDelegate : public FileWriterDelegate {
382*86ee64e7SAndroid Build Coastguard Worker  public:
383*86ee64e7SAndroid Build Coastguard Worker   explicit FilePathWriterDelegate(base::FilePath output_file_path);
384*86ee64e7SAndroid Build Coastguard Worker 
385*86ee64e7SAndroid Build Coastguard Worker   FilePathWriterDelegate(const FilePathWriterDelegate&) = delete;
386*86ee64e7SAndroid Build Coastguard Worker   FilePathWriterDelegate& operator=(const FilePathWriterDelegate&) = delete;
387*86ee64e7SAndroid Build Coastguard Worker 
388*86ee64e7SAndroid Build Coastguard Worker   ~FilePathWriterDelegate() override;
389*86ee64e7SAndroid Build Coastguard Worker 
390*86ee64e7SAndroid Build Coastguard Worker   // Creates the output file and any necessary intermediate directories. Does
391*86ee64e7SAndroid Build Coastguard Worker   // not overwrite any existing file, and returns false if the output file
392*86ee64e7SAndroid Build Coastguard Worker   // cannot be created because another file conflicts with it.
393*86ee64e7SAndroid Build Coastguard Worker   bool PrepareOutput() override;
394*86ee64e7SAndroid Build Coastguard Worker 
395*86ee64e7SAndroid Build Coastguard Worker   // Deletes the output file.
396*86ee64e7SAndroid Build Coastguard Worker   void OnError() override;
397*86ee64e7SAndroid Build Coastguard Worker 
398*86ee64e7SAndroid Build Coastguard Worker  private:
399*86ee64e7SAndroid Build Coastguard Worker   const base::FilePath output_file_path_;
400*86ee64e7SAndroid Build Coastguard Worker };
401*86ee64e7SAndroid Build Coastguard Worker 
402*86ee64e7SAndroid Build Coastguard Worker }  // namespace zip
403*86ee64e7SAndroid Build Coastguard Worker 
404*86ee64e7SAndroid Build Coastguard Worker #endif  // THIRD_PARTY_ZLIB_GOOGLE_ZIP_READER_H_
405