Changes to work with new config and some minor fixes

This commit is contained in:
ohartl 2016-03-01 15:12:28 +01:00
parent 25f08f5e76
commit fadbd4a6b4
24 changed files with 391 additions and 330 deletions

2
.gitignore vendored
View file

@ -1 +1 @@
config/config.inc.php
config/config.php

View file

@ -1,120 +0,0 @@
<?php
/* DO NOT EDIT THIS FILE!
Instead, copy this config file to config.inc.php and make your changes
in the copied version. This is just a template!
*/
/*
* MySQL server and database settings
*/
define("MYSQL_HOST", "localhost");
define("MYSQL_USER", "vmail");
define("MYSQL_PASSWORD", "vmail");
define("MYSQL_DATABASE", "vmail");
/*
* Database table names
*/
// Table names
define("DBT_USERS", "users");
define("DBT_DOMAINS", "domains");
define("DBT_ALIASES", "aliases");
// Users table columns
define("DBC_USERS_ID", "id");
define("DBC_USERS_USERNAME", "username");
define("DBC_USERS_DOMAIN", "domain");
define("DBC_USERS_PASSWORD", "password");
// define("DBC_USERS_MAILBOXLIMIT", "mailbox_limit"); // (Optional)
// Domains table columns
define("DBC_DOMAINS_ID", "id");
define("DBC_DOMAINS_DOMAIN", "domain");
// Aliases table columns
define("DBC_ALIASES_ID", "id");
define("DBC_ALIASES_SOURCE", "source");
define("DBC_ALIASES_DESTINATION", "destination");
// Enable multi source redirects, needs a new column in aliase table with VARCHAR(32)
//define("DBC_ALIASES_MULTI_SOURCE", "multi_source"); // (Optional, Recommended)
/*
* General options
*/
// Enable validating that the source addresses are ending with domain from domains
//define("VALIDATE_ALIASES_SOURCE_DOMAIN_ENABLED", true); // (Optional, Recommended)
/*
* Frontend paths
*/
define("FRONTEND_BASE_PATH", "http://localhost/webmum/");
/*
* Admin e-mail address
*/
// outdated: define("ADMIN_EMAIL", "admin@domain.tld");
// new: $admins = array("admin1@server.tld", "admin2@server.tld");
$admins = array("admin@domain.tld");
/**
* Limited admin domain access
*
* Unlisted admins have access to every domain, the admin is limited to listed domains only!
* Unlisted domains aren't accessible by that admin.
*
* Note that listed admins also cannot create new domains!
*/
//define("ADMIN_DOMAIN_LIMITS_ENABLED", true); // (Optional)
$adminDomainLimits = array(
// Example:
// "low_rank_admin@domain.tld" => array("his-domain.tld", "shared-domain.tld"),
);
/*
* Password
*/
/*
* Select on of the following schemas (only these are supported)
* SHA-512, SHA-256, BLOWFISH
*/
define("PASS_HASH_SCHEMA", "SHA-512");
//minimum password length
define("MIN_PASS_LENGTH", 8);
/*
* Write log file? Failed login attempts will be written to the logfile.
* You can mointor the logfile with fail2ban and ban attackers' IP-addresses.
* Make sure that PHP has permission to create the log directory and webmum.log (write permissions for php user)
*
* Default: Do not write logfile
*/
// define("WRITE_LOG", true);
// define("WRITE_LOG_PATH","/var/www/webmum/log/");
/*
* Frontend options
*/
// Separator for email lists
define("FRONTEND_EMAIL_SEPARATOR_TEXT", ', '); // possible values: ', ' (default), '; ', PHP_EOL (newline)
define("FRONTEND_EMAIL_SEPARATOR_FORM", ','); // possible values: ',' (default), ';', PHP_EOL (newline)
?>

View file

@ -95,8 +95,8 @@ class Auth
/** @var User $user */
$user = User::findWhereFirst(
array(
array(DBC_USERS_USERNAME, $username),
array(DBC_USERS_DOMAIN, $domain),
array(User::attr('username'), $username),
array(User::attr('domain'), $domain),
)
);
@ -178,8 +178,10 @@ class Auth
}
// Check if password length is okay
if(strlen($password) < MIN_PASS_LENGTH){
throw new Exception("Passwords must be at least ".MIN_PASS_LENGTH." characters long.", 4);
if(Config::has('password.min_length')
&& strlen($password) < Config::get('password.min_length')
){
throw new Exception("Passwords must be at least ".Config::get('password.min_length')." characters long.", 4);
}
}
@ -207,11 +209,13 @@ class Auth
'SHA-512' => '$6$rounds=5000$',
);
if(isset($map[PASS_HASH_SCHEMA])){
return $map[PASS_HASH_SCHEMA];
$key = Config::get('password.hash_algorithm', 'SHA-512');
if(!isset($map[$key])){
$key = 'SHA-512';
}
return $map['SHA-512'];
return $map[$key];
}

View file

@ -70,9 +70,21 @@ class Database
* @param string $password
* @param string $database
*/
public static function init($host, $user, $password, $database)
public static function init($host, $user = null, $password = null, $database = null)
{
if(!static::isInitialized()){
if(is_array($host)){
if(isset($host['host']) && isset($host['user']) && isset($host['password']) && isset($host['database'])){
$user = $host['user'];
$password = $host['password'];
$database = $host['database'];
$host = $host['host'];
}
else{
throw new InvalidArgumentException;
}
}
static::setInstance(
new static($host, $user, $password, $database)
);

View file

@ -161,7 +161,7 @@ class Router
*/
public static function getCurrentUrlPath($removeGetParameters = true)
{
$baseUrl = parse_url(FRONTEND_BASE_PATH);
$baseUrl = parse_url(Config::get('base_url'));
$basePath = isset($baseUrl['path']) ? rtrim($baseUrl['path'], '/') : '';
$url = $_SERVER['REQUEST_URI'];
@ -227,7 +227,7 @@ class Router
*/
public static function url($url)
{
return sprintf('%s/%s', rtrim(FRONTEND_BASE_PATH, '/'), trim($url, '/'));
return sprintf('%s/%s', rtrim(Config::get('base_url'), '/'), trim($url, '/'));
}

View file

@ -29,18 +29,85 @@ require_once 'include/php/global.inc.php';
/**
* Require config
*/
if(file_exists('config/config.inc.php')){
require_once 'config/config.inc.php';
if(file_exists('config/config.php')){
$configValues = require_once 'config/config.php';
if(!is_array($configValues)){
die('Config must return an array of config values.');
}
Config::init($configValues);
}
else{
require_once 'config/config.inc.php.example';
$configValues = require_once 'config/config.php.example';
if(!is_array($configValues)){
die('Config must return an array of config values.');
}
Config::init($configValues);
/**
* Handle old config style, if it still exists.
**/
if(file_exists('config/config.inc.php') || file_exists('config/config.inc.php.example')){
define('USING_OLD_CONFIG', true);
if(file_exists('config/config.inc.php')){
require_once 'config/config.inc.php';
}
else{
require_once 'config/config.inc.php.example';
}
Config::set('base_url', FRONTEND_BASE_PATH);
Config::set('mysql.host', MYSQL_HOST);
Config::set('mysql.user', MYSQL_USER);
Config::set('mysql.password', MYSQL_PASSWORD);
Config::set('mysql.database', MYSQL_DATABASE);
Config::set('schema.tables.users', DBT_USERS);
Config::set('schema.tables.domains', DBT_DOMAINS);
Config::set('schema.tables.aliases', DBT_ALIASES);
Config::set('schema.attributes.users.id', DBC_USERS_ID);
Config::set('schema.attributes.users.username', DBC_USERS_USERNAME);
Config::set('schema.attributes.users.domain', DBC_USERS_DOMAIN);
Config::set('schema.attributes.users.password', DBC_USERS_PASSWORD);
Config::set('schema.attributes.users.mailbox_limit', defined('DBC_USERS_MAILBOXLIMIT') ? DBC_USERS_MAILBOXLIMIT : 'mailbox_limit');
Config::set('schema.attributes.domains.id', DBC_DOMAINS_ID);
Config::set('schema.attributes.domains.domain', DBC_DOMAINS_DOMAIN);
Config::set('schema.attributes.aliases.id', DBC_ALIASES_ID);
Config::set('schema.attributes.aliases.source', DBC_ALIASES_SOURCE);
Config::set('schema.attributes.aliases.destination', DBC_ALIASES_DESTINATION);
Config::set('schema.attributes.aliases.multi_source', defined('DBC_ALIASES_MULTI_SOURCE') ? DBC_ALIASES_MULTI_SOURCE : 'multi_source');
Config::set('options.enable_mailbox_limits', defined('DBC_USERS_MAILBOXLIMIT'));
Config::set('options.enable_validate_aliases_source_domain', defined('VALIDATE_ALIASES_SOURCE_DOMAIN_ENABLED'));
Config::set('options.enable_multi_source_redirects', defined('DBC_ALIASES_MULTI_SOURCE'));
Config::set('options.enable_admin_domain_limits', defined('ADMIN_DOMAIN_LIMITS_ENABLED') ? ADMIN_DOMAIN_LIMITS_ENABLED : false);
Config::set('options.enable_logging', defined('WRITE_LOG') ? WRITE_LOG : false);
Config::set('admins', isset($admins) ? $admins : array());
Config::set('admin_domain_limits', isset($adminDomainLimits) ? $adminDomainLimits : array());
Config::set('password.hash_algorithm', PASS_HASH_SCHEMA);
Config::set('password.min_length', MIN_PASS_LENGTH);
Config::set('log_path', defined('WRITE_LOG_PATH') ? WRITE_LOG_PATH : '/var/www/webmum/log/');
Config::set('frontend_options.email_separator_text', FRONTEND_EMAIL_SEPARATOR_TEXT);
Config::set('frontend_options.email_separator_form', FRONTEND_EMAIL_SEPARATOR_FORM);
}
}
/**
* Establish database connection
*/
Database::init(MYSQL_HOST, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE);
Database::init(Config::get('mysql'));
/**
@ -48,7 +115,6 @@ Database::init(MYSQL_HOST, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE);
*/
Auth::init();
/**
* Setup routes
*/

View file

@ -8,15 +8,15 @@
*/
function writeLog($text)
{
if(defined('WRITE_LOG') && defined('WRITE_LOG_PATH')){
$logdestination = realpath(WRITE_LOG_PATH).DIRECTORY_SEPARATOR."webmum.log";
if(is_writable(WRITE_LOG_PATH)){
if(Config::get('options.enable_logging', false) && Config::has('log_path')){
$logdestination = realpath(Config::get('log_path')).DIRECTORY_SEPARATOR."webmum.log";
if(is_writable(Config::get('log_path'))){
$logfile = fopen($logdestination, "a") or die("Unable to create or open logfile \"".$logdestination."\" in root directory!");
fwrite($logfile, date('M d H:i:s').": ".$text."\n");
fclose($logfile);
}
else{
die("Directory \"".WRITE_LOG_PATH."\" isn't writable");
die("Directory \"".Config::get('log_path')."\" isn't writable");
}
}
}
@ -103,3 +103,21 @@ function formatEmails($input, $glue)
}
function formatEmailsText($input)
{
return formatEmails(
$input,
str_replace(PHP_EOL, '<br>', Config::get('frontend_options.email_separator_text', ', '))
);
}
function formatEmailsForm($input)
{
return strip_tags(
formatEmails(
$input,
Config::get('frontend_options.email_separator_form', ',')
)
);
}

View file

@ -24,26 +24,30 @@ abstract class AbstractModel
*
* @var array
*/
protected $attributeDbAttributeMapping = array();
protected static $attributeDbAttributeMapping = null;
/**
* Setup db attribute mapping
*
* @param array $childMapping
*
* @return array
*
* @throws Exception
* Initialize Model
*/
protected function setupDbMapping($childMapping = array())
abstract protected static function initModel();
/**
* Get mapped db attribute
*
* @param string $name
* @return string
*/
public static function attr($name)
{
return array_replace(
array(
'id' => static::$idAttribute,
),
$childMapping
);
static::initModel();
if(isset(static::$attributeDbAttributeMapping[$name])){
return static::$attributeDbAttributeMapping[$name];
}
return false;
}
@ -75,7 +79,7 @@ abstract class AbstractModel
*/
protected function __construct($data)
{
$this->attributeDbAttributeMapping = $this->setupDbMapping();
static::initModel();
if(isset($data[static::$idAttribute])){
$id = is_numeric($data[static::$idAttribute]) && strpos($data[static::$idAttribute], ',') === false
@ -143,7 +147,9 @@ abstract class AbstractModel
{
$model = static::create($data);
if(!is_null($model) && $model->save()){
if(!is_null($model)){
$model->save();
return $model;
}
@ -304,19 +310,6 @@ abstract class AbstractModel
}
/**
* Find all models
*
* @param array|null $orderBy see helperOrderBy
*
* @return ModelCollection|static[]
*/
public static function findAll($orderBy = null)
{
return static::findWhere(array(), 'AND', $orderBy);
}
/**
* Find models by a condition
*
@ -329,6 +322,8 @@ abstract class AbstractModel
*/
public static function findWhere($conditions = array(), $conditionConnector = 'AND', $orderBy = null, $limit = 0)
{
static::initModel();
$result = Database::getInstance()->select(static::$table, $conditions, $conditionConnector, $orderBy, $limit);
if($limit === 1){
@ -339,6 +334,19 @@ abstract class AbstractModel
}
/**
* Find all models
*
* @param array|null $orderBy see helperOrderBy
*
* @return ModelCollection|static[]
*/
public static function findAll($orderBy = null)
{
return static::findWhere(array(), 'AND', $orderBy);
}
/**
* Find first model matching a condition
*
@ -363,6 +371,8 @@ abstract class AbstractModel
*/
public static function find($id)
{
static::initModel();
return static::findWhereFirst(array(static::$idAttribute, $id));
}
@ -375,7 +385,7 @@ abstract class AbstractModel
$data = $this->preSave($this->data);
$values = array();
foreach($this->attributeDbAttributeMapping as $attribute => $sqlAttribute){
foreach(static::$attributeDbAttributeMapping as $attribute => $sqlAttribute){
if($sqlAttribute === static::$idAttribute){
continue;
}
@ -421,6 +431,8 @@ abstract class AbstractModel
*/
public static function countWhere($conditions = array(), $conditionConnector = 'AND')
{
static::initModel();
return Database::getInstance()->count(static::$table, static::$idAttribute, $conditions, $conditionConnector);
}

View file

@ -4,15 +4,29 @@ abstract class AbstractRedirect extends AbstractModel
{
use DomainLimitTrait;
/**
* @inheritdoc
*/
public static $table = DBT_ALIASES;
/**
* @inheritdoc
* Db table for find methods
*
* @var string
*/
public static $idAttribute = DBC_ALIASES_ID;
public static $table;
/**
* Db id attribute for find methods
*
* @var string
*/
public static $idAttribute;
/**
* Mapping model attributes and database attributes for saving
*
* @var array
*/
protected static $attributeDbAttributeMapping = null;
/**
@ -24,21 +38,19 @@ abstract class AbstractRedirect extends AbstractModel
/**
* @inheritdoc
*/
protected function setupDbMapping($childMapping = array())
protected static function initModel()
{
$thisMapping = array(
'source' => DBC_ALIASES_SOURCE,
'destination' => DBC_ALIASES_DESTINATION,
);
if(is_null(static::$attributeDbAttributeMapping)){
static::$table = Config::get('schema.tables.aliases', 'aliases');
static::$idAttribute = Config::get('schema.attributes.aliases.id', 'id');
if(defined('DBC_ALIASES_MULTI_SOURCE')){
$thisMapping['multiHash'] = DBC_ALIASES_MULTI_SOURCE;
static::$attributeDbAttributeMapping = array(
'id' => Config::get('schema.attributes.aliases.id', 'id'),
'source' => Config::get('schema.attributes.aliases.source', 'source'),
'destination' => Config::get('schema.attributes.aliases.destination', 'destination'),
'multi_hash' => Config::get('schema.attributes.aliases.multi_source', 'multi_source'),
);
}
return array_replace(
parent::setupDbMapping($thisMapping),
$childMapping
);
}
@ -63,8 +75,8 @@ abstract class AbstractRedirect extends AbstractModel
{
parent::__construct($data);
$source = stringToEmails($data[DBC_ALIASES_SOURCE]);
$destination = stringToEmails($data[DBC_ALIASES_DESTINATION]);
$source = stringToEmails($data[static::attr('source')]);
$destination = stringToEmails($data[static::attr('destination')]);
if(get_called_class() === 'Alias' || get_called_class() === 'Redirect'){
$source = $source[0];
@ -77,8 +89,8 @@ abstract class AbstractRedirect extends AbstractModel
$this->setSource($source);
$this->setDestination($destination);
if(defined('DBC_ALIASES_MULTI_SOURCE')){
$this->setMultiHash($data[DBC_ALIASES_MULTI_SOURCE]);
if(Config::get('options.enable_multi_source_redirects', false)){
$this->setMultiHash($data[static::attr('multi_hash')]);
}
}
@ -92,13 +104,13 @@ abstract class AbstractRedirect extends AbstractModel
return parent::create($data);
}
$hasMultipleSources = array_key_exists(DBC_ALIASES_SOURCE, $data)
&& strpos($data[DBC_ALIASES_SOURCE], ',') !== false;
$hasMultipleSources = array_key_exists(static::attr('source'), $data)
&& strpos($data[static::attr('source')], ',') !== false;
$hasMultipleDestinations = array_key_exists(DBC_ALIASES_DESTINATION, $data)
&& strpos($data[DBC_ALIASES_DESTINATION], ',') !== false;
$hasMultipleDestinations = array_key_exists(static::attr('destination'), $data)
&& strpos($data[static::attr('destination')], ',') !== false;
if(defined('DBC_ALIASES_MULTI_SOURCE') && $hasMultipleSources
if(Config::get('options.enable_multi_source_redirects', false) && $hasMultipleSources
){
if($hasMultipleDestinations){
return MultiRedirect::create($data);
@ -168,7 +180,7 @@ abstract class AbstractRedirect extends AbstractModel
*/
public function getMultiHash()
{
return $this->getAttribute('multiHash');
return $this->getAttribute('multi_hash');
}
@ -177,7 +189,7 @@ abstract class AbstractRedirect extends AbstractModel
*/
public function setMultiHash($value)
{
$this->setAttribute('multiHash', $value);
$this->setAttribute('multi_hash', $value);
}
@ -256,8 +268,12 @@ abstract class AbstractRedirect extends AbstractModel
/**
* @inheritdoc
*/
public static function findAll($orderBy = array(DBC_ALIASES_SOURCE))
public static function findAll($orderBy = null)
{
if(is_null($orderBy)){
$orderBy = array(static::attr('source'));
}
return parent::findAll($orderBy);
}
@ -267,24 +283,24 @@ abstract class AbstractRedirect extends AbstractModel
*/
private static function generateRedirectBaseQuery()
{
if(defined('DBC_ALIASES_MULTI_SOURCE')){
if(Config::get('options.enable_multi_source_redirects', false)){
return "SELECT r.* FROM (
SELECT
GROUP_CONCAT(g.`".static::$idAttribute."` ORDER BY g.`".static::$idAttribute."` SEPARATOR ',') AS `".static::$idAttribute."`,
GROUP_CONCAT(g.`".DBC_ALIASES_SOURCE."` SEPARATOR ',') AS `".DBC_ALIASES_SOURCE."`,
g.`".DBC_ALIASES_DESTINATION."`,
g.`".DBC_ALIASES_MULTI_SOURCE."`
GROUP_CONCAT(g.`".static::attr('source')."` SEPARATOR ',') AS `".static::attr('source')."`,
g.`".static::attr('destination')."`,
g.`".static::attr('multi_hash')."`
FROM `".static::$table."` AS g
WHERE g.`".DBC_ALIASES_MULTI_SOURCE."` IS NOT NULL
GROUP BY g.`".DBC_ALIASES_MULTI_SOURCE."`
WHERE g.`".static::attr('multi_hash')."` IS NOT NULL
GROUP BY g.`".static::attr('multi_hash')."`
UNION
SELECT
s.`".DBC_ALIASES_ID."`,
s.`".DBC_ALIASES_SOURCE."`,
s.`".DBC_ALIASES_DESTINATION."`,
s.`".DBC_ALIASES_MULTI_SOURCE."`
s.`".static::$idAttribute."`,
s.`".static::attr('source')."`,
s.`".static::attr('destination')."`,
s.`".static::attr('multi_hash')."`
FROM `".static::$table."` AS s
WHERE s.`".DBC_ALIASES_MULTI_SOURCE."` IS NULL
WHERE s.`".static::attr('multi_hash')."` IS NULL
) AS r";
}
else{
@ -293,8 +309,14 @@ UNION
}
public static function findMultiAll($orderBy = array(DBC_ALIASES_SOURCE))
public static function findMultiAll($orderBy = null)
{
static::initModel();
if(is_null($orderBy)){
$orderBy = array(static::attr('source'));
}
$sql = static::generateRedirectBaseQuery()
.Database::helperOrderBy($orderBy);
@ -325,6 +347,8 @@ UNION
public static function findMulti($id)
{
static::initModel();
return static::findMultiWhereFirst(array(static::$idAttribute, $id));
}

View file

@ -4,30 +4,45 @@ class Domain extends AbstractModel
{
use DomainLimitTrait;
/**
* @inheritdoc
*/
public static $table = DBT_DOMAINS;
/**
* @inheritdoc
* Db table for find methods
*
* @var string
*/
public static $idAttribute = DBC_DOMAINS_ID;
public static $table;
/**
* Db id attribute for find methods
*
* @var string
*/
public static $idAttribute;
/**
* Mapping model attributes and database attributes for saving
*
* @var array
*/
protected static $attributeDbAttributeMapping = null;
/**
* @inheritdoc
*/
protected function setupDbMapping($childMapping = array())
protected static function initModel()
{
return array_replace(
parent::setupDbMapping(
array(
'domain' => DBC_DOMAINS_DOMAIN,
)
),
$childMapping
);
if(is_null(static::$attributeDbAttributeMapping)){
static::$table = Config::get('schema.tables.domains', 'domains');
static::$idAttribute = Config::get('schema.attributes.domains.id', 'id');
static::$attributeDbAttributeMapping = array(
'id' => Config::get('schema.attributes.domains.id', 'id'),
'domain' => Config::get('schema.attributes.domains.domain', 'domain'),
);
}
}
@ -38,7 +53,7 @@ class Domain extends AbstractModel
{
parent::__construct($data);
$this->setDomain($data[DBC_DOMAINS_DOMAIN]);
$this->setDomain($data[static::attr('domain')]);
}
@ -65,7 +80,9 @@ class Domain extends AbstractModel
*/
public function countUsers()
{
return User::countWhere(array(DBC_USERS_DOMAIN, $this->getDomain()));
return User::countWhere(
array(User::attr('domain'), $this->getDomain())
);
}
@ -74,7 +91,9 @@ class Domain extends AbstractModel
*/
public function countRedirects()
{
return AbstractRedirect::countWhere(array(DBC_ALIASES_SOURCE, 'LIKE', "%@{$this->getDomain()}%"));
return AbstractRedirect::countWhere(
array(AbstractRedirect::attr('source'), 'LIKE', "%@{$this->getDomain()}%")
);
}
}

View file

@ -9,7 +9,7 @@ trait DomainLimitTrait
*/
public function isInLimitedDomains($limitedBy = null)
{
if(!defined('ADMIN_DOMAIN_LIMITS_ENABLED')) {
if(!Config::get('options.enable_admin_domain_limits', false)) {
return true;
}
if(is_null($limitedBy)){
@ -17,7 +17,7 @@ trait DomainLimitTrait
}
elseif($limitedBy instanceof User) {
/** @var User $limitedBy */
return $limitedBy->isDomainLimited() && static::isInLimitedDomains($limitedBy->getDomainLimits());
return !$limitedBy->isDomainLimited() || static::isInLimitedDomains($limitedBy->getDomainLimits());
}
if(!is_array($limitedBy)){
@ -51,6 +51,7 @@ trait DomainLimitTrait
{
return $collection->searchAll(function($model) use ($limitedBy){
/** @var static $model */
//var_dump($model->isInLimitedDomains($limitedBy), $model->getDomain());
return $model->isInLimitedDomains($limitedBy);
});
}

View file

@ -4,15 +4,29 @@ class User extends AbstractModel
{
use DomainLimitTrait;
/**
* @inheritdoc
*/
public static $table = DBT_USERS;
/**
* @inheritdoc
* Db table for find methods
*
* @var string
*/
public static $idAttribute = DBC_USERS_ID;
public static $table;
/**
* Db id attribute for find methods
*
* @var string
*/
public static $idAttribute;
/**
* Mapping model attributes and database attributes for saving
*
* @var array
*/
protected static $attributeDbAttributeMapping = null;
const ROLE_USER = 'user';
@ -34,22 +48,20 @@ class User extends AbstractModel
/**
* @inheritdoc
*/
protected function setupDbMapping($childMapping = array())
protected static function initModel()
{
$thisMappings = array(
'username' => DBC_USERS_USERNAME,
'domain' => DBC_USERS_DOMAIN,
'password_hash' => DBC_USERS_PASSWORD,
);
if(is_null(static::$attributeDbAttributeMapping)){
static::$table = Config::get('schema.tables.users', 'users');
static::$idAttribute = Config::get('schema.attributes.users.id', 'id');
if(defined('DBC_USERS_MAILBOXLIMIT')){
$thisMappings['mailboxLimit'] = DBC_USERS_MAILBOXLIMIT;
static::$attributeDbAttributeMapping = array(
'id' => Config::get('schema.attributes.users.id', 'id'),
'username' => Config::get('schema.attributes.users.username', 'username'),
'domain' => Config::get('schema.attributes.users.domain', 'domain'),
'password_hash' => Config::get('schema.attributes.users.password', 'password'),
'mailbox_limit' => Config::get('schema.attributes.users.mailbox_limit'),
);
}
return array_replace(
parent::setupDbMapping($thisMappings),
$childMapping
);
}
@ -60,10 +72,13 @@ class User extends AbstractModel
{
parent::__construct($data);
$this->setUsername($data[DBC_USERS_USERNAME]);
$this->setDomain($data[DBC_USERS_DOMAIN]);
$this->setPasswordHash($data[DBC_USERS_PASSWORD]);
$this->setMailboxLimit(defined('DBC_USERS_MAILBOXLIMIT') ? intval($data[DBC_USERS_MAILBOXLIMIT]) : 0);
$this->setUsername($data[static::attr('username')]);
$this->setDomain($data[static::attr('domain')]);
$this->setPasswordHash($data[static::attr('password_hash')]);
$this->setMailboxLimit(Config::get('options.enable_mailbox_limits', false)
? intval($data[static::attr('mailbox_limit')])
: 0
);
$this->setAttribute('role', static::getRoleByEmail($this->getEmail()));
}
@ -137,7 +152,7 @@ class User extends AbstractModel
*/
public function getMailboxLimit()
{
return $this->getAttribute('mailboxLimit');
return $this->getAttribute('mailbox_limit');
}
@ -146,7 +161,7 @@ class User extends AbstractModel
*/
public function setMailboxLimit($value)
{
$this->setAttribute('mailboxLimit', $value);
$this->setAttribute('mailbox_limit', $value);
}
@ -157,9 +172,11 @@ class User extends AbstractModel
*/
public static function getMailboxLimitDefault()
{
if(defined('DBC_USERS_MAILBOXLIMIT')){
static::initModel();
$sql = "SELECT DEFAULT(".DBC_USERS_MAILBOXLIMIT.") FROM `".static::$table."` LIMIT 1";
if(Config::get('options.enable_mailbox_limits', false)){
$sql = "SELECT DEFAULT(".static::attr('mailbox_limit').") FROM `".static::$table."` LIMIT 1";
$result = Database::getInstance()->query($sql);
@ -190,9 +207,7 @@ class User extends AbstractModel
*/
private static function getRoleByEmail($email)
{
global $admins;
if(in_array($email, $admins)){
if(in_array($email, Config::get('admins', array()))){
return static::ROLE_ADMIN;
}
@ -207,10 +222,10 @@ class User extends AbstractModel
*/
public function isDomainLimited()
{
global $adminDomainLimits;
$adminDomainLimits = Config::get('admin_domain_limits', array());
return defined('ADMIN_DOMAIN_LIMITS_ENABLED')
&& isset($adminDomainLimits) && isset($adminDomainLimits[$this->getEmail()]);
return Config::get('options.enable_admin_domain_limits', false)
&& is_array($adminDomainLimits) && isset($adminDomainLimits[$this->getEmail()]);
}
@ -221,9 +236,9 @@ class User extends AbstractModel
*/
public function getDomainLimits()
{
global $adminDomainLimits;
if($this->isDomainLimited()){
$adminDomainLimits = Config::get('admin_domain_limits', array());
if(!is_array($adminDomainLimits[$this->getEmail()])){
throw new InvalidArgumentException('Config value of admin domain limits for email "'.$this->getEmail().'" needs to be of type array.');
}
@ -242,7 +257,7 @@ class User extends AbstractModel
{
if(is_null($this->conflictingRedirect)){
$this->conflictingRedirect = AbstractRedirect::findWhereFirst(
array(DBC_ALIASES_SOURCE, $this->getEmail())
array(AbstractRedirect::attr('source'), $this->getEmail())
);
}
@ -257,7 +272,7 @@ class User extends AbstractModel
{
if(is_null($this->redirects)){
$this->redirects = AbstractRedirect::findMultiWhere(
array(DBC_ALIASES_DESTINATION, 'LIKE', '%'.$this->getEmail().'%')
array(AbstractRedirect::attr('destination'), 'LIKE', '%'.$this->getEmail().'%')
);
}
@ -306,8 +321,12 @@ class User extends AbstractModel
/**
* @inheritdoc
*/
public static function findAll($orderBy = array(DBC_USERS_DOMAIN, DBC_USERS_USERNAME))
public static function findAll($orderBy = null)
{
if(is_null($orderBy)){
$orderBy = array(static::attr('domain'), static::attr('username'));
}
return parent::findAll($orderBy);
}
@ -315,7 +334,7 @@ class User extends AbstractModel
/**
* @param string $email
*
* @return static|null
* @return User|null
*/
public static function findByEmail($email)
{
@ -328,8 +347,8 @@ class User extends AbstractModel
return static::findWhereFirst(
array(
array('username', $username),
array('domain', $domain)
array(static::attr('username'), $username),
array(static::attr('domain'), $domain)
)
);
}

View file

@ -9,13 +9,13 @@ if(isset($_POST['domain'])){
if(!empty($inputDomain)){
$existingDomain = Domain::findWhere(array(DBC_DOMAINS_DOMAIN, $inputDomain));
$existingDomain = Domain::findWhere(array(Domain::attr('domain'), $inputDomain));
if(!is_null($existingDomain)){
Domain::createAndSave(
array(
DBC_DOMAINS_DOMAIN => $inputDomain,
Domain::attr('domain') => $inputDomain,
)
);

View file

@ -31,7 +31,7 @@ if(isset($_POST['confirm'])){
// Check if admin domain is affected
$isAdminDomain = false;
foreach($admins as $admin){
foreach(Config::get('admins', array()) as $admin){
$parts = explode("@", $admin);
if(count($parts) === 2 && $parts[2] === $domain->getDomain()){
$isAdminDomain = true;
@ -41,7 +41,7 @@ if(isset($_POST['confirm'])){
if(!$isAdminDomain){
$users = User::findWhere(array(DBC_USERS_DOMAIN, $domain->getDomain()));
$users = User::findWhere(array(User::attr('domain'), $domain->getDomain()));
/** @var User $user */
foreach($users as $user){

View file

@ -28,7 +28,7 @@ if(isset($_POST['confirm'])){
// Get single source rows of multi source redirect/alias instead
$hash = $redirect->getMultiHash();
$singleRedirects = AbstractRedirect::findWhere(array(DBC_ALIASES_MULTI_SOURCE, $hash));
$singleRedirects = AbstractRedirect::findWhere(array(AbstractRedirect::attr('multi_hash'), $hash));
/** @var AbstractRedirect $redirectToDelete */
foreach($singleRedirects as $redirectToDelete){
@ -60,12 +60,12 @@ else{
<form class="form" action="" method="post" autocomplete="off">
<div class="input-group">
<label>Source</label>
<div class="input-info"><?php echo formatEmails($redirect->getSource(), str_replace(PHP_EOL, '<br>', FRONTEND_EMAIL_SEPARATOR_TEXT)); ?></div>
<div class="input-info"><?php echo formatEmailsText($redirect->getSource()); ?></div>
</div>
<div class="input-group">
<label>Destination</label>
<div class="input-info"><?php echo formatEmails($redirect->getDestination(), str_replace(PHP_EOL, '<br>', FRONTEND_EMAIL_SEPARATOR_TEXT)); ?></div>
<div class="input-info"><?php echo formatEmailsText($redirect->getDestination()); ?></div>
</div>
<div class="input-group">

View file

@ -25,7 +25,7 @@ if(isset($_POST['confirm'])){
if($confirm === "yes"){
// Check if admin is affected
if(!in_array($user->getEmail(), $admins)){
if(!in_array($user->getEmail(), Config::get('admins', array()))){
$user->delete();

View file

@ -36,7 +36,7 @@ if(isset($_POST['savemode'])){
}
// validate source emails are on domains
if(defined('VALIDATE_ALIASES_SOURCE_DOMAIN_ENABLED')){
if(Config::get('options.enable_validate_aliases_source_domain', true)){
$domains = Domain::getByLimitedDomains();
foreach($inputSources as $email){
@ -72,14 +72,14 @@ if(isset($_POST['savemode'])){
if(count($inputSources) > 0 && count($inputDestinations) > 0){
if(defined('DBC_ALIASES_MULTI_SOURCE') && $redirect instanceof AbstractMultiRedirect){
if(Config::get('options.enable_multi_source_redirects', false) && $redirect instanceof AbstractMultiRedirect){
$existingRedirectsToEdit = AbstractRedirect::findWhere(
array(DBC_ALIASES_MULTI_SOURCE, $redirect->getMultiHash())
array(AbstractRedirect::attr('multi_hash'), $redirect->getMultiHash())
);
}
else{
$existingRedirectsToEdit = AbstractRedirect::findWhere(
array(DBC_ALIASES_ID, $redirect->getId())
array(AbstractRedirect::attr('id'), $redirect->getId())
);
}
@ -94,7 +94,7 @@ if(isset($_POST['savemode'])){
if(count($emailsToCheck) > 0){
$existingRedirectsOther = AbstractRedirect::findWhere(
array(
array(DBC_ALIASES_SOURCE, 'IN', $emailsToCheck)
array(AbstractRedirect::attr('source'), 'IN', $emailsToCheck)
)
);
}
@ -140,11 +140,11 @@ if(isset($_POST['savemode'])){
}
else{
$data = array(
DBC_ALIASES_SOURCE => $sourceAddress,
DBC_ALIASES_DESTINATION => emailsToString($inputDestinations),
AbstractRedirect::attr('source') => $sourceAddress,
AbstractRedirect::attr('destination') => emailsToString($inputDestinations),
);
if(defined('DBC_ALIASES_MULTI_SOURCE')){
$data[DBC_ALIASES_MULTI_SOURCE] = $hash;
if(Config::get('options.enable_multi_source_redirects', false)){
$data[AbstractRedirect::attr('multi_hash')] = $hash;
}
AbstractRedirect::createAndSave($data);
@ -169,7 +169,7 @@ if(isset($_POST['savemode'])){
if(count($inputSources) > 0 && count($inputDestinations) > 0){
$existingRedirects = AbstractRedirect::findWhere(
array(DBC_ALIASES_SOURCE, 'IN', $inputSources)
array(AbstractRedirect::attr('source'), 'IN', $inputSources)
);
if($existingRedirects->count() > 0){
@ -184,7 +184,7 @@ if(isset($_POST['savemode'])){
else{
$inputDestination = emailsToString($inputDestinations);
if(defined('DBC_ALIASES_MULTI_SOURCE') && count($inputSources) > 1){
if(AbstractRedirect::attr('multiSource') !== false && count($inputSources) > 1){
$hash = md5(emailsToString($inputSources));
}
else{
@ -193,12 +193,12 @@ if(isset($_POST['savemode'])){
foreach($inputSources as $inputSource){
$data = array(
DBC_ALIASES_SOURCE => $inputSource,
DBC_ALIASES_DESTINATION => $inputDestination,
AbstractRedirect::attr('source') => $inputSource,
AbstractRedirect::attr('destination') => $inputDestination,
);
if(defined('DBC_ALIASES_MULTI_SOURCE')){
$data[DBC_ALIASES_MULTI_SOURCE] = $hash;
if(Config::get('options.enable_multi_source_redirects', false)){
$data[AbstractRedirect::attr('multi_hash')] = $hash;
}
$a = AbstractRedirect::createAndSave($data);
@ -238,7 +238,7 @@ $domains = Domain::getByLimitedDomains();
<?php echo Message::getInstance()->render(); ?>
<?php if(defined('VALIDATE_ALIASES_SOURCE_DOMAIN_ENABLED') && Auth::getUser()->isDomainLimited() && $domains->count() === 0): ?>
<?php if(Config::get('options.enable_validate_aliases_source_domain', true) && Auth::getUser()->isDomainLimited() && $domains->count() === 0): ?>
<div class="notification notification-fail">
You are listed for limited access to domains, but it seems there are no domains listed you can access.
</div>
@ -270,10 +270,10 @@ $domains = Domain::getByLimitedDomains();
<?php endif; ?>
</div>
<div class="input">
<?php if(defined('DBC_ALIASES_MULTI_SOURCE')): ?>
<textarea name="source" placeholder="Source" required autofocus><?php echo formatEmails(isset($_POST['source']) ? strip_tags($_POST['source']) : (is_null($redirect) ? '' : $redirect->getSource()), FRONTEND_EMAIL_SEPARATOR_FORM); ?></textarea>
<?php if(Config::get('options.enable_multi_source_redirects', false)): ?>
<textarea name="source" placeholder="Source" required autofocus><?php echo formatEmailsForm(isset($_POST['source']) ? $_POST['source'] : (is_null($redirect) ? '' : $redirect->getSource())); ?></textarea>
<?php else: ?>
<input type="text" name="source" placeholder="Source (single address)" required autofocus value="<?php echo strip_tags(formatEmails(isset($_POST['source']) ? $_POST['source'] : (is_null($redirect) ? '' : $redirect->getSource()), FRONTEND_EMAIL_SEPARATOR_FORM)); ?>"/>
<input type="text" name="source" placeholder="Source (single address)" required autofocus value="<?php echo formatEmailsForm(isset($_POST['source']) ? $_POST['source'] : (is_null($redirect) ? '' : $redirect->getSource())); ?>"/>
<?php endif; ?>
</div>
</div>
@ -281,7 +281,7 @@ $domains = Domain::getByLimitedDomains();
<div class="input-group">
<label for="destination">Destination</label>
<div class="input">
<textarea name="destination" placeholder="Destination" required><?php echo formatEmails(isset($_POST['destination']) ? strip_tags($_POST['destination']) : (is_null($redirect) ? '' : $redirect->getDestination()), FRONTEND_EMAIL_SEPARATOR_FORM); ?></textarea>
<textarea name="destination" placeholder="Destination" required><?php echo formatEmailsForm(isset($_POST['destination']) ? $_POST['destination'] : (is_null($redirect) ? '' : $redirect->getDestination())); ?></textarea>
</div>
</div>

View file

@ -12,7 +12,7 @@ if(!is_null($saveMode)){
$inputPasswordRepeated = isset($_POST['password_repeat']) ? $_POST['password_repeat'] : null;
$inputMailboxLimit = null;
if(defined('DBC_USERS_MAILBOXLIMIT')){
if(Config::get('options.enable_mailbox_limits', false)){
$inputMailboxLimit = isset($_POST['mailbox_limit']) ? intval($_POST['mailbox_limit']) : $mailboxLimitDefault;
if(!$inputMailboxLimit === 0 && empty($inputMailboxLimit)){
$inputMailboxLimit = $mailboxLimitDefault;
@ -41,7 +41,7 @@ if(!is_null($saveMode)){
Router::redirect("admin/listusers/?missing-permission=1");
}
if(defined('DBC_USERS_MAILBOXLIMIT') && !is_null($inputMailboxLimit)){
if(Config::get('options.enable_mailbox_limits', false) && !is_null($inputMailboxLimit)){
$userToEdit->setMailboxLimit($inputMailboxLimit);
}
@ -79,7 +79,7 @@ if(!is_null($saveMode)){
/** @var Domain $selectedDomain */
$selectedDomain = Domain::findWhereFirst(
array(DBC_DOMAINS_DOMAIN, $inputDomain)
array(Domain::attr('domain'), $inputDomain)
);
if(!is_null($selectedDomain)){
@ -91,8 +91,8 @@ if(!is_null($saveMode)){
/** @var User $user */
$user = User::findWhereFirst(
array(
array(DBC_USERS_USERNAME, $inputUsername),
array(DBC_USERS_DOMAIN, $selectedDomain->getDomain()),
array(User::attr('username'), $inputUsername),
array(User::attr('domain'), $selectedDomain->getDomain()),
)
);
@ -103,13 +103,13 @@ if(!is_null($saveMode)){
Auth::validateNewPassword($inputPassword, $inputPasswordRepeated);
$data = array(
DBC_USERS_USERNAME => $inputUsername,
DBC_USERS_DOMAIN => $selectedDomain->getDomain(),
DBC_USERS_PASSWORD => Auth::generatePasswordHash($inputPassword)
User::attr('username') => $inputUsername,
User::attr('domain') => $selectedDomain->getDomain(),
User::attr('password_hash') => Auth::generatePasswordHash($inputPassword)
);
if(defined('DBC_USERS_MAILBOXLIMIT') && !is_null($inputMailboxLimit)){
$data[DBC_USERS_MAILBOXLIMIT] = $inputMailboxLimit;
if(Config::get('options.enable_mailbox_limits', false) && !is_null($inputMailboxLimit)){
$data[User::attr('mailbox_limit')] = $inputMailboxLimit;
}
/** @var User $user */
@ -206,22 +206,24 @@ if(isset($_GET['id'])){
<div class="input-group">
<label for="password">Password</label>
<div class="input-info">The new password must be at least <?php echo MIN_PASS_LENGTH; ?> characters long.</div>
<?php if(Config::has('password.min_length')): ?>
<div class="input-info">The new password must be at least <?php echo Config::get('password.min_length'); ?> characters long.</div>
<?php endif; ?>
<div class="input input-action">
<input type="password" name="password" placeholder="New password" <?php echo ($mode === "create") ? 'required' : ''; ?> minlength="<?php echo MIN_PASS_LENGTH; ?>"/>
<input type="password" name="password" placeholder="New password" <?php echo ($mode === "create") ? 'required' : ''; ?> minlength="<?php echo Config::get('password.min_length', 0); ?>"/>
<button type="button" class="button" onclick="pass=generatePassword();this.form.password.value=pass;this.form.password_repeat.value=pass;this.form.password.type='text';this.form.password_repeat.type='text'">Generate password</button>
</div>
<div class="input">
<input type="password" name="password_repeat" placeholder="Repeat password" <?php echo ($mode === "create") ? 'required' : ''; ?> minlength="<?php echo MIN_PASS_LENGTH; ?>"/>
<input type="password" name="password_repeat" placeholder="Repeat password" <?php echo ($mode === "create") ? 'required' : ''; ?> minlength="<?php echo Config::get('password.min_length', 0); ?>"/>
</div>
</div>
<?php if(defined('DBC_USERS_MAILBOXLIMIT')): ?>
<?php if(Config::get('options.enable_mailbox_limits', false)): ?>
<div class="input-group">
<label>Mailbox limit</label>
<div class="input-info">The default limit is <?php echo $mailboxLimitDefault; ?> MB. Limit set to 0 means no limit in size.</div>
<div class="input input-labeled input-labeled-right">
<input name="mailbox_limit" type="number" value="<?php echo isset($_POST['mailbox_limit']) ? strip_tags($_POST['mailbox_limit']) : ((isset($user) && defined('DBC_USERS_MAILBOXLIMIT')) ? $user->getMailboxLimit() : $mailboxLimitDefault); ?>" placeholder="Mailbox limit in MB" min="0" required/>
<input name="mailbox_limit" type="number" value="<?php echo isset($_POST['mailbox_limit']) ? strip_tags($_POST['mailbox_limit']) : ((isset($user) && Config::get('options.enable_mailbox_limits', false)) ? $user->getMailboxLimit() : $mailboxLimitDefault); ?>" placeholder="Mailbox limit in MB" min="0" required/>
<span class="input-label">MB</span>
</div>
</div>

View file

@ -48,9 +48,9 @@ $redirects = AbstractRedirect::getMultiByLimitedDomains();
<?php if($redirect->getConflictingUsers()->count() > 0): ?>
<strong><?php echo $redirect->getConflictingUsers()->count() === 1 ? 'The marked redirect overrides a mailbox.' : 'The marked redirects override mailboxes.'; ?></strong><br>
<?php endif; ?>
<?php echo formatEmails($redirect->getConflictingMarkedSource(), str_replace(PHP_EOL, '<br>', FRONTEND_EMAIL_SEPARATOR_TEXT)); ?>
<?php echo formatEmailsText($redirect->getConflictingMarkedSource()); ?>
</td>
<td><?php echo formatEmails($redirect->getDestination(), str_replace(PHP_EOL, '<br>', FRONTEND_EMAIL_SEPARATOR_TEXT)); ?></td>
<td><?php echo formatEmailsText($redirect->getDestination()); ?></td>
<td>
<a href="<?php echo Router::url('admin/editredirect/?id='.$redirect->getId()); ?>">[Edit]</a>
</td>

View file

@ -40,7 +40,7 @@ $users = User::getByLimitedDomains();
<tr>
<th>Username</th>
<th>Domain</th>
<?php if(defined('DBC_USERS_MAILBOXLIMIT')): ?>
<?php if(Config::get('options.enable_mailbox_limits', false)): ?>
<th>Mailbox Limit</th>
<?php endif; ?>
<th>Redirect count</th>
@ -59,7 +59,7 @@ $users = User::getByLimitedDomains();
<?php echo $user->getUsername(); ?>
</td>
<td><?php echo $user->getDomain(); ?></td>
<?php if(defined('DBC_USERS_MAILBOXLIMIT')): ?>
<?php if(Config::get('options.enable_mailbox_limits', false)): ?>
<td style="text-align: right"><?php echo ($user->getMailboxLimit() > 0) ? $user->getMailboxLimit().' MB' : 'No limit'; ?></td>
<?php endif; ?>
<td><?php echo $user->getRedirects()->count(); ?></td>

View file

@ -1,7 +1,7 @@
<?php
if(isset($_POST['password']) && isset($_POST['password_repeat'])){
try {
try{
Auth::getUser()->changePassword($_POST['password'], $_POST['password_repeat']);
Message::getInstance()->success("Password changed successfully!");
@ -24,13 +24,15 @@ if(isset($_POST['password']) && isset($_POST['password_repeat'])){
<form class="form" action="" method="post" autocomplete="off">
<div class="input-group">
<label for="password">Password</label>
<div class="input-info">Your new password must be at least <?php echo MIN_PASS_LENGTH; ?> characters long.</div>
<?php if(Config::has('password.min_length')): ?>
<div class="input-info">Your new password must be at least <?php echo Config::get('password.min_length'); ?> characters long.</div>
<?php endif; ?>
<div class="input input-action">
<input type="password" name="password" placeholder="New password" required minlength="<?php echo MIN_PASS_LENGTH; ?>" autofocus/>
<input type="password" name="password" placeholder="New password" required minlength="<?php echo Config::get('password.min_length', 0); ?>" autofocus/>
<button type="button" class="button" onclick="pass=generatePassword();this.form.password.value=pass;this.form.password_repeat.value=pass;this.form.password.type='text';this.form.password_repeat.type='text'">Generate password</button>
</div>
<div class="input">
<input type="password" name="password_repeat" placeholder="Repeat password" required minlength="<?php echo MIN_PASS_LENGTH; ?>"/>
<input type="password" name="password_repeat" placeholder="Repeat password" required minlength="<?php echo Config::get('password.min_length', 0); ?>"/>
</div>
</div>

View file

@ -23,8 +23,8 @@ $redirects = Auth::getUser()->getAnonymizedRedirects();
<tbody>
<?php foreach($redirects as $redirect): /** @var AbstractRedirect $redirect */ ?>
<tr>
<td><?php echo formatEmails($redirect->getSource(), str_replace(PHP_EOL, '<br>', FRONTEND_EMAIL_SEPARATOR_TEXT)); ?></td>
<td><?php echo formatEmails($redirect->getDestination(), str_replace(PHP_EOL, '<br>', FRONTEND_EMAIL_SEPARATOR_TEXT)); ?></td>
<td><?php echo formatEmailsText($redirect->getSource()); ?></td>
<td><?php echo formatEmailsText($redirect->getDestination()); ?></td>
</tr>
<?php endforeach; ?>
</tbody>

View file

@ -3,10 +3,9 @@
<head>
<title>WebMUM</title>
<link rel=stylesheet href="<?php echo Router::url('include/css/style.css'); ?>" type="text/css" media=screen>
<?php if(defined('MIN_PASS_LENGTH')): ?>
<script type="text/javascript">
function generatePassword() {
var length = <?php echo MIN_PASS_LENGTH + 1; ?>,
var length = <?php echo Config::get('password.min_length', 8) + 1; ?>,
charset = "abcdefghijklnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#",
retVal = "";
for (var i = 0, n = charset.length; i < length; ++i) {
@ -15,7 +14,6 @@
return retVal;
}
</script>
<?php endif; ?>
</head>
<body>

View file

@ -11,6 +11,10 @@ require_once 'include/php/default.inc.php';
*/
$content = Router::executeCurrentRequest();
if(defined('USING_OLD_CONFIG') && Auth::hasPermission(User::ROLE_ADMIN) && !Auth::getUser()->isDomainLimited()){
$content = '<div class="notification notification-fail"><strong>Your WebMUM installation is still using the old deprecated config style!</strong><br><br>Please update your config to the new style (an example config can be found in <cite>config.php.example</cite>)<br>and delete your old <cite>config.inc.php</cite> and <cite>config.inc.php.example</cite>.</div>'.$content;
}
echo Router::loadAndBufferOutput(
'include/php/template/layout.php',
array(