diff --git a/build/owncloud/rainloop-app/INSTALL b/build/owncloud/rainloop-app/INSTALL
index 8a8662368..314f5babe 100755
--- a/build/owncloud/rainloop-app/INSTALL
+++ b/build/owncloud/rainloop-app/INSTALL
@@ -1,26 +1,23 @@
-************************************************************************
-*
-* ownCloud - RainLoop Webmail mail plugin
-*
-* @author RainLoop Team
-* @copyright 2014 RainLoop Team
-*
-* https://github.com/RainLoop/rainloop-webmail/tree/master/build/owncloud
-*
-************************************************************************
-
-REQUIREMENTS:
-- Installed and configured RainLoop Webmail (standalone)
-- ownCloud version 6 or higher
-- Both apps (RainLoop & ownCloud) running on the same domain
-
-
-INSTALL:
-- Unpack the RainLoop Webmail application package in the apps directory of your OwnCloud instance
-
-
-CONFIGURATION:
-- ownCloud:
- 1) In the Apps > Enable 'RainLoop' plugin
- 2) In the Settings > Admin > Enter "RainLoop Webmail URL" and "Absolute (full) path to RainLoop Webmail installation"
- 3) In the Settings > Personal > Type your mail server email (login) and password
+************************************************************************
+*
+* ownCloud - RainLoop Webmail package
+*
+* @author RainLoop Team
+* @copyright 2015 RainLoop Team
+*
+* https://github.com/RainLoop/rainloop-webmail/tree/master/build/owncloud
+*
+************************************************************************
+
+REQUIREMENTS:
+- ownCloud version 6 or higher
+
+
+INSTALL:
+- Unpack the RainLoop Webmail application package in the apps directory of your OwnCloud instance
+
+
+CONFIGURATION:
+- ownCloud:
+ 1) In the Apps > Enable 'RainLoop' plugin
+ 2) In the Settings > Personal > Type your mail server email (login) and password
diff --git a/build/owncloud/rainloop-app/admin.php b/build/owncloud/rainloop-app/admin.php
index ba8913669..3fc6a67bd 100644
--- a/build/owncloud/rainloop-app/admin.php
+++ b/build/owncloud/rainloop-app/admin.php
@@ -1,20 +1,32 @@
-assign('rainloop-url', OCP\Config::getAppValue('rainloop', 'rainloop-url', ''));
-$oTemplate->assign('rainloop-path', OCP\Config::getAppValue('rainloop', 'rainloop-path', ''));
-$oTemplate->assign('rainloop-autologin', OCP\Config::getAppValue('rainloop', 'rainloop-autologin', false));
-return $oTemplate->fetchPage();
+assign('rainloop-admin-panel-link',
+ OC_RainLoop_Helper::getAppUrl().'?admin');
+}
+else
+{
+ $oTemplate = new OCP\Template('rainloop', 'admin');
+ $oTemplate->assign('rainloop-admin-panel-link', '');
+ $oTemplate->assign('rainloop-url', OCP\Config::getAppValue('rainloop', 'rainloop-url', ''));
+ $oTemplate->assign('rainloop-path', OCP\Config::getAppValue('rainloop', 'rainloop-path', ''));
+}
+
+$oTemplate->assign('rainloop-autologin', OCP\Config::getAppValue('rainloop', 'rainloop-autologin', false));
+return $oTemplate->fetchPage();
diff --git a/build/owncloud/rainloop-app/ajax/admin.php b/build/owncloud/rainloop-app/ajax/admin.php
index fd35d61f4..8c935d93e 100644
--- a/build/owncloud/rainloop-app/ajax/admin.php
+++ b/build/owncloud/rainloop-app/ajax/admin.php
@@ -4,7 +4,7 @@
* ownCloud - RainLoop mail plugin
*
* @author RainLoop Team
- * @copyright 2014 RainLoop Team
+ * @copyright 2015 RainLoop Team
*
* https://github.com/RainLoop/rainloop-webmail/tree/master/build/owncloud
*/
@@ -17,22 +17,32 @@ $sUrl = '';
$sPath = '';
$bAutologin = false;
-if (isset($_POST['appname'], $_POST['rainloop-url'], $_POST['rainloop-path']) && 'rainloop' === $_POST['appname'])
+$bInstalledLocaly = file_exists(__DIR__.'/../app/index.php');
+
+if (isset($_POST['appname']) && 'rainloop' === $_POST['appname'] &&
+ ($bInstalledLocaly ? true : isset($_POST['rainloop-url'], $_POST['rainloop-path'])))
{
- OCP\Config::setAppValue('rainloop', 'rainloop-url', $_POST['rainloop-url']);
- OCP\Config::setAppValue('rainloop', 'rainloop-path', $_POST['rainloop-path']);
OCP\Config::setAppValue('rainloop', 'rainloop-autologin', isset($_POST['rainloop-autologin']) ?
'1' === $_POST['rainloop-autologin'] : false);
- $sUrl = OCP\Config::getAppValue('rainloop', 'rainloop-url', '');
- $sPath = OCP\Config::getAppValue('rainloop', 'rainloop-path', '');
+ if (!$bInstalledLocaly)
+ {
+ OCP\Config::setAppValue('rainloop', 'rainloop-url', $_POST['rainloop-url']);
+ OCP\Config::setAppValue('rainloop', 'rainloop-path', $_POST['rainloop-path']);
+
+ $sUrl = OCP\Config::getAppValue('rainloop', 'rainloop-url', '');
+ $sPath = OCP\Config::getAppValue('rainloop', 'rainloop-path', '');
+ }
+
$bAutologin = OCP\Config::getAppValue('rainloop', 'rainloop-autologin', false);
}
else
{
+ sleep(1);
OC_JSON::error(array('Message' => 'Invalid Argument(s)', 'Url' => $sUrl, 'Path' => $sPath));
return false;
}
+sleep(1);
OCP\JSON::success(array('Message' => 'Saved successfully', 'Url' => $sUrl, 'Path' => $sPath));
return true;
diff --git a/build/owncloud/rainloop-app/ajax/personal.php b/build/owncloud/rainloop-app/ajax/personal.php
index 3fcf22fb7..4ea738417 100644
--- a/build/owncloud/rainloop-app/ajax/personal.php
+++ b/build/owncloud/rainloop-app/ajax/personal.php
@@ -4,7 +4,7 @@
* ownCloud - RainLoop mail plugin
*
* @author RainLoop Team
- * @copyright 2014 RainLoop Team
+ * @copyright 2015 RainLoop Team
*
* https://github.com/RainLoop/rainloop-webmail/tree/master/build/owncloud
*/
@@ -37,9 +37,11 @@ if (isset($_POST['appname'], $_POST['rainloop-password'], $_POST['rainloop-email
}
else
{
+ sleep(1);
OC_JSON::error(array('Message' => 'Invalid argument(s)', 'Email' => $sEmail));
return false;
}
+sleep(1);
OCP\JSON::success(array('Message' => 'Saved successfully', 'Email' => $sEmail));
return true;
diff --git a/build/owncloud/rainloop-app/app.php b/build/owncloud/rainloop-app/app.php
new file mode 100644
index 000000000..94fdee86e
--- /dev/null
+++ b/build/owncloud/rainloop-app/app.php
@@ -0,0 +1,10 @@
+
rainloop
RainLoop
- RainLoop Webmail
+ Simple, modern & fast web-based email client.
+
+Modest system requirements, decent performance, simple installation and upgrade, no database required -
+all these make RainLoop Webmail a perfect choice for your email solution.
0.0
CC BY-NC-SA 3.0
RainLoop Team
diff --git a/build/owncloud/rainloop-app/appinfo/routes.php b/build/owncloud/rainloop-app/appinfo/routes.php
new file mode 100644
index 000000000..7716e0a74
--- /dev/null
+++ b/build/owncloud/rainloop-app/appinfo/routes.php
@@ -0,0 +1,13 @@
+create('rainloop_index', '/')
+ ->actionInclude('rainloop/index.php');
+
+$this->create('rainloop_app', '/app/')
+ ->actionInclude('rainloop/app.php');
+
+$this->create('rainloop_ajax_personal', 'ajax/personal.php')
+ ->actionInclude('rainloop/ajax/personal.php');
+
+$this->create('rainloop_ajax_admin', 'ajax/admin.php')
+ ->actionInclude('rainloop/ajax/admin.php');
diff --git a/build/owncloud/rainloop-app/index.php b/build/owncloud/rainloop-app/index.php
index a958d631a..c38d27def 100644
--- a/build/owncloud/rainloop-app/index.php
+++ b/build/owncloud/rainloop-app/index.php
@@ -4,7 +4,7 @@
* ownCloud - RainLoop mail plugin
*
* @author RainLoop Team
- * @copyright 2014 RainLoop Team
+ * @copyright 2015 RainLoop Team
*
* https://github.com/RainLoop/rainloop-webmail/tree/master/build/owncloud
*/
@@ -13,8 +13,23 @@ OCP\User::checkLoggedIn();
OCP\App::checkAppEnabled('rainloop');
OCP\App::setActiveNavigationEntry('rainloop_index');
-$sUrl = trim(OCP\Config::getAppValue('rainloop', 'rainloop-url', ''));
-$sPath = trim(OCP\Config::getAppValue('rainloop', 'rainloop-path', ''));
+include_once OC_App::getAppPath('rainloop').'/lib/RainLoopHelper.php';
+
+$sUrl = '';
+$sPath = '';
+
+$bInstalledLocaly = file_exists(__DIR__.'/app/index.php');
+if ($bInstalledLocaly)
+{
+ $sUrl = OC_RainLoop_Helper::getAppUrl();
+ $sPath = __DIR__.'/app/';
+}
+else
+{
+ $sUrl = trim(OCP\Config::getAppValue('rainloop', 'rainloop-url', ''));
+ $sPath = trim(OCP\Config::getAppValue('rainloop', 'rainloop-path', ''));
+}
+
$bAutologin = OCP\Config::getAppValue('rainloop', 'rainloop-autologin', false);
if ('' === $sUrl || '' === $sPath)
@@ -23,10 +38,6 @@ if ('' === $sUrl || '' === $sPath)
}
else
{
- include_once OC_App::getAppPath('rainloop').'/lib/RainLoopHelper.php';
-
- OC_Config::setValue('xframe_restriction', false);
-
$sUser = OCP\User::getUser();
if ($bAutologin)
diff --git a/build/owncloud/rainloop-app/js/admin.js b/build/owncloud/rainloop-app/js/admin.js
index c47ed8b2c..a7a2bc4be 100755
--- a/build/owncloud/rainloop-app/js/admin.js
+++ b/build/owncloud/rainloop-app/js/admin.js
@@ -1,13 +1,13 @@
-
-/**
- * ownCloud - RainLoop mail plugin
- *
- * @author RainLoop Team
- * @copyright 2014 RainLoop Team
- *
- * https://github.com/RainLoop/rainloop-webmail/tree/master/build/owncloud
- */
-
-$(function() {
- RainLoopFormHelper('#mail-rainloop-admin-form', 'admin.php');
-});
+
+/**
+ * ownCloud - RainLoop mail plugin
+ *
+ * @author RainLoop Team
+ * @copyright 2015 RainLoop Team
+ *
+ * https://github.com/RainLoop/rainloop-webmail/tree/master/build/owncloud
+ */
+
+$(function() {
+ RainLoopFormHelper('#mail-rainloop-admin-form', 'admin.php');
+});
diff --git a/build/owncloud/rainloop-app/js/personal.js b/build/owncloud/rainloop-app/js/personal.js
index 008bf41b4..ab65be751 100755
--- a/build/owncloud/rainloop-app/js/personal.js
+++ b/build/owncloud/rainloop-app/js/personal.js
@@ -1,13 +1,13 @@
-
-/**
- * ownCloud - RainLoop mail plugin
- *
- * @author RainLoop Team
- * @copyright 2014 RainLoop Team
- *
- * https://github.com/RainLoop/rainloop-webmail/tree/master/build/owncloud
- */
-
-$(function() {
- RainLoopFormHelper('#mail-rainloop-personal-form', 'personal.php');
-});
+
+/**
+ * ownCloud - RainLoop mail plugin
+ *
+ * @author RainLoop Team
+ * @copyright 2015 RainLoop Team
+ *
+ * https://github.com/RainLoop/rainloop-webmail/tree/master/build/owncloud
+ */
+
+$(function() {
+ RainLoopFormHelper('#mail-rainloop-personal-form', 'personal.php');
+});
diff --git a/build/owncloud/rainloop-app/lib/RainLoopHelper.php b/build/owncloud/rainloop-app/lib/RainLoopHelper.php
index cc67e8c3d..eb3d1cdf5 100644
--- a/build/owncloud/rainloop-app/lib/RainLoopHelper.php
+++ b/build/owncloud/rainloop-app/lib/RainLoopHelper.php
@@ -2,6 +2,18 @@
class OC_RainLoop_Helper
{
+ /**
+ * @return string
+ */
+ public static function getAppUrl()
+ {
+ $sRequestUri = empty($_SERVER['REQUEST_URI']) ? '': trim($_SERVER['REQUEST_URI']);
+ $sRequestUri = preg_replace('/index.php\/.+$/', 'index.php/', $sRequestUri);
+ $sRequestUri = $sRequestUri.'apps/rainloop/app/';
+
+ return '/'.ltrim($sRequestUri, '/\\');
+ }
+
/**
* @param string $sPath
* @param string $sEmail
@@ -16,6 +28,8 @@ class OC_RainLoop_Helper
$sPath = rtrim(trim($sPath), '\\/').'/index.php';
if (file_exists($sPath))
{
+ self::regRainLoopDataFunction();
+
$_ENV['RAINLOOP_INCLUDE_AS_API'] = true;
include $sPath;
@@ -124,4 +138,102 @@ class OC_RainLoop_Helper
return false;
}
+
+ public static function regRainLoopDataFunction()
+ {
+ if (!@function_exists('__get_custom_data_full_path'))
+ {
+ $_ENV['RAINLOOP_OWNCLOUD'] = true;
+
+ function __get_custom_data_full_path()
+ {
+ $sData = __DIR__.'/../../data/';
+ if (class_exists('OC_Config'))
+ {
+ $sData = rtrim(trim(OC_Config::getValue('datadirectory', '')), '\\/').'/';
+ }
+
+ return @is_dir($sData) ? $sData.'rainloop-storage' : '';
+ }
+ }
+ }
+
+ public static function mimeContentType($filename) {
+
+ $mime_types = array(
+
+ 'woff' => 'application/font-woff',
+
+ 'txt' => 'text/plain',
+ 'htm' => 'text/html',
+ 'html' => 'text/html',
+ 'php' => 'text/html',
+ 'css' => 'text/css',
+ 'js' => 'application/javascript',
+ 'json' => 'application/json',
+ 'xml' => 'application/xml',
+ 'swf' => 'application/x-shockwave-flash',
+ 'flv' => 'video/x-flv',
+
+ // images
+ 'png' => 'image/png',
+ 'jpe' => 'image/jpeg',
+ 'jpeg' => 'image/jpeg',
+ 'jpg' => 'image/jpeg',
+ 'gif' => 'image/gif',
+ 'bmp' => 'image/bmp',
+ 'ico' => 'image/vnd.microsoft.icon',
+ 'tiff' => 'image/tiff',
+ 'tif' => 'image/tiff',
+ 'svg' => 'image/svg+xml',
+ 'svgz' => 'image/svg+xml',
+
+ // archives
+ 'zip' => 'application/zip',
+ 'rar' => 'application/x-rar-compressed',
+ 'exe' => 'application/x-msdownload',
+ 'msi' => 'application/x-msdownload',
+ 'cab' => 'application/vnd.ms-cab-compressed',
+
+ // audio/video
+ 'mp3' => 'audio/mpeg',
+ 'qt' => 'video/quicktime',
+ 'mov' => 'video/quicktime',
+
+ // adobe
+ 'pdf' => 'application/pdf',
+ 'psd' => 'image/vnd.adobe.photoshop',
+ 'ai' => 'application/postscript',
+ 'eps' => 'application/postscript',
+ 'ps' => 'application/postscript',
+
+ // ms office
+ 'doc' => 'application/msword',
+ 'rtf' => 'application/rtf',
+ 'xls' => 'application/vnd.ms-excel',
+ 'ppt' => 'application/vnd.ms-powerpoint',
+
+ // open office
+ 'odt' => 'application/vnd.oasis.opendocument.text',
+ 'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
+ );
+
+ if (0 < strpos($filename, '.'))
+ {
+ $ext = strtolower(array_pop(explode('.',$filename)));
+ if (array_key_exists($ext, $mime_types))
+ {
+ return $mime_types[$ext];
+ }
+ else if (function_exists('finfo_open'))
+ {
+ $finfo = finfo_open(FILEINFO_MIME);
+ $mimetype = finfo_file($finfo, $filename);
+ finfo_close($finfo);
+ return $mimetype;
+ }
+ }
+
+ return 'application/octet-stream';
+ }
}
diff --git a/build/owncloud/rainloop-app/personal.php b/build/owncloud/rainloop-app/personal.php
index 31ca9c409..0499d520e 100644
--- a/build/owncloud/rainloop-app/personal.php
+++ b/build/owncloud/rainloop-app/personal.php
@@ -4,7 +4,7 @@
* ownCloud - RainLoop mail plugin
*
* @author RainLoop Team
- * @copyright 2014 RainLoop Team
+ * @copyright 2015 RainLoop Team
*
* https://github.com/RainLoop/rainloop-webmail/tree/master/build/owncloud
*/
@@ -14,11 +14,19 @@ OCP\App::checkAppEnabled('rainloop');
OCP\Util::addScript('rainloop', 'personal');
-$sUrl = trim(OCP\Config::getAppValue('rainloop', 'rainloop-url', ''));
-$sPath = trim(OCP\Config::getAppValue('rainloop', 'rainloop-path', ''));
+$sUrl = '';
+$sPath = '';
+
$bAutologin = OCP\Config::getAppValue('rainloop', 'rainloop-autologin', false);
-if ($bAutologin || '' === $sUrl || '' === $sPath)
+$bInstalledLocaly = file_exists(__DIR__.'/app/index.php');
+if (!$bInstalledLocaly)
+{
+ $sUrl = trim(OCP\Config::getAppValue('rainloop', 'rainloop-url', ''));
+ $sPath = trim(OCP\Config::getAppValue('rainloop', 'rainloop-path', ''));
+}
+
+if ($bAutologin || (!$bInstalledLocaly && ('' === $sUrl || '' === $sPath)))
{
$oTemplate = new OCP\Template('rainloop', 'empty');
}
diff --git a/build/owncloud/rainloop-app/templates/admin-local.php b/build/owncloud/rainloop-app/templates/admin-local.php
new file mode 100644
index 000000000..27a90acf2
--- /dev/null
+++ b/build/owncloud/rainloop-app/templates/admin-local.php
@@ -0,0 +1,29 @@
+
\ No newline at end of file
diff --git a/dev/App/Abstract.js b/dev/App/Abstract.js
index 95d5e1485..5eb1ebd46 100644
--- a/dev/App/Abstract.js
+++ b/dev/App/Abstract.js
@@ -50,6 +50,37 @@
}
});
+ Globals.$win.on('resize', function () {
+ Events.pub('window.resize');
+ });
+
+ Events.sub('window.resize', _.throttle(function () {
+
+ var
+ iH = Globals.$win.height(),
+ iW = Globals.$win.height()
+ ;
+
+ if (Globals.$win.__sizes[0] !== iH || Globals.$win.__sizes[1] !== iW)
+ {
+ Globals.$win.__sizes[0] = iH;
+ Globals.$win.__sizes[1] = iW;
+
+ Events.pub('window.resize.real');
+ }
+
+ }, 50));
+
+ // TODO
+// Events.sub({
+// 'window.resize': function () {
+// window.console.log('window.resize');
+// },
+// 'window.resize.real': function () {
+// window.console.log('window.resize.real');
+// }
+// });
+
Globals.$doc.on('keydown', function (oEvent) {
if (oEvent && oEvent.ctrlKey)
{
@@ -315,6 +346,8 @@
ssm.ready();
+
+
require('Stores/Language').populate();
require('Stores/Theme').populate();
require('Stores/Social').populate();
diff --git a/dev/App/User.js b/dev/App/User.js
index b4a2792f2..9361f2af0 100644
--- a/dev/App/User.js
+++ b/dev/App/User.js
@@ -41,6 +41,7 @@
MessageModel = require('Model/Message'),
AccountModel = require('Model/Account'),
IdentityModel = require('Model/Identity'),
+ TemplateModel = require('Model/Template'),
OpenPgpKeyModel = require('Model/OpenPgpKey'),
AbstractApp = require('App/Abstract')
@@ -611,12 +612,10 @@
{
Utils.delegateRunOnDestroy(TemplateStore.templates());
- IdentityStore.templates(_.map(oData.Result['Templates'], function (oIdentityData) {
- return {
- 'id': Utils.pString(oIdentityData['Id']),
- 'name': Utils.pString(oIdentityData['Name'])
- };
- }));
+ TemplateStore.templates(_.compact(_.map(oData.Result['Templates'], function (oTemplateData) {
+ var oTemplate = new TemplateModel();
+ return oTemplate.parse(oTemplateData) ? oTemplate : null;
+ })));
}
});
};
diff --git a/dev/Common/Enums.js b/dev/Common/Enums.js
index 4a5c157ed..77851e32e 100644
--- a/dev/Common/Enums.js
+++ b/dev/Common/Enums.js
@@ -45,6 +45,7 @@
'Sieve': 'SIEVE',
'Filters': 'FILTERS',
'AttachmentThumbnails': 'ATTACHMENT_THUMBNAILS',
+ 'Templates': 'TEMPLATES',
'AdditionalAccounts': 'ADDITIONAL_ACCOUNTS'
};
diff --git a/dev/Common/Events.js b/dev/Common/Events.js
index b8198fb1f..14b71d3a0 100644
--- a/dev/Common/Events.js
+++ b/dev/Common/Events.js
@@ -28,12 +28,24 @@
*/
Events.prototype.sub = function (sName, fFunc, oContext)
{
- if (Utils.isUnd(this.oSubs[sName]))
+ if (Utils.isObject(sName))
{
- this.oSubs[sName] = [];
- }
+ oContext = fFunc || null;
+ fFunc = null;
- this.oSubs[sName].push([fFunc, oContext]);
+ _.each(sName, function (fSubFunc, sSubName) {
+ this.sub(sSubName, fSubFunc, oContext);
+ }, this);
+ }
+ else
+ {
+ if (Utils.isUnd(this.oSubs[sName]))
+ {
+ this.oSubs[sName] = [];
+ }
+
+ this.oSubs[sName].push([fFunc, oContext]);
+ }
return this;
};
diff --git a/dev/Common/Globals.js b/dev/Common/Globals.js
index 752d02797..71ada0360 100644
--- a/dev/Common/Globals.js
+++ b/dev/Common/Globals.js
@@ -20,6 +20,8 @@
Globals.$html = $('html');
Globals.$div = $('');
+ Globals.$win.__sizes = [0, 0];
+
/**
* @type {?}
*/
@@ -255,7 +257,7 @@
});
Globals.keyScopeReal.subscribe(function (sValue) {
-// window.console.log(sValue);
+// window.console.log(sValue); //TODO
key.setScope(sValue);
});
diff --git a/dev/Common/HtmlEditor.js b/dev/Common/HtmlEditor.js
index ead03e929..b039de237 100644
--- a/dev/Common/HtmlEditor.js
+++ b/dev/Common/HtmlEditor.js
@@ -106,8 +106,13 @@
.replace("\u0002", '').replace("\u0002", '')
.replace("\u0003", '').replace("\u0003", '')
.replace("\u0003", '').replace("\u0003", '')
+ .replace("\u0004", '').replace("\u0004", '')
+ .replace("\u0004", '').replace("\u0004", '')
+ .replace("\u0005", '').replace("\u0005", '')
+ .replace("\u0005", '').replace("\u0005", '')
;
- }
+ };
+
/**
* @param {boolean=} bWrapIsHtml = false
* @param {boolean=} bClearSignatureSigns = false
diff --git a/dev/Common/Utils.js b/dev/Common/Utils.js
index 0c75e5d8e..f53db4e5b 100644
--- a/dev/Common/Utils.js
+++ b/dev/Common/Utils.js
@@ -24,6 +24,7 @@
Utils.trim = $.trim;
Utils.inArray = $.inArray;
Utils.isArray = _.isArray;
+ Utils.isObject = _.isObject;
Utils.isFunc = _.isFunction;
Utils.isUnd = _.isUndefined;
Utils.isNull = _.isNull;
diff --git a/dev/Knoin/AbstractModel.js b/dev/Knoin/AbstractModel.js
index cc9a0161b..67ce5cd86 100644
--- a/dev/Knoin/AbstractModel.js
+++ b/dev/Knoin/AbstractModel.js
@@ -41,7 +41,7 @@
AbstractModel.prototype.onDestroy = function ()
{
Utils.disposeObject(this);
-// window.console.log('onDestroy: ' + this.sModelName);
+// window.console.log('onDestroy: ' + this.sModelName); // TODO
};
module.exports = AbstractModel;
diff --git a/dev/Model/Template.js b/dev/Model/Template.js
index e8b53ae1d..765802dc2 100644
--- a/dev/Model/Template.js
+++ b/dev/Model/Template.js
@@ -7,6 +7,8 @@
_ = require('_'),
ko = require('ko'),
+ Utils = require('Common/Utils'),
+
AbstractModel = require('Knoin/AbstractModel')
;
@@ -24,6 +26,7 @@
this.id = sID;
this.name = sName;
this.body = sBody;
+ this.populated = true;
this.deleteAccess = ko.observable(false);
}
@@ -45,6 +48,30 @@
*/
TemplateModel.prototype.body = '';
+ /**
+ * @type {boolean}
+ */
+ TemplateModel.prototype.populated = true;
+
+ /**
+ * @type {boolean}
+ */
+ TemplateModel.prototype.parse = function (oItem)
+ {
+ var bResult = false;
+ if (oItem && 'Object/Template' === oItem['@Object'])
+ {
+ this.id = Utils.pString(oItem['ID']);
+ this.name = Utils.pString(oItem['Name']);
+ this.body = Utils.pString(oItem['Body']);
+ this.populated = !!oItem['Populated'];
+
+ bResult = true;
+ }
+
+ return bResult;
+ };
+
module.exports = TemplateModel;
}());
\ No newline at end of file
diff --git a/dev/Screen/User/Settings.js b/dev/Screen/User/Settings.js
index 201d394c6..473fed7e2 100644
--- a/dev/Screen/User/Settings.js
+++ b/dev/Screen/User/Settings.js
@@ -85,8 +85,11 @@
'SettingsChangePassword', 'SETTINGS_LABELS/LABEL_CHANGE_PASSWORD_NAME', 'change-password');
}
-// kn.addSettingsViewModel(require('Settings/User/Templates'),
-// 'SettingsTemplates', 'SETTINGS_LABELS/LABEL_TEMPLATES_NAME', 'templates');
+ if (Settings.capa(Enums.Capa.Templates))
+ {
+ kn.addSettingsViewModel(require('Settings/User/Templates'),
+ 'SettingsTemplates', 'SETTINGS_LABELS/LABEL_TEMPLATES_NAME', 'templates');
+ }
kn.addSettingsViewModel(require('Settings/User/Folders'),
'SettingsFolders', 'SETTINGS_LABELS/LABEL_FOLDERS_NAME', 'folders');
diff --git a/dev/Settings/Admin/General.js b/dev/Settings/Admin/General.js
index 929b1d388..5e80bfb4b 100644
--- a/dev/Settings/Admin/General.js
+++ b/dev/Settings/Admin/General.js
@@ -34,6 +34,7 @@
this.capaGravatar = CapaAdminStore.gravatar;
this.capaAdditionalAccounts = CapaAdminStore.additionalAccounts;
this.capaAttachmentThumbnails = CapaAdminStore.attachmentThumbnails;
+ this.capaTemplates = CapaAdminStore.templates;
this.allowLanguagesOnSettings = AppAdminStore.allowLanguagesOnSettings;
this.weakPassword = AppAdminStore.weakPassword;
@@ -105,6 +106,12 @@
});
});
+ self.capaTemplates.subscribe(function (bValue) {
+ Remote.saveAdminConfig(null, {
+ 'CapaTemplates': bValue ? '1' : '0'
+ });
+ });
+
self.capaGravatar.subscribe(function (bValue) {
Remote.saveAdminConfig(null, {
'CapaGravatar': bValue ? '1' : '0'
diff --git a/dev/Settings/User/Accounts.js b/dev/Settings/User/Accounts.js
index 43ffb65f6..ac49ffb26 100644
--- a/dev/Settings/User/Accounts.js
+++ b/dev/Settings/User/Accounts.js
@@ -9,7 +9,6 @@
ko = require('ko'),
Enums = require('Common/Enums'),
- Utils = require('Common/Utils'),
Translator = require('Common/Translator'),
Links = require('Common/Links'),
diff --git a/dev/Storage/User/Remote.js b/dev/Storage/User/Remote.js
index a9b6178e5..c53c713f2 100644
--- a/dev/Storage/User/Remote.js
+++ b/dev/Storage/User/Remote.js
@@ -293,7 +293,17 @@
/**
* @param {?Function} fCallback
*/
- RemoteUserStorage.prototype.templateGetById = function (fCallback, sID, sName, sBody)
+ RemoteUserStorage.prototype.templateDelete = function (fCallback, sID)
+ {
+ this.defaultRequest(fCallback, 'TemplateDelete', {
+ 'IdToDelete': sID
+ });
+ };
+
+ /**
+ * @param {?Function} fCallback
+ */
+ RemoteUserStorage.prototype.templateSetup = function (fCallback, sID, sName, sBody)
{
this.defaultRequest(fCallback, 'TemplateSetup', {
'ID': sID,
diff --git a/dev/Stores/Admin/Capa.js b/dev/Stores/Admin/Capa.js
index e473d145b..55b7886cc 100644
--- a/dev/Stores/Admin/Capa.js
+++ b/dev/Stores/Admin/Capa.js
@@ -25,6 +25,7 @@
this.userBackground = ko.observable(false);
this.openPGP = ko.observable(false);
this.twoFactorAuth = ko.observable(false);
+ this.templates = ko.observable(false);
}
CapaAdminStore.prototype.populate = function()
@@ -38,6 +39,7 @@
this.userBackground(Settings.capa(Enums.Capa.UserBackground));
this.openPGP(Settings.capa(Enums.Capa.OpenPGP));
this.twoFactorAuth(Settings.capa(Enums.Capa.TwoFactor));
+ this.templates(Settings.capa(Enums.Capa.Templates));
};
module.exports = new CapaAdminStore();
diff --git a/dev/Stores/User/Template.js b/dev/Stores/User/Template.js
index 8a3f41030..cfaff8986 100644
--- a/dev/Stores/User/Template.js
+++ b/dev/Stores/User/Template.js
@@ -5,9 +5,9 @@
var
_ = require('_'),
- ko = require('ko'),
+ ko = require('ko')
- Remote = require('Storage/User/Remote')
+// Remote = require('Storage/User/Remote')
;
/**
@@ -27,16 +27,16 @@
})));
}, this);
- this.templatesNames.subscribe(function (aList) {
- if (this.templatesNames.skipFirst)
- {
- this.templatesNames.skipFirst = false;
- }
- else if (aList && 1 < aList.length)
- {
- Remote.templatesSortOrder(null, aList);
- }
- }, this);
+// this.templatesNames.subscribe(function (aList) {
+// if (this.templatesNames.skipFirst)
+// {
+// this.templatesNames.skipFirst = false;
+// }
+// else if (aList && 1 < aList.length)
+// {
+// Remote.templatesSortOrder(null, aList);
+// }
+// }, this);
}
module.exports = new TemplateUserStore();
diff --git a/dev/Styles/SettingsTemplates.less b/dev/Styles/SettingsTemplates.less
index 85718eba1..2aa1afb30 100644
--- a/dev/Styles/SettingsTemplates.less
+++ b/dev/Styles/SettingsTemplates.less
@@ -1,5 +1,5 @@
-.b-settings-identities {
+.b-settings-templates {
.process-place {
text-align: center;
diff --git a/dev/Styles/Template.less b/dev/Styles/Template.less
index 6ab167d76..5da4d9f1e 100644
--- a/dev/Styles/Template.less
+++ b/dev/Styles/Template.less
@@ -2,11 +2,15 @@
.b-template-add-content {
&.modal {
- width: 700px;
+ width: 750px;
}
.modal-header {
background-color: #fff;
}
+
+ .e-template-place {
+ height: 300px;
+ }
}
}
diff --git a/dev/View/Popup/Compose.js b/dev/View/Popup/Compose.js
index 2cfce8863..aa824b90d 100644
--- a/dev/View/Popup/Compose.js
+++ b/dev/View/Popup/Compose.js
@@ -80,7 +80,7 @@
this.bFromDraft = false;
this.sReferences = '';
- this.triggerForResize = _.bind(this.triggerForResize, this);
+ this.resizerTrigger = _.bind(this.resizerTrigger, this);
this.allowContacts = !!AppStore.contactsIsAllowed();
@@ -90,8 +90,6 @@
this.capaOpenPGP = PgpStore.capaOpenPGP;
- this.resizer = ko.observable(false).extend({'throttle': 50});
-
this.identitiesDropdownTrigger = ko.observable(false);
this.to = ko.observable('');
@@ -241,11 +239,13 @@
}
}, this);
- this.editorResizeThrottle = _.throttle(_.bind(this.editorResize, this), 100);
+ this.resizer = ko.observable(false).extend({'throttle': 50});
- this.resizer.subscribe(function () {
- this.editorResizeThrottle();
- }, this);
+ this.resizer.subscribe(_.bind(function () {
+ if (this.oEditor){
+ this.oEditor.resize();
+ }
+ }, this));
this.canBeSendedOrSaved = ko.computed(function () {
return !this.sending() && !this.saving();
@@ -429,9 +429,9 @@
}
}, this);
- this.showCc.subscribe(this.triggerForResize);
- this.showBcc.subscribe(this.triggerForResize);
- this.showReplyTo.subscribe(this.triggerForResize);
+ this.showCc.subscribe(this.resizerTrigger);
+ this.showBcc.subscribe(this.resizerTrigger);
+ this.showReplyTo.subscribe(this.resizerTrigger);
this.dropboxEnabled = SocialStore.dropbox.enabled;
this.dropboxApiKey = SocialStore.dropbox.apiKey;
@@ -1230,7 +1230,7 @@
this.currentIdentity(oIdentity);
}
- this.triggerForResize();
+ this.resizerTrigger();
};
ComposePopupView.prototype.onFocus = function ()
@@ -1244,15 +1244,7 @@
this.oEditor.focus();
}
- this.triggerForResize();
- };
-
- ComposePopupView.prototype.editorResize = function ()
- {
- if (this.oEditor)
- {
- this.oEditor.resize();
- }
+ this.resizerTrigger();
};
ComposePopupView.prototype.tryToClosePopup = function ()
@@ -1315,7 +1307,7 @@
return false;
});
- Globals.$win.on('resize', self.triggerForResize);
+ Events.sub('window.resize.real', this.resizerTrigger);
if (this.dropboxEnabled())
{
@@ -2034,10 +2026,9 @@
});
};
- ComposePopupView.prototype.triggerForResize = function ()
+ ComposePopupView.prototype.resizerTrigger = function ()
{
this.resizer(!this.resizer());
- this.editorResizeThrottle();
};
module.exports = ComposePopupView;
diff --git a/dev/View/Popup/Template.js b/dev/View/Popup/Template.js
index da43d16a3..5b745d4b0 100644
--- a/dev/View/Popup/Template.js
+++ b/dev/View/Popup/Template.js
@@ -36,6 +36,7 @@
this.name.focus = ko.observable(false);
this.body = ko.observable('');
+ this.body.loading = ko.observable(false);
this.body.error = ko.observable(false);
this.name.subscribe(function () {
@@ -51,6 +52,8 @@
this.addTemplateCommand = Utils.createCommand(this, function () {
+ this.populateBodyFromEditor();
+
this.name.error('' === Utils.trim(this.name()));
this.body.error('' === Utils.trim(this.body()) ||
':HTML:' === Utils.trim(this.body()));
@@ -109,40 +112,52 @@
this.submitRequest(false);
this.submitError('');
+
+ if (this.editor)
+ {
+ this.setBody('');
+ }
+ };
+
+ TemplatePopupView.prototype.setBody = function (sBody)
+ {
+ if (this.editor)
+ {
+ if (':HTML:' === sBody.substr(0, 6))
+ {
+ this.editor.setHtml(sBody.substr(6), false);
+ }
+ else
+ {
+ this.editor.setPlain(sBody, false);
+ }
+ }
+ };
+
+ TemplatePopupView.prototype.populateBodyFromEditor = function ()
+ {
+ if (this.editor)
+ {
+ this.body(
+ (this.editor.isHtml() ? ':HTML:' : '') + this.editor.getData()
+ );
+ }
};
TemplatePopupView.prototype.editorSetBody = function (sBody)
{
- var
- self = this,
- fEditorSetData = function (sBody) {
- if (self.editor)
- {
- if (':HTML:' === sBody.substr(0, 6))
- {
- self.editor.setHtml(sBody.substr(6), false);
- }
- else
- {
- self.editor.setPlain(sBody, false);
- }
- }
- }
- ;
-
if (!this.editor && this.signatureDom())
{
+ var self = this;
this.editor = new HtmlEditor(self.signatureDom(), function () {
- self.body(
- (self.editor.isHtml() ? ':HTML:' : '') + self.editor.getData()
- );
+ self.populateBodyFromEditor();
}, function () {
- fEditorSetData(sBody);
+ self.setBody(sBody);
});
}
- else if (this.editor)
+ else
{
- fEditorSetData(sBody);
+ this.setBody(sBody);
}
};
@@ -156,16 +171,44 @@
{
this.id(oTemplate.id);
this.name(oTemplate.name);
+ this.body(oTemplate.body);
- this.body.loading(true);
+ if (oTemplate.populated)
+ {
+ self.editorSetBody(this.body());
+ }
+ else
+ {
+ this.body.loading(true);
+ self.body.error(false);
- Remote.templateGetById(function () {
+ Remote.templateGetById(function (sResult, oData) {
- self.body.loading(false);
+ self.body.loading(false);
- self.editorSetBody('');
+ if (Enums.StorageResultType.Success === sResult && oData && oData.Result &&
+ 'Object/Template' === oData.Result['@Object'] && Utils.isNormal(oData.Result['Body']))
+ {
+ oTemplate.body = oData.Result['Body'];
+ oTemplate.populated = true;
- }, this.id());
+ self.body(oTemplate.body);
+ self.body.error(false);
+ }
+ else
+ {
+ self.body('');
+ self.body.error(true);
+ }
+
+ self.editorSetBody(self.body());
+
+ }, this.id());
+ }
+ }
+ else
+ {
+ self.editorSetBody('');
}
};
diff --git a/dev/View/User/MailBox/MessageView.js b/dev/View/User/MailBox/MessageView.js
index 8f74fbcb2..980f7ada8 100644
--- a/dev/View/User/MailBox/MessageView.js
+++ b/dev/View/User/MailBox/MessageView.js
@@ -423,11 +423,11 @@
this.showFullInfo.subscribe(fCheckHeaderHeight);
this.message.subscribe(fCheckHeaderHeight);
- Globals.$win.on('resize', function () {
+ Events.sub('window.resize', _.throttle(function () {
_.delay(fCheckHeaderHeight, 1);
_.delay(fCheckHeaderHeight, 200);
_.delay(fCheckHeaderHeight, 500);
- });
+ }, 50));
this.showFullInfo.subscribe(function () {
Utils.windowResize();
diff --git a/gulpfile.js b/gulpfile.js
index 41ca2c310..dd0ada027 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -7,6 +7,7 @@ var
devVersion: '0.0.0',
releasesPath: 'build/dist/releases',
+ rainloopBuilded: false,
destPath: '',
cleanPath: '',
zipSrcPath: '',
@@ -459,6 +460,8 @@ gulp.task('rainloop:setup', ['rainloop:copy'], function() {
cfg.zipSrcPath = dist;
cfg.zipFile = 'rainloop-' + versionFull + '.zip';
cfg.md5File = cfg.zipFile;
+
+ cfg.rainloopBuilded = true;
});
gulp.task('rainloop:zip', ['rainloop:copy', 'rainloop:setup'], function() {
@@ -490,7 +493,28 @@ gulp.task('rainloop:owncloud:copy', function() {
.pipe(gulp.dest(dist + 'rainloop'));
});
-gulp.task('rainloop:owncloud:setup', ['rainloop:owncloud:copy'], function() {
+gulp.task('rainloop:owncloud:copy-rainloop', ['rainloop:start', 'rainloop:owncloud:copy'], function() {
+
+ var
+ versionFull = pkg.ownCloudPackageVersion,
+ dist = cfg.releasesPath + '/owncloud/' + versionFull + '/src/rainloop/'
+ ;
+
+ if (cfg.rainloopBuilded && cfg.destPath)
+ {
+ return gulp.src(cfg.destPath + '/src/**/*', {base: cfg.destPath + '/src/'})
+ .pipe(gulp.dest(dist + 'app/'));
+ }
+
+ return true;
+});
+
+gulp.task('rainloop:owncloud:copy-rainloop:clean', ['rainloop:owncloud:copy-rainloop'], function() {
+ return (cfg.cleanPath) ? cleanDir(cfg.cleanPath) : false;
+});
+
+gulp.task('rainloop:owncloud:setup', ['rainloop:owncloud:copy',
+ 'rainloop:owncloud:copy-rainloop'], function() {
var
versionFull = pkg.ownCloudPackageVersion,
@@ -529,8 +553,12 @@ gulp.task('rainloop:owncloud:clean', ['rainloop:owncloud:copy', 'rainloop:ownclo
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']);
-gulp.task('owncloud', ['rainloop:owncloud:copy', 'rainloop:owncloud:setup', 'rainloop:owncloud:zip', 'rainloop:owncloud:md5', 'rainloop:owncloud:clean']);
+gulp.task('rainloop:start', ['js:lint', 'rainloop:copy', 'rainloop:setup']);
+gulp.task('rainloop', ['rainloop:start', 'rainloop:zip', 'rainloop:md5', 'rainloop:clean']);
+
+gulp.task('owncloud', ['rainloop:owncloud:copy',
+ 'rainloop:owncloud:copy-rainloop',
+ 'rainloop:owncloud:setup', 'rainloop:owncloud:zip', 'rainloop:owncloud:md5', 'rainloop:owncloud:clean']);
//WATCH
gulp.task('watch', ['fast'], function() {
diff --git a/package.json b/package.json
index e65fe165d..90e8cb481 100644
--- a/package.json
+++ b/package.json
@@ -1,8 +1,8 @@
{
"name": "RainLoop",
"title": "RainLoop Webmail",
- "version": "1.8.0",
- "release": "251",
+ "version": "1.8.1",
+ "release": "255",
"description": "Simple, modern & fast web-based email client",
"homepage": "http://rainloop.net",
"main": "gulpfile.js",
@@ -36,7 +36,7 @@
"plugins"
],
"readmeFilename": "README.md",
- "ownCloudPackageVersion": "2.3",
+ "ownCloudPackageVersion": "3.0",
"engines": {
"node": ">= 0.10.0"
},
diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Base/Http.php b/rainloop/v/0.0.0/app/libraries/MailSo/Base/Http.php
index 40d74653d..fb6b94e47 100644
--- a/rainloop/v/0.0.0/app/libraries/MailSo/Base/Http.php
+++ b/rainloop/v/0.0.0/app/libraries/MailSo/Base/Http.php
@@ -263,7 +263,6 @@ class Http
*/
public function GetHeader($sHeader)
{
- $sResultHeader = '';
$sServerKey = 'HTTP_'.\strtoupper(\str_replace('-', '_', $sHeader));
$sResultHeader = $this->GetServer($sServerKey, '');
diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Base/StreamWrappers/SubStreams.php b/rainloop/v/0.0.0/app/libraries/MailSo/Base/StreamWrappers/SubStreams.php
index 4edf61254..cd967af6c 100644
--- a/rainloop/v/0.0.0/app/libraries/MailSo/Base/StreamWrappers/SubStreams.php
+++ b/rainloop/v/0.0.0/app/libraries/MailSo/Base/StreamWrappers/SubStreams.php
@@ -65,7 +65,7 @@ class SubStreams
\stream_wrapper_register(self::STREAM_NAME, '\MailSo\Base\StreamWrappers\SubStreams');
}
- $sHashName = \md5(\microtime(true).\rand(1000, 9999));
+ $sHashName = \MailSo\Base\Utils::Md5Rand();
self::$aStreams[$sHashName] = $aSubStreams;
@@ -84,7 +84,7 @@ class SubStreams
{
return $this->aSubStreams[$this->iIndex];
}
-
+
return $nNull;
}
diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Base/Utils.php b/rainloop/v/0.0.0/app/libraries/MailSo/Base/Utils.php
index 4d258380b..7e13d15bf 100644
--- a/rainloop/v/0.0.0/app/libraries/MailSo/Base/Utils.php
+++ b/rainloop/v/0.0.0/app/libraries/MailSo/Base/Utils.php
@@ -2147,6 +2147,28 @@ class Utils
return \is_string($mResult) && 0 < \strlen($mResult) ? $mResult : '';
}
+ /**
+ * @param string $sAdditionalSalt = ''
+ *
+ * @return string
+ */
+ public static function Md5Rand($sAdditionalSalt = '')
+ {
+ return \md5(\microtime(true).\rand(10000, 99999).
+ \md5($sAdditionalSalt).\rand(10000, 99999).\microtime(true));
+ }
+
+ /**
+ * @param string $sAdditionalSalt = ''
+ *
+ * @return string
+ */
+ public static function Sha1Rand($sAdditionalSalt = '')
+ {
+ return \sha1(\microtime(true).\rand(10000, 99999).
+ \sha1($sAdditionalSalt).\rand(10000, 99999).\microtime(true));
+ }
+
/**
* @param string $sData
* @param string $sKey
diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Log/Logger.php b/rainloop/v/0.0.0/app/libraries/MailSo/Log/Logger.php
index 47cd599d1..3d513f170 100644
--- a/rainloop/v/0.0.0/app/libraries/MailSo/Log/Logger.php
+++ b/rainloop/v/0.0.0/app/libraries/MailSo/Log/Logger.php
@@ -121,7 +121,7 @@ class Logger extends \MailSo\Base\Collection
static $sCache = null;
if (null === $sCache)
{
- $sCache = \substr(\md5(\microtime(true).\rand(10000, 99999)), -8);
+ $sCache = \substr(\MailSo\Base\Utils::Md5Rand(), -8);
}
return $sCache;
diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php b/rainloop/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php
index 24a25d95e..99c49d9fe 100644
--- a/rainloop/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php
+++ b/rainloop/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php
@@ -990,7 +990,7 @@ class MailClient
{
do
{
- $sKey = \md5(\rand(10000, 90000).\microtime(true));
+ $sKey = \MailSo\Base\Utils::Md5Rand();
}
while (isset($aCache[$sKey]));
@@ -1006,7 +1006,7 @@ class MailClient
{
do
{
- $sKey = \md5(\rand(10000, 90000).\microtime(true));
+ $sKey = \MailSo\Base\Utils::Md5Rand();
}
while (isset($aCache[$sKey]));
diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Mime/Message.php b/rainloop/v/0.0.0/app/libraries/MailSo/Mime/Message.php
index 0b14d5625..8d0c99b12 100644
--- a/rainloop/v/0.0.0/app/libraries/MailSo/Mime/Message.php
+++ b/rainloop/v/0.0.0/app/libraries/MailSo/Mime/Message.php
@@ -535,8 +535,9 @@ class Message
$sHostName = 'localhost';
}
- return '<'.\md5(\rand(100000, 999999).\time().$sHostName.
- (\MailSo\Base\Utils::FunctionExistsAndEnabled('getmypid') ? @\getmypid() : '')).'@'.$sHostName.'>';
+ return '<'.
+ \MailSo\Base\Utils::Md5Rand($sHostName.
+ (\MailSo\Base\Utils::FunctionExistsAndEnabled('getmypid') ? @\getmypid() : '')).'@'.$sHostName.'>';
}
/**
diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php
index 7186607b4..d6dbab2b4 100644
--- a/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php
+++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php
@@ -1511,7 +1511,7 @@ class Actions
$aResult['UseLocalProxyForExternalImages'] = (bool) $oConfig->Get('labs', 'use_local_proxy_for_external_images', false);
// user
- $aResult['ShowImages'] = (bool) $oConfig->Get('webmail', 'show_images', false);
+ $aResult['ShowImages'] = (bool) $oConfig->Get('defaults', 'show_images', false);
$aResult['MPP'] = (int) $oConfig->Get('webmail', 'messages_per_page', 25);
$aResult['SoundNotification'] = false;
$aResult['DesktopNotifications'] = false;
@@ -1982,7 +1982,7 @@ class Actions
*/
private function generateSignMeToken($sEmail)
{
- return \md5(\microtime(true).APP_SALT.\rand(10000, 99999).$sEmail);
+ return \MailSo\Base\Utils::Md5Rand(APP_SALT.$sEmail);
}
/**
@@ -2122,6 +2122,85 @@ class Actions
return $aAccounts;
}
+ /**
+ * @param \RainLoop\Model\Account $oAccount
+ *
+ * @return array
+ */
+ public function GetTemplates($oAccount)
+ {
+ $aTemplates = array();
+ if ($oAccount)
+ {
+ $aData = array();
+
+ $sData = $this->StorageProvider(true)->Get($oAccount,
+ \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG,
+ 'templates'
+ );
+
+ if ('' !== $sData && '[' === \substr($sData, 0, 1))
+ {
+ $aData = @\json_decode($sData, true);
+ }
+
+ if (\is_array($aData) && 0 < \count($aData))
+ {
+ foreach ($aData as $aItem)
+ {
+ $oItem = \RainLoop\Model\Template::NewInstance();
+ $oItem->FromJSON($aItem);
+
+ if ($oItem && $oItem->Validate())
+ {
+ \array_push($aTemplates, $oItem);
+ }
+ }
+ }
+
+ if (1 < \count($aTemplates))
+ {
+ $sOrder = $this->StorageProvider()->Get($oAccount,
+ \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG,
+ 'templates_order'
+ );
+
+ $aOrder = empty($sOrder) ? array() : @\json_decode($sOrder, true);
+ if (\is_array($aOrder) && 1 < \count($aOrder))
+ {
+ \usort($aTemplates, function ($a, $b) use ($aOrder) {
+ return \array_search($a->Id(), $aOrder) < \array_search($b->Id(), $aOrder) ? -1 : 1;
+ });
+ }
+ }
+ }
+
+ return $aTemplates;
+ }
+
+ /**
+ * @param \RainLoop\Model\Account $oAccount
+ * @param string $sID
+ *
+ * @return \RainLoop\Model\Identity
+ */
+ public function GetTemplateByID($oAccount, $sID)
+ {
+ $aTemplates = $this->GetTemplates($oAccount);
+ if (\is_array($aTemplates))
+ {
+ foreach ($aTemplates as $oIdentity)
+ {
+ if ($oIdentity && $sID === $oIdentity->Id())
+ {
+ return $oIdentity;
+ }
+ }
+ }
+
+ return isset($aTemplates[0]) ? $aTemplates[0] : null;
+ }
+
/**
* @param \RainLoop\Model\Account $oAccount
*
@@ -2279,6 +2358,27 @@ class Actions
);
}
+ /**
+ * @param \RainLoop\Model\Account $oAccount
+ * @param array $aTemplates = array()
+ *
+ * @return array
+ */
+ public function SetTemplates($oAccount, $aTemplates = array())
+ {
+ $aResult = array();
+ foreach ($aTemplates as $oItem)
+ {
+ $aResult[] = $oItem->ToSimpleJSON(false);
+ }
+
+ return $this->StorageProvider(true)->Put($oAccount,
+ \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG,
+ 'templates',
+ @\json_encode($aResult)
+ );
+ }
+
/**
* @return array
*
@@ -2497,6 +2597,117 @@ class Actions
return $this->DefaultResponse(__FUNCTION__, $this->SetIdentities($oAccount, $aNew));
}
+ /**
+ * @return array
+ *
+ * @throws \MailSo\Base\Exceptions\Exception
+ */
+ public function DoTemplateSetup()
+ {
+ $oAccount = $this->getAccountFromToken();
+
+ if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::TEMPLATES, $oAccount))
+ {
+ return $this->FalseResponse(__FUNCTION__);
+ }
+
+ $oTemplate = \RainLoop\Model\Template::NewInstance();
+ if (!$oTemplate->FromJSON($this->GetActionParams(), true))
+ {
+ throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::InvalidInputArgument);
+ }
+
+ if ('' === $oTemplate->Id())
+ {
+ $oTemplate->GenerateID();
+ }
+
+ $aTemplatesForSave = array();
+ $aTemplates = $this->GetTemplates($oAccount);
+
+
+ foreach ($aTemplates as $oItem)
+ {
+ if ($oItem && $oItem->Id() !== $oTemplate->Id())
+ {
+ $aTemplatesForSave[] = $oItem;
+ }
+ }
+
+ $aTemplatesForSave[] = $oTemplate;
+
+ return $this->DefaultResponse(__FUNCTION__, $this->SetTemplates($oAccount, $aTemplatesForSave));
+ }
+
+ /**
+ * @return array
+ *
+ * @throws \MailSo\Base\Exceptions\Exception
+ */
+ public function DoTemplateDelete()
+ {
+ $oAccount = $this->getAccountFromToken();
+
+ if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::TEMPLATES, $oAccount))
+ {
+ return $this->FalseResponse(__FUNCTION__);
+ }
+
+ $sId = \trim($this->GetActionParam('IdToDelete', ''));
+ if (empty($sId))
+ {
+ throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::UnknownError);
+ }
+
+ $aNew = array();
+ $aTemplates = $this->GetTemplates($oAccount);
+ foreach ($aTemplates as $oItem)
+ {
+ if ($oItem && $sId !== $oItem->Id())
+ {
+ $aNew[] = $oItem;
+ }
+ }
+
+ return $this->DefaultResponse(__FUNCTION__, $this->SetTemplates($oAccount, $aNew));
+ }
+
+ /**
+ * @return array
+ *
+ * @throws \MailSo\Base\Exceptions\Exception
+ */
+ public function DoTemplateGetByID()
+ {
+ $oAccount = $this->getAccountFromToken();
+
+ if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::TEMPLATES, $oAccount))
+ {
+ return $this->FalseResponse(__FUNCTION__);
+ }
+
+ $sId = \trim($this->GetActionParam('ID', ''));
+ if (empty($sId))
+ {
+ throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::UnknownError);
+ }
+
+ $oTemplate = false;
+ $aTemplates = $this->GetTemplates($oAccount);
+
+ foreach ($aTemplates as $oItem)
+ {
+ if ($oItem && $sId === $oItem->Id())
+ {
+ $oTemplate = $oItem;
+ break;
+ }
+ }
+
+ $oTemplate->SetPopulateAlways(true);
+ return $this->DefaultResponse(__FUNCTION__, $oTemplate);
+ }
+
/**
* @return array
*
@@ -2550,6 +2761,25 @@ class Actions
));
}
+ /**
+ * @return array
+ *
+ * @throws \MailSo\Base\Exceptions\Exception
+ */
+ public function DoTemplates()
+ {
+ $oAccount = $this->getAccountFromToken();
+
+ if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::TEMPLATES, $oAccount))
+ {
+ return $this->FalseResponse(__FUNCTION__);
+ }
+
+ return $this->DefaultResponse(__FUNCTION__, array(
+ 'Templates' => $this->GetTemplates($oAccount)
+ ));
+ }
+
/**
* @param string $sHash
*
@@ -2821,6 +3051,9 @@ class Actions
case \RainLoop\Enumerations\Capa::ADDITIONAL_ACCOUNTS:
$this->setConfigFromParams($oConfig, $sParamName, 'webmail', 'allow_additional_accounts', 'bool');
break;
+ case \RainLoop\Enumerations\Capa::TEMPLATES:
+ $this->setConfigFromParams($oConfig, $sParamName, 'capa', 'templates', 'bool');
+ break;
case \RainLoop\Enumerations\Capa::TWO_FACTOR:
$this->setConfigFromParams($oConfig, $sParamName, 'security', 'allow_two_factor_auth', 'bool');
break;
@@ -2923,6 +3156,7 @@ class Actions
});
$this->setCapaFromParams($oConfig, 'CapaAdditionalAccounts', \RainLoop\Enumerations\Capa::ADDITIONAL_ACCOUNTS);
+ $this->setCapaFromParams($oConfig, 'CapaTemplates', \RainLoop\Enumerations\Capa::TEMPLATES);
$this->setCapaFromParams($oConfig, 'CapaTwoFactorAuth', \RainLoop\Enumerations\Capa::TWO_FACTOR);
$this->setCapaFromParams($oConfig, 'CapaOpenPGP', \RainLoop\Enumerations\Capa::OPEN_PGP);
$this->setCapaFromParams($oConfig, 'CapaGravatar', \RainLoop\Enumerations\Capa::GRAVATAR);
@@ -5303,6 +5537,27 @@ class Actions
return $oMessage;
}
+ /**
+ * @param \RainLoop\Model\Account $oAccount
+ *
+ * @return void
+ */
+ private function deleteMessageAttachmnets($oAccount)
+ {
+ $aAttachments = $this->GetActionParam('Attachments', null);
+
+ if (\is_array($aAttachments))
+ {
+ foreach (\array_keys($aAttachments) as $sTempName)
+ {
+ if ($this->FilesProvider()->FileExists($oAccount, $sTempName))
+ {
+ $this->FilesProvider()->Clear($oAccount, $sTempName);
+ }
+ }
+ }
+ }
+
/**
* @param \RainLoop\Model\Account $oAccount
*
@@ -5600,6 +5855,8 @@ class Actions
{
$this->smtpSendMessage($oAccount, $oMessage, $rMessageStream, $iMessageStreamSize);
+ $this->deleteMessageAttachmnets($oAccount);
+
if (is_array($aDraftInfo) && 3 === count($aDraftInfo))
{
$sDraftInfoType = $aDraftInfo[0];
@@ -6967,7 +7224,7 @@ class Actions
$oSettings = $this->SettingsProvider()->Load($oAccount);
if ($oSettings)
{
- $sHash = \md5($sName.APP_VERSION.APP_SALT.\rand(1000, 9999).\microtime(true));
+ $sHash = \MailSo\Base\Utils::Md5Rand($sName.APP_VERSION.APP_SALT);
$oSettings->SetConf('UserBackgroundName', $sName);
$oSettings->SetConf('UserBackgroundHash', $sHash);
@@ -7225,7 +7482,7 @@ class Actions
$sLast = \array_pop($aParams);
$sUrl = $this->Http()->GetFullUrl().'?/Raw/&s=/'.implode('/', $aParams).'/&ss=/'.$sLast;
- $sFullUrl = 'http://docs.google.com/viewer?embedded=true&url='.urlencode($sUrl);
+ $sFullUrl = 'https://docs.google.com/viewer?embedded=true&url='.urlencode($sUrl);
@\header('Content-Type: text/html; charset=utf-8');
echo ''.
@@ -7272,6 +7529,8 @@ class Actions
$rMessageStream = $this->FilesProvider()->GetFile($oAccount, $sSavedName);
$this->MailClient()->MessageAppendStream($rMessageStream, $iMessageStreamSize, $sFolderFullNameRaw);
+
+ $this->FilesProvider()->Clear($oAccount, $sSavedName);
}
}
}
@@ -7301,6 +7560,11 @@ class Actions
}
}
+// if ($oConfig->Get('capa', 'templates', true))
+// {
+// $aResult[] = \RainLoop\Enumerations\Capa::TEMPLATES;
+// }
+
if ($oConfig->Get('webmail', 'allow_additional_accounts', false))
{
$aResult[] = \RainLoop\Enumerations\Capa::ADDITIONAL_ACCOUNTS;
@@ -7455,7 +7719,7 @@ class Actions
{
\MailSo\Base\StreamWrappers\TempFile::Reg();
- $sFileName = 'mailsotempfile://'.\md5($sFileNameOut.\rand(1000, 9999));
+ $sFileName = 'mailsotempfile://'.\MailSo\Base\Utils::Md5Rand($sFileNameOut);
$rTempResource = \fopen($sFileName, 'r+b');
if (@\is_resource($rTempResource))
@@ -8256,25 +8520,6 @@ class Actions
@\header('Location: '.$sUrl);
}
- /**
- * @param string $sTitle
- * @param string $sDesc
- *
- * @return mixed
- */
- public function ErrorTemplates($sTitle, $sDesc, $bShowBackLink = true)
- {
- return strtr(file_get_contents(APP_VERSION_ROOT_PATH.'app/templates/Error.html'), array(
- '{{BaseWebStaticPath}}' => APP_WEB_STATIC_PATH,
- '{{ErrorTitle}}' => $sTitle,
- '{{ErrorHeader}}' => $sTitle,
- '{{ErrorDesc}}' => $sDesc,
- '{{BackLinkVisibilityStyle}}' => $bShowBackLink ? 'display:inline-block' : 'display:none',
- '{{BackLink}}' => $this->StaticI18N('STATIC/BACK_LINK'),
- '{{BackHref}}' => './'
- ));
- }
-
/**
* @param object $oData
* @param string $sParent
diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Api.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Api.php
index 4d2e23cf8..736734b35 100644
--- a/rainloop/v/0.0.0/app/libraries/RainLoop/Api.php
+++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Api.php
@@ -136,7 +136,7 @@ class Api
*/
public static function GetUserSsoHash($sEmail, $sPassword, $bUseTimeout = true)
{
- $sSsoHash = \sha1(\rand(10000, 99999).$sEmail.$sPassword.\microtime(true));
+ $sSsoHash = \MailSo\Base\Utils::Sha1Rand($sEmail.$sPassword);
return \RainLoop\Api::Actions()->Cacher()->Set(\RainLoop\KeyPathHelper::SsoCacherKey($sSsoHash), \RainLoop\Utils::EncodeKeyValues(array(
'Email' => $sEmail,
diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Config/Application.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Config/Application.php
index 3c9b6bffa..7207daa8a 100644
--- a/rainloop/v/0.0.0/app/libraries/RainLoop/Config/Application.php
+++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Config/Application.php
@@ -129,7 +129,8 @@ class Application extends \RainLoop\Config\AbstractConfig
),
'capa' => array(
- 'filters' => array(true)
+ 'filters' => array(true),
+ 'templates' => array(true)
),
'login' => array(
@@ -164,6 +165,7 @@ Values:
'view_editor_type' => array('Html', 'Editor mode used by default (Plain, Html, HtmlForced or PlainForced)'),
'view_layout' => array(1, 'layout: 0 - no preview, 1 - side preview, 3 - bottom preview'),
'view_use_checkboxes' => array(true),
+ 'show_images' => array(false),
'contacts_autosave' => array(true),
'mail_use_threads' => array(false),
'mail_reply_same_folder' => array(false)
diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php
index 5f8dad390..8a5cef54a 100644
--- a/rainloop/v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php
+++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php
@@ -15,4 +15,5 @@ class Capa
const FILTERS = 'FILTERS';
const ATTACHMENT_THUMBNAILS = 'ATTACHMENT_THUMBNAILS';
const ADDITIONAL_ACCOUNTS = 'ADDITIONAL_ACCOUNTS';
+ const TEMPLATES = 'TEMPLATES';
}
diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Model/Template.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Model/Template.php
new file mode 100644
index 000000000..0d4b1e7b0
--- /dev/null
+++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Model/Template.php
@@ -0,0 +1,149 @@
+sId = $sId;
+ $this->sName = $sName;
+ $this->sBody = $sBody;
+ $this->bPopulateAlways = false;
+ }
+
+ /**
+ * @param string $sId = ''
+ * @param string $sName = ''
+ * @param string $sBody = ''
+ *
+ * @return \RainLoop\Model\Template
+ */
+ public static function NewInstance($sId = '', $sName = '', $sBody = '')
+ {
+ return new self($sId, $sBody);
+ }
+
+ /**
+ * @return string
+ */
+ public function Id()
+ {
+ return $this->sId;
+ }
+
+ /**
+ * @return string
+ */
+ public function Name()
+ {
+ return $this->sName;
+ }
+
+ /**
+ * @return string
+ */
+ public function Body()
+ {
+ return $this->sBody;
+ }
+
+ /**
+ * @param bool $bPopulateAlways
+ */
+ public function SetPopulateAlways($bPopulateAlways)
+ {
+ $this->bPopulateAlways = !!$bPopulateAlways;
+
+ }
+
+ /**
+ * @param array $aData
+ * @param bool $bAjax = false
+ *
+ * @return bool
+ */
+ public function FromJSON($aData, $bAjax = false)
+ {
+ if (isset($aData['ID'], $aData['Name'], $aData['Body']))
+ {
+ $this->sId = $aData['ID'];
+ $this->sName = $aData['Name'];
+ $this->sBody = $aData['Body'];
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * @param bool $bAjax = false
+ *
+ * @return array
+ */
+ public function ToSimpleJSON($bAjax = false)
+ {
+ $sBody = $this->Body();
+ $bPopulated = true;
+
+ if ($bAjax && $bPopulated && !$this->bPopulateAlways)
+ {
+ if (1024 * 5 < \strlen($sBody) || true)
+ {
+ $bPopulated = false;
+ $sBody = '';
+ }
+ }
+
+ return array(
+ 'ID' => $this->Id(),
+ 'Name' => $this->Name(),
+ 'Populated' => $bPopulated,
+ 'Body' => $sBody
+ );
+ }
+
+ /**
+ * @return bool
+ */
+ public function GenerateID()
+ {
+ return $this->sId = \MailSo\Base\Utils::Md5Rand();
+ }
+
+ /**
+ * @return bool
+ */
+ public function Validate()
+ {
+ return 0 < \strlen($this->sBody);
+ }
+}
diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/Classes/Contact.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/Classes/Contact.php
index cfd4916e8..0a20fae41 100644
--- a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/Classes/Contact.php
+++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/Classes/Contact.php
@@ -151,7 +151,7 @@ class Contact
public function RegenerateContactStr()
{
$this->IdContactStr = \class_exists('Sabre\DAV\Client') ?
- \Sabre\DAV\UUIDUtil::getUUID() : \md5(\microtime(true).'-'.\rand(10000, 99999));
+ \Sabre\DAV\UUIDUtil::getUUID() : \MailSo\Base\Utils::Md5Rand();
}
/**
diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Files.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Files.php
index 750a93a23..638848039 100644
--- a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Files.php
+++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Files.php
@@ -107,6 +107,15 @@ class Files extends \RainLoop\Providers\AbstractProvider
return $this->oDriver ? $this->oDriver->GC($iTimeToClearInHours) : false;
}
+ /**
+ * @return bool
+ */
+ public function CloseAllOpenedFiles()
+ {
+ return $this->oDriver && \method_exists($this->oDriver, 'CloseAllOpenedFiles') ?
+ $this->oDriver->CloseAllOpenedFiles() : false;
+ }
+
/**
* @return bool
*/
diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Files/DefaultStorage.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Files/DefaultStorage.php
index d3b7844d2..d377ff248 100644
--- a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Files/DefaultStorage.php
+++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Files/DefaultStorage.php
@@ -4,6 +4,11 @@ namespace RainLoop\Providers\Files;
class DefaultStorage implements \RainLoop\Providers\Files\FilesInterface
{
+ /**
+ * @var array
+ */
+ private $aResources;
+
/**
* @var string
*/
@@ -16,6 +21,7 @@ class DefaultStorage implements \RainLoop\Providers\Files\FilesInterface
*/
public function __construct($sStoragePath)
{
+ $this->aResources = array();
$this->sDataPath = \rtrim(\trim($sStoragePath), '\\/');
}
@@ -70,6 +76,11 @@ class DefaultStorage implements \RainLoop\Providers\Files\FilesInterface
if ($bCreate || \file_exists($sFileName))
{
$mResult = @\fopen($sFileName, $sOpenMode);
+
+ if (\is_resource($mResult))
+ {
+ $this->aResources[$sFileName] = $mResult;
+ }
}
return $mResult;
@@ -105,6 +116,11 @@ class DefaultStorage implements \RainLoop\Providers\Files\FilesInterface
$sFileName = $this->generateFileName($oAccount, $sKey);
if (\file_exists($sFileName))
{
+ if (isset($this->aResources[$sFileName]) && \is_resource($this->aResources[$sFileName]))
+ {
+ @\fclose($this->aResources[$sFileName]);
+ }
+
$mResult = @\unlink($sFileName);
}
@@ -156,6 +172,25 @@ class DefaultStorage implements \RainLoop\Providers\Files\FilesInterface
return false;
}
+ /**
+ * @return bool
+ */
+ public function CloseAllOpenedFiles()
+ {
+ if (\is_array($this->aResources) && 0 < \count($this->aResources))
+ {
+ foreach ($this->aResources as $sFileName => $rFile)
+ {
+ if (!empty($sFileName) && \is_resource($rFile))
+ {
+ @\fclose($rFile);
+ }
+ }
+ }
+
+ return true;
+ }
+
/**
* @param \RainLoop\Model\Account $oAccount
* @param string $sKey
diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Service.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Service.php
index 944d7c3de..2a8fee58b 100644
--- a/rainloop/v/0.0.0/app/libraries/RainLoop/Service.php
+++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Service.php
@@ -125,7 +125,7 @@ class Service
if ($bAdmin && !$this->oActions->Config()->Get('security', 'allow_admin_panel', true))
{
- echo $this->oActions->ErrorTemplates('Access Denied.',
+ echo $this->oServiceActions->ErrorTemplates('Access Denied.',
'Access to the RainLoop Webmail Admin Panel is not allowed!', true);
return $this;
@@ -150,6 +150,9 @@ class Service
if ($bIndex)
{
+ @\header('Content-Security-Policy:');
+ @\header_remove('Content-Security-Policy');
+
@header('Content-Type: text/html; charset=utf-8');
$this->oHttp->ServerNoCache();
@@ -216,7 +219,7 @@ class Service
$bAppJsDebug = !!$this->oActions->Config()->Get('labs', 'use_app_debug_js', false);
$bAppCssDebug = !!$this->oActions->Config()->Get('labs', 'use_app_debug_css', false);
- $sStaticPrefix = APP_WEB_STATIC_PATH;
+ $sStaticPrefix = $this->oServiceActions->WebStaticPath();
$aData = array(
'Language' => $sLanguage,
@@ -254,7 +257,7 @@ class Service
\implode('~', array(
\md5($this->oActions->Config()->Get('cache', 'index', '')),
$this->oActions->Plugins()->Hash(),
- APP_WEB_PATH, APP_VERSION
+ $this->oServiceActions->WebVersionPath(), APP_VERSION
)).
\implode('~', $aTemplateParameters)
);
diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/ServiceActions.php b/rainloop/v/0.0.0/app/libraries/RainLoop/ServiceActions.php
index dc1776a66..bd8f63976 100644
--- a/rainloop/v/0.0.0/app/libraries/RainLoop/ServiceActions.php
+++ b/rainloop/v/0.0.0/app/libraries/RainLoop/ServiceActions.php
@@ -675,7 +675,7 @@ class ServiceActions
if (\file_exists($sThemeFile) && \file_exists($sThemeTemplateFile) && \file_exists($sThemeValuesFile))
{
- $aResult[] = '@base: "'.($bCustomTheme ? '' : APP_WEB_PATH).'themes/'.$sRealTheme.'/";';
+ $aResult[] = '@base: "'.($bCustomTheme ? $this->WebPath() : $this->WebVersionPath()).'themes/'.$sRealTheme.'/";';
$aResult[] = \file_get_contents($sThemeValuesFile);
$aResult[] = \file_get_contents($sThemeFile);
$aResult[] = \file_get_contents($sThemeTemplateFile);
@@ -779,7 +779,7 @@ class ServiceActions
@\header('Content-Type: text/html; charset=utf-8');
return \strtr(\file_get_contents(APP_VERSION_ROOT_PATH.'app/templates/BadBrowser.html'), array(
- '{{BaseWebStaticPath}}' => APP_WEB_STATIC_PATH,
+ '{{BaseWebStaticPath}}' => $this->WebStaticPath(),
'{{ErrorTitle}}' => $sTitle,
'{{ErrorHeader}}' => $sTitle,
'{{ErrorDesc}}' => $sDesc
@@ -1051,6 +1051,58 @@ class ServiceActions
return '';
}
+ /**
+ * @param string $sTitle
+ * @param string $sDesc
+ *
+ * @return mixed
+ */
+ public function ErrorTemplates($sTitle, $sDesc, $bShowBackLink = true)
+ {
+ return strtr(file_get_contents(APP_VERSION_ROOT_PATH.'app/templates/Error.html'), array(
+ '{{BaseWebStaticPath}}' => $this->WebStaticPath(),
+ '{{ErrorTitle}}' => $sTitle,
+ '{{ErrorHeader}}' => $sTitle,
+ '{{ErrorDesc}}' => $sDesc,
+ '{{BackLinkVisibilityStyle}}' => $bShowBackLink ? 'display:inline-block' : 'display:none',
+ '{{BackLink}}' => $this->oActions->StaticI18N('STATIC/BACK_LINK'),
+ '{{BackHref}}' => './'
+ ));
+ }
+
+ /**
+ * @return string
+ */
+ public function WebPath()
+ {
+ if (isset($_ENV['RAINLOOP_OWNCLOUD']) && $_ENV['RAINLOOP_OWNCLOUD'])
+ {
+ $sUrl = $this->oHttp->GetUrl();
+ if ($sUrl && \preg_match('/\/index\.php\/apps\/rainloop/', $sUrl))
+ {
+ $sUrl = \preg_replace('/\/index\.php\/apps\/rainloop.+$/', '/', $sUrl);
+ return \rtrim(\trim($sUrl), '\//').'/apps/rainloop/app/';
+ }
+ }
+
+ return '';
+ }
+ /**
+ * @return string
+ */
+ public function WebVersionPath()
+ {
+ return $this->WebPath().'rainloop/v/'.APP_VERSION.'/';
+ }
+
+ /**
+ * @return string
+ */
+ public function WebStaticPath()
+ {
+ return $this->WebVersionPath().'static/';
+ }
+
/**
* @param string $sTitle
* @param string $sDesc
diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Utils.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Utils.php
index 23a1a516a..f04983e7e 100644
--- a/rainloop/v/0.0.0/app/libraries/RainLoop/Utils.php
+++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Utils.php
@@ -72,7 +72,7 @@ class Utils
$sToken = \RainLoop\Utils::GetCookie($sKey, null);
if (null === $sToken)
{
- $sToken = \md5(\rand(10000, 99999).\microtime(true).APP_SALT);
+ $sToken = \MailSo\Base\Utils::Md5Rand(APP_SALT);
\RainLoop\Utils::SetCookie($sKey, $sToken, \time() + 60 * 60 * 24 * 30, '/', null, null, true);
}
@@ -97,7 +97,7 @@ class Utils
$sToken = \RainLoop\Utils::GetCookie($sKey, null);
if (null === $sToken)
{
- $sToken = \md5(\rand(10000, 99999).\microtime(true).APP_SALT);
+ $sToken = \MailSo\Base\Utils::Md5Rand(APP_SALT);
\RainLoop\Utils::SetCookie($sKey, $sToken, 0, '/', null, null, true);
}
diff --git a/rainloop/v/0.0.0/app/templates/Views/Admin/AdminSettingsGeneral.html b/rainloop/v/0.0.0/app/templates/Views/Admin/AdminSettingsGeneral.html
index 1b7699f82..a074aaa6f 100644
--- a/rainloop/v/0.0.0/app/templates/Views/Admin/AdminSettingsGeneral.html
+++ b/rainloop/v/0.0.0/app/templates/Views/Admin/AdminSettingsGeneral.html
@@ -138,5 +138,18 @@
}">
+
\ No newline at end of file
diff --git a/rainloop/v/0.0.0/app/templates/Views/User/PopupsTemplate.html b/rainloop/v/0.0.0/app/templates/Views/User/PopupsTemplate.html
index ac99ffea9..1bfcc0cff 100644
--- a/rainloop/v/0.0.0/app/templates/Views/User/PopupsTemplate.html
+++ b/rainloop/v/0.0.0/app/templates/Views/User/PopupsTemplate.html
@@ -16,13 +16,15 @@
+
diff --git a/rainloop/v/0.0.0/include.php b/rainloop/v/0.0.0/include.php
index 22265ac91..17bce383f 100644
--- a/rainloop/v/0.0.0/include.php
+++ b/rainloop/v/0.0.0/include.php
@@ -26,9 +26,9 @@ Options -Indexes
if (file_exists(APP_INDEX_ROOT_PATH.'include.php'))
{
include_once APP_INDEX_ROOT_PATH.'include.php';
- $sCustomDataPath = function_exists('__get_custom_data_full_path') ? rtrim(trim(__get_custom_data_full_path()), '\\/') : '';
}
+ $sCustomDataPath = function_exists('__get_custom_data_full_path') ? rtrim(trim(__get_custom_data_full_path()), '\\/') : '';
define('APP_DATA_FOLDER_PATH', 0 === strlen($sCustomDataPath) ? APP_INDEX_ROOT_PATH.'data/' : $sCustomDataPath.'/');
unset($sCustomDataPath);
@@ -58,8 +58,6 @@ Options -Indexes
define('APP_REP_PATH', 'http://repository.rainloop.net/v1/');
define('APP_REPO_CORE_FILE', 'http://repository.rainloop.net/v2/core.{{channel}}.json');
define('APP_STATUS_PATH', 'http://status.rainloop.net/');
- define('APP_WEB_PATH', 'rainloop/v/'.APP_VERSION.'/');
- define('APP_WEB_STATIC_PATH', APP_WEB_PATH.'static/');
define('APP_DATA_FOLDER_PATH_UNIX', str_replace('\\', '/', APP_DATA_FOLDER_PATH));
$sSalt = @file_get_contents(APP_DATA_FOLDER_PATH.'SALT.php');