diff --git a/CHANGELOG b/CHANGELOG
index c5e49fcdf..00502abd4 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,14 +1,19 @@
CHANGELOG RoundCube Webmail
---------------------------
-2008/04/11 (alec)
+2008/04/12 (thomasb)
+----------
+- Changed codebase to PHP5 with autoloader
+- Added some new classes from devel-vnext branch
+2008/04/11 (alec)
+----------
- Mark as read in one action with message preview (#1484972)
- Delete redundant quota reads (#1484972)
- Add options for empty trash and expunge inbox on logout (#1483863)
2008/04/10 (alec)
-
+----------
- Add rows highlighting in onmousemove on ksearch list
- Remove lines wrapping when displaying message
- Fix month localization
@@ -16,7 +21,7 @@ CHANGELOG RoundCube Webmail
- Fix debug (ajax) console
2008/04/02 (alec)
-
+----------
- Updated timezones list (#1484908)
- Fix design in Settings (#1484799)
- Fix deleting messages after clicking on "All" (#1484838)
@@ -24,21 +29,21 @@ CHANGELOG RoundCube Webmail
- Fix creating a new folder w/a comma in its name (#1484681)
2008/04/01 (thomasb)
-
+----------
- Fix Enter problem on login (#1484839)
- Make the http-received header in outgoing mails configurable
2008/03/30 (till)
-
+----------
- Fix Firefox problem with ob_gzhandler (#1484932)
- Improve message previewpane - less loading (#1484316)
2008/03/28 (thomasb)
-
+----------
- Disable installer by default; add config option to enable it again
2008/03/24 (till)
-
+----------
- Don't send mark requests for already marked messages (#1484906)
- Fix "quote inside a quote" (#1484783)
diff --git a/INSTALL b/INSTALL
index a88f4f9be..098e886f9 100644
--- a/INSTALL
+++ b/INSTALL
@@ -11,7 +11,7 @@ REQUIREMENTS
* The Apache or Lighttpd Webserver
* .htaccess support allowing overrides for DirectoryIndex
-* PHP Version 4.3.1 or greater including
+* PHP Version 5.2 or greater including
- PCRE (perl compatible regular expression)
- libiconv (recommended)
- mbstring (optional)
diff --git a/README b/README
index 6b2313a8a..1129cf59e 100644
--- a/README
+++ b/README
@@ -4,8 +4,8 @@ RoundCube Webmail (http://roundcube.net)
ATTENTION
---------
This is just a snapshot of the current SVN repository and is NOT A STABLE
-version of RoundCube. There have been major changes since the latest release
-so please read the update instructions carefully. It's not recommended to
+version of RoundCube. Unlike the latest release this version requires PHP 5
+and does not work on a webserver with PHP 4. It's not recommended to
replace an existing installation of RoundCube with this version. Also using
a separate database or this installation is highly recommended.
diff --git a/bin/html2text.php b/bin/html2text.php
index 7f74ac622..0f0e6ae14 100644
--- a/bin/html2text.php
+++ b/bin/html2text.php
@@ -1,21 +1,11 @@
get_text();
-
-$phpver = explode('.', phpversion());
-$vernum = $phpver[0] . $phpver[1] . $phpver[2];
-
-# html_entity_decode doesn't handle UTF character sets in PHP 4.x
-
-if (($vernum >= 500) && function_exists('html_entity_decode'))
- print html_entity_decode($plaintext, ENT_COMPAT, 'UTF-8');
-else
- print $plaintext;
+print html_entity_decode($converter->get_text(), ENT_COMPAT, 'UTF-8');
?>
diff --git a/bin/modcss.php b/bin/modcss.php
index e482389a8..e97b8ec9c 100644
--- a/bin/modcss.php
+++ b/bin/modcss.php
@@ -19,10 +19,8 @@
*/
-$INSTALL_PATH = realpath("./../") . "/";
-ini_set('include_path', $INSTALL_PATH.PATH_SEPARATOR.$INSTALL_PATH.'program'.PATH_SEPARATOR.ini_get('include_path'));
-
-require 'include/main.inc';
+define('INSTALL_PATH', realpath('./../') . '/');
+require INSTALL_PATH.'program/include/iniset.php';
$source = "";
if ($url = preg_replace('/[^a-z0-9.-_\?\$&=%]/i', '', $_GET['u']))
diff --git a/bin/msgexport.sh b/bin/msgexport.sh
index 616895561..890d48a06 100755
--- a/bin/msgexport.sh
+++ b/bin/msgexport.sh
@@ -1,14 +1,10 @@
#!/usr/bin/php -qC
';
}
-// init necessary objects for GUI
-rcmail_load_gui();
+// init output class
+if (!empty($_GET['_remote']) || !empty($_POST['_remote'])) {
+ rcmail_init_json();
+}
+else {
+ rcmail_load_gui();
+}
// check DB connections and exit on failure
-if ($err_str = $DB->is_error())
-{
+if ($err_str = $DB->is_error()) {
raise_error(array(
'code' => 603,
'type' => 'db',
@@ -145,24 +105,21 @@ if ($err_str = $DB->is_error())
// error steps
-if ($_action=='error' && !empty($_GET['_code']))
+if ($_action=='error' && !empty($_GET['_code'])) {
raise_error(array('code' => hexdec($_GET['_code'])), FALSE, TRUE);
-
+}
// try to log in
-if ($_action=='login' && $_task=='mail')
-{
+if ($_action=='login' && $_task=='mail') {
$host = rcmail_autoselect_host();
// check if client supports cookies
- if (empty($_COOKIE))
- {
+ if (empty($_COOKIE)) {
$OUTPUT->show_message("cookiesdisabled", 'warning');
}
else if ($_SESSION['temp'] && !empty($_POST['_user']) && isset($_POST['_pass']) &&
rcmail_login(trim(get_input_value('_user', RCUBE_INPUT_POST), ' '),
- get_input_value('_pass', RCUBE_INPUT_POST, true, 'ISO-8859-1'), $host))
- {
+ get_input_value('_pass', RCUBE_INPUT_POST, true, 'ISO-8859-1'), $host)) {
// create new session ID
unset($_SESSION['temp']);
sess_regenerate_id();
@@ -174,26 +131,22 @@ if ($_action=='login' && $_task=='mail')
header("Location: $COMM_PATH");
exit;
}
- else
- {
+ else {
$OUTPUT->show_message($IMAP->error_code == -1 ? 'imaperror' : 'loginfailed', 'warning');
rcmail_kill_session();
}
}
// end session
-else if (($_task=='logout' || $_action=='logout') && isset($_SESSION['user_id']))
-{
+else if (($_task=='logout' || $_action=='logout') && isset($_SESSION['user_id'])) {
$OUTPUT->show_message('loggedout');
rcmail_logout_actions();
rcmail_kill_session();
}
// check session and auth cookie
-else if ($_action != 'login' && $_SESSION['user_id'] && $_action != 'send')
-{
- if (!rcmail_authenticate_session())
- {
+else if ($_action != 'login' && $_SESSION['user_id'] && $_action != 'send') {
+ if (!rcmail_authenticate_session()) {
$OUTPUT->show_message('sessionerror', 'error');
rcmail_kill_session();
}
@@ -201,22 +154,20 @@ else if ($_action != 'login' && $_SESSION['user_id'] && $_action != 'send')
// log in to imap server
-if (!empty($USER->ID) && $_task=='mail')
-{
+if (!empty($USER->ID) && $_task=='mail') {
$conn = $IMAP->connect($_SESSION['imap_host'], $_SESSION['username'], decrypt_passwd($_SESSION['password']), $_SESSION['imap_port'], $_SESSION['imap_ssl']);
- if (!$conn)
- {
+ if (!$conn) {
$OUTPUT->show_message($IMAP->error_code == -1 ? 'imaperror' : 'sessionerror', 'error');
rcmail_kill_session();
}
- else
+ else {
rcmail_set_imap_prop();
+ }
}
// not logged in -> set task to 'login
-if (empty($USER->ID))
-{
+if (empty($USER->ID)) {
if ($OUTPUT->ajax_call)
$OUTPUT->remote_response("setTimeout(\"location.href='\"+this.env.comm_path+\"'\", 2000);");
@@ -225,10 +176,8 @@ if (empty($USER->ID))
// check client X-header to verify request origin
-if ($OUTPUT->ajax_call)
-{
- if (empty($CONFIG['devel_mode']) && !rc_request_header('X-RoundCube-Referer'))
- {
+if ($OUTPUT->ajax_call) {
+ if (empty($CONFIG['devel_mode']) && !rc_request_header('X-RoundCube-Referer')) {
header('HTTP/1.1 404 Not Found');
die("Invalid Request");
}
@@ -237,24 +186,25 @@ if ($OUTPUT->ajax_call)
// set task and action to client
$OUTPUT->set_env('task', $_task);
-if (!empty($_action))
+if (!empty($_action)) {
$OUTPUT->set_env('action', $_action);
+}
// not logged in -> show login page
-if (empty($USER->ID))
-{
+if (empty($USER->ID)) {
// check if installer is still active
- if ($CONFIG['enable_installer'] && is_readable('./installer/index.php'))
- $OUTPUT->add_footer('
-
-
Installer script is still accessible
-
The install script of your RoundCube installation is still stored in its default location!
-
Please remove the whole installer folder from the RoundCube directory because
- these files may expose sensitive configuration data like server passwords and encryption keys
- to the public. Make sure you cannot access the installer script from your browser.
-
');
+ if ($CONFIG['enable_installer'] && is_readable('./installer/index.php')) {
+ $OUTPUT->add_footer(html::div(array('style' => "background:#ef9398; border:2px solid #dc5757; padding:0.5em; margin:2em auto; width:50em"),
+ html::tag('h2', array('style' => "margin-top:0.2em"), "Installer script is still accessible") .
+ html::p(null, "The install script of your RoundCube installation is still stored in its default location!") .
+ html::p(null, "Please remove the whole installer folder from the RoundCube directory because .
+ these files may expose sensitive configuration data like server passwords and encryption keys
+ to the public. Make sure you cannot access the installer script from your browser.")
+ )
+ );
+ }
$OUTPUT->task = 'login';
$OUTPUT->send('login');
@@ -263,16 +213,14 @@ if (empty($USER->ID))
// handle keep-alive signal
-if ($_action=='keep-alive')
-{
+if ($_action=='keep-alive') {
$OUTPUT->reset();
$OUTPUT->send('');
exit;
}
// include task specific files
-if ($_task=='mail')
-{
+if ($_task=='mail') {
include_once('program/steps/mail/func.inc');
if ($_action=='show' || $_action=='preview' || $_action=='print')
@@ -327,13 +275,12 @@ if ($_task=='mail')
include('program/steps/mail/rss.inc');
// make sure the message count is refreshed
- $IMAP->messagecount($_SESSION['mbox'], 'ALL', TRUE);
+ $IMAP->messagecount($_SESSION['mbox'], 'ALL', true);
}
// include task specific files
-if ($_task=='addressbook')
-{
+if ($_task=='addressbook') {
include_once('program/steps/addressbook/func.inc');
if ($_action=='save')
@@ -363,8 +310,7 @@ if ($_task=='addressbook')
// include task specific files
-if ($_task=='settings')
-{
+if ($_task=='settings') {
include_once('program/steps/settings/func.inc');
if ($_action=='save-identity')
@@ -385,7 +331,6 @@ if ($_task=='settings')
if ($_action=='folders' || $_action=='subscribe' || $_action=='unsubscribe' ||
$_action=='create-folder' || $_action=='rename-folder' || $_action=='delete-folder')
include('program/steps/settings/manage_folders.inc');
-
}
@@ -399,6 +344,6 @@ raise_error(array(
'type' => 'php',
'line' => __LINE__,
'file' => __FILE__,
- 'message' => "Invalid request"), TRUE, TRUE);
+ 'message' => "Invalid request"), true, true);
?>
diff --git a/installer/check.php b/installer/check.php
index 2afa7da29..7ca982f2d 100644
--- a/installer/check.php
+++ b/installer/check.php
@@ -37,7 +37,7 @@ echo '
load_defaults();
@@ -29,7 +26,7 @@ if (!empty($_POST['submit'])) {
echo ' within the config/ directory of your RoundCube installation. ';
echo ' Make sure that there are no characters outside the <?php ?> brackets when saving the files.';
- $textbox = new textarea(array('rows' => 16, 'cols' => 60, 'class' => "configfile"));
+ $textbox = new html_textarea(array('rows' => 16, 'cols' => 60, 'class' => "configfile"));
echo '
'_des_key', 'size' => 30, 'id' => "cfgdeskey"));
+$input_deskey = new html_inputfield(array('name' => '_des_key', 'size' => 30, 'id' => "cfgdeskey"));
echo $input_deskey->show($RCI->getprop('des_key'));
?>
@@ -144,7 +141,7 @@ If you enter it manually please provide a string of exactly 24 chars.
'_auto_create_user', 'id' => "cfgautocreate"));
+$check_autocreate = new html_checkbox(array('name' => '_auto_create_user', 'id' => "cfgautocreate"));
echo $check_autocreate->show(intval($RCI->getprop('auto_create_user')), array('value' => 1));
?>
@@ -320,7 +317,7 @@ what means that you have to create those records manually or disable this option
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>%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('