From 47124c2279382714afd8dbe4a867a867ea179199 Mon Sep 17 00:00:00 2001 From: thomascube Date: Sat, 12 Apr 2008 13:54:45 +0000 Subject: Changed codebase to PHP5 with autoloader + added some new classes from the devel-vnext branch --- program/include/bugs.inc | 4 +- program/include/html.php | 642 +++++++ program/include/iniset.php | 98 + program/include/main.inc | 89 +- program/include/rcmail_template.inc | 948 ---------- program/include/rcube_browser.php | 75 + program/include/rcube_contacts.inc | 458 ----- program/include/rcube_contacts.php | 405 ++++ program/include/rcube_db.inc | 608 ------ program/include/rcube_db.php | 603 ++++++ program/include/rcube_html.inc | 667 ------- program/include/rcube_html_page.php | 256 +++ program/include/rcube_imap.inc | 2932 ----------------------------- program/include/rcube_imap.php | 2931 ++++++++++++++++++++++++++++ program/include/rcube_json_output.php | 237 +++ program/include/rcube_ldap.inc | 459 ----- program/include/rcube_ldap.php | 459 +++++ program/include/rcube_mail_mime.php | 206 ++ program/include/rcube_mdb2.inc | 620 ------ program/include/rcube_mdb2.php | 613 ++++++ program/include/rcube_result_set.php | 74 + program/include/rcube_shared.inc | 12 +- program/include/rcube_template.php | 1004 ++++++++++ program/include/rcube_user.inc | 482 ----- program/include/rcube_user.php | 482 +++++ program/js/app.js | 35 +- program/lib/html2text.inc | 451 ----- program/lib/html2text.php | 451 +++++ program/lib/rc_mail_mime.inc | 205 -- program/steps/addressbook/edit.inc | 6 +- program/steps/addressbook/func.inc | 7 +- program/steps/error.inc | 2 +- program/steps/mail/addcontact.inc | 2 - program/steps/mail/compose.inc | 38 +- program/steps/mail/func.inc | 3 +- program/steps/mail/get.inc | 2 +- program/steps/mail/sendmail.inc | 13 +- program/steps/mail/sendmdn.inc | 2 - program/steps/mail/show.inc | 23 +- program/steps/settings/edit_identity.inc | 4 +- program/steps/settings/func.inc | 24 +- program/steps/settings/identities.inc | 2 +- program/steps/settings/manage_folders.inc | 12 +- 43 files changed, 8656 insertions(+), 7990 deletions(-) create mode 100644 program/include/html.php create mode 100755 program/include/iniset.php delete mode 100644 program/include/rcmail_template.inc create mode 100644 program/include/rcube_browser.php delete mode 100644 program/include/rcube_contacts.inc create mode 100644 program/include/rcube_contacts.php delete mode 100644 program/include/rcube_db.inc create mode 100644 program/include/rcube_db.php delete mode 100644 program/include/rcube_html.inc create mode 100644 program/include/rcube_html_page.php delete mode 100644 program/include/rcube_imap.inc create mode 100644 program/include/rcube_imap.php create mode 100644 program/include/rcube_json_output.php delete mode 100644 program/include/rcube_ldap.inc create mode 100644 program/include/rcube_ldap.php create mode 100644 program/include/rcube_mail_mime.php delete mode 100644 program/include/rcube_mdb2.inc create mode 100644 program/include/rcube_mdb2.php create mode 100644 program/include/rcube_result_set.php create mode 100755 program/include/rcube_template.php delete mode 100644 program/include/rcube_user.inc create mode 100644 program/include/rcube_user.php delete mode 100644 program/lib/html2text.inc create mode 100644 program/lib/html2text.php delete mode 100644 program/lib/rc_mail_mime.inc (limited to 'program') 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 @@ + | + +-----------------------------------------------------------------------+ + + $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"; + 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
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

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 + * + * @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:

+ * // 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');
+ * 
+ * + * @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 + 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 + $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 @@ + | + | Thomas Bruederli | + +-----------------------------------------------------------------------+ + + $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 @@ -1260,16 +1253,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 * @@ -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 @@ - | - +-----------------------------------------------------------------------+ - - $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('
- console -
'); - - $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('/]+)>/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('/]+)>/is', $matches[3], 2, PREG_SPLIT_DELIM_CAPTURE); - - if ($condmet) - $result = $submatches[0] . ($submatches[1] != 'endif' ? preg_replace('/.*]+>/Uis', '', $submatches[3], 1) : $submatches[3]); - else - $result = "" . $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('/]+)>/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('', $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('', $attrib_str); - } - - // generate html code for button - if ($btn_content) - { - $attrib_str = create_attrib_string($attrib, $link_attrib); - $out = sprintf('%s', $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 tag - $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id')); - $out = '"; - - $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_end = !strlen($attrib['form']) ? '' : ''; - - if ($fields['host']) - $form_host = <<
- - - - -EOF; - - $OUTPUT->add_gui_object('loginform', $form_name); - - $out = << - - - - - - - - -$form_host -
$fields[host]
$fields[user]
$fields[pass]
-$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( - '
%s
', - 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 @@ + | + +-----------------------------------------------------------------------+ + + $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.inc deleted file mode 100644 index 6a4865662..000000000 --- a/program/include/rcube_contacts.inc +++ /dev/null @@ -1,458 +0,0 @@ - | - +-----------------------------------------------------------------------+ - - $Id: rcube_contacts.inc 328 2006-08-30 17:41:21Z thomasb $ - -*/ - - -/** - * Model class for the local address book database - * - * @package Addressbook - */ -class rcube_contacts -{ - var $db = null; - var $db_name = ''; - var $user_id = 0; - var $filter = null; - var $result = null; - var $search_fields; - var $search_string; - var $table_cols = array('name', 'email', 'firstname', 'surname'); - - /** public properties */ - var $primary_key = 'contact_id'; - var $readonly = false; - var $list_page = 1; - var $page_size = 10; - var $ready = false; - - - /** - * Object constructor - * - * @param object Instance of the rcube_db class - * @param integer User-ID - */ - function __construct($dbconn, $user) - { - $this->db = $dbconn; - $this->db_name = get_table_name('contacts'); - $this->user_id = $user; - $this->ready = $this->db && !$this->db->is_error(); - } - - /** - * PHP 4 object constructor - * - * @see rcube_contacts::__construct() - */ - function rcube_contacts($dbconn, $user) - { - $this->__construct($dbconn, $user); - } - - - /** - * Set internal list page - * - * @param number Page number to list - * @access public - */ - function set_page($page) - { - $this->list_page = (int)$page; - } - - - /** - * Set internal page size - * - * @param number Number of messages to display on one page - * @access public - */ - function set_pagesize($size) - { - $this->page_size = (int)$size; - } - - - /** - * Save a search string for future listings - * - * @param string SQL params to use in listing method - */ - function set_search_set($filter) - { - $this->filter = $filter; - } - - - /** - * Getter for saved search properties - * - * @return mixed Search properties used by this class - */ - function get_search_set() - { - return $this->filter; - } - - - /** - * Reset all saved results and search parameters - */ - function reset() - { - $this->result = null; - $this->filter = null; - $this->search_fields = null; - $this->search_string = null; - } - - - /** - * Close connection to source - * Called on script shutdown - */ - function close(){} - - - /** - * List the current set of contact records - * - * @param array List of cols to show - * @param int Only return this number of records, use negative values for tail - * @return array Indexed list of contact records, each a hash array - */ - function list_records($cols=null, $subset=0) - { - // count contacts for this user - $this->result = $this->count(); - $sql_result = NULL; - - // get contacts from DB - if ($this->result->count) - { - $start_row = $subset < 0 ? $this->result->first + $this->page_size + $subset : $this->result->first; - $length = $subset != 0 ? abs($subset) : $this->page_size; - - $sql_result = $this->db->limitquery( - "SELECT * FROM ".$this->db_name." - WHERE del<>1 - AND user_id=?" . - ($this->filter ? " AND (".$this->filter.")" : "") . - " ORDER BY name", - $start_row, - $length, - $this->user_id); - } - - while ($sql_result && ($sql_arr = $this->db->fetch_assoc($sql_result))) - { - $sql_arr['ID'] = $sql_arr[$this->primary_key]; - // make sure we have a name to display - if (empty($sql_arr['name'])) - $sql_arr['name'] = $sql_arr['email']; - $this->result->add($sql_arr); - } - - return $this->result; - } - - - /** - * Search contacts - * - * @param array List of fields to search in - * @param string Search value - * @param boolean True if results are requested, False if count only - * @return Indexed list of contact records and 'count' value - */ - function search($fields, $value, $strict=false, $select=true) - { - if (!is_array($fields)) - $fields = array($fields); - - $add_where = array(); - foreach ($fields as $col) - { - if ($col == 'ID' || $col == $this->primary_key) - { - $ids = !is_array($value) ? split(',', $value) : $value; - $add_where[] = $this->primary_key." IN (".join(',', $ids).")"; - } - else if ($strict) - $add_where[] = $this->db->quoteIdentifier($col)."=".$this->db->quote($value); - else - $add_where[] = $this->db->quoteIdentifier($col)." LIKE ".$this->db->quote(strlen($value)>2 ? "%$value%" : "$value%"); - } - - if (!empty($add_where)) - { - $this->set_search_set(join(' OR ', $add_where)); - if ($select) - $this->list_records(); - else - $this->result = $this->count(); - } - - return $this->result; - } - - - /** - * Count number of available contacts in database - * - * @return Result array with values for 'count' and 'first' - */ - function count() - { - // count contacts for this user - $sql_result = $this->db->query( - "SELECT COUNT(contact_id) AS rows - FROM ".$this->db_name." - WHERE del<>1 - AND user_id=?". - ($this->filter ? " AND (".$this->filter.")" : ""), - $this->user_id); - - $sql_arr = $this->db->fetch_assoc($sql_result); - return new rcube_result_set($sql_arr['rows'], ($this->list_page-1) * $this->page_size);; - } - - - /** - * Return the last result set - * - * @return Result array or NULL if nothing selected yet - */ - function get_result($as_res=true) - { - return $this->result; - } - - - /** - * Get a specific contact record - * - * @param mixed record identifier(s) - * @return Result object with all record fields or False if not found - */ - function get_record($id, $assoc=false) - { - // return cached result - if ($this->result && ($first = $this->result->first()) && $first[$this->primary_key] == $id) - return $assoc ? $first : $this->result; - - $this->db->query( - "SELECT * FROM ".$this->db_name." - WHERE contact_id=? - AND user_id=? - AND del<>1", - $id, - $this->user_id); - - if ($sql_arr = $this->db->fetch_assoc()) - { - $sql_arr['ID'] = $sql_arr[$this->primary_key]; - $this->result = new rcube_result_set(1); - $this->result->add($sql_arr); - } - - return $assoc && $sql_arr ? $sql_arr : $this->result; - } - - - /** - * Create a new contact record - * - * @param array Assoziative array with save data - * @return The created record ID on success, False on error - */ - function insert($save_data, $check=false) - { - if (is_object($save_data) && is_a($save_data, rcube_result_set)) - return $this->insert_recset($save_data, $check); - - $insert_id = $existing = false; - - if ($check) - $existing = $this->search('email', $save_data['email'], true, false); - - $a_insert_cols = $a_insert_values = array(); - foreach ($this->table_cols as $col) - if (isset($save_data[$col])) - { - $a_insert_cols[] = $this->db->quoteIdentifier($col); - $a_insert_values[] = $this->db->quote($save_data[$col]); - } - - if (!$existing->count && !empty($a_insert_cols)) - { - $this->db->query( - "INSERT INTO ".$this->db_name." - (user_id, changed, del, ".join(', ', $a_insert_cols).") - VALUES (?, ".$this->db->now().", 0, ".join(', ', $a_insert_values).")", - $this->user_id); - - $insert_id = $this->db->insert_id(get_sequence_name('contacts')); - } - - return $insert_id; - } - - - /** - * Insert new contacts for each row in set - */ - function insert_recset($result, $check=false) - { - $ids = array(); - while ($row = $result->next()) - { - if ($insert = $this->insert($row, $check)) - $ids[] = $insert; - } - return $ids; - } - - - /** - * Update a specific contact record - * - * @param mixed Record identifier - * @param array Assoziative array with save data - * @return True on success, False on error - */ - function update($id, $save_cols) - { - $updated = false; - $write_sql = array(); - foreach ($this->table_cols as $col) - if (isset($save_cols[$col])) - $write_sql[] = sprintf("%s=%s", $this->db->quoteIdentifier($col), $this->db->quote($save_cols[$col])); - - if (!empty($write_sql)) - { - $this->db->query( - "UPDATE ".$this->db_name." - SET changed=".$this->db->now().", ".join(', ', $write_sql)." - WHERE contact_id=? - AND user_id=? - AND del<>1", - $id, - $this->user_id); - - $updated = $this->db->affected_rows(); - } - - return $updated; - } - - - /** - * Mark one or more contact records as deleted - * - * @param array Record identifiers - */ - function delete($ids) - { - if (is_array($ids)) - $ids = join(',', $ids); - - $this->db->query( - "UPDATE ".$this->db_name." - SET del=1 - WHERE user_id=? - AND contact_id IN (".$ids.")", - $this->user_id); - - return $this->db->affected_rows(); - } - - - /** - * Remove all records from the database - */ - function delete_all() - { - if (is_array($ids)) - $ids = join(',', $ids); - - $this->db->query("DELETE FROM {$this->db_name} WHERE user_id=?", $this->user_id); - return $this->db->affected_rows(); - } - -} - - -/** - * 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_contacts.php b/program/include/rcube_contacts.php new file mode 100644 index 000000000..a9d16149e --- /dev/null +++ b/program/include/rcube_contacts.php @@ -0,0 +1,405 @@ + | + +-----------------------------------------------------------------------+ + + $Id: rcube_contacts.inc 328 2006-08-30 17:41:21Z thomasb $ + +*/ + + +/** + * Model class for the local address book database + * + * @package Addressbook + */ +class rcube_contacts +{ + var $db = null; + var $db_name = ''; + var $user_id = 0; + var $filter = null; + var $result = null; + var $search_fields; + var $search_string; + var $table_cols = array('name', 'email', 'firstname', 'surname'); + + /** public properties */ + var $primary_key = 'contact_id'; + var $readonly = false; + var $list_page = 1; + var $page_size = 10; + var $ready = false; + + + /** + * Object constructor + * + * @param object Instance of the rcube_db class + * @param integer User-ID + */ + function __construct($dbconn, $user) + { + $this->db = $dbconn; + $this->db_name = get_table_name('contacts'); + $this->user_id = $user; + $this->ready = $this->db && !$this->db->is_error(); + } + + /** + * PHP 4 object constructor + * + * @see rcube_contacts::__construct() + */ + function rcube_contacts($dbconn, $user) + { + $this->__construct($dbconn, $user); + } + + + /** + * Set internal list page + * + * @param number Page number to list + * @access public + */ + function set_page($page) + { + $this->list_page = (int)$page; + } + + + /** + * Set internal page size + * + * @param number Number of messages to display on one page + * @access public + */ + function set_pagesize($size) + { + $this->page_size = (int)$size; + } + + + /** + * Save a search string for future listings + * + * @param string SQL params to use in listing method + */ + function set_search_set($filter) + { + $this->filter = $filter; + } + + + /** + * Getter for saved search properties + * + * @return mixed Search properties used by this class + */ + function get_search_set() + { + return $this->filter; + } + + + /** + * Reset all saved results and search parameters + */ + function reset() + { + $this->result = null; + $this->filter = null; + $this->search_fields = null; + $this->search_string = null; + } + + + /** + * Close connection to source + * Called on script shutdown + */ + function close(){} + + + /** + * List the current set of contact records + * + * @param array List of cols to show + * @param int Only return this number of records, use negative values for tail + * @return array Indexed list of contact records, each a hash array + */ + function list_records($cols=null, $subset=0) + { + // count contacts for this user + $this->result = $this->count(); + $sql_result = NULL; + + // get contacts from DB + if ($this->result->count) + { + $start_row = $subset < 0 ? $this->result->first + $this->page_size + $subset : $this->result->first; + $length = $subset != 0 ? abs($subset) : $this->page_size; + + $sql_result = $this->db->limitquery( + "SELECT * FROM ".$this->db_name." + WHERE del<>1 + AND user_id=?" . + ($this->filter ? " AND (".$this->filter.")" : "") . + " ORDER BY name", + $start_row, + $length, + $this->user_id); + } + + while ($sql_result && ($sql_arr = $this->db->fetch_assoc($sql_result))) + { + $sql_arr['ID'] = $sql_arr[$this->primary_key]; + // make sure we have a name to display + if (empty($sql_arr['name'])) + $sql_arr['name'] = $sql_arr['email']; + $this->result->add($sql_arr); + } + + return $this->result; + } + + + /** + * Search contacts + * + * @param array List of fields to search in + * @param string Search value + * @param boolean True if results are requested, False if count only + * @return Indexed list of contact records and 'count' value + */ + function search($fields, $value, $strict=false, $select=true) + { + if (!is_array($fields)) + $fields = array($fields); + + $add_where = array(); + foreach ($fields as $col) + { + if ($col == 'ID' || $col == $this->primary_key) + { + $ids = !is_array($value) ? split(',', $value) : $value; + $add_where[] = $this->primary_key." IN (".join(',', $ids).")"; + } + else if ($strict) + $add_where[] = $this->db->quoteIdentifier($col)."=".$this->db->quote($value); + else + $add_where[] = $this->db->quoteIdentifier($col)." LIKE ".$this->db->quote(strlen($value)>2 ? "%$value%" : "$value%"); + } + + if (!empty($add_where)) + { + $this->set_search_set(join(' OR ', $add_where)); + if ($select) + $this->list_records(); + else + $this->result = $this->count(); + } + + return $this->result; + } + + + /** + * Count number of available contacts in database + * + * @return Result array with values for 'count' and 'first' + */ + function count() + { + // count contacts for this user + $sql_result = $this->db->query( + "SELECT COUNT(contact_id) AS rows + FROM ".$this->db_name." + WHERE del<>1 + AND user_id=?". + ($this->filter ? " AND (".$this->filter.")" : ""), + $this->user_id); + + $sql_arr = $this->db->fetch_assoc($sql_result); + return new rcube_result_set($sql_arr['rows'], ($this->list_page-1) * $this->page_size);; + } + + + /** + * Return the last result set + * + * @return Result array or NULL if nothing selected yet + */ + function get_result($as_res=true) + { + return $this->result; + } + + + /** + * Get a specific contact record + * + * @param mixed record identifier(s) + * @return Result object with all record fields or False if not found + */ + function get_record($id, $assoc=false) + { + // return cached result + if ($this->result && ($first = $this->result->first()) && $first[$this->primary_key] == $id) + return $assoc ? $first : $this->result; + + $this->db->query( + "SELECT * FROM ".$this->db_name." + WHERE contact_id=? + AND user_id=? + AND del<>1", + $id, + $this->user_id); + + if ($sql_arr = $this->db->fetch_assoc()) + { + $sql_arr['ID'] = $sql_arr[$this->primary_key]; + $this->result = new rcube_result_set(1); + $this->result->add($sql_arr); + } + + return $assoc && $sql_arr ? $sql_arr : $this->result; + } + + + /** + * Create a new contact record + * + * @param array Assoziative array with save data + * @return The created record ID on success, False on error + */ + function insert($save_data, $check=false) + { + if (is_object($save_data) && is_a($save_data, rcube_result_set)) + return $this->insert_recset($save_data, $check); + + $insert_id = $existing = false; + + if ($check) + $existing = $this->search('email', $save_data['email'], true, false); + + $a_insert_cols = $a_insert_values = array(); + foreach ($this->table_cols as $col) + if (isset($save_data[$col])) + { + $a_insert_cols[] = $this->db->quoteIdentifier($col); + $a_insert_values[] = $this->db->quote($save_data[$col]); + } + + if (!$existing->count && !empty($a_insert_cols)) + { + $this->db->query( + "INSERT INTO ".$this->db_name." + (user_id, changed, del, ".join(', ', $a_insert_cols).") + VALUES (?, ".$this->db->now().", 0, ".join(', ', $a_insert_values).")", + $this->user_id); + + $insert_id = $this->db->insert_id(get_sequence_name('contacts')); + } + + return $insert_id; + } + + + /** + * Insert new contacts for each row in set + */ + function insert_recset($result, $check=false) + { + $ids = array(); + while ($row = $result->next()) + { + if ($insert = $this->insert($row, $check)) + $ids[] = $insert; + } + return $ids; + } + + + /** + * Update a specific contact record + * + * @param mixed Record identifier + * @param array Assoziative array with save data + * @return True on success, False on error + */ + function update($id, $save_cols) + { + $updated = false; + $write_sql = array(); + foreach ($this->table_cols as $col) + if (isset($save_cols[$col])) + $write_sql[] = sprintf("%s=%s", $this->db->quoteIdentifier($col), $this->db->quote($save_cols[$col])); + + if (!empty($write_sql)) + { + $this->db->query( + "UPDATE ".$this->db_name." + SET changed=".$this->db->now().", ".join(', ', $write_sql)." + WHERE contact_id=? + AND user_id=? + AND del<>1", + $id, + $this->user_id); + + $updated = $this->db->affected_rows(); + } + + return $updated; + } + + + /** + * Mark one or more contact records as deleted + * + * @param array Record identifiers + */ + function delete($ids) + { + if (is_array($ids)) + $ids = join(',', $ids); + + $this->db->query( + "UPDATE ".$this->db_name." + SET del=1 + WHERE user_id=? + AND contact_id IN (".$ids.")", + $this->user_id); + + return $this->db->affected_rows(); + } + + + /** + * Remove all records from the database + */ + function delete_all() + { + if (is_array($ids)) + $ids = join(',', $ids); + + $this->db->query("DELETE FROM {$this->db_name} WHERE user_id=?", $this->user_id); + return $this->db->affected_rows(); + } + +} + + diff --git a/program/include/rcube_db.inc b/program/include/rcube_db.inc deleted file mode 100644 index 63c6759b9..000000000 --- a/program/include/rcube_db.inc +++ /dev/null @@ -1,608 +0,0 @@ - | - | Thomas Bruederli | - +-----------------------------------------------------------------------+ - - $Id$ - -*/ - - -/** - * 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 - * - * @package Database - * @author David Saez Padros - * @author Thomas Bruederli - * @version 1.17 - * @link http://pear.php.net/package/DB - */ -class rcube_db - { - var $db_dsnw; // DSN for write operations - var $db_dsnr; // DSN for read operations - var $db_connected = false; // Already connected ? - var $db_mode = ''; // Connection mode - var $db_handle = 0; // Connection handle - var $db_pconn = false; // Use persistent connections - var $db_error = false; - var $db_error_msg = ''; - - var $a_query_results = array('dummy'); - var $last_res_id = 0; - - - /** - * Object constructor - * - * @param string DSN for read/write operations - * @param string Optional DSN for read only operations - */ - function __construct($db_dsnw, $db_dsnr='', $pconn=false) - { - if ($db_dsnr=='') - $db_dsnr=$db_dsnw; - - $this->db_dsnw = $db_dsnw; - $this->db_dsnr = $db_dsnr; - $this->db_pconn = $pconn; - - $dsn_array = DB::parseDSN($db_dsnw); - $this->db_provider = $dsn_array['phptype']; - } - - - /** - * PHP 4 object constructor - * - * @see rcube_db::__construct - */ - function rcube_db($db_dsnw, $db_dsnr='', $pconn=false) - { - $this->__construct($db_dsnw, $db_dsnr, $pconn); - } - - - /** - * Connect to specific database - * - * @param string DSN for DB connections - * @return object PEAR database handle - * @access private - */ - function dsn_connect($dsn) - { - // Use persistent connections if available - $dbh = DB::connect($dsn, array('persistent' => $this->db_pconn)); - - if (DB::isError($dbh)) - { - $this->db_error = TRUE; - $this->db_error_msg = $dbh->getMessage(); - - raise_error(array('code' => 603, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, - 'message' => $this->db_error_msg), TRUE, FALSE); - - return FALSE; - } - - else if ($this->db_provider=='sqlite') - { - $dsn_array = DB::parseDSN($dsn); - if (!filesize($dsn_array['database']) && !empty($this->sqlite_initials)) - $this->_sqlite_create_database($dbh, $this->sqlite_initials); - } - - return $dbh; - } - - - /** - * Connect to appropiate databse - * depending on the operation - * - * @param string Connection mode (r|w) - * @access public - */ - function db_connect($mode) - { - $this->db_mode = $mode; - - // Already connected - if ($this->db_connected) - { - // no replication, current connection is ok - if ($this->db_dsnw==$this->db_dsnr) - return; - - // connected to master, current connection is ok - if ($this->db_mode=='w') - return; - - // Same mode, current connection is ok - if ($this->db_mode==$mode) - return; - } - - if ($mode=='r') - $dsn = $this->db_dsnr; - else - $dsn = $this->db_dsnw; - - $this->db_handle = $this->dsn_connect($dsn); - $this->db_connected = $this->db_handle ? TRUE : FALSE; - } - - - /** - * Activate/deactivate debug mode - * (not implemented) - */ - function set_debug($dbg = true) - { - - } - - - /** - * Getter for error state - * - * @param boolean True on error - */ - function is_error() - { - return $this->db_error ? $this->db_error_msg : FALSE; - } - - - /** - * Execute a SQL query - * - * @param string SQL query to execute - * @param mixed Values to be inserted in query - * @return number Query handle identifier - * @access public - */ - function query() - { - $params = func_get_args(); - $query = array_shift($params); - - return $this->_query($query, 0, 0, $params); - } - - - /** - * Execute a SQL query with limits - * - * @param string SQL query to execute - * @param number Offset for LIMIT statement - * @param number Number of rows for LIMIT statement - * @param mixed Values to be inserted in query - * @return number Query handle identifier - * @access public - */ - function limitquery() - { - $params = func_get_args(); - $query = array_shift($params); - $offset = array_shift($params); - $numrows = array_shift($params); - - return $this->_query($query, $offset, $numrows, $params); - } - - - /** - * Execute a SQL query with limits - * - * @param string SQL query to execute - * @param number Offset for LIMIT statement - * @param number Number of rows for LIMIT statement - * @param array Values to be inserted in query - * @return number Query handle identifier - * @access private - */ - function _query($query, $offset, $numrows, $params) - { - // Read or write ? - if (strtolower(trim(substr($query,0,6)))=='select') - $mode='r'; - else - $mode='w'; - - $this->db_connect($mode); - - if (!$this->db_connected) - return FALSE; - - if ($this->db_provider == 'sqlite') - $this->_sqlite_prepare(); - - if ($numrows || $offset) - $result = $this->db_handle->limitQuery($query,$offset,$numrows,$params); - else - $result = $this->db_handle->query($query, $params); - - // add result, even if it's an error - return $this->_add_result($result); - } - - - /** - * Get number of rows for a SQL query - * If no query handle is specified, the last query will be taken as reference - * - * @param number Optional query handle identifier - * @return mixed Number of rows or FALSE on failure - * @access public - */ - function num_rows($res_id=NULL) - { - if (!$this->db_handle) - return FALSE; - - if ($result = $this->_get_result($res_id)) - return $result->numRows(); - else - return FALSE; - } - - - /** - * Get number of affected rows fort he last query - * - * @return mixed Number of rows or FALSE on failure - * @access public - */ - function affected_rows() - { - if (!$this->db_handle) - return FALSE; - - return $this->db_handle->affectedRows(); - } - - - /** - * Get last inserted record ID - * For Postgres databases, a sequence name is required - * - * @param string Sequence name for increment - * @return mixed ID or FALSE on failure - * @access public - */ - function insert_id($sequence = '') - { - if (!$this->db_handle || $this->db_mode=='r') - return FALSE; - - switch($this->db_provider) - { - case 'pgsql': - $result = &$this->db_handle->getOne("SELECT CURRVAL('$sequence')"); - if (DB::isError($result)) - raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, - 'message' => $result->getMessage()), TRUE, FALSE); - return $result; - - case 'mssql': - $result = &$this->db_handle->getOne("SELECT @@IDENTITY"); - if (DB::isError($result)) - raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, - 'message' => $result->getMessage()), TRUE, FALSE); - return $result; - - case 'mysql': // This is unfortuneate - return mysql_insert_id($this->db_handle->connection); - - case 'mysqli': - return mysqli_insert_id($this->db_handle->connection); - - case 'sqlite': - return sqlite_last_insert_rowid($this->db_handle->connection); - - default: - die("portability issue with this database, please have the developer fix"); - } - } - - - /** - * Get an associative array for one row - * If no query handle is specified, the last query will be taken as reference - * - * @param number Optional query handle identifier - * @return mixed Array with col values or FALSE on failure - * @access public - */ - function fetch_assoc($res_id=NULL) - { - $result = $this->_get_result($res_id); - return $this->_fetch_row($result, DB_FETCHMODE_ASSOC); - } - - - /** - * Get an index array for one row - * If no query handle is specified, the last query will be taken as reference - * - * @param number Optional query handle identifier - * @return mixed Array with col values or FALSE on failure - * @access public - */ - function fetch_array($res_id=NULL) - { - $result = $this->_get_result($res_id); - return $this->_fetch_row($result, DB_FETCHMODE_ORDERED); - } - - - /** - * Get co values for a result row - * - * @param object Query result handle - * @param number Fetch mode identifier - * @return mixed Array with col values or FALSE on failure - * @access private - */ - function _fetch_row($result, $mode) - { - if (!$result || DB::isError($result)) - { - raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, - 'message' => $this->db_link->getMessage()), TRUE, FALSE); - return FALSE; - } - elseif (!is_object($result)) - return FALSE; - - return $result->fetchRow($mode); - } - - - /** - * Formats input so it can be safely used in a query - * - * @param mixed Value to quote - * @return string Quoted/converted string for use in query - * @access public - */ - function quote($input) - { - // create DB handle if not available - if (!$this->db_handle) - $this->db_connect('r'); - - // escape pear identifier chars - $rep_chars = array('?' => '\?', - '!' => '\!', - '&' => '\&'); - - return $this->db_handle->quoteSmart(strtr($input, $rep_chars)); - } - - - /** - * Quotes a string so it can be safely used as a table or column name - * - * @param string Value to quote - * @return string Quoted string for use in query - * @deprecated Replaced by rcube_db::quote_identifier - * @see rcube_db::quote_identifier - * @access public - */ - function quoteIdentifier($str) - { - return $this->quote_identifier($str); - } - - - /** - * Quotes a string so it can be safely used as a table or column name - * - * @param string Value to quote - * @return string Quoted string for use in query - * @access public - */ - function quote_identifier($str) - { - if (!$this->db_handle) - $this->db_connect('r'); - - return $this->db_handle->quoteIdentifier($str); - } - - - /** - * Escapes a string - * - * @param string The string to be escaped - * @return string The escaped string - * @access public - */ - function escapeSimple($str) - { - if (!$this->db_handle) - $this->db_connect('r'); - - return $this->db_handle->escapeSimple($str); - } - - - /* - * Return SQL function for current time and date - * - * @return string SQL function to use in query - * @access public - */ - function now() - { - switch($this->db_provider) - { - case 'mssql': - return "getdate()"; - - default: - return "now()"; - } - } - - - /** - * Return SQL statement to convert a field value into a unix timestamp - * - * @param string Field name - * @return string SQL statement to use in query - * @access public - */ - function unixtimestamp($field) - { - switch($this->db_provider) - { - case 'pgsql': - return "EXTRACT (EPOCH FROM $field)"; - - case 'mssql': - return "datediff(s, '1970-01-01 00:00:00', $field)"; - - default: - return "UNIX_TIMESTAMP($field)"; - } - } - - - /** - * Return SQL statement to convert from a unix timestamp - * - * @param string Field name - * @return string SQL statement to use in query - * @access public - */ - function fromunixtime($timestamp) - { - switch($this->db_provider) - { - case 'mysqli': - case 'mysql': - case 'sqlite': - return sprintf("FROM_UNIXTIME(%d)", $timestamp); - - default: - return date("'Y-m-d H:i:s'", $timestamp); - } - } - - - /** - * Adds a query result and returns a handle ID - * - * @param object Query handle - * @return mixed Handle ID or FALE on failure - * @access private - */ - function _add_result($res) - { - // sql error occured - if (DB::isError($res)) - { - raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, - 'message' => $res->getMessage() . " Query: " . substr(preg_replace('/[\r\n]+\s*/', ' ', $res->userinfo), 0, 512)), TRUE, FALSE); - return FALSE; - } - else - { - $res_id = sizeof($this->a_query_results); - $this->a_query_results[$res_id] = $res; - $this->last_res_id = $res_id; - return $res_id; - } - } - - - /** - * Resolves a given handle ID and returns the according query handle - * If no ID is specified, the last ressource handle will be returned - * - * @param number Handle ID - * @return mixed Ressource handle or FALE on failure - * @access private - */ - function _get_result($res_id=NULL) - { - if ($res_id==NULL) - $res_id = $this->last_res_id; - - if ($res_id && isset($this->a_query_results[$res_id])) - return $this->a_query_results[$res_id]; - else - return FALSE; - } - - - /** - * Create a sqlite database from a file - * - * @param object SQLite database handle - * @param string File path to use for DB creation - * @access private - */ - function _sqlite_create_database($dbh, $file_name) - { - if (empty($file_name) || !is_string($file_name)) - return; - - $data = ''; - if ($fd = fopen($file_name, 'r')) - { - $data = fread($fd, filesize($file_name)); - fclose($fd); - } - - if (strlen($data)) - sqlite_exec($dbh->connection, $data); - } - - - /** - * Add some proprietary database functions to the current SQLite handle - * in order to make it MySQL compatible - * - * @access private - */ - function _sqlite_prepare() - { - include_once('include/rcube_sqlite.inc'); - - // we emulate via callback some missing MySQL function - sqlite_create_function($this->db_handle->connection, "from_unixtime", "rcube_sqlite_from_unixtime"); - sqlite_create_function($this->db_handle->connection, "unix_timestamp", "rcube_sqlite_unix_timestamp"); - sqlite_create_function($this->db_handle->connection, "now", "rcube_sqlite_now"); - sqlite_create_function($this->db_handle->connection, "md5", "rcube_sqlite_md5"); - } - - - } // end class rcube_db - -?> diff --git a/program/include/rcube_db.php b/program/include/rcube_db.php new file mode 100644 index 000000000..8fa34e6a5 --- /dev/null +++ b/program/include/rcube_db.php @@ -0,0 +1,603 @@ + | + | Thomas Bruederli | + +-----------------------------------------------------------------------+ + + $Id$ + +*/ + + +/** + * Database independent query interface + * + * This is a wrapper for the PEAR::DB class + * + * @package Database + * @author David Saez Padros + * @author Thomas Bruederli + * @version 1.17 + * @link http://pear.php.net/package/DB + */ +class rcube_db + { + var $db_dsnw; // DSN for write operations + var $db_dsnr; // DSN for read operations + var $db_connected = false; // Already connected ? + var $db_mode = ''; // Connection mode + var $db_handle = 0; // Connection handle + var $db_pconn = false; // Use persistent connections + var $db_error = false; + var $db_error_msg = ''; + + var $a_query_results = array('dummy'); + var $last_res_id = 0; + + + /** + * Object constructor + * + * @param string DSN for read/write operations + * @param string Optional DSN for read only operations + */ + function __construct($db_dsnw, $db_dsnr='', $pconn=false) + { + if ($db_dsnr=='') + $db_dsnr=$db_dsnw; + + $this->db_dsnw = $db_dsnw; + $this->db_dsnr = $db_dsnr; + $this->db_pconn = $pconn; + + $dsn_array = DB::parseDSN($db_dsnw); + $this->db_provider = $dsn_array['phptype']; + } + + + /** + * PHP 4 object constructor + * + * @see rcube_db::__construct + */ + function rcube_db($db_dsnw, $db_dsnr='', $pconn=false) + { + $this->__construct($db_dsnw, $db_dsnr, $pconn); + } + + + /** + * Connect to specific database + * + * @param string DSN for DB connections + * @return object PEAR database handle + * @access private + */ + function dsn_connect($dsn) + { + // Use persistent connections if available + $dbh = DB::connect($dsn, array('persistent' => $this->db_pconn)); + + if (DB::isError($dbh)) + { + $this->db_error = TRUE; + $this->db_error_msg = $dbh->getMessage(); + + raise_error(array('code' => 603, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, + 'message' => $this->db_error_msg), TRUE, FALSE); + + return FALSE; + } + + else if ($this->db_provider=='sqlite') + { + $dsn_array = DB::parseDSN($dsn); + if (!filesize($dsn_array['database']) && !empty($this->sqlite_initials)) + $this->_sqlite_create_database($dbh, $this->sqlite_initials); + } + + return $dbh; + } + + + /** + * Connect to appropiate databse + * depending on the operation + * + * @param string Connection mode (r|w) + * @access public + */ + function db_connect($mode) + { + $this->db_mode = $mode; + + // Already connected + if ($this->db_connected) + { + // no replication, current connection is ok + if ($this->db_dsnw==$this->db_dsnr) + return; + + // connected to master, current connection is ok + if ($this->db_mode=='w') + return; + + // Same mode, current connection is ok + if ($this->db_mode==$mode) + return; + } + + if ($mode=='r') + $dsn = $this->db_dsnr; + else + $dsn = $this->db_dsnw; + + $this->db_handle = $this->dsn_connect($dsn); + $this->db_connected = $this->db_handle ? TRUE : FALSE; + } + + + /** + * Activate/deactivate debug mode + * (not implemented) + */ + function set_debug($dbg = true) + { + + } + + + /** + * Getter for error state + * + * @param boolean True on error + */ + function is_error() + { + return $this->db_error ? $this->db_error_msg : FALSE; + } + + + /** + * Execute a SQL query + * + * @param string SQL query to execute + * @param mixed Values to be inserted in query + * @return number Query handle identifier + * @access public + */ + function query() + { + $params = func_get_args(); + $query = array_shift($params); + + return $this->_query($query, 0, 0, $params); + } + + + /** + * Execute a SQL query with limits + * + * @param string SQL query to execute + * @param number Offset for LIMIT statement + * @param number Number of rows for LIMIT statement + * @param mixed Values to be inserted in query + * @return number Query handle identifier + * @access public + */ + function limitquery() + { + $params = func_get_args(); + $query = array_shift($params); + $offset = array_shift($params); + $numrows = array_shift($params); + + return $this->_query($query, $offset, $numrows, $params); + } + + + /** + * Execute a SQL query with limits + * + * @param string SQL query to execute + * @param number Offset for LIMIT statement + * @param number Number of rows for LIMIT statement + * @param array Values to be inserted in query + * @return number Query handle identifier + * @access private + */ + function _query($query, $offset, $numrows, $params) + { + // Read or write ? + if (strtolower(trim(substr($query,0,6)))=='select') + $mode='r'; + else + $mode='w'; + + $this->db_connect($mode); + + if (!$this->db_connected) + return FALSE; + + if ($this->db_provider == 'sqlite') + $this->_sqlite_prepare(); + + if ($numrows || $offset) + $result = $this->db_handle->limitQuery($query,$offset,$numrows,$params); + else + $result = $this->db_handle->query($query, $params); + + // add result, even if it's an error + return $this->_add_result($result); + } + + + /** + * Get number of rows for a SQL query + * If no query handle is specified, the last query will be taken as reference + * + * @param number Optional query handle identifier + * @return mixed Number of rows or FALSE on failure + * @access public + */ + function num_rows($res_id=NULL) + { + if (!$this->db_handle) + return FALSE; + + if ($result = $this->_get_result($res_id)) + return $result->numRows(); + else + return FALSE; + } + + + /** + * Get number of affected rows fort he last query + * + * @return mixed Number of rows or FALSE on failure + * @access public + */ + function affected_rows() + { + if (!$this->db_handle) + return FALSE; + + return $this->db_handle->affectedRows(); + } + + + /** + * Get last inserted record ID + * For Postgres databases, a sequence name is required + * + * @param string Sequence name for increment + * @return mixed ID or FALSE on failure + * @access public + */ + function insert_id($sequence = '') + { + if (!$this->db_handle || $this->db_mode=='r') + return FALSE; + + switch($this->db_provider) + { + case 'pgsql': + $result = &$this->db_handle->getOne("SELECT CURRVAL('$sequence')"); + if (DB::isError($result)) + raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, + 'message' => $result->getMessage()), TRUE, FALSE); + return $result; + + case 'mssql': + $result = &$this->db_handle->getOne("SELECT @@IDENTITY"); + if (DB::isError($result)) + raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, + 'message' => $result->getMessage()), TRUE, FALSE); + return $result; + + case 'mysql': // This is unfortuneate + return mysql_insert_id($this->db_handle->connection); + + case 'mysqli': + return mysqli_insert_id($this->db_handle->connection); + + case 'sqlite': + return sqlite_last_insert_rowid($this->db_handle->connection); + + default: + die("portability issue with this database, please have the developer fix"); + } + } + + + /** + * Get an associative array for one row + * If no query handle is specified, the last query will be taken as reference + * + * @param number Optional query handle identifier + * @return mixed Array with col values or FALSE on failure + * @access public + */ + function fetch_assoc($res_id=NULL) + { + $result = $this->_get_result($res_id); + return $this->_fetch_row($result, DB_FETCHMODE_ASSOC); + } + + + /** + * Get an index array for one row + * If no query handle is specified, the last query will be taken as reference + * + * @param number Optional query handle identifier + * @return mixed Array with col values or FALSE on failure + * @access public + */ + function fetch_array($res_id=NULL) + { + $result = $this->_get_result($res_id); + return $this->_fetch_row($result, DB_FETCHMODE_ORDERED); + } + + + /** + * Get co values for a result row + * + * @param object Query result handle + * @param number Fetch mode identifier + * @return mixed Array with col values or FALSE on failure + * @access private + */ + function _fetch_row($result, $mode) + { + if (!$result || DB::isError($result)) + { + raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, + 'message' => $this->db_link->getMessage()), TRUE, FALSE); + return FALSE; + } + elseif (!is_object($result)) + return FALSE; + + return $result->fetchRow($mode); + } + + + /** + * Formats input so it can be safely used in a query + * + * @param mixed Value to quote + * @return string Quoted/converted string for use in query + * @access public + */ + function quote($input) + { + // create DB handle if not available + if (!$this->db_handle) + $this->db_connect('r'); + + // escape pear identifier chars + $rep_chars = array('?' => '\?', + '!' => '\!', + '&' => '\&'); + + return $this->db_handle->quoteSmart(strtr($input, $rep_chars)); + } + + + /** + * Quotes a string so it can be safely used as a table or column name + * + * @param string Value to quote + * @return string Quoted string for use in query + * @deprecated Replaced by rcube_db::quote_identifier + * @see rcube_db::quote_identifier + * @access public + */ + function quoteIdentifier($str) + { + return $this->quote_identifier($str); + } + + + /** + * Quotes a string so it can be safely used as a table or column name + * + * @param string Value to quote + * @return string Quoted string for use in query + * @access public + */ + function quote_identifier($str) + { + if (!$this->db_handle) + $this->db_connect('r'); + + return $this->db_handle->quoteIdentifier($str); + } + + + /** + * Escapes a string + * + * @param string The string to be escaped + * @return string The escaped string + * @access public + */ + function escapeSimple($str) + { + if (!$this->db_handle) + $this->db_connect('r'); + + return $this->db_handle->escapeSimple($str); + } + + + /* + * Return SQL function for current time and date + * + * @return string SQL function to use in query + * @access public + */ + function now() + { + switch($this->db_provider) + { + case 'mssql': + return "getdate()"; + + default: + return "now()"; + } + } + + + /** + * Return SQL statement to convert a field value into a unix timestamp + * + * @param string Field name + * @return string SQL statement to use in query + * @access public + */ + function unixtimestamp($field) + { + switch($this->db_provider) + { + case 'pgsql': + return "EXTRACT (EPOCH FROM $field)"; + + case 'mssql': + return "datediff(s, '1970-01-01 00:00:00', $field)"; + + default: + return "UNIX_TIMESTAMP($field)"; + } + } + + + /** + * Return SQL statement to convert from a unix timestamp + * + * @param string Field name + * @return string SQL statement to use in query + * @access public + */ + function fromunixtime($timestamp) + { + switch($this->db_provider) + { + case 'mysqli': + case 'mysql': + case 'sqlite': + return sprintf("FROM_UNIXTIME(%d)", $timestamp); + + default: + return date("'Y-m-d H:i:s'", $timestamp); + } + } + + + /** + * Adds a query result and returns a handle ID + * + * @param object Query handle + * @return mixed Handle ID or FALE on failure + * @access private + */ + function _add_result($res) + { + // sql error occured + if (DB::isError($res)) + { + raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, + 'message' => $res->getMessage() . " Query: " . substr(preg_replace('/[\r\n]+\s*/', ' ', $res->userinfo), 0, 512)), TRUE, FALSE); + return FALSE; + } + else + { + $res_id = sizeof($this->a_query_results); + $this->a_query_results[$res_id] = $res; + $this->last_res_id = $res_id; + return $res_id; + } + } + + + /** + * Resolves a given handle ID and returns the according query handle + * If no ID is specified, the last ressource handle will be returned + * + * @param number Handle ID + * @return mixed Ressource handle or FALE on failure + * @access private + */ + function _get_result($res_id=NULL) + { + if ($res_id==NULL) + $res_id = $this->last_res_id; + + if ($res_id && isset($this->a_query_results[$res_id])) + return $this->a_query_results[$res_id]; + else + return FALSE; + } + + + /** + * Create a sqlite database from a file + * + * @param object SQLite database handle + * @param string File path to use for DB creation + * @access private + */ + function _sqlite_create_database($dbh, $file_name) + { + if (empty($file_name) || !is_string($file_name)) + return; + + $data = ''; + if ($fd = fopen($file_name, 'r')) + { + $data = fread($fd, filesize($file_name)); + fclose($fd); + } + + if (strlen($data)) + sqlite_exec($dbh->connection, $data); + } + + + /** + * Add some proprietary database functions to the current SQLite handle + * in order to make it MySQL compatible + * + * @access private + */ + function _sqlite_prepare() + { + include_once('include/rcube_sqlite.inc'); + + // we emulate via callback some missing MySQL function + sqlite_create_function($this->db_handle->connection, "from_unixtime", "rcube_sqlite_from_unixtime"); + sqlite_create_function($this->db_handle->connection, "unix_timestamp", "rcube_sqlite_unix_timestamp"); + sqlite_create_function($this->db_handle->connection, "now", "rcube_sqlite_now"); + sqlite_create_function($this->db_handle->connection, "md5", "rcube_sqlite_md5"); + } + + + } // 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 @@ - | - +-----------------------------------------------------------------------+ - - $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 = "\n"; - var $script_tag = "\n"; - var $default_template = "\n\n\n"; - - 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 - */ - 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 = ''."\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), '')) - $__page_header .= "\n"; - else - { - if (!is_numeric($hpos)) - $hpos = strpos(strtolower($output), '')+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, '')) || - ($fpos = strrstr($output_lc, ''))) - $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 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 field - * - * @package HTML - */ -class textfield extends input_field -{ - var $type = 'text'; -} - -/** - * Builder for a field - * - * @package HTML - */ -class passwordfield extends input_field -{ - var $type = 'password'; -} - -/** - * Builder for fields - * - * @package HTML - */ -class radiobutton extends input_field -{ - var $type = 'radio'; -} - -/** - * Builder for 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
' + ); + } + $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('/]+)>/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('/]+)>/is', $matches[3], 2, PREG_SPLIT_DELIM_CAPTURE); + if ($condmet) { + $result = $submatches[0]; + $result.= ($submatches[1] != 'endif' ? preg_replace('/.*]+>/Uis', '', $submatches[3], 1) : $submatches[3]); + } + else { + $result = "" . $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('/]+)>/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('', $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('', $attrib_str); + } + + // generate html code for button + if ($btn_content) { + $attrib_str = html::attrib_string($attrib, $link_attrib); + $out = sprintf('%s', $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.inc deleted file mode 100644 index e748758a9..000000000 --- a/program/include/rcube_user.inc +++ /dev/null @@ -1,482 +0,0 @@ - | - +-----------------------------------------------------------------------+ - - $Id: rcube_user.inc 933 2007-11-29 14:17:32Z thomasb $ - -*/ - - -/** - * Class representing a system user - * - * @package core - * @author Thomas Bruederli - */ -class rcube_user -{ - var $ID = null; - var $data = null; - - - /** - * Object constructor - * - * @param object DB Database connection - */ - function __construct($id = null, $sql_arr = null) - { - global $DB; - - if ($id && !$sql_arr) - { - $sql_result = $DB->query("SELECT * FROM ".get_table_name('users')." WHERE user_id=?", $id); - $sql_arr = $DB->fetch_assoc($sql_result); - } - - if (!empty($sql_arr)) - { - $this->ID = $sql_arr['user_id']; - $this->data = $sql_arr; - } - } - - /** - * PHP 4 object constructor - * - * @see rcube_user::__construct - */ - function rcube_user($id = null, $sql_arr = null) - { - $this->__construct($id, $sql_arr); - } - - - /** - * Build a user name string (as e-mail address) - * - * @return string Full user name - */ - function get_username() - { - return $this->data['username'] ? $this->data['username'] . (!strpos($this->data['username'], '@') ? '@'.$this->data['mail_host'] : '') : false; - } - - - /** - * Get the preferences saved for this user - * - * @return array Hash array with prefs - */ - function get_prefs() - { - if ($this->ID && $this->data['preferences']) - return unserialize($this->data['preferences']); - else - return array(); - } - - - /** - * Write the given user prefs to the user's record - * - * @param mixed User prefs to save - * @return boolean True on success, False on failure - */ - function save_prefs($a_user_prefs) - { - global $DB, $CONFIG, $sess_user_lang; - - if (!$this->ID) - return false; - - // merge (partial) prefs array with existing settings - $a_user_prefs += (array)$this->get_prefs(); - - $DB->query( - "UPDATE ".get_table_name('users')." - SET preferences=?, - language=? - WHERE user_id=?", - serialize($a_user_prefs), - $sess_user_lang, - $this->ID); - - if ($DB->affected_rows()) - { - $CONFIG = array_merge($CONFIG, $a_user_prefs); - return true; - } - - return false; - } - - - /** - * Get default identity of this user - * - * @param int Identity ID. If empty, the default identity is returned - * @return array Hash array with all cols of the - */ - function get_identity($id = null) - { - global $DB; - - $sql_result = $this->list_identities($id ? sprintf('AND identity_id=%d', $id) : ''); - return $DB->fetch_assoc($sql_result); - } - - - /** - * Return a list of all identities linked with this user - * - * @return array List of identities - */ - function list_identities($sql_add = '') - { - global $DB; - - // get contacts from DB - $sql_result = $DB->query( - "SELECT * FROM ".get_table_name('identities')." - WHERE del<>1 - AND user_id=? - $sql_add - ORDER BY ".$DB->quoteIdentifier('standard')." DESC, name ASC", - $this->ID); - - return $sql_result; - } - - - /** - * Update a specific identity record - * - * @param int Identity ID - * @param array Hash array with col->value pairs to save - * @return boolean True if saved successfully, false if nothing changed - */ - function update_identity($iid, $data) - { - global $DB; - - if (!$this->ID) - return false; - - $write_sql = array(); - - foreach ((array)$data as $col => $value) - { - $write_sql[] = sprintf("%s=%s", - $DB->quoteIdentifier($col), - $DB->quote($value)); - } - - $DB->query( - "UPDATE ".get_table_name('identities')." - SET ".join(', ', $write_sql)." - WHERE identity_id=? - AND user_id=? - AND del<>1", - $iid, - $this->ID); - - return $DB->affected_rows(); - } - - - /** - * Create a new identity record linked with this user - * - * @param array Hash array with col->value pairs to save - * @return int The inserted identity ID or false on error - */ - function insert_identity($data) - { - global $DB; - - if (!$this->ID) - return false; - - $insert_cols = $insert_values = array(); - foreach ((array)$data as $col => $value) - { - $insert_cols[] = $DB->quoteIdentifier($col); - $insert_values[] = $DB->quote($value); - } - - $DB->query( - "INSERT INTO ".get_table_name('identities')." - (user_id, ".join(', ', $insert_cols).") - VALUES (?, ".join(', ', $insert_values).")", - $this->ID); - - return $DB->insert_id(get_sequence_name('identities')); - } - - - /** - * Mark the given identity as deleted - * - * @param int Identity ID - * @return boolean True if deleted successfully, false if nothing changed - */ - function delete_identity($iid) - { - global $DB; - - if (!$this->ID) - return false; - - if (!$this->ID || $this->ID == '') - return false; - - $sql_result = $DB->query("SELECT count(*) AS ident_count FROM " . - get_table_name('identities') . - " WHERE user_id = ? AND del <> 1", - $this->ID); - - $sql_arr = $DB->fetch_assoc($sql_result); - if ($sql_arr['ident_count'] <= 1) - return false; - - $DB->query( - "UPDATE ".get_table_name('identities')." - SET del=1 - WHERE user_id=? - AND identity_id=?", - $this->ID, - $iid); - - return $DB->affected_rows(); - } - - - /** - * Make this identity the default one for this user - * - * @param int The identity ID - */ - function set_default($iid) - { - global $DB; - - if ($this->ID && $iid) - { - $DB->query( - "UPDATE ".get_table_name('identities')." - SET ".$DB->quoteIdentifier('standard')."='0' - WHERE user_id=? - AND identity_id<>? - AND del<>1", - $this->ID, - $iid); - } - } - - - /** - * Update user's last_login timestamp - */ - function touch() - { - global $DB; - - if ($this->ID) - { - $DB->query( - "UPDATE ".get_table_name('users')." - SET last_login=".$DB->now()." - WHERE user_id=?", - $this->ID); - } - } - - - /** - * Clear the saved object state - */ - function reset() - { - $this->ID = null; - $this->data = null; - } - - - /** - * Find a user record matching the given name and host - * - * @param string IMAP user name - * @param string IMAP host name - * @return object rcube_user New user instance - * @static - */ - function query($user, $host) - { - global $DB; - - // query if user already registered - $sql_result = $DB->query( - "SELECT * FROM ".get_table_name('users')." - WHERE mail_host=? AND (username=? OR alias=?)", - $host, - $user, - $user); - - // user already registered -> overwrite username - if ($sql_arr = $DB->fetch_assoc($sql_result)) - return new rcube_user($sql_arr['user_id'], $sql_arr); - else - return false; - } - - - /** - * Create a new user record and return a rcube_user instance - * - * @param string IMAP user name - * @param string IMAP host - * @return object rcube_user New user instance - * @static - */ - function create($user, $host) - { - global $DB, $CONFIG; - - $user_email = ''; - - // try to resolve user in virtusertable - if (!empty($CONFIG['virtuser_file']) && !strpos($user, '@')) - $user_email = rcube_user::user2email($user); - - $DB->query( - "INSERT INTO ".get_table_name('users')." - (created, last_login, username, mail_host, alias, language) - VALUES (".$DB->now().", ".$DB->now().", ?, ?, ?, ?)", - strip_newlines($user), - strip_newlines($host), - strip_newlines($user_email), - $_SESSION['user_lang']); - - if ($user_id = $DB->insert_id(get_sequence_name('users'))) - { - $mail_domain = rcmail_mail_domain($host); - - if ($user_email=='') - $user_email = strpos($user, '@') ? $user : sprintf('%s@%s', $user, $mail_domain); - - $user_name = $user != $user_email ? $user : ''; - - // try to resolve the e-mail address from the virtuser table - if (!empty($CONFIG['virtuser_query']) && - ($sql_result = $DB->query(preg_replace('/%u/', $DB->escapeSimple($user), $CONFIG['virtuser_query']))) && - ($DB->num_rows()>0)) - { - while ($sql_arr = $DB->fetch_array($sql_result)) - { - $DB->query( - "INSERT INTO ".get_table_name('identities')." - (user_id, del, standard, name, email) - VALUES (?, 0, 1, ?, ?)", - $user_id, - strip_newlines($user_name), - preg_replace('/^@/', $user . '@', $sql_arr[0])); - } - } - else - { - // also create new identity records - $DB->query( - "INSERT INTO ".get_table_name('identities')." - (user_id, del, standard, name, email) - VALUES (?, 0, 1, ?, ?)", - $user_id, - strip_newlines($user_name), - strip_newlines($user_email)); - } - } - else - { - raise_error(array( - 'code' => 500, - 'type' => 'php', - 'line' => __LINE__, - 'file' => __FILE__, - 'message' => "Failed to create new user"), true, false); - } - - return $user_id ? new rcube_user($user_id) : false; - } - - - /** - * Resolve username using a virtuser table - * - * @param string E-mail address to resolve - * @return string Resolved IMAP username - * @static - */ - function email2user($email) - { - $user = $email; - $r = rcmail_findinvirtual("^$email"); - - for ($i=0; $i 0) - { - $user = trim($arr[count($arr)-1]); - break; - } - } - - return $user; - } - - - /** - * Resolve e-mail address from virtuser table - * - * @param string User name - * @return string Resolved e-mail address - * @static - */ - function user2email($user) - { - $email = ""; - $r = rcmail_findinvirtual("$user$"); - - for ($i=0; $i 0) - { - $email = trim(str_replace('\\@', '@', $arr[0])); - break; - } - } - - return $email; - } - -} - - -?> diff --git a/program/include/rcube_user.php b/program/include/rcube_user.php new file mode 100644 index 000000000..e748758a9 --- /dev/null +++ b/program/include/rcube_user.php @@ -0,0 +1,482 @@ + | + +-----------------------------------------------------------------------+ + + $Id: rcube_user.inc 933 2007-11-29 14:17:32Z thomasb $ + +*/ + + +/** + * Class representing a system user + * + * @package core + * @author Thomas Bruederli + */ +class rcube_user +{ + var $ID = null; + var $data = null; + + + /** + * Object constructor + * + * @param object DB Database connection + */ + function __construct($id = null, $sql_arr = null) + { + global $DB; + + if ($id && !$sql_arr) + { + $sql_result = $DB->query("SELECT * FROM ".get_table_name('users')." WHERE user_id=?", $id); + $sql_arr = $DB->fetch_assoc($sql_result); + } + + if (!empty($sql_arr)) + { + $this->ID = $sql_arr['user_id']; + $this->data = $sql_arr; + } + } + + /** + * PHP 4 object constructor + * + * @see rcube_user::__construct + */ + function rcube_user($id = null, $sql_arr = null) + { + $this->__construct($id, $sql_arr); + } + + + /** + * Build a user name string (as e-mail address) + * + * @return string Full user name + */ + function get_username() + { + return $this->data['username'] ? $this->data['username'] . (!strpos($this->data['username'], '@') ? '@'.$this->data['mail_host'] : '') : false; + } + + + /** + * Get the preferences saved for this user + * + * @return array Hash array with prefs + */ + function get_prefs() + { + if ($this->ID && $this->data['preferences']) + return unserialize($this->data['preferences']); + else + return array(); + } + + + /** + * Write the given user prefs to the user's record + * + * @param mixed User prefs to save + * @return boolean True on success, False on failure + */ + function save_prefs($a_user_prefs) + { + global $DB, $CONFIG, $sess_user_lang; + + if (!$this->ID) + return false; + + // merge (partial) prefs array with existing settings + $a_user_prefs += (array)$this->get_prefs(); + + $DB->query( + "UPDATE ".get_table_name('users')." + SET preferences=?, + language=? + WHERE user_id=?", + serialize($a_user_prefs), + $sess_user_lang, + $this->ID); + + if ($DB->affected_rows()) + { + $CONFIG = array_merge($CONFIG, $a_user_prefs); + return true; + } + + return false; + } + + + /** + * Get default identity of this user + * + * @param int Identity ID. If empty, the default identity is returned + * @return array Hash array with all cols of the + */ + function get_identity($id = null) + { + global $DB; + + $sql_result = $this->list_identities($id ? sprintf('AND identity_id=%d', $id) : ''); + return $DB->fetch_assoc($sql_result); + } + + + /** + * Return a list of all identities linked with this user + * + * @return array List of identities + */ + function list_identities($sql_add = '') + { + global $DB; + + // get contacts from DB + $sql_result = $DB->query( + "SELECT * FROM ".get_table_name('identities')." + WHERE del<>1 + AND user_id=? + $sql_add + ORDER BY ".$DB->quoteIdentifier('standard')." DESC, name ASC", + $this->ID); + + return $sql_result; + } + + + /** + * Update a specific identity record + * + * @param int Identity ID + * @param array Hash array with col->value pairs to save + * @return boolean True if saved successfully, false if nothing changed + */ + function update_identity($iid, $data) + { + global $DB; + + if (!$this->ID) + return false; + + $write_sql = array(); + + foreach ((array)$data as $col => $value) + { + $write_sql[] = sprintf("%s=%s", + $DB->quoteIdentifier($col), + $DB->quote($value)); + } + + $DB->query( + "UPDATE ".get_table_name('identities')." + SET ".join(', ', $write_sql)." + WHERE identity_id=? + AND user_id=? + AND del<>1", + $iid, + $this->ID); + + return $DB->affected_rows(); + } + + + /** + * Create a new identity record linked with this user + * + * @param array Hash array with col->value pairs to save + * @return int The inserted identity ID or false on error + */ + function insert_identity($data) + { + global $DB; + + if (!$this->ID) + return false; + + $insert_cols = $insert_values = array(); + foreach ((array)$data as $col => $value) + { + $insert_cols[] = $DB->quoteIdentifier($col); + $insert_values[] = $DB->quote($value); + } + + $DB->query( + "INSERT INTO ".get_table_name('identities')." + (user_id, ".join(', ', $insert_cols).") + VALUES (?, ".join(', ', $insert_values).")", + $this->ID); + + return $DB->insert_id(get_sequence_name('identities')); + } + + + /** + * Mark the given identity as deleted + * + * @param int Identity ID + * @return boolean True if deleted successfully, false if nothing changed + */ + function delete_identity($iid) + { + global $DB; + + if (!$this->ID) + return false; + + if (!$this->ID || $this->ID == '') + return false; + + $sql_result = $DB->query("SELECT count(*) AS ident_count FROM " . + get_table_name('identities') . + " WHERE user_id = ? AND del <> 1", + $this->ID); + + $sql_arr = $DB->fetch_assoc($sql_result); + if ($sql_arr['ident_count'] <= 1) + return false; + + $DB->query( + "UPDATE ".get_table_name('identities')." + SET del=1 + WHERE user_id=? + AND identity_id=?", + $this->ID, + $iid); + + return $DB->affected_rows(); + } + + + /** + * Make this identity the default one for this user + * + * @param int The identity ID + */ + function set_default($iid) + { + global $DB; + + if ($this->ID && $iid) + { + $DB->query( + "UPDATE ".get_table_name('identities')." + SET ".$DB->quoteIdentifier('standard')."='0' + WHERE user_id=? + AND identity_id<>? + AND del<>1", + $this->ID, + $iid); + } + } + + + /** + * Update user's last_login timestamp + */ + function touch() + { + global $DB; + + if ($this->ID) + { + $DB->query( + "UPDATE ".get_table_name('users')." + SET last_login=".$DB->now()." + WHERE user_id=?", + $this->ID); + } + } + + + /** + * Clear the saved object state + */ + function reset() + { + $this->ID = null; + $this->data = null; + } + + + /** + * Find a user record matching the given name and host + * + * @param string IMAP user name + * @param string IMAP host name + * @return object rcube_user New user instance + * @static + */ + function query($user, $host) + { + global $DB; + + // query if user already registered + $sql_result = $DB->query( + "SELECT * FROM ".get_table_name('users')." + WHERE mail_host=? AND (username=? OR alias=?)", + $host, + $user, + $user); + + // user already registered -> overwrite username + if ($sql_arr = $DB->fetch_assoc($sql_result)) + return new rcube_user($sql_arr['user_id'], $sql_arr); + else + return false; + } + + + /** + * Create a new user record and return a rcube_user instance + * + * @param string IMAP user name + * @param string IMAP host + * @return object rcube_user New user instance + * @static + */ + function create($user, $host) + { + global $DB, $CONFIG; + + $user_email = ''; + + // try to resolve user in virtusertable + if (!empty($CONFIG['virtuser_file']) && !strpos($user, '@')) + $user_email = rcube_user::user2email($user); + + $DB->query( + "INSERT INTO ".get_table_name('users')." + (created, last_login, username, mail_host, alias, language) + VALUES (".$DB->now().", ".$DB->now().", ?, ?, ?, ?)", + strip_newlines($user), + strip_newlines($host), + strip_newlines($user_email), + $_SESSION['user_lang']); + + if ($user_id = $DB->insert_id(get_sequence_name('users'))) + { + $mail_domain = rcmail_mail_domain($host); + + if ($user_email=='') + $user_email = strpos($user, '@') ? $user : sprintf('%s@%s', $user, $mail_domain); + + $user_name = $user != $user_email ? $user : ''; + + // try to resolve the e-mail address from the virtuser table + if (!empty($CONFIG['virtuser_query']) && + ($sql_result = $DB->query(preg_replace('/%u/', $DB->escapeSimple($user), $CONFIG['virtuser_query']))) && + ($DB->num_rows()>0)) + { + while ($sql_arr = $DB->fetch_array($sql_result)) + { + $DB->query( + "INSERT INTO ".get_table_name('identities')." + (user_id, del, standard, name, email) + VALUES (?, 0, 1, ?, ?)", + $user_id, + strip_newlines($user_name), + preg_replace('/^@/', $user . '@', $sql_arr[0])); + } + } + else + { + // also create new identity records + $DB->query( + "INSERT INTO ".get_table_name('identities')." + (user_id, del, standard, name, email) + VALUES (?, 0, 1, ?, ?)", + $user_id, + strip_newlines($user_name), + strip_newlines($user_email)); + } + } + else + { + raise_error(array( + 'code' => 500, + 'type' => 'php', + 'line' => __LINE__, + 'file' => __FILE__, + 'message' => "Failed to create new user"), true, false); + } + + return $user_id ? new rcube_user($user_id) : false; + } + + + /** + * Resolve username using a virtuser table + * + * @param string E-mail address to resolve + * @return string Resolved IMAP username + * @static + */ + function email2user($email) + { + $user = $email; + $r = rcmail_findinvirtual("^$email"); + + for ($i=0; $i 0) + { + $user = trim($arr[count($arr)-1]); + break; + } + } + + return $user; + } + + + /** + * Resolve e-mail address from virtuser table + * + * @param string User name + * @return string Resolved e-mail address + * @static + */ + function user2email($user) + { + $email = ""; + $r = rcmail_findinvirtual("$user$"); + + for ($i=0; $i 0) + { + $email = trim(str_replace('\\@', '@', $arr[0])); + break; + } + } + + return $email; + } + +} + + +?> diff --git a/program/js/app.js b/program/js/app.js index 02c1cf5c2..a62d8d8ec 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -1581,11 +1581,11 @@ function rcube_webmail() parent.rcmail.set_classname(rows[uid].obj, 'unread', false); if (rows[uid].replied && parent.rcmail.env.repliedicon) - icn_src = parent.rcmail.env.repliedicon; + icn_src = parent.rcmail.env.repliedicon; else if (parent.rcmail.env.messageicon) icn_src = parent.rcmail.env.messageicon; - if (rows[uid].icon && icn_src) + if (rows[uid].icon && icn_src) rows[uid].icon.src = icn_src; } } @@ -3502,28 +3502,27 @@ function rcube_webmail() this.message_list.init(); case 'purge': - case 'expunge': - if (!this.env.messagecount) - { - // clear preview pane content - if (this.env.contentframe) - this.show_contentframe(false); - // disable commands useless when mailbox is empty - this.enable_command('show', 'reply', 'reply-all', 'forward', 'moveto', 'delete', 'mark', 'viewsource', - 'print', 'load-attachment', 'purge', 'expunge', 'select-all', 'select-none', 'sort', false); - } + case 'expunge': + if (!this.env.messagecount) + { + // clear preview pane content + if (this.env.contentframe) + this.show_contentframe(false); + // disable commands useless when mailbox is empty + this.enable_command('show', 'reply', 'reply-all', 'forward', 'moveto', 'delete', 'mark', 'viewsource', + 'print', 'load-attachment', 'purge', 'expunge', 'select-all', 'select-none', 'sort', false); + } - break; + break; case 'list': - this.msglist_select(this.message_list); + this.msglist_select(this.message_list); case 'check-recent': case 'getunread': - this.enable_command('show', 'expunge', 'select-all', 'select-none', 'sort', (this.env.messagecount > 0)); - this.enable_command('purge', (this.env.messagecount && (this.env.mailbox==this.env.trash_mailbox || this.env.mailbox==this.env.junk_mailbox))); - - break; + this.enable_command('show', 'expunge', 'select-all', 'select-none', 'sort', (this.env.messagecount > 0)); + this.enable_command('purge', (this.env.messagecount && (this.env.mailbox==this.env.trash_mailbox || this.env.mailbox==this.env.junk_mailbox))); + break; } diff --git a/program/lib/html2text.inc b/program/lib/html2text.inc deleted file mode 100644 index 7d7d9d1f4..000000000 --- a/program/lib/html2text.inc +++ /dev/null @@ -1,451 +0,0 @@ - * -* All rights reserved. * -* * -* This script is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -* The GNU General Public License can be found at * -* http://www.gnu.org/copyleft/gpl.html. * -* * -* This script is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU General Public License for more details. * -* * -* Author(s): Jon Abernathy * -* * -* Last modified: 04/06/05 * -* Modified: 2004/05/19 (tbr) * -* * -*************************************************************************/ - - -/** -* Takes HTML and converts it to formatted, plain text. -* -* Thanks to Alexander Krug (http://www.krugar.de/) to pointing out and -* correcting an error in the regexp search array. Fixed 7/30/03. -* -* Updated set_html() function's file reading mechanism, 9/25/03. -* -* Thanks to Joss Sanglier (http://www.dancingbear.co.uk/) for adding -* several more HTML entity codes to the $search and $replace arrays. -* Updated 11/7/03. -* -* Thanks to Darius Kasperavicius (http://www.dar.dar.lt/) for -* suggesting the addition of $allowed_tags and its supporting function -* (which I slightly modified). Updated 3/12/04. -* -* Thanks to Justin Dearing for pointing out that a replacement for the -* tag was missing, and suggesting an appropriate fix. -* Updated 8/25/04. -* -* Thanks to Mathieu Collas (http://www.myefarm.com/) for finding a -* display/formatting bug in the _build_link_list() function: email -* readers would show the left bracket and number ("[1") as part of the -* rendered email address. -* Updated 12/16/04. -* -* Thanks to Wojciech Bajon (http://histeria.pl/) for submitting code -* to handle relative links, which I hadn't considered. I modified his -* code a bit to handle normal HTTP links and MAILTO links. Also for -* suggesting three additional HTML entity codes to search for. -* Updated 03/02/05. -* -* Thanks to Jacob Chandler for pointing out another link condition -* for the _build_link_list() function: "https". -* Updated 04/06/05. -* -* @author Jon Abernathy -* @version 0.6.1 -* @since PHP 4.0.2 -*/ -class html2text -{ - - /** - * Contains the HTML content to convert. - * - * @var string $html - * @access public - */ - var $html; - - /** - * Contains the converted, formatted text. - * - * @var string $text - * @access public - */ - var $text; - - /** - * Maximum width of the formatted text, in columns. - * - * @var integer $width - * @access public - */ - var $width = 70; - - /** - * List of preg* regular expression patterns to search for, - * used in conjunction with $replace. - * - * @var array $search - * @access public - * @see $replace - */ - var $search = array( - "/\r/", // Non-legal carriage return - "/[\n\t]+/", // Newlines and tabs - '/]*>.*?<\/script>/i', //