Page MenuHomePhorge

No OneTemporary

Size
125 KB
Referenced Files
None
Subscribers
None
diff --git a/program/lib/Roundcube/bootstrap.php b/program/lib/Roundcube/bootstrap.php
index e80165a53..d3f948645 100644
--- a/program/lib/Roundcube/bootstrap.php
+++ b/program/lib/Roundcube/bootstrap.php
@@ -1,492 +1,492 @@
<?php
/**
+-----------------------------------------------------------------------+
| This file is part of the Roundcube webmail client |
| |
| Copyright (C) The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
| |
| CONTENTS: |
| Roundcube Framework Initialization |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
| Author: Aleksander Machniak <alec@alec.pl> |
+-----------------------------------------------------------------------+
*/
/**
* Roundcube Framework Initialization
*
* @package Framework
* @subpackage Core
*/
-$config = array(
+$config = [
'error_reporting' => E_ALL & ~E_NOTICE & ~E_STRICT,
'display_errors' => false,
'log_errors' => true,
// Some users are not using Installer, so we'll check some
// critical PHP settings here. Only these, which doesn't provide
// an error/warning in the logs later. See (#1486307).
'mbstring.func_overload' => 0,
-);
+];
// check these additional ini settings if not called via CLI
if (php_sapi_name() != 'cli') {
- $config += array(
+ $config += [
'suhosin.session.encrypt' => false,
'file_uploads' => true,
'session.auto_start' => false,
'zlib.output_compression' => false,
- );
+ ];
}
foreach ($config as $optname => $optval) {
$ini_optval = filter_var(ini_get($optname), is_bool($optval) ? FILTER_VALIDATE_BOOLEAN : FILTER_VALIDATE_INT);
if ($optval != $ini_optval && @ini_set($optname, $optval) === false) {
$optval = !is_bool($optval) ? $optval : ($optval ? 'On' : 'Off');
$error = "ERROR: Wrong '$optname' option value and it wasn't possible to set it to required value ($optval).\n"
. "Check your PHP configuration (including php_admin_flag).";
if (defined('STDERR')) fwrite(STDERR, $error); else echo $error;
exit(1);
}
}
// framework constants
define('RCUBE_VERSION', '1.5-git');
define('RCUBE_CHARSET', 'UTF-8');
define('RCUBE_TEMP_FILE_PREFIX', 'RCMTEMP');
if (!defined('RCUBE_LIB_DIR')) {
define('RCUBE_LIB_DIR', __DIR__ . '/');
}
if (!defined('RCUBE_INSTALL_PATH')) {
define('RCUBE_INSTALL_PATH', RCUBE_LIB_DIR);
}
if (!defined('RCUBE_CONFIG_DIR')) {
define('RCUBE_CONFIG_DIR', RCUBE_INSTALL_PATH . 'config/');
}
if (!defined('RCUBE_PLUGINS_DIR')) {
define('RCUBE_PLUGINS_DIR', RCUBE_INSTALL_PATH . 'plugins/');
}
if (!defined('RCUBE_LOCALIZATION_DIR')) {
define('RCUBE_LOCALIZATION_DIR', RCUBE_INSTALL_PATH . 'localization/');
}
// set internal encoding for mbstring extension
mb_internal_encoding(RCUBE_CHARSET);
mb_regex_encoding(RCUBE_CHARSET);
// make sure the Roundcube lib directory is in the include_path
$rcube_path = realpath(RCUBE_LIB_DIR . '..');
$sep = PATH_SEPARATOR;
$regexp = "!(^|$sep)" . preg_quote($rcube_path, '!') . "($sep|\$)!";
$path = ini_get('include_path');
if (!preg_match($regexp, $path)) {
set_include_path($path . PATH_SEPARATOR . $rcube_path);
}
// Register autoloader
spl_autoload_register('rcube_autoload');
// set PEAR error handling (will also load the PEAR main class)
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, function($err) { rcube::raise_error($err, true); });
/**
* Similar function as in_array() but case-insensitive with multibyte support.
*
* @param string $needle Needle value
* @param array $heystack Array to search in
*
- * @return boolean True if found, False if not
+ * @return bool True if found, False if not
*/
function in_array_nocase($needle, $haystack)
{
// use much faster method for ascii
if (is_ascii($needle)) {
foreach ((array) $haystack as $value) {
if (strcasecmp($value, $needle) === 0) {
return true;
}
}
}
else {
$needle = mb_strtolower($needle);
foreach ((array) $haystack as $value) {
if ($needle === mb_strtolower($value)) {
return true;
}
}
}
return false;
}
/**
* Parse a human readable string for a number of bytes.
*
* @param string $str Input string
*
* @return float Number of bytes
*/
function parse_bytes($str)
{
if (is_numeric($str)) {
return floatval($str);
}
$bytes = 0;
if (preg_match('/([0-9\.]+)\s*([a-z]*)/i', $str, $regs)) {
$bytes = floatval($regs[1]);
switch (strtolower($regs[2])) {
case 'g':
case 'gb':
$bytes *= 1073741824;
break;
case 'm':
case 'mb':
$bytes *= 1048576;
break;
case 'k':
case 'kb':
$bytes *= 1024;
break;
}
}
return floatval($bytes);
}
/**
* Make sure the string ends with a slash
*
* @param string $str A string
*
* @return string A string ending with a slash
*/
function slashify($str)
{
return unslashify($str) . '/';
}
/**
* Remove slashes at the end of the string
*
* @param string $str A string
*
* @return string A string ending with no slash
*/
function unslashify($str)
{
return rtrim($str, '/');
}
/**
* Returns number of seconds for a specified offset string.
*
* @param string $str String representation of the offset (e.g. 20min, 5h, 2days, 1week)
*
* @return int Number of seconds
*/
function get_offset_sec($str)
{
if (preg_match('/^([0-9]+)\s*([smhdw])/i', $str, $regs)) {
$amount = (int) $regs[1];
$unit = strtolower($regs[2]);
}
else {
$amount = (int) $str;
$unit = 's';
}
switch ($unit) {
case 'w':
$amount *= 7;
case 'd':
$amount *= 24;
case 'h':
$amount *= 60;
case 'm':
$amount *= 60;
}
return $amount;
}
/**
* Create a unix timestamp with a specified offset from now.
*
* @param string $offset_str String representation of the offset (e.g. 20min, 5h, 2days)
* @param int $factor Factor to multiply with the offset
*
* @return int Unix timestamp
*/
function get_offset_time($offset_str, $factor = 1)
{
return time() + get_offset_sec($offset_str) * $factor;
}
/**
* Truncate string if it is longer than the allowed length.
* Replace the middle or the ending part of a string with a placeholder.
*
* @param string $str Input string
* @param int $maxlength Max. length
* @param string $placeholder Replace removed chars with this
* @param bool $ending Set to True if string should be truncated from the end
*
* @return string Abbreviated string
*/
function abbreviate_string($str, $maxlength, $placeholder = '...', $ending = false)
{
$length = mb_strlen($str);
if ($length > $maxlength) {
if ($ending) {
return mb_substr($str, 0, $maxlength) . $placeholder;
}
$placeholder_length = mb_strlen($placeholder);
$first_part_length = floor(($maxlength - $placeholder_length)/2);
$second_starting_location = $length - $maxlength + $first_part_length + $placeholder_length;
$prefix = mb_substr($str, 0, $first_part_length);
$suffix = mb_substr($str, $second_starting_location);
$str = $prefix . $placeholder . $suffix;
}
return $str;
}
/**
* Get all keys from array (recursive).
*
* @param array $array Input array
*
* @return array List of array keys
*/
function array_keys_recursive($array)
{
- $keys = array();
+ $keys = [];
if (!empty($array) && is_array($array)) {
foreach ($array as $key => $child) {
$keys[] = $key;
foreach (array_keys_recursive($child) as $val) {
$keys[] = $val;
}
}
}
return $keys;
}
/**
* Remove all non-ascii and non-word chars except ., -, _
*
* @param string $str A string
* @param bool $css_id The result may be used as CSS identifier
* @param string $replace_with Replacement character
*
* @return string Clean string
*/
function asciiwords($str, $css_id = false, $replace_with = '')
{
$allowed = 'a-z0-9\_\-' . (!$css_id ? '\.' : '');
- return preg_replace("/[^$allowed]/i", $replace_with, $str);
+ return preg_replace("/[^$allowed]+/i", $replace_with, $str);
}
/**
* Check if a string contains only ascii characters
*
* @param string $str String to check
* @param bool $control_chars Includes control characters
*
* @return bool True if the string contains ASCII-only, False otherwise
*/
function is_ascii($str, $control_chars = true)
{
$regexp = $control_chars ? '/[^\x00-\x7F]/' : '/[^\x20-\x7E]/';
return preg_match($regexp, $str) ? false : true;
}
/**
* Compose a valid representation of name and e-mail address
*
* @param string $email E-mail address
* @param string $name Person name
*
* @return string Formatted string
*/
function format_email_recipient($email, $name = '')
{
$email = trim($email);
if ($name && $name != $email) {
// Special chars as defined by RFC 822 need to in quoted string (or escaped).
if (preg_match('/[\(\)\<\>\\\.\[\]@,;:"]/', $name)) {
$name = '"'.addcslashes($name, '"').'"';
}
return "$name <$email>";
}
return $email;
}
/**
* Format e-mail address
*
* @param string $email E-mail address
*
* @return string Formatted e-mail address
*/
function format_email($email)
{
$email = trim($email);
$parts = explode('@', $email);
$count = count($parts);
if ($count > 1) {
$parts[$count-1] = mb_strtolower($parts[$count-1]);
$email = implode('@', $parts);
}
return $email;
}
/**
* Fix version number so it can be used correctly in version_compare()
*
* @param string $version Version number string
*
* @param return Version number string
*/
function version_parse($version)
{
return str_replace(
- array('-stable', '-git'),
- array('.0', '.99'),
+ ['-stable', '-git'],
+ ['.0', '.99'],
$version
);
}
// intl replacement functions
if (!function_exists('idn_to_utf8'))
{
/**
* Convert domain name from IDNA ASCII to Unicode
*
* @param string $domain Domain to convert in an IDNA ASCII-compatible format.
*
* @return string|false Unicode domain, False on failure
*/
function idn_to_utf8($domain)
{
static $idn, $loaded;
if (!$loaded) {
- $idn = new Net_IDNA2(array('version' => '2008'));
+ $idn = new Net_IDNA2(['version' => '2008']);
$loaded = true;
}
if ($idn && $domain && preg_match('/(^|\.)xn--/i', $domain)) {
try {
$domain = $idn->decode($domain);
}
catch (Exception $e) {
return false;
}
}
return $domain;
}
}
if (!function_exists('idn_to_ascii'))
{
/**
* Convert domain name to IDNA ASCII-compatible form Unicode
*
* @param string $domain The domain to convert, which must be UTF-8 encoded
*
* @return string|false The domain name encoded in ASCII-compatible form, False on failure
*/
function idn_to_ascii($domain)
{
static $idn, $loaded;
if (!$loaded) {
- $idn = new Net_IDNA2(array('version' => '2008'));
+ $idn = new Net_IDNA2(['version' => '2008']);
$loaded = true;
}
if ($idn && $domain && preg_match('/[^\x20-\x7E]/', $domain)) {
try {
$domain = $idn->encode($domain);
}
catch (Exception $e) {
return false;
}
}
return $domain;
}
}
/**
* Use PHP5 autoload for dynamic class loading
*
* @param string $classname Class name
*
* @return bool True when the class file has been found
*
* @todo Make Zend, PEAR etc play with this
* @todo Make our classes conform to a more straight forward CS.
*/
function rcube_autoload($classname)
{
if (strpos($classname, 'rcube') === 0) {
$classname = preg_replace('/^rcube_(cache|db|session|spellchecker)_/', '\\1/', $classname);
$classname = 'Roundcube/' . $classname;
}
else if (strpos($classname, 'html_') === 0 || $classname === 'html') {
$classname = 'Roundcube/html';
}
else if (strpos($classname, 'Mail_') === 0) {
$classname = 'Mail/' . substr($classname, 5);
}
else if (strpos($classname, 'Net_') === 0) {
$classname = 'Net/' . substr($classname, 4);
}
else if (strpos($classname, 'Auth_') === 0) {
$classname = 'Auth/' . substr($classname, 5);
}
// Translate PHP namespaces into directories,
// i.e. use \Sabre\VObject; $vcf = VObject\Reader::read(...)
// -> Sabre/VObject/Reader.php
$classname = str_replace('\\', '/', $classname);
if ($fp = @fopen("$classname.php", 'r', true)) {
fclose($fp);
include_once "$classname.php";
return true;
}
return false;
}
diff --git a/program/lib/Roundcube/html.php b/program/lib/Roundcube/html.php
index ef548918a..546c4f731 100644
--- a/program/lib/Roundcube/html.php
+++ b/program/lib/Roundcube/html.php
@@ -1,1023 +1,1029 @@
<?php
/**
+-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client |
| |
| Copyright (C) The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
| |
| PURPOSE: |
| Helper class to create valid XHTML code |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
*/
/**
* Class for HTML code creation
*
* @package Framework
* @subpackage View
*/
class html
{
protected $tagname;
protected $content;
- protected $attrib = array();
- protected $allowed = array();
+ protected $attrib = [];
+ protected $allowed = [];
public static $doctype = 'xhtml';
public static $lc_tags = true;
- public static $common_attrib = array('id','class','style','title','align','unselectable','tabindex','role');
- public static $containers = array('iframe','div','span','p','h1','h2','h3','ul','form','textarea','table','thead','tbody','tr','th','td','style','script','a');
- public static $bool_attrib = array('checked','multiple','disabled','selected','autofocus','readonly','required');
+ public static $common_attrib = ['id','class','style','title','align','unselectable','tabindex','role'];
+ public static $containers = ['iframe','div','span','p','h1','h2','h3','ul','form','textarea','table','thead','tbody','tr','th','td','style','script','a'];
+ public static $bool_attrib = ['checked','multiple','disabled','selected','autofocus','readonly','required'];
/**
* Constructor
*
* @param array $attrib Hash array with tag attributes
*/
- public function __construct($attrib = array())
+ public function __construct($attrib = [])
{
if (is_array($attrib)) {
$this->attrib = $attrib;
}
}
/**
* Return the tag code
*
* @return string The finally composed HTML tag
*/
public function show()
{
return self::tag($this->tagname, $this->attrib, $this->content, array_merge(self::$common_attrib, $this->allowed));
}
/****** STATIC METHODS *******/
/**
* Generic method to create a HTML tag
*
* @param string $tagname Tag name
* @param array $attrib Tag attributes as key/value pairs
* @param string $content Optional Tag content (creates a container tag)
* @param array $allowed List with allowed attributes, omit to allow all
*
* @return string The XHTML tag
*/
- public static function tag($tagname, $attrib = array(), $content = null, $allowed = null)
+ public static function tag($tagname, $attrib = [], $content = null, $allowed = null)
{
if (is_string($attrib)) {
- $attrib = array('class' => $attrib);
+ $attrib = ['class' => $attrib];
}
- $inline_tags = array('a','span','img');
+ $inline_tags = ['a', 'span', 'img'];
$suffix = (isset($attrib['nl']) && $content && $attrib['nl'] && !in_array($tagname, $inline_tags)) ? "\n" : '';
$tagname = self::$lc_tags ? strtolower($tagname) : $tagname;
if (isset($content) || in_array($tagname, self::$containers)) {
$suffix = !empty($attrib['noclose']) ? $suffix : '</' . $tagname . '>' . $suffix;
unset($attrib['noclose'], $attrib['nl']);
return '<' . $tagname . self::attrib_string($attrib, $allowed) . '>' . $content . $suffix;
}
else {
return '<' . $tagname . self::attrib_string($attrib, $allowed) . '>' . $suffix;
}
}
/**
* Return DOCTYPE tag of specified type
*
* @param string $type Document type (html5, xhtml, 'xhtml-trans, xhtml-strict)
*/
public static function doctype($type)
{
- $doctypes = array(
+ $doctypes = [
'html5' => '<!DOCTYPE html>',
'xhtml' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
'xhtml-trans' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
'xhtml-strict' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
- );
+ ];
- if ($doctypes[$type]) {
+ if (!empty($doctypes[$type])) {
self::$doctype = preg_replace('/-\w+$/', '', $type);
return $doctypes[$type];
}
return '';
}
/**
* Derrived method for <div> containers
*
* @param mixed $attr Hash array with tag attributes or string with class name
* @param string $cont Div content
*
* @return string HTML code
* @see html::tag()
*/
public static function div($attr = null, $cont = null)
{
if (is_string($attr)) {
- $attr = array('class' => $attr);
+ $attr = ['class' => $attr];
}
- return self::tag('div', $attr, $cont, array_merge(self::$common_attrib, array('onclick')));
+ return self::tag('div', $attr, $cont, array_merge(self::$common_attrib, ['onclick']));
}
/**
* Derrived method for <p> blocks
*
* @param mixed $attr Hash array with tag attributes or string with class name
* @param string $cont Paragraph content
*
* @return string HTML code
* @see html::tag()
*/
public static function p($attr = null, $cont = null)
{
if (is_string($attr)) {
- $attr = array('class' => $attr);
+ $attr = ['class' => $attr];
}
return self::tag('p', $attr, $cont, self::$common_attrib);
}
/**
* Derrived method to create <img />
*
- * @param mixed $attr Hash array with tag attributes or string with image source (src)
+ * @param string|array $attr Hash array with tag attributes or string with image source (src)
*
* @return string HTML code
* @see html::tag()
*/
public static function img($attr = null)
{
if (is_string($attr)) {
- $attr = array('src' => $attr);
+ $attr = ['src' => $attr];
}
- return self::tag('img', $attr + array('alt' => ''), null, array_merge(self::$common_attrib,
- array('src','alt','width','height','border','usemap','onclick','onerror','onload')));
+ $allowed = ['src','alt','width','height','border','usemap','onclick','onerror','onload'];
+
+ return self::tag('img', $attr + ['alt' => ''], null, array_merge(self::$common_attrib, $allowed));
}
/**
* Derrived method for link tags
*
- * @param mixed $attr Hash array with tag attributes or string with link location (href)
- * @param string $cont Link content
+ * @param string|array $attr Hash array with tag attributes or string with link location (href)
+ * @param string $cont Link content
*
* @return string HTML code
* @see html::tag()
*/
public static function a($attr, $cont)
{
if (is_string($attr)) {
- $attr = array('href' => $attr);
+ $attr = ['href' => $attr];
}
- return self::tag('a', $attr, $cont, array_merge(self::$common_attrib,
- array('href','target','name','rel','onclick','onmouseover','onmouseout','onmousedown','onmouseup')));
+ $allowed = ['href','target','name','rel','onclick','onmouseover','onmouseout','onmousedown','onmouseup'];
+
+ return self::tag('a', $attr, $cont, array_merge(self::$common_attrib, $allowed));
}
/**
* Derrived method for inline span tags
*
- * @param mixed $attr Hash array with tag attributes or string with class name
- * @param string $cont Tag content
+ * @param string|array $attr Hash array with tag attributes or string with class name
+ * @param string $cont Tag content
*
* @return string HTML code
* @see html::tag()
*/
public static function span($attr, $cont)
{
if (is_string($attr)) {
- $attr = array('class' => $attr);
+ $attr = ['class' => $attr];
}
return self::tag('span', $attr, $cont, self::$common_attrib);
}
/**
* Derrived method for form element labels
*
- * @param mixed $attr Hash array with tag attributes or string with 'for' attrib
- * @param string $cont Tag content
+ * @param string|array $attr Hash array with tag attributes or string with 'for' attrib
+ * @param string $cont Tag content
*
* @return string HTML code
* @see html::tag()
*/
public static function label($attr, $cont)
{
if (is_string($attr)) {
- $attr = array('for' => $attr);
+ $attr = ['for' => $attr];
}
- return self::tag('label', $attr, $cont, array_merge(self::$common_attrib,
- array('for','onkeypress')));
+ return self::tag('label', $attr, $cont, array_merge(self::$common_attrib, ['for','onkeypress']));
}
/**
* Derrived method to create <iframe></iframe>
*
- * @param mixed $attr Hash array with tag attributes or string with frame source (src)
- * @param string $cont Tag content
+ * @param string|array $attr Hash array with tag attributes or string with frame source (src)
+ * @param string $cont Tag content
*
* @return string HTML code
* @see html::tag()
*/
public static function iframe($attr = null, $cont = null)
{
if (is_string($attr)) {
- $attr = array('src' => $attr);
+ $attr = ['src' => $attr];
}
- return self::tag('iframe', $attr, $cont, array_merge(self::$common_attrib,
- array('src','name','width','height','border','frameborder','onload','allowfullscreen')));
+ $allowed = ['src','name','width','height','border','frameborder','onload','allowfullscreen'];
+
+ return self::tag('iframe', $attr, $cont, array_merge(self::$common_attrib, $allowed));
}
/**
* Derrived method to create <script> tags
*
- * @param mixed $attr Hash array with tag attributes or string with script source (src)
- * @param string $cont Javascript code to be placed as tag content
+ * @param string|array $attr Hash array with tag attributes or string with script source (src)
+ * @param string $cont Javascript code to be placed as tag content
*
* @return string HTML code
* @see html::tag()
*/
public static function script($attr, $cont = null)
{
if (is_string($attr)) {
- $attr = array('src' => $attr);
+ $attr = ['src' => $attr];
}
if ($cont) {
if (self::$doctype == 'xhtml') {
$cont = "/* <![CDATA[ */\n{$cont}\n/* ]]> */";
}
$cont = "\n{$cont}\n";
}
if (self::$doctype == 'xhtml') {
- $attr += array('type' => 'text/javascript');
+ $attr += ['type' => 'text/javascript'];
}
- return self::tag('script', $attr + array('nl' => true), $cont,
- array_merge(self::$common_attrib, array('src', 'type', 'charset')));
+ return self::tag('script', $attr + ['nl' => true], $cont,
+ array_merge(self::$common_attrib, ['src', 'type', 'charset']));
}
/**
* Derrived method for line breaks
*
* @param array $attrib Associative arry with tag attributes
*
* @return string HTML code
* @see html::tag()
*/
- public static function br($attrib = array())
+ public static function br($attrib = [])
{
return self::tag('br', $attrib);
}
/**
* Create string with attributes
*
* @param array $attrib Associative array with tag attributes
* @param array $allowed List of allowed attributes
*
* @return string Valid attribute string
*/
- public static function attrib_string($attrib = array(), $allowed = null)
+ public static function attrib_string($attrib = [], $allowed = null)
{
if (empty($attrib)) {
return '';
}
- $allowed_f = array_flip((array)$allowed);
- $attrib_arr = array();
+ $allowed_f = array_flip((array) $allowed);
+ $attrib_arr = [];
foreach ($attrib as $key => $value) {
// skip size if not numeric
if ($key == 'size' && !is_numeric($value)) {
continue;
}
// ignore "internal" or empty attributes
if ($key == 'nl' || $value === null) {
continue;
}
// ignore not allowed attributes, except aria-* and data-*
if (!empty($allowed)) {
$is_data_attr = @substr_compare($key, 'data-', 0, 5) === 0;
$is_aria_attr = @substr_compare($key, 'aria-', 0, 5) === 0;
if (!$is_aria_attr && !$is_data_attr && !isset($allowed_f[$key])) {
continue;
}
}
// skip empty eventhandlers
if (preg_match('/^on[a-z]+/', $key) && !$value) {
continue;
}
// attributes with no value
if (in_array($key, self::$bool_attrib)) {
if ($value) {
$value = $key;
if (self::$doctype == 'xhtml') {
$value .= '="' . $value . '"';
}
$attrib_arr[] = $value;
}
}
else {
$attrib_arr[] = $key . '="' . self::quote($value) . '"';
}
}
return count($attrib_arr) ? ' '.implode(' ', $attrib_arr) : '';
}
/**
* Convert a HTML attribute string attributes to an associative array (name => value)
*
* @param string $str Input string
*
* @return array Key-value pairs of parsed attributes
*/
public static function parse_attrib_string($str)
{
- $attrib = array();
+ $attrib = [];
$html = '<html>'
. '<head><meta http-equiv="Content-Type" content="text/html; charset=' . RCUBE_CHARSET . '" /></head>'
. '<body><div ' . rtrim($str, '/ ') . ' /></body>'
. '</html>';
$document = new DOMDocument('1.0', RCUBE_CHARSET);
@$document->loadHTML($html);
if ($node = $document->getElementsByTagName('div')->item(0)) {
foreach ($node->attributes as $name => $attr) {
$attrib[strtolower($name)] = $attr->nodeValue;
}
}
return $attrib;
}
/**
* Replacing specials characters in html attribute value
*
* @param string $str Input string
*
* @return string The quoted string
*/
public static function quote($str)
{
return @htmlspecialchars($str, ENT_COMPAT | ENT_SUBSTITUTE, RCUBE_CHARSET);
}
}
/**
* Class to create an HTML input field
*
* @package Framework
* @subpackage View
*/
class html_inputfield extends html
{
protected $tagname = 'input';
protected $type = 'text';
- protected $allowed = array(
+ protected $allowed = [
'type','name','value','size','tabindex','autocapitalize','required',
'autocomplete','checked','onchange','onclick','disabled','readonly',
'spellcheck','results','maxlength','src','multiple','accept',
'placeholder','autofocus','pattern','oninput'
- );
+ ];
/**
* Object constructor
*
* @param array $attrib Associative array with tag attributes
*/
- public function __construct($attrib = array())
+ public function __construct($attrib = [])
{
if (is_array($attrib)) {
$this->attrib = $attrib;
}
if (!empty($attrib['type'])) {
$this->type = $attrib['type'];
}
}
/**
* Compose input tag
*
* @param string $value Field value
* @param array $attrib Additional attributes to override
*
* @return string HTML output
*/
public function show($value = null, $attrib = null)
{
// overwrite object attributes
if (is_array($attrib)) {
$this->attrib = array_merge($this->attrib, $attrib);
}
// set value attribute
if ($value !== null) {
$this->attrib['value'] = $value;
}
// set type
$this->attrib['type'] = $this->type;
return parent::show();
}
}
/**
* Class to create an HTML password field
*
* @package Framework
* @subpackage View
*/
class html_passwordfield extends html_inputfield
{
protected $type = 'password';
}
/**
* Class to create an hidden HTML input field
*
* @package Framework
* @subpackage View
*/
class html_hiddenfield extends html
{
protected $tagname = 'input';
protected $type = 'hidden';
- protected $allowed = array('type','name','value','onchange','disabled','readonly');
- protected $fields = array();
+ protected $allowed = ['type','name','value','onchange','disabled','readonly'];
+ protected $fields = [];
/**
* Constructor
*
* @param array $attrib Named tag attributes
*/
public function __construct($attrib = null)
{
if (is_array($attrib)) {
$this->add($attrib);
}
}
/**
* Add a hidden field to this instance
*
* @param array $attrib Named tag attributes
*/
public function add($attrib)
{
$this->fields[] = $attrib;
}
/**
* Create HTML code for the hidden fields
*
* @return string Final HTML code
*/
public function show()
{
$out = '';
+
foreach ($this->fields as $attrib) {
- $out .= self::tag($this->tagname, array('type' => $this->type) + $attrib);
+ $out .= self::tag($this->tagname, ['type' => $this->type] + $attrib);
}
return $out;
}
}
/**
* Class to create HTML radio buttons
*
* @package Framework
* @subpackage View
*/
class html_radiobutton extends html_inputfield
{
protected $type = 'radio';
/**
* Get HTML code for this object
*
* @param string $value Value of the checked field
* @param array $attrib Additional attributes to override
*
* @return string HTML output
*/
public function show($value = '', $attrib = null)
{
// overwrite object attributes
if (is_array($attrib)) {
$this->attrib = array_merge($this->attrib, $attrib);
}
// set value attribute
$this->attrib['checked'] = ((string)$value == (string)$this->attrib['value']);
return parent::show();
}
}
/**
* Class to create HTML checkboxes
*
* @package Framework
* @subpackage View
*/
class html_checkbox extends html_inputfield
{
protected $type = 'checkbox';
/**
* Get HTML code for this object
*
* @param string $value Value of the checked field
* @param array $attrib Additional attributes to override
*
* @return string HTML output
*/
public function show($value = '', $attrib = null)
{
// overwrite object attributes
if (is_array($attrib)) {
$this->attrib = array_merge($this->attrib, $attrib);
}
// set value attribute
$this->attrib['checked'] = ((string)$value == (string)$this->attrib['value']);
return parent::show();
}
}
/**
* Class to create HTML button
*
* @package Framework
* @subpackage View
*/
class html_button extends html_inputfield
{
protected $tagname = 'button';
protected $type = 'button';
/**
* Get HTML code for this object
*
* @param string $content Text Content of the button
* @param array $attrib Additional attributes to override
*
* @return string HTML output
*/
public function show($content = '', $attrib = null)
{
// overwrite object attributes
if (is_array($attrib)) {
$this->attrib = array_merge($this->attrib, $attrib);
}
$this->content = $content;
return parent::show();
}
}
/**
* Class to create an HTML textarea
*
* @package Framework
* @subpackage View
*/
class html_textarea extends html
{
protected $tagname = 'textarea';
- protected $allowed = array('name','rows','cols','wrap','tabindex',
- 'onchange','disabled','readonly','spellcheck');
+ protected $allowed = ['name','rows','cols','wrap','tabindex',
+ 'onchange','disabled','readonly','spellcheck'];
/**
* Get HTML code for this object
*
* @param string $value Textbox value
* @param array $attrib Additional attributes to override
*
* @return string HTML output
*/
public function show($value = '', $attrib = null)
{
// overwrite object attributes
if (is_array($attrib)) {
$this->attrib = array_merge($this->attrib, $attrib);
}
// take value attribute as content
if (empty($value) && !empty($this->attrib['value'])) {
$value = $this->attrib['value'];
}
// make shure we don't print the value attribute
if (isset($this->attrib['value'])) {
unset($this->attrib['value']);
}
if (!empty($value) && empty($this->attrib['is_escaped'])) {
$value = self::quote($value);
}
return self::tag($this->tagname, $this->attrib, $value,
array_merge(self::$common_attrib, $this->allowed));
}
}
/**
* Builder for HTML drop-down menus
* Syntax:<pre>
* // create instance. arguments are used to set attributes of select-tag
* $select = new html_select(array('name' => 'fieldname'));
*
* // add one option
* $select->add('Switzerland', 'CH');
*
* // add multiple options
* $select->add(array('Switzerland','Germany'), array('CH','DE'));
*
* // generate pulldown with selection 'Switzerland' and return html-code
* // as second argument the same attributes available to instantiate can be used
* print $select->show('CH');
* </pre>
*
* @package Framework
* @subpackage View
*/
class html_select extends html
{
protected $tagname = 'select';
- protected $options = array();
- protected $allowed = array('name','size','tabindex','autocomplete',
- 'multiple','onchange','disabled','rel');
+ protected $options = [];
+ protected $allowed = ['name','size','tabindex','autocomplete',
+ 'multiple','onchange','disabled','rel'];
/**
* Add a new option to this drop-down
*
* @param mixed $names Option name or array with option names
* @param mixed $values Option value or array with option values
* @param array $attrib Additional attributes for the option entry
*/
- public function add($names, $values = null, $attrib = array())
+ public function add($names, $values = null, $attrib = [])
{
if (is_array($names)) {
foreach ($names as $i => $text) {
- $this->options[] = array('text' => $text, 'value' => $values[$i]) + $attrib;
+ $this->options[] = ['text' => $text, 'value' => $values[$i]] + $attrib;
}
}
else {
- $this->options[] = array('text' => $names, 'value' => $values) + $attrib;
+ $this->options[] = ['text' => $names, 'value' => $values] + $attrib;
}
}
/**
* Get HTML code for this object
*
* @param string $select Value of the selection option
* @param array $attrib Additional attributes to override
*
* @return string HTML output
*/
- public function show($select = array(), $attrib = null)
+ public function show($select = [], $attrib = null)
{
// overwrite object attributes
if (is_array($attrib)) {
$this->attrib = array_merge($this->attrib, $attrib);
}
$this->content = "\n";
- $select = (array)$select;
+ $select = (array) $select;
foreach ($this->options as $option) {
- $attr = array(
+ $attr = [
'value' => $option['value'],
'selected' => (in_array($option['value'], $select, true) ||
- in_array($option['text'], $select, true)) ? 1 : null);
+ in_array($option['text'], $select, true)) ? 1 : null
+ ];
$option_content = $option['text'];
if (empty($this->attrib['is_escaped'])) {
$option_content = self::quote($option_content);
}
- $this->content .= self::tag('option', $attr + $option, $option_content, array('value','label','class','style','title','disabled','selected'));
+ $allowed = ['value','label','class','style','title','disabled','selected'];
+
+ $this->content .= self::tag('option', $attr + $option, $option_content, $allowed);
}
return parent::show();
}
}
/**
* Class to build an HTML table
*
* @package Framework
* @subpackage View
*/
class html_table extends html
{
protected $tagname = 'table';
- protected $allowed = array('id','class','style','width','summary',
- 'cellpadding','cellspacing','border');
+ protected $allowed = ['id','class','style','width','summary',
+ 'cellpadding','cellspacing','border'];
private $header = null;
- private $rows = array();
+ private $rows = [];
private $rowindex = 0;
private $colindex = 0;
/**
* Constructor
*
* @param array $attrib Named tag attributes
*/
- public function __construct($attrib = array())
+ public function __construct($attrib = [])
{
- $default_attrib = self::$doctype == 'xhtml' ? array('border' => '0') : array();
+ $default_attrib = self::$doctype == 'xhtml' ? ['border' => '0'] : [];
$this->attrib = array_merge($attrib, $default_attrib);
if (!empty($attrib['tagname']) && $attrib['tagname'] != 'table') {
$this->tagname = $attrib['tagname'];
$this->allowed = self::$common_attrib;
}
}
/**
* Add a table cell
*
* @param array $attr Cell attributes
* @param string $cont Cell content
*/
public function add($attr, $cont)
{
if (is_string($attr)) {
- $attr = array('class' => $attr);
+ $attr = ['class' => $attr];
}
$cell = new stdClass;
$cell->attrib = $attr;
$cell->content = $cont;
if (!isset($this->rows[$this->rowindex])) {
$this->rows[$this->rowindex] = new stdClass;
$this->rows[$this->rowindex]->attrib = [];
}
$this->rows[$this->rowindex]->cells[$this->colindex] = $cell;
$this->colindex += max(1, isset($attr['colspan']) ? intval($attr['colspan']) : 0);
if (!empty($this->attrib['cols']) && $this->colindex >= $this->attrib['cols']) {
$this->add_row();
}
}
/**
* Add a table header cell
*
- * @param array $attr Cell attributes
- * @param string $cont Cell content
+ * @param string|array $attr Cell attributes array or class name
+ * @param string $cont Cell content
*/
public function add_header($attr, $cont)
{
if (is_string($attr)) {
- $attr = array('class' => $attr);
+ $attr = ['class' => $attr];
}
$cell = new stdClass;
$cell->attrib = $attr;
$cell->content = $cont;
if (empty($this->header)) {
$this->header = new stdClass;
$this->header->attrib = [];
}
$this->header->cells[] = $cell;
}
/**
* Remove a column from a table
* Useful for plugins making alterations
*
* @param string $class Class name
*/
public function remove_column($class)
{
// Remove the header
foreach ($this->header->cells as $index => $header) {
if ($header->attrib['class'] == $class) {
unset($this->header[$index]);
break;
}
}
// Remove cells from rows
foreach ($this->rows as $i => $row) {
foreach ($row->cells as $j => $cell) {
if ($cell->attrib['class'] == $class) {
unset($this->rows[$i]->cells[$j]);
break;
}
}
}
}
/**
* Jump to next row
*
* @param array $attr Row attributes
*/
- public function add_row($attr = array())
+ public function add_row($attr = [])
{
$this->rowindex++;
$this->colindex = 0;
$this->rows[$this->rowindex] = new stdClass;
$this->rows[$this->rowindex]->attrib = $attr;
- $this->rows[$this->rowindex]->cells = array();
+ $this->rows[$this->rowindex]->cells = [];
}
/**
* Set header attributes
*
- * @param array $attr Row attributes
+ * @param string|array $attr Row attributes array or class name
*/
- public function set_header_attribs($attr = array())
+ public function set_header_attribs($attr = [])
{
if (is_string($attr)) {
- $attr = array('class' => $attr);
+ $attr = ['class' => $attr];
}
if (empty($this->header)) {
$this->header = new stdClass;
}
$this->header->attrib = $attr;
}
/**
* Set row attributes
*
- * @param array $attr Row attributes
- * @param int $index Optional row index (default current row index)
+ * @param string|array $attr Row attributes array or class name
+ * @param int $index Optional row index (default current row index)
*/
- public function set_row_attribs($attr = array(), $index = null)
+ public function set_row_attribs($attr = [], $index = null)
{
if (is_string($attr)) {
- $attr = array('class' => $attr);
+ $attr = ['class' => $attr];
}
if ($index === null) {
$index = $this->rowindex;
}
// make sure row object exists (#1489094)
if (empty($this->rows[$index])) {
$this->rows[$index] = new stdClass;
}
$this->rows[$index]->attrib = $attr;
}
/**
* Get row attributes
*
* @param int $index Row index
*
* @return array Row attributes
*/
public function get_row_attribs($index = null)
{
if ($index === null) {
$index = $this->rowindex;
}
return !empty($this->rows[$index]) ? $this->rows[$index]->attrib : null;
}
/**
* Build HTML output of the table data
*
* @param array $attrib Table attributes
*
* @return string The final table HTML code
*/
public function show($attrib = null)
{
if (is_array($attrib)) {
$this->attrib = array_merge($this->attrib, $attrib);
}
$thead = '';
$tbody = '';
$col_tagname = $this->_col_tagname();
$row_tagname = $this->_row_tagname();
$head_tagname = $this->_head_tagname();
// include <thead>
if (!empty($this->header)) {
$rowcontent = '';
foreach ($this->header->cells as $c => $col) {
$rowcontent .= self::tag($head_tagname, $col->attrib, $col->content);
}
$thead = $this->tagname == 'table' ? self::tag('thead', null, self::tag('tr', $this->header->attrib ?: null, $rowcontent, parent::$common_attrib)) :
- self::tag($row_tagname, array('class' => 'thead'), $rowcontent, parent::$common_attrib);
+ self::tag($row_tagname, ['class' => 'thead'], $rowcontent, parent::$common_attrib);
}
foreach ($this->rows as $r => $row) {
$rowcontent = '';
foreach ($row->cells as $c => $col) {
if ($row_tagname == 'li' && empty($col->attrib) && count($row->cells) == 1) {
$rowcontent .= $col->content;
}
else {
$rowcontent .= self::tag($col_tagname, $col->attrib, $col->content);
}
}
if ($r < $this->rowindex || count($row->cells)) {
$tbody .= self::tag($row_tagname, $row->attrib, $rowcontent, parent::$common_attrib);
}
}
if (!empty($this->attrib['rowsonly'])) {
return $tbody;
}
// add <tbody>
$this->content = $thead . ($this->tagname == 'table' ? self::tag('tbody', null, $tbody) : $tbody);
unset($this->attrib['cols'], $this->attrib['rowsonly']);
return parent::show();
}
/**
* Count number of rows
*
* @return int The number of rows
*/
public function size()
{
return count($this->rows);
}
/**
* Remove table body (all rows)
*/
public function remove_body()
{
- $this->rows = array();
+ $this->rows = [];
$this->rowindex = 0;
}
/**
* Getter for the corresponding tag name for table row elements
*/
private function _row_tagname()
{
- static $row_tagnames = array('table' => 'tr', 'ul' => 'li', '*' => 'div');
+ static $row_tagnames = ['table' => 'tr', 'ul' => 'li', '*' => 'div'];
return !empty($row_tagnames[$this->tagname]) ? $row_tagnames[$this->tagname] : $row_tagnames['*'];
}
/**
* Getter for the corresponding tag name for table row elements
*/
private function _head_tagname()
{
- static $head_tagnames = array('table' => 'th', '*' => 'span');
+ static $head_tagnames = ['table' => 'th', '*' => 'span'];
return !empty($head_tagnames[$this->tagname]) ? $head_tagnames[$this->tagname] : $head_tagnames['*'];
}
/**
* Getter for the corresponding tag name for table cell elements
*/
private function _col_tagname()
{
- static $col_tagnames = array('table' => 'td', '*' => 'span');
+ static $col_tagnames = ['table' => 'td', '*' => 'span'];
return !empty($col_tagnames[$this->tagname]) ? $col_tagnames[$this->tagname] : $col_tagnames['*'];
}
}
diff --git a/program/lib/Roundcube/rcube.php b/program/lib/Roundcube/rcube.php
index 1ebb289f2..817824ae6 100644
--- a/program/lib/Roundcube/rcube.php
+++ b/program/lib/Roundcube/rcube.php
@@ -1,1822 +1,1829 @@
<?php
/**
+-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client |
| |
| Copyright (C) The Roundcube Dev Team |
| Copyright (C) Kolab Systems AG |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
| |
| PURPOSE: |
| Framework base class providing core functions and holding |
| instances of all 'global' objects like db- and storage-connections |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
*/
/**
* Base class of the Roundcube Framework
* implemented as singleton
*
* @package Framework
* @subpackage Core
*/
class rcube
{
// Init options
const INIT_WITH_DB = 1;
const INIT_WITH_PLUGINS = 2;
// Request status
const REQUEST_VALID = 0;
const REQUEST_ERROR_URL = 1;
const REQUEST_ERROR_TOKEN = 2;
const DEBUG_LINE_LENGTH = 4096;
/** @var rcube_config Stores instance of rcube_config */
public $config;
/** @var rcube_db Instance of database class */
public $db;
/** @var Memcache Instance of Memcache class */
public $memcache;
/** @var Memcached Instance of Memcached class */
public $memcached;
/** @var Redis Instance of Redis class */
public $redis;
/** @var rcube_session Instance of rcube_session class */
public $session;
/** @var rcube_smtp Instance of rcube_smtp class */
public $smtp;
/** @var rcube_storage Instance of rcube_storage class */
public $storage;
/** @var rcube_output Instance of rcube_output class */
public $output;
/** @var rcube_plugin_api Instance of rcube_plugin_api */
public $plugins;
/** @var rcube_user Instance of rcube_user class */
public $user;
/** @var int Request status */
public $request_status = 0;
/** @var array Localization */
protected $texts;
/** @var rcube_cache[] Initialized cache objects */
- protected $caches = array();
+ protected $caches = [];
/** @var array Registered shutdown functions */
- protected $shutdown_functions = array();
+ protected $shutdown_functions = [];
/** @var rcube Singleton instance of rcube */
static protected $instance;
/**
* This implements the 'singleton' design pattern
*
* @param int $mode Options to initialize with this instance. See rcube::INIT_WITH_* constants
* @param string $env Environment name to run (e.g. live, dev, test)
*
* @return rcube The one and only instance
*/
static function get_instance($mode = 0, $env = '')
{
if (!self::$instance) {
self::$instance = new rcube($env);
self::$instance->init($mode);
}
return self::$instance;
}
/**
* Private constructor
*
* @param string $env Environment name to run (e.g. live, dev, test)
*/
protected function __construct($env = '')
{
// load configuration
$this->config = new rcube_config($env);
$this->plugins = new rcube_dummy_plugin_api;
- register_shutdown_function(array($this, 'shutdown'));
+ register_shutdown_function([$this, 'shutdown']);
}
/**
* Initial startup function
*
* @param int $mode Options to initialize with this instance. See rcube::INIT_WITH_* constants
*/
protected function init($mode = 0)
{
// initialize syslog
if ($this->config->get('log_driver') == 'syslog') {
$syslog_id = $this->config->get('syslog_id', 'roundcube');
$syslog_facility = $this->config->get('syslog_facility', LOG_USER);
openlog($syslog_id, LOG_ODELAY, $syslog_facility);
}
// connect to database
if ($mode & self::INIT_WITH_DB) {
$this->get_dbh();
}
// create plugin API and load plugins
if ($mode & self::INIT_WITH_PLUGINS) {
$this->plugins = rcube_plugin_api::get_instance();
}
}
/**
* Get the current database connection
*
* @return rcube_db Database object
*/
public function get_dbh()
{
if (!$this->db) {
$this->db = rcube_db::factory(
$this->config->get('db_dsnw'),
$this->config->get('db_dsnr'),
$this->config->get('db_persistent')
);
$this->db->set_debug((bool)$this->config->get('sql_debug'));
}
return $this->db;
}
/**
* Get global handle for memcache access
*
* @return object Memcache
*/
public function get_memcache()
{
if (!isset($this->memcache)) {
$this->memcache = rcube_cache_memcache::engine();
}
return $this->memcache;
}
/**
* Get global handle for memcached access
*
* @return object Memcached
*/
public function get_memcached()
{
if (!isset($this->memcached)) {
$this->memcached = rcube_cache_memcached::engine();
}
return $this->memcached;
}
/**
* Get global handle for redis access
*
* @return object Redis
*/
public function get_redis()
{
if (!isset($this->redis)) {
$this->redis = rcube_cache_redis::engine();
}
return $this->redis;
}
/**
* Initialize and get user cache object
*
* @param string $name Cache identifier
* @param string $type Cache type ('db', 'apc', 'memcache', 'redis')
* @param string $ttl Expiration time for cache items
* @param bool $packed Enables/disables data serialization
* @param bool $indexed Use indexed cache
*
* @return rcube_cache|null User cache object
*/
public function get_cache($name, $type = 'db', $ttl = 0, $packed = true, $indexed = false)
{
if (!isset($this->caches[$name]) && ($userid = $this->get_user_id())) {
$this->caches[$name] = rcube_cache::factory($type, $userid, $name, $ttl, $packed, $indexed);
}
return $this->caches[$name];
}
/**
* Initialize and get shared cache object
*
* @param string $name Cache identifier
* @param bool $packed Enables/disables data serialization
*
* @return rcube_cache Shared cache object
*/
public function get_cache_shared($name, $packed = true)
{
$shared_name = "shared_$name";
if (!array_key_exists($shared_name, $this->caches)) {
$opt = strtolower($name) . '_cache';
$type = $this->config->get($opt);
$ttl = $this->config->get($opt . '_ttl');
if (!$type) {
// cache is disabled
return $this->caches[$shared_name] = null;
}
if ($ttl === null) {
$ttl = $this->config->get('shared_cache_ttl', '10d');
}
$this->caches[$shared_name] = rcube_cache::factory($type, null, $name, $ttl, $packed);
}
return $this->caches[$shared_name];
}
/**
* Initialize HTTP client
*
* @param array $options Configuration options
*
* @return \GuzzleHttp\Client HTTP client
*/
public function get_http_client($options = [])
{
return new \GuzzleHttp\Client($options + $this->config->get('http_client'));
}
/**
* Create SMTP object and connect to server
*
* @param boolean $connect True if connection should be established
*/
public function smtp_init($connect = false)
{
$this->smtp = new rcube_smtp();
if ($connect) {
$this->smtp->connect();
}
}
/**
* Initialize and get storage object
*
* @return rcube_storage Storage object
*/
public function get_storage()
{
// already initialized
if (!is_object($this->storage)) {
$this->storage_init();
}
return $this->storage;
}
/**
* Initialize storage object
*/
public function storage_init()
{
// already initialized
if (is_object($this->storage)) {
return;
}
$driver = $this->config->get('storage_driver', 'imap');
$driver_class = "rcube_{$driver}";
if (!class_exists($driver_class)) {
- self::raise_error(array(
- 'code' => 700, 'type' => 'php',
- 'file' => __FILE__, 'line' => __LINE__,
- 'message' => "Storage driver class ($driver) not found!"),
- true, true);
+ self::raise_error([
+ 'code' => 700, 'file' => __FILE__, 'line' => __LINE__,
+ 'message' => "Storage driver class ($driver) not found!"
+ ],
+ true, true
+ );
}
// Initialize storage object
$this->storage = new $driver_class;
// for backward compat. (deprecated, will be removed)
$this->imap = $this->storage;
// set class options
- $options = array(
+ $options = [
'auth_type' => $this->config->get("{$driver}_auth_type", 'check'),
'auth_cid' => $this->config->get("{$driver}_auth_cid"),
'auth_pw' => $this->config->get("{$driver}_auth_pw"),
'debug' => (bool) $this->config->get("{$driver}_debug"),
'force_caps' => (bool) $this->config->get("{$driver}_force_caps"),
'disabled_caps' => $this->config->get("{$driver}_disabled_caps"),
'socket_options' => $this->config->get("{$driver}_conn_options"),
'timeout' => (int) $this->config->get("{$driver}_timeout"),
'skip_deleted' => (bool) $this->config->get('skip_deleted'),
'driver' => $driver,
- );
+ ];
if (!empty($_SESSION['storage_host'])) {
$options['language'] = $_SESSION['language'];
$options['host'] = $_SESSION['storage_host'];
$options['user'] = $_SESSION['username'];
$options['port'] = $_SESSION['storage_port'];
$options['ssl'] = $_SESSION['storage_ssl'];
$options['password'] = $this->decrypt($_SESSION['password']);
$_SESSION[$driver.'_host'] = $_SESSION['storage_host'];
}
$options = $this->plugins->exec_hook("storage_init", $options);
// for backward compat. (deprecated, to be removed)
$options = $this->plugins->exec_hook("imap_init", $options);
$this->storage->set_options($options);
$this->set_storage_prop();
// subscribe to 'storage_connected' hook for session logging
if ($this->config->get('imap_log_session', false)) {
- $this->plugins->register_hook('storage_connected', array($this, 'storage_log_session'));
+ $this->plugins->register_hook('storage_connected', [$this, 'storage_log_session']);
}
}
/**
* Set storage parameters.
*/
protected function set_storage_prop()
{
$storage = $this->get_storage();
// set pagesize from config
$pagesize = $this->config->get('mail_pagesize');
if (!$pagesize) {
$pagesize = $this->config->get('pagesize', 50);
}
$storage->set_pagesize($pagesize);
$storage->set_charset($this->config->get('default_charset', RCUBE_CHARSET));
// enable caching of mail data
$driver = $this->config->get('storage_driver', 'imap');
$storage_cache = $this->config->get("{$driver}_cache");
$messages_cache = $this->config->get('messages_cache');
+
// for backward compatybility
if ($storage_cache === null && $messages_cache === null && $this->config->get('enable_caching')) {
$storage_cache = 'db';
$messages_cache = true;
}
if ($storage_cache) {
$storage->set_caching($storage_cache);
}
+
if ($messages_cache) {
$storage->set_messages_caching(true);
}
}
/**
* Set special folders type association.
* This must be done AFTER connecting to the server!
*/
protected function set_special_folders()
{
$storage = $this->get_storage();
$folders = $storage->get_special_folders(true);
- $prefs = array();
+ $prefs = [];
// check SPECIAL-USE flags on IMAP folders
foreach ($folders as $type => $folder) {
$idx = $type . '_mbox';
if ($folder !== $this->config->get($idx)) {
$prefs[$idx] = $folder;
}
}
// Some special folders differ, update user preferences
if (!empty($prefs) && $this->user) {
$this->user->save_prefs($prefs);
}
// create default folders (on login)
if ($this->config->get('create_default_folders')) {
$storage->create_default_folders();
}
}
/**
* Callback for IMAP connection events to log session identifiers
*
* @param array $args Callback arguments
*/
public function storage_log_session($args)
{
if (!empty($args['session']) && session_id()) {
$this->write_log('imap_session', $args['session']);
}
}
/**
* Create session object and start the session.
*/
public function session_init()
{
// Ignore in CLI mode or when session started (Installer?)
if (empty($_SERVER['REMOTE_ADDR']) || session_id()) {
return;
}
$storage = $this->config->get('session_storage', 'db');
$sess_name = $this->config->get('session_name');
$sess_domain = $this->config->get('session_domain');
$sess_path = $this->config->get('session_path');
$sess_samesite = $this->config->get('session_samesite');
$lifetime = $this->config->get('session_lifetime', 0) * 60;
$is_secure = $this->config->get('use_https') || rcube_utils::https_check();
// set session domain
if ($sess_domain) {
ini_set('session.cookie_domain', $sess_domain);
}
// set session path
if ($sess_path) {
ini_set('session.cookie_path', $sess_path);
}
// set session samesite attribute
// requires PHP >= 7.3.0, see https://wiki.php.net/rfc/same-site-cookie for more info
if (version_compare(PHP_VERSION, '7.3.0', '>=') && $sess_samesite) {
ini_set('session.cookie_samesite', $sess_samesite);
}
// set session garbage collecting time according to session_lifetime
if ($lifetime) {
ini_set('session.gc_maxlifetime', $lifetime * 2);
}
// set session cookie lifetime so it never expires (#5961)
ini_set('session.cookie_lifetime', 0);
ini_set('session.cookie_secure', $is_secure);
ini_set('session.name', $sess_name ?: 'roundcube_sessid');
ini_set('session.use_cookies', 1);
ini_set('session.use_only_cookies', 1);
ini_set('session.cookie_httponly', 1);
// Make sure session garbage collector is enabled when using custom handlers (#6560)
// Note: Use session.gc_divisor to control accuracy
if ($storage != 'php' && !ini_get('session.gc_probability')) {
ini_set('session.gc_probability', 1);
}
// Start the session
$this->session = rcube_session::factory($this->config);
- $this->session->register_gc_handler(array($this, 'gc'));
+ $this->session->register_gc_handler([$this, 'gc']);
$this->session->start();
}
/**
* Garbage collector - cache/temp cleaner
*/
public function gc()
{
rcube_cache::gc();
$this->get_storage()->cache_gc();
$this->gc_temp();
}
/**
* Garbage collector function for temp files.
* Removes temporary files older than temp_dir_ttl.
*/
public function gc_temp()
{
$tmp = unslashify($this->config->get('temp_dir'));
// expire in 48 hours by default
$temp_dir_ttl = $this->config->get('temp_dir_ttl', '48h');
$temp_dir_ttl = get_offset_sec($temp_dir_ttl);
if ($temp_dir_ttl < 6*3600) {
$temp_dir_ttl = 6*3600; // 6 hours sensible lower bound.
}
$expire = time() - $temp_dir_ttl;
if ($tmp && ($dir = opendir($tmp))) {
while (($fname = readdir($dir)) !== false) {
if (strpos($fname, RCUBE_TEMP_FILE_PREFIX) !== 0) {
continue;
}
if (@filemtime("$tmp/$fname") < $expire) {
@unlink("$tmp/$fname");
}
}
closedir($dir);
}
}
/**
* Runs garbage collector with probability based on
* session settings. This is intended for environments
* without a session.
*/
public function gc_run()
{
$probability = (int) ini_get('session.gc_probability');
$divisor = (int) ini_get('session.gc_divisor');
if ($divisor > 0 && $probability > 0) {
$random = mt_rand(1, $divisor);
if ($random <= $probability) {
$this->gc();
}
}
}
/**
* Get localized text in the desired language
*
* @param mixed $attrib Named parameters array or label name
* @param string $domain Label domain (plugin) name
*
* @return string Localized text
*/
public function gettext($attrib, $domain = null)
{
// load localization files if not done yet
if (empty($this->texts)) {
$this->load_language();
}
// extract attributes
if (is_string($attrib)) {
- $attrib = array('name' => $attrib);
+ $attrib = ['name' => $attrib];
}
$name = (string) $attrib['name'];
// attrib contain text values: use them from now
$slang = !empty($_SESSION['language']) ? strtolower($_SESSION['language']) : 'en_us';
if (isset($attrib[$slang])) {
$this->texts[$name] = $attrib[$slang];
}
if ($slang != 'en_us' && isset($attrib['en_us'])) {
$this->texts[$name] = $attrib['en_us'];
}
// check for text with domain
if ($domain && isset($this->texts["$domain.$name"])) {
$text = $this->texts["$domain.$name"];
}
else if (isset($this->texts[$name])) {
$text = $this->texts[$name];
}
// text does not exist
if (!isset($text)) {
return "[$name]";
}
// replace vars in text
if (!empty($attrib['vars']) && is_array($attrib['vars'])) {
foreach ($attrib['vars'] as $var_key => $var_value) {
$text = str_replace($var_key[0] != '$' ? '$'.$var_key : $var_key, $var_value, $text);
}
}
// replace \n with real line break
- $text = strtr($text, array('\n' => "\n"));
+ $text = strtr($text, ['\n' => "\n"]);
// case folding
if ((!empty($attrib['uppercase']) && strtolower($attrib['uppercase']) == 'first') || !empty($attrib['ucfirst'])) {
$case_mode = MB_CASE_TITLE;
}
else if (!empty($attrib['uppercase'])) {
$case_mode = MB_CASE_UPPER;
}
else if (!empty($attrib['lowercase'])) {
$case_mode = MB_CASE_LOWER;
}
if (isset($case_mode)) {
$text = mb_convert_case($text, $case_mode);
}
return $text;
}
/**
* Check if the given text label exists
*
* @param string $name Label name
* @param string $domain Label domain (plugin) name or '*' for all domains
* @param string &$ref_domain Sets domain name if label is found
*
- * @return boolean True if text exists (either in the current language or in en_US)
+ * @return bool True if text exists (either in the current language or in en_US)
*/
public function text_exists($name, $domain = null, &$ref_domain = null)
{
// load localization files if not done yet
if (empty($this->texts)) {
$this->load_language();
}
if (isset($this->texts[$name])) {
$ref_domain = '';
return true;
}
// any of loaded domains (plugins)
if ($domain == '*') {
foreach ($this->plugins->loaded_plugins() as $domain) {
if (isset($this->texts[$domain.'.'.$name])) {
$ref_domain = $domain;
return true;
}
}
}
// specified domain
else if ($domain && isset($this->texts[$domain.'.'.$name])) {
$ref_domain = $domain;
return true;
}
return false;
}
/**
* Load a localization package
*
* @param string $lang Language ID
* @param array $add Additional text labels/messages
* @param array $merge Additional text labels/messages to merge
*/
- public function load_language($lang = null, $add = array(), $merge = array())
+ public function load_language($lang = null, $add = [], $merge = [])
{
$sess_lang = !empty($_SESSION['language']) ? $_SESSION['language'] : 'en_US';
$lang = $this->language_prop($lang ?: $sess_lang);
// load localized texts
if (empty($this->texts) || $lang != $sess_lang) {
// get english labels (these should be complete)
- $files = array(
+ $files = [
RCUBE_LOCALIZATION_DIR . 'en_US/labels.inc',
RCUBE_LOCALIZATION_DIR . 'en_US/messages.inc',
- );
+ ];
// include user language files
if ($lang != 'en' && $lang != 'en_US' && is_dir(RCUBE_LOCALIZATION_DIR . $lang)) {
$files[] = RCUBE_LOCALIZATION_DIR . $lang . '/labels.inc';
$files[] = RCUBE_LOCALIZATION_DIR . $lang . '/messages.inc';
}
- $this->texts = array();
+ $this->texts = [];
foreach ($files as $file) {
$this->texts = self::read_localization_file($file, $this->texts);
}
$_SESSION['language'] = $lang;
}
// append additional texts (from plugin)
if (is_array($add) && !empty($add)) {
$this->texts += $add;
}
// merge additional texts (from plugin)
if (is_array($merge) && !empty($merge)) {
$this->texts = array_merge($this->texts, $merge);
}
}
/**
* Read localized texts from an additional location (plugins, skins).
* Then you can use the result as 2nd arg to load_language().
*
* @param string $dir Directory to search in
* @param string|null $lang Language code to read
*
* @return array Localization labels/messages
*/
public function read_localization($dir, $lang = null)
{
if ($lang == null) {
$lang = $_SESSION['language'];
}
- $langs = array_unique(array('en_US', $lang));
+ $langs = array_unique(['en_US', $lang]);
$locdir = slashify($dir);
- $texts = array();
+ $texts = [];
// Language aliases used to find localization in similar lang, see below
- $aliases = array(
+ $aliases = [
'de_CH' => 'de_DE',
'es_AR' => 'es_ES',
'fa_AF' => 'fa_IR',
'nl_BE' => 'nl_NL',
'pt_BR' => 'pt_PT',
'zh_CN' => 'zh_TW',
- );
+ ];
foreach ($langs as $lng) {
$fpath = $locdir . $lng . '.inc';
$_texts = self::read_localization_file($fpath);
if (!empty($_texts)) {
$texts = array_merge($texts, $_texts);
}
// Fallback to a localization in similar language (#1488401)
else if ($lng != 'en_US') {
$alias = null;
if (!empty($aliases[$lng])) {
$alias = $aliases[$lng];
}
else if ($key = array_search($lng, $aliases)) {
$alias = $key;
}
if (!empty($alias)) {
$fpath = $locdir . $alias . '.inc';
$texts = self::read_localization_file($fpath, $texts);
}
}
}
return $texts;
}
/**
* Load localization file
*
* @param string $file File location
* @param array $texts Additional texts to merge with
*
* @return array Localization labels/messages
*/
- public static function read_localization_file($file, $texts = array())
+ public static function read_localization_file($file, $texts = [])
{
if (is_file($file) && is_readable($file)) {
$labels = [];
$messages = [];
// use buffering to handle empty lines/spaces after closing PHP tag
ob_start();
include $file;
ob_end_clean();
if (!empty($labels)) {
$texts = array_merge($texts, $labels);
}
if (!empty($messages)) {
$texts = array_merge($texts, $messages);
}
}
return $texts;
}
/**
* Check the given string and return a valid language code
*
* @param string $lang Language code
*
* @return string Valid language code
*/
protected function language_prop($lang)
{
static $rcube_languages, $rcube_language_aliases;
// user HTTP_ACCEPT_LANGUAGE if no language is specified
if (empty($lang) || $lang == 'auto') {
$accept_langs = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
$lang = $accept_langs[0];
if (preg_match('/^([a-z]+)[_-]([a-z]+)$/i', $lang, $m)) {
$lang = $m[1] . '_' . strtoupper($m[2]);
}
}
if (empty($rcube_languages)) {
@include(RCUBE_LOCALIZATION_DIR . 'index.inc');
}
// check if we have an alias for that language
if (!isset($rcube_languages[$lang]) && isset($rcube_language_aliases[$lang])) {
$lang = $rcube_language_aliases[$lang];
}
// try the first two chars
else if (!isset($rcube_languages[$lang])) {
$short = substr($lang, 0, 2);
// check if we have an alias for the short language code
if (!isset($rcube_languages[$short]) && isset($rcube_language_aliases[$short])) {
$lang = $rcube_language_aliases[$short];
}
// expand 'nn' to 'nn_NN'
else if (!isset($rcube_languages[$short])) {
$lang = $short.'_'.strtoupper($short);
}
}
if (!isset($rcube_languages[$lang]) || !is_dir(RCUBE_LOCALIZATION_DIR . $lang)) {
$lang = 'en_US';
}
return $lang;
}
/**
* Read directory program/localization and return a list of available languages
*
* @return array List of available localizations
*/
public function list_languages()
{
- static $sa_languages = array();
+ static $sa_languages = [];
if (!count($sa_languages)) {
@include(RCUBE_LOCALIZATION_DIR . 'index.inc');
if ($dh = @opendir(RCUBE_LOCALIZATION_DIR)) {
while (($name = readdir($dh)) !== false) {
if ($name[0] == '.' || !is_dir(RCUBE_LOCALIZATION_DIR . $name)) {
continue;
}
if (isset($rcube_languages[$name])) {
$sa_languages[$name] = $rcube_languages[$name];
}
}
closedir($dh);
}
}
return $sa_languages;
}
/**
* Encrypt a string
*
* @param string $clear Clear text input
* @param string $key Encryption key to retrieve from the configuration, defaults to 'des_key'
* @param bool $base64 Whether or not to base64_encode() the result before returning
*
* @return string Encrypted text
*/
public function encrypt($clear, $key = 'des_key', $base64 = true)
{
if (!is_string($clear) || !strlen($clear)) {
return '';
}
$ckey = $this->config->get_crypto_key($key);
$method = $this->config->get_crypto_method();
$opts = defined('OPENSSL_RAW_DATA') ? OPENSSL_RAW_DATA : true;
$iv = rcube_utils::random_bytes(openssl_cipher_iv_length($method), true);
$cipher = openssl_encrypt($clear, $method, $ckey, $opts, $iv);
if ($cipher === false) {
- self::raise_error(array(
+ self::raise_error([
'file' => __FILE__,
'line' => __LINE__,
'message' => "Failed to encrypt data with configured cipher method: $method!"
- ), true, false);
+ ], true, false);
return false;
}
$cipher = $iv . $cipher;
return $base64 ? base64_encode($cipher) : $cipher;
}
/**
* Decrypt a string
*
* @param string $cipher Encrypted text
* @param string $key Encryption key to retrieve from the configuration, defaults to 'des_key'
* @param boo $base64 Whether or not input is base64-encoded
*
* @return string Decrypted text
*/
public function decrypt($cipher, $key = 'des_key', $base64 = true)
{
if (!$cipher) {
return '';
}
$cipher = $base64 ? base64_decode($cipher) : $cipher;
$ckey = $this->config->get_crypto_key($key);
$method = $this->config->get_crypto_method();
$opts = defined('OPENSSL_RAW_DATA') ? OPENSSL_RAW_DATA : true;
$iv_size = openssl_cipher_iv_length($method);
$iv = substr($cipher, 0, $iv_size);
// session corruption? (#1485970)
if (strlen($iv) < $iv_size) {
return '';
}
$cipher = substr($cipher, $iv_size);
$clear = openssl_decrypt($cipher, $method, $ckey, $opts, $iv);
return $clear;
}
/**
* Returns session token for secure URLs
*
* @param bool $generate Generate token if not exists in session yet
*
* @return string|bool Token string, False when disabled
*/
public function get_secure_url_token($generate = false)
{
if ($len = $this->config->get('use_secure_urls')) {
if (empty($_SESSION['secure_token']) && $generate) {
// generate x characters long token
$length = $len > 1 ? $len : 16;
$token = rcube_utils::random_bytes($length);
- $plugin = $this->plugins->exec_hook('secure_token',
- array('value' => $token, 'length' => $length));
+ $plugin = $this->plugins->exec_hook('secure_token', ['value' => $token, 'length' => $length]);
$_SESSION['secure_token'] = $plugin['value'];
}
return $_SESSION['secure_token'];
}
return false;
}
/**
* Generate a unique token to be used in a form request
*
* @return string The request token
*/
public function get_request_token()
{
if (empty($_SESSION['request_token'])) {
- $plugin = $this->plugins->exec_hook('request_token', array(
- 'value' => rcube_utils::random_bytes(32)));
+ $plugin = $this->plugins->exec_hook('request_token', ['value' => rcube_utils::random_bytes(32)]);
$_SESSION['request_token'] = $plugin['value'];
}
return $_SESSION['request_token'];
}
/**
* Check if the current request contains a valid token.
* Empty requests aren't checked until use_secure_urls is set.
*
* @param int $mode Request method
*
* @return bool True if request token is valid false if not
*/
public function check_request($mode = rcube_utils::INPUT_POST)
{
// check secure token in URL if enabled
if ($token = $this->get_secure_url_token()) {
foreach (explode('/', preg_replace('/[?#&].*$/', '', $_SERVER['REQUEST_URI'])) as $tok) {
if ($tok == $token) {
return true;
}
}
$this->request_status = self::REQUEST_ERROR_URL;
return false;
}
$sess_tok = $this->get_request_token();
// ajax requests
if (rcube_utils::request_header('X-Roundcube-Request') === $sess_tok) {
return true;
}
// skip empty requests
if (($mode == rcube_utils::INPUT_POST && empty($_POST))
|| ($mode == rcube_utils::INPUT_GET && empty($_GET))
) {
return true;
}
// default method of securing requests
$token = rcube_utils::get_input_value('_token', $mode);
if (empty($_COOKIE[ini_get('session.name')]) || $token !== $sess_tok) {
$this->request_status = self::REQUEST_ERROR_TOKEN;
return false;
}
return true;
}
/**
* Build a valid URL to this instance of Roundcube
*
* @param mixed $p Either a string with the action or url parameters as key-value pairs
*
* @return string Valid application URL
*/
public function url($p)
{
// STUB: should be overloaded by the application
return '';
}
/**
* Function to be executed in script shutdown
* Registered with register_shutdown_function()
*/
public function shutdown()
{
foreach ($this->shutdown_functions as $function) {
call_user_func($function);
}
// write session data as soon as possible and before
// closing database connection, don't do this before
// registered shutdown functions, they may need the session
// Note: this will run registered gc handlers (ie. cache gc)
if (!empty($_SERVER['REMOTE_ADDR']) && is_object($this->session)) {
$this->session->write_close();
}
if (is_object($this->smtp)) {
$this->smtp->disconnect();
}
foreach ($this->caches as $cache) {
if (is_object($cache)) {
$cache->close();
}
}
if (is_object($this->storage)) {
$this->storage->close();
}
if ($this->config->get('log_driver') == 'syslog') {
closelog();
}
}
/**
* Registers shutdown function to be executed on shutdown.
* The functions will be executed before destroying any
* objects like smtp, imap, session, etc.
*
* @param callback $function Function callback
*/
public function add_shutdown_function($function)
{
$this->shutdown_functions[] = $function;
}
/**
* When you're going to sleep the script execution for a longer time
* it is good to close all external connections (sql, memcache, redis, SMTP, IMAP).
*
* No action is required on wake up, all connections will be
* re-established automatically.
*/
public function sleep()
{
foreach ($this->caches as $cache) {
if (is_object($cache)) {
$cache->close();
}
}
if ($this->storage) {
$this->storage->close();
}
if ($this->db) {
$this->db->closeConnection();
}
if ($this->memcache) {
$this->memcache->close();
}
if ($this->memcached) {
$this->memcached->quit();
}
if ($this->smtp) {
$this->smtp->disconnect();
}
if ($this->redis) {
$this->redis->close();
}
}
/**
* Quote a given string.
* Shortcut function for rcube_utils::rep_specialchars_output()
*
* @param string $str A string to quote
* @param string $mode Replace mode for tags: show|remove|strict
* @param bool $newlines Convert newlines
*
* @return string HTML-quoted string
*/
public static function Q($str, $mode = 'strict', $newlines = true)
{
return rcube_utils::rep_specialchars_output($str, 'html', $mode, $newlines);
}
/**
* Quote a given string for javascript output.
* Shortcut function for rcube_utils::rep_specialchars_output()
*
* @param string $str A string to quote
*
* @return string JS-quoted string
*/
public static function JQ($str)
{
return rcube_utils::rep_specialchars_output($str, 'js');
}
/**
* Quote a given string, remove new-line characters, use strict mode.
* Shortcut function for rcube_utils::rep_specialchars_output()
*
* @param string $str A string to quote
*
* @return string HTML-quoted string
*/
public static function SQ($str)
{
return rcube_utils::rep_specialchars_output($str, 'html', 'strict', false);
}
/**
* Construct shell command, execute it and return output as string.
* Keywords {keyword} are replaced with arguments
*
* @param string $cmd Format string with {keywords} to be replaced
* @param mixed $values,... (zero, one or more arrays can be passed)
*
* @return string Output of command. Shell errors not detectable
*/
public static function exec(/* $cmd, $values1 = array(), ... */)
{
$args = func_get_args();
$cmd = array_shift($args);
- $values = $replacements = array();
+ $values = $replacements = [];
// merge values into one array
foreach ($args as $arg) {
- $values += (array)$arg;
+ $values += (array) $arg;
}
preg_match_all('/({(-?)([a-z]\w*)})/', $cmd, $matches, PREG_SET_ORDER);
foreach ($matches as $tags) {
list(, $tag, $option, $key) = $tags;
- $parts = array();
+ $parts = [];
if ($option) {
- foreach ((array)$values["-$key"] as $key => $value) {
+ foreach ((array) $values["-$key"] as $key => $value) {
if ($value === true || $value === false || $value === null) {
$parts[] = $value ? $key : "";
}
else {
foreach ((array)$value as $val) {
$parts[] = "$key " . escapeshellarg($val);
}
}
}
}
else {
- foreach ((array)$values[$key] as $value) {
+ foreach ((array) $values[$key] as $value) {
$parts[] = escapeshellarg($value);
}
}
$replacements[$tag] = implode(' ', $parts);
}
// use strtr behaviour of going through source string once
$cmd = strtr($cmd, $replacements);
return (string) shell_exec($cmd);
}
/**
* Print or write debug messages
*
* @param mixed Debug message or data
*/
public static function console()
{
$args = func_get_args();
if (class_exists('rcube', false)) {
$rcube = self::get_instance();
- $plugin = $rcube->plugins->exec_hook('console', array('args' => $args));
+ $plugin = $rcube->plugins->exec_hook('console', ['args' => $args]);
if ($plugin['abort']) {
return;
}
$args = $plugin['args'];
}
- $msg = array();
+ $msg = [];
foreach ($args as $arg) {
$msg[] = !is_string($arg) ? var_export($arg, true) : $arg;
}
self::write_log('console', implode(";\n", $msg));
}
/**
* Append a line to a logfile in the logs directory.
* Date will be added automatically to the line.
*
* @param string $name Name of the log file
* @param mixed $line Line to append
*
* @return bool True on success, False on failure
*/
public static function write_log($name, $line)
{
if (!is_string($line)) {
$line = var_export($line, true);
}
$date_format = $log_driver = $session_key = null;
if (self::$instance) {
$date_format = self::$instance->config->get('log_date_format');
$log_driver = self::$instance->config->get('log_driver');
$session_key = intval(self::$instance->config->get('log_session_id', 8));
}
$date = rcube_utils::date_format($date_format);
// trigger logging hook
if (is_object(self::$instance) && is_object(self::$instance->plugins)) {
$log = self::$instance->plugins->exec_hook('write_log',
- array('name' => $name, 'date' => $date, 'line' => $line));
+ ['name' => $name, 'date' => $date, 'line' => $line]);
$name = $log['name'];
$line = $log['line'];
$date = $log['date'];
if ($log['abort']) {
return true;
}
}
// add session ID to the log
if ($session_key > 0 && ($sess = session_id())) {
$line = '<' . substr($sess, 0, $session_key) . '> ' . $line;
}
if ($log_driver == 'syslog') {
$prio = $name == 'errors' ? LOG_ERR : LOG_INFO;
return syslog($prio, $line);
}
// write message with file name when configured to log to STDOUT
if ($log_driver == 'stdout') {
$stdout = "php://stdout";
$line = "$name: $line\n";
return file_put_contents($stdout, $line, FILE_APPEND) !== false;
}
// log_driver == 'file' is assumed here
$line = sprintf("[%s]: %s\n", $date, $line);
// per-user logging is activated
if (self::$instance && self::$instance->config->get('per_user_logging')
&& self::$instance->get_user_id()
- && !in_array($name, array('userlogins', 'sendmail'))
+ && !in_array($name, ['userlogins', 'sendmail'])
) {
$log_dir = self::$instance->get_user_log_dir();
if (empty($log_dir) && $name !== 'errors') {
return false;
}
}
if (empty($log_dir)) {
if (!empty($log['dir'])) {
$log_dir = $log['dir'];
}
else if (self::$instance) {
$log_dir = self::$instance->config->get('log_dir');
}
}
if (empty($log_dir)) {
$log_dir = RCUBE_INSTALL_PATH . 'logs';
}
if (self::$instance) {
$name .= self::$instance->config->get('log_file_ext', '.log');
}
else {
$name .= '.log';
}
return file_put_contents("$log_dir/$name", $line, FILE_APPEND) !== false;
}
/**
* Throw system error (and show error page).
*
* @param array $arg Named parameters
* - code: Error code (required)
* - type: Error type [php|db|imap|javascript]
* - message: Error message
* - file: File where error occurred
* - line: Line where error occurred
* @param bool $log True to log the error
* @param bool $terminate Terminate script execution
*/
- public static function raise_error($arg = array(), $log = false, $terminate = false)
+ public static function raise_error($arg = [], $log = false, $terminate = false)
{
// handle PHP exceptions
if ($arg instanceof Exception) {
- $arg = array(
+ $arg = [
'code' => $arg->getCode(),
'line' => $arg->getLine(),
'file' => $arg->getFile(),
'message' => $arg->getMessage(),
- );
+ ];
}
else if ($arg instanceof PEAR_Error) {
$info = $arg->getUserInfo();
- $arg = array(
+ $arg = [
'code' => $arg->getCode(),
'message' => $arg->getMessage() . ($info ? ': ' . $info : ''),
- );
+ ];
}
else if (is_string($arg)) {
- $arg = array('message' => $arg);
+ $arg = ['message' => $arg];
}
if (empty($arg['code'])) {
$arg['code'] = 500;
}
$cli = php_sapi_name() == 'cli';
$arg['cli'] = $cli;
$arg['log'] = $log;
$arg['terminate'] = $terminate;
// send error to external error tracking tool
if (self::$instance) {
$arg = self::$instance->plugins->exec_hook('raise_error', $arg);
}
// installer
if (!$cli && class_exists('rcmail_install', false)) {
$rci = rcmail_install::get_instance();
$rci->raise_error($arg);
return;
}
if (($log || $terminate) && !$cli && $arg['message']) {
$arg['fatal'] = $terminate;
self::log_bug($arg);
}
if ($cli) {
fwrite(STDERR, 'ERROR: ' . trim($arg['message']) . "\n");
}
else if ($terminate && is_object(self::$instance->output)) {
self::$instance->output->raise_error($arg['code'], $arg['message']);
}
else if ($terminate) {
header("HTTP/1.0 500 Internal Error");
}
// terminate script
if ($terminate) {
if (defined('ROUNDCUBE_TEST_MODE') && ROUNDCUBE_TEST_MODE) {
throw new Exception('Error raised');
}
exit(1);
}
}
/**
* Log an error
*
* @param array $arg_arr Named parameters
* @see self::raise_error()
*/
public static function log_bug($arg_arr)
{
- $program = strtoupper($arg_arr['type'] ?: 'php');
- $uri = $_SERVER['REQUEST_URI'];
+ $program = !empty($arg_arr['type']) ? strtoupper($arg_arr['type']) : 'PHP';
+ $uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
// write error to local log file
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
- $post_query = array();
- foreach (array('_task', '_action') as $arg) {
- if ($_POST[$arg] && !$_GET[$arg]) {
+ $post_query = [];
+ foreach (['_task', '_action'] as $arg) {
+ if (isset($_POST[$arg]) && !isset($_GET[$arg])) {
$post_query[$arg] = $_POST[$arg];
}
}
if (!empty($post_query)) {
$uri .= (strpos($uri, '?') != false ? '&' : '?')
. http_build_query($post_query, '', '&');
}
}
$log_entry = sprintf("%s Error: %s%s (%s %s)",
$program,
$arg_arr['message'],
$arg_arr['file'] ? sprintf(' in %s on line %d', $arg_arr['file'], $arg_arr['line']) : '',
$_SERVER['REQUEST_METHOD'],
- $uri);
+ $uri
+ );
if (!self::write_log('errors', $log_entry)) {
// send error to PHPs error handler if write_log didn't succeed
trigger_error($arg_arr['message'], E_USER_WARNING);
}
}
/**
* Write debug info to the log
*
* @param string $engine Engine type - file name (memcache, apc, redis)
* @param string $data Data string to log
* @param bool $result Operation result
*/
public static function debug($engine, $data, $result = null)
{
static $debug_counter;
$line = '[' . (++$debug_counter[$engine]) . '] ' . $data;
if (($len = strlen($line)) > self::DEBUG_LINE_LENGTH) {
$diff = $len - self::DEBUG_LINE_LENGTH;
$line = substr($line, 0, self::DEBUG_LINE_LENGTH) . "... [truncated $diff bytes]";
}
if ($result !== null) {
$line .= ' [' . ($result ? 'TRUE' : 'FALSE') . ']';
}
self::write_log($engine, $line);
}
/**
* Returns current time (with microseconds).
*
* @return float Current time in seconds since the Unix
*/
public static function timer()
{
return microtime(true);
}
/**
* Logs time difference according to provided timer
*
* @param float $timer Timer (self::timer() result)
* @param string $label Log line prefix
* @param string $dest Log file name
*
* @see self::timer()
*/
public static function print_timer($timer, $label = 'Timer', $dest = 'console')
{
static $print_count = 0;
$print_count++;
$now = self::timer();
$diff = $now - $timer;
if (empty($label)) {
$label = 'Timer '.$print_count;
}
self::write_log($dest, sprintf("%s: %0.4f sec", $label, $diff));
}
/**
* Setter for system user object
*
* @param rcube_user Current user instance
*/
public function set_user($user)
{
if (is_object($user)) {
$this->user = $user;
// overwrite config with user preferences
$this->config->set_user_prefs((array)$this->user->get_prefs());
}
}
/**
* Getter for logged user ID.
*
* @return mixed User identifier
*/
public function get_user_id()
{
if (is_object($this->user)) {
return $this->user->ID;
}
else if (isset($_SESSION['user_id'])) {
return $_SESSION['user_id'];
}
}
/**
* Getter for logged user name.
*
* @return string User name
*/
public function get_user_name()
{
if (is_object($this->user)) {
return $this->user->get_username();
}
else if (isset($_SESSION['username'])) {
return $_SESSION['username'];
}
}
/**
* Getter for logged user email (derived from user name not identity).
*
* @return string User email address
*/
public function get_user_email()
{
if (is_object($this->user)) {
return $this->user->get_username('mail');
}
}
/**
* Getter for logged user password.
*
* @return string User password
*/
public function get_user_password()
{
if (!empty($this->password)) {
return $this->password;
}
else if ($_SESSION['password']) {
return $this->decrypt($_SESSION['password']);
}
}
/**
* Get the per-user log directory
*
* @return string|false Per-user log directory if it exists and is writable, False otherwise
*/
protected function get_user_log_dir()
{
$log_dir = $this->config->get('log_dir', RCUBE_INSTALL_PATH . 'logs');
$user_name = $this->get_user_name();
$user_log_dir = $log_dir . '/' . $user_name;
return !empty($user_name) && is_writable($user_log_dir) ? $user_log_dir : false;
}
/**
* Getter for logged user language code.
*
* @return string User language code
*/
public function get_user_language()
{
if (is_object($this->user)) {
return $this->user->language;
}
else if (isset($_SESSION['language'])) {
return $_SESSION['language'];
}
}
/**
* Unique Message-ID generator.
*
* @param string $sender Optional sender e-mail address
*
* @return string Message-ID
*/
public function gen_message_id($sender = null)
{
$local_part = md5(uniqid('rcube'.mt_rand(), true));
$domain_part = '';
if ($sender && preg_match('/@([^\s]+\.[a-z0-9-]+)/', $sender, $m)) {
$domain_part = $m[1];
}
else {
$domain_part = $this->user->get_username('domain');
}
// Try to find FQDN, some spamfilters doesn't like 'localhost' (#1486924)
if (!preg_match('/\.[a-z0-9-]+$/i', $domain_part)) {
foreach (array($_SERVER['HTTP_HOST'], $_SERVER['SERVER_NAME']) as $host) {
$host = preg_replace('/:[0-9]+$/', '', $host);
if ($host && preg_match('/\.[a-z]+$/i', $host)) {
$domain_part = $host;
break;
}
}
}
return sprintf('<%s@%s>', $local_part, $domain_part);
}
/**
* Send the given message using the configured method.
*
* @param Mail_Mime &$message Reference to Mail_MIME object
* @param string $from Sender address string
* @param array|string $mailto Either a comma-separated list of recipients (RFC822 compliant),
* or an array of recipients, each RFC822 valid
* @param array|string &$error SMTP error array or (deprecated) string
* @param string &$body_file Location of file with saved message body,
* used when delay_file_io is enabled
* @param array $options SMTP options (e.g. DSN request)
* @param bool $disconnect Close SMTP connection ASAP
*
* @return bool Send status.
*/
public function deliver_message(&$message, $from, $mailto, &$error,
&$body_file = null, $options = null, $disconnect = false)
{
- $plugin = $this->plugins->exec_hook('message_before_send', array(
- 'message' => $message,
- 'from' => $from,
- 'mailto' => $mailto,
- 'options' => $options,
- ));
+ $plugin = $this->plugins->exec_hook('message_before_send', [
+ 'message' => $message,
+ 'from' => $from,
+ 'mailto' => $mailto,
+ 'options' => $options,
+ ]);
if ($plugin['abort']) {
if (!empty($plugin['error'])) {
$error = $plugin['error'];
}
if (!empty($plugin['body_file'])) {
$body_file = $plugin['body_file'];
}
return isset($plugin['result']) ? $plugin['result'] : false;
}
$from = $plugin['from'];
$mailto = $plugin['mailto'];
$options = $plugin['options'];
$message = $plugin['message'];
$headers = $message->headers();
// generate list of recipients
$a_recipients = (array) $mailto;
if (strlen($headers['Cc'])) {
$a_recipients[] = $headers['Cc'];
}
if (strlen($headers['Bcc'])) {
$a_recipients[] = $headers['Bcc'];
}
// remove Bcc header and get the whole head of the message as string
- $smtp_headers = $message->txtHeaders(array('Bcc' => null), true);
+ $smtp_headers = $message->txtHeaders(['Bcc' => null], true);
if ($message->getParam('delay_file_io')) {
// use common temp dir
$body_file = rcube_utils::temp_filename('msg');
$mime_result = $message->saveMessageBody($body_file);
if (is_a($mime_result, 'PEAR_Error')) {
- self::raise_error(array('code' => 650, 'type' => 'php',
- 'file' => __FILE__, 'line' => __LINE__,
- 'message' => "Could not create message: ".$mime_result->getMessage()),
- true, false);
+ self::raise_error([
+ 'code' => 650, 'file' => __FILE__, 'line' => __LINE__,
+ 'message' => "Could not create message: ".$mime_result->getMessage()
+ ],
+ true, false
+ );
return false;
}
$msg_body = fopen($body_file, 'r');
}
else {
$msg_body = $message->get();
}
// initialize SMTP connection
if (!is_object($this->smtp)) {
$this->smtp_init(true);
}
// send message
$sent = $this->smtp->send_mail($from, $a_recipients, $smtp_headers, $msg_body, $options);
$response = $this->smtp->get_response();
$error = $this->smtp->get_error();
if (!$sent) {
- self::raise_error(array('code' => 800, 'type' => 'smtp',
- 'line' => __LINE__, 'file' => __FILE__,
- 'message' => implode("\n", $response)), true, false);
+ self::raise_error([
+ 'code' => 800, 'type' => 'smtp',
+ 'line' => __LINE__, 'file' => __FILE__,
+ 'message' => implode("\n", $response)
+ ], true, false);
// allow plugins to catch sending errors with the same parameters as in 'message_before_send'
- $this->plugins->exec_hook('message_send_error', $plugin + array('error' => $error));
+ $this->plugins->exec_hook('message_send_error', $plugin + ['error' => $error]);
}
else {
- $this->plugins->exec_hook('message_sent', array('headers' => $headers, 'body' => $msg_body, 'message' => $message));
+ $this->plugins->exec_hook('message_sent', ['headers' => $headers, 'body' => $msg_body, 'message' => $message]);
// remove MDN headers after sending
unset($headers['Return-Receipt-To'], $headers['Disposition-Notification-To']);
if ($this->config->get('smtp_log')) {
// get all recipient addresses
$mailto = implode(',', $a_recipients);
$mailto = rcube_mime::decode_address_list($mailto, null, false, null, true);
self::write_log('sendmail', sprintf("User %s [%s]; Message %s for %s; %s",
$this->user->get_username(),
rcube_utils::remote_addr(),
$headers['Message-ID'],
implode(', ', $mailto),
- !empty($response) ? implode('; ', $response) : ''));
+ !empty($response) ? implode('; ', $response) : '')
+ );
}
}
if (is_resource($msg_body)) {
fclose($msg_body);
}
if ($disconnect) {
$this->smtp->disconnect();
}
// Add Bcc header back
if (!empty($headers['Bcc'])) {
- $message->headers(array('Bcc' => $headers['Bcc']), true);
+ $message->headers(['Bcc' => $headers['Bcc']], true);
}
return $sent;
}
}
/**
* Lightweight plugin API class serving as a dummy if plugins are not enabled
*
* @package Framework
* @subpackage Core
*/
class rcube_dummy_plugin_api
{
/**
* Triggers a plugin hook.
*
* @param string $hook Hook name
* @param array $args Hook arguments
*
* @return array Hook arguments
* @see rcube_plugin_api::exec_hook()
*/
- public function exec_hook($hook, $args = array())
+ public function exec_hook($hook, $args = [])
{
return $args;
}
}
diff --git a/tests/Framework/Bootstrap.php b/tests/Framework/Bootstrap.php
index 616633073..dcc9b68a1 100644
--- a/tests/Framework/Bootstrap.php
+++ b/tests/Framework/Bootstrap.php
@@ -1,218 +1,245 @@
<?php
/**
* Test class to test rcube_shared functions
*
* @package Tests
*/
class Framework_Bootstrap extends PHPUnit\Framework\TestCase
{
+ /**
+ * bootstrap.php: asciiwords()
+ */
+ function test_asciiwords()
+ {
+ $this->assertSame('abc.123', asciiwords('abc%.123', false));
+ $this->assertSame('abc-123', asciiwords('abc%.123', true, '-'));
+ }
+
/**
* bootstrap.php: in_array_nocase()
*/
function test_in_array_nocase()
{
- $haystack = array('Test');
+ $haystack = ['Test'];
$needle = 'test';
$result = in_array_nocase($needle, $haystack);
$this->assertTrue($result, "Invalid in_array_nocase() result (Array)");
$result = in_array_nocase($needle, null);
$this->assertFalse($result, "Invalid in_array_nocase() result (null)");
}
/**
* bootstrap.php: parse_bytes()
*/
function test_parse_bytes()
{
- $data = array(
+ $data = [
'1' => 1,
'1024' => 1024,
'2k' => 2 * 1024,
- '2 k' => 2 * 1024,
+ '2 k' => 2 * 1024,
'2kb' => 2 * 1024,
'2kB' => 2 * 1024,
'2m' => 2 * 1048576,
- '2 m' => 2 * 1048576,
+ '2 m' => 2 * 1048576,
'2mb' => 2 * 1048576,
'2mB' => 2 * 1048576,
'2g' => 2 * 1024 * 1048576,
- '2 g' => 2 * 1024 * 1048576,
+ '2 g' => 2 * 1024 * 1048576,
'2gb' => 2 * 1024 * 1048576,
'2gB' => 2 * 1024 * 1048576,
- );
+ ];
foreach ($data as $value => $expected) {
$result = parse_bytes($value);
$this->assertEquals($expected, $result, "Invalid parse_bytes() result for $value");
}
}
/**
* bootstrap.php: slashify()
*/
function test_slashify()
{
- $data = array(
+ $data = [
'test' => 'test/',
'test/' => 'test/',
'' => '/',
"\\" => "\\/",
- );
+ ];
foreach ($data as $value => $expected) {
$result = slashify($value);
$this->assertEquals($expected, $result, "Invalid slashify() result for $value");
}
}
/**
* bootstrap.php: unslashify()
*/
function test_unslashify()
{
- $data = array(
+ $data = [
'test' => 'test',
'test/' => 'test',
'/' => '',
"\\/" => "\\",
'test/test' => 'test/test',
'test//' => 'test',
'/test//' => '/test',
- );
+ ];
foreach ($data as $value => $expected) {
$result = unslashify($value);
$this->assertEquals($expected, $result, "Invalid unslashify() result for $value");
}
}
/**
* bootstrap.php: get_offset_sec()
*/
function test_get_offset_sec()
{
- $data = array(
+ $data = [
'1s' => 1,
'1m' => 1 * 60,
'1h' => 1 * 60 * 60,
'1d' => 1 * 60 * 60 * 24,
'1w' => 1 * 60 * 60 * 24 * 7,
'1y' => (int) '1y',
'100' => 100,
- );
+ ];
foreach ($data as $value => $expected) {
$result = get_offset_sec($value);
$this->assertEquals($expected, $result, "Invalid get_offset_sec() result for $value");
}
}
/**
* bootstrap.php: array_keys_recursive()
*/
function test_array_keys_recursive()
{
- $input = array(
- 'one' => array(
- 'two' => array(
- 'three' => array(),
+ $input = [
+ 'one' => [
+ 'two' => [
+ 'three' => [],
'four' => 'something',
- ),
- ),
+ ],
+ ],
'five' => 'test',
- );
+ ];
$result = array_keys_recursive($input);
$input_str = 'one,two,three,four,five';
$result_str = implode(',', $result);
$this->assertEquals($input_str, $result_str, "Invalid array_keys_recursive() result");
}
+ /**
+ * bootstrap.php: abbreviate_string()
+ */
+ function test_abbreviate_string()
+ {
+ $data = [
+ // expected, string, maxlength, placeholder, $ending
+ ['', '', 10, '...', false],
+ ['1234.90abc', '1234567890abc', 10, '.', false],
+ ['żćżć.12345', 'żćżćżćżć12345', 10, '.', false],
+ // TODO: more cases
+ ];
+
+ foreach ($data as $set) {
+ $result = abbreviate_string($set[1], $set[2], $set[3], $set[4]);
+ $this->assertEquals($set[0], $result);
+ }
+ }
+
/**
* bootstrap.php: format_email()
*/
function test_format_email()
{
- $data = array(
+ $data = [
'' => '',
'test' => 'test',
'test@test.tld' => 'test@test.tld',
'test@[127.0.0.1]' => 'test@[127.0.0.1]',
'TEST@TEST.TLD' => 'TEST@test.tld',
- );
+ ];
foreach ($data as $value => $expected) {
$result = format_email($value);
$this->assertEquals($expected, $result, "Invalid format_email() result for $value");
}
-
}
/**
* bootstrap.php: format_email_recipient()
*/
function test_format_email_recipient()
{
- $data = array(
- '' => array(''),
- 'test' => array('test'),
- 'test@test.tld' => array('test@test.tld'),
- 'test@[127.0.0.1]' => array('test@[127.0.0.1]'),
- 'TEST@TEST.TLD' => array('TEST@TEST.TLD'),
- 'TEST <test@test.tld>' => array('test@test.tld', 'TEST'),
- '"TEST\"" <test@test.tld>' => array('test@test.tld', 'TEST"'),
- );
+ $data = [
+ '' => [''],
+ 'test' => ['test'],
+ 'test@test.tld' => ['test@test.tld'],
+ 'test@[127.0.0.1]' => ['test@[127.0.0.1]'],
+ 'TEST@TEST.TLD' => ['TEST@TEST.TLD'],
+ 'TEST <test@test.tld>' => ['test@test.tld', 'TEST'],
+ '"TEST\"" <test@test.tld>' => ['test@test.tld', 'TEST"'],
+ ];
foreach ($data as $expected => $value) {
$result = format_email_recipient($value[0], isset($value[1]) ? $value[1] : null);
$this->assertEquals($expected, $result, "Invalid format_email_recipient()");
}
}
/**
* bootstrap.php: is_ascii()
*/
function test_is_ascii()
{
$result = is_ascii("0123456789");
$this->assertTrue($result, "Valid ASCII (numbers)");
$result = is_ascii("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
$this->assertTrue($result, "Valid ASCII (letters)");
$result = is_ascii(" !\"#\$%&'()*+,-./:;<=>?@[\\^_`{|}~");
$this->assertTrue($result, "Valid ASCII (special characters)");
$result = is_ascii("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"
."\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F");
$this->assertTrue($result, "Valid ASCII (control characters)");
$result = is_ascii("\n", false);
$this->assertFalse($result, "Valid ASCII (control characters)");
$result = is_ascii("ż");
$this->assertFalse($result, "Invalid ASCII (UTF-8 character)");
$result = is_ascii("ż", false);
$this->assertFalse($result, "Invalid ASCII (UTF-8 character [2])");
}
/**
* bootstrap.php: version_parse()
*/
function test_version_parse()
{
$this->assertEquals('0.9.0', version_parse('0.9-stable'));
$this->assertEquals('0.9.99', version_parse('0.9-git'));
}
}
diff --git a/tests/Framework/Html.php b/tests/Framework/Html.php
index 01e2a4915..7407bcedc 100644
--- a/tests/Framework/Html.php
+++ b/tests/Framework/Html.php
@@ -1,135 +1,135 @@
<?php
/**
* Test class to test rcube_html class
*
* @package Tests
*/
class Framework_Html extends PHPUnit\Framework\TestCase
{
/**
* Class constructor
*/
function test_class()
{
$object = new html;
$this->assertInstanceOf('html', $object, "Class constructor");
}
/**
* Data for test_attrib_string()
*/
function data_attrib_string()
{
- return array(
- array(
- array(), null, '',
- ),
- array(
- array('test' => 'test'), null, ' test="test"',
- ),
- array(
- array('test' => 'test'), array('test'), ' test="test"',
- ),
- array(
- array('test' => 'test'), array('other'), '',
- ),
- array(
- array('checked' => true), null, ' checked="checked"',
- ),
- array(
- array('checked' => ''), null, '',
- ),
- array(
- array('onclick' => ''), null, '',
- ),
- array(
- array('size' => 5), null, ' size="5"',
- ),
- array(
- array('size' => 'test'), null, '',
- ),
- array(
- array('data-test' => 'test'), null, ' data-test="test"',
- ),
- );
+ return [
+ [
+ [], null, '',
+ ],
+ [
+ ['test' => 'test'], null, ' test="test"',
+ ],
+ [
+ ['test' => 'test'], ['test'], ' test="test"',
+ ],
+ [
+ ['test' => 'test'], ['other'], '',
+ ],
+ [
+ ['checked' => true], null, ' checked="checked"',
+ ],
+ [
+ ['checked' => ''], null, '',
+ ],
+ [
+ ['onclick' => ''], null, '',
+ ],
+ [
+ ['size' => 5], null, ' size="5"',
+ ],
+ [
+ ['size' => 'test'], null, '',
+ ],
+ [
+ ['data-test' => 'test'], null, ' data-test="test"',
+ ],
+ ];
}
/**
* Test for attrib_string()
* @dataProvider data_attrib_string
*/
function test_attrib_string($arg1, $arg2, $expected)
{
$this->assertEquals($expected, html::attrib_string($arg1, $arg2));
}
/**
* Data for test_quote()
*/
function data_quote()
{
- return array(
- array('abc', 'abc'),
- array('?', '?'),
- array('"', '&quot;'),
- array('<', '&lt;'),
- array('>', '&gt;'),
- array('&', '&amp;'),
- array('&amp;', '&amp;amp;'),
- );
+ return [
+ ['abc', 'abc'],
+ ['?', '?'],
+ ['"', '&quot;'],
+ ['<', '&lt;'],
+ ['>', '&gt;'],
+ ['&', '&amp;'],
+ ['&amp;', '&amp;amp;'],
+ ];
}
/**
* Test for quote()
* @dataProvider data_quote
*/
function test_quote($str, $expected)
{
$this->assertEquals($expected, html::quote($str));
}
/**
* Data for test_parse_attrib_string()
*/
function data_parse_attrib_string()
{
- return array(
- array(
+ return [
+ [
'',
- array(),
- ),
- array(
+ [],
+ ],
+ [
'test="test1-val"',
- array('test' => 'test1-val'),
- ),
- array(
+ ['test' => 'test1-val'],
+ ],
+ [
'test1="test1-val" test2=test2-val',
- array('test1' => 'test1-val', 'test2' => 'test2-val'),
- ),
- array(
+ ['test1' => 'test1-val', 'test2' => 'test2-val'],
+ ],
+ [
' test1="test1\'val" test2=\'test2"val\' ',
- array('test1' => 'test1\'val', 'test2' => 'test2"val'),
- ),
- array(
+ ['test1' => 'test1\'val', 'test2' => 'test2"val'],
+ ],
+ [
'expression="test == true ? \' test\' : \'\'" ',
- array('expression' => 'test == true ? \' test\' : \'\''),
- ),
- array(
+ ['expression' => 'test == true ? \' test\' : \'\''],
+ ],
+ [
'href="http://domain.tld/страница"',
- array('href' => 'http://domain.tld/страница'),
- ),
- );
+ ['href' => 'http://domain.tld/страница'],
+ ],
+ ];
}
/**
* Test for parse_attrib_string()
* @dataProvider data_parse_attrib_string
*/
function test_parse_attrib_string($arg1, $expected)
{
$this->assertEquals($expected, html::parse_attrib_string($arg1));
}
}
diff --git a/tests/Framework/Rcube.php b/tests/Framework/Rcube.php
index 3bec0be7b..4b24f8ddf 100644
--- a/tests/Framework/Rcube.php
+++ b/tests/Framework/Rcube.php
@@ -1,20 +1,53 @@
<?php
/**
* Test class to test rcube class
*
* @package Tests
*/
class Framework_Rcube extends PHPUnit\Framework\TestCase
{
/**
* Class constructor
*/
function test_class()
{
$object = rcube::get_instance();
$this->assertInstanceOf('rcube', $object, "Class singleton");
}
+
+ /**
+ * rcube::read_localization()
+ */
+ function test_read_localization()
+ {
+ $rcube = rcube::get_instance();
+ $result = $rcube->read_localization(INSTALL_PATH . 'plugins/acl/localization', 'pl_PL');
+
+ $this->assertSame('Zapis', $result['aclwrite']);
+ }
+
+ /**
+ * rcube::list_languages()
+ */
+ function test_list_languages()
+ {
+ $rcube = rcube::get_instance();
+ $result = $rcube->list_languages();
+
+ $this->assertSame('English (US)', $result['en_US']);
+ }
+
+ /**
+ * rcube::encrypt() and rcube::decrypt()
+ */
+ function test_encrypt_and_decrypt()
+ {
+ $rcube = rcube::get_instance();
+ $result = $rcube->decrypt($rcube->encrypt('test'));
+
+ $this->assertSame('test', $result);
+ }
}

File Metadata

Mime Type
text/x-diff
Expires
Sat, Apr 18, 8:24 AM (1 h, 4 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
435570
Default Alt Text
(125 KB)

Event Timeline