Index: utils/ofzip/Archive.h ================================================================== --- utils/ofzip/Archive.h +++ utils/ofzip/Archive.h @@ -19,14 +19,16 @@ #import "OFFile.h" #import "OFArray.h" @protocol Archive + (instancetype)archiveWithStream: (OF_KINDOF(OFStream *))stream - mode: (OFString *)mode; + mode: (OFString *)mode + encoding: (of_string_encoding_t)encoding; - (instancetype)initWithStream: (OF_KINDOF(OFStream *))stream - mode: (OFString *)mode; + mode: (OFString *)mode + encoding: (of_string_encoding_t)encoding; - (void)listFiles; - (void)extractFiles: (OFArray OF_GENERIC(OFString *) *)files; - (void)printFiles: (OFArray OF_GENERIC(OFString *) *)files; @optional - (void)addFiles: (OFArray OF_GENERIC(OFString *) *)files; @end Index: utils/ofzip/GZIPArchive.m ================================================================== --- utils/ofzip/GZIPArchive.m +++ utils/ofzip/GZIPArchive.m @@ -51,17 +51,20 @@ app = (OFZIP *)[[OFApplication sharedApplication] delegate]; } + (instancetype)archiveWithStream: (OF_KINDOF(OFStream *))stream mode: (OFString *)mode + encoding: (of_string_encoding_t)encoding { return [[[self alloc] initWithStream: stream - mode: mode] autorelease]; + mode: mode + encoding: encoding] autorelease]; } - (instancetype)initWithStream: (OF_KINDOF(OFStream *))stream mode: (OFString *)mode + encoding: (of_string_encoding_t)encoding { self = [super init]; @try { _stream = [[OFGZIPStream alloc] initWithStream: stream Index: utils/ofzip/OFZIP.h ================================================================== --- utils/ofzip/OFZIP.h +++ utils/ofzip/OFZIP.h @@ -38,15 +38,16 @@ int _exitStatus; } - (id )openArchiveWithPath: (OFString *)path type: (OFString *)type - mode: (char)mode; + mode: (char)mode + encoding: (of_string_encoding_t)encoding; - (bool)shouldExtractFile: (OFString *)fileName outFileName: (OFString *)outFileName; - (ssize_t)copyBlockFromStream: (OFStream *)input toStream: (OFStream *)output fileName: (OFString *)fileName; - (nullable OFString *)safeLocalPathForPath: (OFString *)path; @end OF_ASSUME_NONNULL_END Index: utils/ofzip/OFZIP.m ================================================================== --- utils/ofzip/OFZIP.m +++ utils/ofzip/OFZIP.m @@ -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)]; Index: utils/ofzip/TarArchive.m ================================================================== --- utils/ofzip/TarArchive.m +++ utils/ofzip/TarArchive.m @@ -51,23 +51,28 @@ app = (OFZIP *)[[OFApplication sharedApplication] delegate]; } + (instancetype)archiveWithStream: (OF_KINDOF(OFStream *))stream mode: (OFString *)mode + encoding: (of_string_encoding_t)encoding { return [[[self alloc] initWithStream: stream - mode: mode] autorelease]; + mode: mode + encoding: encoding] autorelease]; } - (instancetype)initWithStream: (OF_KINDOF(OFStream *))stream mode: (OFString *)mode + encoding: (of_string_encoding_t)encoding { self = [super init]; @try { _archive = [[OFTarArchive alloc] initWithStream: stream mode: mode]; + + [_archive setEncoding: encoding]; } @catch (id e) { [self release]; @throw e; } Index: utils/ofzip/ZIPArchive.m ================================================================== --- utils/ofzip/ZIPArchive.m +++ utils/ofzip/ZIPArchive.m @@ -63,17 +63,20 @@ app = (OFZIP *)[[OFApplication sharedApplication] delegate]; } + (instancetype)archiveWithStream: (OF_KINDOF(OFStream *))stream mode: (OFString *)mode + encoding: (of_string_encoding_t)encoding { return [[[self alloc] initWithStream: stream - mode: mode] autorelease]; + mode: mode + encoding: encoding] autorelease]; } - (instancetype)initWithStream: (OF_KINDOF(OFStream *))stream mode: (OFString *)mode + encoding: (of_string_encoding_t)encoding { self = [super init]; @try { _archive = [[OFZIPArchive alloc] initWithStream: stream Index: utils/ofzip/lang/de.json ================================================================== --- utils/ofzip/lang/de.json +++ utils/ofzip/lang/de.json @@ -5,10 +5,11 @@ "full_usage": [ "Optionen:\n", " -a --append Zu Archiv hinzufügen\n", " -c --create Archiv erstellen\n", " -C --directory In angegebenes Verzeichnis entpacken\n", + " -E --encoding Das Encoding des Archivs (nur tar-Dateien)\n", " -f --force Existierende Dateien überschreiben\n", " -h --help Diese Hilfe anzeigen\n", " -l --list Alle Dateien im Archiv auflisten\n", " -n --no-clobber Dateien niemals überschreiben\n", " -p --print Eine oder mehr Dateien aus dem Archiv ausgeben", @@ -27,12 +28,17 @@ "--%[longopt2], -%[shortopt3] / --%[longopt3], ", "-%[shortopt4] / --%[longopt4] und\n", " -%[shortopt5] / --%[longopt5] schließen sich gegenseitig aus!" ], "option_takes_no_argument": "%[prog]: Option --%[opt] nimmt kein Argument", + "long_option_requires_argument": [ + "%[prog]: Option --%[opt] benötigt ein Argument" + ], + "option_requires_argument": "%[prog]: Option -%[opt] benötigt ein Argument", "unknown_long_option": "%[prog]: Unbekannte Option: --%[opt]", "unknown_option": "%[prog]: Unbekannte Option: -%[opt]", + "invalid_encoding": "%[prog]: Invalid encoding: %[encoding]", "writing_not_supported": [ "Schreiben von Dateien des Typs %[type] wird (noch) nicht unterstützt!" ], "failed_to_create_directory": [ "Fehler beim Erstellen des Verzeichnis %[dir]: %[error]"