@capgo/capacitor-updater 5.0.0-alpha.0 → 7.0.0

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 (38) hide show
  1. package/CapgoCapacitorUpdater.podspec +1 -1
  2. package/LICENCE +373 -661
  3. package/README.md +339 -75
  4. package/android/build.gradle +13 -12
  5. package/android/src/main/AndroidManifest.xml +4 -2
  6. package/android/src/main/java/ee/forgr/capacitor_updater/BundleInfo.java +205 -121
  7. package/android/src/main/java/ee/forgr/capacitor_updater/BundleStatus.java +32 -24
  8. package/android/src/main/java/ee/forgr/capacitor_updater/CapacitorUpdater.java +1041 -441
  9. package/android/src/main/java/ee/forgr/capacitor_updater/CapacitorUpdaterPlugin.java +1217 -536
  10. package/android/src/main/java/ee/forgr/capacitor_updater/CryptoCipher.java +153 -0
  11. package/android/src/main/java/ee/forgr/capacitor_updater/DelayCondition.java +62 -0
  12. package/android/src/main/java/ee/forgr/capacitor_updater/DelayUntilNext.java +14 -0
  13. package/android/src/main/java/ee/forgr/capacitor_updater/DownloadService.java +126 -0
  14. package/dist/docs.json +727 -171
  15. package/dist/esm/definitions.d.ts +234 -45
  16. package/dist/esm/definitions.js +5 -0
  17. package/dist/esm/definitions.js.map +1 -1
  18. package/dist/esm/index.d.ts +2 -2
  19. package/dist/esm/index.js +9 -4
  20. package/dist/esm/index.js.map +1 -1
  21. package/dist/esm/web.d.ts +12 -6
  22. package/dist/esm/web.js +64 -20
  23. package/dist/esm/web.js.map +1 -1
  24. package/dist/plugin.cjs.js +70 -23
  25. package/dist/plugin.cjs.js.map +1 -1
  26. package/dist/plugin.js +70 -23
  27. package/dist/plugin.js.map +1 -1
  28. package/ios/Plugin/BundleInfo.swift +38 -19
  29. package/ios/Plugin/BundleStatus.swift +11 -4
  30. package/ios/Plugin/CapacitorUpdater.swift +520 -192
  31. package/ios/Plugin/CapacitorUpdaterPlugin.m +8 -1
  32. package/ios/Plugin/CapacitorUpdaterPlugin.swift +447 -190
  33. package/ios/Plugin/CryptoCipher.swift +240 -0
  34. package/ios/Plugin/DelayCondition.swift +74 -0
  35. package/ios/Plugin/DelayUntilNext.swift +30 -0
  36. package/ios/Plugin/UserDefaultsExtension.swift +48 -0
  37. package/package.json +26 -20
  38. package/ios/Plugin/ObjectPreferences.swift +0 -97
@@ -0,0 +1,153 @@
1
+ /*
2
+ * This Source Code Form is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5
+ */
6
+
7
+ package ee.forgr.capacitor_updater;
8
+
9
+ /**
10
+ * Created by Awesometic
11
+ * It's encrypt returns Base64 encoded, and also decrypt for Base64 encoded cipher
12
+ * references: http://stackoverflow.com/questions/12471999/rsa-encryption-decryption-in-android
13
+ */
14
+ import android.util.Base64;
15
+ import java.security.GeneralSecurityException;
16
+ import java.security.InvalidAlgorithmParameterException;
17
+ import java.security.InvalidKeyException;
18
+ import java.security.KeyFactory;
19
+ import java.security.NoSuchAlgorithmException;
20
+ import java.security.PrivateKey;
21
+ import java.security.spec.InvalidKeySpecException;
22
+ import java.security.spec.MGF1ParameterSpec;
23
+ import java.security.spec.PKCS8EncodedKeySpec;
24
+ import javax.crypto.BadPaddingException;
25
+ import javax.crypto.Cipher;
26
+ import javax.crypto.IllegalBlockSizeException;
27
+ import javax.crypto.NoSuchPaddingException;
28
+ import javax.crypto.SecretKey;
29
+ import javax.crypto.spec.IvParameterSpec;
30
+ import javax.crypto.spec.OAEPParameterSpec;
31
+ import javax.crypto.spec.PSource;
32
+ import javax.crypto.spec.SecretKeySpec;
33
+
34
+ public class CryptoCipher {
35
+
36
+ public static byte[] decryptRSA(byte[] source, PrivateKey privateKey)
37
+ throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
38
+ Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPPadding");
39
+ OAEPParameterSpec oaepParams = new OAEPParameterSpec(
40
+ "SHA-256",
41
+ "MGF1",
42
+ new MGF1ParameterSpec("SHA-256"),
43
+ PSource.PSpecified.DEFAULT
44
+ );
45
+ cipher.init(Cipher.DECRYPT_MODE, privateKey, oaepParams);
46
+ byte[] decryptedBytes = cipher.doFinal(source);
47
+ return decryptedBytes;
48
+ }
49
+
50
+ public static byte[] decryptAES(byte[] cipherText, SecretKey key, byte[] iv) {
51
+ try {
52
+ IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
53
+ Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
54
+ SecretKeySpec keySpec = new SecretKeySpec(key.getEncoded(), "AES");
55
+ cipher.init(Cipher.DECRYPT_MODE, keySpec, ivParameterSpec);
56
+ byte[] decryptedText = cipher.doFinal(cipherText);
57
+ return decryptedText;
58
+ } catch (Exception e) {
59
+ e.printStackTrace();
60
+ }
61
+ return null;
62
+ }
63
+
64
+ public static SecretKey byteToSessionKey(byte[] sessionKey) {
65
+ // rebuild key using SecretKeySpec
66
+ SecretKey originalKey = new SecretKeySpec(
67
+ sessionKey,
68
+ 0,
69
+ sessionKey.length,
70
+ "AES"
71
+ );
72
+ return originalKey;
73
+ }
74
+
75
+ private static PrivateKey readPkcs8PrivateKey(byte[] pkcs8Bytes)
76
+ throws GeneralSecurityException {
77
+ KeyFactory keyFactory = KeyFactory.getInstance("RSA");
78
+ PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pkcs8Bytes);
79
+ try {
80
+ return keyFactory.generatePrivate(keySpec);
81
+ } catch (InvalidKeySpecException e) {
82
+ throw new IllegalArgumentException("Unexpected key format!", e);
83
+ }
84
+ }
85
+
86
+ private static byte[] join(byte[] byteArray1, byte[] byteArray2) {
87
+ byte[] bytes = new byte[byteArray1.length + byteArray2.length];
88
+ System.arraycopy(byteArray1, 0, bytes, 0, byteArray1.length);
89
+ System.arraycopy(
90
+ byteArray2,
91
+ 0,
92
+ bytes,
93
+ byteArray1.length,
94
+ byteArray2.length
95
+ );
96
+ return bytes;
97
+ }
98
+
99
+ private static PrivateKey readPkcs1PrivateKey(byte[] pkcs1Bytes)
100
+ throws GeneralSecurityException {
101
+ // We can't use Java internal APIs to parse ASN.1 structures, so we build a PKCS#8 key Java can understand
102
+ int pkcs1Length = pkcs1Bytes.length;
103
+ int totalLength = pkcs1Length + 22;
104
+ byte[] pkcs8Header = new byte[] {
105
+ 0x30,
106
+ (byte) 0x82,
107
+ (byte) ((totalLength >> 8) & 0xff),
108
+ (byte) (totalLength & 0xff), // Sequence + total length
109
+ 0x2,
110
+ 0x1,
111
+ 0x0, // Integer (0)
112
+ 0x30,
113
+ 0xD,
114
+ 0x6,
115
+ 0x9,
116
+ 0x2A,
117
+ (byte) 0x86,
118
+ 0x48,
119
+ (byte) 0x86,
120
+ (byte) 0xF7,
121
+ 0xD,
122
+ 0x1,
123
+ 0x1,
124
+ 0x1,
125
+ 0x5,
126
+ 0x0, // Sequence: 1.2.840.113549.1.1.1, NULL
127
+ 0x4,
128
+ (byte) 0x82,
129
+ (byte) ((pkcs1Length >> 8) & 0xff),
130
+ (byte) (pkcs1Length & 0xff), // Octet string + length
131
+ };
132
+ byte[] pkcs8bytes = join(pkcs8Header, pkcs1Bytes);
133
+ return readPkcs8PrivateKey(pkcs8bytes);
134
+ }
135
+
136
+ public static PrivateKey stringToPrivateKey(String private_key)
137
+ throws GeneralSecurityException {
138
+ // Base64 decode the result
139
+
140
+ String pkcs1Pem = private_key.toString();
141
+ pkcs1Pem = pkcs1Pem.replace("-----BEGIN RSA PRIVATE KEY-----", "");
142
+ pkcs1Pem = pkcs1Pem.replace("-----END RSA PRIVATE KEY-----", "");
143
+ pkcs1Pem = pkcs1Pem.replace("\\n", "");
144
+ pkcs1Pem = pkcs1Pem.replace(" ", "");
145
+
146
+ byte[] pkcs1EncodedBytes = Base64.decode(
147
+ pkcs1Pem.getBytes(),
148
+ Base64.DEFAULT
149
+ );
150
+ // extract the private key
151
+ return readPkcs1PrivateKey(pkcs1EncodedBytes);
152
+ }
153
+ }
@@ -0,0 +1,62 @@
1
+ /*
2
+ * This Source Code Form is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5
+ */
6
+
7
+ package ee.forgr.capacitor_updater;
8
+
9
+ import com.google.gson.annotations.SerializedName;
10
+ import java.util.Objects;
11
+
12
+ public class DelayCondition {
13
+
14
+ @SerializedName("kind")
15
+ private DelayUntilNext kind;
16
+
17
+ @SerializedName("value")
18
+ private String value;
19
+
20
+ public DelayCondition(DelayUntilNext kind, String value) {
21
+ this.kind = kind;
22
+ this.value = value;
23
+ }
24
+
25
+ public DelayUntilNext getKind() {
26
+ return kind;
27
+ }
28
+
29
+ public void setKind(DelayUntilNext kind) {
30
+ this.kind = kind;
31
+ }
32
+
33
+ public String getValue() {
34
+ return value;
35
+ }
36
+
37
+ public void setValue(String value) {
38
+ this.value = value;
39
+ }
40
+
41
+ @Override
42
+ public boolean equals(Object o) {
43
+ if (this == o) return true;
44
+ if (!(o instanceof DelayCondition)) return false;
45
+ DelayCondition that = (DelayCondition) o;
46
+ return (
47
+ getKind() == that.getKind() && Objects.equals(getValue(), that.getValue())
48
+ );
49
+ }
50
+
51
+ @Override
52
+ public int hashCode() {
53
+ return Objects.hash(getKind(), getValue());
54
+ }
55
+
56
+ @Override
57
+ public String toString() {
58
+ return (
59
+ "DelayCondition{" + "kind=" + kind + ", value='" + value + '\'' + '}'
60
+ );
61
+ }
62
+ }
@@ -0,0 +1,14 @@
1
+ /*
2
+ * This Source Code Form is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5
+ */
6
+
7
+ package ee.forgr.capacitor_updater;
8
+
9
+ public enum DelayUntilNext {
10
+ background,
11
+ kill,
12
+ nativeVersion,
13
+ date,
14
+ }
@@ -0,0 +1,126 @@
1
+ /*
2
+ * This Source Code Form is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5
+ */
6
+
7
+ package ee.forgr.capacitor_updater;
8
+
9
+ import android.app.IntentService;
10
+ import android.content.Intent;
11
+ import java.io.DataInputStream;
12
+ import java.io.File;
13
+ import java.io.FileOutputStream;
14
+ import java.io.InputStream;
15
+ import java.net.URL;
16
+ import java.net.URLConnection;
17
+
18
+ public class DownloadService extends IntentService {
19
+
20
+ public static final String URL = "URL";
21
+ public static final String ID = "id";
22
+ public static final String PERCENT = "percent";
23
+ public static final String FILEDEST = "filendest";
24
+ public static final String DOCDIR = "docdir";
25
+ public static final String ERROR = "error";
26
+ public static final String VERSION = "version";
27
+ public static final String SESSIONKEY = "sessionkey";
28
+ public static final String CHECKSUM = "checksum";
29
+ public static final String NOTIFICATION = "service receiver";
30
+ public static final String PERCENTDOWNLOAD = "percent receiver";
31
+
32
+ public DownloadService() {
33
+ super("Background DownloadService");
34
+ }
35
+
36
+ private int calcTotalPercent(
37
+ final int percent,
38
+ final int min,
39
+ final int max
40
+ ) {
41
+ return (percent * (max - min)) / 100 + min;
42
+ }
43
+
44
+ // Will be called asynchronously by OS.
45
+ @Override
46
+ protected void onHandleIntent(Intent intent) {
47
+ String url = intent.getStringExtra(URL);
48
+ String id = intent.getStringExtra(ID);
49
+ String documentsDir = intent.getStringExtra(DOCDIR);
50
+ String dest = intent.getStringExtra(FILEDEST);
51
+ String version = intent.getStringExtra(VERSION);
52
+ String sessionKey = intent.getStringExtra(SESSIONKEY);
53
+ String checksum = intent.getStringExtra(CHECKSUM);
54
+
55
+ try {
56
+ final URL u = new URL(url);
57
+ final URLConnection connection = u.openConnection();
58
+ final InputStream is = u.openStream();
59
+ final DataInputStream dis = new DataInputStream(is);
60
+
61
+ final File target = new File(documentsDir, dest);
62
+ target.getParentFile().mkdirs();
63
+ target.createNewFile();
64
+ final FileOutputStream fos = new FileOutputStream(target);
65
+
66
+ final long totalLength = connection.getContentLength();
67
+ final int bufferSize = 1024;
68
+ final byte[] buffer = new byte[bufferSize];
69
+ int length;
70
+
71
+ int bytesRead = bufferSize;
72
+ int percent = 0;
73
+ this.notifyDownload(id, 10);
74
+ while ((length = dis.read(buffer)) > 0) {
75
+ fos.write(buffer, 0, length);
76
+ final int newPercent = (int) ((bytesRead * 100) / totalLength);
77
+ if (totalLength > 1 && newPercent != percent) {
78
+ percent = newPercent;
79
+ this.notifyDownload(id, this.calcTotalPercent(percent, 10, 70));
80
+ }
81
+ bytesRead += length;
82
+ }
83
+ publishResults(dest, id, version, checksum, sessionKey, "");
84
+ } catch (Exception e) {
85
+ e.printStackTrace();
86
+ publishResults(
87
+ "",
88
+ id,
89
+ version,
90
+ checksum,
91
+ sessionKey,
92
+ e.getLocalizedMessage()
93
+ );
94
+ }
95
+ }
96
+
97
+ private void notifyDownload(String id, int percent) {
98
+ Intent intent = new Intent(PERCENTDOWNLOAD);
99
+ intent.putExtra(ID, id);
100
+ intent.putExtra(PERCENT, percent);
101
+ sendBroadcast(intent);
102
+ }
103
+
104
+ private void publishResults(
105
+ String dest,
106
+ String id,
107
+ String version,
108
+ String checksum,
109
+ String sessionKey,
110
+ String error
111
+ ) {
112
+ Intent intent = new Intent(NOTIFICATION);
113
+ if (dest != null && !dest.isEmpty()) {
114
+ intent.putExtra(FILEDEST, dest);
115
+ }
116
+ if (error != null && !error.isEmpty()) {
117
+ intent.putExtra(ERROR, error);
118
+ }
119
+ intent.putExtra(ID, id);
120
+ intent.putExtra(VERSION, version);
121
+ intent.putExtra(SESSIONKEY, sessionKey);
122
+ intent.putExtra(CHECKSUM, checksum);
123
+ intent.putExtra(ERROR, error);
124
+ sendBroadcast(intent);
125
+ }
126
+ }