Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F2513045
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
125 KB
Referenced Files
None
Subscribers
None
View Options
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('"', '"'),
- array('<', '<'),
- array('>', '>'),
- array('&', '&'),
- array('&', '&amp;'),
- );
+ return [
+ ['abc', 'abc'],
+ ['?', '?'],
+ ['"', '"'],
+ ['<', '<'],
+ ['>', '>'],
+ ['&', '&'],
+ ['&', '&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
Details
Attached
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)
Attached To
Mode
R3 roundcubemail
Attached
Detach File
Event Timeline
Log In to Comment