/* * Copyright (c) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef FOUNDATION_AAFWK_STANDARD_TOOLS_ZIP_READER_H_ #define FOUNDATION_AAFWK_STANDARD_TOOLS_ZIP_READER_H_ #include #include #include #include #include #include #include #include "file_path.h" #include "zip_utils.h" #include "contrib/minizip/unzip.h" namespace OHOS { namespace AAFwk { namespace LIBZIP { // A delegate interface used to stream out an entry; see // ZipReader::ExtractCurrentEntry. class WriterDelegate { public: virtual ~WriterDelegate() {} // Invoked once before any data is streamed out to pave the way (e.g., to open // the output file). Return false on failure to cancel extraction. virtual bool PrepareOutput() = 0; // Invoked to write the next chunk of data. Return false on failure to cancel // extraction. virtual bool WriteBytes(const char *data, int numBytes) = 0; // Sets the last-modified time of the data. virtual void SetTimeModified(const struct tm *modifiedTime) = 0; }; // This class is used for reading zip files. class ZipReader { public: // A callback that is called when the operation is successful. using SuccessCallback = std::function; // A callback that is called when the operation fails. using FailureCallback = std::function; using ProgressCallback = std::function; // This class represents information of an entry (file or directory) in // a zip file. class EntryInfo { public: EntryInfo(const std::string &fileNameInZip, const unz_file_info &rawFileInfo); virtual ~EntryInfo() {} // Returns the file path. The path is usually relative like // "foo/bar.txt", but if it's absolute, is_unsafe() returns true. const FilePath &GetFilePath() const { return filePath_; } // Returns the size of the original file (i.e. after uncompressed). // Returns 0 if the entry is a directory. // Note: this value should not be trusted, because it is stored as metadata // in the zip archive and can be different from the real uncompressed size. int64_t GetOriginalSize() const { return originalSize_; } // Returns the last modified time. If the time stored in the zip file was // not valid, the unix epoch will be returned. struct tm GetLastModified() const { return lastModified_; } // Returns true if the entry is a directory. bool IsDirectory() const { return isDirectory_; } // Returns true if the entry is unsafe, like having ".." or invalid // UTF-8 characters in its file name, or the file path is absolute. bool IsUnsafe() const { return isUnsafe_; } // Returns true if the entry is encrypted. bool IsEncrypted() const { return isEncrypted_; } private: FilePath filePath_; int64_t originalSize_ = 0; struct tm lastModified_ { .tm_year = 0, .tm_mon = 0, .tm_mday = 0, .tm_hour = 0, .tm_min = 0, .tm_sec = 0 }; bool isDirectory_ = false; bool isUnsafe_ = false; bool isEncrypted_ = false; DISALLOW_COPY_AND_ASSIGN(EntryInfo); }; ZipReader(); ~ZipReader(); // Opens the zip file specified by |zipFilePath|. Returns true on // success. bool Open(FilePath &zipFilePath); // Opens the zip file referred to by the platform file |zipFd|, without // taking ownership of |zipFd|. Returns true on success. bool OpenFromPlatformFile(PlatformFile zipFd); // Opens the zip data stored in |data|. This class uses a weak reference to // the given sring while extracting files, i.e. the caller should keep the // string until it finishes extracting files. bool OpenFromString(const std::string &data); // Closes the currently opened zip file. This function is called in the // destructor of the class, so you usually don't need to call this. void Close(); // Returns true if there is at least one entry to read. This function is // used to scan entries with AdvanceToNextEntry(), like: // // while (reader.HasMore()) { // // Do something with the current file here. // reader.AdvanceToNextEntry(); // } bool HasMore(); // Advances the next entry. Returns true on success. bool AdvanceToNextEntry(); // Opens the current entry in the zip file. On success, returns true and // updates the the current entry state (i.e. CurrentEntryInfo() is // updated). This function should be called before operations over the // current entry like ExtractCurrentEntryToFile(). // // Note that there is no CloseCurrentEntryInZip(). The the current entry // state is reset automatically as needed. bool OpenCurrentEntryInZip(); // Extracts |numBytesToExtract| bytes of the current entry to |delegate|, // starting from the beginning of the entry. Return value specifies whether // the entire file was extracted. bool ExtractCurrentEntry(WriterDelegate *delegate, uint64_t numBytesToExtract) const; // Returns the current entry info. Returns NULL if the current entry is // not yet opened. OpenCurrentEntryInZip() must be called beforehand. EntryInfo *CurrentEntryInfo() const { return currentEntryInfo_.get(); } // Returns the number of entries in the zip file. // Open() must be called beforehand. int num_entries() const { return numEntries_; } private: // Common code used both in Open and OpenFromFd. bool OpenInternal(); // Resets the internal state. void Reset(); unzFile zipFile_; int numEntries_; bool reachedEnd_; std::unique_ptr currentEntryInfo_; DISALLOW_COPY_AND_ASSIGN(ZipReader); }; // A writer delegate that writes a file at a given path. class FilePathWriterDelegate : public WriterDelegate { public: explicit FilePathWriterDelegate(const FilePath &outputFilePath); ~FilePathWriterDelegate() override; // WriterDelegate methods: // Creates the output file and any necessary intermediate directories. bool PrepareOutput() override; // Writes |numBytes| bytes of |data| to the file, returning false if not all // bytes could be written. bool WriteBytes(const char *data, int numBytes) override; // Sets the last-modified time of the data. void SetTimeModified(const struct tm *time) override; private: FilePath outputFilePath_ = FilePath(std::string()); FILE *file_ = nullptr; DISALLOW_COPY_AND_ASSIGN(FilePathWriterDelegate); }; } // namespace LIBZIP } // namespace AAFwk } // namespace OHOS #endif // FOUNDATION_AAFWK_STANDARD_TOOLS_ZIP_READER_H_