File unar-1.10.1-self-extracting_rar.patch of Package unar.10380
Index: unar-1.10.1/XADMaster/XADRAR5Parser.h
===================================================================
--- unar-1.10.1.orig/XADMaster/XADRAR5Parser.h
+++ unar-1.10.1/XADMaster/XADRAR5Parser.h
@@ -9,6 +9,29 @@ typedef struct RAR5Block
CSHandle *fh;
} RAR5Block;
+typedef enum {
+ RAR5ArchiveFlagsNone = 0,
+ RAR5ArchiveFlagsVolume = 0x0001, // Volume. Archive is a part of multivolume set.
+ RAR5ArchiveFlagsVolumeNumberPresent = 0x0002, // Volume number field is present.
+ // This flag is present in all volumes except first.
+ RAR5ArchiveFlagsSolid = 0x0004, // Solid archive.
+ RAR5ArchiveFlagsRecoveryRecordPresent = 0x0008, // Recovery record is present.
+ RAR5ArchiveFlagsLocked = 0x0010, // Locked archive.
+} RAR5ArchiveFlags;
+ typedef enum {
+ RAR5HeaderTypeUnknown = 0,
+ RAR5HeaderTypeMain = 1, // Main archive header.
+ RAR5HeaderTypeFile = 2, // File header.
+ RAR5HeaderTypeService = 3, // Service header.
+ RAR5HeaderTypeEncryption = 4, // Archive encryption header.
+ RAR5HeaderTypeEnd = 5, // End of archive header.
+} RAR5HeaderType;
+ typedef struct RAR5HeaderBlock
+{
+ RAR5Block block;
+ RAR5ArchiveFlags archiveFlags;
+} RAR5HeaderBlock;
+
@interface XADRAR5Parser:XADArchiveParser
{
NSData *headerkey;
Index: unar-1.10.1/XADMaster/XADRAR5Parser.m
===================================================================
--- unar-1.10.1.orig/XADMaster/XADRAR5Parser.m
+++ unar-1.10.1/XADMaster/XADRAR5Parser.m
@@ -4,10 +4,16 @@
#import "XADRARAESHandle.h"
#import "XADCRCHandle.h"
#import "NSDateXAD.h"
+#import "CSFileHandle.h"
#import "Crypto/hmac_sha256.h"
#import "Crypto/pbkdf2_hmac_sha256.h"
#define ZeroBlock ((RAR5Block){0})
+#define ZeroHeaderBlock ((RAR5HeaderBlock){0})
+
+NSString *RAR5SignatureCannotBeFound=@"RAR5SignatureCannotBeFound";
+const off_t RAR5MaximumSFXHeader = 1 << 20; // 1 MB
+const off_t RAR5SignatureNotFound = -1;
static uint32_t EncryptRAR5CRC32(uint32_t crc,id context);
@@ -34,9 +40,11 @@ static uint64_t ReadRAR5VInt(CSHandle *h
}
static inline BOOL IsZeroBlock(RAR5Block block) { return block.start==0; }
+static inline BOOL IsZeroHeaderBlock(RAR5HeaderBlock block) { return IsZeroBlock(block.block); }
-
-
+ @interface XADRAR5Parser (Multipart)
+ +(BOOL)isPartOfMultiVolume:(CSHandle *)handle;
+@end
@implementation XADRAR5Parser
@@ -47,24 +55,43 @@ static inline BOOL IsZeroBlock(RAR5Block
+(BOOL)recognizeFileWithHandle:(CSHandle *)handle firstBytes:(NSData *)data name:(NSString *)name
{
- const uint8_t *bytes=[data bytes];
- int length=[data length];
-
- if(length<8) return NO; // TODO: fix to use correct min size
-
- if(IsRAR5Signature(bytes)) return YES;
+ off_t signatureLocation = [self signatureLocationInData:data];
+ return signatureLocation != RAR5SignatureNotFound;
+}
- return NO;
++ (off_t)signatureLocationInData:(NSData *)data {
+ const uint8_t *bytes=[data bytes];
+ int length=[data length];
+
+ if(length<8) return RAR5SignatureNotFound; // TODO: fix to use correct min size
+
+ // for SFXX, RAR Signature can be found not at start, but anywhere in the data
+ int maxxSearch = MIN(length, RAR5MaximumSFXHeader) - 8;
+
+ const uint8_t *sign = bytes;
+ for (int i =0 ; i < maxxSearch; i++, sign++) {
+ if(IsRAR5Signature(sign)) {
+ return i;
+ }
+ }
+ return RAR5SignatureNotFound;
}
+(NSArray *)volumesForHandle:(CSHandle *)handle firstBytes:(NSData *)data name:(NSString *)name
{
+ // Check if multipart
+ CSFileHandle *filehandle=[CSFileHandle fileHandleForReadingAtPath:name];
+ if (![self isPartOfMultiVolume:filehandle]) {
+ return nil;
+ }
+
+
// New naming scheme. Find the last number in the name, and look for other files
// with the same number of digits in the same location.
NSArray *matches;
- if((matches=[name substringsCapturedByPattern:@"^(.*[^0-9])([0-9]+)(.*)\\.rar$" options:REG_ICASE]))
+ if((matches=[name substringsCapturedByPattern:@"^(.*[^0-9])([0-9]+)(.*)\\.(rar|sfx|exe)$" options:REG_ICASE]))
return [self scanForVolumesWithFilename:name
- regex:[XADRegex regexWithPattern:[NSString stringWithFormat:@"^%@[0-9]{%ld}%@.rar$",
+ regex:[XADRegex regexWithPattern:[NSString stringWithFormat:@"^%@[0-9]{%ld}%@.(rar|sfx|exe)$",
[[matches objectAtIndex:1] escapedPattern],
(long)[(NSString *)[matches objectAtIndex:2] length],
[[matches objectAtIndex:3] escapedPattern]] options:REG_ICASE]
@@ -93,6 +120,18 @@ static inline BOOL IsZeroBlock(RAR5Block
[super dealloc];
}
+- (void)readUntilSignature {
+ CSHandle * signatureSearchingHandle = [[self handle] subHandleToEndOfFileFrom:0];
+ NSData * data = [signatureSearchingHandle readDataOfLengthAtMost:RAR5MaximumSFXHeader];
+ off_t signatureLocation = [XADRAR5Parser signatureLocationInData:data];
+ if (signatureLocation == RAR5SignatureNotFound) {
+ [NSException raise:RAR5SignatureCannotBeFound format:@"Signature cannot be found %@",[self class]];
+ }
+
+ [self.handle skipBytes:signatureLocation];
+}
+
+
-(void)parse
{
currsolidstream=nil;
@@ -101,12 +140,13 @@ static inline BOOL IsZeroBlock(RAR5Block
NSMutableDictionary *currdict=nil;
NSMutableArray *currparts=[NSMutableArray array];
- [[self handle] skipBytes:8];
-
// TODO: Catch exceptions and emit partial files?
@try
{
+ [self readUntilSignature];
+ [self.handle skipBytes:8];
+
for(;;)
{
RAR5Block block=[self readBlockHeader];
@@ -117,11 +157,13 @@ static inline BOOL IsZeroBlock(RAR5Block
switch(block.type)
{
- case 1: // Main archive header.
+ case RAR5HeaderTypeMain: // Main archive header.
+
[self skipBlock:block];
break;
- case 2: // File header.
+ case RAR5HeaderTypeFile: // File header.
+
{
NSMutableDictionary *dict=[self readFileBlockHeader:block];
@@ -176,10 +218,12 @@ static inline BOOL IsZeroBlock(RAR5Block
}
break;
- //case 3: // Service header.
+ //case RAR5HeaderTypeService: // Service header.
+
//break;
- case 4: // Archive encryption header.
+ case RAR5HeaderTypeEncryption: // Archive encryption header.
+
{
uint64_t version=ReadRAR5VInt(handle);
if(version!=0) [XADException raiseNotSupportedException];
@@ -202,7 +246,8 @@ static inline BOOL IsZeroBlock(RAR5Block
}
break;
- case 5: // End of archive header.
+ case RAR5HeaderTypeEnd: // End of archive header.
+
{
uint64_t flags=ReadRAR5VInt(handle);
if(flags&0x0001)
@@ -550,6 +595,52 @@ inputParts:(NSArray *)parts isCorrupted:
return dict;
}
++(RAR5HeaderBlock)readMasterHeaderFromHandle:(CSHandle *)handle
+{
+
+ RAR5HeaderBlock header;
+ RAR5Block block;
+ block.outerstart=0;
+
+ @try
+ {
+ CSHandle * signatureSearchingHandle = [handle subHandleToEndOfFileFrom:0];
+ NSData * data = [signatureSearchingHandle readDataOfLengthAtMost:RAR5MaximumSFXHeader];
+ off_t signatureLocation = [XADRAR5Parser signatureLocationInData:data];
+ if (signatureLocation == RAR5SignatureNotFound) {
+ [NSException raise:RAR5SignatureCannotBeFound format:@"Signature cannot be found %@",[self class]];
+ }
+
+ [handle skipBytes:signatureLocation];
+ [handle skipBytes:8];
+ if([handle atEndOfFile]) return ZeroHeaderBlock;
+ block.crc=[handle readUInt32LE];
+ block.headersize=ReadRAR5VInt(handle);
+ block.start=[handle offsetInFile];
+ block.type=ReadRAR5VInt(handle);
+ block.flags=ReadRAR5VInt(handle);
+
+ if(block.flags&0x0001) block.extrasize=ReadRAR5VInt(handle);
+ else block.extrasize=0;
+
+ header.archiveFlags=ReadRAR5VInt(handle);
+
+ if(block.flags&0x0002) block.datasize=ReadRAR5VInt(handle);
+ else block.datasize=0;
+ }
+ @catch(id e) { return ZeroHeaderBlock; }
+
+ // If first block wasn't main
+ if (block.type != RAR5HeaderTypeMain) {
+ return ZeroHeaderBlock;
+ }
+
+ block.fh=handle;
+
+ header.block = block;
+ return header;
+}
+
-(RAR5Block)readBlockHeader
{
CSHandle *fh=[self handle];
@@ -788,3 +879,15 @@ static uint32_t EncryptRAR5CRC32(uint32_
return newcrc^0xffffffff;
}
+
+@implementation XADRAR5Parser (Multipart)
+ +(BOOL)isPartOfMultiVolume:(CSHandle *)handle
+{
+ RAR5HeaderBlock header = [self readMasterHeaderFromHandle:handle];
+ if (IsZeroHeaderBlock(header)) {
+ return NO;
+ }
+ return (header.archiveFlags & RAR5ArchiveFlagsVolume);
+}
+@end
+
Index: unar-1.10.1/XADMaster/XADArchiveParser.m
===================================================================
--- unar-1.10.1.orig/XADMaster/XADArchiveParser.m
+++ unar-1.10.1/XADMaster/XADArchiveParser.m
@@ -183,9 +183,9 @@ static int maxheader=0;
// Detectors that require lots of work
[XADWinZipSFXParser class],
[XADZipItSEAParser class],
- [XADZipSFXParser class],
[XADEmbeddedRARParser class],
[XADEmbeddedRAR5Parser class],
+ [XADZipSFXParser class],
[XAD7ZipSFXParser class],
[XADNSISParser class],
[XADGzipSFXParser class],