@@ -34,10 +34,11 @@ #import "TarArchive.h" #import "ZIPArchive.h" #import "OFCreateDirectoryFailedException.h" #import "OFInvalidArgumentException.h" +#import "OFInvalidEncodingException.h" #import "OFInvalidFormatException.h" #import "OFNotImplementedException.h" #import "OFOpenItemFailedException.h" #import "OFReadFailedException.h" #import "OFSeekFailedException.h" @@ -60,10 +61,12 @@ @"Options:\n" @" -a --append Append to archive\n" @" -c --create Create archive\n" @" -C --directory Extract into the specified " @"directory\n" + @" -E --encoding The encoding used by the archive " + "(only tar files)\n" @" -f --force Force / overwrite files\n" @" -h --help Show this help\n" @" -l --list List all files in the archive\n" @" -n --no-clobber Never overwrite files\n" @" -p --print Print one or more files from the " @@ -144,15 +147,16 @@ } @implementation OFZIP - (void)applicationDidFinishLaunching { - OFString *outputDir = nil, *type = nil; + OFString *outputDir = nil, *encodingString = nil, *type = nil; const of_options_parser_option_t options[] = { { 'a', @"append", 0, NULL, NULL }, { 'c', @"create", 0, NULL, NULL }, { 'C', @"directory", 1, NULL, &outputDir }, + { 'E', @"encoding", 1, NULL, &encodingString }, { 'f', @"force", 0, NULL, NULL }, { 'h', @"help", 0, NULL, NULL }, { 'l', @"list", 0, NULL, NULL }, { 'n', @"no-clobber", 0, NULL, NULL }, { 'p', @"print", 0, NULL, NULL }, @@ -162,10 +166,11 @@ { 'x', @"extract", 0, NULL, NULL }, { '\0', nil, 0, NULL, NULL } }; OFOptionsParser *optionsParser; of_unichar_t option, mode = '\0'; + of_string_encoding_t encoding = OF_STRING_ENCODING_UTF_8; OFArray OF_GENERIC(OFString *) *remainingArguments, *files; id archive; #ifdef OF_HAVE_SANDBOX OFSandbox *sandbox = [[OFSandbox alloc] init]; @@ -245,20 +250,42 @@ @"prog", [OFApplication programName], @"opt", [optionsParser lastLongOption])]; [OFApplication terminateWithStatus: 1]; break; + case ':': + if ([optionsParser lastLongOption] != nil) + [of_stderr writeLine: OF_LOCALIZED( + @"long_option_requires_argument", + @"%[prog]: Option --%[opt] requires an " + @"argument", + @"prog", [OFApplication programName], + @"opt", [optionsParser lastLongOption])]; + else { + OFString *optStr = [OFString + stringWithFormat: @"%C", + [optionsParser lastOption]]; + [of_stderr writeLine: OF_LOCALIZED( + @"option_requires_argument", + @"%[prog]: Option -%[opt] requires an " + @"argument", + @"prog", [OFApplication programName], + @"opt", optStr)]; + } + + [OFApplication terminateWithStatus: 1]; + break; case '?': if ([optionsParser lastLongOption] != nil) [of_stderr writeLine: OF_LOCALIZED( @"unknown_long_option", @"%[prog]: Unknown option: --%[opt]", @"prog", [OFApplication programName], @"opt", [optionsParser lastLongOption])]; else { OFString *optStr = [OFString - stringWithFormat: @"%c", + stringWithFormat: @"%C", [optionsParser lastOption]]; [of_stderr writeLine: OF_LOCALIZED( @"unknown_option", @"%[prog]: Unknown option: -%[opt]", @"prog", [OFApplication programName], @@ -266,15 +293,29 @@ } [OFApplication terminateWithStatus: 1]; } } + + @try { + if (encodingString != nil) + encoding = of_string_parse_encoding(encodingString); + } @catch (OFInvalidEncodingException *e) { + [of_stderr writeLine: OF_LOCALIZED( + @"invalid_encoding", + @"%[prog]: Invalid encoding: %[encoding]", + @"prog", [OFApplication programName], + @"encoding", encodingString)]; + + [OFApplication terminateWithStatus: 1]; + } remainingArguments = [optionsParser remainingArguments]; archive = [self openArchiveWithPath: [remainingArguments firstObject] type: type - mode: mode]; + mode: mode + encoding: encoding]; if (outputDir != nil) [[OFFileManager defaultManager] changeCurrentDirectoryPath: outputDir]; @@ -347,10 +388,11 @@ } - (id )openArchiveWithPath: (OFString *)path type: (OFString *)type mode: (char)mode + encoding: (of_string_encoding_t)encoding { OFString *modeString, *fileModeString; OFFile *file = nil; id archive = nil; @@ -407,23 +449,27 @@ } @try { if ([type isEqual: @"gz"]) archive = [GZIPArchive archiveWithStream: file - mode: modeString]; + mode: modeString + encoding: encoding]; else if ([type isEqual: @"tar"]) archive = [TarArchive archiveWithStream: file - mode: modeString]; + mode: modeString + encoding: encoding]; else if ([type isEqual: @"tgz"]) { OFStream *GZIPStream = [OFGZIPStream streamWithStream: file mode: modeString]; archive = [TarArchive archiveWithStream: GZIPStream - mode: modeString]; + mode: modeString + encoding: encoding]; } else if ([type isEqual: @"zip"]) archive = [ZIPArchive archiveWithStream: file - mode: modeString]; + mode: modeString + encoding: encoding]; else { [of_stderr writeLine: OF_LOCALIZED( @"unknown_archive_type", @"Unknown archive type: %[type]", @"type", type)];