Merge branch 'master' of github.com:Psychi1/snappymail

This commit is contained in:
uwe 2022-03-21 17:57:29 +01:00
commit 80e816927f
119 changed files with 603 additions and 534 deletions

View file

@ -289,5 +289,5 @@ dev_email = ""
dev_password = "" dev_password = ""
[version] [version]
current = "2.12.0" current = "2.12.2"
saved = "Mon, 23 Aug 2021 07:55:13 +0000" saved = "Mon, 23 Aug 2021 07:55:13 +0000"

View file

@ -140,22 +140,22 @@ RainLoop 1.15 vs SnappyMail
|js/* |RainLoop |Snappy | |js/* |RainLoop |Snappy |
|--------------- |--------: |--------: | |--------------- |--------: |--------: |
|admin.js |2.158.025 | 86.330 | |admin.js |2.158.025 | 86.330 |
|app.js |4.215.733 | 443.039 | |app.js |4.215.733 | 442.968 |
|boot.js | 672.433 | 2.049 | |boot.js | 672.433 | 2.049 |
|libs.js | 647.679 | 206.717 | |libs.js | 647.679 | 206.717 |
|polyfills.js | 325.908 | 0 | |polyfills.js | 325.908 | 0 |
|serviceworker.js | 0 | 285 | |serviceworker.js | 0 | 285 |
|TOTAL |8.019.778 | 738.420 | |TOTAL |8.019.778 | 738.349 |
|js/min/* |RainLoop |Snappy |RL gzip |SM gzip |RL brotli |SM brotli | |js/min/* |RainLoop |Snappy |RL gzip |SM gzip |RL brotli |SM brotli |
|--------------- |--------: |--------: |------: |------: |--------: |--------: | |--------------- |--------: |--------: |------: |------: |--------: |--------: |
|admin.min.js | 255.514 | 43.341 | 73.899 | 13.994 | 60.674 | 12.482 | |admin.min.js | 255.514 | 43.341 | 73.899 | 13.994 | 60.674 | 12.482 |
|app.min.js | 516.000 | 219.474 |140.430 | 68.650 |110.657 | 58.572 | |app.min.js | 516.000 | 219.211 |140.430 | 68.665 |110.657 | 58.612 |
|boot.min.js | 66.456 | 1.278 | 22.553 | 789 | 20.043 | 632 | |boot.min.js | 66.456 | 1.278 | 22.553 | 789 | 20.043 | 632 |
|libs.min.js | 574.626 | 98.988 |177.280 | 36.290 |151.855 | 32.467 | |libs.min.js | 574.626 | 98.988 |177.280 | 36.290 |151.855 | 32.467 |
|polyfills.min.js | 32.608 | 0 | 11.315 | 0 | 10.072 | 0 | |polyfills.min.js | 32.608 | 0 | 11.315 | 0 | 10.072 | 0 |
|TOTAL |1.445.204 | 363.081 |425.477 |119.723 |353.301 |104.153 | |TOTAL |1.445.204 | 362.818 |425.477 |119.738 |353.301 |104.193 |
|TOTAL (no admin) |1.189.690 | 319.740 |351.061 |105.729 |292.627 | 91.671 | |TOTAL (no admin) |1.189.690 | 319.477 |351.061 |105.744 |292.627 | 91.711 |
For a user its around 69% smaller and faster than traditional RainLoop. For a user its around 69% smaller and faster than traditional RainLoop.
@ -183,12 +183,12 @@ For a user its around 69% smaller and faster than traditional RainLoop.
|css/* |RainLoop |Snappy |RL gzip |SM gzip |SM brotli | |css/* |RainLoop |Snappy |RL gzip |SM gzip |SM brotli |
|------------ |-------: |------: |------: |------: |--------: | |------------ |-------: |------: |------: |------: |--------: |
|app.css | 340.334 | 83.066 | 46.959 | 17.023 | 14.627 | |app.css | 340.334 | 82.315 | 46.959 | 16.904 | 14.555 |
|app.min.css | 274.791 | 66.988 | 39.618 | 15.081 | 13.276 | |app.min.css | 274.791 | 66.384 | 39.618 | 14.984 | 13.193 |
|boot.css | | 1.326 | | 664 | 545 | |boot.css | | 1.326 | | 664 | 545 |
|boot.min.css | | 1.071 | | 590 | 474 | |boot.min.css | | 1.071 | | 590 | 474 |
|admin.css | | 30.589 | | 6.914 | 6.003 | |admin.css | | 30.212 | | 6.840 | 5.929 |
|admin.min.css | | 24.590 | | 6.258 | 5.508 | |admin.min.css | | 24.288 | | 6.195 | 5.451 |
### PGP ### PGP
RainLoop uses the old OpenPGP.js v2 RainLoop uses the old OpenPGP.js v2

View file

@ -105,30 +105,34 @@ export const
'id', 'class', 'contenteditable', 'designmode', 'formaction', 'manifest', 'action', 'id', 'class', 'contenteditable', 'designmode', 'formaction', 'manifest', 'action',
'data-bind', 'data-reactid', 'xmlns', 'srcset', 'data-bind', 'data-reactid', 'xmlns', 'srcset',
'fscommand', 'seeksegmenttime' 'fscommand', 'seeksegmenttime'
],
disallowedTags = [
'HEAD','STYLE','SVG','SCRIPT','TITLE','LINK','BASE','META',
'INPUT','OUTPUT','SELECT','BUTTON','TEXTAREA',
'BGSOUND','KEYGEN','SOURCE','OBJECT','EMBED','APPLET','IFRAME','FRAME','FRAMESET','VIDEO','AUDIO','AREA','MAP'
]; ];
tpl.innerHTML = html tpl.innerHTML = html
.replace(/(<pre[^>]*>)([\s\S]*?)(<\/pre>)/gi, aMatches => { .replace(/(<pre[^>]*>)([\s\S]*?)(<\/pre>)/gi, aMatches => {
return (aMatches[1] + aMatches[2].trim() + aMatches[3].trim()).replace(/\r?\n/g, '<br>'); return (aMatches[1] + aMatches[2].trim() + aMatches[3].trim()).replace(/\r?\n/g, '<br>');
}) })
// \MailSo\Base\HtmlUtils::ClearComments()
.replace(/<!--[\s\S]*?-->/g, '')
// \MailSo\Base\HtmlUtils::ClearTags()
// eslint-disable-next-line max-len
.replace(/<\/?(link|form|input|output|select|button|textarea|center|base|meta|bgsound|keygen|source|object|embed|applet|mocha|i?frame|frameset|video|audio|area|map)(\s[\s\S]*?)?>/gi, '')
// GetDomFromText // GetDomFromText
.replace('<o:p></o:p>', '') .replace('<o:p></o:p>', '')
.replace('<o:p>', '<span>') .replace('<o:p>', '<span>')
.replace('</o:p>', '</span>') .replace('</o:p>', '</span>')
// https://github.com/the-djmaze/snappymail/issues/187
// .replace(/<a(?:\s[^>]*)?>((?![\s\S]*<\/a)[\s\S]*?<a(\s[^>]*)?>)/gi, '$1')
// \MailSo\Base\HtmlUtils::ClearFastTags // \MailSo\Base\HtmlUtils::ClearFastTags
.replace(/<p[^>]*><\/p>/i, '')
.replace(/<!doctype[^>]*>/i, '') .replace(/<!doctype[^>]*>/i, '')
.replace(/<\?xml [^>]*\?>/i, '') .replace(/<\?xml [^>]*\?>/i, '')
.trim(); .trim();
html = ''; html = '';
// \MailSo\Base\HtmlUtils::ClearComments()
// https://github.com/the-djmaze/snappymail/issues/187
const nodeIterator = document.createNodeIterator(tpl.content, NodeFilter.SHOW_COMMENT);
while (nodeIterator.nextNode()) {
nodeIterator.referenceNode.remove();
}
tpl.content.querySelectorAll('*').forEach(oElement => { tpl.content.querySelectorAll('*').forEach(oElement => {
const name = oElement.tagName, const name = oElement.tagName,
oStyle = oElement.style, oStyle = oElement.style,
@ -137,7 +141,8 @@ export const
setAttribute = (name, value) => oElement.setAttribute(name, value), setAttribute = (name, value) => oElement.setAttribute(name, value),
delAttribute = name => oElement.removeAttribute(name); delAttribute = name => oElement.removeAttribute(name);
if (['HEAD','STYLE','SVG','SCRIPT','TITLE','INPUT','BUTTON','TEXTAREA','SELECT'].includes(name) // \MailSo\Base\HtmlUtils::ClearTags()
if (disallowedTags.includes(name)
|| 'none' == oStyle.display || 'none' == oStyle.display
|| 'hidden' == oStyle.visibility || 'hidden' == oStyle.visibility
// || (oStyle.lineHeight && 1 > parseFloat(oStyle.lineHeight) // || (oStyle.lineHeight && 1 > parseFloat(oStyle.lineHeight)
@ -148,7 +153,21 @@ export const
oElement.remove(); oElement.remove();
return; return;
} }
// if (['CENTER','FORM'].includes(name)) {
if ('FORM' === name) {
replaceWithChildren(oElement);
return;
}
/*
// Idea to allow CSS
if ('STYLE' === name) {
msgId = '#rl-msg-061eb4d647771be4185943ce91f0039d';
oElement.textContent = oElement.textContent
.replace(/[^{}]+{/g, m => msgId + ' ' + m.replace(',', ', '+msgId+' '))
.replace(/(background-)color:[^};]+/g, '');
return;
}
*/
if ('BODY' === name) { if ('BODY' === name) {
forEachObjectEntry(tasks, (name, cb) => { forEachObjectEntry(tasks, (name, cb) => {
if (hasAttribute(name)) { if (hasAttribute(name)) {
@ -160,18 +179,15 @@ export const
else if ('TABLE' === name && hasAttribute('width')) { else if ('TABLE' === name && hasAttribute('width')) {
value = getAttribute('width'); value = getAttribute('width');
if (!value.includes('%')) {
delAttribute('width'); delAttribute('width');
oStyle.maxWidth = value + (/^[0-9]+$/.test(value) ? 'px' : ''); oStyle.maxWidth = value + 'px';
oStyle.removeProperty('width'); oStyle.width = '100%';
}
} }
else if ('A' === name) { else if ('A' === name) {
value = oElement.href; value = oElement.href;
// https://github.com/the-djmaze/snappymail/issues/187 <a> can't have block element inside
if (!value || oElement.querySelector('td,div,p,li')) {
replaceWithChildren(oElement);
return;
}
value = stripTracking(value); value = stripTracking(value);
if (!/^([a-z]+):/i.test(value) && '//' !== value.slice(0, 2)) { if (!/^([a-z]+):/i.test(value) && '//' !== value.slice(0, 2)) {
setAttribute('data-x-broken-href', value); setAttribute('data-x-broken-href', value);
@ -216,8 +232,8 @@ export const
if (detectHiddenImages if (detectHiddenImages
&& 'IMG' === name && 'IMG' === name
&& (('' != getAttribute('height') && 2 > pInt(getAttribute('height'))) && (('' != getAttribute('height') && 3 > pInt(getAttribute('height')))
|| ('' != getAttribute('width') && 2 > pInt(getAttribute('width'))) || ('' != getAttribute('width') && 3 > pInt(getAttribute('width')))
|| [ || [
'email.microsoftemail.com/open', 'email.microsoftemail.com/open',
'github.com/notifications/beacon/', 'github.com/notifications/beacon/',
@ -320,7 +336,7 @@ export const
setAttribute('data-x-style-broken-urls', JSON.stringify(urls.broken)); setAttribute('data-x-style-broken-urls', JSON.stringify(urls.broken));
} }
if (11 < pInt(oStyle.fontSize)) { if (11 > pInt(oStyle.fontSize)) {
oStyle.removeProperty('font-size'); oStyle.removeProperty('font-size');
} }

View file

@ -1,31 +1,24 @@
<html> <html>
<head> <head>
<meta charset="utf-8"/> <meta charset="utf-8"/>
<meta name="viewport" content="user-scalable=no"/> <title></title>
<title>{{subject}}</title>
<style> <style>
html, body { html, body {
background-color: #fff;
color: #000;
font-size: 13px;
margin: 0; margin: 0;
padding: 0; padding: 0;
} }
header { header {
background: #eee; background: rgba(125,128,128,0.3);
border-bottom: 1px solid #ccc; border-bottom: 1px solid #888;
padding: 0 15px;
} }
header h1 { header h1 {
font-size: 16px; font-size: 120%;
margin: 0;
} }
header * { header * {
font-size: 12px; margin: 5px 0;
padding: 5px 0;
} }
header time { header time {
@ -33,30 +26,21 @@ header time {
} }
blockquote { blockquote {
border-left: 2px solid black; border-left: 2px solid rgba(125,128,128,0.5);
margin: 0; margin: 0;
padding: 0 10px; padding: 0 0 0 10px;
} }
pre, .body-wrp.plain { pre {
white-space: pre-wrap; white-space: pre-wrap;
word-wrap: break-word; word-wrap: break-word;
word-break: normal; word-break: normal;
} }
.body-wrp { body > * {
padding: 15px; padding: 0.5em 1em;
} }
</style> </style>
</head> </head>
<body> <body></body>
<header>
<h1>{{subject}}</h1>
<time>{{date}}</time>
<div>{{fromCreds}}</div>
<div>{{toLabel}}: {{toCreds}}</div>
<div {{ccHide}}>{{ccLabel}}: {{ccCreds}}</div>
</header>
<div class="body-wrp {{bodyClass}}">{{html}}</div>
</body>
</html> </html>

View file

@ -34,6 +34,6 @@ export class IdentityModel extends AbstractModel {
const name = this.name(), const name = this.name(),
email = this.email(); email = this.email();
return name ? name + ' (' + email + ')' : email; return name ? name + ' <' + email + '>' : email;
} }
} }

View file

@ -73,7 +73,6 @@ export class MessageModel extends AbstractModel {
isHtml: false, isHtml: false,
hasImages: false, hasImages: false,
hasExternals: false, hasExternals: false,
hasAttachments: false,
pgpSigned: null, pgpSigned: null,
pgpEncrypted: null, pgpEncrypted: null,
@ -95,6 +94,7 @@ export class MessageModel extends AbstractModel {
attachmentIconClass: () => FileInfo.getAttachmentsIconClass(this.attachments()), attachmentIconClass: () => FileInfo.getAttachmentsIconClass(this.attachments()),
threadsLen: () => this.threads().length, threadsLen: () => this.threads().length,
isImportant: () => MessagePriority.High === this.priority(), isImportant: () => MessagePriority.High === this.priority(),
hasAttachments: () => this.attachments().hasVisible(),
isDeleted: () => this.flags().includes('\\deleted'), isDeleted: () => this.flags().includes('\\deleted'),
isUnseen: () => !this.flags().includes('\\seen') /* || this.flags().includes('\\unseen')*/, isUnseen: () => !this.flags().includes('\\seen') /* || this.flags().includes('\\unseen')*/,
@ -150,7 +150,6 @@ export class MessageModel extends AbstractModel {
this.isHtml(false); this.isHtml(false);
this.hasImages(false); this.hasImages(false);
this.hasExternals(false); this.hasExternals(false);
this.hasAttachments(false);
this.attachments(new AttachmentCollectionModel); this.attachments(new AttachmentCollectionModel);
this.pgpSigned(null); this.pgpSigned(null);
@ -402,7 +401,6 @@ export class MessageModel extends AbstractModel {
oAttachment.isInline(found); oAttachment.isInline(found);
oAttachment.isLinked(found || result.foundContentLocationUrls.includes(oAttachment.contentLocation)); oAttachment.isLinked(found || result.foundContentLocationUrls.includes(oAttachment.contentLocation));
}); });
this.hasAttachments(oAttachments.hasVisible());
body.innerHTML = result.html; body.innerHTML = result.html;
@ -491,21 +489,18 @@ export class MessageModel extends AbstractModel {
ccLine = this.ccToLine(false), ccLine = this.ccToLine(false),
m = 0 < timeStampInUTC ? new Date(timeStampInUTC * 1000) : null, m = 0 < timeStampInUTC ? new Date(timeStampInUTC * 1000) : null,
win = open(''), win = open(''),
doc = win.document; sdoc = win.document;
doc.write(PreviewHTML let subject = encodeHtml(this.subject()),
.replace(/{{subject}}/g, encodeHtml(this.subject())) mode = this.isHtml() ? 'div' : 'pre',
.replace('{{date}}', encodeHtml(m ? m.format('LLL') : '')) cc = ccLine ? `<div>${encodeHtml(i18n('GLOBAL/CC'))}: ${encodeHtml(ccLine)}</div>` : '',
.replace('{{fromCreds}}', encodeHtml(this.fromToLine(false))) style = getComputedStyle(doc.querySelector('.messageView')),
.replace('{{toCreds}}', encodeHtml(this.toToLine(false))) prop = property => style.getPropertyValue(property);
.replace('{{toLabel}}', encodeHtml(i18n('GLOBAL/TO'))) sdoc.write(PreviewHTML
.replace('{{ccHide}}', ccLine ? '' : 'hidden=""') .replace('<title>', '<title>'+subject)
.replace('{{ccCreds}}', encodeHtml(ccLine)) // eslint-disable-next-line max-len
.replace('{{ccLabel}}', encodeHtml(i18n('GLOBAL/CC'))) .replace('<body>', `<body style="background-color:${prop('background-color')};color:${prop('color')}"><header><h1>${subject}</h1><time>${encodeHtml(m ? m.format('LLL') : '')}</time><div>${encodeHtml(this.fromToLine(false))}</div><div>${encodeHtml(i18n('GLOBAL/TO'))}: ${encodeHtml(this.toToLine(false))}</div>${cc}</header><${mode}>${this.bodyAsHTML()}</${mode}>`)
.replace('{{bodyClass}}', this.isHtml() ? 'html' : 'plain')
.replace('{{html}}', this.bodyAsHTML())
); );
sdoc.close();
doc.close();
if (print) { if (print) {
setTimeout(() => win.print(), 100); setTimeout(() => win.print(), 100);
@ -555,7 +550,6 @@ export class MessageModel extends AbstractModel {
this.priority(message.priority()); this.priority(message.priority());
this.hasExternals(message.hasExternals()); this.hasExternals(message.hasExternals());
this.hasAttachments(message.hasAttachments());
this.emails = message.emails; this.emails = message.emails;

View file

@ -12,7 +12,7 @@ html, body {
body { body {
-webkit-touch-callout: none; -webkit-touch-callout: none;
font-size: @baseFontSize;
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;

View file

@ -55,12 +55,12 @@
background-color: rgba(0,0,0,0.8); background-color: rgba(0,0,0,0.8);
.close, .minimize-custom { .close, .minimize-custom {
opacity: 1;
color: #fff;
border-color: #eee; border-color: #eee;
float: none;
font-size: 24px; font-size: 24px;
line-height: 24px; opacity: 1;
line-height: 28px;
margin-left: .7em;
} }
.btn.disabled { .btn.disabled {
@ -76,6 +76,10 @@
.disabled.button-delete { .disabled.button-delete {
margin-left: 0; margin-left: 0;
} }
.pull-right * {
vertical-align: top;
}
} }
.b-header { .b-header {
@ -98,20 +102,13 @@
width: 4em; width: 4em;
} }
.e-identity { #identity-toggle {
color: var(--main-color); color: var(--main-color);
font-weight: bold; margin-left: 6px;
line-height: @baseLineHeight;
padding: 4px 0;
text-decoration: none; text-decoration: none;
&.multiply {
cursor: pointer;
border-bottom: 1px dashed var(--main-color);
}
&.multiply::after {
content: ' ▼';
} }
#identity-toggle::after {
content: '▼';
} }
textarea, input[type="text"] { textarea, input[type="text"] {
@ -170,12 +167,7 @@
border: 0 solid #333; border: 0 solid #333;
border-bottom-width: 3px; border-bottom-width: 3px;
display: inline-block; display: inline-block;
float: right;
height: 20px; height: 20px;
width: 16px; width: 16px;
font-size: 20px;
font-weight: bold;
line-height: 20px;
margin-right: 15px;
cursor: pointer; cursor: pointer;
} }

View file

@ -64,7 +64,6 @@
.listClear { .listClear {
text-align: center; text-align: center;
padding: 10px; padding: 10px;
font-size: 14px;
line-height: 13px; line-height: 13px;
box-shadow: inset 0 -1px 0 #ccc; box-shadow: inset 0 -1px 0 #ccc;
} }

View file

@ -74,7 +74,6 @@
background-color: transparent; background-color: transparent;
vertical-align: middle; vertical-align: middle;
color: var(--folders-disabled-color, #666); color: var(--folders-disabled-color, #666);
font-size: 14px;
border-left: 3px solid transparent; border-left: 3px solid transparent;
padding: 0 2em 0 @folderItemPadding; padding: 0 2em 0 @folderItemPadding;

View file

@ -115,7 +115,6 @@ html.rl-no-preview-pane {
.listClear { .listClear {
text-align: center; text-align: center;
padding: 10px; padding: 10px;
font-size: 14px;
line-height: 13px; line-height: 13px;
} }

View file

@ -332,7 +332,7 @@ html.rl-no-preview-pane {
} }
img { img {
max-width: 100%; max-width: 90vw;
} }
img[data-x-src]:not([src]) { img[data-x-src]:not([src]) {
border: 1px solid #999; border: 1px solid #999;

View file

@ -100,7 +100,6 @@
blockquote p { blockquote p {
margin: 0 0 10px; margin: 0 0 10px;
font-size: 14px;
line-height: 20px; line-height: 20px;
} }

View file

@ -15,11 +15,6 @@ summary.legend {
cursor: pointer; cursor: pointer;
} }
.btn-small.btn-small-small {
font-size: 11px;
line-height: 11px;
}
.btn.btn-thin { .btn.btn-thin {
padding: 4px 9px; padding: 4px 9px;
} }

View file

@ -9,7 +9,6 @@
[class*=" icon-"] { [class*=" icon-"] {
display: inline-block; display: inline-block;
width: 1em; width: 1em;
height: 1em;
vertical-align: text-top; vertical-align: text-top;
.disabled &, .disabled &,

View file

@ -50,6 +50,13 @@ import { ThemeStore } from 'Stores/Theme';
const const
base64_encode = text => btoa(text).match(/.{1,76}/g).join('\r\n'), base64_encode = text => btoa(text).match(/.{1,76}/g).join('\r\n'),
email = new EmailModel(),
getEmail = value => {
email.clear();
email.parse(value.trim());
return email.email || false;
},
/** /**
* @param {string} prefix * @param {string} prefix
* @param {string} subject * @param {string} subject
@ -165,6 +172,7 @@ class ComposePopupView extends AbstractViewPopup {
this.addObservables({ this.addObservables({
identitiesDropdownTrigger: false, identitiesDropdownTrigger: false,
from: '',
to: '', to: '',
cc: '', cc: '',
bcc: '', bcc: '',
@ -214,9 +222,11 @@ class ComposePopupView extends AbstractViewPopup {
editorArea: null, // initDom editorArea: null, // initDom
currentIdentity: IdentityUserStore()[0] || null currentIdentity: IdentityUserStore()[0]
}); });
this.from(IdentityUserStore()[0].formattedName());
// this.to.subscribe((v) => console.log(v)); // this.to.subscribe((v) => console.log(v));
// Used by ko.bindingHandlers.emailsTags // Used by ko.bindingHandlers.emailsTags
@ -289,11 +299,6 @@ class ComposePopupView extends AbstractViewPopup {
optText: item.formattedName() optText: item.formattedName()
})), })),
currentIdentityView: () => {
const item = this.currentIdentity();
return item ? item.formattedName() : 'unknown';
},
canBeSentOrSaved: () => !this.sending() && !this.saving() canBeSentOrSaved: () => !this.sending() && !this.saving()
}); });
@ -304,11 +309,14 @@ class ComposePopupView extends AbstractViewPopup {
sendSuccessButSaveError: value => !value && this.savedErrorDesc(''), sendSuccessButSaveError: value => !value && this.savedErrorDesc(''),
currentIdentity: value => { currentIdentity: value => value && this.from(value.formattedName()),
from: value => {
this.canPgpSign(false); this.canPgpSign(false);
value && PgpUserStore.getKeyForSigning(value.email()).then(result => { value = getEmail(value);
value && PgpUserStore.getKeyForSigning(value).then(result => {
console.log({ console.log({
email: value.email(), email: value,
canPgpSign:result canPgpSign:result
}); });
this.canPgpSign(result) this.canPgpSign(result)
@ -373,6 +381,7 @@ class ComposePopupView extends AbstractViewPopup {
MessageFolder: this.draftsFolder(), MessageFolder: this.draftsFolder(),
MessageUid: this.draftUid(), MessageUid: this.draftUid(),
SaveFolder: sSaveFolder, SaveFolder: sSaveFolder,
From: this.from(),
To: this.to(), To: this.to(),
Cc: this.cc(), Cc: this.cc(),
Bcc: this.bcc(), Bcc: this.bcc(),
@ -730,9 +739,10 @@ class ComposePopupView extends AbstractViewPopup {
} }
selectIdentity(identity) { selectIdentity(identity) {
if (identity && identity.item) { identity = identity && identity.item;
this.currentIdentity(identity.item); if (identity) {
this.setSignatureFromIdentity(identity.item); this.currentIdentity(identity);
this.setSignatureFromIdentity(identity);
} }
} }
@ -1594,18 +1604,14 @@ class ComposePopupView extends AbstractViewPopup {
} }
allRecipients() { allRecipients() {
const email = new EmailModel();
return [ return [
// From/sender is also recipient (Sent mailbox) // From/sender is also recipient (Sent mailbox)
this.currentIdentity().email(), // this.currentIdentity().email(),
this.from(),
this.to(), this.to(),
this.cc(), this.cc(),
this.bcc() this.bcc()
].join(',').split(',').map(value => { ].join(',').split(',').map(value => getEmail(value.trim())).validUnique();
email.clear();
email.parse(value.trim());
return email.email || false;
}).validUnique();
} }
initPgpEncrypt() { initPgpEncrypt() {

View file

@ -1,4 +1,4 @@
This app packages SnappyMail <upstream>2.12.0</upstream>. This app packages SnappyMail <upstream>2.12.2</upstream>.
SnappyMail is a simple, modern, lightweight & fast web-based email client. SnappyMail is a simple, modern, lightweight & fast web-based email client.

View file

@ -4,7 +4,7 @@ RUN mkdir -p /app/code
WORKDIR /app/code WORKDIR /app/code
# If you change the extraction below, be sure to test on scaleway # If you change the extraction below, be sure to test on scaleway
VERSION=2.12.0 VERSION=2.12.2
RUN wget https://github.com/the-djmaze/snappymail/releases/download/v${VERSION}/snappymail-${VERSION}.zip -O /tmp/snappymail.zip && \ 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 && \ unzip /tmp/snappymail.zip -d /app/code && \
rm /tmp/snappymail.zip && \ rm /tmp/snappymail.zip && \

View file

@ -1 +1 @@
2.12.0 2.12.2

View file

@ -4,7 +4,7 @@
<name>SnappyMail</name> <name>SnappyMail</name>
<summary>SnappyMail Webmail</summary> <summary>SnappyMail Webmail</summary>
<description>Simple, modern and fast web-based email client. After enabling in Nextcloud, go to Nextcloud admin panel, "Additionnal settings" and you will see a "SnappyMail webmail" section. There, click on the link to go to the SnappyMail admin panel. The default user/password is admin/12345. This version is based on SnappyMail 2.6.0 (2021-07).</description> <description>Simple, modern and fast web-based email client. After enabling in Nextcloud, go to Nextcloud admin panel, "Additionnal settings" and you will see a "SnappyMail webmail" section. There, click on the link to go to the SnappyMail admin panel. The default user/password is admin/12345. This version is based on SnappyMail 2.6.0 (2021-07).</description>
<version>2.12.0</version> <version>2.12.2</version>
<licence>agpl</licence> <licence>agpl</licence>
<author>SnappyMail Team, Nextgen-Networks, Tab Fitts, Nathan Kinkade, Pierre-Alain Bandinelli</author> <author>SnappyMail Team, Nextgen-Networks, Tab Fitts, Nathan Kinkade, Pierre-Alain Bandinelli</author>
<namespace>SnappyMail</namespace> <namespace>SnappyMail</namespace>

View file

@ -20,7 +20,7 @@ return "SnappyMail Webmail is a browser-based multilingual IMAP client with an a
# script_snappymail_versions() # script_snappymail_versions()
sub script_snappymail_versions sub script_snappymail_versions
{ {
return ( "2.12.0" ); return ( "2.12.2" );
} }
sub script_snappymail_version_desc sub script_snappymail_version_desc

View file

@ -3,7 +3,7 @@
"title": "SnappyMail", "title": "SnappyMail",
"description": "Simple, modern & fast web-based email client", "description": "Simple, modern & fast web-based email client",
"private": true, "private": true,
"version": "2.12.0", "version": "2.12.2",
"homepage": "https://snappymail.eu", "homepage": "https://snappymail.eu",
"author": { "author": {
"name": "DJ Maze", "name": "DJ Maze",

View file

@ -301,6 +301,10 @@ $Plugin->addHook('hook.name', 'functionName');
\RainLoop\Model\Account $oAccount \RainLoop\Model\Account $oAccount
int $iLimit int $iLimit
### main.content-security-policy
params:
\SnappyMail\HTTP\CSP $oCSP
### main.default-response ### main.default-response
params: params:
string $sActionName string $sActionName

View file

@ -6,9 +6,9 @@ class RecaptchaPlugin extends \RainLoop\Plugins\AbstractPlugin
NAME = 'reCaptcha', NAME = 'reCaptcha',
AUTHOR = 'SnappyMail', AUTHOR = 'SnappyMail',
URL = 'https://snappymail.eu/', URL = 'https://snappymail.eu/',
VERSION = '2.12', VERSION = '2.12.1',
RELEASE = '2022-02-11', RELEASE = '2022-02-14',
REQUIRED = '2.12.0', REQUIRED = '2.12.1',
CATEGORY = 'General', CATEGORY = 'General',
LICENSE = 'MIT', LICENSE = 'MIT',
DESCRIPTION = 'A CAPTCHA (v2) is a program that can generate and grade tests that humans can pass but current computer programs cannot. For example, humans can read distorted text as the one shown below, but current computer programs can\'t. More info at https://developers.google.com/recaptcha'; DESCRIPTION = 'A CAPTCHA (v2) is a program that can generate and grade tests that humans can pass but current computer programs cannot. For example, humans can read distorted text as the one shown below, but current computer programs can\'t. More info at https://developers.google.com/recaptcha';
@ -24,6 +24,7 @@ class RecaptchaPlugin extends \RainLoop\Plugins\AbstractPlugin
$this->addHook('json.action-pre-call', 'AjaxActionPreCall'); $this->addHook('json.action-pre-call', 'AjaxActionPreCall');
$this->addHook('filter.json-response', 'FilterAjaxResponse'); $this->addHook('filter.json-response', 'FilterAjaxResponse');
$this->addHook('main.content-security-policy', 'ContentSecurityPolicy');
} }
protected function configMapping() : array protected function configMapping() : array
@ -77,7 +78,7 @@ class RecaptchaPlugin extends \RainLoop\Plugins\AbstractPlugin
public function FilterAppDataPluginSection(bool $bAdmin, bool $bAuth, array &$aConfig) : void public function FilterAppDataPluginSection(bool $bAdmin, bool $bAuth, array &$aConfig) : void
{ {
if (!$bAdmin && !$bAuth) { if (!$bAdmin && !$bAuth) {
$aConfig['show_captcha_on_login'] = 1; $aConfig['show_captcha_on_login'] = 1 > $this->getLimit();;
} }
} }
@ -140,4 +141,13 @@ class RecaptchaPlugin extends \RainLoop\Plugins\AbstractPlugin
} }
} }
} }
public function ContentSecurityPolicy(\SnappyMail\HTTP\CSP $CSP)
{
$CSP->script[] = 'https://www.google.com/recaptcha/';
$CSP->script[] = 'https://www.gstatic.com/recaptcha/';
$CSP->frame[] = 'https://www.google.com/recaptcha/';
$CSP->frame[] = 'https://recaptcha.google.com/recaptcha/';
}
} }

View file

@ -368,7 +368,7 @@ abstract class HtmlUtils
$sResult = static::GetTextFromDom($oDom, false); $sResult = static::GetTextFromDom($oDom, false);
unset($oDom); unset($oDom);
return '<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>'. return '<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head>'.
'<body>'.$sResult.'</body></html>'; '<body>'.$sResult.'</body></html>';
} }
@ -446,12 +446,11 @@ abstract class HtmlUtils
$sText = \preg_replace('/[\n]{3,}/', "\n\n", $sText); $sText = \preg_replace('/[\n]{3,}/', "\n\n", $sText);
$sText = \strtr($sText, array( $sText = \strtr($sText, array(
"\n" => "<br />",
"\t" => "\xC2\xA0\xC2\xA0\xC2\xA0\xC2\xA0", "\t" => "\xC2\xA0\xC2\xA0\xC2\xA0\xC2\xA0",
' ' => "\xC2\xA0\xC2\xA0" ' ' => "\xC2\xA0\xC2\xA0"
)); ));
return $sText; return \nl2br($sText);
} }
public static function ConvertHtmlToPlain(string $sText) : string public static function ConvertHtmlToPlain(string $sText) : string

View file

@ -51,6 +51,14 @@ trait Folders
array($this->EscapeFolderName($sFolderName))); array($this->EscapeFolderName($sFolderName)));
// $this->FolderCheck(); // $this->FolderCheck();
// $this->FolderUnselect(); // $this->FolderUnselect();
// Will this workaround solve Dovecot issue #124 ?
try {
$this->FolderRename($sFolderName, "{$sFolderName}-dummy");
$this->FolderRename("{$sFolderName}-dummy", $sFolderName);
} catch (\Throwable $e) {
}
return $this; return $this;
} }

View file

@ -46,13 +46,13 @@ trait Quota
: null; : null;
} }
// * QUOTA "User quota" (STORAGE 1284645 2097152)\r\n
private function getQuotaResult(\MailSo\Imap\ResponseCollection $oResponseCollection) : array private function getQuotaResult(\MailSo\Imap\ResponseCollection $oResponseCollection) : array
{ {
$aReturn = array(0, 0); $aReturn = array(0, 0);
foreach ($oResponseCollection as $oResponse) { foreach ($oResponseCollection as $oResponse) {
if (Enumerations\ResponseType::UNTAGGED === $oResponse->ResponseType if (Enumerations\ResponseType::UNTAGGED === $oResponse->ResponseType
&& 'QUOTA' === $oResponse->StatusOrIndex && 'QUOTA' === $oResponse->StatusOrIndex
&& \is_array($oResponse->ResponseList)
&& isset($oResponse->ResponseList[3]) && isset($oResponse->ResponseList[3])
&& \is_array($oResponse->ResponseList[3]) && \is_array($oResponse->ResponseList[3])
&& 2 < \count($oResponse->ResponseList[3]) && 2 < \count($oResponse->ResponseList[3])

View file

@ -602,7 +602,7 @@ class Message implements \JsonSerializable
} }
} }
$oMessage->sHtml = \implode('<br />', $aHtmlParts); $oMessage->sHtml = \implode('<br>', $aHtmlParts);
$oMessage->sPlain = \trim(\implode("\n", $aPlainParts)); $oMessage->sPlain = \trim(\implode("\n", $aPlainParts));
$oMessage->bPgpEncrypted = !$oMessage->bPgpEncrypted && false !== \stripos($oMessage->sPlain, '-----BEGIN PGP MESSAGE-----'); $oMessage->bPgpEncrypted = !$oMessage->bPgpEncrypted && false !== \stripos($oMessage->sPlain, '-----BEGIN PGP MESSAGE-----');

View file

@ -848,11 +848,13 @@ class Actions
$aResult['ReplySameFolder'] = (bool)$oSettingsLocal->GetConf('ReplySameFolder', $aResult['ReplySameFolder']); $aResult['ReplySameFolder'] = (bool)$oSettingsLocal->GetConf('ReplySameFolder', $aResult['ReplySameFolder']);
} }
if ($oConfig->Get('login', 'determine_user_language', true)) {
$sLanguage = $this->ValidateLanguage($UserLanguageRaw, $sLanguage, false);
}
if ($oSettings instanceof Settings) { if ($oSettings instanceof Settings) {
if ($oConfig->Get('webmail', 'allow_languages_on_settings', true)) { if ($oConfig->Get('webmail', 'allow_languages_on_settings', true)) {
$sLanguage = (string)$oSettings->GetConf('Language', $sLanguage = (string) $oSettings->GetConf('Language', $sLanguage);
$oConfig->Get('login', 'determine_user_language', true) ? $UserLanguageRaw : $sLanguage
);
} }
$aResult['EditorDefaultType'] = (string)$oSettings->GetConf('EditorDefaultType', $aResult['EditorDefaultType']); $aResult['EditorDefaultType'] = (string)$oSettings->GetConf('EditorDefaultType', $aResult['EditorDefaultType']);

View file

@ -1041,6 +1041,9 @@ trait Messages
$oMessage->DoesNotAddDefaultXMailer(); $oMessage->DoesNotAddDefaultXMailer();
} }
$sFrom = $this->GetActionParam('From', '');
$oMessage->SetFrom(\MailSo\Mime\Email::Parse($sFrom));
/*
$oFromIdentity = $this->GetIdentityByID($oAccount, $this->GetActionParam('IdentityID', '')); $oFromIdentity = $this->GetIdentityByID($oAccount, $this->GetActionParam('IdentityID', ''));
if ($oFromIdentity) if ($oFromIdentity)
{ {
@ -1054,7 +1057,7 @@ trait Messages
{ {
$oMessage->SetFrom(\MailSo\Mime\Email::Parse($oAccount->Email())); $oMessage->SetFrom(\MailSo\Mime\Email::Parse($oAccount->Email()));
} }
*/
$oFrom = $oMessage->GetFrom(); $oFrom = $oMessage->GetFrom();
$oMessage->RegenerateMessageId($oFrom ? $oFrom->GetDomain() : ''); $oMessage->RegenerateMessageId($oFrom ? $oFrom->GetDomain() : '');

View file

@ -28,6 +28,7 @@ trait Pgp
* BSD 4.4 max length = 104 * BSD 4.4 max length = 104
*/ */
if (80 < \strlen($homedir)) { if (80 < \strlen($homedir)) {
\clearstatcache();
// First try a symbolic link // First try a symbolic link
$tmpdir = \sys_get_temp_dir() . '/snappymail'; $tmpdir = \sys_get_temp_dir() . '/snappymail';
// if (\RainLoop\Utils::inOpenBasedir($tmpdir) && // if (\RainLoop\Utils::inOpenBasedir($tmpdir) &&
@ -39,7 +40,7 @@ trait Pgp
} }
// Else try ~/.gnupg/ + hash(email address) // Else try ~/.gnupg/ + hash(email address)
if (80 < \strlen($homedir)) { if (80 < \strlen($homedir)) {
$tmpdir = ($_SERVER['HOME'] ?: \exec('echo ~') ?: \dirname(getcwd())) . '/.gnupg/'; $tmpdir = ($_SERVER['HOME'] ?: \exec('echo ~') ?: \dirname(\getcwd())) . '/.gnupg/';
if ($oAccount instanceof \RainLoop\Model\AdditionalAccount) { if ($oAccount instanceof \RainLoop\Model\AdditionalAccount) {
$tmpdir .= \sha1($oAccount->ParentEmail()); $tmpdir .= \sha1($oAccount->ParentEmail());
} else { } else {
@ -50,6 +51,10 @@ trait Pgp
$homedir = $link; $homedir = $link;
} }
} }
if (104 <= \strlen($homedir . '/S.gpg-agent.extra')) {
throw new \Exception("socket name for '{$homedir}/S.gpg-agent.extra' is too long");
}
} }
return \SnappyMail\PGP\GnuPG::getInstance($homedir); return \SnappyMail\PGP\GnuPG::getInstance($homedir);

View file

@ -99,25 +99,31 @@ trait Themes
$sTheme = \substr($sTheme, 0, -7); $sTheme = \substr($sTheme, 0, -7);
} }
$aResult = array(); $mResult = array();
$sThemeCSSFile = ($bCustomTheme ? APP_INDEX_ROOT_PATH : APP_VERSION_ROOT_PATH).'themes/'.$sTheme.'/styles.css';
$sThemeLessFile = ($bCustomTheme ? APP_INDEX_ROOT_PATH : APP_VERSION_ROOT_PATH).'themes/'.$sTheme.'/styles.less';
$sBase = ($bCustomTheme ? \RainLoop\Utils::WebPath() : \RainLoop\Utils::WebVersionPath()) $sBase = ($bCustomTheme ? \RainLoop\Utils::WebPath() : \RainLoop\Utils::WebVersionPath())
. "themes/{$sTheme}/"; . "themes/{$sTheme}/";
$bLess = false;
$sThemeCSSFile = ($bCustomTheme ? APP_INDEX_ROOT_PATH : APP_VERSION_ROOT_PATH).'themes/'.$sTheme.'/styles.css';
if (\is_file($sThemeCSSFile)) { if (\is_file($sThemeCSSFile)) {
$aResult[] = \preg_replace('@(url\(["\']?)(\\./)?([a-z]+[^:a-z])@', $mResult[] = \file_get_contents($sThemeCSSFile);
"\$1{$sBase}\$3", } else {
\str_replace('@{base}', $sBase, \file_get_contents($sThemeCSSFile))); $sThemeCSSFile = \str_replace('styles.css', 'styles.less', $sThemeCSSFile);
} else if (\is_file($sThemeLessFile)) { if (\is_file($sThemeCSSFile)) {
$aResult[] = "@base: \"{$sBase}\";"; $bLess = true;
$aResult[] = \file_get_contents($sThemeLessFile); $mResult[] = "@base: \"{$sBase}\";";
$mResult[] = \file_get_contents($sThemeCSSFile);
}
} }
$aResult[] = $this->Plugins()->CompileCss($bAdmin); $mResult[] = $this->Plugins()->CompileCss($bAdmin, $bLess);
return (new \LessPHP\lessc())->compile(\implode("\n", $aResult)); $mResult = \preg_replace('@(url\(["\']?)(\\./)?([a-z]+[^:a-z])@',
"\$1{$sBase}\$3",
\str_replace('@{base}', $sBase, \implode("\n", $mResult)));
return $bLess ? (new \LessPHP\lessc())->compile($mResult) : $mResult;
} }
} }

View file

@ -51,7 +51,6 @@ trait User
{ {
$sEmail = \MailSo\Base\Utils::Trim($this->GetActionParam('Email', '')); $sEmail = \MailSo\Base\Utils::Trim($this->GetActionParam('Email', ''));
$sPassword = $this->GetActionParam('Password', ''); $sPassword = $this->GetActionParam('Password', '');
$sLanguage = $this->GetActionParam('Language', '');
$bSignMe = !empty($this->GetActionParam('SignMe', 0)); $bSignMe = !empty($this->GetActionParam('SignMe', 0));
$oAccount = null; $oAccount = null;
@ -63,7 +62,8 @@ trait User
$this->SetAuthToken($oAccount); $this->SetAuthToken($oAccount);
if ($oAccount && \strlen($sLanguage)) $sLanguage = $this->GetActionParam('Language', '');
if ($oAccount && $sLanguage)
{ {
$oSettings = $this->SettingsProvider()->Load($oAccount); $oSettings = $this->SettingsProvider()->Load($oAccount);
if ($oSettings) if ($oSettings)

View file

@ -181,6 +181,7 @@ class Application extends \RainLoop\Config\AbstractConfig
'admin_panel_host' => array(''), 'admin_panel_host' => array(''),
'admin_panel_key' => array('admin'), 'admin_panel_key' => array('admin'),
'content_security_policy' => array(''), 'content_security_policy' => array(''),
'csp_report' => array(false),
'encrypt_cipher' => array($sCipher) 'encrypt_cipher' => array($sCipher)
), ),

View file

@ -167,13 +167,14 @@ class Manager
return $this->bIsEnabled && \count($this->aJs[$bAdminScope ? 1 : 0]); return $this->bIsEnabled && \count($this->aJs[$bAdminScope ? 1 : 0]);
} }
public function CompileCss(bool $bAdminScope = false) : string public function CompileCss(bool $bAdminScope, bool &$bLess) : string
{ {
$aResult = array(); $aResult = array();
if ($this->bIsEnabled) { if ($this->bIsEnabled) {
foreach ($this->aCss[$bAdminScope ? 1 : 0] as $sFile) { foreach ($this->aCss[$bAdminScope ? 1 : 0] as $sFile) {
if (\is_readable($sFile)) { if (\is_readable($sFile)) {
$aResult[] = \file_get_contents($sFile); $aResult[] = \file_get_contents($sFile);
$bLess = $bLess || \str_ends_with($sFile, '.less');
} }
} }
} }

View file

@ -166,8 +166,8 @@ abstract class Service
$sAppleTouchLink = $sFaviconUrl ? '' : $oActions->StaticPath('apple-touch-icon.png'); $sAppleTouchLink = $sFaviconUrl ? '' : $oActions->StaticPath('apple-touch-icon.png');
$aTemplateParameters = array( $aTemplateParameters = array(
'{{BaseAppFaviconPngLinkTag}}' => $sFaviconPngLink ? '<link type="image/png" rel="shortcut icon" href="'.$sFaviconPngLink.'" />' : '', '{{BaseAppFaviconPngLinkTag}}' => $sFaviconPngLink ? '<link type="image/png" rel="shortcut icon" href="'.$sFaviconPngLink.'">' : '',
'{{BaseAppFaviconTouchLinkTag}}' => $sAppleTouchLink ? '<link type="image/png" rel="apple-touch-icon" href="'.$sAppleTouchLink.'" />' : '', '{{BaseAppFaviconTouchLinkTag}}' => $sAppleTouchLink ? '<link type="image/png" rel="apple-touch-icon" href="'.$sAppleTouchLink.'">' : '',
'{{BaseAppMainCssLink}}' => $oActions->StaticPath('css/'.($bAdmin ? 'admin' : 'app').$sAppCssMin.'.css'), '{{BaseAppMainCssLink}}' => $oActions->StaticPath('css/'.($bAdmin ? 'admin' : 'app').$sAppCssMin.'.css'),
'{{BaseAppThemeCssLink}}' => $oActions->ThemeLink($bAdmin), '{{BaseAppThemeCssLink}}' => $oActions->ThemeLink($bAdmin),
'{{BaseAppManifestLink}}' => $oActions->StaticPath('manifest.json'), '{{BaseAppManifestLink}}' => $oActions->StaticPath('manifest.json'),
@ -240,23 +240,22 @@ abstract class Service
private static function setCSP(string $sScriptNonce = null) : void private static function setCSP(string $sScriptNonce = null) : void
{ {
// "img-src https:" is allowed due to remote images in e-mails $CSP = new \SnappyMail\HTTP\CSP(\trim(Api::Config()->Get('security', 'content_security_policy', '')));
$sContentSecurityPolicy = \trim(Api::Config()->Get('security', 'content_security_policy', '')) $CSP->report = Api::Config()->Get('security', 'csp_report', false);
?: "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; img-src 'self' data: https: http:; style-src 'self' 'unsafe-inline'"; $CSP->report_only = Api::Config()->Get('debug', 'enable', false); // '0.0.0' === APP_VERSION
if (Api::Config()->Get('security', 'use_local_proxy_for_external_images', '')) {
$sContentSecurityPolicy = \preg_replace('/(img-src[^;]+)\\shttps:(\\s|;|$)/D', '$1$2', $sContentSecurityPolicy); // Allow https: due to remote images in e-mails or use proxy
$sContentSecurityPolicy = \preg_replace('/(img-src[^;]+)\\shttp:(\\s|;|$)/D', '$1$2', $sContentSecurityPolicy); if (!Api::Config()->Get('security', 'use_local_proxy_for_external_images', '')) {
$CSP->img[] = 'https:';
$CSP->img[] = 'http:';
} }
// Internet Explorer does not support 'nonce' // Internet Explorer does not support 'nonce'
if (!$_SERVER['HTTP_USER_AGENT'] || (!\strpos($_SERVER['HTTP_USER_AGENT'], 'Trident/') && !\strpos($_SERVER['HTTP_USER_AGENT'], 'Edge/1'))) { if ($sScriptNonce && !$_SERVER['HTTP_USER_AGENT'] || (!\strpos($_SERVER['HTTP_USER_AGENT'], 'Trident/') && !\strpos($_SERVER['HTTP_USER_AGENT'], 'Edge/1'))) {
if ($sScriptNonce) { $CSP->script[] = "'nonce-{$sScriptNonce}'";
$sContentSecurityPolicy = \str_replace('script-src', "script-src 'nonce-{$sScriptNonce}'", $sContentSecurityPolicy);
} }
// Knockout.js requires unsafe-inline?
$sContentSecurityPolicy = \preg_replace("/(script-src[^;]+)'unsafe-inline'/", '$1', $sContentSecurityPolicy); Api::Actions()->Plugins()->RunHook('main.content-security-policy', array($CSP));
// Knockout.js requires eval() for observable binding purposes
//$sContentSecurityPolicy = \preg_replace("/(script-src[^;]+)'unsafe-eval'/", '$1', $sContentSecurityPolicy); $CSP->setHeaders();
}
\header('Content-Security-Policy: '.$sContentSecurityPolicy);
} }
} }

View file

@ -351,15 +351,17 @@ class ServiceActions
\header('X-Content-Location: '.$aData['Url']); \header('X-Content-Location: '.$aData['Url']);
$tmp = \tmpfile(); $tmp = \tmpfile();
$HTTP = \SnappyMail\HTTP\Request::factory(); $HTTP = \SnappyMail\HTTP\Request::factory();
$HTTP->max_redirects = 2;
$HTTP->streamBodyTo($tmp); $HTTP->streamBodyTo($tmp);
$oResponse = $HTTP->doRequest('GET', $aData['Url']); $oResponse = $HTTP->doRequest('GET', $aData['Url']);
if ($oResponse && 200 === $oResponse->status if ($oResponse && 200 === $oResponse->status
&& \str_starts_with($oResponse->getHeader('content-type'), 'image/') && \str_starts_with($oResponse->getHeader('content-type'), 'image/')
) { ) {
$this->oActions->cacheByKey($sData); $this->oActions->cacheByKey($sData);
\header('Content-Type: '.$sContentType); \header('Content-Type: ' . $oResponse->getHeader('content-type'));
\header('Cache-Control: public'); \header('Cache-Control: public');
\header('Expires: '.\gmdate('D, j M Y H:i:s', 2592000 + \time()).' UTC'); \header('Expires: '.\gmdate('D, j M Y H:i:s', 2592000 + \time()).' UTC');
\header('X-Content-Redirect-Location: '.$oResponse->final_uri);
\rewind($tmp); \rewind($tmp);
\fpassthru($tmp); \fpassthru($tmp);
exit; exit;
@ -371,6 +373,11 @@ class ServiceActions
return ''; return '';
} }
public function ServiceCspReport() : void
{
\SnappyMail\HTTP\CSP::logReport();
}
public function ServiceRaw() : string public function ServiceRaw() : string
{ {
$sResult = ''; $sResult = '';

View file

@ -227,7 +227,7 @@ class Utils
return true; return true;
} }
} }
\SnappyMail\Log::warning("open_basedir restriction in effect. {$name} is not within the allowed path(s): " . \ini_get('open_basedir')); \SnappyMail\Log::warning('OpenBasedir', "open_basedir restriction in effect. {$name} is not within the allowed path(s): " . \ini_get('open_basedir'));
return false; return false;
} }
return true; return true;

View file

@ -0,0 +1,80 @@
<?php
/**
* Controls the content_security_policy
*/
namespace SnappyMail\HTTP;
class CSP
{
public
$default = ["'self'"],
// Knockout.js requires unsafe-inline?
// Knockout.js requires eval() for observable binding purposes
$script = ["'self'", "'unsafe-eval'"/*, "'unsafe-inline'"*/],
$img = ["'self'", 'data:'],
$style = ["'self'", "'unsafe-inline'"],
$frame = [],
$report = false,
$report_to = [],
$report_only = false;
function __construct(string $default = '')
{
if ($default) {
foreach (\explode(';', $default) as $directive) {
$values = \explode(' ', $directive);
$name = \preg_replace('/-.+/', '', \trim(\array_shift($values)));
$this->$name = $values;
}
}
}
function __toString() : string
{
$params = [
'default-src ' . \implode(' ', $this->default)
];
if ($this->script) {
$params[] = 'script-src ' . \implode(' ', $this->script);
}
if ($this->img) {
$params[] = 'img-src ' . \implode(' ', $this->img);
}
if ($this->style) {
$params[] = 'style-src ' . \implode(' ', $this->style);
}
if ($this->frame) {
$params[] = 'frame-src ' . \implode(' ', $this->frame);
}
// Deprecated
if ($this->report) {
$params[] = 'report-uri ./?/CspReport';
}
return \implode('; ', $params);
}
public function setHeaders() : void
{
if ($this->report_only) {
\header('Content-Security-Policy-Report-Only: ' . $this);
} else {
\header('Content-Security-Policy: ' . $this);
}
}
public static function logReport() : void
{
\http_response_code(204);
$json = \file_get_contents('php://input');
$report = \json_decode($json, true);
// Useless to log 'moz-extension' as there's no clue which extension violates
if ($json && $report && 'moz-extension' !== $report['csp-report']['source-file']) {
\SnappyMail\Log::error('CSP', $json);
}
exit;
}
}

View file

@ -129,6 +129,7 @@ abstract class Request
throw new \RuntimeException("Fetching URL not allowed: {$url}"); throw new \RuntimeException("Fetching URL not allowed: {$url}");
} }
$this->stream && \rewind($this->stream);
$result = $this->__doRequest($method, $url, $body, \array_merge($this->headers, $extra_headers)); $result = $this->__doRequest($method, $url, $body, \array_merge($this->headers, $extra_headers));
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3 // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3

View file

@ -157,6 +157,7 @@ class Socket extends \SnappyMail\HTTP\Request
"\r\n" === \fread($sock, 2); "\r\n" === \fread($sock, 2);
} else { } else {
\fwrite($this->stream, \fread($sock, 1024)); \fwrite($this->stream, \fread($sock, 1024));
// \stream_copy_to_stream($sock, $this->stream);
} }
} }
} else { } else {

View file

@ -67,6 +67,11 @@ class Response
return null; return null;
} }
public function getHeaders() : array
{
return $this->headers;
}
public function getRedirectLocation() : ?string public function getRedirectLocation() : ?string
{ {
if ($location = $this->getHeader('location')) { if ($location = $this->getHeader('location')) {

View file

@ -81,17 +81,7 @@ class GPG
function __construct(string $homedir) function __construct(string $homedir)
{ {
$homedir = \rtrim($homedir, '/\\'); $this->options['homedir'] = \rtrim($homedir, '/\\');
// BSD 4.4 max length
if (104 <= \strlen($homedir . '/S.gpg-agent.extra')) {
throw new \Exception("socket name for '{$homedir}/S.gpg-agent.extra' is too long");
}
if ($homedir && !\is_dir($homedir) && !\mkdir($homedir, 0700, true)) {
throw new \Exception("mkdir({$homedir}) failed");
}
$this->options['homedir'] = $homedir;
// the random seed file makes subsequent actions faster so only disable it if we have to. // the random seed file makes subsequent actions faster so only disable it if we have to.
if ($this->options['homedir'] && !\is_writeable($this->options['homedir'])) { if ($this->options['homedir'] && !\is_writeable($this->options['homedir'])) {

View file

@ -38,7 +38,7 @@
"LABEL_ALLOW_IDENTITIES": "Povolit další identity", "LABEL_ALLOW_IDENTITIES": "Povolit další identity",
"ALERT_DATA_ACCESS": "Adresář s RainLoop daty je veřejně přístupný. Nakonfigurujte prosím webový server tak, aby skryl adresář data z externího přístupu. Více zde:", "ALERT_DATA_ACCESS": "Adresář s RainLoop daty je veřejně přístupný. Nakonfigurujte prosím webový server tak, aby skryl adresář data z externího přístupu. Více zde:",
"ALERT_WARNING": "Upozornění!", "ALERT_WARNING": "Upozornění!",
"HTML_ALERT_WEAK_PASSWORD": "Používáte výchozí administrátorské heslo.\n<br \/>\nZ bezpečnostních důvodů jej prosím\n<strong><a href=\"#\/security\">změňte<\/a><\/strong>.\n" "HTML_ALERT_WEAK_PASSWORD": "Používáte výchozí administrátorské heslo.\n<br>\nZ bezpečnostních důvodů jej prosím\n<strong><a href=\"#\/security\">změňte<\/a><\/strong>.\n"
}, },
"TAB_LOGIN": { "TAB_LOGIN": {
"LEGEND_LOGIN_SCREEN": "Přihlašovací obrazovka", "LEGEND_LOGIN_SCREEN": "Přihlašovací obrazovka",
@ -66,14 +66,14 @@
"BUTTON_TEST": "Test", "BUTTON_TEST": "Test",
"ALERT_NOTICE": "Upozornění!", "ALERT_NOTICE": "Upozornění!",
"HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "Nepoužívejte tento typ databáze při velkém počtu aktivních uživatelů.", "HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "Nepoužívejte tento typ databáze při velkém počtu aktivních uživatelů.",
"HTML_ALERT_DOES_NOT_SUPPORTED": "Váš systém nepodporuje kontakty.\n<br \/>\nJe potřeba nainstalovat nebo povolit <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong>\nrozšíření na vašem serveru.\n" "HTML_ALERT_DOES_NOT_SUPPORTED": "Váš systém nepodporuje kontakty.\n<br>\nJe potřeba nainstalovat nebo povolit <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong>\nrozšíření na vašem serveru.\n"
}, },
"TAB_DOMAINS": { "TAB_DOMAINS": {
"LEGEND_DOMAINS": "Domény", "LEGEND_DOMAINS": "Domény",
"BUTTON_ADD_DOMAIN": "Přidat Doménu", "BUTTON_ADD_DOMAIN": "Přidat Doménu",
"BUTTON_ADD_ALIAS": "Přidat alias", "BUTTON_ADD_ALIAS": "Přidat alias",
"DELETE_ARE_YOU_SURE": "Jste si jistí?", "DELETE_ARE_YOU_SURE": "Jste si jistí?",
"HTML_DOMAINS_HELPER": "Seznam domén, ke kterým je možné přistupovat přes webmail.\n<br \/>\nKlikněte na jméno domény pro její konfiguraci.\n" "HTML_DOMAINS_HELPER": "Seznam domén, ke kterým je možné přistupovat přes webmail.\n<br>\nKlikněte na jméno domény pro její konfiguraci.\n"
}, },
"TAB_SECURITY": { "TAB_SECURITY": {
"LEGEND_SECURITY": "Zabezpečení", "LEGEND_SECURITY": "Zabezpečení",

View file

@ -38,7 +38,7 @@
"LABEL_ALLOW_IDENTITIES": "Tillad flere identiteter", "LABEL_ALLOW_IDENTITIES": "Tillad flere identiteter",
"ALERT_DATA_ACCESS": "Data folder is accessible. Please configure your web server to hide the data folder from external access. Read more here:", "ALERT_DATA_ACCESS": "Data folder is accessible. Please configure your web server to hide the data folder from external access. Read more here:",
"ALERT_WARNING": "Advarsler!", "ALERT_WARNING": "Advarsler!",
"HTML_ALERT_WEAK_PASSWORD": "Du bruger standard admin adgangskoden.\n<br \/>\nAf sikkerhedsmæssige hensyn bør du venligst\n<strong><a href=\"#\/security\">ændre<\/a><\/strong>\nadgangskoden til noget andet snarest.\n" "HTML_ALERT_WEAK_PASSWORD": "Du bruger standard admin adgangskoden.\n<br>\nAf sikkerhedsmæssige hensyn bør du venligst\n<strong><a href=\"#\/security\">ændre<\/a><\/strong>\nadgangskoden til noget andet snarest.\n"
}, },
"TAB_LOGIN": { "TAB_LOGIN": {
"LEGEND_LOGIN_SCREEN": "Log ind skærm", "LEGEND_LOGIN_SCREEN": "Log ind skærm",
@ -66,14 +66,14 @@
"BUTTON_TEST": "Test", "BUTTON_TEST": "Test",
"ALERT_NOTICE": "Underretning!", "ALERT_NOTICE": "Underretning!",
"HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "Brug ikke denne database type med større antal af aktive brugere.", "HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "Brug ikke denne database type med større antal af aktive brugere.",
"HTML_ALERT_DOES_NOT_SUPPORTED": "Dit system ser ikke ud til at understøtte kontakter.\n<br \/>\nDu skal installere og aktivere <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong> udvidelsen på din server.\n" "HTML_ALERT_DOES_NOT_SUPPORTED": "Dit system ser ikke ud til at understøtte kontakter.\n<br>\nDu skal installere og aktivere <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong> udvidelsen på din server.\n"
}, },
"TAB_DOMAINS": { "TAB_DOMAINS": {
"LEGEND_DOMAINS": "Domæner", "LEGEND_DOMAINS": "Domæner",
"BUTTON_ADD_DOMAIN": "Tilføj domæne", "BUTTON_ADD_DOMAIN": "Tilføj domæne",
"BUTTON_ADD_ALIAS": "Tilføj alias", "BUTTON_ADD_ALIAS": "Tilføj alias",
"DELETE_ARE_YOU_SURE": "Er du sikker?", "DELETE_ARE_YOU_SURE": "Er du sikker?",
"HTML_DOMAINS_HELPER": "Liste over domæner webmail er tilladt adgang til.\n<br \/>\nKlik på navnet for at konfigurere domænet.\n" "HTML_DOMAINS_HELPER": "Liste over domæner webmail er tilladt adgang til.\n<br>\nKlik på navnet for at konfigurere domænet.\n"
}, },
"TAB_SECURITY": { "TAB_SECURITY": {
"LEGEND_SECURITY": "Sikkerhed", "LEGEND_SECURITY": "Sikkerhed",

View file

@ -38,7 +38,7 @@
"LABEL_ALLOW_IDENTITIES": "Mehrere Identitäten erlauben", "LABEL_ALLOW_IDENTITIES": "Mehrere Identitäten erlauben",
"ALERT_DATA_ACCESS": "Data folder is accessible. Please configure your web server to hide the data folder from external access. Read more here:", "ALERT_DATA_ACCESS": "Data folder is accessible. Please configure your web server to hide the data folder from external access. Read more here:",
"ALERT_WARNING": "Warnung!", "ALERT_WARNING": "Warnung!",
"HTML_ALERT_WEAK_PASSWORD": "Sie verwenden das Standard-Admin-Passwort.\n<br \/>\nBitte <strong><a href=\"#\/security\">ändern<\/a><\/strong> Sie\naus Sicherheitsgründen das Passwort jetzt.\n" "HTML_ALERT_WEAK_PASSWORD": "Sie verwenden das Standard-Admin-Passwort.\n<br>\nBitte <strong><a href=\"#\/security\">ändern<\/a><\/strong> Sie\naus Sicherheitsgründen das Passwort jetzt.\n"
}, },
"TAB_LOGIN": { "TAB_LOGIN": {
"LEGEND_LOGIN_SCREEN": "Anmeldebildschirm", "LEGEND_LOGIN_SCREEN": "Anmeldebildschirm",
@ -66,14 +66,14 @@
"BUTTON_TEST": "Testen", "BUTTON_TEST": "Testen",
"ALERT_NOTICE": "Hinweis!", "ALERT_NOTICE": "Hinweis!",
"HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "Verwenden Sie diesen Datenbanktyp nicht bei einer hohen Anzahl aktiver Benutzer.", "HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "Verwenden Sie diesen Datenbanktyp nicht bei einer hohen Anzahl aktiver Benutzer.",
"HTML_ALERT_DOES_NOT_SUPPORTED": "Ihr System unterstützt keine Kontakte.\n<br \/>\nSie müssen die <strong>PDO-Erweiterung (SQLite \/ MySQL \/ PostgreSQL)<\/strong> auf Ihrem Server installieren oder aktivieren.\n" "HTML_ALERT_DOES_NOT_SUPPORTED": "Ihr System unterstützt keine Kontakte.\n<br>\nSie müssen die <strong>PDO-Erweiterung (SQLite \/ MySQL \/ PostgreSQL)<\/strong> auf Ihrem Server installieren oder aktivieren.\n"
}, },
"TAB_DOMAINS": { "TAB_DOMAINS": {
"LEGEND_DOMAINS": "Domains", "LEGEND_DOMAINS": "Domains",
"BUTTON_ADD_DOMAIN": "Domain hinzufügen", "BUTTON_ADD_DOMAIN": "Domain hinzufügen",
"BUTTON_ADD_ALIAS": "Alias hinzufügen", "BUTTON_ADD_ALIAS": "Alias hinzufügen",
"DELETE_ARE_YOU_SURE": "Sind Sie sicher?", "DELETE_ARE_YOU_SURE": "Sind Sie sicher?",
"HTML_DOMAINS_HELPER": "Liste der Domains, die Webmail abrufen darf.\n<br \/>\nKlicken Sie auf den Namen, um die Domain zu konfigurieren.\n" "HTML_DOMAINS_HELPER": "Liste der Domains, die Webmail abrufen darf.\n<br>\nKlicken Sie auf den Namen, um die Domain zu konfigurieren.\n"
}, },
"TAB_SECURITY": { "TAB_SECURITY": {
"LEGEND_SECURITY": "Sicherheit", "LEGEND_SECURITY": "Sicherheit",
@ -138,7 +138,7 @@
"BUTTON_CLOSE": "Schließen", "BUTTON_CLOSE": "Schließen",
"BUTTON_ADD": "Hinzufügen", "BUTTON_ADD": "Hinzufügen",
"BUTTON_UPDATE": "Aktualisieren", "BUTTON_UPDATE": "Aktualisieren",
"NEW_DOMAIN_DESC": "Diese Domain Konfiguration wird es dir möglich machen <br \/>mit <i>%NAME%<\/i> Mailadressen zu arbeiten.", "NEW_DOMAIN_DESC": "Diese Domain Konfiguration wird es dir möglich machen <br>mit <i>%NAME%<\/i> Mailadressen zu arbeiten.",
"WHITE_LIST_ALERT": "Liste der User, die Webmail abrufen darf.\nVerwenden Sie Leerzeichen als Trenner.\n" "WHITE_LIST_ALERT": "Liste der User, die Webmail abrufen darf.\nVerwenden Sie Leerzeichen als Trenner.\n"
}, },
"POPUPS_PLUGIN": { "POPUPS_PLUGIN": {

View file

@ -38,7 +38,7 @@
"LABEL_ALLOW_IDENTITIES": "Allow multiple identities", "LABEL_ALLOW_IDENTITIES": "Allow multiple identities",
"ALERT_DATA_ACCESS": "Data folder is accessible. Please configure your web server to hide the data folder from external access. Read more here:", "ALERT_DATA_ACCESS": "Data folder is accessible. Please configure your web server to hide the data folder from external access. Read more here:",
"ALERT_WARNING": "Warning!", "ALERT_WARNING": "Warning!",
"HTML_ALERT_WEAK_PASSWORD": "You are using the default admin password.\n<br \/>\nFor security reasons please\n<strong><a href=\"#\/security\">change<\/a><\/strong>\npassword to something else now.\n" "HTML_ALERT_WEAK_PASSWORD": "You are using the default admin password.\n<br>\nFor security reasons please\n<strong><a href=\"#\/security\">change<\/a><\/strong>\npassword to something else now.\n"
}, },
"TAB_LOGIN": { "TAB_LOGIN": {
"LEGEND_LOGIN_SCREEN": "Login Screen", "LEGEND_LOGIN_SCREEN": "Login Screen",
@ -66,14 +66,14 @@
"BUTTON_TEST": "Test", "BUTTON_TEST": "Test",
"ALERT_NOTICE": "Notice!", "ALERT_NOTICE": "Notice!",
"HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "Don't use this database type with a large number of active users.", "HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "Don't use this database type with a large number of active users.",
"HTML_ALERT_DOES_NOT_SUPPORTED": "Your system doesn't support contacts.\n<br \/>\nYou need to install or enable <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong> extension on your server.\n" "HTML_ALERT_DOES_NOT_SUPPORTED": "Your system doesn't support contacts.\n<br>\nYou need to install or enable <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong> extension on your server.\n"
}, },
"TAB_DOMAINS": { "TAB_DOMAINS": {
"LEGEND_DOMAINS": "Domains", "LEGEND_DOMAINS": "Domains",
"BUTTON_ADD_DOMAIN": "Add Domain", "BUTTON_ADD_DOMAIN": "Add Domain",
"BUTTON_ADD_ALIAS": "Add Alias", "BUTTON_ADD_ALIAS": "Add Alias",
"DELETE_ARE_YOU_SURE": "Are you sure?", "DELETE_ARE_YOU_SURE": "Are you sure?",
"HTML_DOMAINS_HELPER": "List of domains webmail is allowed to access.\n<br \/>\nClick on the name to configure the domain.\n" "HTML_DOMAINS_HELPER": "List of domains webmail is allowed to access.\n<br>\nClick on the name to configure the domain.\n"
}, },
"TAB_SECURITY": { "TAB_SECURITY": {
"LEGEND_SECURITY": "Security", "LEGEND_SECURITY": "Security",
@ -138,7 +138,7 @@
"BUTTON_CLOSE": "Close", "BUTTON_CLOSE": "Close",
"BUTTON_ADD": "Add", "BUTTON_ADD": "Add",
"BUTTON_UPDATE": "Update", "BUTTON_UPDATE": "Update",
"NEW_DOMAIN_DESC": "This domain configuration will allow you to work <br \/>with <i>%NAME%<\/i> email addresses.", "NEW_DOMAIN_DESC": "This domain configuration will allow you to work <br>with <i>%NAME%<\/i> email addresses.",
"WHITE_LIST_ALERT": "List of domain users webmail is allowed to access.\nUse a space as delimiter.\n" "WHITE_LIST_ALERT": "List of domain users webmail is allowed to access.\nUse a space as delimiter.\n"
}, },
"POPUPS_PLUGIN": { "POPUPS_PLUGIN": {

View file

@ -38,7 +38,7 @@
"LABEL_ALLOW_IDENTITIES": "Permitir múltiples identidades", "LABEL_ALLOW_IDENTITIES": "Permitir múltiples identidades",
"ALERT_DATA_ACCESS": "Data folder is accessible. Please configure your web server to hide the data folder from external access. Read more here:", "ALERT_DATA_ACCESS": "Data folder is accessible. Please configure your web server to hide the data folder from external access. Read more here:",
"ALERT_WARNING": "¡Atención!", "ALERT_WARNING": "¡Atención!",
"HTML_ALERT_WEAK_PASSWORD": "Estas utilizando la contraseña por defecto.\n<br \/>\nDebido a razones de seguridad, debes\n<strong><a href=\"#\/security\">cambiar<\/a><\/strong>\ntu contraseña inmediatamente.\n" "HTML_ALERT_WEAK_PASSWORD": "Estas utilizando la contraseña por defecto.\n<br>\nDebido a razones de seguridad, debes\n<strong><a href=\"#\/security\">cambiar<\/a><\/strong>\ntu contraseña inmediatamente.\n"
}, },
"TAB_LOGIN": { "TAB_LOGIN": {
"LEGEND_LOGIN_SCREEN": "Pantalla de Ingreso", "LEGEND_LOGIN_SCREEN": "Pantalla de Ingreso",
@ -66,14 +66,14 @@
"BUTTON_TEST": "Probar", "BUTTON_TEST": "Probar",
"ALERT_NOTICE": "¡Advertencia!", "ALERT_NOTICE": "¡Advertencia!",
"HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "No utilices este tipo de Base de Datos para un número grande de usuarios.", "HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "No utilices este tipo de Base de Datos para un número grande de usuarios.",
"HTML_ALERT_DOES_NOT_SUPPORTED": "Tu sistema no soporta el uso de Contactos.\n<br \/>\nDebes instalar o habilitar el uso de <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong> en tu servidor.\n" "HTML_ALERT_DOES_NOT_SUPPORTED": "Tu sistema no soporta el uso de Contactos.\n<br>\nDebes instalar o habilitar el uso de <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong> en tu servidor.\n"
}, },
"TAB_DOMAINS": { "TAB_DOMAINS": {
"LEGEND_DOMAINS": "Dominios", "LEGEND_DOMAINS": "Dominios",
"BUTTON_ADD_DOMAIN": "Agregar dominio", "BUTTON_ADD_DOMAIN": "Agregar dominio",
"BUTTON_ADD_ALIAS": "Agregar alias", "BUTTON_ADD_ALIAS": "Agregar alias",
"DELETE_ARE_YOU_SURE": "¿Estás seguro?", "DELETE_ARE_YOU_SURE": "¿Estás seguro?",
"HTML_DOMAINS_HELPER": "Lista de los dominios de correo al que se permite ingresar.\n<br \/>\nHaz click en el nombre de un dominio para modificarlo.\n" "HTML_DOMAINS_HELPER": "Lista de los dominios de correo al que se permite ingresar.\n<br>\nHaz click en el nombre de un dominio para modificarlo.\n"
}, },
"TAB_SECURITY": { "TAB_SECURITY": {
"LEGEND_SECURITY": "Seguridad", "LEGEND_SECURITY": "Seguridad",
@ -138,7 +138,7 @@
"BUTTON_CLOSE": "Cerrar", "BUTTON_CLOSE": "Cerrar",
"BUTTON_ADD": "Agregar", "BUTTON_ADD": "Agregar",
"BUTTON_UPDATE": "Actualizar", "BUTTON_UPDATE": "Actualizar",
"NEW_DOMAIN_DESC": "Esta configuración de Dominio le permitirá trabajar <br \/>con direcciones de correo tipo @<i>%NAME%<\/i>.", "NEW_DOMAIN_DESC": "Esta configuración de Dominio le permitirá trabajar <br>con direcciones de correo tipo @<i>%NAME%<\/i>.",
"WHITE_LIST_ALERT": "Lista de dominios con que los usuarios pueden ingresar.\nUse un espacio como delimitador.\n" "WHITE_LIST_ALERT": "Lista de dominios con que los usuarios pueden ingresar.\nUse un espacio como delimitador.\n"
}, },
"POPUPS_PLUGIN": { "POPUPS_PLUGIN": {

View file

@ -38,7 +38,7 @@
"LABEL_ALLOW_IDENTITIES": "اجازه استفاده از چندین شناسه", "LABEL_ALLOW_IDENTITIES": "اجازه استفاده از چندین شناسه",
"ALERT_DATA_ACCESS": "شاخه data قابل دسترس هست. تنظیمات وب‌سرور را طوری انجام دهید این شاخه از بیرون قابل دسترس نباشد. اطلاعات بیشتر اینجا هست:", "ALERT_DATA_ACCESS": "شاخه data قابل دسترس هست. تنظیمات وب‌سرور را طوری انجام دهید این شاخه از بیرون قابل دسترس نباشد. اطلاعات بیشتر اینجا هست:",
"ALERT_WARNING": "اخطار!", "ALERT_WARNING": "اخطار!",
"HTML_ALERT_WEAK_PASSWORD": "شما در حال استفاده از گذرواژه پیش‌فرض کاربر مدیر هستید.\n<br \/>\nبدلیل رعایت مسائل امنیتی\n<strong><a href=\"#\/security\">گذرواژه<\/a><\/strong>\nرا به کلمه دیگری تغییر دهید.\n\n" "HTML_ALERT_WEAK_PASSWORD": "شما در حال استفاده از گذرواژه پیش‌فرض کاربر مدیر هستید.\n<br>\nبدلیل رعایت مسائل امنیتی\n<strong><a href=\"#\/security\">گذرواژه<\/a><\/strong>\nرا به کلمه دیگری تغییر دهید.\n\n"
}, },
"TAB_LOGIN": { "TAB_LOGIN": {
"LEGEND_LOGIN_SCREEN": "صفحه ورود", "LEGEND_LOGIN_SCREEN": "صفحه ورود",
@ -66,14 +66,14 @@
"BUTTON_TEST": "تست", "BUTTON_TEST": "تست",
"ALERT_NOTICE": "توجه!", "ALERT_NOTICE": "توجه!",
"HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "از این پایگاه داده برای کاربران زیاد استفاده نکنید.", "HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "از این پایگاه داده برای کاربران زیاد استفاده نکنید.",
"HTML_ALERT_DOES_NOT_SUPPORTED": "سیستم از تماس‌ها پشتیبانی نمی‌کند\n<br \/>\nشما باید افزونه <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong> را نصب کنید یا اینکه فعال کنید.\n" "HTML_ALERT_DOES_NOT_SUPPORTED": "سیستم از تماس‌ها پشتیبانی نمی‌کند\n<br>\nشما باید افزونه <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong> را نصب کنید یا اینکه فعال کنید.\n"
}, },
"TAB_DOMAINS": { "TAB_DOMAINS": {
"LEGEND_DOMAINS": "دامنه‌ها", "LEGEND_DOMAINS": "دامنه‌ها",
"BUTTON_ADD_DOMAIN": "اضافه‌کردن دامنه", "BUTTON_ADD_DOMAIN": "اضافه‌کردن دامنه",
"BUTTON_ADD_ALIAS": "اضافه‌کردن نام مستعار", "BUTTON_ADD_ALIAS": "اضافه‌کردن نام مستعار",
"DELETE_ARE_YOU_SURE": "آیا مطمئن هستید؟", "DELETE_ARE_YOU_SURE": "آیا مطمئن هستید؟",
"HTML_DOMAINS_HELPER": "لیستی از دامنه‌هایی که وب‌میل اجازه دسترسی به آنها را دارد.\n<br \/>\nروی دامنه دامنه جهت پیکربندی کلیک کنید.\n" "HTML_DOMAINS_HELPER": "لیستی از دامنه‌هایی که وب‌میل اجازه دسترسی به آنها را دارد.\n<br>\nروی دامنه دامنه جهت پیکربندی کلیک کنید.\n"
}, },
"TAB_SECURITY": { "TAB_SECURITY": {
"LEGEND_SECURITY": "امنیت", "LEGEND_SECURITY": "امنیت",
@ -138,7 +138,7 @@
"BUTTON_CLOSE": "بستن", "BUTTON_CLOSE": "بستن",
"BUTTON_ADD": "اضافه‌کردن", "BUTTON_ADD": "اضافه‌کردن",
"BUTTON_UPDATE": "بروزرسانی", "BUTTON_UPDATE": "بروزرسانی",
"NEW_DOMAIN_DESC": "این تنظیمات دامنه به شما اجازه کار کردن <br \/>با پست الکترونیک <i>%NAME%<\/i> را می‌دهد.", "NEW_DOMAIN_DESC": "این تنظیمات دامنه به شما اجازه کار کردن <br>با پست الکترونیک <i>%NAME%<\/i> را می‌دهد.",
"WHITE_LIST_ALERT": "لیستی از دامنه‌ها که کاربران وب‌میل می‌توانند به آنها دسترسی داشته باشند.\nاز فاصله جهت جدا کردن استفاده کنید.\n" "WHITE_LIST_ALERT": "لیستی از دامنه‌ها که کاربران وب‌میل می‌توانند به آنها دسترسی داشته باشند.\nاز فاصله جهت جدا کردن استفاده کنید.\n"
}, },
"POPUPS_PLUGIN": { "POPUPS_PLUGIN": {

View file

@ -38,7 +38,7 @@
"LABEL_ALLOW_IDENTITIES": "Salli useat identiteetit", "LABEL_ALLOW_IDENTITIES": "Salli useat identiteetit",
"ALERT_DATA_ACCESS": "Data folder is accessible. Please configure your web server to hide the data folder from external access. Read more here:", "ALERT_DATA_ACCESS": "Data folder is accessible. Please configure your web server to hide the data folder from external access. Read more here:",
"ALERT_WARNING": "Varoitus!", "ALERT_WARNING": "Varoitus!",
"HTML_ALERT_WEAK_PASSWORD": "Sinulla on käytössäsi hallintatunnuksen oletussalasana.\n<br \/>\nTietoturvasyistä, ole ystävällinen ja\n<strong><a href=\"#\/security\">vaihda<\/a><\/strong>\nsalasanasi nyt.\n" "HTML_ALERT_WEAK_PASSWORD": "Sinulla on käytössäsi hallintatunnuksen oletussalasana.\n<br>\nTietoturvasyistä, ole ystävällinen ja\n<strong><a href=\"#\/security\">vaihda<\/a><\/strong>\nsalasanasi nyt.\n"
}, },
"TAB_LOGIN": { "TAB_LOGIN": {
"LEGEND_LOGIN_SCREEN": "Kirjautumissivu", "LEGEND_LOGIN_SCREEN": "Kirjautumissivu",
@ -66,14 +66,14 @@
"BUTTON_TEST": "Testi", "BUTTON_TEST": "Testi",
"ALERT_NOTICE": "Huomio!", "ALERT_NOTICE": "Huomio!",
"HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "Älä käytä tätä tietokantatyyppiä suurella määrällä aktiivisia käyttäjiä.", "HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "Älä käytä tätä tietokantatyyppiä suurella määrällä aktiivisia käyttäjiä.",
"HTML_ALERT_DOES_NOT_SUPPORTED": "Järjestelmäsi ei tue yhteystietoja.\n<br\/>\nAsenna tai aktivoi <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong> lisäosa palvelimellasi.\n" "HTML_ALERT_DOES_NOT_SUPPORTED": "Järjestelmäsi ei tue yhteystietoja.\n<br>\nAsenna tai aktivoi <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong> lisäosa palvelimellasi.\n"
}, },
"TAB_DOMAINS": { "TAB_DOMAINS": {
"LEGEND_DOMAINS": "Domainit", "LEGEND_DOMAINS": "Domainit",
"BUTTON_ADD_DOMAIN": "Lisää domain", "BUTTON_ADD_DOMAIN": "Lisää domain",
"BUTTON_ADD_ALIAS": "Lisää alias", "BUTTON_ADD_ALIAS": "Lisää alias",
"DELETE_ARE_YOU_SURE": "Oletko varma?", "DELETE_ARE_YOU_SURE": "Oletko varma?",
"HTML_DOMAINS_HELPER": "Lista domaineista joilla webmaililla on pääsy.\n<br\/>\nKlikkaa nimeä konfiguroidaksesi domain.\n" "HTML_DOMAINS_HELPER": "Lista domaineista joilla webmaililla on pääsy.\n<br>\nKlikkaa nimeä konfiguroidaksesi domain.\n"
}, },
"TAB_SECURITY": { "TAB_SECURITY": {
"LEGEND_SECURITY": "Tietoturva", "LEGEND_SECURITY": "Tietoturva",
@ -138,7 +138,7 @@
"BUTTON_CLOSE": "Sulje", "BUTTON_CLOSE": "Sulje",
"BUTTON_ADD": "Lisää", "BUTTON_ADD": "Lisää",
"BUTTON_UPDATE": "Päivitä", "BUTTON_UPDATE": "Päivitä",
"NEW_DOMAIN_DESC": "Tämän verkkotunnuksen asetukset sallivat käyttää <br\/> <i>%NAME%<i\/> säkhöpostiosoitteita.", "NEW_DOMAIN_DESC": "Tämän verkkotunnuksen asetukset sallivat käyttää <br> <i>%NAME%<i> säkhöpostiosoitteita.",
"WHITE_LIST_ALERT": "Lista domain käyttäjistä joihin webmaililla on oikeus.\nErottele välilyönnillä.\n" "WHITE_LIST_ALERT": "Lista domain käyttäjistä joihin webmaililla on oikeus.\nErottele välilyönnillä.\n"
}, },
"POPUPS_PLUGIN": { "POPUPS_PLUGIN": {

View file

@ -38,7 +38,7 @@
"LABEL_ALLOW_IDENTITIES": "Autoriser les identités multiples", "LABEL_ALLOW_IDENTITIES": "Autoriser les identités multiples",
"ALERT_DATA_ACCESS": "Data folder is accessible. Please configure your web server to hide the data folder from external access. Read more here:", "ALERT_DATA_ACCESS": "Data folder is accessible. Please configure your web server to hide the data folder from external access. Read more here:",
"ALERT_WARNING": "ATTENTION !", "ALERT_WARNING": "ATTENTION !",
"HTML_ALERT_WEAK_PASSWORD": "Vous utilisez le mot de passe administrateur par défaut.\n<br \/>\nPour des raisons de sécurité, veuillez\n<strong><a href=\"#\/security\">changer le mot de passe <\/a><\/strong>\ndès maintenant.\n" "HTML_ALERT_WEAK_PASSWORD": "Vous utilisez le mot de passe administrateur par défaut.\n<br>\nPour des raisons de sécurité, veuillez\n<strong><a href=\"#\/security\">changer le mot de passe <\/a><\/strong>\ndès maintenant.\n"
}, },
"TAB_LOGIN": { "TAB_LOGIN": {
"LEGEND_LOGIN_SCREEN": "Ecran de connexion", "LEGEND_LOGIN_SCREEN": "Ecran de connexion",
@ -66,14 +66,14 @@
"BUTTON_TEST": "Test", "BUTTON_TEST": "Test",
"ALERT_NOTICE": "Avis !", "ALERT_NOTICE": "Avis !",
"HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "N'utilisez pas ce type de base de données avec un grand nombre d'utilisateurs actifs.", "HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "N'utilisez pas ce type de base de données avec un grand nombre d'utilisateurs actifs.",
"HTML_ALERT_DOES_NOT_SUPPORTED": "Votre système ne supporte pas les contacts.\n<br \/>\nVous devez installer ou autoriser l'extension <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong> sur votre serveur.\n" "HTML_ALERT_DOES_NOT_SUPPORTED": "Votre système ne supporte pas les contacts.\n<br>\nVous devez installer ou autoriser l'extension <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong> sur votre serveur.\n"
}, },
"TAB_DOMAINS": { "TAB_DOMAINS": {
"LEGEND_DOMAINS": "Domaines", "LEGEND_DOMAINS": "Domaines",
"BUTTON_ADD_DOMAIN": "Ajouter un domaine", "BUTTON_ADD_DOMAIN": "Ajouter un domaine",
"BUTTON_ADD_ALIAS": "Ajouter un alias", "BUTTON_ADD_ALIAS": "Ajouter un alias",
"DELETE_ARE_YOU_SURE": "Êtes-vous sûr ?", "DELETE_ARE_YOU_SURE": "Êtes-vous sûr ?",
"HTML_DOMAINS_HELPER": "Liste des domaines autorisés.\n<br \/>\nCliquez sur le nom pour configurer le domaine.\n" "HTML_DOMAINS_HELPER": "Liste des domaines autorisés.\n<br>\nCliquez sur le nom pour configurer le domaine.\n"
}, },
"TAB_SECURITY": { "TAB_SECURITY": {
"LEGEND_SECURITY": "Sécurité", "LEGEND_SECURITY": "Sécurité",

View file

@ -38,7 +38,7 @@
"LABEL_ALLOW_IDENTITIES": "Több identitás engedélyezése", "LABEL_ALLOW_IDENTITIES": "Több identitás engedélyezése",
"ALERT_DATA_ACCESS": "A RainLoop adatmappája hozzáférhető. Kérlek állítsd be úgy a webszervert, hogy az adatmappát rejtse el a külső hozzáférés elől. További tudnivalók itt:", "ALERT_DATA_ACCESS": "A RainLoop adatmappája hozzáférhető. Kérlek állítsd be úgy a webszervert, hogy az adatmappát rejtse el a külső hozzáférés elől. További tudnivalók itt:",
"ALERT_WARNING": "Figyelmeztetés!", "ALERT_WARNING": "Figyelmeztetés!",
"HTML_ALERT_WEAK_PASSWORD": "Az alapértelmezett admin jelszót használod\n<br \/>\nBiztonsági okokból kérlek\n<strong><a href=\"#\/security\">változtasd meg<\/a><\/strong>\na jelszót valami másra!\n" "HTML_ALERT_WEAK_PASSWORD": "Az alapértelmezett admin jelszót használod\n<br>\nBiztonsági okokból kérlek\n<strong><a href=\"#\/security\">változtasd meg<\/a><\/strong>\na jelszót valami másra!\n"
}, },
"TAB_LOGIN": { "TAB_LOGIN": {
"LEGEND_LOGIN_SCREEN": "Bejelentkező képernyő", "LEGEND_LOGIN_SCREEN": "Bejelentkező képernyő",
@ -66,14 +66,14 @@
"BUTTON_TEST": "Teszt", "BUTTON_TEST": "Teszt",
"ALERT_NOTICE": "Megjegyzés!", "ALERT_NOTICE": "Megjegyzés!",
"HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "Ne használd ezt az adatbázis típust nagy számú aktív felhasználóval.", "HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "Ne használd ezt az adatbázis típust nagy számú aktív felhasználóval.",
"HTML_ALERT_DOES_NOT_SUPPORTED": "A rendszer nem támogatja a címtárat.\n<br \/>\nTelepítened vagy engedélyezned kell egy <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong> kiterjesztést a szervereden.\n" "HTML_ALERT_DOES_NOT_SUPPORTED": "A rendszer nem támogatja a címtárat.\n<br>\nTelepítened vagy engedélyezned kell egy <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong> kiterjesztést a szervereden.\n"
}, },
"TAB_DOMAINS": { "TAB_DOMAINS": {
"LEGEND_DOMAINS": "Domainek", "LEGEND_DOMAINS": "Domainek",
"BUTTON_ADD_DOMAIN": "Domain hozzáadás", "BUTTON_ADD_DOMAIN": "Domain hozzáadás",
"BUTTON_ADD_ALIAS": "Álnév hozzáadás", "BUTTON_ADD_ALIAS": "Álnév hozzáadás",
"DELETE_ARE_YOU_SURE": "Biztos vagy benne?", "DELETE_ARE_YOU_SURE": "Biztos vagy benne?",
"HTML_DOMAINS_HELPER": "Hozzáféréshez engedélyezett domainek listája:\n<br \/>\nA domain beállításához kattints a névre.\n" "HTML_DOMAINS_HELPER": "Hozzáféréshez engedélyezett domainek listája:\n<br>\nA domain beállításához kattints a névre.\n"
}, },
"TAB_SECURITY": { "TAB_SECURITY": {
"LEGEND_SECURITY": "Biztonság", "LEGEND_SECURITY": "Biztonság",
@ -138,7 +138,7 @@
"BUTTON_CLOSE": "Bezár", "BUTTON_CLOSE": "Bezár",
"BUTTON_ADD": "Hozzáad", "BUTTON_ADD": "Hozzáad",
"BUTTON_UPDATE": "Frissítés", "BUTTON_UPDATE": "Frissítés",
"NEW_DOMAIN_DESC": "Ez a domain konfiguráció lehetővé teszi <br \/>a <i>%NAME%<\/i> email címek használatát.", "NEW_DOMAIN_DESC": "Ez a domain konfiguráció lehetővé teszi <br>a <i>%NAME%<\/i> email címek használatát.",
"WHITE_LIST_ALERT": "Hozzáféréshez engedélyezett domainek listája.\nElválasztáshoz használd a szóközt.\n" "WHITE_LIST_ALERT": "Hozzáféréshez engedélyezett domainek listája.\nElválasztáshoz használd a szóközt.\n"
}, },
"POPUPS_PLUGIN": { "POPUPS_PLUGIN": {

View file

@ -38,7 +38,7 @@
"LABEL_ALLOW_IDENTITIES": "Izinkan identitas jamak", "LABEL_ALLOW_IDENTITIES": "Izinkan identitas jamak",
"ALERT_DATA_ACCESS": "Data foldel RainLoop bisa diakses. Silahkan atur web server anda untuk menyembunyikan folder data dari akses eksternal. Baca selengkapnya di sini:", "ALERT_DATA_ACCESS": "Data foldel RainLoop bisa diakses. Silahkan atur web server anda untuk menyembunyikan folder data dari akses eksternal. Baca selengkapnya di sini:",
"ALERT_WARNING": "Peringatan!", "ALERT_WARNING": "Peringatan!",
"HTML_ALERT_WEAK_PASSWORD": "Anda menggunakan password admin bawaan.\n<br \/>\nAtas alasan keamanan, mohon\n<strong><a href=\"#\/security\">mengganti<\/a><\/strong>\npassword dengan frasa yang lainnya segera.\n" "HTML_ALERT_WEAK_PASSWORD": "Anda menggunakan password admin bawaan.\n<br>\nAtas alasan keamanan, mohon\n<strong><a href=\"#\/security\">mengganti<\/a><\/strong>\npassword dengan frasa yang lainnya segera.\n"
}, },
"TAB_LOGIN": { "TAB_LOGIN": {
"LEGEND_LOGIN_SCREEN": "Laman login", "LEGEND_LOGIN_SCREEN": "Laman login",
@ -66,14 +66,14 @@
"BUTTON_TEST": "Ujicoba", "BUTTON_TEST": "Ujicoba",
"ALERT_NOTICE": "Perhatian!", "ALERT_NOTICE": "Perhatian!",
"HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "Jangan gunakan tipe database ini untuk jumlah user aktif yang besar.", "HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "Jangan gunakan tipe database ini untuk jumlah user aktif yang besar.",
"HTML_ALERT_DOES_NOT_SUPPORTED": "Sistem anda tidak mendukung kontak\n<br \/>\nAnda harus memasang atau mengaktifkan <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong> extension pada server anda.\n" "HTML_ALERT_DOES_NOT_SUPPORTED": "Sistem anda tidak mendukung kontak\n<br>\nAnda harus memasang atau mengaktifkan <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong> extension pada server anda.\n"
}, },
"TAB_DOMAINS": { "TAB_DOMAINS": {
"LEGEND_DOMAINS": "Domain", "LEGEND_DOMAINS": "Domain",
"BUTTON_ADD_DOMAIN": "Tambah domain", "BUTTON_ADD_DOMAIN": "Tambah domain",
"BUTTON_ADD_ALIAS": "Tambah alias", "BUTTON_ADD_ALIAS": "Tambah alias",
"DELETE_ARE_YOU_SURE": "Anda yakin?", "DELETE_ARE_YOU_SURE": "Anda yakin?",
"HTML_DOMAINS_HELPER": "Daftar domain webmail yang diizinkan mengakses.\n<br \/>\nKlik pada nama domain untuk mengatur domain.\n" "HTML_DOMAINS_HELPER": "Daftar domain webmail yang diizinkan mengakses.\n<br>\nKlik pada nama domain untuk mengatur domain.\n"
}, },
"TAB_SECURITY": { "TAB_SECURITY": {
"LEGEND_SECURITY": "Keamanan", "LEGEND_SECURITY": "Keamanan",
@ -138,7 +138,7 @@
"BUTTON_CLOSE": "Tutup", "BUTTON_CLOSE": "Tutup",
"BUTTON_ADD": "Tambah", "BUTTON_ADD": "Tambah",
"BUTTON_UPDATE": "Perbarui", "BUTTON_UPDATE": "Perbarui",
"NEW_DOMAIN_DESC": "Domain ini mengizinkan anda bekerja dengan alamat email <br \/>juga<i>%NAME%<\/i> ", "NEW_DOMAIN_DESC": "Domain ini mengizinkan anda bekerja dengan alamat email <br>juga<i>%NAME%<\/i> ",
"WHITE_LIST_ALERT": "Daftar domain webmail user yang diizinkan diakses.\nGunakan spasi untuk pemisahnya\n" "WHITE_LIST_ALERT": "Daftar domain webmail user yang diizinkan diakses.\nGunakan spasi untuk pemisahnya\n"
}, },
"POPUPS_PLUGIN": { "POPUPS_PLUGIN": {

View file

@ -38,7 +38,7 @@
"LABEL_ALLOW_IDENTITIES": "Permetti di registrare identità multiple", "LABEL_ALLOW_IDENTITIES": "Permetti di registrare identità multiple",
"ALERT_DATA_ACCESS": "Data folder is accessible. Please configure your web server to hide the data folder from external access. Read more here:", "ALERT_DATA_ACCESS": "Data folder is accessible. Please configure your web server to hide the data folder from external access. Read more here:",
"ALERT_WARNING": "Attenzione!", "ALERT_WARNING": "Attenzione!",
"HTML_ALERT_WEAK_PASSWORD": "Stai usando la password di amministrazione predefinita.\n<br \/>\nPer ragioni di sicurezza,\n<strong><a href=\"#\/security\">cambiala<\/a><\/strong>\ncon una nuova password immediatamente.\n" "HTML_ALERT_WEAK_PASSWORD": "Stai usando la password di amministrazione predefinita.\n<br>\nPer ragioni di sicurezza,\n<strong><a href=\"#\/security\">cambiala<\/a><\/strong>\ncon una nuova password immediatamente.\n"
}, },
"TAB_LOGIN": { "TAB_LOGIN": {
"LEGEND_LOGIN_SCREEN": "Schermata di accesso", "LEGEND_LOGIN_SCREEN": "Schermata di accesso",
@ -66,14 +66,14 @@
"BUTTON_TEST": "Verifica dati", "BUTTON_TEST": "Verifica dati",
"ALERT_NOTICE": "Attenzione!", "ALERT_NOTICE": "Attenzione!",
"HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "Non usare questo tipo di database con un alto numero di utenti attivi.", "HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "Non usare questo tipo di database con un alto numero di utenti attivi.",
"HTML_ALERT_DOES_NOT_SUPPORTED": "Il tuo server non supporta il salvataggio dei contatti.\n<br \/>\nDevi abilitare l'estensione <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong> sul tuo server.\n" "HTML_ALERT_DOES_NOT_SUPPORTED": "Il tuo server non supporta il salvataggio dei contatti.\n<br>\nDevi abilitare l'estensione <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong> sul tuo server.\n"
}, },
"TAB_DOMAINS": { "TAB_DOMAINS": {
"LEGEND_DOMAINS": "Domini", "LEGEND_DOMAINS": "Domini",
"BUTTON_ADD_DOMAIN": "Aggiungi dominio", "BUTTON_ADD_DOMAIN": "Aggiungi dominio",
"BUTTON_ADD_ALIAS": "Aggiungi alias", "BUTTON_ADD_ALIAS": "Aggiungi alias",
"DELETE_ARE_YOU_SURE": "Ne sei sicuro?", "DELETE_ARE_YOU_SURE": "Ne sei sicuro?",
"HTML_DOMAINS_HELPER": "Lista di domini a cui la webmail è abilitata ad accedere.\n<br \/>\nClicca su un nome per configurare quel dominio.\n" "HTML_DOMAINS_HELPER": "Lista di domini a cui la webmail è abilitata ad accedere.\n<br>\nClicca su un nome per configurare quel dominio.\n"
}, },
"TAB_SECURITY": { "TAB_SECURITY": {
"LEGEND_SECURITY": "Security", "LEGEND_SECURITY": "Security",
@ -138,7 +138,7 @@
"BUTTON_CLOSE": "Chiudi", "BUTTON_CLOSE": "Chiudi",
"BUTTON_ADD": "Aggiungi", "BUTTON_ADD": "Aggiungi",
"BUTTON_UPDATE": "Aggiorna", "BUTTON_UPDATE": "Aggiorna",
"NEW_DOMAIN_DESC": "La configurazione di questo dominio ti permette di lavorare <br \/>con <i>%NAME%<\/i> indirizzi email.", "NEW_DOMAIN_DESC": "La configurazione di questo dominio ti permette di lavorare <br>con <i>%NAME%<\/i> indirizzi email.",
"WHITE_LIST_ALERT": "Lista di domini a cui gli utenti sono autorizzati ad accedere.\nUtilizzare uno spazio come separatore.\n" "WHITE_LIST_ALERT": "Lista di domini a cui gli utenti sono autorizzati ad accedere.\nUtilizzare uno spazio come separatore.\n"
}, },
"POPUPS_PLUGIN": { "POPUPS_PLUGIN": {

View file

@ -38,7 +38,7 @@
"LABEL_ALLOW_IDENTITIES": "複数の表示名を使用する", "LABEL_ALLOW_IDENTITIES": "複数の表示名を使用する",
"ALERT_DATA_ACCESS": "RainLoop のデータフォルダがアクセス可能になっています。外部から RainLoop のデータフォルダにアクセスできないよう、Web サーバーを設定してください。詳しくは以下をご覧ください:", "ALERT_DATA_ACCESS": "RainLoop のデータフォルダがアクセス可能になっています。外部から RainLoop のデータフォルダにアクセスできないよう、Web サーバーを設定してください。詳しくは以下をご覧ください:",
"ALERT_WARNING": "警告!", "ALERT_WARNING": "警告!",
"HTML_ALERT_WEAK_PASSWORD": "デフォルトの管理者パスワードを使用しています。\n<br \/>\nセキュリティ上の理由から、いますぐパスワードを\n<strong><a href=\"#\/security\">変更<\/a><\/strong>\nしてください。\n" "HTML_ALERT_WEAK_PASSWORD": "デフォルトの管理者パスワードを使用しています。\n<br>\nセキュリティ上の理由から、いますぐパスワードを\n<strong><a href=\"#\/security\">変更<\/a><\/strong>\nしてください。\n"
}, },
"TAB_LOGIN": { "TAB_LOGIN": {
"LEGEND_LOGIN_SCREEN": "ログイン画面", "LEGEND_LOGIN_SCREEN": "ログイン画面",
@ -66,14 +66,14 @@
"BUTTON_TEST": "テスト", "BUTTON_TEST": "テスト",
"ALERT_NOTICE": "注意!", "ALERT_NOTICE": "注意!",
"HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "アクティブユーザーの数が多いとき、このデータベース・タイプを使用しないでください。", "HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "アクティブユーザーの数が多いとき、このデータベース・タイプを使用しないでください。",
"HTML_ALERT_DOES_NOT_SUPPORTED": "このシステムでは連絡先はサポートされていません。\n<br \/>\nサーバーへ<strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong>\n拡張モジュールのインストールが必要です。\n" "HTML_ALERT_DOES_NOT_SUPPORTED": "このシステムでは連絡先はサポートされていません。\n<br>\nサーバーへ<strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong>\n拡張モジュールのインストールが必要です。\n"
}, },
"TAB_DOMAINS": { "TAB_DOMAINS": {
"LEGEND_DOMAINS": "ドメイン", "LEGEND_DOMAINS": "ドメイン",
"BUTTON_ADD_DOMAIN": "ドメインを追加", "BUTTON_ADD_DOMAIN": "ドメインを追加",
"BUTTON_ADD_ALIAS": "エイリアスを追加", "BUTTON_ADD_ALIAS": "エイリアスを追加",
"DELETE_ARE_YOU_SURE": "よろしいですか?", "DELETE_ARE_YOU_SURE": "よろしいですか?",
"HTML_DOMAINS_HELPER": "ドメインの一覧は、Web メールのアクセスを許可されています。\n<br \/>\nドメインを設定するには、名前をクリックしてください。\n" "HTML_DOMAINS_HELPER": "ドメインの一覧は、Web メールのアクセスを許可されています。\n<br>\nドメインを設定するには、名前をクリックしてください。\n"
}, },
"TAB_SECURITY": { "TAB_SECURITY": {
"LEGEND_SECURITY": "セキュリティ", "LEGEND_SECURITY": "セキュリティ",

View file

@ -38,7 +38,7 @@
"LABEL_ALLOW_IDENTITIES": "Leisti daugiau tapatybių", "LABEL_ALLOW_IDENTITIES": "Leisti daugiau tapatybių",
"ALERT_DATA_ACCESS": "Data folder is accessible. Please configure your web server to hide the data folder from external access. Read more here:", "ALERT_DATA_ACCESS": "Data folder is accessible. Please configure your web server to hide the data folder from external access. Read more here:",
"ALERT_WARNING": "Dėmesio!", "ALERT_WARNING": "Dėmesio!",
"HTML_ALERT_WEAK_PASSWORD": "Naudojate numatytąjį administratoriaus slaptažodį.\n<br \/>\nDėl Jūsų saugumo prašome\n<strong><a href=\"#\/security\">pakeiskite<\/a><\/strong>\nslaptažodį kitu.\n\n" "HTML_ALERT_WEAK_PASSWORD": "Naudojate numatytąjį administratoriaus slaptažodį.\n<br>\nDėl Jūsų saugumo prašome\n<strong><a href=\"#\/security\">pakeiskite<\/a><\/strong>\nslaptažodį kitu.\n\n"
}, },
"TAB_LOGIN": { "TAB_LOGIN": {
"LEGEND_LOGIN_SCREEN": "Prisijungimo langas", "LEGEND_LOGIN_SCREEN": "Prisijungimo langas",
@ -73,7 +73,7 @@
"BUTTON_ADD_DOMAIN": "Pridėti Domeną", "BUTTON_ADD_DOMAIN": "Pridėti Domeną",
"BUTTON_ADD_ALIAS": "Pridėti Alias", "BUTTON_ADD_ALIAS": "Pridėti Alias",
"DELETE_ARE_YOU_SURE": "Ar jūs įsitikinę?", "DELETE_ARE_YOU_SURE": "Ar jūs įsitikinę?",
"HTML_DOMAINS_HELPER": "Leidžiamų Domenų sąrašas\n<br\/>\nSpauskite ant pavadinimo norėdami redaguoti.\n" "HTML_DOMAINS_HELPER": "Leidžiamų Domenų sąrašas\n<br>\nSpauskite ant pavadinimo norėdami redaguoti.\n"
}, },
"TAB_SECURITY": { "TAB_SECURITY": {
"LEGEND_SECURITY": "Sauga", "LEGEND_SECURITY": "Sauga",
@ -138,7 +138,7 @@
"BUTTON_CLOSE": "Uždaryti", "BUTTON_CLOSE": "Uždaryti",
"BUTTON_ADD": "Pridėti", "BUTTON_ADD": "Pridėti",
"BUTTON_UPDATE": "Atnaujinti", "BUTTON_UPDATE": "Atnaujinti",
"NEW_DOMAIN_DESC": "Šie nustatymai leis jums dirbti <br\/> su <i>%NAME%<\/i> domeno pašto adresais.", "NEW_DOMAIN_DESC": "Šie nustatymai leis jums dirbti <br> su <i>%NAME%<\/i> domeno pašto adresais.",
"WHITE_LIST_ALERT": "Domeno vartotojų sąrašas, kuriems leista naudotis web paštu.\nNaudokite tarpo simbolį kaip skyriklį.\n" "WHITE_LIST_ALERT": "Domeno vartotojų sąrašas, kuriems leista naudotis web paštu.\nNaudokite tarpo simbolį kaip skyriklį.\n"
}, },
"POPUPS_PLUGIN": { "POPUPS_PLUGIN": {

View file

@ -38,7 +38,7 @@
"LABEL_ALLOW_IDENTITIES": "Tillat bruk av flere identiteter", "LABEL_ALLOW_IDENTITIES": "Tillat bruk av flere identiteter",
"ALERT_DATA_ACCESS": "RainLoop-datamappa di er offentlig tiljgengelig. Sett opp webtjeneren slik at den ikke viser datamappa. Les mer her:", "ALERT_DATA_ACCESS": "RainLoop-datamappa di er offentlig tiljgengelig. Sett opp webtjeneren slik at den ikke viser datamappa. Les mer her:",
"ALERT_WARNING": "Advarsel!", "ALERT_WARNING": "Advarsel!",
"HTML_ALERT_WEAK_PASSWORD": "Du bruker forvalgt admin-passord.\n<br \/>\nAv sikkerhetshensyn bør du\n<strong><a href=\"#\/security\">endre<\/a><\/strong>\npassordet umiddelbart.\n" "HTML_ALERT_WEAK_PASSWORD": "Du bruker forvalgt admin-passord.\n<br>\nAv sikkerhetshensyn bør du\n<strong><a href=\"#\/security\">endre<\/a><\/strong>\npassordet umiddelbart.\n"
}, },
"TAB_LOGIN": { "TAB_LOGIN": {
"LEGEND_LOGIN_SCREEN": "Innloggingsskjerm", "LEGEND_LOGIN_SCREEN": "Innloggingsskjerm",
@ -66,14 +66,14 @@
"BUTTON_TEST": "Test", "BUTTON_TEST": "Test",
"ALERT_NOTICE": "Varsel!", "ALERT_NOTICE": "Varsel!",
"HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "Ikke bruk denne databasetypen hvis dette systemet har mange brukere.", "HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "Ikke bruk denne databasetypen hvis dette systemet har mange brukere.",
"HTML_ALERT_DOES_NOT_SUPPORTED": "Dette systemet støtter ikke kontakter.\n<br \/>\nDu må installere eller slå på utvidelsen <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong> på tjeneren.\n" "HTML_ALERT_DOES_NOT_SUPPORTED": "Dette systemet støtter ikke kontakter.\n<br>\nDu må installere eller slå på utvidelsen <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong> på tjeneren.\n"
}, },
"TAB_DOMAINS": { "TAB_DOMAINS": {
"LEGEND_DOMAINS": "Domener", "LEGEND_DOMAINS": "Domener",
"BUTTON_ADD_DOMAIN": "Legg til domene", "BUTTON_ADD_DOMAIN": "Legg til domene",
"BUTTON_ADD_ALIAS": "Legg til alias", "BUTTON_ADD_ALIAS": "Legg til alias",
"DELETE_ARE_YOU_SURE": "Er du sikker?", "DELETE_ARE_YOU_SURE": "Er du sikker?",
"HTML_DOMAINS_HELPER": "Liste over domener som programmet kan få tilgang til.\n<br \/>\nTrykk på et navn for å sette opp domenet.\n" "HTML_DOMAINS_HELPER": "Liste over domener som programmet kan få tilgang til.\n<br>\nTrykk på et navn for å sette opp domenet.\n"
}, },
"TAB_SECURITY": { "TAB_SECURITY": {
"LEGEND_SECURITY": "Sikkerhet", "LEGEND_SECURITY": "Sikkerhet",
@ -138,7 +138,7 @@
"BUTTON_CLOSE": "Lukk", "BUTTON_CLOSE": "Lukk",
"BUTTON_ADD": "Legg til", "BUTTON_ADD": "Legg til",
"BUTTON_UPDATE": "Oppdater", "BUTTON_UPDATE": "Oppdater",
"NEW_DOMAIN_DESC": "Dette domeneoppsettet lar deg jobbe <br \/> med e-postadresser ved <i>%NAME%<\/i>.", "NEW_DOMAIN_DESC": "Dette domeneoppsettet lar deg jobbe <br> med e-postadresser ved <i>%NAME%<\/i>.",
"WHITE_LIST_ALERT": "Liste over domenebrukere som programmet skal ha tilgang til.\nHold verdier adskilt med mellomrom.\n" "WHITE_LIST_ALERT": "Liste over domenebrukere som programmet skal ha tilgang til.\nHold verdier adskilt med mellomrom.\n"
}, },
"POPUPS_PLUGIN": { "POPUPS_PLUGIN": {

View file

@ -38,7 +38,7 @@
"LABEL_ALLOW_IDENTITIES": "Meerdere identiteiten toestaan", "LABEL_ALLOW_IDENTITIES": "Meerdere identiteiten toestaan",
"ALERT_DATA_ACCESS": "Data folder is accessible. Please configure your web server to hide the data folder from external access. Read more here:", "ALERT_DATA_ACCESS": "Data folder is accessible. Please configure your web server to hide the data folder from external access. Read more here:",
"ALERT_WARNING": "Waarschuwing!", "ALERT_WARNING": "Waarschuwing!",
"HTML_ALERT_WEAK_PASSWORD": "U gebruikt het standaard beheer wachtwoord.\n<br \/>\n<strong><a href=\"#\/security\">Wijzig<\/a><\/strong>\na.u.b. voor uw veiligheid direct het wachtwoord.\n" "HTML_ALERT_WEAK_PASSWORD": "U gebruikt het standaard beheer wachtwoord.\n<br>\n<strong><a href=\"#\/security\">Wijzig<\/a><\/strong>\na.u.b. voor uw veiligheid direct het wachtwoord.\n"
}, },
"TAB_LOGIN": { "TAB_LOGIN": {
"LEGEND_LOGIN_SCREEN": "Inlogscherm", "LEGEND_LOGIN_SCREEN": "Inlogscherm",
@ -66,14 +66,14 @@
"BUTTON_TEST": "Test", "BUTTON_TEST": "Test",
"ALERT_NOTICE": "Aandacht!", "ALERT_NOTICE": "Aandacht!",
"HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "Gegruik deze database soort niet met een groot aantal actieve gebrukers.", "HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "Gegruik deze database soort niet met een groot aantal actieve gebrukers.",
"HTML_ALERT_DOES_NOT_SUPPORTED": "Uw systeem ondersteund geen contactpersonen.\n<br \/>\nU moet een <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong> extentie op uw server installeren of activeren.\n" "HTML_ALERT_DOES_NOT_SUPPORTED": "Uw systeem ondersteund geen contactpersonen.\n<br>\nU moet een <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong> extentie op uw server installeren of activeren.\n"
}, },
"TAB_DOMAINS": { "TAB_DOMAINS": {
"LEGEND_DOMAINS": "Domeinen", "LEGEND_DOMAINS": "Domeinen",
"BUTTON_ADD_DOMAIN": "Domein toevoegen", "BUTTON_ADD_DOMAIN": "Domein toevoegen",
"BUTTON_ADD_ALIAS": "Voeg alias toe", "BUTTON_ADD_ALIAS": "Voeg alias toe",
"DELETE_ARE_YOU_SURE": "Weet u het zeker?", "DELETE_ARE_YOU_SURE": "Weet u het zeker?",
"HTML_DOMAINS_HELPER": "Lijst van toegestane domeinen.\n<br \/>\nKlik op de domeinnaam om deze te configureren.\n" "HTML_DOMAINS_HELPER": "Lijst van toegestane domeinen.\n<br>\nKlik op de domeinnaam om deze te configureren.\n"
}, },
"TAB_SECURITY": { "TAB_SECURITY": {
"LEGEND_SECURITY": "Beveiliging", "LEGEND_SECURITY": "Beveiliging",
@ -138,7 +138,7 @@
"BUTTON_CLOSE": "Annuleer", "BUTTON_CLOSE": "Annuleer",
"BUTTON_ADD": "Toevoegen", "BUTTON_ADD": "Toevoegen",
"BUTTON_UPDATE": "Update", "BUTTON_UPDATE": "Update",
"NEW_DOMAIN_DESC": "Dit domein stelt u in staat om <br \/>met <i>%NAME%<\/i> e-mail adressen te werken.", "NEW_DOMAIN_DESC": "Dit domein stelt u in staat om <br>met <i>%NAME%<\/i> e-mail adressen te werken.",
"WHITE_LIST_ALERT": "Lijst van gebruikers die dit domein mogen gebruiken.\nGebruik een spatie als scheidingsteken.\n" "WHITE_LIST_ALERT": "Lijst van gebruikers die dit domein mogen gebruiken.\nGebruik een spatie als scheidingsteken.\n"
}, },
"POPUPS_PLUGIN": { "POPUPS_PLUGIN": {

View file

@ -38,7 +38,7 @@
"LABEL_ALLOW_IDENTITIES": "Zezwól na posiadanie wielu tożsamości", "LABEL_ALLOW_IDENTITIES": "Zezwól na posiadanie wielu tożsamości",
"ALERT_DATA_ACCESS": "Katalog „data” jest osiągalny z poziomu przeglądarki WWW. Zmień konfigurację serwera www, aby ukryć ten folder z zewnątrz. Więcej informacji tutaj: ", "ALERT_DATA_ACCESS": "Katalog „data” jest osiągalny z poziomu przeglądarki WWW. Zmień konfigurację serwera www, aby ukryć ten folder z zewnątrz. Więcej informacji tutaj: ",
"ALERT_WARNING": "Ostrzeżenie!", "ALERT_WARNING": "Ostrzeżenie!",
"HTML_ALERT_WEAK_PASSWORD": "Korzystasz z domyślnego hasła administratora.\n<br \/>\nZe względów bezpieczeństwa\n<strong><a href=\"#\/security\">zmień hasło<\/a><\/strong>\nna inne.\n" "HTML_ALERT_WEAK_PASSWORD": "Korzystasz z domyślnego hasła administratora.\n<br>\nZe względów bezpieczeństwa\n<strong><a href=\"#\/security\">zmień hasło<\/a><\/strong>\nna inne.\n"
}, },
"TAB_LOGIN": { "TAB_LOGIN": {
"LEGEND_LOGIN_SCREEN": "Ekran logowania", "LEGEND_LOGIN_SCREEN": "Ekran logowania",
@ -66,14 +66,14 @@
"BUTTON_TEST": "Testuj", "BUTTON_TEST": "Testuj",
"ALERT_NOTICE": "Ostrzeżenie!", "ALERT_NOTICE": "Ostrzeżenie!",
"HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "Nie używaj tej bazy danych z dużą ilością aktywnych użytkowników.", "HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "Nie używaj tej bazy danych z dużą ilością aktywnych użytkowników.",
"HTML_ALERT_DOES_NOT_SUPPORTED": "Twój system nie zawiera wsparcia dla obsługi kontaktów.\n<br \/>\nMusisz zainstalować lub uruchomić na serwerze jedno z rozszerzeń <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong>.\n" "HTML_ALERT_DOES_NOT_SUPPORTED": "Twój system nie zawiera wsparcia dla obsługi kontaktów.\n<br>\nMusisz zainstalować lub uruchomić na serwerze jedno z rozszerzeń <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong>.\n"
}, },
"TAB_DOMAINS": { "TAB_DOMAINS": {
"LEGEND_DOMAINS": "Domeny", "LEGEND_DOMAINS": "Domeny",
"BUTTON_ADD_DOMAIN": "Dodaj domenę", "BUTTON_ADD_DOMAIN": "Dodaj domenę",
"BUTTON_ADD_ALIAS": "Dodaj Alias", "BUTTON_ADD_ALIAS": "Dodaj Alias",
"DELETE_ARE_YOU_SURE": "Czy na pewno?", "DELETE_ARE_YOU_SURE": "Czy na pewno?",
"HTML_DOMAINS_HELPER": "Lista domen, do których można uzyskać dostęp poprzez tego klienta.\n<br \/>\nKliknij na nazwę, aby skonfigurować domenę.\n" "HTML_DOMAINS_HELPER": "Lista domen, do których można uzyskać dostęp poprzez tego klienta.\n<br>\nKliknij na nazwę, aby skonfigurować domenę.\n"
}, },
"TAB_SECURITY": { "TAB_SECURITY": {
"LEGEND_SECURITY": "Bezpieczeństwo", "LEGEND_SECURITY": "Bezpieczeństwo",
@ -138,7 +138,7 @@
"BUTTON_CLOSE": "Zamknij", "BUTTON_CLOSE": "Zamknij",
"BUTTON_ADD": "Dodaj", "BUTTON_ADD": "Dodaj",
"BUTTON_UPDATE": "Zaktualizuj", "BUTTON_UPDATE": "Zaktualizuj",
"NEW_DOMAIN_DESC": "Konfiguracja tej domeny pozwala na pracę<br \/>z adresami e-mail: <i>%NAME%<\/i>", "NEW_DOMAIN_DESC": "Konfiguracja tej domeny pozwala na pracę<br>z adresami e-mail: <i>%NAME%<\/i>",
"WHITE_LIST_ALERT": "Lista użytkowników domeny, którzy mogą uzyskać dostęp z tego webmaila.\nUżyj spacji do rozdzielenia.\n" "WHITE_LIST_ALERT": "Lista użytkowników domeny, którzy mogą uzyskać dostęp z tego webmaila.\nUżyj spacji do rozdzielenia.\n"
}, },
"POPUPS_PLUGIN": { "POPUPS_PLUGIN": {

View file

@ -38,7 +38,7 @@
"LABEL_ALLOW_IDENTITIES": "Permitir identidades multiplas", "LABEL_ALLOW_IDENTITIES": "Permitir identidades multiplas",
"ALERT_DATA_ACCESS": "A pasta de dados RainLoop está acessível. Por favor configure o seu servidor web para esconder a pasta de dados do acesso externo. Leia mais aqui:", "ALERT_DATA_ACCESS": "A pasta de dados RainLoop está acessível. Por favor configure o seu servidor web para esconder a pasta de dados do acesso externo. Leia mais aqui:",
"ALERT_WARNING": "Aviso!", "ALERT_WARNING": "Aviso!",
"HTML_ALERT_WEAK_PASSWORD": "Você está usando a senha administrativa padrão.\n<br \/>\nPor motivo de segurança por favor\n<strong><a href=\"#\/security\">troque a senha<\/a><\/strong>\nagora.\n" "HTML_ALERT_WEAK_PASSWORD": "Você está usando a senha administrativa padrão.\n<br>\nPor motivo de segurança por favor\n<strong><a href=\"#\/security\">troque a senha<\/a><\/strong>\nagora.\n"
}, },
"TAB_LOGIN": { "TAB_LOGIN": {
"LEGEND_LOGIN_SCREEN": "Tela de entrada", "LEGEND_LOGIN_SCREEN": "Tela de entrada",
@ -66,14 +66,14 @@
"BUTTON_TEST": "Testar", "BUTTON_TEST": "Testar",
"ALERT_NOTICE": "Aviso!", "ALERT_NOTICE": "Aviso!",
"HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "Não use este tipo de banco de dados com um grande número de usuários ativos.", "HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "Não use este tipo de banco de dados com um grande número de usuários ativos.",
"HTML_ALERT_DOES_NOT_SUPPORTED": "O seu sistema não suporta o uso dos contatos.\n<br \/>\nVocê precisa instalar ou habilitar a extensão <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong> em seu servidor.\n" "HTML_ALERT_DOES_NOT_SUPPORTED": "O seu sistema não suporta o uso dos contatos.\n<br>\nVocê precisa instalar ou habilitar a extensão <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong> em seu servidor.\n"
}, },
"TAB_DOMAINS": { "TAB_DOMAINS": {
"LEGEND_DOMAINS": "Domínios", "LEGEND_DOMAINS": "Domínios",
"BUTTON_ADD_DOMAIN": "Adicionar Domínio", "BUTTON_ADD_DOMAIN": "Adicionar Domínio",
"BUTTON_ADD_ALIAS": "Adicionar apelido (Alias)", "BUTTON_ADD_ALIAS": "Adicionar apelido (Alias)",
"DELETE_ARE_YOU_SURE": "Você tem certeza?", "DELETE_ARE_YOU_SURE": "Você tem certeza?",
"HTML_DOMAINS_HELPER": "Lista dos domínios com acesso permitido ao webmail.\n<br \/>\nClique no domínio para configurá-lo.\n" "HTML_DOMAINS_HELPER": "Lista dos domínios com acesso permitido ao webmail.\n<br>\nClique no domínio para configurá-lo.\n"
}, },
"TAB_SECURITY": { "TAB_SECURITY": {
"LEGEND_SECURITY": "Segurança", "LEGEND_SECURITY": "Segurança",
@ -138,7 +138,7 @@
"BUTTON_CLOSE": "Fechar", "BUTTON_CLOSE": "Fechar",
"BUTTON_ADD": "Adicionar", "BUTTON_ADD": "Adicionar",
"BUTTON_UPDATE": "Atualizar", "BUTTON_UPDATE": "Atualizar",
"NEW_DOMAIN_DESC": "Esta configuração de domínio lhe permitirá trabalhar <br \/> com endereços de e-mail do <i>%NAME%<\/i>.", "NEW_DOMAIN_DESC": "Esta configuração de domínio lhe permitirá trabalhar <br> com endereços de e-mail do <i>%NAME%<\/i>.",
"WHITE_LIST_ALERT": "Filtrar com lista dos únicos usuários do domínio que terão acesso ao webmail.\nUse um espaço como delimitador.\n" "WHITE_LIST_ALERT": "Filtrar com lista dos únicos usuários do domínio que terão acesso ao webmail.\nUse um espaço como delimitador.\n"
}, },
"POPUPS_PLUGIN": { "POPUPS_PLUGIN": {

View file

@ -38,7 +38,7 @@
"LABEL_ALLOW_IDENTITIES": "Разрешить множественные профили", "LABEL_ALLOW_IDENTITIES": "Разрешить множественные профили",
"ALERT_DATA_ACCESS": "Папка данных RainLoop доступна. Пожалуйста, настройте свой веб-сервер так, чтобы скрыть папку данных с внешнего доступа. Подробнее здесь:", "ALERT_DATA_ACCESS": "Папка данных RainLoop доступна. Пожалуйста, настройте свой веб-сервер так, чтобы скрыть папку данных с внешнего доступа. Подробнее здесь:",
"ALERT_WARNING": "Внимание!", "ALERT_WARNING": "Внимание!",
"HTML_ALERT_WEAK_PASSWORD": "Вы используете пароль администратора по умолчанию.\n<br \/>\nПо соображениям безопасности, пожалуйста,\n<strong><a href=\"#\/security\">измените пароль<\/a><\/strong> прямо сейчас.\n" "HTML_ALERT_WEAK_PASSWORD": "Вы используете пароль администратора по умолчанию.\n<br>\nПо соображениям безопасности, пожалуйста,\n<strong><a href=\"#\/security\">измените пароль<\/a><\/strong> прямо сейчас.\n"
}, },
"TAB_LOGIN": { "TAB_LOGIN": {
"LEGEND_LOGIN_SCREEN": "Cтраница Входа", "LEGEND_LOGIN_SCREEN": "Cтраница Входа",
@ -66,14 +66,14 @@
"BUTTON_TEST": "Тест", "BUTTON_TEST": "Тест",
"ALERT_NOTICE": "Внимание!", "ALERT_NOTICE": "Внимание!",
"HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "Не используйте этот тип базы данных с большим числом активных пользователей.", "HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "Не используйте этот тип базы данных с большим числом активных пользователей.",
"HTML_ALERT_DOES_NOT_SUPPORTED": "Ваша система не поддерживает контакты.\n<br \/>\nВам необходимо установить или включить <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong> расширения на вашем сервере.\n" "HTML_ALERT_DOES_NOT_SUPPORTED": "Ваша система не поддерживает контакты.\n<br>\nВам необходимо установить или включить <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong> расширения на вашем сервере.\n"
}, },
"TAB_DOMAINS": { "TAB_DOMAINS": {
"LEGEND_DOMAINS": "Домены", "LEGEND_DOMAINS": "Домены",
"BUTTON_ADD_DOMAIN": "Добавить домен", "BUTTON_ADD_DOMAIN": "Добавить домен",
"BUTTON_ADD_ALIAS": "Добавить Алиас", "BUTTON_ADD_ALIAS": "Добавить Алиас",
"DELETE_ARE_YOU_SURE": "Вы уверены?", "DELETE_ARE_YOU_SURE": "Вы уверены?",
"HTML_DOMAINS_HELPER": "Список доменов к которым разрешен доступ.\n<br \/>\nНажмите на имя, чтобы настроить домен.\n" "HTML_DOMAINS_HELPER": "Список доменов к которым разрешен доступ.\n<br>\nНажмите на имя, чтобы настроить домен.\n"
}, },
"TAB_SECURITY": { "TAB_SECURITY": {
"LEGEND_SECURITY": "Безопасность", "LEGEND_SECURITY": "Безопасность",
@ -138,7 +138,7 @@
"BUTTON_CLOSE": "Закрыть", "BUTTON_CLOSE": "Закрыть",
"BUTTON_ADD": "Добавить", "BUTTON_ADD": "Добавить",
"BUTTON_UPDATE": "Обновить", "BUTTON_UPDATE": "Обновить",
"NEW_DOMAIN_DESC": "Эта конфигурация позволит вам работать <br \/>с <i>%NAME%<\/i> адресами.", "NEW_DOMAIN_DESC": "Эта конфигурация позволит вам работать <br>с <i>%NAME%<\/i> адресами.",
"WHITE_LIST_ALERT": "Список пользователей домена к которым разрешен доступ.\nИспользуйте пробел в качестве разделителя.\n" "WHITE_LIST_ALERT": "Список пользователей домена к которым разрешен доступ.\nИспользуйте пробел в качестве разделителя.\n"
}, },
"POPUPS_PLUGIN": { "POPUPS_PLUGIN": {

View file

@ -38,7 +38,7 @@
"LABEL_ALLOW_IDENTITIES": "Povoliť viaceré identity", "LABEL_ALLOW_IDENTITIES": "Povoliť viaceré identity",
"ALERT_DATA_ACCESS": "Adresár data je dostupný. Prosím skonfigurujte svoj webserver tak, aby bol adresár data nedostupný. Viac informácií:", "ALERT_DATA_ACCESS": "Adresár data je dostupný. Prosím skonfigurujte svoj webserver tak, aby bol adresár data nedostupný. Viac informácií:",
"ALERT_WARNING": "Upozornenie!", "ALERT_WARNING": "Upozornenie!",
"HTML_ALERT_WEAK_PASSWORD": "Používate predvolené administrátorské heslo.\n<br \/>\nKvôli bezpečnosti prosím\n<strong><a href=\"#\/security\">zmeňte<\/a><\/strong>\nheslo na iné.\n" "HTML_ALERT_WEAK_PASSWORD": "Používate predvolené administrátorské heslo.\n<br>\nKvôli bezpečnosti prosím\n<strong><a href=\"#\/security\">zmeňte<\/a><\/strong>\nheslo na iné.\n"
}, },
"TAB_LOGIN": { "TAB_LOGIN": {
"LEGEND_LOGIN_SCREEN": "Prihlasovacia obrazovka", "LEGEND_LOGIN_SCREEN": "Prihlasovacia obrazovka",
@ -66,14 +66,14 @@
"BUTTON_TEST": "Test", "BUTTON_TEST": "Test",
"ALERT_NOTICE": "Notice!", "ALERT_NOTICE": "Notice!",
"HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "Nepoužívajte tento typ databázy, ak máte veľký počet aktívnych používateľov.", "HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "Nepoužívajte tento typ databázy, ak máte veľký počet aktívnych používateľov.",
"HTML_ALERT_DOES_NOT_SUPPORTED": "Your system doesn't support contacts.\n<br \/>\nYou need to install or enable <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong> extension on your server.\n" "HTML_ALERT_DOES_NOT_SUPPORTED": "Your system doesn't support contacts.\n<br>\nYou need to install or enable <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong> extension on your server.\n"
}, },
"TAB_DOMAINS": { "TAB_DOMAINS": {
"LEGEND_DOMAINS": "Domény", "LEGEND_DOMAINS": "Domény",
"BUTTON_ADD_DOMAIN": "Pridať doménu", "BUTTON_ADD_DOMAIN": "Pridať doménu",
"BUTTON_ADD_ALIAS": "Pridať alias", "BUTTON_ADD_ALIAS": "Pridať alias",
"DELETE_ARE_YOU_SURE": "Ste si istí?", "DELETE_ARE_YOU_SURE": "Ste si istí?",
"HTML_DOMAINS_HELPER": "List of domains webmail is allowed to access.\n<br \/>\nClick on the name to configure the domain.\n" "HTML_DOMAINS_HELPER": "List of domains webmail is allowed to access.\n<br>\nClick on the name to configure the domain.\n"
}, },
"TAB_SECURITY": { "TAB_SECURITY": {
"LEGEND_SECURITY": "Bezpečnosť", "LEGEND_SECURITY": "Bezpečnosť",
@ -138,7 +138,7 @@
"BUTTON_CLOSE": "Zatvoriť", "BUTTON_CLOSE": "Zatvoriť",
"BUTTON_ADD": "Pridať", "BUTTON_ADD": "Pridať",
"BUTTON_UPDATE": "Aktualizovať", "BUTTON_UPDATE": "Aktualizovať",
"NEW_DOMAIN_DESC": "This domain configuration will allow you to work <br \/>with <i>%NAME%<\/i> email addresses.", "NEW_DOMAIN_DESC": "This domain configuration will allow you to work <br>with <i>%NAME%<\/i> email addresses.",
"WHITE_LIST_ALERT": "List of domain users webmail is allowed to access.\nUse a space as delimiter.\n" "WHITE_LIST_ALERT": "List of domain users webmail is allowed to access.\nUse a space as delimiter.\n"
}, },
"POPUPS_PLUGIN": { "POPUPS_PLUGIN": {

View file

@ -38,7 +38,7 @@
"LABEL_ALLOW_IDENTITIES": "Dovoli več identitet", "LABEL_ALLOW_IDENTITIES": "Dovoli več identitet",
"ALERT_DATA_ACCESS": "Mapa z RainLoop podatki je prosto ogledljiva. Prosimo, nastavite strežnik, da skrije mapo pred zunanjimi dostopi. Preberite več tukaj:", "ALERT_DATA_ACCESS": "Mapa z RainLoop podatki je prosto ogledljiva. Prosimo, nastavite strežnik, da skrije mapo pred zunanjimi dostopi. Preberite več tukaj:",
"ALERT_WARNING": "Pozor!", "ALERT_WARNING": "Pozor!",
"HTML_ALERT_WEAK_PASSWORD": "V uporabi je privzeto geslo administratorja\n<br \/>\nIz varnostnih razlogov\n<strong><a href=\"#\/security\">spremenite<\/a><\/strong>\ngeslo v nekaj drugega.\n" "HTML_ALERT_WEAK_PASSWORD": "V uporabi je privzeto geslo administratorja\n<br>\nIz varnostnih razlogov\n<strong><a href=\"#\/security\">spremenite<\/a><\/strong>\ngeslo v nekaj drugega.\n"
}, },
"TAB_LOGIN": { "TAB_LOGIN": {
"LEGEND_LOGIN_SCREEN": "Prijavni zaslon", "LEGEND_LOGIN_SCREEN": "Prijavni zaslon",
@ -66,14 +66,14 @@
"BUTTON_TEST": "Preizkus", "BUTTON_TEST": "Preizkus",
"ALERT_NOTICE": "Obvestilo!", "ALERT_NOTICE": "Obvestilo!",
"HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "Ta tip podatkovne baze ni priporočljiv za večje število uporabnikov.", "HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "Ta tip podatkovne baze ni priporočljiv za večje število uporabnikov.",
"HTML_ALERT_DOES_NOT_SUPPORTED": "Sistem ne podpira stikov.\n<br \/>\nNamestite ali omogočite <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong> razširitev na strežniku.\n" "HTML_ALERT_DOES_NOT_SUPPORTED": "Sistem ne podpira stikov.\n<br>\nNamestite ali omogočite <strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong> razširitev na strežniku.\n"
}, },
"TAB_DOMAINS": { "TAB_DOMAINS": {
"LEGEND_DOMAINS": "Domene", "LEGEND_DOMAINS": "Domene",
"BUTTON_ADD_DOMAIN": "Dodaj domeno", "BUTTON_ADD_DOMAIN": "Dodaj domeno",
"BUTTON_ADD_ALIAS": "Dodaj vzdevek", "BUTTON_ADD_ALIAS": "Dodaj vzdevek",
"DELETE_ARE_YOU_SURE": "Ste prepričani?", "DELETE_ARE_YOU_SURE": "Ste prepričani?",
"HTML_DOMAINS_HELPER": "Seznam domen, do katerih je omogočen dostop.\n<br \/>\nKliknite ime za konfiguracijo domene.\n" "HTML_DOMAINS_HELPER": "Seznam domen, do katerih je omogočen dostop.\n<br>\nKliknite ime za konfiguracijo domene.\n"
}, },
"TAB_SECURITY": { "TAB_SECURITY": {
"LEGEND_SECURITY": "Varnost", "LEGEND_SECURITY": "Varnost",
@ -138,7 +138,7 @@
"BUTTON_CLOSE": "Zapri", "BUTTON_CLOSE": "Zapri",
"BUTTON_ADD": "Dodaj", "BUTTON_ADD": "Dodaj",
"BUTTON_UPDATE": "Posodobi", "BUTTON_UPDATE": "Posodobi",
"NEW_DOMAIN_DESC": "Ta konfiguiracija domene bo omogočala delo <br \/>z <i>%NAME%<\/i> e-naslovi.", "NEW_DOMAIN_DESC": "Ta konfiguiracija domene bo omogočala delo <br>z <i>%NAME%<\/i> e-naslovi.",
"WHITE_LIST_ALERT": "Seznam uporabnikov domene, do katerih je omogočen dostop.\nUporabnike ločite s presledkom.\n" "WHITE_LIST_ALERT": "Seznam uporabnikov domene, do katerih je omogočen dostop.\nUporabnike ločite s presledkom.\n"
}, },
"POPUPS_PLUGIN": { "POPUPS_PLUGIN": {

View file

@ -38,7 +38,7 @@
"LABEL_ALLOW_IDENTITIES": "Tillåt multiidentiteter", "LABEL_ALLOW_IDENTITIES": "Tillåt multiidentiteter",
"ALERT_DATA_ACCESS": "RainLoops datamapp är åtkomstbar. Var vänlig konfigurera din webb-server för att förhindra extern åtkomst och synlighet. Läs mer här: ", "ALERT_DATA_ACCESS": "RainLoops datamapp är åtkomstbar. Var vänlig konfigurera din webb-server för att förhindra extern åtkomst och synlighet. Läs mer här: ",
"ALERT_WARNING": "Varning!", "ALERT_WARNING": "Varning!",
"HTML_ALERT_WEAK_PASSWORD": "Du använder standardlösenord.\n<br \/>\nFör säkerhetsskäl\n<strong><a href=\"#\/security\">ändra<\/a><\/strong>\nlösenord till något annat\n" "HTML_ALERT_WEAK_PASSWORD": "Du använder standardlösenord.\n<br>\nFör säkerhetsskäl\n<strong><a href=\"#\/security\">ändra<\/a><\/strong>\nlösenord till något annat\n"
}, },
"TAB_LOGIN": { "TAB_LOGIN": {
"LEGEND_LOGIN_SCREEN": "Inloggningsskärm", "LEGEND_LOGIN_SCREEN": "Inloggningsskärm",
@ -66,14 +66,14 @@
"BUTTON_TEST": "Test", "BUTTON_TEST": "Test",
"ALERT_NOTICE": "Notis", "ALERT_NOTICE": "Notis",
"HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "Använd inte denna typ av databas med ett stort antal aktiva användare.", "HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "Använd inte denna typ av databas med ett stort antal aktiva användare.",
"HTML_ALERT_DOES_NOT_SUPPORTED": "Systemet stöder inte kontakter\n<br \/>\nDu behöver installera eller aktivera <strong>SUB (SQLite\/MySQL\/PostgreSQL)<\/strong> förlängning på server.\n" "HTML_ALERT_DOES_NOT_SUPPORTED": "Systemet stöder inte kontakter\n<br>\nDu behöver installera eller aktivera <strong>SUB (SQLite\/MySQL\/PostgreSQL)<\/strong> förlängning på server.\n"
}, },
"TAB_DOMAINS": { "TAB_DOMAINS": {
"LEGEND_DOMAINS": "Domäner", "LEGEND_DOMAINS": "Domäner",
"BUTTON_ADD_DOMAIN": "Lägg till domän", "BUTTON_ADD_DOMAIN": "Lägg till domän",
"BUTTON_ADD_ALIAS": "Lägg till Alias", "BUTTON_ADD_ALIAS": "Lägg till Alias",
"DELETE_ARE_YOU_SURE": "Är du säker?", "DELETE_ARE_YOU_SURE": "Är du säker?",
"HTML_DOMAINS_HELPER": "Lista med domäner webmail tillåts access.\n<br \/>\nKlicka på namnet för att konfigurera domain.\n" "HTML_DOMAINS_HELPER": "Lista med domäner webmail tillåts access.\n<br>\nKlicka på namnet för att konfigurera domain.\n"
}, },
"TAB_SECURITY": { "TAB_SECURITY": {
"LEGEND_SECURITY": "Säkerhet", "LEGEND_SECURITY": "Säkerhet",
@ -138,7 +138,7 @@
"BUTTON_CLOSE": "Stäng", "BUTTON_CLOSE": "Stäng",
"BUTTON_ADD": "Lägg till", "BUTTON_ADD": "Lägg till",
"BUTTON_UPDATE": "Uppdatera", "BUTTON_UPDATE": "Uppdatera",
"NEW_DOMAIN_DESC": "Denna domän konfiguration gör att du kan arbeta <br \/>med <i>%NAME%<\/ i> e-postadresser.", "NEW_DOMAIN_DESC": "Denna domän konfiguration gör att du kan arbeta <br>med <i>%NAME%<\/ i> e-postadresser.",
"WHITE_LIST_ALERT": "Lista över domänanvändare som tillåts.\nAnvända ett utrymme som avgränsare.\n" "WHITE_LIST_ALERT": "Lista över domänanvändare som tillåts.\nAnvända ett utrymme som avgränsare.\n"
}, },
"POPUPS_PLUGIN": { "POPUPS_PLUGIN": {

View file

@ -38,7 +38,7 @@
"LABEL_ALLOW_IDENTITIES": "允许多重身份", "LABEL_ALLOW_IDENTITIES": "允许多重身份",
"ALERT_DATA_ACCESS": "数据文件夹可被访问。请配置您的 Web 服务器以阻止从外部访问数据文件夹。获取更多帮助:", "ALERT_DATA_ACCESS": "数据文件夹可被访问。请配置您的 Web 服务器以阻止从外部访问数据文件夹。获取更多帮助:",
"ALERT_WARNING": "警告!", "ALERT_WARNING": "警告!",
"HTML_ALERT_WEAK_PASSWORD": "您正在使用默认的管理员密码\n<br \/>\n安全起见请立即将密码\n<strong><a href=\"#\/security\">更改<\/a><\/strong>\n为其他的字符串。\n" "HTML_ALERT_WEAK_PASSWORD": "您正在使用默认的管理员密码\n<br>\n安全起见请立即将密码\n<strong><a href=\"#\/security\">更改<\/a><\/strong>\n为其他的字符串。\n"
}, },
"TAB_LOGIN": { "TAB_LOGIN": {
"LEGEND_LOGIN_SCREEN": "登录界面", "LEGEND_LOGIN_SCREEN": "登录界面",
@ -66,14 +66,14 @@
"BUTTON_TEST": "测试", "BUTTON_TEST": "测试",
"ALERT_NOTICE": "提示!", "ALERT_NOTICE": "提示!",
"HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "如果有大量的活跃用户,请不要选择此数据库类型。", "HTML_ALERT_DO_NOT_USE_THIS_DATABASE": "如果有大量的活跃用户,请不要选择此数据库类型。",
"HTML_ALERT_DOES_NOT_SUPPORTED": "你的系统不支持联系人\n<br \/>\n你需要在你的服务器上安装或启用<strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong> 组件。\n" "HTML_ALERT_DOES_NOT_SUPPORTED": "你的系统不支持联系人\n<br>\n你需要在你的服务器上安装或启用<strong>PDO (SQLite \/ MySQL \/ PostgreSQL)<\/strong> 组件。\n"
}, },
"TAB_DOMAINS": { "TAB_DOMAINS": {
"LEGEND_DOMAINS": "域名", "LEGEND_DOMAINS": "域名",
"BUTTON_ADD_DOMAIN": "添加域名", "BUTTON_ADD_DOMAIN": "添加域名",
"BUTTON_ADD_ALIAS": "添加别名", "BUTTON_ADD_ALIAS": "添加别名",
"DELETE_ARE_YOU_SURE": "你确定吗?", "DELETE_ARE_YOU_SURE": "你确定吗?",
"HTML_DOMAINS_HELPER": "允许访问的域名。\n<br \/>\n点击域名进行设置。\n" "HTML_DOMAINS_HELPER": "允许访问的域名。\n<br>\n点击域名进行设置。\n"
}, },
"TAB_SECURITY": { "TAB_SECURITY": {
"LEGEND_SECURITY": "安全", "LEGEND_SECURITY": "安全",
@ -138,7 +138,7 @@
"BUTTON_CLOSE": "关闭", "BUTTON_CLOSE": "关闭",
"BUTTON_ADD": "添加", "BUTTON_ADD": "添加",
"BUTTON_UPDATE": "更新", "BUTTON_UPDATE": "更新",
"NEW_DOMAIN_DESC": "此域名配置将允许你<br \/>和<i>%NAME%<\/i>电子邮件地址一起工作.", "NEW_DOMAIN_DESC": "此域名配置将允许你<br>和<i>%NAME%<\/i>电子邮件地址一起工作.",
"WHITE_LIST_ALERT": "允许访问的域用户;使用空格分隔。\n" "WHITE_LIST_ALERT": "允许访问的域用户;使用空格分隔。\n"
}, },
"POPUPS_PLUGIN": { "POPUPS_PLUGIN": {

View file

@ -1,8 +1,8 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en" dir="ltr"> <html lang="en" dir="ltr">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8">
<meta name="robots" content="noindex, nofollow, noodp" /> <meta name="robots" content="noindex, nofollow, noodp">
<title>{{ErrorTitle}}</title> <title>{{ErrorTitle}}</title>
<style type="text/css"> <style type="text/css">
html, body { html, body {
@ -32,7 +32,7 @@
</head> </head>
<body class="content"> <body class="content">
<h1>{{ErrorHeader}}</h1> <h1>{{ErrorHeader}}</h1>
<br /> <br>
<div class="error-desc"> <div class="error-desc">
<p>{{ErrorDesc}}</p> <p>{{ErrorDesc}}</p>
<a href="https://www.google.com/chrome/" target="_blank">Google Chrome</a> <a href="https://www.google.com/chrome/" target="_blank">Google Chrome</a>

View file

@ -1,10 +1,10 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en" dir="ltr"> <html lang="en" dir="ltr">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="robots" content="noindex, nofollow, noodp" /> <meta name="robots" content="noindex, nofollow, noodp">
<meta name="google" content="notranslate" /> <meta name="google" content="notranslate">
<title>{{ErrorTitle}}</title> <title>{{ErrorTitle}}</title>
<style type="text/css"> <style type="text/css">
@ -41,14 +41,14 @@
<div class="error-header"> <div class="error-header">
{{ErrorHeader}} {{ErrorHeader}}
</div> </div>
<br /> <br>
<div class="error-desc"> <div class="error-desc">
<br /> <br>
{{ErrorDesc}} {{ErrorDesc}}
<br /> <br>
<br /> <br>
<div style="{{BackLinkVisibilityStyle}}"> <div style="{{BackLinkVisibilityStyle}}">
<br /> <br>
<a href="{{BackHref}}">{{BackLink}}</a> <a href="{{BackHref}}">{{BackLink}}</a>
</div> </div>
</div> </div>

View file

@ -8,21 +8,21 @@
<input name="Login" required="" type="text" class="input-block-level" <input name="Login" required="" type="text" class="input-block-level"
autofocus="" autocomplete="username" autocorrect="off" autocapitalize="off" spellcheck="false" autofocus="" autocomplete="username" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="textInput: login, disable: submitRequest" data-bind="textInput: login, disable: submitRequest"
data-i18n="[placeholder]LOGIN/LABEL_LOGIN" /> data-i18n="[placeholder]LOGIN/LABEL_LOGIN">
</div> </div>
<div class="controls" data-bind="css: {'error': passwordError}"> <div class="controls" data-bind="css: {'error': passwordError}">
<span class="fontastic">🔑</span> <span class="fontastic">🔑</span>
<input name="Password" required="" type="password" class="input-block-level" <input name="Password" required="" type="password" class="input-block-level"
autocomplete="current-password" autocorrect="off" autocapitalize="off" spellcheck="false" autocomplete="current-password" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="textInput: password, disable: submitRequest" data-bind="textInput: password, disable: submitRequest"
data-i18n="[placeholder]LOGIN/LABEL_PASSWORD" /> data-i18n="[placeholder]LOGIN/LABEL_PASSWORD">
</div> </div>
<div class="controls"> <div class="controls">
<span class="fontastic"></span> <span class="fontastic"></span>
<input name="TOTP" type="text" pattern="[0-9]*" inputmode="numeric" class="input-block-level" <input name="TOTP" type="text" pattern="[0-9]*" inputmode="numeric" class="input-block-level"
autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="textInput: totp, disable: submitRequest" data-bind="textInput: totp, disable: submitRequest"
data-i18n="[placeholder]LOGIN/LABEL_TOTP" /> data-i18n="[placeholder]LOGIN/LABEL_TOTP">
<button class="fontastic" data-bind="command: submitCommand" data-i18n="[title]LOGIN/BUTTON_LOGIN"></button> <button class="fontastic" data-bind="command: submitCommand" data-i18n="[title]LOGIN/BUTTON_LOGIN"></button>
</div> </div>
<div id="plugin-Login-BottomControlGroup"></div> <div id="plugin-Login-BottomControlGroup"></div>

View file

@ -5,7 +5,7 @@
<div class="rl-logo"></div> <div class="rl-logo"></div>
<div> <div>
2022 © <span data-i18n="TAB_ABOUT/LABEL_ALL_RIGHTS_RESERVED"></span> 2022 © <span data-i18n="TAB_ABOUT/LABEL_ALL_RIGHTS_RESERVED"></span>
<br /> <br>
<a class="g-ui-link" href="https://snappymail.eu/" target="_blank" style="padding-left: 0">https://snappymail.eu/</a> <a class="g-ui-link" href="https://snappymail.eu/" target="_blank" style="padding-left: 0">https://snappymail.eu/</a>
</div> </div>
</div> </div>

View file

@ -9,10 +9,10 @@
<td data-bind="text: name"></td> <td data-bind="text: name"></td>
<td> <td>
<!-- ko if: 'checkbox' == type --> <!-- ko if: 'checkbox' == type -->
<input type="checkbox" data-bind="attr: {name: key, checked: value}" readonly=""/> <input type="checkbox" data-bind="attr: {name: key, checked: value}" readonly="">
<!-- /ko --> <!-- /ko -->
<!-- ko if: 'checkbox' != type --> <!-- ko if: 'checkbox' != type -->
<input data-bind="attr: {name: key, type: type}, value: value" readonly=""/> <input data-bind="attr: {name: key, type: type}, value: value" readonly="">
<!-- /ko --> <!-- /ko -->
<em data-bind="text: comment, visible: comment"></em> <em data-bind="text: comment, visible: comment"></em>
</td> </td>

View file

@ -39,27 +39,21 @@
<label data-i18n="TAB_CONTACTS/LABEL_STORAGE_DSN"></label> <label data-i18n="TAB_CONTACTS/LABEL_STORAGE_DSN"></label>
<div> <div>
<input type="text" class="span6" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" <input type="text" class="span6" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="value: pdoDsn, saveTrigger: pdoDsnTrigger" /> data-bind="value: pdoDsn, saveTrigger: pdoDsnTrigger" placeholder="mysql:host=127.0.0.1;port=3306;dbname=snappymail">
<blockquote style="margin: 0">
<p class="muted">
host=127.0.0.1;port=3306;dbname=snappymail<br />
host=127.0.0.1;port=5432;dbname=snappymail
</p>
</blockquote>
</div> </div>
</div> </div>
<div class="control-group"> <div class="control-group">
<label data-i18n="TAB_CONTACTS/LABEL_STORAGE_USER"></label> <label data-i18n="TAB_CONTACTS/LABEL_STORAGE_USER"></label>
<div> <div>
<input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" <input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="value: pdoUser, saveTrigger: pdoUserTrigger" /> data-bind="value: pdoUser, saveTrigger: pdoUserTrigger">
</div> </div>
</div> </div>
<div class="control-group"> <div class="control-group">
<label data-i18n="TAB_CONTACTS/LABEL_STORAGE_PASSWORD"></label> <label data-i18n="TAB_CONTACTS/LABEL_STORAGE_PASSWORD"></label>
<div> <div>
<input type="password" autocomplete="current-password" autocorrect="off" autocapitalize="off" spellcheck="false" <input type="password" autocomplete="current-password" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="value: pdoPassword, saveTrigger: pdoPasswordTrigger" /> data-bind="value: pdoPassword, saveTrigger: pdoPasswordTrigger">
</div> </div>
</div> </div>
<div class="control-group"> <div class="control-group">

View file

@ -5,17 +5,15 @@
<a class="btn" data-bind="click: createDomain" data-icon="✚" data-i18n="TAB_DOMAINS/BUTTON_ADD_DOMAIN"></a> <a class="btn" data-bind="click: createDomain" data-icon="✚" data-i18n="TAB_DOMAINS/BUTTON_ADD_DOMAIN"></a>
&nbsp;&nbsp; &nbsp;&nbsp;
<a class="btn" data-bind="click: createDomainAlias" data-icon="✚" data-i18n="TAB_DOMAINS/BUTTON_ADD_ALIAS"></a> <a class="btn" data-bind="click: createDomainAlias" data-icon="✚" data-i18n="TAB_DOMAINS/BUTTON_ADD_ALIAS"></a>
<br /> <br>
<br /> <br>
<blockquote> <p data-i18n="[html]TAB_DOMAINS/HTML_DOMAINS_HELPER"></p>
<p class="muted" data-i18n="[html]TAB_DOMAINS/HTML_DOMAINS_HELPER"></p>
</blockquote>
<table class="table table-hover b-admin-domains-list-table" data-bind="i18nUpdate: domains"> <table class="table table-hover b-admin-domains-list-table" data-bind="i18nUpdate: domains">
<colgroup> <colgroup>
<col /> <col>
<col style="width: 140px" /> <col style="width: 140px">
<col style="width: 1%" /> <col style="width: 1%">
<col style="width: 1%" /> <col style="width: 1%">
</colgroup> </colgroup>
<tbody data-bind="foreach: domains"> <tbody data-bind="foreach: domains">
<tr data-bind="css: {'disabled': disabled }"> <tr data-bind="css: {'disabled': disabled }">
@ -24,7 +22,7 @@
<span class="domain-alias" data-bind="if: alias">(alias)</span> <span class="domain-alias" data-bind="if: alias">(alias)</span>
</td> </td>
<td> <td>
<a class="btn btn-small btn-small-small btn-danger button-confirm-delete" data-bind="css: {'delete-access': askDelete()}, click: function(oDomain) { $root.deleteDomain(oDomain); }" <a class="btn btn-small btn-danger button-confirm-delete" data-bind="css: {'delete-access': askDelete()}, click: function(oDomain) { $root.deleteDomain(oDomain); }"
data-i18n="TAB_DOMAINS/DELETE_ARE_YOU_SURE"></a> data-i18n="TAB_DOMAINS/DELETE_ARE_YOU_SURE"></a>
</td> </td>
<td> <td>

View file

@ -1,14 +1,14 @@
<div class="row" data-bind="visible: weakPassword"> <div class="row" data-bind="visible: weakPassword">
<div class="alert alert-warning span8" style="margin-top: 10px;"> <div class="alert alert-warning span8" style="margin-top: 10px;">
<h4 data-i18n="TAB_GENERAL/ALERT_WARNING"></h4> <h4 data-i18n="TAB_GENERAL/ALERT_WARNING"></h4>
<br /> <br>
<div data-i18n="[html]TAB_GENERAL/HTML_ALERT_WEAK_PASSWORD"></div> <div data-i18n="[html]TAB_GENERAL/HTML_ALERT_WEAK_PASSWORD"></div>
</div> </div>
</div> </div>
<div class="row" data-bind="visible: dataFolderAccess"> <div class="row" data-bind="visible: dataFolderAccess">
<div class="alert alert-error span8" style="margin-top: 10px;"> <div class="alert alert-error span8" style="margin-top: 10px;">
<h4 data-i18n="TAB_GENERAL/ALERT_WARNING"></h4> <h4 data-i18n="TAB_GENERAL/ALERT_WARNING"></h4>
<br /> <br>
<span data-i18n="TAB_GENERAL/ALERT_DATA_ACCESS"></span> <span data-i18n="TAB_GENERAL/ALERT_DATA_ACCESS"></span>
&nbsp; &nbsp;
<a href="https://www.rainloop.net/docs/installation/#notice" <a href="https://www.rainloop.net/docs/installation/#notice"
@ -90,12 +90,12 @@
<div class="control-group"> <div class="control-group">
<label data-i18n="TAB_GENERAL/LABEL_ATTACHMENT_SIZE_LIMIT"></label> <label data-i18n="TAB_GENERAL/LABEL_ATTACHMENT_SIZE_LIMIT"></label>
<div> <div>
<input type="number" min="1" step="1" class="span1" data-bind="textInput: mainAttachmentLimit"/> <input type="number" min="1" step="1" class="span1" data-bind="textInput: mainAttachmentLimit">
&nbsp; &nbsp;
<span data-i18n="MB"></span> <span data-i18n="MB"></span>
<span data-bind="saveTrigger: attachmentLimitTrigger"></span> <span data-bind="saveTrigger: attachmentLimitTrigger"></span>
<br /> <br>
<br /> <br>
<div class="alert alert-info"> <div class="alert alert-info">
<b>PHP:</b>&nbsp;<!-- ko text: uploadDataDesc --><!-- /ko --> <b>PHP:</b>&nbsp;<!-- ko text: uploadDataDesc --><!-- /ko -->
</div> </div>

View file

@ -17,7 +17,7 @@
name: 'Checkbox', name: 'Checkbox',
params: { value: determineUserDomain, label: 'TAB_LOGIN/LABEL_DETERMINE_USER_DOMAIN' } params: { value: determineUserDomain, label: 'TAB_LOGIN/LABEL_DETERMINE_USER_DOMAIN' }
}"></div> }"></div>
<br /> <br>
<div data-bind="component: { <div data-bind="component: {
name: 'Checkbox', name: 'Checkbox',
params: { value: allowLanguagesOnLogin, label: 'TAB_LOGIN/LABEL_ALLOW_LANGUAGES_ON_LOGIN' } params: { value: allowLanguagesOnLogin, label: 'TAB_LOGIN/LABEL_ALLOW_LANGUAGES_ON_LOGIN' }
@ -26,7 +26,7 @@
name: 'Checkbox', name: 'Checkbox',
params: { enable: allowLanguagesOnLogin, value: determineUserLanguage, label: 'TAB_LOGIN/LABEL_DETERMINE_USER_LANGUAGE' } params: { enable: allowLanguagesOnLogin, value: determineUserLanguage, label: 'TAB_LOGIN/LABEL_DETERMINE_USER_LANGUAGE' }
}"></div> }"></div>
<br /> <br>
<div data-bind="component: { <div data-bind="component: {
name: 'Checkbox', name: 'Checkbox',
params: { value: hideSubmitButton, label: 'TAB_LOGIN/LABEL_HIDE_SUBMIT_BUTTON' } params: { value: hideSubmitButton, label: 'TAB_LOGIN/LABEL_HIDE_SUBMIT_BUTTON' }

View file

@ -18,7 +18,7 @@
params: { value: enabledPlugins, label: 'TAB_PACKAGES/LABEL_ENABLE_PLUGINS' } params: { value: enabledPlugins, label: 'TAB_PACKAGES/LABEL_ENABLE_PLUGINS' }
}"></div> }"></div>
<br /> <br>
<div data-bind="visible: packagesAvailableForUpdate().length"> <div data-bind="visible: packagesAvailableForUpdate().length">
<div class="legend"> <div class="legend">

View file

@ -1,8 +1,8 @@
<table class="table table-hover table-bordered" data-bind="i18nUpdate: f"> <table class="table table-hover table-bordered" data-bind="i18nUpdate: f">
<colgroup> <colgroup>
<col /> <col>
<col style="width: 100px" /> <col style="width: 100px">
<col style="width: 80px" /> <col style="width: 80px">
</colgroup> </colgroup>
<tbody data-bind="foreach: f"> <tbody data-bind="foreach: f">
<tr data-bind="css: {'disabled': !enabled() }"> <tr data-bind="css: {'disabled': !enabled() }">

View file

@ -1,15 +1,15 @@
<label data-bind="text: Label, visible: 5 !== Type"></label> <label data-bind="text: Label, visible: 5 !== Type"></label>
<!-- ko if: 0 === Type --> <!-- ko if: 0 === Type -->
<input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" <input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="value: value, attr: {placeholder: placeholder}" /> data-bind="value: value, attr: {placeholder: placeholder}">
<!-- /ko --> <!-- /ko -->
<!-- ko if: 1 === Type --> <!-- ko if: 1 === Type -->
<input type="number" step="1" <input type="number" step="1"
data-bind="value: value, attr: {placeholder: placeholder}" /> data-bind="value: value, attr: {placeholder: placeholder}">
<!-- /ko --> <!-- /ko -->
<!-- ko if: 3 === Type --> <!-- ko if: 3 === Type -->
<input type="password" autocomplete="current-password" autocorrect="off" autocapitalize="off" spellcheck="false" <input type="password" autocomplete="current-password" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="value: value, attr: {placeholder: placeholder}" /> data-bind="value: value, attr: {placeholder: placeholder}">
<!-- /ko --> <!-- /ko -->
<!-- ko if: 2 === Type --> <!-- ko if: 2 === Type -->
<div data-bind="component: { <div data-bind="component: {
@ -28,7 +28,7 @@
<!-- /ko --> <!-- /ko -->
<!-- ko if: 6 === Type --> <!-- ko if: 6 === Type -->
<input type="url" <input type="url"
data-bind="value: value, attr: {placeholder: placeholder}" /> data-bind="value: value, attr: {placeholder: placeholder}">
<!-- /ko --> <!-- /ko -->
<!-- ko if: '' !== Desc --> <!-- ko if: '' !== Desc -->
<span tabindex="0" class="help-block"><span data-bind="text: Desc"></span></span> <span tabindex="0" class="help-block"><span data-bind="text: Desc"></span></span>

View file

@ -25,28 +25,28 @@
<div class="control-group"> <div class="control-group">
<label data-i18n="TAB_SECURITY/LABEL_CURRENT_PASSWORD"></label> <label data-i18n="TAB_SECURITY/LABEL_CURRENT_PASSWORD"></label>
<input type="password" autocomplete="current-password" autocorrect="off" autocapitalize="off" spellcheck="false" <input type="password" autocomplete="current-password" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="textInput: adminPassword" /> data-bind="textInput: adminPassword">
</div> </div>
<div class="control-group" data-bind="css: {'error': adminLoginError}"> <div class="control-group" data-bind="css: {'error': adminLoginError}">
<label data-i18n="TAB_SECURITY/LABEL_NEW_LOGIN"></label> <label data-i18n="TAB_SECURITY/LABEL_NEW_LOGIN"></label>
<input type="text" autocomplete="username" autocorrect="off" autocapitalize="off" spellcheck="false" <input type="text" autocomplete="username" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="textInput: adminLogin" /> data-bind="textInput: adminLogin">
</div> </div>
<div class="control-group" data-bind="css: {'error': adminPasswordNewError}"> <div class="control-group" data-bind="css: {'error': adminPasswordNewError}">
<label data-i18n="TAB_SECURITY/LABEL_NEW_PASSWORD"></label> <label data-i18n="TAB_SECURITY/LABEL_NEW_PASSWORD"></label>
<input type="password" autocomplete="new-password" autocorrect="off" autocapitalize="off" spellcheck="false" <input type="password" autocomplete="new-password" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="textInput: adminPasswordNew" /> data-bind="textInput: adminPasswordNew">
</div> </div>
<div class="control-group" data-bind="css: {'error': adminPasswordNewError}"> <div class="control-group" data-bind="css: {'error': adminPasswordNewError}">
<label data-i18n="TAB_SECURITY/LABEL_REPEAT_PASSWORD"></label> <label data-i18n="TAB_SECURITY/LABEL_REPEAT_PASSWORD"></label>
<input type="password" autocomplete="new-password" autocorrect="off" autocapitalize="off" spellcheck="false" <input type="password" autocomplete="new-password" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="textInput: adminPasswordNew2" /> data-bind="textInput: adminPasswordNew2">
</div> </div>
<div class="control-group"> <div class="control-group">
<label data-i18n="LOGIN/LABEL_TOTP"></label> <label data-i18n="LOGIN/LABEL_TOTP"></label>
<input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" <input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
pattern="[A-Z2-7]{16,}" pattern="[A-Z2-7]{16,}"
data-bind="textInput: adminTOTP" /> data-bind="textInput: adminTOTP">
</div> </div>
<div class="control-group"> <div class="control-group">
<a class="btn" data-bind="command: saveNewAdminPasswordCommand, css: { 'btn-success': adminPasswordUpdateSuccess, 'btn-danger': adminPasswordUpdateError }" <a class="btn" data-bind="command: saveNewAdminPasswordCommand, css: { 'btn-success': adminPasswordUpdateSuccess, 'btn-danger': adminPasswordUpdateError }"
@ -67,7 +67,7 @@
}"></div> }"></div>
&nbsp;&nbsp; &nbsp;&nbsp;
<span style="color:red">(<span data-i18n="HINTS/UNSTABLE"></span>)</span> <span style="color:red">(<span data-i18n="HINTS/UNSTABLE"></span>)</span>
<br /> <br>
<div data-bind="component: { <div data-bind="component: {
name: 'Checkbox', name: 'Checkbox',
params: { params: {

View file

@ -8,9 +8,9 @@
<span data-i18n="POPUPS_DOMAIN/LABEL_NAME"></span> <span data-i18n="POPUPS_DOMAIN/LABEL_NAME"></span>
&nbsp; &nbsp;
<span style="color: #aaa">(<span data-i18n="POPUPS_DOMAIN/NAME_HELPER"></span>)</span> <span style="color: #aaa">(<span data-i18n="POPUPS_DOMAIN/NAME_HELPER"></span>)</span>
<br /> <br>
<input type="text" class="span4" autofocus="" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" <input type="text" class="span4" autofocus="" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="textInput: name" /> data-bind="textInput: name">
<div class="alert-error" data-bind="visible: '' !== savingError(), text: savingError"></div> <div class="alert-error" data-bind="visible: '' !== savingError(), text: savingError"></div>
</div> </div>
<div class="span5 domain-desc" data-bind="visible: '' !== domainDesc(), html: domainDesc"></div> <div class="span5 domain-desc" data-bind="visible: '' !== domainDesc(), html: domainDesc"></div>
@ -19,7 +19,7 @@
<form class="form-horizontal domain-form" action="#/" onsubmit="return false;"> <form class="form-horizontal domain-form" action="#/" onsubmit="return false;">
<div class="tabs"> <div class="tabs">
<input type="radio" name="helptabs" id="tab-help1" checked /> <input type="radio" name="helptabs" id="tab-help1" checked>
<label for="tab-help1" role="tab" tabindex="0" <label for="tab-help1" role="tab" tabindex="0"
data-bind="css: { 'testing-done': testingDone, 'testing-error': testingImapError }, tooltipErrorTip: testingImapErrorDesc" data-bind="css: { 'testing-done': testingDone, 'testing-error': testingImapError }, tooltipErrorTip: testingImapErrorDesc"
data-i18n="POPUPS_DOMAIN/LABEL_IMAP"></label> data-i18n="POPUPS_DOMAIN/LABEL_IMAP"></label>
@ -27,13 +27,13 @@
<div class="row"> <div class="row">
<div class="span3"> <div class="span3">
<span data-i18n="POPUPS_DOMAIN/LABEL_SERVER"></span> <span data-i18n="POPUPS_DOMAIN/LABEL_SERVER"></span>
<br /> <br>
<input type="text" class="span3" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" <input type="text" class="span3" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="textInput: imapServer, hasfocus: imapServerFocus" /> data-bind="textInput: imapServer, hasfocus: imapServerFocus">
</div> </div>
<div class="span2"> <div class="span2">
<span data-i18n="POPUPS_DOMAIN/LABEL_SECURE"></span> <span data-i18n="POPUPS_DOMAIN/LABEL_SECURE"></span>
<br /> <br>
<select class="span2" data-bind="value: imapSecure"> <select class="span2" data-bind="value: imapSecure">
<option value="0" data-i18n="POPUPS_DOMAIN/SECURE_OPTION_NONE"></option> <option value="0" data-i18n="POPUPS_DOMAIN/SECURE_OPTION_NONE"></option>
<option value="1" data-i18n="POPUPS_DOMAIN/SECURE_OPTION_SSL"></option> <option value="1" data-i18n="POPUPS_DOMAIN/SECURE_OPTION_SSL"></option>
@ -42,12 +42,12 @@
</div> </div>
<div class="span2"> <div class="span2">
<span data-i18n="POPUPS_DOMAIN/LABEL_PORT"></span> <span data-i18n="POPUPS_DOMAIN/LABEL_PORT"></span>
<br /> <br>
<input type="number" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" <input type="number" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
style="width:6em" data-bind="textInput: imapPort" /> style="width:6em" data-bind="textInput: imapPort">
</div> </div>
</div> </div>
<br /> <br>
<div data-bind="component: { <div data-bind="component: {
name: 'Checkbox', name: 'Checkbox',
params: { params: {
@ -60,7 +60,7 @@
<span style="color: #aaa">(user@domain.com → user)</span> <span style="color: #aaa">(user@domain.com → user)</span>
</div> </div>
<input type="radio" name="helptabs" id="tab-help2" /> <input type="radio" name="helptabs" id="tab-help2">
<label for="tab-help2" role="tab" tabindex="0" <label for="tab-help2" role="tab" tabindex="0"
data-bind="css: { 'testing-done': testingDone, 'testing-error': testingSmtpError }, tooltipErrorTip: testingSmtpErrorDesc" data-bind="css: { 'testing-done': testingDone, 'testing-error': testingSmtpError }, tooltipErrorTip: testingSmtpErrorDesc"
data-i18n="POPUPS_DOMAIN/LABEL_SMTP"></label> data-i18n="POPUPS_DOMAIN/LABEL_SMTP"></label>
@ -69,13 +69,13 @@
<div class="row"> <div class="row">
<div class="span3"> <div class="span3">
<span data-i18n="POPUPS_DOMAIN/LABEL_SERVER"></span> <span data-i18n="POPUPS_DOMAIN/LABEL_SERVER"></span>
<br /> <br>
<input type="text" class="span3" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" <input type="text" class="span3" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="textInput: smtpServer, hasfocus: smtpServerFocus" /> data-bind="textInput: smtpServer, hasfocus: smtpServerFocus">
</div> </div>
<div class="span2"> <div class="span2">
<span data-i18n="POPUPS_DOMAIN/LABEL_SECURE"></span> <span data-i18n="POPUPS_DOMAIN/LABEL_SECURE"></span>
<br /> <br>
<select class="span2" data-bind="value: smtpSecure"> <select class="span2" data-bind="value: smtpSecure">
<option value="0" data-i18n="POPUPS_DOMAIN/SECURE_OPTION_NONE"></option> <option value="0" data-i18n="POPUPS_DOMAIN/SECURE_OPTION_NONE"></option>
<option value="1" data-i18n="POPUPS_DOMAIN/SECURE_OPTION_SSL"></option> <option value="1" data-i18n="POPUPS_DOMAIN/SECURE_OPTION_SSL"></option>
@ -84,12 +84,12 @@
</div> </div>
<div class="span2"> <div class="span2">
<span data-i18n="POPUPS_DOMAIN/LABEL_PORT"></span> <span data-i18n="POPUPS_DOMAIN/LABEL_PORT"></span>
<br /> <br>
<input type="number" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" <input type="number" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
style="width:6em" data-bind="textInput: smtpPort" /> style="width:6em" data-bind="textInput: smtpPort">
</div> </div>
</div> </div>
<br /> <br>
<div data-bind="component: { <div data-bind="component: {
name: 'Checkbox', name: 'Checkbox',
params: { params: {
@ -107,7 +107,7 @@
value: smtpAuth value: smtpAuth
} }
}"></div> }"></div>
<br /> <br>
</div> </div>
<div data-bind="component: { <div data-bind="component: {
name: 'Checkbox', name: 'Checkbox',
@ -117,7 +117,7 @@
inline: true inline: true
} }
}"></div> }"></div>
<br /> <br>
<div data-bind="component: { <div data-bind="component: {
name: 'Checkbox', name: 'Checkbox',
params: { params: {
@ -130,7 +130,7 @@
<span style="color:red">(<span data-i18n="HINTS/BETA"></span>)</span> <span style="color:red">(<span data-i18n="HINTS/BETA"></span>)</span>
</div> </div>
<input type="radio" name="helptabs" id="tab-help3" /> <input type="radio" name="helptabs" id="tab-help3">
<label for="tab-help3" role="tab" tabindex="0" <label for="tab-help3" role="tab" tabindex="0"
data-bind="css: { 'testing-done': testingDone, 'testing-error': testingSieveError }, tooltipErrorTip: testingSieveErrorDesc"> data-bind="css: { 'testing-done': testingDone, 'testing-error': testingSieveError }, tooltipErrorTip: testingSieveErrorDesc">
<i class="icon-filter"></i> <i class="icon-filter"></i>
@ -150,13 +150,13 @@
<div class="row"> <div class="row">
<div class="span3"> <div class="span3">
<span data-i18n="POPUPS_DOMAIN/LABEL_SERVER"></span> <span data-i18n="POPUPS_DOMAIN/LABEL_SERVER"></span>
<br /> <br>
<input type="text" class="span3" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" <input type="text" class="span3" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="textInput: sieveServer, hasfocus: sieveServerFocus" /> data-bind="textInput: sieveServer, hasfocus: sieveServerFocus">
</div> </div>
<div class="span2"> <div class="span2">
<span data-i18n="POPUPS_DOMAIN/LABEL_SECURE"></span> <span data-i18n="POPUPS_DOMAIN/LABEL_SECURE"></span>
<br /> <br>
<select class="span2" data-bind="value: sieveSecure"> <select class="span2" data-bind="value: sieveSecure">
<option value="0" data-i18n="POPUPS_DOMAIN/SECURE_OPTION_NONE"></option> <option value="0" data-i18n="POPUPS_DOMAIN/SECURE_OPTION_NONE"></option>
<option value="1" data-i18n="POPUPS_DOMAIN/SECURE_OPTION_SSL"></option> <option value="1" data-i18n="POPUPS_DOMAIN/SECURE_OPTION_SSL"></option>
@ -165,15 +165,15 @@
</div> </div>
<div class="span2"> <div class="span2">
<span data-i18n="POPUPS_DOMAIN/LABEL_PORT"></span> <span data-i18n="POPUPS_DOMAIN/LABEL_PORT"></span>
<br /> <br>
<input type="number" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" <input type="number" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
style="width:6em" data-bind="textInput: sievePort" /> style="width:6em" data-bind="textInput: sievePort">
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<input type="radio" name="helptabs" id="tab-help4" /> <input type="radio" name="helptabs" id="tab-help4">
<label for="tab-help4" role="tab" tabindex="0" data-icon="👥" data-i18n="POPUPS_DOMAIN/BUTTON_WHITE_LIST"></label> <label for="tab-help4" role="tab" tabindex="0" data-icon="👥" data-i18n="POPUPS_DOMAIN/BUTTON_WHITE_LIST"></label>
<div class="tab-content" role="tabpanel" aria-hidden="true"> <div class="tab-content" role="tabpanel" aria-hidden="true">
<div class="alert" data-i18n="POPUPS_DOMAIN/WHITE_LIST_ALERT"></div> <div class="alert" data-i18n="POPUPS_DOMAIN/WHITE_LIST_ALERT"></div>

View file

@ -1,5 +1,5 @@
<input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" <input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="textInput: value, attr: {'placeholder': placeholder}, enable: enable, css: className" /> data-bind="textInput: value, attr: {'placeholder': placeholder}, enable: enable, css: className">
<!-- ko if: labeled --> <!-- ko if: labeled -->
&nbsp; &nbsp;
<span data-bind="attr: {'data-i18n': label}"></span> <span data-bind="attr: {'data-i18n': label}"></span>

View file

@ -11,14 +11,14 @@
<input name="Email" required="" type="text" class="input-block-level" pattern="[^@\s]+(@[^\s]+)?" inputmode="email" <input name="Email" required="" type="text" class="input-block-level" pattern="[^@\s]+(@[^\s]+)?" inputmode="email"
autofocus="" autocomplete="email" autocorrect="off" autocapitalize="off" spellcheck="false" autofocus="" autocomplete="email" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="textInput: email, disable: submitRequest" data-bind="textInput: email, disable: submitRequest"
data-i18n="[placeholder]GLOBAL/EMAIL" /> data-i18n="[placeholder]GLOBAL/EMAIL">
</div> </div>
<div class="controls" data-bind="css: {'error': passwordError}"> <div class="controls" data-bind="css: {'error': passwordError}">
<span class="fontastic">🔑</span> <span class="fontastic">🔑</span>
<input name="Password" required="" type="password" class="input-block-level" <input name="Password" required="" type="password" class="input-block-level"
autocomplete="current-password" autocorrect="off" autocapitalize="off" spellcheck="false" autocomplete="current-password" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="textInput: password, disable: submitRequest" data-bind="textInput: password, disable: submitRequest"
data-i18n="[placeholder]GLOBAL/PASSWORD" /> data-i18n="[placeholder]GLOBAL/PASSWORD">
<button class="fontastic" data-bind="command: submitCommand, visible: '' !== password()" data-i18n="[title]LOGIN/BUTTON_SIGN_IN"></button> <button class="fontastic" data-bind="command: submitCommand, visible: '' !== password()" data-i18n="[title]LOGIN/BUTTON_SIGN_IN"></button>
</div> </div>
<div id="plugin-Login-BottomControlGroup"></div> <div id="plugin-Login-BottomControlGroup"></div>

View file

@ -19,7 +19,7 @@
</a> </a>
</li> </li>
</ul> </ul>
<hr/> <hr>
<ul class="b-folders-user" data-bind="template: { name: 'MailFolderListItem', foreach: folderListVisible }"></ul> <ul class="b-folders-user" data-bind="template: { name: 'MailFolderListItem', foreach: folderListVisible }"></ul>
<div class="move-action-content-wrapper" data-bind="visible: moveAction"></div> <div class="move-action-content-wrapper" data-bind="visible: moveAction"></div>
</div> </div>

View file

@ -103,7 +103,7 @@
<i class="checkboxCheckAll fontastic" data-bind="text: checkAll() ? (isIncompleteChecked() ? '▣' : '☑') : '☐'"></i> <i class="checkboxCheckAll fontastic" data-bind="text: checkAll() ? (isIncompleteChecked() ? '▣' : '☑') : '☐'"></i>
<!-- ko if: allowSearch --> <!-- ko if: allowSearch -->
<div class="search-input-wrp"> <div class="search-input-wrp">
<input type="search" class="inputSearch" tabindex="-1" placeholder="Search" autocorrect="off" autocapitalize="off" data-i18n="[placeholder]GLOBAL/SEARCH" data-bind="value: inputProxyMessageListSearch, onEnter: searchEnterAction, hasfocus: inputMessageListSearchFocus" /> <input type="search" class="inputSearch" tabindex="-1" placeholder="Search" autocorrect="off" autocapitalize="off" data-i18n="[placeholder]GLOBAL/SEARCH" data-bind="value: inputProxyMessageListSearch, onEnter: searchEnterAction, hasfocus: inputMessageListSearchFocus">
<a class="closeSearch" data-bind="click: cancelSearch, visible: messageListSearchDesc()">×</a> <a class="closeSearch" data-bind="click: cancelSearch, visible: messageListSearchDesc()">×</a>
</div> </div>
<a class="btn buttonMoreSearch" data-bind="visible: allowSearchAdv, click: advancedSearchClick"></a> <a class="btn buttonMoreSearch" data-bind="visible: allowSearchAdv, click: advancedSearchClick"></a>

View file

@ -10,7 +10,7 @@
<a href="#" class="close" data-bind="click: function () { submitError('') }">×</a> <a href="#" class="close" data-bind="click: function () { submitError('') }">×</a>
<span data-bind="text: submitError"></span> <span data-bind="text: submitError"></span>
<div data-bind="visible: submitErrorAdditional"> <div data-bind="visible: submitErrorAdditional">
<br /> <br>
<span data-bind="text: submitErrorAdditional"></span> <span data-bind="text: submitErrorAdditional"></span>
</div> </div>
</div> </div>
@ -19,12 +19,12 @@
<strong style="margin-top: 5px;" data-bind="visible: !isNew(), text: email"></strong> <strong style="margin-top: 5px;" data-bind="visible: !isNew(), text: email"></strong>
<input type="email" class="input-xlarge" <input type="email" class="input-xlarge"
autofocus="" autocorrect="off" autocapitalize="off" spellcheck="false" autofocus="" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="visible: isNew, textInput: email, onEnter: addAccountCommand" /> data-bind="visible: isNew, textInput: email, onEnter: addAccountCommand">
</div> </div>
<div class="control-group" data-bind="css: {'error': passwordError}"> <div class="control-group" data-bind="css: {'error': passwordError}">
<label data-i18n="GLOBAL/PASSWORD"></label> <label data-i18n="GLOBAL/PASSWORD"></label>
<input type="password" class="input-xlarge" autocomplete="new-password" autocorrect="off" autocapitalize="off" spellcheck="false" <input type="password" class="input-xlarge" autocomplete="new-password" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="value: password, onEnter: addAccountCommand" /> data-bind="value: password, onEnter: addAccountCommand">
</div> </div>
</form> </form>
<footer> <footer>

View file

@ -9,22 +9,22 @@
<div class="control-group"> <div class="control-group">
<label data-i18n="GLOBAL/FROM"></label> <label data-i18n="GLOBAL/FROM"></label>
<input type="text" autofocus="" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" <input type="text" autofocus="" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="value: from, onEnter: searchCommand, onEsc: cancelCommand" /> data-bind="value: from, onEnter: searchCommand, onEsc: cancelCommand">
</div> </div>
<div class="control-group"> <div class="control-group">
<label data-i18n="GLOBAL/TO"></label> <label data-i18n="GLOBAL/TO"></label>
<input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" <input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="value: to, onEnter: searchCommand, onEsc: cancelCommand" /> data-bind="value: to, onEnter: searchCommand, onEsc: cancelCommand">
</div> </div>
<div class="control-group"> <div class="control-group">
<label data-i18n="GLOBAL/SUBJECT"></label> <label data-i18n="GLOBAL/SUBJECT"></label>
<input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" <input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="value: subject, onEnter: searchCommand, onEsc: cancelCommand" /> data-bind="value: subject, onEnter: searchCommand, onEsc: cancelCommand">
</div> </div>
<div class="control-group"> <div class="control-group">
<label data-i18n="SEARCH/LABEL_ADV_TEXT"></label> <label data-i18n="SEARCH/LABEL_ADV_TEXT"></label>
<input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" <input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="value: text, onEnter: searchCommand, onEsc: cancelCommand" /> data-bind="value: text, onEnter: searchCommand, onEsc: cancelCommand">
</div> </div>
</div> </div>
<div class="span4"> <div class="span4">

View file

@ -8,37 +8,11 @@
<span class="hide-mobile" data-i18n="GLOBAL/SAVE"></span> <span class="hide-mobile" data-i18n="GLOBAL/SAVE"></span>
</a> </a>
<a class="close" data-bind="click: tryToClosePopup" data-i18n="[title]GLOBAL/CANCEL">×</a>
<a class="minimize-custom" data-bind="click: skipCommand" data-i18n="[title]COMPOSE/BUTTON_MINIMIZE"></a>
<a class="btn btn-danger button-delete fontastic" data-bind="command: deleteCommand">🗑</a> <a class="btn btn-danger button-delete fontastic" data-bind="command: deleteCommand">🗑</a>
<span class="saved-text hide-mobile" data-bind="text: savedTimeText"></span> <span class="saved-text hide-mobile" data-bind="text: savedTimeText"></span>
</header>
<div class="modal-body">
<div class="b-header g-ui-user-select-none">
<table>
<tr>
<td data-i18n="GLOBAL/FROM"></td>
<td>
<!-- ko if: 1 < identitiesOptions().length -->
<div class="dropdown" style="display:inline-block" data-bind="registerBootstrapDropdown: true, openDropdownTrigger: identitiesDropdownTrigger">
<a class="dropdown-toggle e-identity multiply" href="#" tabindex="-1"
id="identity-label-id" role="button"
data-bind="text: currentIdentityView">
</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="identity-label-id" data-bind="foreach: identitiesOptions">
<li role="presentation">
<a tabindex="-1" href="#" data-bind="click: function (oIdentity) { $root.selectIdentity(oIdentity); return true; }, text: optText"></a>
</li>
</ul>
</div>
<!-- /ko -->
<!-- ko if: 2 > identitiesOptions().length -->
<span class="e-identity" data-bind="text: currentIdentityView"></span>
<!-- /ko -->
<div class="pull-right"> <div class="pull-right">
<a class="btn" data-i18n="GLOBAL/BCC" <a class="btn" data-i18n="GLOBAL/BCC" data-bind="visible: !showBcc(), click: function () { showBcc(true); }"></a>
data-bind="visible: !showBcc(), click: function () { showBcc(true); }"></a>
<a class="btn fontastic" data-bind="visible: allowContacts, command: contactsCommand" data-i18n="[title]GLOBAL/CONTACTS">📇</a> <a class="btn fontastic" data-bind="visible: allowContacts, command: contactsCommand" data-i18n="[title]GLOBAL/CONTACTS">📇</a>
<div class="btn-group dropdown" data-bind="registerBootstrapDropdown: true" style="display:inline-block;vertical-align:top"> <div class="btn-group dropdown" data-bind="registerBootstrapDropdown: true" style="display:inline-block;vertical-align:top">
<a class="btn dropdown-toggle fontastic"></a> <a class="btn dropdown-toggle fontastic"></a>
@ -81,7 +55,27 @@
</li> </li>
</ul> </ul>
</div> </div>
</span> <a class="minimize-custom" data-bind="click: skipCommand" data-i18n="[title]COMPOSE/BUTTON_MINIMIZE"></a>
<a class="close" data-bind="click: tryToClosePopup" data-i18n="[title]GLOBAL/CANCEL">×</a>
</div>
</header>
<div class="modal-body">
<div class="b-header g-ui-user-select-none">
<table>
<tr>
<td data-i18n="GLOBAL/FROM"></td>
<td>
<input type="text" data-bind="textInput: from" style="width:calc(100% - 20px)">
<!-- ko if: 1 < identitiesOptions().length -->
<div class="dropdown" style="display:inline-block" data-bind="registerBootstrapDropdown: true, openDropdownTrigger: identitiesDropdownTrigger">
<a class="dropdown-toggle" href="#" tabindex="-1" id="identity-toggle" role="button"></a>
<ul class="dropdown-menu right-edge" role="menu" aria-labelledby="identity-toggle" data-bind="foreach: identitiesOptions">
<li role="presentation">
<a tabindex="-1" href="#" data-bind="click: function (oIdentity) { $root.selectIdentity(oIdentity); return true; }, text: optText"></a>
</li>
</ul>
</div>
<!-- /ko -->
</td> </td>
</tr> </tr>
<tr> <tr>
@ -90,31 +84,31 @@
data-i18n="GLOBAL/TO"></label> data-i18n="GLOBAL/TO"></label>
</td> </td>
<td> <td>
<input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" data-bind="emailsTags: to, autoCompleteSource: emailsSource" /> <input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" data-bind="emailsTags: to, autoCompleteSource: emailsSource">
</td> </td>
</tr> </tr>
<tr class="cc-row" data-bind="visible: showCc"> <tr class="cc-row" data-bind="visible: showCc">
<td data-i18n="GLOBAL/CC"></div> <td data-i18n="GLOBAL/CC"></div>
<td> <td>
<input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" data-bind="emailsTags: cc, autoCompleteSource: emailsSource" /> <input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" data-bind="emailsTags: cc, autoCompleteSource: emailsSource">
</td> </td>
</tr> </tr>
<tr class="bcc-row" data-bind="visible: showBcc"> <tr class="bcc-row" data-bind="visible: showBcc">
<td data-i18n="GLOBAL/BCC"></div> <td data-i18n="GLOBAL/BCC"></div>
<td> <td>
<input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" data-bind="emailsTags: bcc, autoCompleteSource: emailsSource" /> <input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" data-bind="emailsTags: bcc, autoCompleteSource: emailsSource">
</td> </td>
</tr> </tr>
<tr class="reply-to-row" data-bind="visible: showReplyTo"> <tr class="reply-to-row" data-bind="visible: showReplyTo">
<td data-i18n="GLOBAL/REPLY_TO"></div> <td data-i18n="GLOBAL/REPLY_TO"></div>
<td> <td>
<input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" data-bind="emailsTags: replyTo, autoCompleteSource: emailsSource" /> <input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" data-bind="emailsTags: replyTo, autoCompleteSource: emailsSource">
</td> </td>
</tr> </tr>
<tr> <tr>
<td data-i18n="GLOBAL/SUBJECT"></div> <td data-i18n="GLOBAL/SUBJECT"></div>
<td> <td>
<input type="text" size="70" autocomplete="off" data-bind="textInput: subject" /> <input type="text" size="70" autocomplete="off" data-bind="textInput: subject">
</td> </td>
</tr> </tr>
</table> </table>

View file

@ -44,7 +44,7 @@
</header> </header>
<div class="modal-body"> <div class="modal-body">
<div class="b-list-toolbar"> <div class="b-list-toolbar">
<input type="search" class="e-search" placeholder="Search" autocorrect="off" autocapitalize="off" data-i18n="[placeholder]GLOBAL/SEARCH" data-bind="value: search" /> <input type="search" class="e-search" placeholder="Search" autocorrect="off" autocapitalize="off" data-i18n="[placeholder]GLOBAL/SEARCH" data-bind="value: search">
</div> </div>
<div class="b-list-content g-ui-user-select-none" data-bind="css: {'hideContactListCheckbox': !useCheckboxesInList()}"> <div class="b-list-content g-ui-user-select-none" data-bind="css: {'hideContactListCheckbox': !useCheckboxesInList()}">
<div class="content"> <div class="content">
@ -132,7 +132,7 @@
<span data-bind="text: value"></span> <span data-bind="text: value"></span>
<input type="text" <input type="text"
autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="value: value, hasfocus: focused, valueUpdate: 'keyup', attr: {'placeholder': placeholderValue}" /> data-bind="value: value, hasfocus: focused, valueUpdate: 'keyup', attr: {'placeholder': placeholderValue}">
</div> </div>
</div> </div>
<div data-bind="visible: viewPropertiesOther().length, foreach: viewPropertiesOther"> <div data-bind="visible: viewPropertiesOther().length, foreach: viewPropertiesOther">
@ -141,7 +141,7 @@
<span data-bind="text: value"></span> <span data-bind="text: value"></span>
<input type="text" <input type="text"
autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="value: value, hasfocus: focused, valueUpdate: 'keyup', attr: {'placeholder': placeholderValue}" /> data-bind="value: value, hasfocus: focused, valueUpdate: 'keyup', attr: {'placeholder': placeholderValue}">
<!-- /ko --> <!-- /ko -->
<!-- ko if: largeValue --> <!-- ko if: largeValue -->
<span data-bind="text: value"></span> <span data-bind="text: value"></span>
@ -161,7 +161,7 @@
<span data-bind="text: value"></span> <span data-bind="text: value"></span>
<input type="text" <input type="text"
autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="value: value, hasfocus: focused, valueUpdate: 'keyup'" /> data-bind="value: value, hasfocus: focused, valueUpdate: 'keyup'">
</div> </div>
</div> </div>
<a href="#" class="g-ui-link add-link" data-bind="visible: !viewReadOnly(), click: addNewEmail" data-i18n="CONTACTS/LINK_ADD_EMAIL"></a> <a href="#" class="g-ui-link add-link" data-bind="visible: !viewReadOnly(), click: addNewEmail" data-i18n="CONTACTS/LINK_ADD_EMAIL"></a>
@ -175,7 +175,7 @@
<span data-bind="text: value"></span> <span data-bind="text: value"></span>
<input type="text" <input type="text"
autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="value: value, hasfocus: focused, valueUpdate: 'keyup'" /> data-bind="value: value, hasfocus: focused, valueUpdate: 'keyup'">
</div> </div>
</div> </div>
</div> </div>
@ -188,7 +188,7 @@
<span data-bind="text: value"></span> <span data-bind="text: value"></span>
<input type="text" placeholder="https://" <input type="text" placeholder="https://"
autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="value: value, hasfocus: focused, valueUpdate: 'keyup'" /> data-bind="value: value, hasfocus: focused, valueUpdate: 'keyup'">
</div> </div>
</div> </div>
</div> </div>

View file

@ -13,8 +13,7 @@
<input type="text" class="span5" <input type="text" class="span5"
data-bind="value: name, hasfocus: nameFocused" data-bind="value: name, hasfocus: nameFocused"
autocorrect="off" autocapitalize="off" spellcheck="false" autocorrect="off" autocapitalize="off" spellcheck="false"
data-i18n="[placeholder]GLOBAL/NAME" data-i18n="[placeholder]GLOBAL/NAME">
/>
</div> </div>
<div class="legend" data-i18n="POPUPS_FILTER/LEGEND_CONDITIONS"></div> <div class="legend" data-i18n="POPUPS_FILTER/LEGEND_CONDITIONS"></div>

View file

@ -9,10 +9,10 @@
<i class="fontastic" style="color:red"></i> <i class="fontastic" style="color:red"></i>
&nbsp;&nbsp; &nbsp;&nbsp;
<strong data-i18n="[html]POPUPS_CLEAR_FOLDER/DANGER_DESC_WARNING"></strong> <strong data-i18n="[html]POPUPS_CLEAR_FOLDER/DANGER_DESC_WARNING"></strong>
<br /> <br>
<br /> <br>
<span data-bind="html: dangerDescHtml"></span> <span data-bind="html: dangerDescHtml"></span>
<br /> <br>
<span data-i18n="[html]POPUPS_CLEAR_FOLDER/DANGER_DESC_HTML_2"></span> <span data-i18n="[html]POPUPS_CLEAR_FOLDER/DANGER_DESC_HTML_2"></span>
</div> </div>
<footer> <footer>

View file

@ -13,7 +13,7 @@
<label data-i18n="GLOBAL/NAME"></label> <label data-i18n="GLOBAL/NAME"></label>
<input type="text" <input type="text"
autofocus="" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" autofocus="" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="textInput: folderName, onEnter: createFolderCommand" /> data-bind="textInput: folderName, onEnter: createFolderCommand">
</div> </div>
<div class="control-group" data-bind="component: { <div class="control-group" data-bind="component: {
name: 'Checkbox', name: 'Checkbox',

View file

@ -17,26 +17,26 @@
<div class="textEmail" data-bind="text: email, visible: owner"></div> <div class="textEmail" data-bind="text: email, visible: owner"></div>
<input type="email" class="input-xlarge" autofocus="" <input type="email" class="input-xlarge" autofocus=""
autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="visible: !owner(), value: email, onEnter: addOrEditIdentityCommand, hasfocus: emailFocused" /> data-bind="visible: !owner(), value: email, onEnter: addOrEditIdentityCommand, hasfocus: emailFocused">
</div> </div>
</div> </div>
<div class="control-group"> <div class="control-group">
<label data-i18n="GLOBAL/NAME"></label> <label data-i18n="GLOBAL/NAME"></label>
<input type="text" class="input-xlarge" <input type="text" class="input-xlarge"
autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="value: name, onEnter: addOrEditIdentityCommand" /> data-bind="value: name, onEnter: addOrEditIdentityCommand">
</div> </div>
<div class="control-group" data-bind="visible: showReplyTo, css: {'error': replyToHasError}"> <div class="control-group" data-bind="visible: showReplyTo, css: {'error': replyToHasError}">
<label data-i18n="GLOBAL/REPLY_TO"></label> <label data-i18n="GLOBAL/REPLY_TO"></label>
<input type="text" class="inputReplyTo input-xlarge" <input type="text" class="inputReplyTo input-xlarge"
autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="value: replyTo, onEnter: addOrEditIdentityCommand, hasfocus: replyToFocused" /> data-bind="value: replyTo, onEnter: addOrEditIdentityCommand, hasfocus: replyToFocused">
</div> </div>
<div class="control-group" data-bind="visible: showBcc, css: {'error': bccHasError}"> <div class="control-group" data-bind="visible: showBcc, css: {'error': bccHasError}">
<label data-i18n="GLOBAL/BCC"></label> <label data-i18n="GLOBAL/BCC"></label>
<input type="text" class="inputBcc input-xlarge" <input type="text" class="inputBcc input-xlarge"
autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="value: bcc, onEnter: addOrEditIdentityCommand, hasfocus: bccFocused" /> data-bind="value: bcc, onEnter: addOrEditIdentityCommand, hasfocus: bccFocused">
</div> </div>
<div class="control-group" data-bind="visible: !showReplyTo() || !showBcc()"> <div class="control-group" data-bind="visible: !showReplyTo() || !showBcc()">
<div> <div>
@ -52,7 +52,7 @@
</div> </div>
</div> </div>
</div> </div>
<hr /> <hr>
<div class="control-group g-ui-user-select-none"> <div class="control-group g-ui-user-select-none">
<div data-bind="component: { <div data-bind="component: {
name: 'Checkbox', name: 'Checkbox',

View file

@ -6,7 +6,7 @@
<div class="tabs"> <div class="tabs">
<input type="radio" name="helptabs" id="tab-help1" checked /> <input type="radio" name="helptabs" id="tab-help1" checked>
<label for="tab-help1" <label for="tab-help1"
role="tab" role="tab"
aria-selected="true" aria-selected="true"
@ -26,7 +26,7 @@
</table> </table>
</div> </div>
<input type="radio" name="helptabs" id="tab-help2" /> <input type="radio" name="helptabs" id="tab-help2">
<label for="tab-help2" <label for="tab-help2"
role="tab" role="tab"
aria-selected="false" aria-selected="false"
@ -53,7 +53,7 @@
</table> </table>
</div> </div>
<input type="radio" name="helptabs" id="tab-help3" /> <input type="radio" name="helptabs" id="tab-help3">
<label for="tab-help3" <label for="tab-help3"
role="tab" role="tab"
aria-selected="false" aria-selected="false"
@ -73,7 +73,7 @@
</table> </table>
</div> </div>
<input type="radio" name="helptabs" id="tab-help4" /> <input type="radio" name="helptabs" id="tab-help4">
<label for="tab-help4" <label for="tab-help4"
role="tab" role="tab"
aria-selected="false" aria-selected="false"

View file

@ -8,12 +8,12 @@
<span data-bind="text: submitError"></span> <span data-bind="text: submitError"></span>
</div> </div>
<!-- Disable stupid browser password autofill --> <!-- Disable stupid browser password autofill -->
<input type="password" style="display:none"/> <input type="password" style="display:none">
<div class="control-group" data-bind="css: {'error': emailError}"> <div class="control-group" data-bind="css: {'error': emailError}">
<label data-i18n="GLOBAL/EMAIL"></label> <label data-i18n="GLOBAL/EMAIL"></label>
<input type="email" required="" class="input-xlarge" <input type="email" required="" class="input-xlarge"
autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
list="emailaddresses" data-bind="value: email" /> list="emailaddresses" data-bind="value: email">
<datalist id="emailaddresses"> <datalist id="emailaddresses">
<!-- ko foreach: identities --> <!-- ko foreach: identities -->
<option data-bind="attr:{value:email}"></option> <option data-bind="attr:{value:email}"></option>
@ -24,13 +24,13 @@
<label data-i18n="GLOBAL/NAME"></label> <label data-i18n="GLOBAL/NAME"></label>
<input type="text" required="" class="input-xlarge" <input type="text" required="" class="input-xlarge"
autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="value: name" /> data-bind="value: name">
</div> </div>
<div class="control-group"> <div class="control-group">
<label data-i18n="GLOBAL/PASSWORD"></label> <label data-i18n="GLOBAL/PASSWORD"></label>
<input type="password" required="" class="input-xlarge" <input type="password" required="" class="input-xlarge"
autocomplete="new-password" autocorrect="off" autocapitalize="off" spellcheck="false" autocomplete="new-password" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="value: password" /> data-bind="value: password">
</div> </div>
<div class="control-group"> <div class="control-group">
<label data-i18n="OPENPGP/LABEL_KEY_TYPE"></label> <label data-i18n="OPENPGP/LABEL_KEY_TYPE"></label>
@ -44,7 +44,7 @@
value: backupPublicKey value: backupPublicKey
} }
}"></div> }"></div>
<br/> <br>
<div data-bind="component: { <div data-bind="component: {
name: 'Checkbox', name: 'Checkbox',
params: { params: {
@ -52,7 +52,7 @@
value: backupPrivateKey value: backupPrivateKey
} }
}"></div> }"></div>
<br/> <br>
<div data-bind="visible: canGnuPG, component: { <div data-bind="visible: canGnuPG, component: {
name: 'Checkbox', name: 'Checkbox',
params: { params: {
@ -60,7 +60,7 @@
value: saveGnuPGPublic value: saveGnuPGPublic
} }
}"></div> }"></div>
<br/> <br>
<div data-bind="visible: canGnuPG, component: { <div data-bind="visible: canGnuPG, component: {
name: 'Checkbox', name: 'Checkbox',
params: { params: {

View file

@ -16,7 +16,7 @@
value: saveServer value: saveServer
} }
}"></div> }"></div>
<br/> <br>
--> -->
<div data-bind="visible: canGnuPG, component: { <div data-bind="visible: canGnuPG, component: {
name: 'Checkbox', name: 'Checkbox',

View file

@ -13,8 +13,7 @@
<input type="text" class="span5" <input type="text" class="span5"
data-bind="value: name, hasfocus: !exists()" data-bind="value: name, hasfocus: !exists()"
autocorrect="off" autocapitalize="off" spellcheck="false" autocorrect="off" autocapitalize="off" spellcheck="false"
data-i18n="[placeholder]GLOBAL/NAME" data-i18n="[placeholder]GLOBAL/NAME">
/>
</div> </div>
<div class="alert g-ui-user-select-none" data-bind="visible: hasChanges" data-icon="⚠" data-i18n="POPUPS_SIEVE_SCRIPT/CHANGES_NEED_TO_BE_SAVED_DESC"></div> <div class="alert g-ui-user-select-none" data-bind="visible: hasChanges" data-icon="⚠" data-i18n="POPUPS_SIEVE_SCRIPT/CHANGES_NEED_TO_BE_SAVED_DESC"></div>
@ -33,11 +32,11 @@
<table class="table table-hover list-table filters-list g-ui-user-select-none" <table class="table table-hover list-table filters-list g-ui-user-select-none"
data-bind="i18nUpdate: filters"> data-bind="i18nUpdate: filters">
<colgroup> <colgroup>
<col style="width: 30px" /> <col style="width: 30px">
<col style="width: 16px" /> <col style="width: 16px">
<col /> <col>
<col style="width: 140px" /> <col style="width: 140px">
<col style="width: 1em" /> <col style="width: 1em">
</colgroup> </colgroup>
<tbody data-bind="foreach: filters"> <tbody data-bind="foreach: filters">
<tr class="filter-item" draggable="true" data-bind="sortableItem: { list: $parent.filters }"> <tr class="filter-item" draggable="true" data-bind="sortableItem: { list: $parent.filters }">
@ -49,7 +48,7 @@
<span class="filter-sub-name" data-bind="text: nameSub()"></span> <span class="filter-sub-name" data-bind="text: nameSub()"></span>
</td> </td>
<td> <td>
<a class="btn btn-small btn-small-small btn-danger button-confirm-delete" data-bind="css: {'delete-access': askDelete()}, click: function(oFilter) { $root.deleteFilter(oFilter); }" <a class="btn btn-small btn-danger button-confirm-delete" data-bind="css: {'delete-access': askDelete()}, click: function(oFilter) { $root.deleteFilter(oFilter); }"
data-i18n="GLOBAL/ARE_YOU_SURE"></a> data-i18n="GLOBAL/ARE_YOU_SURE"></a>
</td> </td>
<td> <td>

View file

@ -23,7 +23,7 @@
<span class="account-name" data-bind="text: email"></span> <span class="account-name" data-bind="text: email"></span>
</td> </td>
<td> <td>
<a class="btn btn-small btn-small-small btn-danger button-confirm-delete" data-bind="css: {'delete-access': askDelete}, click: function(oAccount) { $root.deleteAccount(oAccount); }" <a class="btn btn-small btn-danger button-confirm-delete" data-bind="css: {'delete-access': askDelete}, click: function(oAccount) { $root.deleteAccount(oAccount); }"
data-i18n="GLOBAL/ARE_YOU_SURE"></a> data-i18n="GLOBAL/ARE_YOU_SURE"></a>
</td> </td>
<td> <td>
@ -52,7 +52,7 @@
<span class="identity-default" data-bind="visible: 0 === $index()" data-i18n="SETTINGS_ACCOUNTS/DEFAULT_IDENTITY_LABEL"></span> <span class="identity-default" data-bind="visible: 0 === $index()" data-i18n="SETTINGS_ACCOUNTS/DEFAULT_IDENTITY_LABEL"></span>
</td> </td>
<td> <td>
<a class="btn btn-small btn-small-small btn-danger button-confirm-delete" data-bind="visible: canBeDeleted, css: {'delete-access': askDelete}, click: function(oIdentity) { $root.deleteIdentity(oIdentity); }" <a class="btn btn-small btn-danger button-confirm-delete" data-bind="visible: canBeDeleted, css: {'delete-access': askDelete}, click: function(oIdentity) { $root.deleteIdentity(oIdentity); }"
data-i18n="GLOBAL/ARE_YOU_SURE"></a> data-i18n="GLOBAL/ARE_YOU_SURE"></a>
</td> </td>
<td> <td>

View file

@ -24,17 +24,17 @@
<div class="control-group"> <div class="control-group">
<label data-i18n="SETTINGS_CONTACTS/LABEL_CONTACTS_SYNC_AB_URL"></label> <label data-i18n="SETTINGS_CONTACTS/LABEL_CONTACTS_SYNC_AB_URL"></label>
<input type="text" class="input-xxlarge" autocomplete="off" autocorrect="off" autocapitalize="off" <input type="text" class="input-xxlarge" autocomplete="off" autocorrect="off" autocapitalize="off"
spellcheck="false" data-bind="value: contactsSyncUrl" placeholder="https://" /> spellcheck="false" data-bind="value: contactsSyncUrl" placeholder="https://">
</div> </div>
<div class="control-group"> <div class="control-group">
<label data-i18n="SETTINGS_CONTACTS/LABEL_CONTACTS_SYNC_USER"></label> <label data-i18n="SETTINGS_CONTACTS/LABEL_CONTACTS_SYNC_USER"></label>
<input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" <input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="value: contactsSyncUser" /> data-bind="value: contactsSyncUser">
</div> </div>
<div class="control-group"> <div class="control-group">
<label data-i18n="GLOBAL/PASSWORD"></label> <label data-i18n="GLOBAL/PASSWORD"></label>
<input type="password" autocomplete="current-password" autocorrect="off" autocapitalize="off" <input type="password" autocomplete="current-password" autocorrect="off" autocapitalize="off"
spellcheck="false" data-bind="value: contactsSyncPass" /> spellcheck="false" data-bind="value: contactsSyncPass">
</div> </div>
</div> </div>

View file

@ -9,10 +9,10 @@
<table class="table table-hover list-table g-ui-user-select-none" <table class="table table-hover list-table g-ui-user-select-none"
data-bind="i18nUpdate: scripts"> data-bind="i18nUpdate: scripts">
<colgroup> <colgroup>
<col style="width: 30px" /> <col style="width: 30px">
<col /> <col>
<col style="width: 140px" /> <col style="width: 140px">
<col style="width: 1em" /> <col style="width: 1em">
</colgroup> </colgroup>
<tbody data-bind="foreach: scripts"> <tbody data-bind="foreach: scripts">
<tr class="script-item"> <tr class="script-item">
@ -21,7 +21,7 @@
</td> </td>
<td class="e-action" class="script-name" data-bind="text: name()"></td> <td class="e-action" class="script-name" data-bind="text: name()"></td>
<td> <td>
<a class="btn btn-small btn-small-small btn-danger button-confirm-delete" data-bind="css: {'delete-access': askDelete()}, click: function(oScript) { $root.deleteScript(oScript); }" <a class="btn btn-small btn-danger button-confirm-delete" data-bind="css: {'delete-access': askDelete()}, click: function(oScript) { $root.deleteScript(oScript); }"
data-i18n="GLOBAL/ARE_YOU_SURE"></a> data-i18n="GLOBAL/ARE_YOU_SURE"></a>
</td> </td>
<td> <td>

View file

@ -1,6 +1,6 @@
<div class="control-group" data-bind="css: {'error': actionValueError}"> <div class="control-group" data-bind="css: {'error': actionValueError}">
<input type="text" class="span3" data-bind="value: actionValue" <input type="text" class="span3" data-bind="value: actionValue"
data-i18n="[placeholder]GLOBAL/EMAIL" /> data-i18n="[placeholder]GLOBAL/EMAIL">
</div> </div>
<div class="control-group"> <div class="control-group">
<div> <div>

Some files were not shown because too many files have changed in this diff Show more