CRLF to LF

This commit is contained in:
djmaze 2020-03-11 14:17:52 +01:00
parent 4468d5bd22
commit 6e0d0b3b6e
209 changed files with 23729 additions and 22109 deletions

View file

@ -1,6 +1,7 @@
module.exports = { module.exports = {
parser: 'babel-eslint', parser: 'babel-eslint',
extends: ['eslint:recommended', 'plugin:prettier/recommended'], // extends: ['eslint:recommended', 'plugin:prettier/recommended'],
extends: ['eslint:recommended'],
plugins: ['prettier'], plugins: ['prettier'],
parserOptions: { parserOptions: {
ecmaVersion: 6, ecmaVersion: 6,
@ -18,8 +19,8 @@ module.exports = {
// http://eslint.org/docs/rules/ // http://eslint.org/docs/rules/
rules: { rules: {
// plugins // plugins
'prettier/prettier': 'error', // 'prettier/prettier': 'error',
'no-mixed-spaces-and-tabs': 'off',
'no-console': 'error', 'no-console': 'error',
'max-len': [ 'max-len': [
'error', 'error',

View file

@ -1,21 +1,21 @@
<?php <?php
// Name this file as "include.php" to enable it. // Name this file as "include.php" to enable it.
/** /**
* @return string * @return string
*/ */
function __get_custom_data_full_path() function __get_custom_data_full_path()
{ {
return ''; return '';
return '/var/external-rainloop-data-folder/'; // custom data folder path return '/var/external-rainloop-data-folder/'; // custom data folder path
} }
/** /**
* @return string * @return string
*/ */
function __get_additional_configuration_name() function __get_additional_configuration_name()
{ {
return ''; return '';
return defined('APP_SITE') && 0 < strlen(APP_SITE) ? APP_SITE.'.ini' : ''; // additional configuration file name return defined('APP_SITE') && 0 < strlen(APP_SITE) ? APP_SITE.'.ini' : ''; // additional configuration file name
} }

View file

@ -1125,8 +1125,7 @@ class AppUser extends AbstractApp {
let contactsSyncInterval = pInt(Settings.settingsGet('ContactsSyncInterval')); let contactsSyncInterval = pInt(Settings.settingsGet('ContactsSyncInterval'));
const jsHash = Settings.appSettingsGet('jsHash'), const startupUrl = pString(Settings.settingsGet('StartupUrl'));
startupUrl = pString(Settings.settingsGet('StartupUrl'));
if (progressJs) { if (progressJs) {
progressJs.set(90); progressJs.set(90);

View file

@ -1,8 +1,6 @@
import _ from '_'; import _ from '_';
import { Capa, MessageSetAction } from 'Common/Enums'; import { MessageSetAction } from 'Common/Enums';
import { trim, pInt, isArray } from 'Common/Utils'; import { trim, pInt, isArray } from 'Common/Utils';
import * as Links from 'Common/Links';
import * as Settings from 'Storage/Settings';
let FOLDERS_CACHE = {}, let FOLDERS_CACHE = {},
FOLDERS_NAME_CACHE = {}, FOLDERS_NAME_CACHE = {},
@ -12,8 +10,7 @@ let FOLDERS_CACHE = {},
NEW_MESSAGE_CACHE = {}, NEW_MESSAGE_CACHE = {},
inboxFolderName = ''; inboxFolderName = '';
const REQUESTED_MESSAGE_CACHE = {}, const REQUESTED_MESSAGE_CACHE = {};
capaGravatar = Settings.capa(Capa.Gravatar);
/** /**
* @returns {void} * @returns {void}
@ -33,7 +30,7 @@ export function clear() {
*/ */
export function getUserPic(email, callback) { export function getUserPic(email, callback) {
email = trim(email); email = trim(email);
callback(capaGravatar && '' !== email ? Links.avatarLink(email) : '', email); callback('', email);
} }
/** /**

View file

@ -83,11 +83,6 @@ export const bDisableNanoScroll = bMobileDevice;
export const bAnimationSupported = export const bAnimationSupported =
!bMobileDevice && $html.hasClass('csstransitions') && $html.hasClass('cssanimations'); !bMobileDevice && $html.hasClass('csstransitions') && $html.hasClass('cssanimations');
/**
* @type {boolean}
*/
export const bXMLHttpRequestSupported = !!window.XMLHttpRequest;
/** /**
* @type {boolean} * @type {boolean}
*/ */

View file

@ -37,7 +37,6 @@ class GeneralAdminSettings {
this.capaThemes = CapaAdminStore.themes; this.capaThemes = CapaAdminStore.themes;
this.capaUserBackground = CapaAdminStore.userBackground; this.capaUserBackground = CapaAdminStore.userBackground;
this.capaGravatar = CapaAdminStore.gravatar;
this.capaAdditionalAccounts = CapaAdminStore.additionalAccounts; this.capaAdditionalAccounts = CapaAdminStore.additionalAccounts;
this.capaIdentities = CapaAdminStore.identities; this.capaIdentities = CapaAdminStore.identities;
this.capaAttachmentThumbnails = CapaAdminStore.attachmentThumbnails; this.capaAttachmentThumbnails = CapaAdminStore.attachmentThumbnails;
@ -135,12 +134,6 @@ class GeneralAdminSettings {
}); });
}); });
this.capaGravatar.subscribe((value) => {
Remote.saveAdminConfig(null, {
'CapaGravatar': boolToAjax(value)
});
});
this.capaAttachmentThumbnails.subscribe((value) => { this.capaAttachmentThumbnails.subscribe((value) => {
Remote.saveAdminConfig(null, { Remote.saveAdminConfig(null, {
'CapaAttachmentThumbnails': boolToAjax(value) 'CapaAttachmentThumbnails': boolToAjax(value)

View file

@ -6,7 +6,6 @@ class CapaAdminStore {
constructor() { constructor() {
this.additionalAccounts = ko.observable(false); this.additionalAccounts = ko.observable(false);
this.identities = ko.observable(false); this.identities = ko.observable(false);
this.gravatar = ko.observable(false);
this.attachmentThumbnails = ko.observable(false); this.attachmentThumbnails = ko.observable(false);
this.sieve = ko.observable(false); this.sieve = ko.observable(false);
this.filters = ko.observable(false); this.filters = ko.observable(false);
@ -21,7 +20,6 @@ class CapaAdminStore {
populate() { populate() {
this.additionalAccounts(Settings.capa(Capa.AdditionalAccounts)); this.additionalAccounts(Settings.capa(Capa.AdditionalAccounts));
this.identities(Settings.capa(Capa.Identities)); this.identities(Settings.capa(Capa.Identities));
this.gravatar(Settings.capa(Capa.Gravatar));
this.attachmentThumbnails(Settings.capa(Capa.AttachmentThumbnails)); this.attachmentThumbnails(Settings.capa(Capa.AttachmentThumbnails));
this.sieve(Settings.capa(Capa.Sieve)); this.sieve(Settings.capa(Capa.Sieve));
this.filters(Settings.capa(Capa.Filters)); this.filters(Settings.capa(Capa.Filters));

View file

@ -1,63 +1,63 @@
.progressjs-theme-rainloop { .progressjs-theme-rainloop {
z-index: 2000; z-index: 2000;
} }
.progressjs-theme-rainloop .progressjs-inner { .progressjs-theme-rainloop .progressjs-inner {
background-color: #939595; background-color: #939595;
position: relative; position: relative;
z-index: 2000; z-index: 2000;
height: 3px; height: 3px;
overflow: hidden; overflow: hidden;
-webkit-transition: width .5s; -webkit-transition: width .5s;
-moz-transition: width .5s; -moz-transition: width .5s;
-o-transition: width .5s; -o-transition: width .5s;
transition: width .5s; transition: width .5s;
} }
.progressjs-theme-rainloop .progressjs-percent { .progressjs-theme-rainloop .progressjs-percent {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
right: -32px; right: -32px;
bottom: 0; bottom: 0;
background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.3)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.3)), color-stop(0.75, rgba(255, 255, 255, 0.3)), color-stop(0.75, transparent), to(transparent)); background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.3)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.3)), color-stop(0.75, rgba(255, 255, 255, 0.3)), color-stop(0.75, transparent), to(transparent));
background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.3) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.3) 50%, rgba(255, 255, 255, 0.3) 75%, transparent 75%, transparent); background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.3) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.3) 50%, rgba(255, 255, 255, 0.3) 75%, transparent 75%, transparent);
background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.3) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.3) 50%, rgba(255, 255, 255, 0.3) 75%, transparent 75%, transparent); background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.3) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.3) 50%, rgba(255, 255, 255, 0.3) 75%, transparent 75%, transparent);
background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.3) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.3) 50%, rgba(255, 255, 255, 0.3) 75%, transparent 75%, transparent); background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.3) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.3) 50%, rgba(255, 255, 255, 0.3) 75%, transparent 75%, transparent);
background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.3) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.3) 50%, rgba(255, 255, 255, 0.3) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.3) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.3) 50%, rgba(255, 255, 255, 0.3) 75%, transparent 75%, transparent);
-webkit-background-size: 32px 32px; -webkit-background-size: 32px 32px;
-moz-background-size: 32px 32px; -moz-background-size: 32px 32px;
-o-background-size: 32px 32px; -o-background-size: 32px 32px;
background-size: 32px 32px; background-size: 32px 32px;
-webkit-animation: simple-pace-stripe-animation 500ms linear infinite; -webkit-animation: simple-pace-stripe-animation 500ms linear infinite;
-moz-animation: simple-pace-stripe-animation 500ms linear infinite; -moz-animation: simple-pace-stripe-animation 500ms linear infinite;
-ms-animation: simple-pace-stripe-animation 500ms linear infinite; -ms-animation: simple-pace-stripe-animation 500ms linear infinite;
-o-animation: simple-pace-stripe-animation 500ms linear infinite; -o-animation: simple-pace-stripe-animation 500ms linear infinite;
animation: simple-pace-stripe-animation 500ms linear infinite; animation: simple-pace-stripe-animation 500ms linear infinite;
} }
@-webkit-keyframes simple-pace-stripe-animation { @-webkit-keyframes simple-pace-stripe-animation {
0% { -webkit-transform: none; transform: none; } 0% { -webkit-transform: none; transform: none; }
100% { -webkit-transform: translate(-32px, 0); transform: translate(-32px, 0); } 100% { -webkit-transform: translate(-32px, 0); transform: translate(-32px, 0); }
} }
@-moz-keyframes simple-pace-stripe-animation { @-moz-keyframes simple-pace-stripe-animation {
0% { -moz-transform: none; transform: none; } 0% { -moz-transform: none; transform: none; }
100% { -moz-transform: translate(-32px, 0); transform: translate(-32px, 0); } 100% { -moz-transform: translate(-32px, 0); transform: translate(-32px, 0); }
} }
@-o-keyframes simple-pace-stripe-animation { @-o-keyframes simple-pace-stripe-animation {
0% { -o-transform: none; transform: none; } 0% { -o-transform: none; transform: none; }
100% { -o-transform: translate(-32px, 0); transform: translate(-32px, 0); } 100% { -o-transform: translate(-32px, 0); transform: translate(-32px, 0); }
} }
@-ms-keyframes simple-pace-stripe-animation { @-ms-keyframes simple-pace-stripe-animation {
0% { -ms-transform: none; transform: none; } 0% { -ms-transform: none; transform: none; }
100% { -ms-transform: translate(-32px, 0); transform: translate(-32px, 0); } 100% { -ms-transform: translate(-32px, 0); transform: translate(-32px, 0); }
} }
@keyframes simple-pace-stripe-animation { @keyframes simple-pace-stripe-animation {
0% { transform: none; transform: none; } 0% { transform: none; transform: none; }
100% { transform: translate(-32px, 0); transform: translate(-32px, 0); } 100% { transform: translate(-32px, 0); transform: translate(-32px, 0); }
} }

View file

@ -34,13 +34,13 @@ import {
} from 'Common/Utils'; } from 'Common/Utils';
import { UNUSED_OPTION_VALUE } from 'Common/Consts'; import { UNUSED_OPTION_VALUE } from 'Common/Consts';
import { bXMLHttpRequestSupported, bMobileDevice } from 'Common/Globals';
import { upload } from 'Common/Links'; import { upload } from 'Common/Links';
import { i18n, getNotification, getUploadErrorDescByCode } from 'Common/Translator'; import { i18n, getNotification, getUploadErrorDescByCode } from 'Common/Translator';
import { format as momentorFormat } from 'Common/Momentor'; import { format as momentorFormat } from 'Common/Momentor';
import { getMessageFlagsFromCache, setMessageFlagsToCache, setFolderHash } from 'Common/Cache'; import { getMessageFlagsFromCache, setMessageFlagsToCache, setFolderHash } from 'Common/Cache';
import { HtmlEditor } from 'Common/HtmlEditor'; import { HtmlEditor } from 'Common/HtmlEditor';
import { bMobileDevice } from 'Common/Globals';
import AppStore from 'Stores/User/App'; import AppStore from 'Stores/User/App';
import SettingsStore from 'Stores/User/Settings'; import SettingsStore from 'Stores/User/Settings';

View file

@ -1,4 +1,3 @@
import window from 'window';
import _ from '_'; import _ from '_';
import ko from 'ko'; import ko from 'ko';
@ -11,7 +10,7 @@ import {
Notification Notification
} from 'Common/Enums'; } from 'Common/Enums';
import { trim, inArray, pInt, convertLangName, triggerAutocompleteInputChange } from 'Common/Utils'; import { trim, inArray, convertLangName, triggerAutocompleteInputChange } from 'Common/Utils';
import { $win } from 'Common/Globals'; import { $win } from 'Common/Globals';
import { getNotification, getNotificationFromResponse, reload as translatorReload } from 'Common/Translator'; import { getNotification, getNotificationFromResponse, reload as translatorReload } from 'Common/Translator';
@ -289,8 +288,7 @@ class LoginUserView extends AbstractViewNext {
onBuild() { onBuild() {
const signMeLocal = Local.get(ClientSideKeyName.LastSignMe), const signMeLocal = Local.get(ClientSideKeyName.LastSignMe),
signMe = (Settings.settingsGet('SignMe') || 'unused').toLowerCase(), signMe = (Settings.settingsGet('SignMe') || 'unused').toLowerCase();
jsHash = Settings.appSettingsGet('jsHash');
switch (signMe) { switch (signMe) {
case LoginSignMeTypeAsString.DefaultOff: case LoginSignMeTypeAsString.DefaultOff:

View file

@ -1,4 +1,3 @@
import window from 'window';
import _ from '_'; import _ from '_';
import $ from '$'; import $ from '$';
import ko from 'ko'; import ko from 'ko';
@ -22,7 +21,6 @@ import { $html, leftPanelDisabled, keyScopeReal, useKeyboardShortcuts, moveActio
import { import {
inArray, inArray,
isArray,
isNonEmptyArray, isNonEmptyArray,
trim, trim,
noop, noop,

View file

@ -1,19 +1,19 @@
<?php <?php
if (!defined('APP_VERSION')) if (!defined('APP_VERSION'))
{ {
define('APP_VERSION', '0.0.0'); define('APP_VERSION', '0.0.0');
define('APP_VERSION_TYPE', 'source'); define('APP_VERSION_TYPE', 'source');
define('APP_INDEX_ROOT_FILE', __FILE__); define('APP_INDEX_ROOT_FILE', __FILE__);
define('APP_INDEX_ROOT_PATH', str_replace('\\', '/', rtrim(dirname(__FILE__), '\\/').'/')); define('APP_INDEX_ROOT_PATH', str_replace('\\', '/', rtrim(dirname(__FILE__), '\\/').'/'));
} }
if (file_exists(APP_INDEX_ROOT_PATH.'rainloop/v/'.APP_VERSION.'/include.php')) if (file_exists(APP_INDEX_ROOT_PATH.'rainloop/v/'.APP_VERSION.'/include.php'))
{ {
include APP_INDEX_ROOT_PATH.'rainloop/v/'.APP_VERSION.'/include.php'; include APP_INDEX_ROOT_PATH.'rainloop/v/'.APP_VERSION.'/include.php';
} }
else else
{ {
echo '[105] Missing version directory'; echo '[105] Missing version directory';
exit(105); exit(105);
} }

View file

@ -1,40 +1,40 @@
<?php <?php
class AddXOriginatingIpHeaderPlugin extends \RainLoop\Plugins\AbstractPlugin class AddXOriginatingIpHeaderPlugin extends \RainLoop\Plugins\AbstractPlugin
{ {
public function Init() public function Init()
{ {
$this->addHook('filter.build-message', 'FilterBuildMessage'); $this->addHook('filter.build-message', 'FilterBuildMessage');
} }
/** /**
* @param \MailSo\Mime\Message $oMessage * @param \MailSo\Mime\Message $oMessage
*/ */
public function FilterBuildMessage(&$oMessage) public function FilterBuildMessage(&$oMessage)
{ {
if ($oMessage instanceof \MailSo\Mime\Message) if ($oMessage instanceof \MailSo\Mime\Message)
{ {
$sIP = $this->Manager()->Actions()->Http()->GetClientIp( $sIP = $this->Manager()->Actions()->Http()->GetClientIp(
!!$this->Config()->Get('plugin', 'check_proxy', false)); !!$this->Config()->Get('plugin', 'check_proxy', false));
$oMessage->SetCustomHeader( $oMessage->SetCustomHeader(
\MailSo\Mime\Enumerations\Header::X_ORIGINATING_IP, \MailSo\Mime\Enumerations\Header::X_ORIGINATING_IP,
$this->Manager()->Actions()->Http()->IsLocalhost($sIP) ? '127.0.0.1' : $sIP $this->Manager()->Actions()->Http()->IsLocalhost($sIP) ? '127.0.0.1' : $sIP
); );
} }
} }
/** /**
* @return array * @return array
*/ */
public function configMapping() public function configMapping()
{ {
return array( return array(
\RainLoop\Plugins\Property::NewInstance('check_proxy') \RainLoop\Plugins\Property::NewInstance('check_proxy')
->SetLabel('Сheck User Proxy') ->SetLabel('Сheck User Proxy')
->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL) ->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL)
->SetDescription('Enable, if you need to check proxy header') ->SetDescription('Enable, if you need to check proxy header')
->SetDefaultValue(false) ->SetDefaultValue(false)
); );
} }
} }

View file

@ -7,15 +7,15 @@
* *
* Based on: * Based on:
* https://github.com/RainLoop/rainloop-webmail/blob/master/plugins/override-smtp-credentials/index.php * https://github.com/RainLoop/rainloop-webmail/blob/master/plugins/override-smtp-credentials/index.php
* *
*/ */
class AutoDomainGrabPlugin extends \RainLoop\Plugins\AbstractPlugin class AutoDomainGrabPlugin extends \RainLoop\Plugins\AbstractPlugin
{ {
private $imap_prefix = "mail."; private $imap_prefix = "mail.";
private $smtp_prefix = "mail."; private $smtp_prefix = "mail.";
public function Init() public function Init()
{ {
$this->addHook('filter.smtp-credentials', 'FilterSmtpCredentials'); $this->addHook('filter.smtp-credentials', 'FilterSmtpCredentials');
@ -41,7 +41,7 @@ class AutoDomainGrabPlugin extends \RainLoop\Plugins\AbstractPlugin
{ {
$aImapCredentials['Host'] = $mxhosts[0]; $aImapCredentials['Host'] = $mxhosts[0];
} }
else else
{ {
$aImapCredentials['Host'] = $this->imap_prefix.$domain; $aImapCredentials['Host'] = $this->imap_prefix.$domain;
} }
@ -67,8 +67,8 @@ class AutoDomainGrabPlugin extends \RainLoop\Plugins\AbstractPlugin
if(getmxrr($domain, $mxhosts) && sizeof($mxhosts) > 0) if(getmxrr($domain, $mxhosts) && sizeof($mxhosts) > 0)
{ {
$aSmtpCredentials['Host'] = $mxhosts[0]; $aSmtpCredentials['Host'] = $mxhosts[0];
} }
else else
{ {
$aSmtpCredentials['Host'] = $this->smtp_prefix.$domain; $aSmtpCredentials['Host'] = $this->smtp_prefix.$domain;
} }

View file

@ -1,237 +1,237 @@
<?php <?php
class ChangePasswordCustomSqlDriver implements \RainLoop\Providers\ChangePassword\ChangePasswordInterface class ChangePasswordCustomSqlDriver implements \RainLoop\Providers\ChangePassword\ChangePasswordInterface
{ {
/** /**
* @var string * @var string
*/ */
private $mHost = '127.0.0.1'; private $mHost = '127.0.0.1';
/** /**
* @var string * @var string
*/ */
private $mUser = ''; private $mUser = '';
/** /**
* @var string * @var string
*/ */
private $mPass = ''; private $mPass = '';
/** /**
* @var string * @var string
*/ */
private $mDatabase = ''; private $mDatabase = '';
/** /**
* @var string * @var string
*/ */
private $mTable = ''; private $mTable = '';
/** /**
* @var string * @var string
*/ */
private $mSql = ''; private $mSql = '';
/** /**
* @var \MailSo\Log\Logger * @var \MailSo\Log\Logger
*/ */
private $oLogger = null; private $oLogger = null;
/** /**
* @param string $mHost * @param string $mHost
* *
* @return \ChangePasswordCustomSqlDriver * @return \ChangePasswordCustomSqlDriver
*/ */
public function SetmHost($mHost) public function SetmHost($mHost)
{ {
$this->mHost = $mHost; $this->mHost = $mHost;
return $this; return $this;
} }
/** /**
* @param string $mUser * @param string $mUser
* *
* @return \ChangePasswordCustomSqlDriver * @return \ChangePasswordCustomSqlDriver
*/ */
public function SetmUser($mUser) public function SetmUser($mUser)
{ {
$this->mUser = $mUser; $this->mUser = $mUser;
return $this; return $this;
} }
/** /**
* @param string $mPass * @param string $mPass
* *
* @return \ChangePasswordCustomSqlDriver * @return \ChangePasswordCustomSqlDriver
*/ */
public function SetmPass($mPass) public function SetmPass($mPass)
{ {
$this->mPass = $mPass; $this->mPass = $mPass;
return $this; return $this;
} }
/** /**
* @param string $mDatabase * @param string $mDatabase
* *
* @return \ChangePasswordCustomSqlDriver * @return \ChangePasswordCustomSqlDriver
*/ */
public function SetmDatabase($mDatabase) public function SetmDatabase($mDatabase)
{ {
$this->mDatabase = $mDatabase; $this->mDatabase = $mDatabase;
return $this; return $this;
} }
/** /**
* @param string $mTable * @param string $mTable
* *
* @return \ChangePasswordCustomSqlDriver * @return \ChangePasswordCustomSqlDriver
*/ */
public function SetmTable($mTable) public function SetmTable($mTable)
{ {
$this->mTable = $mTable; $this->mTable = $mTable;
return $this; return $this;
} }
/** /**
* @param string $mSql * @param string $mSql
* *
* @return \ChangePasswordCustomSqlDriver * @return \ChangePasswordCustomSqlDriver
*/ */
public function SetmSql($mSql) public function SetmSql($mSql)
{ {
$this->mSql = $mSql; $this->mSql = $mSql;
return $this; return $this;
} }
/** /**
* @param \MailSo\Log\Logger $oLogger * @param \MailSo\Log\Logger $oLogger
* *
* @return \ChangePasswordCustomSqlDriver * @return \ChangePasswordCustomSqlDriver
*/ */
public function SetLogger($oLogger) public function SetLogger($oLogger)
{ {
if ($oLogger instanceof \MailSo\Log\Logger) if ($oLogger instanceof \MailSo\Log\Logger)
{ {
$this->oLogger = $oLogger; $this->oLogger = $oLogger;
} }
return $this; return $this;
} }
/** /**
* @param \RainLoop\Account $oAccount * @param \RainLoop\Account $oAccount
* *
* @return bool * @return bool
*/ */
public function PasswordChangePossibility($oAccount) public function PasswordChangePossibility($oAccount)
{ {
return $oAccount && $oAccount->Email(); return $oAccount && $oAccount->Email();
} }
/** /**
* @param \RainLoop\Account $oAccount * @param \RainLoop\Account $oAccount
* @param string $sPrevPassword * @param string $sPrevPassword
* @param string $sNewPassword * @param string $sNewPassword
* *
* @return bool * @return bool
*/ */
public function ChangePassword(\RainLoop\Account $oAccount, $sPrevPassword, $sNewPassword) public function ChangePassword(\RainLoop\Account $oAccount, $sPrevPassword, $sNewPassword)
{ {
if ($this->oLogger) if ($this->oLogger)
{ {
$this->oLogger->Write('Try to change password for '.$oAccount->Email()); $this->oLogger->Write('Try to change password for '.$oAccount->Email());
} }
$bResult = false; $bResult = false;
$dsn = 'mysql:host='.$this->mHost.';dbname='.$this->mDatabase.';charset=utf8'; $dsn = 'mysql:host='.$this->mHost.';dbname='.$this->mDatabase.';charset=utf8';
$options = array( $options = array(
PDO::ATTR_EMULATE_PREPARES => true, PDO::ATTR_EMULATE_PREPARES => true,
PDO::ATTR_PERSISTENT => true, PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
); );
try try
{ {
$conn = new PDO($dsn,$this->mUser,$this->mPass,$options); $conn = new PDO($dsn,$this->mUser,$this->mPass,$options);
//prepare SQL varaibles //prepare SQL varaibles
$sEmail = $oAccount->Email(); $sEmail = $oAccount->Email();
$sEmailUser = \MailSo\Base\Utils::GetAccountNameFromEmail($sEmail); $sEmailUser = \MailSo\Base\Utils::GetAccountNameFromEmail($sEmail);
$sEmailDomain = \MailSo\Base\Utils::GetDomainFromEmail($sEmail); $sEmailDomain = \MailSo\Base\Utils::GetDomainFromEmail($sEmail);
// some variables cannot be prepared // some variables cannot be prepared
$this->mSql = str_replace(array( $this->mSql = str_replace(array(
':table' ':table'
), array( ), array(
$this->mTable $this->mTable
), $this->mSql); ), $this->mSql);
$placeholders = array( $placeholders = array(
':email' => $sEmail, ':email' => $sEmail,
':oldpass' => $sPrevPassword, ':oldpass' => $sPrevPassword,
':newpass' => $sNewPassword, ':newpass' => $sNewPassword,
':domain' => $sEmailDomain, ':domain' => $sEmailDomain,
':username' => $sEmailUser ':username' => $sEmailUser
); );
// we have to check that all placehoders are used in the query, passing any unused placeholders will generate an error // we have to check that all placehoders are used in the query, passing any unused placeholders will generate an error
$used_placeholders = array(); $used_placeholders = array();
foreach($placeholders as $placeholder => $value) { foreach($placeholders as $placeholder => $value) {
if(preg_match_all('/'.$placeholder . '(?![a-zA-Z0-9\-])'.'/', $this->mSql) === 1) { if(preg_match_all('/'.$placeholder . '(?![a-zA-Z0-9\-])'.'/', $this->mSql) === 1) {
// backwards-compabitibility: remove single and double quotes around placeholders // backwards-compabitibility: remove single and double quotes around placeholders
$this->mSql = str_replace('`'.$placeholder.'`', $placeholder, $this->mSql); $this->mSql = str_replace('`'.$placeholder.'`', $placeholder, $this->mSql);
$this->mSql = str_replace("'".$placeholder."'", $placeholder, $this->mSql); $this->mSql = str_replace("'".$placeholder."'", $placeholder, $this->mSql);
$this->mSql = str_replace('"'.$placeholder.'"', $placeholder, $this->mSql); $this->mSql = str_replace('"'.$placeholder.'"', $placeholder, $this->mSql);
$used_placeholders[$placeholder] = $value; $used_placeholders[$placeholder] = $value;
} }
} }
$statement = $conn->prepare($this->mSql); $statement = $conn->prepare($this->mSql);
// everything is ready (hopefully), bind the values // everything is ready (hopefully), bind the values
foreach($used_placeholders as $placeholder => $value) { foreach($used_placeholders as $placeholder => $value) {
$statement->bindValue($placeholder, $value); $statement->bindValue($placeholder, $value);
} }
// and execute // and execute
$mSqlReturn = $statement->execute(); $mSqlReturn = $statement->execute();
/* can be used for debugging /* can be used for debugging
ob_start(); ob_start();
$statement->debugDumpParams(); $statement->debugDumpParams();
$r = ob_get_contents(); $r = ob_get_contents();
ob_end_clean(); ob_end_clean();
$this->oLogger->Write($r); $this->oLogger->Write($r);
*/ */
if ($mSqlReturn == true) if ($mSqlReturn == true)
{ {
$bResult = true; $bResult = true;
if ($this->oLogger) if ($this->oLogger)
{ {
$this->oLogger->Write('Success! Password changed.'); $this->oLogger->Write('Success! Password changed.');
} }
} }
else else
{ {
$bResult = false; $bResult = false;
if ($this->oLogger) if ($this->oLogger)
{ {
$this->oLogger->Write('Something went wrong. Either current password is incorrect, or new password does not match criteria.'); $this->oLogger->Write('Something went wrong. Either current password is incorrect, or new password does not match criteria.');
} }
} }
} }
catch (\Exception $oException) catch (\Exception $oException)
{ {
$bResult = false; $bResult = false;
if ($this->oLogger) if ($this->oLogger)
{ {
$this->oLogger->WriteException($oException); $this->oLogger->WriteException($oException);
} }
} }
return $bResult; return $bResult;
} }
} }

View file

@ -1,53 +1,53 @@
<?php <?php
class ChangePasswordCustomSqlPlugin extends \RainLoop\Plugins\AbstractPlugin class ChangePasswordCustomSqlPlugin extends \RainLoop\Plugins\AbstractPlugin
{ {
public function Init() public function Init()
{ {
$this->addHook('main.fabrica', 'MainFabrica'); $this->addHook('main.fabrica', 'MainFabrica');
} }
/** /**
* @param string $sName * @param string $sName
* @param mixed $oProvider * @param mixed $oProvider
*/ */
public function MainFabrica($sName, &$oProvider) public function MainFabrica($sName, &$oProvider)
{ {
switch ($sName) switch ($sName)
{ {
case 'change-password': case 'change-password':
include_once __DIR__.'/ChangePasswordCustomSqlDriver.php'; include_once __DIR__.'/ChangePasswordCustomSqlDriver.php';
$oProvider = new ChangePasswordCustomSqlDriver(); $oProvider = new ChangePasswordCustomSqlDriver();
$oProvider $oProvider
->SetLogger($this->Manager()->Actions()->Logger()) ->SetLogger($this->Manager()->Actions()->Logger())
->SetmHost($this->Config()->Get('plugin', 'mHost', '')) ->SetmHost($this->Config()->Get('plugin', 'mHost', ''))
->SetmUser($this->Config()->Get('plugin', 'mUser', '')) ->SetmUser($this->Config()->Get('plugin', 'mUser', ''))
->SetmPass($this->Config()->Get('plugin', 'mPass', '')) ->SetmPass($this->Config()->Get('plugin', 'mPass', ''))
->SetmDatabase($this->Config()->Get('plugin', 'mDatabase', '')) ->SetmDatabase($this->Config()->Get('plugin', 'mDatabase', ''))
->SetmTable($this->Config()->Get('plugin', 'mTable', '')) ->SetmTable($this->Config()->Get('plugin', 'mTable', ''))
->SetmSql($this->Config()->Get('plugin', 'mSql', '')) ->SetmSql($this->Config()->Get('plugin', 'mSql', ''))
; ;
break; break;
} }
} }
/** /**
* @return array * @return array
*/ */
public function configMapping() public function configMapping()
{ {
return array( return array(
\RainLoop\Plugins\Property::NewInstance('mHost')->SetLabel('MySQL Host') \RainLoop\Plugins\Property::NewInstance('mHost')->SetLabel('MySQL Host')
->SetDefaultValue('127.0.0.1'), ->SetDefaultValue('127.0.0.1'),
\RainLoop\Plugins\Property::NewInstance('mUser')->SetLabel('MySQL User'), \RainLoop\Plugins\Property::NewInstance('mUser')->SetLabel('MySQL User'),
\RainLoop\Plugins\Property::NewInstance('mPass')->SetLabel('MySQL Password') \RainLoop\Plugins\Property::NewInstance('mPass')->SetLabel('MySQL Password')
->SetType(\RainLoop\Enumerations\PluginPropertyType::PASSWORD), ->SetType(\RainLoop\Enumerations\PluginPropertyType::PASSWORD),
\RainLoop\Plugins\Property::NewInstance('mDatabase')->SetLabel('MySQL Database'), \RainLoop\Plugins\Property::NewInstance('mDatabase')->SetLabel('MySQL Database'),
\RainLoop\Plugins\Property::NewInstance('mTable')->SetLabel('MySQL Table'), \RainLoop\Plugins\Property::NewInstance('mTable')->SetLabel('MySQL Table'),
\RainLoop\Plugins\Property::NewInstance('mSql')->SetLabel('SQL statement') \RainLoop\Plugins\Property::NewInstance('mSql')->SetLabel('SQL statement')
->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING_TEXT) ->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING_TEXT)
->SetDescription('SQL statement (allowed wildcards :table, :email, :oldpass, :newpass, :domain, :username). Use SQL functions for encryption.') ->SetDescription('SQL statement (allowed wildcards :table, :email, :oldpass, :newpass, :domain, :username). Use SQL functions for encryption.')
->SetDefaultValue('UPDATE :table SET password = md5(:newpass) WHERE domain = :domain AND username = :username and oldpass = md5(:oldpass)') ->SetDefaultValue('UPDATE :table SET password = md5(:newpass) WHERE domain = :domain AND username = :username and oldpass = md5(:oldpass)')
); );
} }
} }

View file

@ -1,138 +1,138 @@
<?php <?php
class ChangePasswordCyberPanel implements \RainLoop\Providers\ChangePassword\ChangePasswordInterface class ChangePasswordCyberPanel implements \RainLoop\Providers\ChangePassword\ChangePasswordInterface
{ {
/** /**
* @var string * @var string
*/ */
private $mHost = '127.0.0.1'; private $mHost = '127.0.0.1';
/** /**
* @var string * @var string
*/ */
private $mUser = ''; private $mUser = '';
/** /**
* @var string * @var string
*/ */
private $mPass = ''; private $mPass = '';
/** /**
* @var \MailSo\Log\Logger * @var \MailSo\Log\Logger
*/ */
private $oLogger = null; private $oLogger = null;
/** /**
* @param string $mHost * @param string $mHost
* *
* @return \ChangePasswordCyberPanel * @return \ChangePasswordCyberPanel
*/ */
public function SetmHost($mHost) public function SetmHost($mHost)
{ {
$this->mHost = $mHost; $this->mHost = $mHost;
return $this; return $this;
} }
/** /**
* @param string $mUser * @param string $mUser
* *
* @return \ChangePasswordCyberPanel * @return \ChangePasswordCyberPanel
*/ */
public function SetmUser($mUser) public function SetmUser($mUser)
{ {
$this->mUser = $mUser; $this->mUser = $mUser;
return $this; return $this;
} }
/** /**
* @param string $mPass * @param string $mPass
* *
* @return \ChangePasswordCyberPanel * @return \ChangePasswordCyberPanel
*/ */
public function SetmPass($mPass) public function SetmPass($mPass)
{ {
$this->mPass = $mPass; $this->mPass = $mPass;
return $this; return $this;
} }
/** /**
* @param \MailSo\Log\Logger $oLogger * @param \MailSo\Log\Logger $oLogger
* *
* @return \ChangePasswordCyberPanel * @return \ChangePasswordCyberPanel
*/ */
public function SetLogger($oLogger) public function SetLogger($oLogger)
{ {
if ($oLogger instanceof \MailSo\Log\Logger) if ($oLogger instanceof \MailSo\Log\Logger)
{ {
$this->oLogger = $oLogger; $this->oLogger = $oLogger;
} }
return $this; return $this;
} }
/** /**
* @param \RainLoop\Account $oAccount * @param \RainLoop\Account $oAccount
* *
* @return bool * @return bool
*/ */
public function PasswordChangePossibility($oAccount) public function PasswordChangePossibility($oAccount)
{ {
return $oAccount && $oAccount->Email(); return $oAccount && $oAccount->Email();
} }
/** /**
* @param \RainLoop\Account $oAccount * @param \RainLoop\Account $oAccount
* @param string $sPrevPassword * @param string $sPrevPassword
* @param string $sNewPassword * @param string $sNewPassword
* *
* @return bool * @return bool
*/ */
public function ChangePassword(\RainLoop\Account $oAccount, $sPrevPassword, $sNewPassword) public function ChangePassword(\RainLoop\Account $oAccount, $sPrevPassword, $sNewPassword)
{ {
if ($this->oLogger) if ($this->oLogger)
{ {
$this->oLogger->Write('Try to change password for '.$oAccount->Email()); $this->oLogger->Write('Try to change password for '.$oAccount->Email());
} }
$bResult = false; $bResult = false;
$db = mysqli_connect($this->mHost, $this->mUser, $this->mPass, 'cyberpanel'); $db = mysqli_connect($this->mHost, $this->mUser, $this->mPass, 'cyberpanel');
try try
{ {
$sEmail = mysqli_real_escape_string($db, $oAccount->Email()); $sEmail = mysqli_real_escape_string($db, $oAccount->Email());
$sEmailUser = mysqli_real_escape_string($db, \MailSo\Base\Utils::GetAccountNameFromEmail($sEmail)); $sEmailUser = mysqli_real_escape_string($db, \MailSo\Base\Utils::GetAccountNameFromEmail($sEmail));
$sEmailDomain = mysqli_real_escape_string($db, \MailSo\Base\Utils::GetDomainFromEmail($sEmail)); $sEmailDomain = mysqli_real_escape_string($db, \MailSo\Base\Utils::GetDomainFromEmail($sEmail));
$password_check_query = "SELECT * FROM e_users WHERE emailOwner_id = '$sEmailDomain' AND email = '$sEmail'"; $password_check_query = "SELECT * FROM e_users WHERE emailOwner_id = '$sEmailDomain' AND email = '$sEmail'";
$result = mysqli_query($db, $password_check_query); $result = mysqli_query($db, $password_check_query);
$password_check = mysqli_fetch_assoc($result); $password_check = mysqli_fetch_assoc($result);
if (password_verify($sPrevPassword, substr($password_check['password'], 7))) { if (password_verify($sPrevPassword, substr($password_check['password'], 7))) {
$hashed_password = mysqli_real_escape_string($db, '{CRYPT}'.password_hash($sNewPassword, PASSWORD_BCRYPT, ['cost' => 12,])); $hashed_password = mysqli_real_escape_string($db, '{CRYPT}'.password_hash($sNewPassword, PASSWORD_BCRYPT, ['cost' => 12,]));
$password_update_query = "UPDATE e_users SET password = '$hashed_password' WHERE emailOwner_id = '$sEmailDomain' AND email = '$sEmail'"; $password_update_query = "UPDATE e_users SET password = '$hashed_password' WHERE emailOwner_id = '$sEmailDomain' AND email = '$sEmail'";
mysqli_query($db, $password_update_query); mysqli_query($db, $password_update_query);
$bResult = true; $bResult = true;
if ($this->oLogger) if ($this->oLogger)
{ {
$this->oLogger->Write('Success! The password was changed.'); $this->oLogger->Write('Success! The password was changed.');
} }
} else { } else {
$bResult = false; $bResult = false;
if ($this->oLogger) if ($this->oLogger)
{ {
$this->oLogger->Write('Something went wrong. Either the current password is incorrect or the new password does not meet the criteria.'); $this->oLogger->Write('Something went wrong. Either the current password is incorrect or the new password does not meet the criteria.');
} }
} }
} }
catch (\Exception $oException) catch (\Exception $oException)
{ {
$bResult = false; $bResult = false;
if ($this->oLogger) if ($this->oLogger)
{ {
$this->oLogger->WriteException($oException); $this->oLogger->WriteException($oException);
} }
} }
return $bResult; return $bResult;
} }
} }

View file

@ -1,44 +1,44 @@
<?php <?php
class ChangePasswordCyberPanelPlugin extends \RainLoop\Plugins\AbstractPlugin class ChangePasswordCyberPanelPlugin extends \RainLoop\Plugins\AbstractPlugin
{ {
public function Init() public function Init()
{ {
$this->addHook('main.fabrica', 'MainFabrica'); $this->addHook('main.fabrica', 'MainFabrica');
} }
/** /**
* @param string $sName * @param string $sName
* @param mixed $oProvider * @param mixed $oProvider
*/ */
public function MainFabrica($sName, &$oProvider) public function MainFabrica($sName, &$oProvider)
{ {
switch ($sName) switch ($sName)
{ {
case 'change-password': case 'change-password':
include_once __DIR__.'/ChangePasswordCyberPanel.php'; include_once __DIR__.'/ChangePasswordCyberPanel.php';
$oProvider = new ChangePasswordCyberPanel(); $oProvider = new ChangePasswordCyberPanel();
$oProvider $oProvider
->SetLogger($this->Manager()->Actions()->Logger()) ->SetLogger($this->Manager()->Actions()->Logger())
->SetmHost($this->Config()->Get('plugin', 'mHost', '')) ->SetmHost($this->Config()->Get('plugin', 'mHost', ''))
->SetmUser($this->Config()->Get('plugin', 'mUser', '')) ->SetmUser($this->Config()->Get('plugin', 'mUser', ''))
->SetmPass($this->Config()->Get('plugin', 'mPass', '')) ->SetmPass($this->Config()->Get('plugin', 'mPass', ''))
; ;
break; break;
} }
} }
/** /**
* @return array * @return array
*/ */
public function configMapping() public function configMapping()
{ {
return array( return array(
\RainLoop\Plugins\Property::NewInstance('mHost')->SetLabel('MySQL Host') \RainLoop\Plugins\Property::NewInstance('mHost')->SetLabel('MySQL Host')
->SetDefaultValue('127.0.0.1'), ->SetDefaultValue('127.0.0.1'),
\RainLoop\Plugins\Property::NewInstance('mUser')->SetLabel('MySQL User'), \RainLoop\Plugins\Property::NewInstance('mUser')->SetLabel('MySQL User'),
\RainLoop\Plugins\Property::NewInstance('mPass')->SetLabel('MySQL Password') \RainLoop\Plugins\Property::NewInstance('mPass')->SetLabel('MySQL Password')
->SetType(\RainLoop\Enumerations\PluginPropertyType::PASSWORD) ->SetType(\RainLoop\Enumerations\PluginPropertyType::PASSWORD)
); );
} }
} }

View file

@ -11,7 +11,7 @@ class DirectAdminChangePasswordDriver implements \RainLoop\Providers\ChangePassw
* @var string * @var string
*/ */
private $iPort = 2222; private $iPort = 2222;
/** /**
* @var string * @var string
*/ */
@ -21,7 +21,7 @@ class DirectAdminChangePasswordDriver implements \RainLoop\Providers\ChangePassw
* @var \MailSo\Log\Logger * @var \MailSo\Log\Logger
*/ */
private $oLogger = null; private $oLogger = null;
/** /**
* @param string $sHost * @param string $sHost
* @param int $iPort * @param int $iPort
@ -97,7 +97,7 @@ class DirectAdminChangePasswordDriver implements \RainLoop\Providers\ChangePassw
$sHost = \str_replace('{user:host-smtp}', $oAccount->Domain()->OutHost(), $sHost); $sHost = \str_replace('{user:host-smtp}', $oAccount->Domain()->OutHost(), $sHost);
$sHost = \str_replace('{user:domain}', \MailSo\Base\Utils::GetDomainFromEmail($sEmail), $sHost); $sHost = \str_replace('{user:domain}', \MailSo\Base\Utils::GetDomainFromEmail($sEmail), $sHost);
$sHost = \rtrim($this->sHost, '/\\'); $sHost = \rtrim($this->sHost, '/\\');
if (!\preg_match('/^http[s]?:\/\//i', $sHost)) if (!\preg_match('/^http[s]?:\/\//i', $sHost))
{ {
$sHost = 'http://'.$sHost; $sHost = 'http://'.$sHost;

View file

@ -1,76 +1,76 @@
<?php <?php
class FroxlorchangePasswordPlugin extends \RainLoop\Plugins\AbstractPlugin class FroxlorchangePasswordPlugin extends \RainLoop\Plugins\AbstractPlugin
{ {
public function Init() public function Init()
{ {
$this->addHook('main.fabrica', 'MainFabrica'); $this->addHook('main.fabrica', 'MainFabrica');
} }
/** /**
* @return string * @return string
*/ */
public function Supported() public function Supported()
{ {
if (!extension_loaded('pdo') || !class_exists('PDO')) if (!extension_loaded('pdo') || !class_exists('PDO'))
{ {
return 'The PHP exention PDO (mysql) must be installed to use this plugin'; return 'The PHP exention PDO (mysql) must be installed to use this plugin';
} }
$aDrivers = \PDO::getAvailableDrivers(); $aDrivers = \PDO::getAvailableDrivers();
if (!is_array($aDrivers) || !in_array('mysql', $aDrivers)) if (!is_array($aDrivers) || !in_array('mysql', $aDrivers))
{ {
return 'The PHP exention PDO (mysql) must be installed to use this plugin'; return 'The PHP exention PDO (mysql) must be installed to use this plugin';
} }
return ''; return '';
} }
/** /**
* @param string $sName * @param string $sName
* @param mixed $oProvider * @param mixed $oProvider
*/ */
public function MainFabrica($sName, &$oProvider) public function MainFabrica($sName, &$oProvider)
{ {
switch ($sName) switch ($sName)
{ {
case 'change-password': case 'change-password':
$sDsn = \trim($this->Config()->Get('plugin', 'pdo_dsn', '')); $sDsn = \trim($this->Config()->Get('plugin', 'pdo_dsn', ''));
$sUser = (string) $this->Config()->Get('plugin', 'user', ''); $sUser = (string) $this->Config()->Get('plugin', 'user', '');
$sPassword = (string) $this->Config()->Get('plugin', 'password', ''); $sPassword = (string) $this->Config()->Get('plugin', 'password', '');
if (!empty($sDsn) && 0 < \strlen($sUser) && 0 < \strlen($sPassword)) if (!empty($sDsn) && 0 < \strlen($sUser) && 0 < \strlen($sPassword))
{ {
include_once __DIR__.'/FroxlorChangePasswordDriver.php'; include_once __DIR__.'/FroxlorChangePasswordDriver.php';
$oProvider = new FroxlorChangePasswordDriver(); $oProvider = new FroxlorChangePasswordDriver();
$oProvider->SetLogger($this->Manager()->Actions()->Logger()); $oProvider->SetLogger($this->Manager()->Actions()->Logger());
$oProvider->SetConfig($sDsn, $sUser, $sPassword); $oProvider->SetConfig($sDsn, $sUser, $sPassword);
$oProvider->SetAllowedEmails(\strtolower(\trim($this->Config()->Get('plugin', 'allowed_emails', '')))); $oProvider->SetAllowedEmails(\strtolower(\trim($this->Config()->Get('plugin', 'allowed_emails', ''))));
} }
break; break;
} }
} }
/** /**
* @return array * @return array
*/ */
public function configMapping() public function configMapping()
{ {
return array( return array(
\RainLoop\Plugins\Property::NewInstance('pdo_dsn')->SetLabel('Froxlor PDO dsn') \RainLoop\Plugins\Property::NewInstance('pdo_dsn')->SetLabel('Froxlor PDO dsn')
->SetDefaultValue('mysql:host=127.0.0.1;dbname=froxlor'), ->SetDefaultValue('mysql:host=127.0.0.1;dbname=froxlor'),
\RainLoop\Plugins\Property::NewInstance('user')->SetLabel('DB User') \RainLoop\Plugins\Property::NewInstance('user')->SetLabel('DB User')
->SetDefaultValue('root'), ->SetDefaultValue('root'),
\RainLoop\Plugins\Property::NewInstance('password')->SetLabel('DB Password') \RainLoop\Plugins\Property::NewInstance('password')->SetLabel('DB Password')
->SetType(\RainLoop\Enumerations\PluginPropertyType::PASSWORD) ->SetType(\RainLoop\Enumerations\PluginPropertyType::PASSWORD)
->SetDefaultValue(''), ->SetDefaultValue(''),
\RainLoop\Plugins\Property::NewInstance('allowed_emails')->SetLabel('Allowed emails') \RainLoop\Plugins\Property::NewInstance('allowed_emails')->SetLabel('Allowed emails')
->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING_TEXT) ->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING_TEXT)
->SetDescription('Allowed emails, space as delimiter, wildcard supported. Example: user1@domain1.net user2@domain1.net *@domain2.net') ->SetDescription('Allowed emails, space as delimiter, wildcard supported. Example: user1@domain1.net user2@domain1.net *@domain2.net')
->SetDefaultValue('*') ->SetDefaultValue('*')
); );
} }
} }

View file

@ -1,49 +1,49 @@
<?php <?php
class GoogleAnalyticsPlugin extends \RainLoop\Plugins\AbstractPlugin class GoogleAnalyticsPlugin extends \RainLoop\Plugins\AbstractPlugin
{ {
/** /**
* @return void * @return void
*/ */
public function Init() public function Init()
{ {
if ('' !== $this->Config()->Get('plugin', 'account', '')) if ('' !== $this->Config()->Get('plugin', 'account', ''))
{ {
$this->addJs('js/include.js'); $this->addJs('js/include.js');
} }
} }
/** /**
* @return array * @return array
*/ */
public function configMapping() public function configMapping()
{ {
$oAccount = \RainLoop\Plugins\Property::NewInstance('account')->SetLabel('Account') $oAccount = \RainLoop\Plugins\Property::NewInstance('account')->SetLabel('Account')
->SetAllowedInJs(true) ->SetAllowedInJs(true)
->SetDefaultValue('') ->SetDefaultValue('')
; ;
if (\method_exists($oAccount, 'SetPlaceholder')) if (\method_exists($oAccount, 'SetPlaceholder'))
{ {
$oAccount->SetPlaceholder('UA-XXXXXXXX-X'); $oAccount->SetPlaceholder('UA-XXXXXXXX-X');
} }
return array($oAccount, return array($oAccount,
\RainLoop\Plugins\Property::NewInstance('domain_name')->SetLabel('Domain Name') \RainLoop\Plugins\Property::NewInstance('domain_name')->SetLabel('Domain Name')
->SetAllowedInJs(true) ->SetAllowedInJs(true)
->SetDefaultValue(''), ->SetDefaultValue(''),
\RainLoop\Plugins\Property::NewInstance('universal_analytics')->SetLabel('Use Universal Analytics') \RainLoop\Plugins\Property::NewInstance('universal_analytics')->SetLabel('Use Universal Analytics')
->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL) ->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL)
->SetAllowedInJs(true) ->SetAllowedInJs(true)
->SetDefaultValue(true), ->SetDefaultValue(true),
\RainLoop\Plugins\Property::NewInstance('track_pageview')->SetLabel('Track Pageview') \RainLoop\Plugins\Property::NewInstance('track_pageview')->SetLabel('Track Pageview')
->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL) ->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL)
->SetAllowedInJs(true) ->SetAllowedInJs(true)
->SetDefaultValue(true), ->SetDefaultValue(true),
\RainLoop\Plugins\Property::NewInstance('send_events')->SetLabel('Send Events') \RainLoop\Plugins\Property::NewInstance('send_events')->SetLabel('Send Events')
->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL) ->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL)
->SetAllowedInJs(true) ->SetAllowedInJs(true)
->SetDefaultValue(false) ->SetDefaultValue(false)
); );
} }
} }

View file

@ -1,95 +1,95 @@
<?php <?php
class IspmailChangePasswordPlugin extends \RainLoop\Plugins\AbstractPlugin class IspmailChangePasswordPlugin extends \RainLoop\Plugins\AbstractPlugin
{ {
public function Init() public function Init()
{ {
$this->addHook('main.fabrica', 'MainFabrica'); $this->addHook('main.fabrica', 'MainFabrica');
} }
/** /**
* @return string * @return string
*/ */
public function Supported() public function Supported()
{ {
if (!extension_loaded('pdo') || !class_exists('PDO')) if (!extension_loaded('pdo') || !class_exists('PDO'))
{ {
return 'The PHP extension PDO (mysql) must be installed to use this plugin'; return 'The PHP extension PDO (mysql) must be installed to use this plugin';
} }
$aDrivers = \PDO::getAvailableDrivers(); $aDrivers = \PDO::getAvailableDrivers();
if (!is_array($aDrivers) || !in_array('mysql', $aDrivers)) if (!is_array($aDrivers) || !in_array('mysql', $aDrivers))
{ {
return 'The PHP extension PDO (mysql) must be installed to use this plugin'; return 'The PHP extension PDO (mysql) must be installed to use this plugin';
} }
return ''; return '';
} }
/** /**
* @param string $sName * @param string $sName
* @param mixed $oProvider * @param mixed $oProvider
*/ */
public function MainFabrica($sName, &$oProvider) public function MainFabrica($sName, &$oProvider)
{ {
switch ($sName) switch ($sName)
{ {
case 'change-password': case 'change-password':
include_once __DIR__.'/ChangePasswordISPmailDriver.php'; include_once __DIR__.'/ChangePasswordISPmailDriver.php';
$oProvider = new ChangePasswordISPmailDriver(); $oProvider = new ChangePasswordISPmailDriver();
$oProvider $oProvider
->SetHost($this->Config()->Get('plugin', 'host', '')) ->SetHost($this->Config()->Get('plugin', 'host', ''))
->SetPort((int) $this->Config()->Get('plugin', 'port', 3306)) ->SetPort((int) $this->Config()->Get('plugin', 'port', 3306))
->SetDatabase($this->Config()->Get('plugin', 'database', '')) ->SetDatabase($this->Config()->Get('plugin', 'database', ''))
->SetTable($this->Config()->Get('plugin', 'table', '')) ->SetTable($this->Config()->Get('plugin', 'table', ''))
->SetUserColumn($this->Config()->Get('plugin', 'usercol', '')) ->SetUserColumn($this->Config()->Get('plugin', 'usercol', ''))
->SetPasswordColumn($this->Config()->Get('plugin', 'passcol', '')) ->SetPasswordColumn($this->Config()->Get('plugin', 'passcol', ''))
->SetUser($this->Config()->Get('plugin', 'user', '')) ->SetUser($this->Config()->Get('plugin', 'user', ''))
->SetPassword($this->Config()->Get('plugin', 'password', '')) ->SetPassword($this->Config()->Get('plugin', 'password', ''))
->SetEncrypt($this->Config()->Get('plugin', 'encrypt', '')) ->SetEncrypt($this->Config()->Get('plugin', 'encrypt', ''))
->SetAllowedEmails(\strtolower(\trim($this->Config()->Get('plugin', 'allowed_emails', '')))) ->SetAllowedEmails(\strtolower(\trim($this->Config()->Get('plugin', 'allowed_emails', ''))))
->SetLogger($this->Manager()->Actions()->Logger()) ->SetLogger($this->Manager()->Actions()->Logger())
; ;
break; break;
} }
} }
/** /**
* @return array * @return array
*/ */
public function configMapping() public function configMapping()
{ {
return array( return array(
\RainLoop\Plugins\Property::NewInstance('host')->SetLabel('MySQL Host') \RainLoop\Plugins\Property::NewInstance('host')->SetLabel('MySQL Host')
->SetDefaultValue('127.0.0.1'), ->SetDefaultValue('127.0.0.1'),
\RainLoop\Plugins\Property::NewInstance('port')->SetLabel('MySQL Port') \RainLoop\Plugins\Property::NewInstance('port')->SetLabel('MySQL Port')
->SetType(\RainLoop\Enumerations\PluginPropertyType::INT) ->SetType(\RainLoop\Enumerations\PluginPropertyType::INT)
->SetDefaultValue(3306), ->SetDefaultValue(3306),
\RainLoop\Plugins\Property::NewInstance('database')->SetLabel('MySQL Database') \RainLoop\Plugins\Property::NewInstance('database')->SetLabel('MySQL Database')
->SetDefaultValue('mailserver'), ->SetDefaultValue('mailserver'),
\RainLoop\Plugins\Property::NewInstance('table')->SetLabel('MySQL table') \RainLoop\Plugins\Property::NewInstance('table')->SetLabel('MySQL table')
->SetDefaultValue('virtual_users'), ->SetDefaultValue('virtual_users'),
\RainLoop\Plugins\Property::NewInstance('usercol')->SetLabel('MySQL username column') \RainLoop\Plugins\Property::NewInstance('usercol')->SetLabel('MySQL username column')
->SetDefaultValue('email'), ->SetDefaultValue('email'),
\RainLoop\Plugins\Property::NewInstance('passcol')->SetLabel('MySQL password column') \RainLoop\Plugins\Property::NewInstance('passcol')->SetLabel('MySQL password column')
->SetDefaultValue('password'), ->SetDefaultValue('password'),
\RainLoop\Plugins\Property::NewInstance('user')->SetLabel('MySQL User') \RainLoop\Plugins\Property::NewInstance('user')->SetLabel('MySQL User')
->SetDefaultValue('mailuser'), ->SetDefaultValue('mailuser'),
\RainLoop\Plugins\Property::NewInstance('password')->SetLabel('MySQL Password') \RainLoop\Plugins\Property::NewInstance('password')->SetLabel('MySQL Password')
->SetType(\RainLoop\Enumerations\PluginPropertyType::PASSWORD) ->SetType(\RainLoop\Enumerations\PluginPropertyType::PASSWORD)
->SetDefaultValue(''), ->SetDefaultValue(''),
\RainLoop\Plugins\Property::NewInstance('encrypt')->SetLabel('Encrypt') \RainLoop\Plugins\Property::NewInstance('encrypt')->SetLabel('Encrypt')
->SetType(\RainLoop\Enumerations\PluginPropertyType::SELECTION) ->SetType(\RainLoop\Enumerations\PluginPropertyType::SELECTION)
->SetDefaultValue(array('PLAIN-MD5', 'SHA256-CRYPT')) ->SetDefaultValue(array('PLAIN-MD5', 'SHA256-CRYPT'))
->SetDescription('In what way do you want the passwords to be crypted ?'), ->SetDescription('In what way do you want the passwords to be crypted ?'),
\RainLoop\Plugins\Property::NewInstance('allowed_emails')->SetLabel('Allowed emails') \RainLoop\Plugins\Property::NewInstance('allowed_emails')->SetLabel('Allowed emails')
->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING_TEXT) ->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING_TEXT)
->SetDescription('Allowed emails, space as delimiter, wildcard supported. Example: user1@domain1.net user2@domain1.net *@domain2.net') ->SetDescription('Allowed emails, space as delimiter, wildcard supported. Example: user1@domain1.net user2@domain1.net *@domain2.net')
->SetDefaultValue('*') ->SetDefaultValue('*')
); );
} }
} }

View file

@ -1,162 +1,162 @@
<?php <?php
class MailcowChangePasswordDriver implements \RainLoop\Providers\ChangePassword\ChangePasswordInterface class MailcowChangePasswordDriver implements \RainLoop\Providers\ChangePassword\ChangePasswordInterface
{ {
/** /**
* @var string * @var string
*/ */
private $sDsn = ''; private $sDsn = '';
/** /**
* @var string * @var string
*/ */
private $sUser = ''; private $sUser = '';
/** /**
* @var string * @var string
*/ */
private $sPassword = ''; private $sPassword = '';
/** /**
* @var string * @var string
*/ */
private $sAllowedEmails = ''; private $sAllowedEmails = '';
/** /**
* @var \MailSo\Log\Logger * @var \MailSo\Log\Logger
*/ */
private $oLogger = null; private $oLogger = null;
/** /**
* @param string $sDsn * @param string $sDsn
* @param string $sUser * @param string $sUser
* @param string $sPassword * @param string $sPassword
* *
* @return \IspConfigChangePasswordDriver * @return \IspConfigChangePasswordDriver
*/ */
public function SetConfig($sDsn, $sUser, $sPassword) public function SetConfig($sDsn, $sUser, $sPassword)
{ {
$this->sDsn = $sDsn; $this->sDsn = $sDsn;
$this->sUser = $sUser; $this->sUser = $sUser;
$this->sPassword = $sPassword; $this->sPassword = $sPassword;
return $this; return $this;
} }
/** /**
* @param string $sAllowedEmails * @param string $sAllowedEmails
* *
* @return \IspConfigChangePasswordDriver * @return \IspConfigChangePasswordDriver
*/ */
public function SetAllowedEmails($sAllowedEmails) public function SetAllowedEmails($sAllowedEmails)
{ {
$this->sAllowedEmails = $sAllowedEmails; $this->sAllowedEmails = $sAllowedEmails;
return $this; return $this;
} }
/** /**
* @param \MailSo\Log\Logger $oLogger * @param \MailSo\Log\Logger $oLogger
* *
* @return \IspConfigChangePasswordDriver * @return \IspConfigChangePasswordDriver
*/ */
public function SetLogger($oLogger) public function SetLogger($oLogger)
{ {
if ($oLogger instanceof \MailSo\Log\Logger) if ($oLogger instanceof \MailSo\Log\Logger)
{ {
$this->oLogger = $oLogger; $this->oLogger = $oLogger;
} }
return $this; return $this;
} }
/** /**
* @param \RainLoop\Account $oAccount * @param \RainLoop\Account $oAccount
* *
* @return bool * @return bool
*/ */
public function PasswordChangePossibility($oAccount) public function PasswordChangePossibility($oAccount)
{ {
return $oAccount && $oAccount->Email() && return $oAccount && $oAccount->Email() &&
\RainLoop\Plugins\Helper::ValidateWildcardValues($oAccount->Email(), $this->sAllowedEmails); \RainLoop\Plugins\Helper::ValidateWildcardValues($oAccount->Email(), $this->sAllowedEmails);
} }
/** /**
* @param \RainLoop\Account $oAccount * @param \RainLoop\Account $oAccount
* @param string $sPrevPassword * @param string $sPrevPassword
* @param string $sNewPassword * @param string $sNewPassword
* *
* @return bool * @return bool
*/ */
public function ChangePassword(\RainLoop\Account $oAccount, $sPrevPassword, $sNewPassword) public function ChangePassword(\RainLoop\Account $oAccount, $sPrevPassword, $sNewPassword)
{ {
if ($this->oLogger) if ($this->oLogger)
{ {
$this->oLogger->Write('Mailcow: Try to change password for '.$oAccount->Email()); $this->oLogger->Write('Mailcow: Try to change password for '.$oAccount->Email());
} }
$bResult = false; $bResult = false;
if (!empty($this->sDsn) && 0 < \strlen($this->sUser) && 0 < \strlen($this->sPassword) && $oAccount) if (!empty($this->sDsn) && 0 < \strlen($this->sUser) && 0 < \strlen($this->sPassword) && $oAccount)
{ {
try try
{ {
$oPdo = new \PDO($this->sDsn, $this->sUser, $this->sPassword); $oPdo = new \PDO($this->sDsn, $this->sUser, $this->sPassword);
$oPdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); $oPdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$oStmt = $oPdo->prepare('SELECT password, username FROM mailbox WHERE username = ? LIMIT 1'); $oStmt = $oPdo->prepare('SELECT password, username FROM mailbox WHERE username = ? LIMIT 1');
if ($oStmt->execute(array($oAccount->IncLogin()))) if ($oStmt->execute(array($oAccount->IncLogin())))
{ {
$aFetchResult = $oStmt->fetchAll(\PDO::FETCH_ASSOC); $aFetchResult = $oStmt->fetchAll(\PDO::FETCH_ASSOC);
if (\is_array($aFetchResult) && isset($aFetchResult[0]['password'], $aFetchResult[0]['username'])) if (\is_array($aFetchResult) && isset($aFetchResult[0]['password'], $aFetchResult[0]['username']))
{ {
$sDbPassword = $aFetchResult[0]['password']; $sDbPassword = $aFetchResult[0]['password'];
if (\substr($sDbPassword, 0, 14) === '{SHA512-CRYPT}') { if (\substr($sDbPassword, 0, 14) === '{SHA512-CRYPT}') {
$sDbSalt = \substr($sDbPassword, 17, 16); $sDbSalt = \substr($sDbPassword, 17, 16);
} else { } else {
$sDbSalt = \substr($sDbPassword, 3, 16); $sDbSalt = \substr($sDbPassword, 3, 16);
} }
if ('{SHA512-CRYPT}'.\crypt($sPrevPassword, '$6$'.$sDbSalt) === $sDbPassword) if ('{SHA512-CRYPT}'.\crypt($sPrevPassword, '$6$'.$sDbSalt) === $sDbPassword)
{ {
$oStmt = $oPdo->prepare('UPDATE mailbox SET password = ? WHERE username = ?'); $oStmt = $oPdo->prepare('UPDATE mailbox SET password = ? WHERE username = ?');
if ($oStmt->execute(array($this->cryptPassword($sNewPassword), $aFetchResult[0]['username']))) { if ($oStmt->execute(array($this->cryptPassword($sNewPassword), $aFetchResult[0]['username']))) {
$oStmt = $oPdo ->prepare('UPDATE users SET digesta1=MD5(CONCAT(?, ":SabreDAV:", ?)) WHERE username=?'); $oStmt = $oPdo ->prepare('UPDATE users SET digesta1=MD5(CONCAT(?, ":SabreDAV:", ?)) WHERE username=?');
if ($oStmt->execute(array($aFetchResult[0]['username'],$sNewPassword,$aFetchResult[0]['username']))) { if ($oStmt->execute(array($aFetchResult[0]['username'],$sNewPassword,$aFetchResult[0]['username']))) {
//the MailCow & SabreDav have been updated, now update the doveadm password //the MailCow & SabreDav have been updated, now update the doveadm password
exec("/usr/bin/doveadm pw -s SHA512-CRYPT -p $sNewPassword", $hash, $return); exec("/usr/bin/doveadm pw -s SHA512-CRYPT -p $sNewPassword", $hash, $return);
$bResult = true; $bResult = true;
} }
} }
} }
} }
} }
} }
catch (\Exception $oException) catch (\Exception $oException)
{ {
if ($this->oLogger) if ($this->oLogger)
{ {
$this->oLogger->WriteException($oException); $this->oLogger->WriteException($oException);
} }
} }
} }
return $bResult; return $bResult;
} }
/** /**
* @param string $sPassword * @param string $sPassword
* @return string * @return string
*/ */
private function cryptPassword($sPassword) private function cryptPassword($sPassword)
{ {
$sSalt = ''; $sSalt = '';
$sBase64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; $sBase64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
for ($iIndex = 0; $iIndex < 16; $iIndex++) for ($iIndex = 0; $iIndex < 16; $iIndex++)
{ {
$sSalt .= $sBase64[\rand(0, 63)]; $sSalt .= $sBase64[\rand(0, 63)];
} }
$crypted = \crypt($sPassword, '$6$'.$sSalt); $crypted = \crypt($sPassword, '$6$'.$sSalt);
return '{SHA512-CRYPT}'.$crypted; return '{SHA512-CRYPT}'.$crypted;
} }
} }

View file

@ -1,76 +1,76 @@
<?php <?php
class MailcowChangePasswordPlugin extends \RainLoop\Plugins\AbstractPlugin class MailcowChangePasswordPlugin extends \RainLoop\Plugins\AbstractPlugin
{ {
public function Init() public function Init()
{ {
$this->addHook('main.fabrica', 'MainFabrica'); $this->addHook('main.fabrica', 'MainFabrica');
} }
/** /**
* @return string * @return string
*/ */
public function Supported() public function Supported()
{ {
if (!extension_loaded('pdo') || !class_exists('PDO')) if (!extension_loaded('pdo') || !class_exists('PDO'))
{ {
return 'The PHP extension PDO (mysql) must be installed to use this plugin'; return 'The PHP extension PDO (mysql) must be installed to use this plugin';
} }
$aDrivers = \PDO::getAvailableDrivers(); $aDrivers = \PDO::getAvailableDrivers();
if (!is_array($aDrivers) || !in_array('mysql', $aDrivers)) if (!is_array($aDrivers) || !in_array('mysql', $aDrivers))
{ {
return 'The PHP extension PDO (mysql) must be installed to use this plugin'; return 'The PHP extension PDO (mysql) must be installed to use this plugin';
} }
return ''; return '';
} }
/** /**
* @param string $sName * @param string $sName
* @param mixed $oProvider * @param mixed $oProvider
*/ */
public function MainFabrica($sName, &$oProvider) public function MainFabrica($sName, &$oProvider)
{ {
switch ($sName) switch ($sName)
{ {
case 'change-password': case 'change-password':
$sDsn = \trim($this->Config()->Get('plugin', 'pdo_dsn', '')); $sDsn = \trim($this->Config()->Get('plugin', 'pdo_dsn', ''));
$sUser = (string) $this->Config()->Get('plugin', 'user', ''); $sUser = (string) $this->Config()->Get('plugin', 'user', '');
$sPassword = (string) $this->Config()->Get('plugin', 'password', ''); $sPassword = (string) $this->Config()->Get('plugin', 'password', '');
if (!empty($sDsn) && 0 < \strlen($sUser) && 0 < \strlen($sPassword)) if (!empty($sDsn) && 0 < \strlen($sUser) && 0 < \strlen($sPassword))
{ {
include_once __DIR__.'/MailcowChangePasswordDriver.php'; include_once __DIR__.'/MailcowChangePasswordDriver.php';
$oProvider = new MailcowChangePasswordDriver(); $oProvider = new MailcowChangePasswordDriver();
$oProvider->SetLogger($this->Manager()->Actions()->Logger()); $oProvider->SetLogger($this->Manager()->Actions()->Logger());
$oProvider->SetConfig($sDsn, $sUser, $sPassword); $oProvider->SetConfig($sDsn, $sUser, $sPassword);
$oProvider->SetAllowedEmails(\strtolower(\trim($this->Config()->Get('plugin', 'allowed_emails', '')))); $oProvider->SetAllowedEmails(\strtolower(\trim($this->Config()->Get('plugin', 'allowed_emails', ''))));
} }
break; break;
} }
} }
/** /**
* @return array * @return array
*/ */
public function configMapping() public function configMapping()
{ {
return array( return array(
\RainLoop\Plugins\Property::NewInstance('pdo_dsn')->SetLabel('Mailcow PDO dsn') \RainLoop\Plugins\Property::NewInstance('pdo_dsn')->SetLabel('Mailcow PDO dsn')
->SetDefaultValue('mysql:host=127.0.0.1;dbname=mailcow'), ->SetDefaultValue('mysql:host=127.0.0.1;dbname=mailcow'),
\RainLoop\Plugins\Property::NewInstance('user')->SetLabel('DB User') \RainLoop\Plugins\Property::NewInstance('user')->SetLabel('DB User')
->SetDefaultValue('mailcow'), ->SetDefaultValue('mailcow'),
\RainLoop\Plugins\Property::NewInstance('password')->SetLabel('DB Password') \RainLoop\Plugins\Property::NewInstance('password')->SetLabel('DB Password')
->SetType(\RainLoop\Enumerations\PluginPropertyType::PASSWORD) ->SetType(\RainLoop\Enumerations\PluginPropertyType::PASSWORD)
->SetDefaultValue(''), ->SetDefaultValue(''),
\RainLoop\Plugins\Property::NewInstance('allowed_emails')->SetLabel('Allowed emails') \RainLoop\Plugins\Property::NewInstance('allowed_emails')->SetLabel('Allowed emails')
->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING_TEXT) ->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING_TEXT)
->SetDescription('Allowed emails, space as delimiter, wildcard supported. Example: user1@domain1.net user2@domain1.net *@domain2.net') ->SetDescription('Allowed emails, space as delimiter, wildcard supported. Example: user1@domain1.net user2@domain1.net *@domain2.net')
->SetDefaultValue('*') ->SetDefaultValue('*')
); );
} }
} }

View file

@ -289,7 +289,7 @@ class ChangePasswordPostfixAdminDriver implements \RainLoop\Providers\ChangePass
if (function_exists('random_bytes')) { if (function_exists('random_bytes')) {
$sSalt = substr(base64_encode(random_bytes(32)), 0, 16); $sSalt = substr(base64_encode(random_bytes(32)), 0, 16);
} else { } else {
$sSalt = substr(str_shuffle('./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'), 0, 16); $sSalt = substr(str_shuffle('./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'), 0, 16);
} }
switch (strtolower($this->sEncrypt)) switch (strtolower($this->sEncrypt))
{ {

View file

@ -1,100 +1,100 @@
<?php <?php
class PostfixadminChangePasswordPlugin extends \RainLoop\Plugins\AbstractPlugin class PostfixadminChangePasswordPlugin extends \RainLoop\Plugins\AbstractPlugin
{ {
public function Init() public function Init()
{ {
$this->addHook('main.fabrica', 'MainFabrica'); $this->addHook('main.fabrica', 'MainFabrica');
} }
/** /**
* @return string * @return string
*/ */
public function Supported() public function Supported()
{ {
if (!extension_loaded('pdo') || !class_exists('PDO')) if (!extension_loaded('pdo') || !class_exists('PDO'))
{ {
return 'The PHP extension PDO must be installed to use this plugin'; return 'The PHP extension PDO must be installed to use this plugin';
} }
$aDrivers = \PDO::getAvailableDrivers(); $aDrivers = \PDO::getAvailableDrivers();
if (!is_array($aDrivers) || (!in_array('mysql', $aDrivers) && !in_array('pgsql', $aDrivers))) if (!is_array($aDrivers) || (!in_array('mysql', $aDrivers) && !in_array('pgsql', $aDrivers)))
{ {
return 'The PHP extension PDO (mysql or pgsql) must be installed to use this plugin'; return 'The PHP extension PDO (mysql or pgsql) must be installed to use this plugin';
} }
return ''; return '';
} }
/** /**
* @param string $sName * @param string $sName
* @param mixed $oProvider * @param mixed $oProvider
*/ */
public function MainFabrica($sName, &$oProvider) public function MainFabrica($sName, &$oProvider)
{ {
switch ($sName) switch ($sName)
{ {
case 'change-password': case 'change-password':
include_once __DIR__.'/ChangePasswordPostfixAdminDriver.php'; include_once __DIR__.'/ChangePasswordPostfixAdminDriver.php';
$oProvider = new ChangePasswordPostfixAdminDriver(); $oProvider = new ChangePasswordPostfixAdminDriver();
$oProvider $oProvider
->SetEngine($this->Config()->Get('plugin', 'engine','')) ->SetEngine($this->Config()->Get('plugin', 'engine',''))
->SetHost($this->Config()->Get('plugin', 'host', '')) ->SetHost($this->Config()->Get('plugin', 'host', ''))
->SetPort((int) $this->Config()->Get('plugin', 'port', 3306)) ->SetPort((int) $this->Config()->Get('plugin', 'port', 3306))
->SetDatabase($this->Config()->Get('plugin', 'database', '')) ->SetDatabase($this->Config()->Get('plugin', 'database', ''))
->SetTable($this->Config()->Get('plugin', 'table', '')) ->SetTable($this->Config()->Get('plugin', 'table', ''))
->SetUserColumn($this->Config()->Get('plugin', 'usercol', '')) ->SetUserColumn($this->Config()->Get('plugin', 'usercol', ''))
->SetPasswordColumn($this->Config()->Get('plugin', 'passcol', '')) ->SetPasswordColumn($this->Config()->Get('plugin', 'passcol', ''))
->SetUser($this->Config()->Get('plugin', 'user', '')) ->SetUser($this->Config()->Get('plugin', 'user', ''))
->SetPassword($this->Config()->Get('plugin', 'password', '')) ->SetPassword($this->Config()->Get('plugin', 'password', ''))
->SetEncrypt($this->Config()->Get('plugin', 'encrypt', '')) ->SetEncrypt($this->Config()->Get('plugin', 'encrypt', ''))
->SetAllowedEmails(\strtolower(\trim($this->Config()->Get('plugin', 'allowed_emails', '')))) ->SetAllowedEmails(\strtolower(\trim($this->Config()->Get('plugin', 'allowed_emails', ''))))
->SetLogger($this->Manager()->Actions()->Logger()) ->SetLogger($this->Manager()->Actions()->Logger())
; ;
break; break;
} }
} }
/** /**
* @return array * @return array
*/ */
public function configMapping() public function configMapping()
{ {
return array( return array(
\RainLoop\Plugins\Property::NewInstance('engine')->SetLabel('Engine') \RainLoop\Plugins\Property::NewInstance('engine')->SetLabel('Engine')
->SetType(\RainLoop\Enumerations\PluginPropertyType::SELECTION) ->SetType(\RainLoop\Enumerations\PluginPropertyType::SELECTION)
->SetDefaultValue(array('MySQL', 'PostgreSQL')) ->SetDefaultValue(array('MySQL', 'PostgreSQL'))
->SetDescription('Database Engine'), ->SetDescription('Database Engine'),
\RainLoop\Plugins\Property::NewInstance('host')->SetLabel('Host') \RainLoop\Plugins\Property::NewInstance('host')->SetLabel('Host')
->SetDefaultValue('127.0.0.1'), ->SetDefaultValue('127.0.0.1'),
\RainLoop\Plugins\Property::NewInstance('port')->SetLabel('Port') \RainLoop\Plugins\Property::NewInstance('port')->SetLabel('Port')
->SetType(\RainLoop\Enumerations\PluginPropertyType::INT) ->SetType(\RainLoop\Enumerations\PluginPropertyType::INT)
->SetDefaultValue(3306), ->SetDefaultValue(3306),
\RainLoop\Plugins\Property::NewInstance('database')->SetLabel('Database') \RainLoop\Plugins\Property::NewInstance('database')->SetLabel('Database')
->SetDefaultValue('postfixadmin'), ->SetDefaultValue('postfixadmin'),
\RainLoop\Plugins\Property::NewInstance('table')->SetLabel('table') \RainLoop\Plugins\Property::NewInstance('table')->SetLabel('table')
->SetDefaultValue('mailbox'), ->SetDefaultValue('mailbox'),
\RainLoop\Plugins\Property::NewInstance('usercol')->SetLabel('username column') \RainLoop\Plugins\Property::NewInstance('usercol')->SetLabel('username column')
->SetDefaultValue('username'), ->SetDefaultValue('username'),
\RainLoop\Plugins\Property::NewInstance('passcol')->SetLabel('password column') \RainLoop\Plugins\Property::NewInstance('passcol')->SetLabel('password column')
->SetDefaultValue('password'), ->SetDefaultValue('password'),
\RainLoop\Plugins\Property::NewInstance('user')->SetLabel('User') \RainLoop\Plugins\Property::NewInstance('user')->SetLabel('User')
->SetDefaultValue('postfixadmin'), ->SetDefaultValue('postfixadmin'),
\RainLoop\Plugins\Property::NewInstance('password')->SetLabel('Password') \RainLoop\Plugins\Property::NewInstance('password')->SetLabel('Password')
->SetType(\RainLoop\Enumerations\PluginPropertyType::PASSWORD) ->SetType(\RainLoop\Enumerations\PluginPropertyType::PASSWORD)
->SetDefaultValue(''), ->SetDefaultValue(''),
\RainLoop\Plugins\Property::NewInstance('encrypt')->SetLabel('Encrypt') \RainLoop\Plugins\Property::NewInstance('encrypt')->SetLabel('Encrypt')
->SetType(\RainLoop\Enumerations\PluginPropertyType::SELECTION) ->SetType(\RainLoop\Enumerations\PluginPropertyType::SELECTION)
->SetDefaultValue(array('md5crypt', 'md5', 'system', 'cleartext', 'mysql_encrypt', 'SHA256-CRYPT', 'SHA512-CRYPT')) ->SetDefaultValue(array('md5crypt', 'md5', 'system', 'cleartext', 'mysql_encrypt', 'SHA256-CRYPT', 'SHA512-CRYPT'))
->SetDescription('In what way do you want the passwords to be crypted ?'), ->SetDescription('In what way do you want the passwords to be crypted ?'),
\RainLoop\Plugins\Property::NewInstance('allowed_emails')->SetLabel('Allowed emails') \RainLoop\Plugins\Property::NewInstance('allowed_emails')->SetLabel('Allowed emails')
->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING_TEXT) ->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING_TEXT)
->SetDescription('Allowed emails, space as delimiter, wildcard supported. Example: user1@domain1.net user2@domain1.net *@domain2.net') ->SetDescription('Allowed emails, space as delimiter, wildcard supported. Example: user1@domain1.net user2@domain1.net *@domain2.net')
->SetDefaultValue('*') ->SetDefaultValue('*')
); );
} }
} }

View file

@ -52,7 +52,7 @@ function md5crypt($pw, $salt = "", $magic = "")
{ {
$ctx .= $pw[0]; $ctx .= $pw[0];
} }
$i = $i >> 1; $i = $i >> 1;
} }

View file

@ -1,151 +1,151 @@
<?php <?php
class RecaptchaPlugin extends \RainLoop\Plugins\AbstractPlugin class RecaptchaPlugin extends \RainLoop\Plugins\AbstractPlugin
{ {
/** /**
* @return void * @return void
*/ */
public function Init() public function Init()
{ {
$this->UseLangs(true); $this->UseLangs(true);
$this->addJs('js/recaptcha.js'); $this->addJs('js/recaptcha.js');
$this->addHook('ajax.action-pre-call', 'AjaxActionPreCall'); $this->addHook('ajax.action-pre-call', 'AjaxActionPreCall');
$this->addHook('filter.ajax-response', 'FilterAjaxResponse'); $this->addHook('filter.ajax-response', 'FilterAjaxResponse');
} }
/** /**
* @return array * @return array
*/ */
public function configMapping() public function configMapping()
{ {
return array( return array(
\RainLoop\Plugins\Property::NewInstance('public_key')->SetLabel('Site key') \RainLoop\Plugins\Property::NewInstance('public_key')->SetLabel('Site key')
->SetAllowedInJs(true) ->SetAllowedInJs(true)
->SetDefaultValue(''), ->SetDefaultValue(''),
\RainLoop\Plugins\Property::NewInstance('private_key')->SetLabel('Secret key') \RainLoop\Plugins\Property::NewInstance('private_key')->SetLabel('Secret key')
->SetDefaultValue(''), ->SetDefaultValue(''),
\RainLoop\Plugins\Property::NewInstance('theme')->SetLabel('Theme') \RainLoop\Plugins\Property::NewInstance('theme')->SetLabel('Theme')
->SetAllowedInJs(true) ->SetAllowedInJs(true)
->SetType(\RainLoop\Enumerations\PluginPropertyType::SELECTION) ->SetType(\RainLoop\Enumerations\PluginPropertyType::SELECTION)
->SetDefaultValue(array('light', 'dark')), ->SetDefaultValue(array('light', 'dark')),
\RainLoop\Plugins\Property::NewInstance('error_limit')->SetLabel('Limit') \RainLoop\Plugins\Property::NewInstance('error_limit')->SetLabel('Limit')
->SetType(\RainLoop\Enumerations\PluginPropertyType::SELECTION) ->SetType(\RainLoop\Enumerations\PluginPropertyType::SELECTION)
->SetDefaultValue(array(0, 1, 2, 3, 4, 5)) ->SetDefaultValue(array(0, 1, 2, 3, 4, 5))
->SetDescription('') ->SetDescription('')
); );
} }
/** /**
* @return string * @return string
*/ */
private function getCaptchaCacherKey() private function getCaptchaCacherKey()
{ {
return 'CaptchaNew/Login/'.\RainLoop\Utils::GetConnectionToken(); return 'CaptchaNew/Login/'.\RainLoop\Utils::GetConnectionToken();
} }
/** /**
* @return int * @return int
*/ */
private function getLimit() private function getLimit()
{ {
$iConfigLimit = $this->Config()->Get('plugin', 'error_limit', 0); $iConfigLimit = $this->Config()->Get('plugin', 'error_limit', 0);
if (0 < $iConfigLimit) if (0 < $iConfigLimit)
{ {
$oCacher = $this->Manager()->Actions()->Cacher(); $oCacher = $this->Manager()->Actions()->Cacher();
$sLimit = $oCacher && $oCacher->IsInited() ? $oCacher->Get($this->getCaptchaCacherKey()) : '0'; $sLimit = $oCacher && $oCacher->IsInited() ? $oCacher->Get($this->getCaptchaCacherKey()) : '0';
if (0 < \strlen($sLimit) && \is_numeric($sLimit)) if (0 < \strlen($sLimit) && \is_numeric($sLimit))
{ {
$iConfigLimit -= (int) $sLimit; $iConfigLimit -= (int) $sLimit;
} }
} }
return $iConfigLimit; return $iConfigLimit;
} }
/** /**
* @return void * @return void
*/ */
public function FilterAppDataPluginSection($bAdmin, $bAuth, &$aData) public function FilterAppDataPluginSection($bAdmin, $bAuth, &$aData)
{ {
if (!$bAdmin && !$bAuth && \is_array($aData)) if (!$bAdmin && !$bAuth && \is_array($aData))
{ {
$aData['show_captcha_on_login'] = 1 > $this->getLimit(); $aData['show_captcha_on_login'] = 1 > $this->getLimit();
} }
} }
/** /**
* @param string $sAction * @param string $sAction
*/ */
public function AjaxActionPreCall($sAction) public function AjaxActionPreCall($sAction)
{ {
if ('Login' === $sAction && 0 >= $this->getLimit()) if ('Login' === $sAction && 0 >= $this->getLimit())
{ {
$bResult = false; $bResult = false;
$sResult = $this->Manager()->Actions()->Http()->SendPostRequest( $sResult = $this->Manager()->Actions()->Http()->SendPostRequest(
'https://www.google.com/recaptcha/api/siteverify', 'https://www.google.com/recaptcha/api/siteverify',
array( array(
'secret' => $this->Config()->Get('plugin', 'private_key', ''), 'secret' => $this->Config()->Get('plugin', 'private_key', ''),
'response' => $this->Manager()->Actions()->GetActionParam('RecaptchaResponse', '') 'response' => $this->Manager()->Actions()->GetActionParam('RecaptchaResponse', '')
) )
); );
if ($sResult) if ($sResult)
{ {
$aResp = @\json_decode($sResult, true); $aResp = @\json_decode($sResult, true);
if (\is_array($aResp) && isset($aResp['success']) && $aResp['success']) if (\is_array($aResp) && isset($aResp['success']) && $aResp['success'])
{ {
$bResult = true; $bResult = true;
} }
} }
if (!$bResult) if (!$bResult)
{ {
$this->Manager()->Actions()->Logger()->Write('RecaptchaResponse:'.$sResult); $this->Manager()->Actions()->Logger()->Write('RecaptchaResponse:'.$sResult);
throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CaptchaError); throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CaptchaError);
} }
} }
} }
/** /**
* @param string $sAction * @param string $sAction
* @param array $aResponseItem * @param array $aResponseItem
*/ */
public function FilterAjaxResponse($sAction, &$aResponseItem) public function FilterAjaxResponse($sAction, &$aResponseItem)
{ {
if ('Login' === $sAction && $aResponseItem && isset($aResponseItem['Result'])) if ('Login' === $sAction && $aResponseItem && isset($aResponseItem['Result']))
{ {
$oCacher = $this->Manager()->Actions()->Cacher(); $oCacher = $this->Manager()->Actions()->Cacher();
$iConfigLimit = (int) $this->Config()->Get('plugin', 'error_limit', 0); $iConfigLimit = (int) $this->Config()->Get('plugin', 'error_limit', 0);
$sKey = $this->getCaptchaCacherKey(); $sKey = $this->getCaptchaCacherKey();
if (0 < $iConfigLimit && $oCacher && $oCacher->IsInited()) if (0 < $iConfigLimit && $oCacher && $oCacher->IsInited())
{ {
if (false === $aResponseItem['Result']) if (false === $aResponseItem['Result'])
{ {
$iLimit = 0; $iLimit = 0;
$sLimut = $oCacher->Get($sKey); $sLimut = $oCacher->Get($sKey);
if (0 < \strlen($sLimut) && \is_numeric($sLimut)) if (0 < \strlen($sLimut) && \is_numeric($sLimut))
{ {
$iLimit = (int) $sLimut; $iLimit = (int) $sLimut;
} }
$oCacher->Set($sKey, ++$iLimit); $oCacher->Set($sKey, ++$iLimit);
if ($iConfigLimit <= $iLimit) if ($iConfigLimit <= $iLimit)
{ {
$aResponseItem['Captcha'] = true; $aResponseItem['Captcha'] = true;
} }
} }
else else
{ {
$oCacher->Delete($sKey); $oCacher->Delete($sKey);
} }
} }
} }
} }
} }

View file

@ -1,95 +1,95 @@
(function ($, window) { (function ($, window) {
$(function () { $(function () {
var var
nId = null, nId = null,
bStarted = false bStarted = false
; ;
function ShowRecaptcha() function ShowRecaptcha()
{ {
if (window.grecaptcha && window.rl) if (window.grecaptcha && window.rl)
{ {
if (null === nId) if (null === nId)
{ {
var var
oEl = null, oEl = null,
oLink = $('.plugin-mark-Login-BottomControlGroup') oLink = $('.plugin-mark-Login-BottomControlGroup')
; ;
if (oLink && oLink[0]) if (oLink && oLink[0])
{ {
oEl = $('<div class="controls"></div>'); oEl = $('<div class="controls"></div>');
$(oLink[0]).after(oEl); $(oLink[0]).after(oEl);
nId = window.grecaptcha.render(oEl[0], { nId = window.grecaptcha.render(oEl[0], {
'sitekey': window.rl.pluginSettingsGet('recaptcha', 'public_key'), 'sitekey': window.rl.pluginSettingsGet('recaptcha', 'public_key'),
'theme': window.rl.pluginSettingsGet('recaptcha', 'theme') 'theme': window.rl.pluginSettingsGet('recaptcha', 'theme')
}); });
} }
} }
} }
} }
window.__globalShowRecaptcha = ShowRecaptcha; window.__globalShowRecaptcha = ShowRecaptcha;
function StartRecaptcha() function StartRecaptcha()
{ {
if (!window.grecaptcha && window.rl) if (!window.grecaptcha && window.rl)
{ {
$.getScript('https://www.google.com/recaptcha/api.js?onload=__globalShowRecaptcha&render=explicit&hl=' + window.rl.settingsGet('Language')); $.getScript('https://www.google.com/recaptcha/api.js?onload=__globalShowRecaptcha&render=explicit&hl=' + window.rl.settingsGet('Language'));
} }
else else
{ {
ShowRecaptcha(); ShowRecaptcha();
} }
} }
if (window.rl) if (window.rl)
{ {
window.rl.addHook('user-login-submit', function (fSubmitResult) { window.rl.addHook('user-login-submit', function (fSubmitResult) {
if (null !== nId && !window.grecaptcha.getResponse(nId)) if (null !== nId && !window.grecaptcha.getResponse(nId))
{ {
fSubmitResult(105); fSubmitResult(105);
} }
}); });
window.rl.addHook('view-model-on-show', function (sName, oViewModel) { window.rl.addHook('view-model-on-show', function (sName, oViewModel) {
if (!bStarted && oViewModel && if (!bStarted && oViewModel &&
('View:RainLoop:Login' === sName || 'View/App/Login' === sName || 'LoginViewModel' === sName || 'LoginAppView' === sName) && ('View:RainLoop:Login' === sName || 'View/App/Login' === sName || 'LoginViewModel' === sName || 'LoginAppView' === sName) &&
window.rl.pluginSettingsGet('recaptcha', 'show_captcha_on_login')) window.rl.pluginSettingsGet('recaptcha', 'show_captcha_on_login'))
{ {
bStarted = true; bStarted = true;
StartRecaptcha(); StartRecaptcha();
} }
}); });
window.rl.addHook('ajax-default-request', function (sAction, oParameters) { window.rl.addHook('ajax-default-request', function (sAction, oParameters) {
if ('Login' === sAction && oParameters && null !== nId && window.grecaptcha) if ('Login' === sAction && oParameters && null !== nId && window.grecaptcha)
{ {
oParameters['RecaptchaResponse'] = window.grecaptcha.getResponse(nId); oParameters['RecaptchaResponse'] = window.grecaptcha.getResponse(nId);
} }
}); });
window.rl.addHook('ajax-default-response', function (sAction, oData, sType) { window.rl.addHook('ajax-default-response', function (sAction, oData, sType) {
if ('Login' === sAction) if ('Login' === sAction)
{ {
if (!oData || 'success' !== sType || !oData['Result']) if (!oData || 'success' !== sType || !oData['Result'])
{ {
if (null !== nId && window.grecaptcha) if (null !== nId && window.grecaptcha)
{ {
window.grecaptcha.reset(nId); window.grecaptcha.reset(nId);
} }
else if (oData && oData['Captcha']) else if (oData && oData['Captcha'])
{ {
StartRecaptcha(); StartRecaptcha();
} }
} }
} }
}); });
} }
}); });
}($, window)); }($, window));

View file

@ -1,275 +1,275 @@
/* Snowfall pure js /* Snowfall pure js
==================================================================== ====================================================================
LICENSE LICENSE
==================================================================== ====================================================================
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
==================================================================== ====================================================================
1.0 1.0
Wanted to rewrite my snow plugin to use pure JS so you werent necessarily tied to using a framework. Wanted to rewrite my snow plugin to use pure JS so you werent necessarily tied to using a framework.
Does not include a selector engine or anything, just pass elements to it using standard JS selectors. Does not include a selector engine or anything, just pass elements to it using standard JS selectors.
Does not clear snow currently. Collection portion removed just for ease of testing will add back in next version Does not clear snow currently. Collection portion removed just for ease of testing will add back in next version
Theres a few ways to call the snow you could do it the following way by directly passing the selector, Theres a few ways to call the snow you could do it the following way by directly passing the selector,
snowFall.snow(document.getElementsByTagName("body"), {options}); snowFall.snow(document.getElementsByTagName("body"), {options});
or you could save the selector results to a variable, and then call it or you could save the selector results to a variable, and then call it
var elements = document.getElementsByClassName('yourclass'); var elements = document.getElementsByClassName('yourclass');
snowFall.snow(elements, {options}); snowFall.snow(elements, {options});
Options are all the same as the plugin except clear, and collection Options are all the same as the plugin except clear, and collection
values for snow options are values for snow options are
flakeCount, flakeCount,
flakeColor, flakeColor,
flakeIndex, flakeIndex,
minSize, minSize,
maxSize, maxSize,
minSpeed, minSpeed,
maxSpeed, maxSpeed,
round, true or false, makes the snowflakes rounded if the browser supports it. round, true or false, makes the snowflakes rounded if the browser supports it.
shadow true or false, gives the snowflakes a shadow if the browser supports it. shadow true or false, gives the snowflakes a shadow if the browser supports it.
*/ */
// Paul Irish requestAnimationFrame polyfill // Paul Irish requestAnimationFrame polyfill
(function(window) { (function(window) {
var lastTime = 0; var lastTime = 0;
var vendors = ['webkit', 'moz']; var vendors = ['webkit', 'moz'];
for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
window.cancelAnimationFrame = window.cancelAnimationFrame =
window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame']; window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
} }
if (!window.requestAnimationFrame) if (!window.requestAnimationFrame)
window.requestAnimationFrame = function(callback, element) { window.requestAnimationFrame = function(callback, element) {
var currTime = new Date().getTime(); var currTime = new Date().getTime();
var timeToCall = window.Math.max(0, 16 - (currTime - lastTime)); var timeToCall = window.Math.max(0, 16 - (currTime - lastTime));
var id = window.setTimeout(function() { callback(currTime + timeToCall); }, var id = window.setTimeout(function() { callback(currTime + timeToCall); },
timeToCall); timeToCall);
lastTime = currTime + timeToCall; lastTime = currTime + timeToCall;
return id; return id;
}; };
if (!window.cancelAnimationFrame) if (!window.cancelAnimationFrame)
window.cancelAnimationFrame = function(id) { window.cancelAnimationFrame = function(id) {
clearTimeout(id); clearTimeout(id);
}; };
}(window)); }(window));
var snowFall = (function(){ var snowFall = (function(){
function jSnow(){ function jSnow(){
// local methods // local methods
var defaults = { var defaults = {
flakeCount : 35, flakeCount : 35,
flakeColor : '#ffffff', flakeColor : '#ffffff',
flakeIndex: 999999, flakeIndex: 999999,
minSize : 1, minSize : 1,
maxSize : 2, maxSize : 2,
minSpeed : 1, minSpeed : 1,
maxSpeed : 5, maxSpeed : 5,
round : false, round : false,
shadow : false, shadow : false,
collection : false, collection : false,
image : false, image : false,
collectionHeight : 40 collectionHeight : 40
}, },
element = {}, element = {},
flakes = [], flakes = [],
flakeId = 0, flakeId = 0,
elHeight = 0, elHeight = 0,
elWidth = 0, elWidth = 0,
elTop = 0, elTop = 0,
elLeft = 0, elLeft = 0,
widthOffset = 0, widthOffset = 0,
snowTimeout = 0, snowTimeout = 0,
// For extending the default object with properties // For extending the default object with properties
extend = function(obj, extObj){ extend = function(obj, extObj){
for(var i in extObj){ for(var i in extObj){
if(obj.hasOwnProperty(i)){ if(obj.hasOwnProperty(i)){
obj[i] = extObj[i]; obj[i] = extObj[i];
} }
} }
}, },
// random between range // random between range
random = function random(min, max){ random = function random(min, max){
return window.Math.round(min + window.Math.random()*(max-min)); return window.Math.round(min + window.Math.random()*(max-min));
}, },
// Set multiple styles at once. // Set multiple styles at once.
setStyle = function(element, props) setStyle = function(element, props)
{ {
for (var property in props){ for (var property in props){
element.style[property] = props[property] + ((property === 'width' || property === 'height') ? 'px' : ''); element.style[property] = props[property] + ((property === 'width' || property === 'height') ? 'px' : '');
} }
}, },
// snowflake // snowflake
flake = function(_x, _y, _size, _speed, _id) flake = function(_x, _y, _size, _speed, _id)
{ {
// Flake properties // Flake properties
this.id = _id; this.id = _id;
this.x = _x + elLeft; this.x = _x + elLeft;
this.y = _y + elTop; this.y = _y + elTop;
this.size = _size; this.size = _size;
this.speed = _speed; this.speed = _speed;
this.step = 0; this.step = 0;
this.stepSize = random(1,10) / 100; this.stepSize = random(1,10) / 100;
if(defaults.collection){ if(defaults.collection){
this.target = defaults.collection[random(0,defaults.collection.length-1)]; this.target = defaults.collection[random(0,defaults.collection.length-1)];
} }
var flakeObj = null; var flakeObj = null;
if(defaults.image){ if(defaults.image){
flakeObj = new Image(); flakeObj = new Image();
flakeObj.src = defaults.image; flakeObj.src = defaults.image;
}else{ }else{
flakeObj = window.document.createElement("div"); flakeObj = window.document.createElement("div");
setStyle(flakeObj, {'background' : defaults.flakeColor}); setStyle(flakeObj, {'background' : defaults.flakeColor});
} }
flakeObj.className = 'snowfall-flakes'; flakeObj.className = 'snowfall-flakes';
flakeObj.setAttribute('id','flake-' + this.id); flakeObj.setAttribute('id','flake-' + this.id);
setStyle(flakeObj, {'width' : this.size, 'height' : this.size, 'position' : 'absolute', 'top' : this.y, 'left' : this.x, 'fontSize' : 0, 'zIndex' : defaults.flakeIndex}); setStyle(flakeObj, {'width' : this.size, 'height' : this.size, 'position' : 'absolute', 'top' : this.y, 'left' : this.x, 'fontSize' : 0, 'zIndex' : defaults.flakeIndex});
// This adds the style to make the snowflakes round via border radius property // This adds the style to make the snowflakes round via border radius property
if(defaults.round){ if(defaults.round){
setStyle(flakeObj,{'-moz-border-radius' : ~~(defaults.maxSize) + 'px', '-webkit-border-radius' : ~~(defaults.maxSize) + 'px', 'borderRadius' : ~~(defaults.maxSize) + 'px'}); setStyle(flakeObj,{'-moz-border-radius' : ~~(defaults.maxSize) + 'px', '-webkit-border-radius' : ~~(defaults.maxSize) + 'px', 'borderRadius' : ~~(defaults.maxSize) + 'px'});
} }
// This adds shadows just below the snowflake so they pop a bit on lighter colored web pages // This adds shadows just below the snowflake so they pop a bit on lighter colored web pages
if(defaults.shadow){ if(defaults.shadow){
setStyle(flakeObj,{'-moz-box-shadow' : '1px 1px 1px #555', '-webkit-box-shadow' : '1px 1px 1px #555', 'boxShadow' : '1px 1px 1px #555'}); setStyle(flakeObj,{'-moz-box-shadow' : '1px 1px 1px #555', '-webkit-box-shadow' : '1px 1px 1px #555', 'boxShadow' : '1px 1px 1px #555'});
} }
window.document.body.appendChild(flakeObj); window.document.body.appendChild(flakeObj);
this.element = flakeObj; this.element = flakeObj;
// Update function, used to update the snow flakes, and checks current snowflake against bounds // Update function, used to update the snow flakes, and checks current snowflake against bounds
this.update = function(){ this.update = function(){
this.y += this.speed; this.y += this.speed;
if(this.y > (elTop + elHeight) - (this.size + 6)){ if(this.y > (elTop + elHeight) - (this.size + 6)){
this.reset(); this.reset();
} }
this.element.style.top = this.y + 'px'; this.element.style.top = this.y + 'px';
this.element.style.left = ~~this.x + 'px'; this.element.style.left = ~~this.x + 'px';
this.step += this.stepSize; this.step += this.stepSize;
this.x += window.Math.cos(this.step); this.x += window.Math.cos(this.step);
if(this.x > (elLeft + elWidth) - widthOffset || this.x < widthOffset){ if(this.x > (elLeft + elWidth) - widthOffset || this.x < widthOffset){
this.reset(); this.reset();
} }
}; };
// Resets the snowflake once it reaches one of the bounds set // Resets the snowflake once it reaches one of the bounds set
this.reset = function(){ this.reset = function(){
this.y = elTop; this.y = elTop;
this.x = elLeft + random(widthOffset, elWidth - widthOffset); this.x = elLeft + random(widthOffset, elWidth - widthOffset);
this.stepSize = random(1,10) / 100; this.stepSize = random(1,10) / 100;
this.size = random((defaults.minSize * 100), (defaults.maxSize * 100)) / 100; this.size = random((defaults.minSize * 100), (defaults.maxSize * 100)) / 100;
this.speed = random(defaults.minSpeed, defaults.maxSpeed); this.speed = random(defaults.minSpeed, defaults.maxSpeed);
}; };
}, },
// this controls flow of the updating snow // this controls flow of the updating snow
animateSnow = function(){ animateSnow = function(){
for(var i = 0; i < flakes.length; i += 1){ for(var i = 0; i < flakes.length; i += 1){
flakes[i].update(); flakes[i].update();
} }
snowTimeout = requestAnimationFrame(function(){animateSnow();}); snowTimeout = requestAnimationFrame(function(){animateSnow();});
}; };
return{ return{
snow : function(_element, _options){ snow : function(_element, _options){
extend(defaults, _options); extend(defaults, _options);
//init the element vars //init the element vars
element = _element; element = _element;
elHeight = element.clientHeight, elHeight = element.clientHeight,
elWidth = element.offsetWidth; elWidth = element.offsetWidth;
elTop = element.offsetTop; elTop = element.offsetTop;
elLeft = element.offsetLeft; elLeft = element.offsetLeft;
element.snow = this; element.snow = this;
// if this is the body the offset is a little different // if this is the body the offset is a little different
if(element.tagName.toLowerCase() === 'body'){ if(element.tagName.toLowerCase() === 'body'){
widthOffset = 25; widthOffset = 25;
} }
// Bind the window resize event so we can get the innerHeight again // Bind the window resize event so we can get the innerHeight again
window.onresize = function(){ window.onresize = function(){
elHeight = element.clientHeight; elHeight = element.clientHeight;
elWidth = element.offsetWidth; elWidth = element.offsetWidth;
elTop = element.offsetTop; elTop = element.offsetTop;
elLeft = element.offsetLeft; elLeft = element.offsetLeft;
}; };
// initialize the flakes // initialize the flakes
for(var i = 0; i < defaults.flakeCount; i+=1){ for(var i = 0; i < defaults.flakeCount; i+=1){
flakeId = flakes.length; flakeId = flakes.length;
flakes.push(new flake(random(widthOffset,elWidth - widthOffset), random(0, elHeight), random((defaults.minSize * 100), (defaults.maxSize * 100)) / 100, random(defaults.minSpeed, defaults.maxSpeed), flakeId)); flakes.push(new flake(random(widthOffset,elWidth - widthOffset), random(0, elHeight), random((defaults.minSize * 100), (defaults.maxSize * 100)) / 100, random(defaults.minSpeed, defaults.maxSpeed), flakeId));
} }
// start the snow // start the snow
animateSnow(); animateSnow();
}, },
clear : function(){ clear : function(){
var flakeChildren = null; var flakeChildren = null;
if(!element.getElementsByClassName){ if(!element.getElementsByClassName){
flakeChildren = element.querySelectorAll('.snowfall-flakes'); flakeChildren = element.querySelectorAll('.snowfall-flakes');
}else{ }else{
flakeChildren = element.getElementsByClassName('snowfall-flakes'); flakeChildren = element.getElementsByClassName('snowfall-flakes');
} }
var flakeChilLen = flakeChildren.length; var flakeChilLen = flakeChildren.length;
while(flakeChilLen--){ while(flakeChilLen--){
element.removeChild(flakeChildren[flakeChilLen]); element.removeChild(flakeChildren[flakeChilLen]);
} }
flakes = []; flakes = [];
cancelAnimationFrame(snowTimeout); cancelAnimationFrame(snowTimeout);
} }
}; };
}; };
return{ return{
snow : function(elements, options){ snow : function(elements, options){
if(typeof(options) === 'string'){ if(typeof(options) === 'string'){
if(elements.length > 0){ if(elements.length > 0){
for(var i = 0; i < elements.length; i++){ for(var i = 0; i < elements.length; i++){
if(elements[i].snow){ if(elements[i].snow){
elements[i].snow.clear(); elements[i].snow.clear();
} }
} }
}else{ }else{
elements.snow.clear(); elements.snow.clear();
} }
}else{ }else{
if(elements.length > 0){ if(elements.length > 0){
for(var i = 0; i < elements.length; i++){ for(var i = 0; i < elements.length; i++){
new jSnow().snow(elements[i], options); new jSnow().snow(elements[i], options);
} }
}else{ }else{
new jSnow().snow(elements, options); new jSnow().snow(elements, options);
} }
} }
} }
}; };
})(); })();

View file

@ -1282,7 +1282,6 @@ class Actions
'forgotPasswordLinkUrl' => \trim($oConfig->Get('login', 'forgot_password_link_url', '')), 'forgotPasswordLinkUrl' => \trim($oConfig->Get('login', 'forgot_password_link_url', '')),
'registrationLinkUrl' => \trim($oConfig->Get('login', 'registration_link_url', '')), 'registrationLinkUrl' => \trim($oConfig->Get('login', 'registration_link_url', '')),
'hideSubmitButton' => (bool) $oConfig->Get('login', 'hide_submit_button', true), 'hideSubmitButton' => (bool) $oConfig->Get('login', 'hide_submit_button', true),
'jsHash' => \md5(\RainLoop\Utils::GetConnectionToken()),
'useImapThread' => (bool) $oConfig->Get('labs', 'use_imap_thread', false), 'useImapThread' => (bool) $oConfig->Get('labs', 'use_imap_thread', false),
'useImapSubscribe' => (bool) $oConfig->Get('labs', 'use_imap_list_subscribe', true), 'useImapSubscribe' => (bool) $oConfig->Get('labs', 'use_imap_list_subscribe', true),
'allowAppendMessage' => (bool) $oConfig->Get('labs', 'allow_message_append', false), 'allowAppendMessage' => (bool) $oConfig->Get('labs', 'allow_message_append', false),

View file

@ -29,7 +29,7 @@
function ProgressJs(obj) { function ProgressJs(obj) {
if (typeof obj.length != 'undefined') { if (typeof obj.length != 'undefined') {
this._targetElement = obj; this._targetElement = obj;
} else { } else {
this._targetElement = [obj]; this._targetElement = [obj];
} }
@ -37,7 +37,7 @@
if (typeof window._progressjsId === 'undefined') if (typeof window._progressjsId === 'undefined')
window._progressjsId = 1; window._progressjsId = 1;
if (typeof window._progressjsIntervals === 'undefined') if (typeof window._progressjsIntervals === 'undefined')
window._progressjsIntervals = {}; window._progressjsIntervals = {};
this._options = { this._options = {
@ -54,7 +54,7 @@
* Start progress for specific element(s) * Start progress for specific element(s)
* *
* @api private * @api private
* @method _createContainer * @method _createContainer
*/ */
function _startProgress() { function _startProgress() {
@ -79,7 +79,7 @@
* @param {Object} targetElement * @param {Object} targetElement
*/ */
function _setProgress(targetElement) { function _setProgress(targetElement) {
//if the target element already as `data-progressjs`, ignore the init //if the target element already as `data-progressjs`, ignore the init
if (targetElement.hasAttribute("data-progressjs")) if (targetElement.hasAttribute("data-progressjs"))
return; return;
@ -88,7 +88,7 @@
var targetElementOffset = _getOffset.call(this, targetElement); var targetElementOffset = _getOffset.call(this, targetElement);
targetElement.setAttribute("data-progressjs", window._progressjsId); targetElement.setAttribute("data-progressjs", window._progressjsId);
var progressElementContainer = document.createElement('div'); var progressElementContainer = document.createElement('div');
progressElementContainer.className = 'progressjs-progress progressjs-theme-' + this._options.theme; progressElementContainer.className = 'progressjs-progress progressjs-theme-' + this._options.theme;
@ -110,7 +110,7 @@
progressPercentElement.innerHTML = "1%"; progressPercentElement.innerHTML = "1%";
progressElement.appendChild(progressPercentElement); progressElement.appendChild(progressPercentElement);
if (this._options.overlayMode && targetElement.tagName.toLowerCase() === 'body') { if (this._options.overlayMode && targetElement.tagName.toLowerCase() === 'body') {
//if we have `body` for target element and also overlay mode is enable, we should use a different //if we have `body` for target element and also overlay mode is enable, we should use a different
//position for progress bar container element //position for progress bar container element
@ -164,7 +164,7 @@
*/ */
function _setPercentFor(targetElement, percent) { function _setPercentFor(targetElement, percent) {
var self = this; var self = this;
//prevent overflow! //prevent overflow!
if (percent >= 100) if (percent >= 100)
percent = 100; percent = 100;
@ -191,7 +191,7 @@
if (existingPercent > currentPercent) { if (existingPercent > currentPercent) {
increasement = false; increasement = false;
} }
var intervalIn = 10; var intervalIn = 10;
function changePercentTimer(percentElement, existingPercent, currentPercent) { function changePercentTimer(percentElement, existingPercent, currentPercent) {
//calculate the distance between two percents //calculate the distance between two percents
@ -210,17 +210,17 @@
setTimeout(function() { changePercentTimer(percentElement, existingPercent, currentPercent); }, intervalIn); setTimeout(function() { changePercentTimer(percentElement, existingPercent, currentPercent); }, intervalIn);
} }
} }
changePercentTimer(percentElement, existingPercent, currentPercent); changePercentTimer(percentElement, existingPercent, currentPercent);
})(percentElement, existingPercent, parseInt(percent)); })(percentElement, existingPercent, parseInt(percent));
}, 50); }, 50);
} }
} }
/** /**
* Get the progress bar element * Get the progress bar element
* *
* @api private * @api private
* @method _getPercentElement * @method _getPercentElement
@ -228,7 +228,7 @@
*/ */
function _getPercentElement(targetElement) { function _getPercentElement(targetElement) {
var progressjsId = parseInt(targetElement.getAttribute('data-progressjs')); var progressjsId = parseInt(targetElement.getAttribute('data-progressjs'));
return document.querySelector('.progressjs-container > .progressjs-progress[data-progressjs="' + progressjsId + '"] > .progressjs-inner'); return document.querySelector('.progressjs-container > .progressjs-progress[data-progressjs="' + progressjsId + '"] > .progressjs-inner');
} }
/** /**
@ -241,9 +241,9 @@
*/ */
function _autoIncrease(size, millisecond) { function _autoIncrease(size, millisecond) {
var self = this; var self = this;
var progressjsId = parseInt(this._targetElement[0].getAttribute('data-progressjs')); var progressjsId = parseInt(this._targetElement[0].getAttribute('data-progressjs'));
if (typeof window._progressjsIntervals[progressjsId] != 'undefined') { if (typeof window._progressjsIntervals[progressjsId] != 'undefined') {
clearInterval(window._progressjsIntervals[progressjsId]); clearInterval(window._progressjsIntervals[progressjsId]);
} }
@ -273,7 +273,7 @@
} }
/** /**
* Close and remove progress bar * Close and remove progress bar
* *
* @api private * @api private
* @method _end * @method _end
@ -288,10 +288,10 @@
} else { } else {
this._onBeforeEndCallback.call(this); this._onBeforeEndCallback.call(this);
} }
} }
var progressjsId = parseInt(this._targetElement[0].getAttribute('data-progressjs')); var progressjsId = parseInt(this._targetElement[0].getAttribute('data-progressjs'));
for (var i = 0, elmsLength = this._targetElement.length; i < elmsLength; i++) { for (var i = 0, elmsLength = this._targetElement.length; i < elmsLength; i++) {
var currentElement = this._targetElement[i]; var currentElement = this._targetElement[i];
var percentElement = _getPercentElement(currentElement); var percentElement = _getPercentElement(currentElement);
@ -300,7 +300,7 @@
return; return;
var existingPercent = parseInt(percentElement.style.width.replace('%', '')); var existingPercent = parseInt(percentElement.style.width.replace('%', ''));
var timeoutSec = 1; var timeoutSec = 1;
if (existingPercent < 100) { if (existingPercent < 100) {
_setPercentFor.call(this, currentElement, 100); _setPercentFor.call(this, currentElement, 100);
@ -412,7 +412,7 @@
} else if (typeof (targetElm) === 'string') { } else if (typeof (targetElm) === 'string') {
//select the target element with query selector //select the target element with query selector
var targetElement = document.querySelectorAll(targetElm); var targetElement = document.querySelectorAll(targetElm);
if (targetElement) { if (targetElement) {
return new ProgressJs(targetElement); return new ProgressJs(targetElement);
} else { } else {

View file

@ -1,216 +1,216 @@
(function() { (function() {
var var
selectRange = function (el, start, end) { selectRange = function (el, start, end) {
if (!el) { if (!el) {
return; return;
} }
if (end === undefined) { if (end === undefined) {
end = start; end = start;
} }
if('selectionStart' in el) { if('selectionStart' in el) {
el.selectionStart = start; el.selectionStart = start;
el.selectionEnd = end; el.selectionEnd = end;
} else if(el.setSelectionRange) { } else if(el.setSelectionRange) {
el.setSelectionRange(start, end); el.setSelectionRange(start, end);
} else if(el.createTextRange) { } else if(el.createTextRange) {
var range = el.createTextRange(); var range = el.createTextRange();
range.collapse(true); range.collapse(true);
range.moveEnd('character', end); range.moveEnd('character', end);
range.moveStart('character', start); range.moveStart('character', start);
range.select(); range.select();
} }
}, },
toTop = function (el) { toTop = function (el) {
selectRange(el, 0); selectRange(el, 0);
if (el) { if (el) {
el.scrollTop = 0; el.scrollTop = 0;
} }
}, },
simplePlainToHtml = function (sPlain) { simplePlainToHtml = function (sPlain) {
return sPlain return sPlain
.replace(/&/g, '&amp;') .replace(/&/g, '&amp;')
.replace(/>/g, '&gt;').replace(/</g, '&lt;') .replace(/>/g, '&gt;').replace(/</g, '&lt;')
.replace(/[\-_~]{10,}/g, '<hr />') .replace(/[\-_~]{10,}/g, '<hr />')
.replace(/\n/g, '<br />') .replace(/\n/g, '<br />')
.replace(/ /g, '&nbsp;') .replace(/ /g, '&nbsp;')
; ;
}, },
simpleHtmlToPlain = function (sHtml) { simpleHtmlToPlain = function (sHtml) {
var sText = sHtml var sText = sHtml
.replace(/[\s]+/gm, ' ') .replace(/[\s]+/gm, ' ')
.replace(/<br[^>]*>/gmi, '\n') .replace(/<br[^>]*>/gmi, '\n')
.replace(/<\/h[\d]>/gi, '\n') .replace(/<\/h[\d]>/gi, '\n')
.replace(/<\/p>/gi, '\n\n') .replace(/<\/p>/gi, '\n\n')
.replace(/<\/li>/gi, '\n') .replace(/<\/li>/gi, '\n')
.replace(/<\/td>/gi, '\n') .replace(/<\/td>/gi, '\n')
.replace(/<\/tr>/gi, '\n') .replace(/<\/tr>/gi, '\n')
.replace(/<\/div>/gi, '\n') .replace(/<\/div>/gi, '\n')
.replace(/<blockquote[^>]*>/gmi, '\n') .replace(/<blockquote[^>]*>/gmi, '\n')
.replace(/<\/blockquote>/gi, '\n') .replace(/<\/blockquote>/gi, '\n')
.replace(/<hr[^>]*>/gmi, '\n_______________________________\n\n') .replace(/<hr[^>]*>/gmi, '\n_______________________________\n\n')
.replace(/&nbsp;/gi, ' ') .replace(/&nbsp;/gi, ' ')
.replace(/&quot;/gi, '"') .replace(/&quot;/gi, '"')
.replace(/<[^>]*>/gm, '') .replace(/<[^>]*>/gm, '')
; ;
sText = $('<div></div>').html(sText).text(); sText = $('<div></div>').html(sText).text();
sText = sText sText = sText
.replace(/\n[ \t]+/gm, '\n') .replace(/\n[ \t]+/gm, '\n')
.replace(/[\n]{3,}/gm, '\n\n') .replace(/[\n]{3,}/gm, '\n\n')
.replace(/&gt;/gi, '>') .replace(/&gt;/gi, '>')
.replace(/&lt;/gi, '<') .replace(/&lt;/gi, '<')
.replace(/&amp;/gi, '&') .replace(/&amp;/gi, '&')
; ;
return sText; return sText;
} }
; ;
CKEDITOR.plugins.add('plain', { CKEDITOR.plugins.add('plain', {
lang: '', lang: '',
icons: 'plain', icons: 'plain',
hidpi: true, hidpi: true,
init: function(editor) init: function(editor)
{ {
if (editor.elementMode === CKEDITOR.ELEMENT_MODE_INLINE) { if (editor.elementMode === CKEDITOR.ELEMENT_MODE_INLINE) {
return; return;
} }
editor.__textUtils = { editor.__textUtils = {
plainToHtml: function(data) { plainToHtml: function(data) {
return window.rainloop_Utils_plainToHtml ? return window.rainloop_Utils_plainToHtml ?
window.rainloop_Utils_plainToHtml(data, true) : simplePlainToHtml(data); window.rainloop_Utils_plainToHtml(data, true) : simplePlainToHtml(data);
}, },
htmlToPlain: function(data) { htmlToPlain: function(data) {
return window.rainloop_Utils_htmlToPlain ? return window.rainloop_Utils_htmlToPlain ?
window.rainloop_Utils_htmlToPlain(data, true) : simpleHtmlToPlain(data); window.rainloop_Utils_htmlToPlain(data, true) : simpleHtmlToPlain(data);
} }
}; };
var plain = CKEDITOR.plugins.plain; var plain = CKEDITOR.plugins.plain;
editor.addMode('plain', function(callback) { editor.addMode('plain', function(callback) {
var var
contentsSpace = editor.ui.space('contents'), contentsSpace = editor.ui.space('contents'),
textarea = contentsSpace.getDocument().createElement('textarea') textarea = contentsSpace.getDocument().createElement('textarea')
; ;
textarea.setStyles( textarea.setStyles(
CKEDITOR.tools.extend({ CKEDITOR.tools.extend({
width: CKEDITOR.env.ie7Compat ? '99%' : '100%', width: CKEDITOR.env.ie7Compat ? '99%' : '100%',
height: '100%', height: '100%',
resize: 'none', resize: 'none',
outline: 'none', outline: 'none',
'text-align': 'left' 'text-align': 'left'
}, },
CKEDITOR.tools.cssVendorPrefix('tab-size', 4))) CKEDITOR.tools.cssVendorPrefix('tab-size', 4)))
; ;
textarea.setAttribute('dir', 'ltr'); textarea.setAttribute('dir', 'ltr');
textarea.addClass('cke_plain'); textarea.addClass('cke_plain');
CKEDITOR.plugins.clipboard.preventDefaultDropOnElement(textarea); CKEDITOR.plugins.clipboard.preventDefaultDropOnElement(textarea);
contentsSpace.append(textarea); contentsSpace.append(textarea);
var editable = editor.editable(new plainEditable(editor, textarea)); var editable = editor.editable(new plainEditable(editor, textarea));
editable.setData(editor.getData(1)); editable.setData(editor.getData(1));
editor.__plain = editable; editor.__plain = editable;
editor.__textarea = textarea.$; editor.__textarea = textarea.$;
if (CKEDITOR.env.ie) { if (CKEDITOR.env.ie) {
editable.attachListener(editor, 'resize', onResize, editable); editable.attachListener(editor, 'resize', onResize, editable);
editable.attachListener(CKEDITOR.document.getWindow(), 'resize', onResize, editable); editable.attachListener(CKEDITOR.document.getWindow(), 'resize', onResize, editable);
CKEDITOR.tools.setTimeout(onResize, 0, editable); CKEDITOR.tools.setTimeout(onResize, 0, editable);
} }
editor.fire('ariaWidget', this); editor.fire('ariaWidget', this);
callback(); callback();
}); });
editor.addCommand('plain', plain.commands.plain); editor.addCommand('plain', plain.commands.plain);
if (editor.ui.addButton) { if (editor.ui.addButton) {
editor.ui.addButton('plain', { editor.ui.addButton('plain', {
label: window.rl && window.rl.i18n ? window.rl.i18n('EDITOR/TEXT_SWITCHER_PLAINT_TEXT') : 'Plain', label: window.rl && window.rl.i18n ? window.rl.i18n('EDITOR/TEXT_SWITCHER_PLAINT_TEXT') : 'Plain',
command: 'plain', command: 'plain',
toolbar: 'spec,10' toolbar: 'spec,10'
}); });
} }
editor.on('mode', function() { editor.on('mode', function() {
editor.getCommand('plain').setState(editor.mode === 'plain' ? CKEDITOR.TRISTATE_ON : CKEDITOR.TRISTATE_OFF); editor.getCommand('plain').setState(editor.mode === 'plain' ? CKEDITOR.TRISTATE_ON : CKEDITOR.TRISTATE_OFF);
editor.editable().addClass('cke_enable_context_menu'); editor.editable().addClass('cke_enable_context_menu');
editor.focus(); editor.focus();
if (editor.mode === 'plain') { if (editor.mode === 'plain') {
toTop(editor.__textarea); toTop(editor.__textarea);
} }
}); });
function onResize() { function onResize() {
this.hide(); this.hide();
this.setStyle('height', this.getParent().$.clientHeight + 'px'); this.setStyle('height', this.getParent().$.clientHeight + 'px');
this.setStyle('width', this.getParent().$.clientWidth + 'px'); this.setStyle('width', this.getParent().$.clientWidth + 'px');
this.show(); this.show();
} }
} }
}); });
var plainEditable = CKEDITOR.tools.createClass({ var plainEditable = CKEDITOR.tools.createClass({
base: CKEDITOR.editable, base: CKEDITOR.editable,
proto: { proto: {
setData: function(data) { setData: function(data) {
this.setValue(this.editor.__textUtils.htmlToPlain(data)); this.setValue(this.editor.__textUtils.htmlToPlain(data));
this.editor.fire('dataReady'); this.editor.fire('dataReady');
}, },
setRawData: function(data) { setRawData: function(data) {
this.setValue(data); this.setValue(data);
this.editor.fire('dataReady'); this.editor.fire('dataReady');
}, },
getData: function() { getData: function() {
return this.editor.__textUtils.plainToHtml(this.getValue()); return this.editor.__textUtils.plainToHtml(this.getValue());
}, },
getRawData: function() { getRawData: function() {
return this.getValue(); return this.getValue();
}, },
insertHtml: function() {}, insertHtml: function() {},
insertElement: function() {}, insertElement: function() {},
insertText: function() {}, insertText: function() {},
setReadOnly: function( isReadOnly ) { setReadOnly: function( isReadOnly ) {
this[(isReadOnly ? 'set' : 'remove') + 'Attribute' ]('readOnly', 'readonly'); this[(isReadOnly ? 'set' : 'remove') + 'Attribute' ]('readOnly', 'readonly');
}, },
detach: function() { detach: function() {
plainEditable.baseProto.detach.call( this ); plainEditable.baseProto.detach.call( this );
this.clearCustomData(); this.clearCustomData();
this.remove(); this.remove();
} }
} }
}); });
CKEDITOR.plugins.plain = { CKEDITOR.plugins.plain = {
commands: { commands: {
plain: { plain: {
modes: { modes: {
wysiwyg: 1, plain: 1 wysiwyg: 1, plain: 1
}, },
editorFocus: true, editorFocus: true,
readOnly: false, readOnly: false,
exec: function(editor) { exec: function(editor) {
if (editor.mode === 'wysiwyg') { if (editor.mode === 'wysiwyg') {
editor.fire('saveSnapshot'); editor.fire('saveSnapshot');
} }
editor.getCommand('plain').setState(CKEDITOR.TRISTATE_DISABLED); editor.getCommand('plain').setState(CKEDITOR.TRISTATE_DISABLED);
editor.setMode(editor.mode === 'plain' ? 'wysiwyg' : 'plain'); editor.setMode(editor.mode === 'plain' ? 'wysiwyg' : 'plain');
}, },
canUndo: false canUndo: false
} }
} }
}; };
}()); }());

View file

@ -1,141 +1,141 @@
(function(CKEDITOR, $, undefined) { (function(CKEDITOR, $, undefined) {
'use strict'; 'use strict';
var rl_signature_replacer = function(editor, text, signature, isHtml, insertBefore) { var rl_signature_replacer = function(editor, text, signature, isHtml, insertBefore) {
var var
skipInsert = false, skipInsert = false,
isEmptyText = false, isEmptyText = false,
newLine = (isHtml ? '<br />' : "\n"), newLine = (isHtml ? '<br />' : "\n"),
clearHtmlLine = function(html) { clearHtmlLine = function(html) {
return $.trim(editor.__textUtils.htmlToPlain(html)); return $.trim(editor.__textUtils.htmlToPlain(html));
}; };
isEmptyText = '' === $.trim(text); isEmptyText = '' === $.trim(text);
if (!isEmptyText && isHtml) if (!isEmptyText && isHtml)
{ {
isEmptyText = '' === clearHtmlLine(text); isEmptyText = '' === clearHtmlLine(text);
} }
if (editor.__previos_signature && !isEmptyText) if (editor.__previos_signature && !isEmptyText)
{ {
if (isHtml && !editor.__previos_signature_is_html) if (isHtml && !editor.__previos_signature_is_html)
{ {
editor.__previos_signature = editor.__textUtils.plainToHtml(editor.__previos_signature); editor.__previos_signature = editor.__textUtils.plainToHtml(editor.__previos_signature);
editor.__previos_signature_is_html = true; editor.__previos_signature_is_html = true;
} }
else if (!isHtml && editor.__previos_signature_is_html) else if (!isHtml && editor.__previos_signature_is_html)
{ {
editor.__previos_signature = editor.__textUtils.htmlToPlain(editor.__previos_signature); editor.__previos_signature = editor.__textUtils.htmlToPlain(editor.__previos_signature);
editor.__previos_signature_is_html = false; editor.__previos_signature_is_html = false;
} }
skipInsert = false; skipInsert = false;
if (isHtml) if (isHtml)
{ {
var clearSig = clearHtmlLine(editor.__previos_signature); var clearSig = clearHtmlLine(editor.__previos_signature);
text = text.replace(/<signature>([\s\S]*)<\/signature>/igm, function(all){ text = text.replace(/<signature>([\s\S]*)<\/signature>/igm, function(all){
var c = clearSig === clearHtmlLine(all); var c = clearSig === clearHtmlLine(all);
if (!c) { if (!c) {
skipInsert = true; skipInsert = true;
} }
return c ? '' : all; return c ? '' : all;
}); });
} }
else else
{ {
var textLen = text.length; var textLen = text.length;
text = text text = text
.replace('' + editor.__previos_signature, '') .replace('' + editor.__previos_signature, '')
.replace('' + editor.__previos_signature, ''); .replace('' + editor.__previos_signature, '');
if (textLen === text.length) if (textLen === text.length)
{ {
skipInsert = true; skipInsert = true;
} }
} }
} }
if (!skipInsert) if (!skipInsert)
{ {
signature = newLine + newLine + (isHtml ? '<signature>' : '') + signature + (isHtml ? '</signature>' : ''); signature = newLine + newLine + (isHtml ? '<signature>' : '') + signature + (isHtml ? '</signature>' : '');
text = insertBefore ? signature + text : text + signature; text = insertBefore ? signature + text : text + signature;
if (10 < signature.length) if (10 < signature.length)
{ {
editor.__previos_signature = signature; editor.__previos_signature = signature;
editor.__previos_signature_is_html = isHtml; editor.__previos_signature_is_html = isHtml;
} }
} }
return text; return text;
}; };
CKEDITOR.plugins.add('signature', { CKEDITOR.plugins.add('signature', {
init: function(editor) { init: function(editor) {
editor.addCommand('insertSignature', { editor.addCommand('insertSignature', {
modes: {wysiwyg: 1, plain: 1}, modes: {wysiwyg: 1, plain: 1},
exec: function(editor, cfg) { exec: function(editor, cfg) {
if (cfg && cfg.clearCache) if (cfg && cfg.clearCache)
{ {
editor.__previos_signature = undefined; editor.__previos_signature = undefined;
editor.__previos_signature_is_html = undefined; editor.__previos_signature_is_html = undefined;
return true; return true;
} }
var var
bIsHtml = false, bIsHtml = false,
bInsertBefore = false, bInsertBefore = false,
sSignature = '', sSignature = '',
sResultSignature = ''; sResultSignature = '';
if (cfg) if (cfg)
{ {
bIsHtml = undefined === cfg.isHtml ? false : !!cfg.isHtml; bIsHtml = undefined === cfg.isHtml ? false : !!cfg.isHtml;
bInsertBefore = undefined === cfg.insertBefore ? false : !!cfg.insertBefore; bInsertBefore = undefined === cfg.insertBefore ? false : !!cfg.insertBefore;
sSignature = undefined === cfg.signature ? '' : cfg.signature; sSignature = undefined === cfg.signature ? '' : cfg.signature;
} }
sResultSignature = sSignature; sResultSignature = sSignature;
try try
{ {
if ('plain' === editor.mode && editor.__plain && editor.__textUtils) if ('plain' === editor.mode && editor.__plain && editor.__textUtils)
{ {
if (editor.__textUtils && editor.__textUtils.htmlToPlain) if (editor.__textUtils && editor.__textUtils.htmlToPlain)
{ {
if (bIsHtml) if (bIsHtml)
{ {
sResultSignature = editor.__textUtils.htmlToPlain(sResultSignature); sResultSignature = editor.__textUtils.htmlToPlain(sResultSignature);
} }
} }
editor.__plain.setRawData( editor.__plain.setRawData(
rl_signature_replacer(editor, editor.__plain.getRawData(), sResultSignature, false, bInsertBefore)); rl_signature_replacer(editor, editor.__plain.getRawData(), sResultSignature, false, bInsertBefore));
} }
else else
{ {
if (editor.__textUtils && editor.__textUtils.plainToHtml) if (editor.__textUtils && editor.__textUtils.plainToHtml)
{ {
if (!bIsHtml) if (!bIsHtml)
{ {
sResultSignature = editor.__textUtils.plainToHtml(sResultSignature); sResultSignature = editor.__textUtils.plainToHtml(sResultSignature);
} }
} }
editor.setData( editor.setData(
rl_signature_replacer(editor, editor.getData(), sResultSignature, true, bInsertBefore)); rl_signature_replacer(editor, editor.getData(), sResultSignature, true, bInsertBefore));
} }
} }
catch (e) {} catch (e) {}
} }
}); });
} }
}); });
}(CKEDITOR, $)); }(CKEDITOR, $));

View file

@ -1,12 +1,12 @@
:(t=!!k[n],"br"!=n||!e.data("cke-eol") :(t=!!k[n],"br"!=n||!e.data("cke-eol")
:(t=!k||!!k[n],"br"!=n||!e.data("cke-eol") :(t=!k||!!k[n],"br"!=n||!e.data("cke-eol")
--- ---
for(F=null;y&&!p[y.getName()][L.name];){ for(F=null;y&&!p[y.getName()][L.name];){
for(F=null;y&&(!p||!p[y.getName()]||!p[y.getName()][L.name]);){ for(F=null;y&&(!p||!p[y.getName()]||!p[y.getName()][L.name]);){
--- ---
a.window.$.getSelection().removeAllRanges() a.window.$.getSelection().removeAllRanges()
a.window&&a.window.$&&a.window.$.getSelection().removeAllRanges() a.window&&a.window.$&&a.window.$.getSelection().removeAllRanges()

View file

@ -1,4 +1,4 @@
/* /*
Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.md or http://ckeditor.com/license For licensing, see LICENSE.md or http://ckeditor.com/license
*/ */

View file

@ -1,54 +1,54 @@
/** /**
* @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md or http://ckeditor.com/license * For licensing, see LICENSE.md or http://ckeditor.com/license
*/ */
/** /**
* This file was added automatically by CKEditor builder. * This file was added automatically by CKEditor builder.
* You may re-use it at any time to build CKEditor again. * You may re-use it at any time to build CKEditor again.
* *
* If you would like to build CKEditor online again * If you would like to build CKEditor online again
* (for example to upgrade), visit one the following links: * (for example to upgrade), visit one the following links:
* *
* (1) http://ckeditor.com/builder * (1) http://ckeditor.com/builder
* Visit online builder to build CKEditor from scratch. * Visit online builder to build CKEditor from scratch.
* *
* (2) http://ckeditor.com/builder/9b9471acfb896c4f73b825ccf971b5bc * (2) http://ckeditor.com/builder/9b9471acfb896c4f73b825ccf971b5bc
* Visit online builder to build CKEditor, starting with the same setup as before. * Visit online builder to build CKEditor, starting with the same setup as before.
* *
* (3) http://ckeditor.com/builder/download/9b9471acfb896c4f73b825ccf971b5bc * (3) http://ckeditor.com/builder/download/9b9471acfb896c4f73b825ccf971b5bc
* Straight download link to the latest version of CKEditor (Optimized) with the same setup as before. * Straight download link to the latest version of CKEditor (Optimized) with the same setup as before.
* *
* NOTE: * NOTE:
* This file is not used by CKEditor, you may remove it. * This file is not used by CKEditor, you may remove it.
* Changing this file will not change your CKEditor configuration. * Changing this file will not change your CKEditor configuration.
*/ */
var CKBUILDER_CONFIG = { var CKBUILDER_CONFIG = {
skin: 'moono-lisa', skin: 'moono-lisa',
preset: 'basic', preset: 'basic',
ignore: [ ignore: [
'.bender', '.bender',
'bender.js', 'bender.js',
'bender-err.log', 'bender-err.log',
'bender-out.log', 'bender-out.log',
'dev', 'dev',
'.DS_Store', '.DS_Store',
'.editorconfig', '.editorconfig',
'.gitattributes', '.gitattributes',
'.gitignore', '.gitignore',
'gruntfile.js', 'gruntfile.js',
'.idea', '.idea',
'.jscsrc', '.jscsrc',
'.jshintignore', '.jshintignore',
'.jshintrc', '.jshintrc',
'less', 'less',
'.mailmap', '.mailmap',
'node_modules', 'node_modules',
'package.json', 'package.json',
'README.md', 'README.md',
'tests' 'tests'
], ],
plugins : { plugins : {
'about' : 1, 'about' : 1,
'autolink' : 1, 'autolink' : 1,

View file

@ -1,4 +1,4 @@
/* /*
Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.md or http://ckeditor.com/license For licensing, see LICENSE.md or http://ckeditor.com/license
*/ */

View file

@ -1,4 +1,4 @@
/* /*
Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.md or http://ckeditor.com/license For licensing, see LICENSE.md or http://ckeditor.com/license
*/ */

View file

@ -1,208 +1,208 @@
/* /*
Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.md or http://ckeditor.com/license For licensing, see LICENSE.md or http://ckeditor.com/license
*/ */
body body
{ {
/* Font */ /* Font */
font-family: sans-serif, Arial, Verdana, "Trebuchet MS"; font-family: sans-serif, Arial, Verdana, "Trebuchet MS";
font-size: 12px; font-size: 12px;
/* Text color */ /* Text color */
color: #333; color: #333;
/* Remove the background color to make it transparent */ /* Remove the background color to make it transparent */
background-color: #fff; background-color: #fff;
margin: 20px; margin: 20px;
} }
.cke_editable .cke_editable
{ {
font-size: 13px; font-size: 13px;
line-height: 1.6; line-height: 1.6;
/* Fix for missing scrollbars with RTL texts. (#10488) */ /* Fix for missing scrollbars with RTL texts. (#10488) */
word-wrap: break-word; word-wrap: break-word;
} }
blockquote blockquote
{ {
font-style: italic; font-style: italic;
font-family: Georgia, Times, "Times New Roman", serif; font-family: Georgia, Times, "Times New Roman", serif;
padding: 2px 0; padding: 2px 0;
border-style: solid; border-style: solid;
border-color: #ccc; border-color: #ccc;
border-width: 0; border-width: 0;
} }
.cke_contents_ltr blockquote .cke_contents_ltr blockquote
{ {
padding-left: 20px; padding-left: 20px;
padding-right: 8px; padding-right: 8px;
border-left-width: 5px; border-left-width: 5px;
} }
.cke_contents_rtl blockquote .cke_contents_rtl blockquote
{ {
padding-left: 8px; padding-left: 8px;
padding-right: 20px; padding-right: 20px;
border-right-width: 5px; border-right-width: 5px;
} }
a a
{ {
color: #0782C1; color: #0782C1;
} }
ol,ul,dl ol,ul,dl
{ {
/* IE7: reset rtl list margin. (#7334) */ /* IE7: reset rtl list margin. (#7334) */
*margin-right: 0px; *margin-right: 0px;
/* preserved spaces for list items with text direction other than the list. (#6249,#8049)*/ /* preserved spaces for list items with text direction other than the list. (#6249,#8049)*/
padding: 0 40px; padding: 0 40px;
} }
h1,h2,h3,h4,h5,h6 h1,h2,h3,h4,h5,h6
{ {
font-weight: normal; font-weight: normal;
line-height: 1.2; line-height: 1.2;
} }
hr hr
{ {
border: 0px; border: 0px;
border-top: 1px solid #ccc; border-top: 1px solid #ccc;
} }
img.right img.right
{ {
border: 1px solid #ccc; border: 1px solid #ccc;
float: right; float: right;
margin-left: 15px; margin-left: 15px;
padding: 5px; padding: 5px;
} }
img.left img.left
{ {
border: 1px solid #ccc; border: 1px solid #ccc;
float: left; float: left;
margin-right: 15px; margin-right: 15px;
padding: 5px; padding: 5px;
} }
pre pre
{ {
white-space: pre-wrap; /* CSS 2.1 */ white-space: pre-wrap; /* CSS 2.1 */
word-wrap: break-word; /* IE7 */ word-wrap: break-word; /* IE7 */
-moz-tab-size: 4; -moz-tab-size: 4;
tab-size: 4; tab-size: 4;
} }
.marker .marker
{ {
background-color: Yellow; background-color: Yellow;
} }
span[lang] span[lang]
{ {
font-style: italic; font-style: italic;
} }
figure figure
{ {
text-align: center; text-align: center;
border: solid 1px #ccc; border: solid 1px #ccc;
border-radius: 2px; border-radius: 2px;
background: rgba(0,0,0,0.05); background: rgba(0,0,0,0.05);
padding: 10px; padding: 10px;
margin: 10px 20px; margin: 10px 20px;
display: inline-block; display: inline-block;
} }
figure > figcaption figure > figcaption
{ {
text-align: center; text-align: center;
display: block; /* For IE8 */ display: block; /* For IE8 */
} }
a > img { a > img {
padding: 1px; padding: 1px;
margin: 1px; margin: 1px;
border: none; border: none;
outline: 1px solid #0782C1; outline: 1px solid #0782C1;
} }
/* Widget Styles */ /* Widget Styles */
.code-featured .code-featured
{ {
border: 5px solid red; border: 5px solid red;
} }
.math-featured .math-featured
{ {
padding: 20px; padding: 20px;
box-shadow: 0 0 2px rgba(200, 0, 0, 1); box-shadow: 0 0 2px rgba(200, 0, 0, 1);
background-color: rgba(255, 0, 0, 0.05); background-color: rgba(255, 0, 0, 0.05);
margin: 10px; margin: 10px;
} }
.image-clean .image-clean
{ {
border: 0; border: 0;
background: none; background: none;
padding: 0; padding: 0;
} }
.image-clean > figcaption .image-clean > figcaption
{ {
font-size: .9em; font-size: .9em;
text-align: right; text-align: right;
} }
.image-grayscale .image-grayscale
{ {
background-color: white; background-color: white;
color: #666; color: #666;
} }
.image-grayscale img, img.image-grayscale .image-grayscale img, img.image-grayscale
{ {
filter: grayscale(100%); filter: grayscale(100%);
} }
.embed-240p .embed-240p
{ {
max-width: 426px; max-width: 426px;
max-height: 240px; max-height: 240px;
margin:0 auto; margin:0 auto;
} }
.embed-360p .embed-360p
{ {
max-width: 640px; max-width: 640px;
max-height: 360px; max-height: 360px;
margin:0 auto; margin:0 auto;
} }
.embed-480p .embed-480p
{ {
max-width: 854px; max-width: 854px;
max-height: 480px; max-height: 480px;
margin:0 auto; margin:0 auto;
} }
.embed-720p .embed-720p
{ {
max-width: 1280px; max-width: 1280px;
max-height: 720px; max-height: 720px;
margin:0 auto; margin:0 auto;
} }
.embed-1080p .embed-1080p
{ {
max-width: 1920px; max-width: 1920px;
max-height: 1080px; max-height: 1080px;
margin:0 auto; margin:0 auto;
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

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