@@ -173,23 +173,22 @@ of_string_encoding_t encoding = OF_STRING_ENCODING_AUTODETECT; OFArray OF_GENERIC(OFString *) *remainingArguments, *files; id archive; #ifdef OF_HAVE_SANDBOX - OFSandbox *sandbox = [[OFSandbox alloc] init]; - @try { - [sandbox setAllowsStdIO: true]; - [sandbox setAllowsReadingFiles: true]; - [sandbox setAllowsWritingFiles: true]; - [sandbox setAllowsCreatingFiles: true]; - [sandbox setAllowsChangingFileAttributes: true]; - [sandbox setAllowsUserDatabaseReading: true]; - - [OFApplication activateSandbox: sandbox]; - } @finally { - [sandbox release]; - } + OFSandbox *sandbox = [OFSandbox sandbox]; + + [sandbox setAllowsStdIO: true]; + [sandbox setAllowsReadingFiles: true]; + [sandbox setAllowsWritingFiles: true]; + [sandbox setAllowsCreatingFiles: true]; + [sandbox setAllowsChangingFileAttributes: true]; + [sandbox setAllowsUserDatabaseReading: true]; + /* Dropped after parsing options */ + [sandbox setAllowsUnveil: true]; + + [OFApplication activateSandbox: sandbox]; #endif #ifndef OF_AMIGAOS [OFLocale addLanguageDirectory: @LANGUAGE_DIR]; #else @@ -310,18 +309,10 @@ [OFApplication terminateWithStatus: 1]; } remainingArguments = [optionsParser remainingArguments]; - archive = [self openArchiveWithPath: [remainingArguments firstObject] - type: type - mode: mode - encoding: encoding]; - - if (outputDir != nil) - [[OFFileManager defaultManager] - changeCurrentDirectoryPath: outputDir]; switch (mode) { case 'a': case 'c': if ([remainingArguments count] < 1) @@ -328,34 +319,108 @@ help(of_stderr, false, 1); files = [remainingArguments objectsInRange: of_range(1, [remainingArguments count] - 1)]; +#ifdef OF_HAVE_SANDBOX + [sandbox unveilPath: [remainingArguments firstObject] + permissions: (mode == 'a' ? @"rwc" : @"wc")]; + + for (OFString *path in files) + [sandbox unveilPath: path + permissions: @"r"]; + + [sandbox setAllowsUnveil: false]; + [OFApplication activateSandbox: sandbox]; +#endif + + archive = [self + openArchiveWithPath: [remainingArguments firstObject] + type: type + mode: mode + encoding: encoding]; + [archive addFiles: files]; break; case 'l': if ([remainingArguments count] != 1) help(of_stderr, false, 1); +#ifdef OF_HAVE_SANDBOX + [sandbox unveilPath: [remainingArguments firstObject] + permissions: @"r"]; + [sandbox setAllowsUnveil: false]; + [OFApplication activateSandbox: sandbox]; +#endif + + archive = [self + openArchiveWithPath: [remainingArguments firstObject] + type: type + mode: mode + encoding: encoding]; + [archive listFiles]; break; case 'p': if ([remainingArguments count] < 1) help(of_stderr, false, 1); + +#ifdef OF_HAVE_SANDBOX + [sandbox unveilPath: [remainingArguments firstObject] + permissions: @"r"]; + [sandbox setAllowsUnveil: false]; + [OFApplication activateSandbox: sandbox]; +#endif files = [remainingArguments objectsInRange: of_range(1, [remainingArguments count] - 1)]; + archive = [self + openArchiveWithPath: [remainingArguments firstObject] + type: type + mode: mode + encoding: encoding]; + [archive printFiles: files]; break; case 'x': if ([remainingArguments count] < 1) help(of_stderr, false, 1); files = [remainingArguments objectsInRange: of_range(1, [remainingArguments count] - 1)]; +#ifdef OF_HAVE_SANDBOX + [sandbox unveilPath: [remainingArguments firstObject] + permissions: @"r"]; + + if ([files count] > 0) + for (OFString *path in files) + [sandbox unveilPath: path + permissions: @"wc"]; + else { + OFString *path = (outputDir != nil + ? outputDir : OF_PATH_CURRENT_DIRECTORY); + /* We need 'r' to change the directory to it. */ + [sandbox unveilPath: path + permissions: @"rwc"]; + } + + [sandbox setAllowsUnveil: false]; + [OFApplication activateSandbox: sandbox]; +#endif + + archive = [self + openArchiveWithPath: [remainingArguments firstObject] + type: type + mode: mode + encoding: encoding]; + + if (outputDir != nil) + [[OFFileManager defaultManager] + changeCurrentDirectoryPath: outputDir]; + @try { [archive extractFiles: files]; } @catch (OFCreateDirectoryFailedException *e) { OFString *error = [OFString stringWithCString: strerror([e errNo])