diff options
author | thomascube <thomas@roundcube.net> | 2005-12-03 16:54:12 +0000 |
---|---|---|
committer | thomascube <thomas@roundcube.net> | 2005-12-03 16:54:12 +0000 |
commit | 1cded85790206afe084e1baff371c543711b2b18 (patch) | |
tree | b050fb89707e048df5f30f500faad792962a1e81 /program | |
parent | 5bc8cb662fc3bcda9aa641b7a5e88c0b81dd63d6 (diff) |
Re-design of caching (new database table added\!); some bugfixes; Postgres support
Diffstat (limited to 'program')
32 files changed, 1703 insertions, 818 deletions
diff --git a/program/include/cache.inc b/program/include/cache.inc index 8d088e57b..06e0681ce 100644 --- a/program/include/cache.inc +++ b/program/include/cache.inc @@ -43,8 +43,8 @@ function rcube_read_cache($key) return $data; } - - + + function rcube_write_cache($key, $data, $session_cache=FALSE) { global $DB, $CACHE_KEYS, $sess_id; @@ -91,7 +91,6 @@ function rcube_write_cache($key, $data, $session_cache=FALSE) } - function rcube_clear_cache($key) { global $DB; diff --git a/program/include/main.inc b/program/include/main.inc index ddb42181a..40ca1d4d7 100644 --- a/program/include/main.inc +++ b/program/include/main.inc @@ -69,7 +69,7 @@ function rcmail_startup($task='mail') // we can use the database for storing session data // session queries do not work with MDB2 - if ($CONFIG['db_backend']!='mdb2' && is_object($DB) && $DB->db_provider!='sqlite') + if ($CONFIG['db_backend']!='mdb2' && is_object($DB) /* && $DB->db_provider!='sqlite' */) include_once('include/session.inc'); @@ -143,9 +143,9 @@ function rcmail_auth_hash($sess_id, $ts) // create IMAP object and connect to server function rcmail_imap_init($connect=FALSE) { - global $CONFIG, $IMAP; + global $CONFIG, $DB, $IMAP; - $IMAP = new rcube_imap(); + $IMAP = new rcube_imap($DB); // connect with stored session data if ($connect) @@ -227,6 +227,22 @@ function get_table_name($table) } +// return correct name for a specific database sequence +// (used for Postres only) +function get_sequence_name($sequence) + { + global $CONFIG; + + // return table name if configured + $config_key = 'db_sequence_'.$sequence; + + if (strlen($CONFIG[$config_key])) + return $CONFIG[$config_key]; + + return $table; + } + + // init output object for GUI and add common scripts function load_gui() @@ -380,15 +396,15 @@ function rcmail_create_user($user, $host) $host, $_SESSION['user_lang']); - if ($user_id = $DB->insert_id('user_ids')) + if ($user_id = $DB->insert_id(get_sequence_name('users'))) { $user_email = strstr($user, '@') ? $user : sprintf('%s@%s', $user, $host); $user_name = $user!=$user_email ? $user : ''; // also create a new identity record $DB->query("INSERT INTO ".get_table_name('identities')." - (user_id, `default`, name, email) - VALUES (?, '1', ?, ?)", + (user_id, del, standard, name, email) + VALUES (?, 0, 1, ?, ?)", $user_id, $user_name, $user_email); @@ -479,7 +495,6 @@ function decrypt_passwd($cypher) function rcube_remote_response($js_code) { send_nocacheing_headers(); - //header('Content-Type: text/javascript'); header('Content-Type: application/x-javascript'); print '/** remote response ['.date('d/M/Y h:i:s O')."] **/\n"; @@ -530,6 +545,117 @@ function rcube_add_label() } +// remove temp files of a session +function rcmail_clear_session_temp($sess_id) + { + global $CONFIG; + + $temp_dir = $CONFIG['temp_dir'].(!eregi('\/$', $CONFIG['temp_dir']) ? '/' : ''); + $cache_dir = $temp_dir.$sess_id; + + if (is_dir($cache_dir)) + { + clear_directory($cache_dir); + rmdir($cache_dir); + } + } + + + +// replace specials characters to a specific encoding type +function rep_specialchars_output($str, $enctype='', $mode='', $newlines=TRUE) + { + global $OUTPUT_TYPE, $CHARSET; + static $html_encode_arr, $js_rep_table, $rtf_rep_table, $xml_rep_table; + + if (!$enctype) + $enctype = $GLOBALS['OUTPUT_TYPE']; + + // convert nbsps back to normal spaces if not html + if ($enctype!='html') + $str = str_replace(chr(160), ' ', $str); + + + // encode for plaintext + if ($enctype=='text') + return str_replace("\r\n", "\n", $mode=='remove' ? strip_tags($str) : $str); + + // encode for HTML output + if ($enctype=='html') + { + if (!$html_encode_arr) + { + if ($CHARSET=='ISO-8859-1') + { + $html_encode_arr = get_html_translation_table(HTML_ENTITIES); + $html_encode_arr[chr(128)] = '€'; + } + else + $html_encode_arr = get_html_translation_table(HTML_SPECIALCHARS); + + unset($html_encode_arr['?']); + unset($html_encode_arr['&']); + } + + $ltpos = strpos($str, '<'); + $encode_arr = $html_encode_arr; + + // don't replace quotes and html tags + if (($mode=='show' || $mode=='') && $ltpos!==false && strpos($str, '>', $ltpos)!==false) + { + unset($encode_arr['"']); + unset($encode_arr['<']); + unset($encode_arr['>']); + } + else if ($mode=='remove') + $str = strip_tags($str); + + $out = strtr($str, $encode_arr); + + return $newlines ? nl2br($out) : $out; + } + + + if ($enctype=='url') + return rawurlencode($str); + + + // if the replace tables for RTF, XML and JS are not yet defined + if (!$js_rep_table) + { + $js_rep_table = $rtf_rep_table = $xml_rep_table = array(); + + for ($c=160; $c<256; $c++) // can be increased to support more charsets + { + $hex = dechex($c); + $rtf_rep_table[Chr($c)] = "\\'$hex"; + $xml_rep_table[Chr($c)] = "&#$c;"; + + if ($CHARSET=='ISO-8859-1') + $js_rep_table[Chr($c)] = sprintf("\u%s%s", str_repeat('0', 4-strlen($hex)), $hex); + } + + $js_rep_table['"'] = sprintf("\u%s%s", str_repeat('0', 4-strlen(dechex(34))), dechex(34)); + $xml_rep_table['"'] = '"'; + } + + // encode for RTF + if ($enctype=='xml') + return strtr($str, $xml_rep_table); + + // encode for javascript use + if ($enctype=='js') + return preg_replace(array("/\r\n/", '/"/', "/([^\\\])'/"), array('\n', '\"', "$1\'"), strtr($str, $js_rep_table)); + + // encode for RTF + if ($enctype=='rtf') + return preg_replace("/\r\n/", "\par ", strtr($str, $rtf_rep_table)); + + // no encoding given -> return original string + return $str; + } + + // ************** template parsing and gui functions ************** @@ -653,104 +779,53 @@ function rcube_xml_command($command, $str_attrib, $a_attrib=NULL) case 'object': $object = strtolower($attrib['name']); + $object_handlers = array( + // MAIL + 'mailboxlist' => 'rcmail_mailbox_list', + 'messages' => 'rcmail_message_list', + 'messagecountdisplay' => 'rcmail_messagecount_display', + 'messageheaders' => 'rcmail_message_headers', + 'messagebody' => 'rcmail_message_body', + 'messageattachments' => 'rcmail_message_attachments', + 'blockedobjects' => 'rcmail_remote_objects_msg', + 'messagecontentframe' => 'rcmail_messagecontent_frame', + 'messagepartframe' => 'rcmail_message_part_frame', + 'messagepartcontrols' => 'rcmail_message_part_controls', + 'composeheaders' => 'rcmail_compose_headers', + 'composesubject' => 'rcmail_compose_subject', + 'composebody' => 'rcmail_compose_body', + 'composeattachmentlist' => 'rcmail_compose_attachment_list', + 'composeattachmentform' => 'rcmail_compose_attachment_form', + 'composeattachment' => 'rcmail_compose_attachment_field', + 'priorityselector' => 'rcmail_priority_selector', + 'charsetselector' => 'rcmail_charset_selector', + + // ADDRESS BOOK + 'addresslist' => 'rcmail_contacts_list', + 'addressframe' => 'rcmail_contact_frame', + 'recordscountdisplay' => 'rcmail_rowcount_display', + 'contactdetails' => 'rcmail_contact_details', + 'contacteditform' => 'rcmail_contact_editform', + + // USER SETTINGS + 'userprefs' => 'rcmail_user_prefs_form', + 'itentitieslist' => 'rcmail_identities_list', + 'identityframe' => 'rcmail_identity_frame', + 'identityform' => 'rcube_identity_form', + 'foldersubscription' => 'rcube_subscription_form', + 'createfolder' => 'rcube_create_folder_form', + 'composebody' => 'rcmail_compose_body' + ); + if ($object=='loginform') return rcmail_login_form($attrib); else if ($object=='message') return rcmail_message_container($attrib); - - // MAIL - else if ($object=='mailboxlist' && function_exists('rcmail_mailbox_list')) - return rcmail_mailbox_list($attrib); - - else if ($object=='messages' && function_exists('rcmail_message_list')) - return rcmail_message_list($attrib); - - else if ($object=='messagecountdisplay' && function_exists('rcmail_messagecount_display')) - return rcmail_messagecount_display($attrib); - - else if ($object=='messageheaders' && function_exists('rcmail_message_headers')) - return rcmail_message_headers($attrib); - - else if ($object=='messageattachments' && function_exists('rcmail_message_attachments')) - return rcmail_message_attachments($attrib); - - else if ($object=='messagebody' && function_exists('rcmail_message_body')) - return rcmail_message_body($attrib); - - else if ($object=='blockedobjects' && function_exists('rcmail_remote_objects_msg')) - return rcmail_remote_objects_msg($attrib); - - else if ($object=='messagecontentframe' && function_exists('rcmail_messagecontent_frame')) - return rcmail_messagecontent_frame($attrib); - - else if ($object=='messagepartframe' && function_exists('rcmail_message_part_frame')) - return rcmail_message_part_frame($attrib); - - else if ($object=='messagepartcontrols' && function_exists('rcmail_message_part_controls')) - return rcmail_message_part_controls($attrib); - - else if ($object=='composeheaders' && function_exists('rcmail_compose_headers')) - return rcmail_compose_headers($attrib); - - else if ($object=='composesubject' && function_exists('rcmail_compose_subject')) - return rcmail_compose_subject($attrib); - - else if ($object=='composebody' && function_exists('rcmail_compose_body')) - return rcmail_compose_body($attrib); - - else if ($object=='composeattachmentlist' && function_exists('rcmail_compose_attachment_list')) - return rcmail_compose_attachment_list($attrib); - - else if ($object=='composeattachmentform' && function_exists('rcmail_compose_attachment_form')) - return rcmail_compose_attachment_form($attrib); - - else if ($object=='composeattachment' && function_exists('rcmail_compose_attachment_field')) - return rcmail_compose_attachment_field($attrib); - - else if ($object=='priorityselector' && function_exists('rcmail_priority_selector')) - return rcmail_priority_selector($attrib); - - else if ($object=='priorityselector' && function_exists('rcmail_priority_selector')) - return rcmail_priority_selector($attrib); - - - // ADDRESS BOOK - else if ($object=='addresslist' && function_exists('rcmail_contacts_list')) - return rcmail_contacts_list($attrib); - - else if ($object=='addressframe' && function_exists('rcmail_contact_frame')) - return rcmail_contact_frame($attrib); - - else if ($object=='recordscountdisplay' && function_exists('rcmail_rowcount_display')) - return rcmail_rowcount_display($attrib); - - else if ($object=='contactdetails' && function_exists('rcmail_contact_details')) - return rcmail_contact_details($attrib); - - else if ($object=='contacteditform' && function_exists('rcmail_contact_editform')) - return rcmail_contact_editform($attrib); - - - // USER SETTINGS - else if ($object=='userprefs' && function_exists('rcmail_user_prefs_form')) - return rcmail_user_prefs_form($attrib); - - else if ($object=='itentitieslist' && function_exists('rcmail_identities_list')) - return rcmail_identities_list($attrib); - - else if ($object=='identityframe' && function_exists('rcmail_identity_frame')) - return rcmail_identity_frame($attrib); - - else if ($object=='identityform' && function_exists('rcube_identity_form')) - return rcube_identity_form($attrib); - - else if ($object=='foldersubscription' && function_exists('rcube_subscription_form')) - return rcube_subscription_form($attrib); - - else if ($object=='createfolder' && function_exists('rcube_create_folder_form')) - return rcube_create_folder_form($attrib); - + + // execute object handler function + else if ($object_handlers[$object] && function_exists($object_handlers[$object])) + return call_user_func($object_handlers[$object], $attrib); else if ($object=='pagetitle') { @@ -878,7 +953,7 @@ function rcube_button($attrib) // generate image tag if ($attrib['type']=='image') { - $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id', 'width', 'height', 'border', 'hspace', 'vspace', 'alt')); + $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id', 'width', 'height', 'border', 'hspace', 'vspace', 'align', 'alt')); $img_tag = sprintf('<img src="%%s"%s />', $attrib_str); $btn_content = sprintf($img_tag, $skin_path.$attrib['image']); if ($attrib['label']) @@ -1161,4 +1236,39 @@ EOF; } + +function rcmail_charset_selector($attrib) + { + // pass the following attributes to the form class + $field_attrib = array('name' => '_charset'); + foreach ($attrib as $attr => $value) + if (in_array($attr, array('id', 'class', 'style', 'size', 'tabindex'))) + $field_attrib[$attr] = $value; + + $charsets = array( + 'US-ASCII' => 'ASCII (English)', + 'X-EUC-JP' => 'EUC-JP (Japanese)', + 'EUC-KR' => 'EUC-KR (Korean)', + 'BIG5' => 'BIG5 (Chinese)', + 'GB2312' => 'GB2312 (Chinese)', + 'ISO-8859-1' => 'ISO-8859-1 (Latin-1)', + 'ISO-8859-2' => 'ISO-8895-2 (Central European)', + 'ISO-8859-7' => 'ISO-8859-7 (Greek)', + 'ISO-8859-9' => 'ISO-8859-9 (Turkish)', + 'Windows-1251' => 'Windows-1251 (Cyrillic)', + 'Windows-1252' => 'Windows-1252 (Western)', + 'Windows-1255' => 'Windows-1255 (Hebrew)', + 'Windows-1256' => 'Windows-1256 (Arabic)', + 'Windows-1257' => 'Windows-1257 (Baltic)', + 'UTF-8' => 'UTF-8' + ); + + $select = new select($field_attrib); + $select->add(array_values($charsets), array_keys($charsets)); + + $set = $_POST['_charset'] ? $_POST['_charset'] : $GLOBALS['CHARSET']; + return $select->show($set); + } + + ?>
\ No newline at end of file diff --git a/program/include/rcube_db.inc b/program/include/rcube_db.inc index f13ab55c0..acb13ce37 100755 --- a/program/include/rcube_db.inc +++ b/program/include/rcube_db.inc @@ -23,299 +23,332 @@ require_once('DB.php'); class rcube_db -{ - var $db_dsnw; // DSN for write operations - var $db_dsnr; // DSN for read operations - var $db_connected=false; // Already connected ? - var $db_mode=''; // Connection mode - var $db_handle=0; // Connection handle - - var $a_query_results = array('dummy'); - var $last_res_id = 0; - - // PHP 5 constructor - function __construct($db_dsnw,$db_dsnr='') + { + var $db_dsnw; // DSN for write operations + var $db_dsnr; // DSN for read operations + var $db_connected = false; // Already connected ? + var $db_mode = ''; // Connection mode + var $db_handle = 0; // Connection handle + + var $a_query_results = array('dummy'); + var $last_res_id = 0; + + + // PHP 5 constructor + function __construct($db_dsnw,$db_dsnr='') { - if ($db_dsnr=='') $db_dsnr=$db_dsnw; + if ($db_dsnr=='') + $db_dsnr=$db_dsnw; - $this->db_dsnw = $db_dsnw; - $this->db_dsnr = $db_dsnr; + $this->db_dsnw = $db_dsnw; + $this->db_dsnr = $db_dsnr; - $dsn_array = DB::parseDSN($db_dsnw); - $this->db_provider = $dsn_array['phptype']; + $dsn_array = DB::parseDSN($db_dsnw); + $this->db_provider = $dsn_array['phptype']; } - // PHP 4 compatibility - function rcube_db($db_dsnw,$db_dsnr='') + + // PHP 4 compatibility + function rcube_db($db_dsnw,$db_dsnr='') { - $this->__construct($db_dsnw,$db_dsnr); + $this->__construct($db_dsnw,$db_dsnr); } - // Connect to specific database - function dsn_connect($dsn) + + // Connect to specific database + function dsn_connect($dsn) { - // Use persistent connections if available - $dbh = DB::connect($dsn, array('persistent' => $true)); + // Use persistent connections if available + $dbh = DB::connect($dsn, array('persistent' => TRUE)); - if (DB::isError($dbh)) - raise_error(array('code' => 500, + if (DB::isError($dbh)) + raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, 'message' => $dbh->getMessage()), TRUE, FALSE); - else if ($this->db_provider=='sqlite') - { - $dsn_array = DB::parseDSN($dsn); - if (!filesize($dsn_array['database']) && !empty($this->sqlite_initials)) - $this->_sqlite_create_database($dbh, $this->sqlite_initials); - } + else if ($this->db_provider=='sqlite') + { + $dsn_array = DB::parseDSN($dsn); + if (!filesize($dsn_array['database']) && !empty($this->sqlite_initials)) + $this->_sqlite_create_database($dbh, $this->sqlite_initials); + } - return $dbh; + return $dbh; } - // Connect to appropiate databse - function db_connect ($mode) - { - $this->db_mode = $mode; - // Already connected - if ($this->db_connected) - { - // no replication, current connection is ok - if ($this->db_dsnw==$this->db_dsnr) return; + // Connect to appropiate databse + function db_connect ($mode) + { + $this->db_mode = $mode; + + // Already connected + if ($this->db_connected) + { + // no replication, current connection is ok + if ($this->db_dsnw==$this->db_dsnr) + return; - // connected to master, current connection is ok - if ($this->db_mode=='w') return; - - // Same mode, current connection is ok - if ($this->db_mode==$mode) return; - } + // connected to master, current connection is ok + if ($this->db_mode=='w') + return; + + // Same mode, current connection is ok + if ($this->db_mode==$mode) + return; + } - if ($mode=='r') - $dsn=$this->db_dsnr; - else - $dsn=$this->db_dsnw; + if ($mode=='r') + $dsn = $this->db_dsnr; + else + $dsn = $this->db_dsnw; - $this->db_handle = $this->dsn_connect($dsn); - $this->db_connected = true; + $this->db_handle = $this->dsn_connect($dsn); + $this->db_connected = true; } - // Query database - - function query() + + // Query database + function query() { - $params = func_get_args(); - $query = array_shift($params); - - return $this->_query($query, 0, 0, $params); + $params = func_get_args(); + $query = array_shift($params); + + return $this->_query($query, 0, 0, $params); } - - function limitquery() + + + // Query with limits + function limitquery() { - $params = func_get_args(); - $query = array_shift($params); - $offset = array_shift($params); - $numrows = array_shift($params); + $params = func_get_args(); + $query = array_shift($params); + $offset = array_shift($params); + $numrows = array_shift($params); - return $this->_query($query, $offset, $numrows, $params); + return $this->_query($query, $offset, $numrows, $params); } - - function _query($query, $offset, $numrows, $params) + + + function _query($query, $offset, $numrows, $params) { - // Read or write ? - if (strtolower(trim(substr($query,0,6)))=='select') - $mode='r'; - else - $mode='w'; + // Read or write ? + if (strtolower(trim(substr($query,0,6)))=='select') + $mode='r'; + else + $mode='w'; - $this->db_connect($mode); + $this->db_connect($mode); - if ($this->db_provider == 'sqlite') - $query = $this->_sqlite_prepare_query($query); - - if ($numrows || $offset) - { - $result = $this->db_handle->limitQuery($query,$offset,$numrows,$params); - } - else - $result = $this->db_handle->query($query, $params); + if ($this->db_provider == 'sqlite') + $this->_sqlite_prepare(); - if (DB::isError($result)) - { - raise_error(array('code' => 500, - 'type' => 'db', - 'line' => __LINE__, - 'file' => __FILE__, - 'message' => $result->getMessage().'; QUERY: '.$query), TRUE, FALSE); - return false; - } - - return $this->_add_result($result, $query); + if ($numrows || $offset) + $result = $this->db_handle->limitQuery($query,$offset,$numrows,$params); + else + $result = $this->db_handle->query($query, $params); + + // add result, even if it's an error + return $this->_add_result($result); } - - function num_rows($res_id=NULL) + + + function num_rows($res_id=NULL) { - if (!$this->db_handle) - return FALSE; + if (!$this->db_handle) + return FALSE; - $result = $this->_get_result($res_id); - - if ($result) - return $result->numRows(); - else - return FALSE; + if ($result = $this->_get_result($res_id)) + return $result->numRows(); + else + return FALSE; } - function affected_rows($res_id=NULL) + + function affected_rows($res_id=NULL) { - if (!$this->db_handle) - return FALSE; - - return $this->db_handle->affectedRows(); + if (!$this->db_handle) + return FALSE; + + return $this->db_handle->affectedRows(); } - function insert_id($sequence = '') + + function insert_id($sequence = '') { - if (!$this->db_handle || $this->db_mode=='r') - return FALSE; - - switch($this->db_provider) - { - case 'pgsql': - // PostgreSQL uses sequences - $result =& $this->db_handle->getOne("SELECT CURRVAL('$sequence')"); - if (DB::isError($result)) { - raise_error( array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, - 'message' => $result->getMessage()), TRUE, TRUE); - } - return $result; + if (!$this->db_handle || $this->db_mode=='r') + return FALSE; + + switch($this->db_provider) + { + case 'pgsql': + // PostgreSQL uses sequences + $result =& $this->db_handle->getOne("SELECT CURRVAL('$sequence')"); + if (DB::isError($result)) + raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, + 'message' => $result->getMessage()), TRUE, FALSE); + + return $result; - case 'mysql': // This is unfortuneate - return mysql_insert_id($this->db_handle->connection); + case 'mysql': // This is unfortuneate + return mysql_insert_id($this->db_handle->connection); - case 'mysqli': - return mysqli_insert_id($this->db_handle->connection); + case 'mysqli': + return mysqli_insert_id($this->db_handle->connection); - case 'sqlite': - return sqlite_last_insert_rowid($this->db_handle->connection); + case 'sqlite': + return sqlite_last_insert_rowid($this->db_handle->connection); - default: - die("portability issue with this database, please have the developer fix"); - } + default: + die("portability issue with this database, please have the developer fix"); + } } - function fetch_assoc($res_id=NULL) + function fetch_assoc($res_id=NULL) { - $result = $this->_get_result($res_id); - - if (DB::isError($result)) - { - raise_error( array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, - 'message' => $this->db_link->getMessage()), TRUE, FALSE); - return FALSE; - } + $result = $this->_get_result($res_id); + + if (DB::isError($result)) + { + raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, + 'message' => $this->db_link->getMessage()), TRUE, FALSE); + return FALSE; + } - return $result->fetchRow(DB_FETCHMODE_ASSOC); + return $result->fetchRow(DB_FETCHMODE_ASSOC); } - function quote($input, $type=null) + function quote($input, $type=null) { - if (!$this->db_handle) - $this->db_connect('r'); + if (!$this->db_handle) + $this->db_connect('r'); - return $this->db_handle->quote($input); + return $this->db_handle->quote($input); } - function quoteIdentifier($str) + function quoteIdentifier($str) { - if (!$this->db_handle) - $this->db_connect('r'); + if (!$this->db_handle) + $this->db_connect('r'); - return $this->db_handle->quoteIdentifier($str); - } - - function quote_identifier($str) - { - return $this->quoteIdentifier($str); + return $this->db_handle->quoteIdentifier($str); } - - function unixtimestamp($field) - { - switch($this->db_provider) - { - case 'pgsql': - return "EXTRACT (EPOCH FROM $field)"; - break; - default: - return "UNIX_TIMESTAMP($field)"; - } - } - - function _add_result($res, $query) + + function quote_identifier($str) + { + return $this->quoteIdentifier($str); + } + + + function unixtimestamp($field) { - // sql error occured - if (DB::isError($res)) - { - raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, 'message' => $res->getMessage() . " Query: " . substr(preg_replace('/[\r\n]+\s*/', ' ', $query), 0, 1024)), TRUE, FALSE); - return FALSE; - } - else - { - $res_id = sizeof($this->a_query_results); - $this->a_query_results[$res_id] = $res; - $this->last_res_id = $res_id; - return $res_id; - } + switch($this->db_provider) + { + case 'pgsql': + return "EXTRACT (EPOCH FROM $field)"; + break; + + default: + return "UNIX_TIMESTAMP($field)"; + } } - function _get_result($res_id) + function fromunixtime($timestamp) { - if ($res_id==NULL) - $res_id = $this->last_res_id; + switch($this->db_provider) + { + case 'mysqli': + case 'mysql': + case 'sqlite': + return "FROM_UNIXTIME($timestamp)"; + + default: + return date("'Y-m-d H:i:s'", $timestamp); + } + } + + + function _add_result($res) + { + // sql error occured + if (DB::isError($res)) + { + raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, + 'message' => $res->getMessage() . " Query: " . substr(preg_replace('/[\r\n]+\s*/', ' ', $res->userinfo), 0, 1024)), TRUE, FALSE); + return FALSE; + } + else + { + $res_id = sizeof($this->a_query_results); + $this->a_query_results[$res_id] = $res; + $this->last_res_id = $res_id; + return $res_id; + } + } + + + function _get_result($res_id) + { + if ($res_id==NULL) + $res_id = $this->last_res_id; - if ($res_id && isset($this->a_query_results[$res_id])) - return $this->a_query_results[$res_id]; - else - return FALSE; + if ($res_id && isset($this->a_query_results[$res_id])) + return $this->a_query_results[$res_id]; + else + return FALSE; } - // create a sqlite database from a file - function _sqlite_create_database($dbh, $fileName) + // create a sqlite database from a file + function _sqlite_create_database($dbh, $fileName) { - if (empty($fileName) || !is_string($fileName)) - return ; - - $data = ''; - if ($fd = fopen($fileName, 'r')) - { - $data = fread($fd, filesize($fileName)); - fclose($fd); - } - - if (strlen($data)) - sqlite_exec($dbh->connection, $data); + if (empty($fileName) || !is_string($fileName)) + return ; + + $data = ''; + if ($fd = fopen($fileName, 'r')) + { + $data = fread($fd, filesize($fileName)); + fclose($fd); + } + + if (strlen($data)) + sqlite_exec($dbh->connection, $data); } - // transform a query so that it is sqlite2 compliant - function _sqlite_prepare_query($query) + function _sqlite_prepare() { - if (!is_string($query)) - return ($query); - - $search = array('/NOW\(\)/i', '/`/'); - $replace = array("datetime('now')", '"'); - $query = preg_replace($search, $replace, $query); + include_once('include/rcube_sqlite.inc'); - return ($query); + // we emulate via callback some missing MySQL function + sqlite_create_function($this->db_handle->connection, "from_unixtime", "rcube_sqlite_from_unixtime"); + sqlite_create_function($this->db_handle->connection, "unix_timestamp", "rcube_sqlite_unix_timestamp"); + sqlite_create_function($this->db_handle->connection, "now", "rcube_sqlite_now"); + sqlite_create_function($this->db_handle->connection, "md5", "rcube_sqlite_md5"); } - -} + +/* + // transform a query so that it is sqlite2 compliant + function _sqlite_prepare_query($query) + { + if (!is_string($query)) + return ($query); + + + $search = array('/NOW\(\)/i', '/`/'); + $replace = array("datetime('now')", '"'); + $query = preg_replace($search, $replace, $query); + + return ($query); + } +*/ + } // end class rcube_db ?>
\ No newline at end of file diff --git a/program/include/rcube_imap.inc b/program/include/rcube_imap.inc index 2237b38f3..ed7c3edcd 100644 --- a/program/include/rcube_imap.inc +++ b/program/include/rcube_imap.inc @@ -28,6 +28,7 @@ require_once('lib/utf7.inc'); class rcube_imap { + var $db; var $conn; var $root_ns = ''; var $root_dir = ''; @@ -38,21 +39,23 @@ class rcube_imap var $caching_enabled = FALSE; var $default_folders = array('inbox', 'drafts', 'sent', 'junk', 'trash'); var $cache = array(); + var $cache_keys = array(); var $cache_changes = array(); var $uid_id_map = array(); var $msg_headers = array(); + var $capabilities = array(); // PHP 5 constructor - function __construct() + function __construct($db_conn) { - + $this->db = $db_conn; } // PHP 4 compatibility - function rcube_imap() + function rcube_imap($db_conn) { - $this->__construct(); + $this->__construct($db_conn); } @@ -95,6 +98,7 @@ class rcube_imap // get account namespace if ($this->conn) { + $this->_parse_capability($this->conn->capability); iil_C_NameSpace($this->conn); if (!empty($this->conn->delimiter)) @@ -185,6 +189,13 @@ class rcube_imap } + function get_capability($cap) + { + $cap = strtoupper($cap); + return $this->capabilities[$cap]; + } + + function get_hierarchy_delimiter() { if ($this->conn && empty($this->delimiter)) @@ -298,200 +309,131 @@ class rcube_imap // private method for listing message header - // by DrSlump <drslump@drslump.biz> - function __list_headers($mailbox='', $page=NULL, $sort_field='date', $sort_order='DESC') + function _list_headers($mailbox='', $page=NULL, $sort_field='date', $sort_order='DESC') { - $a_out = array(); - $cached_count = 0; - if (!strlen($mailbox)) - return $a_out; + return array(); + + $max = $this->_messagecount($mailbox); + $start_msg = ($this->list_page-1) * $this->page_size; + + if ($page=='all') + { + $begin = 0; + $end = $max; + } + else if ($sort_order=='DESC') + { + $begin = $max - $this->page_size - $start_msg; + $end = $max - $start_msg; + } + else + { + $begin = $start_msg; + $end = $start_msg + $this->page_size; + } - $mbox_count = $this->_messagecount($mailbox /*, 'ALL', TRUE*/); + if ($begin < 0) $begin = 0; + if ($end < 0) $end = $max; + if ($end > $max) $end = $max; - $revalidate = false; - if ($mbox_count) +//console("fetch headers $start_msg to ".($start_msg+$this->page_size)." (msg $begin to $end)"); + + $headers_sorted = FALSE; + $cache_key = $mailbox.'.msg'; + $cache_status = $this->check_cache_status($mailbox, $cache_key); + +//console("Cache status = $cache_status"); + + // cache is OK, we can get all messages from local cache + if ($cache_status>0) + { + $a_msg_headers = $this->get_message_cache($cache_key, $start_msg, $start_msg+$this->page_size, $sort_field, $sort_order); + $headers_sorted = TRUE; + } + else { - // get cached headers - $a_out = $this->get_cache($mailbox.'.msg'); - $a_out = is_array($a_out) ? $a_out : array(); // make sure we get an array - - $cached_count = count($a_out); - $a_new = array(); - $revalidate = true; // revalidate by default - - // if the cache count is greater then there have been changes for sure - if ($cached_count <= $mbox_count) + // retrieve headers from IMAP + if ($this->get_capability('sort') && ($msg_index = iil_C_Sort($this->conn, $mailbox, $sort_field))) { - $from = $cached_count?$cached_count:1; - - //get new headers (at least one is returned) - $a_temp = iil_C_FetchHeaders($this->conn, $mailbox, $from . ':' . $mbox_count); - $duplicated = $cached_count?true:false; - - foreach ($a_temp as $hdr) +//console("$mailbox: ".count($msg_index)); + + $msgs = $msg_index[$begin]; + for ($i=$begin; $i < $end; $i++) { - //skip the first one if duplicated - if ($duplicated) - { - //check for changes using the UID - $lastCacheHdr = end($a_out); - if ($hdr->uid === $lastCacheHdr->uid) - $revalidate = false; - - $duplicated = false; - continue; - } - - //skip deleted ones - if (! $hdr->deleted) - $a_new[ $hdr->uid ] = $hdr; + if ($sort_order == 'DESC') + $msgs = $msg_index[$i].','.$msgs; + else + $msgs = $msgs.','.$msg_index[$i]; } - } - //revalidate cache if needed - $to = $mbox_count - count($a_new); - if ($revalidate && $to !== 0) //we'll need to reindex the array so we have to make a copy + $sorted = TRUE; + } + else { - $a_dirty = $a_out; - $a_out = array(); - $a_buffers = array(); + $msgs = sprintf("%d:%d", $begin+1, $end); + $sorted = FALSE; + } - //fetch chunks of 20 headers - $step = 20; - $found = false; - - //fetch headers in blocks starting from new to old - do { - $from = $to-$step; - if ($from < 1) $from = 1; - //store the block in a temporal buffer - $a_buffers[$from] = iil_C_FetchHeaders($this->conn, $mailbox, $from . ':' . $to); + // cache is dirty, sync it + if ($this->caching_enabled && $cache_status==-1) + { + $this->sync_header_index($mailbox); + return $this->_list_headers($mailbox, $page, $sort_field, $sort_order); + } + - //compare the fetched headers with the ones in the cache - $idx = 0; - foreach ($a_buffers[$from] as $k=>$hdr) + // cache is incomplete + $cache_index = $this->get_message_cache_index($cache_key); + + // fetch reuested headers from server + $a_header_index = iil_C_FetchHeaders($this->conn, $mailbox, $msgs); + $a_msg_headers = array(); + + + if (!empty($a_header_index)) + { + foreach ($a_header_index as $i => $headers) + { + if ($headers->deleted) { - //if it's different the comparison ends - if (!isset($a_dirty[$hdr->uid]) || $a_dirty[$hdr->uid]->id !== $hdr->id) - break; + // delete from cache + if ($cache_index[$headers->id] && $cache_index[$headers->id] == $headers->uid) + $this->remove_message_cache($cache_key, $headers->id); - //if we arrive here then we know that the older messages in cache are ok - $found = $hdr->id; - $idx++; + continue; } - //remove from the buffer the headers which are already cached - if ($found) - $a_buffers[$from] = array_splice($a_buffers[$from], 0, $idx ); - - $to = $from-1; - } - while ($found===false && $from > 1); + // add message to cache + if ($this->caching_enabled && $cache_index[$headers->id] != $headers->uid) + $this->add_message_cache($cache_key, $headers->id, $headers); - //just keep the headers we are certain that didn't change in the cache - if ($found !== false) - { - foreach ($a_dirty as $hdr) - { - if ($hdr->id > $found) break; - $a_out[$hdr->uid] = $hdr; - } - } - - //we builded the block buffers from new to older, we process them in reverse order - ksort($a_buffers, SORT_NUMERIC); - foreach ($a_buffers as $a_buff) - { - foreach ($a_buff as $hdr) - { - if (! $hdr->deleted) - $a_out[$hdr->uid] = $hdr; - } + $a_msg_headers[$headers->uid] = $headers; } } - - //array_merge() would reindex the keys, so we use this 'hack' - $a_out += $a_new; - } - - //write headers list to cache if needed - if ($revalidate || count($a_out)!=$cached_count) { - $this->update_cache($mailbox.'.msg', $a_out); - } - - //sort headers by a specific col - $a_out = iil_SortHeaders( $a_out, $sort_field, $sort_order ); - - // return complete list of messages - if (strtolower($page)=='all') - return $a_out; - $start_msg = ($this->list_page-1) * $this->page_size; - return array_slice($a_out, $start_msg, $this->page_size); - } + // delete cached messages with a higher index than $max + $this->clear_message_cache($cache_key, $max); - // original function; replaced 2005/10/18 - // private method for listing message header - function _list_headers($mailbox='', $page=NULL, $sort_field='date', $sort_order='DESC') - { - $max = $this->_messagecount($mailbox); - - if (!strlen($mailbox)) - return array(); - - // get cached headers - $a_msg_headers = $this->get_cache($mailbox.'.msg'); - - // retrieve headers from IMAP - if (!is_array($a_msg_headers) || sizeof($a_msg_headers) != $max) - { - $a_header_index = iil_C_FetchHeaders($this->conn, $mailbox, "1:$max"); - $a_msg_headers = array(); - - if (!empty($a_header_index)) - foreach ($a_header_index as $i => $headers) - if (!$headers->deleted) - $a_msg_headers[$headers->uid] = $headers; - } - else - $headers_cached = TRUE; - - if (!is_array($a_msg_headers)) - return array(); - - // sort headers by a specific col - $a_headers = iil_SortHeaders($a_msg_headers, $sort_field, $sort_order); - $headers_count = count($a_headers); - - // free memory - unset($a_msg_headers); - - // write headers list to cache - if (!$headers_cached) - $this->update_cache($mailbox.'.msg', $a_headers); + // kick child process to sync cache - // update message count cache - $a_mailbox_cache = $this->get_cache('messagecount'); - if (isset($a_mailbox_cache[$mailbox]['ALL']) && $a_mailbox_cache[$mailbox]['ALL'] != $headers_count) - { - $a_mailbox_cache[$mailbox]['ALL'] = (int)$headers_count; - $this->update_cache('messagecount', $a_mailbox_cache); } - if (empty($a_headers)) + + // return empty array if no messages found + if (!is_array($a_msg_headers) || empty($a_msg_headers)) return array(); - - // return complete list of messages - if (strtolower($page)=='all') - return $a_headers; - $start_msg = ($this->list_page-1) * $this->page_size; - return array_slice($a_headers, $start_msg, $this->page_size); + + // if not already sorted + if (!$headers_sorted) + $a_msg_headers = iil_SortHeaders($a_msg_headers, $sort_field, $sort_order); + + return array_values($a_msg_headers); } - + // return sorted array of message UIDs function message_index($mbox='', $sort_field='date', $sort_order='DESC') @@ -510,9 +452,54 @@ class rcube_imap } - function sync_header_index($mbox=NULL) + function sync_header_index($mailbox) { - + $cache_key = $mailbox.'.msg'; + $cache_index = $this->get_message_cache_index($cache_key); + $msg_count = $this->_messagecount($mailbox); + + // fetch complete message index + $a_message_index = iil_C_FetchHeaderIndex($this->conn, $mailbox, "1:$msg_count", 'UID'); + + foreach ($a_message_index as $id => $uid) + { + // message in cache at correct position + if ($cache_index[$id] == $uid) + { +// console("$id / $uid: OK"); + unset($cache_index[$id]); + continue; + } + + // message in cache but in wrong position + if (in_array((string)$uid, $cache_index, TRUE)) + { +// console("$id / $uid: Moved"); + unset($cache_index[$id]); + } + + // other message at this position + if (isset($cache_index[$id])) + { +// console("$id / $uid: Delete"); + $this->remove_message_cache($cache_key, $id); + unset($cache_index[$id]); + } + + +// console("$id / $uid: Add"); + + // fetch complete headers and add to cache + $headers = iil_C_FetchHeader($this->conn, $mailbox, $id); + $this->add_message_cache($cache_key, $headers->id, $headers); + } + + // those ids that are still in cache_index have been deleted + if (!empty($cache_index)) + { + foreach ($cache_index as $id => $uid) + $this->remove_message_cache($cache_key, $id); + } } @@ -527,22 +514,19 @@ class rcube_imap function get_headers($uid, $mbox=NULL) { $mailbox = $mbox ? $this->_mod_mailbox($mbox) : $this->mailbox; - + // get cached headers - $a_msg_headers = $this->get_cache($mailbox.'.msg'); - - // return cached header - if ($a_msg_headers[$uid]) - return $a_msg_headers[$uid]; + if ($headers = $this->get_cached_message($mailbox.'.msg', $uid)) + return $headers; $msg_id = $this->_uid2id($uid); - $header = iil_C_FetchHeader($this->conn, $mailbox, $msg_id); + $headers = iil_C_FetchHeader($this->conn, $mailbox, $msg_id); // write headers cache - $a_msg_headers[$uid] = $header; - $this->update_cache($mailbox.'.msg', $a_msg_headers); + if ($headers) + $this->add_message_cache($mailbox.'.msg', $msg_id, $headers); - return $header; + return $headers; } @@ -595,19 +579,20 @@ class rcube_imap // reload message headers if cached $cache_key = $this->mailbox.'.msg'; - if ($this->caching_enabled && $result && ($a_cached_headers = $this->get_cache($cache_key))) + if ($this->caching_enabled) { - // close and re-open connection - $this->reconnect(); - - foreach ($uids as $uid) + foreach ($msg_ids as $id) { - if (isset($a_cached_headers[$uid])) + if ($cached_headers = $this->get_cached_message($cache_key, $id)) { - unset($this->cache[$cache_key][$uid]); - $this->get_headers($uid); + $this->remove_message_cache($cache_key, $id); + //$this->get_headers($uid); } } + + // close and re-open connection + // this prevents connection problems with Courier + $this->reconnect(); } // set nr of messages that were flaged @@ -633,7 +618,7 @@ class rcube_imap // make shure mailbox exists if (in_array($mailbox, $this->_list_mailboxes())) $saved = iil_C_Append($this->conn, $mailbox, $message); - + if ($saved) { // increase messagecount of the target mailbox @@ -672,20 +657,24 @@ class rcube_imap // really deleted from the source mailbox if ($moved) { - $this->expunge($from_mbox, FALSE); - $this->clear_cache($to_mbox.'.msg'); + $this->_expunge($from_mbox, FALSE); $this->_clear_messagecount($from_mbox); $this->_clear_messagecount($to_mbox); } // update cached message headers $cache_key = $from_mbox.'.msg'; - if ($moved && ($a_cached_headers = $this->get_cache($cache_key))) + if ($moved && ($a_cache_index = $this->get_message_cache_index($cache_key))) { + $start_index = 100000; foreach ($a_uids as $uid) - unset($a_cached_headers[$uid]); + { + $index = array_search($uid, $a_cache_index); + $start_index = min($index, $start_index); + } - $this->update_cache($cache_key, $a_cached_headers); + // clear cache from the lowest index on + $this->clear_message_cache($cache_key, $start_index); } return $moved; @@ -716,17 +705,23 @@ class rcube_imap // really deleted from the mailbox if ($deleted) { - $this->expunge($mailbox, FALSE); + $this->_expunge($mailbox, FALSE); $this->_clear_messagecount($mailbox); } // remove deleted messages from cache - if ($deleted && ($a_cached_headers = $this->get_cache($mailbox.'.msg'))) + $cache_key = $mailbox.'.msg'; + if ($deleted && ($a_cache_index = $this->get_message_cache_index($cache_key))) { + $start_index = 100000; foreach ($a_uids as $uid) - unset($a_cached_headers[$uid]); + { + $index = array_search($uid, $a_cache_index); + $start_index = min($index, $start_index); + } - $this->update_cache($mailbox.'.msg', $a_cached_headers); + // clear cache from the lowest index on + $this->clear_message_cache($cache_key, $start_index); } return $deleted; @@ -740,7 +735,10 @@ class rcube_imap $msg_count = $this->_messagecount($mailbox, 'ALL'); if ($msg_count>0) + { + $this->clear_message_cache($mailbox.'.msg'); return iil_C_ClearFolder($this->conn, $mailbox); + } else return 0; } @@ -750,12 +748,18 @@ class rcube_imap function expunge($mbox='', $clear_cache=TRUE) { $mailbox = $mbox ? $this->_mod_mailbox($mbox) : $this->mailbox; - + return $this->_expunge($mailbox, $clear_cache); + } + + + // send IMAP expunge command and clear cache + function _expunge($mailbox, $clear_cache=TRUE) + { $result = iil_C_Expunge($this->conn, $mailbox); if ($result>=0 && $clear_cache) { - $this->clear_cache($mailbox.'.msg'); + //$this->clear_message_cache($mailbox.'.msg'); $this->_clear_messagecount($mailbox); } @@ -763,7 +767,6 @@ class rcube_imap } - /* -------------------------------- * folder managment * --------------------------------*/ @@ -824,13 +827,18 @@ class rcube_imap function create_mailbox($name, $subscribe=FALSE) { $result = FALSE; + + // replace backslashes + $name = preg_replace('/[\\\]+/', '-', $name); + $name_enc = UTF7EncodeString($name); + + // reduce mailbox name to 100 chars + $name_enc = substr($name_enc, 0, 100); + $abs_name = $this->_mod_mailbox($name_enc); $a_mailbox_cache = $this->get_cache('mailboxes'); - - //if (strlen($this->root_ns)) - // $abs_name = $this->root_ns.$abs_name; - + if (strlen($abs_name) && (!is_array($a_mailbox_cache) || !in_array($abs_name, $a_mailbox_cache))) $result = iil_C_CreateFolder($this->conn, $abs_name); @@ -875,37 +883,41 @@ class rcube_imap // clear mailboxlist cache if ($deleted) + { + $this->clear_message_cache($mailbox.'.msg'); $this->clear_cache('mailboxes'); + } - return $updated; + return $deleted; } /* -------------------------------- - * internal caching functions + * internal caching methods * --------------------------------*/ function set_caching($set) { - if ($set && function_exists('rcube_read_cache')) + if ($set && is_object($this->db)) $this->caching_enabled = TRUE; else $this->caching_enabled = FALSE; } + function get_cache($key) { // read cache if (!isset($this->cache[$key]) && $this->caching_enabled) { - $cache_data = rcube_read_cache('IMAP.'.$key); + $cache_data = $this->_read_cache_record('IMAP.'.$key); $this->cache[$key] = strlen($cache_data) ? unserialize($cache_data) : FALSE; } - return $this->cache[$key]; + return $this->cache[$key]; } @@ -924,7 +936,7 @@ class rcube_imap foreach ($this->cache as $key => $data) { if ($this->cache_changes[$key]) - rcube_write_cache('IMAP.'.$key, serialize($data)); + $this->_write_cache_record('IMAP.'.$key, serialize($data)); } } } @@ -935,7 +947,7 @@ class rcube_imap if ($key===NULL) { foreach ($this->cache as $key => $data) - rcube_clear_cache('IMAP.'.$key); + $this->_clear_cache_record('IMAP.'.$key); $this->cache = array(); $this->cache_changed = FALSE; @@ -943,7 +955,7 @@ class rcube_imap } else { - rcube_clear_cache('IMAP.'.$key); + $this->_clear_cache_record('IMAP.'.$key); $this->cache_changes[$key] = FALSE; unset($this->cache[$key]); } @@ -951,8 +963,276 @@ class rcube_imap + function _read_cache_record($key) + { + $cache_data = FALSE; + + if ($this->db) + { + // get cached data from DB + $sql_result = $this->db->query( + "SELECT cache_id, data + FROM ".get_table_name('cache')." + WHERE user_id=? + AND cache_key=?", + $_SESSION['user_id'], + $key); + + if ($sql_arr = $this->db->fetch_assoc($sql_result)) + { + $cache_data = $sql_arr['data']; + $this->cache_keys[$key] = $sql_arr['cache_id']; + } + } + + return $cache_data; + } + + + function _write_cache_record($key, $data) + { + if (!$this->db) + return FALSE; + + // check if we already have a cache entry for this key + if (!isset($this->cache_keys[$key])) + { + $sql_result = $this->db->query( + "SELECT cache_id + FROM ".get_table_name('cache')." + WHERE user_id=? + AND cache_key=?", + $_SESSION['user_id'], + $key); + + if ($sql_arr = $this->db->fetch_assoc($sql_result)) + $this->cache_keys[$key] = $sql_arr['cache_id']; + else + $this->cache_keys[$key] = FALSE; + } + + // update existing cache record + if ($this->cache_keys[$key]) + { + $this->db->query( + "UPDATE ".get_table_name('cache')." + SET created=now(), + data=? + WHERE user_id=? + AND cache_key=?", + $data, + $_SESSION['user_id'], + $key); + } + // add new cache record + else + { + $this->db->query( + "INSERT INTO ".get_table_name('cache')." + (created, user_id, cache_key, data) + VALUES (now(), ?, ?, ?)", + $_SESSION['user_id'], + $key, + $data); + } + } + + + function _clear_cache_record($key) + { + $this->db->query( + "DELETE FROM ".get_table_name('cache')." + WHERE user_id=? + AND cache_key=?", + $_SESSION['user_id'], + $key); + } + + + + /* -------------------------------- + * message caching methods + * --------------------------------*/ + + + // checks if the cache is up-to-date + // return: -3 = off, -2 = incomplete, -1 = dirty + function check_cache_status($mailbox, $cache_key) + { + if (!$this->caching_enabled) + return -3; + + $cache_index = $this->get_message_cache_index($cache_key, TRUE); + $msg_count = $this->_messagecount($mailbox); + $cache_count = count($cache_index); + + // console("Cache check: $msg_count !== ".count($cache_index)); + + if ($cache_count==$msg_count) + { + // get highest index + $header = iil_C_FetchHeader($this->conn, $mailbox, "$msg_count"); + $cache_uid = array_pop($cache_index); + + // uids of highes message matches -> cache seems OK + if ($cache_uid == $header->uid) + return 1; + + // cache is dirty + return -1; + } + // if cache count differs less that 10% report as dirty + else if (abs($msg_count - $cache_count) < $msg_count/10) + return -1; + else + return -2; + } + + + + function get_message_cache($key, $from, $to, $sort_field, $sort_order) + { + $cache_key = "$key:$from:$to:$sort_field:$sort_order"; + $db_header_fields = array('idx', 'uid', 'subject', 'from', 'to', 'cc', 'date', 'size'); + + if (!in_array($sort_field, $db_header_fields)) + $sort_field = 'idx'; + + if ($this->caching_enabled && !isset($this->cache[$cache_key])) + { + $this->cache[$cache_key] = array(); + $sql_result = $this->db->limitquery( + "SELECT idx, uid, headers + FROM ".get_table_name('messages')." + WHERE user_id=? + AND cache_key=? + ORDER BY ".$this->db->quoteIdentifier($sort_field)." ". + strtoupper($sort_order), + $from, + $to-$from, + $_SESSION['user_id'], + $key); + + while ($sql_arr = $this->db->fetch_assoc($sql_result)) + { + $uid = $sql_arr['uid']; + $this->cache[$cache_key][$uid] = unserialize($sql_arr['headers']); + } + } + + return $this->cache[$cache_key]; + } + + + function get_cached_message($key, $uid, $body=FALSE) + { + if (!$this->caching_enabled) + return FALSE; + + $internal_key = '__single_msg'; + if ($this->caching_enabled && (!isset($this->cache[$internal_key][$uid]) || $body)) + { + $sql_select = "idx, uid, headers"; + if ($body) + $sql_select .= ", body"; + + $sql_result = $this->db->query( + "SELECT $sql_select + FROM ".get_table_name('messages')." + WHERE user_id=? + AND cache_key=? + AND uid=?", + $_SESSION['user_id'], + $key, + $uid); + + if ($sql_arr = $this->db->fetch_assoc($sql_result)) + { + $headers = unserialize($sql_arr['headers']); + if (is_object($headers) && !empty($sql_arr['body'])) + $headers->body = $sql_arr['body']; + + $this->cache[$internal_key][$uid] = $headers; + } + } + + return $this->cache[$internal_key][$uid]; + } + + + function get_message_cache_index($key, $force=FALSE) + { + static $sa_message_index = array(); + + if (!empty($sa_message_index[$key]) && !$force) + return $sa_message_index[$key]; + + $sa_message_index[$key] = array(); + $sql_result = $this->db->query( + "SELECT idx, uid + FROM ".get_table_name('messages')." + WHERE user_id=? + AND cache_key=? + ORDER BY idx ASC", + $_SESSION['user_id'], + $key); + + while ($sql_arr = $this->db->fetch_assoc($sql_result)) + $sa_message_index[$key][$sql_arr['idx']] = $sql_arr['uid']; + + return $sa_message_index[$key]; + } + + + function add_message_cache($key, $index, $headers) + { + $this->db->query( + "INSERT INTO ".get_table_name('messages')." + (user_id, del, cache_key, idx, uid, subject, ".$this->db->quoteIdentifier('from').", ".$this->db->quoteIdentifier('to').", cc, date, size, headers) + VALUES (?, 0, ?, ?, ?, ?, ?, ?, ?, ".$this->db->fromunixtime($headers->timestamp).", ?, ?)", + $_SESSION['user_id'], + $key, + $index, + $headers->uid, + $this->decode_header($headers->subject, TRUE), + $this->decode_header($headers->from, TRUE), + $this->decode_header($headers->to, TRUE), + $this->decode_header($headers->cc, TRUE), + $headers->size, + serialize($headers)); + } + + + function remove_message_cache($key, $index) + { + $this->db->query( + "DELETE FROM ".get_table_name('messages')." + WHERE user_id=? + AND cache_key=? + AND idx=?", + $_SESSION['user_id'], + $key, + $index); + } + + + function clear_message_cache($key, $start_index=1) + { + $this->db->query( + "DELETE FROM ".get_table_name('messages')." + WHERE user_id=? + AND cache_key=? + AND idx>=?", + $_SESSION['user_id'], + $key, + $start_index); + } + + + + /* -------------------------------- - * encoding/decoding functions + * encoding/decoding methods * --------------------------------*/ @@ -986,9 +1266,15 @@ class rcube_imap } - function decode_header($input) + function decode_header($input, $remove_quotes=FALSE) { - return $this->decode_mime_string($input); + $str = $this->decode_mime_string($input); + if ($str{0}=='"' && $remove_quotes) + { + $str = str_replace('"', '', $str); + } + + return $str; } @@ -1094,6 +1380,7 @@ class rcube_imap } + /* -------------------------------- * private methods * --------------------------------*/ @@ -1149,6 +1436,33 @@ class rcube_imap } + // parse string or array of server capabilities and put them in internal array + function _parse_capability($caps) + { + if (!is_array($caps)) + $cap_arr = explode(' ', $caps); + else + $cap_arr = $caps; + + foreach ($cap_arr as $cap) + { + if ($cap=='CAPABILITY') + continue; + + if (strpos($cap, '=')>0) + { + list($key, $value) = explode('=', $cap); + if (!is_array($this->capabilities[$key])) + $this->capabilities[$key] = array(); + + $this->capabilities[$key][] = $value; + } + else + $this->capabilities[$cap] = TRUE; + } + } + + // subscribe/unsubscribe a list of mailboxes and update local cache function _change_subscription($a_mboxes, $mode) { diff --git a/program/include/rcube_mdb2.inc b/program/include/rcube_mdb2.inc index 35973ad5d..54a40e796 100755 --- a/program/include/rcube_mdb2.inc +++ b/program/include/rcube_mdb2.inc @@ -238,6 +238,22 @@ class rcube_db } + function format_date($timestamp) + { + switch($this->db_provider) + { + case 'mysqli': + case 'mysql': + return "FROM_UNIXTIME($timestamp)"; + break; + case 'sqlite': + return "datetime('$timestamp')"; + break; + default: + return date("Y-m-d H:i:s", $timestamp); + } + } + function _add_result($res, $query) { // sql error occured diff --git a/program/include/rcube_shared.inc b/program/include/rcube_shared.inc index 400e345c0..75db7603f 100644 --- a/program/include/rcube_shared.inc +++ b/program/include/rcube_shared.inc @@ -1185,99 +1185,6 @@ function send_future_expire_header() } -// replace specials characters to a specific encoding type -function rep_specialchars_output($str, $enctype='', $mode='', $newlines=TRUE) - { - global $OUTPUT_TYPE, $CHARSET; - static $html_encode_arr, $js_rep_table, $rtf_rep_table, $xml_rep_table; - - if (!$enctype) - $enctype = $GLOBALS['OUTPUT_TYPE']; - - // convert nbsps back to normal spaces if not html - if ($enctype!='html') - $str = str_replace(chr(160), ' ', $str); - - - // encode for plaintext - if ($enctype=='text') - return str_replace("\r\n", "\n", $mode=='remove' ? strip_tags($str) : $str); - - // encode for HTML output - if ($enctype=='html') - { - if (!$html_encode_arr) - { - if ($CHARSET=='ISO-8859-1') - { - $html_encode_arr = get_html_translation_table(HTML_ENTITIES); - $html_encode_arr[chr(128)] = '€'; - } - else - $html_encode_arr = get_html_translation_table(HTML_SPECIALCHARS); - - unset($html_encode_arr['?']); - unset($html_encode_arr['&']); - } - - $ltpos = strpos($str, '<'); - $encode_arr = $html_encode_arr; - - // don't replace quotes and html tags - if (($mode=='show' || $mode=='') && $ltpos!==false && strpos($str, '>', $ltpos)!==false) - { - unset($encode_arr['"']); - unset($encode_arr['<']); - unset($encode_arr['>']); - } - else if ($mode=='remove') - $str = strip_tags($str); - - $out = strtr($str, $encode_arr); - - return $newlines ? nl2br($out) : $out; - } - - - if ($enctype=='url') - return rawurlencode($str); - - - // if the replace tables for RTF, XML and JS are not yet defined - if (!$js_rep_table) - { - $js_rep_table = $rtf_rep_table = $xml_rep_table = array(); - - for ($c=160; $c<256; $c++) // can be increased to support more charsets - { - $hex = dechex($c); - $rtf_rep_table[Chr($c)] = "\\'$hex"; - $xml_rep_table[Chr($c)] = "&#$c;"; - - if ($CHARSET=='ISO-8859-1') - $js_rep_table[Chr($c)] = sprintf("\u%s%s", str_repeat('0', 4-strlen($hex)), $hex); - } - - $js_rep_table['"'] = sprintf("\u%s%s", str_repeat('0', 4-strlen(dechex(34))), dechex(34)); - $xml_rep_table['"'] = '"'; - } - - // encode for RTF - if ($enctype=='xml') - return strtr($str, $xml_rep_table); - - // encode for javascript use - if ($enctype=='js') - return preg_replace(array("/\r\n/", '/"/', "/([^\\\])'/"), array('\n', '\"', "$1\'"), strtr($str, $js_rep_table)); - - // encode for RTF - if ($enctype=='rtf') - return preg_replace("/\r\n/", "\par ", strtr($str, $rtf_rep_table)); - - // no encoding given -> return original string - return $str; - } - function decode_specialchars($input, $charset='') { @@ -1462,7 +1369,21 @@ function abbrevate_string($str, $maxlength, $place_holder='...') return $str; } - + + +// delete all files within a folder +function clear_directory($dir_path) + { + $dir = @opendir($dir_path); + if(!$dir) return FALSE; + + while ($file = readdir($dir)) + if (strlen($file)>2) + unlink("$dir_path/$file"); + + closedir($dir); + return TRUE; + } ?>
\ No newline at end of file diff --git a/program/include/rcube_sqlite.inc b/program/include/rcube_sqlite.inc new file mode 100644 index 000000000..78c671d38 --- /dev/null +++ b/program/include/rcube_sqlite.inc @@ -0,0 +1,71 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | program/include/rcube_sqlite.inc | + | | + | This file is part of the RoundCube Webmail client | + | Copyright (C) 2005, RoundCube Dev. - Switzerland | + | Licensed under the GNU GPL | + | | + | PURPOSE: | + | Provide callback functions for sqlite that will emulate | + | sone MySQL functions | + | | + +-----------------------------------------------------------------------+ + | Author: Thomas Bruederli <roundcube@gmail.com> | + +-----------------------------------------------------------------------+ + + $Id$ + +*/ + + +function rcube_sqlite_from_unixtime($timestamp) + { + $timestamp = trim($timestamp); + if (!preg_match("/^[0-9]+$/is", $timestamp)) + $ret = strtotime($timestamp); + else + $ret = $timestamp; + + $ret = date("Y-m-d H:i:s", $ret); + rcube_sqlite_debug("FROM_UNIXTIME ($timestamp) = $ret"); + return $ret; + } + + +function rcube_sqlite_unix_timestamp($timestamp="") + { + $timestamp = trim($timestamp); + if (!$timestamp) + $ret = time(); + else if (!preg_match("/^[0-9]+$/is", $timestamp)) + $ret = strtotime($timestamp); + else + $ret = $timestamp; + + rcube_sqlite_debug("UNIX_TIMESTAMP ($timestamp) = $ret"); + return $ret; + } + + +function rcube_sqlite_now() + { + rcube_sqlite_debug("NOW() = ".date("Y-m-d H:i:s")); + return date("Y-m-d H:i:s"); + } + + +function rcube_sqlite_md5($str) + { + return md5($str); + } + + +function rcube_sqlite_debug($str) + { + //console($str); + } + +?>
\ No newline at end of file diff --git a/program/include/session.inc b/program/include/session.inc index 54ed798fc..f10a2b37e 100644 --- a/program/include/session.inc +++ b/program/include/session.inc @@ -45,7 +45,7 @@ function sess_read($key) if ($sql_arr = $DB->fetch_assoc($sql_result)) { - $SESS_CHANGED = $sql_arr['changed']; + $SESS_CHANGED = mktime(); //$sql_arr['changed']; if (strlen($sql_arr['vars'])) return $sql_arr['vars']; @@ -59,7 +59,7 @@ function sess_read($key) function sess_write($key, $vars) { global $DB; - + $sql_result = $DB->query("SELECT 1 FROM ".get_table_name('session')." WHERE sess_id=?", @@ -83,6 +83,8 @@ function sess_write($key, $vars) $key, $vars, $_SERVER['REMOTE_ADDR']); + + } return TRUE; @@ -102,7 +104,9 @@ function sess_destroy($key) $DB->query("DELETE FROM ".get_table_name('session')." WHERE sess_id=?", $key); - + + rcmail_clear_session_temp($key); + return TRUE; } @@ -115,7 +119,7 @@ function sess_gc($maxlifetime) // get all expired sessions $sql_result = $DB->query("SELECT sess_id FROM ".get_table_name('session')." - WHERE ".$DB->unixtimestamp('now()')."-".$DB->unixtimestamp('created')." > ?", + WHERE ".$DB->unixtimestamp('now()')."-".$DB->unixtimestamp('changed')." > ?", $maxlifetime); $a_exp_sessions = array(); @@ -134,6 +138,10 @@ function sess_gc($maxlifetime) WHERE sess_id IN ('".join("','", $a_exp_sessions)."')"); } + // remove session specific temp dirs + foreach ($a_exp_sessions as $key) + rcmail_clear_session_temp($key); + return TRUE; } diff --git a/program/js/app.js b/program/js/app.js index 095c89d3a..d65af420e 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -210,7 +210,7 @@ function rcube_webmail() this.enable_command('logout', true); // disable browser's contextmenus - //document.oncontextmenu = function(){ return false; } + // document.oncontextmenu = function(){ return false; } // flag object as complete this.loaded = true; @@ -286,6 +286,7 @@ function rcube_webmail() return false; //this.messageform = this.gui_objects.messageform; + var input_from = rcube_find_object('_from'); var input_to = rcube_find_object('_to'); var input_cc = rcube_find_object('_cc'); var input_bcc = rcube_find_object('_bcc'); @@ -300,6 +301,10 @@ function rcube_webmail() this.init_address_input_events(input_cc); if (input_bcc) this.init_address_input_events(input_bcc); + + // add signature according to selected identity + if (input_from && input_from.type=='select-one') + this.change_identity(input_from); if (input_to && input_to.value=='') input_to.focus(); @@ -461,9 +466,18 @@ function rcube_webmail() // get the type of sorting var a_sort = props.split('_'); var sort_col = a_sort[0]; - var sort_order = a_sort[1].toUpperCase(); + var sort_order = a_sort[1] ? a_sort[1].toUpperCase() : null; var header; + // no sort order specified: toggle + if (sort_order==null) + { + if (this.env.sort_col==sort_col) + sort_order = this.env.sort_order=='ASC' ? 'DESC' : 'ASC'; + else + sort_order = this.env.sort_order; + } + if (this.env.sort_col==sort_col && this.env.sort_order==sort_order) break; @@ -478,7 +492,7 @@ function rcube_webmail() this.env.sort_order = sort_order; // reload message list - this.list_mailbox('', '', props); + this.list_mailbox('', '', sort_col+'_'+sort_order); break; case 'nextpage': @@ -805,7 +819,7 @@ function rcube_webmail() break; case 'delete-folder': - if (confirm('Do you really want to delete this folder?')) + if (confirm(this.get_label('deletefolderconfirm'))) this.delete_folder(props); break; @@ -933,8 +947,8 @@ function rcube_webmail() if (!this.in_selection_before) { - var shift = this.check_shiftkey(e); - this.select(id, shift); + var ctrl = this.check_ctrlkey(e); + this.select(id, ctrl); } if (this.selection.length) @@ -951,7 +965,7 @@ function rcube_webmail() // onmouseup-handler of message list row this.click_row = function(e, id) { - var shift = this.check_shiftkey(e); + var ctrl = this.check_ctrlkey(e); // don't do anything (another action processed before) if (this.dont_select) @@ -961,13 +975,13 @@ function rcube_webmail() } if (!this.drag_active && this.in_selection_before==id) - this.select(id, (shift && this.task!='settings')); + this.select(id, (ctrl && this.task!='settings')); this.drag_start = false; this.in_selection_before = false; // row was double clicked - if (this.task=='mail' && this.list_rows && this.list_rows[id].clicked && !shift) + if (this.task=='mail' && this.list_rows && this.list_rows[id].clicked && !ctrl) { this.show_message(id); return false; @@ -1332,6 +1346,38 @@ function rcube_webmail() /*********************************************************/ /********* message compose methods *********/ /*********************************************************/ + + + this.change_identity = function(obj) + { + if (!obj || !obj.options) + return false; + + var id = obj.options[obj.selectedIndex].value; + var input_message = rcube_find_object('_message'); + var message = input_message ? input_message.value : ''; + + // remove the 'old' signature + if (this.env.identity && this.env.signatures && this.env.signatures[this.env.identity]) + { + var sig = this.env.signatures[this.env.identity]; + + if (p = message.lastIndexOf(sig)) + message = message.substring(0, p-1) + message.substring(p+sig.length, message.length); + } + + // add the new signature string + if (this.env.signatures && this.env.signatures[id]) + { + var sig = this.env.signatures[id]; + message += '\n'+sig; + } + + if (input_message && message) + input_message.value = message; + + this.env.identity = id; + }; this.show_attachment_form = function(a) @@ -1854,19 +1900,23 @@ function rcube_webmail() { if (folder) { - for (var id in this.env.subscriptionrows) - if (this.env.subscriptionrows[id]==folder) - break; - - var row; - if (id && (row = document.getElementById(id))) - row.style.display = 'none'; - this.http_request('delete-folder', '_mboxes='+escape(folder)); } }; + this.remove_folder_row = function(folder) + { + for (var id in this.env.subscriptionrows) + if (this.env.subscriptionrows[id]==folder) + break; + + var row; + if (id && (row = document.getElementById(id))) + row.style.display = 'none'; + }; + + this.subscribe_folder = function(folder) { var form; @@ -2491,6 +2541,21 @@ function rcube_webmail() return false; } + // check if Shift-key is pressed on event + this.check_ctrlkey = function(e) + { + if(!e && window.event) + e = window.event; + + if(bw.linux && bw.ns4 && e.modifiers) + return true; + else if (bw.mac) + return this.check_shiftkey(e); + else if((bw.ns4 && e.modifiers & Event.CTRL_MASK) || (e && e.ctrlKey)) + return true; + else + return false; + } this.get_mouse_pos = function(e) { diff --git a/program/localization/de/labels.inc b/program/localization/de/labels.inc index 4bbb14c95..12ec06e8c 100644 --- a/program/localization/de/labels.inc +++ b/program/localization/de/labels.inc @@ -109,6 +109,7 @@ $labels['unread'] = 'Ungelesene'; $labels['compose'] = 'Neue Nachricht verfassen'; $labels['sendmessage'] = 'Nachricht jetzt senden'; $labels['addattachment'] = 'Datei anfügen'; +$labels['charset'] = 'Zeichensatz'; $labels['attachments'] = 'Anhänge'; $labels['upload'] = 'Hochladen'; @@ -121,7 +122,6 @@ $labels['high'] = 'Hoch'; $labels['highest'] = 'Höchste'; $labels['nosubject'] = '(kein Betreff)'; - $labels['showimages'] = 'Bilder anzeigen'; @@ -165,7 +165,7 @@ $labels['setdefault'] = 'Als Standard'; $labels['language'] = 'Sprache'; $labels['timezone'] = 'Zeitzone'; $labels['pagesize'] = 'Einträge pro Seite'; - +$labels['signature'] = 'Signatur'; $labels['folders'] = 'Ordner'; $labels['foldername'] = 'Ordnername'; diff --git a/program/localization/de/messages.inc b/program/localization/de/messages.inc index e8eabe10a..145c7b4a7 100644 --- a/program/localization/de/messages.inc +++ b/program/localization/de/messages.inc @@ -54,6 +54,8 @@ $messages['sendingfailed'] = 'Versand der Nachricht fehlgeschlagen'; $messages['errorsaving'] = 'Beim Speichern ist ein Fehler aufgetreten'; +$messages['deletefolderconfirm'] = 'Wollen Sie diesen Ordner wirklich löschen?'; + $messages['formincomplete'] = 'Das Formular wurde nicht vollständig ausgefüllt'; $messages['noemailwarning'] = 'Bitte geben Sie eine gültige E-Mail-Adresse ein'; diff --git a/program/localization/ee/labels.inc b/program/localization/ee/labels.inc new file mode 100644 index 000000000..76050726f --- /dev/null +++ b/program/localization/ee/labels.inc @@ -0,0 +1,182 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | language/ee/labels.inc | + | | + | Language file of the RoundCube Webmail client | + | Copyright (C) 2005, RoundQube Dev. - Switzerland | + | Licensed under the GNU GPL | + | | + +-----------------------------------------------------------------------+ + | Author: Üllar Pajus <yllar.pajus@gmail.com> | + +-----------------------------------------------------------------------+ + + $Id$ + +*/ + +$labels = array(); + +// login page +$labels['username'] = 'Kasutajanimi'; +$labels['password'] = 'Parool'; +$labels['server'] = 'Server'; +$labels['login'] = 'Logi sisse'; + +// taskbar +$labels['logout'] = 'Logi välja'; +$labels['mail'] = 'Postkast'; +$labels['settings'] = 'Seaded'; +$labels['addressbook'] = 'Aadressiraamat'; + +// mailbox names +$labels['inbox'] = 'Sissetulevad'; +$labels['sent'] = 'Saadetud'; +$labels['trash'] = 'Prügikast'; +$labels['drafts'] = 'Ootel'; +$labels['junk'] = 'Rämps'; + +// message listing +$labels['subject'] = 'Pealkiri'; +$labels['from'] = 'Saatja'; +$labels['to'] = 'Saaja'; +$labels['cc'] = 'Koopia'; +$labels['bcc'] = 'Bcc'; +$labels['replyto'] = 'Vastus aadressile'; +$labels['date'] = 'Kuupäev'; +$labels['size'] = 'Suurus'; +$labels['priority'] = 'Tähtsus'; +$labels['organization'] = 'Organisatsioon'; + +// aliases +$labels['reply-to'] = $labels['replyto']; + +$labels['mailboxlist'] = 'Kaustad'; +$labels['messagesfromto'] = 'Kirjed $from kuni $to, kokku $count'; +$labels['messagenrof'] = 'Kiri $nr, kokku $count'; + +$labels['moveto'] = 'liiguta kausta...'; +$labels['download'] = 'lae arvutisse'; + +$labels['filename'] = 'Faili nimi'; +$labels['filesize'] = 'Faili suurus'; + +$labels['preferhtml'] = 'Eelista HTMLi'; +$labels['htmlmessage'] = 'HTML kirjad'; +$labels['prettydate'] = 'Kenad kuupäevad'; + +$labels['addtoaddressbook'] = 'Lisa aadressiraamatusse'; + +// weekdays short +$labels['sun'] = 'P'; +$labels['mon'] = 'E'; +$labels['tue'] = 'T'; +$labels['wed'] = 'K'; +$labels['thu'] = 'N'; +$labels['fri'] = 'R'; +$labels['sat'] = 'L'; + +// weekdays long +$labels['sunday'] = 'Pühapäev'; +$labels['monday'] = 'Esmaspäev'; +$labels['tuesday'] = 'Teisipäev'; +$labels['wednesday'] = 'Kolmapäev'; +$labels['thursday'] = 'Neljapäev'; +$labels['friday'] = 'Reede'; +$labels['saturday'] = 'Laupäev'; + +$labels['today'] = 'Täna'; + +// toolbar buttons +$labels['writenewmessage'] = 'Kirjuta uus kiri'; +$labels['replytomessage'] = 'Vasta kirjale'; +$labels['replytoallmessage'] = 'Vasta saatjale ja teistele kirja saanutele'; +$labels['forwardmessage'] = 'Edasta see kiri'; +$labels['deletemessage'] = 'Liiguta kiri prügikasti'; +$labels['printmessage'] = 'Trüki kiri'; +$labels['previousmessages'] = 'Näita eelmisi kirju'; +$labels['nextmessages'] = 'Näita järgmisi kirju'; +$labels['backtolist'] = 'Tagasi kirjade nimekirja'; +$labels['viewsource'] = 'Näita lähtekoodi'; + +$labels['select'] = 'Vali'; +$labels['all'] = 'kõik'; +$labels['none'] = 'mitte midagi'; +$labels['unread'] = 'mitte loetud'; + +// message compose +$labels['compose'] = 'Koosta kiri'; +$labels['sendmessage'] = 'Saada kiri kohe'; +$labels['addattachment'] = 'Lisa fail'; + +$labels['attachments'] = 'Manused'; +$labels['upload'] = 'Kinnita manus'; +$labels['close'] = 'Sulge'; + +$labels['low'] = 'Madal'; +$labels['lowest'] = 'Madalaim'; +$labels['normal'] = 'Tavaline'; +$labels['high'] = 'Kõrge'; +$labels['highest'] = 'Kõrgeim'; + +$labels['nosubject'] = '(teema puudub)'; + +$labels['showimages'] = 'Näita pilte'; + + +// address boook +$labels['name'] = 'Näidatav nimi'; +$labels['firstname'] = 'Eesnimi'; +$labels['surname'] = 'Perekonnanimi'; +$labels['email'] = 'E-Mail'; + +$labels['addcontact'] = 'Lisa uus kontakt'; +$labels['editcontact'] = 'Muuda kontakti'; + +$labels['edit'] = 'Muuda'; +$labels['cancel'] = 'Katkesta'; +$labels['save'] = 'Salvesta'; +$labels['delete'] = 'Kustuta'; + +$labels['newcontact'] = 'Loo uus sissekanne'; +$labels['deletecontact'] = 'Kustuta märgistatud kontaktid'; +$labels['composeto'] = 'Kirjuta kiri'; +$labels['contactsfromto'] = 'Kirjed $from kuni $to, kokku $count'; +$labels['print'] = 'Trüki'; +$labels['export'] = 'Ekspordi'; + + +// settings +$labels['settingsfor'] = 'Kasutajaeelistused kontole'; + +$labels['preferences'] = 'Eelistused'; +$labels['userpreferences'] = 'Kasutaja eelistused'; +$labels['editpreferences'] = 'Muuda kasutaja eelistusi'; + +$labels['identities'] = 'Identiteedid'; +$labels['manageidentities'] = 'Halda selle konto identiteete'; +$labels['newidentity'] = 'Uus identiteet'; + +$labels['newitem'] = 'Uus sissekanne'; +$labels['edititem'] = 'Muuda sissekannet'; + +$labels['setdefault'] = 'Muuda vaikeseadeks'; +$labels['language'] = 'Keel'; +$labels['timezone'] = 'Ajatsoon'; +$labels['pagesize'] = 'Ridu lehe kohta'; + + +$labels['folders'] = 'Kaustad'; +$labels['foldername'] = 'Kausta nimi'; +$labels['subscribed'] = 'Näitan'; +$labels['create'] = 'Loo'; +$labels['createfolder'] = 'Loo uus kaust'; +$labels['deletefolder'] = 'Kustuta kaust'; +$labels['managefolders'] = 'Manage folders'; + +$labels['sortby'] = 'Järjesta'; +$labels['sortasc'] = 'Järjesta kasvavalt'; +$labels['sortdesc'] = 'Järjesta kahanevalt'; + +?> diff --git a/program/localization/ee/messages.inc b/program/localization/ee/messages.inc new file mode 100644 index 000000000..6aeff2834 --- /dev/null +++ b/program/localization/ee/messages.inc @@ -0,0 +1,80 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | language/ee/messages.inc | + | | + | Language file of the RoundCube Webmail client | + | Copyright (C) 2005, RoundCube Dev. - Switzerland | + | Licensed under the GNU GPL | + | | + +-----------------------------------------------------------------------+ + | Author: Üllar Pajus <yllar.pajus@gmail.com> | + +-----------------------------------------------------------------------+ + + $Id$ + +*/ + +$messages = array(); + +$messages['loginfailed'] = 'Sisselogimine ebaõnnestus'; + +$messages['cookiesdisabled'] = 'Sinu veebilehitseja ei võta präänikuid vastu'; + +$messages['sessionerror'] = 'Sinu sessioon on aegunud või vigane'; + +$messages['imaperror'] = 'Ei õnnestunud IMAP serveriga ühendust luua'; + +$messages['nomessagesfound'] = 'Postkast paistab tühi olevat'; + +$messages['loggedout'] = 'Sinu sessioon on edukalt lõpetatud. Nägemiseni!'; + +$messages['mailboxempty'] = 'Postkast on tühi'; + +$messages['loading'] = 'Laen...'; + +$messages['loadingdata'] = 'Laen andmeid...'; + +$messages['sendingmessage'] = 'Saadan kirja...'; + +$messages['messagesent'] = 'Kiri edukalt saadetud'; + +$messages['successfullysaved'] = 'Edukalt salvestatud'; + +$messages['addedsuccessfully'] = 'Kontakt lisati edukalt aadressiraamatusse'; + +$messages['contactexists'] = 'Sama e-maili aadressiga kontakt on juba olemas'; + +$messages['blockedimages'] = 'Sinu privaatsuse kaitsmiseks on selles kirjas välised pildid blokeeritud.'; + +$messages['encryptedmessage'] = 'See on krüpteeritud kiri ja kahjuks pole seda võimalik näidata. Andestust!'; + +$messages['nocontactsfound'] = 'Ei leidnud ühtegi kontakti'; + +$messages['sendingfailed'] = 'Kirja saatmine ebaõnnestus'; + +$messages['errorsaving'] = 'Salvestamie ajal ilmnes viga'; + +$messages['errormoving'] = 'Ei suutnud seda kirja liigutada'; + +$messages['errordeleting'] = 'Ei suutnud seda kirja kustutada'; + +$messages['errordeleting'] = 'Ei suutnud seda kirja kustutada'; + +$messages['formincomplete'] = 'Vormi kõik väljad ei ole täidetud'; + +$messages['noemailwarning'] = 'Palun sisesta toimiv e-maili aadress'; + +$messages['nonamewarning'] = 'Palun sisesta nimi'; + +$messages['nopagesizewarning'] = 'Palun sisesta lehekülje suurus'; + +$messages['norecipientwarning'] = 'Palun sisesta vähemalt üks kirjasaaja'; + +$messages['nosubjectwarning'] = 'Väli "Pealkiri" on tühi. Soovid selle ära täita ?'; + +$messages['nobodywarning'] = 'Saadan selle kirja ilma tekstita ?'; + + +?> diff --git a/program/localization/en/labels.inc b/program/localization/en/labels.inc index 35813cdb0..b37b48140 100644 --- a/program/localization/en/labels.inc +++ b/program/localization/en/labels.inc @@ -109,6 +109,7 @@ $labels['unread'] = 'Unread'; $labels['compose'] = 'Compose a message'; $labels['sendmessage'] = 'Send the message now'; $labels['addattachment'] = 'Attach a file'; +$labels['charset'] = 'Charset'; $labels['attachments'] = 'Attachments'; $labels['upload'] = 'Upload'; @@ -121,7 +122,6 @@ $labels['high'] = 'High'; $labels['highest'] = 'Highest'; $labels['nosubject'] = '(no subject)'; - $labels['showimages'] = 'Display images'; @@ -165,7 +165,7 @@ $labels['setdefault'] = 'Set default'; $labels['language'] = 'Language'; $labels['timezone'] = 'Time zone'; $labels['pagesize'] = 'Rows per page'; - +$labels['signature'] = 'Signature'; $labels['folders'] = 'Folders'; $labels['foldername'] = 'Folder name'; diff --git a/program/localization/en/messages.inc b/program/localization/en/messages.inc index 1ce6bba6d..d0286e229 100644 --- a/program/localization/en/messages.inc +++ b/program/localization/en/messages.inc @@ -60,13 +60,13 @@ $messages['errormoving'] = 'Could not move the message'; $messages['errordeleting'] = 'Could not delete the message'; -$messages['errordeleting'] = 'Could not delete the message'; +$messages['deletefolderconfirm'] = 'Do you really want to delete this folder?'; -$messages['formincomplete'] = 'The form was not completely filled out'; +$messages['formincomplete'] = 'The form was not completely filled out'; -$messages['noemailwarning'] = 'Please enter a valid email address'; +$messages['noemailwarning'] = 'Please enter a valid email address'; -$messages['nonamewarning'] = 'Please enter a name'; +$messages['nonamewarning'] = 'Please enter a name'; $messages['nopagesizewarning'] = 'Please enter a page size'; diff --git a/program/localization/en_GB/labels.inc b/program/localization/en_GB/labels.inc index d1a274971..cd9b5032d 100644 --- a/program/localization/en_GB/labels.inc +++ b/program/localization/en_GB/labels.inc @@ -120,6 +120,7 @@ $labels['normal'] = 'Normal'; $labels['high'] = 'High'; $labels['highest'] = 'Highest'; +$labels['nosubject'] = '(no subject)'; $labels['showimages'] = 'Display images'; @@ -163,7 +164,7 @@ $labels['setdefault'] = 'Set default'; $labels['language'] = 'Language'; $labels['timezone'] = 'Time zone'; $labels['pagesize'] = 'Rows per page'; - +$labels['signature'] = 'Signature'; $labels['folders'] = 'Folders'; $labels['foldername'] = 'Folder name'; diff --git a/program/localization/index.inc b/program/localization/index.inc index 3386ebd68..82424e602 100644 --- a/program/localization/index.inc +++ b/program/localization/index.inc @@ -32,6 +32,7 @@ 'da' => 'Dansk', 'de' => 'Deutsch', 'es' => 'Español', + 'ee' => 'Estonian', 'fr' => 'Français', 'ga' => 'Galician', 'el' => 'Greek', diff --git a/program/steps/addressbook/delete.inc b/program/steps/addressbook/delete.inc index a3fcefbf7..b95988d12 100644 --- a/program/steps/addressbook/delete.inc +++ b/program/steps/addressbook/delete.inc @@ -24,7 +24,7 @@ $REMOTE_REQUEST = TRUE; if ($_GET['_cid']) { $DB->query("UPDATE ".get_table_name('contacts')." - SET del='1' + SET del=1 WHERE user_id=? AND contact_id IN (".$_GET['_cid'].")", $_SESSION['user_id']); @@ -40,7 +40,7 @@ if ($_GET['_cid']) // count contacts for this user $sql_result = $DB->query("SELECT COUNT(contact_id) AS rows FROM ".get_table_name('contacts')." - WHERE del<>'1' + WHERE del<>1 AND user_id=?", $_SESSION['user_id']); @@ -60,7 +60,7 @@ if ($_GET['_cid']) // get contacts from DB $sql_result = $DB->limitquery("SELECT * FROM ".get_table_name('contacts')." - WHERE del<>'1' + WHERE del<>1 AND user_id=? ORDER BY name", $start_row, diff --git a/program/steps/addressbook/edit.inc b/program/steps/addressbook/edit.inc index feb794f4d..a129d0094 100644 --- a/program/steps/addressbook/edit.inc +++ b/program/steps/addressbook/edit.inc @@ -26,7 +26,7 @@ if (($_GET['_cid'] || $_POST['_cid']) && $_action=='edit') $DB->query("SELECT * FROM ".get_table_name('contacts')." WHERE contact_id=? AND user_id=? - AND del<>'1'", + AND del<>1", $cid, $_SESSION['user_id']); diff --git a/program/steps/addressbook/func.inc b/program/steps/addressbook/func.inc index 4cc79bad6..8065219b0 100644 --- a/program/steps/addressbook/func.inc +++ b/program/steps/addressbook/func.inc @@ -43,7 +43,7 @@ function rcmail_contacts_list($attrib) // count contacts for this user $sql_result = $DB->query("SELECT COUNT(contact_id) AS rows FROM ".get_table_name('contacts')." - WHERE del<>'1' + WHERE del<>1 AND user_id=?", $_SESSION['user_id']); @@ -56,7 +56,7 @@ function rcmail_contacts_list($attrib) // get contacts from DB $sql_result = $DB->limitquery("SELECT * FROM ".get_table_name('contacts')." - WHERE del<>'1' + WHERE del<>1 AND user_id= ? ORDER BY name", $start_row, @@ -173,7 +173,7 @@ function rcmail_get_rowcount_text($max=NULL) if ($max===NULL) { $sql_result = $DB->query("SELECT 1 FROM ".get_table_name('contacts')." - WHERE del<>'1' + WHERE del<>1 AND user_id=?", $_SESSION['user_id']); diff --git a/program/steps/addressbook/list.inc b/program/steps/addressbook/list.inc index ecb634b6f..0aa4873b3 100644 --- a/program/steps/addressbook/list.inc +++ b/program/steps/addressbook/list.inc @@ -24,7 +24,7 @@ $REMOTE_REQUEST = TRUE; // count contacts for this user $sql_result = $DB->query("SELECT COUNT(contact_id) AS rows FROM ".get_table_name('contacts')." - WHERE del<>'1' + WHERE del<>1 AND user_id=?", $_SESSION['user_id']); @@ -40,7 +40,7 @@ $start_row = ($CONTACTS_LIST['page']-1) * $CONFIG['pagesize']; // get contacts from DB $sql_result = $DB->limitquery("SELECT * FROM ".get_table_name('contacts')." - WHERE del<>'1' + WHERE del<>1 AND user_id=? ORDER BY name", $start_row, diff --git a/program/steps/addressbook/save.inc b/program/steps/addressbook/save.inc index 2f54e435b..f5ba139b9 100644 --- a/program/steps/addressbook/save.inc +++ b/program/steps/addressbook/save.inc @@ -52,7 +52,7 @@ if ($_POST['_cid']) SET changed=now(), ".join(', ', $a_write_sql)." WHERE contact_id=? AND user_id=? - AND del<>'1'", + AND del<>1", $_POST['_cid'], $_SESSION['user_id']); @@ -73,7 +73,7 @@ if ($_POST['_cid']) $sql_result = $DB->query("SELECT * FROM ".get_table_name('contacts')." WHERE contact_id=? AND user_id=? - AND del<>'1'", + AND del<>1", $_POST['_cid'], $_SESSION['user_id']); @@ -109,7 +109,7 @@ else $sql_result = $DB->query("SELECT 1 FROM ".get_table_name('contacts')." WHERE user_id=? AND email=? - AND del<>'1'", + AND del<>1", $_SESSION['user_id'], $_POST['_email']); @@ -134,11 +134,11 @@ else if (sizeof($a_insert_cols)) { $DB->query("INSERT INTO ".get_table_name('contacts')." - (user_id, changed, ".join(', ', $a_insert_cols).") - VALUES (?, now(), ".join(', ', $a_insert_values).")", + (user_id, changed, del, ".join(', ', $a_insert_cols).") + VALUES (?, now(), 0, ".join(', ', $a_insert_values).")", $_SESSION['user_id']); - $insert_id = $DB->insert_id(); + $insert_id = $DB->insert_id(get_sequence_name('contacts')); } if ($insert_id) diff --git a/program/steps/addressbook/show.inc b/program/steps/addressbook/show.inc index 83db486cc..960ea1c45 100644 --- a/program/steps/addressbook/show.inc +++ b/program/steps/addressbook/show.inc @@ -26,7 +26,7 @@ if ($_GET['_cid'] || $_POST['_cid']) $DB->query("SELECT * FROM ".get_table_name('contacts')." WHERE contact_id=? AND user_id=? - AND del<>'1'", + AND del<>1", $cid, $_SESSION['user_id']); diff --git a/program/steps/mail/addcontact.inc b/program/steps/mail/addcontact.inc index ad1544e71..b1129ec9d 100644 --- a/program/steps/mail/addcontact.inc +++ b/program/steps/mail/addcontact.inc @@ -32,7 +32,7 @@ if ($_GET['_address']) $sql_result = $DB->query("SELECT 1 FROM ".get_table_name('contacts')." WHERE user_id=? AND email=? - AND del<>'1'", + AND del<>1", $_SESSION['user_id'],$contact['mailto']); // contact entry with this mail address exists @@ -42,13 +42,13 @@ if ($_GET['_address']) else if ($contact['mailto']) { $DB->query("INSERT INTO ".get_table_name('contacts')." - (user_id, changed, name, email) - VALUES (?, now(), ?, ?)", + (user_id, changed, del, name, email) + VALUES (?, now(), 0, ?, ?)", $_SESSION['user_id'], $contact['name'], $contact['mailto']); - $added = $DB->insert_id(); + $added = $DB->insert_id(get_sequence_name('contacts')); } } diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc index 9509b492b..45f111263 100644 --- a/program/steps/mail/compose.inc +++ b/program/steps/mail/compose.inc @@ -88,50 +88,20 @@ function rcmail_compose_headers($attrib) switch ($part) { case 'from': - // pass the following attributes to the form class - $field_attrib = array('name' => '_from'); - foreach ($attrib as $attr => $value) - if (in_array($attr, array('id', 'class', 'style', 'size', 'tabindex'))) - $field_attrib[$attr] = $value; - - // get this user's identities - $sql_result = $DB->query("SELECT identity_id, name, email - FROM ".get_table_name('identities')." WHERE user_id=? - AND del<>'1' - ORDER BY ".$DB->quoteIdentifier('default')." DESC, name ASC", - $_SESSION['user_id']); - - if ($DB->num_rows($sql_result)) - { - $select_from = new select($field_attrib); - while ($sql_arr = $DB->fetch_assoc($sql_result)) - $select_from->add(format_email_recipient($sql_arr['email'], $sql_arr['name']), $sql_arr['identity_id']); - - $out = $select_from->show($_POST['_from']); - } - else - { - $input_from = new textfield($field_attrib); - $out = $input_from->show($_POST['_from']); - } - - if ($form_start) - $out = $form_start.$out; - - return $out; - + return rcmail_compose_header_from($attrib); case 'to': $fname = '_to'; $header = 'to'; - + // we have contact id's as get parameters - if (!empty($_GET['_to']) && preg_match('/[0-9]+,?/', $_GET['_to'])) + if (!empty($_GET['_to']) && preg_match('/^([0-9]+,?)+$/', $_GET['_to'])) { $a_recipients = array(); $sql_result = $DB->query("SELECT name, email - FROM ".get_table_name('contacts')." WHERE user_id=? - AND del<>'1' + FROM ".get_table_name('contacts')." + WHERE user_id=? + AND del<>1 AND contact_id IN (".$_GET['_to'].")", $_SESSION['user_id']); @@ -229,71 +199,91 @@ function rcmail_compose_headers($attrib) } -/*function rcube_compose_headers($attrib) - { - global $CONFIG, $OUTPUT; - - list($form_start, $form_end) = get_form_tags($attrib); - - // allow the following attributes to be added to the headers table - $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id', 'cellpadding', 'cellspacing', 'border')); - - $labels = array(); - $labels['from'] = rcube_label('from'); - $labels['to'] = rcube_label('to'); - $labels['cc'] = rcube_label('cc'); - $labels['bcc'] = rcube_label('bcc'); - $labels['replyto'] = rcube_label('replyto'); - - $input_from = new textfield(array('name' => '_from', 'size' => 30)); - $input_to = new textfield(array('name' => '_to', 'size' => 30)); - $input_cc = new textfield(array('name' => '_cc', 'size' => 30)); - $input_bcc = new textfield(array('name' => '_bcc', 'size' => 30)); - $input_replyto = new textfield(array('name' => '_replyto', 'size' => 30)); - - $fields = array(); - $fields['from'] = $input_from->show($_POST['_from']); - $fields['to'] = $input_to->show($_POST['_to']); - $fields['cc'] = $input_cc->show($_POST['_cc']); - $fields['bcc'] = $input_bcc->show($_POST['_bcc']); - $fields['replyto'] = $input_replyto->show($_POST['_replyto']); - - - $out = <<<EOF -$form_start -<table$attrib_str><tr> - -<td class="title">$labels[from]</td> -<td>$fields[from]</td> - -</tr><tr> - -<td class="title">$labels[to]</td> -<td>$fields[to]</td> -</tr><tr> +function rcmail_compose_header_from($attrib) + { + global $IMAP, $REPLY_MESSAGE, $DB, $OUTPUT, $JS_OBJECT_NAME; + + // pass the following attributes to the form class + $field_attrib = array('name' => '_from'); + foreach ($attrib as $attr => $value) + if (in_array($attr, array('id', 'class', 'style', 'size', 'tabindex'))) + $field_attrib[$attr] = $value; + + // extract all recipients of the reply-message + $a_recipients = array(); + if ($REPLY_MESSAGE && is_object($REPLY_MESSAGE['headers'])) + { + $a_to = $IMAP->decode_address_list($REPLY_MESSAGE['headers']->to); + foreach ($a_to as $addr) + { + if (!empty($addr['mailto'])) + $a_recipients[] = $addr['mailto']; + } -<td class="title">$labels[cc]</td> -<td>$fields[cc]</td> + if (!empty($REPLY_MESSAGE['headers']->cc)) + { + $a_cc = $IMAP->decode_address_list($REPLY_MESSAGE['headers']->cc); + foreach ($a_cc as $addr) + { + if (!empty($addr['mailto'])) + $a_recipients[] = $addr['mailto']; + } + } + } -</tr><tr> + // get this user's identities + $sql_result = $DB->query("SELECT identity_id, name, email, signature + FROM ".get_table_name('identities')." + WHERE user_id=? + AND del<>1 + ORDER BY ".$DB->quoteIdentifier('standard')." DESC, name ASC", + $_SESSION['user_id']); + + if ($DB->num_rows($sql_result)) + { + $from_id = 0; + $a_signatures = array(); + + $field_attrib['onchange'] = "$JS_OBJECT_NAME.change_identity(this)"; + $select_from = new select($field_attrib); + + while ($sql_arr = $DB->fetch_assoc($sql_result)) + { + $select_from->add(format_email_recipient($sql_arr['email'], $sql_arr['name']), $sql_arr['identity_id']); -<td class="title">$labels[bcc]</td> -<td>$fields[bcc]</td> + // add signature to array + if (!empty($sql_arr['signature'])) + $a_signatures[$sql_arr['identity_id']] = $sql_arr['signature']; + + // set identity if it's one of the reply-message recipients + if (in_array($sql_arr['email'], $a_recipients)) + $from_id = $sql_arr['identity_id']; + } -</tr><tr> + // overwrite identity selection with post parameter + if (isset($_POST['_from'])) + $from_id = $_POST['_from']; -<td class="title">$labels[replyto]</td> -<td>$fields[replyto]</td> + $out = $select_from->show($from_id); + -</tr></table> -$form_end -EOF; + // add signatures to client + $OUTPUT->add_script(sprintf("%s.set_env('signatures', %s);", $JS_OBJECT_NAME, array2js($a_signatures))); + } + else + { + $input_from = new textfield($field_attrib); + $out = $input_from->show($_POST['_from']); + } + + if ($form_start) + $out = $form_start.$out; - return $out; + return $out; } -*/ + function rcmail_compose_body($attrib) { @@ -360,6 +350,14 @@ function rcmail_create_reply_body($body) $pefix = sprintf("\n\n\nOn %s, %s wrote:\n", $REPLY_MESSAGE['headers']->date, $IMAP->decode_header($REPLY_MESSAGE['headers']->from)); + + + // try to remove the signature + if ($sp = strrpos($body, '--')) + { + if ($body{$sp+3}==' ' || $body{$sp+3}=="\n" || $body{$sp+3}=="\r") + $body = substr($body, 0, $sp-1); + } return $pefix.$body; } @@ -596,7 +594,7 @@ function rcmail_charset_pulldown($selected='ISO-8859-1') $sql_result = $DB->query("SELECT name, email FROM ".get_table_name('contacts')." WHERE user_id=? - AND del<>'1'",$_SESSION['user_id']); + AND del<>1",$_SESSION['user_id']); if ($DB->num_rows($sql_result)) { diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc index ca72f7437..c81dd2fd2 100644 --- a/program/steps/mail/func.inc +++ b/program/steps/mail/func.inc @@ -305,26 +305,41 @@ function rcmail_message_list($attrib) // make sort links $sort = ''; - if (in_array($col, $a_sort_cols) && (!empty($attrib['sortdescbutton']) || !empty($attrib['sortascbutton']))) + if ($IMAP->get_capability('sort') && in_array($col, $a_sort_cols)) { - $sort = ' '; - - // asc link - if (!empty($attrib['sortascbutton'])) + // have buttons configured + if (!empty($attrib['sortdescbutton']) || !empty($attrib['sortascbutton'])) { - $sort .= rcube_button(array('command' => 'sort', - 'prop' => $col.'_ASC', - 'image' => $attrib['sortascbutton'], - 'title' => 'sortasc')); - } + $sort = ' '; + + // asc link + if (!empty($attrib['sortascbutton'])) + { + $sort .= rcube_button(array('command' => 'sort', + 'prop' => $col.'_ASC', + 'image' => $attrib['sortascbutton'], + 'align' => 'absmiddle', + 'title' => 'sortasc')); + } - // desc link - if (!empty($attrib['sortdescbutton'])) + // desc link + if (!empty($attrib['sortdescbutton'])) + { + $sort .= rcube_button(array('command' => 'sort', + 'prop' => $col.'_DESC', + 'image' => $attrib['sortdescbutton'], + 'align' => 'absmiddle', + 'title' => 'sortdesc')); + } + } + // just add a link tag to the header + else { - $sort .= rcube_button(array('command' => 'sort', - 'prop' => $col.'_DESC', - 'image' => $attrib['sortdescbutton'], - 'title' => 'sortdesc')); + $col_name = sprintf('<a href="./#sort" onclick="return %s.command(\'sort\',\'%s\',this)" title="%s">%s</a>', + $JS_OBJECT_NAME, + $col, + rcube_label('sortby'), + $col_name); } } @@ -1128,20 +1143,76 @@ function rcmail_first_text_part($message_parts) // get source code of a specific message and cache it function rcmail_message_source($uid) { - global $IMAP, $DB; + global $IMAP, $DB, $CONFIG; + + // get message ID if uid is given + $cache_key = $IMAP->mailbox.'.msg'; + $cached = $IMAP->get_cached_message($cache_key, $uid, FALSE); + + // message is cached in database + if ($cached && !empty($cached->body)) + return $cached->body; + + if (!$cached) + $headers = $IMAP->get_headers($uid); + else + $headers = &$cached; + - // get message ID if uid is given - $headers = $IMAP->get_headers($uid); $message_id = $headers->messageID; - // get cached message source - $msg_source = rcube_read_cache($message_id); + $temp_dir = $CONFIG['temp_dir'].(!eregi('\/$', $CONFIG['temp_dir']) ? '/' : ''); + $cache_dir = $temp_dir.$_SESSION['client_id']; + $cache_path = $cache_dir.'/'.$message_id; + + // message is cached in temp dir + if (is_dir($cache_dir) && is_file($cache_path)) + { + if ($fp = fopen($cache_path, 'r')) + { + $msg_source = fread($fp, filesize($cache_path)); + fclose($fp); + return $msg_source; + } + } + + + // get message from server + $msg_source = $IMAP->get_raw_body($uid); + + // let's cache the message body within the database + if ($CONFIG['enable_caching'] && $cached && ($CONFIG['db_max_length'] -300) > $headers->size) + { + $DB->query("UPDATE ".get_table_name('messages')." + SET body=? + WHERE user_id=? + AND cache_key=? + AND uid=?", + $msg_source, + $_SESSION['user_id'], + $cache_key, + $uid); + + return $msg_source; + } + + + // create dir for caching + if (!is_dir($cache_dir)) + $dir = mkdir($cache_dir); + else + $dir = true; - // get message from server and cache it - if (!$msg_source) + // attempt to write a file with the message body + if ($dir && ($fp = fopen($cache_path, 'w'))) + { + fwrite($fp, $msg_source); + fclose($fp); + } + else { - $msg_source = $IMAP->get_raw_body($uid); - rcube_write_cache($message_id, $msg_source, TRUE); + raise_error(array('code' => 403, 'type' => 'php', 'line' => __LINE__, 'file' => __FILE__, + 'message' => "Failed to write to temp dir"), TRUE, FALSE); } return $msg_source; diff --git a/program/steps/mail/sendmail.inc b/program/steps/mail/sendmail.inc index 11fb559dd..8ec30b0a7 100644 --- a/program/steps/mail/sendmail.inc +++ b/program/steps/mail/sendmail.inc @@ -46,7 +46,7 @@ function rcmail_get_identity($id) FROM ".get_table_name('identities')." WHERE identity_id=? AND user_id=? - AND del<>'1'", + AND del<>1", $id,$_SESSION['user_id']); if ($DB->num_rows($sql_result)) @@ -78,8 +78,8 @@ if (empty($CHARSET)) $CHARSET = 'ISO-8859-1'; -$mailto_regexp = array('/,\s*[\r\n]+/', '/[\r\n]+/', '/,\s*$/m'); -$mailto_replace = array(' ', ', ', ''); +$mailto_regexp = array('/[,;]\s*[\r\n]+/', '/[\r\n]+/', '/[,;]\s*$/m'); +$mailto_replace = array(', ', ', ', ''); // repalce new lines and strip ending ', ' $mailto = preg_replace($mailto_regexp, $mailto_replace, stripslashes($_POST['_to'])); @@ -175,13 +175,16 @@ if (is_array($_FILES['_attachments']['tmp_name'])) foreach ($_FILES['_attachments']['tmp_name'] as $i => $filepath) $MAIL_MIME->addAttachment($filepath, $files['type'][$i], $files['name'][$i], TRUE); + +$message_charset = isset($_POST['_charset']) ? $_POST['_charset'] : $CHARSET; + // encoding settings for mail composing $message_param = array('text_encoding' => '7bit', 'html_encoding' => 'quoted-printable', 'head_encoding' => 'quoted-printable', - 'head_charset' => $CHARSET, - 'html_charset' => $CHARSET, - 'text_charset' => $CHARSET); + '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); diff --git a/program/steps/settings/delete_identity.inc b/program/steps/settings/delete_identity.inc index 3bca860b3..b8f9f526c 100644 --- a/program/steps/settings/delete_identity.inc +++ b/program/steps/settings/delete_identity.inc @@ -24,7 +24,7 @@ $REMOTE_REQUEST = $_GET['_remote'] ? TRUE : FALSE; if ($_GET['_iid']) { $DB->query("UPDATE ".get_table_name('identities')." - SET del='1' + SET del=1 WHERE user_id=? AND identity_id IN (".$_GET['_iid'].")", $_SESSION['user_id']); diff --git a/program/steps/settings/edit_identity.inc b/program/steps/settings/edit_identity.inc index 6649c209a..07cd8fa02 100644 --- a/program/steps/settings/edit_identity.inc +++ b/program/steps/settings/edit_identity.inc @@ -25,7 +25,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'", + AND del<>1", $id, $_SESSION['user_id']); @@ -63,7 +63,8 @@ function rcube_identity_form($attrib) 'organization' => array('type' => 'text'), 'reply-to' => array('type' => 'text', 'label' => 'replyto'), 'bcc' => array('type' => 'text'), - 'default' => array('type' => 'checkbox', 'label' => 'setdefault')); + 'signature' => array('type' => 'textarea'), + 'standard' => array('type' => 'checkbox', 'label' => 'setdefault')); // a specific part is requested diff --git a/program/steps/settings/func.inc b/program/steps/settings/func.inc index 01b692395..b33f8d434 100644 --- a/program/steps/settings/func.inc +++ b/program/steps/settings/func.inc @@ -146,9 +146,9 @@ function rcmail_identities_list($attrib) // get contacts from DB $sql_result = $DB->query("SELECT * FROM ".get_table_name('identities')." - WHERE del<>'1' + WHERE del<>1 AND user_id=? - ORDER BY ".$DB->quoteIdentifier('default')." DESC, name ASC", + ORDER BY standard DESC, name ASC", $_SESSION['user_id']); diff --git a/program/steps/settings/manage_folders.inc b/program/steps/settings/manage_folders.inc index 04b2a461e..33d83dfff 100644 --- a/program/steps/settings/manage_folders.inc +++ b/program/steps/settings/manage_folders.inc @@ -69,10 +69,15 @@ else if ($_action=='create-folder') else if ($_action=='delete-folder') { if (strlen($_GET['_mboxes'])) - $IMAP->delete_mailbox(explode(',', $_GET['_mboxes'])); + $deleted = $IMAP->delete_mailbox(explode(',', $_GET['_mboxes'])); - if ($_GET['_remote']) - rcube_remote_response('// deleted'); + if ($_GET['_remote'] && $deleted) + rcube_remote_response(sprintf("this.remove_folder_row('%s')", rep_specialchars_output($_GET['_mboxes'], 'js'))); + else if ($_GET['_remote']) + { + $commands = show_message('errorsaving', 'error'); + rcube_remote_response($commands); + } } @@ -174,5 +179,9 @@ function rcube_create_folder_form($attrib) } +// add some labels to client +rcube_add_label('deletefolderconfirm'); + + parse_template('managefolders'); ?>
\ No newline at end of file diff --git a/program/steps/settings/save_identity.inc b/program/steps/settings/save_identity.inc index 2e42987bf..dc61b7875 100644 --- a/program/steps/settings/save_identity.inc +++ b/program/steps/settings/save_identity.inc @@ -19,7 +19,7 @@ */ -$a_save_cols = array('name', 'email', 'organization', 'reply-to', 'bcc', 'default'); +$a_save_cols = array('name', 'email', 'organization', 'reply-to', 'bcc', 'standard', 'signature'); // check input @@ -51,7 +51,7 @@ if ($_POST['_iid']) SET ".join(', ', $a_write_sql)." WHERE identity_id=? AND user_id=? - AND del<>'1'", + AND del<>1", $_POST['_iid'], $_SESSION['user_id']); @@ -64,10 +64,10 @@ if ($_POST['_iid']) // mark all other identities as 'not-default' $DB->query("UPDATE ".get_table_name('identities')." - SET ".$DB->quoteIdentifier('default')."='0' + SET ".$DB->quoteIdentifier('standard')."='0' WHERE user_id=? AND identity_id<>? - AND del<>'1'", + AND del<>1", $_SESSION['user_id'], $_POST['_iid']); @@ -106,8 +106,8 @@ else (user_id, ".join(', ', $a_insert_cols).") VALUES (?, ".join(', ', $a_insert_values).")", $_SESSION['user_id']); - - $insert_id = $DB->insert_id(); + + $insert_id = $DB->insert_id(get_sequence_name('identities')); } if ($insert_id) |