Page MenuHomePhorge

No OneTemporary

Size
207 KB
Referenced Files
None
Subscribers
None
diff --git a/CHANGELOG b/CHANGELOG
index df1546338..bfca82ee4 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,343 +1,345 @@
CHANGELOG RoundCube Webmail
---------------------------
2006/07/30 (thomasb)
----------
- Alter links in HTML messages (Bug #1326402)
- Added fallback if host not found in 'mail_domain' array
- Applied patch of Charles to highlight droptargets (Ticket #1473034)
+- Fixed folder renaming (Bug #1483914)
+- Added confirmation message after deleting a folder
2006/07/25 (thomasb)
----------
- Made folder renaming a bit more ajax-style
- Changed rename-labels and German translation
- Fixed addressbox countbar width (Bug #1483845)
- Fixed refresh interval problems in Safari (Bug #1483902)
- Fixed clear_message_list_header() errors (Bug #1483898)
- Sanity check of $message_set in imap.inc (Bug #1443200)
- Added correct changing of message list headers for Sent folder
- Updated Spanish localization (Ticket #1483887)
- Applied patch #1483846
2006/07/24 (richs)
----------
- Draft window no longer reloads. It saves to an iframe in the background instead (fixes bug #1483869)
- Draft timer now part of program/js/app.js instead of skins/default/templates/compose.inc
- Draft saving now properly returns an error when saving fails
- Draft timer stops and resets properly when attachments are uploaded, or when saving manually
- Old compose session/attachments are now cleaned up when a new/forward/reply/draft is made/opened
2006/07/19 (thomasb)
----------
- Correct entity encoding of link urls (HTML validity)
- Improved usability in compose step (Ticket #1483807)
- Added absolute URLs to several buttons (for "open in new window")
- Applied patch #1328032
- Fixed Bug/Patch #1443200
2006/07/18 (thomasb)
----------
- Fixed password with spaces issue (Bug #1364122)
- Replaced _auth hash with second cookie (Ticket #1483811)
- Don't use get_input_value() for passwords (Bug #1468895)
- Made password encryption key configurable
- Minor bugfixes with charset encoding
- Added <label> tags to forms (Ticket #1483810)
2006/07/07 (thomasb)
----------
- Fixed INSTALL_PATH bug #1425663
2006/07/03 (richs)
----------
- Fixed compatibility with in-body email addresses containing "+" (Bug #1483836)
- Updated French localizations (Ticket #1483862)
- Incoming messages can now be moved to Drafts, edited, saved, then moved back (Feature #1436191)
- Added Firefox workaround when clicking whitespace to drag messages (Bug #1483857)
- Corrected Dutch and Italian localizations (Ticket #1483851 and #1483848)
- Enabled 'Empty' (purge) command for Junk mailbox (defined in main.inc.php)
2006/06/30 (richs)
----------
- Fixed empty INBOX compatibility bug (Patch #1443200)
- Temporarily fixed French "compact" localization (Patch #1483862)
- Fixed "Select All" not working with Delete interface button (Bug #1332434)
- Fixed messsage list column compatibility with Konqueror (Bug #1395711)
- Fixed "unread count" in window title when count changed (Bug #1483812)
- Fixed DB error when deleting from message table (Patch #1483835)
2006/06/29 (richs)
----------
- Added ability to remove attachments (Feature #1436721)
- Default folders are now auto-created on first login (Feature #1471594)
- Fixed compatibility with folder apostrophes (e.g.: Joe's Folder) (Bug #1429458)
- Corrected Italian localizations
- Tweaked rename-folder form to clear after a rename
2006/06/26 (richs)
----------
- Added button to immediately check for new messages
- New message checking now displays status "Checking for new messages..."
- New message checking now looks for unread messages in all mailboxes (Feature #1326401)
- Task buttons now respond to clicks by darkening (as in other applications)
- Fixed "Sender" column changing to "Recipient" for "Sent" and "Drafts" message lists
- Added ability to sort messages by "Size"
- Added ability to rename folders (Feature #1326396)
- Added 'protect_default_folders' option to main.inc.php to prevent renames/deletes/unsubscribes of default folders
- Corrected 5 typos of "INSTLL" to "INSTALL" in program/include/main.inc
2006/06/25
----------
- Changed behavior to include host-specific configuration (Bug #1483849)
- Assume ISO-8859-1 encoding of mail messages by default (Patch #1483839)
- Fixed spell checker to work with the new URL at google.com
- Some memory and security optimizations sendmail.inc
- Updated UGRADING description
2006/06/19
----------
- Added Drafts support (Feature #1326839) (richs)
2006/06/02
----------
- Updated Estonian localization and moved from ee to et
- Added Bulgarian localization
2006/05/25
----------
- Finalized GoogieSpell integration
2006/05/18
----------
- Added Arabic and Armenian localizations
- Updated Russian localization
- Removed MDB2 classes from repository. Install them seperately if used.
- Updated MDB2 wrapper class contributed by Lukas Kahwe Smith
- Allow & in e-mail addresses
2006/05/05
----------
- Fixed typos in function rcube_button() (Bugs #1473198 and #1473201)
- Check for zlib.output_compression before using ob_gzhandler (Bug #1471069)
- Casting date parts in iil_StrToTime() to avoid warnings (Bug #1482140)
- Corrected INSTALL description (Bug #1476106)
- Added charset to javascript HTTP headers
- Fixed Opera bug with CC and BCC fields (Bug #1474576)
- Changed login page title regarding product name (Bug #1476413)
- Pimped search function
- Applied attachment viewing/forwarding patches by Andrew Fladmark
- Applied prev/next patch by Leonard Bouchet
- Applied patches by Mark Bucciarelli
- Applied patch for requesting receipts by Salvatore Ansani
- Integrated GoogieSpell as suggested by phil (styling is not perfect yet, localization is missing)
2006/04/13
----------
- Added Slovenian localization
- Updated Portuguese localization
- Fixed parent.location problem for compose-links
- Added sort order saving patch by Jacob Brunson
- Added gzip compression support
2006/04/02
----------
- Added Lithuanian localization
- Improved search function
- Added version string as template object
- Load host-specific configuration file (see config/main.inc.php)
- New config parameter adding domain to user names for login
- Strip tags on _auth, _action, _task parameters
- Corrected labels for next/previous page buttons in address book
2006/03/23
----------
- Auto-detect mail header delimiters
- Regard daylight savings
- Localized quota display
- Started implementing search function
2006/03/20
----------
- Avoid error message when saving an unchanged identity (Bug #1429510)
- Fixed hard-coded cols selection for sent folder (Bug #1354586)
- Enable some HTML links for use with "open in new window" or "save target"
- Check meta-key instead of ctrl on Macs
- Ignore double clicks when holding down a modifier key
- Fixed reloading of the login page
- Fixed typo in compose template (Bug #1446852)
- Added compose button to message read step (Request #1433288)
- New config parameter for persistent database connections (Bug #1431817)
2006/03/14
----------
- Don't remove internal HTML tags in plaintext messages
- Improved error handling in DB connection failure
2006/02/22
----------
- Updated localizations
- Fixed bug #1435989
2006/02/19
----------
- Updated localizations
- Applied patch of Anders Karlsson
- Applied patch of Jacob Brunson
- Applied patch for virtuser_query by Robin Elfrink
- Added support for References header (patch by Auke)
- Added support for mbstring module by Tadashi Jokagi
- Added function for automatic remove of slashes on GET and POST vars
if magic_quotes is enabled
2006/02/05
----------
- Added Slovak, Hungarian, Bosnian and Croation translation
- 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
- Changed to full UTF-8 support
- Additional timezones (Patch #1389912)
- Added LDAP public search (experimental)
- Applied patch for correct ctrl/shift behavior for message selection (Bug #1326364)
- Casting to strings when adding empty headers to message cache (Bug #1406026)
- Skip sender-address as recipient when Reply-to-all
- Fixes in utf8-class
- Added patch for Quota display by Aury Fink Filho <nuny@aury.com.br>
- Added garbage collector for message cache
- Added patches for BCC headers
2005/12/16
----------
- Added Turkish and Simplified Chinese translation
- Use virtusertable to resolve e-mail addresses at login
- Configurable mail_domain used to compose correct e-mail addresses
on first login
2005/12/03
----------
- Added Finnish, Romanian, Polish, Czech, British, Norwegian, Greek, Russian,
Estonian and Chinese translation
- Get IMAP server capabilities in array
- Check for NAMESPACE capability before sending command
- Set default user language from config 'locale_string'
- Added sorting patch for message list
- Make default sort col/order configurable
- Fixed XSS in address book and identities
- Added more XSS protection (Bug #1308236)
- Added tab indexes for compose form
- Added 'changed' col to contacts table
- Support for 160-bit session hashes
- Added input check for contacts and identities (Patch #1346523)
- Added messages/warning to compose step (Patch #1323895)
- Added favicon to the default skin
- Fixed Bug #1334337 as far as possible
- Added Reply-To-All functionality (Request #1326395, Patch #1349777)
- Redesign of client side AJAX code (enable multi threading)
- Added keep-alive signal every minute
- Make logs dir configurable
- Added support for SMTPS
- Decode attachment file names
- Make delimiter for message headers configurable
- Add generic footer to sent messages
- Choose the rigt identity when replying
- Remove signature when replying (Request #1333167)
- Signatures for each identity
- Select charset when composing message
- Complete re-design of the caching mechanism
2005/08/11
----------
- Write list header to client even if list is empty
- Add functions "select all", "select none" to message list
- Improved filter for HTML messages to remove potentially malicious tags
(script, iframe, object) and event handlers.
- Buttons for next/previous message in view mode
- Add new created contact to list and show confirmation status
- Added folder management (subscribe/create/delete)
- Log message sending (SMTP log)
- Grant access for Camino browser
- Added German translation
2005/10/20
----------
- Added Swedish, Latvian, Portuguese and Catalan translation
- Make SMTP auth method configurable
- Make mailboxlist scrollable (Bug #1326372)
- Fixed SSL support
- Improved support for Courier IMAP (root folder and delimiter issues)
- Moved taskbar from bottom to top
- Added 'session_lifetime' parameter
- Fixed wrong unread count when deleting message (Bug #1332434)
- Srip tags when creating a new folder (Bug #1332084)
- Translate HTML tags in message headers (Bug #1330134)
- Correction in German translation (Bug #1329434)
- Display folder names with special chars correctly (Bug #1330157)
2005/10/07
----------
- Added French, Italian, Spanish, Danish, Dutch translation
- Clarified license (Bug #1305966)
- Fixed PHP warnings (Bug #1299403)
- Fixed english translation (Bug #1295406)
- Fixed bug #1290833: Last character of email not seen
- Fixed bug #1292199 when creating new user
- Allow more browsers (Bug #1285101)
- Added setting for showing pretty dates
- Added support for SQLite database
- Make use of message caching configurable
- Also add attachments when forwarding a message
- Long folder names will not flow over message list (Bug #1267232)
- Show nested mailboxes hieracically
- Enable IMAPS by host
2005/08/20
----------
- Improved cacheing of mailbox messagecount
- Fixed javascript bug when creating a new message folder
- Fixed javascript bugs #1260990 and #1260992: folder selection
- Make Trash folder configurable
- Auto create folders Inbox, Sent and Trash (if configured)
- Support for IMAP root folder
- Added support fot text/enriched messages
- Make list of special mailboxes configurable
diff --git a/program/include/rcube_imap.inc b/program/include/rcube_imap.inc
index c98c480a9..4137d109a 100644
--- a/program/include/rcube_imap.inc
+++ b/program/include/rcube_imap.inc
@@ -1,2107 +1,2108 @@
<?php
/*
+-----------------------------------------------------------------------+
| program/include/rcube_imap.inc |
| |
| This file is part of the RoundCube Webmail client |
| Copyright (C) 2005, RoundCube Dev. - Switzerland |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
| IMAP wrapper that implements the Iloha IMAP Library (IIL) |
| See http://ilohamail.org/ for details |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
$Id$
*/
/**
* 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.26
* @link http://ilohamail.org
*/
class rcube_imap
{
var $db;
var $conn;
var $root_ns = '';
var $root_dir = '';
var $mailbox = 'INBOX';
var $list_page = 1;
var $page_size = 10;
var $sort_field = 'date';
var $sort_order = 'DESC';
var $delimiter = NULL;
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();
var $skip_deleted = FALSE;
var $debug_level = 1;
/**
* Object constructor
*
* @param object Database connection
*/
function __construct($db_conn)
{
$this->db = $db_conn;
}
/**
* 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, $IMAP_USE_INTERNAL_DATE;
// 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__,
'message' => 'Open SSL not available;'), TRUE, FALSE);
$port = 143;
}
$ICL_PORT = $port;
$IMAP_USE_INTERNAL_DATE = false;
$this->conn = iil_Connect($host, $user, $pass, array('imap' => 'check'));
$this->host = $host;
$this->user = $user;
$this->pass = $pass;
$this->port = $port;
$this->ssl = $use_ssl;
// print trace mesages
if ($this->conn && ($this->debug_level & 8))
console($this->conn->message);
// write error log
else if (!$this->conn && $GLOBALS['iil_error'])
{
raise_error(array('code' => 403,
'type' => 'imap',
'message' => $GLOBALS['iil_error']), TRUE, FALSE);
}
// get account namespace
if ($this->conn)
{
$this->_parse_capability($this->conn->capability);
iil_C_NameSpace($this->conn);
if (!empty($this->conn->delimiter))
$this->delimiter = $this->conn->delimiter;
if (!empty($this->conn->rootdir))
{
$this->set_rootdir($this->conn->rootdir);
$this->root_ns = ereg_replace('[\.\/]$', '', $this->conn->rootdir);
}
}
return $this->conn ? TRUE : FALSE;
}
/**
* Close IMAP connection
* Usually done on script shutdown
*
* @access public
*/
function close()
{
if ($this->conn)
iil_Close($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();
$this->connect($this->host, $this->user, $this->pass, $this->port, $this->ssl);
}
/**
* 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)==='/')
$root = substr($root, 0, -1);
$this->root_dir = $root;
if (empty($this->delimiter))
$this->get_hierarchy_delimiter();
}
/**
* 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))
{
$this->default_folders = array();
// add mailbox names lower case
foreach ($arr as $mbox_row)
$this->default_folders[] = strtolower($mbox_row);
// add inbox if not included
if (!in_array('inbox', $this->default_folders))
array_unshift($arr, 'inbox');
}
}
/**
* Set internal mailbox reference.
*
* All operations will be perfomed on this mailbox/folder
*
* @param string Mailbox/Folder name
* @access public
*/
function set_mailbox($new_mbox)
{
$mailbox = $this->_mod_mailbox($new_mbox);
if ($this->mailbox == $mailbox)
return;
$this->mailbox = $mailbox;
// clear messagecount cache for this mailbox
$this->_clear_messagecount($mailbox);
}
/**
* 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);
return $this->capabilities[$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))
$this->delimiter = iil_C_GetHierarchyDelimiter($this->conn);
if (empty($this->delimiter))
$this->delimiter = '/';
return $this->delimiter;
}
/**
* 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();
$a_mboxes = $this->_list_mailboxes($root, $filter);
foreach ($a_mboxes as $mbox_row)
{
$name = $this->_mod_mailbox($mbox_row, 'out');
if (strlen($name))
$a_out[] = $name;
}
// sort mailboxes
$a_out = $this->_sort_mailbox_list($a_out);
return $a_out;
}
/**
* 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 cached folder list
$a_mboxes = $this->get_cache('mailboxes');
if (is_array($a_mboxes))
return $a_mboxes;
// retrieve list of folders from IMAP server
$a_folders = iil_C_ListSubscribed($this->conn, $this->_mod_mailbox($root), $filter);
if (!is_array($a_folders) || !sizeof($a_folders))
$a_folders = array();
// create Default folders if they do not exist
global $CONFIG;
foreach ($CONFIG['default_imap_folders'] as $folder)
{
if (!in_array_nocase($folder, $a_folders))
{
$this->create_mailbox($folder, TRUE);
$this->subscribe($folder);
}
}
$a_folders = iil_C_ListSubscribed($this->conn, $this->_mod_mailbox($root), $filter);
$a_mailbox_cache = array();
// write mailboxlist to cache
$this->update_cache('mailboxes', $a_folders);
return $a_folders;
}
/**
* Get message count for a specific mailbox
*
* @param string Mailbox/folder name
* @param string Mode for count [ALL|UNSEEN|RECENT]
* @param boolean Force reading from server and update cache
* @return number Number of messages
* @access public
*/
function messagecount($mbox_name='', $mode='ALL', $force=FALSE)
{
$mailbox = $mbox_name ? $this->_mod_mailbox($mbox_name) : $this->mailbox;
return $this->_messagecount($mailbox, $mode, $force);
}
/**
* Private method for getting nr of messages
*
* @access private
* @see rcube_imap::messagecount
*/
function _messagecount($mailbox='', $mode='ALL', $force=FALSE)
{
$a_mailbox_cache = FALSE;
$mode = strtoupper($mode);
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];
// RECENT count is fetched abit different
if ($mode == 'RECENT')
$count = iil_C_CheckForRecent($this->conn, $mailbox);
// use SEARCH for message counting
else if ($this->skip_deleted)
{
$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]))
$a_mailbox_cache[$mailbox] = array();
$a_mailbox_cache[$mailbox][$mode] = (int)$count;
// write back to cache
$this->update_cache('messagecount', $a_mailbox_cache);
return (int)$count;
}
/**
* Public method for listing headers
* convert mailbox name with root dir first
*
* @param string Mailbox/folder name
* @param number Current page to list
* @param string Header field to sort by
* @param string Sort order [ASC|DESC]
* @return array Indexed array with message header objects
* @access public
*/
function list_headers($mbox_name='', $page=NULL, $sort_field=NULL, $sort_order=NULL)
{
$mailbox = $mbox_name ? $this->_mod_mailbox($mbox_name) : $this->mailbox;
return $this->_list_headers($mailbox, $page, $sort_field, $sort_order);
}
/**
* Private method for listing message headers
*
* @access private
* @see rcube_imap::list_headers
*/
function _list_headers($mailbox='', $page=NULL, $sort_field=NULL, $sort_order=NULL, $recursive=FALSE)
{
if (!strlen($mailbox))
return array();
if ($sort_field!=NULL)
$this->sort_field = $sort_field;
if ($sort_order!=NULL)
$this->sort_order = strtoupper($sort_order);
$max = $this->_messagecount($mailbox);
$start_msg = ($this->list_page-1) * $this->page_size;
list($begin, $end) = $this->_get_message_range($max, $page);
// mailbox is empty
if ($begin >= $end)
return array();
$headers_sorted = FALSE;
$cache_key = $mailbox.'.msg';
$cache_status = $this->check_cache_status($mailbox, $cache_key);
// 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, $this->sort_field, $this->sort_order);
$headers_sorted = TRUE;
}
else
{
// retrieve headers from IMAP
if ($this->get_capability('sort') && ($msg_index = iil_C_Sort($this->conn, $mailbox, $this->sort_field, $this->skip_deleted ? 'UNDELETED' : '')))
{
$msgs = $msg_index[$begin];
for ($i=$begin+1; $i < $end; $i++)
$msgs = $msgs.','.$msg_index[$i];
}
else
{
$msgs = sprintf("%d:%d", $begin+1, $end);
}
// cache is dirty, sync it
if ($this->caching_enabled && $cache_status==-1 && !$recursive)
{
$this->sync_header_index($mailbox);
return $this->_list_headers($mailbox, $page, $this->sort_field, $this->sort_order, TRUE);
}
// fetch reuested headers from server
$a_msg_headers = array();
$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);
// kick child process to sync cache
// ...
}
// return empty array if no messages found
if (!is_array($a_msg_headers) || empty($a_msg_headers))
return array();
// if not already sorted
if (!$headers_sorted)
$a_msg_headers = iil_SortHeaders($a_msg_headers, $this->sort_field, $this->sort_order);
if (!$headers_sorted && $this->sort_order == 'DESC')
$a_msg_headers = array_reverse($a_msg_headers);
return array_values($a_msg_headers);
}
/**
* Public method for listing a specific set of headers
* convert mailbox name with root dir first
*
* @param string Mailbox/folder name
* @param array List of message ids to list
* @param number Current page to list
* @param string Header field to sort by
* @param string Sort order [ASC|DESC]
* @return array Indexed array with message header objects
* @access public
*/
function list_header_set($mbox_name='', $msgs, $page=NULL, $sort_field=NULL, $sort_order=NULL)
{
$mailbox = $mbox_name ? $this->_mod_mailbox($mbox_name) : $this->mailbox;
return $this->_list_header_set($mailbox, $msgs, $page, $sort_field, $sort_order);
}
/**
* Private method for listing a set of message headers
*
* @access private
* @see rcube_imap::list_header_set
*/
function _list_header_set($mailbox, $msgs, $page=NULL, $sort_field=NULL, $sort_order=NULL)
{
// also accept a comma-separated list of message ids
if (is_string($msgs))
$msgs = split(',', $msgs);
if (!strlen($mailbox) || empty($msgs))
return array();
if ($sort_field!=NULL)
$this->sort_field = $sort_field;
if ($sort_order!=NULL)
$this->sort_order = strtoupper($sort_order);
$max = count($msgs);
$start_msg = ($this->list_page-1) * $this->page_size;
// fetch reuested headers from server
$a_msg_headers = array();
$this->_fetch_headers($mailbox, join(',', $msgs), $a_msg_headers, NULL);
// return empty array if no messages found
if (!is_array($a_msg_headers) || empty($a_msg_headers))
return array();
// if not already sorted
$a_msg_headers = iil_SortHeaders($a_msg_headers, $this->sort_field, $this->sort_order);
// only return the requested part of the set
return array_slice(array_values($a_msg_headers), $start_msg, min($max-$start_msg, $this->page_size));
}
/**
* Helper function to get first and last index of the requested set
*
* @param number message count
* @param mixed page number to show, or string 'all'
* @return array array with two values: first index, last index
* @access private
*/
function _get_message_range($max, $page)
{
$start_msg = ($this->list_page-1) * $this->page_size;
if ($page=='all')
{
$begin = 0;
$end = $max;
}
else if ($this->sort_order=='DESC')
{
$begin = $max - $this->page_size - $start_msg;
$end = $max - $start_msg;
}
else
{
$begin = $start_msg;
$end = $start_msg + $this->page_size;
}
if ($begin < 0) $begin = 0;
if ($end < 0) $end = $max;
if ($end > $max) $end = $max;
return array($begin, $end);
}
/**
* Fetches message headers
* Used for loop
*
* @param string Mailbox name
* @param string Message index 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 message_index($mbox_name='', $sort_field=NULL, $sort_order=NULL)
{
if ($sort_field!=NULL)
$this->sort_field = $sort_field;
if ($sort_order!=NULL)
$this->sort_order = strtoupper($sort_order);
$mailbox = $mbox_name ? $this->_mod_mailbox($mbox_name) : $this->mailbox;
$key = "$mbox:".$this->sort_field.":".$this->sort_order.".msgi";
// have stored it in RAM
if (isset($this->cache[$key]))
return $this->cache[$key];
// check local cache
$cache_key = $mailbox.'.msg';
$cache_status = $this->check_cache_status($mailbox, $cache_key);
// cache is OK
if ($cache_status>0)
{
$a_index = $this->get_message_cache_index($cache_key, TRUE, $this->sort_field, $this->sort_order);
return array_values($a_index);
}
// fetch complete message index
$msg_count = $this->_messagecount($mailbox);
if ($this->get_capability('sort') && ($a_index = iil_C_Sort($this->conn, $mailbox, $this->sort_field, '', TRUE)))
{
if ($this->sort_order == 'DESC')
$a_index = array_reverse($a_index);
$this->cache[$key] = $a_index;
}
else
{
$a_index = iil_C_FetchHeaderIndex($this->conn, $mailbox, "1:$msg_count", $this->sort_field);
$a_uids = iil_C_FetchUIDs($this->conn, $mailbox);
if ($this->sort_order=="ASC")
asort($a_index);
else if ($this->sort_order=="DESC")
arsort($a_index);
$i = 0;
$this->cache[$key] = array();
foreach ($a_index as $index => $value)
$this->cache[$key][$i++] = $a_uids[$index];
}
return $this->cache[$key];
}
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);
}
}
/**
* Invoke search request to IMAP server
*
* @param string mailbox name to search in
* @param string search criteria (ALL, TO, FROM, SUBJECT, etc)
* @param string search string
* @return array search results as list of message ids
* @access public
*/
function search($mbox_name='', $criteria='ALL', $str=NULL)
{
$mailbox = $mbox_name ? $this->_mod_mailbox($mbox_name) : $this->mailbox;
if ($str && $criteria)
{
$criteria = 'CHARSET UTF-8 '.$criteria.' "'.UTF7EncodeString($str).'"';
return $this->_search_index($mailbox, $criteria);
}
else
return $this->_search_index($mailbox, $criteria);
}
/**
* Private search method
*
* @return array search results as list of message ids
* @access private
* @see rcube_imap::search()
*/
function _search_index($mailbox, $criteria='ALL')
{
$a_messages = iil_C_Search($this->conn, $mailbox, $criteria);
// clean message list (there might be some empty entries)
if (is_array($a_messages))
{
foreach ($a_messages as $i => $val)
if (empty($val))
unset($a_messages[$i]);
}
return $a_messages;
}
function get_headers($id, $mbox_name=NULL, $is_uid=TRUE)
{
$mailbox = $mbox_name ? $this->_mod_mailbox($mbox_name) : $this->mailbox;
// get cached headers
if ($is_uid && ($headers = $this->get_cached_message($mailbox.'.msg', $id)))
return $headers;
$msg_id = $is_uid ? $this->_uid2id($id) : $id;
$headers = iil_C_FetchHeader($this->conn, $mailbox, $msg_id);
// write headers cache
if ($headers)
$this->add_message_cache($mailbox.'.msg', $msg_id, $headers);
return $headers;
}
function get_body($uid, $part=1)
{
if (!($msg_id = $this->_uid2id($uid)))
return FALSE;
$structure_str = iil_C_FetchStructureString($this->conn, $this->mailbox, $msg_id);
$structure = iml_GetRawStructureArray($structure_str);
$body = iil_C_FetchPartBody($this->conn, $this->mailbox, $msg_id, $part);
$encoding = iml_GetPartEncodingCode($structure, $part);
if ($encoding==3) $body = $this->mime_decode($body, 'base64');
else if ($encoding==4) $body = $this->mime_decode($body, 'quoted-printable');
return $body;
}
function get_raw_body($uid)
{
if (!($msg_id = $this->_uid2id($uid)))
return FALSE;
$body = iil_C_FetchPartHeader($this->conn, $this->mailbox, $msg_id, NULL);
$body .= iil_C_HandlePartBody($this->conn, $this->mailbox, $msg_id, NULL, 1);
return $body;
}
// set message flag to one or several messages
// possible flags are: SEEN, UNDELETED, DELETED, RECENT, ANSWERED, DRAFT
function set_flag($uids, $flag)
{
$flag = strtoupper($flag);
$msg_ids = array();
if (!is_array($uids))
$uids = explode(',',$uids);
foreach ($uids as $uid) {
$msg_ids[$uid] = $this->_uid2id($uid);
}
if ($flag=='UNDELETED')
$result = iil_C_Undelete($this->conn, $this->mailbox, join(',', array_values($msg_ids)));
else if ($flag=='UNSEEN')
$result = iil_C_Unseen($this->conn, $this->mailbox, join(',', array_values($msg_ids)));
else
$result = iil_C_Flag($this->conn, $this->mailbox, join(',', array_values($msg_ids)), $flag);
// reload message headers if cached
$cache_key = $this->mailbox.'.msg';
if ($this->caching_enabled)
{
foreach ($msg_ids as $uid => $id)
{
if ($cached_headers = $this->get_cached_message($cache_key, $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
$count = count($msg_ids);
// clear message count cache
if ($result && $flag=='SEEN')
$this->_set_messagecount($this->mailbox, 'UNSEEN', $count*(-1));
else if ($result && $flag=='UNSEEN')
$this->_set_messagecount($this->mailbox, 'UNSEEN', $count);
else if ($result && $flag=='DELETED')
$this->_set_messagecount($this->mailbox, 'ALL', $count*(-1));
return $result;
}
// append a mail message (source) to a specific mailbox
function save_message($mbox_name, &$message)
{
$mbox_name = stripslashes($mbox_name);
$mailbox = $this->_mod_mailbox($mbox_name);
// make sure 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
$this->_set_messagecount($mailbox, 'ALL', 1);
}
return $saved;
}
// move a message from one mailbox to another
function move_message($uids, $to_mbox, $from_mbox='')
{
$to_mbox = stripslashes($to_mbox);
$from_mbox = stripslashes($from_mbox);
$to_mbox = $this->_mod_mailbox($to_mbox);
$from_mbox = $from_mbox ? $this->_mod_mailbox($from_mbox) : $this->mailbox;
// make sure mailbox exists
if (!in_array($to_mbox, $this->_list_mailboxes()))
{
if (in_array(strtolower($to_mbox), $this->default_folders))
$this->create_mailbox($to_mbox, TRUE);
else
return FALSE;
}
// convert the list of uids to array
$a_uids = is_string($uids) ? explode(',', $uids) : (is_array($uids) ? $uids : NULL);
// exit if no message uids are specified
if (!is_array($a_uids))
return false;
// convert uids to message ids
$a_mids = array();
foreach ($a_uids as $uid)
$a_mids[] = $this->_uid2id($uid, $from_mbox);
$moved = iil_C_Move($this->conn, join(',', $a_mids), $from_mbox, $to_mbox);
// send expunge command in order to have the moved message
// really deleted from the source mailbox
if ($moved)
{
$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_cache_index = $this->get_message_cache_index($cache_key)))
{
$start_index = 100000;
foreach ($a_uids as $uid)
{
if(($index = array_search($uid, $a_cache_index)) !== FALSE)
$start_index = min($index, $start_index);
}
// clear cache from the lowest index on
$this->clear_message_cache($cache_key, $start_index);
}
return $moved;
}
// mark messages as deleted and expunge mailbox
function delete_message($uids, $mbox_name='')
{
$mbox_name = stripslashes($mbox_name);
$mailbox = $mbox_name ? $this->_mod_mailbox($mbox_name) : $this->mailbox;
// convert the list of uids to array
$a_uids = is_string($uids) ? explode(',', $uids) : (is_array($uids) ? $uids : NULL);
// exit if no message uids are specified
if (!is_array($a_uids))
return false;
// convert uids to message ids
$a_mids = array();
foreach ($a_uids as $uid)
$a_mids[] = $this->_uid2id($uid, $mailbox);
$deleted = iil_C_Delete($this->conn, $mailbox, join(',', $a_mids));
// send expunge command in order to have the deleted message
// really deleted from the mailbox
if ($deleted)
{
$this->_expunge($mailbox, FALSE);
$this->_clear_messagecount($mailbox);
}
// remove deleted messages from cache
$cache_key = $mailbox.'.msg';
if ($deleted && ($a_cache_index = $this->get_message_cache_index($cache_key)))
{
$start_index = 100000;
foreach ($a_uids as $uid)
{
$index = array_search($uid, $a_cache_index);
$start_index = min($index, $start_index);
}
// clear cache from the lowest index on
$this->clear_message_cache($cache_key, $start_index);
}
return $deleted;
}
// clear all messages in a specific mailbox
function clear_mailbox($mbox_name=NULL)
{
$mbox_name = stripslashes($mbox_name);
$mailbox = !empty($mbox_name) ? $this->_mod_mailbox($mbox_name) : $this->mailbox;
$msg_count = $this->_messagecount($mailbox, 'ALL');
if ($msg_count>0)
{
$cleared = iil_C_ClearFolder($this->conn, $mailbox);
// make sure the message count cache is cleared as well
if ($cleared)
{
$this->clear_message_cache($mailbox.'.msg');
$a_mailbox_cache = $this->get_cache('messagecount');
unset($a_mailbox_cache[$mailbox]);
$this->update_cache('messagecount', $a_mailbox_cache);
}
return $cleared;
}
else
return 0;
}
// send IMAP expunge command and clear cache
function expunge($mbox_name='', $clear_cache=TRUE)
{
$mbox_name = stripslashes($mbox_name);
$mailbox = $mbox_name ? $this->_mod_mailbox($mbox_name) : $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_message_cache($mailbox.'.msg');
$this->_clear_messagecount($mailbox);
}
return $result;
}
/* --------------------------------
* folder managment
* --------------------------------*/
// return an array with all folders available in IMAP server
function list_unsubscribed($root='')
{
static $sa_unsubscribed;
if (is_array($sa_unsubscribed))
return $sa_unsubscribed;
// retrieve list of folders from IMAP server
$a_mboxes = iil_C_ListMailboxes($this->conn, $this->_mod_mailbox($root), '*');
// modify names with root dir
foreach ($a_mboxes as $mbox_name)
{
$name = $this->_mod_mailbox($mbox_name, 'out');
if (strlen($name))
$a_folders[] = $name;
}
// filter folders and sort them
$sa_unsubscribed = $this->_sort_mailbox_list($a_folders);
return $sa_unsubscribed;
}
/**
* Get quota
* added by Nuny
*/
function get_quota()
{
if ($this->get_capability('QUOTA'))
{
$result = iil_C_GetQuota($this->conn);
if ($result["total"])
return sprintf("%.2fMB / %.2fMB (%.0f%%)", $result["used"] / 1000.0, $result["total"] / 1000.0, $result["percent"]);
}
return FALSE;
}
// subscribe to a specific mailbox(es)
function subscribe($mbox_name, $mode='subscribe')
{
if (is_array($mbox_name))
$a_mboxes = $mbox_name;
else if (is_string($mbox_name) && strlen($mbox_name))
$a_mboxes = explode(',', $mbox_name);
// let this common function do the main work
return $this->_change_subscription($a_mboxes, 'subscribe');
}
// unsubscribe mailboxes
function unsubscribe($mbox_name)
{
if (is_array($mbox_name))
$a_mboxes = $mbox_name;
else if (is_string($mbox_name) && strlen($mbox_name))
$a_mboxes = explode(',', $mbox_name);
// let this common function do the main work
return $this->_change_subscription($a_mboxes, 'unsubscribe');
}
// create a new mailbox on the server and register it in local cache
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($abs_name) && (!is_array($a_mailbox_cache) || !in_array($abs_name, $a_mailbox_cache)))
$result = iil_C_CreateFolder($this->conn, $abs_name);
// update mailboxlist cache
if ($result && $subscribe)
$this->subscribe($name_enc);
return $result ? $name : FALSE;
}
// set a new name to an existing mailbox
- function rename_mailbox($mbox_name, $new_name, $subscribe=TRUE)
+ function rename_mailbox($mbox_name, $new_name)
{
$result = FALSE;
// replace backslashes
$name = preg_replace('/[\\\]+/', '-', $new_name);
+
+ // encode mailbox name and reduce it to 100 chars
+ $name_enc = substr(UTF7EncodeString($new_name), 0, 100);
- $name_enc = UTF7EncodeString($new_name);
-
- // reduce mailbox name to 100 chars
- $name_enc = substr($name_enc, 0, 100);
-
+ // make absolute path
+ $mailbox = $this->_mod_mailbox($mbox_name);
$abs_name = $this->_mod_mailbox($name_enc);
- $a_mailbox_cache = $this->get_cache('mailboxes');
-
- if (strlen($abs_name) && (!is_array($a_mailbox_cache) || !in_array($abs_name, $a_mailbox_cache)))
- $result = iil_C_RenameFolder($this->conn, $mbox_name, $abs_name);
-
- // update mailboxlist cache
- if ($result && $subscribe)
- $this->unsubscribe($mbox_name);
- $this->subscribe($name_enc);
+
+ if (strlen($abs_name))
+ $result = iil_C_RenameFolder($this->conn, $mailbox, $abs_name);
+
+ // clear cache
+ if ($result)
+ {
+ $this->clear_message_cache($mailbox.'.msg');
+ $this->clear_cache('mailboxes');
+ }
return $result ? $name : FALSE;
}
// remove mailboxes from server
function delete_mailbox($mbox_name)
{
$deleted = FALSE;
if (is_array($mbox_name))
$a_mboxes = $mbox_name;
else if (is_string($mbox_name) && strlen($mbox_name))
$a_mboxes = explode(',', $mbox_name);
if (is_array($a_mboxes))
foreach ($a_mboxes as $mbox_name)
{
$mailbox = $this->_mod_mailbox($mbox_name);
// unsubscribe mailbox before deleting
iil_C_UnSubscribe($this->conn, $mailbox);
// send delete command to server
$result = iil_C_DeleteFolder($this->conn, $mailbox);
if ($result>=0)
$deleted = TRUE;
}
// clear mailboxlist cache
if ($deleted)
{
$this->clear_message_cache($mailbox.'.msg');
$this->clear_cache('mailboxes');
}
return $deleted;
}
/* --------------------------------
* internal caching methods
* --------------------------------*/
function set_caching($set)
{
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 = $this->_read_cache_record('IMAP.'.$key);
$this->cache[$key] = strlen($cache_data) ? unserialize($cache_data) : FALSE;
}
return $this->cache[$key];
}
function update_cache($key, $data)
{
$this->cache[$key] = $data;
$this->cache_changed = TRUE;
$this->cache_changes[$key] = TRUE;
}
function write_cache()
{
if ($this->caching_enabled && $this->cache_changed)
{
foreach ($this->cache as $key => $data)
{
if ($this->cache_changes[$key])
$this->_write_cache_record('IMAP.'.$key, serialize($data));
}
}
}
function clear_cache($key=NULL)
{
if ($key===NULL)
{
foreach ($this->cache as $key => $data)
$this->_clear_cache_record('IMAP.'.$key);
$this->cache = array();
$this->cache_changed = FALSE;
$this->cache_changes = array();
}
else
{
$this->_clear_cache_record('IMAP.'.$key);
$this->cache_changes[$key] = FALSE;
unset($this->cache[$key]);
}
}
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 highest message matches -> cache seems OK
if ($cache_uid == $header->uid)
return 1;
// cache is dirty
return -1;
}
// if cache count differs less than 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, $sort_col='idx', $sort_order='ASC')
{
static $sa_message_index = array();
// empty key -> empty array
if (empty($key))
return 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 ".$this->db->quote_identifier($sort_col)." ".$sort_order,
$_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)
{
if (!$key || !is_object($headers) || empty($headers->uid))
return;
$this->db->query(
"INSERT INTO ".get_table_name('messages')."
(user_id, del, cache_key, created, idx, uid, subject, ".$this->db->quoteIdentifier('from').", ".$this->db->quoteIdentifier('to').", cc, date, size, headers)
VALUES (?, 0, ?, now(), ?, ?, ?, ?, ?, ?, ".$this->db->fromunixtime($headers->timestamp).", ?, ?)",
$_SESSION['user_id'],
$key,
$index,
$headers->uid,
(string)substr($this->decode_header($headers->subject, TRUE), 0, 128),
(string)substr($this->decode_header($headers->from, TRUE), 0, 128),
(string)substr($this->decode_header($headers->to, TRUE), 0, 128),
(string)substr($this->decode_header($headers->cc, TRUE), 0, 128),
(int)$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 methods
* --------------------------------*/
function decode_address_list($input, $max=NULL)
{
$a = $this->_parse_address_list($input);
$out = array();
if (!is_array($a))
return $out;
$c = count($a);
$j = 0;
foreach ($a as $val)
{
$j++;
$address = $val['address'];
$name = preg_replace(array('/^[\'"]/', '/[\'"]$/'), '', trim($val['name']));
$string = $name!==$address ? sprintf('%s <%s>', strpos($name, ',')!==FALSE ? '"'.$name.'"' : $name, $address) : $address;
$out[$j] = array('name' => $name,
'mailto' => $address,
'string' => $string);
if ($max && $j==$max)
break;
}
return $out;
}
function decode_header($input, $remove_quotes=FALSE)
{
$str = $this->decode_mime_string((string)$input);
if ($str{0}=='"' && $remove_quotes)
{
$str = str_replace('"', '', $str);
}
return $str;
}
/**
* Decode a mime-encoded string to internal charset
*
* @access static
*/
function decode_mime_string($input, $recursive=false)
{
$out = '';
$pos = strpos($input, '=?');
if ($pos !== false)
{
$out = substr($input, 0, $pos);
$end_cs_pos = strpos($input, "?", $pos+2);
$end_en_pos = strpos($input, "?", $end_cs_pos+1);
$end_pos = strpos($input, "?=", $end_en_pos+1);
$encstr = substr($input, $pos+2, ($end_pos-$pos-2));
$rest = substr($input, $end_pos+2);
$out .= rcube_imap::_decode_mime_string_part($encstr);
$out .= rcube_imap::decode_mime_string($rest);
return $out;
}
// no encoding information, defaults to what is specified in the class header
return rcube_charset_convert($input, 'ISO-8859-1');
}
/**
* Decode a part of a mime-encoded string
*
* @access static
*/
function _decode_mime_string_part($str)
{
$a = explode('?', $str);
$count = count($a);
// should be in format "charset?encoding?base64_string"
if ($count >= 3)
{
for ($i=2; $i<$count; $i++)
$rest.=$a[$i];
if (($a[1]=="B")||($a[1]=="b"))
$rest = base64_decode($rest);
else if (($a[1]=="Q")||($a[1]=="q"))
{
$rest = str_replace("_", " ", $rest);
$rest = quoted_printable_decode($rest);
}
return rcube_charset_convert($rest, $a[0]);
}
else
return $str; // we dont' know what to do with this
}
function mime_decode($input, $encoding='7bit')
{
switch (strtolower($encoding))
{
case '7bit':
return $input;
break;
case 'quoted-printable':
return quoted_printable_decode($input);
break;
case 'base64':
return base64_decode($input);
break;
default:
return $input;
}
}
function mime_encode($input, $encoding='7bit')
{
switch ($encoding)
{
case 'quoted-printable':
return quoted_printable_encode($input);
break;
case 'base64':
return base64_encode($input);
break;
default:
return $input;
}
}
// convert body chars according to the ctype_parameters
function charset_decode($body, $ctype_param)
{
if (is_array($ctype_param) && !empty($ctype_param['charset']))
return rcube_charset_convert($body, $ctype_param['charset']);
// defaults to what is specified in the class header
return rcube_charset_convert($body, 'ISO-8859-1');
}
/* --------------------------------
* private methods
* --------------------------------*/
function _mod_mailbox($mbox_name, $mode='in')
{
if ((!empty($this->root_ns) && $this->root_ns == $mbox_name) || ($mbox_name == 'INBOX' && $mode == 'in'))
return $mbox_name;
if (!empty($this->root_dir) && $mode=='in')
$mbox_name = $this->root_dir.$this->delimiter.$mbox_name;
else if (strlen($this->root_dir) && $mode=='out')
$mbox_name = substr($mbox_name, strlen($this->root_dir)+1);
return $mbox_name;
}
// sort mailboxes first by default folders and then in alphabethical order
function _sort_mailbox_list($a_folders)
{
$a_out = $a_defaults = array();
// find default folders and skip folders starting with '.'
foreach($a_folders as $i => $folder)
{
if ($folder{0}=='.')
continue;
if (($p = array_search(strtolower($folder), $this->default_folders))!==FALSE)
$a_defaults[$p] = $folder;
else
$a_out[] = $folder;
}
sort($a_out);
ksort($a_defaults);
return array_merge($a_defaults, $a_out);
}
function get_id($uid, $mbox_name=NULL)
{
return $this->_uid2id($uid, $mbox_name);
}
function get_uid($id,$mbox_name=NULL)
{
return $this->_id2uid($id, $mbox_name);
}
function _uid2id($uid, $mbox_name=NULL)
{
if (!$mbox_name)
$mbox_name = $this->mailbox;
if (!isset($this->uid_id_map[$mbox_name][$uid]))
$this->uid_id_map[$mbox_name][$uid] = iil_C_UID2ID($this->conn, $mbox_name, $uid);
return $this->uid_id_map[$mbox_name][$uid];
}
function _id2uid($id, $mbox_name=NULL)
{
if (!$mbox_name)
$mbox_name = $this->mailbox;
return iil_C_ID2UID($this->conn, $mbox_name, $id);
}
// 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)
{
$updated = FALSE;
if (is_array($a_mboxes))
foreach ($a_mboxes as $i => $mbox_name)
{
$mailbox = $this->_mod_mailbox($mbox_name);
$a_mboxes[$i] = $mailbox;
if ($mode=='subscribe')
$result = iil_C_Subscribe($this->conn, $mailbox);
else if ($mode=='unsubscribe')
$result = iil_C_UnSubscribe($this->conn, $mailbox);
if ($result>=0)
$updated = TRUE;
}
// get cached mailbox list
if ($updated)
{
$a_mailbox_cache = $this->get_cache('mailboxes');
if (!is_array($a_mailbox_cache))
return $updated;
// modify cached list
if ($mode=='subscribe')
$a_mailbox_cache = array_merge($a_mailbox_cache, $a_mboxes);
else if ($mode=='unsubscribe')
$a_mailbox_cache = array_diff($a_mailbox_cache, $a_mboxes);
// write mailboxlist to cache
$this->update_cache('mailboxes', $this->_sort_mailbox_list($a_mailbox_cache));
}
return $updated;
}
// increde/decrese messagecount for a specific mailbox
function _set_messagecount($mbox_name, $mode, $increment)
{
$a_mailbox_cache = FALSE;
$mailbox = $mbox_name ? $mbox_name : $this->mailbox;
$mode = strtoupper($mode);
$a_mailbox_cache = $this->get_cache('messagecount');
if (!is_array($a_mailbox_cache[$mailbox]) || !isset($a_mailbox_cache[$mailbox][$mode]) || !is_numeric($increment))
return FALSE;
// add incremental value to messagecount
$a_mailbox_cache[$mailbox][$mode] += $increment;
// there's something wrong, delete from cache
if ($a_mailbox_cache[$mailbox][$mode] < 0)
unset($a_mailbox_cache[$mailbox][$mode]);
// write back to cache
$this->update_cache('messagecount', $a_mailbox_cache);
return TRUE;
}
// remove messagecount of a specific mailbox from cache
function _clear_messagecount($mbox_name='')
{
$a_mailbox_cache = FALSE;
$mailbox = $mbox_name ? $mbox_name : $this->mailbox;
$a_mailbox_cache = $this->get_cache('messagecount');
if (is_array($a_mailbox_cache[$mailbox]))
{
unset($a_mailbox_cache[$mailbox]);
$this->update_cache('messagecount', $a_mailbox_cache);
}
}
function _parse_address_list($str)
{
$a = $this->_explode_quoted_string(',', $str);
$result = array();
foreach ($a as $key => $val)
{
$val = str_replace("\"<", "\" <", $val);
$sub_a = $this->_explode_quoted_string(' ', $val);
foreach ($sub_a as $k => $v)
{
if ((strpos($v, '@') > 0) && (strpos($v, '.') > 0))
$result[$key]['address'] = str_replace('<', '', str_replace('>', '', $v));
else
$result[$key]['name'] .= (empty($result[$key]['name'])?'':' ').str_replace("\"",'',stripslashes($v));
}
if (empty($result[$key]['name']))
$result[$key]['name'] = $result[$key]['address'];
$result[$key]['name'] = $this->decode_header($result[$key]['name']);
}
return $result;
}
function _explode_quoted_string($delimiter, $string)
{
$quotes = explode("\"", $string);
foreach ($quotes as $key => $val)
if (($key % 2) == 1)
$quotes[$key] = str_replace($delimiter, "_!@!_", $quotes[$key]);
$string = implode("\"", $quotes);
$result = explode($delimiter, $string);
foreach ($result as $key => $val)
$result[$key] = str_replace("_!@!_", $delimiter, $result[$key]);
return $result;
}
}
function quoted_printable_encode($input="", $line_max=76, $space_conv=false)
{
$hex = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
$lines = preg_split("/(?:\r\n|\r|\n)/", $input);
$eol = "\r\n";
$escape = "=";
$output = "";
while( list(, $line) = each($lines))
{
//$line = rtrim($line); // remove trailing white space -> no =20\r\n necessary
$linlen = strlen($line);
$newline = "";
for($i = 0; $i < $linlen; $i++)
{
$c = substr( $line, $i, 1 );
$dec = ord( $c );
if ( ( $i == 0 ) && ( $dec == 46 ) ) // convert first point in the line into =2E
{
$c = "=2E";
}
if ( $dec == 32 )
{
if ( $i == ( $linlen - 1 ) ) // convert space at eol only
{
$c = "=20";
}
else if ( $space_conv )
{
$c = "=20";
}
}
else if ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) // always encode "\t", which is *not* required
{
$h2 = floor($dec/16);
$h1 = floor($dec%16);
$c = $escape.$hex["$h2"].$hex["$h1"];
}
if ( (strlen($newline) + strlen($c)) >= $line_max ) // CRLF is not counted
{
$output .= $newline.$escape.$eol; // soft line break; " =\r\n" is okay
$newline = "";
// check if newline first character will be point or not
if ( $dec == 46 )
{
$c = "=2E";
}
}
$newline .= $c;
} // end of for
$output .= $newline.$eol;
} // end of while
return trim($output);
}
?>
diff --git a/program/js/app.js b/program/js/app.js
index 84e9e45c7..51d9f8570 100644
--- a/program/js/app.js
+++ b/program/js/app.js
@@ -1,3858 +1,3861 @@
/*
+-----------------------------------------------------------------------+
| RoundCube Webmail Client Script |
| |
| This file is part of the RoundCube Webmail client |
| Copyright (C) 2005, RoundCube Dev, - Switzerland |
| Licensed under the GNU GPL |
| |
+-----------------------------------------------------------------------+
| Authors: Thomas Bruederli <roundcube@gmail.com> |
| Charles McNulty <charles@charlesmcnulty.com> |
+-----------------------------------------------------------------------+
$Id$
*/
// Constants
var CONTROL_KEY = 1;
var SHIFT_KEY = 2;
var CONTROL_SHIFT_KEY = 3;
var DRAFT_AUTOSAVE = 10; // Minutes
var rcube_webmail_client;
var rcube_save_timer;
function rcube_webmail()
{
this.env = new Object();
this.labels = new Object();
this.buttons = new Object();
this.gui_objects = new Object();
this.commands = new Object();
this.selection = new Array();
this.last_selected = 0;
this.in_message_list = false;
// create public reference to myself
rcube_webmail_client = this;
this.ref = 'rcube_webmail_client';
// webmail client settings
this.dblclick_time = 600;
this.message_time = 5000;
this.request_timeout = 180000;
this._interval = 60000;
this.mbox_expression = new RegExp('[^0-9a-z\-_]', 'gi');
this.env.blank_img = 'skins/default/images/blank.gif';
// mimetypes supported by the browser (default settings)
this.mimetypes = new Array('text/plain', 'text/html', 'text/xml',
'image/jpeg', 'image/gif', 'image/png',
'application/x-javascript', 'application/pdf',
'application/x-shockwave-flash');
// set environment variable
this.set_env = function(name, value)
{
//if (!this.busy)
this.env[name] = value;
};
// add a localized label to the client environment
this.add_label = function(key, value)
{
this.labels[key] = value;
};
// add a button to the button list
this.register_button = function(command, id, type, act, sel, over)
{
if (!this.buttons[command])
this.buttons[command] = new Array();
var button_prop = {id:id, type:type};
if (act) button_prop.act = act;
if (sel) button_prop.sel = sel;
if (over) button_prop.over = over;
this.buttons[command][this.buttons[command].length] = button_prop;
};
// register a specific gui object
this.gui_object = function(name, id)
{
this.gui_objects[name] = id;
};
// initialize webmail client
this.init = function()
{
this.task = this.env.task;
// check browser
if (!bw.dom || !bw.xmlhttp_test())
{
location.href = this.env.comm_path+'&_action=error&_code=0x199';
return;
}
// find all registered gui objects
for (var n in this.gui_objects)
this.gui_objects[n] = rcube_find_object(this.gui_objects[n]);
// tell parent window that this frame is loaded
if (this.env.framed && parent.rcmail && parent.rcmail.set_busy)
parent.rcmail.set_busy(false);
// enable general commands
this.enable_command('logout', 'mail', 'addressbook', 'settings', true);
switch (this.task)
{
case 'mail':
var msg_list_frame = this.gui_objects.mailcontframe;
var msg_list = this.gui_objects.messagelist;
if (msg_list)
{
msg_list_frame.onmousedown = function(e){return rcube_webmail_client.click_on_list(e);};
this.init_messagelist(msg_list);
this.enable_command('toggle_status', true);
}
// enable mail commands
this.enable_command('list', 'checkmail', 'compose', 'add-contact', 'search', 'reset-search', true);
if (this.env.action=='show')
{
this.enable_command('show', 'reply', 'reply-all', 'forward', 'moveto', 'delete', 'viewsource', 'print', 'load-attachment', true);
if (this.env.next_uid)
this.enable_command('nextmessage', true);
if (this.env.prev_uid)
this.enable_command('previousmessage', true);
}
if (this.env.action=='show' && this.env.blockedobjects)
{
if (this.gui_objects.remoteobjectsmsg)
this.gui_objects.remoteobjectsmsg.style.display = 'block';
this.enable_command('load-images', true);
}
if (this.env.action=='compose')
{
this.enable_command('add-attachment', 'send-attachment', 'remove-attachment', 'send', true);
if (this.env.spellcheck)
this.enable_command('spellcheck', true);
if (this.env.drafts_mailbox)
this.enable_command('savedraft', true);
}
if (this.env.messagecount)
this.enable_command('select-all', 'select-none', 'sort', 'expunge', true);
if (this.env.messagecount && (this.env.mailbox==this.env.trash_mailbox || this.env.mailbox==this.env.junk_mailbox))
this.enable_command('purge', true);
this.set_page_buttons();
// focus this window
window.focus();
// init message compose form
if (this.env.action=='compose')
this.init_messageform();
// 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;
case 'addressbook':
var contacts_list = this.gui_objects.contactslist;
var ldap_contacts_list = this.gui_objects.ldapcontactslist;
if (contacts_list)
this.init_contactslist(contacts_list);
if (ldap_contacts_list)
this.init_ldapsearchlist(ldap_contacts_list);
this.set_page_buttons();
if (this.env.cid)
this.enable_command('show', 'edit', true);
if ((this.env.action=='add' || this.env.action=='edit') && this.gui_objects.editform)
this.enable_command('save', true);
this.enable_command('list', 'add', true);
this.enable_command('ldappublicsearch', this.env.ldappublicsearch);
break;
case 'settings':
this.enable_command('preferences', 'identities', 'save', 'folders', true);
if (this.env.action=='identities' || this.env.action=='edit-identity' || this.env.action=='add-identity')
this.enable_command('edit', 'add', 'delete', true);
if (this.env.action=='edit-identity' || this.env.action=='add-identity')
this.enable_command('save', true);
if (this.env.action=='folders')
this.enable_command('subscribe', 'unsubscribe', 'create-folder', 'rename-folder', 'delete-folder', true);
var identities_list = this.gui_objects.identitieslist;
if (identities_list)
this.init_identitieslist(identities_list);
break;
case 'login':
var input_user = rcube_find_object('_user');
var input_pass = rcube_find_object('_pass');
if (input_user && input_user.value=='')
input_user.focus();
else if (input_pass)
input_pass.focus();
this.enable_command('login', true);
break;
default:
break;
}
// enable basic commands
this.enable_command('logout', true);
// disable browser's contextmenus
// document.oncontextmenu = function(){ return false; }
// load body click event
document.onmousedown = function(){ return rcube_webmail_client.reset_click(); };
document.onkeydown = function(e){ return rcube_webmail_client.key_pressed(e, msg_list_frame); };
// set default keep alive interval
if (!this.keep_alive_interval)
this.keep_alive_interval = this._interval;
// flag object as complete
this.loaded = true;
// show message
if (this.pending_message)
this.display_message(this.pending_message[0], this.pending_message[1]);
// start interval for keep-alive/recent_check signal
if (this.keep_alive_interval && this.task=='mail' && this.gui_objects.messagelist)
this._int = setInterval(this.ref+'.check_for_recent()', this.keep_alive_interval);
else if (this.task!='login')
this._int = setInterval(this.ref+'.send_keep_alive()', this.keep_alive_interval);
};
// reset last clicked if user clicks on anything other than the message table
this.reset_click = function()
{
var id;
this.in_message_list = false;
for (var n=0; n<this.selection.length; n++)
{
id = this.selection[n];
if (this.list_rows[id] && this.list_rows[id].obj)
{
this.set_classname(this.list_rows[id].obj, 'selected', false);
this.set_classname(this.list_rows[id].obj, 'unfocused', true);
}
}
};
this.click_on_list = function(e)
{
if (!e)
e = window.event;
for (var n=0; n<this.selection.length; n++)
{
id = this.selection[n];
if (this.list_rows[id].obj)
{
this.set_classname(this.list_rows[id].obj, 'selected', true);
this.set_classname(this.list_rows[id].obj, 'unfocused', false);
}
}
var mbox_li;
if (mbox_li = this.get_mailbox_li())
this.set_classname(mbox_li, 'unfocused', true);
this.in_message_list = true;
e.cancelBubble = true;
};
this.key_pressed = function(e, msg_list_frame) {
if (this.in_message_list != true)
return true;
var keyCode = document.layers ? e.which : document.all ? event.keyCode : document.getElementById ? e.keyCode : 0;
var mod_key = this.get_modifier(e);
switch (keyCode) {
case 13:
this.command('show','',this);
break;
case 40:
case 38:
return this.use_arrow_key(keyCode, mod_key, msg_list_frame);
break;
case 46:
return this.use_delete_key(keyCode, mod_key, msg_list_frame);
break;
default:
return true;
}
return true;
}
this.use_arrow_key = function(keyCode, mod_key, msg_list_frame) {
var scroll_to = 0;
if (keyCode == 40) { // down arrow key pressed
new_row = this.get_next_row();
if (!new_row) return false;
scroll_to = (Number(new_row.offsetTop) + Number(new_row.offsetHeight)) - Number(msg_list_frame.offsetHeight);
} else if (keyCode == 38) { // up arrow key pressed
new_row = this.get_prev_row();
if (!new_row) return false;
scroll_to = new_row.offsetTop;
} else {return true;}
this.select_row(new_row.uid,mod_key,true);
if (((Number(new_row.offsetTop)) < (Number(msg_list_frame.scrollTop))) ||
((Number(new_row.offsetTop) + Number(new_row.offsetHeight)) > (Number(msg_list_frame.scrollTop) + Number(msg_list_frame.offsetHeight)))) {
msg_list_frame.scrollTop = scroll_to;
}
return false;
};
this.use_delete_key = function(keyCode, mod_key, msg_list_frame){
this.command('delete','',this);
return false;
}
// get all message rows from HTML table and init each row
this.init_messagelist = function(msg_list)
{
if (msg_list && msg_list.tBodies[0])
{
this.message_rows = new Array();
var row;
for(var r=0; r<msg_list.tBodies[0].childNodes.length; r++)
{
row = msg_list.tBodies[0].childNodes[r];
while (row && (row.nodeType != 1 || row.style.display == 'none')) {
row = row.nextSibling;
r++;
}
//row = msg_list.tBodies[0].rows[r];
if (row) this.init_message_row(row);
}
}
// alias to common rows array
this.list_rows = this.message_rows;
};
// make references in internal array and set event handlers
this.init_message_row = function(row)
{
var uid, msg_icon;
if (String(row.id).match(/rcmrow([0-9]+)/))
{
uid = RegExp.$1;
row.uid = uid;
this.message_rows[uid] = {id:row.id, obj:row,
classname:row.className,
deleted:this.env.messages[uid] ? this.env.messages[uid].deleted : null,
unread:this.env.messages[uid] ? this.env.messages[uid].unread : null,
replied:this.env.messages[uid] ? this.env.messages[uid].replied : null};
// set eventhandlers to table row
row.onmousedown = function(e){ return rcube_webmail_client.drag_row(e, this.uid); };
row.onmouseup = function(e){ return rcube_webmail_client.click_row(e, this.uid); };
if (document.all)
row.onselectstart = function() { return false; };
// set eventhandler to message icon
if ((msg_icon = row.cells[0].childNodes[0]) && row.cells[0].childNodes[0].nodeName=='IMG')
{
msg_icon.id = 'msgicn_'+uid;
msg_icon._row = row;
msg_icon.onmousedown = function(e) { rcube_webmail_client.command('toggle_status', this); };
// get message icon and save original icon src
this.message_rows[uid].icon = msg_icon;
}
}
};
// init message compose form: set focus and eventhandlers
this.init_messageform = function()
{
if (!this.gui_objects.messageform)
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');
var input_replyto = rcube_find_object('_replyto');
var input_subject = rcube_find_object('_subject');
var input_message = rcube_find_object('_message');
// init live search events
if (input_to)
this.init_address_input_events(input_to);
if (input_cc)
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();
else if (input_subject && input_subject.value=='')
input_subject.focus();
else if (input_message)
this.set_caret2start(input_message); // input_message.focus();
// get summary of all field values
this.cmp_hash = this.compose_field_hash();
// start the auto-save timer
this.auto_save_start();
};
this.init_address_input_events = function(obj)
{
var handler = function(e){ return rcube_webmail_client.ksearch_keypress(e,this); };
var handler2 = function(e){ return rcube_webmail_client.ksearch_blur(e,this); };
if (bw.safari)
{
obj.addEventListener('keydown', handler, false);
// obj.addEventListener('blur', handler2, false);
}
else if (bw.mz)
{
obj.addEventListener('keypress', handler, false);
obj.addEventListener('blur', handler2, false);
}
else if (bw.ie)
{
obj.onkeydown = handler;
//obj.attachEvent('onkeydown', handler);
// obj.attachEvent('onblur', handler2, false);
}
obj.setAttribute('autocomplete', 'off');
};
// get all contact rows from HTML table and init each row
this.init_contactslist = function(contacts_list)
{
if (contacts_list && contacts_list.tBodies[0])
{
this.contact_rows = new Array();
var row;
for(var r=0; r<contacts_list.tBodies[0].childNodes.length; r++)
{
row = contacts_list.tBodies[0].childNodes[r];
this.init_table_row(row, 'contact_rows');
}
}
// alias to common rows array
this.list_rows = this.contact_rows;
if (this.env.cid)
this.highlight_row(this.env.cid);
};
// get all contact rows from HTML table and init each row
this.init_ldapsearchlist = function(ldap_contacts_list)
{
if (ldap_contacts_list && ldap_contacts_list.tBodies[0])
{
this.ldap_contact_rows = new Array();
var row;
for(var r=0; r<ldap_contacts_list.tBodies[0].childNodes.length; r++)
{
row = ldap_contacts_list.tBodies[0].childNodes[r];
this.init_table_row(row, 'ldap_contact_rows');
}
}
// alias to common rows array
this.list_rows = this.ldap_contact_rows;
};
// make references in internal array and set event handlers
this.init_table_row = function(row, array_name)
{
var cid;
if (String(row.id).match(/rcmrow([0-9]+)/))
{
cid = RegExp.$1;
row.cid = cid;
this[array_name][cid] = {id:row.id,
obj:row,
classname:row.className};
// set eventhandlers to table row
row.onmousedown = function(e) { rcube_webmail_client.in_selection_before=this.cid; return false; }; // fake for drag handler
row.onmouseup = function(e){ return rcube_webmail_client.click_row(e, this.cid); };
}
};
// get all contact rows from HTML table and init each row
this.init_identitieslist = function(identities_list)
{
if (identities_list && identities_list.tBodies[0])
{
this.identity_rows = new Array();
var row;
for(var r=0; r<identities_list.tBodies[0].childNodes.length; r++)
{
row = identities_list.tBodies[0].childNodes[r];
this.init_table_row(row, 'identity_rows');
}
}
// alias to common rows array
this.list_rows = this.identity_rows;
if (this.env.iid)
this.highlight_row(this.env.iid);
};
/*********************************************************/
/********* client command interface *********/
/*********************************************************/
// execute a specific command on the web client
this.command = function(command, props, obj)
{
if (obj && obj.blur)
obj.blur();
if (this.busy)
return false;
// command not supported or allowed
if (!this.commands[command])
{
// pass command to parent window
if (this.env.framed && parent.rcmail && parent.rcmail.command)
parent.rcmail.command(command, props);
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)
{
case 'login':
if (this.gui_objects.loginform)
this.gui_objects.loginform.submit();
break;
case 'logout':
location.href = this.env.comm_path+'&_action=logout';
break;
// commands to switch task
case 'mail':
case 'addressbook':
case 'settings':
this.switch_task(command);
break;
// misc list commands
case 'list':
if (this.task=='mail')
{
if (this.env.search_request<0 || (this.env.search_request && props != this.env.mailbox))
this.reset_qsearch();
// Reset message list header, unless returning from compose/read/etc
// don't know what this is good for (thomasb, 2006/07/25)
//if (this.env.mailbox != props && this.message_rows)
// this.clear_message_list_header();
this.list_mailbox(props);
}
else if (this.task=='addressbook')
this.list_contacts();
break;
case 'sort':
// get the type of sorting
var a_sort = props.split('_');
var sort_col = a_sort[0];
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;
// set table header class
if (header = document.getElementById('rcmHead'+this.env.sort_col))
this.set_classname(header, 'sorted'+(this.env.sort_order.toUpperCase()), false);
if (header = document.getElementById('rcmHead'+sort_col))
this.set_classname(header, 'sorted'+sort_order, true);
// save new sort properties
this.env.sort_col = sort_col;
this.env.sort_order = sort_order;
// reload message list
this.list_mailbox('', '', sort_col+'_'+sort_order);
break;
case 'nextpage':
this.list_page('next');
break;
case 'previouspage':
this.list_page('prev');
break;
case 'expunge':
if (this.env.messagecount)
this.expunge_mailbox(this.env.mailbox);
break;
case 'purge':
case 'empty-mailbox':
if (this.env.messagecount)
this.purge_mailbox(this.env.mailbox);
break;
// common commands used in multiple tasks
case 'show':
if (this.task=='mail')
{
var uid = this.get_single_uid();
if (uid && (!this.env.uid || uid != this.env.uid))
{
if (this.env.mailbox==this.env.drafts_mailbox)
{
this.set_busy(true);
location.href = this.env.comm_path+'&_action=compose&_draft_uid='+uid+'&_mbox='+escape(this.env.mailbox);
}
else
{
this.show_message(uid);
}
}
}
else if (this.task=='addressbook')
{
var cid = props ? props : this.get_single_cid();
if (cid && !(this.env.action=='show' && cid==this.env.cid))
this.load_contact(cid, 'show');
}
break;
case 'add':
if (this.task=='addressbook')
if (!window.frames[this.env.contentframe].rcmail)
this.load_contact(0, 'add');
else
{
if (window.frames[this.env.contentframe].rcmail.selection.length)
this.add_ldap_contacts();
else
this.load_contact(0, 'add');
}
else if (this.task=='settings')
{
this.clear_selection();
this.load_identity(0, 'add-identity');
}
break;
case 'edit':
var cid;
if (this.task=='addressbook' && (cid = this.get_single_cid()))
this.load_contact(cid, 'edit');
else if (this.task=='settings' && props)
this.load_identity(props, 'edit-identity');
break;
case 'save-identity':
case 'save':
if (this.gui_objects.editform)
{
var input_pagesize = rcube_find_object('_pagesize');
var input_name = rcube_find_object('_name');
var input_email = rcube_find_object('_email');
// user prefs
if (input_pagesize && isNaN(input_pagesize.value))
{
alert(this.get_label('nopagesizewarning'));
input_pagesize.focus();
break;
}
// contacts/identities
else
{
if (input_name && input_name.value == '')
{
alert(this.get_label('nonamewarning'));
input_name.focus();
break;
}
else if (input_email && !rcube_check_email(input_email.value))
{
alert(this.get_label('noemailwarning'));
input_email.focus();
break;
}
}
this.gui_objects.editform.submit();
}
break;
case 'delete':
// mail task
if (this.task=='mail')
this.delete_messages();
// addressbook task
else if (this.task=='addressbook')
this.delete_contacts();
// user settings task
else if (this.task=='settings')
this.delete_identity();
break;
// mail task commands
case 'move':
case 'moveto':
this.move_messages(props);
break;
case 'toggle_status':
if (props && !props._row)
break;
var uid;
var flag = 'read';
if (props._row.uid)
{
uid = props._row.uid;
this.dont_select = true;
// toggle read/unread
if (this.message_rows[uid].deleted) {
flag = 'undelete';
} else if (!this.message_rows[uid].unread)
flag = 'unread';
}
this.mark_message(flag, uid);
break;
case 'load-images':
if (this.env.uid)
this.show_message(this.env.uid, true);
break;
case 'load-attachment':
var url = this.env.comm_path+'&_action=get&_mbox='+this.env.mailbox+'&_uid='+this.env.uid+'&_part='+props.part;
// open attachment in frame if it's of a supported mimetype
if (this.env.uid && props.mimetype && find_in_array(props.mimetype, this.mimetypes)>=0)
{
this.attachment_win = window.open(url+'&_frame=1', 'rcubemailattachment');
if (this.attachment_win)
{
setTimeout(this.ref+'.attachment_win.focus()', 10);
break;
}
}
location.href = url;
break;
case 'select-all':
this.select_all(props);
break;
case 'select-none':
this.clear_selection();
break;
case 'nextmessage':
if (this.env.next_uid)
this.show_message(this.env.next_uid);
//location.href = this.env.comm_path+'&_action=show&_uid='+this.env.next_uid+'&_mbox='+this.env.mailbox;
break;
case 'previousmessage':
if (this.env.prev_uid)
this.show_message(this.env.prev_uid);
//location.href = this.env.comm_path+'&_action=show&_uid='+this.env.prev_uid+'&_mbox='+this.env.mailbox;
break;
case 'checkmail':
this.check_for_recent();
break;
case 'compose':
var url = this.env.comm_path+'&_action=compose';
if (this.task=='mail' && this.env.mailbox==this.env.drafts_mailbox)
{
var uid = this.get_single_uid();
url += '&_draft_uid='+uid+'&_mbox='+escape(this.env.mailbox);
}
// modify url if we're in addressbook
else if (this.task=='addressbook')
{
url = this.get_task_url('mail', url);
var a_cids = new Array();
// use contact_id passed as command parameter
if (props)
a_cids[a_cids.length] = props;
// get selected contacts
else
{
if (!window.frames[this.env.contentframe].rcmail.selection.length)
{
for (var n=0; n<this.selection.length; n++)
a_cids[a_cids.length] = this.selection[n];
}
else
{
var frameRcmail = window.frames[this.env.contentframe].rcmail;
// get the email address(es)
for (var n=0; n<frameRcmail.selection.length; n++)
a_cids[a_cids.length] = frameRcmail.ldap_contact_rows[frameRcmail.selection[n]].obj.cells[1].innerHTML;
}
}
if (a_cids.length)
url += '&_to='+a_cids.join(',');
else
break;
}
else if (props)
url += '&_to='+encodeURIComponent(props);
// don't know if this is necessary...
url = url.replace(/&_framed=1/, "");
this.set_busy(true);
// need parent in case we are coming from the contact frame
if (this.env.framed)
parent.location.href = url;
else
location.href = url;
break;
case 'spellcheck':
if (this.env.spellcheck && this.env.spellcheck.spellCheck)
this.env.spellcheck.spellCheck(this.env.spellcheck.check_link);
break;
case 'savedraft':
// Reset the auto-save timer
self.clearTimeout(rcube_save_timer);
if (!this.gui_objects.messageform)
break;
// if saving Drafts is disabled in main.inc.php
if (!this.env.drafts_mailbox)
break;
this.set_busy(true, 'savingmessage');
var form = this.gui_objects.messageform;
form.target = "savetarget";
form.submit();
break;
case 'send':
if (!this.gui_objects.messageform)
break;
if (!this.check_compose_input())
break;
// all checks passed, send message
this.set_busy(true, 'sendingmessage');
var form = this.gui_objects.messageform;
form._draft.value='';
form.submit();
break;
case 'add-attachment':
this.show_attachment_form(true);
case 'send-attachment':
// Reset the auto-save timer
self.clearTimeout(rcube_save_timer);
this.upload_file(props)
break;
case 'remove-attachment':
this.remove_attachment(props);
break;
case 'reply-all':
case 'reply':
var uid;
if (uid = this.get_single_uid())
{
this.set_busy(true);
location.href = this.env.comm_path+'&_action=compose&_reply_uid='+uid+'&_mbox='+escape(this.env.mailbox)+(command=='reply-all' ? '&_all=1' : '');
}
break;
case 'forward':
var uid;
if (uid = this.get_single_uid())
{
this.set_busy(true);
location.href = this.env.comm_path+'&_action=compose&_forward_uid='+uid+'&_mbox='+escape(this.env.mailbox);
}
break;
case 'print':
var uid;
if (uid = this.get_single_uid())
{
this.printwin = window.open(this.env.comm_path+'&_action=print&_uid='+uid+'&_mbox='+escape(this.env.mailbox)+(this.env.safemode ? '&_safe=1' : ''));
if (this.printwin)
setTimeout(this.ref+'.printwin.focus()', 20);
}
break;
case 'viewsource':
var uid;
if (uid = this.get_single_uid())
{
this.sourcewin = window.open(this.env.comm_path+'&_action=viewsource&_uid='+this.env.uid+'&_mbox='+escape(this.env.mailbox));
if (this.sourcewin)
setTimeout(this.ref+'.sourcewin.focus()', 20);
}
break;
case 'add-contact':
this.add_contact(props);
break;
// mail quicksearch
case 'search':
if (!props && this.gui_objects.qsearchbox)
props = this.gui_objects.qsearchbox.value;
if (props)
this.qsearch(escape(props), this.env.mailbox);
break;
// reset quicksearch
case 'reset-search':
var s = this.env.search_request;
this.reset_qsearch();
if (s)
this.list_mailbox(this.env.mailbox);
break;
// ldap search
case 'ldappublicsearch':
if (this.gui_objects.ldappublicsearchform)
this.gui_objects.ldappublicsearchform.submit();
else
this.ldappublicsearch(command);
break;
// user settings commands
case 'preferences':
location.href = this.env.comm_path;
break;
case 'identities':
location.href = this.env.comm_path+'&_action=identities';
break;
case 'delete-identity':
this.delete_identity();
case 'folders':
location.href = this.env.comm_path+'&_action=folders';
break;
case 'subscribe':
this.subscribe_folder(props);
break;
case 'unsubscribe':
this.unsubscribe_folder(props);
break;
case 'create-folder':
this.create_folder(props);
break;
case 'rename-folder':
this.rename_folder(props);
break;
case 'delete-folder':
if (confirm(this.get_label('deletefolderconfirm')))
this.delete_folder(props);
break;
}
return obj ? false : true;
};
// set command enabled or disabled
this.enable_command = function()
{
var args = arguments;
if(!args.length) return -1;
var command;
var enable = args[args.length-1];
for(var n=0; n<args.length-1; n++)
{
command = args[n];
this.commands[command] = enable;
this.set_button(command, (enable ? 'act' : 'pas'));
}
return true;
};
// lock/unlock interface
this.set_busy = function(a, message)
{
if (a && message)
{
var msg = this.get_label(message);
if (msg==message)
msg = 'Loading...';
this.display_message(msg, 'loading', true);
}
else if (!a && this.busy)
this.hide_message();
this.busy = a;
//document.body.style.cursor = a ? 'wait' : 'default';
if (this.gui_objects.editform)
this.lock_form(this.gui_objects.editform, a);
// clear pending timer
if (this.request_timer)
clearTimeout(this.request_timer);
// set timer for requests
if (a && this.request_timeout)
this.request_timer = setTimeout(this.ref+'.request_timed_out()', this.request_timeout);
};
// return a localized string
this.get_label = function(name)
{
if (this.labels[name])
return this.labels[name];
else
return name;
};
// switch to another application task
this.switch_task = function(task)
{
if (this.task===task && task!='mail')
return;
var url = this.get_task_url(task);
if (task=='mail')
url += '&_mbox=INBOX';
this.set_busy(true);
location.href = url;
};
this.get_task_url = function(task, url)
{
if (!url)
url = this.env.comm_path;
return url.replace(/_task=[a-z]+/, '_task='+task);
};
// called when a request timed out
this.request_timed_out = function()
{
this.set_busy(false);
this.display_message('Request timed out!', 'error');
};
/*********************************************************/
/********* event handling methods *********/
/*********************************************************/
// onmouseup handler for mailboxlist item
this.mbox_mouse_up = function(mbox)
{
if (this.drag_active)
{
this.unfocus_mailbox(mbox);
this.command('moveto', mbox);
}
else
this.command('list', mbox);
return false;
};
// onmousedown-handler of message list row
this.drag_row = function(e, id)
{
this.in_selection_before = this.in_selection(id) ? id : false;
// don't do anything (another action processed before)
if (this.dont_select)
return false;
// selects currently unselected row
if (!this.in_selection_before && !this.list_rows[id].clicked)
{
var mod_key = this.get_modifier(e);
this.select_row(id,mod_key,false);
}
if (this.selection.length)
{
this.drag_start = true;
document.onmousemove = function(e){ return rcube_webmail_client.drag_mouse_move(e); };
document.onmouseup = function(e){ return rcube_webmail_client.drag_mouse_up(e); };
}
return false;
};
// onmouseup-handler of message list row
this.click_row = function(e, id)
{
var mod_key = this.get_modifier(e);
// don't do anything (another action processed before)
if (this.dont_select)
{
this.dont_select = false;
return false;
}
// unselects currently selected row
if (!this.drag_active && this.in_selection_before==id && !this.list_rows[id].clicked)
this.select_row(id,mod_key,false);
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 && this.in_selection(id))
{
if (this.env.mailbox==this.env.drafts_mailbox)
{
this.set_busy(true);
location.href = this.env.comm_path+'&_action=compose&_draft_uid='+id+'&_mbox='+escape(this.env.mailbox);
}
else
{
this.show_message(id);
}
return false;
}
else if (this.task=='addressbook')
{
if (this.contact_rows && this.selection.length==1)
{
this.load_contact(this.selection[0], 'show', true);
// change the text for the add contact button
var links = parent.document.getElementById('abooktoolbar').getElementsByTagName('A');
for (i = 0; i < links.length; i++)
{
var onclickstring = new String(links[i].onclick);
if (onclickstring.search('\"add\"') != -1)
links[i].title = this.env.newcontact;
}
}
else if (this.contact_rows && this.contact_rows[id].clicked)
{
this.load_contact(id, 'show');
return false;
}
else if (this.ldap_contact_rows && !this.ldap_contact_rows[id].clicked)
{
// clear selection
parent.rcmail.clear_selection();
// disable delete
parent.rcmail.set_button('delete', 'pas');
// change the text for the add contact button
var links = parent.document.getElementById('abooktoolbar').getElementsByTagName('A');
for (i = 0; i < links.length; i++)
{
var onclickstring = new String(links[i].onclick);
if (onclickstring.search('\"add\"') != -1)
links[i].title = this.env.addcontact;
}
}
// handle double click event
else if (this.ldap_contact_rows && this.selection.length==1 && this.ldap_contact_rows[id].clicked)
this.command('compose', this.ldap_contact_rows[id].obj.cells[1].innerHTML);
else if (this.env.contentframe)
{
var elm = document.getElementById(this.env.contentframe);
elm.style.visibility = 'hidden';
}
}
else if (this.task=='settings')
{
if (this.selection.length==1)
this.command('edit', this.selection[0]);
}
this.list_rows[id].clicked = true;
setTimeout(this.ref+'.list_rows['+id+'].clicked=false;', this.dblclick_time);
return false;
};
/*********************************************************/
/********* (message) list functionality *********/
/*********************************************************/
// get next and previous rows that are not hidden
this.get_next_row = function(){
if (!this.list_rows) return false;
var last_selected_row = this.list_rows[this.last_selected];
var new_row = last_selected_row.obj.nextSibling;
while (new_row && (new_row.nodeType != 1 || new_row.style.display == 'none')) {
new_row = new_row.nextSibling;
}
return new_row;
}
this.get_prev_row = function(){
if (!this.list_rows) return false;
var last_selected_row = this.list_rows[this.last_selected];
var new_row = last_selected_row.obj.previousSibling;
while (new_row && (new_row.nodeType != 1 || new_row.style.display == 'none')) {
new_row = new_row.previousSibling;
}
return new_row;
}
// highlight/unhighlight a row
this.highlight_row = function(id, multiple)
{
var selected = false
if (this.list_rows[id] && !multiple)
{
this.clear_selection();
this.selection[0] = id;
this.list_rows[id].obj.className += ' selected';
selected = true;
}
else if (this.list_rows[id])
{
if (!this.in_selection(id)) // select row
{
this.selection[this.selection.length] = id;
this.set_classname(this.list_rows[id].obj, 'selected', true);
}
else // unselect row
{
var p = find_in_array(id, this.selection);
var a_pre = this.selection.slice(0, p);
var a_post = this.selection.slice(p+1, this.selection.length);
this.selection = a_pre.concat(a_post);
this.set_classname(this.list_rows[id].obj, 'selected', false);
this.set_classname(this.list_rows[id].obj, 'unfocused', false);
}
selected = (this.selection.length==1);
}
// enable/disable commands for message
if (this.task=='mail')
{
if (this.env.mailbox==this.env.drafts_mailbox)
{
this.enable_command('show', selected);
this.enable_command('delete', 'moveto', this.selection.length>0 ? true : false);
}
else
{
this.enable_command('show', 'reply', 'reply-all', 'forward', 'print', selected);
this.enable_command('delete', 'moveto', this.selection.length>0 ? true : false);
}
}
else if (this.task=='addressbook')
{
this.enable_command('edit', /*'print',*/ selected);
this.enable_command('delete', 'compose', this.selection.length>0 ? true : false);
}
};
// selects or unselects the proper row depending on the modifier key pressed
this.select_row = function(id,mod_key,with_mouse) {
if (!mod_key) {
this.shift_start = id;
this.highlight_row(id, false);
} else {
switch (mod_key) {
case SHIFT_KEY: {
this.shift_select(id,false);
break; }
case CONTROL_KEY: {
this.shift_start = id;
if (!with_mouse)
this.highlight_row(id, true);
break;
}
case CONTROL_SHIFT_KEY: {
this.shift_select(id,true);
break;
}
default: {
this.highlight_row(id, false);
break;
}
}
}
if (this.last_selected != 0 && this.list_rows[this.last_selected])
this.set_classname(this.list_rows[this.last_selected].obj, 'focused', false);
this.last_selected = id;
this.set_classname(this.list_rows[id].obj, 'focused', true);
};
this.shift_select = function(id, control) {
var from_rowIndex = this.list_rows[this.shift_start].obj.rowIndex;
var to_rowIndex = this.list_rows[id].obj.rowIndex;
var i = ((from_rowIndex < to_rowIndex)? from_rowIndex : to_rowIndex);
var j = ((from_rowIndex > to_rowIndex)? from_rowIndex : to_rowIndex);
// iterate through the entire message list
for (var n in this.list_rows) {
if ((this.list_rows[n].obj.rowIndex >= i) && (this.list_rows[n].obj.rowIndex <= j)) {
if (!this.in_selection(n))
this.highlight_row(n, true);
} else {
if (this.in_selection(n) && !control)
this.highlight_row(n, true);
}
}
};
this.clear_selection = function()
{
for(var n=0; n<this.selection.length; n++)
if (this.list_rows[this.selection[n]]) {
this.set_classname(this.list_rows[this.selection[n]].obj, 'selected', false);
this.set_classname(this.list_rows[this.selection[n]].obj, 'unfocused', false);
}
this.selection = new Array();
};
// check if given id is part of the current selection
this.in_selection = function(id)
{
for(var n in this.selection)
if (this.selection[n]==id)
return true;
return false;
};
// select each row in list
this.select_all = function(filter)
{
if (!this.list_rows || !this.list_rows.length)
return false;
// reset selection first
this.clear_selection();
for (var n in this.list_rows)
{
if (!filter || this.list_rows[n][filter]==true)
{
this.last_selected = n;
this.highlight_row(n, true);
}
}
return true;
};
// when user doble-clicks on a row
this.show_message = function(id, safe)
{
var add_url = '';
var target = window;
if (this.env.contentframe && window.frames && window.frames[this.env.contentframe])
{
target = window.frames[this.env.contentframe];
add_url = '&_framed=1';
}
if (safe)
add_url = '&_safe=1';
if (id)
{
this.set_busy(true, 'loading');
target.location.href = this.env.comm_path+'&_action=show&_uid='+id+'&_mbox='+escape(this.env.mailbox)+add_url;
}
};
// list a specific page
this.list_page = function(page)
{
if (page=='next')
page = this.env.current_page+1;
if (page=='prev' && this.env.current_page>1)
page = this.env.current_page-1;
if (page > 0 && page <= this.env.pagecount)
{
this.env.current_page = page;
if (this.task=='mail')
this.list_mailbox(this.env.mailbox, page);
else if (this.task=='addressbook')
this.list_contacts(page);
}
};
// list messages of a specific mailbox
this.list_mailbox = function(mbox, page, sort)
{
this.last_selected = 0;
var add_url = '';
var target = window;
if (!mbox)
mbox = this.env.mailbox;
// add sort to url if set
if (sort)
add_url += '&_sort=' + sort;
// set page=1 if changeing to another mailbox
if (!page && mbox != this.env.mailbox)
{
page = 1;
add_url += '&_refresh=1';
this.env.current_page = page;
this.clear_selection();
}
// also send search request to get the right messages
if (this.env.search_request)
add_url += '&_search='+this.env.search_request;
this.select_mailbox(mbox);
// load message list remotely
if (this.gui_objects.messagelist)
{
this.list_mailbox_remote(mbox, page, add_url);
return;
}
if (this.env.contentframe && window.frames && window.frames[this.env.contentframe])
{
target = window.frames[this.env.contentframe];
add_url += '&_framed=1';
}
// load message list to target frame/window
if (mbox)
{
this.set_busy(true, 'loading');
target.location.href = this.env.comm_path+'&_mbox='+escape(mbox)+(page ? '&_page='+page : '')+add_url;
}
};
// send remote request to load message list
this.list_mailbox_remote = function(mbox, page, add_url)
{
// 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]);
table.removeChild(table.tBodies[1]);
this.message_rows = new Array();
this.list_rows = this.message_rows;
};
this.clear_message_list_header = function()
{
var table;
if (table = this.gui_objects.messagelist)
{
if (table.colgroup)
table.removeChild(table.colgroup);
if (table.tHead)
table.removeChild(table.tHead);
var colgroup = document.createElement('COLGROUP');
var thead = document.createElement('THEAD');
table.insertBefore(colgroup, table.tBodies[0]);
table.insertBefore(thead, table.tBodies[0]);
}
};
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);
this.http_request('expunge', url+add_url, lock);
};
this.purge_mailbox = function(mbox)
{
var lock = false;
var add_url = '';
if (!confirm(this.get_label('purgefolderconfirm')))
return false;
// 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);
this.http_request('purge', url+add_url, lock);
return true;
};
this.focus_mailbox = function(mbox)
{
var mbox_li;
if (this.drag_active && mbox != this.env.mailbox && (mbox_li = this.get_mailbox_li(mbox)))
this.set_classname(mbox_li, 'droptarget', true);
}
this.unfocus_mailbox = function(mbox)
{
var mbox_li;
if (this.drag_active && (mbox_li = this.get_mailbox_li(mbox)))
this.set_classname(mbox_li, 'droptarget', false);
}
// move selected messages to the specified mailbox
this.move_messages = function(mbox)
{
// exit if no mailbox specified or if selection is empty
if (!mbox || !(this.selection.length || this.env.uid) || mbox==this.env.mailbox)
return;
var a_uids = new Array();
if (this.env.uid)
a_uids[a_uids.length] = this.env.uid;
else
{
var id;
for (var n=0; n<this.selection.length; n++)
{
id = this.selection[n];
a_uids[a_uids.length] = id;
// 'remove' message row from list (just hide it)
if (this.message_rows[id].obj)
this.message_rows[id].obj.style.display = 'none';
}
next_row = this.get_next_row();
prev_row = this.get_prev_row();
new_row = (next_row) ? next_row : prev_row;
if (new_row) this.select_row(new_row.uid,false,false);
}
var lock = false;
// show wait message
if (this.env.action=='show')
{
lock = true;
this.set_busy(true, 'movingmessage');
}
// send request to server
this.http_request('moveto', '_uid='+a_uids.join(',')+'&_mbox='+escape(this.env.mailbox)+'&_target_mbox='+escape(mbox)+'&_from='+(this.env.action ? this.env.action : ''), lock);
};
this.permanently_remove_messages = function() {
// exit if no mailbox specified or if selection is empty
if (!(this.selection.length || this.env.uid))
return;
var a_uids = new Array();
if (this.env.uid)
a_uids[a_uids.length] = this.env.uid;
else
{
var id;
for (var n=0; n<this.selection.length; n++)
{
id = this.selection[n];
a_uids[a_uids.length] = id;
// 'remove' message row from list (just hide it)
if (this.message_rows[id].obj)
this.message_rows[id].obj.style.display = 'none';
}
}
next_row = this.get_next_row();
prev_row = this.get_prev_row();
new_row = (next_row) ? next_row : prev_row;
if (new_row) this.select_row(new_row.uid,false,false);
// send request to server
this.http_request('delete', '_uid='+a_uids.join(',')+'&_mbox='+escape(this.env.mailbox)+'&_from='+(this.env.action ? this.env.action : ''));
}
// delete selected messages from the current mailbox
this.delete_messages = function()
{
// exit if no mailbox specified or if selection is empty
if (!(this.selection.length || this.env.uid))
return;
// if there is a trash mailbox defined and we're not currently in it:
if (this.env.trash_mailbox && String(this.env.mailbox).toLowerCase()!=String(this.env.trash_mailbox).toLowerCase())
this.move_messages(this.env.trash_mailbox);
// if there is a trash mailbox defined but we *are* in it:
else if (this.env.trash_mailbox && String(this.env.mailbox).toLowerCase() == String(this.env.trash_mailbox).toLowerCase())
this.permanently_remove_messages();
// if there isn't a defined trash mailbox and the config is set to flag for deletion
else if (!this.env.trash_mailbox && this.env.flag_for_deletion) {
flag = 'delete';
this.mark_message(flag);
if(this.env.action=="show"){
this.command('nextmessage','',this);
} else if (this.selection.length == 1) {
next_row = this.get_next_row();
prev_row = this.get_prev_row();
new_row = (next_row) ? next_row : prev_row;
if (new_row) this.select_row(new_row.uid,false,false);
}
// if there isn't a defined trash mailbox and the config is set NOT to flag for deletion
}else if (!this.env.trash_mailbox && !this.env.flag_for_deletion) {
this.permanently_remove_messages();
}
return;
};
// set a specific flag to one or more messages
this.mark_message = function(flag, uid)
{
var a_uids = new Array();
if (uid)
a_uids[0] = uid;
else if (this.env.uid)
a_uids[0] = this.env.uid;
else
{
var id;
for (var n=0; n<this.selection.length; n++)
{
id = this.selection[n];
a_uids[a_uids.length] = id;
}
}
switch (flag) {
case 'read':
case 'unread':
this.toggle_read_status(flag,a_uids);
break;
case 'delete':
case 'undelete':
this.toggle_delete_status(a_uids);
break;
}
};
// set class to read/unread
this.toggle_read_status = function(flag, a_uids) {
// mark all message rows as read/unread
var icn_src;
for (var i=0; i<a_uids.length; i++)
{
uid = a_uids[i];
if (this.message_rows[uid])
{
this.message_rows[uid].unread = (flag=='unread' ? true : false);
if (this.message_rows[uid].classname.indexOf('unread')<0 && this.message_rows[uid].unread)
{
this.message_rows[uid].classname += ' unread';
this.set_classname(this.message_rows[uid].obj, 'unread', true);
if (this.env.unreadicon)
icn_src = this.env.unreadicon;
}
else if (!this.message_rows[uid].unread)
{
this.message_rows[uid].classname = this.message_rows[uid].classname.replace(/\s*unread/, '');
this.set_classname(this.message_rows[uid].obj, 'unread', false);
if (this.message_rows[uid].replied && this.env.repliedicon)
icn_src = this.env.repliedicon;
else if (this.env.messageicon)
icn_src = this.env.messageicon;
}
if (this.message_rows[uid].icon && icn_src)
this.message_rows[uid].icon.src = icn_src;
}
}
this.http_request('mark', '_uid='+a_uids.join(',')+'&_flag='+flag);
}
// mark all message rows as deleted/undeleted
this.toggle_delete_status = function(a_uids) {
if (this.env.read_when_deleted) {
this.toggle_read_status('read',a_uids);
}
// if deleting message from "view message" don't bother with delete icon
if (this.env.action == "show")
return false;
if (a_uids.length==1){
if(this.message_rows[a_uids[0]].classname.indexOf('deleted') < 0 ){
this.flag_as_deleted(a_uids)
} else {
this.flag_as_undeleted(a_uids)
}
return true;
}
var all_deleted = true;
for (var i=0; i<a_uids.length; i++) {
uid = a_uids[i];
if (this.message_rows[uid]) {
if (this.message_rows[uid].classname.indexOf('deleted')<0) {
all_deleted = false;
break;
}
}
}
if (all_deleted)
this.flag_as_undeleted(a_uids);
else
this.flag_as_deleted(a_uids);
return true;
}
this.flag_as_undeleted = function(a_uids){
// if deleting message from "view message" don't bother with delete icon
if (this.env.action == "show")
return false;
var icn_src;
for (var i=0; i<a_uids.length; i++) {
uid = a_uids[i];
if (this.message_rows[uid]) {
this.message_rows[uid].deleted = false;
if (this.message_rows[uid].classname.indexOf('deleted') > 0) {
this.message_rows[uid].classname = this.message_rows[uid].classname.replace(/\s*deleted/, '');
this.set_classname(this.message_rows[uid].obj, 'deleted', false);
}
if (this.message_rows[uid].unread && this.env.unreadicon)
icn_src = this.env.unreadicon;
else if (this.message_rows[uid].replied && this.env.repliedicon)
icn_src = this.env.repliedicon;
else if (this.env.messageicon)
icn_src = this.env.messageicon;
if (this.message_rows[uid].icon && icn_src)
this.message_rows[uid].icon.src = icn_src;
}
}
this.http_request('mark', '_uid='+a_uids.join(',')+'&_flag=undelete');
return true;
}
this.flag_as_deleted = function(a_uids) {
// if deleting message from "view message" don't bother with delete icon
if (this.env.action == "show")
return false;
for (var i=0; i<a_uids.length; i++) {
uid = a_uids[i];
if (this.message_rows[uid]) {
this.message_rows[uid].deleted = true;
if (this.message_rows[uid].classname.indexOf('deleted')<0) {
this.message_rows[uid].classname += ' deleted';
this.set_classname(this.message_rows[uid].obj, 'deleted', true);
}
if (this.message_rows[uid].icon && this.env.deletedicon)
this.message_rows[uid].icon.src = this.env.deletedicon;
}
}
this.http_request('mark', '_uid='+a_uids.join(',')+'&_flag=delete');
return true;
}
this.get_mailbox_li = function(mbox)
{
if (this.gui_objects.mailboxlist)
{
mbox = String((mbox ? mbox : this.env.mailbox)).toLowerCase().replace(this.mbox_expression, '');
return document.getElementById('rcmbx'+mbox);
}
return null;
};
/*********************************************************/
/********* message compose methods *********/
/*********************************************************/
// checks the input fields before sending a message
this.check_compose_input = function()
{
// check input fields
var input_to = rcube_find_object('_to');
var input_subject = rcube_find_object('_subject');
var input_message = rcube_find_object('_message');
// check for empty recipient
if (input_to && !rcube_check_email(input_to.value, true))
{
alert(this.get_label('norecipientwarning'));
input_to.focus();
return false;
}
// display localized warning for missing subject
if (input_subject && input_subject.value == '')
{
var subject = prompt(this.get_label('nosubjectwarning'), this.get_label('nosubject'));
// user hit cancel, so don't send
if (!subject && subject !== '')
{
input_subject.focus();
return false;
}
else
{
input_subject.value = subject ? subject : this.get_label('nosubject');
}
}
// check for empty body
if (input_message.value=='')
{
if (!confirm(this.get_label('nobodywarning')))
{
input_message.focus();
return false;
}
}
return true;
};
this.auto_save_start = function()
{
rcube_save_timer = self.setTimeout('rcmail.command("savedraft","",this)',DRAFT_AUTOSAVE * 60000);
}
this.compose_field_hash = function()
{
// check input fields
var input_to = rcube_find_object('_to');
var input_cc = rcube_find_object('_to');
var input_bcc = rcube_find_object('_to');
var input_subject = rcube_find_object('_subject');
var input_message = rcube_find_object('_message');
var str = '';
if (input_to && input_to.value)
str += input_to.value+':';
if (input_cc && input_cc.value)
str += input_cc.value+':';
if (input_bcc && input_bcc.value)
str += input_bcc.value+':';
if (input_subject && input_subject.value)
str += input_subject.value+':';
if (input_message && input_message.value)
str += input_message.value;
return str;
};
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 : '';
var sig, p;
if (!this.env.identity)
this.env.identity = id
// remove the 'old' signature
if (this.env.identity && this.env.signatures && this.env.signatures[this.env.identity])
{
sig = this.env.signatures[this.env.identity];
if (sig.indexOf('--')!=0)
sig = '--\n'+sig;
p = message.lastIndexOf(sig);
if (p>=0)
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])
{
sig = this.env.signatures[id];
if (sig.indexOf('--')!=0)
sig = '--\n'+sig;
message += '\n'+sig;
}
if (input_message)
input_message.value = message;
this.env.identity = id;
return true;
};
this.show_attachment_form = function(a)
{
if (!this.gui_objects.uploadbox)
return false;
var elm, list;
if (elm = this.gui_objects.uploadbox)
{
if (a && (list = this.gui_objects.attachmentlist))
{
var pos = rcube_get_object_pos(list);
var left = pos.x;
var top = pos.y + list.offsetHeight + 10;
elm.style.top = top+'px';
elm.style.left = left+'px';
}
elm.style.visibility = a ? 'visible' : 'hidden';
}
// clear upload form
if (!a && this.gui_objects.attachmentform && this.gui_objects.attachmentform!=this.gui_objects.messageform)
this.gui_objects.attachmentform.reset();
return true;
};
// upload attachment file
this.upload_file = function(form)
{
if (!form)
return false;
// get file input fields
var send = false;
for (var n=0; n<form.elements.length; n++)
if (form.elements[n].type=='file' && form.elements[n].value)
{
send = true;
break;
}
// create hidden iframe and post upload form
if (send)
{
var ts = new Date().getTime();
var frame_name = 'rcmupload'+ts;
// have to do it this way for IE
// otherwise the form will be posted to a new window
if(document.all && !window.opera)
{
var html = '<iframe name="'+frame_name+'" src="program/blank.gif" style="width:0;height:0;visibility:hidden;"></iframe>';
document.body.insertAdjacentHTML('BeforeEnd',html);
}
else // for standards-compilant browsers
{
var frame = document.createElement('IFRAME');
frame.name = frame_name;
frame.width = 10;
frame.height = 10;
frame.style.visibility = 'hidden';
document.body.appendChild(frame);
}
form.target = frame_name;
form.action = this.env.comm_path+'&_action=upload';
form.setAttribute('enctype', 'multipart/form-data');
form.submit();
}
// set reference to the form object
this.gui_objects.attachmentform = form;
return true;
};
// add file name to attachment list
// called from upload page
this.add2attachment_list = function(name,content)
{
if (!this.gui_objects.attachmentlist)
return false;
var li = document.createElement('LI');
li.id = name;
li.innerHTML = content;
this.gui_objects.attachmentlist.appendChild(li);
return true;
};
this.remove_from_attachment_list = function(name)
{
if (!this.gui_objects.attachmentlist)
return false;
var list = this.gui_objects.attachmentlist.getElementsByTagName("li");
for (i=0;i<list.length;i++)
if (list[i].id == name)
this.gui_objects.attachmentlist.removeChild(list[i]);
}
this.remove_attachment = function(name)
{
if (name)
this.http_request('remove-attachment', '_filename='+escape(name));
return true;
}
// send remote request to add a new contact
this.add_contact = function(value)
{
if (value)
this.http_request('addcontact', '_address='+value);
return true;
};
// send remote request to search mail
this.qsearch = function(value, mbox)
{
if (value && mbox)
{
this.clear_message_list();
this.set_busy(true, 'searching');
this.http_request('search', '_search='+value+'&_mbox='+mbox, true);
}
return true;
};
// reset quick-search form
this.reset_qsearch = function()
{
if (this.gui_objects.qsearchbox)
this.gui_objects.qsearchbox.value = '';
this.env.search_request = null;
return true;
};
/*********************************************************/
/********* keyboard live-search methods *********/
/*********************************************************/
// handler for keyboard events on address-fields
this.ksearch_keypress = function(e, obj)
{
if (typeof(this.env.contacts)!='object' || !this.env.contacts.length)
return true;
if (this.ksearch_timer)
clearTimeout(this.ksearch_timer);
if (!e)
e = window.event;
var highlight;
var key = e.keyCode ? e.keyCode : e.which;
switch (key)
{
case 38: // key up
case 40: // key down
if (!this.ksearch_pane)
break;
var dir = key==38 ? 1 : 0;
var next;
highlight = document.getElementById('rcmksearchSelected');
if (!highlight)
highlight = this.ksearch_pane.ul.firstChild;
if (highlight && (next = dir ? highlight.previousSibling : highlight.nextSibling))
{
highlight.removeAttribute('id');
//highlight.removeAttribute('class');
this.set_classname(highlight, 'selected', false);
}
if (next)
{
next.setAttribute('id', 'rcmksearchSelected');
this.set_classname(next, 'selected', true);
this.ksearch_selected = next._rcm_id;
}
if (e.preventDefault)
e.preventDefault();
return false;
case 9: // tab
if(e.shiftKey)
break;
case 13: // enter
if (this.ksearch_selected===null || !this.ksearch_input || !this.ksearch_value)
break;
// get cursor pos
var inp_value = this.ksearch_input.value.toLowerCase();
var cpos = this.get_caret_pos(this.ksearch_input);
var p = inp_value.lastIndexOf(this.ksearch_value, cpos);
// replace search string with full address
var pre = this.ksearch_input.value.substring(0, p);
var end = this.ksearch_input.value.substring(p+this.ksearch_value.length, this.ksearch_input.value.length);
var insert = this.env.contacts[this.ksearch_selected]+', ';
this.ksearch_input.value = pre + insert + end;
//this.ksearch_input.value = this.ksearch_input.value.substring(0, p)+insert;
// set caret to insert pos
cpos = p+insert.length;
if (this.ksearch_input.setSelectionRange)
this.ksearch_input.setSelectionRange(cpos, cpos);
// hide ksearch pane
this.ksearch_hide();
if (e.preventDefault)
e.preventDefault();
return false;
case 27: // escape
this.ksearch_hide();
break;
}
// start timer
this.ksearch_timer = setTimeout(this.ref+'.ksearch_get_results()', 200);
this.ksearch_input = obj;
return true;
};
// address search processor
this.ksearch_get_results = function()
{
var inp_value = this.ksearch_input ? this.ksearch_input.value : null;
if (inp_value===null)
return;
// get string from current cursor pos to last comma
var cpos = this.get_caret_pos(this.ksearch_input);
var p = inp_value.lastIndexOf(',', cpos-1);
var q = inp_value.substring(p+1, cpos);
// trim query string
q = q.replace(/(^\s+|\s+$)/g, '').toLowerCase();
if (!q.length || q==this.ksearch_value)
{
if (!q.length && this.ksearch_pane && this.ksearch_pane.visible)
this.ksearch_pane.show(0);
return;
}
this.ksearch_value = q;
// start searching the contact list
var a_results = new Array();
var a_result_ids = new Array();
var c=0;
for (var i=0; i<this.env.contacts.length; i++)
{
if (this.env.contacts[i].toLowerCase().indexOf(q)>=0)
{
a_results[c] = this.env.contacts[i];
a_result_ids[c++] = i;
if (c==15) // limit search results
break;
}
}
// display search results
if (c && a_results.length)
{
var p, ul, li;
// create results pane if not present
if (!this.ksearch_pane)
{
ul = document.createElement('UL');
this.ksearch_pane = new rcube_layer('rcmKSearchpane', {vis:0, zindex:30000});
this.ksearch_pane.elm.appendChild(ul);
this.ksearch_pane.ul = ul;
}
else
ul = this.ksearch_pane.ul;
// remove all search results
ul.innerHTML = '';
// add each result line to list
for (i=0; i<a_results.length; i++)
{
li = document.createElement('LI');
li.innerHTML = a_results[i].replace(/</, '&lt;').replace(/>/, '&gt;');
li._rcm_id = a_result_ids[i];
ul.appendChild(li);
}
// check if last selected item is still in result list
if (this.ksearch_selected!==null)
{
p = find_in_array(this.ksearch_selected, a_result_ids);
if (p>=0 && ul.childNodes)
{
ul.childNodes[p].setAttribute('id', 'rcmksearchSelected');
this.set_classname(ul.childNodes[p], 'selected', true);
}
else
this.ksearch_selected = null;
}
// if no item selected, select the first one
if (this.ksearch_selected===null)
{
ul.firstChild.setAttribute('id', 'rcmksearchSelected');
this.set_classname(ul.firstChild, 'selected', true);
this.ksearch_selected = a_result_ids[0];
}
// resize the containing layer to fit the list
//this.ksearch_pane.resize(ul.offsetWidth, ul.offsetHeight);
// move the results pane right under the input box and make it visible
var pos = rcube_get_object_pos(this.ksearch_input);
this.ksearch_pane.move(pos.x, pos.y+this.ksearch_input.offsetHeight);
this.ksearch_pane.show(1);
}
// hide results pane
else
this.ksearch_hide();
};
this.ksearch_blur = function(e, obj)
{
if (this.ksearch_timer)
clearTimeout(this.ksearch_timer);
this.ksearch_value = '';
this.ksearch_input = null;
this.ksearch_hide();
};
this.ksearch_hide = function()
{
this.ksearch_selected = null;
if (this.ksearch_pane)
this.ksearch_pane.show(0);
};
/*********************************************************/
/********* address book methods *********/
/*********************************************************/
this.list_contacts = function(page)
{
var add_url = '';
var target = window;
if (page && this.current_page==page)
return false;
// load contacts remotely
if (this.gui_objects.contactslist)
{
this.list_contacts_remote(page);
return;
}
if (this.env.contentframe && window.frames && window.frames[this.env.contentframe])
{
target = window.frames[this.env.contentframe];
add_url = '&_framed=1';
}
this.set_busy(true, 'loading');
location.href = this.env.comm_path+(page ? '&_page='+page : '')+add_url;
};
// send remote request to load contacts list
this.list_contacts_remote = function(page)
{
// clear list
var table = this.gui_objects.contactslist;
var tbody = document.createElement('TBODY');
table.insertBefore(tbody, table.tBodies[0]);
table.tBodies[1].style.display = 'none';
this.contact_rows = new Array();
this.list_rows = this.contact_rows;
// send request to server
var url = page ? '&_page='+page : '';
this.set_busy(true, 'loading');
this.http_request('list', url, true);
};
// load contact record
this.load_contact = function(cid, action, framed)
{
var add_url = '';
var target = window;
if (this.env.contentframe && window.frames && window.frames[this.env.contentframe])
{
add_url = '&_framed=1';
target = window.frames[this.env.contentframe];
document.getElementById(this.env.contentframe).style.visibility = 'inherit';
}
else if (framed)
return false;
//if (this.env.framed && add_url=='')
// add_url = '&_framed=1';
if (action && (cid || action=='add'))
{
this.set_busy(true);
target.location.href = this.env.comm_path+'&_action='+action+'&_cid='+cid+add_url;
}
return true;
};
this.delete_contacts = function()
{
// exit if no mailbox specified or if selection is empty
if (!(this.selection.length || this.env.cid) || !confirm(this.get_label('deletecontactconfirm')))
return;
var a_cids = new Array();
if (this.env.cid)
a_cids[a_cids.length] = this.env.cid;
else
{
var id;
for (var n=0; n<this.selection.length; n++)
{
id = this.selection[n];
a_cids[a_cids.length] = id;
// 'remove' row from list (just hide it)
if (this.contact_rows[id].obj)
this.contact_rows[id].obj.style.display = 'none';
}
// hide content frame if we delete the currently displayed contact
if (this.selection.length==1 && this.env.contentframe)
{
var elm = document.getElementById(this.env.contentframe);
elm.style.visibility = 'hidden';
}
}
// send request to server
this.http_request('delete', '_cid='+a_cids.join(',')+'&_from='+(this.env.action ? this.env.action : ''));
return true;
};
// update a contact record in the list
this.update_contact_row = function(cid, cols_arr)
{
if (!this.contact_rows[cid] || !this.contact_rows[cid].obj)
return false;
var row = this.contact_rows[cid].obj;
for (var c=0; c<cols_arr.length; c++){
if (row.cells[c])
row.cells[c].innerHTML = cols_arr[c];
}
return true;
};
// load ldap search form
this.ldappublicsearch = function(action)
{
var add_url = '';
var target = window;
if (this.env.contentframe && window.frames && window.frames[this.env.contentframe])
{
add_url = '&_framed=1';
target = window.frames[this.env.contentframe];
document.getElementById(this.env.contentframe).style.visibility = 'inherit';
}
else
return false;
if (action == 'ldappublicsearch')
target.location.href = this.env.comm_path+'&_action='+action+add_url;
return true;
};
// add ldap contacts to address book
this.add_ldap_contacts = function()
{
if (window.frames[this.env.contentframe].rcmail)
{
var frame = window.frames[this.env.contentframe];
// build the url
var url = '&_framed=1';
var emails = '&_emails=';
var names = '&_names=';
var end = '';
for (var n=0; n<frame.rcmail.selection.length; n++)
{
end = n < frame.rcmail.selection.length - 1 ? ',' : '';
emails += frame.rcmail.ldap_contact_rows[frame.rcmail.selection[n]].obj.cells[1].innerHTML + end;
names += frame.rcmail.ldap_contact_rows[frame.rcmail.selection[n]].obj.cells[0].innerHTML + end;
}
frame.location.href = this.env.comm_path + '&_action=save&_framed=1' + emails + names;
}
return false;
}
/*********************************************************/
/********* user settings methods *********/
/*********************************************************/
// load contact record
this.load_identity = function(id, action)
{
if (action=='edit-identity' && (!id || id==this.env.iid))
return false;
var add_url = '';
var target = window;
if (this.env.contentframe && window.frames && window.frames[this.env.contentframe])
{
add_url = '&_framed=1';
target = window.frames[this.env.contentframe];
document.getElementById(this.env.contentframe).style.visibility = 'inherit';
}
if (action && (id || action=='add-identity'))
{
this.set_busy(true);
target.location.href = this.env.comm_path+'&_action='+action+'&_iid='+id+add_url;
}
return true;
};
this.delete_identity = function(id)
{
// exit if no mailbox specified or if selection is empty
if (!(this.selection.length || this.env.iid))
return;
if (!id)
id = this.env.iid ? this.env.iid : this.selection[0];
/*
// 'remove' row from list (just hide it)
if (this.identity_rows && this.identity_rows[id].obj)
{
this.clear_selection();
this.identity_rows[id].obj.style.display = 'none';
}
*/
// if (this.env.framed && id)
this.set_busy(true);
location.href = this.env.comm_path+'&_action=delete-identity&_iid='+id;
// else if (id)
// this.http_request('delete-identity', '_iid='+id);
return true;
};
// tell server to create and subscribe a new mailbox
this.create_folder = function(name)
{
if (this.edit_folder)
this.reset_folder_rename();
var form;
if ((form = this.gui_objects.editform) && form.elements['_folder_name'])
name = form.elements['_folder_name'].value;
if (name)
this.http_request('create-folder', '_name='+escape(name), true);
else if (form.elements['_folder_name'])
form.elements['_folder_name'].focus();
};
// entry point for folder renaming
this.rename_folder = function(props)
{
var form, oldname, newname;
// rename a specific mailbox
if (props)
this.edit_foldername(props);
// use a dropdown and input field (old behavior)
else if ((form = this.gui_objects.editform) && form.elements['_folder_oldname'] && form.elements['_folder_newname'])
{
oldname = form.elements['_folder_oldname'].value;
newname = form.elements['_folder_newname'].value;
}
if (oldname && newname)
this.http_request('rename-folder', '_folder_oldname='+escape(oldname)+'&_folder_newname='+escape(newname));
};
// start editing the mailbox name.
// this will replace the name string with an input field
this.edit_foldername = function(folder)
{
var temp, row, form;
var id = this.get_folder_row_id(folder);
// reset current renaming
if (temp = this.edit_folder)
{
this.reset_folder_rename();
if (temp == id)
return;
}
if (id && (row = document.getElementById(id)))
{
this.name_input = document.createElement('INPUT');
this.name_input.value = this.env.subscriptionrows[id];
this.name_input.style.width = '100%';
this.name_input.onkeypress = function(e){ rcmail.name_input_keypress(e); };
row.cells[0].replaceChild(this.name_input, row.cells[0].firstChild);
this.edit_folder = id;
this.name_input.select();
if (form = this.gui_objects.editform)
form.onsubmit = function(){ return false; };
}
};
// remove the input field and write the current mailbox name to the table cell
this.reset_folder_rename = function()
{
var cell = this.name_input ? this.name_input.parentNode : null;
if (cell && this.edit_folder)
cell.innerHTML = this.env.subscriptionrows[this.edit_folder];
this.edit_folder = null;
};
// handler for keyboard events on the input field
this.name_input_keypress = function(e)
{
var key = document.all ? event.keyCode : document.getElementById ? e.keyCode : 0;
// enter
if (key==13)
{
var newname = this.name_input ? this.name_input.value : null;
if (this.edit_folder && newname)
this.http_request('rename-folder', '_folder_oldname='+escape(this.env.subscriptionrows[this.edit_folder])+'&_folder_newname='+escape(newname));
}
// escape
else if (key==27)
this.reset_folder_rename();
};
// delete a specific mailbox with all its messages
this.delete_folder = function(folder)
{
if (this.edit_folder)
this.reset_folder_rename();
if (folder)
this.http_request('delete-folder', '_mboxes='+escape(folder));
};
// add a new folder to the subscription list by cloning a folder row
this.add_folder_row = function(name, replace)
{
name = name.replace('\\',"");
if (!this.gui_objects.subscriptionlist)
return false;
for (var refid in this.env.subscriptionrows)
if (this.env.subscriptionrows[refid]!=null)
break;
var refrow, form;
var tbody = this.gui_objects.subscriptionlist.tBodies[0];
var id = replace && replace.id ? replace.id : tbody.childNodes.length+1;
if (!id || !(refrow = document.getElementById(refid)))
{
// Refresh page if we don't have a table row to clone
location.href = this.env.comm_path+'&_action=folders';
}
else
{
// clone a table row if there are existing rows
var row = this.clone_table_row(refrow);
row.id = 'rcmrow'+id;
if (replace)
tbody.replaceChild(row, replace);
else
tbody.appendChild(row);
}
// add to folder/row-ID map
this.env.subscriptionrows[row.id] = name;
// set folder name
row.cells[0].innerHTML = name;
if (row.cells[1] && row.cells[1].firstChild.tagName=='INPUT')
{
row.cells[1].firstChild.value = name;
row.cells[1].firstChild.checked = true;
}
if (row.cells[2] && row.cells[2].firstChild.tagName=='A')
row.cells[2].firstChild.onclick = new Function(this.ref+".command('rename-folder','"+name.replace('\'','\\\'')+"')");
if (row.cells[3] && row.cells[3].firstChild.tagName=='A')
row.cells[3].firstChild.onclick = new Function(this.ref+".command('delete-folder','"+name.replace('\'','\\\'')+"')");
// add new folder to rename-folder list and clear input field
- if (!replace && (form = this.gui_objects.editform) && form.elements['_folder_name'])
+ if (!replace && (form = this.gui_objects.editform))
{
- form.elements['_folder_oldname'].options[form.elements['_folder_oldname'].options.length] = new Option(name,name);
- form.elements['_folder_name'].value = '';
+ if (form.elements['_folder_oldname'])
+ form.elements['_folder_oldname'].options[form.elements['_folder_oldname'].options.length] = new Option(name,name);
+ if (form.elements['_folder_name'])
+ form.elements['_folder_name'].value = '';
}
};
// replace an existing table row with a new folder line
this.replace_folder_row = function(newfolder, oldfolder)
{
var id = this.get_folder_row_id(oldfolder);
var row = document.getElementById(id);
// replace an existing table row (if found)
this.add_folder_row(newfolder, row);
this.env.subscriptionrows[id] = null;
// rename folder in rename-folder dropdown
var form, elm;
if ((form = this.gui_objects.editform) && (elm = form.elements['_folder_oldname']))
{
for (var i=0;i<elm.options.length;i++)
{
if (elm.options[i].value == oldfolder)
{
elm.options[i].text = newfolder;
elm.options[i].value = newfolder;
break;
}
}
form.elements['_folder_newname'].value = '';
}
};
// remove the table row of a specific mailbox from the table
// (the row will not be removed, just hidden)
this.remove_folder_row = function(folder)
{
var row;
var id = this.get_folder_row_id(folder);
if (id && (row = document.getElementById(id)))
row.style.display = 'none';
// remove folder from rename-folder list
var form;
if ((form = this.gui_objects.editform) && form.elements['_folder_oldname'])
{
for (var i=0;i<form.elements['_folder_oldname'].options.length;i++)
{
if (form.elements['_folder_oldname'].options[i].value == folder)
{
form.elements['_folder_oldname'].options[i] = null;
break;
}
}
}
- form.elements['_folder_newname'].value = '';
+ if (form && form.elements['_folder_newname'])
+ form.elements['_folder_newname'].value = '';
};
this.subscribe_folder = function(folder)
{
var form;
if ((form = this.gui_objects.editform) && form.elements['_unsubscribed'])
this.change_subscription('_unsubscribed', '_subscribed', 'subscribe');
else if (folder)
this.http_request('subscribe', '_mboxes='+escape(folder));
};
this.unsubscribe_folder = function(folder)
{
var form;
if ((form = this.gui_objects.editform) && form.elements['_subscribed'])
this.change_subscription('_subscribed', '_unsubscribed', 'unsubscribe');
else if (folder)
this.http_request('unsubscribe', '_mboxes='+escape(folder));
};
this.change_subscription = function(from, to, action)
{
var form;
if (form = this.gui_objects.editform)
{
var a_folders = new Array();
var list_from = form.elements[from];
for (var i=0; list_from && i<list_from.options.length; i++)
{
if (list_from.options[i] && list_from.options[i].selected)
{
a_folders[a_folders.length] = list_from.options[i].value;
list_from[i] = null;
i--;
}
}
// yes, we have some folders selected
if (a_folders.length)
{
var list_to = form.elements[to];
var index;
for (var n=0; n<a_folders.length; n++)
{
index = list_to.options.length;
list_to[index] = new Option(a_folders[n]);
}
this.http_request(action, '_mboxes='+escape(a_folders.join(',')));
}
}
};
// helper method to find a specific mailbox row ID
this.get_folder_row_id = function(folder)
{
for (var id in this.env.subscriptionrows)
if (this.env.subscriptionrows[id]==folder)
break;
return id;
};
// duplicate a specific table row
this.clone_table_row = function(row)
{
var cell, td;
var new_row = document.createElement('TR');
for(var n=0; n<row.childNodes.length; n++)
{
cell = row.childNodes[n];
td = document.createElement('TD');
if (cell.className)
td.className = cell.className;
if (cell.align)
td.setAttribute('align', cell.align);
td.innerHTML = cell.innerHTML;
new_row.appendChild(td);
}
return new_row;
};
/*********************************************************/
/********* GUI functionality *********/
/*********************************************************/
// eable/disable buttons for page shifting
this.set_page_buttons = function()
{
this.enable_command('nextpage', (this.env.pagecount > this.env.current_page));
this.enable_command('previouspage', (this.env.current_page > 1));
}
// set button to a specific state
this.set_button = function(command, state)
{
var a_buttons = this.buttons[command];
var button, obj;
if(!a_buttons || !a_buttons.length)
return;
for(var n=0; n<a_buttons.length; n++)
{
button = a_buttons[n];
obj = document.getElementById(button.id);
// get default/passive setting of the button
if (obj && button.type=='image' && !button.status)
button.pas = obj._original_src ? obj._original_src : obj.src;
else if (obj && !button.status)
button.pas = String(obj.className);
// set image according to button state
if (obj && button.type=='image' && button[state])
{
button.status = state;
obj.src = button[state];
}
// set class name according to button state
else if (obj && typeof(button[state])!='undefined')
{
button.status = state;
obj.className = button[state];
}
// disable/enable input buttons
if (obj && button.type=='input')
{
button.status = state;
obj.disabled = !state;
}
}
};
// mouse over button
this.button_over = function(command, id)
{
var a_buttons = this.buttons[command];
var button, img;
if(!a_buttons || !a_buttons.length)
return;
for(var n=0; n<a_buttons.length; n++)
{
button = a_buttons[n];
if(button.id==id && button.status=='act')
{
img = document.getElementById(button.id);
if (img && button.over)
img.src = button.over;
}
}
};
// mouse down on button
this.button_sel = function(command, id)
{
var a_buttons = this.buttons[command];
var button, img;
if(!a_buttons || !a_buttons.length)
return;
for(var n=0; n<a_buttons.length; n++)
{
button = a_buttons[n];
if(button.id==id && button.status=='act')
{
img = document.getElementById(button.id);
if (img && button.sel)
img.src = button.sel;
}
}
};
// mouse out of button
this.button_out = function(command, id)
{
var a_buttons = this.buttons[command];
var button, img;
if(!a_buttons || !a_buttons.length)
return;
for(var n=0; n<a_buttons.length; n++)
{
button = a_buttons[n];
if(button.id==id && button.status=='act')
{
img = document.getElementById(button.id);
if (img && button.act)
img.src = button.act;
}
}
};
// set/unset a specific class name
this.set_classname = function(obj, classname, set)
{
var reg = new RegExp('\s*'+classname, 'i');
if (!set && obj.className.match(reg))
obj.className = obj.className.replace(reg, '');
else if (set && !obj.className.match(reg))
obj.className += ' '+classname;
};
// display a specific alttext
this.alttext = function(text)
{
};
// display a system message
this.display_message = function(msg, type, hold)
{
this.set_busy(false);
if (!this.loaded) // save message in order to display after page loaded
{
this.pending_message = new Array(msg, type);
return true;
}
if (!this.gui_objects.message)
return false;
-
+
if (this.message_timer)
clearTimeout(this.message_timer);
var cont = msg;
if (type)
cont = '<div class="'+type+'">'+cont+'</div>';
this.gui_objects.message._rcube = this;
this.gui_objects.message.innerHTML = cont;
this.gui_objects.message.style.display = 'block';
if (type!='loading')
this.gui_objects.message.onmousedown = function(){ this._rcube.hide_message(); return true; };
if (!hold)
this.message_timer = setTimeout(this.ref+'.hide_message()', this.message_time);
};
// make a message row disapear
this.hide_message = function()
{
if (this.gui_objects.message)
{
this.gui_objects.message.style.display = 'none';
this.gui_objects.message.onmousedown = null;
}
};
// mark a mailbox as selected and set environment variable
this.select_mailbox = function(mbox)
{
if (this.gui_objects.mailboxlist )
{
var item, reg, text_obj;
var current_li = this.get_mailbox_li();
var mbox_li = this.get_mailbox_li(mbox);
if (current_li)
{
this.set_classname(current_li, 'selected', false);
this.set_classname(current_li, 'unfocused', false);
}
if (mbox_li || this.env.mailbox == mbox)
{
this.set_classname(mbox_li, 'unfocused', false);
this.set_classname(mbox_li, 'selected', true);
}
}
this.env.mailbox = mbox;
};
// for reordering column array, Konqueror workaround
this.set_message_coltypes = function(coltypes)
{
this.coltypes = coltypes;
// set correct list titles
var cell, col;
var thead = this.gui_objects.messagelist ? this.gui_objects.messagelist.tHead : null;
for (var n=0; thead && n<this.coltypes.length; n++)
{
col = this.coltypes[n];
if ((cell = thead.rows[0].cells[n+1]) && (col=='from' || col=='to'))
{
// if we have links for sorting, it's a bit more complicated...
if (cell.firstChild && cell.firstChild.tagName=='A')
{
cell.firstChild.innerHTML = this.get_label(this.coltypes[n]);
cell.firstChild.onclick = function(){ return rcmail.command('sort', this.__col, this); };
cell.firstChild.__col = col;
}
else
cell.innerHTML = this.get_label(this.coltypes[n]);
cell.id = 'rcmHead'+col;
}
}
};
// create a table row in the message list
this.add_message_row = function(uid, cols, flags, attachment, attop)
{
if (!this.gui_objects.messagelist || !this.gui_objects.messagelist.tBodies[0])
return false;
var tbody = this.gui_objects.messagelist.tBodies[0];
var rowcount = tbody.rows.length;
var even = rowcount%2;
this.env.messages[uid] = {deleted:flags.deleted?1:0,
replied:flags.replied?1:0,
unread:flags.unread?1:0};
var row = document.createElement('TR');
row.id = 'rcmrow'+uid;
row.className = 'message '+(even ? 'even' : 'odd')+(flags.unread ? ' unread' : '')+(flags.deleted ? ' deleted' : '');
if (this.in_selection(uid))
row.className += ' selected';
var icon = flags.deleted && this.env.deletedicon ? this.env.deletedicon:
(flags.unread && this.env.unreadicon ? this.env.unreadicon :
(flags.replied && this.env.repliedicon ? this.env.repliedicon : this.env.messageicon));
var col = document.createElement('TD');
col.className = 'icon';
col.innerHTML = icon ? '<img src="'+icon+'" alt="" border="0" />' : '';
row.appendChild(col);
// add each submitted col
for (var n = 0; n < this.coltypes.length; n++)
{
var c = this.coltypes[n];
col = document.createElement('TD');
col.className = String(c).toLowerCase();
col.innerHTML = cols[c];
row.appendChild(col);
}
col = document.createElement('TD');
col.className = 'icon';
col.innerHTML = attachment && this.env.attachmenticon ? '<img src="'+this.env.attachmenticon+'" alt="" border="0" />' : '';
row.appendChild(col);
if (attop && tbody.rows.length)
tbody.insertBefore(row, tbody.firstChild);
else
tbody.appendChild(row);
this.init_message_row(row);
};
// replace content of row count display
this.set_rowcount = function(text)
{
if (this.gui_objects.countdisplay)
this.gui_objects.countdisplay.innerHTML = text;
// update page navigation buttons
this.set_page_buttons();
};
// replace content of quota display
this.set_quota = function(text)
{
if (this.gui_objects.quotadisplay)
this.gui_objects.quotadisplay.innerHTML = text;
};
// update the mailboxlist
this.set_unread_count = function(mbox, count, set_title)
{
if (!this.gui_objects.mailboxlist)
return false;
if (mbox==this.env.mailbox)
set_title = true;
var reg, text_obj;
var item = this.get_mailbox_li(mbox);
mbox = String(mbox).toLowerCase().replace(this.mbox_expression, '');
if (item && 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, '');
// set the right classes
this.set_classname(item, 'unread', count>0 ? true : false);
}
// set unread count to window title
reg = /^\([0-9]+\)\s+/i;
if (set_title && document.title)
{
var doc_title = String(document.title);
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, '');
}
};
// add row to contacts list
this.add_contact_row = function(cid, cols)
{
if (!this.gui_objects.contactslist || !this.gui_objects.contactslist.tBodies[0])
return false;
var tbody = this.gui_objects.contactslist.tBodies[0];
var rowcount = tbody.rows.length;
var even = rowcount%2;
var row = document.createElement('TR');
row.id = 'rcmrow'+cid;
row.className = 'contact '+(even ? 'even' : 'odd');
if (this.in_selection(cid))
row.className += ' selected';
// add each submitted col
for (var c in cols)
{
col = document.createElement('TD');
col.className = String(c).toLowerCase();
col.innerHTML = cols[c];
row.appendChild(col);
}
tbody.appendChild(row);
this.init_table_row(row, 'contact_rows');
};
/********************************************************/
/********* drag & drop methods *********/
/********************************************************/
this.drag_mouse_move = function(e)
{
if (this.drag_start)
{
if (!this.draglayer)
this.draglayer = new rcube_layer('rcmdraglayer', {x:0, y:0, width:300, vis:0, zindex:2000});
// get subjects of selectedd messages
var names = '';
var c, subject, obj;
for(var n=0; n<this.selection.length; n++)
{
if (n>12) // only show 12 lines
{
names += '...';
break;
}
if (this.message_rows[this.selection[n]].obj)
{
obj = this.message_rows[this.selection[n]].obj;
subject = '';
for(c=0; c<obj.childNodes.length; c++)
if (!subject && obj.childNodes[c].nodeName=='TD' && obj.childNodes[c].firstChild && obj.childNodes[c].firstChild.nodeType==3)
{
subject = obj.childNodes[c].firstChild.data;
names += (subject.length > 50 ? subject.substring(0, 50)+'...' : subject) + '<br />';
}
}
}
this.draglayer.write(names);
this.draglayer.show(1);
}
var pos = this.get_mouse_pos(e);
this.draglayer.move(pos.x+20, pos.y-5);
this.drag_start = false;
this.drag_active = true;
return false;
};
this.drag_mouse_up = function()
{
document.onmousemove = null;
if (this.draglayer && this.draglayer.visible)
this.draglayer.show(0);
this.drag_active = false;
return false;
};
/********************************************************/
/********* remote request methods *********/
/********************************************************/
this.http_sockets = new Array();
// find a non-busy socket or create a new one
this.get_request_obj = function()
{
for (var n=0; n<this.http_sockets.length; n++)
{
if (!this.http_sockets[n].busy)
return this.http_sockets[n];
}
// create a new XMLHTTP object
var i = this.http_sockets.length;
this.http_sockets[i] = new rcube_http_request();
return this.http_sockets[i];
};
// send a http request to the server
this.http_request = function(action, querystring, lock)
{
var request_obj = this.get_request_obj();
querystring += '&_remote=1';
// add timestamp to request url to avoid cacheing problems in Safari
if (bw.safari)
querystring += '&_ts='+(new Date().getTime());
// send request
if (request_obj)
{
// prompt('request', this.env.comm_path+'&_action='+escape(action)+'&'+querystring);
console('HTTP request: '+this.env.comm_path+'&_action='+escape(action)+'&'+querystring);
if (lock)
this.set_busy(true);
request_obj.__lock = lock ? true : false;
request_obj.__action = action;
request_obj.onerror = function(o){ rcube_webmail_client.http_error(o); };
request_obj.oncomplete = function(o){ rcube_webmail_client.http_response(o); };
request_obj.GET(this.env.comm_path+'&_action='+escape(action)+'&'+querystring);
}
};
// handle HTTP response
this.http_response = function(request_obj)
{
var ctype = request_obj.get_header('Content-Type');
if (ctype){
ctype = String(ctype).toLowerCase();
var ctype_array=ctype.split(";");
ctype = ctype_array[0];
}
this.set_busy(false);
console(request_obj.get_text());
// if we get javascript code from server -> execute it
if (request_obj.get_text() && (ctype=='text/javascript' || ctype=='application/x-javascript'))
eval(request_obj.get_text());
// process the response data according to the sent action
switch (request_obj.__action)
{
case 'delete':
case 'moveto':
if (this.env.action=='show')
this.command('list');
break;
case 'list':
if (this.env.messagecount)
this.enable_command('purge', (this.env.mailbox==this.env.trash_mailbox));
case 'expunge':
this.enable_command('select-all', 'select-none', 'expunge', this.env.messagecount ? true : false);
break;
}
request_obj.reset();
};
// handle HTTP request errors
this.http_error = function(request_obj)
{
alert('Error sending request: '+request_obj.url);
if (request_obj.__lock)
this.set_busy(false);
request_obj.reset();
request_obj.__lock = false;
};
// use an image to send a keep-alive siganl to the server
this.send_keep_alive = function()
{
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()
{
this.set_busy(true, 'checkingmail');
var d = new Date();
this.http_request('check-recent', '_t='+d.getTime());
};
/********************************************************/
/********* helper methods *********/
/********************************************************/
// check if we're in show mode or if we have a unique selection
// and return the message uid
this.get_single_uid = function()
{
return this.env.uid ? this.env.uid : (this.selection.length==1 ? this.selection[0] : null);
};
// same as above but for contacts
this.get_single_cid = function()
{
return this.env.cid ? this.env.cid : (this.selection.length==1 ? this.selection[0] : null);
};
/* deprecated methods
// check if Shift-key is pressed on event
this.check_shiftkey = function(e)
{
if(!e && window.event)
e = window.event;
if(bw.linux && bw.ns4 && e.modifiers)
return true;
else if((bw.ns4 && e.modifiers & Event.SHIFT_MASK) || (e && e.shiftKey))
return true;
else
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;
}
*/
// returns modifier key (constants defined at top of file)
this.get_modifier = function(e)
{
var opcode = 0;
e = e || window.event;
if (bw.mac && e)
{
opcode += (e.metaKey && CONTROL_KEY) + (e.shiftKey && SHIFT_KEY);
return opcode;
}
if (e)
{
opcode += (e.ctrlKey && CONTROL_KEY) + (e.shiftKey && SHIFT_KEY);
return opcode;
}
if (e.cancelBubble)
{
e.cancelBubble = true;
e.returnValue = false;
}
else if (e.preventDefault)
e.preventDefault();
}
this.get_mouse_pos = function(e)
{
if(!e) e = window.event;
var mX = (e.pageX) ? e.pageX : e.clientX;
var mY = (e.pageY) ? e.pageY : e.clientY;
if(document.body && document.all)
{
mX += document.body.scrollLeft;
mY += document.body.scrollTop;
}
return { x:mX, y:mY };
};
this.get_caret_pos = function(obj)
{
if (typeof(obj.selectionEnd)!='undefined')
return obj.selectionEnd;
else if (document.selection && document.selection.createRange)
{
var range = document.selection.createRange();
if (range.parentElement()!=obj)
return 0;
var gm = range.duplicate();
if (obj.tagName=='TEXTAREA')
gm.moveToElementText(obj);
else
gm.expand('textedit');
gm.setEndPoint('EndToStart', range);
var p = gm.text.length;
return p<=obj.value.length ? p : -1;
}
else
return obj.value.length;
};
this.set_caret2start = function(obj)
{
if (obj.createTextRange)
{
var range = obj.createTextRange();
range.collapse(true);
range.select();
}
else if (obj.setSelectionRange)
obj.setSelectionRange(0,0);
obj.focus();
};
// set all fields of a form disabled
this.lock_form = function(form, lock)
{
if (!form || !form.elements)
return;
var type;
for (var n=0; n<form.elements.length; n++)
{
type = form.elements[n];
if (type=='hidden')
continue;
form.elements[n].disabled = lock;
}
};
} // end object rcube_webmail
// class for HTTP requests
function rcube_http_request()
{
this.url = '';
this.busy = false;
this.xmlhttp = null;
// reset object properties
this.reset = function()
{
// set unassigned event handlers
this.onloading = function(){ };
this.onloaded = function(){ };
this.oninteractive = function(){ };
this.oncomplete = function(){ };
this.onabort = function(){ };
this.onerror = function(){ };
this.url = '';
this.busy = false;
this.xmlhttp = null;
}
// create HTMLHTTP object
this.build = function()
{
if (window.XMLHttpRequest)
this.xmlhttp = new XMLHttpRequest();
else if (window.ActiveXObject)
this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
else
{
}
}
// sedn GET request
this.GET = function(url)
{
this.build();
if (!this.xmlhttp)
{
this.onerror(this);
return false;
}
var ref = this;
this.url = url;
this.busy = true;
this.xmlhttp.onreadystatechange = function(){ ref.xmlhttp_onreadystatechange(); };
this.xmlhttp.open('GET', url);
this.xmlhttp.send(null);
};
this.POST = function(url, a_param)
{
// not implemented yet
};
// handle onreadystatechange event
this.xmlhttp_onreadystatechange = function()
{
if(this.xmlhttp.readyState == 1)
this.onloading(this);
else if(this.xmlhttp.readyState == 2)
this.onloaded(this);
else if(this.xmlhttp.readyState == 3)
this.oninteractive(this);
else if(this.xmlhttp.readyState == 4)
{
if(this.xmlhttp.status == 0)
this.onabort(this);
else if(this.xmlhttp.status == 200)
this.oncomplete(this);
else
this.onerror(this);
this.busy = false;
}
}
// getter method for HTTP headers
this.get_header = function(name)
{
return this.xmlhttp.getResponseHeader(name);
};
this.get_text = function()
{
return this.xmlhttp.responseText;
};
this.get_xml = function()
{
return this.xmlhttp.responseXML;
};
this.reset();
} // end class rcube_http_request
function console(str)
{
if (document.debugform && document.debugform.console)
document.debugform.console.value += str+'\n--------------------------------------\n';
}
// set onload handler
window.onload = function(e)
{
if (window.rcube_webmail_client)
rcube_webmail_client.init();
};
diff --git a/program/localization/de_CH/messages.inc b/program/localization/de_CH/messages.inc
index d3314a9d6..f1c7e5be3 100644
--- a/program/localization/de_CH/messages.inc
+++ b/program/localization/de_CH/messages.inc
@@ -1,106 +1,108 @@
<?php
/*
+-----------------------------------------------------------------------+
| language/de_CH/messages.inc |
| |
| Language file of the RoundCube Webmail client |
| Copyright (C) 2005, RoundCube Dev. - Switzerland |
| Licensed under the GNU GPL |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
$Id$
*/
$messages = array();
$messages['loginfailed'] = 'Login fehlgeschlagen';
$messages['cookiesdisabled'] = 'Ihr Browser akzeptiert keine Cookies';
$messages['sessionerror'] = 'Ihre Session ist ungültig oder abgelaufen';
$messages['imaperror'] = 'Keine Verbindung zum IMAP Server';
$messages['nomessagesfound'] = 'Keine Nachrichten in diesem Ordner';
$messages['loggedout'] = 'Sie haben Ihre Session erfolgreich beendet. Auf Wiedersehen!';
$messages['mailboxempty'] = 'Ordner ist leer';
$messages['loading'] = $messages['loadingdata'] = 'Daten werden geladen...';
$messages['checkingmail'] = 'Überprüfung auf neue Nachrichten...';
$messages['sendingmessage'] = 'Nachricht wird gesendet...';
$messages['messagesent'] = 'Nachricht erfolgreich gesendet';
$messages['savingmessage'] = 'Nachricht wird gespeichert...';
$messages['messagesaved'] = 'Nachricht als Entwurf gespeichert';
$messages['successfullysaved'] = 'Erfolgreich gespeichert';
$messages['addedsuccessfully'] = 'Kontakt zum Adressbuch hinzugefügt';
$messages['contactexists'] = 'Es existiert bereits ein Eintrag mit dieser E-Mail-Adresse';
$messages['blockedimages'] = 'Um Ihre Privatsphäre zur schützen, wurden externe Bilder blockiert.';
$messages['encryptedmessage'] = 'Dies ist eine verschlüsselte Nachricht und kann leider nicht angezeigt werden.';
$messages['nocontactsfound'] = 'Keine Kontakte gefunden';
$messages['sendingfailed'] = 'Versand der Nachricht fehlgeschlagen';
$messages['errorsaving'] = 'Beim Speichern ist ein Fehler aufgetreten';
$messages['errormoving'] = 'Nachricht konnte nicht verschoben werden';
$messages['errordeleting'] = 'Nachricht konnte nicht gelöscht werden';
$messages['deletecontactconfirm'] = 'Wollen Sie die ausgewählten Kontakte wirklich löschen';
$messages['deletefolderconfirm'] = 'Wollen Sie diesen Ordner wirklich löschen?';
$messages['purgefolderconfirm'] = 'Wollen Sie diesen Ordner wirklich leeren?';
$messages['formincomplete'] = 'Das Formular wurde nicht vollständig ausgefüllt';
$messages['noemailwarning'] = 'Bitte geben Sie eine gültige E-Mail-Adresse ein';
$messages['nonamewarning'] = 'Bitte geben Sie einen Namen ein';
$messages['nopagesizewarning'] = 'Bitte geben Sie eine Einträge pro Seite ein';
$messages['norecipientwarning'] = 'Bitte geben Sie mindestens einen Empfänger an';
$messages['nosubjectwarning'] = 'Die Betreffzeile ist leer. Möchten Sie jetzt einen Betreff eingeben?';
$messages['nobodywarning'] = 'Diese Nachricht ohne Inhalt senden?';
$messages['notsentwarning'] = 'Ihre Nachricht wurde nicht gesendet. Wollen Sie die Nachricht verwerfen?';
$messages['noldapserver'] = 'Bitte wählen Sie einen LDAP-Server aus';
$messages['nocontactsreturned'] = 'Es wurden keine Kontakte gefunden';
$messages['nosearchname'] = 'Bitte geben Sie einen Namen oder eine E-Mail-Adresse ein';
$messages['searchsuccessful'] = '$nr Nachrichten gefunden';
$messages['searchnomatch'] = 'Keine Treffer';
$messages['searching'] = 'Suche...';
$messages['checking'] = 'Prüfe...';
$messages['nospellerrors'] = 'Keine Rechtschreibfehler gefunden';
+$messages['folderdeleted'] = 'Ordner erfolgreich gelöscht';
+
?>
\ No newline at end of file
diff --git a/program/localization/de_DE/messages.inc b/program/localization/de_DE/messages.inc
index c6ca701a0..8a178edba 100644
--- a/program/localization/de_DE/messages.inc
+++ b/program/localization/de_DE/messages.inc
@@ -1,107 +1,109 @@
<?php
/*
+-----------------------------------------------------------------------+
| language/de_DE/messages.inc |
| |
| Language file of the RoundCube Webmail client |
| Copyright (C) 2005, RoundCube Dev. - Switzerland |
| Licensed under the GNU GPL |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
| de_DE translation: Stephan Diehl <info@sd-edv.de> |
+-----------------------------------------------------------------------+
$Id$
*/
$messages = array();
$messages['loginfailed'] = 'Anmelden fehlgeschlagen';
$messages['cookiesdisabled'] = 'Ihr Browser akzeptiert keine Cookies';
$messages['sessionerror'] = 'Ihre Session ist ungültig oder abgelaufen';
$messages['imaperror'] = 'Keine Verbindung zum IMAP Server';
$messages['nomessagesfound'] = 'Keine Nachrichten in diesem Ordner';
$messages['loggedout'] = 'Sie haben Ihre Session erfolgreich beendet. Auf Wiedersehen!';
$messages['mailboxempty'] = 'Ordner ist leer';
$messages['loading'] = $messages['loadingdata'] = 'Daten werden geladen...';
$messages['checkingmail'] = 'Überprüfung auf neue Nachrichten...';
$messages['sendingmessage'] = 'Nachricht wird gesendet...';
$messages['messagesent'] = 'Nachricht erfolgreich gesendet';
$messages['savingmessage'] = 'Nachricht wird gespeichert...';
$messages['messagesaved'] = 'Nachricht als Entwurf gespeichert';
$messages['successfullysaved'] = 'Erfolgreich gespeichert';
$messages['addedsuccessfully'] = 'Kontakt zum Adressbuch hinzugefügt';
$messages['contactexists'] = 'Es existiert bereits ein Eintrag mit dieser E-Mail-Adresse';
$messages['blockedimages'] = 'Um Ihre Privatsphäre zur schützen, wurden externe Bilder blockiert.';
$messages['encryptedmessage'] = 'Dies ist eine verschlüsselte Nachricht und kann leider nicht angezeigt werden.';
$messages['nocontactsfound'] = 'Keine Kontakte gefunden';
$messages['sendingfailed'] = 'Versand der Nachricht fehlgeschlagen';
$messages['errorsaving'] = 'Beim Speichern ist ein Fehler aufgetreten';
$messages['errormoving'] = 'Nachricht konnte nicht verschoben werden';
$messages['errordeleting'] = 'Nachricht konnte nicht gelöscht werden';
$messages['deletecontactconfirm'] = 'Wollen Sie die ausgewählten Kontakte wirklich löschen';
$messages['deletefolderconfirm'] = 'Wollen Sie diesen Ordner wirklich löschen?';
$messages['purgefolderconfirm'] = 'Wollen Sie diesen Ordner wirklich leeren?';
$messages['formincomplete'] = 'Das Formular wurde nicht vollständig ausgefüllt';
$messages['noemailwarning'] = 'Bitte geben Sie eine gültige E-Mail-Adresse ein';
$messages['nonamewarning'] = 'Bitte geben Sie einen Namen ein';
$messages['nopagesizewarning'] = 'Bitte geben Sie eine Einträge pro Seite ein';
$messages['norecipientwarning'] = 'Bitte geben Sie mindestens einen Empfänger an';
$messages['nosubjectwarning'] = 'Die Betreffzeile ist leer. Möchten Sie jetzt einen Betreff eingeben?';
$messages['nobodywarning'] = 'Diese Nachricht ohne Inhalt senden?';
$messages['notsentwarning'] = 'Ihre Nachricht wurde nicht gesendet. Wollen Sie die Nachricht verwerfen?';
$messages['noldapserver'] = 'Bitte wählen Sie einen LDAP-Server aus';
$messages['nocontactsreturned'] = 'Es wurden keine Kontakte gefunden';
$messages['nosearchname'] = 'Bitte geben Sie einen Namen oder eine E-Mail-Adresse ein';
$messages['searchsuccessful'] = '$nr Nachrichten gefunden';
$messages['searchnomatch'] = 'Keine Treffer';
$messages['searching'] = 'Suche...';
$messages['checking'] = 'Prüfe...';
$messages['nospellerrors'] = 'Keine Rechtschreibfehler gefunden';
+$messages['folderdeleted'] = 'Ordner erfolgreich gelöscht';
+
?>
\ No newline at end of file
diff --git a/program/localization/en_GB/messages.inc b/program/localization/en_GB/messages.inc
index 262e30007..7a60b835d 100644
--- a/program/localization/en_GB/messages.inc
+++ b/program/localization/en_GB/messages.inc
@@ -1,93 +1,106 @@
<?php
/*
+-----------------------------------------------------------------------+
| language/en_GB/messages.inc |
| |
| Language file of the RoundCube Webmail client |
| Copyright (C) 2005, RoundCube Dev. - Switzerland |
| Licensed under the GNU GPL |
| |
+-----------------------------------------------------------------------+
| Author: Weiran Zhang (weiran@weiran.co.uk) |
+-----------------------------------------------------------------------+
$Id$
*/
$messages = array();
$messages['loginfailed'] = 'Login failed';
$messages['cookiesdisabled'] = 'Your browser does not accept cookies';
$messages['sessionerror'] = 'Your session is invalid or expired';
$messages['imaperror'] = 'Connection to IMAP server failed';
$messages['nomessagesfound'] = 'No messages found in this mailbox';
$messages['loggedout'] = 'You have successfully terminated the session. Good bye!';
$messages['mailboxempty'] = 'Mailbox is empty';
$messages['loading'] = 'Loading...';
$messages['loadingdata'] = 'Loading data...';
$messages['checkingmail'] = 'Checking for new messages...';
$messages['messagesent'] = 'Message sent successfully';
$messages['savingmessage'] = 'Saving message...';
$messages['messagesaved'] = 'Message saved to Drafts';
$messages['successfullysaved'] = 'Successfully saved';
$messages['addedsuccessfully'] = 'Contact added successfully to address book';
$messages['contactexists'] = 'A contact with this e-mail address already exists';
$messages['blockedimages'] = 'To protect your privacy, remote images are blocked in this message.';
$messages['encryptedmessage'] = 'This is an encrypted message and can not be displayed. Sorry!';
$messages['nocontactsfound'] = 'No contacts found';
$messages['sendingfailed'] = 'Failed to send message';
$messages['errorsaving'] = 'An error occured while saving';
$messages['errormoving'] = 'Could not move the message';
$messages['errordeleting'] = 'Could not delete the message';
$messages['deletecontactconfirm'] = 'Do you really want to delete the selected contact(s)?';
$messages['deletefolderconfirm'] = 'Do you really want to delete this folder?';
$messages['formincomplete'] = 'The form was not completely filled out';
$messages['noemailwarning'] = 'Please enter a valid email address';
$messages['nonamewarning'] = 'Please enter a name';
$messages['nopagesizewarning'] = 'Please enter a page size';
$messages['norecipientwarning'] = 'Please enter at least one recipient';
$messages['nosubjectwarning'] = 'The "Subject" field is empty. Would you like to enter one now?';
$messages['nobodywarning'] = 'Send this message without text?';
$messages['notsentwarning'] = 'Message has not been sent. Do you want to discard your message?';
$messages['noldapserver'] = 'Please select an ldap server to search';
$messages['nocontactsreturned'] = 'No contacts were found';
$messages['nosearchname'] = 'Please enter a contact name or email address';
+$messages['searchsuccessful'] = '$nr messages found';
+
+$messages['searchnomatch'] = 'Search returned no matches';
+
+$messages['searching'] = 'Searching...';
+
+$messages['checking'] = 'Checking...';
+
+$messages['nospellerrors'] = 'No spelling errors found';
+
+$messages['folderdeleted'] = 'Folder successfully deleted';
+
+
?>
diff --git a/program/localization/en_US/messages.inc b/program/localization/en_US/messages.inc
index a5ffc091c..f406ff128 100644
--- a/program/localization/en_US/messages.inc
+++ b/program/localization/en_US/messages.inc
@@ -1,108 +1,110 @@
<?php
/*
+-----------------------------------------------------------------------+
| language/en/messages.inc |
| |
| Language file of the RoundCube Webmail client |
| Copyright (C) 2005, RoundCube Dev. - Switzerland |
| Licensed under the GNU GPL |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
$Id$
*/
$messages = array();
$messages['loginfailed'] = 'Login failed';
$messages['cookiesdisabled'] = 'Your browser does not accept cookies';
$messages['sessionerror'] = 'Your session is invalid or expired';
$messages['imaperror'] = 'Connection to IMAP server failed';
$messages['nomessagesfound'] = 'No messages found in this mailbox';
$messages['loggedout'] = 'You have successfully terminated the session. Good bye!';
$messages['mailboxempty'] = 'Mailbox is empty';
$messages['loading'] = 'Loading...';
$messages['loadingdata'] = 'Loading data...';
$messages['checkingmail'] = 'Checking for new messages...';
$messages['sendingmessage'] = 'Sending message...';
$messages['messagesent'] = 'Message sent successfully';
$messages['savingmessage'] = 'Saving message...';
$messages['messagesaved'] = 'Message saved to Drafts';
$messages['successfullysaved'] = 'Successfully saved';
$messages['addedsuccessfully'] = 'Contact added successfully to address book';
$messages['contactexists'] = 'A contact with this e-mail address already exists';
$messages['blockedimages'] = 'To protect your privacy, remote images are blocked in this message.';
$messages['encryptedmessage'] = 'This is an encrypted message and can not be displayed. Sorry!';
$messages['nocontactsfound'] = 'No contacts found';
$messages['sendingfailed'] = 'Failed to send message';
$messages['errorsaving'] = 'An error occured while saving';
$messages['errormoving'] = 'Could not move the message';
$messages['errordeleting'] = 'Could not delete the message';
$messages['deletecontactconfirm'] = 'Do you really want to delete the selected contact(s)?';
$messages['deletefolderconfirm'] = 'Do you really want to delete this folder?';
$messages['purgefolderconfirm'] = 'Do you really want to delete all messages in this folder?';
$messages['formincomplete'] = 'The form was not completely filled out';
$messages['noemailwarning'] = 'Please enter a valid email address';
$messages['nonamewarning'] = 'Please enter a name';
$messages['nopagesizewarning'] = 'Please enter a page size';
$messages['norecipientwarning'] = 'Please enter at least one recipient';
$messages['nosubjectwarning'] = 'The "Subject" field is empty. Would you like to enter one now?';
$messages['nobodywarning'] = 'Send this message without text?';
$messages['notsentwarning'] = 'Message has not been sent. Do you want to discard your message?';
$messages['noldapserver'] = 'Please select an ldap server to search';
$messages['nocontactsreturned'] = 'No contacts were found';
$messages['nosearchname'] = 'Please enter a contact name or email address';
$messages['searchsuccessful'] = '$nr messages found';
$messages['searchnomatch'] = 'Search returned no matches';
$messages['searching'] = 'Searching...';
$messages['checking'] = 'Checking...';
$messages['nospellerrors'] = 'No spelling errors found';
+$messages['folderdeleted'] = 'Folder successfully deleted';
+
?>
diff --git a/program/steps/settings/manage_folders.inc b/program/steps/settings/manage_folders.inc
index 770bac2fd..457fcb5d2 100644
--- a/program/steps/settings/manage_folders.inc
+++ b/program/steps/settings/manage_folders.inc
@@ -1,269 +1,273 @@
<?php
/*
+-----------------------------------------------------------------------+
| program/steps/settings/manage_folders.inc |
| |
| This file is part of the RoundCube Webmail client |
| Copyright (C) 2005, RoundCube Dev. - Switzerland |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
| Provide functionality to create/delete/rename folders |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
$Id$
*/
// init IMAP connection
rcmail_imap_init(TRUE);
// subscribe to one or more mailboxes
if ($_action=='subscribe')
{
if (strlen($_GET['_mboxes']))
$IMAP->subscribe(array($_GET['_mboxes']));
if ($REMOTE_REQUEST)
rcube_remote_response('// subscribed');
}
// unsubscribe one or more mailboxes
else if ($_action=='unsubscribe')
{
if (strlen($_GET['_mboxes']))
$IMAP->unsubscribe(array($_GET['_mboxes']));
if ($REMOTE_REQUEST)
rcube_remote_response('// unsubscribed');
}
// create a new mailbox
else if ($_action=='create-folder')
{
if (!empty($_GET['_name']))
$create = $IMAP->create_mailbox(trim(get_input_value('_name', RCUBE_INPUT_GET)), TRUE);
if ($create && $REMOTE_REQUEST)
{
$commands = sprintf("this.add_folder_row('%s')", rep_specialchars_output($create, 'js'));
rcube_remote_response($commands);
}
else if (!$create && $REMOTE_REQUEST)
{
$commands = show_message('errorsaving', 'error');
rcube_remote_response($commands);
}
else if (!$create)
show_message('errorsaving', 'error');
}
// rename a mailbox
else if ($_action=='rename-folder')
{
if (!empty($_GET['_folder_oldname']) && !empty($_GET['_folder_newname']))
- $rename = $IMAP->rename_mailbox(get_input_value('_folder_oldname', RCUBE_INPUT_GET), trim(get_input_value('_folder_newname', RCUBE_INPUT_GET)), TRUE);
+ $rename = $IMAP->rename_mailbox(get_input_value('_folder_oldname', RCUBE_INPUT_GET), trim(get_input_value('_folder_newname', RCUBE_INPUT_GET)));
if ($rename && $REMOTE_REQUEST)
{
$commands = sprintf("this.replace_folder_row('%s','%s');",
addslashes(rep_specialchars_output($rename, 'js')),
rep_specialchars_output($_GET['_folder_oldname'], 'js'));
rcube_remote_response($commands);
}
else if (!$rename && $REMOTE_REQUEST)
{
$commands = "this.reset_folder_rename();\n";
$commands .= show_message('errorsaving', 'error');
rcube_remote_response($commands);
}
else if (!$rename)
show_message('errorsaving', 'error');
}
// delete an existing IMAP mailbox
else if ($_action=='delete-folder')
{
- if (strlen($_GET['_mboxes']))
- $deleted = $IMAP->delete_mailbox(array($_GET['_mboxes']));
+ if (!empty($_GET['_mboxes']))
+ $deleted = $IMAP->delete_mailbox(array(get_input_value('_mboxes', RCUBE_INPUT_GET)));
if ($REMOTE_REQUEST && $deleted)
- rcube_remote_response(sprintf("this.remove_folder_row('%s')", rep_specialchars_output($_GET['_mboxes'], 'js')));
+ {
+ $commands = sprintf("this.remove_folder_row('%s');\n", rep_specialchars_output(get_input_value('_mboxes', RCUBE_INPUT_GET), 'js'));
+ $commands .= show_message('folderdeleted', 'confirmation');
+ rcube_remote_response($commands);
+ }
else if ($REMOTE_REQUEST)
{
$commands = show_message('errorsaving', 'error');
rcube_remote_response($commands);
}
}
// build table with all folders listed by server
function rcube_subscription_form($attrib)
{
global $IMAP, $CONFIG, $OUTPUT, $JS_OBJECT_NAME;
list($form_start, $form_end) = get_form_tags($attrib, 'folders');
unset($attrib['form']);
if (!$attrib['id'])
$attrib['id'] = 'rcmSubscriptionlist';
// allow the following attributes to be added to the <table> tag
$attrib_str = create_attrib_string($attrib, array('style', 'class', 'id', 'cellpadding', 'cellspacing', 'border', 'summary'));
$out = "$form_start\n<table" . $attrib_str . ">\n";
// add table header
$out .= "<thead><tr>\n";
$out .= sprintf('<td class="name">%s</td><td class="subscribed">%s</td>'.
'<td class="rename">&nbsp;</td><td class="delete">&nbsp;</td>',
rcube_label('foldername'), rcube_label('subscribed'));
$out .= "\n</tr></thead>\n<tbody>\n";
// get folders from server
$a_unsubscribed = $IMAP->list_unsubscribed();
$a_subscribed = $IMAP->list_mailboxes();
$a_js_folders = array();
$checkbox_subscribe = new checkbox(array('name' => '_subscribed[]', 'onclick' => "$JS_OBJECT_NAME.command(this.checked?'subscribe':'unsubscribe',this.value)"));
if (!empty($attrib['deleteicon']))
$del_button = sprintf('<img src="%s%s" alt="%s" border="0" />', $CONFIG['skin_path'], $attrib['deleteicon'], rcube_label('delete'));
else
$del_button = rcube_label('delete');
if (!empty($attrib['renameicon']))
$edit_button = sprintf('<img src="%s%s" alt="%s" border="0" />', $CONFIG['skin_path'], $attrib['renameicon'], rcube_label('rename'));
else
$del_button = rcube_label('rename');
// create list of available folders
foreach ($a_unsubscribed as $i => $folder)
{
$protected = ($CONFIG['protect_default_folders'] == TRUE && in_array($folder,$CONFIG['default_imap_folders']));
$zebra_class = $i%2 ? 'even' : 'odd';
$folder_js = rep_specialchars_output($folder, 'js');
if (!$protected)
$a_js_folders['rcmrow'.($i+1)] = $folder_js;
$out .= sprintf('<tr id="rcmrow%d" class="%s"><td>%s</td><td>%s</td>',
$i+1,
$zebra_class,
rep_specialchars_output(rcube_charset_convert($folder, 'UTF-7', 'UTF-8'), 'html', 'all'),
$checkbox_subscribe->show(in_array($folder, $a_subscribed)?$folder:'', array('value' => $folder, 'disabled' => $protected)));
// add rename and delete buttons
if (!$protected)
$out .= sprintf('<td><a href="#rename" onclick="%s.command(\'rename-folder\',\'%s\')" title="%s">%s</a>'.
'<td><a href="#delete" onclick="%s.command(\'delete-folder\',\'%s\')" title="%s">%s</a></td>',
$JS_OBJECT_NAME,
$folder_js,
rcube_label('renamefolder'),
$edit_button,
$JS_OBJECT_NAME,
$folder_js,
rcube_label('deletefolder'),
$del_button);
else
$out .= '<td></td><td></td>';
$out .= "</tr>\n";
}
$out .= "</tbody>\n</table>";
$out .= "\n$form_end";
$javascript = sprintf("%s.gui_object('subscriptionlist', '%s');\n", $JS_OBJECT_NAME, $attrib['id']);
$javascript .= sprintf("%s.set_env('subscriptionrows', %s);", $JS_OBJECT_NAME, array2js($a_js_folders));
$OUTPUT->add_script($javascript);
return $out;
}
function rcube_create_folder_form($attrib)
{
global $JS_OBJECT_NAME;
list($form_start, $form_end) = get_form_tags($attrib, 'create-folder');
unset($attrib['form']);
// return the complete edit form as table
$out = "$form_start\n";
$input = new textfield(array('name' => '_folder_name'));
$out .= $input->show();
if (get_boolean($attrib['button']))
{
$button = new input_field(array('type' => 'button',
'value' => rcube_label('create'),
'onclick' => "$JS_OBJECT_NAME.command('create-folder',this.form)"));
$out .= $button->show();
}
$out .= "\n$form_end";
return $out;
}
function rcube_rename_folder_form($attrib)
{
global $CONFIG, $IMAP, $JS_OBJECT_NAME;
list($form_start, $form_end) = get_form_tags($attrib, 'rename-folder');
unset($attrib['form']);
// return the complete edit form as table
$out = "$form_start\n";
$a_unsubscribed = $IMAP->list_unsubscribed();
$select_folder = new select(array('name' => '_folder_oldname', 'id' => 'rcmfd_oldfolder'));
foreach ($a_unsubscribed as $i => $folder)
{
if ($CONFIG['protect_default_folders'] == TRUE && in_array($folder,$CONFIG['default_imap_folders']))
continue;
$select_folder->add($folder);
}
$out .= $select_folder->show();
$out .= " to ";
$inputtwo = new textfield(array('name' => '_folder_newname'));
$out .= $inputtwo->show();
if (get_boolean($attrib['button']))
{
$button = new input_field(array('type' => 'button',
'value' => rcube_label('rename'),
'onclick' => "$JS_OBJECT_NAME.command('rename-folder',this.form)"));
$out .= $button->show();
}
$out .= "\n$form_end";
return $out;
}
// add some labels to client
rcube_add_label('deletefolderconfirm');
parse_template('managefolders');
?>

File Metadata

Mime Type
text/x-diff
Expires
Thu, Dec 18, 1:29 PM (1 d, 15 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
418841
Default Alt Text
(207 KB)

Event Timeline