diff --git a/Cartfile.resolved b/Cartfile.resolved index 145a4d4..9457c9c 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1,3 +1,3 @@ -github "abbeycode/UnrarKit" "2.9" +github "abbeycode/UnrarKit" "2.10" github "abbeycode/UnzipKit" "1.9" github "sindresorhus/DockProgress" "v3.2.0" diff --git a/Carthage/Build/.DockProgress.version b/Carthage/Build/.DockProgress.version index ce0bf86..2de2d76 100644 --- a/Carthage/Build/.DockProgress.version +++ b/Carthage/Build/.DockProgress.version @@ -2,10 +2,10 @@ "commitish" : "v3.2.0", "Mac" : [ { - "hash" : "13e7fe07ca491fe900ae7c858e66797a66d0a2e1dffde3a2c0b64188b211012e", + "hash" : "19676367de93b3ec3bc61b60e454d565ca1c47fe32c4116ef78955c7ecdfcd1e", "name" : "DockProgress", "linking" : "dynamic", - "swiftToolchainVersion" : "5.4 (swiftlang-1205.0.26.9 clang-1205.0.19.55)" + "swiftToolchainVersion" : "5.6 (swiftlang-5.6.0.323.62 clang-1316.0.20.8)" } ] } \ No newline at end of file diff --git a/Carthage/Build/.UnrarKit.version b/Carthage/Build/.UnrarKit.version index ba37cb6..672368e 100644 --- a/Carthage/Build/.UnrarKit.version +++ b/Carthage/Build/.UnrarKit.version @@ -2,7 +2,7 @@ "Mac" : [ { "name" : "UnrarKit", - "hash" : "0ee8db439c431777277ec76976faa8a1d19ba93d3f6977094746350e942215d3", + "hash" : "e18e69a1e9f0344776a442bf542e0a45be0427977b765897399058bb766e83db", "linking" : "dynamic" } ], @@ -12,11 +12,11 @@ "tvOS" : [ ], - "commitish" : "2.9", + "commitish" : "2.10", "iOS" : [ { "name" : "UnrarKit", - "hash" : "2c752a88c360be277b938f55190d07bc6688ce0452932b4fbf52a12e9bfcf5d0", + "hash" : "308b414f23c29d8599f7b214fb8ef39ea574ac8117b21b6946a7c969b9cf38b4", "linking" : "dynamic" } ] diff --git a/Carthage/Build/Mac/DockProgress.framework.dSYM/Contents/Resources/DWARF/DockProgress b/Carthage/Build/Mac/DockProgress.framework.dSYM/Contents/Resources/DWARF/DockProgress index 5c1abd4..5be8595 100644 Binary files a/Carthage/Build/Mac/DockProgress.framework.dSYM/Contents/Resources/DWARF/DockProgress and b/Carthage/Build/Mac/DockProgress.framework.dSYM/Contents/Resources/DWARF/DockProgress differ diff --git a/Carthage/Build/Mac/DockProgress.framework/Versions/A/DockProgress b/Carthage/Build/Mac/DockProgress.framework/Versions/A/DockProgress index 661f474..cd2aa90 100755 Binary files a/Carthage/Build/Mac/DockProgress.framework/Versions/A/DockProgress and b/Carthage/Build/Mac/DockProgress.framework/Versions/A/DockProgress differ diff --git a/Carthage/Build/Mac/DockProgress.framework/Versions/A/Headers/DockProgress-Swift.h b/Carthage/Build/Mac/DockProgress.framework/Versions/A/Headers/DockProgress-Swift.h index 6c8dac0..16e39b8 100644 --- a/Carthage/Build/Mac/DockProgress.framework/Versions/A/Headers/DockProgress-Swift.h +++ b/Carthage/Build/Mac/DockProgress.framework/Versions/A/Headers/DockProgress-Swift.h @@ -1,6 +1,6 @@ #if 0 #elif defined(__arm64__) && __arm64__ -// Generated by Apple Swift version 5.4 (swiftlang-1205.0.26.9 clang-1205.0.19.55) +// Generated by Apple Swift version 5.6 (swiftlang-5.6.0.323.62 clang-1316.0.20.8) #ifndef DOCKPROGRESS_SWIFT_H #define DOCKPROGRESS_SWIFT_H #pragma clang diagnostic push @@ -186,6 +186,13 @@ typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4))); #if !defined(IBSegueAction) # define IBSegueAction #endif +#if !defined(SWIFT_EXTERN) +# if defined(__cplusplus) +# define SWIFT_EXTERN extern "C" +# else +# define SWIFT_EXTERN extern +# endif +#endif #if __has_feature(modules) #if __has_warning("-Watimport-in-framework-header") #pragma clang diagnostic ignored "-Watimport-in-framework-header" @@ -221,7 +228,7 @@ typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4))); #endif #elif defined(__x86_64__) && __x86_64__ -// Generated by Apple Swift version 5.4 (swiftlang-1205.0.26.9 clang-1205.0.19.55) +// Generated by Apple Swift version 5.6 (swiftlang-5.6.0.323.62 clang-1316.0.20.8) #ifndef DOCKPROGRESS_SWIFT_H #define DOCKPROGRESS_SWIFT_H #pragma clang diagnostic push @@ -407,6 +414,13 @@ typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4))); #if !defined(IBSegueAction) # define IBSegueAction #endif +#if !defined(SWIFT_EXTERN) +# if defined(__cplusplus) +# define SWIFT_EXTERN extern "C" +# else +# define SWIFT_EXTERN extern +# endif +#endif #if __has_feature(modules) #if __has_warning("-Watimport-in-framework-header") #pragma clang diagnostic ignored "-Watimport-in-framework-header" diff --git a/Carthage/Build/Mac/DockProgress.framework/Versions/A/Modules/DockProgress.swiftmodule/arm64-apple-macos.swiftdoc b/Carthage/Build/Mac/DockProgress.framework/Versions/A/Modules/DockProgress.swiftmodule/arm64-apple-macos.swiftdoc index eb5053c..e89e249 100644 Binary files a/Carthage/Build/Mac/DockProgress.framework/Versions/A/Modules/DockProgress.swiftmodule/arm64-apple-macos.swiftdoc and b/Carthage/Build/Mac/DockProgress.framework/Versions/A/Modules/DockProgress.swiftmodule/arm64-apple-macos.swiftdoc differ diff --git a/Carthage/Build/Mac/DockProgress.framework/Versions/A/Modules/DockProgress.swiftmodule/arm64-apple-macos.swiftmodule b/Carthage/Build/Mac/DockProgress.framework/Versions/A/Modules/DockProgress.swiftmodule/arm64-apple-macos.swiftmodule index 512a204..fd94511 100644 Binary files a/Carthage/Build/Mac/DockProgress.framework/Versions/A/Modules/DockProgress.swiftmodule/arm64-apple-macos.swiftmodule and b/Carthage/Build/Mac/DockProgress.framework/Versions/A/Modules/DockProgress.swiftmodule/arm64-apple-macos.swiftmodule differ diff --git a/Carthage/Build/Mac/DockProgress.framework/Versions/A/Modules/DockProgress.swiftmodule/x86_64-apple-macos.swiftdoc b/Carthage/Build/Mac/DockProgress.framework/Versions/A/Modules/DockProgress.swiftmodule/x86_64-apple-macos.swiftdoc index 3d42eac..2efe353 100644 Binary files a/Carthage/Build/Mac/DockProgress.framework/Versions/A/Modules/DockProgress.swiftmodule/x86_64-apple-macos.swiftdoc and b/Carthage/Build/Mac/DockProgress.framework/Versions/A/Modules/DockProgress.swiftmodule/x86_64-apple-macos.swiftdoc differ diff --git a/Carthage/Build/Mac/DockProgress.framework/Versions/A/Modules/DockProgress.swiftmodule/x86_64-apple-macos.swiftmodule b/Carthage/Build/Mac/DockProgress.framework/Versions/A/Modules/DockProgress.swiftmodule/x86_64-apple-macos.swiftmodule index 71c14e4..4bc7c54 100644 Binary files a/Carthage/Build/Mac/DockProgress.framework/Versions/A/Modules/DockProgress.swiftmodule/x86_64-apple-macos.swiftmodule and b/Carthage/Build/Mac/DockProgress.framework/Versions/A/Modules/DockProgress.swiftmodule/x86_64-apple-macos.swiftmodule differ diff --git a/Carthage/Build/Mac/DockProgress.framework/Versions/A/Resources/Info.plist b/Carthage/Build/Mac/DockProgress.framework/Versions/A/Resources/Info.plist index 422ce73..5b1d695 100644 --- a/Carthage/Build/Mac/DockProgress.framework/Versions/A/Resources/Info.plist +++ b/Carthage/Build/Mac/DockProgress.framework/Versions/A/Resources/Info.plist @@ -3,7 +3,7 @@ BuildMachineOSBuild - 20E241 + 21F5048e CFBundleExecutable DockProgress CFBundleIdentifier @@ -23,19 +23,19 @@ DTCompiler com.apple.compilers.llvm.clang.1_0 DTPlatformBuild - 12E262 + 13E500a DTPlatformName macosx DTPlatformVersion - 11.3 + 12.3 DTSDKBuild - 20E214 + 21E226 DTSDKName - macosx11.3 + macosx12.3 DTXcode - 1250 + 1331 DTXcodeBuild - 12E262 + 13E500a LSMinimumSystemVersion 10.12 diff --git a/Carthage/Build/Mac/UnrarKit.framework.dSYM/Contents/Info.plist b/Carthage/Build/Mac/UnrarKit.framework.dSYM/Contents/Info.plist index c7fe283..cf0c25f 100644 --- a/Carthage/Build/Mac/UnrarKit.framework.dSYM/Contents/Info.plist +++ b/Carthage/Build/Mac/UnrarKit.framework.dSYM/Contents/Info.plist @@ -13,8 +13,8 @@ CFBundleSignature ???? CFBundleShortVersionString - 2.9 + 2.10-beta8 CFBundleVersion - 2.9 + 2.10-beta8 diff --git a/Carthage/Build/Mac/UnrarKit.framework.dSYM/Contents/Resources/DWARF/UnrarKit b/Carthage/Build/Mac/UnrarKit.framework.dSYM/Contents/Resources/DWARF/UnrarKit index ca76e96..9ee2500 100644 Binary files a/Carthage/Build/Mac/UnrarKit.framework.dSYM/Contents/Resources/DWARF/UnrarKit and b/Carthage/Build/Mac/UnrarKit.framework.dSYM/Contents/Resources/DWARF/UnrarKit differ diff --git a/Carthage/Build/Mac/UnrarKit.framework/Versions/A/Headers/URKArchive.h b/Carthage/Build/Mac/UnrarKit.framework/Versions/A/Headers/URKArchive.h index bd064cb..367862d 100644 --- a/Carthage/Build/Mac/UnrarKit.framework/Versions/A/Headers/URKArchive.h +++ b/Carthage/Build/Mac/UnrarKit.framework/Versions/A/Headers/URKArchive.h @@ -6,14 +6,14 @@ #import #import -#import "UnrarKitMacros.h" +#import RarosHppIgnore -#import "raros.hpp" +#import #pragma clang diagnostic pop DllHppIgnore -#import "dll.hpp" +#import #pragma clang diagnostic pop @class URKFileInfo; @@ -25,7 +25,7 @@ DllHppIgnore typedef NS_ENUM(NSInteger, URKErrorCode) { /** - * The archive's header is empty + * The last file of the archive has been read */ URKErrorCodeEndOfArchive = ERAR_END_ARCHIVE, @@ -35,7 +35,7 @@ typedef NS_ENUM(NSInteger, URKErrorCode) { URKErrorCodeNoMemory = ERAR_NO_MEMORY, /** - * The header is broken + * The header's CRC doesn't match the decompressed data's CRC */ URKErrorCodeBadData = ERAR_BAD_DATA, @@ -173,6 +173,17 @@ extern NSString *URKErrorDomain; */ @property(nullable, strong) NSProgress *progress; +/** + * When performing operations on a RAR archive, the contents of compressed files are checked + * against the record of what they were when the archive was created. If there's a mismatch, + * either the metadata (header) or archive contents have become corrupted. You can defeat this check by + * setting this property to YES, though there may be security implications to turning the + * warnings off, as it may indicate a maliciously crafted archive intended to exploit a vulnerability. + * + * It's recommended to leave the decision of how to treat archives with mismatched CRCs to the user + */ +@property (assign) BOOL ignoreCRCMismatches; + /** * **DEPRECATED:** Creates and returns an archive at the given path @@ -475,15 +486,34 @@ extern NSString *URKErrorDomain; - (BOOL)validatePassword; /** - Extract each file in the archive, checking whether the data matches the CRC checksum - stored at the time it was written - - @return YES if the data is all correct, false if any check failed + Iterate through the archive, checking for any errors, including CRC mismatches between + the archived file and its header + + @return YES if the data is all correct, false if any check failed (_even if ignoreCRCMismatches is YES_) */ - (BOOL)checkDataIntegrity; /** - Extract a particular file, to determine if its data matches the CRC + Iterate through the archive, checking for any errors, including CRC mismatches between + the archived file and its header. If any file's CRC doesn't match, run the given block + to allow the API consumer to decide whether to ignore mismatches. NOTE: This may be a + security risk. The block is intended to prompt the user, which is why it's forced onto + the main thread, rather than making a design-time decision + + @param ignoreCRCMismatches This block, called on the main thread, allows a consuming API to + prompt the user whether or not he'd like to ignore CRC mismatches. + This block is called the first time a CRC mismatch is detected, if + at all. It won't be called if all CRCs match. If this returns YES, + then all further CRC mismatches will be ignored for the + archive instance + + @return YES if the data is all correct and/or the block returns YES; returns false if + any check failed and the given block also returns NO + */ +- (BOOL)checkDataIntegrityIgnoringCRCMismatches:(BOOL(^)(void))ignoreCRCMismatches; + +/** + Check a particular file, to determine if its data matches the CRC checksum stored at the time it written @param filePath The file in the archive to check diff --git a/Carthage/Build/Mac/UnrarKit.framework/Versions/A/Headers/URKFileInfo.h b/Carthage/Build/Mac/UnrarKit.framework/Versions/A/Headers/URKFileInfo.h index 5bf2c95..8cd29fb 100644 --- a/Carthage/Build/Mac/UnrarKit.framework/Versions/A/Headers/URKFileInfo.h +++ b/Carthage/Build/Mac/UnrarKit.framework/Versions/A/Headers/URKFileInfo.h @@ -4,14 +4,14 @@ // #import -#import "UnrarKitMacros.h" +#import RarosHppIgnore -#import "raros.hpp" +#import #pragma clang diagnostic pop DllHppIgnore -#import "dll.hpp" +#import #pragma clang diagnostic pop /* See http://www.forensicswiki.org/wiki/RAR and diff --git a/Carthage/Build/Mac/UnrarKit.framework/Versions/A/Headers/UnrarKit.h b/Carthage/Build/Mac/UnrarKit.framework/Versions/A/Headers/UnrarKit.h index 78db3b3..d2e390e 100644 --- a/Carthage/Build/Mac/UnrarKit.framework/Versions/A/Headers/UnrarKit.h +++ b/Carthage/Build/Mac/UnrarKit.framework/Versions/A/Headers/UnrarKit.h @@ -15,5 +15,5 @@ FOUNDATION_EXPORT double UnrarKitVersionNumber; FOUNDATION_EXPORT const unsigned char UnrarKitVersionString[]; -#import "URKArchive.h" -#import "URKFileInfo.h" +#import +#import diff --git a/Carthage/Build/Mac/UnrarKit.framework/Versions/A/Headers/UnrarKitMacros.h b/Carthage/Build/Mac/UnrarKit.framework/Versions/A/Headers/UnrarKitMacros.h index aea9343..38e466f 100644 --- a/Carthage/Build/Mac/UnrarKit.framework/Versions/A/Headers/UnrarKitMacros.h +++ b/Carthage/Build/Mac/UnrarKit.framework/Versions/A/Headers/UnrarKitMacros.h @@ -60,7 +60,7 @@ __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000 \ #import // Called from +[UnrarKit initialize] and +[URKArchiveTestCase setUp] -extern os_log_t unrarkit_log; // Declared in URKArchive.m +extern os_log_t unrarkit_log; // Declared in URKArchive.mm extern BOOL unrarkitIsAtLeast10_13SDK; // Declared in URKArchive.m #define URKLogInit() \ unrarkit_log = os_log_create("com.abbey-code.UnrarKit", "General"); \ diff --git a/Carthage/Build/Mac/UnrarKit.framework/Versions/A/Headers/dll.hpp b/Carthage/Build/Mac/UnrarKit.framework/Versions/A/Headers/dll.hpp index 7f82906..c785ff1 100644 --- a/Carthage/Build/Mac/UnrarKit.framework/Versions/A/Headers/dll.hpp +++ b/Carthage/Build/Mac/UnrarKit.framework/Versions/A/Headers/dll.hpp @@ -1,7 +1,7 @@ #ifndef _UNRAR_DLL_ #define _UNRAR_DLL_ -#pragma pack(1) +#pragma pack(push, 1) #define ERAR_SUCCESS 0 #define ERAR_END_ARCHIVE 10 @@ -135,6 +135,8 @@ typedef int (CALLBACK *UNRARCALLBACK)(UINT msg,LPARAM UserData,LPARAM P1,LPARAM #define ROADF_ENCHEADERS 0x0080 #define ROADF_FIRSTVOLUME 0x0100 +#define ROADOF_KEEPBROKEN 0x0001 + struct RAROpenArchiveDataEx { char *ArcName; @@ -148,7 +150,9 @@ struct RAROpenArchiveDataEx unsigned int Flags; UNRARCALLBACK Callback; LPARAM UserData; - unsigned int Reserved[28]; + unsigned int OpFlags; + wchar_t *CmtBufW; + unsigned int Reserved[25]; }; enum UNRARCALLBACK_MESSAGES { @@ -180,6 +184,6 @@ int PASCAL RARGetDllVersion(); } #endif -#pragma pack() +#pragma pack(pop) #endif diff --git a/Carthage/Build/Mac/UnrarKit.framework/Versions/A/Resources/Info.plist b/Carthage/Build/Mac/UnrarKit.framework/Versions/A/Resources/Info.plist index 49d07d6..fbb0c36 100644 --- a/Carthage/Build/Mac/UnrarKit.framework/Versions/A/Resources/Info.plist +++ b/Carthage/Build/Mac/UnrarKit.framework/Versions/A/Resources/Info.plist @@ -3,7 +3,7 @@ BuildMachineOSBuild - 17D47 + 19H2 CFBundleDevelopmentRegion English CFBundleExecutable @@ -17,7 +17,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 2.9 + 2.10-beta8 CFBundleSignature ???? CFBundleSupportedPlatforms @@ -25,20 +25,24 @@ MacOSX CFBundleVersion - 2.9 + 2.10-beta8 DTCompiler com.apple.compilers.llvm.clang.1_0 DTPlatformBuild - 9E145 + 12A7300 + DTPlatformName + macosx DTPlatformVersion - GM + 10.15.6 DTSDKBuild - 17E189 + 19G68 DTSDKName - macosx10.13 + macosx10.15 DTXcode - 0930 + 1201 DTXcodeBuild - 9E145 + 12A7300 + LSMinimumSystemVersion + 10.15 diff --git a/Carthage/Build/Mac/UnrarKit.framework/Versions/A/Resources/UnrarKitResources.bundle/Contents/Info.plist b/Carthage/Build/Mac/UnrarKit.framework/Versions/A/Resources/UnrarKitResources.bundle/Contents/Info.plist index e9f384d..da6edfb 100644 --- a/Carthage/Build/Mac/UnrarKit.framework/Versions/A/Resources/UnrarKitResources.bundle/Contents/Info.plist +++ b/Carthage/Build/Mac/UnrarKit.framework/Versions/A/Resources/UnrarKitResources.bundle/Contents/Info.plist @@ -3,7 +3,7 @@ BuildMachineOSBuild - 17D47 + 19H2 CFBundleDevelopmentRegion English CFBundleIdentifier @@ -15,7 +15,7 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 2.9 + 2.10-beta8 CFBundleSignature ???? CFBundleSupportedPlatforms @@ -23,21 +23,25 @@ MacOSX CFBundleVersion - 2.9 + 2.10-beta8 DTCompiler com.apple.compilers.llvm.clang.1_0 DTPlatformBuild - 9E145 + 12A7300 + DTPlatformName + macosx DTPlatformVersion - GM + 10.15.6 DTSDKBuild - 17E189 + 19G68 DTSDKName - macosx10.13 + macosx10.15 DTXcode - 0930 + 1201 DTXcodeBuild - 9E145 + 12A7300 + LSMinimumSystemVersion + 10.15 NSHumanReadableCopyright Copyright © 2017 Abbey Code. All rights reserved. diff --git a/Carthage/Build/Mac/UnrarKit.framework/Versions/A/UnrarKit b/Carthage/Build/Mac/UnrarKit.framework/Versions/A/UnrarKit index d2fb1ee..a620327 100755 Binary files a/Carthage/Build/Mac/UnrarKit.framework/Versions/A/UnrarKit and b/Carthage/Build/Mac/UnrarKit.framework/Versions/A/UnrarKit differ diff --git a/Carthage/Build/iOS/UnrarKit.framework.dSYM/Contents/Info.plist b/Carthage/Build/iOS/UnrarKit.framework.dSYM/Contents/Info.plist index c7fe283..cf0c25f 100644 --- a/Carthage/Build/iOS/UnrarKit.framework.dSYM/Contents/Info.plist +++ b/Carthage/Build/iOS/UnrarKit.framework.dSYM/Contents/Info.plist @@ -13,8 +13,8 @@ CFBundleSignature ???? CFBundleShortVersionString - 2.9 + 2.10-beta8 CFBundleVersion - 2.9 + 2.10-beta8 diff --git a/Carthage/Build/iOS/UnrarKit.framework.dSYM/Contents/Resources/DWARF/UnrarKit b/Carthage/Build/iOS/UnrarKit.framework.dSYM/Contents/Resources/DWARF/UnrarKit index 1aa0730..7ae3f97 100644 Binary files a/Carthage/Build/iOS/UnrarKit.framework.dSYM/Contents/Resources/DWARF/UnrarKit and b/Carthage/Build/iOS/UnrarKit.framework.dSYM/Contents/Resources/DWARF/UnrarKit differ diff --git a/Carthage/Build/iOS/UnrarKit.framework/Headers/URKArchive.h b/Carthage/Build/iOS/UnrarKit.framework/Headers/URKArchive.h index bd064cb..367862d 100644 --- a/Carthage/Build/iOS/UnrarKit.framework/Headers/URKArchive.h +++ b/Carthage/Build/iOS/UnrarKit.framework/Headers/URKArchive.h @@ -6,14 +6,14 @@ #import #import -#import "UnrarKitMacros.h" +#import RarosHppIgnore -#import "raros.hpp" +#import #pragma clang diagnostic pop DllHppIgnore -#import "dll.hpp" +#import #pragma clang diagnostic pop @class URKFileInfo; @@ -25,7 +25,7 @@ DllHppIgnore typedef NS_ENUM(NSInteger, URKErrorCode) { /** - * The archive's header is empty + * The last file of the archive has been read */ URKErrorCodeEndOfArchive = ERAR_END_ARCHIVE, @@ -35,7 +35,7 @@ typedef NS_ENUM(NSInteger, URKErrorCode) { URKErrorCodeNoMemory = ERAR_NO_MEMORY, /** - * The header is broken + * The header's CRC doesn't match the decompressed data's CRC */ URKErrorCodeBadData = ERAR_BAD_DATA, @@ -173,6 +173,17 @@ extern NSString *URKErrorDomain; */ @property(nullable, strong) NSProgress *progress; +/** + * When performing operations on a RAR archive, the contents of compressed files are checked + * against the record of what they were when the archive was created. If there's a mismatch, + * either the metadata (header) or archive contents have become corrupted. You can defeat this check by + * setting this property to YES, though there may be security implications to turning the + * warnings off, as it may indicate a maliciously crafted archive intended to exploit a vulnerability. + * + * It's recommended to leave the decision of how to treat archives with mismatched CRCs to the user + */ +@property (assign) BOOL ignoreCRCMismatches; + /** * **DEPRECATED:** Creates and returns an archive at the given path @@ -475,15 +486,34 @@ extern NSString *URKErrorDomain; - (BOOL)validatePassword; /** - Extract each file in the archive, checking whether the data matches the CRC checksum - stored at the time it was written - - @return YES if the data is all correct, false if any check failed + Iterate through the archive, checking for any errors, including CRC mismatches between + the archived file and its header + + @return YES if the data is all correct, false if any check failed (_even if ignoreCRCMismatches is YES_) */ - (BOOL)checkDataIntegrity; /** - Extract a particular file, to determine if its data matches the CRC + Iterate through the archive, checking for any errors, including CRC mismatches between + the archived file and its header. If any file's CRC doesn't match, run the given block + to allow the API consumer to decide whether to ignore mismatches. NOTE: This may be a + security risk. The block is intended to prompt the user, which is why it's forced onto + the main thread, rather than making a design-time decision + + @param ignoreCRCMismatches This block, called on the main thread, allows a consuming API to + prompt the user whether or not he'd like to ignore CRC mismatches. + This block is called the first time a CRC mismatch is detected, if + at all. It won't be called if all CRCs match. If this returns YES, + then all further CRC mismatches will be ignored for the + archive instance + + @return YES if the data is all correct and/or the block returns YES; returns false if + any check failed and the given block also returns NO + */ +- (BOOL)checkDataIntegrityIgnoringCRCMismatches:(BOOL(^)(void))ignoreCRCMismatches; + +/** + Check a particular file, to determine if its data matches the CRC checksum stored at the time it written @param filePath The file in the archive to check diff --git a/Carthage/Build/iOS/UnrarKit.framework/Headers/URKFileInfo.h b/Carthage/Build/iOS/UnrarKit.framework/Headers/URKFileInfo.h index 5bf2c95..8cd29fb 100644 --- a/Carthage/Build/iOS/UnrarKit.framework/Headers/URKFileInfo.h +++ b/Carthage/Build/iOS/UnrarKit.framework/Headers/URKFileInfo.h @@ -4,14 +4,14 @@ // #import -#import "UnrarKitMacros.h" +#import RarosHppIgnore -#import "raros.hpp" +#import #pragma clang diagnostic pop DllHppIgnore -#import "dll.hpp" +#import #pragma clang diagnostic pop /* See http://www.forensicswiki.org/wiki/RAR and diff --git a/Carthage/Build/iOS/UnrarKit.framework/Headers/UnrarKit.h b/Carthage/Build/iOS/UnrarKit.framework/Headers/UnrarKit.h index 78db3b3..d2e390e 100644 --- a/Carthage/Build/iOS/UnrarKit.framework/Headers/UnrarKit.h +++ b/Carthage/Build/iOS/UnrarKit.framework/Headers/UnrarKit.h @@ -15,5 +15,5 @@ FOUNDATION_EXPORT double UnrarKitVersionNumber; FOUNDATION_EXPORT const unsigned char UnrarKitVersionString[]; -#import "URKArchive.h" -#import "URKFileInfo.h" +#import +#import diff --git a/Carthage/Build/iOS/UnrarKit.framework/Headers/UnrarKitMacros.h b/Carthage/Build/iOS/UnrarKit.framework/Headers/UnrarKitMacros.h index aea9343..38e466f 100644 --- a/Carthage/Build/iOS/UnrarKit.framework/Headers/UnrarKitMacros.h +++ b/Carthage/Build/iOS/UnrarKit.framework/Headers/UnrarKitMacros.h @@ -60,7 +60,7 @@ __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000 \ #import // Called from +[UnrarKit initialize] and +[URKArchiveTestCase setUp] -extern os_log_t unrarkit_log; // Declared in URKArchive.m +extern os_log_t unrarkit_log; // Declared in URKArchive.mm extern BOOL unrarkitIsAtLeast10_13SDK; // Declared in URKArchive.m #define URKLogInit() \ unrarkit_log = os_log_create("com.abbey-code.UnrarKit", "General"); \ diff --git a/Carthage/Build/iOS/UnrarKit.framework/Headers/dll.hpp b/Carthage/Build/iOS/UnrarKit.framework/Headers/dll.hpp index 7f82906..c785ff1 100644 --- a/Carthage/Build/iOS/UnrarKit.framework/Headers/dll.hpp +++ b/Carthage/Build/iOS/UnrarKit.framework/Headers/dll.hpp @@ -1,7 +1,7 @@ #ifndef _UNRAR_DLL_ #define _UNRAR_DLL_ -#pragma pack(1) +#pragma pack(push, 1) #define ERAR_SUCCESS 0 #define ERAR_END_ARCHIVE 10 @@ -135,6 +135,8 @@ typedef int (CALLBACK *UNRARCALLBACK)(UINT msg,LPARAM UserData,LPARAM P1,LPARAM #define ROADF_ENCHEADERS 0x0080 #define ROADF_FIRSTVOLUME 0x0100 +#define ROADOF_KEEPBROKEN 0x0001 + struct RAROpenArchiveDataEx { char *ArcName; @@ -148,7 +150,9 @@ struct RAROpenArchiveDataEx unsigned int Flags; UNRARCALLBACK Callback; LPARAM UserData; - unsigned int Reserved[28]; + unsigned int OpFlags; + wchar_t *CmtBufW; + unsigned int Reserved[25]; }; enum UNRARCALLBACK_MESSAGES { @@ -180,6 +184,6 @@ int PASCAL RARGetDllVersion(); } #endif -#pragma pack() +#pragma pack(pop) #endif diff --git a/Carthage/Build/iOS/UnrarKit.framework/Info.plist b/Carthage/Build/iOS/UnrarKit.framework/Info.plist index 66dcb2e..c7321d2 100644 Binary files a/Carthage/Build/iOS/UnrarKit.framework/Info.plist and b/Carthage/Build/iOS/UnrarKit.framework/Info.plist differ diff --git a/Carthage/Build/iOS/UnrarKit.framework/UnrarKit b/Carthage/Build/iOS/UnrarKit.framework/UnrarKit index 23fe062..2fd324d 100755 Binary files a/Carthage/Build/iOS/UnrarKit.framework/UnrarKit and b/Carthage/Build/iOS/UnrarKit.framework/UnrarKit differ diff --git a/Carthage/Build/iOS/UnrarKit.framework/UnrarKitResources.bundle/Info.plist b/Carthage/Build/iOS/UnrarKit.framework/UnrarKitResources.bundle/Info.plist index 30476c2..5f63634 100644 Binary files a/Carthage/Build/iOS/UnrarKit.framework/UnrarKitResources.bundle/Info.plist and b/Carthage/Build/iOS/UnrarKit.framework/UnrarKitResources.bundle/Info.plist differ diff --git a/Carthage/Checkouts/UnrarKit/.travis.yml b/Carthage/Checkouts/UnrarKit/.travis.yml index 4be4f70..2b46075 100644 --- a/Carthage/Checkouts/UnrarKit/.travis.yml +++ b/Carthage/Checkouts/UnrarKit/.travis.yml @@ -1,7 +1,12 @@ language: objective-c -osx_image: xcode9.3 +osx_image: xcode12 + +branches: + except: + - circle-ci before_script: + - pod --version # Make log level less verbose. Temporarily undo if more info is needed - sudo log config --mode "level:default" @@ -15,7 +20,7 @@ matrix: - stage: Test env: Name=iOS # The CLANG arguments and find command fail the build on analyzer errors - script: xcodebuild -workspace UnrarKit.xcworkspace -scheme UnrarKit -destination 'platform=iOS Simulator,name=iPhone 7,OS=latest' -configuration Release analyze test CLANG_ANALYZER_OUTPUT=html CLANG_ANALYZER_OUTPUT_DIR=analyzer-output && [[ -z `find analyzer-output -name "*.html"` ]] + script: xcodebuild -workspace UnrarKit.xcworkspace -scheme UnrarKit -destination 'platform=iOS Simulator,name=iPhone 11,OS=latest' -configuration Release analyze test CLANG_ANALYZER_OUTPUT=html CLANG_ANALYZER_OUTPUT_DIR=analyzer-output && [[ -z `find analyzer-output -name "*.html"` ]] - stage: Test env: Name=ExampleAppBuild @@ -32,5 +37,4 @@ matrix: - stage: Release if: tag IS present - before_install: brew upgrade python # Needs Python 3 script: ./Scripts/push-output.sh diff --git a/Carthage/Checkouts/UnrarKit/CHANGELOG.md b/Carthage/Checkouts/UnrarKit/CHANGELOG.md index f47b8a4..d75cd5b 100644 --- a/Carthage/Checkouts/UnrarKit/CHANGELOG.md +++ b/Carthage/Checkouts/UnrarKit/CHANGELOG.md @@ -1,5 +1,14 @@ # UnrarKit CHANGELOG +## 2.10 + +* Added method (`checkDataIntegrityIgnoringCRCMismatches:`) to prompt user for a decision on whether or not to ignore CRC mismatches (Issue #82) +* Fixed crash in `+pathIsARAR:` when a file is unreadable (Issue #85) +* Fixed crash in `-_unrarOpenFile:inMode:withPassword:error:` (PR #97) +* Updated to v5.9.4 of UnRAR library +* Xcode 12 compatibility in Carthage + + ## 2.9 * Added support for `NSProgress` and `NSProgressReporting` in all extraction and iteration methods (Issue #34) diff --git a/Carthage/Checkouts/UnrarKit/Classes/URKArchive.h b/Carthage/Checkouts/UnrarKit/Classes/URKArchive.h index bd064cb..367862d 100644 --- a/Carthage/Checkouts/UnrarKit/Classes/URKArchive.h +++ b/Carthage/Checkouts/UnrarKit/Classes/URKArchive.h @@ -6,14 +6,14 @@ #import #import -#import "UnrarKitMacros.h" +#import RarosHppIgnore -#import "raros.hpp" +#import #pragma clang diagnostic pop DllHppIgnore -#import "dll.hpp" +#import #pragma clang diagnostic pop @class URKFileInfo; @@ -25,7 +25,7 @@ DllHppIgnore typedef NS_ENUM(NSInteger, URKErrorCode) { /** - * The archive's header is empty + * The last file of the archive has been read */ URKErrorCodeEndOfArchive = ERAR_END_ARCHIVE, @@ -35,7 +35,7 @@ typedef NS_ENUM(NSInteger, URKErrorCode) { URKErrorCodeNoMemory = ERAR_NO_MEMORY, /** - * The header is broken + * The header's CRC doesn't match the decompressed data's CRC */ URKErrorCodeBadData = ERAR_BAD_DATA, @@ -173,6 +173,17 @@ extern NSString *URKErrorDomain; */ @property(nullable, strong) NSProgress *progress; +/** + * When performing operations on a RAR archive, the contents of compressed files are checked + * against the record of what they were when the archive was created. If there's a mismatch, + * either the metadata (header) or archive contents have become corrupted. You can defeat this check by + * setting this property to YES, though there may be security implications to turning the + * warnings off, as it may indicate a maliciously crafted archive intended to exploit a vulnerability. + * + * It's recommended to leave the decision of how to treat archives with mismatched CRCs to the user + */ +@property (assign) BOOL ignoreCRCMismatches; + /** * **DEPRECATED:** Creates and returns an archive at the given path @@ -475,15 +486,34 @@ extern NSString *URKErrorDomain; - (BOOL)validatePassword; /** - Extract each file in the archive, checking whether the data matches the CRC checksum - stored at the time it was written - - @return YES if the data is all correct, false if any check failed + Iterate through the archive, checking for any errors, including CRC mismatches between + the archived file and its header + + @return YES if the data is all correct, false if any check failed (_even if ignoreCRCMismatches is YES_) */ - (BOOL)checkDataIntegrity; /** - Extract a particular file, to determine if its data matches the CRC + Iterate through the archive, checking for any errors, including CRC mismatches between + the archived file and its header. If any file's CRC doesn't match, run the given block + to allow the API consumer to decide whether to ignore mismatches. NOTE: This may be a + security risk. The block is intended to prompt the user, which is why it's forced onto + the main thread, rather than making a design-time decision + + @param ignoreCRCMismatches This block, called on the main thread, allows a consuming API to + prompt the user whether or not he'd like to ignore CRC mismatches. + This block is called the first time a CRC mismatch is detected, if + at all. It won't be called if all CRCs match. If this returns YES, + then all further CRC mismatches will be ignored for the + archive instance + + @return YES if the data is all correct and/or the block returns YES; returns false if + any check failed and the given block also returns NO + */ +- (BOOL)checkDataIntegrityIgnoringCRCMismatches:(BOOL(^)(void))ignoreCRCMismatches; + +/** + Check a particular file, to determine if its data matches the CRC checksum stored at the time it written @param filePath The file in the archive to check diff --git a/Carthage/Checkouts/UnrarKit/Classes/URKArchive.mm b/Carthage/Checkouts/UnrarKit/Classes/URKArchive.mm index d00c3b8..ae669cc 100644 --- a/Carthage/Checkouts/UnrarKit/Classes/URKArchive.mm +++ b/Carthage/Checkouts/UnrarKit/Classes/URKArchive.mm @@ -28,6 +28,11 @@ BOOL unrarkitIsAtLeast10_13SDK; static NSBundle *_resources = nil; +typedef enum : NSUInteger { + URKReadHeaderLoopActionStopReading, + URKReadHeaderLoopActionContinueReading, +} URKReadHeaderLoopAction; + @interface URKArchive () @@ -46,6 +51,9 @@ NS_DESIGNATED_INITIALIZER @property (strong) NSObject *threadLock; +@property (copy) NSString *lastArchivePath; +@property (copy) NSString *lastFilepath; + @end @@ -160,6 +168,10 @@ NS_DESIGNATED_INITIALIZER error:&bookmarkError]; _password = password; _threadLock = [[NSObject alloc] init]; + + _lastArchivePath = nil; + _lastFilepath = nil; + _ignoreCRCMismatches = NO; if (bookmarkError) { URKLogFault("Error creating bookmark to RAR archive: %{public}@", bookmarkError); @@ -336,6 +348,9 @@ NS_DESIGNATED_INITIALIZER URKLogDebug("File is not a RAR. Unknown contents in 7th and 8th bytes (%02X %02X)", dataBytes[6], dataBytes[7]); } + @catch (NSException *e) { + URKLogError("Error checking if %{public}@ is a RAR archive: %{public}@", filePath, e); + } @finally { [handle closeFile]; } @@ -508,8 +523,7 @@ NS_DESIGNATED_INITIALIZER URKLogInfo("Extracting to %{public}@", filePath); URKLogDebug("Reading through RAR header looking for files..."); - while ((RHCode = RARReadHeaderEx(welf.rarFile, welf.header)) == ERAR_SUCCESS) { - fileInfo = [URKFileInfo fileInfo:welf.header]; + while ([welf readHeader:&RHCode info:&fileInfo] == URKReadHeaderLoopActionContinueReading) { URKLogDebug("Extracting %{public}@ (%{iec-bytes}lld)", fileInfo.filename, fileInfo.uncompressedSize); NSURL *extractedURL = [[NSURL fileURLWithPath:filePath] URLByAppendingPathComponent:fileInfo.filename]; [progress setUserInfoObject:extractedURL @@ -517,7 +531,7 @@ NS_DESIGNATED_INITIALIZER [progress setUserInfoObject:fileInfo forKey:URKProgressInfoKeyFileInfoExtracting]; - if ([self headerContainsErrors:innerError]) { + if ([welf headerContainsErrors:innerError]) { URKLogError("Header contains an error") result = NO; return; @@ -525,7 +539,7 @@ NS_DESIGNATED_INITIALIZER if (progress.isCancelled) { NSString *errorName = nil; - [self assignError:innerError code:URKErrorCodeUserCancelled errorName:&errorName]; + [welf assignError:innerError code:URKErrorCodeUserCancelled errorName:&errorName]; URKLogInfo("Halted file extraction due to user cancellation: %{public}@", errorName); result = NO; return; @@ -537,7 +551,7 @@ NS_DESIGNATED_INITIALIZER encoding:NSUTF8StringEncoding]; if (!utf8ConversionSucceeded) { NSString *errorName = nil; - [self assignError:innerError code:URKErrorCodeStringConversion errorName:&errorName]; + [welf assignError:innerError code:URKErrorCodeStringConversion errorName:&errorName]; URKLogError("Error converting file to UTF-8 (buffer too short?)"); result = NO; return; @@ -550,12 +564,13 @@ NS_DESIGNATED_INITIALIZER }; RARSetCallback(welf.rarFile, AllowCancellationCallbackProc, (long)shouldCancelBlock); - if ((PFCode = RARProcessFile(welf.rarFile, RAR_EXTRACT, cFilePath, NULL)) != 0) { + PFCode = RARProcessFile(welf.rarFile, RAR_EXTRACT, cFilePath, NULL); + if (![welf didReturnSuccessfully:PFCode]) { RARSetCallback(welf.rarFile, NULL, NULL); - + NSString *errorName = nil; NSInteger errorCode = progress.isCancelled ? URKErrorCodeUserCancelled : PFCode; - [self assignError:innerError code:errorCode errorName:&errorName]; + [welf assignError:innerError code:errorCode errorName:&errorName]; URKLogError("Error extracting file: %{public}@ (%ld)", errorName, (long)errorCode); result = NO; return; @@ -582,14 +597,14 @@ NS_DESIGNATED_INITIALIZER } RARSetCallback(welf.rarFile, NULL, NULL); - - if (RHCode != ERAR_SUCCESS && RHCode != ERAR_END_ARCHIVE) { + + if (![welf didReturnSuccessfully:RHCode]) { NSString *errorName = nil; - [self assignError:innerError code:RHCode errorName:&errorName]; + [welf assignError:innerError code:RHCode errorName:&errorName]; URKLogError("Error reading file header: %{public}@ (%d)", errorName, RHCode); result = NO; } - + if (progressBlock) { progressBlock(fileInfo, 1.0); } @@ -642,14 +657,12 @@ NS_DESIGNATED_INITIALIZER URKFileInfo *fileInfo; URKLogDebug("Reading through RAR header looking for files..."); - while ((RHCode = RARReadHeaderEx(welf.rarFile, welf.header)) == ERAR_SUCCESS) { - if ([self headerContainsErrors:innerError]) { + while ([welf readHeader:&RHCode info:&fileInfo] == URKReadHeaderLoopActionContinueReading) { + if ([welf headerContainsErrors:innerError]) { URKLogError("Header contains an error") return; } - fileInfo = [URKFileInfo fileInfo:welf.header]; - if ([fileInfo.filename isEqualToString:filePath]) { URKLogDebug("Extracting %{public}@", fileInfo.filename); break; @@ -658,7 +671,7 @@ NS_DESIGNATED_INITIALIZER URKLogDebug("Skipping %{public}@", fileInfo.filename); if ((PFCode = RARProcessFileW(welf.rarFile, RAR_SKIP, NULL, NULL)) != 0) { NSString *errorName = nil; - [self assignError:innerError code:(NSInteger)PFCode errorName:&errorName]; + [welf assignError:innerError code:(NSInteger)PFCode errorName:&errorName]; URKLogError("Error skipping file: %{public}@ (%d)", errorName, PFCode); return; } @@ -667,7 +680,7 @@ NS_DESIGNATED_INITIALIZER if (RHCode != ERAR_SUCCESS) { NSString *errorName = nil; - [self assignError:innerError code:RHCode errorName:&errorName]; + [welf assignError:innerError code:RHCode errorName:&errorName]; URKLogError("Error reading file header: %{public}@ (%d)", errorName, RHCode); return; } @@ -715,14 +728,14 @@ NS_DESIGNATED_INITIALIZER if (progress.isCancelled) { NSString *errorName = nil; - [self assignError:innerError code:URKErrorCodeUserCancelled errorName:&errorName]; + [welf assignError:innerError code:URKErrorCodeUserCancelled errorName:&errorName]; URKLogInfo("Returning nil data from extraction due to user cancellation: %{public}@", errorName); return; } - if (PFCode != 0) { + if (![welf didReturnSuccessfully:PFCode]) { NSString *errorName = nil; - [self assignError:innerError code:(NSInteger)PFCode errorName:&errorName]; + [welf assignError:innerError code:(NSInteger)PFCode errorName:&errorName]; URKLogError("Error extracting file data: %{public}@ (%d)", errorName, PFCode); return; } @@ -813,27 +826,36 @@ NS_DESIGNATED_INITIALIZER BOOL stop = NO; - NSProgress *progress = [self beginProgressOperation:totalSize.longLongValue]; + NSProgress *progress = [welf beginProgressOperation:totalSize.longLongValue]; URKLogDebug("Reading through RAR header looking for files..."); - while ((RHCode = RARReadHeaderEx(welf.rarFile, welf.header)) == 0) { + + URKFileInfo *info = nil; + while ([welf readHeader:&RHCode info:&info] == URKReadHeaderLoopActionContinueReading) { if (stop || progress.isCancelled) { URKLogDebug("Action dictated an early stop"); return; } - if ([self headerContainsErrors:innerError]) { + if ([welf headerContainsErrors:innerError]) { URKLogError("Header contains an error") return; } - URKFileInfo *info = [URKFileInfo fileInfo:welf.header]; URKLogDebug("Performing action on %{public}@", info.filename); // Empty file, or a directory - if (info.uncompressedSize == 0) { + if (info.isDirectory || info.uncompressedSize == 0) { URKLogDebug("%{public}@ is an empty file, or a directory", info.filename); action(info, [NSData data], &stop); + PFCode = RARProcessFile(welf.rarFile, RAR_SKIP, NULL, NULL); + if (PFCode != 0) { + NSString *errorName = nil; + [welf assignError:innerError code:(NSInteger)PFCode errorName:&errorName]; + URKLogError("Error skipping directory: %{public}@ (%d)", errorName, PFCode); + return; + } + continue; } @@ -845,9 +867,9 @@ NS_DESIGNATED_INITIALIZER URKLogInfo("Processing file..."); PFCode = RARProcessFile(welf.rarFile, RAR_TEST, NULL, NULL); - if (PFCode != 0) { + if (![welf didReturnSuccessfully:PFCode]) { NSString *errorName = nil; - [self assignError:innerError code:(NSInteger)PFCode errorName:&errorName]; + [welf assignError:innerError code:(NSInteger)PFCode errorName:&errorName]; URKLogError("Error processing file: %{public}@ (%d)", errorName, PFCode); return; } @@ -861,14 +883,14 @@ NS_DESIGNATED_INITIALIZER if (progress.isCancelled) { NSString *errorName = nil; - [self assignError:innerError code:URKErrorCodeUserCancelled errorName:&errorName]; + [welf assignError:innerError code:URKErrorCodeUserCancelled errorName:&errorName]; URKLogInfo("Returning NO from performOnData:error: due to user cancellation: %{public}@", errorName); return; } - if (RHCode != ERAR_SUCCESS && RHCode != ERAR_END_ARCHIVE) { + if (![welf didReturnSuccessfully:RHCode]) { NSString *errorName = nil; - [self assignError:innerError code:RHCode errorName:&errorName]; + [welf assignError:innerError code:RHCode errorName:&errorName]; URKLogError("Error reading file header: %{public}@ (%d)", errorName, RHCode); return; } @@ -897,24 +919,22 @@ NS_DESIGNATED_INITIALIZER URKLogInfo("Looping through files, looking for %{public}@...", filePath); - while ((RHCode = RARReadHeaderEx(welf.rarFile, welf.header)) == ERAR_SUCCESS) { - if ([self headerContainsErrors:innerError]) { + while ([welf readHeader:&RHCode info:&fileInfo] == URKReadHeaderLoopActionContinueReading) { + if ([welf headerContainsErrors:innerError]) { URKLogDebug("Header contains error") return; } - URKLogDebug("Getting file info from header"); - fileInfo = [URKFileInfo fileInfo:welf.header]; - if ([fileInfo.filename isEqualToString:filePath]) { URKLogDebug("Found desired file"); break; } else { URKLogDebug("Skipping file..."); - if ((PFCode = RARProcessFile(welf.rarFile, RAR_SKIP, NULL, NULL)) != 0) { + PFCode = RARProcessFile(welf.rarFile, RAR_SKIP, NULL, NULL); + if (![welf didReturnSuccessfully:PFCode]) { NSString *errorName = nil; - [self assignError:innerError code:(NSInteger)PFCode errorName:&errorName]; + [welf assignError:innerError code:(NSInteger)PFCode errorName:&errorName]; URKLogError("Failed to skip file: %{public}@ (%d)", errorName, PFCode); return; } @@ -924,9 +944,9 @@ NS_DESIGNATED_INITIALIZER long long totalBytes = fileInfo.uncompressedSize; progress.totalUnitCount = totalBytes; - if (RHCode != ERAR_SUCCESS) { + if (![welf didReturnSuccessfully:RHCode]) { NSString *errorName = nil; - [self assignError:innerError code:RHCode errorName:&errorName]; + [welf assignError:innerError code:RHCode errorName:&errorName]; URKLogError("Header read yielded error: %{public}@ (%d)", errorName, RHCode); return; } @@ -965,14 +985,14 @@ NS_DESIGNATED_INITIALIZER if (progress.isCancelled) { NSString *errorName = nil; - [self assignError:innerError code:URKErrorCodeUserCancelled errorName:&errorName]; + [welf assignError:innerError code:URKErrorCodeUserCancelled errorName:&errorName]; URKLogError("Buffered data extraction has been cancelled: %{public}@", errorName); return; } - if (PFCode != 0) { + if (![welf didReturnSuccessfully:PFCode]) { NSString *errorName = nil; - [self assignError:innerError code:(NSInteger)PFCode errorName:&errorName]; + [welf assignError:innerError code:(NSInteger)PFCode errorName:&errorName]; URKLogError("Error processing file: %{public}@ (%d)", errorName, PFCode); } } inMode:RAR_OM_EXTRACT error:&actionError]; @@ -1049,7 +1069,7 @@ NS_DESIGNATED_INITIALIZER int RHCode = RARReadHeaderEx(welf.rarFile, welf.header); int PFCode = RARProcessFile(welf.rarFile, RAR_TEST, NULL, NULL); - if ([self headerContainsErrors:innerError]) { + if ([welf headerContainsErrors:innerError]) { if (error.code == ERAR_MISSING_PASSWORD) { URKLogDebug("Password invalidated by header"); passwordIsGood = NO; @@ -1062,13 +1082,18 @@ NS_DESIGNATED_INITIALIZER } if (RHCode == ERAR_MISSING_PASSWORD || PFCode == ERAR_MISSING_PASSWORD - || RHCode == ERAR_BAD_DATA || PFCode == ERAR_BAD_DATA || RHCode == ERAR_BAD_PASSWORD || PFCode == ERAR_BAD_PASSWORD) { URKLogDebug("Missing/bad password indicated by RHCode (%d) or PFCode (%d)", RHCode, PFCode); passwordIsGood = NO; return; } + + if ([welf hasBadCRC:RHCode] || [welf hasBadCRC:PFCode]) { + URKLogDebug("Missing/bad password indicated via CRC mismatch by RHCode (%d) or PFCode (%d)", RHCode, PFCode); + passwordIsGood = NO; + return; + } } inMode:RAR_OM_EXTRACT error:&error]; if (!success) { @@ -1084,47 +1109,96 @@ NS_DESIGNATED_INITIALIZER return [self checkDataIntegrityOfFile:(NSString *_Nonnull)nil]; } -- (BOOL)checkDataIntegrityOfFile:(NSString *)filePath +- (BOOL)checkDataIntegrityIgnoringCRCMismatches:(BOOL(^)())ignoreCRCMismatches +{ + int rhCode = [self dataIntegrityCodeOfFile:nil]; + if (rhCode == ERAR_SUCCESS) { + return YES; + } + + if (rhCode == ERAR_BAD_DATA) { + NSOperationQueue *mainQueue = [NSOperationQueue mainQueue]; + + __block BOOL blockResult; + + if ([NSOperationQueue currentQueue] == mainQueue) { + blockResult = ignoreCRCMismatches(); + } else { + [mainQueue addOperations:@[[NSBlockOperation blockOperationWithBlock:^{ + blockResult = ignoreCRCMismatches(); + }]] + waitUntilFinished:YES]; + } + + self.ignoreCRCMismatches = blockResult; + return self.ignoreCRCMismatches; + } + + return NO; +} + +- (BOOL)checkDataIntegrityOfFile:(NSString *)filePath { + return [self dataIntegrityCodeOfFile:filePath] == ERAR_SUCCESS; +} + +- (int)dataIntegrityCodeOfFile:(NSString *)filePath { URKCreateActivity("Checking Data Integrity"); URKLogInfo("Checking integrity of %{public}@", filePath ? filePath : @"whole archive"); - __block BOOL corruptDataFound = YES; + __block int RHCode = 0; + __block int PFCode = 0; + + __weak URKArchive *welf = self; NSError *performOnFilesError = nil; - [self performOnFilesInArchive:^(URKFileInfo *fileInfo, BOOL *stop) { + BOOL wasSuccessful = [self performActionWithArchiveOpen:^(NSError **innerError) { URKCreateActivity("Iterating through each file"); - corruptDataFound = NO; // Set inside here so invalid archives are marked as corrupt - if (filePath && ![fileInfo.filename isEqualToString:filePath]) return; - - URKLogDebug("Extracting '%{public}@ to check its CRC...", fileInfo.filename); - NSError *extractError = nil; - NSData *fileData = [self extractData:fileInfo error:&extractError]; - if (!fileData) { - URKLogError("Error extracting %{public}@: %{public}@", fileInfo.filename, extractError); - *stop = YES; - return; + while (true) { + URKFileInfo *fileInfo = nil; + [welf readHeader:&RHCode info:&fileInfo]; + welf.lastFilepath = nil; + welf.lastArchivePath = nil; + + if (RHCode == ERAR_END_ARCHIVE) { + RHCode = ERAR_SUCCESS; + break; + } + + if (filePath && ![fileInfo.filename isEqualToString:filePath]) continue; + + if (RHCode != ERAR_SUCCESS) { + break; + } + + if ((PFCode = RARProcessFile(welf.rarFile, RAR_TEST, NULL, NULL)) != ERAR_SUCCESS) { + RHCode = PFCode; + break; + } + + if (filePath) { + break; + } } - - uLong expectedCRC = fileInfo.CRC; - uLong actualCRC = crc32((uLong)0, (const Bytef*)fileData.bytes, (uint)fileData.length); - URKLogDebug("Checking integrity of %{public}@. Expected CRC: %010lu vs. Actual: %010lu", - fileInfo.filename, expectedCRC, actualCRC); - if (expectedCRC != actualCRC) { - corruptDataFound = YES; - URKLogError("Corrupt data found (filename: %{public}@, expected CRC: %010lu, actual CRC: %010lu", - fileInfo.filename, expectedCRC, actualCRC); - } - - if (filePath) *stop = YES; - } error:&performOnFilesError]; + } inMode:RAR_OM_EXTRACT error:&performOnFilesError]; + + if (RHCode == ERAR_END_ARCHIVE) { + RHCode = ERAR_SUCCESS; + } if (performOnFilesError) { URKLogError("Error checking data integrity: %{public}@", performOnFilesError); } - return !corruptDataFound; + if (!wasSuccessful) { + URKLogError("Error checking data integrity"); + if (RHCode == ERAR_SUCCESS) { + RHCode = ERAR_UNKNOWN; + } + } + + return RHCode; } @@ -1269,22 +1343,24 @@ int CALLBACK AllowCancellationCallbackProc(UINT msg, long UserData, long P1, lon URKLogDebug("Setting archive name..."); - const char *filenameData = (const char *) [rarFile UTF8String]; - self.flags->ArcName = new char[strlen(filenameData) + 1]; - strcpy(self.flags->ArcName, filenameData); - self.flags->OpenMode = (uint)mode; + self.flags->ArcName = strdup(rarFile.UTF8String); + self.flags->OpenMode = (uint)mode; + self.flags->OpFlags = self.ignoreCRCMismatches ? ROADOF_KEEPBROKEN : 0; URKLogDebug("Opening archive %{public}@...", rarFile); - self.rarFile = RAROpenArchiveEx(self.flags); - if (self.rarFile == 0 || self.flags->OpenResult != 0) { + self.rarFile = RAROpenArchiveEx(self.flags); + if (self.rarFile == 0 || self.flags->OpenResult != 0) { NSString *errorName = nil; [self assignError:error code:(NSInteger)self.flags->OpenResult errorName:&errorName]; URKLogError("Error opening archive: %{public}@ (%d)", errorName, self.flags->OpenResult); return NO; } - if(aPassword != nil) { + self.lastFilepath = nil; + self.lastArchivePath = nil; + + if (aPassword != nil) { URKLogDebug("Setting password..."); char cPassword[2048]; @@ -1339,10 +1415,10 @@ int CALLBACK AllowCancellationCallbackProc(UINT msg, long UserData, long P1, lon URKLogDebug("Reading through RAR header looking for files..."); - while ((RHCode = RARReadHeaderEx(welf.rarFile, welf.header)) == 0) { + URKFileInfo *info = nil; + while ([welf readHeader:&RHCode info:&info] == URKReadHeaderLoopActionContinueReading) { URKLogDebug("Calling iterateAllFileInfo handler"); BOOL shouldStop = NO; - URKFileInfo *info = [URKFileInfo fileInfo:welf.header]; action(info, &shouldStop); if (shouldStop) { @@ -1353,15 +1429,15 @@ int CALLBACK AllowCancellationCallbackProc(UINT msg, long UserData, long P1, lon URKLogDebug("Skipping to next file..."); if ((PFCode = RARProcessFile(welf.rarFile, RAR_SKIP, NULL, NULL)) != 0) { NSString *errorName = nil; - [self assignError:innerError code:(NSInteger)PFCode errorName:&errorName]; + [welf assignError:innerError code:(NSInteger)PFCode errorName:&errorName]; URKLogError("Error skipping to next header file: %{public}@ (%d)", errorName, PFCode); return; } } - if (RHCode != ERAR_SUCCESS && RHCode != ERAR_END_ARCHIVE) { + if (![welf didReturnSuccessfully:RHCode]) { NSString *errorName = nil; - [self assignError:innerError code:RHCode errorName:&errorName]; + [welf assignError:innerError code:RHCode errorName:&errorName]; URKLogError("Error reading RAR header: %{public}@ (%d)", errorName, RHCode); } } inMode:RAR_OM_LIST_INCSPLIT error:error]; @@ -1485,7 +1561,7 @@ int CALLBACK AllowCancellationCallbackProc(UINT msg, long UserData, long P1, lon default: errorName = [NSString stringWithFormat:@"Unknown (%ld)", (long)errorCode]; - detail = [NSString localizedStringWithFormat:NSLocalizedStringFromTableInBundle(@"Unknown error encountered (code %ld)", @"UnrarKit", _resources, @"Error detail string"), errorCode]; + detail = [NSString localizedStringWithFormat:NSLocalizedStringFromTableInBundle(@"Unknown error encountered (code %ld)", @"UnrarKit", _resources, @"Error detail string"), (long)errorCode]; break; } @@ -1641,4 +1717,71 @@ int CALLBACK AllowCancellationCallbackProc(UINT msg, long UserData, long P1, lon return volumeURL; } +- (URKReadHeaderLoopAction) readHeader:(int *)returnCode + info:(URKFileInfo *__autoreleasing *)info +{ + NSAssert(returnCode != NULL, @"otherReturnCode argument is required"); + NSAssert(info != NULL, @"info argument is required"); + + URKLogDebug("Reading RAR header"); + *returnCode = RARReadHeaderEx(self.rarFile, self.header); + URKLogDebug("Reading file info from RAR header"); + *info = [URKFileInfo fileInfo:self.header]; + URKLogDebug("RARReadHeaderEx returned %d", *returnCode); + + URKReadHeaderLoopAction result; + + switch (*returnCode) { + case ERAR_SUCCESS: + result = URKReadHeaderLoopActionContinueReading; + break; + + case ERAR_END_ARCHIVE: + URKLogDebug("Successful return code from RARReadHeaderEx"); + result = URKReadHeaderLoopActionStopReading; + break; + + case ERAR_BAD_DATA: + if (self.ignoreCRCMismatches) { + URKLogError("Ignoring CRC mismatch in %{public}@", (*info).filename); + result = URKReadHeaderLoopActionContinueReading; + } else { + URKLogError("CRC mismatch when reading %{public}@. To read the archive and ignore CRC mismatches, use -checkDataIntegrityIgnoringCRCMismatches:", (*info).filename); + result = URKReadHeaderLoopActionStopReading; + } + break; + + default: + result = URKReadHeaderLoopActionStopReading; + break; + } + + if (result == URKReadHeaderLoopActionContinueReading + && [self.lastFilepath isEqualToString:(*info).filename] + && [self.lastArchivePath isEqualToString:(*info).archiveName]) + { + URKLogInfo("Same header returned twice. Presuming archive done being read. Probably a bad CRC") + result = URKReadHeaderLoopActionStopReading; + } + + self.lastFilepath = (result == URKReadHeaderLoopActionStopReading + ? nil + : (*info).filename); + self.lastArchivePath = (result == URKReadHeaderLoopActionStopReading + ? nil + : (*info).archiveName); + + return result; +} + +- (BOOL)didReturnSuccessfully:(int)returnCode { + return (returnCode == ERAR_SUCCESS + || returnCode == ERAR_END_ARCHIVE + || (returnCode == ERAR_BAD_DATA && self.ignoreCRCMismatches)); +} + +- (BOOL)hasBadCRC:(int)returnCode { + return returnCode == ERAR_BAD_DATA && !self.ignoreCRCMismatches; +} + @end diff --git a/Carthage/Checkouts/UnrarKit/Classes/URKFileInfo.h b/Carthage/Checkouts/UnrarKit/Classes/URKFileInfo.h index 5bf2c95..8cd29fb 100644 --- a/Carthage/Checkouts/UnrarKit/Classes/URKFileInfo.h +++ b/Carthage/Checkouts/UnrarKit/Classes/URKFileInfo.h @@ -4,14 +4,14 @@ // #import -#import "UnrarKitMacros.h" +#import RarosHppIgnore -#import "raros.hpp" +#import #pragma clang diagnostic pop DllHppIgnore -#import "dll.hpp" +#import #pragma clang diagnostic pop /* See http://www.forensicswiki.org/wiki/RAR and diff --git a/Carthage/Checkouts/UnrarKit/Classes/URKFileInfo.m b/Carthage/Checkouts/UnrarKit/Classes/URKFileInfo.m index 24232eb..6b1c083 100644 --- a/Carthage/Checkouts/UnrarKit/Classes/URKFileInfo.m +++ b/Carthage/Checkouts/UnrarKit/Classes/URKFileInfo.m @@ -40,7 +40,7 @@ _isEncryptedWithPassword = fileHeader->Flags & (1 << 2); //_fileHasComment = fileHeader->Flags & (1 << 3) - _isDirectory = fileHeader->Flags & RHDF_DIRECTORY; + _isDirectory = (fileHeader->Flags & RHDF_DIRECTORY) ? YES : NO; } return self; diff --git a/Carthage/Checkouts/UnrarKit/Classes/UnrarKit.h b/Carthage/Checkouts/UnrarKit/Classes/UnrarKit.h index 78db3b3..d2e390e 100644 --- a/Carthage/Checkouts/UnrarKit/Classes/UnrarKit.h +++ b/Carthage/Checkouts/UnrarKit/Classes/UnrarKit.h @@ -15,5 +15,5 @@ FOUNDATION_EXPORT double UnrarKitVersionNumber; FOUNDATION_EXPORT const unsigned char UnrarKitVersionString[]; -#import "URKArchive.h" -#import "URKFileInfo.h" +#import +#import diff --git a/Carthage/Checkouts/UnrarKit/Classes/UnrarKitMacros.h b/Carthage/Checkouts/UnrarKit/Classes/UnrarKitMacros.h index aea9343..38e466f 100644 --- a/Carthage/Checkouts/UnrarKit/Classes/UnrarKitMacros.h +++ b/Carthage/Checkouts/UnrarKit/Classes/UnrarKitMacros.h @@ -60,7 +60,7 @@ __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000 \ #import // Called from +[UnrarKit initialize] and +[URKArchiveTestCase setUp] -extern os_log_t unrarkit_log; // Declared in URKArchive.m +extern os_log_t unrarkit_log; // Declared in URKArchive.mm extern BOOL unrarkitIsAtLeast10_13SDK; // Declared in URKArchive.m #define URKLogInit() \ unrarkit_log = os_log_create("com.abbey-code.UnrarKit", "General"); \ diff --git a/Carthage/Checkouts/UnrarKit/Example/UnrarExample.xcodeproj/project.pbxproj b/Carthage/Checkouts/UnrarKit/Example/UnrarExample.xcodeproj/project.pbxproj index 2d57e06..415b200 100644 --- a/Carthage/Checkouts/UnrarKit/Example/UnrarExample.xcodeproj/project.pbxproj +++ b/Carthage/Checkouts/UnrarKit/Example/UnrarExample.xcodeproj/project.pbxproj @@ -143,17 +143,15 @@ 29B97313FDCFA39411CA2CEA /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0930; + LastUpgradeCheck = 1200; }; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "UnrarExample" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 1; knownRegions = ( - English, - Japanese, - French, - German, + en, + Base, ); mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; projectDirPath = ""; @@ -257,6 +255,7 @@ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -272,14 +271,13 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; ONLY_ACTIVE_ARCH = YES; OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)"; OTHER_LDFLAGS = ( "-lc++", "-all_load", ); - PREBINDING = NO; SDKROOT = iphoneos; }; name = Debug; @@ -301,6 +299,7 @@ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -316,13 +315,12 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; OTHER_LDFLAGS = ( "-lc++", "-all_load", ); - PREBINDING = NO; SDKROOT = iphoneos; WARNING_CFLAGS = "-Wno-error=unused-command-line-argument"; }; diff --git a/Carthage/Checkouts/UnrarKit/Example/UnrarExample.xcodeproj/xcshareddata/xcschemes/UnrarExample.xcscheme b/Carthage/Checkouts/UnrarKit/Example/UnrarExample.xcodeproj/xcshareddata/xcschemes/UnrarExample.xcscheme index 10829dc..1c9263a 100644 --- a/Carthage/Checkouts/UnrarKit/Example/UnrarExample.xcodeproj/xcshareddata/xcschemes/UnrarExample.xcscheme +++ b/Carthage/Checkouts/UnrarKit/Example/UnrarExample.xcodeproj/xcshareddata/xcschemes/UnrarExample.xcscheme @@ -1,6 +1,6 @@ - - - - + + - - *CmtData) { if (!MainComment) return false; - SaveFilePos SavePos(*this); + int64 SavePos=Tell(); + bool Success=DoGetComment(CmtData); + Seek(SavePos,SEEK_SET); + return Success; +} + +bool Archive::DoGetComment(Array *CmtData) +{ #ifndef SFX_MODULE uint CmtLength; if (Format==RARFMT14) @@ -34,7 +41,7 @@ bool Archive::GetComment(Array *CmtData) #ifndef SFX_MODULE // Old style (RAR 2.9) comment header embedded into the main // archive header. - if (BrokenHeader) + if (BrokenHeader || CommHead.HeadSize *CmtData) #else UnpCmtLength=GetByte(); UnpCmtLength+=(GetByte()<<8); + if (CmtLength<2) + return false; CmtLength-=2; DataIO.SetCmt13Encryption(); CommHead.UnpVer=15; @@ -85,15 +94,18 @@ bool Archive::GetComment(Array *CmtData) byte *UnpData; size_t UnpDataSize; DataIO.GetUnpackedData(&UnpData,&UnpDataSize); + if (UnpDataSize>0) + { #ifdef _WIN_ALL - // If we ever decide to extend it to Android, we'll need to alloc - // 4x memory for OEM to UTF-8 output here. - OemToCharBuffA((char *)UnpData,(char *)UnpData,(DWORD)UnpDataSize); + // If we ever decide to extend it to Android, we'll need to alloc + // 4x memory for OEM to UTF-8 output here. + OemToCharBuffA((char *)UnpData,(char *)UnpData,(DWORD)UnpDataSize); #endif - CmtData->Alloc(UnpDataSize+1); - memset(CmtData->Addr(0),0,CmtData->Size()*sizeof(wchar)); - CharToWide((char *)UnpData,CmtData->Addr(0),CmtData->Size()); - CmtData->Alloc(wcslen(CmtData->Addr(0))); + CmtData->Alloc(UnpDataSize+1); + memset(CmtData->Addr(0),0,CmtData->Size()*sizeof(wchar)); + CharToWide((char *)UnpData,CmtData->Addr(0),CmtData->Size()); + CmtData->Alloc(wcslen(CmtData->Addr(0))); + } } } else @@ -131,7 +143,7 @@ bool Archive::GetComment(Array *CmtData) bool Archive::ReadCommentData(Array *CmtData) { Array CmtRaw; - if (!ReadSubData(&CmtRaw,NULL)) + if (!ReadSubData(&CmtRaw,NULL,false)) return false; size_t CmtSize=CmtRaw.Size(); CmtRaw.Push(0); diff --git a/Carthage/Checkouts/UnrarKit/Libraries/unrar/archive.cpp b/Carthage/Checkouts/UnrarKit/Libraries/unrar/archive.cpp index 6532869..8c5a1da 100644 --- a/Carthage/Checkouts/UnrarKit/Libraries/unrar/archive.cpp +++ b/Carthage/Checkouts/UnrarKit/Libraries/unrar/archive.cpp @@ -208,15 +208,16 @@ bool Archive::IsArchive(bool EnableBroken) break; } - // This check allows to make RS based recovery even if password is incorrect. - // But we should not do it for EnableBroken or we'll get 'not RAR archive' + + // We should not do it for EnableBroken or we'll get 'not RAR archive' // messages when extracting encrypted archives with wrong password. if (FailedHeaderDecryption && !EnableBroken) return false; if (BrokenHeader || !StartFound) // Main archive header is corrupt or missing. { - uiMsg(UIERROR_MHEADERBROKEN,FileName); + if (!FailedHeaderDecryption) // If not reported a wrong password already. + uiMsg(UIERROR_MHEADERBROKEN,FileName); if (!EnableBroken) return false; } @@ -232,7 +233,7 @@ bool Archive::IsArchive(bool EnableBroken) // immediately after IsArchive call. if (HeadersLeft && (!SilentOpen || !Encrypted)) { - SaveFilePos SavePos(*this); + int64 SavePos=Tell(); int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos; HEADER_TYPE SaveCurHeaderType=CurHeaderType; @@ -261,6 +262,7 @@ bool Archive::IsArchive(bool EnableBroken) CurBlockPos=SaveCurBlockPos; NextBlockPos=SaveNextBlockPos; CurHeaderType=SaveCurHeaderType; + Seek(SavePos,SEEK_SET); } if (!Volume || FirstVolume) wcsncpyz(FirstVolumeName,FileName,ASIZE(FirstVolumeName)); diff --git a/Carthage/Checkouts/UnrarKit/Libraries/unrar/archive.hpp b/Carthage/Checkouts/UnrarKit/Libraries/unrar/archive.hpp index da59973..d9518f1 100644 --- a/Carthage/Checkouts/UnrarKit/Libraries/unrar/archive.hpp +++ b/Carthage/Checkouts/UnrarKit/Libraries/unrar/archive.hpp @@ -20,13 +20,15 @@ enum ADDSUBDATA_FLAGS ASDF_CRYPTIFHEADERS = 8 // Encrypt data after subheader only in -hp mode. }; +// RAR5 headers must not exceed 2 MB. +#define MAX_HEADER_SIZE_RAR5 0x200000 + class Archive:public File { private: void UpdateLatestTime(FileHeader *CurBlock); void ConvertNameCase(wchar *Name); void ConvertFileHeader(FileHeader *hd); - void WriteBlock50(HEADER_TYPE HeaderType,BaseBlock *wb,bool OnlySetSize,bool NonFinalWrite); size_t ReadHeader14(); size_t ReadHeader15(); size_t ReadHeader50(); @@ -34,8 +36,8 @@ class Archive:public File void RequestArcPassword(); void UnexpEndArcMsg(); void BrokenHeaderMsg(); - void UnkEncVerMsg(const wchar *Name); - void UnkEncVerMsg(); + void UnkEncVerMsg(const wchar *Name,const wchar *Info); + bool DoGetComment(Array *CmtData); bool ReadCommentData(Array *CmtData); #if !defined(RAR_NOCRYPT) @@ -63,8 +65,6 @@ class Archive:public File size_t SearchBlock(HEADER_TYPE HeaderType); size_t SearchSubBlock(const wchar *Type); size_t SearchRR(); - void WriteBlock(HEADER_TYPE HeaderType,BaseBlock *wb=NULL,bool OnlySetSize=false,bool NonFinalWrite=false); - void SetBlockSize(HEADER_TYPE HeaderType,BaseBlock *wb=NULL) {WriteBlock(HeaderType,wb,true);} size_t ReadHeader(); void CheckArc(bool EnableBroken); void CheckOpen(const wchar *Name); @@ -81,8 +81,8 @@ class Archive:public File int64 GetStartPos(); void AddSubData(byte *SrcData,uint64 DataSize,File *SrcFile, const wchar *Name,uint Flags); - bool ReadSubData(Array *UnpData,File *DestFile); - HEADER_TYPE GetHeaderType() {return CurHeaderType;}; + bool ReadSubData(Array *UnpData,File *DestFile,bool TestMode); + HEADER_TYPE GetHeaderType() {return CurHeaderType;} RAROptions* GetRAROptions() {return Cmd;} void SetSilentOpen(bool Mode) {SilentOpen=Mode;} #if 0 diff --git a/Carthage/Checkouts/UnrarKit/Libraries/unrar/arcread.cpp b/Carthage/Checkouts/UnrarKit/Libraries/unrar/arcread.cpp index 4045b5e..b0cf39f 100644 --- a/Carthage/Checkouts/UnrarKit/Libraries/unrar/arcread.cpp +++ b/Carthage/Checkouts/UnrarKit/Libraries/unrar/arcread.cpp @@ -10,7 +10,10 @@ size_t Archive::ReadHeader() CurBlockPos=Tell(); - size_t ReadSize; + // Other developers asked us to initialize it to suppress "may be used + // uninitialized" warning in code below in some compilers. + size_t ReadSize=0; + switch(Format) { #ifndef SFX_MODULE @@ -113,9 +116,9 @@ void Archive::BrokenHeaderMsg() } -void Archive::UnkEncVerMsg(const wchar *Name) +void Archive::UnkEncVerMsg(const wchar *Name,const wchar *Info) { - uiMsg(UIERROR_UNKNOWNENCMETHOD,FileName,Name); + uiMsg(UIERROR_UNKNOWNENCMETHOD,FileName,Name,Info); ErrHandler.SetErrorCode(RARX_WARNING); } @@ -201,7 +204,7 @@ size_t Archive::ReadHeader15() if (ShortBlock.HeaderType==HEAD_MAIN && (ShortBlock.Flags & MHD_COMMENT)!=0) { // Old style (up to RAR 2.9) main archive comment embedded into - // the main archive header found. While we can read the entire + // the main archive header found. While we can read the entire // ShortBlock.HeadSize here and remove this part of "if", it would be // waste of memory, because we'll read and process this comment data // in other function anyway and we do not need them here now. @@ -227,7 +230,7 @@ size_t Archive::ReadHeader15() Encrypted=(MainHead.Flags & MHD_PASSWORD)!=0; Signed=MainHead.PosAV!=0 || MainHead.HighPosAV!=0; MainHead.CommentInHeader=(MainHead.Flags & MHD_COMMENT)!=0; - + // Only for encrypted 3.0+ archives. 2.x archives did not have this // flag, so for non-encrypted archives, we'll set it later based on // file attributes. @@ -254,7 +257,7 @@ size_t Archive::ReadHeader15() hd->WinSize=hd->Dir ? 0:0x10000<<((hd->Flags & LHD_WINDOWMASK)>>5); hd->CommentInHeader=(hd->Flags & LHD_COMMENT)!=0; hd->Version=(hd->Flags & LHD_VERSION)!=0; - + hd->DataSize=Raw.Get4(); uint LowUnpSize=Raw.Get4(); hd->HostOS=Raw.Get1(); @@ -265,21 +268,21 @@ size_t Archive::ReadHeader15() uint FileTime=Raw.Get4(); hd->UnpVer=Raw.Get1(); - // RAR15 did not use the special dictionary size to mark dirs. - if (hd->UnpVer<20 && (hd->FileAttr & 0x10)!=0) - hd->Dir=true; - hd->Method=Raw.Get1()-0x30; size_t NameSize=Raw.Get2(); hd->FileAttr=Raw.Get4(); + // RAR15 did not use the special dictionary size to mark dirs. + if (hd->UnpVer<20 && (hd->FileAttr & 0x10)!=0) + hd->Dir=true; + hd->CryptMethod=CRYPT_NONE; if (hd->Encrypted) switch(hd->UnpVer) { case 13: hd->CryptMethod=CRYPT_RAR13; break; case 15: hd->CryptMethod=CRYPT_RAR15; break; - case 20: + case 20: case 26: hd->CryptMethod=CRYPT_RAR20; break; default: hd->CryptMethod=CRYPT_RAR30; break; } @@ -301,7 +304,7 @@ size_t Archive::ReadHeader15() } hd->Inherited=!FileBlock && (hd->SubFlags & SUBHEAD_FLAGS_INHERITED)!=0; - + hd->LargeFile=(hd->Flags & LHD_LARGE)!=0; uint HighPackSize,HighUnpSize; @@ -311,7 +314,7 @@ size_t Archive::ReadHeader15() HighUnpSize=Raw.Get4(); hd->UnknownUnpSize=(LowUnpSize==0xffffffff && HighUnpSize==0xffffffff); } - else + else { HighPackSize=HighUnpSize=0; // UnpSize equal to 0xffffffff without LHD_LARGE flag indicates @@ -399,8 +402,8 @@ size_t Archive::ReadHeader15() if (rmode & 4) rlt.Second++; rlt.Reminder=0; - int count=rmode&3; - for (int J=0;J. Wrong password can be intentionally provided + // in -p to not stop batch processing for encrypted archives. + bool GlobalPassword=Cmd->Password.IsSet() || uiIsGlobalPasswordSet(); + while (true) // Repeat the password prompt for wrong passwords. { RequestArcPassword(); @@ -572,11 +579,23 @@ size_t Archive::ReadHeader50() // Verify password validity. if (CryptHead.UsePswCheck && memcmp(PswCheck,CryptHead.PswCheck,SIZE_PSWCHECK)!=0) { - // This message is used by Android GUI and Windows GUI and SFX to - // reset cached passwords. Update appropriate code if changed. - uiMsg(UIWAIT_BADPSW,FileName); + if (GlobalPassword) // For -p or Ctrl+P. + { + // This message is used by Android GUI to reset cached passwords. + // Update appropriate code if changed. + uiMsg(UIERROR_BADPSW,FileName,FileName); + FailedHeaderDecryption=true; + ErrHandler.SetErrorCode(RARX_BADPWD); + return 0; + } + else // For passwords entered manually. + { + // This message is used by Android GUI and Windows GUI and SFX to + // reset cached passwords. Update appropriate code if changed. + uiMsg(UIWAIT_BADPSW,FileName,FileName); + Cmd->Password.Clean(); + } - Cmd->Password.Clean(); #ifdef RARDLL // Avoid new requests for unrar.dll to prevent the infinite loop // if app always returns the same password. @@ -595,8 +614,8 @@ size_t Archive::ReadHeader50() } // Header size must not occupy more than 3 variable length integer bytes - // resulting in 2 MB maximum header size, so here we read 4 byte CRC32 - // followed by 3 bytes or less of header size. + // resulting in 2 MB maximum header size (MAX_HEADER_SIZE_RAR5), + // so here we read 4 byte CRC32 followed by 3 bytes or less of header size. const size_t FirstReadSize=7; // Smallest possible block size. if (Raw.Read(FirstReadSize)CRYPT_VERSION) { - UnkEncVerMsg(FileName); + wchar Info[20]; + swprintf(Info,ASIZE(Info),L"h%u",CryptVersion); + UnkEncVerMsg(FileName,Info); return 0; } uint EncFlags=(uint)Raw.GetV(); @@ -693,9 +714,12 @@ size_t Archive::ReadHeader50() CryptHead.Lg2Count=Raw.Get1(); if (CryptHead.Lg2Count>CRYPT5_KDF_LG2_COUNT_MAX) { - UnkEncVerMsg(FileName); + wchar Info[20]; + swprintf(Info,ASIZE(Info),L"hc%u",CryptHead.Lg2Count); + UnkEncVerMsg(FileName,Info); return 0; } + Raw.GetB(CryptHead.Salt,SIZE_SALT50); if (CryptHead.UsePswCheck) { @@ -746,7 +770,7 @@ size_t Archive::ReadHeader50() // to not break normal archive processing by calling function. int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos; HEADER_TYPE SaveCurHeaderType=CurHeaderType; - + QOpen.Init(this,false); QOpen.Load(MainHead.QOpenOffset); @@ -771,7 +795,7 @@ size_t Archive::ReadHeader50() hd->PackSize=DataSize; hd->FileFlags=(uint)Raw.GetV(); hd->UnpSize=Raw.GetV(); - + hd->UnknownUnpSize=(hd->FileFlags & FHFL_UNPUNKNOWN)!=0; if (hd->UnknownUnpSize) hd->UnpSize=INT64NDF; @@ -798,6 +822,8 @@ size_t Archive::ReadHeader50() // but it was already used in RAR 1.5 and Unpack needs to distinguish // them. hd->UnpVer=(CompInfo & 0x3f) + 50; + if (hd->UnpVer!=50) // Only 5.0 compression is known now. + hd->UnpVer=VER_UNKNOWN; hd->HostOS=(byte)Raw.GetV(); size_t NameSize=(size_t)Raw.GetV(); @@ -856,7 +882,7 @@ size_t Archive::ReadHeader50() RecoverySize=Header.RecSectionSize*Header.RecCount; } #endif - + if (BadCRC) // Add the file name to broken header message displayed above. uiMsg(UIERROR_FHEADERBROKEN,Archive::FileName,hd->FileName); } @@ -972,8 +998,12 @@ void Archive::ProcessExtra50(RawRead *Raw,size_t ExtraSize,BaseBlock *bb) { FileHeader *hd=(FileHeader *)bb; uint EncVersion=(uint)Raw->GetV(); - if (EncVersion > CRYPT_VERSION) - UnkEncVerMsg(hd->FileName); + if (EncVersion>CRYPT_VERSION) + { + wchar Info[20]; + swprintf(Info,ASIZE(Info),L"x%u",EncVersion); + UnkEncVerMsg(hd->FileName,Info); + } else { uint Flags=(uint)Raw->GetV(); @@ -981,7 +1011,11 @@ void Archive::ProcessExtra50(RawRead *Raw,size_t ExtraSize,BaseBlock *bb) hd->UseHashKey=(Flags & FHEXTRA_CRYPT_HASHMAC)!=0; hd->Lg2Count=Raw->Get1(); if (hd->Lg2Count>CRYPT5_KDF_LG2_COUNT_MAX) - UnkEncVerMsg(hd->FileName); + { + wchar Info[20]; + swprintf(Info,ASIZE(Info),L"xc%u",hd->Lg2Count); + UnkEncVerMsg(hd->FileName,Info); + } Raw->GetB(hd->Salt,SIZE_SALT50); Raw->GetB(hd->InitV,SIZE_INITV); if (hd->UsePswCheck) @@ -1222,11 +1256,13 @@ size_t Archive::ReadHeader14() Raw.Read(NameSize); char FileName[NM]; - Raw.GetB((byte *)FileName,Min(NameSize,ASIZE(FileName))); - FileName[NameSize]=0; + size_t ReadNameSize=Min(NameSize,ASIZE(FileName)-1); + Raw.GetB((byte *)FileName,ReadNameSize); + FileName[ReadNameSize]=0; IntToExt(FileName,FileName,ASIZE(FileName)); CharToWide(FileName,FileHead.FileName,ASIZE(FileHead.FileName)); ConvertNameCase(FileHead.FileName); + ConvertFileHeader(&FileHead); if (Raw.Size()!=0) NextBlockPos=CurBlockPos+FileHead.HeadSize+FileHead.PackSize; @@ -1273,7 +1309,7 @@ void Archive::ConvertAttributes() if (mask == (mode_t) -1) { - // umask call returns the current umask value. Argument (022) is not + // umask call returns the current umask value. Argument (022) is not // really important here. mask = umask(022); @@ -1350,8 +1386,8 @@ void Archive::ConvertFileHeader(FileHeader *hd) // ':' in file names is allowed in Unix, but not in Windows. // Even worse, file data will be written to NTFS stream on NTFS, - // so automatic name correction on file create error in extraction - // routine does not work. In Windows and DOS versions we better + // so automatic name correction on file create error in extraction + // routine does not work. In Windows and DOS versions we better // replace ':' now. if (*s==':') *s='_'; @@ -1380,7 +1416,7 @@ int64 Archive::GetStartPos() } -bool Archive::ReadSubData(Array *UnpData,File *DestFile) +bool Archive::ReadSubData(Array *UnpData,File *DestFile,bool TestMode) { if (BrokenHeader) { @@ -1428,6 +1464,7 @@ bool Archive::ReadSubData(Array *UnpData,File *DestFile) SubDataIO.SetPackedSizeToRead(SubHead.PackSize); SubDataIO.EnableShowProgress(false); SubDataIO.SetFiles(this,DestFile); + SubDataIO.SetTestMode(TestMode); SubDataIO.UnpVolume=SubHead.SplitAfter; SubDataIO.SetSubHeader(&SubHead,NULL); Unpack.SetDestSize(SubHead.UnpSize); diff --git a/Carthage/Checkouts/UnrarKit/Libraries/unrar/blake2s.hpp b/Carthage/Checkouts/UnrarKit/Libraries/unrar/blake2s.hpp index 7dd7157..f88ef37 100644 --- a/Carthage/Checkouts/UnrarKit/Libraries/unrar/blake2s.hpp +++ b/Carthage/Checkouts/UnrarKit/Libraries/unrar/blake2s.hpp @@ -3,6 +3,7 @@ #define _RAR_BLAKE2_ #define BLAKE2_DIGEST_SIZE 32 +#define BLAKE2_THREADS_NUMBER 8 enum blake2s_constant { diff --git a/Carthage/Checkouts/UnrarKit/Libraries/unrar/cmddata.cpp b/Carthage/Checkouts/UnrarKit/Libraries/unrar/cmddata.cpp index 32b8412..74e565a 100644 --- a/Carthage/Checkouts/UnrarKit/Libraries/unrar/cmddata.cpp +++ b/Carthage/Checkouts/UnrarKit/Libraries/unrar/cmddata.cpp @@ -1,5 +1,8 @@ #include "rar.hpp" +#include "cmdfilter.cpp" +#include "cmdmix.cpp" + CommandData::CommandData() { Init(); @@ -120,6 +123,7 @@ void CommandData::ParseArg(wchar *Arg) wchar CmdChar=toupperw(*Command); bool Add=wcschr(L"AFUM",CmdChar)!=NULL; bool Extract=CmdChar=='X' || CmdChar=='E'; + bool Repair=CmdChar=='R' && Command[1]==0; if (EndSeparator && !Add) wcsncpyz(ExtrPath,Arg,ASIZE(ExtrPath)); else @@ -130,15 +134,15 @@ void CommandData::ParseArg(wchar *Arg) FindData FileData; bool Found=FindFile::FastFind(Arg,&FileData); if ((!Found || ListMode==RCLM_ACCEPT_LISTS) && - ListMode!=RCLM_REJECT_LISTS && *Arg=='@' && !IsWildcard(Arg)) + ListMode!=RCLM_REJECT_LISTS && *Arg=='@' && !IsWildcard(Arg+1)) { FileLists=true; ReadTextFile(Arg+1,&FileArgs,false,true,FilelistCharset,true,true,true); } - else - if (Found && FileData.IsDir && Extract && *ExtrPath==0) + else // We use 'destpath\' when extracting and reparing. + if (Found && FileData.IsDir && (Extract || Repair) && *ExtrPath==0) { wcsncpyz(ExtrPath,Arg,ASIZE(ExtrPath)); AddEndSlash(ExtrPath,ASIZE(ExtrPath)); @@ -280,17 +284,24 @@ void CommandData::ProcessSwitch(const wchar *Switch) ClearArc=true; break; case 'D': - AppendArcNameToPath=true; + if (Switch[2]==0) + AppendArcNameToPath=APPENDARCNAME_DESTPATH; + else + if (Switch[2]=='1') + AppendArcNameToPath=APPENDARCNAME_OWNDIR; break; #ifndef SFX_MODULE case 'G': if (Switch[2]=='-' && Switch[3]==0) GenerateArcName=0; else - { - GenerateArcName=true; - wcsncpyz(GenerateMask,Switch+2,ASIZE(GenerateMask)); - } + if (toupperw(Switch[2])=='F') + wcsncpyz(DefGenerateMask,Switch+3,ASIZE(DefGenerateMask)); + else + { + GenerateArcName=true; + wcsncpyz(GenerateMask,Switch+2,ASIZE(GenerateMask)); + } break; #endif case 'I': @@ -302,7 +313,7 @@ void CommandData::ProcessSwitch(const wchar *Switch) AddArcOnly=true; break; case 'P': - wcscpy(ArcPath,Switch+2); + wcsncpyz(ArcPath,Switch+2,ASIZE(ArcPath)); break; case 'S': SyncFiles=true; @@ -365,11 +376,11 @@ void CommandData::ProcessSwitch(const wchar *Switch) default: if (Switch[1]=='+') { - InclFileAttr|=GetExclAttr(Switch+2); + InclFileAttr|=GetExclAttr(Switch+2,InclDir); InclAttrSet=true; } else - ExclFileAttr|=GetExclAttr(Switch+1); + ExclFileAttr|=GetExclAttr(Switch+1,ExclDir); break; } break; @@ -407,9 +418,9 @@ void CommandData::ProcessSwitch(const wchar *Switch) wcsncpyz(LogName,Switch[4]!=0 ? Switch+4:DefLogName,ASIZE(LogName)); break; } - if (wcsicomp(Switch+1,L"SND")==0) + if (wcsnicomp(Switch+1,L"SND",3)==0) { - Sound=true; + Sound=Switch[4]=='-' ? SOUND_NOTIFY_OFF : SOUND_NOTIFY_ON; break; } if (wcsicomp(Switch+1,L"ERR")==0) @@ -805,51 +816,19 @@ void CommandData::ProcessSwitch(const wchar *Switch) ArcTime=ARCTIME_LATEST; break; case 'O': - FileTimeBefore.SetAgeText(Switch+2); + SetTimeFilters(Switch+2,true,true); break; case 'N': - FileTimeAfter.SetAgeText(Switch+2); + SetTimeFilters(Switch+2,false,true); break; case 'B': - FileTimeBefore.SetIsoText(Switch+2); + SetTimeFilters(Switch+2,true,false); break; case 'A': - FileTimeAfter.SetIsoText(Switch+2); + SetTimeFilters(Switch+2,false,false); break; case 'S': - { - EXTTIME_MODE Mode=EXTTIME_HIGH3; - bool CommonMode=Switch[2]>='0' && Switch[2]<='4'; - if (CommonMode) - Mode=(EXTTIME_MODE)(Switch[2]-'0'); - if (Mode==EXTTIME_HIGH1 || Mode==EXTTIME_HIGH2) // '2' and '3' not supported anymore. - Mode=EXTTIME_HIGH3; - if (Switch[2]=='-') - Mode=EXTTIME_NONE; - if (CommonMode || Switch[2]=='-' || Switch[2]=='+' || Switch[2]==0) - xmtime=xctime=xatime=Mode; - else - { - if (Switch[3]>='0' && Switch[3]<='4') - Mode=(EXTTIME_MODE)(Switch[3]-'0'); - if (Mode==EXTTIME_HIGH1 || Mode==EXTTIME_HIGH2) // '2' and '3' not supported anymore. - Mode=EXTTIME_HIGH3; - if (Switch[3]=='-') - Mode=EXTTIME_NONE; - switch(toupperw(Switch[2])) - { - case 'M': - xmtime=Mode; - break; - case 'C': - xctime=Mode; - break; - case 'A': - xatime=Mode; - break; - } - } - } + SetStoreTimeMode(Switch+2); break; case '-': Test=false; @@ -897,7 +876,7 @@ void CommandData::ProcessSwitch(const wchar *Switch) if (Switch[1]==0) { // If comment file is not specified, we read data from stdin. - wcscpy(CommentFile,L"stdin"); + wcsncpyz(CommentFile,L"stdin",ASIZE(CommentFile)); } else wcsncpyz(CommentFile,Switch+1,ASIZE(CommentFile)); @@ -922,309 +901,6 @@ void CommandData::BadSwitch(const wchar *Switch) #endif -void CommandData::OutTitle() -{ - if (BareOutput || DisableCopyright) - return; -#if defined(__GNUC__) && defined(SFX_MODULE) - mprintf(St(MCopyrightS)); -#else -#ifndef SILENT - static bool TitleShown=false; - if (TitleShown) - return; - TitleShown=true; - - wchar Version[80]; - if (RARVER_BETA!=0) - swprintf(Version,ASIZE(Version),L"%d.%02d %ls %d",RARVER_MAJOR,RARVER_MINOR,St(MBeta),RARVER_BETA); - else - swprintf(Version,ASIZE(Version),L"%d.%02d",RARVER_MAJOR,RARVER_MINOR); -#if defined(_WIN_32) || defined(_WIN_64) - wcsncatz(Version,L" ",ASIZE(Version)); -#endif -#ifdef _WIN_32 - wcsncatz(Version,St(Mx86),ASIZE(Version)); -#endif -#ifdef _WIN_64 - wcsncatz(Version,St(Mx64),ASIZE(Version)); -#endif - if (PrintVersion) - { - mprintf(L"%s",Version); - exit(0); - } - mprintf(St(MUCopyright),Version,RARVER_YEAR); -#endif -#endif -} - - -inline bool CmpMSGID(MSGID i1,MSGID i2) -{ -#ifdef MSGID_INT - return i1==i2; -#else - // If MSGID is const char*, we cannot compare pointers only. - // Pointers to different instances of same string can differ, - // so we need to compare complete strings. - return wcscmp(i1,i2)==0; -#endif -} - -void CommandData::OutHelp(RAR_EXIT ExitCode) -{ -#if !defined(SILENT) - OutTitle(); - static MSGID Help[]={ -#ifdef SFX_MODULE - // Console SFX switches definition. - MCHelpCmd,MSHelpCmdE,MSHelpCmdT,MSHelpCmdV -#else - // UnRAR switches definition. - MUNRARTitle1,MRARTitle2,MCHelpCmd,MCHelpCmdE,MCHelpCmdL, - MCHelpCmdP,MCHelpCmdT,MCHelpCmdV,MCHelpCmdX,MCHelpSw,MCHelpSwm, - MCHelpSwAT,MCHelpSwAC,MCHelpSwAD,MCHelpSwAG,MCHelpSwAI,MCHelpSwAP, - MCHelpSwCm,MCHelpSwCFGm,MCHelpSwCL,MCHelpSwCU, - MCHelpSwDH,MCHelpSwEP,MCHelpSwEP3,MCHelpSwF,MCHelpSwIDP,MCHelpSwIERR, - MCHelpSwINUL,MCHelpSwIOFF,MCHelpSwKB,MCHelpSwN,MCHelpSwNa,MCHelpSwNal, - MCHelpSwO,MCHelpSwOC,MCHelpSwOL,MCHelpSwOR,MCHelpSwOW,MCHelpSwP, - MCHelpSwPm,MCHelpSwR,MCHelpSwRI,MCHelpSwSC,MCHelpSwSL,MCHelpSwSM, - MCHelpSwTA,MCHelpSwTB,MCHelpSwTN,MCHelpSwTO,MCHelpSwTS,MCHelpSwU, - MCHelpSwVUnr,MCHelpSwVER,MCHelpSwVP,MCHelpSwX,MCHelpSwXa,MCHelpSwXal, - MCHelpSwY -#endif - }; - - for (uint I=0;IRewind(); - while (Args->GetString(CurMask,ASIZE(CurMask))) - { - wchar *LastMaskChar=PointToLastChar(CurMask); - bool DirMask=IsPathDiv(*LastMaskChar); // Mask for directories only. - - if (Dir) - { - // CheckName is a directory. - if (DirMask) - { - // We process the directory and have the directory exclusion mask. - // So let's convert "mask\" to "mask" and process it normally. - - *LastMaskChar=0; - } - else - { - // REMOVED, we want -npath\* to match empty folders too. - // If mask has wildcards in name part and does not have the trailing - // '\' character, we cannot use it for directories. - - // if (IsWildcard(PointToName(CurMask))) - // continue; - } - } - else - { - // If we process a file inside of directory excluded by "dirmask\". - // we want to exclude such file too. So we convert "dirmask\" to - // "dirmask\*". It is important for operations other than archiving - // with -x. When archiving with -x, directory matched by "dirmask\" - // is excluded from further scanning. - - if (DirMask) - wcsncatz(CurMask,L"*",ASIZE(CurMask)); - } - -#ifndef SFX_MODULE - if (CheckFullPath && IsFullPath(CurMask)) - { - // We do not need to do the special "*\" processing here, because - // unlike the "else" part of this "if", now we convert names to full - // format, so they all include the path, which is matched by "*\" - // correctly. Moreover, removing "*\" from mask would break - // the comparison, because now all names have the path. - - if (*FullName==0) - ConvertNameToFull(CheckName,FullName,ASIZE(FullName)); - if (CmpName(CurMask,FullName,MatchMode)) - return true; - } - else -#endif - { - wchar NewName[NM+2],*CurName=Name; - - // Important to convert before "*\" check below, so masks like - // d:*\something are processed properly. - wchar *CmpMask=ConvertPath(CurMask,NULL); - - if (CmpMask[0]=='*' && IsPathDiv(CmpMask[1])) - { - // We want "*\name" to match 'name' not only in subdirectories, - // but also in the current directory. We convert the name - // from 'name' to '.\name' to be matched by "*\" part even if it is - // in current directory. - NewName[0]='.'; - NewName[1]=CPATHDIVIDER; - wcsncpyz(NewName+2,Name,ASIZE(NewName)-2); - CurName=NewName; - } - - if (CmpName(CmpMask,CurName,MatchMode)) - return true; - } - } - return false; -} - - -#ifndef SFX_MODULE -// Now this function performs only one task and only in Windows version: -// it skips symlinks to directories if -e1024 switch is specified. -// Symlinks are skipped in ScanTree class, so their entire contents -// is skipped too. Without this function we would check the attribute -// only directly before archiving, so we would skip the symlink record, -// but not the contents of symlinked directory. -bool CommandData::ExclDirByAttr(uint FileAttr) -{ -#ifdef _WIN_ALL - if ((FileAttr & FILE_ATTRIBUTE_REPARSE_POINT)!=0 && - (ExclFileAttr & FILE_ATTRIBUTE_REPARSE_POINT)!=0) - return true; -#endif - return false; -} -#endif - - - - -#ifndef SFX_MODULE -// Return 'true' if we need to exclude the file from processing. -bool CommandData::TimeCheck(RarTime &ft) -{ - if (FileTimeBefore.IsSet() && ft>=FileTimeBefore) - return true; - if (FileTimeAfter.IsSet() && ft<=FileTimeAfter) - return true; - return false; -} -#endif - - -#ifndef SFX_MODULE -// Return 'true' if we need to exclude the file from processing. -bool CommandData::SizeCheck(int64 Size) -{ - if (FileSizeLess!=INT64NDF && Size>=FileSizeLess) - return(true); - if (FileSizeMore!=INT64NDF && Size<=FileSizeMore) - return(true); - return(false); -} -#endif - - - - -int CommandData::IsProcessFile(FileHeader &FileHead,bool *ExactMatch,int MatchType, - wchar *MatchedArg,uint MatchedArgSize) -{ - if (MatchedArg!=NULL && MatchedArgSize>0) - *MatchedArg=0; -// if (wcslen(FileHead.FileName)>=NM) -// return 0; - bool Dir=FileHead.Dir; - if (ExclCheck(FileHead.FileName,Dir,false,true)) - return 0; -#ifndef SFX_MODULE - if (TimeCheck(FileHead.mtime)) - return 0; - if ((FileHead.FileAttr & ExclFileAttr)!=0 || InclAttrSet && (FileHead.FileAttr & InclFileAttr)==0) - return 0; - if (!Dir && SizeCheck(FileHead.UnpSize)) - return 0; -#endif - wchar *ArgName; - FileArgs.Rewind(); - for (int StringCount=1;(ArgName=FileArgs.GetString())!=NULL;StringCount++) - if (CmpName(ArgName,FileHead.FileName,MatchType)) - { - if (ExactMatch!=NULL) - *ExactMatch=wcsicompc(ArgName,FileHead.FileName)==0; - if (MatchedArg!=NULL) - wcsncpyz(MatchedArg,ArgName,MatchedArgSize); - return StringCount; - } - return 0; -} - - void CommandData::ProcessCommand() { #ifndef SFX_MODULE @@ -1255,7 +931,10 @@ void CommandData::ProcessCommand() if (wcschr(L"AFUMD",*Command)==NULL) { if (GenerateArcName) - GenerateArchiveName(ArcName,ASIZE(ArcName),GenerateMask,false); + { + const wchar *Mask=*GenerateMask!=0 ? GenerateMask:DefGenerateMask; + GenerateArchiveName(ArcName,ASIZE(ArcName),Mask,false); + } StringList ArcMasks; ArcMasks.AddString(ArcName); @@ -1274,7 +953,6 @@ void CommandData::ProcessCommand() case 'X': case 'E': case 'T': - case 'I': { CmdExtract Extract(this); Extract.DoExtract(); @@ -1317,7 +995,7 @@ bool CommandData::IsSwitch(int Ch) #ifndef SFX_MODULE -uint CommandData::GetExclAttr(const wchar *Str) +uint CommandData::GetExclAttr(const wchar *Str,bool &Dir) { if (IsDigit(*Str)) return wcstol(Str,NULL,0); @@ -1327,10 +1005,10 @@ uint CommandData::GetExclAttr(const wchar *Str) { switch(toupperw(*Str)) { -#ifdef _UNIX case 'D': - Attr|=S_IFDIR; + Dir=true; break; +#ifdef _UNIX case 'V': Attr|=S_IFCHR; break; @@ -1344,9 +1022,6 @@ uint CommandData::GetExclAttr(const wchar *Str) case 'S': Attr|=0x4; break; - case 'D': - Attr|=0x10; - break; case 'A': Attr|=0x20; break; diff --git a/Carthage/Checkouts/UnrarKit/Libraries/unrar/cmddata.hpp b/Carthage/Checkouts/UnrarKit/Libraries/unrar/cmddata.hpp index e12d4fb..0c6d148 100644 --- a/Carthage/Checkouts/UnrarKit/Libraries/unrar/cmddata.hpp +++ b/Carthage/Checkouts/UnrarKit/Libraries/unrar/cmddata.hpp @@ -6,13 +6,19 @@ enum RAR_CMD_LIST_MODE {RCLM_AUTO,RCLM_REJECT_LISTS,RCLM_ACCEPT_LISTS}; +enum IS_PROCESS_FILE_FLAGS {IPFF_EXCLUDE_PARENT=1}; + class CommandData:public RAROptions { private: void ProcessSwitchesString(const wchar *Str); void ProcessSwitch(const wchar *Switch); void BadSwitch(const wchar *Switch); - uint GetExclAttr(const wchar *Str); + uint GetExclAttr(const wchar *Str,bool &Dir); +#if !defined(SFX_MODULE) + void SetTimeFilters(const wchar *Mod,bool Before,bool Age); + void SetStoreTimeMode(const wchar *S); +#endif bool FileLists; bool NoMoreSwitches; @@ -34,11 +40,11 @@ class CommandData:public RAROptions bool ExclCheck(const wchar *CheckName,bool Dir,bool CheckFullPath,bool CheckInclList); static bool CheckArgs(StringList *Args,bool Dir,const wchar *CheckName,bool CheckFullPath,int MatchMode); bool ExclDirByAttr(uint FileAttr); - bool TimeCheck(RarTime &ft); + bool TimeCheck(RarTime &ftm,RarTime &ftc,RarTime &fta); bool SizeCheck(int64 Size); bool AnyFiltersActive(); - int IsProcessFile(FileHeader &FileHead,bool *ExactMatch=NULL,int MatchType=MATCH_WILDSUBPATH, - wchar *MatchedArg=NULL,uint MatchedArgSize=0); + int IsProcessFile(FileHeader &FileHead,bool *ExactMatch,int MatchType, + bool Flags,wchar *MatchedArg,uint MatchedArgSize); void ProcessCommand(); void AddArcName(const wchar *Name); bool GetArcName(wchar *Name,int MaxSize); diff --git a/Carthage/Checkouts/UnrarKit/Libraries/unrar/crc.cpp b/Carthage/Checkouts/UnrarKit/Libraries/unrar/crc.cpp index 1097f4c..cf23bbf 100644 --- a/Carthage/Checkouts/UnrarKit/Libraries/unrar/crc.cpp +++ b/Carthage/Checkouts/UnrarKit/Libraries/unrar/crc.cpp @@ -73,7 +73,7 @@ uint CRC32(uint StartCRC,const void *Addr,size_t Size) crc_tables[5][(byte)(StartCRC >> 16)] ^ crc_tables[4][(byte)(StartCRC >> 24)] ^ crc_tables[3][(byte) NextData ] ^ - crc_tables[2][(byte)(NextData >>8 ) ] ^ + crc_tables[2][(byte)(NextData >> 8) ] ^ crc_tables[1][(byte)(NextData >> 16)] ^ crc_tables[0][(byte)(NextData >> 24)]; } diff --git a/Carthage/Checkouts/UnrarKit/Libraries/unrar/crypt3.cpp b/Carthage/Checkouts/UnrarKit/Libraries/unrar/crypt3.cpp index 4840648..fe3bf97 100644 --- a/Carthage/Checkouts/UnrarKit/Libraries/unrar/crypt3.cpp +++ b/Carthage/Checkouts/UnrarKit/Libraries/unrar/crypt3.cpp @@ -28,8 +28,8 @@ void CryptData::SetKey30(bool Encrypt,SecPassword *Password,const wchar *PwdW,co sha1_context c; sha1_init(&c); - const int HashRounds=0x40000; - for (int I=0;I>(J*8)); KDF3Cache[KDF3CachePos].Pwd=*Password; diff --git a/Carthage/Checkouts/UnrarKit/Libraries/unrar/dll.cpp b/Carthage/Checkouts/UnrarKit/Libraries/unrar/dll.cpp index b5eada5..61a68b4 100644 --- a/Carthage/Checkouts/UnrarKit/Libraries/unrar/dll.cpp +++ b/Carthage/Checkouts/UnrarKit/Libraries/unrar/dll.cpp @@ -42,6 +42,7 @@ HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *r) Data->Cmd.DllError=0; Data->OpenMode=r->OpenMode; Data->Cmd.FileArgs.AddString(L"*"); + Data->Cmd.KeepBroken=(r->OpFlags&ROADOF_KEEPBROKEN)!=0; char AnsiArcName[NM]; *AnsiArcName=0; @@ -94,36 +95,50 @@ HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *r) r->Flags=0; if (Data->Arc.Volume) - r->Flags|=0x01; + r->Flags|=ROADF_VOLUME; + if (Data->Arc.MainComment) + r->Flags|=ROADF_COMMENT; if (Data->Arc.Locked) - r->Flags|=0x04; + r->Flags|=ROADF_LOCK; if (Data->Arc.Solid) - r->Flags|=0x08; + r->Flags|=ROADF_SOLID; if (Data->Arc.NewNumbering) - r->Flags|=0x10; + r->Flags|=ROADF_NEWNUMBERING; if (Data->Arc.Signed) - r->Flags|=0x20; + r->Flags|=ROADF_SIGNED; if (Data->Arc.Protected) - r->Flags|=0x40; + r->Flags|=ROADF_RECOVERY; if (Data->Arc.Encrypted) - r->Flags|=0x80; + r->Flags|=ROADF_ENCHEADERS; if (Data->Arc.FirstVolume) - r->Flags|=0x100; + r->Flags|=ROADF_FIRSTVOLUME; Array CmtDataW; if (r->CmtBufSize!=0 && Data->Arc.GetComment(&CmtDataW)) { - Array CmtData(CmtDataW.Size()*4+1); - memset(&CmtData[0],0,CmtData.Size()); - WideToChar(&CmtDataW[0],&CmtData[0],CmtData.Size()-1); - size_t Size=strlen(&CmtData[0])+1; + if (r->CmtBufW!=NULL) + { + CmtDataW.Push(0); + size_t Size=wcslen(&CmtDataW[0])+1; - r->Flags|=2; - r->CmtState=Size>r->CmtBufSize ? ERAR_SMALL_BUF:1; - r->CmtSize=(uint)Min(Size,r->CmtBufSize); - memcpy(r->CmtBuf,&CmtData[0],r->CmtSize-1); - if (Size<=r->CmtBufSize) - r->CmtBuf[r->CmtSize-1]=0; + r->CmtState=Size>r->CmtBufSize ? ERAR_SMALL_BUF:1; + r->CmtSize=(uint)Min(Size,r->CmtBufSize); + memcpy(r->CmtBufW,&CmtDataW[0],(r->CmtSize-1)*sizeof(*r->CmtBufW)); + r->CmtBufW[r->CmtSize-1]=0; + } + else + if (r->CmtBuf!=NULL) + { + Array CmtData(CmtDataW.Size()*4+1); + memset(&CmtData[0],0,CmtData.Size()); + WideToChar(&CmtDataW[0],&CmtData[0],CmtData.Size()-1); + size_t Size=strlen(&CmtData[0])+1; + + r->CmtState=Size>r->CmtBufSize ? ERAR_SMALL_BUF:1; + r->CmtSize=(uint)Min(Size,r->CmtBufSize); + memcpy(r->CmtBuf,&CmtData[0],r->CmtSize-1); + r->CmtBuf[r->CmtSize-1]=0; + } } else r->CmtState=r->CmtSize=0; @@ -253,10 +268,7 @@ int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *D) D->UnpSize=uint(hd->UnpSize & 0xffffffff); D->UnpSizeHigh=uint(hd->UnpSize>>32); D->HostOS=hd->HSType==HSYS_WINDOWS ? HOST_WIN32:HOST_UNIX; - if (Data->Arc.Format==RARFMT50) - D->UnpVer=Data->Arc.FileHead.UnpVer==0 ? 50 : 200; // If it is not 0, just set it to something big. - else - D->UnpVer=Data->Arc.FileHead.UnpVer; + D->UnpVer=Data->Arc.FileHead.UnpVer; D->FileCRC=hd->FileHash.CRC32; D->FileTime=hd->mtime.GetDos(); @@ -372,7 +384,7 @@ int PASCAL ProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestNa if (DestNameW!=NULL) wcsncpyz(Data->Cmd.DllDestName,DestNameW,ASIZE(Data->Cmd.DllDestName)); - wcscpy(Data->Cmd.Command,Operation==RAR_EXTRACT ? L"X":L"T"); + wcsncpyz(Data->Cmd.Command,Operation==RAR_EXTRACT ? L"X":L"T",ASIZE(Data->Cmd.Command)); Data->Cmd.Test=Operation!=RAR_EXTRACT; bool Repeat=false; Data->Extract.ExtractCurrentFile(Data->Arc,Data->HeaderSize,Repeat); @@ -439,16 +451,16 @@ void PASCAL RARSetProcessDataProc(HANDLE hArcData,PROCESSDATAPROC ProcessDataPro } -#ifndef RAR_NOCRYPT void PASCAL RARSetPassword(HANDLE hArcData,char *Password) { +#ifndef RAR_NOCRYPT DataSet *Data=(DataSet *)hArcData; wchar PasswordW[MAXPASSWORD]; GetWideName(Password,NULL,PasswordW,ASIZE(PasswordW)); Data->Cmd.Password.Set(PasswordW); cleandata(PasswordW,sizeof(PasswordW)); -} #endif +} int PASCAL RARGetDllVersion() diff --git a/Carthage/Checkouts/UnrarKit/Libraries/unrar/dll.def b/Carthage/Checkouts/UnrarKit/Libraries/unrar/dll.def index 660f69b..3c9a2c8 100644 --- a/Carthage/Checkouts/UnrarKit/Libraries/unrar/dll.def +++ b/Carthage/Checkouts/UnrarKit/Libraries/unrar/dll.def @@ -5,6 +5,7 @@ EXPORTS RARReadHeader RARReadHeaderEx RARProcessFile + RARProcessFileW RARSetCallback RARSetChangeVolProc RARSetProcessDataProc diff --git a/Carthage/Checkouts/UnrarKit/Libraries/unrar/dll.hpp b/Carthage/Checkouts/UnrarKit/Libraries/unrar/dll.hpp index 7f82906..c785ff1 100644 --- a/Carthage/Checkouts/UnrarKit/Libraries/unrar/dll.hpp +++ b/Carthage/Checkouts/UnrarKit/Libraries/unrar/dll.hpp @@ -1,7 +1,7 @@ #ifndef _UNRAR_DLL_ #define _UNRAR_DLL_ -#pragma pack(1) +#pragma pack(push, 1) #define ERAR_SUCCESS 0 #define ERAR_END_ARCHIVE 10 @@ -135,6 +135,8 @@ typedef int (CALLBACK *UNRARCALLBACK)(UINT msg,LPARAM UserData,LPARAM P1,LPARAM #define ROADF_ENCHEADERS 0x0080 #define ROADF_FIRSTVOLUME 0x0100 +#define ROADOF_KEEPBROKEN 0x0001 + struct RAROpenArchiveDataEx { char *ArcName; @@ -148,7 +150,9 @@ struct RAROpenArchiveDataEx unsigned int Flags; UNRARCALLBACK Callback; LPARAM UserData; - unsigned int Reserved[28]; + unsigned int OpFlags; + wchar_t *CmtBufW; + unsigned int Reserved[25]; }; enum UNRARCALLBACK_MESSAGES { @@ -180,6 +184,6 @@ int PASCAL RARGetDllVersion(); } #endif -#pragma pack() +#pragma pack(pop) #endif diff --git a/Carthage/Checkouts/UnrarKit/Libraries/unrar/dll.rc b/Carthage/Checkouts/UnrarKit/Libraries/unrar/dll.rc index c28ecfb..7ff2021 100644 --- a/Carthage/Checkouts/UnrarKit/Libraries/unrar/dll.rc +++ b/Carthage/Checkouts/UnrarKit/Libraries/unrar/dll.rc @@ -2,8 +2,8 @@ #include VS_VERSION_INFO VERSIONINFO -FILEVERSION 5, 60, 3, 2672 -PRODUCTVERSION 5, 60, 3, 2672 +FILEVERSION 5, 91, 100, 3470 +PRODUCTVERSION 5, 91, 100, 3470 FILEOS VOS__WINDOWS32 FILETYPE VFT_APP { @@ -14,9 +14,9 @@ FILETYPE VFT_APP VALUE "CompanyName", "Alexander Roshal\0" VALUE "ProductName", "RAR decompression library\0" VALUE "FileDescription", "RAR decompression library\0" - VALUE "FileVersion", "5.60.3\0" - VALUE "ProductVersion", "5.60.3\0" - VALUE "LegalCopyright", "Copyright © Alexander Roshal 1993-2018\0" + VALUE "FileVersion", "5.91.0\0" + VALUE "ProductVersion", "5.91.0\0" + VALUE "LegalCopyright", "Copyright © Alexander Roshal 1993-2020\0" VALUE "OriginalFilename", "Unrar.dll\0" } } diff --git a/Carthage/Checkouts/UnrarKit/Libraries/unrar/errhnd.cpp b/Carthage/Checkouts/UnrarKit/Libraries/unrar/errhnd.cpp index b2f76a8..c86d176 100644 --- a/Carthage/Checkouts/UnrarKit/Libraries/unrar/errhnd.cpp +++ b/Carthage/Checkouts/UnrarKit/Libraries/unrar/errhnd.cpp @@ -158,6 +158,7 @@ void ErrorHandler::OpenErrorMsg(const wchar *FileName) void ErrorHandler::OpenErrorMsg(const wchar *ArcName,const wchar *FileName) { + Wait(); // Keep GUI responsive if many files cannot be opened when archiving. uiMsg(UIERROR_FILEOPEN,ArcName,FileName); SysErrMsg(); SetErrorCode(RARX_OPEN); @@ -270,6 +271,7 @@ void _stdfunction ProcessSignal(int SigType) #endif ErrHandler.UserBreak=true; + ErrHandler.SetDisableShutdown(); mprintf(St(MBreak)); #ifdef _WIN_ALL @@ -293,7 +295,7 @@ void _stdfunction ProcessSignal(int SigType) #endif #if defined(_WIN_ALL) && !defined(_MSC_VER) - // never reached, just to avoid a compiler warning + // Never reached, just to avoid a compiler warning return TRUE; #endif } @@ -327,7 +329,7 @@ void ErrorHandler::Throw(RAR_EXIT Code) bool ErrorHandler::GetSysErrMsg(wchar *Msg,size_t Size) { -#if !defined(SFX_MODULE) && !defined(SILENT) +#ifndef SILENT #ifdef _WIN_ALL int ErrType=GetLastError(); if (ErrType!=0) @@ -360,7 +362,7 @@ void ErrorHandler::SysErrMsg() return; #ifdef _WIN_ALL wchar *CurMsg=Msg; - while (CurMsg!=NULL) + while (CurMsg!=NULL) // Print string with \r\n as several strings to multiple lines. { while (*CurMsg=='\r' || *CurMsg=='\n') CurMsg++; diff --git a/Carthage/Checkouts/UnrarKit/Libraries/unrar/errhnd.hpp b/Carthage/Checkouts/UnrarKit/Libraries/unrar/errhnd.hpp index c360c6c..3455dac 100644 --- a/Carthage/Checkouts/UnrarKit/Libraries/unrar/errhnd.hpp +++ b/Carthage/Checkouts/UnrarKit/Libraries/unrar/errhnd.hpp @@ -56,11 +56,12 @@ class ErrorHandler uint GetErrorCount() {return ErrCount;} void SetSignalHandlers(bool Enable); void Throw(RAR_EXIT Code); - void SetSilent(bool Mode) {Silent=Mode;}; + void SetSilent(bool Mode) {Silent=Mode;} bool GetSysErrMsg(wchar *Msg,size_t Size); void SysErrMsg(); int GetSystemErrorCode(); void SetSystemErrorCode(int Code); + void SetDisableShutdown() {DisableShutdown=true;} bool IsShutdownEnabled() {return !DisableShutdown;} bool UserBreak; // Ctrl+Break is pressed. diff --git a/Carthage/Checkouts/UnrarKit/Libraries/unrar/extract.cpp b/Carthage/Checkouts/UnrarKit/Libraries/unrar/extract.cpp index 99cca62..76ee2d4 100644 --- a/Carthage/Checkouts/UnrarKit/Libraries/unrar/extract.cpp +++ b/Carthage/Checkouts/UnrarKit/Libraries/unrar/extract.cpp @@ -40,6 +40,8 @@ void CmdExtract::DoExtract() { if (Cmd->ManualPassword) Cmd->Password.Clean(); // Clean user entered password before processing next archive. + + ReconstructDone=false; // Must be reset here, not in ExtractArchiveInit(). while (true) { EXTRACT_ARC_CODE Code=ExtractArchive(); @@ -59,7 +61,11 @@ void CmdExtract::DoExtract() { if (!PasswordCancelled) uiMsg(UIERROR_NOFILESTOEXTRACT,ArcName); - ErrHandler.SetErrorCode(RARX_NOFILES); + + // Other error codes may explain a reason of "no files extracted" clearer, + // so set it only if no other errors found (wrong mask set by user). + if (ErrHandler.GetErrorCode()==RARX_SUCCESS) + ErrHandler.SetErrorCode(RARX_NOFILES); } else if (!Cmd->DisableDone) @@ -83,13 +89,12 @@ void CmdExtract::ExtractArchiveInit(Archive &Arc) FirstFile=true; #endif - PasswordAll=(Cmd->Password.IsSet()); + GlobalPassword=Cmd->Password.IsSet() || uiIsGlobalPasswordSet(); DataIO.UnpVolume=false; PrevProcessed=false; AllMatchesExact=true; - ReconstructDone=false; AnySolidDataUnpackedWell=false; StartTime.SetCurrentTime(); @@ -157,7 +162,7 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive() // This size is necessary to display the correct total progress indicator. wchar NextName[NM]; - wcscpy(NextName,Arc.FileName); + wcsncpyz(NextName,Arc.FileName,ASIZE(NextName)); while (true) { @@ -257,15 +262,17 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) if (HeaderType==HEAD_ENDARC) if (Arc.EndArcHead.NextVolume) { -#ifndef NOVOLUME +#ifdef NOVOLUME + return false; +#else if (!MergeArchive(Arc,&DataIO,false,Command)) { ErrHandler.SetErrorCode(RARX_WARNING); return false; } -#endif Arc.Seek(Arc.CurBlockPos,SEEK_SET); return true; +#endif } else return false; @@ -294,7 +301,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) bool EqualNames=false; wchar MatchedArg[NM]; - int MatchNumber=Cmd->IsProcessFile(Arc.FileHead,&EqualNames,MatchType,MatchedArg,ASIZE(MatchedArg)); + int MatchNumber=Cmd->IsProcessFile(Arc.FileHead,&EqualNames,MatchType,0,MatchedArg,ASIZE(MatchedArg)); bool MatchFound=MatchNumber!=0; #ifndef SFX_MODULE if (Cmd->ExclPath==EXCL_BASEPATH) @@ -319,6 +326,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) if (wcsicomp(ArcName,CurVolName)!=0 && FileExist(ArcName)) { + wcsncpyz(Cmd->ArcName,ArcName,ASIZE(ArcName)); // For GUI "Delete archive after extraction". // If first volume name does not match the current name and if such // volume name really exists, let's unpack from this first volume. Repeat=true; @@ -340,7 +348,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) #endif wchar ArcFileName[NM]; - ConvertPath(Arc.FileHead.FileName,ArcFileName); + ConvertPath(Arc.FileHead.FileName,ArcFileName,ASIZE(ArcFileName)); if (Arc.FileHead.Version) { @@ -468,17 +476,17 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) memcmp(Arc.FileHead.PswCheck,PswCheck,SIZE_PSWCHECK)!=0 && !Arc.BrokenHeader) { - if (PasswordAll) // For -p or Ctrl+P. + if (GlobalPassword) // For -p or Ctrl+P to avoid the infinite loop. { // This message is used by Android GUI to reset cached passwords. // Update appropriate code if changed. - uiMsg(UIERROR_BADPSW,ArcFileName); + uiMsg(UIERROR_BADPSW,Arc.FileName,ArcFileName); } else // For passwords entered manually. { // This message is used by Android GUI and Windows GUI and SFX to // reset cached passwords. Update appropriate code if changed. - uiMsg(UIWAIT_BADPSW,ArcFileName); + uiMsg(UIWAIT_BADPSW,Arc.FileName,ArcFileName); Cmd->Password.Clean(); // Avoid new requests for unrar.dll to prevent the infinite loop @@ -609,11 +617,14 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) } #endif - if (!TestMode && !Arc.BrokenHeader && - (Arc.FileHead.PackSize<<11)>Arc.FileHead.UnpSize && + uint64 Preallocated=0; + if (!TestMode && !Arc.BrokenHeader && Arc.FileHead.UnpSize>1000000 && + Arc.FileHead.PackSize*1024>Arc.FileHead.UnpSize && (Arc.FileHead.UnpSize<100000000 || Arc.FileLength()>Arc.FileHead.PackSize)) + { CurFile.Prealloc(Arc.FileHead.UnpSize); - + Preallocated=Arc.FileHead.UnpSize; + } CurFile.SetAllowDelete(!Cmd->KeepBroken); bool FileCreateMode=!TestMode && !SkipSolid && Command!='P'; @@ -725,37 +736,52 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) else mprintf(L"\b\b\b\b\b "); + // If we successfully unpacked a hard link, we wish to set its file + // attributes. Hard link shares file metadata with link target, + // so we do not need to set link time or owner. But when we overwrite + // an existing link, we can call PrepareToDelete(), which affects + // link target attributes as well. So we set link attributes to restore + // both target and link attributes if PrepareToDelete() changed them. + bool SetAttrOnly=LinkEntry && Arc.FileHead.RedirType==FSREDIR_HARDLINK && LinkSuccess; + if (!TestMode && (Command=='X' || Command=='E') && - (!LinkEntry || Arc.FileHead.RedirType==FSREDIR_FILECOPY && LinkSuccess) && + (!LinkEntry || SetAttrOnly || Arc.FileHead.RedirType==FSREDIR_FILECOPY && LinkSuccess) && (!BrokenFile || Cmd->KeepBroken)) { - // We could preallocate more space that really written to broken file. - if (BrokenFile) - CurFile.Truncate(); + // Below we use DestFileName instead of CurFile.FileName, + // so we can set file attributes also for hard links, which do not + // have the open CurFile. These strings are the same for other items. -#if defined(_WIN_ALL) || defined(_EMX) - if (Cmd->ClearArc) - Arc.FileHead.FileAttr&=~FILE_ATTRIBUTE_ARCHIVE; -#endif + if (!SetAttrOnly) + { + // We could preallocate more space that really written to broken file + // or file with crafted header. + if (Preallocated>0 && (BrokenFile || DataIO.CurUnpWrite!=Preallocated)) + CurFile.Truncate(); - CurFile.SetOpenFileTime( - Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.FileHead.mtime, - Cmd->xctime==EXTTIME_NONE ? NULL:&Arc.FileHead.ctime, - Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.FileHead.atime); - CurFile.Close(); + CurFile.SetOpenFileTime( + Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.FileHead.mtime, + Cmd->xctime==EXTTIME_NONE ? NULL:&Arc.FileHead.ctime, + Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.FileHead.atime); + CurFile.Close(); + + SetFileHeaderExtra(Cmd,Arc,DestFileName); + + CurFile.SetCloseFileTime( + Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.FileHead.mtime, + Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.FileHead.atime); + } + #if defined(_WIN_ALL) && !defined(SFX_MODULE) if (Cmd->SetCompressedAttr && (Arc.FileHead.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0) - SetFileCompression(CurFile.FileName,true); + SetFileCompression(DestFileName,true); + if (Cmd->ClearArc) + Arc.FileHead.FileAttr&=~FILE_ATTRIBUTE_ARCHIVE; #endif - SetFileHeaderExtra(Cmd,Arc,CurFile.FileName); - - CurFile.SetCloseFileTime( - Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.FileHead.mtime, - Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.FileHead.atime); - if (!Cmd->IgnoreGeneralAttr && !SetFileAttr(CurFile.FileName,Arc.FileHead.FileAttr)) - uiMsg(UIERROR_FILEATTR,Arc.FileName,CurFile.FileName); + if (!Cmd->IgnoreGeneralAttr && !SetFileAttr(DestFileName,Arc.FileHead.FileAttr)) + uiMsg(UIERROR_FILEATTR,Arc.FileName,DestFileName); PrevProcessed=true; } @@ -846,9 +872,12 @@ void CmdExtract::ExtrPrepareName(Archive &Arc,const wchar *ArcFileName,wchar *De } #ifndef SFX_MODULE - if (Cmd->AppendArcNameToPath) + if (Cmd->AppendArcNameToPath!=APPENDARCNAME_NONE) { - wcsncatz(DestName,PointToName(Arc.FirstVolumeName),DestSize); + if (Cmd->AppendArcNameToPath==APPENDARCNAME_DESTPATH) + wcsncatz(DestName,PointToName(Arc.FirstVolumeName),DestSize); + else + wcsncpyz(DestName,Arc.FirstVolumeName,DestSize); // To archive own dir. SetExt(DestName,NULL,DestSize); AddEndSlash(DestName,DestSize); } @@ -961,14 +990,18 @@ bool CmdExtract::ExtrGetPassword(Archive &Arc,const wchar *ArcFileName) if (!uiGetPassword(UIPASSWORD_FILE,ArcFileName,&Cmd->Password)/* || !Cmd->Password.IsSet()*/) { // Suppress "test is ok" message if user cancelled the password prompt. - uiMsg(UIERROR_INCERRCOUNT); +// 2019.03.23: If some archives are tested ok and prompt is cancelled for others, +// do we really need to suppress "test is ok"? Also if we set an empty password +// and "Use for all archives" in WinRAR Ctrl+P and skip some encrypted archives. +// We commented out this UIERROR_INCERRCOUNT for now. +// uiMsg(UIERROR_INCERRCOUNT); return false; } Cmd->ManualPassword=true; } #if !defined(SILENT) else - if (!PasswordAll && !Arc.FileHead.Solid) + if (!GlobalPassword && !Arc.FileHead.Solid) { eprintf(St(MUseCurPsw),ArcFileName); switch(Cmd->AllYes ? 1 : Ask(St(MYesNoAll))) @@ -980,7 +1013,7 @@ bool CmdExtract::ExtrGetPassword(Archive &Arc,const wchar *ArcFileName) return false; break; case 3: - PasswordAll=true; + GlobalPassword=true; break; } } @@ -1077,7 +1110,7 @@ void CmdExtract::ExtrCreateDir(Archive &Arc,const wchar *ArcFileName) { #if defined(_WIN_ALL) && !defined(SFX_MODULE) if (Cmd->SetCompressedAttr && - (Arc.FileHead.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0 && WinNT()) + (Arc.FileHead.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0 && WinNT()!=WNT_NONE) SetFileCompression(DestFileName,true); #endif SetFileHeaderExtra(Cmd,Arc,DestFileName); diff --git a/Carthage/Checkouts/UnrarKit/Libraries/unrar/extract.hpp b/Carthage/Checkouts/UnrarKit/Libraries/unrar/extract.hpp index 85a21f5..325928d 100644 --- a/Carthage/Checkouts/UnrarKit/Libraries/unrar/extract.hpp +++ b/Carthage/Checkouts/UnrarKit/Libraries/unrar/extract.hpp @@ -43,7 +43,7 @@ class CmdExtract wchar ArcName[NM]; - bool PasswordAll; + bool GlobalPassword; bool PrevProcessed; // If previous file was successfully extracted or tested. wchar DestFileName[NM]; bool PasswordCancelled; diff --git a/Carthage/Checkouts/UnrarKit/Libraries/unrar/file.cpp b/Carthage/Checkouts/UnrarKit/Libraries/unrar/file.cpp index e2bb42a..e506fde 100644 --- a/Carthage/Checkouts/UnrarKit/Libraries/unrar/file.cpp +++ b/Carthage/Checkouts/UnrarKit/Libraries/unrar/file.cpp @@ -13,6 +13,7 @@ File::File() OpenShared=false; AllowDelete=true; AllowExceptions=true; + PreserveAtime=false; #ifdef _WIN_ALL NoSequentialRead=false; CreateMode=FMF_UNDEFINED; @@ -56,6 +57,9 @@ bool File::Open(const wchar *Name,uint Mode) if (OpenShared) ShareMode|=FILE_SHARE_WRITE; uint Flags=NoSequentialRead ? 0:FILE_FLAG_SEQUENTIAL_SCAN; + FindData FD; + if (PreserveAtime) + Access|=FILE_WRITE_ATTRIBUTES; // Needed to preserve atime. hNewFile=CreateFile(Name,Access,ShareMode,NULL,OPEN_EXISTING,Flags,NULL); DWORD LastError; @@ -86,6 +90,11 @@ bool File::Open(const wchar *Name,uint Mode) } if (hNewFile==FILE_BAD_HANDLE && LastError==ERROR_FILE_NOT_FOUND) ErrorType=FILE_NOTFOUND; + if (PreserveAtime && hNewFile!=FILE_BAD_HANDLE) + { + FILETIME ft={0xffffffff,0xffffffff}; // This value prevents atime modification. + SetFileTime(hNewFile,NULL,&ft,NULL); + } #else int flags=UpdateMode ? O_RDWR:(WriteMode ? O_WRONLY:O_RDONLY); @@ -94,6 +103,11 @@ bool File::Open(const wchar *Name,uint Mode) #if defined(_AIX) && defined(_LARGE_FILE_API) flags|=O_LARGEFILE; #endif +#endif + // NDK r20 has O_NOATIME, but fails to create files with it in Android 7+. +#if defined(O_NOATIME) + if (PreserveAtime) + flags|=O_NOATIME; #endif char NameA[NM]; WideToChar(Name,NameA,ASIZE(NameA)); @@ -230,7 +244,7 @@ bool File::Close() { #ifdef _WIN_ALL // We use the standard system handle for stdout in Windows - // and it must not be closed here. + // and it must not be closed here. if (HandleType==FILE_HANDLENORMAL) Success=CloseHandle(hFile)==TRUE; #else @@ -271,7 +285,7 @@ bool File::Rename(const wchar *NewName) Success=RenameFile(FileName,NewName); if (Success) - wcscpy(FileName,NewName); + wcsncpyz(FileName,NewName,ASIZE(FileName)); return Success; } @@ -387,7 +401,7 @@ int File::Read(void *Data,size_t Size) } break; } - return ReadSize; + return ReadSize; // It can return -1 only if AllowExceptions is disabled. } @@ -670,9 +684,11 @@ void File::GetOpenFileTime(RarTime *ft) int64 File::FileLength() { - SaveFilePos SavePos(*this); + int64 SavePos=Tell(); Seek(0,SEEK_END); - return Tell(); + int64 Length=Tell(); + Seek(SavePos,SEEK_SET); + return Length; } diff --git a/Carthage/Checkouts/UnrarKit/Libraries/unrar/file.hpp b/Carthage/Checkouts/UnrarKit/Libraries/unrar/file.hpp index f99336a..a343ce6 100644 --- a/Carthage/Checkouts/UnrarKit/Libraries/unrar/file.hpp +++ b/Carthage/Checkouts/UnrarKit/Libraries/unrar/file.hpp @@ -62,6 +62,7 @@ class File bool NoSequentialRead; uint CreateMode; #endif + bool PreserveAtime; protected: bool OpenShared; // Set by 'Archive' class. public: @@ -99,7 +100,7 @@ class File void SetCloseFileTime(RarTime *ftm,RarTime *fta=NULL); static void SetCloseFileTimeByName(const wchar *Name,RarTime *ftm,RarTime *fta); void GetOpenFileTime(RarTime *ft); - virtual bool IsOpened() {return hFile!=FILE_BAD_HANDLE;}; // 'virtual' for MultiFile class. + virtual bool IsOpened() {return hFile!=FILE_BAD_HANDLE;} // 'virtual' for MultiFile class. int64 FileLength(); void SetHandleType(FILE_HANDLETYPE Type) {HandleType=Type;} FILE_HANDLETYPE GetHandleType() {return HandleType;} @@ -114,6 +115,7 @@ class File #ifdef _WIN_ALL void RemoveSequentialFlag() {NoSequentialRead=true;} #endif + void SetPreserveAtime(bool Preserve) {PreserveAtime=Preserve;} #ifdef _UNIX int GetFD() { diff --git a/Carthage/Checkouts/UnrarKit/Libraries/unrar/filefn.cpp b/Carthage/Checkouts/UnrarKit/Libraries/unrar/filefn.cpp index 4eb7b9b..57a334d 100644 --- a/Carthage/Checkouts/UnrarKit/Libraries/unrar/filefn.cpp +++ b/Carthage/Checkouts/UnrarKit/Libraries/unrar/filefn.cpp @@ -348,7 +348,7 @@ wchar *MkTemp(wchar *Name,size_t MaxSize) swprintf(RndText,ASIZE(RndText),L"%u.%03u",PID,Ext); if (Length+wcslen(RndText)>=MaxSize || Attempt==1000) return NULL; - wcscpy(Name+Length,RndText); + wcsncpyz(Name+Length,RndText,MaxSize-Length); if (!FileExist(Name)) break; } @@ -360,7 +360,7 @@ wchar *MkTemp(wchar *Name,size_t MaxSize) #if !defined(SFX_MODULE) void CalcFileSum(File *SrcFile,uint *CRC32,byte *Blake2,uint Threads,int64 Size,uint Flags) { - SaveFilePos SavePos(*SrcFile); + int64 SavePos=SrcFile->Tell(); #ifndef SILENT int64 FileLength=Size==INT64NDF ? SrcFile->FileLength() : Size; #endif @@ -415,6 +415,8 @@ void CalcFileSum(File *SrcFile,uint *CRC32,byte *Blake2,uint Threads,int64 Size, if (Size!=INT64NDF) Size-=ReadSize; } + SrcFile->Seek(SavePos,SEEK_SET); + if ((Flags & CALCFSUM_SHOWPERCENT)!=0) uiMsg(UIEVENT_FILESUMEND); diff --git a/Carthage/Checkouts/UnrarKit/Libraries/unrar/find.cpp b/Carthage/Checkouts/UnrarKit/Libraries/unrar/find.cpp index 812af6b..b22f82d 100644 --- a/Carthage/Checkouts/UnrarKit/Libraries/unrar/find.cpp +++ b/Carthage/Checkouts/UnrarKit/Libraries/unrar/find.cpp @@ -26,7 +26,7 @@ FindFile::~FindFile() void FindFile::SetMask(const wchar *Mask) { - wcscpy(FindMask,Mask); + wcsncpyz(FindMask,Mask,ASIZE(FindMask)); FirstCall=true; } @@ -52,7 +52,7 @@ bool FindFile::Next(FindData *fd,bool GetSymLink) wcsncpyz(DirName,FindMask,ASIZE(DirName)); RemoveNameFromPath(DirName); if (*DirName==0) - wcscpy(DirName,L"."); + wcsncpyz(DirName,L".",ASIZE(DirName)); char DirNameA[NM]; WideToChar(DirName,DirNameA,ASIZE(DirNameA)); if ((dirp=opendir(DirNameA))==NULL) @@ -63,32 +63,32 @@ bool FindFile::Next(FindData *fd,bool GetSymLink) } while (1) { + wchar Name[NM]; struct dirent *ent=readdir(dirp); if (ent==NULL) return false; if (strcmp(ent->d_name,".")==0 || strcmp(ent->d_name,"..")==0) continue; - wchar Name[NM]; if (!CharToWide(ent->d_name,Name,ASIZE(Name))) uiMsg(UIERROR_INVALIDNAME,UINULL,Name); if (CmpName(FindMask,Name,MATCH_NAMES)) { wchar FullName[NM]; - wcscpy(FullName,FindMask); + wcsncpyz(FullName,FindMask,ASIZE(FullName)); *PointToName(FullName)=0; if (wcslen(FullName)+wcslen(Name)>=ASIZE(FullName)-1) { uiMsg(UIERROR_PATHTOOLONG,FullName,L"",Name); return false; } - wcscat(FullName,Name); + wcsncatz(FullName,Name,ASIZE(FullName)); if (!FastFind(FullName,fd,GetSymLink)) { ErrHandler.OpenErrorMsg(FullName); continue; } - wcscpy(fd->Name,FullName); + wcsncpyz(fd->Name,FullName,ASIZE(fd->Name)); break; } } diff --git a/Carthage/Checkouts/UnrarKit/Libraries/unrar/hardlinks.cpp b/Carthage/Checkouts/UnrarKit/Libraries/unrar/hardlinks.cpp index cf0b25a..946a395 100644 --- a/Carthage/Checkouts/UnrarKit/Libraries/unrar/hardlinks.cpp +++ b/Carthage/Checkouts/UnrarKit/Libraries/unrar/hardlinks.cpp @@ -3,7 +3,12 @@ bool ExtractHardlink(wchar *NameNew,wchar *NameExisting,size_t NameExistingSize) SlashToNative(NameExisting,NameExisting,NameExistingSize); // Not needed for RAR 5.1+ archives. if (!FileExist(NameExisting)) + { + uiMsg(UIERROR_HLINKCREATE,NameNew); + uiMsg(UIERROR_NOLINKTARGET); + ErrHandler.SetErrorCode(RARX_CREATE); return false; + } CreatePath(NameNew,true); #ifdef _WIN_ALL diff --git a/Carthage/Checkouts/UnrarKit/Libraries/unrar/hash.cpp b/Carthage/Checkouts/UnrarKit/Libraries/unrar/hash.cpp index 42791f4..a4559e0 100644 --- a/Carthage/Checkouts/UnrarKit/Libraries/unrar/hash.cpp +++ b/Carthage/Checkouts/UnrarKit/Libraries/unrar/hash.cpp @@ -53,7 +53,7 @@ DataHash::DataHash() DataHash::~DataHash() { #ifdef RAR_SMP - DestroyThreadPool(ThPool); + delete ThPool; #endif cleandata(&CurCRC32, sizeof(CurCRC32)); if (blake2ctx!=NULL) @@ -94,7 +94,7 @@ void DataHash::Update(const void *Data,size_t DataSize) { #ifdef RAR_SMP if (MaxThreads>1 && ThPool==NULL) - ThPool=CreateThreadPool(); + ThPool=new ThreadPool(BLAKE2_THREADS_NUMBER); blake2ctx->ThPool=ThPool; blake2ctx->MaxThreads=MaxThreads; #endif diff --git a/Carthage/Checkouts/UnrarKit/Libraries/unrar/headers.hpp b/Carthage/Checkouts/UnrarKit/Libraries/unrar/headers.hpp index 488960a..6af453a 100644 --- a/Carthage/Checkouts/UnrarKit/Libraries/unrar/headers.hpp +++ b/Carthage/Checkouts/UnrarKit/Libraries/unrar/headers.hpp @@ -14,10 +14,11 @@ #define SIZEOF_UOHEAD 18 #define SIZEOF_STREAMHEAD 26 -#define VER_PACK 29 -#define VER_PACK5 50 // It is stored as 0, but we subtract 50 when saving an archive. -#define VER_UNPACK 29 -#define VER_UNPACK5 50 // It is stored as 0, but we add 50 when reading an archive. +#define VER_PACK 29U +#define VER_PACK5 50U // It is stored as 0, but we subtract 50 when saving an archive. +#define VER_UNPACK 29U +#define VER_UNPACK5 50U // It is stored as 0, but we add 50 when reading an archive. +#define VER_UNKNOWN 9999U // Just some large value. #define MHD_VOLUME 0x0001U @@ -174,7 +175,7 @@ struct MainHeader:BaseBlock struct FileHeader:BlockHeader { byte HostOS; - byte UnpVer; + uint UnpVer; // It is 1 byte in RAR29 and bit field in RAR5. byte Method; union { uint FileAttr; @@ -190,7 +191,7 @@ struct FileHeader:BlockHeader int64 PackSize; int64 UnpSize; - int64 MaxSize; // Reserve size bytes for vint of this size. + int64 MaxSize; // Reserve packed and unpacked size bytes for vint of this size. HashValue FileHash; diff --git a/Carthage/Checkouts/UnrarKit/Libraries/unrar/list.cpp b/Carthage/Checkouts/UnrarKit/Libraries/unrar/list.cpp index 561122b..77c1041 100644 --- a/Carthage/Checkouts/UnrarKit/Libraries/unrar/list.cpp +++ b/Carthage/Checkouts/UnrarKit/Libraries/unrar/list.cpp @@ -71,6 +71,7 @@ void ListArchive(CommandData *Cmd) *VolNumText=0; while(Arc.ReadHeader()>0) { + Wait(); // Allow quit listing with Ctrl+C. HEADER_TYPE HeaderType=Arc.GetHeaderType(); if (HeaderType==HEAD_ENDARC) { @@ -91,7 +92,7 @@ void ListArchive(CommandData *Cmd) switch(HeaderType) { case HEAD_FILE: - FileMatched=Cmd->IsProcessFile(Arc.FileHead)!=0; + FileMatched=Cmd->IsProcessFile(Arc.FileHead,NULL,MATCH_WILDSUBPATH,0,NULL,0)!=0; if (FileMatched) { ListFileHeader(Arc,Arc.FileHead,TitleShown,Verbose,Technical,Bare); @@ -215,7 +216,7 @@ void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bo wchar UnpSizeText[30],PackSizeText[30]; if (hd.UnpSize==INT64NDF) - wcscpy(UnpSizeText,L"?"); + wcsncpyz(UnpSizeText,L"?",ASIZE(UnpSizeText)); else itoa(hd.UnpSize,UnpSizeText,ASIZE(UnpSizeText)); itoa(hd.PackSize,PackSizeText,ASIZE(PackSizeText)); @@ -229,13 +230,13 @@ void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bo wchar RatioStr[10]; if (hd.SplitBefore && hd.SplitAfter) - wcscpy(RatioStr,L"<->"); + wcsncpyz(RatioStr,L"<->",ASIZE(RatioStr)); else if (hd.SplitBefore) - wcscpy(RatioStr,L"<--"); + wcsncpyz(RatioStr,L"<--",ASIZE(RatioStr)); else if (hd.SplitAfter) - wcscpy(RatioStr,L"-->"); + wcsncpyz(RatioStr,L"-->",ASIZE(RatioStr)); else swprintf(RatioStr,ASIZE(RatioStr),L"%d%%",ToPercentUnlim(hd.PackSize,hd.UnpSize)); @@ -344,7 +345,8 @@ void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bo mprintf(L"\n%12ls: %ls",St(MListHostOS),HostOS); mprintf(L"\n%12ls: RAR %ls(v%d) -m%d -md=%d%s",St(MListCompInfo), - Format==RARFMT15 ? L"3.0":L"5.0",hd.UnpVer,hd.Method, + Format==RARFMT15 ? L"1.5":L"5.0", + hd.UnpVer==VER_UNKNOWN ? 0 : hd.UnpVer,hd.Method, hd.WinSize>=0x100000 ? hd.WinSize/0x100000:hd.WinSize/0x400, hd.WinSize>=0x100000 ? L"M":L"K"); @@ -466,7 +468,7 @@ void ListFileAttr(uint A,HOST_SYSTEM_TYPE HostType,wchar *AttrStr,size_t AttrSiz (A & 0x0001) ? ((A & 0x200)!=0 ? 't' : 'x') : '-'); break; case HSYS_UNKNOWN: - wcscpy(AttrStr,L"?"); + wcsncpyz(AttrStr,L"?",AttrSize); break; } } diff --git a/Carthage/Checkouts/UnrarKit/Libraries/unrar/loclang.hpp b/Carthage/Checkouts/UnrarKit/Libraries/unrar/loclang.hpp index 87499bb..a82aca5 100644 --- a/Carthage/Checkouts/UnrarKit/Libraries/unrar/loclang.hpp +++ b/Carthage/Checkouts/UnrarKit/Libraries/unrar/loclang.hpp @@ -85,7 +85,7 @@ #define MCHelpSwILOG L"\n ilog[name] Log errors to file" #define MCHelpSwINUL L"\n inul Disable all messages" #define MCHelpSwIOFF L"\n ioff[n] Turn PC off after completing an operation" -#define MCHelpSwISND L"\n isnd Enable sound" +#define MCHelpSwISND L"\n isnd[-] Control notification sounds" #define MCHelpSwIVER L"\n iver Display the version number" #define MCHelpSwK L"\n k Lock archive" #define MCHelpSwKB L"\n kb Keep broken extracted files" @@ -127,11 +127,11 @@ #define MCHelpSwT L"\n t Test files after archiving" #define MCHelpSwTK L"\n tk Keep original archive time" #define MCHelpSwTL L"\n tl Set archive time to latest file" -#define MCHelpSwTN L"\n tn