1212#include < QDebug>
1313#include < QDir>
1414#include < QElapsedTimer>
15+ #include < QEventLoop>
16+ #include < QFutureWatcher>
1517#include < QMessageBox>
1618#include < QMimeDatabase>
1719#include < QQueue>
2123#include < QSqlError>
2224#include < QSqlRecord>
2325#include < QTemporaryFile>
26+ #include < QThread>
2427#include < QUrl>
28+ #include < QtConcurrent/QtConcurrentRun>
2529#include < utility>
2630
2731#include " api/noteapi.h"
@@ -408,6 +412,37 @@ static QString buildNoteEncryptionEnvelope(const QString &cipherText, const QStr
408412 QString::number (NoteEncryptionKdfIterations), salt, NoteEncryptionCipher, nonce, mac,
409413 cipherText);
410414}
415+
416+ static QString encryptNoteTextWithBotan (const QString &text, const QString &password) {
417+ BotanWrapper botanWrapper;
418+ botanWrapper.setPassword (password);
419+ const QString salt = BotanWrapper::randomBytesBase64 (NoteEncryptionSaltBytes);
420+ const QString nonce = BotanWrapper::randomBytesBase64 (NoteEncryptionNonceBytes);
421+ QString mac;
422+ const QString encryptedText =
423+ botanWrapper.EncryptV2 (text, salt, nonce, NoteEncryptionKdfIterations, &mac);
424+
425+ return encryptedText.isEmpty () ? encryptedText
426+ : buildNoteEncryptionEnvelope (encryptedText, salt, nonce, mac);
427+ }
428+
429+ static QString encryptNoteTextWithBotanInBackground (const QString &text, const QString &password) {
430+ if (qApp == nullptr || QThread::currentThread () != qApp->thread ()) {
431+ return encryptNoteTextWithBotan (text, password);
432+ }
433+
434+ QFutureWatcher<QString> watcher;
435+ QEventLoop loop;
436+ QObject::connect (&watcher, &QFutureWatcher<QString>::finished, &loop, &QEventLoop::quit);
437+ watcher.setFuture (
438+ QtConcurrent::run ([text, password]() { return encryptNoteTextWithBotan (text, password); }));
439+
440+ if (!watcher.isFinished ()) {
441+ loop.exec ();
442+ }
443+
444+ return watcher.result ();
445+ }
411446} // namespace
412447
413448int Note::getId () const { return this ->_id ; }
@@ -2245,8 +2280,22 @@ bool Note::storeNoteTextFileToDisk(bool ¤tNoteTextChanged,
22452280
22462281 // if we find a decrypted text to encrypt, then we attempt to encrypt it
22472282 if (!_decryptedNoteText.isEmpty ()) {
2283+ const QString decryptedNoteText = _decryptedNoteText;
22482284 _noteText = _decryptedNoteText;
2249- encryptNoteText ();
2285+
2286+ encryptNoteText (false );
2287+
2288+ if (_id > 0 ) {
2289+ const Note latestNote = Note::fetch (_id);
2290+
2291+ if (latestNote.isFetched () && latestNote._decryptedNoteText != decryptedNoteText) {
2292+ qDebug ()
2293+ << __func__
2294+ << " - encrypted note changed while encryption was running, deferring save" ;
2295+ return false ;
2296+ }
2297+ }
2298+
22502299 _decryptedNoteText = QLatin1String (" " );
22512300 }
22522301
@@ -4266,7 +4315,7 @@ void Note::resetChecksumStats() {
42664315/* *
42674316 * Encrypts the note text with the note's crypto key
42684317 */
4269- QString Note::encryptNoteText () {
4318+ QString Note::encryptNoteText (bool persist ) {
42704319 if (_noteText.isEmpty ()) {
42714320 return _noteText;
42724321 }
@@ -4314,16 +4363,7 @@ QString Note::encryptNoteText() {
43144363 if (encryptedText.isEmpty ()) {
43154364 // fallback to Botan
43164365 // encrypt the text
4317- BotanWrapper botanWrapper;
4318- botanWrapper.setPassword (_cryptoPassword);
4319- const QString salt = BotanWrapper::randomBytesBase64 (NoteEncryptionSaltBytes);
4320- const QString nonce = BotanWrapper::randomBytesBase64 (NoteEncryptionNonceBytes);
4321- QString mac;
4322- encryptedText =
4323- botanWrapper.EncryptV2 (text, salt, nonce, NoteEncryptionKdfIterations, &mac);
4324- if (!encryptedText.isEmpty ()) {
4325- encryptedText = buildNoteEncryptionEnvelope (encryptedText, salt, nonce, mac);
4326- }
4366+ encryptedText = encryptNoteTextWithBotanInBackground (text, _cryptoPassword);
43274367
43284368 // SimpleCrypt *crypto = new
43294369 // SimpleCrypt(static_cast<quint64>(cryptoKey)); QString
@@ -4334,8 +4374,10 @@ QString Note::encryptNoteText() {
43344374 _noteText +=
43354375 encryptedText + QStringLiteral (" \n " ) + QStringLiteral (NOTE_TEXT_ENCRYPTION_POST_STRING );
43364376
4337- // store note
4338- store ();
4377+ if (persist) {
4378+ // store note
4379+ store ();
4380+ }
43394381
43404382 return _noteText;
43414383}
0 commit comments