From f94fc34d4fc336360cc6e92e27fadae6d302c3c1 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Thu, 22 Feb 2024 00:33:20 +0100 Subject: [PATCH 001/110] Cleanup OpenPgpImportPopupView code --- dev/View/Popup/OpenPgpImport.js | 48 +++++++++++++++------------------ 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/dev/View/Popup/OpenPgpImport.js b/dev/View/Popup/OpenPgpImport.js index 90f7e5c84..896cc0829 100644 --- a/dev/View/Popup/OpenPgpImport.js +++ b/dev/View/Popup/OpenPgpImport.js @@ -78,36 +78,30 @@ export class OpenPgpImportPopupView extends AbstractViewPopup { this.keyError(!keyTrimmed); this.keyErrorMessage(''); - if (!keyTrimmed) { - return; - } - - let match = null, - count = 30, - done = false; - // eslint-disable-next-line max-len - const reg = /[-]{3,6}BEGIN[\s]PGP[\s](PRIVATE|PUBLIC)[\s]KEY[\s]BLOCK[-]{3,6}[\s\S]+?[-]{3,6}END[\s]PGP[\s](PRIVATE|PUBLIC)[\s]KEY[\s]BLOCK[-]{3,6}/gi; - - do { - match = reg.exec(keyTrimmed); - if (match && 0 < count) { - if (match[0] && match[1] && match[2] && match[1] === match[2]) { - const GnuPG = this.saveGnuPG() && GnuPGUserStore.isSupported(), - backup = this.saveServer(); - PgpUserStore.importKey(this.key(), GnuPG, backup); - } - --count; + if (keyTrimmed) { + let match = null, + count = 30, done = false; - } else { - done = true; - } - } while (!done); + const GnuPG = this.saveGnuPG() && GnuPGUserStore.isSupported(), + backup = this.saveServer(), + // eslint-disable-next-line max-len + reg = /[-]{3,6}BEGIN[\s]PGP[\s](PRIVATE|PUBLIC)[\s]KEY[\s]BLOCK[-]{3,6}[\s\S]+?[-]{3,6}END[\s]PGP[\s](PRIVATE|PUBLIC)[\s]KEY[\s]BLOCK[-]{3,6}/gi; - if (this.keyError()) { - return; + do { + match = reg.exec(keyTrimmed); + if (match && 0 < count) { + if (match[0] && match[1] && match[2] && match[1] === match[2]) { + PgpUserStore.importKey(this.key(), GnuPG, backup); + } + --count; + done = false; + } else { + done = true; + } + } while (!done); + + this.close(); } - - this.close(); } onShow(key) { From 70a7784d68795692293a1573c570fbd7d63431ee Mon Sep 17 00:00:00 2001 From: tinola Date: Thu, 22 Feb 2024 17:32:39 +0100 Subject: [PATCH 002/110] update polish translation --- snappymail/v/0.0.0/app/localization/pl-PL/user.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/snappymail/v/0.0.0/app/localization/pl-PL/user.json b/snappymail/v/0.0.0/app/localization/pl-PL/user.json index 68e0a956c..249c65a9b 100644 --- a/snappymail/v/0.0.0/app/localization/pl-PL/user.json +++ b/snappymail/v/0.0.0/app/localization/pl-PL/user.json @@ -302,10 +302,10 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Utwórz kopię zapasową klucza prywatnego na serwerze" }, "SMIME": { - "CERTIFICATES": "S\/MIME Certificates", + "CERTIFICATES": "Certyfikaty S\/MIME", "SIGNED_MESSAGE": "Wiadomość podpisana S\/MIME", "ENCRYPTED_MESSAGE": "Wiadomość zaszyfrowana S\/MIME", - "PRIVATE_KEY_OF": "S\/MIME private key of %EMAIL%" + "PRIVATE_KEY_OF": "Klucz prywatny S\/MIME adresu %EMAIL%" }, "POPUPS_FILTER": { "TITLE_CREATE_FILTER": "Czy stworzyć filtr?", From 6ac5cea2e488b5e16053724d379ff91089ed4e7c Mon Sep 17 00:00:00 2001 From: tinola Date: Thu, 22 Feb 2024 17:51:20 +0100 Subject: [PATCH 003/110] small fix --- snappymail/v/0.0.0/app/localization/pl-PL/user.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snappymail/v/0.0.0/app/localization/pl-PL/user.json b/snappymail/v/0.0.0/app/localization/pl-PL/user.json index 249c65a9b..065bdab89 100644 --- a/snappymail/v/0.0.0/app/localization/pl-PL/user.json +++ b/snappymail/v/0.0.0/app/localization/pl-PL/user.json @@ -281,7 +281,7 @@ "VERIFY": "Weryfikuj", "GOOD_SIGNATURE": "Poprawnie podpisana przez %USER%", "ERROR": "Błąd %TYPE%: %ERROR%", - "CREATE_SELF_SIGNED": "Utwórz samodzielnie podpisanym certyfikatem", + "CREATE_SELF_SIGNED": "Utwórz samodzielnie podpisany certyfikat", "VALID_UNTIL": "Ważny do" }, "OPENPGP": { From 6f33bc23d3a1bc276ee31faf7de75571bfa50019 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Fri, 23 Feb 2024 03:14:36 +0100 Subject: [PATCH 004/110] Added Import S/MIME certificate popup And much better handling of the sign and encrypt options --- dev/Settings/User/Security.js | 5 + dev/Stores/User/GnuPG.js | 3 +- dev/Stores/User/Mailvelope.js | 124 +++++++++++ dev/Stores/User/Pgp.js | 152 +------------ dev/View/Popup/Compose.js | 206 +++++++++++------- dev/View/Popup/SMimeImport.js | 50 +++++ .../app/libraries/RainLoop/Actions/SMime.php | 9 + .../v/0.0.0/app/localization/ar-SA/user.json | 1 + .../v/0.0.0/app/localization/bg-BG/user.json | 1 + .../v/0.0.0/app/localization/cs-CZ/user.json | 1 + .../v/0.0.0/app/localization/da-DK/user.json | 1 + .../v/0.0.0/app/localization/de-DE/user.json | 1 + .../v/0.0.0/app/localization/el-GR/user.json | 1 + .../v/0.0.0/app/localization/en-GB/user.json | 1 + .../v/0.0.0/app/localization/en/user.json | 1 + .../v/0.0.0/app/localization/es-ES/user.json | 1 + .../v/0.0.0/app/localization/et-EE/user.json | 1 + .../v/0.0.0/app/localization/eu/user.json | 1 + .../v/0.0.0/app/localization/fa-IR/user.json | 1 + .../v/0.0.0/app/localization/fi-FI/user.json | 1 + .../v/0.0.0/app/localization/fr-FR/user.json | 1 + .../v/0.0.0/app/localization/hu-HU/user.json | 1 + .../v/0.0.0/app/localization/id-ID/user.json | 1 + .../v/0.0.0/app/localization/is-IS/user.json | 1 + .../v/0.0.0/app/localization/it-IT/user.json | 1 + .../v/0.0.0/app/localization/ja-JP/user.json | 1 + .../v/0.0.0/app/localization/ko-KR/user.json | 1 + .../v/0.0.0/app/localization/lt-LT/user.json | 1 + .../v/0.0.0/app/localization/lv-LV/user.json | 1 + .../v/0.0.0/app/localization/nb-NO/user.json | 1 + .../v/0.0.0/app/localization/nl-NL/user.json | 1 + .../v/0.0.0/app/localization/pl-PL/user.json | 1 + .../v/0.0.0/app/localization/pt-BR/user.json | 1 + .../v/0.0.0/app/localization/pt-PT/user.json | 1 + .../v/0.0.0/app/localization/pt/user.json | 1 + .../v/0.0.0/app/localization/ro-RO/user.json | 1 + .../v/0.0.0/app/localization/ru-RU/user.json | 1 + .../v/0.0.0/app/localization/sk-SK/user.json | 1 + .../v/0.0.0/app/localization/sl-SI/user.json | 1 + .../v/0.0.0/app/localization/sv-SE/user.json | 1 + .../v/0.0.0/app/localization/tr-TR/user.json | 1 + .../v/0.0.0/app/localization/uk-UA/user.json | 1 + .../v/0.0.0/app/localization/vi-VN/user.json | 1 + .../v/0.0.0/app/localization/zh-CN/user.json | 1 + .../v/0.0.0/app/localization/zh-TW/user.json | 1 + .../Views/User/PopupsSMimeImport.html | 13 ++ .../Views/User/SettingsSecurity.html | 2 + 47 files changed, 375 insertions(+), 227 deletions(-) create mode 100644 dev/Stores/User/Mailvelope.js create mode 100644 dev/View/Popup/SMimeImport.js create mode 100644 snappymail/v/0.0.0/app/templates/Views/User/PopupsSMimeImport.html diff --git a/dev/Settings/User/Security.js b/dev/Settings/User/Security.js index cabde4a80..f73cfa882 100644 --- a/dev/Settings/User/Security.js +++ b/dev/Settings/User/Security.js @@ -16,6 +16,7 @@ import { OpenPgpImportPopupView } from 'View/Popup/OpenPgpImport'; import { OpenPgpGeneratePopupView } from 'View/Popup/OpenPgpGenerate'; import { SMimeUserStore } from 'Stores/User/SMime'; +import { SMimeImportPopupView } from 'View/Popup/SMimeImport'; import Remote from 'Remote/User/Fetch'; @@ -70,6 +71,10 @@ export class UserSettingsSecurity extends AbstractViewSettings { ); } + importToSMime() { + showScreenPopup(SMimeImportPopupView); + } + onBuild() { /** * Create an iframe to display the Mailvelope keyring settings. diff --git a/dev/Stores/User/GnuPG.js b/dev/Stores/User/GnuPG.js index cd121194d..f5106588f 100644 --- a/dev/Stores/User/GnuPG.js +++ b/dev/Stores/User/GnuPG.js @@ -35,7 +35,8 @@ export const GnuPGUserStore = new class { this.keyring = null; this.publicKeys([]); this.privateKeys([]); - Remote.request('GnupgGetKeys', + SettingsCapa('GnuPG') + && Remote.request('GnupgGetKeys', (iError, oData) => { if (oData?.Result) { this.keyring = oData.Result; diff --git a/dev/Stores/User/Mailvelope.js b/dev/Stores/User/Mailvelope.js new file mode 100644 index 000000000..e811806f0 --- /dev/null +++ b/dev/Stores/User/Mailvelope.js @@ -0,0 +1,124 @@ +import { SettingsGet } from 'Common/Globals'; + +// https://mailvelope.github.io/mailvelope/Keyring.html +let mailvelopeKeyring = null; + +export const MailvelopeUserStore = { + keyring: null, + + loadKeyring(identifier) { + identifier = identifier || SettingsGet('Email'); + if (window.mailvelope) { + const fn = keyring => { + mailvelopeKeyring = keyring; + console.log('mailvelope ready'); + }; + mailvelope.getKeyring().then(fn, err => { + if (identifier) { + // attempt to create a new keyring for this app/user + mailvelope.createKeyring(identifier).then(fn, err => console.error(err)); + } else { + console.error(err); + } + }); + addEventListener('mailvelope-disconnect', event => { + alert('Mailvelope is updated to version ' + event.detail.version + '. Reload page'); + }, false); + } else { + addEventListener('mailvelope', () => this.loadKeyring(identifier)); + } + }, + + async hasPublicKeyForEmails(recipients) { + const + mailvelope = mailvelopeKeyring && await mailvelopeKeyring.validKeyForAddress(recipients) + /*.then(LookupResult => Object.entries(LookupResult))*/, + entries = mailvelope && Object.entries(mailvelope); + return entries && entries.filter(value => value[1]).length === recipients.length; + }, + + async getPrivateKeyFor(email/*, sign*/) { + if (mailvelopeKeyring && await mailvelopeKeyring.hasPrivateKey({email:email})) { + return ['mailvelope', email]; + } + return false; + }, + + async decrypt(message) { + // Try Mailvelope (does not support inline images) + if (mailvelopeKeyring) { + const sender = message.from[0].email, + armoredText = message.plain(); + try { + let emails = [...message.from,...message.to,...message.cc].validUnique(), + i = emails.length; + while (i--) { + if (await this.getMailvelopePrivateKeyFor(emails[i].email)) { + /** + * https://mailvelope.github.io/mailvelope/Mailvelope.html#createEncryptedFormContainer + * Creates an iframe to display an encrypted form + */ + // mailvelope.createEncryptedFormContainer('#mailvelope-form'); + /** + * https://mailvelope.github.io/mailvelope/Mailvelope.html#createDisplayContainer + * Creates an iframe to display the decrypted content of the encrypted mail. + */ + const body = message.body; + body.textContent = ''; + let result = await mailvelope.createDisplayContainer( + '#'+body.id, + armoredText, + mailvelopeKeyring, + { + senderAddress: sender + // emails[i].email + } + ); + if (result) { + if (result.error?.message) { + if ('PWD_DIALOG_CANCEL' !== result.error.code) { + alert(result.error.code + ': ' + result.error.message); + } + } else { + body.classList.add('mailvelope'); + return true; + } + } + break; + } + } + } catch (err) { + console.error(err); + } + } + } + /** + * Returns headers that should be added to an outgoing email. + * So far this is only the autocrypt header. + */ +/* + mailvelopeKeyring.additionalHeadersForOutgoingEmail(from: 'abc@web.de') + .then(function(additional) { + console.log('additionalHeadersForOutgoingEmail', additional); + // logs: {autocrypt: "addr=abc@web.de; prefer-encrypt=mutual; keydata=..."} + }); + + mailvelopeKeyring.addSyncHandler(syncHandlerObj) + mailvelopeKeyring.createKeyBackupContainer(selector, options) + mailvelopeKeyring.createKeyGenContainer(selector, { +// userIds: [], + keySize: 4096 + }) + + mailvelopeKeyring.exportOwnPublicKey(emailAddr).then() + mailvelopeKeyring.importPublicKey(armored) + + // https://mailvelope.github.io/mailvelope/global.html#SyncHandlerObject + mailvelopeKeyring.addSyncHandler({ + uploadSync + downloadSync + backup + restore + }); +*/ +}; diff --git a/dev/Stores/User/Pgp.js b/dev/Stores/User/Pgp.js index 3895c4194..7eb788464 100644 --- a/dev/Stores/User/Pgp.js +++ b/dev/Stores/User/Pgp.js @@ -8,12 +8,10 @@ import { SettingsCapa, SettingsGet } from 'Common/Globals'; import { GnuPGUserStore } from 'Stores/User/GnuPG'; import { OpenPGPUserStore } from 'Stores/User/OpenPGP'; +import { MailvelopeUserStore } from 'Stores/User/Mailvelope'; import Remote from 'Remote/User/Fetch'; -// https://mailvelope.github.io/mailvelope/Keyring.html -let mailvelopeKeyring = null; - export const BEGIN_PGP_MESSAGE = '-----BEGIN PGP MESSAGE-----', // BEGIN_PGP_SIGNATURE = '-----BEGIN PGP SIGNATURE-----', @@ -37,32 +35,9 @@ export const } loadKeyrings(identifier) { - identifier = identifier || SettingsGet('Email'); - if (window.mailvelope) { - const fn = keyring => { - mailvelopeKeyring = keyring; - console.log('mailvelope ready'); - }; - mailvelope.getKeyring().then(fn, err => { - if (identifier) { - // attempt to create a new keyring for this app/user - mailvelope.createKeyring(identifier).then(fn, err => console.error(err)); - } else { - console.error(err); - } - }); - addEventListener('mailvelope-disconnect', event => { - alert('Mailvelope is updated to version ' + event.detail.version + '. Reload page'); - }, false); - } else { - addEventListener('mailvelope', () => this.loadKeyrings(identifier)); - } - + MailvelopeUserStore.loadKeyring(identifier); OpenPGPUserStore.loadKeyrings(); - - if (SettingsCapa('GnuPG')) { - GnuPGUserStore.loadKeyrings(); - } + GnuPGUserStore.loadKeyrings(); } /** @@ -92,22 +67,14 @@ export const } ); } - OpenPGPUserStore.isSupported() && OpenPGPUserStore.importKey(key); - } - - async mailvelopeHasPublicKeyForEmails(recipients) { - const - mailvelope = mailvelopeKeyring && await mailvelopeKeyring.validKeyForAddress(recipients) - /*.then(LookupResult => Object.entries(LookupResult))*/, - entries = mailvelope && Object.entries(mailvelope); - return entries && entries.filter(value => value[1]).length === recipients.length; + OpenPGPUserStore.importKey(key); } /** * Checks if verifying/encrypting a message is possible with given email addresses. * Returns the first library that can. */ - async hasPublicKeyForEmails(recipients) { + hasPublicKeyForEmails(recipients) { if (recipients.length) { if (GnuPGUserStore.hasPublicKeyForEmails(recipients)) { return 'gnupg'; @@ -119,40 +86,15 @@ export const return false; } - async getMailvelopePrivateKeyFor(email/*, sign*/) { - if (mailvelopeKeyring && await mailvelopeKeyring.hasPrivateKey({email:email})) { - return ['mailvelope', email]; - } - return false; - } - - /** - * Checks if signing a message is possible with given email address. - * Returns the first library that can. - */ - async getKeyForSigning(email) { - let key = OpenPGPUserStore.getPrivateKeyFor(email, 1); - if (key) { - return ['openpgp', key]; - } - - key = GnuPGUserStore.getPrivateKeyFor(email, 1); - if (key) { - return ['gnupg', key]; - } - - // return await this.getMailvelopePrivateKeyFor(email, 1); - } - async decrypt(message) { - const sender = message.from[0].email, - armoredText = message.plain(); + const armoredText = message.plain(); if (!this.isEncrypted(armoredText)) { throw Error('Not armored text'); } // Try OpenPGP.js if (OpenPGPUserStore.isSupported()) { + const sender = message.from[0].email; let result = await OpenPGPUserStore.decrypt(armoredText, sender); if (result) { return result; @@ -160,52 +102,9 @@ export const } // Try Mailvelope (does not support inline images) - if (mailvelopeKeyring) { - try { - let emails = [...message.from,...message.to,...message.cc].validUnique(), - i = emails.length; - while (i--) { - if (await this.getMailvelopePrivateKeyFor(emails[i].email)) { - /** - * https://mailvelope.github.io/mailvelope/Mailvelope.html#createEncryptedFormContainer - * Creates an iframe to display an encrypted form - */ - // mailvelope.createEncryptedFormContainer('#mailvelope-form'); - /** - * https://mailvelope.github.io/mailvelope/Mailvelope.html#createDisplayContainer - * Creates an iframe to display the decrypted content of the encrypted mail. - */ - const body = message.body; - body.textContent = ''; - let result = await mailvelope.createDisplayContainer( - '#'+body.id, - armoredText, - mailvelopeKeyring, - { - senderAddress: sender - // emails[i].email - } - ); - if (result) { - if (result.error?.message) { - if ('PWD_DIALOG_CANCEL' !== result.error.code) { - alert(result.error.code + ': ' + result.error.message); - } - } else { - body.classList.add('mailvelope'); - return true; - } - } - break; - } - } - } catch (err) { - console.error(err); - } - } - - // Now try GnuPG - return GnuPGUserStore.decrypt(message); + return (await MailvelopeUserStore.decrypt(message)) + // Or try GnuPG + || GnuPGUserStore.decrypt(message); } async verify(message) { @@ -248,35 +147,4 @@ export const } return false; } - - /** - * Returns headers that should be added to an outgoing email. - * So far this is only the autocrypt header. - */ - /* - mailvelopeKeyring.additionalHeadersForOutgoingEmail(from: 'abc@web.de') - .then(function(additional) { - console.log('additionalHeadersForOutgoingEmail', additional); - // logs: {autocrypt: "addr=abc@web.de; prefer-encrypt=mutual; keydata=..."} - }); - - mailvelopeKeyring.addSyncHandler(syncHandlerObj) - mailvelopeKeyring.createKeyBackupContainer(selector, options) - mailvelopeKeyring.createKeyGenContainer(selector, { - // userIds: [], - keySize: 4096 - }) - - mailvelopeKeyring.exportOwnPublicKey(emailAddr).then() - mailvelopeKeyring.importPublicKey(armored) - - // https://mailvelope.github.io/mailvelope/global.html#SyncHandlerObject - mailvelopeKeyring.addSyncHandler({ - uploadSync - downloadSync - backup - restore - }); - */ - }; diff --git a/dev/View/Popup/Compose.js b/dev/View/Popup/Compose.js index d5b5de78c..e0eee9391 100644 --- a/dev/View/Popup/Compose.js +++ b/dev/View/Popup/Compose.js @@ -32,6 +32,7 @@ import { FolderUserStore } from 'Stores/User/Folder'; import { PgpUserStore } from 'Stores/User/Pgp'; import { OpenPGPUserStore } from 'Stores/User/OpenPGP'; import { GnuPGUserStore } from 'Stores/User/GnuPG'; +import { MailvelopeUserStore } from 'Stores/User/Mailvelope'; //import { OpenPgpImportPopupView } from 'View/Popup/OpenPgpImport'; import { SMimeUserStore } from 'Stores/User/SMime'; import { Passphrases } from 'Storage/Passphrases'; @@ -255,13 +256,6 @@ export class ComposePopupView extends AbstractViewPopup { doSign: false, doEncrypt: false, - pgpSignKey: false, - canPgpEncrypt: false, - canMailvelope: false, - - canSMimeSign: false, - canSMimeEncrypt: false, - draftsFolder: '', draftUid: 0, sending: false, @@ -284,6 +278,8 @@ export class ComposePopupView extends AbstractViewPopup { }); this.attachments = koArrayWithDestroy(); + this.encryptOptions = koArrayWithDestroy(); + this.signOptions = koArrayWithDestroy(); this.dragAndDropOver = ko.observable(false).extend({ debounce: 1 }); this.dragAndDropVisible = ko.observable(false).extend({ debounce: 1 }); @@ -336,11 +332,9 @@ export class ComposePopupView extends AbstractViewPopup { attachmentsInProcessCount: () => this.attachmentsInProcess.length, isDraft: () => this.draftsFolder() && this.draftUid(), - canSign: () => { - let s = this.canSMimeSign(); - return this.pgpSignKey() || s; - }, - canEncrypt: () => this.canPgpEncrypt() | this.canSMimeEncrypt(), + canEncrypt: () => this.encryptOptions().length, + canMailvelope: () => this.encryptOptions.includes('Mailvelope'), + canSign: () => this.signOptions().length, identitiesOptions: () => IdentityUserStore.map(item => ({ @@ -361,24 +355,14 @@ export class ComposePopupView extends AbstractViewPopup { currentIdentity: value => { if (value) { - const smime = !!(value.smimeKey() && value.smimeCertificate()); this.from(value.formattedName()); this.doEncrypt(value.pgpEncrypt()/* || SettingsUserStore.pgpEncrypt()*/); - this.doSign(smime || value.pgpSign()/* || SettingsUserStore.pgpSign()*/); - this.canSMimeSign(smime); + this.doSign(value.pgpSign()/* || SettingsUserStore.pgpSign()*/); } }, - from: value => { - this.pgpSignKey(false); - value = getEmail(value); - value && PgpUserStore.getKeyForSigning(value).then(result => { - console.log({ - email: value, - pgpSignKey:result - }); - this.pgpSignKey(result) - }); + from: () => { + this.initSign(); this.initEncrypt(); }, @@ -1381,29 +1365,57 @@ export class ComposePopupView extends AbstractViewPopup { ].join(',').split(',').map(value => getEmail(value.trim())).validUnique(); } - initEncrypt() { - const recipients = this.allRecipients(); - PgpUserStore.hasPublicKeyForEmails(recipients).then(result => { - console.log({canPgpEncrypt:result}); - this.canPgpEncrypt(result); - }); - PgpUserStore.mailvelopeHasPublicKeyForEmails(recipients).then(result => { - console.log({canMailvelope:result}); - this.canMailvelope(result); - if (!result) { - 'mailvelope' === this.viewArea() && this.bodyArea(); -// this.dropMailvelope(); - } - }); - const count = recipients.length, + /** + * Checks if signing a message is possible with from email address. + * And sets all that can. + */ + initSign() { + let options = [], identity = this.currentIdentity(), - from = (identity.smimeKey() && identity.smimeCertificate()) ? identity.email() : null, - length = count ? recipients.filter(email => - email == from - || SMimeUserStore.find(certificate => email == certificate.emailAddress && certificate.smimeencrypt) - ).length : 0; - this.canSMimeEncrypt(length && length === count); - console.log({canSMimeEncrypt:this.canSMimeEncrypt()}); + email = getEmail(this.from()), + key = OpenPGPUserStore.getPrivateKeyFor(email, 1); + key && options.push(['OpenPGP', key]); + key = GnuPGUserStore.getPrivateKeyFor(email, 1); + key && options.push(['GnuPG', key]); + identity.smimeKey() && identity.smimeCertificate() && identity.email() === email + && options.push(['S/MIME']); + console.dir({signOptions: options}); + this.signOptions(options); + } + + initEncrypt() { + const recipients = this.allRecipients(), + options = []; + + if (recipients.length) { + GnuPGUserStore.hasPublicKeyForEmails(recipients) + && options.push('GnuPG'); + + OpenPGPUserStore.hasPublicKeyForEmails(recipients) + && options.push('OpenPGP'); + + MailvelopeUserStore.hasPublicKeyForEmails(recipients).then(result => { + if (result) { + options.push('Mailvelope'); + } else { + 'mailvelope' === this.viewArea() && this.bodyArea(); + // this.dropMailvelope(); + } + }); + + const count = recipients.length, + identity = this.currentIdentity(), + from = (identity.smimeKey() && identity.smimeCertificate()) ? identity.email() : null; + count + && count === recipients.filter(email => + email == from + || SMimeUserStore.find(certificate => email == certificate.emailAddress && certificate.smimeencrypt) + ).length + && options.push('S/MIME'); + } + + console.dir({encryptOptions:options}); + this.encryptOptions(options); } async getMessageRequestParams(sSaveFolder, draft) @@ -1464,8 +1476,8 @@ export class ComposePopupView extends AbstractViewPopup { linkedData: [] }, recipients = draft ? [identity.email()] : this.allRecipients(), - sign = !draft && this.doSign() && (this.pgpSignKey() || this.canSMimeSign()), - encrypt = this.doEncrypt() && (this.canPgpEncrypt() || this.canSMimeEncrypt()), + signOptions = !draft && this.doSign() && this.signOptions(), + encryptOptions = this.doEncrypt() && this.encryptOptions(), isHtml = this.oEditor.isHtml(); if (isHtml) { @@ -1492,7 +1504,7 @@ export class ComposePopupView extends AbstractViewPopup { params.autocrypt.push({addr:k, keydata:v.replace(/-----(BEGIN|END) PGP PUBLIC KEY BLOCK-----/g).trim()}) ); */ - } else if (sign || encrypt) { + } else if (signOptions.length || encryptOptions.length) { if (!draft && !hasAttachments && !Text.length) { throw i18n('COMPOSE/ERROR_EMPTY_BODY'); } @@ -1512,9 +1524,10 @@ export class ComposePopupView extends AbstractViewPopup { alternative.children.push(data); data = alternative; } - if (sign) { - if (sign?.[1]) { - if ('openpgp' == sign[0]) { + let sign = true; + for (let i = 0; i < signOptions.length; ++i) { + if ('OpenPGP' == signOptions[i][0]) { + try { // Doesn't sign attachments params.html = params.plain = ''; let signed = new MimePart; @@ -1525,34 +1538,53 @@ export class ComposePopupView extends AbstractViewPopup { let signature = new MimePart; signature.headers['Content-Type'] = 'application/pgp-signature; name="signature.asc"'; signature.headers['Content-Transfer-Encoding'] = '7Bit'; - signature.body = await OpenPGPUserStore.sign(data.toString(), sign[1], 1); + signature.body = await OpenPGPUserStore.sign(data.toString(), signOptions[i][1], 1); signed.children.push(signature); params.signed = signed.toString(); params.boundary = signed.boundary; data = signed; - } else if ('gnupg' == sign[0]) { - // TODO: sign in PHP fails - // params.signData = data.toString(); - params.signFingerprint = sign[1].fingerprint; - params.signPassphrase = await GnuPGUserStore.sign(sign[1]); - } else { - throw 'Signing with ' + sign[0] + ' not yet implemented'; + } catch (e) { + sign = false; + console.error(e); } - } else if (this.canSMimeSign()) { + break; + } + if ('GnuPG' == signOptions[i][0]) { + // TODO: sign in PHP fails + let pass = await GnuPGUserStore.sign(signOptions[i][1]); + if (null != pass) { +// params.signData = data.toString(); + params.signFingerprint = signOptions[i][1].fingerprint; + params.signPassphrase = pass; + } else { + sign = false; + } + break; + } + if ('S/MIME' == signOptions[i][0]) { + // TODO: sign in PHP fails params.signCertificate = identity.smimeCertificate(); params.signPrivateKey = identity.smimeKey(); if (identity.smimeKeyEncrypted()) { const pass = await Passphrases.ask( - params.signPrivateKey, + identity.smimeKey(), i18n('SMIME/PRIVATE_KEY_OF', {EMAIL: identity.email()}), 'CRYPTO/DECRYPT' ); - params.signPassphrase = pass?.password; -// pass && pass.remember && Passphrases.set(identity, pass.password); + if (null != pass) { + params.signPassphrase = pass.password; +// pass.remember && Passphrases.set(identity, pass.password); + } else { + sign = false; + } } } } - if (encrypt) { + if (signOptions.length && !sign) { + throw 'Signing failed'; + } + + if (encryptOptions.length) { const autocrypt = () => Object.entries(PgpUserStore.getPublicKeyOfEmails(recipients) || {}).forEach(([k,v]) => params.autocrypt.push({ @@ -1560,24 +1592,30 @@ export class ComposePopupView extends AbstractViewPopup { keydata: v.replace(/-----(BEGIN|END) PGP PUBLIC KEY BLOCK-----/g, '').trim() }) ); - if ('openpgp' == encrypt) { - // Doesn't encrypt attachments - params.encrypted = await OpenPGPUserStore.encrypt(data.toString(), recipients); - params.signed = ''; - autocrypt(); - } else if ('gnupg' == encrypt) { - // Does encrypt attachments - params.encryptFingerprints = JSON.stringify(GnuPGUserStore.getPublicKeyFingerprints(recipients)); - autocrypt(); - } else if (this.canSMimeEncrypt() && identity && identity.smimeKey() && identity.smimeCertificate()) { - params.encryptCertificates = [identity.smimeCertificate()]; - SMimeUserStore.forEach(certificate => { - certificate.emailAddress != identity.email() - && recipients.includes(certificate.emailAddress) - && params.encryptCertificates.push(certificate.id) - }); - } else { - throw 'Encryption with ' + encrypt + ' not yet implemented'; + for (let i = 0; i < encryptOptions.length; ++i) { + if ('OpenPGP' == encryptOptions[i]) { + // Doesn't encrypt attachments + params.encrypted = await OpenPGPUserStore.encrypt(data.toString(), recipients); + params.signed = ''; + autocrypt(); + break; + } + if ('GnuPG' == encryptOptions[i]) { + // Does encrypt attachments + params.encryptFingerprints = JSON.stringify(GnuPGUserStore.getPublicKeyFingerprints(recipients)); + autocrypt(); + break; + } + if ('S/MIME' == encryptOptions[i]) { + params.encryptCertificates = [identity.smimeCertificate()]; + SMimeUserStore.forEach(certificate => { + certificate.emailAddress != identity.email() + && recipients.includes(certificate.emailAddress) + && params.encryptCertificates.push(certificate.id) + }); + break; + } + // We skip Mailvelope as it has its own window } } } diff --git a/dev/View/Popup/SMimeImport.js b/dev/View/Popup/SMimeImport.js new file mode 100644 index 000000000..7ebf721f9 --- /dev/null +++ b/dev/View/Popup/SMimeImport.js @@ -0,0 +1,50 @@ +import { addObservablesTo } from 'External/ko'; +import { getNotification } from 'Common/Translator'; + +import { AbstractViewPopup } from 'Knoin/AbstractViews'; + +import Remote from 'Remote/User/Fetch'; + +export class SMimeImportPopupView extends AbstractViewPopup { + constructor() { + super('SMimeImport'); + + addObservablesTo(this, { + pem: '', + pemError: false, + pemErrorMessage: '', + pemValid: false + }); + + this.pem.subscribe(value => { + this.pemError(false); + this.pemErrorMessage(''); + this.pemValid(value && value.includes('-----BEGIN CERTIFICATE-----')); + }); + } + + submitForm() { + if (this.pemValid()) { + Remote.request('SMimeImportCertificate', + (iError, oData) => { + if (iError) { + this.pemError(true); + this.pemErrorMessage(getNotification(iError, oData?.ErrorMessage)); +// oData?.ErrorMessageAdditional; + } else { + this.close(); + } + }, + {pem:this.pem()} + ); + } else { + this.pemError(true); + } + } + + onShow() { + this.pem(''); + this.pemError(false); + this.pemErrorMessage(''); + } +} diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/SMime.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/SMime.php index d5d1437b4..5aed83217 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/SMime.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/SMime.php @@ -173,6 +173,15 @@ trait SMime return $this->DefaultResponse($result); } + public function DoSMimeImportCertificate() : array + { + return $this->DefaultResponse( + $this->SMIME()->storeCertificate( + $this->GetActionParam('pem', '') + ) + ); + } + public function DoSMimeImportCertificatesFromMessage() : array { /* diff --git a/snappymail/v/0.0.0/app/localization/ar-SA/user.json b/snappymail/v/0.0.0/app/localization/ar-SA/user.json index 4aed9b45f..a5b5c6c44 100644 --- a/snappymail/v/0.0.0/app/localization/ar-SA/user.json +++ b/snappymail/v/0.0.0/app/localization/ar-SA/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME signed message", "ENCRYPTED_MESSAGE": "S\/MIME encrypted message", diff --git a/snappymail/v/0.0.0/app/localization/bg-BG/user.json b/snappymail/v/0.0.0/app/localization/bg-BG/user.json index d43e119ad..553dc3d84 100644 --- a/snappymail/v/0.0.0/app/localization/bg-BG/user.json +++ b/snappymail/v/0.0.0/app/localization/bg-BG/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "Подписано с S\/MIME", "ENCRYPTED_MESSAGE": "Шифровано с S\/MIME", diff --git a/snappymail/v/0.0.0/app/localization/cs-CZ/user.json b/snappymail/v/0.0.0/app/localization/cs-CZ/user.json index 57d449b7a..349c021d6 100644 --- a/snappymail/v/0.0.0/app/localization/cs-CZ/user.json +++ b/snappymail/v/0.0.0/app/localization/cs-CZ/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "Zpráva podepsaná S\/MIME", "ENCRYPTED_MESSAGE": "Zpráva šifrovaná S\/MIME", diff --git a/snappymail/v/0.0.0/app/localization/da-DK/user.json b/snappymail/v/0.0.0/app/localization/da-DK/user.json index 0a2887de5..7f59e18c7 100644 --- a/snappymail/v/0.0.0/app/localization/da-DK/user.json +++ b/snappymail/v/0.0.0/app/localization/da-DK/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME signeret meddelelse", "ENCRYPTED_MESSAGE": "S\/MIME krypteret meddelelse", diff --git a/snappymail/v/0.0.0/app/localization/de-DE/user.json b/snappymail/v/0.0.0/app/localization/de-DE/user.json index 49f560744..a9b9675fc 100644 --- a/snappymail/v/0.0.0/app/localization/de-DE/user.json +++ b/snappymail/v/0.0.0/app/localization/de-DE/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME-signierte Nachricht", "ENCRYPTED_MESSAGE": "S\/MIME-verschlüsselte Nachricht", diff --git a/snappymail/v/0.0.0/app/localization/el-GR/user.json b/snappymail/v/0.0.0/app/localization/el-GR/user.json index 0339d0672..a356d916c 100644 --- a/snappymail/v/0.0.0/app/localization/el-GR/user.json +++ b/snappymail/v/0.0.0/app/localization/el-GR/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "Μήνυμα υπογεγραμμένο με S\/MIME", "ENCRYPTED_MESSAGE": "Μήνυμα κωδικοποιημένο με S\/MIME", diff --git a/snappymail/v/0.0.0/app/localization/en-GB/user.json b/snappymail/v/0.0.0/app/localization/en-GB/user.json index 533853e27..a45ee06a5 100644 --- a/snappymail/v/0.0.0/app/localization/en-GB/user.json +++ b/snappymail/v/0.0.0/app/localization/en-GB/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME signed message", "ENCRYPTED_MESSAGE": "S\/MIME encrypted message", diff --git a/snappymail/v/0.0.0/app/localization/en/user.json b/snappymail/v/0.0.0/app/localization/en/user.json index 650c51006..c4013b6cd 100644 --- a/snappymail/v/0.0.0/app/localization/en/user.json +++ b/snappymail/v/0.0.0/app/localization/en/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S/MIME certificate", "CERTIFICATES": "S/MIME Certificates", "SIGNED_MESSAGE": "S/MIME signed message", "ENCRYPTED_MESSAGE": "S/MIME encrypted message", diff --git a/snappymail/v/0.0.0/app/localization/es-ES/user.json b/snappymail/v/0.0.0/app/localization/es-ES/user.json index d27e0325c..bbf3c8512 100644 --- a/snappymail/v/0.0.0/app/localization/es-ES/user.json +++ b/snappymail/v/0.0.0/app/localization/es-ES/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "Mensaje firmado mediante S\/MIME", "ENCRYPTED_MESSAGE": "Mensaje cifrado mediante S\/MIME", diff --git a/snappymail/v/0.0.0/app/localization/et-EE/user.json b/snappymail/v/0.0.0/app/localization/et-EE/user.json index fce18d98d..d62282c68 100644 --- a/snappymail/v/0.0.0/app/localization/et-EE/user.json +++ b/snappymail/v/0.0.0/app/localization/et-EE/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME abil signeeritud kiri", "ENCRYPTED_MESSAGE": "S\/MIME abil krüpteeritud kiri", diff --git a/snappymail/v/0.0.0/app/localization/eu/user.json b/snappymail/v/0.0.0/app/localization/eu/user.json index 25261ae8a..a86fcfbc5 100644 --- a/snappymail/v/0.0.0/app/localization/eu/user.json +++ b/snappymail/v/0.0.0/app/localization/eu/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME sinatutako mezua", "ENCRYPTED_MESSAGE": "S\/MIME zifratutako mezua", diff --git a/snappymail/v/0.0.0/app/localization/fa-IR/user.json b/snappymail/v/0.0.0/app/localization/fa-IR/user.json index 5e397af55..39ae02b55 100644 --- a/snappymail/v/0.0.0/app/localization/fa-IR/user.json +++ b/snappymail/v/0.0.0/app/localization/fa-IR/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "پیام توسط S\/MIME امضاء شد", "ENCRYPTED_MESSAGE": "پیام توسط S\/MIME رمزنگاری شد", diff --git a/snappymail/v/0.0.0/app/localization/fi-FI/user.json b/snappymail/v/0.0.0/app/localization/fi-FI/user.json index c709c9abf..3218d34d4 100644 --- a/snappymail/v/0.0.0/app/localization/fi-FI/user.json +++ b/snappymail/v/0.0.0/app/localization/fi-FI/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME allekirjoitettu viesti", "ENCRYPTED_MESSAGE": "S\/MIME salattu visti", diff --git a/snappymail/v/0.0.0/app/localization/fr-FR/user.json b/snappymail/v/0.0.0/app/localization/fr-FR/user.json index 035c53052..192e71452 100644 --- a/snappymail/v/0.0.0/app/localization/fr-FR/user.json +++ b/snappymail/v/0.0.0/app/localization/fr-FR/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "Message signé par S\/MIME", "ENCRYPTED_MESSAGE": "Message chiffré par S\/MIME", diff --git a/snappymail/v/0.0.0/app/localization/hu-HU/user.json b/snappymail/v/0.0.0/app/localization/hu-HU/user.json index 63d7aaa0b..05e81b2ba 100644 --- a/snappymail/v/0.0.0/app/localization/hu-HU/user.json +++ b/snappymail/v/0.0.0/app/localization/hu-HU/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME aláírt üzenet", "ENCRYPTED_MESSAGE": "S\/MIME kódolt üzenet", diff --git a/snappymail/v/0.0.0/app/localization/id-ID/user.json b/snappymail/v/0.0.0/app/localization/id-ID/user.json index 744c70033..3a53d77c5 100644 --- a/snappymail/v/0.0.0/app/localization/id-ID/user.json +++ b/snappymail/v/0.0.0/app/localization/id-ID/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "Pesan bertanda-tangan S\/MIME", "ENCRYPTED_MESSAGE": "Pesan terenkripsi S\/MIME", diff --git a/snappymail/v/0.0.0/app/localization/is-IS/user.json b/snappymail/v/0.0.0/app/localization/is-IS/user.json index fee5de7fa..dab352ccc 100644 --- a/snappymail/v/0.0.0/app/localization/is-IS/user.json +++ b/snappymail/v/0.0.0/app/localization/is-IS/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "Skeyti undirritað með S\/MIME", "ENCRYPTED_MESSAGE": "Skeyti dulritað með S\/MIME", diff --git a/snappymail/v/0.0.0/app/localization/it-IT/user.json b/snappymail/v/0.0.0/app/localization/it-IT/user.json index cfab3b291..85454dbf7 100644 --- a/snappymail/v/0.0.0/app/localization/it-IT/user.json +++ b/snappymail/v/0.0.0/app/localization/it-IT/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "Messaggio firmato con S\/MIME", "ENCRYPTED_MESSAGE": "Messaggio cifrato con S\/MIME", diff --git a/snappymail/v/0.0.0/app/localization/ja-JP/user.json b/snappymail/v/0.0.0/app/localization/ja-JP/user.json index e050683cd..d9d3ca459 100644 --- a/snappymail/v/0.0.0/app/localization/ja-JP/user.json +++ b/snappymail/v/0.0.0/app/localization/ja-JP/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME署名済みメッセージ", "ENCRYPTED_MESSAGE": "S\/MIME暗号化メッセージ", diff --git a/snappymail/v/0.0.0/app/localization/ko-KR/user.json b/snappymail/v/0.0.0/app/localization/ko-KR/user.json index b4e0cf497..21ec495a4 100644 --- a/snappymail/v/0.0.0/app/localization/ko-KR/user.json +++ b/snappymail/v/0.0.0/app/localization/ko-KR/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME로 서명된 메세지입니다.", "ENCRYPTED_MESSAGE": "S\/MIME로 암호화된 메세지입니다.", diff --git a/snappymail/v/0.0.0/app/localization/lt-LT/user.json b/snappymail/v/0.0.0/app/localization/lt-LT/user.json index 9675c674b..131f0ff17 100644 --- a/snappymail/v/0.0.0/app/localization/lt-LT/user.json +++ b/snappymail/v/0.0.0/app/localization/lt-LT/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME pasirašytas pranešimas", "ENCRYPTED_MESSAGE": "S\/MIME šifruotas pranešimas", diff --git a/snappymail/v/0.0.0/app/localization/lv-LV/user.json b/snappymail/v/0.0.0/app/localization/lv-LV/user.json index 0ca93a400..457f236dd 100644 --- a/snappymail/v/0.0.0/app/localization/lv-LV/user.json +++ b/snappymail/v/0.0.0/app/localization/lv-LV/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME signed message", "ENCRYPTED_MESSAGE": "S\/MIME encrypted message", diff --git a/snappymail/v/0.0.0/app/localization/nb-NO/user.json b/snappymail/v/0.0.0/app/localization/nb-NO/user.json index dd3b2fee3..7c0edcc20 100644 --- a/snappymail/v/0.0.0/app/localization/nb-NO/user.json +++ b/snappymail/v/0.0.0/app/localization/nb-NO/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME-signert melding", "ENCRYPTED_MESSAGE": "S\/MIME-kryptert melding", diff --git a/snappymail/v/0.0.0/app/localization/nl-NL/user.json b/snappymail/v/0.0.0/app/localization/nl-NL/user.json index f2a211bd9..fb4f0bf2f 100644 --- a/snappymail/v/0.0.0/app/localization/nl-NL/user.json +++ b/snappymail/v/0.0.0/app/localization/nl-NL/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Maak een back-up van de privésleutel op de server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Importeer S\/MIME certificaat", "CERTIFICATES": "S\/MIME Certificaten", "SIGNED_MESSAGE": "S\/MIME ondertekend bericht", "ENCRYPTED_MESSAGE": "S\/MIME versleuteld bericht", diff --git a/snappymail/v/0.0.0/app/localization/pl-PL/user.json b/snappymail/v/0.0.0/app/localization/pl-PL/user.json index 68e0a956c..65d6d9809 100644 --- a/snappymail/v/0.0.0/app/localization/pl-PL/user.json +++ b/snappymail/v/0.0.0/app/localization/pl-PL/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Utwórz kopię zapasową klucza prywatnego na serwerze" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "Wiadomość podpisana S\/MIME", "ENCRYPTED_MESSAGE": "Wiadomość zaszyfrowana S\/MIME", diff --git a/snappymail/v/0.0.0/app/localization/pt-BR/user.json b/snappymail/v/0.0.0/app/localization/pt-BR/user.json index 4e5a61090..b043e1de0 100644 --- a/snappymail/v/0.0.0/app/localization/pt-BR/user.json +++ b/snappymail/v/0.0.0/app/localization/pt-BR/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "Mensagem assinada com S\/MIME", "ENCRYPTED_MESSAGE": "Mensagem criptografada com S\/MIME", diff --git a/snappymail/v/0.0.0/app/localization/pt-PT/user.json b/snappymail/v/0.0.0/app/localization/pt-PT/user.json index e0d1465d3..11b2854d2 100644 --- a/snappymail/v/0.0.0/app/localization/pt-PT/user.json +++ b/snappymail/v/0.0.0/app/localization/pt-PT/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "Mensagem assinada com S\/MIME", "ENCRYPTED_MESSAGE": "Mensagem encriptada com S\/MIME", diff --git a/snappymail/v/0.0.0/app/localization/pt/user.json b/snappymail/v/0.0.0/app/localization/pt/user.json index e0d1465d3..11b2854d2 100644 --- a/snappymail/v/0.0.0/app/localization/pt/user.json +++ b/snappymail/v/0.0.0/app/localization/pt/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "Mensagem assinada com S\/MIME", "ENCRYPTED_MESSAGE": "Mensagem encriptada com S\/MIME", diff --git a/snappymail/v/0.0.0/app/localization/ro-RO/user.json b/snappymail/v/0.0.0/app/localization/ro-RO/user.json index 71d0dd768..3b804924a 100644 --- a/snappymail/v/0.0.0/app/localization/ro-RO/user.json +++ b/snappymail/v/0.0.0/app/localization/ro-RO/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME signed message", "ENCRYPTED_MESSAGE": "S\/MIME encrypted message", diff --git a/snappymail/v/0.0.0/app/localization/ru-RU/user.json b/snappymail/v/0.0.0/app/localization/ru-RU/user.json index a32b18735..c306d7226 100644 --- a/snappymail/v/0.0.0/app/localization/ru-RU/user.json +++ b/snappymail/v/0.0.0/app/localization/ru-RU/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME подписанное сообщение", "ENCRYPTED_MESSAGE": "S\/MIME шифрованное сообщение", diff --git a/snappymail/v/0.0.0/app/localization/sk-SK/user.json b/snappymail/v/0.0.0/app/localization/sk-SK/user.json index a7525cdb9..14edc1aab 100644 --- a/snappymail/v/0.0.0/app/localization/sk-SK/user.json +++ b/snappymail/v/0.0.0/app/localization/sk-SK/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "Správa podpísaná s S\/MIME", "ENCRYPTED_MESSAGE": "Správa šifrovaná s S\/MIME", diff --git a/snappymail/v/0.0.0/app/localization/sl-SI/user.json b/snappymail/v/0.0.0/app/localization/sl-SI/user.json index 86c97df7d..a491aeb58 100644 --- a/snappymail/v/0.0.0/app/localization/sl-SI/user.json +++ b/snappymail/v/0.0.0/app/localization/sl-SI/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "Sporočilo, podpisano z S\/MIME", "ENCRYPTED_MESSAGE": "Sporočilo, šifrirano z S\/MIME", diff --git a/snappymail/v/0.0.0/app/localization/sv-SE/user.json b/snappymail/v/0.0.0/app/localization/sv-SE/user.json index 45f14d86e..52941c9ed 100644 --- a/snappymail/v/0.0.0/app/localization/sv-SE/user.json +++ b/snappymail/v/0.0.0/app/localization/sv-SE/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME-signerat meddelande", "ENCRYPTED_MESSAGE": "S\/MIME-krypterat meddelande", diff --git a/snappymail/v/0.0.0/app/localization/tr-TR/user.json b/snappymail/v/0.0.0/app/localization/tr-TR/user.json index e268ff335..93e7c1e88 100644 --- a/snappymail/v/0.0.0/app/localization/tr-TR/user.json +++ b/snappymail/v/0.0.0/app/localization/tr-TR/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME imzalı mesaj", "ENCRYPTED_MESSAGE": "S\/MIME şifreli mesaj", diff --git a/snappymail/v/0.0.0/app/localization/uk-UA/user.json b/snappymail/v/0.0.0/app/localization/uk-UA/user.json index 1f0dd8d6c..a7bd28f5b 100644 --- a/snappymail/v/0.0.0/app/localization/uk-UA/user.json +++ b/snappymail/v/0.0.0/app/localization/uk-UA/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME підписане повідомлення", "ENCRYPTED_MESSAGE": "S\/MIME шифроване повідомлення", diff --git a/snappymail/v/0.0.0/app/localization/vi-VN/user.json b/snappymail/v/0.0.0/app/localization/vi-VN/user.json index 00628cedd..dd617e949 100644 --- a/snappymail/v/0.0.0/app/localization/vi-VN/user.json +++ b/snappymail/v/0.0.0/app/localization/vi-VN/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "Thư đã được ký xác nhận bằng mã S\/MIME", "ENCRYPTED_MESSAGE": "Thư đã được mã hóa bởi S\/MIME", diff --git a/snappymail/v/0.0.0/app/localization/zh-CN/user.json b/snappymail/v/0.0.0/app/localization/zh-CN/user.json index 1099eece5..325c7e3b5 100644 --- a/snappymail/v/0.0.0/app/localization/zh-CN/user.json +++ b/snappymail/v/0.0.0/app/localization/zh-CN/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "由 S\/MIME 签名", "ENCRYPTED_MESSAGE": "由 S\/MIME 加密", diff --git a/snappymail/v/0.0.0/app/localization/zh-TW/user.json b/snappymail/v/0.0.0/app/localization/zh-TW/user.json index 6849d86dd..54a15fdee 100644 --- a/snappymail/v/0.0.0/app/localization/zh-TW/user.json +++ b/snappymail/v/0.0.0/app/localization/zh-TW/user.json @@ -302,6 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "已透過 S\/MIME 簽署郵件", "ENCRYPTED_MESSAGE": "已透過 S\/MIME 加密郵件", diff --git a/snappymail/v/0.0.0/app/templates/Views/User/PopupsSMimeImport.html b/snappymail/v/0.0.0/app/templates/Views/User/PopupsSMimeImport.html new file mode 100644 index 000000000..c7a80814c --- /dev/null +++ b/snappymail/v/0.0.0/app/templates/Views/User/PopupsSMimeImport.html @@ -0,0 +1,13 @@ +
+ × +

+
+ +
+ +
diff --git a/snappymail/v/0.0.0/app/templates/Views/User/SettingsSecurity.html b/snappymail/v/0.0.0/app/templates/Views/User/SettingsSecurity.html index e37e36b4a..68c12379f 100644 --- a/snappymail/v/0.0.0/app/templates/Views/User/SettingsSecurity.html +++ b/snappymail/v/0.0.0/app/templates/Views/User/SettingsSecurity.html @@ -125,6 +125,8 @@
+ + From a7041b4efbc854b09822d1fe502bc0621fbb07e8 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Fri, 23 Feb 2024 03:22:29 +0100 Subject: [PATCH 005/110] bugfix: store in Passphrases --- dev/Stores/User/GnuPG.js | 3 +-- dev/Stores/User/OpenPGP.js | 5 ++--- dev/View/Popup/Compose.js | 3 +-- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/dev/Stores/User/GnuPG.js b/dev/Stores/User/GnuPG.js index f5106588f..45dc3e7dc 100644 --- a/dev/Stores/User/GnuPG.js +++ b/dev/Stores/User/GnuPG.js @@ -70,8 +70,7 @@ export const GnuPGUserStore = new class { }; if (isPrivate) { key.password = async (btnTxt = 'SIGN') => { - const pass = await Passphrases.ask( - key, + const pass = await Passphrases.ask(key, 'GnuPG key
' + key.id + ' ' + key.emails[0], 'CRYPTO/'+btnTxt ); diff --git a/dev/Stores/User/OpenPGP.js b/dev/Stores/User/OpenPGP.js index df2a1172d..d61aad134 100644 --- a/dev/Stores/User/OpenPGP.js +++ b/dev/Stores/User/OpenPGP.js @@ -24,8 +24,7 @@ const return privateKey.key; } const key = privateKey.id, - pass = await Passphrases.ask( - key, + pass = await Passphrases.ask(privateKey, 'OpenPGP.js key
' + key + ' ' + privateKey.emails[0], 'CRYPTO/'+btnTxt ); @@ -35,7 +34,7 @@ const privateKey: privateKey.key, passphrase }); - result && pass.remember && Passphrases.set(key, passphrase); + result && pass.remember && Passphrases.set(privateKey, passphrase); return result; } }, diff --git a/dev/View/Popup/Compose.js b/dev/View/Popup/Compose.js index e0eee9391..0070b43c4 100644 --- a/dev/View/Popup/Compose.js +++ b/dev/View/Popup/Compose.js @@ -1566,8 +1566,7 @@ export class ComposePopupView extends AbstractViewPopup { params.signCertificate = identity.smimeCertificate(); params.signPrivateKey = identity.smimeKey(); if (identity.smimeKeyEncrypted()) { - const pass = await Passphrases.ask( - identity.smimeKey(), + const pass = await Passphrases.ask(identity, i18n('SMIME/PRIVATE_KEY_OF', {EMAIL: identity.email()}), 'CRYPTO/DECRYPT' ); From 1e03eac9a5c31a56010d405f1ee86633e6126a3e Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Sun, 25 Feb 2024 11:38:19 +0100 Subject: [PATCH 006/110] Resolve #1448 --- dev/View/Popup/Compose.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/View/Popup/Compose.js b/dev/View/Popup/Compose.js index 0070b43c4..f14c6f068 100644 --- a/dev/View/Popup/Compose.js +++ b/dev/View/Popup/Compose.js @@ -356,8 +356,8 @@ export class ComposePopupView extends AbstractViewPopup { currentIdentity: value => { if (value) { this.from(value.formattedName()); - this.doEncrypt(value.pgpEncrypt()/* || SettingsUserStore.pgpEncrypt()*/); - this.doSign(value.pgpSign()/* || SettingsUserStore.pgpSign()*/); + this.doEncrypt(value.pgpEncrypt() || SettingsUserStore.pgpEncrypt()); + this.doSign(value.pgpSign() || SettingsUserStore.pgpSign()); } }, From 5552d3c1b9cca9ca3255b72ebe867adecc9aadd0 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Sun, 25 Feb 2024 12:56:25 +0100 Subject: [PATCH 007/110] pre-verify S/MIME opaque signed messages so we have a body to view --- dev/Model/Message.js | 7 +++++ dev/View/User/MailBox/MessageView.js | 2 +- .../MailSo/Imap/Commands/Messages.php | 20 +++++++++++++ .../app/libraries/MailSo/Mail/MailClient.php | 10 +++++++ .../app/libraries/MailSo/Mail/Message.php | 2 +- .../app/libraries/RainLoop/Actions/SMime.php | 28 +++---------------- .../templates/Views/User/MailMessageView.html | 2 +- 7 files changed, 44 insertions(+), 27 deletions(-) diff --git a/dev/Model/Message.js b/dev/Model/Message.js index eac31f777..0767fc072 100644 --- a/dev/Model/Message.js +++ b/dev/Model/Message.js @@ -24,6 +24,8 @@ import { LanguageStore } from 'Stores/Language'; import Remote from 'Remote/User/Fetch'; +import { MimeToMessage } from 'Mime/Utils'; + const msgHtml = msg => cleanHtml(msg.html(), msg.attachments(), '#rl-msg-' + msg.hash), @@ -196,6 +198,11 @@ export class MessageModel extends AbstractModel { return options; } }); + + this.smimeSigned.subscribe(value => { + value?.body && MimeToMessage(value.body, this); + value?.body && this.smimeVerified(value.verified); + }); } get requestHash() { diff --git a/dev/View/User/MailBox/MessageView.js b/dev/View/User/MailBox/MessageView.js index c2e9654c2..551915799 100644 --- a/dev/View/User/MailBox/MessageView.js +++ b/dev/View/User/MailBox/MessageView.js @@ -671,7 +671,7 @@ export class MailMessageView extends AbstractViewRight { message.html() ? message.viewHtml() : message.viewPlain(); response.Result.body = null; } - message.smimeVerified(response.Result); + message.smimeVerified(response.Result.success); } }); } diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Commands/Messages.php b/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Commands/Messages.php index 2febf7c7b..69293d6bc 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Commands/Messages.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Commands/Messages.php @@ -132,6 +132,26 @@ trait Messages return $aReturn; } + public function FetchMessagePart(int $iUid, string $sPartId) : string + { + if ('TEXT' === $sPartId) { + $oFetchResponse = $this->Fetch([ + FetchType::BODY_PEEK.'['.$sPartId.']', + FetchType::BODY_HEADER_PEEK + ], $iUid, true)[0]; + $sHeader = $oFetchResponse->GetFetchValue(FetchType::BODY_HEADER); + } else { + $oFetchResponse = $this->Fetch([ + FetchType::BODY_PEEK.'['.$sPartId.']', + // An empty section specification refers to the entire message, including the header. + // But Dovecot does not return it with BODY.PEEK[1], so we also use BODY.PEEK[1.MIME]. + FetchType::BODY_PEEK.'['.$sPartId.'.MIME]' + ], $iUid, true)[0]; + $sHeader = $oFetchResponse->GetFetchValue(FetchType::BODY.'['.$sPartId.'.MIME]'); + } + return $sHeader . $oFetchResponse->GetFetchValue(FetchType::BODY.'['.$sPartId.']'); + } + /** * Appends message to specified folder * diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php b/snappymail/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php index 38ee6d9e0..1ac9cc2ed 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php @@ -171,6 +171,16 @@ class MailClient $aFetchResponse = $this->oImapClient->Fetch($aFetchItems, $iIndex, $bIndexIsUid); if (\count($aFetchResponse)) { $oMessage = Message::fromFetchResponse($sFolderName, $aFetchResponse[0], $oBodyStructure); + // S/MIME opaque signed. Verify it, so we have the raw mime body to show + if ($oMessage->smimeSigned && !$oMessage->smimeSigned['detached']) { + $sBody = $this->oImapClient->FetchMessagePart( + $oMessage->Uid, + $oMessage->smimeSigned['partId'] + ); + $result = (new \SnappyMail\SMime\OpenSSL(''))->verify($sBody, null, true); + $oMessage->smimeSigned['body'] = $result['body']; + $oMessage->smimeSigned['verified'] = true; + } } return $oMessage; diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Mail/Message.php b/snappymail/v/0.0.0/app/libraries/MailSo/Mail/Message.php index 13b098013..3578fdd2e 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Mail/Message.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Mail/Message.php @@ -69,7 +69,7 @@ class Message implements \JsonSerializable private ?array $pgpSigned = null; private ?array $pgpEncrypted = null; - private ?array $smimeSigned = null; + public ?array $smimeSigned = null; private ?array $smimeEncrypted = null; private ?\MailSo\Mime\EmailCollection diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/SMime.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/SMime.php index 5aed83217..96263411b 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/SMime.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/SMime.php @@ -118,32 +118,12 @@ trait SMime $sPartId = $this->GetActionParam('partId', ''); $bDetached = !empty($this->GetActionParam('detached', 0)); if (!$sBody && $sPartId) { - $sFolderName = $this->GetActionParam('folder', ''); $iUid = (int) $this->GetActionParam('uid', 0); - $sMicAlg = $this->GetActionParam('micAlg', ''); - +// $sMicAlg = $this->GetActionParam('micAlg', ''); $this->initMailClientConnection(); $oImapClient = $this->ImapClient(); - $oImapClient->FolderExamine($sFolderName); - - if ('TEXT' === $sPartId) { - $oFetchResponse = $oImapClient->Fetch([ - FetchType::BODY_PEEK.'['.$sPartId.']', - // An empty section specification refers to the entire message, including the header. - // But Dovecot does not return it with BODY.PEEK[1], so we also use BODY.PEEK[1.MIME]. - FetchType::BODY_HEADER_PEEK - ], $iUid, true)[0]; - $sBody = $oFetchResponse->GetFetchValue(FetchType::BODY_HEADER); - } else { - $oFetchResponse = $oImapClient->Fetch([ - FetchType::BODY_PEEK.'['.$sPartId.']', - // An empty section specification refers to the entire message, including the header. - // But Dovecot does not return it with BODY.PEEK[1], so we also use BODY.PEEK[1.MIME]. - FetchType::BODY_PEEK.'['.$sPartId.'.MIME]' - ], $iUid, true)[0]; - $sBody = $oFetchResponse->GetFetchValue(FetchType::BODY.'['.$sPartId.'.MIME]'); - } - $sBody .= $oFetchResponse->GetFetchValue(FetchType::BODY.'['.$sPartId.']'); + $oImapClient->FolderExamine($this->GetActionParam('folder', '')); + $sBody = $oImapClient->FetchMessagePart($iUid, $sPartId); } $result = $this->SMIME()->verify($sBody, null, !$bDetached); @@ -151,7 +131,7 @@ trait SMime // Import the certificates automatically $sBody = $this->GetActionParam('sigPart', ''); $sPartId = $this->GetActionParam('sigPartId', '') ?: $sPartId; - if (!$sBody && $sPartId) { + if (!$sBody && $sPartId && $oImapClient) { $sBody = $oImapClient->Fetch( [FetchType::BODY_PEEK.'['.$sPartId.']'], $iUid, diff --git a/snappymail/v/0.0.0/app/templates/Views/User/MailMessageView.html b/snappymail/v/0.0.0/app/templates/Views/User/MailMessageView.html index 97d0022e7..53e17a085 100644 --- a/snappymail/v/0.0.0/app/templates/Views/User/MailMessageView.html +++ b/snappymail/v/0.0.0/app/templates/Views/User/MailMessageView.html @@ -312,7 +312,7 @@
-
+
From 57ce6f9bbfc94a9de776bedfcb1dd90889114483 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Sun, 25 Feb 2024 13:11:17 +0100 Subject: [PATCH 008/110] Fix timestampToString() for future dates --- dev/Common/Translator.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dev/Common/Translator.js b/dev/Common/Translator.js index cb8570179..0b609a99d 100644 --- a/dev/Common/Translator.js +++ b/dev/Common/Translator.js @@ -102,8 +102,7 @@ export const timestampToString = (timeStampInUTC, formatStr) => { const now = Date.now(), - time = 0 < timeStampInUTC ? Math.min(now, timeStampInUTC * 1000) : (0 === timeStampInUTC ? now : 0); - + time = 0 < timeStampInUTC ? timeStampInUTC * 1000 : (0 === timeStampInUTC ? now : 0); if (31536000000 < time) { const m = new Date(time), h = LanguageStore.hourCycle(); switch (formatStr) { From c6aad255817c956ba7228f8f2ae543f78d156dd4 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Sun, 25 Feb 2024 20:13:39 +0100 Subject: [PATCH 009/110] Move php8.php to /app/libraries/polyfill/ --- .../v/0.0.0/app/libraries/polyfill/php8.php | 76 +++++++++++++++++++ snappymail/v/0.0.0/include.php | 2 +- snappymail/v/0.0.0/php8.php | 37 --------- 3 files changed, 77 insertions(+), 38 deletions(-) create mode 100644 snappymail/v/0.0.0/app/libraries/polyfill/php8.php delete mode 100644 snappymail/v/0.0.0/php8.php diff --git a/snappymail/v/0.0.0/app/libraries/polyfill/php8.php b/snappymail/v/0.0.0/app/libraries/polyfill/php8.php new file mode 100644 index 000000000..92a5dc534 --- /dev/null +++ b/snappymail/v/0.0.0/app/libraries/polyfill/php8.php @@ -0,0 +1,76 @@ + Date: Mon, 26 Feb 2024 02:47:56 +0100 Subject: [PATCH 010/110] Improved Settings handling to prevent bugs in outer code --- .../libraries/RainLoop/Actions/Folders.php | 4 ++-- .../app/libraries/RainLoop/Actions/Themes.php | 2 +- .../app/libraries/RainLoop/Actions/User.php | 11 ++++----- .../libraries/RainLoop/Plugins/Manager.php | 2 +- .../RainLoop/Providers/AbstractProvider.php | 10 -------- .../libraries/RainLoop/Providers/Settings.php | 18 +++++++-------- .../Providers/Settings/DefaultSettings.php | 23 ++++++++++--------- .../Storage/Enumerations/StorageType.php | 6 +++++ .../app/libraries/RainLoop/ServiceActions.php | 2 +- .../0.0.0/app/libraries/RainLoop/Settings.php | 16 +++++++++++-- 10 files changed, 50 insertions(+), 44 deletions(-) diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Folders.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Folders.php index be90a63b0..6ca21093b 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Folders.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Folders.php @@ -192,7 +192,7 @@ trait Folders $oSettingsLocal->SetConf('CheckableFolder', \json_encode(\array_unique($aCheckableFolder))); - return $this->DefaultResponse($this->SettingsProvider(true)->Save($oAccount, $oSettingsLocal)); + return $this->DefaultResponse($oSettingsLocal->save()); } /** @@ -320,7 +320,7 @@ trait Folders $oSettingsLocal->SetConf('TrashFolder', $this->GetActionParam('trash', '')); $oSettingsLocal->SetConf('ArchiveFolder', $this->GetActionParam('archive', '')); - return $this->DefaultResponse($this->SettingsProvider(true)->Save($oAccount, $oSettingsLocal)); + return $this->DefaultResponse($oSettingsLocal->save()); } public function DoFolderACL() : array diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Themes.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Themes.php index 3fa64a8f1..89a60d884 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Themes.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Themes.php @@ -187,7 +187,7 @@ trait Themes $oSettings->SetConf('UserBackgroundName', $sName); $oSettings->SetConf('UserBackgroundHash', $sHash); - $this->SettingsProvider()->Save($oAccount, $oSettings); + $oSettings->save(); } } } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/User.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/User.php index 1c4d04ea6..07db0edfd 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/User.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/User.php @@ -61,7 +61,7 @@ trait User if ($sCurrentLanguage !== $sLanguage) { $oSettings->SetConf('language', $sLanguage); - $this->SettingsProvider()->Save($oAccount, $oSettings); + $oSettings->save(); } } } @@ -219,8 +219,7 @@ trait User $this->setSettingsFromParams($oSettingsLocal, 'ShowUnreadCount', 'bool'); $this->setSettingsFromParams($oSettingsLocal, 'CheckMailInterval', 'int'); - return $this->DefaultResponse($this->SettingsProvider()->Save($oAccount, $oSettings) && - $this->SettingsProvider(true)->Save($oAccount, $oSettingsLocal)); + return $this->DefaultResponse($oSettings->save() && $oSettingsLocal->save()); } public function DoQuota() : array @@ -263,12 +262,11 @@ trait User public function DoClearUserBackground() : array { - $oAccount = $this->getAccountFromToken(); - if (!$this->GetCapa(Capa::USER_BACKGROUND)) { return $this->FalseResponse(); } + $oAccount = $this->getAccountFromToken(); $oSettings = $this->SettingsProvider()->Load($oAccount); if ($oAccount && $oSettings) { $this->StorageProvider()->Clear($oAccount, @@ -280,8 +278,7 @@ trait User $oSettings->SetConf('UserBackgroundHash', ''); } - return $this->DefaultResponse($oAccount && $oSettings ? - $this->SettingsProvider()->Save($oAccount, $oSettings) : false); + return $this->DefaultResponse($oAccount && $oSettings ? $oSettings->save() : false); } private function setSettingsFromParams(\RainLoop\Settings $oSettings, string $sConfigName, string $sType = 'string', ?callable $cCallback = null) : void diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Plugins/Manager.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Plugins/Manager.php index ef7ebcb79..5fe62aaab 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Plugins/Manager.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Plugins/Manager.php @@ -419,7 +419,7 @@ class Manager $aData[$sPluginName] = $aPluginSettings; $oSettings->SetConf('Plugins',$aData); - return $this->oActions->SettingsProvider()->Save($oAccount, $oSettings); + return $oSettings->save(); } } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AbstractProvider.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AbstractProvider.php index f499c712e..9c1e2c5a5 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AbstractProvider.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AbstractProvider.php @@ -6,18 +6,8 @@ abstract class AbstractProvider { use \MailSo\Log\Inherit; - /** - * @var \RainLoop\Model\Account - */ - protected $oAccount; - public function IsActive() : bool { return false; } - - public function SetAccount(\RainLoop\Model\Account $oAccount) - { - $this->oAccount = $oAccount; - } } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Settings.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Settings.php index b10a50307..66123e4bf 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Settings.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Settings.php @@ -2,30 +2,30 @@ namespace RainLoop\Providers; +use RainLoop\Model\Account; +use RainLoop\Providers\Settings\ISettings; + class Settings extends \RainLoop\Providers\AbstractProvider { - /** - * @var \RainLoop\Providers\Settings\ISettings - */ - private $oDriver; + private ISettings $oDriver; - public function __construct(\RainLoop\Providers\Settings\ISettings $oDriver) + public function __construct(ISettings $oDriver) { $this->oDriver = $oDriver; } - public function Load(\RainLoop\Model\Account $oAccount) : \RainLoop\Settings + public function Load(Account $oAccount) : \RainLoop\Settings { - return new \RainLoop\Settings($this->oDriver->Load($oAccount)); + return new \RainLoop\Settings($this, $oAccount, $this->oDriver->Load($oAccount)); } - public function Save(\RainLoop\Model\Account $oAccount, \RainLoop\Settings $oSettings) : bool + public function Save(Account $oAccount, \RainLoop\Settings $oSettings) : bool { return $this->oDriver->Save($oAccount, $oSettings); } public function IsActive() : bool { - return $this->oDriver instanceof \RainLoop\Providers\Settings\ISettings; + return true; } } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Settings/DefaultSettings.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Settings/DefaultSettings.php index 1ea00d7a2..63df9be23 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Settings/DefaultSettings.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Settings/DefaultSettings.php @@ -2,25 +2,26 @@ namespace RainLoop\Providers\Settings; +use RainLoop\Model\Account; +use RainLoop\Providers\Storage; +use RainLoop\Providers\Storage\Enumerations\StorageType; + class DefaultSettings implements ISettings { const FILE_NAME = 'settings'; const FILE_NAME_LOCAL = 'settings_local'; - /** - * @var \RainLoop\Providers\Storage - */ - private $oStorageProvider; + private Storage $oStorageProvider; - public function __construct(\RainLoop\Providers\Storage $oStorageProvider) + public function __construct(Storage $oStorageProvider) { $this->oStorageProvider = $oStorageProvider; } - public function Load(\RainLoop\Model\Account $oAccount) : array + public function Load(Account $oAccount) : array { $sValue = $this->oStorageProvider->Get($oAccount, - \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, + StorageType::CONFIG, $this->oStorageProvider->IsLocal() ? self::FILE_NAME_LOCAL : self::FILE_NAME @@ -36,20 +37,20 @@ class DefaultSettings implements ISettings return array(); } - public function Save(\RainLoop\Model\Account $oAccount, \RainLoop\Settings $oSettings) : bool + public function Save(Account $oAccount, \RainLoop\Settings $oSettings) : bool { return $this->oStorageProvider->Put($oAccount, - \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, + StorageType::CONFIG, $this->oStorageProvider->IsLocal() ? self::FILE_NAME_LOCAL : self::FILE_NAME, \json_encode($oSettings)); } - public function Delete(\RainLoop\Model\Account $oAccount) : bool + public function Delete(Account $oAccount) : bool { return $this->oStorageProvider->Clear($oAccount, - \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, + StorageType::CONFIG, $this->oStorageProvider->IsLocal() ? self::FILE_NAME_LOCAL : self::FILE_NAME); diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Storage/Enumerations/StorageType.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Storage/Enumerations/StorageType.php index 0b3c29cb7..969c28156 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Storage/Enumerations/StorageType.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Storage/Enumerations/StorageType.php @@ -2,6 +2,12 @@ namespace RainLoop\Providers\Storage\Enumerations; +/** + * PHP 8.1 +enum StorageType: int { + case USER = 1; +} +*/ class StorageType { const USER = 1; diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php b/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php index 762bf9bf3..a4986f70f 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php @@ -588,7 +588,7 @@ class ServiceActions } if ($bNeedToSettings) { - $this->SettingsProvider()->Save($oAccount, $oSettings); + $oSettings->save(); } } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Settings.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Settings.php index b2791824b..bf0bf23ad 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Settings.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Settings.php @@ -2,11 +2,16 @@ namespace RainLoop; +use RainLoop\Model\Account; +use RainLoop\Providers\Settings as SettingsProvider; + class Settings implements \JsonSerializable { - protected array $aData = array(); + protected array $aData; + protected Account $oAccount; + protected SettingsProvider $oProvider; - public function __construct(array $aData) + public function __construct(SettingsProvider $oProvider, Account $oAccount, array $aData) { if (isset($aData['SpamFolder']) && !isset($aData['JunkFolder'])) { $aData['JunkFolder'] = $aData['SpamFolder']; @@ -19,6 +24,13 @@ class Settings implements \JsonSerializable unset($aData['Language']); } $this->aData = $aData; + $this->oAccount = $oAccount; + $this->oProvider = $oProvider; + } + + public function save() : bool + { + return $this->oProvider->Save($this->oAccount, $this); } public function toArray() : array From cfc497556ea13e2bc0494c31b505934f54b55240 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Mon, 26 Feb 2024 02:49:06 +0100 Subject: [PATCH 011/110] Changed AbstractProvider::IsActive() to be abstract --- .../app/libraries/RainLoop/Providers/AbstractProvider.php | 5 +---- .../v/0.0.0/app/libraries/RainLoop/Providers/Identities.php | 5 +++++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AbstractProvider.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AbstractProvider.php index 9c1e2c5a5..78ee2bfdb 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AbstractProvider.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AbstractProvider.php @@ -6,8 +6,5 @@ abstract class AbstractProvider { use \MailSo\Log\Inherit; - public function IsActive() : bool - { - return false; - } + abstract public function IsActive() : bool; } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Identities.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Identities.php index cf1331a6c..be1f775ce 100755 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Identities.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Identities.php @@ -27,6 +27,11 @@ class Identities extends AbstractProvider }); } + public function IsActive() : bool; + { + return true; + } + /** * @param Account $account * @param bool $allowMultipleIdentities From 58d3fc8fd5d70f344e60f2e0e69318b2700e4696 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Mon, 26 Feb 2024 02:54:44 +0100 Subject: [PATCH 012/110] Example for #1449 --- plugins/nextcloud/index.php | 6 ++++++ plugins/nextcloud/storage.php | 22 ++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 plugins/nextcloud/storage.php diff --git a/plugins/nextcloud/index.php b/plugins/nextcloud/index.php index 37dd8006e..c6a31ae2d 100644 --- a/plugins/nextcloud/index.php +++ b/plugins/nextcloud/index.php @@ -328,6 +328,12 @@ class NextcloudPlugin extends \RainLoop\Plugins\AbstractPlugin $this->Config()->Get('plugin', 'ignoreSystemAddressbook', true) ); } +/* + if ('storage' === $sName || 'storage-local' === $sName) { + require_once __DIR__ . '/storage.php'; + $oDriver = new \NextcloudStorage(APP_PRIVATE_DATA.'storage', $sName === 'storage-local'); + } +*/ } } diff --git a/plugins/nextcloud/storage.php b/plugins/nextcloud/storage.php new file mode 100644 index 000000000..05f38fb82 --- /dev/null +++ b/plugins/nextcloud/storage.php @@ -0,0 +1,22 @@ +getUserSession()->getUser()->getUID(); + $sDataPath .= "/.config/{$sUID}/"; + if ($bMkDir && !\is_dir($sDataPath) && !\mkdir($sDataPath, 0700, true)) { + throw new \RainLoop\Exceptions\Exception('Can\'t make storage directory "'.$sDataPath.'"'); + } + } + return $sDataPath; + } +} From dcfa144ce3b6b36ac37959525676e4f23a4e03e5 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Mon, 26 Feb 2024 02:58:06 +0100 Subject: [PATCH 013/110] bugfix: previous IsActive() commit --- .../v/0.0.0/app/libraries/RainLoop/Providers/Identities.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Identities.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Identities.php index be1f775ce..5e258c166 100755 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Identities.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Identities.php @@ -27,7 +27,7 @@ class Identities extends AbstractProvider }); } - public function IsActive() : bool; + public function IsActive() : bool { return true; } From 044b0dcde68f015be55431582ea014d587bd2320 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Mon, 26 Feb 2024 03:16:18 +0100 Subject: [PATCH 014/110] OpenSSL required due to S/MIME --- snappymail/v/0.0.0/app/libraries/snappymail/integrity.php | 1 + 1 file changed, 1 insertion(+) diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/integrity.php b/snappymail/v/0.0.0/app/libraries/snappymail/integrity.php index be4e8327f..7b1d301a9 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/integrity.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/integrity.php @@ -97,6 +97,7 @@ abstract class Integrity public static function phpExtensions() { $aRequirements = array( + 'openssl' => extension_loaded('openssl'), 'mbstring' => extension_loaded('mbstring'), 'Zlib' => extension_loaded('zlib'), // enabled by default: From 9ef11db8951fce6c1d179dc5178c883b4bc0adae Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Mon, 26 Feb 2024 04:20:28 +0100 Subject: [PATCH 015/110] Use get_debug_type() instead of gettype() --- .../app/libraries/RainLoop/Actions/UserAuth.php | 2 +- .../libraries/RainLoop/Config/AbstractConfig.php | 16 ++++++++-------- .../v/0.0.0/app/libraries/Sabre/Xml/Reader.php | 8 +------- .../libraries/Sabre/Xml/Serializer/functions.php | 4 ++-- 4 files changed, 12 insertions(+), 18 deletions(-) diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/UserAuth.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/UserAuth.php index 2511e99b2..fc93974b9 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/UserAuth.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/UserAuth.php @@ -261,7 +261,7 @@ trait UserAuth $this->oMainAuthAccount = $oMainAuthAccount; } else { $this->StorageProvider()->Clear($oMainAuthAccount, StorageType::SESSION, $sToken); - \SnappyMail\Log::notice('TOKENS', 'SESSION_TOKEN value invalid: ' . \gettype($sTokenValue)); + \SnappyMail\Log::notice('TOKENS', 'SESSION_TOKEN value invalid: ' . \get_debug_type($sTokenValue)); } } else { \SnappyMail\Log::notice('TOKENS', 'AUTH_SPEC_TOKEN_KEY invalid'); diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Config/AbstractConfig.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Config/AbstractConfig.php index 549e247f7..2a87abf36 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Config/AbstractConfig.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Config/AbstractConfig.php @@ -88,15 +88,15 @@ abstract class AbstractConfig implements \ArrayAccess, \JsonSerializable if (!\is_scalar($mParamValue)) { $mParamValue = null; } - switch (\gettype($this->aData[$sSectionKey][$sParamKey][0])) + switch (\get_debug_type($this->aData[$sSectionKey][$sParamKey][0])) { - case 'boolean': + case 'bool': $this->aData[$sSectionKey][$sParamKey][0] = (bool) $mParamValue; break; - case 'double': + case 'float': $this->aData[$sSectionKey][$sParamKey][0] = (float) $mParamValue; break; - case 'integer': + case 'int': $this->aData[$sSectionKey][$sParamKey][0] = (int) $mParamValue; break; case 'string': @@ -289,13 +289,13 @@ abstract class AbstractConfig implements \ArrayAccess, \JsonSerializable $bFirst = false; $sValue = '""'; - switch (\gettype($mParamValue[0])) + switch (\get_debug_type($mParamValue[0])) { - case 'boolean': + case 'bool': $sValue = $mParamValue[0] ? 'On' : 'Off'; break; - case 'double': - case 'integer': + case 'float': + case 'int': $sValue = $mParamValue[0]; break; case 'string': diff --git a/snappymail/v/0.0.0/app/libraries/Sabre/Xml/Reader.php b/snappymail/v/0.0.0/app/libraries/Sabre/Xml/Reader.php index c1399ad19..53d64d54d 100644 --- a/snappymail/v/0.0.0/app/libraries/Sabre/Xml/Reader.php +++ b/snappymail/v/0.0.0/app/libraries/Sabre/Xml/Reader.php @@ -306,12 +306,6 @@ class Reader extends \XMLReader return [$deserializer, 'xmlDeserialize']; } - $type = gettype($deserializer); - if (is_string($deserializer)) { - $type .= ' ('.$deserializer.')'; - } elseif (is_object($deserializer)) { - $type .= ' ('.get_class($deserializer).')'; - } - throw new \LogicException('Could not use this type as a deserializer: '.$type.' for element: '.$name); + throw new \LogicException('Could not use this type as a deserializer: '.get_debug_type($deserializer).' for element: '.$name); } } diff --git a/snappymail/v/0.0.0/app/libraries/Sabre/Xml/Serializer/functions.php b/snappymail/v/0.0.0/app/libraries/Sabre/Xml/Serializer/functions.php index 930e97b19..4e0856a0c 100644 --- a/snappymail/v/0.0.0/app/libraries/Sabre/Xml/Serializer/functions.php +++ b/snappymail/v/0.0.0/app/libraries/Sabre/Xml/Serializer/functions.php @@ -172,12 +172,12 @@ function standardSerializer(Writer $writer, $value): void $writer->write($item); $writer->endElement(); } else { - throw new \InvalidArgumentException('The writer does not know how to serialize arrays with keys of type: '.gettype($name)); + throw new \InvalidArgumentException('The writer does not know how to serialize arrays with keys of type: '.get_debug_type($name)); } } } elseif (is_object($value)) { throw new \InvalidArgumentException('The writer cannot serialize objects of class: '.get_class($value)); } elseif (!is_null($value)) { - throw new \InvalidArgumentException('The writer cannot serialize values of type: '.gettype($value)); + throw new \InvalidArgumentException('The writer cannot serialize values of type: '.get_debug_type($value)); } } From cbfc7e7d82165c52d6dee47ed30ec10c78a6d15d Mon Sep 17 00:00:00 2001 From: tinola Date: Mon, 26 Feb 2024 07:25:09 +0100 Subject: [PATCH 016/110] update polish translation --- snappymail/v/0.0.0/app/localization/pl-PL/user.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snappymail/v/0.0.0/app/localization/pl-PL/user.json b/snappymail/v/0.0.0/app/localization/pl-PL/user.json index 2ef81a8e1..1f1930b27 100644 --- a/snappymail/v/0.0.0/app/localization/pl-PL/user.json +++ b/snappymail/v/0.0.0/app/localization/pl-PL/user.json @@ -302,7 +302,7 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Utwórz kopię zapasową klucza prywatnego na serwerze" }, "SMIME": { - "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "POPUP_IMPORT_TITLE": "Importuj certyfikat S\/MIME", "CERTIFICATES": "Certyfikaty S\/MIME", "SIGNED_MESSAGE": "Wiadomość podpisana S\/MIME", "ENCRYPTED_MESSAGE": "Wiadomość zaszyfrowana S\/MIME", From e1dced8007f633fa2bd55e1c71c157938c0417a8 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Mon, 26 Feb 2024 11:12:02 +0100 Subject: [PATCH 017/110] Make all Enumerations classes abstract --- .../libraries/MailSo/Mime/Enumerations/DkimStatus.php | 2 ++ .../MailSo/Net/Enumerations/ConnectionSecurityType.php | 6 ++---- .../v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php | 3 +-- .../0.0.0/app/libraries/RainLoop/Enumerations/Layout.php | 2 +- .../RainLoop/Enumerations/PluginPropertyType.php | 2 +- .../app/libraries/RainLoop/Enumerations/SignMeType.php | 2 +- .../app/libraries/RainLoop/Enumerations/TimeFormat.php | 9 --------- .../Providers/AddressBook/Enumerations/PropertyType.php | 2 +- .../Providers/Storage/Enumerations/StorageType.php | 2 +- 9 files changed, 10 insertions(+), 20 deletions(-) delete mode 100644 snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/TimeFormat.php diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Mime/Enumerations/DkimStatus.php b/snappymail/v/0.0.0/app/libraries/MailSo/Mime/Enumerations/DkimStatus.php index 366e67a70..398514375 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Mime/Enumerations/DkimStatus.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Mime/Enumerations/DkimStatus.php @@ -16,6 +16,8 @@ namespace MailSo\Mime\Enumerations; * @package Mime * @subpackage Enumerations */ +//enum DkimStatus:string +//final class DkimStatus extends \BackedEnumString abstract class DkimStatus { const NONE = 'none'; diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Net/Enumerations/ConnectionSecurityType.php b/snappymail/v/0.0.0/app/libraries/MailSo/Net/Enumerations/ConnectionSecurityType.php index 687a3b966..660e0b870 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Net/Enumerations/ConnectionSecurityType.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Net/Enumerations/ConnectionSecurityType.php @@ -27,8 +27,7 @@ abstract class ConnectionSecurityType { $iPort = (int) $iPort; $iResult = (int) $iSecurityType; - if (self::AUTO_DETECT === $iSecurityType) - { + if (self::AUTO_DETECT === $iSecurityType) { switch (true) { case 993 === $iPort: @@ -39,8 +38,7 @@ abstract class ConnectionSecurityType } } - if (self::SSL === $iResult && !\in_array('ssl', \stream_get_transports())) - { + if (self::SSL === $iResult && !\in_array('ssl', \stream_get_transports())) { $iResult = self::NONE; } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php index 054b25335..ba897a874 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php @@ -2,7 +2,7 @@ namespace RainLoop\Enumerations; -class Capa +abstract class Capa { const GNUPG = 'GnuPG'; const OPEN_PGP = 'OpenPGP'; @@ -16,5 +16,4 @@ class Capa const QUOTA = 'Quota'; const ATTACHMENTS_ACTIONS = 'AttachmentsActions'; const DANGEROUS_ACTIONS = 'DangerousActions'; - const AUTOLOGOUT = ''; // Obsolete } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/Layout.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/Layout.php index 32af1fe45..0fe236ae7 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/Layout.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/Layout.php @@ -2,7 +2,7 @@ namespace RainLoop\Enumerations; -class Layout +abstract class Layout { const NO_PREVIEW = 0; const SIDE_PREVIEW = 1; diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/PluginPropertyType.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/PluginPropertyType.php index 2cbf7a9d0..32b6cc8d5 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/PluginPropertyType.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/PluginPropertyType.php @@ -2,7 +2,7 @@ namespace RainLoop\Enumerations; -class PluginPropertyType +abstract class PluginPropertyType { const GROUP = 7, diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/SignMeType.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/SignMeType.php index aca8eb5db..d762abfca 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/SignMeType.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/SignMeType.php @@ -2,7 +2,7 @@ namespace RainLoop\Enumerations; -class SignMeType +abstract class SignMeType { const DEFAULT_OFF = 'DefaultOff'; const DEFAULT_ON = 'DefaultOn'; diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/TimeFormat.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/TimeFormat.php deleted file mode 100644 index 0dc07e2c6..000000000 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/TimeFormat.php +++ /dev/null @@ -1,9 +0,0 @@ - Date: Mon, 26 Feb 2024 13:26:06 +0100 Subject: [PATCH 018/110] Added search functionality in Admin -> Config And removed the unused ['capa']['quota'] --- dev/Settings/Admin/Config.js | 25 +++++++++++++++++++ .../0.0.0/app/libraries/RainLoop/Actions.php | 1 - .../libraries/RainLoop/Actions/Messages.php | 2 +- .../app/libraries/RainLoop/ActionsAdmin.php | 2 ++ .../libraries/RainLoop/Config/Application.php | 3 +-- .../v/0.0.0/app/localization/cs-CZ/admin.json | 3 ++- .../v/0.0.0/app/localization/da-DK/admin.json | 3 ++- .../v/0.0.0/app/localization/de-DE/admin.json | 3 ++- .../v/0.0.0/app/localization/en/admin.json | 3 ++- .../v/0.0.0/app/localization/es-ES/admin.json | 3 ++- .../v/0.0.0/app/localization/eu/admin.json | 3 ++- .../v/0.0.0/app/localization/fa-IR/admin.json | 3 ++- .../v/0.0.0/app/localization/fi-FI/admin.json | 3 ++- .../v/0.0.0/app/localization/fr-FR/admin.json | 3 ++- .../v/0.0.0/app/localization/hu-HU/admin.json | 3 ++- .../v/0.0.0/app/localization/id-ID/admin.json | 3 ++- .../v/0.0.0/app/localization/it-IT/admin.json | 3 ++- .../v/0.0.0/app/localization/ja-JP/admin.json | 3 ++- .../v/0.0.0/app/localization/lt-LT/admin.json | 3 ++- .../v/0.0.0/app/localization/nb-NO/admin.json | 3 ++- .../v/0.0.0/app/localization/nl-NL/admin.json | 3 ++- .../v/0.0.0/app/localization/pl-PL/admin.json | 3 ++- .../v/0.0.0/app/localization/pt-BR/admin.json | 3 ++- .../v/0.0.0/app/localization/pt-PT/admin.json | 3 ++- .../v/0.0.0/app/localization/pt/admin.json | 3 ++- .../v/0.0.0/app/localization/ru-RU/admin.json | 3 ++- .../v/0.0.0/app/localization/sk-SK/admin.json | 3 ++- .../v/0.0.0/app/localization/sl-SI/admin.json | 3 ++- .../v/0.0.0/app/localization/sv-SE/admin.json | 3 ++- .../v/0.0.0/app/localization/vi-VN/admin.json | 3 ++- .../v/0.0.0/app/localization/zh-CN/admin.json | 3 ++- .../Views/Admin/AdminSettingsConfig.html | 1 + 32 files changed, 82 insertions(+), 30 deletions(-) diff --git a/dev/Settings/Admin/Config.js b/dev/Settings/Admin/Config.js index cd3e1dade..4c415adc1 100644 --- a/dev/Settings/Admin/Config.js +++ b/dev/Settings/Admin/Config.js @@ -7,7 +7,32 @@ export class AdminSettingsConfig /*extends AbstractViewSettings*/ { constructor() { this.config = ko.observableArray(); + this.search = ko.observableArray(); this.saved = ko.observable(false).extend({ falseTimeout: 5000 }); + + this.search.subscribe(value => { + const v = value.toLowerCase(), + qsa = (node, selector, fn) => node.querySelectorAll(selector).forEach(fn), + match = node => node.textContent.toLowerCase().includes(v); + if (v.length) { + qsa(this.viewModelDom, 'tbody', tbody => { + let show = match(tbody.querySelector('th')); + if (show) { + qsa(tbody, '[hidden]', n => n.hidden = false); + } else { + qsa(tbody, 'tbody td:first-child', td => { + let hide = !match(td); + show = show || !hide; +// td.closest('tr').hidden = hide; + td.parentNode.hidden = hide; + }); + } + tbody.hidden = !show; + }); + } else { + qsa(this.viewModelDom, 'table [hidden]', n => n.hidden = false); + } + }); } beforeShow() { diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php index eebc01df7..d1232c5f6 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php @@ -985,7 +985,6 @@ class Actions 'Identities' => (bool) $oConfig->Get('webmail', 'allow_additional_identities', false), 'Kolab' => false, // See Kolab plugin 'OpenPGP' => (bool) $oConfig->Get('security', 'openpgp', false), - 'Quota' => (bool) $oConfig->Get('capa', 'quota', true), 'Sieve' => false, 'Themes' => (bool) $oConfig->Get('webmail', 'allow_themes', false), 'UserBackground' => (bool) $oConfig->Get('webmail', 'allow_user_background', false) diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Messages.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Messages.php index 9e2db480d..3f6c4f163 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Messages.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Messages.php @@ -76,7 +76,7 @@ trait Messages $oParams->oCacher = $this->Cacher($oAccount); } -// $oParams->bUseSort = $this->ImapClient->hasCapability('SORT'); +// $oParams->bUseSort = $this->ImapClient()->hasCapability('SORT'); $oParams->bUseSort = true; $oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount); diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/ActionsAdmin.php b/snappymail/v/0.0.0/app/libraries/RainLoop/ActionsAdmin.php index c19423f0c..eed8be6f1 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/ActionsAdmin.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/ActionsAdmin.php @@ -25,6 +25,8 @@ class ActionsAdmin extends Actions unset($aConfig['version']); $aConfig['logs']['time_zone'][1] = ''; $aConfig['logs']['time_zone'][2] = \DateTimeZone::listIdentifiers(); + $aConfig['login']['sign_me_auto'][2] = ['DefaultOff','DefaultOn','Unused']; + $aConfig['defaults']['view_images'][2] = ['ask','match','always']; return $this->DefaultResponse($aConfig); } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Config/Application.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Config/Application.php index ff1e8b7ac..8ee4d7fdd 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Config/Application.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Config/Application.php @@ -262,7 +262,6 @@ Default is "site=same-origin;site=none"') ), 'capa' => array( - 'quota' => array(true), 'dangerous_actions' => array(true, 'Allow clear folder and delete messages without moving to trash'), 'attachments_actions' => array(true, 'Allow download attachments as Zip (and optionally others)') ), @@ -419,7 +418,7 @@ Enables caching in the system'), 'labs' => array( 'date_from_headers' => array(true, 'Display message RFC 2822 date and time header, instead of the arrival internal date.'), - 'allow_message_append' => array(false), + 'allow_message_append' => array(false, 'Allow drag & drop .eml files from system into messages list'), 'login_fault_delay' => array(5, 'When login fails, wait N seconds before responding'), 'log_ajax_response_write_limit' => array(300), 'smtp_show_server_errors' => array(false), diff --git a/snappymail/v/0.0.0/app/localization/cs-CZ/admin.json b/snappymail/v/0.0.0/app/localization/cs-CZ/admin.json index e49b78c0e..2e1c125d0 100644 --- a/snappymail/v/0.0.0/app/localization/cs-CZ/admin.json +++ b/snappymail/v/0.0.0/app/localization/cs-CZ/admin.json @@ -7,7 +7,8 @@ "UPDATE": "Aktualizovat", "USERNAME": "Uživatelské jméno", "PASSWORD": "Heslo", - "CANCEL": "Zrušit" + "CANCEL": "Zrušit", + "SEARCH": "Nebyly nalezeny žádné kontakty" }, "LOGIN": { "LABEL_LOGIN": "Login", diff --git a/snappymail/v/0.0.0/app/localization/da-DK/admin.json b/snappymail/v/0.0.0/app/localization/da-DK/admin.json index 3c9abe355..cefbbe277 100644 --- a/snappymail/v/0.0.0/app/localization/da-DK/admin.json +++ b/snappymail/v/0.0.0/app/localization/da-DK/admin.json @@ -7,7 +7,8 @@ "UPDATE": "Opdater", "USERNAME": "Brugernavn", "PASSWORD": "Adgangskode", - "CANCEL": "Annuller" + "CANCEL": "Annuller", + "SEARCH": "Ingen kontakter fundet" }, "LOGIN": { "LABEL_LOGIN": "Log ind", diff --git a/snappymail/v/0.0.0/app/localization/de-DE/admin.json b/snappymail/v/0.0.0/app/localization/de-DE/admin.json index 950c189d7..7a2388412 100644 --- a/snappymail/v/0.0.0/app/localization/de-DE/admin.json +++ b/snappymail/v/0.0.0/app/localization/de-DE/admin.json @@ -7,7 +7,8 @@ "UPDATE": "Aktualisieren", "USERNAME": "Nutzername", "PASSWORD": "Passwort", - "CANCEL": "Abbrechen" + "CANCEL": "Abbrechen", + "SEARCH": "Suchen" }, "LOGIN": { "LABEL_LOGIN": "Benutzer", diff --git a/snappymail/v/0.0.0/app/localization/en/admin.json b/snappymail/v/0.0.0/app/localization/en/admin.json index 98331ee32..f7269f857 100644 --- a/snappymail/v/0.0.0/app/localization/en/admin.json +++ b/snappymail/v/0.0.0/app/localization/en/admin.json @@ -7,7 +7,8 @@ "UPDATE": "Update", "USERNAME": "Username", "PASSWORD": "Password", - "CANCEL": "Cancel" + "CANCEL": "Cancel", + "SEARCH": "Search" }, "LOGIN": { "LABEL_LOGIN": "Login", diff --git a/snappymail/v/0.0.0/app/localization/es-ES/admin.json b/snappymail/v/0.0.0/app/localization/es-ES/admin.json index 68fc56f06..3ca6ad4cd 100644 --- a/snappymail/v/0.0.0/app/localization/es-ES/admin.json +++ b/snappymail/v/0.0.0/app/localization/es-ES/admin.json @@ -7,7 +7,8 @@ "UPDATE": "Actualizar", "USERNAME": "Nombre de usuario", "PASSWORD": "Contraseña", - "CANCEL": "Cancelar" + "CANCEL": "Cancelar", + "SEARCH": "Buscar" }, "LOGIN": { "LABEL_LOGIN": "Ingresar", diff --git a/snappymail/v/0.0.0/app/localization/eu/admin.json b/snappymail/v/0.0.0/app/localization/eu/admin.json index 0235b23cc..1e3fbfe8c 100644 --- a/snappymail/v/0.0.0/app/localization/eu/admin.json +++ b/snappymail/v/0.0.0/app/localization/eu/admin.json @@ -7,7 +7,8 @@ "UPDATE": "Eguneratu", "USERNAME": "Erabiltzailea", "PASSWORD": "Pasahitza", - "CANCEL": "Ezeztatu" + "CANCEL": "Ezeztatu", + "SEARCH": "Bilatu" }, "LOGIN": { "LABEL_LOGIN": "Login", diff --git a/snappymail/v/0.0.0/app/localization/fa-IR/admin.json b/snappymail/v/0.0.0/app/localization/fa-IR/admin.json index 4de8d5d7b..fb3820422 100644 --- a/snappymail/v/0.0.0/app/localization/fa-IR/admin.json +++ b/snappymail/v/0.0.0/app/localization/fa-IR/admin.json @@ -7,7 +7,8 @@ "UPDATE": "بروزرسانی", "USERNAME": "نام کاربری", "PASSWORD": "گذرواژه", - "CANCEL": "انصراف" + "CANCEL": "انصراف", + "SEARCH": "هیچ تماسی پیدا نشد" }, "LOGIN": { "LABEL_LOGIN": "ورود", diff --git a/snappymail/v/0.0.0/app/localization/fi-FI/admin.json b/snappymail/v/0.0.0/app/localization/fi-FI/admin.json index a0147ffea..0a6a836d9 100644 --- a/snappymail/v/0.0.0/app/localization/fi-FI/admin.json +++ b/snappymail/v/0.0.0/app/localization/fi-FI/admin.json @@ -7,7 +7,8 @@ "UPDATE": "Päivitä", "USERNAME": "Käyttäjätunnus", "PASSWORD": "Salasana", - "CANCEL": "Peruuta" + "CANCEL": "Peruuta", + "SEARCH": "Yhtään yhteystietoa ei löytynyt" }, "LOGIN": { "LABEL_LOGIN": "Tunnus", diff --git a/snappymail/v/0.0.0/app/localization/fr-FR/admin.json b/snappymail/v/0.0.0/app/localization/fr-FR/admin.json index 0ac55abb7..065ba67bc 100644 --- a/snappymail/v/0.0.0/app/localization/fr-FR/admin.json +++ b/snappymail/v/0.0.0/app/localization/fr-FR/admin.json @@ -7,7 +7,8 @@ "UPDATE": "Mettre à jour", "USERNAME": "Nom d'utilisateur", "PASSWORD": "Mot de passe", - "CANCEL": "Annuler" + "CANCEL": "Annuler", + "SEARCH": "Rechercher" }, "LOGIN": { "LABEL_LOGIN": "Identifiant", diff --git a/snappymail/v/0.0.0/app/localization/hu-HU/admin.json b/snappymail/v/0.0.0/app/localization/hu-HU/admin.json index 41a3d572d..48d198def 100644 --- a/snappymail/v/0.0.0/app/localization/hu-HU/admin.json +++ b/snappymail/v/0.0.0/app/localization/hu-HU/admin.json @@ -7,7 +7,8 @@ "UPDATE": "Frissítés", "USERNAME": "Felhasználónév", "PASSWORD": "Jelszó", - "CANCEL": "Mégse" + "CANCEL": "Mégse", + "SEARCH": "Nem találtam névjegyeket" }, "LOGIN": { "LABEL_LOGIN": "Belépés", diff --git a/snappymail/v/0.0.0/app/localization/id-ID/admin.json b/snappymail/v/0.0.0/app/localization/id-ID/admin.json index 0d7bb89e3..57dca6f98 100644 --- a/snappymail/v/0.0.0/app/localization/id-ID/admin.json +++ b/snappymail/v/0.0.0/app/localization/id-ID/admin.json @@ -7,7 +7,8 @@ "UPDATE": "Pembaruan", "USERNAME": "Nama belakang", "PASSWORD": "Sandi", - "CANCEL": "Batal" + "CANCEL": "Batal", + "SEARCH": "Tidak ditemukan kontak" }, "LOGIN": { "LABEL_LOGIN": "Login", diff --git a/snappymail/v/0.0.0/app/localization/it-IT/admin.json b/snappymail/v/0.0.0/app/localization/it-IT/admin.json index 021b332d9..7c4778d1c 100644 --- a/snappymail/v/0.0.0/app/localization/it-IT/admin.json +++ b/snappymail/v/0.0.0/app/localization/it-IT/admin.json @@ -7,7 +7,8 @@ "UPDATE": "Aggiorna", "USERNAME": "Nome utente", "PASSWORD": "Password", - "CANCEL": "Annulla" + "CANCEL": "Annulla", + "SEARCH": "Cerca" }, "LOGIN": { "LABEL_LOGIN": "Login", diff --git a/snappymail/v/0.0.0/app/localization/ja-JP/admin.json b/snappymail/v/0.0.0/app/localization/ja-JP/admin.json index 6ef1a1ea0..b1a3b6475 100644 --- a/snappymail/v/0.0.0/app/localization/ja-JP/admin.json +++ b/snappymail/v/0.0.0/app/localization/ja-JP/admin.json @@ -7,7 +7,8 @@ "UPDATE": "更新", "USERNAME": "ユーザー名", "PASSWORD": "パスワード", - "CANCEL": "キャンセル" + "CANCEL": "キャンセル", + "SEARCH": "検索" }, "LOGIN": { "LABEL_LOGIN": "ログイン", diff --git a/snappymail/v/0.0.0/app/localization/lt-LT/admin.json b/snappymail/v/0.0.0/app/localization/lt-LT/admin.json index 4aa1e10b8..338332f4b 100644 --- a/snappymail/v/0.0.0/app/localization/lt-LT/admin.json +++ b/snappymail/v/0.0.0/app/localization/lt-LT/admin.json @@ -7,7 +7,8 @@ "UPDATE": "Atnaujinti", "USERNAME": "Vartotojo vardas", "PASSWORD": "Slaptažodis", - "CANCEL": "Atšaukti" + "CANCEL": "Atšaukti", + "SEARCH": "Kontaktų nerasta" }, "LOGIN": { "LABEL_LOGIN": "Prisijungimo vardas", diff --git a/snappymail/v/0.0.0/app/localization/nb-NO/admin.json b/snappymail/v/0.0.0/app/localization/nb-NO/admin.json index 01c5045c7..0e9ad1ed5 100644 --- a/snappymail/v/0.0.0/app/localization/nb-NO/admin.json +++ b/snappymail/v/0.0.0/app/localization/nb-NO/admin.json @@ -7,7 +7,8 @@ "UPDATE": "Oppdater", "USERNAME": "Brukernavn", "PASSWORD": "Passord", - "CANCEL": "Avbryt" + "CANCEL": "Avbryt", + "SEARCH": "Fant ingen kontakter" }, "LOGIN": { "LABEL_LOGIN": "Brukernavn", diff --git a/snappymail/v/0.0.0/app/localization/nl-NL/admin.json b/snappymail/v/0.0.0/app/localization/nl-NL/admin.json index de7a7d07e..2e60fd590 100644 --- a/snappymail/v/0.0.0/app/localization/nl-NL/admin.json +++ b/snappymail/v/0.0.0/app/localization/nl-NL/admin.json @@ -7,7 +7,8 @@ "UPDATE": "Updaten", "USERNAME": "Gebruikersnaam", "PASSWORD": "Wachtwoord", - "CANCEL": "Annuleer" + "CANCEL": "Annuleer", + "SEARCH": "Zoeken" }, "LOGIN": { "LABEL_LOGIN": "Inlognaam", diff --git a/snappymail/v/0.0.0/app/localization/pl-PL/admin.json b/snappymail/v/0.0.0/app/localization/pl-PL/admin.json index 21ef22f3b..d1cd6f0aa 100644 --- a/snappymail/v/0.0.0/app/localization/pl-PL/admin.json +++ b/snappymail/v/0.0.0/app/localization/pl-PL/admin.json @@ -7,7 +7,8 @@ "UPDATE": "Zaktualizuj", "USERNAME": "Nazwa użytkownika", "PASSWORD": "Hasło", - "CANCEL": "Anuluj" + "CANCEL": "Anuluj", + "SEARCH": "Szukaj" }, "LOGIN": { "LABEL_LOGIN": "Login", diff --git a/snappymail/v/0.0.0/app/localization/pt-BR/admin.json b/snappymail/v/0.0.0/app/localization/pt-BR/admin.json index cece0a148..ca165436d 100644 --- a/snappymail/v/0.0.0/app/localization/pt-BR/admin.json +++ b/snappymail/v/0.0.0/app/localization/pt-BR/admin.json @@ -7,7 +7,8 @@ "UPDATE": "Atualizar", "USERNAME": "Nome de usuário", "PASSWORD": "Senha", - "CANCEL": "Cancelar" + "CANCEL": "Cancelar", + "SEARCH": "Nenhum contato encontrado" }, "LOGIN": { "LABEL_LOGIN": "Usuário", diff --git a/snappymail/v/0.0.0/app/localization/pt-PT/admin.json b/snappymail/v/0.0.0/app/localization/pt-PT/admin.json index b81726337..995612a4e 100644 --- a/snappymail/v/0.0.0/app/localization/pt-PT/admin.json +++ b/snappymail/v/0.0.0/app/localization/pt-PT/admin.json @@ -7,7 +7,8 @@ "UPDATE": "Atualizar", "USERNAME": "Nome de utilizador", "PASSWORD": "Palavra-passe", - "CANCEL": "Cancelar" + "CANCEL": "Cancelar", + "SEARCH": "Pesquisar" }, "LOGIN": { "LABEL_LOGIN": "Utilizador", diff --git a/snappymail/v/0.0.0/app/localization/pt/admin.json b/snappymail/v/0.0.0/app/localization/pt/admin.json index b81726337..995612a4e 100644 --- a/snappymail/v/0.0.0/app/localization/pt/admin.json +++ b/snappymail/v/0.0.0/app/localization/pt/admin.json @@ -7,7 +7,8 @@ "UPDATE": "Atualizar", "USERNAME": "Nome de utilizador", "PASSWORD": "Palavra-passe", - "CANCEL": "Cancelar" + "CANCEL": "Cancelar", + "SEARCH": "Pesquisar" }, "LOGIN": { "LABEL_LOGIN": "Utilizador", diff --git a/snappymail/v/0.0.0/app/localization/ru-RU/admin.json b/snappymail/v/0.0.0/app/localization/ru-RU/admin.json index f63e0e1e0..6b431dc1c 100644 --- a/snappymail/v/0.0.0/app/localization/ru-RU/admin.json +++ b/snappymail/v/0.0.0/app/localization/ru-RU/admin.json @@ -7,7 +7,8 @@ "UPDATE": "Обновить", "USERNAME": "Имя пользователя", "PASSWORD": "Пароль", - "CANCEL": "Отменить" + "CANCEL": "Отменить", + "SEARCH": "Поиск" }, "LOGIN": { "LABEL_LOGIN": "Логин", diff --git a/snappymail/v/0.0.0/app/localization/sk-SK/admin.json b/snappymail/v/0.0.0/app/localization/sk-SK/admin.json index 66c4e2681..4e89c4f0d 100644 --- a/snappymail/v/0.0.0/app/localization/sk-SK/admin.json +++ b/snappymail/v/0.0.0/app/localization/sk-SK/admin.json @@ -7,7 +7,8 @@ "UPDATE": "Aktualizovať", "USERNAME": "Používateľské men", "PASSWORD": "Heslo", - "CANCEL": "Zrušiť" + "CANCEL": "Zrušiť", + "SEARCH": "Nenašli sa žiadne kontakty" }, "LOGIN": { "LABEL_LOGIN": "Prihlasovanie", diff --git a/snappymail/v/0.0.0/app/localization/sl-SI/admin.json b/snappymail/v/0.0.0/app/localization/sl-SI/admin.json index dd4b444d1..226398a13 100644 --- a/snappymail/v/0.0.0/app/localization/sl-SI/admin.json +++ b/snappymail/v/0.0.0/app/localization/sl-SI/admin.json @@ -7,7 +7,8 @@ "UPDATE": "Posodobi", "USERNAME": "Uporabniško ime", "PASSWORD": "Geslo", - "CANCEL": "Prekliči" + "CANCEL": "Prekliči", + "SEARCH": "Ni ujemajočih stikov" }, "LOGIN": { "LABEL_LOGIN": "Prijava", diff --git a/snappymail/v/0.0.0/app/localization/sv-SE/admin.json b/snappymail/v/0.0.0/app/localization/sv-SE/admin.json index 2cb0e8554..188574317 100644 --- a/snappymail/v/0.0.0/app/localization/sv-SE/admin.json +++ b/snappymail/v/0.0.0/app/localization/sv-SE/admin.json @@ -7,7 +7,8 @@ "UPDATE": "Uppdatera", "USERNAME": "Användarnamn", "PASSWORD": "Lösenord", - "CANCEL": "Avbryt" + "CANCEL": "Avbryt", + "SEARCH": "Inga kontakter funna" }, "LOGIN": { "LABEL_LOGIN": "Logga in", diff --git a/snappymail/v/0.0.0/app/localization/vi-VN/admin.json b/snappymail/v/0.0.0/app/localization/vi-VN/admin.json index 085af03bd..a9f5cf570 100644 --- a/snappymail/v/0.0.0/app/localization/vi-VN/admin.json +++ b/snappymail/v/0.0.0/app/localization/vi-VN/admin.json @@ -7,7 +7,8 @@ "UPDATE": "Cập nhật", "USERNAME": "Tên tài khoản", "PASSWORD": "Mật khẩu", - "CANCEL": "Hủy" + "CANCEL": "Hủy", + "SEARCH": "Tìm kiếm" }, "LOGIN": { "LABEL_LOGIN": "Đăng nhập", diff --git a/snappymail/v/0.0.0/app/localization/zh-CN/admin.json b/snappymail/v/0.0.0/app/localization/zh-CN/admin.json index 1c92af253..96570af41 100644 --- a/snappymail/v/0.0.0/app/localization/zh-CN/admin.json +++ b/snappymail/v/0.0.0/app/localization/zh-CN/admin.json @@ -7,7 +7,8 @@ "UPDATE": "更新", "USERNAME": "用户名", "PASSWORD": "密码", - "CANCEL": "取消" + "CANCEL": "取消", + "SEARCH": "搜索" }, "LOGIN": { "LABEL_LOGIN": "登录", diff --git a/snappymail/v/0.0.0/app/templates/Views/Admin/AdminSettingsConfig.html b/snappymail/v/0.0.0/app/templates/Views/Admin/AdminSettingsConfig.html index 0019760ef..623557f84 100644 --- a/snappymail/v/0.0.0/app/templates/Views/Admin/AdminSettingsConfig.html +++ b/snappymail/v/0.0.0/app/templates/Views/Admin/AdminSettingsConfig.html @@ -1,5 +1,6 @@
application.ini
+
From 9006c377fdf25b31f8b74eab59534d99aa645bf9 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Mon, 26 Feb 2024 13:36:10 +0100 Subject: [PATCH 019/110] Cleanup Quota handling --- .../app/libraries/MailSo/Imap/Commands/Quota.php | 2 +- .../app/libraries/RainLoop/Actions/Folders.php | 13 +++++-------- .../v/0.0.0/app/libraries/RainLoop/Actions/User.php | 9 +-------- .../app/libraries/RainLoop/Enumerations/Capa.php | 1 - 4 files changed, 7 insertions(+), 18 deletions(-) diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Commands/Quota.php b/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Commands/Quota.php index 480be15cb..12cb374d5 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Commands/Quota.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Commands/Quota.php @@ -50,8 +50,8 @@ trait Quota if (!$this->hasCapability('QUOTA')) { return null; } + $aReturn = array(0, 0, 0, 0); $oResponseCollection = $this->SendRequest(($root?'GETQUOTAROOT':'GETQUOTA') . " {$this->EscapeFolderName($sFolderName)}"); - $aReturn = array(0, 0); foreach ($this->yieldUntaggedResponses() as $oResponse) { if ('QUOTA' === $oResponse->StatusOrIndex && isset($oResponse->ResponseList[3]) diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Folders.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Folders.php index 6ca21093b..e7ff3bc57 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Folders.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Folders.php @@ -86,14 +86,11 @@ trait Folders } if ($oFolderCollection) { - $aQuota = null; - if ($this->GetCapa(Capa::QUOTA)) { - try { -// $aQuota = $this->ImapClient()->Quota(); - $aQuota = $this->ImapClient()->QuotaRoot(); - } catch (\Throwable $oException) { - // ignore - } + try { +// $aQuota = $this->ImapClient()->Quota(); + $aQuota = $this->ImapClient()->QuotaRoot(); + } catch (\Throwable $oException) { + // ignore } $aCapabilities = \array_values(\array_filter($this->ImapClient()->Capability() ?: [], function ($item) { diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/User.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/User.php index 07db0edfd..8a15f8bcf 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/User.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/User.php @@ -225,21 +225,14 @@ trait User public function DoQuota() : array { $oAccount = $this->initMailClientConnection(); - - if (!$this->GetCapa(Capa::QUOTA)) { - return $this->DefaultResponse(array(0, 0, 0, 0)); - } - try { - $aQuota = $this->ImapClient()->QuotaRoot(); + return $this->DefaultResponse($this->ImapClient()->QuotaRoot() ?: [0, 0, 0, 0]); } catch (\Throwable $oException) { throw new ClientException(Notifications::MailServerError, $oException); } - - return $this->DefaultResponse($aQuota); } public function DoSuggestions() : array diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php index ba897a874..edc10a495 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php @@ -13,7 +13,6 @@ abstract class Capa const ADDITIONAL_ACCOUNTS = 'AdditionalAccounts'; const IDENTITIES = 'Identities'; const CONTACTS = 'Contacts'; - const QUOTA = 'Quota'; const ATTACHMENTS_ACTIONS = 'AttachmentsActions'; const DANGEROUS_ACTIONS = 'DangerousActions'; } From 6e1aae3f61c1f6b9def667d2ada320e8d524cdc9 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Mon, 26 Feb 2024 13:39:09 +0100 Subject: [PATCH 020/110] OPEN_PGP should be OPENPGP as it is one word --- snappymail/v/0.0.0/app/libraries/MailSo/Mail/Message.php | 2 +- snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php | 2 +- snappymail/v/0.0.0/app/localization/cs-CZ/admin.json | 2 +- snappymail/v/0.0.0/app/localization/da-DK/admin.json | 2 +- snappymail/v/0.0.0/app/localization/de-DE/admin.json | 2 +- snappymail/v/0.0.0/app/localization/en/admin.json | 2 +- snappymail/v/0.0.0/app/localization/es-ES/admin.json | 2 +- snappymail/v/0.0.0/app/localization/eu/admin.json | 2 +- snappymail/v/0.0.0/app/localization/fa-IR/admin.json | 2 +- snappymail/v/0.0.0/app/localization/fi-FI/admin.json | 2 +- snappymail/v/0.0.0/app/localization/fr-FR/admin.json | 2 +- snappymail/v/0.0.0/app/localization/hu-HU/admin.json | 2 +- snappymail/v/0.0.0/app/localization/id-ID/admin.json | 2 +- snappymail/v/0.0.0/app/localization/it-IT/admin.json | 2 +- snappymail/v/0.0.0/app/localization/ja-JP/admin.json | 2 +- snappymail/v/0.0.0/app/localization/lt-LT/admin.json | 2 +- snappymail/v/0.0.0/app/localization/nb-NO/admin.json | 2 +- snappymail/v/0.0.0/app/localization/nl-NL/admin.json | 2 +- snappymail/v/0.0.0/app/localization/pl-PL/admin.json | 2 +- snappymail/v/0.0.0/app/localization/pt-BR/admin.json | 2 +- snappymail/v/0.0.0/app/localization/pt-PT/admin.json | 2 +- snappymail/v/0.0.0/app/localization/pt/admin.json | 2 +- snappymail/v/0.0.0/app/localization/ru-RU/admin.json | 2 +- snappymail/v/0.0.0/app/localization/sk-SK/admin.json | 2 +- snappymail/v/0.0.0/app/localization/sl-SI/admin.json | 2 +- snappymail/v/0.0.0/app/localization/sv-SE/admin.json | 2 +- snappymail/v/0.0.0/app/localization/vi-VN/admin.json | 2 +- snappymail/v/0.0.0/app/localization/zh-CN/admin.json | 2 +- .../0.0.0/app/templates/Views/Admin/AdminSettingsSecurity.html | 2 +- 29 files changed, 29 insertions(+), 29 deletions(-) diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Mail/Message.php b/snappymail/v/0.0.0/app/libraries/MailSo/Mail/Message.php index 3578fdd2e..bb26b9b17 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Mail/Message.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Mail/Message.php @@ -543,7 +543,7 @@ class Message implements \JsonSerializable $result['html'] = $this->sHtml; $result['plain'] = $this->sPlain; } -// $this->GetCapa(Capa::OPEN_PGP) || $this->GetCapa(Capa::GNUPG) +// $this->GetCapa(Capa::OPENPGP) || $this->GetCapa(Capa::GNUPG) if ($this->pgpSigned) { $result['pgpSigned'] = $this->pgpSigned; } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php index edc10a495..083153859 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php @@ -5,7 +5,7 @@ namespace RainLoop\Enumerations; abstract class Capa { const GNUPG = 'GnuPG'; - const OPEN_PGP = 'OpenPGP'; + const OPENPGP = 'OpenPGP'; const THEMES = 'Themes'; const USER_BACKGROUND = 'UserBackground'; const SIEVE = 'Sieve'; diff --git a/snappymail/v/0.0.0/app/localization/cs-CZ/admin.json b/snappymail/v/0.0.0/app/localization/cs-CZ/admin.json index 2e1c125d0..979e5ac7b 100644 --- a/snappymail/v/0.0.0/app/localization/cs-CZ/admin.json +++ b/snappymail/v/0.0.0/app/localization/cs-CZ/admin.json @@ -85,7 +85,7 @@ "TAB_SECURITY": { "LEGEND_SECURITY": "Zabezpečení", "LABEL_USE_IMAGE_PROXY": "Použít lokální proxy pro externí obrázky", - "LABEL_ALLOW_OPEN_PGP": "Povolit OpenPGP", + "LABEL_ALLOW_OPENPGP": "Povolit OpenPGP", "LABEL_SHOW_PHP_INFO": "Zobrazit PHP informace (php_info)", "LEGEND_ADMIN_PANEL_ACCESS_CREDENTIALS": "Přístupové údaje administrace", "LABEL_CURRENT_PASSWORD": "Současné heslo", diff --git a/snappymail/v/0.0.0/app/localization/da-DK/admin.json b/snappymail/v/0.0.0/app/localization/da-DK/admin.json index cefbbe277..efe48787c 100644 --- a/snappymail/v/0.0.0/app/localization/da-DK/admin.json +++ b/snappymail/v/0.0.0/app/localization/da-DK/admin.json @@ -85,7 +85,7 @@ "TAB_SECURITY": { "LEGEND_SECURITY": "Sikkerhed", "LABEL_USE_IMAGE_PROXY": "Brug lokal proxy til eksterne billeder", - "LABEL_ALLOW_OPEN_PGP": "Tillad OpenPGP", + "LABEL_ALLOW_OPENPGP": "Tillad OpenPGP", "LABEL_SHOW_PHP_INFO": "Vis PHP informationer", "LEGEND_ADMIN_PANEL_ACCESS_CREDENTIALS": "Admin Panel Adgangsoplysninger", "LABEL_CURRENT_PASSWORD": "Nuværende adgangskode", diff --git a/snappymail/v/0.0.0/app/localization/de-DE/admin.json b/snappymail/v/0.0.0/app/localization/de-DE/admin.json index 7a2388412..f78a4934c 100644 --- a/snappymail/v/0.0.0/app/localization/de-DE/admin.json +++ b/snappymail/v/0.0.0/app/localization/de-DE/admin.json @@ -85,7 +85,7 @@ "TAB_SECURITY": { "LEGEND_SECURITY": "Sicherheit", "LABEL_USE_IMAGE_PROXY": "Lokalen Proxy für externe Bilder verwenden", - "LABEL_ALLOW_OPEN_PGP": "OpenPGP erlauben", + "LABEL_ALLOW_OPENPGP": "OpenPGP erlauben", "LABEL_SHOW_PHP_INFO": "PHP-Informationen anzeigen", "LEGEND_ADMIN_PANEL_ACCESS_CREDENTIALS": "Adminpanel-Zugangsdaten", "LABEL_CURRENT_PASSWORD": "Aktuelles Passwort", diff --git a/snappymail/v/0.0.0/app/localization/en/admin.json b/snappymail/v/0.0.0/app/localization/en/admin.json index f7269f857..ae7797e19 100644 --- a/snappymail/v/0.0.0/app/localization/en/admin.json +++ b/snappymail/v/0.0.0/app/localization/en/admin.json @@ -85,7 +85,7 @@ "TAB_SECURITY": { "LEGEND_SECURITY": "Security", "LABEL_USE_IMAGE_PROXY": "Use local proxy for external images", - "LABEL_ALLOW_OPEN_PGP": "Allow OpenPGP", + "LABEL_ALLOW_OPENPGP": "Allow OpenPGP", "LABEL_SHOW_PHP_INFO": "Show PHP information", "LEGEND_ADMIN_PANEL_ACCESS_CREDENTIALS": "Admin Panel Access Credentials", "LABEL_CURRENT_PASSWORD": "Current password", diff --git a/snappymail/v/0.0.0/app/localization/es-ES/admin.json b/snappymail/v/0.0.0/app/localization/es-ES/admin.json index 3ca6ad4cd..ccc13cdbf 100644 --- a/snappymail/v/0.0.0/app/localization/es-ES/admin.json +++ b/snappymail/v/0.0.0/app/localization/es-ES/admin.json @@ -85,7 +85,7 @@ "TAB_SECURITY": { "LEGEND_SECURITY": "Seguridad", "LABEL_USE_IMAGE_PROXY": "Utilizar un proxy local para mostrar imágenes externas", - "LABEL_ALLOW_OPEN_PGP": "Permitir OpenPGP", + "LABEL_ALLOW_OPENPGP": "Permitir OpenPGP", "LABEL_SHOW_PHP_INFO": "Mostrar información de PHP", "LEGEND_ADMIN_PANEL_ACCESS_CREDENTIALS": "Credenciales de Acceso al panel de control", "LABEL_CURRENT_PASSWORD": "Contraseña actual", diff --git a/snappymail/v/0.0.0/app/localization/eu/admin.json b/snappymail/v/0.0.0/app/localization/eu/admin.json index 1e3fbfe8c..8cf9cf9b7 100644 --- a/snappymail/v/0.0.0/app/localization/eu/admin.json +++ b/snappymail/v/0.0.0/app/localization/eu/admin.json @@ -85,7 +85,7 @@ "TAB_SECURITY": { "LEGEND_SECURITY": "Segurtasuna", "LABEL_USE_IMAGE_PROXY": "Erabili proxy lokala kanpoko irudientzat", - "LABEL_ALLOW_OPEN_PGP": "Baimendu OpenPGP", + "LABEL_ALLOW_OPENPGP": "Baimendu OpenPGP", "LABEL_SHOW_PHP_INFO": "Erakutsi PHP informazioa", "LEGEND_ADMIN_PANEL_ACCESS_CREDENTIALS": "Admin Panelerako Sarbide Kredentzialak", "LABEL_CURRENT_PASSWORD": "Uneko pasahitza", diff --git a/snappymail/v/0.0.0/app/localization/fa-IR/admin.json b/snappymail/v/0.0.0/app/localization/fa-IR/admin.json index fb3820422..1bbc393c8 100644 --- a/snappymail/v/0.0.0/app/localization/fa-IR/admin.json +++ b/snappymail/v/0.0.0/app/localization/fa-IR/admin.json @@ -85,7 +85,7 @@ "TAB_SECURITY": { "LEGEND_SECURITY": "امنیت", "LABEL_USE_IMAGE_PROXY": "از پروکسی محلی برای عکسهای خارج از سرور استفاده شود", - "LABEL_ALLOW_OPEN_PGP": "فعال‌سازی OpenPGP", + "LABEL_ALLOW_OPENPGP": "فعال‌سازی OpenPGP", "LABEL_SHOW_PHP_INFO": "نمایش اطلاعات PHP", "LEGEND_ADMIN_PANEL_ACCESS_CREDENTIALS": "اعتبار مجوز دسترسی به صفحه مدیریت", "LABEL_CURRENT_PASSWORD": "گذرواژه فعلی", diff --git a/snappymail/v/0.0.0/app/localization/fi-FI/admin.json b/snappymail/v/0.0.0/app/localization/fi-FI/admin.json index 0a6a836d9..3fed9ed01 100644 --- a/snappymail/v/0.0.0/app/localization/fi-FI/admin.json +++ b/snappymail/v/0.0.0/app/localization/fi-FI/admin.json @@ -85,7 +85,7 @@ "TAB_SECURITY": { "LEGEND_SECURITY": "Tietoturva", "LABEL_USE_IMAGE_PROXY": "Käytä paikallista proxya ulkoisille kuville.", - "LABEL_ALLOW_OPEN_PGP": "Salli OpenPGP", + "LABEL_ALLOW_OPENPGP": "Salli OpenPGP", "LABEL_SHOW_PHP_INFO": "Näytä PHP tiedot", "LEGEND_ADMIN_PANEL_ACCESS_CREDENTIALS": "Hallintapaneeli kirjautumistiedot", "LABEL_CURRENT_PASSWORD": "Nykyinen salasana", diff --git a/snappymail/v/0.0.0/app/localization/fr-FR/admin.json b/snappymail/v/0.0.0/app/localization/fr-FR/admin.json index 065ba67bc..ae74e7f74 100644 --- a/snappymail/v/0.0.0/app/localization/fr-FR/admin.json +++ b/snappymail/v/0.0.0/app/localization/fr-FR/admin.json @@ -85,7 +85,7 @@ "TAB_SECURITY": { "LEGEND_SECURITY": "Sécurité", "LABEL_USE_IMAGE_PROXY": "Utiliser un proxy local pour les images externes", - "LABEL_ALLOW_OPEN_PGP": "Autoriser OpenPGP", + "LABEL_ALLOW_OPENPGP": "Autoriser OpenPGP", "LABEL_SHOW_PHP_INFO": "Voir les informations PHP", "LEGEND_ADMIN_PANEL_ACCESS_CREDENTIALS": "Codes d'accès au panneau d'administration", "LABEL_CURRENT_PASSWORD": "Mot de passe actuel", diff --git a/snappymail/v/0.0.0/app/localization/hu-HU/admin.json b/snappymail/v/0.0.0/app/localization/hu-HU/admin.json index 48d198def..f400c4a73 100644 --- a/snappymail/v/0.0.0/app/localization/hu-HU/admin.json +++ b/snappymail/v/0.0.0/app/localization/hu-HU/admin.json @@ -85,7 +85,7 @@ "TAB_SECURITY": { "LEGEND_SECURITY": "Biztonság", "LABEL_USE_IMAGE_PROXY": "Helyi proxy használata a külső képekhez", - "LABEL_ALLOW_OPEN_PGP": "OpenPGP engedélyezése", + "LABEL_ALLOW_OPENPGP": "OpenPGP engedélyezése", "LABEL_SHOW_PHP_INFO": "PHP információ megjelenítése", "LEGEND_ADMIN_PANEL_ACCESS_CREDENTIALS": "Admin panel hozzáférés hitelesítés", "LABEL_CURRENT_PASSWORD": "Jelenlegi jelszó", diff --git a/snappymail/v/0.0.0/app/localization/id-ID/admin.json b/snappymail/v/0.0.0/app/localization/id-ID/admin.json index 57dca6f98..9dd0666d0 100644 --- a/snappymail/v/0.0.0/app/localization/id-ID/admin.json +++ b/snappymail/v/0.0.0/app/localization/id-ID/admin.json @@ -85,7 +85,7 @@ "TAB_SECURITY": { "LEGEND_SECURITY": "Keamanan", "LABEL_USE_IMAGE_PROXY": "Gunakan proxy lokal untuk gambar dari luar", - "LABEL_ALLOW_OPEN_PGP": "Izinkan OpenPGP", + "LABEL_ALLOW_OPENPGP": "Izinkan OpenPGP", "LABEL_SHOW_PHP_INFO": "Tampilkan informasi PHP", "LEGEND_ADMIN_PANEL_ACCESS_CREDENTIALS": "Hak Akses Panel Admin", "LABEL_CURRENT_PASSWORD": "Password saat ini", diff --git a/snappymail/v/0.0.0/app/localization/it-IT/admin.json b/snappymail/v/0.0.0/app/localization/it-IT/admin.json index 7c4778d1c..01c62b4cc 100644 --- a/snappymail/v/0.0.0/app/localization/it-IT/admin.json +++ b/snappymail/v/0.0.0/app/localization/it-IT/admin.json @@ -85,7 +85,7 @@ "TAB_SECURITY": { "LEGEND_SECURITY": "Sicurezza", "LABEL_USE_IMAGE_PROXY": "Use local proxy for external images", - "LABEL_ALLOW_OPEN_PGP": "Permetti OpenPGP", + "LABEL_ALLOW_OPENPGP": "Permetti OpenPGP", "LABEL_SHOW_PHP_INFO": "Mostra informazioni PHP", "LEGEND_ADMIN_PANEL_ACCESS_CREDENTIALS": "Credenziali di Accesso Pannello Admin", "LABEL_CURRENT_PASSWORD": "Password Corrente", diff --git a/snappymail/v/0.0.0/app/localization/ja-JP/admin.json b/snappymail/v/0.0.0/app/localization/ja-JP/admin.json index b1a3b6475..effd6fb8a 100644 --- a/snappymail/v/0.0.0/app/localization/ja-JP/admin.json +++ b/snappymail/v/0.0.0/app/localization/ja-JP/admin.json @@ -85,7 +85,7 @@ "TAB_SECURITY": { "LEGEND_SECURITY": "セキュリティ", "LABEL_USE_IMAGE_PROXY": "外部イメージにローカルProxyを使う", - "LABEL_ALLOW_OPEN_PGP": "OpenPGPを使う", + "LABEL_ALLOW_OPENPGP": "OpenPGPを使う", "LABEL_SHOW_PHP_INFO": "PHP情報を表示", "LEGEND_ADMIN_PANEL_ACCESS_CREDENTIALS": "管理画面アクセス情報", "LABEL_CURRENT_PASSWORD": "現在のパスワード", diff --git a/snappymail/v/0.0.0/app/localization/lt-LT/admin.json b/snappymail/v/0.0.0/app/localization/lt-LT/admin.json index 338332f4b..c4417e2c3 100644 --- a/snappymail/v/0.0.0/app/localization/lt-LT/admin.json +++ b/snappymail/v/0.0.0/app/localization/lt-LT/admin.json @@ -85,7 +85,7 @@ "TAB_SECURITY": { "LEGEND_SECURITY": "Sauga", "LABEL_USE_IMAGE_PROXY": "naudoti vietinį šliuzą (proxy) išoriniams paveikslėliams", - "LABEL_ALLOW_OPEN_PGP": "Leisti OpenPGP", + "LABEL_ALLOW_OPENPGP": "Leisti OpenPGP", "LABEL_SHOW_PHP_INFO": "Rodyti PHP informaciją", "LEGEND_ADMIN_PANEL_ACCESS_CREDENTIALS": "Valdymo skydo prieigos rekvizitai", "LABEL_CURRENT_PASSWORD": "Dabartinis slaptažodis", diff --git a/snappymail/v/0.0.0/app/localization/nb-NO/admin.json b/snappymail/v/0.0.0/app/localization/nb-NO/admin.json index 0e9ad1ed5..354730265 100644 --- a/snappymail/v/0.0.0/app/localization/nb-NO/admin.json +++ b/snappymail/v/0.0.0/app/localization/nb-NO/admin.json @@ -85,7 +85,7 @@ "TAB_SECURITY": { "LEGEND_SECURITY": "Sikkerhet", "LABEL_USE_IMAGE_PROXY": "Bruk lokal mellomtjener for eksterne bilder", - "LABEL_ALLOW_OPEN_PGP": "Tillat OpenPGP", + "LABEL_ALLOW_OPENPGP": "Tillat OpenPGP", "LABEL_SHOW_PHP_INFO": "Vis PHP-informasjon", "LEGEND_ADMIN_PANEL_ACCESS_CREDENTIALS": "Akkreditiver for admin-panel", "LABEL_CURRENT_PASSWORD": "Gjeldende passord", diff --git a/snappymail/v/0.0.0/app/localization/nl-NL/admin.json b/snappymail/v/0.0.0/app/localization/nl-NL/admin.json index 2e60fd590..c58142a1c 100644 --- a/snappymail/v/0.0.0/app/localization/nl-NL/admin.json +++ b/snappymail/v/0.0.0/app/localization/nl-NL/admin.json @@ -85,7 +85,7 @@ "TAB_SECURITY": { "LEGEND_SECURITY": "Beveiliging", "LABEL_USE_IMAGE_PROXY": "Gebruik de server als proxy voor externe afbeeldingen", - "LABEL_ALLOW_OPEN_PGP": "OpenPGP toestaan", + "LABEL_ALLOW_OPENPGP": "OpenPGP toestaan", "LABEL_SHOW_PHP_INFO": "PHP informatie tonen", "LEGEND_ADMIN_PANEL_ACCESS_CREDENTIALS": "Toegangsgegevens beheer paneel", "LABEL_CURRENT_PASSWORD": "Huidig wachtwoord", diff --git a/snappymail/v/0.0.0/app/localization/pl-PL/admin.json b/snappymail/v/0.0.0/app/localization/pl-PL/admin.json index d1cd6f0aa..4b65c8437 100644 --- a/snappymail/v/0.0.0/app/localization/pl-PL/admin.json +++ b/snappymail/v/0.0.0/app/localization/pl-PL/admin.json @@ -85,7 +85,7 @@ "TAB_SECURITY": { "LEGEND_SECURITY": "Bezpieczeństwo", "LABEL_USE_IMAGE_PROXY": "Użyj lokalnego serwera proxy dla zewnętrznych obrazów", - "LABEL_ALLOW_OPEN_PGP": "Zezwól na używanie OpenPGP", + "LABEL_ALLOW_OPENPGP": "Zezwól na używanie OpenPGP", "LABEL_SHOW_PHP_INFO": "Pokaż informacje o wersji PHP", "LEGEND_ADMIN_PANEL_ACCESS_CREDENTIALS": "Poświadczenia dostępu do panelu administracyjnego", "LABEL_CURRENT_PASSWORD": "Bieżące hasło", diff --git a/snappymail/v/0.0.0/app/localization/pt-BR/admin.json b/snappymail/v/0.0.0/app/localization/pt-BR/admin.json index ca165436d..56bcfd7eb 100644 --- a/snappymail/v/0.0.0/app/localization/pt-BR/admin.json +++ b/snappymail/v/0.0.0/app/localization/pt-BR/admin.json @@ -85,7 +85,7 @@ "TAB_SECURITY": { "LEGEND_SECURITY": "Segurança", "LABEL_USE_IMAGE_PROXY": "Usar proxy local para imagens externas", - "LABEL_ALLOW_OPEN_PGP": "Permitir OpenPGP", + "LABEL_ALLOW_OPENPGP": "Permitir OpenPGP", "LABEL_SHOW_PHP_INFO": "Mostar informações PHP", "LEGEND_ADMIN_PANEL_ACCESS_CREDENTIALS": "Credenciais de acesso ao Painel Administrativo", "LABEL_CURRENT_PASSWORD": "Senha atual", diff --git a/snappymail/v/0.0.0/app/localization/pt-PT/admin.json b/snappymail/v/0.0.0/app/localization/pt-PT/admin.json index 995612a4e..12adf1893 100644 --- a/snappymail/v/0.0.0/app/localization/pt-PT/admin.json +++ b/snappymail/v/0.0.0/app/localization/pt-PT/admin.json @@ -85,7 +85,7 @@ "TAB_SECURITY": { "LEGEND_SECURITY": "Segurança", "LABEL_USE_IMAGE_PROXY": "Usar proxy local para imagens externas", - "LABEL_ALLOW_OPEN_PGP": "Permitir OpenPGP", + "LABEL_ALLOW_OPENPGP": "Permitir OpenPGP", "LABEL_SHOW_PHP_INFO": "Mostrar informação do PHP", "LEGEND_ADMIN_PANEL_ACCESS_CREDENTIALS": "Credenciais de acesso ao Painel de Admin", "LABEL_CURRENT_PASSWORD": "Palavra-passe atual", diff --git a/snappymail/v/0.0.0/app/localization/pt/admin.json b/snappymail/v/0.0.0/app/localization/pt/admin.json index 995612a4e..12adf1893 100644 --- a/snappymail/v/0.0.0/app/localization/pt/admin.json +++ b/snappymail/v/0.0.0/app/localization/pt/admin.json @@ -85,7 +85,7 @@ "TAB_SECURITY": { "LEGEND_SECURITY": "Segurança", "LABEL_USE_IMAGE_PROXY": "Usar proxy local para imagens externas", - "LABEL_ALLOW_OPEN_PGP": "Permitir OpenPGP", + "LABEL_ALLOW_OPENPGP": "Permitir OpenPGP", "LABEL_SHOW_PHP_INFO": "Mostrar informação do PHP", "LEGEND_ADMIN_PANEL_ACCESS_CREDENTIALS": "Credenciais de acesso ao Painel de Admin", "LABEL_CURRENT_PASSWORD": "Palavra-passe atual", diff --git a/snappymail/v/0.0.0/app/localization/ru-RU/admin.json b/snappymail/v/0.0.0/app/localization/ru-RU/admin.json index 6b431dc1c..d516e2a7f 100644 --- a/snappymail/v/0.0.0/app/localization/ru-RU/admin.json +++ b/snappymail/v/0.0.0/app/localization/ru-RU/admin.json @@ -85,7 +85,7 @@ "TAB_SECURITY": { "LEGEND_SECURITY": "Безопасность", "LABEL_USE_IMAGE_PROXY": "Использовать локальный прокси для внешних изображений", - "LABEL_ALLOW_OPEN_PGP": "Разрешить OpenPGP", + "LABEL_ALLOW_OPENPGP": "Разрешить OpenPGP", "LABEL_SHOW_PHP_INFO": "Показать PHP информацию", "LEGEND_ADMIN_PANEL_ACCESS_CREDENTIALS": "Учетные данные для доступа к панели администратора", "LABEL_CURRENT_PASSWORD": "Текущий пароль", diff --git a/snappymail/v/0.0.0/app/localization/sk-SK/admin.json b/snappymail/v/0.0.0/app/localization/sk-SK/admin.json index 4e89c4f0d..71e3f1772 100644 --- a/snappymail/v/0.0.0/app/localization/sk-SK/admin.json +++ b/snappymail/v/0.0.0/app/localization/sk-SK/admin.json @@ -85,7 +85,7 @@ "TAB_SECURITY": { "LEGEND_SECURITY": "Bezpečnosť", "LABEL_USE_IMAGE_PROXY": "Use local proxy for external images", - "LABEL_ALLOW_OPEN_PGP": "Povoliť OpenPGP", + "LABEL_ALLOW_OPENPGP": "Povoliť OpenPGP", "LABEL_SHOW_PHP_INFO": "Zobraziť informácie o PHP", "LEGEND_ADMIN_PANEL_ACCESS_CREDENTIALS": "Admin Panel Access Credentials", "LABEL_CURRENT_PASSWORD": "Súčasné heslo", diff --git a/snappymail/v/0.0.0/app/localization/sl-SI/admin.json b/snappymail/v/0.0.0/app/localization/sl-SI/admin.json index 226398a13..3e9494052 100644 --- a/snappymail/v/0.0.0/app/localization/sl-SI/admin.json +++ b/snappymail/v/0.0.0/app/localization/sl-SI/admin.json @@ -85,7 +85,7 @@ "TAB_SECURITY": { "LEGEND_SECURITY": "Varnost", "LABEL_USE_IMAGE_PROXY": "Uporabni lokalni posredniški strežnik za zunanje slike", - "LABEL_ALLOW_OPEN_PGP": "Dovoli OpenPGP", + "LABEL_ALLOW_OPENPGP": "Dovoli OpenPGP", "LABEL_SHOW_PHP_INFO": "Prikaz PHP informacij", "LEGEND_ADMIN_PANEL_ACCESS_CREDENTIALS": "Prijavni podatki za administracijsko ploščo", "LABEL_CURRENT_PASSWORD": "Trenutno geslo", diff --git a/snappymail/v/0.0.0/app/localization/sv-SE/admin.json b/snappymail/v/0.0.0/app/localization/sv-SE/admin.json index 188574317..1d7730891 100644 --- a/snappymail/v/0.0.0/app/localization/sv-SE/admin.json +++ b/snappymail/v/0.0.0/app/localization/sv-SE/admin.json @@ -85,7 +85,7 @@ "TAB_SECURITY": { "LEGEND_SECURITY": "Säkerhet", "LABEL_USE_IMAGE_PROXY": "Använd lokal proxy för externa bilder", - "LABEL_ALLOW_OPEN_PGP": "Tillåt OpenPGP", + "LABEL_ALLOW_OPENPGP": "Tillåt OpenPGP", "LABEL_SHOW_PHP_INFO": "Visa PHP-information", "LEGEND_ADMIN_PANEL_ACCESS_CREDENTIALS": "Administrativsuppgifter", "LABEL_CURRENT_PASSWORD": "Nuvarande lösenord", diff --git a/snappymail/v/0.0.0/app/localization/vi-VN/admin.json b/snappymail/v/0.0.0/app/localization/vi-VN/admin.json index a9f5cf570..e8ea1a3b0 100644 --- a/snappymail/v/0.0.0/app/localization/vi-VN/admin.json +++ b/snappymail/v/0.0.0/app/localization/vi-VN/admin.json @@ -85,7 +85,7 @@ "TAB_SECURITY": { "LEGEND_SECURITY": "An ninh", "LABEL_USE_IMAGE_PROXY": "Sử dụng proxy tại máy chủ cho những hình ảnh tải ngoài về", - "LABEL_ALLOW_OPEN_PGP": "Cho phép OpenPGP", + "LABEL_ALLOW_OPENPGP": "Cho phép OpenPGP", "LABEL_SHOW_PHP_INFO": "Hiển thị thông tin PHP", "LEGEND_ADMIN_PANEL_ACCESS_CREDENTIALS": "Thông tin truy cập bảng quản trị", "LABEL_CURRENT_PASSWORD": "Mật khẩu hiện tại", diff --git a/snappymail/v/0.0.0/app/localization/zh-CN/admin.json b/snappymail/v/0.0.0/app/localization/zh-CN/admin.json index 96570af41..280df7686 100644 --- a/snappymail/v/0.0.0/app/localization/zh-CN/admin.json +++ b/snappymail/v/0.0.0/app/localization/zh-CN/admin.json @@ -85,7 +85,7 @@ "TAB_SECURITY": { "LEGEND_SECURITY": "安全", "LABEL_USE_IMAGE_PROXY": "对外部图片使用本地代理", - "LABEL_ALLOW_OPEN_PGP": "允许使用 OpenPGP", + "LABEL_ALLOW_OPENPGP": "允许使用 OpenPGP", "LABEL_SHOW_PHP_INFO": "显示 PHP 信息", "LEGEND_ADMIN_PANEL_ACCESS_CREDENTIALS": "管理员面板访问凭据", "LABEL_CURRENT_PASSWORD": "当前密码", diff --git a/snappymail/v/0.0.0/app/templates/Views/Admin/AdminSettingsSecurity.html b/snappymail/v/0.0.0/app/templates/Views/Admin/AdminSettingsSecurity.html index 2e5e27c57..a4721ccdf 100644 --- a/snappymail/v/0.0.0/app/templates/Views/Admin/AdminSettingsSecurity.html +++ b/snappymail/v/0.0.0/app/templates/Views/Admin/AdminSettingsSecurity.html @@ -13,7 +13,7 @@ name: 'Checkbox', params: { value: capaOpenPGP, - label: 'TAB_SECURITY/LABEL_ALLOW_OPEN_PGP' + label: 'TAB_SECURITY/LABEL_ALLOW_OPENPGP' } }"> From 118587dcf36cc049406cc13893a0eb18a4323624 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Mon, 26 Feb 2024 13:48:57 +0100 Subject: [PATCH 021/110] Improve Capa handling --- .../0.0.0/app/libraries/RainLoop/Actions.php | 34 ++++++++++--------- .../libraries/RainLoop/Enumerations/Capa.php | 14 ++++---- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php index d1232c5f6..3dbb5a992 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php @@ -2,6 +2,8 @@ namespace RainLoop; +use RainLoop\Enumerations\Capa; + class Actions { use Actions\Admin; @@ -471,7 +473,7 @@ class Actions $oDriver = null; try { // if ($this->oConfig->Get('contacts', 'enable', false)) { - if ($this->GetCapa(Enumerations\Capa::CONTACTS)) { + if ($this->GetCapa(Capa::CONTACTS)) { $oDriver = $this->fabrica('address-book', $oAccount); } if ($oAccount && $oDriver) { @@ -712,7 +714,7 @@ class Actions ]); $aAttachmentsActions = array(); - if ($this->GetCapa(Enumerations\Capa::ATTACHMENTS_ACTIONS)) { + if ($this->GetCapa(Capa::ATTACHMENTS_ACTIONS)) { if (\class_exists('PharData') || \class_exists('ZipArchive')) { $aAttachmentsActions[] = 'zip'; } @@ -809,7 +811,7 @@ class Actions $aResult['fontSerif'] = $oSettings->GetConf('fontSerif', ''); $aResult['fontMono'] = $oSettings->GetConf('fontMono', ''); - if ($this->GetCapa(Enumerations\Capa::USER_BACKGROUND)) { + if ($this->GetCapa(Capa::USER_BACKGROUND)) { $aResult['userBackgroundName'] = (string)$oSettings->GetConf('UserBackgroundName', ''); $aResult['userBackgroundHash'] = (string)$oSettings->GetConf('UserBackgroundHash', ''); } @@ -971,26 +973,26 @@ class Actions if (!$aResult) { $oConfig = $this->oConfig; $aResult = array( - 'AdditionalAccounts' => (bool) $oConfig->Get('webmail', 'allow_additional_accounts', false), - 'AttachmentThumbnails' => (bool) $oConfig->Get('interface', 'show_attachment_thumbnail', true) + Capa::ADDITIONAL_ACCOUNTS => (bool) $oConfig->Get('webmail', 'allow_additional_accounts', false), + Capa::ATTACHMENT_THUMBNAILS => (bool) $oConfig->Get('interface', 'show_attachment_thumbnail', true) && ($bAdmin || \extension_loaded('gd') || \extension_loaded('gmagick') || \extension_loaded('imagick') ), - 'AttachmentsActions' => (bool) $oConfig->Get('capa', 'attachments_actions', false), - 'Contacts' => (bool) $oConfig->Get('contacts', 'enable', false), - 'DangerousActions' => (bool) $oConfig->Get('capa', 'dangerous_actions', true), - 'GnuPG' => (bool) $oConfig->Get('security', 'openpgp', false) && \SnappyMail\PGP\GnuPG::isSupported(), - 'Identities' => (bool) $oConfig->Get('webmail', 'allow_additional_identities', false), - 'Kolab' => false, // See Kolab plugin - 'OpenPGP' => (bool) $oConfig->Get('security', 'openpgp', false), - 'Sieve' => false, - 'Themes' => (bool) $oConfig->Get('webmail', 'allow_themes', false), - 'UserBackground' => (bool) $oConfig->Get('webmail', 'allow_user_background', false) + Capa::ATTACHMENTS_ACTIONS => (bool) $oConfig->Get('capa', 'attachments_actions', false), + Capa::CONTACTS => (bool) $oConfig->Get('contacts', 'enable', false), + Capa::DANGEROUS_ACTIONS => (bool) $oConfig->Get('capa', 'dangerous_actions', true), + Capa::GNUPG => (bool) $oConfig->Get('security', 'openpgp', false) && \SnappyMail\PGP\GnuPG::isSupported(), + Capa::IDENTITIES => (bool) $oConfig->Get('webmail', 'allow_additional_identities', false), + Capa::OPENPGP => (bool) $oConfig->Get('security', 'openpgp', false), + Capa::SIEVE => false, + Capa::THEMES => (bool) $oConfig->Get('webmail', 'allow_themes', false), + Capa::USER_BACKGROUND => (bool) $oConfig->Get('webmail', 'allow_user_background', false), + 'Kolab' => false, // See Kolab plugin ); } - $aResult['Sieve'] = $bAdmin || ($oAccount && $oAccount->Domain()->UseSieve()); + $aResult[Capa::SIEVE] = $bAdmin || ($oAccount && $oAccount->Domain()->UseSieve()); return $aResult; } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php index 083153859..5637e9738 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php @@ -4,15 +4,15 @@ namespace RainLoop\Enumerations; abstract class Capa { + const ADDITIONAL_ACCOUNTS = 'AdditionalAccounts'; + const ATTACHMENTS_ACTIONS = 'AttachmentsActions'; + const ATTACHMENT_THUMBNAILS = 'AttachmentThumbnails'; + const CONTACTS = 'Contacts'; + const DANGEROUS_ACTIONS = 'DangerousActions'; const GNUPG = 'GnuPG'; + const IDENTITIES = 'Identities'; const OPENPGP = 'OpenPGP'; + const SIEVE = 'Sieve'; const THEMES = 'Themes'; const USER_BACKGROUND = 'UserBackground'; - const SIEVE = 'Sieve'; - const ATTACHMENT_THUMBNAILS = 'AttachmentThumbnails'; - const ADDITIONAL_ACCOUNTS = 'AdditionalAccounts'; - const IDENTITIES = 'Identities'; - const CONTACTS = 'Contacts'; - const ATTACHMENTS_ACTIONS = 'AttachmentsActions'; - const DANGEROUS_ACTIONS = 'DangerousActions'; } From 99b7ec661c9d34f2520fde6fdae9092602fd1d1a Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Mon, 26 Feb 2024 14:53:25 +0100 Subject: [PATCH 022/110] Resolve #1451 --- examples/docker/docker-compose.mysql.yml | 2 +- examples/docker/docker-compose.postgres.yml | 2 +- examples/docker/docker-compose.simple.yml | 2 +- examples/docker/docker-compose.traefik.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/docker/docker-compose.mysql.yml b/examples/docker/docker-compose.mysql.yml index b555a4c15..0e9844630 100644 --- a/examples/docker/docker-compose.mysql.yml +++ b/examples/docker/docker-compose.mysql.yml @@ -1,7 +1,7 @@ version: '2' services: snappymail: - image: leojonathanoh/snappymail:pr-1 + image: djmaze/snappymail:latest ports: - 8888:8888 environment: diff --git a/examples/docker/docker-compose.postgres.yml b/examples/docker/docker-compose.postgres.yml index f2bf1b7bb..bc9d4f33b 100644 --- a/examples/docker/docker-compose.postgres.yml +++ b/examples/docker/docker-compose.postgres.yml @@ -1,7 +1,7 @@ version: '2' services: snappymail: - image: leojonathanoh/snappymail:pr-1 + image: djmaze/snappymail:latest ports: - 8888:8888 environment: diff --git a/examples/docker/docker-compose.simple.yml b/examples/docker/docker-compose.simple.yml index e45f48477..fc112a3cc 100644 --- a/examples/docker/docker-compose.simple.yml +++ b/examples/docker/docker-compose.simple.yml @@ -1,7 +1,7 @@ version: '2' services: snappymail: - image: leojonathanoh/snappymail:pr-1 + image: djmaze/snappymail:latest ports: - 8888:8888 environment: diff --git a/examples/docker/docker-compose.traefik.yml b/examples/docker/docker-compose.traefik.yml index 91a8db51e..6ef69fcec 100644 --- a/examples/docker/docker-compose.traefik.yml +++ b/examples/docker/docker-compose.traefik.yml @@ -38,7 +38,7 @@ services: # snappymail will be available at: https://snappymail.example.com snappymail: - image: leojonathanoh/snappymail:pr-1 + image: djmaze/snappymail:latest labels: - "traefik.enable=true" - "traefik.docker.network=traefik-network" From 2559c09b2351d536d43685586120c212e24801a1 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Mon, 26 Feb 2024 16:42:35 +0100 Subject: [PATCH 023/110] Bugfix TypeError: b64Encode(...).match(...) is null --- dev/View/Popup/Compose.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/View/Popup/Compose.js b/dev/View/Popup/Compose.js index f14c6f068..8ced18616 100644 --- a/dev/View/Popup/Compose.js +++ b/dev/View/Popup/Compose.js @@ -66,7 +66,7 @@ const tpl = createElement('template'), - base64_encode = text => b64Encode(text).match(/.{1,76}/g).join('\r\n'), + base64_encode = text => text ? b64Encode(text).match(/.{1,76}/g).join('\r\n') : '', getEmail = value => addressparser(value)[0]?.email || false, From ab748aab99d51b95110505982c60c1f7bb7134cb Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Mon, 26 Feb 2024 16:44:25 +0100 Subject: [PATCH 024/110] Small StorageType change --- plugins/nextcloud/storage.php | 2 +- .../app/libraries/RainLoop/Model/Account.php | 7 ++ .../libraries/RainLoop/Model/MainAccount.php | 7 ++ .../Storage/Enumerations/StorageType.php | 13 ++- .../Providers/Storage/FileStorage.php | 99 +++++++++---------- 5 files changed, 70 insertions(+), 58 deletions(-) diff --git a/plugins/nextcloud/storage.php b/plugins/nextcloud/storage.php index 05f38fb82..c8c71e1fc 100644 --- a/plugins/nextcloud/storage.php +++ b/plugins/nextcloud/storage.php @@ -12,7 +12,7 @@ class NextcloudStorage extends \RainLoop\Providers\Storage\FileStorage $sDataPath = parent::GenerateFilePath($mAccount, $iStorageType, $bMkDir); if (StorageType::CONFIG === $iStorageType) { $sUID = \OC::$server->getUserSession()->getUser()->getUID(); - $sDataPath .= "/.config/{$sUID}/"; + $sDataPath .= ".config/{$sUID}/"; if ($bMkDir && !\is_dir($sDataPath) && !\mkdir($sDataPath, 0700, true)) { throw new \RainLoop\Exceptions\Exception('Can\'t make storage directory "'.$sDataPath.'"'); } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Model/Account.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Model/Account.php index 26b73bb16..05564db93 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Model/Account.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Model/Account.php @@ -306,4 +306,11 @@ abstract class Account implements \JsonSerializable return $bResult; } +/* + // Stores settings in AdditionalAccount else MainAccount + public function settingsLocal() : \RainLoop\Settings + { + return \RainLoop\Api::Actions()->SettingsProvider(true)->Load($this); + } +*/ } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Model/MainAccount.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Model/MainAccount.php index e2823c1a9..f48a3b2b1 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Model/MainAccount.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Model/MainAccount.php @@ -63,4 +63,11 @@ class MainAccount extends Account { $this->sCryptKey = new SensitiveString($sKey); } +/* + // Stores settings in MainAccount + public function settings() : \RainLoop\Settings + { + return \RainLoop\Api::Actions()->SettingsProvider()->Load($this); + } +*/ } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Storage/Enumerations/StorageType.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Storage/Enumerations/StorageType.php index 3d02b13a3..f2337ba41 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Storage/Enumerations/StorageType.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Storage/Enumerations/StorageType.php @@ -10,11 +10,10 @@ enum StorageType: int { */ abstract class StorageType { - const USER = 1; - const CONFIG = 2; - const NOBODY = 3; - const SIGN_ME = 4; - const SESSION = 5; - const PGP = 6; - const ROOT = 7; + const CONFIG = 1; + const NOBODY = 2; + const SIGN_ME = 3; + const SESSION = 4; + const PGP = 5; + const ROOT = 6; } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Storage/FileStorage.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Storage/FileStorage.php index 04f9948fd..5a3a7830f 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Storage/FileStorage.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Storage/FileStorage.php @@ -90,58 +90,57 @@ class FileStorage implements \RainLoop\Providers\Storage\IStorage */ public function GenerateFilePath($mAccount, int $iStorageType, bool $bMkDir = false) : string { - $sEmail = $sSubFolder = ''; - if (null === $mAccount) { - $iStorageType = StorageType::NOBODY; - } else if ($mAccount instanceof \RainLoop\Model\MainAccount) { - $sEmail = $mAccount->Email(); - } else if ($mAccount instanceof \RainLoop\Model\AdditionalAccount) { - $sEmail = $mAccount->ParentEmail(); - if ($this->bLocal) { - $sSubFolder = $mAccount->Email(); - } - } else if (\is_string($mAccount)) { - $sEmail = $mAccount; - } - - if ($sEmail) { - if (StorageType::SIGN_ME === $iStorageType) { - $sSubFolder = '.sign_me'; - } else if (StorageType::SESSION === $iStorageType) { - $sSubFolder = '.sessions'; - } else if (StorageType::PGP === $iStorageType) { - $sSubFolder = '.pgp'; - } else if (StorageType::ROOT === $iStorageType) { - $sSubFolder = ''; - } - } - - $sFilePath = ''; - switch ($iStorageType) - { - case StorageType::NOBODY: - $sFilePath = $this->sDataPath.'/__nobody__/'; - break; - case StorageType::SIGN_ME: - case StorageType::SESSION: - case StorageType::CONFIG: - case StorageType::PGP: - case StorageType::ROOT: - if (empty($sEmail)) { - return ''; + $sEmail = $sSubFolder = $sFilePath = ''; + if (null === $mAccount || StorageType::NOBODY === $iStorageType) { + $sFilePath = $this->sDataPath.'/__nobody__/'; + } else { + if ($mAccount instanceof \RainLoop\Model\MainAccount) { + $sEmail = $mAccount->Email(); + } else if ($mAccount instanceof \RainLoop\Model\AdditionalAccount) { + $sEmail = $mAccount->ParentEmail(); + if ($this->bLocal) { + $sSubFolder = $mAccount->Email(); } - if (\is_dir("{$this->sDataPath}/cfg")) { - \SnappyMail\Upgrade::FileStorage($this->sDataPath); + } else if (\is_string($mAccount)) { + $sEmail = $mAccount; + } + + if ($sEmail) { + // these are never local + if (StorageType::SIGN_ME === $iStorageType) { + $sSubFolder = '.sign_me'; + } else if (StorageType::SESSION === $iStorageType) { + $sSubFolder = '.sessions'; + } else if (StorageType::PGP === $iStorageType) { + $sSubFolder = '.pgp'; + } else if (StorageType::ROOT === $iStorageType) { + $sSubFolder = ''; } - $aEmail = \explode('@', $sEmail ?: 'nobody@unknown.tld'); - $sDomain = \trim(1 < \count($aEmail) ? \array_pop($aEmail) : ''); - $sFilePath = $this->sDataPath - .'/'.\MailSo\Base\Utils::SecureFileName($sDomain ?: 'unknown.tld') - .'/'.\MailSo\Base\Utils::SecureFileName(\implode('@', $aEmail) ?: '.unknown') - .'/'.($sSubFolder ? \MailSo\Base\Utils::SecureFileName($sSubFolder).'/' : ''); - break; - default: - throw new \Exception("Invalid storage type {$iStorageType}"); + } + + switch ($iStorageType) + { + case StorageType::CONFIG: + case StorageType::SIGN_ME: + case StorageType::SESSION: + case StorageType::PGP: + case StorageType::ROOT: + if (empty($sEmail)) { + return ''; + } + if (\is_dir("{$this->sDataPath}/cfg")) { + \SnappyMail\Upgrade::FileStorage($this->sDataPath); + } + $aEmail = \explode('@', $sEmail ?: 'nobody@unknown.tld'); + $sDomain = \trim(1 < \count($aEmail) ? \array_pop($aEmail) : ''); + $sFilePath = $this->sDataPath + .'/'.\MailSo\Base\Utils::SecureFileName($sDomain ?: 'unknown.tld') + .'/'.\MailSo\Base\Utils::SecureFileName(\implode('@', $aEmail) ?: '.unknown') + .'/'.($sSubFolder ? \MailSo\Base\Utils::SecureFileName($sSubFolder).'/' : ''); + break; + default: + throw new \Exception("Invalid storage type {$iStorageType}"); + } } if ($bMkDir && !empty($sFilePath) && !\is_dir($sFilePath) && !\mkdir($sFilePath, 0700, true)) From 0cbca605ec6f66ea400831d59b61a55bf645170d Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Mon, 26 Feb 2024 16:59:50 +0100 Subject: [PATCH 025/110] Bugfix: mailvelope editor failed --- dev/View/Popup/Compose.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/dev/View/Popup/Compose.js b/dev/View/Popup/Compose.js index 8ced18616..2fd0e23bd 100644 --- a/dev/View/Popup/Compose.js +++ b/dev/View/Popup/Compose.js @@ -1383,7 +1383,7 @@ export class ComposePopupView extends AbstractViewPopup { this.signOptions(options); } - initEncrypt() { + async initEncrypt() { const recipients = this.allRecipients(), options = []; @@ -1394,14 +1394,12 @@ export class ComposePopupView extends AbstractViewPopup { OpenPGPUserStore.hasPublicKeyForEmails(recipients) && options.push('OpenPGP'); - MailvelopeUserStore.hasPublicKeyForEmails(recipients).then(result => { - if (result) { - options.push('Mailvelope'); - } else { - 'mailvelope' === this.viewArea() && this.bodyArea(); - // this.dropMailvelope(); - } - }); + if (await MailvelopeUserStore.hasPublicKeyForEmails(recipients)) { + options.push('Mailvelope'); + } else { + 'mailvelope' === this.viewArea() && this.bodyArea(); +// this.dropMailvelope(); + } const count = recipients.length, identity = this.currentIdentity(), From 50569e1854e666954b37a860bb748794788da990 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Mon, 26 Feb 2024 17:17:32 +0100 Subject: [PATCH 026/110] Bugfix: undefined getMailvelopePrivateKeyFor() --- dev/Stores/User/Mailvelope.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/Stores/User/Mailvelope.js b/dev/Stores/User/Mailvelope.js index e811806f0..a4893f2fa 100644 --- a/dev/Stores/User/Mailvelope.js +++ b/dev/Stores/User/Mailvelope.js @@ -53,7 +53,7 @@ export const MailvelopeUserStore = { let emails = [...message.from,...message.to,...message.cc].validUnique(), i = emails.length; while (i--) { - if (await this.getMailvelopePrivateKeyFor(emails[i].email)) { + if (await this.getPrivateKeyFor(emails[i].email)) { /** * https://mailvelope.github.io/mailvelope/Mailvelope.html#createEncryptedFormContainer * Creates an iframe to display an encrypted form From 7bc302c66584171e9290e4584d45f5073859e92d Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Mon, 26 Feb 2024 17:36:55 +0100 Subject: [PATCH 027/110] Bugfix: MIME parser RegExp didn't escape `boundary` which caused issues --- dev/Mime/Parser.js | 2 +- dev/prototype.js | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/dev/Mime/Parser.js b/dev/Mime/Parser.js index 91e744add..2816d07a3 100644 --- a/dev/Mime/Parser.js +++ b/dev/Mime/Parser.js @@ -175,7 +175,7 @@ export function ParseMime(text) let boundary = headers['content-type']?.params.boundary; if (boundary) { part.boundary = boundary; - let regex = new RegExp('(?:^|\r?\n)--' + boundary + '(?:--)?(?:\r?\n|$)', 'g'), + let regex = new RegExp('(?:^|\r?\n)--' + RegExp.escape(boundary) + '(?:--)?(?:\r?\n|$)', 'g'), body = mimePart.slice(head.length), bodies = body.split(regex), pos = part.bodyStart; diff --git a/dev/prototype.js b/dev/prototype.js index 8e106d0a1..f8b74e92b 100644 --- a/dev/prototype.js +++ b/dev/prototype.js @@ -44,6 +44,13 @@ return template.content.firstChild; }; + /** + * https://github.com/tc39/proposal-regex-escaping + */ + if (!RegExp.escape){ + RegExp.escape = s => String(s).replace(/[\\^$*+?.()|[\]{}]/g, '\\$&'); + } + /** * Every time the function is executed, * it will delay the execution with the given amount of milliseconds. From 6f98aee998fef5c8861b9e005e8615fd62a2ab52 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Mon, 26 Feb 2024 18:26:51 +0100 Subject: [PATCH 028/110] Return detailed info on PgpImportKey --- .../v/0.0.0/app/libraries/RainLoop/Actions/Pgp.php | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Pgp.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Pgp.php index ea819cd17..768855c19 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Pgp.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Pgp.php @@ -221,15 +221,11 @@ trait Pgp } } - $result = false; + $result = []; if ($sKey) { $sKey = \trim($sKey); - if ($this->GetActionParam('backup', '')) { - $result = $result || Backup::PGPKey($sKey); - } - if ($this->GetActionParam('gnuPG', '') && ($GPG = $this->GnuPG())) { - $result = $result || $GPG->import($sKey); - } + $result['backup'] = $this->GetActionParam('backup', '') && Backup::PGPKey($sKey); + $result['gnuPG'] = $this->GetActionParam('gnuPG', '') && ($GPG = $this->GnuPG()) && $GPG->import($sKey); } return $this->DefaultResponse($result); From 6141ca7936cc0c9024fbcf37596d418ae9b27fba Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Mon, 26 Feb 2024 18:43:17 +0100 Subject: [PATCH 029/110] Show GnuPG verify error --- dev/Stores/User/GnuPG.js | 5 +++-- .../v/0.0.0/app/templates/Views/User/MailMessageView.html | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/dev/Stores/User/GnuPG.js b/dev/Stores/User/GnuPG.js index 45dc3e7dc..6b734c6b3 100644 --- a/dev/Stores/User/GnuPG.js +++ b/dev/Stores/User/GnuPG.js @@ -183,7 +183,7 @@ export const GnuPGUserStore = new class { } if (null !== params.passphrase) { const result = await Remote.post('GnupgDecrypt', null, params); - if (result?.Result && false !== result.Result.data) { + if (result?.Result?.data) { return result.Result; } Passphrases.delete(key); @@ -208,7 +208,8 @@ export const GnuPGUserStore = new class { if (response?.Result) { return { fingerprint: response.Result.fingerprint, - success: 0 == response.Result.status // GOODSIG + success: 0 == response.Result.status, // GOODSIG + error: response.Result.message }; } } diff --git a/snappymail/v/0.0.0/app/templates/Views/User/MailMessageView.html b/snappymail/v/0.0.0/app/templates/Views/User/MailMessageView.html index 53e17a085..111b344f6 100644 --- a/snappymail/v/0.0.0/app/templates/Views/User/MailMessageView.html +++ b/snappymail/v/0.0.0/app/templates/Views/User/MailMessageView.html @@ -302,6 +302,7 @@
+
From 091895df38bce63d9f9de47879e88f792304b8e0 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Mon, 26 Feb 2024 19:21:40 +0100 Subject: [PATCH 030/110] Sort PGP keys by email and id --- dev/Stores/User/GnuPG.js | 10 +++++++--- dev/Stores/User/OpenPGP.js | 29 +++++++++++++++-------------- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/dev/Stores/User/GnuPG.js b/dev/Stores/User/GnuPG.js index 6b734c6b3..f4351cb61 100644 --- a/dev/Stores/User/GnuPG.js +++ b/dev/Stores/User/GnuPG.js @@ -101,9 +101,13 @@ export const GnuPGUserStore = new class { }; key.view = () => key.fetch(() => showScreenPopup(OpenPgpKeyPopupView, [key])); return key; - }; - this.publicKeys(oData.Result.public.map(key => initKey(key, 0))); - this.privateKeys(oData.Result.private.map(key => initKey(key, 1))); + }, + collator = new Intl.Collator(undefined, {sensitivity: 'base'}), + sort = keys => keys.sort( + (a, b) => collator.compare(a.emails[0], b.emails[0]) || collator.compare(a.id, b.id) + ); + this.publicKeys(sort(oData.Result.public.map(key => initKey(key, 0)))); + this.privateKeys(sort(oData.Result.private.map(key => initKey(key, 1)))); console.log('gnupg ready'); } } diff --git a/dev/Stores/User/OpenPGP.js b/dev/Stores/User/OpenPGP.js index d61aad134..1a637f311 100644 --- a/dev/Stores/User/OpenPGP.js +++ b/dev/Stores/User/OpenPGP.js @@ -39,6 +39,15 @@ const } }, + collator = new Intl.Collator(undefined, {sensitivity: 'base'}), + sort = keys => keys.sort( +// (a, b) => collator.compare(a.emails[0], b.emails[0]) || collator.compare(a.fingerprint, b.fingerprint) + (a, b) => collator.compare(a.emails[0], b.emails[0]) || collator.compare(a.id, b.id) + ), + dedup = keys => sort((keys || []) + .filter((v, i, a) => a.findIndex(entry => entry.fingerprint == v.fingerprint) === i) + ), + /** * OpenPGP.js v5 removed the localStorage (keyring) * This should be compatible with the old OpenPGP.js v2 @@ -114,10 +123,6 @@ export const OpenPGPUserStore = new class { loadKeyrings() { if (window.openpgp) { - const collator = new Intl.Collator(undefined, {numeric: true, sensitivity: 'base'}), - dedup = keys => (keys || []) - .filter((v, i, a) => a.findIndex(entry => entry.fingerprint == v.fingerprint) === i) - .sort((a, b) => collator.compare(a.emails[0], b.emails[0])); loadOpenPgpKeys(publicKeysItem).then(keys => { this.publicKeys(dedup(keys)); console.log('openpgp.js public keys loaded'); @@ -140,16 +145,12 @@ export const OpenPGPUserStore = new class { window.openpgp && openpgp.readKey({armoredKey:armoredKey}).then(key => { if (!key.err) { key = new OpenPgpKeyModel(armoredKey, key); - if (key.key.isPrivate()) { - if (!this.privateKeys.find(entry => entry.fingerprint == key.fingerprint)) { - this.privateKeys.push(key); - storeOpenPgpKeys(this.privateKeys, privateKeysItem); - } - } else { - if (!this.publicKeys.find(entry => entry.fingerprint == key.fingerprint)) { - this.publicKeys.push(key); - storeOpenPgpKeys(this.publicKeys, publicKeysItem); - } + const isPrivate = key.key.isPrivate(), + keys = isPrivate ? this.privateKeys : this.publicKeys; + if (!keys.find(entry => entry.fingerprint == key.fingerprint)) { + keys.push(key); + keys(sort(keys)); + storeOpenPgpKeys(keys, isPrivate ? privateKeysItem : publicKeysItem); } } }); From 20daa1ce137f166fba83e1a89b76573f3ac04e2f Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Mon, 26 Feb 2024 19:34:50 +0100 Subject: [PATCH 031/110] Sort S/MIME certificates on emailAddress else validTo --- dev/Stores/User/SMime.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dev/Stores/User/SMime.js b/dev/Stores/User/SMime.js index f5f5dd312..70fa2043c 100644 --- a/dev/Stores/User/SMime.js +++ b/dev/Stores/User/SMime.js @@ -12,6 +12,9 @@ SMimeUserStore.loadCertificates = () => { SMimeUserStore.loading(true); Remote.request('SMimeGetCertificates', (iError, oData) => { SMimeUserStore.loading(false); - iError || SMimeUserStore(oData.Result); + const collator = new Intl.Collator(undefined, {sensitivity: 'base'}); + iError || SMimeUserStore(oData.Result.sort( + (a, b) => collator.compare(a.emailAddress, b.emailAddress) || (b.validTo_time_t - a.validTo_time_t) + )); }); }; From 97b65465e2045effcd4830f08dabc8e65b67a207 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Mon, 26 Feb 2024 22:34:15 +0100 Subject: [PATCH 032/110] S/MIME import from signature use `BEGIN PKCS7` --- .../0.0.0/app/libraries/RainLoop/Actions/SMime.php | 4 ++-- .../app/libraries/snappymail/smime/openssl.php | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/SMime.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/SMime.php index 96263411b..6b6638f19 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/SMime.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/SMime.php @@ -142,7 +142,7 @@ trait SMime $sBody = \trim($sBody); $certificates = []; \openssl_pkcs7_read( - "-----BEGIN CERTIFICATE-----\n\n{$sBody}\n-----END CERTIFICATE-----", + "-----BEGIN PKCS7-----\n\n{$sBody}\n-----END PKCS7-----", $certificates ) || \error_log("OpenSSL openssl_pkcs7_read: " . \openssl_error_string()); foreach ($certificates as $certificate) { @@ -179,7 +179,7 @@ trait SMime $sBody = \trim($sBody); $certificates = []; \openssl_pkcs7_read( - "-----BEGIN CERTIFICATE-----\n\n{$sBody}\n-----END CERTIFICATE-----", + "-----BEGIN PKCS7-----\n\n{$sBody}\n-----END PKCS7-----", $certificates ); diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/smime/openssl.php b/snappymail/v/0.0.0/app/libraries/snappymail/smime/openssl.php index 776aed98e..4bbd3617c 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/smime/openssl.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/smime/openssl.php @@ -142,6 +142,19 @@ class OpenSSL } } +/* + public function asn1parse(/*string|Temporary* / $input) : ?string + { + if (\is_string($input)) { + $tmp = new Temporary('smimein-'); + if (!$tmp->putContents($input)) { + return null; + } + $input = $tmp; + } + `openssl asn1parse -in $input->filename()` + } +*/ public function decrypt(/*string|Temporary*/ $input) : ?string { if (\is_string($input)) { From 182f88437435ccf5bdac58725c95d85d88435103 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Tue, 27 Feb 2024 02:19:12 +0100 Subject: [PATCH 033/110] Optionally use existing private key to generate S/MIME certificate --- dev/View/Popup/Identity.js | 3 +++ .../libraries/RainLoop/Actions/Accounts.php | 6 ++++- .../app/libraries/RainLoop/Actions/SMime.php | 8 +++--- .../app/libraries/RainLoop/Model/Identity.php | 10 +++++++ .../snappymail/smime/certificate.php | 26 ++++++++++++++----- .../templates/Views/User/PopupsIdentity.html | 2 +- 6 files changed, 41 insertions(+), 14 deletions(-) diff --git a/dev/View/Popup/Identity.js b/dev/View/Popup/Identity.js index 0a15cd6de..97b8de9d9 100644 --- a/dev/View/Popup/Identity.js +++ b/dev/View/Popup/Identity.js @@ -52,10 +52,13 @@ export class IdentityPopupView extends AbstractViewPopup { if (oData.Result.x509) { identity.smimeKey(oData.Result.pkey); identity.smimeCertificate(oData.Result.x509); + } else { + this.submitError(oData.ErrorMessage); } }, { name: identity.name(), email: identity.email(), + privateKey: identity.smimeKey(), passphrase: pass.password }); } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Accounts.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Accounts.php index 5a583f6e9..9de1db9f4 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Accounts.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Accounts.php @@ -261,7 +261,11 @@ trait Accounts if (!$oIdentity->FromJSON($this->GetActionParams(), true)) { throw new ClientException(Notifications::InvalidInputArgument); } - +/* // TODO: verify private key for certificate? + if ($oIdentity->smimeCertificate && $oIdentity->smimeKey) { + new \SnappyMail\SMime\Certificate($oIdentity->smimeCertificate, $oIdentity->smimeKey); + } +*/ $this->IdentitiesProvider()->UpdateIdentity($oAccount, $oIdentity); return $this->TrueResponse(); } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/SMime.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/SMime.php index 6b6638f19..6c1f47b13 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/SMime.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/SMime.php @@ -59,15 +59,13 @@ trait SMime { $oAccount = $this->getAccountFromToken(); - $sName = $this->GetActionParam('name', '') ?: $oAccount->Name(); - $sEmail = $this->GetActionParam('email', '') ?: $oAccount->Email(); $sPassphrase = $this->GetActionParam('passphrase', ''); $this->logMask($sPassphrase); $cert = new Certificate(); - $cert->distinguishedName['commonName'] = $sName; - $cert->distinguishedName['emailAddress'] = $sEmail; - $result = $cert->createSelfSigned($sPassphrase); + $cert->distinguishedName['commonName'] = $this->GetActionParam('name', '') ?: $oAccount->Name(); + $cert->distinguishedName['emailAddress'] = $this->GetActionParam('email', '') ?: $oAccount->Email(); + $result = $cert->createSelfSigned($sPassphrase, $this->GetActionParam('privateKey', '')); return $this->DefaultResponse($result ?: false); } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Model/Identity.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Model/Identity.php index 34f3d2398..3cbd725ee 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Model/Identity.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Model/Identity.php @@ -37,6 +37,16 @@ class Identity implements \JsonSerializable $this->sEmail = $sEmail; } + function __get(string $name) + { + if (!\property_exists($this, $name)) { + $name = \substr($name, 1); + } + if (\property_exists($this, $name)) { + return $this->$name; + } + } + function toMime() : \MailSo\Mime\Email { return new \MailSo\Mime\Email($this->sEmail, $this->sName); diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/smime/certificate.php b/snappymail/v/0.0.0/app/libraries/snappymail/smime/certificate.php index 801cebfaa..b897fbd85 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/smime/certificate.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/smime/certificate.php @@ -112,7 +112,11 @@ class Certificate return \openssl_get_cipher_methods($aliases); } - public function createSelfSigned(string $passphrase = '') : array + public function createSelfSigned( + #[\SensitiveParameter] + string $passphrase = '', + ?string $privateKey = null + ) : array { $options = array( 'config' => __DIR__ . '/openssl.cnf', @@ -134,7 +138,13 @@ class Certificate } $pkey = null; // openssl_pkey_new($options); - $csr = \openssl_csr_new($dn, $pkey, $options); + if ($privateKey) { + $pkey = \openssl_pkey_get_private($privateKey, $passphrase); + if (!$pkey) { + throw new \RuntimeException('OpenSSL pkey: ' . \openssl_error_string()); + } + } + $csr = \openssl_csr_new($dn, $pkey, $options); if ($csr) { $this->x509 = \openssl_csr_sign( $csr, @@ -145,13 +155,11 @@ class Certificate ); if ($this->x509/* && $this->canSign() && $this->canEncrypt()*/) { $this->pkey = $pkey; - $privatekey = ''; + $privateKey || \openssl_pkey_export($pkey, $privateKey, $passphrase); $certificate = ''; - $csrStr = ''; - \openssl_pkey_export($pkey, $privatekey, $passphrase); \openssl_x509_export($this->x509, $certificate); return array( - 'pkey' => $privatekey, + 'pkey' => $privateKey, 'x509' => $certificate, // 'pkcs12' => $this->asPKCS12($pkey, $passphrase/*, array $args = array()*/) // 'canSign' => $this->canSign(), @@ -167,7 +175,11 @@ class Certificate } // returns binary data - public function asPKCS12(string $pass = '', array $args = array()) : string + public function asPKCS12( + #[\SensitiveParameter] + string $pass = '', + array $args = array() + ) : string { $out = ''; \openssl_pkcs12_export($this->x509, $out, $this->pkey, $pass, $args); diff --git a/snappymail/v/0.0.0/app/templates/Views/User/PopupsIdentity.html b/snappymail/v/0.0.0/app/templates/Views/User/PopupsIdentity.html index f49013933..7dddd40cc 100644 --- a/snappymail/v/0.0.0/app/templates/Views/User/PopupsIdentity.html +++ b/snappymail/v/0.0.0/app/templates/Views/User/PopupsIdentity.html @@ -96,7 +96,7 @@ -
+
From 847d33abc6c17813098d4eb5cd55ab89496215d6 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Tue, 27 Feb 2024 02:31:53 +0100 Subject: [PATCH 034/110] Chaned some error_log() to MailSo Logger() --- .../v/0.0.0/app/libraries/RainLoop/Actions/Pgp.php | 2 +- .../v/0.0.0/app/libraries/RainLoop/Actions/SMime.php | 2 +- .../v/0.0.0/app/libraries/snappymail/smime/openssl.php | 9 ++++++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Pgp.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Pgp.php index 768855c19..fd0e38158 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Pgp.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Pgp.php @@ -81,7 +81,7 @@ trait Pgp if (\is_link($link) || \symlink($homedir, $link)) { $homedir = $link; } else { - \error_log("symlink('{$homedir}', '{$link}') failed"); + $this->logWrite("symlink('{$homedir}', '{$link}') failed", \LOG_WARNING, 'GnuPG'); } } // Else try ~/.gnupg/ + hash(email address) diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/SMime.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/SMime.php index 6c1f47b13..5068679ea 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/SMime.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/SMime.php @@ -142,7 +142,7 @@ trait SMime \openssl_pkcs7_read( "-----BEGIN PKCS7-----\n\n{$sBody}\n-----END PKCS7-----", $certificates - ) || \error_log("OpenSSL openssl_pkcs7_read: " . \openssl_error_string()); + ) || $this->logWrite("openssl_pkcs7_read: " . \openssl_error_string(), \LOG_ERR, 'OpenSSL'); foreach ($certificates as $certificate) { $this->SMIME()->storeCertificate($certificate); } diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/smime/openssl.php b/snappymail/v/0.0.0/app/libraries/snappymail/smime/openssl.php index 4bbd3617c..2f5b88f89 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/smime/openssl.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/smime/openssl.php @@ -34,12 +34,15 @@ class OpenSSL { $data = \openssl_x509_parse(\openssl_x509_read($certificate)); if (!$data) { - \error_log("OpenSSL parse: " . \openssl_error_string()); + \SnappyMail\Log::error('OpenSSL', "parse: " . \openssl_error_string()); return false; } $key = \str_replace(':', '', $data['extensions']['subjectKeyIdentifier'] ?? $data['hash']); $filename = "{$this->homedir}/{$key}.crt"; - if (!\file_exists($filename)) { + if (\file_exists($filename)) { + \SnappyMail\Log::debug('OpenSSL', 'certificate already imported'); + } else { + \SnappyMail\Log::debug('OpenSSL', 'certificate imported'); \file_put_contents("{$this->homedir}/{$key}.crt", $certificate); // \unlink("{$this->homedir}/certificates.json"); $this->certificates(true); @@ -98,7 +101,7 @@ class OpenSSL } $result[] = $short; } else { - \error_log("OpenSSL parse({$file}): " . \openssl_error_string()); + \SnappyMail\Log::error('OpenSSL', "parse({$file}): " . \openssl_error_string()); } } \file_put_contents($cacheFile, \json_encode($result)); From 0f7505baba2278381bae28964da49ab9e39fcc9a Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Tue, 27 Feb 2024 02:41:16 +0100 Subject: [PATCH 035/110] Force reload of S/MIME certificates list on import --- .../v/0.0.0/app/libraries/snappymail/smime/openssl.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/smime/openssl.php b/snappymail/v/0.0.0/app/libraries/snappymail/smime/openssl.php index 2f5b88f89..9b8fbbbc3 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/smime/openssl.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/smime/openssl.php @@ -40,12 +40,12 @@ class OpenSSL $key = \str_replace(':', '', $data['extensions']['subjectKeyIdentifier'] ?? $data['hash']); $filename = "{$this->homedir}/{$key}.crt"; if (\file_exists($filename)) { - \SnappyMail\Log::debug('OpenSSL', 'certificate already imported'); + \SnappyMail\Log::debug('OpenSSL', "certificate {$key} already imported"); } else { - \SnappyMail\Log::debug('OpenSSL', 'certificate imported'); \file_put_contents("{$this->homedir}/{$key}.crt", $certificate); // \unlink("{$this->homedir}/certificates.json"); $this->certificates(true); + \SnappyMail\Log::debug('OpenSSL', "certificate {$key} imported"); } return true; } @@ -53,7 +53,7 @@ class OpenSSL public function certificates(bool $force = false) : array { $cacheFile = "{$this->homedir}/certificates.json"; - $result = \file_exists($cacheFile) + $result = (!$force && \file_exists($cacheFile)) ? \json_decode(\file_get_contents($cacheFile), true) : null; if (!\is_array($result)) { From 7cacc9b503cfa2b7e7ace2e05c699f52462270b6 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Tue, 27 Feb 2024 11:03:36 +0100 Subject: [PATCH 036/110] Make better use of SnappyMail\SensitiveString --- .../snappymail/lib/Util/SnappyMailHelper.php | 6 ++-- .../libraries/RainLoop/Actions/Accounts.php | 6 ++-- .../RainLoop/Actions/AdminDomains.php | 4 +-- .../libraries/RainLoop/Actions/Messages.php | 7 ++--- .../app/libraries/RainLoop/Actions/Pgp.php | 17 +++++----- .../app/libraries/RainLoop/Actions/SMime.php | 12 +++---- .../app/libraries/RainLoop/Actions/User.php | 4 +-- .../libraries/RainLoop/Actions/UserAuth.php | 26 ++++++---------- .../app/libraries/RainLoop/ActionsAdmin.php | 24 ++++++-------- .../libraries/RainLoop/Config/Application.php | 19 +++--------- .../app/libraries/RainLoop/Model/Account.php | 31 +++++++------------ .../app/libraries/RainLoop/ServiceActions.php | 14 ++------- .../app/libraries/snappymail/gpg/base.php | 15 ++------- .../app/libraries/snappymail/gpg/pgp.php | 8 ++--- .../app/libraries/snappymail/pgp/gnupg.php | 20 +++--------- .../libraries/snappymail/sensitivestring.php | 9 +++++- .../snappymail/smime/certificate.php | 6 +--- .../libraries/snappymail/smime/openssl.php | 3 +- 18 files changed, 84 insertions(+), 147 deletions(-) diff --git a/integrations/nextcloud/snappymail/lib/Util/SnappyMailHelper.php b/integrations/nextcloud/snappymail/lib/Util/SnappyMailHelper.php index 1752da30a..721cdf86e 100644 --- a/integrations/nextcloud/snappymail/lib/Util/SnappyMailHelper.php +++ b/integrations/nextcloud/snappymail/lib/Util/SnappyMailHelper.php @@ -91,7 +91,6 @@ class SnappyMailHelper */ if ($doLogin && $aCredentials[1] && $aCredentials[2]) { try { - $oActions->Logger()->AddSecret($aCredentials[2]); $oAccount = $oActions->LoginProcess($aCredentials[1], $aCredentials[2]); if ($oAccount) { // Must be here due to bug #1241 @@ -202,9 +201,10 @@ class SnappyMailHelper return \SnappyMail\Crypt::EncryptUrlSafe($sPassword, $sSalt); } - public static function decodePassword(string $sPassword, string $sSalt)/* : mixed */ + public static function decodePassword(string $sPassword, string $sSalt) : ?\SnappyMail\SensitiveString { static::loadApp(); - return \SnappyMail\Crypt::DecryptUrlSafe($sPassword, $sSalt); + $result = \SnappyMail\Crypt::DecryptUrlSafe($sPassword, $sSalt); + return $result ? new \SnappyMail\SensitiveString($result) : $result; } } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Accounts.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Accounts.php index 9de1db9f4..1fd3d2003 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Accounts.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Accounts.php @@ -81,7 +81,7 @@ trait Accounts $aAccounts = $this->GetAccounts($oMainAccount); $sEmail = \trim($this->GetActionParam('email', '')); - $sPassword = $this->GetActionParam('password', ''); + $oPassword = new \SnappyMail\SensitiveString($this->GetActionParam('password', '')); $sName = \trim($this->GetActionParam('name', '')); $bNew = !empty($this->GetActionParam('new', 1)); @@ -92,8 +92,8 @@ trait Accounts throw new ClientException(Notifications::AccountDoesNotExist); } - if ($bNew || $sPassword) { - $oNewAccount = $this->LoginProcess($sEmail, $sPassword, false); + if ($bNew || \strlen($oPassword)) { + $oNewAccount = $this->LoginProcess($sEmail, $oPassword, false); $aAccounts[$sEmail] = $oNewAccount->asTokenArray($oMainAccount); } else { $aAccounts[$sEmail] = \RainLoop\Model\AdditionalAccount::convertArray($aAccounts[$sEmail]); diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/AdminDomains.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/AdminDomains.php index c7b1bc35d..c917f3bbf 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/AdminDomains.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/AdminDomains.php @@ -60,9 +60,9 @@ trait AdminDomains public function DoAdminDomainMatch() : array { $sEmail = $this->GetActionParam('username'); - $sPassword = '********'; + $oPassword = new \SnappyMail\SensitiveString('********'); $sLogin = ''; - $this->resolveLoginCredentials($sEmail, $sPassword, $sLogin); + $this->resolveLoginCredentials($sEmail, $oPassword, $sLogin); $oDomain = \str_contains($sEmail, '@') ? $this->DomainProvider()->Load(\MailSo\Base\Utils::GetDomainFromEmail($sEmail), true) : null; diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Messages.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Messages.php index 3f6c4f163..61c847220 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Messages.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Messages.php @@ -1065,8 +1065,7 @@ trait Messages } } - $sPassphrase = $this->GetActionParam('signPassphrase', ''); - $this->logMask($sPassphrase); + $oPassphrase = new \SnappyMail\SensitiveString($this->GetActionParam('signPassphrase', '')); $sFingerprint = $this->GetActionParam('signFingerprint', ''); if ($sFingerprint) { @@ -1084,7 +1083,7 @@ trait Messages $oMessage->SubParts->Clear(); $oMessage->Attachments()->Clear(); - $GPG->addSignKey($sFingerprint, $sPassphrase); + $GPG->addSignKey($sFingerprint, $oPassphrase); $GPG->setsignmode(GNUPG_SIG_MODE_DETACH); $sSignature = $GPG->signStream($fp); if (!$sSignature) { @@ -1127,7 +1126,7 @@ trait Messages $SMIME = $this->SMIME(); $SMIME->setCertificate($sCertificate); - $SMIME->setPrivateKey($sPrivateKey, $sPassphrase); + $SMIME->setPrivateKey($sPrivateKey, $oPassphrase); $sSignature = $SMIME->sign($tmp, $detached); if (!$sSignature) { diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Pgp.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Pgp.php index fd0e38158..ac427165f 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Pgp.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Pgp.php @@ -113,10 +113,9 @@ trait Pgp return $this->FalseResponse(); } - $sPassphrase = $this->GetActionParam('passphrase', ''); - $this->logMask($sPassphrase); + $oPassphrase = new \SnappyMail\SensitiveString($this->GetActionParam('passphrase', '')); - $GPG->addDecryptKey($this->GetActionParam('keyId', ''), $sPassphrase); + $GPG->addDecryptKey($this->GetActionParam('keyId', ''), $oPassphrase); $sData = $this->GetActionParam('data', ''); $oPart = null; @@ -160,12 +159,13 @@ trait Pgp public function DoGnupgExportKey() : array { - $sPassphrase = $this->GetActionParam('passphrase', ''); - $this->logMask($sPassphrase); + $oPassphrase = $this->GetActionParam('isPrivate', '') + ? new \SnappyMail\SensitiveString($this->GetActionParam('passphrase', '')) + : null; $GPG = $this->GnuPG(); return $this->DefaultResponse($GPG ? $GPG->export( $this->GetActionParam('keyId', ''), - $sPassphrase + $oPassphrase ) : false); } @@ -176,11 +176,10 @@ trait Pgp if ($GPG) { $sName = $this->GetActionParam('name', ''); $sEmail = $this->GetActionParam('email', ''); - $sPassphrase = $this->GetActionParam('passphrase', ''); - $this->logMask($sPassphrase); + $oPassphrase = new \SnappyMail\SensitiveString($this->GetActionParam('passphrase', '')); $fingerprint = $GPG->generateKey( $sName ? "{$sName} <{$sEmail}>" : $sEmail, - $sPassphrase + $oPassphrase ); } return $this->DefaultResponse($fingerprint); diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/SMime.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/SMime.php index 5068679ea..75e35e5d2 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/SMime.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/SMime.php @@ -53,19 +53,18 @@ trait SMime } /** - * Can be use by Identity + * Can be used by Identity */ public function DoSMimeCreateCertificate() : array { $oAccount = $this->getAccountFromToken(); - $sPassphrase = $this->GetActionParam('passphrase', ''); - $this->logMask($sPassphrase); + $oPassphrase = new \SnappyMail\SensitiveString($this->GetActionParam('passphrase', '')); $cert = new Certificate(); $cert->distinguishedName['commonName'] = $this->GetActionParam('name', '') ?: $oAccount->Name(); $cert->distinguishedName['emailAddress'] = $this->GetActionParam('email', '') ?: $oAccount->Email(); - $result = $cert->createSelfSigned($sPassphrase, $this->GetActionParam('privateKey', '')); + $result = $cert->createSelfSigned($oPassphrase, $this->GetActionParam('privateKey', '')); return $this->DefaultResponse($result ?: false); } @@ -76,8 +75,7 @@ trait SMime $sPartId = $this->GetActionParam('partId', ''); $sCertificate = $this->GetActionParam('certificate', ''); $sPrivateKey = $this->GetActionParam('privateKey', ''); - $sPassphrase = $this->GetActionParam('passphrase', ''); - $this->logMask($sPassphrase); + $oPassphrase = new \SnappyMail\SensitiveString($this->GetActionParam('passphrase', '')); $this->initMailClientConnection(); $oImapClient = $this->ImapClient(); @@ -104,7 +102,7 @@ trait SMime $SMIME = $this->SMIME(); $SMIME->setCertificate($sCertificate); - $SMIME->setPrivateKey($sPrivateKey, $sPassphrase); + $SMIME->setPrivateKey($sPrivateKey, $oPassphrase); $result = $SMIME->decrypt($sBody); return $this->DefaultResponse($result ?: false); diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/User.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/User.php index 8a15f8bcf..91ff9775f 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/User.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/User.php @@ -36,10 +36,10 @@ trait User public function DoLogin() : array { $sEmail = \MailSo\Base\Utils::Trim($this->GetActionParam('Email', '')); - $sPassword = $this->GetActionParam('Password', ''); + $oPassword = new \SnappyMail\SensitiveString($this->GetActionParam('Password', '')); try { - $oAccount = $this->LoginProcess($sEmail, $sPassword); + $oAccount = $this->LoginProcess($sEmail, $oPassword); } catch (\Throwable $oException) { $this->loginErrorDelay(); throw $oException; diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/UserAuth.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/UserAuth.php index fc93974b9..89b72d1a8 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/UserAuth.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/UserAuth.php @@ -22,10 +22,7 @@ trait UserAuth /** * @throws \RainLoop\Exceptions\ClientException */ - public function resolveLoginCredentials(string &$sEmail, - #[\SensitiveParameter] - string &$sPassword, - string &$sLogin): void + public function resolveLoginCredentials(string &$sEmail, \SnappyMail\SensitiveString $oPassword, string &$sLogin): void { $sEmail = \MailSo\Base\Utils::Trim($sEmail); if ($this->Config()->Get('login', 'login_lowercase', true)) { @@ -101,43 +98,40 @@ trait UserAuth } } + $sPassword = (string) $oPassword; $this->Plugins()->RunHook('login.credentials.step-2', array(&$sEmail, &$sPassword)); + $this->logMask($sPassword); $sLogin = $sEmail; if ($this->Config()->Get('login', 'login_lowercase', true)) { $sLogin = \mb_strtolower($sLogin); } - $this->logMask($sPassword); $this->Plugins()->RunHook('login.credentials', array(&$sEmail, &$sLogin, &$sPassword)); $this->logMask($sPassword); + + $oPassword->setValue($sPassword); } /** * @throws \RainLoop\Exceptions\ClientException */ - public function LoginProcess(string &$sEmail, - #[\SensitiveParameter] - string &$sPassword, - bool $bMainAccount = true - ): Account + public function LoginProcess(string &$sEmail, \SnappyMail\SensitiveString $oPassword, bool $bMainAccount = true): Account { $sInputEmail = $sEmail; - $this->logMask($sPassword); - $sLogin = ''; - $this->resolveLoginCredentials($sEmail, $sPassword, $sLogin); + $this->resolveLoginCredentials($sEmail, $oPassword, $sLogin); - if (!\str_contains($sEmail, '@') || !\strlen($sPassword)) { + if (!\str_contains($sEmail, '@') || !\strlen($oPassword)) { throw new ClientException(Notifications::InvalidInputArgument); } $oAccount = null; try { $oAccount = $bMainAccount - ? MainAccount::NewInstanceFromCredentials($this, $sEmail, $sLogin, $sPassword, true) - : AdditionalAccount::NewInstanceFromCredentials($this, $sEmail, $sLogin, $sPassword, true); + ? MainAccount::NewInstanceFromCredentials($this, $sEmail, $sLogin, $oPassword, true) + : AdditionalAccount::NewInstanceFromCredentials($this, $sEmail, $sLogin, $oPassword, true); if (!$oAccount) { throw new ClientException(Notifications::AuthError); } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/ActionsAdmin.php b/snappymail/v/0.0.0/app/libraries/RainLoop/ActionsAdmin.php index eed8be6f1..757169491 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/ActionsAdmin.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/ActionsAdmin.php @@ -111,17 +111,15 @@ class ActionsAdmin extends Actions public function DoAdminLogin() : array { $sLogin = trim($this->GetActionParam('Login', '')); - $sPassword = $this->GetActionParam('Password', ''); - - $this->logMask($sPassword); + $oPassword = new \SnappyMail\SensitiveString($this->GetActionParam('Password', '')); $totp = $this->Config()->Get('security', 'admin_totp', ''); // \explode(':',`getent shadow root`)[1]; - if (!\strlen($sLogin) || !\strlen($sPassword) || + if (!\strlen($sLogin) || !\strlen($oPassword) || !$this->Config()->Get('security', 'allow_admin_panel', true) || $sLogin !== $this->Config()->Get('security', 'admin_login', '') || - !$this->Config()->ValidatePassword($sPassword) + !$this->Config()->ValidatePassword($oPassword) || ($totp && !\SnappyMail\TOTP::Verify($totp, $this->GetActionParam('TOTP', '')))) { $this->LoggerAuthHelper(null, $this->getAdditionalLogParamsByUserLogin($sLogin, true), true); @@ -183,17 +181,13 @@ class ActionsAdmin extends Actions $bResult = false; $oConfig = $this->Config(); - $sPassword = $this->GetActionParam('Password', ''); - $this->logMask($sPassword); + $oPassword = new \SnappyMail\SensitiveString($this->GetActionParam('Password', '')); - $sNewPassword = $this->GetActionParam('newPassword', ''); - if (\strlen($sNewPassword)) { - $this->logMask($sNewPassword); - } + $oNewPassword = new \SnappyMail\SensitiveString($this->GetActionParam('newPassword', '')); $passfile = APP_PRIVATE_DATA.'admin_password.txt'; - if ($oConfig->ValidatePassword($sPassword)) { + if ($oConfig->ValidatePassword($oPassword)) { $sLogin = \trim($this->GetActionParam('Login', '')); if (\strlen($sLogin)) { $oConfig->Set('security', 'admin_login', $sLogin); @@ -201,9 +195,9 @@ class ActionsAdmin extends Actions $oConfig->Set('security', 'admin_totp', $this->GetActionParam('TOTP', '')); - if (\strlen($sNewPassword)) { - $oConfig->SetPassword($sNewPassword); - if (\is_file($passfile) && \trim(\file_get_contents($passfile)) !== $sNewPassword) { + if (\strlen($oNewPassword)) { + $oConfig->SetPassword($oNewPassword); + if (\is_file($passfile) && \trim(\file_get_contents($passfile)) !== (string) $oNewPassword) { \unlink($passfile); } } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Config/Application.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Config/Application.php index 8ee4d7fdd..e27f7dd20 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Config/Application.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Config/Application.php @@ -120,25 +120,14 @@ class Application extends \RainLoop\Config\AbstractConfig parent::Set($sSectionKey, $sParamKey, $mParamValue); } - public function SetPassword( - #[\SensitiveParameter] - string $sPassword - ) : void + public function SetPassword(\SnappyMail\SensitiveString $oPassword) : void { - $this->Set('security', 'admin_password', \password_hash($sPassword, PASSWORD_DEFAULT)); + $this->Set('security', 'admin_password', \password_hash($oPassword, PASSWORD_DEFAULT)); } - public function ValidatePassword( - #[\SensitiveParameter] - string $sPassword - ) : bool + public function ValidatePassword(\SnappyMail\SensitiveString $oPassword) : bool { - $sConfigPassword = (string) $this->Get('security', 'admin_password', ''); - if (32 == \strlen($sPassword) && \md5(APP_SALT.$sPassword.APP_SALT) === $sConfigPassword) { - $this->SetPassword($sPassword); - return true; - } - return \strlen($sPassword) && \password_verify($sPassword, $sConfigPassword); + return \strlen($oPassword) && \password_verify($oPassword, $this->Get('security', 'admin_password', '')); } public function Save() : bool diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Model/Account.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Model/Account.php index 05564db93..f2b9ad8b2 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Model/Account.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Model/Account.php @@ -15,7 +15,7 @@ abstract class Account implements \JsonSerializable private string $sLogin = ''; - private ?SensitiveString $sPassword = null; + private ?SensitiveString $oPassword = null; private string $sSmtpLogin = ''; @@ -46,7 +46,7 @@ abstract class Account implements \JsonSerializable public function IncPassword() : string { - return $this->sPassword ? $this->sPassword->getValue() : ''; + return $this->oPassword ? $this->oPassword->getValue() : ''; } public function OutLogin() : string @@ -66,16 +66,13 @@ abstract class Account implements \JsonSerializable $this->sEmail, $this->sLogin, // \json_encode($this->Domain()), -// $this->sPassword +// $this->oPassword ])); } - public function SetPassword( - #[\SensitiveParameter] - string $sPassword - ) : void + public function SetPassword(SensitiveString $oPassword) : void { - $this->sPassword = new SensitiveString($sPassword); + $this->oPassword = $oPassword; } public function SetSmtpPassword( @@ -125,12 +122,11 @@ abstract class Account implements \JsonSerializable public static function NewInstanceFromCredentials(\RainLoop\Actions $oActions, string $sEmail, string $sLogin, - #[\SensitiveParameter] - string $sPassword, + SensitiveString $oPassword, bool $bThrowException = false): ?self { $oAccount = null; - if ($sEmail && $sLogin && $sPassword) { + if ($sEmail && $sLogin && \strlen($oPassword)) { $oDomain = $oActions->DomainProvider()->Load(\MailSo\Base\Utils::GetDomainFromEmail($sEmail), true); if ($oDomain) { if ($oDomain->ValidateWhiteList($sEmail, $sLogin)) { @@ -138,7 +134,7 @@ abstract class Account implements \JsonSerializable $oAccount->sEmail = \MailSo\Base\Utils::IdnToAscii($sEmail, true); $oAccount->sLogin = \MailSo\Base\Utils::IdnToAscii($sLogin); - $oAccount->SetPassword($sPassword); + $oAccount->SetPassword($oPassword); $oAccount->oDomain = $oDomain; $oActions->Plugins()->RunHook('filter.account', array($oAccount)); @@ -194,25 +190,22 @@ abstract class Account implements \JsonSerializable $oActions, $aAccountHash['email'], $aAccountHash['login'], - $aAccountHash['pass'], + new SensitiveString($aAccountHash['pass']), $bThrowExceptionOnFalse ); if ($oAccount) { if (isset($aAccountHash['name'])) { $oAccount->sName = $aAccountHash['name']; } - $oActions->logMask($oAccount->IncPassword()); // init smtp user/password if (isset($aAccountHash['smtp'])) { $oAccount->sSmtpLogin = $aAccountHash['smtp']['user']; $oAccount->SetSmtpPassword($aAccountHash['smtp']['pass']); - $oActions->logMask($oAccount->sSmtpPassword); } // init proxy user/password if (isset($aAccountHash['proxy'])) { $oAccount->sProxyAuthUser = $aAccountHash['proxy']['user']; $oAccount->SetProxyAuthPassword($aAccountHash['proxy']['pass']); - $oActions->logMask($oAccount->sProxyAuthPassword); } } } @@ -240,7 +233,7 @@ abstract class Account implements \JsonSerializable $oImapClient->Connect($oSettings); $oPlugins->RunHook('imap.after-connect', array($this, $oImapClient, $oSettings)); - $oSettings->Password = $this->sPassword; + $oSettings->Password = $this->oPassword; return $this->netClientLogin($oImapClient, $oPlugins); } @@ -264,7 +257,7 @@ abstract class Account implements \JsonSerializable throw new RequireCredentialsException } */ - $oSettings->Password = $this->sSmtpPassword ?: $this->sPassword; + $oSettings->Password = $this->sSmtpPassword ?: $this->oPassword; return $this->netClientLogin($oSmtpClient, $oPlugins); } @@ -279,7 +272,7 @@ abstract class Account implements \JsonSerializable $oSieveClient->Connect($oSettings); $oPlugins->RunHook('sieve.after-connect', array($this, $oSieveClient, $oSettings)); - $oSettings->Password = $this->sPassword; + $oSettings->Password = $this->oPassword; return $this->netClientLogin($oSieveClient, $oPlugins); } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php b/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php index a4986f70f..f88ccc374 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php @@ -120,16 +120,6 @@ class ServiceActions $aPost[$key] = '*******'; } } -/* - switch ($sMethodName) - { - case 'DoLogin': - case 'DoAdminLogin': - case 'DoAccountAdd': - $this->oActions->logMask($this->oActions->GetActionParam('Password', '')); - break; - } -*/ $this->oActions->logWrite(Utils::jsonEncode($aPost), \LOG_INFO, 'POST'); } else if (3 < \count($this->aPaths) && $this->oHttp->IsGet()) { $this->oActions->SetActionParams(array( @@ -561,14 +551,14 @@ class ServiceActions (0 === $aData['Time'] || \time() - 10 < $aData['Time'])) { $sEmail = \trim($aData['Email']); - $sPassword = $aData['Password']; + $oPassword = new \SnappyMail\SensitiveString($aData['Password']); $aAdditionalOptions = (isset($aData['AdditionalOptions']) && \is_array($aData['AdditionalOptions'])) ? $aData['AdditionalOptions'] : []; try { - $oAccount = $this->oActions->LoginProcess($sEmail, $sPassword); + $oAccount = $this->oActions->LoginProcess($sEmail, $oPassword); if ($aAdditionalOptions) { $bNeedToSettings = false; diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/gpg/base.php b/snappymail/v/0.0.0/app/libraries/snappymail/gpg/base.php index 858270ed1..3436e2339 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/gpg/base.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/gpg/base.php @@ -284,10 +284,7 @@ abstract class Base /** * Add a key for decryption */ - public function addDecryptKey(string $fingerprint, - #[\SensitiveParameter] - string $passphrase - ) : bool + public function addDecryptKey(string $fingerprint, \SnappyMail\SensitiveString $passphrase) : bool { $this->decryptKeys[$fingerprint] = $passphrase; // $this->decryptKeys[\substr($fingerprint, -16)] = $passphrase; @@ -306,10 +303,7 @@ abstract class Base /** * Add a key for signing */ - public function addSignKey(string $fingerprint, - #[\SensitiveParameter] - string $passphrase - ) : bool + public function addSignKey(string $fingerprint, \SnappyMail\SensitiveString $passphrase) : bool { $this->signKeys[$fingerprint] = $passphrase; // $this->signKeys[\substr($fingerprint, -16)] = $passphrase; @@ -356,10 +350,7 @@ abstract class Base ]; } - public function addPassphrase($keyId, - #[\SensitiveParameter] - $passphrase - ) + public function addPassphrase($keyId, \SnappyMail\SensitiveString $passphrase) { $this->passphrases[$keyId] = $passphrase; return $this; diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/gpg/pgp.php b/snappymail/v/0.0.0/app/libraries/snappymail/gpg/pgp.php index af80bac23..eef6ab062 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/gpg/pgp.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/gpg/pgp.php @@ -95,7 +95,7 @@ class PGP extends Base $fclose = $this->setOutput($output); if ($this->decryptKeys) { - $_ENV['PINENTRY_USER_DATA'] = \json_encode($this->decryptKeys); + $_ENV['PINENTRY_USER_DATA'] = \json_encode(\array_map('strval', $this->decryptKeys)); } $result = $this->exec(['--decrypt','--skip-verify']); @@ -241,7 +241,7 @@ class PGP extends Base throw new \Exception(($private ? 'Private' : 'Public') . ' key not found: ' . $keyId); } if ($private && $this->passphrases) { - $_ENV['PINENTRY_USER_DATA'] = \json_encode($this->passphrases); + $_ENV['PINENTRY_USER_DATA'] = \json_encode(\array_map('strval', $this->passphrases)); } $result = $this->exec([ $private ? '--export-secret-keys' : '--export', @@ -362,7 +362,7 @@ class PGP extends Base $arguments = ['--import']; if ($this->passphrases) { - $_ENV['PINENTRY_USER_DATA'] = \json_encode($this->passphrases); + $_ENV['PINENTRY_USER_DATA'] = \json_encode(\array_map('strval', $this->passphrases)); } else { $arguments[] = '--batch'; } @@ -629,7 +629,7 @@ class PGP extends Base foreach ($this->signKeys as $fingerprint => $pass) { $arguments[] = '--local-user ' . \escapeshellarg($fingerprint); } - $_ENV['PINENTRY_USER_DATA'] = \json_encode($this->signKeys); + $_ENV['PINENTRY_USER_DATA'] = \json_encode(\array_map('strval', $this->signKeys)); } $result = $this->exec($arguments); diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/pgp/gnupg.php b/snappymail/v/0.0.0/app/libraries/snappymail/pgp/gnupg.php index c744d0ac5..799d15142 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/pgp/gnupg.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/pgp/gnupg.php @@ -86,10 +86,7 @@ class GnuPG /** * Add a key for decryption */ - public function addDecryptKey(string $fingerprint, - #[\SensitiveParameter] - string $passphrase - ) : bool + public function addDecryptKey(string $fingerprint, \SnappyMail\SensitiveString $passphrase) : bool { return $this->handler()->adddecryptkey($fingerprint, $passphrase); } @@ -105,10 +102,7 @@ class GnuPG /** * Add a key for signing */ - public function addSignKey(string $fingerprint, - #[\SensitiveParameter] - ?string $passphrase - ) : bool + public function addSignKey(string $fingerprint, \SnappyMail\SensitiveString $passphrase) : bool { return $this->handler()->addsignkey($fingerprint, $passphrase); } @@ -226,10 +220,7 @@ class GnuPG /** * Exports a key */ - public function export(string $fingerprint, - #[\SensitiveParameter] - string $passphrase = '' - ) /*: string|false*/ + public function export(string $fingerprint, ?\SnappyMail\SensitiveString $passphrase = null) /*: string|false*/ { if ($passphrase) { return $this->getGPG() @@ -276,10 +267,7 @@ class GnuPG /** * Generates a key */ - public function generateKey(string $uid, - #[\SensitiveParameter] - string $passphrase - ) /*: string|false*/ + public function generateKey(string $uid, \SnappyMail\SensitiveString $passphrase) /*: string|false*/ { $GPG = $this->getGPG(false); return $GPG ? $GPG->generateKey($uid, $passphrase) : false; diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/sensitivestring.php b/snappymail/v/0.0.0/app/libraries/snappymail/sensitivestring.php index 420725e4e..bac6afb17 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/sensitivestring.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/sensitivestring.php @@ -2,7 +2,7 @@ namespace SnappyMail; -class SensitiveString /* extends SensitiveParameterValue | SensitiveParameter */ implements \Stringable +class SensitiveString /* extends SensitiveParameterValue | SensitiveParameter */ implements \Stringable, \JsonSerializable { private string $value, $nonce; private static ?string $key = null; @@ -28,6 +28,7 @@ class SensitiveString /* extends SensitiveParameterValue | SensitiveParameter */ string $value ) : void { + \strlen($value) && \RainLoop\Api::Actions()->logMask($value); if (\is_callable('sodium_crypto_secretbox')) { $this->nonce = \random_bytes(\SODIUM_CRYPTO_SECRETBOX_NONCEBYTES); if (!static::$key) { @@ -60,6 +61,12 @@ class SensitiveString /* extends SensitiveParameterValue | SensitiveParameter */ return $this->getValue(); } + #[\ReturnTypeWillChange] + public function jsonSerialize() + { + throw new \Exception("JSON serialization of 'SnappyMail\\SensitiveString' is not allowed"); + } + public function __debugInfo(): array { return []; diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/smime/certificate.php b/snappymail/v/0.0.0/app/libraries/snappymail/smime/certificate.php index b897fbd85..2a12ba905 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/smime/certificate.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/smime/certificate.php @@ -112,11 +112,7 @@ class Certificate return \openssl_get_cipher_methods($aliases); } - public function createSelfSigned( - #[\SensitiveParameter] - string $passphrase = '', - ?string $privateKey = null - ) : array + public function createSelfSigned(\SnappyMail\SensitiveString $passphrase, ?string $privateKey = null) : array { $options = array( 'config' => __DIR__ . '/openssl.cnf', diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/smime/openssl.php b/snappymail/v/0.0.0/app/libraries/snappymail/smime/openssl.php index 9b8fbbbc3..235ba7cfb 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/smime/openssl.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/smime/openssl.php @@ -132,8 +132,7 @@ class OpenSSL } public function setPrivateKey(/*OpenSSLAsymmetricKey|string*/$privateKey, - #[\SensitiveParameter] - ?string $passphrase = null + ?\SnappyMail\SensitiveString $passphrase = null ) : void { $this->privateKey = \openssl_pkey_get_private($privateKey, $passphrase); From 28d8bec93587070c36ca22fa547a7f89721517de Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Tue, 27 Feb 2024 11:04:35 +0100 Subject: [PATCH 037/110] Fix view PGP key button --- dev/Stores/User/GnuPG.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dev/Stores/User/GnuPG.js b/dev/Stores/User/GnuPG.js index f4351cb61..a3bdfba56 100644 --- a/dev/Stores/User/GnuPG.js +++ b/dev/Stores/User/GnuPG.js @@ -72,7 +72,7 @@ export const GnuPGUserStore = new class { key.password = async (btnTxt = 'SIGN') => { const pass = await Passphrases.ask(key, 'GnuPG key
' + key.id + ' ' + key.emails[0], - 'CRYPTO/'+btnTxt + 'OPENPGP/'+btnTxt ); pass && pass.remember && Passphrases.set(key, pass.password); return pass?.password; @@ -83,7 +83,7 @@ export const GnuPGUserStore = new class { callback && callback(); } else { let pass = isPrivate ? await key.password('POPUP_VIEW_TITLE') : ''; - if (null != pass) { + if (null != pass) try { const result = await Remote.post('GnupgExportKey', null, { keyId: key.id, isPrivate: isPrivate, @@ -95,6 +95,8 @@ export const GnuPGUserStore = new class { } else { Passphrases.delete(key); } + } catch (e) { + Passphrases.delete(key); } } return key.armor; From 275ad40346653cacc97662b1241c9d7bbc684a9f Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Tue, 27 Feb 2024 11:25:34 +0100 Subject: [PATCH 038/110] Mask all POST data that has a key which contains `pass` --- .../app/libraries/RainLoop/ServiceActions.php | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php b/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php index f88ccc374..627c24a9b 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php @@ -112,15 +112,16 @@ class ServiceActions $this->oActions->logWrite('Action: '.$sMethodName, \LOG_INFO, 'JSON'); - $aPost = $_POST ?? null; - if ($aPost) { - $this->oActions->SetActionParams($aPost, $sMethodName); - foreach ($aPost as $key => $value) { - if (false !== \stripos($key, 'Password')) { - $aPost[$key] = '*******'; + if ($_POST) { + $this->oActions->SetActionParams($_POST, $sMethodName); + foreach ($_POST as $key => $value) { + // password & passphrase + if (false !== \stripos($key, 'pass')) { +// $_POST[$key] = '*******'; + $this->oActions->logMask($value); } } - $this->oActions->logWrite(Utils::jsonEncode($aPost), \LOG_INFO, 'POST'); + $this->oActions->logWrite(Utils::jsonEncode($_POST), \LOG_INFO, 'POST'); } else if (3 < \count($this->aPaths) && $this->oHttp->IsGet()) { $this->oActions->SetActionParams(array( 'RawKey' => empty($this->aPaths[3]) ? '' : $this->aPaths[3] From b0211424a7322f43998c208ddf876d0d08377ad5 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Tue, 27 Feb 2024 12:05:30 +0100 Subject: [PATCH 039/110] v2.35.1 --- CHANGELOG.md | 29 +++++++++++++++++++ integrations/cloudron/DESCRIPTION.md | 2 +- integrations/cloudron/Dockerfile | 2 +- .../nextcloud/snappymail/appinfo/info.xml | 2 +- integrations/virtualmin/snappymail.pl | 2 +- package.json | 2 +- plugins/nextcloud/index.php | 7 ++++- .../libraries/snappymail/http/response.php | 4 +++ 8 files changed, 44 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 691acb47d..7bddafb59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,32 @@ +## 2.35.1 – 2024-02-26 + +### Added +- Search functionality in Admin -> Config +- Cache S/MIME passphrases when "remember" is checked +- Import S/MIME certificate popup +- pre-verify S/MIME opaque signed messages so we have a body to view +- Sort PGP keys and S/MIME certificates on email address +- Optionally use existing private key to generate S/MIME certificate + +### Changed +- Better handling to detect which PGP or S/MIME sign/encrypt to use +- Improved StorageType handling +- Cleanup and improved Capa handling +- OPEN_PGP should be OPENPGP as it is one word +- Use get_debug_type() instead of gettype() +- Require OpenSSL due to S/MIME +- AbstractProvider::IsActive() is now an abstract method and must be defined in child class +- Make better use of SnappyMail\SensitiveString +- Update Polish translation by @tinola + +### Fixed +- Verify S/MIME signatures got broken allong the way while implementing this +- Generate S/MIME self-signed certificate failed to keep existing private key +- MIME parser RegExp didn't escape boundary which caused issues +- TypeError: b64Encode(...).match(...) is null on saving compose draft +- Fix timestampToString() for future dates + + ## 2.35.0 – 2024-02-20 ### Added diff --git a/integrations/cloudron/DESCRIPTION.md b/integrations/cloudron/DESCRIPTION.md index dd880b220..587cb3c7c 100644 --- a/integrations/cloudron/DESCRIPTION.md +++ b/integrations/cloudron/DESCRIPTION.md @@ -1,4 +1,4 @@ -This app packages SnappyMail 2.35.0. +This app packages SnappyMail 2.35.1. SnappyMail is a simple, modern, lightweight & fast web-based email client. diff --git a/integrations/cloudron/Dockerfile b/integrations/cloudron/Dockerfile index fa0c1dfba..cd1b147c6 100644 --- a/integrations/cloudron/Dockerfile +++ b/integrations/cloudron/Dockerfile @@ -4,7 +4,7 @@ RUN mkdir -p /app/code WORKDIR /app/code # If you change the extraction below, be sure to test on scaleway -VERSION=2.35.0 +VERSION=2.35.1 RUN wget https://github.com/the-djmaze/snappymail/releases/download/v${VERSION}/snappymail-${VERSION}.zip -O /tmp/snappymail.zip && \ unzip /tmp/snappymail.zip -d /app/code && \ rm /tmp/snappymail.zip && \ diff --git a/integrations/nextcloud/snappymail/appinfo/info.xml b/integrations/nextcloud/snappymail/appinfo/info.xml index d0cd260d7..8264e0bff 100644 --- a/integrations/nextcloud/snappymail/appinfo/info.xml +++ b/integrations/nextcloud/snappymail/appinfo/info.xml @@ -3,7 +3,7 @@ snappymail SnappyMail SnappyMail Webmail - 2.35.0 + 2.35.1 agpl SnappyMail, RainLoop Team, Nextgen-Networks, Tab Fitts, Nathan Kinkade, Pierre-Alain Bandinelli Config()->Get('plugin', 'storage', false) && ('storage' === $sName || 'storage-local' === $sName)) { require_once __DIR__ . '/storage.php'; $oDriver = new \NextcloudStorage(APP_PRIVATE_DATA.'storage', $sName === 'storage-local'); } @@ -346,6 +346,11 @@ class NextcloudPlugin extends \RainLoop\Plugins\AbstractPlugin \RainLoop\Plugins\Property::NewInstance('ignoreSystemAddressbook')->SetLabel('Ignore system addressbook') ->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL) ->SetDefaultValue(true), +/* + \RainLoop\Plugins\Property::NewInstance('storage')->SetLabel('Use Nextcloud user ID in config storage path') + ->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL) + ->SetDefaultValue(false) +*/ \RainLoop\Plugins\Property::NewInstance('calendar')->SetLabel('Enable "Put ICS in calendar"') ->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL) ->SetDefaultValue(false) diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/http/response.php b/snappymail/v/0.0.0/app/libraries/snappymail/http/response.php index 3593aa41d..126af9564 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/http/response.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/http/response.php @@ -42,6 +42,10 @@ class Response if (\function_exists('gzinflate') && isset($this->headers['content-encoding']) && (false !== \stripos($this->headers['content-encoding'], 'gzip'))) { $this->body = \gzinflate(\substr($body, 10, -4)); + if (false === $this->body) { + $err = \error_get_last() ?: ['message' => 'gzinflate failed']; + throw new \RuntimeException("{$err['message']} for {$request_uri}"); + } } else { $this->body = $body; } From c73e3637a34de675c095cc95b882d668fbb73974 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Tue, 27 Feb 2024 15:12:42 +0100 Subject: [PATCH 040/110] Resolve #1455 --- .../v/0.0.0/app/libraries/MailSo/Sieve/SieveClient.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Sieve/SieveClient.php b/snappymail/v/0.0.0/app/libraries/MailSo/Sieve/SieveClient.php index 65dced595..669273225 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Sieve/SieveClient.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Sieve/SieveClient.php @@ -184,7 +184,12 @@ class SieveClient extends \MailSo\Net\NetClient public function Logout() : void { if ($this->bIsLoggined) { - $this->sendRequestWithCheck('LOGOUT'); + try { + $this->sendRequestWithCheck('LOGOUT'); + } catch (\Throwable $e) { + // https://github.com/the-djmaze/snappymail/issues/1455 + $this->writeLogException($e, \LOG_WARNING, false); + } $this->bIsLoggined = false; } } @@ -408,6 +413,7 @@ class SieveClient extends \MailSo\Net\NetClient if (null === $sResponseBuffer) { break; } + // \MailSo\Imap\Enumerations\ResponseStatus $bEnd = \in_array(\substr($sResponseBuffer, 0, 2), array('OK', 'NO')); // convertEndOfLine $sLine = \trim($sResponseBuffer); From 3d176d4e4fd8d47ae6a606c1d3639e91c01d3964 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Tue, 27 Feb 2024 18:45:25 +0100 Subject: [PATCH 041/110] Improved GnuPG error handling --- dev/Stores/User/GnuPG.js | 23 +++-- dev/View/User/MailBox/MessageView.js | 7 +- .../app/libraries/RainLoop/Actions/Pgp.php | 10 +- .../libraries/RainLoop/Actions/Response.php | 11 ++- .../app/libraries/RainLoop/ServiceActions.php | 9 +- .../app/libraries/snappymail/gpg/base.php | 2 +- .../app/libraries/snappymail/gpg/pgp.php | 4 +- .../app/libraries/snappymail/gpg/smime.php | 4 +- .../app/libraries/snappymail/pgp/gnupg.php | 96 +++++++++++++------ 9 files changed, 110 insertions(+), 56 deletions(-) diff --git a/dev/Stores/User/GnuPG.js b/dev/Stores/User/GnuPG.js index a3bdfba56..e390162d5 100644 --- a/dev/Stores/User/GnuPG.js +++ b/dev/Stores/User/GnuPG.js @@ -69,10 +69,10 @@ export const GnuPGUserStore = new class { } }; if (isPrivate) { - key.password = async (btnTxt = 'SIGN') => { + key.password = async (btnTxt = 'CRYPTO/SIGN') => { const pass = await Passphrases.ask(key, 'GnuPG key
' + key.id + ' ' + key.emails[0], - 'OPENPGP/'+btnTxt + btnTxt ); pass && pass.remember && Passphrases.set(key, pass.password); return pass?.password; @@ -82,7 +82,7 @@ export const GnuPGUserStore = new class { if (key.armor) { callback && callback(); } else { - let pass = isPrivate ? await key.password('POPUP_VIEW_TITLE') : ''; + let pass = isPrivate ? await key.password('OPENPGP/POPUP_VIEW_TITLE') : ''; if (null != pass) try { const result = await Remote.post('GnupgExportKey', null, { keyId: key.id, @@ -184,15 +184,20 @@ export const GnuPGUserStore = new class { uid: message.uid, partId: pgpInfo.partId, keyId: key.id, - passphrase: await key.password('DECRYPT'), + passphrase: await key.password('CRYPTO/DECRYPT'), data: '' // message.plain() optional } - if (null !== params.passphrase) { - const result = await Remote.post('GnupgDecrypt', null, params); - if (result?.Result?.data) { - return result.Result; + if (null != params.passphrase) { + try { + const response = await Remote.post('GnupgDecrypt', null, params); + if (response?.Result?.data) { + return response.Result; + } + throw response; + } catch (e) { + Passphrases.delete(key); + throw e; } - Passphrases.delete(key); } } } diff --git a/dev/View/User/MailBox/MessageView.js b/dev/View/User/MailBox/MessageView.js index 551915799..70c113131 100644 --- a/dev/View/User/MailBox/MessageView.js +++ b/dev/View/User/MailBox/MessageView.js @@ -587,10 +587,13 @@ export class MailMessageView extends AbstractViewRight { } } else { // TODO: translate - alert('Decryption failed, canceled or not possible'); + throw 'Decryption failed, canceled or not possible'; } }) - .catch(e => console.error(e)); + .catch(e => { + console.error(e) + alert(e.message); + }); } pgpVerify(/*self, event*/) { diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Pgp.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Pgp.php index ac427165f..59e10e655 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Pgp.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Pgp.php @@ -120,7 +120,7 @@ trait Pgp $sData = $this->GetActionParam('data', ''); $oPart = null; $result = [ - 'data' => '', + 'data' => null, 'signatures' => [] ]; if ($sData) { @@ -130,11 +130,13 @@ trait Pgp $this->initMailClientConnection(); $this->MailClient()->MessageMimeStream( function ($rResource) use ($GPG, &$result, &$oPart) { - if (\is_resource($rResource)) { + if (\is_resource($rResource)) try { $result['data'] = $GPG->decryptStream($rResource); // $oPart = \MailSo\Mime\Part::FromString($result); // $GPG->decryptStream($rResource, $rStreamHandle); // $oPart = \MailSo\Mime\Part::FromStream($rStreamHandle); + } catch (\Throwable $e) { + $result = $e; } }, $this->GetActionParam('folder', ''), @@ -148,6 +150,10 @@ trait Pgp // $result['signatures'] = $oPart->SubParts[0]; } + if ($result instanceof \Throwable) { + throw $result; + } + return $this->DefaultResponse($result); } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Response.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Response.php index 446d3fcc4..a61ba47fc 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Response.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Response.php @@ -45,9 +45,10 @@ trait Response public function ExceptionResponse(\Throwable $oException) : array { - $iErrorCode = 0; - $sErrorMessage = ''; + $iErrorCode = Notifications::UnknownError; + $sErrorMessage = $oException->getMessage(); $sErrorMessageAdditional = ''; + $iExceptionCode = 0; if ($oException instanceof \RainLoop\Exceptions\ClientException) { $iErrorCode = $oException->getCode(); @@ -56,8 +57,7 @@ trait Response } $sErrorMessageAdditional = $oException->getAdditionalMessage(); } else { - $iErrorCode = Notifications::UnknownError; - $sErrorMessage = $oException->getCode().' - '.$oException->getMessage(); + $iExceptionCode = $oException->getCode(); } $this->logException($oException->getPrevious() ?: $oException); @@ -65,7 +65,8 @@ trait Response return $this->DefaultResponse(false, [ 'ErrorCode' => $iErrorCode, 'ErrorMessage' => $sErrorMessage, - 'ErrorMessageAdditional' => $sErrorMessageAdditional + 'ErrorMessageAdditional' => $sErrorMessageAdditional, + 'ExceptionCode' => $iExceptionCode ]); } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php b/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php index 627c24a9b..5e7092b26 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php @@ -114,14 +114,15 @@ class ServiceActions if ($_POST) { $this->oActions->SetActionParams($_POST, $sMethodName); - foreach ($_POST as $key => $value) { + $aPost = $_POST; + foreach ($aPost as $key => $value) { // password & passphrase if (false !== \stripos($key, 'pass')) { -// $_POST[$key] = '*******'; - $this->oActions->logMask($value); + $aPost[$key] = '*******'; +// $this->oActions->logMask($value); } } - $this->oActions->logWrite(Utils::jsonEncode($_POST), \LOG_INFO, 'POST'); + $this->oActions->logWrite(Utils::jsonEncode($aPost), \LOG_INFO, 'POST'); } else if (3 < \count($this->aPaths) && $this->oHttp->IsGet()) { $this->oActions->SetActionParams(array( 'RawKey' => empty($this->aPaths[3]) ? '' : $this->aPaths[3] diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/gpg/base.php b/snappymail/v/0.0.0/app/libraries/snappymail/gpg/base.php index 3436e2339..168f8f63f 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/gpg/base.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/gpg/base.php @@ -243,7 +243,7 @@ abstract class Base /** * Signs a given file */ - public function signStream($fp, /*string|resource*/ $output = null) /*: array|false*/ + public function signStream($fp, /*string|resource*/ $output = null) /*: string|false*/ { return false; } diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/gpg/pgp.php b/snappymail/v/0.0.0/app/libraries/snappymail/gpg/pgp.php index eef6ab062..40b08252a 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/gpg/pgp.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/gpg/pgp.php @@ -666,7 +666,7 @@ class PGP extends Base /** * Signs a given file */ - public function signStream($fp, /*string|resource*/ $output = null) /*: array|false*/ + public function signStream($fp, /*string|resource*/ $output = null) /*: string|false*/ { if (!$fp || !\is_resource($fp)) { throw new \Exception('Invalid stream resource'); @@ -674,7 +674,7 @@ class PGP extends Base return $this->_sign($fp, $output); } - protected function _verify($input, string $signature) + protected function _verify($input, string $signature) /*: array|false*/ { $arguments = ['--verify']; if ($signature) { diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/gpg/smime.php b/snappymail/v/0.0.0/app/libraries/snappymail/gpg/smime.php index b958e2d6b..8adff5a7a 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/gpg/smime.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/gpg/smime.php @@ -540,7 +540,7 @@ class SMIME extends Base /** * Signs a given file */ - public function signStream($fp, /*string|resource*/ $output = null) /*: array|false*/ + public function signStream($fp, /*string|resource*/ $output = null) /*: string|false*/ { if (!$fp || !\is_resource($fp)) { throw new \Exception('Invalid stream resource'); @@ -548,7 +548,7 @@ class SMIME extends Base return $this->_sign($fp, $output); } - protected function _verify($input, string $signature) + protected function _verify($input, string $signature) /*: array|false*/ { $arguments = ['--verify']; if ($signature) { diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/pgp/gnupg.php b/snappymail/v/0.0.0/app/libraries/snappymail/pgp/gnupg.php index 799d15142..88215493e 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/pgp/gnupg.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/pgp/gnupg.php @@ -36,6 +36,7 @@ class GnuPG ]); // Output is ASCII $this->GnuPG->setarmor(1); + \SnappyMail\Log::info('GnuPG', 'Using PECL'); } else { $this->getGPG(); } @@ -52,6 +53,12 @@ class GnuPG */ } + function __destruct() + { + $this->clearDecryptKeys(); + $this->clearSignKeys(); + } + public static function isSupported() : bool { return \class_exists('gnupg') || GPG::isSupported(); @@ -71,11 +78,20 @@ class GnuPG return $this->GnuPG ?: $this->GPG; } + public function gnupgError() + { + $error = $this->GnuPG ? $this->GnuPG->geterrorinfo() : null; + if ($error) { + throw new \Exception("{$error['gpgme_source']} {$error['generic_message']}. {$error['gpgme_message']}", $error['gpgme_code']); + } + } + public function getGPG(bool $throw = true) : ?GPG { if (!$this->GPG) { if (GPG::isSupported()) { $this->GPG = new GPG($this->homedir); + \SnappyMail\Log::info('GnuPG', 'Using ' . GPG::class); } else if ($throw) { throw new \Exception('GnuPG not supported'); } @@ -88,7 +104,9 @@ class GnuPG */ public function addDecryptKey(string $fingerprint, \SnappyMail\SensitiveString $passphrase) : bool { - return $this->handler()->adddecryptkey($fingerprint, $passphrase); + return $this->GnuPG + ? $this->GnuPG->adddecryptkey($fingerprint, \strval($passphrase)) || $this->gnupgError() + : $this->GPG->addDecryptKey($fingerprint, $passphrase); } /** @@ -104,7 +122,9 @@ class GnuPG */ public function addSignKey(string $fingerprint, \SnappyMail\SensitiveString $passphrase) : bool { - return $this->handler()->addsignkey($fingerprint, $passphrase); + return $this->GnuPG + ? $this->GnuPG->addsignkey($fingerprint, \strval($passphrase)) || $this->gnupgError() + : $this->GPG->addSignKey($fingerprint, $passphrase); } /** @@ -136,9 +156,12 @@ class GnuPG */ public function decrypt(string $text) /*: string|false */ { - return $this->GnuPG - ? $this->GnuPG->decrypt($text) - : $this->GPG->decrypt($text); + if ($this->GnuPG) { + $result = $this->GnuPG->decrypt($text); + (false === $result) && $this->gnupgError(); + return $result; + } + return $this->GPG->decrypt($text); } /** @@ -146,9 +169,12 @@ class GnuPG */ public function decryptFile(string $filename) /*: string|false */ { - return $this->GnuPG - ? $this->GnuPG->decrypt(\file_get_contents($filename)) - : $this->GPG->decryptFile($filename); + if ($this->GnuPG) { + $result = $this->GnuPG->decrypt(\file_get_contents($filename)); + (false === $result) && $this->gnupgError(); + return $result; + } + return $this->GPG->decryptFile($filename); } /** @@ -159,9 +185,12 @@ class GnuPG if (!$fp || !\is_resource($fp)) { throw new \Exception('Invalid stream resource'); } - return $this->GnuPG - ? $this->GnuPG->decrypt(\stream_get_contents($fp)) - : $this->GPG->decryptStream($fp, $output); + if ($this->GnuPG) { + $result = $this->GnuPG->decrypt(\stream_get_contents($fp)); + (false === $result) && $this->gnupgError(); + return $result; + } + return $this->GPG->decryptStream($fp, $output); } /** @@ -169,9 +198,12 @@ class GnuPG */ public function decryptVerify(string $text, string &$plaintext) /*: array|false*/ { - return $this->GnuPG - ? $this->GnuPG->decryptverify($text, $plaintext) - : $this->GPG->decryptverify($text, $plaintext); + if ($this->GnuPG) { + $result = $this->GnuPG->decryptverify($text, $plaintext); + (false === $result) && $this->gnupgError(); + return $result; + } + return $this->GPG->decryptverify($text, $plaintext); } /** @@ -179,9 +211,12 @@ class GnuPG */ public function decryptVerifyFile(string $filename, string &$plaintext) /*: array|false*/ { - return $this->GnuPG - ? $this->GnuPG->decryptverify(\file_get_contents($filename), $plaintext) - : $this->GPG->decryptverifyFile($filename, $plaintext); + if ($this->GnuPG) { + $result = $this->GnuPG->decryptverify(\file_get_contents($filename), $plaintext); + (false === $result) && $this->gnupgError(); + return $result; + } + return $this->GPG->decryptverifyFile($filename, $plaintext); } public function deleteKey(string $keyId, bool $private) : bool @@ -195,7 +230,7 @@ class GnuPG public function encrypt(string $plaintext) /*: string|false*/ { return $this->GnuPG - ? $this->GnuPG->encrypt($plaintext) + ? $this->GnuPG->encrypt($plaintext) ?: $this->gnupgError() : $this->GPG->encrypt($plaintext); } @@ -205,7 +240,7 @@ class GnuPG public function encryptFile(string $filename) /*: string|false*/ { return $this->GnuPG - ? $this->GnuPG->encrypt(\file_get_contents($filename)) + ? $this->GnuPG->encrypt(\file_get_contents($filename)) ?: $this->gnupgError() : $this->GPG->encryptFile($filename); } @@ -213,7 +248,7 @@ class GnuPG { \rewind($fp); return $this->GnuPG - ? $this->GnuPG->encrypt(\stream_get_contents($fp)) + ? $this->GnuPG->encrypt(\stream_get_contents($fp)) ?: $this->gnupgError() : $this->GPG->encryptStream($fp); } @@ -228,7 +263,7 @@ class GnuPG ->exportPrivateKey($fingerprint); } return $this->GnuPG - ? $this->GnuPG->export($fingerprint) + ? $this->GnuPG->export($fingerprint) ?: $this->gnupgError() : $this->GPG->export($fingerprint); } @@ -287,7 +322,7 @@ class GnuPG public function importFile(string $filename) /*: array|false*/ { return $this->GnuPG - ? $this->GnuPG->import(\file_get_contents($filename)) + ? $this->GnuPG->import(\file_get_contents($filename)) ?: $this->gnupgError() : $this->GPG->importFile($filename); } @@ -350,7 +385,7 @@ class GnuPG public function sign(string $plaintext) /*: string|false*/ { return $this->GnuPG - ? $this->GnuPG->sign($plaintext) + ? $this->GnuPG->sign($plaintext) ?: $this->gnupgError() : $this->GPG->sign($plaintext); } @@ -360,18 +395,18 @@ class GnuPG public function signFile(string $filename) /*: string|false*/ { return $this->GnuPG - ? $this->GnuPG->sign(\file_get_contents($filename)) + ? $this->GnuPG->sign(\file_get_contents($filename)) ?: $this->gnupgError() : $this->GPG->signFile($filename); } /** * Signs a given file */ - public function signStream($fp, /*string|resource*/ $output = null) /*: array|false*/ + public function signStream($fp, /*string|resource*/ $output = null) /*: string|false*/ { \rewind($fp); return $this->GnuPG - ? $this->GnuPG->sign(\stream_get_contents($fp)) + ? $this->GnuPG->sign(\stream_get_contents($fp)) ?: $this->gnupgError() : $this->GPG->signStream($fp); } @@ -381,7 +416,7 @@ class GnuPG public function verify(string $signed_text, string $signature, string &$plaintext = null) /*: array|false*/ { $result = $this->GnuPG - ? $this->GnuPG->verify($signed_text, $signature ?: false, $plaintext) + ? $this->GnuPG->verify($signed_text, $signature ?: false, $plaintext) ?: $this->gnupgError() : $this->GPG->verify($signed_text, $signature, $plaintext); if (!$result) { if ($this->GnuPG) { @@ -400,18 +435,21 @@ class GnuPG public function verifyFile(string $filename, string $signature, string &$plaintext = null) /*: array|false*/ { return $this->GnuPG - ? $this->GnuPG->verify(\file_get_contents($filename), $signature, $plaintext) + ? $this->GnuPG->verify(\file_get_contents($filename), $signature, $plaintext) ?: $this->gnupgError() : $this->GPG->verifyFile($filename, $signature, $plaintext); } /** * Verifies a given resource */ - public function verifyStream(/*resource*/ $fp, string $signature, string &$plaintext = null) /*: string|false */ + public function verifyStream(/*resource*/ $fp, string $signature, string &$plaintext = null) /*: array|false */ { if (!$fp || !\is_resource($fp)) { throw new \Exception('Invalid stream resource'); } +// return $this->GnuPG +// ? $this->GnuPG->verify(\stream_get_contents($fp), $signature, $plaintext) ?: $this->gnupgError() +// : $this->GPG->verifyStream($fp, $signature, $plaintext); return $this->getGPG()->verifyStream($fp, $signature, $plaintext); } From 150d95c157588ffd1843c45fd0d672976ded7a22 Mon Sep 17 00:00:00 2001 From: lmperfis Date: Tue, 27 Feb 2024 18:00:43 +0000 Subject: [PATCH 042/110] Update pt/pt-PT translation --- .../v/0.0.0/app/localization/pt-PT/user.json | 28 +++++++++---------- .../v/0.0.0/app/localization/pt/user.json | 28 +++++++++---------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/snappymail/v/0.0.0/app/localization/pt-PT/user.json b/snappymail/v/0.0.0/app/localization/pt-PT/user.json index 11b2854d2..64d57df1b 100644 --- a/snappymail/v/0.0.0/app/localization/pt-PT/user.json +++ b/snappymail/v/0.0.0/app/localization/pt-PT/user.json @@ -154,8 +154,8 @@ "HAS_VIRUS_WARNING": "AVISO: vírus detetado", "TAGS": "Etiquetas", "NEW_TAG": "Nova etiqueta", - "ENABLE_TRACKING_LINKS": "Enable tracking links", - "TRACKING_ENABLED": "Links are now tracked when clicked!" + "ENABLE_TRACKING_LINKS": "Ativar ligações de rastreamento", + "TRACKING_ENABLED": "As ligações irão ser rastreadas quando clicadas!" }, "MESSAGE_TAGS": { "$important": "Importante", @@ -255,7 +255,7 @@ "POPUPS_IDENTITY": { "TITLE_ADD_IDENTITY": "Adicionar identidade?", "TITLE_UPDATE_IDENTITY": "Atualizar identidade?", - "LABEL": "Label", + "LABEL": "Rótulo", "BUTTON_ADD_IDENTITY": "Adicionar", "BUTTON_UPDATE_IDENTITY": "Atualizar", "SIGNATURE": "Assinatura", @@ -281,8 +281,8 @@ "VERIFY": "Validar", "GOOD_SIGNATURE": "Boa assinatura de %USER%", "ERROR": "Erro %TYPE%: %ERROR%", - "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "CREATE_SELF_SIGNED": "Criar auto-assinado", + "VALID_UNTIL": "Válido até" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "Importar chave OpenPGP", @@ -295,18 +295,18 @@ "SIGNED_MESSAGE": "Mensagem assinada com OpenPGP", "ENCRYPTED_MESSAGE": "Mensagem encriptada com OpenPGP", "STORE_IN_GNUPG": "Guardar no servidor em GnuPG", - "STORE_PUBLIC_KEY_IN_GNUPG": "Store public key on server in GnuPG", - "STORE_PRIVATE_KEY_IN_GNUPG": "Store private key on server in GnuPG", + "STORE_PUBLIC_KEY_IN_GNUPG": "Guardar a chave pública no servidor em GnuPG", + "STORE_PRIVATE_KEY_IN_GNUPG": "Guardar a chave privada no servidor em GnuPG", "BACKUP_ON_SERVER": "Guardar (encriptado) no servidor", - "BACKUP_PUBLIC_KEY_ON_SERVER": "Backup public key on server", - "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" + "BACKUP_PUBLIC_KEY_ON_SERVER": "Fazer cópia de segurança da chave pública no servidor", + "BACKUP_PRIVATE_KEY_ON_SERVER": "Fazer cópia de segurança da chave privada no servidor" }, "SMIME": { - "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", - "CERTIFICATES": "S\/MIME Certificates", + "POPUP_IMPORT_TITLE": "Importar certificado S\/MIME", + "CERTIFICATES": "Certificados S\/MIME", "SIGNED_MESSAGE": "Mensagem assinada com S\/MIME", "ENCRYPTED_MESSAGE": "Mensagem encriptada com S\/MIME", - "PRIVATE_KEY_OF": "S\/MIME private key of %EMAIL%" + "PRIVATE_KEY_OF": "Chave privada S\/MIME de %EMAIL%" }, "POPUPS_FILTER": { "TITLE_CREATE_FILTER": "Criar um filtro?", @@ -405,7 +405,7 @@ "IMAGEUPLOAD": "Escolher imagem", "UNDO": "Desfazer", "REDO": "Refazer", - "REMOVESTYLE": "Remove style" + "REMOVESTYLE": "Remover estilo" }, "SETTINGS_LABELS": { "GENERAL": "Geral", @@ -530,7 +530,7 @@ "SETTINGS_OPENPGP": { "BUTTON_IMPORT_KEY": "Importar chave", "BUTTON_GENERATE_KEY_PAIR": "Gerar chaves", - "IMPORT_FROM_SERVER": "Import from server", + "IMPORT_FROM_SERVER": "Importar de servidor", "TITLE_PRIVATE": "Privada", "TITLE_PUBLIC": "Pública", "GET_MAILVELOPE": "Obter extensão Mailvelope para o navegador." diff --git a/snappymail/v/0.0.0/app/localization/pt/user.json b/snappymail/v/0.0.0/app/localization/pt/user.json index 11b2854d2..64d57df1b 100644 --- a/snappymail/v/0.0.0/app/localization/pt/user.json +++ b/snappymail/v/0.0.0/app/localization/pt/user.json @@ -154,8 +154,8 @@ "HAS_VIRUS_WARNING": "AVISO: vírus detetado", "TAGS": "Etiquetas", "NEW_TAG": "Nova etiqueta", - "ENABLE_TRACKING_LINKS": "Enable tracking links", - "TRACKING_ENABLED": "Links are now tracked when clicked!" + "ENABLE_TRACKING_LINKS": "Ativar ligações de rastreamento", + "TRACKING_ENABLED": "As ligações irão ser rastreadas quando clicadas!" }, "MESSAGE_TAGS": { "$important": "Importante", @@ -255,7 +255,7 @@ "POPUPS_IDENTITY": { "TITLE_ADD_IDENTITY": "Adicionar identidade?", "TITLE_UPDATE_IDENTITY": "Atualizar identidade?", - "LABEL": "Label", + "LABEL": "Rótulo", "BUTTON_ADD_IDENTITY": "Adicionar", "BUTTON_UPDATE_IDENTITY": "Atualizar", "SIGNATURE": "Assinatura", @@ -281,8 +281,8 @@ "VERIFY": "Validar", "GOOD_SIGNATURE": "Boa assinatura de %USER%", "ERROR": "Erro %TYPE%: %ERROR%", - "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "CREATE_SELF_SIGNED": "Criar auto-assinado", + "VALID_UNTIL": "Válido até" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "Importar chave OpenPGP", @@ -295,18 +295,18 @@ "SIGNED_MESSAGE": "Mensagem assinada com OpenPGP", "ENCRYPTED_MESSAGE": "Mensagem encriptada com OpenPGP", "STORE_IN_GNUPG": "Guardar no servidor em GnuPG", - "STORE_PUBLIC_KEY_IN_GNUPG": "Store public key on server in GnuPG", - "STORE_PRIVATE_KEY_IN_GNUPG": "Store private key on server in GnuPG", + "STORE_PUBLIC_KEY_IN_GNUPG": "Guardar a chave pública no servidor em GnuPG", + "STORE_PRIVATE_KEY_IN_GNUPG": "Guardar a chave privada no servidor em GnuPG", "BACKUP_ON_SERVER": "Guardar (encriptado) no servidor", - "BACKUP_PUBLIC_KEY_ON_SERVER": "Backup public key on server", - "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" + "BACKUP_PUBLIC_KEY_ON_SERVER": "Fazer cópia de segurança da chave pública no servidor", + "BACKUP_PRIVATE_KEY_ON_SERVER": "Fazer cópia de segurança da chave privada no servidor" }, "SMIME": { - "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", - "CERTIFICATES": "S\/MIME Certificates", + "POPUP_IMPORT_TITLE": "Importar certificado S\/MIME", + "CERTIFICATES": "Certificados S\/MIME", "SIGNED_MESSAGE": "Mensagem assinada com S\/MIME", "ENCRYPTED_MESSAGE": "Mensagem encriptada com S\/MIME", - "PRIVATE_KEY_OF": "S\/MIME private key of %EMAIL%" + "PRIVATE_KEY_OF": "Chave privada S\/MIME de %EMAIL%" }, "POPUPS_FILTER": { "TITLE_CREATE_FILTER": "Criar um filtro?", @@ -405,7 +405,7 @@ "IMAGEUPLOAD": "Escolher imagem", "UNDO": "Desfazer", "REDO": "Refazer", - "REMOVESTYLE": "Remove style" + "REMOVESTYLE": "Remover estilo" }, "SETTINGS_LABELS": { "GENERAL": "Geral", @@ -530,7 +530,7 @@ "SETTINGS_OPENPGP": { "BUTTON_IMPORT_KEY": "Importar chave", "BUTTON_GENERATE_KEY_PAIR": "Gerar chaves", - "IMPORT_FROM_SERVER": "Import from server", + "IMPORT_FROM_SERVER": "Importar de servidor", "TITLE_PRIVATE": "Privada", "TITLE_PUBLIC": "Pública", "GET_MAILVELOPE": "Obter extensão Mailvelope para o navegador." From 6bb77d6d7c13c249c7cdbd4bf92b7600b3ae8e03 Mon Sep 17 00:00:00 2001 From: tinola Date: Tue, 27 Feb 2024 21:19:50 +0100 Subject: [PATCH 043/110] update Polish translation --- snappymail/v/0.0.0/app/localization/pl-PL/user.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/snappymail/v/0.0.0/app/localization/pl-PL/user.json b/snappymail/v/0.0.0/app/localization/pl-PL/user.json index 1f1930b27..35adcdc4a 100644 --- a/snappymail/v/0.0.0/app/localization/pl-PL/user.json +++ b/snappymail/v/0.0.0/app/localization/pl-PL/user.json @@ -154,8 +154,8 @@ "HAS_VIRUS_WARNING": "Uwaga: wykryto wirusa!", "TAGS": "Tagi", "NEW_TAG": "Nowy tag", - "ENABLE_TRACKING_LINKS": "Enable tracking links", - "TRACKING_ENABLED": "Links are now tracked when clicked!" + "ENABLE_TRACKING_LINKS": "Włącz linki śledzące", + "TRACKING_ENABLED": "Linki są teraz śledzone!" }, "MESSAGE_TAGS": { "$important": "Ważne", From 68ed7cafae79f30b73de51d3b36544cfe5e35e4e Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Tue, 27 Feb 2024 22:29:36 +0100 Subject: [PATCH 044/110] Drop support for gnupg pecl extension as it fails with "no passphrase" issues --- .../app/libraries/RainLoop/Actions/Pgp.php | 10 +- .../app/libraries/snappymail/gpg/base.php | 37 +- .../app/libraries/snappymail/gpg/pgp.php | 69 ++- .../app/libraries/snappymail/gpg/smime.php | 27 +- .../app/libraries/snappymail/pgp/gnupg.php | 445 +----------------- .../app/libraries/snappymail/pgp/pecl.php | 397 ++++++++++++++++ .../libraries/snappymail/pgp/pgpinterface.php | 43 ++ 7 files changed, 536 insertions(+), 492 deletions(-) create mode 100644 snappymail/v/0.0.0/app/libraries/snappymail/pgp/pecl.php create mode 100644 snappymail/v/0.0.0/app/libraries/snappymail/pgp/pgpinterface.php diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Pgp.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Pgp.php index 59e10e655..57aba42ea 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Pgp.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Pgp.php @@ -24,7 +24,7 @@ trait Pgp $GPG = $this->GnuPG(); if ($GPG) { - $keys = $GPG->keyInfo(''); + $keys = $GPG->allKeysInfo(''); foreach ($keys['public'] as $key) { $key = $GPG->export($key['subkeys'][0]['fingerprint'] ?: $key['subkeys'][0]['keyid']); if ($key) { @@ -47,7 +47,7 @@ trait Pgp /** * @throws \MailSo\RuntimeException */ - public function GnuPG() : ?GnuPG + public function GnuPG() : ?\SnappyMail\PGP\PGPInterface { $oAccount = $this->getMainAccountFromToken(); if (!$oAccount) { @@ -97,10 +97,6 @@ trait Pgp $homedir = $tmpdir; } } - - if (104 <= \strlen($homedir . '/S.gpg-agent.extra')) { - throw new \Exception("socket name for '{$homedir}/S.gpg-agent.extra' is too long"); - } } return GnuPG::getInstance($homedir); @@ -160,7 +156,7 @@ trait Pgp public function DoGnupgGetKeys() : array { $GPG = $this->GnuPG(); - return $this->DefaultResponse($GPG ? $GPG->keyInfo('') : false); + return $this->DefaultResponse($GPG ? $GPG->allKeysInfo('') : false); } public function DoGnupgExportKey() : array diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/gpg/base.php b/snappymail/v/0.0.0/app/libraries/snappymail/gpg/base.php index 168f8f63f..2518677a7 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/gpg/base.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/gpg/base.php @@ -5,6 +5,8 @@ namespace SnappyMail\GPG; +use SnappyMail\SensitiveString; + abstract class Base { const @@ -64,7 +66,13 @@ abstract class Base function __construct(string $homedir) { - $this->options['homedir'] = \rtrim($homedir, '/\\'); + $homedir = \rtrim($homedir, '/\\'); + // BSD 4.4 max length + if (104 <= \strlen($homedir . '/S.gpg-agent.extra')) { + throw new \Exception('Socket name for S.gpg-agent.extra is too long'); + } + $this->options['homedir'] = $homedir; +// \putenv("GNUPGHOME={$homedir}"); } function __destruct() @@ -169,22 +177,13 @@ abstract class Base } /** - * Exports a public key + * Exports a public or private key */ - public function export(string $fingerprint) /*: string|false*/ + public function export(string $fingerprint, ?SensitiveString $passphrase = null) /*: string|false*/ { return false; } - /** - * Exports a private key - */ - public function exportPrivateKey(string $fingerprint) /*: string|false*/ - { - return false; - } - - /** * Imports a key */ @@ -209,12 +208,11 @@ abstract class Base /** * Returns an array with information about all keys that matches the given pattern */ - public function keyInfo(string $pattern, int $private = 0) : array + public function keyInfo(string $pattern, bool $private = false) : array { return []; } - /** * Sets the mode for error_reporting * GNUPG_ERROR_WARNING, GNUPG_ERROR_EXCEPTION and GNUPG_ERROR_SILENT. @@ -284,7 +282,7 @@ abstract class Base /** * Add a key for decryption */ - public function addDecryptKey(string $fingerprint, \SnappyMail\SensitiveString $passphrase) : bool + public function addDecryptKey(string $fingerprint, SensitiveString $passphrase) : bool { $this->decryptKeys[$fingerprint] = $passphrase; // $this->decryptKeys[\substr($fingerprint, -16)] = $passphrase; @@ -303,7 +301,7 @@ abstract class Base /** * Add a key for signing */ - public function addSignKey(string $fingerprint, \SnappyMail\SensitiveString $passphrase) : bool + public function addSignKey(string $fingerprint, SensitiveString $passphrase) : bool { $this->signKeys[$fingerprint] = $passphrase; // $this->signKeys[\substr($fingerprint, -16)] = $passphrase; @@ -350,7 +348,7 @@ abstract class Base ]; } - public function addPassphrase($keyId, \SnappyMail\SensitiveString $passphrase) + public function addPassphrase($keyId, SensitiveString $passphrase) { $this->passphrases[$keyId] = $passphrase; return $this; @@ -358,10 +356,11 @@ abstract class Base /** * Toggle the armored output + * When true the output is ASCII */ - public function setArmor(int $armor = 1) : bool + public function setArmor(bool $armor = true) : bool { - $this->armor = !!$armor; + $this->armor = $armor; return true; } diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/gpg/pgp.php b/snappymail/v/0.0.0/app/libraries/snappymail/gpg/pgp.php index 40b08252a..c0c675202 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/gpg/pgp.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/gpg/pgp.php @@ -7,7 +7,9 @@ namespace SnappyMail\GPG; -class PGP extends Base +use SnappyMail\SensitiveString; + +class PGP extends Base implements \SnappyMail\PGP\PGPInterface { private $_message, @@ -137,6 +139,7 @@ class PGP extends Base if (!$fp || !\is_resource($fp)) { throw new \Exception('Invalid stream resource'); } +// \rewind($fp); return $this->_decrypt($fp, $output); } @@ -215,6 +218,7 @@ class PGP extends Base if (!$fp || !\is_resource($fp)) { throw new \Exception('Invalid stream resource'); } + \rewind($fp); return $this->_encrypt($fp, $output); } @@ -234,9 +238,9 @@ class PGP extends Base return false; } - protected function _exportKey($keyId, $private = false) + protected function _exportKey($keyId, bool $private = false) { - $keys = $this->keyInfo($keyId, $private ? 1 : 0); + $keys = $this->keyInfo($keyId, $private); if (!$keys) { throw new \Exception(($private ? 'Private' : 'Public') . ' key not found: ' . $keyId); } @@ -252,21 +256,19 @@ class PGP extends Base } /** - * Exports a public key + * Exports a public or private key */ - public function export(string $fingerprint) /*: string|false*/ + public function export(string $fingerprint, ?SensitiveString $passphrase = null) /*: string|false*/ { +// \SnappyMail\Log::debug('GnuPG', "export({$fingerprint}, {$passphrase})"); + if (null !== $passphrase) { + return $this + ->addPassphrase($fingerprint, $passphrase) + ->_exportKey($fingerprint, true); + } return $this->_exportKey($fingerprint); } - /** - * Exports a private key - */ - public function exportPrivateKey(string $fingerprint) /*: string|false*/ - { - return $this->_exportKey($fingerprint, true); - } - /** * Returns the errortext, if a function fails */ @@ -296,8 +298,13 @@ class PGP extends Base * Also saves revocation certificate in {homedir}/openpgp-revocs.d/ * https://www.gnupg.org/documentation/manuals/gnupg/OpenPGP-Key-Management.html */ - public function generateKey(PGPKeySettings $settings) /*: string|false*/ + public function generateKey(string $uid, SensitiveString $passphrase) /*: string|false*/ { + $settings = new PGPKeySettings; + $settings->name = $uid; + $settings->email = $uid; + $settings->passphrase = $passphrase; + $arguments = [ '--batch', '--yes', @@ -421,13 +428,13 @@ class PGP extends Base } } - public function deleteKey(string $keyId, bool $private) + public function deleteKey(string $keyId, bool $private) : bool { - $key = $this->keyInfo($keyId, $private ? 1 : 0); + $key = $this->keyInfo($keyId, $private); if (!$key) { throw new \Exception(($private ? 'Private' : 'Public') . ' key not found: ' . $keyId); } -// if (!$private && $this->keyInfo($keyId, 1)) { +// if (!$private && $this->keyInfo($keyId, true)) { // throw new \Exception('Delete private key first: ' . $keyId); // } @@ -448,7 +455,7 @@ class PGP extends Base /** * Returns an array with information about all keys that matches the given pattern */ - public function keyInfo(string $pattern, int $private = 0) : array + public function keyInfo(string $pattern, bool $private = false) : array { // According to The file 'doc/DETAILS' in the GnuPG distribution, using // double '--with-fingerprint' also prints the fingerprint for subkeys. @@ -572,6 +579,30 @@ class PGP extends Base return $keys; } + /** + * Returns an array with information about all keys that matches the given pattern + */ + public function allKeysInfo(string $pattern) : array + { + $keys = [ + 'public' => [], + 'private' => [] + ]; + // Public + foreach (($this->keyinfo($pattern) ?: []) as $key) { + $key['can_verify'] = $key['can_sign']; + unset($key['can_sign']); + $keys['public'][] = $key; + } + // Private, read https://github.com/php-gnupg/php-gnupg/issues/5 + foreach (($this->keyinfo($pattern, 1) ?: []) as $key) { + $key['can_decrypt'] = $key['can_encrypt']; + unset($key['can_encrypt']); + $keys['private'][] = $key; + } + return $keys; + } + /** * Sets the mode for error_reporting * GNUPG_ERROR_WARNING, GNUPG_ERROR_EXCEPTION and GNUPG_ERROR_SILENT. @@ -671,6 +702,7 @@ class PGP extends Base if (!$fp || !\is_resource($fp)) { throw new \Exception('Invalid stream resource'); } + \rewind($fp); return $this->_sign($fp, $output); } @@ -768,6 +800,7 @@ class PGP extends Base if (!$fp || !\is_resource($fp)) { throw new \Exception('Invalid stream resource'); } +// \rewind($fp); return $this->_verify($fp, $signature); } diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/gpg/smime.php b/snappymail/v/0.0.0/app/libraries/snappymail/gpg/smime.php index 8adff5a7a..3e8d76f5e 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/gpg/smime.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/gpg/smime.php @@ -11,6 +11,8 @@ namespace SnappyMail\GPG; +use SnappyMail\SensitiveString; + class SMIME extends Base { private @@ -235,9 +237,9 @@ class SMIME extends Base return false; } - protected function _exportKey($keyId, $private = false) + protected function _exportKey($keyId, bool $private = false) { - $keys = $this->keyInfo($keyId, $private ? 1 : 0); + $keys = $this->keyInfo($keyId, $private); if (!$keys) { throw new \Exception(($private ? 'Private' : 'Public') . ' key not found: ' . $keyId); } @@ -253,21 +255,18 @@ class SMIME extends Base } /** - * Exports a public key + * Exports a public or private key */ - public function export(string $fingerprint) /*: string|false*/ + public function export(string $fingerprint, ?SensitiveString $passphrase = null) /*: string|false*/ { + if ($passphrase) { + return $this + ->addPassphrase($fingerprint, $passphrase) + ->_exportKey($fingerprint, true); + } return $this->_exportKey($fingerprint); } - /** - * Exports a private key - */ - public function exportPrivateKey(string $fingerprint) /*: string|false*/ - { - return $this->_exportKey($fingerprint, true); - } - protected function _importKey($input) /*: array|false*/ { $arguments = ['--import']; @@ -334,7 +333,7 @@ class SMIME extends Base public function deleteKey(string $keyId, bool $private) { - $key = $this->keyInfo($keyId, $private ? 1 : 0); + $key = $this->keyInfo($keyId, $private); if (!$key) { throw new \Exception(($private ? 'Private' : 'Public') . ' key not found: ' . $keyId); } @@ -359,7 +358,7 @@ class SMIME extends Base /** * Returns an array with information about all keys that matches the given pattern */ - public function keyInfo(string $pattern, int $private = 0) : array + public function keyInfo(string $pattern, bool $private = false) : array { // According to The file 'doc/DETAILS' in the GnuPG distribution, using // double '--with-fingerprint' also prints the fingerprint for subkeys. diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/pgp/gnupg.php b/snappymail/v/0.0.0/app/libraries/snappymail/pgp/gnupg.php index 88215493e..72494fd68 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/pgp/gnupg.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/pgp/gnupg.php @@ -8,449 +8,26 @@ defined('GNUPG_SIG_MODE_CLEAR') || define('GNUPG_SIG_MODE_CLEAR', 2); use SnappyMail\GPG\PGP as GPG; -class GnuPG +abstract class GnuPG { - private - $homedir, - // Instance of gnupg pecl extension https://www.php.net/gnupg - $GnuPG, - // Instance of \SnappyMail\GPG\PGP - $GPG; - - function __construct(string $homedir) - { - $homedir = \rtrim($homedir, '/\\'); - // BSD 4.4 max length - if (104 <= \strlen($homedir . '/S.gpg-agent.extra')) { - throw new \Exception('socket name for S.gpg-agent.extra is too long'); - } - $this->homedir = $homedir; -// \putenv("GNUPGHOME={$homedir}"); - - if (\class_exists('gnupg') && \version_compare(\phpversion('gnupg'), '1.5', '>=')) { - $this->GnuPG = new \gnupg([ - // It is the file name of the executable program implementing this protocol which is usually path of the gpg executable. -// 'file_name' => '/usr/bin/gpg', - // It is the directory name of the configuration directory. It also overrides GNUPGHOME environment variable that is used for the same purpose. - 'home_dir' => $homedir - ]); - // Output is ASCII - $this->GnuPG->setarmor(1); - \SnappyMail\Log::info('GnuPG', 'Using PECL'); - } else { - $this->getGPG(); - } - -/* - $conf = "{$homedir}/gpg-agent.conf"; - if (!\file_exists($conf)) { - \file_put_contents($conf, 'default-cache-ttl 1'); - } - $conf = "{$homedir}/gpg.conf"; - if (!\file_exists($conf)) { - \file_put_contents($conf, "batch\nno-comments"); - } -*/ - } - - function __destruct() - { - $this->clearDecryptKeys(); - $this->clearSignKeys(); - } - public static function isSupported() : bool { - return \class_exists('gnupg') || GPG::isSupported(); + return GPG::isSupported(); } private static $instance; - public static function getInstance(string $homedir) : ?self + public static function getInstance(string $homedir) : ?PGPInterface { if (!static::$instance) { - static::$instance = new self($homedir); + if (GPG::isSupported()) { + static::$instance = new GPG($homedir); + } +/* + else if (PECL::isSupported()) { + static::$instance = new PECL($homedir); + } +*/ } return static::$instance; } - - public function handler() - { - return $this->GnuPG ?: $this->GPG; - } - - public function gnupgError() - { - $error = $this->GnuPG ? $this->GnuPG->geterrorinfo() : null; - if ($error) { - throw new \Exception("{$error['gpgme_source']} {$error['generic_message']}. {$error['gpgme_message']}", $error['gpgme_code']); - } - } - - public function getGPG(bool $throw = true) : ?GPG - { - if (!$this->GPG) { - if (GPG::isSupported()) { - $this->GPG = new GPG($this->homedir); - \SnappyMail\Log::info('GnuPG', 'Using ' . GPG::class); - } else if ($throw) { - throw new \Exception('GnuPG not supported'); - } - } - return $this->GPG; - } - - /** - * Add a key for decryption - */ - public function addDecryptKey(string $fingerprint, \SnappyMail\SensitiveString $passphrase) : bool - { - return $this->GnuPG - ? $this->GnuPG->adddecryptkey($fingerprint, \strval($passphrase)) || $this->gnupgError() - : $this->GPG->addDecryptKey($fingerprint, $passphrase); - } - - /** - * Add a key for encryption - */ - public function addEncryptKey(string $fingerprint) : bool - { - return $this->handler()->addencryptkey($fingerprint); - } - - /** - * Add a key for signing - */ - public function addSignKey(string $fingerprint, \SnappyMail\SensitiveString $passphrase) : bool - { - return $this->GnuPG - ? $this->GnuPG->addsignkey($fingerprint, \strval($passphrase)) || $this->gnupgError() - : $this->GPG->addSignKey($fingerprint, $passphrase); - } - - /** - * Removes all keys which were set for decryption before - */ - public function clearDecryptKeys() : bool - { - return $this->handler()->cleardecryptkeys(); - } - - /** - * Removes all keys which were set for encryption before - */ - public function clearEncryptKeys() : bool - { - return $this->handler()->clearencryptkeys(); - } - - /** - * Removes all keys which were set for signing before - */ - public function clearSignKeys() : bool - { - return $this->handler()->clearsignkeys(); - } - - /** - * Decrypts a given text - */ - public function decrypt(string $text) /*: string|false */ - { - if ($this->GnuPG) { - $result = $this->GnuPG->decrypt($text); - (false === $result) && $this->gnupgError(); - return $result; - } - return $this->GPG->decrypt($text); - } - - /** - * Decrypts a given file - */ - public function decryptFile(string $filename) /*: string|false */ - { - if ($this->GnuPG) { - $result = $this->GnuPG->decrypt(\file_get_contents($filename)); - (false === $result) && $this->gnupgError(); - return $result; - } - return $this->GPG->decryptFile($filename); - } - - /** - * Decrypts a given resource - */ - public function decryptStream(/*resource*/ $fp, /*string|resource*/ $output = null) /*: string|false */ - { - if (!$fp || !\is_resource($fp)) { - throw new \Exception('Invalid stream resource'); - } - if ($this->GnuPG) { - $result = $this->GnuPG->decrypt(\stream_get_contents($fp)); - (false === $result) && $this->gnupgError(); - return $result; - } - return $this->GPG->decryptStream($fp, $output); - } - - /** - * Decrypts and verifies a given text - */ - public function decryptVerify(string $text, string &$plaintext) /*: array|false*/ - { - if ($this->GnuPG) { - $result = $this->GnuPG->decryptverify($text, $plaintext); - (false === $result) && $this->gnupgError(); - return $result; - } - return $this->GPG->decryptverify($text, $plaintext); - } - - /** - * Decrypts and verifies a given file - */ - public function decryptVerifyFile(string $filename, string &$plaintext) /*: array|false*/ - { - if ($this->GnuPG) { - $result = $this->GnuPG->decryptverify(\file_get_contents($filename), $plaintext); - (false === $result) && $this->gnupgError(); - return $result; - } - return $this->GPG->decryptverifyFile($filename, $plaintext); - } - - public function deleteKey(string $keyId, bool $private) : bool - { - return $this->getGPG()->deleteKey($keyId, $private); - } - - /** - * Encrypts a given text - */ - public function encrypt(string $plaintext) /*: string|false*/ - { - return $this->GnuPG - ? $this->GnuPG->encrypt($plaintext) ?: $this->gnupgError() - : $this->GPG->encrypt($plaintext); - } - - /** - * Encrypts a given text - */ - public function encryptFile(string $filename) /*: string|false*/ - { - return $this->GnuPG - ? $this->GnuPG->encrypt(\file_get_contents($filename)) ?: $this->gnupgError() - : $this->GPG->encryptFile($filename); - } - - public function encryptStream(/*resource*/ $fp, /*string|resource*/ $output = null) /*: string|false*/ - { - \rewind($fp); - return $this->GnuPG - ? $this->GnuPG->encrypt(\stream_get_contents($fp)) ?: $this->gnupgError() - : $this->GPG->encryptStream($fp); - } - - /** - * Exports a key - */ - public function export(string $fingerprint, ?\SnappyMail\SensitiveString $passphrase = null) /*: string|false*/ - { - if ($passphrase) { - return $this->getGPG() - ->addPassphrase($fingerprint, $passphrase) - ->exportPrivateKey($fingerprint); - } - return $this->GnuPG - ? $this->GnuPG->export($fingerprint) ?: $this->gnupgError() - : $this->GPG->export($fingerprint); - } - - /** - * Returns the engine info - */ - public function getEngineInfo() : array - { - return $this->handler()->getengineinfo(); - } - - /** - * Returns the errortext, if a function fails - */ - public function getError() /*: string|false*/ - { - return $this->handler()->geterror(); - } - - /** - * Returns the error info - */ - public function getErrorInfo() : array - { - return $this->handler()->geterrorinfo(); - } - - /** - * Returns the currently active protocol for all operations - */ - public function getProtocol() : int - { - return $this->handler()->getprotocol(); - } - - /** - * Generates a key - */ - public function generateKey(string $uid, \SnappyMail\SensitiveString $passphrase) /*: string|false*/ - { - $GPG = $this->getGPG(false); - return $GPG ? $GPG->generateKey($uid, $passphrase) : false; - } - - /** - * Imports a key - */ - public function import(string $keydata) /*: array|false*/ - { - return $this->handler()->import($keydata); - } - - /** - * Imports a key - */ - public function importFile(string $filename) /*: array|false*/ - { - return $this->GnuPG - ? $this->GnuPG->import(\file_get_contents($filename)) ?: $this->gnupgError() - : $this->GPG->importFile($filename); - } - - /** - * Returns an array with information about all keys that matches the given pattern - */ - public function keyInfo(string $pattern) : array - { - $keys = [ - 'public' => [], - 'private' => [] - ]; - // Public - foreach (($this->handler()->keyinfo($pattern) ?: []) as $key) { - $key['can_verify'] = $key['can_sign']; - unset($key['can_sign']); - $keys['public'][] = $key; - } - // Private, read https://github.com/php-gnupg/php-gnupg/issues/5 - foreach (($this->handler()->keyinfo($pattern, 1) ?: []) as $key) { - $key['can_decrypt'] = $key['can_encrypt']; - unset($key['can_encrypt']); - $keys['private'][] = $key; - } - return $keys; - } - - /** - * Toggle armored output - * When true the output is ASCII - */ - public function setArmor(bool $armor = true) : bool - { - return $this->handler()->setarmor($armor ? 1 : 0); - } - - /** - * Sets the mode for error_reporting - * GNUPG_ERROR_WARNING, GNUPG_ERROR_EXCEPTION and GNUPG_ERROR_SILENT. - * By default GNUPG_ERROR_SILENT is used. - */ - public function setErrorMode(int $errormode) : void - { - $this->handler()->seterrormode($errormode); - } - - /** - * Sets the mode for signing - * GNUPG_SIG_MODE_NORMAL, GNUPG_SIG_MODE_DETACH and GNUPG_SIG_MODE_CLEAR. - * By default GNUPG_SIG_MODE_CLEAR - */ - public function setSignMode(int $signmode) : bool - { - return $this->handler()->setsignmode($signmode); - } - - /** - * Signs a given text - */ - public function sign(string $plaintext) /*: string|false*/ - { - return $this->GnuPG - ? $this->GnuPG->sign($plaintext) ?: $this->gnupgError() - : $this->GPG->sign($plaintext); - } - - /** - * Signs a given file - */ - public function signFile(string $filename) /*: string|false*/ - { - return $this->GnuPG - ? $this->GnuPG->sign(\file_get_contents($filename)) ?: $this->gnupgError() - : $this->GPG->signFile($filename); - } - - /** - * Signs a given file - */ - public function signStream($fp, /*string|resource*/ $output = null) /*: string|false*/ - { - \rewind($fp); - return $this->GnuPG - ? $this->GnuPG->sign(\stream_get_contents($fp)) ?: $this->gnupgError() - : $this->GPG->signStream($fp); - } - - /** - * Verifies a signed text - */ - public function verify(string $signed_text, string $signature, string &$plaintext = null) /*: array|false*/ - { - $result = $this->GnuPG - ? $this->GnuPG->verify($signed_text, $signature ?: false, $plaintext) ?: $this->gnupgError() - : $this->GPG->verify($signed_text, $signature, $plaintext); - if (!$result) { - if ($this->GnuPG) { - \SnappyMail\Log::notice('GnuPG', 'gnupg_verify() failed: ' . $this->GnuPG->geterror()); - \SnappyMail\Log::info('GnuPG', \print_r($this->GnuPG->geterrorinfo(),1)); - } else { - \SnappyMail\Log::notice('GPG', 'GPG->verify() failed'); - } - } - return $result; - } - - /** - * Verifies a signed file - */ - public function verifyFile(string $filename, string $signature, string &$plaintext = null) /*: array|false*/ - { - return $this->GnuPG - ? $this->GnuPG->verify(\file_get_contents($filename), $signature, $plaintext) ?: $this->gnupgError() - : $this->GPG->verifyFile($filename, $signature, $plaintext); - } - - /** - * Verifies a given resource - */ - public function verifyStream(/*resource*/ $fp, string $signature, string &$plaintext = null) /*: array|false */ - { - if (!$fp || !\is_resource($fp)) { - throw new \Exception('Invalid stream resource'); - } -// return $this->GnuPG -// ? $this->GnuPG->verify(\stream_get_contents($fp), $signature, $plaintext) ?: $this->gnupgError() -// : $this->GPG->verifyStream($fp, $signature, $plaintext); - return $this->getGPG()->verifyStream($fp, $signature, $plaintext); - } - } diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/pgp/pecl.php b/snappymail/v/0.0.0/app/libraries/snappymail/pgp/pecl.php new file mode 100644 index 000000000..a8582b578 --- /dev/null +++ b/snappymail/v/0.0.0/app/libraries/snappymail/pgp/pecl.php @@ -0,0 +1,397 @@ +homedir = $homedir; +// \putenv("GNUPGHOME={$homedir}"); + + $this->GnuPG = new \gnupg([ + // It is the file name of the executable program implementing this protocol which is usually path of the gpg executable. +// 'file_name' => '/usr/bin/gpg', + // It is the directory name of the configuration directory. It also overrides GNUPGHOME environment variable that is used for the same purpose. + 'home_dir' => $homedir + ]); + // Output is ASCII + $this->GnuPG->setarmor(1); +/* + $conf = "{$homedir}/gpg-agent.conf"; + if (!\file_exists($conf)) { + \file_put_contents($conf, 'default-cache-ttl 1'); + } + $conf = "{$homedir}/gpg.conf"; + if (!\file_exists($conf)) { + \file_put_contents($conf, "batch\nno-comments"); + } +*/ + } + + function __destruct() + { + $this->GnuPG->cleardecryptkeys(); + $this->GnuPG->clearsignkeys(); + } + + public static function isSupported() : bool + { + return \class_exists('gnupg') && \version_compare(\phpversion('gnupg'), '1.5', '>='); + } + + public function gnupgError() + { + $error = $this->GnuPG->geterrorinfo(); + if ($error) { + throw new \Exception("{$error['gpgme_source']} {$error['generic_message']}. {$error['gpgme_message']}", $error['gpgme_code']); + } + } + + public function getGPG(bool $throw = true) : ?GPG + { + if (!$this->GPG) { + if (GPG::isSupported()) { + $this->GPG = new GPG($this->homedir); + } else if ($throw) { + throw new \Exception('GPG not supported'); + } + } + return $this->GPG; + } + + /** + * Add a key for decryption + */ + public function addDecryptKey(string $fingerprint, SensitiveString $passphrase) : bool + { +// \SnappyMail\Log::debug('GnuPG', "addDecryptKey({$fingerprint}, {$passphrase})"); + return $this->GnuPG->adddecryptkey($fingerprint, \strval($passphrase)) || $this->gnupgError(); + } + + /** + * Add a key for encryption + */ + public function addEncryptKey(string $fingerprint) : bool + { + return $this->GnuPG->addencryptkey($fingerprint) || $this->gnupgError(); + } + + /** + * Add a key for signing + */ + public function addSignKey(string $fingerprint, SensitiveString $passphrase) : bool + { +// \SnappyMail\Log::debug('GnuPG', "addSignKey({$fingerprint}, {$passphrase})"); + return $this->GnuPG->addsignkey($fingerprint, \strval($passphrase)) || $this->gnupgError(); + } + + /** + * Removes all keys which were set for decryption before + */ + public function clearDecryptKeys() : bool + { + return $this->GnuPG->cleardecryptkeys(); + } + + /** + * Removes all keys which were set for encryption before + */ + public function clearEncryptKeys() : bool + { + return $this->GnuPG->clearencryptkeys(); + } + + /** + * Removes all keys which were set for signing before + */ + public function clearSignKeys() : bool + { + return $this->GnuPG->clearsignkeys(); + } + + /** + * Decrypts a given text + */ + public function decrypt(string $text) /*: string|false */ + { + $result = $this->GnuPG->decrypt($text); + (false === $result) && $this->gnupgError(); + return $result; + } + + /** + * Decrypts a given file + */ + public function decryptFile(string $filename) /*: string|false */ + { + $result = $this->GnuPG->decrypt(\file_get_contents($filename)); + (false === $result) && $this->gnupgError(); + return $result; + } + + /** + * Decrypts a given resource + */ + public function decryptStream(/*resource*/ $fp, /*string|resource*/ $output = null) /*: string|false */ + { + if (!$fp || !\is_resource($fp)) { + throw new \Exception('Invalid stream resource'); + } +// \rewind($fp); + $result = $this->GnuPG->decrypt(\stream_get_contents($fp)); + (false === $result) && $this->gnupgError(); + return $result; + } + + /** + * Decrypts and verifies a given text + */ + public function decryptVerify(string $text, string &$plaintext) /*: array|false*/ + { + $result = $this->GnuPG->decryptverify($text, $plaintext); + (false === $result) && $this->gnupgError(); + return $result; + } + + /** + * Decrypts and verifies a given file + */ + public function decryptVerifyFile(string $filename, string &$plaintext) /*: array|false*/ + { + $result = $this->GnuPG->decryptverify(\file_get_contents($filename), $plaintext); + (false === $result) && $this->gnupgError(); + return $result; + } + + public function deleteKey(string $keyId, bool $private) : bool + { + return $this->getGPG()->deleteKey($keyId, $private); + } + + /** + * Encrypts a given text + */ + public function encrypt(string $plaintext) /*: string|false*/ + { + return $this->GnuPG->encrypt($plaintext) ?: $this->gnupgError(); + } + + /** + * Encrypts a given text + */ + public function encryptFile(string $filename) /*: string|false*/ + { + return $this->GnuPG->encrypt(\file_get_contents($filename)) ?: $this->gnupgError(); + } + + public function encryptStream(/*resource*/ $fp, /*string|resource*/ $output = null) /*: string|false*/ + { + \rewind($fp); + return $this->GnuPG->encrypt(\stream_get_contents($fp)) ?: $this->gnupgError(); + } + + /** + * Exports a key + */ + public function export(string $fingerprint, ?SensitiveString $passphrase = null) /*: string|false*/ + { + if (null !== $passphrase) { + return $this->getGPG()->export($fingerprint, $passphrase); + } + return $this->GnuPG->export($fingerprint) ?: $this->gnupgError(); + } + + /** + * Returns the engine info + */ + public function getEngineInfo() : array + { + return $this->GnuPG->getengineinfo(); + } + + /** + * Returns the errortext, if a function fails + */ + public function getError() /*: string|false*/ + { + return $this->GnuPG->geterror(); + } + + /** + * Returns the error info + */ + public function getErrorInfo() : array + { + return $this->GnuPG->geterrorinfo(); + } + + /** + * Returns the currently active protocol for all operations + */ + public function getProtocol() : int + { + return $this->GnuPG->getprotocol(); + } + + /** + * Generates a key + */ + public function generateKey(string $uid, SensitiveString $passphrase) /*: string|false*/ + { + $GPG = $this->getGPG(false); + return $GPG ? $GPG->generateKey($uid, $passphrase) : false; + } + + /** + * Imports a key + */ + public function import(string $keydata) /*: array|false*/ + { + return $this->GnuPG->import($keydata); + } + + /** + * Imports a key + */ + public function importFile(string $filename) /*: array|false*/ + { + return $this->GnuPG->import(\file_get_contents($filename)) ?: $this->gnupgError(); + } + + public function keyInfo(string $pattern, bool $private = false) : array + { + return $this->GnuPG->keyinfo($pattern, $private ? 1 : 0); + } + + /** + * Returns an array with information about all keys that matches the given pattern + */ + public function allKeysInfo(string $pattern) : array + { + $keys = [ + 'public' => [], + 'private' => [] + ]; + // Public + foreach (($this->GnuPG->keyinfo($pattern) ?: []) as $key) { + $key['can_verify'] = $key['can_sign']; + unset($key['can_sign']); + $keys['public'][] = $key; + } + // Private, read https://github.com/php-gnupg/php-gnupg/issues/5 + foreach (($this->GnuPG->keyinfo($pattern, 1) ?: []) as $key) { + $key['can_decrypt'] = $key['can_encrypt']; + unset($key['can_encrypt']); + $keys['private'][] = $key; + } + return $keys; + } + + /** + * Toggle armored output + * When true the output is ASCII + */ + public function setArmor(bool $armor = true) : bool + { + return $this->GnuPG->setarmor($armor ? 1 : 0); + } + + /** + * Sets the mode for error_reporting + * GNUPG_ERROR_WARNING, GNUPG_ERROR_EXCEPTION and GNUPG_ERROR_SILENT. + * By default GNUPG_ERROR_SILENT is used. + */ + public function setErrorMode(int $errormode) : void + { + $this->GnuPG->seterrormode($errormode); + } + + /** + * Sets the mode for signing + * GNUPG_SIG_MODE_NORMAL, GNUPG_SIG_MODE_DETACH and GNUPG_SIG_MODE_CLEAR. + * By default GNUPG_SIG_MODE_CLEAR + */ + public function setSignMode(int $signmode) : bool + { + return $this->GnuPG->setsignmode($signmode); + } + + /** + * Signs a given text + */ + public function sign(string $plaintext) /*: string|false*/ + { + return $this->GnuPG->sign($plaintext) ?: $this->gnupgError(); + } + + /** + * Signs a given file + */ + public function signFile(string $filename) /*: string|false*/ + { + return $this->GnuPG->sign(\file_get_contents($filename)) ?: $this->gnupgError(); + } + + /** + * Signs a given file + */ + public function signStream($fp, /*string|resource*/ $output = null) /*: string|false*/ + { + \rewind($fp); + return $this->GnuPG->sign(\stream_get_contents($fp)) ?: $this->gnupgError(); + } + + /** + * Verifies a signed text + */ + public function verify(string $signed_text, string $signature, string &$plaintext = null) /*: array|false*/ + { + $result = $this->GnuPG->verify($signed_text, $signature ?: false, $plaintext) ?: $this->gnupgError(); + if (!$result) { + \SnappyMail\Log::notice('GnuPG', 'gnupg_verify() failed: ' . $this->GnuPG->geterror()); + \SnappyMail\Log::info('GnuPG', \print_r($this->GnuPG->geterrorinfo(),1)); + } + return $result; + } + + /** + * Verifies a signed file + */ + public function verifyFile(string $filename, string $signature, string &$plaintext = null) /*: array|false*/ + { + return $this->GnuPG->verify(\file_get_contents($filename), $signature, $plaintext) ?: $this->gnupgError(); + } + + /** + * Verifies a given resource + */ + public function verifyStream(/*resource*/ $fp, string $signature, string &$plaintext = null) /*: array|false */ + { + if (!$fp || !\is_resource($fp)) { + throw new \Exception('Invalid stream resource'); + } +// \rewind($fp); + return $this->GnuPG->verify(\stream_get_contents($fp), $signature, $plaintext) ?: $this->gnupgError(); + } + +} diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/pgp/pgpinterface.php b/snappymail/v/0.0.0/app/libraries/snappymail/pgp/pgpinterface.php new file mode 100644 index 000000000..50fc1350e --- /dev/null +++ b/snappymail/v/0.0.0/app/libraries/snappymail/pgp/pgpinterface.php @@ -0,0 +1,43 @@ + Date: Tue, 27 Feb 2024 22:30:29 +0100 Subject: [PATCH 045/110] Resolve #1456 --- integrations/nextcloud/snappymail/lib/Migration/InstallStep.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrations/nextcloud/snappymail/lib/Migration/InstallStep.php b/integrations/nextcloud/snappymail/lib/Migration/InstallStep.php index 6e805af6a..dfb1f1e8d 100644 --- a/integrations/nextcloud/snappymail/lib/Migration/InstallStep.php +++ b/integrations/nextcloud/snappymail/lib/Migration/InstallStep.php @@ -72,7 +72,7 @@ class InstallStep implements IRepairStep if ('12345' == $sPassword || !$sPassword) { $output->info('Generate admin password'); $sPassword = \substr(\base64_encode(\random_bytes(16)), 0, 12); - $oConfig->SetPassword($sPassword); + $oConfig->SetPassword(new \SnappyMail\SensitiveString($sPassword)); \RainLoop\Utils::saveFile(APP_PRIVATE_DATA . 'admin_password.txt', $sPassword . "\n"); $bSave = true; } From 7e6523b59a803dfaa9e8c75980767d92cfc87be9 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Tue, 27 Feb 2024 22:51:10 +0100 Subject: [PATCH 046/110] Resolve #1458 --- snappymail/v/0.0.0/app/localization/ar-SA/user.json | 4 +++- snappymail/v/0.0.0/app/localization/bg-BG/user.json | 4 +++- snappymail/v/0.0.0/app/localization/cs-CZ/user.json | 4 +++- snappymail/v/0.0.0/app/localization/da-DK/user.json | 4 +++- snappymail/v/0.0.0/app/localization/de-DE/user.json | 4 +++- snappymail/v/0.0.0/app/localization/el-GR/user.json | 4 +++- snappymail/v/0.0.0/app/localization/en-GB/user.json | 4 +++- snappymail/v/0.0.0/app/localization/en/user.json | 4 +++- snappymail/v/0.0.0/app/localization/es-ES/user.json | 4 +++- snappymail/v/0.0.0/app/localization/et-EE/user.json | 4 +++- snappymail/v/0.0.0/app/localization/eu/user.json | 4 +++- snappymail/v/0.0.0/app/localization/fa-IR/user.json | 4 +++- snappymail/v/0.0.0/app/localization/fi-FI/user.json | 4 +++- snappymail/v/0.0.0/app/localization/fr-FR/user.json | 4 +++- snappymail/v/0.0.0/app/localization/hu-HU/user.json | 4 +++- snappymail/v/0.0.0/app/localization/id-ID/user.json | 4 +++- snappymail/v/0.0.0/app/localization/is-IS/user.json | 4 +++- snappymail/v/0.0.0/app/localization/it-IT/user.json | 4 +++- snappymail/v/0.0.0/app/localization/ja-JP/user.json | 4 +++- snappymail/v/0.0.0/app/localization/ko-KR/user.json | 4 +++- snappymail/v/0.0.0/app/localization/lt-LT/user.json | 4 +++- snappymail/v/0.0.0/app/localization/lv-LV/user.json | 4 +++- snappymail/v/0.0.0/app/localization/nb-NO/user.json | 4 +++- snappymail/v/0.0.0/app/localization/nl-NL/user.json | 4 +++- snappymail/v/0.0.0/app/localization/pl-PL/user.json | 4 +++- snappymail/v/0.0.0/app/localization/pt-BR/user.json | 4 +++- snappymail/v/0.0.0/app/localization/pt-PT/user.json | 4 +++- snappymail/v/0.0.0/app/localization/pt/user.json | 4 +++- snappymail/v/0.0.0/app/localization/ro-RO/user.json | 4 +++- snappymail/v/0.0.0/app/localization/ru-RU/user.json | 4 +++- snappymail/v/0.0.0/app/localization/sk-SK/user.json | 4 +++- snappymail/v/0.0.0/app/localization/sl-SI/user.json | 4 +++- snappymail/v/0.0.0/app/localization/sv-SE/user.json | 4 +++- snappymail/v/0.0.0/app/localization/tr-TR/user.json | 4 +++- snappymail/v/0.0.0/app/localization/uk-UA/user.json | 4 +++- snappymail/v/0.0.0/app/localization/vi-VN/user.json | 4 +++- snappymail/v/0.0.0/app/localization/zh-CN/user.json | 4 +++- snappymail/v/0.0.0/app/localization/zh-TW/user.json | 4 +++- .../v/0.0.0/app/templates/Views/User/PopupsIdentity.html | 4 ++-- 39 files changed, 116 insertions(+), 40 deletions(-) diff --git a/snappymail/v/0.0.0/app/localization/ar-SA/user.json b/snappymail/v/0.0.0/app/localization/ar-SA/user.json index a5b5c6c44..681ec190d 100644 --- a/snappymail/v/0.0.0/app/localization/ar-SA/user.json +++ b/snappymail/v/0.0.0/app/localization/ar-SA/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "توقيع جيد من %USER%", "ERROR": "%TYPE% error: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "OpenPGP استيراد مفتاح", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME signed message", "ENCRYPTED_MESSAGE": "S\/MIME encrypted message", diff --git a/snappymail/v/0.0.0/app/localization/bg-BG/user.json b/snappymail/v/0.0.0/app/localization/bg-BG/user.json index 553dc3d84..0bd9a57e2 100644 --- a/snappymail/v/0.0.0/app/localization/bg-BG/user.json +++ b/snappymail/v/0.0.0/app/localization/bg-BG/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "Валиден подпис за %USER%", "ERROR": "%TYPE% грешка: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "Внасяне на OpenPGP ключ", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "Подписано с S\/MIME", "ENCRYPTED_MESSAGE": "Шифровано с S\/MIME", diff --git a/snappymail/v/0.0.0/app/localization/cs-CZ/user.json b/snappymail/v/0.0.0/app/localization/cs-CZ/user.json index 349c021d6..67b9c5efa 100644 --- a/snappymail/v/0.0.0/app/localization/cs-CZ/user.json +++ b/snappymail/v/0.0.0/app/localization/cs-CZ/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "Ověřený podpis od %USER%", "ERROR": "%TYPE% chyba: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "Import OpenPGP klíče", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "Zpráva podepsaná S\/MIME", "ENCRYPTED_MESSAGE": "Zpráva šifrovaná S\/MIME", diff --git a/snappymail/v/0.0.0/app/localization/da-DK/user.json b/snappymail/v/0.0.0/app/localization/da-DK/user.json index 7f59e18c7..a81a91d3b 100644 --- a/snappymail/v/0.0.0/app/localization/da-DK/user.json +++ b/snappymail/v/0.0.0/app/localization/da-DK/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "Accepteret signatur for %USER\"", "ERROR": "%TYPE% fejl: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "Importer OpenPGP nøgle", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME signeret meddelelse", "ENCRYPTED_MESSAGE": "S\/MIME krypteret meddelelse", diff --git a/snappymail/v/0.0.0/app/localization/de-DE/user.json b/snappymail/v/0.0.0/app/localization/de-DE/user.json index a9b9675fc..5e07f0630 100644 --- a/snappymail/v/0.0.0/app/localization/de-DE/user.json +++ b/snappymail/v/0.0.0/app/localization/de-DE/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "Gültige Unterschrift von %USER%", "ERROR": "%TYPE%-Fehler: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "OpenPGP-Schlüssel importieren", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME-signierte Nachricht", "ENCRYPTED_MESSAGE": "S\/MIME-verschlüsselte Nachricht", diff --git a/snappymail/v/0.0.0/app/localization/el-GR/user.json b/snappymail/v/0.0.0/app/localization/el-GR/user.json index a356d916c..8e71fbdda 100644 --- a/snappymail/v/0.0.0/app/localization/el-GR/user.json +++ b/snappymail/v/0.0.0/app/localization/el-GR/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "Good signature from %USER%", "ERROR": "%TYPE% error: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "Εισαγωγή κλειδιού OpenPGP", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "Μήνυμα υπογεγραμμένο με S\/MIME", "ENCRYPTED_MESSAGE": "Μήνυμα κωδικοποιημένο με S\/MIME", diff --git a/snappymail/v/0.0.0/app/localization/en-GB/user.json b/snappymail/v/0.0.0/app/localization/en-GB/user.json index a45ee06a5..599754e0c 100644 --- a/snappymail/v/0.0.0/app/localization/en-GB/user.json +++ b/snappymail/v/0.0.0/app/localization/en-GB/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "Good signature from %USER%", "ERROR": "%TYPE% error: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "Import OpenPGP key", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME signed message", "ENCRYPTED_MESSAGE": "S\/MIME encrypted message", diff --git a/snappymail/v/0.0.0/app/localization/en/user.json b/snappymail/v/0.0.0/app/localization/en/user.json index c4013b6cd..c42199b18 100644 --- a/snappymail/v/0.0.0/app/localization/en/user.json +++ b/snappymail/v/0.0.0/app/localization/en/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "Good signature from %USER%", "ERROR": "%TYPE% error: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "Import OpenPGP key", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S/MIME Certificates", "SIGNED_MESSAGE": "S/MIME signed message", "ENCRYPTED_MESSAGE": "S/MIME encrypted message", diff --git a/snappymail/v/0.0.0/app/localization/es-ES/user.json b/snappymail/v/0.0.0/app/localization/es-ES/user.json index bbf3c8512..15ae227ad 100644 --- a/snappymail/v/0.0.0/app/localization/es-ES/user.json +++ b/snappymail/v/0.0.0/app/localization/es-ES/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "Buena firma de %USER%", "ERROR": "Error %TYPE%: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "Importar clave OpenPGP", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "Mensaje firmado mediante S\/MIME", "ENCRYPTED_MESSAGE": "Mensaje cifrado mediante S\/MIME", diff --git a/snappymail/v/0.0.0/app/localization/et-EE/user.json b/snappymail/v/0.0.0/app/localization/et-EE/user.json index d62282c68..3629b8826 100644 --- a/snappymail/v/0.0.0/app/localization/et-EE/user.json +++ b/snappymail/v/0.0.0/app/localization/et-EE/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "Korralik signatuur kasutajalt %USER%", "ERROR": "%TYPE% viga: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "Impordi OpenPGP võti", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME abil signeeritud kiri", "ENCRYPTED_MESSAGE": "S\/MIME abil krüpteeritud kiri", diff --git a/snappymail/v/0.0.0/app/localization/eu/user.json b/snappymail/v/0.0.0/app/localization/eu/user.json index a86fcfbc5..2a560f4b7 100644 --- a/snappymail/v/0.0.0/app/localization/eu/user.json +++ b/snappymail/v/0.0.0/app/localization/eu/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "%USER%-en sinadura egokia", "ERROR": "%TYPE% errorea: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "Inportatu OpenPGP gakoa", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME sinatutako mezua", "ENCRYPTED_MESSAGE": "S\/MIME zifratutako mezua", diff --git a/snappymail/v/0.0.0/app/localization/fa-IR/user.json b/snappymail/v/0.0.0/app/localization/fa-IR/user.json index 39ae02b55..90eae77c2 100644 --- a/snappymail/v/0.0.0/app/localization/fa-IR/user.json +++ b/snappymail/v/0.0.0/app/localization/fa-IR/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "امضای صحیح از %USER%", "ERROR": "خطای %TYPE%: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "واردکردن کلید OpenPGP", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "پیام توسط S\/MIME امضاء شد", "ENCRYPTED_MESSAGE": "پیام توسط S\/MIME رمزنگاری شد", diff --git a/snappymail/v/0.0.0/app/localization/fi-FI/user.json b/snappymail/v/0.0.0/app/localization/fi-FI/user.json index 3218d34d4..61de7d2f1 100644 --- a/snappymail/v/0.0.0/app/localization/fi-FI/user.json +++ b/snappymail/v/0.0.0/app/localization/fi-FI/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "Oikea allekirjoitus %USER% lle", "ERROR": "%TYPE% virhe: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "Tuo OpenPGP avain", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME allekirjoitettu viesti", "ENCRYPTED_MESSAGE": "S\/MIME salattu visti", diff --git a/snappymail/v/0.0.0/app/localization/fr-FR/user.json b/snappymail/v/0.0.0/app/localization/fr-FR/user.json index 192e71452..a7fb60907 100644 --- a/snappymail/v/0.0.0/app/localization/fr-FR/user.json +++ b/snappymail/v/0.0.0/app/localization/fr-FR/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "Signature valide pour %USER%", "ERROR": "Erreur %TYPE%: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "Importer la clef OpenPGP", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "Message signé par S\/MIME", "ENCRYPTED_MESSAGE": "Message chiffré par S\/MIME", diff --git a/snappymail/v/0.0.0/app/localization/hu-HU/user.json b/snappymail/v/0.0.0/app/localization/hu-HU/user.json index 05e81b2ba..e52ba69b0 100644 --- a/snappymail/v/0.0.0/app/localization/hu-HU/user.json +++ b/snappymail/v/0.0.0/app/localization/hu-HU/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "Jó aláírás tőle: %USER%", "ERROR": "%TYPE% hiba: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "OpenPGP kulcs importálás", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME aláírt üzenet", "ENCRYPTED_MESSAGE": "S\/MIME kódolt üzenet", diff --git a/snappymail/v/0.0.0/app/localization/id-ID/user.json b/snappymail/v/0.0.0/app/localization/id-ID/user.json index 3a53d77c5..a80534b95 100644 --- a/snappymail/v/0.0.0/app/localization/id-ID/user.json +++ b/snappymail/v/0.0.0/app/localization/id-ID/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "Tandatangan sah dari user %USER%", "ERROR": "Kesalahan %TYPE%: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "Impor kunci OpenPGP", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "Pesan bertanda-tangan S\/MIME", "ENCRYPTED_MESSAGE": "Pesan terenkripsi S\/MIME", diff --git a/snappymail/v/0.0.0/app/localization/is-IS/user.json b/snappymail/v/0.0.0/app/localization/is-IS/user.json index dab352ccc..51d0207a3 100644 --- a/snappymail/v/0.0.0/app/localization/is-IS/user.json +++ b/snappymail/v/0.0.0/app/localization/is-IS/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "Gild undirritun frá %USER%", "ERROR": "%TYPE% villa: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "Flytja inn OpenPGP-lykil", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "Skeyti undirritað með S\/MIME", "ENCRYPTED_MESSAGE": "Skeyti dulritað með S\/MIME", diff --git a/snappymail/v/0.0.0/app/localization/it-IT/user.json b/snappymail/v/0.0.0/app/localization/it-IT/user.json index 85454dbf7..d8fb8b1dd 100644 --- a/snappymail/v/0.0.0/app/localization/it-IT/user.json +++ b/snappymail/v/0.0.0/app/localization/it-IT/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "Firma valida da %USER%", "ERROR": "Errore di %TYPE%: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "Importa chiave OpenPGP", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "Messaggio firmato con S\/MIME", "ENCRYPTED_MESSAGE": "Messaggio cifrato con S\/MIME", diff --git a/snappymail/v/0.0.0/app/localization/ja-JP/user.json b/snappymail/v/0.0.0/app/localization/ja-JP/user.json index d9d3ca459..77b27be1e 100644 --- a/snappymail/v/0.0.0/app/localization/ja-JP/user.json +++ b/snappymail/v/0.0.0/app/localization/ja-JP/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "%USER%からの正しい署名", "ERROR": "%TYPE% エラー: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "OpenPGPキーをインポート", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME署名済みメッセージ", "ENCRYPTED_MESSAGE": "S\/MIME暗号化メッセージ", diff --git a/snappymail/v/0.0.0/app/localization/ko-KR/user.json b/snappymail/v/0.0.0/app/localization/ko-KR/user.json index 21ec495a4..1c74e40a2 100644 --- a/snappymail/v/0.0.0/app/localization/ko-KR/user.json +++ b/snappymail/v/0.0.0/app/localization/ko-KR/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "%USER%(으)로부터 수신한 양호한 서명", "ERROR": "%TYPE% 오류: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "OpenPGP 키 가져오기", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME로 서명된 메세지입니다.", "ENCRYPTED_MESSAGE": "S\/MIME로 암호화된 메세지입니다.", diff --git a/snappymail/v/0.0.0/app/localization/lt-LT/user.json b/snappymail/v/0.0.0/app/localization/lt-LT/user.json index 131f0ff17..91f6a5883 100644 --- a/snappymail/v/0.0.0/app/localization/lt-LT/user.json +++ b/snappymail/v/0.0.0/app/localization/lt-LT/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "Tinkamas parašas nuo %USER%", "ERROR": "%TYPE% klaida: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "Importuoti OpenPGP raktą", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME pasirašytas pranešimas", "ENCRYPTED_MESSAGE": "S\/MIME šifruotas pranešimas", diff --git a/snappymail/v/0.0.0/app/localization/lv-LV/user.json b/snappymail/v/0.0.0/app/localization/lv-LV/user.json index 457f236dd..9b06be54d 100644 --- a/snappymail/v/0.0.0/app/localization/lv-LV/user.json +++ b/snappymail/v/0.0.0/app/localization/lv-LV/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "Good signature from %USER%", "ERROR": "%TYPE% error: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "Import OpenPGP key", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME signed message", "ENCRYPTED_MESSAGE": "S\/MIME encrypted message", diff --git a/snappymail/v/0.0.0/app/localization/nb-NO/user.json b/snappymail/v/0.0.0/app/localization/nb-NO/user.json index 7c0edcc20..c3bfd3c08 100644 --- a/snappymail/v/0.0.0/app/localization/nb-NO/user.json +++ b/snappymail/v/0.0.0/app/localization/nb-NO/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "Gyldig signatur fra %USER%", "ERROR": "%TYPE%-feil: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "Importer OpenPGP-nøkkel", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME-signert melding", "ENCRYPTED_MESSAGE": "S\/MIME-kryptert melding", diff --git a/snappymail/v/0.0.0/app/localization/nl-NL/user.json b/snappymail/v/0.0.0/app/localization/nl-NL/user.json index fb4f0bf2f..c7b374905 100644 --- a/snappymail/v/0.0.0/app/localization/nl-NL/user.json +++ b/snappymail/v/0.0.0/app/localization/nl-NL/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "Juiste handtekening van %USER%", "ERROR": "%TYPE% foutmelding: %ERROR%", "CREATE_SELF_SIGNED": "Zelfondertekend certificaat aanmaken", - "VALID_UNTIL": "Geldig tot" + "VALID_UNTIL": "Geldig tot", + "PRIVATE_KEY": "Privésleutel" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "Importeer OpenPGP sleutel", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Importeer S\/MIME certificaat", + "CERTIFICATE": "Certificaat", "CERTIFICATES": "S\/MIME Certificaten", "SIGNED_MESSAGE": "S\/MIME ondertekend bericht", "ENCRYPTED_MESSAGE": "S\/MIME versleuteld bericht", diff --git a/snappymail/v/0.0.0/app/localization/pl-PL/user.json b/snappymail/v/0.0.0/app/localization/pl-PL/user.json index 1f1930b27..64d30cb08 100644 --- a/snappymail/v/0.0.0/app/localization/pl-PL/user.json +++ b/snappymail/v/0.0.0/app/localization/pl-PL/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "Poprawnie podpisana przez %USER%", "ERROR": "Błąd %TYPE%: %ERROR%", "CREATE_SELF_SIGNED": "Utwórz samodzielnie podpisany certyfikat", - "VALID_UNTIL": "Ważny do" + "VALID_UNTIL": "Ważny do", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "Importowanie klucza OpenPGP", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Importuj certyfikat S\/MIME", + "CERTIFICATE": "Certificate", "CERTIFICATES": "Certyfikaty S\/MIME", "SIGNED_MESSAGE": "Wiadomość podpisana S\/MIME", "ENCRYPTED_MESSAGE": "Wiadomość zaszyfrowana S\/MIME", diff --git a/snappymail/v/0.0.0/app/localization/pt-BR/user.json b/snappymail/v/0.0.0/app/localization/pt-BR/user.json index b043e1de0..917bb3189 100644 --- a/snappymail/v/0.0.0/app/localization/pt-BR/user.json +++ b/snappymail/v/0.0.0/app/localization/pt-BR/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "Boa assinatura de %USER%", "ERROR": "Erro %TYPE%: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "Importar chave OpenPGP", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "Mensagem assinada com S\/MIME", "ENCRYPTED_MESSAGE": "Mensagem criptografada com S\/MIME", diff --git a/snappymail/v/0.0.0/app/localization/pt-PT/user.json b/snappymail/v/0.0.0/app/localization/pt-PT/user.json index 64d57df1b..cdd061104 100644 --- a/snappymail/v/0.0.0/app/localization/pt-PT/user.json +++ b/snappymail/v/0.0.0/app/localization/pt-PT/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "Boa assinatura de %USER%", "ERROR": "Erro %TYPE%: %ERROR%", "CREATE_SELF_SIGNED": "Criar auto-assinado", - "VALID_UNTIL": "Válido até" + "VALID_UNTIL": "Válido até", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "Importar chave OpenPGP", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Importar certificado S\/MIME", + "CERTIFICATE": "Certificate", "CERTIFICATES": "Certificados S\/MIME", "SIGNED_MESSAGE": "Mensagem assinada com S\/MIME", "ENCRYPTED_MESSAGE": "Mensagem encriptada com S\/MIME", diff --git a/snappymail/v/0.0.0/app/localization/pt/user.json b/snappymail/v/0.0.0/app/localization/pt/user.json index 64d57df1b..cdd061104 100644 --- a/snappymail/v/0.0.0/app/localization/pt/user.json +++ b/snappymail/v/0.0.0/app/localization/pt/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "Boa assinatura de %USER%", "ERROR": "Erro %TYPE%: %ERROR%", "CREATE_SELF_SIGNED": "Criar auto-assinado", - "VALID_UNTIL": "Válido até" + "VALID_UNTIL": "Válido até", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "Importar chave OpenPGP", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Importar certificado S\/MIME", + "CERTIFICATE": "Certificate", "CERTIFICATES": "Certificados S\/MIME", "SIGNED_MESSAGE": "Mensagem assinada com S\/MIME", "ENCRYPTED_MESSAGE": "Mensagem encriptada com S\/MIME", diff --git a/snappymail/v/0.0.0/app/localization/ro-RO/user.json b/snappymail/v/0.0.0/app/localization/ro-RO/user.json index 3b804924a..f6bf1d448 100644 --- a/snappymail/v/0.0.0/app/localization/ro-RO/user.json +++ b/snappymail/v/0.0.0/app/localization/ro-RO/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "Good signature from %USER%", "ERROR": "%TYPE% error: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "Import OpenPGP key", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME signed message", "ENCRYPTED_MESSAGE": "S\/MIME encrypted message", diff --git a/snappymail/v/0.0.0/app/localization/ru-RU/user.json b/snappymail/v/0.0.0/app/localization/ru-RU/user.json index c306d7226..a9b841bc7 100644 --- a/snappymail/v/0.0.0/app/localization/ru-RU/user.json +++ b/snappymail/v/0.0.0/app/localization/ru-RU/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "Подтвержденная сигнатура для %USER%", "ERROR": "%TYPE% ошибка: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "Импорт OpenPGP ключа", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME подписанное сообщение", "ENCRYPTED_MESSAGE": "S\/MIME шифрованное сообщение", diff --git a/snappymail/v/0.0.0/app/localization/sk-SK/user.json b/snappymail/v/0.0.0/app/localization/sk-SK/user.json index 14edc1aab..9f9eab751 100644 --- a/snappymail/v/0.0.0/app/localization/sk-SK/user.json +++ b/snappymail/v/0.0.0/app/localization/sk-SK/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "Good signature from %USER%", "ERROR": "%TYPE% error: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "Importovať kľúč OpenPGP", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "Správa podpísaná s S\/MIME", "ENCRYPTED_MESSAGE": "Správa šifrovaná s S\/MIME", diff --git a/snappymail/v/0.0.0/app/localization/sl-SI/user.json b/snappymail/v/0.0.0/app/localization/sl-SI/user.json index a491aeb58..a62f793f0 100644 --- a/snappymail/v/0.0.0/app/localization/sl-SI/user.json +++ b/snappymail/v/0.0.0/app/localization/sl-SI/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "Dober podpis od %USER%", "ERROR": "%TYPE% napaka: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "Uvoz OpenPGP ključa", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "Sporočilo, podpisano z S\/MIME", "ENCRYPTED_MESSAGE": "Sporočilo, šifrirano z S\/MIME", diff --git a/snappymail/v/0.0.0/app/localization/sv-SE/user.json b/snappymail/v/0.0.0/app/localization/sv-SE/user.json index 52941c9ed..4041f143c 100644 --- a/snappymail/v/0.0.0/app/localization/sv-SE/user.json +++ b/snappymail/v/0.0.0/app/localization/sv-SE/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "Godkänd signatur för %USER%", "ERROR": "%TYPE%-fel: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "Import av OpenPGP-nyckel", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME-signerat meddelande", "ENCRYPTED_MESSAGE": "S\/MIME-krypterat meddelande", diff --git a/snappymail/v/0.0.0/app/localization/tr-TR/user.json b/snappymail/v/0.0.0/app/localization/tr-TR/user.json index 93e7c1e88..6d0e83dd6 100644 --- a/snappymail/v/0.0.0/app/localization/tr-TR/user.json +++ b/snappymail/v/0.0.0/app/localization/tr-TR/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "Geçerli imza %USER%", "ERROR": "%TYPE% hatası: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "OpenPGP key'i içe aktar", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME imzalı mesaj", "ENCRYPTED_MESSAGE": "S\/MIME şifreli mesaj", diff --git a/snappymail/v/0.0.0/app/localization/uk-UA/user.json b/snappymail/v/0.0.0/app/localization/uk-UA/user.json index a7bd28f5b..b4742ae0d 100644 --- a/snappymail/v/0.0.0/app/localization/uk-UA/user.json +++ b/snappymail/v/0.0.0/app/localization/uk-UA/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "Підтверджена сигнатура для %USER%", "ERROR": "%TYPE% помилка: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "Імпорт OpenPGP ключа", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "S\/MIME підписане повідомлення", "ENCRYPTED_MESSAGE": "S\/MIME шифроване повідомлення", diff --git a/snappymail/v/0.0.0/app/localization/vi-VN/user.json b/snappymail/v/0.0.0/app/localization/vi-VN/user.json index dd617e949..358270e2d 100644 --- a/snappymail/v/0.0.0/app/localization/vi-VN/user.json +++ b/snappymail/v/0.0.0/app/localization/vi-VN/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "Chữ ký ổn từ %USER%", "ERROR": "Lỗi %TYPE%: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "Nhập mật mã OpenPGP", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "Thư đã được ký xác nhận bằng mã S\/MIME", "ENCRYPTED_MESSAGE": "Thư đã được mã hóa bởi S\/MIME", diff --git a/snappymail/v/0.0.0/app/localization/zh-CN/user.json b/snappymail/v/0.0.0/app/localization/zh-CN/user.json index 325c7e3b5..60edd171f 100644 --- a/snappymail/v/0.0.0/app/localization/zh-CN/user.json +++ b/snappymail/v/0.0.0/app/localization/zh-CN/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "来自 %USER% 的可用签名", "ERROR": "%TYPE% 错误: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "导入 OpenPGP 密钥", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "由 S\/MIME 签名", "ENCRYPTED_MESSAGE": "由 S\/MIME 加密", diff --git a/snappymail/v/0.0.0/app/localization/zh-TW/user.json b/snappymail/v/0.0.0/app/localization/zh-TW/user.json index 54a15fdee..907397303 100644 --- a/snappymail/v/0.0.0/app/localization/zh-TW/user.json +++ b/snappymail/v/0.0.0/app/localization/zh-TW/user.json @@ -282,7 +282,8 @@ "GOOD_SIGNATURE": "來自「%USER%」的良好簽署", "ERROR": "%TYPE% 錯誤: %ERROR%", "CREATE_SELF_SIGNED": "Create self-signed", - "VALID_UNTIL": "Valid until" + "VALID_UNTIL": "Valid until", + "PRIVATE_KEY": "Private key" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "匯入 OpenPGP 金鑰", @@ -303,6 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", + "CERTIFICATE": "Certificate", "CERTIFICATES": "S\/MIME Certificates", "SIGNED_MESSAGE": "已透過 S\/MIME 簽署郵件", "ENCRYPTED_MESSAGE": "已透過 S\/MIME 加密郵件", diff --git a/snappymail/v/0.0.0/app/templates/Views/User/PopupsIdentity.html b/snappymail/v/0.0.0/app/templates/Views/User/PopupsIdentity.html index 7dddd40cc..57c451116 100644 --- a/snappymail/v/0.0.0/app/templates/Views/User/PopupsIdentity.html +++ b/snappymail/v/0.0.0/app/templates/Views/User/PopupsIdentity.html @@ -89,11 +89,11 @@
S/MIME
- +
- +
From 37dee0e78eaee01426a6c5959f2243ab461d8048 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Tue, 27 Feb 2024 23:04:32 +0100 Subject: [PATCH 047/110] v2.35.2 --- CHANGELOG.md | 19 +++++++++++++++ README.md | 24 +++++++++---------- dev/Styles/User/FolderList.less | 18 +++++++------- integrations/cloudron/DESCRIPTION.md | 2 +- integrations/cloudron/Dockerfile | 2 +- .../nextcloud/snappymail/appinfo/info.xml | 2 +- integrations/virtualmin/snappymail.pl | 2 +- package.json | 2 +- 8 files changed, 44 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7bddafb59..ce8d9390d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,22 @@ +## 2.35.2 – 2024-02-26 + +### Added +- GnuPG error handling +- Missing strings for localization inside identity popup (Cryptography > S/MIME) + [#1458](https://github.com/the-djmaze/snappymail/issues/1458) + +### Changed +- Update Portuguese by @ner00 + +### Fixed +- Verify S/MIME signatures got broken allong the way while implementing this +- Drop support for gnupg PECL extension as it fails with "no passphrase" issues +- Error 352 when getting Filters + [#1455](https://github.com/the-djmaze/snappymail/issues/1455) +- Nextcloud SetPassword(): Argument #1 must be of type SensitiveString, string given + [#1456](https://github.com/the-djmaze/snappymail/issues/1456) + + ## 2.35.1 – 2024-02-26 ### Added diff --git a/README.md b/README.md index b582d07b4..1c68bed22 100644 --- a/README.md +++ b/README.md @@ -140,26 +140,26 @@ RainLoop 1.17 vs SnappyMail |js/* |RainLoop |Snappy | |--------------- |--------: |--------: | -|admin.js |2.170.153 | 81.641 | -|app.js |4.207.787 | 426.852 | +|admin.js |2.170.153 | 82.445 | +|app.js |4.207.787 | 429.565 | |boot.js | 868.735 | 4.142 | -|libs.js | 658.812 | 192.625 | +|libs.js | 658.812 | 192.786 | |sieve.js | 0 | 84.707 | |polyfills.js | 334.608 | 0 | |serviceworker.js | 0 | 285 | -|TOTAL |8.240.095 | 790.252 | +|TOTAL |8.240.095 | 793.930 | |js/min/* |RainLoop |Snappy |RL gzip |SM gzip |RL brotli |SM brotli | |--------------- |--------: |--------: |------: |------: |--------: |--------: | -|admin.min.js | 256.831 | 40.142 | 73.606 | 13.445 | 60.877 | 12.047 | -|app.min.js | 515.367 | 193.738 |139.456 | 65.570 |110.485 | 56.281 | +|admin.min.js | 256.831 | 40.573 | 73.606 | 13.585 | 60.877 | 12.188 | +|app.min.js | 515.367 | 195.013 |139.456 | 66.135 |110.485 | 56.623 | |boot.min.js | 84.659 | 2.084 | 26.998 | 1.202 | 23.643 | 1.003 | -|libs.min.js | 584.772 | 92.664 |180.901 | 34.414 |155.182 | 30.850 | +|libs.min.js | 584.772 | 92.746 |180.901 | 34.452 |155.182 | 30.890 | |sieve.min.js | 0 | 41.164 | 0 | 10.365 | 0 | 9.359 | |polyfills.min.js | 32.837 | 0 | 11.406 | 0 | 10.175 | 0 | -|TOTAL user |1.217.635 | 288.486 |358.761 |101.186 |299.485 | 88.134 | -|TOTAL user+sieve |1.217.635 | 329.650 |358.761 |111.551 |299.485 | 97.493 | -|TOTAL admin | 959.099 | 134.890 |292.911 | 49.061 |249.877 | 43.900 | +|TOTAL user |1.217.635 | 289.843 |358.761 |101.789 |299.485 | 88.516 | +|TOTAL user+sieve |1.217.635 | 331.007 |358.761 |112.154 |299.485 | 97.875 | +|TOTAL admin | 959.099 | 135.403 |292.911 | 49.239 |249.877 | 44.081 | For a user it is around 69% smaller and faster than traditional RainLoop. @@ -188,8 +188,8 @@ For a user it is around 69% smaller and faster than traditional RainLoop. |css/* |RainLoop |Snappy |RL gzip |SM gzip |SM brotli | |------------ |-------: |------: |------: |------: |--------: | -|app.css | 340.331 | 84.435 | 46.946 | 17.612 | 15.091 | -|app.min.css | 274.947 | 67.825 | 39.647 | 15.526 | 13.540 | +|app.css | 340.331 | 84.472 | 46.946 | 17.622 | 15.112 | +|app.min.css | 274.947 | 67.857 | 39.647 | 15.537 | 13.549 | |boot.css | | 1.326 | | 664 | 545 | |boot.min.css | | 1.071 | | 590 | 474 | |admin.css | | 30.576 | | 7.013 | 6.096 | diff --git a/dev/Styles/User/FolderList.less b/dev/Styles/User/FolderList.less index f1e5b243a..6157ec2e1 100644 --- a/dev/Styles/User/FolderList.less +++ b/dev/Styles/User/FolderList.less @@ -65,6 +65,7 @@ overflow: hidden; overflow-y: auto; min-width: 100px; + color: var(--folders-color, #333); } hr { @@ -77,22 +78,18 @@ white-space: nowrap; a { - display: block; - position: relative; - z-index: 1; - line-height: 34px; background-color: transparent; - vertical-align: middle; - color: var(--folders-disabled-color, #666); border-left: 3px solid transparent; - + color: var(--folders-color, #333); + display: block; + line-height: 34px; padding: 0 2em 0 @folderItemPadding; - + position: relative; text-decoration: none; + vertical-align: middle; + z-index: 1; &.selectable { - - color: var(--folders-color, #333); cursor: pointer; &:hover { @@ -115,6 +112,7 @@ } } &:not(.selectable) { + color: var(--folders-disabled-color, #666); cursor: default; font-style: italic; } diff --git a/integrations/cloudron/DESCRIPTION.md b/integrations/cloudron/DESCRIPTION.md index 587cb3c7c..668ac8df4 100644 --- a/integrations/cloudron/DESCRIPTION.md +++ b/integrations/cloudron/DESCRIPTION.md @@ -1,4 +1,4 @@ -This app packages SnappyMail 2.35.1. +This app packages SnappyMail 2.35.2. SnappyMail is a simple, modern, lightweight & fast web-based email client. diff --git a/integrations/cloudron/Dockerfile b/integrations/cloudron/Dockerfile index cd1b147c6..29f540199 100644 --- a/integrations/cloudron/Dockerfile +++ b/integrations/cloudron/Dockerfile @@ -4,7 +4,7 @@ RUN mkdir -p /app/code WORKDIR /app/code # If you change the extraction below, be sure to test on scaleway -VERSION=2.35.1 +VERSION=2.35.2 RUN wget https://github.com/the-djmaze/snappymail/releases/download/v${VERSION}/snappymail-${VERSION}.zip -O /tmp/snappymail.zip && \ unzip /tmp/snappymail.zip -d /app/code && \ rm /tmp/snappymail.zip && \ diff --git a/integrations/nextcloud/snappymail/appinfo/info.xml b/integrations/nextcloud/snappymail/appinfo/info.xml index 8264e0bff..c6e1b1a84 100644 --- a/integrations/nextcloud/snappymail/appinfo/info.xml +++ b/integrations/nextcloud/snappymail/appinfo/info.xml @@ -3,7 +3,7 @@ snappymail SnappyMail SnappyMail Webmail - 2.35.1 + 2.35.2 agpl SnappyMail, RainLoop Team, Nextgen-Networks, Tab Fitts, Nathan Kinkade, Pierre-Alain Bandinelli Date: Tue, 27 Feb 2024 23:08:42 +0100 Subject: [PATCH 048/110] fix changelog --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ce8d9390d..26981f208 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,6 @@ - Update Portuguese by @ner00 ### Fixed -- Verify S/MIME signatures got broken allong the way while implementing this - Drop support for gnupg PECL extension as it fails with "no passphrase" issues - Error 352 when getting Filters [#1455](https://github.com/the-djmaze/snappymail/issues/1455) From b3893f71642599b037d0da88c83269a2ca7ed85d Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Tue, 27 Feb 2024 23:16:47 +0100 Subject: [PATCH 049/110] Resolve #1461 --- snappymail/v/0.0.0/app/libraries/snappymail/http/request.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/http/request.php b/snappymail/v/0.0.0/app/libraries/snappymail/http/request.php index 8b4a7e684..0bdf9468e 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/http/request.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/http/request.php @@ -7,10 +7,11 @@ abstract class Request const /** * Authentication + * These are bitwise options */ AUTH_BASIC = 1, AUTH_DIGEST = 2, - AUTH_BEARER = 3; + AUTH_BEARER = 4; public $timeout = 5, // timeout in seconds. From a95ecf6133df110d04954ba6c1b1981e3566c89e Mon Sep 17 00:00:00 2001 From: lmperfis Date: Wed, 28 Feb 2024 14:18:01 +0000 Subject: [PATCH 050/110] Update pt/pt-PT translation --- snappymail/v/0.0.0/app/localization/pt-PT/user.json | 4 ++-- snappymail/v/0.0.0/app/localization/pt/user.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/snappymail/v/0.0.0/app/localization/pt-PT/user.json b/snappymail/v/0.0.0/app/localization/pt-PT/user.json index cdd061104..603d28cab 100644 --- a/snappymail/v/0.0.0/app/localization/pt-PT/user.json +++ b/snappymail/v/0.0.0/app/localization/pt-PT/user.json @@ -283,7 +283,7 @@ "ERROR": "Erro %TYPE%: %ERROR%", "CREATE_SELF_SIGNED": "Criar auto-assinado", "VALID_UNTIL": "Válido até", - "PRIVATE_KEY": "Private key" + "PRIVATE_KEY": "Chave privada" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "Importar chave OpenPGP", @@ -304,7 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Importar certificado S\/MIME", - "CERTIFICATE": "Certificate", + "CERTIFICATE": "Certificado", "CERTIFICATES": "Certificados S\/MIME", "SIGNED_MESSAGE": "Mensagem assinada com S\/MIME", "ENCRYPTED_MESSAGE": "Mensagem encriptada com S\/MIME", diff --git a/snappymail/v/0.0.0/app/localization/pt/user.json b/snappymail/v/0.0.0/app/localization/pt/user.json index cdd061104..603d28cab 100644 --- a/snappymail/v/0.0.0/app/localization/pt/user.json +++ b/snappymail/v/0.0.0/app/localization/pt/user.json @@ -283,7 +283,7 @@ "ERROR": "Erro %TYPE%: %ERROR%", "CREATE_SELF_SIGNED": "Criar auto-assinado", "VALID_UNTIL": "Válido até", - "PRIVATE_KEY": "Private key" + "PRIVATE_KEY": "Chave privada" }, "OPENPGP": { "POPUP_IMPORT_TITLE": "Importar chave OpenPGP", @@ -304,7 +304,7 @@ }, "SMIME": { "POPUP_IMPORT_TITLE": "Importar certificado S\/MIME", - "CERTIFICATE": "Certificate", + "CERTIFICATE": "Certificado", "CERTIFICATES": "Certificados S\/MIME", "SIGNED_MESSAGE": "Mensagem assinada com S\/MIME", "ENCRYPTED_MESSAGE": "Mensagem encriptada com S\/MIME", From 57003ab4b8b09003fe022250613ac172ddaca888 Mon Sep 17 00:00:00 2001 From: Sergey Mosin Date: Wed, 28 Feb 2024 09:47:39 -0500 Subject: [PATCH 051/110] compact-composer plugin v1.0.0 --- plugins/compact-composer/css/composer.css | 87 + plugins/compact-composer/index.php | 22 + .../compact-composer/js/CompactComposer.js | 967 ++++ plugins/compact-composer/js/parsel.js | 413 ++ plugins/compact-composer/js/squire-raw.js | 4102 +++++++++++++++++ .../screenshots/Screenshot1.png | Bin 0 -> 90564 bytes .../screenshots/Screenshot2.png | Bin 0 -> 62154 bytes .../screenshots/Screenshot3.png | Bin 0 -> 63201 bytes .../screenshots/Screenshot4.png | Bin 0 -> 60321 bytes .../screenshots/Screenshot5.png | Bin 0 -> 61356 bytes .../screenshots/Screenshot6.png | Bin 0 -> 93133 bytes .../templates/PopupsCompose.html | 238 + 12 files changed, 5829 insertions(+) create mode 100644 plugins/compact-composer/css/composer.css create mode 100644 plugins/compact-composer/index.php create mode 100644 plugins/compact-composer/js/CompactComposer.js create mode 100644 plugins/compact-composer/js/parsel.js create mode 100644 plugins/compact-composer/js/squire-raw.js create mode 100644 plugins/compact-composer/screenshots/Screenshot1.png create mode 100644 plugins/compact-composer/screenshots/Screenshot2.png create mode 100644 plugins/compact-composer/screenshots/Screenshot3.png create mode 100644 plugins/compact-composer/screenshots/Screenshot4.png create mode 100644 plugins/compact-composer/screenshots/Screenshot5.png create mode 100644 plugins/compact-composer/screenshots/Screenshot6.png create mode 100644 plugins/compact-composer/templates/PopupsCompose.html diff --git a/plugins/compact-composer/css/composer.css b/plugins/compact-composer/css/composer.css new file mode 100644 index 000000000..3b7cb6f55 --- /dev/null +++ b/plugins/compact-composer/css/composer.css @@ -0,0 +1,87 @@ +.squire-toolbar { + padding-top: 4px; + padding-bottom: 0; + overflow: visible; + z-index: 200; + white-space: normal; + min-height: auto; +} + +.squire-toolbar > .btn-group { + margin-bottom: 4px; +} + +.squire-toolbar > .btn-group > a.btn, +.squire-toolbar button.btn, +.squire-toolbar select.btn { + line-height: 20px; + padding-top: 4px; + padding-bottom: 4px; + min-height: 24px; +} + +.squire-toolbar-menu-item { + display: flex; + align-items: center; + gap: .25em; + margin: .1em !important; + cursor: pointer; + padding: .25em; +} + +.squire-toolbar-menu-item.active { + background-color: rgba(128, 128, 128, .1); +} + +.squire-toolbar-menu-item:hover { + background-color: rgba(128, 128, 128, .2); +} + +.squire-toolbar-svg-icon { + display: block; +} + +.squire2-mode-wysiwyg .squire-plain, +.squire2-mode-source .squire-wysiwyg, +.squire2-mode-plain .squire-wysiwyg { + display: none; +} + +.squire2-mode-source .squire-plain, +.squire2-mode-plain .squire-plain { + display: block; +} + +.squire-toolbar > .squire-toolbar-menu-wrap:last-child { + float: right; +} + +.squire-toolbar.mode-plain .squire-html-mode-item { + display: none; +} + +#V-PopupsCompose .attachmentAreaParent.compact { + height: auto; + min-height: auto; + padding: 0; + overflow: auto; + flex: 1 0 auto; + max-height: 12em; + margin: 0; +} + +#V-PopupsCompose .compact > .b-attachment-place { + position: static; + display: none; + margin: .375em; + line-height: 4em; +} + +#V-PopupsCompose .compact > .b-attachment-place.dragAndDropOver { + display: block; +} + +#V-PopupsCompose .compact .attachmentList { + margin: 0; + padding: 0; +} \ No newline at end of file diff --git a/plugins/compact-composer/index.php b/plugins/compact-composer/index.php new file mode 100644 index 000000000..6568791ed --- /dev/null +++ b/plugins/compact-composer/index.php @@ -0,0 +1,22 @@ +addTemplate('templates/PopupsCompose.html'); + $this->addCss('css/composer.css'); + $this->addJs('js/squire-raw.js'); + $this->addJs('js/parsel.js'); + $this->addJs('js/CompactComposer.js'); + } +} diff --git a/plugins/compact-composer/js/CompactComposer.js b/plugins/compact-composer/js/CompactComposer.js new file mode 100644 index 000000000..503d00c9e --- /dev/null +++ b/plugins/compact-composer/js/CompactComposer.js @@ -0,0 +1,967 @@ +/* eslint max-len: 0 */ +(win => { + + addEventListener('rl-view-model.create', e => { + if (e.detail.viewModelTemplateID === 'PopupsCompose') { + // There is a better way to do this probably, + // but we need this for drag and drop to work + e.detail.attachmentsArea = e.detail.bodyArea; + } + }); + + const doc = win.document; + const rl = win.rl; + + const + removeElements = 'HEAD,LINK,META,NOSCRIPT,SCRIPT,TEMPLATE,TITLE', + allowedElements = 'A,B,BLOCKQUOTE,BR,DIV,EM,FONT,H1,H2,H3,H4,H5,H6,HR,I,IMG,LI,OL,P,SPAN,STRONG,TABLE,TD,TH,TR,U,UL', + allowedAttributes = 'abbr,align,background,bgcolor,border,cellpadding,cellspacing,class,color,colspan,dir,face,frame,height,href,hspace,id,lang,rowspan,rules,scope,size,src,style,target,type,usemap,valign,vspace,width'.split(','), + + // TODO: labels translations + i18n = (str, def) => rl.i18n(str) || def, + + ctrlKey = shortcuts.getMetaKey() + ' + ', + + createElement = name => doc.createElement(name), + + tpl = createElement('template'), + + trimLines = html => html.trim().replace(/^(
\s*\s*<\/div>)+/, '').trim(), + htmlToPlain = html => rl.Utils.htmlToPlain(html).trim(), + plainToHtml = text => rl.Utils.plainToHtml(text), + + getFragmentOfChildren = parent => { + let frag = doc.createDocumentFragment(); + frag.append(...parent.childNodes); + return frag; + }, + + /** + * @param {Array} data + * @param {String} prop + */ + getByProp = (data, prop) => { + for (let i = 0; i < data.length; i++) { + const outer = data[i]; + if (outer.hasOwnProperty(prop)) { + return outer; + } + if (outer.items && Array.isArray(outer.items)) { + const item = outer.items.find(item => item.prop === prop); + if (item) { + return item; + } + } + } + throw new Error('item with prop ' + prop + ' not found'); + }, + + SquireDefaultConfig = { + /* + addLinks: true // allow_smart_html_links + */ + sanitizeToDOMFragment: (html) => { + tpl.innerHTML = (html || '') + .replace(/<\/?(BODY|HTML)[^>]*>/gi, '') + .replace(//g, '') + .replace(/]*>\s*<\/span>/gi, '') + .trim(); + tpl.querySelectorAll('a:empty,span:empty').forEach(el => el.remove()); + return tpl.content; + } + }, + + pasteSanitizer = (event) => { + const frag = event.detail.fragment; + frag.querySelectorAll('a:empty,span:empty').forEach(el => el.remove()); + frag.querySelectorAll(removeElements).forEach(el => el.remove()); + frag.querySelectorAll('*').forEach(el => { + if (!el.matches(allowedElements)) { + el.replaceWith(getFragmentOfChildren(el)); + } else if (el.hasAttributes()) { + [...el.attributes].forEach(attr => { + let name = attr.name.toLowerCase(); + if (!allowedAttributes.includes(name)) { + el.removeAttribute(name); + } + }); + } + }); + }, + + pasteImageHandler = (e, squire) => { + + const items = [...e.detail.clipboardData.items]; + const imageItems = items.filter((item) => /image/.test(item.type)); + if (!imageItems.length) { + return false; + } + let reader = new FileReader(); + reader.onload = (loadEvent) => { + squire.insertImage(loadEvent.target.result); + }; + reader.readAsDataURL(imageItems[0].getAsFile()); + }; + + + class CompactComposer { + constructor(container) { + const + plain = createElement('textarea'), + wysiwyg = createElement('div'), + toolbar = createElement('div'), + squire = new win.Squire2(wysiwyg, SquireDefaultConfig); + + this.container = container; + + toolbar.className = 'squire-toolbar btn-toolbar'; + const actions = this.#makeActions(squire, toolbar); + + plain.className = 'squire-plain'; + wysiwyg.className = 'squire-wysiwyg'; + wysiwyg.dir = 'auto'; + this.mode = ''; // 'plain' | 'wysiwyg' + this.squire = squire; + this.plain = plain; + this.wysiwyg = wysiwyg; + this.toolbar = toolbar; + + this.squire.addEventListener('willPaste', pasteSanitizer); + this.squire.addEventListener('pasteImage', (e) => { + pasteImageHandler(e, squire); + }); + +// squire.addEventListener('focus', () => shortcuts.off()); +// squire.addEventListener('blur', () => shortcuts.on()); + + container.append(toolbar, wysiwyg, plain); + + const fontFamilySelect = getByProp(actions, 'fontFamily').element; + + const fontSizeAction = getByProp(actions, 'fontSize'); + + /** + * @param {string} fontName + * @return {string} + */ + const normalizeFontName = (fontName) => fontName.trim().replace(/(^["']*|["']*$)/g, '').trim().toLowerCase(); + + /** @type {string[]} - lower cased array of available font families*/ + const fontFamiliesLowerCase = Object.values(fontFamilySelect.options).map(option => option.value.toLowerCase()); + + /** + * A theme might have CSS like div.squire-wysiwyg[contenteditable="true"] { + * font-family: 'Times New Roman', Times, serif; } + * so let's find the best match squire.getRoot()'s font + * it will also help to properly handle generic font names like 'sans-serif' + * @type {number} + */ + let defaultFontFamilyIndex = 0; + const squireRootFonts = getComputedStyle(squire.getRoot()).fontFamily.split(',').map(normalizeFontName); + fontFamiliesLowerCase.some((family, index) => { + const matchFound = family.split(',').some(availableFontName => { + const normalizedFontName = normalizeFontName(availableFontName); + return squireRootFonts.some(squireFontName => squireFontName === normalizedFontName); + }); + if (matchFound) { + defaultFontFamilyIndex = index; + } + return matchFound; + }); + + /** + * Instead of comparing whole 'font-family' strings, + * we are going to look for individual font names, because we might be + * editing a Draft started in another email client for example + * + * @type {Object.} + */ + const fontNamesMap = {}; + /** + * @param {string} fontFamily + * @param {number} index + */ + const processFontFamilyString = (fontFamily, index) => { + fontFamily.split(',').forEach(fontName => { + const key = normalizeFontName(fontName); + if (fontNamesMap[key] === undefined) { + fontNamesMap[key] = index; + } + }); + }; + // first deal with the default font family + processFontFamilyString(fontFamiliesLowerCase[defaultFontFamilyIndex], defaultFontFamilyIndex); + // and now with the rest of the font families + fontFamiliesLowerCase.forEach((fontFamily, index) => { + if (index !== defaultFontFamilyIndex) { + processFontFamilyString(fontFamily, index); + } + }); + + // ----- + + let ignoreNextSelectEvent = false; + + squire.addEventListener('pathChange', e => { + + const tokensMap = this.buildTokensMap(e.detail); + + if (tokensMap.has('__selection__')) { + ignoreNextSelectEvent = false; + return; + } + this.indicators.forEach((indicator) => { + indicator.element.classList.toggle('active', indicator.selectors.some(selector => tokensMap.has(selector))); + }); + + let familySelectedIndex = defaultFontFamilyIndex; + const fontFamily = tokensMap.get('__font_family__'); + if (fontFamily) { + familySelectedIndex = -1; // show empty select if we don't know the font + const fontNames = fontFamily.split(','); + for (let i = 0; i < fontNames.length; i++) { + const index = fontNamesMap[normalizeFontName(fontNames[i])]; + if (index !== undefined) { + familySelectedIndex = index; + break; + } + } + } + fontFamilySelect.selectedIndex = familySelectedIndex; + + let sizeSelectedIndex = fontSizeAction.defaultValueIndex; + const fontSize = tokensMap.get('__font_size__'); + if (fontSize) { + // -1 is ok because it will just show a blank
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
+ + + +
+ +
+ +
+ +
+ +
+ + + +
+ + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+ + +
    +
  • +
    + +
    +
    +
    +
    + × +
    + +
    +
  • +
+
From 6e56808a0dd73b0c2c896bbc74ca86d4765c7089 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Wed, 28 Feb 2024 19:36:57 +0100 Subject: [PATCH 052/110] Resolve #1462 --- snappymail/v/0.0.0/app/libraries/MailSo/Imap/BodyStructure.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Imap/BodyStructure.php b/snappymail/v/0.0.0/app/libraries/MailSo/Imap/BodyStructure.php index d619b13cb..b7e72b890 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Imap/BodyStructure.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Imap/BodyStructure.php @@ -213,7 +213,7 @@ class BodyStructure implements \JsonSerializable if (!$aParts) { $gEncryptedParts = $this->SearchByContentType('multipart/encrypted'); foreach ($gEncryptedParts as $oPart) { - if ($oPart->isPgpEncrypted() && $oPart->SubParts()[1]->isInline()) { + if ($oPart->isPgpEncrypted()) { return array($oPart->SubParts()[1]); } } From df963e353705981adc20d9cc71760c8b9851bc55 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Wed, 28 Feb 2024 19:45:14 +0100 Subject: [PATCH 053/110] Fix decrypt error message --- dev/View/User/MailBox/MessageView.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/View/User/MailBox/MessageView.js b/dev/View/User/MailBox/MessageView.js index 70c113131..29331d771 100644 --- a/dev/View/User/MailBox/MessageView.js +++ b/dev/View/User/MailBox/MessageView.js @@ -587,7 +587,7 @@ export class MailMessageView extends AbstractViewRight { } } else { // TODO: translate - throw 'Decryption failed, canceled or not possible'; + throw Error('Decryption failed, canceled or not possible'); } }) .catch(e => { From 14bee5d3bda241ed466379e89f950e16f64b7f7d Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Wed, 28 Feb 2024 19:46:21 +0100 Subject: [PATCH 054/110] `new Error()` to `Error()` --- dev/Common/Translator.js | 2 +- dev/DAV/JCard.js | 12 ++++++------ dev/DAV/VCardProperty.js | 2 +- dev/External/ko.js | 2 +- dev/Knoin/AbstractModel.js | 2 +- dev/Model/AbstractCollection.js | 2 +- dev/Sieve/Model/Abstract.js | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/dev/Common/Translator.js b/dev/Common/Translator.js index 0b609a99d..f67aae246 100644 --- a/dev/Common/Translator.js +++ b/dev/Common/Translator.js @@ -211,7 +211,7 @@ export const script.remove(); resolve(); }; - script.onerror = () => reject(new Error('Language '+language+' failed')); + script.onerror = () => reject(Error('Language '+language+' failed')); script.src = langLink(language, admin); // script.async = true; doc.head.append(script); diff --git a/dev/DAV/JCard.js b/dev/DAV/JCard.js index 56c247e67..1dad7d8c8 100644 --- a/dev/DAV/JCard.js +++ b/dev/DAV/JCard.js @@ -15,7 +15,7 @@ export class JCard { if (input) { // read from jCard if (typeof input !== 'object') { - throw new Error('error reading vcard') + throw Error('error reading vcard') } this.parseFromJCard(input) } @@ -87,7 +87,7 @@ export class JCard { arg = new VCardProperty(String(arg), value, params, type); } if (!(arg instanceof VCardProperty)) { - throw new Error('invalid argument of VCard.set(), expects string arguments or a VCardProperty'); + throw Error('invalid argument of VCard.set(), expects string arguments or a VCardProperty'); } let field = arg.getField(); this.props.set(field, [arg]); @@ -101,7 +101,7 @@ export class JCard { arg = new VCardProperty(String(arg), value, params, type); } if (!(arg instanceof VCardProperty)) { - throw new Error('invalid argument of VCard.add(), expects string arguments or a VCardProperty'); + throw Error('invalid argument of VCard.add(), expects string arguments or a VCardProperty'); } // VCardProperty arguments let field = arg.getField(); @@ -125,14 +125,14 @@ export class JCard { else if (arg instanceof VCardProperty) { let propArray = this.props.get(arg.getField()); if (!(propArray === null || propArray === void 0 ? void 0 : propArray.includes(arg))) - throw new Error("Attempted to remove VCardProperty VCard does not have: ".concat(arg)); + throw Error("Attempted to remove VCardProperty VCard does not have: ".concat(arg)); propArray.splice(propArray.indexOf(arg), 1); if (propArray.length === 0) this.props.delete(arg.getField()); } // incorrect arguments else - throw new Error('invalid argument of VCard.remove(), expects ' + + throw Error('invalid argument of VCard.remove(), expects ' + 'string and optional param filter or a VCardProperty'); } @@ -202,7 +202,7 @@ export class JCard { parseFullName(options) { let n = this.getOne('n'); if (n === undefined) { - throw new Error('\'fn\' VCardProperty not present in card, cannot parse full name'); + throw Error('\'fn\' VCardProperty not present in card, cannot parse full name'); } let fnString = ''; // Position in n -> position in fn diff --git a/dev/DAV/VCardProperty.js b/dev/DAV/VCardProperty.js index 59c290e67..30fd8813e 100644 --- a/dev/DAV/VCardProperty.js +++ b/dev/DAV/VCardProperty.js @@ -55,7 +55,7 @@ export class VCardProperty { } // invalid property else { - throw new Error('invalid Property constructor'); + throw Error('invalid Property constructor'); } } diff --git a/dev/External/ko.js b/dev/External/ko.js index 53425caa9..7022c646f 100644 --- a/dev/External/ko.js +++ b/dev/External/ko.js @@ -107,7 +107,7 @@ Object.assign(ko.bindingHandlers, { const command = fValueAccessor(); if (!command || !command.canExecute) { - throw new Error('Value should be a command'); + throw Error('Value should be a command'); } ko.bindingHandlers['FORM'==element.nodeName ? 'submit' : 'click'].init( diff --git a/dev/Knoin/AbstractModel.js b/dev/Knoin/AbstractModel.js index 724cf3dce..0fb0b2d90 100644 --- a/dev/Knoin/AbstractModel.js +++ b/dev/Knoin/AbstractModel.js @@ -27,7 +27,7 @@ export class AbstractModel { constructor() { /* if (new.target === AbstractModel) { - throw new Error("Can't instantiate AbstractModel!"); + throw Error("Can't instantiate AbstractModel!"); } */ Object.defineProperty(this, 'disposables', {value: []}); diff --git a/dev/Model/AbstractCollection.js b/dev/Model/AbstractCollection.js index 35c70413c..e4a9d0910 100644 --- a/dev/Model/AbstractCollection.js +++ b/dev/Model/AbstractCollection.js @@ -5,7 +5,7 @@ export class AbstractCollectionModel extends Array constructor() { /* if (new.target === AbstractCollectionModel) { - throw new Error("Can't instantiate AbstractCollectionModel!"); + throw Error("Can't instantiate AbstractCollectionModel!"); } */ super(); diff --git a/dev/Sieve/Model/Abstract.js b/dev/Sieve/Model/Abstract.js index 84c534ee0..3130fd175 100644 --- a/dev/Sieve/Model/Abstract.js +++ b/dev/Sieve/Model/Abstract.js @@ -22,7 +22,7 @@ export class AbstractModel { constructor() { /* if (new.target === AbstractModel) { - throw new Error("Can't instantiate AbstractModel!"); + throw Error("Can't instantiate AbstractModel!"); } */ Object.defineProperty(this, 'disposables', {value: []}); From 593fd4c41d2f21f0de852436ce96f9970744dce8 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Wed, 28 Feb 2024 20:09:16 +0100 Subject: [PATCH 055/110] Resolve #1463 --- snappymail/v/0.0.0/themes/NextcloudV25+/styles.css | 1 + 1 file changed, 1 insertion(+) diff --git a/snappymail/v/0.0.0/themes/NextcloudV25+/styles.css b/snappymail/v/0.0.0/themes/NextcloudV25+/styles.css index 7cb38a5a7..d86fd5b1d 100644 --- a/snappymail/v/0.0.0/themes/NextcloudV25+/styles.css +++ b/snappymail/v/0.0.0/themes/NextcloudV25+/styles.css @@ -1322,6 +1322,7 @@ html.rl-left-panel-disabled #rl-app .b-folders .b-toolbar { #rl-app .b-folders .b-content { top: 60px; bottom: 162px; + color: unset; } #rl-app .b-folders .b-content.show-on-panel-disabled { From 490465cbbf6357de7ec42b2e84ec9a340490530f Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Wed, 28 Feb 2024 20:12:15 +0100 Subject: [PATCH 056/110] Show url for #1466 --- plugins/compact-composer/index.php | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/compact-composer/index.php b/plugins/compact-composer/index.php index 6568791ed..b165bddaf 100644 --- a/plugins/compact-composer/index.php +++ b/plugins/compact-composer/index.php @@ -5,6 +5,7 @@ class CompactComposerPlugin extends \RainLoop\Plugins\AbstractPlugin const NAME = 'Compact Composer', AUTHOR = 'Sergey Mosin', + URL = 'https://github.com/the-djmaze/snappymail/pull/1466', VERSION = '1.0.0', RELEASE = '2024-02-23', REQUIRED = '2.34.0', From 5b3b3620129bed838d3d5fe64a92ef4daacac90c Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Wed, 28 Feb 2024 20:42:31 +0100 Subject: [PATCH 057/110] Simplify SignMe/Remember me code --- dev/View/User/Login.js | 17 ++++++----------- .../v/0.0.0/app/libraries/RainLoop/Actions.php | 7 ++++++- .../libraries/RainLoop/Config/Application.php | 2 +- .../RainLoop/Enumerations/SignMeType.php | 6 +++--- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/dev/View/User/Login.js b/dev/View/User/Login.js index 044813049..00e8eebe8 100644 --- a/dev/View/User/Login.js +++ b/dev/View/User/Login.js @@ -138,25 +138,20 @@ export class LoginUserView extends AbstractViewLogin { onBuild(dom) { super.onBuild(dom); - const signMe = (SettingsGet('signMe') || '').toLowerCase(); - + let signMe = (SettingsGet('signMe') || '').toLowerCase(); switch (signMe) { - case 'defaultoff': - case 'defaulton': - this.signMeType( - 'defaulton' === signMe ? SignMeOn : SignMeOff - ); - + case SignMeOff: + case SignMeOn: switch (Local.get(ClientSideKeyNameLastSignMe)) { case '-1-': - this.signMeType(SignMeOn); + signMe = SignMeOn; break; case '-0-': - this.signMeType(SignMeOff); + signMe = SignMeOff; break; // no default } - + this.signMeType(signMe); break; default: this.signMeType(SignMeUnused); diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php index 3dbb5a992..72ae3f07c 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php @@ -3,6 +3,7 @@ namespace RainLoop; use RainLoop\Enumerations\Capa; +use RainLoop\Enumerations\SignMeType; class Actions { @@ -834,7 +835,11 @@ class Actions $aResult['DevPassword'] = ''; } - $aResult['signMe'] = (string) $oConfig->Get('login', 'sign_me_auto', Enumerations\SignMeType::DEFAULT_OFF); + $aResult['signMe'] = [ + SignMeType::DefaultOff => 0, + SignMeType::DefaultOn => 1, + SignMeType::Unused => 2 + ][(string) $oConfig->Get('login', 'sign_me_auto', SignMeType::DefaultOff)]; } } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Config/Application.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Config/Application.php index e27f7dd20..f097bd6dd 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Config/Application.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Config/Application.php @@ -272,7 +272,7 @@ When this value is gethostname, the gethostname() value is used. 'login_lowercase' => array(true), - 'sign_me_auto' => array(\RainLoop\Enumerations\SignMeType::DEFAULT_OFF, + 'sign_me_auto' => array(\RainLoop\Enumerations\SignMeType::DefaultOff, 'This option allows webmail to remember the logged in user once they closed the browser window. diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/SignMeType.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/SignMeType.php index d762abfca..bb50c4345 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/SignMeType.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/SignMeType.php @@ -4,7 +4,7 @@ namespace RainLoop\Enumerations; abstract class SignMeType { - const DEFAULT_OFF = 'DefaultOff'; - const DEFAULT_ON = 'DefaultOn'; - const UNUSED = 'Unused'; + const DefaultOff = 'DefaultOff'; + const DefaultOn = 'DefaultOn'; + const Unused = 'Unused'; } From c1b7d376631734ea919e9fd7a843b88343e61a39 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Fri, 1 Mar 2024 01:39:00 +0100 Subject: [PATCH 058/110] Simplify language Notifications --- dev/Common/Enums.js | 1 - dev/Common/Translator.js | 2 +- dev/Remote/AbstractFetch.js | 1 - dev/View/User/Login.js | 2 +- .../RainLoop/Enumerations/UploadError.php | 20 ++--- .../app/libraries/RainLoop/Notifications.php | 1 - .../app/libraries/RainLoop/ServiceActions.php | 2 +- .../v/0.0.0/app/localization/ar-SA/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/bg-BG/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/cs-CZ/admin.json | 24 +++--- .../v/0.0.0/app/localization/cs-CZ/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/da-DK/admin.json | 24 +++--- .../v/0.0.0/app/localization/da-DK/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/de-DE/admin.json | 24 +++--- .../v/0.0.0/app/localization/de-DE/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/el-GR/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/en-GB/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/en/admin.json | 26 +++--- .../v/0.0.0/app/localization/en/user.json | 84 +++++++++---------- .../v/0.0.0/app/localization/es-ES/admin.json | 24 +++--- .../v/0.0.0/app/localization/es-ES/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/et-EE/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/eu/admin.json | 24 +++--- .../v/0.0.0/app/localization/eu/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/fa-IR/admin.json | 24 +++--- .../v/0.0.0/app/localization/fa-IR/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/fi-FI/admin.json | 24 +++--- .../v/0.0.0/app/localization/fi-FI/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/fr-FR/admin.json | 24 +++--- .../v/0.0.0/app/localization/fr-FR/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/hu-HU/admin.json | 24 +++--- .../v/0.0.0/app/localization/hu-HU/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/id-ID/admin.json | 24 +++--- .../v/0.0.0/app/localization/id-ID/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/is-IS/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/it-IT/admin.json | 24 +++--- .../v/0.0.0/app/localization/it-IT/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/ja-JP/admin.json | 24 +++--- .../v/0.0.0/app/localization/ja-JP/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/ko-KR/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/lt-LT/admin.json | 24 +++--- .../v/0.0.0/app/localization/lt-LT/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/lv-LV/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/nb-NO/admin.json | 24 +++--- .../v/0.0.0/app/localization/nb-NO/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/nl-NL/admin.json | 24 +++--- .../v/0.0.0/app/localization/nl-NL/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/pl-PL/admin.json | 24 +++--- .../v/0.0.0/app/localization/pl-PL/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/pt-BR/admin.json | 24 +++--- .../v/0.0.0/app/localization/pt-BR/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/pt-PT/admin.json | 24 +++--- .../v/0.0.0/app/localization/pt-PT/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/pt/admin.json | 24 +++--- .../v/0.0.0/app/localization/pt/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/ro-RO/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/ru-RU/admin.json | 24 +++--- .../v/0.0.0/app/localization/ru-RU/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/sk-SK/admin.json | 24 +++--- .../v/0.0.0/app/localization/sk-SK/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/sl-SI/admin.json | 24 +++--- .../v/0.0.0/app/localization/sl-SI/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/sv-SE/admin.json | 24 +++--- .../v/0.0.0/app/localization/sv-SE/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/tr-TR/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/uk-UA/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/vi-VN/admin.json | 24 +++--- .../v/0.0.0/app/localization/vi-VN/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/zh-CN/admin.json | 24 +++--- .../v/0.0.0/app/localization/zh-CN/user.json | 74 ++++++++-------- .../v/0.0.0/app/localization/zh-TW/user.json | 74 ++++++++-------- 71 files changed, 1737 insertions(+), 1740 deletions(-) diff --git a/dev/Common/Enums.js b/dev/Common/Enums.js index 028d2a700..6a6acee72 100644 --- a/dev/Common/Enums.js +++ b/dev/Common/Enums.js @@ -95,7 +95,6 @@ Notifications = { JsonParse: 952, // JsonTimeout: 953, - UnknownNotification: 998, UnknownError: 999, // Admin diff --git a/dev/Common/Translator.js b/dev/Common/Translator.js index f67aae246..4d1111a64 100644 --- a/dev/Common/Translator.js +++ b/dev/Common/Translator.js @@ -22,7 +22,7 @@ const getNotificationMessage = code => { let key = getKeyByValue(Notifications, code); - return key ? I18N_DATA.NOTIFICATIONS[i18nKey(key).replace('_NOTIFICATION', '_ERROR')] : ''; + return key ? I18N_DATA.NOTIFICATIONS[key] : ''; }, fromNow = date => relativeTime(Math.round((date.getTime() - Date.now()) / 1000)); diff --git a/dev/Remote/AbstractFetch.js b/dev/Remote/AbstractFetch.js index c0f4b4f59..1b2ae870f 100644 --- a/dev/Remote/AbstractFetch.js +++ b/dev/Remote/AbstractFetch.js @@ -19,7 +19,6 @@ checkResponseError = data => { Notifications.DomainNotAllowed, Notifications.AccountNotAllowed, Notifications.MailServerError, - Notifications.UnknownNotification, Notifications.UnknownError ].includes(err) ) { diff --git a/dev/View/User/Login.js b/dev/View/User/Login.js index 00e8eebe8..fb38995bf 100644 --- a/dev/View/User/Login.js +++ b/dev/View/User/Login.js @@ -120,7 +120,7 @@ export class LoginUserView extends AbstractViewLogin { iError = Notifications.AuthError; } this.submitError(getNotification(iError, oData?.ErrorMessage, - Notifications.UnknownNotification)); + Notifications.UnknownError)); this.submitErrorAdditional(oData?.ErrorMessageAdditional); } else { rl.setData(oData.Result); diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/UploadError.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/UploadError.php index 83d54b488..c31dd8f45 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/UploadError.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/UploadError.php @@ -9,16 +9,16 @@ abstract class UploadError const CONFIG_SIZE = 1001; const ON_SAVING = 1002; - const EMPTY_FILES_DATA = 1003; + const EMPTY_FILE = 1003; private static $messages = [ - \UPLOAD_ERR_INI_SIZE => 'Filesize exceeds the upload_max_filesize directive in php.ini', - \UPLOAD_ERR_FORM_SIZE => 'Filesize exceeds the MAX_FILE_SIZE directive that was specified in the html form', - \UPLOAD_ERR_PARTIAL => 'File was only partially uploaded', - \UPLOAD_ERR_NO_FILE => 'No file was uploaded', - \UPLOAD_ERR_NO_TMP_DIR => 'Missing a temporary folder', - \UPLOAD_ERR_CANT_WRITE => 'Failed to write file to disk', - \UPLOAD_ERR_EXTENSION => 'File upload stopped by extension', + /*1*/\UPLOAD_ERR_INI_SIZE => 'Filesize exceeds the upload_max_filesize directive in php.ini', + /*2*/\UPLOAD_ERR_FORM_SIZE => 'Filesize exceeds the MAX_FILE_SIZE directive that was specified in the html form', + /*3*/\UPLOAD_ERR_PARTIAL => 'File was only partially uploaded', + /*4*/\UPLOAD_ERR_NO_FILE => 'No file was uploaded', + /*6*/\UPLOAD_ERR_NO_TMP_DIR => 'Missing a temporary folder', + /*7*/\UPLOAD_ERR_CANT_WRITE => 'Failed to write file to disk', + /*8*/\UPLOAD_ERR_EXTENSION => 'File upload stopped by extension', 98 => 'Invalid file type', 99 => 'Unknown error', 1001 => 'Filesize exceeds the config setting', @@ -28,7 +28,7 @@ abstract class UploadError public static function getMessage(int $code): string { - return isset(static::$messages[$code]) ? static::$messages[$code] : 0; + return isset(static::$messages[$code]) ? static::$messages[$code] : ''; } public static function getUserMessage(int $iError, int &$iClientError): string @@ -39,12 +39,12 @@ abstract class UploadError case \UPLOAD_ERR_PARTIAL: case \UPLOAD_ERR_NO_FILE: case static::FILE_TYPE: + case static::EMPTY_FILE: break; case \UPLOAD_ERR_INI_SIZE: case \UPLOAD_ERR_FORM_SIZE: case static::CONFIG_SIZE: - case static::EMPTY_FILES_DATA: return 'File is too big'; case \UPLOAD_ERR_NO_TMP_DIR: diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Notifications.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Notifications.php index 6e376d4b9..fc431e743 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Notifications.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Notifications.php @@ -58,7 +58,6 @@ class Notifications const MailServerError = 901; const ClientViewError = 902; const InvalidInputArgument = 903; -// const UnknownNotification = 998; const UnknownError = 999; // Admin diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php b/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php index 5e7092b26..6ff2831a2 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php @@ -218,7 +218,7 @@ class ServiceActions } else if (empty($_FILES)) { $iError = UPLOAD_ERR_INI_SIZE; } else { - $iError = Enumerations\UploadError::EMPTY_FILES_DATA; + $iError = Enumerations\UploadError::EMPTY_FILE; } if (\method_exists($this->oActions, $sAction) && \is_callable(array($this->oActions, $sAction))) { diff --git a/snappymail/v/0.0.0/app/localization/ar-SA/user.json b/snappymail/v/0.0.0/app/localization/ar-SA/user.json index 681ec190d..7a1f816b3 100644 --- a/snappymail/v/0.0.0/app/localization/ar-SA/user.json +++ b/snappymail/v/0.0.0/app/localization/ar-SA/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "إغلاق الرسالة" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "خاطىء token", - "AUTH_ERROR": "خطأ في كلمة السر \\اسم المستخدم", - "CONNECTION_ERROR": "لايمكن الإتصال بالمخدم", - "DOMAIN_ALREADY_EXISTS": "الموقع موجود مسبقاَ", - "DOMAIN_NOT_ALLOWED": "غير مسموح لهذا الموقع", - "ACCOUNT_NOT_ALLOWED": "الحساب غير مسموح له", - "CONTACTS_SYNC_ERROR": "خطأ في مزامنة جهات الإتصال", - "CANT_GET_MESSAGE_LIST": "لايمكن الوصول الى قائمة الرسائل", - "CANT_GET_MESSAGE": "لايمكن الوصول الى الرسالة", - "CANT_DELETE_MESSAGE": "لايمكن حذف الرسالة", - "CANT_COPY_MESSAGE": "Can't copy message", - "CANT_MOVE_MESSAGE": "لايمكن نقل الرسالة", - "CANT_SAVE_MESSAGE": "لايمكن حفظ الرسالة", - "CANT_SEND_MESSAGE": "لايمكن إرسال الرسالة", - "INVALID_RECIPIENTS": "يرجى التأكد من عناوين المرسل اليهم", - "CANT_SAVE_FILTERS": "لايمكن حفظ عامل التصفية", - "CANT_GET_FILTERS": "لايمكن الوصول الى عوامل التصفية", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Can't activate filters script", - "CANT_DELETE_FILTERS_SCRIPT": "Can't delete filters script", - "FILTERS_ARE_NOT_CORRECT": "عوامل التصفية خطأ", - "CANT_CREATE_FOLDER": "لايمكن إنشاء مجلد", - "CANT_RENAME_FOLDER": "لايمكن إعادة تسمية المجلد", - "CANT_DELETE_FOLDER": "لايمكن حذف المجلد", - "CANT_DELETE_NON_EMPTY_FOLDER": "لايمكن حذف مجلد ممتلأ", - "CANT_SUBSCRIBE_FOLDER": "لايمكن الإشتراك بالمجلد", - "CANT_UNSUBSCRIBE_FOLDER": "لايمكن حذف الإشتراك من المجلد", - "DEMO_SEND_MESSAGE_ERROR": "لأسباب أمنية, هذا الحساب غير مسموح له إرسال رسائل", - "DEMO_ACCOUNT_ERROR": "لأسباب أمنية , هذا الحساب قد منع من هذا الإجراء", - "ACCOUNT_ALREADY_EXISTS": "الحساب موجود مسبقاَ", - "ACCOUNT_DOES_NOT_EXIST": "الحساب المطلوب غير موجود", - "ACCOUNT_SWITCH_FAILED": "Switch to account \"%EMAIL%\" failed", - "MAIL_SERVER_ERROR": "حدث خطأ أثناء محاولة الوصول الى المخدم البريدي", - "INVALID_INPUT_ARGUMENT": "Invalid input argument", - "UNKNOWN_ERROR": "خطأ غير معروف" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "خاطىء token", + "AuthError": "خطأ في كلمة السر \\اسم المستخدم", + "ConnectionError": "لايمكن الإتصال بالمخدم", + "DomainAlreadyExists": "الموقع موجود مسبقاَ", + "DomainNotAllowed": "غير مسموح لهذا الموقع", + "AccountNotAllowed": "الحساب غير مسموح له", + "ContactsSyncError": "خطأ في مزامنة جهات الإتصال", + "CantGetMessageList": "لايمكن الوصول الى قائمة الرسائل", + "CantGetMessage": "لايمكن الوصول الى الرسالة", + "CantDeleteMessage": "لايمكن حذف الرسالة", + "CantCopyMessage": "Can't copy message", + "CantMoveMessage": "لايمكن نقل الرسالة", + "CantSaveMessage": "لايمكن حفظ الرسالة", + "CantSendMessage": "لايمكن إرسال الرسالة", + "InvalidRecipients": "يرجى التأكد من عناوين المرسل اليهم", + "CantSaveFilters": "لايمكن حفظ عامل التصفية", + "CantGetFilters": "لايمكن الوصول الى عوامل التصفية", + "CantActivateFiltersScript": "Can't activate filters script", + "CantDeleteFiltersScript": "Can't delete filters script", + "FiltersAreNotCorrect": "عوامل التصفية خطأ", + "CantCreateFolder": "لايمكن إنشاء مجلد", + "CantRenameFolder": "لايمكن إعادة تسمية المجلد", + "CantDeleteFolder": "لايمكن حذف المجلد", + "CantDeleteNonEmptyFolder": "لايمكن حذف مجلد ممتلأ", + "CantSubscribeFolder": "لايمكن الإشتراك بالمجلد", + "CantUnsubscribeFolder": "لايمكن حذف الإشتراك من المجلد", + "DemoSendMessageError": "لأسباب أمنية, هذا الحساب غير مسموح له إرسال رسائل", + "DemoAccountError": "لأسباب أمنية , هذا الحساب قد منع من هذا الإجراء", + "AccountAlreadyExists": "الحساب موجود مسبقاَ", + "AccountDoesNotExist": "الحساب المطلوب غير موجود", + "AccountSwitchFailed": "Switch to account \"%EMAIL%\" failed", + "MailServerError": "حدث خطأ أثناء محاولة الوصول الى المخدم البريدي", + "InvalidInputArgument": "Invalid input argument", + "UnknownError": "خطأ غير معروف" } } diff --git a/snappymail/v/0.0.0/app/localization/bg-BG/user.json b/snappymail/v/0.0.0/app/localization/bg-BG/user.json index 0bd9a57e2..8f7e61b4a 100644 --- a/snappymail/v/0.0.0/app/localization/bg-BG/user.json +++ b/snappymail/v/0.0.0/app/localization/bg-BG/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "Затвори създаването" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Невалиден токен", - "AUTH_ERROR": "Неуспешно удостоверяване", - "CONNECTION_ERROR": "Не може да се свърже със сървъра", - "DOMAIN_ALREADY_EXISTS": "Домейна вече съществува", - "DOMAIN_NOT_ALLOWED": "Този домейн не е разрешен", - "ACCOUNT_NOT_ALLOWED": "Този акаунт не е разрешен", - "CONTACTS_SYNC_ERROR": "Грешка при синхронизацията", - "CANT_GET_MESSAGE_LIST": "Не може да се изтегли списъка със съобщения", - "CANT_GET_MESSAGE": "Не може да се изтегли съобщението", - "CANT_DELETE_MESSAGE": "Не може да се изтрие съобщението", - "CANT_COPY_MESSAGE": "Can't copy message", - "CANT_MOVE_MESSAGE": "Не може да се премести съобщението", - "CANT_SAVE_MESSAGE": "Не може да се запамети съобщението", - "CANT_SEND_MESSAGE": "Не може да се изпрати съобщението", - "INVALID_RECIPIENTS": "Невалидни получатели", - "CANT_SAVE_FILTERS": "Не може да се запаметят филтрите", - "CANT_GET_FILTERS": "Не могат да се изтеглят филтрите", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Can't activate filters script", - "CANT_DELETE_FILTERS_SCRIPT": "Can't delete filters script", - "FILTERS_ARE_NOT_CORRECT": "Грешни филтри", - "CANT_CREATE_FOLDER": "Не може да се създаде папка", - "CANT_RENAME_FOLDER": "Не може да се преименува папка", - "CANT_DELETE_FOLDER": "Не може да се изтрие папка", - "CANT_DELETE_NON_EMPTY_FOLDER": "Не може да се изтрие папка, която не е празна", - "CANT_SUBSCRIBE_FOLDER": "Не може да се абонира за папка", - "CANT_UNSUBSCRIBE_FOLDER": "Не може да се махне абонамента за папка", - "DEMO_SEND_MESSAGE_ERROR": "С цел сугурност, на този акаунт е забранено да изпраща съобщения до външни email адреси!", - "DEMO_ACCOUNT_ERROR": "С цел сигурност, това действие не е разрешено за този акаунт!", - "ACCOUNT_ALREADY_EXISTS": "Акаунта вече съществува", - "ACCOUNT_DOES_NOT_EXIST": "Акаунта не съществува", - "ACCOUNT_SWITCH_FAILED": "Switch to account \"%EMAIL%\" failed", - "MAIL_SERVER_ERROR": "Възникна грешка при комуникацията с пощенския сървър", - "INVALID_INPUT_ARGUMENT": "Невалидни входни аргументи", - "UNKNOWN_ERROR": "Неизвестна грешка" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Невалиден токен", + "AuthError": "Неуспешно удостоверяване", + "ConnectionError": "Не може да се свърже със сървъра", + "DomainAlreadyExists": "Домейна вече съществува", + "DomainNotAllowed": "Този домейн не е разрешен", + "AccountNotAllowed": "Този акаунт не е разрешен", + "ContactsSyncError": "Грешка при синхронизацията", + "CantGetMessageList": "Не може да се изтегли списъка със съобщения", + "CantGetMessage": "Не може да се изтегли съобщението", + "CantDeleteMessage": "Не може да се изтрие съобщението", + "CantCopyMessage": "Can't copy message", + "CantMoveMessage": "Не може да се премести съобщението", + "CantSaveMessage": "Не може да се запамети съобщението", + "CantSendMessage": "Не може да се изпрати съобщението", + "InvalidRecipients": "Невалидни получатели", + "CantSaveFilters": "Не може да се запаметят филтрите", + "CantGetFilters": "Не могат да се изтеглят филтрите", + "CantActivateFiltersScript": "Can't activate filters script", + "CantDeleteFiltersScript": "Can't delete filters script", + "FiltersAreNotCorrect": "Грешни филтри", + "CantCreateFolder": "Не може да се създаде папка", + "CantRenameFolder": "Не може да се преименува папка", + "CantDeleteFolder": "Не може да се изтрие папка", + "CantDeleteNonEmptyFolder": "Не може да се изтрие папка, която не е празна", + "CantSubscribeFolder": "Не може да се абонира за папка", + "CantUnsubscribeFolder": "Не може да се махне абонамента за папка", + "DemoSendMessageError": "С цел сугурност, на този акаунт е забранено да изпраща съобщения до външни email адреси!", + "DemoAccountError": "С цел сигурност, това действие не е разрешено за този акаунт!", + "AccountAlreadyExists": "Акаунта вече съществува", + "AccountDoesNotExist": "Акаунта не съществува", + "AccountSwitchFailed": "Switch to account \"%EMAIL%\" failed", + "MailServerError": "Възникна грешка при комуникацията с пощенския сървър", + "InvalidInputArgument": "Невалидни входни аргументи", + "UnknownError": "Неизвестна грешка" } } diff --git a/snappymail/v/0.0.0/app/localization/cs-CZ/admin.json b/snappymail/v/0.0.0/app/localization/cs-CZ/admin.json index 979e5ac7b..aa5a6a211 100644 --- a/snappymail/v/0.0.0/app/localization/cs-CZ/admin.json +++ b/snappymail/v/0.0.0/app/localization/cs-CZ/admin.json @@ -168,17 +168,17 @@ "UNKNOWN_ERROR": "Neznámá chyba" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Neplatný token", - "AUTH_ERROR": "Chyba autorizace", - "DOMAIN_ALREADY_EXISTS": "Tato doména již existuje", - "CANT_SAVE_PLUGIN_SETTINGS": "Nastavení se nepodařilo uložit", - "CANT_INSTALL_PACKAGE": "Instalace balíčku se nezdařila", - "CANT_DELETE_PACKAGE": "Odstranění balíčku se nezdařilo", - "INVALID_PLUGIN_PACKAGE": "Nevalidní balíček", - "UNSUPPORTED_PLUGIN_PACKAGE": "Nepodporovaný balíček rozšíření", - "UNKNOWN_ERROR": "Neznámá chyba" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Neplatný token", + "AuthError": "Chyba autorizace", + "DomainAlreadyExists": "Tato doména již existuje", + "CantSavePluginSettings": "Nastavení se nepodařilo uložit", + "CantInstallPackage": "Instalace balíčku se nezdařila", + "CantDeletePackage": "Odstranění balíčku se nezdařilo", + "InvalidPluginPackage": "Nevalidní balíček", + "UnsupportedPluginPackage": "Nepodporovaný balíček rozšíření", + "UnknownError": "Neznámá chyba" } } diff --git a/snappymail/v/0.0.0/app/localization/cs-CZ/user.json b/snappymail/v/0.0.0/app/localization/cs-CZ/user.json index 67b9c5efa..cbaf3a58b 100644 --- a/snappymail/v/0.0.0/app/localization/cs-CZ/user.json +++ b/snappymail/v/0.0.0/app/localization/cs-CZ/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "Zavřít okno se zprávou" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Neplatný token", - "AUTH_ERROR": "Ověření selhalo", - "CONNECTION_ERROR": "Nepodařilo se připojit k serveru", - "DOMAIN_ALREADY_EXISTS": "Tato doména již existuje", - "DOMAIN_NOT_ALLOWED": "Doména není povolená", - "ACCOUNT_NOT_ALLOWED": "Účet není povolený", - "CONTACTS_SYNC_ERROR": "Chyba při synchronizaci kontaktů", - "CANT_GET_MESSAGE_LIST": "Chyba při vytváření seznamu zpráv", - "CANT_GET_MESSAGE": "Zprávu se nepodařilo načíst", - "CANT_DELETE_MESSAGE": "Zprávu se nepodařilo odstranit", - "CANT_COPY_MESSAGE": "Can't copy message", - "CANT_MOVE_MESSAGE": "Zprávu se nepodařilo přesunout", - "CANT_SAVE_MESSAGE": "Zprávu se nepodařilo uložit", - "CANT_SEND_MESSAGE": "Zprávu se nepodařilo odeslat", - "INVALID_RECIPIENTS": "Neplatný příjemci", - "CANT_SAVE_FILTERS": "Nelze uložit filtry", - "CANT_GET_FILTERS": "Nelze načíst filtry", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Can't activate filters script", - "CANT_DELETE_FILTERS_SCRIPT": "Can't delete filters script", - "FILTERS_ARE_NOT_CORRECT": "Filtry nejsou validní", - "CANT_CREATE_FOLDER": "Složku se nepodařilo vytvořit", - "CANT_RENAME_FOLDER": "Složku se nepodařilo přejmenovat", - "CANT_DELETE_FOLDER": "Složku se nepodařilo odstranit", - "CANT_DELETE_NON_EMPTY_FOLDER": "Nelze odstranit neprázdnou složku", - "CANT_SUBSCRIBE_FOLDER": "Nelze přihlásit adresář", - "CANT_UNSUBSCRIBE_FOLDER": "Nelze odhlásit adresář", - "DEMO_SEND_MESSAGE_ERROR": "Z důvodu bezpečnosti tento demo účet není oprávněn posílat zprávy na externí emaily!", - "DEMO_ACCOUNT_ERROR": "Z důvodu bezpečnosti tento účet nemá oprávnění toto provést!", - "ACCOUNT_ALREADY_EXISTS": "Účet už existuje", - "ACCOUNT_DOES_NOT_EXIST": "Účet neexistuje", - "ACCOUNT_SWITCH_FAILED": "Switch to account \"%EMAIL%\" failed", - "MAIL_SERVER_ERROR": "Nastala chyba během přístupu na poštovní server", - "INVALID_INPUT_ARGUMENT": "Nevalidní vstupní argument", - "UNKNOWN_ERROR": "Neznámá chyba" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Neplatný token", + "AuthError": "Ověření selhalo", + "ConnectionError": "Nepodařilo se připojit k serveru", + "DomainAlreadyExists": "Tato doména již existuje", + "DomainNotAllowed": "Doména není povolená", + "AccountNotAllowed": "Účet není povolený", + "ContactsSyncError": "Chyba při synchronizaci kontaktů", + "CantGetMessageList": "Chyba při vytváření seznamu zpráv", + "CantGetMessage": "Zprávu se nepodařilo načíst", + "CantDeleteMessage": "Zprávu se nepodařilo odstranit", + "CantCopyMessage": "Can't copy message", + "CantMoveMessage": "Zprávu se nepodařilo přesunout", + "CantSaveMessage": "Zprávu se nepodařilo uložit", + "CantSendMessage": "Zprávu se nepodařilo odeslat", + "InvalidRecipients": "Neplatný příjemci", + "CantSaveFilters": "Nelze uložit filtry", + "CantGetFilters": "Nelze načíst filtry", + "CantActivateFiltersScript": "Can't activate filters script", + "CantDeleteFiltersScript": "Can't delete filters script", + "FiltersAreNotCorrect": "Filtry nejsou validní", + "CantCreateFolder": "Složku se nepodařilo vytvořit", + "CantRenameFolder": "Složku se nepodařilo přejmenovat", + "CantDeleteFolder": "Složku se nepodařilo odstranit", + "CantDeleteNonEmptyFolder": "Nelze odstranit neprázdnou složku", + "CantSubscribeFolder": "Nelze přihlásit adresář", + "CantUnsubscribeFolder": "Nelze odhlásit adresář", + "DemoSendMessageError": "Z důvodu bezpečnosti tento demo účet není oprávněn posílat zprávy na externí emaily!", + "DemoAccountError": "Z důvodu bezpečnosti tento účet nemá oprávnění toto provést!", + "AccountAlreadyExists": "Účet už existuje", + "AccountDoesNotExist": "Účet neexistuje", + "AccountSwitchFailed": "Switch to account \"%EMAIL%\" failed", + "MailServerError": "Nastala chyba během přístupu na poštovní server", + "InvalidInputArgument": "Nevalidní vstupní argument", + "UnknownError": "Neznámá chyba" } } diff --git a/snappymail/v/0.0.0/app/localization/da-DK/admin.json b/snappymail/v/0.0.0/app/localization/da-DK/admin.json index efe48787c..b6d5db762 100644 --- a/snappymail/v/0.0.0/app/localization/da-DK/admin.json +++ b/snappymail/v/0.0.0/app/localization/da-DK/admin.json @@ -168,17 +168,17 @@ "UNKNOWN_ERROR": "Ukendt fejl" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Ugyldigt tegn", - "AUTH_ERROR": "Godkendelse fejlede", - "DOMAIN_ALREADY_EXISTS": "Domæne eksisterer allerede", - "CANT_SAVE_PLUGIN_SETTINGS": "Kan ikke gemme instillinger", - "CANT_INSTALL_PACKAGE": "Installation af pakke mislykkedes", - "CANT_DELETE_PACKAGE": "Fjernelse af pakke mislykkedes", - "INVALID_PLUGIN_PACKAGE": "Ugyldig tilføjelsespakke", - "UNSUPPORTED_PLUGIN_PACKAGE": "Tilføjelsespakke ikke understøttet", - "UNKNOWN_ERROR": "Ukendt fejl" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Ugyldigt tegn", + "AuthError": "Godkendelse fejlede", + "DomainAlreadyExists": "Domæne eksisterer allerede", + "CantSavePluginSettings": "Kan ikke gemme instillinger", + "CantInstallPackage": "Installation af pakke mislykkedes", + "CantDeletePackage": "Fjernelse af pakke mislykkedes", + "InvalidPluginPackage": "Ugyldig tilføjelsespakke", + "UnsupportedPluginPackage": "Tilføjelsespakke ikke understøttet", + "UnknownError": "Ukendt fejl" } } diff --git a/snappymail/v/0.0.0/app/localization/da-DK/user.json b/snappymail/v/0.0.0/app/localization/da-DK/user.json index a81a91d3b..f1d6e14f2 100644 --- a/snappymail/v/0.0.0/app/localization/da-DK/user.json +++ b/snappymail/v/0.0.0/app/localization/da-DK/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "Luk forfatter mode" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Ugyldigt tegn", - "AUTH_ERROR": "Godkendelse fejlede", - "CONNECTION_ERROR": "Kan ikke kontakte server", - "DOMAIN_ALREADY_EXISTS": "Domæne eksisterer allerede", - "DOMAIN_NOT_ALLOWED": "Domæne ikke tilladt", - "ACCOUNT_NOT_ALLOWED": "Konto ikke tilladt", - "CONTACTS_SYNC_ERROR": "Fejl ved synkronisering af kontakter", - "CANT_GET_MESSAGE_LIST": "Kan ikke indlæse meddelelsesoversigt ", - "CANT_GET_MESSAGE": "Kan ikke indlæse meddelelse", - "CANT_DELETE_MESSAGE": "Kan ikke slette meddelelse", - "CANT_COPY_MESSAGE": "Can't copy message", - "CANT_MOVE_MESSAGE": "Kan ikke flytte meddelelse", - "CANT_SAVE_MESSAGE": "Kan ikke gemme meddelelse", - "CANT_SEND_MESSAGE": "Kan ikke sende meddelelse", - "INVALID_RECIPIENTS": "Ugyldige modtagere", - "CANT_SAVE_FILTERS": "Kan ikke gemme filtre", - "CANT_GET_FILTERS": "Kan ikke indlæse filtre", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Can't activate filters script", - "CANT_DELETE_FILTERS_SCRIPT": "Can't delete filters script", - "FILTERS_ARE_NOT_CORRECT": "Fejl i filtre", - "CANT_CREATE_FOLDER": "Kan ikke oprette mappe", - "CANT_RENAME_FOLDER": "Kan ikke omdøbe mappe", - "CANT_DELETE_FOLDER": "Kan ikke slette mappe", - "CANT_DELETE_NON_EMPTY_FOLDER": "Kan ikke slette mappe som ikke er tom", - "CANT_SUBSCRIBE_FOLDER": "Kan ikke abonnere på mappe", - "CANT_UNSUBSCRIBE_FOLDER": "Kan ikke afmelde mappe", - "DEMO_SEND_MESSAGE_ERROR": "Denne konto kan af sikkerhedshensyn ikke sende e-mails til eksterne adresser!", - "DEMO_ACCOUNT_ERROR": "Denne konto kan af sikkerhedshensyn ikke udføre denne handling!", - "ACCOUNT_ALREADY_EXISTS": "Kontoen eksisterer allerede", - "ACCOUNT_DOES_NOT_EXIST": "Kontoen eksisterer ikke", - "ACCOUNT_SWITCH_FAILED": "Switch to account \"%EMAIL%\" failed", - "MAIL_SERVER_ERROR": "Der skete en fejl under adgang til e-mail serveren", - "INVALID_INPUT_ARGUMENT": "Ugyldigt argument", - "UNKNOWN_ERROR": "Ukendt fejl" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Ugyldigt tegn", + "AuthError": "Godkendelse fejlede", + "ConnectionError": "Kan ikke kontakte server", + "DomainAlreadyExists": "Domæne eksisterer allerede", + "DomainNotAllowed": "Domæne ikke tilladt", + "AccountNotAllowed": "Konto ikke tilladt", + "ContactsSyncError": "Fejl ved synkronisering af kontakter", + "CantGetMessageList": "Kan ikke indlæse meddelelsesoversigt ", + "CantGetMessage": "Kan ikke indlæse meddelelse", + "CantDeleteMessage": "Kan ikke slette meddelelse", + "CantCopyMessage": "Can't copy message", + "CantMoveMessage": "Kan ikke flytte meddelelse", + "CantSaveMessage": "Kan ikke gemme meddelelse", + "CantSendMessage": "Kan ikke sende meddelelse", + "InvalidRecipients": "Ugyldige modtagere", + "CantSaveFilters": "Kan ikke gemme filtre", + "CantGetFilters": "Kan ikke indlæse filtre", + "CantActivateFiltersScript": "Can't activate filters script", + "CantDeleteFiltersScript": "Can't delete filters script", + "FiltersAreNotCorrect": "Fejl i filtre", + "CantCreateFolder": "Kan ikke oprette mappe", + "CantRenameFolder": "Kan ikke omdøbe mappe", + "CantDeleteFolder": "Kan ikke slette mappe", + "CantDeleteNonEmptyFolder": "Kan ikke slette mappe som ikke er tom", + "CantSubscribeFolder": "Kan ikke abonnere på mappe", + "CantUnsubscribeFolder": "Kan ikke afmelde mappe", + "DemoSendMessageError": "Denne konto kan af sikkerhedshensyn ikke sende e-mails til eksterne adresser!", + "DemoAccountError": "Denne konto kan af sikkerhedshensyn ikke udføre denne handling!", + "AccountAlreadyExists": "Kontoen eksisterer allerede", + "AccountDoesNotExist": "Kontoen eksisterer ikke", + "AccountSwitchFailed": "Switch to account \"%EMAIL%\" failed", + "MailServerError": "Der skete en fejl under adgang til e-mail serveren", + "InvalidInputArgument": "Ugyldigt argument", + "UnknownError": "Ukendt fejl" } } diff --git a/snappymail/v/0.0.0/app/localization/de-DE/admin.json b/snappymail/v/0.0.0/app/localization/de-DE/admin.json index f78a4934c..d930e0dec 100644 --- a/snappymail/v/0.0.0/app/localization/de-DE/admin.json +++ b/snappymail/v/0.0.0/app/localization/de-DE/admin.json @@ -168,17 +168,17 @@ "UNKNOWN_ERROR": "Unbekannter Fehler" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Anfrage fehlgeschlagen", - "REQUEST_ABORTED": "Anfrage abgebrochen", - "REQUEST_TIMEOUT": "Antrag auf Auslieferung", - "INVALID_TOKEN": "Ungültiger Token", - "AUTH_ERROR": "Authentifizierung fehlgeschlagen", - "DOMAIN_ALREADY_EXISTS": "Diese Domain existiert bereits", - "CANT_SAVE_PLUGIN_SETTINGS": "Einstellungen können nicht gespeichert werden", - "CANT_INSTALL_PACKAGE": "Fehler beim Installieren der Erweiterung", - "CANT_DELETE_PACKAGE": "Fehler beim entfernen der Erweiterung", - "INVALID_PLUGIN_PACKAGE": "Erweiterungspaket ist ungültig", - "UNSUPPORTED_PLUGIN_PACKAGE": "Erweiterungspaket wird nicht unterstützt", - "UNKNOWN_ERROR": "Unbekannter Fehler" + "RequestError": "Anfrage fehlgeschlagen", + "RequestAborted": "Anfrage abgebrochen", + "RequestTimeout": "Antrag auf Auslieferung", + "InvalidToken": "Ungültiger Token", + "AuthError": "Authentifizierung fehlgeschlagen", + "DomainAlreadyExists": "Diese Domain existiert bereits", + "CantSavePluginSettings": "Einstellungen können nicht gespeichert werden", + "CantInstallPackage": "Fehler beim Installieren der Erweiterung", + "CantDeletePackage": "Fehler beim entfernen der Erweiterung", + "InvalidPluginPackage": "Erweiterungspaket ist ungültig", + "UnsupportedPluginPackage": "Erweiterungspaket wird nicht unterstützt", + "UnknownError": "Unbekannter Fehler" } } diff --git a/snappymail/v/0.0.0/app/localization/de-DE/user.json b/snappymail/v/0.0.0/app/localization/de-DE/user.json index 5e07f0630..2d86df283 100644 --- a/snappymail/v/0.0.0/app/localization/de-DE/user.json +++ b/snappymail/v/0.0.0/app/localization/de-DE/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "Popup schließen" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Anfrage fehlgeschlagen", - "REQUEST_ABORTED": "Anfrage abgebrochen", - "REQUEST_TIMEOUT": "Antrag auf Auslieferung", - "INVALID_TOKEN": "Ungültiger Token", - "AUTH_ERROR": "Authentifizierung fehlgeschlagen", - "CONNECTION_ERROR": "Serververbindung kann nicht hergestellt werden", - "DOMAIN_ALREADY_EXISTS": "Diese Domain existiert bereits", - "DOMAIN_NOT_ALLOWED": "Diese Domain ist nicht zugelassen.", - "ACCOUNT_NOT_ALLOWED": "Konto ist nicht zugelassen.", - "CONTACTS_SYNC_ERROR": "Fehler bei Kontakte-Synchronisierung", - "CANT_GET_MESSAGE_LIST": "Die Nachrichtenliste ist nicht verfügbar", - "CANT_GET_MESSAGE": "Diese Nachricht ist nicht verfügbar", - "CANT_DELETE_MESSAGE": "Diese Nachricht kann nicht gelöscht werden", - "CANT_COPY_MESSAGE": "Diese Nachricht kann nicht kopiert werden", - "CANT_MOVE_MESSAGE": "Diese Nachricht kann nicht verschoben werden", - "CANT_SAVE_MESSAGE": "Diese Nachricht kann nicht gespeichert werden", - "CANT_SEND_MESSAGE": "Diese Nachricht kann nicht gesendet werden", - "INVALID_RECIPIENTS": "Ungültige Empfängeradressen", - "CANT_SAVE_FILTERS": "Die Filter können nicht gespeichert werden", - "CANT_GET_FILTERS": "Die Filter sind nicht verfügbar", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Filters-Skript kann nicht aktiviert werden", - "CANT_DELETE_FILTERS_SCRIPT": "Filters-Skript kann nicht gelöscht werden", - "FILTERS_ARE_NOT_CORRECT": "Die Filter sind fehlerhaft", - "CANT_CREATE_FOLDER": "Dieser Ordner kann nicht angelegt werden", - "CANT_RENAME_FOLDER": "Dieser Ordner kann nicht umbenannt werden", - "CANT_DELETE_FOLDER": "Dieser Ordner kann nicht gelöscht werden", - "CANT_DELETE_NON_EMPTY_FOLDER": "Der Ordner kann nicht gelöscht werden; er ist nicht leer", - "CANT_SUBSCRIBE_FOLDER": "Dieser Ordner kann nicht abonniert werden", - "CANT_UNSUBSCRIBE_FOLDER": "Das Abonnement dieses Ordners kann nicht gelöscht werden", - "DEMO_SEND_MESSAGE_ERROR": "Dieses Demokonto darf aus Sicherheitsgründen keine Nachrichten an externe E-Mail-Adressen versenden!", - "DEMO_ACCOUNT_ERROR": "Aus Sicherheitsgründen ist dieses Konto nicht zu dieser Aktion berechtigt!", - "ACCOUNT_ALREADY_EXISTS": "Dieses Konto existiert bereits", - "ACCOUNT_DOES_NOT_EXIST": "Dieser Account existiert nicht.", - "ACCOUNT_SWITCH_FAILED": "Konto wechseln \"%EMAIL%\" versagt", - "MAIL_SERVER_ERROR": "Beim Zugriff auf den E-Mail-Server trat ein Fehler auf.", - "INVALID_INPUT_ARGUMENT": "Ungültige Eingabe", - "UNKNOWN_ERROR": "Unbekannter Fehler" + "RequestError": "Anfrage fehlgeschlagen", + "RequestAborted": "Anfrage abgebrochen", + "RequestTimeout": "Antrag auf Auslieferung", + "InvalidToken": "Ungültiger Token", + "AuthError": "Authentifizierung fehlgeschlagen", + "ConnectionError": "Serververbindung kann nicht hergestellt werden", + "DomainAlreadyExists": "Diese Domain existiert bereits", + "DomainNotAllowed": "Diese Domain ist nicht zugelassen.", + "AccountNotAllowed": "Konto ist nicht zugelassen.", + "ContactsSyncError": "Fehler bei Kontakte-Synchronisierung", + "CantGetMessageList": "Die Nachrichtenliste ist nicht verfügbar", + "CantGetMessage": "Diese Nachricht ist nicht verfügbar", + "CantDeleteMessage": "Diese Nachricht kann nicht gelöscht werden", + "CantCopyMessage": "Diese Nachricht kann nicht kopiert werden", + "CantMoveMessage": "Diese Nachricht kann nicht verschoben werden", + "CantSaveMessage": "Diese Nachricht kann nicht gespeichert werden", + "CantSendMessage": "Diese Nachricht kann nicht gesendet werden", + "InvalidRecipients": "Ungültige Empfängeradressen", + "CantSaveFilters": "Die Filter können nicht gespeichert werden", + "CantGetFilters": "Die Filter sind nicht verfügbar", + "CantActivateFiltersScript": "Filters-Skript kann nicht aktiviert werden", + "CantDeleteFiltersScript": "Filters-Skript kann nicht gelöscht werden", + "FiltersAreNotCorrect": "Die Filter sind fehlerhaft", + "CantCreateFolder": "Dieser Ordner kann nicht angelegt werden", + "CantRenameFolder": "Dieser Ordner kann nicht umbenannt werden", + "CantDeleteFolder": "Dieser Ordner kann nicht gelöscht werden", + "CantDeleteNonEmptyFolder": "Der Ordner kann nicht gelöscht werden; er ist nicht leer", + "CantSubscribeFolder": "Dieser Ordner kann nicht abonniert werden", + "CantUnsubscribeFolder": "Das Abonnement dieses Ordners kann nicht gelöscht werden", + "DemoSendMessageError": "Dieses Demokonto darf aus Sicherheitsgründen keine Nachrichten an externe E-Mail-Adressen versenden!", + "DemoAccountError": "Aus Sicherheitsgründen ist dieses Konto nicht zu dieser Aktion berechtigt!", + "AccountAlreadyExists": "Dieses Konto existiert bereits", + "AccountDoesNotExist": "Dieser Account existiert nicht.", + "AccountSwitchFailed": "Konto wechseln \"%EMAIL%\" versagt", + "MailServerError": "Beim Zugriff auf den E-Mail-Server trat ein Fehler auf.", + "InvalidInputArgument": "Ungültige Eingabe", + "UnknownError": "Unbekannter Fehler" } } diff --git a/snappymail/v/0.0.0/app/localization/el-GR/user.json b/snappymail/v/0.0.0/app/localization/el-GR/user.json index 8e71fbdda..2aaeed110 100644 --- a/snappymail/v/0.0.0/app/localization/el-GR/user.json +++ b/snappymail/v/0.0.0/app/localization/el-GR/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "Close compose" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Invalid token", - "AUTH_ERROR": "Authentication failed", - "CONNECTION_ERROR": "Can't connect to server", - "DOMAIN_ALREADY_EXISTS": "Domain already exists", - "DOMAIN_NOT_ALLOWED": "Domain is not allowed", - "ACCOUNT_NOT_ALLOWED": "Account is not allowed", - "CONTACTS_SYNC_ERROR": "Contacts synchronization error", - "CANT_GET_MESSAGE_LIST": "Can't get message list", - "CANT_GET_MESSAGE": "Can't get message", - "CANT_DELETE_MESSAGE": "Can't delete message", - "CANT_COPY_MESSAGE": "Can't copy message", - "CANT_MOVE_MESSAGE": "Can't move message", - "CANT_SAVE_MESSAGE": "Can't save message", - "CANT_SEND_MESSAGE": "Can't send message", - "INVALID_RECIPIENTS": "Invalid recipients", - "CANT_SAVE_FILTERS": "Can't save filters", - "CANT_GET_FILTERS": "Can't get filters", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Can't activate filters script", - "CANT_DELETE_FILTERS_SCRIPT": "Can't delete filters script", - "FILTERS_ARE_NOT_CORRECT": "Filters are not correct", - "CANT_CREATE_FOLDER": "Can't create folder", - "CANT_RENAME_FOLDER": "Can't rename folder", - "CANT_DELETE_FOLDER": "Can't delete folder", - "CANT_DELETE_NON_EMPTY_FOLDER": "Can't delete non-empty directory", - "CANT_SUBSCRIBE_FOLDER": "Can't subscribe folder", - "CANT_UNSUBSCRIBE_FOLDER": "Can't unsubscribe folder", - "DEMO_SEND_MESSAGE_ERROR": "For security purposes, this account is not allowed to send messages to external e-mail addresses!", - "DEMO_ACCOUNT_ERROR": "For security purposes, this account is not allowed for this action!", - "ACCOUNT_ALREADY_EXISTS": "Account already exists", - "ACCOUNT_DOES_NOT_EXIST": "Account doesn't exist", - "ACCOUNT_SWITCH_FAILED": "Switch to account \"%EMAIL%\" failed", - "MAIL_SERVER_ERROR": "An error has occured while accessing mail server", - "INVALID_INPUT_ARGUMENT": "Invalid input argument", - "UNKNOWN_ERROR": "Unknown error" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Invalid token", + "AuthError": "Authentication failed", + "ConnectionError": "Can't connect to server", + "DomainAlreadyExists": "Domain already exists", + "DomainNotAllowed": "Domain is not allowed", + "AccountNotAllowed": "Account is not allowed", + "ContactsSyncError": "Contacts synchronization error", + "CantGetMessageList": "Can't get message list", + "CantGetMessage": "Can't get message", + "CantDeleteMessage": "Can't delete message", + "CantCopyMessage": "Can't copy message", + "CantMoveMessage": "Can't move message", + "CantSaveMessage": "Can't save message", + "CantSendMessage": "Can't send message", + "InvalidRecipients": "Invalid recipients", + "CantSaveFilters": "Can't save filters", + "CantGetFilters": "Can't get filters", + "CantActivateFiltersScript": "Can't activate filters script", + "CantDeleteFiltersScript": "Can't delete filters script", + "FiltersAreNotCorrect": "Filters are not correct", + "CantCreateFolder": "Can't create folder", + "CantRenameFolder": "Can't rename folder", + "CantDeleteFolder": "Can't delete folder", + "CantDeleteNonEmptyFolder": "Can't delete non-empty directory", + "CantSubscribeFolder": "Can't subscribe folder", + "CantUnsubscribeFolder": "Can't unsubscribe folder", + "DemoSendMessageError": "For security purposes, this account is not allowed to send messages to external e-mail addresses!", + "DemoAccountError": "For security purposes, this account is not allowed for this action!", + "AccountAlreadyExists": "Account already exists", + "AccountDoesNotExist": "Account doesn't exist", + "AccountSwitchFailed": "Switch to account \"%EMAIL%\" failed", + "MailServerError": "An error has occured while accessing mail server", + "InvalidInputArgument": "Invalid input argument", + "UnknownError": "Unknown error" } } diff --git a/snappymail/v/0.0.0/app/localization/en-GB/user.json b/snappymail/v/0.0.0/app/localization/en-GB/user.json index 599754e0c..4e8d90468 100644 --- a/snappymail/v/0.0.0/app/localization/en-GB/user.json +++ b/snappymail/v/0.0.0/app/localization/en-GB/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "Close compose" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Invalid token", - "AUTH_ERROR": "Authentication failed", - "CONNECTION_ERROR": "Can't connect to server", - "DOMAIN_ALREADY_EXISTS": "Domain already exists", - "DOMAIN_NOT_ALLOWED": "Domain is not allowed", - "ACCOUNT_NOT_ALLOWED": "Account is not allowed", - "CONTACTS_SYNC_ERROR": "Contacts synchronization error", - "CANT_GET_MESSAGE_LIST": "Can't get message list", - "CANT_GET_MESSAGE": "Can't get message", - "CANT_DELETE_MESSAGE": "Can't delete message", - "CANT_COPY_MESSAGE": "Can't copy message", - "CANT_MOVE_MESSAGE": "Can't move message", - "CANT_SAVE_MESSAGE": "Can't save message", - "CANT_SEND_MESSAGE": "Can't send message", - "INVALID_RECIPIENTS": "Invalid recipients", - "CANT_SAVE_FILTERS": "Can't save filters", - "CANT_GET_FILTERS": "Can't get filters", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Can't activate filters script", - "CANT_DELETE_FILTERS_SCRIPT": "Can't delete filters script", - "FILTERS_ARE_NOT_CORRECT": "Filters are not correct", - "CANT_CREATE_FOLDER": "Can't create folder", - "CANT_RENAME_FOLDER": "Can't rename folder", - "CANT_DELETE_FOLDER": "Can't delete folder", - "CANT_DELETE_NON_EMPTY_FOLDER": "Can't delete non-empty directory", - "CANT_SUBSCRIBE_FOLDER": "Can't subscribe folder", - "CANT_UNSUBSCRIBE_FOLDER": "Can't unsubscribe folder", - "DEMO_SEND_MESSAGE_ERROR": "For security purposes, this account is not allowed to send messages to external e-mail addresses!", - "DEMO_ACCOUNT_ERROR": "For security purposes, this account is not allowed for this action!", - "ACCOUNT_ALREADY_EXISTS": "Account already exists", - "ACCOUNT_DOES_NOT_EXIST": "Account doesn't exist", - "ACCOUNT_SWITCH_FAILED": "Switch to account \"%EMAIL%\" failed", - "MAIL_SERVER_ERROR": "An error has occured while accessing mail server", - "INVALID_INPUT_ARGUMENT": "Invalid input argument", - "UNKNOWN_ERROR": "Unknown error" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Invalid token", + "AuthError": "Authentication failed", + "ConnectionError": "Can't connect to server", + "DomainAlreadyExists": "Domain already exists", + "DomainNotAllowed": "Domain is not allowed", + "AccountNotAllowed": "Account is not allowed", + "ContactsSyncError": "Contacts synchronization error", + "CantGetMessageList": "Can't get message list", + "CantGetMessage": "Can't get message", + "CantDeleteMessage": "Can't delete message", + "CantCopyMessage": "Can't copy message", + "CantMoveMessage": "Can't move message", + "CantSaveMessage": "Can't save message", + "CantSendMessage": "Can't send message", + "InvalidRecipients": "Invalid recipients", + "CantSaveFilters": "Can't save filters", + "CantGetFilters": "Can't get filters", + "CantActivateFiltersScript": "Can't activate filters script", + "CantDeleteFiltersScript": "Can't delete filters script", + "FiltersAreNotCorrect": "Filters are not correct", + "CantCreateFolder": "Can't create folder", + "CantRenameFolder": "Can't rename folder", + "CantDeleteFolder": "Can't delete folder", + "CantDeleteNonEmptyFolder": "Can't delete non-empty directory", + "CantSubscribeFolder": "Can't subscribe folder", + "CantUnsubscribeFolder": "Can't unsubscribe folder", + "DemoSendMessageError": "For security purposes, this account is not allowed to send messages to external e-mail addresses!", + "DemoAccountError": "For security purposes, this account is not allowed for this action!", + "AccountAlreadyExists": "Account already exists", + "AccountDoesNotExist": "Account doesn't exist", + "AccountSwitchFailed": "Switch to account \"%EMAIL%\" failed", + "MailServerError": "An error has occured while accessing mail server", + "InvalidInputArgument": "Invalid input argument", + "UnknownError": "Unknown error" } } diff --git a/snappymail/v/0.0.0/app/localization/en/admin.json b/snappymail/v/0.0.0/app/localization/en/admin.json index ae7797e19..abe729cf4 100644 --- a/snappymail/v/0.0.0/app/localization/en/admin.json +++ b/snappymail/v/0.0.0/app/localization/en/admin.json @@ -107,7 +107,7 @@ "LABEL_ALL_RIGHTS_RESERVED": "All Rights Reserved.", "HINT_READ_CHANGE_LOG": "Please read the change log before updating.", "HINT_IS_UP_TO_DATE": "SnappyMail is up to date.", - "HTML_NEW_VERSION": "New %VERSION% version is available.", + "HTML_NEW_VERSION": "New %VERSION%<\/b> version is available.", "LABEL_UPDATING": "Updating", "LABEL_CHECKING": "Checking for updates", "BUTTON_RELEASES": "Releases" @@ -168,17 +168,17 @@ "UNKNOWN_ERROR": "Unknown error" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Invalid token", - "AUTH_ERROR": "Authentication failed", - "DOMAIN_ALREADY_EXISTS": "Domain already exists", - "CANT_SAVE_PLUGIN_SETTINGS": "Can't save settings", - "CANT_INSTALL_PACKAGE": "Failed to install extension", - "CANT_DELETE_PACKAGE": "Failed to remove extension", - "INVALID_PLUGIN_PACKAGE": "Invalid extension package", - "UNSUPPORTED_PLUGIN_PACKAGE": "Unsupported extension package", - "UNKNOWN_ERROR": "Unknown error" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Invalid token", + "AuthError": "Authentication failed", + "DomainAlreadyExists": "Domain already exists", + "CantSavePluginSettings": "Can't save settings", + "CantInstallPackage": "Failed to install extension", + "CantDeletePackage": "Failed to remove extension", + "InvalidPluginPackage": "Invalid extension package", + "UnsupportedPluginPackage": "Unsupported extension package", + "UnknownError": "Unknown error" } } diff --git a/snappymail/v/0.0.0/app/localization/en/user.json b/snappymail/v/0.0.0/app/localization/en/user.json index c42199b18..547c74d8f 100644 --- a/snappymail/v/0.0.0/app/localization/en/user.json +++ b/snappymail/v/0.0.0/app/localization/en/user.json @@ -303,12 +303,12 @@ "BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server" }, "SMIME": { - "POPUP_IMPORT_TITLE": "Import S/MIME certificate", + "POPUP_IMPORT_TITLE": "Import S\/MIME certificate", "CERTIFICATE": "Certificate", - "CERTIFICATES": "S/MIME Certificates", - "SIGNED_MESSAGE": "S/MIME signed message", - "ENCRYPTED_MESSAGE": "S/MIME encrypted message", - "PRIVATE_KEY_OF": "S/MIME private key of %EMAIL%" + "CERTIFICATES": "S\/MIME Certificates", + "SIGNED_MESSAGE": "S\/MIME signed message", + "ENCRYPTED_MESSAGE": "S\/MIME encrypted message", + "PRIVATE_KEY_OF": "S\/MIME private key of %EMAIL%" }, "POPUPS_FILTER": { "TITLE_CREATE_FILTER": "Create a filter?", @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "Close compose" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Invalid token", - "AUTH_ERROR": "Authentication failed", - "CONNECTION_ERROR": "Can't connect to server", - "DOMAIN_ALREADY_EXISTS": "Domain already exists", - "DOMAIN_NOT_ALLOWED": "Domain is not allowed", - "ACCOUNT_NOT_ALLOWED": "Account is not allowed", - "CONTACTS_SYNC_ERROR": "Contacts synchronization error", - "CANT_GET_MESSAGE_LIST": "Can't get message list", - "CANT_GET_MESSAGE": "Can't get message", - "CANT_DELETE_MESSAGE": "Can't delete message", - "CANT_COPY_MESSAGE": "Can't copy message", - "CANT_MOVE_MESSAGE": "Can't move message", - "CANT_SAVE_MESSAGE": "Can't save message", - "CANT_SEND_MESSAGE": "Can't send message", - "INVALID_RECIPIENTS": "Invalid recipients", - "CANT_SAVE_FILTERS": "Can't save filters", - "CANT_GET_FILTERS": "Can't get filters", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Can't activate filters script", - "CANT_DELETE_FILTERS_SCRIPT": "Can't delete filters script", - "FILTERS_ARE_NOT_CORRECT": "Filters are not correct", - "CANT_CREATE_FOLDER": "Can't create folder", - "CANT_RENAME_FOLDER": "Can't rename folder", - "CANT_DELETE_FOLDER": "Can't delete folder", - "CANT_DELETE_NON_EMPTY_FOLDER": "Can't delete non-empty directory", - "CANT_SUBSCRIBE_FOLDER": "Can't subscribe folder", - "CANT_UNSUBSCRIBE_FOLDER": "Can't unsubscribe folder", - "DEMO_SEND_MESSAGE_ERROR": "For security purposes, this account is not allowed to send messages to external e-mail addresses!", - "DEMO_ACCOUNT_ERROR": "For security purposes, this account is not allowed for this action!", - "ACCOUNT_ALREADY_EXISTS": "Account already exists", - "ACCOUNT_DOES_NOT_EXIST": "Account doesn't exist", - "ACCOUNT_SWITCH_FAILED": "Switch to account \"%EMAIL%\" failed", - "MAIL_SERVER_ERROR": "An error has occured while accessing mail server", - "INVALID_INPUT_ARGUMENT": "Invalid input argument", - "UNKNOWN_ERROR": "Unknown error" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Invalid token", + "AuthError": "Authentication failed", + "ConnectionError": "Can't connect to server", + "DomainAlreadyExists": "Domain already exists", + "DomainNotAllowed": "Domain is not allowed", + "AccountNotAllowed": "Account is not allowed", + "ContactsSyncError": "Contacts synchronization error", + "CantGetMessageList": "Can't get message list", + "CantGetMessage": "Can't get message", + "CantDeleteMessage": "Can't delete message", + "CantCopyMessage": "Can't copy message", + "CantMoveMessage": "Can't move message", + "CantSaveMessage": "Can't save message", + "CantSendMessage": "Can't send message", + "InvalidRecipients": "Invalid recipients", + "CantSaveFilters": "Can't save filters", + "CantGetFilters": "Can't get filters", + "CantActivateFiltersScript": "Can't activate filters script", + "CantDeleteFiltersScript": "Can't delete filters script", + "FiltersAreNotCorrect": "Filters are not correct", + "CantCreateFolder": "Can't create folder", + "CantRenameFolder": "Can't rename folder", + "CantDeleteFolder": "Can't delete folder", + "CantDeleteNonEmptyFolder": "Can't delete non-empty directory", + "CantSubscribeFolder": "Can't subscribe folder", + "CantUnsubscribeFolder": "Can't unsubscribe folder", + "DemoSendMessageError": "For security purposes, this account is not allowed to send messages to external e-mail addresses!", + "DemoAccountError": "For security purposes, this account is not allowed for this action!", + "AccountAlreadyExists": "Account already exists", + "AccountDoesNotExist": "Account doesn't exist", + "AccountSwitchFailed": "Switch to account \"%EMAIL%\" failed", + "MailServerError": "An error has occured while accessing mail server", + "InvalidInputArgument": "Invalid input argument", + "UnknownError": "Unknown error" } } diff --git a/snappymail/v/0.0.0/app/localization/es-ES/admin.json b/snappymail/v/0.0.0/app/localization/es-ES/admin.json index ccc13cdbf..17183a4d7 100644 --- a/snappymail/v/0.0.0/app/localization/es-ES/admin.json +++ b/snappymail/v/0.0.0/app/localization/es-ES/admin.json @@ -168,17 +168,17 @@ "UNKNOWN_ERROR": "Error desconocido" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Token inválido", - "AUTH_ERROR": "Autenticación fallida", - "DOMAIN_ALREADY_EXISTS": "El Dominio ya existe", - "CANT_SAVE_PLUGIN_SETTINGS": "No se pudieron guardar las configuraciones", - "CANT_INSTALL_PACKAGE": "No se ha podido instalar el extensión", - "CANT_DELETE_PACKAGE": "No se ha podido eliminar el extensión", - "INVALID_PLUGIN_PACKAGE": "El paquete de extensión no válido", - "UNSUPPORTED_PLUGIN_PACKAGE": "El paquete del extensión es incompatible", - "UNKNOWN_ERROR": "Error desconocido" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Token inválido", + "AuthError": "Autenticación fallida", + "DomainAlreadyExists": "El Dominio ya existe", + "CantSavePluginSettings": "No se pudieron guardar las configuraciones", + "CantInstallPackage": "No se ha podido instalar el extensión", + "CantDeletePackage": "No se ha podido eliminar el extensión", + "InvalidPluginPackage": "El paquete de extensión no válido", + "UnsupportedPluginPackage": "El paquete del extensión es incompatible", + "UnknownError": "Error desconocido" } } diff --git a/snappymail/v/0.0.0/app/localization/es-ES/user.json b/snappymail/v/0.0.0/app/localization/es-ES/user.json index 15ae227ad..3dec72e65 100644 --- a/snappymail/v/0.0.0/app/localization/es-ES/user.json +++ b/snappymail/v/0.0.0/app/localization/es-ES/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "Cerrar componer" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Elemento no válido", - "AUTH_ERROR": "Autentificación fallida", - "CONNECTION_ERROR": "No se puede conectar al servidor", - "DOMAIN_ALREADY_EXISTS": "El Dominio ya existe", - "DOMAIN_NOT_ALLOWED": "Dominio no permitido", - "ACCOUNT_NOT_ALLOWED": "La cuenta no está permitida", - "CONTACTS_SYNC_ERROR": "Error de sincronización de Contactos", - "CANT_GET_MESSAGE_LIST": "No se puede obtener la lista de mensajes", - "CANT_GET_MESSAGE": "No se puede obtener el mensaje", - "CANT_DELETE_MESSAGE": "No se puede eliminar el mensaje", - "CANT_COPY_MESSAGE": "No se puede copiar el mensaje", - "CANT_MOVE_MESSAGE": "No se puede mover el mensaje", - "CANT_SAVE_MESSAGE": "No se puede guardar el mensaje", - "CANT_SEND_MESSAGE": "No se puede enviar el mensaje", - "INVALID_RECIPIENTS": "Los destinatarios no son válidos", - "CANT_SAVE_FILTERS": "No se pueden guardar los filtros", - "CANT_GET_FILTERS": "No se pueden obtener los filtros", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Can't activate filters script", - "CANT_DELETE_FILTERS_SCRIPT": "Can't delete filters script", - "FILTERS_ARE_NOT_CORRECT": "Filtros incorrectos", - "CANT_CREATE_FOLDER": "No se puede crear la carpeta", - "CANT_RENAME_FOLDER": "No se puede renombrar la carpeta", - "CANT_DELETE_FOLDER": "No se puede eliminar la carpeta", - "CANT_DELETE_NON_EMPTY_FOLDER": "No se puede eliminar un directorio que no está vacío", - "CANT_SUBSCRIBE_FOLDER": "No se puede suscribir carpeta", - "CANT_UNSUBSCRIBE_FOLDER": "No puede darse de baja de la carpeta", - "DEMO_SEND_MESSAGE_ERROR": "Por razones de seguridad, esta cuenta demo no permite enviar mensajes a direcciones de correo electrónico externas!", - "DEMO_ACCOUNT_ERROR": "For security purposes, this account is not allowed for this action!", - "ACCOUNT_ALREADY_EXISTS": "La cuenta ya existe", - "ACCOUNT_DOES_NOT_EXIST": "La cuenta no existe", - "ACCOUNT_SWITCH_FAILED": "Switch to account \"%EMAIL%\" failed", - "MAIL_SERVER_ERROR": "Ocurrió un error mientras se accedía al servidor", - "INVALID_INPUT_ARGUMENT": "Argumento no válido", - "UNKNOWN_ERROR": "Error desconocido" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Elemento no válido", + "AuthError": "Autentificación fallida", + "ConnectionError": "No se puede conectar al servidor", + "DomainAlreadyExists": "El Dominio ya existe", + "DomainNotAllowed": "Dominio no permitido", + "AccountNotAllowed": "La cuenta no está permitida", + "ContactsSyncError": "Error de sincronización de Contactos", + "CantGetMessageList": "No se puede obtener la lista de mensajes", + "CantGetMessage": "No se puede obtener el mensaje", + "CantDeleteMessage": "No se puede eliminar el mensaje", + "CantCopyMessage": "No se puede copiar el mensaje", + "CantMoveMessage": "No se puede mover el mensaje", + "CantSaveMessage": "No se puede guardar el mensaje", + "CantSendMessage": "No se puede enviar el mensaje", + "InvalidRecipients": "Los destinatarios no son válidos", + "CantSaveFilters": "No se pueden guardar los filtros", + "CantGetFilters": "No se pueden obtener los filtros", + "CantActivateFiltersScript": "Can't activate filters script", + "CantDeleteFiltersScript": "Can't delete filters script", + "FiltersAreNotCorrect": "Filtros incorrectos", + "CantCreateFolder": "No se puede crear la carpeta", + "CantRenameFolder": "No se puede renombrar la carpeta", + "CantDeleteFolder": "No se puede eliminar la carpeta", + "CantDeleteNonEmptyFolder": "No se puede eliminar un directorio que no está vacío", + "CantSubscribeFolder": "No se puede suscribir carpeta", + "CantUnsubscribeFolder": "No puede darse de baja de la carpeta", + "DemoSendMessageError": "Por razones de seguridad, esta cuenta demo no permite enviar mensajes a direcciones de correo electrónico externas!", + "DemoAccountError": "For security purposes, this account is not allowed for this action!", + "AccountAlreadyExists": "La cuenta ya existe", + "AccountDoesNotExist": "La cuenta no existe", + "AccountSwitchFailed": "Switch to account \"%EMAIL%\" failed", + "MailServerError": "Ocurrió un error mientras se accedía al servidor", + "InvalidInputArgument": "Argumento no válido", + "UnknownError": "Error desconocido" } } diff --git a/snappymail/v/0.0.0/app/localization/et-EE/user.json b/snappymail/v/0.0.0/app/localization/et-EE/user.json index 3629b8826..b8e91f463 100644 --- a/snappymail/v/0.0.0/app/localization/et-EE/user.json +++ b/snappymail/v/0.0.0/app/localization/et-EE/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "Sulge kirja koostamise aken" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Puudulik tõend", - "AUTH_ERROR": "Autentimine ebaõnnestus", - "CONNECTION_ERROR": "Serveriga ühendumine ebaõnnestus", - "DOMAIN_ALREADY_EXISTS": "Domeen juba eksisteerib", - "DOMAIN_NOT_ALLOWED": "Domeenil ei ole lubatud siseneda", - "ACCOUNT_NOT_ALLOWED": "Kasutajakontol ei ole lubatud siseneda", - "CONTACTS_SYNC_ERROR": "Kontaktide sünkroniseerimise viga", - "CANT_GET_MESSAGE_LIST": "Kirjade nimekirja laadimine ebaõnnestus", - "CANT_GET_MESSAGE": "Kirja laadimine ebaõnnestus", - "CANT_DELETE_MESSAGE": "Kirja kustutamine ebaõnnestus", - "CANT_COPY_MESSAGE": "Can't copy message", - "CANT_MOVE_MESSAGE": "Kirja liigutamine ebaõnnestus", - "CANT_SAVE_MESSAGE": "Kirja salvestamine ebaõnnestus", - "CANT_SEND_MESSAGE": "Kirja saatmine ebaõnnestus", - "INVALID_RECIPIENTS": "Puudulikud saajad", - "CANT_SAVE_FILTERS": "Filtri salvestamine ebaõnnestus", - "CANT_GET_FILTERS": "Filtrite laadimine ebaõnnestus", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Can't activate filters script", - "CANT_DELETE_FILTERS_SCRIPT": "Can't delete filters script", - "FILTERS_ARE_NOT_CORRECT": "Filtrid on puudulikud", - "CANT_CREATE_FOLDER": "Kausta loomine ebaõnnestus", - "CANT_RENAME_FOLDER": "Kausta ümbernimetamine ebaõnnestus", - "CANT_DELETE_FOLDER": "Kausta kustutamine ebaõnnestus", - "CANT_DELETE_NON_EMPTY_FOLDER": "Kirju sisaldavat kausta pole võimalik kustutada", - "CANT_SUBSCRIBE_FOLDER": "Kausta tellimine ebaõnnestus.", - "CANT_UNSUBSCRIBE_FOLDER": "Kausta tellimisest loobumine ebaõnnestus.", - "DEMO_SEND_MESSAGE_ERROR": "Turvalisusega seotud põhjustel ei ole sellel kontol lubatud saata kirju välistele aadressidele!", - "DEMO_ACCOUNT_ERROR": "Turvalisusega seotud põhjustel ei ole sellel kontol lubatud soovitud toimingut teostada!", - "ACCOUNT_ALREADY_EXISTS": "Konto juba eksisteerib", - "ACCOUNT_DOES_NOT_EXIST": "Kontot veel ei eksisteeri", - "ACCOUNT_SWITCH_FAILED": "Switch to account \"%EMAIL%\" failed", - "MAIL_SERVER_ERROR": "E-posti serveri poole pöördumisel tekkis viga", - "INVALID_INPUT_ARGUMENT": "Puudulik sisendi arument", - "UNKNOWN_ERROR": "Tundmatu viga" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Puudulik tõend", + "AuthError": "Autentimine ebaõnnestus", + "ConnectionError": "Serveriga ühendumine ebaõnnestus", + "DomainAlreadyExists": "Domeen juba eksisteerib", + "DomainNotAllowed": "Domeenil ei ole lubatud siseneda", + "AccountNotAllowed": "Kasutajakontol ei ole lubatud siseneda", + "ContactsSyncError": "Kontaktide sünkroniseerimise viga", + "CantGetMessageList": "Kirjade nimekirja laadimine ebaõnnestus", + "CantGetMessage": "Kirja laadimine ebaõnnestus", + "CantDeleteMessage": "Kirja kustutamine ebaõnnestus", + "CantCopyMessage": "Can't copy message", + "CantMoveMessage": "Kirja liigutamine ebaõnnestus", + "CantSaveMessage": "Kirja salvestamine ebaõnnestus", + "CantSendMessage": "Kirja saatmine ebaõnnestus", + "InvalidRecipients": "Puudulikud saajad", + "CantSaveFilters": "Filtri salvestamine ebaõnnestus", + "CantGetFilters": "Filtrite laadimine ebaõnnestus", + "CantActivateFiltersScript": "Can't activate filters script", + "CantDeleteFiltersScript": "Can't delete filters script", + "FiltersAreNotCorrect": "Filtrid on puudulikud", + "CantCreateFolder": "Kausta loomine ebaõnnestus", + "CantRenameFolder": "Kausta ümbernimetamine ebaõnnestus", + "CantDeleteFolder": "Kausta kustutamine ebaõnnestus", + "CantDeleteNonEmptyFolder": "Kirju sisaldavat kausta pole võimalik kustutada", + "CantSubscribeFolder": "Kausta tellimine ebaõnnestus.", + "CantUnsubscribeFolder": "Kausta tellimisest loobumine ebaõnnestus.", + "DemoSendMessageError": "Turvalisusega seotud põhjustel ei ole sellel kontol lubatud saata kirju välistele aadressidele!", + "DemoAccountError": "Turvalisusega seotud põhjustel ei ole sellel kontol lubatud soovitud toimingut teostada!", + "AccountAlreadyExists": "Konto juba eksisteerib", + "AccountDoesNotExist": "Kontot veel ei eksisteeri", + "AccountSwitchFailed": "Switch to account \"%EMAIL%\" failed", + "MailServerError": "E-posti serveri poole pöördumisel tekkis viga", + "InvalidInputArgument": "Puudulik sisendi arument", + "UnknownError": "Tundmatu viga" } } diff --git a/snappymail/v/0.0.0/app/localization/eu/admin.json b/snappymail/v/0.0.0/app/localization/eu/admin.json index 8cf9cf9b7..a4609ce76 100644 --- a/snappymail/v/0.0.0/app/localization/eu/admin.json +++ b/snappymail/v/0.0.0/app/localization/eu/admin.json @@ -168,17 +168,17 @@ "UNKNOWN_ERROR": "Errore ezezaguna" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Eskaerak huts egin du", - "REQUEST_ABORTED": "Eskaera bertan behera utzi da", - "REQUEST_TIMEOUT": "Eskaeraren denbora-muga gainditu da", - "INVALID_TOKEN": "Ez-baliozko tokena", - "AUTH_ERROR": "Autentikazioak huts egin du", - "DOMAIN_ALREADY_EXISTS": "Domeinua jadanik existitzen da", - "CANT_SAVE_PLUGIN_SETTINGS": "Ezin dira ezarpenak gorde", - "CANT_INSTALL_PACKAGE": "Akatsa gehigarria instalatzean", - "CANT_DELETE_PACKAGE": "Akatsa gehigarria kentzean", - "INVALID_PLUGIN_PACKAGE": "Ez-baliozko gehigarri paketea", - "UNSUPPORTED_PLUGIN_PACKAGE": "Gehigarri paketea ez da onartzen", - "UNKNOWN_ERROR": "Errore ezezaguna" + "RequestError": "Eskaerak huts egin du", + "RequestAborted": "Eskaera bertan behera utzi da", + "RequestTimeout": "Eskaeraren denbora-muga gainditu da", + "InvalidToken": "Ez-baliozko tokena", + "AuthError": "Autentikazioak huts egin du", + "DomainAlreadyExists": "Domeinua jadanik existitzen da", + "CantSavePluginSettings": "Ezin dira ezarpenak gorde", + "CantInstallPackage": "Akatsa gehigarria instalatzean", + "CantDeletePackage": "Akatsa gehigarria kentzean", + "InvalidPluginPackage": "Ez-baliozko gehigarri paketea", + "UnsupportedPluginPackage": "Gehigarri paketea ez da onartzen", + "UnknownError": "Errore ezezaguna" } } diff --git a/snappymail/v/0.0.0/app/localization/eu/user.json b/snappymail/v/0.0.0/app/localization/eu/user.json index 2a560f4b7..0145c2877 100644 --- a/snappymail/v/0.0.0/app/localization/eu/user.json +++ b/snappymail/v/0.0.0/app/localization/eu/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "Itxi mezua" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Eskaerak huts egin du", - "REQUEST_ABORTED": "Eskaera bertan behera utzi da", - "REQUEST_TIMEOUT": "Eskaera denboraz kantpo", - "INVALID_TOKEN": "Ez-baliozko tokena", - "AUTH_ERROR": "Autentikazio errorea", - "CONNECTION_ERROR": "Ezin da zerbitzarira konektatu", - "DOMAIN_ALREADY_EXISTS": "Domeinua jadanik existitzen da", - "DOMAIN_NOT_ALLOWED": "Domeinu ez baimendua", - "ACCOUNT_NOT_ALLOWED": "Kontu ez baimendua", - "CONTACTS_SYNC_ERROR": "Kontaktu sinkronizazio errorea", - "CANT_GET_MESSAGE_LIST": "Ezin da mezuen zerrenda eskuratu", - "CANT_GET_MESSAGE": "Ezin da mezua eskuratu", - "CANT_DELETE_MESSAGE": "Ezin da mezua ezabatu", - "CANT_COPY_MESSAGE": "Ezin da mezua kopiatu", - "CANT_MOVE_MESSAGE": "Ezin da mezua mugitu", - "CANT_SAVE_MESSAGE": "Ezin da mezua gorde", - "CANT_SEND_MESSAGE": "Ezin da mezua bidali", - "INVALID_RECIPIENTS": "Ez-baliozko hartzaileak", - "CANT_SAVE_FILTERS": "Ezin dira iragazkiak gorde", - "CANT_GET_FILTERS": "Ezin dira iragazkiak eskuratu", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Ezin dira iragazki-scriptak aktibatu", - "CANT_DELETE_FILTERS_SCRIPT": "Ezin dira iragazki-scriptak ezabatu", - "FILTERS_ARE_NOT_CORRECT": "Iragazkiak ez dira zuzenak", - "CANT_CREATE_FOLDER": "Ezin da karpeta sortu", - "CANT_RENAME_FOLDER": "Ezin da karpeta berrizendatu", - "CANT_DELETE_FOLDER": "Ezin da karpeta ezabatu", - "CANT_DELETE_NON_EMPTY_FOLDER": "Ezin da hutsi ez dagoen direktorioa ezabatu", - "CANT_SUBSCRIBE_FOLDER": "Ezin da karpetara harpidetu", - "CANT_UNSUBSCRIBE_FOLDER": "Ezin da karpetatik harpidetza kendu", - "DEMO_SEND_MESSAGE_ERROR": "Segurtasunagatik, kontua honek ezin du kanpoko e-mail helbideetara mezurik bidali!", - "DEMO_ACCOUNT_ERROR": "Segurtasunagatik, kontu hau ez dago ahalbideratuta ekintza honetarako!", - "ACCOUNT_ALREADY_EXISTS": "Kontua jada existitzen da", - "ACCOUNT_DOES_NOT_EXIST": "Kontua ez da existitzen", - "ACCOUNT_SWITCH_FAILED": "\"%EMAIL%\" kontura aldaketak akatsa eman du", - "MAIL_SERVER_ERROR": "Errore bat gertatu da posta zebritzarira sartzean", - "INVALID_INPUT_ARGUMENT": "Ez-naliozko sarrera-argumentua", - "UNKNOWN_ERROR": "Errore ezezaguna" + "RequestError": "Eskaerak huts egin du", + "RequestAborted": "Eskaera bertan behera utzi da", + "RequestTimeout": "Eskaera denboraz kantpo", + "InvalidToken": "Ez-baliozko tokena", + "AuthError": "Autentikazio errorea", + "ConnectionError": "Ezin da zerbitzarira konektatu", + "DomainAlreadyExists": "Domeinua jadanik existitzen da", + "DomainNotAllowed": "Domeinu ez baimendua", + "AccountNotAllowed": "Kontu ez baimendua", + "ContactsSyncError": "Kontaktu sinkronizazio errorea", + "CantGetMessageList": "Ezin da mezuen zerrenda eskuratu", + "CantGetMessage": "Ezin da mezua eskuratu", + "CantDeleteMessage": "Ezin da mezua ezabatu", + "CantCopyMessage": "Ezin da mezua kopiatu", + "CantMoveMessage": "Ezin da mezua mugitu", + "CantSaveMessage": "Ezin da mezua gorde", + "CantSendMessage": "Ezin da mezua bidali", + "InvalidRecipients": "Ez-baliozko hartzaileak", + "CantSaveFilters": "Ezin dira iragazkiak gorde", + "CantGetFilters": "Ezin dira iragazkiak eskuratu", + "CantActivateFiltersScript": "Ezin dira iragazki-scriptak aktibatu", + "CantDeleteFiltersScript": "Ezin dira iragazki-scriptak ezabatu", + "FiltersAreNotCorrect": "Iragazkiak ez dira zuzenak", + "CantCreateFolder": "Ezin da karpeta sortu", + "CantRenameFolder": "Ezin da karpeta berrizendatu", + "CantDeleteFolder": "Ezin da karpeta ezabatu", + "CantDeleteNonEmptyFolder": "Ezin da hutsi ez dagoen direktorioa ezabatu", + "CantSubscribeFolder": "Ezin da karpetara harpidetu", + "CantUnsubscribeFolder": "Ezin da karpetatik harpidetza kendu", + "DemoSendMessageError": "Segurtasunagatik, kontua honek ezin du kanpoko e-mail helbideetara mezurik bidali!", + "DemoAccountError": "Segurtasunagatik, kontu hau ez dago ahalbideratuta ekintza honetarako!", + "AccountAlreadyExists": "Kontua jada existitzen da", + "AccountDoesNotExist": "Kontua ez da existitzen", + "AccountSwitchFailed": "\"%EMAIL%\" kontura aldaketak akatsa eman du", + "MailServerError": "Errore bat gertatu da posta zebritzarira sartzean", + "InvalidInputArgument": "Ez-naliozko sarrera-argumentua", + "UnknownError": "Errore ezezaguna" } } diff --git a/snappymail/v/0.0.0/app/localization/fa-IR/admin.json b/snappymail/v/0.0.0/app/localization/fa-IR/admin.json index 1bbc393c8..1b9c23c68 100644 --- a/snappymail/v/0.0.0/app/localization/fa-IR/admin.json +++ b/snappymail/v/0.0.0/app/localization/fa-IR/admin.json @@ -168,17 +168,17 @@ "UNKNOWN_ERROR": "خطای نامشخص" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "توکن نامعتبر", - "AUTH_ERROR": "احراز هویت انجام نشد", - "DOMAIN_ALREADY_EXISTS": "دامنه در حال حاضر موجود است", - "CANT_SAVE_PLUGIN_SETTINGS": "امکان ذخیره تنظیمات نیست", - "CANT_INSTALL_PACKAGE": "نصب بسته با خطا همراه بود", - "CANT_DELETE_PACKAGE": "حذف بسته با خطا همراه بو", - "INVALID_PLUGIN_PACKAGE": "بسته افزونه نامعتبر است", - "UNSUPPORTED_PLUGIN_PACKAGE": "بسته افزونه پشتیبانی نمی‌شود", - "UNKNOWN_ERROR": "خطای نامشخص" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "توکن نامعتبر", + "AuthError": "احراز هویت انجام نشد", + "DomainAlreadyExists": "دامنه در حال حاضر موجود است", + "CantSavePluginSettings": "امکان ذخیره تنظیمات نیست", + "CantInstallPackage": "نصب بسته با خطا همراه بود", + "CantDeletePackage": "حذف بسته با خطا همراه بو", + "InvalidPluginPackage": "بسته افزونه نامعتبر است", + "UnsupportedPluginPackage": "بسته افزونه پشتیبانی نمی‌شود", + "UnknownError": "خطای نامشخص" } } diff --git a/snappymail/v/0.0.0/app/localization/fa-IR/user.json b/snappymail/v/0.0.0/app/localization/fa-IR/user.json index 90eae77c2..797ed1584 100644 --- a/snappymail/v/0.0.0/app/localization/fa-IR/user.json +++ b/snappymail/v/0.0.0/app/localization/fa-IR/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "بستن صفحه ایجاد" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "توکن نامعتبر", - "AUTH_ERROR": "احراز هویت با موفقیت همراه نبود", - "CONNECTION_ERROR": "عدم اتصال به سرور", - "DOMAIN_ALREADY_EXISTS": "دامنه در حال حاضر موجود است", - "DOMAIN_NOT_ALLOWED": "به دامنه اجازه داده نشده است", - "ACCOUNT_NOT_ALLOWED": "به حساب کاربری اجازه داده نشده است", - "CONTACTS_SYNC_ERROR": "همگام‌سازی تماس‌ها با خطا همراه بود", - "CANT_GET_MESSAGE_LIST": "امکان دریافت لیست پیام‌ها نیست", - "CANT_GET_MESSAGE": "امکان دریافت پیام نیست", - "CANT_DELETE_MESSAGE": "امکان حذف پیام نیست", - "CANT_COPY_MESSAGE": "Can't copy message", - "CANT_MOVE_MESSAGE": "امکان انتقال پیام نیست", - "CANT_SAVE_MESSAGE": "امکان ذخیره پیام نیست", - "CANT_SEND_MESSAGE": "امکان ارسال پیام نیست", - "INVALID_RECIPIENTS": "گیرنده نامعتبر", - "CANT_SAVE_FILTERS": "امکان ذخیره فیلترها نیست", - "CANT_GET_FILTERS": "امکان دریافت فیلترها نیست", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Can't activate filters script", - "CANT_DELETE_FILTERS_SCRIPT": "Can't delete filters script", - "FILTERS_ARE_NOT_CORRECT": "فیلترها صحیح نیستند", - "CANT_CREATE_FOLDER": "امکان ایجاد شاخه وجود ندارد", - "CANT_RENAME_FOLDER": "امکان تغییر نام شاخه نیست", - "CANT_DELETE_FOLDER": "امکان حذف شاخه نیست", - "CANT_DELETE_NON_EMPTY_FOLDER": "امکان حذف شاخه‌ای که خالی نیست وجود ندارد", - "CANT_SUBSCRIBE_FOLDER": "امکان اشتراک شاخه نیست", - "CANT_UNSUBSCRIBE_FOLDER": "امکان عدم اشتراک شاخه نیست", - "DEMO_SEND_MESSAGE_ERROR": "بنابر اهداف امنیتی، این کاربر اجازه ارسال ایمیل به یک ایمیل خارج از دامنه را ندارد!", - "DEMO_ACCOUNT_ERROR": "بنابر اهداف امنیتی، این کاربر اجازه انجام این عملیات را ندارد!", - "ACCOUNT_ALREADY_EXISTS": "کاربر وجود دارد", - "ACCOUNT_DOES_NOT_EXIST": "کاربر وجود ندارد", - "ACCOUNT_SWITCH_FAILED": "Switch to account \"%EMAIL%\" failed", - "MAIL_SERVER_ERROR": "یک خطا در زمان دسترسی به سرویس پست الکترونیک رخ داد", - "INVALID_INPUT_ARGUMENT": "پارامترهای ورودی نامعتبر", - "UNKNOWN_ERROR": "خطای نامشخص" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "توکن نامعتبر", + "AuthError": "احراز هویت با موفقیت همراه نبود", + "ConnectionError": "عدم اتصال به سرور", + "DomainAlreadyExists": "دامنه در حال حاضر موجود است", + "DomainNotAllowed": "به دامنه اجازه داده نشده است", + "AccountNotAllowed": "به حساب کاربری اجازه داده نشده است", + "ContactsSyncError": "همگام‌سازی تماس‌ها با خطا همراه بود", + "CantGetMessageList": "امکان دریافت لیست پیام‌ها نیست", + "CantGetMessage": "امکان دریافت پیام نیست", + "CantDeleteMessage": "امکان حذف پیام نیست", + "CantCopyMessage": "Can't copy message", + "CantMoveMessage": "امکان انتقال پیام نیست", + "CantSaveMessage": "امکان ذخیره پیام نیست", + "CantSendMessage": "امکان ارسال پیام نیست", + "InvalidRecipients": "گیرنده نامعتبر", + "CantSaveFilters": "امکان ذخیره فیلترها نیست", + "CantGetFilters": "امکان دریافت فیلترها نیست", + "CantActivateFiltersScript": "Can't activate filters script", + "CantDeleteFiltersScript": "Can't delete filters script", + "FiltersAreNotCorrect": "فیلترها صحیح نیستند", + "CantCreateFolder": "امکان ایجاد شاخه وجود ندارد", + "CantRenameFolder": "امکان تغییر نام شاخه نیست", + "CantDeleteFolder": "امکان حذف شاخه نیست", + "CantDeleteNonEmptyFolder": "امکان حذف شاخه‌ای که خالی نیست وجود ندارد", + "CantSubscribeFolder": "امکان اشتراک شاخه نیست", + "CantUnsubscribeFolder": "امکان عدم اشتراک شاخه نیست", + "DemoSendMessageError": "بنابر اهداف امنیتی، این کاربر اجازه ارسال ایمیل به یک ایمیل خارج از دامنه را ندارد!", + "DemoAccountError": "بنابر اهداف امنیتی، این کاربر اجازه انجام این عملیات را ندارد!", + "AccountAlreadyExists": "کاربر وجود دارد", + "AccountDoesNotExist": "کاربر وجود ندارد", + "AccountSwitchFailed": "Switch to account \"%EMAIL%\" failed", + "MailServerError": "یک خطا در زمان دسترسی به سرویس پست الکترونیک رخ داد", + "InvalidInputArgument": "پارامترهای ورودی نامعتبر", + "UnknownError": "خطای نامشخص" } } diff --git a/snappymail/v/0.0.0/app/localization/fi-FI/admin.json b/snappymail/v/0.0.0/app/localization/fi-FI/admin.json index 3fed9ed01..94354fad1 100644 --- a/snappymail/v/0.0.0/app/localization/fi-FI/admin.json +++ b/snappymail/v/0.0.0/app/localization/fi-FI/admin.json @@ -168,17 +168,17 @@ "UNKNOWN_ERROR": "Tuntematon virhe" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Väärä token", - "AUTH_ERROR": "Tunnistautuminen epäonnistui", - "DOMAIN_ALREADY_EXISTS": "Verkkotunnus on jo olemassa", - "CANT_SAVE_PLUGIN_SETTINGS": "Asetuksia ei voida tallentaa", - "CANT_INSTALL_PACKAGE": "Paketin asennus epäonnistui", - "CANT_DELETE_PACKAGE": "Paketin poisto epäonnistui", - "INVALID_PLUGIN_PACKAGE": "Virheellinen lisäosa-paketti", - "UNSUPPORTED_PLUGIN_PACKAGE": "Ei tuettu lisäosa-paketti", - "UNKNOWN_ERROR": "Tuntematon virhe" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Väärä token", + "AuthError": "Tunnistautuminen epäonnistui", + "DomainAlreadyExists": "Verkkotunnus on jo olemassa", + "CantSavePluginSettings": "Asetuksia ei voida tallentaa", + "CantInstallPackage": "Paketin asennus epäonnistui", + "CantDeletePackage": "Paketin poisto epäonnistui", + "InvalidPluginPackage": "Virheellinen lisäosa-paketti", + "UnsupportedPluginPackage": "Ei tuettu lisäosa-paketti", + "UnknownError": "Tuntematon virhe" } } diff --git a/snappymail/v/0.0.0/app/localization/fi-FI/user.json b/snappymail/v/0.0.0/app/localization/fi-FI/user.json index 61de7d2f1..de67cb02c 100644 --- a/snappymail/v/0.0.0/app/localization/fi-FI/user.json +++ b/snappymail/v/0.0.0/app/localization/fi-FI/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "Sule luo viesti" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Väärä suojaustunnus", - "AUTH_ERROR": "Tunnistusvirhe", - "CONNECTION_ERROR": "Ei voi yhdistää palvelimeen", - "DOMAIN_ALREADY_EXISTS": "Verkkotunnus on jo olemassa", - "DOMAIN_NOT_ALLOWED": "Verkkotunnus ei ole sallittu", - "ACCOUNT_NOT_ALLOWED": "Tili ei ole sallittu", - "CONTACTS_SYNC_ERROR": "Yhteystietojen synkronointivirhe", - "CANT_GET_MESSAGE_LIST": "Viestilistaa ei voi näyttää", - "CANT_GET_MESSAGE": "Viestiä ei voi näyttää", - "CANT_DELETE_MESSAGE": "Viestiä ei voi poistaa", - "CANT_COPY_MESSAGE": "Can't copy message", - "CANT_MOVE_MESSAGE": "Viestiä ei voi siirtää", - "CANT_SAVE_MESSAGE": "Viestiä ei voi tallentaa", - "CANT_SEND_MESSAGE": "Viestiä ei voi lähettää", - "INVALID_RECIPIENTS": "Vastaanottajassa virhe", - "CANT_SAVE_FILTERS": "Suodattimia ei voi tallentaa", - "CANT_GET_FILTERS": "Suodattimia ei voi ladata", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Can't activate filters script", - "CANT_DELETE_FILTERS_SCRIPT": "Can't delete filters script", - "FILTERS_ARE_NOT_CORRECT": "Suodattimet väärin", - "CANT_CREATE_FOLDER": "Kansiota ei voi luoda", - "CANT_RENAME_FOLDER": "Kansiota ei voi uudelleennimetä", - "CANT_DELETE_FOLDER": "Kansiota ei voi poistaa", - "CANT_DELETE_NON_EMPTY_FOLDER": "Kansiossa on viestejä, ei voi poistaa", - "CANT_SUBSCRIBE_FOLDER": "Kansiota ei voi tilata", - "CANT_UNSUBSCRIBE_FOLDER": "Kansiotilausta ei voi peruuttaa", - "DEMO_SEND_MESSAGE_ERROR": "Turvallisuus syistä tältä tililtä ei voi lähettää viestejä ulkopuolisiin osoitteisiin!", - "DEMO_ACCOUNT_ERROR": "Turvallisuus syistä tämä ei ole sallittua!", - "ACCOUNT_ALREADY_EXISTS": "Tili on jo olemassa.", - "ACCOUNT_DOES_NOT_EXIST": "Tiliä ei ole olemassa", - "ACCOUNT_SWITCH_FAILED": "Switch to account \"%EMAIL%\" failed", - "MAIL_SERVER_ERROR": "Palvelinyhteydessä tapahtui virhe", - "INVALID_INPUT_ARGUMENT": "Virheelinen komento", - "UNKNOWN_ERROR": "Tuntematon virhe" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Väärä suojaustunnus", + "AuthError": "Tunnistusvirhe", + "ConnectionError": "Ei voi yhdistää palvelimeen", + "DomainAlreadyExists": "Verkkotunnus on jo olemassa", + "DomainNotAllowed": "Verkkotunnus ei ole sallittu", + "AccountNotAllowed": "Tili ei ole sallittu", + "ContactsSyncError": "Yhteystietojen synkronointivirhe", + "CantGetMessageList": "Viestilistaa ei voi näyttää", + "CantGetMessage": "Viestiä ei voi näyttää", + "CantDeleteMessage": "Viestiä ei voi poistaa", + "CantCopyMessage": "Can't copy message", + "CantMoveMessage": "Viestiä ei voi siirtää", + "CantSaveMessage": "Viestiä ei voi tallentaa", + "CantSendMessage": "Viestiä ei voi lähettää", + "InvalidRecipients": "Vastaanottajassa virhe", + "CantSaveFilters": "Suodattimia ei voi tallentaa", + "CantGetFilters": "Suodattimia ei voi ladata", + "CantActivateFiltersScript": "Can't activate filters script", + "CantDeleteFiltersScript": "Can't delete filters script", + "FiltersAreNotCorrect": "Suodattimet väärin", + "CantCreateFolder": "Kansiota ei voi luoda", + "CantRenameFolder": "Kansiota ei voi uudelleennimetä", + "CantDeleteFolder": "Kansiota ei voi poistaa", + "CantDeleteNonEmptyFolder": "Kansiossa on viestejä, ei voi poistaa", + "CantSubscribeFolder": "Kansiota ei voi tilata", + "CantUnsubscribeFolder": "Kansiotilausta ei voi peruuttaa", + "DemoSendMessageError": "Turvallisuus syistä tältä tililtä ei voi lähettää viestejä ulkopuolisiin osoitteisiin!", + "DemoAccountError": "Turvallisuus syistä tämä ei ole sallittua!", + "AccountAlreadyExists": "Tili on jo olemassa.", + "AccountDoesNotExist": "Tiliä ei ole olemassa", + "AccountSwitchFailed": "Switch to account \"%EMAIL%\" failed", + "MailServerError": "Palvelinyhteydessä tapahtui virhe", + "InvalidInputArgument": "Virheelinen komento", + "UnknownError": "Tuntematon virhe" } } diff --git a/snappymail/v/0.0.0/app/localization/fr-FR/admin.json b/snappymail/v/0.0.0/app/localization/fr-FR/admin.json index ae74e7f74..d651ab977 100644 --- a/snappymail/v/0.0.0/app/localization/fr-FR/admin.json +++ b/snappymail/v/0.0.0/app/localization/fr-FR/admin.json @@ -168,17 +168,17 @@ "UNKNOWN_ERROR": "Erreur inconnue" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "La requête a échouée", - "REQUEST_ABORTED": "La requête a été annulée", - "REQUEST_TIMEOUT": "La requête a expirée", - "INVALID_TOKEN": "Jeton invalide", - "AUTH_ERROR": "L'authentification a échoué", - "DOMAIN_ALREADY_EXISTS": "Le domaine existe déjà", - "CANT_SAVE_PLUGIN_SETTINGS": "Vous ne pouvez pas enregistrer les paramètres", - "CANT_INSTALL_PACKAGE": "Impossible d'installer le extension", - "CANT_DELETE_PACKAGE": "Impossible de supprimer le extension", - "INVALID_PLUGIN_PACKAGE": "Package d'extension non valide", - "UNSUPPORTED_PLUGIN_PACKAGE": "Package d'extension non pris en charge", - "UNKNOWN_ERROR": "Erreur inconnue" + "RequestError": "La requête a échouée", + "RequestAborted": "La requête a été annulée", + "RequestTimeout": "La requête a expirée", + "InvalidToken": "Jeton invalide", + "AuthError": "L'authentification a échoué", + "DomainAlreadyExists": "Le domaine existe déjà", + "CantSavePluginSettings": "Vous ne pouvez pas enregistrer les paramètres", + "CantInstallPackage": "Impossible d'installer le extension", + "CantDeletePackage": "Impossible de supprimer le extension", + "InvalidPluginPackage": "Package d'extension non valide", + "UnsupportedPluginPackage": "Package d'extension non pris en charge", + "UnknownError": "Erreur inconnue" } } diff --git a/snappymail/v/0.0.0/app/localization/fr-FR/user.json b/snappymail/v/0.0.0/app/localization/fr-FR/user.json index a7fb60907..9ecfbfe3c 100644 --- a/snappymail/v/0.0.0/app/localization/fr-FR/user.json +++ b/snappymail/v/0.0.0/app/localization/fr-FR/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "Fermer la fenêtre d'édition" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "La requête a échouée", - "REQUEST_ABORTED": "La requête a été annulée", - "REQUEST_TIMEOUT": "La requête a expirée", - "INVALID_TOKEN": "Jeton invalide", - "AUTH_ERROR": "L'authentification a échoué", - "CONNECTION_ERROR": "Serveur injoignable", - "DOMAIN_ALREADY_EXISTS": "Le domaine existe déjà", - "DOMAIN_NOT_ALLOWED": "Ce domaine n'est pas autorisé", - "ACCOUNT_NOT_ALLOWED": "Ce compte n'est pas autorisé", - "CONTACTS_SYNC_ERROR": "Erreur de synchronisation des contacts", - "CANT_GET_MESSAGE_LIST": "Impossible d'obtenir la liste des messages", - "CANT_GET_MESSAGE": "Impossible d'obtenir le message", - "CANT_DELETE_MESSAGE": "Impossible de supprimer le message", - "CANT_COPY_MESSAGE": "Impossible de copier le message", - "CANT_MOVE_MESSAGE": "Impossible de déplacer le message", - "CANT_SAVE_MESSAGE": "Impossible d'enregistrer le message", - "CANT_SEND_MESSAGE": "Impossible d'envoyer le message", - "INVALID_RECIPIENTS": "Destinataires invalides", - "CANT_SAVE_FILTERS": "Impossible d'enregistrer les filtres", - "CANT_GET_FILTERS": "Impossible d'obtenir les filtres", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Impossible d'activer le script des filtres", - "CANT_DELETE_FILTERS_SCRIPT": "Impossible de supprimer le script des filtres", - "FILTERS_ARE_NOT_CORRECT": "Les filtres ne sont pas corrects", - "CANT_CREATE_FOLDER": "Impossible de créer le dossier", - "CANT_RENAME_FOLDER": "Impossible de renommer le dossier", - "CANT_DELETE_FOLDER": "Impossible de supprimer le dossier", - "CANT_DELETE_NON_EMPTY_FOLDER": "Impossible de supprimer un dossier non vide", - "CANT_SUBSCRIBE_FOLDER": "Impossible de s'abonner au dossier", - "CANT_UNSUBSCRIBE_FOLDER": "Impossible de se désabonner du dossier", - "DEMO_SEND_MESSAGE_ERROR": "Pour des raisons de sécurité, ce compte de démonstration n'est pas autorisé à envoyer des messages à des adresses e-mail externes !", - "DEMO_ACCOUNT_ERROR": "Pour des raisons de sécurité, ce compte n'est pas autorisé à faire cette action !", - "ACCOUNT_ALREADY_EXISTS": "Ce compte existe déjà", - "ACCOUNT_DOES_NOT_EXIST": "Ce compte n'existe pas", - "ACCOUNT_SWITCH_FAILED": "Switch vers le compte \"%EMAIL%\" a échoué", - "MAIL_SERVER_ERROR": "Une erreur est survenue lors de l'accès au serveur mail", - "INVALID_INPUT_ARGUMENT": "Argument invalide", - "UNKNOWN_ERROR": "Erreur inconnue" + "RequestError": "La requête a échouée", + "RequestAborted": "La requête a été annulée", + "RequestTimeout": "La requête a expirée", + "InvalidToken": "Jeton invalide", + "AuthError": "L'authentification a échoué", + "ConnectionError": "Serveur injoignable", + "DomainAlreadyExists": "Le domaine existe déjà", + "DomainNotAllowed": "Ce domaine n'est pas autorisé", + "AccountNotAllowed": "Ce compte n'est pas autorisé", + "ContactsSyncError": "Erreur de synchronisation des contacts", + "CantGetMessageList": "Impossible d'obtenir la liste des messages", + "CantGetMessage": "Impossible d'obtenir le message", + "CantDeleteMessage": "Impossible de supprimer le message", + "CantCopyMessage": "Impossible de copier le message", + "CantMoveMessage": "Impossible de déplacer le message", + "CantSaveMessage": "Impossible d'enregistrer le message", + "CantSendMessage": "Impossible d'envoyer le message", + "InvalidRecipients": "Destinataires invalides", + "CantSaveFilters": "Impossible d'enregistrer les filtres", + "CantGetFilters": "Impossible d'obtenir les filtres", + "CantActivateFiltersScript": "Impossible d'activer le script des filtres", + "CantDeleteFiltersScript": "Impossible de supprimer le script des filtres", + "FiltersAreNotCorrect": "Les filtres ne sont pas corrects", + "CantCreateFolder": "Impossible de créer le dossier", + "CantRenameFolder": "Impossible de renommer le dossier", + "CantDeleteFolder": "Impossible de supprimer le dossier", + "CantDeleteNonEmptyFolder": "Impossible de supprimer un dossier non vide", + "CantSubscribeFolder": "Impossible de s'abonner au dossier", + "CantUnsubscribeFolder": "Impossible de se désabonner du dossier", + "DemoSendMessageError": "Pour des raisons de sécurité, ce compte de démonstration n'est pas autorisé à envoyer des messages à des adresses e-mail externes !", + "DemoAccountError": "Pour des raisons de sécurité, ce compte n'est pas autorisé à faire cette action !", + "AccountAlreadyExists": "Ce compte existe déjà", + "AccountDoesNotExist": "Ce compte n'existe pas", + "AccountSwitchFailed": "Switch vers le compte \"%EMAIL%\" a échoué", + "MailServerError": "Une erreur est survenue lors de l'accès au serveur mail", + "InvalidInputArgument": "Argument invalide", + "UnknownError": "Erreur inconnue" } } diff --git a/snappymail/v/0.0.0/app/localization/hu-HU/admin.json b/snappymail/v/0.0.0/app/localization/hu-HU/admin.json index f400c4a73..41daa0787 100644 --- a/snappymail/v/0.0.0/app/localization/hu-HU/admin.json +++ b/snappymail/v/0.0.0/app/localization/hu-HU/admin.json @@ -168,17 +168,17 @@ "UNKNOWN_ERROR": "Ismeretlen hiba" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Érvénytelen token", - "AUTH_ERROR": "Sikertelen hitelesítés", - "DOMAIN_ALREADY_EXISTS": "A domain már létezik", - "CANT_SAVE_PLUGIN_SETTINGS": "Nem lehet menteni a beállításokat", - "CANT_INSTALL_PACKAGE": "Nem sikerült telepíteni a bővítményt", - "CANT_DELETE_PACKAGE": "Nem sikerült eltávolítani a bővítményt", - "INVALID_PLUGIN_PACKAGE": "Érvénytelen kiterjesztési csomag", - "UNSUPPORTED_PLUGIN_PACKAGE": "Nem támogatott bővítménycsomag", - "UNKNOWN_ERROR": "Ismeretlen hiba" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Érvénytelen token", + "AuthError": "Sikertelen hitelesítés", + "DomainAlreadyExists": "A domain már létezik", + "CantSavePluginSettings": "Nem lehet menteni a beállításokat", + "CantInstallPackage": "Nem sikerült telepíteni a bővítményt", + "CantDeletePackage": "Nem sikerült eltávolítani a bővítményt", + "InvalidPluginPackage": "Érvénytelen kiterjesztési csomag", + "UnsupportedPluginPackage": "Nem támogatott bővítménycsomag", + "UnknownError": "Ismeretlen hiba" } } diff --git a/snappymail/v/0.0.0/app/localization/hu-HU/user.json b/snappymail/v/0.0.0/app/localization/hu-HU/user.json index e52ba69b0..96f3e8301 100644 --- a/snappymail/v/0.0.0/app/localization/hu-HU/user.json +++ b/snappymail/v/0.0.0/app/localization/hu-HU/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "Levélírás bezárása" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Érvénytelen kulcs", - "AUTH_ERROR": "Érvénytelen hitelesítés", - "CONNECTION_ERROR": "Nem lehet kapcsolódni a szerverhez", - "DOMAIN_ALREADY_EXISTS": "A domain már létezik", - "DOMAIN_NOT_ALLOWED": "A domain nem engedélyezett", - "ACCOUNT_NOT_ALLOWED": "A fiók nem engedélyezett", - "CONTACTS_SYNC_ERROR": "Hiba lépett fel a névjegyek szinkronizálása közben", - "CANT_GET_MESSAGE_LIST": "Nem tudom letölteni az üzenetlistát", - "CANT_GET_MESSAGE": "Nem tudom letölteni az üzenetet", - "CANT_DELETE_MESSAGE": "Nem lehet törölni az üzenetet", - "CANT_COPY_MESSAGE": "Can't copy message", - "CANT_MOVE_MESSAGE": "Nem lehet áthelyezni az üzenetet", - "CANT_SAVE_MESSAGE": "Nem lehet menteni az üzenetet", - "CANT_SEND_MESSAGE": "Nem lehet elküldeni az üzenetet", - "INVALID_RECIPIENTS": "Érvénytelent címzettek", - "CANT_SAVE_FILTERS": "Nem lehet menteni a szűrőket", - "CANT_GET_FILTERS": "Nem lehet letölteni a szűrőket", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Can't activate filters script", - "CANT_DELETE_FILTERS_SCRIPT": "Can't delete filters script", - "FILTERS_ARE_NOT_CORRECT": "A szűrők nem megfelelőek", - "CANT_CREATE_FOLDER": "Nem lehet létrehozni a mappát", - "CANT_RENAME_FOLDER": "Nem lehet átnevezni a mappát", - "CANT_DELETE_FOLDER": "Nem lehet törölni a mappát", - "CANT_DELETE_NON_EMPTY_FOLDER": "Nem üres mappát nem lehet törölni", - "CANT_SUBSCRIBE_FOLDER": "Nem lehet feliratkozni mappára", - "CANT_UNSUBSCRIBE_FOLDER": "Nem lehet leiratkozni mappáról", - "DEMO_SEND_MESSAGE_ERROR": "Biztonsági okokból, ebből a demó fiókból nem lehet külső e-mail címekre üzenetet küldeni.", - "DEMO_ACCOUNT_ERROR": "Biztonsági okokból, ebből a fiókból nem lehet elvégezni ezt a műveletet!", - "ACCOUNT_ALREADY_EXISTS": "A fiók már létezik", - "ACCOUNT_DOES_NOT_EXIST": "A fiók nem létezik", - "ACCOUNT_SWITCH_FAILED": "Switch to account \"%EMAIL%\" failed", - "MAIL_SERVER_ERROR": "Hiba történt a levelező szerverhez történő hozzáférés közben", - "INVALID_INPUT_ARGUMENT": "Érvénytelen input argumentum", - "UNKNOWN_ERROR": "Ismeretlen hiba" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Érvénytelen kulcs", + "AuthError": "Érvénytelen hitelesítés", + "ConnectionError": "Nem lehet kapcsolódni a szerverhez", + "DomainAlreadyExists": "A domain már létezik", + "DomainNotAllowed": "A domain nem engedélyezett", + "AccountNotAllowed": "A fiók nem engedélyezett", + "ContactsSyncError": "Hiba lépett fel a névjegyek szinkronizálása közben", + "CantGetMessageList": "Nem tudom letölteni az üzenetlistát", + "CantGetMessage": "Nem tudom letölteni az üzenetet", + "CantDeleteMessage": "Nem lehet törölni az üzenetet", + "CantCopyMessage": "Can't copy message", + "CantMoveMessage": "Nem lehet áthelyezni az üzenetet", + "CantSaveMessage": "Nem lehet menteni az üzenetet", + "CantSendMessage": "Nem lehet elküldeni az üzenetet", + "InvalidRecipients": "Érvénytelent címzettek", + "CantSaveFilters": "Nem lehet menteni a szűrőket", + "CantGetFilters": "Nem lehet letölteni a szűrőket", + "CantActivateFiltersScript": "Can't activate filters script", + "CantDeleteFiltersScript": "Can't delete filters script", + "FiltersAreNotCorrect": "A szűrők nem megfelelőek", + "CantCreateFolder": "Nem lehet létrehozni a mappát", + "CantRenameFolder": "Nem lehet átnevezni a mappát", + "CantDeleteFolder": "Nem lehet törölni a mappát", + "CantDeleteNonEmptyFolder": "Nem üres mappát nem lehet törölni", + "CantSubscribeFolder": "Nem lehet feliratkozni mappára", + "CantUnsubscribeFolder": "Nem lehet leiratkozni mappáról", + "DemoSendMessageError": "Biztonsági okokból, ebből a demó fiókból nem lehet külső e-mail címekre üzenetet küldeni.", + "DemoAccountError": "Biztonsági okokból, ebből a fiókból nem lehet elvégezni ezt a műveletet!", + "AccountAlreadyExists": "A fiók már létezik", + "AccountDoesNotExist": "A fiók nem létezik", + "AccountSwitchFailed": "Switch to account \"%EMAIL%\" failed", + "MailServerError": "Hiba történt a levelező szerverhez történő hozzáférés közben", + "InvalidInputArgument": "Érvénytelen input argumentum", + "UnknownError": "Ismeretlen hiba" } } diff --git a/snappymail/v/0.0.0/app/localization/id-ID/admin.json b/snappymail/v/0.0.0/app/localization/id-ID/admin.json index 9dd0666d0..e0f269a1c 100644 --- a/snappymail/v/0.0.0/app/localization/id-ID/admin.json +++ b/snappymail/v/0.0.0/app/localization/id-ID/admin.json @@ -168,17 +168,17 @@ "UNKNOWN_ERROR": "Kesalahan tidak diketahui" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Token invalid", - "AUTH_ERROR": "Otentikasi gagal", - "DOMAIN_ALREADY_EXISTS": "Domain sudah ada", - "CANT_SAVE_PLUGIN_SETTINGS": "Tidak bisa menyimpan pengaturan", - "CANT_INSTALL_PACKAGE": "Gagal memasang paket", - "CANT_DELETE_PACKAGE": "Gagal menghapus paket", - "INVALID_PLUGIN_PACKAGE": "Paket plugin tidak sah", - "UNSUPPORTED_PLUGIN_PACKAGE": "Paket plugin tidak didukung", - "UNKNOWN_ERROR": "Kesalahan tidak diketahui" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Token invalid", + "AuthError": "Otentikasi gagal", + "DomainAlreadyExists": "Domain sudah ada", + "CantSavePluginSettings": "Tidak bisa menyimpan pengaturan", + "CantInstallPackage": "Gagal memasang paket", + "CantDeletePackage": "Gagal menghapus paket", + "InvalidPluginPackage": "Paket plugin tidak sah", + "UnsupportedPluginPackage": "Paket plugin tidak didukung", + "UnknownError": "Kesalahan tidak diketahui" } } diff --git a/snappymail/v/0.0.0/app/localization/id-ID/user.json b/snappymail/v/0.0.0/app/localization/id-ID/user.json index a80534b95..aa88f161c 100644 --- a/snappymail/v/0.0.0/app/localization/id-ID/user.json +++ b/snappymail/v/0.0.0/app/localization/id-ID/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "Tutup buat pesan" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Token tidak sah", - "AUTH_ERROR": "Otentikasi gagal", - "CONNECTION_ERROR": "Tidak terhubung ke server", - "DOMAIN_ALREADY_EXISTS": "Domain telah ada", - "DOMAIN_NOT_ALLOWED": "Domain tidak diizinkan", - "ACCOUNT_NOT_ALLOWED": "Akun ini tidak diizinkan", - "CONTACTS_SYNC_ERROR": "Kesalahan sinkronisasi kontak", - "CANT_GET_MESSAGE_LIST": "Gagal memperoleh daftar pesan", - "CANT_GET_MESSAGE": "Gagal memperoleh pesan", - "CANT_DELETE_MESSAGE": "Gagal menghapus pesan", - "CANT_COPY_MESSAGE": "Can't copy message", - "CANT_MOVE_MESSAGE": "Gagal memindahkan pesan", - "CANT_SAVE_MESSAGE": "Gagal menyimpan pesan", - "CANT_SEND_MESSAGE": "Gagal mengirim pesan", - "INVALID_RECIPIENTS": "Penerima tidak valid", - "CANT_SAVE_FILTERS": "Gagal menyimpan filter", - "CANT_GET_FILTERS": "Gagal memperoleh filter", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Can't activate filters script", - "CANT_DELETE_FILTERS_SCRIPT": "Can't delete filters script", - "FILTERS_ARE_NOT_CORRECT": "Filter tidak benar", - "CANT_CREATE_FOLDER": "Gagal membuat folder", - "CANT_RENAME_FOLDER": "Gagal mengubah nama folder", - "CANT_DELETE_FOLDER": "Gagal menghapus folder", - "CANT_DELETE_NON_EMPTY_FOLDER": "Gagal menghapus direkori yang berisi", - "CANT_SUBSCRIBE_FOLDER": "Gagal mengkaitkan folder", - "CANT_UNSUBSCRIBE_FOLDER": "Tidak bisa memutus folder", - "DEMO_SEND_MESSAGE_ERROR": "Atas alasan keamanan, akun ini tidak diizinkan mengirim pesan ke alamat luar!", - "DEMO_ACCOUNT_ERROR": "Atas alasan keamanan, akun ini tidak diizinkan melakukan aksi ini!", - "ACCOUNT_ALREADY_EXISTS": "Akun sudah ada", - "ACCOUNT_DOES_NOT_EXIST": "Akun tidak ada", - "ACCOUNT_SWITCH_FAILED": "Switch to account \"%EMAIL%\" failed", - "MAIL_SERVER_ERROR": "Terjadi kesalahan saat mengakses server mail", - "INVALID_INPUT_ARGUMENT": "Uraian input tidak sah", - "UNKNOWN_ERROR": "Kesalahan tidak diketahui" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Token tidak sah", + "AuthError": "Otentikasi gagal", + "ConnectionError": "Tidak terhubung ke server", + "DomainAlreadyExists": "Domain telah ada", + "DomainNotAllowed": "Domain tidak diizinkan", + "AccountNotAllowed": "Akun ini tidak diizinkan", + "ContactsSyncError": "Kesalahan sinkronisasi kontak", + "CantGetMessageList": "Gagal memperoleh daftar pesan", + "CantGetMessage": "Gagal memperoleh pesan", + "CantDeleteMessage": "Gagal menghapus pesan", + "CantCopyMessage": "Can't copy message", + "CantMoveMessage": "Gagal memindahkan pesan", + "CantSaveMessage": "Gagal menyimpan pesan", + "CantSendMessage": "Gagal mengirim pesan", + "InvalidRecipients": "Penerima tidak valid", + "CantSaveFilters": "Gagal menyimpan filter", + "CantGetFilters": "Gagal memperoleh filter", + "CantActivateFiltersScript": "Can't activate filters script", + "CantDeleteFiltersScript": "Can't delete filters script", + "FiltersAreNotCorrect": "Filter tidak benar", + "CantCreateFolder": "Gagal membuat folder", + "CantRenameFolder": "Gagal mengubah nama folder", + "CantDeleteFolder": "Gagal menghapus folder", + "CantDeleteNonEmptyFolder": "Gagal menghapus direkori yang berisi", + "CantSubscribeFolder": "Gagal mengkaitkan folder", + "CantUnsubscribeFolder": "Tidak bisa memutus folder", + "DemoSendMessageError": "Atas alasan keamanan, akun ini tidak diizinkan mengirim pesan ke alamat luar!", + "DemoAccountError": "Atas alasan keamanan, akun ini tidak diizinkan melakukan aksi ini!", + "AccountAlreadyExists": "Akun sudah ada", + "AccountDoesNotExist": "Akun tidak ada", + "AccountSwitchFailed": "Switch to account \"%EMAIL%\" failed", + "MailServerError": "Terjadi kesalahan saat mengakses server mail", + "InvalidInputArgument": "Uraian input tidak sah", + "UnknownError": "Kesalahan tidak diketahui" } } diff --git a/snappymail/v/0.0.0/app/localization/is-IS/user.json b/snappymail/v/0.0.0/app/localization/is-IS/user.json index 51d0207a3..da32fa761 100644 --- a/snappymail/v/0.0.0/app/localization/is-IS/user.json +++ b/snappymail/v/0.0.0/app/localization/is-IS/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "Loka ritli" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Rangt tákn", - "AUTH_ERROR": "Auðkenning mistókst", - "CONNECTION_ERROR": "Get ekki tengst á netþjón", - "DOMAIN_ALREADY_EXISTS": "Lén er nú þegar til staðar", - "DOMAIN_NOT_ALLOWED": "Lén ekki leyft", - "ACCOUNT_NOT_ALLOWED": "Aðgangur er ekki leyfður", - "CONTACTS_SYNC_ERROR": "Villa í samstillingu tengiliða", - "CANT_GET_MESSAGE_LIST": "Get ekki sótt skilaboðlista", - "CANT_GET_MESSAGE": "Get ekki sótt skilaboð", - "CANT_DELETE_MESSAGE": "Get ekki eytt skilaboðum", - "CANT_COPY_MESSAGE": "Can't copy message", - "CANT_MOVE_MESSAGE": "Get ekki fært skilaboð", - "CANT_SAVE_MESSAGE": "Get ekki vistað skilaboð", - "CANT_SEND_MESSAGE": "Get ekki sent skilaboð", - "INVALID_RECIPIENTS": "Rangir viðtakendur", - "CANT_SAVE_FILTERS": "Get ekki vistað síur", - "CANT_GET_FILTERS": "Get ekki sótt síur", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Can't activate filters script", - "CANT_DELETE_FILTERS_SCRIPT": "Can't delete filters script", - "FILTERS_ARE_NOT_CORRECT": "Síur eru ekki réttar", - "CANT_CREATE_FOLDER": "Get ekki búið til möppu", - "CANT_RENAME_FOLDER": "Get ekki endurnefnt möppu", - "CANT_DELETE_FOLDER": "Get ekki eytt möppu", - "CANT_DELETE_NON_EMPTY_FOLDER": "Get ekki eytt möppu í notkun", - "CANT_SUBSCRIBE_FOLDER": "Get ekki gerst áskrifandi á möppu", - "CANT_UNSUBSCRIBE_FOLDER": "Get ekki hætt áskrift á möppu", - "DEMO_SEND_MESSAGE_ERROR": "Vegna öryggissjónarmiða, þá hefur þessi aðgangur ekki leyfi til að senda póst á utanaðkomandi netföng!", - "DEMO_ACCOUNT_ERROR": "Vegna öryggissjónarmiða, þá hefur þessi aðgangur ekki heimild fyrir þessa aðgerð!", - "ACCOUNT_ALREADY_EXISTS": "Aðgangur er nú þegar til staðar", - "ACCOUNT_DOES_NOT_EXIST": "Aðgangur er ekki til", - "ACCOUNT_SWITCH_FAILED": "Switch to account \"%EMAIL%\" failed", - "MAIL_SERVER_ERROR": "Villa kom upp við tilraun til að tengjast póstþjóni", - "INVALID_INPUT_ARGUMENT": "Óleyfilegt inntaksviðfang", - "UNKNOWN_ERROR": "Óþekkt villa" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Rangt tákn", + "AuthError": "Auðkenning mistókst", + "ConnectionError": "Get ekki tengst á netþjón", + "DomainAlreadyExists": "Lén er nú þegar til staðar", + "DomainNotAllowed": "Lén ekki leyft", + "AccountNotAllowed": "Aðgangur er ekki leyfður", + "ContactsSyncError": "Villa í samstillingu tengiliða", + "CantGetMessageList": "Get ekki sótt skilaboðlista", + "CantGetMessage": "Get ekki sótt skilaboð", + "CantDeleteMessage": "Get ekki eytt skilaboðum", + "CantCopyMessage": "Can't copy message", + "CantMoveMessage": "Get ekki fært skilaboð", + "CantSaveMessage": "Get ekki vistað skilaboð", + "CantSendMessage": "Get ekki sent skilaboð", + "InvalidRecipients": "Rangir viðtakendur", + "CantSaveFilters": "Get ekki vistað síur", + "CantGetFilters": "Get ekki sótt síur", + "CantActivateFiltersScript": "Can't activate filters script", + "CantDeleteFiltersScript": "Can't delete filters script", + "FiltersAreNotCorrect": "Síur eru ekki réttar", + "CantCreateFolder": "Get ekki búið til möppu", + "CantRenameFolder": "Get ekki endurnefnt möppu", + "CantDeleteFolder": "Get ekki eytt möppu", + "CantDeleteNonEmptyFolder": "Get ekki eytt möppu í notkun", + "CantSubscribeFolder": "Get ekki gerst áskrifandi á möppu", + "CantUnsubscribeFolder": "Get ekki hætt áskrift á möppu", + "DemoSendMessageError": "Vegna öryggissjónarmiða, þá hefur þessi aðgangur ekki leyfi til að senda póst á utanaðkomandi netföng!", + "DemoAccountError": "Vegna öryggissjónarmiða, þá hefur þessi aðgangur ekki heimild fyrir þessa aðgerð!", + "AccountAlreadyExists": "Aðgangur er nú þegar til staðar", + "AccountDoesNotExist": "Aðgangur er ekki til", + "AccountSwitchFailed": "Switch to account \"%EMAIL%\" failed", + "MailServerError": "Villa kom upp við tilraun til að tengjast póstþjóni", + "InvalidInputArgument": "Óleyfilegt inntaksviðfang", + "UnknownError": "Óþekkt villa" } } diff --git a/snappymail/v/0.0.0/app/localization/it-IT/admin.json b/snappymail/v/0.0.0/app/localization/it-IT/admin.json index 01c62b4cc..b03df0e94 100644 --- a/snappymail/v/0.0.0/app/localization/it-IT/admin.json +++ b/snappymail/v/0.0.0/app/localization/it-IT/admin.json @@ -168,17 +168,17 @@ "UNKNOWN_ERROR": "Errore sconosciuto" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Richiesta fallita", - "REQUEST_ABORTED": "Richiesta annullata", - "REQUEST_TIMEOUT": "Richiesta scaduta", - "INVALID_TOKEN": "Token non valido", - "AUTH_ERROR": "Autenticazione fallita", - "DOMAIN_ALREADY_EXISTS": "Il dominio esiste già", - "CANT_SAVE_PLUGIN_SETTINGS": "Impossibile salvare le impostazioni", - "CANT_INSTALL_PACKAGE": "Installazione estensione fallita", - "CANT_DELETE_PACKAGE": "Rimozione estensione fallita", - "INVALID_PLUGIN_PACKAGE": "Pacchetto estensione non valido", - "UNSUPPORTED_PLUGIN_PACKAGE": "Pacchetto estensione non supportato", - "UNKNOWN_ERROR": "Errore sconosciuto" + "RequestError": "Richiesta fallita", + "RequestAborted": "Richiesta annullata", + "RequestTimeout": "Richiesta scaduta", + "InvalidToken": "Token non valido", + "AuthError": "Autenticazione fallita", + "DomainAlreadyExists": "Il dominio esiste già", + "CantSavePluginSettings": "Impossibile salvare le impostazioni", + "CantInstallPackage": "Installazione estensione fallita", + "CantDeletePackage": "Rimozione estensione fallita", + "InvalidPluginPackage": "Pacchetto estensione non valido", + "UnsupportedPluginPackage": "Pacchetto estensione non supportato", + "UnknownError": "Errore sconosciuto" } } diff --git a/snappymail/v/0.0.0/app/localization/it-IT/user.json b/snappymail/v/0.0.0/app/localization/it-IT/user.json index d8fb8b1dd..65ef0a8ba 100644 --- a/snappymail/v/0.0.0/app/localization/it-IT/user.json +++ b/snappymail/v/0.0.0/app/localization/it-IT/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "Chiudi finestra di scrittura" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Richiesta fallita", - "REQUEST_ABORTED": "Richiesta annullata", - "REQUEST_TIMEOUT": "Richiesta scaduta", - "INVALID_TOKEN": "Token invalido", - "AUTH_ERROR": "Autenticazione fallita", - "CONNECTION_ERROR": "Impossibile connettersi al server", - "DOMAIN_ALREADY_EXISTS": "Il dominio esiste già", - "DOMAIN_NOT_ALLOWED": "Il dominio non è autorizzato", - "ACCOUNT_NOT_ALLOWED": "L'account non è autorizzato", - "CONTACTS_SYNC_ERROR": "Errore durante la sincronizzazione dei contatti", - "CANT_GET_MESSAGE_LIST": "Impossibile ottenere la lista dei messaggi", - "CANT_GET_MESSAGE": "Impossibile caricare il messaggio", - "CANT_DELETE_MESSAGE": "Impossibile eliminare il messaggio", - "CANT_COPY_MESSAGE": "Impossibile copiare il messaggio", - "CANT_MOVE_MESSAGE": "Impossibile spostare il messaggio", - "CANT_SAVE_MESSAGE": "Impossibile salvare il messaggio", - "CANT_SEND_MESSAGE": "Impossibile inviare il messaggio", - "INVALID_RECIPIENTS": "Destinatario non valido", - "CANT_SAVE_FILTERS": "Impossibile salvare i filtri", - "CANT_GET_FILTERS": "Impossibile caricare i filtri", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Impossibile attivare i filtri script", - "CANT_DELETE_FILTERS_SCRIPT": "Impossibile eliminare i filtri script", - "FILTERS_ARE_NOT_CORRECT": "I filtri non sono corretti", - "CANT_CREATE_FOLDER": "Impossibile creare la cartella", - "CANT_RENAME_FOLDER": "Impossibile rinominare la cartella", - "CANT_DELETE_FOLDER": "Impossibile eliminare la cartella", - "CANT_DELETE_NON_EMPTY_FOLDER": "Impossibile eliminare una cartella non vuota", - "CANT_SUBSCRIBE_FOLDER": "Impossibile sottoscrivere la cartella", - "CANT_UNSUBSCRIBE_FOLDER": "Impossibile rimuovere la sottoscrizione alla cartella", - "DEMO_SEND_MESSAGE_ERROR": "Per ragioni di sicurezza, questa demo non è abilitata ad inviare email ad inidirizzi esterni", - "DEMO_ACCOUNT_ERROR": "Per ragioni di sicurezza, questo account non è autorizzato ad effettuare questa operazione!", - "ACCOUNT_ALREADY_EXISTS": "L'account esiste già", - "ACCOUNT_DOES_NOT_EXIST": "L'account non esiste", - "ACCOUNT_SWITCH_FAILED": "Passaggio all'account \"%EMAIL%\" fallito", - "MAIL_SERVER_ERROR": "Si è verificato un errore nel server mail", - "INVALID_INPUT_ARGUMENT": "Argomento non valido", - "UNKNOWN_ERROR": "Errore sconosciuto" + "RequestError": "Richiesta fallita", + "RequestAborted": "Richiesta annullata", + "RequestTimeout": "Richiesta scaduta", + "InvalidToken": "Token invalido", + "AuthError": "Autenticazione fallita", + "ConnectionError": "Impossibile connettersi al server", + "DomainAlreadyExists": "Il dominio esiste già", + "DomainNotAllowed": "Il dominio non è autorizzato", + "AccountNotAllowed": "L'account non è autorizzato", + "ContactsSyncError": "Errore durante la sincronizzazione dei contatti", + "CantGetMessageList": "Impossibile ottenere la lista dei messaggi", + "CantGetMessage": "Impossibile caricare il messaggio", + "CantDeleteMessage": "Impossibile eliminare il messaggio", + "CantCopyMessage": "Impossibile copiare il messaggio", + "CantMoveMessage": "Impossibile spostare il messaggio", + "CantSaveMessage": "Impossibile salvare il messaggio", + "CantSendMessage": "Impossibile inviare il messaggio", + "InvalidRecipients": "Destinatario non valido", + "CantSaveFilters": "Impossibile salvare i filtri", + "CantGetFilters": "Impossibile caricare i filtri", + "CantActivateFiltersScript": "Impossibile attivare i filtri script", + "CantDeleteFiltersScript": "Impossibile eliminare i filtri script", + "FiltersAreNotCorrect": "I filtri non sono corretti", + "CantCreateFolder": "Impossibile creare la cartella", + "CantRenameFolder": "Impossibile rinominare la cartella", + "CantDeleteFolder": "Impossibile eliminare la cartella", + "CantDeleteNonEmptyFolder": "Impossibile eliminare una cartella non vuota", + "CantSubscribeFolder": "Impossibile sottoscrivere la cartella", + "CantUnsubscribeFolder": "Impossibile rimuovere la sottoscrizione alla cartella", + "DemoSendMessageError": "Per ragioni di sicurezza, questa demo non è abilitata ad inviare email ad inidirizzi esterni", + "DemoAccountError": "Per ragioni di sicurezza, questo account non è autorizzato ad effettuare questa operazione!", + "AccountAlreadyExists": "L'account esiste già", + "AccountDoesNotExist": "L'account non esiste", + "AccountSwitchFailed": "Passaggio all'account \"%EMAIL%\" fallito", + "MailServerError": "Si è verificato un errore nel server mail", + "InvalidInputArgument": "Argomento non valido", + "UnknownError": "Errore sconosciuto" } } diff --git a/snappymail/v/0.0.0/app/localization/ja-JP/admin.json b/snappymail/v/0.0.0/app/localization/ja-JP/admin.json index effd6fb8a..ea3bd7e30 100644 --- a/snappymail/v/0.0.0/app/localization/ja-JP/admin.json +++ b/snappymail/v/0.0.0/app/localization/ja-JP/admin.json @@ -168,17 +168,17 @@ "UNKNOWN_ERROR": "不明なエラー" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "要求は失敗しました", - "REQUEST_ABORTED": "要求は中断されました", - "REQUEST_TIMEOUT": "要求はタイムアウトしました", - "INVALID_TOKEN": "無効なトークン", - "AUTH_ERROR": "認証に失敗しました", - "DOMAIN_ALREADY_EXISTS": "ドメインが既に存在しています", - "CANT_SAVE_PLUGIN_SETTINGS": "設定が保存できません", - "CANT_INSTALL_PACKAGE": "パッケージのインストールに失敗しました", - "CANT_DELETE_PACKAGE": "パッケージの削除に失敗しました", - "INVALID_PLUGIN_PACKAGE": "無効なプラグインパッケージ", - "UNSUPPORTED_PLUGIN_PACKAGE": "サポートされていないプラグインパッケージ", - "UNKNOWN_ERROR": "不明なエラー" + "RequestError": "要求は失敗しました", + "RequestAborted": "要求は中断されました", + "RequestTimeout": "要求はタイムアウトしました", + "InvalidToken": "無効なトークン", + "AuthError": "認証に失敗しました", + "DomainAlreadyExists": "ドメインが既に存在しています", + "CantSavePluginSettings": "設定が保存できません", + "CantInstallPackage": "パッケージのインストールに失敗しました", + "CantDeletePackage": "パッケージの削除に失敗しました", + "InvalidPluginPackage": "無効なプラグインパッケージ", + "UnsupportedPluginPackage": "サポートされていないプラグインパッケージ", + "UnknownError": "不明なエラー" } } diff --git a/snappymail/v/0.0.0/app/localization/ja-JP/user.json b/snappymail/v/0.0.0/app/localization/ja-JP/user.json index 77b27be1e..4c5e117ae 100644 --- a/snappymail/v/0.0.0/app/localization/ja-JP/user.json +++ b/snappymail/v/0.0.0/app/localization/ja-JP/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "作成画面を閉じる" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "要求は失敗しました", - "REQUEST_ABORTED": "要求は中断されました", - "REQUEST_TIMEOUT": "要求はタイムアウトしました", - "INVALID_TOKEN": "無効なトークン", - "AUTH_ERROR": "認証に失敗しました", - "CONNECTION_ERROR": "サーバーへ接続できません", - "DOMAIN_ALREADY_EXISTS": "ドメインが既に存在しています", - "DOMAIN_NOT_ALLOWED": "ドメインは、許可されていません", - "ACCOUNT_NOT_ALLOWED": "アカウントは、許可されていません", - "CONTACTS_SYNC_ERROR": "連絡先 同期 エラー", - "CANT_GET_MESSAGE_LIST": "メッセージ一覧が取得できません", - "CANT_GET_MESSAGE": "メッセージを取得できません", - "CANT_DELETE_MESSAGE": "メッセージを削除できません", - "CANT_COPY_MESSAGE": "メッセージをコピーできません", - "CANT_MOVE_MESSAGE": "メッセージを移動できません", - "CANT_SAVE_MESSAGE": "メッセージを保存できません", - "CANT_SEND_MESSAGE": "メッセージ送信できません", - "INVALID_RECIPIENTS": "無効な受信者", - "CANT_SAVE_FILTERS": "フィルターを保存できません", - "CANT_GET_FILTERS": "フィルターを取得できません", - "CANT_ACTIVATE_FILTERS_SCRIPT": "フィルタースクリプトを有効にできません", - "CANT_DELETE_FILTERS_SCRIPT": "フィルタースクリプトを削除できません", - "FILTERS_ARE_NOT_CORRECT": "フィルターが正しくありません", - "CANT_CREATE_FOLDER": "フォルダを作成できません", - "CANT_RENAME_FOLDER": "フォルダの名前を変更できません", - "CANT_DELETE_FOLDER": "フォルダを削除できません", - "CANT_DELETE_NON_EMPTY_FOLDER": "空ではないディレクトリを削除できません", - "CANT_SUBSCRIBE_FOLDER": "フォルダを購読できません", - "CANT_UNSUBSCRIBE_FOLDER": "フォルダを購読解除できません", - "DEMO_SEND_MESSAGE_ERROR": "セキュリティ上の理由から、アカウントは、外部の電子メールアドレスにメッセージを送信することを許可されていません!", - "DEMO_ACCOUNT_ERROR": "セキュリティ上の理由から、アカウントには、このアクションが許可されていません!", - "ACCOUNT_ALREADY_EXISTS": "アカウントがすでに存在します", - "ACCOUNT_DOES_NOT_EXIST": "アカウントは存在しません", - "ACCOUNT_SWITCH_FAILED": "アカウントを\"%EMAIL%\"に切り換えるのに失敗しました", - "MAIL_SERVER_ERROR": "メールサーバーへのアクセス中にエラーが発生しました", - "INVALID_INPUT_ARGUMENT": "無効な入力引数", - "UNKNOWN_ERROR": "不明なエラー" + "RequestError": "要求は失敗しました", + "RequestAborted": "要求は中断されました", + "RequestTimeout": "要求はタイムアウトしました", + "InvalidToken": "無効なトークン", + "AuthError": "認証に失敗しました", + "ConnectionError": "サーバーへ接続できません", + "DomainAlreadyExists": "ドメインが既に存在しています", + "DomainNotAllowed": "ドメインは、許可されていません", + "AccountNotAllowed": "アカウントは、許可されていません", + "ContactsSyncError": "連絡先 同期 エラー", + "CantGetMessageList": "メッセージ一覧が取得できません", + "CantGetMessage": "メッセージを取得できません", + "CantDeleteMessage": "メッセージを削除できません", + "CantCopyMessage": "メッセージをコピーできません", + "CantMoveMessage": "メッセージを移動できません", + "CantSaveMessage": "メッセージを保存できません", + "CantSendMessage": "メッセージ送信できません", + "InvalidRecipients": "無効な受信者", + "CantSaveFilters": "フィルターを保存できません", + "CantGetFilters": "フィルターを取得できません", + "CantActivateFiltersScript": "フィルタースクリプトを有効にできません", + "CantDeleteFiltersScript": "フィルタースクリプトを削除できません", + "FiltersAreNotCorrect": "フィルターが正しくありません", + "CantCreateFolder": "フォルダを作成できません", + "CantRenameFolder": "フォルダの名前を変更できません", + "CantDeleteFolder": "フォルダを削除できません", + "CantDeleteNonEmptyFolder": "空ではないディレクトリを削除できません", + "CantSubscribeFolder": "フォルダを購読できません", + "CantUnsubscribeFolder": "フォルダを購読解除できません", + "DemoSendMessageError": "セキュリティ上の理由から、アカウントは、外部の電子メールアドレスにメッセージを送信することを許可されていません!", + "DemoAccountError": "セキュリティ上の理由から、アカウントには、このアクションが許可されていません!", + "AccountAlreadyExists": "アカウントがすでに存在します", + "AccountDoesNotExist": "アカウントは存在しません", + "AccountSwitchFailed": "アカウントを\"%EMAIL%\"に切り換えるのに失敗しました", + "MailServerError": "メールサーバーへのアクセス中にエラーが発生しました", + "InvalidInputArgument": "無効な入力引数", + "UnknownError": "不明なエラー" } } diff --git a/snappymail/v/0.0.0/app/localization/ko-KR/user.json b/snappymail/v/0.0.0/app/localization/ko-KR/user.json index 1c74e40a2..bb76428e4 100644 --- a/snappymail/v/0.0.0/app/localization/ko-KR/user.json +++ b/snappymail/v/0.0.0/app/localization/ko-KR/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "쓰기 창 닫기" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "잘못된 토큰입니다.", - "AUTH_ERROR": "인증에 실패했습니다", - "CONNECTION_ERROR": "서버에 연결할 수 없습니다.", - "DOMAIN_ALREADY_EXISTS": "이미 존재하는 도메인입니다.", - "DOMAIN_NOT_ALLOWED": "허용된 도메인이 아닙니다.", - "ACCOUNT_NOT_ALLOWED": "허용된 계정이 아닙니다.", - "CONTACTS_SYNC_ERROR": "연락처 동기화 오류", - "CANT_GET_MESSAGE_LIST": "메시지 목록을 불러 올 수 없습니다.", - "CANT_GET_MESSAGE": "메시지를 가져올 수 없습니다.", - "CANT_DELETE_MESSAGE": "메시지를 삭제할 수 없습니다.", - "CANT_COPY_MESSAGE": "Can't copy message", - "CANT_MOVE_MESSAGE": "메시지를 이동할 수 없습니다.", - "CANT_SAVE_MESSAGE": "메시지를 저장할 수 없습니다.", - "CANT_SEND_MESSAGE": "메시지를 보낼 수 없습니다.", - "INVALID_RECIPIENTS": "유효하지 않은 수신인", - "CANT_SAVE_FILTERS": "필터를 저장할 수 없습니다", - "CANT_GET_FILTERS": "필터를 가져올 수 없습니다", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Can't activate filters script", - "CANT_DELETE_FILTERS_SCRIPT": "Can't delete filters script", - "FILTERS_ARE_NOT_CORRECT": "필터가 올바르지 않습니다", - "CANT_CREATE_FOLDER": "폴더를 생성할 수 없습니다.", - "CANT_RENAME_FOLDER": "폴더명을 변경할 수 없습니다.", - "CANT_DELETE_FOLDER": "폴더를 삭제할 수 없습니다.", - "CANT_DELETE_NON_EMPTY_FOLDER": "비어있지 않은 디렉터리를 삭제할 수 없습니다.", - "CANT_SUBSCRIBE_FOLDER": "폴더를 볼 수 없습니다.", - "CANT_UNSUBSCRIBE_FOLDER": "폴더를 보이지 않게 할 수 없습니다.", - "DEMO_SEND_MESSAGE_ERROR": "이 테스트 계정은 외부 메일 발송이 금지되어있습니다.", - "DEMO_ACCOUNT_ERROR": "보안을 사유로 이 계정에서는 해당 동작이 허용되지 않습니다.", - "ACCOUNT_ALREADY_EXISTS": "이미 존재하는 계정입니다.", - "ACCOUNT_DOES_NOT_EXIST": "존재하지 않는 계정입니다", - "ACCOUNT_SWITCH_FAILED": "Switch to account \"%EMAIL%\" failed", - "MAIL_SERVER_ERROR": "메일 서버에 연결하는 도중 오류가 발생했습니다.", - "INVALID_INPUT_ARGUMENT": "유효하지 않은 input argument", - "UNKNOWN_ERROR": "알 수 없는 오류" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "잘못된 토큰입니다.", + "AuthError": "인증에 실패했습니다", + "ConnectionError": "서버에 연결할 수 없습니다.", + "DomainAlreadyExists": "이미 존재하는 도메인입니다.", + "DomainNotAllowed": "허용된 도메인이 아닙니다.", + "AccountNotAllowed": "허용된 계정이 아닙니다.", + "ContactsSyncError": "연락처 동기화 오류", + "CantGetMessageList": "메시지 목록을 불러 올 수 없습니다.", + "CantGetMessage": "메시지를 가져올 수 없습니다.", + "CantDeleteMessage": "메시지를 삭제할 수 없습니다.", + "CantCopyMessage": "Can't copy message", + "CantMoveMessage": "메시지를 이동할 수 없습니다.", + "CantSaveMessage": "메시지를 저장할 수 없습니다.", + "CantSendMessage": "메시지를 보낼 수 없습니다.", + "InvalidRecipients": "유효하지 않은 수신인", + "CantSaveFilters": "필터를 저장할 수 없습니다", + "CantGetFilters": "필터를 가져올 수 없습니다", + "CantActivateFiltersScript": "Can't activate filters script", + "CantDeleteFiltersScript": "Can't delete filters script", + "FiltersAreNotCorrect": "필터가 올바르지 않습니다", + "CantCreateFolder": "폴더를 생성할 수 없습니다.", + "CantRenameFolder": "폴더명을 변경할 수 없습니다.", + "CantDeleteFolder": "폴더를 삭제할 수 없습니다.", + "CantDeleteNonEmptyFolder": "비어있지 않은 디렉터리를 삭제할 수 없습니다.", + "CantSubscribeFolder": "폴더를 볼 수 없습니다.", + "CantUnsubscribeFolder": "폴더를 보이지 않게 할 수 없습니다.", + "DemoSendMessageError": "이 테스트 계정은 외부 메일 발송이 금지되어있습니다.", + "DemoAccountError": "보안을 사유로 이 계정에서는 해당 동작이 허용되지 않습니다.", + "AccountAlreadyExists": "이미 존재하는 계정입니다.", + "AccountDoesNotExist": "존재하지 않는 계정입니다", + "AccountSwitchFailed": "Switch to account \"%EMAIL%\" failed", + "MailServerError": "메일 서버에 연결하는 도중 오류가 발생했습니다.", + "InvalidInputArgument": "유효하지 않은 input argument", + "UnknownError": "알 수 없는 오류" } } diff --git a/snappymail/v/0.0.0/app/localization/lt-LT/admin.json b/snappymail/v/0.0.0/app/localization/lt-LT/admin.json index c4417e2c3..57a080c7e 100644 --- a/snappymail/v/0.0.0/app/localization/lt-LT/admin.json +++ b/snappymail/v/0.0.0/app/localization/lt-LT/admin.json @@ -168,17 +168,17 @@ "UNKNOWN_ERROR": "Nežinoma klaida" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Neteisingas raktas", - "AUTH_ERROR": "Autorizacija nepavyko", - "DOMAIN_ALREADY_EXISTS": "Toks domenas jau yra", - "CANT_SAVE_PLUGIN_SETTINGS": "Nepavyksta išsaugoti nustatymų", - "CANT_INSTALL_PACKAGE": "Nepavyksta įdiegti paketo", - "CANT_DELETE_PACKAGE": "Nepavyksta pašalinti paketo", - "INVALID_PLUGIN_PACKAGE": "Netinkamas įskiepio paketas", - "UNSUPPORTED_PLUGIN_PACKAGE": "Nepalaikomas įskiepio paketas", - "UNKNOWN_ERROR": "Nežinoma klaida" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Neteisingas raktas", + "AuthError": "Autorizacija nepavyko", + "DomainAlreadyExists": "Toks domenas jau yra", + "CantSavePluginSettings": "Nepavyksta išsaugoti nustatymų", + "CantInstallPackage": "Nepavyksta įdiegti paketo", + "CantDeletePackage": "Nepavyksta pašalinti paketo", + "InvalidPluginPackage": "Netinkamas įskiepio paketas", + "UnsupportedPluginPackage": "Nepalaikomas įskiepio paketas", + "UnknownError": "Nežinoma klaida" } } diff --git a/snappymail/v/0.0.0/app/localization/lt-LT/user.json b/snappymail/v/0.0.0/app/localization/lt-LT/user.json index 91f6a5883..707652092 100644 --- a/snappymail/v/0.0.0/app/localization/lt-LT/user.json +++ b/snappymail/v/0.0.0/app/localization/lt-LT/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "Uždaryti laišką" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Neteisingas raktas", - "AUTH_ERROR": "Autorizacija nepavyko", - "CONNECTION_ERROR": "Nepavyskta prisijungti prie serverio", - "DOMAIN_ALREADY_EXISTS": "Subdomenas jau egzistuoja", - "DOMAIN_NOT_ALLOWED": "Šis subdomenas neleidžiamas", - "ACCOUNT_NOT_ALLOWED": "Paskyra neleidžiama", - "CONTACTS_SYNC_ERROR": "Kontaktų sinchronizavimo klaida", - "CANT_GET_MESSAGE_LIST": "Nepavyksta gauti laiškų sąrašo", - "CANT_GET_MESSAGE": "Nepavyksta gauti laiško", - "CANT_DELETE_MESSAGE": "Nepavyko pašalinti laiško", - "CANT_COPY_MESSAGE": "Can't copy message", - "CANT_MOVE_MESSAGE": "Nepavyko perkelti laiško", - "CANT_SAVE_MESSAGE": "Nepavyko išsaugoti laiško", - "CANT_SEND_MESSAGE": "Nepavyko išsiųsti laiško", - "INVALID_RECIPIENTS": "Netinkamas gavėjas", - "CANT_SAVE_FILTERS": "Nepavyko išsaugoti filtrų", - "CANT_GET_FILTERS": "Nepavyko gauti filtrų", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Can't activate filters script", - "CANT_DELETE_FILTERS_SCRIPT": "Can't delete filters script", - "FILTERS_ARE_NOT_CORRECT": "Filtrai neteisingi", - "CANT_CREATE_FOLDER": "Nepavyksta sukurti katalogo", - "CANT_RENAME_FOLDER": "Nepavyksta pervadinti katalogo", - "CANT_DELETE_FOLDER": "Nepavyksta pašalinti katalogo", - "CANT_DELETE_NON_EMPTY_FOLDER": "Negalima pašalinti ne tuščio katalogo", - "CANT_SUBSCRIBE_FOLDER": "Nepavyskta užprenumeruoti katalogo", - "CANT_UNSUBSCRIBE_FOLDER": "Nepavyksta nutraukti katalogo prenumeratos", - "DEMO_SEND_MESSAGE_ERROR": "Saugumo sumetimais, ši demo paskyra neleidžia siųsti laiškų išoriniais e-pašto adresais!", - "DEMO_ACCOUNT_ERROR": "Saugumo sumetimais, su šia paskyra negalima atlikti norimo veiksmo!", - "ACCOUNT_ALREADY_EXISTS": "Paskyra jau egzistuoja", - "ACCOUNT_DOES_NOT_EXIST": "Nėra tokios paskyros", - "ACCOUNT_SWITCH_FAILED": "Switch to account \"%EMAIL%\" failed", - "MAIL_SERVER_ERROR": "Klaida bandant pasiekti pašto serverį", - "INVALID_INPUT_ARGUMENT": "Neteisingas įvesties argumentas", - "UNKNOWN_ERROR": "Nežinoma klaida" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Neteisingas raktas", + "AuthError": "Autorizacija nepavyko", + "ConnectionError": "Nepavyskta prisijungti prie serverio", + "DomainAlreadyExists": "Subdomenas jau egzistuoja", + "DomainNotAllowed": "Šis subdomenas neleidžiamas", + "AccountNotAllowed": "Paskyra neleidžiama", + "ContactsSyncError": "Kontaktų sinchronizavimo klaida", + "CantGetMessageList": "Nepavyksta gauti laiškų sąrašo", + "CantGetMessage": "Nepavyksta gauti laiško", + "CantDeleteMessage": "Nepavyko pašalinti laiško", + "CantCopyMessage": "Can't copy message", + "CantMoveMessage": "Nepavyko perkelti laiško", + "CantSaveMessage": "Nepavyko išsaugoti laiško", + "CantSendMessage": "Nepavyko išsiųsti laiško", + "InvalidRecipients": "Netinkamas gavėjas", + "CantSaveFilters": "Nepavyko išsaugoti filtrų", + "CantGetFilters": "Nepavyko gauti filtrų", + "CantActivateFiltersScript": "Can't activate filters script", + "CantDeleteFiltersScript": "Can't delete filters script", + "FiltersAreNotCorrect": "Filtrai neteisingi", + "CantCreateFolder": "Nepavyksta sukurti katalogo", + "CantRenameFolder": "Nepavyksta pervadinti katalogo", + "CantDeleteFolder": "Nepavyksta pašalinti katalogo", + "CantDeleteNonEmptyFolder": "Negalima pašalinti ne tuščio katalogo", + "CantSubscribeFolder": "Nepavyskta užprenumeruoti katalogo", + "CantUnsubscribeFolder": "Nepavyksta nutraukti katalogo prenumeratos", + "DemoSendMessageError": "Saugumo sumetimais, ši demo paskyra neleidžia siųsti laiškų išoriniais e-pašto adresais!", + "DemoAccountError": "Saugumo sumetimais, su šia paskyra negalima atlikti norimo veiksmo!", + "AccountAlreadyExists": "Paskyra jau egzistuoja", + "AccountDoesNotExist": "Nėra tokios paskyros", + "AccountSwitchFailed": "Switch to account \"%EMAIL%\" failed", + "MailServerError": "Klaida bandant pasiekti pašto serverį", + "InvalidInputArgument": "Neteisingas įvesties argumentas", + "UnknownError": "Nežinoma klaida" } } diff --git a/snappymail/v/0.0.0/app/localization/lv-LV/user.json b/snappymail/v/0.0.0/app/localization/lv-LV/user.json index 9b06be54d..447a10487 100644 --- a/snappymail/v/0.0.0/app/localization/lv-LV/user.json +++ b/snappymail/v/0.0.0/app/localization/lv-LV/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "Close compose" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Nepareizs tokens", - "AUTH_ERROR": "Autorizācija neizdevās", - "CONNECTION_ERROR": "Nevar savienoties ar serveri", - "DOMAIN_ALREADY_EXISTS": "Domeņes jau eksistē", - "DOMAIN_NOT_ALLOWED": "Šis domēns nav atļauts", - "ACCOUNT_NOT_ALLOWED": "Account is not allowed", - "CONTACTS_SYNC_ERROR": "Contacts synchronization error", - "CANT_GET_MESSAGE_LIST": "Nevar ielādēt ziņojumu sarakstu", - "CANT_GET_MESSAGE": "Nevar ielādēt ziņojumu", - "CANT_DELETE_MESSAGE": "Nevar izdzēst ziņojumu", - "CANT_COPY_MESSAGE": "Can't copy message", - "CANT_MOVE_MESSAGE": "Nevar pārvietot ziņojumu", - "CANT_SAVE_MESSAGE": "Nevar saglabāt ziņojumu", - "CANT_SEND_MESSAGE": "Nevar nosūtīt ziņojumu", - "INVALID_RECIPIENTS": "Nepareizi saņēmēji", - "CANT_SAVE_FILTERS": "Can't save filters", - "CANT_GET_FILTERS": "Can't get filters", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Can't activate filters script", - "CANT_DELETE_FILTERS_SCRIPT": "Can't delete filters script", - "FILTERS_ARE_NOT_CORRECT": "Filters are not correct", - "CANT_CREATE_FOLDER": "Nevar izveidot mapi", - "CANT_RENAME_FOLDER": "Nevar pārsaukt mapi", - "CANT_DELETE_FOLDER": "Nevar izdzēst mapi", - "CANT_DELETE_NON_EMPTY_FOLDER": "Nevar izdzēst pilnu mapi", - "CANT_SUBSCRIBE_FOLDER": "Nevar pierakstīties mapei", - "CANT_UNSUBSCRIBE_FOLDER": "Nevar atrakstīties mapei", - "DEMO_SEND_MESSAGE_ERROR": "Drošīnas iemeslu dēļ, demo konts nedrīks sūtīt e-pastu uz ārējiem e-pastiem!", - "DEMO_ACCOUNT_ERROR": "For security purposes, this account is not allowed for this action!", - "ACCOUNT_ALREADY_EXISTS": "Konts jau eksistē", - "ACCOUNT_DOES_NOT_EXIST": "Konts neeksistē", - "ACCOUNT_SWITCH_FAILED": "Switch to account \"%EMAIL%\" failed", - "MAIL_SERVER_ERROR": "Radās kļūda savienojoties ar serveri", - "INVALID_INPUT_ARGUMENT": "Invalid input argument", - "UNKNOWN_ERROR": "Nezināma kļūda" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Nepareizs tokens", + "AuthError": "Autorizācija neizdevās", + "ConnectionError": "Nevar savienoties ar serveri", + "DomainAlreadyExists": "Domeņes jau eksistē", + "DomainNotAllowed": "Šis domēns nav atļauts", + "AccountNotAllowed": "Account is not allowed", + "ContactsSyncError": "Contacts synchronization error", + "CantGetMessageList": "Nevar ielādēt ziņojumu sarakstu", + "CantGetMessage": "Nevar ielādēt ziņojumu", + "CantDeleteMessage": "Nevar izdzēst ziņojumu", + "CantCopyMessage": "Can't copy message", + "CantMoveMessage": "Nevar pārvietot ziņojumu", + "CantSaveMessage": "Nevar saglabāt ziņojumu", + "CantSendMessage": "Nevar nosūtīt ziņojumu", + "InvalidRecipients": "Nepareizi saņēmēji", + "CantSaveFilters": "Can't save filters", + "CantGetFilters": "Can't get filters", + "CantActivateFiltersScript": "Can't activate filters script", + "CantDeleteFiltersScript": "Can't delete filters script", + "FiltersAreNotCorrect": "Filters are not correct", + "CantCreateFolder": "Nevar izveidot mapi", + "CantRenameFolder": "Nevar pārsaukt mapi", + "CantDeleteFolder": "Nevar izdzēst mapi", + "CantDeleteNonEmptyFolder": "Nevar izdzēst pilnu mapi", + "CantSubscribeFolder": "Nevar pierakstīties mapei", + "CantUnsubscribeFolder": "Nevar atrakstīties mapei", + "DemoSendMessageError": "Drošīnas iemeslu dēļ, demo konts nedrīks sūtīt e-pastu uz ārējiem e-pastiem!", + "DemoAccountError": "For security purposes, this account is not allowed for this action!", + "AccountAlreadyExists": "Konts jau eksistē", + "AccountDoesNotExist": "Konts neeksistē", + "AccountSwitchFailed": "Switch to account \"%EMAIL%\" failed", + "MailServerError": "Radās kļūda savienojoties ar serveri", + "InvalidInputArgument": "Invalid input argument", + "UnknownError": "Nezināma kļūda" } } diff --git a/snappymail/v/0.0.0/app/localization/nb-NO/admin.json b/snappymail/v/0.0.0/app/localization/nb-NO/admin.json index 354730265..138a1c805 100644 --- a/snappymail/v/0.0.0/app/localization/nb-NO/admin.json +++ b/snappymail/v/0.0.0/app/localization/nb-NO/admin.json @@ -168,17 +168,17 @@ "UNKNOWN_ERROR": "Ukjent feil" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Forespørsel feilet", - "REQUEST_ABORTED": "Forespørselen er avbrutt", - "REQUEST_TIMEOUT": "Forespørselen ble tidsavbrutt", - "INVALID_TOKEN": "Ugyldig symbol", - "AUTH_ERROR": "Autentisering mislyktes", - "DOMAIN_ALREADY_EXISTS": "Domenet finnes allerede", - "CANT_SAVE_PLUGIN_SETTINGS": "Klarte ikke å lagre innstillinger", - "CANT_INSTALL_PACKAGE": "Klarte ikke å installere pakke", - "CANT_DELETE_PACKAGE": "Klarte ikke å fjerne pakke", - "INVALID_PLUGIN_PACKAGE": "Ugyldig tilleggspakke", - "UNSUPPORTED_PLUGIN_PACKAGE": "Tilleggspakke støttes ikke", - "UNKNOWN_ERROR": "Ukjent feil" + "RequestError": "Forespørsel feilet", + "RequestAborted": "Forespørselen er avbrutt", + "RequestTimeout": "Forespørselen ble tidsavbrutt", + "InvalidToken": "Ugyldig symbol", + "AuthError": "Autentisering mislyktes", + "DomainAlreadyExists": "Domenet finnes allerede", + "CantSavePluginSettings": "Klarte ikke å lagre innstillinger", + "CantInstallPackage": "Klarte ikke å installere pakke", + "CantDeletePackage": "Klarte ikke å fjerne pakke", + "InvalidPluginPackage": "Ugyldig tilleggspakke", + "UnsupportedPluginPackage": "Tilleggspakke støttes ikke", + "UnknownError": "Ukjent feil" } } diff --git a/snappymail/v/0.0.0/app/localization/nb-NO/user.json b/snappymail/v/0.0.0/app/localization/nb-NO/user.json index c3bfd3c08..d8f7eb369 100644 --- a/snappymail/v/0.0.0/app/localization/nb-NO/user.json +++ b/snappymail/v/0.0.0/app/localization/nb-NO/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "Lukk ny melding" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Ugyldig info", - "AUTH_ERROR": "Autentisering mislyktes", - "CONNECTION_ERROR": "Klarte ikke å koble til tjeneren", - "DOMAIN_ALREADY_EXISTS": "Domenet finnes allerede", - "DOMAIN_NOT_ALLOWED": "Dette domenet tillates ikke", - "ACCOUNT_NOT_ALLOWED": "Denne kontoen tillates ikke", - "CONTACTS_SYNC_ERROR": "Synkronisering av kontakter mislyktes", - "CANT_GET_MESSAGE_LIST": "Klarte ikke å hente liste over meldinger", - "CANT_GET_MESSAGE": "Klarte ikke å hente melding", - "CANT_DELETE_MESSAGE": "Klarte ikke å slette melding", - "CANT_COPY_MESSAGE": "Can't copy message", - "CANT_MOVE_MESSAGE": "Klarte ikke å flytte melding", - "CANT_SAVE_MESSAGE": "Klarte ikke å lagre melding", - "CANT_SEND_MESSAGE": "Klarte ikke å sende melding", - "INVALID_RECIPIENTS": "Ugyldige mottakere", - "CANT_SAVE_FILTERS": "Klarte ikke å lagre filtre", - "CANT_GET_FILTERS": "Klarte ikke å hente filtre", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Can't activate filters script", - "CANT_DELETE_FILTERS_SCRIPT": "Can't delete filters script", - "FILTERS_ARE_NOT_CORRECT": "Feilutformet filter", - "CANT_CREATE_FOLDER": "Klarte ikke å lage mappe", - "CANT_RENAME_FOLDER": "Klarte ikke å endre navn på mappe", - "CANT_DELETE_FOLDER": "Klarte ikke å slette mappe", - "CANT_DELETE_NON_EMPTY_FOLDER": "Du må slette mappeinnholdet før du kan slette mappa", - "CANT_SUBSCRIBE_FOLDER": "Klarte ikke å abonnere på mappe", - "CANT_UNSUBSCRIBE_FOLDER": "Klarte ikke å avslutte abonnement", - "DEMO_SEND_MESSAGE_ERROR": "Denne demo-kontoen er blokkert fra å sende meldinger til eksterne e-postadresser av sikkerhetshensyn.", - "DEMO_ACCOUNT_ERROR": "Av sikkerhetshensyn er denne kontoen blokkert fra å utføre denne handlinga.", - "ACCOUNT_ALREADY_EXISTS": "Kontoen finnes allerede", - "ACCOUNT_DOES_NOT_EXIST": "Kontoen finnes ikke", - "ACCOUNT_SWITCH_FAILED": "Switch to account \"%EMAIL%\" failed", - "MAIL_SERVER_ERROR": "Fikk ikke tilgang til e-posttjener", - "INVALID_INPUT_ARGUMENT": "Ugyldig inndata-argument", - "UNKNOWN_ERROR": "Ukjent feil" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Ugyldig info", + "AuthError": "Autentisering mislyktes", + "ConnectionError": "Klarte ikke å koble til tjeneren", + "DomainAlreadyExists": "Domenet finnes allerede", + "DomainNotAllowed": "Dette domenet tillates ikke", + "AccountNotAllowed": "Denne kontoen tillates ikke", + "ContactsSyncError": "Synkronisering av kontakter mislyktes", + "CantGetMessageList": "Klarte ikke å hente liste over meldinger", + "CantGetMessage": "Klarte ikke å hente melding", + "CantDeleteMessage": "Klarte ikke å slette melding", + "CantCopyMessage": "Can't copy message", + "CantMoveMessage": "Klarte ikke å flytte melding", + "CantSaveMessage": "Klarte ikke å lagre melding", + "CantSendMessage": "Klarte ikke å sende melding", + "InvalidRecipients": "Ugyldige mottakere", + "CantSaveFilters": "Klarte ikke å lagre filtre", + "CantGetFilters": "Klarte ikke å hente filtre", + "CantActivateFiltersScript": "Can't activate filters script", + "CantDeleteFiltersScript": "Can't delete filters script", + "FiltersAreNotCorrect": "Feilutformet filter", + "CantCreateFolder": "Klarte ikke å lage mappe", + "CantRenameFolder": "Klarte ikke å endre navn på mappe", + "CantDeleteFolder": "Klarte ikke å slette mappe", + "CantDeleteNonEmptyFolder": "Du må slette mappeinnholdet før du kan slette mappa", + "CantSubscribeFolder": "Klarte ikke å abonnere på mappe", + "CantUnsubscribeFolder": "Klarte ikke å avslutte abonnement", + "DemoSendMessageError": "Denne demo-kontoen er blokkert fra å sende meldinger til eksterne e-postadresser av sikkerhetshensyn.", + "DemoAccountError": "Av sikkerhetshensyn er denne kontoen blokkert fra å utføre denne handlinga.", + "AccountAlreadyExists": "Kontoen finnes allerede", + "AccountDoesNotExist": "Kontoen finnes ikke", + "AccountSwitchFailed": "Switch to account \"%EMAIL%\" failed", + "MailServerError": "Fikk ikke tilgang til e-posttjener", + "InvalidInputArgument": "Ugyldig inndata-argument", + "UnknownError": "Ukjent feil" } } diff --git a/snappymail/v/0.0.0/app/localization/nl-NL/admin.json b/snappymail/v/0.0.0/app/localization/nl-NL/admin.json index c58142a1c..33cd56350 100644 --- a/snappymail/v/0.0.0/app/localization/nl-NL/admin.json +++ b/snappymail/v/0.0.0/app/localization/nl-NL/admin.json @@ -168,17 +168,17 @@ "UNKNOWN_ERROR": "Onbekende fout" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Aanvraag mislukt", - "REQUEST_ABORTED": "Aanvraag is afgebroken", - "REQUEST_TIMEOUT": "Aanvraag verlopen", - "INVALID_TOKEN": "Onjuiste token", - "AUTH_ERROR": "Authenticatie mislukt", - "DOMAIN_ALREADY_EXISTS": "Domein bestaat al", - "CANT_SAVE_PLUGIN_SETTINGS": "Kan instellingen niet opslaan", - "CANT_INSTALL_PACKAGE": "Extensie installeren mislukt", - "CANT_DELETE_PACKAGE": "Extensie verwijderen mislukt", - "INVALID_PLUGIN_PACKAGE": "Onjuist extensie pakket", - "UNSUPPORTED_PLUGIN_PACKAGE": "Niet ondersteund extensie pakket", - "UNKNOWN_ERROR": "Onbekende fout" + "RequestError": "Aanvraag mislukt", + "RequestAborted": "Aanvraag is afgebroken", + "RequestTimeout": "Aanvraag verlopen", + "InvalidToken": "Onjuiste token", + "AuthError": "Authenticatie mislukt", + "DomainAlreadyExists": "Domein bestaat al", + "CantSavePluginSettings": "Kan instellingen niet opslaan", + "CantInstallPackage": "Extensie installeren mislukt", + "CantDeletePackage": "Extensie verwijderen mislukt", + "InvalidPluginPackage": "Onjuist extensie pakket", + "UnsupportedPluginPackage": "Niet ondersteund extensie pakket", + "UnknownError": "Onbekende fout" } } diff --git a/snappymail/v/0.0.0/app/localization/nl-NL/user.json b/snappymail/v/0.0.0/app/localization/nl-NL/user.json index c7b374905..98b572a32 100644 --- a/snappymail/v/0.0.0/app/localization/nl-NL/user.json +++ b/snappymail/v/0.0.0/app/localization/nl-NL/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "Nieuw bericht venster sluiten" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Verzoek mislukt", - "REQUEST_ABORTED": "Verzoek is afgebroken", - "REQUEST_TIMEOUT": "Verzoek time-out", - "INVALID_TOKEN": "Ongeldige token", - "AUTH_ERROR": "Authenticatie mislukt", - "CONNECTION_ERROR": "Kan geen verbinding maken met de Server", - "DOMAIN_ALREADY_EXISTS": "Domein bestaat reeds", - "DOMAIN_NOT_ALLOWED": "Domein is niet toegestaan", - "ACCOUNT_NOT_ALLOWED": "Account is niet toegestaan", - "CONTACTS_SYNC_ERROR": "Contactpersonen synchronisatie fout", - "CANT_GET_MESSAGE_LIST": "Berichtenlijst kan niet worden opgehaald", - "CANT_GET_MESSAGE": "Bericht kan niet worden opgehaald", - "CANT_DELETE_MESSAGE": "Kan bericht niet verwijderen", - "CANT_COPY_MESSAGE": "Kan bericht niet kopiëren", - "CANT_MOVE_MESSAGE": "Kan bericht niet verplaatsen", - "CANT_SAVE_MESSAGE": "Kan bericht niet opslaan", - "CANT_SEND_MESSAGE": "Kan bericht niet verzenden", - "INVALID_RECIPIENTS": "Onjuiste ontvangers", - "CANT_SAVE_FILTERS": "Kan filters niet opslaan", - "CANT_GET_FILTERS": "Kan filters niet ophalen", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Kan filters script niet activeren", - "CANT_DELETE_FILTERS_SCRIPT": "Kan filters script niet verwijderen", - "FILTERS_ARE_NOT_CORRECT": "Filters zijn onjuist", - "CANT_CREATE_FOLDER": "Kan map niet aanmaken", - "CANT_RENAME_FOLDER": "Kan map niet hernoemen", - "CANT_DELETE_FOLDER": "Kan map niet verwijderen", - "CANT_DELETE_NON_EMPTY_FOLDER": "Een niet lege map kan niet verwijderd worden", - "CANT_SUBSCRIBE_FOLDER": "Kan niet abonneren op folder", - "CANT_UNSUBSCRIBE_FOLDER": "Kan abonnement op folder niet opzeggen", - "DEMO_SEND_MESSAGE_ERROR": "Vanwege beveiliging is het niet toegestaan dat deze demo account e-mail naar extern verzend!", - "DEMO_ACCOUNT_ERROR": "Vanwege beveiliging is deze actie niet toegestaan voor deze account!", - "ACCOUNT_ALREADY_EXISTS": "Account bestaat al", - "ACCOUNT_DOES_NOT_EXIST": "Account bestaat niet.", - "ACCOUNT_SWITCH_FAILED": "Overschakelen naar account \"%EMAIL%\" mislukt", - "MAIL_SERVER_ERROR": "Fout bij toegang tot de mail Server", - "INVALID_INPUT_ARGUMENT": "Ongeldig invoer argument", - "UNKNOWN_ERROR": "Er is een onbekende fout opgetreden" + "RequestError": "Verzoek mislukt", + "RequestAborted": "Verzoek is afgebroken", + "RequestTimeout": "Verzoek time-out", + "InvalidToken": "Ongeldige token", + "AuthError": "Authenticatie mislukt", + "ConnectionError": "Kan geen verbinding maken met de Server", + "DomainAlreadyExists": "Domein bestaat reeds", + "DomainNotAllowed": "Domein is niet toegestaan", + "AccountNotAllowed": "Account is niet toegestaan", + "ContactsSyncError": "Contactpersonen synchronisatie fout", + "CantGetMessageList": "Berichtenlijst kan niet worden opgehaald", + "CantGetMessage": "Bericht kan niet worden opgehaald", + "CantDeleteMessage": "Kan bericht niet verwijderen", + "CantCopyMessage": "Kan bericht niet kopiëren", + "CantMoveMessage": "Kan bericht niet verplaatsen", + "CantSaveMessage": "Kan bericht niet opslaan", + "CantSendMessage": "Kan bericht niet verzenden", + "InvalidRecipients": "Onjuiste ontvangers", + "CantSaveFilters": "Kan filters niet opslaan", + "CantGetFilters": "Kan filters niet ophalen", + "CantActivateFiltersScript": "Kan filters script niet activeren", + "CantDeleteFiltersScript": "Kan filters script niet verwijderen", + "FiltersAreNotCorrect": "Filters zijn onjuist", + "CantCreateFolder": "Kan map niet aanmaken", + "CantRenameFolder": "Kan map niet hernoemen", + "CantDeleteFolder": "Kan map niet verwijderen", + "CantDeleteNonEmptyFolder": "Een niet lege map kan niet verwijderd worden", + "CantSubscribeFolder": "Kan niet abonneren op folder", + "CantUnsubscribeFolder": "Kan abonnement op folder niet opzeggen", + "DemoSendMessageError": "Vanwege beveiliging is het niet toegestaan dat deze demo account e-mail naar extern verzend!", + "DemoAccountError": "Vanwege beveiliging is deze actie niet toegestaan voor deze account!", + "AccountAlreadyExists": "Account bestaat al", + "AccountDoesNotExist": "Account bestaat niet.", + "AccountSwitchFailed": "Overschakelen naar account \"%EMAIL%\" mislukt", + "MailServerError": "Fout bij toegang tot de mail Server", + "InvalidInputArgument": "Ongeldig invoer argument", + "UnknownError": "Er is een onbekende fout opgetreden" } } diff --git a/snappymail/v/0.0.0/app/localization/pl-PL/admin.json b/snappymail/v/0.0.0/app/localization/pl-PL/admin.json index 4b65c8437..9b07359a1 100644 --- a/snappymail/v/0.0.0/app/localization/pl-PL/admin.json +++ b/snappymail/v/0.0.0/app/localization/pl-PL/admin.json @@ -168,17 +168,17 @@ "UNKNOWN_ERROR": "Nieznany błąd" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Zapytanie zakończone niepowodzeniem", - "REQUEST_ABORTED": "Zapytanie przerwane", - "REQUEST_TIMEOUT": "Upłynął limit czasu", - "INVALID_TOKEN": "Nieprawidłowy token", - "AUTH_ERROR": "Uwierzytelnienie zakończone niepowodzeniem", - "DOMAIN_ALREADY_EXISTS": "Ta domena już istnieje", - "CANT_SAVE_PLUGIN_SETTINGS": "Nie można zapisać ustawień wtyczki", - "CANT_INSTALL_PACKAGE": "Instalacja wtyczki zakończona niepowodzeniem", - "CANT_DELETE_PACKAGE": "Usunięcie wtyczki zakończone niepowodzeniem", - "INVALID_PLUGIN_PACKAGE": "Nieprawidłowa wtyczka", - "UNSUPPORTED_PLUGIN_PACKAGE": "Nieobsługiwana wtyczka", - "UNKNOWN_ERROR": "Nieznany błąd" + "RequestError": "Zapytanie zakończone niepowodzeniem", + "RequestAborted": "Zapytanie przerwane", + "RequestTimeout": "Upłynął limit czasu", + "InvalidToken": "Nieprawidłowy token", + "AuthError": "Uwierzytelnienie zakończone niepowodzeniem", + "DomainAlreadyExists": "Ta domena już istnieje", + "CantSavePluginSettings": "Nie można zapisać ustawień wtyczki", + "CantInstallPackage": "Instalacja wtyczki zakończona niepowodzeniem", + "CantDeletePackage": "Usunięcie wtyczki zakończone niepowodzeniem", + "InvalidPluginPackage": "Nieprawidłowa wtyczka", + "UnsupportedPluginPackage": "Nieobsługiwana wtyczka", + "UnknownError": "Nieznany błąd" } } diff --git a/snappymail/v/0.0.0/app/localization/pl-PL/user.json b/snappymail/v/0.0.0/app/localization/pl-PL/user.json index 9563f77b6..18394f856 100644 --- a/snappymail/v/0.0.0/app/localization/pl-PL/user.json +++ b/snappymail/v/0.0.0/app/localization/pl-PL/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "Zamknij okno tworzenia wiadomości" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Zapytanie zakończone niepowodzeniem", - "REQUEST_ABORTED": "Zapytanie przerwane", - "REQUEST_TIMEOUT": "Upłynął limit czasu", - "INVALID_TOKEN": "Nieprawidłowy token", - "AUTH_ERROR": "Uwierzytelnienie zakończone niepowodzeniem", - "CONNECTION_ERROR": "Nie można połączyć z serwerem", - "DOMAIN_ALREADY_EXISTS": "Domena już istnieje", - "DOMAIN_NOT_ALLOWED": "Domena jest niedozwolona", - "ACCOUNT_NOT_ALLOWED": "Konto nie jest dozwolone", - "CONTACTS_SYNC_ERROR": "Błąd synchronizacji kontaktów", - "CANT_GET_MESSAGE_LIST": "Nie można pobrać listy wiadomości", - "CANT_GET_MESSAGE": "Nie można pobrać wiadomości", - "CANT_DELETE_MESSAGE": "Nie można usunąć wiadomości", - "CANT_COPY_MESSAGE": "Nie można skopiować wiadomości", - "CANT_MOVE_MESSAGE": "Nie można przenieść wiadomości", - "CANT_SAVE_MESSAGE": "Nie można zapisać wiadomości", - "CANT_SEND_MESSAGE": "Nie można wysłać wiadomości", - "INVALID_RECIPIENTS": "Nieprawidłowy adres odbiorcy", - "CANT_SAVE_FILTERS": "Nie można zapisać filtrów", - "CANT_GET_FILTERS": "Nie można pobrać filtrów", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Nie można aktywować skryptu filtrów", - "CANT_DELETE_FILTERS_SCRIPT": "Nie można usunąć skryptu filtrów", - "FILTERS_ARE_NOT_CORRECT": "Filtry są nieprawidłowe", - "CANT_CREATE_FOLDER": "Nie można utworzyć folderu", - "CANT_RENAME_FOLDER": "Nie można zmienić nazwy folderu", - "CANT_DELETE_FOLDER": "Nie można usunąć folderu", - "CANT_DELETE_NON_EMPTY_FOLDER": "Nie można usunąć folderu, w którym znajdują się wiadomości", - "CANT_SUBSCRIBE_FOLDER": "Nie można zasubskrybować folderu", - "CANT_UNSUBSCRIBE_FOLDER": "Nie można usunąć subskrypcji folderu", - "DEMO_SEND_MESSAGE_ERROR": "Ze względów bezpieczeństwa konto testowe nie ma możliwości przesyłania wiadomości na zewnętrzne adresy e-mail.", - "DEMO_ACCOUNT_ERROR": "Ze względów bezpieczeństwa ta akcja jest niedozwolona na tym koncie!", - "ACCOUNT_ALREADY_EXISTS": "Konto o takiej nazwie już istnieje", - "ACCOUNT_DOES_NOT_EXIST": "Konto nie istnieje", - "ACCOUNT_SWITCH_FAILED": "Przełączenie na konto \"%EMAIL%\" nie powiodło się", - "MAIL_SERVER_ERROR": "Wystąpił błąd w trakcie połączenia z serwerem poczty", - "INVALID_INPUT_ARGUMENT": "Nieprawidłowy argument", - "UNKNOWN_ERROR": "Nieznany błąd" + "RequestError": "Zapytanie zakończone niepowodzeniem", + "RequestAborted": "Zapytanie przerwane", + "RequestTimeout": "Upłynął limit czasu", + "InvalidToken": "Nieprawidłowy token", + "AuthError": "Uwierzytelnienie zakończone niepowodzeniem", + "ConnectionError": "Nie można połączyć z serwerem", + "DomainAlreadyExists": "Domena już istnieje", + "DomainNotAllowed": "Domena jest niedozwolona", + "AccountNotAllowed": "Konto nie jest dozwolone", + "ContactsSyncError": "Błąd synchronizacji kontaktów", + "CantGetMessageList": "Nie można pobrać listy wiadomości", + "CantGetMessage": "Nie można pobrać wiadomości", + "CantDeleteMessage": "Nie można usunąć wiadomości", + "CantCopyMessage": "Nie można skopiować wiadomości", + "CantMoveMessage": "Nie można przenieść wiadomości", + "CantSaveMessage": "Nie można zapisać wiadomości", + "CantSendMessage": "Nie można wysłać wiadomości", + "InvalidRecipients": "Nieprawidłowy adres odbiorcy", + "CantSaveFilters": "Nie można zapisać filtrów", + "CantGetFilters": "Nie można pobrać filtrów", + "CantActivateFiltersScript": "Nie można aktywować skryptu filtrów", + "CantDeleteFiltersScript": "Nie można usunąć skryptu filtrów", + "FiltersAreNotCorrect": "Filtry są nieprawidłowe", + "CantCreateFolder": "Nie można utworzyć folderu", + "CantRenameFolder": "Nie można zmienić nazwy folderu", + "CantDeleteFolder": "Nie można usunąć folderu", + "CantDeleteNonEmptyFolder": "Nie można usunąć folderu, w którym znajdują się wiadomości", + "CantSubscribeFolder": "Nie można zasubskrybować folderu", + "CantUnsubscribeFolder": "Nie można usunąć subskrypcji folderu", + "DemoSendMessageError": "Ze względów bezpieczeństwa konto testowe nie ma możliwości przesyłania wiadomości na zewnętrzne adresy e-mail.", + "DemoAccountError": "Ze względów bezpieczeństwa ta akcja jest niedozwolona na tym koncie!", + "AccountAlreadyExists": "Konto o takiej nazwie już istnieje", + "AccountDoesNotExist": "Konto nie istnieje", + "AccountSwitchFailed": "Przełączenie na konto \"%EMAIL%\" nie powiodło się", + "MailServerError": "Wystąpił błąd w trakcie połączenia z serwerem poczty", + "InvalidInputArgument": "Nieprawidłowy argument", + "UnknownError": "Nieznany błąd" } } diff --git a/snappymail/v/0.0.0/app/localization/pt-BR/admin.json b/snappymail/v/0.0.0/app/localization/pt-BR/admin.json index 56bcfd7eb..0c7e98d3d 100644 --- a/snappymail/v/0.0.0/app/localization/pt-BR/admin.json +++ b/snappymail/v/0.0.0/app/localization/pt-BR/admin.json @@ -168,17 +168,17 @@ "UNKNOWN_ERROR": "Erro desconhecido" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Senha inválida", - "AUTH_ERROR": "Falha na autenticação", - "DOMAIN_ALREADY_EXISTS": "O domínio já existe", - "CANT_SAVE_PLUGIN_SETTINGS": "Não foi possível salvar as configurações", - "CANT_INSTALL_PACKAGE": "Erro ao instalar pacote de plugin", - "CANT_DELETE_PACKAGE": "Erro ao remover pacote de plugin", - "INVALID_PLUGIN_PACKAGE": "Pacote de plugins inválido", - "UNSUPPORTED_PLUGIN_PACKAGE": "Pacote de plugins insuportados", - "UNKNOWN_ERROR": "Erro desconhecido" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Senha inválida", + "AuthError": "Falha na autenticação", + "DomainAlreadyExists": "O domínio já existe", + "CantSavePluginSettings": "Não foi possível salvar as configurações", + "CantInstallPackage": "Erro ao instalar pacote de plugin", + "CantDeletePackage": "Erro ao remover pacote de plugin", + "InvalidPluginPackage": "Pacote de plugins inválido", + "UnsupportedPluginPackage": "Pacote de plugins insuportados", + "UnknownError": "Erro desconhecido" } } diff --git a/snappymail/v/0.0.0/app/localization/pt-BR/user.json b/snappymail/v/0.0.0/app/localization/pt-BR/user.json index 917bb3189..64f5a8377 100644 --- a/snappymail/v/0.0.0/app/localization/pt-BR/user.json +++ b/snappymail/v/0.0.0/app/localization/pt-BR/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "Fechar composição" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Senha inválida", - "AUTH_ERROR": "Falha na autenticação", - "CONNECTION_ERROR": "Não foi possível conectar-se ao servidor", - "DOMAIN_ALREADY_EXISTS": "O domínio já existe", - "DOMAIN_NOT_ALLOWED": "Este domínio não é permitido", - "ACCOUNT_NOT_ALLOWED": "Conta não permitida", - "CONTACTS_SYNC_ERROR": "Erro na sincronização dos contatos", - "CANT_GET_MESSAGE_LIST": "Não foi possível obter a lista de mensagens", - "CANT_GET_MESSAGE": "Não foi possível obter a mensagem", - "CANT_DELETE_MESSAGE": "Não foi possível excluir a mensagem", - "CANT_COPY_MESSAGE": "Can't copy message", - "CANT_MOVE_MESSAGE": "Não foi possível mover a mensagem", - "CANT_SAVE_MESSAGE": "Não foi possível salvar a mensagem", - "CANT_SEND_MESSAGE": "Não foi possível enviar a mensagem", - "INVALID_RECIPIENTS": "Destinatário inválido", - "CANT_SAVE_FILTERS": "Não é possível salvar os filtros", - "CANT_GET_FILTERS": "Não é possível obter os filtros", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Can't activate filters script", - "CANT_DELETE_FILTERS_SCRIPT": "Can't delete filters script", - "FILTERS_ARE_NOT_CORRECT": "Os filtros não estão corretos", - "CANT_CREATE_FOLDER": "Não foi possível criar a pasta", - "CANT_RENAME_FOLDER": "Não foi possível renomear a pasta", - "CANT_DELETE_FOLDER": "Não foi possível exluir a pasta", - "CANT_DELETE_NON_EMPTY_FOLDER": "Não é possível excluir diretório não vazio", - "CANT_SUBSCRIBE_FOLDER": "Não foi possível inscrever esta pasta", - "CANT_UNSUBSCRIBE_FOLDER": "Não foi possível desinscrever esta pasta", - "DEMO_SEND_MESSAGE_ERROR": "Por motivos de segurança, esta conta demo não tem permissão para enviar mensagens para endereços de e-mail externo!", - "DEMO_ACCOUNT_ERROR": "For security purposes, this account is not allowed for this action!", - "ACCOUNT_ALREADY_EXISTS": "Esta conta já existe", - "ACCOUNT_DOES_NOT_EXIST": "Conta não existente", - "ACCOUNT_SWITCH_FAILED": "Switch to account \"%EMAIL%\" failed", - "MAIL_SERVER_ERROR": "Ocorreu um erro ao acessar o servidor de e-mail", - "INVALID_INPUT_ARGUMENT": "Argumento de entrada inválido", - "UNKNOWN_ERROR": "Erro desconhecido" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Senha inválida", + "AuthError": "Falha na autenticação", + "ConnectionError": "Não foi possível conectar-se ao servidor", + "DomainAlreadyExists": "O domínio já existe", + "DomainNotAllowed": "Este domínio não é permitido", + "AccountNotAllowed": "Conta não permitida", + "ContactsSyncError": "Erro na sincronização dos contatos", + "CantGetMessageList": "Não foi possível obter a lista de mensagens", + "CantGetMessage": "Não foi possível obter a mensagem", + "CantDeleteMessage": "Não foi possível excluir a mensagem", + "CantCopyMessage": "Can't copy message", + "CantMoveMessage": "Não foi possível mover a mensagem", + "CantSaveMessage": "Não foi possível salvar a mensagem", + "CantSendMessage": "Não foi possível enviar a mensagem", + "InvalidRecipients": "Destinatário inválido", + "CantSaveFilters": "Não é possível salvar os filtros", + "CantGetFilters": "Não é possível obter os filtros", + "CantActivateFiltersScript": "Can't activate filters script", + "CantDeleteFiltersScript": "Can't delete filters script", + "FiltersAreNotCorrect": "Os filtros não estão corretos", + "CantCreateFolder": "Não foi possível criar a pasta", + "CantRenameFolder": "Não foi possível renomear a pasta", + "CantDeleteFolder": "Não foi possível exluir a pasta", + "CantDeleteNonEmptyFolder": "Não é possível excluir diretório não vazio", + "CantSubscribeFolder": "Não foi possível inscrever esta pasta", + "CantUnsubscribeFolder": "Não foi possível desinscrever esta pasta", + "DemoSendMessageError": "Por motivos de segurança, esta conta demo não tem permissão para enviar mensagens para endereços de e-mail externo!", + "DemoAccountError": "For security purposes, this account is not allowed for this action!", + "AccountAlreadyExists": "Esta conta já existe", + "AccountDoesNotExist": "Conta não existente", + "AccountSwitchFailed": "Switch to account \"%EMAIL%\" failed", + "MailServerError": "Ocorreu um erro ao acessar o servidor de e-mail", + "InvalidInputArgument": "Argumento de entrada inválido", + "UnknownError": "Erro desconhecido" } } diff --git a/snappymail/v/0.0.0/app/localization/pt-PT/admin.json b/snappymail/v/0.0.0/app/localization/pt-PT/admin.json index 12adf1893..c7849e0bd 100644 --- a/snappymail/v/0.0.0/app/localization/pt-PT/admin.json +++ b/snappymail/v/0.0.0/app/localization/pt-PT/admin.json @@ -168,17 +168,17 @@ "UNKNOWN_ERROR": "Erro desconhecido" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "A solicitação falhou", - "REQUEST_ABORTED": "A solicitação foi abortada", - "REQUEST_TIMEOUT": "A solicitação expirou", - "INVALID_TOKEN": "Token inválido", - "AUTH_ERROR": "A autenticação falhou", - "DOMAIN_ALREADY_EXISTS": "O domínio já existe", - "CANT_SAVE_PLUGIN_SETTINGS": "Não é possível guardar as definições", - "CANT_INSTALL_PACKAGE": "Não foi possível instalar a extensão", - "CANT_DELETE_PACKAGE": "Não foi possível remover a extensão", - "INVALID_PLUGIN_PACKAGE": "Pacote de extensão inválido", - "UNSUPPORTED_PLUGIN_PACKAGE": "Pacote de extensão não suportado", - "UNKNOWN_ERROR": "Erro desconhecido" + "RequestError": "A solicitação falhou", + "RequestAborted": "A solicitação foi abortada", + "RequestTimeout": "A solicitação expirou", + "InvalidToken": "Token inválido", + "AuthError": "A autenticação falhou", + "DomainAlreadyExists": "O domínio já existe", + "CantSavePluginSettings": "Não é possível guardar as definições", + "CantInstallPackage": "Não foi possível instalar a extensão", + "CantDeletePackage": "Não foi possível remover a extensão", + "InvalidPluginPackage": "Pacote de extensão inválido", + "UnsupportedPluginPackage": "Pacote de extensão não suportado", + "UnknownError": "Erro desconhecido" } } diff --git a/snappymail/v/0.0.0/app/localization/pt-PT/user.json b/snappymail/v/0.0.0/app/localization/pt-PT/user.json index 603d28cab..9da68b559 100644 --- a/snappymail/v/0.0.0/app/localization/pt-PT/user.json +++ b/snappymail/v/0.0.0/app/localization/pt-PT/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "Fechar janela de composição" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "A solicitação falhou", - "REQUEST_ABORTED": "A solicitação foi abortada", - "REQUEST_TIMEOUT": "A solicitação expirou", - "INVALID_TOKEN": "Token inválido", - "AUTH_ERROR": "A autenticação falhou", - "CONNECTION_ERROR": "Não foi possível ligar ao servidor", - "DOMAIN_ALREADY_EXISTS": "O domínio já existe", - "DOMAIN_NOT_ALLOWED": "Este domínio não é permitido", - "ACCOUNT_NOT_ALLOWED": "Esta conta não é permitida", - "CONTACTS_SYNC_ERROR": "Erro na sincronização de contactos", - "CANT_GET_MESSAGE_LIST": "Não é possível obter a lista de mensagens", - "CANT_GET_MESSAGE": "Não é possível obter a mensagem", - "CANT_DELETE_MESSAGE": "Não é possível eliminar a mensagem", - "CANT_COPY_MESSAGE": "Não é possível copiar a mensagem", - "CANT_MOVE_MESSAGE": "Não é possível mover a mensagem", - "CANT_SAVE_MESSAGE": "Não é possível guardar a mensagem", - "CANT_SEND_MESSAGE": "Não é possível enviar a mensagem", - "INVALID_RECIPIENTS": "Destinatários inválidos", - "CANT_SAVE_FILTERS": "Não é possível guardar os filtros", - "CANT_GET_FILTERS": "Não é possível obter os filtros", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Não é possível ativar o script de filtração", - "CANT_DELETE_FILTERS_SCRIPT": "Não é possível apagar o script de filtração", - "FILTERS_ARE_NOT_CORRECT": "Os filtros não estão corretos", - "CANT_CREATE_FOLDER": "Não é possível criar a pasta", - "CANT_RENAME_FOLDER": "Não é possível renomear a pasta", - "CANT_DELETE_FOLDER": "Não é possível eliminar a pasta", - "CANT_DELETE_NON_EMPTY_FOLDER": "Não é possível eliminar pastas com conteúdos", - "CANT_SUBSCRIBE_FOLDER": "Não é possível subscrever a esta pasta", - "CANT_UNSUBSCRIBE_FOLDER": "Não é possível anular a subsrição desta pasta", - "DEMO_SEND_MESSAGE_ERROR": "Por motivos de segurança, esta conta de demonstração não tem permissão para enviar mensagens para endereços de e-mail externos!", - "DEMO_ACCOUNT_ERROR": "Por motivos de segurança, esta conta não tem permissão de executar esta ação!", - "ACCOUNT_ALREADY_EXISTS": "Esta conta já existe", - "ACCOUNT_DOES_NOT_EXIST": "Esta conta não existe", - "ACCOUNT_SWITCH_FAILED": "A mudança para a conta \"%EMAIL%\" falhou", - "MAIL_SERVER_ERROR": "Ocorreu um erro ao aceder ao servidor de correio", - "INVALID_INPUT_ARGUMENT": "Parâmetro de entrada inválido", - "UNKNOWN_ERROR": "Erro desconhecido" + "RequestError": "A solicitação falhou", + "RequestAborted": "A solicitação foi abortada", + "RequestTimeout": "A solicitação expirou", + "InvalidToken": "Token inválido", + "AuthError": "A autenticação falhou", + "ConnectionError": "Não foi possível ligar ao servidor", + "DomainAlreadyExists": "O domínio já existe", + "DomainNotAllowed": "Este domínio não é permitido", + "AccountNotAllowed": "Esta conta não é permitida", + "ContactsSyncError": "Erro na sincronização de contactos", + "CantGetMessageList": "Não é possível obter a lista de mensagens", + "CantGetMessage": "Não é possível obter a mensagem", + "CantDeleteMessage": "Não é possível eliminar a mensagem", + "CantCopyMessage": "Não é possível copiar a mensagem", + "CantMoveMessage": "Não é possível mover a mensagem", + "CantSaveMessage": "Não é possível guardar a mensagem", + "CantSendMessage": "Não é possível enviar a mensagem", + "InvalidRecipients": "Destinatários inválidos", + "CantSaveFilters": "Não é possível guardar os filtros", + "CantGetFilters": "Não é possível obter os filtros", + "CantActivateFiltersScript": "Não é possível ativar o script de filtração", + "CantDeleteFiltersScript": "Não é possível apagar o script de filtração", + "FiltersAreNotCorrect": "Os filtros não estão corretos", + "CantCreateFolder": "Não é possível criar a pasta", + "CantRenameFolder": "Não é possível renomear a pasta", + "CantDeleteFolder": "Não é possível eliminar a pasta", + "CantDeleteNonEmptyFolder": "Não é possível eliminar pastas com conteúdos", + "CantSubscribeFolder": "Não é possível subscrever a esta pasta", + "CantUnsubscribeFolder": "Não é possível anular a subsrição desta pasta", + "DemoSendMessageError": "Por motivos de segurança, esta conta de demonstração não tem permissão para enviar mensagens para endereços de e-mail externos!", + "DemoAccountError": "Por motivos de segurança, esta conta não tem permissão de executar esta ação!", + "AccountAlreadyExists": "Esta conta já existe", + "AccountDoesNotExist": "Esta conta não existe", + "AccountSwitchFailed": "A mudança para a conta \"%EMAIL%\" falhou", + "MailServerError": "Ocorreu um erro ao aceder ao servidor de correio", + "InvalidInputArgument": "Parâmetro de entrada inválido", + "UnknownError": "Erro desconhecido" } } diff --git a/snappymail/v/0.0.0/app/localization/pt/admin.json b/snappymail/v/0.0.0/app/localization/pt/admin.json index 12adf1893..c7849e0bd 100644 --- a/snappymail/v/0.0.0/app/localization/pt/admin.json +++ b/snappymail/v/0.0.0/app/localization/pt/admin.json @@ -168,17 +168,17 @@ "UNKNOWN_ERROR": "Erro desconhecido" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "A solicitação falhou", - "REQUEST_ABORTED": "A solicitação foi abortada", - "REQUEST_TIMEOUT": "A solicitação expirou", - "INVALID_TOKEN": "Token inválido", - "AUTH_ERROR": "A autenticação falhou", - "DOMAIN_ALREADY_EXISTS": "O domínio já existe", - "CANT_SAVE_PLUGIN_SETTINGS": "Não é possível guardar as definições", - "CANT_INSTALL_PACKAGE": "Não foi possível instalar a extensão", - "CANT_DELETE_PACKAGE": "Não foi possível remover a extensão", - "INVALID_PLUGIN_PACKAGE": "Pacote de extensão inválido", - "UNSUPPORTED_PLUGIN_PACKAGE": "Pacote de extensão não suportado", - "UNKNOWN_ERROR": "Erro desconhecido" + "RequestError": "A solicitação falhou", + "RequestAborted": "A solicitação foi abortada", + "RequestTimeout": "A solicitação expirou", + "InvalidToken": "Token inválido", + "AuthError": "A autenticação falhou", + "DomainAlreadyExists": "O domínio já existe", + "CantSavePluginSettings": "Não é possível guardar as definições", + "CantInstallPackage": "Não foi possível instalar a extensão", + "CantDeletePackage": "Não foi possível remover a extensão", + "InvalidPluginPackage": "Pacote de extensão inválido", + "UnsupportedPluginPackage": "Pacote de extensão não suportado", + "UnknownError": "Erro desconhecido" } } diff --git a/snappymail/v/0.0.0/app/localization/pt/user.json b/snappymail/v/0.0.0/app/localization/pt/user.json index 603d28cab..9da68b559 100644 --- a/snappymail/v/0.0.0/app/localization/pt/user.json +++ b/snappymail/v/0.0.0/app/localization/pt/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "Fechar janela de composição" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "A solicitação falhou", - "REQUEST_ABORTED": "A solicitação foi abortada", - "REQUEST_TIMEOUT": "A solicitação expirou", - "INVALID_TOKEN": "Token inválido", - "AUTH_ERROR": "A autenticação falhou", - "CONNECTION_ERROR": "Não foi possível ligar ao servidor", - "DOMAIN_ALREADY_EXISTS": "O domínio já existe", - "DOMAIN_NOT_ALLOWED": "Este domínio não é permitido", - "ACCOUNT_NOT_ALLOWED": "Esta conta não é permitida", - "CONTACTS_SYNC_ERROR": "Erro na sincronização de contactos", - "CANT_GET_MESSAGE_LIST": "Não é possível obter a lista de mensagens", - "CANT_GET_MESSAGE": "Não é possível obter a mensagem", - "CANT_DELETE_MESSAGE": "Não é possível eliminar a mensagem", - "CANT_COPY_MESSAGE": "Não é possível copiar a mensagem", - "CANT_MOVE_MESSAGE": "Não é possível mover a mensagem", - "CANT_SAVE_MESSAGE": "Não é possível guardar a mensagem", - "CANT_SEND_MESSAGE": "Não é possível enviar a mensagem", - "INVALID_RECIPIENTS": "Destinatários inválidos", - "CANT_SAVE_FILTERS": "Não é possível guardar os filtros", - "CANT_GET_FILTERS": "Não é possível obter os filtros", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Não é possível ativar o script de filtração", - "CANT_DELETE_FILTERS_SCRIPT": "Não é possível apagar o script de filtração", - "FILTERS_ARE_NOT_CORRECT": "Os filtros não estão corretos", - "CANT_CREATE_FOLDER": "Não é possível criar a pasta", - "CANT_RENAME_FOLDER": "Não é possível renomear a pasta", - "CANT_DELETE_FOLDER": "Não é possível eliminar a pasta", - "CANT_DELETE_NON_EMPTY_FOLDER": "Não é possível eliminar pastas com conteúdos", - "CANT_SUBSCRIBE_FOLDER": "Não é possível subscrever a esta pasta", - "CANT_UNSUBSCRIBE_FOLDER": "Não é possível anular a subsrição desta pasta", - "DEMO_SEND_MESSAGE_ERROR": "Por motivos de segurança, esta conta de demonstração não tem permissão para enviar mensagens para endereços de e-mail externos!", - "DEMO_ACCOUNT_ERROR": "Por motivos de segurança, esta conta não tem permissão de executar esta ação!", - "ACCOUNT_ALREADY_EXISTS": "Esta conta já existe", - "ACCOUNT_DOES_NOT_EXIST": "Esta conta não existe", - "ACCOUNT_SWITCH_FAILED": "A mudança para a conta \"%EMAIL%\" falhou", - "MAIL_SERVER_ERROR": "Ocorreu um erro ao aceder ao servidor de correio", - "INVALID_INPUT_ARGUMENT": "Parâmetro de entrada inválido", - "UNKNOWN_ERROR": "Erro desconhecido" + "RequestError": "A solicitação falhou", + "RequestAborted": "A solicitação foi abortada", + "RequestTimeout": "A solicitação expirou", + "InvalidToken": "Token inválido", + "AuthError": "A autenticação falhou", + "ConnectionError": "Não foi possível ligar ao servidor", + "DomainAlreadyExists": "O domínio já existe", + "DomainNotAllowed": "Este domínio não é permitido", + "AccountNotAllowed": "Esta conta não é permitida", + "ContactsSyncError": "Erro na sincronização de contactos", + "CantGetMessageList": "Não é possível obter a lista de mensagens", + "CantGetMessage": "Não é possível obter a mensagem", + "CantDeleteMessage": "Não é possível eliminar a mensagem", + "CantCopyMessage": "Não é possível copiar a mensagem", + "CantMoveMessage": "Não é possível mover a mensagem", + "CantSaveMessage": "Não é possível guardar a mensagem", + "CantSendMessage": "Não é possível enviar a mensagem", + "InvalidRecipients": "Destinatários inválidos", + "CantSaveFilters": "Não é possível guardar os filtros", + "CantGetFilters": "Não é possível obter os filtros", + "CantActivateFiltersScript": "Não é possível ativar o script de filtração", + "CantDeleteFiltersScript": "Não é possível apagar o script de filtração", + "FiltersAreNotCorrect": "Os filtros não estão corretos", + "CantCreateFolder": "Não é possível criar a pasta", + "CantRenameFolder": "Não é possível renomear a pasta", + "CantDeleteFolder": "Não é possível eliminar a pasta", + "CantDeleteNonEmptyFolder": "Não é possível eliminar pastas com conteúdos", + "CantSubscribeFolder": "Não é possível subscrever a esta pasta", + "CantUnsubscribeFolder": "Não é possível anular a subsrição desta pasta", + "DemoSendMessageError": "Por motivos de segurança, esta conta de demonstração não tem permissão para enviar mensagens para endereços de e-mail externos!", + "DemoAccountError": "Por motivos de segurança, esta conta não tem permissão de executar esta ação!", + "AccountAlreadyExists": "Esta conta já existe", + "AccountDoesNotExist": "Esta conta não existe", + "AccountSwitchFailed": "A mudança para a conta \"%EMAIL%\" falhou", + "MailServerError": "Ocorreu um erro ao aceder ao servidor de correio", + "InvalidInputArgument": "Parâmetro de entrada inválido", + "UnknownError": "Erro desconhecido" } } diff --git a/snappymail/v/0.0.0/app/localization/ro-RO/user.json b/snappymail/v/0.0.0/app/localization/ro-RO/user.json index f6bf1d448..e1ed75994 100644 --- a/snappymail/v/0.0.0/app/localization/ro-RO/user.json +++ b/snappymail/v/0.0.0/app/localization/ro-RO/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "Close compose" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Semn invalid", - "AUTH_ERROR": "Nu se poate realiza conectarea", - "CONNECTION_ERROR": "Eroare la conectarea la server.", - "DOMAIN_ALREADY_EXISTS": "Domeniu există deja.", - "DOMAIN_NOT_ALLOWED": "Domeniul nu apartine de Wey5", - "ACCOUNT_NOT_ALLOWED": "Contul nu are permisiunea de conectare", - "CONTACTS_SYNC_ERROR": "Contacts synchronization error", - "CANT_GET_MESSAGE_LIST": "Nu găsesc o lista de scrisori", - "CANT_GET_MESSAGE": "Nu pot obține scrisoarea. Încercați din nou", - "CANT_DELETE_MESSAGE": "Nu pot șterge scrisoarea. Încercați din nou", - "CANT_COPY_MESSAGE": "Can't copy message", - "CANT_MOVE_MESSAGE": "Nu pot muta scrisoarea.Încercați din nou", - "CANT_SAVE_MESSAGE": "Nu pot salva mesajul. Încercați din nou", - "CANT_SEND_MESSAGE": "Nu pot trimite scrisoarea.Încercați din nou", - "INVALID_RECIPIENTS": "Verificați dacă ați introdus toate adresele.", - "CANT_SAVE_FILTERS": "Can't save filters", - "CANT_GET_FILTERS": "Can't get filters", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Can't activate filters script", - "CANT_DELETE_FILTERS_SCRIPT": "Can't delete filters script", - "FILTERS_ARE_NOT_CORRECT": "Filters are not correct", - "CANT_CREATE_FOLDER": "Nu crea dosarul. Încercați din nou", - "CANT_RENAME_FOLDER": "Nu pot redenumi dosarul. Încercați din nou", - "CANT_DELETE_FOLDER": "Nu pot șterge dosarul. Încercați din nou", - "CANT_DELETE_NON_EMPTY_FOLDER": "Nu pot șterge un dosar care nu este gol", - "CANT_SUBSCRIBE_FOLDER": "Nu pot semna dosarul. Încercați din nou", - "CANT_UNSUBSCRIBE_FOLDER": "Nu mă pot dezbona. Încercați din nou", - "DEMO_SEND_MESSAGE_ERROR": "Cont demo trimite e-mail la adresele de e-mail externe este interzisă!", - "DEMO_ACCOUNT_ERROR": "For security purposes, this account is not allowed for this action!", - "ACCOUNT_ALREADY_EXISTS": "Contul deja există", - "ACCOUNT_DOES_NOT_EXIST": "contul nu există", - "ACCOUNT_SWITCH_FAILED": "Switch to account \"%EMAIL%\" failed", - "MAIL_SERVER_ERROR": "Nu am reușit să accesez serverul de e-mail", - "INVALID_INPUT_ARGUMENT": "Invalid input argument", - "UNKNOWN_ERROR": "Eroare necunoscută" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Semn invalid", + "AuthError": "Nu se poate realiza conectarea", + "ConnectionError": "Eroare la conectarea la server.", + "DomainAlreadyExists": "Domeniu există deja.", + "DomainNotAllowed": "Domeniul nu apartine de Wey5", + "AccountNotAllowed": "Contul nu are permisiunea de conectare", + "ContactsSyncError": "Contacts synchronization error", + "CantGetMessageList": "Nu găsesc o lista de scrisori", + "CantGetMessage": "Nu pot obține scrisoarea. Încercați din nou", + "CantDeleteMessage": "Nu pot șterge scrisoarea. Încercați din nou", + "CantCopyMessage": "Can't copy message", + "CantMoveMessage": "Nu pot muta scrisoarea.Încercați din nou", + "CantSaveMessage": "Nu pot salva mesajul. Încercați din nou", + "CantSendMessage": "Nu pot trimite scrisoarea.Încercați din nou", + "InvalidRecipients": "Verificați dacă ați introdus toate adresele.", + "CantSaveFilters": "Can't save filters", + "CantGetFilters": "Can't get filters", + "CantActivateFiltersScript": "Can't activate filters script", + "CantDeleteFiltersScript": "Can't delete filters script", + "FiltersAreNotCorrect": "Filters are not correct", + "CantCreateFolder": "Nu crea dosarul. Încercați din nou", + "CantRenameFolder": "Nu pot redenumi dosarul. Încercați din nou", + "CantDeleteFolder": "Nu pot șterge dosarul. Încercați din nou", + "CantDeleteNonEmptyFolder": "Nu pot șterge un dosar care nu este gol", + "CantSubscribeFolder": "Nu pot semna dosarul. Încercați din nou", + "CantUnsubscribeFolder": "Nu mă pot dezbona. Încercați din nou", + "DemoSendMessageError": "Cont demo trimite e-mail la adresele de e-mail externe este interzisă!", + "DemoAccountError": "For security purposes, this account is not allowed for this action!", + "AccountAlreadyExists": "Contul deja există", + "AccountDoesNotExist": "contul nu există", + "AccountSwitchFailed": "Switch to account \"%EMAIL%\" failed", + "MailServerError": "Nu am reușit să accesez serverul de e-mail", + "InvalidInputArgument": "Invalid input argument", + "UnknownError": "Eroare necunoscută" } } diff --git a/snappymail/v/0.0.0/app/localization/ru-RU/admin.json b/snappymail/v/0.0.0/app/localization/ru-RU/admin.json index d516e2a7f..46103cbd1 100644 --- a/snappymail/v/0.0.0/app/localization/ru-RU/admin.json +++ b/snappymail/v/0.0.0/app/localization/ru-RU/admin.json @@ -168,17 +168,17 @@ "UNKNOWN_ERROR": "Неизвестная ошибка" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Запрос не выполнен", - "REQUEST_ABORTED": "Запрос прерван", - "REQUEST_TIMEOUT": "Истекло время запроса", - "INVALID_TOKEN": "Неверный токен запроса", - "AUTH_ERROR": "Не удалось авторизоваться", - "DOMAIN_ALREADY_EXISTS": "Домен уже существует", - "CANT_SAVE_PLUGIN_SETTINGS": "Не могу сохранить настройки", - "CANT_INSTALL_PACKAGE": "Ошибка установки плагина", - "CANT_DELETE_PACKAGE": "Ошибка удаления плагина", - "INVALID_PLUGIN_PACKAGE": "Ошибка пакета плагина", - "UNSUPPORTED_PLUGIN_PACKAGE": "Для работы плагина необходима полная поддержка сервера", - "UNKNOWN_ERROR": "Неизвестная ошибка" + "RequestError": "Запрос не выполнен", + "RequestAborted": "Запрос прерван", + "RequestTimeout": "Истекло время запроса", + "InvalidToken": "Неверный токен запроса", + "AuthError": "Не удалось авторизоваться", + "DomainAlreadyExists": "Домен уже существует", + "CantSavePluginSettings": "Не могу сохранить настройки", + "CantInstallPackage": "Ошибка установки плагина", + "CantDeletePackage": "Ошибка удаления плагина", + "InvalidPluginPackage": "Ошибка пакета плагина", + "UnsupportedPluginPackage": "Для работы плагина необходима полная поддержка сервера", + "UnknownError": "Неизвестная ошибка" } } diff --git a/snappymail/v/0.0.0/app/localization/ru-RU/user.json b/snappymail/v/0.0.0/app/localization/ru-RU/user.json index a9b841bc7..d0acfb3b1 100644 --- a/snappymail/v/0.0.0/app/localization/ru-RU/user.json +++ b/snappymail/v/0.0.0/app/localization/ru-RU/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "Закрыть сообщение" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Запрос не выполнен", - "REQUEST_ABORTED": "Запрос прерван", - "REQUEST_TIMEOUT": "Истекло время запроса", - "INVALID_TOKEN": "Неверный токен запроса", - "AUTH_ERROR": "Не удалось авторизоваться", - "CONNECTION_ERROR": "Ошибка соединения с сервером.", - "DOMAIN_ALREADY_EXISTS": "Домен уже существует", - "DOMAIN_NOT_ALLOWED": "Данный домен не разрешен", - "ACCOUNT_NOT_ALLOWED": "Данный аккаунт не разрешен", - "CONTACTS_SYNC_ERROR": "Ошибка синхронизации контактов", - "CANT_GET_MESSAGE_LIST": "Не могу получить список писем", - "CANT_GET_MESSAGE": "Не могу получить письмо", - "CANT_DELETE_MESSAGE": "Не могу удалить письмо", - "CANT_COPY_MESSAGE": "Не могу скопировать сообщение", - "CANT_MOVE_MESSAGE": "Не могу переместить письмо", - "CANT_SAVE_MESSAGE": "Не могу сохранить письмо", - "CANT_SEND_MESSAGE": "Не могу отправить письмо", - "INVALID_RECIPIENTS": "Проверьте правильность ввода всех адресов.", - "CANT_SAVE_FILTERS": "Не могу сохранить фильтры", - "CANT_GET_FILTERS": "Не могу загрузить фильтры", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Не могу активировать сценарий фильтров", - "CANT_DELETE_FILTERS_SCRIPT": "Не могу удалить сценарий фильтров", - "FILTERS_ARE_NOT_CORRECT": "Фильтры неправильны", - "CANT_CREATE_FOLDER": "Не могу создать папку", - "CANT_RENAME_FOLDER": "Не могу переименовать папку", - "CANT_DELETE_FOLDER": "Не могу удалить папку", - "CANT_DELETE_NON_EMPTY_FOLDER": "Не могу удалить непустую папку", - "CANT_SUBSCRIBE_FOLDER": "Не могу подписать папку", - "CANT_UNSUBSCRIBE_FOLDER": "Не могу отписать папку", - "DEMO_SEND_MESSAGE_ERROR": "Демо аккаунту отправка писем на внешние почтовые адреса запрещена!", - "DEMO_ACCOUNT_ERROR": "По соображениям безопасности данный аккаунт не может выполнить это действие.", - "ACCOUNT_ALREADY_EXISTS": "Аккаунт уже добавлен", - "ACCOUNT_DOES_NOT_EXIST": "Аккаунт не существует", - "ACCOUNT_SWITCH_FAILED": "Не удалось переключиться на учетную запись \"%EMAIL%\"", - "MAIL_SERVER_ERROR": "Ошибка доступа к почтовому серверу", - "INVALID_INPUT_ARGUMENT": "Неверный параметр", - "UNKNOWN_ERROR": "Неизвестная ошибка" + "RequestError": "Запрос не выполнен", + "RequestAborted": "Запрос прерван", + "RequestTimeout": "Истекло время запроса", + "InvalidToken": "Неверный токен запроса", + "AuthError": "Не удалось авторизоваться", + "ConnectionError": "Ошибка соединения с сервером.", + "DomainAlreadyExists": "Домен уже существует", + "DomainNotAllowed": "Данный домен не разрешен", + "AccountNotAllowed": "Данный аккаунт не разрешен", + "ContactsSyncError": "Ошибка синхронизации контактов", + "CantGetMessageList": "Не могу получить список писем", + "CantGetMessage": "Не могу получить письмо", + "CantDeleteMessage": "Не могу удалить письмо", + "CantCopyMessage": "Не могу скопировать сообщение", + "CantMoveMessage": "Не могу переместить письмо", + "CantSaveMessage": "Не могу сохранить письмо", + "CantSendMessage": "Не могу отправить письмо", + "InvalidRecipients": "Проверьте правильность ввода всех адресов.", + "CantSaveFilters": "Не могу сохранить фильтры", + "CantGetFilters": "Не могу загрузить фильтры", + "CantActivateFiltersScript": "Не могу активировать сценарий фильтров", + "CantDeleteFiltersScript": "Не могу удалить сценарий фильтров", + "FiltersAreNotCorrect": "Фильтры неправильны", + "CantCreateFolder": "Не могу создать папку", + "CantRenameFolder": "Не могу переименовать папку", + "CantDeleteFolder": "Не могу удалить папку", + "CantDeleteNonEmptyFolder": "Не могу удалить непустую папку", + "CantSubscribeFolder": "Не могу подписать папку", + "CantUnsubscribeFolder": "Не могу отписать папку", + "DemoSendMessageError": "Демо аккаунту отправка писем на внешние почтовые адреса запрещена!", + "DemoAccountError": "По соображениям безопасности данный аккаунт не может выполнить это действие.", + "AccountAlreadyExists": "Аккаунт уже добавлен", + "AccountDoesNotExist": "Аккаунт не существует", + "AccountSwitchFailed": "Не удалось переключиться на учетную запись \"%EMAIL%\"", + "MailServerError": "Ошибка доступа к почтовому серверу", + "InvalidInputArgument": "Неверный параметр", + "UnknownError": "Неизвестная ошибка" } } diff --git a/snappymail/v/0.0.0/app/localization/sk-SK/admin.json b/snappymail/v/0.0.0/app/localization/sk-SK/admin.json index 71e3f1772..42ed92a32 100644 --- a/snappymail/v/0.0.0/app/localization/sk-SK/admin.json +++ b/snappymail/v/0.0.0/app/localization/sk-SK/admin.json @@ -168,17 +168,17 @@ "UNKNOWN_ERROR": "Neznáma chyba" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Neplatný token", - "AUTH_ERROR": "Overenie zlyhalo", - "DOMAIN_ALREADY_EXISTS": "Táto Doména už existuje", - "CANT_SAVE_PLUGIN_SETTINGS": "Nastavenia sa nepodarilo uložiť", - "CANT_INSTALL_PACKAGE": "Inštalácia balíčka zlyhala", - "CANT_DELETE_PACKAGE": "Odstránenie balíčka zlyhalo", - "INVALID_PLUGIN_PACKAGE": "Invalid plugin package", - "UNSUPPORTED_PLUGIN_PACKAGE": "Unsupported plugin package", - "UNKNOWN_ERROR": "Neznáma chyba" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Neplatný token", + "AuthError": "Overenie zlyhalo", + "DomainAlreadyExists": "Táto Doména už existuje", + "CantSavePluginSettings": "Nastavenia sa nepodarilo uložiť", + "CantInstallPackage": "Inštalácia balíčka zlyhala", + "CantDeletePackage": "Odstránenie balíčka zlyhalo", + "InvalidPluginPackage": "Invalid plugin package", + "UnsupportedPluginPackage": "Unsupported plugin package", + "UnknownError": "Neznáma chyba" } } diff --git a/snappymail/v/0.0.0/app/localization/sk-SK/user.json b/snappymail/v/0.0.0/app/localization/sk-SK/user.json index 9f9eab751..fb0b69b30 100644 --- a/snappymail/v/0.0.0/app/localization/sk-SK/user.json +++ b/snappymail/v/0.0.0/app/localization/sk-SK/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "Close compose" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Neplatný token", - "AUTH_ERROR": "Overenie zlyhalo", - "CONNECTION_ERROR": "Nepodarilo sa pripojiť k serveru", - "DOMAIN_ALREADY_EXISTS": "Táto Doména už existuje", - "DOMAIN_NOT_ALLOWED": "Doména nie je povolená", - "ACCOUNT_NOT_ALLOWED": "Účet nie je povolený", - "CONTACTS_SYNC_ERROR": "Contacts synchronization error", - "CANT_GET_MESSAGE_LIST": "Chyba pri vytváraní zoznamu správ.", - "CANT_GET_MESSAGE": "Správu sa nepodarilo načítať", - "CANT_DELETE_MESSAGE": "Správu sa nepodarilo odstrániť", - "CANT_COPY_MESSAGE": "Can't copy message", - "CANT_MOVE_MESSAGE": "Správu sa nepodarilo presunúť", - "CANT_SAVE_MESSAGE": "Správu sa nepodarilo uložiť", - "CANT_SEND_MESSAGE": "Správu sa nepodarilo odoslať", - "INVALID_RECIPIENTS": "Neplatný príjemcovia", - "CANT_SAVE_FILTERS": "Can't save filters", - "CANT_GET_FILTERS": "Can't get filters", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Can't activate filters script", - "CANT_DELETE_FILTERS_SCRIPT": "Can't delete filters script", - "FILTERS_ARE_NOT_CORRECT": "Filters are not correct", - "CANT_CREATE_FOLDER": "Priečinok sa nepodarilo vytvoriť", - "CANT_RENAME_FOLDER": "Priečinok sa nepodarilo premenovať", - "CANT_DELETE_FOLDER": "Priečinok sa nepodarilo odstrániť", - "CANT_DELETE_NON_EMPTY_FOLDER": "Nemôžem odstrániť neprázdny priečinok", - "CANT_SUBSCRIBE_FOLDER": "Can't subscribe folder", - "CANT_UNSUBSCRIBE_FOLDER": "Can't unsubscribe folder", - "DEMO_SEND_MESSAGE_ERROR": "For security purposes, this demo account is not allowed to send messages to external e-mail addresses!", - "DEMO_ACCOUNT_ERROR": "For security purposes, this account is not allowed for this action!", - "ACCOUNT_ALREADY_EXISTS": "účet už existuje", - "ACCOUNT_DOES_NOT_EXIST": "Účet neexistuje", - "ACCOUNT_SWITCH_FAILED": "Switch to account \"%EMAIL%\" failed", - "MAIL_SERVER_ERROR": "Nastala chyba počas prístupu na poštový server", - "INVALID_INPUT_ARGUMENT": "Invalid input argument", - "UNKNOWN_ERROR": "Neznáma chyba" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Neplatný token", + "AuthError": "Overenie zlyhalo", + "ConnectionError": "Nepodarilo sa pripojiť k serveru", + "DomainAlreadyExists": "Táto Doména už existuje", + "DomainNotAllowed": "Doména nie je povolená", + "AccountNotAllowed": "Účet nie je povolený", + "ContactsSyncError": "Contacts synchronization error", + "CantGetMessageList": "Chyba pri vytváraní zoznamu správ.", + "CantGetMessage": "Správu sa nepodarilo načítať", + "CantDeleteMessage": "Správu sa nepodarilo odstrániť", + "CantCopyMessage": "Can't copy message", + "CantMoveMessage": "Správu sa nepodarilo presunúť", + "CantSaveMessage": "Správu sa nepodarilo uložiť", + "CantSendMessage": "Správu sa nepodarilo odoslať", + "InvalidRecipients": "Neplatný príjemcovia", + "CantSaveFilters": "Can't save filters", + "CantGetFilters": "Can't get filters", + "CantActivateFiltersScript": "Can't activate filters script", + "CantDeleteFiltersScript": "Can't delete filters script", + "FiltersAreNotCorrect": "Filters are not correct", + "CantCreateFolder": "Priečinok sa nepodarilo vytvoriť", + "CantRenameFolder": "Priečinok sa nepodarilo premenovať", + "CantDeleteFolder": "Priečinok sa nepodarilo odstrániť", + "CantDeleteNonEmptyFolder": "Nemôžem odstrániť neprázdny priečinok", + "CantSubscribeFolder": "Can't subscribe folder", + "CantUnsubscribeFolder": "Can't unsubscribe folder", + "DemoSendMessageError": "For security purposes, this demo account is not allowed to send messages to external e-mail addresses!", + "DemoAccountError": "For security purposes, this account is not allowed for this action!", + "AccountAlreadyExists": "účet už existuje", + "AccountDoesNotExist": "Účet neexistuje", + "AccountSwitchFailed": "Switch to account \"%EMAIL%\" failed", + "MailServerError": "Nastala chyba počas prístupu na poštový server", + "InvalidInputArgument": "Invalid input argument", + "UnknownError": "Neznáma chyba" } } diff --git a/snappymail/v/0.0.0/app/localization/sl-SI/admin.json b/snappymail/v/0.0.0/app/localization/sl-SI/admin.json index 3e9494052..a8d9843b5 100644 --- a/snappymail/v/0.0.0/app/localization/sl-SI/admin.json +++ b/snappymail/v/0.0.0/app/localization/sl-SI/admin.json @@ -168,17 +168,17 @@ "UNKNOWN_ERROR": "Neznana napaka" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Neveljaven žeton", - "AUTH_ERROR": "Spodletelo overjanje", - "DOMAIN_ALREADY_EXISTS": "Domena že obstaja", - "CANT_SAVE_PLUGIN_SETTINGS": "Ni mogoče shraniti nastavitev", - "CANT_INSTALL_PACKAGE": "Neuspešna namestitev paketa", - "CANT_DELETE_PACKAGE": "Neuspešno odstranjevanje paketa", - "INVALID_PLUGIN_PACKAGE": "Neveljaven paket vtičnika", - "UNSUPPORTED_PLUGIN_PACKAGE": "Nepodprt paket vtičnika", - "UNKNOWN_ERROR": "Neznana napaka" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Neveljaven žeton", + "AuthError": "Spodletelo overjanje", + "DomainAlreadyExists": "Domena že obstaja", + "CantSavePluginSettings": "Ni mogoče shraniti nastavitev", + "CantInstallPackage": "Neuspešna namestitev paketa", + "CantDeletePackage": "Neuspešno odstranjevanje paketa", + "InvalidPluginPackage": "Neveljaven paket vtičnika", + "UnsupportedPluginPackage": "Nepodprt paket vtičnika", + "UnknownError": "Neznana napaka" } } diff --git a/snappymail/v/0.0.0/app/localization/sl-SI/user.json b/snappymail/v/0.0.0/app/localization/sl-SI/user.json index a62f793f0..7c31febc4 100644 --- a/snappymail/v/0.0.0/app/localization/sl-SI/user.json +++ b/snappymail/v/0.0.0/app/localization/sl-SI/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "Zapri sestavljanje" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Neveljaven žeton", - "AUTH_ERROR": "Spodletelo overjanje", - "CONNECTION_ERROR": "Ni mogoče vzpostaviti povezave s strežnikom", - "DOMAIN_ALREADY_EXISTS": "Domena že obstaja", - "DOMAIN_NOT_ALLOWED": "Domena ni dovoljena", - "ACCOUNT_NOT_ALLOWED": "Račun ni dovoljen", - "CONTACTS_SYNC_ERROR": "Napaka sinhronizacije stikov", - "CANT_GET_MESSAGE_LIST": "Ni mogoče pridobiti seznama sporočil", - "CANT_GET_MESSAGE": "Ni mogoče pridobiti sporočila", - "CANT_DELETE_MESSAGE": "Ni mogoče izbrisati sporočila", - "CANT_COPY_MESSAGE": "Can't copy message", - "CANT_MOVE_MESSAGE": "Ni mogoče premakniti sporočila", - "CANT_SAVE_MESSAGE": "Ni mogoče shraniti sporočila", - "CANT_SEND_MESSAGE": "Ni mogoče poslati sporočila", - "INVALID_RECIPIENTS": "Neveljavni prejemniki", - "CANT_SAVE_FILTERS": "Ni mogoče shraniti filtrov", - "CANT_GET_FILTERS": "Ni mogoče pridobiti filtrov", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Can't activate filters script", - "CANT_DELETE_FILTERS_SCRIPT": "Can't delete filters script", - "FILTERS_ARE_NOT_CORRECT": "Filtri so nepravilni", - "CANT_CREATE_FOLDER": "Ni mogoče ustvariti mape", - "CANT_RENAME_FOLDER": "Ni mogoče preimenovati mape", - "CANT_DELETE_FOLDER": "Ni mogoče izbrisati mape", - "CANT_DELETE_NON_EMPTY_FOLDER": "Ni mogoče izbrisati neprazne mape", - "CANT_SUBSCRIBE_FOLDER": "Ni mogoče slediti mapi", - "CANT_UNSUBSCRIBE_FOLDER": "Ni mogoče prenehati slediti mapi", - "DEMO_SEND_MESSAGE_ERROR": "Iz varnostnih razlogov ta račun ne sme pošiljati pošte na zunanje e-naslove!", - "DEMO_ACCOUNT_ERROR": "Iz varnostnih razlogov ta račun ne sme izvršiti tega dejanja!", - "ACCOUNT_ALREADY_EXISTS": "Račun že obstaja", - "ACCOUNT_DOES_NOT_EXIST": "Račun ne obstaja", - "ACCOUNT_SWITCH_FAILED": "Switch to account \"%EMAIL%\" failed", - "MAIL_SERVER_ERROR": "Napaka pri dostopu do poštnega strežnika", - "INVALID_INPUT_ARGUMENT": "Neveljaven vhodni argument", - "UNKNOWN_ERROR": "Neznana napaka" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Neveljaven žeton", + "AuthError": "Spodletelo overjanje", + "ConnectionError": "Ni mogoče vzpostaviti povezave s strežnikom", + "DomainAlreadyExists": "Domena že obstaja", + "DomainNotAllowed": "Domena ni dovoljena", + "AccountNotAllowed": "Račun ni dovoljen", + "ContactsSyncError": "Napaka sinhronizacije stikov", + "CantGetMessageList": "Ni mogoče pridobiti seznama sporočil", + "CantGetMessage": "Ni mogoče pridobiti sporočila", + "CantDeleteMessage": "Ni mogoče izbrisati sporočila", + "CantCopyMessage": "Can't copy message", + "CantMoveMessage": "Ni mogoče premakniti sporočila", + "CantSaveMessage": "Ni mogoče shraniti sporočila", + "CantSendMessage": "Ni mogoče poslati sporočila", + "InvalidRecipients": "Neveljavni prejemniki", + "CantSaveFilters": "Ni mogoče shraniti filtrov", + "CantGetFilters": "Ni mogoče pridobiti filtrov", + "CantActivateFiltersScript": "Can't activate filters script", + "CantDeleteFiltersScript": "Can't delete filters script", + "FiltersAreNotCorrect": "Filtri so nepravilni", + "CantCreateFolder": "Ni mogoče ustvariti mape", + "CantRenameFolder": "Ni mogoče preimenovati mape", + "CantDeleteFolder": "Ni mogoče izbrisati mape", + "CantDeleteNonEmptyFolder": "Ni mogoče izbrisati neprazne mape", + "CantSubscribeFolder": "Ni mogoče slediti mapi", + "CantUnsubscribeFolder": "Ni mogoče prenehati slediti mapi", + "DemoSendMessageError": "Iz varnostnih razlogov ta račun ne sme pošiljati pošte na zunanje e-naslove!", + "DemoAccountError": "Iz varnostnih razlogov ta račun ne sme izvršiti tega dejanja!", + "AccountAlreadyExists": "Račun že obstaja", + "AccountDoesNotExist": "Račun ne obstaja", + "AccountSwitchFailed": "Switch to account \"%EMAIL%\" failed", + "MailServerError": "Napaka pri dostopu do poštnega strežnika", + "InvalidInputArgument": "Neveljaven vhodni argument", + "UnknownError": "Neznana napaka" } } diff --git a/snappymail/v/0.0.0/app/localization/sv-SE/admin.json b/snappymail/v/0.0.0/app/localization/sv-SE/admin.json index 1d7730891..3cdfed6e9 100644 --- a/snappymail/v/0.0.0/app/localization/sv-SE/admin.json +++ b/snappymail/v/0.0.0/app/localization/sv-SE/admin.json @@ -168,17 +168,17 @@ "UNKNOWN_ERROR": "Okänt fel" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "ogiltiga symboler", - "AUTH_ERROR": "Autentisering misslyckades", - "DOMAIN_ALREADY_EXISTS": "Domänen finns redan", - "CANT_SAVE_PLUGIN_SETTINGS": "Kan inte spara inställningarna", - "CANT_INSTALL_PACKAGE": "Det gick inte att installera tillägget", - "CANT_DELETE_PACKAGE": "Det gick inte att ta bort tillägget", - "INVALID_PLUGIN_PACKAGE": "Ogiltigt tilläggspaket", - "UNSUPPORTED_PLUGIN_PACKAGE": "Tillägg som inte stöds", - "UNKNOWN_ERROR": "Okänt fel" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "ogiltiga symboler", + "AuthError": "Autentisering misslyckades", + "DomainAlreadyExists": "Domänen finns redan", + "CantSavePluginSettings": "Kan inte spara inställningarna", + "CantInstallPackage": "Det gick inte att installera tillägget", + "CantDeletePackage": "Det gick inte att ta bort tillägget", + "InvalidPluginPackage": "Ogiltigt tilläggspaket", + "UnsupportedPluginPackage": "Tillägg som inte stöds", + "UnknownError": "Okänt fel" } } diff --git a/snappymail/v/0.0.0/app/localization/sv-SE/user.json b/snappymail/v/0.0.0/app/localization/sv-SE/user.json index 4041f143c..799f50aba 100644 --- a/snappymail/v/0.0.0/app/localization/sv-SE/user.json +++ b/snappymail/v/0.0.0/app/localization/sv-SE/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "Stäng fönster" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Ogiltigt tecken", - "AUTH_ERROR": "Autentisering misslyckades", - "CONNECTION_ERROR": "Kan inte ansluta till servern", - "DOMAIN_ALREADY_EXISTS": "Domänen finns redan", - "DOMAIN_NOT_ALLOWED": "Domän är inte tillåtet", - "ACCOUNT_NOT_ALLOWED": "Konto är inte tillåtet", - "CONTACTS_SYNC_ERROR": "Kontakt-synkroniseringsfel", - "CANT_GET_MESSAGE_LIST": "Kan inte hämta meddelandelista", - "CANT_GET_MESSAGE": "Kan inte hämta meddelande", - "CANT_DELETE_MESSAGE": "Kan inte ta bort meddelande", - "CANT_COPY_MESSAGE": "Can't copy message", - "CANT_MOVE_MESSAGE": "Kan inte flytta meddelande", - "CANT_SAVE_MESSAGE": "Kan inte spara meddelande", - "CANT_SEND_MESSAGE": "Kan inte skicka meddelande", - "INVALID_RECIPIENTS": "Ogiltig mottagare", - "CANT_SAVE_FILTERS": "Kan inte spara filter", - "CANT_GET_FILTERS": "Kan inte ta emot filter", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Can't activate filters script", - "CANT_DELETE_FILTERS_SCRIPT": "Can't delete filters script", - "FILTERS_ARE_NOT_CORRECT": "Filter är inte korrekt", - "CANT_CREATE_FOLDER": "Kan inte skapa mapp", - "CANT_RENAME_FOLDER": "Kan inte byta namn på mapp", - "CANT_DELETE_FOLDER": "Kan inte ta bort mapp", - "CANT_DELETE_NON_EMPTY_FOLDER": "Kan inte ta bort mapp med innehåll", - "CANT_SUBSCRIBE_FOLDER": "Kan inte prenumerera på mapp", - "CANT_UNSUBSCRIBE_FOLDER": "Kan inte avprenumerera på mapp", - "DEMO_SEND_MESSAGE_ERROR": "Av säkerhets skäl kan inte detta demo-konto skicka epost till externa adressater!", - "DEMO_ACCOUNT_ERROR": "Av säkerhetsskäl är det här kontot inte tillåtet för denna åtgärd!", - "ACCOUNT_ALREADY_EXISTS": "Kontot finns redan", - "ACCOUNT_DOES_NOT_EXIST": "Kontot finns inte", - "ACCOUNT_SWITCH_FAILED": "Switch to account \"%EMAIL%\" failed", - "MAIL_SERVER_ERROR": "Ett fel har inträffat vid anslutning till epostservern", - "INVALID_INPUT_ARGUMENT": "Ogiltigt argument", - "UNKNOWN_ERROR": "Okänt fel" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Ogiltigt tecken", + "AuthError": "Autentisering misslyckades", + "ConnectionError": "Kan inte ansluta till servern", + "DomainAlreadyExists": "Domänen finns redan", + "DomainNotAllowed": "Domän är inte tillåtet", + "AccountNotAllowed": "Konto är inte tillåtet", + "ContactsSyncError": "Kontakt-synkroniseringsfel", + "CantGetMessageList": "Kan inte hämta meddelandelista", + "CantGetMessage": "Kan inte hämta meddelande", + "CantDeleteMessage": "Kan inte ta bort meddelande", + "CantCopyMessage": "Can't copy message", + "CantMoveMessage": "Kan inte flytta meddelande", + "CantSaveMessage": "Kan inte spara meddelande", + "CantSendMessage": "Kan inte skicka meddelande", + "InvalidRecipients": "Ogiltig mottagare", + "CantSaveFilters": "Kan inte spara filter", + "CantGetFilters": "Kan inte ta emot filter", + "CantActivateFiltersScript": "Can't activate filters script", + "CantDeleteFiltersScript": "Can't delete filters script", + "FiltersAreNotCorrect": "Filter är inte korrekt", + "CantCreateFolder": "Kan inte skapa mapp", + "CantRenameFolder": "Kan inte byta namn på mapp", + "CantDeleteFolder": "Kan inte ta bort mapp", + "CantDeleteNonEmptyFolder": "Kan inte ta bort mapp med innehåll", + "CantSubscribeFolder": "Kan inte prenumerera på mapp", + "CantUnsubscribeFolder": "Kan inte avprenumerera på mapp", + "DemoSendMessageError": "Av säkerhets skäl kan inte detta demo-konto skicka epost till externa adressater!", + "DemoAccountError": "Av säkerhetsskäl är det här kontot inte tillåtet för denna åtgärd!", + "AccountAlreadyExists": "Kontot finns redan", + "AccountDoesNotExist": "Kontot finns inte", + "AccountSwitchFailed": "Switch to account \"%EMAIL%\" failed", + "MailServerError": "Ett fel har inträffat vid anslutning till epostservern", + "InvalidInputArgument": "Ogiltigt argument", + "UnknownError": "Okänt fel" } } diff --git a/snappymail/v/0.0.0/app/localization/tr-TR/user.json b/snappymail/v/0.0.0/app/localization/tr-TR/user.json index 6d0e83dd6..d291e58d1 100644 --- a/snappymail/v/0.0.0/app/localization/tr-TR/user.json +++ b/snappymail/v/0.0.0/app/localization/tr-TR/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "Oluşturulanı Kapat" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Geçersiz token", - "AUTH_ERROR": "Kimlik doğrulama başarısız oldu", - "CONNECTION_ERROR": "Sunucuya bağlanılamadı", - "DOMAIN_ALREADY_EXISTS": "Alanadı bulunuyor", - "DOMAIN_NOT_ALLOWED": "Alan Adına izin verilmemiş", - "ACCOUNT_NOT_ALLOWED": "Hesaba izin verilmemiş", - "CONTACTS_SYNC_ERROR": "Kişi listesi senkronizasyon hatası", - "CANT_GET_MESSAGE_LIST": "Mesaj listesi alınamadı", - "CANT_GET_MESSAGE": "Mesaj alınamadı", - "CANT_DELETE_MESSAGE": "Mesaj silinemedi", - "CANT_COPY_MESSAGE": "Can't copy message", - "CANT_MOVE_MESSAGE": "Mesaj taşınamadı", - "CANT_SAVE_MESSAGE": "Mesaj kaydedilemedi", - "CANT_SEND_MESSAGE": "Mesaj gönderilemedi", - "INVALID_RECIPIENTS": "Geçersiz alıcılar", - "CANT_SAVE_FILTERS": "Can't save filters", - "CANT_GET_FILTERS": "Can't get filters", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Can't activate filters script", - "CANT_DELETE_FILTERS_SCRIPT": "Can't delete filters script", - "FILTERS_ARE_NOT_CORRECT": "Filters are not correct", - "CANT_CREATE_FOLDER": "Klasör oluşturulamadı", - "CANT_RENAME_FOLDER": "Klasör oluşturulamadı", - "CANT_DELETE_FOLDER": "Klasör silimedi", - "CANT_DELETE_NON_EMPTY_FOLDER": "Boş olmayan dizin silinemedi", - "CANT_SUBSCRIBE_FOLDER": "Klasöre abone olunamadı", - "CANT_UNSUBSCRIBE_FOLDER": "Klasör Aboneliğinden çıkılamadı", - "DEMO_SEND_MESSAGE_ERROR": "Güvenlik amacıyla, bu demo hesabı harici e-posta adreslerine mesaj göndermek için izin verilmez!", - "DEMO_ACCOUNT_ERROR": "For security purposes, this account is not allowed for this action!", - "ACCOUNT_ALREADY_EXISTS": "Hesap zaten var", - "ACCOUNT_DOES_NOT_EXIST": "Account doesn't exist", - "ACCOUNT_SWITCH_FAILED": "Switch to account \"%EMAIL%\" failed", - "MAIL_SERVER_ERROR": "Posta sunucusuna erişirken bir hata oluştu", - "INVALID_INPUT_ARGUMENT": "Invalid input argument", - "UNKNOWN_ERROR": "Bilinmeyen Hata" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Geçersiz token", + "AuthError": "Kimlik doğrulama başarısız oldu", + "ConnectionError": "Sunucuya bağlanılamadı", + "DomainAlreadyExists": "Alanadı bulunuyor", + "DomainNotAllowed": "Alan Adına izin verilmemiş", + "AccountNotAllowed": "Hesaba izin verilmemiş", + "ContactsSyncError": "Kişi listesi senkronizasyon hatası", + "CantGetMessageList": "Mesaj listesi alınamadı", + "CantGetMessage": "Mesaj alınamadı", + "CantDeleteMessage": "Mesaj silinemedi", + "CantCopyMessage": "Can't copy message", + "CantMoveMessage": "Mesaj taşınamadı", + "CantSaveMessage": "Mesaj kaydedilemedi", + "CantSendMessage": "Mesaj gönderilemedi", + "InvalidRecipients": "Geçersiz alıcılar", + "CantSaveFilters": "Can't save filters", + "CantGetFilters": "Can't get filters", + "CantActivateFiltersScript": "Can't activate filters script", + "CantDeleteFiltersScript": "Can't delete filters script", + "FiltersAreNotCorrect": "Filters are not correct", + "CantCreateFolder": "Klasör oluşturulamadı", + "CantRenameFolder": "Klasör oluşturulamadı", + "CantDeleteFolder": "Klasör silimedi", + "CantDeleteNonEmptyFolder": "Boş olmayan dizin silinemedi", + "CantSubscribeFolder": "Klasöre abone olunamadı", + "CantUnsubscribeFolder": "Klasör Aboneliğinden çıkılamadı", + "DemoSendMessageError": "Güvenlik amacıyla, bu demo hesabı harici e-posta adreslerine mesaj göndermek için izin verilmez!", + "DemoAccountError": "For security purposes, this account is not allowed for this action!", + "AccountAlreadyExists": "Hesap zaten var", + "AccountDoesNotExist": "Account doesn't exist", + "AccountSwitchFailed": "Switch to account \"%EMAIL%\" failed", + "MailServerError": "Posta sunucusuna erişirken bir hata oluştu", + "InvalidInputArgument": "Invalid input argument", + "UnknownError": "Bilinmeyen Hata" } } diff --git a/snappymail/v/0.0.0/app/localization/uk-UA/user.json b/snappymail/v/0.0.0/app/localization/uk-UA/user.json index b4742ae0d..bf29758f5 100644 --- a/snappymail/v/0.0.0/app/localization/uk-UA/user.json +++ b/snappymail/v/0.0.0/app/localization/uk-UA/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "Закрити повідомлення" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Невірний токен запиту", - "AUTH_ERROR": "Не вдалося авторизуватися", - "CONNECTION_ERROR": "Помилка з'єднання з сервером.", - "DOMAIN_ALREADY_EXISTS": "Домен вже існує", - "DOMAIN_NOT_ALLOWED": "Цей домен заборонений", - "ACCOUNT_NOT_ALLOWED": "Цей акаунт заборонений", - "CONTACTS_SYNC_ERROR": "Помилка синхронізації контактів", - "CANT_GET_MESSAGE_LIST": "Не можу отримати список листів", - "CANT_GET_MESSAGE": "Не можу отримати листа", - "CANT_DELETE_MESSAGE": "Не можу видалити листа", - "CANT_COPY_MESSAGE": "Can't copy message", - "CANT_MOVE_MESSAGE": "Не можу перемістити листа", - "CANT_SAVE_MESSAGE": "Не можу зберегти листа", - "CANT_SEND_MESSAGE": "Не можу відправити листа", - "INVALID_RECIPIENTS": "Перевірити правильність вводу всіх адрес.", - "CANT_SAVE_FILTERS": "Не можу зберегти фільтри", - "CANT_GET_FILTERS": "Can't get filters", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Can't activate filters script", - "CANT_DELETE_FILTERS_SCRIPT": "Can't delete filters script", - "FILTERS_ARE_NOT_CORRECT": "Filters are not correct", - "CANT_CREATE_FOLDER": "Не можу створити теку", - "CANT_RENAME_FOLDER": "Не можу перейменувати теку", - "CANT_DELETE_FOLDER": "Не можу видалити теку", - "CANT_DELETE_NON_EMPTY_FOLDER": "Не можу видалити не порожню теку", - "CANT_SUBSCRIBE_FOLDER": "Не можу підписати теку", - "CANT_UNSUBSCRIBE_FOLDER": "Не можу відписати теку", - "DEMO_SEND_MESSAGE_ERROR": "Демо акаунту надсилання листів на зовнішні поштові адреси заборонена!", - "DEMO_ACCOUNT_ERROR": "For security purposes, this account is not allowed for this action!", - "ACCOUNT_ALREADY_EXISTS": "акаунт вже додано", - "ACCOUNT_DOES_NOT_EXIST": "Account doesn't exist", - "ACCOUNT_SWITCH_FAILED": "Switch to account \"%EMAIL%\" failed", - "MAIL_SERVER_ERROR": "Помилка доступу до поштового серверу", - "INVALID_INPUT_ARGUMENT": "Invalid input argument", - "UNKNOWN_ERROR": "Невідома помилка" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Невірний токен запиту", + "AuthError": "Не вдалося авторизуватися", + "ConnectionError": "Помилка з'єднання з сервером.", + "DomainAlreadyExists": "Домен вже існує", + "DomainNotAllowed": "Цей домен заборонений", + "AccountNotAllowed": "Цей акаунт заборонений", + "ContactsSyncError": "Помилка синхронізації контактів", + "CantGetMessageList": "Не можу отримати список листів", + "CantGetMessage": "Не можу отримати листа", + "CantDeleteMessage": "Не можу видалити листа", + "CantCopyMessage": "Can't copy message", + "CantMoveMessage": "Не можу перемістити листа", + "CantSaveMessage": "Не можу зберегти листа", + "CantSendMessage": "Не можу відправити листа", + "InvalidRecipients": "Перевірити правильність вводу всіх адрес.", + "CantSaveFilters": "Не можу зберегти фільтри", + "CantGetFilters": "Can't get filters", + "CantActivateFiltersScript": "Can't activate filters script", + "CantDeleteFiltersScript": "Can't delete filters script", + "FiltersAreNotCorrect": "Filters are not correct", + "CantCreateFolder": "Не можу створити теку", + "CantRenameFolder": "Не можу перейменувати теку", + "CantDeleteFolder": "Не можу видалити теку", + "CantDeleteNonEmptyFolder": "Не можу видалити не порожню теку", + "CantSubscribeFolder": "Не можу підписати теку", + "CantUnsubscribeFolder": "Не можу відписати теку", + "DemoSendMessageError": "Демо акаунту надсилання листів на зовнішні поштові адреси заборонена!", + "DemoAccountError": "For security purposes, this account is not allowed for this action!", + "AccountAlreadyExists": "акаунт вже додано", + "AccountDoesNotExist": "Account doesn't exist", + "AccountSwitchFailed": "Switch to account \"%EMAIL%\" failed", + "MailServerError": "Помилка доступу до поштового серверу", + "InvalidInputArgument": "Invalid input argument", + "UnknownError": "Невідома помилка" } } diff --git a/snappymail/v/0.0.0/app/localization/vi-VN/admin.json b/snappymail/v/0.0.0/app/localization/vi-VN/admin.json index e8ea1a3b0..5f0dd530b 100644 --- a/snappymail/v/0.0.0/app/localization/vi-VN/admin.json +++ b/snappymail/v/0.0.0/app/localization/vi-VN/admin.json @@ -168,17 +168,17 @@ "UNKNOWN_ERROR": "Lỗi chưa xác định" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Token không hợp lệ", - "AUTH_ERROR": "Xác minh thất bại", - "DOMAIN_ALREADY_EXISTS": "Tên miền đã tồn tại", - "CANT_SAVE_PLUGIN_SETTINGS": "Không thể lưu cài đặt", - "CANT_INSTALL_PACKAGE": "Không thể cài đặt tiện ích mở rộng", - "CANT_DELETE_PACKAGE": "Không thể xóa bỏ tiện ích mở rộng", - "INVALID_PLUGIN_PACKAGE": "Gói tiện ích mở rộng không đúng", - "UNSUPPORTED_PLUGIN_PACKAGE": "Gói tiện ích mở rộng chưa được hỗ trợ", - "UNKNOWN_ERROR": "Lỗi chưa xác định" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Token không hợp lệ", + "AuthError": "Xác minh thất bại", + "DomainAlreadyExists": "Tên miền đã tồn tại", + "CantSavePluginSettings": "Không thể lưu cài đặt", + "CantInstallPackage": "Không thể cài đặt tiện ích mở rộng", + "CantDeletePackage": "Không thể xóa bỏ tiện ích mở rộng", + "InvalidPluginPackage": "Gói tiện ích mở rộng không đúng", + "UnsupportedPluginPackage": "Gói tiện ích mở rộng chưa được hỗ trợ", + "UnknownError": "Lỗi chưa xác định" } } diff --git a/snappymail/v/0.0.0/app/localization/vi-VN/user.json b/snappymail/v/0.0.0/app/localization/vi-VN/user.json index 358270e2d..3c993dfa4 100644 --- a/snappymail/v/0.0.0/app/localization/vi-VN/user.json +++ b/snappymail/v/0.0.0/app/localization/vi-VN/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "Đóng bảng viết thư" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "Request failed", - "REQUEST_ABORTED": "Request is aborted", - "REQUEST_TIMEOUT": "Request timed out", - "INVALID_TOKEN": "Token không hợp lệ", - "AUTH_ERROR": "Xác minh thất bại", - "CONNECTION_ERROR": "Không thể kết nối với máy chủ", - "DOMAIN_ALREADY_EXISTS": "Tên miền đã tồn tại", - "DOMAIN_NOT_ALLOWED": "Tên miền không được cho phép truy cập", - "ACCOUNT_NOT_ALLOWED": "Tài khoản không được cho phép truy cập", - "CONTACTS_SYNC_ERROR": "Lỗi đồng bộ danh bạ", - "CANT_GET_MESSAGE_LIST": "Không thể lấy được danh sách thư", - "CANT_GET_MESSAGE": "Không lấy được thư", - "CANT_DELETE_MESSAGE": "Không thể xóa được thư", - "CANT_COPY_MESSAGE": "Không copy được thư", - "CANT_MOVE_MESSAGE": "Không di chuyển được thư", - "CANT_SAVE_MESSAGE": "Không lưu được thư", - "CANT_SEND_MESSAGE": "Không gửi được thư", - "INVALID_RECIPIENTS": "Người nhận thư không hợp lệ", - "CANT_SAVE_FILTERS": "Không thể lưu những tấm lọc thư", - "CANT_GET_FILTERS": "Không thể lấy về những tấm lọc thư", - "CANT_ACTIVATE_FILTERS_SCRIPT": "Không thể kích hoạt script lọc thư", - "CANT_DELETE_FILTERS_SCRIPT": "Không thể xóa script lọc thư", - "FILTERS_ARE_NOT_CORRECT": "Tấm lọc thư chưa đúng", - "CANT_CREATE_FOLDER": "Không thể tạo thư mục", - "CANT_RENAME_FOLDER": "Không thể đổi tên thư mục", - "CANT_DELETE_FOLDER": "Không thể xóa thư mục", - "CANT_DELETE_NON_EMPTY_FOLDER": "Không thể xóa thư mục đang chứa dữ liệu", - "CANT_SUBSCRIBE_FOLDER": "Không thể theo dõi thư mục", - "CANT_UNSUBSCRIBE_FOLDER": "Không thể bỏ theo dõi thư mục", - "DEMO_SEND_MESSAGE_ERROR": "Vì lý do an ninh, tài khoản này không được phép gửi thư ra cho những địa chỉ email bên ngoài!", - "DEMO_ACCOUNT_ERROR": "Vì lý do an ninh, tài khoản này không được phép thực hiện hành động này!", - "ACCOUNT_ALREADY_EXISTS": "Tài khoản đã tồn tại", - "ACCOUNT_DOES_NOT_EXIST": "Tài khoản không tồn tại", - "ACCOUNT_SWITCH_FAILED": "Không chuyển sang được tài khoản \"%EMAIL%\"", - "MAIL_SERVER_ERROR": "Có lỗi xảy ra khi truy cập vào máy chủ quản lý mail", - "INVALID_INPUT_ARGUMENT": "Thông tin nhập vào không hợp lệ", - "UNKNOWN_ERROR": "Lỗi chưa xác định" + "RequestError": "Request failed", + "RequestAborted": "Request is aborted", + "RequestTimeout": "Request timed out", + "InvalidToken": "Token không hợp lệ", + "AuthError": "Xác minh thất bại", + "ConnectionError": "Không thể kết nối với máy chủ", + "DomainAlreadyExists": "Tên miền đã tồn tại", + "DomainNotAllowed": "Tên miền không được cho phép truy cập", + "AccountNotAllowed": "Tài khoản không được cho phép truy cập", + "ContactsSyncError": "Lỗi đồng bộ danh bạ", + "CantGetMessageList": "Không thể lấy được danh sách thư", + "CantGetMessage": "Không lấy được thư", + "CantDeleteMessage": "Không thể xóa được thư", + "CantCopyMessage": "Không copy được thư", + "CantMoveMessage": "Không di chuyển được thư", + "CantSaveMessage": "Không lưu được thư", + "CantSendMessage": "Không gửi được thư", + "InvalidRecipients": "Người nhận thư không hợp lệ", + "CantSaveFilters": "Không thể lưu những tấm lọc thư", + "CantGetFilters": "Không thể lấy về những tấm lọc thư", + "CantActivateFiltersScript": "Không thể kích hoạt script lọc thư", + "CantDeleteFiltersScript": "Không thể xóa script lọc thư", + "FiltersAreNotCorrect": "Tấm lọc thư chưa đúng", + "CantCreateFolder": "Không thể tạo thư mục", + "CantRenameFolder": "Không thể đổi tên thư mục", + "CantDeleteFolder": "Không thể xóa thư mục", + "CantDeleteNonEmptyFolder": "Không thể xóa thư mục đang chứa dữ liệu", + "CantSubscribeFolder": "Không thể theo dõi thư mục", + "CantUnsubscribeFolder": "Không thể bỏ theo dõi thư mục", + "DemoSendMessageError": "Vì lý do an ninh, tài khoản này không được phép gửi thư ra cho những địa chỉ email bên ngoài!", + "DemoAccountError": "Vì lý do an ninh, tài khoản này không được phép thực hiện hành động này!", + "AccountAlreadyExists": "Tài khoản đã tồn tại", + "AccountDoesNotExist": "Tài khoản không tồn tại", + "AccountSwitchFailed": "Không chuyển sang được tài khoản \"%EMAIL%\"", + "MailServerError": "Có lỗi xảy ra khi truy cập vào máy chủ quản lý mail", + "InvalidInputArgument": "Thông tin nhập vào không hợp lệ", + "UnknownError": "Lỗi chưa xác định" } } diff --git a/snappymail/v/0.0.0/app/localization/zh-CN/admin.json b/snappymail/v/0.0.0/app/localization/zh-CN/admin.json index 280df7686..b9a4f0d03 100644 --- a/snappymail/v/0.0.0/app/localization/zh-CN/admin.json +++ b/snappymail/v/0.0.0/app/localization/zh-CN/admin.json @@ -168,17 +168,17 @@ "UNKNOWN_ERROR": "未知错误" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "请求失败", - "REQUEST_ABORTED": "请求中止", - "REQUEST_TIMEOUT": "请求超时", - "INVALID_TOKEN": "无效标记", - "AUTH_ERROR": "认证失败", - "DOMAIN_ALREADY_EXISTS": "域名已经存在", - "CANT_SAVE_PLUGIN_SETTINGS": "无法保存设置", - "CANT_INSTALL_PACKAGE": "安装插件包失败", - "CANT_DELETE_PACKAGE": "移除插件包失败", - "INVALID_PLUGIN_PACKAGE": "无效插件包", - "UNSUPPORTED_PLUGIN_PACKAGE": "不支持的插件包", - "UNKNOWN_ERROR": "未知错误" + "RequestError": "请求失败", + "RequestAborted": "请求中止", + "RequestTimeout": "请求超时", + "InvalidToken": "无效标记", + "AuthError": "认证失败", + "DomainAlreadyExists": "域名已经存在", + "CantSavePluginSettings": "无法保存设置", + "CantInstallPackage": "安装插件包失败", + "CantDeletePackage": "移除插件包失败", + "InvalidPluginPackage": "无效插件包", + "UnsupportedPluginPackage": "不支持的插件包", + "UnknownError": "未知错误" } } diff --git a/snappymail/v/0.0.0/app/localization/zh-CN/user.json b/snappymail/v/0.0.0/app/localization/zh-CN/user.json index 60edd171f..792aba289 100644 --- a/snappymail/v/0.0.0/app/localization/zh-CN/user.json +++ b/snappymail/v/0.0.0/app/localization/zh-CN/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "退出新邮件" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "请求失败", - "REQUEST_ABORTED": "请求中止", - "REQUEST_TIMEOUT": "请求超时", - "INVALID_TOKEN": "无效标记", - "AUTH_ERROR": "认证失败", - "CONNECTION_ERROR": "无法连接至服务器", - "DOMAIN_ALREADY_EXISTS": "域已经存在", - "DOMAIN_NOT_ALLOWED": "不允许此域名", - "ACCOUNT_NOT_ALLOWED": "不允许此账户", - "CONTACTS_SYNC_ERROR": "联系人同步错误", - "CANT_GET_MESSAGE_LIST": "无法获取邮件列表", - "CANT_GET_MESSAGE": "无法获取邮件", - "CANT_DELETE_MESSAGE": "无法删除邮件", - "CANT_COPY_MESSAGE": "无法复制邮件", - "CANT_MOVE_MESSAGE": "无法移动邮件", - "CANT_SAVE_MESSAGE": "无法保存邮件", - "CANT_SEND_MESSAGE": "无法发送邮件", - "INVALID_RECIPIENTS": "无效接收人", - "CANT_SAVE_FILTERS": "无法保存筛选器规则", - "CANT_GET_FILTERS": "无法获取筛选器规则", - "CANT_ACTIVATE_FILTERS_SCRIPT": "无法激活过滤器脚本", - "CANT_DELETE_FILTERS_SCRIPT": "无法删除过滤器脚本", - "FILTERS_ARE_NOT_CORRECT": "不正确的筛选器规则", - "CANT_CREATE_FOLDER": "无法创建文件夹", - "CANT_RENAME_FOLDER": "无法重命名文件夹", - "CANT_DELETE_FOLDER": "无法删除文件夹", - "CANT_DELETE_NON_EMPTY_FOLDER": "无法删除非空文件夹", - "CANT_SUBSCRIBE_FOLDER": "无法订阅文件夹", - "CANT_UNSUBSCRIBE_FOLDER": "无法取消订阅文件夹", - "DEMO_SEND_MESSAGE_ERROR": "出于安全考虑,测试账号无法发送外部邮件。", - "DEMO_ACCOUNT_ERROR": "出于安全考虑,测试账号无法进行此操作!", - "ACCOUNT_ALREADY_EXISTS": "账户已存在", - "ACCOUNT_DOES_NOT_EXIST": "账户不存在", - "ACCOUNT_SWITCH_FAILED": "切换到账户 \"%EMAIL%\" 失败", - "MAIL_SERVER_ERROR": "访问邮件服务器遇到错误。", - "INVALID_INPUT_ARGUMENT": "无效的参数输入", - "UNKNOWN_ERROR": "未知错误" + "RequestError": "请求失败", + "RequestAborted": "请求中止", + "RequestTimeout": "请求超时", + "InvalidToken": "无效标记", + "AuthError": "认证失败", + "ConnectionError": "无法连接至服务器", + "DomainAlreadyExists": "域已经存在", + "DomainNotAllowed": "不允许此域名", + "AccountNotAllowed": "不允许此账户", + "ContactsSyncError": "联系人同步错误", + "CantGetMessageList": "无法获取邮件列表", + "CantGetMessage": "无法获取邮件", + "CantDeleteMessage": "无法删除邮件", + "CantCopyMessage": "无法复制邮件", + "CantMoveMessage": "无法移动邮件", + "CantSaveMessage": "无法保存邮件", + "CantSendMessage": "无法发送邮件", + "InvalidRecipients": "无效接收人", + "CantSaveFilters": "无法保存筛选器规则", + "CantGetFilters": "无法获取筛选器规则", + "CantActivateFiltersScript": "无法激活过滤器脚本", + "CantDeleteFiltersScript": "无法删除过滤器脚本", + "FiltersAreNotCorrect": "不正确的筛选器规则", + "CantCreateFolder": "无法创建文件夹", + "CantRenameFolder": "无法重命名文件夹", + "CantDeleteFolder": "无法删除文件夹", + "CantDeleteNonEmptyFolder": "无法删除非空文件夹", + "CantSubscribeFolder": "无法订阅文件夹", + "CantUnsubscribeFolder": "无法取消订阅文件夹", + "DemoSendMessageError": "出于安全考虑,测试账号无法发送外部邮件。", + "DemoAccountError": "出于安全考虑,测试账号无法进行此操作!", + "AccountAlreadyExists": "账户已存在", + "AccountDoesNotExist": "账户不存在", + "AccountSwitchFailed": "切换到账户 \"%EMAIL%\" 失败", + "MailServerError": "访问邮件服务器遇到错误。", + "InvalidInputArgument": "无效的参数输入", + "UnknownError": "未知错误" } } diff --git a/snappymail/v/0.0.0/app/localization/zh-TW/user.json b/snappymail/v/0.0.0/app/localization/zh-TW/user.json index 907397303..647ed87ca 100644 --- a/snappymail/v/0.0.0/app/localization/zh-TW/user.json +++ b/snappymail/v/0.0.0/app/localization/zh-TW/user.json @@ -575,42 +575,42 @@ "LABEL_CLOSE_COMPOSE": "關閉撰寫" }, "NOTIFICATIONS": { - "REQUEST_ERROR": "請求失敗", - "REQUEST_ABORTED": "已中止請求", - "REQUEST_TIMEOUT": "請求逾時", - "INVALID_TOKEN": "標記無效", - "AUTH_ERROR": "驗證失敗", - "CONNECTION_ERROR": "無法連線至伺服器", - "DOMAIN_ALREADY_EXISTS": "域名已經存在", - "DOMAIN_NOT_ALLOWED": "不可使用該域名", - "ACCOUNT_NOT_ALLOWED": "不可使用該帳戶", - "CONTACTS_SYNC_ERROR": "連絡人同步錯誤", - "CANT_GET_MESSAGE_LIST": "無法取得郵件清單", - "CANT_GET_MESSAGE": "無法取得郵件", - "CANT_DELETE_MESSAGE": "無法刪除郵件", - "CANT_COPY_MESSAGE": "無法複製郵件", - "CANT_MOVE_MESSAGE": "無法移動郵件", - "CANT_SAVE_MESSAGE": "無法儲存郵件", - "CANT_SEND_MESSAGE": "無法傳送郵件", - "INVALID_RECIPIENTS": "收件人無效", - "CANT_SAVE_FILTERS": "無法儲存篩選器", - "CANT_GET_FILTERS": "無法取得篩選器", - "CANT_ACTIVATE_FILTERS_SCRIPT": "無法啟用篩選器指令檔", - "CANT_DELETE_FILTERS_SCRIPT": "無法刪除篩選器指令檔", - "FILTERS_ARE_NOT_CORRECT": "篩選器不正確", - "CANT_CREATE_FOLDER": "無法新增資料夾", - "CANT_RENAME_FOLDER": "無法重新命名資料夾", - "CANT_DELETE_FOLDER": "無法刪除資料夾", - "CANT_DELETE_NON_EMPTY_FOLDER": "無法刪除非空資料夾", - "CANT_SUBSCRIBE_FOLDER": "無法訂閱資料夾", - "CANT_UNSUBSCRIBE_FOLDER": "無法取消訂閱資料夾", - "DEMO_SEND_MESSAGE_ERROR": "基於安全性考量,此帳戶不允許傳送郵件至外部電子郵件地址。", - "DEMO_ACCOUNT_ERROR": "基於安全性考量,此帳戶不允許執行此操作!", - "ACCOUNT_ALREADY_EXISTS": "帳戶已經存在", - "ACCOUNT_DOES_NOT_EXIST": "帳戶不存在", - "ACCOUNT_SWITCH_FAILED": "切換至「%EMAIL%」帳戶時失敗", - "MAIL_SERVER_ERROR": "存取郵件伺服器時發生錯誤。", - "INVALID_INPUT_ARGUMENT": "輸入引數無效", - "UNKNOWN_ERROR": "未知錯誤" + "RequestError": "請求失敗", + "RequestAborted": "已中止請求", + "RequestTimeout": "請求逾時", + "InvalidToken": "標記無效", + "AuthError": "驗證失敗", + "ConnectionError": "無法連線至伺服器", + "DomainAlreadyExists": "域名已經存在", + "DomainNotAllowed": "不可使用該域名", + "AccountNotAllowed": "不可使用該帳戶", + "ContactsSyncError": "連絡人同步錯誤", + "CantGetMessageList": "無法取得郵件清單", + "CantGetMessage": "無法取得郵件", + "CantDeleteMessage": "無法刪除郵件", + "CantCopyMessage": "無法複製郵件", + "CantMoveMessage": "無法移動郵件", + "CantSaveMessage": "無法儲存郵件", + "CantSendMessage": "無法傳送郵件", + "InvalidRecipients": "收件人無效", + "CantSaveFilters": "無法儲存篩選器", + "CantGetFilters": "無法取得篩選器", + "CantActivateFiltersScript": "無法啟用篩選器指令檔", + "CantDeleteFiltersScript": "無法刪除篩選器指令檔", + "FiltersAreNotCorrect": "篩選器不正確", + "CantCreateFolder": "無法新增資料夾", + "CantRenameFolder": "無法重新命名資料夾", + "CantDeleteFolder": "無法刪除資料夾", + "CantDeleteNonEmptyFolder": "無法刪除非空資料夾", + "CantSubscribeFolder": "無法訂閱資料夾", + "CantUnsubscribeFolder": "無法取消訂閱資料夾", + "DemoSendMessageError": "基於安全性考量,此帳戶不允許傳送郵件至外部電子郵件地址。", + "DemoAccountError": "基於安全性考量,此帳戶不允許執行此操作!", + "AccountAlreadyExists": "帳戶已經存在", + "AccountDoesNotExist": "帳戶不存在", + "AccountSwitchFailed": "切換至「%EMAIL%」帳戶時失敗", + "MailServerError": "存取郵件伺服器時發生錯誤。", + "InvalidInputArgument": "輸入引數無效", + "UnknownError": "未知錯誤" } } From d84f39be865de7017c18e927c56ceaf67fa035b2 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Fri, 1 Mar 2024 01:45:56 +0100 Subject: [PATCH 059/110] Bugfix: SetPassword expects \SnappyMail\SensitiveString --- .../0.0.0/app/libraries/RainLoop/Actions.php | 2 +- .../app/libraries/RainLoop/ActionsAdmin.php | 50 ------------------- 2 files changed, 1 insertion(+), 51 deletions(-) diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php index 72ae3f07c..7d7ee26bc 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php @@ -669,7 +669,7 @@ class Actions $sPassword = \substr(\base64_encode(\random_bytes(16)), 0, 12); Utils::saveFile($passfile, $sPassword . "\n"); // \chmod($passfile, 0600); - $oConfig->SetPassword($sPassword); + $oConfig->SetPassword(new \SnappyMail\SensitiveString($sPassword)); $oConfig->Save(); } } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/ActionsAdmin.php b/snappymail/v/0.0.0/app/libraries/RainLoop/ActionsAdmin.php index 757169491..2180a37e7 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/ActionsAdmin.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/ActionsAdmin.php @@ -365,56 +365,6 @@ class ActionsAdmin extends Actions return $this->DefaultResponse($QR->__toString()); } -/* - public function AdminAppData(array &$aResult): void - { - $oConfig = $this->oConfig; - $aResult['Auth'] = $this->IsAdminLoggined(false); - if ($aResult['Auth']) { - $aResult['adminLogin'] = (string)$oConfig->Get('security', 'admin_login', ''); - $aResult['adminTOTP'] = (string)$oConfig->Get('security', 'admin_totp', ''); - $aResult['pluginsEnable'] = (bool)$oConfig->Get('plugins', 'enable', false); - - $aResult['loginDefaultDomain'] = $oConfig->Get('login', 'default_domain', ''); - $aResult['determineUserLanguage'] = (bool)$oConfig->Get('login', 'determine_user_language', true); - $aResult['determineUserDomain'] = (bool)$oConfig->Get('login', 'determine_user_domain', false); - - $aResult['supportedPdoDrivers'] = \RainLoop\Pdo\Base::getAvailableDrivers(); - - $aResult['contactsEnable'] = (bool)$oConfig->Get('contacts', 'enable', false); - $aResult['contactsSync'] = (bool)$oConfig->Get('contacts', 'allow_sync', false); - $aResult['contactsPdoType'] = Providers\AddressBook\PdoAddressBook::validPdoType($oConfig->Get('contacts', 'type', 'sqlite')); - $aResult['contactsPdoDsn'] = (string)$oConfig->Get('contacts', 'pdo_dsn', ''); - $aResult['contactsPdoType'] = (string)$oConfig->Get('contacts', 'type', ''); - $aResult['contactsPdoUser'] = (string)$oConfig->Get('contacts', 'pdo_user', ''); - $aResult['contactsPdoPassword'] = static::APP_DUMMY; - $aResult['contactsMySQLSSLCA'] = (string) $oConfig->Get('contacts', 'mysql_ssl_ca', ''); - $aResult['contactsMySQLSSLVerify'] = !!$oConfig->Get('contacts', 'mysql_ssl_verify', true); - $aResult['contactsMySQLSSLCiphers'] = (string) $oConfig->Get('contacts', 'mysql_ssl_ciphers', ''); - $aResult['contactsSQLiteGlobal'] = !!$oConfig->Get('contacts', 'sqlite_global', \is_file(APP_PRIVATE_DATA . '/AddressBook.sqlite')); - $aResult['contactsSuggestionsLimit'] = (int)$oConfig->Get('contacts', 'suggestions_limit', 20); - - $aResult['faviconUrl'] = $oConfig->Get('webmail', 'favicon_url', ''); - - $aResult['weakPassword'] = \is_file(APP_PRIVATE_DATA.'admin_password.txt'); - - $aResult['System']['languagesAdmin'] = \SnappyMail\L10n::getLanguages(true); - $aResult['languageAdmin'] = $this->ValidateLanguage($oConfig->Get('webmail', 'language_admin', 'en'), '', true); - $aResult['languageUsers'] = $this->ValidateLanguage($this->detectUserLanguage(true), '', true, true); - } else { - $passfile = APP_PRIVATE_DATA.'admin_password.txt'; - $sPassword = $oConfig->Get('security', 'admin_password', ''); - if (!$sPassword) { - $sPassword = \substr(\base64_encode(\random_bytes(16)), 0, 12); - Utils::saveFile($passfile, $sPassword . "\n"); -// \chmod($passfile, 0600); - $oConfig->SetPassword($sPassword); - $oConfig->Save(); - } - } - } -*/ - private function setAdminAuthToken() : string { $sRand = \MailSo\Base\Utils::Sha1Rand(); From 2efe90fe48f871c059ce693ec90d925b2ab3b3f8 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Fri, 1 Mar 2024 02:08:29 +0100 Subject: [PATCH 060/110] https://github.com/the-djmaze/snappymail/issues/1450#issuecomment-1972147950 --- dev/Model/Identity.js | 6 +++--- dev/View/Popup/Compose.js | 2 +- .../v/0.0.0/app/templates/Views/User/PopupsIdentity.html | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dev/Model/Identity.js b/dev/Model/Identity.js index ac46a15fe..89beda875 100644 --- a/dev/Model/Identity.js +++ b/dev/Model/Identity.js @@ -32,9 +32,9 @@ export class IdentityModel extends AbstractModel { }); addComputablesTo(this, { - smimeKeyEncrypted: () => this.smimeKey().includes('-----BEGIN ENCRYPTED PRIVATE KEY-----') -// smimeKeyValid: () => this.smimeKeyEncrypted() | this.smimeKey().includes('-----BEGIN PRIVATE KEY-----') -// smimeCertificateValid: () => this.smimeKey().includes('-----BEGIN CERTIFICATE-----') + smimeKeyEncrypted: () => this.smimeKey().includes('-----BEGIN ENCRYPTED PRIVATE KEY-----'), + smimeKeyValid: () => /^-----BEGIN (ENCRYPTED )?PRIVATE KEY-----/.test(this.smimeKey()), + smimeCertificateValid: () => /^-----BEGIN CERTIFICATE-----/.test(this.smimeCertificate()) }); } diff --git a/dev/View/Popup/Compose.js b/dev/View/Popup/Compose.js index 2fd0e23bd..4384c5b25 100644 --- a/dev/View/Popup/Compose.js +++ b/dev/View/Popup/Compose.js @@ -1377,7 +1377,7 @@ export class ComposePopupView extends AbstractViewPopup { key && options.push(['OpenPGP', key]); key = GnuPGUserStore.getPrivateKeyFor(email, 1); key && options.push(['GnuPG', key]); - identity.smimeKey() && identity.smimeCertificate() && identity.email() === email + identity.smimeKeyValid() && identity.smimeCertificateValid() && identity.email() === email && options.push(['S/MIME']); console.dir({signOptions: options}); this.signOptions(options); diff --git a/snappymail/v/0.0.0/app/templates/Views/User/PopupsIdentity.html b/snappymail/v/0.0.0/app/templates/Views/User/PopupsIdentity.html index 57c451116..2f7934fdc 100644 --- a/snappymail/v/0.0.0/app/templates/Views/User/PopupsIdentity.html +++ b/snappymail/v/0.0.0/app/templates/Views/User/PopupsIdentity.html @@ -88,11 +88,11 @@ -->
S/MIME -
+
-
+
From c0247ff2bd364fe77138765999713f65d3ac3f18 Mon Sep 17 00:00:00 2001 From: Sergey Mosin Date: Fri, 1 Mar 2024 10:07:14 -0500 Subject: [PATCH 061/110] improve: fire the 'squire2-toolbar' event after more props are added --- plugins/compact-composer/js/CompactComposer.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/compact-composer/js/CompactComposer.js b/plugins/compact-composer/js/CompactComposer.js index 503d00c9e..668151336 100644 --- a/plugins/compact-composer/js/CompactComposer.js +++ b/plugins/compact-composer/js/CompactComposer.js @@ -114,9 +114,6 @@ this.container = container; - toolbar.className = 'squire-toolbar btn-toolbar'; - const actions = this.#makeActions(squire, toolbar); - plain.className = 'squire-plain'; wysiwyg.className = 'squire-wysiwyg'; wysiwyg.dir = 'auto'; @@ -126,6 +123,9 @@ this.wysiwyg = wysiwyg; this.toolbar = toolbar; + toolbar.className = 'squire-toolbar btn-toolbar'; + const actions = this.#makeActions(squire, toolbar); + this.squire.addEventListener('willPaste', pasteSanitizer); this.squire.addEventListener('pasteImage', (e) => { pasteImageHandler(e, squire); From 6169f6083f15d1e1b09d15860ed90df4091dd9e8 Mon Sep 17 00:00:00 2001 From: Sergey Mosin Date: Fri, 1 Mar 2024 10:12:24 -0500 Subject: [PATCH 062/110] improve: add dark theme support and use 'button' element as menu trigger for consistent styling --- plugins/compact-composer/css/composer.css | 1 + .../compact-composer/js/CompactComposer.js | 6 +-- .../templates/PopupsCompose.html | 43 ++----------------- 3 files changed, 7 insertions(+), 43 deletions(-) diff --git a/plugins/compact-composer/css/composer.css b/plugins/compact-composer/css/composer.css index 3b7cb6f55..143a3e1cf 100644 --- a/plugins/compact-composer/css/composer.css +++ b/plugins/compact-composer/css/composer.css @@ -39,6 +39,7 @@ .squire-toolbar-svg-icon { display: block; + fill: var(--dialog-clr, #333); } .squire2-mode-wysiwyg .squire-plain, diff --git a/plugins/compact-composer/js/CompactComposer.js b/plugins/compact-composer/js/CompactComposer.js index 668151336..4a95a6c13 100644 --- a/plugins/compact-composer/js/CompactComposer.js +++ b/plugins/compact-composer/js/CompactComposer.js @@ -663,13 +663,13 @@ return indicators; case 'menu': case 'menu_more': - const menuWrap = document.createElement('div'); + const menuWrap = createElement('div'); menuWrap.className = 'btn-group dropdown squire-toolbar-menu-wrap'; menuWrap.title = item.label; if (!item.showInPlainMode) { menuWrap.className += ' squire-html-mode-item'; } - const menuBtn = document.createElement('a'); + const menuBtn = createElement('button'); menuBtn.className = 'btn dropdown-toggle'; if (item.icon !== '') { menuBtn.innerHTML = item.icon; @@ -680,7 +680,7 @@ } menuWrap.appendChild(menuBtn); - const menu = document.createElement('ul'); + const menu = createElement('ul'); menu.className = 'dropdown-menu squire-toolbar-menu'; if (item.rightEdge) { menu.className += ' right-edge'; diff --git a/plugins/compact-composer/templates/PopupsCompose.html b/plugins/compact-composer/templates/PopupsCompose.html index ad22c4006..7c05c875f 100644 --- a/plugins/compact-composer/templates/PopupsCompose.html +++ b/plugins/compact-composer/templates/PopupsCompose.html @@ -145,10 +145,10 @@
@@ -167,41 +167,6 @@
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -