1/* 2 3 RarArchive.m 4 Zipper 5 6 Copyright (C) 2012 Free Software Foundation, Inc 7 8 Authors: 9 10 This application is free software; you can redistribute it and/or modify it 11 under the terms of the GNU General Public License as published by the Free 12 Software Foundation; either version 2 of the License, or (at your option) 13 any later version. 14 15 This program is distributed in the hope that it will be useful, but 16 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 17 or FITNESS FOR A PARTICULAR PURPOSE. 18 See the GNU General Public License for more details 19 20 */ 21 22#import <Foundation/Foundation.h> 23#import "RarArchive.h" 24#import "FileInfo.h" 25#import "NSString+Custom.h" 26#import "Preferences.h" 27#import "NSArray+Custom.h" 28#import "common.h" 29 30static NSData *_magicBytes; 31 32@interface RarArchive (PrivateAPI) 33- (NSData *)dataByRunningRar; 34@end 35 36@implementation RarArchive : Archive 37 38/** 39 * register our supported file extensions with our superclass. 40 */ 41+ (void)initialize 42{ 43 // rar files start with 'R a r !' 44 char rarBytes[] = { 'R', 'a', 'r', '!' }; 45 _magicBytes = [[NSData dataWithBytes:rarBytes length:4] retain]; 46 47 [self registerFileExtension:@"rar" forArchiveClass:self]; 48} 49 50+ (NSString *)unarchiveExecutable 51{ 52 return [Preferences rarExecutable]; 53} 54 55/** 56 * rar archives <em>do</em> contain info about compression ratio. 57 */ 58+ (BOOL)hasRatio; 59{ 60 return YES; 61} 62 63+ (ArchiveType)archiveType 64{ 65 return RAR; 66} 67 68+ (NSData *)magicBytes 69{ 70 return _magicBytes; 71} 72 73//------------------------------------------------------------------------------ 74// expanding the archive 75//------------------------------------------------------------------------------ 76- (int)expandFiles:(NSArray *)files withPathInfo:(BOOL)usePathInfo toPath:(NSString *)path 77{ 78 FileInfo *fileInfo; 79 NSMutableArray *args; 80 81 args = [NSMutableArray array]; 82 if (usePathInfo) 83 { 84 [args addObject:@"x"]; 85 } 86 else 87 { 88 [args addObject:@"e"]; 89 } 90 91 // protect against archives and files starting with - 92 [args addObject:@"--"]; 93 94 [args addObject:[self path]]; 95 96 if (files != nil) 97 { 98 NSEnumerator *cursor = [files objectEnumerator]; 99 while ((fileInfo = [cursor nextObject]) != nil) 100 { 101 [args addObject:[fileInfo fullPath]]; 102 } 103 } 104 105 // destination dir 106 [args addObject:path]; 107 return [self runUnarchiverWithArguments:args]; 108} 109 110- (NSArray *)listContents 111{ 112 NSUInteger lineCount, i; 113 NSString *path = nil; 114 115 NSMutableArray *results = [NSMutableArray array]; 116 NSData *data = [self dataByRunningRar]; 117 NSString *string = [[[NSString alloc] initWithData:data 118 encoding:NSASCIIStringEncoding] autorelease]; 119 NSArray *lines = [string componentsSeparatedByString:@"\n"]; 120 121 // take out first 9 lines (header) and last 3 lines (footer) 122 lines = [lines subarrayWithRange:NSMakeRange(8, [lines count] - 8)]; 123 lines = [lines subarrayWithRange:NSMakeRange(0, [lines count] - 4)]; 124 125 lineCount = [lines count]; 126 for (i = 0; i < lineCount; i++) 127 { 128 NSString *line = nil; 129 130 line = [lines objectAtIndex:i]; 131 if ((i % 2) == 0) 132 { 133 path = [line stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; 134 } 135 else 136 { 137 NSArray *components; 138 NSString *date, *ratio; 139 int length; 140 NSCalendarDate *calendarDate; 141 FileInfo *info; 142 143 components = [[line componentsSeparatedByString:@" "] arrayByRemovingEmptyStrings]; 144 // continue only for non-directory entries 145 if ([[components objectAtIndex:5] hasPrefix:@"d"] == NO) 146 { 147 length = [[components objectAtIndex:0] intValue]; 148 ratio = [components objectAtIndex:2]; 149 150 date = [components objectAtIndex:3]; 151 date = [NSString stringWithFormat:@"%@ %@", date, [components objectAtIndex:4]]; 152 calendarDate = [NSCalendarDate dateWithString:date 153 calendarFormat:@"%d-%m-%y %H:%M"]; 154 155 info = [FileInfo newWithPath:path date:calendarDate 156 size:[NSNumber numberWithInt:length] ratio:ratio]; 157 [results addObject:info]; 158 } 159 } 160 } 161 return results; 162} 163 164//------------------------------------------------------------------------------ 165// private API 166//------------------------------------------------------------------------------ 167- (NSData *)dataByRunningRar 168{ 169 // Args for rar: 170 // v view contents of archive 171 // -c- suppress archive comment 172 173 NSArray *args = [NSArray arrayWithObjects:@"v", @"-c-", @"--", [self path], nil]; 174 return [self dataByRunningUnachiverWithArguments:args]; 175} 176 177@end 178