@capgo/capacitor-updater 6.40.0 → 6.40.5
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 +135 -0
- package/android/src/main/java/ee/forgr/capacitor_updater/CapacitorUpdaterPlugin.java +1 -1
- package/android/src/main/java/ee/forgr/capacitor_updater/CapgoUpdater.java +56 -34
- package/android/src/main/java/ee/forgr/capacitor_updater/CryptoCipher.java +10 -14
- package/dist/docs.json +557 -1
- package/dist/esm/definitions.d.ts +320 -0
- package/dist/esm/definitions.js +1 -0
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/index.d.ts +0 -1
- package/dist/esm/index.js +0 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/plugin.cjs.js +1 -1
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +2 -2
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/CapacitorUpdaterPlugin/AES.swift +26 -8
- package/ios/Sources/CapacitorUpdaterPlugin/BigInt.swift +9 -9
- package/ios/Sources/CapacitorUpdaterPlugin/BundleInfo.swift +51 -14
- package/ios/Sources/CapacitorUpdaterPlugin/BundleStatus.swift +11 -11
- package/ios/Sources/CapacitorUpdaterPlugin/CapacitorUpdaterPlugin.swift +1 -1
- package/ios/Sources/CapacitorUpdaterPlugin/CapgoUpdater.swift +99 -51
- package/ios/Sources/CapacitorUpdaterPlugin/CryptoCipher.swift +37 -20
- package/ios/Sources/CapacitorUpdaterPlugin/DelayUpdateUtils.swift +23 -7
- package/ios/Sources/CapacitorUpdaterPlugin/InternalUtils.swift +10 -1
- package/ios/Sources/CapacitorUpdaterPlugin/Logger.swift +9 -9
- package/ios/Sources/CapacitorUpdaterPlugin/ShakeMenu.swift +6 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -257,7 +257,142 @@ Capacitor Updater works by unzipping a compiled app bundle to the native device
|
|
|
257
257
|
<docgen-config>
|
|
258
258
|
<!--Update the source file JSDoc comments and rerun docgen to update the docs below-->
|
|
259
259
|
|
|
260
|
+
CapacitorUpdater can be configured with these options:
|
|
261
|
+
|
|
262
|
+
| Prop | Type | Description | Default | Since |
|
|
263
|
+
| ----------------------------- | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ------- |
|
|
264
|
+
| **`appReadyTimeout`** | <code>number</code> | Configure the number of milliseconds the native plugin should wait before considering an update 'failed'. Only available for Android and iOS. | <code>10000 // (10 seconds)</code> | |
|
|
265
|
+
| **`responseTimeout`** | <code>number</code> | Configure the number of seconds the native plugin should wait before considering API timeout. Only available for Android and iOS. | <code>20 // (20 second)</code> | |
|
|
266
|
+
| **`autoDeleteFailed`** | <code>boolean</code> | Configure whether the plugin should use automatically delete failed bundles. Only available for Android and iOS. | <code>true</code> | |
|
|
267
|
+
| **`autoDeletePrevious`** | <code>boolean</code> | Configure whether the plugin should use automatically delete previous bundles after a successful update. Only available for Android and iOS. | <code>true</code> | |
|
|
268
|
+
| **`autoUpdate`** | <code>boolean</code> | Configure whether the plugin should use Auto Update via an update server. Only available for Android and iOS. | <code>true</code> | |
|
|
269
|
+
| **`resetWhenUpdate`** | <code>boolean</code> | Automatically delete previous downloaded bundles when a newer native app bundle is installed to the device. Setting this to false can broke the auto update flow if the user download from the store a native app bundle that is older than the current downloaded bundle. Upload will be prevented by channel setting downgrade_under_native. Only available for Android and iOS. | <code>true</code> | |
|
|
270
|
+
| **`updateUrl`** | <code>string</code> | Configure the URL / endpoint to which update checks are sent. Only available for Android and iOS. | <code>https://plugin.capgo.app/updates</code> | |
|
|
271
|
+
| **`channelUrl`** | <code>string</code> | Configure the URL / endpoint for channel operations. Only available for Android and iOS. | <code>https://plugin.capgo.app/channel_self</code> | |
|
|
272
|
+
| **`statsUrl`** | <code>string</code> | Configure the URL / endpoint to which update statistics are sent. Only available for Android and iOS. Set to "" to disable stats reporting. | <code>https://plugin.capgo.app/stats</code> | |
|
|
273
|
+
| **`publicKey`** | <code>string</code> | Configure the public key for end to end live update encryption Version 2 Only available for Android and iOS. | <code>undefined</code> | 6.2.0 |
|
|
274
|
+
| **`version`** | <code>string</code> | Configure the current version of the app. This will be used for the first update request. If not set, the plugin will get the version from the native code. Only available for Android and iOS. | <code>undefined</code> | 4.17.48 |
|
|
275
|
+
| **`directUpdate`** | <code>boolean \| 'always' \| 'atInstall' \| 'onLaunch'</code> | Configure when the plugin should direct install updates. Only for autoUpdate mode. Works well for apps less than 10MB and with uploads done using --partial flag. Zip or apps more than 10MB will be relatively slow for users to update. - false: Never do direct updates (use default behavior: download at start, set when backgrounded) - atInstall: Direct update only when app is installed, updated from store, otherwise act as directUpdate = false - onLaunch: Direct update only on app installed, updated from store or after app kill, otherwise act as directUpdate = false - always: Direct update in all previous cases (app installed, updated from store, after app kill or app resume), never act as directUpdate = false - true: (deprecated) Same as "always" for backward compatibility Only available for Android and iOS. | <code>false</code> | 5.1.0 |
|
|
276
|
+
| **`autoSplashscreen`** | <code>boolean</code> | Automatically handle splashscreen hiding when using directUpdate. When enabled, the plugin will automatically hide the splashscreen after updates are applied or when no update is needed. This removes the need to manually listen for appReady events and call SplashScreen.hide(). Only works when directUpdate is set to "atInstall", "always", "onLaunch", or true. Requires the @capacitor/splash-screen plugin to be installed and configured with launchAutoHide: false. Requires autoUpdate and directUpdate to be enabled. Only available for Android and iOS. | <code>false</code> | 7.6.0 |
|
|
277
|
+
| **`autoSplashscreenLoader`** | <code>boolean</code> | Display a native loading indicator on top of the splashscreen while automatic direct updates are running. Only takes effect when {@link autoSplashscreen} is enabled. Requires the @capacitor/splash-screen plugin to be installed and configured with launchAutoHide: false. Only available for Android and iOS. | <code>false</code> | 7.19.0 |
|
|
278
|
+
| **`autoSplashscreenTimeout`** | <code>number</code> | Automatically hide the splashscreen after the specified number of milliseconds when using automatic direct updates. If the timeout elapses, the update continues to download in the background while the splashscreen is dismissed. Set to `0` (zero) to disable the timeout. When the timeout fires, the direct update flow is skipped and the downloaded bundle is installed on the next background/launch. Requires {@link autoSplashscreen} to be enabled. Only available for Android and iOS. | <code>10000 // (10 seconds)</code> | 7.19.0 |
|
|
279
|
+
| **`periodCheckDelay`** | <code>number</code> | Configure the delay period for period update check. the unit is in seconds. Only available for Android and iOS. Cannot be less than 600 seconds (10 minutes). | <code>0 (disabled)</code> | |
|
|
280
|
+
| **`localS3`** | <code>boolean</code> | Configure the CLI to use a local server for testing or self-hosted update server. | <code>undefined</code> | 4.17.48 |
|
|
281
|
+
| **`localHost`** | <code>string</code> | Configure the CLI to use a local server for testing or self-hosted update server. | <code>undefined</code> | 4.17.48 |
|
|
282
|
+
| **`localWebHost`** | <code>string</code> | Configure the CLI to use a local server for testing or self-hosted update server. | <code>undefined</code> | 4.17.48 |
|
|
283
|
+
| **`localSupa`** | <code>string</code> | Configure the CLI to use a local server for testing or self-hosted update server. | <code>undefined</code> | 4.17.48 |
|
|
284
|
+
| **`localSupaAnon`** | <code>string</code> | Configure the CLI to use a local server for testing. | <code>undefined</code> | 4.17.48 |
|
|
285
|
+
| **`localApi`** | <code>string</code> | Configure the CLI to use a local api for testing. | <code>undefined</code> | 6.3.3 |
|
|
286
|
+
| **`localApiFiles`** | <code>string</code> | Configure the CLI to use a local file api for testing. | <code>undefined</code> | 6.3.3 |
|
|
287
|
+
| **`allowModifyUrl`** | <code>boolean</code> | Allow the plugin to modify the updateUrl, statsUrl and channelUrl dynamically from the JavaScript side. | <code>false</code> | 5.4.0 |
|
|
288
|
+
| **`allowModifyAppId`** | <code>boolean</code> | Allow the plugin to modify the appId dynamically from the JavaScript side. | <code>false</code> | 7.14.0 |
|
|
289
|
+
| **`allowManualBundleError`** | <code>boolean</code> | Allow marking bundles as errored from JavaScript while using manual update flows. When enabled, {@link CapacitorUpdaterPlugin.setBundleError} can change a bundle status to `error`. | <code>false</code> | 7.20.0 |
|
|
290
|
+
| **`persistCustomId`** | <code>boolean</code> | Persist the customId set through {@link CapacitorUpdaterPlugin.setCustomId} across app restarts. Only available for Android and iOS. | <code>false (will be true by default in a future major release v8.x.x)</code> | 7.17.3 |
|
|
291
|
+
| **`persistModifyUrl`** | <code>boolean</code> | Persist the updateUrl, statsUrl and channelUrl set through {@link CapacitorUpdaterPlugin.setUpdateUrl}, {@link CapacitorUpdaterPlugin.setStatsUrl} and {@link CapacitorUpdaterPlugin.setChannelUrl} across app restarts. Only available for Android and iOS. | <code>false</code> | 7.20.0 |
|
|
292
|
+
| **`allowSetDefaultChannel`** | <code>boolean</code> | Allow or disallow the {@link CapacitorUpdaterPlugin.setChannel} method to modify the defaultChannel. When set to `false`, calling `setChannel()` will return an error with code `disabled_by_config`. | <code>true</code> | 7.34.0 |
|
|
293
|
+
| **`defaultChannel`** | <code>string</code> | Set the default channel for the app in the config. Case sensitive. This will setting will override the default channel set in the cloud, but will still respect overrides made in the cloud. This requires the channel to allow devices to self dissociate/associate in the channel settings. https://capgo.app/docs/public-api/channels/#channel-configuration-options | <code>undefined</code> | 5.5.0 |
|
|
294
|
+
| **`appId`** | <code>string</code> | Configure the app id for the app in the config. | <code>undefined</code> | 6.0.0 |
|
|
295
|
+
| **`keepUrlPathAfterReload`** | <code>boolean</code> | Configure the plugin to keep the URL path after a reload. WARNING: When a reload is triggered, 'window.history' will be cleared. | <code>false</code> | 6.8.0 |
|
|
296
|
+
| **`disableJSLogging`** | <code>boolean</code> | Disable the JavaScript logging of the plugin. if true, the plugin will not log to the JavaScript console. only the native log will be done | <code>false</code> | 7.3.0 |
|
|
297
|
+
| **`shakeMenu`** | <code>boolean</code> | Enable shake gesture to show update menu for debugging/testing purposes | <code>false</code> | 7.5.0 |
|
|
298
|
+
|
|
299
|
+
### Examples
|
|
300
|
+
|
|
301
|
+
In `capacitor.config.json`:
|
|
260
302
|
|
|
303
|
+
```json
|
|
304
|
+
{
|
|
305
|
+
"plugins": {
|
|
306
|
+
"CapacitorUpdater": {
|
|
307
|
+
"appReadyTimeout": 1000 // (1 second, minimum 1000),
|
|
308
|
+
"responseTimeout": 10 // (10 second),
|
|
309
|
+
"autoDeleteFailed": false,
|
|
310
|
+
"autoDeletePrevious": false,
|
|
311
|
+
"autoUpdate": false,
|
|
312
|
+
"resetWhenUpdate": false,
|
|
313
|
+
"updateUrl": https://example.com/api/auto_update,
|
|
314
|
+
"channelUrl": https://example.com/api/channel,
|
|
315
|
+
"statsUrl": https://example.com/api/stats,
|
|
316
|
+
"publicKey": undefined,
|
|
317
|
+
"version": undefined,
|
|
318
|
+
"directUpdate": undefined,
|
|
319
|
+
"autoSplashscreen": undefined,
|
|
320
|
+
"autoSplashscreenLoader": undefined,
|
|
321
|
+
"autoSplashscreenTimeout": undefined,
|
|
322
|
+
"periodCheckDelay": 3600 (1 hour),
|
|
323
|
+
"localS3": undefined,
|
|
324
|
+
"localHost": undefined,
|
|
325
|
+
"localWebHost": undefined,
|
|
326
|
+
"localSupa": undefined,
|
|
327
|
+
"localSupaAnon": undefined,
|
|
328
|
+
"localApi": undefined,
|
|
329
|
+
"localApiFiles": undefined,
|
|
330
|
+
"allowModifyUrl": undefined,
|
|
331
|
+
"allowModifyAppId": undefined,
|
|
332
|
+
"allowManualBundleError": undefined,
|
|
333
|
+
"persistCustomId": undefined,
|
|
334
|
+
"persistModifyUrl": undefined,
|
|
335
|
+
"allowSetDefaultChannel": undefined,
|
|
336
|
+
"defaultChannel": undefined,
|
|
337
|
+
"appId": undefined,
|
|
338
|
+
"keepUrlPathAfterReload": undefined,
|
|
339
|
+
"disableJSLogging": undefined,
|
|
340
|
+
"shakeMenu": undefined
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
In `capacitor.config.ts`:
|
|
347
|
+
|
|
348
|
+
```ts
|
|
349
|
+
/// <reference types="@capgo/capacitor-updater" />
|
|
350
|
+
|
|
351
|
+
import { CapacitorConfig } from '@capacitor/cli';
|
|
352
|
+
|
|
353
|
+
const config: CapacitorConfig = {
|
|
354
|
+
plugins: {
|
|
355
|
+
CapacitorUpdater: {
|
|
356
|
+
appReadyTimeout: 1000 // (1 second, minimum 1000),
|
|
357
|
+
responseTimeout: 10 // (10 second),
|
|
358
|
+
autoDeleteFailed: false,
|
|
359
|
+
autoDeletePrevious: false,
|
|
360
|
+
autoUpdate: false,
|
|
361
|
+
resetWhenUpdate: false,
|
|
362
|
+
updateUrl: https://example.com/api/auto_update,
|
|
363
|
+
channelUrl: https://example.com/api/channel,
|
|
364
|
+
statsUrl: https://example.com/api/stats,
|
|
365
|
+
publicKey: undefined,
|
|
366
|
+
version: undefined,
|
|
367
|
+
directUpdate: undefined,
|
|
368
|
+
autoSplashscreen: undefined,
|
|
369
|
+
autoSplashscreenLoader: undefined,
|
|
370
|
+
autoSplashscreenTimeout: undefined,
|
|
371
|
+
periodCheckDelay: 3600 (1 hour),
|
|
372
|
+
localS3: undefined,
|
|
373
|
+
localHost: undefined,
|
|
374
|
+
localWebHost: undefined,
|
|
375
|
+
localSupa: undefined,
|
|
376
|
+
localSupaAnon: undefined,
|
|
377
|
+
localApi: undefined,
|
|
378
|
+
localApiFiles: undefined,
|
|
379
|
+
allowModifyUrl: undefined,
|
|
380
|
+
allowModifyAppId: undefined,
|
|
381
|
+
allowManualBundleError: undefined,
|
|
382
|
+
persistCustomId: undefined,
|
|
383
|
+
persistModifyUrl: undefined,
|
|
384
|
+
allowSetDefaultChannel: undefined,
|
|
385
|
+
defaultChannel: undefined,
|
|
386
|
+
appId: undefined,
|
|
387
|
+
keepUrlPathAfterReload: undefined,
|
|
388
|
+
disableJSLogging: undefined,
|
|
389
|
+
shakeMenu: undefined,
|
|
390
|
+
},
|
|
391
|
+
},
|
|
392
|
+
};
|
|
393
|
+
|
|
394
|
+
export default config;
|
|
395
|
+
```
|
|
261
396
|
|
|
262
397
|
</docgen-config>
|
|
263
398
|
|
|
@@ -85,7 +85,7 @@ public class CapacitorUpdaterPlugin extends Plugin {
|
|
|
85
85
|
private static final String[] BREAKING_EVENT_NAMES = { "breakingAvailable", "majorAvailable" };
|
|
86
86
|
private static final String LAST_FAILED_BUNDLE_PREF_KEY = "CapacitorUpdater.lastFailedBundle";
|
|
87
87
|
|
|
88
|
-
private final String pluginVersion = "6.40.
|
|
88
|
+
private final String pluginVersion = "6.40.5";
|
|
89
89
|
private static final String DELAY_CONDITION_PREFERENCES = "";
|
|
90
90
|
|
|
91
91
|
private SharedPreferences.Editor editor;
|
|
@@ -107,7 +107,10 @@ public class CapgoUpdater {
|
|
|
107
107
|
|
|
108
108
|
private boolean isProd() {
|
|
109
109
|
try {
|
|
110
|
-
|
|
110
|
+
if (activity == null) {
|
|
111
|
+
return true; // Default to production if no activity context
|
|
112
|
+
}
|
|
113
|
+
return (activity.getApplicationInfo().flags & android.content.pm.ApplicationInfo.FLAG_DEBUGGABLE) == 0;
|
|
111
114
|
} catch (Exception e) {
|
|
112
115
|
return true; // Default to production if we can't determine
|
|
113
116
|
}
|
|
@@ -181,7 +184,8 @@ public class CapgoUpdater {
|
|
|
181
184
|
ZipEntry entry;
|
|
182
185
|
while ((entry = zis.getNextEntry()) != null) {
|
|
183
186
|
if (entry.getName().contains("\\")) {
|
|
184
|
-
logger.error("
|
|
187
|
+
logger.error("Unzip failed: Windows path not supported");
|
|
188
|
+
logger.debug("Invalid path: " + entry.getName());
|
|
185
189
|
this.sendStats("windows_path_fail");
|
|
186
190
|
}
|
|
187
191
|
final File file = new File(targetDirectory, entry.getName());
|
|
@@ -277,7 +281,8 @@ public class CapgoUpdater {
|
|
|
277
281
|
boolean success = finishDownload(id, dest, version, sessionKey, checksum, true, isManifest);
|
|
278
282
|
BundleInfo resultBundle;
|
|
279
283
|
if (!success) {
|
|
280
|
-
logger.error("Finish download failed
|
|
284
|
+
logger.error("Finish download failed");
|
|
285
|
+
logger.debug("Version: " + version);
|
|
281
286
|
resultBundle = new BundleInfo(
|
|
282
287
|
id,
|
|
283
288
|
version,
|
|
@@ -309,7 +314,8 @@ public class CapgoUpdater {
|
|
|
309
314
|
case FAILED:
|
|
310
315
|
Data failedData = workInfo.getOutputData();
|
|
311
316
|
String error = failedData.getString(DownloadService.ERROR);
|
|
312
|
-
logger.error("Download failed
|
|
317
|
+
logger.error("Download failed");
|
|
318
|
+
logger.debug("Error: " + error + ", State: " + workInfo.getState());
|
|
313
319
|
String failedVersion = failedData.getString(DownloadService.VERSION);
|
|
314
320
|
|
|
315
321
|
io.execute(() -> {
|
|
@@ -428,7 +434,8 @@ public class CapgoUpdater {
|
|
|
428
434
|
CryptoCipher.logChecksumInfo("Calculated checksum", checksum);
|
|
429
435
|
CryptoCipher.logChecksumInfo("Expected checksum", checksumDecrypted);
|
|
430
436
|
if ((!checksumDecrypted.isEmpty() || !this.publicKey.isEmpty()) && !checksumDecrypted.equals(checksum)) {
|
|
431
|
-
logger.error("
|
|
437
|
+
logger.error("Checksum mismatch");
|
|
438
|
+
logger.debug("Expected: " + checksumDecrypted + ", Got: " + checksum);
|
|
432
439
|
this.sendStats("checksum_fail");
|
|
433
440
|
throw new IOException("Checksum failed: " + id);
|
|
434
441
|
}
|
|
@@ -440,7 +447,8 @@ public class CapgoUpdater {
|
|
|
440
447
|
}
|
|
441
448
|
final Boolean res = this.delete(id);
|
|
442
449
|
if (!res) {
|
|
443
|
-
logger.info("
|
|
450
|
+
logger.info("Failed to cleanup after error");
|
|
451
|
+
logger.debug("Version: " + version);
|
|
444
452
|
}
|
|
445
453
|
|
|
446
454
|
final Map<String, Object> ret = new HashMap<>();
|
|
@@ -541,7 +549,8 @@ public class CapgoUpdater {
|
|
|
541
549
|
this.deleteDirectory(cacheFolder, threadToCheck);
|
|
542
550
|
logger.info("Cleaned up delta cache folder");
|
|
543
551
|
} catch (IOException e) {
|
|
544
|
-
logger.error("Failed to cleanup delta cache
|
|
552
|
+
logger.error("Failed to cleanup delta cache");
|
|
553
|
+
logger.debug("Error: " + e.getMessage());
|
|
545
554
|
}
|
|
546
555
|
}
|
|
547
556
|
|
|
@@ -582,9 +591,11 @@ public class CapgoUpdater {
|
|
|
582
591
|
try {
|
|
583
592
|
this.deleteDirectory(entry, threadToCheck);
|
|
584
593
|
this.removeBundleInfo(id);
|
|
585
|
-
logger.info("Deleted orphan bundle directory
|
|
594
|
+
logger.info("Deleted orphan bundle directory");
|
|
595
|
+
logger.debug("Bundle ID: " + id);
|
|
586
596
|
} catch (IOException e) {
|
|
587
|
-
logger.error("Failed to delete orphan bundle directory
|
|
597
|
+
logger.error("Failed to delete orphan bundle directory");
|
|
598
|
+
logger.debug("Bundle ID: " + id + ", Error: " + e.getMessage());
|
|
588
599
|
}
|
|
589
600
|
}
|
|
590
601
|
}
|
|
@@ -621,9 +632,11 @@ public class CapgoUpdater {
|
|
|
621
632
|
|
|
622
633
|
try {
|
|
623
634
|
this.deleteDirectory(entry, threadToCheck);
|
|
624
|
-
logger.info("Deleted orphaned temp unzip folder
|
|
635
|
+
logger.info("Deleted orphaned temp unzip folder");
|
|
636
|
+
logger.debug("Folder: " + folderName);
|
|
625
637
|
} catch (IOException e) {
|
|
626
|
-
logger.error("Failed to delete orphaned temp folder
|
|
638
|
+
logger.error("Failed to delete orphaned temp folder");
|
|
639
|
+
logger.debug("Folder: " + folderName + ", Error: " + e.getMessage());
|
|
627
640
|
}
|
|
628
641
|
}
|
|
629
642
|
}
|
|
@@ -710,7 +723,8 @@ public class CapgoUpdater {
|
|
|
710
723
|
} catch (Exception e) {
|
|
711
724
|
// Clean up on failure
|
|
712
725
|
downloadFutures.remove(id);
|
|
713
|
-
logger.error("Error waiting for download
|
|
726
|
+
logger.error("Error waiting for download");
|
|
727
|
+
logger.debug("Error: " + e.getMessage());
|
|
714
728
|
BundleInfo errorBundle = new BundleInfo(id, version, BundleStatus.ERROR, new Date(System.currentTimeMillis()), "");
|
|
715
729
|
saveBundleInfo(id, errorBundle);
|
|
716
730
|
if (e instanceof IOException) {
|
|
@@ -750,12 +764,14 @@ public class CapgoUpdater {
|
|
|
750
764
|
public Boolean delete(final String id, final Boolean removeInfo) throws IOException {
|
|
751
765
|
final BundleInfo deleted = this.getBundleInfo(id);
|
|
752
766
|
if (deleted.isBuiltin() || this.getCurrentBundleId().equals(id)) {
|
|
753
|
-
logger.error("Cannot delete
|
|
767
|
+
logger.error("Cannot delete current or builtin bundle");
|
|
768
|
+
logger.debug("Bundle ID: " + id);
|
|
754
769
|
return false;
|
|
755
770
|
}
|
|
756
771
|
final BundleInfo next = this.getNextBundle();
|
|
757
772
|
if (next != null && !next.isDeleted() && !next.isErrorStatus() && next.getId().equals(id)) {
|
|
758
|
-
logger.error("Cannot delete the next bundle"
|
|
773
|
+
logger.error("Cannot delete the next bundle");
|
|
774
|
+
logger.debug("Bundle ID: " + id);
|
|
759
775
|
return false;
|
|
760
776
|
}
|
|
761
777
|
// Cancel download for this version if active
|
|
@@ -772,7 +788,8 @@ public class CapgoUpdater {
|
|
|
772
788
|
}
|
|
773
789
|
return true;
|
|
774
790
|
}
|
|
775
|
-
logger.
|
|
791
|
+
logger.info("Bundle not found on disk");
|
|
792
|
+
logger.debug("Version: " + deleted.getVersionName());
|
|
776
793
|
// perhaps we did not find the bundle in the files, but if the user requested a delete, we delete
|
|
777
794
|
if (removeInfo) {
|
|
778
795
|
this.removeBundleInfo(id);
|
|
@@ -943,11 +960,13 @@ public class CapgoUpdater {
|
|
|
943
960
|
if (response.isSuccessful()) {
|
|
944
961
|
logger.info("Rate limit statistic sent");
|
|
945
962
|
} else {
|
|
946
|
-
logger.error("Error sending rate limit statistic
|
|
963
|
+
logger.error("Error sending rate limit statistic");
|
|
964
|
+
logger.debug("Response code: " + response.code());
|
|
947
965
|
}
|
|
948
966
|
}
|
|
949
967
|
} catch (final Exception e) {
|
|
950
|
-
logger.error("Failed to send rate limit statistic
|
|
968
|
+
logger.error("Failed to send rate limit statistic");
|
|
969
|
+
logger.debug("Error: " + e.getMessage());
|
|
951
970
|
}
|
|
952
971
|
}
|
|
953
972
|
|
|
@@ -1044,7 +1063,8 @@ public class CapgoUpdater {
|
|
|
1044
1063
|
json.put("defaultChannel", channel);
|
|
1045
1064
|
}
|
|
1046
1065
|
} catch (JSONException e) {
|
|
1047
|
-
logger.error("Error
|
|
1066
|
+
logger.error("Error getting latest version");
|
|
1067
|
+
logger.debug("JSONException: " + e.getMessage());
|
|
1048
1068
|
final Map<String, Object> retError = new HashMap<>();
|
|
1049
1069
|
retError.put("message", "Cannot get info: " + e);
|
|
1050
1070
|
retError.put("error", "json_error");
|
|
@@ -1116,7 +1136,8 @@ public class CapgoUpdater {
|
|
|
1116
1136
|
json = this.createInfoObject();
|
|
1117
1137
|
json.put("channel", channel);
|
|
1118
1138
|
} catch (JSONException e) {
|
|
1119
|
-
logger.error("Error
|
|
1139
|
+
logger.error("Error setting channel");
|
|
1140
|
+
logger.debug("JSONException: " + e.getMessage());
|
|
1120
1141
|
final Map<String, Object> retError = new HashMap<>();
|
|
1121
1142
|
retError.put("message", "Cannot get info: " + e);
|
|
1122
1143
|
retError.put("error", "json_error");
|
|
@@ -1162,7 +1183,8 @@ public class CapgoUpdater {
|
|
|
1162
1183
|
try {
|
|
1163
1184
|
json = this.createInfoObject();
|
|
1164
1185
|
} catch (JSONException e) {
|
|
1165
|
-
logger.error("Error
|
|
1186
|
+
logger.error("Error getting channel");
|
|
1187
|
+
logger.debug("JSONException: " + e.getMessage());
|
|
1166
1188
|
final Map<String, Object> retError = new HashMap<>();
|
|
1167
1189
|
retError.put("message", "Cannot get info: " + e);
|
|
1168
1190
|
retError.put("error", "json_error");
|
|
@@ -1284,7 +1306,8 @@ public class CapgoUpdater {
|
|
|
1284
1306
|
try {
|
|
1285
1307
|
json = this.createInfoObject();
|
|
1286
1308
|
} catch (JSONException e) {
|
|
1287
|
-
logger.error("Error creating info object
|
|
1309
|
+
logger.error("Error creating info object");
|
|
1310
|
+
logger.debug("JSONException: " + e.getMessage());
|
|
1288
1311
|
final Map<String, Object> retError = new HashMap<>();
|
|
1289
1312
|
retError.put("message", "Cannot get info: " + e);
|
|
1290
1313
|
retError.put("error", "json_error");
|
|
@@ -1304,7 +1327,8 @@ public class CapgoUpdater {
|
|
|
1304
1327
|
}
|
|
1305
1328
|
}
|
|
1306
1329
|
} catch (JSONException e) {
|
|
1307
|
-
logger.error("Error adding query parameters
|
|
1330
|
+
logger.error("Error adding query parameters");
|
|
1331
|
+
logger.debug("JSONException: " + e.getMessage());
|
|
1308
1332
|
}
|
|
1309
1333
|
|
|
1310
1334
|
Request request = new Request.Builder().url(urlBuilder.build()).get().build();
|
|
@@ -1425,7 +1449,8 @@ public class CapgoUpdater {
|
|
|
1425
1449
|
json.put("old_version_name", oldVersionName);
|
|
1426
1450
|
json.put("action", action);
|
|
1427
1451
|
} catch (JSONException e) {
|
|
1428
|
-
logger.error("Error
|
|
1452
|
+
logger.error("Error preparing stats");
|
|
1453
|
+
logger.debug("JSONException: " + e.getMessage());
|
|
1429
1454
|
return;
|
|
1430
1455
|
}
|
|
1431
1456
|
|
|
@@ -1440,7 +1465,8 @@ public class CapgoUpdater {
|
|
|
1440
1465
|
new okhttp3.Callback() {
|
|
1441
1466
|
@Override
|
|
1442
1467
|
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
|
1443
|
-
logger.error("Failed to send stats
|
|
1468
|
+
logger.error("Failed to send stats");
|
|
1469
|
+
logger.debug("Error: " + e.getMessage());
|
|
1444
1470
|
}
|
|
1445
1471
|
|
|
1446
1472
|
@Override
|
|
@@ -1452,9 +1478,11 @@ public class CapgoUpdater {
|
|
|
1452
1478
|
}
|
|
1453
1479
|
|
|
1454
1480
|
if (response.isSuccessful()) {
|
|
1455
|
-
logger.info("Stats
|
|
1481
|
+
logger.info("Stats sent successfully");
|
|
1482
|
+
logger.debug("Action: " + action + ", Version: " + versionName);
|
|
1456
1483
|
} else {
|
|
1457
|
-
logger.error("Error sending stats
|
|
1484
|
+
logger.error("Error sending stats");
|
|
1485
|
+
logger.debug("Response code: " + response.code());
|
|
1458
1486
|
}
|
|
1459
1487
|
}
|
|
1460
1488
|
}
|
|
@@ -1481,14 +1509,8 @@ public class CapgoUpdater {
|
|
|
1481
1509
|
result = BundleInfo.fromJSON(stored);
|
|
1482
1510
|
}
|
|
1483
1511
|
} catch (JSONException e) {
|
|
1484
|
-
logger.error(
|
|
1485
|
-
|
|
1486
|
-
trueId +
|
|
1487
|
-
"] stored value: '" +
|
|
1488
|
-
this.prefs.getString(trueId + INFO_SUFFIX, "") +
|
|
1489
|
-
"' error: " +
|
|
1490
|
-
e.getMessage()
|
|
1491
|
-
);
|
|
1512
|
+
logger.error("Failed to parse bundle info");
|
|
1513
|
+
logger.debug("Bundle ID: " + trueId + ", Error: " + e.getMessage());
|
|
1492
1514
|
// Clear corrupted data
|
|
1493
1515
|
this.editor.remove(trueId + INFO_SUFFIX);
|
|
1494
1516
|
this.editor.commit();
|
|
@@ -235,14 +235,11 @@ public class CryptoCipher {
|
|
|
235
235
|
detectedAlgorithm = "SHA-256";
|
|
236
236
|
} else if (decryptedChecksum.length == 4) {
|
|
237
237
|
detectedAlgorithm = "CRC32 (deprecated)";
|
|
238
|
-
logger.error(
|
|
239
|
-
"CRC32 checksum detected. This algorithm is deprecated and no longer supported. Please update your CLI to use SHA-256 checksums."
|
|
240
|
-
);
|
|
238
|
+
logger.error("CRC32 checksum detected - deprecated algorithm");
|
|
241
239
|
} else {
|
|
242
240
|
detectedAlgorithm = "unknown (" + decryptedChecksum.length + " bytes)";
|
|
243
|
-
logger.error(
|
|
244
|
-
|
|
245
|
-
);
|
|
241
|
+
logger.error("Unknown checksum algorithm detected");
|
|
242
|
+
logger.debug("Byte count: " + decryptedChecksum.length + ", Expected: 32 (SHA-256)");
|
|
246
243
|
}
|
|
247
244
|
logger.debug(
|
|
248
245
|
"Decrypted checksum: " +
|
|
@@ -255,7 +252,8 @@ public class CryptoCipher {
|
|
|
255
252
|
);
|
|
256
253
|
return result;
|
|
257
254
|
} catch (GeneralSecurityException e) {
|
|
258
|
-
logger.error("
|
|
255
|
+
logger.error("Checksum decryption failed");
|
|
256
|
+
logger.debug("Error: " + e.getMessage());
|
|
259
257
|
throw new IOException("Decryption failed: " + e.getMessage());
|
|
260
258
|
}
|
|
261
259
|
}
|
|
@@ -286,13 +284,10 @@ public class CryptoCipher {
|
|
|
286
284
|
String algorithm = detectChecksumAlgorithm(hexChecksum);
|
|
287
285
|
logger.debug(label + ": " + algorithm + " hex format (length: " + hexChecksum.length() + " chars)");
|
|
288
286
|
if (algorithm.contains("CRC32")) {
|
|
289
|
-
logger.error(
|
|
290
|
-
"CRC32 checksum detected. This algorithm is deprecated and no longer supported. Please update your CLI to use SHA-256 checksums."
|
|
291
|
-
);
|
|
287
|
+
logger.error("CRC32 checksum detected - deprecated algorithm");
|
|
292
288
|
} else if (algorithm.contains("unknown")) {
|
|
293
|
-
logger.error(
|
|
294
|
-
|
|
295
|
-
);
|
|
289
|
+
logger.error("Unknown checksum algorithm detected");
|
|
290
|
+
logger.debug("Char count: " + hexChecksum.length() + ", Expected: 64 (SHA-256)");
|
|
296
291
|
}
|
|
297
292
|
}
|
|
298
293
|
|
|
@@ -321,7 +316,8 @@ public class CryptoCipher {
|
|
|
321
316
|
}
|
|
322
317
|
return hexString.toString();
|
|
323
318
|
} catch (IOException e) {
|
|
324
|
-
logger.error("Cannot
|
|
319
|
+
logger.error("Cannot calculate checksum");
|
|
320
|
+
logger.debug("Path: " + file.getPath() + ", Error: " + e.getMessage());
|
|
325
321
|
return "";
|
|
326
322
|
}
|
|
327
323
|
}
|