Optimized loading time; added periodic mail check; added EXPUNGE command
3 files added
21 files modified
| | |
| | | CHANGELOG RoundCube Webmail |
| | | --------------------------- |
| | | |
| | | 2006/01/04 |
| | | ---------- |
| | | - Fixed bug when inserting signatures with !?& |
| | | - Chopping message headers before inserting into the message cache table (to avoid bugs in Postgres) |
| | | - Allow one-char domains in e-mail addresses |
| | | - Make product name in page title configurable |
| | | - Make username available as skin object |
| | | - Added session_write_close() in rcube_db class destructor to avoid problems in PHP 5.0.5 |
| | | - Use move_uploaded_file() instead of copy() for a more secure handling of uploaded attachments |
| | | - Additional config parameter to show/hide deleted messages |
| | | - Added periodic request for checking new mails (Request #1307821) |
| | | - Added EXPUNGE command |
| | | - Optimized loading time for mail interface |
| | | |
| | | |
| | | 2005/12/16 |
| | | ---------- |
| | |
| | | * The Apache Webserver |
| | | * .htaccess support allowing overrides for DirectoryIndex |
| | | * PHP Version 4.3.1 or greater |
| | | * PCRE (perl compatible regular expression) installed with PHP |
| | | * php.ini options: |
| | | - error_reporting E_ALL & ~E_NOTICE (or lower) |
| | | - file_uploads on (for attachment upload features) |
| | |
| | | `created` datetime NOT NULL default '0000-00-00 00:00:00', |
| | | `last_login` datetime NOT NULL default '0000-00-00 00:00:00', |
| | | `language` varchar(5) NOT NULL default 'en', |
| | | `preferences` text NOT NULL, |
| | | `preferences` text NOT NULL default '', |
| | | PRIMARY KEY (`user_id`) |
| | | ) TYPE=MyISAM; |
| | | |
| | |
| | | -- Version 0.1-20051007 |
| | | |
| | | |
| | | ALTER TABLE session ADD ip VARCHAR(15) NOT NULL AFTER changed; |
| | | ALTER TABLE users ADD alias VARCHAR(128) NOT NULL AFTER mail_host; |
| | | ALTER TABLE `session` ADD `ip` VARCHAR(15) NOT NULL AFTER changed; |
| | | ALTER TABLE `users` ADD `alias` VARCHAR(128) NOT NULL AFTER mail_host; |
| | | |
| | | |
| | | |
| | |
| | | -- |
| | | |
| | | CREATE TABLE users ( |
| | | user_id integer DEFAULT nextval('user_ids'::text) NOT NULL, |
| | | user_id integer DEFAULT nextval('user_ids'::text) PRIMARY KEY, |
| | | username character varying(128) DEFAULT ''::character varying NOT NULL, |
| | | mail_host character varying(128) DEFAULT ''::character varying NOT NULL, |
| | | alias character varying(128) DEFAULT ''::character varying NOT NULL, |
| | |
| | | -- |
| | | |
| | | CREATE TABLE "session" ( |
| | | sess_id character varying(40) DEFAULT ''::character varying NOT NULL, |
| | | sess_id character varying(40) DEFAULT ''::character varying PRIMARY KEY, |
| | | created timestamp with time zone DEFAULT now() NOT NULL, |
| | | changed timestamp with time zone DEFAULT now() NOT NULL, |
| | | ip character varying(16) NOT NULL, |
| | |
| | | -- |
| | | |
| | | CREATE TABLE identities ( |
| | | identity_id integer DEFAULT nextval('identity_ids'::text) NOT NULL, |
| | | user_id integer DEFAULT 0 NOT NULL, |
| | | identity_id integer DEFAULT nextval('identity_ids'::text) PRIMARY KEY, |
| | | user_id integer NOT NULL REFERENCES users (user_id), |
| | | del integer DEFAULT 0 NOT NULL, |
| | | standard integer DEFAULT 0 NOT NULL, |
| | | name character varying(128) NOT NULL, |
| | |
| | | -- |
| | | |
| | | CREATE TABLE contacts ( |
| | | contact_id integer DEFAULT nextval('contact_ids'::text) NOT NULL, |
| | | user_id integer DEFAULT 0 NOT NULL, |
| | | contact_id integer DEFAULT nextval('contact_ids'::text) PRIMARY KEY, |
| | | user_id integer NOT NULL REFERENCES users (user_id), |
| | | changed timestamp with time zone DEFAULT now() NOT NULL, |
| | | del integer DEFAULT 0 NOT NULL, |
| | | name character varying(128) DEFAULT ''::character varying NOT NULL, |
| | |
| | | -- |
| | | |
| | | CREATE TABLE "cache" ( |
| | | cache_id integer DEFAULT nextval('cache_ids'::text) NOT NULL, |
| | | user_id integer DEFAULT 0 NOT NULL, |
| | | session_id character varying(40), |
| | | cache_id integer DEFAULT nextval('cache_ids'::text) PRIMARY KEY, |
| | | user_id integer NOT NULL REFERENCES users (user_id), |
| | | session_id character varying(40) REFERENCES "session" (session_id), |
| | | cache_key character varying(128) DEFAULT ''::character varying NOT NULL, |
| | | created timestamp with time zone DEFAULT now() NOT NULL, |
| | | data text NOT NULL |
| | |
| | | -- |
| | | |
| | | CREATE TABLE "messages" ( |
| | | message_id integer DEFAULT nextval('message_ids'::text) NOT NULL, |
| | | user_id integer DEFAULT 0 NOT NULL, |
| | | message_id integer DEFAULT nextval('message_ids'::text) PRIMARY KEY, |
| | | user_id integer NOT NULL REFERENCES users (user_id), |
| | | del integer DEFAULT 0 NOT NULL, |
| | | cache_key character varying(128) DEFAULT ''::character varying NOT NULL, |
| | | idx integer DEFAULT 0 NOT NULL, |
| | |
| | | headers text NOT NULL, |
| | | body text |
| | | ); |
| | | |
| | | |
| | | |
| | | -- |
| | | -- Add primary keys |
| | | -- |
| | | |
| | | ALTER TABLE ONLY "cache" |
| | | ADD CONSTRAINT cache_pkey PRIMARY KEY (cache_id); |
| | | |
| | | |
| | | ALTER TABLE ONLY "contacts" |
| | | ADD CONSTRAINT contacts_pkey PRIMARY KEY (contact_id); |
| | | |
| | | |
| | | ALTER TABLE ONLY identities |
| | | ADD CONSTRAINT identities_pkey PRIMARY KEY (identity_id); |
| | | |
| | | |
| | | ALTER TABLE ONLY "session" |
| | | ADD CONSTRAINT session_pkey PRIMARY KEY (sess_id); |
| | | |
| | | |
| | | ALTER TABLE ONLY "users" |
| | | ADD CONSTRAINT users_pkey PRIMARY KEY (user_id); |
| | | |
| | | |
| | | ALTER TABLE ONLY "messages" |
| | | ADD CONSTRAINT messages_pkey PRIMARY KEY (message_id); |
| | | |
| | | |
| | | -- |
| | | -- Reference keys |
| | | -- |
| | | |
| | | ALTER TABLE ONLY "cache" |
| | | ADD CONSTRAINT "$1" FOREIGN KEY (user_id) REFERENCES users(user_id); |
| | | |
| | | ALTER TABLE ONLY "cache" |
| | | ADD CONSTRAINT "$2" FOREIGN KEY (session_id) REFERENCES "session"(sess_id); |
| | | |
| | | |
| | | ALTER TABLE ONLY "contacts" |
| | | ADD CONSTRAINT "$1" FOREIGN KEY (user_id) REFERENCES users(user_id); |
| | | |
| | | |
| | | ALTER TABLE ONLY "identities" |
| | | ADD CONSTRAINT "$1" FOREIGN KEY (user_id) REFERENCES users(user_id); |
| | | |
| | | |
| | | ALTER TABLE ONLY "messages" |
| | | ADD CONSTRAINT "$1" FOREIGN KEY (user_id) REFERENCES users(user_id); |
| | | |
| | |
| | | $rcmail_config['smtp_port'] = 25; |
| | | $rcmail_config['default_port'] = 143; |
| | | $rcmail_config['session_lifetime'] = 20; |
| | | $rcmail_config['skip_deleted'] = FALSE; |
| | | $rcmail_config['message_sort_col'] = 'date'; |
| | | $rcmail_config['message_sort_order'] = 'DESC'; |
| | | $rcmail_config['log_dir'] = 'logs/'; |
| | |
| | | $rcmail_config['smtp_port'] = 25; |
| | | $rcmail_config['default_port'] = 143; |
| | | $rcmail_config['session_lifetime'] = 20; |
| | | $rcmail_config['skip_deleted'] = FALSE; |
| | | $rcmail_config['message_sort_col'] = 'date'; |
| | | $rcmail_config['message_sort_order'] = 'DESC'; |
| | | $rcmail_config['log_dir'] = 'logs/'; |
| | |
| | | - add these lines to /config/main.inc.php |
| | | $rcmail_config['smtp_auth_type'] = ''; // if you need to specify an auth method for SMTP |
| | | $rcmail_config['session_lifetime'] = 20; // to specify the session lifetime in minutes |
| | | $rcmail_config['skip_deleted'] = FALSE; |
| | | $rcmail_config['message_sort_col'] = 'date'; |
| | | $rcmail_config['message_sort_order'] = 'DESC'; |
| | | $rcmail_config['log_dir'] = 'logs/'; |
| | |
| | | - replace all files in folder /skins/default/ |
| | | - run all commands in SQL/*.update.sql or re-initalize database with *.initial.sql |
| | | - add these lines to /config/main.inc.php |
| | | $rcmail_config['skip_deleted'] = FALSE; |
| | | $rcmail_config['message_sort_col'] = 'date'; |
| | | $rcmail_config['message_sort_order'] = 'DESC'; |
| | | $rcmail_config['log_dir'] = 'logs/'; |
| | |
| | | $rcmail_config['db_sequence_identity_ids'] = 'identity_ids'; |
| | | $rcmail_config['db_sequence_contact_ids'] = 'contact_ids'; |
| | | $rcmail_config['db_sequence_cache_ids'] = 'cache_ids'; |
| | | $rcmail_config['db_sequence_message_ids'] = 'message_ids'; |
| | | $rcmail_config['db_sequence_message_ids'] = 'message_ids'; |
| | | |
| | |
| | | // add this user-agent to message headers when sending |
| | | $rcmail_config['useragent'] = 'RoundCube Webmail/0.1b'; |
| | | |
| | | // use this name to compose page titles |
| | | $rcmail_config['product_name'] = 'RoundCube Webmail'; |
| | | |
| | | // only list folders within this path |
| | | $rcmail_config['imap_root'] = ''; |
| | | |
| | |
| | | /* |
| | | +-----------------------------------------------------------------------+ |
| | | | RoundCube Webmail IMAP Client | |
| | | | Version 0.1-20051214 | |
| | | | Version 0.1-20060104 | |
| | | | | |
| | | | Copyright (C) 2005, RoundCube Dev. - Switzerland | |
| | | | Licensed under the GNU GPL | |
| | |
| | | $Id$ |
| | | |
| | | */ |
| | | |
| | | define('RCMAIL_VERSION', '0.1-20060104'); |
| | | |
| | | |
| | | // define global vars |
| | | $INSTALL_PATH = dirname($_SERVER['SCRIPT_FILENAME']); |
| | |
| | | |
| | | if ($_action=='addcontact') |
| | | include('program/steps/mail/addcontact.inc'); |
| | | |
| | | if ($_action=='expunge') |
| | | include('program/steps/mail/folders.inc'); |
| | | |
| | | if ($_action=='check-recent') |
| | | include('program/steps/mail/check_recent.inc'); |
| | | |
| | | if ($_action=='getunread') |
| | | include('program/steps/mail/getunread.inc'); |
| | | |
| | | if ($_action=='list' && $_GET['_remote']) |
| | | include('program/steps/mail/list.inc'); |
| | |
| | | global $CONFIG, $DB, $IMAP; |
| | | |
| | | $IMAP = new rcube_imap($DB); |
| | | $IMAP->debug_level = $CONFIG['debug_level']; |
| | | $IMAP->skip_deleted = $CONFIG['skip_deleted']; |
| | | |
| | | |
| | | // connect with stored session data |
| | | if ($connect) |
| | |
| | | |
| | | |
| | | // send correct response on a remote request |
| | | function rcube_remote_response($js_code) |
| | | function rcube_remote_response($js_code, $flush=FALSE) |
| | | { |
| | | send_nocacheing_headers(); |
| | | header('Content-Type: application/x-javascript'); |
| | | static $s_header_sent = FALSE; |
| | | |
| | | if (!$s_header_sent) |
| | | { |
| | | $s_header_sent = TRUE; |
| | | send_nocacheing_headers(); |
| | | header('Content-Type: application/x-javascript'); |
| | | print '/** remote response ['.date('d/M/Y h:i:s O')."] **/\n"; |
| | | } |
| | | |
| | | print '/** remote response ['.date('d/M/Y h:i:s O')."] **/\n"; |
| | | // send response code |
| | | print $js_code; |
| | | exit; |
| | | |
| | | if ($flush) // flush the output buffer |
| | | flush(); |
| | | else // terminate script |
| | | exit; |
| | | } |
| | | |
| | | |
| | |
| | | $object = strtolower($attrib['name']); |
| | | |
| | | $object_handlers = array( |
| | | // GENERAL |
| | | 'loginform' => 'rcmail_login_form', |
| | | 'username' => 'rcmail_current_username', |
| | | |
| | | // MAIL |
| | | 'mailboxlist' => 'rcmail_mailbox_list', |
| | | 'message' => 'rcmail_message_container', |
| | | 'messages' => 'rcmail_message_list', |
| | | 'messagecountdisplay' => 'rcmail_messagecount_display', |
| | | 'messageheaders' => 'rcmail_message_headers', |
| | |
| | | 'composebody' => 'rcmail_compose_body' |
| | | ); |
| | | |
| | | if ($object=='loginform') |
| | | return rcmail_login_form($attrib); |
| | | |
| | | else if ($object=='message') |
| | | return rcmail_message_container($attrib); |
| | | |
| | | // execute object handler function |
| | | else if ($object_handlers[$object] && function_exists($object_handlers[$object])) |
| | | if ($object_handlers[$object] && function_exists($object_handlers[$object])) |
| | | return call_user_func($object_handlers[$object], $attrib); |
| | | |
| | | else if ($object=='pagetitle') |
| | | { |
| | | $task = $GLOBALS['_task']; |
| | | $title = !empty($CONFIG['product_name']) ? $CONFIG['product_name'].' :: ' : ''; |
| | | |
| | | if ($task=='mail' && isset($GLOBALS['MESSAGE']['subject'])) |
| | | return rep_specialchars_output("RoundCube|Mail :: ".$GLOBALS['MESSAGE']['subject']); |
| | | $title .= $GLOBALS['MESSAGE']['subject']; |
| | | else if (isset($GLOBALS['PAGE_TITLE'])) |
| | | return rep_specialchars_output("RoundCube|Mail :: ".$GLOBALS['PAGE_TITLE']); |
| | | $title .= $GLOBALS['PAGE_TITLE']; |
| | | else if ($task=='mail' && ($mbox_name = $IMAP->get_mailbox_name())) |
| | | return "RoundCube|Mail :: ".rep_specialchars_output(UTF7DecodeString($mbox_name), 'html', 'all'); |
| | | $title .= UTF7DecodeString($mbox_name); |
| | | else |
| | | return "RoundCube|Mail :: $task"; |
| | | $title .= $task; |
| | | |
| | | return rep_specialchars_output($title, 'html', 'all'); |
| | | } |
| | | |
| | | else if ($object=='about') |
| | | return ''; |
| | | |
| | | break; |
| | | } |
| | |
| | | } |
| | | |
| | | |
| | | // return the IMAP username of the current session |
| | | function rcmail_current_username($attrib) |
| | | { |
| | | global $DB; |
| | | static $s_username; |
| | | |
| | | // alread fetched |
| | | if (!empty($s_username)) |
| | | return $s_username; |
| | | |
| | | // get e-mail address form default identity |
| | | $sql_result = $DB->query("SELECT email AS mailto |
| | | FROM ".get_table_name('identities')." |
| | | WHERE user_id=? |
| | | AND standard=1 |
| | | AND del<>1", |
| | | $_SESSION['user_id']); |
| | | |
| | | if ($DB->num_rows($sql_result)) |
| | | { |
| | | $sql_arr = $DB->fetch_assoc($sql_result); |
| | | $s_username = $sql_arr['mailto']; |
| | | } |
| | | else if (strstr($_SESSION['username'], '@')) |
| | | $s_username = $_SESSION['username']; |
| | | else |
| | | $s_username = $_SESSION['username'].'@'.$_SESSION['imap_host']; |
| | | |
| | | return $s_username; |
| | | } |
| | | |
| | | |
| | | // return code for the webmail login form |
| | | function rcmail_login_form($attrib) |
| | | { |
| | |
| | | } |
| | | |
| | | |
| | | |
| | | function rcube_timer() |
| | | { |
| | | list($usec, $sec) = explode(" ", microtime()); |
| | | return ((float)$usec + (float)$sec); |
| | | } |
| | | |
| | | |
| | | function rcube_print_time($timer, $label='Timer') |
| | | { |
| | | static $print_count = 0; |
| | | |
| | | $print_count++; |
| | | $now = rcube_timer(); |
| | | $diff = $now-$timer; |
| | | |
| | | if (empty($label)) |
| | | $label = 'Timer '.$print_count; |
| | | |
| | | console(sprintf("%s: %0.4f sec", $label, $diff)); |
| | | } |
| | | |
| | | |
| | | ?> |
| | |
| | | |
| | | */ |
| | | |
| | | |
| | | /** |
| | | * Obtain the PEAR::DB class that is used for abstraction |
| | | */ |
| | | require_once('DB.php'); |
| | | |
| | | |
| | | /** |
| | | * Database independent query interface |
| | | * |
| | | * This is a wrapper for the PEAR::DB class |
| | | * |
| | | * @package RoundCube Webmail |
| | | * @author David Saez Padros <david@ols.es> |
| | | * @author Thomas Bruederli <roundcube@gmail.com> |
| | | * @version 1.14 |
| | | * @link http://pear.php.net/package/DB |
| | | */ |
| | | class rcube_db |
| | | { |
| | | var $db_dsnw; // DSN for write operations |
| | |
| | | var $last_res_id = 0; |
| | | |
| | | |
| | | // PHP 5 constructor |
| | | function __construct($db_dsnw,$db_dsnr='') |
| | | /** |
| | | * Object constructor |
| | | * |
| | | * @param string DSN for read/write operations |
| | | * @param string Optional DSN for read only operations |
| | | */ |
| | | function __construct($db_dsnw, $db_dsnr='') |
| | | { |
| | | if ($db_dsnr=='') |
| | | $db_dsnr=$db_dsnw; |
| | |
| | | } |
| | | |
| | | |
| | | // PHP 4 compatibility |
| | | /** |
| | | * PHP 4 object constructor |
| | | * |
| | | * @see rcube_db::__construct |
| | | */ |
| | | function rcube_db($db_dsnw,$db_dsnr='') |
| | | { |
| | | $this->__construct($db_dsnw,$db_dsnr); |
| | | } |
| | | |
| | | |
| | | // Connect to specific database |
| | | /** |
| | | * Object destructor |
| | | */ |
| | | function __destruct() |
| | | { |
| | | // before closing the database connection, write session data |
| | | session_write_close(); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Connect to specific database |
| | | * |
| | | * @param string DSN for DB connections |
| | | * @return object PEAR database handle |
| | | * @access private |
| | | */ |
| | | function dsn_connect($dsn) |
| | | { |
| | | // Use persistent connections if available |
| | | $dbh = DB::connect($dsn, array('persistent' => TRUE)); |
| | | |
| | | if (DB::isError($dbh)) |
| | | raise_error(array('code' => 500, |
| | | 'type' => 'db', |
| | | 'line' => __LINE__, |
| | | 'file' => __FILE__, |
| | | { |
| | | raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, |
| | | 'message' => $dbh->getMessage()), TRUE, FALSE); |
| | | } |
| | | |
| | | else if ($this->db_provider=='sqlite') |
| | | { |
| | |
| | | } |
| | | |
| | | |
| | | // Connect to appropiate databse |
| | | function db_connect ($mode) |
| | | /** |
| | | * Connect to appropiate databse |
| | | * depending on the operation |
| | | * |
| | | * @param string Connection mode (r|w) |
| | | * @access public |
| | | */ |
| | | function db_connect($mode) |
| | | { |
| | | $this->db_mode = $mode; |
| | | |
| | |
| | | if ($this->db_mode==$mode) |
| | | return; |
| | | } |
| | | |
| | | |
| | | if ($mode=='r') |
| | | $dsn = $this->db_dsnr; |
| | | else |
| | |
| | | } |
| | | |
| | | |
| | | // Query database |
| | | /** |
| | | * Execute a SQL query |
| | | * |
| | | * @param string SQL query to execute |
| | | * @param mixed Values to be inserted in query |
| | | * @return number Query handle identifier |
| | | * @access public |
| | | */ |
| | | function query() |
| | | { |
| | | $params = func_get_args(); |
| | |
| | | } |
| | | |
| | | |
| | | // Query with limits |
| | | /** |
| | | * Execute a SQL query with limits |
| | | * |
| | | * @param string SQL query to execute |
| | | * @param number Offset for LIMIT statement |
| | | * @param number Number of rows for LIMIT statement |
| | | * @param mixed Values to be inserted in query |
| | | * @return number Query handle identifier |
| | | * @access public |
| | | */ |
| | | function limitquery() |
| | | { |
| | | $params = func_get_args(); |
| | |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Execute a SQL query with limits |
| | | * |
| | | * @param string SQL query to execute |
| | | * @param number Offset for LIMIT statement |
| | | * @param number Number of rows for LIMIT statement |
| | | * @param array Values to be inserted in query |
| | | * @return number Query handle identifier |
| | | * @access private |
| | | */ |
| | | function _query($query, $offset, $numrows, $params) |
| | | { |
| | | // Read or write ? |
| | |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Get number of rows for a SQL query |
| | | * If no query handle is specified, the last query will be taken as reference |
| | | * |
| | | * @param number Optional query handle identifier |
| | | * @return mixed Number of rows or FALSE on failure |
| | | * @access public |
| | | */ |
| | | function num_rows($res_id=NULL) |
| | | { |
| | | if (!$this->db_handle) |
| | |
| | | } |
| | | |
| | | |
| | | function affected_rows($res_id=NULL) |
| | | /** |
| | | * Get number of affected rows fort he last query |
| | | * |
| | | * @return mixed Number of rows or FALSE on failure |
| | | * @access public |
| | | */ |
| | | function affected_rows() |
| | | { |
| | | if (!$this->db_handle) |
| | | return FALSE; |
| | |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Get last inserted record ID |
| | | * For Postgres databases, a sequence name is required |
| | | * |
| | | * @param string Sequence name for increment |
| | | * @return mixed ID or FALSE on failure |
| | | * @access public |
| | | */ |
| | | function insert_id($sequence = '') |
| | | { |
| | | if (!$this->db_handle || $this->db_mode=='r') |
| | |
| | | { |
| | | case 'pgsql': |
| | | // PostgreSQL uses sequences |
| | | $result =& $this->db_handle->getOne("SELECT CURRVAL('$sequence')"); |
| | | $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; |
| | | |
| | |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Get an associative array for one row |
| | | * If no query handle is specified, the last query will be taken as reference |
| | | * |
| | | * @param number Optional query handle identifier |
| | | * @return mixed Array with col values or FALSE on failure |
| | | * @access public |
| | | */ |
| | | function fetch_assoc($res_id=NULL) |
| | | { |
| | | $result = $this->_get_result($res_id); |
| | |
| | | } |
| | | |
| | | |
| | | function quote($input, $type=null) |
| | | /** |
| | | * Formats input so it can be safely used in a query |
| | | * |
| | | * @param mixed Value to quote |
| | | * @return string Quoted/converted string for use in query |
| | | * @access public |
| | | */ |
| | | function quote($input) |
| | | { |
| | | // create DB handle if not available |
| | | if (!$this->db_handle) |
| | | $this->db_connect('r'); |
| | | |
| | | return $this->db_handle->quote($input); |
| | | |
| | | // escape pear identifier chars |
| | | $rep_chars = array('?' => '\?', |
| | | '!' => '\!', |
| | | '&' => '\&'); |
| | | |
| | | return $this->db_handle->quoteSmart(strtr($input, $rep_chars)); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Quotes a string so it can be safely used as a table or column name |
| | | * |
| | | * @param string Value to quote |
| | | * @return string Quoted string for use in query |
| | | * @deprecated Replaced by rcube_db::quote_identifier |
| | | * @see rcube_db::quote_identifier |
| | | * @access public |
| | | */ |
| | | function quoteIdentifier($str) |
| | | { |
| | | return $this->quote_identifier($str); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Quotes a string so it can be safely used as a table or column name |
| | | * |
| | | * @param string Value to quote |
| | | * @return string Quoted string for use in query |
| | | * @access public |
| | | */ |
| | | function quote_identifier($str) |
| | | { |
| | | if (!$this->db_handle) |
| | | $this->db_connect('r'); |
| | | |
| | | return $this->db_handle->quoteIdentifier($str); |
| | | } |
| | | |
| | | |
| | | function quote_identifier($str) |
| | | { |
| | | return $this->quoteIdentifier($str); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Return SQL statement to convert a field value into a unix timestamp |
| | | * |
| | | * @param string Field name |
| | | * @return string SQL statement to use in query |
| | | * @access public |
| | | */ |
| | | function unixtimestamp($field) |
| | | { |
| | | switch($this->db_provider) |
| | |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Return SQL statement to convert from a unix timestamp |
| | | * |
| | | * @param string Field name |
| | | * @return string SQL statement to use in query |
| | | * @access public |
| | | */ |
| | | function fromunixtime($timestamp) |
| | | { |
| | | switch($this->db_provider) |
| | |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Adds a query result and returns a handle ID |
| | | * |
| | | * @param object Query handle |
| | | * @return mixed Handle ID or FALE on failure |
| | | * @access private |
| | | */ |
| | | function _add_result($res) |
| | | { |
| | | // sql error occured |
| | | if (DB::isError($res)) |
| | | { |
| | | raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, |
| | | 'message' => $res->getMessage() . " Query: " . substr(preg_replace('/[\r\n]+\s*/', ' ', $res->userinfo), 0, 1024)), TRUE, FALSE); |
| | | 'message' => $res->getMessage() . " Query: " . substr(preg_replace('/[\r\n]+\s*/', ' ', $res->userinfo), 0, 512)), TRUE, FALSE); |
| | | return FALSE; |
| | | } |
| | | else |
| | |
| | | } |
| | | |
| | | |
| | | function _get_result($res_id) |
| | | /** |
| | | * Resolves a given handle ID and returns the according query handle |
| | | * If no ID is specified, the last ressource handle will be returned |
| | | * |
| | | * @param number Handle ID |
| | | * @return mixed Ressource handle or FALE on failure |
| | | * @access private |
| | | */ |
| | | function _get_result($res_id=NULL) |
| | | { |
| | | if ($res_id==NULL) |
| | | $res_id = $this->last_res_id; |
| | |
| | | } |
| | | |
| | | |
| | | // create a sqlite database from a file |
| | | function _sqlite_create_database($dbh, $fileName) |
| | | /** |
| | | * Create a sqlite database from a file |
| | | * |
| | | * @param object SQLite database handle |
| | | * @param string File path to use for DB creation |
| | | * @access private |
| | | */ |
| | | function _sqlite_create_database($dbh, $file_name) |
| | | { |
| | | if (empty($fileName) || !is_string($fileName)) |
| | | return ; |
| | | if (empty($file_name) || !is_string($file_name)) |
| | | return; |
| | | |
| | | $data = ''; |
| | | if ($fd = fopen($fileName, 'r')) |
| | | if ($fd = fopen($file_name, 'r')) |
| | | { |
| | | $data = fread($fd, filesize($fileName)); |
| | | $data = fread($fd, filesize($file_name)); |
| | | fclose($fd); |
| | | } |
| | | |
| | |
| | | sqlite_exec($dbh->connection, $data); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Add some proprietary database functions to the current SQLite handle |
| | | * in order to make it MySQL compatible |
| | | * |
| | | * @access private |
| | | */ |
| | | function _sqlite_prepare() |
| | | { |
| | | include_once('include/rcube_sqlite.inc'); |
| | |
| | | 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 |
| | | |
| | | ?> |
| | |
| | | */ |
| | | |
| | | |
| | | /** |
| | | * Obtain classes from the Iloha IMAP library |
| | | */ |
| | | require_once('lib/imap.inc'); |
| | | require_once('lib/mime.inc'); |
| | | require_once('lib/utf7.inc'); |
| | | |
| | | |
| | | /** |
| | | * Interface class for accessing an IMAP server |
| | | * |
| | | * This is a wrapper that implements the Iloha IMAP Library (IIL) |
| | | * |
| | | * @package RoundCube Webmail |
| | | * @author Thomas Bruederli <roundcube@gmail.com> |
| | | * @version 1.22 |
| | | * @link http://ilohamail.org |
| | | */ |
| | | class rcube_imap |
| | | { |
| | | var $db; |
| | |
| | | var $uid_id_map = array(); |
| | | var $msg_headers = array(); |
| | | var $capabilities = array(); |
| | | var $skip_deleted = FALSE; |
| | | var $debug_level = 1; |
| | | |
| | | |
| | | // PHP 5 constructor |
| | | /** |
| | | * Object constructor |
| | | * |
| | | * @param object Database connection |
| | | */ |
| | | function __construct($db_conn) |
| | | { |
| | | $this->db = $db_conn; |
| | | } |
| | | |
| | | // PHP 4 compatibility |
| | | |
| | | /** |
| | | * PHP 4 object constructor |
| | | * |
| | | * @see rcube_imap::__construct |
| | | */ |
| | | function rcube_imap($db_conn) |
| | | { |
| | | $this->__construct($db_conn); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Connect to an IMAP server |
| | | * |
| | | * @param string Host to connect |
| | | * @param string Username for IMAP account |
| | | * @param string Password for IMAP account |
| | | * @param number Port to connect to |
| | | * @param boolean Use SSL connection |
| | | * @return boolean TRUE on success, FALSE on failure |
| | | * @access public |
| | | */ |
| | | function connect($host, $user, $pass, $port=143, $use_ssl=FALSE) |
| | | { |
| | | global $ICL_SSL, $ICL_PORT, $CONFIG; |
| | | global $ICL_SSL, $ICL_PORT; |
| | | |
| | | // check for Open-SSL support in PHP build |
| | | if ($use_ssl && in_array('openssl', get_loaded_extensions())) |
| | | $ICL_SSL = TRUE; |
| | | else if ($use_ssl) |
| | | { |
| | | raise_error(array('code' => 403, |
| | | 'type' => 'imap', |
| | | 'file' => __FILE__, |
| | | raise_error(array('code' => 403, 'type' => 'imap', 'file' => __FILE__, |
| | | 'message' => 'Open SSL not available;'), TRUE, FALSE); |
| | | $port = 143; |
| | | } |
| | |
| | | $this->ssl = $use_ssl; |
| | | |
| | | // print trace mesages |
| | | if ($this->conn && ($CONFIG['debug_level'] & 8)) |
| | | if ($this->conn && ($this->debug_level & 8)) |
| | | console($this->conn->message); |
| | | |
| | | // write error log |
| | |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Close IMAP connection |
| | | * Usually done on script shutdown |
| | | * |
| | | * @access public |
| | | */ |
| | | function close() |
| | | { |
| | | if ($this->conn) |
| | |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Close IMAP connection and re-connect |
| | | * This is used to avoid some strange socket errors when talking to Courier IMAP |
| | | * |
| | | * @access public |
| | | */ |
| | | function reconnect() |
| | | { |
| | | $this->close(); |
| | |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Set a root folder for the IMAP connection. |
| | | * |
| | | * Only folders within this root folder will be displayed |
| | | * and all folder paths will be translated using this folder name |
| | | * |
| | | * @param string Root folder |
| | | * @access public |
| | | */ |
| | | function set_rootdir($root) |
| | | { |
| | | if (ereg('[\.\/]$', $root)) //(substr($root, -1, 1)==='/') |
| | |
| | | } |
| | | |
| | | |
| | | /** |
| | | * This list of folders will be listed above all other folders |
| | | * |
| | | * @param array Indexed list of folder names |
| | | * @access public |
| | | */ |
| | | function set_default_mailboxes($arr) |
| | | { |
| | | if (is_array($arr)) |
| | |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Set internal mailbox reference. |
| | | * |
| | | * All operations will be perfomed on this mailbox/folder |
| | | * |
| | | * @param string Mailbox/Folder name |
| | | * @access public |
| | | */ |
| | | function set_mailbox($mbox) |
| | | { |
| | | $mailbox = $this->_mod_mailbox($mbox); |
| | |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Set internal list page |
| | | * |
| | | * @param number Page number to list |
| | | * @access public |
| | | */ |
| | | function set_page($page) |
| | | { |
| | | $this->list_page = (int)$page; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Set internal page size |
| | | * |
| | | * @param number Number of messages to display on one page |
| | | * @access public |
| | | */ |
| | | function set_pagesize($size) |
| | | { |
| | | $this->page_size = (int)$size; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Returns the currently used mailbox name |
| | | * |
| | | * @return string Name of the mailbox/folder |
| | | * @access public |
| | | */ |
| | | function get_mailbox_name() |
| | | { |
| | | return $this->conn ? $this->_mod_mailbox($this->mailbox, 'out') : ''; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Returns the IMAP server's capability |
| | | * |
| | | * @param string Capability name |
| | | * @return mixed Capability value or TRUE if supported, FALSE if not |
| | | * @access public |
| | | */ |
| | | function get_capability($cap) |
| | | { |
| | | $cap = strtoupper($cap); |
| | |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Returns the delimiter that is used by the IMAP server for folder separation |
| | | * |
| | | * @return string Delimiter string |
| | | * @access public |
| | | */ |
| | | function get_hierarchy_delimiter() |
| | | { |
| | | if ($this->conn && empty($this->delimiter)) |
| | |
| | | return $this->delimiter; |
| | | } |
| | | |
| | | // public method for mailbox listing |
| | | // convert mailbox name with root dir first |
| | | |
| | | /** |
| | | * Public method for mailbox listing. |
| | | * |
| | | * Converts mailbox name with root dir first |
| | | * |
| | | * @param string Optional root folder |
| | | * @param string Optional filter for mailbox listing |
| | | * @return array List of mailboxes/folders |
| | | * @access public |
| | | */ |
| | | function list_mailboxes($root='', $filter='*') |
| | | { |
| | | $a_out = array(); |
| | |
| | | return $a_out; |
| | | } |
| | | |
| | | // private method for mailbox listing |
| | | |
| | | /** |
| | | * Private method for mailbox listing |
| | | * |
| | | * @return array List of mailboxes/folders |
| | | * @access private |
| | | * @see rcube_imap::list_mailboxes |
| | | */ |
| | | function _list_mailboxes($root='', $filter='*') |
| | | { |
| | | $a_defaults = $a_out = array(); |
| | |
| | | } |
| | | |
| | | |
| | | // get message count for a specific mailbox; acceptes modes are: ALL, UNSEEN |
| | | // get message count for a specific mailbox; acceptes modes are: ALL, UNSEEN, RECENT |
| | | function messagecount($mbox='', $mode='ALL', $force=FALSE) |
| | | { |
| | | $mailbox = $mbox ? $this->_mod_mailbox($mbox) : $this->mailbox; |
| | |
| | | $a_mailbox_cache = FALSE; |
| | | $mode = strtoupper($mode); |
| | | |
| | | if (!$mailbox) |
| | | if (empty($mailbox)) |
| | | $mailbox = $this->mailbox; |
| | | |
| | | $a_mailbox_cache = $this->get_cache('messagecount'); |
| | |
| | | // return cached value |
| | | if (!$force && is_array($a_mailbox_cache[$mailbox]) && isset($a_mailbox_cache[$mailbox][$mode])) |
| | | return $a_mailbox_cache[$mailbox][$mode]; |
| | | |
| | | $search_str = "ALL UNDELETED"; |
| | | |
| | | // get message count and store in cache |
| | | if ($mode == 'UNSEEN') |
| | | $search_str .= " UNSEEN"; |
| | | // RECENT count is fetched abit different |
| | | if ($mode == 'RECENT') |
| | | $count = iil_C_CheckForRecent($this->conn, $mailbox); |
| | | |
| | | // get message count using SEARCH |
| | | // not very performant but more precise (using UNDELETED) |
| | | $count = 0; |
| | | $index = $this->_search_index($mailbox, $search_str); |
| | | if (is_array($index)) |
| | | // use SEARCH for message counting |
| | | else if ($this->skip_deleted) |
| | | { |
| | | $str = implode(",", $index); |
| | | if (!empty($str)) |
| | | $count = count($index); |
| | | $search_str = "ALL UNDELETED"; |
| | | |
| | | // get message count and store in cache |
| | | if ($mode == 'UNSEEN') |
| | | $search_str .= " UNSEEN"; |
| | | |
| | | // get message count using SEARCH |
| | | // not very performant but more precise (using UNDELETED) |
| | | $count = 0; |
| | | $index = $this->_search_index($mailbox, $search_str); |
| | | if (is_array($index)) |
| | | { |
| | | $str = implode(",", $index); |
| | | if (!empty($str)) |
| | | $count = count($index); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | if ($mode == 'UNSEEN') |
| | | $count = iil_C_CountUnseen($this->conn, $mailbox); |
| | | else |
| | | $count = iil_C_CountMessages($this->conn, $mailbox); |
| | | } |
| | | |
| | | if (is_array($a_mailbox_cache[$mailbox])) |
| | |
| | | else |
| | | { |
| | | $begin = $start_msg; |
| | | $end = $start_msg + $this->page_size; |
| | | $end = $start_msg + $this->page_size; |
| | | } |
| | | |
| | | if ($begin < 0) $begin = 0; |
| | |
| | | else |
| | | { |
| | | // retrieve headers from IMAP |
| | | if ($this->get_capability('sort') && ($msg_index = iil_C_Sort($this->conn, $mailbox, $this->sort_field))) |
| | | if ($this->get_capability('sort') && ($msg_index = iil_C_Sort($this->conn, $mailbox, $this->sort_field, $this->skip_deleted ? 'UNDELETED' : ''))) |
| | | { |
| | | //console("$mailbox: ".count($msg_index)); |
| | | //console("$mailbox: ".join(',', $msg_index)); |
| | | |
| | | $msgs = $msg_index[$begin]; |
| | | for ($i=$begin; $i < $end; $i++) |
| | | for ($i=$begin+1; $i < $end; $i++) |
| | | { |
| | | if ($this->sort_order == 'DESC') |
| | | $msgs = $msg_index[$i].','.$msgs; |
| | | else |
| | | //if ($this->sort_order == 'DESC') |
| | | // $msgs = $msg_index[$i].','.$msgs; |
| | | //else |
| | | $msgs = $msgs.','.$msg_index[$i]; |
| | | } |
| | | |
| | |
| | | return $this->_list_headers($mailbox, $page, $this->sort_field, $this->sort_order, TRUE); |
| | | } |
| | | |
| | | |
| | | // 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(); |
| | | $deleted_count = 0; |
| | | |
| | | if (!empty($a_header_index)) |
| | | { |
| | | foreach ($a_header_index as $i => $headers) |
| | | { |
| | | if ($headers->deleted) |
| | | { |
| | | // delete from cache |
| | | if ($cache_index[$headers->id] && $cache_index[$headers->id] == $headers->uid) |
| | | $this->remove_message_cache($cache_key, $headers->id); |
| | | |
| | | $deleted_count++; |
| | | continue; |
| | | } |
| | | |
| | | // add message to cache |
| | | if ($this->caching_enabled && $cache_index[$headers->id] != $headers->uid) |
| | | $this->add_message_cache($cache_key, $headers->id, $headers); |
| | | |
| | | $a_msg_headers[$headers->uid] = $headers; |
| | | } |
| | | } |
| | | $deleted_count = $this->_fetch_headers($mailbox, $msgs, $a_msg_headers, $cache_key); |
| | | |
| | | // delete cached messages with a higher index than $max |
| | | $this->clear_message_cache($cache_key, $max); |
| | | |
| | | |
| | | // fetch more headers of there were any deleted messages |
| | | // ... |
| | | |
| | | |
| | | // kick child process to sync cache |
| | | // ... |
| | | |
| | |
| | | |
| | | return array_values($a_msg_headers); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Fetches message headers |
| | | * Used for loop |
| | | * |
| | | * @param string Mailbox name |
| | | * @param string Message indey to fetch |
| | | * @param array Reference to message headers array |
| | | * @param array Array with cache index |
| | | * @return number Number of deleted messages |
| | | * @access private |
| | | */ |
| | | function _fetch_headers($mailbox, $msgs, &$a_msg_headers, $cache_key) |
| | | { |
| | | // 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); |
| | | $deleted_count = 0; |
| | | |
| | | if (!empty($a_header_index)) |
| | | { |
| | | foreach ($a_header_index as $i => $headers) |
| | | { |
| | | if ($headers->deleted && $this->skip_deleted) |
| | | { |
| | | // delete from cache |
| | | if ($cache_index[$headers->id] && $cache_index[$headers->id] == $headers->uid) |
| | | $this->remove_message_cache($cache_key, $headers->id); |
| | | |
| | | $deleted_count++; |
| | | continue; |
| | | } |
| | | |
| | | // add message to cache |
| | | if ($this->caching_enabled && $cache_index[$headers->id] != $headers->uid) |
| | | $this->add_message_cache($cache_key, $headers->id, $headers); |
| | | |
| | | $a_msg_headers[$headers->uid] = $headers; |
| | | } |
| | | } |
| | | |
| | | return $deleted_count; |
| | | } |
| | | |
| | | |
| | | |
| | | // return sorted array of message UIDs |
| | |
| | | } |
| | | |
| | | |
| | | function get_headers($uid, $mbox=NULL) |
| | | function get_headers($id, $mbox=NULL, $is_uid=TRUE) |
| | | { |
| | | $mailbox = $mbox ? $this->_mod_mailbox($mbox) : $this->mailbox; |
| | | |
| | |
| | | if ($headers = $this->get_cached_message($mailbox.'.msg', $uid)) |
| | | return $headers; |
| | | |
| | | $msg_id = $this->_uid2id($uid); |
| | | $msg_id = $is_uid ? $this->_uid2id($id) : $id; |
| | | $headers = iil_C_FetchHeader($this->conn, $mailbox, $msg_id); |
| | | |
| | | // write headers cache |
| | |
| | | |
| | | |
| | | // clear all messages in a specific mailbox |
| | | function clear_mailbox($mbox) |
| | | function clear_mailbox($mbox=NULL) |
| | | { |
| | | $mailbox = $mbox ? $this->_mod_mailbox($mbox) : $this->mailbox; |
| | | $mailbox = !empty($mbox) ? $this->_mod_mailbox($mbox) : $this->mailbox; |
| | | $msg_count = $this->_messagecount($mailbox, 'ALL'); |
| | | |
| | | if ($msg_count>0) |
| | |
| | | $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), |
| | | substr($this->decode_header($headers->subject, TRUE), 0, 128), |
| | | substr($this->decode_header($headers->from, TRUE), 0, 128), |
| | | substr($this->decode_header($headers->to, TRUE), 0, 128), |
| | | substr($this->decode_header($headers->cc, TRUE), 0, 128), |
| | | (int)$headers->size, |
| | | serialize($headers)); |
| | | } |
| | |
| | | | Copyright (C) 2005, RoundCube Dev, - Switzerland | |
| | | | Licensed under the GNU GPL | |
| | | | | |
| | | | Modified: 2005/12/16 (roundcube) | |
| | | | | |
| | | +-----------------------------------------------------------------------+ |
| | | | Author: Thomas Bruederli <roundcube@gmail.com> | |
| | | +-----------------------------------------------------------------------+ |
| | | |
| | | $Id$ |
| | | */ |
| | | |
| | | |
| | |
| | | this.enable_command('add-attachment', 'send-attachment', 'send', true); |
| | | |
| | | if (this.env.messagecount) |
| | | this.enable_command('select-all', 'select-none', 'sort', true); |
| | | this.enable_command('select-all', 'select-none', 'sort', 'expunge', true); |
| | | |
| | | this.set_page_buttons(); |
| | | |
| | |
| | | // show printing dialog |
| | | if (this.env.action=='print') |
| | | window.print(); |
| | | |
| | | // get unread count for each mailbox |
| | | if (this.gui_objects.mailboxlist) |
| | | this.http_request('getunread', ''); |
| | | |
| | | break; |
| | | |
| | |
| | | if (this.pending_message) |
| | | this.display_message(this.pending_message[0], this.pending_message[1]); |
| | | |
| | | // start interval for keep-alive siganl |
| | | // start interval for keep-alive/recent_check signal |
| | | if (this.kepp_alive_interval) |
| | | this.kepp_alive_int = setInterval(this.ref+'.send_keep_alive()', this.kepp_alive_interval); |
| | | this.kepp_alive_int = setInterval(this.ref+'.'+(this.task=='mail'?'check_for_recent()':'send_keep_alive()'), this.kepp_alive_interval); |
| | | }; |
| | | |
| | | |
| | |
| | | |
| | | return false; |
| | | } |
| | | |
| | | |
| | | // check input before leaving compose step |
| | | if (this.task=='mail' && this.env.action=='compose' && (command=='list' || command=='mail' || command=='addressbook' || command=='settings')) |
| | | { |
| | | if (this.cmp_hash != this.compose_field_hash() && !confirm(this.get_label('notsentwarning'))) |
| | | return false; |
| | | } |
| | | |
| | | |
| | | // process command |
| | | switch (command) |
| | |
| | | // misc list commands |
| | | case 'list': |
| | | if (this.task=='mail') |
| | | { |
| | | // check input before leaving compose step |
| | | if (this.env.action=='compose' && this.cmp_hash != this.compose_field_hash() && !confirm(this.get_label('notsentwarning'))) |
| | | break; |
| | | |
| | | this.list_mailbox(props); |
| | | } |
| | | else if (this.task=='addressbook') |
| | | this.list_contacts(); |
| | | break; |
| | |
| | | |
| | | case 'previouspage': |
| | | this.list_page('prev'); |
| | | break; |
| | | |
| | | case 'expunge': |
| | | if (this.env.messagecount) |
| | | this.expunge_mailbox(this.env.mailbox); |
| | | break; |
| | | |
| | | case 'clear-mailbox': |
| | | //if (this.env.messagecount) |
| | | //this.clear_mailbox(this.env.mailbox); |
| | | break; |
| | | |
| | | |
| | |
| | | // send remote request to load message list |
| | | this.list_mailbox_remote = function(mbox, page, add_url) |
| | | { |
| | | // clear message list |
| | | // clear message list first |
| | | this.clear_message_list(); |
| | | |
| | | // send request to server |
| | | var url = '_mbox='+escape(mbox)+(page ? '&_page='+page : ''); |
| | | this.set_busy(true, 'loading'); |
| | | this.http_request('list', url+add_url, true); |
| | | }; |
| | | |
| | | |
| | | this.clear_message_list = function() |
| | | { |
| | | var table = this.gui_objects.messagelist; |
| | | var tbody = document.createElement('TBODY'); |
| | | table.insertBefore(tbody, table.tBodies[0]); |
| | |
| | | |
| | | this.message_rows = new Array(); |
| | | this.list_rows = this.message_rows; |
| | | |
| | | }; |
| | | |
| | | |
| | | this.expunge_mailbox = function(mbox) |
| | | { |
| | | var lock = false; |
| | | var add_url = ''; |
| | | |
| | | // lock interface if it's the active mailbox |
| | | if (mbox == this.env.mailbox) |
| | | { |
| | | lock = true; |
| | | this.set_busy(true, 'loading'); |
| | | add_url = '&_reload=1'; |
| | | } |
| | | |
| | | // send request to server |
| | | var url = '_mbox='+escape(mbox)+(page ? '&_page='+page : ''); |
| | | this.set_busy(true, 'loading'); |
| | | this.http_request('list', url+add_url, true); |
| | | var url = '_mbox='+escape(mbox); |
| | | this.http_request('expunge', url+add_url, lock); |
| | | }; |
| | | |
| | | |
| | |
| | | |
| | | |
| | | // create a table row in the message list |
| | | this.add_message_row = function(uid, cols, flags, attachment) |
| | | this.add_message_row = function(uid, cols, flags, attachment, attop) |
| | | { |
| | | if (!this.gui_objects.messagelist || !this.gui_objects.messagelist.tBodies[0]) |
| | | return false; |
| | |
| | | |
| | | var row = document.createElement('TR'); |
| | | row.id = 'rcmrow'+uid; |
| | | row.className = 'message '+(even ? 'even' : 'odd')+(flags.unread ? ' unread' : ''); |
| | | |
| | | row.className = 'message '+(even ? 'even' : 'odd')+(flags.unread ? ' unread' : '')+(flags.deleted ? ' deleted' : ''); |
| | | |
| | | if (this.in_selection(uid)) |
| | | row.className += ' selected'; |
| | | |
| | |
| | | col.innerHTML = attachment && this.env.attachmenticon ? '<img src="'+this.env.attachmenticon+'" alt="" border="0" />' : ''; |
| | | row.appendChild(col); |
| | | |
| | | tbody.appendChild(row); |
| | | if (attop && tbody.rows.length) |
| | | tbody.insertBefore(row, tbody.firstChild); |
| | | else |
| | | tbody.appendChild(row); |
| | | |
| | | this.init_message_row(row); |
| | | }; |
| | | |
| | |
| | | |
| | | |
| | | // update the mailboxlist |
| | | this.set_unread_count = function(mbox, count) |
| | | this.set_unread_count = function(mbox, count, set_title) |
| | | { |
| | | if (!this.gui_objects.mailboxlist) |
| | | return false; |
| | | |
| | | mbox = String(mbox).toLowerCase().replace(this.mbox_expression, ''); |
| | | |
| | | var item, reg, text_obj; |
| | | for (var n=0; n<this.gui_objects.mailboxlist.childNodes.length; n++) |
| | | mbox = String(mbox).toLowerCase().replace(this.mbox_expression, ''); |
| | | item = document.getElementById('rcmbx'+mbox); |
| | | |
| | | if (item && item.className && item.className.indexOf('mailbox '+mbox)>=0) |
| | | { |
| | | item = this.gui_objects.mailboxlist.childNodes[n]; |
| | | // set new text |
| | | text_obj = item.firstChild; |
| | | reg = /\s+\([0-9]+\)$/i; |
| | | |
| | | if (item.className && item.className.indexOf('mailbox '+mbox)>=0) |
| | | { |
| | | // set new text |
| | | text_obj = item.firstChild; |
| | | reg = /\s+\([0-9]+\)$/i; |
| | | |
| | | if (count && text_obj.innerHTML.match(reg)) |
| | | text_obj.innerHTML = text_obj.innerHTML.replace(reg, ' ('+count+')'); |
| | | else if (count) |
| | | text_obj.innerHTML += ' ('+count+')'; |
| | | else |
| | | text_obj.innerHTML = text_obj.innerHTML.replace(reg, ''); |
| | | if (count && text_obj.innerHTML.match(reg)) |
| | | text_obj.innerHTML = text_obj.innerHTML.replace(reg, ' ('+count+')'); |
| | | else if (count) |
| | | text_obj.innerHTML += ' ('+count+')'; |
| | | else |
| | | text_obj.innerHTML = text_obj.innerHTML.replace(reg, ''); |
| | | |
| | | // set the right classes |
| | | this.set_classname(item, 'unread', count>0 ? true : false); |
| | | break; |
| | | } |
| | | // set the right classes |
| | | this.set_classname(item, 'unread', count>0 ? true : false); |
| | | } |
| | | |
| | | // set unread count to window title |
| | | if (set_title && document.title) |
| | | { |
| | | var doc_title = String(document.title); |
| | | reg = /^\([0-9]+\)\s+/i; |
| | | |
| | | if (count && doc_title.match(reg)) |
| | | document.title = doc_title.replace(reg, '('+count+') '); |
| | | else if (count) |
| | | document.title = '('+count+') '+doc_title; |
| | | else |
| | | document.title = doc_title.replace(reg, ''); |
| | | } |
| | | }; |
| | | |
| | |
| | | if (this.env.action=='show') |
| | | this.command('list'); |
| | | break; |
| | | |
| | | |
| | | case 'list': |
| | | this.enable_command('select-all', 'select-none', this.env.messagecount ? true : false); |
| | | case 'expunge': |
| | | this.enable_command('select-all', 'select-none', 'expunge', this.env.messagecount ? true : false); |
| | | break; |
| | | } |
| | | |
| | |
| | | var d = new Date(); |
| | | this.http_request('keep-alive', '_t='+d.getTime()); |
| | | }; |
| | | |
| | | |
| | | // send periodic request to check for recent messages |
| | | this.check_for_recent = function() |
| | | { |
| | | var d = new Date(); |
| | | this.http_request('check-recent', '_t='+d.getTime()); |
| | | }; |
| | | |
| | | |
| | | /********************************************************/ |
| | |
| | | { |
| | | if (input && window.RegExp) |
| | | { |
| | | var reg_str = '([a-z0-9][-a-z0-9\.\+_]*)\@([a-z0-9]([-a-z0-9][\.]?)*[a-z0-9]\.[a-z]{2,9})'; |
| | | var reg_str = '([a-z0-9][-a-z0-9\.\+_]*)\@(([-a-z0-9][\.]?)*[a-z0-9]\.[a-z]{2,9})'; |
| | | var reg1 = inline ? new RegExp(reg_str, 'i') : new RegExp('^'+reg_str+'$', 'i'); |
| | | var reg2 = /[\._\-\@]{2}/; |
| | | return reg1.test(input) && !reg2.test(input) ? true : false; |
| | |
| | | return $time2; |
| | | } |
| | | |
| | | function iil_C_Sort(&$conn, $mailbox, $field){ |
| | | function iil_C_Sort(&$conn, $mailbox, $field, $add=''){ |
| | | /* Do "SELECT" command */ |
| | | if (!iil_C_Select($conn, $mailbox)) return false; |
| | | |
| | |
| | | if (!$fields[$field]) return false; |
| | | |
| | | $fp = $conn->fp; |
| | | $command = 's SORT ('.$field.') US-ASCII ALL UNDELETED'."\r\n"; |
| | | $command = 's SORT ('.$field.') US-ASCII ALL '."$add\r\n"; |
| | | //$command = 's SORT ('.$field.') US-ASCII ALL UNDELETED'."\r\n"; |
| | | $line = $data = ''; |
| | | |
| | | if (!fputs($fp, $command)) return false; |
| | |
| | | $labels['none'] = 'Keine'; |
| | | $labels['unread'] = 'Ungelesene'; |
| | | |
| | | $labels['compact'] = 'Packen'; |
| | | |
| | | |
| | | // message compose // Nachrichten erstellen |
| | | $labels['compose'] = 'Neue Nachricht verfassen'; |
| | | $labels['sendmessage'] = 'Nachricht jetzt senden'; |
| | |
| | | $labels['pagesize'] = 'Einträge pro Seite'; |
| | | $labels['signature'] = 'Signatur'; |
| | | |
| | | $labels['folder'] = 'Ordner'; |
| | | $labels['folders'] = 'Ordner'; |
| | | $labels['foldername'] = 'Ordnername'; |
| | | $labels['subscribed'] = 'Abonniert'; |
| | |
| | | $labels['none'] = 'None'; |
| | | $labels['unread'] = 'Unread'; |
| | | |
| | | $labels['compact'] = 'Compact'; |
| | | |
| | | |
| | | // message compose |
| | | $labels['compose'] = 'Compose a message'; |
| | | $labels['sendmessage'] = 'Send the message now'; |
| | |
| | | $labels['pagesize'] = 'Rows per page'; |
| | | $labels['signature'] = 'Signature'; |
| | | |
| | | $labels['folder'] = 'Folder'; |
| | | $labels['folders'] = 'Folders'; |
| | | $labels['foldername'] = 'Folder name'; |
| | | $labels['subscribed'] = 'Subscribed'; |
New file |
| | |
| | | <?php |
| | | |
| | | /* |
| | | +-----------------------------------------------------------------------+ |
| | | | program/steps/mail/check_recent.inc | |
| | | | | |
| | | | This file is part of the RoundCube Webmail client | |
| | | | Copyright (C) 2005, RoundCube Dev. - Switzerland | |
| | | | Licensed under the GNU GPL | |
| | | | | |
| | | | PURPOSE: | |
| | | | Check for recent messages | |
| | | | | |
| | | +-----------------------------------------------------------------------+ |
| | | | Author: Thomas Bruederli <roundcube@gmail.com> | |
| | | +-----------------------------------------------------------------------+ |
| | | |
| | | $Id$ |
| | | |
| | | */ |
| | | |
| | | $REMOTE_REQUEST = TRUE; |
| | | $mbox = $IMAP->get_mailbox_name(); |
| | | |
| | | if ($recent_count = $IMAP->messagecount(NULL, 'RECENT')) |
| | | { |
| | | $count = $IMAP->messagecount(); |
| | | $unread_count = $IMAP->messagecount(NULL, 'UNSEEN'); |
| | | |
| | | $commands = sprintf("this.set_unread_count('%s', %d, true);\n", addslashes($mbox), $unread_count); |
| | | $commands .= sprintf("this.set_env('messagecount', %d);\n", $count); |
| | | $commands .= sprintf("this.set_rowcount('%s');\n", rcmail_get_messagecount_text()); |
| | | |
| | | // add new message headers to list |
| | | $a_headers = array(); |
| | | for ($i=$recent_count, $id=$count-$recent_count+1; $i>0; $i--, $id++) |
| | | $a_headers[] = $IMAP->get_headers($id, NULL, FALSE); |
| | | |
| | | $commands .= rcmail_js_message_list($a_headers, TRUE); |
| | | } |
| | | |
| | | if (strtoupper($mbox)!='INBOX' && $IMAP->messagecount('INBOX', 'RECENT')) |
| | | $commands = sprintf("this.set_unread_count('INBOX', %d);\n", $IMAP->messagecount('INBOX', 'UNSEEN')); |
| | | |
| | | |
| | | rcube_remote_response($commands); |
| | | ?> |
New file |
| | |
| | | <?php |
| | | |
| | | /* |
| | | +-----------------------------------------------------------------------+ |
| | | | program/steps/mail/folders.inc | |
| | | | | |
| | | | This file is part of the RoundCube Webmail client | |
| | | | Copyright (C) 2005, RoundCube Dev. - Switzerland | |
| | | | Licensed under the GNU GPL | |
| | | | | |
| | | | PURPOSE: | |
| | | | Implement folder operations line EXPUNGE and Clear | |
| | | | | |
| | | +-----------------------------------------------------------------------+ |
| | | | Author: Thomas Bruederli <roundcube@gmail.com> | |
| | | +-----------------------------------------------------------------------+ |
| | | |
| | | $Id$ |
| | | |
| | | */ |
| | | |
| | | $REMOTE_REQUEST = TRUE; |
| | | $mbox = $IMAP->get_mailbox_name(); |
| | | |
| | | |
| | | // send EXPUNGE command |
| | | if ($_action=='expunge') |
| | | { |
| | | $success = $IMAP->expunge(); |
| | | |
| | | // reload message list if current mailbox |
| | | if ($success && $_GET['_reload']) |
| | | { |
| | | rcube_remote_response('this.clear_message_list();', TRUE); |
| | | $_action = 'list'; |
| | | return; |
| | | } |
| | | else |
| | | $commands = "// expunged: $success\n"; |
| | | } |
| | | |
| | | // clear mailbox |
| | | else if ($_action=='purge') |
| | | { |
| | | $success = $IMAP->clear_mailbox(); |
| | | |
| | | if ($success && $_GET['_reload']) |
| | | { |
| | | $commands = "this.set_env('messagecount', 0);\n"; |
| | | $commands .= "this.set_env('pagecount', 0);\n"; |
| | | $commands .= sprintf("this.set_rowcount('%s');\n", rcmail_get_messagecount_text()); |
| | | $commands .= sprintf("this.set_unread_count('%s', 0);\n", addslashes($mbox)); |
| | | } |
| | | else |
| | | $commands = "// purged: $success"; |
| | | } |
| | | |
| | | |
| | | |
| | | rcube_remote_response($commands); |
| | | ?> |
| | |
| | | static $s_added_script = FALSE; |
| | | static $a_mailboxes; |
| | | |
| | | // $mboxlist_start = rcube_timer(); |
| | | |
| | | $type = $attrib['type'] ? $attrib['type'] : 'ul'; |
| | | $add_attrib = $type=='select' ? array('style', 'class', 'id', 'name', 'onchange') : |
| | | array('style', 'class', 'id'); |
| | |
| | | $a_folders = $IMAP->list_mailboxes(); |
| | | $delimiter = $IMAP->get_hierarchy_delimiter(); |
| | | $a_mailboxes = array(); |
| | | |
| | | |
| | | // rcube_print_time($mboxlist_start, 'list_mailboxes()'); |
| | | |
| | | foreach ($a_folders as $folder) |
| | | rcmail_build_folder_tree($a_mailboxes, $folder, $delimiter); |
| | | } |
| | |
| | | $out .= rcmail_render_folder_tree_select($a_mailboxes, $special_mailboxes, $mbox, $attrib['maxlength']); |
| | | else |
| | | $out .= rcmail_render_folder_tree_html($a_mailboxes, $special_mailboxes, $mbox, $attrib['maxlength']); |
| | | |
| | | // rcube_print_time($mboxlist_start, 'render_folder_tree()'); |
| | | |
| | | |
| | | if ($type=='ul') |
| | |
| | | } |
| | | |
| | | // add unread message count display |
| | | if ($unread_count = $IMAP->messagecount($folder['id'], 'UNSEEN', ($folder['id']==$mbox))) |
| | | if ($unread_count = $IMAP->messagecount($folder['id'], 'RECENT', ($folder['id']==$mbox))) |
| | | $foldername .= sprintf(' (%d)', $unread_count); |
| | | |
| | | // make folder name safe for ids and class names |
| | |
| | | if ($attrib['attachmenticon'] && preg_match("/multipart\/m/i", $header->ctype)) |
| | | $attach_icon = $attrib['attachmenticon']; |
| | | |
| | | $out .= sprintf('<tr id="rcmrow%d" class="message'.($header->seen ? '' : ' unread').' '.$zebra_class.'">'."\n", $header->uid); |
| | | $out .= sprintf('<tr id="rcmrow%d" class="message%s%s %s">'."\n", |
| | | $header->uid, |
| | | $header->seen ? '' : ' unread', |
| | | $header->deleted ? ' deleted' : '', |
| | | $zebra_class); |
| | | |
| | | $out .= sprintf("<td class=\"icon\">%s</td>\n", $message_icon ? sprintf($image_tag, $skin_path, $message_icon, '') : ''); |
| | | |
| | | // format each col |
| | |
| | | |
| | | $a_msg_flags['unread'] = $header->seen ? 0 : 1; |
| | | $a_msg_flags['replied'] = $header->answered ? 1 : 0; |
| | | |
| | | if ($header->deleted) |
| | | $a_msg_flags['deleted'] = 1; |
| | | |
| | | $commands .= sprintf("this.add_message_row(%s, %s, %s, %b);\n", |
| | | $commands .= sprintf("this.add_message_row(%s, %s, %s, %b, %b);\n", |
| | | $header->uid, |
| | | array2js($a_msg_cols), |
| | | array2js($a_msg_flags), |
| | | preg_match("/multipart\/m/i", $header->ctype)); |
| | | preg_match("/multipart\/m/i", $header->ctype), |
| | | $insert_top); |
| | | } |
| | | |
| | | return $commands; |
| | |
| | | // remove attachment files from temp dir |
| | | if (is_array($_SESSION['compose']['attachments'])) |
| | | foreach ($_SESSION['compose']['attachments'] as $attachment) |
| | | unlink($attachment['path']); |
| | | @unlink($attachment['path']); |
| | | |
| | | // kill temp dir |
| | | if ($_SESSION['compose']['temp_dir']) |
| | | rmdir($_SESSION['compose']['temp_dir']); |
| | | @rmdir($_SESSION['compose']['temp_dir']); |
| | | |
| | | unset($_SESSION['compose']); |
| | | } |
New file |
| | |
| | | <?php |
| | | |
| | | /* |
| | | +-----------------------------------------------------------------------+ |
| | | | program/steps/mail/getunread.inc | |
| | | | | |
| | | | This file is part of the RoundCube Webmail client | |
| | | | Copyright (C) 2005, RoundCube Dev. - Switzerland | |
| | | | Licensed under the GNU GPL | |
| | | | | |
| | | | PURPOSE: | |
| | | | Check all mailboxes for unread messages and update GUI | |
| | | | | |
| | | +-----------------------------------------------------------------------+ |
| | | | Author: Thomas Bruederli <roundcube@gmail.com> | |
| | | +-----------------------------------------------------------------------+ |
| | | |
| | | $Id$ |
| | | |
| | | */ |
| | | |
| | | $REMOTE_REQUEST = TRUE; |
| | | |
| | | $a_folders = $IMAP->list_mailboxes(); |
| | | |
| | | if (!empty($a_folders)) |
| | | { |
| | | foreach ($a_folders as $mbox) |
| | | { |
| | | $commands = sprintf("this.set_unread_count('%s', %d);\n", $mbox, $IMAP->messagecount($mbox, 'UNSEEN')); |
| | | rcube_remote_response($commands, TRUE); |
| | | } |
| | | } |
| | | |
| | | exit; |
| | | ?> |
| | |
| | | { |
| | | // unset some headers because they will be added by the mail() function |
| | | $headers_php = $headers; |
| | | $headers_enc = $MAIL_MIME->headers($headers); |
| | | unset($headers_php['To'], $headers_php['Subject']); |
| | | |
| | | // reset stored headers and overwrite |
| | | $MAIL_MIME->_headers = array(); |
| | | $header_str = $MAIL_MIME->txtHeaders($headers_php); |
| | | |
| | | if(ini_get('safe_mode')) |
| | | $sent = mail($mailto, $msg_subject, $msg_body, $header_str); |
| | | else |
| | | $sent = mail($mailto, $msg_subject, $msg_body, $header_str, "-f$from"); |
| | | $sent = mail($headers_enc['To'], $headers_enc['Subject'], $msg_body, $header_str); |
| | | else |
| | | $sent = mail($headers_enc['To'], $headers_enc['Subject'], $msg_body, $header_str, "-f$from"); |
| | | } |
| | | |
| | | |
| | |
| | | foreach ($_FILES['_attachments']['tmp_name'] as $i => $filepath) |
| | | { |
| | | $tmpfname = tempnam($temp_dir, 'rcmAttmnt'); |
| | | if (copy($filepath, $tmpfname)) |
| | | if (move_uploaded_file($filepath, $tmpfname)) |
| | | { |
| | | $_SESSION['compose']['attachments'][] = array('name' => $_FILES['_attachments']['name'][$i], |
| | | 'mimetype' => $_FILES['_attachments']['type'][$i], |
| | |
| | | |
| | | #listcontrols a, |
| | | #listcontrols a:active, |
| | | #listcontrols a:visited |
| | | #listcontrols a:visited, |
| | | #mailboxcontrols a, |
| | | #mailboxcontrols a:active, |
| | | #mailboxcontrols a:visited |
| | | { |
| | | color: #999999; |
| | | font-size: 11px; |
| | |
| | | |
| | | #listcontrols a.active, |
| | | #listcontrols a.active:active, |
| | | #listcontrols a.active:visited |
| | | #listcontrols a.active:visited, |
| | | #mailboxcontrols a.active, |
| | | #mailboxcontrols a.active:active, |
| | | #mailboxcontrols a.active:visited |
| | | { |
| | | color: #CC0000; |
| | | } |
| | | |
| | | #listcontrols a.active:hover |
| | | #listcontrols a.active:hover, |
| | | #mailboxcontrols a.active:hover |
| | | { |
| | | text-decoration: underline; |
| | | } |
| | |
| | | } |
| | | |
| | | |
| | | #mailboxcontrols |
| | | { |
| | | position: absolute; |
| | | left: 20px; |
| | | width: 160px; |
| | | bottom: 20px; |
| | | height: 16px; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | |
| | | /** message list styles */ |
| | | |
| | | body.messagelist |
| | |
| | | color: #FFFFFF; |
| | | } |
| | | |
| | | #messagelist tr.deleted td, |
| | | #messagelist tr.deleted td a |
| | | { |
| | | color: #CCCCCC; |
| | | } |
| | | |
| | | |
| | | /** message view styles */ |
| | | |
| | |
| | | <div id="mailboxlist-header"><roundcube:label name="mailboxlist" /></div> |
| | | <div id="mailboxlist-container"><roundcube:object name="mailboxlist" id="mailboxlist" maxlength="16" /></div> |
| | | |
| | | <div id="mailboxcontrols"> |
| | | <roundcube:label name="folder" />: |
| | | <roundcube:button command="expunge" label="compact" classAct="active" /> |
| | | </div> |
| | | |
| | | |
| | | <div id="mailcontframe"> |
| | | <roundcube:object name="messages" |