1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
|
#import "XADNowCompressParser.h"
#import "XADNowCompressHandle.h"
#import "NSDateXAD.h"
#import "XADCRCHandle.h"
@implementation XADNowCompressParser
+(int)requiredHeaderSize
{
return 24;
}
+(BOOL)recognizeFileWithHandle:(CSHandle *)handle firstBytes:(NSData *)data name:(NSString *)name
{
int length=[data length];
const uint8_t *bytes=[data bytes];
if(length<134) return NO;
if(bytes[0]!=0x00||bytes[1]!=0x02) return NO; // Check magic bytes.
if(CSUInt32BE(&bytes[8])>0xffff) return NO; // Check number of files. Assume no
if(CSUInt32BE(&bytes[8])==0) return NO; // archive has more than 65535 files.
if(bytes[24]>31) return NO; // Check name length.
if(bytes[24]==0) return NO;
for(int i=0;i<bytes[24];i++)
if(bytes[25+i]<32) return NO; // Check for valid filename.
uint32_t sum=0;
for(int i=24;i<130;i++) sum+=bytes[i];
if(sum!=CSUInt32BE(&bytes[130])) return NO; // Check checksum.
return YES;
}
-(void)parse
{
[self setIsMacArchive:YES];
CSHandle *fh=[self handle];
[fh skipBytes:8];
totalentries=[fh readUInt32BE];
[fh skipBytes:12];
currentries=0;
entries=[NSMutableArray array];
filesarray=[NSMutableArray array];
solidoffset=0;
[self parseDirectoryWithParent:[self XADPath] numberOfEntries:INT_MAX];
int numdicts=[entries count];
for(int i=0;i<numdicts && [self shouldKeepParsing];i++)
[self addEntryWithDictionary:[entries objectAtIndex:i]];
}
-(void)parseDirectoryWithParent:(XADPath *)parent numberOfEntries:(int)numentries
{
CSHandle *fh=[self handle];
for(int i=0;i<numentries && currentries<totalentries;i++,currentries++)
{
if(![self shouldKeepParsing]) break;
int namelen=[fh readUInt8];
NSData *namedata=[fh readDataOfLength:namelen];
[fh skipBytes:31-namelen];
[fh skipBytes:4];
int flags=[fh readUInt16BE];
NSData *finderinfo=[fh readDataOfLength:16];
uint32_t creation=[fh readUInt32BE];
uint32_t modification=[fh readUInt32BE];
uint32_t access=[fh readUInt32BE];
[fh skipBytes:16];
int numdirentries=[fh readUInt16BE];
[fh skipBytes:2];
uint32_t datasize=[fh readUInt32BE];
uint32_t rsrcsize=[fh readUInt32BE];
[fh skipBytes:4];
uint32_t datastart=[fh readUInt32BE];
uint32_t dataend=[fh readUInt32BE];
[fh skipBytes:4]; // Skip checksum.
XADString *name=[self XADStringWithData:namedata];
XADPath *path=[parent pathByAppendingXADStringComponent:name];
NSMutableDictionary *shareddict=[NSMutableDictionary dictionaryWithObjectsAndKeys:
path,XADFileNameKey,
[NSDate XADDateWithTimeIntervalSince1904:modification],XADLastModificationDateKey,
[NSDate XADDateWithTimeIntervalSince1904:creation],XADCreationDateKey,
finderinfo,XADFinderInfoKey,
[NSNumber numberWithInt:flags],@"NowFlags",
nil];
if(access) [shareddict setObject:[NSDate XADDateWithTimeIntervalSince1904:access] forKey:XADLastAccessDateKey];
if(flags&0x10) // Directory
{
NSMutableDictionary *dict=[NSMutableDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES],XADIsDirectoryKey,
nil];
[dict addEntriesFromDictionary:shareddict];
[entries addObject:dict];
[self parseDirectoryWithParent:path numberOfEntries:numdirentries];
}
else
{
[filesarray addObject:[NSNumber numberWithUnsignedInt:datastart]];
if(rsrcsize)
{
NSMutableDictionary *dict=[NSMutableDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES],XADIsResourceForkKey,
[NSNumber numberWithUnsignedInt:rsrcsize],XADFileSizeKey,
[NSNumber numberWithUnsignedInt:(dataend-datastart)*rsrcsize/(datasize+rsrcsize)],XADCompressedSizeKey,
[self XADStringWithString:@"Now Compress"],XADCompressionNameKey,
filesarray,XADSolidObjectKey,
[NSNumber numberWithLongLong:solidoffset],XADSolidOffsetKey,
[NSNumber numberWithUnsignedInt:rsrcsize],XADSolidLengthKey,
nil];
[dict addEntriesFromDictionary:shareddict];
[entries addObject:dict];
solidoffset+=rsrcsize;
}
if(datasize||!rsrcsize)
{
NSMutableDictionary *dict=[NSMutableDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithUnsignedInt:datasize],XADFileSizeKey,
[self XADStringWithString:@"Now Compress"],XADCompressionNameKey,
filesarray,XADSolidObjectKey,
[NSNumber numberWithLongLong:solidoffset],XADSolidOffsetKey,
[NSNumber numberWithUnsignedInt:datasize],XADSolidLengthKey,
nil];
[dict addEntriesFromDictionary:shareddict];
if(datasize+rsrcsize) [dict setObject:[NSNumber numberWithUnsignedInt:(dataend-datastart)*datasize/(datasize+rsrcsize)] forKey:XADCompressedSizeKey];
else [dict setObject:[NSNumber numberWithUnsignedInt:0] forKey:XADCompressedSizeKey];
[entries addObject:dict];
solidoffset+=datasize;
}
}
}
}
-(CSHandle *)handleForEntryWithDictionary:(NSDictionary *)dict wantChecksum:(BOOL)checksum
{
if([dict objectForKey:XADIsDirectoryKey]) return nil;
return [self subHandleFromSolidStreamForEntryWithDictionary:dict];
/* CSHandle *handle=[self subHandleFromSolidStreamForEntryWithDictionary:dict];
if([[[dict objectForKey:XADFileNameKey] lastPathComponent] isEqual:@"test5"])
handle=[XADCRCHandle IEEECRC32HandleWithHandle:handle correctCRC:0x4fa8ca5a conditioned:YES];
else if([[[dict objectForKey:XADFileNameKey] lastPathComponent] isEqual:@"test6"])
handle=[XADCRCHandle IEEECRC32HandleWithHandle:handle correctCRC:0x4dee978f conditioned:YES];
else if([[[dict objectForKey:XADFileNameKey] lastPathComponent] isEqual:@"test7"])
handle=[XADCRCHandle IEEECRC32HandleWithHandle:handle correctCRC:0xaab9ef52 conditioned:YES];
else if([[[dict objectForKey:XADFileNameKey] lastPathComponent] isEqual:@"test8"])
handle=[XADCRCHandle IEEECRC32HandleWithHandle:handle correctCRC:0x23dcbf69 conditioned:YES];
return handle;*/
}
-(CSHandle *)handleForSolidStreamWithObject:(id)obj wantChecksum:(BOOL)checksum
{
return [[[XADNowCompressHandle alloc] initWithHandle:[self handle] files:obj] autorelease];
}
-(NSString *)formatName
{
return @"Now Compress";
}
@end
|