mirror of
https://github.com/the-djmaze/snappymail.git
synced 2024-09-20 07:35:55 +08:00
CRLF to LF
This commit is contained in:
parent
4468d5bd22
commit
6e0d0b3b6e
|
@ -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',
|
||||||
|
|
42
_include.php
42
_include.php
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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); }
|
||||||
}
|
}
|
||||||
|
|
|
@ -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';
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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,
|
||||||
|
|
38
index.php
38
index.php
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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('*')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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('*')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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('*')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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))
|
||||||
{
|
{
|
||||||
|
|
|
@ -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('*')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ function md5crypt($pw, $salt = "", $magic = "")
|
||||||
{
|
{
|
||||||
$ctx .= $pw[0];
|
$ctx .= $pw[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
$i = $i >> 1;
|
$i = $i >> 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})();
|
})();
|
|
@ -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),
|
||||||
|
|
40
vendors/Progress.js/src/progress.js
vendored
40
vendors/Progress.js/src/progress.js
vendored
|
@ -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 {
|
||||||
|
|
432
vendors/ckeditor-plugins/plain/plugin.js
vendored
432
vendors/ckeditor-plugins/plain/plugin.js
vendored
|
@ -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, '&')
|
.replace(/&/g, '&')
|
||||||
.replace(/>/g, '>').replace(/</g, '<')
|
.replace(/>/g, '>').replace(/</g, '<')
|
||||||
.replace(/[\-_~]{10,}/g, '<hr />')
|
.replace(/[\-_~]{10,}/g, '<hr />')
|
||||||
.replace(/\n/g, '<br />')
|
.replace(/\n/g, '<br />')
|
||||||
.replace(/ /g, ' ')
|
.replace(/ /g, ' ')
|
||||||
;
|
;
|
||||||
},
|
},
|
||||||
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(/ /gi, ' ')
|
.replace(/ /gi, ' ')
|
||||||
.replace(/"/gi, '"')
|
.replace(/"/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(/>/gi, '>')
|
.replace(/>/gi, '>')
|
||||||
.replace(/</gi, '<')
|
.replace(/</gi, '<')
|
||||||
.replace(/&/gi, '&')
|
.replace(/&/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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}());
|
}());
|
||||||
|
|
282
vendors/ckeditor-plugins/signature/plugin.js
vendored
282
vendors/ckeditor-plugins/signature/plugin.js
vendored
|
@ -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, $));
|
||||||
|
|
24
vendors/ckeditor/FIXES.txt
vendored
24
vendors/ckeditor/FIXES.txt
vendored
|
@ -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()
|
||||||
|
|
2
vendors/ckeditor/adapters/jquery.js
vendored
2
vendors/ckeditor/adapters/jquery.js
vendored
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
|
102
vendors/ckeditor/build-config.js
vendored
102
vendors/ckeditor/build-config.js
vendored
|
@ -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,
|
||||||
|
|
2
vendors/ckeditor/ckeditor.js
vendored
2
vendors/ckeditor/ckeditor.js
vendored
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
|
2
vendors/ckeditor/ckeditor.orig.js
vendored
2
vendors/ckeditor/ckeditor.orig.js
vendored
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
|
416
vendors/ckeditor/contents.css
vendored
416
vendors/ckeditor/contents.css
vendored
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
6
vendors/ckeditor/lang/af.js
vendored
6
vendors/ckeditor/lang/af.js
vendored
File diff suppressed because one or more lines are too long
247
vendors/ckeditor/lang/ar.js
vendored
247
vendors/ckeditor/lang/ar.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/az.js
vendored
6
vendors/ckeditor/lang/az.js
vendored
File diff suppressed because one or more lines are too long
14
vendors/ckeditor/lang/bg.js
vendored
14
vendors/ckeditor/lang/bg.js
vendored
File diff suppressed because one or more lines are too long
22
vendors/ckeditor/lang/bn.js
vendored
22
vendors/ckeditor/lang/bn.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/bs.js
vendored
6
vendors/ckeditor/lang/bs.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/ca.js
vendored
6
vendors/ckeditor/lang/ca.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/cs.js
vendored
6
vendors/ckeditor/lang/cs.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/cy.js
vendored
6
vendors/ckeditor/lang/cy.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/da.js
vendored
6
vendors/ckeditor/lang/da.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/de-ch.js
vendored
6
vendors/ckeditor/lang/de-ch.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/de.js
vendored
6
vendors/ckeditor/lang/de.js
vendored
File diff suppressed because one or more lines are too long
149
vendors/ckeditor/lang/el.js
vendored
149
vendors/ckeditor/lang/el.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/en-au.js
vendored
6
vendors/ckeditor/lang/en-au.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/en-ca.js
vendored
6
vendors/ckeditor/lang/en-ca.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/en-gb.js
vendored
6
vendors/ckeditor/lang/en-gb.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/en.js
vendored
6
vendors/ckeditor/lang/en.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/eo.js
vendored
6
vendors/ckeditor/lang/eo.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/es.js
vendored
6
vendors/ckeditor/lang/es.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/et.js
vendored
6
vendors/ckeditor/lang/et.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/eu.js
vendored
6
vendors/ckeditor/lang/eu.js
vendored
File diff suppressed because one or more lines are too long
170
vendors/ckeditor/lang/fa.js
vendored
170
vendors/ckeditor/lang/fa.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/fi.js
vendored
6
vendors/ckeditor/lang/fi.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/fo.js
vendored
6
vendors/ckeditor/lang/fo.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/fr-ca.js
vendored
6
vendors/ckeditor/lang/fr-ca.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/fr.js
vendored
6
vendors/ckeditor/lang/fr.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/gl.js
vendored
6
vendors/ckeditor/lang/gl.js
vendored
File diff suppressed because one or more lines are too long
39
vendors/ckeditor/lang/gu.js
vendored
39
vendors/ckeditor/lang/gu.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/he.js
vendored
6
vendors/ckeditor/lang/he.js
vendored
File diff suppressed because one or more lines are too long
45
vendors/ckeditor/lang/hi.js
vendored
45
vendors/ckeditor/lang/hi.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/hr.js
vendored
6
vendors/ckeditor/lang/hr.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/hu.js
vendored
6
vendors/ckeditor/lang/hu.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/id.js
vendored
6
vendors/ckeditor/lang/id.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/is.js
vendored
6
vendors/ckeditor/lang/is.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/it.js
vendored
6
vendors/ckeditor/lang/it.js
vendored
File diff suppressed because one or more lines are too long
76
vendors/ckeditor/lang/ja.js
vendored
76
vendors/ckeditor/lang/ja.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/ka.js
vendored
6
vendors/ckeditor/lang/ka.js
vendored
File diff suppressed because one or more lines are too long
127
vendors/ckeditor/lang/km.js
vendored
127
vendors/ckeditor/lang/km.js
vendored
File diff suppressed because one or more lines are too long
85
vendors/ckeditor/lang/ko.js
vendored
85
vendors/ckeditor/lang/ko.js
vendored
File diff suppressed because one or more lines are too long
107
vendors/ckeditor/lang/ku.js
vendored
107
vendors/ckeditor/lang/ku.js
vendored
File diff suppressed because one or more lines are too long
39
vendors/ckeditor/lang/lt.js
vendored
39
vendors/ckeditor/lang/lt.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/lv.js
vendored
6
vendors/ckeditor/lang/lv.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/mk.js
vendored
6
vendors/ckeditor/lang/mk.js
vendored
File diff suppressed because one or more lines are too long
169
vendors/ckeditor/lang/mn.js
vendored
169
vendors/ckeditor/lang/mn.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/ms.js
vendored
6
vendors/ckeditor/lang/ms.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/nb.js
vendored
6
vendors/ckeditor/lang/nb.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/nl.js
vendored
6
vendors/ckeditor/lang/nl.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/no.js
vendored
6
vendors/ckeditor/lang/no.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/oc.js
vendored
6
vendors/ckeditor/lang/oc.js
vendored
File diff suppressed because one or more lines are too long
69
vendors/ckeditor/lang/pl.js
vendored
69
vendors/ckeditor/lang/pl.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/pt-br.js
vendored
6
vendors/ckeditor/lang/pt-br.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/pt.js
vendored
6
vendors/ckeditor/lang/pt.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/ro.js
vendored
6
vendors/ckeditor/lang/ro.js
vendored
File diff suppressed because one or more lines are too long
25
vendors/ckeditor/lang/ru.js
vendored
25
vendors/ckeditor/lang/ru.js
vendored
File diff suppressed because one or more lines are too long
62
vendors/ckeditor/lang/si.js
vendored
62
vendors/ckeditor/lang/si.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/sk.js
vendored
6
vendors/ckeditor/lang/sk.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/sl.js
vendored
6
vendors/ckeditor/lang/sl.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/sq.js
vendored
6
vendors/ckeditor/lang/sq.js
vendored
File diff suppressed because one or more lines are too long
6
vendors/ckeditor/lang/sr-latn.js
vendored
6
vendors/ckeditor/lang/sr-latn.js
vendored
File diff suppressed because one or more lines are too long
12
vendors/ckeditor/lang/sr.js
vendored
12
vendors/ckeditor/lang/sr.js
vendored
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
Loading…
Reference in a new issue