1#import <Foundation/Foundation.h>
2#import "LzxArchive.h"
3#import "FileInfo.h"
4#import "NSString+Custom.h"
5#import "Preferences.h"
6#import "NSArray+Custom.h"
7
8@interface LzxArchive (PrivateAPI)
9- (NSData *)dataByRunningLzx;
10@end
11
12@implementation LzxArchive : Archive
13
14/**
15 * register our supported file extensions with our superclass.
16 */
17+ (void)initialize
18{
19	[self registerFileExtension:@"lzx" forArchiveClass:self];
20}
21
22+ (NSString *)unarchiveExecutable
23{
24	return [Preferences lzxExecutable];
25}
26
27/**
28 * lzx archives can only be unpacked with path info
29 */
30+ (BOOL)canExtractWithoutFullPath
31{
32	return NO;
33}
34
35/**
36 * lzx archives <em>do not</em> contain info about compression ratio.
37 */
38+ (BOOL)hasRatio;
39{
40	return NO;
41}
42
43+ (ArchiveType)archiveType
44{
45	return LZX;
46}
47
48//------------------------------------------------------------------------------
49// expanding the archive
50//------------------------------------------------------------------------------
51/**
52 * the unlzx command does not allow to unpack single files from the archive. We
53 * resort to unpacking the entire archive instead ...
54 */
55- (int)expandFiles:(NSArray *)files withPathInfo:(BOOL)usePathInfo toPath:(NSString *)path
56{
57	NSArray *args;
58
59	args = [NSArray arrayWithObjects:@"-x", @"--", [self path], nil];
60	return [[self class] runUnarchiverWithArguments:args inDirectory:path];
61}
62
63- (NSArray *)listContents
64{
65	NSEnumerator *cursor;
66	NSString *line;
67
68    NSMutableArray *results = [NSMutableArray array];
69    NSData *data = [self dataByRunningLzx];
70    NSString *string = [[[NSString alloc] initWithData:data
71		encoding:NSASCIIStringEncoding] autorelease];
72    NSArray *lines = [string componentsSeparatedByString:@"\n"];
73
74    // take out first 2 lines (header) and last 2 lines (footer)
75    lines = [lines subarrayWithRange:NSMakeRange(2, [lines count] - 2)];
76    lines = [lines subarrayWithRange:NSMakeRange(0, [lines count] - 3)];
77
78	cursor = [lines objectEnumerator];
79	while ((line = [cursor nextObject]) != nil)
80	{
81		NSArray *components;
82		int length;
83		NSString *path, *dateString, *timeString;
84		NSCalendarDate *date;
85		FileInfo *info;
86
87		components = [line componentsSeparatedByString:@" "];
88		components = [components arrayByRemovingEmptyStrings];
89
90		timeString = [components objectAtIndex:2];
91		if ([timeString isEqual:@"Merged"])
92		{
93			// skip lines that continue "Merged" in the time column, they contain no usable info
94			continue;
95		}
96
97		length = [[components objectAtIndex:0] intValue];
98		path = [components objectAtIndex:5];
99		if ([path hasPrefix:@"\""])
100		{
101			path = [path substringFromIndex:1];
102		}
103		if ([path hasSuffix:@"\""])
104		{
105			path = [path substringToIndex:[path length] - 1];
106		}
107
108		dateString = [components objectAtIndex:3];
109		dateString = [NSString stringWithFormat:@"%@ %@", dateString, timeString];
110		date = [NSCalendarDate dateWithString:dateString calendarFormat:@"%d-%b-%Y %H:%M:%S"];
111
112		info = [FileInfo newWithPath:path date:date size:[NSNumber numberWithInt:length]];
113		[results addObject:info];
114	}
115
116    return results;
117}
118
119//------------------------------------------------------------------------------
120// private API
121//------------------------------------------------------------------------------
122- (NSData *)dataByRunningLzx
123{
124	NSData *data;
125
126	NSArray *args = [NSArray arrayWithObjects:@"-v", @"--", [self path], nil];
127	data = [self dataByRunningUnachiverWithArguments:args];
128	return data;
129}
130
131@end
132