From 0c259682f65eaaf23ea4ccb56a706d6baf3007e4 Mon Sep 17 00:00:00 2001 From: alecpl Date: Fri, 13 Apr 2012 08:52:02 +0000 Subject: - Merge devel-framework branch, resolved conflicts --- program/include/clisetup.php | 2 +- program/include/html.php | 66 +- program/include/iniset.php | 60 +- program/include/main.inc | 2110 ++--------------------------- program/include/rcmail.php | 1247 ++++++----------- program/include/rcube.php | 1226 +++++++++++++++++ program/include/rcube_addressbook.php | 7 +- program/include/rcube_base_replacer.php | 110 ++ program/include/rcube_cache.php | 14 +- program/include/rcube_config.php | 14 +- program/include/rcube_contacts.php | 42 +- program/include/rcube_html_page.php | 323 ----- program/include/rcube_imap.php | 53 +- program/include/rcube_imap_cache.php | 69 +- program/include/rcube_imap_generic.php | 49 +- program/include/rcube_json_output.php | 298 ---- program/include/rcube_ldap.php | 32 +- program/include/rcube_mdb2.php | 345 +++-- program/include/rcube_message.php | 18 +- program/include/rcube_message_header.php | 238 ++++ program/include/rcube_message_part.php | 103 ++ program/include/rcube_output.php | 259 ++++ program/include/rcube_output_html.php | 1604 ++++++++++++++++++++++ program/include/rcube_output_json.php | 271 ++++ program/include/rcube_plugin.php | 16 +- program/include/rcube_plugin_api.php | 83 +- program/include/rcube_session.php | 21 +- program/include/rcube_shared.inc | 612 ++++----- program/include/rcube_smtp.php | 6 +- program/include/rcube_spellchecker.php | 20 +- program/include/rcube_sqlite.inc | 79 -- program/include/rcube_storage.php | 92 +- program/include/rcube_string_replacer.php | 6 +- program/include/rcube_template.php | 1374 ------------------- program/include/rcube_ui.php | 1468 ++++++++++++++++++++ program/include/rcube_user.php | 36 +- program/include/rcube_vcard.php | 6 +- program/steps/addressbook/func.inc | 2 +- program/steps/mail/compose.inc | 16 +- program/steps/mail/func.inc | 25 +- program/steps/mail/get.inc | 25 +- program/steps/mail/show.inc | 26 +- program/steps/utils/error.inc | 15 +- 43 files changed, 6704 insertions(+), 5784 deletions(-) create mode 100644 program/include/rcube.php create mode 100644 program/include/rcube_base_replacer.php delete mode 100644 program/include/rcube_html_page.php delete mode 100644 program/include/rcube_json_output.php create mode 100644 program/include/rcube_message_header.php create mode 100644 program/include/rcube_message_part.php create mode 100644 program/include/rcube_output.php create mode 100644 program/include/rcube_output_html.php create mode 100644 program/include/rcube_output_json.php delete mode 100644 program/include/rcube_sqlite.inc delete mode 100644 program/include/rcube_template.php create mode 100644 program/include/rcube_ui.php (limited to 'program') diff --git a/program/include/clisetup.php b/program/include/clisetup.php index c5f8dd1cc..22ffbbc92 100644 --- a/program/include/clisetup.php +++ b/program/include/clisetup.php @@ -55,7 +55,7 @@ function get_opt($aliases=array()) continue; $args[$key] = preg_replace(array('/^["\']/', '/["\']$/'), '', $value); - + if ($alias = $aliases[$key]) $args[$alias] = $args[$key]; } diff --git a/program/include/html.php b/program/include/html.php index 0e89d778f..305a39781 100644 --- a/program/include/html.php +++ b/program/include/html.php @@ -277,7 +277,7 @@ class html $attrib_arr = array(); foreach ($attrib as $key => $value) { // skip size if not numeric - if (($key=='size' && !is_numeric($value))) { + if ($key == 'size' && !is_numeric($value)) { continue; } @@ -297,17 +297,57 @@ class html $attrib_arr[] = $key . '="' . $key . '"'; } } - else if ($key=='value') { - $attrib_arr[] = $key . '="' . Q($value, 'strict', false) . '"'; - } else { - $attrib_arr[] = $key . '="' . Q($value) . '"'; + $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 Input string + * @return array Key-value pairs of parsed attributes + */ + public static function parse_attrib_string($str) + { + $attrib = array(); + $regexp = '/\s*([-_a-z]+)=(["\'])??(?(2)([^\2]*)\2|(\S+?))/Ui'; + + preg_match_all($regexp, stripslashes($str), $regs, PREG_SET_ORDER); + + // convert attributes to an associative array (name => value) + if ($regs) { + foreach ($regs as $attr) { + $attrib[strtolower($attr[1])] = html_entity_decode($attr[3] . $attr[4]); + } + } + + return $attrib; + } + + /** + * Replacing specials characters in html attribute value + * + * @param string $str Input string + * + * @return string The quoted string + */ + public static function quote($str) + { + $str = htmlspecialchars($str, ENT_COMPAT, RCMAIL_CHARSET); + + // avoid douple quotation of & + // @TODO: get rid of it? + $str = preg_replace('/&([A-Za-z]{2,6}|#[0-9]{2,4});/', '&\\1;', $str); + + return $str; + } } + /** * Class to create an HTML input field * @@ -317,9 +357,11 @@ class html_inputfield extends html { protected $tagname = 'input'; protected $type = 'text'; - protected $allowed = array('type','name','value','size','tabindex', + protected $allowed = array( + 'type','name','value','size','tabindex', 'autocomplete','checked','onchange','onclick','disabled','readonly', - 'spellcheck','results','maxlength','src','multiple','placeholder'); + 'spellcheck','results','maxlength','src','multiple','placeholder', + ); /** * Object constructor @@ -517,11 +559,11 @@ class html_textarea extends html } if (!empty($value) && !preg_match('/mce_editor/', $this->attrib['class'])) { - $value = Q($value, 'strict', false); + $value = self::quote($value); } return self::tag($this->tagname, $this->attrib, $value, - array_merge(self::$common_attrib, $this->allowed)); + array_merge(self::$common_attrib, $this->allowed)); } } @@ -550,7 +592,7 @@ class html_select extends html protected $options = array(); protected $allowed = array('name','size','tabindex','autocomplete', 'multiple','onchange','disabled','rel'); - + /** * Add a new option to this drop-down * @@ -591,8 +633,9 @@ class html_select extends html 'selected' => (in_array($option['value'], $select, true) || in_array($option['text'], $select, true)) ? 1 : null); - $this->content .= self::tag('option', $attr, Q($option['text'])); + $this->content .= self::tag('option', $attr, self::quote($option['text'])); } + return parent::show(); } } @@ -803,4 +846,3 @@ class html_table extends html } } - diff --git a/program/include/iniset.php b/program/include/iniset.php index 5feca7d9c..3715c21ef 100644 --- a/program/include/iniset.php +++ b/program/include/iniset.php @@ -40,7 +40,7 @@ foreach ($crit_opts as $optname => $optval) { } // application constants -define('RCMAIL_VERSION', '0.8-svn'); +define('RCMAIL_VERSION', '0.9-svn'); define('RCMAIL_CHARSET', 'UTF-8'); define('JS_OBJECT_NAME', 'rcmail'); define('RCMAIL_START', microtime(true)); @@ -53,11 +53,6 @@ if (!defined('RCMAIL_CONFIG_DIR')) { define('RCMAIL_CONFIG_DIR', INSTALL_PATH . 'config'); } -// make sure path_separator is defined -if (!defined('PATH_SEPARATOR')) { - define('PATH_SEPARATOR', (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') ? ';' : ':'); -} - // 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 @@ -80,59 +75,14 @@ if (extension_loaded('mbstring')) { @mb_regex_encoding(RCMAIL_CHARSET); } -/** - * 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; -} +// include global functions +require_once INSTALL_PATH . 'program/include/rcube_shared.inc'; +// Register autoloader spl_autoload_register('rcube_autoload'); -/** - * Local callback function for PEAR errors - */ -function rcube_pear_error($err) -{ - error_log(sprintf("%s (%s): %s", - $err->getMessage(), - $err->getCode(), - $err->getUserinfo()), 0); -} - // set PEAR error handling (will also load the PEAR main class) PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'rcube_pear_error'); -// include global functions +// backward compatybility (to be removed) require_once INSTALL_PATH . 'program/include/main.inc'; -require_once INSTALL_PATH . 'program/include/rcube_shared.inc'; diff --git a/program/include/main.inc b/program/include/main.inc index 3f502753e..791e657b4 100644 --- a/program/include/main.inc +++ b/program/include/main.inc @@ -5,14 +5,14 @@ | program/include/main.inc | | | | This file is part of the Roundcube Webmail client | - | Copyright (C) 2005-2011, The Roundcube Dev Team | + | 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. | | | | PURPOSE: | - | Provide basic functions for the webmail package | + | Provide deprecated functions aliases for backward compatibility | | | +-----------------------------------------------------------------------+ | Author: Thomas Bruederli | @@ -23,2224 +23,324 @@ */ /** - * Roundcube Webmail common functions + * Roundcube Webmail deprecated functions * * @package Core * @author Thomas Bruederli */ -require_once INSTALL_PATH . 'program/include/rcube_shared.inc'; +// constants for input reading +define('RCUBE_INPUT_GET', rcube_ui::INPUT_GET); +define('RCUBE_INPUT_POST', rcube_ui::INPUT_POST); +define('RCUBE_INPUT_GPC', rcube_ui::INPUT_GPC); -// define constannts for input reading -define('RCUBE_INPUT_GET', 0x0101); -define('RCUBE_INPUT_POST', 0x0102); -define('RCUBE_INPUT_GPC', 0x0103); - - -/** - * Return correct name for a specific database table - * - * @param string Table name - * @return string Translated table name - */ function get_table_name($table) - { - global $CONFIG; - - // return table name if configured - $config_key = 'db_table_'.$table; - - if (strlen($CONFIG[$config_key])) - return $CONFIG[$config_key]; - - return $table; - } - +{ + return rcmail::get_instance()->db->table_name($table); +} -/** - * Return correct name for a specific database sequence - * (used for Postgres only) - * - * @param string Secuence name - * @return string Translated sequence name - */ function get_sequence_name($sequence) - { - // return sequence name if configured - $config_key = 'db_sequence_'.$sequence; - $opt = rcmail::get_instance()->config->get($config_key); - - if (!empty($opt)) - return $opt; - - return $sequence; - } - +{ + return rcmail::get_instance()->db->sequence_name($sequence); +} -/** - * Get localized text in the desired language - * It's a global wrapper for rcmail::gettext() - * - * @param mixed Named parameters array or label name - * @param string Domain to search in (e.g. plugin name) - * @return string Localized text - * @see rcmail::gettext() - */ function rcube_label($p, $domain=null) { - return rcmail::get_instance()->gettext($p, $domain); + return rcmail::get_instance()->gettext($p, $domain); } - -/** - * Global wrapper of rcmail::text_exists() - * to check whether a text label is defined - * - * @see rcmail::text_exists() - */ function rcube_label_exists($name, $domain=null, &$ref_domain = null) { - return rcmail::get_instance()->text_exists($name, $domain, $ref_domain); + return rcmail::get_instance()->text_exists($name, $domain, $ref_domain); } - -/** - * Overwrite action variable - * - * @param string New action value - */ function rcmail_overwrite_action($action) - { - $app = rcmail::get_instance(); - $app->action = $action; - $app->output->set_env('action', $action); - } - +{ + rcmail::get_instance()->overwrite_action($action); +} -/** - * Compose an URL for a specific action - * - * @param string Request action - * @param array More URL parameters - * @param string Request task (omit if the same) - * @return The application URL - */ function rcmail_url($action, $p=array(), $task=null) { - $app = rcmail::get_instance(); - return $app->url((array)$p + array('_action' => $action, 'task' => $task)); + return rcube_ui::url($action, $p, $task); } - -/** - * Garbage collector function for temp files. - * Remove temp files older than two days - */ function rcmail_temp_gc() { - $rcmail = rcmail::get_instance(); - - $tmp = unslashify($rcmail->config->get('temp_dir')); - $expire = mktime() - 172800; // expire in 48 hours - - if ($dir = opendir($tmp)) { - while (($fname = readdir($dir)) !== false) { - if ($fname{0} == '.') - continue; - - if (filemtime($tmp.'/'.$fname) < $expire) - @unlink($tmp.'/'.$fname); - } - - closedir($dir); - } + $rcmail = rcmail::get_instance()->temp_gc(); } - -// Deprecated function rcube_charset_convert($str, $from, $to=NULL) { return rcube_charset::convert($str, $from, $to); } - -// Deprecated function rc_detect_encoding($string, $failover='') { return rcube_charset::detect($string, $failover); } - -// Deprecated function rc_utf8_clean($input) { return rcube_charset::clean($input); } - -/** - * Convert a variable into a javascript object notation - * - * @param mixed Input value - * @return string Serialized JSON string - */ function json_serialize($input) { - $input = rcube_charset::clean($input); - - // sometimes even using rcube_charset::clean() the input contains invalid UTF-8 sequences - // that's why we have @ here - return @json_encode($input); + return rcube_output::json_serialize($input); } - -/** - * Replacing specials characters to a specific encoding type - * - * @param string Input string - * @param string Encoding type: text|html|xml|js|url - * @param string Replace mode for tags: show|replace|remove - * @param boolean Convert newlines - * @return string The quoted string - */ function rep_specialchars_output($str, $enctype='', $mode='', $newlines=TRUE) - { - static $html_encode_arr = false; - static $js_rep_table = false; - static $xml_rep_table = false; - - if (!$enctype) - $enctype = $OUTPUT->type; - - // encode for HTML output - if ($enctype=='html') - { - if (!$html_encode_arr) - { - $html_encode_arr = get_html_translation_table(HTML_SPECIALCHARS); - unset($html_encode_arr['?']); - } - - $ltpos = strpos($str, '<'); - $encode_arr = $html_encode_arr; - - // don't replace quotes and html tags - if (($mode=='show' || $mode=='') && $ltpos!==false && strpos($str, '>', $ltpos)!==false) - { - unset($encode_arr['"']); - unset($encode_arr['<']); - unset($encode_arr['>']); - unset($encode_arr['&']); - } - else if ($mode=='remove') - $str = strip_tags($str); - - $out = strtr($str, $encode_arr); - - // avoid douple quotation of & - $out = preg_replace('/&([A-Za-z]{2,6}|#[0-9]{2,4});/', '&\\1;', $out); - - return $newlines ? nl2br($out) : $out; - } - - // if the replace tables for XML and JS are not yet defined - if ($js_rep_table===false) - { - $js_rep_table = $xml_rep_table = array(); - $xml_rep_table['&'] = '&'; - - for ($c=160; $c<256; $c++) // can be increased to support more charsets - $xml_rep_table[chr($c)] = "&#$c;"; - - $xml_rep_table['"'] = '"'; - $js_rep_table['"'] = '\\"'; - $js_rep_table["'"] = "\\'"; - $js_rep_table["\\"] = "\\\\"; - // Unicode line and paragraph separators (#1486310) - $js_rep_table[chr(hexdec(E2)).chr(hexdec(80)).chr(hexdec(A8))] = '
'; - $js_rep_table[chr(hexdec(E2)).chr(hexdec(80)).chr(hexdec(A9))] = '
'; - } - - // encode for javascript use - if ($enctype=='js') - return preg_replace(array("/\r?\n/", "/\r/", '/<\\//'), array('\n', '\n', '<\\/'), strtr($str, $js_rep_table)); - - // encode for plaintext - if ($enctype=='text') - return str_replace("\r\n", "\n", $mode=='remove' ? strip_tags($str) : $str); - - if ($enctype=='url') - return rawurlencode($str); - - // encode for XML - if ($enctype=='xml') - return strtr($str, $xml_rep_table); - - // no encoding given -> return original string - return $str; - } - -/** - * Quote a given string. - * Shortcut function for rep_specialchars_output - * - * @return string HTML-quoted string - * @see rep_specialchars_output() - */ -function Q($str, $mode='strict', $newlines=TRUE) - { - return rep_specialchars_output($str, 'html', $mode, $newlines); - } - -/** - * Quote a given string for javascript output. - * Shortcut function for rep_specialchars_output - * - * @return string JS-quoted string - * @see rep_specialchars_output() - */ -function JQ($str) - { - return rep_specialchars_output($str, 'js'); - } - - -/** - * Read input value and convert it for internal use - * Performs stripslashes() and charset conversion if necessary - * - * @param string Field name to read - * @param int Source to get value from (GPC) - * @param boolean Allow HTML tags in field value - * @param string Charset to convert into - * @return string Field value or NULL if not available - */ -function get_input_value($fname, $source, $allow_html=FALSE, $charset=NULL) { - $value = NULL; - - if ($source == RCUBE_INPUT_GET) { - if (isset($_GET[$fname])) - $value = $_GET[$fname]; - } - else if ($source == RCUBE_INPUT_POST) { - if (isset($_POST[$fname])) - $value = $_POST[$fname]; - } - else if ($source == RCUBE_INPUT_GPC) { - if (isset($_POST[$fname])) - $value = $_POST[$fname]; - else if (isset($_GET[$fname])) - $value = $_GET[$fname]; - else if (isset($_COOKIE[$fname])) - $value = $_COOKIE[$fname]; - } - - return parse_input_value($value, $allow_html, $charset); + return rcube_ui::rep_specialchars_output($str, $enctype, $mode, $newlines); } -/** - * Parse/validate input value. See get_input_value() - * Performs stripslashes() and charset conversion if necessary - * - * @param string Input value - * @param boolean Allow HTML tags in field value - * @param string Charset to convert into - * @return string Parsed value - */ -function parse_input_value($value, $allow_html=FALSE, $charset=NULL) +function Q($str, $mode='strict', $newlines=TRUE) { - global $OUTPUT; - - if (empty($value)) - return $value; - - if (is_array($value)) { - foreach ($value as $idx => $val) - $value[$idx] = parse_input_value($val, $allow_html, $charset); - return $value; - } - - // strip single quotes if magic_quotes_sybase is enabled - if (ini_get('magic_quotes_sybase')) - $value = str_replace("''", "'", $value); - // strip slashes if magic_quotes enabled - else if (get_magic_quotes_gpc() || get_magic_quotes_runtime()) - $value = stripslashes($value); - - // remove HTML tags if not allowed - if (!$allow_html) - $value = strip_tags($value); - - $output_charset = is_object($OUTPUT) ? $OUTPUT->get_charset() : null; - - // remove invalid characters (#1488124) - if ($output_charset == 'UTF-8') - $value = rc_utf8_clean($value); - - // convert to internal charset - if ($charset && $output_charset) - $value = rcube_charset_convert($value, $output_charset, $charset); - - return $value; + return rcube_ui::Q($str, $mode, $newlines); } -/** - * Convert array of request parameters (prefixed with _) - * to a regular array with non-prefixed keys. - * - * @param int Source to get value from (GPC) - * @return array Hash array with all request parameters - */ -function request2param($mode = RCUBE_INPUT_GPC, $ignore = 'task|action') +function JQ($str) { - $out = array(); - $src = $mode == RCUBE_INPUT_GET ? $_GET : ($mode == RCUBE_INPUT_POST ? $_POST : $_REQUEST); - foreach ($src as $key => $value) { - $fname = $key[0] == '_' ? substr($key, 1) : $key; - if ($ignore && !preg_match('/^(' . $ignore . ')$/', $fname)) - $out[$fname] = get_input_value($key, $mode); - } - - return $out; + return rcube_ui::JQ($str); } -/** - * Remove all non-ascii and non-word chars - * except ., -, _ - */ -function asciiwords($str, $css_id = false, $replace_with = '') +function get_input_value($fname, $source, $allow_html=FALSE, $charset=NULL) { - $allowed = 'a-z0-9\_\-' . (!$css_id ? '\.' : ''); - return preg_replace("/[^$allowed]/i", $replace_with, $str); + return rcube_ui::get_input_value($fname, $source, $allow_html, $charset); } -/** - * Convert the given string into a valid HTML identifier - * Same functionality as done in app.js with rcube_webmail.html_identifier() - */ -function html_identifier($str, $encode=false) +function parse_input_value($value, $allow_html=FALSE, $charset=NULL) { - if ($encode) - return rtrim(strtr(base64_encode($str), '+/', '-_'), '='); - else - return asciiwords($str, true, '_'); + return rcube_ui::parse_input_value($value, $allow_html, $charset); } -/** - * Remove single and double quotes from given string - * - * @param string Input value - * @return string Dequoted string - */ -function strip_quotes($str) +function request2param($mode = RCUBE_INPUT_GPC, $ignore = 'task|action') { - return str_replace(array("'", '"'), '', $str); + return rcube_ui::request2param($mode, $ignore); } - -/** - * Remove new lines characters from given string - * - * @param string Input value - * @return string Stripped string - */ -function strip_newlines($str) +function html_identifier($str, $encode=false) { - return preg_replace('/[\r\n]/', '', $str); + return rcube_ui::html_identifier($str, $encode); } - -/** - * Create a HTML table based on the given data - * - * @param array Named table attributes - * @param mixed Table row data. Either a two-dimensional array or a valid SQL result set - * @param array List of cols to show - * @param string Name of the identifier col - * @return string HTML table code - */ function rcube_table_output($attrib, $table_data, $a_show_cols, $id_col) { - global $RCMAIL; - - $table = new html_table(/*array('cols' => count($a_show_cols))*/); - - // add table header - if (!$attrib['noheader']) - foreach ($a_show_cols as $col) - $table->add_header($col, Q(rcube_label($col))); - - $c = 0; - if (!is_array($table_data)) - { - $db = $RCMAIL->get_dbh(); - while ($table_data && ($sql_arr = $db->fetch_assoc($table_data))) - { - $table->add_row(array('id' => 'rcmrow' . html_identifier($sql_arr[$id_col]))); - - // format each col - foreach ($a_show_cols as $col) - $table->add($col, Q($sql_arr[$col])); - - $c++; - } - } - else { - foreach ($table_data as $row_data) - { - $class = !empty($row_data['class']) ? $row_data['class'] : ''; - - $table->add_row(array('id' => 'rcmrow' . html_identifier($row_data[$id_col]), 'class' => $class)); - - // format each col - foreach ($a_show_cols as $col) - $table->add($col, Q(is_array($row_data[$col]) ? $row_data[$col][0] : $row_data[$col])); - - $c++; - } - } - - return $table->show($attrib); + return rcube_ui::table_output($attrib, $table_data, $a_show_cols, $id_col); } - -/** - * Create an edit field for inclusion on a form - * - * @param string col field name - * @param string value field value - * @param array attrib HTML element attributes for field - * @param string type HTML element type (default 'text') - * @return string HTML field definition - */ function rcmail_get_edit_field($col, $value, $attrib, $type='text') { - static $colcounts = array(); - - $fname = '_'.$col; - $attrib['name'] = $fname . ($attrib['array'] ? '[]' : ''); - $attrib['class'] = trim($attrib['class'] . ' ff_' . $col); - - if ($type == 'checkbox') { - $attrib['value'] = '1'; - $input = new html_checkbox($attrib); - } - else if ($type == 'textarea') { - $attrib['cols'] = $attrib['size']; - $input = new html_textarea($attrib); - } - else if ($type == 'select') { - $input = new html_select($attrib); - $input->add('---', ''); - $input->add(array_values($attrib['options']), array_keys($attrib['options'])); - } - else if ($attrib['type'] == 'password') { - $input = new html_passwordfield($attrib); - } - else { - if ($attrib['type'] != 'text' && $attrib['type'] != 'hidden') - $attrib['type'] = 'text'; - $input = new html_inputfield($attrib); - } - - // use value from post - if (isset($_POST[$fname])) { - $postvalue = get_input_value($fname, RCUBE_INPUT_POST, true); - $value = $attrib['array'] ? $postvalue[intval($colcounts[$col]++)] : $postvalue; - } - - $out = $input->show($value); - - return $out; + return rcube_ui::get_edit_field($col, $value, $attrib, $type); } - -/** - * Replace all css definitions with #container [def] - * and remove css-inlined scripting - * - * @param string CSS source code - * @param string Container ID to use as prefix - * @return string Modified CSS source - */ function rcmail_mod_css_styles($source, $container_id, $allow_remote=false) - { - $last_pos = 0; - $replacements = new rcube_string_replacer; - - // ignore the whole block if evil styles are detected - $source = rcmail_xss_entity_decode($source); - $stripped = preg_replace('/[^a-z\(:;]/i', '', $source); - $evilexpr = 'expression|behavior|javascript:|import[^a]' . (!$allow_remote ? '|url\(' : ''); - if (preg_match("/$evilexpr/i", $stripped)) - return '/* evil! */'; - - // cut out all contents between { and } - while (($pos = strpos($source, '{', $last_pos)) && ($pos2 = strpos($source, '}', $pos))) { - $styles = substr($source, $pos+1, $pos2-($pos+1)); - - // check every line of a style block... - if ($allow_remote) { - $a_styles = preg_split('/;[\r\n]*/', $styles, -1, PREG_SPLIT_NO_EMPTY); - foreach ($a_styles as $line) { - $stripped = preg_replace('/[^a-z\(:;]/i', '', $line); - // ... and only allow strict url() values - if (stripos($stripped, 'url(') && !preg_match('!url\s*\([ "\'](https?:)//[a-z0-9/._+-]+["\' ]\)!Uims', $line)) { - $a_styles = array('/* evil! */'); - break; - } - } - $styles = join(";\n", $a_styles); - } - - $key = $replacements->add($styles); - $source = substr($source, 0, $pos+1) . $replacements->get_replacement($key) . substr($source, $pos2, strlen($source)-$pos2); - $last_pos = $pos+2; - } - - // remove html comments and add #container to each tag selector. - // also replace body definition because we also stripped off the tag - $styles = preg_replace( - array( - '/(^\s*\s*$)/', - '/(^\s*|,\s*|\}\s*)([a-z0-9\._#\*][a-z0-9\.\-_]*)/im', - '/'.preg_quote($container_id, '/').'\s+body/i', - ), - array( - '', - "\\1#$container_id \\2", - $container_id, - ), - $source); - - // put block contents back in - $styles = $replacements->resolve($styles); - - return $styles; - } - - -/** - * Decode escaped entities used by known XSS exploits. - * See http://downloads.securityfocus.com/vulnerabilities/exploits/26800.eml for examples - * - * @param string CSS content to decode - * @return string Decoded string - */ -function rcmail_xss_entity_decode($content) { - $out = html_entity_decode(html_entity_decode($content)); - $out = preg_replace_callback('/\\\([0-9a-f]{4})/i', 'rcmail_xss_entity_decode_callback', $out); - $out = preg_replace('#/\*.*\*/#Ums', '', $out); - return $out; + return rcube_ui::mod_css_styles($source, $container_id, $allow_remote); } - -/** - * preg_replace_callback callback for rcmail_xss_entity_decode_callback - * - * @param array matches result from preg_replace_callback - * @return string decoded entity - */ -function rcmail_xss_entity_decode_callback($matches) -{ - return chr(hexdec($matches[1])); +function rcmail_xss_entity_decode($content) +{ + return rcube_ui::xss_entity_decode($content); } -/** - * Compose a valid attribute string for HTML tags - * - * @param array Named tag attributes - * @param array List of allowed attributes - * @return string HTML formatted attribute string - */ function create_attrib_string($attrib, $allowed_attribs=array('id', 'class', 'style')) - { - // allow the following attributes to be added to the