|
|
|
<?php
|
|
|
|
|
|
|
|
/*
|
|
|
|
+-----------------------------------------------------------------------+
|
|
|
|
| program/include/rcube_shared.inc |
|
|
|
|
| |
|
|
|
|
| This file is part of the Roundcube PHP suite |
|
|
|
|
| Copyright (C) 2005-2012, 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: |
|
|
|
|
| Shared functions used by Roundcube Framework |
|
|
|
|
| |
|
|
|
|
+-----------------------------------------------------------------------+
|
|
|
|
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
|
|
|
+-----------------------------------------------------------------------+
|
|
|
|
|
|
|
|
$Id$
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Roundcube shared functions
|
|
|
|
*
|
|
|
|
* @package Core
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Similar function as in_array() but case-insensitive
|
|
|
|
*
|
|
|
|
* @param string $needle Needle value
|
|
|
|
* @param array $heystack Array to search in
|
|
|
|
*
|
|
|
|
* @return boolean True if found, False if not
|
|
|
|
*/
|
|
|
|
function in_array_nocase($needle, $haystack)
|
|
|
|
{
|
|
|
|
$needle = mb_strtolower($needle);
|
|
|
|
foreach ($haystack as $value) {
|
|
|
|
if ($needle === mb_strtolower($value)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Find out if the string content means true or false
|
|
|
|
*
|
|
|
|
* @param string $str Input value
|
|
|
|
*
|
|
|
|
* @return boolean Boolean value
|
|
|
|
*/
|
|
|
|
function get_boolean($str)
|
|
|
|
{
|
|
|
|
$str = strtolower($str);
|
|
|
|
|
|
|
|
return !in_array($str, array('false', '0', 'no', 'off', 'nein', ''), true);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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);
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
*/
|
|
|
|
function slashify($str)
|
|
|
|
{
|
|
|
|
return unslashify($str).'/';
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove slash at the end of the string
|
|
|
|
*/
|
|
|
|
function unslashify($str)
|
|
|
|
{
|
|
|
|
return preg_replace('/\/$/', '', $str);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Delete all files within a folder
|
|
|
|
*
|
|
|
|
* @param string Path to directory
|
|
|
|
*
|
|
|
|
* @return boolean True on success, False if directory was not found
|
|
|
|
*/
|
|
|
|
function clear_directory($dir_path)
|
|
|
|
{
|
|
|
|
$dir = @opendir($dir_path);
|
|
|
|
if (!$dir) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
while ($file = readdir($dir)) {
|
|
|
|
if (strlen($file) > 2) {
|
|
|
|
unlink("$dir_path/$file");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
closedir($dir);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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;
|
|
|
|
|
|
|
|
$str = mb_substr($str, 0, $first_part_length) . $placeholder . mb_substr($str, $second_starting_location);
|
|
|
|
}
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
|
|
|
if (!empty($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 ., -, _
|
|
|
|
*/
|
|
|
|
function asciiwords($str, $css_id = false, $replace_with = '')
|
|
|
|
{
|
|
|
|
$allowed = 'a-z0-9\_\-' . (!$css_id ? '\.' : '');
|
|
|
|
return preg_replace("/[^$allowed]/i", $replace_with, $str);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove single and double quotes from given string
|
|
|
|
*
|
|
|
|
* @param string Input value
|
|
|
|
*
|
|
|
|
* @return string Dequoted string
|
|
|
|
*/
|
|
|
|
function strip_quotes($str)
|
|
|
|
{
|
|
|
|
return str_replace(array("'", '"'), '', $str);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove new lines characters from given string
|
|
|
|
*
|
|
|
|
* @param string $str Input value
|
|
|
|
*
|
|
|
|
* @return string Stripped string
|
|
|
|
*/
|
|
|
|
function strip_newlines($str)
|
|
|
|
{
|
|
|
|
return preg_replace('/[\r\n]/', '', $str);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* mbstring replacement functions
|
|
|
|
*/
|
|
|
|
if (!extension_loaded('mbstring'))
|
|
|
|
{
|
|
|
|
function mb_strlen($str)
|
|
|
|
{
|
|
|
|
return strlen($str);
|
|
|
|
}
|
|
|
|
|
|
|
|
function mb_strtolower($str)
|
|
|
|
{
|
|
|
|
return strtolower($str);
|
|
|
|
}
|
|
|
|
|
|
|
|
function mb_strtoupper($str)
|
|
|
|
{
|
|
|
|
return strtoupper($str);
|
|
|
|
}
|
|
|
|
|
|
|
|
function mb_substr($str, $start, $len=null)
|
|
|
|
{
|
|
|
|
return substr($str, $start, $len);
|
|
|
|
}
|
|
|
|
|
|
|
|
function mb_strpos($haystack, $needle, $offset=0)
|
|
|
|
{
|
|
|
|
return strpos($haystack, $needle, $offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
function mb_strrpos($haystack, $needle, $offset=0)
|
|
|
|
{
|
|
|
|
return strrpos($haystack, $needle, $offset);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* intl replacement functions
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (!function_exists('idn_to_utf8'))
|
|
|
|
{
|
|
|
|
function idn_to_utf8($domain, $flags=null)
|
|
|
|
{
|
|
|
|
static $idn, $loaded;
|
|
|
|
|
|
|
|
if (!$loaded) {
|
|
|
|
$idn = new Net_IDNA2();
|
|
|
|
$loaded = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($idn && $domain && preg_match('/(^|\.)xn--/i', $domain)) {
|
|
|
|
try {
|
|
|
|
$domain = $idn->decode($domain);
|
|
|
|
}
|
|
|
|
catch (Exception $e) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return $domain;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!function_exists('idn_to_ascii'))
|
|
|
|
{
|
|
|
|
function idn_to_ascii($domain, $flags=null)
|
|
|
|
{
|
|
|
|
static $idn, $loaded;
|
|
|
|
|
|
|
|
if (!$loaded) {
|
|
|
|
$idn = new Net_IDNA2();
|
|
|
|
$loaded = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($idn && $domain && preg_match('/[^\x20-\x7E]/', $domain)) {
|
|
|
|
try {
|
|
|
|
$domain = $idn->encode($domain);
|
|
|
|
}
|
|
|
|
catch (Exception $e) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return $domain;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Use PHP5 autoload for dynamic class loading
|
|
|
|
*
|
|
|
|
* @todo Make Zend, PEAR etc play with this
|
|
|
|
* @todo Make our classes conform to a more straight forward CS.
|
|
|
|
*/
|
|
|
|
function rcube_autoload($classname)
|
|
|
|
{
|
|
|
|
$filename = preg_replace(
|
|
|
|
array(
|
|
|
|
'/MDB2_(.+)/',
|
|
|
|
'/Mail_(.+)/',
|
|
|
|
'/Net_(.+)/',
|
|
|
|
'/Auth_(.+)/',
|
|
|
|
'/^html_.+/',
|
|
|
|
'/^utf8$/',
|
|
|
|
),
|
|
|
|
array(
|
|
|
|
'MDB2/\\1',
|
|
|
|
'Mail/\\1',
|
|
|
|
'Net/\\1',
|
|
|
|
'Auth/\\1',
|
|
|
|
'html',
|
|
|
|
'utf8.class',
|
|
|
|
),
|
|
|
|
$classname
|
|
|
|
);
|
|
|
|
|
|
|
|
if ($fp = @fopen("$filename.php", 'r', true)) {
|
|
|
|
fclose($fp);
|
|
|
|
include_once "$filename.php";
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Local callback function for PEAR errors
|
|
|
|
*/
|
|
|
|
function rcube_pear_error($err)
|
|
|
|
{
|
|
|
|
error_log(sprintf("%s (%s): %s",
|
|
|
|
$err->getMessage(),
|
|
|
|
$err->getCode(),
|
|
|
|
$err->getUserinfo()), 0);
|
|
|
|
}
|