94 Commits

Author SHA1 Message Date
Adam Yanalunas
60312c173b Merge pull request #111 from soffes/test/relative_path_fixture
Relative symlink fixture for new symlink detection in #91
2014-09-08 11:26:13 -07:00
Adam Yanalunas
c363747a15 Merge pull request #91 from landonf/master
Fix symlink detection
2014-09-08 11:26:01 -07:00
Adam Yanalunas
e29efca7bf Relative symlink fixture for new symlink detection in #91 2014-09-05 13:19:30 -07:00
Sam Soffes
89b32b9328 Merge pull request #99 from mr-fahrenheit/master
Fixed warnings from Xcode Analyzer
2014-04-06 09:25:57 -04:00
Mr. Fahrenheit
1b2ec1a9ec Fixed warnings from Xcode Analyzer 2014-04-06 19:42:33 +08:00
Sam Soffes
b4c9bde3fb Fix warnings on 64-bit 2014-03-22 08:01:08 -07:00
Andreas Dangel
4fca963b62 Add a unit test for zipArchiveProgressEvent. 2014-03-22 03:56:37 +01:00
Andreas Dangel
281571d99f Add a progress event while unzipping.
The progress is determined by the compressed file size and zip entries.
2014-03-14 21:22:20 -04:00
Landon Fuller
653caaa9b2 Replace symlink heuristic with a well-defined test.
As per the PKWARE ZIP File Format Specification (6.3.2), this
patch tests the file 'version made by' field for the UNIX (3)
constant, and then interprets the external file attributes accordingly,
assuming an st_mode field in the high 16 bits.
2014-01-16 11:53:45 -05:00
Sam Soffes
d3c40f0e95 Happy New Year 🎉 2014-01-01 11:00:26 -08:00
Sam Soffes
ebc0b248ef Merge pull request #86 from dennda/master
Issue #85: Keep relative symbolic links relative.
2013-11-08 11:52:25 -08:00
Christopher Denter
f89c159b2a Issue #85: Add test for relative symlink preservation patch.
This test adds a fixture RelativeSymlinks.zip with the following
structure:

    RelativeSymbolicLink
    ├── symlinkedFile
    ├── symlinkedFolder
    └── symlinks
       ├── fileSymlink -> ../symlinkedFile
       └── folderSymlink -> ../symlinkedFolder

The test checks if both `fileSymlink` and `folderSymlink` still point to
the respective files in the parent directory after the fixture has been
unzipped.
2013-11-08 20:34:17 +01:00
Christopher Denter
a5de5b6bef Issue #85: Keep relative symbolic links relative.
Before, the library resolved symbolic links that are relative
into absolute paths, using the current working directory of the process
that's doing the unzipping, which to me seems pretty wrong.
This was due to using -[NSURL fileURLWithPath:], which transforms
relative URLs to absolute URLs automatically.

I don't see much of a reason to use NSFileManager here, so I made that
use symlink() directly. Alternatively, one could also use -[NSURL
URLWithString:].

This keeps relative symlinks relative after unzipping.
2013-11-08 19:04:42 +01:00
Sam Soffes
bf95dc2fd4 Fix 2013-09-11 08:56:12 -07:00
Sam Soffes
c2b33b42d0 There we go 2013-09-11 08:43:46 -07:00
Sam Soffes
b91252282e Simplify project structure 2013-09-10 00:03:11 -07:00
Sam Soffes
1fefbc022f Add shares scheme 2013-09-09 23:50:07 -07:00
Sam Soffes
273fc1b36e Fix minizip path 2013-09-09 09:04:04 -07:00
Sam Soffes
164ae9bfd3 Move minizip up 2013-09-09 09:00:52 -07:00
Sam Soffes
6ca6e0c28f Version 0.3.0 2013-09-07 08:52:49 -07:00
Sam Soffes
07cfb62107 Update readme 2013-09-07 08:38:55 -07:00
Sam Soffes
364be2ed4f Restructure project and move to XCTest 2013-09-07 08:33:47 -07:00
Sam Soffes
524ca1abae Add missing fclose. Thanks @aceisScope! 2013-09-07 08:22:56 -07:00
Sam Soffes
c81002605b Version 0.2.5 2013-07-16 10:20:46 -04:00
Sam Soffes
5227bb251b Merge pull request #68 from marcelofabri/master
Fixing compilation error (missing ";")
2013-07-12 15:34:05 -07:00
Marcelo Fabri
3bb7fe8d26 Adding missing ";".
Fixes syntax error.
2013-07-12 19:31:18 -03:00
Sam Soffes
21c3694d0c Merge pull request #67 from ChristopherRogers/master
NSCalendar caching
2013-07-12 08:27:07 -07:00
Rogers, Christopher
84c8171151 Caching Gregorian NSCalendar for performance.
This was taking about 30% of the time unzipping on an iPhone 5.
2013-07-12 17:28:18 +09:00
Sam Soffes
f9136dd744 Merge pull request #65 from nibroc/master
Added check to ensure permissions are not explicitly set if they do not exist in the zip
2013-07-10 17:50:20 -07:00
Sam Soffes
d7ac059a8a Version 0.2.4 2013-07-03 08:58:01 -07:00
Corbin Hughes
adfc3cae92 Added a check to make sure 0 permissions are not set 2013-07-01 04:55:42 -05:00
Joshua Garnham
9d322d173f Added tests for compressing and uncompressing files with permissions 2013-06-26 12:16:29 +01:00
Joshua Garnham
c91865d01b Adds support for maintaining file permissions when compressing and decompressing 2013-06-25 17:11:08 +01:00
frytaz
548b3acbba Fix for file creation date + tests 2013-06-25 13:45:30 +02:00
djskinner
7627a1b4fc wrapped main loop in @autorelease pool
Massively reduces the memory overhead whilst unzipping
2013-06-17 15:33:44 +02:00
Sam Soffes
481ddf2096 Merge pull request #53 from randomsequence/master
Fix NSFileManager leak when building without ARC
2013-05-03 06:15:24 -07:00
Johnnie Walker
b078433f2e Fix warning with -Widiomatic-parentheses enabled 2013-05-01 12:38:44 +01:00
Johnnie Walker
ceae6ae819 Fix warning with -Wmissing-braces enabled 2013-05-01 12:36:32 +01:00
Johnnie Walker
d7c7955cdc Fix NSFileManager leak when building without ARC 2013-05-01 12:03:48 +01:00
Sam Soffes
ffbacdb288 Merge pull request #51 from carlj/master
Notice file date when save file
2013-04-23 02:03:25 -07:00
Carl Jahn
4ac78e3121 fixed bug: writeFileAtPath now notice the file date 2013-04-19 15:05:54 +02:00
Sam Soffes
b4fa2e4739 Merge pull request #44 from iggycoder/master
zipping folders
2013-03-09 09:40:39 -08:00
Ingmar
7aea62f0dd - add folder zipping functionality
- fixed zipping test case [testZipping] (zipped an empty archive)
2013-03-09 05:36:20 -08:00
Sam Soffes
798a317bdc Merge pull request #40 from Keithbsmiley/master
Podspec fix
2013-03-03 10:55:22 -08:00
Sam Soffes
ec5de8e02b Merge pull request #43 from levigroker/master
#define added to the .h which allows conditional compilation for third parties wishing to conditionally add functionality based on the presence of SSZipArchive.
2013-03-03 10:53:15 -08:00
Levi Brown
a15c76e057 Fixed podspec.
Signed-off-by: Levi Brown <levi@grokers.net>
2013-03-01 17:17:35 -07:00
Levi Brown
f7266f6b4d Adding #define of SSZipArchive header inclusion to allow for conditional compilation of libraries which can add functionality conditionally, if SSZipArchive is present.
Signed-off-by: Levi Brown <levi@grokers.net>
2013-03-01 14:40:28 -07:00
Sam Soffes
d6f5b1c7a3 Update readme 2013-02-25 16:09:47 -08:00
Sam Soffes
2f05d42988 Add Travis CI 2013-02-25 06:46:56 -05:00
Sam Soffes
d630ae5f5e Merge pull request #41 from xenosoz/master
This fixes a small typo.
2013-02-24 16:11:58 -08:00
Xenosoz Hwang
04605b7967 Fix bad loop end condition for unzip. 2013-02-24 10:40:21 -08:00
Keith Smiley
294cd2992b Fixed podspec 2013-02-07 11:45:12 -05:00
Sam Soffes
a311e60107 Version 0.2.3
* Update podspec
* Fix remote
* Bump year
* Release changes since last release
2013-01-29 01:54:19 -05:00
Sam Soffes
69fb8f4a4c Merge pull request #34 from cvisprogrammer/master
added fclose to writeFile
2013-01-18 08:14:24 -08:00
Farooq Ahmad
1d163e4db5 Added fclose to writeFile
need fclose to avoid running out of file handles
2012-11-28 09:16:10 -08:00
Sam Soffes
3f5a7b30dc Merge pull request #28 from nivektric/master
Change clean_path to preserve_paths in podspec to pass validation
2012-07-10 12:01:07 -07:00
Kevin Monahan
bdbab4d3b3 Change clean_path to preserve_paths in podspec to pass validation 2012-07-10 14:35:58 -04:00
Sam Soffes
fdb1726299 Merge pull request #27 from nivektric/0.2.2
Bump version number in podspec
2012-07-09 21:39:27 -07:00
Kevin Monahan
709006228c Bump version number in podspec 2012-07-09 23:47:10 -04:00
Sam Soffes
db0c62c481 Bump license year and add podspec 2012-06-02 13:32:57 -07:00
Sam Soffes
d9ea638369 Merge pull request #23 from jparishy/master
Fix for issues with Unicode filenames and Symbolic Links. Fixes #14
2012-05-09 21:32:13 -07:00
Julius Parishy
f18a98e551 Remote old debug NSLogs
Just taking out some NSLogs I missed when cleaning up the source.
2012-05-09 23:55:36 -04:00
Julius Parishy
557e869222 Remove files I accidentally unzipped.
They weren't needed and were cluttering up the directory.
2012-05-09 23:54:47 -04:00
Julius Parishy
26630b36af Fix for mailing tests regarding unicode filenames and symbolic links.
See my note about ZIPs lack of documentation for symbolic links. A lot
of this seems to be trial and error on my part as the implementation
isn't documented. This seems to do the trick, however, and all of the
tests are now passing on my end.

As always, send more problems my way.
2012-05-09 23:53:22 -04:00
Sam Soffes
581adbb98c Don't clean output director for debugging purposes 2012-05-09 09:54:16 -07:00
Sam Soffes
d646bf93a2 Add failing test for #14 2012-05-09 09:53:06 -07:00
Sam Soffes
b7598bc95f Version 0.2.1 2012-05-09 09:53:06 -07:00
Sam Soffes
236fcb7d65 Merge pull request #20 from florianbachmann/master
get rid of these three little warnings
2012-05-09 08:39:01 -07:00
Sam Soffes
a46e35e2b8 Remove warning in tests
* Switch to SSToolkit MD5 implementation
* Fix warning in MD5 implementation
2012-05-09 08:38:19 -07:00
Florian Bachmann
e171229257 get rid of these three warnings:
- Missing field 'tm_min' initializer
- Suggest braces around initialization of subobject
- Missing field 'dosDate' initializer
2012-05-09 08:38:19 -07:00
Sam Soffes
3a87f3ccfa Merge pull request #21 from EgoAleSum/patch-1
Fixed two warnings
2012-05-09 08:32:10 -07:00
Sam Soffes
df4ffca706 Merge pull request #22 from jparishy/preserve-symbolic-links
Preserve symbolic links. Fixes #5
2012-05-09 08:31:40 -07:00
Julius Parishy
64c542e090 Clean up and fix bug in test.
I commented out a bunch of NSLogs while debugging so I put those back
in, and fixed a bug where the test would crash if the symbolic link
failed to be created.
2012-05-09 11:14:56 -04:00
Julius Parishy
f900d38036 Symbolic Link support.
Adds support for ZIP files that include files that are symbolic links.
See the note in SSZipArchive.m for more information about that.
Includes a test that will probably only pass if you have GitHub for Mac
installed because that's the program I used as a test to symlink
against.

I created the symbolic link with 'ln -s /Applications/GitHub.app
SymbolicLink/GitHub.app' so I'm not entirely sure how it'll behave for
hard links, but I can't test that right now.
2012-05-09 11:12:04 -04:00
Alessandro Segala
9070c825f8 Fixed two warnings 2012-05-09 16:35:09 +02:00
Julius Parishy
bfc0904d14 Looking into the symbolic link issue.
http://www.pkware.com/documents/casestudies/APPNOTE.TXT
2012-05-09 08:18:19 -04:00
Florian Bachmann
45009d71e7 get rid of these three warnings:
- Missing field 'tm_min' initializer
- Suggest braces around initialization of subobject
- Missing field 'dosDate' initializer
2012-05-09 11:17:44 +02:00
Sam Soffes
b27c74b04c Merge pull request #19 from jparishy/master
Fix for Issue #16. Closes #16
2012-05-08 20:35:18 -07:00
Julius Parishy
b6f7f605fe Fix for Issue #16
Fixes issues with files being truncated when their headers have values
that represent smaller uncompressed sizes then the actual data. This
generally fixes issues where the whatever program zipped the file
fucked up the headers. The fix makes ssziparchive behave like other
unzip utilities that ignore the header and decompress the actual data
until it's finished.

I've tested a bunch and all of the tests included pass, if any other
issues arrive I'd be glad to take additional time to look into it.

Includes a file, IncorrectHeaders.zip, that is a zip of a folder called
IncorrectHeaders which includes a single file, Readme.txt. I've
intentionally changed the header for that file to read 50 bytes intend
of the actual 59 for testing purposes.
2012-05-08 22:55:30 -04:00
Sam Soffes
f6eb58cc51 Verify delegate file indexes. Closes #18
Using `zip` in Terminal generates zip files with just the files you zip. If you use OS X's archiver, it will add hidden files making the indexes appear to be wrong.
2012-05-08 09:47:56 -07:00
Sam Soffes
5651fb2c1b Add ARC note to readme 2012-05-08 00:08:44 -07:00
Sam Soffes
cd0be3772a Version 0.2.0 2012-05-07 23:48:03 -07:00
Sam Soffes
a7c7978c42 Update Changelog.markdown 2012-05-07 23:46:20 -07:00
Sam Soffes
f7e9630fd0 Fix support for unzipping with password. Fixes #13 2012-05-07 23:41:24 -07:00
Sam Soffes
c4b61b7092 Improve unzipping progress delegate 2012-05-07 23:09:29 -07:00
Sam Soffes
23426fd0de Fixes for unzipping modification dates and add ARC support
* Add ARC support
* Fixes: One of the bugs is that the file modification dates for files being unzipped were wrong. Apparently the code was taking the MS-DOS date and time and treating it as an NSTimeInterval since Jan 1, 1980. This is not correct and was resulting in modification dates for me in 2014. — Brant Sears
* Fixes: The second bug was that the file modification dates for folders were showing up as the current date/time, but when I unzip the same archive using Apple's implementation of zip, the file modification dates for those folders were set sometime in the past. — Brant Sears
2012-05-07 23:08:49 -07:00
Johannes Ekberg
f78aa2c1be added Progress Delegate Support 2012-05-07 23:07:38 -07:00
Johannes Ekberg
13edbb940e Added Delegation Support 2012-05-07 23:06:51 -07:00
Sam Soffes
c05ee25f7f Fixes for unzipping modification dates and add ARC support
* Add ARC support
* Fixes: One of the bugs is that the file modification dates for files being unzipped were wrong. Apparently the code was taking the MS-DOS date and time and treating it as an NSTimeInterval since Jan 1, 1980. This is not correct and was resulting in modification dates for me in 2014. — Brant Sears
* Fixes: The second bug was that the file modification dates for folders were showing up as the current date/time, but when I unzip the same archive using Apple's implementation of zip, the file modification dates for those folders were set sometime in the past. — Brant Sears
2012-05-07 22:27:45 -07:00
Sam Soffes
2ad10f1713 Fix warnings 2012-05-07 22:12:09 -07:00
Sam Soffes
f487007ff2 Merge pull request #10 from jazzbox/jazzbranch
Improved writing
2012-01-09 09:32:42 -08:00
Bernd Ohr
dbad12bffb writeData: writing chunks is unnecessary and set file date to now 2011-12-27 17:25:34 +01:00
Bernd Ohr
0a7c36ffb7 Dont't import "minizip/zip.h" in the header file 2011-12-27 17:15:40 +01:00
Sam Soffes
cd31818aa4 Updated readme 2011-12-26 23:38:42 -05:00
44 changed files with 1838 additions and 672 deletions

1
.gitignore vendored
View File

@@ -4,3 +4,4 @@
*.perspectivev3
*.xcworkspace
xcuserdata
DerivedData

View File

@@ -1,20 +0,0 @@
# SSZipArchive Changelog
### Version 0.1.2
[Released December 26, 2011](https://github.com/samsoffes/sskeychain/tree/0.1.2)
* Add creation support. Thanks Johnnie Walker ([@randomsequence](https://github.com/randomsequence))!
### Version 0.1.1
[Released October 31, 2011](https://github.com/samsoffes/sskeychain/tree/0.1.1)
* Added basic tests
* Upgraded minizip to 1.1 to support zip64
### Version 0.1.0
[Released September 18, 2011](https://github.com/samsoffes/sskeychain/tree/0.1.0)
* Initial release

View File

@@ -0,0 +1,13 @@
//
// SSAppDelegate.h
// SSZipArchive
//
// Created by Sam Soffes on 9/7/13.
// Copyright (c) 2013-2014 Sam Soffes. All rights reserved.
//
@interface SSAppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end

View File

@@ -0,0 +1,22 @@
//
// SSAppDelegate.m
// SSZipArchive
//
// Created by Sam Soffes on 9/7/13.
// Copyright (c) 2013-2014 Sam Soffes. All rights reserved.
//
#import "SSAppDelegate.h"
@implementation SSAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Nothing to see here yet.
[self.window makeKeyAndVisible];
return YES;
}
@end

View File

@@ -0,0 +1,16 @@
//
// Prefix header
//
// The contents of this file are implicitly included at the beginning of every source file.
//
#import <Availability.h>
#ifndef __IPHONE_3_0
#warning "This project uses features only available in iOS SDK 3.0 and later."
#endif
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#endif

View File

@@ -0,0 +1,15 @@
//
// main.m
// SSZipArchive
//
// Created by Sam Soffes on 9/7/13.
// Copyright (c) 2013-2014 Sam Soffes. All rights reserved.
//
#import "SSAppDelegate.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([SSAppDelegate class]));
}
}

View File

@@ -0,0 +1,53 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,51 @@
{
"images" : [
{
"orientation" : "portrait",
"idiom" : "iphone",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
},
{
"orientation" : "portrait",
"idiom" : "iphone",
"subtype" : "retina4",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
},
{
"orientation" : "portrait",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "1x"
},
{
"orientation" : "landscape",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "1x"
},
{
"orientation" : "portrait",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
},
{
"orientation" : "landscape",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>com.samsoffes.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>

View File

@@ -1,4 +1,4 @@
Copyright (c) 2010-2011 Sam Soffes
Copyright (c) 2010-2014 Sam Soffes, http://soff.es
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

View File

@@ -1,6 +1,6 @@
# SSZipArchive
SSZipArchive is a simple utility class for unzipping files originally based on [ZipArchive](http://code.google.com/p/ziparchive) by aish. Features:
SSZipArchive is a simple utility class for zipping and unzipping files. Features:
* Unzipping zip files
* Unzipping password protected zip files
@@ -11,9 +11,11 @@ SSZipArchive is a simple utility class for unzipping files originally based on [
## Adding to your project
1. Add `SSZipArchive.h`, `SSZipArchive.m`, and `minizip` to your project.
1. Add the `SSZipArchive` and `minizip` folders to your project.
2. Add the `libz` library to your target
SSZipArchive requires ARC.
## Usage
``` objective-c
@@ -31,10 +33,14 @@ NSArray *inputPaths = [NSArray arrayWithObjects:
[SSZipArchive createZipFileAtPath:zippedPath withFilesAtPaths:inputPaths];
```
## Tests
Simply, open the Xcode 5 or higher project in the Tests directory and press Command-U to run the tests.
## License
SSZipArchive is licensed under the [MIT license](https://github.com/samsoffes/ssziparchive/raw/master/LICENSE). A slightly modified version of [Minizip](http://www.winimage.com/zLibDll/minizip.html) 1.1 is also included and is licensed under the [Zlib license](http://www.zlib.net/zlib_license.html).
## Thanks
Thanks [aish](http://code.google.com/p/ziparchive) for creating [ZipArchive](http://code.google.com/p/ziparchive), Johnnie Walker ([@randomsequence](https://github.com/randomsequence)) for implementing creation support, and John Engelhart ([@johnezang](https://github.com/johnezang)) for his help along the way.
Thanks [aish](http://code.google.com/p/ziparchive) for creating [ZipArchive](http://code.google.com/p/ziparchive) which SSZipArchive is based on, Johnnie Walker ([@randomsequence](https://github.com/randomsequence)) for implementing creation support, and John Engelhart ([@johnezang](https://github.com/johnezang)) for all his amazing help along the way.

View File

@@ -1,27 +0,0 @@
//
// SSZipArchive.h
// SSZipArchive
//
// Created by Sam Soffes on 7/21/10.
// Copyright (c) Sam Soffes 2010-2011. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "minizip/zip.h"
@interface SSZipArchive : NSObject
// Unzip
+ (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination;
+ (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination overwrite:(BOOL)overwrite password:(NSString *)password error:(NSError **)error;
// Zip
+ (BOOL)createZipFileAtPath:(NSString *)path withFilesAtPaths:(NSArray *)filenames;
- (id)initWithPath:(NSString *)path;
- (BOOL)open;
- (BOOL)writeFile:(NSString *)path;
- (BOOL)writeData:(NSData *)data filename:(NSString *)filename;
- (BOOL)close;
@end

View File

@@ -1,267 +0,0 @@
//
// SSZipArchive.m
// SSZipArchive
//
// Created by Sam Soffes on 7/21/10.
// Copyright (c) Sam Soffes 2010-2011. All rights reserved.
//
#import "SSZipArchive.h"
#include "minizip/zip.h"
#include "minizip/unzip.h"
#import "zlib.h"
#import "zconf.h"
#define CHUNK 16384
@interface SSZipArchive ()
+ (NSDate *)_dateFor1980;
@end
@implementation SSZipArchive {
NSString *_path;
NSString *_filename;
zipFile _zip;
}
#pragma mark - Unzipping
+ (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination {
return [self unzipFileAtPath:path toDestination:destination overwrite:YES password:nil error:nil];
}
+ (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination overwrite:(BOOL)overwrite password:(NSString *)password error:(NSError **)error {
// Begin opening
zipFile zip = unzOpen((const char*)[path UTF8String]);
if (zip == NULL) {
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:@"failed to open zip file" forKey:NSLocalizedDescriptionKey];
if (error) {
*error = [NSError errorWithDomain:@"SSZipArchiveErrorDomain" code:-1 userInfo:userInfo];
}
return NO;
}
unz_global_info globalInfo = {0ul, 0ul};
unzGetGlobalInfo(zip, &globalInfo);
// Begin unzipping
if (unzGoToFirstFile(zip) != UNZ_OK) {
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:@"failed to open first file in zip file" forKey:NSLocalizedDescriptionKey];
if (error) {
*error = [NSError errorWithDomain:@"SSZipArchiveErrorDomain" code:-2 userInfo:userInfo];
}
return NO;
}
BOOL success = YES;
int ret;
unsigned char buffer[4096] = {0};
NSFileManager *fileManager = [NSFileManager defaultManager];
NSDate *nineteenEighty = [self _dateFor1980];
do {
if ([password length] == 0) {
ret = unzOpenCurrentFile(zip);
} else {
ret = unzOpenCurrentFilePassword(zip, [password cStringUsingEncoding:NSASCIIStringEncoding]);
}
if (ret != UNZ_OK) {
success = NO;
break;
}
// Reading data and write to file
unz_file_info fileInfo;
memset(&fileInfo, 0, sizeof(unz_file_info));
ret = unzGetCurrentFileInfo(zip, &fileInfo, NULL, 0, NULL, 0, NULL, 0);
if (ret != UNZ_OK) {
success = NO;
unzCloseCurrentFile(zip);
break;
}
char *filename = (char *)malloc(fileInfo.size_filename + 1);
unzGetCurrentFileInfo(zip, &fileInfo, filename, fileInfo.size_filename + 1, NULL, 0, NULL, 0);
filename[fileInfo.size_filename] = '\0';
// Check if it contains directory
NSString *strPath = [NSString stringWithCString:filename encoding:NSUTF8StringEncoding];
BOOL isDirectory = NO;
if (filename[fileInfo.size_filename-1] == '/' || filename[fileInfo.size_filename-1] == '\\') {
isDirectory = YES;
}
free(filename);
// Contains a path
if ([strPath rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"/\\"]].location != NSNotFound) {
strPath = [strPath stringByReplacingOccurrencesOfString:@"\\" withString:@"/"];
}
NSString* fullPath = [destination stringByAppendingPathComponent:strPath];
if (isDirectory) {
[fileManager createDirectoryAtPath:fullPath withIntermediateDirectories:YES attributes:nil error:nil];
} else {
[fileManager createDirectoryAtPath:[fullPath stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:nil];
}
if ([fileManager fileExistsAtPath:fullPath] && !isDirectory && !overwrite) {
unzCloseCurrentFile(zip);
ret = unzGoToNextFile(zip);
continue;
}
FILE *fp = fopen((const char*)[fullPath UTF8String], "wb");
while (fp) {
int readBytes = unzReadCurrentFile(zip, buffer, 4096);
if (readBytes > 0) {
fwrite(buffer, readBytes, 1, fp );
} else {
break;
}
}
if (fp) {
fclose(fp);
// Set the original datetime property
if (fileInfo.dosDate != 0) {
NSDate *orgDate = [[NSDate alloc] initWithTimeInterval:(NSTimeInterval)fileInfo.dosDate sinceDate:nineteenEighty];
NSDictionary *attr = [NSDictionary dictionaryWithObject:orgDate forKey:NSFileModificationDate];
if (attr) {
if ([fileManager setAttributes:attr ofItemAtPath:fullPath error:nil] == NO) {
// Can't set attributes
NSLog(@"Failed to set attributes");
}
}
[orgDate release];
}
}
unzCloseCurrentFile( zip );
ret = unzGoToNextFile( zip );
} while(ret == UNZ_OK && UNZ_OK != UNZ_END_OF_LIST_OF_FILE);
// Close
unzClose(zip);
return success;
}
#pragma mark - Zipping
+ (BOOL)createZipFileAtPath:(NSString *)path withFilesAtPaths:(NSArray *)paths {
BOOL success = NO;
SSZipArchive *zipArchive = [[SSZipArchive alloc] initWithPath:path];
if ([zipArchive open]) {
for (NSString *path in paths) {
[zipArchive writeFile:path];
}
success = [zipArchive close];
}
[zipArchive release];
return success;
}
- (id)initWithPath:(NSString *)path {
if ((self = [super init])) {
_path = [path copy];
}
return self;
}
- (void)dealloc {
[_path release];
[super dealloc];
}
- (BOOL)open {
NSAssert((_zip == NULL), @"Attempting open an archive which is already open");
_zip = zipOpen([_path UTF8String], APPEND_STATUS_CREATE);
return (NULL != _zip);
}
- (BOOL)writeFile:(NSString *)path {
NSAssert((_zip != NULL), @"Attempting to write to an archive which was never opened");
FILE *input = fopen([path UTF8String], "r");
if (NULL == input) {
return NO;
}
zipOpenNewFileInZip(_zip, [[path lastPathComponent] UTF8String], NULL, NULL, 0, NULL, 0, NULL, Z_DEFLATED,
Z_DEFAULT_COMPRESSION);
void *buffer = malloc(CHUNK);
unsigned int len = 0;
while (!feof(input)) {
len = (unsigned int) fread(buffer, 1, CHUNK, input);
zipWriteInFileInZip(_zip, buffer, len);
}
zipCloseFileInZip(_zip);
free(buffer);
return YES;
}
- (BOOL)writeData:(NSData *)data filename:(NSString *)filename {
NSAssert((_zip != NULL), @"Attempting to write to an archive which was never opened");
NSAssert((data != NULL), @"Nil data");
zipOpenNewFileInZip(_zip, [filename UTF8String], NULL, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION);
void *buffer = malloc(CHUNK);
unsigned int offset = 0;
NSUInteger length = [data length];
unsigned int chunk_length = 0;
while (offset < length) {
chunk_length = MIN(CHUNK, ((unsigned int) length)-offset);
[data getBytes:&buffer range:NSMakeRange(offset, chunk_length)];
zipWriteInFileInZip(_zip, buffer, chunk_length);
offset += chunk_length;
}
zipCloseFileInZip(_zip);
free(buffer);
return YES;
}
- (BOOL)close {
NSAssert((_zip != NULL), @"Attempting to close an archive which was never opened");
zipClose(_zip, NULL);
return YES;
}
#pragma mark - Private
+ (NSDate *)_dateFor1980 {
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setDay:1];
[comps setMonth:1];
[comps setYear:1980];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *date = [gregorian dateFromComponents:comps];
[comps release];
[gregorian release];
return date;
}
@end

14
SSZipArchive.podspec Normal file
View File

@@ -0,0 +1,14 @@
Pod::Spec.new do |s|
s.name = 'SSZipArchive'
s.version = '0.3.1'
s.summary = 'Utility class for zipping and unzipping files on iOS and Mac.'
s.description = 'SSZipArchive is a simple utility class for zipping and unzipping files on iOS and Mac.'
s.homepage = 'https://github.com/soffes/ssziparchive'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.author = { 'Sam Soffes' => 'sam@soff.es' }
s.source = { :git => 'https://github.com/soffes/ssziparchive.git', :tag => "v#{s.version}" }
s.ios.deployment_target = '4.0'
s.osx.deployment_target = '10.6'
s.source_files = 'SSZipArchive/**/*',
s.library = 'z'
end

View File

@@ -0,0 +1,534 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
011F4B96182D71B700DE704F /* RelativeSymbolicLink.zip in Resources */ = {isa = PBXBuildFile; fileRef = 011F4B95182D71B700DE704F /* RelativeSymbolicLink.zip */; };
011F4B97182D72B400DE704F /* RelativeSymbolicLink.zip in Resources */ = {isa = PBXBuildFile; fileRef = 011F4B95182D71B700DE704F /* RelativeSymbolicLink.zip */; };
210D525417DEFB880060D41A /* ioapi.c in Sources */ = {isa = PBXBuildFile; fileRef = 210D524C17DEFB880060D41A /* ioapi.c */; };
210D525517DEFB880060D41A /* ioapi.c in Sources */ = {isa = PBXBuildFile; fileRef = 210D524C17DEFB880060D41A /* ioapi.c */; };
210D525617DEFB880060D41A /* mztools.c in Sources */ = {isa = PBXBuildFile; fileRef = 210D524E17DEFB880060D41A /* mztools.c */; };
210D525717DEFB880060D41A /* mztools.c in Sources */ = {isa = PBXBuildFile; fileRef = 210D524E17DEFB880060D41A /* mztools.c */; };
210D525817DEFB880060D41A /* unzip.c in Sources */ = {isa = PBXBuildFile; fileRef = 210D525017DEFB880060D41A /* unzip.c */; };
210D525917DEFB880060D41A /* unzip.c in Sources */ = {isa = PBXBuildFile; fileRef = 210D525017DEFB880060D41A /* unzip.c */; };
210D525A17DEFB880060D41A /* zip.c in Sources */ = {isa = PBXBuildFile; fileRef = 210D525217DEFB880060D41A /* zip.c */; };
210D525B17DEFB880060D41A /* zip.c in Sources */ = {isa = PBXBuildFile; fileRef = 210D525217DEFB880060D41A /* zip.c */; };
21CC41A917DB7D1300201DDC /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21CC41A817DB7D1300201DDC /* Foundation.framework */; };
21CC41AB17DB7D1300201DDC /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21CC41AA17DB7D1300201DDC /* CoreGraphics.framework */; };
21CC41AD17DB7D1300201DDC /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21CC41AC17DB7D1300201DDC /* UIKit.framework */; };
21CC41C217DB7D1300201DDC /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21CC41C117DB7D1300201DDC /* XCTest.framework */; };
21CC41C317DB7D1300201DDC /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21CC41A817DB7D1300201DDC /* Foundation.framework */; };
21CC41C417DB7D1300201DDC /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21CC41AC17DB7D1300201DDC /* UIKit.framework */; };
21CC41EC17DB7D2F00201DDC /* SSZipArchive.m in Sources */ = {isa = PBXBuildFile; fileRef = 21CC41E317DB7D2F00201DDC /* SSZipArchive.m */; };
21CC41ED17DB7D2F00201DDC /* SSZipArchive.m in Sources */ = {isa = PBXBuildFile; fileRef = 21CC41E317DB7D2F00201DDC /* SSZipArchive.m */; };
21CC41F817DB7D3500201DDC /* IncorrectHeaders.zip in Resources */ = {isa = PBXBuildFile; fileRef = 21CC41F017DB7D3500201DDC /* IncorrectHeaders.zip */; };
21CC41F917DB7D3500201DDC /* PermissionsTestApp.app in Resources */ = {isa = PBXBuildFile; fileRef = 21CC41F117DB7D3500201DDC /* PermissionsTestApp.app */; };
21CC41FA17DB7D3500201DDC /* SymbolicLink.zip in Resources */ = {isa = PBXBuildFile; fileRef = 21CC41F217DB7D3500201DDC /* SymbolicLink.zip */; };
21CC41FB17DB7D3500201DDC /* TestArchive.zip in Resources */ = {isa = PBXBuildFile; fileRef = 21CC41F317DB7D3500201DDC /* TestArchive.zip */; };
21CC41FC17DB7D3500201DDC /* TestPasswordArchive.zip in Resources */ = {isa = PBXBuildFile; fileRef = 21CC41F417DB7D3500201DDC /* TestPasswordArchive.zip */; };
21CC41FD17DB7D3500201DDC /* Unicode.zip in Resources */ = {isa = PBXBuildFile; fileRef = 21CC41F517DB7D3500201DDC /* Unicode.zip */; };
21CC41FF17DB7D3500201DDC /* SSZipArchiveTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 21CC41F717DB7D3500201DDC /* SSZipArchiveTests.m */; };
21CC420F17DB7D6F00201DDC /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 21CC420817DB7D6300201DDC /* Images.xcassets */; };
21CC421017DB7D7400201DDC /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 21CC420517DB7D6300201DDC /* main.m */; };
21CC421117DB7D7900201DDC /* SSAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 21CC420317DB7D6300201DDC /* SSAppDelegate.m */; };
21CC421317DB7E0500201DDC /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 21CC421217DB7E0500201DDC /* libz.dylib */; };
21CC421417DB7E0900201DDC /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 21CC421217DB7E0500201DDC /* libz.dylib */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
21CC41C517DB7D1300201DDC /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 21CC419D17DB7D1300201DDC /* Project object */;
proxyType = 1;
remoteGlobalIDString = 21CC41A417DB7D1300201DDC;
remoteInfo = SSZipArchive;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
011F4B95182D71B700DE704F /* RelativeSymbolicLink.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = RelativeSymbolicLink.zip; sourceTree = "<group>"; };
210D524B17DEFB880060D41A /* crypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypt.h; sourceTree = "<group>"; };
210D524C17DEFB880060D41A /* ioapi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioapi.c; sourceTree = "<group>"; };
210D524D17DEFB880060D41A /* ioapi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ioapi.h; sourceTree = "<group>"; };
210D524E17DEFB880060D41A /* mztools.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mztools.c; sourceTree = "<group>"; };
210D524F17DEFB880060D41A /* mztools.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mztools.h; sourceTree = "<group>"; };
210D525017DEFB880060D41A /* unzip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = unzip.c; sourceTree = "<group>"; };
210D525117DEFB880060D41A /* unzip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = unzip.h; sourceTree = "<group>"; };
210D525217DEFB880060D41A /* zip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zip.c; sourceTree = "<group>"; };
210D525317DEFB880060D41A /* zip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zip.h; sourceTree = "<group>"; };
21CC41A517DB7D1300201DDC /* SSZipArchive.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SSZipArchive.app; sourceTree = BUILT_PRODUCTS_DIR; };
21CC41A817DB7D1300201DDC /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
21CC41AA17DB7D1300201DDC /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
21CC41AC17DB7D1300201DDC /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
21CC41C017DB7D1300201DDC /* SSZipArchiveTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SSZipArchiveTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
21CC41C117DB7D1300201DDC /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
21CC41E217DB7D2F00201DDC /* SSZipArchive.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SSZipArchive.h; sourceTree = "<group>"; };
21CC41E317DB7D2F00201DDC /* SSZipArchive.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SSZipArchive.m; sourceTree = "<group>"; };
21CC41F017DB7D3500201DDC /* IncorrectHeaders.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = IncorrectHeaders.zip; sourceTree = "<group>"; };
21CC41F117DB7D3500201DDC /* PermissionsTestApp.app */ = {isa = PBXFileReference; lastKnownFileType = wrapper.application; path = PermissionsTestApp.app; sourceTree = "<group>"; };
21CC41F217DB7D3500201DDC /* SymbolicLink.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = SymbolicLink.zip; sourceTree = "<group>"; };
21CC41F317DB7D3500201DDC /* TestArchive.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = TestArchive.zip; sourceTree = "<group>"; };
21CC41F417DB7D3500201DDC /* TestPasswordArchive.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = TestPasswordArchive.zip; sourceTree = "<group>"; };
21CC41F517DB7D3500201DDC /* Unicode.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = Unicode.zip; sourceTree = "<group>"; };
21CC41F617DB7D3500201DDC /* SSZipArchiveTests-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "SSZipArchiveTests-Info.plist"; sourceTree = "<group>"; };
21CC41F717DB7D3500201DDC /* SSZipArchiveTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SSZipArchiveTests.m; sourceTree = "<group>"; };
21CC420217DB7D6300201DDC /* SSAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SSAppDelegate.h; sourceTree = "<group>"; };
21CC420317DB7D6300201DDC /* SSAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SSAppDelegate.m; sourceTree = "<group>"; };
21CC420517DB7D6300201DDC /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
21CC420617DB7D6300201DDC /* SSZipArchive-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SSZipArchive-Prefix.pch"; sourceTree = "<group>"; };
21CC420817DB7D6300201DDC /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
21CC420917DB7D6300201DDC /* SSZipArchive-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "SSZipArchive-Info.plist"; sourceTree = "<group>"; };
21CC421217DB7E0500201DDC /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
21CC41A217DB7D1300201DDC /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
21CC421317DB7E0500201DDC /* libz.dylib in Frameworks */,
21CC41AB17DB7D1300201DDC /* CoreGraphics.framework in Frameworks */,
21CC41AD17DB7D1300201DDC /* UIKit.framework in Frameworks */,
21CC41A917DB7D1300201DDC /* Foundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
21CC41BD17DB7D1300201DDC /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
21CC421417DB7E0900201DDC /* libz.dylib in Frameworks */,
21CC41C217DB7D1300201DDC /* XCTest.framework in Frameworks */,
21CC41C417DB7D1300201DDC /* UIKit.framework in Frameworks */,
21CC41C317DB7D1300201DDC /* Foundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
210D524A17DEFB880060D41A /* minizip */ = {
isa = PBXGroup;
children = (
210D524B17DEFB880060D41A /* crypt.h */,
210D524C17DEFB880060D41A /* ioapi.c */,
210D524D17DEFB880060D41A /* ioapi.h */,
210D524E17DEFB880060D41A /* mztools.c */,
210D524F17DEFB880060D41A /* mztools.h */,
210D525017DEFB880060D41A /* unzip.c */,
210D525117DEFB880060D41A /* unzip.h */,
210D525217DEFB880060D41A /* zip.c */,
210D525317DEFB880060D41A /* zip.h */,
);
path = minizip;
sourceTree = "<group>";
};
21CC419C17DB7D1300201DDC = {
isa = PBXGroup;
children = (
21CC41D717DB7D2F00201DDC /* SSZipArchive */,
21CC420017DB7D6300201DDC /* Example */,
21CC41EE17DB7D3500201DDC /* Tests */,
21CC41A717DB7D1300201DDC /* Frameworks */,
21CC41A617DB7D1300201DDC /* Products */,
);
sourceTree = "<group>";
};
21CC41A617DB7D1300201DDC /* Products */ = {
isa = PBXGroup;
children = (
21CC41A517DB7D1300201DDC /* SSZipArchive.app */,
21CC41C017DB7D1300201DDC /* SSZipArchiveTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
21CC41A717DB7D1300201DDC /* Frameworks */ = {
isa = PBXGroup;
children = (
21CC421217DB7E0500201DDC /* libz.dylib */,
21CC41A817DB7D1300201DDC /* Foundation.framework */,
21CC41AA17DB7D1300201DDC /* CoreGraphics.framework */,
21CC41AC17DB7D1300201DDC /* UIKit.framework */,
21CC41C117DB7D1300201DDC /* XCTest.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
21CC41D717DB7D2F00201DDC /* SSZipArchive */ = {
isa = PBXGroup;
children = (
21CC41E217DB7D2F00201DDC /* SSZipArchive.h */,
21CC41E317DB7D2F00201DDC /* SSZipArchive.m */,
210D524A17DEFB880060D41A /* minizip */,
);
path = SSZipArchive;
sourceTree = "<group>";
};
21CC41EE17DB7D3500201DDC /* Tests */ = {
isa = PBXGroup;
children = (
21CC41EF17DB7D3500201DDC /* Fixtures */,
21CC41F617DB7D3500201DDC /* SSZipArchiveTests-Info.plist */,
21CC41F717DB7D3500201DDC /* SSZipArchiveTests.m */,
);
path = Tests;
sourceTree = "<group>";
};
21CC41EF17DB7D3500201DDC /* Fixtures */ = {
isa = PBXGroup;
children = (
011F4B95182D71B700DE704F /* RelativeSymbolicLink.zip */,
21CC41F017DB7D3500201DDC /* IncorrectHeaders.zip */,
21CC41F117DB7D3500201DDC /* PermissionsTestApp.app */,
21CC41F217DB7D3500201DDC /* SymbolicLink.zip */,
21CC41F317DB7D3500201DDC /* TestArchive.zip */,
21CC41F417DB7D3500201DDC /* TestPasswordArchive.zip */,
21CC41F517DB7D3500201DDC /* Unicode.zip */,
);
path = Fixtures;
sourceTree = "<group>";
};
21CC420017DB7D6300201DDC /* Example */ = {
isa = PBXGroup;
children = (
21CC420117DB7D6300201DDC /* Classes */,
21CC420417DB7D6300201DDC /* Other Sources */,
21CC420717DB7D6300201DDC /* Resources */,
);
path = Example;
sourceTree = "<group>";
};
21CC420117DB7D6300201DDC /* Classes */ = {
isa = PBXGroup;
children = (
21CC420217DB7D6300201DDC /* SSAppDelegate.h */,
21CC420317DB7D6300201DDC /* SSAppDelegate.m */,
);
path = Classes;
sourceTree = "<group>";
};
21CC420417DB7D6300201DDC /* Other Sources */ = {
isa = PBXGroup;
children = (
21CC420517DB7D6300201DDC /* main.m */,
21CC420617DB7D6300201DDC /* SSZipArchive-Prefix.pch */,
);
path = "Other Sources";
sourceTree = "<group>";
};
21CC420717DB7D6300201DDC /* Resources */ = {
isa = PBXGroup;
children = (
21CC420817DB7D6300201DDC /* Images.xcassets */,
21CC420917DB7D6300201DDC /* SSZipArchive-Info.plist */,
);
path = Resources;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
21CC41A417DB7D1300201DDC /* SSZipArchive */ = {
isa = PBXNativeTarget;
buildConfigurationList = 21CC41D117DB7D1300201DDC /* Build configuration list for PBXNativeTarget "SSZipArchive" */;
buildPhases = (
21CC41A117DB7D1300201DDC /* Sources */,
21CC41A217DB7D1300201DDC /* Frameworks */,
21CC41A317DB7D1300201DDC /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = SSZipArchive;
productName = SSZipArchive;
productReference = 21CC41A517DB7D1300201DDC /* SSZipArchive.app */;
productType = "com.apple.product-type.application";
};
21CC41BF17DB7D1300201DDC /* SSZipArchiveTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 21CC41D417DB7D1300201DDC /* Build configuration list for PBXNativeTarget "SSZipArchiveTests" */;
buildPhases = (
21CC41BC17DB7D1300201DDC /* Sources */,
21CC41BD17DB7D1300201DDC /* Frameworks */,
21CC41BE17DB7D1300201DDC /* Resources */,
);
buildRules = (
);
dependencies = (
21CC41C617DB7D1300201DDC /* PBXTargetDependency */,
);
name = SSZipArchiveTests;
productName = SSZipArchiveTests;
productReference = 21CC41C017DB7D1300201DDC /* SSZipArchiveTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
21CC419D17DB7D1300201DDC /* Project object */ = {
isa = PBXProject;
attributes = {
CLASSPREFIX = SS;
LastUpgradeCheck = 0500;
ORGANIZATIONNAME = "Sam Soffes";
TargetAttributes = {
21CC41BF17DB7D1300201DDC = {
TestTargetID = 21CC41A417DB7D1300201DDC;
};
};
};
buildConfigurationList = 21CC41A017DB7D1300201DDC /* Build configuration list for PBXProject "SSZipArchive" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = 21CC419C17DB7D1300201DDC;
productRefGroup = 21CC41A617DB7D1300201DDC /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
21CC41A417DB7D1300201DDC /* SSZipArchive */,
21CC41BF17DB7D1300201DDC /* SSZipArchiveTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
21CC41A317DB7D1300201DDC /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
21CC420F17DB7D6F00201DDC /* Images.xcassets in Resources */,
011F4B96182D71B700DE704F /* RelativeSymbolicLink.zip in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
21CC41BE17DB7D1300201DDC /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
011F4B97182D72B400DE704F /* RelativeSymbolicLink.zip in Resources */,
21CC41F817DB7D3500201DDC /* IncorrectHeaders.zip in Resources */,
21CC41FD17DB7D3500201DDC /* Unicode.zip in Resources */,
21CC41FA17DB7D3500201DDC /* SymbolicLink.zip in Resources */,
21CC41F917DB7D3500201DDC /* PermissionsTestApp.app in Resources */,
21CC41FB17DB7D3500201DDC /* TestArchive.zip in Resources */,
21CC41FC17DB7D3500201DDC /* TestPasswordArchive.zip in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
21CC41A117DB7D1300201DDC /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
210D525817DEFB880060D41A /* unzip.c in Sources */,
21CC41EC17DB7D2F00201DDC /* SSZipArchive.m in Sources */,
21CC421117DB7D7900201DDC /* SSAppDelegate.m in Sources */,
210D525417DEFB880060D41A /* ioapi.c in Sources */,
210D525A17DEFB880060D41A /* zip.c in Sources */,
21CC421017DB7D7400201DDC /* main.m in Sources */,
210D525617DEFB880060D41A /* mztools.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
21CC41BC17DB7D1300201DDC /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
210D525517DEFB880060D41A /* ioapi.c in Sources */,
210D525917DEFB880060D41A /* unzip.c in Sources */,
21CC41FF17DB7D3500201DDC /* SSZipArchiveTests.m in Sources */,
210D525B17DEFB880060D41A /* zip.c in Sources */,
210D525717DEFB880060D41A /* mztools.c in Sources */,
21CC41ED17DB7D2F00201DDC /* SSZipArchive.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
21CC41C617DB7D1300201DDC /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 21CC41A417DB7D1300201DDC /* SSZipArchive */;
targetProxy = 21CC41C517DB7D1300201DDC /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
21CC41CF17DB7D1300201DDC /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
21CC41D017DB7D1300201DDC /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = YES;
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
21CC41D217DB7D1300201DDC /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Example/Other Sources/SSZipArchive-Prefix.pch";
INFOPLIST_FILE = "Example/Resources/SSZipArchive-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
name = Debug;
};
21CC41D317DB7D1300201DDC /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Example/Other Sources/SSZipArchive-Prefix.pch";
INFOPLIST_FILE = "Example/Resources/SSZipArchive-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
name = Release;
};
21CC41D517DB7D1300201DDC /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/SSZipArchive.app/SSZipArchive";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
"$(DEVELOPER_FRAMEWORKS_DIR)",
);
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = "Tests/SSZipArchiveTests-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUNDLE_LOADER)";
WRAPPER_EXTENSION = xctest;
};
name = Debug;
};
21CC41D617DB7D1300201DDC /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/SSZipArchive.app/SSZipArchive";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
"$(DEVELOPER_FRAMEWORKS_DIR)",
);
INFOPLIST_FILE = "Tests/SSZipArchiveTests-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUNDLE_LOADER)";
WRAPPER_EXTENSION = xctest;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
21CC41A017DB7D1300201DDC /* Build configuration list for PBXProject "SSZipArchive" */ = {
isa = XCConfigurationList;
buildConfigurations = (
21CC41CF17DB7D1300201DDC /* Debug */,
21CC41D017DB7D1300201DDC /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
21CC41D117DB7D1300201DDC /* Build configuration list for PBXNativeTarget "SSZipArchive" */ = {
isa = XCConfigurationList;
buildConfigurations = (
21CC41D217DB7D1300201DDC /* Debug */,
21CC41D317DB7D1300201DDC /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
21CC41D417DB7D1300201DDC /* Build configuration list for PBXNativeTarget "SSZipArchiveTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
21CC41D517DB7D1300201DDC /* Debug */,
21CC41D617DB7D1300201DDC /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 21CC419D17DB7D1300201DDC /* Project object */;
}

View File

@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0500"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "21CC41A417DB7D1300201DDC"
BuildableName = "SSZipArchive.app"
BlueprintName = "SSZipArchive"
ReferencedContainer = "container:SSZipArchive.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "21CC41BF17DB7D1300201DDC"
BuildableName = "SSZipArchiveTests.xctest"
BlueprintName = "SSZipArchiveTests"
ReferencedContainer = "container:SSZipArchive.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "21CC41A417DB7D1300201DDC"
BuildableName = "SSZipArchive.app"
BlueprintName = "SSZipArchive"
ReferencedContainer = "container:SSZipArchive.xcodeproj">
</BuildableReference>
</MacroExpansion>
</TestAction>
<LaunchAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
allowLocationSimulation = "YES">
<BuildableProductRunnable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "21CC41A417DB7D1300201DDC"
BuildableName = "SSZipArchive.app"
BlueprintName = "SSZipArchive"
ReferencedContainer = "container:SSZipArchive.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
<BuildableProductRunnable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "21CC41A417DB7D1300201DDC"
BuildableName = "SSZipArchive.app"
BlueprintName = "SSZipArchive"
ReferencedContainer = "container:SSZipArchive.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@@ -0,0 +1,52 @@
//
// SSZipArchive.h
// SSZipArchive
//
// Created by Sam Soffes on 7/21/10.
// Copyright (c) Sam Soffes 2010-2014. All rights reserved.
//
#ifndef _SSZIPARCHIVE_H
#define _SSZIPARCHIVE_H
#import <Foundation/Foundation.h>
#include "unzip.h"
@protocol SSZipArchiveDelegate;
@interface SSZipArchive : NSObject
// Unzip
+ (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination;
+ (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination overwrite:(BOOL)overwrite password:(NSString *)password error:(NSError **)error;
+ (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination delegate:(id<SSZipArchiveDelegate>)delegate;
+ (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination overwrite:(BOOL)overwrite password:(NSString *)password error:(NSError **)error delegate:(id<SSZipArchiveDelegate>)delegate;
// Zip
+ (BOOL)createZipFileAtPath:(NSString *)path withFilesAtPaths:(NSArray *)filenames;
+ (BOOL)createZipFileAtPath:(NSString *)path withContentsOfDirectory:(NSString *)directoryPath;
- (id)initWithPath:(NSString *)path;
- (BOOL)open;
- (BOOL)writeFile:(NSString *)path;
- (BOOL)writeData:(NSData *)data filename:(NSString *)filename;
- (BOOL)close;
@end
@protocol SSZipArchiveDelegate <NSObject>
@optional
- (void)zipArchiveWillUnzipArchiveAtPath:(NSString *)path zipInfo:(unz_global_info)zipInfo;
- (void)zipArchiveDidUnzipArchiveAtPath:(NSString *)path zipInfo:(unz_global_info)zipInfo unzippedPath:(NSString *)unzippedPath;
- (void)zipArchiveWillUnzipFileAtIndex:(NSInteger)fileIndex totalFiles:(NSInteger)totalFiles archivePath:(NSString *)archivePath fileInfo:(unz_file_info)fileInfo;
- (void)zipArchiveDidUnzipFileAtIndex:(NSInteger)fileIndex totalFiles:(NSInteger)totalFiles archivePath:(NSString *)archivePath fileInfo:(unz_file_info)fileInfo;
- (void)zipArchiveProgressEvent:(NSInteger)loaded total:(NSInteger)total;
@end
#endif /* _SSZIPARCHIVE_H */

532
SSZipArchive/SSZipArchive.m Normal file
View File

@@ -0,0 +1,532 @@
//
// SSZipArchive.m
// SSZipArchive
//
// Created by Sam Soffes on 7/21/10.
// Copyright (c) Sam Soffes 2010-2014. All rights reserved.
//
#import "SSZipArchive.h"
#include "zip.h"
#import "zlib.h"
#import "zconf.h"
#include <sys/stat.h>
#define CHUNK 16384
@interface SSZipArchive ()
+ (NSDate *)_dateWithMSDOSFormat:(UInt32)msdosDateTime;
@end
@implementation SSZipArchive {
NSString *_path;
NSString *_filename;
zipFile _zip;
}
#pragma mark - Unzipping
+ (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination {
return [self unzipFileAtPath:path toDestination:destination delegate:nil];
}
+ (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination overwrite:(BOOL)overwrite password:(NSString *)password error:(NSError **)error {
return [self unzipFileAtPath:path toDestination:destination overwrite:overwrite password:password error:error delegate:nil];
}
+ (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination delegate:(id<SSZipArchiveDelegate>)delegate {
return [self unzipFileAtPath:path toDestination:destination overwrite:YES password:nil error:nil delegate:delegate];
}
+ (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination overwrite:(BOOL)overwrite password:(NSString *)password error:(NSError **)error delegate:(id<SSZipArchiveDelegate>)delegate {
// Begin opening
zipFile zip = unzOpen((const char*)[path UTF8String]);
if (zip == NULL) {
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:@"failed to open zip file" forKey:NSLocalizedDescriptionKey];
if (error) {
*error = [NSError errorWithDomain:@"SSZipArchiveErrorDomain" code:-1 userInfo:userInfo];
}
return NO;
}
NSDictionary * fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil];
ZPOS64_T fileSize = fileAttributes.fileSize;
ZPOS64_T currentPosition = 0;
unz_global_info globalInfo = {0ul, 0ul};
unzGetGlobalInfo(zip, &globalInfo);
// Begin unzipping
if (unzGoToFirstFile(zip) != UNZ_OK) {
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:@"failed to open first file in zip file" forKey:NSLocalizedDescriptionKey];
if (error) {
*error = [NSError errorWithDomain:@"SSZipArchiveErrorDomain" code:-2 userInfo:userInfo];
}
return NO;
}
BOOL success = YES;
int ret = 0;
unsigned char buffer[4096] = {0};
NSFileManager *fileManager = [NSFileManager defaultManager];
NSMutableSet *directoriesModificationDates = [[NSMutableSet alloc] init];
// Message delegate
if ([delegate respondsToSelector:@selector(zipArchiveWillUnzipArchiveAtPath:zipInfo:)]) {
[delegate zipArchiveWillUnzipArchiveAtPath:path zipInfo:globalInfo];
}
if ([delegate respondsToSelector:@selector(zipArchiveProgressEvent:total:)]) {
[delegate zipArchiveProgressEvent:currentPosition total:fileSize];
}
NSInteger currentFileNumber = 0;
do {
@autoreleasepool {
if ([password length] == 0) {
ret = unzOpenCurrentFile(zip);
} else {
ret = unzOpenCurrentFilePassword(zip, [password cStringUsingEncoding:NSASCIIStringEncoding]);
}
if (ret != UNZ_OK) {
success = NO;
break;
}
// Reading data and write to file
unz_file_info fileInfo;
memset(&fileInfo, 0, sizeof(unz_file_info));
ret = unzGetCurrentFileInfo(zip, &fileInfo, NULL, 0, NULL, 0, NULL, 0);
if (ret != UNZ_OK) {
success = NO;
unzCloseCurrentFile(zip);
break;
}
currentPosition += fileInfo.compressed_size;
// Message delegate
if ([delegate respondsToSelector:@selector(zipArchiveWillUnzipFileAtIndex:totalFiles:archivePath:fileInfo:)]) {
[delegate zipArchiveWillUnzipFileAtIndex:currentFileNumber totalFiles:(NSInteger)globalInfo.number_entry
archivePath:path fileInfo:fileInfo];
}
if ([delegate respondsToSelector:@selector(zipArchiveProgressEvent:total:)]) {
[delegate zipArchiveProgressEvent:currentPosition total:fileSize];
}
char *filename = (char *)malloc(fileInfo.size_filename + 1);
unzGetCurrentFileInfo(zip, &fileInfo, filename, fileInfo.size_filename + 1, NULL, 0, NULL, 0);
filename[fileInfo.size_filename] = '\0';
//
// Determine whether this is a symbolic link:
// - File is stored with 'version made by' value of UNIX (3),
// as per http://www.pkware.com/documents/casestudies/APPNOTE.TXT
// in the upper byte of the version field.
// - BSD4.4 st_mode constants are stored in the high 16 bits of the
// external file attributes (defacto standard, verified against libarchive)
//
// The original constants can be found here:
// http://minnie.tuhs.org/cgi-bin/utree.pl?file=4.4BSD/usr/include/sys/stat.h
//
const uLong ZipUNIXVersion = 3;
const uLong BSD_SFMT = 0170000;
const uLong BSD_IFLNK = 0120000;
BOOL fileIsSymbolicLink = NO;
if (((fileInfo.version >> 8) == ZipUNIXVersion) && BSD_IFLNK == (BSD_SFMT & (fileInfo.external_fa >> 16))) {
fileIsSymbolicLink = YES;
}
// Check if it contains directory
NSString *strPath = [NSString stringWithCString:filename encoding:NSUTF8StringEncoding];
BOOL isDirectory = NO;
if (filename[fileInfo.size_filename-1] == '/' || filename[fileInfo.size_filename-1] == '\\') {
isDirectory = YES;
}
free(filename);
// Contains a path
if ([strPath rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"/\\"]].location != NSNotFound) {
strPath = [strPath stringByReplacingOccurrencesOfString:@"\\" withString:@"/"];
}
NSString *fullPath = [destination stringByAppendingPathComponent:strPath];
NSError *err = nil;
NSDate *modDate = [[self class] _dateWithMSDOSFormat:(UInt32)fileInfo.dosDate];
NSDictionary *directoryAttr = [NSDictionary dictionaryWithObjectsAndKeys:modDate, NSFileCreationDate, modDate, NSFileModificationDate, nil];
if (isDirectory) {
[fileManager createDirectoryAtPath:fullPath withIntermediateDirectories:YES attributes:directoryAttr error:&err];
} else {
[fileManager createDirectoryAtPath:[fullPath stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:directoryAttr error:&err];
}
if (nil != err) {
NSLog(@"[SSZipArchive] Error: %@", err.localizedDescription);
}
if(!fileIsSymbolicLink)
[directoriesModificationDates addObject: [NSDictionary dictionaryWithObjectsAndKeys:fullPath, @"path", modDate, @"modDate", nil]];
if ([fileManager fileExistsAtPath:fullPath] && !isDirectory && !overwrite) {
unzCloseCurrentFile(zip);
ret = unzGoToNextFile(zip);
continue;
}
if(!fileIsSymbolicLink)
{
FILE *fp = fopen((const char*)[fullPath UTF8String], "wb");
while (fp) {
int readBytes = unzReadCurrentFile(zip, buffer, 4096);
if (readBytes > 0) {
fwrite(buffer, readBytes, 1, fp );
} else {
break;
}
}
if (fp) {
fclose(fp);
// Set the original datetime property
if (fileInfo.dosDate != 0) {
NSDate *orgDate = [[self class] _dateWithMSDOSFormat:(UInt32)fileInfo.dosDate];
NSDictionary *attr = [NSDictionary dictionaryWithObject:orgDate forKey:NSFileModificationDate];
if (attr) {
if ([fileManager setAttributes:attr ofItemAtPath:fullPath error:nil] == NO) {
// Can't set attributes
NSLog(@"[SSZipArchive] Failed to set attributes - whilst setting modification date");
}
}
}
// Set the original permissions on the file
uLong permissions = fileInfo.external_fa >> 16;
if (permissions != 0) {
// Store it into a NSNumber
NSNumber *permissionsValue = @(permissions);
// Retrieve any existing attributes
NSMutableDictionary *attrs = [[NSMutableDictionary alloc] initWithDictionary:[fileManager attributesOfItemAtPath:fullPath error:nil]];
// Set the value in the attributes dict
attrs[NSFilePosixPermissions] = permissionsValue;
// Update attributes
if ([fileManager setAttributes:attrs ofItemAtPath:fullPath error:nil] == NO) {
// Unable to set the permissions attribute
NSLog(@"[SSZipArchive] Failed to set attributes - whilst setting permissions");
}
#if !__has_feature(objc_arc)
[attrs release];
#endif
}
}
}
else
{
// Assemble the path for the symbolic link
NSMutableString* destinationPath = [NSMutableString string];
int bytesRead = 0;
while((bytesRead = unzReadCurrentFile(zip, buffer, 4096)) > 0)
{
buffer[bytesRead] = 0;
[destinationPath appendString:[NSString stringWithUTF8String:(const char*)buffer]];
}
// Create the symbolic link (making sure it stays relative if it was relative before)
int symlinkError = symlink([destinationPath cStringUsingEncoding:NSUTF8StringEncoding],
[fullPath cStringUsingEncoding:NSUTF8StringEncoding]);
if(symlinkError != 0)
{
NSLog(@"Failed to create symbolic link at \"%@\" to \"%@\". symlink() error code: %d", fullPath, destinationPath, errno);
}
}
unzCloseCurrentFile( zip );
ret = unzGoToNextFile( zip );
// Message delegate
if ([delegate respondsToSelector:@selector(zipArchiveDidUnzipFileAtIndex:totalFiles:archivePath:fileInfo:)]) {
[delegate zipArchiveDidUnzipFileAtIndex:currentFileNumber totalFiles:(NSInteger)globalInfo.number_entry
archivePath:path fileInfo:fileInfo];
}
currentFileNumber++;
}
} while(ret == UNZ_OK && ret != UNZ_END_OF_LIST_OF_FILE);
// Close
unzClose(zip);
// The process of decompressing the .zip archive causes the modification times on the folders
// to be set to the present time. So, when we are done, they need to be explicitly set.
// set the modification date on all of the directories.
NSError * err = nil;
for (NSDictionary * d in directoriesModificationDates) {
if (![[NSFileManager defaultManager] setAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[d objectForKey:@"modDate"], NSFileModificationDate, nil] ofItemAtPath:[d objectForKey:@"path"] error:&err]) {
NSLog(@"[SSZipArchive] Set attributes failed for directory: %@.", [d objectForKey:@"path"]);
}
if (err) {
NSLog(@"[SSZipArchive] Error setting directory file modification date attribute: %@",err.localizedDescription);
}
}
#if !__has_feature(objc_arc)
[directoriesModificationDates release];
#endif
// Message delegate
if (success && [delegate respondsToSelector:@selector(zipArchiveDidUnzipArchiveAtPath:zipInfo:unzippedPath:)]) {
[delegate zipArchiveDidUnzipArchiveAtPath:path zipInfo:globalInfo unzippedPath:destination];
}
// final progress event = 100%
if ([delegate respondsToSelector:@selector(zipArchiveProgressEvent:total:)]) {
[delegate zipArchiveProgressEvent:fileSize total:fileSize];
}
return success;
}
#pragma mark - Zipping
+ (BOOL)createZipFileAtPath:(NSString *)path withFilesAtPaths:(NSArray *)paths {
BOOL success = NO;
SSZipArchive *zipArchive = [[SSZipArchive alloc] initWithPath:path];
if ([zipArchive open]) {
for (NSString *path in paths) {
[zipArchive writeFile:path];
}
success = [zipArchive close];
}
#if !__has_feature(objc_arc)
[zipArchive release];
#endif
return success;
}
+ (BOOL)createZipFileAtPath:(NSString *)path withContentsOfDirectory:(NSString *)directoryPath {
BOOL success = NO;
NSFileManager *fileManager = nil;
SSZipArchive *zipArchive = [[SSZipArchive alloc] initWithPath:path];
if ([zipArchive open]) {
// use a local filemanager (queue/thread compatibility)
fileManager = [[NSFileManager alloc] init];
NSDirectoryEnumerator *dirEnumerator = [fileManager enumeratorAtPath:directoryPath];
NSString *fileName;
while ((fileName = [dirEnumerator nextObject])) {
BOOL isDir;
NSString *fullFilePath = [directoryPath stringByAppendingPathComponent:fileName];
[fileManager fileExistsAtPath:fullFilePath isDirectory:&isDir];
if (!isDir) {
[zipArchive writeFileAtPath:fullFilePath withFileName:fileName];
}
}
success = [zipArchive close];
}
#if !__has_feature(objc_arc)
[fileManager release];
[zipArchive release];
#endif
return success;
}
- (id)initWithPath:(NSString *)path {
if ((self = [super init])) {
_path = [path copy];
}
return self;
}
#if !__has_feature(objc_arc)
- (void)dealloc {
[_path release];
[super dealloc];
}
#endif
- (BOOL)open {
NSAssert((_zip == NULL), @"Attempting open an archive which is already open");
_zip = zipOpen([_path UTF8String], APPEND_STATUS_CREATE);
return (NULL != _zip);
}
- (void)zipInfo:(zip_fileinfo*)zipInfo setDate:(NSDate*)date {
NSCalendar *currentCalendar = [NSCalendar currentCalendar];
uint flags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
NSDateComponents *components = [currentCalendar components:flags fromDate:date];
zipInfo->tmz_date.tm_sec = (unsigned int)components.second;
zipInfo->tmz_date.tm_min = (unsigned int)components.minute;
zipInfo->tmz_date.tm_hour = (unsigned int)components.hour;
zipInfo->tmz_date.tm_mday = (unsigned int)components.day;
zipInfo->tmz_date.tm_mon = (unsigned int)components.month - 1;
zipInfo->tmz_date.tm_year = (unsigned int)components.year;
}
- (BOOL)writeFile:(NSString *)path
{
return [self writeFileAtPath:path withFileName:nil];
}
// supports writing files with logical folder/directory structure
// *path* is the absolute path of the file that will be compressed
// *fileName* is the relative name of the file how it is stored within the zip e.g. /folder/subfolder/text1.txt
- (BOOL)writeFileAtPath:(NSString *)path withFileName:(NSString *)fileName {
NSAssert((_zip != NULL), @"Attempting to write to an archive which was never opened");
FILE *input = fopen([path UTF8String], "r");
if (NULL == input) {
return NO;
}
const char *afileName;
if (!fileName) {
afileName = [path.lastPathComponent UTF8String];
}
else {
afileName = [fileName UTF8String];
}
zip_fileinfo zipInfo = {{0}};
NSDictionary *attr = [[NSFileManager defaultManager] attributesOfItemAtPath:path error: nil];
if( attr )
{
NSDate *fileDate = (NSDate *)[attr objectForKey:NSFileModificationDate];
if( fileDate )
{
[self zipInfo:&zipInfo setDate: fileDate ];
}
// Write permissions into the external attributes, for details on this see here: http://unix.stackexchange.com/a/14727
// Get the permissions value from the files attributes
NSNumber *permissionsValue = (NSNumber *)[attr objectForKey:NSFilePosixPermissions];
if (permissionsValue) {
// Get the short value for the permissions
short permissionsShort = permissionsValue.shortValue;
// Convert this into an octal by adding 010000, 010000 being the flag for a regular file
NSInteger permissionsOctal = 0100000 + permissionsShort;
// Convert this into a long value
uLong permissionsLong = @(permissionsOctal).unsignedLongValue;
// Store this into the external file attributes once it has been shifted 16 places left to form part of the second from last byte
zipInfo.external_fa = permissionsLong << 16L;
}
}
zipOpenNewFileInZip(_zip, afileName, &zipInfo, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION);
void *buffer = malloc(CHUNK);
unsigned int len = 0;
while (!feof(input))
{
len = (unsigned int) fread(buffer, 1, CHUNK, input);
zipWriteInFileInZip(_zip, buffer, len);
}
zipCloseFileInZip(_zip);
free(buffer);
fclose(input);
return YES;
}
- (BOOL)writeData:(NSData *)data filename:(NSString *)filename {
if (!_zip) {
return NO;
}
if (!data) {
return NO;
}
zip_fileinfo zipInfo = {{0,0,0,0,0,0},0,0,0};
[self zipInfo:&zipInfo setDate:[NSDate date]];
zipOpenNewFileInZip(_zip, [filename UTF8String], &zipInfo, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION);
zipWriteInFileInZip(_zip, data.bytes, (unsigned int)data.length);
zipCloseFileInZip(_zip);
return YES;
}
- (BOOL)close {
NSAssert((_zip != NULL), @"[SSZipArchive] Attempting to close an archive which was never opened");
zipClose(_zip, NULL);
return YES;
}
#pragma mark - Private
// Format from http://newsgroups.derkeiler.com/Archive/Comp/comp.os.msdos.programmer/2009-04/msg00060.html
// Two consecutive words, or a longword, YYYYYYYMMMMDDDDD hhhhhmmmmmmsssss
// YYYYYYY is years from 1980 = 0
// sssss is (seconds/2).
//
// 3658 = 0011 0110 0101 1000 = 0011011 0010 11000 = 27 2 24 = 2007-02-24
// 7423 = 0111 0100 0010 0011 - 01110 100001 00011 = 14 33 2 = 14:33:06
+ (NSDate *)_dateWithMSDOSFormat:(UInt32)msdosDateTime {
static const UInt32 kYearMask = 0xFE000000;
static const UInt32 kMonthMask = 0x1E00000;
static const UInt32 kDayMask = 0x1F0000;
static const UInt32 kHourMask = 0xF800;
static const UInt32 kMinuteMask = 0x7E0;
static const UInt32 kSecondMask = 0x1F;
static NSCalendar *gregorian;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
});
NSDateComponents *components = [[NSDateComponents alloc] init];
NSAssert(0xFFFFFFFF == (kYearMask | kMonthMask | kDayMask | kHourMask | kMinuteMask | kSecondMask), @"[SSZipArchive] MSDOS date masks don't add up");
[components setYear:1980 + ((msdosDateTime & kYearMask) >> 25)];
[components setMonth:(msdosDateTime & kMonthMask) >> 21];
[components setDay:(msdosDateTime & kDayMask) >> 16];
[components setHour:(msdosDateTime & kHourMask) >> 11];
[components setMinute:(msdosDateTime & kMinuteMask) >> 5];
[components setSecond:(msdosDateTime & kSecondMask) * 2];
NSDate *date = [NSDate dateWithTimeInterval:0 sinceDate:[gregorian dateFromComponents:components]];
#if !__has_feature(objc_arc)
[components release];
#endif
return date;
}
@end

View File

@@ -68,9 +68,9 @@
#include <stdlib.h>
#include <string.h>
#ifndef NOUNCRYPT
#define NOUNCRYPT
#endif
//#ifndef NOUNCRYPT
// #define NOUNCRYPT
//#endif
#include "zlib.h"
#include "unzip.h"
@@ -1514,6 +1514,7 @@ extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method,
pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
pfile_in_zip_read_info->pos_local_extrafield=0;
pfile_in_zip_read_info->raw=raw;
pfile_in_zip_read_info->byte_before_the_zipfile = 0;
if (pfile_in_zip_read_info->read_buffer==NULL)
{
@@ -1629,7 +1630,7 @@ extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method,
if (password != NULL)
{
int i;
s->pcrc_32_tab = get_crc_table();
s->pcrc_32_tab = (const unsigned long*)get_crc_table();
init_keys(password,s->keys,s->pcrc_32_tab);
if (ZSEEK64(s->z_filefunc, s->filestream,
s->pfile_in_zip_read->pos_in_zipfile +
@@ -1718,10 +1719,24 @@ extern int ZEXPORT unzReadCurrentFile (unzFile file, voidp buf, unsigned len)
pfile_in_zip_read_info->stream.avail_out = (uInt)len;
// NOTE:
// This bit of code seems to try to set the amount of space in the output buffer based on the
// value stored in the headers stored in the .zip file. However, if those values are incorrect
// it may result in a loss of data when uncompresssing that file. The compressed data is still
// legit and will deflate without knowing the uncompressed code so this tidbit is unnecessary and
// may cause issues for some .zip files.
//
// It's removed in here to fix those issues.
//
// See: https://github.com/samsoffes/ssziparchive/issues/16
//
/*
if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&
(!(pfile_in_zip_read_info->raw)))
pfile_in_zip_read_info->stream.avail_out =
(uInt)pfile_in_zip_read_info->rest_read_uncompressed;
*/
if ((len>pfile_in_zip_read_info->rest_read_compressed+
pfile_in_zip_read_info->stream.avail_in) &&

View File

@@ -1250,7 +1250,7 @@ extern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename,
unsigned char bufHead[RAND_HEAD_LEN];
unsigned int sizeHead;
zi->ci.encrypt = 1;
zi->ci.pcrc_32_tab = get_crc_table();
zi->ci.pcrc_32_tab = (const unsigned long*)get_crc_table();
/*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/
sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting);

Binary file not shown.

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildMachineOSBuild</key>
<string>13A476u</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>TestProject</string>
<key>CFBundleIdentifier</key>
<string>com.squaredtiki.TestProject</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>TestProject</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>DTCompiler</key>
<string>com.apple.compilers.llvm.clang.1_0</string>
<key>DTPlatformBuild</key>
<string>5A11314m</string>
<key>DTPlatformVersion</key>
<string>GM</string>
<key>DTSDKBuild</key>
<string>13A476n</string>
<key>DTSDKName</key>
<string>macosx10.9</string>
<key>DTXcode</key>
<string>0500</string>
<key>DTXcodeBuild</key>
<string>5A11314m</string>
<key>LSMinimumSystemVersion</key>
<string>10.9</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2013 TestBench. All rights reserved.</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>

View File

@@ -0,0 +1 @@
APPL????

View File

@@ -0,0 +1,29 @@
{\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;}
{\colortbl;\red255\green255\blue255;}
\paperw9840\paperh8400
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural
\f0\b\fs24 \cf0 Engineering:
\b0 \
Some people\
\
\b Human Interface Design:
\b0 \
Some other people\
\
\b Testing:
\b0 \
Hopefully not nobody\
\
\b Documentation:
\b0 \
Whoever\
\
\b With special thanks to:
\b0 \
Mom\
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Tests/Fixtures/Unicode.zip Normal file

Binary file not shown.

View File

@@ -1,308 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
B215FB32143AD3C7003AC546 /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B215FB31143AD3C7003AC546 /* SenTestingKit.framework */; };
B215FB63143AD514003AC546 /* SSZipArchiveTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B215FB61143AD514003AC546 /* SSZipArchiveTests.m */; };
B215FB65143AD527003AC546 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B215FB64143AD527003AC546 /* libz.dylib */; };
B215FB66143AD52D003AC546 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B215FB18143AD3C7003AC546 /* Foundation.framework */; };
B215FB67143AD56D003AC546 /* SSZipArchive.m in Sources */ = {isa = PBXBuildFile; fileRef = B215FB58143AD460003AC546 /* SSZipArchive.m */; };
B215FB68143AD576003AC546 /* ioapi.c in Sources */ = {isa = PBXBuildFile; fileRef = B215FB4F143AD460003AC546 /* ioapi.c */; };
B215FB69143AD576003AC546 /* mztools.c in Sources */ = {isa = PBXBuildFile; fileRef = B215FB51143AD460003AC546 /* mztools.c */; };
B215FB6A143AD576003AC546 /* unzip.c in Sources */ = {isa = PBXBuildFile; fileRef = B215FB53143AD460003AC546 /* unzip.c */; };
B215FB6B143AD576003AC546 /* zip.c in Sources */ = {isa = PBXBuildFile; fileRef = B215FB55143AD460003AC546 /* zip.c */; };
B215FB6D143AD6FF003AC546 /* TestArchive.zip in Resources */ = {isa = PBXBuildFile; fileRef = B215FB6C143AD6FF003AC546 /* TestArchive.zip */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
B215FB18143AD3C7003AC546 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
B215FB30143AD3C7003AC546 /* SSZipArchiveTests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SSZipArchiveTests.octest; sourceTree = BUILT_PRODUCTS_DIR; };
B215FB31143AD3C7003AC546 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; };
B215FB4E143AD460003AC546 /* crypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypt.h; sourceTree = "<group>"; };
B215FB4F143AD460003AC546 /* ioapi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioapi.c; sourceTree = "<group>"; };
B215FB50143AD460003AC546 /* ioapi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ioapi.h; sourceTree = "<group>"; };
B215FB51143AD460003AC546 /* mztools.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mztools.c; sourceTree = "<group>"; };
B215FB52143AD460003AC546 /* mztools.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mztools.h; sourceTree = "<group>"; };
B215FB53143AD460003AC546 /* unzip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = unzip.c; sourceTree = "<group>"; };
B215FB54143AD460003AC546 /* unzip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = unzip.h; sourceTree = "<group>"; };
B215FB55143AD460003AC546 /* zip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zip.c; sourceTree = "<group>"; };
B215FB56143AD460003AC546 /* zip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zip.h; sourceTree = "<group>"; };
B215FB57143AD460003AC546 /* SSZipArchive.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SSZipArchive.h; path = ../SSZipArchive.h; sourceTree = "<group>"; };
B215FB58143AD460003AC546 /* SSZipArchive.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SSZipArchive.m; path = ../SSZipArchive.m; sourceTree = "<group>"; };
B215FB5F143AD514003AC546 /* SSZipArchiveTests-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "SSZipArchiveTests-Info.plist"; sourceTree = "<group>"; };
B215FB60143AD514003AC546 /* SSZipArchiveTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SSZipArchiveTests.h; sourceTree = "<group>"; };
B215FB61143AD514003AC546 /* SSZipArchiveTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SSZipArchiveTests.m; sourceTree = "<group>"; };
B215FB64143AD527003AC546 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
B215FB6C143AD6FF003AC546 /* TestArchive.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = TestArchive.zip; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
B215FB2C143AD3C7003AC546 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
B215FB65143AD527003AC546 /* libz.dylib in Frameworks */,
B215FB66143AD52D003AC546 /* Foundation.framework in Frameworks */,
B215FB32143AD3C7003AC546 /* SenTestingKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
B215FB04143AD3C7003AC546 = {
isa = PBXGroup;
children = (
B215FB4B143AD449003AC546 /* SSZipArchive */,
B215FB5E143AD505003AC546 /* SSZipArchiveTests */,
B215FB12143AD3C7003AC546 /* Frameworks */,
B215FB10143AD3C7003AC546 /* Products */,
);
sourceTree = "<group>";
};
B215FB10143AD3C7003AC546 /* Products */ = {
isa = PBXGroup;
children = (
B215FB30143AD3C7003AC546 /* SSZipArchiveTests.octest */,
);
name = Products;
sourceTree = "<group>";
};
B215FB12143AD3C7003AC546 /* Frameworks */ = {
isa = PBXGroup;
children = (
B215FB64143AD527003AC546 /* libz.dylib */,
B215FB31143AD3C7003AC546 /* SenTestingKit.framework */,
B215FB18143AD3C7003AC546 /* Foundation.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
B215FB4B143AD449003AC546 /* SSZipArchive */ = {
isa = PBXGroup;
children = (
B215FB57143AD460003AC546 /* SSZipArchive.h */,
B215FB58143AD460003AC546 /* SSZipArchive.m */,
B215FB4D143AD460003AC546 /* minizip */,
);
name = SSZipArchive;
sourceTree = "<group>";
};
B215FB4D143AD460003AC546 /* minizip */ = {
isa = PBXGroup;
children = (
B215FB4E143AD460003AC546 /* crypt.h */,
B215FB4F143AD460003AC546 /* ioapi.c */,
B215FB50143AD460003AC546 /* ioapi.h */,
B215FB51143AD460003AC546 /* mztools.c */,
B215FB52143AD460003AC546 /* mztools.h */,
B215FB53143AD460003AC546 /* unzip.c */,
B215FB54143AD460003AC546 /* unzip.h */,
B215FB55143AD460003AC546 /* zip.c */,
B215FB56143AD460003AC546 /* zip.h */,
);
name = minizip;
path = ../minizip;
sourceTree = "<group>";
};
B215FB5E143AD505003AC546 /* SSZipArchiveTests */ = {
isa = PBXGroup;
children = (
B215FB60143AD514003AC546 /* SSZipArchiveTests.h */,
B215FB61143AD514003AC546 /* SSZipArchiveTests.m */,
B215FB5F143AD514003AC546 /* SSZipArchiveTests-Info.plist */,
B215FB6C143AD6FF003AC546 /* TestArchive.zip */,
);
name = SSZipArchiveTests;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
B215FB2F143AD3C7003AC546 /* SSZipArchiveTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = B215FB44143AD3C7003AC546 /* Build configuration list for PBXNativeTarget "SSZipArchiveTests" */;
buildPhases = (
B215FB2B143AD3C7003AC546 /* Sources */,
B215FB2C143AD3C7003AC546 /* Frameworks */,
B215FB2D143AD3C7003AC546 /* Resources */,
B215FB2E143AD3C7003AC546 /* ShellScript */,
);
buildRules = (
);
dependencies = (
);
name = SSZipArchiveTests;
productName = SSZipArchiveTests;
productReference = B215FB30143AD3C7003AC546 /* SSZipArchiveTests.octest */;
productType = "com.apple.product-type.bundle";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
B215FB06143AD3C7003AC546 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0420;
ORGANIZATIONNAME = "Sam Soffes";
};
buildConfigurationList = B215FB09143AD3C7003AC546 /* Build configuration list for PBXProject "SSZipArchive" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = B215FB04143AD3C7003AC546;
productRefGroup = B215FB10143AD3C7003AC546 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
B215FB2F143AD3C7003AC546 /* SSZipArchiveTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
B215FB2D143AD3C7003AC546 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B215FB6D143AD6FF003AC546 /* TestArchive.zip in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
B215FB2E143AD3C7003AC546 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
B215FB2B143AD3C7003AC546 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B215FB63143AD514003AC546 /* SSZipArchiveTests.m in Sources */,
B215FB67143AD56D003AC546 /* SSZipArchive.m in Sources */,
B215FB68143AD576003AC546 /* ioapi.c in Sources */,
B215FB69143AD576003AC546 /* mztools.c in Sources */,
B215FB6A143AD576003AC546 /* unzip.c in Sources */,
B215FB6B143AD576003AC546 /* zip.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
B215FB3F143AD3C7003AC546 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
COPY_PHASE_STRIP = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.7;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
};
name = Debug;
};
B215FB40143AD3C7003AC546 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.7;
SDKROOT = macosx;
};
name = Release;
};
B215FB45143AD3C7003AC546 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks";
INFOPLIST_FILE = "SSZipArchiveTests-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
RUN_CLANG_STATIC_ANALYZER = YES;
TEST_HOST = "$(BUNDLE_LOADER)";
WRAPPER_EXTENSION = octest;
};
name = Debug;
};
B215FB46143AD3C7003AC546 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks";
INFOPLIST_FILE = "SSZipArchiveTests-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
RUN_CLANG_STATIC_ANALYZER = YES;
TEST_HOST = "$(BUNDLE_LOADER)";
WRAPPER_EXTENSION = octest;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
B215FB09143AD3C7003AC546 /* Build configuration list for PBXProject "SSZipArchive" */ = {
isa = XCConfigurationList;
buildConfigurations = (
B215FB3F143AD3C7003AC546 /* Debug */,
B215FB40143AD3C7003AC546 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
B215FB44143AD3C7003AC546 /* Build configuration list for PBXNativeTarget "SSZipArchiveTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
B215FB45143AD3C7003AC546 /* Debug */,
B215FB46143AD3C7003AC546 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = B215FB06143AD3C7003AC546 /* Project object */;
}

View File

@@ -1,16 +0,0 @@
//
// SSZipArchiveTests.h
// SSZipArchiveTests
//
// Created by Sam Soffes on 10/3/11.
// Copyright (c) 2011 Sam Soffes. All rights reserved.
//
#import <SenTestingKit/SenTestingKit.h>
@interface SSZipArchiveTests : SenTestCase
- (void)testZipping;
- (void)testUnzipping;
@end

View File

@@ -3,58 +3,319 @@
// SSZipArchiveTests
//
// Created by Sam Soffes on 10/3/11.
// Copyright (c) 2011 Sam Soffes. All rights reserved.
// Copyright (c) 2011-2014 Sam Soffes. All rights reserved.
//
#import "SSZipArchiveTests.h"
#import "SSZipArchive.h"
#import <XCTest/XCTest.h>
#import <CommonCrypto/CommonDigest.h>
@interface SSZipArchiveTests ()
- (NSString *)_cachesPath;
@interface SSZipArchiveTests : XCTestCase <SSZipArchiveDelegate>
@end
@implementation SSZipArchiveTests
@implementation SSZipArchiveTests {
NSMutableArray *progressEvents;
}
- (void)setUp {
[super setUp];
progressEvents = [NSMutableArray array];
}
- (void)tearDown {
[super tearDown];
[[NSFileManager defaultManager] removeItemAtPath:[self _cachesPath:nil] error:nil];
}
- (void)testZipping {
NSString *outputPath = [self _cachesPath];
// use extracted files from [-testUnzipping]
NSString *inputPath = [self _cachesPath:@"Regular"];
NSArray *inputPaths = [NSArray arrayWithObjects:
[outputPath stringByAppendingPathComponent:@"Readme.markdown"],
[outputPath stringByAppendingPathComponent:@"LICENSE"],
[inputPath stringByAppendingPathComponent:@"Readme.markdown"],
[inputPath stringByAppendingPathComponent:@"LICENSE"],
nil];
NSString *outputPath = [self _cachesPath:@"Zipped"];
NSString *archivePath = [outputPath stringByAppendingPathComponent:@"CreatedArchive.zip"];
[SSZipArchive createZipFileAtPath:archivePath withFilesAtPaths:inputPaths];
// TODO: Make sure the files are actually unzipped. They are, but the test should be better.
STAssertTrue([[NSFileManager defaultManager] fileExistsAtPath:archivePath], @"Archive created");
XCTAssertTrue([[NSFileManager defaultManager] fileExistsAtPath:archivePath], @"Archive created");
}
- (void)testDirectoryZipping {
// use Unicode as folder (has a file in root and a file in subfolder)
NSString *inputPath = [self _cachesPath:@"Unicode"];
NSString *outputPath = [self _cachesPath:@"FolderZipped"];
NSString *archivePath = [outputPath stringByAppendingPathComponent:@"ArchiveWithFolders.zip"];
[SSZipArchive createZipFileAtPath:archivePath withContentsOfDirectory:inputPath];
XCTAssertTrue([[NSFileManager defaultManager] fileExistsAtPath:archivePath], @"Folder Archive created");
}
- (void)testUnzipping {
NSString *zipPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"TestArchive" ofType:@"zip"];
NSString *outputPath = [self _cachesPath];
[SSZipArchive unzipFileAtPath:zipPath toDestination:outputPath];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *outputPath = [self _cachesPath:@"Regular"];
[SSZipArchive unzipFileAtPath:zipPath toDestination:outputPath delegate:self];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *testPath = [outputPath stringByAppendingPathComponent:@"Readme.markdown"];
STAssertTrue([fileManager fileExistsAtPath:testPath], @"Readme unzipped");
XCTAssertTrue([fileManager fileExistsAtPath:testPath], @"Readme unzipped");
testPath = [outputPath stringByAppendingPathComponent:@"LICENSE"];
STAssertTrue([fileManager fileExistsAtPath:testPath], @"LICENSE unzipped");
// 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.
// zipPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"LargeArchive" ofType:@"zip"];
// outputPath = [[self _cachesPath] stringByAppendingPathComponent:@"large"];
XCTAssertTrue([fileManager fileExistsAtPath:testPath], @"LICENSE unzipped");
}
- (void)testUnzippingProgress {
NSString *zipPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"TestArchive" ofType:@"zip"];
NSString *outputPath = [self _cachesPath:@"Progress"];
[progressEvents removeAllObjects];
[SSZipArchive unzipFileAtPath:zipPath toDestination:outputPath delegate:self];
// 4 events: the first, then for each of the two files one, then the final event
XCTAssertTrue(4 == [progressEvents count], @"Expected 4 progress events");
XCTAssertTrue(0 == [[progressEvents objectAtIndex:0] intValue]);
XCTAssertTrue(619 == [[progressEvents objectAtIndex:1] intValue]);
XCTAssertTrue(1114 == [[progressEvents objectAtIndex:2] intValue]);
XCTAssertTrue(1436 == [[progressEvents objectAtIndex:3] intValue]);
}
- (void)testUnzippingWithPassword {
NSString *zipPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"TestPasswordArchive" ofType:@"zip"];
NSString *outputPath = [self _cachesPath:@"Password"];
NSError *error = nil;
[SSZipArchive unzipFileAtPath:zipPath toDestination:outputPath overwrite:YES password:@"passw0rd" error:&error delegate:self];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *testPath = [outputPath stringByAppendingPathComponent:@"Readme.markdown"];
XCTAssertTrue([fileManager fileExistsAtPath:testPath], @"Readme unzipped");
testPath = [outputPath stringByAppendingPathComponent:@"LICENSE"];
XCTAssertTrue([fileManager fileExistsAtPath:testPath], @"LICENSE unzipped");
}
- (void)testUnzippingTruncatedFileFix {
NSString* zipPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"IncorrectHeaders" ofType:@"zip"];
NSString* outputPath = [self _cachesPath:@"IncorrectHeaders"];
[SSZipArchive unzipFileAtPath:zipPath toDestination:outputPath delegate:self];
NSString* intendedReadmeTxtMD5 = @"31ac96301302eb388070c827447290b5";
NSString* filePath = [outputPath stringByAppendingPathComponent:@"IncorrectHeaders/Readme.txt"];
NSData* data = [NSData dataWithContentsOfFile:filePath];
NSString* actualReadmeTxtMD5 = [self _calculateMD5Digest:data];
XCTAssertTrue([actualReadmeTxtMD5 isEqualToString:intendedReadmeTxtMD5], @"Readme.txt MD5 digest should match original.");
}
- (void)testUnzippingWithSymlinkedFileInside {
NSString* zipPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"SymbolicLink" ofType:@"zip"];
NSString* outputPath = [self _cachesPath:@"SymbolicLink"];
[SSZipArchive unzipFileAtPath:zipPath toDestination:outputPath delegate:self];
NSString *testSymlinkFolder = [outputPath stringByAppendingPathComponent:@"SymbolicLink/GitHub.app"];
NSString *testSymlinkFile = [outputPath stringByAppendingPathComponent:@"SymbolicLink/Icon.icns"];
NSError *error = nil;
NSString *symlinkFolderPath = [[NSFileManager defaultManager] destinationOfSymbolicLinkAtPath:testSymlinkFolder error:&error];
bool symbolicLinkToFolderPersists = ((symlinkFolderPath != nil) && [symlinkFolderPath isEqualToString:@"/Applications/GitHub.app"]) && (error == nil);
error = nil;
NSString *symlinkFilePath = [[NSFileManager defaultManager] destinationOfSymbolicLinkAtPath:testSymlinkFile error:&error];
bool symbolicLinkToFilePersists = ((symlinkFilePath != nil) && [symlinkFilePath isEqualToString:@"/Applications/GitHub.app/Contents/Resources/AppIcon.icns"]) && (error == nil);
XCTAssertTrue(symbolicLinkToFilePersists && symbolicLinkToFolderPersists, @"Symbolic links should persist from the original archive to the outputted files.");
}
- (void)testUnzippingWithRelativeSymlink {
NSString *resourceName = @"RelativeSymbolicLink";
NSString* zipPath = [[NSBundle bundleForClass:[self class]] pathForResource:resourceName ofType:@"zip"];
NSString* outputPath = [self _cachesPath:resourceName];
[SSZipArchive unzipFileAtPath:zipPath toDestination:outputPath delegate:self];
// Determine where the symlinks are
NSString *subfolderName = @"symlinks";
NSString *testBasePath = [NSString pathWithComponents:@[outputPath]];
NSString *testSymlinkFolder = [NSString pathWithComponents:@[testBasePath, subfolderName, @"folderSymlink"]];
NSString *testSymlinkFile = [NSString pathWithComponents:@[testBasePath, subfolderName, @"fileSymlink"]];
// Determine where the files they link to are
NSString *parentDir = @"../";
NSString *testSymlinkFolderTarget = [NSString pathWithComponents:@[parentDir, @"symlinkedFolder"]];
NSString *testSymlinkFileTarget = [NSString pathWithComponents:@[parentDir, @"symlinkedFile"]];
NSError *error = nil;
NSString *symlinkFolderPath = [[NSFileManager defaultManager] destinationOfSymbolicLinkAtPath:testSymlinkFolder error:&error];
bool symbolicLinkToFolderPersists = ((symlinkFolderPath != nil) && [symlinkFolderPath isEqualToString:testSymlinkFolderTarget]) && (error == nil);
error = nil;
NSString *symlinkFilePath = [[NSFileManager defaultManager] destinationOfSymbolicLinkAtPath:testSymlinkFile error:&error];
bool symbolicLinkToFilePersists = ((symlinkFilePath != nil) && [symlinkFilePath isEqualToString:testSymlinkFileTarget]) && (error == nil);
XCTAssertTrue(symbolicLinkToFilePersists && symbolicLinkToFolderPersists, @"Relative symbolic links should persist from the original archive to the outputted files (and also remain relative).");
}
- (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"]];
XCTAssertTrue(unicodeFilenameWasExtracted, @"Files with filenames in unicode should be extracted properly.");
XCTAssertTrue(unicodeFolderWasExtracted, @"Folders with names in unicode should be extracted propertly.");
}
- (void)testZippingAndUnzippingForDate {
NSString *inputPath = [self _cachesPath:@"Regular"];
NSArray *inputPaths = [NSArray arrayWithObjects:
[inputPath stringByAppendingPathComponent:@"Readme.markdown"],
nil];
NSDictionary *originalFileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:[inputPath stringByAppendingPathComponent:@"Readme.markdown"] error:nil];
NSString *outputPath = [self _cachesPath:@"ZippedDate"];
NSString *archivePath = [outputPath stringByAppendingPathComponent:@"CreatedArchive.zip"];
[SSZipArchive createZipFileAtPath:archivePath withFilesAtPaths:inputPaths];
[SSZipArchive unzipFileAtPath:archivePath toDestination:outputPath delegate:self];
NSDictionary *createdFileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:[outputPath stringByAppendingPathComponent:@"Readme.markdown"] error:nil];
XCTAssertEqualObjects(originalFileAttributes[NSFileCreationDate], createdFileAttributes[@"NSFileCreationDate"], @"Orginal file creationDate should match created one");
}
- (void)testZippingAndUnzippingForPermissions {
// File we're going to test permissions on before and after zipping
NSString *targetFile = @"/Contents/MacOS/TestProject";
/********** Zipping ********/
// The .app file we're going to zip up
NSString *inputFile = [[NSBundle mainBundle] pathForResource:@"PermissionsTestApp" ofType:@"app"];
// The path to the target file in the app before zipping
NSString *targetFilePreZipPath = [inputFile stringByAppendingPathComponent:targetFile];
// Atribtues for the target file before zipping
NSDictionary *preZipAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:targetFilePreZipPath error:nil];
// Directory to output our created zip file
NSString *outputDir = [self _cachesPath:@"PermissionsTest"];
// The path to where the archive shall be created
NSString *archivePath = [outputDir stringByAppendingPathComponent:@"TestAppArchive.zip"];
// Create the zip file using the contents of the .app file as the input
[SSZipArchive createZipFileAtPath:archivePath withContentsOfDirectory:inputFile];
/********** Un-zipping *******/
// Using this newly created zip file, unzip it
[SSZipArchive unzipFileAtPath:archivePath toDestination:outputDir];
// Get the path to the target file after unzipping
NSString *targetFilePath = [outputDir stringByAppendingPathComponent:@"/Contents/MacOS/TestProject"];
// Get the file attributes of the target file following the unzipping
NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:targetFilePath error:nil];
// Compare the value of the permissions attribute to assert equality
XCTAssertEqual(fileAttributes[NSFilePosixPermissions], preZipAttributes[NSFilePosixPermissions], @"File permissions should be retained during compression and de-compression");
}
// 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.
//
//- (void)testUnzippingLargeFiles {
// NSString *zipPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"LargeArchive" ofType:@"zip"];
// NSString *outputPath = [self _cachesPath:@"Large"];
//
// [SSZipArchive unzipFileAtPath:zipPath toDestination:outputPath];
//}
#pragma mark - SSZipArchiveDelegate
- (void)zipArchiveWillUnzipArchiveAtPath:(NSString *)path zipInfo:(unz_global_info)zipInfo {
NSLog(@"*** zipArchiveWillUnzipArchiveAtPath: `%@` zipInfo:", path);
}
- (void)zipArchiveDidUnzipArchiveAtPath:(NSString *)path zipInfo:(unz_global_info)zipInfo unzippedPath:(NSString *)unzippedPath {
NSLog(@"*** zipArchiveDidUnzipArchiveAtPath: `%@` zipInfo: unzippedPath: `%@`", path, unzippedPath);
}
- (void)zipArchiveWillUnzipFileAtIndex:(NSInteger)fileIndex totalFiles:(NSInteger)totalFiles archivePath:(NSString *)archivePath fileInfo:(unz_file_info)fileInfo {
NSLog(@"*** zipArchiveWillUnzipFileAtIndex: `%d` totalFiles: `%d` archivePath: `%@` fileInfo:", (int)fileIndex, (int)totalFiles, archivePath);
}
- (void)zipArchiveDidUnzipFileAtIndex:(NSInteger)fileIndex totalFiles:(NSInteger)totalFiles archivePath:(NSString *)archivePath fileInfo:(unz_file_info)fileInfo {
NSLog(@"*** zipArchiveDidUnzipFileAtIndex: `%d` totalFiles: `%d` archivePath: `%@` fileInfo:", (int)fileIndex, (int)totalFiles, archivePath);
}
- (void)zipArchiveProgressEvent:(NSInteger)loaded total:(NSInteger)total {
NSLog(@"*** zipArchiveProgressEvent: loaded: `%d` total: `%d`", (int)loaded, (int)total);
[progressEvents addObject:[[NSNumber alloc] initWithInteger:loaded]];
}
#pragma mark - Private
- (NSString *)_cachesPath {
return [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]
stringByAppendingPathComponent:@"com.samsoffes.ssziparchive.tests"];
- (NSString *)_cachesPath:(NSString *)directory {
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]
stringByAppendingPathComponent:@"com.samsoffes.ssziparchive.tests"];
if (directory) {
path = [path stringByAppendingPathComponent:directory];
}
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:path]) {
[fileManager createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
}
return path;
}
// Taken from https://github.com/samsoffes/sstoolkit/blob/master/SSToolkit/NSData+SSToolkitAdditions.m
- (NSString *)_calculateMD5Digest:(NSData *)data {
unsigned char digest[CC_MD5_DIGEST_LENGTH], i;
CC_MD5(data.bytes, (unsigned int)data.length, digest);
NSMutableString *ms = [NSMutableString string];
for (i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
[ms appendFormat: @"%02x", (int)(digest[i])];
}
return [ms copy];
}
@end

Binary file not shown.