| | |
| | | * Base class of the Roundcube Framework |
| | | * implemented as singleton |
| | | * |
| | | * @package Core |
| | | * @package Framework |
| | | * @subpackage Core |
| | | */ |
| | | class rcube |
| | | { |
| | |
| | | /** |
| | | * Instace of database class. |
| | | * |
| | | * @var rcube_pdo |
| | | * @var rcube_db |
| | | */ |
| | | public $db; |
| | | |
| | |
| | | * This implements the 'singleton' design pattern |
| | | * |
| | | * @param integer Options to initialize with this instance. See rcube::INIT_WITH_* constants |
| | | * |
| | | * @return rcube The one and only instance |
| | | */ |
| | | static function get_instance($mode = 0) |
| | |
| | | protected function __construct() |
| | | { |
| | | // load configuration |
| | | $this->config = new rcube_config(); |
| | | $this->config = new rcube_config; |
| | | $this->plugins = new rcube_dummy_plugin_api; |
| | | |
| | | register_shutdown_function(array($this, 'shutdown')); |
| | |
| | | /** |
| | | * Get the current database connection |
| | | * |
| | | * @return rcube_pdo Database connection object |
| | | * @return rcube_db Database object |
| | | */ |
| | | public function get_dbh() |
| | | { |
| | |
| | | $port = 0; |
| | | } |
| | | |
| | | $this->mc_available += intval($this->memcache->addServer($host, $port, $pconnect, 1, 1, 15, false, array($this, 'memcache_failure'))); |
| | | $this->mc_available += intval($this->memcache->addServer( |
| | | $host, $port, $pconnect, 1, 1, 15, false, array($this, 'memcache_failure'))); |
| | | } |
| | | |
| | | // test connection and failover (will result in $this->mc_available == 0 on complete failure) |
| | | $this->memcache->increment('__CONNECTIONTEST__', 1); // NOP if key doesn't exist |
| | | |
| | | if (!$this->mc_available) |
| | | if (!$this->mc_available) { |
| | | $this->memcache = false; |
| | | } |
| | | } |
| | | |
| | | return $this->memcache; |
| | |
| | | // only report once |
| | | if (!$seen["$host:$port"]++) { |
| | | $this->mc_available--; |
| | | self::raise_error(array('code' => 604, 'type' => 'db', |
| | | self::raise_error(array( |
| | | 'code' => 604, 'type' => 'db', |
| | | 'line' => __LINE__, 'file' => __FILE__, |
| | | 'message' => "Memcache failure on host $host:$port"), |
| | | true, false); |
| | |
| | | { |
| | | $this->smtp = new rcube_smtp(); |
| | | |
| | | if ($connect) |
| | | if ($connect) { |
| | | $this->smtp->connect(); |
| | | } |
| | | } |
| | | |
| | | |
| | |
| | | $messages_cache = true; |
| | | } |
| | | |
| | | if ($storage_cache) |
| | | if ($storage_cache) { |
| | | $this->storage->set_caching($storage_cache); |
| | | if ($messages_cache) |
| | | } |
| | | if ($messages_cache) { |
| | | $this->storage->set_messages_caching(true); |
| | | } |
| | | |
| | | // set pagesize from config |
| | | $pagesize = $this->config->get('mail_pagesize'); |
| | |
| | | public function gettext($attrib, $domain=null) |
| | | { |
| | | // load localization files if not done yet |
| | | if (empty($this->texts)) |
| | | if (empty($this->texts)) { |
| | | $this->load_language(); |
| | | } |
| | | |
| | | // extract attributes |
| | | if (is_string($attrib)) |
| | | if (is_string($attrib)) { |
| | | $attrib = array('name' => $attrib); |
| | | } |
| | | |
| | | $name = $attrib['name'] ? $attrib['name'] : ''; |
| | | |
| | | // attrib contain text values: use them from now |
| | | if (($setval = $attrib[strtolower($_SESSION['language'])]) || ($setval = $attrib['en_us'])) |
| | | if (($setval = $attrib[strtolower($_SESSION['language'])]) || ($setval = $attrib['en_us'])) { |
| | | $this->texts[$name] = $setval; |
| | | } |
| | | |
| | | // check for text with domain |
| | | if ($domain && ($text = $this->texts[$domain.'.'.$name])) |
| | | ; |
| | | if ($domain && ($text = $this->texts[$domain.'.'.$name])) { |
| | | } |
| | | // text does not exist |
| | | else if (!($text = $this->texts[$name])) { |
| | | return "[$name]"; |
| | |
| | | |
| | | // replace vars in text |
| | | if (is_array($attrib['vars'])) { |
| | | foreach ($attrib['vars'] as $var_key => $var_value) |
| | | foreach ($attrib['vars'] as $var_key => $var_value) { |
| | | $text = str_replace($var_key[0]!='$' ? '$'.$var_key : $var_key, $var_value, $text); |
| | | } |
| | | } |
| | | |
| | | // format output |
| | | if (($attrib['uppercase'] && strtolower($attrib['uppercase']=='first')) || $attrib['ucfirst']) |
| | | if (($attrib['uppercase'] && strtolower($attrib['uppercase'] == 'first')) || $attrib['ucfirst']) { |
| | | return ucfirst($text); |
| | | else if ($attrib['uppercase']) |
| | | } |
| | | else if ($attrib['uppercase']) { |
| | | return mb_strtoupper($text); |
| | | else if ($attrib['lowercase']) |
| | | } |
| | | else if ($attrib['lowercase']) { |
| | | return mb_strtolower($text); |
| | | } |
| | | |
| | | return strtr($text, array('\n' => "\n")); |
| | | } |
| | |
| | | public function text_exists($name, $domain = null, &$ref_domain = null) |
| | | { |
| | | // load localization files if not done yet |
| | | if (empty($this->texts)) |
| | | if (empty($this->texts)) { |
| | | $this->load_language(); |
| | | } |
| | | |
| | | if (isset($this->texts[$name])) { |
| | | $ref_domain = ''; |
| | |
| | | |
| | | // any of loaded domains (plugins) |
| | | if ($domain == '*') { |
| | | foreach ($this->plugins->loaded_plugins() as $domain) |
| | | foreach ($this->plugins->loaded_plugins() as $domain) { |
| | | if (isset($this->texts[$domain.'.'.$name])) { |
| | | $ref_domain = $domain; |
| | | return true; |
| | | } |
| | | } |
| | | } |
| | | // specified domain |
| | |
| | | return false; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Load a localization package |
| | | * |
| | | * @param string Language ID |
| | | * @param array Additional text labels/messages |
| | | */ |
| | | public function load_language($lang = null, $add = array()) |
| | | { |
| | |
| | | } |
| | | |
| | | // append additional texts (from plugin) |
| | | if (is_array($add) && !empty($add)) |
| | | if (is_array($add) && !empty($add)) { |
| | | $this->texts += $add; |
| | | } |
| | | } |
| | | |
| | | |
| | |
| | | * Check the given string and return a valid language code |
| | | * |
| | | * @param string Language code |
| | | * |
| | | * @return string Valid language code |
| | | */ |
| | | protected function language_prop($lang) |
| | |
| | | |
| | | if ($dh = @opendir(INSTALL_PATH . 'program/localization')) { |
| | | while (($name = readdir($dh)) !== false) { |
| | | if ($name[0] == '.' || !is_dir(INSTALL_PATH . 'program/localization/' . $name)) |
| | | if ($name[0] == '.' || !is_dir(INSTALL_PATH . 'program/localization/' . $name)) { |
| | | continue; |
| | | } |
| | | |
| | | if ($label = $rcube_languages[$name]) |
| | | if ($label = $rcube_languages[$name]) { |
| | | $sa_languages[$name] = $label; |
| | | } |
| | | } |
| | | closedir($dh); |
| | | } |
| | |
| | | */ |
| | | public function encrypt($clear, $key = 'des_key', $base64 = true) |
| | | { |
| | | if (!$clear) |
| | | if (!$clear) { |
| | | return ''; |
| | | } |
| | | |
| | | /*- |
| | | * Add a single canary byte to the end of the clear text, which |
| | |
| | | $clear = pack("a*H2", $clear, "80"); |
| | | |
| | | if (function_exists('mcrypt_module_open') && |
| | | ($td = mcrypt_module_open(MCRYPT_TripleDES, "", MCRYPT_MODE_CBC, ""))) { |
| | | ($td = mcrypt_module_open(MCRYPT_TripleDES, "", MCRYPT_MODE_CBC, "")) |
| | | ) { |
| | | $iv = $this->create_iv(mcrypt_enc_get_iv_size($td)); |
| | | mcrypt_generic_init($td, $this->config->get_crypto_key($key), $iv); |
| | | $cipher = $iv . mcrypt_generic($td, $clear); |
| | |
| | | return $base64 ? base64_encode($cipher) : $cipher; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Decrypt 3DES-encrypted string |
| | | * |
| | |
| | | */ |
| | | public function decrypt($cipher, $key = 'des_key', $base64 = true) |
| | | { |
| | | if (!$cipher) |
| | | if (!$cipher) { |
| | | return ''; |
| | | } |
| | | |
| | | $cipher = $base64 ? base64_decode($cipher) : $cipher; |
| | | |
| | | if (function_exists('mcrypt_module_open') && |
| | | ($td = mcrypt_module_open(MCRYPT_TripleDES, "", MCRYPT_MODE_CBC, ""))) { |
| | | ($td = mcrypt_module_open(MCRYPT_TripleDES, "", MCRYPT_MODE_CBC, "")) |
| | | ) { |
| | | $iv_size = mcrypt_enc_get_iv_size($td); |
| | | $iv = substr($cipher, 0, $iv_size); |
| | | |
| | | // session corruption? (#1485970) |
| | | if (strlen($iv) < $iv_size) |
| | | if (strlen($iv) < $iv_size) { |
| | | return ''; |
| | | } |
| | | |
| | | $cipher = substr($cipher, $iv_size); |
| | | mcrypt_generic_init($td, $this->config->get_crypto_key($key), $iv); |
| | |
| | | return $clear; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Generates encryption initialization vector (IV) |
| | | * |
| | | * @param int Vector size |
| | | * |
| | | * @return string Vector string |
| | | */ |
| | | private function create_iv($size) |
| | |
| | | // mcrypt_create_iv() can be slow when system lacks entrophy |
| | | // we'll generate IV vector manually |
| | | $iv = ''; |
| | | for ($i = 0; $i < $size; $i++) |
| | | for ($i = 0; $i < $size; $i++) { |
| | | $iv .= chr(mt_rand(0, 255)); |
| | | } |
| | | |
| | | return $iv; |
| | | } |
| | | |
| | |
| | | */ |
| | | public function shutdown() |
| | | { |
| | | foreach ($this->shutdown_functions as $function) |
| | | foreach ($this->shutdown_functions as $function) { |
| | | call_user_func($function); |
| | | } |
| | | |
| | | if (is_object($this->smtp)) |
| | | if (is_object($this->smtp)) { |
| | | $this->smtp->disconnect(); |
| | | } |
| | | |
| | | foreach ($this->caches as $cache) { |
| | | if (is_object($cache)) |
| | | if (is_object($cache)) { |
| | | $cache->close(); |
| | | } |
| | | } |
| | | |
| | | if (is_object($this->storage)) { |
| | | if ($this->expunge_cache) |
| | | if ($this->expunge_cache) { |
| | | $this->storage->expunge_cache(); |
| | | } |
| | | $this->storage->close(); |
| | | } |
| | | } |
| | |
| | | * |
| | | * @param $cmd Format string with {keywords} to be replaced |
| | | * @param $values (zero, one or more arrays can be passed) |
| | | * |
| | | * @return output of command. shell errors not detectable |
| | | */ |
| | | public static function exec(/* $cmd, $values1 = array(), ... */) |
| | |
| | | $values = $replacements = array(); |
| | | |
| | | // merge values into one array |
| | | foreach ($args as $arg) |
| | | foreach ($args as $arg) { |
| | | $values += (array)$arg; |
| | | } |
| | | |
| | | preg_match_all('/({(-?)([a-z]\w*)})/', $cmd, $matches, PREG_SET_ORDER); |
| | | foreach ($matches as $tags) { |
| | |
| | | |
| | | if ($option) { |
| | | foreach ((array)$values["-$key"] as $key => $value) { |
| | | if ($value === true || $value === false || $value === null) |
| | | if ($value === true || $value === false || $value === null) { |
| | | $parts[] = $value ? $key : ""; |
| | | else foreach ((array)$value as $val) |
| | | } |
| | | 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] = join(" ", $parts); |
| | | } |