123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 |
- /*
- ==============================================================================
- This file is part of the JUCE library.
- Copyright (c) 2017 - ROLI Ltd.
- JUCE is an open source library subject to commercial or open-source
- licensing.
- The code included in this file is provided under the terms of the ISC license
- http://www.isc.org/downloads/software-support-policy/isc-license. Permission
- To use, copy, modify, and/or distribute this software for any purpose with or
- without fee is hereby granted provided that the above copyright notice and
- this permission notice appear in all copies.
- JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
- EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
- DISCLAIMED.
- ==============================================================================
- */
- namespace juce
- {
- //==============================================================================
- /**
- Decodes a ZIP file from a stream.
- This can enumerate the items in a ZIP file and can create suitable stream objects
- to read each one.
- @tags{Core}
- */
- class JUCE_API ZipFile
- {
- public:
- /** Creates a ZipFile to read a specific file. */
- explicit ZipFile (const File& file);
- //==============================================================================
- /** Creates a ZipFile for a given stream.
- @param inputStream the stream to read from
- @param deleteStreamWhenDestroyed if set to true, the object passed-in
- will be deleted when this ZipFile object is deleted
- */
- ZipFile (InputStream* inputStream, bool deleteStreamWhenDestroyed);
- /** Creates a ZipFile for a given stream.
- The stream will not be owned or deleted by this class - if you want the ZipFile to
- manage the stream's lifetime, use the other constructor.
- */
- explicit ZipFile (InputStream& inputStream);
- /** Creates a ZipFile for an input source.
- The inputSource object will be owned by the zip file, which will delete
- it later when not needed.
- */
- explicit ZipFile (InputSource* inputSource);
- /** Destructor. */
- ~ZipFile();
- //==============================================================================
- /**
- Contains information about one of the entries in a ZipFile.
- @see ZipFile::getEntry
- */
- struct ZipEntry
- {
- /** The name of the file, which may also include a partial pathname. */
- String filename;
- /** The file's original size. */
- int64 uncompressedSize;
- /** The last time the file was modified. */
- Time fileTime;
- /** True if the zip entry is a symbolic link. */
- bool isSymbolicLink;
- /** Platform specific data. Depending on how the zip file was created this
- may contain macOS and Linux file types, permissions and
- setuid/setgid/sticky bits.
- */
- uint32 externalFileAttributes;
- };
- //==============================================================================
- /** Returns the number of items in the zip file. */
- int getNumEntries() const noexcept;
- /** Returns a structure that describes one of the entries in the zip file.
- This may return a nullptr if the index is out of range.
- @see ZipFile::ZipEntry
- */
- const ZipEntry* getEntry (int index) const noexcept;
- /** Returns the index of the first entry with a given filename.
- This uses a case-sensitive comparison to look for a filename in the
- list of entries. It might return -1 if no match is found.
- @see ZipFile::ZipEntry
- */
- int getIndexOfFileName (const String& fileName, bool ignoreCase = false) const noexcept;
- /** Returns a structure that describes one of the entries in the zip file.
- This uses a case-sensitive comparison to look for a filename in the
- list of entries. It might return 0 if no match is found.
- @see ZipFile::ZipEntry
- */
- const ZipEntry* getEntry (const String& fileName, bool ignoreCase = false) const noexcept;
- /** Sorts the list of entries, based on the filename. */
- void sortEntriesByFilename();
- //==============================================================================
- /** Creates a stream that can read from one of the zip file's entries.
- The stream that is returned must be deleted by the caller (and
- a nullptr might be returned if a stream can't be opened for some reason).
- The stream must not be used after the ZipFile object that created
- has been deleted.
- Note that if the ZipFile was created with a user-supplied InputStream object,
- then all the streams which are created by this method will by trying to share
- the same source stream, so cannot be safely used on multiple threads! (But if
- you create the ZipFile from a File or InputSource, then it is safe to do this).
- */
- InputStream* createStreamForEntry (int index);
- /** Creates a stream that can read from one of the zip file's entries.
- The stream that is returned must be deleted by the caller (and
- a nullptr might be returned if a stream can't be opened for some reason).
- The stream must not be used after the ZipFile object that created
- has been deleted.
- Note that if the ZipFile was created with a user-supplied InputStream object,
- then all the streams which are created by this method will by trying to share
- the same source stream, so cannot be safely used on multiple threads! (But if
- you create the ZipFile from a File or InputSource, then it is safe to do this).
- */
- InputStream* createStreamForEntry (const ZipEntry& entry);
- //==============================================================================
- /** Uncompresses all of the files in the zip file.
- This will expand all the entries into a target directory. The relative
- paths of the entries are used.
- @param targetDirectory the root folder to uncompress to
- @param shouldOverwriteFiles whether to overwrite existing files with similarly-named ones
- @returns success if the file is successfully unzipped
- */
- Result uncompressTo (const File& targetDirectory,
- bool shouldOverwriteFiles = true);
- /** Uncompresses one of the entries from the zip file.
- This will expand the entry and write it in a target directory. The entry's path is used to
- determine which subfolder of the target should contain the new file.
- @param index the index of the entry to uncompress - this must be a valid index
- between 0 and (getNumEntries() - 1).
- @param targetDirectory the root folder to uncompress into
- @param shouldOverwriteFiles whether to overwrite existing files with similarly-named ones
- @returns success if all the files are successfully unzipped
- */
- Result uncompressEntry (int index,
- const File& targetDirectory,
- bool shouldOverwriteFiles = true);
- //==============================================================================
- /** Used to create a new zip file.
- Create a ZipFile::Builder object, and call its addFile() method to add some files,
- then you can write it to a stream with write().
- */
- class JUCE_API Builder
- {
- public:
- /** Creates an empty builder object. */
- Builder();
- /** Destructor. */
- ~Builder();
- /** Adds a file to the list of items which will be added to the archive.
- The file isn't read immediately: the files will be read later when the writeToStream()
- method is called.
- The compressionLevel can be between 0 (no compression), and 9 (maximum compression).
- If the storedPathName parameter is specified, you can customise the partial pathname that
- will be stored for this file.
- */
- void addFile (const File& fileToAdd, int compressionLevel,
- const String& storedPathName = String());
- /** Adds a stream to the list of items which will be added to the archive.
- @param streamToRead this stream isn't read immediately - a pointer to the stream is
- stored, then used later when the writeToStream() method is called, and
- deleted by the Builder object when no longer needed, so be very careful
- about its lifetime and the lifetime of any objects on which it depends!
- This must not be null.
- @param compressionLevel this can be between 0 (no compression), and 9 (maximum compression).
- @param storedPathName the partial pathname that will be stored for this file
- @param fileModificationTime the timestamp that will be stored as the last modification time
- of this entry
- */
- void addEntry (InputStream* streamToRead, int compressionLevel,
- const String& storedPathName, Time fileModificationTime);
- /** Generates the zip file, writing it to the specified stream.
- If the progress parameter is non-null, it will be updated with an approximate
- progress status between 0 and 1.0
- */
- bool writeToStream (OutputStream& target, double* progress) const;
- //==============================================================================
- private:
- struct Item;
- OwnedArray<Item> items;
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Builder)
- };
- private:
- //==============================================================================
- struct ZipInputStream;
- struct ZipEntryHolder;
- OwnedArray<ZipEntryHolder> entries;
- CriticalSection lock;
- InputStream* inputStream = nullptr;
- std::unique_ptr<InputStream> streamToDelete;
- std::unique_ptr<InputSource> inputSource;
- #if JUCE_DEBUG
- struct OpenStreamCounter
- {
- OpenStreamCounter() = default;
- ~OpenStreamCounter();
- int numOpenStreams = 0;
- };
- OpenStreamCounter streamCounter;
- #endif
- void init();
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ZipFile)
- };
- } // namespace juce
|