diff options
-rw-r--r-- | .htaccess | 2 | ||||
-rw-r--r-- | CHANGELOG | 5 | ||||
-rw-r--r-- | index.php | 13 | ||||
-rw-r--r-- | program/include/main.inc | 254 | ||||
-rw-r--r-- | program/include/rcmail_template.inc | 18 | ||||
-rw-r--r-- | program/include/rcube_user.inc | 470 | ||||
-rw-r--r-- | program/js/app.js | 10 | ||||
-rw-r--r-- | program/lib/imap.inc | 82 | ||||
-rw-r--r-- | program/lib/rc_mail_mime.inc | 28 | ||||
-rw-r--r-- | program/localization/en_US/labels.inc | 5 | ||||
-rw-r--r-- | program/localization/en_US/messages.inc | 2 | ||||
-rw-r--r-- | program/steps/mail/compose.inc | 11 | ||||
-rw-r--r-- | program/steps/mail/func.inc | 66 | ||||
-rw-r--r-- | program/steps/mail/sendmail.inc | 111 | ||||
-rw-r--r-- | program/steps/mail/sendmdn.inc | 97 | ||||
-rw-r--r-- | program/steps/mail/show.inc | 3 | ||||
-rw-r--r-- | program/steps/settings/delete_identity.inc | 11 | ||||
-rw-r--r-- | program/steps/settings/edit_identity.inc | 9 | ||||
-rw-r--r-- | program/steps/settings/func.inc | 24 | ||||
-rw-r--r-- | program/steps/settings/save_identity.inc | 107 | ||||
-rw-r--r-- | program/steps/settings/save_prefs.inc | 7 | ||||
-rw-r--r-- | skins/default/mail.css | 12 |
22 files changed, 870 insertions, 477 deletions
@@ -7,6 +7,7 @@ AddType text/x-component .htc php_value error_log logs/errors php_value upload_max_filesize 5M php_value post_max_size 6M + php_value memory_limit 64M </IfModule> <IfModule mod_php5.c> @@ -15,6 +16,7 @@ AddType text/x-component .htc php_value error_log logs/errors php_value upload_max_filesize 5M php_value post_max_size 6M + php_value memory_limit 64M </IfModule> <FilesMatch "(\.inc|\~)$"> @@ -1,6 +1,11 @@ CHANGELOG RoundCube Webmail --------------------------- +2007/12/10 (thomasb) +---------- +- Delegate user-stuff to new class rcube_user +- Implement Message-Disposition-Notification (Receipts) + 2007/12/05 (tomekp) ---------- - update bg, uk localization @@ -2,7 +2,7 @@ /* +-----------------------------------------------------------------------+ | RoundCube Webmail IMAP Client | - | Version 0.1-20071017 | + | Version 0.1-20071210 | | | | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland | | Licensed under the GNU GPL | @@ -41,7 +41,7 @@ */ // application constants -define('RCMAIL_VERSION', '0.1-20071017'); +define('RCMAIL_VERSION', '0.1-20071210'); define('RCMAIL_CHARSET', 'UTF-8'); define('JS_OBJECT_NAME', 'rcmail'); @@ -196,7 +196,7 @@ else if ($_action != 'login' && $_SESSION['user_id'] && $_action != 'send') // log in to imap server -if (!empty($_SESSION['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) @@ -210,7 +210,7 @@ if (!empty($_SESSION['user_id']) && $_task=='mail') // not logged in -> set task to 'login -if (empty($_SESSION['user_id'])) +if (empty($USER->ID)) { if ($OUTPUT->ajax_call) $OUTPUT->remote_response("setTimeout(\"location.href='\"+this.env.comm_path+\"'\", 2000);"); @@ -238,7 +238,7 @@ if (!empty($_action)) // not logged in -> show login page -if (!$_SESSION['user_id']) +if (empty($USER->ID)) { $OUTPUT->task = 'login'; $OUTPUT->send('login'); @@ -274,6 +274,9 @@ if ($_task=='mail') if ($_action=='viewsource') include('program/steps/mail/viewsource.inc'); + if ($_action=='sendmdn') + include('program/steps/mail/sendmdn.inc'); + if ($_action=='send') include('program/steps/mail/sendmail.inc'); diff --git a/program/include/main.inc b/program/include/main.inc index 55cd8efce..7892d0924 100644 --- a/program/include/main.inc +++ b/program/include/main.inc @@ -29,6 +29,7 @@ require_once('lib/des.inc'); require_once('lib/utf7.inc'); require_once('lib/utf8.class.php'); +require_once('include/rcube_user.inc'); require_once('include/rcube_shared.inc'); require_once('include/rcmail_template.inc'); @@ -48,7 +49,7 @@ 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; + global $CONFIG, $INSTALL_PATH, $BROWSER, $OUTPUT, $_SESSION, $IMAP, $DB, $USER; // check client $BROWSER = rcube_browser(); @@ -87,6 +88,8 @@ function rcmail_startup($task='mail') // set session vars global $sess_user_lang = rcube_language_prop($_SESSION['user_lang']); + // create user object + $USER = new rcube_user($_SESSION['user_id']); // overwrite config with user preferences if (is_array($_SESSION['user_prefs'])) @@ -321,21 +324,18 @@ function rcmail_shutdown() */ function rcmail_kill_session() { - // save user preferences - $a_user_prefs = $_SESSION['user_prefs']; - if (!is_array($a_user_prefs)) - $a_user_prefs = array(); - + global $USER; + if ((isset($_SESSION['sort_col']) && $_SESSION['sort_col']!=$a_user_prefs['message_sort_col']) || (isset($_SESSION['sort_order']) && $_SESSION['sort_order']!=$a_user_prefs['message_sort_order'])) { - $a_user_prefs['message_sort_col'] = $_SESSION['sort_col']; - $a_user_prefs['message_sort_order'] = $_SESSION['sort_order']; - rcmail_save_user_prefs($a_user_prefs); + $a_user_prefs = array('message_sort_col' => $_SESSION['sort_col'], 'message_sort_order' => $_SESSION['sort_order']); + $USER->save_prefs($a_user_prefs); } $_SESSION = array('user_lang' => $GLOBALS['sess_user_lang'], 'auth_time' => time(), 'temp' => true); setcookie('sessauth', '-del-', time()-60); + $USER->reset(); } @@ -531,7 +531,7 @@ function rcmail_autoselect_host() */ function rcmail_login($user, $pass, $host=NULL) { - global $CONFIG, $IMAP, $DB, $sess_user_lang; + global $CONFIG, $IMAP, $DB, $USER, $sess_user_lang; $user_id = NULL; if (!$host) @@ -583,58 +583,51 @@ function rcmail_login($user, $pass, $host=NULL) // try to resolve email address from virtuser table if (!empty($CONFIG['virtuser_file']) && strpos($user, '@')) - $user = rcmail_email2user($user); + $user = rcube_user::email2user($user); // lowercase username if it's an e-mail address (#1484473) if (strpos($user, '@')) $user = strtolower($user); // query if user already registered - $sql_result = $DB->query( - "SELECT user_id, username, language, preferences - FROM ".get_table_name('users')." - WHERE mail_host=? AND (username=? OR alias=?)", - $host, - $user, - $user); + if ($existing = rcube_user::query($user, $host)) + $USER = $existing; // user already registered -> overwrite username - if ($sql_arr = $DB->fetch_assoc($sql_result)) + if ($USER->ID) { - $user_id = $sql_arr['user_id']; - $user = $sql_arr['username']; + $user_id = $USER->ID; + $user = $USER->data['username']; } // exit if IMAP login failed if (!($imap_login = $IMAP->connect($host, $user, $pass, $imap_port, $imap_ssl))) - return FALSE; + return false; // user already registered - if ($user_id && !empty($sql_arr)) + if ($USER->ID) { // get user prefs - if (strlen($sql_arr['preferences'])) - { - $user_prefs = unserialize($sql_arr['preferences']); - $_SESSION['user_prefs'] = $user_prefs; - array_merge($CONFIG, $user_prefs); - } - + $_SESSION['user_prefs'] = $USER->get_prefs(); + array_merge($CONFIG, $_SESSION['user_prefs']); // set user specific language - if (strlen($sql_arr['language'])) - $sess_user_lang = $_SESSION['user_lang'] = $sql_arr['language']; + if (!empty($USER->data['language'])) + $sess_user_lang = $_SESSION['user_lang'] = $USER->data['language']; // update user's record - $DB->query("UPDATE ".get_table_name('users')." - SET last_login=".$DB->now()." - WHERE user_id=?", - $user_id); + $USER->touch(); } // create new system user else if ($CONFIG['auto_create_user']) { - $user_id = rcmail_create_user($user, $host); + if ($created = rcube_user::create($user, $host)) + { + $USER = $created; + + // get existing mailboxes + $a_mailboxes = $IMAP->list_mailboxes(); + } } else { @@ -646,13 +639,13 @@ function rcmail_login($user, $pass, $host=NULL) ), true, false); } - if ($user_id) + if ($USER->ID) { - $_SESSION['user_id'] = $user_id; + $_SESSION['user_id'] = $USER->ID; + $_SESSION['username'] = $USER->data['username']; $_SESSION['imap_host'] = $host; $_SESSION['imap_port'] = $imap_port; $_SESSION['imap_ssl'] = $imap_ssl; - $_SESSION['username'] = $user; $_SESSION['user_lang'] = $sess_user_lang; $_SESSION['password'] = encrypt_passwd($pass); $_SESSION['login_time'] = mktime(); @@ -672,83 +665,6 @@ function rcmail_login($user, $pass, $host=NULL) /** - * Create new entry in users and identities table - * - * @param string User name - * @param string IMAP host - * @return mixed New user ID or False on failure - */ -function rcmail_create_user($user, $host) -{ - global $DB, $CONFIG, $IMAP; - - $user_email = ''; - - // try to resolve user in virtusertable - if (!empty($CONFIG['virtuser_file']) && !strpos($user, '@')) - $user_email = rcmail_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)); - } - - // get existing mailboxes - $a_mailboxes = $IMAP->list_mailboxes(); - } - else - { - raise_error(array( - 'code' => 500, - 'type' => 'php', - 'line' => __LINE__, - 'file' => __FILE__, - 'message' => "Failed to create new user"), TRUE, FALSE); - } - - return $user_id; -} - - -/** * Load virtuser table in array * * @return array Virtuser table entries @@ -794,90 +710,6 @@ function rcmail_findinvirtual($pattern) /** - * Resolve username using a virtuser table - * - * @param string E-mail address to resolve - * @return string Resolved IMAP username - */ -function rcmail_email2user($email) - { - $user = $email; - $r = rcmail_findinvirtual("^$email"); - - for ($i=0; $i<count($r); $i++) - { - $data = $r[$i]; - $arr = preg_split('/\s+/', $data); - if(count($arr)>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 - */ -function rcmail_user2email($user) - { - $email = ""; - $r = rcmail_findinvirtual("$user$"); - - for ($i=0; $i<count($r); $i++) - { - $data=$r[$i]; - $arr = preg_split('/\s+/', $data); - if (count($arr)>0) - { - $email = trim($arr[0]); - break; - } - } - - return $email; - } - - -/** - * 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 rcmail_save_user_prefs($a_user_prefs) - { - global $DB, $CONFIG, $sess_user_lang; - - // merge (partial) prefs array with existing settings - $a_user_prefs += (array)$_SESSION['user_prefs']; - - $DB->query("UPDATE ".get_table_name('users')." - SET preferences=?, - language=? - WHERE user_id=?", - serialize($a_user_prefs), - $sess_user_lang, - $_SESSION['user_id']); - - if ($DB->affected_rows()) - { - $_SESSION['user_prefs'] = $a_user_prefs; - $CONFIG = array_merge($CONFIG, $a_user_prefs); - return TRUE; - } - - return FALSE; - } - - -/** * Overwrite action variable * * @param string New action value @@ -1514,6 +1346,26 @@ function rcmail_mod_css_styles($source, $container_id, $base_url = '') return $styles; } +/** + * Try to autodetect operating system and find the correct line endings + * + * @return string The appropriate mail header delimiter + */ +function rcmail_header_delm() +{ + global $CONFIG; + + // use the configured delimiter for headers + if (!empty($CONFIG['mail_header_delimiter'])) + return $CONFIG['mail_header_delimiter']; + else if (strtolower(substr(PHP_OS, 0, 3)=='win')) + return "\r\n"; + else if (strtolower(substr(PHP_OS, 0, 3)=='mac')) + return "\r\n"; + else + return "\n"; +} + /** * Compose a valid attribute string for HTML tags diff --git a/program/include/rcmail_template.inc b/program/include/rcmail_template.inc index 558bd4bf6..cc5a58ac1 100644 --- a/program/include/rcmail_template.inc +++ b/program/include/rcmail_template.inc @@ -761,27 +761,15 @@ function rcmail_message_container($attrib) */ function rcmail_current_username($attrib) { - global $DB; + global $USER; static $s_username; // alread fetched if (!empty($s_username)) return $s_username; - // get e-mail address form default identity - $sql_result = $DB->query( - "SELECT email AS mailto - FROM ".get_table_name('identities')." - WHERE user_id=? - AND standard=1 - AND del<>1", - $_SESSION['user_id']); - - if ($DB->num_rows($sql_result)) - { - $sql_arr = $DB->fetch_assoc($sql_result); - $s_username = $sql_arr['mailto']; - } + if ($sql_arr = $USER->get_identity()) + $s_username = $sql_arr['email']; else if (strstr($_SESSION['username'], '@')) $s_username = $_SESSION['username']; else diff --git a/program/include/rcube_user.inc b/program/include/rcube_user.inc new file mode 100644 index 000000000..841c84341 --- /dev/null +++ b/program/include/rcube_user.inc @@ -0,0 +1,470 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | program/include/rcube_user.inc | + | | + | This file is part of the RoundCube Webmail client | + | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland | + | Licensed under the GNU GPL | + | | + | PURPOSE: | + | This class represents a system user linked and provides access | + | to the related database records. | + | | + +-----------------------------------------------------------------------+ + | Author: Thomas Bruederli <roundcube@gmail.com> | + +-----------------------------------------------------------------------+ + + $Id: rcube_user.inc 933 2007-11-29 14:17:32Z thomasb $ + +*/ + + +/** + * Class representing a system user + * + * @package core + * @author Thomas Bruederli <roundcube@gmail.com> + */ +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; + + $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 = self::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<count($r); $i++) + { + $data = $r[$i]; + $arr = preg_split('/\s+/', $data); + if (count($arr) > 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<count($r); $i++) + { + $data = $r[$i]; + $arr = preg_split('/\s+/', $data); + if (count($arr) > 0) + { + $email = trim($arr[0]); + break; + } + } + + return $email; + } + +} + + +?> diff --git a/program/js/app.js b/program/js/app.js index 7162795fe..f0065acf5 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -223,6 +223,16 @@ function rcube_webmail() this.gui_objects.folderlist = this.gui_objects.mailboxlist; this.http_request('getunread', ''); } + + // ask user to send MDN + if (this.env.mdn_request && this.env.uid) + { + var mdnurl = '_uid='+this.env.uid+'&_mbox='+urlencode(this.env.mailbox); + if (confirm(this.get_label('mdnrequest'))) + this.http_post('sendmdn', mdnurl); + else + this.http_post('mark', mdnurl+'&_flag=mdnsent'); + } break; diff --git a/program/lib/imap.inc b/program/lib/imap.inc index fef0b8b5d..c5940773d 100644 --- a/program/lib/imap.inc +++ b/program/lib/imap.inc @@ -1255,6 +1255,7 @@ function iil_C_FetchHeaders(&$conn, $mailbox, $message_set, $uidfetch=false){ $result[$id]=new iilBasicHeader; $result[$id]->id = $id; $result[$id]->subject = ""; + $result[$id]->messageID = "mid:".$id; /* Start parsing headers. The problem is, some header "lines" take up multiple lines. So, we'll read ahead, and if the one we're reading now is a valid header, we'll @@ -1293,38 +1294,63 @@ function iil_C_FetchHeaders(&$conn, $mailbox, $message_set, $uidfetch=false){ } // create array with header field:data - $headers = array(); while ( list($lines_key, $str) = each($lines) ){ list($field, $string) = iil_SplitHeaderLine($str); $field = strtolower($field); - $headers[$field] = $string; - } - $result[$id]->date = $headers["date"]; - $result[$id]->timestamp = iil_StrToTime($headers["date"]); - $result[$id]->from = $headers["from"]; - $result[$id]->to = str_replace("\n", " ", $headers["to"]); - $result[$id]->subject = str_replace("\n", "", $headers["subject"]); - $result[$id]->replyto = str_replace("\n", " ", $headers["reply-to"]); - $result[$id]->cc = str_replace("\n", " ", $headers["cc"]); - $result[$id]->bcc = str_replace("\n", " ", $headers["bcc"]); - $result[$id]->encoding = str_replace("\n", " ", $headers["content-transfer-encoding"]); - $result[$id]->ctype = str_replace("\n", " ", $headers["content-type"]); - $result[$id]->in_reply_to = ereg_replace("[\n<>]",'', $headers['in-reply-to']); - $result[$id]->references = $headers["references"]; - $result[$id]->mdn_to = $headers["disposition-notification-to"]; - - list($result[$id]->ctype, $ctype_add) = explode(";", $headers["content-type"]); - - if (preg_match('/charset="?([a-z0-9\-]+)"?/i', $ctype_add, $regs)) - $result[$id]->charset = $regs[1]; - - $messageID = $headers["message-id"]; - if (!$messageID) "mid:".$id; - $result[$id]->messageID = $messageID; + + switch ($field){ + case 'date'; + $result[$id]->date = $string; + $result[$id]->timestamp = iil_StrToTime($string); + break; + case 'from': + $result[$id]->from = $string; + break; + case 'to': + $result[$id]->to = str_replace("\n", " ", $string); + break; + case 'subject': + $result[$id]->subject = str_replace("\n", "", $string); + break; + case 'reply-to': + $result[$id]->replyto = str_replace("\n", " ", $string); + break; + case 'cc': + $result[$id]->cc = str_replace("\n", " ", $string); + break; + case 'bcc': + $result[$id]->bcc = str_replace("\n", " ", $string); + break; + case 'content-transfer-encoding': + $result[$id]->encoding = str_replace("\n", " ", $string); + break; + case 'content-type': + $ctype_parts = explode(";", $string); + $result[$id]->ctype = array_shift($ctype_parts); + foreach ($ctype_parts as $ctype_add) + if (preg_match('/charset="?([a-z0-9\-]+)"?/i', $ctype_add, $regs)) + $result[$id]->charset = $regs[1]; + break; + case 'in-reply-to': + $result[$id]->in_reply_to = ereg_replace("[\n<>]", '', $string); + break; + case 'references': + $result[$id]->references = $string; + break; + case 'return-receipt-to': + case 'disposition-notification-to': + case 'x-confirm-reading-to': + $result[$id]->mdn_to = str_replace("\n", " ", $string); + break; + case 'message-id': + $result[$id]->messageID = $string; + break; + } } - else { - $a=explode(" ", $line); - } + } + else { + $a=explode(" ", $line); + } } }while(strcmp($a[0], $key)!=0); diff --git a/program/lib/rc_mail_mime.inc b/program/lib/rc_mail_mime.inc index 12d80bbfb..ca4d0bf93 100644 --- a/program/lib/rc_mail_mime.inc +++ b/program/lib/rc_mail_mime.inc @@ -25,6 +25,14 @@ require_once('Mail/mime.php'); class rc_mail_mime extends Mail_mime { + /** + * Set build parameters + */ + function setParam($param) + { + if (is_array($param)) + $this->_build_params = array_merge($this->_build_params, $param); + } /** * Adds an image to the list of embedded images. @@ -63,7 +71,7 @@ class rc_mail_mime extends Mail_mime return true; } - + /** * returns the HTML body portion of the message @@ -77,6 +85,22 @@ class rc_mail_mime extends Mail_mime /** + * Creates a new mimePart object, using multipart/mixed as + * the initial content-type and returns it during the + * build process. + * + * @return object The multipart/mixed mimePart object + * @access private + */ + function &_addMixedPart() + { + $params['content_type'] = $this->_headers['Content-Type'] ? $this->_headers['Content-Type'] : 'multipart/mixed'; + $ret = new Mail_mimePart('', $params); + return $ret; + } + + + /** * Encodes a header as per RFC2047 * * @param array $input The header data to encode @@ -138,7 +162,7 @@ class rc_mail_mime extends Mail_mime // add chunk to output string by regarding the header maxlen $len = strlen($value); - if ($line_len + $len < $maxlen) + if ($i == 0 || $line_len + $len < $maxlen) { $hdr_value .= ($i>0?', ':'') . $value; $line_len += $len + ($i>0?2:0); diff --git a/program/localization/en_US/labels.inc b/program/localization/en_US/labels.inc index e4f04f95e..0b8213759 100644 --- a/program/localization/en_US/labels.inc +++ b/program/localization/en_US/labels.inc @@ -160,6 +160,11 @@ $labels['addcc'] = 'Add Cc'; $labels['addbcc'] = 'Add Bcc'; $labels['addreplyto'] = 'Add Reply-To'; +// mdn +$labels['mdnrequest'] = 'The sender of this message has asked to be notified when you read this message. Do you wish to notify the sender?'; +$labels['receiptread'] = 'Return Receipt (read)'; +$labels['yourmessage'] = 'This is a Return Receipt for your message'; +$labels['receiptnote'] = 'Note: This receipt only acknowledges that the message was displayed on the recipient\'s computer. There is no guarantee that the recipient has read or understood the message contents.'; // address boook $labels['name'] = 'Display name'; diff --git a/program/localization/en_US/messages.inc b/program/localization/en_US/messages.inc index 601075771..119e59512 100644 --- a/program/localization/en_US/messages.inc +++ b/program/localization/en_US/messages.inc @@ -74,5 +74,7 @@ $messages['copyerror'] = 'Could not copy any addresses'; $messages['sourceisreadonly'] = 'This address source is read only'; $messages['errorsavingcontact'] = 'Could not save the contact address'; $messages['movingmessage'] = 'Moving message...'; +$messages['receiptsent'] = 'Successfully send the receipt message'; +$messages['errorsendingreceipt'] = 'Could not send the receipt'; ?>
\ No newline at end of file diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc index 5131010af..36a3d7069 100644 --- a/program/steps/mail/compose.inc +++ b/program/steps/mail/compose.inc @@ -230,7 +230,7 @@ function rcmail_compose_headers($attrib) function rcmail_compose_header_from($attrib) { - global $IMAP, $MESSAGE, $DB, $OUTPUT, $compose_mode; + global $IMAP, $MESSAGE, $DB, $USER, $OUTPUT, $compose_mode; // pass the following attributes to the form class $field_attrib = array('name' => '_from'); @@ -263,12 +263,7 @@ function rcmail_compose_header_from($attrib) } // get this user's identities - $sql_result = $DB->query("SELECT identity_id, name, email, signature, html_signature - FROM ".get_table_name('identities')." - WHERE user_id=? - AND del<>1 - ORDER BY ".$DB->quoteIdentifier('standard')." DESC, name ASC", - $_SESSION['user_id']); + $sql_result = $USER->list_identities(); if ($DB->num_rows($sql_result)) { @@ -869,7 +864,7 @@ $OUTPUT->add_handlers(array( require_once('include/rcube_contacts.inc'); -$CONTACTS = new rcube_contacts($DB, $_SESSION['user_id']); +$CONTACTS = new rcube_contacts($DB, $USER->ID); $CONTACTS->set_pagesize(1000); if ($result = $CONTACTS->list_records()) diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc index dd3801672..de8987248 100644 --- a/program/steps/mail/func.inc +++ b/program/steps/mail/func.inc @@ -21,6 +21,7 @@ require_once('lib/html2text.inc'); require_once('lib/enriched.inc'); +require_once('include/rcube_smtp.inc'); $EMAIL_ADDRESS_PATTERN = '/([a-z0-9][a-z0-9\-\.\+\_]*@[a-z0-9]([a-z0-9\-][.]?)*[a-z0-9]\\.[a-z]{2,5})/i'; @@ -725,7 +726,7 @@ function rcmail_parse_message(&$structure, $arg=array(), $recursive=FALSE) // part text/[plain|html] OR message/delivery-status else if (($primary_type=='text' && ($secondary_type=='plain' || $secondary_type=='html') && $mail_part->disposition!='attachment') || - ($primary_type=='message' && $secondary_type=='delivery-status')) + ($primary_type=='message' && ($secondary_type=='delivery-status' || $secondary_type=='disposition-notification'))) { $mail_part->type = 'content'; $a_return_parts[] = $mail_part; @@ -758,7 +759,7 @@ function rcmail_parse_message(&$structure, $arg=array(), $recursive=FALSE) else { if (!$mail_part->filename) - $mail_part->filename = 'file_'.$mail_part->mime_id; + $mail_part->filename = 'Part '.$mail_part->mime_id; $a_attachments[] = $mail_part; } } @@ -1250,6 +1251,67 @@ function rcmail_compose_cleanup() unset($_SESSION['compose']); } + + +/** + * Send the given message compose object using the configured method + */ +function rcmail_deliver_message(&$message, $from, $mailto) +{ + global $CONFIG; + + $headers = $message->headers(); + $msg_body = $message->get(); + + // send thru SMTP server using custom SMTP library + if ($CONFIG['smtp_server']) + { + // generate list of recipients + $a_recipients = array($mailto); + + if (strlen($headers['Cc'])) + $a_recipients[] = $headers['Cc']; + if (strlen($headers['Bcc'])) + $a_recipients[] = $headers['Bcc']; + + // clean Bcc from header for recipients + $send_headers = $headers; + unset($send_headers['Bcc']); + + // send message + $smtp_response = array(); + $sent = smtp_mail($from, $a_recipients, ($foo = $message->txtHeaders($send_headers)), $msg_body, $smtp_response); + + // log error + if (!$sent) + raise_error(array('code' => 800, 'type' => 'smtp', 'line' => __LINE__, 'file' => __FILE__, + 'message' => "SMTP error: ".join("\n", $smtp_response)), TRUE, FALSE); + } + + // send mail using PHP's mail() function + else + { + // unset some headers because they will be added by the mail() function + $headers_enc = $message->headers($headers); + $headers_php = $message->_headers; + unset($headers_php['To'], $headers_php['Subject']); + + // reset stored headers and overwrite + $message->_headers = array(); + $header_str = $message->txtHeaders($headers_php); + + if (ini_get('safe_mode')) + $sent = mail($headers_enc['To'], $headers_enc['Subject'], $msg_body, $header_str); + else + $sent = mail($headers_enc['To'], $headers_enc['Subject'], $msg_body, $header_str, "-f$from"); + } + + + $message->_headers = array(); + $message->headers($headers); + + return $sent; +} // register UI objects diff --git a/program/steps/mail/sendmail.inc b/program/steps/mail/sendmail.inc index d118af53f..6f4744db9 100644 --- a/program/steps/mail/sendmail.inc +++ b/program/steps/mail/sendmail.inc @@ -22,7 +22,6 @@ //require_once('lib/smtp.inc'); -require_once('include/rcube_smtp.inc'); require_once('lib/html2text.inc'); require_once('lib/rc_mail_mime.inc'); @@ -37,26 +36,19 @@ if (!isset($_SESSION['compose']['id'])) /****** message sending functions ********/ +// get identity record function rcmail_get_identity($id) { - global $DB, $OUTPUT; + global $USER, $OUTPUT; - // get identity record - $sql_result = $DB->query("SELECT *, email AS mailto - FROM ".get_table_name('identities')." - WHERE identity_id=? - AND user_id=? - AND del<>1", - $id,$_SESSION['user_id']); - - if ($DB->num_rows($sql_result)) + if ($sql_arr = $USER->get_identity($id)) { - $sql_arr = $DB->fetch_assoc($sql_result); $out = $sql_arr; + $out['mailto'] = $sql_arr['email']; $name = strpos($sql_arr['name'], ",") ? '"'.$sql_arr['name'].'"' : $sql_arr['name']; $out['string'] = sprintf('%s <%s>', rcube_charset_convert($name, RCMAIL_CHARSET, $OUTPUT->get_charset()), - $sql_arr['mailto']); + $sql_arr['email']); return $out; } @@ -166,7 +158,7 @@ if (empty($identity_arr['string'])) $identity_arr['string'] = $from; // compose headers array -$headers = array('Date' => date('D, j M Y H:i:s O'), +$headers = array('Date' => date('r'), 'From' => rcube_charset_convert($identity_arr['string'], RCMAIL_CHARSET, $message_charset), 'To' => $mailto); @@ -225,23 +217,11 @@ $message_body = get_input_value('_message', RCUBE_INPUT_POST, TRUE, $message_cha if (!$savedraft && !empty($CONFIG['generic_message_footer']) && ($footer = file_get_contents(realpath($CONFIG['generic_message_footer'])))) $message_body .= "\r\n" . rcube_charset_convert($footer, 'UTF-8', $message_charset); -// try to autodetect operating system and use the correct line endings -// use the configured delimiter for headers -if (!empty($CONFIG['mail_header_delimiter'])) - $header_delm = $CONFIG['mail_header_delimiter']; -else if (strtolower(substr(PHP_OS, 0, 3)=='win')) - $header_delm = "\r\n"; -else if (strtolower(substr(PHP_OS, 0, 3)=='mac')) - $header_delm = "\r\n"; -else - $header_delm = "\n"; - - $isHtmlVal = strtolower(get_input_value('_is_html', RCUBE_INPUT_POST)); $isHtml = ($isHtmlVal == "1"); // create extended PEAR::Mail_mime instance -$MAIL_MIME = new rc_mail_mime($header_delm); +$MAIL_MIME = new rc_mail_mime(rcmail_header_delm()); // For HTML-formatted messages, construct the MIME message with both // the HTML part and the plain-text part @@ -282,80 +262,30 @@ $charset_7bit = array('ASCII', 'ISO-2022-JP', 'ISO-8859-1', 'ISO-8859-2', 'ISO-8 $transfer_encoding = in_array(strtoupper($message_charset), $charset_7bit) ? '7bit' : '8bit'; // encoding settings for mail composing -$message_param = array( +$MAIL_MIME->setParam(array( 'text_encoding' => $transfer_encoding, 'html_encoding' => 'quoted-printable', 'head_encoding' => 'quoted-printable', 'head_charset' => $message_charset, 'html_charset' => $message_charset, 'text_charset' => $message_charset, -); - -// compose message body and get headers -$msg_body = $MAIL_MIME->get($message_param); -// unset to save memory. -unset($MAIL_MIME->_parts); +)); // encoding subject header with mb_encode provides better results with asian characters if ($MBSTRING && function_exists("mb_encode_mimeheader")) { mb_internal_encoding($message_charset); - $mb_subject = mb_encode_mimeheader($headers['Subject'], $message_charset, 'Q'); + $headers['Subject'] = mb_encode_mimeheader($headers['Subject'], $message_charset, 'Q'); mb_internal_encoding(RCMAIL_CHARSET); } -// Begin SMTP Delivery Block -if (!$savedraft) { +// pass headers to message object +$MAIL_MIME->headers($headers); - // send thru SMTP server using custom SMTP library - if ($CONFIG['smtp_server']) - { - // generate list of recipients - $a_recipients = array($mailto); - - if (strlen($headers['Cc'])) - $a_recipients[] = $headers['Cc']; - if (strlen($headers['Bcc'])) - $a_recipients[] = $headers['Bcc']; - - // clean Bcc from header for recipients - $send_headers = $headers; - unset($send_headers['Bcc']); - - if (!empty($mb_subject)) - $send_headers['Subject'] = $mb_subject; - - // send message - $smtp_response = array(); - $sent = smtp_mail($from, $a_recipients, ($foo = $MAIL_MIME->txtHeaders($send_headers)), $msg_body, $smtp_response); - - // log error - if (!$sent) - raise_error(array('code' => 800, 'type' => 'smtp', 'line' => __LINE__, 'file' => __FILE__, - 'message' => "SMTP error: ".join("\n", $smtp_response)), TRUE, FALSE); - } - - // send mail using PHP's mail() function - else - { - // unset some headers because they will be added by the mail() function - $headers_enc = $MAIL_MIME->headers($headers); - $headers_php = $MAIL_MIME->_headers; - unset($headers_php['To'], $headers_php['Subject']); - - if (!empty($mb_subject)) - $headers_enc['Subject'] = $mb_subject; - - // reset stored headers and overwrite - $MAIL_MIME->_headers = array(); - $header_str = $MAIL_MIME->txtHeaders($headers_php); - - if (ini_get('safe_mode')) - $sent = mail($headers_enc['To'], $headers_enc['Subject'], $msg_body, $header_str); - else - $sent = mail($headers_enc['To'], $headers_enc['Subject'], $msg_body, $header_str, "-f$from"); - } - +// Begin SMTP Delivery Block +if (!$savedraft) +{ + $sent = rcmail_deliver_message($MAIL_MIME, $from, $mailto); // return to compose page if sending failed if (!$sent) @@ -365,7 +295,6 @@ if (!$savedraft) { return; } - // set repliead flag if ($_SESSION['compose']['reply_uid']) $IMAP->set_flag($_SESSION['compose']['reply_uid'], 'ANSWERED'); @@ -382,21 +311,15 @@ else if ($CONFIG[$store_target]) { - // create string of complete message headers - $header_str = $MAIL_MIME->txtHeaders($headers); - // check if mailbox exists if (!in_array_nocase($CONFIG[$store_target], $IMAP->list_mailboxes())) $store_folder = $IMAP->create_mailbox($CONFIG[$store_target], TRUE); else $store_folder = TRUE; - // add headers to message body - $msg_body = $header_str."\r\n".$msg_body; - // append message to sent box if ($store_folder) - $saved = $IMAP->save_message($CONFIG[$store_target], $msg_body); + $saved = $IMAP->save_message($CONFIG[$store_target], $MAIL_MIME->getMessage()); // raise error if saving failed if (!$saved) diff --git a/program/steps/mail/sendmdn.inc b/program/steps/mail/sendmdn.inc new file mode 100644 index 000000000..0944e7602 --- /dev/null +++ b/program/steps/mail/sendmdn.inc @@ -0,0 +1,97 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | program/steps/mail/sendmdn.inc | + | | + | This file is part of the RoundCube Webmail client | + | Copyright (C) 2007, RoundCube Dev. - Switzerland | + | Licensed under the GNU GPL | + | | + | PURPOSE: | + | Send a message disposition notification for a specific mail | + | | + +-----------------------------------------------------------------------+ + | Author: Thomas Bruederli <roundcube@gmail.com> | + +-----------------------------------------------------------------------+ + + $Id: sendmail.inc 930 2007-11-25 17:34:19Z thomasb $ + +*/ + +require_once('lib/rc_mail_mime.inc'); + + +if (!empty($_POST['_uid'])) + { + $MESSAGE = array('UID' => get_input_value('_uid', RCUBE_INPUT_POST)); + $MESSAGE['headers'] = $IMAP->get_headers($MESSAGE['UID']); + $MESSAGE['subject'] = rcube_imap::decode_mime_string($MESSAGE['headers']->subject, $MESSAGE['headers']->charset); + + if ($MESSAGE['headers']->mdn_to && !$MESSAGE['headers']->mdn_sent) + { + $identity = $USER->get_identity(); + $sender = format_email_recipient($identity['email'], $identity['name']); + $recipient = array_shift($IMAP->decode_address_list($MESSAGE['headers']->mdn_to)); + $mailto = $recipient['mailto']; + + $COMPOSE = new rc_mail_mime(rcmail_header_delm()); + $COMPOSE->setParam(array( + 'text_encoding' => 'quoted-printable', + 'html_encoding' => 'quoted-printable', + 'head_encoding' => 'quoted-printable', + 'head_charset' => RCMAIL_CHARSET, + 'html_charset' => RCMAIL_CHARSET, + 'text_charset' => RCMAIL_CHARSET, + )); + + // compose headers array + $headers = array( + 'Date' => date('r'), + 'From' => $sender, + 'To' => $MESSAGE['headers']->mdn_to, + 'Subject' => rcube_label('receiptread') . ': ' . $MESSAGE['subject'], + 'Message-ID' => sprintf('<%s@%s>', md5(uniqid('rcmail'.rand(),true)), rcmail_mail_domain($_SESSION['imap_host'])), + 'X-Sender' => $identity['email'], + 'Content-Type' => 'multipart/report; report-type=disposition-notification', + ); + + if (!empty($CONFIG['useragent'])) + $headers['User-Agent'] = $CONFIG['useragent']; + + $body = rcube_label("yourmessage") . "\r\n\r\n" . + "\t" . rcube_label("to") . ': ' . rcube_imap::decode_mime_string($MESSAGE['headers']->to, $MESSAGE['headers']->charset) . "\r\n" . + "\t" . rcube_label("subject") . ': ' . $MESSAGE['subject'] . "\r\n" . + "\t" . rcube_label("sent") . ': ' . format_date(strtotime($MESSAGE['headers']->date), $CONFIG['date_long']) . "\r\n" . + "\r\n" . rcube_label("receiptnote") . "\r\n"; + + $report = "Reporting-UA: RoundCube Webmail (Version ".RCMAIL_VERSION.")\r\n"; + + if ($MESSAGE['headers']->to) + $report .= "Original-Recipient: {$MESSAGE['headers']->to}\r\n"; + + $report .= "Final-Recipient: rfc822; {$identity['email']}\r\n" . + "Original-Message-ID: {$MESSAGE['headers']->messageID}\r\n" . + "Disposition: manual-action/MDN-sent-manually; displayed\r\n"; + + $COMPOSE->headers($headers, true); + $COMPOSE->setTXTBody($body); + $COMPOSE->addAttachment($report, 'message/disposition-notification', 'MDNPart2.txt', false, '7bit', 'inline'); + + $sent = rcmail_deliver_message($COMPOSE, $identity['email'], $mailto); + + if ($sent) + { + $IMAP->set_flag($MESSAGE['UID'], 'MDNSENT'); + $OUTPUT->set_env('mdn_request', false); + $OUTPUT->show_message('receiptsent', 'confirmation'); + $OUTPUT->send(); + } + } +} + +// Error if arrive here +$OUTPUT->show_message('errorsendingreceipt', 'error'); +$OUTPUT->send(); + +?>
\ No newline at end of file diff --git a/program/steps/mail/show.inc b/program/steps/mail/show.inc index 022edb0ed..45d64b87b 100644 --- a/program/steps/mail/show.inc +++ b/program/steps/mail/show.inc @@ -75,7 +75,10 @@ if ($_GET['_uid']) // check for unset disposition notification if ($MESSAGE['headers']->mdn_to && !$MESSAGE['headers']->mdn_sent) + { + rcube_add_label('mdnrequest'); $OUTPUT->set_env('mdn_request', true); + } $next = $prev = -1; // get previous, first, next and last message UID diff --git a/program/steps/settings/delete_identity.inc b/program/steps/settings/delete_identity.inc index 3614a3e96..06fdd94f4 100644 --- a/program/steps/settings/delete_identity.inc +++ b/program/steps/settings/delete_identity.inc @@ -21,15 +21,8 @@ if (($ids = get_input_value('_iid', RCUBE_INPUT_GET)) && preg_match('/^[0-9]+(,[0-9]+)*$/', $ids)) { - $DB->query( - "UPDATE ".get_table_name('identities')." - SET del=1 - WHERE user_id=? - AND identity_id IN (".$ids.")", - $_SESSION['user_id']); - - $count = $DB->affected_rows(); - if ($count) + + if ($USER->delete_identity($ids)) $OUTPUT->show_message('deletedsuccessfully', 'confirmation'); // send response diff --git a/program/steps/settings/edit_identity.inc b/program/steps/settings/edit_identity.inc index 51a0cd0a0..4d89f7cbc 100644 --- a/program/steps/settings/edit_identity.inc +++ b/program/steps/settings/edit_identity.inc @@ -21,14 +21,7 @@ if (($_GET['_iid'] || $_POST['_iid']) && $_action=='edit-identity') { - $DB->query("SELECT * FROM ".get_table_name('identities')." - WHERE identity_id=? - AND user_id=? - AND del<>1", - get_input_value('_iid', RCUBE_INPUT_GPC), - $_SESSION['user_id']); - - $IDENTITY_RECORD = $DB->fetch_assoc(); + $IDENTITY_RECORD = $USER->get_identity(get_input_value('_iid', RCUBE_INPUT_GPC)); if (is_array($IDENTITY_RECORD)) $OUTPUT->set_env('iid', $IDENTITY_RECORD['identity_id']); diff --git a/program/steps/settings/func.inc b/program/steps/settings/func.inc index ecdbcbd76..e63f01620 100644 --- a/program/steps/settings/func.inc +++ b/program/steps/settings/func.inc @@ -20,15 +20,8 @@ */ -// get user record -$sql_result = $DB->query("SELECT username, mail_host FROM ".get_table_name('users')." - WHERE user_id=?", - $_SESSION['user_id']); - -if ($USER_DATA = $DB->fetch_assoc($sql_result)) -{ - $OUTPUT->set_pagetitle(rcube_label('settingsfor') . " ". $USER_DATA['username'] . (!strpos($USER_DATA['username'], '@') ? '@'.$USER_DATA['mail_host'] : '')); -} +if ($USER->ID) + $OUTPUT->set_pagetitle(rcube_label('settingsfor') . " ". $USER->get_username()); @@ -204,16 +197,7 @@ function rcmail_user_prefs_form($attrib) function rcmail_identities_list($attrib) { - global $DB, $CONFIG, $OUTPUT; - - - // get contacts from DB - $sql_result = $DB->query("SELECT * FROM ".get_table_name('identities')." - WHERE del<>1 - AND user_id=? - ORDER BY standard DESC, name ASC", - $_SESSION['user_id']); - + global $OUTPUT, $USER; // add id to message list table if not specified if (!strlen($attrib['id'])) @@ -223,7 +207,7 @@ function rcmail_identities_list($attrib) $a_show_cols = array('name', 'email', 'organization', 'reply-to'); // create XHTML table - $out = rcube_table_output($attrib, $sql_result, $a_show_cols, 'identity_id'); + $out = rcube_table_output($attrib, $USER->list_identities(), $a_show_cols, 'identity_id'); // set client env $OUTPUT->add_gui_object('identitieslist', $attrib['id']); diff --git a/program/steps/settings/save_identity.inc b/program/steps/settings/save_identity.inc index 8079b589a..2c2a55e49 100644 --- a/program/steps/settings/save_identity.inc +++ b/program/steps/settings/save_identity.inc @@ -33,123 +33,78 @@ if (empty($_POST['_name']) || empty($_POST['_email'])) } +$save_data = array(); +foreach ($a_save_cols as $col) +{ + $fname = '_'.$col; + if (isset($_POST[$fname])) + $save_data[$col] = get_input_value($fname, RCUBE_INPUT_POST, in_array($col, $a_html_cols)); +} + +// set "off" values for checkboxes that were not checked, and therefore +// not included in the POST body. +foreach ($a_boolean_cols as $col) +{ + $fname = '_' . $col; + if (!isset($_POST[$fname])) + $save_data[$col] = 0; +} + + // update an existing contact if ($_POST['_iid']) +{ + if ($updated = $USER->update_identity(get_input_value('_iid', RCUBE_INPUT_POST), $save_data)) { - $a_write_sql = array(); - - foreach ($a_save_cols as $col) - { - $fname = '_'.$col; - if (isset($_POST[$fname])) - $a_write_sql[] = sprintf("%s=%s", - $DB->quoteIdentifier($col), - $DB->quote(get_input_value($fname, RCUBE_INPUT_POST, in_array($col, $a_html_cols)))); - } - - // set "off" values for checkboxes that were not checked, and therefore - // not included in the POST body. - foreach ($a_boolean_cols as $col) - { - $fname = '_' . $col; - if (!isset($_POST[$fname])) - $a_write_sql[] = sprintf("%s=0", $DB->quoteIdentifier($col)); - } - - if (sizeof($a_write_sql)) - { - $DB->query( - "UPDATE ".get_table_name('identities')." - SET ".join(', ', $a_write_sql)." - WHERE identity_id=? - AND user_id=? - AND del<>1", - get_input_value('_iid', RCUBE_INPUT_POST), - $_SESSION['user_id']); - - $updated = $DB->affected_rows(); - } - - if ($updated) - { $OUTPUT->show_message('successfullysaved', 'confirmation'); if (!empty($_POST['_standard'])) $default_id = get_input_value('_iid', RCUBE_INPUT_POST); if ($_POST['_framed']) - { + { // update the changed col in list // ... - } } + } else if ($DB->is_error()) - { + { // show error message $OUTPUT->show_message('errorsaving', 'error'); rcmail_overwrite_action('edit-identitiy'); return; - } } +} // insert a new contact else +{ + if ($insert_id = $USER->insert_identity($save_data)) { - $a_insert_cols = $a_insert_values = array(); - - foreach ($a_save_cols as $col) - { - $fname = '_'.$col; - if (!isset($_POST[$fname])) - continue; - - $a_insert_cols[] = $DB->quoteIdentifier($col); - $a_insert_values[] = $DB->quote(get_input_value($fname, RCUBE_INPUT_POST, in_array($col, $a_html_cols))); - } - - if (sizeof($a_insert_cols)) - { - $DB->query("INSERT INTO ".get_table_name('identities')." - (user_id, ".join(', ', $a_insert_cols).") - VALUES (?, ".join(', ', $a_insert_values).")", - $_SESSION['user_id']); - - $insert_id = $DB->insert_id(get_sequence_name('identities')); - } - - if ($insert_id) - { $_GET['_iid'] = $insert_id; if (!empty($_POST['_standard'])) $default_id = $insert_id; if ($_POST['_framed']) - { + { // add contact row or jump to the page where it should appear // .... - } } + } else - { + { // show error message $OUTPUT->show_message('errorsaving', 'error'); rcmail_overwrite_action('edit-identity'); return; - } } +} // mark all other identities as 'not-default' if ($default_id) - $DB->query( - "UPDATE ".get_table_name('identities')." - SET ".$DB->quoteIdentifier('standard')."='0' - WHERE user_id=? - AND identity_id<>? - AND del<>1", - $_SESSION['user_id'], - $default_id); + $USER->set_default($default_id); // go to next step rcmail_overwrite_action($_framed ? 'edit-identity' : 'identities'); diff --git a/program/steps/settings/save_prefs.inc b/program/steps/settings/save_prefs.inc index 0565260f0..caa4a49e5 100644 --- a/program/steps/settings/save_prefs.inc +++ b/program/steps/settings/save_prefs.inc @@ -44,15 +44,12 @@ if (isset($_POST['_language'])) // force min size if ($a_user_prefs['pagesize'] < 1) - { $a_user_prefs['pagesize'] = 10; - } + if (isset($CONFIG['max_pagesize']) && ($a_user_prefs['pagesize'] > $CONFIG['max_pagesize'])) - { $a_user_prefs['pagesize'] = (int) $CONFIG['max_pagesize']; - } -if (rcmail_save_user_prefs($a_user_prefs)) +if ($USER->save_prefs($a_user_prefs)) $OUTPUT->show_message('successfullysaved', 'confirmation'); diff --git a/skins/default/mail.css b/skins/default/mail.css index fb130ce6c..6e44c17d7 100644 --- a/skins/default/mail.css +++ b/skins/default/mail.css @@ -632,16 +632,20 @@ table.headers-table tr td.subject { position:relative; min-height: 300px; - padding-top: 10px; padding-bottom: 10px; background-color: #FFFFFF; } div.message-part { - padding: 8px; - padding-top: 10px; - overflow: hidden; + padding: 10px 8px; + border-top: 1px solid #ccc; +/* overflow: hidden; */ +} + +#messagebody div:first-child +{ + border-top: 0; } div.message-part a |