@appzung/react-native-code-push 8.3.2 → 10.0.0-rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (191) hide show
  1. package/CodePush.js +22 -19
  2. package/CodePush.podspec +3 -3
  3. package/LICENSE.md +1 -1
  4. package/README.md +159 -296
  5. package/android/app/.gradle/config.properties +2 -0
  6. package/android/app/build.gradle +2 -0
  7. package/android/app/local.properties +8 -0
  8. package/android/app/src/main/AndroidManifest.xml +1 -2
  9. package/android/app/src/main/java/com/microsoft/codepush/react/CodePush.java +27 -21
  10. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushBuilder.java +5 -5
  11. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushConstants.java +1 -1
  12. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushDialog.java +1 -1
  13. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushInstallMode.java +2 -2
  14. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushInvalidPublicKeyException.java +2 -2
  15. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushInvalidUpdateException.java +1 -1
  16. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushMalformedDataException.java +2 -2
  17. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushNativeModule.java +5 -5
  18. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushNotInitializedException.java +2 -2
  19. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushTelemetryManager.java +14 -14
  20. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushUnknownException.java +2 -2
  21. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushUpdateManager.java +1 -1
  22. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushUpdateState.java +2 -2
  23. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushUpdateUtils.java +16 -9
  24. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushUtils.java +1 -1
  25. package/android/app/src/main/java/com/microsoft/codepush/react/DownloadProgress.java +1 -1
  26. package/android/app/src/main/java/com/microsoft/codepush/react/DownloadProgressCallback.java +1 -1
  27. package/android/app/src/main/java/com/microsoft/codepush/react/FileUtils.java +1 -1
  28. package/android/app/src/main/java/com/microsoft/codepush/react/ReactInstanceHolder.java +1 -1
  29. package/android/app/src/main/java/com/microsoft/codepush/react/SettingsManager.java +1 -1
  30. package/android/app/src/main/java/com/microsoft/codepush/react/TLSSocketFactory.java +1 -1
  31. package/android/build.gradle +3 -0
  32. package/android/codepush.gradle +3 -3
  33. package/docs/advanced-usage.md +56 -0
  34. package/docs/api-android.md +12 -75
  35. package/docs/api-ios.md +5 -17
  36. package/docs/api-js.md +18 -55
  37. package/docs/setup-android.md +15 -397
  38. package/docs/setup-ios.md +24 -198
  39. package/docs/setup-windows.md +7 -74
  40. package/ios/CodePush/CodePush.h +4 -4
  41. package/ios/CodePush/CodePush.m +10 -9
  42. package/ios/CodePush/CodePushConfig.m +14 -11
  43. package/ios/CodePush/CodePushPackage.m +60 -60
  44. package/ios/CodePush/CodePushTelemetryManager.m +13 -13
  45. package/ios/CodePush.xcodeproj/project.pbxproj +24 -470
  46. package/ios/PrivacyInfo.xcprivacy +31 -0
  47. package/package.json +27 -24
  48. package/react-native.config.js +1 -1
  49. package/scripts/generateBundledResourcesHash.js +1 -1
  50. package/scripts/getFilesInFolder.js +1 -1
  51. package/scripts/recordFilesBeforeBundleCommand.js +1 -1
  52. package/typings/react-native-code-push.d.ts +22 -22
  53. package/windows/CodePush/CodePushConfig.cpp +3 -3
  54. package/windows/CodePush/CodePushConfig.h +3 -3
  55. package/windows/CodePush/CodePushNativeModule.cpp +27 -27
  56. package/windows/CodePush/CodePushNativeModule.h +4 -4
  57. package/windows/CodePush/CodePushTelemetryManager.cpp +12 -12
  58. package/windows/CodePush/CodePushTelemetryManager.h +1 -1
  59. package/.azurepipelines/build-rn-code-push-1es.yml +0 -104
  60. package/.azurepipelines/test-rn-code-push.yml +0 -94
  61. package/.config/CredScanSuppressions.json +0 -14
  62. package/SECURITY.md +0 -41
  63. package/docs/multi-deployment-testing-android.md +0 -148
  64. package/docs/multi-deployment-testing-ios.md +0 -59
  65. package/ios/CodePush/Base64/Base64/MF_Base64Additions.h +0 -34
  66. package/ios/CodePush/Base64/Base64/MF_Base64Additions.m +0 -252
  67. package/ios/CodePush/Base64/README.md +0 -47
  68. package/ios/CodePush/JWT/Core/Algorithms/Base/JWTAlgorithm.h +0 -69
  69. package/ios/CodePush/JWT/Core/Algorithms/Base/JWTAlgorithmFactory.h +0 -16
  70. package/ios/CodePush/JWT/Core/Algorithms/Base/JWTAlgorithmFactory.m +0 -51
  71. package/ios/CodePush/JWT/Core/Algorithms/Base/JWTAlgorithmNone.h +0 -15
  72. package/ios/CodePush/JWT/Core/Algorithms/Base/JWTAlgorithmNone.m +0 -55
  73. package/ios/CodePush/JWT/Core/Algorithms/ESFamily/JWTAlgorithmESBase.h +0 -24
  74. package/ios/CodePush/JWT/Core/Algorithms/ESFamily/JWTAlgorithmESBase.m +0 -41
  75. package/ios/CodePush/JWT/Core/Algorithms/HSFamily/JWTAlgorithmHSBase.h +0 -28
  76. package/ios/CodePush/JWT/Core/Algorithms/HSFamily/JWTAlgorithmHSBase.m +0 -205
  77. package/ios/CodePush/JWT/Core/Algorithms/Holders/JWTAlgorithmDataHolder.h +0 -103
  78. package/ios/CodePush/JWT/Core/Algorithms/Holders/JWTAlgorithmDataHolder.m +0 -322
  79. package/ios/CodePush/JWT/Core/Algorithms/Holders/JWTAlgorithmDataHolderChain.h +0 -37
  80. package/ios/CodePush/JWT/Core/Algorithms/Holders/JWTAlgorithmDataHolderChain.m +0 -145
  81. package/ios/CodePush/JWT/Core/Algorithms/RSFamily/JWTAlgorithmRSBase.h +0 -35
  82. package/ios/CodePush/JWT/Core/Algorithms/RSFamily/JWTAlgorithmRSBase.m +0 -551
  83. package/ios/CodePush/JWT/Core/Algorithms/RSFamily/JWTRSAlgorithm.h +0 -23
  84. package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoKey.h +0 -43
  85. package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoKey.m +0 -230
  86. package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoKeyExtractor.h +0 -31
  87. package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoKeyExtractor.m +0 -113
  88. package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoSecurity.h +0 -38
  89. package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoSecurity.m +0 -500
  90. package/ios/CodePush/JWT/Core/ClaimSet/JWTClaim.h +0 -18
  91. package/ios/CodePush/JWT/Core/ClaimSet/JWTClaim.m +0 -214
  92. package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSet.h +0 -23
  93. package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSet.m +0 -29
  94. package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSetSerializer.h +0 -19
  95. package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSetSerializer.m +0 -68
  96. package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSetVerifier.h +0 -18
  97. package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSetVerifier.m +0 -72
  98. package/ios/CodePush/JWT/Core/Coding/JWTCoding+ResultTypes.h +0 -67
  99. package/ios/CodePush/JWT/Core/Coding/JWTCoding+ResultTypes.m +0 -111
  100. package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionOne.h +0 -119
  101. package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionOne.m +0 -307
  102. package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionThree.h +0 -94
  103. package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionThree.m +0 -619
  104. package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionTwo.h +0 -164
  105. package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionTwo.m +0 -514
  106. package/ios/CodePush/JWT/Core/Coding/JWTCoding.h +0 -24
  107. package/ios/CodePush/JWT/Core/Coding/JWTCoding.m +0 -11
  108. package/ios/CodePush/JWT/Core/FrameworkSupplement/JWT.h +0 -52
  109. package/ios/CodePush/JWT/Core/FrameworkSupplement/Map.modulemap +0 -5
  110. package/ios/CodePush/JWT/Core/Supplement/JWTBase64Coder.h +0 -28
  111. package/ios/CodePush/JWT/Core/Supplement/JWTBase64Coder.m +0 -70
  112. package/ios/CodePush/JWT/Core/Supplement/JWTDeprecations.h +0 -22
  113. package/ios/CodePush/JWT/Core/Supplement/JWTErrorDescription.h +0 -34
  114. package/ios/CodePush/JWT/Core/Supplement/JWTErrorDescription.m +0 -73
  115. package/ios/CodePush/JWT/LICENSE +0 -19
  116. package/ios/CodePush/JWT/README.md +0 -489
  117. package/ios/CodePush/SSZipArchive/Common.h +0 -81
  118. package/ios/CodePush/SSZipArchive/README.md +0 -1
  119. package/ios/CodePush/SSZipArchive/SSZipArchive.h +0 -76
  120. package/ios/CodePush/SSZipArchive/SSZipArchive.m +0 -691
  121. package/ios/CodePush/SSZipArchive/aes/aes.h +0 -198
  122. package/ios/CodePush/SSZipArchive/aes/aes_via_ace.h +0 -541
  123. package/ios/CodePush/SSZipArchive/aes/aescrypt.c +0 -294
  124. package/ios/CodePush/SSZipArchive/aes/aeskey.c +0 -548
  125. package/ios/CodePush/SSZipArchive/aes/aesopt.h +0 -739
  126. package/ios/CodePush/SSZipArchive/aes/aestab.c +0 -391
  127. package/ios/CodePush/SSZipArchive/aes/aestab.h +0 -173
  128. package/ios/CodePush/SSZipArchive/aes/brg_endian.h +0 -126
  129. package/ios/CodePush/SSZipArchive/aes/brg_types.h +0 -219
  130. package/ios/CodePush/SSZipArchive/aes/entropy.c +0 -54
  131. package/ios/CodePush/SSZipArchive/aes/entropy.h +0 -16
  132. package/ios/CodePush/SSZipArchive/aes/fileenc.c +0 -144
  133. package/ios/CodePush/SSZipArchive/aes/fileenc.h +0 -121
  134. package/ios/CodePush/SSZipArchive/aes/hmac.c +0 -145
  135. package/ios/CodePush/SSZipArchive/aes/hmac.h +0 -103
  136. package/ios/CodePush/SSZipArchive/aes/prng.c +0 -155
  137. package/ios/CodePush/SSZipArchive/aes/prng.h +0 -82
  138. package/ios/CodePush/SSZipArchive/aes/pwd2key.c +0 -103
  139. package/ios/CodePush/SSZipArchive/aes/pwd2key.h +0 -57
  140. package/ios/CodePush/SSZipArchive/aes/sha1.c +0 -258
  141. package/ios/CodePush/SSZipArchive/aes/sha1.h +0 -73
  142. package/ios/CodePush/SSZipArchive/minizip/crypt.h +0 -130
  143. package/ios/CodePush/SSZipArchive/minizip/ioapi.c +0 -369
  144. package/ios/CodePush/SSZipArchive/minizip/ioapi.h +0 -175
  145. package/ios/CodePush/SSZipArchive/minizip/mztools.c +0 -284
  146. package/ios/CodePush/SSZipArchive/minizip/mztools.h +0 -31
  147. package/ios/CodePush/SSZipArchive/minizip/unzip.c +0 -1839
  148. package/ios/CodePush/SSZipArchive/minizip/unzip.h +0 -248
  149. package/ios/CodePush/SSZipArchive/minizip/zip.c +0 -1910
  150. package/ios/CodePush/SSZipArchive/minizip/zip.h +0 -202
  151. package/scripts/postlink/android/postlink.js +0 -87
  152. package/scripts/postlink/ios/postlink.js +0 -116
  153. package/scripts/postlink/run.js +0 -11
  154. package/scripts/postunlink/android/postunlink.js +0 -74
  155. package/scripts/postunlink/ios/postunlink.js +0 -87
  156. package/scripts/postunlink/run.js +0 -11
  157. package/scripts/tools/linkToolsAndroid.js +0 -57
  158. package/scripts/tools/linkToolsIos.js +0 -130
  159. package/windows-legacy/CodePush/CodePush.csproj +0 -128
  160. package/windows-legacy/CodePush/CodePushUtils.cs +0 -47
  161. package/windows-legacy/CodePush/FileUtils.cs +0 -40
  162. package/windows-legacy/CodePush/Properties/AssemblyInfo.cs +0 -29
  163. package/windows-legacy/CodePush/Properties/CodePush.rd.xml +0 -33
  164. package/windows-legacy/CodePush/UpdateManager.cs +0 -305
  165. package/windows-legacy/CodePush/UpdateUtils.cs +0 -46
  166. package/windows-legacy/CodePush.Net46/Adapters/Http/HttpProgress.cs +0 -28
  167. package/windows-legacy/CodePush.Net46/Adapters/Storage/ApplicationDataContainer.cs +0 -106
  168. package/windows-legacy/CodePush.Net46/CodePush.Net46.csproj +0 -103
  169. package/windows-legacy/CodePush.Net46/CodePushUtils.cs +0 -158
  170. package/windows-legacy/CodePush.Net46/FileUtils.cs +0 -55
  171. package/windows-legacy/CodePush.Net46/Properties/AssemblyInfo.cs +0 -36
  172. package/windows-legacy/CodePush.Net46/UpdateManager.cs +0 -330
  173. package/windows-legacy/CodePush.Net46/UpdateUtils.cs +0 -70
  174. package/windows-legacy/CodePush.Net46/packages.config +0 -5
  175. package/windows-legacy/CodePush.Net46.Test/ApplicationDataContainerTest.cs +0 -105
  176. package/windows-legacy/CodePush.Net46.Test/CodePush.Net46.Test.csproj +0 -137
  177. package/windows-legacy/CodePush.Net46.Test/Properties/AssemblyInfo.cs +0 -36
  178. package/windows-legacy/CodePush.Net46.Test/TelemetryManagerTest.cs +0 -117
  179. package/windows-legacy/CodePush.Net46.Test/app.config +0 -11
  180. package/windows-legacy/CodePush.Net46.Test/packages.config +0 -4
  181. package/windows-legacy/CodePush.Shared/CodePush.Shared.projitems +0 -22
  182. package/windows-legacy/CodePush.Shared/CodePush.Shared.shproj +0 -13
  183. package/windows-legacy/CodePush.Shared/CodePushConstants.cs +0 -35
  184. package/windows-legacy/CodePush.Shared/CodePushNativeModule.cs +0 -329
  185. package/windows-legacy/CodePush.Shared/CodePushReactPackage.cs +0 -235
  186. package/windows-legacy/CodePush.Shared/CodePushUtils.cs +0 -70
  187. package/windows-legacy/CodePush.Shared/InstallMode.cs +0 -9
  188. package/windows-legacy/CodePush.Shared/MinimumBackgroundListener.cs +0 -44
  189. package/windows-legacy/CodePush.Shared/SettingsManager.cs +0 -148
  190. package/windows-legacy/CodePush.Shared/TelemetryManager.cs +0 -250
  191. package/windows-legacy/CodePush.Shared/UpdateState.cs +0 -9
@@ -1,691 +0,0 @@
1
- //
2
- // SSZipArchive.m
3
- // SSZipArchive
4
- //
5
- // Created by Sam Soffes on 7/21/10.
6
- // Copyright (c) Sam Soffes 2010-2015. All rights reserved.
7
- //
8
- #import "SSZipArchive.h"
9
- #include "unzip.h"
10
- #include "zip.h"
11
- #import "zlib.h"
12
- #import "zconf.h"
13
-
14
- #include <sys/stat.h>
15
-
16
- #define CHUNK 16384
17
-
18
- @interface SSZipArchive ()
19
- + (NSDate *)_dateWithMSDOSFormat:(UInt32)msdosDateTime;
20
- @end
21
-
22
- @implementation SSZipArchive
23
- {
24
- NSString *_path;
25
- NSString *_filename;
26
- zipFile _zip;
27
- }
28
-
29
- #pragma mark - Unzipping
30
-
31
- + (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination
32
- {
33
- return [self unzipFileAtPath:path toDestination:destination delegate:nil];
34
- }
35
-
36
- + (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination overwrite:(BOOL)overwrite password:(NSString *)password error:(NSError **)error
37
- {
38
- return [self unzipFileAtPath:path toDestination:destination overwrite:overwrite password:password error:error delegate:nil progressHandler:nil completionHandler:nil];
39
- }
40
-
41
- + (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination delegate:(id<SSZipArchiveDelegate>)delegate
42
- {
43
- return [self unzipFileAtPath:path toDestination:destination overwrite:YES password:nil error:nil delegate:delegate progressHandler:nil completionHandler:nil];
44
- }
45
-
46
- + (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination overwrite:(BOOL)overwrite password:(NSString *)password error:(NSError **)error delegate:(id<SSZipArchiveDelegate>)delegate
47
- {
48
- return [self unzipFileAtPath:path toDestination:destination overwrite:overwrite password:password error:error delegate:delegate progressHandler:nil completionHandler:nil];
49
- }
50
-
51
- + (BOOL)unzipFileAtPath:(NSString *)path
52
- toDestination:(NSString *)destination
53
- overwrite:(BOOL)overwrite
54
- password:(NSString *)password
55
- progressHandler:(void (^)(NSString *entry, unz_file_info zipInfo, long entryNumber, long total))progressHandler
56
- completionHandler:(void (^)(NSString *path, BOOL succeeded, NSError *error))completionHandler
57
- {
58
- return [self unzipFileAtPath:path toDestination:destination overwrite:overwrite password:password error:nil delegate:nil progressHandler:progressHandler completionHandler:completionHandler];
59
- }
60
-
61
- + (BOOL)unzipFileAtPath:(NSString *)path
62
- toDestination:(NSString *)destination
63
- progressHandler:(void (^)(NSString *entry, unz_file_info zipInfo, long entryNumber, long total))progressHandler
64
- completionHandler:(void (^)(NSString *path, BOOL succeeded, NSError *error))completionHandler
65
- {
66
- return [self unzipFileAtPath:path toDestination:destination overwrite:YES password:nil error:nil delegate:nil progressHandler:progressHandler completionHandler:completionHandler];
67
- }
68
-
69
- + (BOOL)unzipFileAtPath:(NSString *)path
70
- toDestination:(NSString *)destination
71
- overwrite:(BOOL)overwrite
72
- password:(NSString *)password
73
- error:(NSError **)error
74
- delegate:(id<SSZipArchiveDelegate>)delegate
75
- progressHandler:(void (^)(NSString *entry, unz_file_info zipInfo, long entryNumber, long total))progressHandler
76
- completionHandler:(void (^)(NSString *path, BOOL succeeded, NSError *error))completionHandler
77
- {
78
- // Begin opening
79
- zipFile zip = unzOpen((const char*)[path UTF8String]);
80
- if (zip == NULL)
81
- {
82
- NSDictionary *userInfo = @{NSLocalizedDescriptionKey: @"failed to open zip file"};
83
- NSError *err = [NSError errorWithDomain:@"SSZipArchiveErrorDomain" code:-1 userInfo:userInfo];
84
- if (error)
85
- {
86
- *error = err;
87
- }
88
- if (completionHandler)
89
- {
90
- completionHandler(nil, NO, err);
91
- }
92
- return NO;
93
- }
94
-
95
- NSDictionary * fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil];
96
- unsigned long long fileSize = [fileAttributes[NSFileSize] unsignedLongLongValue];
97
- unsigned long long currentPosition = 0;
98
-
99
- unz_global_info globalInfo = {0ul, 0ul};
100
- unzGetGlobalInfo(zip, &globalInfo);
101
-
102
- // Begin unzipping
103
- if (unzGoToFirstFile(zip) != UNZ_OK)
104
- {
105
- NSDictionary *userInfo = @{NSLocalizedDescriptionKey: @"failed to open first file in zip file"};
106
- NSError *err = [NSError errorWithDomain:@"SSZipArchiveErrorDomain" code:-2 userInfo:userInfo];
107
- if (error)
108
- {
109
- *error = err;
110
- }
111
- if (completionHandler)
112
- {
113
- completionHandler(nil, NO, err);
114
- }
115
- return NO;
116
- }
117
-
118
- BOOL success = YES;
119
- BOOL canceled = NO;
120
- int ret = 0;
121
- int crc_ret =0;
122
- unsigned char buffer[4096] = {0};
123
- NSFileManager *fileManager = [NSFileManager defaultManager];
124
- NSMutableSet *directoriesModificationDates = [[NSMutableSet alloc] init];
125
-
126
- // Message delegate
127
- if ([delegate respondsToSelector:@selector(zipArchiveWillUnzipArchiveAtPath:zipInfo:)]) {
128
- [delegate zipArchiveWillUnzipArchiveAtPath:path zipInfo:globalInfo];
129
- }
130
- if ([delegate respondsToSelector:@selector(zipArchiveProgressEvent:total:)]) {
131
- [delegate zipArchiveProgressEvent:(NSInteger)currentPosition total:(NSInteger)fileSize];
132
- }
133
-
134
- NSInteger currentFileNumber = 0;
135
- do {
136
- @autoreleasepool {
137
- if ([password length] == 0) {
138
- ret = unzOpenCurrentFile(zip);
139
- } else {
140
- ret = unzOpenCurrentFilePassword(zip, [password cStringUsingEncoding:NSASCIIStringEncoding]);
141
- }
142
-
143
- if (ret != UNZ_OK) {
144
- success = NO;
145
- break;
146
- }
147
-
148
- // Reading data and write to file
149
- unz_file_info fileInfo;
150
- memset(&fileInfo, 0, sizeof(unz_file_info));
151
-
152
- ret = unzGetCurrentFileInfo(zip, &fileInfo, NULL, 0, NULL, 0, NULL, 0);
153
- if (ret != UNZ_OK) {
154
- success = NO;
155
- unzCloseCurrentFile(zip);
156
- break;
157
- }
158
-
159
- currentPosition += fileInfo.compressed_size;
160
-
161
- // Message delegate
162
- if ([delegate respondsToSelector:@selector(zipArchiveShouldUnzipFileAtIndex:totalFiles:archivePath:fileInfo:)]) {
163
- if (![delegate zipArchiveShouldUnzipFileAtIndex:currentFileNumber
164
- totalFiles:(NSInteger)globalInfo.number_entry
165
- archivePath:path fileInfo:fileInfo]) {
166
- success = NO;
167
- canceled = YES;
168
- break;
169
- }
170
- }
171
- if ([delegate respondsToSelector:@selector(zipArchiveWillUnzipFileAtIndex:totalFiles:archivePath:fileInfo:)]) {
172
- [delegate zipArchiveWillUnzipFileAtIndex:currentFileNumber totalFiles:(NSInteger)globalInfo.number_entry
173
- archivePath:path fileInfo:fileInfo];
174
- }
175
- if ([delegate respondsToSelector:@selector(zipArchiveProgressEvent:total:)]) {
176
- [delegate zipArchiveProgressEvent:(NSInteger)currentPosition total:(NSInteger)fileSize];
177
- }
178
-
179
- char *filename = (char *)malloc(fileInfo.size_filename + 1);
180
- unzGetCurrentFileInfo(zip, &fileInfo, filename, fileInfo.size_filename + 1, NULL, 0, NULL, 0);
181
- filename[fileInfo.size_filename] = '\0';
182
-
183
- //
184
- // Determine whether this is a symbolic link:
185
- // - File is stored with 'version made by' value of UNIX (3),
186
- // as per http://www.pkware.com/documents/casestudies/APPNOTE.TXT
187
- // in the upper byte of the version field.
188
- // - BSD4.4 st_mode constants are stored in the high 16 bits of the
189
- // external file attributes (defacto standard, verified against libarchive)
190
- //
191
- // The original constants can be found here:
192
- // http://minnie.tuhs.org/cgi-bin/utree.pl?file=4.4BSD/usr/include/sys/stat.h
193
- //
194
- const uLong ZipUNIXVersion = 3;
195
- const uLong BSD_SFMT = 0170000;
196
- const uLong BSD_IFLNK = 0120000;
197
-
198
- BOOL fileIsSymbolicLink = NO;
199
- if (((fileInfo.version >> 8) == ZipUNIXVersion) && BSD_IFLNK == (BSD_SFMT & (fileInfo.external_fa >> 16))) {
200
- fileIsSymbolicLink = NO;
201
- }
202
-
203
- // Check if it contains directory
204
- NSString *strPath = @(filename);
205
- BOOL isDirectory = NO;
206
- if (filename[fileInfo.size_filename-1] == '/' || filename[fileInfo.size_filename-1] == '\\') {
207
- isDirectory = YES;
208
- }
209
- free(filename);
210
-
211
- // Contains a path
212
- if ([strPath rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"/\\"]].location != NSNotFound) {
213
- strPath = [strPath stringByReplacingOccurrencesOfString:@"\\" withString:@"/"];
214
- }
215
-
216
- NSString *fullPath = [destination stringByAppendingPathComponent:strPath];
217
- NSError *err = nil;
218
- NSDate *modDate = [[self class] _dateWithMSDOSFormat:(UInt32)fileInfo.dosDate];
219
- NSDictionary *directoryAttr = @{NSFileCreationDate: modDate, NSFileModificationDate: modDate};
220
-
221
- if (isDirectory) {
222
- [fileManager createDirectoryAtPath:fullPath withIntermediateDirectories:YES attributes:directoryAttr error:&err];
223
- } else {
224
- [fileManager createDirectoryAtPath:[fullPath stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:directoryAttr error:&err];
225
- }
226
- if (nil != err) {
227
- NSLog(@"[SSZipArchive] Error: %@", err.localizedDescription);
228
- }
229
-
230
- if(!fileIsSymbolicLink)
231
- [directoriesModificationDates addObject: @{@"path": fullPath, @"modDate": modDate}];
232
-
233
- if ([fileManager fileExistsAtPath:fullPath] && !isDirectory && !overwrite) {
234
- //FIXME: couldBe CRC Check?
235
- unzCloseCurrentFile(zip);
236
- ret = unzGoToNextFile(zip);
237
- continue;
238
- }
239
-
240
- if (!fileIsSymbolicLink) {
241
- FILE *fp = fopen((const char*)[fullPath UTF8String], "wb");
242
- while (fp) {
243
- int readBytes = unzReadCurrentFile(zip, buffer, 4096);
244
-
245
- if (readBytes > 0) {
246
- fwrite(buffer, readBytes, 1, fp );
247
- } else {
248
- break;
249
- }
250
- }
251
-
252
- if (fp) {
253
- if ([[[fullPath pathExtension] lowercaseString] isEqualToString:@"zip"]) {
254
- NSLog(@"Unzipping nested .zip file: %@", [fullPath lastPathComponent]);
255
- if ([self unzipFileAtPath:fullPath toDestination:[fullPath stringByDeletingLastPathComponent] overwrite:overwrite password:password error:nil delegate:nil]) {
256
- [[NSFileManager defaultManager] removeItemAtPath:fullPath error:nil];
257
- }
258
- }
259
-
260
- fclose(fp);
261
-
262
- // Set the original datetime property
263
- if (fileInfo.dosDate != 0) {
264
- NSDate *orgDate = [[self class] _dateWithMSDOSFormat:(UInt32)fileInfo.dosDate];
265
- NSDictionary *attr = @{NSFileModificationDate: orgDate};
266
-
267
- if (attr) {
268
- if ([fileManager setAttributes:attr ofItemAtPath:fullPath error:nil] == NO) {
269
- // Can't set attributes
270
- NSLog(@"[SSZipArchive] Failed to set attributes - whilst setting modification date");
271
- }
272
- }
273
- }
274
-
275
- // Set the original permissions on the file
276
- uLong permissions = fileInfo.external_fa >> 16;
277
- if (permissions != 0) {
278
- // Store it into a NSNumber
279
- NSNumber *permissionsValue = @(permissions);
280
-
281
- // Retrieve any existing attributes
282
- NSMutableDictionary *attrs = [[NSMutableDictionary alloc] initWithDictionary:[fileManager attributesOfItemAtPath:fullPath error:nil]];
283
-
284
- // Set the value in the attributes dict
285
- attrs[NSFilePosixPermissions] = permissionsValue;
286
-
287
- // Update attributes
288
- if ([fileManager setAttributes:attrs ofItemAtPath:fullPath error:nil] == NO) {
289
- // Unable to set the permissions attribute
290
- NSLog(@"[SSZipArchive] Failed to set attributes - whilst setting permissions");
291
- }
292
-
293
- #if !__has_feature(objc_arc)
294
- [attrs release];
295
- #endif
296
- }
297
- }
298
- }
299
- else
300
- {
301
- // Assemble the path for the symbolic link
302
- NSMutableString* destinationPath = [NSMutableString string];
303
- int bytesRead = 0;
304
- while((bytesRead = unzReadCurrentFile(zip, buffer, 4096)) > 0)
305
- {
306
- buffer[bytesRead] = (int)0;
307
- [destinationPath appendString:@((const char*)buffer)];
308
- }
309
-
310
- // Create the symbolic link (making sure it stays relative if it was relative before)
311
- int symlinkError = symlink([destinationPath cStringUsingEncoding:NSUTF8StringEncoding],
312
- [fullPath cStringUsingEncoding:NSUTF8StringEncoding]);
313
-
314
- if(symlinkError != 0)
315
- {
316
- NSLog(@"Failed to create symbolic link at \"%@\" to \"%@\". symlink() error code: %d", fullPath, destinationPath, errno);
317
- }
318
- }
319
-
320
- crc_ret = unzCloseCurrentFile( zip );
321
- if (crc_ret == UNZ_CRCERROR) {
322
- //CRC ERROR
323
- return NO;
324
- }
325
- ret = unzGoToNextFile( zip );
326
-
327
- // Message delegate
328
- if ([delegate respondsToSelector:@selector(zipArchiveDidUnzipFileAtIndex:totalFiles:archivePath:fileInfo:)]) {
329
- [delegate zipArchiveDidUnzipFileAtIndex:currentFileNumber totalFiles:(NSInteger)globalInfo.number_entry
330
- archivePath:path fileInfo:fileInfo];
331
- } else if ([delegate respondsToSelector: @selector(zipArchiveDidUnzipFileAtIndex:totalFiles:archivePath:unzippedFilePath:)]) {
332
- [delegate zipArchiveDidUnzipFileAtIndex: currentFileNumber totalFiles: (NSInteger)globalInfo.number_entry
333
- archivePath:path unzippedFilePath: fullPath];
334
- }
335
-
336
- currentFileNumber++;
337
- if (progressHandler)
338
- {
339
- progressHandler(strPath, fileInfo, currentFileNumber, globalInfo.number_entry);
340
- }
341
- }
342
- } while(ret == UNZ_OK && ret != UNZ_END_OF_LIST_OF_FILE);
343
-
344
- // Close
345
- unzClose(zip);
346
-
347
- // The process of decompressing the .zip archive causes the modification times on the folders
348
- // to be set to the present time. So, when we are done, they need to be explicitly set.
349
- // set the modification date on all of the directories.
350
- NSError * err = nil;
351
- for (NSDictionary * d in directoriesModificationDates) {
352
- if (![[NSFileManager defaultManager] setAttributes:@{NSFileModificationDate: d[@"modDate"]} ofItemAtPath:d[@"path"] error:&err]) {
353
- NSLog(@"[SSZipArchive] Set attributes failed for directory: %@.", d[@"path"]);
354
- }
355
- if (err) {
356
- NSLog(@"[SSZipArchive] Error setting directory file modification date attribute: %@",err.localizedDescription);
357
- }
358
- }
359
-
360
- #if !__has_feature(objc_arc)
361
- [directoriesModificationDates release];
362
- #endif
363
-
364
- // Message delegate
365
- if (success && [delegate respondsToSelector:@selector(zipArchiveDidUnzipArchiveAtPath:zipInfo:unzippedPath:)]) {
366
- [delegate zipArchiveDidUnzipArchiveAtPath:path zipInfo:globalInfo unzippedPath:destination];
367
- }
368
- // final progress event = 100%
369
- if (!canceled && [delegate respondsToSelector:@selector(zipArchiveProgressEvent:total:)]) {
370
- [delegate zipArchiveProgressEvent:fileSize total:fileSize];
371
- }
372
-
373
- if (completionHandler)
374
- {
375
- completionHandler(path, YES, nil);
376
- }
377
- return success;
378
- }
379
-
380
- #pragma mark - Zipping
381
- + (BOOL)createZipFileAtPath:(NSString *)path withFilesAtPaths:(NSArray *)paths
382
- {
383
- return [SSZipArchive createZipFileAtPath:path withFilesAtPaths:paths withPassword:nil];
384
- }
385
- + (BOOL)createZipFileAtPath:(NSString *)path withContentsOfDirectory:(NSString *)directoryPath{
386
- return [SSZipArchive createZipFileAtPath:path withContentsOfDirectory:directoryPath withPassword:nil];
387
- }
388
-
389
- + (BOOL)createZipFileAtPath:(NSString *)path withContentsOfDirectory:(NSString *)directoryPath keepParentDirectory:(BOOL)keepParentDirector{
390
- return [SSZipArchive createZipFileAtPath:path withContentsOfDirectory:directoryPath keepParentDirectory:keepParentDirector withPassword:nil];
391
- }
392
-
393
- + (BOOL)createZipFileAtPath:(NSString *)path withFilesAtPaths:(NSArray *)paths withPassword:(NSString *)password
394
- {
395
- BOOL success = NO;
396
- SSZipArchive *zipArchive = [[SSZipArchive alloc] initWithPath:path];
397
- if ([zipArchive open]) {
398
- for (NSString *filePath in paths) {
399
- [zipArchive writeFile:filePath withPassword:password];
400
- }
401
- success = [zipArchive close];
402
- }
403
-
404
- #if !__has_feature(objc_arc)
405
- [zipArchive release];
406
- #endif
407
-
408
- return success;
409
- }
410
-
411
- + (BOOL)createZipFileAtPath:(NSString *)path withContentsOfDirectory:(NSString *)directoryPath withPassword:(NSString *)password{
412
- return [self createZipFileAtPath:path withContentsOfDirectory:directoryPath keepParentDirectory:NO withPassword:password];
413
- }
414
-
415
-
416
- + (BOOL)createZipFileAtPath:(NSString *)path withContentsOfDirectory:(NSString *)directoryPath keepParentDirectory:(BOOL)keepParentDirectory withPassword:(NSString *)password{
417
- BOOL success = NO;
418
-
419
- NSFileManager *fileManager = nil;
420
- SSZipArchive *zipArchive = [[SSZipArchive alloc] initWithPath:path];
421
-
422
- if ([zipArchive open]) {
423
- // use a local filemanager (queue/thread compatibility)
424
- fileManager = [[NSFileManager alloc] init];
425
- NSDirectoryEnumerator *dirEnumerator = [fileManager enumeratorAtPath:directoryPath];
426
- NSString *fileName;
427
- while ((fileName = [dirEnumerator nextObject])) {
428
- BOOL isDir;
429
- NSString *fullFilePath = [directoryPath stringByAppendingPathComponent:fileName];
430
- [fileManager fileExistsAtPath:fullFilePath isDirectory:&isDir];
431
- if (!isDir) {
432
- if (keepParentDirectory)
433
- {
434
- fileName = [[directoryPath lastPathComponent] stringByAppendingPathComponent:fileName];
435
- }
436
- [zipArchive writeFileAtPath:fullFilePath withFileName:fileName withPassword:password];
437
- }
438
- else
439
- {
440
- if([[NSFileManager defaultManager] subpathsOfDirectoryAtPath:fullFilePath error:nil].count == 0)
441
- {
442
- NSString *tempName = [fullFilePath stringByAppendingPathComponent:@".DS_Store"];
443
- [@"" writeToFile:tempName atomically:YES encoding:NSUTF8StringEncoding error:nil];
444
- [zipArchive writeFileAtPath:tempName withFileName:[fileName stringByAppendingPathComponent:@".DS_Store"] withPassword:password];
445
- [[NSFileManager defaultManager] removeItemAtPath:tempName error:nil];
446
- }
447
- }
448
- }
449
- success = [zipArchive close];
450
- }
451
-
452
- #if !__has_feature(objc_arc)
453
- [fileManager release];
454
- [zipArchive release];
455
- #endif
456
-
457
- return success;
458
- }
459
-
460
-
461
- - (instancetype)initWithPath:(NSString *)path
462
- {
463
- if ((self = [super init])) {
464
- _path = [path copy];
465
- }
466
- return self;
467
- }
468
-
469
-
470
- #if !__has_feature(objc_arc)
471
- - (void)dealloc
472
- {
473
- [_path release];
474
- [super dealloc];
475
- }
476
- #endif
477
-
478
-
479
- - (BOOL)open
480
- {
481
- NSAssert((_zip == NULL), @"Attempting open an archive which is already open");
482
- _zip = zipOpen([_path UTF8String], APPEND_STATUS_CREATE);
483
- return (NULL != _zip);
484
- }
485
-
486
-
487
- - (void)zipInfo:(zip_fileinfo*)zipInfo setDate:(NSDate*)date
488
- {
489
- NSCalendar *currentCalendar = [NSCalendar currentCalendar];
490
- #if defined(__IPHONE_8_0) || defined(__MAC_10_10)
491
- uint flags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
492
- #else
493
- uint flags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
494
- #endif
495
- NSDateComponents *components = [currentCalendar components:flags fromDate:date];
496
- zipInfo->tmz_date.tm_sec = (unsigned int)components.second;
497
- zipInfo->tmz_date.tm_min = (unsigned int)components.minute;
498
- zipInfo->tmz_date.tm_hour = (unsigned int)components.hour;
499
- zipInfo->tmz_date.tm_mday = (unsigned int)components.day;
500
- zipInfo->tmz_date.tm_mon = (unsigned int)components.month - 1;
501
- zipInfo->tmz_date.tm_year = (unsigned int)components.year;
502
- }
503
-
504
- - (BOOL)writeFolderAtPath:(NSString *)path withFolderName:(NSString *)folderName withPassword:(NSString *)password
505
- {
506
- NSAssert((_zip != NULL), @"Attempting to write to an archive which was never opened");
507
-
508
- zip_fileinfo zipInfo = {{0}};
509
-
510
- NSDictionary *attr = [[NSFileManager defaultManager] attributesOfItemAtPath:path error: nil];
511
- if( attr )
512
- {
513
- NSDate *fileDate = (NSDate *)attr[NSFileModificationDate];
514
- if( fileDate )
515
- {
516
- [self zipInfo:&zipInfo setDate: fileDate ];
517
- }
518
-
519
- // Write permissions into the external attributes, for details on this see here: http://unix.stackexchange.com/a/14727
520
- // Get the permissions value from the files attributes
521
- NSNumber *permissionsValue = (NSNumber *)attr[NSFilePosixPermissions];
522
- if (permissionsValue) {
523
- // Get the short value for the permissions
524
- short permissionsShort = permissionsValue.shortValue;
525
-
526
- // Convert this into an octal by adding 010000, 010000 being the flag for a regular file
527
- NSInteger permissionsOctal = 0100000 + permissionsShort;
528
-
529
- // Convert this into a long value
530
- uLong permissionsLong = @(permissionsOctal).unsignedLongValue;
531
-
532
- // Store this into the external file attributes once it has been shifted 16 places left to form part of the second from last byte
533
- zipInfo.external_fa = permissionsLong << 16L;
534
- }
535
- }
536
-
537
- unsigned int len = 0;
538
- zipOpenNewFileInZip3(_zip, [[folderName stringByAppendingString:@"/"] UTF8String], &zipInfo, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_NO_COMPRESSION, 0, -MAX_WBITS, DEF_MEM_LEVEL,
539
- Z_DEFAULT_STRATEGY, [password UTF8String], 0);
540
- zipWriteInFileInZip(_zip, &len, 0);
541
- zipCloseFileInZip(_zip);
542
- return YES;
543
- }
544
-
545
- - (BOOL)writeFile:(NSString *)path withPassword:(NSString *)password;
546
- {
547
- return [self writeFileAtPath:path withFileName:nil withPassword:password];
548
- }
549
-
550
- // supports writing files with logical folder/directory structure
551
- // *path* is the absolute path of the file that will be compressed
552
- // *fileName* is the relative name of the file how it is stored within the zip e.g. /folder/subfolder/text1.txt
553
- - (BOOL)writeFileAtPath:(NSString *)path withFileName:(NSString *)fileName withPassword:(NSString *)password
554
- {
555
- NSAssert((_zip != NULL), @"Attempting to write to an archive which was never opened");
556
-
557
- FILE *input = fopen([path UTF8String], "r");
558
- if (NULL == input) {
559
- return NO;
560
- }
561
-
562
- const char *afileName;
563
- if (!fileName) {
564
- afileName = [path.lastPathComponent UTF8String];
565
- }
566
- else {
567
- afileName = [fileName UTF8String];
568
- }
569
-
570
- zip_fileinfo zipInfo = {{0}};
571
-
572
- NSDictionary *attr = [[NSFileManager defaultManager] attributesOfItemAtPath:path error: nil];
573
- if( attr )
574
- {
575
- NSDate *fileDate = (NSDate *)attr[NSFileModificationDate];
576
- if( fileDate )
577
- {
578
- [self zipInfo:&zipInfo setDate: fileDate ];
579
- }
580
-
581
- // Write permissions into the external attributes, for details on this see here: http://unix.stackexchange.com/a/14727
582
- // Get the permissions value from the files attributes
583
- NSNumber *permissionsValue = (NSNumber *)attr[NSFilePosixPermissions];
584
- if (permissionsValue) {
585
- // Get the short value for the permissions
586
- short permissionsShort = permissionsValue.shortValue;
587
-
588
- // Convert this into an octal by adding 010000, 010000 being the flag for a regular file
589
- NSInteger permissionsOctal = 0100000 + permissionsShort;
590
-
591
- // Convert this into a long value
592
- uLong permissionsLong = @(permissionsOctal).unsignedLongValue;
593
-
594
- // Store this into the external file attributes once it has been shifted 16 places left to form part of the second from last byte
595
- zipInfo.external_fa = permissionsLong << 16L;
596
- }
597
- }
598
-
599
- 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);
600
-
601
- void *buffer = malloc(CHUNK);
602
- unsigned int len = 0;
603
-
604
- while (!feof(input))
605
- {
606
- len = (unsigned int) fread(buffer, 1, CHUNK, input);
607
- zipWriteInFileInZip(_zip, buffer, len);
608
- }
609
-
610
- zipCloseFileInZip(_zip);
611
- free(buffer);
612
- fclose(input);
613
- return YES;
614
- }
615
-
616
- - (BOOL)writeData:(NSData *)data filename:(NSString *)filename withPassword:(NSString *)password;
617
- {
618
- if (!_zip) {
619
- return NO;
620
- }
621
- if (!data) {
622
- return NO;
623
- }
624
- zip_fileinfo zipInfo = {{0,0,0,0,0,0},0,0,0};
625
- [self zipInfo:&zipInfo setDate:[NSDate date]];
626
-
627
- 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);
628
-
629
- zipWriteInFileInZip(_zip, data.bytes, (unsigned int)data.length);
630
-
631
- zipCloseFileInZip(_zip);
632
- return YES;
633
- }
634
-
635
-
636
- - (BOOL)close
637
- {
638
- NSAssert((_zip != NULL), @"[SSZipArchive] Attempting to close an archive which was never opened");
639
- zipClose(_zip, NULL);
640
- return YES;
641
- }
642
-
643
- #pragma mark - Private
644
-
645
- // Format from http://newsgroups.derkeiler.com/Archive/Comp/comp.os.msdos.programmer/2009-04/msg00060.html
646
- // Two consecutive words, or a longword, YYYYYYYMMMMDDDDD hhhhhmmmmmmsssss
647
- // YYYYYYY is years from 1980 = 0
648
- // sssss is (seconds/2).
649
- //
650
- // 3658 = 0011 0110 0101 1000 = 0011011 0010 11000 = 27 2 24 = 2007-02-24
651
- // 7423 = 0111 0100 0010 0011 - 01110 100001 00011 = 14 33 3 = 14:33:06
652
- + (NSDate *)_dateWithMSDOSFormat:(UInt32)msdosDateTime
653
- {
654
- static const UInt32 kYearMask = 0xFE000000;
655
- static const UInt32 kMonthMask = 0x1E00000;
656
- static const UInt32 kDayMask = 0x1F0000;
657
- static const UInt32 kHourMask = 0xF800;
658
- static const UInt32 kMinuteMask = 0x7E0;
659
- static const UInt32 kSecondMask = 0x1F;
660
-
661
- static NSCalendar *gregorian;
662
- static dispatch_once_t onceToken;
663
- dispatch_once(&onceToken, ^{
664
- #if defined(__IPHONE_8_0) || defined(__MAC_10_10)
665
- gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
666
- #else
667
- gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
668
- #endif
669
- });
670
-
671
- NSDateComponents *components = [[NSDateComponents alloc] init];
672
-
673
- NSAssert(0xFFFFFFFF == (kYearMask | kMonthMask | kDayMask | kHourMask | kMinuteMask | kSecondMask), @"[SSZipArchive] MSDOS date masks don't add up");
674
-
675
- [components setYear:1980 + ((msdosDateTime & kYearMask) >> 25)];
676
- [components setMonth:(msdosDateTime & kMonthMask) >> 21];
677
- [components setDay:(msdosDateTime & kDayMask) >> 16];
678
- [components setHour:(msdosDateTime & kHourMask) >> 11];
679
- [components setMinute:(msdosDateTime & kMinuteMask) >> 5];
680
- [components setSecond:(msdosDateTime & kSecondMask) * 2];
681
-
682
- NSDate *date = [NSDate dateWithTimeInterval:0 sinceDate:[gregorian dateFromComponents:components]];
683
-
684
- #if !__has_feature(objc_arc)
685
- [components release];
686
- #endif
687
-
688
- return date;
689
- }
690
-
691
- @end