diff --git a/Makefile b/Makefile index aee4c5999..9a958dd82 100644 --- a/Makefile +++ b/Makefile @@ -1,75 +1,83 @@ -GITREMOTE=git://github.com/roundcube/roundcubemail.git +GITREMOTE=https://github.com/roundcube/roundcubemail.git GITBRANCH=release-1.5 GPGKEY=devs@roundcube.net -VERSION=1.5.3 - +VERSION=1.5-git +PHP_VERSION=5.5 +SEDI=sed -i + +UNAME_S := $(shell uname -s) +ifeq ($(UNAME_S),Darwin) + SEDI=sed -i '' +endif + all: clean complete dependent framework - + complete: roundcubemail-git cp -RH roundcubemail-git roundcubemail-$(VERSION) - (cd roundcubemail-$(VERSION); jq '.require += {"kolab/net_ldap3": "~1.1.1"} | del(.suggest."kolab/net_ldap3")' --indent 4 composer.json-dist > composer.json) - (cd roundcubemail-$(VERSION); cp composer.json composer.json-bak; /tmp/composer.phar config platform.php 5.5; /tmp/composer.phar require symfony/polyfill-intl-idn:1.19.0 --no-install) - (cd roundcubemail-$(VERSION); php /tmp/composer.phar install --prefer-dist --no-dev --ignore-platform-reqs) - (cd roundcubemail-$(VERSION); mv composer.json-bak composer.json) + (cd roundcubemail-$(VERSION); cp composer.json-dist composer.json) + (cd roundcubemail-$(VERSION); php /tmp/composer.phar config platform.php $(PHP_VERSION)) + (cd roundcubemail-$(VERSION); php /tmp/composer.phar require "kolab/net_ldap3:~1.1.1" --no-update --no-install) + (cd roundcubemail-$(VERSION); php /tmp/composer.phar require "symfony/polyfill-intl-idn:1.19.0" --no-install) + (cd roundcubemail-$(VERSION); php /tmp/composer.phar config --unset suggest.kolab/net_ldap3) + (cd roundcubemail-$(VERSION); php /tmp/composer.phar config --unset require-dev) + (cd roundcubemail-$(VERSION); php /tmp/composer.phar install --prefer-dist --no-dev --no-interaction) + (cd roundcubemail-$(VERSION); php /tmp/composer.phar config --unset platform) (cd roundcubemail-$(VERSION); bin/install-jsdeps.sh --force) (cd roundcubemail-$(VERSION); bin/jsshrink.sh program/js/publickey.js; bin/jsshrink.sh plugins/managesieve/codemirror/lib/codemirror.js) (cd roundcubemail-$(VERSION); rm jsdeps.json bin/install-jsdeps.sh *.orig; rm -rf vendor/masterminds/html5/test vendor/pear/*/tests vendor/*/*/.git* vendor/pear/crypt_gpg/tools vendor/pear/console_commandline/docs vendor/pear/mail_mime/scripts vendor/pear/net_ldap2/doc vendor/pear/net_smtp/docs vendor/pear/net_smtp/examples vendor/pear/net_smtp/README.rst vendor/endroid/qrcode/tests temp/js_cache) tar czf roundcubemail-$(VERSION)-complete.tar.gz roundcubemail-$(VERSION) rm -rf roundcubemail-$(VERSION) dependent: roundcubemail-git cp -RH roundcubemail-git roundcubemail-$(VERSION) tar czf roundcubemail-$(VERSION).tar.gz roundcubemail-$(VERSION) rm -rf roundcubemail-$(VERSION) framework: roundcubemail-git /tmp/phpDocumentor.phar cp -r roundcubemail-git/program/lib/Roundcube roundcube-framework-$(VERSION) (cd roundcube-framework-$(VERSION); php /tmp/phpDocumentor.phar -d . -t ./doc --title="Roundcube Framework" --defaultpackagename="Framework" --template="clean") (cd roundcube-framework-$(VERSION); rm -rf doc/phpdoc-cache* .phpdoc) tar czf roundcube-framework-$(VERSION).tar.gz roundcube-framework-$(VERSION) rm -rf roundcube-framework-$(VERSION) sign: gpg -u $(GPGKEY) -a --detach-sig roundcubemail-$(VERSION).tar.gz gpg -u $(GPGKEY) -a --detach-sig roundcubemail-$(VERSION)-complete.tar.gz gpg -u $(GPGKEY) -a --detach-sig roundcube-framework-$(VERSION).tar.gz verify: - gpg -v --verify roundcubemail-$(VERSION).tar.gz{.asc,} - gpg -v --verify roundcubemail-$(VERSION)-complete.tar.gz{.asc,} - gpg -v --verify roundcube-framework-$(VERSION).tar.gz{.asc,} + gpg -v --verify roundcubemail-$(VERSION).tar.gz.asc roundcubemail-$(VERSION).tar.gz + gpg -v --verify roundcubemail-$(VERSION)-complete.tar.gz.asc roundcubemail-$(VERSION)-complete.tar.gz + gpg -v --verify roundcube-framework-$(VERSION).tar.gz.asc roundcube-framework-$(VERSION).tar.gz shasum: shasum -a 256 roundcubemail-$(VERSION).tar.gz roundcubemail-$(VERSION)-complete.tar.gz roundcube-framework-$(VERSION).tar.gz roundcubemail-git: buildtools - git clone $(GITREMOTE) roundcubemail-git - (cd roundcubemail-git; git checkout $(GITBRANCH)) + git clone --branch=$(GITBRANCH) --depth=1 $(GITREMOTE) roundcubemail-git (cd roundcubemail-git; bin/jsshrink.sh; bin/updatecss.sh; bin/cssshrink.sh) (cd roundcubemail-git/skins/elastic; \ lessc --clean-css="--s1 --advanced" styles/styles.less > styles/styles.min.css; \ lessc --clean-css="--s1 --advanced" styles/print.less > styles/print.min.css; \ lessc --clean-css="--s1 --advanced" styles/embed.less > styles/embed.min.css) (cd roundcubemail-git/bin; rm -f transifexpull.sh package2composer.sh) (cd roundcubemail-git; find . -name '.gitignore' | xargs rm) - (cd roundcubemail-git; find . -name '.travis.yml' | xargs rm) (cd roundcubemail-git; rm -rf tests plugins/*/tests .git* .tx* .ci* .editorconfig* index-test.php Dockerfile Makefile) - (cd roundcubemail-git; sed -i '' 's/1.5-git/$(VERSION)/' index.php public_html/index.php installer/index.php program/include/iniset.php program/lib/Roundcube/bootstrap.php) - (cd roundcubemail-git; sed -i '' 's/# Unreleased/# Release $(VERSION)'/ CHANGELOG.md) + (cd roundcubemail-git; $(SEDI) 's/1.5-git/$(VERSION)/' index.php public_html/index.php installer/index.php program/include/iniset.php program/lib/Roundcube/bootstrap.php) + (cd roundcubemail-git; $(SEDI) 's/# Unreleased/# Release $(VERSION)'/ CHANGELOG.md) buildtools: /tmp/composer.phar - npm install -g uglify-js - npm install -g lessc - npm install -g less-plugin-clean-css - npm install -g csso-cli - which -s jq || echo "!!!!!! Please install jq (https://stedolan.github.io/jq/) !!!!!!" + npm install uglify-js + npm install lessc + npm install less-plugin-clean-css + npm install csso-cli /tmp/composer.phar: curl -sS https://getcomposer.org/installer | php -- --install-dir=/tmp/ /tmp/phpDocumentor.phar: curl -sSL https://phpdoc.org/phpDocumentor.phar -o /tmp/phpDocumentor.phar clean: rm -rf roundcubemail-git rm -rf roundcubemail-$(VERSION)* diff --git a/index.php b/index.php index d5d12a33b..08fb5399f 100644 --- a/index.php +++ b/index.php @@ -1,283 +1,283 @@ | | Author: Aleksander Machniak | +-------------------------------------------------------------------------+ */ // include environment require_once 'program/include/iniset.php'; // init application, start session, init output class, etc. $RCMAIL = rcmail::get_instance(0, isset($GLOBALS['env']) ? $GLOBALS['env'] : null); // Make the whole PHP output non-cacheable (#1487797) $RCMAIL->output->nocacheing_headers(); $RCMAIL->output->common_headers(!empty($_SESSION['user_id'])); // turn on output buffering ob_start(); // check if config files had errors if ($err_str = $RCMAIL->config->get_error()) { rcmail::raise_error(['code' => 601, 'message' => $err_str], false, true); } // check DB connections and exit on failure if ($err_str = $RCMAIL->db->is_error()) { rcmail::raise_error(['code' => 603, 'type' => 'db', 'message' => $err_str], false, true); } // error steps if ($RCMAIL->action == 'error' && !empty($_GET['_code'])) { rcmail::raise_error(['code' => hexdec($_GET['_code'])], false, true); } // check if https is required (for login) and redirect if necessary if (empty($_SESSION['user_id']) && ($force_https = $RCMAIL->config->get('force_https', false))) { // force_https can be true, , :, if (!is_bool($force_https)) { list($host, $port) = explode(':', $force_https); if (is_numeric($host) && empty($port)) { $port = $host; $host = ''; } } if (empty($port)) { $port = 443; } if (!rcube_utils::https_check($port)) { if (empty($host)) { $host = preg_replace('/:[0-9]+$/', '', $_SERVER['HTTP_HOST']); } if ($port != 443) { $host .= ':' . $port; } header('Location: https://' . $host . $_SERVER['REQUEST_URI']); exit; } } // trigger startup plugin hook $startup = $RCMAIL->plugins->exec_hook('startup', ['task' => $RCMAIL->task, 'action' => $RCMAIL->action]); $RCMAIL->set_task($startup['task']); $RCMAIL->action = $startup['action']; $session_error = null; // try to log in if ($RCMAIL->task == 'login' && $RCMAIL->action == 'login') { $request_valid = !empty($_SESSION['temp']) && $RCMAIL->check_request(); $pass_charset = $RCMAIL->config->get('password_charset', 'UTF-8'); // purge the session in case of new login when a session already exists if ($request_valid) { $RCMAIL->kill_session(); } $auth = $RCMAIL->plugins->exec_hook('authenticate', [ 'host' => $RCMAIL->autoselect_host(), 'user' => trim(rcube_utils::get_input_string('_user', rcube_utils::INPUT_POST)), 'pass' => rcube_utils::get_input_string('_pass', rcube_utils::INPUT_POST, true, $pass_charset), 'valid' => $request_valid, 'error' => null, 'cookiecheck' => true, ]); // Login if ($auth['valid'] && !$auth['abort'] && $RCMAIL->login($auth['user'], $auth['pass'], $auth['host'], $auth['cookiecheck']) ) { // create new session ID, don't destroy the current session // it was destroyed already by $RCMAIL->kill_session() above $RCMAIL->session->remove('temp'); $RCMAIL->session->regenerate_id(false); // send auth cookie if necessary $RCMAIL->session->set_auth_cookie(); // log successful login $RCMAIL->log_login(); // restore original request parameters $query = []; if ($url = rcube_utils::get_input_string('_url', rcube_utils::INPUT_POST)) { parse_str($url, $query); // prevent endless looping on login page if (!empty($query['_task']) && $query['_task'] == 'login') { unset($query['_task']); } // prevent redirect to compose with specified ID (#1488226) if (!empty($query['_action']) && $query['_action'] == 'compose' && !empty($query['_id'])) { $query = ['_action' => 'compose']; } } // allow plugins to control the redirect url after login success $redir = $RCMAIL->plugins->exec_hook('login_after', $query + ['_task' => 'mail']); unset($redir['abort'], $redir['_err']); // send redirect $RCMAIL->output->redirect($redir, 0, true); } else { if (!$auth['valid']) { $error_code = rcmail::ERROR_INVALID_REQUEST; } else { $error_code = is_numeric($auth['error']) ? $auth['error'] : $RCMAIL->login_error(); } $error_labels = [ rcmail::ERROR_STORAGE => 'storageerror', rcmail::ERROR_COOKIES_DISABLED => 'cookiesdisabled', rcmail::ERROR_INVALID_REQUEST => 'invalidrequest', rcmail::ERROR_INVALID_HOST => 'invalidhost', rcmail::ERROR_RATE_LIMIT => 'accountlocked', ]; if (!empty($auth['error']) && !is_numeric($auth['error'])) { $error_message = $auth['error']; } else { $error_message = !empty($error_labels[$error_code]) ? $error_labels[$error_code] : 'loginfailed'; } $RCMAIL->output->show_message($error_message, 'warning'); // log failed login $RCMAIL->log_login($auth['user'], true, $error_code); $RCMAIL->plugins->exec_hook('login_failed', [ 'code' => $error_code, 'host' => $auth['host'], 'user' => $auth['user'], ]); if (!isset($_SESSION['user_id'])) { $RCMAIL->kill_session(); } } } // handle oauth login requests else if ($RCMAIL->task == 'login' && $RCMAIL->action == 'oauth' && $RCMAIL->oauth->is_enabled()) { $oauth_handler = new rcmail_action_login_oauth(); $oauth_handler->run(); } // end session else if ($RCMAIL->task == 'logout' && isset($_SESSION['user_id'])) { $RCMAIL->request_security_check(rcube_utils::INPUT_GET | rcube_utils::INPUT_POST); $userdata = array( 'user' => $_SESSION['username'], 'host' => $_SESSION['storage_host'], 'lang' => $RCMAIL->user->language, ); $RCMAIL->output->show_message('loggedout'); $RCMAIL->logout_actions(); $RCMAIL->kill_session(); $RCMAIL->plugins->exec_hook('logout_after', $userdata); } // check session and auth cookie else if ($RCMAIL->task != 'login' && $_SESSION['user_id']) { if (!$RCMAIL->session->check_auth()) { $RCMAIL->kill_session(); $session_error = 'sessionerror'; } } // not logged in -> show login page if (empty($RCMAIL->user->ID)) { if ( $session_error || (!empty($_REQUEST['_err']) && $_REQUEST['_err'] === 'session') || ($session_error = $RCMAIL->session_error()) ) { $RCMAIL->output->show_message($session_error ?: 'sessionerror', 'error', null, true, -1); } if ($RCMAIL->output->ajax_call || $RCMAIL->output->get_env('framed')) { $RCMAIL->output->command('session_error', $RCMAIL->url(['_err' => 'session'])); $RCMAIL->output->send('iframe'); } // check if installer is still active if ($RCMAIL->config->get('enable_installer') && is_readable('./installer/index.php')) { $RCMAIL->output->add_footer(html::div(['id' => 'login-addon', 'style' => "background:#ef9398; border:2px solid #dc5757; padding:0.5em; margin:2em auto; width:50em"], html::tag('h2', array('style' => "margin-top:0.2em"), "Installer script is still accessible") . html::p(null, "The install script of your Roundcube installation is still stored in its default location!") . html::p(null, "Please remove the whole installer folder from the Roundcube directory because these files may expose sensitive configuration data like server passwords and encryption keys to the public. Make sure you cannot access the installer script from your browser.") )); } $plugin = $RCMAIL->plugins->exec_hook('unauthenticated', [ 'task' => 'login', 'error' => $session_error, // Return 401 only on failed logins (#7010) 'http_code' => empty($session_error) && !empty($error_message) ? 401 : 200 ]); $RCMAIL->set_task($plugin['task']); if ($plugin['http_code'] == 401) { header('HTTP/1.0 401 Unauthorized'); } $RCMAIL->output->send($plugin['task']); } else { // CSRF prevention $RCMAIL->request_security_check(); // check access to disabled actions $disabled_actions = (array) $RCMAIL->config->get('disabled_actions'); if (in_array($RCMAIL->task . '.' . ($RCMAIL->action ?: 'index'), $disabled_actions)) { rcube::raise_error(['code' => 404, 'message' => "Action disabled"], true, true); } } $RCMAIL->action_handler(); diff --git a/installer/index.php b/installer/index.php index d94c502db..52037448f 100644 --- a/installer/index.php +++ b/installer/index.php @@ -1,173 +1,173 @@ | +-------------------------------------------------------------------------+ */ ini_set('display_errors', 1); define('INSTALL_PATH', realpath(__DIR__ . '/../').'/'); require INSTALL_PATH . 'program/include/iniset.php'; if (function_exists('session_start')) { session_start(); } $RCI = rcmail_install::get_instance(); $RCI->load_config(); if (isset($_GET['_getconfig'])) { $filename = 'config.inc.php'; if (!empty($_SESSION['config']) && $_GET['_getconfig'] == 2) { $path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . $filename; @unlink($path); file_put_contents($path, $_SESSION['config']); exit; } if (!empty($_SESSION['config'])) { header('Content-type: text/plain'); header('Content-Disposition: attachment; filename="'.$filename.'"'); echo $_SESSION['config']; exit; } header('HTTP/1.0 404 Not found'); die("The requested configuration was not found. Please run the installer from the beginning."); } if ( $RCI->configured && ($RCI->getprop('enable_installer') || $_SESSION['allowinstaller']) && !empty($_GET['_mergeconfig']) ) { $filename = 'config.inc.php'; header('Content-type: text/plain'); header('Content-Disposition: attachment; filename="'.$filename.'"'); $RCI->merge_config(); echo $RCI->create_config(); exit; } // go to 'check env' step if we have a local configuration if ($RCI->configured && empty($_REQUEST['_step'])) { header("Location: ./?_step=1"); exit; } ?> Roundcube Webmail Installer
configured && !$RCI->getprop('enable_installer') && empty($_SESSION['allowinstaller'])) { // header("HTTP/1.0 404 Not Found"); if ($RCI->configured && $RCI->legacy_config) { echo '

Your configuration needs to be migrated!

'; echo '

We changed the configuration files structure and your installation needs to be updated accordingly.

'; echo '

Please run the bin/update.sh script from the command line or set

  $rcube_config[\'enable_installer\'] = true;

'; echo ' in your RCUBE_CONFIG_DIR/main.inc.php to let the installer help you migrating it.

'; } else { echo '

The installer is disabled!

'; echo '

To enable it again, set $config[\'enable_installer\'] = true; in RCUBE_CONFIG_DIR/config.inc.php

'; } echo '
'; exit; } ?>

Roundcube Webmail Installer

    './check.php', 2 => './config.php', 3 => './test.php', ]; if (!in_array($RCI->step, array_keys($include_steps))) { $RCI->step = 1; } foreach (['Check environment', 'Create config', 'Test config'] as $i => $item) { $j = $i + 1; $link = ($RCI->step >= $j || $RCI->configured) ? '' . rcube::Q($item) . '' : rcube::Q($item); printf('
  1. %s
  2. ', $j+1, $RCI->step > $j ? ' passed' : ($RCI->step == $j ? ' current' : ''), $link); } ?>
step]; ?> diff --git a/program/include/iniset.php b/program/include/iniset.php index 1fb692393..9e279953e 100644 --- a/program/include/iniset.php +++ b/program/include/iniset.php @@ -1,125 +1,125 @@ | | Thomas Bruederli | +-----------------------------------------------------------------------+ */ // application constants -define('RCMAIL_VERSION', '1.5.3'); +define('RCMAIL_VERSION', '1.5-git'); define('RCMAIL_START', microtime(true)); if (!defined('INSTALL_PATH')) { define('INSTALL_PATH', dirname($_SERVER['SCRIPT_FILENAME']).'/'); } if (!defined('RCMAIL_CONFIG_DIR')) { define('RCMAIL_CONFIG_DIR', getenv('ROUNDCUBE_CONFIG_DIR') ?: (INSTALL_PATH . 'config')); } if (!defined('RCUBE_LOCALIZATION_DIR')) { define('RCUBE_LOCALIZATION_DIR', INSTALL_PATH . 'program/localization/'); } define('RCUBE_INSTALL_PATH', INSTALL_PATH); define('RCUBE_CONFIG_DIR', RCMAIL_CONFIG_DIR.'/'); // Show basic error message on fatal PHP error register_shutdown_function('rcmail_fatal_error'); // RC include folders MUST be included FIRST to avoid other // possible not compatible libraries (i.e PEAR) to be included // instead the ones provided by RC $include_path = INSTALL_PATH . 'program/lib' . PATH_SEPARATOR; $include_path.= ini_get('include_path'); if (set_include_path($include_path) === false) { die("Fatal error: ini_set/set_include_path does not work."); } // increase maximum execution time for php scripts // (does not work in safe mode) @set_time_limit(120); // include composer autoloader (if available) if (@file_exists(INSTALL_PATH . 'vendor/autoload.php')) { require INSTALL_PATH . 'vendor/autoload.php'; } // translate PATH_INFO to _task and _action GET parameters if (!empty($_SERVER['PATH_INFO']) && preg_match('!^/([a-z]+)/([a-z]+)$!', $_SERVER['PATH_INFO'], $m)) { if (!isset($_GET['_task'])) { $_GET['_task'] = $m[1]; } if (!isset($_GET['_action'])) { $_GET['_action'] = $m[2]; } } // include Roundcube Framework require_once 'Roundcube/bootstrap.php'; // register autoloader for rcmail app classes spl_autoload_register('rcmail_autoload'); /** * PHP5 autoloader routine for dynamic class loading */ function rcmail_autoload($classname) { if (strpos($classname, 'rcmail') === 0) { if (preg_match('/^rcmail_action_([^_]+)_(.*)$/', $classname, $matches)) { $filepath = INSTALL_PATH . "program/actions/{$matches[1]}/{$matches[2]}.php"; } else { $filepath = INSTALL_PATH . "program/include/$classname.php"; } if (is_readable($filepath)) { include_once $filepath; return true; } } return false; } /** * Show basic error message on fatal PHP error */ function rcmail_fatal_error() { $error = error_get_last(); if ($error && ($error['type'] === E_ERROR || $error['type'] === E_PARSE)) { if (php_sapi_name() === 'cli') { echo "Fatal error: Please check the Roundcube error log and/or server error logs for more information.\n"; } elseif (!empty($_REQUEST['_remote'])) { // Ajax request from UI header('Content-Type: application/json; charset=UTF-8'); echo json_encode(['code' => 500, 'message' => "Internal Server Error"]); } else { if (!defined('RCUBE_FATAL_ERROR_MSG')) { define('RCUBE_FATAL_ERROR_MSG', INSTALL_PATH . 'program/resources/error.html'); } echo file_get_contents(RCUBE_FATAL_ERROR_MSG); } } } diff --git a/program/lib/Roundcube/bootstrap.php b/program/lib/Roundcube/bootstrap.php index 2e69c6d2c..d84bfc1cc 100644 --- a/program/lib/Roundcube/bootstrap.php +++ b/program/lib/Roundcube/bootstrap.php @@ -1,449 +1,449 @@ | | Author: Aleksander Machniak | +-----------------------------------------------------------------------+ */ /** * Roundcube Framework Initialization * * @package Framework * @subpackage Core */ $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 += [ '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.3'); +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 bool True if found, False if not */ function in_array_nocase($needle, $haystack) { if (!is_string($needle) || !is_array($haystack)) { return false; } // use much faster method for ascii if (is_ascii($needle)) { foreach ((array) $haystack as $value) { if (is_string($value) && strcasecmp($value, $needle) === 0) { return true; } } } else { $needle = mb_strtolower($needle); foreach ((array) $haystack as $value) { if (is_string($value) && $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 = []; if (!empty($array) && is_array($array)) { foreach ($array as $key => $child) { $keys[] = $key; foreach (array_keys_recursive($child) as $val) { $keys[] = $val; } } } return $keys; } /** * Get first element from an array * * @param array $array Input array * * @return mixed First element if found, Null otherwise */ function array_first($array) { if (is_array($array)) { reset($array); foreach ($array as $element) { return $element; } } } /** * 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); } /** * 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( ['-stable', '-git'], ['.0', '.99'], $version ); } /** * 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/public_html/index.php b/public_html/index.php index c643abf8f..b48e41f91 100644 --- a/public_html/index.php +++ b/public_html/index.php @@ -1,26 +1,26 @@ | | Author: Aleksander Machniak | +-----------------------------------------------------------------------+ */ define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/'); // include index.php from application root directory include INSTALL_PATH . 'index.php';