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
package/tests/tests.js ADDED
@@ -0,0 +1,255 @@
1
+ exports.defineAutoTests = function() {
2
+
3
+ jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000;
4
+
5
+ describe('cronapp-cordova-plugin-contentsync', function() {
6
+
7
+ it("should exist", function() {
8
+ expect(window.ContentSync).toBeDefined();
9
+ expect(typeof window.ContentSync.sync == 'function').toBe(true);
10
+ expect(typeof window.ContentSync.download == 'function').toBe(true);
11
+ expect(typeof window.ContentSync.unzip == 'function').toBe(true);
12
+ });
13
+
14
+ function syncArchive(url, done) {
15
+
16
+ var progressEvent = null;
17
+ var sync = ContentSync.sync({ src: url, id: 'myapps/myapp', type: 'replace', copyCordovaAssets: false, headers: false });
18
+
19
+
20
+ sync.on('progress', function(progress) {
21
+ //console.log("in progress callback " + Object.getOwnPropertyNames(progress));
22
+ //console.log("onProgress :: " + progress.progress + " status = " + progress.status);
23
+ if(!progressEvent) {
24
+ progressEvent = progress;
25
+ }
26
+ });
27
+
28
+ sync.on('complete', function(data) {
29
+ //console.log("progress = " + progressEvent);
30
+ expect(progressEvent).toBeDefined("Progress should have been received");
31
+
32
+ //console.log("progressEvent.status = " + progressEvent.status);
33
+ expect(progressEvent.status).toBeDefined("Progress event should have a status prop");
34
+
35
+ expect(progressEvent.progress).toBeDefined("Progress event should have a progress prop");
36
+ //console.log("progressEvent.progress = " + progressEvent.progress);
37
+
38
+ //console.log("data = " + data);
39
+ expect(data).toBeDefined("On complete, data is not null");
40
+ done();
41
+ });
42
+
43
+ sync.on('error', function (e) {
44
+ expect(progressEvent).toBeDefined("Progress should have been received");
45
+ expect(e).toBe(null, "Error callback was called :: " + JSON.stringify(e));
46
+ //console.log("got error back :: " + e);
47
+ done();
48
+ });
49
+
50
+ }
51
+
52
+ it("can sync archive without www folder at root", function(done){
53
+ var url = "http://localhost:4321/www1.zip";
54
+ syncArchive(url, done);
55
+ }, 60000); // wait a full 60 secs
56
+
57
+ it("can sync archive with www folder at root", function(done){
58
+ var url = "http://localhost:4321/www2.zip";
59
+ syncArchive(url, done);
60
+ }, 60000); // wait a full 60 secs
61
+
62
+ it('reports error on 404', function(done){
63
+ var sync = ContentSync.sync({
64
+ src: 'https://www.google.com/error/not/found.zip',
65
+ id: 'test' + (new Date().getTime()), // ensure that repeated tests work
66
+ type: 'replace',
67
+ copyCordovaAssets: false
68
+ });
69
+ sync.on('complete', function() {
70
+ fail('404 page should not complete');
71
+ done();
72
+ });
73
+
74
+ sync.on('error', function(e) {
75
+ expect(e).toBeDefined('error should be reported');
76
+ done();
77
+ });
78
+ }, 60000); // wait a full 60 secs for slow Android emulator
79
+
80
+ it('tests copyCordovaAssets works without copyRootApp', function(done) {
81
+ var appId = 'copyCordovaAssets' + (new Date().getTime());
82
+ var sync = ContentSync.sync({
83
+ id: appId,
84
+ copyCordovaAssets: true,
85
+ type: 'local'
86
+ });
87
+
88
+ sync.on('complete', function(data) {
89
+ // cordova.js should be available in the synced directory
90
+ testFileExists(appId + '/cordova.js', function success() {
91
+ done();
92
+ }, function fail() {
93
+ fail('cordova.js should exist in the synced directory.');
94
+ });
95
+ });
96
+ });
97
+
98
+ /**
99
+ * Helper function that tests if the file at the given path exists
100
+ */
101
+ function testFileExists(path, success, fail) {
102
+ var filePath;
103
+ if (path.indexOf('file://') === 0) {
104
+ // test via system url
105
+ filePath = path;
106
+ } else {
107
+ // test via cordova.file.dataDirectory location
108
+ filePath = cordova.file.dataDirectory + '/' + path;
109
+ }
110
+ window.resolveLocalFileSystemURL(filePath, function(fileEntry) {
111
+ expect(fileEntry).toBeDefined();
112
+ success();
113
+ }, function(e){
114
+ fail(path + ' should exist in local copy. Error code ' + e.code);
115
+ });
116
+ }
117
+
118
+ /**
119
+ * Helper function that syncs and test if the local copy has the `/index.html`
120
+ */
121
+ function syncAndTest(appId, useLocalPath, success, fail) {
122
+ var sync = ContentSync.sync({
123
+ id: appId,
124
+ type: 'local',
125
+ copyRootApp: true
126
+ });
127
+ sync.on('complete', function (data) {
128
+ if (useLocalPath && cordova.platformId !== 'windows') {
129
+ testFileExists('file://' + data.localPath + '/index.html', success, fail);
130
+ } else {
131
+ testFileExists(appId + '/index.html', success, fail);
132
+ }
133
+ });
134
+ sync.on('error', function (e) {
135
+ fail();
136
+ });
137
+ }
138
+
139
+ /**
140
+ * Tests if the local copy is at the correct place and can be accessed via file plugin.
141
+ */
142
+ it('local copy is accessible via file plugin', function(done) {
143
+ var appId = 'test' + (new Date()).getTime(); // create new id every time
144
+ syncAndTest(appId, false, done, function(e){
145
+ fail(e);
146
+ done();
147
+ })
148
+ }, 60000); // wait a full 60 secs for slow Android emulator
149
+
150
+ it('create local copy with www prefix', function(done) {
151
+ var appId = 'www/local/test' + (new Date()).getTime(); // create new id every time
152
+ syncAndTest(appId, true, done, function(e){
153
+ fail(e);
154
+ done();
155
+ })
156
+ }, 60000); // wait a full 60 secs for slow Android emulator
157
+
158
+ it('create local copy with www suffix', function(done) {
159
+ var appId = 'local/test' + (new Date()).getTime() + '/www'; // create new id every time
160
+ syncAndTest(appId, true, done, function(e){
161
+ fail(e);
162
+ done();
163
+ })
164
+ }, 60000); // wait a full 60 secs for slow Android emulator
165
+
166
+ /**
167
+ * Test for invalid server name
168
+ */
169
+ it('error on invalid server name', function(done) {
170
+ var sync = ContentSync.sync({
171
+ src: 'http://servername',
172
+ id: 'test' + (new Date().getTime()), // ensure that repeated tests work
173
+ type: 'replace',
174
+ copyCordovaAssets: false
175
+ });
176
+ sync.on('complete', function() {
177
+ fail('invalid server name should not complete');
178
+ done();
179
+ });
180
+
181
+ sync.on('error', function(e) {
182
+ expect(e).toBeDefined('error should be reported');
183
+ done();
184
+ });
185
+ });
186
+
187
+ });
188
+
189
+
190
+ if(cordova.platformId == 'windows') {
191
+ describe('CronApp/cronapp-cordova-plugin-contentsync windows tests', function() {
192
+ it("Has linked C# code", function(done){
193
+ //
194
+ expect(ZipWinProj).toBeDefined("ZipWinProj should exist");
195
+ expect(ZipWinProj.PGZipInflate)
196
+ .toBeDefined("ZipWinProj.PGZipInflate should exist");
197
+ expect(ZipWinProj.PGZipInflate.inflateAsync)
198
+ .toBeDefined("ZipWinProj.PGZipInflate.inflateAsync should exist");
199
+ done();
200
+ });
201
+
202
+ });
203
+ }
204
+
205
+ if (cordova.platformId === 'osx') {
206
+ it("syncing the same id concurrently should fail", function(done) {
207
+
208
+ var url = "https://github.com/timkim/zipTest/archive/master.zip";
209
+ var sync1 = ContentSync.sync({
210
+ src: url,
211
+ id: 'myapps/myapp',
212
+ type: 'replace',
213
+ copyCordovaAssets: false,
214
+ headers: false
215
+ });
216
+ var sync2 = ContentSync.sync({
217
+ src: url,
218
+ id: 'myapps/myapp',
219
+ type: 'replace',
220
+ copyCordovaAssets: false,
221
+ headers: false
222
+ });
223
+
224
+ var numFinished = 0;
225
+
226
+ sync1.on('complete', function(data) {
227
+ expect(data).toBeDefined("On complete, data is not null");
228
+ if (++numFinished == 2) {
229
+ done();
230
+ }
231
+ });
232
+ sync1.on('error', function(e) {
233
+ fail(e);
234
+ done();
235
+ });
236
+
237
+ sync2.on('complete', function(data) {
238
+ fail('syncing concurrently the same id should fail.');
239
+ done();
240
+ });
241
+ sync2.on('error', function(e) {
242
+ expect(e).toEqual(5);
243
+ if (++numFinished == 2) {
244
+ done();
245
+ }
246
+ });
247
+
248
+ }, 60000); // wait a full 60 secs
249
+ }
250
+
251
+ };
252
+
253
+ exports.defineManualTests = function() {
254
+
255
+ };
package/www/index.js ADDED
@@ -0,0 +1,285 @@
1
+ /* global cordova:false */
2
+
3
+ /*!
4
+ * Module dependencies.
5
+ */
6
+
7
+ var exec = cordova.require('cordova/exec');
8
+
9
+ /**
10
+ * ContentSync constructor.
11
+ *
12
+ * @param {Object} options to initiate a new content synchronization.
13
+ * @param {String} src is a URL to the content sync end-point.
14
+ * @param {String} id is used as a unique identifier for the sync operation
15
+ * @param {Object} type defines the sync strategy applied to the content.
16
+ * @param {String} replace completely removes existing content then copies new content.
17
+ * @param {String} merge does not modify existing content, but adds new content.
18
+ * @param {Object} headers are used to set the headers for when we send a request to the src URL
19
+ * @param {Boolean} validateSrc whether to validate src url with a HEAD request before download (ios only, default true).
20
+ * @return {ContentSync} instance that can be monitored and cancelled.
21
+ */
22
+
23
+ var ContentSync = function(options) {
24
+ this._handlers = {
25
+ 'progress': [],
26
+ 'cancel': [],
27
+ 'error': [],
28
+ 'complete': []
29
+ };
30
+
31
+ // require options parameter
32
+ if (typeof options === 'undefined') {
33
+ throw new Error('The options argument is required.');
34
+ }
35
+
36
+ // require options.src parameter
37
+ if (typeof options.src === 'undefined' && options.type !== "local") {
38
+ throw new Error('The options.src argument is required for merge replace types.');
39
+ }
40
+
41
+ // require options.id parameter
42
+ if (typeof options.id === 'undefined') {
43
+ throw new Error('The options.id argument is required.');
44
+ }
45
+
46
+ // define synchronization strategy
47
+ //
48
+ // replace: This is the normal behavior. Existing content is replaced
49
+ // completely by the imported content, i.e. is overridden or
50
+ // deleted accordingly.
51
+ // merge: Existing content is not modified, i.e. only new content is
52
+ // added and none is deleted or modified.
53
+ // local: Existing content is not modified, i.e. only new content is
54
+ // added and none is deleted or modified.
55
+ //
56
+ if (typeof options.type === 'undefined') {
57
+ options.type = 'replace';
58
+ }
59
+
60
+ if (typeof options.headers === 'undefined') {
61
+ options.headers = null;
62
+ }
63
+
64
+ if (typeof options.copyCordovaAssets === 'undefined') {
65
+ options.copyCordovaAssets = false;
66
+ }
67
+
68
+ if (typeof options.copyRootApp === 'undefined') {
69
+ options.copyRootApp = false;
70
+ }
71
+
72
+ if (typeof options.timeout === 'undefined') {
73
+ options.timeout = 15.0;
74
+ }
75
+
76
+ if (typeof options.trustHost === 'undefined') {
77
+ options.trustHost = false;
78
+ }
79
+
80
+ if (typeof options.manifest === 'undefined') {
81
+ options.manifest = "";
82
+ }
83
+
84
+ if (typeof options.validateSrc === 'undefined') {
85
+ options.validateSrc = true;
86
+ }
87
+
88
+ // store the options to this object instance
89
+ this.options = options;
90
+
91
+ // triggered on update and completion
92
+ var that = this;
93
+ var success = function(result) {
94
+ if (result && typeof result.progress !== 'undefined') {
95
+ that.emit('progress', result);
96
+ } else if (result && typeof result.localPath !== 'undefined') {
97
+ that.emit('complete', result);
98
+ }
99
+ };
100
+
101
+ // triggered on error
102
+ var fail = function(msg) {
103
+ var e = (typeof msg === 'string') ? new Error(msg) : msg;
104
+ that.emit('error', e);
105
+ };
106
+
107
+ // wait at least one process tick to allow event subscriptions
108
+ setTimeout(function() {
109
+ exec(success, fail, 'Sync', 'sync', [options.src, options.id, options.type, options.headers, options.copyCordovaAssets, options.copyRootApp, options.timeout, options.trustHost, options.manifest, options.validateSrc]);
110
+ }, 10);
111
+ };
112
+
113
+ /**
114
+ * Cancel the Content Sync
115
+ *
116
+ * After successfully canceling the content sync process, the `cancel` event
117
+ * will be emitted.
118
+ */
119
+
120
+ ContentSync.prototype.cancel = function() {
121
+ var that = this;
122
+ var onCancel = function() {
123
+ that.emit('cancel');
124
+ };
125
+ setTimeout(function() {
126
+ exec(onCancel, onCancel, 'Sync', 'cancel', [ that.options.id ]);
127
+ }, 10);
128
+ };
129
+
130
+ /**
131
+ * Listen for an event.
132
+ *
133
+ * The following events are supported:
134
+ *
135
+ * - progress
136
+ * - cancel
137
+ * - error
138
+ * - completion
139
+ *
140
+ * @param {String} eventName to subscribe to.
141
+ * @param {Function} callback triggered on the event.
142
+ */
143
+
144
+ ContentSync.prototype.on = function(eventName, callback) {
145
+ if (this._handlers.hasOwnProperty(eventName)) {
146
+ this._handlers[eventName].push(callback);
147
+ }
148
+ };
149
+
150
+ /**
151
+ * Emit an event.
152
+ *
153
+ * This is intended for internal use only.
154
+ *
155
+ * @param {String} eventName is the event to trigger.
156
+ * @param {*} all arguments are passed to the event listeners.
157
+ *
158
+ * @return {Boolean} is true when the event is triggered otherwise false.
159
+ */
160
+
161
+ ContentSync.prototype.emit = function() {
162
+ var args = Array.prototype.slice.call(arguments);
163
+ var eventName = args.shift();
164
+
165
+ if (!this._handlers.hasOwnProperty(eventName)) {
166
+ return false;
167
+ }
168
+
169
+ for (var i = 0, length = this._handlers[eventName].length; i < length; i++) {
170
+ this._handlers[eventName][i].apply(undefined,args);
171
+ }
172
+
173
+ return true;
174
+ };
175
+
176
+ /*!
177
+ * Content Sync Plugin.
178
+ */
179
+
180
+ module.exports = {
181
+ /**
182
+ * Synchronize the content.
183
+ *
184
+ * This method will instantiate a new copy of the ContentSync object
185
+ * and start synchronizing.
186
+ *
187
+ * @param {Object} options
188
+ * @return {ContentSync} instance
189
+ */
190
+
191
+ sync: function(options) {
192
+ return new ContentSync(options);
193
+ },
194
+
195
+ /**
196
+ * Unzip
197
+ *
198
+ * This call is to replicate Zip::unzip plugin
199
+ *
200
+ */
201
+
202
+ unzip: function(fileUrl, dirUrl, callback, progressCallback) {
203
+ var win = function(result) {
204
+ if (result && result.progress) {
205
+ if (progressCallback) {
206
+ progressCallback(result);
207
+ }
208
+ } else if (callback) {
209
+ callback(0);
210
+ }
211
+ };
212
+ var fail = function(result) {
213
+ if (callback) {
214
+ callback(-1);
215
+ }
216
+ };
217
+ exec(win, fail, 'Zip', 'unzip', [fileUrl, dirUrl]);
218
+ },
219
+
220
+ /**
221
+ * Download
222
+ *
223
+ * This call is to replicate nothing but might be used instead of FileTransfer
224
+ *
225
+ */
226
+
227
+ download: function(url, headers, cb) {
228
+ var callback = (typeof headers == "function" ? headers : cb);
229
+ exec(callback, callback, 'Sync', 'download', [url, null, headers]);
230
+ },
231
+
232
+ /**
233
+ * loadUrl
234
+ *
235
+ * This method allows loading file:// urls when using WKWebViews on iOS.
236
+ *
237
+ */
238
+
239
+ loadUrl: function(url, cb) {
240
+ if(!url) {
241
+ throw new Error('URL is required.');
242
+ }
243
+ exec(cb, cb, 'Sync', 'loadUrl', [url]);
244
+ },
245
+
246
+
247
+ /**
248
+ * ContentSync Object.
249
+ *
250
+ * Expose the ContentSync object for direct use
251
+ * and testing. Typically, you should use the
252
+ * .sync helper method.
253
+ */
254
+
255
+ ContentSync: ContentSync,
256
+
257
+ /**
258
+ * PROGRESS_STATE enumeration.
259
+ *
260
+ * Maps to the `progress` event's `status` object.
261
+ * The plugin user can customize the enumeration's mapped string
262
+ * to a value that's appropriate for their app.
263
+ */
264
+
265
+ PROGRESS_STATE: {
266
+ 0: 'STOPPED',
267
+ 1: 'DOWNLOADING',
268
+ 2: 'EXTRACTING',
269
+ 3: 'COMPLETE'
270
+ },
271
+
272
+ /**
273
+ * ERROR_STATE enumeration.
274
+ *
275
+ * Maps to the `error` event's `status` object.
276
+ * The plugin user can customize the enumeration's mapped string
277
+ * to a value that's appropriate for their app.
278
+ */
279
+
280
+ ERROR_STATE: {
281
+ 1: 'INVALID_URL_ERR',
282
+ 2: 'CONNECTION_ERR',
283
+ 3: 'UNZIP_ERR'
284
+ }
285
+ };