diff --git a/CliClient/tests/synchronizer.js b/CliClient/tests/synchronizer.js
index 9cbd1b129..2e6c670ff 100644
--- a/CliClient/tests/synchronizer.js
+++ b/CliClient/tests/synchronizer.js
@@ -1034,6 +1034,33 @@ describe('Synchronizer', function() {
expect(allEncrypted).toBe(false);
}));
+ it('should set the resource file size after decryption', asyncTest(async () => {
+ Setting.setValue('encryption.enabled', true);
+ const masterKey = await loadEncryptionMasterKey();
+
+ let folder1 = await Folder.save({ title: "folder1" });
+ let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
+ await shim.attachFileToNote(note1, __dirname + '/../tests/support/photo.jpg');
+ let resource1 = (await Resource.all())[0];
+ await Resource.setFileSizeOnly(resource1.id, -1);
+ let resourcePath1 = Resource.fullPath(resource1);
+ await synchronizer().start();
+
+ await switchClient(2);
+
+ await synchronizer().start();
+ Setting.setObjectKey('encryption.passwordCache', masterKey.id, '123456');
+ await encryptionService().loadMasterKeysFromSettings();
+
+ const fetcher = new ResourceFetcher(() => { return synchronizer().api() });
+ fetcher.queueDownload(resource1.id);
+ await fetcher.waitForAllFinished();
+ await decryptionWorker().start();
+
+ const resource1_2 = await Resource.load(resource1.id);
+ expect(resource1_2.size).toBe(2720);
+ }));
+
it('should encrypt remote resources after encryption has been enabled', asyncTest(async () => {
while (insideBeforeEach) await time.msleep(100);
diff --git a/ReactNativeClient/ios/Joplin/Info.plist b/ReactNativeClient/ios/Joplin/Info.plist
index f96b7c737..037989214 100644
--- a/ReactNativeClient/ios/Joplin/Info.plist
+++ b/ReactNativeClient/ios/Joplin/Info.plist
@@ -17,11 +17,11 @@
CFBundlePackageType
APPL
CFBundleShortVersionString
- 10.0.31
+ 10.0.32
CFBundleSignature
????
CFBundleVersion
- 31
+ 32
LSRequiresIPhoneOS
NSAppTransportSecurity
diff --git a/ReactNativeClient/lib/models/Resource.js b/ReactNativeClient/lib/models/Resource.js
index 2219fbcdc..7427ec976 100644
--- a/ReactNativeClient/lib/models/Resource.js
+++ b/ReactNativeClient/lib/models/Resource.js
@@ -6,6 +6,7 @@ const Setting = require('lib/models/Setting.js');
const ArrayUtils = require('lib/ArrayUtils.js');
const pathUtils = require('lib/path-utils.js');
const { mime } = require('lib/mime-utils.js');
+const { shim } = require('lib/shim');
const { filename, safeFilename } = require('lib/path-utils.js');
const { FsDriverDummy } = require('lib/fs-driver-dummy.js');
const markdownUtils = require('lib/markdownUtils');
@@ -214,6 +215,10 @@ class Resource extends BaseItem {
await ResourceLocalState.save(Object.assign({}, state, { resource_id: id }));
}
+ static async needFileSizeSet() {
+ return this.modelSelectAll('SELECT * FROM resources WHERE `size` < 0 AND encryption_blob_encrypted = 0');
+ }
+
// Only set the `size` field and nothing else, not even the update_time
// This is because it's only necessary to do it once after migration 20
// and each client does it so there's no need to sync the resource.
diff --git a/ReactNativeClient/lib/services/DecryptionWorker.js b/ReactNativeClient/lib/services/DecryptionWorker.js
index 93f947550..b5ec01cbe 100644
--- a/ReactNativeClient/lib/services/DecryptionWorker.js
+++ b/ReactNativeClient/lib/services/DecryptionWorker.js
@@ -1,5 +1,6 @@
const BaseItem = require('lib/models/BaseItem');
const Resource = require('lib/models/Resource');
+const ResourceService = require('lib/services/ResourceService');
const { Logger } = require('lib/logger.js');
class DecryptionWorker {
@@ -132,6 +133,10 @@ class DecryptionWorker {
throw error;
}
+ // 2019-05-12: Temporary to set the file size of the resources
+ // that weren't set in migration/20.js due to being on the sync target
+ await ResourceService.autoSetFileSizes();
+
this.logger().info('DecryptionWorker: completed decryption.');
this.dispatchReport({ state: 'idle' });
diff --git a/ReactNativeClient/lib/services/ResourceFetcher.js b/ReactNativeClient/lib/services/ResourceFetcher.js
index dbcfc9a04..f53e28c62 100644
--- a/ReactNativeClient/lib/services/ResourceFetcher.js
+++ b/ReactNativeClient/lib/services/ResourceFetcher.js
@@ -1,5 +1,6 @@
const Resource = require('lib/models/Resource');
const BaseService = require('lib/services/BaseService');
+const ResourceService = require('lib/services/ResourceService');
const BaseSyncTarget = require('lib/BaseSyncTarget');
const { Logger } = require('lib/logger.js');
const EventEmitter = require('events');
@@ -103,14 +104,17 @@ class ResourceFetcher extends BaseService {
// 2019-05-12: This is only necessary to set the file size of the resources that come via
// sync. The other ones have been done using migrations/20.js. This code can be removed
// after a few months.
- if (resource.size < 0 && localResourceContentPath) {
- const itDoes = await shim.fsDriver().waitTillExists(localResourceContentPath);
- const fileStat = await shim.fsDriver().stat(localResourceContentPath);
- await Resource.setFileSizeOnly(resource.id, fileStat.size);
+ if (resource.size < 0 && localResourceContentPath && !resource.encryption_blob_encrypted) {
+ await ResourceService.autoSetFileSizes();
}
delete this.fetchingItems_[resource.id];
this.scheduleQueueProcess();
+
+ // Note: This downloadComplete event is not really right or useful because the resource
+ // might still be encrypted and the caller usually can't do much with this. In particular
+ // the note being displayed will refresh the resource images but since they are still
+ // encrypted it's not useful. Probably, the views should listen to DecryptionWorker events instead.
if (emitDownloadComplete) this.eventEmitter_.emit('downloadComplete', { id: resource.id });
this.updateReport();
}
diff --git a/ReactNativeClient/lib/services/ResourceService.js b/ReactNativeClient/lib/services/ResourceService.js
index 153156296..219af8de9 100644
--- a/ReactNativeClient/lib/services/ResourceService.js
+++ b/ReactNativeClient/lib/services/ResourceService.js
@@ -111,6 +111,20 @@ class ResourceService extends BaseService {
}
}
+ static async autoSetFileSize(resourceId, filePath) {
+ const itDoes = await shim.fsDriver().waitTillExists(filePath);
+ const fileStat = await shim.fsDriver().stat(filePath);
+ await Resource.setFileSizeOnly(resourceId, fileStat.size);
+ }
+
+ static async autoSetFileSizes() {
+ const resources = await Resource.needFileSizeSet();
+
+ for (const r of resources) {
+ await this.autoSetFileSize(r.id, Resource.fullPath(r));
+ }
+ }
+
async maintenance() {
await this.indexNoteResources();
await this.deleteOrphanResources();