diff --git a/SSZipArchive.m b/SSZipArchive.m index ccd7691..93693f5 100644 --- a/SSZipArchive.m +++ b/SSZipArchive.m @@ -11,6 +11,8 @@ #import "zlib.h" #import "zconf.h" +#include + #define CHUNK 16384 @interface SSZipArchive () @@ -116,25 +118,26 @@ // http://www.pkware.com/documents/casestudies/APPNOTE.TXT // // ...to deduce this method of detecting whether the file in the ZIP is a symbolic link. - // If it is, it is listed as a directory but has an uncompressed data size greater than - // zero (real directories have it equal to 0) and the included, uncompressed data is the - // symbolic link path. + // If it is, it is listed as a directory but has a data size greater than zero (real + // directories have it equal to 0) and the included, uncompressed data is the symbolic link path. + // + // ZIP files did not originally include support for symbolic links so the specification + // doesn't include anything in them that isn't part of a unix extension that isn't being used + // by the archivers we're testing. Most of this is figured out through trial and error and + // reading ZIP headers in hex editors. This seems to do the trick though. // - const uLong ZipDirectoryVersion = 10; const uLong ZipCompressionMethodStore = 0; BOOL fileIsSymbolicLink = NO; - if((fileInfo.version_needed == ZipDirectoryVersion) && // Is it a directory? - (fileInfo.compression_method == ZipCompressionMethodStore) && // Is it compressed? - (fileInfo.compressed_size > 0)) // Is there any data there? + if((fileInfo.compression_method == ZipCompressionMethodStore) && // Is it compressed? + (S_ISDIR(fileInfo.external_fa)) && // Is it marked as a directory + (fileInfo.compressed_size > 0)) // Is there any data? { fileIsSymbolicLink = YES; } - //NSLog(@"\"%s\" is symbolic link? %@", filename, fileIsSymbolicLink ? @"Yes." : @"No."); - // Check if it contains directory NSString *strPath = [NSString stringWithCString:filename encoding:NSUTF8StringEncoding]; BOOL isDirectory = NO; diff --git a/Tests/SSZipArchiveTests.m b/Tests/SSZipArchiveTests.m index 98f1a75..bc45c64 100644 --- a/Tests/SSZipArchiveTests.m +++ b/Tests/SSZipArchiveTests.m @@ -91,16 +91,35 @@ [SSZipArchive unzipFileAtPath:zipPath toDestination:outputPath delegate:self]; - NSString* testSymlink = [outputPath stringByAppendingPathComponent:@"SymbolicLink/GitHub.app"]; + NSString *testSymlinkFolder = [outputPath stringByAppendingPathComponent:@"SymbolicLink/GitHub.app"]; + NSString *testSymlinkFile = [outputPath stringByAppendingPathComponent:@"SymbolicLink/Icon.icns"]; - NSError* error = nil; - NSString* symlinkPath = [[NSFileManager defaultManager] destinationOfSymbolicLinkAtPath:testSymlink error:&error]; + NSError *error = nil; + NSString *symlinkFolderPath = [[NSFileManager defaultManager] destinationOfSymbolicLinkAtPath:testSymlinkFolder error:&error]; + bool symbolicLinkToFolderPersists = ((symlinkFolderPath != nil) && [symlinkFolderPath isEqualToString:@"/Applications/GitHub.app"]) && (error == nil); - bool symbolicLinkPersists = ((symlinkPath != nil) && [symlinkPath isEqualToString:@"/Applications/GitHub.app"]) && (error == nil); + error = nil; - STAssertTrue(symbolicLinkPersists, @"Symbolic links should persist from the original archive to the outputted files."); + NSString *symlinkFilePath = [[NSFileManager defaultManager] destinationOfSymbolicLinkAtPath:testSymlinkFile error:&error]; + bool symbolicLinkToFilePersists = ((symlinkFilePath != nil) && [symlinkFilePath isEqualToString:@"/Applications/GitHub.app/Contents/Resources/AppIcon.icns"]) && (error == nil); + + STAssertTrue(symbolicLinkToFilePersists && symbolicLinkToFolderPersists, @"Symbolic links should persist from the original archive to the outputted files."); } +- (void)testUnzippingWithUnicodeFilenameInside { + + NSString* zipPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"Unicode" ofType:@"zip"]; + NSString* outputPath = [self _cachesPath:@"Unicode"]; + + [SSZipArchive unzipFileAtPath:zipPath toDestination:outputPath delegate:self]; + + bool unicodeFilenameWasExtracted = [[NSFileManager defaultManager] fileExistsAtPath:[outputPath stringByAppendingPathComponent:@"Accént.txt"]]; + + bool unicodeFolderWasExtracted = [[NSFileManager defaultManager] fileExistsAtPath:[outputPath stringByAppendingPathComponent:@"Fólder/Nothing.txt"]]; + + STAssertTrue(unicodeFilenameWasExtracted, @"Files with filenames in unicode should be extracted properly."); + STAssertTrue(unicodeFolderWasExtracted, @"Folders with names in unicode should be extracted propertly."); +} // Commented out to avoid checking in several gig file into the repository. Simply add a file named // `LargeArchive.zip` to the project and uncomment out these lines to test. diff --git a/Tests/SymbolicLink.zip b/Tests/SymbolicLink.zip index 952827d..d2296a1 100644 Binary files a/Tests/SymbolicLink.zip and b/Tests/SymbolicLink.zip differ