File: XADNowCompressParser.m

package info (click to toggle)
unar 1.1-2
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 6,664 kB
  • sloc: ansic: 52,939; objc: 39,563; cpp: 4,074; makefile: 99; perl: 10
file content (205 lines) | stat: -rw-r--r-- 6,028 bytes parent folder | download | duplicates (5)
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