withContentsOfDirectory: should return error when parameter isn't a directory (#718)

`withFilesAtPaths:` should not write a file when parameter is a directory
This commit is contained in:
Cœur
2024-09-22 21:29:09 +02:00
committed by GitHub
parent 79bd17278a
commit 2c7efe4382
3 changed files with 73 additions and 14 deletions
@@ -467,6 +467,17 @@ int twentyMB = 20 * 1024 * 1024;
XCTAssert(fileSize < fileSize2, @"keepParentDirectory should produce a strictly bigger archive.");
}
/// <https://github.com/ZipArchive/ZipArchive/issues/621>
- (void)testZippingNonDirectoryWithContentsOfDirectory {
NSString *inputPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"TestArchive" ofType:@"zip"];
NSString *outputPath = [self _cachesPath:@"ZippingNonDirectory"];
NSString *zipPath = [outputPath stringByAppendingPathComponent:@"ZippingNonDirectory.zip"];
BOOL success = [SSZipArchive createZipFileAtPath:zipPath withContentsOfDirectory:inputPath];
XCTAssertTrue(!success, @"create zip success");
}
/// Using `keepParentDirectory:YES`
- (void)testZippingAndUnzippingEmptyDirectoryWithPassword {
NSString *inputPath = [self _cachesPath:@"Empty"];
@@ -477,12 +488,43 @@ int twentyMB = 20 * 1024 * 1024;
BOOL success = [SSZipArchive createZipFileAtPath:zipPath withContentsOfDirectory:inputPath keepParentDirectory:YES withPassword:@"password"];
XCTAssertTrue(success, @"create zip failure");
outputPath = [self _cachesPath:@"EmptyDirectory"];
outputPath = [self _cachesPath:@"EmptyOutput"];
// unzipping a directory doesn't require a password
id<SSZipArchiveDelegate> delegate = [ProgressDelegate new];
success = [SSZipArchive unzipFileAtPath:zipPath toDestination:outputPath overwrite:YES password:nil error:nil delegate:delegate];
XCTAssertTrue(success, @"unzip failure");
NSString *emptyPath = [outputPath stringByAppendingPathComponent:@"Empty"];
BOOL isDirectory;
XCTAssertTrue([[NSFileManager defaultManager] fileExistsAtPath:emptyPath isDirectory:&isDirectory], @"Empty unzipped");
XCTAssertTrue(isDirectory, @"Empty is a directory");
}
/// Using `withFilesAtPaths:`
- (void)testZippingAndUnzippingEmptyDirectoryWithFilesAtPaths {
NSString *inputPath = [self _cachesPath:@"EmptyWithSubdirectory"];
NSString *emptySubdirectory = [inputPath stringByAppendingPathComponent:@"Empty"];
BOOL success = [[NSFileManager defaultManager] createDirectoryAtPath:emptySubdirectory withIntermediateDirectories:YES attributes:nil error:NULL];
XCTAssertTrue(success, @"create folder failure");
// zipping files
NSString *outputPath = [self _cachesPath:@"Zipped"];
NSString *zipPath = [outputPath stringByAppendingPathComponent:@"EmptyWithSubdirectory.zip"];
success = [SSZipArchive createZipFileAtPath:zipPath withFilesAtPaths:@[emptySubdirectory]];
XCTAssertTrue(success, @"create zip failure");
// unzipping files
outputPath = [self _cachesPath:@"EmptyWithSubdirectoryOutput"];
id<SSZipArchiveDelegate> delegate = [ProgressDelegate new];
success = [SSZipArchive unzipFileAtPath:zipPath toDestination:outputPath overwrite:YES password:nil error:nil delegate:delegate];
XCTAssertTrue(success, @"unzip failure");
NSString *emptyPath = [outputPath stringByAppendingPathComponent:@"Empty"];
BOOL isDirectory;
XCTAssertTrue([[NSFileManager defaultManager] fileExistsAtPath:emptyPath isDirectory:&isDirectory], @"Empty unzipped");
XCTAssertTrue(isDirectory, @"Empty is a directory");
}
- (void)testUnzippingEmptyArchive {
@@ -592,14 +634,14 @@ int twentyMB = 20 * 1024 * 1024;
// `LargeArchive.zip` to the project and uncomment out these lines to test.
//
//- (void)testUnzippingLargeFiles {
// NSString *zipPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"LargeArchive" ofType:@"zip"];
// NSString *outputPath = [self _cachesPath:@"Large"];
// NSString *zipPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"LargeArchive" ofType:@"zip"];
// NSString *outputPath = [self _cachesPath:@"Large"];
//
// BOOL success = [SSZipArchive unzipFileAtPath:zipPath toDestination:outputPath];
// XCTAssertTrue(success, @"unzip failure");
// BOOL success = [SSZipArchive unzipFileAtPath:zipPath toDestination:outputPath];
// XCTAssertTrue(success, @"unzip failure");
//}
-(void)testShouldProvidePathOfUnzippedFileInDelegateCallback {
- (void)testShouldProvidePathOfUnzippedFileInDelegateCallback {
CollectingDelegate *collector = [CollectingDelegate new];
NSString *zipPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"TestArchive" ofType:@"zip"];
NSString *outputPath = [self _cachesPath:@"Regular"];
@@ -692,7 +734,6 @@ int twentyMB = 20 * 1024 * 1024;
XCTAssertTrue(iterations == noFiles, "All files should be present in the exported directory");
}
//PR #560
- (void)testSymlinkZippingWithFilesAtPaths {
NSString *outputDir = [self _cachesPath:@"ZippingSymlinkWithFilesAtPaths"];
@@ -738,7 +779,6 @@ int twentyMB = 20 * 1024 * 1024;
XCTAssertEqualObjects(realFilePath, realFilePathUnzip);
}
//PR #560
- (void)testSymlinkZippingWithContentsOfDirectory {
NSString *outputDir = [self _cachesPath:@"ZippingSymlinkWithContentsOfDirectory"];
@@ -811,7 +851,8 @@ int twentyMB = 20 * 1024 * 1024;
path = [path stringByAppendingPathComponent:directory];
}
[[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
BOOL success = [[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
XCTAssertTrue(success, @"%@", path);
return path;
}
+1 -1
View File
@@ -147,7 +147,7 @@ typedef NS_ENUM(NSInteger, SSZipArchiveErrorCode) {
- (BOOL)writeFile:(NSString *)path withPassword:(nullable NSString *)password;
- (BOOL)writeFileAtPath:(NSString *)path withFileName:(nullable NSString *)fileName withPassword:(nullable NSString *)password;
- (BOOL)writeFileAtPath:(NSString *)path withFileName:(nullable NSString *)fileName compressionLevel:(int)compressionLevel password:(nullable NSString *)password AES:(BOOL)aes;
///write symlink files
/// write symlink files
- (BOOL)writeSymlinkFileAtPath:(NSString *)path withFileName:(nullable NSString *)fileName compressionLevel:(int)compressionLevel password:(nullable NSString *)password AES:(BOOL)aes;
/// write data
- (BOOL)writeData:(NSData *)data filename:(nullable NSString *)filename withPassword:(nullable NSString *)password;
+22 -4
View File
@@ -811,8 +811,19 @@ BOOL _fileIsSymbolicLink(const unz_file_info *fileInfo);
BOOL success = [zipArchive open];
if (success) {
NSUInteger total = paths.count, complete = 0;
// use a local fileManager (queue/thread compatibility)
NSFileManager *fileManager = [[NSFileManager alloc] init];
for (NSString *filePath in paths) {
success &= [zipArchive writeFile:filePath withPassword:password];
BOOL isDir;
[fileManager fileExistsAtPath:filePath isDirectory:&isDir];
if (!isDir) {
// file
success &= [zipArchive writeFile:filePath withPassword:password];
} else {
// directory
// we ignore its content, to allow for archiving this path only
success &= [zipArchive writeFolderAtPath:filePath withFolderName:filePath.lastPathComponent withPassword:password];
}
if (progressHandler) {
complete++;
progressHandler(complete, total);
@@ -861,9 +872,16 @@ BOOL _fileIsSymbolicLink(const unz_file_info *fileInfo);
NSDirectoryEnumerator *dirEnumerator = [fileManager enumeratorAtPath:directoryPath];
NSArray<NSString *> *allObjects = dirEnumerator.allObjects;
NSUInteger total = allObjects.count, complete = 0;
if (keepParentDirectory && !total) {
allObjects = @[@""];
total = 1;
if (!total) {
// <https://github.com/ZipArchive/ZipArchive/issues/621> let's check if it's an actual directory.
BOOL isDir;
[fileManager fileExistsAtPath:directoryPath isDirectory:&isDir];
if (!isDir) {
success = NO;
} else if (keepParentDirectory) {
allObjects = @[@""];
total = 1;
}
}
for (__strong NSString *fileName in allObjects) {
NSString *fullFilePath = [directoryPath stringByAppendingPathComponent:fileName];