Hello community, here is the log from the commit of package unar for openSUSE:Factory checked in at 2019-02-24 17:13:52 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/unar (Old) and /work/SRC/openSUSE:Factory/.unar.new.28833 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "unar" Sun Feb 24 17:13:52 2019 rev:5 rq:672799 version:1.10.1 Changes: -------- --- /work/SRC/openSUSE:Factory/unar/unar.changes 2018-03-20 22:02:10.033778113 +0100 +++ /work/SRC/openSUSE:Factory/.unar.new.28833/unar.changes 2019-02-24 17:13:53.660466648 +0100 @@ -1,0 +2,7 @@ +Wed Feb 6 10:41:24 UTC 2019 - [email protected] + +- add unar-1.10.1-self-extracting_rar.patch to support RAR + self-extracting (SFX) archives [bsc#1110754] +- fix bash completion path for lsar and unar + +------------------------------------------------------------------- New: ---- unar-1.10.1-self-extracting_rar.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ unar.spec ++++++ --- /var/tmp/diff_new_pack.JnkfIH/_old 2019-02-24 17:13:54.192466554 +0100 +++ /var/tmp/diff_new_pack.JnkfIH/_new 2019-02-24 17:13:54.192466554 +0100 @@ -1,7 +1,7 @@ # # spec file for package unar # -# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -20,15 +20,16 @@ Version: 1.10.1 Release: 0 Summary: Multi-format unarchiver -License: LGPL-2.1+ +License: LGPL-2.1-or-later Group: Productivity/Archiving/Compression -Url: http://unarchiver.c3.cx/commandline +URL: http://unarchiver.c3.cx/commandline Source0: http://unarchiver.c3.cx/downloads/%{name}%{version}_src.zip Source1: %{name}.changes # PATCH-FIX-OPENSUSE use-system-wavpack.patch Patch0: use-system-wavpack.patch # PATCH-FIX-UPSTREAM document-undocumented-options.patch (lp#1393321) Patch1: document-undocumented-options.patch +Patch2: unar-1.10.1-self-extracting_rar.patch BuildRequires: gcc-c++ BuildRequires: gcc-objc BuildRequires: gnustep-base-devel @@ -59,6 +60,7 @@ sed -e "s/__DATE__/\"$FAKE_BUILDDATE\"/" -i XADMaster/lsar.m XADMaster/unar.m %patch0 -p1 %patch1 -p1 +%patch2 -p1 %build export CFLAGS="%{optflags} -fno-strict-aliasing" @@ -72,17 +74,18 @@ install -d %{buildroot}%{_mandir}/man1 install -m644 Extra/lsar.1 Extra/unar.1 -t %{buildroot}%{_mandir}/man1 -install -d %{buildroot}%{_sysconfdir}/bash_completion.d -install -m644 Extra/lsar.bash_completion %{buildroot}%{_sysconfdir}/bash_completion.d/lsar -install -m644 Extra/unar.bash_completion %{buildroot}%{_sysconfdir}/bash_completion.d/unar +install -d %{buildroot}%{_datadir}/bash-completion/completions +install -m644 Extra/lsar.bash_completion %{buildroot}%{_datadir}/bash-completion/completions/lsar +install -m644 Extra/unar.bash_completion %{buildroot}%{_datadir}/bash-completion/completions/unar %files -%doc License.txt README.md +%license License.txt +%doc README.md %{_bindir}/lsar %{_bindir}/unar -%{_mandir}/man1/lsar.1%{ext_man} -%{_mandir}/man1/unar.1%{ext_man} -%{_sysconfdir}/bash_completion.d/lsar -%{_sysconfdir}/bash_completion.d/unar +%{_mandir}/man1/lsar.1%{?ext_man} +%{_mandir}/man1/unar.1%{?ext_man} +%{_datadir}/bash-completion/completions/lsar +%{_datadir}/bash-completion/completions/unar %changelog ++++++ unar-1.10.1-self-extracting_rar.patch ++++++ 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],
