Skip to content
This repository was archived by the owner on May 20, 2025. It is now read-only.

Commit 466ff11

Browse files
committed
Merge pull request #82 from Microsoft/asset-update
Enable Asset updates on iOS
2 parents d4b2c63 + 20fe7c2 commit 466ff11

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+11195
-74
lines changed

CodePush.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,15 @@
3939
@interface CodePushDownloadHandler : NSObject <NSURLConnectionDelegate>
4040

4141
@property (strong) NSOutputStream *outputFileStream;
42-
@property long expectedContentLength;
43-
@property long receivedContentLength;
44-
@property (copy) void (^progressCallback)(long, long);
45-
@property (copy) void (^doneCallback)();
42+
@property long long expectedContentLength;
43+
@property long long receivedContentLength;
44+
@property (copy) void (^progressCallback)(long long, long long);
45+
@property (copy) void (^doneCallback)(BOOL);
4646
@property (copy) void (^failCallback)(NSError *err);
4747

4848
- (id)init:(NSString *)downloadFilePath
49-
progressCallback:(void (^)(long, long))progressCallback
50-
doneCallback:(void (^)())doneCallback
49+
progressCallback:(void (^)(long long, long long))progressCallback
50+
doneCallback:(void (^)(BOOL))doneCallback
5151
failCallback:(void (^)(NSError *err))failCallback;
5252

5353
- (void)download:(NSString*)url;
@@ -71,7 +71,7 @@ failCallback:(void (^)(NSError *err))failCallback;
7171

7272

7373
+ (void)downloadPackage:(NSDictionary *)updatePackage
74-
progressCallback:(void (^)(long, long))progressCallback
74+
progressCallback:(void (^)(long long, long long))progressCallback
7575
doneCallback:(void (^)())doneCallback
7676
failCallback:(void (^)(NSError *err))failCallback;
7777

CodePush.m

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -259,13 +259,13 @@ - (void)startRollbackTimer:(int)rollbackTimeout
259259
{
260260
[CodePushPackage downloadPackage:updatePackage
261261
// The download is progressing forward
262-
progressCallback:^(long expectedContentLength, long receivedContentLength) {
262+
progressCallback:^(long long expectedContentLength, long long receivedContentLength) {
263263
// Notify the script-side about the progress
264264
[self.bridge.eventDispatcher
265265
sendDeviceEventWithName:@"CodePushDownloadProgress"
266266
body:@{
267-
@"totalBytes":[NSNumber numberWithLong:expectedContentLength],
268-
@"receivedBytes":[NSNumber numberWithLong:receivedContentLength]
267+
@"totalBytes":[NSNumber numberWithLongLong:expectedContentLength],
268+
@"receivedBytes":[NSNumber numberWithLongLong:receivedContentLength]
269269
}];
270270
}
271271
// The download completed

CodePush.xcodeproj/project.pbxproj

Lines changed: 127 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,20 @@
99
/* Begin PBXBuildFile section */
1010
13BE3DEE1AC21097009241FE /* CodePush.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BE3DED1AC21097009241FE /* CodePush.m */; };
1111
1B23B9141BF9267B000BB2F0 /* RCTConvert+CodePushInstallMode.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B23B9131BF9267B000BB2F0 /* RCTConvert+CodePushInstallMode.m */; };
12+
54A0026C1C0E2880004C3CEC /* aescrypt.c in Sources */ = {isa = PBXBuildFile; fileRef = 54A0024C1C0E2880004C3CEC /* aescrypt.c */; };
13+
54A0026D1C0E2880004C3CEC /* aeskey.c in Sources */ = {isa = PBXBuildFile; fileRef = 54A0024D1C0E2880004C3CEC /* aeskey.c */; };
14+
54A0026E1C0E2880004C3CEC /* aestab.c in Sources */ = {isa = PBXBuildFile; fileRef = 54A0024F1C0E2880004C3CEC /* aestab.c */; };
15+
54A0026F1C0E2880004C3CEC /* entropy.c in Sources */ = {isa = PBXBuildFile; fileRef = 54A002531C0E2880004C3CEC /* entropy.c */; };
16+
54A002701C0E2880004C3CEC /* fileenc.c in Sources */ = {isa = PBXBuildFile; fileRef = 54A002551C0E2880004C3CEC /* fileenc.c */; };
17+
54A002711C0E2880004C3CEC /* hmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 54A002571C0E2880004C3CEC /* hmac.c */; };
18+
54A002721C0E2880004C3CEC /* prng.c in Sources */ = {isa = PBXBuildFile; fileRef = 54A002591C0E2880004C3CEC /* prng.c */; };
19+
54A002731C0E2880004C3CEC /* pwd2key.c in Sources */ = {isa = PBXBuildFile; fileRef = 54A0025B1C0E2880004C3CEC /* pwd2key.c */; };
20+
54A002741C0E2880004C3CEC /* sha1.c in Sources */ = {isa = PBXBuildFile; fileRef = 54A0025D1C0E2880004C3CEC /* sha1.c */; };
21+
54A002751C0E2880004C3CEC /* ioapi.c in Sources */ = {isa = PBXBuildFile; fileRef = 54A002621C0E2880004C3CEC /* ioapi.c */; };
22+
54A002761C0E2880004C3CEC /* mztools.c in Sources */ = {isa = PBXBuildFile; fileRef = 54A002641C0E2880004C3CEC /* mztools.c */; };
23+
54A002771C0E2880004C3CEC /* unzip.c in Sources */ = {isa = PBXBuildFile; fileRef = 54A002661C0E2880004C3CEC /* unzip.c */; };
24+
54A002781C0E2880004C3CEC /* zip.c in Sources */ = {isa = PBXBuildFile; fileRef = 54A002681C0E2880004C3CEC /* zip.c */; };
25+
54A002791C0E2880004C3CEC /* SSZipArchive.m in Sources */ = {isa = PBXBuildFile; fileRef = 54A0026B1C0E2880004C3CEC /* SSZipArchive.m */; };
1226
54FFEDE01BF550630061DD23 /* CodePushDownloadHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 54FFEDDF1BF550630061DD23 /* CodePushDownloadHandler.m */; };
1327
810D4E6D1B96935000B397E9 /* CodePushPackage.m in Sources */ = {isa = PBXBuildFile; fileRef = 810D4E6C1B96935000B397E9 /* CodePushPackage.m */; };
1428
81D51F3A1B6181C2000DA084 /* CodePushConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 81D51F391B6181C2000DA084 /* CodePushConfig.m */; };
@@ -31,6 +45,39 @@
3145
13BE3DEC1AC21097009241FE /* CodePush.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodePush.h; sourceTree = "<group>"; };
3246
13BE3DED1AC21097009241FE /* CodePush.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CodePush.m; sourceTree = "<group>"; };
3347
1B23B9131BF9267B000BB2F0 /* RCTConvert+CodePushInstallMode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTConvert+CodePushInstallMode.m"; sourceTree = "<group>"; };
48+
54A0024A1C0E2880004C3CEC /* aes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aes.h; sourceTree = "<group>"; };
49+
54A0024B1C0E2880004C3CEC /* aes_via_ace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aes_via_ace.h; sourceTree = "<group>"; };
50+
54A0024C1C0E2880004C3CEC /* aescrypt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aescrypt.c; sourceTree = "<group>"; };
51+
54A0024D1C0E2880004C3CEC /* aeskey.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aeskey.c; sourceTree = "<group>"; };
52+
54A0024E1C0E2880004C3CEC /* aesopt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aesopt.h; sourceTree = "<group>"; };
53+
54A0024F1C0E2880004C3CEC /* aestab.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aestab.c; sourceTree = "<group>"; };
54+
54A002501C0E2880004C3CEC /* aestab.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aestab.h; sourceTree = "<group>"; };
55+
54A002511C0E2880004C3CEC /* brg_endian.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = brg_endian.h; sourceTree = "<group>"; };
56+
54A002521C0E2880004C3CEC /* brg_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = brg_types.h; sourceTree = "<group>"; };
57+
54A002531C0E2880004C3CEC /* entropy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = entropy.c; sourceTree = "<group>"; };
58+
54A002541C0E2880004C3CEC /* entropy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = entropy.h; sourceTree = "<group>"; };
59+
54A002551C0E2880004C3CEC /* fileenc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fileenc.c; sourceTree = "<group>"; };
60+
54A002561C0E2880004C3CEC /* fileenc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fileenc.h; sourceTree = "<group>"; };
61+
54A002571C0E2880004C3CEC /* hmac.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hmac.c; sourceTree = "<group>"; };
62+
54A002581C0E2880004C3CEC /* hmac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hmac.h; sourceTree = "<group>"; };
63+
54A002591C0E2880004C3CEC /* prng.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = prng.c; sourceTree = "<group>"; };
64+
54A0025A1C0E2880004C3CEC /* prng.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = prng.h; sourceTree = "<group>"; };
65+
54A0025B1C0E2880004C3CEC /* pwd2key.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pwd2key.c; sourceTree = "<group>"; };
66+
54A0025C1C0E2880004C3CEC /* pwd2key.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pwd2key.h; sourceTree = "<group>"; };
67+
54A0025D1C0E2880004C3CEC /* sha1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sha1.c; sourceTree = "<group>"; };
68+
54A0025E1C0E2880004C3CEC /* sha1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sha1.h; sourceTree = "<group>"; };
69+
54A0025F1C0E2880004C3CEC /* Common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Common.h; sourceTree = "<group>"; };
70+
54A002611C0E2880004C3CEC /* crypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypt.h; sourceTree = "<group>"; };
71+
54A002621C0E2880004C3CEC /* ioapi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioapi.c; sourceTree = "<group>"; };
72+
54A002631C0E2880004C3CEC /* ioapi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ioapi.h; sourceTree = "<group>"; };
73+
54A002641C0E2880004C3CEC /* mztools.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mztools.c; sourceTree = "<group>"; };
74+
54A002651C0E2880004C3CEC /* mztools.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mztools.h; sourceTree = "<group>"; };
75+
54A002661C0E2880004C3CEC /* unzip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = unzip.c; sourceTree = "<group>"; };
76+
54A002671C0E2880004C3CEC /* unzip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = unzip.h; sourceTree = "<group>"; };
77+
54A002681C0E2880004C3CEC /* zip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zip.c; sourceTree = "<group>"; };
78+
54A002691C0E2880004C3CEC /* zip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zip.h; sourceTree = "<group>"; };
79+
54A0026A1C0E2880004C3CEC /* SSZipArchive.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SSZipArchive.h; sourceTree = "<group>"; };
80+
54A0026B1C0E2880004C3CEC /* SSZipArchive.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SSZipArchive.m; sourceTree = "<group>"; };
3481
54FFEDDF1BF550630061DD23 /* CodePushDownloadHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CodePushDownloadHandler.m; sourceTree = "<group>"; };
3582
810D4E6C1B96935000B397E9 /* CodePushPackage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CodePushPackage.m; sourceTree = "<group>"; };
3683
81D51F391B6181C2000DA084 /* CodePushConfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CodePushConfig.m; sourceTree = "<group>"; };
@@ -55,9 +102,66 @@
55102
name = Products;
56103
sourceTree = "<group>";
57104
};
105+
54A002481C0E2880004C3CEC /* SSZipArchive */ = {
106+
isa = PBXGroup;
107+
children = (
108+
54A002491C0E2880004C3CEC /* aes */,
109+
54A0025F1C0E2880004C3CEC /* Common.h */,
110+
54A002601C0E2880004C3CEC /* minizip */,
111+
54A0026A1C0E2880004C3CEC /* SSZipArchive.h */,
112+
54A0026B1C0E2880004C3CEC /* SSZipArchive.m */,
113+
);
114+
path = SSZipArchive;
115+
sourceTree = "<group>";
116+
};
117+
54A002491C0E2880004C3CEC /* aes */ = {
118+
isa = PBXGroup;
119+
children = (
120+
54A0024A1C0E2880004C3CEC /* aes.h */,
121+
54A0024B1C0E2880004C3CEC /* aes_via_ace.h */,
122+
54A0024C1C0E2880004C3CEC /* aescrypt.c */,
123+
54A0024D1C0E2880004C3CEC /* aeskey.c */,
124+
54A0024E1C0E2880004C3CEC /* aesopt.h */,
125+
54A0024F1C0E2880004C3CEC /* aestab.c */,
126+
54A002501C0E2880004C3CEC /* aestab.h */,
127+
54A002511C0E2880004C3CEC /* brg_endian.h */,
128+
54A002521C0E2880004C3CEC /* brg_types.h */,
129+
54A002531C0E2880004C3CEC /* entropy.c */,
130+
54A002541C0E2880004C3CEC /* entropy.h */,
131+
54A002551C0E2880004C3CEC /* fileenc.c */,
132+
54A002561C0E2880004C3CEC /* fileenc.h */,
133+
54A002571C0E2880004C3CEC /* hmac.c */,
134+
54A002581C0E2880004C3CEC /* hmac.h */,
135+
54A002591C0E2880004C3CEC /* prng.c */,
136+
54A0025A1C0E2880004C3CEC /* prng.h */,
137+
54A0025B1C0E2880004C3CEC /* pwd2key.c */,
138+
54A0025C1C0E2880004C3CEC /* pwd2key.h */,
139+
54A0025D1C0E2880004C3CEC /* sha1.c */,
140+
54A0025E1C0E2880004C3CEC /* sha1.h */,
141+
);
142+
path = aes;
143+
sourceTree = "<group>";
144+
};
145+
54A002601C0E2880004C3CEC /* minizip */ = {
146+
isa = PBXGroup;
147+
children = (
148+
54A002611C0E2880004C3CEC /* crypt.h */,
149+
54A002621C0E2880004C3CEC /* ioapi.c */,
150+
54A002631C0E2880004C3CEC /* ioapi.h */,
151+
54A002641C0E2880004C3CEC /* mztools.c */,
152+
54A002651C0E2880004C3CEC /* mztools.h */,
153+
54A002661C0E2880004C3CEC /* unzip.c */,
154+
54A002671C0E2880004C3CEC /* unzip.h */,
155+
54A002681C0E2880004C3CEC /* zip.c */,
156+
54A002691C0E2880004C3CEC /* zip.h */,
157+
);
158+
path = minizip;
159+
sourceTree = "<group>";
160+
};
58161
58B511D21A9E6C8500147676 = {
59162
isa = PBXGroup;
60163
children = (
164+
54A002481C0E2880004C3CEC /* SSZipArchive */,
61165
1B23B9131BF9267B000BB2F0 /* RCTConvert+CodePushInstallMode.m */,
62166
54FFEDDF1BF550630061DD23 /* CodePushDownloadHandler.m */,
63167
810D4E6C1B96935000B397E9 /* CodePushPackage.m */,
@@ -95,7 +199,7 @@
95199
isa = PBXProject;
96200
attributes = {
97201
LastUpgradeCheck = 0610;
98-
ORGANIZATIONNAME = Facebook;
202+
ORGANIZATIONNAME = Microsoft;
99203
TargetAttributes = {
100204
58B511DA1A9E6C8500147676 = {
101205
CreatedOnToolsVersion = 6.1.1;
@@ -124,10 +228,24 @@
124228
isa = PBXSourcesBuildPhase;
125229
buildActionMask = 2147483647;
126230
files = (
231+
54A0026D1C0E2880004C3CEC /* aeskey.c in Sources */,
232+
54A0026E1C0E2880004C3CEC /* aestab.c in Sources */,
233+
54A002761C0E2880004C3CEC /* mztools.c in Sources */,
234+
54A002781C0E2880004C3CEC /* zip.c in Sources */,
235+
54A002791C0E2880004C3CEC /* SSZipArchive.m in Sources */,
127236
1B23B9141BF9267B000BB2F0 /* RCTConvert+CodePushInstallMode.m in Sources */,
128237
81D51F3A1B6181C2000DA084 /* CodePushConfig.m in Sources */,
238+
54A002741C0E2880004C3CEC /* sha1.c in Sources */,
129239
54FFEDE01BF550630061DD23 /* CodePushDownloadHandler.m in Sources */,
240+
54A002711C0E2880004C3CEC /* hmac.c in Sources */,
241+
54A002721C0E2880004C3CEC /* prng.c in Sources */,
242+
54A002731C0E2880004C3CEC /* pwd2key.c in Sources */,
243+
54A002751C0E2880004C3CEC /* ioapi.c in Sources */,
244+
54A002771C0E2880004C3CEC /* unzip.c in Sources */,
245+
54A0026F1C0E2880004C3CEC /* entropy.c in Sources */,
130246
13BE3DEE1AC21097009241FE /* CodePush.m in Sources */,
247+
54A0026C1C0E2880004C3CEC /* aescrypt.c in Sources */,
248+
54A002701C0E2880004C3CEC /* fileenc.c in Sources */,
131249
810D4E6D1B96935000B397E9 /* CodePushPackage.m in Sources */,
132250
);
133251
runOnlyForDeploymentPostprocessing = 0;
@@ -220,7 +338,10 @@
220338
"$(SRCROOT)/../react-native/React/**",
221339
);
222340
LIBRARY_SEARCH_PATHS = "$(inherited)";
223-
OTHER_LDFLAGS = "-ObjC";
341+
OTHER_LDFLAGS = (
342+
"-ObjC",
343+
"-lz",
344+
);
224345
PRODUCT_NAME = CodePush;
225346
SKIP_INSTALL = YES;
226347
};
@@ -237,7 +358,10 @@
237358
"$(SRCROOT)/../react-native/React/**",
238359
);
239360
LIBRARY_SEARCH_PATHS = "$(inherited)";
240-
OTHER_LDFLAGS = "-ObjC";
361+
OTHER_LDFLAGS = (
362+
"-ObjC",
363+
"-lz",
364+
);
241365
PRODUCT_NAME = CodePush;
242366
SKIP_INSTALL = YES;
243367
};

CodePushDownloadHandler.m

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
#import "CodePush.h"
22

3-
@implementation CodePushDownloadHandler
3+
@implementation CodePushDownloadHandler {
4+
// Header chars used to determine if the file is a zip.
5+
char _header[4];
6+
}
47

58
- (id)init:(NSString *)downloadFilePath
6-
progressCallback:(void (^)(long, long))progressCallback
7-
doneCallback:(void (^)())doneCallback
9+
progressCallback:(void (^)(long long, long long))progressCallback
10+
doneCallback:(void (^)(BOOL))doneCallback
811
failCallback:(void (^)(NSError *err))failCallback {
912
self.outputFileStream = [NSOutputStream outputStreamToFileAtPath:downloadFilePath
1013
append:NO];
@@ -42,6 +45,18 @@ -(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLRespons
4245
}
4346

4447
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
48+
if (self.receivedContentLength < 4) {
49+
for (int i = 0; i < [data length]; i++) {
50+
int headerOffset = (int)self.receivedContentLength + i;
51+
if (headerOffset >= 4) {
52+
break;
53+
}
54+
55+
const char *bytes = [data bytes];
56+
_header[headerOffset] = bytes[i];
57+
}
58+
}
59+
4560
self.receivedContentLength = self.receivedContentLength + [data length];
4661

4762
NSInteger bytesLeft = [data length];
@@ -79,7 +94,8 @@ -(void)connectionDidFinishLoading:(NSURLConnection *)connection {
7994
assert(self.receivedContentLength == self.expectedContentLength);
8095

8196
[self.outputFileStream close];
82-
self.doneCallback();
97+
BOOL isZip = _header[0] == 'P' && _header[1] == 'K' && _header[2] == 3 && _header[3] == 4;
98+
self.doneCallback(isZip);
8399
}
84100

85101
@end

0 commit comments

Comments
 (0)