diff --git a/dev/App/Admin.js b/dev/App/Admin.js
index 3c675d2b1..d5f5f4bf2 100644
--- a/dev/App/Admin.js
+++ b/dev/App/Admin.js
@@ -167,6 +167,8 @@
if (Enums.StorageResultType.Success === sResult && oData && oData.Result)
{
Data.coreReal(!!oData.Result.Real);
+ Data.coreChannel(oData.Result.Channel || 'stable');
+ Data.coreType(oData.Result.Type || 'stable');
Data.coreUpdatable(!!oData.Result.Updatable);
Data.coreAccess(!!oData.Result.Access);
Data.coreRemoteVersion(oData.Result.RemoteVersion || '');
@@ -176,6 +178,8 @@
else
{
Data.coreReal(false);
+ Data.coreChannel('stable');
+ Data.coreType('stable');
Data.coreRemoteVersion('');
Data.coreRemoteRelease('');
Data.coreVersionCompare(-2);
diff --git a/dev/Common/Enums.js b/dev/Common/Enums.js
index f695120c1..faf45d482 100644
--- a/dev/Common/Enums.js
+++ b/dev/Common/Enums.js
@@ -51,7 +51,7 @@
'Gravatar': 'GRAVATAR',
'Themes': 'THEMES',
'UserBackground': 'USER_BACKGROUND',
- 'Filters': 'FILTERS',
+ 'Sieve': 'SIEVE',
'AdditionalAccounts': 'ADDITIONAL_ACCOUNTS',
'AdditionalIdentities': 'ADDITIONAL_IDENTITIES'
};
@@ -291,7 +291,6 @@
*/
Enums.FilterConditionField = {
'From': 'From',
- 'To': 'To',
'Recipient': 'Recipient',
'Subject': 'Subject'
};
@@ -320,8 +319,8 @@
* @enum {string}
*/
Enums.FilterRulesType = {
- 'And': 'And',
- 'Or': 'Or'
+ 'All': 'All',
+ 'Any': 'Any'
};
/**
diff --git a/dev/Common/Globals.js b/dev/Common/Globals.js
index 19654ab5b..87d32af36 100644
--- a/dev/Common/Globals.js
+++ b/dev/Common/Globals.js
@@ -145,7 +145,7 @@
'removeButtons': 'Format,Undo,Redo,Cut,Copy,Paste,Anchor,Strike,Subscript,Superscript,Image,SelectAll,Source',
'removeDialogTabs': 'link:advanced;link:target;image:advanced;images:advanced',
- 'extraPlugins': 'plain',
+ 'extraPlugins': 'plain,signature',
'allowedContent': true,
'font_defaultLabel': 'Arial',
diff --git a/dev/Common/HtmlEditor.js b/dev/Common/HtmlEditor.js
index f012711e3..c255ce956 100644
--- a/dev/Common/HtmlEditor.js
+++ b/dev/Common/HtmlEditor.js
@@ -62,6 +62,19 @@
return this.editor ? 'wysiwyg' === this.editor.mode : false;
};
+ /**
+ * @param {string} sSignature
+ */
+ HtmlEditor.prototype.setSignature = function (sSignature)
+ {
+ if (this.editor)
+ {
+ this.editor.execCommand('insertSignature', {
+ 'signature': sSignature
+ });
+ }
+ };
+
/**
* @return {boolean}
*/
@@ -172,7 +185,7 @@
bBiti = !!Settings.settingsGet('AllowHtmlEditorBitiButtons')
;
- if ((bSource || bBiti) && !oConfig.toolbarGroups.__SourceInited)
+ if ((bSource || !bBiti) && !oConfig.toolbarGroups.__SourceInited)
{
oConfig.toolbarGroups.__SourceInited = true;
@@ -181,9 +194,9 @@
oConfig.removeButtons = oConfig.removeButtons.replace(',Source', '');
}
- if (bBiti)
+ if (!bBiti)
{
- oConfig.extraPlugins += (oConfig.extraPlugins ? ',' : '') + 'bidi';
+ oConfig.removePlugins += (oConfig.removePlugins ? ',' : '') + 'bidi';
}
}
diff --git a/dev/Common/Utils.js b/dev/Common/Utils.js
index 7df3ac37c..fbc764f5e 100644
--- a/dev/Common/Utils.js
+++ b/dev/Common/Utils.js
@@ -1059,6 +1059,7 @@
oData.capaAdditionalAccounts = ko.observable(false);
oData.capaAdditionalIdentities = ko.observable(false);
oData.capaGravatar = ko.observable(false);
+ oData.capaSieve = ko.observable(false);
oData.determineUserLanguage = ko.observable(false);
oData.determineUserDomain = ko.observable(false);
@@ -1561,6 +1562,8 @@
{
sPlain = sPlain.toString().replace(/\r/g, '');
+ bFindEmailAndLinks = Utils.isUnd(bFindEmailAndLinks) ? false : !!bFindEmailAndLinks;
+
var
bIn = false,
bDo = true,
@@ -1627,7 +1630,6 @@
.replace(/>/g, '>').replace(/')
.replace(/[\s]*~~~\/blockquote~~~/g, '')
- .replace(/ /g, ' ')
.replace(/\n/g, '
')
;
@@ -1784,11 +1786,12 @@
for (iIndex = 0, iLen = aList.length; iIndex < iLen; iIndex++)
{
oItem = aList[iIndex];
- if (oItem.subScribed() || !oItem.existen || bBuildUnvisible)
+// if (oItem.subScribed() || !oItem.existen || bBuildUnvisible)
+ if ((oItem.subScribed() || !oItem.existen || bBuildUnvisible) && (oItem.selectable || oItem.hasSubScribedSubfolders()))
{
if (fVisibleCallback ? fVisibleCallback.call(null, oItem) : true)
{
- if (Enums.FolderType.User === oItem.type() || !bSystem || 0 < oItem.subFolders().length)
+ if (Enums.FolderType.User === oItem.type() || !bSystem || oItem.hasSubScribedSubfolders())
{
if (bSep && 0 < aResult.length)
{
diff --git a/dev/External/ko.js b/dev/External/ko.js
index 3a0518973..58b9570c8 100644
--- a/dev/External/ko.js
+++ b/dev/External/ko.js
@@ -36,6 +36,7 @@
var
$oEl = null,
+ bi18n = true,
sClass = '',
sPlacement = '',
oSubscription = null,
@@ -47,6 +48,7 @@
{
$oEl = $(oElement);
sClass = $oEl.data('tooltip-class') || '';
+ bi18n = 'on' === ($oEl.data('tooltip-i18n') || 'on');
sPlacement = $oEl.data('tooltip-placement') || 'top';
$oEl.tooltip({
@@ -59,8 +61,9 @@
'placement': sPlacement,
'trigger': 'hover',
'title': function () {
- return $oEl.is('.disabled') || Globals.dropdownVisibility() ? '' : '' +
- Utils.i18n(ko.unwrap(fValueAccessor())) + '';
+ var sValue = bi18n ? ko.unwrap(fValueAccessor()) : fValueAccessor()();
+ return '' === sValue || $oEl.is('.disabled') || Globals.dropdownVisibility() ? '' :
+ '' + (bi18n ? Utils.i18n(sValue) : sValue) + '';
}
}).on('click.koTooltip', function () {
$oEl.tooltip('hide');
@@ -75,42 +78,7 @@
}
};
- ko.bindingHandlers.tooltip2 = {
- 'init': function (oElement, fValueAccessor) {
- var
- Globals = require('Common/Globals'),
-
- $oEl = $(oElement),
- oSubscription = null,
- sClass = $oEl.data('tooltip-class') || '',
- sPlacement = $oEl.data('tooltip-placement') || 'top'
- ;
-
- $oEl.tooltip({
- 'delay': {
- 'show': 500,
- 'hide': 100
- },
- 'html': true,
- 'container': 'body',
- 'placement': sPlacement,
- 'title': function () {
- return $oEl.is('.disabled') || Globals.dropdownVisibility() ? '' :
- '' + fValueAccessor()() + '';
- }
- }).on('click.koTooltip', function () {
- $oEl.tooltip('hide');
- });
-
- oSubscription = Globals.tooltipTrigger.subscribe(function () {
- $oEl.tooltip('hide');
- });
-
- fDisposalTooltipHelper(oElement, $oEl, oSubscription);
- }
- };
-
- ko.bindingHandlers.tooltip3 = {
+ ko.bindingHandlers.tooltipForTest = {
'init': function (oElement) {
var
diff --git a/dev/Model/Filter.js b/dev/Model/Filter.js
index d7bf42618..c1901a09e 100644
--- a/dev/Model/Filter.js
+++ b/dev/Model/Filter.js
@@ -26,14 +26,10 @@
this.name = ko.observable('');
- this.conditionsType = ko.observable(Enums.FilterRulesType.And);
+ this.conditionsType = ko.observable(Enums.FilterRulesType.All);
this.conditions = ko.observableArray([]);
- this.regDisposables(this.conditions.subscribe(function () {
- Utils.windowResize();
- }));
-
// Actions
this.actionMarkAsRead = ko.observable(false);
this.actionSkipOtherFilters = ko.observable(true);
@@ -41,18 +37,27 @@
this.actionType = ko.observable(Enums.FiltersAction.Move);
this.actionTypeOptions = [ // TODO i18n
- {'id': Enums.FiltersAction.None, 'name': 'Action - None'},
- {'id': Enums.FiltersAction.Move, 'name': 'Action - Move to'},
- // {'id': Enums.FiltersAction.Forward, 'name': 'Action - Forward to'},
- {'id': Enums.FiltersAction.Discard, 'name': 'Action - Discard'}
+ {'id': Enums.FiltersAction.None, 'name': 'None'},
+ {'id': Enums.FiltersAction.Move, 'name': ' Move to'},
+ // {'id': Enums.FiltersAction.Forward, 'name': 'Forward to'},
+ {'id': Enums.FiltersAction.Discard, 'name': 'Discard'}
];
- this.actionMarkAsReadVisiblity = ko.computed(function () {
- return -1 < Utils.inArray(this.actionType(), [
- Enums.FiltersAction.None, Enums.FiltersAction.Forward, Enums.FiltersAction.Move
+ this.enableSkipOtherFilters = ko.computed(function () {
+ return -1 === Utils.inArray(this.actionType(), [
+ Enums.FiltersAction.Move, Enums.FiltersAction.Forward, Enums.FiltersAction.Discard
]);
}, this);
+ this.actionSkipOtherFiltersResult = ko.computed({
+ 'read': function () {
+ return this.actionSkipOtherFilters() ||
+ !this.enableSkipOtherFilters();
+ },
+ 'write': this.actionSkipOtherFilters,
+ 'owner': this
+ });
+
this.actionTemplate = ko.computed(function () {
var sTemplate = '';
@@ -75,7 +80,11 @@
}, this);
- this.regDisposables([this.actionMarkAsReadVisiblity, this.actionTemplate]);
+ this.regDisposables(this.conditions.subscribe(function () {
+ Utils.windowResize();
+ }));
+
+ this.regDisposables([this.enableSkipOtherFilters, this.actionSkipOtherFiltersResult, this.actionTemplate]);
}
_.extend(FilterModel.prototype, AbstractModel.prototype);
diff --git a/dev/Model/FilterCondition.js b/dev/Model/FilterCondition.js
index 67dba75de..821aeabee 100644
--- a/dev/Model/FilterCondition.js
+++ b/dev/Model/FilterCondition.js
@@ -27,7 +27,6 @@
this.fieldOptions = [ // TODO i18n
{'id': Enums.FilterConditionField.From, 'name': 'From'},
{'id': Enums.FilterConditionField.Recipient, 'name': 'Recipient (To or CC)'},
- {'id': Enums.FilterConditionField.To, 'name': 'To'},
{'id': Enums.FilterConditionField.Subject, 'name': 'Subject'}
];
diff --git a/dev/Model/Folder.js b/dev/Model/Folder.js
index 1d6bdd7ea..88d659279 100644
--- a/dev/Model/Folder.js
+++ b/dev/Model/Folder.js
@@ -86,12 +86,14 @@
}, this);
this.visible = ko.computed(function () {
+
var
bSubScribed = this.subScribed(),
bSubFolders = this.hasSubScribedSubfolders()
;
return (bSubScribed || (bSubFolders && (!this.existen || !this.selectable)));
+
}, this);
this.isSystemFolder = ko.computed(function () {
diff --git a/dev/Screen/User/Settings.js b/dev/Screen/User/Settings.js
index 007b53bf2..19d1435cb 100644
--- a/dev/Screen/User/Settings.js
+++ b/dev/Screen/User/Settings.js
@@ -69,7 +69,7 @@
'SettingsIdentity', 'SETTINGS_LABELS/LABEL_IDENTITY_NAME', 'identity');
}
- if (Settings.capa(Enums.Capa.Filters))
+ if (Settings.capa(Enums.Capa.Sieve))
{
kn.addSettingsViewModel(require('Settings/User/Filters'),
'SettingsFilters', 'SETTINGS_LABELS/LABEL_FILTERS_NAME', 'filters');
diff --git a/dev/Settings/Admin/About.js b/dev/Settings/Admin/About.js
index f49ac692b..77ab4804b 100644
--- a/dev/Settings/Admin/About.js
+++ b/dev/Settings/Admin/About.js
@@ -22,6 +22,8 @@
this.errorDesc = ko.observable('');
this.coreReal = Data.coreReal;
+ this.coreChannel = Data.coreChannel;
+ this.coreType = Data.coreType;
this.coreUpdatable = Data.coreUpdatable;
this.coreAccess = Data.coreAccess;
this.coreChecking = Data.coreChecking;
diff --git a/dev/Storage/AbstractData.js b/dev/Storage/AbstractData.js
index b2912691d..7add1a6d5 100644
--- a/dev/Storage/AbstractData.js
+++ b/dev/Storage/AbstractData.js
@@ -45,6 +45,7 @@
this.capaAdditionalAccounts(Settings.capa(Enums.Capa.AdditionalAccounts));
this.capaAdditionalIdentities(Settings.capa(Enums.Capa.AdditionalIdentities));
this.capaGravatar(Settings.capa(Enums.Capa.Gravatar));
+ this.capaSieve(Settings.capa(Enums.Capa.Sieve));
this.determineUserLanguage(!!Settings.settingsGet('DetermineUserLanguage'));
this.determineUserDomain(!!Settings.settingsGet('DetermineUserDomain'));
diff --git a/dev/Storage/Admin/Data.js b/dev/Storage/Admin/Data.js
index 95dba59cc..158c2c6ad 100644
--- a/dev/Storage/Admin/Data.js
+++ b/dev/Storage/Admin/Data.js
@@ -31,6 +31,8 @@
this.packages.loading = ko.observable(false).extend({'throttle': 100});
this.coreReal = ko.observable(true);
+ this.coreChannel = ko.observable('stable');
+ this.coreType = ko.observable('stable');
this.coreUpdatable = ko.observable(true);
this.coreAccess = ko.observable(true);
this.coreChecking = ko.observable(false).extend({'throttle': 100});
diff --git a/dev/Storage/Admin/Remote.js b/dev/Storage/Admin/Remote.js
index 11174256e..e768924d2 100644
--- a/dev/Storage/Admin/Remote.js
+++ b/dev/Storage/Admin/Remote.js
@@ -212,7 +212,7 @@
RemoteAdminStorage.prototype.createOrUpdateDomain = function (fCallback,
bCreate, sName,
sIncHost, iIncPort, sIncSecure, bIncShortLogin,
- bUseSieve, bUseImapServerForSieve, sSieveHost, iSievePort, sSieveSecure,
+ bUseSieve, sSieveHost, iSievePort, sSieveSecure,
sOutHost, iOutPort, sOutSecure, bOutShortLogin, bOutAuth, bOutPhpMail,
sWhiteList)
{
@@ -226,7 +226,6 @@
'IncShortLogin': bIncShortLogin ? '1' : '0',
'UseSieve': bUseSieve ? '1' : '0',
- 'UseImapServerForSieve': bUseImapServerForSieve ? '1' : '0',
'SieveHost': sSieveHost,
'SievePort': iSievePort,
'SieveSecure': sSieveSecure,
@@ -244,7 +243,7 @@
RemoteAdminStorage.prototype.testConnectionForDomain = function (fCallback, sName,
sIncHost, iIncPort, sIncSecure,
- bUseSieve, bUseImapServerForSieve, sSieveHost, iSievePort, sSieveSecure,
+ bUseSieve, sSieveHost, iSievePort, sSieveSecure,
sOutHost, iOutPort, sOutSecure, bOutAuth, bOutPhpMail)
{
this.defaultRequest(fCallback, 'AdminDomainTest', {
@@ -253,7 +252,6 @@
'IncPort': iIncPort,
'IncSecure': sIncSecure,
'UseSieve': bUseSieve ? '1' : '0',
- 'UseImapServerForSieve': bUseImapServerForSieve ? '1' : '0',
'SieveHost': sSieveHost,
'SievePort': iSievePort,
'SieveSecure': sSieveSecure,
diff --git a/dev/Styles/@Main.less b/dev/Styles/@Main.less
index ea0fd5ecb..d99146e14 100644
--- a/dev/Styles/@Main.less
+++ b/dev/Styles/@Main.less
@@ -90,6 +90,7 @@
@import "SettingsOpenPGP.less";
@import "SettingsFolders.less";
@import "SettingsThemes.less";
+@import "SettingsFilters.less";
@import "Animations.less";
//@import "Responsive.less";
diff --git a/dev/Styles/Compose.less b/dev/Styles/Compose.less
index 343a053bf..e2e1ae4eb 100644
--- a/dev/Styles/Compose.less
+++ b/dev/Styles/Compose.less
@@ -68,7 +68,7 @@
border-bottom: 1px dashed #555;
}
}
-
+
.e-row {
line-height: 30px;
}
@@ -135,6 +135,12 @@
}
}
+ .cke_chrome {
+ border-left-width: 0 !important;
+ border-right-width: 0 !important;
+ border-bottom-width: 0 !important;
+ }
+
.b-attachment-button {
display: inline-block;
}
diff --git a/dev/Styles/Filter.less b/dev/Styles/Filter.less
index fd2cebb19..d4860ab6e 100644
--- a/dev/Styles/Filter.less
+++ b/dev/Styles/Filter.less
@@ -1,10 +1,14 @@
.popups {
.b-filter-content {
- width: 800px;
+ width: 750px;
.modal-header {
background-color: #fff;
}
+
+ .button-delete {
+ cursor: pointer;
+ }
}
}
diff --git a/dev/Styles/SettingsFilters.less b/dev/Styles/SettingsFilters.less
new file mode 100644
index 000000000..a1c07b5a4
--- /dev/null
+++ b/dev/Styles/SettingsFilters.less
@@ -0,0 +1,59 @@
+
+.b-settings-filters {
+
+ .process-place {
+ text-align: center;
+ width: 600px;
+ padding: 14px 0;
+ }
+
+ .list-table {
+
+ width: 600px;
+
+ td {
+ padding: 4px 8px;
+ line-height: 30px;
+ }
+
+ .filter-img {
+ font-size: 12px;
+ margin-right: 5px;
+ }
+
+ .filter-name {
+ display: inline-block;
+ word-break: break-all;
+ box-sizing: border-box;
+ line-height: 22px;
+ cursor: pointer;
+ }
+ }
+
+ .filter-item {
+
+ .e-action {
+ cursor: pointer;
+ }
+
+ .button-delete {
+ margin-right: 15px;
+ margin-top: 5px;
+ visibility: hidden;
+ opacity: 0;
+ }
+
+ .delete-access {
+ &.button-delete {
+ visibility: visible;
+ margin-right: 0;
+ opacity: 1;
+ }
+ }
+
+ .delete-filter {
+ cursor: pointer;
+ opacity: 0.5;
+ }
+ }
+}
diff --git a/dev/Styles/SettingsIdentities.less b/dev/Styles/SettingsIdentities.less
index 98917e230..5a600587e 100644
--- a/dev/Styles/SettingsIdentities.less
+++ b/dev/Styles/SettingsIdentities.less
@@ -10,6 +10,7 @@
.e-signature-place {
display: inline-block;
width: 680px;
+ width: 725px;
height: 250px;
}
diff --git a/dev/Styles/SettingsIdentity.less b/dev/Styles/SettingsIdentity.less
index e88b2ea3c..a99427467 100644
--- a/dev/Styles/SettingsIdentity.less
+++ b/dev/Styles/SettingsIdentity.less
@@ -3,6 +3,7 @@
.e-signature-place {
display: inline-block;
width: 680px;
+ width: 725px;
height: 250px;
}
}
diff --git a/dev/Styles/_CkeFix.less b/dev/Styles/_CkeFix.less
index 039b471c5..158f07624 100644
--- a/dev/Styles/_CkeFix.less
+++ b/dev/Styles/_CkeFix.less
@@ -2,6 +2,40 @@
display: none !important;
}*/
+.cke_chrome {
+ border: 1px solid #ccc !important;
+}
+
+.cke_toolgroup, .cke_combo_button {
+ border: 1px solid #A6A6A6 !important;
+}
+
+.cke_top {
+ padding: 6px 4px 1px 6px !important;
+ -moz-box-shadow: none !important;
+ -webkit-box-shadow: none !important;
+ box-shadow: none !important;
+}
+
+.cke_button {
+ padding: 5px 6px !important;
+}
+
+.cke_combo_text {
+ line-height: 28px !important;
+ padding-left: 8px !important;
+}
+
+.cke_combo_button {
+ background: #FBFBFB !important;
+}
+
+.cke_source {
+ font-family: Monaco, Menlo, Consolas, 'Courier New', monospace !important;
+ padding: 10px !important;
+ padding-right: 0 !important;
+}
+
.cke_plain {
background-color: #fff;
@@ -38,7 +72,7 @@
}
.cke_wysiwyg_div {
-
+
padding: 10px !important;
font-family: arial, sans-serif;
font-size: 13px;
diff --git a/dev/View/Popup/Compose.js b/dev/View/Popup/Compose.js
index ffa6d4855..2039a4eb8 100644
--- a/dev/View/Popup/Compose.js
+++ b/dev/View/Popup/Compose.js
@@ -1052,10 +1052,10 @@
return false;
});
- key('ctrl+enter, command+enter', Enums.KeyState.Compose, function () {
- self.sendCommand();
- return false;
- });
+// key('ctrl+enter, command+enter', Enums.KeyState.Compose, function () {
+// self.sendCommand();
+// return false;
+// });
key('esc', Enums.KeyState.Compose, function () {
if (self.modalVisibility())
diff --git a/dev/View/Popup/Domain.js b/dev/View/Popup/Domain.js
index 6beebf39a..732316111 100644
--- a/dev/View/Popup/Domain.js
+++ b/dev/View/Popup/Domain.js
@@ -12,6 +12,7 @@
Utils = require('Common/Utils'),
Remote = require('Storage/Admin/Remote'),
+ Settings = require('Storage/Settings'),
kn = require('Knoin/Knoin'),
AbstractView = require('Knoin/AbstractView')
@@ -62,14 +63,13 @@
this.name = ko.observable('');
this.name.focused = ko.observable(false);
- this.allowSieve = ko.observable(false);
+ this.allowSieve = ko.observable(Settings.capa(Enums.Capa.Sieve));
this.imapServer = ko.observable('');
this.imapPort = ko.observable('' + Consts.Values.ImapDefaulPort);
this.imapSecure = ko.observable(Enums.ServerSecure.None);
this.imapShortLogin = ko.observable(false);
this.useSieve = ko.observable(false);
- this.useImapServerForSieve = ko.observable(true);
this.sieveServer = ko.observable('');
this.sievePort = ko.observable('' + Consts.Values.SieveDefaulPort);
this.sieveSecure = ko.observable(Enums.ServerSecure.None);
@@ -94,14 +94,13 @@
var
bPhpMail = this.smtpPhpMail(),
bAllowSieve = this.allowSieve(),
- bUseSieve = this.useSieve(),
- bIseImapServerForSieve = this.useImapServerForSieve()
+ bUseSieve = this.useSieve()
;
return '' !== this.name() &&
'' !== this.imapServer() &&
'' !== this.imapPort() &&
- (bAllowSieve && bUseSieve ? (bIseImapServerForSieve ? true : ('' !== this.sieveServer() && '' !== this.sievePort())) : true) &&
+ (bAllowSieve && bUseSieve ? ('' !== this.sieveServer() && '' !== this.sievePort()) : true) &&
(('' !== this.smtpServer() && '' !== this.smtpPort()) || bPhpMail);
}, this);
@@ -127,7 +126,6 @@
this.imapShortLogin(),
this.useSieve(),
- this.useImapServerForSieve(),
this.sieveServer(),
Utils.pInt(this.sievePort()),
this.sieveSecure(),
@@ -162,7 +160,6 @@
this.imapSecure(),
this.useSieve(),
- this.useImapServerForSieve(),
this.sieveServer(),
Utils.pInt(this.sievePort()),
this.sieveSecure(),
@@ -201,9 +198,9 @@
}, this);
this.sieveServerFocus.subscribe(function (bValue) {
- if (bValue && '' !== this.name() && '' === this.sieveServer())
+ if (bValue && '' !== this.imapServer() && '' === this.sieveServer())
{
- this.sieveServer(this.name().replace(/[.]?[*][.]?/g, ''));
+ this.sieveServer(this.imapServer());
}
}, this);
@@ -356,7 +353,6 @@
this.imapSecure(Utils.trim(oDomain.IncSecure));
this.imapShortLogin(!!oDomain.IncShortLogin);
this.useSieve(!!oDomain.UseSieve);
- this.useImapServerForSieve(!!oDomain.UseImapServerForSieve);
this.sieveServer(Utils.trim(oDomain.SieveHost));
this.sievePort('' + Utils.pInt(oDomain.SievePort));
this.sieveSecure(Utils.trim(oDomain.SieveSecure));
@@ -400,7 +396,6 @@
this.imapShortLogin(false);
this.useSieve(false);
- this.useImapServerForSieve(true);
this.sieveServer('');
this.sievePort('' + Consts.Values.SieveDefaulPort);
this.sieveSecure(Enums.ServerSecure.None);
diff --git a/dev/View/Popup/Languages.js b/dev/View/Popup/Languages.js
index 9762c06aa..6ee6d47f9 100644
--- a/dev/View/Popup/Languages.js
+++ b/dev/View/Popup/Languages.js
@@ -48,7 +48,8 @@
LanguagesPopupView.prototype.languageEnName = function (sLanguage)
{
- return Utils.convertLangName(sLanguage, true);
+ var sResult = Utils.convertLangName(sLanguage, true);
+ return 'English' === sResult ? '' : sResult;
};
LanguagesPopupView.prototype.resetMainLanguage = function ()
diff --git a/dev/View/User/MailBox/MessageView.js b/dev/View/User/MailBox/MessageView.js
index b31d51587..2fa1cd386 100644
--- a/dev/View/User/MailBox/MessageView.js
+++ b/dev/View/User/MailBox/MessageView.js
@@ -452,12 +452,6 @@
}
});
- // TODO // more toggle
- // key('', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () {
- // self.moreDropdownTrigger(true);
- // return false;
- // });
-
// reply
key('r', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () {
if (Data.message())
diff --git a/dev/bootstrap.js b/dev/bootstrap.js
index 6777c7377..2dd1bcd20 100644
--- a/dev/bootstrap.js
+++ b/dev/bootstrap.js
@@ -42,6 +42,7 @@
window['rl']['remoteRequest'] = _.bind(Plugins.remoteRequest, Plugins);
window['rl']['pluginSettingsGet'] = _.bind(Plugins.settingsGet, Plugins);
window['rl']['createCommand'] = Utils.createCommand;
+ window['rl']['i18n'] = Utils.i18n;
window['rl']['EmailModel'] = EmailModel;
window['rl']['Enums'] = Enums;
diff --git a/gulpfile.js b/gulpfile.js
index a09f8c757..d1529077d 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -30,6 +30,7 @@ var
concat = require('gulp-concat-util'),
header = require('gulp-header'),
eol = require('gulp-eol'),
+ stripbom = require('gulp-stripbom'),
rename = require('gulp-rename'),
replace = require('gulp-replace'),
uglify = require('gulp-uglify'),
@@ -188,7 +189,7 @@ gulp.task('less:main', function() {
.pipe(gulp.dest(cfg.paths.staticCSS));
});
-gulp.task('css:main', ['less:main'], function() {
+gulp.task('css:main-begin', ['less:main'], function() {
var
// csslint = require('gulp-csslint'),
@@ -208,6 +209,14 @@ gulp.task('css:main', ['less:main'], function() {
;
});
+gulp.task('css:clear-less', ['css:main-begin'], function() {
+
+ return gulp.src(cfg.paths.staticCSS + cfg.paths.less.main.name, {read: false})
+ .pipe(require('gulp-rimraf')());
+});
+
+gulp.task('css:main', ['css:clear-less']);
+
gulp.task('css:main:min', ['css:main'], function() {
var minifyCss = require('gulp-minify-css');
return gulp.src(cfg.paths.staticCSS + cfg.paths.css.main.name)
@@ -381,6 +390,39 @@ gulp.task('package-inc-release', function() {
(1 + parseInt(pkg.release, 10)) + '",'));
});
+gulp.task('fontastic-fonts:clear', function() {
+ return cleanDir('rainloop/v/' + cfg.devVersion + '/static/css/fonts/rainloop.*');
+});
+
+gulp.task('fontastic-fonts:copy', ['fontastic-fonts:clear'], function() {
+ return gulp.src('vendors/fontastic/fonts/rainloop.*')
+ .pipe(gulp.dest('rainloop/v/' + cfg.devVersion + '/static/css/fonts'));
+});
+
+gulp.task('fontastic', ['fontastic-fonts:copy']);
+
+gulp.task('ckeditor:clear', function() {
+ return cleanDir('rainloop/v/' + cfg.devVersion + '/static/ckeditor');
+});
+
+gulp.task('ckeditor:copy', ['ckeditor:clear'], function() {
+ return gulp.src('vendors/ckeditor/**/*')
+ .pipe(gulp.dest('rainloop/v/' + cfg.devVersion + '/static/ckeditor'));
+});
+
+gulp.task('ckeditor:copy-plugins', ['ckeditor:copy'], function() {
+ return gulp.src('vendors/ckeditor-plugins/**/*')
+ .pipe(gulp.dest('rainloop/v/' + cfg.devVersion + '/static/ckeditor/plugins'));
+});
+
+gulp.task('ckeditor', ['ckeditor:copy-plugins'], function () {
+ return gulp.src('rainloop/v/' + cfg.devVersion + '/static/ckeditor/*.js')
+ .pipe(stripbom())
+ .pipe(replace("\u200B", "\\u200B"))
+ .pipe(header("\uFEFF")) // BOM
+ .pipe(gulp.dest('rainloop/v/' + cfg.devVersion + '/static/ckeditor'));
+});
+
// BUILD (RainLoop)
gulp.task('rainloop:copy', ['default'], function() {
@@ -412,8 +454,6 @@ gulp.task('rainloop:setup', ['rainloop:copy'], function() {
fs.writeFileSync(dist + 'rainloop/v/' + versionFull + '/index.php.root', fs.readFileSync(dist + 'index.php'));
- fs.unlinkSync(dist + 'rainloop/v/' + versionFull + '/static/css/less.css');
-
cfg.destPath = cfg.releasesPath + '/webmail/' + versionFull + '/';
cfg.cleanPath = dist;
cfg.zipSrcPath = dist;
@@ -486,7 +526,7 @@ gulp.task('rainloop:owncloud:clean', ['rainloop:owncloud:copy', 'rainloop:ownclo
});
// MAIN
-gulp.task('default', ['js:libs', 'js:boot', 'js:openpgp', 'js:min', 'css:main:min']);
+gulp.task('default', ['js:libs', 'js:boot', 'js:openpgp', 'js:min', 'css:main:min', 'ckeditor', 'fontastic']);
gulp.task('fast', ['js:app', 'js:admin', 'js:chunks', 'css:main']);
gulp.task('rainloop', ['js:lint', 'rainloop:copy', 'rainloop:setup', 'rainloop:zip', 'rainloop:md5', 'rainloop:clean']);
diff --git a/package.json b/package.json
index 6d2ec2704..a35dc8e77 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "RainLoop",
"title": "RainLoop Webmail",
"version": "1.7.0",
- "release": "204",
+ "release": "207",
"description": "Simple, modern & fast web-based email client",
"homepage": "http://rainloop.net",
"main": "gulpfile.js",
@@ -58,6 +58,7 @@
"gulp-replace": "*",
"gulp-header": "*",
"gulp-eol": "*",
+ "gulp-stripbom": "*",
"gulp-minify-css": "*",
"gulp-autoprefixer": "*",
"gulp-csscomb": "*",
diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Net/NetClient.php b/rainloop/v/0.0.0/app/libraries/MailSo/Net/NetClient.php
index 6e65504ac..7c920969c 100644
--- a/rainloop/v/0.0.0/app/libraries/MailSo/Net/NetClient.php
+++ b/rainloop/v/0.0.0/app/libraries/MailSo/Net/NetClient.php
@@ -508,10 +508,10 @@ abstract class NetClient
$iReadedLen = \strlen($this->sResponseBuffer);
if (null === $mReadLen || $bForceLogin)
{
- $iLimit = 5000; // 5kb
+ $iLimit = 5000; // 5KB
if ($iLimit < $iReadedLen)
{
- $this->writeLogWithCrlf('[cutted:'.$iReadedLen.'b] < '.\substr($this->sResponseBuffer.'...', 0, $iLimit),
+ $this->writeLogWithCrlf('[cutted:'.$iReadedLen.'] < '.\substr($this->sResponseBuffer, 0, $iLimit).'...',
\MailSo\Log\Enumerations\Type::INFO);
}
else
diff --git a/rainloop/v/0.0.0/app/src/RainLoop/Actions.php b/rainloop/v/0.0.0/app/src/RainLoop/Actions.php
index baddec787..42d42470d 100644
--- a/rainloop/v/0.0.0/app/src/RainLoop/Actions.php
+++ b/rainloop/v/0.0.0/app/src/RainLoop/Actions.php
@@ -70,6 +70,11 @@ class Actions
*/
private $oSettingsProvider;
+ /**
+ * @var \RainLoop\Providers\Filters
+ */
+ private $oFiltersProvider;
+
/**
* @var \RainLoop\Providers\AddressBook
*/
@@ -118,6 +123,7 @@ class Actions
$this->oStorageProvider = null;
$this->oFilesProvider = null;
$this->oSettingsProvider = null;
+ $this->oFiltersProvider = null;
$this->oDomainProvider = null;
$this->oAddressBookProvider = null;
$this->oSuggestionsProvider = null;
@@ -242,6 +248,10 @@ class Actions
// \RainLoop\Providers\Domain\DomainAdminInterface
$oResult = new \RainLoop\Providers\Domain\DefaultDomain(APP_PRIVATE_DATA.'domains', $this->Cacher());
break;
+ case 'filters':
+ // \RainLoop\Providers\Filters\FiltersInterface
+ $oResult = new \RainLoop\Providers\Filters\SieveStorage();
+ break;
case 'address-book':
// \RainLoop\Providers\AddressBook\AddressBookInterface
@@ -574,6 +584,20 @@ class Actions
return $this->oSettingsProvider;
}
+ /**
+ * @return \RainLoop\Providers\Filters
+ */
+ public function FiltersProvider()
+ {
+ if (null === $this->oFiltersProvider)
+ {
+ $this->oFiltersProvider = new \RainLoop\Providers\Filters(
+ $this->fabrica('filters'));
+ }
+
+ return $this->oFiltersProvider;
+ }
+
/**
* @return \RainLoop\Providers\ChangePassword
*/
@@ -992,6 +1016,14 @@ class Actions
return $bResult;
}
+ /**
+ * @return bool
+ */
+ private function UseSieve()
+ {
+ return false; // TODO
+ }
+
/**
* @param bool $bAdmin
* @param string $sAuthAccountHash = ''
@@ -1044,6 +1076,7 @@ class Actions
'ContactsIsAllowed' => false,
'ChangePasswordIsAllowed' => false,
'JsHash' => \md5(\RainLoop\Utils::GetConnectionToken()),
+ 'UseSieve' => $this->UseSieve(),
'UseImapThread' => (bool) $oConfig->Get('labs', 'use_imap_thread', false),
'UseImapSubscribe' => (bool) $oConfig->Get('labs', 'use_imap_list_subscribe', true),
'AllowAppendMessage' => (bool) $oConfig->Get('labs', 'allow_message_append', false),
@@ -3188,10 +3221,27 @@ class Actions
return $aResult;
}
+ /**
+ * @return string
+ */
+ private function getCoreChannel()
+ {
+ $sChannel = \trim(\strtolower($this->Config()->Get('labs', 'update_channel', 'stable')));
+ if (empty($sChannel) || !\in_array($sChannel, array('stable', 'beta')))
+ {
+ $sChannel = 'stable';
+ }
+
+ return $sChannel;
+ }
+
private function getCoreData(&$bReal)
{
$bReal = false;
- $sRepo = APP_REPO_CORE_FILE;
+
+ $sChannel = $this->getCoreChannel();
+
+ $sRepo = \str_replace('{{channel}}', $sChannel, APP_REPO_CORE_FILE);
$oHttp = \MailSo\Base\Http::SingletonInstance();
@@ -3341,11 +3391,14 @@ class Actions
}
$sVersion = empty($aData['version']) ? '' : $aData['version'];
+ $sType = empty($aData['channel']) ? 'stable' : $aData['channel'];
return $this->DefaultResponse(__FUNCTION__, array(
'Real' => $bReal,
'Access' => $bRainLoopAccess,
'Updatable' => $bRainLoopUpdatable,
+ 'Channel' => $this->getCoreChannel(),
+ 'Type' => $sType,
'Version' => APP_VERSION,
'RemoteVersion' => $sVersion,
'RemoteRelease' => empty($aData['release']) ? '' : $aData['release'],
@@ -6058,19 +6111,19 @@ class Actions
* @param string $sFileName
* @param string $sContentType
* @param string $sMimeIndex
+ * @param int $iMaxLength = 250
*
* @return string
*/
- public function MainClearFileName($sFileName, $sContentType, $sMimeIndex)
+ public function MainClearFileName($sFileName, $sContentType, $sMimeIndex, $iMaxLength = 250)
{
- $sFileName = 0 === strlen($sFileName) ? preg_replace('/[^a-zA-Z0-9]/', '.', (empty($sMimeIndex) ? '' : $sMimeIndex.'.').$sContentType) : $sFileName;
- $sClearedFileName = preg_replace('/[\s]+/', ' ', preg_replace('/[\.]+/', '.', $sFileName));
+ $sFileName = 0 === \strlen($sFileName) ? \preg_replace('/[^a-zA-Z0-9]/', '.', (empty($sMimeIndex) ? '' : $sMimeIndex.'.').$sContentType) : $sFileName;
+ $sClearedFileName = \preg_replace('/[\s]+/', ' ', \preg_replace('/[\.]+/', '.', $sFileName));
$sExt = \MailSo\Base\Utils::GetFileExtension($sClearedFileName);
- $iSize = 50;
- if ($iSize < strlen($sClearedFileName) - strlen($sExt))
+ if (10 < $iMaxLength && $iMaxLength < \strlen($sClearedFileName) - \strlen($sExt))
{
- $sClearedFileName = substr($sClearedFileName, 0, $iSize).(empty($sExt) ? '' : '.'.$sExt);
+ $sClearedFileName = \substr($sClearedFileName, 0, $iMaxLength).(empty($sExt) ? '' : '.'.$sExt);
}
return \MailSo\Base\Utils::ClearFileName(\MailSo\Base\Utils::Utf8Clear($sClearedFileName));
@@ -6787,9 +6840,15 @@ class Actions
{
$oConfig = $this->Config();
- $aResult = array(
-// \RainLoop\Enumerations\Capa::FILTERS
- );
+ $aResult = array();
+
+ if ($this->UseSieve())
+ {
+ if ($bAdmin || ($oAccount && $oAccount->Domain()->UseSieve()))
+ {
+ $aResult[] = \RainLoop\Enumerations\Capa::SIEVE;
+ }
+ }
if ($oConfig->Get('webmail', 'allow_additional_accounts', false))
{
diff --git a/rainloop/v/0.0.0/app/src/RainLoop/Api.php b/rainloop/v/0.0.0/app/src/RainLoop/Api.php
index f9b0d6d50..13b3d7e21 100644
--- a/rainloop/v/0.0.0/app/src/RainLoop/Api.php
+++ b/rainloop/v/0.0.0/app/src/RainLoop/Api.php
@@ -97,13 +97,22 @@ class Api
\MailSo\Config::$SystemLogger = \RainLoop\Api::Logger();
$sSslCafile = \RainLoop\Api::Config()->Get('ssl', 'cafile', '');
- if (!empty($sSslCafile))
+ $sSslCapath = \RainLoop\Api::Config()->Get('ssl', 'capath', '');
+
+ if (!empty($sSslCafile) || !empty($sSslCapath))
{
- \MailSo\Hooks::Add('Net.NetClient.StreamContextSettings/Filter', function (&$aStreamContextSettings) use ($sSslCafile) {
- if (isset($aStreamContextSettings['ssl']) && \is_array($aStreamContextSettings['ssl']) &&
- empty($aStreamContextSettings['ssl']['cafile']))
+ \MailSo\Hooks::Add('Net.NetClient.StreamContextSettings/Filter', function (&$aStreamContextSettings) use ($sSslCafile, $sSslCapath) {
+ if (isset($aStreamContextSettings['ssl']) && \is_array($aStreamContextSettings['ssl']))
{
- $aStreamContextSettings['ssl']['cafile'] = $sSslCafile;
+ if (empty($aStreamContextSettings['ssl']['cafile']) && !empty($sSslCafile))
+ {
+ $aStreamContextSettings['ssl']['cafile'] = $sSslCafile;
+ }
+
+ if (empty($aStreamContextSettings['ssl']['capath']) && !empty($sSslCapath))
+ {
+ $aStreamContextSettings['ssl']['capath'] = $sSslCapath;
+ }
}
});
}
diff --git a/rainloop/v/0.0.0/app/src/RainLoop/Config/Application.php b/rainloop/v/0.0.0/app/src/RainLoop/Config/Application.php
index 202b63444..56b870026 100644
--- a/rainloop/v/0.0.0/app/src/RainLoop/Config/Application.php
+++ b/rainloop/v/0.0.0/app/src/RainLoop/Config/Application.php
@@ -119,6 +119,7 @@ class Application extends \RainLoop\Config\AbstractConfig
'ssl' => array(
'verify_certificate' => array(false, 'Require verification of SSL certificate used.'),
'cafile' => array('', 'Location of Certificate Authority file on local filesystem (/etc/ssl/certs/ca-certificates.crt)'),
+ 'capath' => array('', 'capath must be a correctly hashed certificate directory. (/etc/ssl/certs/)'),
),
'login' => array(
@@ -233,6 +234,7 @@ Enables caching in the system'),
'Experimental settings. Handle with care.
'),
'check_new_password_strength' => array(true),
+ 'update_channel' => array('stable'),
'allow_gravatar' => array(true),
'allow_prefetch' => array(true),
'allow_smart_html_links' => array(true),
diff --git a/rainloop/v/0.0.0/app/src/RainLoop/Enumerations/Capa.php b/rainloop/v/0.0.0/app/src/RainLoop/Enumerations/Capa.php
index 3cea595ea..02e9953f8 100644
--- a/rainloop/v/0.0.0/app/src/RainLoop/Enumerations/Capa.php
+++ b/rainloop/v/0.0.0/app/src/RainLoop/Enumerations/Capa.php
@@ -11,7 +11,7 @@ class Capa
const GRAVATAR = 'GRAVATAR';
const THEMES = 'THEMES';
const USER_BACKGROUND = 'USER_BACKGROUND';
- const FILTERS = 'FILTERS';
+ const SIEVE = 'SIEVE';
const ADDITIONAL_ACCOUNTS = 'ADDITIONAL_ACCOUNTS';
const ADDITIONAL_IDENTITIES = 'ADDITIONAL_IDENTITIES';
}
diff --git a/rainloop/v/0.0.0/app/src/RainLoop/Model/Domain.php b/rainloop/v/0.0.0/app/src/RainLoop/Model/Domain.php
index 4cc54e461..c2873ea80 100644
--- a/rainloop/v/0.0.0/app/src/RainLoop/Model/Domain.php
+++ b/rainloop/v/0.0.0/app/src/RainLoop/Model/Domain.php
@@ -68,11 +68,6 @@ class Domain
*/
private $bUseSieve;
- /**
- * @var bool
- */
- private $bUseImapServerForSieve;
-
/**
* @var string
*/
@@ -100,7 +95,6 @@ class Domain
* @param int $iIncSecure
* @param bool $bIncShortLogin
* @param bool $bUseSieve
- * @param bool $bUseImapServerForSieve
* @param string $sSieveHost
* @param int $iSievePort
* @param int $iSieveSecure
@@ -114,7 +108,7 @@ class Domain
*/
private function __construct($sName,
$sIncHost, $iIncPort, $iIncSecure, $bIncShortLogin,
- $bUseSieve, $bUseImapServerForSieve, $sSieveHost, $iSievePort, $iSieveSecure,
+ $bUseSieve, $sSieveHost, $iSievePort, $iSieveSecure,
$sOutHost, $iOutPort, $iOutSecure, $bOutShortLogin, $bOutAuth, $bOutUsePhpMail = false,
$sWhiteList = '')
{
@@ -132,7 +126,6 @@ class Domain
$this->bOutUsePhpMail = $bOutUsePhpMail;
$this->bUseSieve = $bUseSieve;
- $this->bUseImapServerForSieve = $bUseImapServerForSieve;
$this->sSieveHost = $sSieveHost;
$this->iSievePort = $iSievePort;
$this->iSieveSecure = $iSieveSecure;
@@ -147,7 +140,6 @@ class Domain
* @param int $iIncSecure
* @param bool $bIncShortLogin
* @param bool $bUseSieve
- * @param bool $bUseImapServerForSieve
* @param string $sSieveHost
* @param int $iSievePort
* @param int $iSieveSecure
@@ -163,13 +155,13 @@ class Domain
*/
public static function NewInstance($sName,
$sIncHost, $iIncPort, $iIncSecure, $bIncShortLogin,
- $bUseSieve, $bUseImapServerForSieve, $sSieveHost, $iSievePort, $iSieveSecure,
+ $bUseSieve, $sSieveHost, $iSievePort, $iSieveSecure,
$sOutHost, $iOutPort, $iOutSecure, $bOutShortLogin, $bOutAuth, $bOutUsePhpMail,
$sWhiteList = '')
{
return new self($sName,
$sIncHost, $iIncPort, $iIncSecure, $bIncShortLogin,
- $bUseSieve, $bUseImapServerForSieve, $sSieveHost, $iSievePort, $iSieveSecure,
+ $bUseSieve, $sSieveHost, $iSievePort, $iSieveSecure,
$sOutHost, $iOutPort, $iOutSecure, $bOutShortLogin, $bOutAuth, $bOutUsePhpMail,
$sWhiteList);
}
@@ -191,6 +183,8 @@ class Domain
$iIncSecure = self::StrConnectionSecurityTypeToCons(
!empty($aDomain['imap_secure']) ? $aDomain['imap_secure'] : '');
+ $bUseSieve = isset($aDomain['sieve_use']) ? (bool) $aDomain['sieve_use'] : false;
+
$sSieveHost = empty($aDomain['sieve_host']) ? '' : (string) $aDomain['sieve_host'];
$iSievePort = empty($aDomain['sieve_port']) ? 2000 : (int) $aDomain['sieve_port'];
$iSieveSecure = self::StrConnectionSecurityTypeToCons(
@@ -205,15 +199,12 @@ class Domain
$bOutUsePhpMail = isset($aDomain['smtp_php_mail']) ? (bool) $aDomain['smtp_php_mail'] : false;
$sWhiteList = (string) (isset($aDomain['white_list']) ? $aDomain['white_list'] : '');
- $bUseSieve = isset($aDomain['sieve_use']) ? (bool) $aDomain['sieve_use'] : false;
- $bUseImapServerForSieve = isset($aDomain['sieve_use_imap_server']) ? (bool) $aDomain['sieve_use_imap_server'] : true;
-
$bIncShortLogin = isset($aDomain['imap_short_login']) ? (bool) $aDomain['imap_short_login'] : false;
$bOutShortLogin = isset($aDomain['smtp_short_login']) ? (bool) $aDomain['smtp_short_login'] : false;
$oDomain = self::NewInstance($sName,
$sIncHost, $iIncPort, $iIncSecure, $bIncShortLogin,
- $bUseSieve, $bUseImapServerForSieve, $sSieveHost, $iSievePort, $iSieveSecure,
+ $bUseSieve, $sSieveHost, $iSievePort, $iSieveSecure,
$sOutHost, $iOutPort, $iOutSecure, $bOutShortLogin, $bOutAuth, $bOutUsePhpMail,
$sWhiteList);
}
@@ -266,7 +257,6 @@ class Domain
'imap_secure = "'.self::ConstConnectionSecurityTypeToStr($this->iIncSecure).'"',
'imap_short_login = '.($this->bIncShortLogin ? 'On' : 'Off'),
'sieve_use = '.($this->bUseSieve ? 'On' : 'Off'),
- 'sieve_use_imap_server = '.($this->bUseImapServerForSieve ? 'On' : 'Off'),
'sieve_host = "'.$this->encodeIniString($this->sSieveHost).'"',
'sieve_port = '.$this->iSievePort,
'sieve_secure = "'.self::ConstConnectionSecurityTypeToStr($this->iSieveSecure).'"',
@@ -327,7 +317,6 @@ class Domain
* @param int $iIncSecure
* @param bool $bIncShortLogin
* @param bool $bUseSieve
- * @param bool $bUseImapServerForSieve
* @param string $sOutHost
* @param int $iOutPort
* @param int $iOutSecure
@@ -340,7 +329,7 @@ class Domain
*/
public function UpdateInstance(
$sIncHost, $iIncPort, $iIncSecure, $bIncShortLogin,
- $bUseSieve, $bUseImapServerForSieve, $sSieveHost, $iSievePort, $iSieveSecure,
+ $bUseSieve, $sSieveHost, $iSievePort, $iSieveSecure,
$sOutHost, $iOutPort, $iOutSecure, $bOutShortLogin, $bOutAuth, $bOutUsePhpMail,
$sWhiteList = '')
{
@@ -350,7 +339,6 @@ class Domain
$this->bIncShortLogin = $bIncShortLogin;
$this->bUseSieve = $bUseSieve;
- $this->bUseImapServerForSieve = $bUseImapServerForSieve;
$this->sSieveHost = \MailSo\Base\Utils::IdnToAscii($sSieveHost);
$this->iSievePort = $iSievePort;
$this->iSieveSecure = $iSieveSecure;
@@ -415,14 +403,6 @@ class Domain
return $this->bUseSieve;
}
- /**
- * @return bool
- */
- public function UseImapServerForSieve()
- {
- return $this->bUseImapServerForSieve;
- }
-
/**
* @return string
*/
@@ -541,7 +521,6 @@ class Domain
'IncSecure' => $this->IncSecure(),
'IncShortLogin' => $this->IncShortLogin(),
'UseSieve' => $this->UseSieve(),
- 'UseImapServerForSieve' => $this->UseImapServerForSieve(),
'SieveHost' => $bAjax ? \MailSo\Base\Utils::IdnToUtf8($this->SieveHost()) : $this->SieveHost(),
'SievePort' => $this->SievePort(),
'SieveSecure' => $this->SieveSecure(),
diff --git a/rainloop/v/0.0.0/app/src/RainLoop/Plugins/AbstractPlugin.php b/rainloop/v/0.0.0/app/src/RainLoop/Plugins/AbstractPlugin.php
index f4ab21c7c..73cdbeda1 100644
--- a/rainloop/v/0.0.0/app/src/RainLoop/Plugins/AbstractPlugin.php
+++ b/rainloop/v/0.0.0/app/src/RainLoop/Plugins/AbstractPlugin.php
@@ -130,15 +130,15 @@ abstract class AbstractPlugin
{
return array();
}
-
+
/**
* @return string
*/
public function Hash()
{
- return \md5($this->sVersion);
+ return \md5($this->sName.'@'.$this->sVersion);
}
-
+
/**
* @return string
*/
@@ -146,7 +146,7 @@ abstract class AbstractPlugin
{
return '';
}
-
+
/**
* @final
* @return array
@@ -161,22 +161,41 @@ abstract class AbstractPlugin
$this->aConfigMap = array();
}
}
-
+
return $this->aConfigMap;
}
/**
* @param string $sPath
- * @param string $sName
- * @param string $sVersion = ''
*
* @return self
*/
- public function SetValues($sPath, $sName, $sVersion = '')
+ public function SetPath($sPath)
{
- $this->sName = $sName;
$this->sPath = $sPath;
+ return $this;
+ }
+
+ /**
+ * @param string $sName
+ *
+ * @return self
+ */
+ public function SetName($sName)
+ {
+ $this->sName = $sName;
+
+ return $this;
+ }
+
+ /**
+ * @param string $sVersion
+ *
+ * @return self
+ */
+ public function SetVersion($sVersion)
+ {
if (0 < \strlen($sVersion))
{
$this->sVersion = $sVersion;
@@ -222,14 +241,14 @@ abstract class AbstractPlugin
*/
public function Init()
{
-
+
}
/**
* @param bool $bAdmin
* @param bool $bAuth
* @param array $aConfig
- *
+ *
* @return void
*/
public function FilterAppDataPluginSection($bAdmin, $bAuth, &$aConfig)
diff --git a/rainloop/v/0.0.0/app/src/RainLoop/Plugins/Manager.php b/rainloop/v/0.0.0/app/src/RainLoop/Plugins/Manager.php
index e4e0cee89..797c08e30 100644
--- a/rainloop/v/0.0.0/app/src/RainLoop/Plugins/Manager.php
+++ b/rainloop/v/0.0.0/app/src/RainLoop/Plugins/Manager.php
@@ -107,13 +107,15 @@ class Manager
}
}
}
+
+ $this->RunHook('api.bootstrap.plugins');
}
}
/**
* @param string $sName
*
- * @return \RainLoop\Plugins\AbstractPlugin | null
+ * @return \RainLoop\Plugins\AbstractPlugin|null
*/
public function CreatePluginByName($sName)
{
@@ -134,9 +136,10 @@ class Manager
if ($oPlugin instanceof \RainLoop\Plugins\AbstractPlugin)
{
$oPlugin
- ->SetValues(APP_PLUGINS_PATH.$sName, $sName,
- \file_exists(APP_PLUGINS_PATH.$sName.'/VERSION') ?
- \file_get_contents(APP_PLUGINS_PATH.$sName.'/VERSION') : '')
+ ->SetName($sName)
+ ->SetPath(APP_PLUGINS_PATH.$sName)
+ ->SetVersion(\file_exists(APP_PLUGINS_PATH.$sName.'/VERSION') ?
+ \file_get_contents(APP_PLUGINS_PATH.$sName.'/VERSION') : '')
->SetPluginManager($this)
->SetPluginConfig(new \RainLoop\Config\Plugin($sName, $oPlugin->ConfigMap()))
;
@@ -167,9 +170,8 @@ class Manager
if (\preg_match('/^[a-z0-9\-]+$/', $sName) &&
\file_exists($sPathName.'/index.php'))
{
- $sVersion = @\file_get_contents($sPathName.'/VERSION');
$aList[] = array(
- $sName, $sVersion
+ $sName, @\file_get_contents($sPathName.'/VERSION')
);
}
}
@@ -205,7 +207,7 @@ class Manager
}
/**
- * @return \RainLoop\Actions
+ * @return string
*/
public function Hash()
{
@@ -231,14 +233,14 @@ class Manager
$aJs = $bAdminScope ? $this->aAdminJs : $this->aJs;
foreach ($aJs as $sFile)
{
- if (file_exists($sFile))
+ if (\file_exists($sFile))
{
- $aResult[] = file_get_contents($sFile);
+ $aResult[] = \file_get_contents($sFile);
}
}
}
- return implode("\n", $aResult);
+ return \implode("\n", $aResult);
}
/**
@@ -279,12 +281,13 @@ class Manager
/**
* @param bool $bAdmin
* @param array $aAppData
+ * @param \RainLoop\Model\Account|null $oAccount = null
*
* @return \RainLoop\Plugins\Manager
*/
public function InitAppData($bAdmin, &$aAppData, $oAccount = null)
{
- if ($this->bIsEnabled && isset($aAppData['Plugins']) && is_array($aAppData['Plugins']))
+ if ($this->bIsEnabled && isset($aAppData['Plugins']) && \is_array($aAppData['Plugins']))
{
$bAuth = isset($aAppData['Auth']) && !!$aAppData['Auth'];
foreach ($this->aPlugins as $oPlugin)
@@ -317,6 +320,12 @@ class Manager
}
$this->RunHook('filter.app-data', array($bAdmin, &$aAppData));
+
+ $this->RunHook('filter.app-data[2]', array(
+ 'IsAdmin' => $bAdmin,
+ 'AppData' => &$aAppData,
+ 'Account' => $oAccount
+ ));
}
return $this;
@@ -330,7 +339,7 @@ class Manager
*/
public function AddHook($sHookName, $mCallbak)
{
- if ($this->bIsEnabled && is_callable($mCallbak))
+ if ($this->bIsEnabled && \is_callable($mCallbak))
{
if (!isset($this->aHooks[$sHookName]))
{
@@ -407,9 +416,9 @@ class Manager
$this->WriteLog('Hook: '.$sHookName, \MailSo\Log\Enumerations\Type::NOTE);
}
- foreach ($this->aHooks[$sHookName] as $mCallbak)
+ foreach ($this->aHooks[$sHookName] as $mCallback)
{
- call_user_func_array($mCallbak, $aArg);
+ \call_user_func_array($mCallback, $aArg);
}
}
}
@@ -491,11 +500,11 @@ class Manager
if ($bPrepend)
{
- array_unshift($this->aProcessTemplate[$sName][$sPlace], $sHtml);
+ \array_unshift($this->aProcessTemplate[$sName][$sPlace], $sHtml);
}
else
{
- array_push($this->aProcessTemplate[$sName][$sPlace], $sHtml);
+ \array_push($this->aProcessTemplate[$sName][$sPlace], $sHtml);
}
}
@@ -510,7 +519,7 @@ class Manager
*/
public function AddAdditionalAjaxAction($sActionName, $mCallbak)
{
- if ($this->bIsEnabled && is_callable($mCallbak) && 0 < strlen($sActionName))
+ if ($this->bIsEnabled && \is_callable($mCallbak) && 0 < \strlen($sActionName))
{
$sActionName = 'Do'.$sActionName;
@@ -544,7 +553,7 @@ class Manager
{
if (isset($this->aAdditionalAjax[$sActionName]))
{
- return call_user_func($this->aAdditionalAjax[$sActionName]);
+ return \call_user_func($this->aAdditionalAjax[$sActionName]);
}
}
@@ -641,29 +650,29 @@ class Manager
/**
* @param string $sDesc
- * @param int $iDescType = \MailSo\Log\Enumerations\Type::INFO
+ * @param int $iType = \MailSo\Log\Enumerations\Type::INFO
*
* @return void
*/
- public function WriteLog($sDesc, $iDescType = \MailSo\Log\Enumerations\Type::INFO)
+ public function WriteLog($sDesc, $iType = \MailSo\Log\Enumerations\Type::INFO)
{
if ($this->oLogger)
{
- $this->oLogger->Write($sDesc, $iDescType, 'PLUGIN');
+ $this->oLogger->Write($sDesc, $iType, 'PLUGIN');
}
}
/**
* @param string $sDesc
- * @param int $iDescType = \MailSo\Log\Enumerations\Type::INFO
+ * @param int $iType = \MailSo\Log\Enumerations\Type::INFO
*
* @return void
*/
- public function WriteException($sDesc, $iDescType = \MailSo\Log\Enumerations\Type::INFO)
+ public function WriteException($sDesc, $iType = \MailSo\Log\Enumerations\Type::INFO)
{
if ($this->oLogger)
{
- $this->oLogger->WriteException($sDesc, $iDescType, 'PLUGIN');
+ $this->oLogger->WriteException($sDesc, $iType, 'PLUGIN');
}
}
}
diff --git a/rainloop/v/0.0.0/app/src/RainLoop/PluginsNext/AbstractPlugin.php b/rainloop/v/0.0.0/app/src/RainLoop/PluginsNext/AbstractPlugin.php
deleted file mode 100644
index bb374b0dd..000000000
--- a/rainloop/v/0.0.0/app/src/RainLoop/PluginsNext/AbstractPlugin.php
+++ /dev/null
@@ -1,340 +0,0 @@
-sName = '';
- $this->sPath = '';
- $this->sVersion = '0.0';
- $this->aConfigMap = null;
-
- $this->oPluginManager = null;
- $this->oPluginConfig = null;
- $this->bPluginConfigLoaded = false;
- $this->bLangs = false;
- }
-
- /**
- * @return \RainLoop\Config\Plugin
- */
- public function Config()
- {
- if (!$this->bPluginConfigLoaded && $this->oPluginConfig)
- {
- $this->bPluginConfigLoaded = true;
- if ($this->oPluginConfig->IsInited())
- {
- if (!$this->oPluginConfig->Load())
- {
- $this->oPluginConfig->Save();
- }
- }
- }
-
- return $this->oPluginConfig;
- }
-
- /**
- * @return \RainLoop\PluginsNext\Manager
- */
- public function Manager()
- {
- return $this->oPluginManager;
- }
-
- /**
- * @return string
- */
- public function Path()
- {
- return $this->sPath;
- }
-
- /**
- * @return string
- */
- public function Name()
- {
- return $this->sName;
- }
-
- /**
- * @return string
- */
- public function Version()
- {
- return $this->sVersion;
- }
-
- /**
- * @param bool|null $bLangs = null
- * @return bool
- */
- public function UseLangs($bLangs = null)
- {
- if (null !== $bLangs)
- {
- $this->bLangs = (bool) $bLangs;
- }
-
- return $this->bLangs;
- }
-
- /**
- * @return array
- */
- protected function configMapping()
- {
- return array();
- }
-
- /**
- * @return string
- */
- public function Hash()
- {
- return \md5($this->sVersion);
- }
-
- /**
- * @return string
- */
- public function Supported()
- {
- return '';
- }
-
- /**
- * @final
- * @return array
- */
- final public function ConfigMap()
- {
- if (null === $this->aConfigMap)
- {
- $this->aConfigMap = $this->configMapping();
- if (!\is_array($this->aConfigMap))
- {
- $this->aConfigMap = array();
- }
- }
-
- return $this->aConfigMap;
- }
-
- /**
- * @param string $sPath
- * @param string $sName
- * @param string $sVersion = ''
- *
- * @return self
- */
- public function SetValues($sPath, $sName, $sVersion = '')
- {
- $this->sName = $sName;
- $this->sPath = $sPath;
-
- if (0 < \strlen($sVersion))
- {
- $this->sVersion = $sVersion;
- }
-
- return $this;
- }
-
- /**
- * @param \RainLoop\PluginsNext\Manager $oPluginManager
- *
- * @return self
- */
- public function SetPluginManager(\RainLoop\PluginsNext\Manager $oPluginManager)
- {
- $this->oPluginManager = $oPluginManager;
-
- return $this;
- }
-
- /**
- * @param \RainLoop\Config\Plugin $oPluginConfig
- *
- * @return self
- */
- public function SetPluginConfig(\RainLoop\Config\Plugin $oPluginConfig)
- {
- $this->oPluginConfig = $oPluginConfig;
-
- return $this;
- }
-
- /**
- * @return self
- */
- public function Init()
- {
-
- }
-
- /**
- * @param string $sStep
- *
- * @return self
- */
- public function InitStep($sStep)
- {
-
- }
-
- /**
- * @param bool $bAdmin
- * @param bool $bAuth
- * @param array $aConfig
- *
- * @return void
- */
- public function FilterAppDataPluginSection($bAdmin, $bAuth, &$aConfig)
- {
-
- }
-
- /**
- * @param string $sHookName
- * @param string $sFunctionName
- *
- * @return self
- */
- protected function addHook($sHookName, $sFunctionName)
- {
- if ($this->oPluginManager)
- {
- $this->oPluginManager->AddHook($sHookName, array(&$this, $sFunctionName));
- }
-
- return $this;
- }
-
- /**
- * @param string $sFile
- * @param bool $bAdminScope = false
- *
- * @return self
- */
- protected function addJs($sFile, $bAdminScope = false)
- {
- if ($this->oPluginManager)
- {
- $this->oPluginManager->AddJs($this->sPath.'/'.$sFile, $bAdminScope);
- }
-
- return $this;
- }
-
- /**
- * @param string $sFile
- * @param bool $bAdminScope = false
- *
- * @return self
- */
- protected function addTemplate($sFile, $bAdminScope = false)
- {
- if ($this->oPluginManager)
- {
- $this->oPluginManager->AddTemplate($this->sPath.'/'.$sFile, $bAdminScope);
- }
-
- return $this;
- }
-
- /**
- * @param string $sActionName
- * @param string $sFunctionName
- *
- * @return self
- */
- protected function addPartHook($sActionName, $sFunctionName)
- {
- if ($this->oPluginManager)
- {
- $this->oPluginManager->AddAdditionalPartAction($sActionName, array(&$this, $sFunctionName));
- }
-
- return $this;
- }
-
- /**
- * @param string $sActionName
- * @param string $sFunctionName
- *
- * @return self
- */
- protected function addAjaxHook($sActionName, $sFunctionName)
- {
- if ($this->oPluginManager)
- {
- $this->oPluginManager->AddAdditionalAjaxAction($sActionName, array(&$this, $sFunctionName));
- }
-
- return $this;
- }
-
- /**
- * @param string $sName
- * @param string $sPlace
- * @param string $sLocalTemplateName
- * @param bool $bPrepend = false
- *
- * @return self
- */
- protected function addTemplateHook($sName, $sPlace, $sLocalTemplateName, $bPrepend = false)
- {
- if ($this->oPluginManager)
- {
- $this->oPluginManager->AddProcessTemplateAction($sName, $sPlace,
- '', $bPrepend);
- }
-
- return $this;
- }
-}
diff --git a/rainloop/v/0.0.0/app/src/RainLoop/PluginsNext/Manager.php b/rainloop/v/0.0.0/app/src/RainLoop/PluginsNext/Manager.php
deleted file mode 100644
index cee2acc81..000000000
--- a/rainloop/v/0.0.0/app/src/RainLoop/PluginsNext/Manager.php
+++ /dev/null
@@ -1,685 +0,0 @@
-oLogger = null;
- $this->oActions = $oActions;
- $this->aPlugins = array();
-
- $this->aHooks = array();
- $this->aJs = array();
- $this->aAdminJs = array();
- $this->aTemplates = array();
- $this->aAdminTemplates = array();
-
- $this->aAjaxFilters = array();
- $this->aAdditionalAjax = array();
- $this->aProcessTemplate = array();
-
- $this->bIsEnabled = (bool) $this->oActions->Config()->Get('plugins', 'enable', false);
- if ($this->bIsEnabled)
- {
- $sList = \strtolower($this->oActions->Config()->Get('plugins', 'enabled_list', ''));
- if (0 < \strlen($sList))
- {
- $aList = \explode(',', $sList);
- $aList = \array_map('trim', $aList);
-
- foreach ($aList as $sName)
- {
- if (0 < \strlen($sName))
- {
- $oPlugin = $this->CreatePluginByName($sName);
- if ($oPlugin)
- {
- $oPlugin->InitStep('step1');
- $oPlugin->Init();
- $oPlugin->InitStep('step2');
-
- $this->aPlugins[] = $oPlugin;
-
- $oPlugin->InitStep('spep3');
- }
- }
- }
- }
-
- $this->RunHook('api.bootstrap.plugins');
- }
- }
-
- /**
- * @param string $sName
- *
- * @return \RainLoop\Plugins\AbstractPlugin|null
- */
- public function CreatePluginByName($sName)
- {
- $oPlugin = null;
- if (\preg_match('/^[a-z0-9\-]+$/', $sName) &&
- \file_exists(APP_PLUGINS_PATH.$sName.'/index.php'))
- {
- $sClassName = $this->convertPluginFolderNameToClassName($sName);
-
- if (!\class_exists($sClassName))
- {
- include APP_PLUGINS_PATH.$sName.'/index.php';
- }
-
- if (\class_exists($sClassName))
- {
- $oPlugin = new $sClassName();
- if ($oPlugin instanceof \RainLoop\PluginsNext\AbstractPlugin)
- {
- $oPlugin
- ->SetValues(APP_PLUGINS_PATH.$sName, $sName,
- \file_exists(APP_PLUGINS_PATH.$sName.'/VERSION') ?
- \file_get_contents(APP_PLUGINS_PATH.$sName.'/VERSION') : '')
- ->SetPluginManager($this)
- ->SetPluginConfig(new \RainLoop\Config\Plugin($sName, $oPlugin->ConfigMap()))
- ;
- }
- else
- {
- $oPlugin = null;
- }
- }
- }
-
- return $oPlugin;
- }
-
- /**
- * @return array
- */
- public function InstalledPlugins()
- {
- $aList = array();
-
- $aGlob = @\glob(APP_PLUGINS_PATH.'*', GLOB_ONLYDIR|GLOB_NOSORT);
- if (\is_array($aGlob))
- {
- foreach ($aGlob as $sPathName)
- {
- $sName = \basename($sPathName);
- if (\preg_match('/^[a-z0-9\-]+$/', $sName) &&
- \file_exists($sPathName.'/index.php'))
- {
- $aList[] = array(
- $sName, @\file_get_contents($sPathName.'/VERSION')
- );
- }
- }
- }
- else
- {
- $this->Actions()->Logger()->Write('Cannot get installed plugins from '.APP_PLUGINS_PATH,
- \MailSo\Log\Enumerations\Type::ERROR);
- }
-
- return $aList;
- }
-
- /**
- * @param string $sFolderName
- *
- * @return string
- */
- private function convertPluginFolderNameToClassName($sFolderName)
- {
- $aParts = \array_map('ucfirst', \array_map('strtolower',
- \explode(' ', \preg_replace('/[^a-z0-9]+/', ' ', $sFolderName))));
-
- return \implode($aParts).'Plugin';
- }
-
- /**
- * @return \RainLoop\Actions
- */
- public function Actions()
- {
- return $this->oActions;
- }
-
- /**
- * @return string
- */
- public function Hash()
- {
- $sResult = \md5(APP_VERSION);
- foreach ($this->aPlugins as $oPlugin)
- {
- $sResult = \md5($sResult.$oPlugin->Path().$oPlugin->Hash());
- }
-
- return $sResult;
- }
-
- /**
- * @param bool $bAdminScope = false
- *
- * @return string
- */
- public function CompileJs($bAdminScope = false)
- {
- $aResult = array();
- if ($this->bIsEnabled)
- {
- $aJs = $bAdminScope ? $this->aAdminJs : $this->aJs;
- foreach ($aJs as $sFile)
- {
- if (\file_exists($sFile))
- {
- $aResult[] = \file_get_contents($sFile);
- }
- }
- }
-
- return \implode("\n", $aResult);
- }
-
- /**
- * @todo
- * @param bool $bAdminScope = false
- *
- * @return string
- */
- public function CompileCss($bAdminScope = false)
- {
- return '';
- }
-
- /**
- * @param bool $bAdminScope = false
- * @return string
- */
- public function CompileTemplate($bAdminScope = false)
- {
- $sResult = '';
- if ($this->bIsEnabled)
- {
- foreach ($bAdminScope ? $this->aAdminTemplates : $this->aTemplates as $sFile)
- {
- if (\file_exists($sFile))
- {
- $sTemplateName = \substr(\basename($sFile), 0, -5);
- $sResult .= '';
- }
- }
- }
-
- return $sResult;
- }
-
- /**
- * @param bool $bAdmin
- * @param array $aAppData
- * @param \RainLoop\Model\Account|null $oAccount = null
- *
- * @return \RainLoop\PluginsNext\Manager
- */
- public function InitAppData($bAdmin, &$aAppData, $oAccount = null)
- {
- if ($this->bIsEnabled && isset($aAppData['Plugins']) && \is_array($aAppData['Plugins']))
- {
- $bAuth = isset($aAppData['Auth']) && !!$aAppData['Auth'];
- foreach ($this->aPlugins as $oPlugin)
- {
- if ($oPlugin)
- {
- $aConfig = array();
- $aMap = $oPlugin->ConfigMap();
- if (\is_array($aMap))
- {
- foreach ($aMap as /* @var $oPluginProperty \RainLoop\PluginsNext\Property */$oPluginProperty)
- {
- if ($oPluginProperty && $oPluginProperty->AllowedInJs())
- {
- $aConfig[$oPluginProperty->Name()] =
- $oPlugin->Config()->Get('plugin',
- $oPluginProperty->Name(),
- $oPluginProperty->DefaultValue());
- }
- }
- }
-
- $oPlugin->FilterAppDataPluginSection($bAdmin, $bAuth, $aConfig);
-
- if (0 < \count($aConfig))
- {
- $aAppData['Plugins'][$oPlugin->Name()] = $aConfig;
- }
- }
- }
-
- $this->RunHook('filter.app-data', array(
- 'IsAdmin' => $bAdmin,
- 'AppData' => &$aAppData
- ), $oAccount);
- }
-
- return $this;
- }
-
- /**
- * @param string $sHookName
- * @param mixed $mCallbak
- *
- * @return \RainLoop\PluginsNext\Manager
- */
- public function AddHook($sHookName, $mCallbak)
- {
- if ($this->bIsEnabled && \is_callable($mCallbak))
- {
- if (!isset($this->aHooks[$sHookName]))
- {
- $this->aHooks[$sHookName] = array();
- }
-
- $this->aHooks[$sHookName][] = $mCallbak;
- }
-
- return $this;
- }
-
- /**
- * @param string $sFile
- * @param bool $bAdminScope = false
- *
- * @return \RainLoop\PluginsNext\Manager
- */
- public function AddJs($sFile, $bAdminScope = false)
- {
- if ($this->bIsEnabled)
- {
- if ($bAdminScope)
- {
- $this->aAdminJs[$sFile] = $sFile;
- }
- else
- {
- $this->aJs[$sFile] = $sFile;
- }
- }
-
- return $this;
- }
-
- /**
- * @param string $sFile
- * @param bool $bAdminScope = false
- *
- * @return \RainLoop\PluginsNext\Manager
- */
- public function AddTemplate($sFile, $bAdminScope = false)
- {
- if ($this->bIsEnabled)
- {
- if ($bAdminScope)
- {
- $this->aAdminTemplates[$sFile] = $sFile;
- }
- else
- {
- $this->aTemplates[$sFile] = $sFile;
- }
- }
-
- return $this;
- }
-
- /**
- * @param string $sHookName
- * @param array $aArg = array()
- * @param \RainLoop\Model\Account|null $oAccount = null
- * @param bool $bLogHook = true
- *
- * @return \RainLoop\PluginsNext\Manager
- */
- public function RunHook($sHookName, $aArg = array(), $oAccount = null, $bLogHook = true)
- {
- if ($this->bIsEnabled)
- {
- if (isset($this->aHooks[$sHookName]))
- {
- if ($bLogHook)
- {
- $this->WriteLog('Hook: '.$sHookName, \MailSo\Log\Enumerations\Type::NOTE);
- }
-
- $bArgArray = 0 < \count($aArg);
- foreach ($this->aHooks[$sHookName] as $mCallbak)
- {
- if ($bArgArray)
- {
- \call_user_func_array($mCallbak, array($aArg));
- }
- else
- {
- \call_user_func($mCallbak);
- }
- }
- }
- }
-
- return $this;
- }
-
- /**
- * @param string $sActionName
- * @param mixed $mCallbak
- *
- * @return \RainLoop\PluginsNext\Manager
- */
- public function AddAdditionalPartAction($sActionName, $mCallbak)
- {
- if ($this->bIsEnabled && \is_callable($mCallbak))
- {
- $sActionName = \strtolower($sActionName);
- if (!isset($this->aAdditionalParts[$sActionName]))
- {
- $this->aAdditionalParts[$sActionName] = array();
- }
-
- $this->aAdditionalParts[$sActionName][] = $mCallbak;
- }
-
- return $this;
- }
-
- /**
- * @param string $sActionName
- * @param array $aParts = array()
- *
- * @return \RainLoop\PluginsNext\Manager
- */
- public function RunAdditionalPart($sActionName, $aParts = array())
- {
- $bResult = false;
- if ($this->bIsEnabled)
- {
- $sActionName = \strtolower($sActionName);
- if (isset($this->aAdditionalParts[$sActionName]))
- {
- foreach ($this->aAdditionalParts[$sActionName] as $mCallbak)
- {
- $bCallResult = \call_user_func_array($mCallbak, $aParts);
- if ($bCallResult && !$bResult)
- {
- $bResult = true;
- }
- }
- }
- }
-
- return $bResult;
- }
-
- /**
- * @param string $sName
- * @param string $sPlace
- * @param string $sHtml
- * @param bool $bPrepend = false
- *
- * @return \RainLoop\PluginsNext\Manager
- */
- public function AddProcessTemplateAction($sName, $sPlace, $sHtml, $bPrepend = false)
- {
- if ($this->bIsEnabled)
- {
- if (!isset($this->aProcessTemplate[$sName]))
- {
- $this->aProcessTemplate[$sName] = array();
- }
-
- if (!isset($this->aProcessTemplate[$sName][$sPlace]))
- {
- $this->aProcessTemplate[$sName][$sPlace] = array();
- }
-
- if ($bPrepend)
- {
- \array_unshift($this->aProcessTemplate[$sName][$sPlace], $sHtml);
- }
- else
- {
- \array_push($this->aProcessTemplate[$sName][$sPlace], $sHtml);
- }
- }
-
- return $this;
- }
-
- /**
- * @param string $sActionName
- * @param mixed $mCallbak
- *
- * @return \RainLoop\Plugins\Manager
- */
- public function AddAdditionalAjaxAction($sActionName, $mCallbak)
- {
- if ($this->bIsEnabled && \is_callable($mCallbak) && 0 < \strlen($sActionName))
- {
- $sActionName = 'Do'.$sActionName;
-
- if (!isset($this->aAdditionalAjax[$sActionName]))
- {
- $this->aAdditionalAjax[$sActionName] = $mCallbak;
- }
- }
-
- return $this;
- }
-
- /**
- * @param string $sActionName
- *
- * @return bool
- */
- public function HasAdditionalAjax($sActionName)
- {
- return $this->bIsEnabled && isset($this->aAdditionalAjax[$sActionName]);
- }
-
- /**
- * @param string $sActionName
- *
- * @return mixed
- */
- public function RunAdditionalAjax($sActionName)
- {
- if ($this->bIsEnabled)
- {
- if (isset($this->aAdditionalAjax[$sActionName]))
- {
- return \call_user_func($this->aAdditionalAjax[$sActionName]);
- }
- }
-
- return false;
- }
-
- /**
- * @param string $sLang
- * @param array $sActionName
- *
- * @return \RainLoop\PluginsNext\Manager
- */
- public function ReadLang($sLang, &$aLang)
- {
- if ($this->bIsEnabled)
- {
- foreach ($this->aPlugins as $oPlugin)
- {
- if ($oPlugin->UseLangs())
- {
- $sPath = $oPlugin->Path();
-
- \RainLoop\Utils::ReadAndAddLang($sPath.'/langs/en.ini', $aLang);
- if ('en' !== $sLang)
- {
- \RainLoop\Utils::ReadAndAddLang($sPath.'/langs/'.$sLang.'.ini', $aLang);
- }
- }
- }
- }
-
- return $this;
- }
-
- /**
- * @param string $sName
- * @param string $sHtml
- *
- * @return string
- */
- public function ProcessTemplate($sName, $sHtml)
- {
- if (isset($this->aProcessTemplate[$sName]))
- {
- foreach ($this->aProcessTemplate[$sName] as $sPlace => $aAddHtml)
- {
- if (\is_array($aAddHtml) && 0 < \count($aAddHtml))
- {
- foreach ($aAddHtml as $sAddHtml)
- {
- $sHtml = \str_replace('{{INCLUDE/'.$sPlace.'/PLACE}}', $sAddHtml.'{{INCLUDE/'.$sPlace.'/PLACE}}', $sHtml);
- }
- }
- }
- }
-
- return $sHtml;
- }
-
- /**
- * @return bool
- */
- public function bIsEnabled()
- {
- return $this->bIsEnabled;
- }
-
- /**
- * @return int
- */
- public function Count()
- {
- return $this->bIsEnabled ? \count($this->aPlugins) : 0;
- }
-
- /**
- * @param \MailSo\Log\Logger $oLogger
- *
- * @return \RainLoop\PluginsNext\Manager
- *
- * @throws \MailSo\Base\Exceptions\InvalidArgumentException
- */
- public function SetLogger($oLogger)
- {
- if (!($oLogger instanceof \MailSo\Log\Logger))
- {
- throw new \MailSo\Base\Exceptions\InvalidArgumentException();
- }
-
- $this->oLogger = $oLogger;
-
- return $this;
- }
-
- /**
- * @param string $sDesc
- * @param int $iType = \MailSo\Log\Enumerations\Type::INFO
- *
- * @return void
- */
- public function WriteLog($sDesc, $iType = \MailSo\Log\Enumerations\Type::INFO)
- {
- if ($this->oLogger)
- {
- $this->oLogger->Write($sDesc, $iType, 'PLUGIN');
- }
- }
-
- /**
- * @param string $sDesc
- * @param int $iType = \MailSo\Log\Enumerations\Type::INFO
- *
- * @return void
- */
- public function WriteException($sDesc, $iType = \MailSo\Log\Enumerations\Type::INFO)
- {
- if ($this->oLogger)
- {
- $this->oLogger->WriteException($sDesc, $iType, 'PLUGIN');
- }
- }
-}
diff --git a/rainloop/v/0.0.0/app/src/RainLoop/PluginsNext/Property.php b/rainloop/v/0.0.0/app/src/RainLoop/PluginsNext/Property.php
deleted file mode 100644
index 065ddf588..000000000
--- a/rainloop/v/0.0.0/app/src/RainLoop/PluginsNext/Property.php
+++ /dev/null
@@ -1,179 +0,0 @@
-sName = $sName;
- $this->iType = \RainLoop\Enumerations\PluginPropertyType::STRING;
- $this->mDefaultValue = '';
- $this->sLabel = '';
- $this->sDesc = '';
- $this->bAllowedInJs = false;
- }
-
- /**
- * @param string $sName
- *
- * @return \RainLoop\PluginsNext\Property
- */
- public static function NewInstance($sName)
- {
- return new self($sName);
- }
-
- /**
- * @param int $iType
- *
- * @return \RainLoop\PluginsNext\Property
- */
- public function SetType($iType)
- {
- $this->iType = (int) $iType;
-
- return $this;
- }
-
- /**
- * @param mixed $mDefaultValue
- *
- * @return \RainLoop\PluginsNext\Property
- */
- public function SetDefaultValue($mDefaultValue)
- {
- $this->mDefaultValue = $mDefaultValue;
-
- return $this;
- }
-
- /**
- * @param string $sLabel
- *
- * @return \RainLoop\PluginsNext\Property
- */
- public function SetLabel($sLabel)
- {
- $this->sLabel = $sLabel;
-
- return $this;
- }
-
- /**
- * @param string $sDesc
- *
- * @return \RainLoop\PluginsNext\Property
- */
- public function SetDescription($sDesc)
- {
- $this->sDesc = $sDesc;
-
- return $this;
- }
-
- /**
- * @param bool $bValue = true
- *
- * @return \RainLoop\PluginsNext\Property
- */
- public function SetAllowedInJs($bValue = true)
- {
- $this->bAllowedInJs = !!$bValue;
-
- return $this;
- }
-
- /**
- * @return string
- */
- public function Name()
- {
- return $this->sName;
- }
-
- /**
- * @return bool
- */
- public function AllowedInJs()
- {
- return $this->bAllowedInJs;
- }
-
- /**
- * @return string
- */
- public function Description()
- {
- return $this->sDesc;
- }
-
- /**
- * @return string
- */
- public function Label()
- {
- return $this->sLabel;
- }
-
- /**
- * @return int
- */
- public function Type()
- {
- return $this->iType;
- }
-
- /**
- * @return mixed
- */
- public function DefaultValue()
- {
- return $this->mDefaultValue;
- }
-
- /**
- * @return array
- */
- public function ToArray()
- {
- return array(
- '',
- $this->sName,
- $this->iType,
- $this->sLabel,
- $this->mDefaultValue,
- $this->sDesc
- );
- }
-}
diff --git a/rainloop/v/0.0.0/app/src/RainLoop/Providers/Domain.php b/rainloop/v/0.0.0/app/src/RainLoop/Providers/Domain.php
index 8e27a1244..5df222f4e 100644
--- a/rainloop/v/0.0.0/app/src/RainLoop/Providers/Domain.php
+++ b/rainloop/v/0.0.0/app/src/RainLoop/Providers/Domain.php
@@ -130,7 +130,6 @@ class Domain extends \RainLoop\Providers\AbstractProvider
$iIncSecure = (int) $oActions->GetActionParam('IncSecure', \MailSo\Net\Enumerations\ConnectionSecurityType::NONE);
$bIncShortLogin = '1' === (string) $oActions->GetActionParam('IncShortLogin', '0');
$bUseSieve = '1' === (string) $oActions->GetActionParam('UseSieve', '0');
- $bUseImapServerForSieve = '1' === (string) $oActions->GetActionParam('UseImapServerForSieve', '1');
$sSieveHost = (string) $oActions->GetActionParam('SieveHost', '');
$iSievePort = (int) $oActions->GetActionParam('SievePort', 2000);
$iSieveSecure = (int) $oActions->GetActionParam('SieveSecure', \MailSo\Net\Enumerations\ConnectionSecurityType::NONE);
@@ -160,7 +159,7 @@ class Domain extends \RainLoop\Providers\AbstractProvider
{
$oDomain->UpdateInstance(
$sIncHost, $iIncPort, $iIncSecure, $bIncShortLogin,
- $bUseSieve, $bUseImapServerForSieve, $sSieveHost, $iSievePort, $iSieveSecure,
+ $bUseSieve, $sSieveHost, $iSievePort, $iSieveSecure,
$sOutHost, $iOutPort, $iOutSecure, $bOutShortLogin, $bOutAuth, $bOutUsePhpMail,
$sWhiteList);
}
@@ -169,7 +168,7 @@ class Domain extends \RainLoop\Providers\AbstractProvider
{
$oDomain = \RainLoop\Model\Domain::NewInstance(0 < strlen($sNameForTest) ? $sNameForTest : $sName,
$sIncHost, $iIncPort, $iIncSecure, $bIncShortLogin,
- $bUseSieve, $bUseImapServerForSieve, $sSieveHost, $iSievePort, $iSieveSecure,
+ $bUseSieve, $sSieveHost, $iSievePort, $iSieveSecure,
$sOutHost, $iOutPort, $iOutSecure, $bOutShortLogin, $bOutAuth, $bOutUsePhpMail,
$sWhiteList);
}
diff --git a/rainloop/v/0.0.0/app/src/RainLoop/Providers/Filters.php b/rainloop/v/0.0.0/app/src/RainLoop/Providers/Filters.php
new file mode 100644
index 000000000..cf0398763
--- /dev/null
+++ b/rainloop/v/0.0.0/app/src/RainLoop/Providers/Filters.php
@@ -0,0 +1,45 @@
+oDriver = $oDriver instanceof \RainLoop\Providers\Filters\FiltersInterface ? $oDriver : null;
+ }
+
+ /**
+ * @return array
+ */
+ public function Load()
+ {
+ return $this->IsActive() ? $this->oDriver->Load() : array();
+ }
+
+ /**
+ * @param array $aFilters
+ *
+ * @return bool
+ */
+ public function Save($aFilters)
+ {
+ return $this->IsActive() ? $this->oDriver->Save($aFilters) : false;
+ }
+
+ /**
+ * @return bool
+ */
+ public function IsActive()
+ {
+ return $this->oDriver instanceof \RainLoop\Providers\Filters\FiltersInterface;
+ }
+}
\ No newline at end of file
diff --git a/rainloop/v/0.0.0/app/src/RainLoop/Providers/Filters/Classes/Filter.php b/rainloop/v/0.0.0/app/src/RainLoop/Providers/Filters/Classes/Filter.php
new file mode 100644
index 000000000..d2522681d
--- /dev/null
+++ b/rainloop/v/0.0.0/app/src/RainLoop/Providers/Filters/Classes/Filter.php
@@ -0,0 +1,150 @@
+Clear();
+ }
+
+ public function Clear()
+ {
+ $this->sName = '';
+
+ $this->aConditions = array();
+
+ $this->sFilterRulesType = \RainLoop\Providers\Filters\Enumerations\FilterRulesType::ALL;
+
+ $this->sActionType = \RainLoop\Providers\Filters\Enumerations\ActionType::MOVE_TO;
+ $this->sActionValue = '';
+
+ $this->bMarkAsRead = false;
+ $this->bSkipOthers = false;
+ }
+
+ /**
+ * @return string
+ */
+ public function Name()
+ {
+ return $this->sName;
+ }
+
+ /**
+ * @return array
+ */
+ public function Conditions()
+ {
+ return $this->aConditions;
+ }
+
+ /**
+ * @return string
+ */
+ public function FilterRulesType()
+ {
+ return $this->sFilterRulesType;
+ }
+
+ /**
+ * @return string
+ */
+ public function ActionType()
+ {
+ return $this->sActionType;
+ }
+
+ /**
+ * @return string
+ */
+ public function ActionValue()
+ {
+ return $this->sActionValue;
+ }
+
+ /**
+ * @return bool
+ */
+ public function MarkAsRead()
+ {
+ return $this->bMarkAsRead;
+ }
+
+ /**
+ * @return bool
+ */
+ public function SkipOthers()
+ {
+ return $this->bSkipOthers;
+ }
+
+ /**
+ * @return string
+ */
+ public function serializeToJson()
+ {
+ return \json_encode($this->ToSimpleJSON());
+ }
+
+ /**
+ * @param string $sFilterJson
+ */
+ public function unserializeFromJson($sFilterJson)
+ {
+ $sFilterJson = \json_decode(\trim($sFilterJson));
+ if (!empty($sFilterJson))
+ {
+ }
+ }
+
+ /**
+ * @param bool $bAjax = false
+ *
+ * @return array
+ */
+ public function ToSimpleJSON($bAjax = false)
+ {
+ $aConditions = $this->Conditions();
+ return array(
+ 'Name' => $this->Name(),
+ 'Conditions' => $aConditions,
+ 'FilterRulesType' => $this->FilterRulesType(),
+ 'ActionType' => $this->ActionType(),
+ 'ActionValue' => $this->ActionValue(),
+ 'MarkAsRead' => $this->MarkAsRead(),
+ 'SkipOthers' => $this->SkipOthers()
+ );
+ }
+}
diff --git a/rainloop/v/0.0.0/app/src/RainLoop/Providers/Filters/Enumerations/ActionType.php b/rainloop/v/0.0.0/app/src/RainLoop/Providers/Filters/Enumerations/ActionType.php
new file mode 100644
index 000000000..d7472fc8a
--- /dev/null
+++ b/rainloop/v/0.0.0/app/src/RainLoop/Providers/Filters/Enumerations/ActionType.php
@@ -0,0 +1,10 @@
+fileStringToCollection(@\file_get_contents('e:/sieve.txt'));
+ }
+
+ /**
+ * @param array $aFilters
+ *
+ * @return bool
+ */
+ public function Save($aFilters)
+ {
+ return @\file_put_contents('e:/sieve.txt', $this->collectionToFileString($aFilters));
+ }
+
+ /**
+ * @param array $aFilters
+ *
+ * @return string
+ */
+ private function collectionToFileString($aFilters)
+ {
+ $aParts = array();
+
+ foreach ($aFilters as /* @var $oItem \RainLoop\Providers\Filters\Classes\Filter */ $oItem)
+ {
+ $sItem = $oItem->serializeToJson();
+ $sItem = \chunk_split(\base64_encode($sItem), 74, "\n");
+
+ $aParts[] = $sItem;
+ }
+
+ return \implode("\n", $aParts);
+ }
+
+ /**
+ * @param string $sFileString
+ *
+ * @return array
+ */
+ private function fileStringToCollection($sFileString)
+ {
+ if (!empty($sFileString))
+ {
+
+ }
+
+ return array();
+ }
+}
diff --git a/rainloop/v/0.0.0/app/templates/Index.html b/rainloop/v/0.0.0/app/templates/Index.html
index 0395264aa..8effbe0c5 100644
--- a/rainloop/v/0.0.0/app/templates/Index.html
+++ b/rainloop/v/0.0.0/app/templates/Index.html
@@ -84,24 +84,33 @@
__simplePace(10);
window.$LAB
- .script('{{BaseAppLibsScriptLink}}')
- .script(window.rainloopAppData['TemplatesLink'])
- .script(window.rainloopAppData['LangLink'])
+ .script(function () {
+ return [
+ {'src': '{{BaseAppLibsScriptLink}}', 'type': 'text/javascript', 'charset': 'utf-8'},
+ {'src': window.rainloopAppData['TemplatesLink'], 'type': 'text/javascript', 'charset': 'utf-8'},
+ {'src': window.rainloopAppData['LangLink'], 'type': 'text/javascript', 'charset': 'utf-8'}
+ ];
+ })
.wait(function () {
__simplePace(30);
})
- .script('{{BaseAppMainScriptLink}}')
+ .script(function () {
+ return {'src': '{{BaseAppMainScriptLink}}', 'type': 'text/javascript', 'charset': 'utf-8'};
+ })
.wait(function () {
__simplePace(20);
})
.script(function () {
- return window.rainloopAppData['PluginsLink'] || null;
+ return window.rainloopAppData['PluginsLink'] ?
+ {'src': '{{BaseAppMainScriptLink}}', 'type': 'text/javascript', 'charset': 'utf-8'} : null;
})
.wait(function () {
__simplePace(5);
__runBoot(false);
})
- .script('{{BaseAppEditorScriptLink}}')
+ .script(function () {
+ return {'src': '{{BaseAppEditorScriptLink}}', 'type': 'text/javascript', 'charset': 'utf-8'};
+ })
.wait(function () {
if (window.CKEDITOR && window.__initEditor) {
window.__initEditor();
diff --git a/rainloop/v/0.0.0/app/templates/Views/Admin/AdminSettingsAbout.html b/rainloop/v/0.0.0/app/templates/Views/Admin/AdminSettingsAbout.html
index f740332c1..f7c9d8d40 100644
--- a/rainloop/v/0.0.0/app/templates/Views/Admin/AdminSettingsAbout.html
+++ b/rainloop/v/0.0.0/app/templates/Views/Admin/AdminSettingsAbout.html
@@ -25,7 +25,12 @@
- New
version is available.
+ New
+
+
+ ()
+
+ version is available.
()
@@ -56,7 +61,11 @@
- RainLoop is up to date.
+ RainLoop
+
+ ()
+
+ is up to date.
diff --git a/rainloop/v/0.0.0/app/templates/Views/Admin/PopupsDomain.html b/rainloop/v/0.0.0/app/templates/Views/Admin/PopupsDomain.html
index f5bb0163c..f6e549ca0 100644
--- a/rainloop/v/0.0.0/app/templates/Views/Admin/PopupsDomain.html
+++ b/rainloop/v/0.0.0/app/templates/Views/Admin/PopupsDomain.html
@@ -20,8 +20,8 @@
-
-
+
@@ -144,7 +133,7 @@
diff --git a/rainloop/v/0.0.0/app/templates/Views/Common/PopupsKeyboardShortcutsHelp.html b/rainloop/v/0.0.0/app/templates/Views/Common/PopupsKeyboardShortcutsHelp.html
index ffbfd2afa..52ec0cebb 100644
--- a/rainloop/v/0.0.0/app/templates/Views/Common/PopupsKeyboardShortcutsHelp.html
+++ b/rainloop/v/0.0.0/app/templates/Views/Common/PopupsKeyboardShortcutsHelp.html
@@ -77,7 +77,7 @@
| W, C |
| Ctrl + Q, Command + Q |
| Ctrl + S, Command + S |
- | Ctrl + Enter, Command + Enter |
+
| Esc |
diff --git a/rainloop/v/0.0.0/app/templates/Views/Common/PopupsLanguages.html b/rainloop/v/0.0.0/app/templates/Views/Common/PopupsLanguages.html
index ba6fa3d30..e825ba690 100644
--- a/rainloop/v/0.0.0/app/templates/Views/Common/PopupsLanguages.html
+++ b/rainloop/v/0.0.0/app/templates/Views/Common/PopupsLanguages.html
@@ -8,8 +8,8 @@
-