@capgo/capacitor-updater 7.2.20 → 7.3.3
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.
- package/README.md +6 -1
- package/android/src/main/java/ee/forgr/capacitor_updater/BundleInfo.java +48 -26
- package/android/src/main/java/ee/forgr/capacitor_updater/CapacitorUpdaterPlugin.java +152 -141
- package/android/src/main/java/ee/forgr/capacitor_updater/{CapacitorUpdater.java → CapgoUpdater.java} +93 -59
- package/android/src/main/java/ee/forgr/capacitor_updater/CryptoCipherV2.java +13 -8
- package/android/src/main/java/ee/forgr/capacitor_updater/DelayUpdateUtils.java +43 -43
- package/android/src/main/java/ee/forgr/capacitor_updater/DownloadService.java +24 -20
- package/android/src/main/java/ee/forgr/capacitor_updater/DownloadWorkerManager.java +8 -4
- package/android/src/main/java/ee/forgr/capacitor_updater/Logger.java +338 -0
- package/dist/docs.json +16 -0
- package/dist/esm/definitions.d.ts +7 -0
- package/dist/esm/definitions.js.map +1 -1
- package/ios/Plugin/AES.swift +5 -3
- package/ios/Plugin/CapacitorUpdaterPlugin.swift +108 -94
- package/ios/Plugin/{CapacitorUpdater.swift → CapgoUpdater.swift} +71 -69
- package/ios/Plugin/CryptoCipherV2.swift +31 -26
- package/ios/Plugin/DelayUpdateUtils.swift +26 -24
- package/ios/Plugin/Logger.swift +289 -0
- package/ios/Plugin/UserDefaultsExtension.swift +0 -2
- package/package.json +1 -1
package/android/src/main/java/ee/forgr/capacitor_updater/{CapacitorUpdater.java → CapgoUpdater.java}
RENAMED
|
@@ -10,7 +10,6 @@ import android.app.Activity;
|
|
|
10
10
|
import android.content.Context;
|
|
11
11
|
import android.content.SharedPreferences;
|
|
12
12
|
import android.os.Build;
|
|
13
|
-
import android.util.Log;
|
|
14
13
|
import androidx.annotation.NonNull;
|
|
15
14
|
import androidx.lifecycle.LifecycleOwner;
|
|
16
15
|
import androidx.work.Data;
|
|
@@ -40,7 +39,9 @@ import org.json.JSONArray;
|
|
|
40
39
|
import org.json.JSONException;
|
|
41
40
|
import org.json.JSONObject;
|
|
42
41
|
|
|
43
|
-
public class
|
|
42
|
+
public class CapgoUpdater {
|
|
43
|
+
|
|
44
|
+
private final Logger logger;
|
|
44
45
|
|
|
45
46
|
private static final String AB = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
46
47
|
private static final SecureRandom rnd = new SecureRandom();
|
|
@@ -75,6 +76,10 @@ public class CapacitorUpdater {
|
|
|
75
76
|
public String deviceID = "";
|
|
76
77
|
public int timeout = 20000;
|
|
77
78
|
|
|
79
|
+
public CapgoUpdater(Logger logger) {
|
|
80
|
+
this.logger = logger;
|
|
81
|
+
}
|
|
82
|
+
|
|
78
83
|
private final FilenameFilter filter = (f, name) -> {
|
|
79
84
|
// ignore directories generated by mac os x
|
|
80
85
|
return (!name.startsWith("__MACOSX") && !name.startsWith(".") && !name.startsWith(".DS_Store"));
|
|
@@ -143,7 +148,7 @@ public class CapacitorUpdater {
|
|
|
143
148
|
ZipEntry entry;
|
|
144
149
|
while ((entry = zis.getNextEntry()) != null) {
|
|
145
150
|
if (entry.getName().contains("\\")) {
|
|
146
|
-
|
|
151
|
+
logger.error("unzip: Windows path is not supported, please use unix path as require by zip RFC: " + entry.getName());
|
|
147
152
|
this.sendStats("windows_path_fail");
|
|
148
153
|
}
|
|
149
154
|
final File file = new File(targetDirectory, entry.getName());
|
|
@@ -208,7 +213,7 @@ public class CapacitorUpdater {
|
|
|
208
213
|
|
|
209
214
|
private void observeWorkProgress(Context context, String id) {
|
|
210
215
|
if (!(context instanceof LifecycleOwner)) {
|
|
211
|
-
|
|
216
|
+
logger.error("Context is not a LifecycleOwner, cannot observe work progress");
|
|
212
217
|
return;
|
|
213
218
|
}
|
|
214
219
|
|
|
@@ -236,7 +241,7 @@ public class CapacitorUpdater {
|
|
|
236
241
|
|
|
237
242
|
boolean success = finishDownload(id, dest, version, sessionKey, checksum, true, isManifest);
|
|
238
243
|
if (!success) {
|
|
239
|
-
|
|
244
|
+
logger.error("Finish download failed: " + version);
|
|
240
245
|
saveBundleInfo(
|
|
241
246
|
id,
|
|
242
247
|
new BundleInfo(id, version, BundleStatus.ERROR, new Date(System.currentTimeMillis()), "")
|
|
@@ -251,7 +256,7 @@ public class CapacitorUpdater {
|
|
|
251
256
|
case FAILED:
|
|
252
257
|
Data failedData = workInfo.getOutputData();
|
|
253
258
|
String error = failedData.getString(DownloadService.ERROR);
|
|
254
|
-
|
|
259
|
+
logger.error("Download failed: " + error + " " + workInfo.getState());
|
|
255
260
|
String failedVersion = failedData.getString(DownloadService.VERSION);
|
|
256
261
|
saveBundleInfo(
|
|
257
262
|
id,
|
|
@@ -281,7 +286,7 @@ public class CapacitorUpdater {
|
|
|
281
286
|
final JSONArray manifest
|
|
282
287
|
) {
|
|
283
288
|
if (this.activity == null) {
|
|
284
|
-
|
|
289
|
+
logger.error("Activity is null, cannot observe work progress");
|
|
285
290
|
return;
|
|
286
291
|
}
|
|
287
292
|
observeWorkProgress(this.activity, id);
|
|
@@ -326,7 +331,7 @@ public class CapacitorUpdater {
|
|
|
326
331
|
|
|
327
332
|
// If public key is present but no checksum provided, refuse installation
|
|
328
333
|
if (!this.publicKey.isEmpty() && checksumDecrypted.isEmpty()) {
|
|
329
|
-
|
|
334
|
+
logger.error("Public key present but no checksum provided");
|
|
330
335
|
this.sendStats("checksum_required");
|
|
331
336
|
throw new IOException("Checksum required when public key is present: " + id);
|
|
332
337
|
}
|
|
@@ -339,7 +344,7 @@ public class CapacitorUpdater {
|
|
|
339
344
|
checksum = CryptoCipherV2.calcChecksum(downloaded);
|
|
340
345
|
}
|
|
341
346
|
if ((!checksumDecrypted.isEmpty() || !this.publicKey.isEmpty()) && !checksumDecrypted.equals(checksum)) {
|
|
342
|
-
|
|
347
|
+
logger.error("Error checksum '" + checksumDecrypted + "' '" + checksum + "' '");
|
|
343
348
|
this.sendStats("checksum_fail");
|
|
344
349
|
throw new IOException("Checksum failed: " + id);
|
|
345
350
|
}
|
|
@@ -348,14 +353,14 @@ public class CapacitorUpdater {
|
|
|
348
353
|
} catch (Exception e) {
|
|
349
354
|
final Boolean res = this.delete(id);
|
|
350
355
|
if (!res) {
|
|
351
|
-
|
|
356
|
+
logger.info("Double error, cannot cleanup: " + version);
|
|
352
357
|
}
|
|
353
358
|
|
|
354
359
|
final Map<String, Object> ret = new HashMap<>();
|
|
355
|
-
ret.put("version",
|
|
360
|
+
ret.put("version", CapgoUpdater.this.getCurrentBundle().getVersionName());
|
|
356
361
|
|
|
357
|
-
|
|
358
|
-
|
|
362
|
+
CapgoUpdater.this.notifyListeners("downloadFailed", ret);
|
|
363
|
+
CapgoUpdater.this.sendStats("download_fail");
|
|
359
364
|
return false;
|
|
360
365
|
}
|
|
361
366
|
|
|
@@ -378,10 +383,10 @@ public class CapacitorUpdater {
|
|
|
378
383
|
|
|
379
384
|
final Map<String, Object> ret = new HashMap<>();
|
|
380
385
|
ret.put("bundle", next.toJSONMap());
|
|
381
|
-
|
|
386
|
+
CapgoUpdater.this.notifyListeners("updateAvailable", ret);
|
|
382
387
|
if (setNext) {
|
|
383
388
|
if (this.directUpdate) {
|
|
384
|
-
|
|
389
|
+
CapgoUpdater.this.directUpdateFinish(next);
|
|
385
390
|
this.directUpdate = false;
|
|
386
391
|
} else {
|
|
387
392
|
this.setNextBundle(next.getId());
|
|
@@ -390,9 +395,9 @@ public class CapacitorUpdater {
|
|
|
390
395
|
} catch (IOException e) {
|
|
391
396
|
e.printStackTrace();
|
|
392
397
|
final Map<String, Object> ret = new HashMap<>();
|
|
393
|
-
ret.put("version",
|
|
394
|
-
|
|
395
|
-
|
|
398
|
+
ret.put("version", CapgoUpdater.this.getCurrentBundle().getVersionName());
|
|
399
|
+
CapgoUpdater.this.notifyListeners("downloadFailed", ret);
|
|
400
|
+
CapgoUpdater.this.sendStats("download_fail");
|
|
396
401
|
return false;
|
|
397
402
|
}
|
|
398
403
|
return true;
|
|
@@ -414,7 +419,7 @@ public class CapacitorUpdater {
|
|
|
414
419
|
|
|
415
420
|
private void setCurrentBundle(final File bundle) {
|
|
416
421
|
this.editor.putString(this.CAP_SERVER_PATH, bundle.getPath());
|
|
417
|
-
|
|
422
|
+
logger.info("Current bundle set to: " + bundle);
|
|
418
423
|
this.editor.commit();
|
|
419
424
|
}
|
|
420
425
|
|
|
@@ -427,10 +432,18 @@ public class CapacitorUpdater {
|
|
|
427
432
|
) {
|
|
428
433
|
final String id = this.randomString();
|
|
429
434
|
|
|
430
|
-
// Check if version is already downloading
|
|
435
|
+
// Check if version is already downloading, but allow retry if previous download failed
|
|
431
436
|
if (this.activity != null && DownloadWorkerManager.isVersionDownloading(version)) {
|
|
432
|
-
|
|
433
|
-
|
|
437
|
+
// Check if there's an existing bundle with error status that we can retry
|
|
438
|
+
BundleInfo existingBundle = this.getBundleInfoByName(version);
|
|
439
|
+
if (existingBundle != null && existingBundle.isErrorStatus()) {
|
|
440
|
+
// Cancel the failed download and allow retry
|
|
441
|
+
DownloadWorkerManager.cancelVersionDownload(this.activity, version);
|
|
442
|
+
logger.info("Retrying failed download for version: " + version);
|
|
443
|
+
} else {
|
|
444
|
+
logger.info("Version already downloading: " + version);
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
434
447
|
}
|
|
435
448
|
|
|
436
449
|
this.saveBundleInfo(id, new BundleInfo(id, version, BundleStatus.DOWNLOADING, new Date(System.currentTimeMillis()), ""));
|
|
@@ -441,6 +454,13 @@ public class CapacitorUpdater {
|
|
|
441
454
|
}
|
|
442
455
|
|
|
443
456
|
public BundleInfo download(final String url, final String version, final String sessionKey, final String checksum) throws IOException {
|
|
457
|
+
// Check for existing bundle with same version and clean up if in error state
|
|
458
|
+
BundleInfo existingBundle = this.getBundleInfoByName(version);
|
|
459
|
+
if (existingBundle != null && (existingBundle.isErrorStatus() || existingBundle.isDeleted())) {
|
|
460
|
+
logger.info("Found existing failed bundle for version " + version + ", deleting before retry");
|
|
461
|
+
this.delete(existingBundle.getId(), true);
|
|
462
|
+
}
|
|
463
|
+
|
|
444
464
|
final String id = this.randomString();
|
|
445
465
|
this.saveBundleInfo(id, new BundleInfo(id, version, BundleStatus.DOWNLOADING, new Date(System.currentTimeMillis()), ""));
|
|
446
466
|
this.notifyDownload(id, 0);
|
|
@@ -474,7 +494,7 @@ public class CapacitorUpdater {
|
|
|
474
494
|
}
|
|
475
495
|
return getBundleInfo(id);
|
|
476
496
|
} catch (Exception e) {
|
|
477
|
-
|
|
497
|
+
logger.error("Error waiting for download " + e.getMessage());
|
|
478
498
|
saveBundleInfo(id, new BundleInfo(id, version, BundleStatus.ERROR, new Date(System.currentTimeMillis()), ""));
|
|
479
499
|
throw new IOException("Error waiting for download: " + e.getMessage());
|
|
480
500
|
}
|
|
@@ -484,14 +504,14 @@ public class CapacitorUpdater {
|
|
|
484
504
|
if (!rawList) {
|
|
485
505
|
final List<BundleInfo> res = new ArrayList<>();
|
|
486
506
|
final File destHot = new File(this.documentsDir, bundleDirectory);
|
|
487
|
-
|
|
507
|
+
logger.debug("list File : " + destHot.getPath());
|
|
488
508
|
if (destHot.exists()) {
|
|
489
509
|
for (final File i : Objects.requireNonNull(destHot.listFiles())) {
|
|
490
510
|
final String id = i.getName();
|
|
491
511
|
res.add(this.getBundleInfo(id));
|
|
492
512
|
}
|
|
493
513
|
} else {
|
|
494
|
-
|
|
514
|
+
logger.info("No versions available to list" + destHot);
|
|
495
515
|
}
|
|
496
516
|
return res;
|
|
497
517
|
} else {
|
|
@@ -510,12 +530,12 @@ public class CapacitorUpdater {
|
|
|
510
530
|
public Boolean delete(final String id, final Boolean removeInfo) throws IOException {
|
|
511
531
|
final BundleInfo deleted = this.getBundleInfo(id);
|
|
512
532
|
if (deleted.isBuiltin() || this.getCurrentBundleId().equals(id)) {
|
|
513
|
-
|
|
533
|
+
logger.error("Cannot delete " + id);
|
|
514
534
|
return false;
|
|
515
535
|
}
|
|
516
536
|
final BundleInfo next = this.getNextBundle();
|
|
517
537
|
if (next != null && !next.isDeleted() && !next.isErrorStatus() && next.getId().equals(id)) {
|
|
518
|
-
|
|
538
|
+
logger.error("Cannot delete the next bundle" + id);
|
|
519
539
|
return false;
|
|
520
540
|
}
|
|
521
541
|
// Cancel download for this version if active
|
|
@@ -532,7 +552,7 @@ public class CapacitorUpdater {
|
|
|
532
552
|
}
|
|
533
553
|
return true;
|
|
534
554
|
}
|
|
535
|
-
|
|
555
|
+
logger.error("bundle removed: " + deleted.getVersionName());
|
|
536
556
|
// perhaps we did not find the bundle in the files, but if the user requested a delete, we delete
|
|
537
557
|
if (removeInfo) {
|
|
538
558
|
this.removeBundleInfo(id);
|
|
@@ -546,7 +566,7 @@ public class CapacitorUpdater {
|
|
|
546
566
|
return this.delete(id, true);
|
|
547
567
|
} catch (IOException e) {
|
|
548
568
|
e.printStackTrace();
|
|
549
|
-
|
|
569
|
+
logger.info("Failed to delete bundle (" + id + ")" + "\nError:\n" + e.toString());
|
|
550
570
|
return false;
|
|
551
571
|
}
|
|
552
572
|
}
|
|
@@ -572,7 +592,7 @@ public class CapacitorUpdater {
|
|
|
572
592
|
return true;
|
|
573
593
|
}
|
|
574
594
|
final File bundle = this.getBundleDirectory(id);
|
|
575
|
-
|
|
595
|
+
logger.info("Setting next active bundle: " + id);
|
|
576
596
|
if (this.bundleExists(id)) {
|
|
577
597
|
var currentBundleName = this.getCurrentBundle().getVersionName();
|
|
578
598
|
this.setCurrentBundle(bundle);
|
|
@@ -588,7 +608,7 @@ public class CapacitorUpdater {
|
|
|
588
608
|
public void autoReset() {
|
|
589
609
|
final BundleInfo currentBundle = this.getCurrentBundle();
|
|
590
610
|
if (!currentBundle.isBuiltin() && !this.bundleExists(currentBundle.getId())) {
|
|
591
|
-
|
|
611
|
+
logger.info("Folder at bundle path does not exist. Triggering reset.");
|
|
592
612
|
this.reset();
|
|
593
613
|
}
|
|
594
614
|
}
|
|
@@ -600,12 +620,12 @@ public class CapacitorUpdater {
|
|
|
600
620
|
public void setSuccess(final BundleInfo bundle, Boolean autoDeletePrevious) {
|
|
601
621
|
this.setBundleStatus(bundle.getId(), BundleStatus.SUCCESS);
|
|
602
622
|
final BundleInfo fallback = this.getFallbackBundle();
|
|
603
|
-
|
|
604
|
-
|
|
623
|
+
logger.debug("Fallback bundle is: " + fallback);
|
|
624
|
+
logger.info("Version successfully loaded: " + bundle.getVersionName());
|
|
605
625
|
if (autoDeletePrevious && !fallback.isBuiltin()) {
|
|
606
626
|
final Boolean res = this.delete(fallback.getId());
|
|
607
627
|
if (res) {
|
|
608
|
-
|
|
628
|
+
logger.info("Deleted previous bundle: " + fallback.getVersionName());
|
|
609
629
|
}
|
|
610
630
|
}
|
|
611
631
|
this.setFallbackBundle(bundle);
|
|
@@ -616,7 +636,7 @@ public class CapacitorUpdater {
|
|
|
616
636
|
}
|
|
617
637
|
|
|
618
638
|
public void reset(final boolean internal) {
|
|
619
|
-
|
|
639
|
+
logger.debug("reset: " + internal);
|
|
620
640
|
var currentBundleName = this.getCurrentBundle().getVersionName();
|
|
621
641
|
this.setCurrentBundle(new File("public"));
|
|
622
642
|
this.setFallbackBundle(null);
|
|
@@ -712,7 +732,7 @@ public class CapacitorUpdater {
|
|
|
712
732
|
json.put("defaultChannel", channel);
|
|
713
733
|
}
|
|
714
734
|
} catch (JSONException e) {
|
|
715
|
-
|
|
735
|
+
logger.error("Error getLatest JSONException " + e.getMessage());
|
|
716
736
|
final Map<String, Object> retError = new HashMap<>();
|
|
717
737
|
retError.put("message", "Cannot get info: " + e);
|
|
718
738
|
retError.put("error", "json_error");
|
|
@@ -720,7 +740,7 @@ public class CapacitorUpdater {
|
|
|
720
740
|
return;
|
|
721
741
|
}
|
|
722
742
|
|
|
723
|
-
|
|
743
|
+
logger.info("Auto-update parameters: " + json);
|
|
724
744
|
|
|
725
745
|
makeJsonRequest(updateUrl, json, callback);
|
|
726
746
|
}
|
|
@@ -728,7 +748,7 @@ public class CapacitorUpdater {
|
|
|
728
748
|
public void unsetChannel(final Callback callback) {
|
|
729
749
|
String channelUrl = this.channelUrl;
|
|
730
750
|
if (channelUrl == null || channelUrl.isEmpty()) {
|
|
731
|
-
|
|
751
|
+
logger.error("Channel URL is not set");
|
|
732
752
|
final Map<String, Object> retError = new HashMap<>();
|
|
733
753
|
retError.put("message", "channelUrl missing");
|
|
734
754
|
retError.put("error", "missing_config");
|
|
@@ -739,7 +759,7 @@ public class CapacitorUpdater {
|
|
|
739
759
|
try {
|
|
740
760
|
json = this.createInfoObject();
|
|
741
761
|
} catch (JSONException e) {
|
|
742
|
-
|
|
762
|
+
logger.error("Error unsetChannel JSONException " + e.getMessage());
|
|
743
763
|
final Map<String, Object> retError = new HashMap<>();
|
|
744
764
|
retError.put("message", "Cannot get info: " + e);
|
|
745
765
|
retError.put("error", "json_error");
|
|
@@ -787,7 +807,7 @@ public class CapacitorUpdater {
|
|
|
787
807
|
ret.put(key, jsonResponse.get(key));
|
|
788
808
|
}
|
|
789
809
|
}
|
|
790
|
-
|
|
810
|
+
logger.info("Channel unset");
|
|
791
811
|
callback.callback(ret);
|
|
792
812
|
} catch (JSONException e) {
|
|
793
813
|
Map<String, Object> retError = new HashMap<>();
|
|
@@ -803,7 +823,7 @@ public class CapacitorUpdater {
|
|
|
803
823
|
public void setChannel(final String channel, final Callback callback) {
|
|
804
824
|
String channelUrl = this.channelUrl;
|
|
805
825
|
if (channelUrl == null || channelUrl.isEmpty()) {
|
|
806
|
-
|
|
826
|
+
logger.error("Channel URL is not set");
|
|
807
827
|
final Map<String, Object> retError = new HashMap<>();
|
|
808
828
|
retError.put("message", "channelUrl missing");
|
|
809
829
|
retError.put("error", "missing_config");
|
|
@@ -815,7 +835,7 @@ public class CapacitorUpdater {
|
|
|
815
835
|
json = this.createInfoObject();
|
|
816
836
|
json.put("channel", channel);
|
|
817
837
|
} catch (JSONException e) {
|
|
818
|
-
|
|
838
|
+
logger.error("Error setChannel JSONException " + e.getMessage());
|
|
819
839
|
final Map<String, Object> retError = new HashMap<>();
|
|
820
840
|
retError.put("message", "Cannot get info: " + e);
|
|
821
841
|
retError.put("error", "json_error");
|
|
@@ -829,7 +849,7 @@ public class CapacitorUpdater {
|
|
|
829
849
|
public void getChannel(final Callback callback) {
|
|
830
850
|
String channelUrl = this.channelUrl;
|
|
831
851
|
if (channelUrl == null || channelUrl.isEmpty()) {
|
|
832
|
-
|
|
852
|
+
logger.error("Channel URL is not set");
|
|
833
853
|
final Map<String, Object> retError = new HashMap<>();
|
|
834
854
|
retError.put("message", "Channel URL is not set");
|
|
835
855
|
retError.put("error", "missing_config");
|
|
@@ -840,7 +860,7 @@ public class CapacitorUpdater {
|
|
|
840
860
|
try {
|
|
841
861
|
json = this.createInfoObject();
|
|
842
862
|
} catch (JSONException e) {
|
|
843
|
-
|
|
863
|
+
logger.error("Error getChannel JSONException " + e.getMessage());
|
|
844
864
|
final Map<String, Object> retError = new HashMap<>();
|
|
845
865
|
retError.put("message", "Cannot get info: " + e);
|
|
846
866
|
retError.put("error", "json_error");
|
|
@@ -875,7 +895,7 @@ public class CapacitorUpdater {
|
|
|
875
895
|
Map<String, Object> ret = new HashMap<>();
|
|
876
896
|
ret.put("channel", defaultChannel);
|
|
877
897
|
ret.put("status", "default");
|
|
878
|
-
|
|
898
|
+
logger.info("Channel get to \"" + ret);
|
|
879
899
|
callback.callback(ret);
|
|
880
900
|
return;
|
|
881
901
|
}
|
|
@@ -901,7 +921,7 @@ public class CapacitorUpdater {
|
|
|
901
921
|
ret.put(key, jsonResponse.get(key));
|
|
902
922
|
}
|
|
903
923
|
}
|
|
904
|
-
|
|
924
|
+
logger.info("Channel get to \"" + ret);
|
|
905
925
|
callback.callback(ret);
|
|
906
926
|
} catch (JSONException e) {
|
|
907
927
|
Map<String, Object> retError = new HashMap<>();
|
|
@@ -934,7 +954,7 @@ public class CapacitorUpdater {
|
|
|
934
954
|
json.put("old_version_name", oldVersionName);
|
|
935
955
|
json.put("action", action);
|
|
936
956
|
} catch (JSONException e) {
|
|
937
|
-
|
|
957
|
+
logger.error("Error sendStats JSONException " + e.getMessage());
|
|
938
958
|
return;
|
|
939
959
|
}
|
|
940
960
|
|
|
@@ -949,15 +969,15 @@ public class CapacitorUpdater {
|
|
|
949
969
|
new okhttp3.Callback() {
|
|
950
970
|
@Override
|
|
951
971
|
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
|
952
|
-
|
|
972
|
+
logger.error("Failed to send stats: " + e.getMessage());
|
|
953
973
|
}
|
|
954
974
|
|
|
955
975
|
@Override
|
|
956
976
|
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
|
|
957
977
|
if (response.isSuccessful()) {
|
|
958
|
-
|
|
978
|
+
logger.info("Stats send for \"" + action + "\", version " + versionName);
|
|
959
979
|
} else {
|
|
960
|
-
|
|
980
|
+
logger.error("Error sending stats: " + response.code());
|
|
961
981
|
}
|
|
962
982
|
}
|
|
963
983
|
}
|
|
@@ -977,13 +997,26 @@ public class CapacitorUpdater {
|
|
|
977
997
|
} else {
|
|
978
998
|
try {
|
|
979
999
|
String stored = this.prefs.getString(trueId + INFO_SUFFIX, "");
|
|
980
|
-
|
|
1000
|
+
if (stored.isEmpty()) {
|
|
1001
|
+
result = new BundleInfo(trueId, null, BundleStatus.PENDING, "", "");
|
|
1002
|
+
} else {
|
|
1003
|
+
result = BundleInfo.fromJSON(stored);
|
|
1004
|
+
}
|
|
981
1005
|
} catch (JSONException e) {
|
|
982
|
-
|
|
983
|
-
|
|
1006
|
+
logger.error(
|
|
1007
|
+
"Failed to parse info for bundle [" +
|
|
1008
|
+
trueId +
|
|
1009
|
+
"] stored value: '" +
|
|
1010
|
+
this.prefs.getString(trueId + INFO_SUFFIX, "") +
|
|
1011
|
+
"' error: " +
|
|
1012
|
+
e.getMessage()
|
|
1013
|
+
);
|
|
1014
|
+
// Clear corrupted data
|
|
1015
|
+
this.editor.remove(trueId + INFO_SUFFIX);
|
|
1016
|
+
this.editor.commit();
|
|
1017
|
+
result = new BundleInfo(trueId, null, BundleStatus.ERROR, "", "");
|
|
984
1018
|
}
|
|
985
1019
|
}
|
|
986
|
-
// Log.d(TAG, "Returning info [" + trueId + "] " + result);
|
|
987
1020
|
return result;
|
|
988
1021
|
}
|
|
989
1022
|
|
|
@@ -1003,17 +1036,18 @@ public class CapacitorUpdater {
|
|
|
1003
1036
|
|
|
1004
1037
|
public void saveBundleInfo(final String id, final BundleInfo info) {
|
|
1005
1038
|
if (id == null || (info != null && (info.isBuiltin() || info.isUnknown()))) {
|
|
1006
|
-
|
|
1039
|
+
logger.debug("Not saving info for bundle: [" + id + "] " + info);
|
|
1007
1040
|
return;
|
|
1008
1041
|
}
|
|
1009
1042
|
|
|
1010
1043
|
if (info == null) {
|
|
1011
|
-
|
|
1044
|
+
logger.debug("Removing info for bundle [" + id + "]");
|
|
1012
1045
|
this.editor.remove(id + INFO_SUFFIX);
|
|
1013
1046
|
} else {
|
|
1014
1047
|
final BundleInfo update = info.setId(id);
|
|
1015
|
-
|
|
1016
|
-
|
|
1048
|
+
String jsonString = update.toString();
|
|
1049
|
+
logger.debug("Storing info for bundle [" + id + "] " + update.getClass().getName() + " -> " + jsonString);
|
|
1050
|
+
this.editor.putString(id + INFO_SUFFIX, jsonString);
|
|
1017
1051
|
}
|
|
1018
1052
|
this.editor.commit();
|
|
1019
1053
|
}
|
|
@@ -1021,7 +1055,7 @@ public class CapacitorUpdater {
|
|
|
1021
1055
|
private void setBundleStatus(final String id, final BundleStatus status) {
|
|
1022
1056
|
if (id != null && status != null) {
|
|
1023
1057
|
BundleInfo info = this.getBundleInfo(id);
|
|
1024
|
-
|
|
1058
|
+
logger.debug("Setting status for bundle [" + id + "] to " + status);
|
|
1025
1059
|
this.saveBundleInfo(id, info.setStatus(status));
|
|
1026
1060
|
}
|
|
1027
1061
|
}
|
|
@@ -12,7 +12,6 @@ package ee.forgr.capacitor_updater;
|
|
|
12
12
|
* references: http://stackoverflow.com/questions/12471999/rsa-encryption-decryption-in-android
|
|
13
13
|
*/
|
|
14
14
|
import android.util.Base64;
|
|
15
|
-
import android.util.Log;
|
|
16
15
|
import java.io.BufferedInputStream;
|
|
17
16
|
import java.io.DataInputStream;
|
|
18
17
|
import java.io.File;
|
|
@@ -38,6 +37,12 @@ import javax.crypto.spec.SecretKeySpec;
|
|
|
38
37
|
|
|
39
38
|
public class CryptoCipherV2 {
|
|
40
39
|
|
|
40
|
+
private static Logger logger;
|
|
41
|
+
|
|
42
|
+
public static void setLogger(Logger loggerInstance) {
|
|
43
|
+
logger = loggerInstance;
|
|
44
|
+
}
|
|
45
|
+
|
|
41
46
|
public static byte[] decryptRSA(byte[] source, PublicKey publicKey)
|
|
42
47
|
throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
|
|
43
48
|
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
|
|
@@ -135,11 +140,11 @@ public class CryptoCipherV2 {
|
|
|
135
140
|
|
|
136
141
|
public static void decryptFile(final File file, final String publicKey, final String ivSessionKey) throws IOException {
|
|
137
142
|
if (publicKey.isEmpty() || ivSessionKey == null || ivSessionKey.isEmpty() || ivSessionKey.split(":").length != 2) {
|
|
138
|
-
|
|
143
|
+
logger.info("Encryption not set, no public key or seesion, ignored");
|
|
139
144
|
return;
|
|
140
145
|
}
|
|
141
146
|
if (!publicKey.startsWith("-----BEGIN RSA PUBLIC KEY-----")) {
|
|
142
|
-
|
|
147
|
+
logger.error("The public key is not a valid RSA Public key");
|
|
143
148
|
return;
|
|
144
149
|
}
|
|
145
150
|
|
|
@@ -168,7 +173,7 @@ public class CryptoCipherV2 {
|
|
|
168
173
|
}
|
|
169
174
|
}
|
|
170
175
|
} catch (GeneralSecurityException e) {
|
|
171
|
-
|
|
176
|
+
logger.info("decryptFile fail");
|
|
172
177
|
e.printStackTrace();
|
|
173
178
|
throw new IOException("GeneralSecurityException");
|
|
174
179
|
}
|
|
@@ -176,7 +181,7 @@ public class CryptoCipherV2 {
|
|
|
176
181
|
|
|
177
182
|
public static String decryptChecksum(String checksum, String publicKey) throws IOException {
|
|
178
183
|
if (publicKey.isEmpty()) {
|
|
179
|
-
|
|
184
|
+
logger.error("No encryption set (public key) ignored");
|
|
180
185
|
return checksum;
|
|
181
186
|
}
|
|
182
187
|
try {
|
|
@@ -187,7 +192,7 @@ public class CryptoCipherV2 {
|
|
|
187
192
|
String result = Base64.encodeToString(decryptedChecksum, Base64.DEFAULT);
|
|
188
193
|
return result.replaceAll("\\s", ""); // Remove all whitespace, including newlines
|
|
189
194
|
} catch (GeneralSecurityException e) {
|
|
190
|
-
|
|
195
|
+
logger.error("decryptChecksum fail: " + e.getMessage());
|
|
191
196
|
throw new IOException("Decryption failed: " + e.getMessage());
|
|
192
197
|
}
|
|
193
198
|
}
|
|
@@ -198,7 +203,7 @@ public class CryptoCipherV2 {
|
|
|
198
203
|
try {
|
|
199
204
|
digest = MessageDigest.getInstance("SHA-256");
|
|
200
205
|
} catch (java.security.NoSuchAlgorithmException e) {
|
|
201
|
-
|
|
206
|
+
logger.error("SHA-256 algorithm not available");
|
|
202
207
|
return "";
|
|
203
208
|
}
|
|
204
209
|
|
|
@@ -217,7 +222,7 @@ public class CryptoCipherV2 {
|
|
|
217
222
|
}
|
|
218
223
|
return hexString.toString();
|
|
219
224
|
} catch (IOException e) {
|
|
220
|
-
|
|
225
|
+
logger.error("Cannot calc checksum v2: " + file.getPath() + " " + e.getMessage());
|
|
221
226
|
return "";
|
|
222
227
|
}
|
|
223
228
|
}
|