From 45681288fe58ac2e47127b95235b3dbe7d80df5f Mon Sep 17 00:00:00 2001 From: Geoffrey Goh Date: Wed, 2 Dec 2015 16:39:46 -0800 Subject: [PATCH] asset-update --- CodePush.h | 14 +- CodePush.m | 6 +- CodePush.xcodeproj/project.pbxproj | 130 +- CodePushDownloadHandler.m | 24 +- CodePushPackage.m | 243 ++- .../CodePushDemoApp/android/app/build.gradle | 6 +- .../CodePushDemoApp/android/app/react.gradle | 75 + .../codepushdemoapp/MainActivity.java | 6 +- Examples/CodePushDemoApp/crossplatformdemo.js | 12 +- .../CodePushDemoApp.xcodeproj/project.pbxproj | 94 +- .../contents.xcworkspacedata | 0 .../xcschemes/CodePushDemoApp.xcscheme | 0 .../iOS/{ => CodePushDemoApp}/AppDelegate.h | 0 .../iOS/{ => CodePushDemoApp}/AppDelegate.m | 2 + .../Base.lproj/LaunchScreen.xib | 0 .../AppIcon.appiconset/Contents.json | 0 .../iOS/{ => CodePushDemoApp}/Info.plist | 2 +- .../iOS/{ => CodePushDemoApp}/main.m | 0 .../images/laptop_phone_howitworks.png | Bin 0 -> 29922 bytes Examples/CodePushDemoApp/package.json | 2 +- .../assets/images/laptop_phone_howitworks.png | Bin 0 -> 31155 bytes SSZipArchive/Common.h | 81 + SSZipArchive/SSZipArchive.h | 76 + SSZipArchive/SSZipArchive.m | 691 ++++++ SSZipArchive/aes/aes.h | 198 ++ SSZipArchive/aes/aes_via_ace.h | 541 +++++ SSZipArchive/aes/aescrypt.c | 294 +++ SSZipArchive/aes/aeskey.c | 548 +++++ SSZipArchive/aes/aesopt.h | 739 +++++++ SSZipArchive/aes/aestab.c | 391 ++++ SSZipArchive/aes/aestab.h | 173 ++ SSZipArchive/aes/brg_endian.h | 126 ++ SSZipArchive/aes/brg_types.h | 219 ++ SSZipArchive/aes/entropy.c | 54 + SSZipArchive/aes/entropy.h | 16 + SSZipArchive/aes/fileenc.c | 144 ++ SSZipArchive/aes/fileenc.h | 121 ++ SSZipArchive/aes/hmac.c | 145 ++ SSZipArchive/aes/hmac.h | 103 + SSZipArchive/aes/prng.c | 155 ++ SSZipArchive/aes/prng.h | 82 + SSZipArchive/aes/pwd2key.c | 193 ++ SSZipArchive/aes/pwd2key.h | 57 + SSZipArchive/aes/sha1.c | 258 +++ SSZipArchive/aes/sha1.h | 73 + SSZipArchive/minizip/crypt.h | 130 ++ SSZipArchive/minizip/ioapi.c | 369 ++++ SSZipArchive/minizip/ioapi.h | 175 ++ SSZipArchive/minizip/mztools.c | 284 +++ SSZipArchive/minizip/mztools.h | 31 + SSZipArchive/minizip/unzip.c | 1839 ++++++++++++++++ SSZipArchive/minizip/unzip.h | 248 +++ SSZipArchive/minizip/zip.c | 1910 +++++++++++++++++ SSZipArchive/minizip/zip.h | 202 ++ package.json | 2 +- 55 files changed, 11206 insertions(+), 78 deletions(-) create mode 100644 Examples/CodePushDemoApp/android/app/react.gradle rename Examples/CodePushDemoApp/{ => iOS}/CodePushDemoApp.xcodeproj/project.pbxproj (90%) rename Examples/CodePushDemoApp/{ => iOS}/CodePushDemoApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata (100%) rename Examples/CodePushDemoApp/{ => iOS}/CodePushDemoApp.xcodeproj/xcshareddata/xcschemes/CodePushDemoApp.xcscheme (100%) rename Examples/CodePushDemoApp/iOS/{ => CodePushDemoApp}/AppDelegate.h (100%) rename Examples/CodePushDemoApp/iOS/{ => CodePushDemoApp}/AppDelegate.m (97%) rename Examples/CodePushDemoApp/iOS/{ => CodePushDemoApp}/Base.lproj/LaunchScreen.xib (100%) rename Examples/CodePushDemoApp/iOS/{ => CodePushDemoApp}/Images.xcassets/AppIcon.appiconset/Contents.json (100%) rename Examples/CodePushDemoApp/iOS/{ => CodePushDemoApp}/Info.plist (96%) rename Examples/CodePushDemoApp/iOS/{ => CodePushDemoApp}/main.m (100%) create mode 100644 Examples/CodePushDemoApp/images/laptop_phone_howitworks.png create mode 100644 Examples/CodePushDemoApp/release/assets/images/laptop_phone_howitworks.png create mode 100755 SSZipArchive/Common.h create mode 100755 SSZipArchive/SSZipArchive.h create mode 100755 SSZipArchive/SSZipArchive.m create mode 100755 SSZipArchive/aes/aes.h create mode 100755 SSZipArchive/aes/aes_via_ace.h create mode 100755 SSZipArchive/aes/aescrypt.c create mode 100755 SSZipArchive/aes/aeskey.c create mode 100755 SSZipArchive/aes/aesopt.h create mode 100755 SSZipArchive/aes/aestab.c create mode 100755 SSZipArchive/aes/aestab.h create mode 100755 SSZipArchive/aes/brg_endian.h create mode 100755 SSZipArchive/aes/brg_types.h create mode 100755 SSZipArchive/aes/entropy.c create mode 100755 SSZipArchive/aes/entropy.h create mode 100755 SSZipArchive/aes/fileenc.c create mode 100755 SSZipArchive/aes/fileenc.h create mode 100755 SSZipArchive/aes/hmac.c create mode 100755 SSZipArchive/aes/hmac.h create mode 100755 SSZipArchive/aes/prng.c create mode 100755 SSZipArchive/aes/prng.h create mode 100755 SSZipArchive/aes/pwd2key.c create mode 100755 SSZipArchive/aes/pwd2key.h create mode 100755 SSZipArchive/aes/sha1.c create mode 100755 SSZipArchive/aes/sha1.h create mode 100755 SSZipArchive/minizip/crypt.h create mode 100755 SSZipArchive/minizip/ioapi.c create mode 100755 SSZipArchive/minizip/ioapi.h create mode 100755 SSZipArchive/minizip/mztools.c create mode 100755 SSZipArchive/minizip/mztools.h create mode 100755 SSZipArchive/minizip/unzip.c create mode 100755 SSZipArchive/minizip/unzip.h create mode 100755 SSZipArchive/minizip/zip.c create mode 100755 SSZipArchive/minizip/zip.h diff --git a/CodePush.h b/CodePush.h index f25f0c2..ec3b880 100644 --- a/CodePush.h +++ b/CodePush.h @@ -39,15 +39,15 @@ @interface CodePushDownloadHandler : NSObject @property (strong) NSOutputStream *outputFileStream; -@property long expectedContentLength; -@property long receivedContentLength; -@property (copy) void (^progressCallback)(long, long); -@property (copy) void (^doneCallback)(); +@property long long expectedContentLength; +@property long long receivedContentLength; +@property (copy) void (^progressCallback)(long long, long long); +@property (copy) void (^doneCallback)(BOOL); @property (copy) void (^failCallback)(NSError *err); - (id)init:(NSString *)downloadFilePath -progressCallback:(void (^)(long, long))progressCallback -doneCallback:(void (^)())doneCallback +progressCallback:(void (^)(long long, long long))progressCallback +doneCallback:(void (^)(BOOL))doneCallback failCallback:(void (^)(NSError *err))failCallback; - (void)download:(NSString*)url; @@ -71,7 +71,7 @@ failCallback:(void (^)(NSError *err))failCallback; + (void)downloadPackage:(NSDictionary *)updatePackage - progressCallback:(void (^)(long, long))progressCallback + progressCallback:(void (^)(long long, long long))progressCallback doneCallback:(void (^)())doneCallback failCallback:(void (^)(NSError *err))failCallback; diff --git a/CodePush.m b/CodePush.m index 5e71dfe..6a6c958 100644 --- a/CodePush.m +++ b/CodePush.m @@ -259,13 +259,13 @@ RCT_EXPORT_METHOD(downloadUpdate:(NSDictionary*)updatePackage { [CodePushPackage downloadPackage:updatePackage // The download is progressing forward - progressCallback:^(long expectedContentLength, long receivedContentLength) { + progressCallback:^(long long expectedContentLength, long long receivedContentLength) { // Notify the script-side about the progress [self.bridge.eventDispatcher sendDeviceEventWithName:@"CodePushDownloadProgress" body:@{ - @"totalBytes":[NSNumber numberWithLong:expectedContentLength], - @"receivedBytes":[NSNumber numberWithLong:receivedContentLength] + @"totalBytes":[NSNumber numberWithLongLong:expectedContentLength], + @"receivedBytes":[NSNumber numberWithLongLong:receivedContentLength] }]; } // The download completed diff --git a/CodePush.xcodeproj/project.pbxproj b/CodePush.xcodeproj/project.pbxproj index a95de0a..6961441 100644 --- a/CodePush.xcodeproj/project.pbxproj +++ b/CodePush.xcodeproj/project.pbxproj @@ -9,6 +9,20 @@ /* Begin PBXBuildFile section */ 13BE3DEE1AC21097009241FE /* CodePush.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BE3DED1AC21097009241FE /* CodePush.m */; }; 1B23B9141BF9267B000BB2F0 /* RCTConvert+CodePushInstallMode.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B23B9131BF9267B000BB2F0 /* RCTConvert+CodePushInstallMode.m */; }; + 54A0026C1C0E2880004C3CEC /* aescrypt.c in Sources */ = {isa = PBXBuildFile; fileRef = 54A0024C1C0E2880004C3CEC /* aescrypt.c */; }; + 54A0026D1C0E2880004C3CEC /* aeskey.c in Sources */ = {isa = PBXBuildFile; fileRef = 54A0024D1C0E2880004C3CEC /* aeskey.c */; }; + 54A0026E1C0E2880004C3CEC /* aestab.c in Sources */ = {isa = PBXBuildFile; fileRef = 54A0024F1C0E2880004C3CEC /* aestab.c */; }; + 54A0026F1C0E2880004C3CEC /* entropy.c in Sources */ = {isa = PBXBuildFile; fileRef = 54A002531C0E2880004C3CEC /* entropy.c */; }; + 54A002701C0E2880004C3CEC /* fileenc.c in Sources */ = {isa = PBXBuildFile; fileRef = 54A002551C0E2880004C3CEC /* fileenc.c */; }; + 54A002711C0E2880004C3CEC /* hmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 54A002571C0E2880004C3CEC /* hmac.c */; }; + 54A002721C0E2880004C3CEC /* prng.c in Sources */ = {isa = PBXBuildFile; fileRef = 54A002591C0E2880004C3CEC /* prng.c */; }; + 54A002731C0E2880004C3CEC /* pwd2key.c in Sources */ = {isa = PBXBuildFile; fileRef = 54A0025B1C0E2880004C3CEC /* pwd2key.c */; }; + 54A002741C0E2880004C3CEC /* sha1.c in Sources */ = {isa = PBXBuildFile; fileRef = 54A0025D1C0E2880004C3CEC /* sha1.c */; }; + 54A002751C0E2880004C3CEC /* ioapi.c in Sources */ = {isa = PBXBuildFile; fileRef = 54A002621C0E2880004C3CEC /* ioapi.c */; }; + 54A002761C0E2880004C3CEC /* mztools.c in Sources */ = {isa = PBXBuildFile; fileRef = 54A002641C0E2880004C3CEC /* mztools.c */; }; + 54A002771C0E2880004C3CEC /* unzip.c in Sources */ = {isa = PBXBuildFile; fileRef = 54A002661C0E2880004C3CEC /* unzip.c */; }; + 54A002781C0E2880004C3CEC /* zip.c in Sources */ = {isa = PBXBuildFile; fileRef = 54A002681C0E2880004C3CEC /* zip.c */; }; + 54A002791C0E2880004C3CEC /* SSZipArchive.m in Sources */ = {isa = PBXBuildFile; fileRef = 54A0026B1C0E2880004C3CEC /* SSZipArchive.m */; }; 54FFEDE01BF550630061DD23 /* CodePushDownloadHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 54FFEDDF1BF550630061DD23 /* CodePushDownloadHandler.m */; }; 810D4E6D1B96935000B397E9 /* CodePushPackage.m in Sources */ = {isa = PBXBuildFile; fileRef = 810D4E6C1B96935000B397E9 /* CodePushPackage.m */; }; 81D51F3A1B6181C2000DA084 /* CodePushConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 81D51F391B6181C2000DA084 /* CodePushConfig.m */; }; @@ -31,6 +45,39 @@ 13BE3DEC1AC21097009241FE /* CodePush.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodePush.h; sourceTree = ""; }; 13BE3DED1AC21097009241FE /* CodePush.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CodePush.m; sourceTree = ""; }; 1B23B9131BF9267B000BB2F0 /* RCTConvert+CodePushInstallMode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTConvert+CodePushInstallMode.m"; sourceTree = ""; }; + 54A0024A1C0E2880004C3CEC /* aes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aes.h; sourceTree = ""; }; + 54A0024B1C0E2880004C3CEC /* aes_via_ace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aes_via_ace.h; sourceTree = ""; }; + 54A0024C1C0E2880004C3CEC /* aescrypt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aescrypt.c; sourceTree = ""; }; + 54A0024D1C0E2880004C3CEC /* aeskey.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aeskey.c; sourceTree = ""; }; + 54A0024E1C0E2880004C3CEC /* aesopt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aesopt.h; sourceTree = ""; }; + 54A0024F1C0E2880004C3CEC /* aestab.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aestab.c; sourceTree = ""; }; + 54A002501C0E2880004C3CEC /* aestab.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aestab.h; sourceTree = ""; }; + 54A002511C0E2880004C3CEC /* brg_endian.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = brg_endian.h; sourceTree = ""; }; + 54A002521C0E2880004C3CEC /* brg_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = brg_types.h; sourceTree = ""; }; + 54A002531C0E2880004C3CEC /* entropy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = entropy.c; sourceTree = ""; }; + 54A002541C0E2880004C3CEC /* entropy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = entropy.h; sourceTree = ""; }; + 54A002551C0E2880004C3CEC /* fileenc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fileenc.c; sourceTree = ""; }; + 54A002561C0E2880004C3CEC /* fileenc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fileenc.h; sourceTree = ""; }; + 54A002571C0E2880004C3CEC /* hmac.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hmac.c; sourceTree = ""; }; + 54A002581C0E2880004C3CEC /* hmac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hmac.h; sourceTree = ""; }; + 54A002591C0E2880004C3CEC /* prng.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = prng.c; sourceTree = ""; }; + 54A0025A1C0E2880004C3CEC /* prng.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = prng.h; sourceTree = ""; }; + 54A0025B1C0E2880004C3CEC /* pwd2key.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pwd2key.c; sourceTree = ""; }; + 54A0025C1C0E2880004C3CEC /* pwd2key.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pwd2key.h; sourceTree = ""; }; + 54A0025D1C0E2880004C3CEC /* sha1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sha1.c; sourceTree = ""; }; + 54A0025E1C0E2880004C3CEC /* sha1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sha1.h; sourceTree = ""; }; + 54A0025F1C0E2880004C3CEC /* Common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Common.h; sourceTree = ""; }; + 54A002611C0E2880004C3CEC /* crypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypt.h; sourceTree = ""; }; + 54A002621C0E2880004C3CEC /* ioapi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioapi.c; sourceTree = ""; }; + 54A002631C0E2880004C3CEC /* ioapi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ioapi.h; sourceTree = ""; }; + 54A002641C0E2880004C3CEC /* mztools.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mztools.c; sourceTree = ""; }; + 54A002651C0E2880004C3CEC /* mztools.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mztools.h; sourceTree = ""; }; + 54A002661C0E2880004C3CEC /* unzip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = unzip.c; sourceTree = ""; }; + 54A002671C0E2880004C3CEC /* unzip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = unzip.h; sourceTree = ""; }; + 54A002681C0E2880004C3CEC /* zip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zip.c; sourceTree = ""; }; + 54A002691C0E2880004C3CEC /* zip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zip.h; sourceTree = ""; }; + 54A0026A1C0E2880004C3CEC /* SSZipArchive.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SSZipArchive.h; sourceTree = ""; }; + 54A0026B1C0E2880004C3CEC /* SSZipArchive.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SSZipArchive.m; sourceTree = ""; }; 54FFEDDF1BF550630061DD23 /* CodePushDownloadHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CodePushDownloadHandler.m; sourceTree = ""; }; 810D4E6C1B96935000B397E9 /* CodePushPackage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CodePushPackage.m; sourceTree = ""; }; 81D51F391B6181C2000DA084 /* CodePushConfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CodePushConfig.m; sourceTree = ""; }; @@ -55,9 +102,66 @@ name = Products; sourceTree = ""; }; + 54A002481C0E2880004C3CEC /* SSZipArchive */ = { + isa = PBXGroup; + children = ( + 54A002491C0E2880004C3CEC /* aes */, + 54A0025F1C0E2880004C3CEC /* Common.h */, + 54A002601C0E2880004C3CEC /* minizip */, + 54A0026A1C0E2880004C3CEC /* SSZipArchive.h */, + 54A0026B1C0E2880004C3CEC /* SSZipArchive.m */, + ); + path = SSZipArchive; + sourceTree = ""; + }; + 54A002491C0E2880004C3CEC /* aes */ = { + isa = PBXGroup; + children = ( + 54A0024A1C0E2880004C3CEC /* aes.h */, + 54A0024B1C0E2880004C3CEC /* aes_via_ace.h */, + 54A0024C1C0E2880004C3CEC /* aescrypt.c */, + 54A0024D1C0E2880004C3CEC /* aeskey.c */, + 54A0024E1C0E2880004C3CEC /* aesopt.h */, + 54A0024F1C0E2880004C3CEC /* aestab.c */, + 54A002501C0E2880004C3CEC /* aestab.h */, + 54A002511C0E2880004C3CEC /* brg_endian.h */, + 54A002521C0E2880004C3CEC /* brg_types.h */, + 54A002531C0E2880004C3CEC /* entropy.c */, + 54A002541C0E2880004C3CEC /* entropy.h */, + 54A002551C0E2880004C3CEC /* fileenc.c */, + 54A002561C0E2880004C3CEC /* fileenc.h */, + 54A002571C0E2880004C3CEC /* hmac.c */, + 54A002581C0E2880004C3CEC /* hmac.h */, + 54A002591C0E2880004C3CEC /* prng.c */, + 54A0025A1C0E2880004C3CEC /* prng.h */, + 54A0025B1C0E2880004C3CEC /* pwd2key.c */, + 54A0025C1C0E2880004C3CEC /* pwd2key.h */, + 54A0025D1C0E2880004C3CEC /* sha1.c */, + 54A0025E1C0E2880004C3CEC /* sha1.h */, + ); + path = aes; + sourceTree = ""; + }; + 54A002601C0E2880004C3CEC /* minizip */ = { + isa = PBXGroup; + children = ( + 54A002611C0E2880004C3CEC /* crypt.h */, + 54A002621C0E2880004C3CEC /* ioapi.c */, + 54A002631C0E2880004C3CEC /* ioapi.h */, + 54A002641C0E2880004C3CEC /* mztools.c */, + 54A002651C0E2880004C3CEC /* mztools.h */, + 54A002661C0E2880004C3CEC /* unzip.c */, + 54A002671C0E2880004C3CEC /* unzip.h */, + 54A002681C0E2880004C3CEC /* zip.c */, + 54A002691C0E2880004C3CEC /* zip.h */, + ); + path = minizip; + sourceTree = ""; + }; 58B511D21A9E6C8500147676 = { isa = PBXGroup; children = ( + 54A002481C0E2880004C3CEC /* SSZipArchive */, 1B23B9131BF9267B000BB2F0 /* RCTConvert+CodePushInstallMode.m */, 54FFEDDF1BF550630061DD23 /* CodePushDownloadHandler.m */, 810D4E6C1B96935000B397E9 /* CodePushPackage.m */, @@ -95,7 +199,7 @@ isa = PBXProject; attributes = { LastUpgradeCheck = 0610; - ORGANIZATIONNAME = Facebook; + ORGANIZATIONNAME = Microsoft; TargetAttributes = { 58B511DA1A9E6C8500147676 = { CreatedOnToolsVersion = 6.1.1; @@ -124,10 +228,24 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 54A0026D1C0E2880004C3CEC /* aeskey.c in Sources */, + 54A0026E1C0E2880004C3CEC /* aestab.c in Sources */, + 54A002761C0E2880004C3CEC /* mztools.c in Sources */, + 54A002781C0E2880004C3CEC /* zip.c in Sources */, + 54A002791C0E2880004C3CEC /* SSZipArchive.m in Sources */, 1B23B9141BF9267B000BB2F0 /* RCTConvert+CodePushInstallMode.m in Sources */, 81D51F3A1B6181C2000DA084 /* CodePushConfig.m in Sources */, + 54A002741C0E2880004C3CEC /* sha1.c in Sources */, 54FFEDE01BF550630061DD23 /* CodePushDownloadHandler.m in Sources */, + 54A002711C0E2880004C3CEC /* hmac.c in Sources */, + 54A002721C0E2880004C3CEC /* prng.c in Sources */, + 54A002731C0E2880004C3CEC /* pwd2key.c in Sources */, + 54A002751C0E2880004C3CEC /* ioapi.c in Sources */, + 54A002771C0E2880004C3CEC /* unzip.c in Sources */, + 54A0026F1C0E2880004C3CEC /* entropy.c in Sources */, 13BE3DEE1AC21097009241FE /* CodePush.m in Sources */, + 54A0026C1C0E2880004C3CEC /* aescrypt.c in Sources */, + 54A002701C0E2880004C3CEC /* fileenc.c in Sources */, 810D4E6D1B96935000B397E9 /* CodePushPackage.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -220,7 +338,10 @@ "$(SRCROOT)/../react-native/React/**", ); LIBRARY_SEARCH_PATHS = "$(inherited)"; - OTHER_LDFLAGS = "-ObjC"; + OTHER_LDFLAGS = ( + "-ObjC", + "-lz", + ); PRODUCT_NAME = CodePush; SKIP_INSTALL = YES; }; @@ -237,7 +358,10 @@ "$(SRCROOT)/../react-native/React/**", ); LIBRARY_SEARCH_PATHS = "$(inherited)"; - OTHER_LDFLAGS = "-ObjC"; + OTHER_LDFLAGS = ( + "-ObjC", + "-lz", + ); PRODUCT_NAME = CodePush; SKIP_INSTALL = YES; }; diff --git a/CodePushDownloadHandler.m b/CodePushDownloadHandler.m index 31725d5..fb6dd69 100644 --- a/CodePushDownloadHandler.m +++ b/CodePushDownloadHandler.m @@ -1,10 +1,13 @@ #import "CodePush.h" -@implementation CodePushDownloadHandler +@implementation CodePushDownloadHandler { + // Header chars used to determine if the file is a zip. + char header[4]; +} - (id)init:(NSString *)downloadFilePath -progressCallback:(void (^)(long, long))progressCallback -doneCallback:(void (^)())doneCallback +progressCallback:(void (^)(long long, long long))progressCallback +doneCallback:(void (^)(BOOL))doneCallback failCallback:(void (^)(NSError *err))failCallback { self.outputFileStream = [NSOutputStream outputStreamToFileAtPath:downloadFilePath append:NO]; @@ -42,6 +45,18 @@ failCallback:(void (^)(NSError *err))failCallback { } -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { + if (self.receivedContentLength < 4) { + const char *bytes = [data bytes]; + for (int i=0; i<[data length]; i++) { + int headerOffset = (int)self.receivedContentLength + i; + if (headerOffset >= 4) { + break; + } + + header[headerOffset] = bytes[i]; + } + } + self.receivedContentLength = self.receivedContentLength + [data length]; NSInteger bytesLeft = [data length]; @@ -79,7 +94,8 @@ failCallback:(void (^)(NSError *err))failCallback { assert(self.receivedContentLength == self.expectedContentLength); [self.outputFileStream close]; - self.doneCallback(); + BOOL isZip = header[0] == 'P' && header[1] == 'K' && header[2] == 3 && header[3] == 4; + self.doneCallback(isZip); } @end \ No newline at end of file diff --git a/CodePushPackage.m b/CodePushPackage.m index 928f502..56a8789 100644 --- a/CodePushPackage.m +++ b/CodePushPackage.m @@ -1,15 +1,32 @@ #import "CodePush.h" +#import "SSZipArchive.h" @implementation CodePushPackage +NSString * const CodePushErrorDomain = @"CodePushError"; +const int CodePushErrorCode = -1; +NSString * const DiffManifestFileName = @"hotcodepush.json"; +NSString * const DownloadFileName = @"download.zip"; +NSString * const RelativeBundlePathKey = @"bundlePath"; NSString * const StatusFile = @"codepush.json"; NSString * const UpdateBundleFileName = @"app.jsbundle"; +NSString * const UnzippedFolderName = @"unzipped"; + (NSString *)getCodePushPath { return [[CodePush getDocumentsDirectory] stringByAppendingPathComponent:@"CodePush"]; } ++ (NSString *)getDownloadFilePath +{ + return [[self getCodePushPath] stringByAppendingPathComponent:DownloadFileName]; +} + ++ (NSString *)getUnzippedFolderPath +{ + return [[self getCodePushPath] stringByAppendingPathComponent:UnzippedFolderName]; +} + + (NSString *)getStatusFilePath { return [[self getCodePushPath] stringByAppendingPathComponent:StatusFile]; @@ -81,7 +98,18 @@ NSString * const UpdateBundleFileName = @"app.jsbundle"; return NULL; } - return [packageFolder stringByAppendingPathComponent:UpdateBundleFileName]; + NSDictionary *currentPackage = [self getCurrentPackage:error]; + + if(*error) { + return NULL; + } + + NSString *relativeBundlePath = [currentPackage objectForKey:RelativeBundlePathKey]; + if (relativeBundlePath) { + return [packageFolder stringByAppendingPathComponent:relativeBundlePath]; + } else { + return [packageFolder stringByAppendingPathComponent:UpdateBundleFileName]; + } } + (NSString *)getCurrentPackageHash:(NSError **)error @@ -161,15 +189,15 @@ NSString * const UpdateBundleFileName = @"app.jsbundle"; } + (void)downloadPackage:(NSDictionary *)updatePackage - progressCallback:(void (^)(long, long))progressCallback + progressCallback:(void (^)(long long, long long))progressCallback doneCallback:(void (^)())doneCallback failCallback:(void (^)(NSError *err))failCallback { - NSString *packageFolderPath = [self getPackageFolderPath:updatePackage[@"packageHash"]]; + NSString *newPackageFolderPath = [self getPackageFolderPath:updatePackage[@"packageHash"]]; NSError *error = nil; - if (![[NSFileManager defaultManager] fileExistsAtPath:packageFolderPath]) { - [[NSFileManager defaultManager] createDirectoryAtPath:packageFolderPath + if (![[NSFileManager defaultManager] fileExistsAtPath:newPackageFolderPath]) { + [[NSFileManager defaultManager] createDirectoryAtPath:newPackageFolderPath withIntermediateDirectories:YES attributes:nil error:&error]; @@ -179,21 +207,122 @@ NSString * const UpdateBundleFileName = @"app.jsbundle"; return failCallback(error); } - NSString *downloadFilePath = [packageFolderPath stringByAppendingPathComponent:UpdateBundleFileName]; + NSString * downloadFilePath = [self getDownloadFilePath]; + NSString * bundleFilePath = [newPackageFolderPath stringByAppendingPathComponent:UpdateBundleFileName]; CodePushDownloadHandler *downloadHandler = [[CodePushDownloadHandler alloc] init:downloadFilePath progressCallback:progressCallback - doneCallback:^{ - NSError *error; + doneCallback:^(BOOL isZip) { + NSError *error = nil; + NSString * unzippedFolderPath = [CodePushPackage getUnzippedFolderPath]; + NSMutableDictionary * mutableUpdatePackage = [updatePackage mutableCopy]; + if (isZip) { + NSError *nonFailingError = nil; + + [SSZipArchive unzipFileAtPath:downloadFilePath + toDestination:unzippedFolderPath]; + [[NSFileManager defaultManager] removeItemAtPath:downloadFilePath + error:&nonFailingError]; + if (nonFailingError) { + NSLog(@"Error deleting downloaded file: %@", nonFailingError); + nonFailingError = nil; + } + + NSString * diffManifestFilePath = [unzippedFolderPath + stringByAppendingPathComponent:DiffManifestFileName]; + + if ([[NSFileManager defaultManager] fileExistsAtPath:diffManifestFilePath]) { + // Copy the current package to the new package. + NSString* currentPackageFolderPath = [self getCurrentPackageFolderPath:&error]; + if (error) { + failCallback(error); + return; + } + + [CodePushPackage copyEntriesInFolder:currentPackageFolderPath + destFolder:newPackageFolderPath + error:&error]; + if (error) { + failCallback(error); + return; + } + + // Delete files mentioned in the manifest. + NSString *manifestContent = [NSString stringWithContentsOfFile:diffManifestFilePath + encoding:NSUTF8StringEncoding + error:&error]; + if (error) { + failCallback(error); + return; + } + + NSData *data = [manifestContent dataUsingEncoding:NSUTF8StringEncoding]; + NSDictionary* manifestJSON = [NSJSONSerialization JSONObjectWithData:data + options:kNilOptions + error:&error]; + NSArray *deletedFiles = manifestJSON[@"deletedFiles"]; + for (NSString *deletedFileName in deletedFiles) { + [[NSFileManager defaultManager] + removeItemAtPath:[newPackageFolderPath + stringByAppendingPathComponent:deletedFileName] + error:&nonFailingError]; + + if (nonFailingError) { + NSLog(@"Error deleting file from current package: %@", nonFailingError); + nonFailingError = nil; + } + } + } + + [CodePushPackage copyEntriesInFolder:unzippedFolderPath + destFolder:newPackageFolderPath + error:&error]; + [[NSFileManager defaultManager] removeItemAtPath:unzippedFolderPath + error:&nonFailingError]; + if (nonFailingError) { + NSLog(@"Error deleting downloaded file: %@", nonFailingError); + nonFailingError = nil; + } + + NSString *relativeBundlePath = [self findMainBundleInFolder:newPackageFolderPath + error:&error]; + if (error) { + failCallback(error); + return; + } + + if (relativeBundlePath) { + [mutableUpdatePackage setValue:relativeBundlePath forKey:RelativeBundlePathKey]; + } else { + error = [[NSError alloc] initWithDomain:CodePushErrorDomain + code:CodePushErrorCode + userInfo:@{ + NSLocalizedDescriptionKey: + NSLocalizedString(@"Update is invalid - no files with extension .jsbundle or .bundle were found in the update package.", nil) + }]; + failCallback(error); + return; + } + } else { + [[NSFileManager defaultManager] moveItemAtPath:downloadFilePath + toPath:bundleFilePath + error:&error]; + if (error) { + failCallback(error); + return; + } + } + NSData *updateSerializedData = [NSJSONSerialization - dataWithJSONObject:updatePackage - options:0 - error:&error]; + dataWithJSONObject:mutableUpdatePackage + options:0 + error:&error]; NSString *packageJsonString = [[NSString alloc] - initWithData:updateSerializedData encoding:NSUTF8StringEncoding]; - - [packageJsonString writeToFile:[packageFolderPath stringByAppendingPathComponent:@"app.json"] + initWithData:updateSerializedData + encoding:NSUTF8StringEncoding]; + + [packageJsonString writeToFile:[newPackageFolderPath stringByAppendingPathComponent:@"app.json"] atomically:YES encoding:NSUTF8StringEncoding error:&error]; @@ -203,15 +332,96 @@ NSString * const UpdateBundleFileName = @"app.jsbundle"; doneCallback(); } } + failCallback:failCallback]; [downloadHandler download:updatePackage[@"downloadUrl"]]; } ++ (NSString *)findMainBundleInFolder:(NSString *)folderPath + error:(NSError **)error +{ + NSArray* folderFiles = [[NSFileManager defaultManager] + contentsOfDirectoryAtPath:folderPath + error:error]; + if (*error) { + return nil; + } + + for (NSString *fileName in folderFiles) { + NSString *fullFilePath = [folderPath stringByAppendingPathComponent:fileName]; + BOOL isDir = NO; + if ([[NSFileManager defaultManager] fileExistsAtPath:fullFilePath + isDirectory:&isDir] && isDir) { + NSString *mainBundlePathInFolder = [self findMainBundleInFolder:fullFilePath error:error]; + if (*error) { + return nil; + } + + if (mainBundlePathInFolder) { + return [fileName stringByAppendingPathComponent:mainBundlePathInFolder]; + } + } else if ([[fileName pathExtension] isEqualToString:@"bundle"] || + [[fileName pathExtension] isEqualToString:@"jsbundle"]) { + return fileName; + } + } + + return nil; +} + + ++ (void)copyEntriesInFolder:(NSString *)sourceFolder + destFolder:(NSString *)destFolder + error:(NSError **)error + +{ + NSArray* files = [[NSFileManager defaultManager] + contentsOfDirectoryAtPath:sourceFolder + error:error]; + if (*error) { + return; + } + + for (NSString *fileName in files) { + NSString * fullFilePath = [sourceFolder stringByAppendingPathComponent:fileName]; + BOOL isDir = NO; + if ([[NSFileManager defaultManager] fileExistsAtPath:fullFilePath + isDirectory:&isDir] && isDir) { + NSString *nestedDestFolder = [destFolder stringByAppendingPathComponent:fileName]; + [self copyEntriesInFolder:fullFilePath + destFolder:nestedDestFolder + error:error]; + } else { + NSString *destFileName = [destFolder stringByAppendingPathComponent:fileName]; + if ([[NSFileManager defaultManager] fileExistsAtPath:destFileName]) { + [[NSFileManager defaultManager] removeItemAtPath:destFileName error:error]; + if (*error) { + return; + } + } + if (![[NSFileManager defaultManager] fileExistsAtPath:destFolder]) { + [[NSFileManager defaultManager] createDirectoryAtPath:destFolder + withIntermediateDirectories:YES + attributes:nil + error:error]; + if (*error) { + return; + } + } + + [[NSFileManager defaultManager] moveItemAtPath:fullFilePath toPath:destFileName error:error]; + if (*error) { + return; + } + } + } +} + + (void)installPackage:(NSDictionary *)updatePackage error:(NSError **)error { - NSString *packageHash = updatePackage[@"packageHash" ]; + NSString *packageHash = updatePackage[@"packageHash"]; NSMutableDictionary *info = [self getCurrentPackageInfo:error]; if (*error) { @@ -223,7 +433,8 @@ NSString * const UpdateBundleFileName = @"app.jsbundle"; NSString *previousPackageFolderPath = [self getPackageFolderPath:previousPackageHash]; // Error in deleting old package will not cause the entire operation to fail. NSError *deleteError; - [[NSFileManager defaultManager] removeItemAtPath:previousPackageFolderPath error:&deleteError]; + [[NSFileManager defaultManager] removeItemAtPath:previousPackageFolderPath + error:&deleteError]; if (deleteError) { NSLog(@"Error deleting old package: %@", deleteError); } diff --git a/Examples/CodePushDemoApp/android/app/build.gradle b/Examples/CodePushDemoApp/android/app/build.gradle index d311359..f3999d3 100644 --- a/Examples/CodePushDemoApp/android/app/build.gradle +++ b/Examples/CodePushDemoApp/android/app/build.gradle @@ -1,5 +1,7 @@ apply plugin: 'com.android.application' +apply from: "react.gradle" + android { compileSdkVersion 23 buildToolsVersion "23.0.1" @@ -15,9 +17,9 @@ android { } } buildTypes { - debug { + /*debug { buildConfigField "String", "RUN_TEST", "\"\"" - } + }*/ release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' diff --git a/Examples/CodePushDemoApp/android/app/react.gradle b/Examples/CodePushDemoApp/android/app/react.gradle new file mode 100644 index 0000000..9da47fd --- /dev/null +++ b/Examples/CodePushDemoApp/android/app/react.gradle @@ -0,0 +1,75 @@ +def config = project.hasProperty("react") ? project.react : []; + +def bundleAssetName = config.bundleAssetName ?: "index.android.bundle" +def entryFile = config.entryFile ?: "index.android.js" + +// because elvis operator +def elvisFile(thing) { + return thing ? file(thing) : null; +} + +def reactRoot = elvisFile(config.root) ?: file("../../") +def jsBundleDirDebug = elvisFile(config.jsBundleDirDebug) ?: + file("$buildDir/intermediates/assets/debug") +def jsBundleDirRelease = elvisFile(config.jsBundleDirRelease) ?: + file("$buildDir/intermediates/assets/release") +def resourcesDirDebug = elvisFile(config.resourcesDirDebug) ?: + file("$buildDir/intermediates/res/merged/debug") +def resourcesDirRelease = elvisFile(config.resourcesDirRelease) ?: + file("$buildDir/intermediates/res/merged/release") +def inputExcludes = config.inputExcludes ?: ["android/**", "ios/**"] + +def jsBundleFileDebug = file("$jsBundleDirDebug/$bundleAssetName") +def jsBundleFileRelease = file("$jsBundleDirRelease/$bundleAssetName") + +task bundleDebugJsAndAssets(type: Exec) { + // create dirs if they are not there (e.g. the "clean" task just ran) + doFirst { + jsBundleDirDebug.mkdirs() + resourcesDirDebug.mkdirs() + } + + // set up inputs and outputs so gradle can cache the result + inputs.files fileTree(dir: reactRoot, excludes: inputExcludes) + outputs.dir jsBundleDirDebug + outputs.dir resourcesDirDebug + + // set up the call to the react-native cli + workingDir reactRoot + commandLine "react-native", "bundle", "--platform", "android", "--dev", "true", "--entry-file", + entryFile, "--bundle-output", jsBundleFileDebug, "--assets-dest", resourcesDirDebug + + enabled config.bundleInDebug ?: true +} + +task bundleReleaseJsAndAssets(type: Exec) { + // create dirs if they are not there (e.g. the "clean" task just ran) + doFirst { + jsBundleDirRelease.mkdirs() + resourcesDirRelease.mkdirs() + } + + // set up inputs and outputs so gradle can cache the result + inputs.files fileTree(dir: reactRoot, excludes: inputExcludes) + outputs.dir jsBundleDirRelease + outputs.dir resourcesDirRelease + + // set up the call to the react-native cli + workingDir reactRoot + commandLine "react-native", "bundle", "--platform", "android", "--dev", "false", "--entry-file", + entryFile, "--bundle-output", jsBundleFileRelease, "--assets-dest", resourcesDirRelease + + enabled config.bundleInRelease ?: true +} + +gradle.projectsEvaluated { + // hook bundleDebugJsAndAssets into the android build process + bundleDebugJsAndAssets.dependsOn mergeDebugResources + bundleDebugJsAndAssets.dependsOn mergeDebugAssets + processDebugResources.dependsOn bundleDebugJsAndAssets + + // hook bundleReleaseJsAndAssets into the android build process + bundleReleaseJsAndAssets.dependsOn mergeReleaseResources + bundleReleaseJsAndAssets.dependsOn mergeReleaseAssets + processReleaseResources.dependsOn bundleReleaseJsAndAssets +} \ No newline at end of file diff --git a/Examples/CodePushDemoApp/android/app/src/main/java/com/microsoft/codepushdemoapp/MainActivity.java b/Examples/CodePushDemoApp/android/app/src/main/java/com/microsoft/codepushdemoapp/MainActivity.java index a62e296..9d64a57 100644 --- a/Examples/CodePushDemoApp/android/app/src/main/java/com/microsoft/codepushdemoapp/MainActivity.java +++ b/Examples/CodePushDemoApp/android/app/src/main/java/com/microsoft/codepushdemoapp/MainActivity.java @@ -25,14 +25,14 @@ public class MainActivity extends FragmentActivity implements DefaultHardwareBac super.onCreate(savedInstanceState); mReactRootView = new ReactRootView(this); - codePush = new CodePush("DEPLOYMENT_KEY_HERE", this); + codePush = new CodePush("d73bf5d8-4fbd-4e55-a837-accd328a21ba", this); ReactInstanceManager.Builder builder = ReactInstanceManager.builder() .setApplication(getApplication()) .setJSBundleFile(codePush.getBundleUrl("index.android.bundle")); String mainComponentName = null; - +/* switch (BuildConfig.RUN_TEST) { case "DOWNLOAD_PROGRESS": builder = builder.setJSMainModuleName(TEST_FOLDER_PREFIX + "DownloadProgressTests/DownloadProgressTestApp"); @@ -51,7 +51,7 @@ public class MainActivity extends FragmentActivity implements DefaultHardwareBac builder = builder.setJSMainModuleName("index.android"); mainComponentName = "CodePushDemoApp"; break; - } + }*/ mReactInstanceManager = builder.addPackage(new MainReactPackage()) .addPackage(codePush.getReactPackage()) diff --git a/Examples/CodePushDemoApp/crossplatformdemo.js b/Examples/CodePushDemoApp/crossplatformdemo.js index 13b55fe..2bd9d24 100644 --- a/Examples/CodePushDemoApp/crossplatformdemo.js +++ b/Examples/CodePushDemoApp/crossplatformdemo.js @@ -3,6 +3,8 @@ var React = require('react-native'); var { AppRegistry, + Dimensions, + Image, StyleSheet, Text, TouchableOpacity, @@ -115,22 +117,28 @@ var CodePushDemoApp = React.createClass({ {syncButton} {syncView} {progressView} + ); } }); var styles = StyleSheet.create({ + image: { + marginTop: 50, + width: Dimensions.get('window').width - 100, + height: 365 * (Dimensions.get('window').width - 100) / 651, + }, container: { flex: 1, alignItems: 'center', backgroundColor: '#F5FCFF', + paddingTop: 50 }, welcome: { fontSize: 20, textAlign: 'center', - margin: 10, - marginTop: 50 + margin: 10 }, messages: { textAlign: 'center', diff --git a/Examples/CodePushDemoApp/CodePushDemoApp.xcodeproj/project.pbxproj b/Examples/CodePushDemoApp/iOS/CodePushDemoApp.xcodeproj/project.pbxproj similarity index 90% rename from Examples/CodePushDemoApp/CodePushDemoApp.xcodeproj/project.pbxproj rename to Examples/CodePushDemoApp/iOS/CodePushDemoApp.xcodeproj/project.pbxproj index 7ab1309..b351bb3 100644 --- a/Examples/CodePushDemoApp/CodePushDemoApp.xcodeproj/project.pbxproj +++ b/Examples/CodePushDemoApp/iOS/CodePushDemoApp.xcodeproj/project.pbxproj @@ -25,7 +25,7 @@ 5451ACBA1B86A5B600E2A7DF /* QueryUpdateTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5451ACB81B86A5B600E2A7DF /* QueryUpdateTests.m */; }; 5451ACEC1B86E40A00E2A7DF /* libRCTTest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5451ACEB1B86E34300E2A7DF /* libRCTTest.a */; }; 54D774BA1B87DAF800F2ABF8 /* InstallUpdateTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 54D774B91B87DAF800F2ABF8 /* InstallUpdateTests.m */; }; - 54F5F2B41BF6B45D007C3CEA /* DownloadProgressTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 54F5F2B31BF6B45D007C3CEA /* DownloadProgressTests.m */; settings = {ASSET_TAGS = (); }; }; + 54F5F2B41BF6B45D007C3CEA /* DownloadProgressTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 54F5F2B31BF6B45D007C3CEA /* DownloadProgressTests.m */; }; 81551E1B1B3B428000F5B9F1 /* libCodePush.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 81551E0F1B3B427200F5B9F1 /* libCodePush.a */; }; /* End PBXBuildFile section */ @@ -131,31 +131,31 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = "node_modules/react-native/Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj"; sourceTree = ""; }; - 00C302AF1ABCB8E700DB3ED1 /* RCTAdSupport.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAdSupport.xcodeproj; path = "node_modules/react-native/Libraries/AdSupport/RCTAdSupport.xcodeproj"; sourceTree = ""; }; - 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTGeolocation.xcodeproj; path = "node_modules/react-native/Libraries/Geolocation/RCTGeolocation.xcodeproj"; sourceTree = ""; }; - 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = "node_modules/react-native/Libraries/Image/RCTImage.xcodeproj"; sourceTree = ""; }; - 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = "node_modules/react-native/Libraries/Network/RCTNetwork.xcodeproj"; sourceTree = ""; }; - 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = "node_modules/react-native/Libraries/Vibration/RCTVibration.xcodeproj"; sourceTree = ""; }; + 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = "../node_modules/react-native/Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj"; sourceTree = ""; }; + 00C302AF1ABCB8E700DB3ED1 /* RCTAdSupport.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAdSupport.xcodeproj; path = "../node_modules/react-native/Libraries/AdSupport/RCTAdSupport.xcodeproj"; sourceTree = ""; }; + 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTGeolocation.xcodeproj; path = "../node_modules/react-native/Libraries/Geolocation/RCTGeolocation.xcodeproj"; sourceTree = ""; }; + 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = "../node_modules/react-native/Libraries/Image/RCTImage.xcodeproj"; sourceTree = ""; }; + 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = "../node_modules/react-native/Libraries/Network/RCTNetwork.xcodeproj"; sourceTree = ""; }; + 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = "../node_modules/react-native/Libraries/Vibration/RCTVibration.xcodeproj"; sourceTree = ""; }; 00E356EE1AD99517003FC87E /* CodePushDemoAppTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CodePushDemoAppTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = "node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj"; sourceTree = ""; }; - 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = "node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj"; sourceTree = ""; }; + 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = "../node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj"; sourceTree = ""; }; + 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = "../node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj"; sourceTree = ""; }; 13B07F961A680F5B00A75B9A /* CodePushDemoApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CodePushDemoApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = iOS/AppDelegate.h; sourceTree = ""; }; - 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = iOS/AppDelegate.m; sourceTree = ""; }; + 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = CodePushDemoApp/AppDelegate.h; sourceTree = ""; }; + 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = CodePushDemoApp/AppDelegate.m; sourceTree = ""; }; 13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = iOS/Images.xcassets; sourceTree = ""; }; - 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = iOS/Info.plist; sourceTree = ""; }; - 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = iOS/main.m; sourceTree = ""; }; - 146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "node_modules/react-native/React/React.xcodeproj"; sourceTree = ""; }; + 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = CodePushDemoApp/Images.xcassets; sourceTree = ""; }; + 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = CodePushDemoApp/Info.plist; sourceTree = ""; }; + 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = CodePushDemoApp/main.m; sourceTree = ""; }; + 146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../node_modules/react-native/React/React.xcodeproj"; sourceTree = ""; }; 5451ACB81B86A5B600E2A7DF /* QueryUpdateTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QueryUpdateTests.m; sourceTree = ""; }; - 5451ACE61B86E34300E2A7DF /* RCTTest.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTTest.xcodeproj; path = "node_modules/react-native/Libraries/RCTTest/RCTTest.xcodeproj"; sourceTree = ""; }; + 5451ACE61B86E34300E2A7DF /* RCTTest.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTTest.xcodeproj; path = "../node_modules/react-native/Libraries/RCTTest/RCTTest.xcodeproj"; sourceTree = ""; }; 54D774B91B87DAF800F2ABF8 /* InstallUpdateTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InstallUpdateTests.m; sourceTree = ""; }; 54F5F2B31BF6B45D007C3CEA /* DownloadProgressTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DownloadProgressTests.m; sourceTree = ""; }; - 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = ""; }; - 81551E0A1B3B427200F5B9F1 /* CodePush.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = CodePush.xcodeproj; path = ../../CodePush.xcodeproj; sourceTree = ""; }; - 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = ""; }; + 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = ""; }; + 81551E0A1B3B427200F5B9F1 /* CodePush.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = CodePush.xcodeproj; path = ../../../CodePush.xcodeproj; sourceTree = ""; }; + 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -237,7 +237,7 @@ name = Products; sourceTree = ""; }; - 00E356EF1AD99517003FC87E /* CodePushDemoAppTests */ = { + 00E356EF1AD99517003FC87E /* ../CodePushDemoAppTests */ = { isa = PBXGroup; children = ( 54F5F2B31BF6B45D007C3CEA /* DownloadProgressTests.m */, @@ -245,7 +245,7 @@ 54D774B91B87DAF800F2ABF8 /* InstallUpdateTests.m */, 00E356F01AD99517003FC87E /* Supporting Files */, ); - path = CodePushDemoAppTests; + path = ../CodePushDemoAppTests; sourceTree = ""; }; 00E356F01AD99517003FC87E /* Supporting Files */ = { @@ -350,7 +350,7 @@ children = ( 13B07FAE1A68108700A75B9A /* CodePushDemoApp */, 832341AE1AAA6A7D00B99B32 /* Libraries */, - 00E356EF1AD99517003FC87E /* CodePushDemoAppTests */, + 00E356EF1AD99517003FC87E /* ../CodePushDemoAppTests */, 83CBBA001A601CBA00E9B192 /* Products */, ); indentWidth = 2; @@ -394,6 +394,7 @@ 13B07F871A680F5B00A75B9A /* Sources */, 13B07F8C1A680F5B00A75B9A /* Frameworks */, 13B07F8E1A680F5B00A75B9A /* Resources */, + 54A001DF1C0D0DAF004C3CEC /* Bundle React Native Code and Images */, ); buildRules = ( ); @@ -605,6 +606,23 @@ }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + 54A001DF1C0D0DAF004C3CEC /* Bundle React Native Code and Images */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Bundle React Native Code and Images"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "../node_modules/react-native/packager/react-native-xcode.sh"; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ 00E356EA1AD99517003FC87E /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -642,7 +660,7 @@ 13B07FB21A68108700A75B9A /* Base */, ); name = LaunchScreen.xib; - path = iOS; + path = CodePushDemoApp; sourceTree = ""; }; /* End PBXVariantGroup section */ @@ -660,7 +678,7 @@ "DEBUG=1", "$(inherited)", ); - INFOPLIST_FILE = CodePushDemoAppTests/Info.plist; + INFOPLIST_FILE = ../CodePushDemoAppTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.2; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -677,7 +695,7 @@ "$(SDKROOT)/Developer/Library/Frameworks", "$(inherited)", ); - INFOPLIST_FILE = CodePushDemoAppTests/Info.plist; + INFOPLIST_FILE = ../CodePushDemoAppTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.2; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -692,12 +710,15 @@ HEADER_SEARCH_PATHS = ( "$(inherited)", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/node_modules/react-native/React/**", - "$(SRCROOT)/../..", + "$(SRCROOT)/../node_modules/react-native/React/**", + "$(SRCROOT)/../../..", ); - INFOPLIST_FILE = "$(SRCROOT)/iOS/Info.plist"; + INFOPLIST_FILE = "$(SRCROOT)/CodePushDemoApp/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - OTHER_LDFLAGS = "-ObjC"; + OTHER_LDFLAGS = ( + "-ObjC", + "-lz", + ); PRODUCT_NAME = CodePushDemoApp; }; name = Debug; @@ -709,12 +730,15 @@ HEADER_SEARCH_PATHS = ( "$(inherited)", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/node_modules/react-native/React/**", - "$(SRCROOT)/../..", + "$(SRCROOT)/../node_modules/react-native/React/**", + "$(SRCROOT)/../../..", ); - INFOPLIST_FILE = "$(SRCROOT)/iOS/Info.plist"; + INFOPLIST_FILE = "$(SRCROOT)/CodePushDemoApp/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - OTHER_LDFLAGS = "-ObjC"; + OTHER_LDFLAGS = ( + "-ObjC", + "-lz", + ); PRODUCT_NAME = CodePushDemoApp; }; name = Release; @@ -756,7 +780,7 @@ HEADER_SEARCH_PATHS = ( "$(inherited)", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/node_modules/react-native/React/**", + "$(SRCROOT)/../node_modules/react-native/React/**", ); IPHONEOS_DEPLOYMENT_TARGET = 7.0; MTL_ENABLE_DEBUG_INFO = YES; @@ -796,7 +820,7 @@ HEADER_SEARCH_PATHS = ( "$(inherited)", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/node_modules/react-native/React/**", + "$(SRCROOT)/../node_modules/react-native/React/**", ); IPHONEOS_DEPLOYMENT_TARGET = 7.0; MTL_ENABLE_DEBUG_INFO = NO; diff --git a/Examples/CodePushDemoApp/CodePushDemoApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Examples/CodePushDemoApp/iOS/CodePushDemoApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 100% rename from Examples/CodePushDemoApp/CodePushDemoApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to Examples/CodePushDemoApp/iOS/CodePushDemoApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/Examples/CodePushDemoApp/CodePushDemoApp.xcodeproj/xcshareddata/xcschemes/CodePushDemoApp.xcscheme b/Examples/CodePushDemoApp/iOS/CodePushDemoApp.xcodeproj/xcshareddata/xcschemes/CodePushDemoApp.xcscheme similarity index 100% rename from Examples/CodePushDemoApp/CodePushDemoApp.xcodeproj/xcshareddata/xcschemes/CodePushDemoApp.xcscheme rename to Examples/CodePushDemoApp/iOS/CodePushDemoApp.xcodeproj/xcshareddata/xcschemes/CodePushDemoApp.xcscheme diff --git a/Examples/CodePushDemoApp/iOS/AppDelegate.h b/Examples/CodePushDemoApp/iOS/CodePushDemoApp/AppDelegate.h similarity index 100% rename from Examples/CodePushDemoApp/iOS/AppDelegate.h rename to Examples/CodePushDemoApp/iOS/CodePushDemoApp/AppDelegate.h diff --git a/Examples/CodePushDemoApp/iOS/AppDelegate.m b/Examples/CodePushDemoApp/iOS/CodePushDemoApp/AppDelegate.m similarity index 97% rename from Examples/CodePushDemoApp/iOS/AppDelegate.m rename to Examples/CodePushDemoApp/iOS/CodePushDemoApp/AppDelegate.m index aac98cc..5e8a6e3 100644 --- a/Examples/CodePushDemoApp/iOS/AppDelegate.m +++ b/Examples/CodePushDemoApp/iOS/CodePushDemoApp/AppDelegate.m @@ -44,6 +44,8 @@ * * see http://facebook.github.io/react-native/docs/runningondevice.html */ + + NSLog(@"%@", [[CodePush bundleURL] absoluteString]); jsCodeLocation = [CodePush bundleURL]; diff --git a/Examples/CodePushDemoApp/iOS/Base.lproj/LaunchScreen.xib b/Examples/CodePushDemoApp/iOS/CodePushDemoApp/Base.lproj/LaunchScreen.xib similarity index 100% rename from Examples/CodePushDemoApp/iOS/Base.lproj/LaunchScreen.xib rename to Examples/CodePushDemoApp/iOS/CodePushDemoApp/Base.lproj/LaunchScreen.xib diff --git a/Examples/CodePushDemoApp/iOS/Images.xcassets/AppIcon.appiconset/Contents.json b/Examples/CodePushDemoApp/iOS/CodePushDemoApp/Images.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from Examples/CodePushDemoApp/iOS/Images.xcassets/AppIcon.appiconset/Contents.json rename to Examples/CodePushDemoApp/iOS/CodePushDemoApp/Images.xcassets/AppIcon.appiconset/Contents.json diff --git a/Examples/CodePushDemoApp/iOS/Info.plist b/Examples/CodePushDemoApp/iOS/CodePushDemoApp/Info.plist similarity index 96% rename from Examples/CodePushDemoApp/iOS/Info.plist rename to Examples/CodePushDemoApp/iOS/CodePushDemoApp/Info.plist index e1033b9..6cb683d 100644 --- a/Examples/CodePushDemoApp/iOS/Info.plist +++ b/Examples/CodePushDemoApp/iOS/CodePushDemoApp/Info.plist @@ -44,6 +44,6 @@ NSLocationWhenInUseUsageDescription CodePushDeploymentKey - deployment-key-here + 5c73310a-cc93-4aa5-bf9f-81c6b648232c diff --git a/Examples/CodePushDemoApp/iOS/main.m b/Examples/CodePushDemoApp/iOS/CodePushDemoApp/main.m similarity index 100% rename from Examples/CodePushDemoApp/iOS/main.m rename to Examples/CodePushDemoApp/iOS/CodePushDemoApp/main.m diff --git a/Examples/CodePushDemoApp/images/laptop_phone_howitworks.png b/Examples/CodePushDemoApp/images/laptop_phone_howitworks.png new file mode 100644 index 0000000000000000000000000000000000000000..de3b10e0e074926231b2bb4aa42d110e04511c49 GIT binary patch literal 29922 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 &Q5q#Ixkv>$F|3s!l@PrXtO}umy}E6 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 literal 0 HcmV?d00001 diff --git a/Examples/CodePushDemoApp/package.json b/Examples/CodePushDemoApp/package.json index 19e695e..b0b2e4e 100644 --- a/Examples/CodePushDemoApp/package.json +++ b/Examples/CodePushDemoApp/package.json @@ -6,7 +6,7 @@ "start": "node_modules/react-native/packager/packager.sh --root ../../" }, "dependencies": { - "react-native": "0.14.2", + "react-native": "0.15.0", "react-native-button": "^1.2.0", "react-native-code-push": "file:../../" } diff --git a/Examples/CodePushDemoApp/release/assets/images/laptop_phone_howitworks.png b/Examples/CodePushDemoApp/release/assets/images/laptop_phone_howitworks.png new file mode 100644 index 0000000000000000000000000000000000000000..eac1ecb8765adabdd86dffd85785a2a41fedefd3 GIT binary patch literal 31155 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 C>_9F6 literal 0 HcmV?d00001 diff --git a/SSZipArchive/Common.h b/SSZipArchive/Common.h new file mode 100755 index 0000000..7a92f13 --- /dev/null +++ b/SSZipArchive/Common.h @@ -0,0 +1,81 @@ +#ifndef SSZipCommon +#define SSZipCommon + +/* tm_unz contain date/time info */ +typedef struct tm_unz_s +{ + unsigned int tm_sec; /* seconds after the minute - [0,59] */ + unsigned int tm_min; /* minutes after the hour - [0,59] */ + unsigned int tm_hour; /* hours since midnight - [0,23] */ + unsigned int tm_mday; /* day of the month - [1,31] */ + unsigned int tm_mon; /* months since January - [0,11] */ + unsigned int tm_year; /* years - [1980..2044] */ +} tm_unz; + +typedef struct unz_file_info_s +{ + unsigned long version; /* version made by 2 bytes */ + unsigned long version_needed; /* version needed to extract 2 bytes */ + unsigned long flag; /* general purpose bit flag 2 bytes */ + unsigned long compression_method; /* compression method 2 bytes */ + unsigned long dosDate; /* last mod file date in Dos fmt 4 bytes */ + unsigned long crc; /* crc-32 4 bytes */ + unsigned long compressed_size; /* compressed size 4 bytes */ + unsigned long uncompressed_size; /* uncompressed size 4 bytes */ + unsigned long size_filename; /* filename length 2 bytes */ + unsigned long size_file_extra; /* extra field length 2 bytes */ + unsigned long size_file_comment; /* file comment length 2 bytes */ + + unsigned long disk_num_start; /* disk number start 2 bytes */ + unsigned long internal_fa; /* internal file attributes 2 bytes */ + unsigned long external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; +} unz_file_info; + +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_info64_s +{ + unsigned long version; /* version made by 2 bytes */ + unsigned long version_needed; /* version needed to extract 2 bytes */ + unsigned long flag; /* general purpose bit flag 2 bytes */ + unsigned long compression_method; /* compression method 2 bytes */ + unsigned long dosDate; /* last mod file date in Dos fmt 4 bytes */ + unsigned long crc; /* crc-32 4 bytes */ + unsigned long long compressed_size; /* compressed size 8 bytes */ + unsigned long long uncompressed_size; /* uncompressed size 8 bytes */ + unsigned long size_filename; /* filename length 2 bytes */ + unsigned long size_file_extra; /* extra field length 2 bytes */ + unsigned long size_file_comment; /* file comment length 2 bytes */ + + unsigned long disk_num_start; /* disk number start 2 bytes */ + unsigned long internal_fa; /* internal file attributes 2 bytes */ + unsigned long external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; + unsigned long long disk_offset; + unsigned long size_file_extra_internal; +} unz_file_info64; + +typedef struct unz_global_info_s +{ + unsigned long number_entry; /* total number of entries in + the central dir on this disk */ + + unsigned long number_disk_with_CD; /* number the the disk with central dir, used for spanning ZIP*/ + + + unsigned long size_comment; /* size of the global comment of the zipfile */ +} unz_global_info; + +typedef struct unz_global_info64 +{ + unsigned long long number_entry; /* total number of entries in + the central dir on this disk */ + + unsigned long number_disk_with_CD; /* number the the disk with central dir, used for spanning ZIP*/ + + unsigned long size_comment; /* size of the global comment of the zipfile */ +} unz_global_info64; + +#endif \ No newline at end of file diff --git a/SSZipArchive/SSZipArchive.h b/SSZipArchive/SSZipArchive.h new file mode 100755 index 0000000..b18cab9 --- /dev/null +++ b/SSZipArchive/SSZipArchive.h @@ -0,0 +1,76 @@ +// +// SSZipArchive.h +// SSZipArchive +// +// Created by Sam Soffes on 7/21/10. +// Copyright (c) Sam Soffes 2010-2015. All rights reserved. +// + +#ifndef _SSZIPARCHIVE_H +#define _SSZIPARCHIVE_H + +#import +#include "Common.h" + +@protocol SSZipArchiveDelegate; + +@interface SSZipArchive : NSObject + +// Unzip ++ (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination; ++ (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination delegate:(id)delegate; + ++ (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination overwrite:(BOOL)overwrite password:(NSString *)password error:(NSError * *)error; ++ (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination overwrite:(BOOL)overwrite password:(NSString *)password error:(NSError * *)error delegate:(id)delegate; + ++ (BOOL)unzipFileAtPath:(NSString *)path + toDestination:(NSString *)destination + progressHandler:(void (^)(NSString *entry, unz_file_info zipInfo, long entryNumber, long total))progressHandler + completionHandler:(void (^)(NSString *path, BOOL succeeded, NSError *error))completionHandler; + ++ (BOOL)unzipFileAtPath:(NSString *)path + toDestination:(NSString *)destination + overwrite:(BOOL)overwrite + password:(NSString *)password + progressHandler:(void (^)(NSString *entry, unz_file_info zipInfo, long entryNumber, long total))progressHandler + completionHandler:(void (^)(NSString *path, BOOL succeeded, NSError *error))completionHandler; + +// Zip + +// without password ++ (BOOL)createZipFileAtPath:(NSString *)path withFilesAtPaths:(NSArray *)paths; ++ (BOOL)createZipFileAtPath:(NSString *)path withContentsOfDirectory:(NSString *)directoryPath; ++ (BOOL)createZipFileAtPath:(NSString *)path withContentsOfDirectory:(NSString *)directoryPath keepParentDirectory:(BOOL)keepParentDirector; + +// with password, password could be nil ++ (BOOL)createZipFileAtPath:(NSString *)path withFilesAtPaths:(NSArray *)paths withPassword:(NSString *)password; ++ (BOOL)createZipFileAtPath:(NSString *)path withContentsOfDirectory:(NSString *)directoryPath withPassword:(NSString *)password; ++ (BOOL)createZipFileAtPath:(NSString *)path withContentsOfDirectory:(NSString *)directoryPath keepParentDirectory:(BOOL)keepParentDirectory withPassword:(NSString *)password; + +- (instancetype)initWithPath:(NSString *)path; +@property (NS_NONATOMIC_IOSONLY, readonly, getter = isOpen) BOOL open; +- (BOOL)writeFile:(NSString *)path withPassword:(NSString *)password; +- (BOOL)writeFileAtPath:(NSString *)path withFileName:(NSString *)fileName withPassword:(NSString *)password; +- (BOOL)writeData:(NSData *)data filename:(NSString *)filename withPassword:(NSString *)password; +@property (NS_NONATOMIC_IOSONLY, readonly, getter = isClosed) BOOL close; + +@end + +@protocol SSZipArchiveDelegate + +@optional + +- (void)zipArchiveWillUnzipArchiveAtPath:(NSString *)path zipInfo:(unz_global_info)zipInfo; +- (void)zipArchiveDidUnzipArchiveAtPath:(NSString *)path zipInfo:(unz_global_info)zipInfo unzippedPath:(NSString *)unzippedPath; + +- (BOOL)zipArchiveShouldUnzipFileAtIndex:(NSInteger)fileIndex totalFiles:(NSInteger)totalFiles archivePath:(NSString *)archivePath fileInfo:(unz_file_info)fileInfo; +- (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)zipArchiveDidUnzipFileAtIndex:(NSInteger)fileIndex totalFiles:(NSInteger)totalFiles archivePath:(NSString *)archivePath unzippedFilePath:(NSString *)unzippedFilePath; + +- (void)zipArchiveProgressEvent:(unsigned long long)loaded total:(unsigned long long)total; +- (void)zipArchiveDidUnzipArchiveFile:(NSString *)zipFile entryPath:(NSString *)entryPath destPath:(NSString *)destPath; + +@end + +#endif /* _SSZIPARCHIVE_H */ diff --git a/SSZipArchive/SSZipArchive.m b/SSZipArchive/SSZipArchive.m new file mode 100755 index 0000000..c4491d2 --- /dev/null +++ b/SSZipArchive/SSZipArchive.m @@ -0,0 +1,691 @@ +// +// SSZipArchive.m +// SSZipArchive +// +// Created by Sam Soffes on 7/21/10. +// Copyright (c) Sam Soffes 2010-2015. All rights reserved. +// +#import "SSZipArchive.h" +#include "unzip.h" +#include "zip.h" +#import "zlib.h" +#import "zconf.h" + +#include + +#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 progressHandler:nil completionHandler:nil]; +} + ++ (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination delegate:(id)delegate +{ + return [self unzipFileAtPath:path toDestination:destination overwrite:YES password:nil error:nil delegate:delegate progressHandler:nil completionHandler:nil]; +} + ++ (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination overwrite:(BOOL)overwrite password:(NSString *)password error:(NSError **)error delegate:(id)delegate +{ + return [self unzipFileAtPath:path toDestination:destination overwrite:overwrite password:password error:error delegate:delegate progressHandler:nil completionHandler:nil]; +} + ++ (BOOL)unzipFileAtPath:(NSString *)path + toDestination:(NSString *)destination + overwrite:(BOOL)overwrite + password:(NSString *)password + progressHandler:(void (^)(NSString *entry, unz_file_info zipInfo, long entryNumber, long total))progressHandler + completionHandler:(void (^)(NSString *path, BOOL succeeded, NSError *error))completionHandler +{ + return [self unzipFileAtPath:path toDestination:destination overwrite:overwrite password:password error:nil delegate:nil progressHandler:progressHandler completionHandler:completionHandler]; +} + ++ (BOOL)unzipFileAtPath:(NSString *)path + toDestination:(NSString *)destination + progressHandler:(void (^)(NSString *entry, unz_file_info zipInfo, long entryNumber, long total))progressHandler + completionHandler:(void (^)(NSString *path, BOOL succeeded, NSError *error))completionHandler +{ + return [self unzipFileAtPath:path toDestination:destination overwrite:YES password:nil error:nil delegate:nil progressHandler:progressHandler completionHandler:completionHandler]; +} + ++ (BOOL)unzipFileAtPath:(NSString *)path + toDestination:(NSString *)destination + overwrite:(BOOL)overwrite + password:(NSString *)password + error:(NSError **)error + delegate:(id)delegate + progressHandler:(void (^)(NSString *entry, unz_file_info zipInfo, long entryNumber, long total))progressHandler + completionHandler:(void (^)(NSString *path, BOOL succeeded, NSError *error))completionHandler +{ + // Begin opening + zipFile zip = unzOpen((const char*)[path UTF8String]); + if (zip == NULL) + { + NSDictionary *userInfo = @{NSLocalizedDescriptionKey: @"failed to open zip file"}; + NSError *err = [NSError errorWithDomain:@"SSZipArchiveErrorDomain" code:-1 userInfo:userInfo]; + if (error) + { + *error = err; + } + if (completionHandler) + { + completionHandler(nil, NO, err); + } + return NO; + } + + NSDictionary * fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil]; + unsigned long long fileSize = [fileAttributes[NSFileSize] unsignedLongLongValue]; + unsigned long long currentPosition = 0; + + unz_global_info globalInfo = {0ul, 0ul}; + unzGetGlobalInfo(zip, &globalInfo); + + // Begin unzipping + if (unzGoToFirstFile(zip) != UNZ_OK) + { + NSDictionary *userInfo = @{NSLocalizedDescriptionKey: @"failed to open first file in zip file"}; + NSError *err = [NSError errorWithDomain:@"SSZipArchiveErrorDomain" code:-2 userInfo:userInfo]; + if (error) + { + *error = err; + } + if (completionHandler) + { + completionHandler(nil, NO, err); + } + return NO; + } + + BOOL success = YES; + BOOL canceled = NO; + int ret = 0; + int crc_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:(NSInteger)currentPosition total:(NSInteger)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(zipArchiveShouldUnzipFileAtIndex:totalFiles:archivePath:fileInfo:)]) { + if (![delegate zipArchiveShouldUnzipFileAtIndex:currentFileNumber + totalFiles:(NSInteger)globalInfo.number_entry + archivePath:path fileInfo:fileInfo]) { + success = NO; + canceled = YES; + break; + } + } + 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:(NSInteger)currentPosition total:(NSInteger)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 = NO; + } + + // Check if it contains directory + NSString *strPath = @(filename); + 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 = @{NSFileCreationDate: modDate, NSFileModificationDate: modDate}; + + 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: @{@"path": fullPath, @"modDate": modDate}]; + + if ([fileManager fileExistsAtPath:fullPath] && !isDirectory && !overwrite) { + //FIXME: couldBe CRC Check? + 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) { + if ([[[fullPath pathExtension] lowercaseString] isEqualToString:@"zip"]) { + NSLog(@"Unzipping nested .zip file: %@", [fullPath lastPathComponent]); + if ([self unzipFileAtPath:fullPath toDestination:[fullPath stringByDeletingLastPathComponent] overwrite:overwrite password:password error:nil delegate:nil]) { + [[NSFileManager defaultManager] removeItemAtPath:fullPath error:nil]; + } + } + + fclose(fp); + + // Set the original datetime property + if (fileInfo.dosDate != 0) { + NSDate *orgDate = [[self class] _dateWithMSDOSFormat:(UInt32)fileInfo.dosDate]; + NSDictionary *attr = @{NSFileModificationDate: orgDate}; + + 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] = (int)0; + [destinationPath appendString:@((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); + } + } + + crc_ret = unzCloseCurrentFile( zip ); + if (crc_ret == UNZ_CRCERROR) { + //CRC ERROR + return NO; + } + 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]; + } else if ([delegate respondsToSelector: @selector(zipArchiveDidUnzipFileAtIndex:totalFiles:archivePath:unzippedFilePath:)]) { + [delegate zipArchiveDidUnzipFileAtIndex: currentFileNumber totalFiles: (NSInteger)globalInfo.number_entry + archivePath:path unzippedFilePath: fullPath]; + } + + currentFileNumber++; + if (progressHandler) + { + progressHandler(strPath, fileInfo, currentFileNumber, globalInfo.number_entry); + } + } + } 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:@{NSFileModificationDate: d[@"modDate"]} ofItemAtPath:d[@"path"] error:&err]) { + NSLog(@"[SSZipArchive] Set attributes failed for directory: %@.", d[@"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 (!canceled && [delegate respondsToSelector:@selector(zipArchiveProgressEvent:total:)]) { + [delegate zipArchiveProgressEvent:fileSize total:fileSize]; + } + + if (completionHandler) + { + completionHandler(path, YES, nil); + } + return success; +} + +#pragma mark - Zipping ++ (BOOL)createZipFileAtPath:(NSString *)path withFilesAtPaths:(NSArray *)paths +{ + return [SSZipArchive createZipFileAtPath:path withFilesAtPaths:paths withPassword:nil]; +} ++ (BOOL)createZipFileAtPath:(NSString *)path withContentsOfDirectory:(NSString *)directoryPath{ + return [SSZipArchive createZipFileAtPath:path withContentsOfDirectory:directoryPath withPassword:nil]; +} + ++ (BOOL)createZipFileAtPath:(NSString *)path withContentsOfDirectory:(NSString *)directoryPath keepParentDirectory:(BOOL)keepParentDirector{ + return [SSZipArchive createZipFileAtPath:path withContentsOfDirectory:directoryPath keepParentDirectory:keepParentDirector withPassword:nil]; +} + ++ (BOOL)createZipFileAtPath:(NSString *)path withFilesAtPaths:(NSArray *)paths withPassword:(NSString *)password +{ + BOOL success = NO; + SSZipArchive *zipArchive = [[SSZipArchive alloc] initWithPath:path]; + if ([zipArchive open]) { + for (NSString *filePath in paths) { + [zipArchive writeFile:filePath withPassword:password]; + } + success = [zipArchive close]; + } + +#if !__has_feature(objc_arc) + [zipArchive release]; +#endif + + return success; +} + ++ (BOOL)createZipFileAtPath:(NSString *)path withContentsOfDirectory:(NSString *)directoryPath withPassword:(NSString *)password{ + return [self createZipFileAtPath:path withContentsOfDirectory:directoryPath keepParentDirectory:NO withPassword:password]; +} + + ++ (BOOL)createZipFileAtPath:(NSString *)path withContentsOfDirectory:(NSString *)directoryPath keepParentDirectory:(BOOL)keepParentDirectory withPassword:(NSString *)password{ + 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) { + if (keepParentDirectory) + { + fileName = [[directoryPath lastPathComponent] stringByAppendingPathComponent:fileName]; + } + [zipArchive writeFileAtPath:fullFilePath withFileName:fileName withPassword:password]; + } + else + { + if([[NSFileManager defaultManager] subpathsOfDirectoryAtPath:fullFilePath error:nil].count == 0) + { + NSString *tempName = [fullFilePath stringByAppendingPathComponent:@".DS_Store"]; + [@"" writeToFile:tempName atomically:YES encoding:NSUTF8StringEncoding error:nil]; + [zipArchive writeFileAtPath:tempName withFileName:[fileName stringByAppendingPathComponent:@".DS_Store"] withPassword:password]; + [[NSFileManager defaultManager] removeItemAtPath:tempName error:nil]; + } + } + } + success = [zipArchive close]; + } + +#if !__has_feature(objc_arc) + [fileManager release]; + [zipArchive release]; +#endif + + return success; +} + + +- (instancetype)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]; +#if defined(__IPHONE_8_0) || defined(__MAC_10_10) + uint flags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond; +#else + uint flags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit; +#endif + 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)writeFolderAtPath:(NSString *)path withFolderName:(NSString *)folderName withPassword:(NSString *)password +{ + NSAssert((_zip != NULL), @"Attempting to write to an archive which was never opened"); + + zip_fileinfo zipInfo = {{0}}; + + NSDictionary *attr = [[NSFileManager defaultManager] attributesOfItemAtPath:path error: nil]; + if( attr ) + { + NSDate *fileDate = (NSDate *)attr[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[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; + } + } + + unsigned int len = 0; + zipOpenNewFileInZip3(_zip, [[folderName stringByAppendingString:@"/"] UTF8String], &zipInfo, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_NO_COMPRESSION, 0, -MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, [password UTF8String], 0); + zipWriteInFileInZip(_zip, &len, 0); + zipCloseFileInZip(_zip); + return YES; +} + +- (BOOL)writeFile:(NSString *)path withPassword:(NSString *)password; +{ + return [self writeFileAtPath:path withFileName:nil withPassword:password]; +} + +// 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 withPassword:(NSString *)password +{ + 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[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[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; + } + } + + zipOpenNewFileInZip3(_zip, afileName, &zipInfo, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION, 0, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, [password UTF8String], 0); + + 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 withPassword:(NSString *)password; +{ + 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]]; + + zipOpenNewFileInZip3(_zip, [filename UTF8String], &zipInfo, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION, 0, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, [password UTF8String], 0); + + 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 3 = 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, ^{ +#if defined(__IPHONE_8_0) || defined(__MAC_10_10) + gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; +#else + gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; +#endif + }); + + 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 \ No newline at end of file diff --git a/SSZipArchive/aes/aes.h b/SSZipArchive/aes/aes.h new file mode 100755 index 0000000..44682c3 --- /dev/null +++ b/SSZipArchive/aes/aes.h @@ -0,0 +1,198 @@ +/* +--------------------------------------------------------------------------- +Copyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved. + +The redistribution and use of this software (with or without changes) +is allowed without the payment of fees or royalties provided that: + + source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation. + +This software is provided 'as is' with no explicit or implied warranties +in respect of its operation, including, but not limited to, correctness +and fitness for purpose. +--------------------------------------------------------------------------- +Issue Date: 20/12/2007 + + This file contains the definitions required to use AES in C. See aesopt.h + for optimisation details. +*/ + +#ifndef _AES_H +#define _AES_H + +#include + +/* This include is used to find 8 & 32 bit unsigned integer types */ +#include "brg_types.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#define AES_128 /* if a fast 128 bit key scheduler is needed */ +#define AES_192 /* if a fast 192 bit key scheduler is needed */ +#define AES_256 /* if a fast 256 bit key scheduler is needed */ +#define AES_VAR /* if variable key size scheduler is needed */ +#define AES_MODES /* if support is needed for modes */ + +/* The following must also be set in assembler files if being used */ + +#define AES_ENCRYPT /* if support for encryption is needed */ +#define AES_DECRYPT /* if support for decryption is needed */ +#define AES_REV_DKS /* define to reverse decryption key schedule */ + +#define AES_BLOCK_SIZE 16 /* the AES block size in bytes */ +#define N_COLS 4 /* the number of columns in the state */ + +/* The key schedule length is 11, 13 or 15 16-byte blocks for 128, */ +/* 192 or 256-bit keys respectively. That is 176, 208 or 240 bytes */ +/* or 44, 52 or 60 32-bit words. */ + +#if defined( AES_VAR ) || defined( AES_256 ) +#define KS_LENGTH 60 +#elif defined( AES_192 ) +#define KS_LENGTH 52 +#else +#define KS_LENGTH 44 +#endif + +#define AES_RETURN INT_RETURN + +/* the character array 'inf' in the following structures is used */ +/* to hold AES context information. This AES code uses cx->inf.b[0] */ +/* to hold the number of rounds multiplied by 16. The other three */ +/* elements can be used by code that implements additional modes */ + +typedef union +{ uint_32t l; + uint_8t b[4]; +} aes_inf; + +typedef struct +{ uint_32t ks[KS_LENGTH]; + aes_inf inf; +} aes_encrypt_ctx; + +typedef struct +{ uint_32t ks[KS_LENGTH]; + aes_inf inf; +} aes_decrypt_ctx; + +/* This routine must be called before first use if non-static */ +/* tables are being used */ + +AES_RETURN aes_init(void); + +/* Key lengths in the range 16 <= key_len <= 32 are given in bytes, */ +/* those in the range 128 <= key_len <= 256 are given in bits */ + +#if defined( AES_ENCRYPT ) + +#if defined( AES_128 ) || defined( AES_VAR) +AES_RETURN aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1]); +#endif + +#if defined( AES_192 ) || defined( AES_VAR) +AES_RETURN aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1]); +#endif + +#if defined( AES_256 ) || defined( AES_VAR) +AES_RETURN aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1]); +#endif + +#if defined( AES_VAR ) +AES_RETURN aes_encrypt_key(const unsigned char *key, int key_len, aes_encrypt_ctx cx[1]); +#endif + +AES_RETURN aes_encrypt(const unsigned char *in, unsigned char *out, const aes_encrypt_ctx cx[1]); + +#endif + +#if defined( AES_DECRYPT ) + +#if defined( AES_128 ) || defined( AES_VAR) +AES_RETURN aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1]); +#endif + +#if defined( AES_192 ) || defined( AES_VAR) +AES_RETURN aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1]); +#endif + +#if defined( AES_256 ) || defined( AES_VAR) +AES_RETURN aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1]); +#endif + +#if defined( AES_VAR ) +AES_RETURN aes_decrypt_key(const unsigned char *key, int key_len, aes_decrypt_ctx cx[1]); +#endif + +AES_RETURN aes_decrypt(const unsigned char *in, unsigned char *out, const aes_decrypt_ctx cx[1]); + +#endif + +#if defined( AES_MODES ) + +/* Multiple calls to the following subroutines for multiple block */ +/* ECB, CBC, CFB, OFB and CTR mode encryption can be used to handle */ +/* long messages incremantally provided that the context AND the iv */ +/* are preserved between all such calls. For the ECB and CBC modes */ +/* each individual call within a series of incremental calls must */ +/* process only full blocks (i.e. len must be a multiple of 16) but */ +/* the CFB, OFB and CTR mode calls can handle multiple incremental */ +/* calls of any length. Each mode is reset when a new AES key is */ +/* set but ECB and CBC operations can be reset without setting a */ +/* new key by setting a new IV value. To reset CFB, OFB and CTR */ +/* without setting the key, aes_mode_reset() must be called and the */ +/* IV must be set. NOTE: All these calls update the IV on exit so */ +/* this has to be reset if a new operation with the same IV as the */ +/* previous one is required (or decryption follows encryption with */ +/* the same IV array). */ + +AES_RETURN aes_test_alignment_detection(unsigned int n); + +AES_RETURN aes_ecb_encrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, const aes_encrypt_ctx cx[1]); + +AES_RETURN aes_ecb_decrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, const aes_decrypt_ctx cx[1]); + +AES_RETURN aes_cbc_encrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *iv, const aes_encrypt_ctx cx[1]); + +AES_RETURN aes_cbc_decrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *iv, const aes_decrypt_ctx cx[1]); + +AES_RETURN aes_mode_reset(aes_encrypt_ctx cx[1]); + +AES_RETURN aes_cfb_encrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *iv, aes_encrypt_ctx cx[1]); + +AES_RETURN aes_cfb_decrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *iv, aes_encrypt_ctx cx[1]); + +#define aes_ofb_encrypt aes_ofb_crypt +#define aes_ofb_decrypt aes_ofb_crypt + +AES_RETURN aes_ofb_crypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *iv, aes_encrypt_ctx cx[1]); + +typedef void cbuf_inc(unsigned char *cbuf); + +#define aes_ctr_encrypt aes_ctr_crypt +#define aes_ctr_decrypt aes_ctr_crypt + +AES_RETURN aes_ctr_crypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *cbuf, cbuf_inc ctr_inc, aes_encrypt_ctx cx[1]); + +#endif + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/SSZipArchive/aes/aes_via_ace.h b/SSZipArchive/aes/aes_via_ace.h new file mode 100755 index 0000000..cb2aa1b --- /dev/null +++ b/SSZipArchive/aes/aes_via_ace.h @@ -0,0 +1,541 @@ +/* +Copyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved. + +The redistribution and use of this software (with or without changes) +is allowed without the payment of fees or royalties provided that: + + source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation. + +This software is provided 'as is' with no explicit or implied warranties +in respect of its operation, including, but not limited to, correctness +and fitness for purpose. +--------------------------------------------------------------------------- +Issue Date: 20/12/2007 +*/ + +#ifndef AES_VIA_ACE_H +#define AES_VIA_ACE_H + +#if defined( _MSC_VER ) +# define INLINE __inline +#elif defined( __GNUC__ ) +# define INLINE static inline +#else +# error VIA ACE requires Microsoft or GNU C +#endif + +#define NEH_GENERATE 1 +#define NEH_LOAD 2 +#define NEH_HYBRID 3 + +#define MAX_READ_ATTEMPTS 1000 + +/* VIA Nehemiah RNG and ACE Feature Mask Values */ + +#define NEH_CPU_IS_VIA 0x00000001 +#define NEH_CPU_READ 0x00000010 +#define NEH_CPU_MASK 0x00000011 + +#define NEH_RNG_PRESENT 0x00000004 +#define NEH_RNG_ENABLED 0x00000008 +#define NEH_ACE_PRESENT 0x00000040 +#define NEH_ACE_ENABLED 0x00000080 +#define NEH_RNG_FLAGS (NEH_RNG_PRESENT | NEH_RNG_ENABLED) +#define NEH_ACE_FLAGS (NEH_ACE_PRESENT | NEH_ACE_ENABLED) +#define NEH_FLAGS_MASK (NEH_RNG_FLAGS | NEH_ACE_FLAGS) + +/* VIA Nehemiah Advanced Cryptography Engine (ACE) Control Word Values */ + +#define NEH_GEN_KEY 0x00000000 /* generate key schedule */ +#define NEH_LOAD_KEY 0x00000080 /* load schedule from memory */ +#define NEH_ENCRYPT 0x00000000 /* encryption */ +#define NEH_DECRYPT 0x00000200 /* decryption */ +#define NEH_KEY128 0x00000000+0x0a /* 128 bit key */ +#define NEH_KEY192 0x00000400+0x0c /* 192 bit key */ +#define NEH_KEY256 0x00000800+0x0e /* 256 bit key */ + +#define NEH_ENC_GEN (NEH_ENCRYPT | NEH_GEN_KEY) +#define NEH_DEC_GEN (NEH_DECRYPT | NEH_GEN_KEY) +#define NEH_ENC_LOAD (NEH_ENCRYPT | NEH_LOAD_KEY) +#define NEH_DEC_LOAD (NEH_DECRYPT | NEH_LOAD_KEY) + +#define NEH_ENC_GEN_DATA {\ + NEH_ENC_GEN | NEH_KEY128, 0, 0, 0,\ + NEH_ENC_GEN | NEH_KEY192, 0, 0, 0,\ + NEH_ENC_GEN | NEH_KEY256, 0, 0, 0 } + +#define NEH_ENC_LOAD_DATA {\ + NEH_ENC_LOAD | NEH_KEY128, 0, 0, 0,\ + NEH_ENC_LOAD | NEH_KEY192, 0, 0, 0,\ + NEH_ENC_LOAD | NEH_KEY256, 0, 0, 0 } + +#define NEH_ENC_HYBRID_DATA {\ + NEH_ENC_GEN | NEH_KEY128, 0, 0, 0,\ + NEH_ENC_LOAD | NEH_KEY192, 0, 0, 0,\ + NEH_ENC_LOAD | NEH_KEY256, 0, 0, 0 } + +#define NEH_DEC_GEN_DATA {\ + NEH_DEC_GEN | NEH_KEY128, 0, 0, 0,\ + NEH_DEC_GEN | NEH_KEY192, 0, 0, 0,\ + NEH_DEC_GEN | NEH_KEY256, 0, 0, 0 } + +#define NEH_DEC_LOAD_DATA {\ + NEH_DEC_LOAD | NEH_KEY128, 0, 0, 0,\ + NEH_DEC_LOAD | NEH_KEY192, 0, 0, 0,\ + NEH_DEC_LOAD | NEH_KEY256, 0, 0, 0 } + +#define NEH_DEC_HYBRID_DATA {\ + NEH_DEC_GEN | NEH_KEY128, 0, 0, 0,\ + NEH_DEC_LOAD | NEH_KEY192, 0, 0, 0,\ + NEH_DEC_LOAD | NEH_KEY256, 0, 0, 0 } + +#define neh_enc_gen_key(x) ((x) == 128 ? (NEH_ENC_GEN | NEH_KEY128) : \ + (x) == 192 ? (NEH_ENC_GEN | NEH_KEY192) : (NEH_ENC_GEN | NEH_KEY256)) + +#define neh_enc_load_key(x) ((x) == 128 ? (NEH_ENC_LOAD | NEH_KEY128) : \ + (x) == 192 ? (NEH_ENC_LOAD | NEH_KEY192) : (NEH_ENC_LOAD | NEH_KEY256)) + +#define neh_enc_hybrid_key(x) ((x) == 128 ? (NEH_ENC_GEN | NEH_KEY128) : \ + (x) == 192 ? (NEH_ENC_LOAD | NEH_KEY192) : (NEH_ENC_LOAD | NEH_KEY256)) + +#define neh_dec_gen_key(x) ((x) == 128 ? (NEH_DEC_GEN | NEH_KEY128) : \ + (x) == 192 ? (NEH_DEC_GEN | NEH_KEY192) : (NEH_DEC_GEN | NEH_KEY256)) + +#define neh_dec_load_key(x) ((x) == 128 ? (NEH_DEC_LOAD | NEH_KEY128) : \ + (x) == 192 ? (NEH_DEC_LOAD | NEH_KEY192) : (NEH_DEC_LOAD | NEH_KEY256)) + +#define neh_dec_hybrid_key(x) ((x) == 128 ? (NEH_DEC_GEN | NEH_KEY128) : \ + (x) == 192 ? (NEH_DEC_LOAD | NEH_KEY192) : (NEH_DEC_LOAD | NEH_KEY256)) + +#if defined( _MSC_VER ) && ( _MSC_VER > 1200 ) +#define aligned_auto(type, name, no, stride) __declspec(align(stride)) type name[no] +#else +#define aligned_auto(type, name, no, stride) \ + unsigned char _##name[no * sizeof(type) + stride]; \ + type *name = (type*)(16 * ((((unsigned long)(_##name)) + stride - 1) / stride)) +#endif + +#if defined( _MSC_VER ) && ( _MSC_VER > 1200 ) +#define aligned_array(type, name, no, stride) __declspec(align(stride)) type name[no] +#elif defined( __GNUC__ ) +#define aligned_array(type, name, no, stride) type name[no] __attribute__ ((aligned(stride))) +#else +#define aligned_array(type, name, no, stride) type name[no] +#endif + +/* VIA ACE codeword */ + +static unsigned char via_flags = 0; + +#if defined ( _MSC_VER ) && ( _MSC_VER > 800 ) + +#define NEH_REKEY __asm pushfd __asm popfd +#define NEH_AES __asm _emit 0xf3 __asm _emit 0x0f __asm _emit 0xa7 +#define NEH_ECB NEH_AES __asm _emit 0xc8 +#define NEH_CBC NEH_AES __asm _emit 0xd0 +#define NEH_CFB NEH_AES __asm _emit 0xe0 +#define NEH_OFB NEH_AES __asm _emit 0xe8 +#define NEH_RNG __asm _emit 0x0f __asm _emit 0xa7 __asm _emit 0xc0 + +INLINE int has_cpuid(void) +{ char ret_value; + __asm + { pushfd /* save EFLAGS register */ + mov eax,[esp] /* copy it to eax */ + mov edx,0x00200000 /* CPUID bit position */ + xor eax,edx /* toggle the CPUID bit */ + push eax /* attempt to set EFLAGS to */ + popfd /* the new value */ + pushfd /* get the new EFLAGS value */ + pop eax /* into eax */ + xor eax,[esp] /* xor with original value */ + and eax,edx /* has CPUID bit changed? */ + setne al /* set to 1 if we have been */ + mov ret_value,al /* able to change it */ + popfd /* restore original EFLAGS */ + } + return (int)ret_value; +} + +INLINE int is_via_cpu(void) +{ char ret_value; + __asm + { push ebx + xor eax,eax /* use CPUID to get vendor */ + cpuid /* identity string */ + xor eax,eax /* is it "CentaurHauls" ? */ + sub ebx,0x746e6543 /* 'Cent' */ + or eax,ebx + sub edx,0x48727561 /* 'aurH' */ + or eax,edx + sub ecx,0x736c7561 /* 'auls' */ + or eax,ecx + sete al /* set to 1 if it is VIA ID */ + mov dl,NEH_CPU_READ /* mark CPU type as read */ + or dl,al /* & store result in flags */ + mov [via_flags],dl /* set VIA detected flag */ + mov ret_value,al /* able to change it */ + pop ebx + } + return (int)ret_value; +} + +INLINE int read_via_flags(void) +{ char ret_value = 0; + __asm + { mov eax,0xC0000000 /* Centaur extended CPUID */ + cpuid + mov edx,0xc0000001 /* >= 0xc0000001 if support */ + cmp eax,edx /* for VIA extended feature */ + jnae no_rng /* flags is available */ + mov eax,edx /* read Centaur extended */ + cpuid /* feature flags */ + mov eax,NEH_FLAGS_MASK /* mask out and save */ + and eax,edx /* the RNG and ACE flags */ + or [via_flags],al /* present & enabled flags */ + mov ret_value,al /* able to change it */ +no_rng: + } + return (int)ret_value; +} + +INLINE unsigned int via_rng_in(void *buf) +{ char ret_value = 0x1f; + __asm + { push edi + mov edi,buf /* input buffer address */ + xor edx,edx /* try to fetch 8 bytes */ + NEH_RNG /* do RNG read operation */ + and ret_value,al /* count of bytes returned */ + pop edi + } + return (int)ret_value; +} + +INLINE void via_ecb_op5( + const void *k, const void *c, const void *s, void *d, int l) +{ __asm + { push ebx + NEH_REKEY + mov ebx, (k) + mov edx, (c) + mov esi, (s) + mov edi, (d) + mov ecx, (l) + NEH_ECB + pop ebx + } +} + +INLINE void via_cbc_op6( + const void *k, const void *c, const void *s, void *d, int l, void *v) +{ __asm + { push ebx + NEH_REKEY + mov ebx, (k) + mov edx, (c) + mov esi, (s) + mov edi, (d) + mov ecx, (l) + mov eax, (v) + NEH_CBC + pop ebx + } +} + +INLINE void via_cbc_op7( + const void *k, const void *c, const void *s, void *d, int l, void *v, void *w) +{ __asm + { push ebx + NEH_REKEY + mov ebx, (k) + mov edx, (c) + mov esi, (s) + mov edi, (d) + mov ecx, (l) + mov eax, (v) + NEH_CBC + mov esi, eax + mov edi, (w) + movsd + movsd + movsd + movsd + pop ebx + } +} + +INLINE void via_cfb_op6( + const void *k, const void *c, const void *s, void *d, int l, void *v) +{ __asm + { push ebx + NEH_REKEY + mov ebx, (k) + mov edx, (c) + mov esi, (s) + mov edi, (d) + mov ecx, (l) + mov eax, (v) + NEH_CFB + pop ebx + } +} + +INLINE void via_cfb_op7( + const void *k, const void *c, const void *s, void *d, int l, void *v, void *w) +{ __asm + { push ebx + NEH_REKEY + mov ebx, (k) + mov edx, (c) + mov esi, (s) + mov edi, (d) + mov ecx, (l) + mov eax, (v) + NEH_CFB + mov esi, eax + mov edi, (w) + movsd + movsd + movsd + movsd + pop ebx + } +} + +INLINE void via_ofb_op6( + const void *k, const void *c, const void *s, void *d, int l, void *v) +{ __asm + { push ebx + NEH_REKEY + mov ebx, (k) + mov edx, (c) + mov esi, (s) + mov edi, (d) + mov ecx, (l) + mov eax, (v) + NEH_OFB + pop ebx + } +} + +#elif defined( __GNUC__ ) + +#define NEH_REKEY asm("pushfl\n popfl\n\t") +#define NEH_ECB asm(".byte 0xf3, 0x0f, 0xa7, 0xc8\n\t") +#define NEH_CBC asm(".byte 0xf3, 0x0f, 0xa7, 0xd0\n\t") +#define NEH_CFB asm(".byte 0xf3, 0x0f, 0xa7, 0xe0\n\t") +#define NEH_OFB asm(".byte 0xf3, 0x0f, 0xa7, 0xe8\n\t") +#define NEH_RNG asm(".byte 0x0f, 0xa7, 0xc0\n\t"); + +INLINE int has_cpuid(void) +{ int val; + asm("pushfl\n\t"); + asm("movl 0(%esp),%eax\n\t"); + asm("xor $0x00200000,%eax\n\t"); + asm("pushl %eax\n\t"); + asm("popfl\n\t"); + asm("pushfl\n\t"); + asm("popl %eax\n\t"); + asm("xorl 0(%esp),%edx\n\t"); + asm("andl $0x00200000,%eax\n\t"); + asm("movl %%eax,%0\n\t" : "=m" (val)); + asm("popfl\n\t"); + return val ? 1 : 0; +} + +INLINE int is_via_cpu(void) +{ int val; + asm("pushl %ebx\n\t"); + asm("xorl %eax,%eax\n\t"); + asm("cpuid\n\t"); + asm("xorl %eax,%eax\n\t"); + asm("subl $0x746e6543,%ebx\n\t"); + asm("orl %ebx,%eax\n\t"); + asm("subl $0x48727561,%edx\n\t"); + asm("orl %edx,%eax\n\t"); + asm("subl $0x736c7561,%ecx\n\t"); + asm("orl %ecx,%eax\n\t"); + asm("movl %%eax,%0\n\t" : "=m" (val)); + asm("popl %ebx\n\t"); + val = (val ? 0 : 1); + via_flags = (val | NEH_CPU_READ); + return val; +} + +INLINE int read_via_flags(void) +{ unsigned char val; + asm("movl $0xc0000000,%eax\n\t"); + asm("cpuid\n\t"); + asm("movl $0xc0000001,%edx\n\t"); + asm("cmpl %edx,%eax\n\t"); + asm("setae %al\n\t"); + asm("movb %%al,%0\n\t" : "=m" (val)); + if(!val) return 0; + asm("movl $0xc0000001,%eax\n\t"); + asm("cpuid\n\t"); + asm("movb %%dl,%0\n\t" : "=m" (val)); + val &= NEH_FLAGS_MASK; + via_flags |= val; + return (int) val; +} + +INLINE int via_rng_in(void *buf) +{ int val; + asm("pushl %edi\n\t"); + asm("movl %0,%%edi\n\t" : : "m" (buf)); + asm("xorl %edx,%edx\n\t"); + NEH_RNG + asm("andl $0x0000001f,%eax\n\t"); + asm("movl %%eax,%0\n\t" : "=m" (val)); + asm("popl %edi\n\t"); + return val; +} + +INLINE volatile void via_ecb_op5( + const void *k, const void *c, const void *s, void *d, int l) +{ + asm("pushl %ebx\n\t"); + NEH_REKEY; + asm("movl %0, %%ebx\n\t" : : "m" (k)); + asm("movl %0, %%edx\n\t" : : "m" (c)); + asm("movl %0, %%esi\n\t" : : "m" (s)); + asm("movl %0, %%edi\n\t" : : "m" (d)); + asm("movl %0, %%ecx\n\t" : : "m" (l)); + NEH_ECB; + asm("popl %ebx\n\t"); +} + +INLINE volatile void via_cbc_op6( + const void *k, const void *c, const void *s, void *d, int l, void *v) +{ + asm("pushl %ebx\n\t"); + NEH_REKEY; + asm("movl %0, %%ebx\n\t" : : "m" (k)); + asm("movl %0, %%edx\n\t" : : "m" (c)); + asm("movl %0, %%esi\n\t" : : "m" (s)); + asm("movl %0, %%edi\n\t" : : "m" (d)); + asm("movl %0, %%ecx\n\t" : : "m" (l)); + asm("movl %0, %%eax\n\t" : : "m" (v)); + NEH_CBC; + asm("popl %ebx\n\t"); +} + +INLINE volatile void via_cbc_op7( + const void *k, const void *c, const void *s, void *d, int l, void *v, void *w) +{ + asm("pushl %ebx\n\t"); + NEH_REKEY; + asm("movl %0, %%ebx\n\t" : : "m" (k)); + asm("movl %0, %%edx\n\t" : : "m" (c)); + asm("movl %0, %%esi\n\t" : : "m" (s)); + asm("movl %0, %%edi\n\t" : : "m" (d)); + asm("movl %0, %%ecx\n\t" : : "m" (l)); + asm("movl %0, %%eax\n\t" : : "m" (v)); + NEH_CBC; + asm("movl %eax,%esi\n\t"); + asm("movl %0, %%edi\n\t" : : "m" (w)); + asm("movsl; movsl; movsl; movsl\n\t"); + asm("popl %ebx\n\t"); +} + +INLINE volatile void via_cfb_op6( + const void *k, const void *c, const void *s, void *d, int l, void *v) +{ + asm("pushl %ebx\n\t"); + NEH_REKEY; + asm("movl %0, %%ebx\n\t" : : "m" (k)); + asm("movl %0, %%edx\n\t" : : "m" (c)); + asm("movl %0, %%esi\n\t" : : "m" (s)); + asm("movl %0, %%edi\n\t" : : "m" (d)); + asm("movl %0, %%ecx\n\t" : : "m" (l)); + asm("movl %0, %%eax\n\t" : : "m" (v)); + NEH_CFB; + asm("popl %ebx\n\t"); +} + +INLINE volatile void via_cfb_op7( + const void *k, const void *c, const void *s, void *d, int l, void *v, void *w) +{ + asm("pushl %ebx\n\t"); + NEH_REKEY; + asm("movl %0, %%ebx\n\t" : : "m" (k)); + asm("movl %0, %%edx\n\t" : : "m" (c)); + asm("movl %0, %%esi\n\t" : : "m" (s)); + asm("movl %0, %%edi\n\t" : : "m" (d)); + asm("movl %0, %%ecx\n\t" : : "m" (l)); + asm("movl %0, %%eax\n\t" : : "m" (v)); + NEH_CFB; + asm("movl %eax,%esi\n\t"); + asm("movl %0, %%edi\n\t" : : "m" (w)); + asm("movsl; movsl; movsl; movsl\n\t"); + asm("popl %ebx\n\t"); +} + +INLINE volatile void via_ofb_op6( + const void *k, const void *c, const void *s, void *d, int l, void *v) +{ + asm("pushl %ebx\n\t"); + NEH_REKEY; + asm("movl %0, %%ebx\n\t" : : "m" (k)); + asm("movl %0, %%edx\n\t" : : "m" (c)); + asm("movl %0, %%esi\n\t" : : "m" (s)); + asm("movl %0, %%edi\n\t" : : "m" (d)); + asm("movl %0, %%ecx\n\t" : : "m" (l)); + asm("movl %0, %%eax\n\t" : : "m" (v)); + NEH_OFB; + asm("popl %ebx\n\t"); +} + +#else +#error VIA ACE is not available with this compiler +#endif + +INLINE int via_ace_test(void) +{ + return has_cpuid() && is_via_cpu() && ((read_via_flags() & NEH_ACE_FLAGS) == NEH_ACE_FLAGS); +} + +#define VIA_ACE_AVAILABLE (((via_flags & NEH_ACE_FLAGS) == NEH_ACE_FLAGS) \ + || (via_flags & NEH_CPU_READ) && (via_flags & NEH_CPU_IS_VIA) || via_ace_test()) + +INLINE int via_rng_test(void) +{ + return has_cpuid() && is_via_cpu() && ((read_via_flags() & NEH_RNG_FLAGS) == NEH_RNG_FLAGS); +} + +#define VIA_RNG_AVAILABLE (((via_flags & NEH_RNG_FLAGS) == NEH_RNG_FLAGS) \ + || (via_flags & NEH_CPU_READ) && (via_flags & NEH_CPU_IS_VIA) || via_rng_test()) + +INLINE int read_via_rng(void *buf, int count) +{ int nbr, max_reads, lcnt = count; + unsigned char *p, *q; + aligned_auto(unsigned char, bp, 64, 16); + + if(!VIA_RNG_AVAILABLE) + return 0; + + do + { + max_reads = MAX_READ_ATTEMPTS; + do + nbr = via_rng_in(bp); + while + (nbr == 0 && --max_reads); + + lcnt -= nbr; + p = (unsigned char*)buf; q = bp; + while(nbr--) + *p++ = *q++; + } + while + (lcnt && max_reads); + + return count - lcnt; +} + +#endif diff --git a/SSZipArchive/aes/aescrypt.c b/SSZipArchive/aes/aescrypt.c new file mode 100755 index 0000000..99141cf --- /dev/null +++ b/SSZipArchive/aes/aescrypt.c @@ -0,0 +1,294 @@ +/* +--------------------------------------------------------------------------- +Copyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved. + +The redistribution and use of this software (with or without changes) +is allowed without the payment of fees or royalties provided that: + + source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation. + +This software is provided 'as is' with no explicit or implied warranties +in respect of its operation, including, but not limited to, correctness +and fitness for purpose. +--------------------------------------------------------------------------- +Issue Date: 20/12/2007 +*/ + +#include "aesopt.h" +#include "aestab.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#define si(y,x,k,c) (s(y,c) = word_in(x, c) ^ (k)[c]) +#define so(y,x,c) word_out(y, c, s(x,c)) + +#if defined(ARRAYS) +#define locals(y,x) x[4],y[4] +#else +#define locals(y,x) x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3 +#endif + +#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ + s(y,2) = s(x,2); s(y,3) = s(x,3); +#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3) +#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3) +#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3) + +#if ( FUNCS_IN_C & ENCRYPTION_IN_C ) + +/* Visual C++ .Net v7.1 provides the fastest encryption code when using + Pentium optimiation with small code but this is poor for decryption + so we need to control this with the following VC++ pragmas +*/ + +#if defined( _MSC_VER ) && !defined( _WIN64 ) +#pragma optimize( "s", on ) +#endif + +/* Given the column (c) of the output state variable, the following + macros give the input state variables which are needed in its + computation for each row (r) of the state. All the alternative + macros give the same end values but expand into different ways + of calculating these values. In particular the complex macro + used for dynamically variable block sizes is designed to expand + to a compile time constant whenever possible but will expand to + conditional clauses on some branches (I am grateful to Frank + Yellin for this construction) +*/ + +#define fwd_var(x,r,c)\ + ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\ + : r == 1 ? ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))\ + : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\ + : ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))) + +#if defined(FT4_SET) +#undef dec_fmvars +#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,n),fwd_var,rf1,c)) +#elif defined(FT1_SET) +#undef dec_fmvars +#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(f,n),fwd_var,rf1,c)) +#else +#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ fwd_mcol(no_table(x,t_use(s,box),fwd_var,rf1,c))) +#endif + +#if defined(FL4_SET) +#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,l),fwd_var,rf1,c)) +#elif defined(FL1_SET) +#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(f,l),fwd_var,rf1,c)) +#else +#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ no_table(x,t_use(s,box),fwd_var,rf1,c)) +#endif + +AES_RETURN aes_encrypt(const unsigned char *in, unsigned char *out, const aes_encrypt_ctx cx[1]) +{ uint_32t locals(b0, b1); + const uint_32t *kp; +#if defined( dec_fmvars ) + dec_fmvars; /* declare variables for fwd_mcol() if needed */ +#endif + + if( cx->inf.b[0] != 10 * 16 && cx->inf.b[0] != 12 * 16 && cx->inf.b[0] != 14 * 16 ) + return EXIT_FAILURE; + + kp = cx->ks; + state_in(b0, in, kp); + +#if (ENC_UNROLL == FULL) + + switch(cx->inf.b[0]) + { + case 14 * 16: + round(fwd_rnd, b1, b0, kp + 1 * N_COLS); + round(fwd_rnd, b0, b1, kp + 2 * N_COLS); + kp += 2 * N_COLS; + case 12 * 16: + round(fwd_rnd, b1, b0, kp + 1 * N_COLS); + round(fwd_rnd, b0, b1, kp + 2 * N_COLS); + kp += 2 * N_COLS; + case 10 * 16: + round(fwd_rnd, b1, b0, kp + 1 * N_COLS); + round(fwd_rnd, b0, b1, kp + 2 * N_COLS); + round(fwd_rnd, b1, b0, kp + 3 * N_COLS); + round(fwd_rnd, b0, b1, kp + 4 * N_COLS); + round(fwd_rnd, b1, b0, kp + 5 * N_COLS); + round(fwd_rnd, b0, b1, kp + 6 * N_COLS); + round(fwd_rnd, b1, b0, kp + 7 * N_COLS); + round(fwd_rnd, b0, b1, kp + 8 * N_COLS); + round(fwd_rnd, b1, b0, kp + 9 * N_COLS); + round(fwd_lrnd, b0, b1, kp +10 * N_COLS); + } + +#else + +#if (ENC_UNROLL == PARTIAL) + { uint_32t rnd; + for(rnd = 0; rnd < (cx->inf.b[0] >> 5) - 1; ++rnd) + { + kp += N_COLS; + round(fwd_rnd, b1, b0, kp); + kp += N_COLS; + round(fwd_rnd, b0, b1, kp); + } + kp += N_COLS; + round(fwd_rnd, b1, b0, kp); +#else + { uint_32t rnd; + for(rnd = 0; rnd < (cx->inf.b[0] >> 4) - 1; ++rnd) + { + kp += N_COLS; + round(fwd_rnd, b1, b0, kp); + l_copy(b0, b1); + } +#endif + kp += N_COLS; + round(fwd_lrnd, b0, b1, kp); + } +#endif + + state_out(out, b0); + return EXIT_SUCCESS; +} + +#endif + +#if ( FUNCS_IN_C & DECRYPTION_IN_C) + +/* Visual C++ .Net v7.1 provides the fastest encryption code when using + Pentium optimiation with small code but this is poor for decryption + so we need to control this with the following VC++ pragmas +*/ + +#if defined( _MSC_VER ) && !defined( _WIN64 ) +#pragma optimize( "t", on ) +#endif + +/* Given the column (c) of the output state variable, the following + macros give the input state variables which are needed in its + computation for each row (r) of the state. All the alternative + macros give the same end values but expand into different ways + of calculating these values. In particular the complex macro + used for dynamically variable block sizes is designed to expand + to a compile time constant whenever possible but will expand to + conditional clauses on some branches (I am grateful to Frank + Yellin for this construction) +*/ + +#define inv_var(x,r,c)\ + ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\ + : r == 1 ? ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))\ + : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\ + : ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))) + +#if defined(IT4_SET) +#undef dec_imvars +#define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,n),inv_var,rf1,c)) +#elif defined(IT1_SET) +#undef dec_imvars +#define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(i,n),inv_var,rf1,c)) +#else +#define inv_rnd(y,x,k,c) (s(y,c) = inv_mcol((k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c))) +#endif + +#if defined(IL4_SET) +#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,l),inv_var,rf1,c)) +#elif defined(IL1_SET) +#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(i,l),inv_var,rf1,c)) +#else +#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c)) +#endif + +/* This code can work with the decryption key schedule in the */ +/* order that is used for encrytpion (where the 1st decryption */ +/* round key is at the high end ot the schedule) or with a key */ +/* schedule that has been reversed to put the 1st decryption */ +/* round key at the low end of the schedule in memory (when */ +/* AES_REV_DKS is defined) */ + +#ifdef AES_REV_DKS +#define key_ofs 0 +#define rnd_key(n) (kp + n * N_COLS) +#else +#define key_ofs 1 +#define rnd_key(n) (kp - n * N_COLS) +#endif + +AES_RETURN aes_decrypt(const unsigned char *in, unsigned char *out, const aes_decrypt_ctx cx[1]) +{ uint_32t locals(b0, b1); +#if defined( dec_imvars ) + dec_imvars; /* declare variables for inv_mcol() if needed */ +#endif + const uint_32t *kp; + + if( cx->inf.b[0] != 10 * 16 && cx->inf.b[0] != 12 * 16 && cx->inf.b[0] != 14 * 16 ) + return EXIT_FAILURE; + + kp = cx->ks + (key_ofs ? (cx->inf.b[0] >> 2) : 0); + state_in(b0, in, kp); + +#if (DEC_UNROLL == FULL) + + kp = cx->ks + (key_ofs ? 0 : (cx->inf.b[0] >> 2)); + switch(cx->inf.b[0]) + { + case 14 * 16: + round(inv_rnd, b1, b0, rnd_key(-13)); + round(inv_rnd, b0, b1, rnd_key(-12)); + case 12 * 16: + round(inv_rnd, b1, b0, rnd_key(-11)); + round(inv_rnd, b0, b1, rnd_key(-10)); + case 10 * 16: + round(inv_rnd, b1, b0, rnd_key(-9)); + round(inv_rnd, b0, b1, rnd_key(-8)); + round(inv_rnd, b1, b0, rnd_key(-7)); + round(inv_rnd, b0, b1, rnd_key(-6)); + round(inv_rnd, b1, b0, rnd_key(-5)); + round(inv_rnd, b0, b1, rnd_key(-4)); + round(inv_rnd, b1, b0, rnd_key(-3)); + round(inv_rnd, b0, b1, rnd_key(-2)); + round(inv_rnd, b1, b0, rnd_key(-1)); + round(inv_lrnd, b0, b1, rnd_key( 0)); + } + +#else + +#if (DEC_UNROLL == PARTIAL) + { uint_32t rnd; + for(rnd = 0; rnd < (cx->inf.b[0] >> 5) - 1; ++rnd) + { + kp = rnd_key(1); + round(inv_rnd, b1, b0, kp); + kp = rnd_key(1); + round(inv_rnd, b0, b1, kp); + } + kp = rnd_key(1); + round(inv_rnd, b1, b0, kp); +#else + { uint_32t rnd; + for(rnd = 0; rnd < (cx->inf.b[0] >> 4) - 1; ++rnd) + { + kp = rnd_key(1); + round(inv_rnd, b1, b0, kp); + l_copy(b0, b1); + } +#endif + kp = rnd_key(1); + round(inv_lrnd, b0, b1, kp); + } +#endif + + state_out(out, b0); + return EXIT_SUCCESS; +} + +#endif + +#if defined(__cplusplus) +} +#endif diff --git a/SSZipArchive/aes/aeskey.c b/SSZipArchive/aes/aeskey.c new file mode 100755 index 0000000..0378f0c --- /dev/null +++ b/SSZipArchive/aes/aeskey.c @@ -0,0 +1,548 @@ +/* +--------------------------------------------------------------------------- +Copyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved. + +The redistribution and use of this software (with or without changes) +is allowed without the payment of fees or royalties provided that: + + source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation. + +This software is provided 'as is' with no explicit or implied warranties +in respect of its operation, including, but not limited to, correctness +and fitness for purpose. +--------------------------------------------------------------------------- +Issue Date: 20/12/2007 +*/ + +#include "aesopt.h" +#include "aestab.h" + +#ifdef USE_VIA_ACE_IF_PRESENT +# include "aes_via_ace.h" +#endif + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* Initialise the key schedule from the user supplied key. The key + length can be specified in bytes, with legal values of 16, 24 + and 32, or in bits, with legal values of 128, 192 and 256. These + values correspond with Nk values of 4, 6 and 8 respectively. + + The following macros implement a single cycle in the key + schedule generation process. The number of cycles needed + for each cx->n_col and nk value is: + + nk = 4 5 6 7 8 + ------------------------------ + cx->n_col = 4 10 9 8 7 7 + cx->n_col = 5 14 11 10 9 9 + cx->n_col = 6 19 15 12 11 11 + cx->n_col = 7 21 19 16 13 14 + cx->n_col = 8 29 23 19 17 14 +*/ + +#if defined( REDUCE_CODE_SIZE ) +# define ls_box ls_sub + uint_32t ls_sub(const uint_32t t, const uint_32t n); +# define inv_mcol im_sub + uint_32t im_sub(const uint_32t x); +# ifdef ENC_KS_UNROLL +# undef ENC_KS_UNROLL +# endif +# ifdef DEC_KS_UNROLL +# undef DEC_KS_UNROLL +# endif +#endif + +#if (FUNCS_IN_C & ENC_KEYING_IN_C) + +#if defined(AES_128) || defined( AES_VAR ) + +#define ke4(k,i) \ +{ k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; \ + k[4*(i)+5] = ss[1] ^= ss[0]; \ + k[4*(i)+6] = ss[2] ^= ss[1]; \ + k[4*(i)+7] = ss[3] ^= ss[2]; \ +} + +AES_RETURN aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1]) +{ uint_32t ss[4]; + + cx->ks[0] = ss[0] = word_in(key, 0); + cx->ks[1] = ss[1] = word_in(key, 1); + cx->ks[2] = ss[2] = word_in(key, 2); + cx->ks[3] = ss[3] = word_in(key, 3); + +#ifdef ENC_KS_UNROLL + ke4(cx->ks, 0); ke4(cx->ks, 1); + ke4(cx->ks, 2); ke4(cx->ks, 3); + ke4(cx->ks, 4); ke4(cx->ks, 5); + ke4(cx->ks, 6); ke4(cx->ks, 7); + ke4(cx->ks, 8); +#else + { uint_32t i; + for(i = 0; i < 9; ++i) + ke4(cx->ks, i); + } +#endif + ke4(cx->ks, 9); + cx->inf.l = 0; + cx->inf.b[0] = 10 * 16; + +#ifdef USE_VIA_ACE_IF_PRESENT + if(VIA_ACE_AVAILABLE) + cx->inf.b[1] = 0xff; +#endif + return EXIT_SUCCESS; +} + +#endif + +#if defined(AES_192) || defined( AES_VAR ) + +#define kef6(k,i) \ +{ k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; \ + k[6*(i)+ 7] = ss[1] ^= ss[0]; \ + k[6*(i)+ 8] = ss[2] ^= ss[1]; \ + k[6*(i)+ 9] = ss[3] ^= ss[2]; \ +} + +#define ke6(k,i) \ +{ kef6(k,i); \ + k[6*(i)+10] = ss[4] ^= ss[3]; \ + k[6*(i)+11] = ss[5] ^= ss[4]; \ +} + +AES_RETURN aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1]) +{ uint_32t ss[6]; + + cx->ks[0] = ss[0] = word_in(key, 0); + cx->ks[1] = ss[1] = word_in(key, 1); + cx->ks[2] = ss[2] = word_in(key, 2); + cx->ks[3] = ss[3] = word_in(key, 3); + cx->ks[4] = ss[4] = word_in(key, 4); + cx->ks[5] = ss[5] = word_in(key, 5); + +#ifdef ENC_KS_UNROLL + ke6(cx->ks, 0); ke6(cx->ks, 1); + ke6(cx->ks, 2); ke6(cx->ks, 3); + ke6(cx->ks, 4); ke6(cx->ks, 5); + ke6(cx->ks, 6); +#else + { uint_32t i; + for(i = 0; i < 7; ++i) + ke6(cx->ks, i); + } +#endif + kef6(cx->ks, 7); + cx->inf.l = 0; + cx->inf.b[0] = 12 * 16; + +#ifdef USE_VIA_ACE_IF_PRESENT + if(VIA_ACE_AVAILABLE) + cx->inf.b[1] = 0xff; +#endif + return EXIT_SUCCESS; +} + +#endif + +#if defined(AES_256) || defined( AES_VAR ) + +#define kef8(k,i) \ +{ k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; \ + k[8*(i)+ 9] = ss[1] ^= ss[0]; \ + k[8*(i)+10] = ss[2] ^= ss[1]; \ + k[8*(i)+11] = ss[3] ^= ss[2]; \ +} + +#define ke8(k,i) \ +{ kef8(k,i); \ + k[8*(i)+12] = ss[4] ^= ls_box(ss[3],0); \ + k[8*(i)+13] = ss[5] ^= ss[4]; \ + k[8*(i)+14] = ss[6] ^= ss[5]; \ + k[8*(i)+15] = ss[7] ^= ss[6]; \ +} + +AES_RETURN aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1]) +{ uint_32t ss[8]; + + cx->ks[0] = ss[0] = word_in(key, 0); + cx->ks[1] = ss[1] = word_in(key, 1); + cx->ks[2] = ss[2] = word_in(key, 2); + cx->ks[3] = ss[3] = word_in(key, 3); + cx->ks[4] = ss[4] = word_in(key, 4); + cx->ks[5] = ss[5] = word_in(key, 5); + cx->ks[6] = ss[6] = word_in(key, 6); + cx->ks[7] = ss[7] = word_in(key, 7); + +#ifdef ENC_KS_UNROLL + ke8(cx->ks, 0); ke8(cx->ks, 1); + ke8(cx->ks, 2); ke8(cx->ks, 3); + ke8(cx->ks, 4); ke8(cx->ks, 5); +#else + { uint_32t i; + for(i = 0; i < 6; ++i) + ke8(cx->ks, i); + } +#endif + kef8(cx->ks, 6); + cx->inf.l = 0; + cx->inf.b[0] = 14 * 16; + +#ifdef USE_VIA_ACE_IF_PRESENT + if(VIA_ACE_AVAILABLE) + cx->inf.b[1] = 0xff; +#endif + return EXIT_SUCCESS; +} + +#endif + +#if defined( AES_VAR ) + +AES_RETURN aes_encrypt_key(const unsigned char *key, int key_len, aes_encrypt_ctx cx[1]) +{ + switch(key_len) + { + case 16: case 128: return aes_encrypt_key128(key, cx); + case 24: case 192: return aes_encrypt_key192(key, cx); + case 32: case 256: return aes_encrypt_key256(key, cx); + default: return EXIT_FAILURE; + } +} + +#endif + +#endif + +#if (FUNCS_IN_C & DEC_KEYING_IN_C) + +/* this is used to store the decryption round keys */ +/* in forward or reverse order */ + +#ifdef AES_REV_DKS +#define v(n,i) ((n) - (i) + 2 * ((i) & 3)) +#else +#define v(n,i) (i) +#endif + +#if DEC_ROUND == NO_TABLES +#define ff(x) (x) +#else +#define ff(x) inv_mcol(x) +#if defined( dec_imvars ) +#define d_vars dec_imvars +#endif +#endif + +#if defined(AES_128) || defined( AES_VAR ) + +#define k4e(k,i) \ +{ k[v(40,(4*(i))+4)] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; \ + k[v(40,(4*(i))+5)] = ss[1] ^= ss[0]; \ + k[v(40,(4*(i))+6)] = ss[2] ^= ss[1]; \ + k[v(40,(4*(i))+7)] = ss[3] ^= ss[2]; \ +} + +#if 1 + +#define kdf4(k,i) \ +{ ss[0] = ss[0] ^ ss[2] ^ ss[1] ^ ss[3]; \ + ss[1] = ss[1] ^ ss[3]; \ + ss[2] = ss[2] ^ ss[3]; \ + ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; \ + ss[i % 4] ^= ss[4]; \ + ss[4] ^= k[v(40,(4*(i)))]; k[v(40,(4*(i))+4)] = ff(ss[4]); \ + ss[4] ^= k[v(40,(4*(i))+1)]; k[v(40,(4*(i))+5)] = ff(ss[4]); \ + ss[4] ^= k[v(40,(4*(i))+2)]; k[v(40,(4*(i))+6)] = ff(ss[4]); \ + ss[4] ^= k[v(40,(4*(i))+3)]; k[v(40,(4*(i))+7)] = ff(ss[4]); \ +} + +#define kd4(k,i) \ +{ ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; \ + ss[i % 4] ^= ss[4]; ss[4] = ff(ss[4]); \ + k[v(40,(4*(i))+4)] = ss[4] ^= k[v(40,(4*(i)))]; \ + k[v(40,(4*(i))+5)] = ss[4] ^= k[v(40,(4*(i))+1)]; \ + k[v(40,(4*(i))+6)] = ss[4] ^= k[v(40,(4*(i))+2)]; \ + k[v(40,(4*(i))+7)] = ss[4] ^= k[v(40,(4*(i))+3)]; \ +} + +#define kdl4(k,i) \ +{ ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; ss[i % 4] ^= ss[4]; \ + k[v(40,(4*(i))+4)] = (ss[0] ^= ss[1]) ^ ss[2] ^ ss[3]; \ + k[v(40,(4*(i))+5)] = ss[1] ^ ss[3]; \ + k[v(40,(4*(i))+6)] = ss[0]; \ + k[v(40,(4*(i))+7)] = ss[1]; \ +} + +#else + +#define kdf4(k,i) \ +{ ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[v(40,(4*(i))+ 4)] = ff(ss[0]); \ + ss[1] ^= ss[0]; k[v(40,(4*(i))+ 5)] = ff(ss[1]); \ + ss[2] ^= ss[1]; k[v(40,(4*(i))+ 6)] = ff(ss[2]); \ + ss[3] ^= ss[2]; k[v(40,(4*(i))+ 7)] = ff(ss[3]); \ +} + +#define kd4(k,i) \ +{ ss[4] = ls_box(ss[3],3) ^ t_use(r,c)[i]; \ + ss[0] ^= ss[4]; ss[4] = ff(ss[4]); k[v(40,(4*(i))+ 4)] = ss[4] ^= k[v(40,(4*(i)))]; \ + ss[1] ^= ss[0]; k[v(40,(4*(i))+ 5)] = ss[4] ^= k[v(40,(4*(i))+ 1)]; \ + ss[2] ^= ss[1]; k[v(40,(4*(i))+ 6)] = ss[4] ^= k[v(40,(4*(i))+ 2)]; \ + ss[3] ^= ss[2]; k[v(40,(4*(i))+ 7)] = ss[4] ^= k[v(40,(4*(i))+ 3)]; \ +} + +#define kdl4(k,i) \ +{ ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[v(40,(4*(i))+ 4)] = ss[0]; \ + ss[1] ^= ss[0]; k[v(40,(4*(i))+ 5)] = ss[1]; \ + ss[2] ^= ss[1]; k[v(40,(4*(i))+ 6)] = ss[2]; \ + ss[3] ^= ss[2]; k[v(40,(4*(i))+ 7)] = ss[3]; \ +} + +#endif + +AES_RETURN aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1]) +{ uint_32t ss[5]; +#if defined( d_vars ) + d_vars; +#endif + cx->ks[v(40,(0))] = ss[0] = word_in(key, 0); + cx->ks[v(40,(1))] = ss[1] = word_in(key, 1); + cx->ks[v(40,(2))] = ss[2] = word_in(key, 2); + cx->ks[v(40,(3))] = ss[3] = word_in(key, 3); + +#ifdef DEC_KS_UNROLL + kdf4(cx->ks, 0); kd4(cx->ks, 1); + kd4(cx->ks, 2); kd4(cx->ks, 3); + kd4(cx->ks, 4); kd4(cx->ks, 5); + kd4(cx->ks, 6); kd4(cx->ks, 7); + kd4(cx->ks, 8); kdl4(cx->ks, 9); +#else + { uint_32t i; + for(i = 0; i < 10; ++i) + k4e(cx->ks, i); +#if !(DEC_ROUND == NO_TABLES) + for(i = N_COLS; i < 10 * N_COLS; ++i) + cx->ks[i] = inv_mcol(cx->ks[i]); +#endif + } +#endif + cx->inf.l = 0; + cx->inf.b[0] = 10 * 16; + +#ifdef USE_VIA_ACE_IF_PRESENT + if(VIA_ACE_AVAILABLE) + cx->inf.b[1] = 0xff; +#endif + return EXIT_SUCCESS; +} + +#endif + +#if defined(AES_192) || defined( AES_VAR ) + +#define k6ef(k,i) \ +{ k[v(48,(6*(i))+ 6)] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; \ + k[v(48,(6*(i))+ 7)] = ss[1] ^= ss[0]; \ + k[v(48,(6*(i))+ 8)] = ss[2] ^= ss[1]; \ + k[v(48,(6*(i))+ 9)] = ss[3] ^= ss[2]; \ +} + +#define k6e(k,i) \ +{ k6ef(k,i); \ + k[v(48,(6*(i))+10)] = ss[4] ^= ss[3]; \ + k[v(48,(6*(i))+11)] = ss[5] ^= ss[4]; \ +} + +#define kdf6(k,i) \ +{ ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[v(48,(6*(i))+ 6)] = ff(ss[0]); \ + ss[1] ^= ss[0]; k[v(48,(6*(i))+ 7)] = ff(ss[1]); \ + ss[2] ^= ss[1]; k[v(48,(6*(i))+ 8)] = ff(ss[2]); \ + ss[3] ^= ss[2]; k[v(48,(6*(i))+ 9)] = ff(ss[3]); \ + ss[4] ^= ss[3]; k[v(48,(6*(i))+10)] = ff(ss[4]); \ + ss[5] ^= ss[4]; k[v(48,(6*(i))+11)] = ff(ss[5]); \ +} + +#define kd6(k,i) \ +{ ss[6] = ls_box(ss[5],3) ^ t_use(r,c)[i]; \ + ss[0] ^= ss[6]; ss[6] = ff(ss[6]); k[v(48,(6*(i))+ 6)] = ss[6] ^= k[v(48,(6*(i)))]; \ + ss[1] ^= ss[0]; k[v(48,(6*(i))+ 7)] = ss[6] ^= k[v(48,(6*(i))+ 1)]; \ + ss[2] ^= ss[1]; k[v(48,(6*(i))+ 8)] = ss[6] ^= k[v(48,(6*(i))+ 2)]; \ + ss[3] ^= ss[2]; k[v(48,(6*(i))+ 9)] = ss[6] ^= k[v(48,(6*(i))+ 3)]; \ + ss[4] ^= ss[3]; k[v(48,(6*(i))+10)] = ss[6] ^= k[v(48,(6*(i))+ 4)]; \ + ss[5] ^= ss[4]; k[v(48,(6*(i))+11)] = ss[6] ^= k[v(48,(6*(i))+ 5)]; \ +} + +#define kdl6(k,i) \ +{ ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[v(48,(6*(i))+ 6)] = ss[0]; \ + ss[1] ^= ss[0]; k[v(48,(6*(i))+ 7)] = ss[1]; \ + ss[2] ^= ss[1]; k[v(48,(6*(i))+ 8)] = ss[2]; \ + ss[3] ^= ss[2]; k[v(48,(6*(i))+ 9)] = ss[3]; \ +} + +AES_RETURN aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1]) +{ uint_32t ss[7]; +#if defined( d_vars ) + d_vars; +#endif + cx->ks[v(48,(0))] = ss[0] = word_in(key, 0); + cx->ks[v(48,(1))] = ss[1] = word_in(key, 1); + cx->ks[v(48,(2))] = ss[2] = word_in(key, 2); + cx->ks[v(48,(3))] = ss[3] = word_in(key, 3); + +#ifdef DEC_KS_UNROLL + cx->ks[v(48,(4))] = ff(ss[4] = word_in(key, 4)); + cx->ks[v(48,(5))] = ff(ss[5] = word_in(key, 5)); + kdf6(cx->ks, 0); kd6(cx->ks, 1); + kd6(cx->ks, 2); kd6(cx->ks, 3); + kd6(cx->ks, 4); kd6(cx->ks, 5); + kd6(cx->ks, 6); kdl6(cx->ks, 7); +#else + cx->ks[v(48,(4))] = ss[4] = word_in(key, 4); + cx->ks[v(48,(5))] = ss[5] = word_in(key, 5); + { uint_32t i; + + for(i = 0; i < 7; ++i) + k6e(cx->ks, i); + k6ef(cx->ks, 7); +#if !(DEC_ROUND == NO_TABLES) + for(i = N_COLS; i < 12 * N_COLS; ++i) + cx->ks[i] = inv_mcol(cx->ks[i]); +#endif + } +#endif + cx->inf.l = 0; + cx->inf.b[0] = 12 * 16; + +#ifdef USE_VIA_ACE_IF_PRESENT + if(VIA_ACE_AVAILABLE) + cx->inf.b[1] = 0xff; +#endif + return EXIT_SUCCESS; +} + +#endif + +#if defined(AES_256) || defined( AES_VAR ) + +#define k8ef(k,i) \ +{ k[v(56,(8*(i))+ 8)] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; \ + k[v(56,(8*(i))+ 9)] = ss[1] ^= ss[0]; \ + k[v(56,(8*(i))+10)] = ss[2] ^= ss[1]; \ + k[v(56,(8*(i))+11)] = ss[3] ^= ss[2]; \ +} + +#define k8e(k,i) \ +{ k8ef(k,i); \ + k[v(56,(8*(i))+12)] = ss[4] ^= ls_box(ss[3],0); \ + k[v(56,(8*(i))+13)] = ss[5] ^= ss[4]; \ + k[v(56,(8*(i))+14)] = ss[6] ^= ss[5]; \ + k[v(56,(8*(i))+15)] = ss[7] ^= ss[6]; \ +} + +#define kdf8(k,i) \ +{ ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[v(56,(8*(i))+ 8)] = ff(ss[0]); \ + ss[1] ^= ss[0]; k[v(56,(8*(i))+ 9)] = ff(ss[1]); \ + ss[2] ^= ss[1]; k[v(56,(8*(i))+10)] = ff(ss[2]); \ + ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ff(ss[3]); \ + ss[4] ^= ls_box(ss[3],0); k[v(56,(8*(i))+12)] = ff(ss[4]); \ + ss[5] ^= ss[4]; k[v(56,(8*(i))+13)] = ff(ss[5]); \ + ss[6] ^= ss[5]; k[v(56,(8*(i))+14)] = ff(ss[6]); \ + ss[7] ^= ss[6]; k[v(56,(8*(i))+15)] = ff(ss[7]); \ +} + +#define kd8(k,i) \ +{ ss[8] = ls_box(ss[7],3) ^ t_use(r,c)[i]; \ + ss[0] ^= ss[8]; ss[8] = ff(ss[8]); k[v(56,(8*(i))+ 8)] = ss[8] ^= k[v(56,(8*(i)))]; \ + ss[1] ^= ss[0]; k[v(56,(8*(i))+ 9)] = ss[8] ^= k[v(56,(8*(i))+ 1)]; \ + ss[2] ^= ss[1]; k[v(56,(8*(i))+10)] = ss[8] ^= k[v(56,(8*(i))+ 2)]; \ + ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ss[8] ^= k[v(56,(8*(i))+ 3)]; \ + ss[8] = ls_box(ss[3],0); \ + ss[4] ^= ss[8]; ss[8] = ff(ss[8]); k[v(56,(8*(i))+12)] = ss[8] ^= k[v(56,(8*(i))+ 4)]; \ + ss[5] ^= ss[4]; k[v(56,(8*(i))+13)] = ss[8] ^= k[v(56,(8*(i))+ 5)]; \ + ss[6] ^= ss[5]; k[v(56,(8*(i))+14)] = ss[8] ^= k[v(56,(8*(i))+ 6)]; \ + ss[7] ^= ss[6]; k[v(56,(8*(i))+15)] = ss[8] ^= k[v(56,(8*(i))+ 7)]; \ +} + +#define kdl8(k,i) \ +{ ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[v(56,(8*(i))+ 8)] = ss[0]; \ + ss[1] ^= ss[0]; k[v(56,(8*(i))+ 9)] = ss[1]; \ + ss[2] ^= ss[1]; k[v(56,(8*(i))+10)] = ss[2]; \ + ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ss[3]; \ +} + +AES_RETURN aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1]) +{ uint_32t ss[9]; +#if defined( d_vars ) + d_vars; +#endif + cx->ks[v(56,(0))] = ss[0] = word_in(key, 0); + cx->ks[v(56,(1))] = ss[1] = word_in(key, 1); + cx->ks[v(56,(2))] = ss[2] = word_in(key, 2); + cx->ks[v(56,(3))] = ss[3] = word_in(key, 3); + +#ifdef DEC_KS_UNROLL + cx->ks[v(56,(4))] = ff(ss[4] = word_in(key, 4)); + cx->ks[v(56,(5))] = ff(ss[5] = word_in(key, 5)); + cx->ks[v(56,(6))] = ff(ss[6] = word_in(key, 6)); + cx->ks[v(56,(7))] = ff(ss[7] = word_in(key, 7)); + kdf8(cx->ks, 0); kd8(cx->ks, 1); + kd8(cx->ks, 2); kd8(cx->ks, 3); + kd8(cx->ks, 4); kd8(cx->ks, 5); + kdl8(cx->ks, 6); +#else + cx->ks[v(56,(4))] = ss[4] = word_in(key, 4); + cx->ks[v(56,(5))] = ss[5] = word_in(key, 5); + cx->ks[v(56,(6))] = ss[6] = word_in(key, 6); + cx->ks[v(56,(7))] = ss[7] = word_in(key, 7); + { uint_32t i; + + for(i = 0; i < 6; ++i) + k8e(cx->ks, i); + k8ef(cx->ks, 6); +#if !(DEC_ROUND == NO_TABLES) + for(i = N_COLS; i < 14 * N_COLS; ++i) + cx->ks[i] = inv_mcol(cx->ks[i]); +#endif + } +#endif + cx->inf.l = 0; + cx->inf.b[0] = 14 * 16; + +#ifdef USE_VIA_ACE_IF_PRESENT + if(VIA_ACE_AVAILABLE) + cx->inf.b[1] = 0xff; +#endif + return EXIT_SUCCESS; +} + +#endif + +#if defined( AES_VAR ) + +AES_RETURN aes_decrypt_key(const unsigned char *key, int key_len, aes_decrypt_ctx cx[1]) +{ + switch(key_len) + { + case 16: case 128: return aes_decrypt_key128(key, cx); + case 24: case 192: return aes_decrypt_key192(key, cx); + case 32: case 256: return aes_decrypt_key256(key, cx); + default: return EXIT_FAILURE; + } +} + +#endif + +#endif + +#if defined(__cplusplus) +} +#endif diff --git a/SSZipArchive/aes/aesopt.h b/SSZipArchive/aes/aesopt.h new file mode 100755 index 0000000..8851425 --- /dev/null +++ b/SSZipArchive/aes/aesopt.h @@ -0,0 +1,739 @@ +/* +--------------------------------------------------------------------------- +Copyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved. + +The redistribution and use of this software (with or without changes) +is allowed without the payment of fees or royalties provided that: + + source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation. + +This software is provided 'as is' with no explicit or implied warranties +in respect of its operation, including, but not limited to, correctness +and fitness for purpose. +--------------------------------------------------------------------------- +Issue Date: 20/12/2007 + + This file contains the compilation options for AES (Rijndael) and code + that is common across encryption, key scheduling and table generation. + + OPERATION + + These source code files implement the AES algorithm Rijndael designed by + Joan Daemen and Vincent Rijmen. This version is designed for the standard + block size of 16 bytes and for key sizes of 128, 192 and 256 bits (16, 24 + and 32 bytes). + + This version is designed for flexibility and speed using operations on + 32-bit words rather than operations on bytes. It can be compiled with + either big or little endian internal byte order but is faster when the + native byte order for the processor is used. + + THE CIPHER INTERFACE + + The cipher interface is implemented as an array of bytes in which lower + AES bit sequence indexes map to higher numeric significance within bytes. + + uint_8t (an unsigned 8-bit type) + uint_32t (an unsigned 32-bit type) + struct aes_encrypt_ctx (structure for the cipher encryption context) + struct aes_decrypt_ctx (structure for the cipher decryption context) + AES_RETURN the function return type + + C subroutine calls: + + AES_RETURN aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1]); + AES_RETURN aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1]); + AES_RETURN aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1]); + AES_RETURN aes_encrypt(const unsigned char *in, unsigned char *out, + const aes_encrypt_ctx cx[1]); + + AES_RETURN aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1]); + AES_RETURN aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1]); + AES_RETURN aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1]); + AES_RETURN aes_decrypt(const unsigned char *in, unsigned char *out, + const aes_decrypt_ctx cx[1]); + + IMPORTANT NOTE: If you are using this C interface with dynamic tables make sure that + you call aes_init() before AES is used so that the tables are initialised. + + C++ aes class subroutines: + + Class AESencrypt for encryption + + Construtors: + AESencrypt(void) + AESencrypt(const unsigned char *key) - 128 bit key + Members: + AES_RETURN key128(const unsigned char *key) + AES_RETURN key192(const unsigned char *key) + AES_RETURN key256(const unsigned char *key) + AES_RETURN encrypt(const unsigned char *in, unsigned char *out) const + + Class AESdecrypt for encryption + Construtors: + AESdecrypt(void) + AESdecrypt(const unsigned char *key) - 128 bit key + Members: + AES_RETURN key128(const unsigned char *key) + AES_RETURN key192(const unsigned char *key) + AES_RETURN key256(const unsigned char *key) + AES_RETURN decrypt(const unsigned char *in, unsigned char *out) const +*/ + +#if !defined( _AESOPT_H ) +#define _AESOPT_H + +#if defined( __cplusplus ) +#include "aescpp.h" +#else +#include "aes.h" +#endif + +/* PLATFORM SPECIFIC INCLUDES */ + +#include "brg_endian.h" + +/* CONFIGURATION - THE USE OF DEFINES + + Later in this section there are a number of defines that control the + operation of the code. In each section, the purpose of each define is + explained so that the relevant form can be included or excluded by + setting either 1's or 0's respectively on the branches of the related + #if clauses. The following local defines should not be changed. +*/ + +#define ENCRYPTION_IN_C 1 +#define DECRYPTION_IN_C 2 +#define ENC_KEYING_IN_C 4 +#define DEC_KEYING_IN_C 8 + +#define NO_TABLES 0 +#define ONE_TABLE 1 +#define FOUR_TABLES 4 +#define NONE 0 +#define PARTIAL 1 +#define FULL 2 + +/* --- START OF USER CONFIGURED OPTIONS --- */ + +/* 1. BYTE ORDER WITHIN 32 BIT WORDS + + The fundamental data processing units in Rijndael are 8-bit bytes. The + input, output and key input are all enumerated arrays of bytes in which + bytes are numbered starting at zero and increasing to one less than the + number of bytes in the array in question. This enumeration is only used + for naming bytes and does not imply any adjacency or order relationship + from one byte to another. When these inputs and outputs are considered + as bit sequences, bits 8*n to 8*n+7 of the bit sequence are mapped to + byte[n] with bit 8n+i in the sequence mapped to bit 7-i within the byte. + In this implementation bits are numbered from 0 to 7 starting at the + numerically least significant end of each byte (bit n represents 2^n). + + However, Rijndael can be implemented more efficiently using 32-bit + words by packing bytes into words so that bytes 4*n to 4*n+3 are placed + into word[n]. While in principle these bytes can be assembled into words + in any positions, this implementation only supports the two formats in + which bytes in adjacent positions within words also have adjacent byte + numbers. This order is called big-endian if the lowest numbered bytes + in words have the highest numeric significance and little-endian if the + opposite applies. + + This code can work in either order irrespective of the order used by the + machine on which it runs. Normally the internal byte order will be set + to the order of the processor on which the code is to be run but this + define can be used to reverse this in special situations + + WARNING: Assembler code versions rely on PLATFORM_BYTE_ORDER being set. + This define will hence be redefined later (in section 4) if necessary +*/ + +#if 1 +# define ALGORITHM_BYTE_ORDER PLATFORM_BYTE_ORDER +#elif 0 +# define ALGORITHM_BYTE_ORDER IS_LITTLE_ENDIAN +#elif 0 +# define ALGORITHM_BYTE_ORDER IS_BIG_ENDIAN +#else +# error The algorithm byte order is not defined +#endif + +/* 2. VIA ACE SUPPORT */ + +#if !defined(__APPLE__) && defined( __GNUC__ ) && defined( __i386__ ) \ + || defined( _WIN32 ) && defined( _M_IX86 ) \ + && !(defined( _WIN64 ) || defined( _WIN32_WCE ) || defined( _MSC_VER ) && ( _MSC_VER <= 800 )) +# define VIA_ACE_POSSIBLE +#endif + +/* Define this option if support for the VIA ACE is required. This uses + inline assembler instructions and is only implemented for the Microsoft, + Intel and GCC compilers. If VIA ACE is known to be present, then defining + ASSUME_VIA_ACE_PRESENT will remove the ordinary encryption/decryption + code. If USE_VIA_ACE_IF_PRESENT is defined then VIA ACE will be used if + it is detected (both present and enabled) but the normal AES code will + also be present. + + When VIA ACE is to be used, all AES encryption contexts MUST be 16 byte + aligned; other input/output buffers do not need to be 16 byte aligned + but there are very large performance gains if this can be arranged. + VIA ACE also requires the decryption key schedule to be in reverse + order (which later checks below ensure). +*/ + +#if 1 && defined( VIA_ACE_POSSIBLE ) && !defined( USE_VIA_ACE_IF_PRESENT ) +# define USE_VIA_ACE_IF_PRESENT +#endif + +#if 0 && defined( VIA_ACE_POSSIBLE ) && !defined( ASSUME_VIA_ACE_PRESENT ) +# define ASSUME_VIA_ACE_PRESENT +# endif + +/* 3. ASSEMBLER SUPPORT + + This define (which can be on the command line) enables the use of the + assembler code routines for encryption, decryption and key scheduling + as follows: + + ASM_X86_V1C uses the assembler (aes_x86_v1.asm) with large tables for + encryption and decryption and but with key scheduling in C + ASM_X86_V2 uses assembler (aes_x86_v2.asm) with compressed tables for + encryption, decryption and key scheduling + ASM_X86_V2C uses assembler (aes_x86_v2.asm) with compressed tables for + encryption and decryption and but with key scheduling in C + ASM_AMD64_C uses assembler (aes_amd64.asm) with compressed tables for + encryption and decryption and but with key scheduling in C + + Change one 'if 0' below to 'if 1' to select the version or define + as a compilation option. +*/ + +#if 0 && !defined( ASM_X86_V1C ) +# define ASM_X86_V1C +#elif 0 && !defined( ASM_X86_V2 ) +# define ASM_X86_V2 +#elif 0 && !defined( ASM_X86_V2C ) +# define ASM_X86_V2C +#elif 0 && !defined( ASM_AMD64_C ) +# define ASM_AMD64_C +#endif + +#if (defined ( ASM_X86_V1C ) || defined( ASM_X86_V2 ) || defined( ASM_X86_V2C )) \ + && !defined( _M_IX86 ) || defined( ASM_AMD64_C ) && !defined( _M_X64 ) +# error Assembler code is only available for x86 and AMD64 systems +#endif + +/* 4. FAST INPUT/OUTPUT OPERATIONS. + + On some machines it is possible to improve speed by transferring the + bytes in the input and output arrays to and from the internal 32-bit + variables by addressing these arrays as if they are arrays of 32-bit + words. On some machines this will always be possible but there may + be a large performance penalty if the byte arrays are not aligned on + the normal word boundaries. On other machines this technique will + lead to memory access errors when such 32-bit word accesses are not + properly aligned. The option SAFE_IO avoids such problems but will + often be slower on those machines that support misaligned access + (especially so if care is taken to align the input and output byte + arrays on 32-bit word boundaries). If SAFE_IO is not defined it is + assumed that access to byte arrays as if they are arrays of 32-bit + words will not cause problems when such accesses are misaligned. +*/ +#if 1 && !defined( _MSC_VER ) +# define SAFE_IO +#endif + +/* 5. LOOP UNROLLING + + The code for encryption and decrytpion cycles through a number of rounds + that can be implemented either in a loop or by expanding the code into a + long sequence of instructions, the latter producing a larger program but + one that will often be much faster. The latter is called loop unrolling. + There are also potential speed advantages in expanding two iterations in + a loop with half the number of iterations, which is called partial loop + unrolling. The following options allow partial or full loop unrolling + to be set independently for encryption and decryption +*/ +#if 1 +# define ENC_UNROLL FULL +#elif 0 +# define ENC_UNROLL PARTIAL +#else +# define ENC_UNROLL NONE +#endif + +#if 1 +# define DEC_UNROLL FULL +#elif 0 +# define DEC_UNROLL PARTIAL +#else +# define DEC_UNROLL NONE +#endif + +#if 1 +# define ENC_KS_UNROLL +#endif + +#if 1 +# define DEC_KS_UNROLL +#endif + +/* 6. FAST FINITE FIELD OPERATIONS + + If this section is included, tables are used to provide faster finite + field arithmetic (this has no effect if FIXED_TABLES is defined). +*/ +#if 1 +# define FF_TABLES +#endif + +/* 7. INTERNAL STATE VARIABLE FORMAT + + The internal state of Rijndael is stored in a number of local 32-bit + word varaibles which can be defined either as an array or as individual + names variables. Include this section if you want to store these local + varaibles in arrays. Otherwise individual local variables will be used. +*/ +#if 1 +# define ARRAYS +#endif + +/* 8. FIXED OR DYNAMIC TABLES + + When this section is included the tables used by the code are compiled + statically into the binary file. Otherwise the subroutine aes_init() + must be called to compute them before the code is first used. +*/ +#if 1 && !(defined( _MSC_VER ) && ( _MSC_VER <= 800 )) +# define FIXED_TABLES +#endif + +/* 9. MASKING OR CASTING FROM LONGER VALUES TO BYTES + + In some systems it is better to mask longer values to extract bytes + rather than using a cast. This option allows this choice. +*/ +#if 0 +# define to_byte(x) ((uint_8t)(x)) +#else +# define to_byte(x) ((x) & 0xff) +#endif + +/* 10. TABLE ALIGNMENT + + On some sytsems speed will be improved by aligning the AES large lookup + tables on particular boundaries. This define should be set to a power of + two giving the desired alignment. It can be left undefined if alignment + is not needed. This option is specific to the Microsft VC++ compiler - + it seems to sometimes cause trouble for the VC++ version 6 compiler. +*/ + +#if 1 && defined( _MSC_VER ) && ( _MSC_VER >= 1300 ) +# define TABLE_ALIGN 32 +#endif + +/* 11. REDUCE CODE AND TABLE SIZE + + This replaces some expanded macros with function calls if AES_ASM_V2 or + AES_ASM_V2C are defined +*/ + +#if 1 && (defined( ASM_X86_V2 ) || defined( ASM_X86_V2C )) +# define REDUCE_CODE_SIZE +#endif + +/* 12. TABLE OPTIONS + + This cipher proceeds by repeating in a number of cycles known as 'rounds' + which are implemented by a round function which can optionally be speeded + up using tables. The basic tables are each 256 32-bit words, with either + one or four tables being required for each round function depending on + how much speed is required. The encryption and decryption round functions + are different and the last encryption and decrytpion round functions are + different again making four different round functions in all. + + This means that: + 1. Normal encryption and decryption rounds can each use either 0, 1 + or 4 tables and table spaces of 0, 1024 or 4096 bytes each. + 2. The last encryption and decryption rounds can also use either 0, 1 + or 4 tables and table spaces of 0, 1024 or 4096 bytes each. + + Include or exclude the appropriate definitions below to set the number + of tables used by this implementation. +*/ + +#if 1 /* set tables for the normal encryption round */ +# define ENC_ROUND FOUR_TABLES +#elif 0 +# define ENC_ROUND ONE_TABLE +#else +# define ENC_ROUND NO_TABLES +#endif + +#if 1 /* set tables for the last encryption round */ +# define LAST_ENC_ROUND FOUR_TABLES +#elif 0 +# define LAST_ENC_ROUND ONE_TABLE +#else +# define LAST_ENC_ROUND NO_TABLES +#endif + +#if 1 /* set tables for the normal decryption round */ +# define DEC_ROUND FOUR_TABLES +#elif 0 +# define DEC_ROUND ONE_TABLE +#else +# define DEC_ROUND NO_TABLES +#endif + +#if 1 /* set tables for the last decryption round */ +# define LAST_DEC_ROUND FOUR_TABLES +#elif 0 +# define LAST_DEC_ROUND ONE_TABLE +#else +# define LAST_DEC_ROUND NO_TABLES +#endif + +/* The decryption key schedule can be speeded up with tables in the same + way that the round functions can. Include or exclude the following + defines to set this requirement. +*/ +#if 1 +# define KEY_SCHED FOUR_TABLES +#elif 0 +# define KEY_SCHED ONE_TABLE +#else +# define KEY_SCHED NO_TABLES +#endif + +/* ---- END OF USER CONFIGURED OPTIONS ---- */ + +/* VIA ACE support is only available for VC++ and GCC */ + +#if !defined( _MSC_VER ) && !defined( __GNUC__ ) +# if defined( ASSUME_VIA_ACE_PRESENT ) +# undef ASSUME_VIA_ACE_PRESENT +# endif +# if defined( USE_VIA_ACE_IF_PRESENT ) +# undef USE_VIA_ACE_IF_PRESENT +# endif +#endif + +#if defined( ASSUME_VIA_ACE_PRESENT ) && !defined( USE_VIA_ACE_IF_PRESENT ) +# define USE_VIA_ACE_IF_PRESENT +#endif + +#if defined( USE_VIA_ACE_IF_PRESENT ) && !defined ( AES_REV_DKS ) +# define AES_REV_DKS +#endif + +/* Assembler support requires the use of platform byte order */ + +#if ( defined( ASM_X86_V1C ) || defined( ASM_X86_V2C ) || defined( ASM_AMD64_C ) ) \ + && (ALGORITHM_BYTE_ORDER != PLATFORM_BYTE_ORDER) +# undef ALGORITHM_BYTE_ORDER +# define ALGORITHM_BYTE_ORDER PLATFORM_BYTE_ORDER +#endif + +/* In this implementation the columns of the state array are each held in + 32-bit words. The state array can be held in various ways: in an array + of words, in a number of individual word variables or in a number of + processor registers. The following define maps a variable name x and + a column number c to the way the state array variable is to be held. + The first define below maps the state into an array x[c] whereas the + second form maps the state into a number of individual variables x0, + x1, etc. Another form could map individual state colums to machine + register names. +*/ + +#if defined( ARRAYS ) +# define s(x,c) x[c] +#else +# define s(x,c) x##c +#endif + +/* This implementation provides subroutines for encryption, decryption + and for setting the three key lengths (separately) for encryption + and decryption. Since not all functions are needed, masks are set + up here to determine which will be implemented in C +*/ + +#if !defined( AES_ENCRYPT ) +# define EFUNCS_IN_C 0 +#elif defined( ASSUME_VIA_ACE_PRESENT ) || defined( ASM_X86_V1C ) \ + || defined( ASM_X86_V2C ) || defined( ASM_AMD64_C ) +# define EFUNCS_IN_C ENC_KEYING_IN_C +#elif !defined( ASM_X86_V2 ) +# define EFUNCS_IN_C ( ENCRYPTION_IN_C | ENC_KEYING_IN_C ) +#else +# define EFUNCS_IN_C 0 +#endif + +#if !defined( AES_DECRYPT ) +# define DFUNCS_IN_C 0 +#elif defined( ASSUME_VIA_ACE_PRESENT ) || defined( ASM_X86_V1C ) \ + || defined( ASM_X86_V2C ) || defined( ASM_AMD64_C ) +# define DFUNCS_IN_C DEC_KEYING_IN_C +#elif !defined( ASM_X86_V2 ) +# define DFUNCS_IN_C ( DECRYPTION_IN_C | DEC_KEYING_IN_C ) +#else +# define DFUNCS_IN_C 0 +#endif + +#define FUNCS_IN_C ( EFUNCS_IN_C | DFUNCS_IN_C ) + +/* END OF CONFIGURATION OPTIONS */ + +#define RC_LENGTH (5 * (AES_BLOCK_SIZE / 4 - 2)) + +/* Disable or report errors on some combinations of options */ + +#if ENC_ROUND == NO_TABLES && LAST_ENC_ROUND != NO_TABLES +# undef LAST_ENC_ROUND +# define LAST_ENC_ROUND NO_TABLES +#elif ENC_ROUND == ONE_TABLE && LAST_ENC_ROUND == FOUR_TABLES +# undef LAST_ENC_ROUND +# define LAST_ENC_ROUND ONE_TABLE +#endif + +#if ENC_ROUND == NO_TABLES && ENC_UNROLL != NONE +# undef ENC_UNROLL +# define ENC_UNROLL NONE +#endif + +#if DEC_ROUND == NO_TABLES && LAST_DEC_ROUND != NO_TABLES +# undef LAST_DEC_ROUND +# define LAST_DEC_ROUND NO_TABLES +#elif DEC_ROUND == ONE_TABLE && LAST_DEC_ROUND == FOUR_TABLES +# undef LAST_DEC_ROUND +# define LAST_DEC_ROUND ONE_TABLE +#endif + +#if DEC_ROUND == NO_TABLES && DEC_UNROLL != NONE +# undef DEC_UNROLL +# define DEC_UNROLL NONE +#endif + +#if defined( bswap32 ) +# define aes_sw32 bswap32 +#elif defined( bswap_32 ) +# define aes_sw32 bswap_32 +#else +# define brot(x,n) (((uint_32t)(x) << n) | ((uint_32t)(x) >> (32 - n))) +# define aes_sw32(x) ((brot((x),8) & 0x00ff00ff) | (brot((x),24) & 0xff00ff00)) +#endif + +/* upr(x,n): rotates bytes within words by n positions, moving bytes to + higher index positions with wrap around into low positions + ups(x,n): moves bytes by n positions to higher index positions in + words but without wrap around + bval(x,n): extracts a byte from a word + + WARNING: The definitions given here are intended only for use with + unsigned variables and with shift counts that are compile + time constants +*/ + +#if ( ALGORITHM_BYTE_ORDER == IS_LITTLE_ENDIAN ) +# define upr(x,n) (((uint_32t)(x) << (8 * (n))) | ((uint_32t)(x) >> (32 - 8 * (n)))) +# define ups(x,n) ((uint_32t) (x) << (8 * (n))) +# define bval(x,n) to_byte((x) >> (8 * (n))) +# define bytes2word(b0, b1, b2, b3) \ + (((uint_32t)(b3) << 24) | ((uint_32t)(b2) << 16) | ((uint_32t)(b1) << 8) | (b0)) +#endif + +#if ( ALGORITHM_BYTE_ORDER == IS_BIG_ENDIAN ) +# define upr(x,n) (((uint_32t)(x) >> (8 * (n))) | ((uint_32t)(x) << (32 - 8 * (n)))) +# define ups(x,n) ((uint_32t) (x) >> (8 * (n))) +# define bval(x,n) to_byte((x) >> (24 - 8 * (n))) +# define bytes2word(b0, b1, b2, b3) \ + (((uint_32t)(b0) << 24) | ((uint_32t)(b1) << 16) | ((uint_32t)(b2) << 8) | (b3)) +#endif + +#if defined( SAFE_IO ) +# define word_in(x,c) bytes2word(((const uint_8t*)(x)+4*c)[0], ((const uint_8t*)(x)+4*c)[1], \ + ((const uint_8t*)(x)+4*c)[2], ((const uint_8t*)(x)+4*c)[3]) +# define word_out(x,c,v) { ((uint_8t*)(x)+4*c)[0] = bval(v,0); ((uint_8t*)(x)+4*c)[1] = bval(v,1); \ + ((uint_8t*)(x)+4*c)[2] = bval(v,2); ((uint_8t*)(x)+4*c)[3] = bval(v,3); } +#elif ( ALGORITHM_BYTE_ORDER == PLATFORM_BYTE_ORDER ) +# define word_in(x,c) (*((uint_32t*)(x)+(c))) +# define word_out(x,c,v) (*((uint_32t*)(x)+(c)) = (v)) +#else +# define word_in(x,c) aes_sw32(*((uint_32t*)(x)+(c))) +# define word_out(x,c,v) (*((uint_32t*)(x)+(c)) = aes_sw32(v)) +#endif + +/* the finite field modular polynomial and elements */ + +#define WPOLY 0x011b +#define BPOLY 0x1b + +/* multiply four bytes in GF(2^8) by 'x' {02} in parallel */ + +#define gf_c1 0x80808080 +#define gf_c2 0x7f7f7f7f +#define gf_mulx(x) ((((x) & gf_c2) << 1) ^ ((((x) & gf_c1) >> 7) * BPOLY)) + +/* The following defines provide alternative definitions of gf_mulx that might + give improved performance if a fast 32-bit multiply is not available. Note + that a temporary variable u needs to be defined where gf_mulx is used. + +#define gf_mulx(x) (u = (x) & gf_c1, u |= (u >> 1), ((x) & gf_c2) << 1) ^ ((u >> 3) | (u >> 6)) +#define gf_c4 (0x01010101 * BPOLY) +#define gf_mulx(x) (u = (x) & gf_c1, ((x) & gf_c2) << 1) ^ ((u - (u >> 7)) & gf_c4) +*/ + +/* Work out which tables are needed for the different options */ + +#if defined( ASM_X86_V1C ) +# if defined( ENC_ROUND ) +# undef ENC_ROUND +# endif +# define ENC_ROUND FOUR_TABLES +# if defined( LAST_ENC_ROUND ) +# undef LAST_ENC_ROUND +# endif +# define LAST_ENC_ROUND FOUR_TABLES +# if defined( DEC_ROUND ) +# undef DEC_ROUND +# endif +# define DEC_ROUND FOUR_TABLES +# if defined( LAST_DEC_ROUND ) +# undef LAST_DEC_ROUND +# endif +# define LAST_DEC_ROUND FOUR_TABLES +# if defined( KEY_SCHED ) +# undef KEY_SCHED +# define KEY_SCHED FOUR_TABLES +# endif +#endif + +#if ( FUNCS_IN_C & ENCRYPTION_IN_C ) || defined( ASM_X86_V1C ) +# if ENC_ROUND == ONE_TABLE +# define FT1_SET +# elif ENC_ROUND == FOUR_TABLES +# define FT4_SET +# else +# define SBX_SET +# endif +# if LAST_ENC_ROUND == ONE_TABLE +# define FL1_SET +# elif LAST_ENC_ROUND == FOUR_TABLES +# define FL4_SET +# elif !defined( SBX_SET ) +# define SBX_SET +# endif +#endif + +#if ( FUNCS_IN_C & DECRYPTION_IN_C ) || defined( ASM_X86_V1C ) +# if DEC_ROUND == ONE_TABLE +# define IT1_SET +# elif DEC_ROUND == FOUR_TABLES +# define IT4_SET +# else +# define ISB_SET +# endif +# if LAST_DEC_ROUND == ONE_TABLE +# define IL1_SET +# elif LAST_DEC_ROUND == FOUR_TABLES +# define IL4_SET +# elif !defined(ISB_SET) +# define ISB_SET +# endif +#endif + +#if !(defined( REDUCE_CODE_SIZE ) && (defined( ASM_X86_V2 ) || defined( ASM_X86_V2C ))) +# if ((FUNCS_IN_C & ENC_KEYING_IN_C) || (FUNCS_IN_C & DEC_KEYING_IN_C)) +# if KEY_SCHED == ONE_TABLE +# if !defined( FL1_SET ) && !defined( FL4_SET ) +# define LS1_SET +# endif +# elif KEY_SCHED == FOUR_TABLES +# if !defined( FL4_SET ) +# define LS4_SET +# endif +# elif !defined( SBX_SET ) +# define SBX_SET +# endif +# endif +# if (FUNCS_IN_C & DEC_KEYING_IN_C) +# if KEY_SCHED == ONE_TABLE +# define IM1_SET +# elif KEY_SCHED == FOUR_TABLES +# define IM4_SET +# elif !defined( SBX_SET ) +# define SBX_SET +# endif +# endif +#endif + +/* generic definitions of Rijndael macros that use tables */ + +#define no_table(x,box,vf,rf,c) bytes2word( \ + box[bval(vf(x,0,c),rf(0,c))], \ + box[bval(vf(x,1,c),rf(1,c))], \ + box[bval(vf(x,2,c),rf(2,c))], \ + box[bval(vf(x,3,c),rf(3,c))]) + +#define one_table(x,op,tab,vf,rf,c) \ + ( tab[bval(vf(x,0,c),rf(0,c))] \ + ^ op(tab[bval(vf(x,1,c),rf(1,c))],1) \ + ^ op(tab[bval(vf(x,2,c),rf(2,c))],2) \ + ^ op(tab[bval(vf(x,3,c),rf(3,c))],3)) + +#define four_tables(x,tab,vf,rf,c) \ + ( tab[0][bval(vf(x,0,c),rf(0,c))] \ + ^ tab[1][bval(vf(x,1,c),rf(1,c))] \ + ^ tab[2][bval(vf(x,2,c),rf(2,c))] \ + ^ tab[3][bval(vf(x,3,c),rf(3,c))]) + +#define vf1(x,r,c) (x) +#define rf1(r,c) (r) +#define rf2(r,c) ((8+r-c)&3) + +/* perform forward and inverse column mix operation on four bytes in long word x in */ +/* parallel. NOTE: x must be a simple variable, NOT an expression in these macros. */ + +#if !(defined( REDUCE_CODE_SIZE ) && (defined( ASM_X86_V2 ) || defined( ASM_X86_V2C ))) + +#if defined( FM4_SET ) /* not currently used */ +# define fwd_mcol(x) four_tables(x,t_use(f,m),vf1,rf1,0) +#elif defined( FM1_SET ) /* not currently used */ +# define fwd_mcol(x) one_table(x,upr,t_use(f,m),vf1,rf1,0) +#else +# define dec_fmvars uint_32t g2 +# define fwd_mcol(x) (g2 = gf_mulx(x), g2 ^ upr((x) ^ g2, 3) ^ upr((x), 2) ^ upr((x), 1)) +#endif + +#if defined( IM4_SET ) +# define inv_mcol(x) four_tables(x,t_use(i,m),vf1,rf1,0) +#elif defined( IM1_SET ) +# define inv_mcol(x) one_table(x,upr,t_use(i,m),vf1,rf1,0) +#else +# define dec_imvars uint_32t g2, g4, g9 +# define inv_mcol(x) (g2 = gf_mulx(x), g4 = gf_mulx(g2), g9 = (x) ^ gf_mulx(g4), g4 ^= g9, \ + (x) ^ g2 ^ g4 ^ upr(g2 ^ g9, 3) ^ upr(g4, 2) ^ upr(g9, 1)) +#endif + +#if defined( FL4_SET ) +# define ls_box(x,c) four_tables(x,t_use(f,l),vf1,rf2,c) +#elif defined( LS4_SET ) +# define ls_box(x,c) four_tables(x,t_use(l,s),vf1,rf2,c) +#elif defined( FL1_SET ) +# define ls_box(x,c) one_table(x,upr,t_use(f,l),vf1,rf2,c) +#elif defined( LS1_SET ) +# define ls_box(x,c) one_table(x,upr,t_use(l,s),vf1,rf2,c) +#else +# define ls_box(x,c) no_table(x,t_use(s,box),vf1,rf2,c) +#endif + +#endif + +#if defined( ASM_X86_V1C ) && defined( AES_DECRYPT ) && !defined( ISB_SET ) +# define ISB_SET +#endif + +#endif diff --git a/SSZipArchive/aes/aestab.c b/SSZipArchive/aes/aestab.c new file mode 100755 index 0000000..6d193af --- /dev/null +++ b/SSZipArchive/aes/aestab.c @@ -0,0 +1,391 @@ +/* +--------------------------------------------------------------------------- +Copyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved. + +The redistribution and use of this software (with or without changes) +is allowed without the payment of fees or royalties provided that: + + source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation. + +This software is provided 'as is' with no explicit or implied warranties +in respect of its operation, including, but not limited to, correctness +and fitness for purpose. +--------------------------------------------------------------------------- +Issue Date: 20/12/2007 +*/ + +#define DO_TABLES + +#include "aes.h" +#include "aesopt.h" + +#if defined(FIXED_TABLES) + +#define sb_data(w) {\ + w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\ + w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\ + w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\ + w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\ + w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\ + w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\ + w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\ + w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\ + w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\ + w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\ + w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\ + w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\ + w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\ + w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\ + w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\ + w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\ + w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\ + w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\ + w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\ + w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\ + w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\ + w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\ + w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\ + w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\ + w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\ + w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\ + w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\ + w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\ + w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\ + w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\ + w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\ + w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) } + +#define isb_data(w) {\ + w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), w(0x38),\ + w(0xbf), w(0x40), w(0xa3), w(0x9e), w(0x81), w(0xf3), w(0xd7), w(0xfb),\ + w(0x7c), w(0xe3), w(0x39), w(0x82), w(0x9b), w(0x2f), w(0xff), w(0x87),\ + w(0x34), w(0x8e), w(0x43), w(0x44), w(0xc4), w(0xde), w(0xe9), w(0xcb),\ + w(0x54), w(0x7b), w(0x94), w(0x32), w(0xa6), w(0xc2), w(0x23), w(0x3d),\ + w(0xee), w(0x4c), w(0x95), w(0x0b), w(0x42), w(0xfa), w(0xc3), w(0x4e),\ + w(0x08), w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), w(0xb2),\ + w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), w(0x25),\ + w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), w(0x98), w(0x16),\ + w(0xd4), w(0xa4), w(0x5c), w(0xcc), w(0x5d), w(0x65), w(0xb6), w(0x92),\ + w(0x6c), w(0x70), w(0x48), w(0x50), w(0xfd), w(0xed), w(0xb9), w(0xda),\ + w(0x5e), w(0x15), w(0x46), w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84),\ + w(0x90), w(0xd8), w(0xab), w(0x00), w(0x8c), w(0xbc), w(0xd3), w(0x0a),\ + w(0xf7), w(0xe4), w(0x58), w(0x05), w(0xb8), w(0xb3), w(0x45), w(0x06),\ + w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), w(0x0f), w(0x02),\ + w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), w(0x8a), w(0x6b),\ + w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), w(0x67), w(0xdc), w(0xea),\ + w(0x97), w(0xf2), w(0xcf), w(0xce), w(0xf0), w(0xb4), w(0xe6), w(0x73),\ + w(0x96), w(0xac), w(0x74), w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85),\ + w(0xe2), w(0xf9), w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e),\ + w(0x47), w(0xf1), w(0x1a), w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89),\ + w(0x6f), w(0xb7), w(0x62), w(0x0e), w(0xaa), w(0x18), w(0xbe), w(0x1b),\ + w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), w(0xd2), w(0x79), w(0x20),\ + w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), w(0xcd), w(0x5a), w(0xf4),\ + w(0x1f), w(0xdd), w(0xa8), w(0x33), w(0x88), w(0x07), w(0xc7), w(0x31),\ + w(0xb1), w(0x12), w(0x10), w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f),\ + w(0x60), w(0x51), w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d),\ + w(0x2d), w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef),\ + w(0xa0), w(0xe0), w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), w(0xb0),\ + w(0xc8), w(0xeb), w(0xbb), w(0x3c), w(0x83), w(0x53), w(0x99), w(0x61),\ + w(0x17), w(0x2b), w(0x04), w(0x7e), w(0xba), w(0x77), w(0xd6), w(0x26),\ + w(0xe1), w(0x69), w(0x14), w(0x63), w(0x55), w(0x21), w(0x0c), w(0x7d) } + +#define mm_data(w) {\ + w(0x00), w(0x01), w(0x02), w(0x03), w(0x04), w(0x05), w(0x06), w(0x07),\ + w(0x08), w(0x09), w(0x0a), w(0x0b), w(0x0c), w(0x0d), w(0x0e), w(0x0f),\ + w(0x10), w(0x11), w(0x12), w(0x13), w(0x14), w(0x15), w(0x16), w(0x17),\ + w(0x18), w(0x19), w(0x1a), w(0x1b), w(0x1c), w(0x1d), w(0x1e), w(0x1f),\ + w(0x20), w(0x21), w(0x22), w(0x23), w(0x24), w(0x25), w(0x26), w(0x27),\ + w(0x28), w(0x29), w(0x2a), w(0x2b), w(0x2c), w(0x2d), w(0x2e), w(0x2f),\ + w(0x30), w(0x31), w(0x32), w(0x33), w(0x34), w(0x35), w(0x36), w(0x37),\ + w(0x38), w(0x39), w(0x3a), w(0x3b), w(0x3c), w(0x3d), w(0x3e), w(0x3f),\ + w(0x40), w(0x41), w(0x42), w(0x43), w(0x44), w(0x45), w(0x46), w(0x47),\ + w(0x48), w(0x49), w(0x4a), w(0x4b), w(0x4c), w(0x4d), w(0x4e), w(0x4f),\ + w(0x50), w(0x51), w(0x52), w(0x53), w(0x54), w(0x55), w(0x56), w(0x57),\ + w(0x58), w(0x59), w(0x5a), w(0x5b), w(0x5c), w(0x5d), w(0x5e), w(0x5f),\ + w(0x60), w(0x61), w(0x62), w(0x63), w(0x64), w(0x65), w(0x66), w(0x67),\ + w(0x68), w(0x69), w(0x6a), w(0x6b), w(0x6c), w(0x6d), w(0x6e), w(0x6f),\ + w(0x70), w(0x71), w(0x72), w(0x73), w(0x74), w(0x75), w(0x76), w(0x77),\ + w(0x78), w(0x79), w(0x7a), w(0x7b), w(0x7c), w(0x7d), w(0x7e), w(0x7f),\ + w(0x80), w(0x81), w(0x82), w(0x83), w(0x84), w(0x85), w(0x86), w(0x87),\ + w(0x88), w(0x89), w(0x8a), w(0x8b), w(0x8c), w(0x8d), w(0x8e), w(0x8f),\ + w(0x90), w(0x91), w(0x92), w(0x93), w(0x94), w(0x95), w(0x96), w(0x97),\ + w(0x98), w(0x99), w(0x9a), w(0x9b), w(0x9c), w(0x9d), w(0x9e), w(0x9f),\ + w(0xa0), w(0xa1), w(0xa2), w(0xa3), w(0xa4), w(0xa5), w(0xa6), w(0xa7),\ + w(0xa8), w(0xa9), w(0xaa), w(0xab), w(0xac), w(0xad), w(0xae), w(0xaf),\ + w(0xb0), w(0xb1), w(0xb2), w(0xb3), w(0xb4), w(0xb5), w(0xb6), w(0xb7),\ + w(0xb8), w(0xb9), w(0xba), w(0xbb), w(0xbc), w(0xbd), w(0xbe), w(0xbf),\ + w(0xc0), w(0xc1), w(0xc2), w(0xc3), w(0xc4), w(0xc5), w(0xc6), w(0xc7),\ + w(0xc8), w(0xc9), w(0xca), w(0xcb), w(0xcc), w(0xcd), w(0xce), w(0xcf),\ + w(0xd0), w(0xd1), w(0xd2), w(0xd3), w(0xd4), w(0xd5), w(0xd6), w(0xd7),\ + w(0xd8), w(0xd9), w(0xda), w(0xdb), w(0xdc), w(0xdd), w(0xde), w(0xdf),\ + w(0xe0), w(0xe1), w(0xe2), w(0xe3), w(0xe4), w(0xe5), w(0xe6), w(0xe7),\ + w(0xe8), w(0xe9), w(0xea), w(0xeb), w(0xec), w(0xed), w(0xee), w(0xef),\ + w(0xf0), w(0xf1), w(0xf2), w(0xf3), w(0xf4), w(0xf5), w(0xf6), w(0xf7),\ + w(0xf8), w(0xf9), w(0xfa), w(0xfb), w(0xfc), w(0xfd), w(0xfe), w(0xff) } + +#define rc_data(w) {\ + w(0x01), w(0x02), w(0x04), w(0x08), w(0x10),w(0x20), w(0x40), w(0x80),\ + w(0x1b), w(0x36) } + +#define h0(x) (x) + +#define w0(p) bytes2word(p, 0, 0, 0) +#define w1(p) bytes2word(0, p, 0, 0) +#define w2(p) bytes2word(0, 0, p, 0) +#define w3(p) bytes2word(0, 0, 0, p) + +#define u0(p) bytes2word(f2(p), p, p, f3(p)) +#define u1(p) bytes2word(f3(p), f2(p), p, p) +#define u2(p) bytes2word(p, f3(p), f2(p), p) +#define u3(p) bytes2word(p, p, f3(p), f2(p)) + +#define v0(p) bytes2word(fe(p), f9(p), fd(p), fb(p)) +#define v1(p) bytes2word(fb(p), fe(p), f9(p), fd(p)) +#define v2(p) bytes2word(fd(p), fb(p), fe(p), f9(p)) +#define v3(p) bytes2word(f9(p), fd(p), fb(p), fe(p)) + +#endif + +#if defined(FIXED_TABLES) || !defined(FF_TABLES) + +#define f2(x) ((x<<1) ^ (((x>>7) & 1) * WPOLY)) +#define f4(x) ((x<<2) ^ (((x>>6) & 1) * WPOLY) ^ (((x>>6) & 2) * WPOLY)) +#define f8(x) ((x<<3) ^ (((x>>5) & 1) * WPOLY) ^ (((x>>5) & 2) * WPOLY) \ + ^ (((x>>5) & 4) * WPOLY)) +#define f3(x) (f2(x) ^ x) +#define f9(x) (f8(x) ^ x) +#define fb(x) (f8(x) ^ f2(x) ^ x) +#define fd(x) (f8(x) ^ f4(x) ^ x) +#define fe(x) (f8(x) ^ f4(x) ^ f2(x)) + +#else + +#define f2(x) ((x) ? pow[log[x] + 0x19] : 0) +#define f3(x) ((x) ? pow[log[x] + 0x01] : 0) +#define f9(x) ((x) ? pow[log[x] + 0xc7] : 0) +#define fb(x) ((x) ? pow[log[x] + 0x68] : 0) +#define fd(x) ((x) ? pow[log[x] + 0xee] : 0) +#define fe(x) ((x) ? pow[log[x] + 0xdf] : 0) + +#endif + +#include "aestab.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#if defined(FIXED_TABLES) + +/* implemented in case of wrong call for fixed tables */ + +AES_RETURN aes_init(void) +{ + return EXIT_SUCCESS; +} + +#else /* Generate the tables for the dynamic table option */ + +#if defined(FF_TABLES) + +#define gf_inv(x) ((x) ? pow[ 255 - log[x]] : 0) + +#else + +/* It will generally be sensible to use tables to compute finite + field multiplies and inverses but where memory is scarse this + code might sometimes be better. But it only has effect during + initialisation so its pretty unimportant in overall terms. +*/ + +/* return 2 ^ (n - 1) where n is the bit number of the highest bit + set in x with x in the range 1 < x < 0x00000200. This form is + used so that locals within fi can be bytes rather than words +*/ + +static uint_8t hibit(const uint_32t x) +{ uint_8t r = (uint_8t)((x >> 1) | (x >> 2)); + + r |= (r >> 2); + r |= (r >> 4); + return (r + 1) >> 1; +} + +/* return the inverse of the finite field element x */ + +static uint_8t gf_inv(const uint_8t x) +{ uint_8t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0; + + if(x < 2) + return x; + + for( ; ; ) + { + if(n1) + while(n2 >= n1) /* divide polynomial p2 by p1 */ + { + n2 /= n1; /* shift smaller polynomial left */ + p2 ^= (p1 * n2) & 0xff; /* and remove from larger one */ + v2 ^= v1 * n2; /* shift accumulated value and */ + n2 = hibit(p2); /* add into result */ + } + else + return v1; + + if(n2) /* repeat with values swapped */ + while(n1 >= n2) + { + n1 /= n2; + p1 ^= p2 * n1; + v1 ^= v2 * n1; + n1 = hibit(p1); + } + else + return v2; + } +} + +#endif + +/* The forward and inverse affine transformations used in the S-box */ +uint_8t fwd_affine(const uint_8t x) +{ uint_32t w = x; + w ^= (w << 1) ^ (w << 2) ^ (w << 3) ^ (w << 4); + return 0x63 ^ ((w ^ (w >> 8)) & 0xff); +} + +uint_8t inv_affine(const uint_8t x) +{ uint_32t w = x; + w = (w << 1) ^ (w << 3) ^ (w << 6); + return 0x05 ^ ((w ^ (w >> 8)) & 0xff); +} + +static int init = 0; + +AES_RETURN aes_init(void) +{ uint_32t i, w; + +#if defined(FF_TABLES) + + uint_8t pow[512], log[256]; + + if(init) + return EXIT_SUCCESS; + /* log and power tables for GF(2^8) finite field with + WPOLY as modular polynomial - the simplest primitive + root is 0x03, used here to generate the tables + */ + + i = 0; w = 1; + do + { + pow[i] = (uint_8t)w; + pow[i + 255] = (uint_8t)w; + log[w] = (uint_8t)i++; + w ^= (w << 1) ^ (w & 0x80 ? WPOLY : 0); + } + while (w != 1); + +#else + if(init) + return EXIT_SUCCESS; +#endif + + for(i = 0, w = 1; i < RC_LENGTH; ++i) + { + t_set(r,c)[i] = bytes2word(w, 0, 0, 0); + w = f2(w); + } + + for(i = 0; i < 256; ++i) + { uint_8t b; + + b = fwd_affine(gf_inv((uint_8t)i)); + w = bytes2word(f2(b), b, b, f3(b)); + +#if defined( SBX_SET ) + t_set(s,box)[i] = b; +#endif + +#if defined( FT1_SET ) /* tables for a normal encryption round */ + t_set(f,n)[i] = w; +#endif +#if defined( FT4_SET ) + t_set(f,n)[0][i] = w; + t_set(f,n)[1][i] = upr(w,1); + t_set(f,n)[2][i] = upr(w,2); + t_set(f,n)[3][i] = upr(w,3); +#endif + w = bytes2word(b, 0, 0, 0); + +#if defined( FL1_SET ) /* tables for last encryption round (may also */ + t_set(f,l)[i] = w; /* be used in the key schedule) */ +#endif +#if defined( FL4_SET ) + t_set(f,l)[0][i] = w; + t_set(f,l)[1][i] = upr(w,1); + t_set(f,l)[2][i] = upr(w,2); + t_set(f,l)[3][i] = upr(w,3); +#endif + +#if defined( LS1_SET ) /* table for key schedule if t_set(f,l) above is*/ + t_set(l,s)[i] = w; /* not of the required form */ +#endif +#if defined( LS4_SET ) + t_set(l,s)[0][i] = w; + t_set(l,s)[1][i] = upr(w,1); + t_set(l,s)[2][i] = upr(w,2); + t_set(l,s)[3][i] = upr(w,3); +#endif + + b = gf_inv(inv_affine((uint_8t)i)); + w = bytes2word(fe(b), f9(b), fd(b), fb(b)); + +#if defined( IM1_SET ) /* tables for the inverse mix column operation */ + t_set(i,m)[b] = w; +#endif +#if defined( IM4_SET ) + t_set(i,m)[0][b] = w; + t_set(i,m)[1][b] = upr(w,1); + t_set(i,m)[2][b] = upr(w,2); + t_set(i,m)[3][b] = upr(w,3); +#endif + +#if defined( ISB_SET ) + t_set(i,box)[i] = b; +#endif +#if defined( IT1_SET ) /* tables for a normal decryption round */ + t_set(i,n)[i] = w; +#endif +#if defined( IT4_SET ) + t_set(i,n)[0][i] = w; + t_set(i,n)[1][i] = upr(w,1); + t_set(i,n)[2][i] = upr(w,2); + t_set(i,n)[3][i] = upr(w,3); +#endif + w = bytes2word(b, 0, 0, 0); +#if defined( IL1_SET ) /* tables for last decryption round */ + t_set(i,l)[i] = w; +#endif +#if defined( IL4_SET ) + t_set(i,l)[0][i] = w; + t_set(i,l)[1][i] = upr(w,1); + t_set(i,l)[2][i] = upr(w,2); + t_set(i,l)[3][i] = upr(w,3); +#endif + } + init = 1; + return EXIT_SUCCESS; +} + +#endif + +#if defined(__cplusplus) +} +#endif + diff --git a/SSZipArchive/aes/aestab.h b/SSZipArchive/aes/aestab.h new file mode 100755 index 0000000..21fc736 --- /dev/null +++ b/SSZipArchive/aes/aestab.h @@ -0,0 +1,173 @@ +/* +--------------------------------------------------------------------------- +Copyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved. + +The redistribution and use of this software (with or without changes) +is allowed without the payment of fees or royalties provided that: + + source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation. + +This software is provided 'as is' with no explicit or implied warranties +in respect of its operation, including, but not limited to, correctness +and fitness for purpose. +--------------------------------------------------------------------------- +Issue Date: 20/12/2007 + + This file contains the code for declaring the tables needed to implement + AES. The file aesopt.h is assumed to be included before this header file. + If there are no global variables, the definitions here can be used to put + the AES tables in a structure so that a pointer can then be added to the + AES context to pass them to the AES routines that need them. If this + facility is used, the calling program has to ensure that this pointer is + managed appropriately. In particular, the value of the t_dec(in,it) item + in the table structure must be set to zero in order to ensure that the + tables are initialised. In practice the three code sequences in aeskey.c + that control the calls to aes_init() and the aes_init() routine itself will + have to be changed for a specific implementation. If global variables are + available it will generally be preferable to use them with the precomputed + FIXED_TABLES option that uses static global tables. + + The following defines can be used to control the way the tables + are defined, initialised and used in embedded environments that + require special features for these purposes + + the 't_dec' construction is used to declare fixed table arrays + the 't_set' construction is used to set fixed table values + the 't_use' construction is used to access fixed table values + + 256 byte tables: + + t_xxx(s,box) => forward S box + t_xxx(i,box) => inverse S box + + 256 32-bit word OR 4 x 256 32-bit word tables: + + t_xxx(f,n) => forward normal round + t_xxx(f,l) => forward last round + t_xxx(i,n) => inverse normal round + t_xxx(i,l) => inverse last round + t_xxx(l,s) => key schedule table + t_xxx(i,m) => key schedule table + + Other variables and tables: + + t_xxx(r,c) => the rcon table +*/ + +#if !defined( _AESTAB_H ) +#define _AESTAB_H + +#if defined(__cplusplus) +extern "C" { +#endif + +#define t_dec(m,n) t_##m##n +#define t_set(m,n) t_##m##n +#define t_use(m,n) t_##m##n + +#if defined(FIXED_TABLES) +# if !defined( __GNUC__ ) && (defined( __MSDOS__ ) || defined( __WIN16__ )) +/* make tables far data to avoid using too much DGROUP space (PG) */ +# define CONST const far +# else +# define CONST const +# endif +#else +# define CONST +#endif + +#if defined(DO_TABLES) +# define EXTERN +#else +# define EXTERN extern +#endif + +#if defined(_MSC_VER) && defined(TABLE_ALIGN) +#define ALIGN __declspec(align(TABLE_ALIGN)) +#else +#define ALIGN +#endif + +#if defined( __WATCOMC__ ) && ( __WATCOMC__ >= 1100 ) +# define XP_DIR __cdecl +#else +# define XP_DIR +#endif + +#if defined(DO_TABLES) && defined(FIXED_TABLES) +#define d_1(t,n,b,e) EXTERN ALIGN CONST XP_DIR t n[256] = b(e) +#define d_4(t,n,b,e,f,g,h) EXTERN ALIGN CONST XP_DIR t n[4][256] = { b(e), b(f), b(g), b(h) } +EXTERN ALIGN CONST uint_32t t_dec(r,c)[RC_LENGTH] = rc_data(w0); +#else +#define d_1(t,n,b,e) EXTERN ALIGN CONST XP_DIR t n[256] +#define d_4(t,n,b,e,f,g,h) EXTERN ALIGN CONST XP_DIR t n[4][256] +EXTERN ALIGN CONST uint_32t t_dec(r,c)[RC_LENGTH]; +#endif + +#if defined( SBX_SET ) + d_1(uint_8t, t_dec(s,box), sb_data, h0); +#endif +#if defined( ISB_SET ) + d_1(uint_8t, t_dec(i,box), isb_data, h0); +#endif + +#if defined( FT1_SET ) + d_1(uint_32t, t_dec(f,n), sb_data, u0); +#endif +#if defined( FT4_SET ) + d_4(uint_32t, t_dec(f,n), sb_data, u0, u1, u2, u3); +#endif + +#if defined( FL1_SET ) + d_1(uint_32t, t_dec(f,l), sb_data, w0); +#endif +#if defined( FL4_SET ) + d_4(uint_32t, t_dec(f,l), sb_data, w0, w1, w2, w3); +#endif + +#if defined( IT1_SET ) + d_1(uint_32t, t_dec(i,n), isb_data, v0); +#endif +#if defined( IT4_SET ) + d_4(uint_32t, t_dec(i,n), isb_data, v0, v1, v2, v3); +#endif + +#if defined( IL1_SET ) + d_1(uint_32t, t_dec(i,l), isb_data, w0); +#endif +#if defined( IL4_SET ) + d_4(uint_32t, t_dec(i,l), isb_data, w0, w1, w2, w3); +#endif + +#if defined( LS1_SET ) +#if defined( FL1_SET ) +#undef LS1_SET +#else + d_1(uint_32t, t_dec(l,s), sb_data, w0); +#endif +#endif + +#if defined( LS4_SET ) +#if defined( FL4_SET ) +#undef LS4_SET +#else + d_4(uint_32t, t_dec(l,s), sb_data, w0, w1, w2, w3); +#endif +#endif + +#if defined( IM1_SET ) + d_1(uint_32t, t_dec(i,m), mm_data, v0); +#endif +#if defined( IM4_SET ) + d_4(uint_32t, t_dec(i,m), mm_data, v0, v1, v2, v3); +#endif + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/SSZipArchive/aes/brg_endian.h b/SSZipArchive/aes/brg_endian.h new file mode 100755 index 0000000..82e48f0 --- /dev/null +++ b/SSZipArchive/aes/brg_endian.h @@ -0,0 +1,126 @@ +/* +--------------------------------------------------------------------------- +Copyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved. + +The redistribution and use of this software (with or without changes) +is allowed without the payment of fees or royalties provided that: + + source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation. + +This software is provided 'as is' with no explicit or implied warranties +in respect of its operation, including, but not limited to, correctness +and fitness for purpose. +--------------------------------------------------------------------------- +Issue Date: 20/12/2007 +*/ + +#ifndef _BRG_ENDIAN_H +#define _BRG_ENDIAN_H + +#define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ +#define IS_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ + +/* Include files where endian defines and byteswap functions may reside */ +#if defined( __sun ) +# include +#elif defined( __FreeBSD__ ) || defined( __OpenBSD__ ) || defined( __NetBSD__ ) +# include +#elif defined( BSD ) && ( BSD >= 199103 ) || defined( __APPLE__ ) || \ + defined( __CYGWIN32__ ) || defined( __DJGPP__ ) || defined( __osf__ ) +# include +#elif defined( __linux__ ) || defined( __GNUC__ ) || defined( __GNU_LIBRARY__ ) +# if !defined( __MINGW32__ ) && !defined( _AIX ) +# include +# if !defined( __BEOS__ ) +# include +# endif +# endif +#endif + +/* Now attempt to set the define for platform byte order using any */ +/* of the four forms SYMBOL, _SYMBOL, __SYMBOL & __SYMBOL__, which */ +/* seem to encompass most endian symbol definitions */ + +#if defined( BIG_ENDIAN ) && defined( LITTLE_ENDIAN ) +# if defined( BYTE_ORDER ) && BYTE_ORDER == BIG_ENDIAN +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +# elif defined( BYTE_ORDER ) && BYTE_ORDER == LITTLE_ENDIAN +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +# endif +#elif defined( BIG_ENDIAN ) +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +#elif defined( LITTLE_ENDIAN ) +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +#endif + +#if defined( _BIG_ENDIAN ) && defined( _LITTLE_ENDIAN ) +# if defined( _BYTE_ORDER ) && _BYTE_ORDER == _BIG_ENDIAN +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +# elif defined( _BYTE_ORDER ) && _BYTE_ORDER == _LITTLE_ENDIAN +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +# endif +#elif defined( _BIG_ENDIAN ) +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +#elif defined( _LITTLE_ENDIAN ) +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +#endif + +#if defined( __BIG_ENDIAN ) && defined( __LITTLE_ENDIAN ) +# if defined( __BYTE_ORDER ) && __BYTE_ORDER == __BIG_ENDIAN +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +# elif defined( __BYTE_ORDER ) && __BYTE_ORDER == __LITTLE_ENDIAN +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +# endif +#elif defined( __BIG_ENDIAN ) +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +#elif defined( __LITTLE_ENDIAN ) +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +#endif + +#if defined( __BIG_ENDIAN__ ) && defined( __LITTLE_ENDIAN__ ) +# if defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __BIG_ENDIAN__ +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +# elif defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __LITTLE_ENDIAN__ +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +# endif +#elif defined( __BIG_ENDIAN__ ) +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +#elif defined( __LITTLE_ENDIAN__ ) +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +#endif + +/* if the platform byte order could not be determined, then try to */ +/* set this define using common machine defines */ +#if !defined(PLATFORM_BYTE_ORDER) + +#if defined( __alpha__ ) || defined( __alpha ) || defined( i386 ) || \ + defined( __i386__ ) || defined( _M_I86 ) || defined( _M_IX86 ) || \ + defined( __OS2__ ) || defined( sun386 ) || defined( __TURBOC__ ) || \ + defined( vax ) || defined( vms ) || defined( VMS ) || \ + defined( __VMS ) || defined( _M_X64 ) +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN + +#elif defined( AMIGA ) || defined( applec ) || defined( __AS400__ ) || \ + defined( _CRAY ) || defined( __hppa ) || defined( __hp9000 ) || \ + defined( ibm370 ) || defined( mc68000 ) || defined( m68k ) || \ + defined( __MRC__ ) || defined( __MVS__ ) || defined( __MWERKS__ ) || \ + defined( sparc ) || defined( __sparc) || defined( SYMANTEC_C ) || \ + defined( __VOS__ ) || defined( __TIGCC__ ) || defined( __TANDEM ) || \ + defined( THINK_C ) || defined( __VMCMS__ ) || defined( _AIX ) +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN + +#elif 0 /* **** EDIT HERE IF NECESSARY **** */ +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +#elif 0 /* **** EDIT HERE IF NECESSARY **** */ +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +#else +# error Please edit lines 126 or 128 in brg_endian.h to set the platform byte order +#endif + +#endif + +#endif diff --git a/SSZipArchive/aes/brg_types.h b/SSZipArchive/aes/brg_types.h new file mode 100755 index 0000000..40d4af5 --- /dev/null +++ b/SSZipArchive/aes/brg_types.h @@ -0,0 +1,219 @@ +/* +--------------------------------------------------------------------------- +Copyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved. + +The redistribution and use of this software (with or without changes) +is allowed without the payment of fees or royalties provided that: + + source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation. + +This software is provided 'as is' with no explicit or implied warranties +in respect of its operation, including, but not limited to, correctness +and fitness for purpose. +--------------------------------------------------------------------------- +Issue Date: 20/12/2007 + + The unsigned integer types defined here are of the form uint_t where + is the length of the type; for example, the unsigned 32-bit type is + 'uint_32t'. These are NOT the same as the 'C99 integer types' that are + defined in the inttypes.h and stdint.h headers since attempts to use these + types have shown that support for them is still highly variable. However, + since the latter are of the form uint_t, a regular expression search + and replace (in VC++ search on 'uint_{:z}t' and replace with 'uint\1_t') + can be used to convert the types used here to the C99 standard types. +*/ + +#ifndef _BRG_TYPES_H +#define _BRG_TYPES_H + +#if defined(__cplusplus) +extern "C" { +#endif + +#include + +#if defined( _MSC_VER ) && ( _MSC_VER >= 1300 ) +# include +# define ptrint_t intptr_t +#elif defined( __ECOS__ ) +# define intptr_t unsigned int +# define ptrint_t intptr_t +#elif defined( __GNUC__ ) && ( __GNUC__ >= 3 ) +# include +# define ptrint_t intptr_t +#else +# define ptrint_t int +#endif + +#ifndef BRG_UI8 +# define BRG_UI8 +# if UCHAR_MAX == 255u + typedef unsigned char uint_8t; +# else +# error Please define uint_8t as an 8-bit unsigned integer type in brg_types.h +# endif +#endif + +#ifndef BRG_UI16 +# define BRG_UI16 +# if USHRT_MAX == 65535u + typedef unsigned short uint_16t; +# else +# error Please define uint_16t as a 16-bit unsigned short type in brg_types.h +# endif +#endif + +#ifndef BRG_UI32 +# define BRG_UI32 +# if UINT_MAX == 4294967295u +# define li_32(h) 0x##h##u + typedef unsigned int uint_32t; +# elif ULONG_MAX == 4294967295u +# define li_32(h) 0x##h##ul + typedef unsigned long uint_32t; +# elif defined( _CRAY ) +# error This code needs 32-bit data types, which Cray machines do not provide +# else +# error Please define uint_32t as a 32-bit unsigned integer type in brg_types.h +# endif +#endif + +#ifndef BRG_UI64 +# if defined( __BORLANDC__ ) && !defined( __MSDOS__ ) +# define BRG_UI64 +# define li_64(h) 0x##h##ui64 + typedef unsigned __int64 uint_64t; +# elif defined( _MSC_VER ) && ( _MSC_VER < 1300 ) /* 1300 == VC++ 7.0 */ +# define BRG_UI64 +# define li_64(h) 0x##h##ui64 + typedef unsigned __int64 uint_64t; +# elif defined( __sun ) && defined( ULONG_MAX ) && ULONG_MAX == 0xfffffffful +# define BRG_UI64 +# define li_64(h) 0x##h##ull + typedef unsigned long long uint_64t; +# elif defined( __MVS__ ) +# define BRG_UI64 +# define li_64(h) 0x##h##ull + typedef unsigned int long long uint_64t; +# elif defined( UINT_MAX ) && UINT_MAX > 4294967295u +# if UINT_MAX == 18446744073709551615u +# define BRG_UI64 +# define li_64(h) 0x##h##u + typedef unsigned int uint_64t; +# endif +# elif defined( ULONG_MAX ) && ULONG_MAX > 4294967295u +# if ULONG_MAX == 18446744073709551615ul +# define BRG_UI64 +# define li_64(h) 0x##h##ul + typedef unsigned long uint_64t; +# endif +# elif defined( ULLONG_MAX ) && ULLONG_MAX > 4294967295u +# if ULLONG_MAX == 18446744073709551615ull +# define BRG_UI64 +# define li_64(h) 0x##h##ull + typedef unsigned long long uint_64t; +# endif +# elif defined( ULONG_LONG_MAX ) && ULONG_LONG_MAX > 4294967295u +# if ULONG_LONG_MAX == 18446744073709551615ull +# define BRG_UI64 +# define li_64(h) 0x##h##ull + typedef unsigned long long uint_64t; +# endif +# endif +#endif + +#if !defined( BRG_UI64 ) +# if defined( NEED_UINT_64T ) +# error Please define uint_64t as an unsigned 64 bit type in brg_types.h +# endif +#endif + +#ifndef RETURN_VALUES +# define RETURN_VALUES +# if defined( DLL_EXPORT ) +# if defined( _MSC_VER ) || defined ( __INTEL_COMPILER ) +# define VOID_RETURN __declspec( dllexport ) void __stdcall +# define INT_RETURN __declspec( dllexport ) int __stdcall +# elif defined( __GNUC__ ) +# define VOID_RETURN __declspec( __dllexport__ ) void +# define INT_RETURN __declspec( __dllexport__ ) int +# else +# error Use of the DLL is only available on the Microsoft, Intel and GCC compilers +# endif +# elif defined( DLL_IMPORT ) +# if defined( _MSC_VER ) || defined ( __INTEL_COMPILER ) +# define VOID_RETURN __declspec( dllimport ) void __stdcall +# define INT_RETURN __declspec( dllimport ) int __stdcall +# elif defined( __GNUC__ ) +# define VOID_RETURN __declspec( __dllimport__ ) void +# define INT_RETURN __declspec( __dllimport__ ) int +# else +# error Use of the DLL is only available on the Microsoft, Intel and GCC compilers +# endif +# elif defined( __WATCOMC__ ) +# define VOID_RETURN void __cdecl +# define INT_RETURN int __cdecl +# else +# define VOID_RETURN void +# define INT_RETURN int +# endif +#endif + +/* These defines are used to detect and set the memory alignment of pointers. + Note that offsets are in bytes. + + ALIGN_OFFSET(x,n) return the positive or zero offset of + the memory addressed by the pointer 'x' + from an address that is aligned on an + 'n' byte boundary ('n' is a power of 2) + + ALIGN_FLOOR(x,n) return a pointer that points to memory + that is aligned on an 'n' byte boundary + and is not higher than the memory address + pointed to by 'x' ('n' is a power of 2) + + ALIGN_CEIL(x,n) return a pointer that points to memory + that is aligned on an 'n' byte boundary + and is not lower than the memory address + pointed to by 'x' ('n' is a power of 2) +*/ + +#define ALIGN_OFFSET(x,n) (((ptrint_t)(x)) & ((n) - 1)) +#define ALIGN_FLOOR(x,n) ((uint_8t*)(x) - ( ((ptrint_t)(x)) & ((n) - 1))) +#define ALIGN_CEIL(x,n) ((uint_8t*)(x) + (-((ptrint_t)(x)) & ((n) - 1))) + +/* These defines are used to declare buffers in a way that allows + faster operations on longer variables to be used. In all these + defines 'size' must be a power of 2 and >= 8. NOTE that the + buffer size is in bytes but the type length is in bits + + UNIT_TYPEDEF(x,size) declares a variable 'x' of length + 'size' bits + + BUFR_TYPEDEF(x,size,bsize) declares a buffer 'x' of length 'bsize' + bytes defined as an array of variables + each of 'size' bits (bsize must be a + multiple of size / 8) + + UNIT_CAST(x,size) casts a variable to a type of + length 'size' bits + + UPTR_CAST(x,size) casts a pointer to a pointer to a + varaiable of length 'size' bits +*/ + +#define UI_TYPE(size) uint_##size##t +#define UNIT_TYPEDEF(x,size) typedef UI_TYPE(size) x +#define BUFR_TYPEDEF(x,size,bsize) typedef UI_TYPE(size) x[bsize / (size >> 3)] +#define UNIT_CAST(x,size) ((UI_TYPE(size) )(x)) +#define UPTR_CAST(x,size) ((UI_TYPE(size)*)(x)) + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/SSZipArchive/aes/entropy.c b/SSZipArchive/aes/entropy.c new file mode 100755 index 0000000..5840a97 --- /dev/null +++ b/SSZipArchive/aes/entropy.c @@ -0,0 +1,54 @@ +#ifdef _WIN32 +#include +#else +#include +#include +#include +#endif + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#ifdef _WIN32 +int entropy_fun(unsigned char buf[], unsigned int len) +{ + HCRYPTPROV provider; + unsigned __int64 pentium_tsc[1]; + unsigned int i; + int result = 0; + + + if (CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) + { + result = CryptGenRandom(provider, len, buf); + CryptReleaseContext(provider, 0); + if (result) + return len; + } + + QueryPerformanceCounter((LARGE_INTEGER *)pentium_tsc); + + for(i = 0; i < 8 && i < len; ++i) + buf[i] = ((unsigned char*)pentium_tsc)[i]; + + return i; +} +#else +int entropy_fun(unsigned char buf[], unsigned int len) +{ + int frand = open("/dev/random", O_RDONLY); + int rlen = 0; + if (frand != -1) + { + rlen = (int)read(frand, buf, len); + close(frand); + } + return rlen; +} +#endif + +#if defined(__cplusplus) +} +#endif diff --git a/SSZipArchive/aes/entropy.h b/SSZipArchive/aes/entropy.h new file mode 100755 index 0000000..306620c --- /dev/null +++ b/SSZipArchive/aes/entropy.h @@ -0,0 +1,16 @@ + +#ifndef _ENTROPY_FUN_H +#define _ENTROPY_FUN_H + +#if defined(__cplusplus) +extern "C" +{ +#endif + +int entropy_fun(unsigned char buf[], unsigned int len); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/SSZipArchive/aes/fileenc.c b/SSZipArchive/aes/fileenc.c new file mode 100755 index 0000000..5057036 --- /dev/null +++ b/SSZipArchive/aes/fileenc.c @@ -0,0 +1,144 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK. + All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + ALTERNATIVELY, provided that this notice is retained in full, this product + may be distributed under the terms of the GNU General Public License (GPL), + in which case the provisions of the GPL apply INSTEAD OF those given above. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + ------------------------------------------------------------------------- + Issue Date: 24/01/2003 + + This file implements password based file encryption and authentication + using AES in CTR mode, HMAC-SHA1 authentication and RFC2898 password + based key derivation. + + */ + +#include + +#include "fileenc.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* subroutine for data encryption/decryption */ +/* this could be speeded up a lot by aligning */ +/* buffers and using 32 bit operations */ + +static void encr_data(unsigned char data[], unsigned long d_len, fcrypt_ctx cx[1]) +{ + unsigned long i = 0, pos = cx->encr_pos; + + while (i < d_len) { + if (pos == AES_BLOCK_SIZE) { + unsigned int j = 0; + /* increment encryption nonce */ + while (j < 8 && !++cx->nonce[j]) + ++j; + /* encrypt the nonce to form next xor buffer */ + aes_encrypt(cx->nonce, cx->encr_bfr, cx->encr_ctx); + pos = 0; + } + + data[i++] ^= cx->encr_bfr[pos++]; + } + + cx->encr_pos = (unsigned int)pos; +} + +int fcrypt_init( + int mode, /* the mode to be used (input) */ + const unsigned char pwd[], /* the user specified password (input) */ + unsigned int pwd_len, /* the length of the password (input) */ + const unsigned char salt[], /* the salt (input) */ +#ifdef PASSWORD_VERIFIER + unsigned char pwd_ver[PWD_VER_LENGTH], /* 2 byte password verifier (output) */ +#endif + fcrypt_ctx cx[1]) /* the file encryption context (output) */ +{ + unsigned char kbuf[2 * MAX_KEY_LENGTH + PWD_VER_LENGTH]; + + if (pwd_len > MAX_PWD_LENGTH) + return PASSWORD_TOO_LONG; + + if (mode < 1 || mode > 3) + return BAD_MODE; + + cx->mode = mode; + cx->pwd_len = pwd_len; + + /* derive the encryption and authentication keys and the password verifier */ + derive_key(pwd, pwd_len, salt, SALT_LENGTH(mode), KEYING_ITERATIONS, + kbuf, 2 * KEY_LENGTH(mode) + PWD_VER_LENGTH); + + /* initialise the encryption nonce and buffer pos */ + cx->encr_pos = AES_BLOCK_SIZE; + /* if we need a random component in the encryption */ + /* nonce, this is where it would have to be set */ + memset(cx->nonce, 0, AES_BLOCK_SIZE * sizeof(unsigned char)); + + /* initialise for encryption using key 1 */ + aes_encrypt_key(kbuf, KEY_LENGTH(mode), cx->encr_ctx); + + /* initialise for authentication using key 2 */ + hmac_sha_begin(cx->auth_ctx); + hmac_sha_key(kbuf + KEY_LENGTH(mode), KEY_LENGTH(mode), cx->auth_ctx); + +#ifdef PASSWORD_VERIFIER + memcpy(pwd_ver, kbuf + 2 * KEY_LENGTH(mode), PWD_VER_LENGTH); +#endif + + return GOOD_RETURN; +} + +/* perform 'in place' encryption and authentication */ + +void fcrypt_encrypt(unsigned char data[], unsigned int data_len, fcrypt_ctx cx[1]) +{ + encr_data(data, data_len, cx); + hmac_sha_data(data, data_len, cx->auth_ctx); +} + +/* perform 'in place' authentication and decryption */ + +void fcrypt_decrypt(unsigned char data[], unsigned int data_len, fcrypt_ctx cx[1]) +{ + hmac_sha_data(data, data_len, cx->auth_ctx); + encr_data(data, data_len, cx); +} + +/* close encryption/decryption and return the MAC value */ + +int fcrypt_end(unsigned char mac[], fcrypt_ctx cx[1]) +{ + hmac_sha_end(mac, MAC_LENGTH(cx->mode), cx->auth_ctx); + return MAC_LENGTH(cx->mode); /* return MAC length in bytes */ +} + +#if defined(__cplusplus) +} +#endif diff --git a/SSZipArchive/aes/fileenc.h b/SSZipArchive/aes/fileenc.h new file mode 100755 index 0000000..ba64a7c --- /dev/null +++ b/SSZipArchive/aes/fileenc.h @@ -0,0 +1,121 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK. + All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + ALTERNATIVELY, provided that this notice is retained in full, this product + may be distributed under the terms of the GNU General Public License (GPL), + in which case the provisions of the GPL apply INSTEAD OF those given above. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 24/01/2003 + + This file contains the header file for fileenc.c, which implements password + based file encryption and authentication using AES in CTR mode, HMAC-SHA1 + authentication and RFC2898 password based key derivation. +*/ + +#ifndef _FENC_H +#define _FENC_H + +#include "aes.h" +#include "hmac.h" +#include "pwd2key.h" + +#define PASSWORD_VERIFIER + +#define MAX_KEY_LENGTH 32 +#define MAX_PWD_LENGTH 128 +#define MAX_SALT_LENGTH 16 +#define KEYING_ITERATIONS 1000 + +#ifdef PASSWORD_VERIFIER +#define PWD_VER_LENGTH 2 +#else +#define PWD_VER_LENGTH 0 +#endif + +#define GOOD_RETURN 0 +#define PASSWORD_TOO_LONG -100 +#define BAD_MODE -101 + +/* + Field lengths (in bytes) versus File Encryption Mode (0 < mode < 4) + + Mode Key Salt MAC Overhead + 1 16 8 10 18 + 2 24 12 10 22 + 3 32 16 10 26 + + The following macros assume that the mode value is correct. +*/ + +#define KEY_LENGTH(mode) (8 * (mode & 3) + 8) +#define SALT_LENGTH(mode) (4 * (mode & 3) + 4) +#define MAC_LENGTH(mode) (10) + +/* the context for file encryption */ + +#if defined(__cplusplus) +extern "C" +{ +#endif + +typedef struct +{ unsigned char nonce[AES_BLOCK_SIZE]; /* the CTR nonce */ + unsigned char encr_bfr[AES_BLOCK_SIZE]; /* encrypt buffer */ + aes_encrypt_ctx encr_ctx[1]; /* encryption context */ + hmac_ctx auth_ctx[1]; /* authentication context */ + unsigned int encr_pos; /* block position (enc) */ + unsigned int pwd_len; /* password length */ + unsigned int mode; /* File encryption mode */ +} fcrypt_ctx; + +/* initialise file encryption or decryption */ + +int fcrypt_init( + int mode, /* the mode to be used (input) */ + const unsigned char pwd[], /* the user specified password (input) */ + unsigned int pwd_len, /* the length of the password (input) */ + const unsigned char salt[], /* the salt (input) */ +#ifdef PASSWORD_VERIFIER + unsigned char pwd_ver[PWD_VER_LENGTH], /* 2 byte password verifier (output) */ +#endif + fcrypt_ctx cx[1]); /* the file encryption context (output) */ + +/* perform 'in place' encryption or decryption and authentication */ + +void fcrypt_encrypt(unsigned char data[], unsigned int data_len, fcrypt_ctx cx[1]); +void fcrypt_decrypt(unsigned char data[], unsigned int data_len, fcrypt_ctx cx[1]); + +/* close encryption/decryption and return the MAC value */ +/* the return value is the length of the MAC */ + +int fcrypt_end(unsigned char mac[], /* the MAC value (output) */ + fcrypt_ctx cx[1]); /* the context (input) */ + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/SSZipArchive/aes/hmac.c b/SSZipArchive/aes/hmac.c new file mode 100755 index 0000000..c71b14e --- /dev/null +++ b/SSZipArchive/aes/hmac.c @@ -0,0 +1,145 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + ALTERNATIVELY, provided that this notice is retained in full, this product + may be distributed under the terms of the GNU General Public License (GPL), + in which case the provisions of the GPL apply INSTEAD OF those given above. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 26/08/2003 + + This is an implementation of HMAC, the FIPS standard keyed hash function +*/ + +#include "hmac.h" +#include "brg_types.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* initialise the HMAC context to zero */ +void hmac_sha_begin(hmac_ctx cx[1]) +{ + memset(cx, 0, sizeof(hmac_ctx)); +} + +/* input the HMAC key (can be called multiple times) */ +int hmac_sha_key(const unsigned char key[], unsigned long key_len, hmac_ctx cx[1]) +{ + if(cx->klen == HMAC_IN_DATA) /* error if further key input */ + return HMAC_BAD_MODE; /* is attempted in data mode */ + + if(cx->klen + key_len > HASH_INPUT_SIZE) /* if the key has to be hashed */ + { + if(cx->klen <= HASH_INPUT_SIZE) /* if the hash has not yet been */ + { /* started, initialise it and */ + sha_begin(cx->ctx); /* hash stored key characters */ + sha_hash(cx->key, cx->klen, cx->ctx); + } + + sha_hash(key, key_len, cx->ctx); /* hash long key data into hash */ + } + else /* otherwise store key data */ + memcpy(cx->key + cx->klen, key, key_len); + + cx->klen += key_len; /* update the key length count */ + return HMAC_OK; +} + +/* input the HMAC data (can be called multiple times) - */ +/* note that this call terminates the key input phase */ +void hmac_sha_data(const unsigned char data[], unsigned long data_len, hmac_ctx cx[1]) +{ unsigned int i; + + if(cx->klen != HMAC_IN_DATA) /* if not yet in data phase */ + { + if(cx->klen > HASH_INPUT_SIZE) /* if key is being hashed */ + { /* complete the hash and */ + sha_end(cx->key, cx->ctx); /* store the result as the */ + cx->klen = HASH_OUTPUT_SIZE; /* key and set new length */ + } + + /* pad the key if necessary */ + memset(cx->key + cx->klen, 0, HASH_INPUT_SIZE - cx->klen); + + /* xor ipad into key value */ + for(i = 0; i < (HASH_INPUT_SIZE >> 2); ++i) + ((uint_32t*)cx->key)[i] ^= 0x36363636; + + /* and start hash operation */ + sha_begin(cx->ctx); + sha_hash(cx->key, HASH_INPUT_SIZE, cx->ctx); + + /* mark as now in data mode */ + cx->klen = HMAC_IN_DATA; + } + + /* hash the data (if any) */ + if(data_len) + sha_hash(data, data_len, cx->ctx); +} + +/* compute and output the MAC value */ +void hmac_sha_end(unsigned char mac[], unsigned long mac_len, hmac_ctx cx[1]) +{ unsigned char dig[HASH_OUTPUT_SIZE]; + unsigned int i; + + /* if no data has been entered perform a null data phase */ + if(cx->klen != HMAC_IN_DATA) + hmac_sha_data((const unsigned char*)0, 0, cx); + + sha_end(dig, cx->ctx); /* complete the inner hash */ + + /* set outer key value using opad and removing ipad */ + for(i = 0; i < (HASH_INPUT_SIZE >> 2); ++i) + ((uint_32t*)cx->key)[i] ^= 0x36363636 ^ 0x5c5c5c5c; + + /* perform the outer hash operation */ + sha_begin(cx->ctx); + sha_hash(cx->key, HASH_INPUT_SIZE, cx->ctx); + sha_hash(dig, HASH_OUTPUT_SIZE, cx->ctx); + sha_end(dig, cx->ctx); + + /* output the hash value */ + for(i = 0; i < mac_len; ++i) + mac[i] = dig[i]; +} + +/* 'do it all in one go' subroutine */ +void hmac_sha(const unsigned char key[], unsigned long key_len, + const unsigned char data[], unsigned long data_len, + unsigned char mac[], unsigned long mac_len) +{ hmac_ctx cx[1]; + + hmac_sha_begin(cx); + hmac_sha_key(key, key_len, cx); + hmac_sha_data(data, data_len, cx); + hmac_sha_end(mac, mac_len, cx); +} + +#if defined(__cplusplus) +} +#endif diff --git a/SSZipArchive/aes/hmac.h b/SSZipArchive/aes/hmac.h new file mode 100755 index 0000000..643037c --- /dev/null +++ b/SSZipArchive/aes/hmac.h @@ -0,0 +1,103 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + ALTERNATIVELY, provided that this notice is retained in full, this product + may be distributed under the terms of the GNU General Public License (GPL), + in which case the provisions of the GPL apply INSTEAD OF those given above. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 26/08/2003 + + This is an implementation of HMAC, the FIPS standard keyed hash function +*/ + +#ifndef _HMAC_H +#define _HMAC_H + +#include + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#define USE_SHA1 + +#if !defined(USE_SHA1) && !defined(USE_SHA256) +#error define USE_SHA1 or USE_SHA256 to set the HMAC hash algorithm +#endif + +#ifdef USE_SHA1 + +#include "sha1.h" + +#define HASH_INPUT_SIZE SHA1_BLOCK_SIZE +#define HASH_OUTPUT_SIZE SHA1_DIGEST_SIZE +#define sha_ctx sha1_ctx +#define sha_begin sha1_begin +#define sha_hash sha1_hash +#define sha_end sha1_end + +#endif + +#ifdef USE_SHA256 + +#include "sha2.h" + +#define HASH_INPUT_SIZE SHA256_BLOCK_SIZE +#define HASH_OUTPUT_SIZE SHA256_DIGEST_SIZE +#define sha_ctx sha256_ctx +#define sha_begin sha256_begin +#define sha_hash sha256_hash +#define sha_end sha256_end + +#endif + +#define HMAC_OK 0 +#define HMAC_BAD_MODE -1 +#define HMAC_IN_DATA 0xffffffff + +typedef struct +{ unsigned char key[HASH_INPUT_SIZE]; + sha_ctx ctx[1]; + unsigned long klen; +} hmac_ctx; + +void hmac_sha_begin(hmac_ctx cx[1]); + +int hmac_sha_key(const unsigned char key[], unsigned long key_len, hmac_ctx cx[1]); + +void hmac_sha_data(const unsigned char data[], unsigned long data_len, hmac_ctx cx[1]); + +void hmac_sha_end(unsigned char mac[], unsigned long mac_len, hmac_ctx cx[1]); + +void hmac_sha(const unsigned char key[], unsigned long key_len, + const unsigned char data[], unsigned long data_len, + unsigned char mac[], unsigned long mac_len); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/SSZipArchive/aes/prng.c b/SSZipArchive/aes/prng.c new file mode 100755 index 0000000..2f91090 --- /dev/null +++ b/SSZipArchive/aes/prng.c @@ -0,0 +1,155 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK. + All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + ALTERNATIVELY, provided that this notice is retained in full, this product + may be distributed under the terms of the GNU General Public License (GPL), + in which case the provisions of the GPL apply INSTEAD OF those given above. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 24/01/2003 + + This file implements a random data pool based on the use of an external + entropy function. It is based on the ideas advocated by Peter Gutmann in + his work on pseudo random sequence generators. It is not a 'paranoid' + random sequence generator and no attempt is made to protect the pool + from prying eyes either by memory locking or by techniques to obscure + its location in memory. +*/ + +#include +#include "prng.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* mix a random data pool using the SHA1 compression function (as */ +/* suggested by Peter Gutmann in his paper on random pools) */ + +static void prng_mix(unsigned char buf[]) +{ unsigned int i, len; + sha1_ctx ctx[1]; + + /*lint -e{663} unusual array to pointer conversion */ + for(i = 0; i < PRNG_POOL_SIZE; i += SHA1_DIGEST_SIZE) + { + /* copy digest size pool block into SHA1 hash block */ + memcpy(ctx->hash, buf + (i ? i : PRNG_POOL_SIZE) + - SHA1_DIGEST_SIZE, SHA1_DIGEST_SIZE); + + /* copy data from pool into the SHA1 data buffer */ + len = PRNG_POOL_SIZE - i; + memcpy(ctx->wbuf, buf + i, (len > SHA1_BLOCK_SIZE ? SHA1_BLOCK_SIZE : len)); + + if(len < SHA1_BLOCK_SIZE) + memcpy(((char*)ctx->wbuf) + len, buf, SHA1_BLOCK_SIZE - len); + + /* compress using the SHA1 compression function */ + sha1_compile(ctx); + + /* put digest size block back into the random pool */ + memcpy(buf + i, ctx->hash, SHA1_DIGEST_SIZE); + } +} + +/* refresh the output buffer and update the random pool by adding */ +/* entropy and remixing */ + +static void update_pool(prng_ctx ctx[1]) +{ unsigned int i = 0; + + /* transfer random pool data to the output buffer */ + memcpy(ctx->obuf, ctx->rbuf, PRNG_POOL_SIZE); + + /* enter entropy data into the pool */ + while(i < PRNG_POOL_SIZE) + i += ctx->entropy(ctx->rbuf + i, PRNG_POOL_SIZE - i); + + /* invert and xor the original pool data into the pool */ + for(i = 0; i < PRNG_POOL_SIZE; ++i) + ctx->rbuf[i] ^= ~ctx->obuf[i]; + + /* mix the pool and the output buffer */ + prng_mix(ctx->rbuf); + prng_mix(ctx->obuf); +} + +void prng_init(prng_entropy_fn fun, prng_ctx ctx[1]) +{ int i; + + /* clear the buffers and the counter in the context */ + memset(ctx, 0, sizeof(prng_ctx)); + + /* set the pointer to the entropy collection function */ + ctx->entropy = fun; + + /* initialise the random data pool */ + update_pool(ctx); + + /* mix the pool a minimum number of times */ + for(i = 0; i < PRNG_MIN_MIX; ++i) + prng_mix(ctx->rbuf); + + /* update the pool to prime the pool output buffer */ + update_pool(ctx); +} + +/* provide random bytes from the random data pool */ + +void prng_rand(unsigned char data[], unsigned int data_len, prng_ctx ctx[1]) +{ unsigned char *rp = data; + unsigned int len, pos = ctx->pos; + + while(data_len) + { + /* transfer 'data_len' bytes (or the number of bytes remaining */ + /* the pool output buffer if less) into the output */ + len = (data_len < PRNG_POOL_SIZE - pos ? data_len : PRNG_POOL_SIZE - pos); + memcpy(rp, ctx->obuf + pos, len); + rp += len; /* update ouput buffer position pointer */ + pos += len; /* update pool output buffer pointer */ + data_len -= len; /* update the remaining data count */ + + /* refresh the random pool if necessary */ + if(pos == PRNG_POOL_SIZE) + { + update_pool(ctx); pos = 0; + } + } + + ctx->pos = pos; +} + +void prng_end(prng_ctx ctx[1]) +{ + /* ensure the data in the context is destroyed */ + memset(ctx, 0, sizeof(prng_ctx)); +} + +#if defined(__cplusplus) +} +#endif + diff --git a/SSZipArchive/aes/prng.h b/SSZipArchive/aes/prng.h new file mode 100755 index 0000000..f934b51 --- /dev/null +++ b/SSZipArchive/aes/prng.h @@ -0,0 +1,82 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK. + All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + ALTERNATIVELY, provided that this notice is retained in full, this product + may be distributed under the terms of the GNU General Public License (GPL), + in which case the provisions of the GPL apply INSTEAD OF those given above. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 24/01/2003 + + This is the header file for an implementation of a random data pool based on + the use of an external entropy function (inspired by Peter Gutmann's work). +*/ + +#ifndef _PRNG_H +#define _PRNG_H + +#include "sha1.h" + +#define PRNG_POOL_LEN 256 /* minimum random pool size */ +#define PRNG_MIN_MIX 20 /* min initial pool mixing iterations */ + +/* ensure that pool length is a multiple of the SHA1 digest size */ + +#define PRNG_POOL_SIZE (SHA1_DIGEST_SIZE * (1 + (PRNG_POOL_LEN - 1) / SHA1_DIGEST_SIZE)) + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* A function for providing entropy is a parameter in the prng_init() */ +/* call. This function has the following form and returns a maximum */ +/* of 'len' bytes of pseudo random data in the buffer 'buf'. It can */ +/* return less than 'len' bytes but will be repeatedly called for more */ +/* data in this case. */ + +typedef int (*prng_entropy_fn)(unsigned char buf[], unsigned int len); + +typedef struct +{ unsigned char rbuf[PRNG_POOL_SIZE]; /* the random pool */ + unsigned char obuf[PRNG_POOL_SIZE]; /* pool output buffer */ + unsigned int pos; /* output buffer position */ + prng_entropy_fn entropy; /* entropy function pointer */ +} prng_ctx; + +/* initialise the random stream generator */ +void prng_init(prng_entropy_fn fun, prng_ctx ctx[1]); + +/* obtain random bytes from the generator */ +void prng_rand(unsigned char data[], unsigned int data_len, prng_ctx ctx[1]); + +/* close the random stream generator */ +void prng_end(prng_ctx ctx[1]); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/SSZipArchive/aes/pwd2key.c b/SSZipArchive/aes/pwd2key.c new file mode 100755 index 0000000..80a4760 --- /dev/null +++ b/SSZipArchive/aes/pwd2key.c @@ -0,0 +1,193 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + ALTERNATIVELY, provided that this notice is retained in full, this product + may be distributed under the terms of the GNU General Public License (GPL), + in which case the provisions of the GPL apply INSTEAD OF those given above. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 26/08/2003 + + This is an implementation of RFC2898, which specifies key derivation from + a password and a salt value. +*/ + +#include +#include "hmac.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +void derive_key(const unsigned char pwd[], /* the PASSWORD */ + unsigned int pwd_len, /* and its length */ + const unsigned char salt[], /* the SALT and its */ + unsigned int salt_len, /* length */ + unsigned int iter, /* the number of iterations */ + unsigned char key[], /* space for the output key */ + unsigned int key_len)/* and its required length */ +{ + unsigned int i, j, k, n_blk; + unsigned char uu[HASH_OUTPUT_SIZE], ux[HASH_OUTPUT_SIZE]; + hmac_ctx c1[1], c2[1], c3[1]; + + /* set HMAC context (c1) for password */ + hmac_sha_begin(c1); + hmac_sha_key(pwd, pwd_len, c1); + + /* set HMAC context (c2) for password and salt */ + memcpy(c2, c1, sizeof(hmac_ctx)); + hmac_sha_data(salt, salt_len, c2); + + /* find the number of SHA blocks in the key */ + n_blk = 1 + (key_len - 1) / HASH_OUTPUT_SIZE; + + for(i = 0; i < n_blk; ++i) /* for each block in key */ + { + /* ux[] holds the running xor value */ + memset(ux, 0, HASH_OUTPUT_SIZE); + + /* set HMAC context (c3) for password and salt */ + memcpy(c3, c2, sizeof(hmac_ctx)); + + /* enter additional data for 1st block into uu */ + uu[0] = (unsigned char)((i + 1) >> 24); + uu[1] = (unsigned char)((i + 1) >> 16); + uu[2] = (unsigned char)((i + 1) >> 8); + uu[3] = (unsigned char)(i + 1); + + /* this is the key mixing iteration */ + for(j = 0, k = 4; j < iter; ++j) + { + /* add previous round data to HMAC */ + hmac_sha_data(uu, k, c3); + + /* obtain HMAC for uu[] */ + hmac_sha_end(uu, HASH_OUTPUT_SIZE, c3); + + /* xor into the running xor block */ + for(k = 0; k < HASH_OUTPUT_SIZE; ++k) + ux[k] ^= uu[k]; + + /* set HMAC context (c3) for password */ + memcpy(c3, c1, sizeof(hmac_ctx)); + } + + /* compile key blocks into the key output */ + j = 0; k = i * HASH_OUTPUT_SIZE; + while(j < HASH_OUTPUT_SIZE && k < key_len) + key[k++] = ux[j++]; + } +} + +#ifdef TEST + +#include + +struct +{ unsigned int pwd_len; + unsigned int salt_len; + unsigned int it_count; + unsigned char *pwd; + unsigned char salt[32]; + unsigned char key[32]; +} tests[] = +{ + { 8, 4, 5, (unsigned char*)"password", + { + 0x12, 0x34, 0x56, 0x78 + }, + { + 0x5c, 0x75, 0xce, 0xf0, 0x1a, 0x96, 0x0d, 0xf7, + 0x4c, 0xb6, 0xb4, 0x9b, 0x9e, 0x38, 0xe6, 0xb5 + } + }, + { 8, 8, 5, (unsigned char*)"password", + { + 0x12, 0x34, 0x56, 0x78, 0x78, 0x56, 0x34, 0x12 + }, + { + 0xd1, 0xda, 0xa7, 0x86, 0x15, 0xf2, 0x87, 0xe6, + 0xa1, 0xc8, 0xb1, 0x20, 0xd7, 0x06, 0x2a, 0x49 + } + }, + { 8, 21, 1, (unsigned char*)"password", + { + "ATHENA.MIT.EDUraeburn" + }, + { + 0xcd, 0xed, 0xb5, 0x28, 0x1b, 0xb2, 0xf8, 0x01, + 0x56, 0x5a, 0x11, 0x22, 0xb2, 0x56, 0x35, 0x15 + } + }, + { 8, 21, 2, (unsigned char*)"password", + { + "ATHENA.MIT.EDUraeburn" + }, + { + 0x01, 0xdb, 0xee, 0x7f, 0x4a, 0x9e, 0x24, 0x3e, + 0x98, 0x8b, 0x62, 0xc7, 0x3c, 0xda, 0x93, 0x5d + } + }, + { 8, 21, 1200, (unsigned char*)"password", + { + "ATHENA.MIT.EDUraeburn" + }, + { + 0x5c, 0x08, 0xeb, 0x61, 0xfd, 0xf7, 0x1e, 0x4e, + 0x4e, 0xc3, 0xcf, 0x6b, 0xa1, 0xf5, 0x51, 0x2b + } + } +}; + +int main() +{ unsigned int i, j, key_len = 256; + unsigned char key[256]; + + printf("\nTest of RFC2898 Password Based Key Derivation"); + for(i = 0; i < 5; ++i) + { + derive_key(tests[i].pwd, tests[i].pwd_len, tests[i].salt, + tests[i].salt_len, tests[i].it_count, key, key_len); + + printf("\ntest %i: ", i + 1); + printf("key %s", memcmp(tests[i].key, key, 16) ? "is bad" : "is good"); + for(j = 0; j < key_len && j < 64; j += 4) + { + if(j % 16 == 0) + printf("\n"); + printf("0x%02x%02x%02x%02x ", key[j], key[j + 1], key[j + 2], key[j + 3]); + } + printf(j < key_len ? " ... \n" : "\n"); + } + printf("\n"); + return 0; +} + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/SSZipArchive/aes/pwd2key.h b/SSZipArchive/aes/pwd2key.h new file mode 100755 index 0000000..99c1ecc --- /dev/null +++ b/SSZipArchive/aes/pwd2key.h @@ -0,0 +1,57 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + ALTERNATIVELY, provided that this notice is retained in full, this product + may be distributed under the terms of the GNU General Public License (GPL), + in which case the provisions of the GPL apply INSTEAD OF those given above. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 26/08/2003 + + This is an implementation of RFC2898, which specifies key derivation from + a password and a salt value. +*/ + +#ifndef PWD2KEY_H +#define PWD2KEY_H + +#if defined(__cplusplus) +extern "C" +{ +#endif + +void derive_key( + const unsigned char pwd[], /* the PASSWORD, and */ + unsigned int pwd_len, /* its length */ + const unsigned char salt[], /* the SALT and its */ + unsigned int salt_len, /* length */ + unsigned int iter, /* the number of iterations */ + unsigned char key[], /* space for the output key */ + unsigned int key_len); /* and its required length */ + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/SSZipArchive/aes/sha1.c b/SSZipArchive/aes/sha1.c new file mode 100755 index 0000000..0fbf05e --- /dev/null +++ b/SSZipArchive/aes/sha1.c @@ -0,0 +1,258 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + ALTERNATIVELY, provided that this notice is retained in full, this product + may be distributed under the terms of the GNU General Public License (GPL), + in which case the provisions of the GPL apply INSTEAD OF those given above. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 01/08/2005 + + This is a byte oriented version of SHA1 that operates on arrays of bytes + stored in memory. +*/ + +#include /* for memcpy() etc. */ + +#include "sha1.h" +#include "brg_endian.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#if defined( _MSC_VER ) && ( _MSC_VER > 800 ) +#pragma intrinsic(memcpy) +#endif + +#if 0 && defined(_MSC_VER) +#define rotl32 _lrotl +#define rotr32 _lrotr +#else +#define rotl32(x,n) (((x) << n) | ((x) >> (32 - n))) +#define rotr32(x,n) (((x) >> n) | ((x) << (32 - n))) +#endif + +#if !defined(bswap_32) +#define bswap_32(x) ((rotr32((x), 24) & 0x00ff00ff) | (rotr32((x), 8) & 0xff00ff00)) +#endif + +#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN) +#define SWAP_BYTES +#else +#undef SWAP_BYTES +#endif + +#if defined(SWAP_BYTES) +#define bsw_32(p,n) \ + { int _i = (n); while(_i--) ((uint_32t*)p)[_i] = bswap_32(((uint_32t*)p)[_i]); } +#else +#define bsw_32(p,n) +#endif + +#define SHA1_MASK (SHA1_BLOCK_SIZE - 1) + +#if 0 + +#define ch(x,y,z) (((x) & (y)) ^ (~(x) & (z))) +#define parity(x,y,z) ((x) ^ (y) ^ (z)) +#define maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) + +#else /* Discovered by Rich Schroeppel and Colin Plumb */ + +#define ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) +#define parity(x,y,z) ((x) ^ (y) ^ (z)) +#define maj(x,y,z) (((x) & (y)) | ((z) & ((x) ^ (y)))) + +#endif + +/* Compile 64 bytes of hash data into SHA1 context. Note */ +/* that this routine assumes that the byte order in the */ +/* ctx->wbuf[] at this point is in such an order that low */ +/* address bytes in the ORIGINAL byte stream will go in */ +/* this buffer to the high end of 32-bit words on BOTH big */ +/* and little endian systems */ + +#ifdef ARRAY +#define q(v,n) v[n] +#else +#define q(v,n) v##n +#endif + +#define one_cycle(v,a,b,c,d,e,f,k,h) \ + q(v,e) += rotr32(q(v,a),27) + \ + f(q(v,b),q(v,c),q(v,d)) + k + h; \ + q(v,b) = rotr32(q(v,b), 2) + +#define five_cycle(v,f,k,i) \ + one_cycle(v, 0,1,2,3,4, f,k,hf(i )); \ + one_cycle(v, 4,0,1,2,3, f,k,hf(i+1)); \ + one_cycle(v, 3,4,0,1,2, f,k,hf(i+2)); \ + one_cycle(v, 2,3,4,0,1, f,k,hf(i+3)); \ + one_cycle(v, 1,2,3,4,0, f,k,hf(i+4)) + +VOID_RETURN sha1_compile(sha1_ctx ctx[1]) +{ uint_32t *w = ctx->wbuf; + +#ifdef ARRAY + uint_32t v[5]; + memcpy(v, ctx->hash, 5 * sizeof(uint_32t)); +#else + uint_32t v0, v1, v2, v3, v4; + v0 = ctx->hash[0]; v1 = ctx->hash[1]; + v2 = ctx->hash[2]; v3 = ctx->hash[3]; + v4 = ctx->hash[4]; +#endif + +#define hf(i) w[i] + + five_cycle(v, ch, 0x5a827999, 0); + five_cycle(v, ch, 0x5a827999, 5); + five_cycle(v, ch, 0x5a827999, 10); + one_cycle(v,0,1,2,3,4, ch, 0x5a827999, hf(15)); \ + +#undef hf +#define hf(i) (w[(i) & 15] = rotl32( \ + w[((i) + 13) & 15] ^ w[((i) + 8) & 15] \ + ^ w[((i) + 2) & 15] ^ w[(i) & 15], 1)) + + one_cycle(v,4,0,1,2,3, ch, 0x5a827999, hf(16)); + one_cycle(v,3,4,0,1,2, ch, 0x5a827999, hf(17)); + one_cycle(v,2,3,4,0,1, ch, 0x5a827999, hf(18)); + one_cycle(v,1,2,3,4,0, ch, 0x5a827999, hf(19)); + + five_cycle(v, parity, 0x6ed9eba1, 20); + five_cycle(v, parity, 0x6ed9eba1, 25); + five_cycle(v, parity, 0x6ed9eba1, 30); + five_cycle(v, parity, 0x6ed9eba1, 35); + + five_cycle(v, maj, 0x8f1bbcdc, 40); + five_cycle(v, maj, 0x8f1bbcdc, 45); + five_cycle(v, maj, 0x8f1bbcdc, 50); + five_cycle(v, maj, 0x8f1bbcdc, 55); + + five_cycle(v, parity, 0xca62c1d6, 60); + five_cycle(v, parity, 0xca62c1d6, 65); + five_cycle(v, parity, 0xca62c1d6, 70); + five_cycle(v, parity, 0xca62c1d6, 75); + +#ifdef ARRAY + ctx->hash[0] += v[0]; ctx->hash[1] += v[1]; + ctx->hash[2] += v[2]; ctx->hash[3] += v[3]; + ctx->hash[4] += v[4]; +#else + ctx->hash[0] += v0; ctx->hash[1] += v1; + ctx->hash[2] += v2; ctx->hash[3] += v3; + ctx->hash[4] += v4; +#endif +} + +VOID_RETURN sha1_begin(sha1_ctx ctx[1]) +{ + ctx->count[0] = ctx->count[1] = 0; + ctx->hash[0] = 0x67452301; + ctx->hash[1] = 0xefcdab89; + ctx->hash[2] = 0x98badcfe; + ctx->hash[3] = 0x10325476; + ctx->hash[4] = 0xc3d2e1f0; +} + +/* SHA1 hash data in an array of bytes into hash buffer and */ +/* call the hash_compile function as required. */ + +VOID_RETURN sha1_hash(const unsigned char data[], unsigned long len, sha1_ctx ctx[1]) +{ uint_32t pos = (uint_32t)(ctx->count[0] & SHA1_MASK), + space = SHA1_BLOCK_SIZE - pos; + const unsigned char *sp = data; + + if((ctx->count[0] += len) < len) + ++(ctx->count[1]); + + while(len >= space) /* tranfer whole blocks if possible */ + { + memcpy(((unsigned char*)ctx->wbuf) + pos, sp, space); + sp += space; len -= space; space = SHA1_BLOCK_SIZE; pos = 0; + bsw_32(ctx->wbuf, SHA1_BLOCK_SIZE >> 2); + sha1_compile(ctx); + } + + memcpy(((unsigned char*)ctx->wbuf) + pos, sp, len); +} + +/* SHA1 final padding and digest calculation */ + +VOID_RETURN sha1_end(unsigned char hval[], sha1_ctx ctx[1]) +{ uint_32t i = (uint_32t)(ctx->count[0] & SHA1_MASK); + + /* put bytes in the buffer in an order in which references to */ + /* 32-bit words will put bytes with lower addresses into the */ + /* top of 32 bit words on BOTH big and little endian machines */ + bsw_32(ctx->wbuf, (i + 3) >> 2); + + /* we now need to mask valid bytes and add the padding which is */ + /* a single 1 bit and as many zero bits as necessary. Note that */ + /* we can always add the first padding byte here because the */ + /* buffer always has at least one empty slot */ + ctx->wbuf[i >> 2] &= 0xffffff80 << 8 * (~i & 3); + ctx->wbuf[i >> 2] |= 0x00000080 << 8 * (~i & 3); + + /* we need 9 or more empty positions, one for the padding byte */ + /* (above) and eight for the length count. If there is not */ + /* enough space, pad and empty the buffer */ + if(i > SHA1_BLOCK_SIZE - 9) + { + if(i < 60) ctx->wbuf[15] = 0; + sha1_compile(ctx); + i = 0; + } + else /* compute a word index for the empty buffer positions */ + i = (i >> 2) + 1; + + while(i < 14) /* and zero pad all but last two positions */ + ctx->wbuf[i++] = 0; + + /* the following 32-bit length fields are assembled in the */ + /* wrong byte order on little endian machines but this is */ + /* corrected later since they are only ever used as 32-bit */ + /* word values. */ + ctx->wbuf[14] = (ctx->count[1] << 3) | (ctx->count[0] >> 29); + ctx->wbuf[15] = ctx->count[0] << 3; + sha1_compile(ctx); + + /* extract the hash value as bytes in case the hash buffer is */ + /* misaligned for 32-bit words */ + for(i = 0; i < SHA1_DIGEST_SIZE; ++i) + hval[i] = (unsigned char)(ctx->hash[i >> 2] >> (8 * (~i & 3))); +} + +VOID_RETURN sha1(unsigned char hval[], const unsigned char data[], unsigned long len) +{ sha1_ctx cx[1]; + + sha1_begin(cx); sha1_hash(data, len, cx); sha1_end(hval, cx); +} + +#if defined(__cplusplus) +} +#endif diff --git a/SSZipArchive/aes/sha1.h b/SSZipArchive/aes/sha1.h new file mode 100755 index 0000000..bace6af --- /dev/null +++ b/SSZipArchive/aes/sha1.h @@ -0,0 +1,73 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + ALTERNATIVELY, provided that this notice is retained in full, this product + may be distributed under the terms of the GNU General Public License (GPL), + in which case the provisions of the GPL apply INSTEAD OF those given above. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 01/08/2005 +*/ + +#ifndef _SHA1_H +#define _SHA1_H + +#include +#include "brg_types.h" + +#define SHA1_BLOCK_SIZE 64 +#define SHA1_DIGEST_SIZE 20 + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* type to hold the SHA256 context */ + +typedef struct +{ uint_32t count[2]; + uint_32t hash[5]; + uint_32t wbuf[16]; +} sha1_ctx; + +/* Note that these prototypes are the same for both bit and */ +/* byte oriented implementations. However the length fields */ +/* are in bytes or bits as appropriate for the version used */ +/* and bit sequences are input as arrays of bytes in which */ +/* bit sequences run from the most to the least significant */ +/* end of each byte */ + +VOID_RETURN sha1_compile(sha1_ctx ctx[1]); + +VOID_RETURN sha1_begin(sha1_ctx ctx[1]); +VOID_RETURN sha1_hash(const unsigned char data[], unsigned long len, sha1_ctx ctx[1]); +VOID_RETURN sha1_end(unsigned char hval[], sha1_ctx ctx[1]); +VOID_RETURN sha1(unsigned char hval[], const unsigned char data[], unsigned long len); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/SSZipArchive/minizip/crypt.h b/SSZipArchive/minizip/crypt.h new file mode 100755 index 0000000..46c63fb --- /dev/null +++ b/SSZipArchive/minizip/crypt.h @@ -0,0 +1,130 @@ +/* crypt.h -- base code for traditional PKWARE encryption + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + Modifications for Info-ZIP crypting + Copyright (C) 2003 Terry Thorsen + + This code is a modified version of crypting code in Info-ZIP distribution + + Copyright (C) 1990-2000 Info-ZIP. All rights reserved. + + See the Info-ZIP LICENSE file version 2000-Apr-09 or later for terms of use + which also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html + + The encryption/decryption parts of this source code (as opposed to the + non-echoing password parts) were originally written in Europe. The + whole source package can be freely distributed, including from the USA. + (Prior to January 2000, re-export from the US was a violation of US law.) + + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). + + If you don't need crypting in your application, just define symbols + NOCRYPT and NOUNCRYPT. +*/ + +#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) + +/*********************************************************************** + * Return the next byte in the pseudo-random sequence + */ +static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab) +{ + unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an + * unpredictable manner on 16-bit systems; not a problem + * with any known compiler so far, though */ + + temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2; + return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); +} + +/*********************************************************************** + * Update the encryption keys with the next byte of plain text + */ +static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c) +{ + (*(pkeys+0)) = CRC32((*(pkeys+0)), c); + (*(pkeys+1)) += (*(pkeys+0)) & 0xff; + (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; + { + register int keyshift = (int)((*(pkeys+1)) >> 24); + (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift); + } + return c; +} + + +/*********************************************************************** + * Initialize the encryption keys and the random header according to + * the given password. + */ +static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab) +{ + *(pkeys+0) = 305419896L; + *(pkeys+1) = 591751049L; + *(pkeys+2) = 878082192L; + while (*passwd != 0) { + update_keys(pkeys,pcrc_32_tab,(int)*passwd); + passwd++; + } +} + +#define zdecode(pkeys,pcrc_32_tab,c) \ + (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab))) + +#define zencode(pkeys,pcrc_32_tab,c,t) \ + (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c)) + +#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED + +#define RAND_HEAD_LEN 12 + /* "last resort" source for second part of crypt seed pattern */ +# ifndef ZCR_SEED2 +# define ZCR_SEED2 3141592654UL /* use PI as default pattern */ +# endif + +static int crypthead(const char* passwd, /* password string */ + unsigned char* buf, /* where to write header */ + int bufSize, + unsigned long* pkeys, + const unsigned long* pcrc_32_tab, + unsigned long crcForCrypting) +{ + int n; /* index in random header */ + int t; /* temporary */ + int c; /* random byte */ + unsigned char header[RAND_HEAD_LEN-2]; /* random header */ + static unsigned calls = 0; /* ensure different random header each time */ + + if (bufSize> 7) & 0xff; + header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t); + } + /* Encrypt random header (last two bytes is high word of crc) */ + init_keys(passwd, pkeys, pcrc_32_tab); + for (n = 0; n < RAND_HEAD_LEN-2; n++) + { + buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t); + } + buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t); + buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t); + return n; +} + +#endif diff --git a/SSZipArchive/minizip/ioapi.c b/SSZipArchive/minizip/ioapi.c new file mode 100755 index 0000000..857f7b9 --- /dev/null +++ b/SSZipArchive/minizip/ioapi.c @@ -0,0 +1,369 @@ +/* ioapi.h -- IO base function header for compress/uncompress .zip + part of the MiniZip project + + Copyright (C) 1998-2010 Gilles Vollant + http://www.winimage.com/zLibDll/minizip.html + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson + http://result42.com + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#include +#include + +#include "ioapi.h" + +#if defined(_WIN32) +# define snprintf _snprintf +#endif + +#ifdef __APPLE__ +/* In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions */ +# define FOPEN_FUNC(filename, mode) fopen(filename, mode) +# define FTELLO_FUNC(stream) ftello(stream) +# define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin) +#else +# define FOPEN_FUNC(filename, mode) fopen64(filename, mode) +# define FTELLO_FUNC(stream) ftello64(stream) +# define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin) +#endif + +/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ +#ifndef SEEK_CUR +# define SEEK_CUR 1 +#endif +#ifndef SEEK_END +# define SEEK_END 2 +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 +#endif + +voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode) +{ + if (pfilefunc->zfile_func64.zopen64_file != NULL) + return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque,filename,mode); + return (*(pfilefunc->zopen32_file))(pfilefunc->zfile_func64.opaque,(const char*)filename,mode); +} + +voidpf call_zopendisk64 OF((const zlib_filefunc64_32_def* pfilefunc, voidpf filestream, int number_disk, int mode)) +{ + if (pfilefunc->zfile_func64.zopendisk64_file != NULL) + return (*(pfilefunc->zfile_func64.zopendisk64_file)) (pfilefunc->zfile_func64.opaque,filestream,number_disk,mode); + return (*(pfilefunc->zopendisk32_file))(pfilefunc->zfile_func64.opaque,filestream,number_disk,mode); +} + +long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin) +{ + uLong offsetTruncated; + if (pfilefunc->zfile_func64.zseek64_file != NULL) + return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin); + offsetTruncated = (uLong)offset; + if (offsetTruncated != offset) + return -1; + return (*(pfilefunc->zseek32_file))(pfilefunc->zfile_func64.opaque,filestream,offsetTruncated,origin); +} + +ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream) +{ + uLong tell_uLong; + if (pfilefunc->zfile_func64.zseek64_file != NULL) + return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream); + tell_uLong = (*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream); + if ((tell_uLong) == 0xffffffff) + return (ZPOS64_T)-1; + return tell_uLong; +} + +void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32) +{ + p_filefunc64_32->zfile_func64.zopen64_file = NULL; + p_filefunc64_32->zfile_func64.zopendisk64_file = NULL; + p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file; + p_filefunc64_32->zopendisk32_file = p_filefunc32->zopendisk_file; + p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; + p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file; + p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file; + p_filefunc64_32->zfile_func64.ztell64_file = NULL; + p_filefunc64_32->zfile_func64.zseek64_file = NULL; + p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file; + p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; + p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque; + p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file; + p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file; +} + +static voidpf ZCALLBACK fopen_file_func OF((voidpf opaque, const char* filename, int mode)); +static uLong ZCALLBACK fread_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size)); +static uLong ZCALLBACK fwrite_file_func OF((voidpf opaque, voidpf stream, const void* buf,uLong size)); +static ZPOS64_T ZCALLBACK ftell64_file_func OF((voidpf opaque, voidpf stream)); +static long ZCALLBACK fseek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); +static int ZCALLBACK fclose_file_func OF((voidpf opaque, voidpf stream)); +static int ZCALLBACK ferror_file_func OF((voidpf opaque, voidpf stream)); + +typedef struct +{ + FILE *file; + int filenameLength; + void *filename; +} FILE_IOPOSIX; + +static voidpf file_build_ioposix(FILE *file, const char *filename) +{ + FILE_IOPOSIX *ioposix = NULL; + if (file == NULL) + return NULL; + ioposix = (FILE_IOPOSIX*)malloc(sizeof(FILE_IOPOSIX)); + ioposix->file = file; + ioposix->filenameLength = (int)strlen(filename) + 1; + ioposix->filename = (char*)malloc(ioposix->filenameLength * sizeof(char)); + strncpy(ioposix->filename, filename, ioposix->filenameLength); + return (voidpf)ioposix; +} + +static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, int mode) +{ + FILE* file = NULL; + const char* mode_fopen = NULL; + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_READ) + mode_fopen = "rb"; + else if (mode & ZLIB_FILEFUNC_MODE_EXISTING) + mode_fopen = "r+b"; + else if (mode & ZLIB_FILEFUNC_MODE_CREATE) + mode_fopen = "wb"; + + if ((filename != NULL) && (mode_fopen != NULL)) + { + file = fopen(filename, mode_fopen); + return file_build_ioposix(file, filename); + } + return file; +} + +static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, int mode) +{ + FILE* file = NULL; + const char* mode_fopen = NULL; + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_READ) + mode_fopen = "rb"; + else if (mode & ZLIB_FILEFUNC_MODE_EXISTING) + mode_fopen = "r+b"; + else if (mode & ZLIB_FILEFUNC_MODE_CREATE) + mode_fopen = "wb"; + + if ((filename != NULL) && (mode_fopen != NULL)) + { + file = FOPEN_FUNC((const char*)filename, mode_fopen); + return file_build_ioposix(file, (const char*)filename); + } + return file; +} + +static voidpf ZCALLBACK fopendisk64_file_func (voidpf opaque, voidpf stream, int number_disk, int mode) +{ + FILE_IOPOSIX *ioposix = NULL; + char *diskFilename = NULL; + voidpf ret = NULL; + int i = 0; + + if (stream == NULL) + return NULL; + ioposix = (FILE_IOPOSIX*)stream; + diskFilename = (char*)malloc(ioposix->filenameLength * sizeof(char)); + strncpy(diskFilename, ioposix->filename, ioposix->filenameLength); + for (i = ioposix->filenameLength - 1; i >= 0; i -= 1) + { + if (diskFilename[i] != '.') + continue; + snprintf(&diskFilename[i], ioposix->filenameLength - i, ".z%02d", number_disk + 1); + break; + } + if (i >= 0) + ret = fopen64_file_func(opaque, diskFilename, mode); + free(diskFilename); + return ret; +} + +static voidpf ZCALLBACK fopendisk_file_func (voidpf opaque, voidpf stream, int number_disk, int mode) +{ + FILE_IOPOSIX *ioposix = NULL; + char *diskFilename = NULL; + voidpf ret = NULL; + int i = 0; + + if (stream == NULL) + return NULL; + ioposix = (FILE_IOPOSIX*)stream; + diskFilename = (char*)malloc(ioposix->filenameLength * sizeof(char)); + strncpy(diskFilename, ioposix->filename, ioposix->filenameLength); + for (i = ioposix->filenameLength - 1; i >= 0; i -= 1) + { + if (diskFilename[i] != '.') + continue; + snprintf(&diskFilename[i], ioposix->filenameLength - i, ".z%02d", number_disk + 1); + break; + } + if (i >= 0) + ret = fopen_file_func(opaque, diskFilename, mode); + free(diskFilename); + return ret; +} + +static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size) +{ + FILE_IOPOSIX *ioposix = NULL; + uLong ret; + if (stream == NULL) + return -1; + ioposix = (FILE_IOPOSIX*)stream; + ret = (uLong)fread(buf, 1, (size_t)size, ioposix->file); + return ret; +} + +static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const void* buf, uLong size) +{ + FILE_IOPOSIX *ioposix = NULL; + uLong ret; + if (stream == NULL) + return -1; + ioposix = (FILE_IOPOSIX*)stream; + ret = (uLong)fwrite(buf, 1, (size_t)size, ioposix->file); + return ret; +} + +static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream) +{ + FILE_IOPOSIX *ioposix = NULL; + long ret = -1; + if (stream == NULL) + return ret; + ioposix = (FILE_IOPOSIX*)stream; + ret = ftell(ioposix->file); + return ret; +} + +static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream) +{ + FILE_IOPOSIX *ioposix = NULL; + ZPOS64_T ret = -1; + if (stream == NULL) + return ret; + ioposix = (FILE_IOPOSIX*)stream; + ret = FTELLO_FUNC(ioposix->file); + return ret; +} + +static long ZCALLBACK fseek_file_func (voidpf opaque, voidpf stream, uLong offset, int origin) +{ + FILE_IOPOSIX *ioposix = NULL; + int fseek_origin = 0; + long ret = 0; + + if (stream == NULL) + return -1; + ioposix = (FILE_IOPOSIX*)stream; + + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR: + fseek_origin = SEEK_CUR; + break; + case ZLIB_FILEFUNC_SEEK_END: + fseek_origin = SEEK_END; + break; + case ZLIB_FILEFUNC_SEEK_SET: + fseek_origin = SEEK_SET; + break; + default: + return -1; + } + if (fseek(ioposix->file, offset, fseek_origin) != 0) + ret = -1; + return ret; +} + +static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) +{ + FILE_IOPOSIX *ioposix = NULL; + int fseek_origin = 0; + long ret = 0; + + if (stream == NULL) + return -1; + ioposix = (FILE_IOPOSIX*)stream; + + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR: + fseek_origin = SEEK_CUR; + break; + case ZLIB_FILEFUNC_SEEK_END: + fseek_origin = SEEK_END; + break; + case ZLIB_FILEFUNC_SEEK_SET: + fseek_origin = SEEK_SET; + break; + default: + return -1; + } + + if(FSEEKO_FUNC(ioposix->file, offset, fseek_origin) != 0) + ret = -1; + + return ret; +} + + +static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream) +{ + FILE_IOPOSIX *ioposix = NULL; + int ret = -1; + if (stream == NULL) + return ret; + ioposix = (FILE_IOPOSIX*)stream; + if (ioposix->filename != NULL) + free(ioposix->filename); + ret = fclose(ioposix->file); + free(ioposix); + return ret; +} + +static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream) +{ + FILE_IOPOSIX *ioposix = NULL; + int ret = -1; + if (stream == NULL) + return ret; + ioposix = (FILE_IOPOSIX*)stream; + ret = ferror(ioposix->file); + return ret; +} + +void fill_fopen_filefunc (zlib_filefunc_def* pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen_file = fopen_file_func; + pzlib_filefunc_def->zopendisk_file = fopendisk_file_func; + pzlib_filefunc_def->zread_file = fread_file_func; + pzlib_filefunc_def->zwrite_file = fwrite_file_func; + pzlib_filefunc_def->ztell_file = ftell_file_func; + pzlib_filefunc_def->zseek_file = fseek_file_func; + pzlib_filefunc_def->zclose_file = fclose_file_func; + pzlib_filefunc_def->zerror_file = ferror_file_func; + pzlib_filefunc_def->opaque = NULL; +} + +void fill_fopen64_filefunc (zlib_filefunc64_def* pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen64_file = fopen64_file_func; + pzlib_filefunc_def->zopendisk64_file = fopendisk64_file_func; + pzlib_filefunc_def->zread_file = fread_file_func; + pzlib_filefunc_def->zwrite_file = fwrite_file_func; + pzlib_filefunc_def->ztell64_file = ftell64_file_func; + pzlib_filefunc_def->zseek64_file = fseek64_file_func; + pzlib_filefunc_def->zclose_file = fclose_file_func; + pzlib_filefunc_def->zerror_file = ferror_file_func; + pzlib_filefunc_def->opaque = NULL; +} diff --git a/SSZipArchive/minizip/ioapi.h b/SSZipArchive/minizip/ioapi.h new file mode 100755 index 0000000..742fae5 --- /dev/null +++ b/SSZipArchive/minizip/ioapi.h @@ -0,0 +1,175 @@ +/* ioapi.h -- IO base function header for compress/uncompress .zip + part of the MiniZip project + + Copyright (C) 1998-2010 Gilles Vollant + http://www.winimage.com/zLibDll/minizip.html + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson + http://result42.com + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#ifndef _ZLIBIOAPI64_H +#define _ZLIBIOAPI64_H + +#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__)) +# ifndef __USE_FILE_OFFSET64 +# define __USE_FILE_OFFSET64 +# endif +# ifndef __USE_LARGEFILE64 +# define __USE_LARGEFILE64 +# endif +# ifndef _LARGEFILE64_SOURCE +# define _LARGEFILE64_SOURCE +# endif +# ifndef _FILE_OFFSET_BIT +# define _FILE_OFFSET_BIT 64 +# endif +#endif + +#include +#include +#include "zlib.h" + +#if defined(USE_FILE32API) +# define fopen64 fopen +# define ftello64 ftell +# define fseeko64 fseek +#else +# if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__) +# define fopen64 fopen +# define ftello64 ftello +# define fseeko64 fseeko +# endif +# ifdef _MSC_VER +# define fopen64 fopen +# if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC))) +# define ftello64 _ftelli64 +# define fseeko64 _fseeki64 +# else /* old MSC */ +# define ftello64 ftell +# define fseeko64 fseek +# endif +# endif +#endif + +/* a type choosen by DEFINE */ +#ifdef HAVE_64BIT_INT_CUSTOM +typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T; +#else +# ifdef HAS_STDINT_H +# include "stdint.h" + typedef uint64_t ZPOS64_T; +# else +# if defined(_MSC_VER) || defined(__BORLANDC__) + typedef unsigned __int64 ZPOS64_T; +# else + typedef unsigned long long int ZPOS64_T; +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_FILEFUNC_SEEK_CUR (1) +#define ZLIB_FILEFUNC_SEEK_END (2) +#define ZLIB_FILEFUNC_SEEK_SET (0) + +#define ZLIB_FILEFUNC_MODE_READ (1) +#define ZLIB_FILEFUNC_MODE_WRITE (2) +#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) +#define ZLIB_FILEFUNC_MODE_EXISTING (4) +#define ZLIB_FILEFUNC_MODE_CREATE (8) + +#ifndef ZCALLBACK +# if (defined(WIN32) || defined(_WIN32) || defined (WINDOWS) || \ + defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) +# define ZCALLBACK CALLBACK +# else +# define ZCALLBACK +# endif +#endif + +typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode)); +typedef voidpf (ZCALLBACK *opendisk_file_func) OF((voidpf opaque, voidpf stream, int number_disk, int mode)); +typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); +typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); +typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream)); +typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream)); + +typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream)); +typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin)); + +/* here is the "old" 32 bits structure structure */ +typedef struct zlib_filefunc_def_s +{ + open_file_func zopen_file; + opendisk_file_func zopendisk_file; + read_file_func zread_file; + write_file_func zwrite_file; + tell_file_func ztell_file; + seek_file_func zseek_file; + close_file_func zclose_file; + testerror_file_func zerror_file; + voidpf opaque; +} zlib_filefunc_def; + +typedef ZPOS64_T (ZCALLBACK *tell64_file_func) OF((voidpf opaque, voidpf stream)); +typedef long (ZCALLBACK *seek64_file_func) OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); +typedef voidpf (ZCALLBACK *open64_file_func) OF((voidpf opaque, const void* filename, int mode)); +typedef voidpf (ZCALLBACK *opendisk64_file_func)OF((voidpf opaque, voidpf stream, int number_disk, int mode)); + +typedef struct zlib_filefunc64_def_s +{ + open64_file_func zopen64_file; + opendisk64_file_func zopendisk64_file; + read_file_func zread_file; + write_file_func zwrite_file; + tell64_file_func ztell64_file; + seek64_file_func zseek64_file; + close_file_func zclose_file; + testerror_file_func zerror_file; + voidpf opaque; +} zlib_filefunc64_def; + +void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); +void fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def)); + +/* now internal definition, only for zip.c and unzip.h */ +typedef struct zlib_filefunc64_32_def_s +{ + zlib_filefunc64_def zfile_func64; + open_file_func zopen32_file; + opendisk_file_func zopendisk32_file; + tell_file_func ztell32_file; + seek_file_func zseek32_file; +} zlib_filefunc64_32_def; + +#define ZREAD64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zread_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) +#define ZWRITE64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zwrite_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) +/*#define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream))*/ +/*#define ZSEEK64(filefunc,filestream,pos,mode) ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode))*/ +#define ZCLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zclose_file)) ((filefunc).zfile_func64.opaque,filestream)) +#define ZERROR64(filefunc,filestream) ((*((filefunc).zfile_func64.zerror_file)) ((filefunc).zfile_func64.opaque,filestream)) + +voidpf call_zopen64 OF((const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode)); +voidpf call_zopendisk64 OF((const zlib_filefunc64_32_def* pfilefunc, voidpf filestream, int number_disk, int mode)); +long call_zseek64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin)); +ZPOS64_T call_ztell64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream)); + +void fill_zlib_filefunc64_32_def_from_filefunc32 OF((zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32)); + +#define ZOPEN64(filefunc,filename,mode) (call_zopen64((&(filefunc)),(filename),(mode))) +#define ZOPENDISK64(filefunc,filestream,diskn,mode) (call_zopendisk64((&(filefunc)),(filestream),(diskn),(mode))) +#define ZTELL64(filefunc,filestream) (call_ztell64((&(filefunc)),(filestream))) +#define ZSEEK64(filefunc,filestream,pos,mode) (call_zseek64((&(filefunc)),(filestream),(pos),(mode))) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/SSZipArchive/minizip/mztools.c b/SSZipArchive/minizip/mztools.c new file mode 100755 index 0000000..80d50e0 --- /dev/null +++ b/SSZipArchive/minizip/mztools.c @@ -0,0 +1,284 @@ +/* + Additional tools for Minizip + Code: Xavier Roche '2004 + License: Same as ZLIB (www.gzip.org) +*/ + +/* Code */ +#include +#include +#include +#include "zlib.h" +#include "unzip.h" +#include "mztools.h" + +#define READ_8(adr) ((unsigned char)*(adr)) +#define READ_16(adr) ( READ_8(adr) | (READ_8(adr+1) << 8) ) +#define READ_32(adr) ( READ_16(adr) | (READ_16((adr)+2) << 16) ) + +#define WRITE_8(buff, n) do { \ + *((unsigned char*)(buff)) = (unsigned char) ((n) & 0xff); \ +} while(0) +#define WRITE_16(buff, n) do { \ + WRITE_8((unsigned char*)(buff), n); \ + WRITE_8(((unsigned char*)(buff)) + 1, (n) >> 8); \ +} while(0) +#define WRITE_32(buff, n) do { \ + WRITE_16((unsigned char*)(buff), (n) & 0xffff); \ + WRITE_16((unsigned char*)(buff) + 2, (n) >> 16); \ +} while(0) + +extern int ZEXPORT unzRepair(file, fileOut, fileOutTmp, nRecovered, bytesRecovered) +const char* file; +const char* fileOut; +const char* fileOutTmp; +uLong* nRecovered; +uLong* bytesRecovered; +{ + int err = Z_OK; + FILE* fpZip = fopen(file, "rb"); + FILE* fpOut = fopen(fileOut, "wb"); + FILE* fpOutCD = fopen(fileOutTmp, "wb"); + if (fpZip != NULL && fpOut != NULL) { + int entries = 0; + uLong totalBytes = 0; + char header[30]; + char filename[256]; + char extra[1024]; + int offset = 0; + int offsetCD = 0; + while ( fread(header, 1, 30, fpZip) == 30 ) { + int currentOffset = offset; + + /* File entry */ + if (READ_32(header) == 0x04034b50) { + unsigned int version = READ_16(header + 4); + unsigned int gpflag = READ_16(header + 6); + unsigned int method = READ_16(header + 8); + unsigned int filetime = READ_16(header + 10); + unsigned int filedate = READ_16(header + 12); + unsigned int crc = READ_32(header + 14); /* crc */ + unsigned int cpsize = READ_32(header + 18); /* compressed size */ + unsigned int uncpsize = READ_32(header + 22); /* uncompressed sz */ + unsigned int fnsize = READ_16(header + 26); /* file name length */ + unsigned int extsize = READ_16(header + 28); /* extra field length */ + filename[0] = extra[0] = '\0'; + + /* Header */ + if (fwrite(header, 1, 30, fpOut) == 30) { + offset += 30; + } else { + err = Z_ERRNO; + break; + } + + /* Filename */ + if (fnsize > 0) { + if (fread(filename, 1, fnsize, fpZip) == fnsize) { + if (fwrite(filename, 1, fnsize, fpOut) == fnsize) { + offset += fnsize; + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_STREAM_ERROR; + break; + } + + /* Extra field */ + if (extsize > 0) { + if (fread(extra, 1, extsize, fpZip) == extsize) { + if (fwrite(extra, 1, extsize, fpOut) == extsize) { + offset += extsize; + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_ERRNO; + break; + } + } + + /* Data */ + { + int dataSize = cpsize; + if (dataSize == 0) { + dataSize = uncpsize; + } + if (dataSize > 0) { + char* data = malloc(dataSize); + if (data != NULL) { + if ((int)fread(data, 1, dataSize, fpZip) == dataSize) { + if ((int)fwrite(data, 1, dataSize, fpOut) == dataSize) { + offset += dataSize; + totalBytes += dataSize; + } else { + err = Z_ERRNO; + } + } else { + err = Z_ERRNO; + } + free(data); + if (err != Z_OK) { + break; + } + } else { + err = Z_MEM_ERROR; + break; + } + } + } + + /* Central directory entry */ + { + char centralDirectoryEntryHeader[46]; + //char* comment = ""; + //int comsize = (int) strlen(comment); + WRITE_32(centralDirectoryEntryHeader, 0x02014b50); + WRITE_16(centralDirectoryEntryHeader + 4, version); + WRITE_16(centralDirectoryEntryHeader + 6, version); + WRITE_16(centralDirectoryEntryHeader + 8, gpflag); + WRITE_16(centralDirectoryEntryHeader + 10, method); + WRITE_16(centralDirectoryEntryHeader + 12, filetime); + WRITE_16(centralDirectoryEntryHeader + 14, filedate); + WRITE_32(centralDirectoryEntryHeader + 16, crc); + WRITE_32(centralDirectoryEntryHeader + 20, cpsize); + WRITE_32(centralDirectoryEntryHeader + 24, uncpsize); + WRITE_16(centralDirectoryEntryHeader + 28, fnsize); + WRITE_16(centralDirectoryEntryHeader + 30, extsize); + WRITE_16(centralDirectoryEntryHeader + 32, 0 /*comsize*/); + WRITE_16(centralDirectoryEntryHeader + 34, 0); /* disk # */ + WRITE_16(centralDirectoryEntryHeader + 36, 0); /* int attrb */ + WRITE_32(centralDirectoryEntryHeader + 38, 0); /* ext attrb */ + WRITE_32(centralDirectoryEntryHeader + 42, currentOffset); + /* Header */ + if (fwrite(centralDirectoryEntryHeader, 1, 46, fpOutCD) == 46) { + offsetCD += 46; + + /* Filename */ + if (fnsize > 0) { + if (fwrite(filename, 1, fnsize, fpOutCD) == fnsize) { + offsetCD += fnsize; + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_STREAM_ERROR; + break; + } + + /* Extra field */ + if (extsize > 0) { + if (fwrite(extra, 1, extsize, fpOutCD) == extsize) { + offsetCD += extsize; + } else { + err = Z_ERRNO; + break; + } + } + + /* Comment field */ + /* + if (comsize > 0) { + if ((int)fwrite(comment, 1, comsize, fpOutCD) == comsize) { + offsetCD += comsize; + } else { + err = Z_ERRNO; + break; + } + } + */ + + } else { + err = Z_ERRNO; + break; + } + } + + /* Success */ + entries++; + + } else { + break; + } + } + + /* Final central directory */ + { + int entriesZip = entries; + char finalCentralDirectoryHeader[22]; + //char* comment = ""; // "ZIP File recovered by zlib/minizip/mztools"; + //int comsize = (int) strlen(comment); + if (entriesZip > 0xffff) { + entriesZip = 0xffff; + } + WRITE_32(finalCentralDirectoryHeader, 0x06054b50); + WRITE_16(finalCentralDirectoryHeader + 4, 0); /* disk # */ + WRITE_16(finalCentralDirectoryHeader + 6, 0); /* disk # */ + WRITE_16(finalCentralDirectoryHeader + 8, entriesZip); /* hack */ + WRITE_16(finalCentralDirectoryHeader + 10, entriesZip); /* hack */ + WRITE_32(finalCentralDirectoryHeader + 12, offsetCD); /* size of CD */ + WRITE_32(finalCentralDirectoryHeader + 16, offset); /* offset to CD */ + WRITE_16(finalCentralDirectoryHeader + 20, 0 /*comsize*/); /* comment */ + + /* Header */ + if (fwrite(finalCentralDirectoryHeader, 1, 22, fpOutCD) == 22) { + + /* Comment field */ + /* + if (comsize > 0) { + if ((int)fwrite(comment, 1, comsize, fpOutCD) != comsize) { + err = Z_ERRNO; + } + } + */ + } else { + err = Z_ERRNO; + } + } + + /* Final merge (file + central directory) */ + fclose(fpOutCD); + if (err == Z_OK) { + fpOutCD = fopen(fileOutTmp, "rb"); + if (fpOutCD != NULL) { + int nRead; + char buffer[8192]; + while ( (nRead = (int)fread(buffer, 1, sizeof(buffer), fpOutCD)) > 0) { + if ((int)fwrite(buffer, 1, nRead, fpOut) != nRead) { + err = Z_ERRNO; + break; + } + } + fclose(fpOutCD); + } + } + + /* Close */ + fclose(fpZip); + fclose(fpOut); + + /* Wipe temporary file */ + (void)remove(fileOutTmp); + + /* Number of recovered entries */ + if (err == Z_OK) { + if (nRecovered != NULL) { + *nRecovered = entries; + } + if (bytesRecovered != NULL) { + *bytesRecovered = totalBytes; + } + } + } else { + err = Z_STREAM_ERROR; + } + return err; +} diff --git a/SSZipArchive/minizip/mztools.h b/SSZipArchive/minizip/mztools.h new file mode 100755 index 0000000..88b3459 --- /dev/null +++ b/SSZipArchive/minizip/mztools.h @@ -0,0 +1,31 @@ +/* + Additional tools for Minizip + Code: Xavier Roche '2004 + License: Same as ZLIB (www.gzip.org) +*/ + +#ifndef _zip_tools_H +#define _zip_tools_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#include "unzip.h" + +/* Repair a ZIP file (missing central directory) + file: file to recover + fileOut: output file after recovery + fileOutTmp: temporary file name used for recovery +*/ +extern int ZEXPORT unzRepair(const char* file, + const char* fileOut, + const char* fileOutTmp, + uLong* nRecovered, + uLong* bytesRecovered); + +#endif diff --git a/SSZipArchive/minizip/unzip.c b/SSZipArchive/minizip/unzip.c new file mode 100755 index 0000000..09d13d1 --- /dev/null +++ b/SSZipArchive/minizip/unzip.c @@ -0,0 +1,1839 @@ +/* unzip.c -- IO for uncompress .zip files using zlib + Version 1.1, February 14h, 2010 + part of the MiniZip project + + Copyright (C) 1998-2010 Gilles Vollant + http://www.winimage.com/zLibDll/minizip.html + Modifications of Unzip for Zip64 + Copyright (C) 2007-2008 Even Rouault + Modifications for Zip64 support on both zip and unzip + Copyright (C) 2009-2010 Mathias Svensson + http://result42.com + Modifications for AES, PKWARE disk spanning + Copyright (C) 2010-2014 Nathan Moinvaziri + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. + */ + + +#include +#include +#include + +/*#ifndef NOUNCRYPT + # define NOUNCRYPT + #endif*/ + +#include "zlib.h" +#include "unzip.h" + +#include "Common.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H +extern int errno; +#else +# include +#endif + +#ifdef HAVE_AES +# define AES_METHOD (99) +# define AES_PWVERIFYSIZE (2) +# define AES_MAXSALTLENGTH (16) +# define AES_AUTHCODESIZE (10) +# define AES_HEADERSIZE (11) +# define AES_KEYSIZE(mode) (64 + (mode * 64)) + +# include "aes.h" +# include "fileenc.h" +#endif +#ifndef NOUNCRYPT +# include "crypt.h" +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +#define DISKHEADERMAGIC (0x08074b50) +#define LOCALHEADERMAGIC (0x04034b50) +#define CENTRALHEADERMAGIC (0x02014b50) +#define ENDHEADERMAGIC (0x06054b50) +#define ZIP64ENDHEADERMAGIC (0x06064b50) +#define ZIP64ENDLOCHEADERMAGIC (0x07064b50) + +#define SIZECENTRALDIRITEM (0x2e) +#define SIZECENTRALHEADERLOCATOR (0x14) /* 20 */ +#define SIZEZIPLOCALHEADER (0x1e) + +#ifndef BUFREADCOMMENT +# define BUFREADCOMMENT (0x400) +#endif + +#ifndef UNZ_BUFSIZE +# define UNZ_BUFSIZE (64 * 1024) +#endif +#ifndef UNZ_MAXFILENAMEINZIP +# define UNZ_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) free(p); } +#endif + +const char unz_copyright[] = + " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; + +/* unz_file_info_interntal contain internal info about a file in zipfile*/ +typedef struct unz_file_info64_internal_s { + ZPOS64_T offset_curfile; /* relative offset of local header 8 bytes */ + ZPOS64_T byte_before_the_zipfile; /* byte before the zipfile, (>0 for sfx) */ +#ifdef HAVE_AES + uLong aes_encryption_mode; + uLong aes_compression_method; + uLong aes_version; +#endif +} unz_file_info64_internal; + +/* file_in_zip_read_info_s contain internal information about a file in zipfile */ +typedef struct { + Bytef *read_buffer; /* internal buffer for compressed data */ + z_stream stream; /* zLib stream structure for inflate */ + +#ifdef HAVE_BZIP2 + bz_stream bstream; /* bzLib stream structure for bziped */ +#endif +#ifdef HAVE_AES + fcrypt_ctx aes_ctx; +#endif + + ZPOS64_T pos_in_zipfile; /* position in byte on the zipfile, for fseek */ + uLong stream_initialised; /* flag set if stream structure is initialised */ + + ZPOS64_T offset_local_extrafield; /* offset of the local extra field */ + uInt size_local_extrafield; /* size of the local extra field */ + ZPOS64_T pos_local_extrafield; /* position in the local extra field in read */ + ZPOS64_T total_out_64; + + uLong crc32; /* crc32 of all data uncompressed */ + uLong crc32_wait; /* crc32 we must obtain after decompress all */ + ZPOS64_T rest_read_compressed; /* number of byte to be decompressed */ + ZPOS64_T rest_read_uncompressed; /* number of byte to be obtained after decomp */ + + zlib_filefunc64_32_def z_filefunc; + + voidpf filestream; /* io structore of the zipfile */ + uLong compression_method; /* compression method (0==store) */ + ZPOS64_T byte_before_the_zipfile; /* byte before the zipfile, (>0 for sfx) */ + int raw; +} file_in_zip64_read_info_s; + +/* unz64_s contain internal information about the zipfile */ +typedef struct { + zlib_filefunc64_32_def z_filefunc; + voidpf filestream; /* io structure of the current zipfile */ + voidpf filestream_with_CD; /* io structure of the disk with the central directory */ + unz_global_info64 gi; /* public global information */ + ZPOS64_T byte_before_the_zipfile; /* byte before the zipfile, (>0 for sfx)*/ + ZPOS64_T num_file; /* number of the current file in the zipfile*/ + ZPOS64_T pos_in_central_dir; /* pos of the current file in the central dir*/ + ZPOS64_T current_file_ok; /* flag about the usability of the current file*/ + ZPOS64_T central_pos; /* position of the beginning of the central dir*/ + uLong number_disk; /* number of the current disk, used for spanning ZIP*/ + ZPOS64_T size_central_dir; /* size of the central directory */ + ZPOS64_T offset_central_dir; /* offset of start of central directory with + respect to the starting disk number */ + + unz_file_info64 cur_file_info; /* public info about the current file in zip*/ + unz_file_info64_internal cur_file_info_internal; + /* private info about it*/ + file_in_zip64_read_info_s *pfile_in_zip_read; + /* structure about the current file if we are decompressing it */ + int isZip64; /* is the current file zip64 */ +#ifndef NOUNCRYPT + unsigned long keys[3]; /* keys defining the pseudo-random sequence */ + const unsigned long *pcrc_32_tab; +#endif +} unz64_s; + +/* Translate date/time from Dos format to tm_unz (readable more easily) */ +local void unz64local_DosDateToTmuDate(ZPOS64_T ulDosDate, tm_unz *ptm) +{ + ZPOS64_T uDate = (ZPOS64_T)(ulDosDate >> 16); + + ptm->tm_mday = (uInt)(uDate & 0x1f); + ptm->tm_mon = (uInt)((((uDate) & 0x1E0) / 0x20) - 1); + ptm->tm_year = (uInt)(((uDate & 0x0FE00) / 0x0200) + 1980); + ptm->tm_hour = (uInt)((ulDosDate & 0xF800) / 0x800); + ptm->tm_min = (uInt)((ulDosDate & 0x7E0) / 0x20); + ptm->tm_sec = (uInt)(2 * (ulDosDate & 0x1f)); + +#define unz64local_in_range(min, max, value) ((min) <= (value) && (value) <= (max)) + if (!unz64local_in_range(0, 11, ptm->tm_mon) || + !unz64local_in_range(1, 31, ptm->tm_mday) || + !unz64local_in_range(0, 23, ptm->tm_hour) || + !unz64local_in_range(0, 59, ptm->tm_min) || + !unz64local_in_range(0, 59, ptm->tm_sec)) + /* Invalid date stored, so don't return it. */ + memset(ptm, 0, sizeof(tm_unz)); +#undef unz64local_in_range +} + +/* Read a byte from a gz_stream; Return EOF for end of file. */ +local int unz64local_getByte(const zlib_filefunc64_32_def *pzlib_filefunc_def, voidpf filestream, int *pi) +{ + unsigned char c; + int err = (int)ZREAD64(*pzlib_filefunc_def, filestream, &c, 1); + if (err == 1) { + *pi = (int)c; + return UNZ_OK; + } + if (ZERROR64(*pzlib_filefunc_def, filestream)) + return UNZ_ERRNO; + return UNZ_EOF; +} + +local int unz64local_getShort OF((const zlib_filefunc64_32_def * pzlib_filefunc_def, voidpf filestream, uLong * pX)); +local int unz64local_getShort(const zlib_filefunc64_32_def *pzlib_filefunc_def, voidpf filestream, uLong *pX) +{ + uLong x; + int i = 0; + int err; + + err = unz64local_getByte(pzlib_filefunc_def, filestream, &i); + x = (uLong)i; + if (err == UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def, filestream, &i); + x |= ((uLong)i) << 8; + + if (err == UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int unz64local_getLong OF((const zlib_filefunc64_32_def * pzlib_filefunc_def, voidpf filestream, uLong * pX)); +local int unz64local_getLong(const zlib_filefunc64_32_def *pzlib_filefunc_def, voidpf filestream, uLong *pX) +{ + uLong x; + int i = 0; + int err; + + err = unz64local_getByte(pzlib_filefunc_def, filestream, &i); + x = (uLong)i; + if (err == UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def, filestream, &i); + x |= ((uLong)i) << 8; + if (err == UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def, filestream, &i); + x |= ((uLong)i) << 16; + if (err == UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def, filestream, &i); + x += ((uLong)i) << 24; + + if (err == UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int unz64local_getLong64 OF((const zlib_filefunc64_32_def * pzlib_filefunc_def, voidpf filestream, ZPOS64_T * pX)); +local int unz64local_getLong64(const zlib_filefunc64_32_def *pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX) +{ + ZPOS64_T x; + int i = 0; + int err; + + err = unz64local_getByte(pzlib_filefunc_def, filestream, &i); + x = (ZPOS64_T)i; + if (err == UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def, filestream, &i); + x |= ((ZPOS64_T)i) << 8; + if (err == UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def, filestream, &i); + x |= ((ZPOS64_T)i) << 16; + if (err == UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def, filestream, &i); + x |= ((ZPOS64_T)i) << 24; + if (err == UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def, filestream, &i); + x |= ((ZPOS64_T)i) << 32; + if (err == UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def, filestream, &i); + x |= ((ZPOS64_T)i) << 40; + if (err == UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def, filestream, &i); + x |= ((ZPOS64_T)i) << 48; + if (err == UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def, filestream, &i); + x |= ((ZPOS64_T)i) << 56; + + if (err == UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +/* Locate the Central directory of a zip file (at the end, just before the global comment) */ +local ZPOS64_T unz64local_SearchCentralDir OF((const zlib_filefunc64_32_def * pzlib_filefunc_def, voidpf filestream)); +local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def *pzlib_filefunc_def, voidpf filestream) +{ + unsigned char *buf; + ZPOS64_T file_size; + ZPOS64_T back_read = 4; + ZPOS64_T max_back = 0xffff; /* maximum size of global comment */ + ZPOS64_T pos_found = 0; + uLong read_size; + ZPOS64_T read_pos; + int i; + + buf = (unsigned char *)ALLOC(BUFREADCOMMENT + 4); + if (buf == NULL) + return 0; + + if (ZSEEK64(*pzlib_filefunc_def, filestream, 0, ZLIB_FILEFUNC_SEEK_END) != 0) { + TRYFREE(buf); + return 0; + } + + file_size = ZTELL64(*pzlib_filefunc_def, filestream); + + if (max_back > file_size) + max_back = file_size; + + while (back_read < max_back) { + if (back_read + BUFREADCOMMENT > max_back) + back_read = max_back; + else + back_read += BUFREADCOMMENT; + + read_pos = file_size - back_read; + read_size = ((BUFREADCOMMENT + 4) < (file_size - read_pos)) ? + (BUFREADCOMMENT + 4) : (uLong)(file_size - read_pos); + + if (ZSEEK64(*pzlib_filefunc_def, filestream, read_pos, ZLIB_FILEFUNC_SEEK_SET) != 0) + break; + if (ZREAD64(*pzlib_filefunc_def, filestream, buf, read_size) != read_size) + break; + + for (i = (int)read_size - 3; (i--) > 0; ) + if (((*(buf + i)) == (ENDHEADERMAGIC & 0xff)) && + ((*(buf + i + 1)) == (ENDHEADERMAGIC >> 8 & 0xff)) && + ((*(buf + i + 2)) == (ENDHEADERMAGIC >> 16 & 0xff)) && + ((*(buf + i + 3)) == (ENDHEADERMAGIC >> 24 & 0xff))) { + pos_found = read_pos + i; + break; + } + + if (pos_found != 0) + break; + } + TRYFREE(buf); + return pos_found; +} + +/* Locate the Central directory 64 of a zipfile (at the end, just before the global comment) */ +local ZPOS64_T unz64local_SearchCentralDir64 OF((const zlib_filefunc64_32_def * pzlib_filefunc_def, voidpf filestream, + const ZPOS64_T endcentraloffset)); +local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def *pzlib_filefunc_def, voidpf filestream, + const ZPOS64_T endcentraloffset) +{ + ZPOS64_T offset; + uLong uL; + + /* Zip64 end of central directory locator */ + if (ZSEEK64(*pzlib_filefunc_def, filestream, endcentraloffset - SIZECENTRALHEADERLOCATOR, ZLIB_FILEFUNC_SEEK_SET) != 0) + return 0; + + /* read locator signature */ + if (unz64local_getLong(pzlib_filefunc_def, filestream, &uL) != UNZ_OK) + return 0; + if (uL != ZIP64ENDLOCHEADERMAGIC) + return 0; + /* number of the disk with the start of the zip64 end of central directory */ + if (unz64local_getLong(pzlib_filefunc_def, filestream, &uL) != UNZ_OK) + return 0; + /* relative offset of the zip64 end of central directory record */ + if (unz64local_getLong64(pzlib_filefunc_def, filestream, &offset) != UNZ_OK) + return 0; + /* total number of disks */ + if (unz64local_getLong(pzlib_filefunc_def, filestream, &uL) != UNZ_OK) + return 0; + /* Goto end of central directory record */ + if (ZSEEK64(*pzlib_filefunc_def, filestream, offset, ZLIB_FILEFUNC_SEEK_SET) != 0) + return 0; + /* the signature */ + if (unz64local_getLong(pzlib_filefunc_def, filestream, &uL) != UNZ_OK) + return 0; + if (uL != ZIP64ENDHEADERMAGIC) + return 0; + + return offset; +} + +local unzFile unzOpenInternal(const void *path, zlib_filefunc64_32_def *pzlib_filefunc64_32_def) +{ + unz64_s us; + unz64_s *s; + ZPOS64_T central_pos; + uLong uL; + voidpf filestream = NULL; + ZPOS64_T number_entry_CD; + int err = UNZ_OK; + + if (unz_copyright[0] != ' ') + return NULL; + + us.filestream = NULL; + us.filestream_with_CD = NULL; + us.z_filefunc.zseek32_file = NULL; + us.z_filefunc.ztell32_file = NULL; + if (pzlib_filefunc64_32_def == NULL) + fill_fopen64_filefunc(&us.z_filefunc.zfile_func64); + else + us.z_filefunc = *pzlib_filefunc64_32_def; + + us.filestream = ZOPEN64(us.z_filefunc, path, ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_EXISTING); + + if (us.filestream == NULL) + return NULL; + + us.filestream_with_CD = us.filestream; + us.isZip64 = 0; + + /* Use unz64local_SearchCentralDir first. Only based on the result + is it necessary to locate the unz64local_SearchCentralDir64 */ + central_pos = unz64local_SearchCentralDir(&us.z_filefunc, us.filestream); + if (central_pos) { + if (ZSEEK64(us.z_filefunc, us.filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0) + err = UNZ_ERRNO; + + /* the signature, already checked */ + if (unz64local_getLong(&us.z_filefunc, us.filestream, &uL) != UNZ_OK) + err = UNZ_ERRNO; + /* number of this disk */ + if (unz64local_getShort(&us.z_filefunc, us.filestream, &uL) != UNZ_OK) + err = UNZ_ERRNO; + us.number_disk = uL; + /* number of the disk with the start of the central directory */ + if (unz64local_getShort(&us.z_filefunc, us.filestream, &uL) != UNZ_OK) + err = UNZ_ERRNO; + us.gi.number_disk_with_CD = uL; + /* total number of entries in the central directory on this disk */ + if (unz64local_getShort(&us.z_filefunc, us.filestream, &uL) != UNZ_OK) + err = UNZ_ERRNO; + us.gi.number_entry = uL; + /* total number of entries in the central directory */ + if (unz64local_getShort(&us.z_filefunc, us.filestream, &uL) != UNZ_OK) + err = UNZ_ERRNO; + number_entry_CD = uL; + if (number_entry_CD != us.gi.number_entry) + err = UNZ_BADZIPFILE; + /* size of the central directory */ + if (unz64local_getLong(&us.z_filefunc, us.filestream, &uL) != UNZ_OK) + err = UNZ_ERRNO; + us.size_central_dir = uL; + /* offset of start of central directory with respect to the starting disk number */ + if (unz64local_getLong(&us.z_filefunc, us.filestream, &uL) != UNZ_OK) + err = UNZ_ERRNO; + us.offset_central_dir = uL; + /* zipfile comment length */ + if (unz64local_getShort(&us.z_filefunc, us.filestream, &us.gi.size_comment) != UNZ_OK) + err = UNZ_ERRNO; + + if ((err == UNZ_OK) && + ((us.gi.number_entry == 0xffff) || (us.size_central_dir == 0xffff) || (us.offset_central_dir == 0xffffffff))) { + /* Format should be Zip64, as the central directory or file size is too large */ + central_pos = unz64local_SearchCentralDir64(&us.z_filefunc, us.filestream, central_pos); + if (central_pos) { + ZPOS64_T uL64; + + us.isZip64 = 1; + + if (ZSEEK64(us.z_filefunc, us.filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0) + err = UNZ_ERRNO; + + /* the signature, already checked */ + if (unz64local_getLong(&us.z_filefunc, us.filestream, &uL) != UNZ_OK) + err = UNZ_ERRNO; + /* size of zip64 end of central directory record */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream, &uL64) != UNZ_OK) + err = UNZ_ERRNO; + /* version made by */ + if (unz64local_getShort(&us.z_filefunc, us.filestream, &uL) != UNZ_OK) + err = UNZ_ERRNO; + /* version needed to extract */ + if (unz64local_getShort(&us.z_filefunc, us.filestream, &uL) != UNZ_OK) + err = UNZ_ERRNO; + /* number of this disk */ + if (unz64local_getLong(&us.z_filefunc, us.filestream, &us.number_disk) != UNZ_OK) + err = UNZ_ERRNO; + /* number of the disk with the start of the central directory */ + if (unz64local_getLong(&us.z_filefunc, us.filestream, &us.gi.number_disk_with_CD) != UNZ_OK) + err = UNZ_ERRNO; + /* total number of entries in the central directory on this disk */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream, &us.gi.number_entry) != UNZ_OK) + err = UNZ_ERRNO; + /* total number of entries in the central directory */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream, &number_entry_CD) != UNZ_OK) + err = UNZ_ERRNO; + if (number_entry_CD != us.gi.number_entry) + err = UNZ_BADZIPFILE; + /* size of the central directory */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream, &us.size_central_dir) != UNZ_OK) + err = UNZ_ERRNO; + /* offset of start of central directory with respect to the starting disk number */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream, &us.offset_central_dir) != UNZ_OK) + err = UNZ_ERRNO; + } else + err = UNZ_BADZIPFILE; + } + } else + err = UNZ_ERRNO; + + if ((err == UNZ_OK) && (central_pos < us.offset_central_dir + us.size_central_dir)) + err = UNZ_BADZIPFILE; + + if (err != UNZ_OK) { + ZCLOSE64(us.z_filefunc, us.filestream); + return NULL; + } + + if (us.gi.number_disk_with_CD == 0) { + /* If there is only one disk open another stream so we don't have to seek between the CD + and the file headers constantly */ + filestream = ZOPEN64(us.z_filefunc, path, ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_EXISTING); + if (filestream != NULL) + us.filestream = filestream; + } + + /* Hack for zip files that have no respect for zip64 + if ((central_pos > 0xffffffff) && (us.offset_central_dir < 0xffffffff)) + us.offset_central_dir = central_pos - us.size_central_dir;*/ + + us.byte_before_the_zipfile = central_pos - (us.offset_central_dir + us.size_central_dir); + us.central_pos = central_pos; + us.pfile_in_zip_read = NULL; + + s = (unz64_s *)ALLOC(sizeof(unz64_s)); + if (s != NULL) { + *s = us; + unzGoToFirstFile((unzFile)s); + } + return (unzFile)s; +} + +extern unzFile ZEXPORT unzOpen2(const char *path, zlib_filefunc_def *pzlib_filefunc32_def) +{ + if (pzlib_filefunc32_def != NULL) { + zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; + fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill, pzlib_filefunc32_def); + return unzOpenInternal(path, &zlib_filefunc64_32_def_fill); + } + return unzOpenInternal(path, NULL); +} + +extern unzFile ZEXPORT unzOpen2_64(const void *path, zlib_filefunc64_def *pzlib_filefunc_def) +{ + if (pzlib_filefunc_def != NULL) { + zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; + zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def; + zlib_filefunc64_32_def_fill.ztell32_file = NULL; + zlib_filefunc64_32_def_fill.zseek32_file = NULL; + return unzOpenInternal(path, &zlib_filefunc64_32_def_fill); + } + return unzOpenInternal(path, NULL); +} + +extern unzFile ZEXPORT unzOpen(const char *path) +{ + return unzOpenInternal(path, NULL); +} + +extern unzFile ZEXPORT unzOpen64(const void *path) +{ + return unzOpenInternal(path, NULL); +} + +extern int ZEXPORT unzClose(unzFile file) +{ + unz64_s *s; + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz64_s *)file; + + if (s->pfile_in_zip_read != NULL) + unzCloseCurrentFile(file); + + if ((s->filestream != NULL) && (s->filestream != s->filestream_with_CD)) + ZCLOSE64(s->z_filefunc, s->filestream); + if (s->filestream_with_CD != NULL) + ZCLOSE64(s->z_filefunc, s->filestream_with_CD); + + s->filestream = NULL; + s->filestream_with_CD = NULL; + TRYFREE(s); + return UNZ_OK; +} + +/* Goto to the next available disk for spanned archives */ +local int unzGoToNextDisk OF((unzFile file)); +local int unzGoToNextDisk(unzFile file) +{ + unz64_s *s; + file_in_zip64_read_info_s *pfile_in_zip_read_info; + uLong number_disk_next = 0; + + s = (unz64_s *)file; + if (s == NULL) + return UNZ_PARAMERROR; + pfile_in_zip_read_info = s->pfile_in_zip_read; + number_disk_next = s->number_disk; + + if ((pfile_in_zip_read_info != NULL) && (pfile_in_zip_read_info->rest_read_uncompressed > 0)) + /* We are currently reading a file and we need the next sequential disk */ + number_disk_next += 1; + else + /* Goto the disk for the current file */ + number_disk_next = s->cur_file_info.disk_num_start; + + if (number_disk_next != s->number_disk) { + /* Switch disks */ + if ((s->filestream != NULL) && (s->filestream != s->filestream_with_CD)) + ZCLOSE64(s->z_filefunc, s->filestream); + + if (number_disk_next == s->gi.number_disk_with_CD) { + s->filestream = s->filestream_with_CD; + } else { + s->filestream = ZOPENDISK64(s->z_filefunc, s->filestream_with_CD, (unsigned int)number_disk_next, + ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_EXISTING); + } + + if (s->filestream == NULL) + return UNZ_ERRNO; + + s->number_disk = number_disk_next; + } + + return UNZ_OK; +} + +extern int ZEXPORT unzGetGlobalInfo(unzFile file, unz_global_info *pglobal_info32) +{ + unz64_s *s; + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz64_s *)file; + /* to do : check if number_entry is not truncated */ + pglobal_info32->number_entry = (uLong)s->gi.number_entry; + pglobal_info32->size_comment = s->gi.size_comment; + pglobal_info32->number_disk_with_CD = s->gi.number_disk_with_CD; + return UNZ_OK; +} + +extern int ZEXPORT unzGetGlobalInfo64(unzFile file, unz_global_info64 *pglobal_info) +{ + unz64_s *s; + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz64_s *)file; + *pglobal_info = s->gi; + return UNZ_OK; +} + +extern int ZEXPORT unzGetGlobalComment(unzFile file, char *comment, uLong comment_size) +{ + unz64_s *s; + uLong bytes_to_read = comment_size; + if (file == NULL) + return (int)UNZ_PARAMERROR; + s = (unz64_s *)file; + + if (bytes_to_read > s->gi.size_comment) + bytes_to_read = s->gi.size_comment; + + if (ZSEEK64(s->z_filefunc, s->filestream_with_CD, s->central_pos + 22, ZLIB_FILEFUNC_SEEK_SET) != 0) + return UNZ_ERRNO; + + if (bytes_to_read > 0) { + *comment = 0; + if (ZREAD64(s->z_filefunc, s->filestream_with_CD, comment, bytes_to_read) != bytes_to_read) + return UNZ_ERRNO; + } + + if ((comment != NULL) && (comment_size > s->gi.size_comment)) + *(comment + s->gi.size_comment) = 0; + return (int)bytes_to_read; +} + +/* Get Info about the current file in the zipfile, with internal only info */ +local int unz64local_GetCurrentFileInfoInternal(unzFile file, unz_file_info64 *pfile_info, + unz_file_info64_internal *pfile_info_internal, char *filename, uLong filename_size, void *extrafield, + uLong extrafield_size, char *comment, uLong comment_size) +{ + unz64_s *s; + unz_file_info64 file_info; + unz_file_info64_internal file_info_internal; + ZPOS64_T bytes_to_read; + int err = UNZ_OK; + uLong uMagic; + long lSeek = 0; + ZPOS64_T current_pos = 0; + uLong acc = 0; + uLong uL; + ZPOS64_T uL64; + + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz64_s *)file; + + if (ZSEEK64(s->z_filefunc, s->filestream_with_CD, + s->pos_in_central_dir + s->byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0) + err = UNZ_ERRNO; + + /* Check the magic */ + if (err == UNZ_OK) { + if (unz64local_getLong(&s->z_filefunc, s->filestream_with_CD, &uMagic) != UNZ_OK) + err = UNZ_ERRNO; + else if (uMagic != CENTRALHEADERMAGIC) + err = UNZ_BADZIPFILE; + } + + /* Read central directory header */ + if (unz64local_getShort(&s->z_filefunc, s->filestream_with_CD, &file_info.version) != UNZ_OK) + err = UNZ_ERRNO; + if (unz64local_getShort(&s->z_filefunc, s->filestream_with_CD, &file_info.version_needed) != UNZ_OK) + err = UNZ_ERRNO; + if (unz64local_getShort(&s->z_filefunc, s->filestream_with_CD, &file_info.flag) != UNZ_OK) + err = UNZ_ERRNO; + if (unz64local_getShort(&s->z_filefunc, s->filestream_with_CD, &file_info.compression_method) != UNZ_OK) + err = UNZ_ERRNO; + if (unz64local_getLong(&s->z_filefunc, s->filestream_with_CD, &file_info.dosDate) != UNZ_OK) + err = UNZ_ERRNO; + unz64local_DosDateToTmuDate(file_info.dosDate, &file_info.tmu_date); + if (unz64local_getLong(&s->z_filefunc, s->filestream_with_CD, &file_info.crc) != UNZ_OK) + err = UNZ_ERRNO; + if (unz64local_getLong(&s->z_filefunc, s->filestream_with_CD, &uL) != UNZ_OK) + err = UNZ_ERRNO; + file_info.compressed_size = uL; + if (unz64local_getLong(&s->z_filefunc, s->filestream_with_CD, &uL) != UNZ_OK) + err = UNZ_ERRNO; + file_info.uncompressed_size = uL; + if (unz64local_getShort(&s->z_filefunc, s->filestream_with_CD, &file_info.size_filename) != UNZ_OK) + err = UNZ_ERRNO; + if (unz64local_getShort(&s->z_filefunc, s->filestream_with_CD, &file_info.size_file_extra) != UNZ_OK) + err = UNZ_ERRNO; + if (unz64local_getShort(&s->z_filefunc, s->filestream_with_CD, &file_info.size_file_comment) != UNZ_OK) + err = UNZ_ERRNO; + if (unz64local_getShort(&s->z_filefunc, s->filestream_with_CD, &file_info.disk_num_start) != UNZ_OK) + err = UNZ_ERRNO; + if (unz64local_getShort(&s->z_filefunc, s->filestream_with_CD, &file_info.internal_fa) != UNZ_OK) + err = UNZ_ERRNO; + if (unz64local_getLong(&s->z_filefunc, s->filestream_with_CD, &file_info.external_fa) != UNZ_OK) + err = UNZ_ERRNO; + /* Relative offset of local header */ + if (unz64local_getLong(&s->z_filefunc, s->filestream_with_CD, &uL) != UNZ_OK) + err = UNZ_ERRNO; + + file_info.size_file_extra_internal = 0; + file_info.disk_offset = uL; + file_info_internal.offset_curfile = uL; +#ifdef HAVE_AES + file_info_internal.aes_compression_method = 0; + file_info_internal.aes_encryption_mode = 0; + file_info_internal.aes_version = 0; +#endif + + lSeek += file_info.size_filename; + + if ((err == UNZ_OK) && (filename != NULL)) { + if (file_info.size_filename < filename_size) { + *(filename + file_info.size_filename) = 0; + bytes_to_read = file_info.size_filename; + } else + bytes_to_read = filename_size; + + if ((file_info.size_filename > 0) && (filename_size > 0)) + if (ZREAD64(s->z_filefunc, s->filestream_with_CD, filename, (uLong)bytes_to_read) != bytes_to_read) + err = UNZ_ERRNO; + lSeek -= (uLong)bytes_to_read; + } + + /* Read extrafield */ + if ((err == UNZ_OK) && (extrafield != NULL)) { + if (file_info.size_file_extra < extrafield_size) + bytes_to_read = file_info.size_file_extra; + else + bytes_to_read = extrafield_size; + + if (lSeek != 0) { + if (ZSEEK64(s->z_filefunc, s->filestream_with_CD, lSeek, ZLIB_FILEFUNC_SEEK_CUR) == 0) + lSeek = 0; + else + err = UNZ_ERRNO; + } + + if ((file_info.size_file_extra > 0) && (extrafield_size > 0)) + if (ZREAD64(s->z_filefunc, s->filestream_with_CD, extrafield, (uLong)bytes_to_read) != bytes_to_read) + err = UNZ_ERRNO; + lSeek += file_info.size_file_extra - (uLong)bytes_to_read; + } else + lSeek += file_info.size_file_extra; + + if ((err == UNZ_OK) && (file_info.size_file_extra != 0)) { + if (lSeek != 0) { + if (ZSEEK64(s->z_filefunc, s->filestream_with_CD, lSeek, ZLIB_FILEFUNC_SEEK_CUR) == 0) + lSeek = 0; + else + err = UNZ_ERRNO; + } + + /* We are going to parse the extra field so we need to move back */ + current_pos = ZTELL64(s->z_filefunc, s->filestream_with_CD); + if (current_pos < file_info.size_file_extra) + err = UNZ_ERRNO; + current_pos -= file_info.size_file_extra; + if (ZSEEK64(s->z_filefunc, s->filestream_with_CD, current_pos, ZLIB_FILEFUNC_SEEK_SET) != 0) + err = UNZ_ERRNO; + + while ((err != UNZ_ERRNO) && (acc < file_info.size_file_extra)) { + uLong headerid; + uLong datasize; + + if (unz64local_getShort(&s->z_filefunc, s->filestream_with_CD, &headerid) != UNZ_OK) + err = UNZ_ERRNO; + if (unz64local_getShort(&s->z_filefunc, s->filestream_with_CD, &datasize) != UNZ_OK) + err = UNZ_ERRNO; + + /* ZIP64 extra fields */ + if (headerid == 0x0001) { + /* Subtract size of ZIP64 field, since ZIP64 is handled internally */ + file_info.size_file_extra_internal += 2 + 2 + datasize; + + if (file_info.uncompressed_size == 0xffffffff) { + if (unz64local_getLong64(&s->z_filefunc, s->filestream_with_CD, &file_info.uncompressed_size) != UNZ_OK) + err = UNZ_ERRNO; + } + if (file_info.compressed_size == 0xffffffff) { + if (unz64local_getLong64(&s->z_filefunc, s->filestream_with_CD, &file_info.compressed_size) != UNZ_OK) + err = UNZ_ERRNO; + } + if (file_info_internal.offset_curfile == 0xffffffff) { + /* Relative Header offset */ + if (unz64local_getLong64(&s->z_filefunc, s->filestream_with_CD, &uL64) != UNZ_OK) + err = UNZ_ERRNO; + file_info_internal.offset_curfile = uL64; + file_info.disk_offset = uL64; + } + if (file_info.disk_num_start == 0xffffffff) { + /* Disk Start Number */ + if (unz64local_getLong(&s->z_filefunc, s->filestream_with_CD, &file_info.disk_num_start) != UNZ_OK) + err = UNZ_ERRNO; + } + } +#ifdef HAVE_AES + /* AES header */ + else if (headerid == 0x9901) { + /* Subtract size of AES field, since AES is handled internally */ + file_info.size_file_extra_internal += 2 + 2 + datasize; + + /* Verify version info */ + if (unz64local_getShort(&s->z_filefunc, s->filestream_with_CD, &uL) != UNZ_OK) + err = UNZ_ERRNO; + /* Support AE-1 and AE-2 */ + if (uL != 1 && uL != 2) + err = UNZ_ERRNO; + file_info_internal.aes_version = uL; + if (unz64local_getByte(&s->z_filefunc, s->filestream_with_CD, (int *)&uL) != UNZ_OK) + err = UNZ_ERRNO; + if ((char)uL != 'A') + err = UNZ_ERRNO; + if (unz64local_getByte(&s->z_filefunc, s->filestream_with_CD, (int *)&uL) != UNZ_OK) + err = UNZ_ERRNO; + if ((char)uL != 'E') + err = UNZ_ERRNO; + /* Get AES encryption strength and actual compression method */ + if (unz64local_getByte(&s->z_filefunc, s->filestream_with_CD, (int *)&uL) != UNZ_OK) + err = UNZ_ERRNO; + file_info_internal.aes_encryption_mode = uL; + if (unz64local_getShort(&s->z_filefunc, s->filestream_with_CD, &uL) != UNZ_OK) + err = UNZ_ERRNO; + file_info_internal.aes_compression_method = uL; + } +#endif + else { + if (ZSEEK64(s->z_filefunc, s->filestream_with_CD, datasize, ZLIB_FILEFUNC_SEEK_CUR) != 0) + err = UNZ_ERRNO; + } + + acc += 2 + 2 + datasize; + } + } + + if (file_info.disk_num_start == s->gi.number_disk_with_CD) + file_info_internal.byte_before_the_zipfile = s->byte_before_the_zipfile; + else + file_info_internal.byte_before_the_zipfile = 0; + + if ((err == UNZ_OK) && (comment != NULL)) { + if (file_info.size_file_comment < comment_size) { + *(comment + file_info.size_file_comment) = 0; + bytes_to_read = file_info.size_file_comment; + } else + bytes_to_read = comment_size; + + if (lSeek != 0) { + if (ZSEEK64(s->z_filefunc, s->filestream_with_CD, lSeek, ZLIB_FILEFUNC_SEEK_CUR) != 0) + err = UNZ_ERRNO; + } + + if ((file_info.size_file_comment > 0) && (comment_size > 0)) + if (ZREAD64(s->z_filefunc, s->filestream_with_CD, comment, (uLong)bytes_to_read) != bytes_to_read) + err = UNZ_ERRNO; + lSeek += file_info.size_file_comment - (uLong)bytes_to_read; + } else + lSeek += file_info.size_file_comment; + + if ((err == UNZ_OK) && (pfile_info != NULL)) + *pfile_info = file_info; + + if ((err == UNZ_OK) && (pfile_info_internal != NULL)) + *pfile_info_internal = file_info_internal; + + return err; +} + +extern int ZEXPORT unzGetCurrentFileInfo(unzFile file, unz_file_info *pfile_info, char *filename, + uLong filename_size, void *extrafield, uLong extrafield_size, char *comment, uLong comment_size) +{ + unz_file_info64 file_info64; + int err; + + err = unz64local_GetCurrentFileInfoInternal(file, &file_info64, NULL, filename, filename_size, + extrafield, extrafield_size, comment, comment_size); + + if ((err == UNZ_OK) && (pfile_info != NULL)) { + pfile_info->version = file_info64.version; + pfile_info->version_needed = file_info64.version_needed; + pfile_info->flag = file_info64.flag; + pfile_info->compression_method = file_info64.compression_method; + pfile_info->dosDate = file_info64.dosDate; + pfile_info->crc = file_info64.crc; + + pfile_info->size_filename = file_info64.size_filename; + pfile_info->size_file_extra = file_info64.size_file_extra - file_info64.size_file_extra_internal; + pfile_info->size_file_comment = file_info64.size_file_comment; + + pfile_info->disk_num_start = file_info64.disk_num_start; + pfile_info->internal_fa = file_info64.internal_fa; + pfile_info->external_fa = file_info64.external_fa; + + pfile_info->tmu_date = file_info64.tmu_date, + + pfile_info->compressed_size = (uLong)file_info64.compressed_size; + pfile_info->uncompressed_size = (uLong)file_info64.uncompressed_size; + + } + return err; +} + +extern int ZEXPORT unzGetCurrentFileInfo64(unzFile file, unz_file_info64 *pfile_info, char *filename, + uLong filename_size, void *extrafield, uLong extrafield_size, char *comment, uLong comment_size) +{ + return unz64local_GetCurrentFileInfoInternal(file, pfile_info, NULL, filename, filename_size, + extrafield, extrafield_size, comment, comment_size); +} + +/* Read the local header of the current zipfile. Check the coherency of the local header and info in the + end of central directory about this file store in *piSizeVar the size of extra info in local header + (filename and size of extra field data) */ +local int unz64local_CheckCurrentFileCoherencyHeader(unz64_s *s, uInt *piSizeVar, ZPOS64_T *poffset_local_extrafield, + uInt *psize_local_extrafield) +{ + uLong uMagic, uL, uFlags; + uLong size_filename; + uLong size_extra_field; + int err = UNZ_OK; + int compression_method = 0; + + *piSizeVar = 0; + *poffset_local_extrafield = 0; + *psize_local_extrafield = 0; + + err = unzGoToNextDisk((unzFile)s); + if (err != UNZ_OK) + return err; + + if (ZSEEK64(s->z_filefunc, s->filestream, s->cur_file_info_internal.offset_curfile + + s->cur_file_info_internal.byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0) + return UNZ_ERRNO; + + if (err == UNZ_OK) { + if (unz64local_getLong(&s->z_filefunc, s->filestream, &uMagic) != UNZ_OK) + err = UNZ_ERRNO; + else if (uMagic != LOCALHEADERMAGIC) + err = UNZ_BADZIPFILE; + } + + if (unz64local_getShort(&s->z_filefunc, s->filestream, &uL) != UNZ_OK) + err = UNZ_ERRNO; + if (unz64local_getShort(&s->z_filefunc, s->filestream, &uFlags) != UNZ_OK) + err = UNZ_ERRNO; + if (unz64local_getShort(&s->z_filefunc, s->filestream, &uL) != UNZ_OK) + err = UNZ_ERRNO; + else if ((err == UNZ_OK) && (uL != s->cur_file_info.compression_method)) + err = UNZ_BADZIPFILE; + + compression_method = (int)s->cur_file_info.compression_method; +#ifdef HAVE_AES + if (compression_method == AES_METHOD) + compression_method = (int)s->cur_file_info_internal.aes_compression_method; +#endif + + if ((err == UNZ_OK) && (compression_method != 0) && +#ifdef HAVE_BZIP2 + (compression_method != Z_BZIP2ED) && +#endif + (compression_method != Z_DEFLATED)) + err = UNZ_BADZIPFILE; + + if (unz64local_getLong(&s->z_filefunc, s->filestream, &uL) != UNZ_OK) /* date/time */ + err = UNZ_ERRNO; + if (unz64local_getLong(&s->z_filefunc, s->filestream, &uL) != UNZ_OK) /* crc */ + err = UNZ_ERRNO; + else if ((err == UNZ_OK) && (uL != s->cur_file_info.crc) && ((uFlags & 8) == 0)) + err = UNZ_BADZIPFILE; + if (unz64local_getLong(&s->z_filefunc, s->filestream, &uL) != UNZ_OK) /* size compr */ + err = UNZ_ERRNO; + else if ((uL != 0xffffffff) && (err == UNZ_OK) && (uL != s->cur_file_info.compressed_size) && ((uFlags & 8) == 0)) + err = UNZ_BADZIPFILE; + if (unz64local_getLong(&s->z_filefunc, s->filestream, &uL) != UNZ_OK) /* size uncompr */ + err = UNZ_ERRNO; + else if ((uL != 0xffffffff) && (err == UNZ_OK) && (uL != s->cur_file_info.uncompressed_size) && ((uFlags & 8) == 0)) + err = UNZ_BADZIPFILE; + if (unz64local_getShort(&s->z_filefunc, s->filestream, &size_filename) != UNZ_OK) + err = UNZ_ERRNO; + else if ((err == UNZ_OK) && (size_filename != s->cur_file_info.size_filename)) + err = UNZ_BADZIPFILE; + + *piSizeVar += (uInt)size_filename; + + if (unz64local_getShort(&s->z_filefunc, s->filestream, &size_extra_field) != UNZ_OK) + err = UNZ_ERRNO; + *poffset_local_extrafield = s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + size_filename; + *psize_local_extrafield = (uInt)size_extra_field; + + *piSizeVar += (uInt)size_extra_field; + + return err; +} + +/* + Open for reading data the current file in the zipfile. + If there is no error and the file is opened, the return value is UNZ_OK. + */ +extern int ZEXPORT unzOpenCurrentFile3(unzFile file, int *method, int *level, int raw, const char *password) +{ + int err = UNZ_OK; + int compression_method; + uInt iSizeVar; + unz64_s *s; + file_in_zip64_read_info_s *pfile_in_zip_read_info; + ZPOS64_T offset_local_extrafield; + uInt size_local_extrafield; +#ifndef NOUNCRYPT + char source[12]; +#else + if (password != NULL) + return UNZ_PARAMERROR; +#endif + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz64_s *)file; + if (!s->current_file_ok) + return UNZ_PARAMERROR; + + if (s->pfile_in_zip_read != NULL) + unzCloseCurrentFile(file); + + if (unz64local_CheckCurrentFileCoherencyHeader(s, &iSizeVar, &offset_local_extrafield, &size_local_extrafield) != UNZ_OK) + return UNZ_BADZIPFILE; + + pfile_in_zip_read_info = (file_in_zip64_read_info_s *)ALLOC(sizeof(file_in_zip64_read_info_s)); + if (pfile_in_zip_read_info == NULL) + return UNZ_INTERNALERROR; + + pfile_in_zip_read_info->read_buffer = (Bytef *)ALLOC(UNZ_BUFSIZE); + pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; + 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; + + if (pfile_in_zip_read_info->read_buffer == NULL) { + TRYFREE(pfile_in_zip_read_info); + return UNZ_INTERNALERROR; + } + + pfile_in_zip_read_info->stream_initialised = 0; + + compression_method = (int)s->cur_file_info.compression_method; +#ifdef HAVE_AES + if (compression_method == AES_METHOD) + compression_method = (int)s->cur_file_info_internal.aes_compression_method; +#endif + + if (method != NULL) + *method = compression_method; + + if (level != NULL) { + *level = 6; + switch (s->cur_file_info.flag & 0x06) { + case 6: *level = 1; break; + case 4: *level = 2; break; + case 2: *level = 9; break; + } + } + + if ((compression_method != 0) && +#ifdef HAVE_BZIP2 + (compression_method != Z_BZIP2ED) && +#endif + (compression_method != Z_DEFLATED)) + err = UNZ_BADZIPFILE; + + pfile_in_zip_read_info->crc32_wait = s->cur_file_info.crc; + pfile_in_zip_read_info->crc32 = 0; + pfile_in_zip_read_info->total_out_64 = 0; + pfile_in_zip_read_info->compression_method = compression_method; + pfile_in_zip_read_info->filestream = s->filestream; + pfile_in_zip_read_info->z_filefunc = s->z_filefunc; + if (s->number_disk == s->gi.number_disk_with_CD) + pfile_in_zip_read_info->byte_before_the_zipfile = s->byte_before_the_zipfile; + else + pfile_in_zip_read_info->byte_before_the_zipfile = 0; + pfile_in_zip_read_info->stream.total_out = 0; + pfile_in_zip_read_info->stream.total_in = 0; + pfile_in_zip_read_info->stream.next_in = NULL; + + if (!raw) { + if (compression_method == Z_BZIP2ED) { +#ifdef HAVE_BZIP2 + pfile_in_zip_read_info->bstream.bzalloc = (void *(*)(void *, int, int)) 0; + pfile_in_zip_read_info->bstream.bzfree = (free_func)0; + pfile_in_zip_read_info->bstream.opaque = (voidpf)0; + pfile_in_zip_read_info->bstream.state = (voidpf)0; + + pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; + pfile_in_zip_read_info->stream.zfree = (free_func)0; + pfile_in_zip_read_info->stream.opaque = (voidpf)0; + pfile_in_zip_read_info->stream.next_in = (voidpf)0; + pfile_in_zip_read_info->stream.avail_in = 0; + + err = BZ2_bzDecompressInit(&pfile_in_zip_read_info->bstream, 0, 0); + if (err == Z_OK) + pfile_in_zip_read_info->stream_initialised = Z_BZIP2ED; + else { + TRYFREE(pfile_in_zip_read_info); + return err; + } +#else + pfile_in_zip_read_info->raw = 1; +#endif + } else if (compression_method == Z_DEFLATED) { + pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; + pfile_in_zip_read_info->stream.zfree = (free_func)0; + pfile_in_zip_read_info->stream.opaque = (voidpf)s; + pfile_in_zip_read_info->stream.next_in = 0; + pfile_in_zip_read_info->stream.avail_in = 0; + + err = inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); + if (err == Z_OK) + pfile_in_zip_read_info->stream_initialised = Z_DEFLATED; + else { + TRYFREE(pfile_in_zip_read_info); + return err; + } + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. + * In unzip, i don't wait absolutely Z_STREAM_END because I known the + * size of both compressed and uncompressed data + */ + } + } + + pfile_in_zip_read_info->rest_read_compressed = s->cur_file_info.compressed_size; + pfile_in_zip_read_info->rest_read_uncompressed = s->cur_file_info.uncompressed_size; + pfile_in_zip_read_info->pos_in_zipfile = s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + iSizeVar; + pfile_in_zip_read_info->stream.avail_in = (uInt)0; + + s->pfile_in_zip_read = pfile_in_zip_read_info; + +#ifndef NOUNCRYPT + if ((password != NULL) && ((s->cur_file_info.flag & 1) != 0)) { + if (ZSEEK64(s->z_filefunc, s->filestream, + s->pfile_in_zip_read->pos_in_zipfile + s->pfile_in_zip_read->byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET) != 0) + return UNZ_INTERNALERROR; +#ifdef HAVE_AES + if (s->cur_file_info.compression_method == AES_METHOD) { + unsigned char passverify[AES_PWVERIFYSIZE]; + unsigned char saltvalue[AES_MAXSALTLENGTH]; + uInt saltlength; + + if ((s->cur_file_info_internal.aes_encryption_mode < 1) || + (s->cur_file_info_internal.aes_encryption_mode > 3)) + return UNZ_INTERNALERROR; + + saltlength = SALT_LENGTH(s->cur_file_info_internal.aes_encryption_mode); + + if (ZREAD64(s->z_filefunc, s->filestream, saltvalue, saltlength) != saltlength) + return UNZ_INTERNALERROR; + if (ZREAD64(s->z_filefunc, s->filestream, passverify, AES_PWVERIFYSIZE) != AES_PWVERIFYSIZE) + return UNZ_INTERNALERROR; + + fcrypt_init((int)s->cur_file_info_internal.aes_encryption_mode, (unsigned char *)password, (unsigned int)strlen(password), saltvalue, + passverify, &s->pfile_in_zip_read->aes_ctx); + + pfile_in_zip_read_info->rest_read_compressed -= saltlength + AES_PWVERIFYSIZE; + pfile_in_zip_read_info->rest_read_compressed -= AES_AUTHCODESIZE; + + s->pfile_in_zip_read->pos_in_zipfile += saltlength + AES_PWVERIFYSIZE; + } else +#endif + { + int i; + s->pcrc_32_tab = (const unsigned long *)get_crc_table(); + init_keys(password, s->keys, s->pcrc_32_tab); + + if (ZREAD64(s->z_filefunc, s->filestream, source, 12) < 12) + return UNZ_INTERNALERROR; + + for (i = 0; i < 12; i++) + zdecode(s->keys, s->pcrc_32_tab, source[i]); + + pfile_in_zip_read_info->rest_read_compressed -= 12; + + s->pfile_in_zip_read->pos_in_zipfile += 12; + } + } +#endif + + return UNZ_OK; +} + +extern int ZEXPORT unzOpenCurrentFile(unzFile file) +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL); +} + +extern int ZEXPORT unzOpenCurrentFilePassword(unzFile file, const char *password) +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, password); +} + +extern int ZEXPORT unzOpenCurrentFile2(unzFile file, int *method, int *level, int raw) +{ + return unzOpenCurrentFile3(file, method, level, raw, NULL); +} + +/* Read bytes from the current file. + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if some bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error (UNZ_ERRNO for IO error, or zLib error for uncompress error) */ +extern int ZEXPORT unzReadCurrentFile(unzFile file, voidp buf, unsigned len) +{ + int err = UNZ_OK; + uInt read = 0; + unz64_s *s; + file_in_zip64_read_info_s *pfile_in_zip_read_info; + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz64_s *)file; + pfile_in_zip_read_info = s->pfile_in_zip_read; + + if (pfile_in_zip_read_info == NULL) + return UNZ_PARAMERROR; + if (pfile_in_zip_read_info->read_buffer == NULL) + return UNZ_END_OF_LIST_OF_FILE; + if (len == 0) + return 0; + + pfile_in_zip_read_info->stream.next_out = (Bytef *)buf; + pfile_in_zip_read_info->stream.avail_out = (uInt)len; + + if (pfile_in_zip_read_info->raw) { + if (len > pfile_in_zip_read_info->rest_read_compressed + pfile_in_zip_read_info->stream.avail_in) + pfile_in_zip_read_info->stream.avail_out = (uInt)pfile_in_zip_read_info->rest_read_compressed + + pfile_in_zip_read_info->stream.avail_in; + } else { + + // 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/ZipArchive/ziparchive/issues/16 + // + + /* + + + FIXME: Upgrading to minizip 1.1 caused issues here, Uncommented the code that was commented before. 11/24/2015 + */ + + if (len > pfile_in_zip_read_info->rest_read_uncompressed) + pfile_in_zip_read_info->stream.avail_out = (uInt)pfile_in_zip_read_info->rest_read_uncompressed; + + + + } + + while (pfile_in_zip_read_info->stream.avail_out > 0) { + if (pfile_in_zip_read_info->stream.avail_in == 0) { + uInt bytes_to_read = UNZ_BUFSIZE; + uInt bytes_not_read = 0; + uInt bytes_read = 0; + uInt total_bytes_read = 0; + + if (pfile_in_zip_read_info->stream.next_in != NULL) + bytes_not_read = (uInt)(pfile_in_zip_read_info->read_buffer + UNZ_BUFSIZE - + pfile_in_zip_read_info->stream.next_in); + bytes_to_read -= bytes_not_read; + if (bytes_not_read > 0) + memcpy(pfile_in_zip_read_info->read_buffer, pfile_in_zip_read_info->stream.next_in, bytes_not_read); + if (pfile_in_zip_read_info->rest_read_compressed < bytes_to_read) + bytes_to_read = (uInt)pfile_in_zip_read_info->rest_read_compressed; + + while (total_bytes_read != bytes_to_read) { + if (ZSEEK64(pfile_in_zip_read_info->z_filefunc, pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->pos_in_zipfile + pfile_in_zip_read_info->byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET) != 0) + return UNZ_ERRNO; + + bytes_read = (int)ZREAD64(pfile_in_zip_read_info->z_filefunc, pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->read_buffer + bytes_not_read + total_bytes_read, + bytes_to_read - total_bytes_read); + + total_bytes_read += bytes_read; + pfile_in_zip_read_info->pos_in_zipfile += bytes_read; + + if (bytes_read == 0) { + if (ZERROR64(pfile_in_zip_read_info->z_filefunc, pfile_in_zip_read_info->filestream)) + return UNZ_ERRNO; + + err = unzGoToNextDisk(file); + if (err != UNZ_OK) + return err; + + pfile_in_zip_read_info->pos_in_zipfile = 0; + pfile_in_zip_read_info->filestream = s->filestream; + } + } + +#ifndef NOUNCRYPT + if ((s->cur_file_info.flag & 1) != 0) { +#ifdef HAVE_AES + if (s->cur_file_info.compression_method == AES_METHOD) { + fcrypt_decrypt(pfile_in_zip_read_info->read_buffer, bytes_to_read, &s->pfile_in_zip_read->aes_ctx); + } else +#endif + { + uInt i; + for (i = 0; i < total_bytes_read; i++) + pfile_in_zip_read_info->read_buffer[i] = + zdecode(s->keys, s->pcrc_32_tab, pfile_in_zip_read_info->read_buffer[i]); + } + } +#endif + + pfile_in_zip_read_info->rest_read_compressed -= total_bytes_read; + pfile_in_zip_read_info->stream.next_in = (Bytef *)pfile_in_zip_read_info->read_buffer; + pfile_in_zip_read_info->stream.avail_in = (uInt)bytes_not_read + total_bytes_read; + } + + if ((pfile_in_zip_read_info->compression_method == 0) || (pfile_in_zip_read_info->raw)) { + uInt copy, i; + + if ((pfile_in_zip_read_info->stream.avail_in == 0) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + return (read == 0) ? UNZ_EOF : read; + + if (pfile_in_zip_read_info->stream.avail_out < pfile_in_zip_read_info->stream.avail_in) + copy = pfile_in_zip_read_info->stream.avail_out; + else + copy = pfile_in_zip_read_info->stream.avail_in; + + for (i = 0; i < copy; i++) + *(pfile_in_zip_read_info->stream.next_out + i) = + *(pfile_in_zip_read_info->stream.next_in + i); + + pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + copy; + pfile_in_zip_read_info->rest_read_uncompressed -= copy; + pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, + pfile_in_zip_read_info->stream.next_out, copy); + + pfile_in_zip_read_info->stream.avail_in -= copy; + pfile_in_zip_read_info->stream.avail_out -= copy; + pfile_in_zip_read_info->stream.next_out += copy; + pfile_in_zip_read_info->stream.next_in += copy; + pfile_in_zip_read_info->stream.total_out += copy; + read += copy; + } else if (pfile_in_zip_read_info->compression_method == Z_BZIP2ED) { +#ifdef HAVE_BZIP2 + uLong total_out_before, total_out_after; + const Bytef *buf_before; + uLong out_bytes; + + pfile_in_zip_read_info->bstream.next_in = (char *)pfile_in_zip_read_info->stream.next_in; + pfile_in_zip_read_info->bstream.avail_in = pfile_in_zip_read_info->stream.avail_in; + pfile_in_zip_read_info->bstream.total_in_lo32 = pfile_in_zip_read_info->stream.total_in; + pfile_in_zip_read_info->bstream.total_in_hi32 = 0; + pfile_in_zip_read_info->bstream.next_out = (char *)pfile_in_zip_read_info->stream.next_out; + pfile_in_zip_read_info->bstream.avail_out = pfile_in_zip_read_info->stream.avail_out; + pfile_in_zip_read_info->bstream.total_out_lo32 = pfile_in_zip_read_info->stream.total_out; + pfile_in_zip_read_info->bstream.total_out_hi32 = 0; + + total_out_before = pfile_in_zip_read_info->bstream.total_out_lo32; + buf_before = (const Bytef *)pfile_in_zip_read_info->bstream.next_out; + + err = BZ2_bzDecompress(&pfile_in_zip_read_info->bstream); + + total_out_after = pfile_in_zip_read_info->bstream.total_out_lo32; + out_bytes = total_out_after - total_out_before; + + pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + out_bytes; + pfile_in_zip_read_info->rest_read_uncompressed -= out_bytes; + pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, buf_before, (uInt)(out_bytes)); + + read += (uInt)(total_out_after - total_out_before); + + pfile_in_zip_read_info->stream.next_in = (Bytef *)pfile_in_zip_read_info->bstream.next_in; + pfile_in_zip_read_info->stream.avail_in = pfile_in_zip_read_info->bstream.avail_in; + pfile_in_zip_read_info->stream.total_in = pfile_in_zip_read_info->bstream.total_in_lo32; + pfile_in_zip_read_info->stream.next_out = (Bytef *)pfile_in_zip_read_info->bstream.next_out; + pfile_in_zip_read_info->stream.avail_out = pfile_in_zip_read_info->bstream.avail_out; + pfile_in_zip_read_info->stream.total_out = pfile_in_zip_read_info->bstream.total_out_lo32; + + if (err == BZ_STREAM_END) + return (read == 0) ? UNZ_EOF : read; + if (err != BZ_OK) + break; +#endif + } else { + ZPOS64_T total_out_before, total_out_after; + const Bytef *buf_before; + ZPOS64_T out_bytes; + int flush = Z_SYNC_FLUSH; + + total_out_before = pfile_in_zip_read_info->stream.total_out; + buf_before = pfile_in_zip_read_info->stream.next_out; + + /* + if ((pfile_in_zip_read_info->rest_read_uncompressed == + pfile_in_zip_read_info->stream.avail_out) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + flush = Z_FINISH; + */ + err = inflate(&pfile_in_zip_read_info->stream, flush); + + if ((err >= 0) && (pfile_in_zip_read_info->stream.msg != NULL)) + err = Z_DATA_ERROR; + + total_out_after = pfile_in_zip_read_info->stream.total_out; + out_bytes = total_out_after - total_out_before; + + pfile_in_zip_read_info->total_out_64 += out_bytes; + pfile_in_zip_read_info->rest_read_uncompressed -= out_bytes; + pfile_in_zip_read_info->crc32 = + crc32(pfile_in_zip_read_info->crc32, buf_before, (uInt)(out_bytes)); + + read += (uInt)(total_out_after - total_out_before); + + if (err == Z_STREAM_END) + return (read == 0) ? UNZ_EOF : read; + if (err != Z_OK) + break; + } + } + + if (err == Z_OK) + return read; + return err; +} + +extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64(unzFile file) +{ + unz64_s *s; + file_in_zip64_read_info_s *pfile_in_zip_read_info; + s = (unz64_s *)file; + if (file == NULL) + return 0; /* UNZ_PARAMERROR */ + pfile_in_zip_read_info = s->pfile_in_zip_read; + if (pfile_in_zip_read_info == NULL) + return 0; /* UNZ_PARAMERROR */ + return pfile_in_zip_read_info->pos_in_zipfile + pfile_in_zip_read_info->byte_before_the_zipfile; +} + +extern int ZEXPORT unzGetLocalExtrafield(unzFile file, voidp buf, unsigned len) +{ + unz64_s *s; + file_in_zip64_read_info_s *pfile_in_zip_read_info; + uInt read_now; + ZPOS64_T size_to_read; + + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz64_s *)file; + pfile_in_zip_read_info = s->pfile_in_zip_read; + + if (pfile_in_zip_read_info == NULL) + return UNZ_PARAMERROR; + + size_to_read = pfile_in_zip_read_info->size_local_extrafield - pfile_in_zip_read_info->pos_local_extrafield; + + if (buf == NULL) + return (int)size_to_read; + + if (len > size_to_read) + read_now = (uInt)size_to_read; + else + read_now = (uInt)len; + + if (read_now == 0) + return 0; + + if (ZSEEK64(pfile_in_zip_read_info->z_filefunc, pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->offset_local_extrafield + pfile_in_zip_read_info->pos_local_extrafield, + ZLIB_FILEFUNC_SEEK_SET) != 0) + return UNZ_ERRNO; + + if (ZREAD64(pfile_in_zip_read_info->z_filefunc, pfile_in_zip_read_info->filestream, buf, read_now) != read_now) + return UNZ_ERRNO; + + return (int)read_now; +} + +extern int ZEXPORT unzCloseCurrentFile(unzFile file) +{ + int err = UNZ_OK; + + unz64_s *s; + file_in_zip64_read_info_s *pfile_in_zip_read_info; + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz64_s *)file; + pfile_in_zip_read_info = s->pfile_in_zip_read; + + if (pfile_in_zip_read_info == NULL) + return UNZ_PARAMERROR; + +#ifdef HAVE_AES + if (s->cur_file_info.compression_method == AES_METHOD) { + unsigned char authcode[AES_AUTHCODESIZE]; + unsigned char rauthcode[AES_AUTHCODESIZE]; + + if (ZREAD64(s->z_filefunc, s->filestream, authcode, AES_AUTHCODESIZE) != AES_AUTHCODESIZE) + return UNZ_ERRNO; + + if (fcrypt_end(rauthcode, &s->pfile_in_zip_read->aes_ctx) != AES_AUTHCODESIZE) + err = UNZ_CRCERROR; + if (memcmp(authcode, rauthcode, AES_AUTHCODESIZE) != 0) + err = UNZ_CRCERROR; + } + /* AES zip version AE-1 will expect a valid crc as well */ + if ((s->cur_file_info.compression_method != AES_METHOD) || + (s->cur_file_info_internal.aes_version == 0x0001)) +#endif + { + if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) && + (!pfile_in_zip_read_info->raw)) { + if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) + err = UNZ_CRCERROR; + } + } + + TRYFREE(pfile_in_zip_read_info->read_buffer); + pfile_in_zip_read_info->read_buffer = NULL; + if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED) + inflateEnd(&pfile_in_zip_read_info->stream); +#ifdef HAVE_BZIP2 + else if (pfile_in_zip_read_info->stream_initialised == Z_BZIP2ED) + BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream); +#endif + + pfile_in_zip_read_info->stream_initialised = 0; + TRYFREE(pfile_in_zip_read_info); + + s->pfile_in_zip_read = NULL; + + return err; +} + +extern int ZEXPORT unzGoToFirstFile2(unzFile file, unz_file_info64 *pfile_info, char *filename, + uLong filename_size, void *extrafield, uLong extrafield_size, char *comment, uLong comment_size) +{ + int err = UNZ_OK; + unz64_s *s; + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz64_s *)file; + s->pos_in_central_dir = s->offset_central_dir; + s->num_file = 0; + err = unz64local_GetCurrentFileInfoInternal(file, &s->cur_file_info, &s->cur_file_info_internal, + filename, filename_size, extrafield, extrafield_size, comment, comment_size); + s->current_file_ok = (err == UNZ_OK); + if ((err == UNZ_OK) && (pfile_info != NULL)) + memcpy(pfile_info, &s->cur_file_info, sizeof(unz_file_info64)); + return err; +} + +extern int ZEXPORT unzGoToFirstFile(unzFile file) +{ + return unzGoToFirstFile2(file, NULL, NULL, 0, NULL, 0, NULL, 0); +} + +extern int ZEXPORT unzGoToNextFile2(unzFile file, unz_file_info64 *pfile_info, char *filename, + uLong filename_size, void *extrafield, uLong extrafield_size, char *comment, uLong comment_size) +{ + unz64_s *s; + int err; + + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz64_s *)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */ + if (s->num_file + 1 == s->gi.number_entry) + return UNZ_END_OF_LIST_OF_FILE; + s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + + s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment; + s->num_file++; + err = unz64local_GetCurrentFileInfoInternal(file, &s->cur_file_info, &s->cur_file_info_internal, + filename, filename_size, extrafield, extrafield_size, comment, comment_size); + s->current_file_ok = (err == UNZ_OK); + if ((err == UNZ_OK) && (pfile_info != NULL)) + memcpy(pfile_info, &s->cur_file_info, sizeof(unz_file_info64)); + return err; +} + +extern int ZEXPORT unzGoToNextFile(unzFile file) +{ + return unzGoToNextFile2(file, NULL, NULL, 0, NULL, 0, NULL, 0); +} + +extern int ZEXPORT unzLocateFile(unzFile file, const char *filename, unzFileNameComparer filename_compare_func) +{ + unz64_s *s; + int err; + unz_file_info64 cur_file_info_saved; + unz_file_info64_internal cur_file_info_internal_saved; + ZPOS64_T num_file_saved; + ZPOS64_T pos_in_central_dir_saved; + char current_filename[UNZ_MAXFILENAMEINZIP + 1]; + + if (file == NULL) + return UNZ_PARAMERROR; + if (strlen(filename) >= UNZ_MAXFILENAMEINZIP) + return UNZ_PARAMERROR; + s = (unz64_s *)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + /* Save the current state */ + num_file_saved = s->num_file; + pos_in_central_dir_saved = s->pos_in_central_dir; + cur_file_info_saved = s->cur_file_info; + cur_file_info_internal_saved = s->cur_file_info_internal; + + err = unzGoToFirstFile2(file, NULL, current_filename, sizeof(current_filename) - 1, NULL, 0, NULL, 0); + + while (err == UNZ_OK) { + if (filename_compare_func != NULL) + err = filename_compare_func(file, current_filename, filename); + else + err = strcmp(current_filename, filename); + if (err == 0) + return UNZ_OK; + err = unzGoToNextFile2(file, NULL, current_filename, sizeof(current_filename) - 1, NULL, 0, NULL, 0); + } + + /* We failed, so restore the state of the 'current file' to where we were. */ + s->num_file = num_file_saved; + s->pos_in_central_dir = pos_in_central_dir_saved; + s->cur_file_info = cur_file_info_saved; + s->cur_file_info_internal = cur_file_info_internal_saved; + return err; +} + +extern int ZEXPORT unzGetFilePos(unzFile file, unz_file_pos *file_pos) +{ + unz64_file_pos file_pos64; + int err = unzGetFilePos64(file, &file_pos64); + if (err == UNZ_OK) { + file_pos->pos_in_zip_directory = (uLong)file_pos64.pos_in_zip_directory; + file_pos->num_of_file = (uLong)file_pos64.num_of_file; + } + return err; +} + +extern int ZEXPORT unzGoToFilePos(unzFile file, unz_file_pos *file_pos) +{ + unz64_file_pos file_pos64; + + if (file_pos == NULL) + return UNZ_PARAMERROR; + file_pos64.pos_in_zip_directory = file_pos->pos_in_zip_directory; + file_pos64.num_of_file = file_pos->num_of_file; + return unzGoToFilePos64(file, &file_pos64); +} + +extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos *file_pos) +{ + unz64_s *s; + + if (file == NULL || file_pos == NULL) + return UNZ_PARAMERROR; + s = (unz64_s *)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + file_pos->pos_in_zip_directory = s->pos_in_central_dir; + file_pos->num_of_file = s->num_file; + + return UNZ_OK; +} + +extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos *file_pos) +{ + unz64_s *s; + int err; + + if (file == NULL || file_pos == NULL) + return UNZ_PARAMERROR; + s = (unz64_s *)file; + + /* jump to the right spot */ + s->pos_in_central_dir = file_pos->pos_in_zip_directory; + s->num_file = file_pos->num_of_file; + + /* set the current file */ + err = unz64local_GetCurrentFileInfoInternal(file, &s->cur_file_info, &s->cur_file_info_internal, NULL, 0, NULL, 0, NULL, 0); + /* return results */ + s->current_file_ok = (err == UNZ_OK); + return err; +} + +extern uLong ZEXPORT unzGetOffset(unzFile file) +{ + ZPOS64_T offset64; + + if (file == NULL) + return 0; /* UNZ_PARAMERROR; */ + offset64 = unzGetOffset64(file); + return (uLong)offset64; +} + +extern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file) +{ + unz64_s *s; + + if (file == NULL) + return 0; /* UNZ_PARAMERROR; */ + s = (unz64_s *)file; + if (!s->current_file_ok) + return 0; + if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff) + if (s->num_file == s->gi.number_entry) + return 0; + return s->pos_in_central_dir; +} + +extern int ZEXPORT unzSetOffset(unzFile file, uLong pos) +{ + return unzSetOffset64(file, pos); +} + +extern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos) +{ + unz64_s *s; + int err; + + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz64_s *)file; + + s->pos_in_central_dir = pos; + s->num_file = s->gi.number_entry; /* hack */ + err = unz64local_GetCurrentFileInfoInternal(file, &s->cur_file_info, &s->cur_file_info_internal, NULL, 0, NULL, 0, NULL, 0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + +extern z_off_t ZEXPORT unztell(unzFile file) +{ + unz64_s *s; + file_in_zip64_read_info_s *pfile_in_zip_read_info; + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz64_s *)file; + pfile_in_zip_read_info = s->pfile_in_zip_read; + if (pfile_in_zip_read_info == NULL) + return UNZ_PARAMERROR; + return (z_off_t)pfile_in_zip_read_info->stream.total_out; +} + +extern ZPOS64_T ZEXPORT unztell64(unzFile file) +{ + + unz64_s *s; + file_in_zip64_read_info_s *pfile_in_zip_read_info; + if (file == NULL) + return (ZPOS64_T)-1; + s = (unz64_s *)file; + pfile_in_zip_read_info = s->pfile_in_zip_read; + + if (pfile_in_zip_read_info == NULL) + return (ZPOS64_T)-1; + + return pfile_in_zip_read_info->total_out_64; +} + +extern int ZEXPORT unzeof(unzFile file) +{ + unz64_s *s; + file_in_zip64_read_info_s *pfile_in_zip_read_info; + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz64_s *)file; + pfile_in_zip_read_info = s->pfile_in_zip_read; + + if (pfile_in_zip_read_info == NULL) + return UNZ_PARAMERROR; + + if (pfile_in_zip_read_info->rest_read_uncompressed == 0) + return 1; + return 0; +} + diff --git a/SSZipArchive/minizip/unzip.h b/SSZipArchive/minizip/unzip.h new file mode 100755 index 0000000..02c4c58 --- /dev/null +++ b/SSZipArchive/minizip/unzip.h @@ -0,0 +1,248 @@ +/* unzip.h -- IO for uncompress .zip files using zlib + Version 1.1, February 14h, 2010 + part of the MiniZip project + + Copyright (C) 1998-2010 Gilles Vollant + http://www.winimage.com/zLibDll/minizip.html + Modifications of Unzip for Zip64 + Copyright (C) 2007-2008 Even Rouault + Modifications for Zip64 support on both zip and unzip + Copyright (C) 2009-2010 Mathias Svensson + http://result42.com + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#include "Common.h" + +#ifndef _UNZ_H +#define _UNZ_H + +#define HAVE_AES + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#ifndef _ZLIBIOAPI_H +#include "ioapi.h" +#endif + +#ifdef HAVE_BZIP2 +#include "bzlib.h" +#endif + +#define Z_BZIP2ED 12 + +#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagunzFile__ { int unused; } unzFile__; +typedef unzFile__ *unzFile; +#else +typedef voidp unzFile; +#endif + + +#define UNZ_OK (0) +#define UNZ_END_OF_LIST_OF_FILE (-100) +#define UNZ_ERRNO (Z_ERRNO) +#define UNZ_EOF (0) +#define UNZ_PARAMERROR (-102) +#define UNZ_BADZIPFILE (-103) +#define UNZ_INTERNALERROR (-104) +#define UNZ_CRCERROR (-105) + + +/***************************************************************************/ +/* Opening and close a zip file */ + +extern unzFile ZEXPORT unzOpen OF((const char *path)); +extern unzFile ZEXPORT unzOpen64 OF((const void *path)); +/* Open a Zip file. + + path should contain the full pathname (by example, on a Windows XP computer + "c:\\zlib\\zlib113.zip" or on an Unix computer "zlib/zlib113.zip". + return NULL if zipfile cannot be opened or doesn't exist + return unzFile handle if no error + + NOTE: The "64" function take a const void* pointer, because the path is just the value passed to the + open64_file_func callback. Under Windows, if UNICODE is defined, using fill_fopen64_filefunc, the path + is a pointer to a wide unicode string (LPCTSTR is LPCWSTR), so const char* does not describe the reality */ + +extern unzFile ZEXPORT unzOpen2 OF((const char *path, zlib_filefunc_def* pzlib_filefunc_def)); +/* Open a Zip file, like unzOpen, but provide a set of file low level API for read/write operations */ +extern unzFile ZEXPORT unzOpen2_64 OF((const void *path, zlib_filefunc64_def* pzlib_filefunc_def)); +/* Open a Zip file, like unz64Open, but provide a set of file low level API for read/write 64-bit operations */ + +extern int ZEXPORT unzClose OF((unzFile file)); +/* Close a ZipFile opened with unzipOpen. If there is files inside the .Zip opened with unzOpenCurrentFile, + these files MUST be closed with unzipCloseCurrentFile before call unzipClose. + + return UNZ_OK if there is no error */ + +extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, unz_global_info *pglobal_info)); +extern int ZEXPORT unzGetGlobalInfo64 OF((unzFile file, unz_global_info64 *pglobal_info)); +/* Write info about the ZipFile in the *pglobal_info structure. + + return UNZ_OK if no error */ + +extern int ZEXPORT unzGetGlobalComment OF((unzFile file, char *comment, uLong comment_size)); +/* Get the global comment string of the ZipFile, in the comment buffer. + + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 */ + +/***************************************************************************/ +/* Reading the content of the current zipfile, you can open it, read data from it, and close it + (you can close it before reading all the file) */ + +extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); +/* Open for reading data the current file in the zipfile. + + return UNZ_OK if no error */ + +extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file, const char* password)); +/* Open for reading data the current file in the zipfile. + password is a crypting password + + return UNZ_OK if no error */ + +extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, int* method, int* level, int raw)); +/* Same as unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 *method will receive method of compression, *level will receive level of compression + + NOTE: you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL */ + +extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file, int* method, int* level, int raw, const char* password)); +/* Same as unzOpenCurrentFile, but takes extra parameter password for encrypted files */ + +extern int ZEXPORT unzReadCurrentFile OF((unzFile file, voidp buf, unsigned len)); +/* Read bytes from the current file (opened by unzOpenCurrentFile) + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error (UNZ_ERRNO for IO error, or zLib error for uncompress error) */ + +extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, unz_file_info *pfile_info, char *filename, + uLong filename_size, void *extrafield, uLong extrafield_size, char *comment, uLong comment_size)); +extern int ZEXPORT unzGetCurrentFileInfo64 OF((unzFile file, unz_file_info64 *pfile_info, char *filename, + uLong filename_size, void *extrafield, uLong extrafield_size, char *comment, uLong comment_size)); +/* Get Info about the current file + + pfile_info if != NULL, the *pfile_info structure will contain somes info about the current file + filename if != NULL, the file name string will be copied in filename + filename_size is the size of the filename buffer + extrafield if != NULL, the extra field information from the central header will be copied in to + extrafield_size is the size of the extraField buffer + comment if != NULL, the comment string of the file will be copied in to + comment_size is the size of the comment buffer */ + +extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64 OF((unzFile file)); + +extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, voidp buf, unsigned len)); +/* Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf == NULL, it return the size of the local extra field + if buf != NULL, len is the size of the buffer, the extra header is copied in buf. + + return number of bytes copied in buf, or (if <0) the error code */ + +extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); +/* Close the file in zip opened with unzOpenCurrentFile + + return UNZ_CRCERROR if all the file was read but the CRC is not good */ + +/***************************************************************************/ +/* Browse the directory of the zipfile */ + +typedef int (*unzFileNameComparer)(unzFile file, const char *filename1, const char *filename2); +typedef int (*unzIteratorFunction)(unzFile file); +typedef int (*unzIteratorFunction2)(unzFile file, unz_file_info64 *pfile_info, char *filename, + uLong filename_size, void *extrafield, uLong extrafield_size, char *comment, uLong comment_size); + +extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); +/* Set the current file of the zipfile to the first file. + + return UNZ_OK if no error */ + +extern int ZEXPORT unzGoToFirstFile2 OF((unzFile file, unz_file_info64 *pfile_info, char *filename, + uLong filename_size, void *extrafield, uLong extrafield_size, char *comment, uLong comment_size)); +/* Set the current file of the zipfile to the first file and retrieves the current info on success. + Not as seek intensive as unzGoToFirstFile + unzGetCurrentFileInfo. + + return UNZ_OK if no error */ + +extern int ZEXPORT unzGoToNextFile OF((unzFile file)); +/* Set the current file of the zipfile to the next file. + + return UNZ_OK if no error + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest */ + +extern int ZEXPORT unzGoToNextFile2 OF((unzFile file, unz_file_info64 *pfile_info, char *filename, + uLong filename_size, void *extrafield, uLong extrafield_size, char *comment, uLong comment_size)); +/* Set the current file of the zipfile to the next file and retrieves the current + info on success. Does less seeking around than unzGotoNextFile + unzGetCurrentFileInfo. + + return UNZ_OK if no error + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest */ + +extern int ZEXPORT unzLocateFile OF((unzFile file, const char *filename, unzFileNameComparer filename_compare_func)); +/* Try locate the file szFileName in the zipfile. For custom filename comparison pass in comparison function. + + return UNZ_OK if the file is found (it becomes the current file) + return UNZ_END_OF_LIST_OF_FILE if the file is not found */ + +/***************************************************************************/ +/* Raw access to zip file */ + +typedef struct unz_file_pos_s +{ + uLong pos_in_zip_directory; /* offset in zip file directory */ + uLong num_of_file; /* # of file */ +} unz_file_pos; + +extern int ZEXPORT unzGetFilePos OF((unzFile file, unz_file_pos* file_pos)); +extern int ZEXPORT unzGoToFilePos OF((unzFile file, unz_file_pos* file_pos)); + +typedef struct unz64_file_pos_s +{ + ZPOS64_T pos_in_zip_directory; /* offset in zip file directory */ + ZPOS64_T num_of_file; /* # of file */ +} unz64_file_pos; + +extern int ZEXPORT unzGetFilePos64 OF((unzFile file, unz64_file_pos* file_pos)); +extern int ZEXPORT unzGoToFilePos64 OF((unzFile file, const unz64_file_pos* file_pos)); + +extern uLong ZEXPORT unzGetOffset OF((unzFile file)); +extern ZPOS64_T ZEXPORT unzGetOffset64 OF((unzFile file)); +/* Get the current file offset */ + +extern int ZEXPORT unzSetOffset OF((unzFile file, uLong pos)); +extern int ZEXPORT unzSetOffset64 OF((unzFile file, ZPOS64_T pos)); +/* Set the current file offset */ + +extern z_off_t ZEXPORT unztell OF((unzFile file)); +extern ZPOS64_T ZEXPORT unztell64 OF((unzFile file)); +/* return current position in uncompressed data */ + +extern int ZEXPORT unzeof OF((unzFile file)); +/* return 1 if the end of file was reached, 0 elsewhere */ + +/***************************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* _UNZ_H */ diff --git a/SSZipArchive/minizip/zip.c b/SSZipArchive/minizip/zip.c new file mode 100755 index 0000000..3a3b16b --- /dev/null +++ b/SSZipArchive/minizip/zip.c @@ -0,0 +1,1910 @@ +/* zip.c -- IO on .zip files using zlib + Version 1.1, February 14h, 2010 + part of the MiniZip project + + Copyright (C) 1998-2010 Gilles Vollant + http://www.winimage.com/zLibDll/minizip.html + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson + http://result42.com + Modifications for AES, PKWARE disk spanning + Copyright (C) 2010-2014 Nathan Moinvaziri + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. + */ + +#include +#include +#include +#include +#include "zlib.h" +#include "zip.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H +extern int errno; +#else +# include +#endif + +#ifdef HAVE_AES +# define AES_METHOD (99) +# define AES_PWVERIFYSIZE (2) +# define AES_AUTHCODESIZE (10) +# define AES_MAXSALTLENGTH (16) +# define AES_VERSION (0x0001) +# define AES_ENCRYPTIONMODE (0x03) + +# include "aes.h" +# include "fileenc.h" +# include "prng.h" +# include "entropy.h" +#endif + +#ifndef NOCRYPT +# define INCLUDECRYPTINGCODE_IFCRYPTALLOWED +# include "crypt.h" +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +#define SIZEDATA_INDATABLOCK (4096 - (4 * 4)) + +#define DISKHEADERMAGIC (0x08074b50) +#define LOCALHEADERMAGIC (0x04034b50) +#define CENTRALHEADERMAGIC (0x02014b50) +#define ENDHEADERMAGIC (0x06054b50) +#define ZIP64ENDHEADERMAGIC (0x06064b50) +#define ZIP64ENDLOCHEADERMAGIC (0x07064b50) + +#define FLAG_LOCALHEADER_OFFSET (0x06) +#define CRC_LOCALHEADER_OFFSET (0x0e) + +#define SIZECENTRALHEADER (0x2e) /* 46 */ +#define SIZECENTRALHEADERLOCATOR (0x14) /* 20 */ +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) + +#ifndef BUFREADCOMMENT +# define BUFREADCOMMENT (0x400) +#endif +#ifndef VERSIONMADEBY +# define VERSIONMADEBY (0x0) /* platform dependent */ +#endif + +#ifndef Z_BUFSIZE +# define Z_BUFSIZE (64 * 1024) +#endif +#ifndef Z_MAXFILENAMEINZIP +# define Z_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) free(p); } +#endif + +/* NOT sure that this work on ALL platform */ +#define MAKEULONG64(a, b) ((ZPOS64_T)(((unsigned long)(a)) | ((ZPOS64_T)((unsigned long)(b))) << 32)) + +#ifndef DEF_MEM_LEVEL +# if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +# else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +# endif +#endif + +const char zip_copyright[] = " zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; + +typedef struct linkedlist_datablock_internal_s { + struct linkedlist_datablock_internal_s *next_datablock; + uLong avail_in_this_block; + uLong filled_in_this_block; + uLong unused; /* for future use and alignment */ + unsigned char data[SIZEDATA_INDATABLOCK]; +} linkedlist_datablock_internal; + +typedef struct linkedlist_data_s { + linkedlist_datablock_internal *first_block; + linkedlist_datablock_internal *last_block; +} linkedlist_data; + +typedef struct { + z_stream stream; /* zLib stream structure for inflate */ +#ifdef HAVE_BZIP2 + bz_stream bstream; /* bzLib stream structure for bziped */ +#endif +#ifdef HAVE_AES + fcrypt_ctx aes_ctx; + prng_ctx aes_rng[1]; +#endif + int stream_initialised; /* 1 is stream is initialized */ + uInt pos_in_buffered_data; /* last written byte in buffered_data */ + + ZPOS64_T pos_local_header; /* offset of the local header of the file currently writing */ + char *central_header; /* central header data for the current file */ + uLong size_centralextra; + uLong size_centralheader; /* size of the central header for cur file */ + uLong size_centralextrafree; /* Extra bytes allocated to the central header but that are not used */ + uLong size_comment; + uLong flag; /* flag of the file currently writing */ + + int method; /* compression method written to file.*/ + int compression_method; /* compression method to use */ + int raw; /* 1 for directly writing raw data */ + Byte buffered_data[Z_BUFSIZE]; /* buffer contain compressed data to be writ*/ + uLong dosDate; + uLong crc32; + int zip64; /* Add ZIP64 extended information in the extra field */ + uLong number_disk; /* number of current disk used for spanning ZIP */ + ZPOS64_T pos_zip64extrainfo; + ZPOS64_T total_compressed; + ZPOS64_T total_uncompressed; +#ifndef NOCRYPT + unsigned long keys[3]; /* keys defining the pseudo-random sequence */ + const unsigned long *pcrc_32_tab; + int crypt_header_size; +#endif +} curfile64_info; + +typedef struct { + zlib_filefunc64_32_def z_filefunc; + voidpf filestream; /* io structure of the zipfile */ + voidpf filestream_with_CD; /* io structure of the zipfile with the central dir */ + linkedlist_data central_dir; /* datablock with central dir in construction*/ + int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/ + int append; /* append mode */ + curfile64_info ci; /* info on the file currently writing */ + + ZPOS64_T begin_pos; /* position of the beginning of the zipfile */ + ZPOS64_T add_position_when_writting_offset; + ZPOS64_T number_entry; + ZPOS64_T disk_size; /* size of each disk */ + uLong number_disk; /* number of the current disk, used for spanning ZIP */ + uLong number_disk_with_CD; /* number the the disk with central dir, used for spanning ZIP */ +#ifndef NO_ADDFILEINEXISTINGZIP + char *globalcomment; +#endif +} zip64_internal; + +/* Allocate a new data block */ +local linkedlist_datablock_internal *allocate_new_datablock OF(()); +local linkedlist_datablock_internal *allocate_new_datablock() +{ + linkedlist_datablock_internal *ldi; + + ldi = (linkedlist_datablock_internal *)ALLOC(sizeof(linkedlist_datablock_internal)); + + if (ldi != NULL) { + ldi->next_datablock = NULL; + ldi->filled_in_this_block = 0; + ldi->avail_in_this_block = SIZEDATA_INDATABLOCK; + } + return ldi; +} + +/* Free data block in linked list */ +local void free_datablock OF((linkedlist_datablock_internal * ldi)); +local void free_datablock(linkedlist_datablock_internal *ldi) +{ + while (ldi != NULL) { + linkedlist_datablock_internal *ldinext = ldi->next_datablock; + TRYFREE(ldi); + ldi = ldinext; + } +} + +/* Initialize linked list */ +local void init_linkedlist OF((linkedlist_data * ll)); +local void init_linkedlist(linkedlist_data *ll) +{ + ll->first_block = ll->last_block = NULL; +} + +/* Free entire linked list and all data blocks */ +local void free_linkedlist OF((linkedlist_data * ll)); +local void free_linkedlist(linkedlist_data *ll) +{ + free_datablock(ll->first_block); + ll->first_block = ll->last_block = NULL; +} + +/* Add data to linked list data block */ +local int add_data_in_datablock OF((linkedlist_data * ll, const void *buf, uLong len)); +local int add_data_in_datablock(linkedlist_data *ll, const void *buf, uLong len) +{ + linkedlist_datablock_internal *ldi; + const unsigned char *from_copy; + + if (ll == NULL) + return ZIP_INTERNALERROR; + + if (ll->last_block == NULL) { + ll->first_block = ll->last_block = allocate_new_datablock(); + if (ll->first_block == NULL) + return ZIP_INTERNALERROR; + } + + ldi = ll->last_block; + from_copy = (unsigned char *)buf; + + while (len > 0) { + uInt copy_this; + uInt i; + unsigned char *to_copy; + + if (ldi->avail_in_this_block == 0) { + ldi->next_datablock = allocate_new_datablock(); + if (ldi->next_datablock == NULL) + return ZIP_INTERNALERROR; + ldi = ldi->next_datablock; + ll->last_block = ldi; + } + + if (ldi->avail_in_this_block < len) + copy_this = (uInt)ldi->avail_in_this_block; + else + copy_this = (uInt)len; + + to_copy = &(ldi->data[ldi->filled_in_this_block]); + + for (i = 0; i < copy_this; i++) + *(to_copy + i) = *(from_copy + i); + + ldi->filled_in_this_block += copy_this; + ldi->avail_in_this_block -= copy_this; + from_copy += copy_this; + len -= copy_this; + } + return ZIP_OK; +} + +local uLong zip64local_TmzDateToDosDate OF((const tm_zip * ptm)); +local uLong zip64local_TmzDateToDosDate(const tm_zip *ptm) +{ + uLong year; +#define zip64local_in_range(min, max, value) ((min) <= (value) && (value) <= (max)) + /* Years supported: + * [00, 79] (assumed to be between 2000 and 2079) + * [80, 207] (assumed to be between 1980 and 2107, typical output of old + software that does 'year-1900' to get a double digit year) + * [1980, 2107] + Due to the date format limitations, only years between 1980 and 2107 can be stored. + */ + if (!(zip64local_in_range(1980, 2107, ptm->tm_year) || zip64local_in_range(0, 207, ptm->tm_year)) || + !zip64local_in_range(0, 11, ptm->tm_mon) || + !zip64local_in_range(1, 31, ptm->tm_mday) || + !zip64local_in_range(0, 23, ptm->tm_hour) || + !zip64local_in_range(0, 59, ptm->tm_min) || + !zip64local_in_range(0, 59, ptm->tm_sec)) + return 0; +#undef zip64local_in_range + + year = (uLong)ptm->tm_year; + if (year >= 1980) /* range [1980, 2107] */ + year -= 1980; + else if (year >= 80) /* range [80, 99] */ + year -= 80; + else /* range [00, 79] */ + year += 20; + + return + (uLong)(((ptm->tm_mday) + (32 * (ptm->tm_mon + 1)) + (512 * year)) << 16) | + ((ptm->tm_sec / 2) + (32 * ptm->tm_min) + (2048 * (uLong)ptm->tm_hour)); +} + +/* Inputs a long in LSB order to the given file: nbByte == 1, 2 ,4 or 8 (byte, short or long, ZPOS64_T) */ +local int zip64local_putValue OF((const zlib_filefunc64_32_def * pzlib_filefunc_def, voidpf filestream, + ZPOS64_T x, int nbByte)); +local int zip64local_putValue(const zlib_filefunc64_32_def *pzlib_filefunc_def, voidpf filestream, + ZPOS64_T x, int nbByte) +{ + unsigned char buf[8]; + int n; + for (n = 0; n < nbByte; n++) { + buf[n] = (unsigned char)(x & 0xff); + x >>= 8; + } + if (x != 0) { + /* data overflow - hack for ZIP64 (X Roche) */ + for (n = 0; n < nbByte; n++) { + buf[n] = 0xff; + } + } + + if (ZWRITE64(*pzlib_filefunc_def, filestream, buf, nbByte) != (uLong)nbByte) + return ZIP_ERRNO; + + return ZIP_OK; +} + +local void zip64local_putValue_inmemory OF((void *dest, ZPOS64_T x, int nbByte)); +local void zip64local_putValue_inmemory(void *dest, ZPOS64_T x, int nbByte) +{ + unsigned char *buf = (unsigned char *)dest; + int n; + for (n = 0; n < nbByte; n++) { + buf[n] = (unsigned char)(x & 0xff); + x >>= 8; + } + + if (x != 0) { + /* data overflow - hack for ZIP64 */ + for (n = 0; n < nbByte; n++) { + buf[n] = 0xff; + } + } +} + +local int zip64local_getByte OF((const zlib_filefunc64_32_def * pzlib_filefunc_def, voidpf filestream, int *pi)); +local int zip64local_getByte(const zlib_filefunc64_32_def *pzlib_filefunc_def, voidpf filestream, int *pi) +{ + unsigned char c; + int err = (int)ZREAD64(*pzlib_filefunc_def, filestream, &c, 1); + if (err == 1) { + *pi = (int)c; + return ZIP_OK; + } + if (ZERROR64(*pzlib_filefunc_def, filestream)) + return ZIP_ERRNO; + return ZIP_EOF; +} + +local int zip64local_getShort OF((const zlib_filefunc64_32_def * pzlib_filefunc_def, voidpf filestream, uLong * pX)); +local int zip64local_getShort(const zlib_filefunc64_32_def *pzlib_filefunc_def, voidpf filestream, uLong *pX) +{ + uLong x; + int i = 0; + int err; + + err = zip64local_getByte(pzlib_filefunc_def, filestream, &i); + x = (uLong)i; + if (err == ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def, filestream, &i); + x += ((uLong)i) << 8; + + if (err == ZIP_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int zip64local_getLong OF((const zlib_filefunc64_32_def * pzlib_filefunc_def, voidpf filestream, uLong * pX)); +local int zip64local_getLong(const zlib_filefunc64_32_def *pzlib_filefunc_def, voidpf filestream, uLong *pX) +{ + uLong x; + int i = 0; + int err; + + err = zip64local_getByte(pzlib_filefunc_def, filestream, &i); + x = (uLong)i; + if (err == ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def, filestream, &i); + x += ((uLong)i) << 8; + if (err == ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def, filestream, &i); + x += ((uLong)i) << 16; + if (err == ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def, filestream, &i); + x += ((uLong)i) << 24; + + if (err == ZIP_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int zip64local_getLong64 OF((const zlib_filefunc64_32_def * pzlib_filefunc_def, voidpf filestream, ZPOS64_T * pX)); +local int zip64local_getLong64(const zlib_filefunc64_32_def *pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX) +{ + ZPOS64_T x; + int i = 0; + int err; + + err = zip64local_getByte(pzlib_filefunc_def, filestream, &i); + x = (ZPOS64_T)i; + if (err == ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def, filestream, &i); + x += ((ZPOS64_T)i) << 8; + if (err == ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def, filestream, &i); + x += ((ZPOS64_T)i) << 16; + if (err == ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def, filestream, &i); + x += ((ZPOS64_T)i) << 24; + if (err == ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def, filestream, &i); + x += ((ZPOS64_T)i) << 32; + if (err == ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def, filestream, &i); + x += ((ZPOS64_T)i) << 40; + if (err == ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def, filestream, &i); + x += ((ZPOS64_T)i) << 48; + if (err == ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def, filestream, &i); + x += ((ZPOS64_T)i) << 56; + + if (err == ZIP_OK) + *pX = x; + else + *pX = 0; + + return err; +} + +/* Gets the amount of bytes left to write to the current disk for spanning archives */ +local int zipGetDiskSizeAvailable OF((zipFile file, ZPOS64_T * size_available)); +local int zipGetDiskSizeAvailable(zipFile file, ZPOS64_T *size_available) +{ + zip64_internal *zi; + ZPOS64_T current_disk_size; + + zi = (zip64_internal *)file; + ZSEEK64(zi->z_filefunc, zi->filestream, 0, ZLIB_FILEFUNC_SEEK_END); + current_disk_size = ZTELL64(zi->z_filefunc, zi->filestream); + *size_available = zi->disk_size - current_disk_size; + return ZIP_OK; +} + +/* Goes to a specific disk number for spanning archives */ +local int zipGoToSpecificDisk OF((zipFile file, int number_disk, int open_existing)); +local int zipGoToSpecificDisk(zipFile file, int number_disk, int open_existing) +{ + zip64_internal *zi; + int err = ZIP_OK; + + zi = (zip64_internal *)file; + if (zi->disk_size == 0) + return err; + + if ((zi->filestream != NULL) && (zi->filestream != zi->filestream_with_CD)) + ZCLOSE64(zi->z_filefunc, zi->filestream); + + zi->filestream = ZOPENDISK64(zi->z_filefunc, zi->filestream_with_CD, number_disk, (open_existing == 1) ? + (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING) : + (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE)); + + if (zi->filestream == NULL) + err = ZIP_ERRNO; + + return err; +} + +/* Goes to the first disk in a spanned archive */ +local int zipGoToFirstDisk OF((zipFile file)); +local int zipGoToFirstDisk(zipFile file) +{ + zip64_internal *zi; + int number_disk_next; + int err = ZIP_OK; + + zi = (zip64_internal *)file; + + if (zi->disk_size == 0) + return err; + number_disk_next = 0; + if (zi->number_disk_with_CD > 0) + number_disk_next = (int)zi->number_disk_with_CD - 1; + err = zipGoToSpecificDisk(file, number_disk_next, (zi->append == APPEND_STATUS_ADDINZIP)); + if ((err == ZIP_ERRNO) && (zi->append == APPEND_STATUS_ADDINZIP)) + err = zipGoToSpecificDisk(file, number_disk_next, 0); + if (err == ZIP_OK) + zi->number_disk = number_disk_next; + ZSEEK64(zi->z_filefunc, zi->filestream, 0, ZLIB_FILEFUNC_SEEK_END); + return err; +} + +/* Goes to the next disk in a spanned archive */ +local int zipGoToNextDisk OF((zipFile file)); +local int zipGoToNextDisk(zipFile file) +{ + zip64_internal *zi; + ZPOS64_T size_available_in_disk; + int err = ZIP_OK; + int number_disk_next; + + zi = (zip64_internal *)file; + + if (zi->disk_size == 0) + return err; + + number_disk_next = (int)zi->number_disk + 1; + + do { + err = zipGoToSpecificDisk(file, number_disk_next, (zi->append == APPEND_STATUS_ADDINZIP)); + if ((err == ZIP_ERRNO) && (zi->append == APPEND_STATUS_ADDINZIP)) + err = zipGoToSpecificDisk(file, number_disk_next, 0); + if (err != ZIP_OK) + break; + err = zipGetDiskSizeAvailable(file, &size_available_in_disk); + if (err != ZIP_OK) + break; + zi->number_disk = number_disk_next; + zi->number_disk_with_CD = zi->number_disk + 1; + + number_disk_next += 1; + } while (size_available_in_disk <= 0); + + return err; +} + +/* Locate the Central directory of a zipfile (at the end, just before the global comment) */ +local ZPOS64_T zip64local_SearchCentralDir OF((const zlib_filefunc64_32_def * pzlib_filefunc_def, voidpf filestream)); +local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def *pzlib_filefunc_def, voidpf filestream) +{ + unsigned char *buf; + ZPOS64_T file_size; + ZPOS64_T back_read = 4; + ZPOS64_T max_back = 0xffff; /* maximum size of global comment */ + ZPOS64_T pos_found = 0; + uLong read_size; + ZPOS64_T read_pos; + int i; + + buf = (unsigned char *)ALLOC(BUFREADCOMMENT + 4); + if (buf == NULL) + return 0; + + if (ZSEEK64(*pzlib_filefunc_def, filestream, 0, ZLIB_FILEFUNC_SEEK_END) != 0) { + TRYFREE(buf); + return 0; + } + + file_size = ZTELL64(*pzlib_filefunc_def, filestream); + + if (max_back > file_size) + max_back = file_size; + + while (back_read < max_back) { + if (back_read + BUFREADCOMMENT > max_back) + back_read = max_back; + else + back_read += BUFREADCOMMENT; + + read_pos = file_size - back_read; + read_size = ((BUFREADCOMMENT + 4) < (file_size - read_pos)) ? + (BUFREADCOMMENT + 4) : (uLong)(file_size - read_pos); + + if (ZSEEK64(*pzlib_filefunc_def, filestream, read_pos, ZLIB_FILEFUNC_SEEK_SET) != 0) + break; + if (ZREAD64(*pzlib_filefunc_def, filestream, buf, read_size) != read_size) + break; + + for (i = (int)read_size - 3; (i--) > 0; ) + if ((*(buf + i)) == (ENDHEADERMAGIC & 0xff) && + (*(buf + i + 1)) == (ENDHEADERMAGIC >> 8 & 0xff) && + (*(buf + i + 2)) == (ENDHEADERMAGIC >> 16 & 0xff) && + (*(buf + i + 3)) == (ENDHEADERMAGIC >> 24 & 0xff)) { + pos_found = read_pos + i; + break; + } + + if (pos_found != 0) + break; + } + TRYFREE(buf); + return pos_found; +} + +/* Locate the Central directory 64 of a zipfile (at the end, just before the global comment) */ +local ZPOS64_T zip64local_SearchCentralDir64 OF((const zlib_filefunc64_32_def * pzlib_filefunc_def, voidpf filestream, + const ZPOS64_T endcentraloffset)); +local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def *pzlib_filefunc_def, voidpf filestream, + const ZPOS64_T endcentraloffset) +{ + ZPOS64_T offset; + uLong uL; + + /* Zip64 end of central directory locator */ + if (ZSEEK64(*pzlib_filefunc_def, filestream, endcentraloffset - SIZECENTRALHEADERLOCATOR, ZLIB_FILEFUNC_SEEK_SET) != 0) + return 0; + + /* read locator signature */ + if (zip64local_getLong(pzlib_filefunc_def, filestream, &uL) != ZIP_OK) + return 0; + if (uL != ZIP64ENDLOCHEADERMAGIC) + return 0; + /* number of the disk with the start of the zip64 end of central directory */ + if (zip64local_getLong(pzlib_filefunc_def, filestream, &uL) != ZIP_OK) + return 0; + /* relative offset of the zip64 end of central directory record */ + if (zip64local_getLong64(pzlib_filefunc_def, filestream, &offset) != ZIP_OK) + return 0; + /* total number of disks */ + if (zip64local_getLong(pzlib_filefunc_def, filestream, &uL) != ZIP_OK) + return 0; + /* Goto end of central directory record */ + if (ZSEEK64(*pzlib_filefunc_def, filestream, offset, ZLIB_FILEFUNC_SEEK_SET) != 0) + return 0; + /* the signature */ + if (zip64local_getLong(pzlib_filefunc_def, filestream, &uL) != ZIP_OK) + return 0; + if (uL != ZIP64ENDHEADERMAGIC) + return 0; + + return offset; +} + +extern zipFile ZEXPORT zipOpen4(const void *pathname, int append, ZPOS64_T disk_size, zipcharpc *globalcomment, + zlib_filefunc64_32_def *pzlib_filefunc64_32_def) +{ + zip64_internal ziinit; + zip64_internal *zi; +#ifndef NO_ADDFILEINEXISTINGZIP + ZPOS64_T byte_before_the_zipfile; /* byte before the zipfile, (>0 for sfx)*/ + ZPOS64_T size_central_dir = 0; /* size of the central directory */ + ZPOS64_T offset_central_dir = 0; /* offset of start of central directory */ + ZPOS64_T number_entry_CD = 0; /* total number of entries in the central dir */ + ZPOS64_T number_entry; + ZPOS64_T central_pos; + ZPOS64_T size_central_dir_to_read; + uLong uL; + uLong size_comment = 0; + size_t buf_size = SIZEDATA_INDATABLOCK; + void *buf_read; +#endif + int err = ZIP_OK; + int mode; + + ziinit.z_filefunc.zseek32_file = NULL; + ziinit.z_filefunc.ztell32_file = NULL; + if (pzlib_filefunc64_32_def == NULL) + fill_fopen64_filefunc(&ziinit.z_filefunc.zfile_func64); + else + ziinit.z_filefunc = *pzlib_filefunc64_32_def; + + if (append == APPEND_STATUS_CREATE) + mode = (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE); + else + mode = (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING); + + ziinit.filestream = ZOPEN64(ziinit.z_filefunc, pathname, mode); + if (ziinit.filestream == NULL) + return NULL; + + if (append == APPEND_STATUS_CREATEAFTER) { + /* Don't support spanning ZIP with APPEND_STATUS_CREATEAFTER */ + if (disk_size > 0) + return NULL; + + ZSEEK64(ziinit.z_filefunc, ziinit.filestream, 0, SEEK_END); + } + + ziinit.filestream_with_CD = ziinit.filestream; + ziinit.append = append; + ziinit.number_disk = 0; + ziinit.number_disk_with_CD = 0; + ziinit.disk_size = disk_size; + ziinit.begin_pos = ZTELL64(ziinit.z_filefunc, ziinit.filestream); + ziinit.in_opened_file_inzip = 0; + ziinit.ci.stream_initialised = 0; + ziinit.number_entry = 0; + ziinit.add_position_when_writting_offset = 0; + init_linkedlist(&(ziinit.central_dir)); + + zi = (zip64_internal *)ALLOC(sizeof(zip64_internal)); + if (zi == NULL) { + ZCLOSE64(ziinit.z_filefunc, ziinit.filestream); + return NULL; + } + +#ifndef NO_ADDFILEINEXISTINGZIP + /* Add file in a zipfile */ + ziinit.globalcomment = NULL; + if (append == APPEND_STATUS_ADDINZIP) { + /* Read and Cache Central Directory Records */ + central_pos = zip64local_SearchCentralDir(&ziinit.z_filefunc, ziinit.filestream); + /* disable to allow appending to empty ZIP archive (must be standard zip, not zip64) + if (central_pos == 0) + err = ZIP_ERRNO; + */ + + if (err == ZIP_OK) { + /* read end of central directory info */ + if (ZSEEK64(ziinit.z_filefunc, ziinit.filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0) + err = ZIP_ERRNO; + + /* the signature, already checked */ + if (zip64local_getLong(&ziinit.z_filefunc, ziinit.filestream, &uL) != ZIP_OK) + err = ZIP_ERRNO; + /* number of this disk */ + if (zip64local_getShort(&ziinit.z_filefunc, ziinit.filestream, &ziinit.number_disk) != ZIP_OK) + err = ZIP_ERRNO; + /* number of the disk with the start of the central directory */ + if (zip64local_getShort(&ziinit.z_filefunc, ziinit.filestream, &ziinit.number_disk_with_CD) != ZIP_OK) + err = ZIP_ERRNO; + /* total number of entries in the central dir on this disk */ + number_entry = 0; + if (zip64local_getShort(&ziinit.z_filefunc, ziinit.filestream, &uL) != ZIP_OK) + err = ZIP_ERRNO; + else + number_entry = uL; + /* total number of entries in the central dir */ + number_entry_CD = 0; + if (zip64local_getShort(&ziinit.z_filefunc, ziinit.filestream, &uL) != ZIP_OK) + err = ZIP_ERRNO; + else + number_entry_CD = uL; + if (number_entry_CD != number_entry) + err = ZIP_BADZIPFILE; + /* size of the central directory */ + size_central_dir = 0; + if (zip64local_getLong(&ziinit.z_filefunc, ziinit.filestream, &uL) != ZIP_OK) + err = ZIP_ERRNO; + else + size_central_dir = uL; + /* offset of start of central directory with respect to the starting disk number */ + offset_central_dir = 0; + if (zip64local_getLong(&ziinit.z_filefunc, ziinit.filestream, &uL) != ZIP_OK) + err = ZIP_ERRNO; + else + offset_central_dir = uL; + /* zipfile global comment length */ + if (zip64local_getShort(&ziinit.z_filefunc, ziinit.filestream, &size_comment) != ZIP_OK) + err = ZIP_ERRNO; + + if ((err == ZIP_OK) && ((number_entry_CD == 0xffff) || (offset_central_dir == 0xffffffff))) { + /* Format should be Zip64, as the central directory or file size is too large */ + central_pos = zip64local_SearchCentralDir64(&ziinit.z_filefunc, ziinit.filestream, central_pos); + + if (central_pos) { + ZPOS64_T sizeEndOfCentralDirectory; + + if (ZSEEK64(ziinit.z_filefunc, ziinit.filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0) + err = ZIP_ERRNO; + + /* the signature, already checked */ + if (zip64local_getLong(&ziinit.z_filefunc, ziinit.filestream, &uL) != ZIP_OK) + err = ZIP_ERRNO; + /* size of zip64 end of central directory record */ + if (zip64local_getLong64(&ziinit.z_filefunc, ziinit.filestream, &sizeEndOfCentralDirectory) != ZIP_OK) + err = ZIP_ERRNO; + /* version made by */ + if (zip64local_getShort(&ziinit.z_filefunc, ziinit.filestream, &uL) != ZIP_OK) + err = ZIP_ERRNO; + /* version needed to extract */ + if (zip64local_getShort(&ziinit.z_filefunc, ziinit.filestream, &uL) != ZIP_OK) + err = ZIP_ERRNO; + /* number of this disk */ + if (zip64local_getLong(&ziinit.z_filefunc, ziinit.filestream, &ziinit.number_disk) != ZIP_OK) + err = ZIP_ERRNO; + /* number of the disk with the start of the central directory */ + if (zip64local_getLong(&ziinit.z_filefunc, ziinit.filestream, &ziinit.number_disk_with_CD) != ZIP_OK) + err = ZIP_ERRNO; + /* total number of entries in the central directory on this disk */ + if (zip64local_getLong64(&ziinit.z_filefunc, ziinit.filestream, &number_entry) != ZIP_OK) + err = ZIP_ERRNO; + /* total number of entries in the central directory */ + if (zip64local_getLong64(&ziinit.z_filefunc, ziinit.filestream, &number_entry_CD) != ZIP_OK) + err = ZIP_ERRNO; + if (number_entry_CD != number_entry) + err = ZIP_BADZIPFILE; + /* size of the central directory */ + if (zip64local_getLong64(&ziinit.z_filefunc, ziinit.filestream, &size_central_dir) != ZIP_OK) + err = ZIP_ERRNO; + /* offset of start of central directory with respect to the starting disk number */ + if (zip64local_getLong64(&ziinit.z_filefunc, ziinit.filestream, &offset_central_dir) != ZIP_OK) + err = ZIP_ERRNO; + } else + err = ZIP_BADZIPFILE; + } + } + + if ((err == ZIP_OK) && (central_pos < offset_central_dir + size_central_dir)) + err = ZIP_BADZIPFILE; + + if (err != ZIP_OK) { + ZCLOSE64(ziinit.z_filefunc, ziinit.filestream); + TRYFREE(zi); + return NULL; + } + + if (size_comment > 0) { + ziinit.globalcomment = (char *)ALLOC(size_comment + 1); + if (ziinit.globalcomment) { + size_comment = ZREAD64(ziinit.z_filefunc, ziinit.filestream, ziinit.globalcomment, size_comment); + ziinit.globalcomment[size_comment] = 0; + } + } + + byte_before_the_zipfile = central_pos - (offset_central_dir + size_central_dir); + ziinit.add_position_when_writting_offset = byte_before_the_zipfile; + + /* Store central directory in memory */ + size_central_dir_to_read = size_central_dir; + buf_size = SIZEDATA_INDATABLOCK; + buf_read = (void *)ALLOC(buf_size); + + if (ZSEEK64(ziinit.z_filefunc, ziinit.filestream, + offset_central_dir + byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0) + err = ZIP_ERRNO; + + while ((size_central_dir_to_read > 0) && (err == ZIP_OK)) { + ZPOS64_T read_this = SIZEDATA_INDATABLOCK; + if (read_this > size_central_dir_to_read) + read_this = size_central_dir_to_read; + + if (ZREAD64(ziinit.z_filefunc, ziinit.filestream, buf_read, (uLong)read_this) != read_this) + err = ZIP_ERRNO; + + if (err == ZIP_OK) + err = add_data_in_datablock(&ziinit.central_dir, buf_read, (uLong)read_this); + + size_central_dir_to_read -= read_this; + } + TRYFREE(buf_read); + + ziinit.begin_pos = byte_before_the_zipfile; + ziinit.number_entry = number_entry_CD; + + if (ZSEEK64(ziinit.z_filefunc, ziinit.filestream, + offset_central_dir + byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0) + err = ZIP_ERRNO; + } + + if (globalcomment) + *globalcomment = ziinit.globalcomment; +#endif + + if (err != ZIP_OK) { +#ifndef NO_ADDFILEINEXISTINGZIP + TRYFREE(ziinit.globalcomment); +#endif + TRYFREE(zi); + return NULL; + } + + *zi = ziinit; + zipGoToFirstDisk((zipFile)zi); + return (zipFile)zi; +} + +extern zipFile ZEXPORT zipOpen2(const char *pathname, int append, zipcharpc *globalcomment, + zlib_filefunc_def *pzlib_filefunc32_def) +{ + if (pzlib_filefunc32_def != NULL) { + zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; + fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill, pzlib_filefunc32_def); + return zipOpen4(pathname, append, 0, globalcomment, &zlib_filefunc64_32_def_fill); + } + return zipOpen4(pathname, append, 0, globalcomment, NULL); +} + +extern zipFile ZEXPORT zipOpen2_64(const void *pathname, int append, zipcharpc *globalcomment, + zlib_filefunc64_def *pzlib_filefunc_def) +{ + if (pzlib_filefunc_def != NULL) { + zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; + zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def; + zlib_filefunc64_32_def_fill.ztell32_file = NULL; + zlib_filefunc64_32_def_fill.zseek32_file = NULL; + return zipOpen4(pathname, append, 0, globalcomment, &zlib_filefunc64_32_def_fill); + } + return zipOpen4(pathname, append, 0, globalcomment, NULL); +} + +extern zipFile ZEXPORT zipOpen3(const char *pathname, int append, ZPOS64_T disk_size, zipcharpc *globalcomment, + zlib_filefunc_def *pzlib_filefunc32_def) +{ + if (pzlib_filefunc32_def != NULL) { + zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; + fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill, pzlib_filefunc32_def); + return zipOpen4(pathname, append, disk_size, globalcomment, &zlib_filefunc64_32_def_fill); + } + return zipOpen4(pathname, append, disk_size, globalcomment, NULL); +} + +extern zipFile ZEXPORT zipOpen3_64(const void *pathname, int append, ZPOS64_T disk_size, zipcharpc *globalcomment, + zlib_filefunc64_def *pzlib_filefunc_def) +{ + if (pzlib_filefunc_def != NULL) { + zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; + zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def; + zlib_filefunc64_32_def_fill.ztell32_file = NULL; + zlib_filefunc64_32_def_fill.zseek32_file = NULL; + return zipOpen4(pathname, append, disk_size, globalcomment, &zlib_filefunc64_32_def_fill); + } + return zipOpen4(pathname, append, disk_size, globalcomment, NULL); +} + +extern zipFile ZEXPORT zipOpen(const char *pathname, int append) +{ + return zipOpen3((const void *)pathname, append, 0, NULL, NULL); +} + +extern zipFile ZEXPORT zipOpen64(const void *pathname, int append) +{ + return zipOpen3(pathname, append, 0, NULL, NULL); +} + +extern int ZEXPORT zipOpenNewFileInZip4_64(zipFile file, const char *filename, const zip_fileinfo *zipfi, + const void *extrafield_local, uInt size_extrafield_local, const void *extrafield_global, + uInt size_extrafield_global, const char *comment, int method, int level, int raw, int windowBits, int memLevel, + int strategy, const char *password, uLong crcForCrypting, uLong versionMadeBy, uLong flagBase, int zip64) +{ + zip64_internal *zi; + uInt size_filename; + uInt size_comment = 0; + uInt i; + int err = ZIP_OK; + ZPOS64_T size_available; + ZPOS64_T size_needed; + +#ifdef NOCRYPT + (crcForCrypting); + if (password != NULL) + return ZIP_PARAMERROR; +#endif + + if (file == NULL) + return ZIP_PARAMERROR; + + if ((method != 0) && +#ifdef HAVE_BZIP2 + (method != Z_BZIP2ED) && +#endif + (method != Z_DEFLATED)) + return ZIP_PARAMERROR; + + zi = (zip64_internal *)file; + + if (zi->in_opened_file_inzip == 1) { + err = zipCloseFileInZip(file); + if (err != ZIP_OK) + return err; + } + + if (filename == NULL) + filename = "-"; + if (comment != NULL) + size_comment = (uInt)strlen(comment); + + size_filename = (uInt)strlen(filename); + + if (zipfi == NULL) + zi->ci.dosDate = 0; + else { + if (zipfi->dosDate != 0) + zi->ci.dosDate = zipfi->dosDate; + else + zi->ci.dosDate = zip64local_TmzDateToDosDate(&zipfi->tmz_date); + } + + zi->ci.method = method; + zi->ci.compression_method = method; + zi->ci.crc32 = 0; + zi->ci.stream_initialised = 0; + zi->ci.pos_in_buffered_data = 0; + zi->ci.raw = raw; + zi->ci.flag = flagBase; + if ((level == 8) || (level == 9)) + zi->ci.flag |= 2; + if (level == 2) + zi->ci.flag |= 4; + if (level == 1) + zi->ci.flag |= 6; + if (password != NULL) { + zi->ci.flag |= 1; +#ifdef HAVE_AES + zi->ci.method = AES_METHOD; +#endif + } + + if (zi->disk_size > 0) { + if ((zi->number_disk == 0) && (zi->number_entry == 0)) + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)DISKHEADERMAGIC, 4); + + /* Make sure enough space available on current disk for local header */ + zipGetDiskSizeAvailable((zipFile)zi, &size_available); + size_needed = 30 + size_filename + size_extrafield_local; + if (zi->ci.zip64) + size_needed += 20; +#ifdef HAVE_AES + if (zi->ci.method == AES_METHOD) + size_needed += 11; +#endif + if (size_available < size_needed) + zipGoToNextDisk((zipFile)zi); + } + + zi->ci.pos_local_header = ZTELL64(zi->z_filefunc, zi->filestream); + zi->ci.size_comment = size_comment; + zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + size_extrafield_global; + zi->ci.size_centralextra = size_extrafield_global; + zi->ci.size_centralextrafree = 32; /* Extra space reserved for ZIP64 extra info */ +#ifdef HAVE_AES + if (zi->ci.method == AES_METHOD) + zi->ci.size_centralextrafree += 11; /* Extra space reserved for AES extra info */ +#endif + zi->ci.central_header = (char *)ALLOC((uInt)zi->ci.size_centralheader + zi->ci.size_centralextrafree + size_comment); + zi->ci.number_disk = zi->number_disk; + + /* Write central directory header */ + zip64local_putValue_inmemory(zi->ci.central_header, (uLong)CENTRALHEADERMAGIC, 4); + zip64local_putValue_inmemory(zi->ci.central_header + 4, (uLong)versionMadeBy, 2); + zip64local_putValue_inmemory(zi->ci.central_header + 6, (uLong)20, 2); + zip64local_putValue_inmemory(zi->ci.central_header + 8, (uLong)zi->ci.flag, 2); + zip64local_putValue_inmemory(zi->ci.central_header + 10, (uLong)zi->ci.method, 2); + zip64local_putValue_inmemory(zi->ci.central_header + 12, (uLong)zi->ci.dosDate, 4); + zip64local_putValue_inmemory(zi->ci.central_header + 16, (uLong)0, 4); /*crc*/ + zip64local_putValue_inmemory(zi->ci.central_header + 20, (uLong)0, 4); /*compr size*/ + zip64local_putValue_inmemory(zi->ci.central_header + 24, (uLong)0, 4); /*uncompr size*/ + zip64local_putValue_inmemory(zi->ci.central_header + 28, (uLong)size_filename, 2); + zip64local_putValue_inmemory(zi->ci.central_header + 30, (uLong)size_extrafield_global, 2); + zip64local_putValue_inmemory(zi->ci.central_header + 32, (uLong)size_comment, 2); + zip64local_putValue_inmemory(zi->ci.central_header + 34, (uLong)zi->ci.number_disk, 2); /*disk nm start*/ + + if (zipfi == NULL) + zip64local_putValue_inmemory(zi->ci.central_header + 36, (uLong)0, 2); + else + zip64local_putValue_inmemory(zi->ci.central_header + 36, (uLong)zipfi->internal_fa, 2); + if (zipfi == NULL) + zip64local_putValue_inmemory(zi->ci.central_header + 38, (uLong)0, 4); + else + zip64local_putValue_inmemory(zi->ci.central_header + 38, (uLong)zipfi->external_fa, 4); + if (zi->ci.pos_local_header >= 0xffffffff) + zip64local_putValue_inmemory(zi->ci.central_header + 42, (uLong)0xffffffff, 4); + else + zip64local_putValue_inmemory(zi->ci.central_header + 42, + (uLong)zi->ci.pos_local_header - zi->add_position_when_writting_offset, 4); + + for (i = 0; i < size_filename; i++) + zi->ci.central_header[SIZECENTRALHEADER + i] = filename[i]; + for (i = 0; i < size_extrafield_global; i++) + zi->ci.central_header[SIZECENTRALHEADER + size_filename + i] = + ((const char *)extrafield_global)[i]; + /* Store comment at the end for later repositioning */ + for (i = 0; i < size_comment; i++) + zi->ci.central_header[zi->ci.size_centralheader + + zi->ci.size_centralextrafree + i] = comment[i]; + + if (zi->ci.central_header == NULL) + return ZIP_INTERNALERROR; + + zi->ci.zip64 = zip64; + zi->ci.total_compressed = 0; + zi->ci.total_uncompressed = 0; + zi->ci.pos_zip64extrainfo = 0; + + /* Write the local header */ + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)LOCALHEADERMAGIC, 4); + + if (err == ZIP_OK) { + if (zi->ci.zip64) + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)45, 2); /* version needed to extract */ + else + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)20, 2); /* version needed to extract */ + } + if (err == ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)zi->ci.flag, 2); + if (err == ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)zi->ci.method, 2); + if (err == ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)zi->ci.dosDate, 4); + + /* CRC & compressed size & uncompressed size will be filled in later and rewritten later */ + + if (err == ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)0, 4); /* crc 32, unknown */ + if (err == ZIP_OK) { + if (zi->ci.zip64) + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)0xFFFFFFFF, 4); /* compressed size, unknown */ + else + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)0, 4); /* compressed size, unknown */ + } + if (err == ZIP_OK) { + if (zi->ci.zip64) /* uncompressed size, unknown */ + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)0xFFFFFFFF, 4); + else /* uncompressed size, unknown */ + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)0, 4); + } + if (err == ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)size_filename, 2); + if (err == ZIP_OK) { + ZPOS64_T size_extrafield = size_extrafield_local; + if (zi->ci.zip64) + size_extrafield += 20; +#ifdef HAVE_AES + if (zi->ci.method == AES_METHOD) + size_extrafield += 11; +#endif + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)size_extrafield, 2); + } + if ((err == ZIP_OK) && (size_filename > 0)) { + if (ZWRITE64(zi->z_filefunc, zi->filestream, filename, size_filename) != size_filename) + err = ZIP_ERRNO; + } + if ((err == ZIP_OK) && (size_extrafield_local > 0)) { + if (ZWRITE64(zi->z_filefunc, zi->filestream, extrafield_local, size_extrafield_local) != size_extrafield_local) + err = ZIP_ERRNO; + } + + /* Write the Zip64 extended info */ + if ((err == ZIP_OK) && (zi->ci.zip64)) { + short headerid = 1; + short datasize = 16; + ZPOS64_T compressed_size = 0; + ZPOS64_T uncompressed_size = 0; + + /* Remember position of Zip64 extended info for the local file header. + (needed when we update size after done with file) */ + zi->ci.pos_zip64extrainfo = ZTELL64(zi->z_filefunc, zi->filestream); + + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)headerid, 2); + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)datasize, 2); + + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)uncompressed_size, 8); + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)compressed_size, 8); + } +#ifdef HAVE_AES + /* Write the AES extended info */ + if ((err == ZIP_OK) && (zi->ci.method == AES_METHOD)) { + int headerid = 0x9901; + short datasize = 7; + + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, headerid, 2); + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, datasize, 2); + + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, AES_VERSION, 2); + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, 'A', 1); + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, 'E', 1); + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, AES_ENCRYPTIONMODE, 1); + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->ci.compression_method, 2); + } +#endif + +#ifdef HAVE_BZIP2 + zi->ci.bstream.avail_in = (uInt)0; + zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.bstream.next_out = (char *)zi->ci.buffered_data; + zi->ci.bstream.total_in_hi32 = 0; + zi->ci.bstream.total_in_lo32 = 0; + zi->ci.bstream.total_out_hi32 = 0; + zi->ci.bstream.total_out_lo32 = 0; +#endif + + zi->ci.stream.avail_in = (uInt)0; + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.stream.next_out = zi->ci.buffered_data; + zi->ci.stream.total_in = 0; + zi->ci.stream.total_out = 0; + zi->ci.stream.data_type = Z_BINARY; + + if ((err == ZIP_OK) && (!zi->ci.raw)) { + if (method == Z_DEFLATED) { + zi->ci.stream.zalloc = (alloc_func)0; + zi->ci.stream.zfree = (free_func)0; + zi->ci.stream.opaque = (voidpf)zi; + + if (windowBits > 0) + windowBits = -windowBits; + + err = deflateInit2(&zi->ci.stream, level, Z_DEFLATED, windowBits, memLevel, strategy); + + if (err == Z_OK) + zi->ci.stream_initialised = Z_DEFLATED; + } else if (method == Z_BZIP2ED) { +#ifdef HAVE_BZIP2 + zi->ci.bstream.bzalloc = 0; + zi->ci.bstream.bzfree = 0; + zi->ci.bstream.opaque = (voidpf)0; + + err = BZ2_bzCompressInit(&zi->ci.bstream, level, 0, 35); + if (err == BZ_OK) + zi->ci.stream_initialised = Z_BZIP2ED; +#endif + } + } + +#ifndef NOCRYPT + zi->ci.crypt_header_size = 0; + if ((err == Z_OK) && ((zi->ci.flag & 1) != 0)) { +#ifdef HAVE_AES + if (zi->ci.method == AES_METHOD) { + unsigned char passverify[AES_PWVERIFYSIZE]; + unsigned char saltvalue[AES_MAXSALTLENGTH]; + uInt saltlength; + + if ((AES_ENCRYPTIONMODE < 1) || (AES_ENCRYPTIONMODE > 3)) + return Z_ERRNO; + + saltlength = SALT_LENGTH(AES_ENCRYPTIONMODE); + + prng_init(entropy_fun, zi->ci.aes_rng); + prng_rand(saltvalue, saltlength, zi->ci.aes_rng); + prng_end(zi->ci.aes_rng); + + fcrypt_init(AES_ENCRYPTIONMODE, (unsigned char *)password, (unsigned int)strlen(password), saltvalue, passverify, &zi->ci.aes_ctx); + + if (ZWRITE64(zi->z_filefunc, zi->filestream, saltvalue, saltlength) != saltlength) + err = ZIP_ERRNO; + if (ZWRITE64(zi->z_filefunc, zi->filestream, passverify, AES_PWVERIFYSIZE) != AES_PWVERIFYSIZE) + err = ZIP_ERRNO; + + zi->ci.crypt_header_size = saltlength + AES_PWVERIFYSIZE + AES_AUTHCODESIZE; + } else +#endif + { + unsigned char bufHead[RAND_HEAD_LEN]; + unsigned int sizeHead; + + 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); + zi->ci.crypt_header_size = sizeHead; + + if (ZWRITE64(zi->z_filefunc, zi->filestream, bufHead, sizeHead) != sizeHead) + err = ZIP_ERRNO; + } + } +#endif + + if (err == Z_OK) + zi->in_opened_file_inzip = 1; + return err; +} + +extern int ZEXPORT zipOpenNewFileInZip4(zipFile file, const char *filename, const zip_fileinfo *zipfi, + const void *extrafield_local, uInt size_extrafield_local, const void *extrafield_global, + uInt size_extrafield_global, const char *comment, int method, int level, int raw, int windowBits, + int memLevel, int strategy, const char *password, uLong crcForCrypting, uLong versionMadeBy, uLong flagBase) +{ + return zipOpenNewFileInZip4_64(file, filename, zipfi, extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, comment, method, level, raw, windowBits, memLevel, + strategy, password, crcForCrypting, versionMadeBy, flagBase, 0); +} + +extern int ZEXPORT zipOpenNewFileInZip3(zipFile file, const char *filename, const zip_fileinfo *zipfi, + const void *extrafield_local, uInt size_extrafield_local, const void *extrafield_global, + uInt size_extrafield_global, const char *comment, int method, int level, int raw, int windowBits, + int memLevel, int strategy, const char *password, uLong crcForCrypting) +{ + return zipOpenNewFileInZip4_64(file, filename, zipfi, extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, comment, method, level, raw, windowBits, memLevel, + strategy, password, crcForCrypting, VERSIONMADEBY, 0, 0); +} + +extern int ZEXPORT zipOpenNewFileInZip3_64(zipFile file, const char *filename, const zip_fileinfo *zipfi, + const void *extrafield_local, uInt size_extrafield_local, const void *extrafield_global, + uInt size_extrafield_global, const char *comment, int method, int level, int raw, int windowBits, + int memLevel, int strategy, const char *password, uLong crcForCrypting, int zip64) +{ + return zipOpenNewFileInZip4_64(file, filename, zipfi, extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, comment, method, level, raw, windowBits, memLevel, strategy, + password, crcForCrypting, VERSIONMADEBY, 0, zip64); +} + +extern int ZEXPORT zipOpenNewFileInZip2(zipFile file, const char *filename, const zip_fileinfo *zipfi, + const void *extrafield_local, uInt size_extrafield_local, const void *extrafield_global, + uInt size_extrafield_global, const char *comment, int method, int level, int raw) +{ + return zipOpenNewFileInZip4_64(file, filename, zipfi, extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, comment, method, level, raw, -MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, NULL, 0, VERSIONMADEBY, 0, 0); +} + +extern int ZEXPORT zipOpenNewFileInZip2_64(zipFile file, const char *filename, const zip_fileinfo *zipfi, + const void *extrafield_local, uInt size_extrafield_local, const void *extrafield_global, + uInt size_extrafield_global, const char *comment, int method, int level, int raw, int zip64) +{ + return zipOpenNewFileInZip4_64(file, filename, zipfi, extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, comment, method, level, raw, -MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, NULL, 0, VERSIONMADEBY, 0, zip64); +} + +extern int ZEXPORT zipOpenNewFileInZip64(zipFile file, const char *filename, const zip_fileinfo *zipfi, + const void *extrafield_local, uInt size_extrafield_local, const void *extrafield_global, + uInt size_extrafield_global, const char *comment, int method, int level, int zip64) +{ + return zipOpenNewFileInZip4_64(file, filename, zipfi, extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, comment, method, level, 0, -MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, NULL, 0, VERSIONMADEBY, 0, zip64); +} + +extern int ZEXPORT zipOpenNewFileInZip(zipFile file, const char *filename, const zip_fileinfo *zipfi, + const void *extrafield_local, uInt size_extrafield_local, const void *extrafield_global, + uInt size_extrafield_global, const char *comment, int method, int level) +{ + return zipOpenNewFileInZip4_64(file, filename, zipfi, extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, comment, method, level, 0, -MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, NULL, 0, VERSIONMADEBY, 0, 0); +} + +/* Flushes the write buffer to disk */ +local int zip64FlushWriteBuffer OF((zip64_internal * zi)); +local int zip64FlushWriteBuffer(zip64_internal *zi) +{ + int err = ZIP_OK; + uInt written = 0; + uInt total_written = 0; + uInt write = 0; + uInt max_write = 0; + ZPOS64_T size_available = 0; + + if ((zi->ci.flag & 1) != 0) { +#ifndef NOCRYPT +#ifdef HAVE_AES + if (zi->ci.method == AES_METHOD) { + fcrypt_encrypt(zi->ci.buffered_data, zi->ci.pos_in_buffered_data, &zi->ci.aes_ctx); + } else +#endif + { + uInt i; + int t; + for (i = 0; i < zi->ci.pos_in_buffered_data; i++) + zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab, zi->ci.buffered_data[i], t); + } +#endif + } + + write = zi->ci.pos_in_buffered_data; + + do { + max_write = write; + + if (zi->disk_size > 0) { + err = zipGetDiskSizeAvailable((zipFile)zi, &size_available); + if (err != ZIP_OK) + return err; + + if (size_available == 0) { + err = zipGoToNextDisk((zipFile)zi); + if (err != ZIP_OK) + return err; + } + + if (size_available < (ZPOS64_T)max_write) + max_write = (uInt)size_available; + } + + written = (unsigned int)ZWRITE64(zi->z_filefunc, zi->filestream, zi->ci.buffered_data + total_written, max_write); + + if (ZERROR64(zi->z_filefunc, zi->filestream)) { + err = ZIP_ERRNO; + break; + } + + total_written += written; + write -= written; + } while (write > 0); + + zi->ci.total_compressed += zi->ci.pos_in_buffered_data; + +#ifdef HAVE_BZIP2 + if (zi->ci.compression_method == Z_BZIP2ED) { + zi->ci.total_uncompressed += zi->ci.bstream.total_in_lo32; + zi->ci.bstream.total_in_lo32 = 0; + zi->ci.bstream.total_in_hi32 = 0; + } else +#endif + { + zi->ci.total_uncompressed += zi->ci.stream.total_in; + zi->ci.stream.total_in = 0; + } + + zi->ci.pos_in_buffered_data = 0; + + return err; +} + +extern int ZEXPORT zipWriteInFileInZip(zipFile file, const void *buf, unsigned int len) +{ + zip64_internal *zi; + int err = ZIP_OK; + + if (file == NULL) + return ZIP_PARAMERROR; + zi = (zip64_internal *)file; + + if (zi->in_opened_file_inzip == 0) + return ZIP_PARAMERROR; + + zi->ci.crc32 = crc32(zi->ci.crc32, buf, (uInt)len); + +#ifdef HAVE_BZIP2 + if ((zi->ci.compression_method == Z_BZIP2ED) && (!zi->ci.raw)) { + zi->ci.bstream.next_in = (void *)buf; + zi->ci.bstream.avail_in = len; + err = BZ_RUN_OK; + + while ((err == BZ_RUN_OK) && (zi->ci.bstream.avail_in > 0)) { + if (zi->ci.bstream.avail_out == 0) { + if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) + err = ZIP_ERRNO; + zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.bstream.next_out = (char *)zi->ci.buffered_data; + } else { + uLong uTotalOutBefore_lo = zi->ci.bstream.total_out_lo32; + uLong uTotalOutBefore_hi = zi->ci.bstream.total_out_hi32; + + err = BZ2_bzCompress(&zi->ci.bstream, BZ_RUN); + + zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore_lo); + } + } + + if (err == BZ_RUN_OK) + err = ZIP_OK; + } else +#endif + { + zi->ci.stream.next_in = (Bytef *)buf; + zi->ci.stream.avail_in = len; + + while ((err == ZIP_OK) && (zi->ci.stream.avail_in > 0)) { + if (zi->ci.stream.avail_out == 0) { + if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) + err = ZIP_ERRNO; + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.stream.next_out = zi->ci.buffered_data; + } + + if (err != ZIP_OK) + break; + + if ((zi->ci.compression_method == Z_DEFLATED) && (!zi->ci.raw)) { + uLong total_out_before = zi->ci.stream.total_out; + err = deflate(&zi->ci.stream, Z_NO_FLUSH); + zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - total_out_before); + } else { + uInt copy_this, i; + if (zi->ci.stream.avail_in < zi->ci.stream.avail_out) + copy_this = zi->ci.stream.avail_in; + else + copy_this = zi->ci.stream.avail_out; + + for (i = 0; i < copy_this; i++) + *(((char *)zi->ci.stream.next_out) + i) = + *(((const char *)zi->ci.stream.next_in) + i); + + zi->ci.stream.avail_in -= copy_this; + zi->ci.stream.avail_out -= copy_this; + zi->ci.stream.next_in += copy_this; + zi->ci.stream.next_out += copy_this; + zi->ci.stream.total_in += copy_this; + zi->ci.stream.total_out += copy_this; + zi->ci.pos_in_buffered_data += copy_this; + } + } + } + + return err; +} + +extern int ZEXPORT zipCloseFileInZipRaw(zipFile file, uLong uncompressed_size, uLong crc32) +{ + return zipCloseFileInZipRaw64(file, uncompressed_size, crc32); +} + +extern int ZEXPORT zipCloseFileInZipRaw64(zipFile file, ZPOS64_T uncompressed_size, uLong crc32) +{ + zip64_internal *zi; + ZPOS64_T compressed_size; + uLong invalidValue = 0xffffffff; + uLong i = 0; + short datasize = 0; + int err = ZIP_OK; + + if (file == NULL) + return ZIP_PARAMERROR; + zi = (zip64_internal *)file; + + if (zi->in_opened_file_inzip == 0) + return ZIP_PARAMERROR; + zi->ci.stream.avail_in = 0; + + if (!zi->ci.raw) { + if (zi->ci.compression_method == Z_DEFLATED) { + while (err == ZIP_OK) { + uLong total_out_before; + if (zi->ci.stream.avail_out == 0) { + if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) + err = ZIP_ERRNO; + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.stream.next_out = zi->ci.buffered_data; + } + total_out_before = zi->ci.stream.total_out; + err = deflate(&zi->ci.stream, Z_FINISH); + zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - total_out_before); + } + } else if (zi->ci.compression_method == Z_BZIP2ED) { +#ifdef HAVE_BZIP2 + err = BZ_FINISH_OK; + while (err == BZ_FINISH_OK) { + uLong total_out_before; + if (zi->ci.bstream.avail_out == 0) { + if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) + err = ZIP_ERRNO; + zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.bstream.next_out = (char *)zi->ci.buffered_data; + } + total_out_before = zi->ci.bstream.total_out_lo32; + err = BZ2_bzCompress(&zi->ci.bstream, BZ_FINISH); + if (err == BZ_STREAM_END) + err = Z_STREAM_END; + zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - total_out_before); + } + + if (err == BZ_FINISH_OK) + err = ZIP_OK; +#endif + } + } + + if (err == Z_STREAM_END) + err = ZIP_OK; /* this is normal */ + + if ((zi->ci.pos_in_buffered_data > 0) && (err == ZIP_OK)) { + if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) + err = ZIP_ERRNO; + } + +#ifdef HAVE_AES + if (zi->ci.method == AES_METHOD) { + unsigned char authcode[AES_AUTHCODESIZE]; + + fcrypt_end(authcode, &zi->ci.aes_ctx); + + if (ZWRITE64(zi->z_filefunc, zi->filestream, authcode, AES_AUTHCODESIZE) != AES_AUTHCODESIZE) + err = ZIP_ERRNO; + } +#endif + + if (!zi->ci.raw) { + if (zi->ci.compression_method == Z_DEFLATED) { + int tmp_err = deflateEnd(&zi->ci.stream); + if (err == ZIP_OK) + err = tmp_err; + zi->ci.stream_initialised = 0; + } +#ifdef HAVE_BZIP2 + else if (zi->ci.compression_method == Z_BZIP2ED) { + int tmperr = BZ2_bzCompressEnd(&zi->ci.bstream); + if (err == ZIP_OK) + err = tmperr; + zi->ci.stream_initialised = 0; + } +#endif + + crc32 = (uLong)zi->ci.crc32; + uncompressed_size = zi->ci.total_uncompressed; + } + + compressed_size = zi->ci.total_compressed; +#ifndef NOCRYPT + compressed_size += zi->ci.crypt_header_size; +#endif + + /* Update current item crc and sizes */ + if (compressed_size >= 0xffffffff || uncompressed_size >= 0xffffffff || zi->ci.pos_local_header >= 0xffffffff) { + zip64local_putValue_inmemory(zi->ci.central_header + 4, (uLong)45, 2); /* version made by */ + zip64local_putValue_inmemory(zi->ci.central_header + 6, (uLong)45, 2); /* version needed */ + } + zip64local_putValue_inmemory(zi->ci.central_header + 16, crc32, 4); /* crc */ + if (compressed_size >= 0xffffffff) + zip64local_putValue_inmemory(zi->ci.central_header + 20, invalidValue, 4); /* compr size */ + else + zip64local_putValue_inmemory(zi->ci.central_header + 20, compressed_size, 4); /* compr size */ + if (zi->ci.stream.data_type == Z_ASCII) + zip64local_putValue_inmemory(zi->ci.central_header + 36, (uLong)Z_ASCII, 2); /* internal file attrib */ + if (uncompressed_size >= 0xffffffff) + zip64local_putValue_inmemory(zi->ci.central_header + 24, invalidValue, 4); /* uncompr size */ + else + zip64local_putValue_inmemory(zi->ci.central_header + 24, uncompressed_size, 4); /* uncompr size */ + + /* Add ZIP64 extra info field for uncompressed size */ + if (uncompressed_size >= 0xffffffff) + datasize += 8; + /* Add ZIP64 extra info field for compressed size */ + if (compressed_size >= 0xffffffff) + datasize += 8; + /* Add ZIP64 extra info field for relative offset to local file header of current file */ + if (zi->ci.pos_local_header >= 0xffffffff) + datasize += 8; + + /* Add Extra Information Header for 'ZIP64 information' */ + if (datasize > 0) { + char *p = zi->ci.central_header + zi->ci.size_centralheader; + + if ((uLong)(datasize + 4) > zi->ci.size_centralextrafree) + return ZIP_BADZIPFILE; + + zip64local_putValue_inmemory(p, 0x0001, 2); + p += 2; + zip64local_putValue_inmemory(p, datasize, 2); + p += 2; + + if (uncompressed_size >= 0xffffffff) { + zip64local_putValue_inmemory(p, uncompressed_size, 8); + p += 8; + } + if (compressed_size >= 0xffffffff) { + zip64local_putValue_inmemory(p, compressed_size, 8); + p += 8; + } + if (zi->ci.pos_local_header >= 0xffffffff) { + zip64local_putValue_inmemory(p, zi->ci.pos_local_header, 8); + p += 8; + } + + zi->ci.size_centralextrafree -= datasize + 4; + zi->ci.size_centralheader += datasize + 4; + zi->ci.size_centralextra += datasize + 4; + + zip64local_putValue_inmemory(zi->ci.central_header + 30, (uLong)zi->ci.size_centralextra, 2); + } + +#ifdef HAVE_AES + /* Write the AES extended info */ + if (zi->ci.method == AES_METHOD) { + char *p = zi->ci.central_header + zi->ci.size_centralheader; + + datasize = 7; + + if ((uLong)(datasize + 4) > zi->ci.size_centralextrafree) + return ZIP_BADZIPFILE; + + zip64local_putValue_inmemory(p, 0x9901, 2); + p += 2; + zip64local_putValue_inmemory(p, datasize, 2); + p += 2; + zip64local_putValue_inmemory(p, AES_VERSION, 2); + p += 2; + zip64local_putValue_inmemory(p, 'A', 1); + p += 1; + zip64local_putValue_inmemory(p, 'E', 1); + p += 1; + zip64local_putValue_inmemory(p, AES_ENCRYPTIONMODE, 1); + p += 1; + zip64local_putValue_inmemory(p, zi->ci.compression_method, 2); + p += 2; + + zi->ci.size_centralextrafree -= datasize + 4; + zi->ci.size_centralheader += datasize + 4; + zi->ci.size_centralextra += datasize + 4; + + zip64local_putValue_inmemory(zi->ci.central_header + 30, (uLong)zi->ci.size_centralextra, 2); + } +#endif + /* Restore comment to correct position */ + for (i = 0; i < zi->ci.size_comment; i++) + zi->ci.central_header[zi->ci.size_centralheader + i] = + zi->ci.central_header[zi->ci.size_centralheader + zi->ci.size_centralextrafree + i]; + zi->ci.size_centralheader += zi->ci.size_comment; + + if (err == ZIP_OK) + err = add_data_in_datablock(&zi->central_dir, zi->ci.central_header, (uLong)zi->ci.size_centralheader); + + free(zi->ci.central_header); + + if (err == ZIP_OK) { + /* Update the LocalFileHeader with the new values. */ + ZPOS64_T cur_pos_inzip = ZTELL64(zi->z_filefunc, zi->filestream); + uLong cur_number_disk = zi->number_disk; + + /* Local file header is stored on previous disk, switch to make edits */ + if (zi->ci.number_disk != cur_number_disk) + err = zipGoToSpecificDisk(file, (int)zi->ci.number_disk, 1); + + if (ZSEEK64(zi->z_filefunc, zi->filestream, zi->ci.pos_local_header + 14, ZLIB_FILEFUNC_SEEK_SET) != 0) + err = ZIP_ERRNO; + if (err == ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, crc32, 4); /* crc 32, unknown */ + + if (uncompressed_size >= 0xffffffff || compressed_size >= 0xffffffff) { + if (zi->ci.pos_zip64extrainfo > 0) { + /* Update the size in the ZIP64 extended field. */ + if (ZSEEK64(zi->z_filefunc, zi->filestream, zi->ci.pos_zip64extrainfo + 4, ZLIB_FILEFUNC_SEEK_SET) != 0) + err = ZIP_ERRNO; + + if (err == ZIP_OK) /* compressed size, unknown */ + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, uncompressed_size, 8); + if (err == ZIP_OK) /* uncompressed size, unknown */ + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, compressed_size, 8); + } else + err = ZIP_BADZIPFILE; /* Caller passed zip64 = 0, so no room for zip64 info -> fatal */ + } else { + if (err == ZIP_OK) /* compressed size, unknown */ + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, compressed_size, 4); + if (err == ZIP_OK) /* uncompressed size, unknown */ + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, uncompressed_size, 4); + } + + /* Now switch back again to the disk we were on before */ + if (zi->ci.number_disk != cur_number_disk) + err = zipGoToSpecificDisk(file, (int)cur_number_disk, 1); + + if (ZSEEK64(zi->z_filefunc, zi->filestream, cur_pos_inzip, ZLIB_FILEFUNC_SEEK_SET) != 0) + err = ZIP_ERRNO; + } + + zi->number_entry++; + zi->in_opened_file_inzip = 0; + + return err; +} + +extern int ZEXPORT zipCloseFileInZip(zipFile file) +{ + return zipCloseFileInZipRaw(file, 0, 0); +} + +extern int ZEXPORT zipClose(zipFile file, const char *global_comment) +{ + zip64_internal *zi; + int err = 0; + uLong size_centraldir = 0; + uInt size_global_comment = 0; + ZPOS64_T centraldir_pos_inzip; + ZPOS64_T pos = 0; + uLong write = 0; + + if (file == NULL) + return ZIP_PARAMERROR; + + zi = (zip64_internal *)file; + + if (zi->in_opened_file_inzip == 1) + err = zipCloseFileInZip(file); + +#ifndef NO_ADDFILEINEXISTINGZIP + if (global_comment == NULL) + global_comment = zi->globalcomment; +#endif + + if (zi->filestream != zi->filestream_with_CD) { + if (ZCLOSE64(zi->z_filefunc, zi->filestream) != 0) + if (err == ZIP_OK) + err = ZIP_ERRNO; + if (zi->disk_size > 0) + zi->number_disk_with_CD = zi->number_disk + 1; + zi->filestream = zi->filestream_with_CD; + } + + centraldir_pos_inzip = ZTELL64(zi->z_filefunc, zi->filestream); + + if (err == ZIP_OK) { + linkedlist_datablock_internal *ldi = zi->central_dir.first_block; + while (ldi != NULL) { + if ((err == ZIP_OK) && (ldi->filled_in_this_block > 0)) { + write = ZWRITE64(zi->z_filefunc, zi->filestream, ldi->data, ldi->filled_in_this_block); + if (write != ldi->filled_in_this_block) + err = ZIP_ERRNO; + } + + size_centraldir += ldi->filled_in_this_block; + ldi = ldi->next_datablock; + } + } + + free_linkedlist(&(zi->central_dir)); + + pos = centraldir_pos_inzip - zi->add_position_when_writting_offset; + + /* Write the ZIP64 central directory header */ + if (pos >= 0xffffffff || zi->number_entry > 0xffff) { + ZPOS64_T zip64eocd_pos_inzip = ZTELL64(zi->z_filefunc, zi->filestream); + uLong zip64datasize = 44; + + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)ZIP64ENDHEADERMAGIC, 4); + + /* size of this 'zip64 end of central directory' */ + if (err == ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)zip64datasize, 8); + /* version made by */ + if (err == ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)45, 2); + /* version needed */ + if (err == ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)45, 2); + /* number of this disk */ + if (err == ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)zi->number_disk_with_CD, 4); + /* number of the disk with the start of the central directory */ + if (err == ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)zi->number_disk_with_CD, 4); + /* total number of entries in the central dir on this disk */ + if (err == ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8); + /* total number of entries in the central dir */ + if (err == ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8); + /* size of the central directory */ + if (err == ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)size_centraldir, 8); + + if (err == ZIP_OK) { + /* offset of start of central directory with respect to the starting disk number */ + ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writting_offset; + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)pos, 8); + } + if (err == ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)ZIP64ENDLOCHEADERMAGIC, 4); + + /* number of the disk with the start of the central directory */ + if (err == ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)zi->number_disk_with_CD, 4); + /*relative offset to the Zip64EndOfCentralDirectory */ + if (err == ZIP_OK) { + ZPOS64_T pos = zip64eocd_pos_inzip - zi->add_position_when_writting_offset; + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, pos, 8); + } + /* number of the disk with the start of the central directory */ + if (err == ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)zi->number_disk_with_CD + 1, 4); + } + + /* Write the central directory header */ + + /* signature */ + if (err == ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)ENDHEADERMAGIC, 4); + /* number of this disk */ + if (err == ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)zi->number_disk_with_CD, 2); + /* number of the disk with the start of the central directory */ + if (err == ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)zi->number_disk_with_CD, 2); + /* total number of entries in the central dir on this disk */ + if (err == ZIP_OK) { + if (zi->number_entry >= 0xffff) + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)0xffff, 2); /* use value in ZIP64 record */ + else + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)zi->number_entry, 2); + } + /* total number of entries in the central dir */ + if (err == ZIP_OK) { + if (zi->number_entry >= 0xffff) + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)0xffff, 2); /* use value in ZIP64 record */ + else + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)zi->number_entry, 2); + } + /* size of the central directory */ + if (err == ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)size_centraldir, 4); + /* offset of start of central directory with respect to the starting disk number */ + if (err == ZIP_OK) { + ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writting_offset; + if (pos >= 0xffffffff) + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)0xffffffff, 4); + else + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)pos, 4); + } + + /* Write global comment */ + + if (global_comment != NULL) + size_global_comment = (uInt)strlen(global_comment); + if (err == ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)size_global_comment, 2); + if (err == ZIP_OK && size_global_comment > 0) { + if (ZWRITE64(zi->z_filefunc, zi->filestream, global_comment, size_global_comment) != size_global_comment) + err = ZIP_ERRNO; + } + + if ((ZCLOSE64(zi->z_filefunc, zi->filestream) != 0) && (err == ZIP_OK)) + err = ZIP_ERRNO; + +#ifndef NO_ADDFILEINEXISTINGZIP + TRYFREE(zi->globalcomment); +#endif + TRYFREE(zi); + + return err; +} + diff --git a/SSZipArchive/minizip/zip.h b/SSZipArchive/minizip/zip.h new file mode 100755 index 0000000..10bbf26 --- /dev/null +++ b/SSZipArchive/minizip/zip.h @@ -0,0 +1,202 @@ +/* zip.h -- IO on .zip files using zlib + Version 1.1, February 14h, 2010 + part of the MiniZip project + + Copyright (C) 1998-2010 Gilles Vollant + http://www.winimage.com/zLibDll/minizip.html + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson + http://result42.com + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#ifndef _ZIP_H +#define _ZIP_H + +#define HAVE_AES + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +# include "zlib.h" +#endif + +#ifndef _ZLIBIOAPI_H +# include "ioapi.h" +#endif + +#ifdef HAVE_BZIP2 +# include "bzlib.h" +#endif + +#define Z_BZIP2ED 12 + +#if defined(STRICTZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagzipFile__ { int unused; } zipFile__; +typedef zipFile__ *zipFile; +#else +typedef voidp zipFile; +#endif + +#define ZIP_OK (0) +#define ZIP_EOF (0) +#define ZIP_ERRNO (Z_ERRNO) +#define ZIP_PARAMERROR (-102) +#define ZIP_BADZIPFILE (-103) +#define ZIP_INTERNALERROR (-104) + +#ifndef DEF_MEM_LEVEL +# if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +# else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +# endif +#endif +/* default memLevel */ + +/* tm_zip contain date/time info */ +typedef struct tm_zip_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_zip; + +typedef struct +{ + tm_zip tmz_date; /* date in understandable format */ + uLong dosDate; /* if dos_date == 0, tmu_date is used */ + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ +} zip_fileinfo; + +typedef const char* zipcharpc; + +#define APPEND_STATUS_CREATE (0) +#define APPEND_STATUS_CREATEAFTER (1) +#define APPEND_STATUS_ADDINZIP (2) + +/***************************************************************************/ +/* Writing a zip file */ + +extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append)); +extern zipFile ZEXPORT zipOpen64 OF((const void *pathname, int append)); +/* Create a zipfile. + + pathname should contain the full pathname (by example, on a Windows XP computer + "c:\\zlib\\zlib113.zip" or on an Unix computer "zlib/zlib113.zip". + + return NULL if zipfile cannot be opened + return zipFile handle if no error + + If the file pathname exist and append == APPEND_STATUS_CREATEAFTER, the zip + will be created at the end of the file. (useful if the file contain a self extractor code) + If the file pathname exist and append == APPEND_STATUS_ADDINZIP, we will add files in existing + zip (be sure you don't add file that doesn't exist) + + NOTE: There is no delete function into a zipfile. If you want delete file into a zipfile, + you must open a zipfile, and create another. Of course, you can use RAW reading and writing to copy + the file you did not want delete. */ + +extern zipFile ZEXPORT zipOpen2 OF((const char *pathname, int append, zipcharpc* globalcomment, + zlib_filefunc_def* pzlib_filefunc_def)); + +extern zipFile ZEXPORT zipOpen2_64 OF((const void *pathname, int append, zipcharpc* globalcomment, + zlib_filefunc64_def* pzlib_filefunc_def)); + +extern zipFile ZEXPORT zipOpen3 OF((const char *pathname, int append, ZPOS64_T disk_size, + zipcharpc* globalcomment, zlib_filefunc_def* pzlib_filefunc_def)); +/* Same as zipOpen2 but allows specification of spanned zip size */ + +extern zipFile ZEXPORT zipOpen3_64 OF((const void *pathname, int append, ZPOS64_T disk_size, + zipcharpc* globalcomment, zlib_filefunc64_def* pzlib_filefunc_def)); + +extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global, + uInt size_extrafield_global, const char* comment, int method, int level)); +/* Open a file in the ZIP for writing. + + filename : the filename in zip (if NULL, '-' without quote will be used + *zipfi contain supplemental information + extrafield_local buffer to store the local header extra field data, can be NULL + size_extrafield_local size of extrafield_local buffer + extrafield_global buffer to store the global header extra field data, can be NULL + size_extrafield_global size of extrafield_local buffer + comment buffer for comment string + method contain the compression method (0 for store, Z_DEFLATED for deflate) + level contain the level of compression (can be Z_DEFAULT_COMPRESSION) + zip64 is set to 1 if a zip64 extended information block should be added to the local file header. + this MUST be '1' if the uncompressed size is >= 0xffffffff. */ + +extern int ZEXPORT zipOpenNewFileInZip64 OF((zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global, + uInt size_extrafield_global, const char* comment, int method, int level, int zip64)); +/* Same as zipOpenNewFileInZip with zip64 support */ + +extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global, + uInt size_extrafield_global, const char* comment, int method, int level, int raw)); +/* Same as zipOpenNewFileInZip, except if raw=1, we write raw file */ + +extern int ZEXPORT zipOpenNewFileInZip2_64 OF((zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global, + uInt size_extrafield_global, const char* comment, int method, int level, int raw, int zip64)); +/* Same as zipOpenNewFileInZip3 with zip64 support */ + +extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global, + uInt size_extrafield_global, const char* comment, int method, int level, int raw, int windowBits, int memLevel, + int strategy, const char* password, uLong crcForCrypting)); +/* Same as zipOpenNewFileInZip2, except + windowBits, memLevel, strategy : see parameter strategy in deflateInit2 + password : crypting password (NULL for no crypting) + crcForCrypting : crc of file to compress (needed for crypting) */ + +extern int ZEXPORT zipOpenNewFileInZip3_64 OF((zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global, + uInt size_extrafield_global, const char* comment, int method, int level, int raw, int windowBits, int memLevel, + int strategy, const char* password, uLong crcForCrypting, int zip64)); +/* Same as zipOpenNewFileInZip3 with zip64 support */ + +extern int ZEXPORT zipOpenNewFileInZip4 OF((zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global, + uInt size_extrafield_global, const char* comment, int method, int level, int raw, int windowBits, int memLevel, + int strategy, const char* password, uLong crcForCrypting, uLong versionMadeBy, uLong flagBase)); +/* Same as zipOpenNewFileInZip3 except versionMadeBy & flag fields */ + +extern int ZEXPORT zipOpenNewFileInZip4_64 OF((zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global, + uInt size_extrafield_global, const char* comment, int method, int level, int raw, int windowBits, int memLevel, + int strategy, const char* password, uLong crcForCrypting, uLong versionMadeBy, uLong flagBase, int zip64)); +/* Same as zipOpenNewFileInZip4 with zip64 support */ + +extern int ZEXPORT zipWriteInFileInZip OF((zipFile file, const void* buf, unsigned len)); +/* Write data in the zipfile */ + +extern int ZEXPORT zipCloseFileInZip OF((zipFile file)); +/* Close the current file in the zipfile */ + +extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file, uLong uncompressed_size, uLong crc32)); +extern int ZEXPORT zipCloseFileInZipRaw64 OF((zipFile file, ZPOS64_T uncompressed_size, uLong crc32)); +/* Close the current file in the zipfile, for file opened with parameter raw=1 in zipOpenNewFileInZip2 + uncompressed_size and crc32 are value for the uncompressed size */ + +extern int ZEXPORT zipClose OF((zipFile file, const char* global_comment)); +/* Close the zipfile */ + +/***************************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* _ZIP_H */ diff --git a/package.json b/package.json index 3ae9f68..b0dc641 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,6 @@ "code-push": "^1.1.1-beta" }, "devDependencies": { - "react-native": "0.14.2" + "react-native": "0.15.0" } } \ No newline at end of file