cronapp-cordova-plugin-contentsync 4.4.0-RC7

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 (42) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +11 -0
  3. package/README.md +372 -0
  4. package/package-lock.json +1545 -0
  5. package/package.json +58 -0
  6. package/plugin.xml +93 -0
  7. package/sample/css/index.css +128 -0
  8. package/sample/img/logo.png +0 -0
  9. package/sample/index.html +47 -0
  10. package/sample/js/index.js +152 -0
  11. package/spec/helper/cordova.js +83 -0
  12. package/spec/index.spec.js +334 -0
  13. package/src/android/Sync.java +1102 -0
  14. package/src/browser/Sync.js +20 -0
  15. package/src/ios/ContentSync.h +74 -0
  16. package/src/ios/ContentSync.m +1002 -0
  17. package/src/ios/SSZipArchive.h +52 -0
  18. package/src/ios/SSZipArchive.m +540 -0
  19. package/src/ios/minizip/crypt.h +131 -0
  20. package/src/ios/minizip/ioapi.c +239 -0
  21. package/src/ios/minizip/ioapi.h +201 -0
  22. package/src/ios/minizip/mztools.c +284 -0
  23. package/src/ios/minizip/mztools.h +31 -0
  24. package/src/ios/minizip/unzip.c +2153 -0
  25. package/src/ios/minizip/unzip.h +437 -0
  26. package/src/ios/minizip/zip.c +2022 -0
  27. package/src/ios/minizip/zip.h +362 -0
  28. package/src/windows/SyncProxy.js +279 -0
  29. package/src/windows/ZipWinProj/PGZipInflate.cs +94 -0
  30. package/src/windows/ZipWinProj/Properties/AssemblyInfo.cs +30 -0
  31. package/src/windows/ZipWinProj/ZipWinProj.csproj +57 -0
  32. package/src/wp8/Sync.cs +746 -0
  33. package/src/wp8/Unzip.cs +481 -0
  34. package/tests/anyfile.txt +1 -0
  35. package/tests/archives/www1.zip +0 -0
  36. package/tests/archives/www2.zip +0 -0
  37. package/tests/package.json +11 -0
  38. package/tests/plugin.xml +22 -0
  39. package/tests/scripts/start-server.sh +2 -0
  40. package/tests/scripts/stop-server.sh +1 -0
  41. package/tests/tests.js +255 -0
  42. package/www/index.js +285 -0
@@ -0,0 +1,52 @@
1
+ //
2
+ // SSZipArchive.h
3
+ // SSZipArchive
4
+ //
5
+ // Created by Sam Soffes on 7/21/10.
6
+ // Copyright (c) Sam Soffes 2010-2014. All rights reserved.
7
+ //
8
+
9
+ #ifndef _SSZIPARCHIVE_H
10
+ #define _SSZIPARCHIVE_H
11
+
12
+ #import <Foundation/Foundation.h>
13
+ #include "unzip.h"
14
+
15
+ @protocol SSZipArchiveDelegate;
16
+
17
+ @interface SSZipArchive : NSObject
18
+
19
+ // Unzip
20
+ + (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination;
21
+ + (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination overwrite:(BOOL)overwrite password:(NSString *)password error:(NSError **)error;
22
+
23
+ + (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination delegate:(id<SSZipArchiveDelegate>)delegate;
24
+ + (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination overwrite:(BOOL)overwrite password:(NSString *)password error:(NSError **)error delegate:(id<SSZipArchiveDelegate>)delegate;
25
+
26
+ // Zip
27
+ + (BOOL)createZipFileAtPath:(NSString *)path withFilesAtPaths:(NSArray *)filenames;
28
+ + (BOOL)createZipFileAtPath:(NSString *)path withContentsOfDirectory:(NSString *)directoryPath;
29
+
30
+ - (id)initWithPath:(NSString *)path;
31
+ - (BOOL)open;
32
+ - (BOOL)writeFile:(NSString *)path;
33
+ - (BOOL)writeData:(NSData *)data filename:(NSString *)filename;
34
+ - (BOOL)close;
35
+
36
+ @end
37
+
38
+
39
+ @protocol SSZipArchiveDelegate <NSObject>
40
+
41
+ @optional
42
+
43
+ - (void)zipArchiveWillUnzipArchiveAtPath:(NSString *)path zipInfo:(unz_global_info)zipInfo;
44
+ - (void)zipArchiveDidUnzipArchiveAtPath:(NSString *)path zipInfo:(unz_global_info)zipInfo unzippedPath:(NSString *)unzippedPath;
45
+
46
+ - (void)zipArchiveWillUnzipFileAtIndex:(NSInteger)fileIndex totalFiles:(NSInteger)totalFiles archivePath:(NSString *)archivePath fileInfo:(unz_file_info)fileInfo;
47
+ - (void)zipArchiveDidUnzipFileAtIndex:(NSInteger)fileIndex totalFiles:(NSInteger)totalFiles archivePath:(NSString *)archivePath fileInfo:(unz_file_info)fileInfo;
48
+
49
+ - (void)zipArchiveProgressEvent:(NSInteger)loaded total:(NSInteger)total;
50
+ @end
51
+
52
+ #endif /* _SSZIPARCHIVE_H */
@@ -0,0 +1,540 @@
1
+ //
2
+ // SSZipArchive.m
3
+ // SSZipArchive
4
+ //
5
+ // Created by Sam Soffes on 7/21/10.
6
+ // Copyright (c) Sam Soffes 2010-2014. All rights reserved.
7
+ //
8
+
9
+ #import "SSZipArchive.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
+
23
+ @implementation SSZipArchive {
24
+ NSString *_path;
25
+ NSString *_filename;
26
+ zipFile _zip;
27
+ }
28
+
29
+
30
+ #pragma mark - Unzipping
31
+
32
+ + (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination {
33
+ return [self unzipFileAtPath:path toDestination:destination delegate:nil];
34
+ }
35
+
36
+
37
+ + (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination overwrite:(BOOL)overwrite password:(NSString *)password error:(NSError **)error {
38
+ return [self unzipFileAtPath:path toDestination:destination overwrite:overwrite password:password error:error delegate:nil];
39
+ }
40
+
41
+
42
+ + (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination delegate:(id<SSZipArchiveDelegate>)delegate {
43
+ return [self unzipFileAtPath:path toDestination:destination overwrite:YES password:nil error:nil delegate:delegate];
44
+ }
45
+
46
+
47
+ + (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination overwrite:(BOOL)overwrite password:(NSString *)password error:(NSError **)error delegate:(id<SSZipArchiveDelegate>)delegate {
48
+ // Begin opening
49
+ zipFile zip = unzOpen((const char*)[path UTF8String]);
50
+ if (zip == NULL) {
51
+ NSDictionary *userInfo = [NSDictionary dictionaryWithObject:@"failed to open zip file" forKey:NSLocalizedDescriptionKey];
52
+ if (error) {
53
+ *error = [NSError errorWithDomain:@"SSZipArchiveErrorDomain" code:-1 userInfo:userInfo];
54
+ }
55
+ return NO;
56
+ }
57
+
58
+ NSDictionary * fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil];
59
+ ZPOS64_T fileSize = fileAttributes.fileSize;
60
+ ZPOS64_T currentPosition = 0;
61
+
62
+ unz_global_info globalInfo = {0ul, 0ul};
63
+ unzGetGlobalInfo(zip, &globalInfo);
64
+
65
+ // Begin unzipping
66
+ if (unzGoToFirstFile(zip) != UNZ_OK) {
67
+ NSDictionary *userInfo = [NSDictionary dictionaryWithObject:@"failed to open first file in zip file" forKey:NSLocalizedDescriptionKey];
68
+ if (error) {
69
+ *error = [NSError errorWithDomain:@"SSZipArchiveErrorDomain" code:-2 userInfo:userInfo];
70
+ }
71
+ return NO;
72
+ }
73
+
74
+ BOOL success = YES;
75
+ int ret = 0;
76
+ unsigned char buffer[4096] = {0};
77
+ NSFileManager *fileManager = [NSFileManager defaultManager];
78
+ NSMutableSet *directoriesModificationDates = [[NSMutableSet alloc] init];
79
+
80
+ // Message delegate
81
+ if ([delegate respondsToSelector:@selector(zipArchiveWillUnzipArchiveAtPath:zipInfo:)]) {
82
+ [delegate zipArchiveWillUnzipArchiveAtPath:path zipInfo:globalInfo];
83
+ }
84
+ if ([delegate respondsToSelector:@selector(zipArchiveProgressEvent:total:)]) {
85
+ [delegate zipArchiveProgressEvent:(NSInteger)currentPosition total:(NSInteger)fileSize];
86
+ }
87
+
88
+ NSInteger currentFileNumber = 0;
89
+ do {
90
+ @autoreleasepool {
91
+ if ([password length] == 0) {
92
+ ret = unzOpenCurrentFile(zip);
93
+ } else {
94
+ ret = unzOpenCurrentFilePassword(zip, [password cStringUsingEncoding:NSASCIIStringEncoding]);
95
+ }
96
+
97
+ if (ret != UNZ_OK) {
98
+ success = NO;
99
+ break;
100
+ }
101
+
102
+ // Reading data and write to file
103
+ unz_file_info fileInfo;
104
+ memset(&fileInfo, 0, sizeof(unz_file_info));
105
+
106
+ ret = unzGetCurrentFileInfo(zip, &fileInfo, NULL, 0, NULL, 0, NULL, 0);
107
+ if (ret != UNZ_OK) {
108
+ success = NO;
109
+ unzCloseCurrentFile(zip);
110
+ break;
111
+ }
112
+
113
+ currentPosition += fileInfo.compressed_size;
114
+
115
+ // Message delegate
116
+ if ([delegate respondsToSelector:@selector(zipArchiveWillUnzipFileAtIndex:totalFiles:archivePath:fileInfo:)]) {
117
+ [delegate zipArchiveWillUnzipFileAtIndex:currentFileNumber totalFiles:(NSInteger)globalInfo.number_entry
118
+ archivePath:path fileInfo:fileInfo];
119
+ }
120
+ if ([delegate respondsToSelector:@selector(zipArchiveProgressEvent:total:)]) {
121
+ [delegate zipArchiveProgressEvent:(NSInteger)currentPosition total:(NSInteger)fileSize];
122
+ }
123
+
124
+ char *filename = (char *)malloc(fileInfo.size_filename + 1);
125
+ unzGetCurrentFileInfo(zip, &fileInfo, filename, fileInfo.size_filename + 1, NULL, 0, NULL, 0);
126
+ filename[fileInfo.size_filename] = '\0';
127
+
128
+ //
129
+ // Determine whether this is a symbolic link:
130
+ // - File is stored with 'version made by' value of UNIX (3),
131
+ // as per http://www.pkware.com/documents/casestudies/APPNOTE.TXT
132
+ // in the upper byte of the version field.
133
+ // - BSD4.4 st_mode constants are stored in the high 16 bits of the
134
+ // external file attributes (defacto standard, verified against libarchive)
135
+ //
136
+ // The original constants can be found here:
137
+ // http://minnie.tuhs.org/cgi-bin/utree.pl?file=4.4BSD/usr/include/sys/stat.h
138
+ //
139
+ const uLong ZipUNIXVersion = 3;
140
+ const uLong BSD_SFMT = 0170000;
141
+ const uLong BSD_IFLNK = 0120000;
142
+
143
+ BOOL fileIsSymbolicLink = NO;
144
+ if (((fileInfo.version >> 8) == ZipUNIXVersion) && BSD_IFLNK == (BSD_SFMT & (fileInfo.external_fa >> 16))) {
145
+ fileIsSymbolicLink = YES;
146
+ }
147
+
148
+ // Check if it contains directory
149
+ NSString *strPath = [NSString stringWithCString:filename encoding:NSUTF8StringEncoding];
150
+ BOOL isDirectory = NO;
151
+ if (filename[fileInfo.size_filename-1] == '/' || filename[fileInfo.size_filename-1] == '\\') {
152
+ isDirectory = YES;
153
+ }
154
+ free(filename);
155
+
156
+ // Contains a path
157
+ if ([strPath rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"/\\"]].location != NSNotFound) {
158
+ strPath = [strPath stringByReplacingOccurrencesOfString:@"\\" withString:@"/"];
159
+ }
160
+
161
+ NSString *fullPath = [destination stringByAppendingPathComponent:strPath];
162
+ NSError *err = nil;
163
+ NSDate *modDate = [[self class] _dateWithMSDOSFormat:(UInt32)fileInfo.dosDate];
164
+ NSDictionary *directoryAttr = [NSDictionary dictionaryWithObjectsAndKeys:modDate, NSFileCreationDate, modDate, NSFileModificationDate, nil];
165
+
166
+ if (isDirectory) {
167
+ [fileManager createDirectoryAtPath:fullPath withIntermediateDirectories:YES attributes:directoryAttr error:&err];
168
+ } else {
169
+ [fileManager createDirectoryAtPath:[fullPath stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:directoryAttr error:&err];
170
+ }
171
+ if (nil != err) {
172
+ NSLog(@"[SSZipArchive] Error: %@", err.localizedDescription);
173
+ }
174
+
175
+ if(!fileIsSymbolicLink)
176
+ [directoriesModificationDates addObject: [NSDictionary dictionaryWithObjectsAndKeys:fullPath, @"path", modDate, @"modDate", nil]];
177
+
178
+ if ([fileManager fileExistsAtPath:fullPath] && !isDirectory && !overwrite) {
179
+ unzCloseCurrentFile(zip);
180
+ ret = unzGoToNextFile(zip);
181
+ continue;
182
+ }
183
+
184
+ if(!fileIsSymbolicLink)
185
+ {
186
+ FILE *fp = fopen((const char*)[fullPath UTF8String], "wb");
187
+ while (fp) {
188
+ int readBytes = unzReadCurrentFile(zip, buffer, 4096);
189
+
190
+ if (readBytes > 0) {
191
+ fwrite(buffer, readBytes, 1, fp );
192
+ } else {
193
+ break;
194
+ }
195
+ }
196
+
197
+ if (fp) {
198
+ fclose(fp);
199
+
200
+ // Set the original datetime property
201
+ if (fileInfo.dosDate != 0) {
202
+ NSDate *orgDate = [[self class] _dateWithMSDOSFormat:(UInt32)fileInfo.dosDate];
203
+ NSDictionary *attr = [NSDictionary dictionaryWithObject:orgDate forKey:NSFileModificationDate];
204
+
205
+ if (attr) {
206
+ if ([fileManager setAttributes:attr ofItemAtPath:fullPath error:nil] == NO) {
207
+ // Can't set attributes
208
+ NSLog(@"[SSZipArchive] Failed to set attributes - whilst setting modification date");
209
+ }
210
+ }
211
+ }
212
+
213
+ // Set the original permissions on the file
214
+ uLong permissions = fileInfo.external_fa >> 16;
215
+ if (permissions != 0) {
216
+ // Store it into a NSNumber
217
+ NSNumber *permissionsValue = @(permissions);
218
+
219
+ // Retrieve any existing attributes
220
+ NSMutableDictionary *attrs = [[NSMutableDictionary alloc] initWithDictionary:[fileManager attributesOfItemAtPath:fullPath error:nil]];
221
+
222
+ // Set the value in the attributes dict
223
+ attrs[NSFilePosixPermissions] = permissionsValue;
224
+
225
+ // Update attributes
226
+ if ([fileManager setAttributes:attrs ofItemAtPath:fullPath error:nil] == NO) {
227
+ // Unable to set the permissions attribute
228
+ NSLog(@"[SSZipArchive] Failed to set attributes - whilst setting permissions");
229
+ }
230
+
231
+ #if !__has_feature(objc_arc)
232
+ [attrs release];
233
+ #endif
234
+ }
235
+ }
236
+ }
237
+ else
238
+ {
239
+ // Assemble the path for the symbolic link
240
+ NSMutableString* destinationPath = [NSMutableString string];
241
+ int bytesRead = 0;
242
+ while((bytesRead = unzReadCurrentFile(zip, buffer, 4096)) > 0)
243
+ {
244
+ buffer[bytesRead] = 0;
245
+ [destinationPath appendString:[NSString stringWithUTF8String:(const char*)buffer]];
246
+ }
247
+
248
+ // Create the symbolic link (making sure it stays relative if it was relative before)
249
+ int symlinkError = symlink([destinationPath cStringUsingEncoding:NSUTF8StringEncoding],
250
+ [fullPath cStringUsingEncoding:NSUTF8StringEncoding]);
251
+
252
+ if(symlinkError != 0)
253
+ {
254
+ NSLog(@"Failed to create symbolic link at \"%@\" to \"%@\". symlink() error code: %d", fullPath, destinationPath, errno);
255
+ }
256
+ }
257
+
258
+ unzCloseCurrentFile( zip );
259
+ ret = unzGoToNextFile( zip );
260
+
261
+ // Message delegate
262
+ if ([delegate respondsToSelector:@selector(zipArchiveDidUnzipFileAtIndex:totalFiles:archivePath:fileInfo:)]) {
263
+ [delegate zipArchiveDidUnzipFileAtIndex:currentFileNumber totalFiles:(NSInteger)globalInfo.number_entry
264
+ archivePath:path fileInfo:fileInfo];
265
+ }
266
+
267
+ currentFileNumber++;
268
+ }
269
+ } while(ret == UNZ_OK && ret != UNZ_END_OF_LIST_OF_FILE);
270
+
271
+ // Close
272
+ unzClose(zip);
273
+
274
+ // The process of decompressing the .zip archive causes the modification times on the folders
275
+ // to be set to the present time. So, when we are done, they need to be explicitly set.
276
+ // set the modification date on all of the directories.
277
+ NSError * err = nil;
278
+ for (NSDictionary * d in directoriesModificationDates) {
279
+ if (![[NSFileManager defaultManager] setAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[d objectForKey:@"modDate"], NSFileModificationDate, nil] ofItemAtPath:[d objectForKey:@"path"] error:&err]) {
280
+ NSLog(@"[SSZipArchive] Set attributes failed for directory: %@.", [d objectForKey:@"path"]);
281
+ }
282
+ if (err) {
283
+ NSLog(@"[SSZipArchive] Error setting directory file modification date attribute: %@",err.localizedDescription);
284
+ }
285
+ }
286
+
287
+ #if !__has_feature(objc_arc)
288
+ [directoriesModificationDates release];
289
+ #endif
290
+
291
+ // Message delegate
292
+ if (success && [delegate respondsToSelector:@selector(zipArchiveDidUnzipArchiveAtPath:zipInfo:unzippedPath:)]) {
293
+ [delegate zipArchiveDidUnzipArchiveAtPath:path zipInfo:globalInfo unzippedPath:destination];
294
+ }
295
+ // final progress event = 100%
296
+ if ([delegate respondsToSelector:@selector(zipArchiveProgressEvent:total:)]) {
297
+ [delegate zipArchiveProgressEvent:(NSInteger)fileSize total:(NSInteger)fileSize];
298
+ }
299
+
300
+ return success;
301
+ }
302
+
303
+
304
+ #pragma mark - Zipping
305
+
306
+ + (BOOL)createZipFileAtPath:(NSString *)path withFilesAtPaths:(NSArray *)paths {
307
+ BOOL success = NO;
308
+ SSZipArchive *zipArchive = [[SSZipArchive alloc] initWithPath:path];
309
+ if ([zipArchive open]) {
310
+ for (NSString *path in paths) {
311
+ [zipArchive writeFile:path];
312
+ }
313
+ success = [zipArchive close];
314
+ }
315
+
316
+ #if !__has_feature(objc_arc)
317
+ [zipArchive release];
318
+ #endif
319
+
320
+ return success;
321
+ }
322
+
323
+
324
+ + (BOOL)createZipFileAtPath:(NSString *)path withContentsOfDirectory:(NSString *)directoryPath {
325
+ BOOL success = NO;
326
+
327
+ NSFileManager *fileManager = nil;
328
+ SSZipArchive *zipArchive = [[SSZipArchive alloc] initWithPath:path];
329
+
330
+ if ([zipArchive open]) {
331
+ // use a local filemanager (queue/thread compatibility)
332
+ fileManager = [[NSFileManager alloc] init];
333
+ NSDirectoryEnumerator *dirEnumerator = [fileManager enumeratorAtPath:directoryPath];
334
+
335
+ NSString *fileName;
336
+ while ((fileName = [dirEnumerator nextObject])) {
337
+ BOOL isDir;
338
+ NSString *fullFilePath = [directoryPath stringByAppendingPathComponent:fileName];
339
+ [fileManager fileExistsAtPath:fullFilePath isDirectory:&isDir];
340
+ if (!isDir) {
341
+ [zipArchive writeFileAtPath:fullFilePath withFileName:fileName];
342
+ }
343
+ }
344
+ success = [zipArchive close];
345
+ }
346
+
347
+ #if !__has_feature(objc_arc)
348
+ [fileManager release];
349
+ [zipArchive release];
350
+ #endif
351
+
352
+ return success;
353
+ }
354
+
355
+
356
+ - (id)initWithPath:(NSString *)path {
357
+ if ((self = [super init])) {
358
+ _path = [path copy];
359
+ }
360
+ return self;
361
+ }
362
+
363
+
364
+ #if !__has_feature(objc_arc)
365
+ - (void)dealloc {
366
+ [_path release];
367
+ [super dealloc];
368
+ }
369
+ #endif
370
+
371
+
372
+ - (BOOL)open {
373
+ NSAssert((_zip == NULL), @"Attempting open an archive which is already open");
374
+ _zip = zipOpen([_path UTF8String], APPEND_STATUS_CREATE);
375
+ return (NULL != _zip);
376
+ }
377
+
378
+
379
+ - (void)zipInfo:(zip_fileinfo*)zipInfo setDate:(NSDate*)date {
380
+ NSCalendar *currentCalendar = [NSCalendar currentCalendar];
381
+ #ifdef __IPHONE_8_0
382
+ uint flags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
383
+ #else
384
+ uint flags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
385
+ #endif
386
+ NSDateComponents *components = [currentCalendar components:flags fromDate:date];
387
+ zipInfo->tmz_date.tm_sec = (unsigned int)components.second;
388
+ zipInfo->tmz_date.tm_min = (unsigned int)components.minute;
389
+ zipInfo->tmz_date.tm_hour = (unsigned int)components.hour;
390
+ zipInfo->tmz_date.tm_mday = (unsigned int)components.day;
391
+ zipInfo->tmz_date.tm_mon = (unsigned int)components.month - 1;
392
+ zipInfo->tmz_date.tm_year = (unsigned int)components.year;
393
+ }
394
+
395
+
396
+ - (BOOL)writeFile:(NSString *)path
397
+ {
398
+ return [self writeFileAtPath:path withFileName:nil];
399
+ }
400
+
401
+ // supports writing files with logical folder/directory structure
402
+ // *path* is the absolute path of the file that will be compressed
403
+ // *fileName* is the relative name of the file how it is stored within the zip e.g. /folder/subfolder/text1.txt
404
+ - (BOOL)writeFileAtPath:(NSString *)path withFileName:(NSString *)fileName {
405
+ NSAssert((_zip != NULL), @"Attempting to write to an archive which was never opened");
406
+
407
+ FILE *input = fopen([path UTF8String], "r");
408
+ if (NULL == input) {
409
+ return NO;
410
+ }
411
+
412
+ const char *afileName;
413
+ if (!fileName) {
414
+ afileName = [path.lastPathComponent UTF8String];
415
+ }
416
+ else {
417
+ afileName = [fileName UTF8String];
418
+ }
419
+
420
+ zip_fileinfo zipInfo = {{0}};
421
+
422
+ NSDictionary *attr = [[NSFileManager defaultManager] attributesOfItemAtPath:path error: nil];
423
+ if( attr )
424
+ {
425
+ NSDate *fileDate = (NSDate *)[attr objectForKey:NSFileModificationDate];
426
+ if( fileDate )
427
+ {
428
+ [self zipInfo:&zipInfo setDate: fileDate ];
429
+ }
430
+
431
+ // Write permissions into the external attributes, for details on this see here: http://unix.stackexchange.com/a/14727
432
+ // Get the permissions value from the files attributes
433
+ NSNumber *permissionsValue = (NSNumber *)[attr objectForKey:NSFilePosixPermissions];
434
+ if (permissionsValue) {
435
+ // Get the short value for the permissions
436
+ short permissionsShort = permissionsValue.shortValue;
437
+
438
+ // Convert this into an octal by adding 010000, 010000 being the flag for a regular file
439
+ NSInteger permissionsOctal = 0100000 + permissionsShort;
440
+
441
+ // Convert this into a long value
442
+ uLong permissionsLong = @(permissionsOctal).unsignedLongValue;
443
+
444
+ // Store this into the external file attributes once it has been shifted 16 places left to form part of the second from last byte
445
+ zipInfo.external_fa = permissionsLong << 16L;
446
+ }
447
+ }
448
+
449
+ zipOpenNewFileInZip(_zip, afileName, &zipInfo, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION);
450
+
451
+ void *buffer = malloc(CHUNK);
452
+ unsigned int len = 0;
453
+
454
+ while (!feof(input))
455
+ {
456
+ len = (unsigned int) fread(buffer, 1, CHUNK, input);
457
+ zipWriteInFileInZip(_zip, buffer, len);
458
+ }
459
+
460
+ zipCloseFileInZip(_zip);
461
+ free(buffer);
462
+ fclose(input);
463
+ return YES;
464
+ }
465
+
466
+
467
+ - (BOOL)writeData:(NSData *)data filename:(NSString *)filename {
468
+ if (!_zip) {
469
+ return NO;
470
+ }
471
+ if (!data) {
472
+ return NO;
473
+ }
474
+ zip_fileinfo zipInfo = {{0,0,0,0,0,0},0,0,0};
475
+ [self zipInfo:&zipInfo setDate:[NSDate date]];
476
+
477
+ zipOpenNewFileInZip(_zip, [filename UTF8String], &zipInfo, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION);
478
+
479
+ zipWriteInFileInZip(_zip, data.bytes, (unsigned int)data.length);
480
+
481
+ zipCloseFileInZip(_zip);
482
+ return YES;
483
+ }
484
+
485
+
486
+ - (BOOL)close {
487
+ NSAssert((_zip != NULL), @"[SSZipArchive] Attempting to close an archive which was never opened");
488
+ zipClose(_zip, NULL);
489
+ return YES;
490
+ }
491
+
492
+
493
+ #pragma mark - Private
494
+
495
+ // Format from http://newsgroups.derkeiler.com/Archive/Comp/comp.os.msdos.programmer/2009-04/msg00060.html
496
+ // Two consecutive words, or a longword, YYYYYYYMMMMDDDDD hhhhhmmmmmmsssss
497
+ // YYYYYYY is years from 1980 = 0
498
+ // sssss is (seconds/2).
499
+ //
500
+ // 3658 = 0011 0110 0101 1000 = 0011011 0010 11000 = 27 2 24 = 2007-02-24
501
+ // 7423 = 0111 0100 0010 0011 - 01110 100001 00011 = 14 33 2 = 14:33:06
502
+ + (NSDate *)_dateWithMSDOSFormat:(UInt32)msdosDateTime {
503
+ static const UInt32 kYearMask = 0xFE000000;
504
+ static const UInt32 kMonthMask = 0x1E00000;
505
+ static const UInt32 kDayMask = 0x1F0000;
506
+ static const UInt32 kHourMask = 0xF800;
507
+ static const UInt32 kMinuteMask = 0x7E0;
508
+ static const UInt32 kSecondMask = 0x1F;
509
+
510
+ static NSCalendar *gregorian;
511
+ static dispatch_once_t onceToken;
512
+ dispatch_once(&onceToken, ^{
513
+ #ifdef __IPHONE_8_0
514
+ gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
515
+ #else
516
+ gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
517
+ #endif
518
+ });
519
+
520
+ NSDateComponents *components = [[NSDateComponents alloc] init];
521
+
522
+ NSAssert(0xFFFFFFFF == (kYearMask | kMonthMask | kDayMask | kHourMask | kMinuteMask | kSecondMask), @"[SSZipArchive] MSDOS date masks don't add up");
523
+
524
+ [components setYear:1980 + ((msdosDateTime & kYearMask) >> 25)];
525
+ [components setMonth:(msdosDateTime & kMonthMask) >> 21];
526
+ [components setDay:(msdosDateTime & kDayMask) >> 16];
527
+ [components setHour:(msdosDateTime & kHourMask) >> 11];
528
+ [components setMinute:(msdosDateTime & kMinuteMask) >> 5];
529
+ [components setSecond:(msdosDateTime & kSecondMask) * 2];
530
+
531
+ NSDate *date = [NSDate dateWithTimeInterval:0 sinceDate:[gregorian dateFromComponents:components]];
532
+
533
+ #if !__has_feature(objc_arc)
534
+ [components release];
535
+ #endif
536
+
537
+ return date;
538
+ }
539
+
540
+ @end