Skip to content

Commit

Permalink
Merge branch 'hotfix/v4.0.5'
Browse files Browse the repository at this point in the history
  • Loading branch information
rikyoz committed Dec 22, 2023
2 parents 3401ca9 + 27e8722 commit b602b43
Show file tree
Hide file tree
Showing 18 changed files with 118 additions and 92 deletions.
37 changes: 18 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ try { // bit7z classes can throw BitException objects
// Extracting a simple archive
extractor.extract( "path/to/archive.7z", "out/dir/" );

// Extracting a specific file
// Extracting a specific file inside an archive
extractor.extractMatching( "path/to/archive.7z", "file.pdf", "out/dir/" );

// Extracting the first file of an archive to a buffer
Expand Down Expand Up @@ -177,28 +177,27 @@ try { // bit7z classes can throw BitException objects
BitArchiveReader arc{ lib, "archive.7z", BitFormat::SevenZip };

// Printing archive metadata
std::cout << "Archive properties" << std::endl;
std::cout << " Items count: " << arc.itemsCount() << std::endl;
std::cout << " Folders count: " << arc.foldersCount() << std::endl;
std::cout << " Files count: " << arc.filesCount() << std::endl;
std::cout << " Size: " << arc.size() << std::endl;
std::cout << " Packed size: " << arc.packSize() << std::endl;
std::cout << std::endl;
std::cout << "Archive properties\n";
std::cout << " Items count: " << arc.itemsCount() << '\n';
std::cout << " Folders count: " << arc.foldersCount() << '\n';
std::cout << " Files count: " << arc.filesCount() << '\n';
std::cout << " Size: " << arc.size() <<'\n';
std::cout << " Packed size: " << arc.packSize() << "\n\n";

// Printing the metadata of the archived items
std::cout << "Archived items";
auto arc_items = arc.items();
for ( auto& item : arc_items ) {
std::cout << std::endl;
std::cout << " Item index: " << item.index() << std::endl;
std::cout << " Name: " << item.name() << std::endl;
std::cout << " Extension: " << item.extension() << std::endl;
std::cout << " Path: " << item.path() << std::endl;
std::cout << " IsDir: " << item.isDir() << std::endl;
std::cout << " Size: " << item.size() << std::endl;
std::cout << " Packed size: " << item.packSize() << std::endl;
std::cout << " CRC: " << item.crc() << std::endl;
for ( const auto& item : arc ) {
std::cout << '\n';
std::cout << " Item index: " << item.index() << '\n';
std::cout << " Name: " << item.name() << '\n';
std::cout << " Extension: " << item.extension() << '\n';
std::cout << " Path: " << item.path() << '\n';
std::cout << " IsDir: " << item.isDir() << '\n';
std::cout << " Size: " << item.size() << '\n';
std::cout << " Packed size: " << item.packSize() << '\n';
std::cout << " CRC: " << std::hex << item.crc() << std::dec << '\n';
}
std::cout.flush();
} catch ( const bit7z::BitException& ex ) { /* Do something with ex.what()...*/ }
```
Expand Down
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ deploy:
tag: $(APPVEYOR_REPO_TAG_NAME)
description: 'Binaries of Bit7z %bit7z_version%'
auth_token:
secure: +dbEuB5+rqsaUx/pMZVdKBpFvgN/E8/ZayhzgsfHnypYI1JnGGSpN3enE5Fvx5Oq
secure: 5b0wRmYrS2S5MEu+5rslOkBY//wJ+ShwhxNeOhxaAaMjTYRbSDqe4cme0CukKSgp
artifact: /.*\.7z/
draft: true
prerelease: false
Expand Down
3 changes: 3 additions & 0 deletions cmake/BuildOptions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ if( BIT7Z_DISABLE_ZIP_ASCII_PWD_CHECK )
target_compile_definitions( ${LIB_TARGET} PRIVATE BIT7Z_DISABLE_ZIP_ASCII_PWD_CHECK )
endif()

option( BIT7Z_DISABLE_USE_STD_FILESYSTEM "Disable using the standard filesystem library (always use ghc::filesystem)" )
message( STATUS "Disable using std::filesystem: ${BIT7Z_DISABLE_USE_STD_FILESYSTEM}" )

set( BIT7Z_CUSTOM_7ZIP_PATH "" CACHE STRING "A custom path to the 7-zip source code" )
if( NOT BIT7Z_CUSTOM_7ZIP_PATH STREQUAL "" )
if( NOT EXISTS ${BIT7Z_CUSTOM_7ZIP_PATH}/CPP AND NOT EXISTS ${BIT7Z_CUSTOM_7ZIP_PATH}/DOC/readme.txt )
Expand Down
4 changes: 3 additions & 1 deletion cmake/CompilerOptions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,10 @@ if( MSVC )
set( CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /nologo" )

# options only for specific MSVC versions
if( MSVC_VERSION GREATER_EQUAL 1910 ) # MSVC >= 15.0 (VS 2017)
if( MSVC_VERSION GREATER_EQUAL 1914 ) # MSVC >= 15.7 (VS 2017)
target_compile_options( ${LIB_TARGET} PRIVATE /Zc:__cplusplus )
endif()
if( MSVC_VERSION GREATER_EQUAL 1910 ) # MSVC >= 15.0 (VS 2017)
# treating warnings as errors
target_compile_options( ${LIB_TARGET} PRIVATE /WX )
else() # MSVC < 15.0 (i.e., <= VS 2015)
Expand Down
2 changes: 1 addition & 1 deletion cmake/FilesystemDetect.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

# checking if compiler supports the standard filesystem library

if( MINGW )
if( MINGW OR BIT7Z_DISABLE_USE_STD_FILESYSTEM )
# Some versions of MinGW have a buggy std::filesystem that doesn't correctly handle paths with unicode characters,
# so we are always using the ghc::filesystem library.
set( USE_STANDARD_FILESYSTEM OFF )
Expand Down
1 change: 1 addition & 0 deletions include/bit7z/biterror.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ enum struct BitError {
NoMatchingItems,
NoMatchingSignature,
NonEmptyOutputBuffer,
NullOutputBuffer,
RequestedWrongVariantType,
UnsupportedOperation,
UnsupportedVariantType,
Expand Down
12 changes: 0 additions & 12 deletions include/bit7z/bitextractor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,18 +160,6 @@ class BitExtractor final : public BitAbstractArchiveOpener {
}

BitInputArchive inputArchive( *this, inArchive );
uint32_t nItems = inputArchive.itemsCount();
// Find if any index passed by the user is not in the valid range [0, itemsCount() - 1]
const auto findRes = std::find_if( indices.cbegin(),
indices.cend(),
[ &nItems ]( uint32_t index ) -> bool {
return index >= nItems;
} );
if ( findRes != indices.cend() ) {
throw BitException( "Cannot extract item at the index " + std::to_string( *findRes ),
make_error_code( BitError::InvalidIndex ) );
}

inputArchive.extractTo( outDir, indices );
}

Expand Down
9 changes: 8 additions & 1 deletion include/bit7z/bitinputarchive.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,20 @@ class BitInputArchive {
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;
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 {
Expand Down
2 changes: 1 addition & 1 deletion include/bit7z/bitpropvariant.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ struct BitPropVariant final : public PROPVARIANT {
*/
template< typename T >
auto operator=( const T& value ) noexcept( std::is_integral< T >::value ) -> BitPropVariant& {
*this = BitPropVariant( value );
*this = BitPropVariant{ value };
return *this;
}

Expand Down
42 changes: 37 additions & 5 deletions src/bitinputarchive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,14 +137,14 @@ BitInputArchive::BitInputArchive( const BitAbstractArchiveHandler& handler, cons
: mDetectedFormat{ &handler.format() }, // if auto, detect the format from content, otherwise try the passed format.
mArchiveHandler{ handler } {
auto bufStream = bit7z::make_com< CBufferInStream, IInStream >( inBuffer );
mInArchive = openArchiveStream( BIT7Z_STRING( "." ), bufStream );
mInArchive = openArchiveStream( fs::path{}, bufStream );
}

BitInputArchive::BitInputArchive( const BitAbstractArchiveHandler& handler, std::istream& inStream )
: mDetectedFormat{ &handler.format() }, // if auto, detect the format from content, otherwise try the passed format.
mArchiveHandler{ handler } {
auto stdStream = bit7z::make_com< CStdInStream, IInStream >( inStream );
mInArchive = openArchiveStream( BIT7Z_STRING( "." ), stdStream );
mInArchive = openArchiveStream( fs::path{}, stdStream );
}

auto BitInputArchive::archiveProperty( BitProperty property ) const -> BitPropVariant {
Expand All @@ -164,7 +164,15 @@ auto BitInputArchive::itemProperty( uint32_t index, BitProperty property ) const
make_hresult_code( res ) );
}
if ( property == BitProperty::Path && itemProperty.isEmpty() && itemsCount() == 1 ) {
itemProperty = path_to_wide_string( tstring_to_path( mArchivePath ).stem() );
auto itemPath = tstring_to_path( mArchivePath );
if ( itemPath.empty() ) {
itemProperty = kEmptyFileWideAlias;
} else {
if ( *mDetectedFormat != BitFormat::Split && itemPath.extension() == ".001" ) {
itemPath = itemPath.stem();
}
itemProperty = path_to_wide_string( itemPath.stem() );
}
}
return itemProperty;
}
Expand Down Expand Up @@ -211,7 +219,26 @@ auto BitInputArchive::handler() const noexcept -> const BitAbstractArchiveHandle
return mArchiveHandler;
}

void BitInputArchive::extractTo( const tstring& outDir ) const {
auto callback = bit7z::make_com< FileExtractCallback, ExtractCallback >( *this, outDir );
extract_arc( mInArchive, {}, callback );
}

inline auto findInvalidIndex( const std::vector< uint32_t >& indices,
uint32_t itemsCount ) -> std::vector< uint32_t >::const_iterator {
return std::find_if( indices.cbegin(), indices.cend(), [&]( uint32_t index ) -> bool {
return index >= itemsCount;
});
}

void BitInputArchive::extractTo( const tstring& outDir, const std::vector< uint32_t >& indices ) const {
// Find if any index passed by the user is not in the valid range [0, itemsCount() - 1]
const auto invalidIndex = findInvalidIndex( indices, itemsCount() );
if ( invalidIndex != indices.cend() ) {
throw BitException( "Cannot extract item at the index " + std::to_string( *invalidIndex ),
make_error_code( BitError::InvalidIndex ) );
}

auto callback = bit7z::make_com< FileExtractCallback, ExtractCallback >( *this, outDir );
extract_arc( mInArchive, indices, callback );
}
Expand Down Expand Up @@ -253,14 +280,19 @@ void BitInputArchive::extractTo( std::ostream& outStream, uint32_t index ) const
}

void BitInputArchive::extractTo( byte_t* buffer, std::size_t size, uint32_t index ) const {
if ( buffer == nullptr ) {
throw BitException( "Cannot extract the item at the index " + std::to_string( index ) + " to the buffer",
make_error_code( BitError::NullOutputBuffer ) );
}

const uint32_t numberItems = itemsCount();
if ( index >= numberItems ) {
throw BitException( "Cannot extract item at the index " + std::to_string( index ),
throw BitException( "Cannot extract the item at the index " + std::to_string( index ) + " to the buffer",
make_error_code( BitError::InvalidIndex ) );
}

if ( isItemFolder( index ) ) { // Consider only files, not folders
throw BitException( "Cannot extract item at the index " + std::to_string( index ) + " to the buffer",
throw BitException( "Cannot extract the item at the index " + std::to_string( index ) + " to the buffer",
make_error_code( BitError::ItemIsAFolder ) );
}

Expand Down
7 changes: 6 additions & 1 deletion src/internal/cfixedbufferoutstream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/

#include <algorithm> //for std::copy_n
#ifdef _MSC_VER
#define _SCL_SECURE_NO_WARNINGS
#endif

#include <algorithm> // for std::copy_n

#include "biterror.hpp"
#include "bitexception.hpp"
Expand Down Expand Up @@ -87,6 +91,7 @@ STDMETHODIMP CFixedBufferOutStream::Write( const void* data, UInt32 size, UInt32

const auto* byteData = static_cast< const byte_t* >( data ); //-V2571
try {
// TODO: Use std::span, gsl::span, or a custom span class (e.g., BufferView).
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
std::copy_n( byteData, writeSize, &mBuffer[ mCurrentPosition ] ); //-V2563
} catch ( ... ) {
Expand Down
1 change: 1 addition & 0 deletions src/internal/extractcallback.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ using namespace NArchive::NExtract;
namespace bit7z {

constexpr auto kEmptyFileAlias = BIT7Z_STRING( "[Content]" );
constexpr auto kEmptyFileWideAlias = L"[Content]";

enum struct ExtractMode {
Extract = NAskMode::kExtract,
Expand Down
7 changes: 6 additions & 1 deletion src/internal/fsutil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
#include <unistd.h>

#include "internal/dateutil.hpp"

// For some reason, GCC on macOS requires including <climits> for defining OPEN_MAX.
#if defined( __APPLE__ ) && !defined( __clang__ )
#include <climits>
#endif
#elif defined( BIT7Z_PATH_SANITIZATION )
#include <cwctype> // for iswdigit
#endif
Expand Down Expand Up @@ -199,7 +204,7 @@ auto fsutil::set_file_attributes( const fs::path& filePath, DWORD attributes ) n
}

if ( ( attributes & FILE_ATTRIBUTE_UNIX_EXTENSION ) != 0 ) {
fileStat.st_mode = attributes >> 16U;
fileStat.st_mode = static_cast< mode_t >( attributes >> 16U );
if ( S_ISLNK( fileStat.st_mode ) ) {
return restore_symlink( filePath );
}
Expand Down
3 changes: 3 additions & 0 deletions src/internal/internalcategory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ auto InternalCategory::message( int errorValue ) const -> std::string {
return "No known signature found.";
case BitError::NonEmptyOutputBuffer:
return "The output buffer is not empty.";
case BitError::NullOutputBuffer:
return "Null output buffer.";
case BitError::RequestedWrongVariantType:
return "Requested the wrong variant type.";
case BitError::UnsupportedOperation:
Expand Down Expand Up @@ -79,6 +81,7 @@ auto InternalCategory::default_error_condition( int errorValue ) const noexcept
case BitError::InvalidWordSize:
case BitError::ItemIsAFolder:
case BitError::NonEmptyOutputBuffer:
case BitError::NullOutputBuffer:
case BitError::InvalidZipPassword:
return std::make_error_condition( std::errc::invalid_argument );
case BitError::NoMatchingItems:
Expand Down
49 changes: 11 additions & 38 deletions src/internal/opencallback.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,15 @@
#include "internal/stringutil.hpp"
#include "internal/util.hpp"

#include <utility>

namespace bit7z {

OpenCallback::OpenCallback( const BitAbstractArchiveHandler& handler, const fs::path& filename )
: Callback( handler ), mSubArchiveMode( false ), mFileItem( filename ), mPasswordWasAsked{ false } {}
OpenCallback::OpenCallback( const BitAbstractArchiveHandler& handler, fs::path archivePath )
: Callback( handler ),
mSubArchiveMode( false ),
mArchivePath{ std::move( archivePath ) },
mPasswordWasAsked{ false } {}

COM_DECLSPEC_NOTHROW
STDMETHODIMP OpenCallback::SetTotal( const UInt64* /* files */, const UInt64* /* bytes */ ) noexcept {
Expand All @@ -34,40 +39,11 @@ STDMETHODIMP OpenCallback::SetCompleted( const UInt64* /* files */, const UInt64
COM_DECLSPEC_NOTHROW
STDMETHODIMP OpenCallback::GetProperty( PROPID property, PROPVARIANT* value ) noexcept try {
BitPropVariant prop;
if ( mSubArchiveMode ) {
if ( property == kpidName ) {
prop = mSubArchiveName;
// case kpidSize: prop = _subArchiveSize; break; // we don't use it for now.
}
} else {
switch ( property ) {
case kpidName:
prop = path_to_wide_string( mFileItem.filesystemName() );
break;
case kpidIsDir:
prop = mFileItem.isDir();
break;
case kpidSize:
prop = mFileItem.size();
break;
case kpidAttrib:
prop = mFileItem.attributes();
break;
case kpidCTime:
prop = mFileItem.creationTime();
break;
case kpidATime:
prop = mFileItem.lastAccessTime();
break;
case kpidMTime:
prop = mFileItem.lastWriteTime();
break;
default: //prop is empty
break;
}
if ( property == kpidName ) {
prop = mSubArchiveMode ? mSubArchiveName : path_to_wide_string( mArchivePath.filename() );
}
*value = prop;
prop.bstrVal = nullptr;
prop.bstrVal = nullptr; // NOLINT(*-pro-type-union-access)
return S_OK;
} catch ( const BitException& ex ) {
return ex.hresultCode();
Expand All @@ -80,10 +56,7 @@ STDMETHODIMP OpenCallback::GetStream( const wchar_t* name, IInStream** inStream
if ( mSubArchiveMode ) {
return S_FALSE;
}
if ( mFileItem.isDir() ) {
return S_FALSE;
}
fs::path streamPath = mFileItem.filesystemPath();
fs::path streamPath = mArchivePath;
if ( name != nullptr ) {
streamPath = streamPath.parent_path();
streamPath.append( name );
Expand Down
5 changes: 2 additions & 3 deletions src/internal/opencallback.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ class OpenCallback final : public IArchiveOpenCallback,
public ICryptoGetTextPassword,
public Callback {
public:
explicit OpenCallback( const BitAbstractArchiveHandler& handler,
const fs::path& filename = BIT7Z_STRING( "." ) );
explicit OpenCallback( const BitAbstractArchiveHandler& handler, fs::path archivePath = fs::path{} );

OpenCallback( const OpenCallback& ) = delete;

Expand Down Expand Up @@ -67,7 +66,7 @@ class OpenCallback final : public IArchiveOpenCallback,
private:
bool mSubArchiveMode;
std::wstring mSubArchiveName;
FilesystemItem mFileItem;
fs::path mArchivePath;
bool mPasswordWasAsked;
};

Expand Down
Loading

0 comments on commit b602b43

Please sign in to comment.