diff --git a/ReactNativeClient/lib/models/Resource.js b/ReactNativeClient/lib/models/Resource.js index bb11ba6153..63c9a29375 100644 --- a/ReactNativeClient/lib/models/Resource.js +++ b/ReactNativeClient/lib/models/Resource.js @@ -72,7 +72,19 @@ class Resource extends BaseItem { await this.fsDriver().move(noExtPath, encryptedPath); } - await this.encryptionService().decryptFile(encryptedPath, plainTextPath); + try { + await this.encryptionService().decryptFile(encryptedPath, plainTextPath); + } catch (error) { + if (error.code === 'invalidIdentifier') { + // As the identifier is invalid it most likely means that this is not encrypted data + // at all. It can happen for example when there's a crash between the moment the data + // is decrypted and the resource item is updated. + this.logger().warn('Found a resource that was most likely already decrypted but was marked as encrypted. Marked it as decrypted: ' + item.id) + this.fsDriver().move(encryptedPath, plainTextPath); + } else { + throw error; + } + } decryptedItem.encryption_blob_encrypted = 0; return super.save(decryptedItem, { autoTimestamp: false }); @@ -151,6 +163,8 @@ class Resource extends BaseItem { for (let i = 0; i < ids.length; i++) { const id = ids[i]; const resource = await Resource.load(id); + if (!resource) continue; + const path = Resource.fullPath(resource); await this.fsDriver().remove(path); await super.batchDelete([id], options); diff --git a/ReactNativeClient/lib/services/EncryptionService.js b/ReactNativeClient/lib/services/EncryptionService.js index 01599f289f..71dc6a5d53 100644 --- a/ReactNativeClient/lib/services/EncryptionService.js +++ b/ReactNativeClient/lib/services/EncryptionService.js @@ -4,6 +4,7 @@ const { shim } = require('lib/shim.js'); const Setting = require('lib/models/Setting.js'); const MasterKey = require('lib/models/MasterKey'); const BaseItem = require('lib/models/BaseItem'); +const JoplinError = require('lib/JoplinError'); const { _ } = require('lib/locale.js'); function hexPad(s, length) { @@ -322,7 +323,7 @@ class EncryptionService { async decryptAbstract_(source, destination) { const identifier = await source.read(5); - if (!this.isValidHeaderIdentifier(identifier)) throw new Error('Invalid encryption identifier. Data is not actually encrypted? ID was: ' + identifier); + if (!this.isValidHeaderIdentifier(identifier)) throw new JoplinError('Invalid encryption identifier. Data is not actually encrypted? ID was: ' + identifier, 'invalidIdentifier'); const mdSizeHex = await source.read(6); const mdSize = parseInt(mdSizeHex, 16); if (isNaN(mdSize) || !mdSize) throw new Error('Invalid header metadata size: ' + mdSizeHex);