diff options
author | thomascube <thomas@roundcube.net> | 2008-04-12 13:54:45 +0000 |
---|---|---|
committer | thomascube <thomas@roundcube.net> | 2008-04-12 13:54:45 +0000 |
commit | 47124c2279382714afd8dbe4a867a867ea179199 (patch) | |
tree | 9ce67f4521f466d8718604a23d74de1786189efd /program/include | |
parent | b00bd0f27d1c066d04fc8124c3a35465a5933ab1 (diff) |
Changed codebase to PHP5 with autoloader + added some new classes from the devel-vnext branch
Diffstat (limited to 'program/include')
19 files changed, 2648 insertions, 1754 deletions
diff --git a/program/include/bugs.inc b/program/include/bugs.inc index 9d98ef45b..78808c321 100644 --- a/program/include/bugs.inc +++ b/program/include/bugs.inc @@ -66,7 +66,7 @@ function raise_error($arg=array(), $log=false, $terminate=false) */ function log_bug($arg_arr) { - global $CONFIG, $INSTALL_PATH; + global $CONFIG; $program = $arg_arr['type']=='xpath' ? 'XPath' : strtoupper($arg_arr['type']); // write error to local log file @@ -81,7 +81,7 @@ function log_bug($arg_arr) $arg_arr['line']); if (empty($CONFIG['log_dir'])) - $CONFIG['log_dir'] = $INSTALL_PATH.'logs'; + $CONFIG['log_dir'] = INSTALL_PATH.'logs'; // try to open specific log file for writing if ($fp = @fopen($CONFIG['log_dir'].'/errors', 'a')) diff --git a/program/include/html.php b/program/include/html.php new file mode 100644 index 000000000..8af1b1f9d --- /dev/null +++ b/program/include/html.php @@ -0,0 +1,642 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | program/include/html.php | + | | + | This file is part of the RoundCube Webmail client | + | Copyright (C) 2005-2008, RoundCube Dev, - Switzerland | + | Licensed under the GNU GPL | + | | + | PURPOSE: | + | Helper class to create valid XHTML code | + | | + +-----------------------------------------------------------------------+ + | Author: Thomas Bruederli <roundcube@gmail.com> | + +-----------------------------------------------------------------------+ + + $Id: $ + + */ + + +/** + * Class for HTML code creation + * + * @package HTML + */ +class html +{ + protected $tagname; + protected $attrib = array(); + protected $allowed; + protected $content; + + protected static $common_attrib = array('id','class','style','title','align'); + public static $containers = array('div','span','p','h1','h2','h3','form','textarea'); + public static $lc_tags = true; + + /** + * Constructor + * + * @param array Hash array with tag attributes + */ + public function __construct($attrib = array()) + { + 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, $this->allowed); + } + + /****** STATIC METHODS *******/ + + /** + * Generic method to create a HTML tag + * + * @param string Tag name + * @param array Tag attributes as key/value pairs + * @param string Optinal Tag content (creates a container tag) + * @param array List with allowed attributes, omit to allow all + * @return string The XHTML tag + */ + public static function tag($tagname, $attrib = array(), $content = null, $allowed_attrib = null) + { + $inline_tags = array('a','span','img'); + $suffix = $attrib['nl'] || ($content && $attrib['nl'] !== false && !in_array($tagname, $inline_tags)) ? "\n" : ''; + + $tagname = self::$lc_tags ? strtolower($tagname) : $tagname; + if ($content || in_array($tagname, self::$containers)) { + $templ = $attrib['noclose'] ? "<%s%s>%s" : "<%s%s>%s</%s>%s"; + unset($attrib['noclose']); + return sprintf($templ, $tagname, self::attrib_string($attrib, $allowed_attrib), $content, $tagname, $suffix); + } + else { + return sprintf("<%s%s />%s", $tagname, self::attrib_string($attrib, $allowed_attrib), $suffix); + } + } + + /** + * Derrived method for <div> containers + * + * @param mixed Hash array with tag attributes or string with class name + * @param string 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); + } + return self::tag('div', $attr, $cont, self::$common_attrib); + } + + /** + * Derrived method for <p> blocks + * + * @param mixed Hash array with tag attributes or string with class name + * @param string 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); + } + return self::tag('p', $attr, $cont, self::$common_attrib); + } + + /** + * Derrived method to create <img /> + * + * @param mixed 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); + } + return self::tag('img', $attr + array('alt' => ''), null, array_merge(self::$common_attrib, array('src','alt','width','height','border','usemap'))); + } + + /** + * Derrived method for link tags + * + * @param mixed Hash array with tag attributes or string with link location (href) + * @param string Link content + * @return string HTML code + * @see html::tag() + */ + public static function a($attr, $cont) + { + if (is_string($attr)) { + $attr = array('href' => $attr); + } + return self::tag('a', $attr, $cont, array_merge(self::$common_attrib, array('href','target','name','onclick','onmouseover','onmouseout'))); + } + + /** + * Derrived method for inline span tags + * + * @param mixed Hash array with tag attributes or string with class name + * @param string Tag content + * @return string HTML code + * @see html::tag() + */ + public static function span($attr, $cont) + { + if (is_string($attr)) { + $attr = array('class' => $attr); + } + return self::tag('span', $attr, $cont, self::$common_attrib); + } + + /** + * Derrived method for form element labels + * + * @param mixed Hash array with tag attributes or string with 'for' attrib + * @param string Tag content + * @return string HTML code + * @see html::tag() + */ + public static function label($attr, $cont) + { + if (is_string($attr)) { + $attr = array('for' => $attr); + } + return self::tag('label', $attr, $cont, array_merge(self::$common_attrib, array('for'))); + } + + /** + * Derrived method for line breaks + * + * @return string HTML code + * @see html::tag() + */ + public static function br() + { + return self::tag('br'); + } + + /** + * Create string with attributes + * + * @param array Associative arry with tag attributes + * @param array List of allowed attributes + * @return string Valid attribute string + */ + public static function attrib_string($attrib = array(), $allowed = null) + { + if (empty($attrib)) { + return ''; + } + + $allowed_f = array_flip((array)$allowed); + $attrib_arr = array(); + foreach ($attrib as $key => $value) { + // skip size if not numeric + if (($key=='size' && !is_numeric($value))) { + continue; + } + + // ignore "internal" or not allowed attributes + if ($key == 'nl' || ($allowed && !isset($allowed_f[$key])) || $value === null) { + continue; + } + + // skip empty eventhandlers + if (preg_match('/^on[a-z]+/', $key) && !$value) { + continue; + } + + // attributes with no value + if (in_array($key, array('checked', 'multiple', 'disabled', 'selected'))) { + if ($value) { + $attrib_arr[] = sprintf('%s="%s"', $key, $key); + } + } + else if ($key=='value') { + $attrib_arr[] = sprintf('%s="%s"', $key, Q($value, 'strict', false)); + } + else { + $attrib_arr[] = sprintf('%s="%s"', $key, Q($value)); + } + } + return count($attrib_arr) ? ' '.implode(' ', $attrib_arr) : ''; + } +} + +/** + * Class to create an HTML input field + * + * @package HTML + */ +class html_inputfield extends html +{ + protected $tagname = 'input'; + protected $type = 'text'; + + public function __construct($attrib = array()) + { + if (is_array($attrib)) { + $this->attrib = $attrib; + } + + if ($attrib['type']) { + $this->type = $attrib['type']; + } + + if ($attrib['newline']) { + $this->newline = true; + } + } + + /** + * Compose input tag + * + * @param string Field value + * @param array 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 HTML + */ +class html_passwordfield extends html_inputfield +{ + protected $type = 'password'; +} + +/** + * Class to create an hidden HTML input field + * + * @package HTML + */ + +class html_hiddenfield extends html_inputfield +{ + protected $type = 'hidden'; + protected $fields_arr = array(); + protected $newline = true; + + /** + * Constructor + * + * @param array Named tag attributes + */ + public function __construct($attrib = null) + { + if (is_array($attrib)) { + $this->add($attrib); + } + } + + /** + * Add a hidden field to this instance + * + * @param array Named tag attributes + */ + public function add($attrib) + { + $this->fields_arr[] = $attrib; + } + + /** + * Create HTML code for the hidden fields + * + * @return string Final HTML code + */ + public function show() + { + $out = ''; + foreach ($this->fields_arr as $attrib) { + $out .= self::tag($this->tagname, array('type' => $this->type) + $attrib); + } + return $out; + } +} + +/** + * Class to create HTML radio buttons + * + * @package HTML + */ +class html_radiobutton extends html_inputfield +{ + protected $type = 'radio'; + + /** + * Get HTML code for this object + * + * @param string Value of the checked field + * @param array 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'] = ($value && (string)$value == (string)$this->attrib['value']); + + return parent::show(); + } +} + +/** + * Class to create HTML checkboxes + * + * @package HTML + */ +class html_checkbox extends html_inputfield +{ + protected $type = 'checkbox'; + + /** + * Get HTML code for this object + * + * @param string Value of the checked field + * @param array 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'] = ($value && (string)$value == (string)$this->attrib['value']); + + return parent::show(); + } +} + +/** + * Class to create an HTML textarea + * + * @package HTML + */ +class html_textarea extends html +{ + protected $tagname = 'textarea'; + protected $allowed_attrib = array('name','rows','cols','wrap'); + + /** + * Get HTML code for this object + * + * @param string Textbox value + * @param array 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 ($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) && !isset($this->attrib['mce_editable'])) { + $value = Q($value, 'strict', FALSE); + } + return self::tag($this->tagname, $this->attrib, Q($value), array_merge(self::$common_attrib, $this->allowed_attrib)); + } +} + +/** + * 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 instanciate can be used + * print $select->show('CH'); + * </pre> + * + * @package HTML + */ +class html_select extends html +{ + protected $tagname = 'select'; + protected $options = array(); + + /** + * Add a new option to this drop-down + * + * @param mixed Option name or array with option names + * @param mixed Option value or array with option values + */ + public function add($names, $values = null) + { + if (is_array($names)) { + foreach ($names as $i => $text) { + $this->options[] = array('text' => $text, 'value' => $values[$i]); + } + } + else { + $this->options[] = array('text' => $names, 'value' => $values); + } + } + + + /** + * Get HTML code for this object + * + * @param string Value of the selection option + * @param array Additional attributes to override + * @return string HTML output + */ + public function show($select = array(), $attrib = null) + { + // overwrite object attributes + if (is_array($attrib)) { + $this->attrib = array_merge($this->attrib, $attrib); + } + + $this->content = "\n"; + $select = (array)$select; + foreach ($this->options as $option) { + $attr = array( + 'value' => $option['value'], + 'selected' => ((!empty($option['value']) && in_array($option['value'], $select, true)) || + (in_array($option['text'], $select, TRUE))) ? 1 : null); + + $this->content .= self::tag('option', $attr, Q($option['text'])); + } + return parent::show(); + } +} + + +/** + * Class to build an HTML table + * + * @package HTML + */ +class html_table extends html +{ + protected $tagname = 'table'; + protected $allowed = array('id','class','style','width','summary','cellpadding','cellspacing','border'); + private $header = array(); + private $rows = array(); + private $rowindex = 0; + private $colindex = 0; + + + public function __construct($attrib = array()) + { + $this->attrib = array_merge($attrib, array('summary' => '', 'border' => 0)); + } + + /** + * Add a table cell + * + * @param array Cell attributes + * @param string Cell content + */ + public function add($attr, $cont) + { + if (is_string($attr)) { + $attr = array('class' => $attr); + } + + $cell = new stdClass; + $cell->attrib = $attr; + $cell->content = $cont; + + $this->rows[$this->rowindex]->cells[$this->colindex] = $cell; + $this->colindex++; + + if ($this->attrib['cols'] && $this->colindex == $this->attrib['cols']) { + $this->add_row(); + } + } + + /** + * Add a table header cell + * + * @param array Cell attributes + * @param string Cell content + */ + private function add_header($attr, $cont) + { + if (is_string($attr)) + $attr = array('class' => $attr); + + $cell = new stdClass; + $cell->attrib = $attr; + $cell->content = $cont; + $this->header[] = $cell; + } + + /** + * Jump to next row + * + * @param array Row attributes + */ + private function add_row($attr = array()) + { + $this->rowindex++; + $this->colindex = 0; + $this->rows[$this->rowindex] = new stdClass; + $this->rows[$this->rowindex]->attrib = $attr; + $this->rows[$this->rowindex]->cells = array(); + } + + + /** + * Build HTML output of the table data + * + * @param array Table attributes + * @return string The final table HTML code + */ + public function show($attr = array()) + { + $this->attrib = array_merge($this->attrib, $attr); + $thead = $tbody = ""; + + // include <thead> + if (!empty($this->header)) { + $rowcontent = ''; + foreach ($this->header as $c => $col) { + $rowcontent .= self::tag('th', $col->attrib, $col->content); + } + $thead = self::tag('thead', null, self::tag('tr', null, $rowcontent)); + } + + foreach ($this->rows as $r => $row) { + $rowcontent = ''; + foreach ($row->cells as $c => $col) { + $rowcontent .= self::tag('td', $col->attrib, $col->content); + } + + if ($r < $this->rowindex || count($row->cells)) { + $tbody .= self::tag('tr', $rows->attrib, $rowcontent); + } + } + + if ($this->attrib['rowsonly']) { + return $tbody; + } + + // add <tbody> + $this->content = $thead . self::tag('tbody', null, $tbody); + + unset($this->attrib['cols'], $this->attrib['rowsonly']); + return parent::show(); + } +} + +?>
\ No newline at end of file diff --git a/program/include/iniset.php b/program/include/iniset.php new file mode 100755 index 000000000..926b2826f --- /dev/null +++ b/program/include/iniset.php @@ -0,0 +1,98 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | program/include/iniset.inc | + | | + | This file is part of the RoundCube Webmail client | + | Copyright (C) 2008, RoundCube Dev, - Switzerland | + | Licensed under the GNU GPL | + | | + | PURPOSE: | + | Setup the application envoronment required to process | + | any request. | + +-----------------------------------------------------------------------+ + | Author: Till Klampaeckel <till@php.net> | + | Thomas Bruederli <roundcube@gmail.com> | + +-----------------------------------------------------------------------+ + + $Id: cache.inc 88 2005-12-03 16:54:12Z roundcube $ + +*/ + + +// application constants +define('RCMAIL_VERSION', '0.1-trunk'); +define('RCMAIL_CHARSET', 'UTF-8'); +define('JS_OBJECT_NAME', 'rcmail'); + +if (!defined('INSTALL_PATH')) { + define('INSTALL_PATH', dirname($_SERVER['SCRIPT_FILENAME']).'/'); +} + +// make sure path_separator is defined +if (!defined('PATH_SEPARATOR')) { + define('PATH_SEPARATOR', (eregi('win', PHP_OS) ? ';' : ':')); +} + +// 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 . PATH_SEPARATOR; +$include_path.= INSTALL_PATH . 'program' . PATH_SEPARATOR; +$include_path.= INSTALL_PATH . 'program/lib' . PATH_SEPARATOR; +$include_path.= INSTALL_PATH . 'program/include' . 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.'); +} + +ini_set('session.name', 'roundcube_sessid'); +ini_set('session.use_cookies', 1); +ini_set('session.gc_maxlifetime', 21600); +ini_set('session.gc_divisor', 500); +ini_set('error_reporting', E_ALL&~E_NOTICE); +set_magic_quotes_runtime(0); + +// increase maximum execution time for php scripts +// (does not work in safe mode) +if (!ini_get('safe_mode')) { + set_time_limit(120); +} + +/** + * Use PHP5 autoload for dynamic class loading + * + * @todo Make Zend, PEAR etc play with this + */ +function __autoload($classname) +{ + $filename = preg_replace( + array('/MDB2_(.+)/', '/Mail_(.+)/', '/^html_.+/', '/^utf8$/'), + array('MDB2/\\1', 'Mail/\\1', 'html', 'utf8.class'), + $classname + ); + include_once $filename. '.php'; +} + +/** + * Local callback function for PEAR errors + */ +function rcube_pear_error($err) +{ + error_log(sprintf("%s (%s): %s", + $err->getMessage(), + $err->getCode(), + $err->getUserinfo()), 0); +} + +// include global functions +require_once 'include/bugs.inc'; +require_once 'include/main.inc'; +require_once 'include/rcube_shared.inc'; + + +// set PEAR error handling (will also load the PEAR main class) +PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'rcube_pear_error'); + diff --git a/program/include/main.inc b/program/include/main.inc index 649dd25e9..6d548d8e5 100644 --- a/program/include/main.inc +++ b/program/include/main.inc @@ -27,9 +27,7 @@ */ require_once('lib/utf7.inc'); -require_once('include/rcube_user.inc'); require_once('include/rcube_shared.inc'); -require_once('include/rcmail_template.inc'); // fallback if not PHP modules are available @include_once('lib/des.inc'); @@ -50,15 +48,12 @@ define('RCUBE_INPUT_GPC', 0x0103); function rcmail_startup($task='mail') { global $sess_id, $sess_user_lang; - global $CONFIG, $INSTALL_PATH, $BROWSER, $OUTPUT, $_SESSION, $IMAP, $DB, $USER; + global $CONFIG, $OUTPUT, $IMAP, $DB, $USER; // start output buffering, we don't need any output yet, // it'll be cleared after reading of config files, etc. ob_start(); - // check client - $BROWSER = rcube_browser(); - // load configuration $CONFIG = rcmail_load_config(); @@ -74,10 +69,9 @@ function rcmail_startup($task='mail') // prepare DB connection $dbwrapper = empty($CONFIG['db_backend']) ? 'db' : $CONFIG['db_backend']; $dbclass = "rcube_" . $dbwrapper; - require_once("include/$dbclass.inc"); $DB = new $dbclass($CONFIG['db_dsnw'], $CONFIG['db_dsnr'], $CONFIG['db_persistent']); - $DB->sqlite_initials = $INSTALL_PATH.'SQL/sqlite.initial.sql'; + $DB->sqlite_initials = INSTALL_PATH.'SQL/sqlite.initial.sql'; $DB->set_debug((bool)$CONFIG['sql_debug']); $DB->db_connect('w'); @@ -136,8 +130,6 @@ function rcmail_startup($task='mail') */ function rcmail_load_config() { - global $INSTALL_PATH; - // load config file include_once('config/main.inc.php'); $conf = is_array($rcmail_config) ? $rcmail_config : array(); @@ -152,7 +144,7 @@ function rcmail_load_config() $conf = array_merge($conf, $rcmail_config); if (empty($conf['log_dir'])) - $conf['log_dir'] = $INSTALL_PATH.'logs'; + $conf['log_dir'] = INSTALL_PATH.'logs'; else $conf['log_dir'] = unslashify($conf['log_dir']); @@ -427,11 +419,10 @@ function get_sequence_name($sequence) */ function rcube_language_prop($lang, $prop='lang') { - global $INSTALL_PATH; static $rcube_languages, $rcube_language_aliases, $rcube_charsets; if (empty($rcube_languages)) - @include($INSTALL_PATH.'program/localization/index.inc'); + @include(INSTALL_PATH.'program/localization/index.inc'); // check if we have an alias for that language if (!isset($rcube_languages[$lang]) && isset($rcube_language_aliases[$lang])) @@ -451,7 +442,7 @@ function rcube_language_prop($lang, $prop='lang') if (isset($rcube_charsets[$lang])) $charset = $rcube_charsets[$lang]; else - $charset = 'UTF-8'; + $charset = 'UTF-8'; if ($prop=='charset') @@ -467,18 +458,15 @@ function rcube_language_prop($lang, $prop='lang') * environment vars according to the current session and configuration */ function rcmail_load_gui() - { +{ global $CONFIG, $OUTPUT, $sess_user_lang; // init output page - $OUTPUT = new rcmail_template($CONFIG, $GLOBALS['_task']); + $OUTPUT = new rcube_template($CONFIG, $GLOBALS['_task']); $OUTPUT->set_env('comm_path', $GLOBALS['COMM_PATH']); - if (is_array($CONFIG['javascript_config'])) - { - foreach ($CONFIG['javascript_config'] as $js_config_var) - $OUTPUT->set_env($js_config_var, $CONFIG[$js_config_var]); - } + foreach (array('read_when_deleted', 'flag_for_deletion') as $js_config_var) + $OUTPUT->set_env($js_config_var, $CONFIG[$js_config_var]); if (!empty($GLOBALS['_framed'])) $OUTPUT->set_env('framed', true); @@ -490,19 +478,23 @@ function rcmail_load_gui() if (!empty($CONFIG['charset'])) $OUTPUT->set_charset($CONFIG['charset']); - // register common UI objects - $OUTPUT->add_handlers(array( - 'loginform' => 'rcmail_login_form', - 'username' => 'rcmail_current_username', - 'message' => 'rcmail_message_container', - 'charsetselector' => 'rcmail_charset_selector', - )); - // add some basic label to client - if (!$OUTPUT->ajax_call) - rcube_add_label('loading', 'movingmessage'); - } + $OUTPUT->add_label('loading', 'movingmessage'); +} +/** + * Create an output object for JSON responses + */ +function rcmail_init_json() +{ + global $CONFIG, $OUTPUT; + + // init output object + $OUTPUT = new rcube_json_output($CONFIG, $GLOBALS['_task']); + + // set locale setting + rcmail_set_locale($sess_user_lang); +} /** * Set localization charset based on the given language. @@ -878,18 +870,18 @@ function get_des_key() */ function rcube_list_languages() { - global $CONFIG, $INSTALL_PATH; + global $CONFIG; static $sa_languages = array(); if (!sizeof($sa_languages)) { - @include($INSTALL_PATH.'program/localization/index.inc'); + @include(INSTALL_PATH.'program/localization/index.inc'); - if ($dh = @opendir($INSTALL_PATH.'program/localization')) + 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]) @@ -904,6 +896,7 @@ function rcube_list_languages() /** * Add a localized label to the client environment + * @deprecated */ function rcube_add_label() { @@ -911,7 +904,7 @@ function rcube_add_label() $arg_list = func_get_args(); foreach ($arg_list as $i => $name) - $OUTPUT->command('add_label', $name, rcube_label($name)); + $OUTPUT->add_label($name); } @@ -1135,7 +1128,7 @@ function rep_specialchars_output($str, $enctype='', $mode='', $newlines=TRUE) if ($OUTPUT->get_charset()!='UTF-8') $str = rcube_charset_convert($str, RCMAIL_CHARSET, $OUTPUT->get_charset()); - return preg_replace(array("/\r?\n/", "/\r/"), array('\n', '\n'), addslashes(strtr($str, $js_rep_table))); + return preg_replace(array("/\r?\n/", "/\r/", '/<\\//'), array('\n', '\n', '<\\/'), addslashes(strtr($str, $js_rep_table))); } // no encoding given -> return original string @@ -1261,16 +1254,6 @@ function template_exists($name) /** - * Wrapper for rcmail_template::parse() - * @deprecated - */ -function parse_template($name='main', $exit=true) - { - $GLOBALS['OUTPUT']->parse($name, $exit); - } - - -/** * Create a HTML table based on the given data * * @param array Named table attributes @@ -1360,15 +1343,15 @@ function rcmail_get_edit_field($col, $value, $attrib, $type='text') if ($type=='checkbox') { $attrib['value'] = '1'; - $input = new checkbox($attrib); + $input = new html_checkbox($attrib); } else if ($type=='textarea') { $attrib['cols'] = $attrib['size']; - $input = new textarea($attrib); + $input = new html_textarea($attrib); } else - $input = new textfield($attrib); + $input = new html_inputfield($attrib); // use value from post if (!empty($_POST[$fname])) @@ -1645,7 +1628,7 @@ function console($msg) */ function write_log($name, $line) { - global $CONFIG, $INSTALL_PATH; + global $CONFIG; if (!is_string($line)) $line = var_export($line, true); @@ -1655,7 +1638,7 @@ function write_log($name, $line) $line); if (empty($CONFIG['log_dir'])) - $CONFIG['log_dir'] = $INSTALL_PATH.'logs'; + $CONFIG['log_dir'] = INSTALL_PATH.'logs'; // try to open specific log file for writing if ($fp = @fopen($CONFIG['log_dir'].'/'.$name, 'a')) diff --git a/program/include/rcmail_template.inc b/program/include/rcmail_template.inc deleted file mode 100644 index 301b3f20d..000000000 --- a/program/include/rcmail_template.inc +++ /dev/null @@ -1,948 +0,0 @@ -<?php - -/* - +-----------------------------------------------------------------------+ - | program/include/rcmail_template.inc | - | | - | This file is part of the RoundCube Webmail client | - | Copyright (C) 2007, RoundCube Dev. - Switzerland | - | Licensed under the GNU GPL | - | | - | PURPOSE: | - | Class to handle HTML page output using a skin template. | - | Extends rcube_html_page class from rcube_html.inc | - | | - +-----------------------------------------------------------------------+ - | Author: Thomas Bruederli <roundcube@gmail.com> | - +-----------------------------------------------------------------------+ - - $Id: $ - -*/ - - -/** - * Classes and functions for HTML output - * - * @package View - */ - -require_once('include/rcube_html.inc'); - - -/** - * Class to create HTML page output using a skin template - */ -class rcmail_template extends rcube_html_page -{ - var $config; - var $task = ''; - var $framed = false; - var $ajax_call = false; - var $pagetitle = ''; - var $env = array(); - var $js_env = array(); - var $js_commands = array(); - var $object_handlers = array(); - - - /** - * Constructor - * - * @param array Configuration array - * @param string Current task - */ - function __construct(&$config, $task) - { - $this->task = $task; - $this->config = $config; - $this->ajax_call = !empty($_GET['_remote']) || !empty($_POST['_remote']); - - // add common javascripts - if (!$this->ajax_call) - { - $javascript = "var ".JS_OBJECT_NAME." = new rcube_webmail();"; - - // don't wait for page onload. Call init at the bottom of the page (delayed) - $javascript_foot = "if (window.call_init)\n call_init('".JS_OBJECT_NAME."');"; - - $this->add_script($javascript, 'head_top'); - $this->add_script($javascript_foot, 'foot'); - $this->scripts_path = 'program/js/'; - $this->include_script('common.js'); - $this->include_script('app.js'); - } - } - - /** - * PHP 4 compatibility - * @see rcmail_template::__construct() - */ - function rcmail_template(&$config, $task) - { - $this->__construct($config, $task); - } - - - /** - * Set environment variable - * - * @param string Property name - * @param mixed Property value - * @param boolean True if this property should be added to client environment - */ - function set_env($name, $value, $addtojs=true) - { - $this->env[$name] = $value; - if ($addtojs || isset($this->js_env[$name])) - $this->js_env[$name] = $value; - } - - - /** - * Set page title variable - */ - function set_pagetitle($title) - { - $this->pagetitle = $title; - } - - - /** - * Register a template object handler - * - * @param string Object name - * @param string Function name to call - */ - function add_handler($obj, $func) - { - $this->object_handlers[$obj] = $func; - } - - /** - * Register a list of template object handlers - * - * @param array Hash array with object=>handler pairs - */ - function add_handlers($arr) - { - $this->object_handlers = array_merge($this->object_handlers, $arr); - } - - /** - * Register a GUI object to the client script - * - * @param string Object name - * @param string Object ID - */ - function add_gui_object($obj, $id) - { - $this->add_script(JS_OBJECT_NAME.".gui_object('$obj', '$id');"); - } - - - /** - * Call a client method - * - * @param string Method to call - * @param ... Additional arguments - */ - function command() - { - $this->js_commands[] = func_get_args(); - } - - - /** - * Invoke display_message command - * - * @param string Message to display - * @param string Message type [notice|confirm|error] - * @param array Key-value pairs to be replaced in localized text - */ - function show_message($message, $type='notice', $vars=NULL) - { - $this->command( - 'display_message', - rcube_label(array('name' => $message, 'vars' => $vars)), - $type); - } - - - /** - * Delete all stored env variables and commands - */ - function reset() - { - $this->env = array(); - $this->js_env = array(); - $this->js_commands = array(); - $this->object_handlers = array(); - parent::reset(); - } - - /** - * Send the request output to the client. - * This will either parse a skin tempalte or send an AJAX response - * - * @param string Template name - * @param boolean True if script should terminate (default) - */ - function send($templ=null, $exit=true) - { - if ($this->ajax_call) - $this->remote_response('', !$exit); - else if ($templ != 'iframe') - $this->parse($templ, false); - else - { - $this->framed = $templ == 'iframe' ? true : $this->framed; - $this->write(); - } - - if ($exit) - exit; - } - - - /** - * Send an AJAX response with executable JS code - * - * @param string Additional JS code - * @param boolean True if output buffer should be flushed - */ - function remote_response($add='', $flush=false) - { - static $s_header_sent = FALSE; - - if (!$s_header_sent) - { - $s_header_sent = TRUE; - send_nocacheing_headers(); - header('Content-Type: application/x-javascript; charset='.RCMAIL_CHARSET); - print '/** ajax response ['.date('d/M/Y h:i:s O')."] **/\n"; - } - - // unset default env vars - unset($this->js_env['task'], $this->js_env['action'], $this->js_env['comm_path']); - - // send response code - print rcube_charset_convert($this->get_js_commands() . $add, RCMAIL_CHARSET, $this->get_charset()); - - if ($flush) // flush the output buffer - flush(); - } - - - /** - * Process template and write to stdOut - * - * @param string HTML template - * @see rcube_html_page::write() - */ - function write($template='') - { - // unlock interface after iframe load - if ($this->framed) - array_unshift($this->js_commands, array('set_busy', false)); - - // write all env variables to client - $js = $this->framed ? "if(window.parent) {\n" : ''; - $js .= $this->get_js_commands() . ($this->framed ? ' }' : ''); - $this->add_script($js, 'head_top'); - - // call super method - parent::write($template, $this->config['skin_path']); - } - - - /** - * Parse a specific skin template and deliver to stdout - * - * @param string Template name - * @param boolean Exit script - */ - function parse($name='main', $exit=true) - { - $skin_path = $this->config['skin_path']; - - // read template file - $templ = ''; - $path = "$skin_path/templates/$name.html"; - - if($fp = @fopen($path, 'r')) - { - $templ = fread($fp, filesize($path)); - fclose($fp); - } - else - { - raise_error(array( - 'code' => 501, - 'type' => 'php', - 'line' => __LINE__, - 'file' => __FILE__, - 'message' => "Error loading template for '$name'"), TRUE, TRUE); - return FALSE; - } - - // parse for specialtags - $output = $this->parse_xml($this->parse_conditions($templ)); - - // add debug console - if ($this->config['debug_level'] & 8) - $this->add_footer('<div style="position:absolute;top:5px;left:5px;width:400px;padding:0.2em;background:white;opacity:0.8;z-index:9000"> - <a href="#toggle" onclick="con=document.getElementById(\'dbgconsole\');con.style.display=(con.style.display==\'none\'?\'block\':\'none\');return false">console</a> - <form action="/" name="debugform"><textarea name="console" id="dbgconsole" rows="20" cols="40" wrap="off" style="display:none;width:400px;border:none;font-size:x-small"></textarea></form></div>'); - - $this->write(trim($this->parse_with_globals($output)), $skin_path); - - if ($exit) - exit; - } - - - /** - * Return executable javascript code for all registered commands - * @access private - */ - function get_js_commands() - { - $out = ''; - if (!$this->framed && !empty($this->js_env)) - $out .= ($this->ajax_call ? 'this' : JS_OBJECT_NAME) . '.set_env('.json_serialize($this->js_env).");\n"; - - // add command to set page title - if ($this->ajax_call && !empty($this->pagetitle)) - $out .= sprintf( - "this.set_pagetitle('%s');\n", - JQ((!empty($this->config['product_name']) ? $this->config['product_name'].' :: ' : '') . $this->pagetitle) - ); - - foreach ($this->js_commands as $i => $args) - { - $method = array_shift($args); - foreach ($args as $i => $arg) - $args[$i] = json_serialize($arg); - - $parent = $this->framed || preg_match('/^parent\./', $method); - $out .= sprintf( - "%s.%s(%s);\n", - $this->ajax_call ? 'this' : ($parent ? 'parent.' : '') . JS_OBJECT_NAME, - preg_replace('/^parent\./', '', $method), - join(',', $args)); - } - - - - return $out; - } - - /** - * Make URLs starting with a slash point to skin directory - * @access private - */ - function abs_url($str) - { - return preg_replace('/^\//', $this->config['skin_path'].'/', $str); - } - - - - /***** Template parsing methods *****/ - - /** - * Replace all strings ($varname) - * with the content of the according global variable. - * @access private - */ - function parse_with_globals($input) - { - $GLOBALS['__comm_path'] = Q($GLOBALS['COMM_PATH']); - return preg_replace('/\$(__[a-z0-9_\-]+)/e', '$GLOBALS["\\1"]', $input); - } - - - /** - * Parse for conditional tags - * @access private - */ - function parse_conditions($input) - { - if (($matches = preg_split('/<roundcube:(if|elseif|else|endif)\s+([^>]+)>/is', $input, 2, PREG_SPLIT_DELIM_CAPTURE)) && count($matches)==4) - { - if (preg_match('/^(else|endif)$/i', $matches[1])) - return $matches[0] . $this->parse_conditions($matches[3]); - else - { - $attrib = parse_attrib_string($matches[2]); - if (isset($attrib['condition'])) - { - $condmet = $this->check_condition($attrib['condition']); - $submatches = preg_split('/<roundcube:(elseif|else|endif)\s+([^>]+)>/is', $matches[3], 2, PREG_SPLIT_DELIM_CAPTURE); - - if ($condmet) - $result = $submatches[0] . ($submatches[1] != 'endif' ? preg_replace('/.*<roundcube:endif\s+[^>]+>/Uis', '', $submatches[3], 1) : $submatches[3]); - else - $result = "<roundcube:$submatches[1] $submatches[2]>" . $submatches[3]; - - return $matches[0] . $this->parse_conditions($result); - } - else - { - raise_error(array('code' => 500, 'type' => 'php', 'line' => __LINE__, 'file' => __FILE__, - 'message' => "Unable to parse conditional tag " . $matches[2]), TRUE, FALSE); - } - } - } - - return $input; - } - - - /** - * Determines if a given condition is met - * - * @return True if condition is valid, False is not - * @access private - */ - function check_condition($condition) - { - $condition = preg_replace( - array('/session:([a-z0-9_]+)/i', '/config:([a-z0-9_]+)/i', '/env:([a-z0-9_]+)/i', '/request:([a-z0-9_]+)/ie'), - array("\$_SESSION['\\1']", "\$this->config['\\1']", "\$this->env['\\1']", "get_input_value('\\1', RCUBE_INPUT_GPC)"), - $condition); - - return @eval("return (".$condition.");"); - } - - - /** - * Search for special tags in input and replace them - * with the appropriate content - * - * @param string Input string to parse - * @return Altered input string - * @access private - */ - function parse_xml($input) - { - return preg_replace('/<roundcube:([-_a-z]+)\s+([^>]+)>/Uie', "\$this->xml_command('\\1', '\\2')", $input); - } - - - /** - * Convert a xml command tag into real content - * - * @param string Tag command: object,button,label, etc. - * @param string Attribute string - * @return Tag/Object content string - * @access private - */ - function xml_command($command, $str_attrib, $add_attrib=array()) - { - $command = strtolower($command); - $attrib = parse_attrib_string($str_attrib) + $add_attrib; - - // empty output if required condition is not met - if (!empty($attrib['condition']) && !$this->check_condition($attrib['condition'])) - return ''; - - // execute command - switch ($command) - { - // return a button - case 'button': - return $this->button($attrib); - break; - - // show a label - case 'label': - if ($attrib['name'] || $attrib['command']) - return Q(rcube_label($attrib + array('vars' => array('product' => $this->config['product_name'])))); - break; - - // include a file - case 'include': - $path = realpath($this->config['skin_path'].$attrib['file']); - if (filesize($path)) - { - if ($this->config['skin_include_php']) - $incl = $this->include_php($path); - else if ($fp = @fopen($path, 'r')) - { - $incl = fread($fp, filesize($path)); - fclose($fp); - } - return $this->parse_xml($incl); - } - break; - - // return code for a specific application object - case 'object': - $object = strtolower($attrib['name']); - - // execute object handler function - if ($this->object_handlers[$object] && function_exists($this->object_handlers[$object])) - return call_user_func($this->object_handlers[$object], $attrib); - - else if ($object=='productname') - { - $name = !empty($this->config['product_name']) ? $this->config['product_name'] : 'RoundCube Webmail'; - return Q($name); - } - else if ($object=='version') - { - return (string)RCMAIL_VERSION; - } - else if ($object=='pagetitle') - { - $task = $this->task; - $title = !empty($this->config['product_name']) ? $this->config['product_name'].' :: ' : ''; - - if (!empty($this->pagetitle)) - $title .= $this->pagetitle; - else if ($task == 'login') - $title = rcube_label(array('name' => 'welcome', 'vars' => array('product' => $this->config['product_name']))); - else - $title .= ucfirst($task); - - return Q($title); - } - - break; - - // return variable - case 'var': - $var = explode(':', $attrib['name']); - $name = $var[1]; - $value = ''; - - switch ($var[0]) - { - case 'env': - $value = $this->env[$name]; - break; - case 'config': - $value = $this->config[$name]; - if (is_array($value) && $value[$_SESSION['imap_host']]) - $value = $value[$_SESSION['imap_host']]; - break; - case 'request': - $value = get_input_value($name, RCUBE_INPUT_GPC); - break; - case 'session': - $value = $_SESSION[$name]; - break; - } - - if (is_array($value)) - $value = join(", ", $value); - - return Q($value); - } - - return ''; - } - - - /** - * Include a specific file and return it's contents - * - * @param string File path - * @return string Contents of the processed file - */ - function include_php($file) - { - ob_start(); - @include($file); - $out = ob_get_contents(); - ob_end_clean(); - - return $out; - } - - - /** - * Create and register a button - * - * @param array Button attributes - * @return HTML button - * @access private - */ - function button($attrib) - { - global $CONFIG, $OUTPUT, $BROWSER, $MAIN_TASKS; - static $sa_buttons = array(); - static $s_button_count = 100; - - // these commands can be called directly via url - $a_static_commands = array('compose', 'list'); - - $skin_path = $this->config['skin_path']; - - if (!($attrib['command'] || $attrib['name'] || $attrib['onclick'])) - return ''; - - // try to find out the button type - if ($attrib['type']) - $attrib['type'] = strtolower($attrib['type']); - else - $attrib['type'] = ($attrib['image'] || $attrib['imagepas'] || $attrib['imageact']) ? 'image' : 'link'; - - $command = $attrib['command']; - - // take the button from the stack - if($attrib['name'] && $sa_buttons[$attrib['name']]) - $attrib = $sa_buttons[$attrib['name']]; - - // add button to button stack - else if($attrib['image'] || $attrib['imageact'] || $attrib['imagepas'] || $attrib['class']) - { - if (!$attrib['name']) - $attrib['name'] = $command; - - if (!$attrib['image']) - $attrib['image'] = $attrib['imagepas'] ? $attrib['imagepas'] : $attrib['imageact']; - - $sa_buttons[$attrib['name']] = $attrib; - } - - // get saved button for this command/name - else if ($command && $sa_buttons[$command]) - $attrib = $sa_buttons[$command]; - - //else - // return ''; - - - // set border to 0 because of the link arround the button - if ($attrib['type']=='image' && !isset($attrib['border'])) - $attrib['border'] = 0; - - if (!$attrib['id']) - $attrib['id'] = sprintf('rcmbtn%d', $s_button_count++); - - // get localized text for labels and titles - if ($attrib['title']) - $attrib['title'] = Q(rcube_label($attrib['title'])); - if ($attrib['label']) - $attrib['label'] = Q(rcube_label($attrib['label'])); - - if ($attrib['alt']) - $attrib['alt'] = Q(rcube_label($attrib['alt'])); - - // set title to alt attribute for IE browsers - if ($BROWSER['ie'] && $attrib['title'] && !$attrib['alt']) - { - $attrib['alt'] = $attrib['title']; - unset($attrib['title']); - } - - // add empty alt attribute for XHTML compatibility - if (!isset($attrib['alt'])) - $attrib['alt'] = ''; - - - // register button in the system - if ($attrib['command']) - { - $this->add_script(sprintf( - "%s.register_button('%s', '%s', '%s', '%s', '%s', '%s');", - JS_OBJECT_NAME, - $command, - $attrib['id'], - $attrib['type'], - $attrib['imageact'] ? $skin_path.$attrib['imageact'] : $attrib['classact'], - $attrib['imagesel'] ? $skin_path.$attrib['imagesel'] : $attrib['classsel'], - $attrib['imageover'] ? $skin_path.$attrib['imageover'] : '') - ); - - // make valid href to specific buttons - if (in_array($attrib['command'], $MAIN_TASKS)) - $attrib['href'] = Q(rcmail_url(null, null, $attrib['command'])); - else if (in_array($attrib['command'], $a_static_commands)) - $attrib['href'] = Q(rcmail_url($attrib['command'])); - } - - // overwrite attributes - if (!$attrib['href']) - $attrib['href'] = '#'; - - if ($command) - $attrib['onclick'] = sprintf("return %s.command('%s','%s',this)", JS_OBJECT_NAME, $command, $attrib['prop']); - - if ($command && $attrib['imageover']) - { - $attrib['onmouseover'] = sprintf("return %s.button_over('%s','%s')", JS_OBJECT_NAME, $command, $attrib['id']); - $attrib['onmouseout'] = sprintf("return %s.button_out('%s','%s')", JS_OBJECT_NAME, $command, $attrib['id']); - } - - if ($command && $attrib['imagesel']) - { - $attrib['onmousedown'] = sprintf("return %s.button_sel('%s','%s')", JS_OBJECT_NAME, $command, $attrib['id']); - $attrib['onmouseup'] = sprintf("return %s.button_out('%s','%s')", JS_OBJECT_NAME, $command, $attrib['id']); - } - - $out = ''; - - // generate image tag - if ($attrib['type']=='image') - { - $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id', 'width', 'height', 'border', 'hspace', 'vspace', 'align', 'alt')); - $img_tag = sprintf('<img src="%%s"%s />', $attrib_str); - $btn_content = sprintf($img_tag, $skin_path.$attrib['image']); - if ($attrib['label']) - $btn_content .= ' '.$attrib['label']; - - $link_attrib = array('href', 'onclick', 'onmouseover', 'onmouseout', 'onmousedown', 'onmouseup', 'title'); - } - else if ($attrib['type']=='link') - { - $btn_content = $attrib['label'] ? $attrib['label'] : $attrib['command']; - $link_attrib = array('href', 'onclick', 'title', 'id', 'class', 'style'); - } - else if ($attrib['type']=='input') - { - $attrib['type'] = 'button'; - - if ($attrib['label']) - $attrib['value'] = $attrib['label']; - - $attrib_str = create_attrib_string($attrib, array('type', 'value', 'onclick', 'id', 'class', 'style')); - $out = sprintf('<input%s disabled="disabled" />', $attrib_str); - } - - // generate html code for button - if ($btn_content) - { - $attrib_str = create_attrib_string($attrib, $link_attrib); - $out = sprintf('<a%s>%s</a>', $attrib_str, $btn_content); - } - - return $out; - } - -} // end class rcmail_template - - - -// ************** common functions delivering gui objects ************** - - -/** - * Builder for GUI object 'message' - * - * @param array Named tag parameters - * @return string HTML code for the gui object - */ -function rcmail_message_container($attrib) - { - global $OUTPUT; - - if (!$attrib['id']) - $attrib['id'] = 'rcmMessageContainer'; - - // allow the following attributes to be added to the <table> tag - $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id')); - $out = '<div' . $attrib_str . "></div>"; - - $OUTPUT->add_gui_object('message', $attrib['id']); - - return $out; - } - - -/** - * GUI object 'username' - * Showing IMAP username of the current session - * - * @param array Named tag parameters (currently not used) - * @return string HTML code for the gui object - */ -function rcmail_current_username($attrib) - { - global $USER; - static $s_username; - - // alread fetched - if (!empty($s_username)) - return $s_username; - - if ($sql_arr = $USER->get_identity()) - $s_username = $sql_arr['email']; - else if (strstr($_SESSION['username'], '@')) - $s_username = $_SESSION['username']; - else - $s_username = $_SESSION['username'].'@'.$_SESSION['imap_host']; - - return $s_username; - } - - -/** - * GUI object 'loginform' - * Returns code for the webmail login form - * - * @param array Named parameters - * @return string HTML code for the gui object - */ -function rcmail_login_form($attrib) - { - global $CONFIG, $OUTPUT, $SESS_HIDDEN_FIELD; - - $labels = array(); - $labels['user'] = rcube_label('username'); - $labels['pass'] = rcube_label('password'); - $labels['host'] = rcube_label('server'); - - $input_user = new textfield(array('name' => '_user', 'id' => 'rcmloginuser', 'size' => 30) + $attrib); - $input_pass = new passwordfield(array('name' => '_pass', 'id' => 'rcmloginpwd', 'size' => 30) + $attrib); - $input_action = new hiddenfield(array('name' => '_action', 'value' => 'login')); - - $fields = array(); - $fields['user'] = $input_user->show(get_input_value('_user', RCUBE_INPUT_POST)); - $fields['pass'] = $input_pass->show(); - $fields['action'] = $input_action->show(); - - if (is_array($CONFIG['default_host'])) - { - $select_host = new select(array('name' => '_host', 'id' => 'rcmloginhost')); - - foreach ($CONFIG['default_host'] as $key => $value) - { - if (!is_array($value)) - $select_host->add($value, (is_numeric($key) ? $value : $key)); - else - { - unset($select_host); - break; - } - } - - $fields['host'] = isset($select_host) ? $select_host->show(get_input_value('_host', RCUBE_INPUT_POST)) : null; - } - else if (!strlen($CONFIG['default_host'])) - { - $input_host = new textfield(array('name' => '_host', 'id' => 'rcmloginhost', 'size' => 30)); - $fields['host'] = $input_host->show(get_input_value('_host', RCUBE_INPUT_POST)); - } - - $form_name = strlen($attrib['form']) ? $attrib['form'] : 'form'; - $form_start = !strlen($attrib['form']) ? '<form name="form" action="./" method="post">' : ''; - $form_end = !strlen($attrib['form']) ? '</form>' : ''; - - if ($fields['host']) - $form_host = <<<EOF - -</tr><tr> - -<td class="title"><label for="rcmloginhost">$labels[host]</label></td> -<td>$fields[host]</td> - -EOF; - - $OUTPUT->add_gui_object('loginform', $form_name); - - $out = <<<EOF -$form_start -$SESS_HIDDEN_FIELD -$fields[action] -<table><tr> - -<td class="title"><label for="rcmloginuser">$labels[user]</label></td> -<td>$fields[user]</td> - -</tr><tr> - -<td class="title"><label for="rcmloginpwd">$labels[pass]</label></td> -<td>$fields[pass]</td> -$form_host -</tr></table> -$form_end -EOF; - - return $out; - } - - -/** - * GUI object 'charsetselector' - * - * @param array Named parameters for the select tag - * @return string HTML code for the gui object - */ -function rcmail_charset_selector($attrib) - { - global $OUTPUT; - - // pass the following attributes to the form class - $field_attrib = array('name' => '_charset'); - foreach ($attrib as $attr => $value) - if (in_array($attr, array('id', 'class', 'style', 'size', 'tabindex'))) - $field_attrib[$attr] = $value; - - $charsets = array( - 'US-ASCII' => 'ASCII (English)', - 'EUC-JP' => 'EUC-JP (Japanese)', - 'EUC-KR' => 'EUC-KR (Korean)', - 'BIG5' => 'BIG5 (Chinese)', - 'GB2312' => 'GB2312 (Chinese)', - 'ISO-2022-JP' => 'ISO-2022-JP (Japanese)', - 'ISO-8859-1' => 'ISO-8859-1 (Latin-1)', - 'ISO-8859-2' => 'ISO-8895-2 (Central European)', - 'ISO-8859-7' => 'ISO-8859-7 (Greek)', - 'ISO-8859-9' => 'ISO-8859-9 (Turkish)', - 'Windows-1251' => 'Windows-1251 (Cyrillic)', - 'Windows-1252' => 'Windows-1252 (Western)', - 'Windows-1255' => 'Windows-1255 (Hebrew)', - 'Windows-1256' => 'Windows-1256 (Arabic)', - 'Windows-1257' => 'Windows-1257 (Baltic)', - 'UTF-8' => 'UTF-8' - ); - - $select = new select($field_attrib); - $select->add(array_values($charsets), array_keys($charsets)); - - $set = $_POST['_charset'] ? $_POST['_charset'] : $OUTPUT->get_charset(); - return $select->show($set); - } - - -/** - * GUI object 'searchform' - * Returns code for search function - * - * @param array Named parameters - * @return string HTML code for the gui object - */ -function rcmail_search_form($attrib) - { - global $OUTPUT; - - // add some labels to client - rcube_add_label('searching'); - - $attrib['name'] = '_q'; - - if (empty($attrib['id'])) - $attrib['id'] = 'rcmqsearchbox'; - - $input_q = new textfield($attrib); - $out = $input_q->show(); - - $OUTPUT->add_gui_object('qsearchbox', $attrib['id']); - - // add form tag around text field - if (empty($attrib['form'])) - $out = sprintf( - '<form name="rcmqsearchform" action="./" '. - 'onsubmit="%s.command(\'search\');return false" style="display:inline;">%s</form>', - JS_OBJECT_NAME, - $out); - - return $out; - } - - -?> diff --git a/program/include/rcube_browser.php b/program/include/rcube_browser.php new file mode 100644 index 000000000..af393d63e --- /dev/null +++ b/program/include/rcube_browser.php @@ -0,0 +1,75 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | program/include/rcube_browser.php | + | | + | This file is part of the RoundCube Webmail client | + | Copyright (C) 2007-2008, RoundCube Dev. - Switzerland | + | Licensed under the GNU GPL | + | | + | PURPOSE: | + | Class representing the client browser's properties | + | | + +-----------------------------------------------------------------------+ + | Author: Thomas Bruederli <roundcube@gmail.com> | + +-----------------------------------------------------------------------+ + + $Id: rcube_browser.php 328 2006-08-30 17:41:21Z thomasb $ + +*/ + +/** + * rcube_browser + * + * Provide details about the client's browser based on the User-Agent header + * + * @package Core + */ +class rcube_browser +{ + function __construct() + { + $HTTP_USER_AGENT = $_SERVER['HTTP_USER_AGENT']; + + $this->ver = 0; + $this->win = stristr($HTTP_USER_AGENT, 'win'); + $this->mac = stristr($HTTP_USER_AGENT, 'mac'); + $this->linux = stristr($HTTP_USER_AGENT, 'linux'); + $this->unix = stristr($HTTP_USER_AGENT, 'unix'); + + $this->ns4 = stristr($HTTP_USER_AGENT, 'mozilla/4') && !stristr($HTTP_USER_AGENT, 'msie'); + $this->ns = ($this->ns4 || stristr($HTTP_USER_AGENT, 'netscape')); + $this->ie = stristr($HTTP_USER_AGENT, 'msie'); + $this->mz = stristr($HTTP_USER_AGENT, 'mozilla/5'); + $this->opera = stristr($HTTP_USER_AGENT, 'opera'); + $this->safari = stristr($HTTP_USER_AGENT, 'safari'); + + if ($this->ns) { + $test = eregi("mozilla\/([0-9\.]+)", $HTTP_USER_AGENT, $regs); + $this->ver = $test ? (float)$regs[1] : 0; + } + if ($this->mz) { + $test = ereg("rv:([0-9\.]+)", $HTTP_USER_AGENT, $regs); + $this->ver = $test ? (float)$regs[1] : 0; + } + if($this->ie) { + $test = eregi("msie ([0-9\.]+)", $HTTP_USER_AGENT, $regs); + $this->ver = $test ? (float)$regs[1] : 0; + } + if ($this->opera) { + $test = eregi("opera ([0-9\.]+)", $HTTP_USER_AGENT, $regs); + $this->ver = $test ? (float)$regs[1] : 0; + } + + if (eregi(" ([a-z]{2})-([a-z]{2})", $HTTP_USER_AGENT, $regs)) + $this->lang = $regs[1]; + else + $this->lang = 'en'; + + $this->dom = ($this->mz || $this->safari || ($this->ie && $this->ver>=5) || ($this->opera && $this->ver>=7)); + $this->pngalpha = $this->mz || $this->safari || ($this->ie && $this->ver>=5.5) || + ($this->ie && $this->ver>=5 && $this->mac) || ($this->opera && $this->ver>=7) ? true : false; + } + } + diff --git a/program/include/rcube_contacts.inc b/program/include/rcube_contacts.php index 6a4865662..a9d16149e 100644 --- a/program/include/rcube_contacts.inc +++ b/program/include/rcube_contacts.php @@ -2,10 +2,10 @@ /* +-----------------------------------------------------------------------+ - | program/include/rcube_contacts.inc | + | program/include/rcube_contacts.php | | | | This file is part of the RoundCube Webmail client | - | Copyright (C) 2006-2007, RoundCube Dev. - Switzerland | + | Copyright (C) 2006-2008, RoundCube Dev. - Switzerland | | Licensed under the GNU GPL | | | | PURPOSE: | @@ -403,56 +403,3 @@ class rcube_contacts } -/** - * RoundCube result set class. - * Representing an address directory result set. - */ -class rcube_result_set -{ - var $count = 0; - var $first = 0; - var $current = 0; - var $records = array(); - - function __construct($c=0, $f=0) - { - $this->count = (int)$c; - $this->first = (int)$f; - } - - function rcube_result_set($c=0, $f=0) - { - $this->__construct($c, $f); - } - - function add($rec) - { - $this->records[] = $rec; - } - - function iterate() - { - return $this->records[$this->current++]; - } - - function first() - { - $this->current = 0; - return $this->records[$this->current++]; - } - - // alias - function next() - { - return $this->iterate(); - } - - function seek($i) - { - $this->current = $i; - } - -} - - -?>
\ No newline at end of file diff --git a/program/include/rcube_db.inc b/program/include/rcube_db.php index 63c6759b9..8fa34e6a5 100644 --- a/program/include/rcube_db.inc +++ b/program/include/rcube_db.php @@ -2,10 +2,10 @@ /* +-----------------------------------------------------------------------+ - | program/include/rcube_db.inc | + | program/include/rcube_db.php | | | | This file is part of the RoundCube Webmail client | - | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland | + | Copyright (C) 2005-2008, RoundCube Dev. - Switzerland | | Licensed under the GNU GPL | | | | PURPOSE: | @@ -23,11 +23,6 @@ /** - * Obtain the PEAR::DB class that is used for abstraction - */ -require_once 'DB.php'; - -/** * Database independent query interface * * This is a wrapper for the PEAR::DB class @@ -605,4 +600,4 @@ class rcube_db } // end class rcube_db -?> + diff --git a/program/include/rcube_html.inc b/program/include/rcube_html.inc deleted file mode 100644 index d23760ade..000000000 --- a/program/include/rcube_html.inc +++ /dev/null @@ -1,667 +0,0 @@ -<?php - -/* - +-----------------------------------------------------------------------+ - | rcube_html.inc | - | | - | This file is part of the RoundCube PHP suite | - | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland | - | Licensed under the GNU GPL | - | | - | CONTENTS: | - | Common Classes to create HTML output | - | | - +-----------------------------------------------------------------------+ - | Author: Thomas Bruederli <roundcube@gmail.com> | - +-----------------------------------------------------------------------+ - - $Id: $ - -*/ - - -/** - * HTML page builder class - * - * @package HTML - */ -class rcube_html_page -{ - var $scripts_path = ''; - var $script_files = array(); - var $scripts = array(); - var $charset = 'UTF-8'; - - var $script_tag_file = "<script type=\"text/javascript\" src=\"%s%s\"></script>\n"; - var $script_tag = "<script type=\"text/javascript\">\n<!--\n%s\n\n//-->\n</script>\n"; - var $default_template = "<html>\n<head><title></title></head>\n<body></body>\n</html>"; - - var $title = 'RoundCube Mail'; - var $header = ''; - var $footer = ''; - var $body = ''; - var $body_attrib = array(); - var $meta_tags = array(); - - - /** - * Link an external script file - * - * @param string File URL - * @param string Target position [head|foot] - */ - function include_script($file, $position='head') - { - static $sa_files = array(); - - if (in_array($file, $sa_files)) - return; - - if (!is_array($this->script_files[$position])) - $this->script_files[$position] = array(); - - $this->script_files[$position][] = $file; - } - - /** - * Add inline javascript code - * - * @param string JS code snippet - * @param string Target position [head|head_top|foot] - */ - function add_script($script, $position='head') - { - if (!isset($this->scripts[$position])) - $this->scripts[$position] = "\n".rtrim($script); - else - $this->scripts[$position] .= "\n".rtrim($script); - } - - /** - * Add HTML code to the page header - */ - function add_header($str) - { - $this->header .= "\n".$str; - } - - /** - * Add HTML code to the page footer - * To be added right befor </body> - */ - function add_footer($str) - { - $this->footer .= "\n".$str; - } - - /** - * Setter for page title - */ - function set_title($t) - { - $this->title = $t; - } - - - /** - * Setter for output charset. - * To be specified in a meta tag and sent as http-header - */ - function set_charset($charset) - { - global $MBSTRING; - - $this->charset = $charset; - - if ($MBSTRING && function_exists("mb_internal_encoding")) - { - if(!@mb_internal_encoding($charset)) - $MBSTRING = FALSE; - } - } - - /** - * Getter for output charset - */ - function get_charset() - { - return $this->charset; - } - - - /** - * Reset all saved properties - */ - function reset() - { - $this->script_files = array(); - $this->scripts = array(); - $this->title = ''; - $this->header = ''; - $this->footer = ''; - } - - - /** - * Process template and write to stdOut - * - * @param string HTML template - * @param string Base for absolute paths - */ - function write($templ='', $base_path='') - { - $output = empty($templ) ? $this->default_template : trim($templ); - - // replace specialchars in content - $__page_title = Q($this->title, 'show', FALSE); - $__page_header = $__page_body = $__page_footer = ''; - - - // include meta tag with charset - if (!empty($this->charset)) - { - header('Content-Type: text/html; charset='.$this->charset, true); - $__page_header = '<meta http-equiv="content-type" content="text/html; charset='.$this->charset.'" />'."\n"; - } - - - // definition of the code to be placed in the document header and footer - if (is_array($this->script_files['head'])) - foreach ($this->script_files['head'] as $file) - $__page_header .= sprintf($this->script_tag_file, $this->scripts_path, $file); - - $head_script = $this->scripts['head_top'] . $this->scripts['head']; - if (!empty($head_script)) - $__page_header .= sprintf($this->script_tag, $head_script); - - if (!empty($this->header)) - $__page_header .= $this->header; - - if (is_array($this->script_files['foot'])) - foreach ($this->script_files['foot'] as $file) - $__page_footer .= sprintf($this->script_tag_file, $this->scripts_path, $file); - - if (!empty($this->scripts['foot'])) - $__page_footer .= sprintf($this->script_tag, $this->scripts['foot']); - - if (!empty($this->footer)) - $__page_footer .= $this->footer; - - // find page header - if ($hpos = strpos(strtolower($output), '</head>')) - $__page_header .= "\n"; - else - { - if (!is_numeric($hpos)) - $hpos = strpos(strtolower($output), '<body'); - if (!is_numeric($hpos) && ($hpos = strpos(strtolower($output), '<html'))) - { - while($output[$hpos]!='>') - $hpos++; - $hpos++; - } - - $__page_header = "<head>\n<title>$__page_title</title>\n$__page_header\n</head>\n"; - } - - // add page hader - if ($hpos) - $output = substr($output,0,$hpos) . $__page_header . substr($output,$hpos,strlen($output)); - else - $output = $__page_header . $output; - - - // find page body - if($bpos = strpos(strtolower($output), '<body')) - { - while($output[$bpos]!='>') $bpos++; - $bpos++; - } - else - $bpos = strpos(strtolower($output), '</head>')+7; - - // add page body - if($bpos && $__page_body) - $output = substr($output,0,$bpos) . "\n$__page_body\n" . substr($output,$bpos,strlen($output)); - - - // find and add page footer - $output_lc = strtolower($output); - if(($fpos = strrstr($output_lc, '</body>')) || - ($fpos = strrstr($output_lc, '</html>'))) - $output = substr($output, 0, $fpos) . "$__page_footer\n" . substr($output, $fpos); - else - $output .= "\n$__page_footer"; - - - // reset those global vars - $__page_header = $__page_footer = ''; - - - // correct absolute paths in images and other tags - $output = preg_replace('/(src|href|background)=(["\']?)(\/[a-z0-9_\-]+)/Ui', "\\1=\\2$base_path\\3", $output); - $output = str_replace('$__skin_path', $base_path, $output); - - print rcube_charset_convert($output, 'UTF-8', $this->charset); - } - -} // end class rcube_html_page - - - -/** - * Base class to build a HTML for element - * - * @package HTML - */ -class rcube_form_element - { - var $uppertags = FALSE; - var $upperattribs = FALSE; - var $upperprops = FALSE; - var $newline = FALSE; - - var $attrib = array(); - - - /** - * Create string with saved attributes - * - * @return string HTML formatted tag attributes - */ - function create_attrib_string() - { - if (!sizeof($this->attrib)) - return ''; - - if ($this->name!='') - $this->attrib['name'] = $this->name; - - $attrib_arr = array(); - foreach ($this->attrib as $key => $value) - { - // don't output some internally used attributes - if (in_array($key, array('form', 'quicksearch'))) - continue; - - // skip if size if not numeric - if (($key=='size' && !is_numeric($value))) - continue; - - // skip empty eventhandlers - if ((strpos($key,'on')===0 && $value=='')) - continue; - - // attributes with no value - if (in_array($key, array('checked', 'multiple', 'disabled', 'selected', 'nowrap'))) - { - if ($value) - $attrib_arr[] = sprintf('%s="%s"', $this->_conv_case($key, 'attrib'), $key); - } - // don't convert size of value attribute - else if ($key=='value') - $attrib_arr[] = sprintf('%s="%s"', $this->_conv_case($key, 'attrib'), Q($value, 'strict', false)); - - // regular tag attributes - else - $attrib_arr[] = sprintf('%s="%s"', $this->_conv_case($key, 'attrib'), $this->_conv_case(Q($value), 'value')); - } - - return sizeof($attrib_arr) ? ' '.implode(' ', $attrib_arr) : ''; - } - - - /** - * Convert tags and attributes to upper-/lowercase - * - * @param string Input string - * @param string Value type (can either be "tag" or "attrib") - * @return string Converted output string - * @access private - */ - function _conv_case($str, $type='attrib') - { - if ($type == 'tag') - return $this->uppertags ? strtoupper($str) : strtolower($str); - else if ($type == 'attrib') - return $this->upperattribs ? strtoupper($str) : strtolower($str); - else if ($type == 'value') - return $this->upperprops ? strtoupper($str) : strtolower($str); - } - } - - -/** - * Builder for an <input> field - * - * @package HTML - */ -class input_field extends rcube_form_element -{ - var $type = 'text'; - - /** - * Constructor - * @param array Named tag attributes - */ - function input_field($attrib=array()) - { - if (is_array($attrib)) - $this->attrib = $attrib; - - if ($attrib['type']) - $this->type = $attrib['type']; - - if ($attrib['newline']) - $this->newline = TRUE; - } - - /** - * Compose input tag - * - * @param string Field value - * @param array Additional tag attributes - * @return string Final HTML code - */ - 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; - - $this->attrib['type'] = $this->type; - - // return final tag - return sprintf( - '<%s%s />%s', - $this->_conv_case('input', 'tag'), - $this->create_attrib_string(), - ($this->newline ? "\n" : "")); - } -} - - -/** - * Builder for a <input type="text"> field - * - * @package HTML - */ -class textfield extends input_field -{ - var $type = 'text'; -} - -/** - * Builder for a <input type="password"> field - * - * @package HTML - */ -class passwordfield extends input_field -{ - var $type = 'password'; -} - -/** - * Builder for <input type="radio"> fields - * - * @package HTML - */ -class radiobutton extends input_field -{ - var $type = 'radio'; -} - -/** - * Builder for <input type="checkbox"> fields - * - * @package HTML - */ -class checkbox extends input_field -{ - var $type = 'checkbox'; - - - /** - * Compose input tag - * - * @param string Field value - * @param array Additional tag attributes - * @return string Final HTML code - */ - function show($value='', $attrib=NULL) - { - // overwrite object attributes - if (is_array($attrib)) - $this->attrib = array_merge($this->attrib, $attrib); - - $this->attrib['type'] = $this->type; - - if ($value && (string)$value==(string)$this->attrib['value']) - $this->attrib['checked'] = TRUE; - else - $this->attrib['checked'] = FALSE; - - // return final tag - return sprintf( - '<%s%s />%s', - $this->_conv_case('input', 'tag'), - $this->create_attrib_string(), - ($this->newline ? "\n" : "")); - } -} - - -/** - * Builder for a <textarea> field - * - * @package HTML - */ -class textarea extends rcube_form_element - { - - /** - * Constructor - * @param array Named tag attributes - */ - function textarea($attrib=array()) - { - $this->attrib = $attrib; - - if ($attrib['newline']) - $this->newline = TRUE; - } - - /** - * Create HTML representation for this field - * - * @param string Field value - * @param array Additional tag attributes - * @return string Final HTML code - */ - 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 ($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) && !isset($this->attrib['mce_editable'])) - $value = Q($value, 'strict', FALSE); - - // return final tag - return sprintf( - '<%s%s>%s</%s>%s', - $this->_conv_case('textarea', 'tag'), - $this->create_attrib_string(), - $value, - $this->_conv_case('textarea', 'tag'), - ($this->newline ? "\n" : "")); - } -} - - -/** - * Builder for group of hidden form fields - * - * @package HTML - */ -class hiddenfield extends rcube_form_element -{ - var $fields_arr = array(); - var $newline = TRUE; - - /** - * Constructor - * - * @param array Named tag attributes - */ - function hiddenfield($attrib=NULL) - { - if (is_array($attrib)) - $this->add($attrib); - } - - /** - * Add a hidden field to this instance - * @param array Named tag attributes - */ - function add($attrib) - { - $this->fields_arr[] = $attrib; - } - - - /** - * Create HTML code for the hidden fields - * - * @return string Final HTML code - */ - function show() - { - $out = ''; - foreach ($this->fields_arr as $attrib) - { - $this->attrib = $attrib; - $this->attrib['type'] = 'hidden'; - - $out .= sprintf( - '<%s%s />%s', - $this->_conv_case('input', 'tag'), - $this->create_attrib_string(), - ($this->newline ? "\n" : "")); - } - - return $out; - } -} - - -/** - * Builder for HTML drop-down menus - * Syntax:<pre> - * // create instance. arguments are used to set attributes of select-tag - * $select = new 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 instanciate can be used - * print $select->show('CH'); - * </pre> - * - * @package HTML - */ -class select extends rcube_form_element -{ - var $options = array(); - - /** - * Constructor - * - * @param array Named tag attributes - */ - function select($attrib=NULL) - { - if (is_array($attrib)) - $this->attrib = $attrib; - - if ($attrib['newline']) - $this->newline = TRUE; - } - - - /** - * Add one ore more menu options - * - * @param mixed Array with names or single option name - * @param mixed Array with values or single option value - */ - function add($names, $values=NULL) - { - if (is_array($names)) - { - foreach ($names as $i => $text) - $this->options[] = array('text' => $text, 'value' => $values[$i]); - } - else - $this->options[] = array('text' => $names, 'value' => $values); - } - - - /** - * Generate HTML code for this drop-down menu - * - * @param string Value of the selected option - * @param array Additional tag attributes - * @return string Final HTML code - */ - function show($select=array(), $attrib=NULL) - { - $options_str = "\n"; - $value_str = $this->_conv_case(' value="%s"', 'attrib'); - - if (!is_array($select)) - $select = array($select); - - foreach ($this->options as $option) - { - $selected = ((isset($option['value']) && - in_array($option['value'], $select, TRUE)) || - (in_array($option['text'], $select, TRUE))) ? - $this->_conv_case(' selected="selected"', 'attrib') : ''; - - $options_str .= sprintf("<%s%s%s>%s</%s>\n", - $this->_conv_case('option', 'tag'), - isset($option['value']) ? sprintf($value_str, Q($option['value'])) : '', - $selected, - Q($option['text'], 'strict', FALSE), - $this->_conv_case('option', 'tag')); - } - - // return final tag - return sprintf('<%s%s>%s</%s>%s', - $this->_conv_case('select', 'tag'), - $this->create_attrib_string(), - $options_str, - $this->_conv_case('select', 'tag'), - ($this->newline ? "\n" : "")); - } -} - - -?> diff --git a/program/include/rcube_html_page.php b/program/include/rcube_html_page.php new file mode 100644 index 000000000..42036f63c --- /dev/null +++ b/program/include/rcube_html_page.php @@ -0,0 +1,256 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | program/include/rcube_html_page.php | + | | + | This file is part of the RoundCube PHP suite | + | Copyright (C) 2005-2008, RoundCube Dev. - Switzerland | + | Licensed under the GNU GPL | + | | + | CONTENTS: | + | Class to build XHTML page output | + | | + +-----------------------------------------------------------------------+ + | Author: Thomas Bruederli <roundcube@gmail.com> | + +-----------------------------------------------------------------------+ + + $Id: $ + +*/ + +/** + * Class for HTML page creation + * + * @package HTML + */ +class rcube_html_page +{ + protected $scripts_path = ''; + protected $script_files = array(); + protected $external_scripts = array(); + protected $scripts = array(); + protected $charset = 'UTF-8'; + + protected $script_tag_file = "<script type=\"text/javascript\" src=\"%s%s\"></script>\n"; + protected $script_tag = "<script type=\"text/javascript\">\n<!--\n%s\n\n//-->\n</script>\n"; + protected $default_template = "<html>\n<head><title></title></head>\n<body></body>\n</html>"; + protected $tag_format_external_script = "<script type=\"text/javascript\" src=\"%s\"></script>\n"; + + protected $title = ''; + protected $header = ''; + protected $footer = ''; + protected $body = ''; + + + /** Constructor */ + public function __construct() {} + + /** + * Link an external script file + * + * @param string File URL + * @param string Target position [head|foot] + */ + public function include_script($file, $position='head') + { + static $sa_files = array(); + + if (in_array($file, $sa_files)) { + return; + } + if (!is_array($this->script_files[$position])) { + $this->script_files[$position] = array(); + } + $this->script_files[$position][] = $file; + } + + /** + * Add inline javascript code + * + * @param string JS code snippet + * @param string Target position [head|head_top|foot] + */ + public function add_script($script, $position='head') + { + if (!isset($this->scripts[$position])) { + $this->scripts[$position] = "\n".rtrim($script); + } else { + $this->scripts[$position] .= "\n".rtrim($script); + } + } + + /** + * Add HTML code to the page header + */ + public function add_header($str) + { + $this->header .= "\n".$str; + } + + /** + * Add HTML code to the page footer + * To be added right befor </body> + */ + public function add_footer($str) + { + $this->footer .= "\n".$str; + } + + /** + * Setter for page title + */ + public function set_title($t) + { + $this->title = $t; + } + + /** + * Setter for output charset. + * To be specified in a meta tag and sent as http-header + */ + public function set_charset($charset) + { + $this->charset = $charset; + } + + /** + * Getter for output charset + */ + public function get_charset() + { + return $this->charset; + } + + /** + * Reset all saved properties + */ + public function reset() + { + $this->script_files = array(); + $this->scripts = array(); + $this->title = ''; + $this->header = ''; + $this->footer = ''; + } + + /** + * Process template and write to stdOut + * + * @param string HTML template + * @param string Base for absolute paths + */ + public function write($templ='', $base_path='') + { + $output = empty($templ) ? $this->default_template : trim($templ); + + // set default page title + if (empty($this->title)) { + $this->title = 'RoundCube Mail'; + } + + // replace specialchars in content + $__page_title = Q($this->title, 'show', FALSE); + $__page_header = $__page_body = $__page_footer = ''; + + // include meta tag with charset + if (!empty($this->charset)) { + if (!headers_sent()) { + header('Content-Type: text/html; charset=' . $this->charset); + } + $__page_header = '<meta http-equiv="content-type"'; + $__page_header.= ' content="text/html; charset='; + $__page_header.= $this->charset . '" />'."\n"; + } + + // definition of the code to be placed in the document header and footer + if (is_array($this->script_files['head'])) { + foreach ($this->script_files['head'] as $file) { + $__page_header .= sprintf($this->script_tag_file, $this->scripts_path, $file); + } + } + + $head_script = $this->scripts['head_top'] . $this->scripts['head']; + if (!empty($head_script)) { + $__page_header .= sprintf($this->script_tag, $head_script); + } + + if (!empty($this->header)) { + $__page_header .= $this->header; + } + + if (is_array($this->script_files['foot'])) { + foreach ($this->script_files['foot'] as $file) { + $__page_footer .= sprintf($this->script_tag_file, $this->scripts_path, $file); + } + } + + if (!empty($this->scripts['foot'])) { + $__page_footer .= sprintf($this->script_tag, $this->scripts['foot']); + } + + if (!empty($this->footer)) { + $__page_footer .= $this->footer; + } + + // find page header + if ($hpos = strpos(strtolower($output), '</head>')) { + $__page_header .= "\n"; + } + else { + if (!is_numeric($hpos)) { + $hpos = strpos(strtolower($output), '<body'); + } + if (!is_numeric($hpos) && ($hpos = strpos(strtolower($output), '<html'))) { + while ($output[$hpos] != '>') { + $hpos++; + } + $hpos++; + } + $__page_header = "<head>\n<title>$__page_title</title>\n$__page_header\n</head>\n"; + } + + // add page hader + if ($hpos) { + $output = substr($output,0,$hpos) . $__page_header . substr($output,$hpos,strlen($output)); + } + else { + $output = $__page_header . $output; + } + + // find page body + if ($bpos = strpos(strtolower($output), '<body')) { + while ($output[$bpos] != '>') { + $bpos++; + } + $bpos++; + } + else { + $bpos = strpos(strtolower($output), '</head>')+7; + } + + // add page body + if ($bpos && $__page_body) { + $output = substr($output,0,$bpos) . "\n$__page_body\n" . substr($output,$bpos,strlen($output)); + } + + // find and add page footer + $output_lc = strtolower($output); + if (($fpos = strrpos($output_lc, '</body>')) || ($fpos = strrpos($output_lc, '</html>'))) { + $output = substr($output, 0, $fpos) . "$__page_footer\n" . substr($output, $fpos); + } + else { + $output .= "\n".$__page_footer; + } + + // reset those global vars + $__page_header = $__page_footer = ''; + + // correct absolute paths in images and other tags + $output = preg_replace('/(src|href|background)=(["\']?)(\/[a-z0-9_\-]+)/Ui', "\\1=\\2$base_path\\3", $output); + $output = str_replace('$__skin_path', $base_path, $output); + + print rcube_charset_convert($output, 'UTF-8', $this->charset); + } +} + diff --git a/program/include/rcube_imap.inc b/program/include/rcube_imap.php index 9a594854c..04bb7bfc3 100644 --- a/program/include/rcube_imap.inc +++ b/program/include/rcube_imap.php @@ -2,10 +2,10 @@ /* +-----------------------------------------------------------------------+ - | program/include/rcube_imap.inc | + | program/include/rcube_imap.php | | | | This file is part of the RoundCube Webmail client | - | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland | + | Copyright (C) 2005-2008, RoundCube Dev. - Switzerland | | Licensed under the GNU GPL | | | | PURPOSE: | @@ -2929,4 +2929,3 @@ function quoted_printable_encode($input, $line_max=76, $space_conv=false) } -?> diff --git a/program/include/rcube_json_output.php b/program/include/rcube_json_output.php new file mode 100644 index 000000000..6bf4f8a2a --- /dev/null +++ b/program/include/rcube_json_output.php @@ -0,0 +1,237 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | program/include/rcube_json_output.php | + | | + | This file is part of the RoundCube Webmail client | + | Copyright (C) 2008, RoundCube Dev. - Switzerland | + | Licensed under the GNU GPL | + | | + | PURPOSE: | + | Class to handle HTML page output using a skin template. | + | Extends rcube_html_page class from rcube_shared.inc | + | | + +-----------------------------------------------------------------------+ + | Author: Thomas Bruederli <roundcube@gmail.com> | + +-----------------------------------------------------------------------+ + + $Id: $ + +*/ + + +/** + * View class to produce JSON responses + * + * @package View + */ +class rcube_json_output +{ + private $config; + private $charset = 'UTF-8'; + private $env = array(); + private $texts = array(); + private $commands = array(); + + public $task = ''; + public $ajax_call = true; + + + /** + * Constructor + */ + public function __construct(&$config, $task) + { + $this->task = $task; + $this->config = $config; + } + + + /** + * Set environment variable + * + * @param string Property name + * @param mixed Property value + */ + public function set_env($name, $value) + { + $this->env[$name] = $value; + } + + /** + * @ignore + */ + public function set_pagetitle($title) + { + // ignore + } + + /** + * @ignore + */ + function set_charset($charset) + { + // ignore: $this->charset = $charset; + } + + + /** + * Get charset for output + * + * @return string Output charset + */ + function get_charset() + { + return $this->charset; + } + + + /** + * Register a template object handler + * + * @param string Object name + * @param string Function name to call + * @return void + */ + public function add_handler($obj, $func) + { + // ignore + } + + /** + * Register a list of template object handlers + * + * @param array Hash array with object=>handler pairs + * @return void + */ + public function add_handlers($arr) + { + // ignore + } + + + /** + * Call a client method + * + * @param string Method to call + * @param ... Additional arguments + */ + public function command() + { + $this->commands[] = func_get_args(); + } + + + /** + * Add a localized label to the client environment + */ + public function add_label() + { + $arg_list = func_get_args(); + foreach ($arg_list as $i => $name) { + $this->texts[$name] = rcube::gettext($name); + } + } + + + /** + * Invoke display_message command + * + * @param string Message to display + * @param string Message type [notice|confirm|error] + * @param array Key-value pairs to be replaced in localized text + * @uses self::command() + */ + public function show_message($message, $type='notice', $vars=null) + { + $this->command( + 'display_message', + rcube::gettext(array('name' => $message, 'vars' => $vars)), + $type + ); + } + + /** + * Delete all stored env variables and commands + */ + public public function reset() + { + $this->env = array(); + $this->texts = array(); + $this->commands = array(); + } + + + /** + * Send an AJAX response to the client. + */ + public function send() + { + $this->remote_response(); + exit; + } + + + /** + * Send an AJAX response with executable JS code + * + * @param string Additional JS code + * @param boolean True if output buffer should be flushed + * @return void + * @deprecated + */ + public function remote_response($add='', $flush=false) + { + static $s_header_sent = false; + + if (!$s_header_sent) { + $s_header_sent = true; + send_nocacheing_headers(); + header('Content-Type: application/x-javascript; charset=' . $this->get_charset()); + print '/** ajax response ['.date('d/M/Y h:i:s O')."] **/\n"; + } + + // unset default env vars + unset($this->env['task'], $this->env['action'], $this->env['comm_path']); + + // send response code + echo $this->get_js_commands() . $add; + + // flush the output buffer + if ($flush) + flush(); + } + + + /** + * Return executable javascript code for all registered commands + * + * @return string $out + */ + private function get_js_commands() + { + $out = 'this.set_env('.json_serialize($this->env).");\n"; + + foreach($this->texts as $name => $text) { + $out .= sprintf("this.add_label('%s', '%s');\n", $name, JQ($text)); + } + + foreach ($this->commands as $i => $args) { + $method = array_shift($args); + foreach ($args as $i => $arg) { + $args[$i] = json_serialize($arg); + } + + $out .= sprintf( + "this.%s(%s);\n", + preg_replace('/^parent\./', '', $method), + implode(',', $args) + ); + } + + return $out; + } +} + + diff --git a/program/include/rcube_ldap.inc b/program/include/rcube_ldap.php index 969101b2a..4d0574e67 100644 --- a/program/include/rcube_ldap.inc +++ b/program/include/rcube_ldap.php @@ -1,10 +1,10 @@ <?php /* +-----------------------------------------------------------------------+ - | program/include/rcube_ldap.inc | + | program/include/rcube_ldap.php | | | | This file is part of the RoundCube Webmail client | - | Copyright (C) 2006-2007, RoundCube Dev. - Switzerland | + | Copyright (C) 2006-2008, RoundCube Dev. - Switzerland | | Licensed under the GNU GPL | | | | PURPOSE: | @@ -456,4 +456,4 @@ class rcube_ldap } -?> + diff --git a/program/include/rcube_mail_mime.php b/program/include/rcube_mail_mime.php new file mode 100644 index 000000000..866786b93 --- /dev/null +++ b/program/include/rcube_mail_mime.php @@ -0,0 +1,206 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | program/include/rcube_mail_mime.php | + | | + | This file is part of the RoundCube Webmail client | + | Copyright (C) 2007-2008, RoundCube Dev. - Switzerland | + | Licensed under the GNU GPL | + | | + | PURPOSE: | + | Extend PEAR:Mail_mime class and override encodeHeaders method | + | | + +-----------------------------------------------------------------------+ + | Author: Thomas Bruederli <roundcube@gmail.com> | + +-----------------------------------------------------------------------+ + + $Id: sendmail.inc 506 2007-03-14 00:39:51Z thomasb $ + +*/ + + +/** + * Replacement PEAR:Mail_mime with some additional or overloaded methods + * + * @package Mail + */ +class rcube_mail_mime extends Mail_mime +{ + /** + * Set build parameters + */ + function setParam($param) + { + if (is_array($param)) { + $this->_build_params = array_merge($this->_build_params, $param); + } + } + + /** + * Adds an image to the list of embedded images. + * + * @param string $file The image file name OR image data itself + * @param string $c_type The content type + * @param string $name The filename of the image. + * Only use if $file is the image data + * @param bool $isfilename Whether $file is a filename or not + * Defaults to true + * @param string $contentid Desired Content-ID of MIME part + * Defaults to generated unique ID + * @return mixed true on success or PEAR_Error object + * @access public + */ + function addHTMLImage($file, $c_type='application/octet-stream', $name = '', $isfilename = true, $contentid = '') + { + $filedata = ($isfilename === true) ? $this->_file2str($file) : $file; + if ($isfilename === true) { + $filename = ($name == '' ? $file : $name); + } + else { + $filename = $name; + } + + if (PEAR::isError($filedata)) { + return $filedata; + } + + if ($contentid == '') { + $contentid = md5(uniqid(time())); + } + + $this->_html_images[] = array( + 'body' => $filedata, + 'name' => $filename, + 'c_type' => $c_type, + 'cid' => $contentid + ); + + return true; + } + + + /** + * returns the HTML body portion of the message + * @return string HTML body of the message + * @access public + */ + function getHTMLBody() + { + return $this->_htmlbody; + } + + + /** + * Creates a new mimePart object, using multipart/mixed as + * the initial content-type and returns it during the + * build process. + * + * @return object The multipart/mixed mimePart object + * @access private + */ + function &_addMixedPart() + { + $params['content_type'] = $this->_headers['Content-Type'] ? $this->_headers['Content-Type'] : 'multipart/mixed'; + $ret = new Mail_mimePart('', $params); + return $ret; + } + + + /** + * Encodes a header as per RFC2047 + * + * @param array $input The header data to encode + * @param array $params Extra build parameters + * @return array Encoded data + * @access private + * @override + */ + function _encodeHeaders($input, $params = array()) + { + $maxlen = 73; + $params += $this->_build_params; + + foreach ($input as $hdr_name => $hdr_value) + { + // if header contains e-mail addresses + if (preg_match('/\s<.+@[a-z0-9\-\.]+\.[a-z]+>/U', $hdr_value)) { + $chunks = $this->_explode_quoted_string(',', $hdr_value); + } + else { + $chunks = array($hdr_value); + } + + $hdr_value = ''; + $line_len = 0; + + foreach ($chunks as $i => $value) { + $value = trim($value); + + //This header contains non ASCII chars and should be encoded. + if (preg_match('#[\x80-\xFF]{1}#', $value)) { + $suffix = ''; + // Don't encode e-mail address + if (preg_match('/(.+)\s(<.+@[a-z0-9\-\.]+>)$/Ui', $value, $matches)) { + $value = $matches[1]; + $suffix = ' '.$matches[2]; + } + + switch ($params['head_encoding']) { + case 'base64': + // Base64 encoding has been selected. + $mode = 'B'; + $encoded = base64_encode($value); + break; + + case 'quoted-printable': + default: + // quoted-printable encoding has been selected + $mode = 'Q'; + $encoded = preg_replace('/([\x2C\x3F\x80-\xFF])/e', "'='.sprintf('%02X', ord('\\1'))", $value); + // replace spaces with _ + $encoded = str_replace(' ', '_', $encoded); + } + + $value = '=?' . $params['head_charset'] . '?' . $mode . '?' . $encoded . '?=' . $suffix; + } + + // add chunk to output string by regarding the header maxlen + $len = strlen($value); + if ($i == 0 || $line_len + $len < $maxlen) { + $hdr_value .= ($i>0?', ':'') . $value; + $line_len += $len + ($i>0?2:0); + } + else { + $hdr_value .= ($i>0?', ':'') . "\n " . $value; + $line_len = $len; + } + } + + $input[$hdr_name] = $hdr_value; + } + + return $input; + } + + + function _explode_quoted_string($delimiter, $string) + { + $result = array(); + $strlen = strlen($string); + for ($q=$p=$i=0; $i < $strlen; $i++) { + if ($string{$i} == "\"" && $string{$i-1} != "\\") { + $q = $q ? false : true; + } + else if (!$q && $string{$i} == $delimiter) { + $result[] = substr($string, $p, $i - $p); + $p = $i + 1; + } + } + + $result[] = substr($string, $p); + return $result; + } + +} + diff --git a/program/include/rcube_mdb2.inc b/program/include/rcube_mdb2.php index 72d906664..f2845d3ac 100644 --- a/program/include/rcube_mdb2.inc +++ b/program/include/rcube_mdb2.php @@ -2,10 +2,10 @@ /* +-----------------------------------------------------------------------+ - | program/include/rcube_mdb2.inc | + | program/include/rcube_mdb2.php | | | | This file is part of the RoundCube Webmail client | - | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland | + | Copyright (C) 2005-2008, RoundCube Dev. - Switzerland | | Licensed under the GNU GPL | | | | PURPOSE: | @@ -22,12 +22,6 @@ /** - * Obtain the PEAR::DB class that is used for abstraction - */ -require_once('MDB2.php'); - - -/** * Database independent query interface * * This is a wrapper for the PEAR::MDB2 class @@ -617,4 +611,3 @@ function mdb2_debug_handler(&$db, $scope, $message, $context = array()) } -?> diff --git a/program/include/rcube_result_set.php b/program/include/rcube_result_set.php new file mode 100644 index 000000000..7e968cd2b --- /dev/null +++ b/program/include/rcube_result_set.php @@ -0,0 +1,74 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | program/include/rcube_result_set.php | + | | + | This file is part of the RoundCube Webmail client | + | Copyright (C) 2006-2008, RoundCube Dev. - Switzerland | + | Licensed under the GNU GPL | + | | + | PURPOSE: | + | Class representing an address directory result set | + | | + +-----------------------------------------------------------------------+ + | Author: Thomas Bruederli <roundcube@gmail.com> | + +-----------------------------------------------------------------------+ + + $Id: rcube_result_set.php 328 2006-08-30 17:41:21Z thomasb $ + +*/ + + +/** + * RoundCube result set class. + * Representing an address directory result set. + * + * @package Addressbook + */ +class rcube_result_set +{ + var $count = 0; + var $first = 0; + var $current = 0; + var $records = array(); + + function __construct($c=0, $f=0) + { + $this->count = (int)$c; + $this->first = (int)$f; + } + + function rcube_result_set($c=0, $f=0) + { + $this->__construct($c, $f); + } + + function add($rec) + { + $this->records[] = $rec; + } + + function iterate() + { + return $this->records[$this->current++]; + } + + function first() + { + $this->current = 0; + return $this->records[$this->current++]; + } + + // alias + function next() + { + return $this->iterate(); + } + + function seek($i) + { + $this->current = $i; + } + +}
\ No newline at end of file diff --git a/program/include/rcube_shared.inc b/program/include/rcube_shared.inc index 815331195..c9cf4fbbf 100644 --- a/program/include/rcube_shared.inc +++ b/program/include/rcube_shared.inc @@ -91,7 +91,7 @@ function rcube_browser() */ function rcube_label($attrib) { - global $sess_user_lang, $INSTALL_PATH, $OUTPUT; + global $sess_user_lang, $OUTPUT; static $sa_text_data, $s_language, $utf8_decode; // extract attributes @@ -111,8 +111,8 @@ function rcube_label($attrib) $sa_text_data = array(); // get english labels (these should be complete) - @include($INSTALL_PATH.'program/localization/en_US/labels.inc'); - @include($INSTALL_PATH.'program/localization/en_US/messages.inc'); + @include(INSTALL_PATH.'program/localization/en_US/labels.inc'); + @include(INSTALL_PATH.'program/localization/en_US/messages.inc'); if (is_array($labels)) $sa_text_data = $labels; @@ -120,10 +120,10 @@ function rcube_label($attrib) $sa_text_data = array_merge($sa_text_data, $messages); // include user language files - if ($sess_user_lang!='en' && is_dir($INSTALL_PATH.'program/localization/'.$sess_user_lang)) + if ($sess_user_lang!='en' && is_dir(INSTALL_PATH.'program/localization/'.$sess_user_lang)) { - include_once($INSTALL_PATH.'program/localization/'.$sess_user_lang.'/labels.inc'); - include_once($INSTALL_PATH.'program/localization/'.$sess_user_lang.'/messages.inc'); + include_once(INSTALL_PATH.'program/localization/'.$sess_user_lang.'/labels.inc'); + include_once(INSTALL_PATH.'program/localization/'.$sess_user_lang.'/messages.inc'); if (is_array($labels)) $sa_text_data = array_merge($sa_text_data, $labels); diff --git a/program/include/rcube_template.php b/program/include/rcube_template.php new file mode 100755 index 000000000..2002a62fc --- /dev/null +++ b/program/include/rcube_template.php @@ -0,0 +1,1004 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | program/include/rcube_template.php | + | | + | This file is part of the RoundCube Webmail client | + | Copyright (C) 2006-2008, RoundCube Dev. - Switzerland | + | Licensed under the GNU GPL | + | | + | PURPOSE: | + | Class to handle HTML page output using a skin template. | + | Extends rcube_html_page class from rcube_shared.inc | + | | + +-----------------------------------------------------------------------+ + | Author: Thomas Bruederli <roundcube@gmail.com> | + +-----------------------------------------------------------------------+ + + $Id$ + + */ + + +/** + * Class to create HTML page output using a skin template + * + * @package View + * @todo Documentation + * @uses rcube_html_page + */ +class rcube_template extends rcube_html_page +{ + var $config; + var $task = ''; + var $framed = false; + var $pagetitle = ''; + var $env = array(); + var $js_env = array(); + var $js_commands = array(); + var $object_handlers = array(); + + public $ajax_call = false; + + /** + * Constructor + * + * @todo Use jQuery's $(document).ready() here. + */ + public function __construct(&$config, $task) + { + parent::__construct(); + + $this->task = $task; + $this->config = $config; + + // add common javascripts + $javascript = 'var '.JS_OBJECT_NAME.' = new rcube_webmail();'; + + // don't wait for page onload. Call init at the bottom of the page (delayed) + $javascript_foot = "if (window.call_init)\n call_init('".JS_OBJECT_NAME."');"; + + $this->add_script($javascript, 'head_top'); + $this->add_script($javascript_foot, 'foot'); + $this->scripts_path = 'program/js/'; + $this->include_script('common.js'); + $this->include_script('app.js'); + + // register common UI objects + $this->add_handlers(array( + 'loginform' => array($this, 'login_form'), + 'username' => array($this, 'current_username'), + 'message' => array($this, 'message_container'), + 'charsetselector' => array($this, 'charset_selector'), + )); + } + + /** + * Set environment variable + * + * @param string Property name + * @param mixed Property value + * @param boolean True if this property should be added to client environment + */ + public function set_env($name, $value, $addtojs = true) + { + $this->env[$name] = $value; + if ($addtojs || isset($this->js_env[$name])) { + $this->js_env[$name] = $value; + } + } + + + /** + * Set page title variable + */ + public function set_pagetitle($title) + { + $this->pagetitle = $title; + } + + + /** + * Register a template object handler + * + * @param string Object name + * @param string Function name to call + * @return void + */ + public function add_handler($obj, $func) + { + $this->object_handlers[$obj] = $func; + } + + /** + * Register a list of template object handlers + * + * @param array Hash array with object=>handler pairs + * @return void + */ + public function add_handlers($arr) + { + $this->object_handlers = array_merge($this->object_handlers, $arr); + } + + /** + * Register a GUI object to the client script + * + * @param string Object name + * @param string Object ID + * @return void + */ + public function add_gui_object($obj, $id) + { + $this->add_script(JS_OBJECT_NAME.".gui_object('$obj', '$id');"); + } + + /** + * Call a client method + * + * @param string Method to call + * @param ... Additional arguments + */ + public function command() + { + $this->js_commands[] = func_get_args(); + } + + + /** + * Add a localized label to the client environment + */ + public function add_label() + { + $arg_list = func_get_args(); + foreach ($arg_list as $i => $name) { + $this->command('add_label', $name, rcube_label($name)); + } + } + + + /** + * Invoke display_message command + * + * @param string Message to display + * @param string Message type [notice|confirm|error] + * @param array Key-value pairs to be replaced in localized text + * @uses self::command() + */ + public function show_message($message, $type='notice', $vars=NULL) + { + $this->command( + 'display_message', + rcube_label(array('name' => $message, 'vars' => $vars)), + $type); + } + + + /** + * Delete all stored env variables and commands + * + * @return void + * @uses rcube_html::reset() + * @uses self::$env + * @uses self::$js_env + * @uses self::$js_commands + * @uses self::$object_handlers + */ + public public function reset() + { + $this->env = array(); + $this->js_env = array(); + $this->js_commands = array(); + $this->object_handlers = array(); + parent::reset(); + } + + + /** + * Send the request output to the client. + * This will either parse a skin tempalte or send an AJAX response + * + * @param string Template name + * @param boolean True if script should terminate (default) + */ + public function send($templ = null, $exit = true) + { + if ($templ != 'iframe') { + $this->parse($templ, false); + } + else { + $this->framed = $templ == 'iframe' ? true : $this->framed; + $this->write(); + } + + if ($exit) { + exit; + } + } + + /** + * Process template and write to stdOut + * + * @param string HTML template + * @see rcube_html_page::write() + * @override + */ + public function write($template = '') + { + // unlock interface after iframe load + if ($this->framed) { + array_unshift($this->js_commands, array('set_busy', false)); + } + // write all env variables to client + $js = $this->framed ? "if(window.parent) {\n" : ''; + $js .= $this->get_js_commands() . ($this->framed ? ' }' : ''); + $this->add_script($js, 'head_top'); + + // call super method + parent::write($template, $this->config['skin_path']); + } + + /** + * Parse a specific skin template and deliver to stdout + * + * Either returns nothing, or exists hard (exit();) + * + * @param string Template name + * @param boolean Exit script + * @return void + * @link http://php.net/manual/en/function.exit.php + */ + private function parse($name = 'main', $exit = true) + { + $skin_path = $this->config['skin_path']; + + // read template file + $templ = ''; + $path = "$skin_path/templates/$name.html"; + + if (($fp = fopen($path, 'r')) === false) { + $message = ''; + ob_start(); + fopen($path, 'r'); + $message.= ob_get_contents(); + ob_end_clean(); + rcube_error::raise(array( + 'code' => 501, + 'type' => 'php', + 'line' => __LINE__, + 'file' => __FILE__, + 'message' => 'Error loading template for '.$name.': '.$message + ), true, true); + return false; + } + $templ = fread($fp, filesize($path)); + fclose($fp); + + // parse for specialtags + $output = $this->parse_conditions($templ); + $output = $this->parse_xml($output); + + // add debug console + if ($this->config['debug_level'] & 8) { + $this->add_footer('<div style="position:absolute;top:5px;left:5px;width:400px;padding:0.2em;background:white;opacity:0.8;z-index:9000"> + <a href="#toggle" onclick="con=document.getElementById(\'dbgconsole\');con.style.display=(con.style.display==\'none\'?\'block\':\'none\');return false">console</a> + <form action="/" name="debugform"><textarea name="console" id="dbgconsole" rows="20" cols="40" wrap="off" style="display:none;width:400px;border:none;font-size:x-small"></textarea></form></div>' + ); + } + $output = $this->parse_with_globals($output); + $this->write(trim($output), $skin_path); + if ($exit) { + exit; + } + } + + + /** + * Return executable javascript code for all registered commands + * + * @return string $out + */ + private function get_js_commands() + { + $out = ''; + if (!$this->framed && !empty($this->js_env)) { + $out .= JS_OBJECT_NAME . '.set_env('.json_serialize($this->js_env).");\n"; + } + foreach ($this->js_commands as $i => $args) { + $method = array_shift($args); + foreach ($args as $i => $arg) { + $args[$i] = json_serialize($arg); + } + $parent = $this->framed || preg_match('/^parent\./', $method); + $out .= sprintf( + "%s.%s(%s);\n", + ($parent ? 'parent.' : '') . JS_OBJECT_NAME, + preg_replace('/^parent\./', '', $method), + implode(',', $args) + ); + } + // add command to set page title + if ($this->ajax_call && !empty($this->pagetitle)) { + $out .= sprintf( + "this.set_pagetitle('%s');\n", + JQ((!empty($this->config['product_name']) ? $this->config['product_name'].' :: ' : '') . $this->pagetitle) + ); + } + return $out; + } + + /** + * Make URLs starting with a slash point to skin directory + * + * @param string Input string + * @return string + */ + public function abs_url($str) + { + return preg_replace('/^\//', $this->config['skin_path'].'/', $str); + } + + + /***** Template parsing methods *****/ + + /** + * Replace all strings ($varname) + * with the content of the according global variable. + */ + private function parse_with_globals($input) + { + $GLOBALS['__comm_path'] = Q($GLOBALS['COMM_PATH']); + return preg_replace('/\$(__[a-z0-9_\-]+)/e', '$GLOBALS["\\1"]', $input); + } + + /** + * Public wrapper to dipp into template parsing. + * + * @param string $input + * @return string + * @uses rcube_template::parse_xml() + * @since 0.1-rc1 + */ + public function just_parse($input) + { + return $this->parse_xml($input); + } + + /** + * Parse for conditional tags + * + * @param string $input + * @return string + */ + private function parse_conditions($input) + { + $matches = preg_split('/<roundcube:(if|elseif|else|endif)\s+([^>]+)>/is', $input, 2, PREG_SPLIT_DELIM_CAPTURE); + if ($matches && count($matches) == 4) { + if (preg_match('/^(else|endif)$/i', $matches[1])) { + return $matches[0] . $this->parse_conditions($matches[3]); + } + $attrib = parse_attrib_string($matches[2]); + if (isset($attrib['condition'])) { + $condmet = $this->check_condition($attrib['condition']); + $submatches = preg_split('/<roundcube:(elseif|else|endif)\s+([^>]+)>/is', $matches[3], 2, PREG_SPLIT_DELIM_CAPTURE); + if ($condmet) { + $result = $submatches[0]; + $result.= ($submatches[1] != 'endif' ? preg_replace('/.*<roundcube:endif\s+[^>]+>/Uis', '', $submatches[3], 1) : $submatches[3]); + } + else { + $result = "<roundcube:$submatches[1] $submatches[2]>" . $submatches[3]; + } + return $matches[0] . $this->parse_conditions($result); + } + rcube_error::raise(array( + 'code' => 500, + 'type' => 'php', + 'line' => __LINE__, + 'file' => __FILE__, + 'message' => "Unable to parse conditional tag " . $matches[2] + ), true, false); + } + return $input; + } + + + /** + * Determines if a given condition is met + * + * @todo Get rid off eval() once I understand what this does. + * @todo Extend this to allow real conditions, not just "set" + * @param string Condition statement + * @return boolean True if condition is met, False is not + */ + private function check_condition($condition) + { + $condition = preg_replace( + array( + '/session:([a-z0-9_]+)/i', + '/config:([a-z0-9_]+)/i', + '/env:([a-z0-9_]+)/i', + '/request:([a-z0-9_]+)/ie' + ), + array( + "\$_SESSION['\\1']", + "\$this->config['\\1']", + "\$this->env['\\1']", + "get_input_value('\\1', RCUVE_INPUT_GPC)" + ), + $condition); + + return eval("return (".$condition.");"); + } + + + /** + * Search for special tags in input and replace them + * with the appropriate content + * + * @param string Input string to parse + * @return string Altered input string + * @todo Maybe a cache. + */ + private function parse_xml($input) + { + return preg_replace('/<roundcube:([-_a-z]+)\s+([^>]+)>/Uie', "\$this->xml_command('\\1', '\\2')", $input); + } + + + /** + * Convert a xml command tag into real content + * + * @param string Tag command: object,button,label, etc. + * @param string Attribute string + * @return string Tag/Object content + */ + private function xml_command($command, $str_attrib, $add_attrib = array()) + { + $command = strtolower($command); + $attrib = parse_attrib_string($str_attrib) + $add_attrib; + + // empty output if required condition is not met + if (!empty($attrib['condition']) && !$this->check_condition($attrib['condition'])) { + return ''; + } + + // execute command + switch ($command) { + // return a button + case 'button': + if ($attrib['command']) { + return $this->button($attrib); + } + break; + + // show a label + case 'label': + if ($attrib['name'] || $attrib['command']) { + return Q(rcube_label($attrib + array('vars' => array('product' => $this->config['product_name'])))); + } + break; + + // include a file + case 'include': + $path = realpath($this->config['skin_path'].$attrib['file']); + if ($fsize = filesize($path)) { + if ($this->config['skin_include_php']) { + $incl = $this->include_php($path); + } + else if ($fp = fopen($path, 'r')) { + $incl = fread($fp, $fsize); + fclose($fp); + } + return $this->parse_xml($incl); + } + break; + + case 'plugin.include': + //rcube::tfk_debug(var_export($this->config['skin_path'], true)); + $path = realpath($this->config['skin_path'].$attrib['file']); + if (!$path) { + //rcube::tfk_debug("Does not exist:"); + //rcube::tfk_debug($this->config['skin_path']); + //rcube::tfk_debug($attrib['file']); + //rcube::tfk_debug($path); + } + $incl = file_get_contents($path); + if ($incl) { + return $this->parse_xml($incl); + } + break; + + // return code for a specific application object + case 'object': + $object = strtolower($attrib['name']); + + // we are calling a class/method + if (($handler = $this->object_handlers[$object]) && is_array($handler)) { + if ((is_object($handler[0]) && method_exists($handler[0], $handler[1])) || + (is_string($handler[0]) && class_exists($handler[0]))) + return call_user_func($handler, $attrib); + } + else if (function_exists($handler)) { + // execute object handler function + return call_user_func($handler, $attrib); + } + + if ($object=='productname') { + $name = !empty($this->config['product_name']) ? $this->config['product_name'] : 'RoundCube Webmail'; + return Q($name); + } + if ($object=='version') { + return (string)RCMAIL_VERSION; + } + if ($object=='pagetitle') { + $task = $this->task; + $title = !empty($this->config['product_name']) ? $this->config['product_name'].' :: ' : ''; + + if (!empty($this->pagetitle)) { + $title .= $this->pagetitle; + } + else if ($task == 'login') { + $title = rcube_label(array('name' => 'welcome', 'vars' => array('product' => $this->config['product_name']))); + } + else { + $title .= ucfirst($task); + } + + return Q($title); + } + break; + + // return variable + case 'var': + $var = explode(':', $attrib['name']); + $name = $var[1]; + $value = ''; + + switch ($var[0]) { + case 'env': + $value = $this->env[$name]; + break; + case 'config': + $value = $this->config[$name]; + if (is_array($value) && $value[$_SESSION['imap_host']]) { + $value = $value[$_SESSION['imap_host']]; + } + break; + case 'request': + $value = get_input_value($name, RCUBE_INPUT_GPC); + break; + case 'session': + $value = $_SESSION[$name]; + break; + } + + if (is_array($value)) { + $value = implode(', ', $value); + } + + return Q($value); + break; + } + return ''; + } + + /** + * Include a specific file and return it's contents + * + * @param string File path + * @return string Contents of the processed file + */ + private function include_php($file) + { + ob_start(); + include $file; + $out = ob_get_contents(); + ob_end_clean(); + + return $out; + } + + + /** + * Create and register a button + * + * @param array Named button attributes + * @return string HTML button + * @todo Remove all inline JS calls and use jQuery instead. + * @todo Remove all sprintf()'s - they are pretty, but also slow. + */ + private function button($attrib) + { + global $CONFIG, $OUTPUT, $MAIN_TASKS; + static $sa_buttons = array(); + static $s_button_count = 100; + + // these commands can be called directly via url + $a_static_commands = array('compose', 'list'); + + $browser = new rcube_browser(); + $skin_path = $this->config['skin_path']; + + if (!($attrib['command'] || $attrib['name'])) { + return ''; + } + // try to find out the button type + if ($attrib['type']) { + $attrib['type'] = strtolower($attrib['type']); + } + else { + $attrib['type'] = ($attrib['image'] || $attrib['imagepas'] || $attrib['imageact']) ? 'image' : 'link'; + } + $command = $attrib['command']; + + // take the button from the stack + if ($attrib['name'] && $sa_buttons[$attrib['name']]) { + $attrib = $sa_buttons[$attrib['name']]; + } + else if($attrib['image'] || $attrib['imageact'] || $attrib['imagepas'] || $attrib['class']) { + // add button to button stack + if (!$attrib['name']) { + $attrib['name'] = $command; + } + if (!$attrib['image']) { + $attrib['image'] = $attrib['imagepas'] ? $attrib['imagepas'] : $attrib['imageact']; + } + $sa_buttons[$attrib['name']] = $attrib; + } + else if ($command && $sa_buttons[$command]) { + // get saved button for this command/name + $attrib = $sa_buttons[$command]; + } + + // set border to 0 because of the link arround the button + if ($attrib['type']=='image' && !isset($attrib['border'])) { + $attrib['border'] = 0; + } + if (!$attrib['id']) { + $attrib['id'] = sprintf('rcmbtn%d', $s_button_count++); + } + // get localized text for labels and titles + if ($attrib['title']) { + $attrib['title'] = Q(rcube_label($attrib['title'])); + } + if ($attrib['label']) { + $attrib['label'] = Q(rcube_label($attrib['label'])); + } + if ($attrib['alt']) { + $attrib['alt'] = Q(rcube_label($attrib['alt'])); + } + // set title to alt attribute for IE browsers + if ($browser->ie && $attrib['title'] && !$attrib['alt']) { + $attrib['alt'] = $attrib['title']; + unset($attrib['title']); + } + + // add empty alt attribute for XHTML compatibility + if (!isset($attrib['alt'])) { + $attrib['alt'] = ''; + } + + // register button in the system + if ($attrib['command']) { + $this->add_script(sprintf( + "%s.register_button('%s', '%s', '%s', '%s', '%s', '%s');", + JS_OBJECT_NAME, + $command, + $attrib['id'], + $attrib['type'], + $attrib['imageact'] ? $skin_path.$attrib['imageact'] : $attrib['classact'], + $attrib['imagesel'] ? $skin_path.$attrib['imagesel'] : $attrib['classsel'], + $attrib['imageover'] ? $skin_path.$attrib['imageover'] : '' + )); + + // make valid href to specific buttons + if (in_array($attrib['command'], $MAIN_TASKS)) { + $attrib['href'] = Q(rcmail_url(null, null, $attrib['command'])); + } + else if (in_array($attrib['command'], $a_static_commands)) { + $attrib['href'] = Q(rcmail_url($attrib['command'])); + } + } + + // overwrite attributes + if (!$attrib['href']) { + $attrib['href'] = '#'; + } + if ($command) { + $attrib['onclick'] = sprintf( + "return %s.command('%s','%s',this)", + JS_OBJECT_NAME, + $command, + $attrib['prop'] + ); + } + if ($command && $attrib['imageover']) { + $attrib['onmouseover'] = sprintf( + "return %s.button_over('%s','%s')", + JS_OBJECT_NAME, + $command, + $attrib['id'] + ); + $attrib['onmouseout'] = sprintf( + "return %s.button_out('%s','%s')", + JS_OBJECT_NAME, + $command, + $attrib['id'] + ); + } + + if ($command && $attrib['imagesel']) { + $attrib['onmousedown'] = sprintf( + "return %s.button_sel('%s','%s')", + JS_OBJECT_NAME, + $command, + $attrib['id'] + ); + $attrib['onmouseup'] = sprintf( + "return %s.button_out('%s','%s')", + JS_OBJECT_NAME, + $command, + $attrib['id'] + ); + } + + $out = ''; + + // generate image tag + if ($attrib['type']=='image') { + $attrib_str = html::attrib_string( + $attrib, + array( + 'style', 'class', 'id', 'width', + 'height', 'border', 'hspace', + 'vspace', 'align', 'alt', + ) + ); + $img_tag = sprintf('<img src="%%s"%s />', $attrib_str); + $btn_content = sprintf($img_tag, $skin_path.$attrib['image']); + if ($attrib['label']) { + $btn_content .= ' '.$attrib['label']; + } + $link_attrib = array('href', 'onclick', 'onmouseover', 'onmouseout', 'onmousedown', 'onmouseup', 'title'); + } + else if ($attrib['type']=='link') { + $btn_content = $attrib['label'] ? $attrib['label'] : $attrib['command']; + $link_attrib = array('href', 'onclick', 'title', 'id', 'class', 'style'); + } + else if ($attrib['type']=='input') { + $attrib['type'] = 'button'; + + if ($attrib['label']) { + $attrib['value'] = $attrib['label']; + } + + $attrib_str = html::attrib_string( + $attrib, + array( + 'type', 'value', 'onclick', + 'id', 'class', 'style' + ) + ); + $out = sprintf('<input%s disabled="disabled" />', $attrib_str); + } + + // generate html code for button + if ($btn_content) { + $attrib_str = html::attrib_string($attrib, $link_attrib); + $out = sprintf('<a%s>%s</a>', $attrib_str, $btn_content); + } + + return $out; + } + + + /* ************* common functions delivering gui objects ************** */ + + + /** + * GUI object 'username' + * Showing IMAP username of the current session + * + * @param array Named tag parameters (currently not used) + * @return string HTML code for the gui object + */ + static function current_username($attrib) + { + global $USER; + static $username; + + // alread fetched + if (!empty($username)) { + return $username; + } + + // get e-mail address form default identity + if ($sql_arr = $USER->get_identity()) { + $s_username = $sql_arr['email']; + } + else if (strstr($_SESSION['username'], '@')) { + $username = $_SESSION['username']; + } + else { + $username = $_SESSION['username'].'@'.$_SESSION['imap_host']; + } + + return $username; + } + + + /** + * GUI object 'loginform' + * Returns code for the webmail login form + * + * @param array Named parameters + * @return string HTML code for the gui object + */ + private function login_form($attrib) + { + global $CONFIG, $SESS_HIDDEN_FIELD; + $default_host = $CONFIG['default_host']; + + $_SESSION['temp'] = true; + + $input_user = new html_inputfield(array('name' => '_user', 'id' => 'rcmloginuser', 'size' => 30, 'autocomplete' => 'off')); + $input_pass = new html_passwordfield(array('name' => '_pass', 'id' => 'rcmloginpwd', 'size' => 30)); + $input_action = new html_hiddenfield(array('name' => '_action', 'value' => 'login')); + $input_host = null; + + if (is_array($default_host)) { + $input_host = new html_select(array('name' => '_host', 'id' => 'rcmloginhost')); + + foreach ($default_host as $key => $value) { + if (!is_array($value)) { + $input_host->add($value, (is_numeric($key) ? $value : $key)); + } + else { + $input_host = null; + break; + } + } + } + else if (!strlen($default_host)) { + $input_host = new html_inputfield(array('name' => '_host', 'id' => 'rcmloginhost', 'size' => 30)); + } + + $form_name = !empty($attrib['form']) ? $attrib['form'] : 'form'; + $this->add_gui_object('loginform', $form_name); + + // create HTML table with two cols + $table = new html_table(array('cols' => 2)); + + $table->add('title', html::label('rcmloginuser', Q(rcube_label('username')))); + $table->add(null, $input_user->show(get_input_value('_user', RCUVE_INPUT_POST))); + + $table->add('title', html::label('rcmloginpwd', Q(rcube_label('password')))); + $table->add(null, $input_pass->show()); + + // add host selection row + if (is_object($input_host)) { + $table->add('title', html::label('rcmloginhost', Q(rcube_label('server')))); + $table->add(null, $input_host->show(get_input_value('_host', RCUVE_INPUT_POST))); + } + + $out = $SESS_HIDDEN_FIELD; + $out .= $input_action->show(); + $out .= $table->show(); + + // surround html output with a form tag + if (empty($attrib['form'])) { + $out = html::tag( + 'form', + array( + 'name' => $form_name, + 'action' => "./", + 'method' => "post" + ), + $out); + } + + return $out; + } + + + /** + * GUI object 'searchform' + * Returns code for search function + * + * @param array Named parameters + * @return string HTML code for the gui object + */ + private function search_form($attrib) + { + // add some labels to client + $this->add_label('searching'); + + $attrib['name'] = '_q'; + + if (empty($attrib['id'])) { + $attrib['id'] = 'rcmqsearchbox'; + } + $input_q = new html_inputfield($attrib); + $out = $input_q->show(); + + $this->add_gui_object('qsearchbox', $attrib['id']); + + // add form tag around text field + if (empty($attrib['form'])) { + $out = html::tag( + 'form', + array( + 'name' => "rcmqsearchform", + 'action' => "./", + 'onsubmit' => JS_OBJECT_NAME . ".command('search');return false;", + 'style' => "display:inline", + ), + $out); + } + + return $out; + } + + + /** + * Builder for GUI object 'message' + * + * @param array Named tag parameters + * @return string HTML code for the gui object + */ + private function message_container($attrib) + { + if (isset($attrib['id']) === false) { + $attrib['id'] = 'rcmMessageContainer'; + } + + $this->add_gui_object('message', $attrib['id']); + return html::div($attrib, ""); + } + + + /** + * GUI object 'charsetselector' + * + * @param array Named parameters for the select tag + * @return string HTML code for the gui object + */ + static function charset_selector($attrib) + { + // pass the following attributes to the form class + $field_attrib = array('name' => '_charset'); + foreach ($attrib as $attr => $value) { + if (in_array($attr, array('id', 'class', 'style', 'size', 'tabindex'))) { + $field_attrib[$attr] = $value; + } + } + $charsets = array( + 'US-ASCII' => 'ASCII (English)', + 'EUC-JP' => 'EUC-JP (Japanese)', + 'EUC-KR' => 'EUC-KR (Korean)', + 'BIG5' => 'BIG5 (Chinese)', + 'GB2312' => 'GB2312 (Chinese)', + 'ISO-2022-JP' => 'ISO-2022-JP (Japanese)', + 'ISO-8859-1' => 'ISO-8859-1 (Latin-1)', + 'ISO-8859-2' => 'ISO-8895-2 (Central European)', + 'ISO-8859-7' => 'ISO-8859-7 (Greek)', + 'ISO-8859-9' => 'ISO-8859-9 (Turkish)', + 'Windows-1251' => 'Windows-1251 (Cyrillic)', + 'Windows-1252' => 'Windows-1252 (Western)', + 'Windows-1255' => 'Windows-1255 (Hebrew)', + 'Windows-1256' => 'Windows-1256 (Arabic)', + 'Windows-1257' => 'Windows-1257 (Baltic)', + 'UTF-8' => 'UTF-8' + ); + + $select = new html_select($field_attrib); + $select->add(array_values($charsets), array_keys($charsets)); + + $set = $_POST['_charset'] ? $_POST['_charset'] : $this->get_charset(); + return $select->show($set); + } + +} // end class rcube_template + + diff --git a/program/include/rcube_user.inc b/program/include/rcube_user.php index e748758a9..e748758a9 100644 --- a/program/include/rcube_user.inc +++ b/program/include/rcube_user.php |