diff --git a/Minecraft.Client/Common/libs/bit7z/include/bit7z.hpp b/Minecraft.Client/Common/libs/bit7z/include/bit7z.hpp new file mode 100644 index 000000000..ac3afd8ea --- /dev/null +++ b/Minecraft.Client/Common/libs/bit7z/include/bit7z.hpp @@ -0,0 +1,25 @@ +/* + * bit7z - A C++ static library to interface with the 7-zip shared libraries. + * Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef BIT7Z_HPP +#define BIT7Z_HPP + +#include "bitarchiveeditor.hpp" +#include "bitarchivereader.hpp" +#include "bitarchivewriter.hpp" +#include "bitexception.hpp" +#include "bitfilecompressor.hpp" +#include "bitfileextractor.hpp" +#include "bitmemcompressor.hpp" +#include "bitmemextractor.hpp" +#include "bitstreamcompressor.hpp" +#include "bitstreamextractor.hpp" + +#endif // BIT7Z_HPP + diff --git a/Minecraft.Client/Common/libs/bit7z/include/bit7zlibrary.hpp b/Minecraft.Client/Common/libs/bit7z/include/bit7zlibrary.hpp new file mode 100644 index 000000000..652b5b6b0 --- /dev/null +++ b/Minecraft.Client/Common/libs/bit7z/include/bit7zlibrary.hpp @@ -0,0 +1,101 @@ +/* + * bit7z - A C++ static library to interface with the 7-zip shared libraries. + * Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef BIT7ZLIBRARY_HPP +#define BIT7ZLIBRARY_HPP + +#include + +#include "bitformat.hpp" +#include "bittypes.hpp" +#include "bitwindows.hpp" + +//! @cond IGNORE_BLOCK_IN_DOXYGEN +struct IInArchive; +struct IOutArchive; + +template< typename T > +class CMyComPtr; +//! @endcond + +/** + * @brief The main namespace of the bit7z library. + */ +namespace bit7z { + +/** + * @brief The default file path for the 7-zip shared library to be used by bit7z + * in case the user doesn't pass a path to the constructor of the Bit7zLibrary class. + * + * @note On Windows, the default library is 7z.dll, and it is searched following the Win32 API rules + * (https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order). + * + * @note On Linux, the default library is the absolute path to the "7z.so" installed by p7zip. + * + * @note In all other cases, the value will be the relative path to a "7z.so" in the working directory of the program. + */ +#ifdef __DOXYGEN__ +constexpr auto kDefaultLibrary = ""; +#elif defined( _WIN32 ) +constexpr auto kDefaultLibrary = BIT7Z_STRING( "7z.dll" ); +#elif defined( __linux__ ) +constexpr auto kDefaultLibrary = "/usr/lib/p7zip/7z.so"; // Default installation path of the p7zip shared library. +#else +constexpr auto kDefaultLibrary = "./7z.so"; +#endif + +/** + * @brief The Bit7zLibrary class allows accessing the basic functionalities provided by the 7z DLLs. + */ +class Bit7zLibrary final { + public: + Bit7zLibrary( const Bit7zLibrary& ) = delete; + + Bit7zLibrary( Bit7zLibrary&& ) = delete; + + auto operator=( const Bit7zLibrary& ) -> Bit7zLibrary& = delete; + + auto operator=( Bit7zLibrary&& ) -> Bit7zLibrary& = delete; + + /** + * @brief Constructs a Bit7zLibrary object by loading the specified 7zip shared library. + * + * By default, it searches a 7z.dll in the same path of the application. + * + * @param libraryPath the path to the shared library file to be loaded. + */ + explicit Bit7zLibrary( const tstring& libraryPath = kDefaultLibrary ); + + /** + * @brief Destructs the Bit7zLibrary object, freeing the loaded shared library. + */ + ~Bit7zLibrary(); + + /** + * @brief Set the 7-zip shared library to use large memory pages. + */ + void setLargePageMode(); + + private: + HMODULE mLibrary; + FARPROC mCreateObjectFunc; + + BIT7Z_NODISCARD + auto initInArchive( const BitInFormat& format ) const -> CMyComPtr< IInArchive >; + + BIT7Z_NODISCARD + auto initOutArchive( const BitInOutFormat& format ) const -> CMyComPtr< IOutArchive >; + + friend class BitInputArchive; + friend class BitOutputArchive; +}; + +} // namespace bit7z + +#endif // BIT7ZLIBRARY_HPP diff --git a/Minecraft.Client/Common/libs/bit7z/include/bitabstractarchivecreator.hpp b/Minecraft.Client/Common/libs/bit7z/include/bitabstractarchivecreator.hpp new file mode 100644 index 000000000..4911d53d5 --- /dev/null +++ b/Minecraft.Client/Common/libs/bit7z/include/bitabstractarchivecreator.hpp @@ -0,0 +1,305 @@ +/* + * bit7z - A C++ static library to interface with the 7-zip shared libraries. + * Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef BITABSTRACTARCHIVECREATOR_HPP +#define BITABSTRACTARCHIVECREATOR_HPP + +#include +#include + +#include "bitabstractarchivehandler.hpp" +#include "bitcompressionlevel.hpp" +#include "bitcompressionmethod.hpp" +#include "bitformat.hpp" +#include "bitinputarchive.hpp" + +struct IOutStream; +struct ISequentialOutStream; + +namespace bit7z { + +using std::ostream; + +class ArchiveProperties; + +/** + * @brief Enumeration representing how an archive creator should deal when the output archive already exists. + */ +enum struct UpdateMode { + None, ///< The creator will throw an exception (unless the OverwriteMode is not None). + Append, ///< The creator will append the new items to the existing archive. + Update, ///< New items whose path already exists in the archive will overwrite the old ones, other will be appended. + BIT7Z_DEPRECATED_ENUMERATOR( Overwrite, Update, "Since v4.0; please use the UpdateMode::Update enumerator." ) ///< @deprecated since v4.0; please use the UpdateMode::Update enumerator. +}; + +/** + * @brief Abstract class representing a generic archive creator. + */ +class BitAbstractArchiveCreator : public BitAbstractArchiveHandler { + public: + BitAbstractArchiveCreator( const BitAbstractArchiveCreator& ) = delete; + + BitAbstractArchiveCreator( BitAbstractArchiveCreator&& ) = delete; + + auto operator=( const BitAbstractArchiveCreator& ) -> BitAbstractArchiveCreator& = delete; + + auto operator=( BitAbstractArchiveCreator&& ) -> BitAbstractArchiveCreator& = delete; + + ~BitAbstractArchiveCreator() override = default; + + /** + * @return the format used for creating/updating an archive. + */ + BIT7Z_NODISCARD auto format() const noexcept -> const BitInFormat& override; + + /** + * @return the format used for creating/updating an archive. + */ + BIT7Z_NODISCARD auto compressionFormat() const noexcept -> const BitInOutFormat&; + + /** + * @return whether the creator crypts also the headers of archives or not. + */ + BIT7Z_NODISCARD auto cryptHeaders() const noexcept -> bool; + + /** + * @return the compression level used for creating/updating an archive. + */ + BIT7Z_NODISCARD auto compressionLevel() const noexcept -> BitCompressionLevel; + + /** + * @return the compression method used for creating/updating an archive. + */ + BIT7Z_NODISCARD auto compressionMethod() const noexcept -> BitCompressionMethod; + + /** + * @return the dictionary size used for creating/updating an archive. + */ + BIT7Z_NODISCARD auto dictionarySize() const noexcept -> uint32_t; + + /** + * @return the word size used for creating/updating an archive. + */ + BIT7Z_NODISCARD auto wordSize() const noexcept -> uint32_t; + + /** + * @return whether the archive creator uses solid compression or not. + */ + BIT7Z_NODISCARD auto solidMode() const noexcept -> bool; + + /** + * @return the update mode used when updating existing archives. + */ + BIT7Z_NODISCARD auto updateMode() const noexcept -> UpdateMode; + + /** + * @return the volume size (in bytes) used when creating multi-volume archives + * (a 0 value means that all files are going in a single archive). + */ + BIT7Z_NODISCARD auto volumeSize() const noexcept -> uint64_t; + + /** + * @return the number of threads used when creating/updating an archive + * (a 0 value means that it will use the 7-zip default value). + */ + BIT7Z_NODISCARD auto threadsCount() const noexcept -> uint32_t; + + /** + * @return whether the archive creator stores symbolic links as links in the output archive. + */ + BIT7Z_NODISCARD auto storeSymbolicLinks() const noexcept -> bool; + + /** + * @brief Sets up a password for the output archives. + * + * When setting a password, the produced archives will be encrypted using the default + * cryptographic method of the output format. The option "crypt headers" remains unchanged, + * in contrast with what happens when calling the setPassword(tstring, bool) method. + * + * @note Calling setPassword when the output format doesn't support archive encryption + * (e.g., GZip, BZip2, etc...) does not have any effects (in other words, it doesn't + * throw exceptions, and it has no effects on compression operations). + * + * @note After a password has been set, it will be used for every subsequent operation. + * To disable the use of the password, you need to call the clearPassword method + * (inherited from BitAbstractArchiveHandler), which is equivalent to setPassword(L""). + * + * @param password the password to be used when creating/updating archives. + */ + void setPassword( const tstring& password ) override; + + /** + * @brief Sets up a password for the output archive. + * + * When setting a password, the produced archive will be encrypted using the default + * cryptographic method of the output format. If the format is 7z, and the option + * "cryptHeaders" is set to true, the headers of the archive will be encrypted, + * resulting in a password request every time the output file will be opened. + * + * @note Calling setPassword when the output format doesn't support archive encryption + * (e.g., GZip, BZip2, etc...) does not have any effects (in other words, it doesn't + * throw exceptions, and it has no effects on compression operations). + * + * @note Calling setPassword with "cryptHeaders" set to true does not have effects on + * formats different from 7z. + * + * @note After a password has been set, it will be used for every subsequent operation. + * To disable the use of the password, you need to call the clearPassword method + * (inherited from BitAbstractArchiveHandler), which is equivalent to setPassword(L""). + * + * @param password the password to be used when creating/updating archives. + * @param cryptHeaders if true, the headers of the output archives will be encrypted + * (valid only when using the 7z format). + */ + void setPassword( const tstring& password, bool cryptHeaders ); + + /** + * @brief Sets the compression level to be used when creating/updating an archive. + * + * @param level the compression level desired. + */ + void setCompressionLevel( BitCompressionLevel level ) noexcept; + + /** + * @brief Sets the compression method to be used when creating/updating an archive. + * + * @param method the compression method desired. + */ + void setCompressionMethod( BitCompressionMethod method ); + + /** + * @brief Sets the dictionary size to be used when creating/updating an archive. + * + * @param dictionarySize the dictionary size desired. + */ + void setDictionarySize( uint32_t dictionarySize ); + + /** + * @brief Sets the word size to be used when creating/updating an archive. + * + * @param wordSize the word size desired. + */ + void setWordSize( uint32_t wordSize ); + + /** + * @brief Sets whether to use solid compression or not. + * + * @note Setting the solid compression mode to true has effect only when using the 7z format with multiple + * input files. + * + * @param solidMode if true, it will be used the "solid compression" method. + */ + void setSolidMode( bool solidMode ) noexcept; + + /** + * @brief Sets whether and how the creator can update existing archives or not. + * + * @note If set to UpdateMode::None, a subsequent compression operation may throw an exception + * if it targets an existing archive. + * + * @param mode the desired update mode. + */ + virtual void setUpdateMode( UpdateMode mode ); + + /** + * @brief Sets whether the creator can update existing archives or not. + * + * @deprecated since v4.0; it is provided just for an easier transition from the old v3 API. + * + * @note If set to false, a subsequent compression operation may throw an exception + * if it targets an existing archive. + * + * @param canUpdate if true, compressing operations will update existing archives. + */ + BIT7Z_DEPRECATED_MSG( "Since v4.0; please use the overloaded function that takes an UpdateMode enumerator." ) + void setUpdateMode( bool canUpdate ); + + /** + * @brief Sets the volumeSize (in bytes) of the output archive volumes. + * + * @note This setting has effects only when the destination archive is on the filesystem. + * + * @param volumeSize The dimension of a volume. + */ + void setVolumeSize( uint64_t volumeSize ) noexcept; + + /** + * @brief Sets the number of threads to be used when creating/updating an archive. + * + * @param threadsCount the number of threads desired. + */ + void setThreadsCount( uint32_t threadsCount ) noexcept; + + /** + * @brief Sets whether the creator will store symbolic links as links in the output archive. + * + * @param storeSymlinks if true, symbolic links will be stored as links. + */ + void setStoreSymbolicLinks( bool storeSymlinks ) noexcept; + + /** + * @brief Sets a property for the output archive format as described by the 7-zip documentation + * (e.g., https://sevenzip.osdn.jp/chm/cmdline/switches/method.htm). + * + * @tparam T An integral type (i.e., a bool or an integer type). + * + * @param name The string name of the property to be set. + * @param value The value to be used for the property. + */ + template< std::size_t N, typename T, typename = typename std::enable_if< std::is_integral< T >::value >::type > + void setFormatProperty( const wchar_t (&name)[N], T value ) noexcept { // NOLINT(*-avoid-c-arrays) + mExtraProperties[ name ] = value; + } + + /** + * @brief Sets a property for the output archive format as described by the 7-zip documentation + * (e.g., https://sevenzip.osdn.jp/chm/cmdline/switches/method.htm). + * + * For example, passing the string L"tm" with a false value while creating a .7z archive + * will disable storing the last modified timestamps of the compressed files. + * + * @tparam T A non-integral type (i.e., a string). + * + * @param name The string name of the property to be set. + * @param value The value to be used for the property. + */ + template< std::size_t N, typename T, typename = typename std::enable_if< !std::is_integral< T >::value >::type > + void setFormatProperty( const wchar_t (&name)[N], const T& value ) noexcept { // NOLINT(*-avoid-c-arrays) + mExtraProperties[ name ] = value; + } + + protected: + BitAbstractArchiveCreator( const Bit7zLibrary& lib, + const BitInOutFormat& format, + tstring password = {}, + UpdateMode updateMode = UpdateMode::None ); + + BIT7Z_NODISCARD auto archiveProperties() const -> ArchiveProperties; + + friend class BitOutputArchive; + + private: + const BitInOutFormat& mFormat; + + UpdateMode mUpdateMode; + BitCompressionLevel mCompressionLevel; + BitCompressionMethod mCompressionMethod; + uint32_t mDictionarySize; + uint32_t mWordSize; + bool mCryptHeaders; + bool mSolidMode; + uint64_t mVolumeSize; + uint32_t mThreadsCount; + bool mStoreSymbolicLinks; + std::map< std::wstring, BitPropVariant > mExtraProperties; +}; + +} // namespace bit7z + +#endif // BITABSTRACTARCHIVECREATOR_HPP diff --git a/Minecraft.Client/Common/libs/bit7z/include/bitabstractarchivehandler.hpp b/Minecraft.Client/Common/libs/bit7z/include/bitabstractarchivehandler.hpp new file mode 100644 index 000000000..8b0a176c2 --- /dev/null +++ b/Minecraft.Client/Common/libs/bit7z/include/bitabstractarchivehandler.hpp @@ -0,0 +1,249 @@ +/* + * bit7z - A C++ static library to interface with the 7-zip shared libraries. + * Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef BITABSTRACTARCHIVEHANDLER_HPP +#define BITABSTRACTARCHIVEHANDLER_HPP + +#include +#include + +#include "bit7zlibrary.hpp" +#include "bitdefines.hpp" + +namespace bit7z { + +class BitInFormat; + +/** + * @brief A std::function whose argument is the total size of the ongoing operation. + */ +using TotalCallback = std::function< void( uint64_t ) >; + +/** + * @brief A std::function whose argument is the currently processed size of the ongoing operation and returns + * true or false whether the operation must continue or not. + */ +using ProgressCallback = std::function< bool( uint64_t ) >; + +/** + * @brief A std::function whose arguments are the current processed input size, and the current output size of the + * ongoing operation. + */ +using RatioCallback = std::function< void( uint64_t, uint64_t ) >; + +/** + * @brief A std::function whose argument is the path, in the archive, of the file currently being processed + * by the ongoing operation. + */ +using FileCallback = std::function< void( tstring ) >; + +/** + * @brief A std::function returning the password to be used to handle an archive. + */ +using PasswordCallback = std::function< tstring() >; + +/** + * @brief Enumeration representing how a handler should deal when an output file already exists. + */ +enum struct OverwriteMode { + None = 0, ///< The handler will throw an exception if the output file or buffer already exists. + Overwrite, ///< The handler will overwrite the old file or buffer with the new one. + Skip, ///< The handler will skip writing to the output file or buffer. +//TODO: RenameOutput, +//TODO: RenameExisting +}; + +/** + * @brief Enumeration representing the policy according to which the archive handler should treat + * the items that match the pattern given by the user. + */ +enum struct FilterPolicy { + Include, ///< Extract/compress the items that match the pattern. + Exclude ///< Do not extract/compress the items that match the pattern. +}; + +/** + * @brief Abstract class representing a generic archive handler. + */ +class BitAbstractArchiveHandler { + public: + BitAbstractArchiveHandler( const BitAbstractArchiveHandler& ) = delete; + + BitAbstractArchiveHandler( BitAbstractArchiveHandler&& ) = delete; + + auto operator=( const BitAbstractArchiveHandler& ) -> BitAbstractArchiveHandler& = delete; + + auto operator=( BitAbstractArchiveHandler&& ) -> BitAbstractArchiveHandler& = delete; + + virtual ~BitAbstractArchiveHandler() = default; + + /** + * @return the Bit7zLibrary object used by the handler. + */ + BIT7Z_NODISCARD auto library() const noexcept -> const Bit7zLibrary&; + + /** + * @return the format used by the handler for extracting or compressing. + */ + BIT7Z_NODISCARD virtual auto format() const -> const BitInFormat& = 0; + + /** + * @return the password used to open, extract, or encrypt the archive. + */ + BIT7Z_NODISCARD auto password() const -> tstring; + + /** + * @return a boolean value indicating whether the directory structure must be preserved while extracting + * or compressing the archive. + */ + BIT7Z_NODISCARD auto retainDirectories() const noexcept -> bool; + + /** + * @return a boolean value indicating whether a password is defined or not. + */ + BIT7Z_NODISCARD auto isPasswordDefined() const noexcept -> bool; + + /** + * @return the current total callback. + */ + BIT7Z_NODISCARD auto totalCallback() const -> TotalCallback; + + /** + * @return the current progress callback. + */ + BIT7Z_NODISCARD auto progressCallback() const -> ProgressCallback; + + /** + * @return the current ratio callback. + */ + BIT7Z_NODISCARD auto ratioCallback() const -> RatioCallback; + + /** + * @return the current file callback. + */ + BIT7Z_NODISCARD auto fileCallback() const -> FileCallback; + + /** + * @return the current password callback. + */ + BIT7Z_NODISCARD auto passwordCallback() const -> PasswordCallback; + + /** + * @return the current OverwriteMode. + */ + BIT7Z_NODISCARD auto overwriteMode() const -> OverwriteMode; + + /** + * @brief Sets up a password to be used by the archive handler. + * + * The password will be used to encrypt/decrypt archives by using the default + * cryptographic method of the archive format. + * + * @note Calling setPassword when the input archive is not encrypted does not have any effect on + * the extraction process. + * + * @note Calling setPassword when the output format doesn't support archive encryption + * (e.g., GZip, BZip2, etc...) does not have any effects (in other words, it doesn't + * throw exceptions, and it has no effects on compression operations). + * + * @note After a password has been set, it will be used for every subsequent operation. + * To disable the use of the password, you need to call the clearPassword method, which is equivalent + * to calling setPassword(L""). + * + * @param password the password to be used. + */ + virtual void setPassword( const tstring& password ); + + /** + * @brief Clear the current password used by the handler. + * + * Calling clearPassword() will disable the encryption/decryption of archives. + * + * @note This is equivalent to calling setPassword(L""). + */ + void clearPassword() noexcept; + + /** + * @brief Sets whether the operations' output will preserve the input's directory structure or not. + * + * @param retain the setting for preserving or not the input directory structure + */ + void setRetainDirectories( bool retain ) noexcept; + + /** + * @brief Sets the function to be called when the total size of an operation is available. + * + * @param callback the total callback to be used. + */ + void setTotalCallback( const TotalCallback& callback ); + + /** + * @brief Sets the function to be called when the processed size of the ongoing operation is updated. + * + * @note The completion percentage of the current operation can be obtained by calculating + * `static_cast((100.0 * processed_size) / total_size)`. + * + * @param callback the progress callback to be used. + */ + void setProgressCallback( const ProgressCallback& callback ); + + /** + * @brief Sets the function to be called when the input processed size and current output size of the + * ongoing operation are known. + * + * @note The ratio percentage of a compression operation can be obtained by calculating + * `static_cast((100.0 * output_size) / input_size)`. + * + * @param callback the ratio callback to be used. + */ + void setRatioCallback( const RatioCallback& callback ); + + /** + * @brief Sets the function to be called when the current file being processed changes. + * + * @param callback the file callback to be used. + */ + void setFileCallback( const FileCallback& callback ); + + /** + * @brief Sets the function to be called when a password is needed to complete the ongoing operation. + * + * @param callback the password callback to be used. + */ + void setPasswordCallback( const PasswordCallback& callback ); + + /** + * @brief Sets how the handler should behave when it tries to output to an existing file or buffer. + * + * @param mode the OverwriteMode to be used by the handler. + */ + void setOverwriteMode( OverwriteMode mode ); + + protected: + explicit BitAbstractArchiveHandler( const Bit7zLibrary& lib, + tstring password = {}, + OverwriteMode overwriteMode = OverwriteMode::None ); + + private: + const Bit7zLibrary& mLibrary; + tstring mPassword; + bool mRetainDirectories; + OverwriteMode mOverwriteMode; + + //CALLBACKS + TotalCallback mTotalCallback; + ProgressCallback mProgressCallback; + RatioCallback mRatioCallback; + FileCallback mFileCallback; + PasswordCallback mPasswordCallback; +}; + +} // namespace bit7z + +#endif // BITABSTRACTARCHIVEHANDLER_HPP diff --git a/Minecraft.Client/Common/libs/bit7z/include/bitabstractarchiveopener.hpp b/Minecraft.Client/Common/libs/bit7z/include/bitabstractarchiveopener.hpp new file mode 100644 index 000000000..91adc0fc8 --- /dev/null +++ b/Minecraft.Client/Common/libs/bit7z/include/bitabstractarchiveopener.hpp @@ -0,0 +1,59 @@ +/* + * bit7z - A C++ static library to interface with the 7-zip shared libraries. + * Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef BITABSTRACTARCHIVEOPENER_HPP +#define BITABSTRACTARCHIVEOPENER_HPP + +#include +#include + +#include "bitabstractarchivehandler.hpp" +#include "bitformat.hpp" + +namespace bit7z { + +using std::ostream; + +/** + * @brief The BitAbstractArchiveOpener abstract class represents a generic archive opener. + */ +class BitAbstractArchiveOpener : public BitAbstractArchiveHandler { + public: + BitAbstractArchiveOpener( const BitAbstractArchiveOpener& ) = delete; + + BitAbstractArchiveOpener( BitAbstractArchiveOpener&& ) = delete; + + auto operator=( const BitAbstractArchiveOpener& ) -> BitAbstractArchiveOpener& = delete; + + auto operator=( BitAbstractArchiveOpener&& ) -> BitAbstractArchiveOpener& = delete; + + ~BitAbstractArchiveOpener() override = default; + + /** + * @return the archive format used by the archive opener. + */ + BIT7Z_NODISCARD auto format() const noexcept -> const BitInFormat& override; + + /** + * @return the archive format used by the archive opener. + */ + BIT7Z_NODISCARD auto extractionFormat() const noexcept -> const BitInFormat&; + + protected: + BitAbstractArchiveOpener( const Bit7zLibrary& lib, + const BitInFormat& format, + const tstring& password = {} ); + + private: + const BitInFormat& mFormat; +}; + +} // namespace bit7z + +#endif // BITABSTRACTARCHIVEOPENER_HPP diff --git a/Minecraft.Client/Common/libs/bit7z/include/bitarchiveeditor.hpp b/Minecraft.Client/Common/libs/bit7z/include/bitarchiveeditor.hpp new file mode 100644 index 000000000..0e47ddb4a --- /dev/null +++ b/Minecraft.Client/Common/libs/bit7z/include/bitarchiveeditor.hpp @@ -0,0 +1,200 @@ +/* + * bit7z - A C++ static library to interface with the 7-zip shared libraries. + * Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef BITARCHIVEEDITOR_HPP +#define BITARCHIVEEDITOR_HPP + +#include + +#include "bitarchivewriter.hpp" + +namespace bit7z { + +using std::vector; + +using EditedItems = std::unordered_map< uint32_t, BitItemsVector::value_type >; + +enum struct DeletePolicy : std::uint8_t { + ItemOnly, + RecurseDirs +}; + +/** + * @brief The BitArchiveEditor class allows creating new file archives or updating old ones. + * Update operations supported are the addition of new items, + * as well as renaming/updating/deleting old items; + * + * @note Changes are applied to the archive only after calling the applyChanges() method. + */ +class BIT7Z_MAYBE_UNUSED BitArchiveEditor final : public BitArchiveWriter { + public: + /** + * @brief Constructs a BitArchiveEditor object, reading the given archive file path. + * + * @param lib the 7z library to use. + * @param inFile the path to an input archive file. + * @param format the input/output archive format. + * @param password (optional) the password needed to read the input archive. + */ + BitArchiveEditor( const Bit7zLibrary& lib, + const tstring& inFile, + const BitInOutFormat& format, + const tstring& password = {} ); + + BitArchiveEditor( const BitArchiveEditor& ) = delete; + + BitArchiveEditor( BitArchiveEditor&& ) = delete; + + auto operator=( const BitArchiveEditor& ) -> BitArchiveEditor& = delete; + + auto operator=( BitArchiveEditor&& ) -> BitArchiveEditor& = delete; + + ~BitArchiveEditor() override; + + /** + * @brief Sets how the editor performs the update of the items in the archive. + * + * @note BitArchiveEditor doesn't support UpdateMode::None. + * + * @param mode the desired update mode (either UpdateMode::Append or UpdateMode::Overwrite). + */ + void setUpdateMode( UpdateMode mode ) override; + + /** + * @brief Requests to change the path of the item at the specified index with the given one. + * + * @param index the index of the item to be renamed. + * @param newPath the new path (in the archive) desired for the item. + */ + void renameItem( uint32_t index, const tstring& newPath ); + + /** + * @brief Requests to change the path of the item from oldPath to the newPath. + * + * @param oldPath the old path (in the archive) of the item to be renamed. + * @param newPath the new path (in the archive) desired for the item. + */ + void renameItem( const tstring& oldPath, const tstring& newPath ); + + /** + * @brief Requests to update the content of the item at the specified index + * with the data from the given file. + * + * @param index the index of the item to be updated. + * @param inFile the path to the file containing the new data for the item. + */ + void updateItem( uint32_t index, const tstring& inFile ); + + /** + * @brief Requests to update the content of the item at the specified index + * with the data from the given buffer. + * + * @param index the index of the item to be updated. + * @param inBuffer the buffer containing the new data for the item. + */ + void updateItem( uint32_t index, const std::vector< byte_t >& inBuffer ); + + /** + * @brief Requests to update the content of the item at the specified index + * with the data from the given stream. + * + * @param index the index of the item to be updated. + * @param inStream the stream of new data for the item. + */ + void updateItem( uint32_t index, std::istream& inStream ); + + /** + * @brief Requests to update the content of the item at the specified path + * with the data from the given file. + * + * @param itemPath the path (in the archive) of the item to be updated. + * @param inFile the path to the file containing the new data for the item. + */ + void updateItem( const tstring& itemPath, const tstring& inFile ); + + /** + * @brief Requests to update the content of the item at the specified path + * with the data from the given buffer. + * + * @param itemPath the path (in the archive) of the item to be updated. + * @param inBuffer the buffer containing the new data for the item. + */ + void updateItem( const tstring& itemPath, const std::vector< byte_t >& inBuffer ); + + /** + * @brief Requests to update the content of the item at the specified path + * with the data from the given stream. + * + * @param itemPath the path (in the archive) of the item to be updated. + * @param inStream the stream of new data for the item. + */ + void updateItem( const tstring& itemPath, istream& inStream ); + + /** + * @brief Marks as deleted the item at the given index. + * + * @note By default, if the item is a folder, only its metadata is deleted, not the files within it. + * If instead the policy is set to DeletePolicy::RecurseDirs, + * then the items within the folder will also be deleted. + * + * @param index the index of the item to be deleted. + * @param policy the policy to be used when deleting items. + * + * @throws BitException if the index is invalid. + */ + void deleteItem( uint32_t index, DeletePolicy policy = DeletePolicy::ItemOnly ); + + /** + * @brief Marks as deleted the archive's item(s) with the specified path. + * + * @note By default, if the marked item is a folder, only its metadata will be deleted, not the files within it. + * To delete the folder contents as well, set the `policy` to `DeletePolicy::RecurseDirs`. + * + * @note The specified path must not begin with a path separator. + * + * @note A path with a trailing separator will _only_ be considered if + * the policy is DeletePolicy::RecurseDirs, and will only match folders; + * with DeletePolicy::ItemOnly, no item will match a path with a trailing separator. + * + * @note Generally, archives may contain multiple items with the same paths. + * If this is the case, all matching items will be marked as deleted according to the specified policy. + * + * @param itemPath the path (in the archive) of the item to be deleted. + * @param policy the policy to be used when deleting items. + * + * @throws BitException if the specified path is empty or invalid, or if no matching item could be found. + */ + void deleteItem( const tstring& itemPath, DeletePolicy policy = DeletePolicy::ItemOnly ); + + /** + * @brief Applies the requested changes (i.e., rename/update/delete operations) to the input archive. + */ + void applyChanges(); + + private: + EditedItems mEditedItems; + + auto findItem( const tstring& itemPath ) -> uint32_t; + + void checkIndex( uint32_t index ); + + auto itemProperty( InputIndex index, BitProperty property ) const -> BitPropVariant override; + + auto itemStream( InputIndex index, ISequentialInStream** inStream ) const -> HRESULT override; + + auto hasNewData( uint32_t index ) const noexcept -> bool override; + + auto hasNewProperties( uint32_t index ) const noexcept -> bool override; + + void markItemAsDeleted( uint32_t index ); +}; + +} // namespace bit7z + +#endif //BITARCHIVEEDITOR_HPP diff --git a/Minecraft.Client/Common/libs/bit7z/include/bitarchiveitem.hpp b/Minecraft.Client/Common/libs/bit7z/include/bitarchiveitem.hpp new file mode 100644 index 000000000..1300d1a40 --- /dev/null +++ b/Minecraft.Client/Common/libs/bit7z/include/bitarchiveitem.hpp @@ -0,0 +1,112 @@ +/* + * bit7z - A C++ static library to interface with the 7-zip shared libraries. + * Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef BITARCHIVEITEM_HPP +#define BITARCHIVEITEM_HPP + +#include "bitgenericitem.hpp" + +namespace bit7z { + +/** + * The BitArchiveItem class represents a generic item inside an archive. + */ +class BitArchiveItem : public BitGenericItem { + public: + /** + * @return the index of the item in the archive. + */ + BIT7Z_NODISCARD auto index() const noexcept -> uint32_t; + + /** + * @return true if and only if the item is a directory (i.e., it has the property BitProperty::IsDir). + */ + BIT7Z_NODISCARD auto isDir() const -> bool override; + + /** + * @return true if and only if the item is a symbolic link (either has a non-empty BitProperty::SymLink, + * or it has POSIX/Win32 symbolic link file attributes). + */ + BIT7Z_NODISCARD auto isSymLink() const -> bool override; + + /** + * @return the item's name; if not available, it tries to get it from the element's path or, + * if not possible, it returns an empty string. + */ + BIT7Z_NODISCARD auto name() const -> tstring override; + + /** + * @return the extension of the item, if available or if it can be inferred from the name; + * otherwise it returns an empty string (e.g., when the item is a folder). + */ + BIT7Z_NODISCARD auto extension() const -> tstring; + + /** + * @return the path of the item in the archive, if available or inferable from the name, or an empty string + * otherwise. + */ + BIT7Z_NODISCARD auto path() const -> tstring override; + + /** + * @note Same as path(), but returning a native string (i.e., std::wstring on Windows, std::string elsewhere). + * + * @return the path of the item in the archive, if available or inferable from the name, or an empty string + * otherwise. + */ + BIT7Z_NODISCARD auto nativePath() const -> native_string; + + /** + * @return the uncompressed size of the item. + */ + BIT7Z_NODISCARD auto size() const -> uint64_t override; + + /** + * @return the item creation time. + */ + BIT7Z_NODISCARD auto creationTime() const -> time_type; + + /** + * @return the item last access time. + */ + BIT7Z_NODISCARD auto lastAccessTime() const -> time_type; + + /** + * @return the item last write time. + */ + BIT7Z_NODISCARD auto lastWriteTime() const -> time_type; + + /** + * @return the item attributes. + */ + BIT7Z_NODISCARD auto attributes() const -> uint32_t override; + + /** + * @return the compressed size of the item. + */ + BIT7Z_NODISCARD auto packSize() const -> uint64_t; + + /** + * @return the CRC value of the item. + */ + BIT7Z_NODISCARD auto crc() const -> uint32_t; + + /** + * @return true if and only if the item is encrypted. + */ + BIT7Z_NODISCARD auto isEncrypted() const -> bool; + + protected: + uint32_t mItemIndex; //Note: it is not const since the subclass BitArchiveItemOffset can increment it! + + explicit BitArchiveItem( uint32_t itemIndex ) noexcept; +}; + +} // namespace bit7z + +#endif // BITARCHIVEITEM_HPP diff --git a/Minecraft.Client/Common/libs/bit7z/include/bitarchiveiteminfo.hpp b/Minecraft.Client/Common/libs/bit7z/include/bitarchiveiteminfo.hpp new file mode 100644 index 000000000..dafbc6ce8 --- /dev/null +++ b/Minecraft.Client/Common/libs/bit7z/include/bitarchiveiteminfo.hpp @@ -0,0 +1,54 @@ +/* + * bit7z - A C++ static library to interface with the 7-zip shared libraries. + * Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef BITARCHIVEITEMINFO_HPP +#define BITARCHIVEITEMINFO_HPP + +#include + +#include "bitarchiveitem.hpp" + +namespace bit7z { + +using std::wstring; +using std::map; + +/** + * @brief The BitArchiveItemInfo class represents an archived item and that stores all its properties for later use. + */ +class BitArchiveItemInfo final : public BitArchiveItem { + public: + /** + * @brief Gets the specified item property. + * + * @param property the property to be retrieved. + * + * @return the value of the item property, if available, or an empty BitPropVariant. + */ + BIT7Z_NODISCARD auto itemProperty( BitProperty property ) const -> BitPropVariant override; + + /** + * @return a map of all the available (i.e., non-empty) item properties and their respective values. + */ + BIT7Z_NODISCARD auto itemProperties() const -> map< BitProperty, BitPropVariant >; + + private: + map< BitProperty, BitPropVariant > mItemProperties; + + /* BitArchiveItem objects can be created and updated only by BitArchiveReader */ + explicit BitArchiveItemInfo( uint32_t itemIndex ); + + void setProperty( BitProperty property, const BitPropVariant& value ); + + friend class BitArchiveReader; +}; + +} // namespace bit7z + +#endif // BITARCHIVEITEMINFO_HPP diff --git a/Minecraft.Client/Common/libs/bit7z/include/bitarchiveitemoffset.hpp b/Minecraft.Client/Common/libs/bit7z/include/bitarchiveitemoffset.hpp new file mode 100644 index 000000000..a7983d8d1 --- /dev/null +++ b/Minecraft.Client/Common/libs/bit7z/include/bitarchiveitemoffset.hpp @@ -0,0 +1,53 @@ +/* + * bit7z - A C++ static library to interface with the 7-zip shared libraries. + * Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef BITARCHIVEITEMOFFSET_HPP +#define BITARCHIVEITEMOFFSET_HPP + +#include "bitarchiveitem.hpp" + +namespace bit7z { + +class BitInputArchive; + +/** + * @brief The BitArchiveItemOffset class represents an archived item but doesn't store its properties. + */ +class BitArchiveItemOffset final : public BitArchiveItem { + public: + auto operator++() noexcept -> BitArchiveItemOffset&; + + auto operator++( int ) noexcept -> BitArchiveItemOffset; // NOLINT(cert-dcl21-cpp) + + auto operator==( const BitArchiveItemOffset& other ) const noexcept -> bool; + + auto operator!=( const BitArchiveItemOffset& other ) const noexcept -> bool; + + /** + * @brief Gets the specified item property. + * + * @param property the property to be retrieved. + * + * @return the value of the item property, if available, or an empty BitPropVariant. + */ + BIT7Z_NODISCARD auto itemProperty( BitProperty property ) const -> BitPropVariant override; + + private: + /* Note: a pointer, instead of a reference, allows this class, and hence BitInputArchive::ConstIterator, + * to be CopyConstructible so that stl algorithms can be used with ConstIterator! */ + const BitInputArchive* mArc; + + BitArchiveItemOffset( uint32_t itemIndex, const BitInputArchive& inputArchive ) noexcept; + + friend class BitInputArchive; +}; + +} // namespace bit7z + +#endif // BITARCHIVEITEMOFFSET_HPP diff --git a/Minecraft.Client/Common/libs/bit7z/include/bitarchivereader.hpp b/Minecraft.Client/Common/libs/bit7z/include/bitarchivereader.hpp new file mode 100644 index 000000000..f0b4bdcc8 --- /dev/null +++ b/Minecraft.Client/Common/libs/bit7z/include/bitarchivereader.hpp @@ -0,0 +1,277 @@ +/* + * bit7z - A C++ static library to interface with the 7-zip shared libraries. + * Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef BITARCHIVEREADER_HPP +#define BITARCHIVEREADER_HPP + +#include "bitabstractarchiveopener.hpp" +#include "bitarchiveiteminfo.hpp" +#include "bitexception.hpp" +#include "bitinputarchive.hpp" + +struct IInArchive; +struct IOutArchive; +struct IArchiveExtractCallback; + +namespace bit7z { + +/** + * @brief The BitArchiveReader class allows reading metadata of archives, as well as extracting them. + */ +class BitArchiveReader final : public BitAbstractArchiveOpener, public BitInputArchive { + public: + /** + * @brief Constructs a BitArchiveReader object, opening the input file archive. + * + * @note When bit7z is compiled using the `BIT7Z_AUTO_FORMAT` option, the format + * argument has the default value BitFormat::Auto (automatic format detection of the input archive). + * On the contrary, when `BIT7Z_AUTO_FORMAT` is not defined (i.e., no auto format detection available), + * the format argument must be specified. + * + * @param lib the 7z library used. + * @param inArchive the path to the archive to be read. + * @param archiveStart whether to search for the archive's start throughout the entire file + * or only at the beginning. + * @param format the format of the input archive. + * @param password (optional) the password needed for opening the input archive. + */ + BitArchiveReader( const Bit7zLibrary& lib, + const tstring& inArchive, + ArchiveStartOffset archiveStart, + const BitInFormat& format BIT7Z_DEFAULT_FORMAT, + const tstring& password = {} ); + + /** + * @brief Constructs a BitArchiveReader object, opening the input file archive. + * + * @note When bit7z is compiled using the `BIT7Z_AUTO_FORMAT` option, the format + * argument has the default value BitFormat::Auto (automatic format detection of the input archive). + * On the contrary, when `BIT7Z_AUTO_FORMAT` is not defined (i.e., no auto format detection available), + * the format argument must be specified. + * + * @param lib the 7z library used. + * @param inArchive the path to the archive to be read. + * @param format the format of the input archive. + * @param password (optional) the password needed for opening the input archive. + */ + BitArchiveReader( const Bit7zLibrary& lib, + const tstring& inArchive, + const BitInFormat& format BIT7Z_DEFAULT_FORMAT, + const tstring& password = {} ); + + /** + * @brief Constructs a BitArchiveReader object, opening the archive in the input buffer. + * + * @note When bit7z is compiled using the `BIT7Z_AUTO_FORMAT` option, the format + * argument has the default value BitFormat::Auto (automatic format detection of the input archive). + * On the contrary, when `BIT7Z_AUTO_FORMAT` is not defined (i.e., no auto format detection available), + * the format argument must be specified. + * + * @param lib the 7z library used. + * @param inArchive the input buffer containing the archive to be read. + * @param archiveStart whether to search for the archive's start throughout the entire file + * or only at the beginning. + * @param format the format of the input archive. + * @param password (optional) the password needed for opening the input archive. + */ + BitArchiveReader( const Bit7zLibrary& lib, + const buffer_t& inArchive, + ArchiveStartOffset archiveStart, + const BitInFormat& format BIT7Z_DEFAULT_FORMAT, + const tstring& password = {} ); + + /** + * @brief Constructs a BitArchiveReader object, opening the archive in the input buffer. + * + * @note When bit7z is compiled using the `BIT7Z_AUTO_FORMAT` option, the format + * argument has the default value BitFormat::Auto (automatic format detection of the input archive). + * On the contrary, when `BIT7Z_AUTO_FORMAT` is not defined (i.e., no auto format detection available), + * the format argument must be specified. + * + * @param lib the 7z library used. + * @param inArchive the input buffer containing the archive to be read. + * @param format the format of the input archive. + * @param password (optional) the password needed for opening the input archive. + */ + BitArchiveReader( const Bit7zLibrary& lib, + const std::vector< byte_t >& inArchive, + const BitInFormat& format BIT7Z_DEFAULT_FORMAT, + const tstring& password = {} ); + + /** + * @brief Constructs a BitArchiveReader object, opening the archive from the standard input stream. + * + * @note When bit7z is compiled using the `BIT7Z_AUTO_FORMAT` option, the format + * argument has the default value BitFormat::Auto (automatic format detection of the input archive). + * On the contrary, when `BIT7Z_AUTO_FORMAT` is not defined (i.e., no auto format detection available), + * the format argument must be specified. + * + * @param lib the 7z library used. + * @param inArchive the standard input stream of the archive to be read. + * @param archiveStart whether to search for the archive's start throughout the entire file + * or only at the beginning. + * @param format the format of the input archive. + * @param password (optional) the password needed for opening the input archive. + */ + BitArchiveReader( const Bit7zLibrary& lib, + std::istream& inArchive, + ArchiveStartOffset archiveStart, + const BitInFormat& format BIT7Z_DEFAULT_FORMAT, + const tstring& password = {} ); + + /** + * @brief Constructs a BitArchiveReader object, opening the archive from the standard input stream. + * + * @note When bit7z is compiled using the `BIT7Z_AUTO_FORMAT` option, the format + * argument has the default value BitFormat::Auto (automatic format detection of the input archive). + * On the contrary, when `BIT7Z_AUTO_FORMAT` is not defined (i.e., no auto format detection available), + * the format argument must be specified. + * + * @param lib the 7z library used. + * @param inArchive the standard input stream of the archive to be read. + * @param format the format of the input archive. + * @param password (optional) the password needed for opening the input archive. + */ + BitArchiveReader( const Bit7zLibrary& lib, + std::istream& inArchive, + const BitInFormat& format BIT7Z_DEFAULT_FORMAT, + const tstring& password = {} ); + + BitArchiveReader( const BitArchiveReader& ) = delete; + + BitArchiveReader( BitArchiveReader&& ) = delete; + + auto operator=( const BitArchiveReader& ) -> BitArchiveReader& = delete; + + auto operator=( BitArchiveReader&& ) -> BitArchiveReader& = delete; + + /** + * @brief BitArchiveReader destructor. + * + * @note It releases the input archive file. + */ + ~BitArchiveReader() override = default; + + /** + * @return a map of all the available (i.e., non-empty) archive properties and their respective values. + */ + BIT7Z_NODISCARD auto archiveProperties() const -> map< BitProperty, BitPropVariant >; + + /** + * @return a vector of all the archive items as BitArchiveItem objects. + */ + BIT7Z_NODISCARD auto items() const -> vector< BitArchiveItemInfo >; + + /** + * @return the number of folders contained in the archive. + */ + BIT7Z_NODISCARD auto foldersCount() const -> uint32_t; + + /** + * @return the number of files contained in the archive. + */ + BIT7Z_NODISCARD auto filesCount() const -> uint32_t; + + /** + * @return the total uncompressed size of the archive content. + */ + BIT7Z_NODISCARD auto size() const -> uint64_t; + + /** + * @return the total compressed size of the archive content. + */ + BIT7Z_NODISCARD auto packSize() const -> uint64_t; + + /** + * @return true if and only if the archive has at least one encrypted item. + */ + BIT7Z_NODISCARD auto hasEncryptedItems() const -> bool; + + /** + * @return true if and only if the archive has only encrypted items. + */ + BIT7Z_NODISCARD auto isEncrypted() const -> bool; + + /** + * @return the number of volumes composing the archive. + */ + BIT7Z_NODISCARD auto volumesCount() const -> uint32_t; + + /** + * @return true if and only if the archive is composed by multiple volumes. + */ + BIT7Z_NODISCARD auto isMultiVolume() const -> bool; + + /** + * @return true if and only if the archive was created using solid compression. + */ + BIT7Z_NODISCARD auto isSolid() const -> bool; + + /** + * Checks if the given archive is header-encrypted or not. + * + * @tparam T The input type of the archive (i.e., file path, buffer, or standard stream). + * + * @param lib the 7z library used. + * @param inArchive the archive to be read. + * @param format the format of the input archive. + * + * @return true if and only if the archive has at least one encrypted item. + */ + template< typename T > + BIT7Z_NODISCARD + static auto isHeaderEncrypted( const Bit7zLibrary& lib, + T&& inArchive, + const BitInFormat& format BIT7Z_DEFAULT_FORMAT ) -> bool { + try { + const BitArchiveReader reader{ lib, std::forward< T >( inArchive ), format }; + return false; + } catch ( const BitException& ex ) { + return isOpenEncryptedError( ex.code() ); + } + } + + /** + * Checks if the given archive contains only encrypted items. + * + * @note A header-encrypted archive is also encrypted, but the contrary is not generally true. + * + * @note An archive might contain both plain and encrypted files; in this case, this function will + * return false. + * + * @tparam T The input type of the archive (i.e., file path, buffer, or standard stream). + * + * @param lib the 7z library used. + * @param inArchive the archive to be read. + * @param format the format of the input archive. + * + * @return true if and only if the archive has only encrypted items. + */ + template< typename T > + BIT7Z_NODISCARD + static auto isEncrypted( const Bit7zLibrary& lib, + T&& inArchive, + const BitInFormat& format BIT7Z_DEFAULT_FORMAT ) -> bool { + try { + const BitArchiveReader reader{ lib, std::forward< T >( inArchive ), format }; + return reader.isEncrypted(); + } catch ( const BitException& ex ) { + return isOpenEncryptedError( ex.code() ); + } + } + + private: + static auto isOpenEncryptedError( std::error_code error ) -> bool; +}; + +BIT7Z_DEPRECATED_TYPEDEF( BitArchiveInfo, BitArchiveReader, "Since v4.0; please use BitArchiveReader." ); + +} // namespace bit7z + +#endif // BITARCHIVEREADER_HPP diff --git a/Minecraft.Client/Common/libs/bit7z/include/bitarchivewriter.hpp b/Minecraft.Client/Common/libs/bit7z/include/bitarchivewriter.hpp new file mode 100644 index 000000000..080b62f68 --- /dev/null +++ b/Minecraft.Client/Common/libs/bit7z/include/bitarchivewriter.hpp @@ -0,0 +1,120 @@ +/* + * bit7z - A C++ static library to interface with the 7-zip shared libraries. + * Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef BITARCHIVEWRITER_HPP +#define BITARCHIVEWRITER_HPP + +#include "bitoutputarchive.hpp" + +namespace bit7z { + +/** + * @brief The BitArchiveWriter class allows creating new archives or updating old ones with new items. + */ +class BitArchiveWriter : public BitAbstractArchiveCreator, public BitOutputArchive { + public: + /** + * @brief Constructs an empty BitArchiveWriter object that can write archives of the specified format. + * + * @param lib the 7z library to use. + * @param format the output archive format. + */ + BitArchiveWriter( const Bit7zLibrary& lib, const BitInOutFormat& format ); + + /** + * @brief Constructs a BitArchiveWriter object, reading the given archive file path. + * + * @param lib the 7z library to use. + * @param inArchive the path to an input archive file. + * @param startOffset whether to search for the archive's start throughout the entire file + * or only at the beginning. + * @param format the input/output archive format. + * @param password (optional) the password needed to read the input archive. + */ + BitArchiveWriter( const Bit7zLibrary& lib, + const tstring& inArchive, + ArchiveStartOffset startOffset, + const BitInOutFormat& format, + const tstring& password = {} ); + + /** + * @brief Constructs a BitArchiveWriter object, reading the given archive file path. + * + * @param lib the 7z library to use. + * @param inArchive the path to an input archive file. + * @param format the input/output archive format. + * @param password (optional) the password needed to read the input archive. + */ + BitArchiveWriter( const Bit7zLibrary& lib, + const tstring& inArchive, + const BitInOutFormat& format, + const tstring& password = {} ); + + /** + * @brief Constructs a BitArchiveWriter object, reading the archive in the given buffer. + * + * @param lib the 7z library to use. + * @param inArchive the buffer containing the input archive. + * @param startOffset whether to search for the archive's start throughout the entire file + * or only at the beginning. + * @param format the input/output archive format. + * @param password (optional) the password needed to read the input archive. + */ + BitArchiveWriter( const Bit7zLibrary& lib, + const buffer_t& inArchive, + ArchiveStartOffset startOffset, + const BitInOutFormat& format, + const tstring& password = {} ); + + /** + * @brief Constructs a BitArchiveWriter object, reading the archive in the given buffer. + * + * @param lib the 7z library to use. + * @param inArchive the buffer containing the input archive. + * @param format the input/output archive format. + * @param password (optional) the password needed to read the input archive. + */ + BitArchiveWriter( const Bit7zLibrary& lib, + const std::vector< byte_t >& inArchive, + const BitInOutFormat& format, + const tstring& password = {} ); + + /** + * @brief Constructs a BitArchiveWriter object, reading the archive from the given standard input stream. + * + * @param lib the 7z library to use. + * @param inArchive the standard stream of the input archive. + * @param startOffset whether to search for the archive's start throughout the entire file + * or only at the beginning. + * @param format the input/output archive format. + * @param password (optional) the password needed to read the input archive. + */ + BitArchiveWriter( const Bit7zLibrary& lib, + std::istream& inArchive, + ArchiveStartOffset startOffset, + const BitInOutFormat& format, + const tstring& password = {} ); + + /** + * @brief Constructs a BitArchiveWriter object, reading the archive from the given standard input stream. + * + * @param lib the 7z library to use. + * @param inArchive the standard stream of the input archive. + * @param format the input/output archive format. + * @param password (optional) the password needed to read the input archive. + */ + BitArchiveWriter( const Bit7zLibrary& lib, + std::istream& inArchive, + const BitInOutFormat& format, + const tstring& password = {} ); +}; + +} // namespace bit7z + +#endif //BITARCHIVEWRITER_HPP diff --git a/Minecraft.Client/Common/libs/bit7z/include/bitcompressionlevel.hpp b/Minecraft.Client/Common/libs/bit7z/include/bitcompressionlevel.hpp new file mode 100644 index 000000000..b742f9b11 --- /dev/null +++ b/Minecraft.Client/Common/libs/bit7z/include/bitcompressionlevel.hpp @@ -0,0 +1,30 @@ +/* + * bit7z - A C++ static library to interface with the 7-zip shared libraries. + * Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef BITCOMPRESSIONLEVEL_HPP +#define BITCOMPRESSIONLEVEL_HPP + +namespace bit7z { + +/** + * @brief The BitCompressionLevel enum represents the compression level used by 7z when creating archives. + * @note It uses the same values used by [7-zip](https://sevenzip.osdn.jp/chm/cmdline/switches/method.htm#ZipX). + */ +enum struct BitCompressionLevel { + None = 0, ///< Copy mode (no compression) + Fastest = 1, ///< Fastest compressing + Fast = 3, ///< Fast compressing + Normal = 5, ///< Normal compressing + Max = 7, ///< Maximum compressing + Ultra = 9 ///< Ultra compressing +}; + +} // namespace bit7z + +#endif // BITCOMPRESSIONLEVEL_HPP diff --git a/Minecraft.Client/Common/libs/bit7z/include/bitcompressionmethod.hpp b/Minecraft.Client/Common/libs/bit7z/include/bitcompressionmethod.hpp new file mode 100644 index 000000000..3f3b6f826 --- /dev/null +++ b/Minecraft.Client/Common/libs/bit7z/include/bitcompressionmethod.hpp @@ -0,0 +1,30 @@ +/* + * bit7z - A C++ static library to interface with the 7-zip shared libraries. + * Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef BITCOMPRESSIONMETHOD_HPP +#define BITCOMPRESSIONMETHOD_HPP + +namespace bit7z { + +/** + * @brief The BitCompressionMethod enum represents the compression methods used by 7z when creating archives. + */ +enum struct BitCompressionMethod { + Copy, + Deflate, + Deflate64, + BZip2, + Lzma, + Lzma2, + Ppmd +}; + +} // namespace bit7z + +#endif // BITCOMPRESSIONMETHOD_HPP diff --git a/Minecraft.Client/Common/libs/bit7z/include/bitcompressor.hpp b/Minecraft.Client/Common/libs/bit7z/include/bitcompressor.hpp new file mode 100644 index 000000000..7ce8f6109 --- /dev/null +++ b/Minecraft.Client/Common/libs/bit7z/include/bitcompressor.hpp @@ -0,0 +1,116 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + +/* + * bit7z - A C++ static library to interface with the 7-zip shared libraries. + * Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef BITCOMPRESSOR_HPP +#define BITCOMPRESSOR_HPP + +#include + +#include "bitoutputarchive.hpp" + +namespace bit7z { + +using std::vector; + +namespace filesystem { // NOLINT(modernize-concat-nested-namespaces) +namespace fsutil { +auto stem( const tstring& path ) -> tstring; +} // namespace fsutil +} // namespace filesystem + +using namespace filesystem; + +#ifdef __cpp_if_constexpr +#define BIT7Z_IF_CONSTEXPR if constexpr +#else +#define BIT7Z_IF_CONSTEXPR if +#endif + +/** + * @brief The BitCompressor template class allows compressing files into archives. + * + * It let decide various properties of the produced archive file, such as the password + * protection and the compression level desired. + */ +template< typename Input > +class BitCompressor : public BitAbstractArchiveCreator { + public: + /** + * @brief Constructs a BitCompressor object. + * + * The Bit7zLibrary parameter is needed to have access to the functionalities + * of the 7z DLLs. On the contrary, the BitInOutFormat is required to know the + * format of the output archive. + * + * @param lib the 7z library to use. + * @param format the output archive format. + */ + BitCompressor( Bit7zLibrary const& lib, BitInOutFormat const& format ) + : BitAbstractArchiveCreator( lib, format ) {} + + /** + * @brief Compresses a single file. + * + * @param inFile the file to be compressed. + * @param outFile the path (relative or absolute) to the output archive file. + * @param inputName (optional) the name to give to the compressed file inside the output archive. + */ + void compressFile( Input inFile, + const tstring& outFile, + const tstring& inputName = {} ) const { + /* Note: if inFile is a filesystem path (i.e., its type is const tstring&), we can deduce the archived + * item filename using the original filename. Otherwise, if the user didn't specify the input file name, + * we use the filename (without extension) of the output file path. */ + tstring name; + BIT7Z_IF_CONSTEXPR( !std::is_same< Input, const tstring& >::value ) { + name = inputName.empty() ? fsutil::stem( outFile ) : inputName; + } + + BitOutputArchive outputArchive{ *this, outFile }; + outputArchive.addFile( inFile, name ); + outputArchive.compressTo( outFile ); + } + + /** + * @brief Compresses the input file to the output buffer. + * + * @param inFile the file to be compressed. + * @param outBuffer the buffer going to contain the output archive. + * @param inputName (optional) the name to give to the compressed file inside the output archive. + */ + void compressFile( Input inFile, + vector< byte_t >& outBuffer, + const tstring& inputName = {} ) const { + BitOutputArchive outputArchive{ *this, outBuffer }; + outputArchive.addFile( inFile, inputName ); + outputArchive.compressTo( outBuffer ); + } + + /** + * @brief Compresses the input file to the output stream. + * + * @param inFile the file to be compressed. + * @param outStream the output stream. + * @param inputName (optional) the name to give to the compressed file inside the output archive. + */ + void compressFile( Input inFile, + ostream& outStream, + const tstring& inputName = {} ) const { + BitOutputArchive outputArchive{ *this }; + outputArchive.addFile( inFile, inputName ); + outputArchive.compressTo( outStream ); + } +}; + +} // namespace bit7z + +#endif //BITCOMPRESSOR_HPP diff --git a/Minecraft.Client/Common/libs/bit7z/include/bitdefines.hpp b/Minecraft.Client/Common/libs/bit7z/include/bitdefines.hpp new file mode 100644 index 000000000..550885c39 --- /dev/null +++ b/Minecraft.Client/Common/libs/bit7z/include/bitdefines.hpp @@ -0,0 +1,121 @@ +/* + * bit7z - A C++ static library to interface with the 7-zip shared libraries. + * Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef BITDEFINES_HPP +#define BITDEFINES_HPP + +/* Uncomment the following macros if you don't want to define them yourself in your project files, + * and you can't enable them via CMake. */ +//#define BIT7Z_AUTO_FORMAT +//#define BIT7Z_AUTO_PREFIX_LONG_PATHS +//#define BIT7Z_DISABLE_USE_STD_FILESYSTEM +//#define BIT7Z_REGEX_MATCHING +//#define BIT7Z_USE_STD_BYTE +//#define BIT7Z_USE_NATIVE_STRING + +#if ( defined( _MSVC_LANG ) && _MSVC_LANG >= 201703L ) || ( defined( __cplusplus ) && __cplusplus >= 201703L ) +# define BIT7Z_CPP_STANDARD 17 +#elif ( defined( _MSVC_LANG ) && _MSVC_LANG >= 201402L ) || ( defined( __cplusplus ) && __cplusplus >= 201402L ) +# define BIT7Z_CPP_STANDARD 14 +#else +# define BIT7Z_CPP_STANDARD 11 +#endif + +#ifndef BIT7Z_DISABLE_USE_STD_FILESYSTEM +# if defined( __cpp_lib_filesystem ) +# define BIT7Z_USE_STANDARD_FILESYSTEM +# elif BIT7Z_CPP_STANDARD >= 17 && defined( __has_include ) +# if __has_include( ) +# define BIT7Z_USE_STANDARD_FILESYSTEM +# endif +# endif +#endif + +/* Macro defines for [[nodiscard]] and [[maybe_unused]] attributes. */ +#if defined( __has_cpp_attribute ) +# if __has_cpp_attribute( nodiscard ) +# define BIT7Z_NODISCARD [[nodiscard]] +# endif +# if __has_cpp_attribute( maybe_unused ) +# define BIT7Z_MAYBE_UNUSED [[maybe_unused]] +# endif +# if __has_cpp_attribute( deprecated ) +# define BIT7Z_DEPRECATED [[deprecated]] +# define BIT7Z_DEPRECATED_MSG( msg ) [[deprecated( msg )]] +# endif +#endif + +/* The compiler doesn't support __has_cpp_attribute, but it is using the C++17 standard. */ +#if !defined( BIT7Z_NODISCARD ) && BIT7Z_CPP_STANDARD >= 17 +# define BIT7Z_NODISCARD [[nodiscard]] +#endif + +#if !defined( BIT7Z_MAYBE_UNUSED ) && BIT7Z_CPP_STANDARD >= 17 +# define BIT7Z_MAYBE_UNUSED [[maybe_unused]] +#endif + +#if !defined( BIT7Z_DEPRECATED ) && BIT7Z_CPP_STANDARD >= 14 +# define BIT7Z_DEPRECATED [[deprecated]] +# define BIT7Z_DEPRECATED_MSG( msg ) [[deprecated( msg )]] +#endif + +/* Compiler is using at most the C++14 standard, so we use the compiler-specific attributes/defines were possible. */ +#ifndef BIT7Z_NODISCARD +# if defined( __GNUC__ ) || defined(__clang__) +# define BIT7Z_NODISCARD __attribute__(( warn_unused_result )) +# elif defined( _Check_return_ ) // Old MSVC versions +# define BIT7Z_NODISCARD _Check_return_ +# else +# define BIT7Z_NODISCARD +# endif +#endif +#ifndef BIT7Z_MAYBE_UNUSED +# if defined( __GNUC__ ) || defined(__clang__) +# define BIT7Z_MAYBE_UNUSED __attribute__(( unused )) +# else +# define BIT7Z_MAYBE_UNUSED +# endif +#endif + +/* Compiler is using the C++11 standard, so we use the compiler-specific attributes were possible. + * Note: these macros are used in the public API, so we cannot assume that we are always using a C++14 compiler.*/ +#ifndef BIT7Z_DEPRECATED +# if defined( __GNUC__ ) || defined( __clang__ ) +# define BIT7Z_DEPRECATED __attribute__(( __deprecated__ )) +# define BIT7Z_DEPRECATED_MSG( msg ) __attribute__(( __deprecated__( msg ) )) +# elif defined( _MSC_VER ) +# define BIT7Z_DEPRECATED __declspec( deprecated ) +# define BIT7Z_DEPRECATED_MSG( msg ) __declspec( deprecated( msg ) ) +# else +# define BIT7Z_DEPRECATED +# define BIT7Z_DEPRECATED_MSG( msg ) +# endif +#endif + +#ifndef BIT7Z_DEPRECATED_ENUMERATOR +// Before v6.0, GCC didn't support deprecating single enumerators. +# if defined( __GNUC__ ) && !defined( __clang__ ) && __GNUC__ < 6 +# define BIT7Z_DEPRECATED_ENUMERATOR( deprecated_value, new_value, msg ) deprecated_value = new_value +# else +# define BIT7Z_DEPRECATED_ENUMERATOR( deprecated_value, new_value, msg ) \ + deprecated_value BIT7Z_DEPRECATED_MSG( msg ) = new_value +# endif +#endif + +#ifndef BIT7Z_DEPRECATED_TYPEDEF +# if defined( __GNUC__ ) && !defined( __clang__ ) && __GNUC__ < 7 +# define BIT7Z_DEPRECATED_TYPEDEF( alias_name, alias_value, msg ) \ + using alias_name BIT7Z_MAYBE_UNUSED __attribute__(( __deprecated__( msg ) )) = alias_value +# else +# define BIT7Z_DEPRECATED_TYPEDEF( alias_name, alias_value, msg ) \ + using alias_name BIT7Z_MAYBE_UNUSED BIT7Z_DEPRECATED_MSG( msg ) = alias_value +# endif +#endif + +#endif //BITDEFINES_HPP diff --git a/Minecraft.Client/Common/libs/bit7z/include/biterror.hpp b/Minecraft.Client/Common/libs/bit7z/include/biterror.hpp new file mode 100644 index 000000000..988a8c7d8 --- /dev/null +++ b/Minecraft.Client/Common/libs/bit7z/include/biterror.hpp @@ -0,0 +1,84 @@ +/* + * bit7z - A C++ static library to interface with the 7-zip shared libraries. + * Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef BITERROR_HPP +#define BITERROR_HPP + +#include + +#include "bitdefines.hpp" + +namespace bit7z { + +/** + * @brief The BitError enum struct values represent bit7z specific errors. + */ +enum struct BitError { + Fail = 1, + FilterNotSpecified, + FormatFeatureNotSupported, + IndicesNotSpecified, + InvalidArchivePath, + InvalidOutputBufferSize, + InvalidCompressionMethod, + InvalidDictionarySize, + InvalidIndex, + InvalidWordSize, + ItemIsAFolder, + ItemMarkedAsDeleted, + NoMatchingItems, + NoMatchingSignature, + NonEmptyOutputBuffer, + NullOutputBuffer, + RequestedWrongVariantType, + UnsupportedOperation, + UnsupportedVariantType, + WrongUpdateMode, + InvalidZipPassword, + InvalidDirectoryPath, + ItemPathOutsideOutputDirectory, + ItemHasAbsolutePath +}; + +auto make_error_code( BitError error ) -> std::error_code; + +/** + * @brief The BitFailureSource enum struct values represent bit7z error conditions. + * They can be used for performing queries on bit7z's `error_code`s, for the purpose + * of grouping, classification, or error translation. + */ +enum struct BitFailureSource { + CRCError, + DataAfterEnd, + DataError, + InvalidArchive, + InvalidArgument, + FormatDetectionError, + HeadersError, + NoSuchItem, + OperationNotSupported, + OperationNotPermitted, + UnavailableData, + UnexpectedEnd, + WrongPassword +}; + +auto make_error_condition( BitFailureSource failureSource ) -> std::error_condition; + +} // namespace bit7z + +namespace std { +template<> +struct BIT7Z_MAYBE_UNUSED is_error_code_enum< bit7z::BitError > : public true_type {}; + +template <> +struct BIT7Z_MAYBE_UNUSED is_error_condition_enum< bit7z::BitFailureSource > : public true_type {}; +} // namespace std + +#endif //BITERROR_HPP diff --git a/Minecraft.Client/Common/libs/bit7z/include/bitexception.hpp b/Minecraft.Client/Common/libs/bit7z/include/bitexception.hpp new file mode 100644 index 000000000..8a272c73a --- /dev/null +++ b/Minecraft.Client/Common/libs/bit7z/include/bitexception.hpp @@ -0,0 +1,103 @@ +/* + * bit7z - A C++ static library to interface with the 7-zip shared libraries. + * Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef BITEXCEPTION_HPP +#define BITEXCEPTION_HPP + +#include +#include + +#include "bitdefines.hpp" +#include "bittypes.hpp" +#include "bitwindows.hpp" + +namespace bit7z { + +using std::system_error; +using FailedFiles = std::vector< std::pair< tstring, std::error_code > >; + +auto make_hresult_code( HRESULT res ) noexcept -> std::error_code; + +auto last_error_code() noexcept -> std::error_code; + +/** + * @brief The BitException class represents a generic exception thrown from the bit7z classes. + */ +class BitException final : public system_error { + public: +#ifdef _WIN32 + using native_code_type = HRESULT; +#else + using native_code_type = int; +#endif + + /** + * @brief Constructs a BitException object with the given message, and the specific files that failed. + * + * @param message the message associated with the exception object. + * @param files the vector of files that failed, with the corresponding error codes. + * @param code the HRESULT code associated with the exception object. + */ + explicit BitException( const char* message, std::error_code code, FailedFiles&& files = {} ); + + /** + * @brief Constructs a BitException object with the given message, and the specific file that failed. + * + * @param message the message associated with the exception object. + * @param code the HRESULT code associated with the exception object. + * @param file the file that failed during the operation. + */ + BitException( const char* message, std::error_code code, tstring&& file ); + + /** + * @brief Constructs a BitException object with the given message, and the specific file that failed. + * + * @param message the message associated with the exception object. + * @param code the HRESULT code associated with the exception object. + * @param file the file that failed during the operation. + */ + BitException( const char* message, std::error_code code, const tstring& file ); + + /** + * @brief Constructs a BitException object with the given message. + * + * @param message the message associated with the exception object. + * @param code the HRESULT code associated with the exception object. + */ + explicit BitException( const std::string& message, std::error_code code ); + + /** + * @return the native error code (e.g., HRESULT on Windows, int elsewhere) + * corresponding to the exception's std::error_code. + */ + BIT7Z_NODISCARD auto nativeCode() const noexcept -> native_code_type; + + /** + * @return the HRESULT error code corresponding to the exception's std::error_code. + */ + BIT7Z_NODISCARD auto hresultCode() const noexcept -> HRESULT; + + /** + * @return the POSIX error code corresponding to the exception's std::error_code. + */ + BIT7Z_NODISCARD auto posixCode() const noexcept -> int; + + /** + * @return the vector of files that caused the exception to be thrown, along with the corresponding + * error codes. + */ + BIT7Z_NODISCARD auto failedFiles() const noexcept -> const FailedFiles&; + + private: + FailedFiles mFailedFiles; +}; + +} // namespace bit7z + +#endif // BITEXCEPTION_HPP diff --git a/Minecraft.Client/Common/libs/bit7z/include/bitextractor.hpp b/Minecraft.Client/Common/libs/bit7z/include/bitextractor.hpp new file mode 100644 index 000000000..e92e2515c --- /dev/null +++ b/Minecraft.Client/Common/libs/bit7z/include/bitextractor.hpp @@ -0,0 +1,284 @@ +/* + * bit7z - A C++ static library to interface with the 7-zip shared libraries. + * Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef BITEXTRACTOR_HPP +#define BITEXTRACTOR_HPP + +#include + +#include "bitabstractarchiveopener.hpp" +#include "biterror.hpp" +#include "bitexception.hpp" +#include "bitinputarchive.hpp" + +namespace bit7z { + +namespace filesystem { // NOLINT(modernize-concat-nested-namespaces) +namespace fsutil { +auto wildcard_match( const tstring& pattern, const tstring& str ) -> bool; +} // namespace fsutil +} // namespace filesystem + +/** + * @brief The BitExtractor template class allows extracting the content of archives from supported input types. + * + * @tparam Input the type of input archives that the generated extractor class supports. + */ +template< typename Input > +class BitExtractor final : public BitAbstractArchiveOpener { + public: + /** + * @brief Constructs a BitExtractor object. + * + * The Bit7zLibrary parameter is needed to have access to the functionalities + * of the 7z DLLs. On the contrary, the BitInFormat is required to know the + * format of the in_file archives. + * + * @note When bit7z is compiled using the BIT7Z_AUTO_FORMAT macro define, the format + * argument has the default value BitFormat::Auto (automatic format detection of the in_file archive). + * Otherwise, when BIT7Z_AUTO_FORMAT is not defined (i.e., no auto format detection available), + * the format argument must be specified. + * + * @param lib the 7z library to use. + * @param format the in_file archive format. + */ + explicit BitExtractor( const Bit7zLibrary& lib, const BitInFormat& format BIT7Z_DEFAULT_FORMAT ) + : BitAbstractArchiveOpener( lib, format ) {} + + /** + * @brief Extracts the given archive to the chosen directory. + * + * @param inArchive the input archive to be extracted. + * @param outDir the output directory where extracted files will be put. + */ + void extract( Input inArchive, const tstring& outDir = {} ) const { + BitInputArchive inputArchive( *this, inArchive ); + inputArchive.extractTo( outDir ); + } + + /** + * @brief Extracts a file from the given archive to the output buffer. + * + * @param inArchive the input archive to extract from. + * @param outBuffer the output buffer where the content of the extracted file will be put. + * @param index the index of the file to be extracted from the archive. + */ + void extract( Input inArchive, vector< byte_t >& outBuffer, uint32_t index = 0 ) const { + BitInputArchive inputArchive( *this, inArchive ); + inputArchive.extractTo( outBuffer, index ); + } + + /** + * @brief Extracts a file from the given archive to the output stream. + * + * @param inArchive the input archive to extract from. + * @param outStream the (binary) stream where the content of the extracted file will be put. + * @param index the index of the file to be extracted from the archive. + */ + void extract( Input inArchive, std::ostream& outStream, uint32_t index = 0 ) const { + BitInputArchive inputArchive( *this, inArchive ); + inputArchive.extractTo( outStream, index ); + } + + /** + * @brief Extracts the content of the given archive into a map of memory buffers, where the keys are + * the paths of the files (inside the archive), and the values are their decompressed contents. + * + * @param inArchive the input archive to be extracted. + * @param outMap the output map. + */ + void extract( Input inArchive, std::map< tstring, vector< byte_t > >& outMap ) const { + BitInputArchive inputArchive( *this, inArchive ); + inputArchive.extractTo( outMap ); + } + + /** + * @brief Extracts the files in the archive that match the given wildcard pattern to the chosen directory. + * + * @param inArchive the input archive to extract from. + * @param itemFilter the wildcard pattern used for matching the paths of files inside the archive. + * @param outDir the output directory where extracted files will be put. + * @param policy the filtering policy to be applied to the matched items. + */ + void extractMatching( Input inArchive, + const tstring& itemFilter, + const tstring& outDir = {}, + FilterPolicy policy = FilterPolicy::Include ) const { + using namespace filesystem; + + if ( itemFilter.empty() ) { + throw BitException( "Cannot extract items", make_error_code( BitError::FilterNotSpecified ) ); + } + + extractMatchingFilter( inArchive, outDir, policy, [ &itemFilter ]( const tstring& itemPath ) -> bool { + return fsutil::wildcard_match( itemFilter, itemPath ); + } ); + } + + /** + * @brief Extracts to the output buffer the first file in the archive matching the given wildcard pattern. + * + * @param inArchive the input archive to extract from. + * @param itemFilter the wildcard pattern used for matching the paths of files inside the archive. + * @param outBuffer the output buffer where to extract the file. + * @param policy the filtering policy to be applied to the matched items. + */ + void extractMatching( Input inArchive, + const tstring& itemFilter, + vector< byte_t >& outBuffer, + FilterPolicy policy = FilterPolicy::Include ) const { + using namespace filesystem; + + if ( itemFilter.empty() ) { + throw BitException( "Cannot extract items", make_error_code( BitError::FilterNotSpecified ) ); + } + + extractMatchingFilter( inArchive, outBuffer, policy, + [ &itemFilter ]( const tstring& itemPath ) -> bool { + return fsutil::wildcard_match( itemFilter, itemPath ); + } ); + } + + /** + * @brief Extracts the specified items from the given archive to the chosen directory. + * + * @param inArchive the input archive to extract from. + * @param indices the indices of the files in the archive that should be extracted. + * @param outDir the output directory where the extracted files will be placed. + */ + void extractItems( Input inArchive, + const std::vector< uint32_t >& indices, + const tstring& outDir = {} ) const { + if ( indices.empty() ) { + throw BitException( "Cannot extract items", make_error_code( BitError::IndicesNotSpecified ) ); + } + + BitInputArchive inputArchive( *this, inArchive ); + inputArchive.extractTo( outDir, indices ); + } + +#ifdef BIT7Z_REGEX_MATCHING + + /** + * @brief Extracts the files in the archive that match the given regex pattern to the chosen directory. + * + * @note Available only when compiling bit7z using the BIT7Z_REGEX_MATCHING preprocessor define. + * + * @param inArchive the input archive to extract from. + * @param regex the regex used for matching the paths of files inside the archive. + * @param outDir the output directory where extracted files will be put. + * @param policy the filtering policy to be applied to the matched items. + */ + void extractMatchingRegex( Input inArchive, + const tstring& regex, + const tstring& outDir = {}, + FilterPolicy policy = FilterPolicy::Include ) const { + if ( regex.empty() ) { + throw BitException( "Cannot extract items", make_error_code( BitError::FilterNotSpecified ) ); + } + + const tregex regexFilter( regex, tregex::ECMAScript | tregex::optimize ); + extractMatchingFilter( inArchive, outDir, policy, [ ®exFilter ]( const tstring& itemPath ) -> bool { + return std::regex_match( itemPath, regexFilter ); + } ); + } + + /** + * @brief Extracts the first file in the archive that matches the given regex pattern to the output buffer. + * + * @note Available only when compiling bit7z using the BIT7Z_REGEX_MATCHING preprocessor define. + * + * @param inArchive the input archive to extract from. + * @param regex the regex used for matching the paths of files inside the archive. + * @param outBuffer the output buffer where the extracted file will be put. + * @param policy the filtering policy to be applied to the matched items. + */ + void extractMatchingRegex( Input inArchive, + const tstring& regex, + vector< byte_t >& outBuffer, + FilterPolicy policy = FilterPolicy::Include ) const { + if ( regex.empty() ) { + throw BitException( "Cannot extract items", make_error_code( BitError::FilterNotSpecified ) ); + } + + const tregex regexFilter( regex, tregex::ECMAScript | tregex::optimize ); + return extractMatchingFilter( inArchive, outBuffer, policy, + [ ®exFilter ]( const tstring& itemPath ) -> bool { + return std::regex_match( itemPath, regexFilter ); + } ); + } + +#endif + + /** + * @brief Tests the given archive without extracting its content. + * + * If the archive is not valid, a BitException is thrown! + * + * @param inArchive the input archive to be tested. + */ + void test( Input inArchive ) const { + BitInputArchive inputArchive( *this, inArchive ); + inputArchive.test(); + } + + private: + void extractMatchingFilter( Input inArchive, + const tstring& outDir, + FilterPolicy policy, + const std::function< bool( const tstring& ) >& filter ) const { + BitInputArchive inputArchive( *this, inArchive ); + + vector< uint32_t > matchedIndices; + const bool shouldExtractMatchedItems = policy == FilterPolicy::Include; + // Searching for files inside the archive that match the given filter + for ( const auto& item : inputArchive ) { + const bool itemMatches = filter( item.path() ); + if ( itemMatches == shouldExtractMatchedItems ) { + /* The if-condition is equivalent to an exclusive XNOR (negated XOR) between + * itemMatches and shouldExtractMatchedItems. + * In other words, it is true only if the current item either: + * - matches the filter, and we must include any matching item; or + * - doesn't match the filter, and we must exclude those that match. */ + matchedIndices.push_back( item.index() ); + } + } + + if ( matchedIndices.empty() ) { + throw BitException( "Cannot extract items", make_error_code( BitError::NoMatchingItems ) ); + } + + inputArchive.extractTo( outDir, matchedIndices ); + } + + void extractMatchingFilter( Input inArchive, + vector< byte_t >& outBuffer, + FilterPolicy policy, + const std::function< bool( const tstring& ) >& filter ) const { + BitInputArchive inputArchive( *this, inArchive ); + + const bool shouldExtractMatchedItem = policy == FilterPolicy::Include; + // Searching for files inside the archive that match the given filter + for ( const auto& item : inputArchive ) { + const bool itemMatches = filter( item.path() ); + if ( itemMatches == shouldExtractMatchedItem ) { + /* The if-condition is equivalent to an exclusive NOR (negated XOR) between + * itemMatches and shouldExtractMatchedItem. */ + inputArchive.extractTo( outBuffer, item.index() ); + return; + } + } + + throw BitException( "Failed to extract items", make_error_code( BitError::NoMatchingItems ) ); + } +}; + +} // namespace bit7z + +#endif //BITEXTRACTOR_HPP diff --git a/Minecraft.Client/Common/libs/bit7z/include/bitfilecompressor.hpp b/Minecraft.Client/Common/libs/bit7z/include/bitfilecompressor.hpp new file mode 100644 index 000000000..dffcf9e03 --- /dev/null +++ b/Minecraft.Client/Common/libs/bit7z/include/bitfilecompressor.hpp @@ -0,0 +1,150 @@ +/* + * bit7z - A C++ static library to interface with the 7-zip shared libraries. + * Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef BITFILECOMPRESSOR_HPP +#define BITFILECOMPRESSOR_HPP + +#include +#include +#include + +#include "bitcompressor.hpp" + +namespace bit7z { + +using std::vector; +using std::map; +using std::ostream; + +using namespace filesystem; + +/** + * @brief The BitFileCompressor class allows compressing files and directories. + * The compressed archives can be saved to the filesystem, standard streams, or memory buffers. + * + * It let decide various properties of the produced archive, such as the password + * protection and the compression level desired. + */ +class BitFileCompressor final : public BitCompressor< const tstring& > { + public: + /** + * @brief Constructs a BitFileCompressor object. + * + * The Bit7zLibrary parameter is needed to have access to the functionalities + * of the 7z DLLs. On the contrary, the BitInOutFormat is required to know the + * format of the output archive. + * + * @param lib the 7z library used. + * @param format the output archive format. + */ + BitFileCompressor( const Bit7zLibrary& lib, const BitInOutFormat& format ); + + /* Compression from the file system to the file system. */ + + /** + * @brief Compresses the given files or directories. + * + * The items in the first argument must be the relative or absolute paths to files or + * directories existing on the filesystem. + * + * @param inPaths a vector of paths. + * @param outFile the path (relative or absolute) to the output archive file. + */ + void compress( const std::vector< tstring >& inPaths, const tstring& outFile ) const; + + /** + * @brief Compresses the given files or directories using the specified aliases. + * + * The items in the first argument must be the relative or absolute paths to files or + * directories existing on the filesystem. + * Each pair in the map must follow the following format: + * {"path to file in the filesystem", "alias path in the archive"}. + * + * @param inPaths a map of paths and corresponding aliases. + * @param outFile the path (relative or absolute) to the output archive file. + */ + void compress( const std::map< tstring, tstring >& inPaths, const tstring& outFile ) const; + + /** + * @brief Compresses a group of files. + * + * @note Any path to a directory or to a not-existing file will be ignored! + * + * @param inFiles the path (relative or absolute) to the input files. + * @param outFile the path (relative or absolute) to the output archive file. + */ + void compressFiles( const std::vector< tstring >& inFiles, const tstring& outFile ) const; + + /** + * @brief Compresses the files contained in a directory. + * + * @param inDir the path (relative or absolute) to the input directory. + * @param outFile the path (relative or absolute) to the output archive file. + * @param recursive (optional) if true, it searches files inside the sub-folders of inDir. + * @param filter (optional) the filter to use when searching files inside inDir. + */ + void compressFiles( const tstring& inDir, + const tstring& outFile, + bool recursive = true, + const tstring& filter = BIT7Z_STRING( "*" ) ) const; + + /** + * @brief Compresses an entire directory. + * + * @note This method is equivalent to compressFiles with filter set to L"". + * + * @param inDir the path (relative or absolute) to the input directory. + * @param outFile the path (relative or absolute) to the output archive file. + */ + void compressDirectory( const tstring& inDir, const tstring& outFile ) const; + + /** + * @brief Compresses the contents of a directory. + * + * @note Unlike compressFiles, this method includes also the metadata of the sub-folders. + * + * @param inDir the path (relative or absolute) to the input directory. + * @param outFile the path (relative or absolute) to the output archive file. + * @param recursive (optional) if true, it searches the contents inside the sub-folders of inDir. + * @param filter (optional) the filter to use when searching the contents inside inDir. + */ + void compressDirectoryContents( const tstring& inDir, + const tstring& outFile, + bool recursive = true, + const tstring& filter = BIT7Z_STRING( "*" ) ) const; + + /* Compression from the file system to standard streams. */ + + /** + * @brief Compresses the given files or directories. + * + * The items in the first argument must be the relative or absolute paths to files or + * directories existing on the filesystem. + * + * @param inPaths a vector of paths. + * @param outStream the standard ostream where the archive will be output. + */ + void compress( const std::vector< tstring >& inPaths, std::ostream& outStream ) const; + + /** + * @brief Compresses the given files or directories using the specified aliases. + * + * The items in the first argument must be the relative or absolute paths to files or + * directories existing on the filesystem. + * Each pair in the map must follow the following format: + * {"path to file in the filesystem", "alias path in the archive"}. + * + * @param inPaths a map of paths and corresponding aliases. + * @param outStream the standard ostream where to output the archive file. + */ + void compress( const std::map< tstring, tstring >& inPaths, std::ostream& outStream ) const; +}; + +} // namespace bit7z +#endif // BITFILECOMPRESSOR_HPP diff --git a/Minecraft.Client/Common/libs/bit7z/include/bitfileextractor.hpp b/Minecraft.Client/Common/libs/bit7z/include/bitfileextractor.hpp new file mode 100644 index 000000000..4352196f1 --- /dev/null +++ b/Minecraft.Client/Common/libs/bit7z/include/bitfileextractor.hpp @@ -0,0 +1,23 @@ +/* + * bit7z - A C++ static library to interface with the 7-zip shared libraries. + * Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef BITFILEEXTRACTOR_HPP +#define BITFILEEXTRACTOR_HPP + +#include "bitextractor.hpp" + +namespace bit7z { + +/** + * @brief The BitFileExtractor alias allows extracting archives on the filesystem. + */ +using BitFileExtractor BIT7Z_MAYBE_UNUSED = BitExtractor< const tstring& >; + +} // namespace bit7z +#endif // BITFILEEXTRACTOR_HPP diff --git a/Minecraft.Client/Common/libs/bit7z/include/bitformat.hpp b/Minecraft.Client/Common/libs/bit7z/include/bitformat.hpp new file mode 100644 index 000000000..d0d12b6a0 --- /dev/null +++ b/Minecraft.Client/Common/libs/bit7z/include/bitformat.hpp @@ -0,0 +1,254 @@ +/* + * bit7z - A C++ static library to interface with the 7-zip shared libraries. + * Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef BITFORMAT_HPP +#define BITFORMAT_HPP + +#include +#include + +#include "bitcompressionmethod.hpp" +#include "bitdefines.hpp" +#include "bittypes.hpp" + +namespace bit7z { + +/** + * @brief The FormatFeatures enum specifies the features supported by an archive file format. + */ +enum struct FormatFeatures : unsigned { + MultipleFiles = 1u << 0, ///< The format can compress/extract multiple files (2^0 = 0000001) + SolidArchive = 1u << 1, ///< The format supports solid archives (2^1 = 0000010) + CompressionLevel = 1u << 2, ///< The format is able to use different compression levels (2^2 = 0000100) + Encryption = 1u << 3, ///< The format supports archive encryption (2^3 = 0001000) + HeaderEncryption = 1u << 4, ///< The format can encrypt the file names (2^4 = 0010000) + MultipleMethods = 1u << 5 ///< The format can use different compression methods (2^6 = 0100000) +}; + +template< typename Enum > +using underlying_type_t = typename std::underlying_type< Enum >::type; + +template< typename Enum > +inline constexpr auto to_underlying( Enum enum_value ) noexcept -> underlying_type_t< Enum > { + return static_cast< underlying_type_t< Enum > >( enum_value ); +} + +inline constexpr auto operator|( FormatFeatures lhs, FormatFeatures rhs ) noexcept -> FormatFeatures { + return static_cast< FormatFeatures >( to_underlying( lhs ) | to_underlying( rhs ) ); +} + +using FormatFeaturesType = underlying_type_t< FormatFeatures >; + +inline constexpr auto operator&( FormatFeatures lhs, FormatFeatures rhs ) noexcept -> FormatFeaturesType { + return to_underlying( lhs ) & to_underlying( rhs ); +} + +/** + * @brief The BitInFormat class specifies an extractable archive format. + * + * @note Usually, the user of the library should not create new formats and, instead, + * use the ones provided by the BitFormat namespace. + */ +class BitInFormat { + public: + //non-copyable + BitInFormat( const BitInFormat& other ) = delete; + + auto operator=( const BitInFormat& other ) -> BitInFormat& = delete; + + //non-movable + BitInFormat( BitInFormat&& other ) = delete; + + auto operator=( BitInFormat&& other ) -> BitInFormat& = delete; + + ~BitInFormat() = default; + + /** + * @brief Constructs a BitInFormat object with the ID value used by the 7z SDK. + * @param value the value of the format in the 7z SDK. + */ + constexpr explicit BitInFormat( unsigned char value ) noexcept: mValue( value ) {} + + /** + * @return the value of the format in the 7z SDK. + */ + BIT7Z_NODISCARD auto value() const noexcept -> unsigned char; + + /** + * @param other the target object to compare to. + * @return a boolean value indicating whether this format is equal to the "other" or not. + */ + auto operator==( BitInFormat const& other ) const noexcept -> bool; + + /** + * @param other the target object to compare to. + * @return a boolean value indicating whether this format is different from the "other" or not. + */ + auto operator!=( BitInFormat const& other ) const noexcept -> bool; + + private: + unsigned char mValue; +}; + +/** + * @brief The BitInOutFormat class specifies a format available for creating new archives and extract old ones. + * + * @note Usually, the user of the library should not create new formats and, instead, + * use the ones provided by the BitFormat namespace. + */ +class BitInOutFormat final : public BitInFormat { + public: + /** + * @brief Constructs a BitInOutFormat object with an ID value, an extension and a set of supported features. + * + * @param value the value of the format in the 7z SDK. + * @param ext the default file extension of the archive format. + * @param defaultMethod the default method used for compressing the archive format. + * @param features the set of features supported by the archive format + */ + constexpr BitInOutFormat( unsigned char value, + const tchar* ext, + BitCompressionMethod defaultMethod, + FormatFeatures features ) noexcept + : BitInFormat( value ), mExtension( ext ), mDefaultMethod( defaultMethod ), mFeatures( features ) {} + + //non-copyable + BitInOutFormat( const BitInOutFormat& other ) = delete; + + auto operator=( const BitInOutFormat& other ) -> BitInOutFormat& = delete; + + //non-movable + BitInOutFormat( BitInOutFormat&& other ) = delete; + + auto operator=( BitInOutFormat&& other ) -> BitInOutFormat& = delete; + + ~BitInOutFormat() = default; + + /** + * @return the default file extension of the archive format. + */ + BIT7Z_NODISCARD + auto extension() const noexcept -> const tchar*; + + /** + * @return the bitset of the features supported by the format. + */ + BIT7Z_NODISCARD + auto features() const noexcept -> FormatFeatures; + + /** + * @brief Checks if the format has a specific feature (see FormatFeatures enum). + * + * @param feature feature to be checked. + * + * @return a boolean value indicating whether the format has the given feature. + */ + BIT7Z_NODISCARD + auto hasFeature( FormatFeatures feature ) const noexcept -> bool; + + /** + * @return the default method used for compressing the archive format. + */ + BIT7Z_NODISCARD + auto defaultMethod() const noexcept -> BitCompressionMethod; + + private: + const tchar* mExtension; + BitCompressionMethod mDefaultMethod; + FormatFeatures mFeatures; +}; + +/** + * @brief The namespace that contains a set of archive formats usable with bit7z classes. + */ +namespace BitFormat { +#ifdef BIT7Z_AUTO_FORMAT +/** + * @brief Automatic Format Detection (available only when compiling bit7z using the `BIT7Z_AUTO_FORMAT` option). + */ +extern const BitInFormat Auto; +#endif +extern const BitInFormat Rar; ///< RAR Archive Format +extern const BitInFormat Arj; ///< ARJ Archive Format +//NOLINTNEXTLINE(*-identifier-length) +extern const BitInFormat Z; ///< Z Archive Format +extern const BitInFormat Lzh; ///< LZH Archive Format +extern const BitInFormat Cab; ///< CAB Archive Format +extern const BitInFormat Nsis; ///< NSIS Archive Format +extern const BitInFormat Lzma; ///< LZMA Archive Format +extern const BitInFormat Lzma86; ///< LZMA86 Archive Format +extern const BitInFormat Ppmd; ///< PPMD Archive Format +extern const BitInFormat Zstd; ///< ZSTD Archive Format +extern const BitInFormat LVM; ///< LVM Archive Format +extern const BitInFormat AVB; ///< AVB Archive Format +extern const BitInFormat LP; ///< LP Archive Format +extern const BitInFormat Sparse; ///< Sparse Archive Format +extern const BitInFormat APFS; ///< APFS Archive Format +extern const BitInFormat Vhdx; ///< VHDX Archive Format +extern const BitInFormat COFF; ///< COFF Archive Format +extern const BitInFormat Ext; ///< EXT Archive Format +extern const BitInFormat VMDK; ///< VMDK Archive Format +extern const BitInFormat VDI; ///< VDI Archive Format +extern const BitInFormat QCow; ///< QCOW Archive Format +extern const BitInFormat GPT; ///< GPT Archive Format +extern const BitInFormat Rar5; ///< RAR5 Archive Format +extern const BitInFormat IHex; ///< IHEX Archive Format +extern const BitInFormat Hxs; ///< HXS Archive Format +//NOLINTNEXTLINE(*-identifier-length) +extern const BitInFormat TE; ///< TE Archive Format +extern const BitInFormat UEFIc; ///< UEFIc Archive Format +extern const BitInFormat UEFIs; ///< UEFIs Archive Format +extern const BitInFormat SquashFS; ///< SquashFS Archive Format +extern const BitInFormat CramFS; ///< CramFS Archive Format +extern const BitInFormat APM; ///< APM Archive Format +extern const BitInFormat Mslz; ///< MSLZ Archive Format +extern const BitInFormat Flv; ///< FLV Archive Format +extern const BitInFormat Swf; ///< SWF Archive Format +extern const BitInFormat Swfc; ///< SWFC Archive Format +extern const BitInFormat Ntfs; ///< NTFS Archive Format +extern const BitInFormat Fat; ///< FAT Archive Format +extern const BitInFormat Mbr; ///< MBR Archive Format +extern const BitInFormat Vhd; ///< VHD Archive Format +//NOLINTNEXTLINE(*-identifier-length) +extern const BitInFormat Pe; ///< PE Archive Format +extern const BitInFormat Elf; ///< ELF Archive Format +extern const BitInFormat Macho; ///< MACHO Archive Format +extern const BitInFormat Udf; ///< UDF Archive Format +extern const BitInFormat Xar; ///< XAR Archive Format +extern const BitInFormat Mub; ///< MUB Archive Format +extern const BitInFormat Hfs; ///< HFS Archive Format +extern const BitInFormat Dmg; ///< DMG Archive Format +extern const BitInFormat Compound; ///< COMPOUND Archive Format +extern const BitInFormat Iso; ///< ISO Archive Format +extern const BitInFormat Chm; ///< CHM Archive Format +extern const BitInFormat Split; ///< SPLIT Archive Format +extern const BitInFormat Rpm; ///< RPM Archive Format +extern const BitInFormat Deb; ///< DEB Archive Format +extern const BitInFormat Cpio; ///< CPIO Archive Format + +extern const BitInOutFormat Zip; ///< ZIP Archive Format +extern const BitInOutFormat BZip2; ///< BZIP2 Archive Format +extern const BitInOutFormat SevenZip; ///< 7Z Archive Format +//NOLINTNEXTLINE(*-identifier-length) +extern const BitInOutFormat Xz; ///< XZ Archive Format +extern const BitInOutFormat Wim; ///< WIM Archive Format +extern const BitInOutFormat Tar; ///< TAR Archive Format +extern const BitInOutFormat GZip; ///< GZIP Archive Format +} // namespace BitFormat + + +#ifdef BIT7Z_AUTO_FORMAT +#define BIT7Z_DEFAULT_FORMAT = BitFormat::Auto +#else +#define BIT7Z_DEFAULT_FORMAT +#endif + +} // namespace bit7z + +#endif // BITFORMAT_HPP diff --git a/Minecraft.Client/Common/libs/bit7z/include/bitfs.hpp b/Minecraft.Client/Common/libs/bit7z/include/bitfs.hpp new file mode 100644 index 000000000..7dcba6743 --- /dev/null +++ b/Minecraft.Client/Common/libs/bit7z/include/bitfs.hpp @@ -0,0 +1,43 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + +/* + * bit7z - A C++ static library to interface with the 7-zip shared libraries. + * Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef BITFS_HPP +#define BITFS_HPP + +/* Header for forward declaring fs namespace. */ + +#include "bitdefines.hpp" /* For BIT7Z_USE_STANDARD_FILESYSTEM */ + +#ifdef BIT7Z_USE_STANDARD_FILESYSTEM +#include +#else +/* Notes: we use this forward declaration to avoid including private headers (e.g. fs.hpp). + * Since some public API headers include bitgenericitem.hpp (e.g. "bitoutputarchive.hpp"), + * including private headers here would result in the "leaking" out of these latter in the public API.*/ +namespace ghc { +namespace filesystem { +class path; +} // namespace filesystem +} // namespace ghc +#endif + +namespace bit7z { +namespace fs { +#ifdef BIT7Z_USE_STANDARD_FILESYSTEM +using namespace std::filesystem; +#else +using namespace ghc::filesystem; +#endif +} // namespace fs +} // namespace bit7z + +#endif //BITFS_HPP diff --git a/Minecraft.Client/Common/libs/bit7z/include/bitgenericitem.hpp b/Minecraft.Client/Common/libs/bit7z/include/bitgenericitem.hpp new file mode 100644 index 000000000..cbd52509e --- /dev/null +++ b/Minecraft.Client/Common/libs/bit7z/include/bitgenericitem.hpp @@ -0,0 +1,66 @@ +/* + * bit7z - A C++ static library to interface with the 7-zip shared libraries. + * Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef BITGENERICITEM_HPP +#define BITGENERICITEM_HPP + +#include "bitpropvariant.hpp" + +namespace bit7z { + +/** + * @brief The BitGenericItem interface class represents a generic item (either inside or outside an archive). + */ +class BitGenericItem { + public: + /** + * @return true if and only if the item is a directory (i.e., it has the property BitProperty::IsDir). + */ + BIT7Z_NODISCARD virtual auto isDir() const -> bool = 0; + + /** + * @return true if and only if the item is a symbolic link. + */ + BIT7Z_NODISCARD virtual auto isSymLink() const -> bool = 0; + + /** + * @return the uncompressed size of the item. + */ + BIT7Z_NODISCARD virtual auto size() const -> uint64_t = 0; + + /** + * @return the name of the item, if available or inferable from the path, or an empty string otherwise. + */ + BIT7Z_NODISCARD virtual auto name() const -> tstring = 0; + + /** + * @return the path of the item. + */ + BIT7Z_NODISCARD virtual auto path() const -> tstring = 0; + + /** + * @return the item attributes. + */ + BIT7Z_NODISCARD virtual auto attributes() const -> uint32_t = 0; + + /** + * @brief Gets the specified item property. + * + * @param property the property to be retrieved. + * + * @return the value of the item property, if available, or an empty BitPropVariant. + */ + BIT7Z_NODISCARD virtual auto itemProperty( BitProperty property ) const -> BitPropVariant = 0; + + virtual ~BitGenericItem() = default; +}; + +} // namespace bit7z + +#endif //BITGENERICITEM_HPP diff --git a/Minecraft.Client/Common/libs/bit7z/include/bitinputarchive.hpp b/Minecraft.Client/Common/libs/bit7z/include/bitinputarchive.hpp new file mode 100644 index 000000000..9387d038f --- /dev/null +++ b/Minecraft.Client/Common/libs/bit7z/include/bitinputarchive.hpp @@ -0,0 +1,452 @@ +/* + * bit7z - A C++ static library to interface with the 7-zip shared libraries. + * Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ +#ifndef BITINPUTARCHIVE_HPP +#define BITINPUTARCHIVE_HPP + +#include +#include + +#include "bitabstractarchivehandler.hpp" +#include "bitarchiveitemoffset.hpp" +#include "bitformat.hpp" +#include "bitfs.hpp" + +struct IInStream; +struct IInArchive; +struct IOutArchive; + +namespace bit7z { + +using std::vector; + +/** + * @brief Offset from where the archive starts within the input file. + */ +enum struct ArchiveStartOffset : std::uint8_t { + None, ///< Don't specify an archive start offset. For some formats, like Zip archives, + ///< this means that the whole input file will be searched for the archive's start. + FileStart ///< Check only the file start for the archive's start. +}; + +/** + * @brief The BitInputArchive class, given a handler object, allows reading/extracting the content of archives. + */ +class BitInputArchive { + public: + /** + * @brief Constructs a BitInputArchive object, opening the input file archive. + * + * @param handler the reference to the BitAbstractArchiveHandler object containing all the settings to + * be used for reading the input archive + * @param inFile the path to the input archive file + * @param startOffset (optional) specifies whether to search for the archive's start throughout the + * entire file or only at the beginning. The default behavior is to search at the beginning. + */ + BitInputArchive( const BitAbstractArchiveHandler& handler, + const tstring& inFile, + ArchiveStartOffset startOffset = ArchiveStartOffset::None ); + + /** + * @brief Constructs a BitInputArchive object, opening the input file archive. + * + * @param handler the reference to the BitAbstractArchiveHandler object containing all the settings to + * be used for reading the input archive + * @param arcPath the path to the input archive file + * @param startOffset (optional) whether to search for the archive's start throughout the entire file + * or only at the beginning. The default behavior is to search at the beginning. + */ + BitInputArchive( const BitAbstractArchiveHandler& handler, + const fs::path& arcPath, + ArchiveStartOffset startOffset = ArchiveStartOffset::None ); + + /** + * @brief Constructs a BitInputArchive object, opening the archive given in the input buffer. + * + * @param handler the reference to the BitAbstractArchiveHandler object containing all the settings to + * be used for reading the input archive + * @param inBuffer the buffer containing the input archive + * @param startOffset (optional) whether to search for the archive's start throughout the entire file + * or only at the beginning. The default behavior is to search at the beginning. + */ + BitInputArchive( const BitAbstractArchiveHandler& handler, + const buffer_t& inBuffer, + ArchiveStartOffset startOffset = ArchiveStartOffset::None ); + + /** + * @brief Constructs a BitInputArchive object, opening the archive by reading the given input stream. + * + * @param handler the reference to the BitAbstractArchiveHandler object containing all the settings to + * be used for reading the input archive + * @param inStream the standard input stream of the input archive + * @param startOffset (optional) whether to search for the archive's start throughout the entire file + * or only at the beginning. The default behavior is to search at the beginning. + */ + BitInputArchive( const BitAbstractArchiveHandler& handler, + std::istream& inStream, + ArchiveStartOffset startOffset = ArchiveStartOffset::None ); + + BitInputArchive( const BitInputArchive& ) = delete; + + BitInputArchive( BitInputArchive&& ) = delete; + + auto operator=( const BitInputArchive& ) -> BitInputArchive& = delete; + + auto operator=( BitInputArchive&& ) -> BitInputArchive& = delete; + + virtual ~BitInputArchive(); + + /** + * @return the detected format of the file. + */ + BIT7Z_NODISCARD auto detectedFormat() const noexcept -> const BitInFormat&; + + /** + * @brief Gets the specified archive property. + * + * @param property the property to be retrieved. + * + * @return the current value of the archive property or an empty BitPropVariant if no value is specified. + */ + BIT7Z_NODISCARD auto archiveProperty( BitProperty property ) const -> BitPropVariant; + + /** + * @brief Gets the specified property of an item in the archive. + * + * @param index the index (in the archive) of the item. + * @param property the property to be retrieved. + * + * @return the current value of the item property or an empty BitPropVariant if the item has no value for + * the property. + */ + BIT7Z_NODISCARD auto itemProperty( uint32_t index, BitProperty property ) const -> BitPropVariant; + + /** + * @return the number of items contained in the archive. + */ + BIT7Z_NODISCARD auto itemsCount() const -> uint32_t; + + /** + * @param index the index of an item in the archive. + * + * @return true if and only if the item at the given index is a folder. + */ + BIT7Z_NODISCARD auto isItemFolder( uint32_t index ) const -> bool; + + /** + * @param index the index of an item in the archive. + * + * @return true if and only if the item at the given index is encrypted. + */ + BIT7Z_NODISCARD auto isItemEncrypted( uint32_t index ) const -> bool; + + /** + * @return the path to the archive (the empty string for buffer/stream archives). + */ + BIT7Z_NODISCARD auto archivePath() const noexcept -> const tstring&; + + /** + * @return the BitAbstractArchiveHandler object containing the settings for reading the archive. + */ + BIT7Z_NODISCARD auto handler() const noexcept -> const BitAbstractArchiveHandler&; + + /** + * @brief Use the given format property to read the archive. + * + * @param name the name of the property. + * @param property the property value. + */ + void useFormatProperty( const wchar_t* name, const BitPropVariant& property ) const; + + /** + * @brief Use the given format property to read the archive. + * + * @tparam T the type of the property. + * @param name the name of the property. + * @param value the property value. + */ + template< typename T, + typename = typename std::enable_if< is_explicitly_convertible< T, BitPropVariant >::value >::type > + void useFormatProperty( const wchar_t* name, T&& value ) const { // NOLINT(*-avoid-c-arrays) + useFormatProperty( name, BitPropVariant{ std::forward< T >( value ) } ); + } + + BIT7Z_DEPRECATED_MSG("Since v4.0; please, use the extractTo method.") + inline void extract( const tstring& outDir, const std::vector< uint32_t >& indices = {} ) const { + extractTo( outDir, indices ); + } + + /** + * @brief Extracts the archive to the chosen directory. + * + * @param outDir the output directory where the extracted files will be put. + */ + void extractTo( const tstring& outDir ) const; + + /** + * @brief Extracts the specified items to the chosen directory. + * + * @param outDir the output directory where the extracted files will be put. + * @param indices the array of indices of the files in the archive that must be extracted. + */ + void extractTo( const tstring& outDir, const std::vector< uint32_t >& indices ) const; + + BIT7Z_DEPRECATED_MSG("Since v4.0; please, use the extractTo method.") + inline void extract( std::vector< byte_t >& outBuffer, uint32_t index = 0 ) const { + extractTo( outBuffer, index ); + } + + /** + * @brief Extracts a file to the output buffer. + * + * @param outBuffer the output buffer where the content of the archive will be put. + * @param index the index of the file to be extracted. + */ + void extractTo( std::vector< byte_t >& outBuffer, uint32_t index = 0 ) const; + + template< std::size_t N > + BIT7Z_DEPRECATED_MSG("Since v4.0; please, use the extractTo method.") + void extract( std::array< byte_t, N >& buffer, uint32_t index = 0 ) const { + extractTo( buffer.data(), buffer.size(), index ); + } + + /** + * @brief Extracts a file to the pre-allocated output buffer. + * + * @tparam N the size of the output buffer (it must be equal to the unpacked size + * of the item to be extracted). + * @param buffer the pre-allocated output buffer. + * @param index the index of the file to be extracted. + */ + template< std::size_t N > + void extractTo( std::array< byte_t, N >& buffer, uint32_t index = 0 ) const { + extractTo( buffer.data(), buffer.size(), index ); + } + + template< std::size_t N > + BIT7Z_DEPRECATED_MSG("Since v4.0; please, use the extractTo method.") + void extract( byte_t (& buffer)[N], uint32_t index = 0 ) const { // NOLINT(*-avoid-c-arrays) + extractTo( buffer, N, index ); + } + + /** + * @brief Extracts a file to the pre-allocated output buffer. + * + * @tparam N the size of the output buffer (it must be equal to the unpacked size + * of the item to be extracted). + * @param buffer the pre-allocated output buffer. + * @param index the index of the file to be extracted. + */ + template< std::size_t N > + void extractTo( byte_t (& buffer)[N], uint32_t index = 0 ) const { // NOLINT(*-avoid-c-arrays) + extractTo( buffer, N, index ); + } + + BIT7Z_DEPRECATED_MSG("Since v4.0; please, use the extractTo method.") + inline void extract( byte_t* buffer, std::size_t size, uint32_t index = 0 ) const { + extractTo( buffer, size, index ); + } + + /** + * @brief Extracts a file to the pre-allocated output buffer. + * + * @param buffer the pre-allocated output buffer. + * @param size the size of the output buffer (it must be equal to the unpacked size + * of the item to be extracted). + * @param index the index of the file to be extracted. + */ + void extractTo( byte_t* buffer, std::size_t size, uint32_t index = 0 ) const; + + BIT7Z_DEPRECATED_MSG("Since v4.0; please, use the extractTo method.") + inline void extract( std::ostream& outStream, uint32_t index = 0 ) const { + extractTo( outStream, index ); + } + + /** + * @brief Extracts a file to the output stream. + * + * @param outStream the (binary) stream where the content of the archive will be put. + * @param index the index of the file to be extracted. + */ + void extractTo( std::ostream& outStream, uint32_t index = 0 ) const; + + BIT7Z_DEPRECATED_MSG("Since v4.0; please, use the extractTo method.") + inline void extract( std::map< tstring, std::vector< byte_t > >& outMap ) const { + extractTo( outMap ); + } + + /** + * @brief Extracts the content of the archive to a map of memory buffers, where the keys are the paths + * of the files (inside the archive), and the values are their decompressed contents. + * + * @param outMap the output map. + */ + void extractTo( std::map< tstring, std::vector< byte_t > >& outMap ) const; + + /** + * @brief Tests the archive without extracting its content. + * + * If the archive is not valid, a BitException is thrown! + */ + void test() const; + + /** + * @brief Tests the item at the given index inside the archive without extracting it. + * + * If the archive is not valid, or there's no item at the given index, a BitException is thrown! + * + * @param index the index of the file to be tested. + */ + void testItem( uint32_t index ) const; + + protected: + auto initUpdatableArchive( IOutArchive** newArc ) const -> HRESULT; + + BIT7Z_NODISCARD auto close() const noexcept -> HRESULT; + + friend class BitAbstractArchiveOpener; + + friend class BitAbstractArchiveCreator; + + friend class BitOutputArchive; + + private: + IInArchive* mInArchive; + const BitInFormat* mDetectedFormat; + const BitAbstractArchiveHandler& mArchiveHandler; + tstring mArchivePath; + + BIT7Z_NODISCARD + auto openArchiveStream( const fs::path& name, IInStream* inStream, ArchiveStartOffset startOffset ) -> IInArchive*; + + public: + /** + * @brief An iterator for the elements contained in an archive. + */ + class ConstIterator { + public: + // iterator traits + using iterator_category BIT7Z_MAYBE_UNUSED = std::input_iterator_tag; + using value_type BIT7Z_MAYBE_UNUSED = BitArchiveItemOffset; + using reference = const BitArchiveItemOffset&; + using pointer = const BitArchiveItemOffset*; + using difference_type BIT7Z_MAYBE_UNUSED = uint32_t; //so that count_if returns an uint32_t + + /** + * @brief Advances the iterator to the next element in the archive. + * + * @return the iterator pointing to the next element in the archive. + */ + auto operator++() noexcept -> ConstIterator&; + + /** + * @brief Advances the iterator to the next element in the archive. + * + * @return the iterator before the advancement. + */ + auto operator++( int ) noexcept -> ConstIterator; // NOLINT(cert-dcl21-cpp) + + /** + * @brief Compares the iterator with another iterator. + * + * @param other Another iterator. + * + * @return whether the two iterators point to the same element in the archive or not. + */ + auto operator==( const ConstIterator& other ) const noexcept -> bool; + + /** + * @brief Compares the iterator with another iterator. + * + * @param other Another iterator. + * + * @return whether the two iterators point to the different elements in the archive or not. + */ + auto operator!=( const ConstIterator& other ) const noexcept -> bool; + + /** + * @brief Accesses the pointed-to element in the archive. + * + * @return a reference to the pointed-to element in the archive. + */ + auto operator*() const noexcept -> reference; + + /** + * @brief Accesses the pointed-to element in the archive. + * + * @return a pointer to the pointed-to element in the archive. + */ + auto operator->() const noexcept -> pointer; + + private: + BitArchiveItemOffset mItemOffset; + + ConstIterator( uint32_t itemIndex, const BitInputArchive& itemArchive ) noexcept; + + friend class BitInputArchive; + }; + + BIT7Z_DEPRECATED_TYPEDEF( const_iterator, ConstIterator, "Use ConstIterator" ); + + /** + * @return an iterator to the first element of the archive; if the archive is empty, + * the returned iterator will be equal to the end() iterator. + */ + BIT7Z_NODISCARD auto begin() const noexcept -> BitInputArchive::ConstIterator; + + /** + * @return an iterator to the element following the last element of the archive; + * this element acts as a placeholder: attempting to access it results in undefined behavior. + */ + BIT7Z_NODISCARD auto end() const noexcept -> BitInputArchive::ConstIterator; + + /** + * @return an iterator to the first element of the archive; if the archive is empty, + * the returned iterator will be equal to the end() iterator. + */ + BIT7Z_NODISCARD auto cbegin() const noexcept -> BitInputArchive::ConstIterator; + + /** + * @return an iterator to the element following the last element of the archive; + * this element acts as a placeholder: attempting to access it results in undefined behavior. + */ + BIT7Z_NODISCARD auto cend() const noexcept -> BitInputArchive::ConstIterator; + + /** + * @brief Find an item in the archive that has the given path. + * + * @param path the path to be searched in the archive. + * + * @return an iterator to the item with the given path, or an iterator equal to the end() iterator + * if no item is found. + */ + BIT7Z_NODISCARD auto find( const tstring& path ) const noexcept -> BitInputArchive::ConstIterator; + + /** + * @brief Find if there is an item in the archive that has the given path. + * + * @param path the path to be searched in the archive. + * + * @return true if and only if an item with the given path exists in the archive. + */ + BIT7Z_NODISCARD auto contains( const tstring& path ) const noexcept -> bool; + + /** + * @brief Retrieve the item at the given index. + * + * @param index the index of the item to be retrieved. + * + * @return the item at the given index within the archive. + */ + BIT7Z_NODISCARD auto itemAt( uint32_t index ) const -> BitArchiveItemOffset; + +}; + +} // namespace bit7z + +#endif //BITINPUTARCHIVE_HPP diff --git a/Minecraft.Client/Common/libs/bit7z/include/bititemsvector.hpp b/Minecraft.Client/Common/libs/bit7z/include/bititemsvector.hpp new file mode 100644 index 000000000..aac5bc8ee --- /dev/null +++ b/Minecraft.Client/Common/libs/bit7z/include/bititemsvector.hpp @@ -0,0 +1,172 @@ +/* + * bit7z - A C++ static library to interface with the 7-zip shared libraries. + * Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef BITITEMSVECTOR_HPP +#define BITITEMSVECTOR_HPP + +#include +#include + +#include "bitabstractarchivehandler.hpp" +#include "bitfs.hpp" +#include "bittypes.hpp" + +namespace bit7z { + +using std::vector; +using std::map; +using std::unique_ptr; + +namespace filesystem { +class FilesystemItem; +} // namespace filesystem + +using filesystem::FilesystemItem; + +struct GenericInputItem; +using GenericInputItemPtr = std::unique_ptr< GenericInputItem >; +using GenericInputItemVector = std::vector< GenericInputItemPtr >; + +/** @cond **/ +struct IndexingOptions { + bool recursive = true; + bool retainFolderStructure = false; + bool onlyFiles = false; + bool followSymlinks = true; +}; +/** @endcond **/ + +/** + * @brief The BitItemsVector class represents a vector of generic input items, i.e., items that can come + * from the filesystem, from memory buffers, or from standard streams. + */ +class BitItemsVector final { + public: + using value_type = GenericInputItemPtr; + + BitItemsVector() = default; + + BitItemsVector( const BitItemsVector& ) = default; + + BitItemsVector( BitItemsVector&& ) = default; + + auto operator=( const BitItemsVector& ) -> BitItemsVector& = default; + + auto operator=( BitItemsVector&& ) -> BitItemsVector& = default; + + /** + * @brief Indexes the given directory, adding to the vector all the files that match the wildcard filter. + * + * @param inDir the directory to be indexed. + * @param filter (optional) the wildcard filter to be used for indexing; + * empty string means "index all files". + * @param policy (optional) the filtering policy to be applied to the matched items. + * @param options (optional) the settings to be used while indexing the given directory + * and all of its subdirectories. + */ + void indexDirectory( const fs::path& inDir, + const tstring& filter = {}, + FilterPolicy policy = FilterPolicy::Include, + IndexingOptions options = {} ); + + /** + * @brief Indexes the given vector of filesystem paths, adding to the item vector all the files. + * + * @param inPaths the vector of filesystem paths. + * @param options (optional) the settings to be used while indexing the given directory + * and all of its subdirectories. + */ + void indexPaths( const std::vector< tstring >& inPaths, IndexingOptions options = {} ); + + /** + * @brief Indexes the given map of filesystem paths, adding to the vector all the files. + * + * @note Map keys represent the filesystem paths to be indexed; the corresponding mapped values are + * the user-defined (possibly different) paths wanted inside archives. + * + * @param inPaths map of filesystem paths with the corresponding user-defined path desired inside the + * output archive. + * @param options (optional) the settings to be used while indexing the given directory + * and all of its subdirectories. + */ + void indexPathsMap( const std::map< tstring, tstring >& inPaths, IndexingOptions options = {} ); + + /** + * @brief Indexes the given file path, with an optional user-defined path to be used in output archives. + * + * @note If a directory path is given, a BitException is thrown. + * + * @param inFile the path to the filesystem file to be indexed in the vector. + * @param name (optional) user-defined path to be used inside archives. + * @param followSymlinks (optional) whether to follow symbolic links or not. + */ + void indexFile( const tstring& inFile, const tstring& name = {}, bool followSymlinks = true ); + + /** + * @brief Indexes the given buffer, using the given name as a path when compressed in archives. + * + * @param inBuffer the buffer containing the file to be indexed in the vector. + * @param name user-defined path to be used inside archives. + */ + void indexBuffer( const std::vector< byte_t >& inBuffer, const tstring& name ); + + /** + * @brief Indexes the given standard input stream, using the given name as a path when compressed in archives. + * + * @param inStream the standard input stream of the file to be indexed in the vector. + * @param name user-defined path to be used inside archives. + */ + void indexStream( std::istream& inStream, const tstring& name ); + + /** + * @return the size of the items vector. + */ + BIT7Z_NODISCARD auto size() const -> std::size_t; + + /** + * @param index the index of the desired item in the vector. + * @return a constant reference to the GenericInputItem at the given index. + */ + auto operator[]( GenericInputItemVector::size_type index ) const -> const GenericInputItem&; + + /** + * @return an iterator to the first element of the vector; if the vector is empty, + * the returned iterator will be equal to the end() iterator. + */ + BIT7Z_NODISCARD auto begin() const noexcept -> GenericInputItemVector::const_iterator; + + /** + * @return an iterator to the element following the last element of the vector; + * this element acts as a placeholder: attempting to access it results in undefined behavior. + */ + BIT7Z_NODISCARD auto end() const noexcept -> GenericInputItemVector::const_iterator; + + /** + * @return an iterator to the first element of the vector; if the vector is empty, + * the returned iterator will be equal to the end() iterator. + */ + BIT7Z_NODISCARD auto cbegin() const noexcept -> GenericInputItemVector::const_iterator; + + /** + * @return an iterator to the element following the last element of the vector; + * this element acts as a placeholder: attempting to access it results in undefined behavior. + */ + BIT7Z_NODISCARD auto cend() const noexcept -> GenericInputItemVector::const_iterator; + + ~BitItemsVector(); + + private: + GenericInputItemVector mItems; + + void indexItem( const FilesystemItem& item, IndexingOptions options ); +}; + +} // namespace bit7z + +#endif //BITITEMSVECTOR_HPP diff --git a/Minecraft.Client/Common/libs/bit7z/include/bitmemcompressor.hpp b/Minecraft.Client/Common/libs/bit7z/include/bitmemcompressor.hpp new file mode 100644 index 000000000..ec35dd6aa --- /dev/null +++ b/Minecraft.Client/Common/libs/bit7z/include/bitmemcompressor.hpp @@ -0,0 +1,27 @@ +/* + * bit7z - A C++ static library to interface with the 7-zip shared libraries. + * Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef BITMEMCOMPRESSOR_HPP +#define BITMEMCOMPRESSOR_HPP + +#include "bitcompressor.hpp" + +namespace bit7z { + +/** + * @brief The BitMemCompressor alias allows compressing memory buffers. + * The compressed archives can be saved to the filesystem, standard streams, or memory buffers. + * + * It let decide various properties of the produced archive, such as the password + * protection and the compression level desired. + */ +using BitMemCompressor BIT7Z_MAYBE_UNUSED = BitCompressor< const std::vector< byte_t >& >; + +} // namespace bit7z +#endif // BITMEMCOMPRESSOR_HPP diff --git a/Minecraft.Client/Common/libs/bit7z/include/bitmemextractor.hpp b/Minecraft.Client/Common/libs/bit7z/include/bitmemextractor.hpp new file mode 100644 index 000000000..bd1e134d5 --- /dev/null +++ b/Minecraft.Client/Common/libs/bit7z/include/bitmemextractor.hpp @@ -0,0 +1,24 @@ +/* + * bit7z - A C++ static library to interface with the 7-zip shared libraries. + * Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef BITMEMEXTRACTOR_HPP +#define BITMEMEXTRACTOR_HPP + +#include "bitextractor.hpp" + +namespace bit7z { + +/** + * @brief The BitMemExtractor alias allows extracting the content of in-memory archives. + */ +using BitMemExtractor BIT7Z_MAYBE_UNUSED = BitExtractor< const std::vector< byte_t >& >; + +} // namespace bit7z + +#endif // BITMEMEXTRACTOR_HPP diff --git a/Minecraft.Client/Common/libs/bit7z/include/bitoutputarchive.hpp b/Minecraft.Client/Common/libs/bit7z/include/bitoutputarchive.hpp new file mode 100644 index 000000000..5f49d5683 --- /dev/null +++ b/Minecraft.Client/Common/libs/bit7z/include/bitoutputarchive.hpp @@ -0,0 +1,368 @@ +/* + * bit7z - A C++ static library to interface with the 7-zip shared libraries. + * Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef BITOUTPUTARCHIVE_HPP +#define BITOUTPUTARCHIVE_HPP + +#include +#include + +#include "bitabstractarchivecreator.hpp" +#include "bititemsvector.hpp" +#include "bitexception.hpp" //for FailedFiles +#include "bitpropvariant.hpp" + +//! @cond IGNORE_BLOCK_IN_DOXYGEN +struct ISequentialInStream; + +template< typename T > +class CMyComPtr; +//! @endcond + +namespace bit7z { + +using std::istream; + +using DeletedItems = std::set< uint32_t >; + +/* General note: I tried my best to explain how indices work here, but it is a bit complex. */ + +/* We introduce a strong index type to differentiate between indices in the output + * archive (uint32_t, as used by the UpdateCallback), and the corresponding indexes + * in the input archive (InputIndex). In this way, we avoid implicit conversions + * between the two kinds of indices. + * + * UpdateCallback uses indices in the range [0, BitOutputArchive::itemsCount() - 1] + * + * Now, if the user doesn't delete any item in the input archive, itemsCount() + * is just equal to + . + * In this case, an InputIndex value is just equal to the index used by UpdateCallback. + * + * On the contrary, if the user wants to delete an item in the input archive, the value + * of an InputIndex may differ from the corresponding UpdateCallback's index. + * + * Note: given an InputIndex i: + * if i < mInputArchiveItemsCount, the item is old (old item in the input archive); + * if i >= mInputArchiveItemsCount, the item is new (added by the user); */ +enum class InputIndex : std::uint32_t {}; + +class UpdateCallback; + +/** + * @brief The BitOutputArchive class, given a creator object, allows creating new archives. + */ +class BitOutputArchive { + public: + /** + * @brief Constructs a BitOutputArchive object for a completely new archive. + * + * @param creator the reference to the BitAbstractArchiveCreator object containing all the settings to + * be used for creating the new archive. + */ + explicit BitOutputArchive( const BitAbstractArchiveCreator& creator ); + + /** + * @brief Constructs a BitOutputArchive object, opening an (optional) input file archive. + * + * If a non-empty input file path is passed, the corresponding archive will be opened and + * used as a base for the creation of the new archive. Otherwise, the class will behave + * as if it is creating a completely new archive. + * + * @param creator the reference to the BitAbstractArchiveCreator object containing all the settings to + * be used for creating the new archive and reading the (optional) input archive. + * @param inFile (optional) the path to an input archive file. + */ + explicit BitOutputArchive( const BitAbstractArchiveCreator& creator, + const tstring& inFile, + ArchiveStartOffset startOffset = ArchiveStartOffset::None ); + + /** + * @brief Constructs a BitOutputArchive object, opening an input file archive from the given buffer. + * + * If a non-empty input buffer is passed, the archive file it contains will be opened and + * used as a base for the creation of the new archive. Otherwise, the class will behave + * as if it is creating a completely new archive. + * + * @param creator the reference to the BitAbstractArchiveCreator object containing all the settings to + * be used for creating the new archive and reading the (optional) input archive. + * @param inBuffer the buffer containing an input archive file. + */ + BitOutputArchive( const BitAbstractArchiveCreator& creator, + const buffer_t& inBuffer, + ArchiveStartOffset startOffset = ArchiveStartOffset::None ); + + /** + * @brief Constructs a BitOutputArchive object, reading an input file archive from the given std::istream. + * + * @param creator the reference to the BitAbstractArchiveCreator object containing all the settings to + * be used for creating the new archive and reading the (optional) input archive. + * @param inStream the standard input stream of the input archive file. + */ + BitOutputArchive( const BitAbstractArchiveCreator& creator, + std::istream& inStream, + ArchiveStartOffset startOffset = ArchiveStartOffset::None ); + + BitOutputArchive( const BitOutputArchive& ) = delete; + + BitOutputArchive( BitOutputArchive&& ) = delete; + + auto operator=( const BitOutputArchive& ) -> BitOutputArchive& = delete; + + auto operator=( BitOutputArchive&& ) -> BitOutputArchive& = delete; + + /** + * @brief Adds all the items that can be found by indexing the given vector of filesystem paths. + * + * @param inPaths the vector of filesystem paths. + */ + void addItems( const std::vector< tstring >& inPaths ); + + /** + * @brief Adds all the items that can be found by indexing the keys of the given map of filesystem paths; + * the corresponding mapped values are the user-defined paths wanted inside the output archive. + * + * @param inPaths map of filesystem paths with the corresponding user-defined path desired inside the + * output archive. + */ + void addItems( const std::map< tstring, tstring >& inPaths ); + + /** + * @brief Adds the given file path, with an optional user-defined path to be used in the output archive. + * + * @note If a directory path is given, a BitException is thrown. + * + * @param inFile the path to the filesystem file to be added to the output archive. + * @param name (optional) user-defined path to be used inside the output archive. + */ + void addFile( const tstring& inFile, const tstring& name = {} ); + + /** + * @brief Adds the given buffer file, using the given name as a path when compressed in the output archive. + * + * @param inBuffer the buffer containing the file to be added to the output archive. + * @param name user-defined path to be used inside the output archive. + */ + void addFile( const std::vector< byte_t >& inBuffer, const tstring& name ); + + /** + * @brief Adds the given standard input stream, using the given name as a path when compressed + * in the output archive. + * + * @param inStream the input stream to be added. + * @param name the name of the file inside the output archive. + */ + void addFile( std::istream& inStream, const tstring& name ); + + /** + * @brief Adds all the files in the given vector of filesystem paths. + * + * @note Paths to directories are ignored. + * + * @param inFiles the vector of paths to files. + */ + void addFiles( const std::vector< tstring >& inFiles ); + + /** + * @brief Adds all the files inside the given directory path that match the given wildcard filter. + * + * @param inDir the directory where to search for files to be added to the output archive. + * @param filter the wildcard filter to be used for searching the files. + * @param recursive recursively search the files in the given directory and all of its subdirectories. + */ + void addFiles( const tstring& inDir, const tstring& filter, bool recursive ); + + /** + * @brief Adds all the files inside the given directory path that match the given wildcard filter. + * + * @param inDir the directory where to search for files to be added to the output archive. + * @param filter (optional) the wildcard filter to be used for searching the files. + * @param recursive (optional) recursively search the files in the given directory + * and all of its subdirectories. + * @param policy (optional) the filtering policy to be applied to the matched items. + */ + void addFiles( const tstring& inDir, + const tstring& filter = BIT7Z_STRING( "*" ), + FilterPolicy policy = FilterPolicy::Include, + bool recursive = true ); + + /** + * @brief Adds the given directory path and all its content. + * + * @param inDir the path of the directory to be added to the archive. + */ + void addDirectory( const tstring& inDir ); + + /** + * @brief Adds the contents of the given directory path. + * + * This function iterates through the specified directory and adds its contents + * based on the provided wildcard filter. Optionally, the operation can be + * recursive, meaning it will include subdirectories and their contents. + * + * @param inDir the directory where to search for files to be added to the output archive. + * @param filter the wildcard filter to be used for searching the files. + * @param recursive recursively search the files in the given directory and all of its subdirectories. + */ + void addDirectoryContents( const tstring& inDir, const tstring& filter, bool recursive ); + + /** + * @brief Adds the contents of the given directory path. + * + * This function iterates through the specified directory and adds its contents + * based on the provided wildcard filter and policy. Optionally, the operation can be + * recursive, meaning it will include subdirectories and their contents. + * + * @param inDir the directory where to search for files to be added to the output archive. + * @param filter (optional) the wildcard filter to be used for searching the files. + * @param recursive (optional) recursively search the files in the given directory + * and all of its subdirectories. + * @param policy (optional) the filtering policy to be applied to the matched items. + */ + void addDirectoryContents( const tstring& inDir, + const tstring& filter = BIT7Z_STRING( "*" ), + FilterPolicy policy = FilterPolicy::Include, + bool recursive = true ); + + /** + * @brief Compresses all the items added to this object to the specified archive file path. + * + * @note If this object was created by passing an input archive file path, and this latter is the same as + * the outFile path parameter, the file will be updated. + * + * @param outFile the output archive file path. + */ + void compressTo( const tstring& outFile ); + + /** + * @brief Compresses all the items added to this object to the specified buffer. + * + * @param outBuffer the output buffer. + */ + void compressTo( std::vector< byte_t >& outBuffer ); + + /** + * @brief Compresses all the items added to this object to the specified buffer. + * + * @param outStream the output standard stream. + */ + void compressTo( std::ostream& outStream ); + + /** + * @return the total number of items added to the output archive object. + */ + auto itemsCount() const -> uint32_t; + + /** + * @return a constant reference to the BitAbstractArchiveHandler object containing the + * settings for writing the output archive. + */ + auto handler() const noexcept -> const BitAbstractArchiveHandler&; + + /** + * @return a constant reference to the BitAbstractArchiveHandler object containing the + * settings for writing the output archive. + */ + auto creator() const noexcept -> const BitAbstractArchiveCreator&; + + /** + * @brief Default destructor. + */ + virtual ~BitOutputArchive() = default; + + protected: + virtual auto itemProperty( InputIndex index, BitProperty property ) const -> BitPropVariant; + + virtual auto itemStream( InputIndex index, ISequentialInStream** inStream ) const -> HRESULT; + + virtual auto hasNewData( uint32_t index ) const noexcept -> bool; + + virtual auto hasNewProperties( uint32_t index ) const noexcept -> bool; + + auto itemInputIndex( uint32_t newIndex ) const noexcept -> InputIndex; + + auto outputItemProperty( uint32_t index, BitProperty property ) const -> BitPropVariant; + + auto outputItemStream( uint32_t index, ISequentialInStream** inStream ) const -> HRESULT; + + auto indexInArchive( uint32_t index ) const noexcept -> uint32_t; + + inline auto inputArchive() const -> BitInputArchive* { + return mInputArchive.get(); + } + + inline void setInputArchive( std::unique_ptr< BitInputArchive >&& inputArchive ) { + mInputArchive = std::move( inputArchive ); + } + + inline auto inputArchiveItemsCount() const -> uint32_t { + return mInputArchiveItemsCount; + } + + inline void setDeletedIndex( uint32_t index ) { + mDeletedItems.insert( index ); + } + + inline auto isDeletedIndex( uint32_t index ) const -> bool { + return mDeletedItems.find( index ) != mDeletedItems.cend(); + } + + inline auto hasDeletedIndexes() const -> bool { + return !mDeletedItems.empty(); + } + + inline auto hasNewItems() const -> bool { + return mNewItemsVector.size() > 0; + } + + friend class UpdateCallback; + + private: + const BitAbstractArchiveCreator& mArchiveCreator; + + unique_ptr< BitInputArchive > mInputArchive; + uint32_t mInputArchiveItemsCount; + + BitItemsVector mNewItemsVector; + DeletedItems mDeletedItems; + + mutable FailedFiles mFailedFiles; + + /* mInputIndices: + * - Position i = index in range [0, itemsCount() - 1] used by UpdateCallback. + * - Value at position i = corresponding index in the input archive (type InputIndex). + * + * If there are some deleted items, then i != mInputIndices[i] + * (at least for values of i greater than the index of the first deleted item). + * + * Otherwise, if there are no deleted items, the vector is empty, and itemInputIndex(i) + * will return InputIndex with value i. + * + * This vector is either empty, or it has size equal to itemsCount() (thanks to updateInputIndices()). */ + std::vector< InputIndex > mInputIndices; + + auto initOutArchive() const -> CMyComPtr< IOutArchive >; + + auto initOutFileStream( const fs::path& outArchive, bool updatingArchive ) const -> CMyComPtr< IOutStream >; + + BitOutputArchive( const BitAbstractArchiveCreator& creator, + const fs::path& inArc, + ArchiveStartOffset archiveStart ); + + void compressToFile( const fs::path& outFile, UpdateCallback* updateCallback ); + + void compressOut( IOutArchive* outArc, IOutStream* outStream, UpdateCallback* updateCallback ); + + void setArchiveProperties( IOutArchive* outArchive ) const; + + void updateInputIndices(); +}; + +} // namespace bit7z + +#endif //BITOUTPUTARCHIVE_HPP diff --git a/Minecraft.Client/Common/libs/bit7z/include/bitpropvariant.hpp b/Minecraft.Client/Common/libs/bit7z/include/bitpropvariant.hpp new file mode 100644 index 000000000..6c0c7a4b0 --- /dev/null +++ b/Minecraft.Client/Common/libs/bit7z/include/bitpropvariant.hpp @@ -0,0 +1,461 @@ +/* + * bit7z - A C++ static library to interface with the 7-zip shared libraries. + * Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef BITPROPVARIANT_HPP +#define BITPROPVARIANT_HPP + +#include +#include + +#include "bitdefines.hpp" +#include "bittypes.hpp" +#include "bitwindows.hpp" + +namespace bit7z { + +/** + * @brief A type representing a time point measured using the system clock. + */ +using time_type = std::chrono::time_point< std::chrono::system_clock >; + +/** + * @brief The BitProperty enum represents the archive/item properties that 7-zip can read or write. + */ +enum struct BitProperty : PROPID { + NoProperty = 0, ///< + MainSubfile, ///< + HandlerItemIndex, ///< + Path, ///< + Name, ///< + Extension, ///< + IsDir, ///< + Size, ///< + PackSize, ///< + Attrib, ///< + CTime, ///< + ATime, ///< + MTime, ///< + Solid, ///< + Commented, ///< + Encrypted, ///< + SplitBefore, ///< + SplitAfter, ///< + DictionarySize, ///< + CRC, ///< + Type, ///< + IsAnti, ///< + Method, ///< + HostOS, ///< + FileSystem, ///< + User, ///< + Group, ///< + Block, ///< + Comment, ///< + Position, ///< + Prefix, ///< + NumSubDirs, ///< + NumSubFiles, ///< + UnpackVer, ///< + Volume, ///< + IsVolume, ///< + Offset, ///< + Links, ///< + NumBlocks, ///< + NumVolumes, ///< + TimeType, ///< + Bit64, ///< + BigEndian, ///< + Cpu, ///< + PhySize, ///< + HeadersSize, ///< + Checksum, ///< + Characts, ///< + Va, ///< + Id, ///< + ShortName, ///< + CreatorApp, ///< + SectorSize, ///< + PosixAttrib, ///< + SymLink, ///< + Error, ///< + TotalSize, ///< + FreeSpace, ///< + ClusterSize, ///< + VolumeName, ///< + LocalName, ///< + Provider, ///< + NtSecure, ///< + IsAltStream, ///< + IsAux, ///< + IsDeleted, ///< + IsTree, ///< + Sha1, ///< + Sha256, ///< + ErrorType, ///< + NumErrors, ///< + ErrorFlags, ///< + WarningFlags, ///< + Warning, ///< + NumStreams, ///< + NumAltStreams, ///< + AltStreamsSize, ///< + VirtualSize, ///< + UnpackSize, ///< + TotalPhySize, ///< + VolumeIndex, ///< + SubType, ///< + ShortComment, ///< + CodePage, ///< + IsNotArcType, ///< + PhySizeCantBeDetected, ///< + ZerosTailIsAllowed, ///< + TailSize, ///< + EmbeddedStubSize, ///< + NtReparse, ///< + HardLink, ///< + INode, ///< + StreamId, ///< + ReadOnly, ///< + OutName, ///< + CopyLink ///< +}; + +/** + * @brief The BitPropVariantType enum represents the possible types that a BitPropVariant can store. + */ +enum struct BitPropVariantType : uint32_t { + Empty, ///< Empty BitPropVariant type + Bool, ///< Boolean BitPropVariant type + String, ///< String BitPropVariant type + UInt8, ///< 8-bit unsigned int BitPropVariant type + UInt16, ///< 16-bit unsigned int BitPropVariant type + UInt32, ///< 32-bit unsigned int BitPropVariant type + UInt64, ///< 64-bit unsigned int BitPropVariant type + Int8, ///< 8-bit signed int BitPropVariant type + Int16, ///< 16-bit signed int BitPropVariant type + Int32, ///< 32-bit signed int BitPropVariant type + Int64, ///< 64-bit signed int BitPropVariant type + FileTime ///< FILETIME BitPropVariant type +}; + +/** + * @brief The BitPropVariant struct is a light extension to the WinAPI PROPVARIANT struct providing useful getters. + */ +struct BitPropVariant final : public PROPVARIANT { + /** + * @brief Constructs an empty BitPropVariant object. + */ + BitPropVariant(); + + /** + * @brief Copy constructs this BitPropVariant from another one. + * + * @param other the variant to be copied. + */ + BitPropVariant( const BitPropVariant& other ); + + /** + * @brief Move constructs this BitPropVariant from another one. + * + * @param other the variant to be moved. + */ + BitPropVariant( BitPropVariant&& other ) noexcept; + + /** + * @brief Constructs a boolean BitPropVariant + * + * @param value the bool value of the BitPropVariant + */ + explicit BitPropVariant( bool value ) noexcept; + + /** + * @brief Constructs a string BitPropVariant from a null-terminated C wide string + * + * @param value the null-terminated C wide string value of the BitPropVariant + */ + explicit BitPropVariant( const wchar_t* value ); + + /** + * @brief Constructs a string BitPropVariant from a wstring + * + * @param value the wstring value of the BitPropVariant + */ + explicit BitPropVariant( const std::wstring& value ); + + /** + * @brief Constructs an 8-bit unsigned integer BitPropVariant + * + * @param value the uint8_t value of the BitPropVariant + */ + explicit BitPropVariant( uint8_t value ) noexcept; + + /** + * @brief Constructs a 16-bit unsigned integer BitPropVariant + * + * @param value the uint16_t value of the BitPropVariant + */ + explicit BitPropVariant( uint16_t value ) noexcept; + + /** + * @brief Constructs a 32-bit unsigned integer BitPropVariant + * + * @param value the uint32_t value of the BitPropVariant + */ + explicit BitPropVariant( uint32_t value ) noexcept; + + /** + * @brief Constructs a 64-bit unsigned integer BitPropVariant + * + * @param value the uint64_t value of the BitPropVariant + */ + explicit BitPropVariant( uint64_t value ) noexcept; + + /** + * @brief Constructs an 8-bit integer BitPropVariant + * + * @param value the int8_t value of the BitPropVariant + */ + explicit BitPropVariant( int8_t value ) noexcept; + + /** + * @brief Constructs a 16-bit integer BitPropVariant + * + * @param value the int16_t value of the BitPropVariant + */ + explicit BitPropVariant( int16_t value ) noexcept; + + /** + * @brief Constructs a 32-bit integer BitPropVariant + * + * @param value the int32_t value of the BitPropVariant + */ + explicit BitPropVariant( int32_t value ) noexcept; + + /** + * @brief Constructs a 64-bit integer BitPropVariant + * + * @param value the int64_t value of the BitPropVariant + */ + explicit BitPropVariant( int64_t value ) noexcept; + + /** + * @brief Constructs a FILETIME BitPropVariant + * + * @param value the FILETIME value of the BitPropVariant + */ + explicit BitPropVariant( FILETIME value ) noexcept; + + /** + * @brief BitPropVariant destructor. + * + * @note This is not virtual to maintain the same memory layout of the base struct! + */ + ~BitPropVariant(); + + /** + * @brief Copy assignment operator. + * + * @param other the variant to be copied. + * + * @return a reference to *this object (with the copied values from other). + */ + auto operator=( const BitPropVariant& other ) -> BitPropVariant&; + + /** + * @brief Move assignment operator. + * + * @param other the variant to be moved. + * + * @return a reference to *this object (with the moved values from other). + */ + auto operator=( BitPropVariant&& other ) noexcept -> BitPropVariant&; + + /** + * @brief Assignment operator + * + * @note this will work only for T types for which a BitPropVariant constructor is defined! + * + * @param value the value to be assigned to the object + * + * @return a reference to *this object having the value as new variant value + */ + template< typename T > + auto operator=( const T& value ) noexcept( std::is_integral< T >::value ) -> BitPropVariant& { + *this = BitPropVariant{ value }; + return *this; + } + + /** + * @return the boolean value of this variant + * (it throws an exception if the variant is not a boolean value). + */ + BIT7Z_NODISCARD auto getBool() const -> bool; + + /** + * @return the string value of this variant + * (it throws an exception if the variant is not a string). + */ + BIT7Z_NODISCARD auto getString() const -> tstring; + + /** + * @return the native string value of this variant + * (it throws an exception if the variant is not a string). + */ + BIT7Z_NODISCARD auto getNativeString() const -> native_string; + + /** + * @return the 8-bit unsigned integer value of this variant + * (it throws an exception if the variant is not an 8-bit unsigned integer). + */ + BIT7Z_NODISCARD auto getUInt8() const -> uint8_t; + + /** + * @return the 16-bit unsigned integer value of this variant + * (it throws an exception if the variant is not an 8 or 16-bit unsigned integer). + */ + BIT7Z_NODISCARD auto getUInt16() const -> uint16_t; + + /** + * @return the 32-bit unsigned integer value of this variant + * (it throws an exception if the variant is not an 8, 16 or 32-bit unsigned integer). + */ + BIT7Z_NODISCARD auto getUInt32() const -> uint32_t; + + /** + * @return the 64-bit unsigned integer value of this variant + * (it throws an exception if the variant is not an 8, 16, 32 or 64-bit unsigned integer). + */ + BIT7Z_NODISCARD auto getUInt64() const -> uint64_t; + + /** + * @return the 8-bit integer value of this variant + * (it throws an exception if the variant is not an 8-bit integer). + */ + BIT7Z_NODISCARD auto getInt8() const -> int8_t; + + /** + * @return the 16-bit integer value of this variant + * (it throws an exception if the variant is not an 8 or 16-bit integer). + */ + BIT7Z_NODISCARD auto getInt16() const -> int16_t; + + /** + * @return the 32-bit integer value of this variant + * (it throws an exception if the variant is not an 8, 16 or 32-bit integer). + */ + BIT7Z_NODISCARD auto getInt32() const -> int32_t; + + /** + * @return the 64-bit integer value of this variant + * (it throws an exception if the variant is not an 8, 16, 32 or 64-bit integer). + */ + BIT7Z_NODISCARD auto getInt64() const -> int64_t; + + /** + * @return the FILETIME value of this variant + * (it throws an exception if the variant is not a filetime). + */ + BIT7Z_NODISCARD auto getFileTime() const -> FILETIME; + + /** + * @return the FILETIME value of this variant converted to std::time_point + * (it throws an exception if the variant is not a filetime). + */ + BIT7Z_NODISCARD auto getTimePoint() const -> time_type; + + /** + * @return the value of this variant converted from any supported type to std::wstring. + */ + BIT7Z_NODISCARD auto toString() const -> tstring; + + /** + * @return a boolean value indicating whether the variant is empty. + */ + BIT7Z_NODISCARD auto isEmpty() const noexcept -> bool; + + /** + * @return a boolean value indicating whether the variant is a boolean value. + */ + BIT7Z_NODISCARD auto isBool() const noexcept -> bool; + + /** + * @return a boolean value indicating whether the variant is a string. + */ + BIT7Z_NODISCARD auto isString() const noexcept -> bool; + + /** + * @return a boolean value indicating whether the variant is an 8-bit unsigned integer. + */ + BIT7Z_NODISCARD auto isUInt8() const noexcept -> bool; + + /** + * @return a boolean value indicating whether the variant is an 8 or 16-bit unsigned integer. + */ + BIT7Z_NODISCARD auto isUInt16() const noexcept -> bool; + + /** + * @return a boolean value indicating whether the variant is an 8, 16 or 32-bit unsigned integer. + */ + BIT7Z_NODISCARD auto isUInt32() const noexcept -> bool; + + /** + * @return a boolean value indicating whether the variant is an 8, 16, 32 or 64-bit unsigned integer. + */ + BIT7Z_NODISCARD auto isUInt64() const noexcept -> bool; + + /** + * @return a boolean value indicating whether the variant is an 8-bit integer. + */ + BIT7Z_NODISCARD auto isInt8() const noexcept -> bool; + + /** + * @return a boolean value indicating whether the variant is an 8 or 16-bit integer. + */ + BIT7Z_NODISCARD auto isInt16() const noexcept -> bool; + + /** + * @return a boolean value indicating whether the variant is an 8, 16 or 32-bit integer. + */ + BIT7Z_NODISCARD auto isInt32() const noexcept -> bool; + + /** + * @return a boolean value indicating whether the variant is an 8, 16, 32 or 64-bit integer. + */ + BIT7Z_NODISCARD auto isInt64() const noexcept -> bool; + + /** + * @return a boolean value indicating whether the variant is a FILETIME structure. + */ + BIT7Z_NODISCARD auto isFileTime() const noexcept -> bool; + + /** + * @return the BitPropVariantType of this variant. + */ + BIT7Z_NODISCARD auto type() const -> BitPropVariantType; + + /** + * @brief Clears the current value of the variant object + */ + void clear() noexcept; + + private: + void internalClear() noexcept; + + friend auto operator==( const BitPropVariant& lhs, const BitPropVariant& rhs ) noexcept -> bool; + + friend auto operator!=( const BitPropVariant& lhs, const BitPropVariant& rhs ) noexcept -> bool; +}; + +auto operator==( const BitPropVariant& lhs, const BitPropVariant& rhs ) noexcept -> bool; + +auto operator!=( const BitPropVariant& lhs, const BitPropVariant& rhs ) noexcept -> bool; + +} // namespace bit7z + +#endif // BITPROPVARIANT_HPP diff --git a/Minecraft.Client/Common/libs/bit7z/include/bitstreamcompressor.hpp b/Minecraft.Client/Common/libs/bit7z/include/bitstreamcompressor.hpp new file mode 100644 index 000000000..ea735b47f --- /dev/null +++ b/Minecraft.Client/Common/libs/bit7z/include/bitstreamcompressor.hpp @@ -0,0 +1,28 @@ +/* + * bit7z - A C++ static library to interface with the 7-zip shared libraries. + * Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef BITSTREAMCOMPRESSOR_HPP +#define BITSTREAMCOMPRESSOR_HPP + +#include "bitcompressor.hpp" + +namespace bit7z { + +/** + * @brief The BitStreamCompressor alias allows compressing data from standard input streams. + * The compressed archives can be saved to the filesystem, standard streams, or memory buffers. + * + * It let decide various properties of the produced archive, such as the password + * protection and the compression level desired. + */ +using BitStreamCompressor BIT7Z_MAYBE_UNUSED = BitCompressor< std::istream& >; + +} // namespace bit7z + +#endif // BITSTREAMCOMPRESSOR_HPP diff --git a/Minecraft.Client/Common/libs/bit7z/include/bitstreamextractor.hpp b/Minecraft.Client/Common/libs/bit7z/include/bitstreamextractor.hpp new file mode 100644 index 000000000..ae36435f5 --- /dev/null +++ b/Minecraft.Client/Common/libs/bit7z/include/bitstreamextractor.hpp @@ -0,0 +1,24 @@ +/* + * bit7z - A C++ static library to interface with the 7-zip shared libraries. + * Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef BITSTREAMEXTRACTOR_HPP +#define BITSTREAMEXTRACTOR_HPP + +#include "bitextractor.hpp" + +namespace bit7z { + +/** + * @brief The BitStreamExtractor alias allows extracting the content of in-memory archives. + */ +using BitStreamExtractor BIT7Z_MAYBE_UNUSED = BitExtractor< std::istream& >; + +} // namespace bit7z + +#endif // BITSTREAMEXTRACTOR_HPP diff --git a/Minecraft.Client/Common/libs/bit7z/include/bittypes.hpp b/Minecraft.Client/Common/libs/bit7z/include/bittypes.hpp new file mode 100644 index 000000000..b19003203 --- /dev/null +++ b/Minecraft.Client/Common/libs/bit7z/include/bittypes.hpp @@ -0,0 +1,130 @@ +/* + * bit7z - A C++ static library to interface with the 7-zip shared libraries. + * Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef BITTYPES_HPP +#define BITTYPES_HPP + +#include +#include + +// Must be included here since the user might have manually enabled a BIT7Z_* compilation option +// by uncommenting the corresponding macro define in bitdefines.hpp. +#include "bitdefines.hpp" + +#ifdef BIT7Z_REGEX_MATCHING +#include +#endif + +namespace bit7z { + +/** + * @brief A type representing a byte. + */ +#ifdef BIT7Z_USE_STD_BYTE +#if __cpp_lib_byte +using byte_t = std::byte; +#else +enum class byte_t : unsigned char {}; //same as std::byte_t +#endif +#else +using byte_t = unsigned char; +#endif + +/** @cond */ +using buffer_t = std::vector< byte_t >; +using index_t = std::ptrdiff_t; //like gsl::index (https://github.com/microsoft/GSL) + +template< class Char > +struct StringTraits; + +template<> +struct StringTraits< char > { + template< class T > + static inline auto convertToString( T value ) -> std::string { + return std::to_string( value ); + } +}; + +template<> +struct StringTraits< wchar_t > { + template< class T > + static inline auto convertToString( T value ) -> std::wstring { + return std::to_wstring( value ); + } +}; +/** @endcond */ + +/** + * Native string type of the system. + * @note On Windows, it is an alias of `std::wstring`. + */ +#ifdef _WIN32 +using native_string = std::wstring; +#define BIT7Z_NATIVE_STRING_( str ) L##str +#define BIT7Z_NATIVE_STRING( str ) BIT7Z_NATIVE_STRING_( str ) +#else +using native_string = std::string; +#define BIT7Z_NATIVE_STRING( str ) str +#endif +using native_char = native_string::value_type; + +/** + * @note On Windows, if the `BIT7Z_USE_NATIVE_STRING` option is enabled, `tchar` is an alias of `wchar_t`. + */ +#if defined( BIT7Z_USE_NATIVE_STRING ) && defined( _WIN32 ) // Windows with native strings +using tchar = wchar_t; +#define BIT7Z_STRING( str ) BIT7Z_NATIVE_STRING_( str ) +#else // Unix, and Windows with non-native strings +using tchar = char; +#define BIT7Z_STRING( str ) str +#endif + +/** + * @note On Windows, if the `BIT7Z_USE_NATIVE_STRING` option is enabled, `tstring` is an alias for std::wstring. + * Otherwise, it is an alias for std::string (default). + */ +using tstring = std::basic_string< tchar >; + +#ifdef BIT7Z_REGEX_MATCHING +/** + * @note On Windows, if the `BIT7Z_USE_NATIVE_STRING` option is enabled, `tregex` is an alias for std::wregex. + * Otherwise, it is an alias for std::regex (default). + */ +using tregex = std::basic_regex< tchar >; +#endif + +template< typename T, typename = typename std::enable_if::value, T>::type > +inline auto to_tstring( T arg ) -> std::basic_string< tchar > { + return StringTraits< tchar >::convertToString( arg ); +} + +/** + * Converts a native string to a tstring. + * + * @note On Linux or on Windows when BIT7Z_USE_NATIVE_STRING is used, + * both native_string and tstring are aliases of the same string type; + * in this case, no conversion is performed, and a const reference to the original string is returned. + * + * @param str The native string to be converted. + * + * @return the converted tstring. + */ +#if defined( _WIN32 ) && !defined( BIT7Z_USE_NATIVE_STRING ) +auto to_tstring( const native_string& str ) -> tstring; +#else +auto to_tstring( const native_string& str ) -> const tstring&; +#endif + +template< typename From, typename To > +using is_explicitly_convertible = std::integral_constant< bool, std::is_constructible< To, From >::value && + !std::is_convertible< From, To >::value >; + +} // namespace bit7z + +#endif // BITTYPES_HPP diff --git a/Minecraft.Client/Common/libs/bit7z/include/bitwindows.hpp b/Minecraft.Client/Common/libs/bit7z/include/bitwindows.hpp new file mode 100644 index 000000000..3a360aa02 --- /dev/null +++ b/Minecraft.Client/Common/libs/bit7z/include/bitwindows.hpp @@ -0,0 +1,159 @@ +/* + * bit7z - A C++ static library to interface with the 7-zip shared libraries. + * Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef BITWINDOWS_HPP +#define BITWINDOWS_HPP + +#ifdef _WIN32 +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +#ifndef NOMINMAX +#define NOMINMAX +#endif +#include +#include +#else + +/* We don't have the "Windows.h" header on Unix systems, so in theory, we could use the "MyWindows.h" of p7zip/7-zip. + * However, some of bit7z's public API headers need some Win32 API structs like PROPVARIANT and GUID. + * Hence, it would result in the leak of p7zip/7-zip headers, making bit7z's clients dependent on them. + * Also, (publicly) forward declaring them and then (internally) using the "MyWindows.h" is impossible: + * the two different declarations would conflict, making the compilation fail. + * + * To avoid all these issues, we define the required Win32 API structs, constants, and type aliases, + * with the same definitions in the MyWindows.h header. + * We will use only this header and avoid including "MyWindows.h" or similar headers (e.g., StdAfx.h). */ +#include +#include +#include + +// Avoiding accidentally including p7zip's MyWindows.h, so that its inclusion is not needed in client code! +#ifndef __MYWINDOWS_H +#define __MYWINDOWS_H // NOLINT +#endif + +// Avoiding accidentally including 7-zip's MyWindows.h, so that its inclusion is not needed in client code! +#ifndef __MY_WINDOWS_H +#define __MY_WINDOWS_H // NOLINT +#endif + +// Avoiding accidentally including 7-zip's MyWindows.h, so that its inclusion is not needed in client code! +#ifndef ZIP7_INC_MY_WINDOWS_H // 7-zip 23.01+ +#define ZIP7_INC_MY_WINDOWS_H +#endif + +using std::size_t; + +#define WINAPI + +namespace bit7z { + +// Win32 type aliases +using FARPROC = void*; +using HMODULE = void*; +using HRESULT = int; +using OLECHAR = wchar_t; +using BSTR = OLECHAR*; +using VARIANT_BOOL = short; +using VARTYPE = unsigned short; + +using WORD = unsigned short; +using DWORD = unsigned int; + +using ULONG = unsigned int; +using PROPID = ULONG; + +// Error codes constants can be useful for bit7z's clients on Unix (since they don't have the Windows.h header). + +#ifndef S_OK // Silencing cppcheck warning on E_NOTIMPL, probably a bug of cppcheck. +// Win32 HRESULT error codes. +constexpr auto S_OK = static_cast< HRESULT >( 0x00000000L ); +constexpr auto S_FALSE = static_cast< HRESULT >( 0x00000001L ); +constexpr auto E_NOTIMPL = static_cast< HRESULT >( 0x80004001L ); +constexpr auto E_NOINTERFACE = static_cast< HRESULT >( 0x80004002L ); +constexpr auto E_ABORT = static_cast< HRESULT >( 0x80004004L ); +constexpr auto E_FAIL = static_cast< HRESULT >( 0x80004005L ); +constexpr auto STG_E_INVALIDFUNCTION = static_cast< HRESULT >( 0x80030001L ); +constexpr auto E_OUTOFMEMORY = static_cast< HRESULT >( 0x8007000EL ); +constexpr auto E_INVALIDARG = static_cast< HRESULT >( 0x80070057L ); +#endif + +#ifndef ERROR_ALREADY_EXISTS +// Win32 error codes (defined by both p7zip and 7-zip as equivalent to POSIX error codes). +constexpr auto ERROR_ALREADY_EXISTS = EEXIST; +constexpr auto ERROR_DISK_FULL = ENOSPC; +constexpr auto ERROR_FILE_EXISTS = EEXIST; +constexpr auto ERROR_FILE_NOT_FOUND = ENOENT; +constexpr auto ERROR_INVALID_PARAMETER = EINVAL; +constexpr auto ERROR_INVALID_FUNCTION = EINVAL; +constexpr auto ERROR_INVALID_HANDLE = EBADF; +constexpr auto ERROR_OPEN_FAILED = EIO; +constexpr auto ERROR_PATH_NOT_FOUND = ENOENT; +constexpr auto ERROR_SEEK = EIO; +constexpr auto ERROR_READ_FAULT = EIO; +constexpr auto ERROR_WRITE_FAULT = EIO; + +// Win32 error codes (defined by p7zip with the same values as in Windows API). +constexpr auto ERROR_NO_MORE_FILES = 0x100018; +constexpr auto ERROR_DIRECTORY = 267; +#endif + +#ifndef CP_UTF8 +// Win32 codepages +constexpr auto CP_UTF8 = 65001u; +#endif + +// Win32 structs. +struct FILETIME { + DWORD dwLowDateTime; + DWORD dwHighDateTime; +}; + +struct LARGE_INTEGER { + int64_t QuadPart; +}; + +struct ULARGE_INTEGER { + uint64_t QuadPart; +}; + +struct PROPVARIANT { + VARTYPE vt; + WORD wReserved1; + WORD wReserved2; + WORD wReserved3; + union { +#if defined( __arm__ ) || defined( __aarch64__ ) + signed char cVal; +#else + char cVal; +#endif + unsigned char bVal; + short iVal; + unsigned short uiVal; + int lVal; + unsigned int ulVal; + int intVal; + unsigned int uintVal; + LARGE_INTEGER hVal; + ULARGE_INTEGER uhVal; + VARIANT_BOOL boolVal; + int scode; + FILETIME filetime; + BSTR bstrVal; + }; +}; + +} // namespace bit7z + +#endif + +#endif //BITWINDOWS_HPP diff --git a/Minecraft.Client/Minecraft.Client.vcxproj b/Minecraft.Client/Minecraft.Client.vcxproj index 8f2547d83..152b8a568 100644 --- a/Minecraft.Client/Minecraft.Client.vcxproj +++ b/Minecraft.Client/Minecraft.Client.vcxproj @@ -3650,6 +3650,11 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CU + + true + true + Document + XML @@ -5822,6 +5827,39 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CUtrue true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -43593,6 +43631,12 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CU + + false + + + false + true true @@ -48710,9 +48754,6 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CUtrue - - - diff --git a/Minecraft.Client/Minecraft.Client.vcxproj.filters b/Minecraft.Client/Minecraft.Client.vcxproj.filters index 0f02a16bc..a0d45792b 100644 --- a/Minecraft.Client/Minecraft.Client.vcxproj.filters +++ b/Minecraft.Client/Minecraft.Client.vcxproj.filters @@ -732,6 +732,24 @@ {c79fd64d-7529-4da4-b5f3-2541e084932b} + + {280237d6-cf3a-418c-990d-30c98fe24dae} + + + {c05c44be-8378-4b7a-b3b6-25980dd2e212} + + + {d47a8022-a3e9-4ce4-8176-4779d6e9512d} + + + {4ed3fe84-3f44-4ec9-97f4-258c9b41fab7} + + + {3c65b1f9-fa53-4956-9e9f-f43bd0ba8a6d} + + + {66652ea1-d6b0-403d-800b-0609c3691785} + @@ -3790,6 +3808,105 @@ Common\Source Files\Audio + + Common\Source Files\libs\bit7z\include + + + Common\Source Files\libs\bit7z\include + + + Common\Source Files\libs\bit7z\include + + + Common\Source Files\libs\bit7z\include + + + Common\Source Files\libs\bit7z\include + + + Common\Source Files\libs\bit7z\include + + + Common\Source Files\libs\bit7z\include + + + Common\Source Files\libs\bit7z\include + + + Common\Source Files\libs\bit7z\include + + + Common\Source Files\libs\bit7z\include + + + Common\Source Files\libs\bit7z\include + + + Common\Source Files\libs\bit7z\include + + + Common\Source Files\libs\bit7z\include + + + Common\Source Files\libs\bit7z\include + + + Common\Source Files\libs\bit7z\include + + + Common\Source Files\libs\bit7z\include + + + Common\Source Files\libs\bit7z\include + + + Common\Source Files\libs\bit7z\include + + + Common\Source Files\libs\bit7z\include + + + Common\Source Files\libs\bit7z\include + + + Common\Source Files\libs\bit7z\include + + + Common\Source Files\libs\bit7z\include + + + Common\Source Files\libs\bit7z\include + + + Common\Source Files\libs\bit7z\include + + + Common\Source Files\libs\bit7z\include + + + Common\Source Files\libs\bit7z\include + + + Common\Source Files\libs\bit7z\include + + + Common\Source Files\libs\bit7z\include + + + Common\Source Files\libs\bit7z\include + + + Common\Source Files\libs\bit7z\include + + + Common\Source Files\libs\bit7z\include + + + Common\Source Files\libs\bit7z\include + + + Common\Source Files\libs\bit7z\include + @@ -6176,6 +6293,13 @@ Xbox\4JLibs\libs + + Common\Source Files\libs\bit7z\lib\Debug + + + Common\Source Files\libs\bit7z\lib\Release + +