From 07e1de2dcd3f3ff8910a3680493f035b3c693cf0 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9my=20Bobbio?= Date: Sat, 18 Jun 2011 21:40:12 +0200 Subject: [PATCH] Imported Upstream version 0.5.2+dfsg --- CHANGELOG | 26 + INSTALL | 1 - SQL/postgres.initial.sql | 4 +- SQL/postgres.update.sql | 2 +- config/main.inc.php.dist | 1 + index.php | 16 +- plugins/archive/archive.php | 2 + plugins/archive/localization/cs_CZ.inc | 2 +- plugins/autologon/autologon.php | 2 + plugins/help/localization/cs_CZ.inc | 2 +- plugins/help/localization/ru_RU.inc | 2 +- .../http_authentication.php | 3 +- plugins/managesieve/Changelog | 12 + plugins/managesieve/lib/Net/Sieve.php | 98 +- plugins/managesieve/lib/rcube_sieve.php | 651 +- plugins/managesieve/localization/es_ES.inc | 2 +- plugins/managesieve/localization/fr_FR.inc | 2 + plugins/managesieve/localization/pl_PL.inc | 8 +- plugins/managesieve/localization/ru_RU.inc | 12 + plugins/managesieve/managesieve.js | 2 - plugins/managesieve/managesieve.php | 6 +- plugins/managesieve/tests/Makefile | 7 + plugins/managesieve/tests/parser.phpt | 103 + plugins/managesieve/tests/tokenize.phpt | 66 + plugins/markasjunk/localization/cs_CZ.inc | 2 +- plugins/markasjunk/markasjunk.php | 4 +- plugins/markasjunk/package.xml | 1 + .../new_user_identity/new_user_identity.php | 2 +- plugins/password/README | 2 +- plugins/password/config.inc.php.dist | 27 +- plugins/password/drivers/directadmin.php | 12 +- plugins/password/drivers/ldap.php | 57 +- plugins/password/drivers/ldap_simple.php | 70 +- plugins/password/drivers/virtualmin.php | 43 +- plugins/password/drivers/xmail.php | 2 +- plugins/password/localization/es_ES.inc | 22 +- plugins/password/localization/ru_RU.inc | 2 +- plugins/password/package.xml | 10 +- plugins/password/password.js | 6 +- plugins/password/password.php | 10 +- .../show_additional_headers.php | 2 +- .../squirrelmail_usercopy.php | 4 +- .../localization/cs_CZ.inc | 2 +- plugins/userinfo/localization/cs_CZ.inc | 2 +- .../vcard_attachments/localization/cs_CZ.inc | 2 +- .../vcard_attachments/localization/es_ES.inc | 4 +- plugins/vcard_attachments/package.xml | 1 + plugins/virtuser_file/virtuser_file.php | 2 +- plugins/virtuser_query/virtuser_query.php | 6 +- program/include/iniset.php | 4 +- program/include/main.inc | 46 +- program/include/rcmail.php | 20 +- program/include/rcmail.php.orig | 1325 ++ program/include/rcube_browser.php | 4 +- program/include/rcube_imap.php | 140 +- program/include/rcube_imap_generic.php | 215 +- program/include/rcube_mdb2.php | 12 +- program/include/rcube_message.php | 6 +- program/include/rcube_session.php | 23 +- program/include/rcube_smtp.php | 11 +- program/include/rcube_template.php | 28 +- program/include/rcube_user.php | 11 +- program/js/app.js | 369 +- program/js/app.js.src | 39 +- program/js/common.js | 38 +- program/js/googiespell.js | 72 +- program/js/list.js | 79 +- program/js/list.js.src | 104 +- program/js/tiny_mce/langs/en.js | 59 +- .../plugins/contextmenu/editor_plugin.js | 2 +- .../plugins/contextmenu/editor_plugin_src.js | 46 +- .../js/tiny_mce/plugins/emotions/emotions.htm | 29 +- .../js/tiny_mce/plugins/media/css/media.css | 9 +- .../tiny_mce/plugins/media/editor_plugin.js | 2 +- .../plugins/media/editor_plugin_src.js | 948 +- program/js/tiny_mce/plugins/media/js/media.js | 930 +- .../js/tiny_mce/plugins/media/langs/en_dlg.js | 10 +- program/js/tiny_mce/plugins/media/media.htm | 571 +- .../plugins/nonbreaking/editor_plugin.js | 2 +- .../plugins/nonbreaking/editor_plugin_src.js | 2 +- .../tiny_mce/plugins/paste/editor_plugin.js | 2 +- .../plugins/paste/editor_plugin_src.js | 249 +- .../plugins/searchreplace/editor_plugin.js | 2 +- .../searchreplace/editor_plugin_src.js | 4 + .../plugins/searchreplace/js/searchreplace.js | 24 +- .../plugins/searchreplace/searchreplace.htm | 33 +- .../plugins/spellchecker/editor_plugin.js | 2 +- .../plugins/spellchecker/editor_plugin_src.js | 92 +- .../plugins/tabfocus/editor_plugin.js | 2 +- .../plugins/tabfocus/editor_plugin_src.js | 58 +- program/js/tiny_mce/plugins/table/cell.htm | 24 +- .../tiny_mce/plugins/table/editor_plugin.js | 2 +- .../plugins/table/editor_plugin_src.js | 149 +- program/js/tiny_mce/plugins/table/js/cell.js | 20 +- program/js/tiny_mce/plugins/table/js/row.js | 31 +- program/js/tiny_mce/plugins/table/js/table.js | 31 +- .../js/tiny_mce/plugins/table/langs/en_dlg.js | 2 +- .../js/tiny_mce/plugins/table/merge_cells.htm | 22 +- program/js/tiny_mce/plugins/table/row.htm | 18 +- program/js/tiny_mce/plugins/table/table.htm | 107 +- .../plugins/visualchars/editor_plugin.js | 2 +- .../plugins/visualchars/editor_plugin_src.js | 33 +- program/js/tiny_mce/themes/advanced/about.htm | 8 +- .../js/tiny_mce/themes/advanced/anchor.htm | 10 +- .../js/tiny_mce/themes/advanced/charmap.htm | 79 +- .../tiny_mce/themes/advanced/color_picker.htm | 19 +- .../themes/advanced/editor_template.js | 2 +- .../themes/advanced/editor_template_src.js | 280 +- program/js/tiny_mce/themes/advanced/image.htm | 102 +- .../js/tiny_mce/themes/advanced/js/about.js | 1 + .../js/tiny_mce/themes/advanced/js/anchor.js | 5 + .../js/tiny_mce/themes/advanced/js/charmap.js | 32 +- .../themes/advanced/js/color_picker.js | 140 +- .../js/tiny_mce/themes/advanced/js/image.js | 4 +- .../js/tiny_mce/themes/advanced/js/link.js | 11 +- .../themes/advanced/js/source_editor.js | 18 +- .../js/tiny_mce/themes/advanced/langs/en.js | 10 +- .../tiny_mce/themes/advanced/langs/en_dlg.js | 9 +- program/js/tiny_mce/themes/advanced/link.htm | 55 +- .../themes/advanced/skins/default/content.css | 12 + .../themes/advanced/skins/default/ui.css | 8 +- .../themes/advanced/skins/o2k7/content.css | 11 + .../themes/advanced/skins/o2k7/dialog.css | 1 + .../themes/advanced/skins/o2k7/ui.css | 9 +- .../themes/advanced/skins/o2k7/ui_black.css | 2 +- .../themes/advanced/skins/o2k7/ui_silver.css | 2 +- .../themes/advanced/source_editor.htm | 6 +- .../tiny_mce/themes/simple/editor_template.js | 2 +- .../themes/simple/editor_template_src.js | 3 +- program/js/tiny_mce/tiny_mce.js | 750 +- program/js/tiny_mce/tiny_mce_popup.js | 2 +- program/js/tiny_mce/tiny_mce_src.js | 12288 +++++++++------- program/js/tiny_mce/utils/form_utils.js | 18 +- program/js/tiny_mce/utils/mctabs.js | 105 +- program/js/tiny_mce/utils/validate.js | 38 +- program/lib/html2text.php | 34 +- program/lib/washtml.php | 3 +- program/localization/de_CH/labels.inc | 4 +- program/localization/de_CH/messages.inc | 8 +- program/localization/de_DE/messages.inc | 8 +- program/localization/fr_FR/labels.inc | 4 +- program/localization/index.inc | 8 +- program/steps/mail/func.inc | 68 +- program/steps/settings/save_prefs.inc | 17 +- program/steps/utils/spell_googie.inc | 4 +- program/steps/utils/spell_html_googie.inc | 2 +- skins/default/iehacks.css | 10 +- skins/default/images/abook_toolbar.png | Bin 13619 -> 13586 bytes skins/default/images/buttons/bg.gif | Bin 211 -> 197 bytes skins/default/images/dbutton.png | Bin 374 -> 240 bytes skins/default/images/dimple.png | Bin 239 -> 174 bytes skins/default/images/display/icons.png | Bin 4300 -> 4246 bytes skins/default/images/icons/expanded.png | Bin 169 -> 123 bytes skins/default/images/icons/glass.png | Bin 535 -> 433 bytes skins/default/images/icons/glass_roll.png | Bin 577 -> 544 bytes skins/default/images/icons/groupactions.png | Bin 660 -> 495 bytes skins/default/images/listheader.gif | Bin 487 -> 470 bytes skins/default/images/mail_footer.png | Bin 2235 -> 1027 bytes skins/default/images/mail_toolbar.png | Bin 39305 -> 37571 bytes skins/default/images/messageicons.png | Bin 3011 -> 2354 bytes skins/default/images/pagenav.gif | Bin 426 -> 357 bytes skins/default/images/searchfield.gif | Bin 397 -> 336 bytes skins/default/images/tabs-left.gif | Bin 461 -> 295 bytes skins/default/images/tabs-right.gif | Bin 2851 -> 837 bytes skins/default/images/taskicons.gif | Bin 2207 -> 1732 bytes skins/default/images/taskicons.png | Bin 3813 -> 1732 bytes skins/default/images/watermark.gif | Bin 11081 -> 10237 bytes skins/default/templates/addressbook.html | 1 - skins/default/templates/contact.html | 2 + skins/default/templates/contactadd.html | 1 - skins/default/templates/contactedit.html | 1 - skins/default/templates/messageprint.html | 1 + 172 files changed, 12916 insertions(+), 8696 deletions(-) create mode 100644 plugins/managesieve/tests/Makefile create mode 100644 plugins/managesieve/tests/parser.phpt create mode 100644 plugins/managesieve/tests/tokenize.phpt create mode 100644 program/include/rcmail.php.orig diff --git a/CHANGELOG b/CHANGELOG index 8674726..a4cd90b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,32 @@ CHANGELOG Roundcube Webmail =========================== +- TinyMCE 3.4.2 now compatible with IE9 +- PEAR::Net_SMTP 1.5.2, fixed timeout issue (#1487843) +- Fix bug where template name without plugin prefix was used in render_page hook +- Support 'abort' and 'result' response in 'preferences_save' hook, add error handling +- Fix bug where some content would cause hang on html2text conversion (#1487863) +- Improve space-stuffing handling in format=flowed messages (#1487861) +- Fix bug where some dates would produce SQL error in MySQL (#1487856) +- Added workaround for some IMAP server with broken STATUS response (#1487859) +- Fix bug where default_charset was not used for text messages (#1487836) +- Stateless request tokens. No keep-alive necessary on login page (#1487829) +- Force names of unique constraints in PostgreSQL DDL +- Add code for prevention from IMAP connection hangs when server closes socket unexpectedly +- Remove redundant DELETE query (for old session deletion) on login +- Get around unreliable rand() and mt_rand() in session ID generation (#1486281) +- Fix some emails are not shown using Cyrus IMAP (#1487820) +- Fix handling of mime-encoded words with non-integral number of octets in a word (#1487801) +- Fix parsing links with non-printable characters inside (#1487805) +- Fixed de_CH/de_DE localization bugs (#1487773) +- Add variable for 'Today' label in date_today option (#1486120) +- Applied plugin changes since 0.5-stable release +- Fix SQL query in rcube_user::query() so it uses index on MySQL again +- Use only one from IMAP authentication methods to prevent login delays (1487784) +- Fix strftime format support in date_today option +- Removed redundant tags from contact add/edit pages +- Fix CSS error in contact details screen on IE7 (#1487775) + RELEASE 0.5.1 ------------- - Fix handling of attachments with invalid content type (#1487767) diff --git a/INSTALL b/INSTALL index 956fb24..ed51b13 100644 --- a/INSTALL +++ b/INSTALL @@ -22,7 +22,6 @@ REQUIREMENTS - MDB2 2.5.0 or newer - Mail_Mime 1.8.1 or newer - Net_SMTP 1.4.2 or newer - - Net_IDNA2 0.1.1 or newer - Auth_SASL 1.0.3 or newer * php.ini options (see .htaccess file): - error_reporting E_ALL & ~E_NOTICE (or lower) diff --git a/SQL/postgres.initial.sql b/SQL/postgres.initial.sql index 089cae0..d6f4db7 100644 --- a/SQL/postgres.initial.sql +++ b/SQL/postgres.initial.sql @@ -25,7 +25,7 @@ CREATE TABLE users ( last_login timestamp with time zone DEFAULT NULL, "language" varchar(5), preferences text DEFAULT ''::text NOT NULL, - UNIQUE (username, mail_host) + CONSTRAINT users_username_key UNIQUE (username, mail_host) ); CREATE INDEX users_alias_id_idx ON users (alias); @@ -217,7 +217,7 @@ CREATE TABLE messages ( size integer DEFAULT 0 NOT NULL, headers text NOT NULL, structure text, - UNIQUE (user_id, cache_key, uid) + CONSTRAINT messages_user_id_key UNIQUE (user_id, cache_key, uid) ); CREATE INDEX messages_index_idx ON messages (user_id, cache_key, idx); diff --git a/SQL/postgres.update.sql b/SQL/postgres.update.sql index 2f4498d..0ae8d3f 100644 --- a/SQL/postgres.update.sql +++ b/SQL/postgres.update.sql @@ -85,7 +85,7 @@ ALTER TABLE users ALTER last_login SET DEFAULT NULL; -- Updates from version 0.4.2 DROP INDEX users_username_id_idx; -ALTER TABLE users ADD UNIQUE (username, mail_host); +ALTER TABLE users ADD CONSTRAINT users_username_key UNIQUE (username, mail_host); ALTER TABLE contacts ALTER email TYPE varchar(255); TRUNCATE messages; diff --git a/config/main.inc.php.dist b/config/main.inc.php.dist index ea0092b..f00bfa8 100644 --- a/config/main.inc.php.dist +++ b/config/main.inc.php.dist @@ -347,6 +347,7 @@ $rcmail_config['date_short'] = 'D H:i'; $rcmail_config['date_long'] = 'd.m.Y H:i'; // use this format for today's date display (date or strftime format) +// Note: $ character will be replaced with 'Today' label $rcmail_config['date_today'] = 'H:i'; // store draft message is this mailbox diff --git a/index.php b/index.php index 883faa6..ff9bc8e 100644 --- a/index.php +++ b/index.php @@ -2,7 +2,7 @@ /* +-------------------------------------------------------------------------+ | Roundcube Webmail IMAP Client | - | Version 0.5.1 | + | Version 0.5.2 | | | | Copyright (C) 2005-2011, Roundcube Dev. - Switzerland | | | @@ -23,7 +23,7 @@ | Author: Thomas Bruederli | +-------------------------------------------------------------------------+ - $Id: index.php 4509 2011-02-09 10:51:50Z thomasb $ + $Id: index.php 4674 2011-04-20 09:03:08Z thomasb $ */ @@ -95,10 +95,12 @@ if ($RCMAIL->task == 'login' && $RCMAIL->action == 'login') { } else if ($auth['valid'] && !$auth['abort'] && !empty($auth['host']) && !empty($auth['user']) && - $RCMAIL->login($auth['user'], $auth['pass'], $auth['host'])) { - // create new session ID + $RCMAIL->login($auth['user'], $auth['pass'], $auth['host']) + ) { + // create new session ID, don't destroy the current session + // it was destroyed already by $RCMAIL->kill_session() above $RCMAIL->session->remove('temp'); - $RCMAIL->session->regenerate_id(); + $RCMAIL->session->regenerate_id(false); // send auth cookie if necessary $RCMAIL->authenticate_session(); @@ -110,7 +112,7 @@ if ($RCMAIL->task == 'login' && $RCMAIL->action == 'login') { $query = array(); if ($url = get_input_value('_url', RCUBE_INPUT_POST)) { parse_str($url, $query); - + // prevent endless looping on login page if ($query['_task'] == 'login') unset($query['_task']); @@ -180,7 +182,7 @@ else { // check client X-header to verify request origin if ($OUTPUT->ajax_call) { - if (rc_request_header('X-Roundcube-Request') != $RCMAIL->get_request_token()) { + if (rc_request_header('X-Roundcube-Request') != $RCMAIL->get_request_token() && !$RCMAIL->config->get('devel_mode')) { header('HTTP/1.1 404 Not Found'); die("Invalid Request"); } diff --git a/plugins/archive/archive.php b/plugins/archive/archive.php index fbb0129..843b612 100644 --- a/plugins/archive/archive.php +++ b/plugins/archive/archive.php @@ -30,6 +30,8 @@ class archive extends rcube_plugin 'command' => 'plugin.archive', 'imagepas' => $skin_path.'/archive_pas.png', 'imageact' => $skin_path.'/archive_act.png', + 'width' => 32, + 'height' => 32, 'title' => 'buttontitle', 'domain' => $this->ID, ), diff --git a/plugins/archive/localization/cs_CZ.inc b/plugins/archive/localization/cs_CZ.inc index 1396fb8..bb257bc 100644 --- a/plugins/archive/localization/cs_CZ.inc +++ b/plugins/archive/localization/cs_CZ.inc @@ -6,7 +6,7 @@ | language/cs_CZ/labels.inc | | | | Language file of the Roundcube archive plugin | -| Copyright (C) 2005-2009, Roundcube Dev. - Switzerland | +| Copyright (C) 2005-2009, The Roundcube Dev Team | | Licensed under the GNU GPL | | | +-----------------------------------------------------------------------+ diff --git a/plugins/autologon/autologon.php b/plugins/autologon/autologon.php index bc3d2ee..9601d61 100644 --- a/plugins/autologon/autologon.php +++ b/plugins/autologon/autologon.php @@ -31,6 +31,8 @@ class autologon extends rcube_plugin $args['user'] = 'me'; $args['pass'] = '******'; $args['host'] = 'localhost'; + $args['cookiecheck'] = false; + $args['valid'] = true; } return $args; diff --git a/plugins/help/localization/cs_CZ.inc b/plugins/help/localization/cs_CZ.inc index 472c753..ae8b39a 100644 --- a/plugins/help/localization/cs_CZ.inc +++ b/plugins/help/localization/cs_CZ.inc @@ -6,7 +6,7 @@ | language/cs_CZ/labels.inc | | | | Language file of the Roundcube help plugin | -| Copyright (C) 2005-2009, Roundcube Dev. - Switzerland | +| Copyright (C) 2005-2009, The Roundcube Dev Team | | Licensed under the GNU GPL | | | +-----------------------------------------------------------------------+ diff --git a/plugins/help/localization/ru_RU.inc b/plugins/help/localization/ru_RU.inc index aad0a61..9f1de41 100644 --- a/plugins/help/localization/ru_RU.inc +++ b/plugins/help/localization/ru_RU.inc @@ -6,7 +6,7 @@ | plugins/help/localization/ru_RU.inc | | | | Language file of the Roundcube help plugin | -| Copyright (C) 2005-2010, Roundcube Dev. - Switzerland | +| Copyright (C) 2005-2010, The Roundcube Dev Team | | Licensed under the GNU GPL | | | +-----------------------------------------------------------------------+ diff --git a/plugins/http_authentication/http_authentication.php b/plugins/http_authentication/http_authentication.php index a8003cf..6da6488 100644 --- a/plugins/http_authentication/http_authentication.php +++ b/plugins/http_authentication/http_authentication.php @@ -5,7 +5,7 @@ * * Make use of an existing HTTP authentication and perform login with the existing user credentials * - * @version 1.1 + * @version 1.2 * @author Thomas Bruederli */ class http_authentication extends rcube_plugin @@ -36,6 +36,7 @@ class http_authentication extends rcube_plugin } $args['cookiecheck'] = false; + $args['valid'] = true; return $args; } diff --git a/plugins/managesieve/Changelog b/plugins/managesieve/Changelog index 61d198c..20e3bb8 100644 --- a/plugins/managesieve/Changelog +++ b/plugins/managesieve/Changelog @@ -1,6 +1,18 @@ +- Fix escaping of backslash character in quoted strings (#1487780) +- Fix STARTTLS for timsieved < 2.3.10 +- Fix handling of non-safe characters (double-quote, backslash) + or UTF-8 characters (dovecot's implementation bug workaround) + in script names + +* version 3.0 [2011-02-01] +----------------------------------------------------------- - Added support for SASL proxy authentication (#1486691) - Fixed parsing of scripts with \r\n line separator - Apply forgotten changes for form errors handling +- Fix multi-line strings parsing (#1487685) +- Added tests for script parser +- Rewritten script parser +- Fix double request when clicking on Filters tab using Firefox * version 2.10 [2010-10-10] ----------------------------------------------------------- diff --git a/plugins/managesieve/lib/Net/Sieve.php b/plugins/managesieve/lib/Net/Sieve.php index ecc9071..0f6a5f6 100644 --- a/plugins/managesieve/lib/Net/Sieve.php +++ b/plugins/managesieve/lib/Net/Sieve.php @@ -475,7 +475,9 @@ class Net_Sieve if (NET_SIEVE_STATE_TRANSACTION != $this->_state) { return PEAR::raiseError('Not currently in TRANSACTION state', 1); } - if (PEAR::isError($res = $this->_doCmd(sprintf('HAVESPACE "%s" %d', $scriptname, $size)))) { + + $command = sprintf('HAVESPACE %s %d', $this->_escape($scriptname), $size); + if (PEAR::isError($res = $this->_doCmd($command))) { return $res; } return true; @@ -740,7 +742,9 @@ class Net_Sieve if (NET_SIEVE_STATE_TRANSACTION != $this->_state) { return PEAR::raiseError('Not currently in AUTHORISATION state', 1); } - if (PEAR::isError($res = $this->_doCmd(sprintf('DELETESCRIPT "%s"', $scriptname)))) { + + $command = sprintf('DELETESCRIPT %s', $this->_escape($scriptname)); + if (PEAR::isError($res = $this->_doCmd($command))) { return $res; } return true; @@ -759,11 +763,12 @@ class Net_Sieve return PEAR::raiseError('Not currently in AUTHORISATION state', 1); } - if (PEAR::isError($res = $this->_doCmd(sprintf('GETSCRIPT "%s"', $scriptname)))) { + $command = sprintf('GETSCRIPT %s', $this->_escape($scriptname)); + if (PEAR::isError($res = $this->_doCmd($command))) { return $res; } - return preg_replace('/{[0-9]+}\r\n/', '', $res); + return preg_replace('/^{[0-9]+}\r\n/', '', $res); } /** @@ -779,9 +784,12 @@ class Net_Sieve if (NET_SIEVE_STATE_TRANSACTION != $this->_state) { return PEAR::raiseError('Not currently in AUTHORISATION state', 1); } - if (PEAR::isError($res = $this->_doCmd(sprintf('SETACTIVE "%s"', $scriptname)))) { + + $command = sprintf('SETACTIVE %s', $this->_escape($scriptname)); + if (PEAR::isError($res = $this->_doCmd($command))) { return $res; } + $this->_activeScript = $scriptname; return true; } @@ -808,9 +816,10 @@ class Net_Sieve $res = explode("\r\n", $res); foreach ($res as $value) { if (preg_match('/^"(.*)"( ACTIVE)?$/i', $value, $matches)) { - $scripts[] = $matches[1]; + $script_name = stripslashes($matches[1]); + $scripts[] = $script_name; if (!empty($matches[2])) { - $activescript = $matches[1]; + $activescript = $script_name; } } } @@ -833,8 +842,10 @@ class Net_Sieve } $stringLength = $this->_getLineLength($scriptdata); + $command = sprintf("PUTSCRIPT %s {%d+}\r\n%s", + $this->_escape($scriptname), $stringLength, $scriptdata); - if (PEAR::isError($res = $this->_doCmd(sprintf("PUTSCRIPT \"%s\" {%d+}\r\n%s", $scriptname, $stringLength, $scriptdata)))) { + if (PEAR::isError($res = $this->_doCmd($command))) { return $res; } @@ -980,6 +991,28 @@ class Net_Sieve return $lastline; } + /** + * Receives x bytes from the server. + * + * @param int $length Number of bytes to read + * + * @return string The server response. + */ + function _recvBytes($length) + { + $response = ''; + $response_length = 0; + + while ($response_length < $length) { + $response .= $this->_sock->read($length - $response_length); + $response_length = $this->_getLineLength($response); + } + + $this->_debug("S: " . rtrim($response)); + + return $response; + } + /** * Send a command and retrieves a response from the server. * @@ -1013,11 +1046,11 @@ class Net_Sieve if ('NO' == substr($uc_line, 0, 2)) { // Check for string literal error message. - if (preg_match('/^no {([0-9]+)\+?}/i', $line, $matches)) { - $line .= str_replace( - "\r\n", ' ', $this->_sock->read($matches[1] + 2) - ); - $this->_debug("S: $line"); + if (preg_match('/{([0-9]+)}$/i', $line, $matches)) { + $line = substr($line, 0, -(strlen($matches[1])+2)) + . str_replace( + "\r\n", ' ', $this->_recvBytes($matches[1] + 2) + ); } return PEAR::raiseError(trim($response . substr($line, 2)), 3); } @@ -1052,16 +1085,9 @@ class Net_Sieve return PEAR::raiseError(trim($response . $line), 6); } - if (preg_match('/^{([0-9]+)\+?}/i', $line, $matches)) { - // Matches String Responses. - $str_size = $matches[1] + 2; - $line = ''; - $line_length = 0; - while ($line_length < $str_size) { - $line .= $this->_sock->read($str_size - $line_length); - $line_length = $this->_getLineLength($line); - } - $this->_debug("S: $line"); + if (preg_match('/^{([0-9]+)}/i', $line, $matches)) { + // Matches literal string responses. + $line = $this->_recvBytes($matches[1] + 2); if (!$auth) { // Receive the pending OK only if we aren't @@ -1146,7 +1172,13 @@ class Net_Sieve // The server should be sending a CAPABILITY response after // negotiating TLS. Read it, and ignore if it doesn't. - $this->_doCmd(); + // Doesn't work with older timsieved versions + $regexp = '/^CYRUS TIMSIEVED V([0-9.]+)/'; + if (!preg_match($regexp, $this->_capability['implementation'], $matches) + || version_compare($matches[1], '2.3.10', '>=') + ) { + $this->_doCmd(); + } // RFC says we need to query the server capabilities again now that we // are under encryption. @@ -1191,6 +1223,24 @@ class Net_Sieve return $string; } + /** + * Convert string into RFC's quoted-string or literal-c2s form + * + * @param string $string The string to convert. + * + * @return string Result string + */ + function _escape($string) + { + // Some implementations doesn't allow UTF-8 characters in quoted-string + // It's safe to use literal-c2s + if (preg_match('/[^\x01-\x09\x0B-\x0C\x0E-\x7F]/', $string)) { + return sprintf("{%d+}\r\n%s", $this->_getLineLength($string), $string); + } + + return '"' . addcslashes($string, '\\"') . '"'; + } + /** * Write debug text to the current debug output handler. * diff --git a/plugins/managesieve/lib/rcube_sieve.php b/plugins/managesieve/lib/rcube_sieve.php index 89ae7d4..64bdb20 100644 --- a/plugins/managesieve/lib/rcube_sieve.php +++ b/plugins/managesieve/lib/rcube_sieve.php @@ -1,11 +1,11 @@ - $Id: rcube_sieve.php 4241 2010-11-20 17:59:50Z alec $ + $Id: rcube_sieve.php 4555 2011-02-16 10:48:11Z alec $ */ @@ -57,7 +57,7 @@ class rcube_sieve $this->sieve->setDebug(true, array($this, 'debug_handler')); } - if (PEAR::isError($this->sieve->connect($host, $port, NULL, $usetls))) { + if (PEAR::isError($this->sieve->connect($host, $port, null, $usetls))) { return $this->_set_error(SIEVE_ERROR_CONNECTION); } @@ -414,12 +414,17 @@ class rcube_sieve_script * @param string Script's text content * @param array Disabled extensions */ - public function __construct($script, $disabled=NULL) + public function __construct($script, $disabled=null) { - if (!empty($disabled)) - foreach ($disabled as $ext) - if (($idx = array_search($ext, $this->supported)) !== false) + if (!empty($disabled)) { + // we're working on lower-cased names + $disabled = array_map('strtolower', (array) $disabled); + foreach ($disabled as $ext) { + if (($idx = array_search($ext, $this->supported)) !== false) { unset($this->supported[$idx]); + } + } + } $this->content = $this->_parse_text($script); } @@ -513,14 +518,11 @@ class rcube_sieve_script $tests[$i] .= 'size :' . ($test['type']=='under' ? 'under ' : 'over ') . $test['arg']; break; case 'true': - $tests[$i] .= ($test['not'] ? 'not true' : 'true'); + $tests[$i] .= ($test['not'] ? 'false' : 'true'); break; case 'exists': $tests[$i] .= ($test['not'] ? 'not ' : ''); - if (is_array($test['arg'])) - $tests[$i] .= 'exists ["' . implode('", "', $this->_escape_string($test['arg'])) . '"]'; - else - $tests[$i] .= 'exists "' . $this->_escape_string($test['arg']) . '"'; + $tests[$i] .= 'exists ' . self::escape_string($test['arg']); break; case 'header': $tests[$i] .= ($test['not'] ? 'not ' : ''); @@ -533,33 +535,34 @@ class rcube_sieve_script } else $tests[$i] .= 'header :' . $test['type']; - - if (is_array($test['arg1'])) - $tests[$i] .= ' ["' . implode('", "', $this->_escape_string($test['arg1'])) . '"]'; - else - $tests[$i] .= ' "' . $this->_escape_string($test['arg1']) . '"'; - - if (is_array($test['arg2'])) - $tests[$i] .= ' ["' . implode('", "', $this->_escape_string($test['arg2'])) . '"]'; - else - $tests[$i] .= ' "' . $this->_escape_string($test['arg2']) . '"'; + $tests[$i] .= ' ' . self::escape_string($test['arg1']); + $tests[$i] .= ' ' . self::escape_string($test['arg2']); break; } $i++; } -// $script .= ($idx>0 ? 'els' : '').($rule['join'] ? 'if allof (' : 'if anyof ('); // disabled rule: if false #.... - $script .= 'if' . ($rule['disabled'] ? ' false #' : ''); - $script .= $rule['join'] ? ' allof (' : ' anyof ('; - if (sizeof($tests) > 1) - $script .= implode(", ", $tests); - else if (sizeof($tests)) - $script .= $tests[0]; - else - $script .= 'true'; - $script .= ")\n{\n"; + $script .= 'if ' . ($rule['disabled'] ? 'false # ' : ''); + + if (empty($tests)) { + $tests_str = 'true'; + } + else if (count($tests) > 1) { + $tests_str = implode(', ', $tests); + } + else { + $tests_str = $tests[0]; + } + + if ($rule['join'] || count($tests) > 1) { + $script .= sprintf('%s (%s)', $rule['join'] ? 'allof' : 'anyof', $tests_str); + } + else { + $script .= $tests_str; + } + $script .= "\n{\n"; // action(s) foreach ($rule['actions'] as $action) { @@ -571,7 +574,7 @@ class rcube_sieve_script $script .= ':copy '; array_push($exts, 'copy'); } - $script .= "\"" . $this->_escape_string($action['target']) . "\";\n"; + $script .= self::escape_string($action['target']) . ";\n"; break; case 'redirect': $script .= "\tredirect "; @@ -579,15 +582,13 @@ class rcube_sieve_script $script .= ':copy '; array_push($exts, 'copy'); } - $script .= "\"" . $this->_escape_string($action['target']) . "\";\n"; + $script .= self::escape_string($action['target']) . ";\n"; break; case 'reject': case 'ereject': array_push($exts, $action['type']); - if (strpos($action['target'], "\n")!==false) - $script .= "\t".$action['type']." text:\n" . $action['target'] . "\n.\n;\n"; - else - $script .= "\t".$action['type']." \"" . $this->_escape_string($action['target']) . "\";\n"; + $script .= "\t".$action['type']." " + . self::escape_string($action['target']) . ";\n"; break; case 'keep': case 'discard': @@ -597,22 +598,19 @@ class rcube_sieve_script case 'vacation': array_push($exts, 'vacation'); $script .= "\tvacation"; - if ($action['days']) + if (!empty($action['days'])) $script .= " :days " . $action['days']; - if ($action['addresses']) - $script .= " :addresses " . $this->_print_list($action['addresses']); - if ($action['subject']) - $script .= " :subject \"" . $this->_escape_string($action['subject']) . "\""; - if ($action['handle']) - $script .= " :handle \"" . $this->_escape_string($action['handle']) . "\""; - if ($action['from']) - $script .= " :from \"" . $this->_escape_string($action['from']) . "\""; - if ($action['mime']) + if (!empty($action['addresses'])) + $script .= " :addresses " . self::escape_string($action['addresses']); + if (!empty($action['subject'])) + $script .= " :subject " . self::escape_string($action['subject']); + if (!empty($action['handle'])) + $script .= " :handle " . self::escape_string($action['handle']); + if (!empty($action['from'])) + $script .= " :from " . self::escape_string($action['from']); + if (!empty($action['mime'])) $script .= " :mime"; - if (strpos($action['reason'], "\n")!==false) - $script .= " text:\n" . $action['reason'] . "\n.\n;\n"; - else - $script .= " \"" . $this->_escape_string($action['reason']) . "\";\n"; + $script .= " " . self::escape_string($action['reason']) . ";\n"; break; } } @@ -656,9 +654,6 @@ class rcube_sieve_script $i = 0; $content = array(); - // remove C comments - $script = preg_replace('|/\*.*?\*/|sm', '', $script); - // tokenize rules if ($tokens = preg_split('/(# rule:\[.*\])\r?\n/', $script, -1, PREG_SPLIT_DELIM_CAPTURE)) { foreach($tokens as $token) { @@ -686,31 +681,118 @@ class rcube_sieve_script */ private function _tokenize_rule($content) { - $result = NULL; + $cond = strtolower(self::tokenize($content, 1)); + + if ($cond != 'if' && $cond != 'elsif' && $cond != 'else') { + return null; + } + + $disabled = false; + $join = false; + + // disabled rule (false + comment): if false # ..... + if (preg_match('/^\s*false\s+#/i', $content)) { + $content = preg_replace('/^\s*false\s+#\s*/i', '', $content); + $disabled = true; + } + + while (strlen($content)) { + $tokens = self::tokenize($content, true); + $separator = array_pop($tokens); + + if (!empty($tokens)) { + $token = array_shift($tokens); + } + else { + $token = $separator; + } + + $token = strtolower($token); + + if ($token == 'not') { + $not = true; + $token = strtolower(array_shift($tokens)); + } + else { + $not = false; + } + + switch ($token) { + case 'allof': + $join = true; + break; + case 'anyof': + break; + + case 'size': + $size = array('test' => 'size', 'not' => $not); + for ($i=0, $len=count($tokens); $i<$len; $i++) { + if (!is_array($tokens[$i]) + && preg_match('/^:(under|over)$/i', $tokens[$i]) + ) { + $size['type'] = strtolower(substr($tokens[$i], 1)); + } + else { + $size['arg'] = $tokens[$i]; + } + } + + $tests[] = $size; + break; + + case 'header': + $header = array('test' => 'header', 'not' => $not, 'arg1' => '', 'arg2' => ''); + for ($i=0, $len=count($tokens); $i<$len; $i++) { + if (!is_array($tokens[$i]) && preg_match('/^:comparator$/i', $tokens[$i])) { + $i++; + } + else if (!is_array($tokens[$i]) && preg_match('/^:(count|value)$/i', $tokens[$i])) { + $header['type'] = strtolower(substr($tokens[$i], 1)) . '-' . $tokens[++$i]; + } + else if (!is_array($tokens[$i]) && preg_match('/^:(is|contains|matches)$/i', $tokens[$i])) { + $header['type'] = strtolower(substr($tokens[$i], 1)); + } + else { + $header['arg1'] = $header['arg2']; + $header['arg2'] = $tokens[$i]; + } + } - if (preg_match('/^(if|elsif|else)\s+((true|false|not\s+true|allof|anyof|exists|header|not|size)(.*))\s+\{(.*)\}$/sm', - trim($content), $matches)) { + $tests[] = $header; + break; - $tests = trim($matches[2]); + case 'exists': + $tests[] = array('test' => 'exists', 'not' => $not, + 'arg' => array_pop($tokens)); + break; + + case 'true': + $tests[] = array('test' => 'true', 'not' => $not); + break; - // disabled rule (false + comment): if false #..... - if ($matches[3] == 'false') { - $tests = preg_replace('/^false\s+#\s+/', '', $tests); - $disabled = true; + case 'false': + $tests[] = array('test' => 'true', 'not' => !$not); + break; + } + + // goto actions... + if ($separator == '{') { + break; } - else - $disabled = false; - - list($tests, $join) = $this->_parse_tests($tests); - $actions = $this->_parse_actions(trim($matches[5])); - - if ($tests && $actions) - $result = array( - 'type' => $matches[1], - 'tests' => $tests, - 'actions' => $actions, - 'join' => $join, - 'disabled' => $disabled, + } + + // ...and actions block + if ($tests) { + $actions = $this->_parse_actions($content); + } + + if ($tests && $actions) { + $result = array( + 'type' => $cond, + 'tests' => $tests, + 'actions' => $actions, + 'join' => $join, + 'disabled' => $disabled, ); } @@ -725,94 +807,76 @@ class rcube_sieve_script */ private function _parse_actions($content) { - $result = NULL; - - // supported actions - $patterns[] = '^\s*discard;'; - $patterns[] = '^\s*keep;'; - $patterns[] = '^\s*stop;'; - $patterns[] = '^\s*redirect\s+(.*?[^\\\]);'; - if (in_array('fileinto', $this->supported)) - $patterns[] = '^\s*fileinto\s+(.*?[^\\\]);'; - if (in_array('reject', $this->supported)) { - $patterns[] = '^\s*reject\s+text:(.*)\n\.\n;'; - $patterns[] = '^\s*reject\s+(.*?[^\\\]);'; - $patterns[] = '^\s*ereject\s+text:(.*)\n\.\n;'; - $patterns[] = '^\s*ereject\s+(.*?[^\\\]);'; - } - if (in_array('vacation', $this->supported)) - $patterns[] = '^\s*vacation\s+(.*?[^\\\]);'; + $result = null; - $pattern = '/(' . implode('\s*$)|(', $patterns) . '$\s*)/ms'; + while (strlen($content)) { + $tokens = self::tokenize($content, true); + $separator = array_pop($tokens); - // parse actions body - if (preg_match_all($pattern, $content, $mm, PREG_SET_ORDER)) { - foreach ($mm as $m) { - $content = trim($m[0]); + if (!empty($tokens)) { + $token = array_shift($tokens); + } + else { + $token = $separator; + } - if(preg_match('/^(discard|keep|stop)/', $content, $matches)) { - $result[] = array('type' => $matches[1]); - } - else if(preg_match('/^fileinto/', $content)) { - $target = $m[sizeof($m)-1]; - $copy = false; - if (preg_match('/^:copy\s+/', $target)) { - $target = preg_replace('/^:copy\s+/', '', $target); + switch ($token) { + case 'discard': + case 'keep': + case 'stop': + $result[] = array('type' => $token); + break; + + case 'fileinto': + case 'redirect': + $copy = false; + $target = ''; + + for ($i=0, $len=count($tokens); $i<$len; $i++) { + if (strtolower($tokens[$i]) == ':copy') { $copy = true; } - $result[] = array('type' => 'fileinto', 'copy' => $copy, - 'target' => $this->_parse_string($target)); - } - else if(preg_match('/^redirect/', $content)) { - $target = $m[sizeof($m)-1]; - $copy = false; - if (preg_match('/^:copy\s+/', $target)) { - $target = preg_replace('/^:copy\s+/', '', $target); - $copy = true; + else { + $target = $tokens[$i]; } - $result[] = array('type' => 'redirect', 'copy' => $copy, - 'target' => $this->_parse_string($target)); - } - else if(preg_match('/^(reject|ereject)\s+(.*);$/sm', $content, $matches)) { - $result[] = array('type' => $matches[1], 'target' => $this->_parse_string($matches[2])); } - else if(preg_match('/^vacation\s+(.*);$/sm', $content, $matches)) { - $vacation = array('type' => 'vacation'); - if (preg_match('/:days\s+([0-9]+)/', $content, $vm)) { - $vacation['days'] = $vm[1]; - $content = preg_replace('/:days\s+([0-9]+)/', '', $content); + $result[] = array('type' => $token, 'copy' => $copy, + 'target' => $target); + break; + + case 'reject': + case 'ereject': + $result[] = array('type' => $token, 'target' => array_pop($tokens)); + break; + + case 'vacation': + $vacation = array('type' => 'vacation', 'reason' => array_pop($tokens)); + + for ($i=0, $len=count($tokens); $i<$len; $i++) { + $tok = strtolower($tokens[$i]); + if ($tok == ':days') { + $vacation['days'] = $tokens[++$i]; } - if (preg_match('/:subject\s+"(.*?[^\\\])"/', $content, $vm)) { - $vacation['subject'] = $vm[1]; - $content = preg_replace('/:subject\s+"(.*?[^\\\])"/', '', $content); + else if ($tok == ':subject') { + $vacation['subject'] = $tokens[++$i]; } - if (preg_match('/:addresses\s+\[(.*?[^\\\])\]/', $content, $vm)) { - $vacation['addresses'] = $this->_parse_list($vm[1]); - $content = preg_replace('/:addresses\s+\[(.*?[^\\\])\]/', '', $content); + else if ($tok == ':addresses') { + $vacation['addresses'] = $tokens[++$i]; } - if (preg_match('/:handle\s+"(.*?[^\\\])"/', $content, $vm)) { - $vacation['handle'] = $vm[1]; - $content = preg_replace('/:handle\s+"(.*?[^\\\])"/', '', $content); + else if ($tok == ':handle') { + $vacation['handle'] = $tokens[++$i]; } - if (preg_match('/:from\s+"(.*?[^\\\])"/', $content, $vm)) { - $vacation['from'] = $vm[1]; - $content = preg_replace('/:from\s+"(.*?[^\\\])"/', '', $content); + else if ($tok == ':from') { + $vacation['from'] = $tokens[++$i]; } - - $content = preg_replace('/^vacation/', '', $content); - $content = preg_replace('/;$/', '', $content); - $content = trim($content); - - if (preg_match('/^:mime/', $content, $vm)) { + else if ($tok == ':mime') { $vacation['mime'] = true; - $content = preg_replace('/^:mime/', '', $content); } - - $vacation['reason'] = $this->_parse_string($content); - - $result[] = $vacation; } + + $result[] = $vacation; + break; } } @@ -820,171 +884,196 @@ class rcube_sieve_script } /** - * Parse test/conditions section + * Escape special chars into quoted string value or multi-line string + * or list of strings * - * @param string Text + * @param string $str Text or array (list) of strings + * + * @return string Result text */ - private function _parse_tests($content) + static function escape_string($str) { - $result = NULL; + if (is_array($str) && count($str) > 1) { + foreach($str as $idx => $val) + $str[$idx] = self::escape_string($val); - // lists - if (preg_match('/^(allof|anyof)\s+\((.*)\)$/sm', $content, $matches)) { - $content = $matches[2]; - $join = $matches[1]=='allof' ? true : false; + return '[' . implode(',', $str) . ']'; } - else - $join = false; - - // supported tests regular expressions - // TODO: comparators, envelope - $patterns[] = '(not\s+)?(exists)\s+\[(.*?[^\\\])\]'; - $patterns[] = '(not\s+)?(exists)\s+(".*?[^\\\]")'; - $patterns[] = '(not\s+)?(true)'; - $patterns[] = '(not\s+)?(size)\s+:(under|over)\s+([0-9]+[KGM]{0,1})'; - $patterns[] = '(not\s+)?(header)\s+:(contains|is|matches)((\s+))\[(.*?[^\\\]")\]\s+\[(.*?[^\\\]")\]'; - $patterns[] = '(not\s+)?(header)\s+:(contains|is|matches)((\s+))(".*?[^\\\]")\s+(".*?[^\\\]")'; - $patterns[] = '(not\s+)?(header)\s+:(contains|is|matches)((\s+))\[(.*?[^\\\]")\]\s+(".*?[^\\\]")'; - $patterns[] = '(not\s+)?(header)\s+:(contains|is|matches)((\s+))(".*?[^\\\]")\s+\[(.*?[^\\\]")\]'; - $patterns[] = '(not\s+)?(header)\s+:(count\s+"[gtleqn]{2}"|value\s+"[gtleqn]{2}")(\s+:comparator\s+"(.*?[^\\\])")?\s+\[(.*?[^\\\]")\]\s+\[(.*?[^\\\]")\]'; - $patterns[] = '(not\s+)?(header)\s+:(count\s+"[gtleqn]{2}"|value\s+"[gtleqn]{2}")(\s+:comparator\s+"(.*?[^\\\])")?\s+(".*?[^\\\]")\s+(".*?[^\\\]")'; - $patterns[] = '(not\s+)?(header)\s+:(count\s+"[gtleqn]{2}"|value\s+"[gtleqn]{2}")(\s+:comparator\s+"(.*?[^\\\])")?\s+\[(.*?[^\\\]")\]\s+(".*?[^\\\]")'; - $patterns[] = '(not\s+)?(header)\s+:(count\s+"[gtleqn]{2}"|value\s+"[gtleqn]{2}")(\s+:comparator\s+"(.*?[^\\\])")?\s+(".*?[^\\\]")\s+\[(.*?[^\\\]")\]'; - - // join patterns... - $pattern = '/(' . implode(')|(', $patterns) . ')/'; - - // ...and parse tests list - if (preg_match_all($pattern, $content, $matches, PREG_SET_ORDER)) { - foreach ($matches as $match) { - $size = sizeof($match); - - if (preg_match('/^(not\s+)?size/', $match[0])) { - $result[] = array( - 'test' => 'size', - 'not' => $match[$size-4] ? true : false, - 'type' => $match[$size-2], // under/over - 'arg' => $match[$size-1], // value - ); - } - else if (preg_match('/^(not\s+)?header/', $match[0])) { - $type = $match[$size-5]; - if (preg_match('/^(count|value)\s+"([gtleqn]{2})"/', $type, $m)) - $type = $m[1] . '-' . $m[2]; - - $result[] = array( - 'test' => 'header', - 'type' => $type, // is/contains/matches - 'not' => $match[$size-7] ? true : false, - 'arg1' => $this->_parse_list($match[$size-2]), // header(s) - 'arg2' => $this->_parse_list($match[$size-1]), // string(s) - ); - } - else if (preg_match('/^(not\s+)?exists/', $match[0])) { - $result[] = array( - 'test' => 'exists', - 'not' => $match[$size-3] ? true : false, - 'arg' => $this->_parse_list($match[$size-1]), // header(s) - ); - } - else if (preg_match('/^(not\s+)?true/', $match[0])) { - $result[] = array( - 'test' => 'true', - 'not' => $match[$size-2] ? true : false, - ); - } - } + else if (is_array($str)) { + $str = array_pop($str); } - return array($result, $join); + // multi-line string + if (preg_match('/[\r\n\0]/', $str) || strlen($str) > 1024) { + return sprintf("text:\n%s\n.\n", self::escape_multiline_string($str)); + } + // quoted-string + else { + $replace = array('\\' => '\\\\', '"' => '\\"'); + $str = str_replace(array_keys($replace), array_values($replace), $str); + return '"' . $str . '"'; + } } /** - * Parse string value + * Escape special chars in multi-line string value + * + * @param string $str Text * - * @param string Text + * @return string Text */ - private function _parse_string($content) + static function escape_multiline_string($str) { - $text = ''; - $content = trim($content); + $str = preg_split('/(\r?\n)/', $str, -1, PREG_SPLIT_DELIM_CAPTURE); - if (preg_match('/^text:(.*)\.$/sm', $content, $matches)) - $text = trim($matches[1]); - else if (preg_match('/^"(.*)"$/', $content, $matches)) - $text = str_replace('\"', '"', $matches[1]); + foreach ($str as $idx => $line) { + // dot-stuffing + if (isset($line[0]) && $line[0] == '.') { + $str[$idx] = '.' . $line; + } + } - return $text; + return implode($str); } /** - * Escape special chars in string value + * Splits script into string tokens + * + * @param string &$str The script + * @param mixed $num Number of tokens to return, 0 for all + * or True for all tokens until separator is found. + * Separator will be returned as last token. + * @param int $in_list Enable to called recursively inside a list * - * @param string Text + * @return mixed Tokens array or string if $num=1 */ - private function _escape_string($content) + static function tokenize(&$str, $num=0, $in_list=false) { - $replace['/"/'] = '\\"'; + $result = array(); - if (is_array($content)) { - for ($x=0, $y=sizeof($content); $x<$y; $x++) - $content[$x] = preg_replace(array_keys($replace), - array_values($replace), $content[$x]); + // remove spaces from the beginning of the string + while (($str = ltrim($str)) !== '' + && (!$num || $num === true || count($result) < $num) + ) { + switch ($str[0]) { - return $content; - } - else - return preg_replace(array_keys($replace), array_values($replace), $content); - } + // Quoted string + case '"': + $len = strlen($str); - /** - * Parse string or list of strings to string or array of strings - * - * @param string Text - */ - private function _parse_list($content) - { - $result = array(); + for ($pos=1; $pos<$len; $pos++) { + if ($str[$pos] == '"') { + break; + } + if ($str[$pos] == "\\") { + if ($str[$pos + 1] == '"' || $str[$pos + 1] == "\\") { + $pos++; + } + } + } + if ($str[$pos] != '"') { + // error + } + // we need to strip slashes for a quoted string + $result[] = stripslashes(substr($str, 1, $pos - 1)); + $str = substr($str, $pos + 1); + break; - for ($x=0, $len=strlen($content); $x<$len; $x++) { - switch ($content[$x]) { - case '\\': - $str .= $content[++$x]; + // Parenthesized list + case '[': + $str = substr($str, 1); + $result[] = self::tokenize($str, 0, true); break; - case '"': - if (isset($str)) { - $result[] = $str; - unset($str); + case ']': + $str = substr($str, 1); + return $result; + break; + + // list/test separator + case ',': + // command separator + case ';': + // block/tests-list + case '(': + case ')': + case '{': + case '}': + $sep = $str[0]; + $str = substr($str, 1); + if ($num === true) { + $result[] = $sep; + break 2; + } + break; + + // bracket-comment + case '/': + if ($str[1] == '*') { + if ($end_pos = strpos($str, '*/')) { + $str = substr($str, $end_pos + 2); + } + else { + // error + $str = ''; + } } - else - $str = ''; break; + + // hash-comment + case '#': + if ($lf_pos = strpos($str, "\n")) { + $str = substr($str, $lf_pos); + break; + } + else { + $str = ''; + } + + // String atom default: - if(isset($str)) - $str .= $content[$x]; - break; + // empty or one character + if ($str === '') { + break 2; + } + if (strlen($str) < 2) { + $result[] = $str; + $str = ''; + break; + } + + // tag/identifier/number + if (preg_match('/^([a-z0-9:_]+)/i', $str, $m)) { + $str = substr($str, strlen($m[1])); + + if ($m[1] != 'text:') { + $result[] = $m[1]; + } + // multiline string + else { + // possible hash-comment after "text:" + if (preg_match('/^( |\t)*(#[^\n]+)?\n/', $str, $m)) { + $str = substr($str, strlen($m[0])); + } + // get text until alone dot in a line + if (preg_match('/^(.*)\r?\n\.\r?\n/sU', $str, $m)) { + $text = $m[1]; + // remove dot-stuffing + $text = str_replace("\n..", "\n.", $text); + $str = substr($str, strlen($m[0])); + } + else { + $text = ''; + } + + $result[] = $text; + } + } + + break; } } - if (sizeof($result)>1) - return $result; - else if (sizeof($result) == 1) - return $result[0]; - else - return NULL; + return $num === 1 ? (isset($result[0]) ? $result[0] : null) : $result; } - /** - * Convert array of elements to list of strings - * - * @param string Text - */ - private function _print_list($list) - { - $list = (array) $list; - foreach($list as $idx => $val) - $list[$idx] = $this->_escape_string($val); - - return '["' . implode('","', $list) . '"]'; - } } diff --git a/plugins/managesieve/localization/es_ES.inc b/plugins/managesieve/localization/es_ES.inc index 6130d70..1dad18d 100644 --- a/plugins/managesieve/localization/es_ES.inc +++ b/plugins/managesieve/localization/es_ES.inc @@ -9,7 +9,7 @@ $labels['filteradd'] = 'Agregar filtro'; $labels['filterdel'] = 'Eliminar filtro'; $labels['moveup'] = 'Mover arriba'; $labels['movedown'] = 'Mover abajo'; -$labels['filterallof'] = 'coinidir con todas las reglas siguientes'; +$labels['filterallof'] = 'coincidir con todas las reglas siguientes'; $labels['filteranyof'] = 'coincidir con alguna de las reglas siguientes'; $labels['filterany'] = 'todos los mensajes'; $labels['filtercontains'] = 'contiene'; diff --git a/plugins/managesieve/localization/fr_FR.inc b/plugins/managesieve/localization/fr_FR.inc index 0b494f0..49bd3c6 100644 --- a/plugins/managesieve/localization/fr_FR.inc +++ b/plugins/managesieve/localization/fr_FR.inc @@ -27,6 +27,8 @@ $labels['messagereply'] = 'Répondre avec le message'; $labels['messagedelete'] = 'Supprimer le message'; $labels['messagediscard'] = 'Rejeter avec le message'; $labels['messagecopyto'] = 'Copier le message vers'; +$labels['messagesendcopy'] = 'Envoyer une copie du message à'; +$labels['messagecopyto'] = 'Copier le message vers'; $labels['messagesendcopy'] = 'Envoyer une copie du message à'; $labels['messagesrules'] = 'Pour les mails entrants:'; $labels['messagesactions'] = '...exécuter les actions suivantes:'; diff --git a/plugins/managesieve/localization/pl_PL.inc b/plugins/managesieve/localization/pl_PL.inc index e530619..1fbe65d 100644 --- a/plugins/managesieve/localization/pl_PL.inc +++ b/plugins/managesieve/localization/pl_PL.inc @@ -41,10 +41,10 @@ $labels['vacationaddresses'] = 'Lista dodatkowych adresów odbiorców (oddzielon $labels['vacationreason'] = 'Treść (przyczyna nieobecności):'; $labels['filterset'] = 'Zbiór filtrów'; $labels['filtersetadd'] = 'Dodaj zbiór filtrów'; -$labels['filtersetdel'] = 'Usuń bierzący zbiór filtrów'; -$labels['filtersetact'] = 'Aktywuj bierzący zbiór filtrów'; -$labels['filtersetdeact'] = 'Deaktywuj bierzący zbiór filtrów'; -$labels['filtersetget'] = 'Pobierz bierzący zbiór filtrów w formacie tekstowym'; +$labels['filtersetdel'] = 'Usuń bieżący zbiór filtrów'; +$labels['filtersetact'] = 'Aktywuj bieżący zbiór filtrów'; +$labels['filtersetdeact'] = 'Deaktywuj bieżący zbiór filtrów'; +$labels['filtersetget'] = 'Pobierz bieżący zbiór filtrów w formacie tekstowym'; $labels['filterdef'] = 'Definicja filtra'; $labels['filtersetname'] = 'Nazwa zbioru'; $labels['newfilterset'] = 'Nowy zbiór filtrów'; diff --git a/plugins/managesieve/localization/ru_RU.inc b/plugins/managesieve/localization/ru_RU.inc index c7c8bb0..c9cd336 100644 --- a/plugins/managesieve/localization/ru_RU.inc +++ b/plugins/managesieve/localization/ru_RU.inc @@ -76,6 +76,18 @@ $labels['countislessthanequal'] = 'количество меньше или ра $labels['countequals'] = 'количество равно'; $labels['countnotequals'] = 'количество не равно'; $labels['valueisgreaterthan'] = 'значение больше, чем'; +$labels['countisgreaterthan'] = 'кПлОчествП бПльше, чеЌ'; +$labels['countisgreaterthanequal'] = 'кПлОчествП бПльше ОлО равМП'; +$labels['countislessthan'] = 'кПлОчествП ЌеМьше, чеЌ'; +$labels['countislessthanequal'] = 'кПлОчествП ЌеМьше ОлО равМП'; +$labels['countequals'] = 'кПлОчествП равМП'; +$labels['countnotequals'] = 'кПлОчествП Ме равМП'; +$labels['valueisgreaterthan'] = 'зМачеМОе бПльше, чеЌ'; +$labels['valueisgreaterthanequal'] = 'зМачеМОе бПльше ОлО равМП'; +$labels['valueislessthan'] = 'зМачеМОе ЌеМьше, чеЌ'; +$labels['valueislessthanequal'] = 'зМачеМОе ЌеМьше ОлО равМП'; +$labels['valueequals'] = 'зМачеМОе равМП'; +$labels['valuenotequals'] = 'зМачеМОе Ме равМП'; $labels['valueisgreaterthanequal'] = 'значение больше или равно'; $labels['valueislessthan'] = 'значение меньше, чем'; $labels['valueislessthanequal'] = 'значение меньше или равно'; diff --git a/plugins/managesieve/managesieve.js b/plugins/managesieve/managesieve.js index 6b96561..04977eb 100644 --- a/plugins/managesieve/managesieve.js +++ b/plugins/managesieve/managesieve.js @@ -7,12 +7,10 @@ if (window.rcmail) { var button = $('').attr('href', rcmail.env.comm_path+'&_action=plugin.managesieve') .attr('title', rcmail.gettext('managesieve.managefilters')) .html(rcmail.gettext('managesieve.filters')) - .bind('click', function(e){ return rcmail.command('plugin.managesieve', this) }) .appendTo(tab); // add button and register commands rcmail.add_element(tab, 'tabs'); - rcmail.register_command('plugin.managesieve', function() { rcmail.goto_url('plugin.managesieve') }, true); rcmail.register_command('plugin.managesieve-save', function() { rcmail.managesieve_save() }, true); rcmail.register_command('plugin.managesieve-add', function() { rcmail.managesieve_add() }, true); rcmail.register_command('plugin.managesieve-del', function() { rcmail.managesieve_del() }, true); diff --git a/plugins/managesieve/managesieve.php b/plugins/managesieve/managesieve.php index 535f382..d8b6084 100644 --- a/plugins/managesieve/managesieve.php +++ b/plugins/managesieve/managesieve.php @@ -7,12 +7,12 @@ * It's clickable interface which operates on text scripts and communicates * with server using managesieve protocol. Adds Filters tab in Settings. * - * @version 2.10 + * @version 3.0 * @author Aleksander 'A.L.E.C' Machniak * * Configuration (see config.inc.php.dist) * - * $Id: managesieve.php 4241 2010-11-20 17:59:50Z alec $ + * $Id: managesieve.php 4555 2011-02-16 10:48:11Z alec $ */ class managesieve extends rcube_plugin @@ -66,7 +66,7 @@ class managesieve extends rcube_plugin $host = rcube_parse_host($this->rc->config->get('managesieve_host', 'localhost')); $port = $this->rc->config->get('managesieve_port', 2000); - $host = idn_to_ascii($host); + $host = rcube_idn_to_ascii($host); // try to connect to managesieve server and to fetch the script $this->sieve = new rcube_sieve($_SESSION['username'], diff --git a/plugins/managesieve/tests/Makefile b/plugins/managesieve/tests/Makefile new file mode 100644 index 0000000..072be2f --- /dev/null +++ b/plugins/managesieve/tests/Makefile @@ -0,0 +1,7 @@ + +clean: + rm -f *.log *.php *.diff *.exp *.out + + +test: + pear run-tests *.phpt diff --git a/plugins/managesieve/tests/parser.phpt b/plugins/managesieve/tests/parser.phpt new file mode 100644 index 0000000..a3b820d --- /dev/null +++ b/plugins/managesieve/tests/parser.phpt @@ -0,0 +1,103 @@ +--TEST-- +Main test of script parser +--SKIPIF-- +--FILE-- +as_text(); + +?> +--EXPECT-- +require ["fileinto","vacation","reject","relational","comparator-i;ascii-numeric"]; +# rule:[spam] +if header :contains "X-DSPAM-Result" "Spam" +{ + fileinto "Spam"; + stop; +} +# rule:[test1] +if header :contains ["From","To"] "test@domain.tld" +{ + discard; + stop; +} +# rule:[test2] +if anyof (not header :contains "Subject" "[test]", header :contains "Subject" "[test2]") +{ + fileinto "test"; + stop; +} +# rule:[test-vacation] +if header :contains "Subject" "vacation" +{ + vacation :days 1 text: +# test +test test /* test */ +test +. +; + stop; +} +# rule:[comments] +if true +{ + stop; +} +# rule:[reject] +if size :over 5000K +{ + reject "Message over 5MB size limit. Please contact me before sending this."; +} +# rule:[redirect] +if header :value "ge" :comparator "i;ascii-numeric" "X-Spam-score" "14" +{ + redirect "test@test.tld"; +} diff --git a/plugins/managesieve/tests/tokenize.phpt b/plugins/managesieve/tests/tokenize.phpt new file mode 100644 index 0000000..d1f68ac --- /dev/null +++ b/plugins/managesieve/tests/tokenize.phpt @@ -0,0 +1,66 @@ +--TEST-- +Script parsing: tokenizer +--SKIPIF-- +--FILE-- + $t) { + echo "[$idx]---------------\n"; + var_dump(rcube_sieve_script::tokenize($t[1], $t[0])); +} +?> +--EXPECT-- +[1]--------------- +string(34) "This is test ; message; +Multi line" +[2]--------------- +array(1) { + [0]=> + array(2) { + [0]=> + string(5) "test1" + [1]=> + string(5) "test2" + } +} +[3]--------------- +array(1) { + [0]=> + string(4) "test" +} +[4]--------------- +string(5) "te"st" +[5]--------------- +array(1) { + [0]=> + string(4) "test" +} +[6]--------------- +array(2) { + [0]=> + string(4) "test" + [1]=> + string(4) "test" +} +[7]--------------- +string(4) "a\"a" diff --git a/plugins/markasjunk/localization/cs_CZ.inc b/plugins/markasjunk/localization/cs_CZ.inc index c547e5a..18509cf 100644 --- a/plugins/markasjunk/localization/cs_CZ.inc +++ b/plugins/markasjunk/localization/cs_CZ.inc @@ -6,7 +6,7 @@ | language/cs_CZ/labels.inc | | | | Language file of the Roundcube markasjunk plugin | -| Copyright (C) 2005-2009, Roundcube Dev. - Switzerland | +| Copyright (C) 2005-2009, The Roundcube Dev Team | | Licensed under the GNU GPL | | | +-----------------------------------------------------------------------+ diff --git a/plugins/markasjunk/markasjunk.php b/plugins/markasjunk/markasjunk.php index 4c15a27..697d880 100644 --- a/plugins/markasjunk/markasjunk.php +++ b/plugins/markasjunk/markasjunk.php @@ -27,7 +27,9 @@ class markasjunk extends rcube_plugin 'command' => 'plugin.markasjunk', 'imagepas' => $skin_path.'/junk_pas.png', 'imageact' => $skin_path.'/junk_act.png', - 'title' => 'markasjunk.buttontitle'), 'toolbar'); + 'width' => 32, + 'height' => 32, + 'title' => 'markasjunk.buttontitle'), 'toolbar'); } } diff --git a/plugins/markasjunk/package.xml b/plugins/markasjunk/package.xml index 8ca7b18..d76bd0c 100644 --- a/plugins/markasjunk/package.xml +++ b/plugins/markasjunk/package.xml @@ -42,6 +42,7 @@ + diff --git a/plugins/new_user_identity/new_user_identity.php b/plugins/new_user_identity/new_user_identity.php index ecdf7c1..45750fa 100644 --- a/plugins/new_user_identity/new_user_identity.php +++ b/plugins/new_user_identity/new_user_identity.php @@ -40,7 +40,7 @@ class new_user_identity extends rcube_plugin if (count($results->records) == 1) { $args['user_name'] = $results->records[0]['name']; if (!$args['user_email'] && strpos($results->records[0]['email'], '@')) { - $args['user_email'] = idn_to_ascii($results->records[0]['email']); + $args['user_email'] = rcube_idn_to_ascii($results->records[0]['email']); } } } diff --git a/plugins/password/README b/plugins/password/README index a31a0e0..81e4f1e 100644 --- a/plugins/password/README +++ b/plugins/password/README @@ -201,7 +201,7 @@ As in sasl driver this one allows to change password using shell utility called "virtualmin". See drivers/chgvirtualminpasswd.c for - installation instructions. + installation instructions. See also config.inc.php.dist file. 2.9. hMailServer (hmail) diff --git a/plugins/password/config.inc.php.dist b/plugins/password/config.inc.php.dist index 54e9e51..ddf8812 100644 --- a/plugins/password/config.inc.php.dist +++ b/plugins/password/config.inc.php.dist @@ -18,6 +18,9 @@ $rcmail_config['password_minimum_length'] = 0; // Change to false to remove this check. $rcmail_config['password_require_nonalpha'] = false; +// Enables logging of password changes into logs/password +$rcmail_config['password_log'] = false; + // SQL Driver options // ------------------ @@ -195,8 +198,15 @@ $rcmail_config['password_ldap_force_replace'] = true; // Whenever the password is changed, the attribute will be updated if set (e.g. shadowLastChange) $rcmail_config['password_ldap_lchattr'] = ''; -// Also try to update Samba password attributes: sambaNTPassword and sambaPwdLastSet -$rcmail_config['password_ldap_samba'] = false; +// LDAP Samba password attribute, e.g. sambaNTPassword +// Name of the LDAP's Samba attribute used for storing user password +$rcmail_config['password_ldap_samba_pwattr'] = ''; + +// LDAP Samba Password Last Change Date attribute, e.g. sambaPwdLastSet +// Some places use an attribute to store the date of the last password change +// The date is meassured in "seconds since epoch" (an integer value) +// Whenever the password is changed, the attribute will be updated if set +$rcmail_config['password_ldap_samba_lchattr'] = ''; // DirectAdmin Driver options @@ -275,3 +285,16 @@ $rcmail_config['hmailserver_server'] = array( 'Password' => 'password' // windows user password ); + +// Virtualmin Driver options +// ------------------------- +// Username format: +// 0: username@domain +// 1: username%domain +// 2: username.domain +// 3: domain.username +// 4: username-domain +// 5: domain-username +// 6: username_domain +// 7: domain_username +$rcmail_config['password_virtualmin_format'] = 0; diff --git a/plugins/password/drivers/directadmin.php b/plugins/password/drivers/directadmin.php index d11aae7..6ca3264 100644 --- a/plugins/password/drivers/directadmin.php +++ b/plugins/password/drivers/directadmin.php @@ -316,8 +316,8 @@ class HTTPSocket { } } - - list($this->result_header,$this->result_body) = split("\r\n\r\n",$this->result,2); + + list($this->result_header, $this->result_body) = explode("\r\n\r\n", $this->result, 2); if ($this->bind_host) { @@ -378,7 +378,7 @@ class HTTPSocket { { if ($asArray) { - return split("\n",$this->fetch_body()); + return explode("\n", $this->fetch_body()); } return $this->fetch_body(); @@ -438,14 +438,14 @@ class HTTPSocket { */ function fetch_header( $header = '' ) { - $array_headers = split("\r\n",$this->result_header); - + $array_headers = explode("\r\n", $this->result_header); + $array_return = array( 0 => $array_headers[0] ); unset($array_headers[0]); foreach ( $array_headers as $pair ) { - list($key,$value) = split(": ",$pair,2); + list($key,$value) = explode(": ", $pair, 2); $array_return[strtolower($key)] = $value; } diff --git a/plugins/password/drivers/ldap.php b/plugins/password/drivers/ldap.php index e4d91fe..a18f349 100644 --- a/plugins/password/drivers/ldap.php +++ b/plugins/password/drivers/ldap.php @@ -62,43 +62,59 @@ function password_save($curpass, $passwd) return PASSWORD_CONNECT_ERROR; } - // Crypting new password - $newCryptedPassword = hashPassword($passwd, $rcmail->config->get('password_ldap_encodage')); - if (!$newCryptedPassword) { + $crypted_pass = hashPassword($passwd, $rcmail->config->get('password_ldap_encodage')); + $force = $rcmail->config->get('password_ldap_force_replace'); + $pwattr = $rcmail->config->get('password_ldap_pwattr'); + $lchattr = $rcmail->config->get('password_ldap_lchattr'); + $smbpwattr = $rcmail->config->get('password_ldap_samba_pwattr'); + $smblchattr = $rcmail->config->get('password_ldap_samba_lchattr'); + $samba = $rcmail->config->get('password_ldap_samba'); + + // Support password_ldap_samba option for backward compat. + if ($samba && !$smbpwattr) { + $smbpwattr = 'sambaNTPassword'; + $smblchattr = 'sambaPwdLastSet'; + } + + // Crypt new password + if (!$crypted_pass) { return PASSWORD_CRYPT_ERROR; } + // Crypt new samba password + if ($smbpwattr && !($samba_pass = hashPassword($passwd, 'samba'))) { + return PASSWORD_CRYPT_ERROR; + } + // Writing new crypted password to LDAP $userEntry = $ldap->getEntry($userDN); if (Net_LDAP2::isError($userEntry)) { return PASSWORD_CONNECT_ERROR; } - $pwattr = $rcmail->config->get('password_ldap_pwattr'); - $force = $rcmail->config->get('password_ldap_force_replace'); - - if (!$userEntry->replace(array($pwattr => $newCryptedPassword), $force)) { + if (!$userEntry->replace(array($pwattr => $crypted_pass), $force)) { return PASSWORD_CONNECT_ERROR; } // Updating PasswordLastChange Attribute if desired - if ($lchattr = $rcmail->config->get('password_ldap_lchattr')) { + if ($lchattr) { $current_day = (int)(time() / 86400); if (!$userEntry->replace(array($lchattr => $current_day), $force)) { return PASSWORD_CONNECT_ERROR; } } - if (Net_LDAP2::isError($userEntry->update())) { - return PASSWORD_CONNECT_ERROR; + // Update Samba password and last change fields + if ($smbpwattr) { + $userEntry->replace(array($smbpwattr => $samba_pass), $force); + } + // Update Samba password last change field + if ($smblchattr) { + $userEntry->replace(array($smblchattr => time()), $force); } - // Update Samba password fields, ignore errors if attributes are not found - if ($rcmail->config->get('password_ldap_samba')) { - $sambaNTPassword = hash('md4', rcube_charset_convert($passwd, RCMAIL_CHARSET, 'UTF-16LE')); - $userEntry->replace(array('sambaNTPassword' => $sambaNTPassword), $force); - $userEntry->replace(array('sambaPwdLastSet' => time()), $force); - $userEntry->update(); + if (Net_LDAP2::isError($userEntry->update())) { + return PASSWORD_CONNECT_ERROR; } // All done, no error @@ -253,6 +269,15 @@ function hashPassword( $passwordClear, $encodageType ) } break; + case 'samba': + if (function_exists('hash')) { + $cryptedPassword = hash('md4', rcube_charset_convert($password_clear, RCMAIL_CHARSET, 'UTF-16LE')); + } else { + /* Your PHP install does not have the hash() function */ + return false; + } + break; + case 'clear': default: $cryptedPassword = $passwordClear; diff --git a/plugins/password/drivers/ldap_simple.php b/plugins/password/drivers/ldap_simple.php index 67f53d0..482b7e5 100644 --- a/plugins/password/drivers/ldap_simple.php +++ b/plugins/password/drivers/ldap_simple.php @@ -14,19 +14,19 @@ function password_save($curpass, $passwd) { $rcmail = rcmail::get_instance(); - /* Connect */ + // Connect if (!$ds = ldap_connect($rcmail->config->get('password_ldap_host'), $rcmail->config->get('password_ldap_port'))) { ldap_unbind($ds); return PASSWORD_CONNECT_ERROR; } - /* Set protocol version */ + // Set protocol version if (!ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, $rcmail->config->get('password_ldap_version'))) { ldap_unbind($ds); return PASSWORD_CONNECT_ERROR; } - /* Start TLS */ + // Start TLS if ($rcmail->config->get('password_ldap_starttls')) { if (!ldap_start_tls($ds)) { ldap_unbind($ds); @@ -34,7 +34,7 @@ function password_save($curpass, $passwd) } } - /* Build user DN */ + // Build user DN if ($user_dn = $rcmail->config->get('password_ldap_userDN_mask')) { $user_dn = ldap_simple_substitute_vars($user_dn); } else { @@ -46,7 +46,7 @@ function password_save($curpass, $passwd) return PASSWORD_CONNECT_ERROR; } - /* Connection method */ + // Connection method switch ($rcmail->config->get('password_ldap_method')) { case 'admin': $binddn = $rcmail->config->get('password_ldap_adminDN'); @@ -59,31 +59,51 @@ function password_save($curpass, $passwd) break; } - /* Bind */ - if (!ldap_bind($ds, $binddn, $bindpw)) { - ldap_unbind($ds); - return PASSWORD_CONNECT_ERROR; - } - /* Crypting new password */ $crypted_pass = ldap_simple_hash_password($passwd, $rcmail->config->get('password_ldap_encodage')); + $lchattr = $rcmail->config->get('password_ldap_lchattr'); + $pwattr = $rcmail->config->get('password_ldap_pwattr'); + $smbpwattr = $rcmail->config->get('password_ldap_samba_pwattr'); + $smblchattr = $rcmail->config->get('password_ldap_samba_lchattr'); + $samba = $rcmail->config->get('password_ldap_samba'); + + // Support password_ldap_samba option for backward compat. + if ($samba && !$smbpwattr) { + $smbpwattr = 'sambaNTPassword'; + $smblchattr = 'sambaPwdLastSet'; + } + + // Crypt new password if (!$crypted_pass) { - ldap_unbind($ds); return PASSWORD_CRYPT_ERROR; } - $entree[$rcmail->config->get('password_ldap_pwattr')] = $crypted_pass; + // Crypt new Samba password + if ($smbpwattr && !($samba_pass = ldap_simple_hash_password($passwd, 'samba'))) { + return PASSWORD_CRYPT_ERROR; + } - /* Updating PasswordLastChange Attribute if desired */ - if ($lchattr = $rcmail->config->get('password_ldap_lchattr')) { + // Bind + if (!ldap_bind($ds, $binddn, $bindpw)) { + ldap_unbind($ds); + return PASSWORD_CONNECT_ERROR; + } + + $entree[$pwattr] = $crypted_pass; + + // Update PasswordLastChange Attribute if desired + if ($lchattr) { $entree[$lchattr] = (int)(time() / 86400); } - /* Update Samba password fields */ - if ($smbattr = $rcmail->config->get('password_ldap_samba')) { - $sambaNTPassword = hash('md4', rcube_charset_convert($passwd, RCMAIL_CHARSET, 'UTF-16LE')); - $entree['sambaNTPassword'] = $sambaNTPassword; - $entree['sambaPwdLastSet'] = time(); + // Update Samba password + if ($smbpwattr) { + $entree[$smbpwattr] = $samba_pass; + } + + // Update Samba password last change + if ($smblchattr) { + $entree[$smblchattr] = time(); } if (!ldap_modify($ds, $user_dn, $entree)) { @@ -91,7 +111,7 @@ function password_save($curpass, $passwd) return PASSWORD_CONNECT_ERROR; } - /* All done, no error */ + // All done, no error ldap_unbind($ds); return PASSWORD_SUCCESS; } @@ -215,6 +235,14 @@ function ldap_simple_hash_password($password_clear, $encodage_type) return false; } break; + case 'samba': + if (function_exists('hash')) { + $crypted_password = hash('md4', rcube_charset_convert($password_clear, RCMAIL_CHARSET, 'UTF-16LE')); + } else { + /* Your PHP install does not have the hash() function */ + return false; + } + break; case 'clear': default: $crypted_password = $password_clear; diff --git a/plugins/password/drivers/virtualmin.php b/plugins/password/drivers/virtualmin.php index 96200d6..78ef4e7 100644 --- a/plugins/password/drivers/virtualmin.php +++ b/plugins/password/drivers/virtualmin.php @@ -10,15 +10,50 @@ * It only works with virtualmin on the same host where Roundcube runs * and requires shell access and gcc in order to compile the binary. * - * @version 1.0 + * @version 2.0 * @author Martijn de Munnik */ function password_save($currpass, $newpass) { - $curdir = realpath(dirname(__FILE__)); - $username = escapeshellcmd($_SESSION['username']); - $domain = substr(strrchr($username, "@"), 1); + $rcmail = rcmail::get_instance(); + + $format = $rcmail->config->get('password_virtualmin_format', 0); + $username = $_SESSION['username']; + + switch ($format) { + case 1: // username%domain + $domain = substr(strrchr($username, "%"), 1); + break; + case 2: // username.domain (could be bogus) + $pieces = explode(".", $username); + $domain = $pieces[count($pieces)-2]. "." . end($pieces); + break; + case 3: // domain.username (could be bogus) + $pieces = explode(".", $username); + $domain = $pieces[0]. "." . $pieces[1]; + break; + case 4: // username-domain + $domain = substr(strrchr($username, "-"), 1); + break; + case 5: // domain-username + $domain = str_replace(strrchr($username, "-"), "", $username); + break; + case 6: // username_domain + $domain = substr(strrchr($username, "_"), 1); + break; + case 7: // domain_username + $pieces = explode("_", $username); + $domain = $pieces[0]; + break; + default: // username@domain + $domain = substr(strrchr($username, "@"), 1); + } + + $username = escapeshellcmd($username); + $domain = escapeshellcmd($domain); + $newpass = escapeshellcmd($newpass); + $curdir = realpath(dirname(__FILE__)); exec("$curdir/chgvirtualminpasswd modify-user --domain $domain --user $username --pass $newpass", $output, $returnvalue); diff --git a/plugins/password/drivers/xmail.php b/plugins/password/drivers/xmail.php index 39d1e71..c7f4261 100644 --- a/plugins/password/drivers/xmail.php +++ b/plugins/password/drivers/xmail.php @@ -20,7 +20,7 @@ function password_save($currpass, $newpass) { $rcmail = rcmail::get_instance(); - list($user,$domain) = split('@',$_SESSION['username']); + list($user,$domain) = explode('@', $_SESSION['username']); $xmail = new XMail; diff --git a/plugins/password/localization/es_ES.inc b/plugins/password/localization/es_ES.inc index b9a9c16..32879b4 100644 --- a/plugins/password/localization/es_ES.inc +++ b/plugins/password/localization/es_ES.inc @@ -1,21 +1,21 @@ diff --git a/plugins/password/localization/ru_RU.inc b/plugins/password/localization/ru_RU.inc index 5a108d6..3776b45 100644 --- a/plugins/password/localization/ru_RU.inc +++ b/plugins/password/localization/ru_RU.inc @@ -5,7 +5,7 @@ | plugins/password/localization/ru_RU.inc | | | | Language file of the Roundcube help plugin | -| Copyright (C) 2005-2010, Roundcube Dev. - Switzerland | +| Copyright (C) 2005-2010, The Roundcube Dev Team | | Licensed under the GNU GPL | | | +-----------------------------------------------------------------------+ diff --git a/plugins/password/package.xml b/plugins/password/package.xml index 1d63142..a4827df 100644 --- a/plugins/password/package.xml +++ b/plugins/password/package.xml @@ -15,8 +15,8 @@ alec@alec.pl yes - - + 2011-02-15 + 2.2 1.6 @@ -34,6 +34,11 @@ - ldap_simple driver: fix parse error - ldap/ldap_simple drivers: support %dc variable in config - ldap/ldap_simple drivers: support Samba password change +- Fix extended error messages handling (#1487676) +- Fix double request when clicking on Password tab in Firefox +- Fix deprecated split() usage in xmail and directadmin drivers (#1487769) +- Added option (password_log) for logging password changes +- Virtualmin driver: Add option for setting username format (#1487781) @@ -61,6 +66,7 @@ + diff --git a/plugins/password/password.js b/plugins/password/password.js index 17fe3f7..26376b3 100644 --- a/plugins/password/password.js +++ b/plugins/password/password.js @@ -7,13 +7,11 @@ if (window.rcmail) { rcmail.addEventListener('init', function(evt) { // var tab = $('').attr('id', 'settingstabpluginpassword').addClass('tablink'); - - var button = $('').attr('href', rcmail.env.comm_path+'&_action=plugin.password').html(rcmail.gettext('password')).appendTo(tab); - button.bind('click', function(e){ return rcmail.command('plugin.password', this) }); + var button = $('').attr('href', rcmail.env.comm_path+'&_action=plugin.password') + .html(rcmail.gettext('password')).appendTo(tab); // add button and register commands rcmail.add_element(tab, 'tabs'); - rcmail.register_command('plugin.password', function() { rcmail.goto_url('plugin.password') }, true); rcmail.register_command('plugin.password-save', function() { var input_curpasswd = rcube_find_object('_curpasswd'); var input_newpasswd = rcube_find_object('_newpasswd'); diff --git a/plugins/password/password.php b/plugins/password/password.php index 6d3042b..8fc95ea 100644 --- a/plugins/password/password.php +++ b/plugins/password/password.php @@ -128,7 +128,15 @@ class password extends rcube_plugin // try to save the password else if (!($res = $this->_save($curpwd, $newpwd))) { $rcmail->output->command('display_message', $this->gettext('successfullysaved'), 'confirmation'); + + // Reset session password $_SESSION['password'] = $rcmail->encrypt($newpwd); + + // Log password change + if ($rcmail->config->get('password_log')) { + write_log('password', sprintf('Password changed for user %s (ID: %d) from %s', + $rcmail->user->get_username(), $rcmail->user->ID, rcmail_remote_ip())); + } } else { $rcmail->output->command('display_message', $res, 'error'); @@ -232,8 +240,8 @@ class password extends rcube_plugin $result = password_save($curpass, $passwd); if (is_array($result)) { - $result = $result['code']; $message = $result['message']; + $result = $result['code']; } switch ($result) { diff --git a/plugins/show_additional_headers/show_additional_headers.php b/plugins/show_additional_headers/show_additional_headers.php index 1cbe690..0007ce3 100644 --- a/plugins/show_additional_headers/show_additional_headers.php +++ b/plugins/show_additional_headers/show_additional_headers.php @@ -44,7 +44,7 @@ class show_additional_headers extends rcube_plugin foreach ((array)$rcmail->config->get('show_additional_headers', array()) as $header) { $key = strtolower($header); if ($value = $p['headers']->others[$key]) - $p['output'][$key] = array('title' => $header, 'value' => $value); + $p['output'][$key] = array('title' => $header, 'value' => Q($value)); } return $p; diff --git a/plugins/squirrelmail_usercopy/squirrelmail_usercopy.php b/plugins/squirrelmail_usercopy/squirrelmail_usercopy.php index 5d7cc01..ee6bcc0 100644 --- a/plugins/squirrelmail_usercopy/squirrelmail_usercopy.php +++ b/plugins/squirrelmail_usercopy/squirrelmail_usercopy.php @@ -73,8 +73,8 @@ class squirrelmail_usercopy extends rcube_plugin foreach ($this->abook as $rec) { // #1487096 handle multi-address and/or too long items $rec['email'] = array_shift(explode(';', $rec['email'])); - if (check_email(idn_to_ascii($rec['email']))) { - $rec['email'] = idn_to_utf8($rec['email']); + if (check_email(rcube_idn_to_ascii($rec['email']))) { + $rec['email'] = rcube_idn_to_utf8($rec['email']); $contacts->insert($rec, true); } } diff --git a/plugins/subscriptions_option/localization/cs_CZ.inc b/plugins/subscriptions_option/localization/cs_CZ.inc index d625201..0d9c1fc 100644 --- a/plugins/subscriptions_option/localization/cs_CZ.inc +++ b/plugins/subscriptions_option/localization/cs_CZ.inc @@ -6,7 +6,7 @@ | language/cs_CZ/labels.inc | | | | Language file of the Roundcube subscriptions option plugin | -| Copyright (C) 2005-2009, Roundcube Dev. - Switzerland | +| Copyright (C) 2005-2009, The Roundcube Dev Team | | Licensed under the GNU GPL | | | +-----------------------------------------------------------------------+ diff --git a/plugins/userinfo/localization/cs_CZ.inc b/plugins/userinfo/localization/cs_CZ.inc index 30f8221..20cd4ae 100644 --- a/plugins/userinfo/localization/cs_CZ.inc +++ b/plugins/userinfo/localization/cs_CZ.inc @@ -6,7 +6,7 @@ | language/cs_CZ/labels.inc | | | | Language file of the Roundcube userinfo plugin | -| Copyright (C) 2005-2009, Roundcube Dev. - Switzerland | +| Copyright (C) 2005-2009, The Roundcube Dev Team | | Licensed under the GNU GPL | | | +-----------------------------------------------------------------------+ diff --git a/plugins/vcard_attachments/localization/cs_CZ.inc b/plugins/vcard_attachments/localization/cs_CZ.inc index 5d7c9c4..11ae8c9 100644 --- a/plugins/vcard_attachments/localization/cs_CZ.inc +++ b/plugins/vcard_attachments/localization/cs_CZ.inc @@ -5,7 +5,7 @@ | language/cs_CZ/labels.inc | | | | Language file of the Roundcube Webmail client | -| Copyright (C) 2008-2010, RoundQube Dev. - Switzerland | +| Copyright (C) 2008-2010, The Roundcube Dev Team | | Licensed under the GNU GPL | | | +-----------------------------------------------------------------------+ diff --git a/plugins/vcard_attachments/localization/es_ES.inc b/plugins/vcard_attachments/localization/es_ES.inc index c00b499..0aba6b3 100644 --- a/plugins/vcard_attachments/localization/es_ES.inc +++ b/plugins/vcard_attachments/localization/es_ES.inc @@ -1,7 +1,7 @@ \ No newline at end of file diff --git a/plugins/vcard_attachments/package.xml b/plugins/vcard_attachments/package.xml index 714750b..e5eaf71 100644 --- a/plugins/vcard_attachments/package.xml +++ b/plugins/vcard_attachments/package.xml @@ -51,6 +51,7 @@ + diff --git a/plugins/virtuser_file/virtuser_file.php b/plugins/virtuser_file/virtuser_file.php index d91e532..9d4efd1 100644 --- a/plugins/virtuser_file/virtuser_file.php +++ b/plugins/virtuser_file/virtuser_file.php @@ -40,7 +40,7 @@ class virtuser_file extends rcube_plugin $arr = preg_split('/\s+/', $r[$i]); if (count($arr) > 0 && strpos($arr[0], '@')) { - $result[] = idn_to_ascii(trim(str_replace('\\@', '@', $arr[0]))); + $result[] = rcube_idn_to_ascii(trim(str_replace('\\@', '@', $arr[0]))); if ($p['first']) { $p['email'] = $result[0]; diff --git a/plugins/virtuser_query/virtuser_query.php b/plugins/virtuser_query/virtuser_query.php index 8f154c2..e59095f 100644 --- a/plugins/virtuser_query/virtuser_query.php +++ b/plugins/virtuser_query/virtuser_query.php @@ -58,11 +58,11 @@ class virtuser_query extends rcube_plugin if (strpos($sql_arr[0], '@')) { if ($p['extended'] && count($sql_arr) > 1) { $result[] = array( - 'email' => idn_to_ascii($sql_arr[0]), + 'email' => rcube_idn_to_ascii($sql_arr[0]), 'name' => $sql_arr[1], 'organization' => $sql_arr[2], - 'reply-to' => idn_to_ascii($sql_arr[3]), - 'bcc' => idn_to_ascii($sql_arr[4]), + 'reply-to' => rcube_idn_to_ascii($sql_arr[3]), + 'bcc' => rcube_idn_to_ascii($sql_arr[4]), 'signature' => $sql_arr[5], 'html_signature' => (int)$sql_arr[6], ); diff --git a/program/include/iniset.php b/program/include/iniset.php index 73a02b0..92a2d90 100755 --- a/program/include/iniset.php +++ b/program/include/iniset.php @@ -16,7 +16,7 @@ | Thomas Bruederli | +-----------------------------------------------------------------------+ - $Id: iniset.php 4469 2011-01-29 14:55:12Z thomasb $ + $Id: iniset.php 4674 2011-04-20 09:03:08Z thomasb $ */ @@ -36,7 +36,7 @@ foreach ($crit_opts as $optname => $optval) { } // application constants -define('RCMAIL_VERSION', '0.5.1'); +define('RCMAIL_VERSION', '0.5.2'); define('RCMAIL_CHARSET', 'UTF-8'); define('JS_OBJECT_NAME', 'rcmail'); define('RCMAIL_START', microtime(true)); diff --git a/program/include/main.inc b/program/include/main.inc index d02dca5..76db567 100644 --- a/program/include/main.inc +++ b/program/include/main.inc @@ -15,7 +15,7 @@ | Author: Thomas Bruederli | +-----------------------------------------------------------------------+ - $Id: main.inc 4509 2011-02-09 10:51:50Z thomasb $ + $Id: main.inc 4568 2011-02-24 12:12:09Z alec $ */ @@ -972,7 +972,7 @@ function parse_attrib_string($str) * @return string Formatted date string */ function format_date($date, $format=NULL) - { +{ global $CONFIG; $ts = NULL; @@ -996,7 +996,7 @@ function format_date($date, $format=NULL) if (empty($ts)) return ''; - + // get user's timezone if ($CONFIG['timezone'] === 'auto') $tz = isset($_SESSION['timezone']) ? $_SESSION['timezone'] : date('Z')/3600; @@ -1008,7 +1008,7 @@ function format_date($date, $format=NULL) // convert time to user's timezone $timestamp = $ts - date('Z', $ts) + ($tz * 3600); - + // get current timestamp in user's timezone $now = time(); // local time $now -= (int)date('Z'); // make GMT time @@ -1016,30 +1016,33 @@ function format_date($date, $format=NULL) $now_date = getdate($now); $today_limit = mktime(0, 0, 0, $now_date['mon'], $now_date['mday'], $now_date['year']); - $week_limit = mktime(0, 0, 0, $now_date['mon'], $now_date['mday']-6, $now_date['year']); + $week_limit = mktime(0, 0, 0, $now_date['mon'], $now_date['mday']-6, $now_date['year']); // define date format depending on current time if (!$format) { - if ($CONFIG['prettydate'] && $timestamp > $today_limit && $timestamp < $now) - return sprintf('%s %s', rcube_label('today'), date($CONFIG['date_today'] ? $CONFIG['date_today'] : 'H:i', $timestamp)); + if ($CONFIG['prettydate'] && $timestamp > $today_limit && $timestamp < $now) { + $format = $CONFIG['date_today'] ? $CONFIG['date_today'] : 'H:i'; + $today = true; + } else if ($CONFIG['prettydate'] && $timestamp > $week_limit && $timestamp < $now) $format = $CONFIG['date_short'] ? $CONFIG['date_short'] : 'D H:i'; else $format = $CONFIG['date_long'] ? $CONFIG['date_long'] : 'd.m.Y H:i'; - } + } // strftime() format - if (preg_match('/%[a-z]+/i', $format)) - return strftime($format, $timestamp); + if (preg_match('/%[a-z]+/i', $format)) { + $format = strftime($format, $timestamp); + return $today ? (rcube_label('today') . ' ' . $format) : $format; + } // parse format string manually in order to provide localized weekday and month names // an alternative would be to convert the date() format string to fit with strftime() $out = ''; - for($i=0; $iplugins->exec_hook('hmtl_editor', array('mode' => $mode)); + $hook = $RCMAIL->plugins->exec_hook('html_editor', array('mode' => $mode)); if ($hook['abort']) return; diff --git a/program/include/rcmail.php b/program/include/rcmail.php index d3d2390..4aa95a0 100644 --- a/program/include/rcmail.php +++ b/program/include/rcmail.php @@ -15,7 +15,7 @@ | Author: Thomas Bruederli | +-----------------------------------------------------------------------+ - $Id: rcmail.php 4509 2011-02-09 10:51:50Z thomasb $ + $Id: rcmail.php 4626 2011-03-31 12:32:44Z alec $ */ @@ -1071,9 +1071,6 @@ class rcmail */ public function shutdown() { - if (is_object($this->imap)) - $this->imap->close(); - if (is_object($this->smtp)) $this->smtp->disconnect(); @@ -1108,12 +1105,9 @@ class rcmail */ public function get_request_token() { - $key = $this->task; - - if (!$_SESSION['request_tokens'][$key]) - $_SESSION['request_tokens'][$key] = md5(uniqid($key . mt_rand(), true)); - - return $_SESSION['request_tokens'][$key]; + $sess_id = $_COOKIE[ini_get('session.name')]; + if (!$sess_id) $sess_id = session_id(); + return md5('RT' . $this->task . $this->config->get('des_key') . $sess_id); } @@ -1126,7 +1120,8 @@ class rcmail public function check_request($mode = RCUBE_INPUT_POST) { $token = get_input_value('_token', $mode); - return !empty($token) && $_SESSION['request_tokens'][$this->task] == $token; + $sess_id = $_COOKIE[ini_get('session.name')]; + return !empty($sess_id) && $token == $this->get_request_token(); } @@ -1198,6 +1193,9 @@ class rcmail } } + if (is_object($this->imap)) + $this->imap->close(); + return $base64 ? base64_encode($cipher) : $cipher; } diff --git a/program/include/rcmail.php.orig b/program/include/rcmail.php.orig new file mode 100644 index 0000000..9613dba --- /dev/null +++ b/program/include/rcmail.php.orig @@ -0,0 +1,1325 @@ + | + +-----------------------------------------------------------------------+ + + $Id: rcmail.php 4626 2011-03-31 12:32:44Z alec $ + +*/ + + +/** + * Application class of Roundcube Webmail + * implemented as singleton + * + * @package Core + */ +class rcmail +{ + /** + * Main tasks. + * + * @var array + */ + static public $main_tasks = array('mail','settings','addressbook','login','logout','utils','dummy'); + + /** + * Singleton instace of rcmail + * + * @var rcmail + */ + static private $instance; + + /** + * Stores instance of rcube_config. + * + * @var rcube_config + */ + public $config; + + /** + * Stores rcube_user instance. + * + * @var rcube_user + */ + public $user; + + /** + * Instace of database class. + * + * @var rcube_mdb2 + */ + public $db; + + /** + * Instace of rcube_session class. + * + * @var rcube_session + */ + public $session; + + /** + * Instance of rcube_smtp class. + * + * @var rcube_smtp + */ + public $smtp; + + /** + * Instance of rcube_imap class. + * + * @var rcube_imap + */ + public $imap; + + /** + * Instance of rcube_template class. + * + * @var rcube_template + */ + public $output; + + /** + * Instance of rcube_plugin_api. + * + * @var rcube_plugin_api + */ + public $plugins; + + /** + * Current task. + * + * @var string + */ + public $task; + + /** + * Current action. + * + * @var string + */ + public $action = ''; + public $comm_path = './'; + + private $texts; + private $books = array(); + + + /** + * This implements the 'singleton' design pattern + * + * @return rcmail The one and only instance + */ + static function get_instance() + { + if (!self::$instance) { + self::$instance = new rcmail(); + self::$instance->startup(); // init AFTER object was linked with self::$instance + } + + return self::$instance; + } + + + /** + * Private constructor + */ + private function __construct() + { + // load configuration + $this->config = new rcube_config(); + + register_shutdown_function(array($this, 'shutdown')); + } + + + /** + * Initial startup function + * to register session, create database and imap connections + * + * @todo Remove global vars $DB, $USER + */ + private function startup() + { + // initialize syslog + if ($this->config->get('log_driver') == 'syslog') { + $syslog_id = $this->config->get('syslog_id', 'roundcube'); + $syslog_facility = $this->config->get('syslog_facility', LOG_USER); + openlog($syslog_id, LOG_ODELAY, $syslog_facility); + } + + // connect to database + $GLOBALS['DB'] = $this->get_dbh(); + + // start session + $this->session_init(); + + // create user object + $this->set_user(new rcube_user($_SESSION['user_id'])); + + // configure session (after user config merge!) + $this->session_configure(); + + // set task and action properties + $this->set_task(get_input_value('_task', RCUBE_INPUT_GPC)); + $this->action = asciiwords(get_input_value('_action', RCUBE_INPUT_GPC)); + + // reset some session parameters when changing task + if ($this->task != 'utils') { + if ($this->session && $_SESSION['task'] != $this->task) + $this->session->remove('page'); + // set current task to session + $_SESSION['task'] = $this->task; + } + + // init output class + if (!empty($_REQUEST['_remote'])) + $GLOBALS['OUTPUT'] = $this->json_init(); + else + $GLOBALS['OUTPUT'] = $this->load_gui(!empty($_REQUEST['_framed'])); + + // create plugin API and load plugins + $this->plugins = rcube_plugin_api::get_instance(); + + // init plugins + $this->plugins->init(); + } + + + /** + * Setter for application task + * + * @param string Task to set + */ + public function set_task($task) + { + $task = asciiwords($task); + + if ($this->user && $this->user->ID) + $task = !$task ? 'mail' : $task; + else + $task = 'login'; + + $this->task = $task; + $this->comm_path = $this->url(array('task' => $this->task)); + + if ($this->output) + $this->output->set_env('task', $this->task); + } + + + /** + * Setter for system user object + * + * @param rcube_user Current user instance + */ + public function set_user($user) + { + if (is_object($user)) { + $this->user = $user; + $GLOBALS['USER'] = $this->user; + + // overwrite config with user preferences + $this->config->set_user_prefs((array)$this->user->get_prefs()); + } + + $_SESSION['language'] = $this->user->language = $this->language_prop($this->config->get('language', $_SESSION['language'])); + + // set localization + setlocale(LC_ALL, $_SESSION['language'] . '.utf8', 'en_US.utf8'); + + // workaround for http://bugs.php.net/bug.php?id=18556 + if (in_array($_SESSION['language'], array('tr_TR', 'ku', 'az_AZ'))) + setlocale(LC_CTYPE, 'en_US' . '.utf8'); + } + + + /** + * Check the given string and return a valid language code + * + * @param string Language code + * @return string Valid language code + */ + private function language_prop($lang) + { + static $rcube_languages, $rcube_language_aliases; + + // user HTTP_ACCEPT_LANGUAGE if no language is specified + if (empty($lang) || $lang == 'auto') { + $accept_langs = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']); + $lang = str_replace('-', '_', $accept_langs[0]); + } + + if (empty($rcube_languages)) { + @include(INSTALL_PATH . 'program/localization/index.inc'); + } + + // check if we have an alias for that language + if (!isset($rcube_languages[$lang]) && isset($rcube_language_aliases[$lang])) { + $lang = $rcube_language_aliases[$lang]; + } + // try the first two chars + else if (!isset($rcube_languages[$lang])) { + $short = substr($lang, 0, 2); + + // check if we have an alias for the short language code + if (!isset($rcube_languages[$short]) && isset($rcube_language_aliases[$short])) { + $lang = $rcube_language_aliases[$short]; + } + // expand 'nn' to 'nn_NN' + else if (!isset($rcube_languages[$short])) { + $lang = $short.'_'.strtoupper($short); + } + } + + if (!isset($rcube_languages[$lang]) || !is_dir(INSTALL_PATH . 'program/localization/' . $lang)) { + $lang = 'en_US'; + } + + return $lang; + } + + + /** + * Get the current database connection + * + * @return rcube_mdb2 Database connection object + */ + public function get_dbh() + { + if (!$this->db) { + $config_all = $this->config->all(); + + $this->db = new rcube_mdb2($config_all['db_dsnw'], $config_all['db_dsnr'], $config_all['db_persistent']); + $this->db->sqlite_initials = INSTALL_PATH . 'SQL/sqlite.initial.sql'; + $this->db->set_debug((bool)$config_all['sql_debug']); + } + + return $this->db; + } + + + /** + * Return instance of the internal address book class + * + * @param string Address book identifier + * @param boolean True if the address book needs to be writeable + * @return rcube_contacts Address book object + */ + public function get_address_book($id, $writeable = false) + { + $contacts = null; + $ldap_config = (array)$this->config->get('ldap_public'); + $abook_type = strtolower($this->config->get('address_book_type')); + + $plugin = $this->plugins->exec_hook('addressbook_get', array('id' => $id, 'writeable' => $writeable)); + + // plugin returned instance of a rcube_addressbook + if ($plugin['instance'] instanceof rcube_addressbook) { + $contacts = $plugin['instance']; + } + else if ($id && $ldap_config[$id]) { + $contacts = new rcube_ldap($ldap_config[$id], $this->config->get('ldap_debug'), $this->config->mail_domain($_SESSION['imap_host'])); + } + else if ($id === '0') { + $contacts = new rcube_contacts($this->db, $this->user->ID); + } + else if ($abook_type == 'ldap') { + // Use the first writable LDAP address book. + foreach ($ldap_config as $id => $prop) { + if (!$writeable || $prop['writable']) { + $contacts = new rcube_ldap($prop, $this->config->get('ldap_debug'), $this->config->mail_domain($_SESSION['imap_host'])); + break; + } + } + } + else { // $id == 'sql' + $contacts = new rcube_contacts($this->db, $this->user->ID); + } + + // add to the 'books' array for shutdown function + if (!in_array($contacts, $this->books)) + $this->books[] = $contacts; + + return $contacts; + } + + + /** + * Return address books list + * + * @param boolean True if the address book needs to be writeable + * @return array Address books array + */ + public function get_address_sources($writeable = false) + { + $abook_type = strtolower($this->config->get('address_book_type')); + $ldap_config = $this->config->get('ldap_public'); + $autocomplete = (array) $this->config->get('autocomplete_addressbooks'); + $list = array(); + + // We are using the DB address book + if ($abook_type != 'ldap') { + $contacts = new rcube_contacts($this->db, null); + $list['0'] = array( + 'id' => 0, + 'name' => rcube_label('personaladrbook'), + 'groups' => $contacts->groups, + 'readonly' => false, + 'autocomplete' => in_array('sql', $autocomplete) + ); + } + + if ($ldap_config) { + $ldap_config = (array) $ldap_config; + foreach ($ldap_config as $id => $prop) + $list[$id] = array( + 'id' => $id, + 'name' => $prop['name'], + 'groups' => false, + 'readonly' => !$prop['writable'], + 'autocomplete' => in_array('sql', $autocomplete) + ); + } + + $plugin = $this->plugins->exec_hook('addressbooks_list', array('sources' => $list)); + $list = $plugin['sources']; + + if ($writeable && !empty($list)) { + foreach ($list as $idx => $item) { + if ($item['readonly']) { + unset($list[$idx]); + } + } + } + + return $list; + } + + + /** + * Init output object for GUI and add common scripts. + * This will instantiate a rcmail_template object and set + * environment vars according to the current session and configuration + * + * @param boolean True if this request is loaded in a (i)frame + * @return rcube_template Reference to HTML output object + */ + public function load_gui($framed = false) + { + // init output page + if (!($this->output instanceof rcube_template)) + $this->output = new rcube_template($this->task, $framed); + + // set keep-alive/check-recent interval + if ($this->session && ($keep_alive = $this->session->get_keep_alive())) { + $this->output->set_env('keep_alive', $keep_alive); + } + + if ($framed) { + $this->comm_path .= '&_framed=1'; + $this->output->set_env('framed', true); + } + + $this->output->set_env('task', $this->task); + $this->output->set_env('action', $this->action); + $this->output->set_env('comm_path', $this->comm_path); + $this->output->set_charset(RCMAIL_CHARSET); + + // add some basic label to client + $this->output->add_label('loading', 'servererror'); + + return $this->output; + } + + + /** + * Create an output object for JSON responses + * + * @return rcube_json_output Reference to JSON output object + */ + public function json_init() + { + if (!($this->output instanceof rcube_json_output)) + $this->output = new rcube_json_output($this->task); + + return $this->output; + } + + + /** + * Create SMTP object and connect to server + * + * @param boolean True if connection should be established + */ + public function smtp_init($connect = false) + { + $this->smtp = new rcube_smtp(); + + if ($connect) + $this->smtp->connect(); + } + + + /** + * Create global IMAP object and connect to server + * + * @param boolean True if connection should be established + * @todo Remove global $IMAP + */ + public function imap_init($connect = false) + { + // already initialized + if (is_object($this->imap)) + return; + + $this->imap = new rcube_imap($this->db); + $this->imap->debug_level = $this->config->get('debug_level'); + $this->imap->skip_deleted = $this->config->get('skip_deleted'); + + // enable caching of imap data + if ($this->config->get('enable_caching')) { + $this->imap->set_caching(true); + } + + // set pagesize from config + $this->imap->set_pagesize($this->config->get('pagesize', 50)); + + // Setting root and delimiter before establishing the connection + // can save time detecting them using NAMESPACE and LIST + $options = array( + 'auth_method' => $this->config->get('imap_auth_type', 'check'), + 'auth_cid' => $this->config->get('imap_auth_cid'), + 'auth_pw' => $this->config->get('imap_auth_pw'), + 'debug' => (bool) $this->config->get('imap_debug', 0), + 'force_caps' => (bool) $this->config->get('imap_force_caps'), + 'timeout' => (int) $this->config->get('imap_timeout', 0), + ); + + $this->imap->set_options($options); + + // set global object for backward compatibility + $GLOBALS['IMAP'] = $this->imap; + + $hook = $this->plugins->exec_hook('imap_init', array('fetch_headers' => $this->imap->fetch_add_headers)); + if ($hook['fetch_headers']) + $this->imap->fetch_add_headers = $hook['fetch_headers']; + + // support this parameter for backward compatibility but log warning + if ($connect) { + $this->imap_connect(); + raise_error(array( + 'code' => 800, 'type' => 'imap', + 'file' => __FILE__, 'line' => __LINE__, + 'message' => "rcube::imap_init(true) is deprecated, use rcube::imap_connect() instead"), + true, false); + } + } + + + /** + * Connect to IMAP server with stored session data + * + * @return bool True on success, false on error + */ + public function imap_connect() + { + if (!$this->imap) + $this->imap_init(); + + if ($_SESSION['imap_host'] && !$this->imap->conn->connected()) { + if (!$this->imap->connect($_SESSION['imap_host'], $_SESSION['username'], $this->decrypt($_SESSION['password']), $_SESSION['imap_port'], $_SESSION['imap_ssl'])) { + if ($this->output) + $this->output->show_message($this->imap->get_error_code() == -1 ? 'imaperror' : 'sessionerror', 'error'); + } + else { + $this->set_imap_prop(); + return $this->imap->conn; + } + } + + return false; + } + + + /** + * Create session object and start the session. + */ + public function session_init() + { + // session started (Installer?) + if (session_id()) + return; + + $lifetime = $this->config->get('session_lifetime', 0) * 60; + + // set session domain + if ($domain = $this->config->get('session_domain')) { + ini_set('session.cookie_domain', $domain); + } + // set session garbage collecting time according to session_lifetime + if ($lifetime) { + ini_set('session.gc_maxlifetime', $lifetime * 2); + } + + ini_set('session.cookie_secure', rcube_https_check()); + ini_set('session.name', 'roundcube_sessid'); + ini_set('session.use_cookies', 1); + ini_set('session.use_only_cookies', 1); + ini_set('session.serialize_handler', 'php'); + + // use database for storing session data + $this->session = new rcube_session($this->get_dbh(), $lifetime); + + $this->session->register_gc_handler('rcmail_temp_gc'); + if ($this->config->get('enable_caching')) + $this->session->register_gc_handler('rcmail_cache_gc'); + + // start PHP session (if not in CLI mode) + if ($_SERVER['REMOTE_ADDR']) + session_start(); + + // set initial session vars + if (!isset($_SESSION['auth_time'])) { + $_SESSION['auth_time'] = time(); + $_SESSION['temp'] = true; + } + } + + + /** + * Configure session object internals + */ + public function session_configure() + { + if (!$this->session) + return; + + $lifetime = $this->config->get('session_lifetime', 0) * 60; + + // set keep-alive/check-recent interval + if ($keep_alive = $this->config->get('keep_alive')) { + // be sure that it's less than session lifetime + if ($lifetime) + $keep_alive = min($keep_alive, $lifetime - 30); + $keep_alive = max(60, $keep_alive); + $this->session->set_keep_alive($keep_alive); + } + } + + + /** + * Perfom login to the IMAP server and to the webmail service. + * This will also create a new user entry if auto_create_user is configured. + * + * @param string IMAP user name + * @param string IMAP password + * @param string IMAP host + * @return boolean True on success, False on failure + */ + function login($username, $pass, $host=NULL) + { + $user = NULL; + $config = $this->config->all(); + + if (!$host) + $host = $config['default_host']; + + // Validate that selected host is in the list of configured hosts + if (is_array($config['default_host'])) { + $allowed = false; + foreach ($config['default_host'] as $key => $host_allowed) { + if (!is_numeric($key)) + $host_allowed = $key; + if ($host == $host_allowed) { + $allowed = true; + break; + } + } + if (!$allowed) + return false; + } + else if (!empty($config['default_host']) && $host != rcube_parse_host($config['default_host'])) + return false; + + // parse $host URL + $a_host = parse_url($host); + if ($a_host['host']) { + $host = $a_host['host']; + $imap_ssl = (isset($a_host['scheme']) && in_array($a_host['scheme'], array('ssl','imaps','tls'))) ? $a_host['scheme'] : null; + if (!empty($a_host['port'])) + $imap_port = $a_host['port']; + else if ($imap_ssl && $imap_ssl != 'tls' && (!$config['default_port'] || $config['default_port'] == 143)) + $imap_port = 993; + } + + $imap_port = $imap_port ? $imap_port : $config['default_port']; + + /* Modify username with domain if required + Inspired by Marco + */ + // Check if we need to add domain + if (!empty($config['username_domain']) && strpos($username, '@') === false) { + if (is_array($config['username_domain']) && isset($config['username_domain'][$host])) + $username .= '@'.rcube_parse_host($config['username_domain'][$host], $host); + else if (is_string($config['username_domain'])) + $username .= '@'.rcube_parse_host($config['username_domain'], $host); + } + + // Convert username to lowercase. If IMAP backend + // is case-insensitive we need to store always the same username (#1487113) + if ($config['login_lc']) { + $username = mb_strtolower($username); + } + + // try to resolve email address from virtuser table + if (strpos($username, '@') && ($virtuser = rcube_user::email2user($username))) { + $username = $virtuser; + } + + // Here we need IDNA ASCII + // Only rcube_contacts class is using domain names in Unicode + $host = rcube_idn_to_ascii($host); + if (strpos($username, '@')) { + // lowercase domain name + list($local, $domain) = explode('@', $username); + $username = $local . '@' . mb_strtolower($domain); + $username = rcube_idn_to_ascii($username); + } + + // user already registered -> overwrite username + if ($user = rcube_user::query($username, $host)) + $username = $user->data['username']; + + if (!$this->imap) + $this->imap_init(); + + // try IMAP login + if (!($imap_login = $this->imap->connect($host, $username, $pass, $imap_port, $imap_ssl))) { + // try with lowercase + $username_lc = mb_strtolower($username); + if ($username_lc != $username) { + // try to find user record again -> overwrite username + if (!$user && ($user = rcube_user::query($username_lc, $host))) + $username_lc = $user->data['username']; + + if ($imap_login = $this->imap->connect($host, $username_lc, $pass, $imap_port, $imap_ssl)) + $username = $username_lc; + } + } + + // exit if IMAP login failed + if (!$imap_login) + return false; + + $this->set_imap_prop(); + + // user already registered -> update user's record + if (is_object($user)) { + // create default folders on first login + if (!$user->data['last_login'] && $config['create_default_folders']) + $this->imap->create_default_folders(); + $user->touch(); + } + // create new system user + else if ($config['auto_create_user']) { + if ($created = rcube_user::create($username, $host)) { + $user = $created; + // create default folders on first login + if ($config['create_default_folders']) + $this->imap->create_default_folders(); + } + else { + raise_error(array( + 'code' => 600, 'type' => 'php', + 'file' => __FILE__, 'line' => __LINE__, + 'message' => "Failed to create a user record. Maybe aborted by a plugin?" + ), true, false); + } + } + else { + raise_error(array( + 'code' => 600, 'type' => 'php', + 'file' => __FILE__, 'line' => __LINE__, + 'message' => "Acces denied for new user $username. 'auto_create_user' is disabled" + ), true, false); + } + + // login succeeded + if (is_object($user) && $user->ID) { + $this->set_user($user); + + // set session vars + $_SESSION['user_id'] = $user->ID; + $_SESSION['username'] = $user->data['username']; + $_SESSION['imap_host'] = $host; + $_SESSION['imap_port'] = $imap_port; + $_SESSION['imap_ssl'] = $imap_ssl; + $_SESSION['password'] = $this->encrypt($pass); + $_SESSION['login_time'] = mktime(); + + if (isset($_REQUEST['_timezone']) && $_REQUEST['_timezone'] != '_default_') + $_SESSION['timezone'] = floatval($_REQUEST['_timezone']); + + // force reloading complete list of subscribed mailboxes + $this->imap->clear_cache('mailboxes'); + + return true; + } + + return false; + } + + + /** + * Set root dir and last stored mailbox + * This must be done AFTER connecting to the server! + */ + public function set_imap_prop() + { + $this->imap->set_charset($this->config->get('default_charset', RCMAIL_CHARSET)); + + if ($default_folders = $this->config->get('default_imap_folders')) { + $this->imap->set_default_mailboxes($default_folders); + } + if (isset($_SESSION['mbox'])) { + $this->imap->set_mailbox($_SESSION['mbox']); + } + if (isset($_SESSION['page'])) { + $this->imap->set_page($_SESSION['page']); + } + } + + + /** + * Auto-select IMAP host based on the posted login information + * + * @return string Selected IMAP host + */ + public function autoselect_host() + { + $default_host = $this->config->get('default_host'); + $host = null; + + if (is_array($default_host)) { + $post_host = get_input_value('_host', RCUBE_INPUT_POST); + + // direct match in default_host array + if ($default_host[$post_host] || in_array($post_host, array_values($default_host))) { + $host = $post_host; + } + + // try to select host by mail domain + list($user, $domain) = explode('@', get_input_value('_user', RCUBE_INPUT_POST)); + if (!empty($domain)) { + foreach ($default_host as $imap_host => $mail_domains) { + if (is_array($mail_domains) && in_array($domain, $mail_domains)) { + $host = $imap_host; + break; + } + } + } + + // take the first entry if $host is still an array + if (empty($host)) { + $host = array_shift($default_host); + } + } + else if (empty($default_host)) { + $host = get_input_value('_host', RCUBE_INPUT_POST); + } + else + $host = rcube_parse_host($default_host); + + return $host; + } + + + /** + * Get localized text in the desired language + * + * @param mixed Named parameters array or label name + * @return string Localized text + */ + public function gettext($attrib, $domain=null) + { + // load localization files if not done yet + if (empty($this->texts)) + $this->load_language(); + + // extract attributes + if (is_string($attrib)) + $attrib = array('name' => $attrib); + + $nr = is_numeric($attrib['nr']) ? $attrib['nr'] : 1; + $name = $attrib['name'] ? $attrib['name'] : ''; + + // check for text with domain + if ($domain && ($text_item = $this->texts[$domain.'.'.$name])) + ; + // text does not exist + else if (!($text_item = $this->texts[$name])) { + return "[$name]"; + } + + // make text item array + $a_text_item = is_array($text_item) ? $text_item : array('single' => $text_item); + + // decide which text to use + if ($nr == 1) { + $text = $a_text_item['single']; + } + else if ($nr > 0) { + $text = $a_text_item['multiple']; + } + else if ($nr == 0) { + if ($a_text_item['none']) + $text = $a_text_item['none']; + else if ($a_text_item['single']) + $text = $a_text_item['single']; + else if ($a_text_item['multiple']) + $text = $a_text_item['multiple']; + } + + // default text is single + if ($text == '') { + $text = $a_text_item['single']; + } + + // replace vars in text + if (is_array($attrib['vars'])) { + foreach ($attrib['vars'] as $var_key => $var_value) + $text = str_replace($var_key[0]!='$' ? '$'.$var_key : $var_key, $var_value, $text); + } + + // format output + if (($attrib['uppercase'] && strtolower($attrib['uppercase']=='first')) || $attrib['ucfirst']) + return ucfirst($text); + else if ($attrib['uppercase']) + return mb_strtoupper($text); + else if ($attrib['lowercase']) + return mb_strtolower($text); + + return $text; + } + + + /** + * Load a localization package + * + * @param string Language ID + */ + public function load_language($lang = null, $add = array()) + { + $lang = $this->language_prop(($lang ? $lang : $_SESSION['language'])); + + // load localized texts + if (empty($this->texts) || $lang != $_SESSION['language']) { + $this->texts = array(); + + // handle empty lines after closing PHP tag in localization files + ob_start(); + + // get english labels (these should be complete) + @include(INSTALL_PATH . 'program/localization/en_US/labels.inc'); + @include(INSTALL_PATH . 'program/localization/en_US/messages.inc'); + + if (is_array($labels)) + $this->texts = $labels; + if (is_array($messages)) + $this->texts = array_merge($this->texts, $messages); + + // include user language files + if ($lang != 'en' && is_dir(INSTALL_PATH . 'program/localization/' . $lang)) { + include_once(INSTALL_PATH . 'program/localization/' . $lang . '/labels.inc'); + include_once(INSTALL_PATH . 'program/localization/' . $lang . '/messages.inc'); + + if (is_array($labels)) + $this->texts = array_merge($this->texts, $labels); + if (is_array($messages)) + $this->texts = array_merge($this->texts, $messages); + } + + ob_end_clean(); + + $_SESSION['language'] = $lang; + } + + // append additional texts (from plugin) + if (is_array($add) && !empty($add)) + $this->texts += $add; + } + + + /** + * Read directory program/localization and return a list of available languages + * + * @return array List of available localizations + */ + public function list_languages() + { + static $sa_languages = array(); + + if (!sizeof($sa_languages)) { + @include(INSTALL_PATH . 'program/localization/index.inc'); + + if ($dh = @opendir(INSTALL_PATH . 'program/localization')) { + while (($name = readdir($dh)) !== false) { + if ($name[0] == '.' || !is_dir(INSTALL_PATH . 'program/localization/' . $name)) + continue; + + if ($label = $rcube_languages[$name]) + $sa_languages[$name] = $label; + } + closedir($dh); + } + } + + return $sa_languages; + } + + + /** + * Check the auth hash sent by the client against the local session credentials + * + * @return boolean True if valid, False if not + */ + function authenticate_session() + { + // advanced session authentication + if ($this->config->get('double_auth')) { + $now = time(); + $valid = ($_COOKIE['sessauth'] == $this->get_auth_hash(session_id(), $_SESSION['auth_time']) || + $_COOKIE['sessauth'] == $this->get_auth_hash(session_id(), $_SESSION['last_auth'])); + + // renew auth cookie every 5 minutes (only for GET requests) + if (!$valid || ($_SERVER['REQUEST_METHOD']!='POST' && $now - $_SESSION['auth_time'] > 300)) { + $_SESSION['last_auth'] = $_SESSION['auth_time']; + $_SESSION['auth_time'] = $now; + rcmail::setcookie('sessauth', $this->get_auth_hash(session_id(), $now), 0); + } + } + else { + $valid = $this->config->get('ip_check') ? $_SERVER['REMOTE_ADDR'] == $this->session->get_ip() : true; + } + + // check session filetime + $lifetime = $this->config->get('session_lifetime'); + $sess_ts = $this->session->get_ts(); + if (!empty($lifetime) && !empty($sess_ts) && $sess_ts + $lifetime*60 < time()) { + $valid = false; + } + + return $valid; + } + + + /** + * Destroy session data and remove cookie + */ + public function kill_session() + { + $this->plugins->exec_hook('session_destroy'); + + $this->session->remove(); + $_SESSION = array('language' => $this->user->language, 'auth_time' => time(), 'temp' => true); + rcmail::setcookie('sessauth', '-del-', time() - 60); + $this->user->reset(); + } + + + /** + * Do server side actions on logout + */ + public function logout_actions() + { + $config = $this->config->all(); + + // on logout action we're not connected to imap server + if (($config['logout_purge'] && !empty($config['trash_mbox'])) || $config['logout_expunge']) { + if (!$this->authenticate_session()) + return; + + $this->imap_connect(); + } + + if ($config['logout_purge'] && !empty($config['trash_mbox'])) { + $this->imap->clear_mailbox($config['trash_mbox']); + } + + if ($config['logout_expunge']) { + $this->imap->expunge('INBOX'); + } + } + + + /** + * Function to be executed in script shutdown + * Registered with register_shutdown_function() + */ + public function shutdown() + { + if (is_object($this->smtp)) + $this->smtp->disconnect(); + + foreach ($this->books as $book) + if (is_object($book)) + $book->close(); + + // before closing the database connection, write session data + if ($_SERVER['REMOTE_ADDR']) + session_write_close(); + + // write performance stats to logs/console + if ($this->config->get('devel_mode')) { + if (function_exists('memory_get_usage')) + $mem = show_bytes(memory_get_usage()); + if (function_exists('memory_get_peak_usage')) + $mem .= '/'.show_bytes(memory_get_peak_usage()); + + $log = $this->task . ($this->action ? '/'.$this->action : '') . ($mem ? " [$mem]" : ''); + if (defined('RCMAIL_START')) + rcube_print_time(RCMAIL_START, $log); + else + console($log); + } + } + + + /** + * Generate a unique token to be used in a form request + * + * @return string The request token + */ + public function get_request_token() + { + $sess_id = $_COOKIE[ini_get('session.name')]; + if (!$sess_id) $sess_id = session_id(); + return md5('RT' . $this->task . $this->config->get('des_key') . $sess_id); + } + + + /** + * Check if the current request contains a valid token + * + * @param int Request method + * @return boolean True if request token is valid false if not + */ + public function check_request($mode = RCUBE_INPUT_POST) + { + $token = get_input_value('_token', $mode); + $sess_id = $_COOKIE[ini_get('session.name')]; + return !empty($sess_id) && $token == $this->get_request_token(); + } + + + /** + * Create unique authorization hash + * + * @param string Session ID + * @param int Timestamp + * @return string The generated auth hash + */ + private function get_auth_hash($sess_id, $ts) + { + $auth_string = sprintf('rcmail*sess%sR%s*Chk:%s;%s', + $sess_id, + $ts, + $this->config->get('ip_check') ? $_SERVER['REMOTE_ADDR'] : '***.***.***.***', + $_SERVER['HTTP_USER_AGENT']); + + if (function_exists('sha1')) + return sha1($auth_string); + else + return md5($auth_string); + } + + + /** + * Encrypt using 3DES + * + * @param string $clear clear text input + * @param string $key encryption key to retrieve from the configuration, defaults to 'des_key' + * @param boolean $base64 whether or not to base64_encode() the result before returning + * + * @return string encrypted text + */ + public function encrypt($clear, $key = 'des_key', $base64 = true) + { + if (!$clear) + return ''; + /*- + * Add a single canary byte to the end of the clear text, which + * will help find out how much of padding will need to be removed + * upon decryption; see http://php.net/mcrypt_generic#68082 + */ + $clear = pack("a*H2", $clear, "80"); + + if (function_exists('mcrypt_module_open') && + ($td = mcrypt_module_open(MCRYPT_TripleDES, "", MCRYPT_MODE_CBC, ""))) + { + $iv = $this->create_iv(mcrypt_enc_get_iv_size($td)); + mcrypt_generic_init($td, $this->config->get_crypto_key($key), $iv); + $cipher = $iv . mcrypt_generic($td, $clear); + mcrypt_generic_deinit($td); + mcrypt_module_close($td); + } + else { + @include_once('lib/des.inc'); + + if (function_exists('des')) { + $des_iv_size = 8; + $iv = $this->create_iv($des_iv_size); + $cipher = $iv . des($this->config->get_crypto_key($key), $clear, 1, 1, $iv); + } + else { + raise_error(array( + 'code' => 500, 'type' => 'php', + 'file' => __FILE__, 'line' => __LINE__, + 'message' => "Could not perform encryption; make sure Mcrypt is installed or lib/des.inc is available" + ), true, true); + } + } + + if (is_object($this->imap)) + $this->imap->close(); + + return $base64 ? base64_encode($cipher) : $cipher; + } + + /** + * Decrypt 3DES-encrypted string + * + * @param string $cipher encrypted text + * @param string $key encryption key to retrieve from the configuration, defaults to 'des_key' + * @param boolean $base64 whether or not input is base64-encoded + * + * @return string decrypted text + */ + public function decrypt($cipher, $key = 'des_key', $base64 = true) + { + if (!$cipher) + return ''; + + $cipher = $base64 ? base64_decode($cipher) : $cipher; + + if (function_exists('mcrypt_module_open') && + ($td = mcrypt_module_open(MCRYPT_TripleDES, "", MCRYPT_MODE_CBC, ""))) + { + $iv_size = mcrypt_enc_get_iv_size($td); + $iv = substr($cipher, 0, $iv_size); + + // session corruption? (#1485970) + if (strlen($iv) < $iv_size) + return ''; + + $cipher = substr($cipher, $iv_size); + mcrypt_generic_init($td, $this->config->get_crypto_key($key), $iv); + $clear = mdecrypt_generic($td, $cipher); + mcrypt_generic_deinit($td); + mcrypt_module_close($td); + } + else { + @include_once('lib/des.inc'); + + if (function_exists('des')) { + $des_iv_size = 8; + $iv = substr($cipher, 0, $des_iv_size); + $cipher = substr($cipher, $des_iv_size); + $clear = des($this->config->get_crypto_key($key), $cipher, 0, 1, $iv); + } + else { + raise_error(array( + 'code' => 500, 'type' => 'php', + 'file' => __FILE__, 'line' => __LINE__, + 'message' => "Could not perform decryption; make sure Mcrypt is installed or lib/des.inc is available" + ), true, true); + } + } + + /*- + * Trim PHP's padding and the canary byte; see note in + * rcmail::encrypt() and http://php.net/mcrypt_generic#68082 + */ + $clear = substr(rtrim($clear, "\0"), 0, -1); + + return $clear; + } + + /** + * Generates encryption initialization vector (IV) + * + * @param int Vector size + * @return string Vector string + */ + private function create_iv($size) + { + // mcrypt_create_iv() can be slow when system lacks entrophy + // we'll generate IV vector manually + $iv = ''; + for ($i = 0; $i < $size; $i++) + $iv .= chr(mt_rand(0, 255)); + return $iv; + } + + /** + * Build a valid URL to this instance of Roundcube + * + * @param mixed Either a string with the action or url parameters as key-value pairs + * @return string Valid application URL + */ + public function url($p) + { + if (!is_array($p)) + $p = array('_action' => @func_get_arg(0)); + + $task = $p['_task'] ? $p['_task'] : ($p['task'] ? $p['task'] : $this->task); + $p['_task'] = $task; + unset($p['task']); + + $url = './'; + $delm = '?'; + foreach (array_reverse($p) as $key => $val) + { + if (!empty($val)) { + $par = $key[0] == '_' ? $key : '_'.$key; + $url .= $delm.urlencode($par).'='.urlencode($val); + $delm = '&'; + } + } + return $url; + } + + + /** + * Helper method to set a cookie with the current path and host settings + * + * @param string Cookie name + * @param string Cookie value + * @param string Expiration time + */ + public static function setcookie($name, $value, $exp = 0) + { + if (headers_sent()) + return; + + $cookie = session_get_cookie_params(); + + setcookie($name, $value, $exp, $cookie['path'], $cookie['domain'], + rcube_https_check(), true); + } +} + + diff --git a/program/include/rcube_browser.php b/program/include/rcube_browser.php index 82ba731..6579d9d 100644 --- a/program/include/rcube_browser.php +++ b/program/include/rcube_browser.php @@ -15,7 +15,7 @@ | Author: Thomas Bruederli | +-----------------------------------------------------------------------+ - $Id: rcube_browser.php 3989 2010-09-25 13:03:53Z alec $ + $Id: rcube_browser.php 4626 2011-03-31 12:32:44Z alec $ */ @@ -42,7 +42,7 @@ class rcube_browser $this->ns4 = strstr($HTTP_USER_AGENT, 'mozilla/4') && !strstr($HTTP_USER_AGENT, 'msie'); $this->ns = ($this->ns4 || strstr($HTTP_USER_AGENT, 'netscape')); $this->ie = !$this->opera && strstr($HTTP_USER_AGENT, 'compatible; msie'); - $this->mz = strstr($HTTP_USER_AGENT, 'mozilla/5'); + $this->mz = !$this->ie && strstr($HTTP_USER_AGENT, 'mozilla/5'); $this->chrome = strstr($HTTP_USER_AGENT, 'chrome'); $this->khtml = strstr($HTTP_USER_AGENT, 'khtml'); $this->safari = !$this->chrome && ($this->khtml || strstr($HTTP_USER_AGENT, 'safari')); diff --git a/program/include/rcube_imap.php b/program/include/rcube_imap.php index 9b65846..9a09180 100644 --- a/program/include/rcube_imap.php +++ b/program/include/rcube_imap.php @@ -16,7 +16,7 @@ | Author: Aleksander Machniak | +-----------------------------------------------------------------------+ - $Id: rcube_imap.php 4516 2011-02-09 12:46:46Z alec $ + $Id: rcube_imap.php 4643 2011-04-11 12:24:00Z alec $ */ @@ -2426,9 +2426,11 @@ class rcube_imap * @param rcube_message_part $o_part Part object created by get_structure() * @param mixed $print True to print part, ressource to write part contents in * @param resource $fp File pointer to save the message part + * @param boolean $skip_charset_conv Disables charset conversion + * * @return string Message/part body if not printed */ - function &get_message_part($uid, $part=1, $o_part=NULL, $print=NULL, $fp=NULL) + function &get_message_part($uid, $part=1, $o_part=NULL, $print=NULL, $fp=NULL, $skip_charset_conv=false) { // get part encoding if not provided if (!is_object($o_part)) { @@ -2458,10 +2460,13 @@ class rcube_imap return true; } - // convert charset (if text or message part) and part's charset is specified - if ($body && $o_part->charset - && preg_match('/^(text|message)$/', $o_part->ctype_primary) + // convert charset (if text or message part) + if ($body && !$skip_charset_conv && + preg_match('/^(text|message)$/', $o_part->ctype_primary) ) { + if (!$o_part->charset || strtoupper($o_part->charset) == 'US-ASCII') { + $o_part->charset = $this->default_charset; + } $body = rcube_charset_convert($body, $o_part->charset); } @@ -4344,80 +4349,95 @@ class rcube_imap */ public static function decode_mime_string($input, $fallback=null) { - // Initialize variable - $out = ''; + if (!empty($fallback)) { + $default_charset = $fallback; + } + else { + $default_charset = rcmail::get_instance()->config->get('default_charset', 'ISO-8859-1'); + } - // Iterate instead of recursing, this way if there are too many values we don't have stack overflows // rfc: all line breaks or other characters not found // in the Base64 Alphabet must be ignored by decoding software // delete all blanks between MIME-lines, differently we can // receive unnecessary blanks and broken utf-8 symbols $input = preg_replace("/\?=\s+=\?/", '?==?', $input); - // Check if there is stuff to decode - if (strpos($input, '=?') !== false) { - // Loop through the string to decode all occurences of =? ?= into the variable $out - while(($pos = strpos($input, '=?')) !== false) { - // Append everything that is before the text to be decoded - $out .= substr($input, 0, $pos); - - // Get the location of the text to decode - $end_cs_pos = strpos($input, "?", $pos+2); - $end_en_pos = strpos($input, "?", $end_cs_pos+1); - $end_pos = strpos($input, "?=", $end_en_pos+1); + // encoded-word regexp + $re = '/=\?([^?]+)\?([BbQq])\?([^?\n]*)\?=/'; - // Extract the encoded string - $encstr = substr($input, $pos+2, ($end_pos-$pos-2)); - // Extract the remaining string - $input = substr($input, $end_pos+2); + // Find all RFC2047's encoded words + if (preg_match_all($re, $input, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) { + // Initialize variables + $tmp = array(); + $out = ''; + $start = 0; - // Decode the string fragement - $out .= rcube_imap::_decode_mime_string_part($encstr); - } + foreach ($matches as $idx => $m) { + $pos = $m[0][1]; + $charset = $m[1][0]; + $encoding = $m[2][0]; + $text = $m[3][0]; + $length = strlen($m[0][0]); - // Deocde the rest (if any) - if (strlen($input) != 0) - $out .= rcube_imap::decode_mime_string($input, $fallback); + // Append everything that is before the text to be decoded + if ($start != $pos) { + $substr = substr($input, $start, $pos-$start); + $out .= rcube_charset_convert($substr, $default_charset); + $start = $pos; + } + $start += $length; + + // Per RFC2047, each string part "MUST represent an integral number + // of characters . A multi-octet character may not be split across + // adjacent encoded-words." However, some mailers break this, so we + // try to handle characters spanned across parts anyway by iterating + // through and aggregating sequential encoded parts with the same + // character set and encoding, then perform the decoding on the + // aggregation as a whole. + + $tmp[] = $text; + if ($next_match = $matches[$idx+1]) { + if ($next_match[0][1] == $start + && $next_match[1][0] == $charset + && $next_match[2][0] == $encoding + ) { + continue; + } + } - // return the results - return $out; - } - - // no encoding information, use fallback - return rcube_charset_convert($input, - !empty($fallback) ? $fallback : rcmail::get_instance()->config->get('default_charset', 'ISO-8859-1')); - } + $count = count($tmp); + $text = ''; + // Decode and join encoded-word's chunks + if ($encoding == 'B' || $encoding == 'b') { + // base64 must be decoded a segment at a time + for ($i=0; $i<$count; $i++) + $text .= base64_decode($tmp[$i]); + } + else { //if ($encoding == 'Q' || $encoding == 'q') { + // quoted printable can be combined and processed at once + for ($i=0; $i<$count; $i++) + $text .= $tmp[$i]; - /** - * Decode a part of a mime-encoded string - * - * @param string $str String to decode - * @return string Decoded string - * @access private - */ - private function _decode_mime_string_part($str) - { - $a = explode('?', $str); - $count = count($a); + $text = str_replace('_', ' ', $text); + $text = quoted_printable_decode($text); + } - // should be in format "charset?encoding?base64_string" - if ($count >= 3) { - for ($i=2; $i<$count; $i++) - $rest .= $a[$i]; + $out .= rcube_charset_convert($text, $charset); + $tmp = array(); + } - 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); + // add the last part of the input string + if ($start != strlen($input)) { + $out .= rcube_charset_convert(substr($input, $start), $default_charset); } - return rcube_charset_convert($rest, $a[0]); + // return the results + return $out; } - // we dont' know what to do with this - return $str; + // no encoding information, use fallback + return rcube_charset_convert($input, $default_charset); } diff --git a/program/include/rcube_imap_generic.php b/program/include/rcube_imap_generic.php index 18f1f5d..e2ee342 100644 --- a/program/include/rcube_imap_generic.php +++ b/program/include/rcube_imap_generic.php @@ -21,7 +21,7 @@ | Author: Ryo Chijiiwa | +-----------------------------------------------------------------------+ - $Id: rcube_imap_generic.php 4516 2011-02-09 12:46:46Z alec $ + $Id: rcube_imap_generic.php 4643 2011-04-11 12:24:00Z alec $ */ @@ -213,31 +213,26 @@ class rcube_imap_generic { $line = ''; - if (!$this->fp) { - return NULL; - } - if (!$size) { $size = 1024; } do { - if (feof($this->fp)) { + if ($this->eof()) { return $line ? $line : NULL; } $buffer = fgets($this->fp, $size); if ($buffer === false) { - @fclose($this->fp); - $this->fp = null; + $this->closeSocket(); break; } if ($this->_debug) { $this->debug('S: '. rtrim($buffer)); } $line .= $buffer; - } while ($buffer[strlen($buffer)-1] != "\n"); + } while (substr($buffer, -1) != "\n"); return $line; } @@ -267,7 +262,7 @@ class rcube_imap_generic { $data = ''; $len = 0; - while ($len < $bytes && !feof($this->fp)) + while ($len < $bytes && !$this->eof()) { $d = fread($this->fp, $bytes-$len); if ($this->_debug) { @@ -312,8 +307,7 @@ class rcube_imap_generic } else if ($res == 'BAD') { $this->errornum = self::ERROR_BAD; } else if ($res == 'BYE') { - @fclose($this->fp); - $this->fp = null; + $this->closeSocket(); $this->errornum = self::ERROR_BYE; } @@ -339,6 +333,32 @@ class rcube_imap_generic return self::ERROR_UNKNOWN; } + private function eof() + { + if (!is_resource($this->fp)) { + return true; + } + + // If a connection opened by fsockopen() wasn't closed + // by the server, feof() will hang. + $start = microtime(true); + + if (feof($this->fp) || + ($this->prefs['timeout'] && (microtime(true) - $start > $this->prefs['timeout'])) + ) { + $this->closeSocket(); + return true; + } + + return false; + } + + private function closeSocket() + { + @fclose($this->fp); + $this->fp = null; + } + function setError($code, $msg='') { $this->errornum = $code; @@ -360,8 +380,7 @@ class rcube_imap_generic } if ($error && preg_match('/^\* (BYE|BAD) /i', $string, $m)) { if (strtoupper($m[1]) == 'BYE') { - @fclose($this->fp); - $this->fp = null; + $this->closeSocket(); } return true; } @@ -701,11 +720,12 @@ class rcube_imap_generic $host = $this->prefs['ssl_mode'] . '://' . $host; } + if ($this->prefs['timeout'] <= 0) { + $this->prefs['timeout'] = ini_get('default_socket_timeout'); + } + // Connect - if ($this->prefs['timeout'] > 0) - $this->fp = @fsockopen($host, $this->prefs['port'], $errno, $errstr, $this->prefs['timeout']); - else - $this->fp = @fsockopen($host, $this->prefs['port'], $errno, $errstr); + $this->fp = @fsockopen($host, $this->prefs['port'], $errno, $errstr, $this->prefs['timeout']); if (!$this->fp) { $this->setError(self::ERROR_BAD, sprintf("Could not connect to %s:%d: %s", $host, $this->prefs['port'], $errstr)); @@ -757,6 +777,13 @@ class rcube_imap_generic // Now we're secure, capabilities need to be reread $this->clearCapability(); } + + // Use best (for security) supported authentication method + foreach (array('DIGEST-MD5', 'CRAM-MD5', 'CRAM_MD5', 'PLAIN', 'LOGIN') as $auth_method) { + if (in_array($auth_method, $auth_methods)) { + break; + } + } } // Send ID info @@ -782,6 +809,13 @@ class rcube_imap_generic else if (!$login_disabled) { $auth_methods[] = 'LOGIN'; } + + // Use best (for security) supported authentication method + foreach (array('DIGEST-MD5', 'CRAM-MD5', 'CRAM_MD5', 'PLAIN', 'LOGIN') as $auth_method) { + if (in_array($auth_method, $auth_methods)) { + break; + } + } } else { // Prevent from sending credentials in plain text when connection is not secure @@ -791,32 +825,28 @@ class rcube_imap_generic return false; } // replace AUTH with CRAM-MD5 for backward compat. - $auth_methods[] = $auth_method == 'AUTH' ? 'CRAM-MD5' : $auth_method; + if ($auth_method == 'AUTH') { + $auth_method = 'CRAM-MD5'; + } } // pre-login capabilities can be not complete $this->capability_readed = false; // Authenticate - foreach ($auth_methods as $method) { - switch ($method) { + switch ($auth_method) { case 'CRAM_MD5': - $method = 'CRAM-MD5'; + $auth_method = 'CRAM-MD5'; case 'CRAM-MD5': case 'DIGEST-MD5': case 'PLAIN': - $result = $this->authenticate($user, $password, $method); + $result = $this->authenticate($user, $password, $auth_method); break; case 'LOGIN': $result = $this->login($user, $password); break; default: - $this->setError(self::ERROR_BAD, "Configuration error. Unknown auth method: $method"); - } - - if (is_resource($result)) { - break; - } + $this->setError(self::ERROR_BAD, "Configuration error. Unknown auth method: $auth_method"); } // Connected and authenticated @@ -845,8 +875,7 @@ class rcube_imap_generic $this->readReply(); } - @fclose($this->fp); - $this->fp = false; + $this->closeSocket(); } /** @@ -935,6 +964,16 @@ class rcube_imap_generic list($mbox, $items) = $this->tokenizeResponse($response, 2); + // Fix for #1487859. Some buggy server returns not quoted + // folder name with spaces. Let's try to handle this situation + if (!is_array($items) && ($pos = strpos($response, '(')) !== false) { + $response = substr($response, $pos); + $items = $this->tokenizeResponse($response, 1); + if (!is_array($items)) { + return $result; + } + } + for ($i=0, $len=count($items); $i<$len; $i += 2) { $result[$items[$i]] = (int) $items[$i+1]; } @@ -1341,7 +1380,7 @@ class rcube_imap_generic $result[$id] = ''; } } else if ($mode == 2) { - if (preg_match('/\((UID|RFC822\.SIZE) ([0-9]+)/', $line, $matches)) { + if (preg_match('/(UID|RFC822\.SIZE) ([0-9]+)/', $line, $matches)) { $result[$id] = trim($matches[2]); } else { $result[$id] = 0; @@ -1540,36 +1579,21 @@ class rcube_imap_generic if (preg_match('/^\* [0-9]+ FETCH \((.*) BODY/sU', $line, $matches)) { $str = $matches[1]; - // swap parents with quotes, then explode - $str = preg_replace('/[()]/', '"', $str); - $a = rcube_explode_quoted_string(' ', $str); - - // did we get the right number of replies? - $parts_count = count($a); - if ($parts_count>=6) { - for ($i=0; $i<$parts_count; $i=$i+2) { - if ($a[$i] == 'UID') { - $result[$id]->uid = intval($a[$i+1]); - } - else if ($a[$i] == 'RFC822.SIZE') { - $result[$id]->size = intval($a[$i+1]); - } - else if ($a[$i] == 'INTERNALDATE') { - $time_str = $a[$i+1]; - } - else if ($a[$i] == 'FLAGS') { - $flags_str = $a[$i+1]; - } + while (list($name, $value) = $this->tokenizeResponse($str, 2)) { + if ($name == 'UID') { + $result[$id]->uid = intval($value); + } + else if ($name == 'RFC822.SIZE') { + $result[$id]->size = intval($value); + } + else if ($name == 'INTERNALDATE') { + $result[$id]->internaldate = $value; + $result[$id]->date = $value; + $result[$id]->timestamp = $this->StrToTime($value); + } + else if ($name == 'FLAGS') { + $flags_a = $value; } - - $time_str = str_replace('"', '', $time_str); - - // if time is gmt... - $time_str = str_replace('GMT','+0000',$time_str); - - $result[$id]->internaldate = $time_str; - $result[$id]->timestamp = $this->StrToTime($time_str); - $result[$id]->date = $time_str; } // BODYSTRUCTURE @@ -1617,7 +1641,7 @@ class rcube_imap_generic // handle FLAGS reply after headers (AOL, Zimbra?) if (preg_match('/\s+FLAGS \((.*)\)\)$/', $line, $matches)) { - $flags_str = $matches[1]; + $flags_a = $this->tokenizeResponse($matches[1]); break; } @@ -1641,10 +1665,10 @@ class rcube_imap_generic // create array with header field:data while (list($lines_key, $str) = each($lines)) { - list($field, $string) = $this->splitHeaderLine($str); + list($field, $string) = explode(':', $str, 2); $field = strtolower($field); - $string = preg_replace('/\n\s*/', ' ', $string); + $string = preg_replace('/\n[\t\s]*/', ' ', trim($string)); switch ($field) { case 'date'; @@ -1708,32 +1732,31 @@ class rcube_imap_generic } // process flags - if (!empty($flags_str)) { - $flags_str = preg_replace('/[\\\"]/', '', $flags_str); - $flags_a = explode(' ', $flags_str); - - if (is_array($flags_a)) { - foreach($flags_a as $flag) { - $flag = strtoupper($flag); - if ($flag == 'SEEN') { - $result[$id]->seen = true; - } else if ($flag == 'DELETED') { - $result[$id]->deleted = true; - } else if ($flag == 'RECENT') { - $result[$id]->recent = true; - } else if ($flag == 'ANSWERED') { - $result[$id]->answered = true; - } else if ($flag == '$FORWARDED') { - $result[$id]->forwarded = true; - } else if ($flag == 'DRAFT') { - $result[$id]->is_draft = true; - } else if ($flag == '$MDNSENT') { - $result[$id]->mdn_sent = true; - } else if ($flag == 'FLAGGED') { - $result[$id]->flagged = true; - } + if (!empty($flags_a)) { + foreach ($flags_a as $flag) { + $flag = str_replace('\\', '', $flag); + $result[$id]->flags[] = $flag; + + switch (strtoupper($flag)) { + case 'SEEN': + $result[$id]->seen = true; + break; + case 'DELETED': + $result[$id]->deleted = true; + break; + case 'ANSWERED': + $result[$id]->answered = true; + break; + case '$FORWARDED': + $result[$id]->forwarded = true; + break; + case '$MDNSENT': + $result[$id]->mdn_sent = true; + break; + case 'FLAGGED': + $result[$id]->flagged = true; + break; } - $result[$id]->flags = $flags_a; } } } @@ -3268,9 +3291,10 @@ class rcube_imap_generic { // support non-standard "GMTXXXX" literal $date = preg_replace('/GMT\s*([+-][0-9]+)/', '\\1', $date); + // if date parsing fails, we have a date in non-rfc format. // remove token from the end and try again - while ((($ts = @strtotime($date))===false) || ($ts < 0)) { + while (($ts = intval(@strtotime($date))) <= 0) { $d = explode(' ', $date); array_pop($d); if (!$d) { @@ -3284,17 +3308,6 @@ class rcube_imap_generic return $ts < 0 ? 0 : $ts; } - private function splitHeaderLine($string) - { - $pos = strpos($string, ':'); - if ($pos>0) { - $res[0] = substr($string, 0, $pos); - $res[1] = trim(substr($string, $pos+1)); - return $res; - } - return $string; - } - private function parseCapability($str, $trusted=false) { $str = preg_replace('/^\* CAPABILITY /i', '', $str); diff --git a/program/include/rcube_mdb2.php b/program/include/rcube_mdb2.php index ab9e648..a763f0c 100644 --- a/program/include/rcube_mdb2.php +++ b/program/include/rcube_mdb2.php @@ -16,7 +16,7 @@ | Author: Lukas Kahwe Smith | +-----------------------------------------------------------------------+ - $Id: rcube_mdb2.php 4057 2010-10-07 07:03:25Z alec $ + $Id: rcube_mdb2.php 4643 2011-04-11 12:24:00Z alec $ */ @@ -553,15 +553,7 @@ class rcube_mdb2 */ function fromunixtime($timestamp) { - switch($this->db_provider) { - case 'mysqli': - case 'mysql': - case 'sqlite': - return sprintf("FROM_UNIXTIME(%d)", $timestamp); - - default: - return date("'Y-m-d H:i:s'", $timestamp); - } + return date("'Y-m-d H:i:s'", $timestamp); } diff --git a/program/include/rcube_message.php b/program/include/rcube_message.php index 2f862b7..acf4a4d 100644 --- a/program/include/rcube_message.php +++ b/program/include/rcube_message.php @@ -15,7 +15,7 @@ | Author: Thomas Bruederli | +-----------------------------------------------------------------------+ - $Id: rcube_message.php 4516 2011-02-09 12:46:46Z alec $ + $Id: rcube_message.php 4643 2011-04-11 12:24:00Z alec $ */ @@ -725,7 +725,9 @@ class rcube_message $line = $prefix . rc_wordwrap($line, $length - $level - 2, " \r\n$prefix "); } else if ($line) { - $line = ' ' . rc_wordwrap(rtrim($line), $length - 2, " \r\n "); + $line = rc_wordwrap(rtrim($line), $length - 2, " \r\n"); + // space-stuffing + $line = preg_replace('/(^|\r\n)(From| |>)/', '\\1 \\2', $line); } $text[$idx] = $line; diff --git a/program/include/rcube_session.php b/program/include/rcube_session.php index 59ce423..0bae4a7 100644 --- a/program/include/rcube_session.php +++ b/program/include/rcube_session.php @@ -183,27 +183,12 @@ class rcube_session } - public function regenerate_id() + public function regenerate_id($destroy=true) { - $randval = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; - - for ($random = '', $i=1; $i <= 32; $i++) { - $random .= substr($randval, mt_rand(0,(strlen($randval) - 1)), 1); - } - - // use md5 value for id or remove capitals from string $randval - $random = md5($random); - - // delete old session record - $this->destroy(session_id()); - - session_id($random); - - $cookie = session_get_cookie_params(); - $lifetime = $cookie['lifetime'] ? time() + $cookie['lifetime'] : 0; - - rcmail::setcookie(session_name(), $random, $lifetime); + session_regenerate_id($destroy); + $this->vars = false; + $this->key = session_id(); return true; } diff --git a/program/include/rcube_smtp.php b/program/include/rcube_smtp.php index e795bc4..817eef8 100644 --- a/program/include/rcube_smtp.php +++ b/program/include/rcube_smtp.php @@ -15,7 +15,7 @@ | Author: Thomas Bruederli | +-----------------------------------------------------------------------+ - $Id: rcube_smtp.php 4509 2011-02-09 10:51:50Z thomasb $ + $Id: rcube_smtp.php 4666 2011-04-17 09:34:02Z alec $ */ @@ -105,7 +105,7 @@ class rcube_smtp $this->conn = new Net_SMTP($smtp_host, $smtp_port, $helo_host); - if($RCMAIL->config->get('smtp_debug')) + if ($RCMAIL->config->get('smtp_debug')) $this->conn->setDebug(true, array($this, 'debug_handler')); // try to connect to server and exit on failure @@ -118,6 +118,13 @@ class rcube_smtp return false; } + // workaround for timeout bug in Net_SMTP 1.5.[0-1] (#1487843) + if (method_exists($this->conn, 'setTimeout') + && ($timeout = ini_get('default_socket_timeout')) + ) { + $this->conn->setTimeout($timeout); + } + $smtp_user = str_replace('%u', $_SESSION['username'], $CONFIG['smtp_user']); $smtp_pass = str_replace('%p', $RCMAIL->decrypt($_SESSION['password']), $CONFIG['smtp_pass']); $smtp_auth_type = empty($CONFIG['smtp_auth_type']) ? NULL : $CONFIG['smtp_auth_type']; diff --git a/program/include/rcube_template.php b/program/include/rcube_template.php index fc11b73..4709c73 100755 --- a/program/include/rcube_template.php +++ b/program/include/rcube_template.php @@ -16,7 +16,7 @@ | Author: Thomas Bruederli | +-----------------------------------------------------------------------+ - $Id: rcube_template.php 4509 2011-02-09 10:51:50Z thomasb $ + $Id: rcube_template.php 4666 2011-04-17 09:34:02Z alec $ */ @@ -373,16 +373,19 @@ class rcube_template extends rcube_html_page private function parse($name = 'main', $exit = true) { $skin_path = $this->config['skin_path']; - $plugin = false; + $plugin = false; + $realname = $name; + $temp = explode('.', $name, 2); $this->plugin_skin_path = null; - $temp = explode(".", $name, 2); if (count($temp) > 1) { - $plugin = $temp[0]; - $name = $temp[1]; - $skin_dir = $plugin . '/skins/' . $this->config['skin']; + $plugin = $temp[0]; + $name = $temp[1]; + $skin_dir = $plugin . '/skins/' . $this->config['skin']; $skin_path = $this->plugin_skin_path = $this->app->plugins->dir . $skin_dir; - if (!is_dir($skin_path)) { // fallback to default skin + + // fallback to default skin + if (!is_dir($skin_path)) { $skin_dir = $plugin . '/skins/default'; $skin_path = $this->plugin_skin_path = $this->app->plugins->dir . $skin_dir; } @@ -390,12 +393,13 @@ class rcube_template extends rcube_html_page $path = "$skin_path/templates/$name.html"; - if (!is_readable($path) && $this->deprecated_templates[$name]) { - $path = "$skin_path/templates/".$this->deprecated_templates[$name].".html"; + if (!is_readable($path) && $this->deprecated_templates[$realname]) { + $path = "$skin_path/templates/".$this->deprecated_templates[$realname].".html"; if (is_readable($path)) raise_error(array('code' => 502, 'type' => 'php', 'file' => __FILE__, 'line' => __LINE__, - 'message' => "Using deprecated template '".$this->deprecated_templates[$name]."' in ".$this->config['skin_path']."/templates. Please rename to '".$name."'"), + 'message' => "Using deprecated template '".$this->deprecated_templates[$realname] + ."' in ".$this->config['skin_path']."/templates. Please rename to '".$realname."'"), true, false); } @@ -406,7 +410,7 @@ class rcube_template extends rcube_html_page 'type' => 'php', 'line' => __LINE__, 'file' => __FILE__, - 'message' => 'Error loading template for '.$name + 'message' => 'Error loading template for '.$realname ), true, true); return false; } @@ -422,7 +426,7 @@ class rcube_template extends rcube_html_page $output = $this->parse_xml($output); // trigger generic hook where plugins can put additional content to the page - $hook = $this->app->plugins->exec_hook("render_page", array('template' => $name, 'content' => $output)); + $hook = $this->app->plugins->exec_hook("render_page", array('template' => $realname, 'content' => $output)); // add debug console if ($this->config['debug_level'] & 8) { diff --git a/program/include/rcube_user.php b/program/include/rcube_user.php index c764b18..39a77ad 100644 --- a/program/include/rcube_user.php +++ b/program/include/rcube_user.php @@ -16,7 +16,7 @@ | Author: Thomas Bruederli | +-----------------------------------------------------------------------+ - $Id: rcube_user.php 4290 2010-11-30 13:43:04Z alec $ + $Id: rcube_user.php 4554 2011-02-16 09:42:31Z alec $ */ @@ -359,16 +359,15 @@ class rcube_user $dbh = rcmail::get_instance()->get_dbh(); // use BINARY (case-sensitive) comparison on MySQL, other engines are case-sensitive - $prefix = preg_match('/^mysql/', $dbh->db_provider) ? 'BINARY ' : ''; + $mod = preg_match('/^mysql/', $dbh->db_provider) ? 'BINARY' : ''; // query for matching user name - $query = "SELECT * FROM ".get_table_name('users')." WHERE mail_host = ? AND %s = ?"; - - $sql_result = $dbh->query(sprintf($query, $prefix.'username'), $host, $user); + $query = "SELECT * FROM ".get_table_name('users')." WHERE mail_host = ? AND %s = $mod ?"; + $sql_result = $dbh->query(sprintf($query, 'username'), $host, $user); // query for matching alias if (!($sql_arr = $dbh->fetch_assoc($sql_result))) { - $sql_result = $dbh->query(sprintf($query, $prefix.'alias'), $host, $user); + $sql_result = $dbh->query(sprintf($query, 'alias'), $host, $user); $sql_arr = $dbh->fetch_assoc($sql_result); } diff --git a/program/js/app.js b/program/js/app.js index 6eb3961..0915847 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -1,187 +1,184 @@ -function rcube_webmail(){this.env={};this.labels={};this.buttons={};this.buttons_sel={};this.gui_objects={};this.gui_containers={};this.commands={};this.command_handlers={};this.onloads=[];this.messages={};this.ref="rcmail";var l=this;this.dblclick_time=500;this.message_time=2E3;this.identifier_expr=RegExp("[^0-9a-z-_]","gi");this.mimetypes=["text/plain","text/html","text/xml","image/jpeg","image/gif","image/png","application/x-javascript","application/pdf","application/x-shockwave-flash"];this.env.keep_alive= -60;this.env.request_timeout=180;this.env.draft_autosave=0;this.env.comm_path="./";this.env.blankpage="program/blank.gif";$.ajaxSetup({cache:false,error:function(a,b,d){l.http_error(a,b,d)},beforeSend:function(a){a.setRequestHeader("X-Roundcube-Request",l.env.request_token)}});this.set_env=function(a,b){if(a!=null&&typeof a=="object"&&!b)for(var d in a)this.env[d]=a[d];else this.env[a]=b};this.add_label=function(a,b){this.labels[a]=b};this.register_button=function(a,b,d,e,f,g){this.buttons[a]||(this.buttons[a]= -[]);b={id:b,type:d};if(e)b.act=e;if(f)b.sel=f;if(g)b.over=g;this.buttons[a].push(b)};this.gui_object=function(a,b){this.gui_objects[a]=b};this.gui_container=function(a,b){this.gui_containers[a]=b};this.add_element=function(a,b){this.gui_containers[b]&&this.gui_containers[b].jquery&&this.gui_containers[b].append(a)};this.register_command=function(a,b,d){this.command_handlers[a]=b;d&&this.enable_command(a,true)};this.add_onload=function(a){this.onloads.push(a)};this.init=function(){var a=this;this.task= -this.env.task;if(!bw.dom||!bw.xmlhttp_test())this.goto_url("error","_code=0x199");else{for(var b in this.gui_containers)this.gui_containers[b]=$("#"+this.gui_containers[b]);for(b in this.gui_objects)this.gui_objects[b]=rcube_find_object(this.gui_objects[b]);this.init_buttons();if(this.is_framed()){parent.rcmail.set_busy(false,null,parent.rcmail.env.frame_lock);parent.rcmail.env.frame_lock=null}this.enable_command("logout","mail","addressbook","settings",true);this.env.permaurl&&this.enable_command("permaurl", -true);switch(this.task){case "mail":this.enable_command("list","checkmail","compose","add-contact","search","reset-search","collapse-folder",true);if(this.gui_objects.messagelist){this.message_list=new rcube_list_widget(this.gui_objects.messagelist,{multiselect:true,multiexpand:true,draggable:true,keyboard:true,column_movable:this.env.col_movable,dblclick_time:this.dblclick_time});this.message_list.row_init=function(e){a.init_message_row(e)};this.message_list.addEventListener("dblclick",function(e){a.msglist_dbl_click(e)}); -this.message_list.addEventListener("click",function(e){a.msglist_click(e)});this.message_list.addEventListener("keypress",function(e){a.msglist_keypress(e)});this.message_list.addEventListener("select",function(e){a.msglist_select(e)});this.message_list.addEventListener("dragstart",function(e){a.drag_start(e)});this.message_list.addEventListener("dragmove",function(e){a.drag_move(e)});this.message_list.addEventListener("dragend",function(e){a.drag_end(e)});this.message_list.addEventListener("expandcollapse", -function(e){a.msglist_expand(e)});this.message_list.addEventListener("column_replace",function(e){a.msglist_set_coltypes(e)});document.onmouseup=function(e){return a.doc_mouse_up(e)};this.gui_objects.messagelist.parentNode.onmousedown=function(e){return a.click_on_list(e)};this.message_list.init();this.enable_command("toggle_status","toggle_flag","menu-open","menu-save",true);this.command("list")}if(this.gui_objects.qsearchbox){if(this.env.search_text!=null)this.gui_objects.qsearchbox.value=this.env.search_text; +function rcube_webmail(){this.env={};this.labels={};this.buttons={};this.buttons_sel={};this.gui_objects={};this.gui_containers={};this.commands={};this.command_handlers={};this.onloads=[];this.messages={};this.ref="rcmail";var j=this;this.dblclick_time=500;this.message_time=2E3;this.identifier_expr=RegExp("[^0-9a-z-_]","gi");this.mimetypes=["text/plain","text/html","text/xml","image/jpeg","image/gif","image/png","application/x-javascript","application/pdf","application/x-shockwave-flash"];this.env.keep_alive= +60;this.env.request_timeout=180;this.env.draft_autosave=0;this.env.comm_path="./";this.env.blankpage="program/blank.gif";$.ajaxSetup({cache:!1,error:function(a,b,d){j.http_error(a,b,d)},beforeSend:function(a){a.setRequestHeader("X-Roundcube-Request",j.env.request_token)}});this.set_env=function(a,b){if(a!=null&&typeof a=="object"&&!b)for(var d in a)this.env[d]=a[d];else this.env[a]=b};this.add_label=function(a,b){this.labels[a]=b};this.register_button=function(a,b,d,e,f,g){this.buttons[a]||(this.buttons[a]= +[]);b={id:b,type:d};if(e)b.act=e;if(f)b.sel=f;if(g)b.over=g;this.buttons[a].push(b)};this.gui_object=function(a,b){this.gui_objects[a]=b};this.gui_container=function(a,b){this.gui_containers[a]=b};this.add_element=function(a,b){this.gui_containers[b]&&this.gui_containers[b].jquery&&this.gui_containers[b].append(a)};this.register_command=function(a,b,d){this.command_handlers[a]=b;d&&this.enable_command(a,!0)};this.add_onload=function(a){this.onloads.push(a)};this.init=function(){var a=this;this.task= +this.env.task;if(!bw.dom||!bw.xmlhttp_test())this.goto_url("error","_code=0x199");else{for(var b in this.gui_containers)this.gui_containers[b]=$("#"+this.gui_containers[b]);for(b in this.gui_objects)this.gui_objects[b]=rcube_find_object(this.gui_objects[b]);this.init_buttons();if(this.is_framed())parent.rcmail.set_busy(!1,null,parent.rcmail.env.frame_lock),parent.rcmail.env.frame_lock=null;this.enable_command("logout","mail","addressbook","settings",!0);this.env.permaurl&&this.enable_command("permaurl", +!0);switch(this.task){case "mail":this.enable_command("list","checkmail","compose","add-contact","search","reset-search","collapse-folder",!0);if(this.gui_objects.messagelist)this.message_list=new rcube_list_widget(this.gui_objects.messagelist,{multiselect:!0,multiexpand:!0,draggable:!0,keyboard:!0,column_movable:this.env.col_movable,dblclick_time:this.dblclick_time}),this.message_list.row_init=function(b){a.init_message_row(b)},this.message_list.addEventListener("dblclick",function(b){a.msglist_dbl_click(b)}), +this.message_list.addEventListener("click",function(b){a.msglist_click(b)}),this.message_list.addEventListener("keypress",function(b){a.msglist_keypress(b)}),this.message_list.addEventListener("select",function(b){a.msglist_select(b)}),this.message_list.addEventListener("dragstart",function(b){a.drag_start(b)}),this.message_list.addEventListener("dragmove",function(b){a.drag_move(b)}),this.message_list.addEventListener("dragend",function(b){a.drag_end(b)}),this.message_list.addEventListener("expandcollapse", +function(b){a.msglist_expand(b)}),this.message_list.addEventListener("column_replace",function(b){a.msglist_set_coltypes(b)}),document.onmouseup=function(b){return a.doc_mouse_up(b)},this.gui_objects.messagelist.parentNode.onmousedown=function(b){return a.click_on_list(b)},this.message_list.init(),this.enable_command("toggle_status","toggle_flag","menu-open","menu-save",!0),this.command("list");if(this.gui_objects.qsearchbox){if(this.env.search_text!=null)this.gui_objects.qsearchbox.value=this.env.search_text; $(this.gui_objects.qsearchbox).focusin(function(){rcmail.message_list.blur()})}this.env.trash_mailbox&&this.env.mailbox!=this.env.trash_mailbox&&this.set_alttext("delete","movemessagetotrash");this.env.message_commands=["show","reply","reply-all","reply-list","forward","moveto","copy","delete","open","mark","edit","viewsource","download","print","load-attachment","load-headers"];if(this.env.action=="show"||this.env.action=="preview"){this.enable_command(this.env.message_commands,this.env.uid);this.enable_command("reply-list", -this.env.list_post);this.env.action=="show"&&this.http_request("pagenav","_uid="+this.env.uid+"&_mbox="+urlencode(this.env.mailbox),this.display_message("","loading"));if(this.env.blockedobjects){if(this.gui_objects.remoteobjectsmsg)this.gui_objects.remoteobjectsmsg.style.display="block";this.enable_command("load-images","always-load",true)}if(this.env.action=="preview"&&this.is_framed()){this.enable_command("compose","add-contact",false);parent.rcmail.show_contentframe(true)}}else if(this.env.action== -"compose"){this.env.compose_commands=["send-attachment","remove-attachment","send","toggle-editor"];this.env.drafts_mailbox&&this.env.compose_commands.push("savedraft");this.enable_command(this.env.compose_commands,"identities",true);if(this.env.spellcheck){this.env.spellcheck.spelling_state_observer=function(e){l.set_spellcheck_state(e)};this.env.compose_commands.push("spellcheck");this.set_spellcheck_state("ready");$("input[name='_is_html']").val()=="1"&&this.display_spellcheck_controls(false)}document.onmouseup= -function(e){return a.doc_mouse_up(e)};this.init_messageform()}else this.env.action=="print"&&this.env.uid&&window.print();if(this.gui_objects.mailboxlist){this.env.unread_counts={};this.gui_objects.folderlist=this.gui_objects.mailboxlist;this.http_request("getunread","")}if(this.env.mdn_request&&this.env.uid){b="_uid="+this.env.uid+"&_mbox="+urlencode(this.env.mailbox);confirm(this.get_label("mdnrequest"))?this.http_post("sendmdn",b):this.http_post("mark",b+"&_flag=mdnsent")}break;case "addressbook":if(this.gui_objects.folderlist)this.env.contactfolders= -$.extend($.extend({},this.env.address_sources),this.env.contactgroups);if(this.gui_objects.contactslist){this.contact_list=new rcube_list_widget(this.gui_objects.contactslist,{multiselect:true,draggable:this.gui_objects.folderlist?true:false,keyboard:true});this.contact_list.row_init=function(e){a.triggerEvent("insertrow",{cid:e.uid,row:e})};this.contact_list.addEventListener("keypress",function(e){a.contactlist_keypress(e)});this.contact_list.addEventListener("select",function(e){a.contactlist_select(e)}); -this.contact_list.addEventListener("dragstart",function(e){a.drag_start(e)});this.contact_list.addEventListener("dragmove",function(e){a.drag_move(e)});this.contact_list.addEventListener("dragend",function(e){a.drag_end(e)});this.contact_list.init();this.env.cid&&this.contact_list.highlight_row(this.env.cid);this.gui_objects.contactslist.parentNode.onmousedown=function(e){return a.click_on_list(e)};document.onmouseup=function(e){return a.doc_mouse_up(e)};this.gui_objects.qsearchbox&&$(this.gui_objects.qsearchbox).focusin(function(){rcmail.contact_list.blur()})}this.set_page_buttons(); -if(this.env.address_sources&&this.env.address_sources[this.env.source]&&!this.env.address_sources[this.env.source].readonly){this.enable_command("add","import",true);this.enable_command("group-create",this.env.address_sources[this.env.source].groups)}if(this.env.cid){this.enable_command("show","edit",true);this.gui_objects.editform&&$("input.groupmember").change(function(){l.http_post(this.checked?"group-addmembers":"group-delmembers","_cid="+urlencode(l.env.cid)+"&_source="+urlencode(l.env.source)+ -"&_gid="+urlencode(this.value))})}if((this.env.action=="add"||this.env.action=="edit")&&this.gui_objects.editform){this.enable_command("save",true);$("input[type='text']").first().select()}else if(this.gui_objects.qsearchbox){this.enable_command("search","reset-search","moveto",true);$(this.gui_objects.qsearchbox).select()}this.contact_list&&this.contact_list.rowcount>0&&this.enable_command("export",true);this.enable_command("list","listgroup",true);break;case "settings":this.enable_command("preferences", -"identities","save","folders",true);if(this.env.action=="identities")this.enable_command("add",this.env.identities_level<2);else if(this.env.action=="edit-identity"||this.env.action=="add-identity"){this.enable_command("add",this.env.identities_level<2);this.enable_command("save","delete","edit","toggle-editor",true)}else if(this.env.action=="folders")this.enable_command("subscribe","unsubscribe","create-folder","rename-folder",true);else if(this.env.action=="edit-folder"&&this.gui_objects.editform){this.enable_command("save", -"folder-size",true);parent.rcmail.env.messagecount=this.env.messagecount;parent.rcmail.enable_command("purge",this.env.messagecount);$("input[type='text']").first().select()}if(this.gui_objects.identitieslist){this.identity_list=new rcube_list_widget(this.gui_objects.identitieslist,{multiselect:false,draggable:false,keyboard:false});this.identity_list.addEventListener("select",function(e){a.identity_select(e)});this.identity_list.init();this.identity_list.focus();this.env.iid&&this.identity_list.highlight_row(this.env.iid)}else if(this.gui_objects.sectionslist){this.sections_list= -new rcube_list_widget(this.gui_objects.sectionslist,{multiselect:false,draggable:false,keyboard:false});this.sections_list.addEventListener("select",function(e){a.section_select(e)});this.sections_list.init();this.sections_list.focus()}else this.gui_objects.subscriptionlist&&this.init_subscription_list();break;case "login":b=$("#rcmloginuser");b.bind("keyup",function(e){return rcmail.login_user_keyup(e)});b.val()==""?b.focus():$("#rcmloginpwd").focus();$("#rcmlogintz").val((new Date).getTimezoneOffset()/ --60);$("form").submit(function(){$("input[type=submit]",this).attr("disabled",true);rcmail.display_message("","loading")});this.enable_command("login",true)}this.loaded=true;this.pending_message&&this.display_message(this.pending_message[0],this.pending_message[1]);if(this.gui_objects.folderlist)this.gui_containers.foldertray=$(this.gui_objects.folderlist);this.triggerEvent("init",{task:this.task,action:this.env.action});for(var d in this.onloads)if(typeof this.onloads[d]=="string")eval(this.onloads[d]); -else if(typeof this.onloads[d]=="function")this.onloads[d]();this.start_keepalive()}};this.command=function(a,b,d){d&&d.blur&&d.blur();if(this.busy)return false;if(!this.commands[a]){this.is_framed()&&parent.rcmail.command(a,b);return false}if(this.task=="mail"&&this.env.action=="compose"&&$.inArray(a,this.env.compose_commands)<0)if(this.cmp_hash!=this.compose_field_hash()&&!confirm(this.get_label("notsentwarning")))return false;if(typeof this.command_handlers[a]=="function"){a=this.command_handlers[a](b, -d);return a!==null?a:d?false:true}else if(typeof this.command_handlers[a]=="string"){a=window[this.command_handlers[a]](b,d);return a!==null?a:d?false:true}this.triggerEvent("actionbefore",{props:b,action:a});var e=this.triggerEvent("before"+a,b);if(typeof e!="undefined")if(e===false)return false;else b=e;switch(a){case "login":this.gui_objects.loginform&&this.gui_objects.loginform.submit();break;case "mail":case "addressbook":case "settings":case "logout":this.switch_task(a);break;case "permaurl":if(d&& -d.href&&d.target)return true;else if(this.env.permaurl)parent.location.href=this.env.permaurl;break;case "menu-open":case "menu-save":this.triggerEvent(a,{props:b});return false;case "open":var f;if(f=this.get_single_uid()){d.href="?_task="+this.env.task+"&_action=show&_mbox="+urlencode(this.env.mailbox)+"&_uid="+f;return true}break;case "list":if(this.task=="mail"){if(!this.env.search_request||b&&b!=this.env.mailbox)this.reset_qsearch();this.list_mailbox(b);if(this.env.trash_mailbox)this.set_alttext("delete", -this.env.mailbox!=this.env.trash_mailbox?"movemessagetotrash":"deletemessage")}else if(this.task=="addressbook"){if(!this.env.search_request||b!=this.env.source)this.reset_qsearch();this.list_contacts(b);this.enable_command("add","import",this.env.address_sources&&!this.env.address_sources[this.env.source].readonly)}break;case "load-headers":this.load_headers(d);break;case "sort":var g=b;f=this.env.sort_col==g?this.env.sort_order=="ASC"?"DESC":"ASC":"ASC";this.set_list_sorting(g,f);this.list_mailbox("", -"",g+"_"+f);break;case "nextpage":this.list_page("next");break;case "lastpage":this.list_page("last");break;case "previouspage":this.list_page("prev");break;case "firstpage":this.list_page("first");break;case "expunge":this.env.messagecount&&this.expunge_mailbox(this.env.mailbox);break;case "purge":case "empty-mailbox":this.env.messagecount&&this.purge_mailbox(this.env.mailbox);break;case "show":if(this.task=="mail"){if((f=this.get_single_uid())&&(!this.env.uid||f!=this.env.uid))this.env.mailbox== -this.env.drafts_mailbox?this.goto_url("compose","_draft_uid="+f+"&_mbox="+urlencode(this.env.mailbox),true):this.show_message(f)}else if(this.task=="addressbook")(g=b?b:this.get_single_cid())&&!(this.env.action=="show"&&g==this.env.cid)&&this.load_contact(g,"show");break;case "add":if(this.task=="addressbook")this.load_contact(0,"add");else if(this.task=="settings"){this.identity_list.clear_selection();this.load_identity(0,"add-identity")}break;case "edit":if(this.task=="addressbook"&&(g=this.get_single_cid()))this.load_contact(g, -"edit");else if(this.task=="settings"&&b)this.load_identity(b,"edit-identity");else if(this.task=="mail"&&(g=this.get_single_uid())){e=this.env.mailbox==this.env.drafts_mailbox?"_draft_uid=":"_uid=";this.goto_url("compose",e+g+"&_mbox="+urlencode(this.env.mailbox),true)}break;case "save":if(this.gui_objects.editform){f=$("input[name='_pagesize']");g=$("input[name='_name']");e=$("input[name='_email']");if(f.length&&isNaN(parseInt(f.val()))){alert(this.get_label("nopagesizewarning"));f.focus();break}else if(g.length&& -g.val()==""){alert(this.get_label("nonamewarning"));g.focus();break}else if(e.length&&!rcube_check_email(e.val())){alert(this.get_label("noemailwarning"));e.focus();break}this.gui_objects.editform.submit()}break;case "delete":if(this.task=="mail")this.delete_messages();else if(this.task=="addressbook")this.delete_contacts();else this.task=="settings"&&this.delete_identity();break;case "move":case "moveto":if(this.task=="mail")this.move_messages(b);else this.task=="addressbook"&&this.drag_active&& -this.copy_contact(null,b);break;case "copy":this.task=="mail"&&this.copy_messages(b);break;case "mark":b&&this.mark_message(b);break;case "toggle_status":if(b&&!b._row)break;g="read";if(b._row.uid){f=b._row.uid;if(this.message_list.rows[f].deleted)g="undelete";else this.message_list.rows[f].unread||(g="unread")}this.mark_message(g,f);break;case "toggle_flag":if(b&&!b._row)break;g="flagged";if(b._row.uid){f=b._row.uid;if(this.message_list.rows[f].flagged)g="unflagged"}this.mark_message(g,f);break; -case "always-load":if(this.env.uid&&this.env.sender){this.add_contact(urlencode(this.env.sender));window.setTimeout(function(){l.command("load-images")},300);break}case "load-images":this.env.uid&&this.show_message(this.env.uid,true,this.env.action=="preview");break;case "load-attachment":f="_mbox="+urlencode(this.env.mailbox)+"&_uid="+this.env.uid+"&_part="+b.part;if(this.env.uid&&b.mimetype&&$.inArray(b.mimetype,this.mimetypes)>=0){if(b.mimetype=="text/html")f+="&_safe=1";if(this.attachment_win= -window.open(this.env.comm_path+"&_action=get&"+f+"&_frame=1","rcubemailattachment")){window.setTimeout(function(){l.attachment_win.focus()},10);break}}this.goto_url("get",f+"&_download=1",false);break;case "select-all":this.select_all_mode=b?false:true;this.dummy_select=true;b=="invert"?this.message_list.invert_selection():this.message_list.select_all(b=="page"?"":b);this.dummy_select=null;break;case "select-none":this.select_all_mode=false;this.message_list.clear_selection();break;case "expand-all":this.env.autoexpand_threads= -1;this.message_list.expand_all();break;case "expand-unread":this.env.autoexpand_threads=2;this.message_list.collapse_all();this.expand_unread();break;case "collapse-all":this.env.autoexpand_threads=0;this.message_list.collapse_all();break;case "nextmessage":this.env.next_uid&&this.show_message(this.env.next_uid,false,this.env.action=="preview");break;case "lastmessage":this.env.last_uid&&this.show_message(this.env.last_uid);break;case "previousmessage":this.env.prev_uid&&this.show_message(this.env.prev_uid, -false,this.env.action=="preview");break;case "firstmessage":this.env.first_uid&&this.show_message(this.env.first_uid);break;case "checkmail":this.check_for_recent(true);break;case "compose":e=this.env.comm_path+"&_action=compose";if(this.task=="mail"){e+="&_mbox="+urlencode(this.env.mailbox);if(this.env.mailbox==this.env.drafts_mailbox){if(f=this.get_single_uid())e+="&_draft_uid="+f}else if(b)e+="&_to="+urlencode(b)}else if(this.task=="addressbook"){if(b&&b.indexOf("@")>0){e=this.get_task_url("mail", -e);this.redirect(e+"&_to="+urlencode(b));break}f=[];if(b)f.push(b);else if(this.contact_list){g=this.contact_list.get_selection();for(e=0;e0){f=this.env.source?"_source="+urlencode(this.env.source)+"&":"";if(this.env.search_request)f+="_search="+this.env.search_request;this.goto_url("export",f)}break;case "preferences":case "identities":case "folders":this.goto_url("settings/"+a);break;default:f=a.replace(/-/g,"_"); -if(this[f]&&typeof this[f]=="function")this[f](b)}this.triggerEvent("after"+a,b);this.triggerEvent("actionafter",{props:b,action:a});return d?false:true};this.enable_command=function(){for(var a=Array.prototype.slice.call(arguments),b=a.pop(),d,e=0;e=e.x2||a.y=e.y2){if(this.env.last_folder_target){$(this.get_folder_li(this.env.last_folder_target)).removeClass("droptarget");this.env.folder_coords[this.env.last_folder_target].on=0;this.env.last_folder_target=null}}else for(var g in this.env.folder_coords){e= -this.env.folder_coords[g];if(a.x>=e.x1&&a.x=e.y1&&a.y1?"copy":"normal")}else this.env.last_folder_target=null;else if(e.on){$(this.get_folder_li(g)).removeClass("droptarget");this.env.folder_coords[g].on=0}}d!=f&&this.contact_list&&this.contact_list.draglayer&&this.contact_list.draglayer.attr("class",d)}};this.collapse_folder=function(a){var b=this.get_folder_li(a),d=$(b.getElementsByTagName("div")[0]); -if(!(!d||!d.hasClass("collapsed")&&!d.hasClass("expanded"))){var e=$(b.getElementsByTagName("ul")[0]);if(d.hasClass("collapsed")){e.show();d.removeClass("collapsed").addClass("expanded");this.set_env("collapsed_folders",this.env.collapsed_folders.replace(RegExp("&"+urlencode(a)+"&"),""))}else{e.hide();d.removeClass("expanded").addClass("collapsed");this.set_env("collapsed_folders",this.env.collapsed_folders+"&"+urlencode(a)+"&");this.env.mailbox.indexOf(a+this.env.delimiter)==0&&this.command("list", -a)}if(bw.ie6||bw.ie7)if((d=b.nextSibling?b.nextSibling.getElementsByTagName("ul"):null)&&d.length&&(b=d[0])&&b.style&&b.style.display!="none"){b.style.display="none";b.style.display=""}this.http_post("save-pref","_name=collapsed_folders&_value="+urlencode(this.env.collapsed_folders));this.set_unread_count_display(a,false)}};this.doc_mouse_up=function(a){var b,d;if(this.message_list){rcube_mouse_is_over(a,this.message_list.list.parentNode)?this.message_list.focus():this.message_list.blur();d=this.message_list; -b=this.env.mailboxes}else if(this.contact_list){rcube_mouse_is_over(a,this.contact_list.list.parentNode)?this.contact_list.focus():this.contact_list.blur();d=this.contact_list;b=this.env.contactfolders}else this.ksearch_value&&this.ksearch_blur();if(this.drag_active&&b&&this.env.last_folder_target){b=b[this.env.last_folder_target];$(this.get_folder_li(this.env.last_folder_target)).removeClass("droptarget");this.env.last_folder_target=null;d.draglayer.hide();this.drag_menu(a,b)||this.command("moveto", -b)}if(this.buttons_sel){for(var e in this.buttons_sel)typeof e!="function"&&this.button_out(this.buttons_sel[e],e);this.buttons_sel={}}};this.click_on_list=function(){this.gui_objects.qsearchbox&&this.gui_objects.qsearchbox.blur();if(this.message_list)this.message_list.focus();else this.contact_list&&this.contact_list.focus();return true};this.msglist_select=function(a){this.preview_timer&&clearTimeout(this.preview_timer);this.preview_read_timer&&clearTimeout(this.preview_read_timer);var b=a.get_single_selection()!= -null;this.enable_command(this.env.message_commands,b);if(b)if(this.env.mailbox==this.env.drafts_mailbox)this.enable_command("reply","reply-all","reply-list","forward",false);else this.env.messages[a.get_single_selection()].ml||this.enable_command("reply-list",false);this.enable_command("delete","moveto","copy","mark",a.selection.length>0?true:false);if(b||a.selection.length&&a.selection.length!=a.rowcount)this.select_all_mode=false;if(b&&this.env.contentframe&&!a.multi_selecting&&!this.dummy_select)this.preview_timer= -window.setTimeout(function(){l.msglist_get_preview()},200);else this.env.contentframe&&this.show_contentframe(false)};this.msglist_click=function(a){if(!(a.multi_selecting||!this.env.contentframe))if(a.get_single_selection()&&window.frames&&window.frames[this.env.contentframe])if(window.frames[this.env.contentframe].location.href.indexOf(this.env.blankpage)>=0){this.preview_timer&&clearTimeout(this.preview_timer);this.preview_read_timer&&clearTimeout(this.preview_read_timer);this.preview_timer=window.setTimeout(function(){l.msglist_get_preview()}, -200)}};this.msglist_dbl_click=function(a){this.preview_timer&&clearTimeout(this.preview_timer);this.preview_read_timer&&clearTimeout(this.preview_read_timer);if((a=a.get_single_selection())&&this.env.mailbox==this.env.drafts_mailbox)this.goto_url("compose","_draft_uid="+a+"&_mbox="+urlencode(this.env.mailbox),true);else a&&this.show_message(a,false,false)};this.msglist_keypress=function(a){if(a.key_pressed==a.ENTER_KEY)this.command("show");else if(a.key_pressed==a.DELETE_KEY)this.command("delete"); -else if(a.key_pressed==a.BACKSPACE_KEY)this.command("delete");else if(a.key_pressed==33)this.command("previouspage");else if(a.key_pressed==34)this.command("nextpage");else a.shiftkey=false};this.msglist_get_preview=function(){var a=this.get_single_uid();if(a&&this.env.contentframe&&!this.drag_active)this.show_message(a,false,true);else this.env.contentframe&&this.show_contentframe(false)};this.msglist_expand=function(a){if(this.env.messages[a.uid])this.env.messages[a.uid].expanded=a.expanded};this.msglist_set_coltypes= -function(a){var b,d=a.list.tHead.rows[0].cells;this.env.coltypes=[];for(a=0;a=0)this.set_env("flagged_col",a);if((a=$.inArray("subject",this.env.coltypes))>=0)this.set_env("subject_col",a);this.http_post("save-pref",{_name:"list_cols",_value:this.env.coltypes,_session:"list_attrib/columns"})};this.check_droptarget=function(a){var b=false, -d=false;if(this.task=="mail")b=this.env.mailboxes[a]&&this.env.mailboxes[a].id!=this.env.mailbox&&!this.env.mailboxes[a].virtual;else if(this.task=="settings")b=a!=this.env.mailbox;else if(this.task=="addressbook")if(a!=this.env.source&&this.env.contactfolders[a])if(this.env.contactfolders[a].type=="group"){d=this.env.contactfolders[a].source;b=this.env.contactfolders[a].id!=this.env.group&&!this.env.contactfolders[d].readonly;d=d!=this.env.source}else{b=!this.env.contactfolders[a].readonly;d=true}return b? -d?2:1:0};this.init_message_row=function(a){var b,d=this,e=a.uid,f=(this.env.status_col!=null?"status":"msg")+"icn"+a.uid;e&&this.env.messages[e]&&$.extend(a,this.env.messages[e]);if(a.icon=document.getElementById(f)){a.icon._row=a.obj;a.icon.onmousedown=function(g){d.command("toggle_status",this);rcube_event.cancel(g)}}a.msgicon=this.env.status_col!=null?document.getElementById("msgicn"+a.uid):a.icon;if(this.env.flagged_col!=null&&(a.flagicon=document.getElementById("flagicn"+a.uid))){a.flagicon._row= -a.obj;a.flagicon.onmousedown=function(g){d.command("toggle_flag",this);rcube_event.cancel(g)}}if(!a.depth&&a.has_children&&(b=document.getElementById("rcmexpando"+a.uid))){a.expando=b;b.onmousedown=function(g){return d.expand_message_row(g,e)}}this.triggerEvent("insertrow",{uid:e,row:a})};this.add_message_row=function(a,b,d,e){if(!this.gui_objects.messagelist||!this.message_list)return false;this.env.messages[a]||(this.env.messages[a]={});$.extend(this.env.messages[a],{deleted:d.deleted?1:0,replied:d.replied? -1:0,unread:d.unread?1:0,forwarded:d.forwarded?1:0,flagged:d.flagged?1:0,has_children:d.has_children?1:0,depth:d.depth?d.depth:0,unread_children:d.unread_children?d.unread_children:0,parent_uid:d.parent_uid?d.parent_uid:0,selected:this.select_all_mode||this.message_list.in_selection(a),ml:d.ml?1:0,ctype:d.ctype,flags:d.extra_flags});var f,g=expando="",h=this.message_list,k=h.rows;f=this.env.messages[a];var j="message"+(this.gui_objects.messagelist.tBodies[0].rows.length%2?" even":" odd")+(d.unread? -" unread":"")+(d.deleted?" deleted":"")+(d.flagged?" flagged":"")+(d.unread_children&&!d.unread&&!this.env.autoexpand_threads?" unroot":"")+(f.selected?" selected":""),m=document.createElement("tr"),n=document.createElement("td");m.id="rcmrow"+a;m.className=j;j="msgicon";if(this.env.status_col===null){j+=" status";if(d.deleted)j+=" deleted";else if(d.unread)j+=" unread";else if(d.unread_children>0)j+=" unreadchildren"}if(d.replied)j+=" replied";if(d.forwarded)j+=" forwarded";f.selected&&!h.in_selection(a)&& -h.selection.push(a);if(this.env.threading){n=f.depth*15;if(f.depth)if(k[f.parent_uid]&&k[f.parent_uid].expanded===false||(this.env.autoexpand_threads==0||this.env.autoexpand_threads==2)&&(!k[f.parent_uid]||!k[f.parent_uid].expanded)){m.style.display="none";f.expanded=false}else f.expanded=true;else if(f.has_children)if(typeof f.expanded=="undefined"&&(this.env.autoexpand_threads==1||this.env.autoexpand_threads==2&&f.unread_children))f.expanded=true;if(n)g+='  ';if(f.has_children&&!f.depth)expando='
  
'}g+=' ';if(!bw.ie&&b.subject){n=d.mbox==this.env.drafts_mailbox?"_draft_uid":"_uid";b.subject='
'+b.subject+""}for(var o in this.env.coltypes){f=this.env.coltypes[o];n=document.createElement("td");n.className=String(f).toLowerCase();if(f=="flag"){j=d.flagged?"flagged":"unflagged";f=' '}else if(f=="attachment")f=/application\/|multipart\/m/.test(d.ctype)?' ':/multipart\/report/.test(d.ctype)?' ':" ";else if(f=="status"){j=d.deleted?"deleted":d.unread? -"unread":d.unread_children>0?"unreadchildren":"msgicon";f=' '}else f=f=="threads"?expando:f=="subject"?g+b[f]:b[f];n.innerHTML=f;m.appendChild(n)}h.insert_row(m,e);if(e&&this.env.pagesize&&h.rowcount>this.env.pagesize){a=h.get_last_row();h.remove_row(a);h.clear_selection(a)}};this.set_list_sorting=function(a,b){$("#rcm"+this.env.sort_col).removeClass("sorted"+this.env.sort_order.toUpperCase());a&&$("#rcm"+a).addClass("sorted"+b);this.env.sort_col= -a;this.env.sort_order=b};this.set_list_options=function(a,b,d,e){var f,g="";if(typeof b=="undefined")b=this.env.sort_col;if(!d)d=this.env.sort_order;if(this.env.sort_col!=b||this.env.sort_order!=d){f=1;this.set_list_sorting(b,d)}if(this.env.threading!=e){f=1;g+="&_threads="+e}if(a&&a.length){var h,k,j=[],m=this.env.coltypes;for(e=0;e=0)this.show_contentframe(true);else{if(!this.env.frame_lock)(this.is_framed()? -parent.rcmail:this).env.frame_lock=this.set_busy(true,"loading");e.location.href=this.env.comm_path+g;if(f=="preview"&&this.message_list&&this.message_list.rows[a]&&this.message_list.rows[a].unread&&this.env.preview_pane_mark_read>=0)this.preview_read_timer=window.setTimeout(function(){l.set_message(a,"unread",false);l.update_thread_root(a,"read");if(l.env.unread_counts[l.env.mailbox]){l.env.unread_counts[l.env.mailbox]-=1;l.set_unread_count(l.env.mailbox,l.env.unread_counts[l.env.mailbox],l.env.mailbox== -"INBOX")}l.env.preview_pane_mark_read>0&&l.http_post("mark","_uid="+a+"&_flag=read&_quiet=1")},this.env.preview_pane_mark_read*1E3)}}};this.show_contentframe=function(a){var b,d;if(this.env.contentframe&&(b=$("#"+this.env.contentframe))&&b.length)if(!a&&(d=window.frames[this.env.contentframe])){if(d.location&&d.location.href.indexOf(this.env.blankpage)<0)d.location.href=this.env.blankpage}else if(!bw.safari&&!bw.konq)b[a?"show":"hide"]();!a&&this.busy&&this.set_busy(false,null,this.env.frame_lock)}; -this.list_page=function(a){if(a=="next")a=this.env.current_page+1;else if(a=="last")a=this.env.pagecount;else if(a=="prev"&&this.env.current_page>1)a=this.env.current_page-1;else if(a=="first"&&this.env.current_page>1)a=1;if(a>0&&a<=this.env.pagecount){this.env.current_page=a;if(this.task=="mail")this.list_mailbox(this.env.mailbox,a);else this.task=="addressbook"&&this.list_contacts(this.env.source,this.env.group,a)}};this.filter_mailbox=function(a){var b,d=this.set_busy(true,"searching");if(this.gui_objects.qsearchbox)b= -this.gui_objects.qsearchbox.value;this.clear_message_list();this.env.current_page=1;this.http_request("search","_filter="+a+(b?"&_q="+urlencode(b):"")+(this.env.mailbox?"&_mbox="+urlencode(this.env.mailbox):""),d)};this.list_mailbox=function(a,b,d,e){var f="",g=window;a||(a=this.env.mailbox?this.env.mailbox:"INBOX");if(e)f+=e;if(d)f+="&_sort="+d;if(this.env.search_request)f+="&_search="+this.env.search_request;if(this.env.mailbox!=a){b=1;this.env.current_page=b;this.select_all_mode=false}this.clear_message_list(); -if(a!=this.env.mailbox||a==this.env.mailbox&&!b&&!d)f+="&_refresh=1";this.select_folder(a,this.env.mailbox);this.env.mailbox=a;if(this.gui_objects.messagelist)this.list_mailbox_remote(a,b,f);else{if(this.env.contentframe&&window.frames&&window.frames[this.env.contentframe]){g=window.frames[this.env.contentframe];f+="&_framed=1"}if(a){this.set_busy(true,"loading");g.location.href=this.env.comm_path+"&_mbox="+urlencode(a)+(b?"&_page="+b:"")+f}}};this.clear_message_list=function(){this.env.messages= -{};this.last_selected=0;this.show_contentframe(false);this.message_list&&this.message_list.clear(true)};this.list_mailbox_remote=function(a,b,d){this.message_list.clear();a="_mbox="+urlencode(a)+(b?"&_page="+b:"");b=this.set_busy(true,"loading");this.http_request("list",a+d,b)};this.update_selection=function(){var a=this.message_list.selection,b=this.message_list.rows,d,e=[];for(d in a)b[a[d]]&&e.push(a[d]);this.message_list.selection=e};this.expand_unread=function(){for(var a,b=this.gui_objects.messagelist.tBodies[0].firstChild;b;){if(b.nodeType== -1&&(a=this.message_list.rows[b.uid])&&a.unread_children){this.message_list.expand_all(a);this.set_unread_children(a.uid)}b=b.nextSibling}return false};this.expand_message_row=function(a,b){var d=this.message_list.rows[b];d.expanded=!d.expanded;this.set_unread_children(b);d.expanded=!d.expanded;this.message_list.expand_row(a,b)};this.expand_threads=function(){if(!(!this.env.threading||!this.env.autoexpand_threads||!this.message_list))switch(this.env.autoexpand_threads){case 2:this.expand_unread(); -break;case 1:this.message_list.expand_all()}};this.init_threads=function(a){for(var b=0,d=a.length;b=0;b--){e=g[b].length;if(e>d.depth){f=e-d.depth;g[b][f]&2||(g[b][f]=g[b][f]?g[b][f]+2:2)}else if(e==d.depth)g[b][0]&2||(g[b][0]+= -2);if(d.depth>e)break}g.push(Array(d.depth));g[g.length-1][0]=1;h.push(d.uid)}else{if(g.length){for(b in g)this.set_tree_icons(h[b],g[b]);g=[];h=[]}if(a&&k!=j[a].obj)break}k=k.nextSibling}if(g.length)for(b in g)this.set_tree_icons(h[b],g[b])};this.set_tree_icons=function(a,b){var d,e=[],f="",g=b.length;for(d=0;d2)e.push({"class":"l3",width:15});else if(b[d]>1)e.push({"class":"l2",width:15});else if(b[d]>0)e.push({"class":"l1",width:15});else if(e.length&&!e[e.length-1]["class"])e[e.length- -1].width+=15;else e.push({"class":null,width:15});for(d=e.length-1;d>=0;d--)f+=e[d]["class"]?'
':'
';f&&$("#rcmtab"+a).html(f)};this.update_thread_root=function(a,b){if(this.env.threading){var d=this.message_list.find_root(a);if(a!=d){var e=this.message_list.rows[d];if(b=="read"&&e.unread_children)e.unread_children--;else if(b=="unread"&&e.has_children)e.unread_children=e.unread_children?e.unread_children+1:1;else return;this.set_message_icon(d); -this.set_unread_children(d)}}};this.update_thread=function(a){if(!this.env.threading)return 0;var b,d=0,e=this.message_list.rows,f=e[a],g=e[a].depth,h=[];if(f.depth){if(f.unread){a=this.message_list.find_root(a);e[a].unread_children--;this.set_unread_children(a)}}else d--;a=f.parent_uid;for(f=f.obj.nextSibling;f;){if(f.nodeType==1&&(b=e[f.uid])){if(!b.depth||b.depth<=g)break;b.depth--;$("#rcmtab"+b.uid).width(b.depth*15).html("");if(b.depth){if(b.depth==g)b.parent_uid=a;b.unread&&h.length&&h[h.length- -1].unread_children++}else{d++;b.parent_uid=0;if(b.has_children){$("#rcmrow"+b.uid+" .leaf:first").attr("id","rcmexpando"+b.uid).attr("class",b.obj.style.display!="none"?"expanded":"collapsed").bind("mousedown",{uid:b.uid,p:this},function(k){return k.data.p.expand_message_row(k,k.data.uid)});b.unread_children=0;h.push(b)}b.obj.style.display=="none"&&$(b.obj).show()}}f=f.nextSibling}for(b=0;b0&&this.delete_excessive_thread_rows();d+="&_uid="+this.uids_to_list(e);b||(b=this.display_message(this.get_label(a=="moveto"?"movingmessage":"deletingmessage"),"loading"));this.http_post(a,"_mbox="+urlencode(this.env.mailbox)+d,b)};this.mark_message=function(a,b){var d=[],e=[], -f,g,h;h=this.message_list?this.message_list.get_selection():[];if(b)d[0]=b;else if(this.env.uid)d[0]=this.env.uid;else if(this.message_list){g=0;for(f=h.length;g0&&this.delete_excessive_thread_rows()}b="&_from="+(this.env.action?this.env.action:"");lock=this.display_message(this.get_label("markingmessage"),"loading");if(d.length)b+="&_ruid="+this.uids_to_list(d);if(this.env.skip_deleted)if(this.env.display_next&&this.env.next_uid)b+="&_next_uid="+this.env.next_uid;if(this.env.search_request)b+="&_search="+this.env.search_request;this.http_post("mark","_uid="+this.uids_to_list(a)+ -"&_flag=delete"+b,lock);return true};this.flag_deleted_as_read=function(a){for(var b=this.message_list?this.message_list.rows:[],d=String(a).split(","),e=0;e"+j)}else{j=this.env.signatures[f].text;j.match(/^--[ -]\r?\n/)||(j=d+"\n"+j);j="
"+j+"
"}g.innerHTML=j}}}else{if(b&&j&&this.env.signatures&&this.env.signatures[j]){j=this.env.signatures[j].is_html?this.env.signatures[j].plain_text:this.env.signatures[j].text;j=j.replace(/\r\n/g,"\n");j.match(/^--[ -]\n/)||(j=d+"\n"+j);e=this.env.sig_above?h.indexOf(j):h.lastIndexOf(j);if(e>=0)h=h.substring(0,e)+h.substring(e+j.length,h.length)}if(b&&this.env.signatures&&this.env.signatures[f]){j= -this.env.signatures[f].is_html?this.env.signatures[f].plain_text:this.env.signatures[f].text;j=j.replace(/\r\n/g,"\n");j.match(/^--[ -]\n/)||(j=d+"\n"+j);if(this.env.sig_above)if(e>=0){h=h.substring(0,e)+j+h.substring(e,h.length);d=e-1}else if(pos=this.get_caret_pos(g.get(0))){h=h.substring(0,pos)+"\n"+j+"\n\n"+h.substring(pos,h.length);d=pos}else{d=0;h="\n\n"+j+"\n\n"+h.replace(/^[\r\n]+/,"")}else{h=h.replace(/[\r\n]+$/,"");d=!this.env.top_posting&&h.length?h.length+1:0;h+="\n\n"+j}}else d=this.env.top_posting? -0:h.length;g.val(h);this.set_caret_pos(g.get(0),d)}this.env.identity=f;return true};this.upload_file=function(a){if(!a)return false;for(var b=false,d=0;d');else{var e=document.createElement("iframe");e.name=d; -e.style.border="none";e.style.width=0;e.style.height=0;e.style.visibility="hidden";document.body.appendChild(e)}$(d).bind("load",{ts:b},function(f){var g,h="";try{if(this.contentDocument)g=this.contentDocument;else if(this.contentWindow)g=this.contentWindow.document;h=g.childNodes[0].innerHTML}catch(k){}if(!h.match(/add2attachment/)&&(!bw.opera||rcmail.env.uploadframe&&rcmail.env.uploadframe==f.data.ts)){h.match(/display_message/)||rcmail.display_message(rcmail.get_label("fileuploaderror"),"error"); -rcmail.remove_from_attachment_list(f.data.ts)}if(bw.opera)rcmail.env.uploadframe=f.data.ts});a.target=d;a.action=this.env.comm_path+"&_action=upload&_uploadid="+b;a.setAttribute("enctype","multipart/form-data");a.submit();e=this.get_label("uploading");if(this.env.loadingicon)e=''+e;if(this.env.cancelicon)e=''+e;this.add2attachment_list(b,{name:"",html:e,complete:false})}this.gui_objects.attachmentform=a;return true};this.add2attachment_list=function(a,b,d){if(!this.gui_objects.attachmentlist)return false;var e=$("
  • ").attr("id",a).html(b.html),f;d&&(f=document.getElementById(d))?e.replaceAll(f):e.appendTo(this.gui_objects.attachmentlist);d&&this.env.attachments[d]&&delete this.env.attachments[d];this.env.attachments[a]=b;return true};this.remove_from_attachment_list=function(a){this.env.attachments[a]&& -delete this.env.attachments[a];if(!this.gui_objects.attachmentlist)return false;var b=this.gui_objects.attachmentlist.getElementsByTagName("li");for(i=0;i");this.ksearch_pane=$("
    ").attr("id","rcmKSearchpane").css({position:"absolute","z-index":3E4}).append(b).appendTo(document.body);this.ksearch_pane.__ul=b[0]}b=this.ksearch_pane.__ul;b.innerHTML="";for(i=0;i/g,">").replace(/##([^%]+)%%/g,"$1");d.onmouseover=function(){l.ksearch_select(this)};d.onmouseup=function(){l.ksearch_click(this)};d._rcm_id=i;b.appendChild(d)}$(b.firstChild).attr("id","rcmksearchSelected").addClass("selected");this.ksearch_selected=0;a=$(this.ksearch_input).offset();this.ksearch_pane.css({left:a.left+"px",top:a.top+this.ksearch_input.offsetHeight+"px"}).show()}else this.ksearch_hide()};this.ksearch_click=function(a){this.ksearch_input&&this.ksearch_input.focus(); -this.insert_recipient(a._rcm_id);this.ksearch_hide()};this.ksearch_blur=function(){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;this.ksearch_pane&&this.ksearch_pane.hide()};this.contactlist_keypress=function(a){a.key_pressed==a.DELETE_KEY&&this.command("delete")};this.contactlist_select=function(a){this.preview_timer&&clearTimeout(this.preview_timer);var b,d=this;if(b= -a.get_single_selection())this.preview_timer=window.setTimeout(function(){d.load_contact(b,"show")},200);else this.env.contentframe&&this.show_contentframe(false);this.enable_command("compose",a.selection.length>0);this.enable_command("edit",b&&this.env.address_sources&&!this.env.address_sources[this.env.source].readonly?true:false);this.enable_command("delete",a.selection.length&&this.env.address_sources&&!this.env.address_sources[this.env.source].readonly);return false};this.list_contacts=function(a, -b,d){var e="",f=window;if(!a)a=this.env.source;if(d&&this.current_page==d&&a==this.env.source&&b==this.env.group)return false;if(a!=this.env.source){d=this.env.current_page=1;this.reset_qsearch()}else if(b!=this.env.group)d=this.env.current_page=1;this.select_folder(b?"G"+a+b:a,this.env.group?"G"+this.env.source+this.env.group:this.env.source);this.env.source=a;this.env.group=b;if(this.gui_objects.contactslist)this.list_contacts_remote(a,b,d);else{if(this.env.contentframe&&window.frames&&window.frames[this.env.contentframe]){f= -window.frames[this.env.contentframe];e="&_framed=1"}if(b)e+="&_gid="+b;if(d)e+="&_page="+d;if(this.env.search_request)e+="&_search="+this.env.search_request;this.set_busy(true,"loading");f.location.href=this.env.comm_path+(a?"&_source="+urlencode(a):"")+e}};this.list_contacts_remote=function(a,b,d){this.contact_list.clear(true);this.show_contentframe(false);this.enable_command("delete","compose",false);d=(a?"_source="+urlencode(a):"")+(d?(a?"&":"")+"_page="+d:"");var e=this.set_busy(true,"loading"); -this.env.source=a;if(this.env.group=b)d+="&_gid="+b;if(this.env.search_request)d+="&_search="+this.env.search_request;this.http_request("list",d,e)};this.load_contact=function(a,b,d){var e="",f=window;if(this.env.contentframe&&window.frames&&window.frames[this.env.contentframe]){e="&_framed=1";f=window.frames[this.env.contentframe];this.show_contentframe(true)}else if(d)return false;if(b&&(a||b=="add")&&!this.drag_active){if(this.env.group)e+="&_gid="+urlencode(this.env.group);this.set_busy(true); -f.location.href=this.env.comm_path+"&_action="+b+"&_source="+urlencode(this.env.source)+"&_cid="+urlencode(a)+e}return true};this.copy_contact=function(a,b){a||(a=this.contact_list.get_selection().join(","));if(b.type=="group"&&b.source==this.env.source)this.http_post("group-addmembers","_cid="+urlencode(a)+"&_source="+urlencode(this.env.source)+"&_gid="+urlencode(b.id));else if(b.type=="group"&&!this.env.address_sources[b.source].readonly)this.http_post("copy","_cid="+urlencode(a)+"&_source="+urlencode(this.env.source)+ -"&_to="+urlencode(b.source)+"&_togid="+urlencode(b.id)+(this.env.group?"&_gid="+urlencode(this.env.group):""));else if(b.id!=this.env.source&&a&&this.env.address_sources[b.id]&&!this.env.address_sources[b.id].readonly)this.http_post("copy","_cid="+urlencode(a)+"&_source="+urlencode(this.env.source)+"&_to="+urlencode(b.id)+(this.env.group?"&_gid="+urlencode(this.env.group):""))};this.delete_contacts=function(){var a=this.contact_list.get_selection();if((a.length||this.env.cid)&&confirm(this.get_label("deletecontactconfirm"))){var b, -d=[],e="";if(this.env.cid)d.push(this.env.cid);else{for(var f=0;f0)};this.group_create=function(){if(this.gui_objects.folderlist&&this.env.address_sources[this.env.source].groups){if(!this.name_input){this.name_input=$("").attr("type", -"text");this.name_input.bind("keydown",function(a){return rcmail.add_input_keydown(a)});this.name_input_li=$("
  • ").addClass("contactgroup").append(this.name_input);this.name_input_li.insertAfter(this.get_folder_li(this.env.source))}this.name_input.select().focus()}};this.group_rename=function(){if(this.env.group&&this.gui_objects.folderlist){if(!this.name_input){this.enable_command("list","listgroup",false);this.name_input=$("").attr("type","text").val(this.env.contactgroups["G"+this.env.source+ -this.env.group].name);this.name_input.bind("keydown",function(d){return rcmail.add_input_keydown(d)});this.env.group_renaming=true;var a,b=this.get_folder_li(this.env.source+this.env.group,"rcmliG");if(b&&(a=b.firstChild))$(a).hide().before(this.name_input)}this.name_input.select().focus()}};this.group_delete=function(){this.env.group&&this.http_post("group-delete","_source="+urlencode(this.env.source)+"&_gid="+urlencode(this.env.group),true)};this.remove_group_item=function(a){var b,d="G"+a.source+ -a.id;if(b=this.get_folder_li(d)){this.triggerEvent("group_delete",{source:a.source,id:a.id,li:b});b.parentNode.removeChild(b);delete this.env.contactfolders[d];delete this.env.contactgroups[d]}this.list_contacts(a.source,0)};this.add_input_keydown=function(a){a=rcube_event.get_keycode(a);if(a==13){if(a=this.name_input.val()){var b=this.set_busy(true,"loading");this.env.group_renaming?this.http_post("group-rename","_source="+urlencode(this.env.source)+"&_gid="+urlencode(this.env.group)+"&_name="+urlencode(a), -b):this.http_post("group-create","_source="+urlencode(this.env.source)+"&_name="+urlencode(a),b)}return false}else a==27&&this.reset_add_input();return true};this.reset_add_input=function(){if(this.name_input){if(this.env.group_renaming){this.name_input.parent().children().last().show();this.env.group_renaming=false}this.name_input.remove();this.name_input_li&&this.name_input_li.remove();this.name_input=this.name_input_li=null}this.enable_command("list","listgroup",true)};this.insert_contact_group= -function(a){this.reset_add_input();a.type="group";var b="G"+a.source+a.id;this.env.contactfolders[b]=this.env.contactgroups[b]=a;var d=$("").attr("href","#").bind("click",function(){return rcmail.command("listgroup",a,this)}).html(a.name);b=$("
  • ").attr("id","rcmli"+b).addClass("contactgroup").append(d).insertAfter(this.get_folder_li(a.source));this.triggerEvent("group_insert",{id:a.id,source:a.source,name:a.name,li:b[0]})};this.update_contact_group=function(a){this.reset_add_input();var b="G"+ -a.source+a.id,d,e=this.get_folder_li(b);if(e&&(d=e.firstChild)&&d.tagName.toLowerCase()=="a")d.innerHTML=a.name;this.env.contactfolders[b].name=this.env.contactgroups[b].name=a.name;this.triggerEvent("group_update",{id:a.id,source:a.source,name:a.name,li:e[0]})};this.init_subscription_list=function(){var a=this;this.subscription_list=new rcube_list_widget(this.gui_objects.subscriptionlist,{multiselect:false,draggable:true,keyboard:false,toggleselect:true});this.subscription_list.addEventListener("select", -function(b){a.subscription_select(b)});this.subscription_list.addEventListener("dragstart",function(){a.drag_active=true});this.subscription_list.addEventListener("dragend",function(b){a.subscription_move_folder(b)});this.subscription_list.row_init=function(b){b.obj.onmouseover=function(){a.focus_subscription(b.id)};b.obj.onmouseout=function(){a.unfocus_subscription(b.id)}};this.subscription_list.init()};this.section_select=function(a){if(a=a.get_single_selection()){var b="",d=window;this.set_busy(true); -if(this.env.contentframe&&window.frames&&window.frames[this.env.contentframe]){b="&_framed=1";d=window.frames[this.env.contentframe]}d.location.href=this.env.comm_path+"&_action=edit-prefs&_section="+a+b}return true};this.identity_select=function(a){if(a=a.get_single_selection())this.load_identity(a,"edit-identity")};this.load_identity=function(a,b){if(b=="edit-identity"&&(!a||a==this.env.iid))return false;var d="",e=window;if(this.env.contentframe&&window.frames&&window.frames[this.env.contentframe]){d= -"&_framed=1";e=window.frames[this.env.contentframe];document.getElementById(this.env.contentframe).style.visibility="inherit"}if(b&&(a||b=="add-identity")){this.set_busy(true);e.location.href=this.env.comm_path+"&_action="+b+"&_iid="+a+d}return true};this.delete_identity=function(a){var b=this.identity_list.get_selection();if(b.length||this.env.iid){a||(a=this.env.iid?this.env.iid:b[0]);this.goto_url("delete-identity","_iid="+a+"&_token="+this.env.request_token,true);return true}};this.focus_subscription= -function(a){var b,d,e=RegExp.escape(this.env.delimiter),f=RegExp("["+e+"]?[^"+e+"]+$");if(this.drag_active&&this.env.mailbox&&(b=document.getElementById(a)))if(this.env.subscriptionrows[a]&&(d=this.env.subscriptionrows[a][0])){if(this.check_droptarget(d)&&!this.env.subscriptionrows[this.get_folder_row_id(this.env.mailbox)][2]&&d!=this.env.mailbox.replace(f,"")&&!d.match(RegExp("^"+RegExp.escape(this.env.mailbox+this.env.delimiter)))){this.set_env("dstfolder",d);$(b).addClass("droptarget")}}else if(this.env.mailbox.match(RegExp(e))){this.set_env("dstfolder", -this.env.delimiter);$(this.subscription_list.frame).addClass("droptarget")}};this.unfocus_subscription=function(a){var b=$("#"+a);this.set_env("dstfolder",null);this.env.subscriptionrows[a]&&b[0]?b.removeClass("droptarget"):$(this.subscription_list.frame).removeClass("droptarget")};this.subscription_select=function(a){var b,d;if(a&&(b=a.get_single_selection())&&(d=this.env.subscriptionrows["rcmrow"+b])){this.set_env("mailbox",d[0]);this.show_folder(d[0]);this.enable_command("delete-folder",!d[2])}else{this.env.mailbox= -null;this.show_contentframe(false);this.enable_command("delete-folder","purge",false)}};this.subscription_move_folder=function(){var a=RegExp.escape(this.env.delimiter),b;if(this.env.mailbox&&this.env.dstfolder&&this.env.dstfolder!=this.env.mailbox&&this.env.dstfolder!=this.env.mailbox.replace(RegExp("["+a+"]?[^"+a+"]+$"),"")){b=RegExp("[^"+a+"]*["+a+"]","g");a=this.set_busy(true,"foldermoving");b=this.env.mailbox.replace(b,"");b=this.env.dstfolder==this.env.delimiter?b:this.env.dstfolder+this.env.delimiter+ -b;this.http_post("rename-folder","_folder_oldname="+urlencode(this.env.mailbox)+"&_folder_newname="+urlencode(b),a)}this.drag_active=false;this.unfocus_subscription(this.get_folder_row_id(this.env.dstfolder))};this.create_folder=function(){this.show_folder("",this.env.mailbox)};this.delete_folder=function(a){if((a=this.env.subscriptionrows[this.get_folder_row_id(a?a:this.env.mailbox)][0])&&confirm(this.get_label("deletefolderconfirm"))){var b=this.set_busy(true,"folderdeleting");this.http_post("delete-folder", -"_mbox="+urlencode(a),b)}};this.add_folder_row=function(a,b,d,e){if(!this.gui_objects.subscriptionlist)return false;var f,g;for(g in this.env.subscriptionrows)if(this.env.subscriptionrows[g]!=null&&!this.env.subscriptionrows[g][2]){f=g;break}var h;g=this.gui_objects.subscriptionlist.tBodies[0];var k="rcmrow"+(g.childNodes.length+1),j=this.subscription_list.get_single_selection();if(d&&d.id)f=k=d.id;if(!k||!f||!(h=document.getElementById(f))){this.goto_url("folders");return false}f=this.clone_table_row(h); -f.id=k;e&&(e=this.get_folder_row_id(e))?g.insertBefore(f,document.getElementById(e)):g.appendChild(f);d&&g.removeChild(d);this.env.subscriptionrows[f.id]=[a,b,0];f.cells[0].innerHTML=b;if(!d){f.cells[1].innerHTML="*";$('input[name="_subscribed[]"]',f).val(a).attr("checked",true)}this.init_subscription_list();j&&document.getElementById("rcmrow"+j)&&this.subscription_list.select_row(j);document.getElementById(k).scrollIntoView&&document.getElementById(k).scrollIntoView()};this.replace_folder_row=function(a, -b,d,e){a=this.get_folder_row_id(a);a=document.getElementById(a);this.add_folder_row(b,d,a,e)};this.remove_folder_row=function(a){var b;if((a=this.get_folder_row_id(a))&&(b=document.getElementById(a)))b.style.display="none"};this.subscribe=function(a){if(a){var b=this.display_message(this.get_label("foldersubscribing"),"loading");this.http_post("subscribe","_mbox="+urlencode(a),b)}};this.unsubscribe=function(a){if(a){var b=this.display_message(this.get_label("folderunsubscribing"),"loading");this.http_post("unsubscribe", -"_mbox="+urlencode(a),b)}};this.get_folder_row_id=function(a){for(var b in this.env.subscriptionrows)if(this.env.subscriptionrows[b]&&this.env.subscriptionrows[b][0]==a)break;return b};this.clone_table_row=function(a){for(var b,d,e=document.createElement("tr"),f=0;f=0&&!d)this.show_contentframe(true);else{if(!this.env.frame_lock)(parent.rcmail?parent.rcmail:this).env.frame_lock=this.set_busy(true,"loading");e.location.href=this.env.comm_path+a}};this.disable_subscription=function(a){(a=this.get_folder_row_id(a))&& -$('input[name="_subscribed[]"]',$("#"+a)).attr("disabled",true)};this.folder_size=function(a){var b=this.set_busy(true,"loading");this.http_post("folder-size","_mbox="+urlencode(a),b)};this.folder_size_update=function(a){$("#folder-size").replaceWith(a)};this.set_page_buttons=function(){this.enable_command("nextpage","lastpage",this.env.pagecount>this.env.current_page);this.enable_command("previouspage","firstpage",this.env.current_page>1)};this.init_buttons=function(){for(var a in this.buttons)if(typeof a== -"string")for(var b=0;b").addClass(b).html(a).data("key",e);$(this.gui_objects.message).append(h).show();this.messages[e]={obj:h,elements:[f]}; -if(b=="loading")this.messages[e].labels=[{id:f,msg:a}];else h.click(function(){return d.hide_message(h)});window.setTimeout(function(){d.hide_message(f,b=="loading")},g);return f};this.hide_message=function(a,b){if(this.is_framed())return parent.rcmail.hide_message(a,b);var d,e,f,g,h=this.messages;if(typeof a=="object"){$(a)[b?"fadeOut":"hide"]();g=$(a).data("key");this.messages[g]&&delete this.messages[g]}else for(d in h)for(e in h[d].elements)if(h[d]&&h[d].elements[e]==a){h[d].elements.splice(e, -1);if(h[d].elements.length){if(d=="loading")for(f in h[d].labels){if(h[d].labels[f].id==a)delete h[d].labels[f];else g=h[d].labels[f].msg;h[d].obj.html(g)}}else{h[d].obj[b?"fadeOut":"hide"]();delete h[d]}}};this.select_folder=function(a,b,d){if(this.gui_objects.folderlist){var e;if(e=this.get_folder_li(b,d))$(e).removeClass("selected").removeClass("unfocused");if(e=this.get_folder_li(a,d))$(e).removeClass("unfocused").addClass("selected");this.triggerEvent("selectfolder",{folder:a,old:b,prefix:d})}}; -this.get_folder_li=function(a,b){b||(b="rcmli");if(this.gui_objects.folderlist){a=String(a).replace(this.identifier_expr,"_");return document.getElementById(b+a)}return null};this.set_message_coltypes=function(a,b){this.env.coltypes=a;var d=this.gui_objects.messagelist?this.gui_objects.messagelist.tHead:null,e,f,g,h;if(d){if(b){f=document.createElement("thead");g=document.createElement("tr");c=0;for(h=b.length;c= -0){this.set_env("subject_col",g);if(this.message_list)this.message_list.subject_col=g}if((g=$.inArray("flag",this.env.coltypes))>=0)this.set_env("flagged_col",g);if((g=$.inArray("status",this.env.coltypes))>=0)this.set_env("status_col",g);this.message_list.init_header()};this.set_rowcount=function(a){$(this.gui_objects.countdisplay).html(a);this.set_page_buttons()};this.set_mailboxname=function(a){if(this.gui_objects.mailboxname&&a)this.gui_objects.mailboxname.innerHTML=a};this.set_quota=function(a){if(a&& -this.gui_objects.quotadisplay)typeof a=="object"&&a.type=="image"?this.percent_indicator(this.gui_objects.quotadisplay,a):$(this.gui_objects.quotadisplay).html(a)};this.set_unread_count=function(a,b,d){if(!this.gui_objects.mailboxlist)return false;this.env.unread_counts[a]=b;this.set_unread_count_display(a,d)};this.set_unread_count_display=function(a,b){var d,e,f,g,h,k;if(f=this.get_folder_li(a)){g=this.env.unread_counts[a]?this.env.unread_counts[a]:0;e=f.getElementsByTagName("a")[0];d=/\s+\([0-9]+\)$/i; -h=0;if((k=f.getElementsByTagName("div")[0])&&k.className.match(/collapsed/))for(var j in this.env.unread_counts)if(j.indexOf(a+this.env.delimiter)==0)h+=this.env.unread_counts[j];if(g&&e.innerHTML.match(d))e.innerHTML=e.innerHTML.replace(d," ("+g+")");else if(g)e.innerHTML+=" ("+g+")";else e.innerHTML=e.innerHTML.replace(d,"");d=RegExp(RegExp.escape(this.env.delimiter)+"[^"+RegExp.escape(this.env.delimiter)+"]+$");a.match(d)&&this.set_unread_count_display(a.replace(d,""),false);g+h>0?$(f).addClass("unread"): -$(f).removeClass("unread")}d=/^\([0-9]+\)\s+/i;if(b&&document.title){e="";e=String(document.title);e=g&&e.match(d)?e.replace(d,"("+g+") "):g?"("+g+") "+e:e.replace(d,"");this.set_pagetitle(e)}};this.new_message_focus=function(){this.env.framed&&window.parent?window.parent.focus():window.focus()};this.toggle_prefer_html=function(a){var b;if(b=document.getElementById("rcmfd_addrbook_show_images"))b.disabled=!a.checked};this.toggle_preview_pane=function(a){var b;if(b=document.getElementById("rcmfd_preview_pane_mark_read"))b.disabled= -!a.checked};this.set_headers=function(a){this.gui_objects.all_headers_row&&this.gui_objects.all_headers_box&&a&&$(this.gui_objects.all_headers_box).html(a).show()};this.load_headers=function(a){if(!(!this.gui_objects.all_headers_row||!this.gui_objects.all_headers_box||!this.env.uid)){$(a).removeClass("show-headers").addClass("hide-headers");$(this.gui_objects.all_headers_row).show();a.onclick=function(){rcmail.hide_headers(a)};this.gui_objects.all_headers_box.innerHTML||this.http_post("headers","_uid="+ -this.env.uid,this.display_message(this.get_label("loading"),"loading"))}};this.hide_headers=function(a){if(this.gui_objects.all_headers_row&&this.gui_objects.all_headers_box){$(a).removeClass("hide-headers").addClass("show-headers");$(this.gui_objects.all_headers_row).hide();a.onclick=function(){rcmail.load_headers(a)}}};this.percent_indicator=function(a,b){if(!b||!a)return false;var d=b.width?b.width:this.env.indicator_width?this.env.indicator_width:100,e=b.height?b.height:this.env.indicator_height? -this.env.indicator_height:14,f=b.percent?Math.abs(parseInt(b.percent)):0,g=parseInt(f/100*d),h=$(a).position();h.top=Math.max(0,h.top);this.env.indicator_width=d;this.env.indicator_height=e;if(g>d){g=d;f=100}if(b.title)b.title=this.get_label("quota")+": "+b.title;var k=$("
    ");k.css({position:"absolute",top:h.top,left:h.left,width:d+"px",height:e+"px",zIndex:100,lineHeight:e+"px"}).attr("title",b.title).addClass("quota_text").html(f+"%");var j=$("
    ");j.css({position:"absolute",top:h.top+1, -left:h.left+1,width:g+"px",height:e+"px",zIndex:99});g=$("
    ");g.css({position:"absolute",top:h.top+1,left:h.left+1,width:d+"px",height:e+"px",zIndex:98}).addClass("quota_bg");if(f>=80){k.addClass(" quota_text_high");j.addClass("quota_high")}else if(f>=55){k.addClass(" quota_text_mid");j.addClass("quota_mid")}else{k.addClass(" quota_text_normal");j.addClass("quota_low")}$(a).html("").append(j).append(g).append(k);$("#quotaimg").attr("title",b.title)};this.html2plain=function(a,b){var d=this,e= -this.set_busy(true,"converting");console.log("HTTP POST: ?_task=utils&_action=html2text");$.ajax({type:"POST",url:"?_task=utils&_action=html2text",data:a,contentType:"application/octet-stream",error:function(f,g,h){d.http_error(f,g,h,e)},success:function(f){d.set_busy(false,null,e);$(document.getElementById(b)).val(f);console.log(f)}})};this.plain2html=function(a,b){var d=this.set_busy(true,"converting");$(document.getElementById(b)).val("
    "+a+"
    ");this.set_busy(false,null,d)};this.redirect= -function(a,b){if(b||b===null)this.set_busy(true);if(this.env.framed&&window.parent)parent.location.href=a;else location.href=a};this.goto_url=function(a,b,d){var e=this.env.comm_path;b=b?"&"+b:"";if(a.match(/([a-z]+)\/([a-z-_]+)/)){a=RegExp.$2;e=e.replace(/\_task=[a-z]+/,"_task="+RegExp.$1)}this.redirect(e+"&_action="+a+b,d)};this.http_request=function(a,b,d){var e=this.env.comm_path;if(a.match(/([a-z]+)\/([a-z-_]+)/)){a=RegExp.$2;e=e.replace(/\_task=[a-z]+/,"_task="+RegExp.$1)}var f=this.triggerEvent("request"+ -a,b);if(typeof f!="undefined")if(f===false)return false;else b=f;e+="&_remote=1&_action="+a+(b?"&":"")+b;console.log("HTTP GET: "+e);$.ajax({type:"GET",url:e,data:{_unlock:d?d:0},dataType:"json",success:function(g){l.http_response(g)},error:function(g,h,k){rcmail.http_error(g,h,k,d)}})};this.http_post=function(a,b,d){var e=this.env.comm_path;if(a.match(/([a-z]+)\/([a-z-_]+)/)){a=RegExp.$2;e=e.replace(/\_task=[a-z]+/,"_task="+RegExp.$1)}e+="&_action="+a;if(b&&typeof b=="object"){b._remote=1;b._unlock= -d?d:0}else b+=(b?"&":"")+"_remote=1"+(d?"&_unlock="+d:"");a=this.triggerEvent("request"+a,b);if(typeof a!="undefined")if(a===false)return false;else b=a;console.log("HTTP POST: "+e);$.ajax({type:"POST",url:e,data:b,dataType:"json",success:function(f){l.http_response(f)},error:function(f,g,h){rcmail.http_error(f,g,h,d)}})};this.http_response=function(a){if(a){a.unlock&&this.set_busy(false);this.triggerEvent("responsebefore",{response:a});this.triggerEvent("responsebefore"+a.action,{response:a});a.env&& -this.set_env(a.env);if(typeof a.texts=="object")for(var b in a.texts)typeof a.texts[b]=="string"&&this.add_label(b,a.texts[b]);if(a.exec){console.log(a.exec);eval(a.exec)}if(a.callbacks&&a.callbacks.length)for(b=0;b0)}case "moveto":if(this.env.action=="show"){this.enable_command(this.env.message_commands,true);this.env.list_post||this.enable_command("reply-list",false)}else this.task=="addressbook"&&this.triggerEvent("listupdate",{folder:this.env.source,rowcount:this.contact_list.rowcount});case "purge":case "expunge":if(this.task=="mail"){if(!this.env.messagecount){this.env.contentframe&& -this.show_contentframe(false);this.enable_command(this.env.message_commands,"purge","expunge","select-all","select-none","sort","expand-all","expand-unread","collapse-all",false)}this.message_list&&this.triggerEvent("listupdate",{folder:this.env.mailbox,rowcount:this.message_list.rowcount})}break;case "check-recent":case "getunread":case "search":case "list":if(this.task=="mail"){this.enable_command("show","expunge","select-all","select-none","sort",this.env.messagecount>0);this.enable_command("purge", -this.purge_mailbox_test());this.enable_command("expand-all","expand-unread","collapse-all",this.env.threading&&this.env.messagecount);if(a.action=="list"||a.action=="search"){this.msglist_select(this.message_list);this.triggerEvent("listupdate",{folder:this.env.mailbox,rowcount:this.message_list.rowcount})}}else if(this.task=="addressbook"){this.enable_command("export",this.contact_list&&this.contact_list.rowcount>0);if(a.action=="list"||a.action=="search"){this.enable_command("group-create",this.env.address_sources[this.env.source].groups&& -!this.env.address_sources[this.env.source].readonly);this.enable_command("group-rename","group-delete",this.env.address_sources[this.env.source].groups&&this.env.group&&!this.env.address_sources[this.env.source].readonly);this.triggerEvent("listupdate",{folder:this.env.source,rowcount:this.contact_list.rowcount})}}}a.unlock&&this.hide_message(a.unlock);this.triggerEvent("responseafter",{response:a});this.triggerEvent("responseafter"+a.action,{response:a})}};this.http_error=function(a,b,d,e){b=a.statusText; -this.set_busy(false,null,e);a.abort();b&&this.display_message(this.get_label("servererror")+" ("+b+")","error")};this.start_keepalive=function(){this._int&&clearInterval(this._int);if(this.env.keep_alive&&!this.env.framed&&this.task=="mail"&&this.gui_objects.mailboxlist)this._int=setInterval(function(){l.check_for_recent(false)},this.env.keep_alive*1E3);else if(this.env.keep_alive&&!this.env.framed&&this.task!="login"&&this.env.action!="print")this._int=setInterval(function(){l.send_keep_alive()}, -this.env.keep_alive*1E3)};this.send_keep_alive=function(){this.http_request("keep-alive","_t="+(new Date).getTime())};this.check_for_recent=function(a){if(!this.busy){var b,d="_t="+(new Date).getTime()+"&_mbox="+urlencode(this.env.mailbox);if(a){b=this.set_busy(true,"checkingmail");d+="&_refresh=1";this.start_keepalive()}if(this.gui_objects.messagelist)d+="&_list=1";if(this.gui_objects.quotadisplay)d+="&_quota=1";if(this.env.search_request)d+="&_search="+this.env.search_request;this.http_request("check-recent", -d,b)}};this.get_single_uid=function(){return this.env.uid?this.env.uid:this.message_list?this.message_list.get_single_selection():null};this.get_single_cid=function(){return this.env.cid?this.env.cid:this.contact_list?this.contact_list.get_single_selection():null};this.get_caret_pos=function(a){if(typeof a.selectionEnd!="undefined")return a.selectionEnd;else if(document.selection&&document.selection.createRange){var b=document.selection.createRange();if(b.parentElement()!=a)return 0;var d=b.duplicate(); -a.tagName=="TEXTAREA"?d.moveToElementText(a):d.expand("textedit");d.setEndPoint("EndToStart",b);b=d.text.length;return b<=a.value.length?b:-1}else return a.value.length};this.set_caret_pos=function(a,b){if(a.setSelectionRange)a.setSelectionRange(b,b);else if(a.createTextRange){var d=a.createTextRange();d.collapse(true);d.moveEnd("character",b);d.moveStart("character",b);d.select()}};this.lock_form=function(a,b){if(a&&a.elements){var d,e,f;if(b)this.disabled_form_elements=[];d=0;for(e=a.elements.length;d< -e;d++){f=a.elements[d];if(f.type!="hidden")if(b&&f.disabled)this.disabled_form_elements.push(f);else if(b||$.inArray(f,this.disabled_form_elements)<0)f.disabled=b}}}}rcube_webmail.long_subject_title=function(l,a){if(!l.title){var b=$(l);if(b.width()+a*15>b.parent().width())l.title=b.html()}};rcube_webmail.prototype.addEventListener=rcube_event_engine.prototype.addEventListener;rcube_webmail.prototype.removeEventListener=rcube_event_engine.prototype.removeEventListener; -rcube_webmail.prototype.triggerEvent=rcube_event_engine.prototype.triggerEvent; +this.env.list_post);this.env.action=="show"&&this.http_request("pagenav","_uid="+this.env.uid+"&_mbox="+urlencode(this.env.mailbox),this.display_message("","loading"));if(this.env.blockedobjects){if(this.gui_objects.remoteobjectsmsg)this.gui_objects.remoteobjectsmsg.style.display="block";this.enable_command("load-images","always-load",!0)}this.env.action=="preview"&&this.is_framed()&&(this.enable_command("compose","add-contact",!1),parent.rcmail.show_contentframe(!0))}else if(this.env.action=="compose"){this.env.compose_commands= +["send-attachment","remove-attachment","send","toggle-editor"];this.env.drafts_mailbox&&this.env.compose_commands.push("savedraft");this.enable_command(this.env.compose_commands,"identities",!0);if(this.env.spellcheck)this.env.spellcheck.spelling_state_observer=function(a){j.set_spellcheck_state(a)},this.env.compose_commands.push("spellcheck"),this.set_spellcheck_state("ready"),$("input[name='_is_html']").val()=="1"&&this.display_spellcheck_controls(!1);document.onmouseup=function(b){return a.doc_mouse_up(b)}; +this.init_messageform()}else this.env.action=="print"&&this.env.uid&&window.print();if(this.gui_objects.mailboxlist)this.env.unread_counts={},this.gui_objects.folderlist=this.gui_objects.mailboxlist,this.http_request("getunread","");this.env.mdn_request&&this.env.uid&&(b="_uid="+this.env.uid+"&_mbox="+urlencode(this.env.mailbox),confirm(this.get_label("mdnrequest"))?this.http_post("sendmdn",b):this.http_post("mark",b+"&_flag=mdnsent"));break;case "addressbook":if(this.gui_objects.folderlist)this.env.contactfolders= +$.extend($.extend({},this.env.address_sources),this.env.contactgroups);if(this.gui_objects.contactslist)this.contact_list=new rcube_list_widget(this.gui_objects.contactslist,{multiselect:!0,draggable:this.gui_objects.folderlist?!0:!1,keyboard:!0}),this.contact_list.row_init=function(b){a.triggerEvent("insertrow",{cid:b.uid,row:b})},this.contact_list.addEventListener("keypress",function(b){a.contactlist_keypress(b)}),this.contact_list.addEventListener("select",function(b){a.contactlist_select(b)}), +this.contact_list.addEventListener("dragstart",function(b){a.drag_start(b)}),this.contact_list.addEventListener("dragmove",function(b){a.drag_move(b)}),this.contact_list.addEventListener("dragend",function(b){a.drag_end(b)}),this.contact_list.init(),this.env.cid&&this.contact_list.highlight_row(this.env.cid),this.gui_objects.contactslist.parentNode.onmousedown=function(b){return a.click_on_list(b)},document.onmouseup=function(b){return a.doc_mouse_up(b)},this.gui_objects.qsearchbox&&$(this.gui_objects.qsearchbox).focusin(function(){rcmail.contact_list.blur()}); +this.set_page_buttons();this.env.address_sources&&this.env.address_sources[this.env.source]&&!this.env.address_sources[this.env.source].readonly&&(this.enable_command("add","import",!0),this.enable_command("group-create",this.env.address_sources[this.env.source].groups));this.env.cid&&(this.enable_command("show","edit",!0),this.gui_objects.editform&&$("input.groupmember").change(function(){j.http_post(this.checked?"group-addmembers":"group-delmembers","_cid="+urlencode(j.env.cid)+"&_source="+urlencode(j.env.source)+ +"&_gid="+urlencode(this.value))}));(this.env.action=="add"||this.env.action=="edit")&&this.gui_objects.editform?(this.enable_command("save",!0),$("input[type='text']").first().select()):this.gui_objects.qsearchbox&&(this.enable_command("search","reset-search","moveto",!0),$(this.gui_objects.qsearchbox).select());this.contact_list&&this.contact_list.rowcount>0&&this.enable_command("export",!0);this.enable_command("list","listgroup",!0);break;case "settings":this.enable_command("preferences","identities", +"save","folders",!0);if(this.env.action=="identities")this.enable_command("add",this.env.identities_level<2);else if(this.env.action=="edit-identity"||this.env.action=="add-identity")this.enable_command("add",this.env.identities_level<2),this.enable_command("save","delete","edit","toggle-editor",!0);else if(this.env.action=="folders")this.enable_command("subscribe","unsubscribe","create-folder","rename-folder",!0);else if(this.env.action=="edit-folder"&&this.gui_objects.editform)this.enable_command("save", +"folder-size",!0),parent.rcmail.env.messagecount=this.env.messagecount,parent.rcmail.enable_command("purge",this.env.messagecount),$("input[type='text']").first().select();this.gui_objects.identitieslist?(this.identity_list=new rcube_list_widget(this.gui_objects.identitieslist,{multiselect:!1,draggable:!1,keyboard:!1}),this.identity_list.addEventListener("select",function(b){a.identity_select(b)}),this.identity_list.init(),this.identity_list.focus(),this.env.iid&&this.identity_list.highlight_row(this.env.iid)): +this.gui_objects.sectionslist?(this.sections_list=new rcube_list_widget(this.gui_objects.sectionslist,{multiselect:!1,draggable:!1,keyboard:!1}),this.sections_list.addEventListener("select",function(b){a.section_select(b)}),this.sections_list.init(),this.sections_list.focus()):this.gui_objects.subscriptionlist&&this.init_subscription_list();break;case "login":b=$("#rcmloginuser"),b.bind("keyup",function(a){return rcmail.login_user_keyup(a)}),b.val()==""?b.focus():$("#rcmloginpwd").focus(),$("#rcmlogintz").val((new Date).getTimezoneOffset()/ +-60),$("form").submit(function(){$("input[type=submit]",this).attr("disabled",!0);rcmail.display_message("","loading")}),this.enable_command("login",!0)}this.loaded=!0;this.pending_message&&this.display_message(this.pending_message[0],this.pending_message[1]);if(this.gui_objects.folderlist)this.gui_containers.foldertray=$(this.gui_objects.folderlist);this.triggerEvent("init",{task:this.task,action:this.env.action});for(var d in this.onloads)if(typeof this.onloads[d]=="string")eval(this.onloads[d]); +else if(typeof this.onloads[d]=="function")this.onloads[d]();this.start_keepalive()}};this.command=function(a,b,d){d&&d.blur&&d.blur();if(this.busy)return!1;if(!this.commands[a])return this.is_framed()&&parent.rcmail.command(a,b),!1;if(this.task=="mail"&&this.env.action=="compose"&&$.inArray(a,this.env.compose_commands)<0&&this.cmp_hash!=this.compose_field_hash()&&!confirm(this.get_label("notsentwarning")))return!1;if(typeof this.command_handlers[a]=="function")return a=this.command_handlers[a](b, +d),a!==null?a:d?!1:!0;else if(typeof this.command_handlers[a]=="string")return a=window[this.command_handlers[a]](b,d),a!==null?a:d?!1:!0;this.triggerEvent("actionbefore",{props:b,action:a});var e=this.triggerEvent("before"+a,b);if(typeof e!="undefined")if(e===!1)return!1;else b=e;switch(a){case "login":this.gui_objects.loginform&&this.gui_objects.loginform.submit();break;case "mail":case "addressbook":case "settings":case "logout":this.switch_task(a);break;case "permaurl":if(d&&d.href&&d.target)return!0; +else if(this.env.permaurl)parent.location.href=this.env.permaurl;break;case "menu-open":case "menu-save":return this.triggerEvent(a,{props:b}),!1;case "open":var f;if(f=this.get_single_uid())return d.href="?_task="+this.env.task+"&_action=show&_mbox="+urlencode(this.env.mailbox)+"&_uid="+f,!0;break;case "list":this.task=="mail"?((!this.env.search_request||b&&b!=this.env.mailbox)&&this.reset_qsearch(),this.list_mailbox(b),this.env.trash_mailbox&&this.set_alttext("delete",this.env.mailbox!=this.env.trash_mailbox? +"movemessagetotrash":"deletemessage")):this.task=="addressbook"&&((!this.env.search_request||b!=this.env.source)&&this.reset_qsearch(),this.list_contacts(b),this.enable_command("add","import",this.env.address_sources&&!this.env.address_sources[this.env.source].readonly));break;case "load-headers":this.load_headers(d);break;case "sort":var g=b;f=this.env.sort_col==g?this.env.sort_order=="ASC"?"DESC":"ASC":"ASC";this.set_list_sorting(g,f);this.list_mailbox("","",g+"_"+f);break;case "nextpage":this.list_page("next"); +break;case "lastpage":this.list_page("last");break;case "previouspage":this.list_page("prev");break;case "firstpage":this.list_page("first");break;case "expunge":this.env.messagecount&&this.expunge_mailbox(this.env.mailbox);break;case "purge":case "empty-mailbox":this.env.messagecount&&this.purge_mailbox(this.env.mailbox);break;case "show":if(this.task=="mail"){if((f=this.get_single_uid())&&(!this.env.uid||f!=this.env.uid))this.env.mailbox==this.env.drafts_mailbox?this.goto_url("compose","_draft_uid="+ +f+"&_mbox="+urlencode(this.env.mailbox),!0):this.show_message(f)}else this.task=="addressbook"&&(g=b?b:this.get_single_cid())&&!(this.env.action=="show"&&g==this.env.cid)&&this.load_contact(g,"show");break;case "add":this.task=="addressbook"?this.load_contact(0,"add"):this.task=="settings"&&(this.identity_list.clear_selection(),this.load_identity(0,"add-identity"));break;case "edit":if(this.task=="addressbook"&&(g=this.get_single_cid()))this.load_contact(g,"edit");else if(this.task=="settings"&&b)this.load_identity(b, +"edit-identity");else if(this.task=="mail"&&(g=this.get_single_uid()))e=this.env.mailbox==this.env.drafts_mailbox?"_draft_uid=":"_uid=",this.goto_url("compose",e+g+"&_mbox="+urlencode(this.env.mailbox),!0);break;case "save":if(this.gui_objects.editform){f=$("input[name='_pagesize']");g=$("input[name='_name']");e=$("input[name='_email']");if(f.length&&isNaN(parseInt(f.val()))){alert(this.get_label("nopagesizewarning"));f.focus();break}else if(g.length&&g.val()==""){alert(this.get_label("nonamewarning")); +g.focus();break}else if(e.length&&!rcube_check_email(e.val())){alert(this.get_label("noemailwarning"));e.focus();break}this.gui_objects.editform.submit()}break;case "delete":this.task=="mail"?this.delete_messages():this.task=="addressbook"?this.delete_contacts():this.task=="settings"&&this.delete_identity();break;case "move":case "moveto":this.task=="mail"?this.move_messages(b):this.task=="addressbook"&&this.drag_active&&this.copy_contact(null,b);break;case "copy":this.task=="mail"&&this.copy_messages(b); +break;case "mark":b&&this.mark_message(b);break;case "toggle_status":if(b&&!b._row)break;g="read";if(b._row.uid)f=b._row.uid,this.message_list.rows[f].deleted?g="undelete":this.message_list.rows[f].unread||(g="unread");this.mark_message(g,f);break;case "toggle_flag":if(b&&!b._row)break;g="flagged";if(b._row.uid)f=b._row.uid,this.message_list.rows[f].flagged&&(g="unflagged");this.mark_message(g,f);break;case "always-load":if(this.env.uid&&this.env.sender){this.add_contact(urlencode(this.env.sender)); +window.setTimeout(function(){j.command("load-images")},300);break}case "load-images":this.env.uid&&this.show_message(this.env.uid,!0,this.env.action=="preview");break;case "load-attachment":f="_mbox="+urlencode(this.env.mailbox)+"&_uid="+this.env.uid+"&_part="+b.part;if(this.env.uid&&b.mimetype&&$.inArray(b.mimetype,this.mimetypes)>=0&&(b.mimetype=="text/html"&&(f+="&_safe=1"),this.attachment_win=window.open(this.env.comm_path+"&_action=get&"+f+"&_frame=1","rcubemailattachment"))){window.setTimeout(function(){j.attachment_win.focus()}, +10);break}this.goto_url("get",f+"&_download=1",!1);break;case "select-all":this.select_all_mode=b?!1:!0;this.dummy_select=!0;b=="invert"?this.message_list.invert_selection():this.message_list.select_all(b=="page"?"":b);this.dummy_select=null;break;case "select-none":this.select_all_mode=!1;this.message_list.clear_selection();break;case "expand-all":this.env.autoexpand_threads=1;this.message_list.expand_all();break;case "expand-unread":this.env.autoexpand_threads=2;this.message_list.collapse_all(); +this.expand_unread();break;case "collapse-all":this.env.autoexpand_threads=0;this.message_list.collapse_all();break;case "nextmessage":this.env.next_uid&&this.show_message(this.env.next_uid,!1,this.env.action=="preview");break;case "lastmessage":this.env.last_uid&&this.show_message(this.env.last_uid);break;case "previousmessage":this.env.prev_uid&&this.show_message(this.env.prev_uid,!1,this.env.action=="preview");break;case "firstmessage":this.env.first_uid&&this.show_message(this.env.first_uid); +break;case "checkmail":this.check_for_recent(!0);break;case "compose":e=this.env.comm_path+"&_action=compose";if(this.task=="mail")if(e+="&_mbox="+urlencode(this.env.mailbox),this.env.mailbox==this.env.drafts_mailbox){if(f=this.get_single_uid())e+="&_draft_uid="+f}else b&&(e+="&_to="+urlencode(b));else if(this.task=="addressbook"){if(b&&b.indexOf("@")>0){e=this.get_task_url("mail",e);this.redirect(e+"&_to="+urlencode(b));break}f=[];if(b)f.push(b);else if(this.contact_list){g=this.contact_list.get_selection(); +for(e=0;e0&&(f=this.env.source?"_source="+urlencode(this.env.source)+"&":"",this.env.search_request&&(f+="_search="+this.env.search_request),this.goto_url("export",f));break;case "preferences":case "identities":case "folders":this.goto_url("settings/"+a);break;default:if(f=a.replace(/-/g,"_"),this[f]&&typeof this[f]=="function")this[f](b)}this.triggerEvent("after"+a,b);this.triggerEvent("actionafter", +{props:b,action:a});return d?!1:!0};this.enable_command=function(){for(var a=Array.prototype.slice.call(arguments),b=a.pop(),d,e=0;e=e.x2||a.y=e.y2){if(this.env.last_folder_target)$(this.get_folder_li(this.env.last_folder_target)).removeClass("droptarget"),this.env.folder_coords[this.env.last_folder_target].on=0,this.env.last_folder_target=null}else for(var g in this.env.folder_coords)if(e=this.env.folder_coords[g],a.x>=e.x1&&a.x=e.y1&&a.y1?"copy": +"normal")}else this.env.last_folder_target=null;else if(e.on)$(this.get_folder_li(g)).removeClass("droptarget"),this.env.folder_coords[g].on=0;d!=f&&this.contact_list&&this.contact_list.draglayer&&this.contact_list.draglayer.attr("class",d)}};this.collapse_folder=function(a){var b=this.get_folder_li(a),d=$(b.getElementsByTagName("div")[0]);if(d&&(d.hasClass("collapsed")||d.hasClass("expanded"))){var e=$(b.getElementsByTagName("ul")[0]);d.hasClass("collapsed")?(e.show(),d.removeClass("collapsed").addClass("expanded"), +this.set_env("collapsed_folders",this.env.collapsed_folders.replace(RegExp("&"+urlencode(a)+"&"),""))):(e.hide(),d.removeClass("expanded").addClass("collapsed"),this.set_env("collapsed_folders",this.env.collapsed_folders+"&"+urlencode(a)+"&"),this.env.mailbox.indexOf(a+this.env.delimiter)==0&&this.command("list",a));if(bw.ie6||bw.ie7)if((d=b.nextSibling?b.nextSibling.getElementsByTagName("ul"):null)&&d.length&&(b=d[0])&&b.style&&b.style.display!="none")b.style.display="none",b.style.display="";this.http_post("save-pref", +"_name=collapsed_folders&_value="+urlencode(this.env.collapsed_folders));this.set_unread_count_display(a,!1)}};this.doc_mouse_up=function(a){var b,d;this.message_list?(rcube_mouse_is_over(a,this.message_list.list.parentNode)?this.message_list.focus():this.message_list.blur(),d=this.message_list,b=this.env.mailboxes):this.contact_list?(rcube_mouse_is_over(a,this.contact_list.list.parentNode)?this.contact_list.focus():this.contact_list.blur(),d=this.contact_list,b=this.env.contactfolders):this.ksearch_value&& +this.ksearch_blur();if(this.drag_active&&b&&this.env.last_folder_target)b=b[this.env.last_folder_target],$(this.get_folder_li(this.env.last_folder_target)).removeClass("droptarget"),this.env.last_folder_target=null,d.draglayer.hide(),this.drag_menu(a,b)||this.command("moveto",b);if(this.buttons_sel){for(var e in this.buttons_sel)typeof e!="function"&&this.button_out(this.buttons_sel[e],e);this.buttons_sel={}}};this.click_on_list=function(){this.gui_objects.qsearchbox&&this.gui_objects.qsearchbox.blur(); +this.message_list?this.message_list.focus():this.contact_list&&this.contact_list.focus();return!0};this.msglist_select=function(a){this.preview_timer&&clearTimeout(this.preview_timer);this.preview_read_timer&&clearTimeout(this.preview_read_timer);var b=a.get_single_selection()!=null;this.enable_command(this.env.message_commands,b);b&&(this.env.mailbox==this.env.drafts_mailbox?this.enable_command("reply","reply-all","reply-list","forward",!1):this.env.messages[a.get_single_selection()].ml||this.enable_command("reply-list", +!1));this.enable_command("delete","moveto","copy","mark",a.selection.length>0?!0:!1);if(b||a.selection.length&&a.selection.length!=a.rowcount)this.select_all_mode=!1;b&&this.env.contentframe&&!a.multi_selecting&&!this.dummy_select?this.preview_timer=window.setTimeout(function(){j.msglist_get_preview()},200):this.env.contentframe&&this.show_contentframe(!1)};this.msglist_click=function(a){if(!a.multi_selecting&&this.env.contentframe&&a.get_single_selection()&&window.frames&&window.frames[this.env.contentframe]&& +window.frames[this.env.contentframe].location.href.indexOf(this.env.blankpage)>=0)this.preview_timer&&clearTimeout(this.preview_timer),this.preview_read_timer&&clearTimeout(this.preview_read_timer),this.preview_timer=window.setTimeout(function(){j.msglist_get_preview()},200)};this.msglist_dbl_click=function(a){this.preview_timer&&clearTimeout(this.preview_timer);this.preview_read_timer&&clearTimeout(this.preview_read_timer);(a=a.get_single_selection())&&this.env.mailbox==this.env.drafts_mailbox?this.goto_url("compose", +"_draft_uid="+a+"&_mbox="+urlencode(this.env.mailbox),!0):a&&this.show_message(a,!1,!1)};this.msglist_keypress=function(a){a.key_pressed==a.ENTER_KEY?this.command("show"):a.key_pressed==a.DELETE_KEY?this.command("delete"):a.key_pressed==a.BACKSPACE_KEY?this.command("delete"):a.key_pressed==33?this.command("previouspage"):a.key_pressed==34?this.command("nextpage"):a.shiftkey=!1};this.msglist_get_preview=function(){var a=this.get_single_uid();a&&this.env.contentframe&&!this.drag_active?this.show_message(a, +!1,!0):this.env.contentframe&&this.show_contentframe(!1)};this.msglist_expand=function(a){if(this.env.messages[a.uid])this.env.messages[a.uid].expanded=a.expanded};this.msglist_set_coltypes=function(a){var b,d,e=a.list.tHead.rows[0].cells;this.env.coltypes=[];for(a=0;a=0&&this.set_env("flagged_col",b);(b=$.inArray("subject",this.env.coltypes))>= +0&&this.set_env("subject_col",b);this.http_post("save-pref",{_name:"list_cols",_value:this.env.coltypes,_session:"list_attrib/columns"})};this.check_droptarget=function(a){var b=!1,d=!1;if(this.task=="mail")b=this.env.mailboxes[a]&&this.env.mailboxes[a].id!=this.env.mailbox&&!this.env.mailboxes[a].virtual;else if(this.task=="settings")b=a!=this.env.mailbox;else if(this.task=="addressbook"&&a!=this.env.source&&this.env.contactfolders[a])this.env.contactfolders[a].type=="group"?(d=this.env.contactfolders[a].source, +b=this.env.contactfolders[a].id!=this.env.group&&!this.env.contactfolders[d].readonly,d=d!=this.env.source):(b=!this.env.contactfolders[a].readonly,d=!0);return b?d?2:1:0};this.init_message_row=function(a){var b,d=this,e=a.uid,f=(this.env.status_col!=null?"status":"msg")+"icn"+a.uid;e&&this.env.messages[e]&&$.extend(a,this.env.messages[e]);if(a.icon=document.getElementById(f))a.icon._row=a.obj,a.icon.onmousedown=function(a){d.command("toggle_status",this);rcube_event.cancel(a)};a.msgicon=this.env.status_col!= +null?document.getElementById("msgicn"+a.uid):a.icon;if(this.env.flagged_col!=null&&(a.flagicon=document.getElementById("flagicn"+a.uid)))a.flagicon._row=a.obj,a.flagicon.onmousedown=function(a){d.command("toggle_flag",this);rcube_event.cancel(a)};if(!a.depth&&a.has_children&&(b=document.getElementById("rcmexpando"+a.uid)))a.expando=b,b.onmousedown=function(a){return d.expand_message_row(a,e)};this.triggerEvent("insertrow",{uid:e,row:a})};this.add_message_row=function(a,b,d,e){if(!this.gui_objects.messagelist|| +!this.message_list)return!1;this.env.messages[a]||(this.env.messages[a]={});$.extend(this.env.messages[a],{deleted:d.deleted?1:0,replied:d.replied?1:0,unread:d.unread?1:0,forwarded:d.forwarded?1:0,flagged:d.flagged?1:0,has_children:d.has_children?1:0,depth:d.depth?d.depth:0,unread_children:d.unread_children?d.unread_children:0,parent_uid:d.parent_uid?d.parent_uid:0,selected:this.select_all_mode||this.message_list.in_selection(a),ml:d.ml?1:0,ctype:d.ctype,flags:d.extra_flags});var f,g=expando="",h= +this.message_list,l=h.rows;f=this.env.messages[a];var k="message"+(this.gui_objects.messagelist.tBodies[0].rows.length%2?" even":" odd")+(d.unread?" unread":"")+(d.deleted?" deleted":"")+(d.flagged?" flagged":"")+(d.unread_children&&!d.unread&&!this.env.autoexpand_threads?" unroot":"")+(f.selected?" selected":""),j=document.createElement("tr"),m=document.createElement("td");j.id="rcmrow"+a;j.className=k;k="msgicon";this.env.status_col===null&&(k+=" status",d.deleted?k+=" deleted":d.unread?k+=" unread": +d.unread_children>0&&(k+=" unreadchildren"));d.replied&&(k+=" replied");d.forwarded&&(k+=" forwarded");f.selected&&!h.in_selection(a)&&h.selection.push(a);if(this.env.threading){m=f.depth*15;if(f.depth)l[f.parent_uid]&&l[f.parent_uid].expanded===!1||(this.env.autoexpand_threads==0||this.env.autoexpand_threads==2)&&(!l[f.parent_uid]||!l[f.parent_uid].expanded)?(j.style.display="none",f.expanded=!1):f.expanded=!0;else if(f.has_children&&typeof f.expanded=="undefined"&&(this.env.autoexpand_threads== +1||this.env.autoexpand_threads==2&&f.unread_children))f.expanded=!0;m&&(g+='  ');f.has_children&&!f.depth&&(expando='
      
    ')}g+=' ';if(!bw.ie&&b.subject)m=d.mbox==this.env.drafts_mailbox?"_draft_uid":"_uid",b.subject='
    '+b.subject+"";for(var o in this.env.coltypes)f=this.env.coltypes[o],m=document.createElement("td"),m.className=String(f).toLowerCase(),f=="flag"?(k=d.flagged?"flagged":"unflagged",f=' '):f=="attachment"?f=/application\/|multipart\/m/.test(d.ctype)?' ': +/multipart\/report/.test(d.ctype)?' ':" ":f=="status"?(k=d.deleted?"deleted":d.unread?"unread":d.unread_children>0?"unreadchildren":"msgicon",f=' '):f=f=="threads"?expando:f=="subject"?g+b[f]:b[f],m.innerHTML=f,j.appendChild(m);h.insert_row(j,e);e&&this.env.pagesize&&h.rowcount>this.env.pagesize&&(a=h.get_last_row(),h.remove_row(a),h.clear_selection(a))};this.set_list_sorting=function(a,b){$("#rcm"+this.env.sort_col).removeClass("sorted"+ +this.env.sort_order.toUpperCase());a&&$("#rcm"+a).addClass("sorted"+b);this.env.sort_col=a;this.env.sort_order=b};this.set_list_options=function(a,b,d,e){var f,g="";if(typeof b=="undefined")b=this.env.sort_col;if(!d)d=this.env.sort_order;if(this.env.sort_col!=b||this.env.sort_order!=d)f=1,this.set_list_sorting(b,d);this.env.threading!=e&&(f=1,g+="&_threads="+e);if(a&&a.length){for(var h,l,k=[],j=this.env.coltypes,e=0;e=0)this.show_contentframe(!0);else{if(!this.env.frame_lock)(this.is_framed()?parent.rcmail:this).env.frame_lock=this.set_busy(!0,"loading");e.location.href=this.env.comm_path+g;if(f=="preview"&&this.message_list&&this.message_list.rows[a]&&this.message_list.rows[a].unread&&this.env.preview_pane_mark_read>=0)this.preview_read_timer=window.setTimeout(function(){j.set_message(a,"unread",!1);j.update_thread_root(a,"read");j.env.unread_counts[j.env.mailbox]&&(j.env.unread_counts[j.env.mailbox]-= +1,j.set_unread_count(j.env.mailbox,j.env.unread_counts[j.env.mailbox],j.env.mailbox=="INBOX"));j.env.preview_pane_mark_read>0&&j.http_post("mark","_uid="+a+"&_flag=read&_quiet=1")},this.env.preview_pane_mark_read*1E3)}}};this.show_contentframe=function(a){var b,d;if(this.env.contentframe&&(b=$("#"+this.env.contentframe))&&b.length)if(!a&&(d=window.frames[this.env.contentframe])){if(d.location&&d.location.href.indexOf(this.env.blankpage)<0)d.location.href=this.env.blankpage}else if(!bw.safari&&!bw.konq)b[a? +"show":"hide"]();!a&&this.busy&&this.set_busy(!1,null,this.env.frame_lock)};this.list_page=function(a){a=="next"?a=this.env.current_page+1:a=="last"?a=this.env.pagecount:a=="prev"&&this.env.current_page>1?a=this.env.current_page-1:a=="first"&&this.env.current_page>1&&(a=1);if(a>0&&a<=this.env.pagecount)this.env.current_page=a,this.task=="mail"?this.list_mailbox(this.env.mailbox,a):this.task=="addressbook"&&this.list_contacts(this.env.source,this.env.group,a)};this.filter_mailbox=function(a){var b, +d=this.set_busy(!0,"searching");if(this.gui_objects.qsearchbox)b=this.gui_objects.qsearchbox.value;this.clear_message_list();this.env.current_page=1;this.http_request("search","_filter="+a+(b?"&_q="+urlencode(b):"")+(this.env.mailbox?"&_mbox="+urlencode(this.env.mailbox):""),d)};this.list_mailbox=function(a,b,d,e){var f="",g=window;a||(a=this.env.mailbox?this.env.mailbox:"INBOX");e&&(f+=e);d&&(f+="&_sort="+d);this.env.search_request&&(f+="&_search="+this.env.search_request);if(this.env.mailbox!=a)b= +1,this.env.current_page=b,this.select_all_mode=!1;this.clear_message_list();if(a!=this.env.mailbox||a==this.env.mailbox&&!b&&!d)f+="&_refresh=1";this.select_folder(a,this.env.mailbox);this.env.mailbox=a;if(this.gui_objects.messagelist)this.list_mailbox_remote(a,b,f);else if(this.env.contentframe&&window.frames&&window.frames[this.env.contentframe]&&(g=window.frames[this.env.contentframe],f+="&_framed=1"),a)this.set_busy(!0,"loading"),g.location.href=this.env.comm_path+"&_mbox="+urlencode(a)+(b?"&_page="+ +b:"")+f};this.clear_message_list=function(){this.env.messages={};this.last_selected=0;this.show_contentframe(!1);this.message_list&&this.message_list.clear(!0)};this.list_mailbox_remote=function(a,b,d){this.message_list.clear();a="_mbox="+urlencode(a)+(b?"&_page="+b:"");b=this.set_busy(!0,"loading");this.http_request("list",a+d,b)};this.update_selection=function(){var a=this.message_list.selection,b=this.message_list.rows,d,e=[];for(d in a)b[a[d]]&&e.push(a[d]);this.message_list.selection=e};this.expand_unread= +function(){for(var a,b=this.gui_objects.messagelist.tBodies[0].firstChild;b;){if(b.nodeType==1&&(a=this.message_list.rows[b.uid])&&a.unread_children)this.message_list.expand_all(a),this.set_unread_children(a.uid);b=b.nextSibling}return!1};this.expand_message_row=function(a,b){var d=this.message_list.rows[b];d.expanded=!d.expanded;this.set_unread_children(b);d.expanded=!d.expanded;this.message_list.expand_row(a,b)};this.expand_threads=function(){if(this.env.threading&&this.env.autoexpand_threads&& +this.message_list)switch(this.env.autoexpand_threads){case 2:this.expand_unread();break;case 1:this.message_list.expand_all()}};this.init_threads=function(a){for(var b=0,d=a.length;b=0;b--)if(e=g[b].length,e>d.depth?(f=e-d.depth, +g[b][f]&2||(g[b][f]=g[b][f]?g[b][f]+2:2)):e==d.depth&&(g[b][0]&2||(g[b][0]+=2)),d.depth>e)break;g.push(Array(d.depth));g[g.length-1][0]=1;h.push(d.uid)}else{if(g.length){for(b in g)this.set_tree_icons(h[b],g[b]);g=[];h=[]}if(a&&l!=k[a].obj)break}l=l.nextSibling}if(g.length)for(b in g)this.set_tree_icons(h[b],g[b])};this.set_tree_icons=function(a,b){var d,e=[],f="",g=b.length;for(d=0;d2?e.push({"class":"l3",width:15}):b[d]>1?e.push({"class":"l2",width:15}):b[d]>0?e.push({"class":"l1",width:15}): +e.length&&!e[e.length-1]["class"]?e[e.length-1].width+=15:e.push({"class":null,width:15});for(d=e.length-1;d>=0;d--)f+=e[d]["class"]?'
    ':'
    ';f&&$("#rcmtab"+a).html(f)};this.update_thread_root=function(a,b){if(this.env.threading){var d=this.message_list.find_root(a);if(a!=d){var e=this.message_list.rows[d];if(b=="read"&&e.unread_children)e.unread_children--;else if(b=="unread"&&e.has_children)e.unread_children=e.unread_children? +e.unread_children+1:1;else return;this.set_message_icon(d);this.set_unread_children(d)}}};this.update_thread=function(a){if(!this.env.threading)return 0;var b,d=0,e=this.message_list.rows,f=e[a],g=e[a].depth,h=[];f.depth?f.unread&&(a=this.message_list.find_root(a),e[a].unread_children--,this.set_unread_children(a)):d--;a=f.parent_uid;for(f=f.obj.nextSibling;f;){if(f.nodeType==1&&(b=e[f.uid])){if(!b.depth||b.depth<=g)break;b.depth--;$("#rcmtab"+b.uid).width(b.depth*15).html("");if(b.depth){if(b.depth== +g)b.parent_uid=a;b.unread&&h.length&&h[h.length-1].unread_children++}else{d++;b.parent_uid=0;if(b.has_children)$("#rcmrow"+b.uid+" .leaf:first").attr("id","rcmexpando"+b.uid).attr("class",b.obj.style.display!="none"?"expanded":"collapsed").bind("mousedown",{uid:b.uid,p:this},function(a){return a.data.p.expand_message_row(a,a.data.uid)}),b.unread_children=0,h.push(b);b.obj.style.display=="none"&&$(b.obj).show()}}f=f.nextSibling}for(b=0;b0&&this.delete_excessive_thread_rows();d+="&_uid="+this.uids_to_list(e);b||(b=this.display_message(this.get_label(a=="moveto"?"movingmessage":"deletingmessage"),"loading"));this.http_post(a,"_mbox="+urlencode(this.env.mailbox)+d,b)};this.mark_message=function(a,b){var d=[],e=[],f,g,h;h=this.message_list?this.message_list.get_selection():[];if(b)d[0]=b;else if(this.env.uid)d[0]= +this.env.uid;else if(this.message_list){g=0;for(f=h.length;g0&&this.delete_excessive_thread_rows());b="&_from="+(this.env.action? +this.env.action:"");lock=this.display_message(this.get_label("markingmessage"),"loading");d.length&&(b+="&_ruid="+this.uids_to_list(d));this.env.skip_deleted&&this.env.display_next&&this.env.next_uid&&(b+="&_next_uid="+this.env.next_uid);this.env.search_request&&(b+="&_search="+this.env.search_request);this.http_post("mark","_uid="+this.uids_to_list(a)+"&_flag=delete"+b,lock);return!0};this.flag_deleted_as_read=function(a){for(var b=this.message_list?this.message_list.rows:[],d=String(a).split(","), +e=0;e"+k)):(k=this.env.signatures[f].text,k.match(/^--[ -]\r?\n/)||(k=d+"\n"+k),k="
    "+k+"
    "),g.innerHTML=k}else b&&k&&this.env.signatures&&this.env.signatures[k]&&(k=this.env.signatures[k].is_html?this.env.signatures[k].plain_text:this.env.signatures[k].text,k= +k.replace(/\r\n/g,"\n"),k.match(/^--[ -]\n/)||(k=d+"\n"+k),e=this.env.sig_above?h.indexOf(k):h.lastIndexOf(k),e>=0&&(h=h.substring(0,e)+h.substring(e+k.length,h.length))),b&&this.env.signatures&&this.env.signatures[f]?(k=this.env.signatures[f].is_html?this.env.signatures[f].plain_text:this.env.signatures[f].text,k=k.replace(/\r\n/g,"\n"),k.match(/^--[ -]\n/)||(k=d+"\n"+k),this.env.sig_above?e>=0?(h=h.substring(0,e)+k+h.substring(e,h.length),d=e-1):(pos=this.get_caret_pos(g.get(0)))?(h=h.substring(0, +pos)+"\n"+k+"\n\n"+h.substring(pos,h.length),d=pos):(d=0,h="\n\n"+k+"\n\n"+h.replace(/^[\r\n]+/,"")):(h=h.replace(/[\r\n]+$/,""),d=!this.env.top_posting&&h.length?h.length+1:0,h+="\n\n"+k)):d=this.env.top_posting?0:h.length,g.val(h),this.set_caret_pos(g.get(0),d);this.env.identity=f;return!0};this.upload_file=function(a){if(!a)return!1;for(var b=!1,d=0;d');else{var e=document.createElement("iframe");e.name=d;e.style.border="none";e.style.width=0;e.style.height=0;e.style.visibility="hidden";document.body.appendChild(e)}$(d).bind("load",{ts:b},function(a){var b,d="";try{if(this.contentDocument)b=this.contentDocument;else if(this.contentWindow)b=this.contentWindow.document;d=b.childNodes[0].innerHTML}catch(e){}if(!d.match(/add2attachment/)&&(!bw.opera|| +rcmail.env.uploadframe&&rcmail.env.uploadframe==a.data.ts))d.match(/display_message/)||rcmail.display_message(rcmail.get_label("fileuploaderror"),"error"),rcmail.remove_from_attachment_list(a.data.ts);if(bw.opera)rcmail.env.uploadframe=a.data.ts});a.target=d;a.action=this.env.comm_path+"&_action=upload&_uploadid="+b;a.setAttribute("enctype","multipart/form-data");a.submit();e=this.get_label("uploading");this.env.loadingicon&&(e=''+e);this.env.cancelicon&& +(e=''+e);this.add2attachment_list(b,{name:"",html:e,complete:!1})}this.gui_objects.attachmentform=a;return!0};this.add2attachment_list=function(a,b,d){if(!this.gui_objects.attachmentlist)return!1;var e=$("
  • ").attr("id",a).html(b.html),f;d&&(f=document.getElementById(d))?e.replaceAll(f):e.appendTo(this.gui_objects.attachmentlist); +d&&this.env.attachments[d]&&delete this.env.attachments[d];this.env.attachments[a]=b;return!0};this.remove_from_attachment_list=function(a){this.env.attachments[a]&&delete this.env.attachments[a];if(!this.gui_objects.attachmentlist)return!1;var b=this.gui_objects.attachmentlist.getElementsByTagName("li");for(i=0;i"),this.ksearch_pane=$("
    ").attr("id","rcmKSearchpane").css({position:"absolute","z-index":3E4}).append(b).appendTo(document.body),this.ksearch_pane.__ul=b[0];b=this.ksearch_pane.__ul;b.innerHTML="";for(i= +0;i/g,">").replace(/##([^%]+)%%/g,"$1"),d.onmouseover=function(){j.ksearch_select(this)},d.onmouseup=function(){j.ksearch_click(this)},d._rcm_id=i,b.appendChild(d);$(b.firstChild).attr("id","rcmksearchSelected").addClass("selected");this.ksearch_selected=0;a=$(this.ksearch_input).offset();this.ksearch_pane.css({left:a.left+ +"px",top:a.top+this.ksearch_input.offsetHeight+"px"}).show()}else this.ksearch_hide()};this.ksearch_click=function(a){this.ksearch_input&&this.ksearch_input.focus();this.insert_recipient(a._rcm_id);this.ksearch_hide()};this.ksearch_blur=function(){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;this.ksearch_pane&&this.ksearch_pane.hide()};this.contactlist_keypress=function(a){a.key_pressed== +a.DELETE_KEY&&this.command("delete")};this.contactlist_select=function(a){this.preview_timer&&clearTimeout(this.preview_timer);var b,d=this;(b=a.get_single_selection())?this.preview_timer=window.setTimeout(function(){d.load_contact(b,"show")},200):this.env.contentframe&&this.show_contentframe(!1);this.enable_command("compose",a.selection.length>0);this.enable_command("edit",b&&this.env.address_sources&&!this.env.address_sources[this.env.source].readonly?!0:!1);this.enable_command("delete",a.selection.length&& +this.env.address_sources&&!this.env.address_sources[this.env.source].readonly);return!1};this.list_contacts=function(a,b,d){var e="",f=window;if(!a)a=this.env.source;if(d&&this.current_page==d&&a==this.env.source&&b==this.env.group)return!1;if(a!=this.env.source)d=this.env.current_page=1,this.reset_qsearch();else if(b!=this.env.group)d=this.env.current_page=1;this.select_folder(b?"G"+a+b:a,this.env.group?"G"+this.env.source+this.env.group:this.env.source);this.env.source=a;this.env.group=b;this.gui_objects.contactslist? +this.list_contacts_remote(a,b,d):(this.env.contentframe&&window.frames&&window.frames[this.env.contentframe]&&(f=window.frames[this.env.contentframe],e="&_framed=1"),b&&(e+="&_gid="+b),d&&(e+="&_page="+d),this.env.search_request&&(e+="&_search="+this.env.search_request),this.set_busy(!0,"loading"),f.location.href=this.env.comm_path+(a?"&_source="+urlencode(a):"")+e)};this.list_contacts_remote=function(a,b,d){this.contact_list.clear(!0);this.show_contentframe(!1);this.enable_command("delete","compose", +!1);var d=(a?"_source="+urlencode(a):"")+(d?(a?"&":"")+"_page="+d:""),e=this.set_busy(!0,"loading");this.env.source=a;(this.env.group=b)&&(d+="&_gid="+b);this.env.search_request&&(d+="&_search="+this.env.search_request);this.http_request("list",d,e)};this.load_contact=function(a,b,d){var e="",f=window;if(this.env.contentframe&&window.frames&&window.frames[this.env.contentframe])e="&_framed=1",f=window.frames[this.env.contentframe],this.show_contentframe(!0);else if(d)return!1;if(b&&(a||b=="add")&& +!this.drag_active)this.env.group&&(e+="&_gid="+urlencode(this.env.group)),this.set_busy(!0),f.location.href=this.env.comm_path+"&_action="+b+"&_source="+urlencode(this.env.source)+"&_cid="+urlencode(a)+e;return!0};this.copy_contact=function(a,b){a||(a=this.contact_list.get_selection().join(","));b.type=="group"&&b.source==this.env.source?this.http_post("group-addmembers","_cid="+urlencode(a)+"&_source="+urlencode(this.env.source)+"&_gid="+urlencode(b.id)):b.type=="group"&&!this.env.address_sources[b.source].readonly? +this.http_post("copy","_cid="+urlencode(a)+"&_source="+urlencode(this.env.source)+"&_to="+urlencode(b.source)+"&_togid="+urlencode(b.id)+(this.env.group?"&_gid="+urlencode(this.env.group):"")):b.id!=this.env.source&&a&&this.env.address_sources[b.id]&&!this.env.address_sources[b.id].readonly&&this.http_post("copy","_cid="+urlencode(a)+"&_source="+urlencode(this.env.source)+"&_to="+urlencode(b.id)+(this.env.group?"&_gid="+urlencode(this.env.group):""))};this.delete_contacts=function(){var a=this.contact_list.get_selection(); +if((a.length||this.env.cid)&&confirm(this.get_label("deletecontactconfirm"))){var b,d=[],e="";if(this.env.cid)d.push(this.env.cid);else{for(var f=0;f0)};this.group_create=function(){if(this.gui_objects.folderlist&&this.env.address_sources[this.env.source].groups){if(!this.name_input)this.name_input= +$("").attr("type","text"),this.name_input.bind("keydown",function(a){return rcmail.add_input_keydown(a)}),this.name_input_li=$("
  • ").addClass("contactgroup").append(this.name_input),this.name_input_li.insertAfter(this.get_folder_li(this.env.source));this.name_input.select().focus()}};this.group_rename=function(){if(this.env.group&&this.gui_objects.folderlist){if(!this.name_input){this.enable_command("list","listgroup",!1);this.name_input=$("").attr("type","text").val(this.env.contactgroups["G"+ +this.env.source+this.env.group].name);this.name_input.bind("keydown",function(a){return rcmail.add_input_keydown(a)});this.env.group_renaming=!0;var a,b=this.get_folder_li(this.env.source+this.env.group,"rcmliG");b&&(a=b.firstChild)&&$(a).hide().before(this.name_input)}this.name_input.select().focus()}};this.group_delete=function(){this.env.group&&this.http_post("group-delete","_source="+urlencode(this.env.source)+"&_gid="+urlencode(this.env.group),!0)};this.remove_group_item=function(a){var b,d= +"G"+a.source+a.id;if(b=this.get_folder_li(d))this.triggerEvent("group_delete",{source:a.source,id:a.id,li:b}),b.parentNode.removeChild(b),delete this.env.contactfolders[d],delete this.env.contactgroups[d];this.list_contacts(a.source,0)};this.add_input_keydown=function(a){a=rcube_event.get_keycode(a);if(a==13){if(a=this.name_input.val()){var b=this.set_busy(!0,"loading");this.env.group_renaming?this.http_post("group-rename","_source="+urlencode(this.env.source)+"&_gid="+urlencode(this.env.group)+"&_name="+ +urlencode(a),b):this.http_post("group-create","_source="+urlencode(this.env.source)+"&_name="+urlencode(a),b)}return!1}else a==27&&this.reset_add_input();return!0};this.reset_add_input=function(){if(this.name_input){if(this.env.group_renaming)this.name_input.parent().children().last().show(),this.env.group_renaming=!1;this.name_input.remove();this.name_input_li&&this.name_input_li.remove();this.name_input=this.name_input_li=null}this.enable_command("list","listgroup",!0)};this.insert_contact_group= +function(a){this.reset_add_input();a.type="group";var b="G"+a.source+a.id;this.env.contactfolders[b]=this.env.contactgroups[b]=a;var d=$("").attr("href","#").bind("click",function(){return rcmail.command("listgroup",a,this)}).html(a.name),b=$("
  • ").attr("id","rcmli"+b).addClass("contactgroup").append(d).insertAfter(this.get_folder_li(a.source));this.triggerEvent("group_insert",{id:a.id,source:a.source,name:a.name,li:b[0]})};this.update_contact_group=function(a){this.reset_add_input();var b="G"+ +a.source+a.id,d,e=this.get_folder_li(b);if(e&&(d=e.firstChild)&&d.tagName.toLowerCase()=="a")d.innerHTML=a.name;this.env.contactfolders[b].name=this.env.contactgroups[b].name=a.name;this.triggerEvent("group_update",{id:a.id,source:a.source,name:a.name,li:e[0]})};this.init_subscription_list=function(){var a=this;this.subscription_list=new rcube_list_widget(this.gui_objects.subscriptionlist,{multiselect:!1,draggable:!0,keyboard:!1,toggleselect:!0});this.subscription_list.addEventListener("select",function(b){a.subscription_select(b)}); +this.subscription_list.addEventListener("dragstart",function(){a.drag_active=!0});this.subscription_list.addEventListener("dragend",function(b){a.subscription_move_folder(b)});this.subscription_list.row_init=function(b){b.obj.onmouseover=function(){a.focus_subscription(b.id)};b.obj.onmouseout=function(){a.unfocus_subscription(b.id)}};this.subscription_list.init()};this.section_select=function(a){if(a=a.get_single_selection()){var b="",d=window;this.set_busy(!0);this.env.contentframe&&window.frames&& +window.frames[this.env.contentframe]&&(b="&_framed=1",d=window.frames[this.env.contentframe]);d.location.href=this.env.comm_path+"&_action=edit-prefs&_section="+a+b}return!0};this.identity_select=function(a){var b;(b=a.get_single_selection())&&this.load_identity(b,"edit-identity")};this.load_identity=function(a,b){if(b=="edit-identity"&&(!a||a==this.env.iid))return!1;var d="",e=window;if(this.env.contentframe&&window.frames&&window.frames[this.env.contentframe])d="&_framed=1",e=window.frames[this.env.contentframe], +document.getElementById(this.env.contentframe).style.visibility="inherit";if(b&&(a||b=="add-identity"))this.set_busy(!0),e.location.href=this.env.comm_path+"&_action="+b+"&_iid="+a+d;return!0};this.delete_identity=function(a){var b=this.identity_list.get_selection();if(b.length||this.env.iid)return a||(a=this.env.iid?this.env.iid:b[0]),this.goto_url("delete-identity","_iid="+a+"&_token="+this.env.request_token,!0),!0};this.focus_subscription=function(a){var b,d,e=RegExp.escape(this.env.delimiter), +f=RegExp("["+e+"]?[^"+e+"]+$");if(this.drag_active&&this.env.mailbox&&(b=document.getElementById(a)))this.env.subscriptionrows[a]&&(d=this.env.subscriptionrows[a][0])?this.check_droptarget(d)&&!this.env.subscriptionrows[this.get_folder_row_id(this.env.mailbox)][2]&&d!=this.env.mailbox.replace(f,"")&&!d.match(RegExp("^"+RegExp.escape(this.env.mailbox+this.env.delimiter)))&&(this.set_env("dstfolder",d),$(b).addClass("droptarget")):this.env.mailbox.match(RegExp(e))&&(this.set_env("dstfolder",this.env.delimiter), +$(this.subscription_list.frame).addClass("droptarget"))};this.unfocus_subscription=function(a){var b=$("#"+a);this.set_env("dstfolder",null);this.env.subscriptionrows[a]&&b[0]?b.removeClass("droptarget"):$(this.subscription_list.frame).removeClass("droptarget")};this.subscription_select=function(a){var b,d;a&&(b=a.get_single_selection())&&(d=this.env.subscriptionrows["rcmrow"+b])?(this.set_env("mailbox",d[0]),this.show_folder(d[0]),this.enable_command("delete-folder",!d[2])):(this.env.mailbox=null, +this.show_contentframe(!1),this.enable_command("delete-folder","purge",!1))};this.subscription_move_folder=function(){var a=RegExp.escape(this.env.delimiter),b;this.env.mailbox&&this.env.dstfolder&&this.env.dstfolder!=this.env.mailbox&&this.env.dstfolder!=this.env.mailbox.replace(RegExp("["+a+"]?[^"+a+"]+$"),"")&&(b=RegExp("[^"+a+"]*["+a+"]","g"),a=this.set_busy(!0,"foldermoving"),b=this.env.mailbox.replace(b,""),b=this.env.dstfolder==this.env.delimiter?b:this.env.dstfolder+this.env.delimiter+b,this.http_post("rename-folder", +"_folder_oldname="+urlencode(this.env.mailbox)+"&_folder_newname="+urlencode(b),a));this.drag_active=!1;this.unfocus_subscription(this.get_folder_row_id(this.env.dstfolder))};this.create_folder=function(){this.show_folder("",this.env.mailbox)};this.delete_folder=function(a){if((a=this.env.subscriptionrows[this.get_folder_row_id(a?a:this.env.mailbox)][0])&&confirm(this.get_label("deletefolderconfirm"))){var b=this.set_busy(!0,"folderdeleting");this.http_post("delete-folder","_mbox="+urlencode(a),b)}}; +this.add_folder_row=function(a,b,d,e){if(!this.gui_objects.subscriptionlist)return!1;var f,g;for(g in this.env.subscriptionrows)if(this.env.subscriptionrows[g]!=null&&!this.env.subscriptionrows[g][2]){f=g;break}var h;g=this.gui_objects.subscriptionlist.tBodies[0];var j="rcmrow"+(g.childNodes.length+1),k=this.subscription_list.get_single_selection();if(d&&d.id)f=j=d.id;if(!j||!f||!(h=document.getElementById(f)))return this.goto_url("folders"),!1;f=this.clone_table_row(h);f.id=j;e&&(e=this.get_folder_row_id(e))? +g.insertBefore(f,document.getElementById(e)):g.appendChild(f);d&&g.removeChild(d);this.env.subscriptionrows[f.id]=[a,b,0];f.cells[0].innerHTML=b;if(!d)f.cells[1].innerHTML="*",$('input[name="_subscribed[]"]',f).val(a).attr("checked",!0);this.init_subscription_list();k&&document.getElementById("rcmrow"+k)&&this.subscription_list.select_row(k);document.getElementById(j).scrollIntoView&&document.getElementById(j).scrollIntoView()};this.replace_folder_row=function(a,b,d,e){a=this.get_folder_row_id(a); +a=document.getElementById(a);this.add_folder_row(b,d,a,e)};this.remove_folder_row=function(a){var b;if((a=this.get_folder_row_id(a))&&(b=document.getElementById(a)))b.style.display="none"};this.subscribe=function(a){if(a){var b=this.display_message(this.get_label("foldersubscribing"),"loading");this.http_post("subscribe","_mbox="+urlencode(a),b)}};this.unsubscribe=function(a){if(a){var b=this.display_message(this.get_label("folderunsubscribing"),"loading");this.http_post("unsubscribe","_mbox="+urlencode(a), +b)}};this.get_folder_row_id=function(a){for(var b in this.env.subscriptionrows)if(this.env.subscriptionrows[b]&&this.env.subscriptionrows[b][0]==a)break;return b};this.clone_table_row=function(a){for(var b,d,e=document.createElement("tr"),f=0;f=0&&!d)this.show_contentframe(!0);else{if(!this.env.frame_lock)(parent.rcmail?parent.rcmail:this).env.frame_lock=this.set_busy(!0,"loading");e.location.href=this.env.comm_path+a}};this.disable_subscription=function(a){(a=this.get_folder_row_id(a))&&$('input[name="_subscribed[]"]',$("#"+ +a)).attr("disabled",!0)};this.folder_size=function(a){var b=this.set_busy(!0,"loading");this.http_post("folder-size","_mbox="+urlencode(a),b)};this.folder_size_update=function(a){$("#folder-size").replaceWith(a)};this.set_page_buttons=function(){this.enable_command("nextpage","lastpage",this.env.pagecount>this.env.current_page);this.enable_command("previouspage","firstpage",this.env.current_page>1)};this.init_buttons=function(){for(var a in this.buttons)if(typeof a=="string")for(var b=0;b").addClass(b).html(a).data("key",e);$(this.gui_objects.message).append(h).show();this.messages[e]={obj:h,elements:[f]};b=="loading"?this.messages[e].labels=[{id:f,msg:a}]:h.click(function(){return d.hide_message(h)}); +window.setTimeout(function(){d.hide_message(f,b=="loading")},g);return f};this.hide_message=function(a,b){if(this.is_framed())return parent.rcmail.hide_message(a,b);var d,e,f,g,h=this.messages;if(typeof a=="object")$(a)[b?"fadeOut":"hide"](),g=$(a).data("key"),this.messages[g]&&delete this.messages[g];else for(d in h)for(e in h[d].elements)if(h[d]&&h[d].elements[e]==a)if(h[d].elements.splice(e,1),h[d].elements.length){if(d=="loading")for(f in h[d].labels)h[d].labels[f].id==a?delete h[d].labels[f]: +g=h[d].labels[f].msg,h[d].obj.html(g)}else h[d].obj[b?"fadeOut":"hide"](),delete h[d]};this.select_folder=function(a,b,d){if(this.gui_objects.folderlist){var e,f;(e=this.get_folder_li(b,d))&&$(e).removeClass("selected").addClass("unfocused");(f=this.get_folder_li(a,d))&&$(f).removeClass("unfocused").addClass("selected");this.triggerEvent("selectfolder",{folder:a,old:b,prefix:d})}};this.get_folder_li=function(a,b){b||(b="rcmli");if(this.gui_objects.folderlist)return a=String(a).replace(this.identifier_expr, +"_"),document.getElementById(b+a);return null};this.set_message_coltypes=function(a,b){var d=this.message_list,e=d?d.list.tHead:null,f,g,h,j;this.env.coltypes=a;if(e){if(b){g=document.createElement("thead");h=document.createElement("tr");c=0;for(j=b.length;c=0)if(this.set_env("subject_col",h),d)d.subject_col=h;(h=$.inArray("flag",this.env.coltypes))>=0&&this.set_env("flagged_col", +h);(h=$.inArray("status",this.env.coltypes))>=0&&this.set_env("status_col",h);d&&d.init_header()};this.set_rowcount=function(a){$(this.gui_objects.countdisplay).html(a);this.set_page_buttons()};this.set_mailboxname=function(a){if(this.gui_objects.mailboxname&&a)this.gui_objects.mailboxname.innerHTML=a};this.set_quota=function(a){a&&this.gui_objects.quotadisplay&&(typeof a=="object"&&a.type=="image"?this.percent_indicator(this.gui_objects.quotadisplay,a):$(this.gui_objects.quotadisplay).html(a))}; +this.set_unread_count=function(a,b,d){if(!this.gui_objects.mailboxlist)return!1;this.env.unread_counts[a]=b;this.set_unread_count_display(a,d)};this.set_unread_count_display=function(a,b){var d,e,f,g,h,j;if(f=this.get_folder_li(a)){g=this.env.unread_counts[a]?this.env.unread_counts[a]:0;e=f.getElementsByTagName("a")[0];d=/\s+\([0-9]+\)$/i;h=0;if((j=f.getElementsByTagName("div")[0])&&j.className.match(/collapsed/))for(var k in this.env.unread_counts)k.indexOf(a+this.env.delimiter)==0&&(h+=this.env.unread_counts[k]); +g&&e.innerHTML.match(d)?e.innerHTML=e.innerHTML.replace(d," ("+g+")"):g?e.innerHTML+=" ("+g+")":e.innerHTML=e.innerHTML.replace(d,"");d=RegExp(RegExp.escape(this.env.delimiter)+"[^"+RegExp.escape(this.env.delimiter)+"]+$");a.match(d)&&this.set_unread_count_display(a.replace(d,""),!1);g+h>0?$(f).addClass("unread"):$(f).removeClass("unread")}d=/^\([0-9]+\)\s+/i;b&&document.title&&(e="",e=String(document.title),e=g&&e.match(d)?e.replace(d,"("+g+") "):g?"("+g+") "+e:e.replace(d,""),this.set_pagetitle(e))}; +this.new_message_focus=function(){this.env.framed&&window.parent?window.parent.focus():window.focus()};this.toggle_prefer_html=function(a){var b;if(b=document.getElementById("rcmfd_addrbook_show_images"))b.disabled=!a.checked};this.toggle_preview_pane=function(a){var b;if(b=document.getElementById("rcmfd_preview_pane_mark_read"))b.disabled=!a.checked};this.set_headers=function(a){this.gui_objects.all_headers_row&&this.gui_objects.all_headers_box&&a&&$(this.gui_objects.all_headers_box).html(a).show()}; +this.load_headers=function(a){if(this.gui_objects.all_headers_row&&this.gui_objects.all_headers_box&&this.env.uid)$(a).removeClass("show-headers").addClass("hide-headers"),$(this.gui_objects.all_headers_row).show(),a.onclick=function(){rcmail.hide_headers(a)},this.gui_objects.all_headers_box.innerHTML||this.http_post("headers","_uid="+this.env.uid,this.display_message(this.get_label("loading"),"loading"))};this.hide_headers=function(a){if(this.gui_objects.all_headers_row&&this.gui_objects.all_headers_box)$(a).removeClass("hide-headers").addClass("show-headers"), +$(this.gui_objects.all_headers_row).hide(),a.onclick=function(){rcmail.load_headers(a)}};this.percent_indicator=function(a,b){if(!b||!a)return!1;var d=b.width?b.width:this.env.indicator_width?this.env.indicator_width:100,e=b.height?b.height:this.env.indicator_height?this.env.indicator_height:14,f=b.percent?Math.abs(parseInt(b.percent)):0,g=parseInt(f/100*d),h=$(a).position();h.top=Math.max(0,h.top);this.env.indicator_width=d;this.env.indicator_height=e;g>d&&(g=d,f=100);if(b.title)b.title=this.get_label("quota")+ +": "+b.title;var j=$("
    ");j.css({position:"absolute",top:h.top,left:h.left,width:d+"px",height:e+"px",zIndex:100,lineHeight:e+"px"}).attr("title",b.title).addClass("quota_text").html(f+"%");var k=$("
    ");k.css({position:"absolute",top:h.top+1,left:h.left+1,width:g+"px",height:e+"px",zIndex:99});g=$("
    ");g.css({position:"absolute",top:h.top+1,left:h.left+1,width:d+"px",height:e+"px",zIndex:98}).addClass("quota_bg");f>=80?(j.addClass(" quota_text_high"),k.addClass("quota_high")):f>=55?(j.addClass(" quota_text_mid"), +k.addClass("quota_mid")):(j.addClass(" quota_text_normal"),k.addClass("quota_low"));$(a).html("").append(k).append(g).append(j);$("#quotaimg").attr("title",b.title)};this.html2plain=function(a,b){var d=this,e=this.set_busy(!0,"converting");console.log("HTTP POST: ?_task=utils&_action=html2text");$.ajax({type:"POST",url:"?_task=utils&_action=html2text",data:a,contentType:"application/octet-stream",error:function(a,b,h){d.http_error(a,b,h,e)},success:function(a){d.set_busy(!1,null,e);$(document.getElementById(b)).val(a); +console.log(a)}})};this.plain2html=function(a,b){var d=this.set_busy(!0,"converting");$(document.getElementById(b)).val("
    "+a+"
    ");this.set_busy(!1,null,d)};this.redirect=function(a,b){(b||b===null)&&this.set_busy(!0);this.env.framed&&window.parent?parent.location.href=a:location.href=a};this.goto_url=function(a,b,d){var e=this.env.comm_path,b=b?"&"+b:"";if(a.match(/([a-z]+)\/([a-z-_]+)/))a=RegExp.$2,e=e.replace(/\_task=[a-z]+/,"_task="+RegExp.$1);this.redirect(e+"&_action="+a+b,d)};this.http_request= +function(a,b,d){var e=this.env.comm_path;if(a.match(/([a-z]+)\/([a-z-_]+)/))a=RegExp.$2,e=e.replace(/\_task=[a-z]+/,"_task="+RegExp.$1);var f=this.triggerEvent("request"+a,b);if(typeof f!="undefined")if(f===!1)return!1;else b=f;e+="&_remote=1&_action="+a+(b?"&":"")+b;console.log("HTTP GET: "+e);$.ajax({type:"GET",url:e,data:{_unlock:d?d:0},dataType:"json",success:function(a){j.http_response(a)},error:function(a,b,e){rcmail.http_error(a,b,e,d)}})};this.http_post=function(a,b,d){var e=this.env.comm_path; +if(a.match(/([a-z]+)\/([a-z-_]+)/))a=RegExp.$2,e=e.replace(/\_task=[a-z]+/,"_task="+RegExp.$1);e+="&_action="+a;b&&typeof b=="object"?(b._remote=1,b._unlock=d?d:0):b+=(b?"&":"")+"_remote=1"+(d?"&_unlock="+d:"");a=this.triggerEvent("request"+a,b);if(typeof a!="undefined")if(a===!1)return!1;else b=a;console.log("HTTP POST: "+e);$.ajax({type:"POST",url:e,data:b,dataType:"json",success:function(a){j.http_response(a)},error:function(a,b,e){rcmail.http_error(a,b,e,d)}})};this.http_response=function(a){if(a){a.unlock&& +this.set_busy(!1);this.triggerEvent("responsebefore",{response:a});this.triggerEvent("responsebefore"+a.action,{response:a});a.env&&this.set_env(a.env);if(typeof a.texts=="object")for(var b in a.texts)typeof a.texts[b]=="string"&&this.add_label(b,a.texts[b]);a.exec&&(console.log(a.exec),eval(a.exec));if(a.callbacks&&a.callbacks.length)for(b=0;b0));case "moveto":this.env.action=="show"?(this.enable_command(this.env.message_commands,!0),this.env.list_post||this.enable_command("reply-list",!1)):this.task=="addressbook"&&this.triggerEvent("listupdate",{folder:this.env.source, +rowcount:this.contact_list.rowcount});case "purge":case "expunge":this.task=="mail"&&(this.env.messagecount||(this.env.contentframe&&this.show_contentframe(!1),this.enable_command(this.env.message_commands,"purge","expunge","select-all","select-none","sort","expand-all","expand-unread","collapse-all",!1)),this.message_list&&this.triggerEvent("listupdate",{folder:this.env.mailbox,rowcount:this.message_list.rowcount}));break;case "check-recent":case "getunread":case "search":case "list":if(this.task== +"mail"){if(this.enable_command("show","expunge","select-all","select-none","sort",this.env.messagecount>0),this.enable_command("purge",this.purge_mailbox_test()),this.enable_command("expand-all","expand-unread","collapse-all",this.env.threading&&this.env.messagecount),a.action=="list"||a.action=="search")this.msglist_select(this.message_list),this.triggerEvent("listupdate",{folder:this.env.mailbox,rowcount:this.message_list.rowcount})}else if(this.task=="addressbook"&&(this.enable_command("export", +this.contact_list&&this.contact_list.rowcount>0),a.action=="list"||a.action=="search"))this.enable_command("group-create",this.env.address_sources[this.env.source].groups&&!this.env.address_sources[this.env.source].readonly),this.enable_command("group-rename","group-delete",this.env.address_sources[this.env.source].groups&&this.env.group&&!this.env.address_sources[this.env.source].readonly),this.triggerEvent("listupdate",{folder:this.env.source,rowcount:this.contact_list.rowcount})}a.unlock&&this.hide_message(a.unlock); +this.triggerEvent("responseafter",{response:a});this.triggerEvent("responseafter"+a.action,{response:a})}};this.http_error=function(a,b,d,e){b=a.statusText;this.set_busy(!1,null,e);a.abort();b&&this.display_message(this.get_label("servererror")+" ("+b+")","error")};this.start_keepalive=function(){this._int&&clearInterval(this._int);if(this.env.keep_alive&&!this.env.framed&&this.task=="mail"&&this.gui_objects.mailboxlist)this._int=setInterval(function(){j.check_for_recent(!1)},this.env.keep_alive* +1E3);else if(this.env.keep_alive&&!this.env.framed&&this.task!="login"&&this.env.action!="print")this._int=setInterval(function(){j.send_keep_alive()},this.env.keep_alive*1E3)};this.send_keep_alive=function(){this.http_request("keep-alive","_t="+(new Date).getTime())};this.check_for_recent=function(a){if(!this.busy){var b,d="_t="+(new Date).getTime()+"&_mbox="+urlencode(this.env.mailbox);a&&(b=this.set_busy(!0,"checkingmail"),d+="&_refresh=1",this.start_keepalive());this.gui_objects.messagelist&& +(d+="&_list=1");this.gui_objects.quotadisplay&&(d+="&_quota=1");this.env.search_request&&(d+="&_search="+this.env.search_request);this.http_request("check-recent",d,b)}};this.get_single_uid=function(){return this.env.uid?this.env.uid:this.message_list?this.message_list.get_single_selection():null};this.get_single_cid=function(){return this.env.cid?this.env.cid:this.contact_list?this.contact_list.get_single_selection():null};this.get_caret_pos=function(a){if(typeof a.selectionEnd!="undefined")return a.selectionEnd; +else if(document.selection&&document.selection.createRange){var b=document.selection.createRange();if(b.parentElement()!=a)return 0;var d=b.duplicate();a.tagName=="TEXTAREA"?d.moveToElementText(a):d.expand("textedit");d.setEndPoint("EndToStart",b);b=d.text.length;return b<=a.value.length?b:-1}else return a.value.length};this.set_caret_pos=function(a,b){if(a.setSelectionRange)a.setSelectionRange(b,b);else if(a.createTextRange){var d=a.createTextRange();d.collapse(!0);d.moveEnd("character",b);d.moveStart("character", +b);d.select()}};this.lock_form=function(a,b){if(a&&a.elements){var d,e,f;if(b)this.disabled_form_elements=[];d=0;for(e=a.elements.length;db.parent().width())j.title=b.html()}};rcube_webmail.prototype.addEventListener=rcube_event_engine.prototype.addEventListener; +rcube_webmail.prototype.removeEventListener=rcube_event_engine.prototype.removeEventListener;rcube_webmail.prototype.triggerEvent=rcube_event_engine.prototype.triggerEvent; diff --git a/program/js/app.js.src b/program/js/app.js.src index 45dac5e..472dc6e 100644 --- a/program/js/app.js.src +++ b/program/js/app.js.src @@ -14,7 +14,7 @@ | Requires: jquery.js, common.js, list.js | +-----------------------------------------------------------------------+ - $Id: app.js 4469 2011-01-29 14:55:12Z thomasb $ + $Id: app.js 4666 2011-04-17 09:34:02Z alec $ */ @@ -2994,11 +2994,11 @@ function rcube_webmail() this.compose_field_hash = function(save) { // check input fields - var value_to = $("[name='_to']").val(); - var value_cc = $("[name='_cc']").val(); - var value_bcc = $("[name='_bcc']").val(); - var value_subject = $("[name='_subject']").val(); - var str = ''; + var ed, str = '', + value_to = $("[name='_to']").val(), + value_cc = $("[name='_cc']").val(), + value_bcc = $("[name='_bcc']").val(), + value_subject = $("[name='_subject']").val(); if (value_to) str += value_to+':'; @@ -3009,9 +3009,8 @@ function rcube_webmail() if (value_subject) str += value_subject+':'; - var editor = tinyMCE.get(this.env.composebody); - if (editor) - str += editor.getContent(); + if (window.tinyMCE && (ed = tinyMCE.get(this.env.composebody))) + str += ed.getContent(); else str += $("[name='_message']").val(); @@ -4622,7 +4621,7 @@ function rcube_webmail() var current_li, target_li; if ((current_li = this.get_folder_li(old, prefix))) { - $(current_li).removeClass('selected').removeClass('unfocused'); + $(current_li).removeClass('selected').addClass('unfocused'); } if ((target_li = this.get_folder_li(name, prefix))) { $(target_li).removeClass('unfocused').addClass('selected'); @@ -4651,17 +4650,18 @@ function rcube_webmail() // and for setting some message list global variables this.set_message_coltypes = function(coltypes, repl) { - this.env.coltypes = coltypes; + var list = this.message_list, + thead = list ? list.list.tHead : null, + cell, col, n, len, th, tr; - // set correct list titles - var thead = this.gui_objects.messagelist ? this.gui_objects.messagelist.tHead : null, - cell, col, n, len; + this.env.coltypes = coltypes; // replace old column headers if (thead) { if (repl) { - var th = document.createElement('thead'), - tr = document.createElement('tr'); + th = document.createElement('thead'); + tr = document.createElement('tr'); + for (c=0, len=repl.length; c < len; c++) { cell = document.createElement('td'); cell.innerHTML = repl[c].html; @@ -4695,15 +4695,16 @@ function rcube_webmail() if ((n = $.inArray('subject', this.env.coltypes)) >= 0) { this.set_env('subject_col', n); - if (this.message_list) - this.message_list.subject_col = n; + if (list) + list.subject_col = n; } if ((n = $.inArray('flag', this.env.coltypes)) >= 0) this.set_env('flagged_col', n); if ((n = $.inArray('status', this.env.coltypes)) >= 0) this.set_env('status_col', n); - this.message_list.init_header(); + if (list) + list.init_header(); }; // replace content of row count display diff --git a/program/js/common.js b/program/js/common.js index 7f068b4..6c3caa7 100644 --- a/program/js/common.js +++ b/program/js/common.js @@ -1,25 +1,25 @@ var CONTROL_KEY=1,SHIFT_KEY=2,CONTROL_SHIFT_KEY=3; function roundcube_browser(){var a=navigator;this.ver=parseFloat(a.appVersion);this.appver=a.appVersion;this.agent=a.userAgent;this.agent_lc=a.userAgent.toLowerCase();this.name=a.appName;this.vendor=a.vendor?a.vendor:"";this.vendver=a.vendorSub?parseFloat(a.vendorSub):0;this.product=a.product?a.product:"";this.platform=String(a.platform).toLowerCase();this.lang=a.language?a.language.substring(0,2):a.browserLanguage?a.browserLanguage.substring(0,2):a.systemLanguage?a.systemLanguage.substring(0,2): -"en";this.win=this.platform.indexOf("win")>=0;this.mac=this.platform.indexOf("mac")>=0;this.linux=this.platform.indexOf("linux")>=0;this.unix=this.platform.indexOf("unix")>=0;this.dom=document.getElementById?true:false;this.dom2=document.addEventListener&&document.removeEventListener;this.ie4=(this.ie=document.all&&!window.opera)&&!this.dom;this.ie5=this.dom&&this.appver.indexOf("MSIE 5")>0;this.ie8=this.dom&&this.appver.indexOf("MSIE 8")>0;this.ie7=this.dom&&this.appver.indexOf("MSIE 7")>0;this.ie6= -this.dom&&!this.ie8&&!this.ie7&&this.appver.indexOf("MSIE 6")>0;this.mz=this.dom&&this.ver>=5;this.ns6=(this.ns=this.ver<5&&this.name=="Netscape"||this.ver>=5&&this.vendor.indexOf("Netscape")>=0)&&parseInt(this.vendver)==6;this.ns7=this.ns&&parseInt(this.vendver)==7;this.chrome=this.agent_lc.indexOf("chrome")>0;this.safari=!this.chrome&&(this.agent_lc.indexOf("safari")>0||this.agent_lc.indexOf("applewebkit")>0);this.konq=this.agent_lc.indexOf("konqueror")>0;this.iphone=this.safari&&this.agent_lc.indexOf("iphone")> -0;this.ipad=this.safari&&this.agent_lc.indexOf("ipad")>0;if((this.opera=window.opera?true:false)&&window.RegExp)this.vendver=/opera(\s|\/)([0-9\.]+)/.test(this.agent_lc)?parseFloat(RegExp.$2):-1;else if(this.chrome&&window.RegExp)this.vendver=/chrome\/([0-9\.]+)/.test(this.agent_lc)?parseFloat(RegExp.$1):0;else if(!this.vendver&&this.safari)this.vendver=/(safari|applewebkit)\/([0-9]+)/.test(this.agent_lc)?parseInt(RegExp.$2):0;else if(!this.vendver&&this.mz||this.agent.indexOf("Camino")>0)this.vendver= +"en";this.win=this.platform.indexOf("win")>=0;this.mac=this.platform.indexOf("mac")>=0;this.linux=this.platform.indexOf("linux")>=0;this.unix=this.platform.indexOf("unix")>=0;this.dom=document.getElementById?!0:!1;this.dom2=document.addEventListener&&document.removeEventListener;this.ie4=(this.ie=document.all&&!window.opera)&&!this.dom;this.ie5=this.dom&&this.appver.indexOf("MSIE 5")>0;this.ie8=this.dom&&this.appver.indexOf("MSIE 8")>0;this.ie7=this.dom&&this.appver.indexOf("MSIE 7")>0;this.ie6=this.dom&& +!this.ie8&&!this.ie7&&this.appver.indexOf("MSIE 6")>0;this.mz=this.dom&&this.ver>=5;this.ns6=(this.ns=this.ver<5&&this.name=="Netscape"||this.ver>=5&&this.vendor.indexOf("Netscape")>=0)&&parseInt(this.vendver)==6;this.ns7=this.ns&&parseInt(this.vendver)==7;this.chrome=this.agent_lc.indexOf("chrome")>0;this.safari=!this.chrome&&(this.agent_lc.indexOf("safari")>0||this.agent_lc.indexOf("applewebkit")>0);this.konq=this.agent_lc.indexOf("konqueror")>0;this.iphone=this.safari&&this.agent_lc.indexOf("iphone")> +0;this.ipad=this.safari&&this.agent_lc.indexOf("ipad")>0;if((this.opera=window.opera?!0:!1)&&window.RegExp)this.vendver=/opera(\s|\/)([0-9\.]+)/.test(this.agent_lc)?parseFloat(RegExp.$2):-1;else if(this.chrome&&window.RegExp)this.vendver=/chrome\/([0-9\.]+)/.test(this.agent_lc)?parseFloat(RegExp.$1):0;else if(!this.vendver&&this.safari)this.vendver=/(safari|applewebkit)\/([0-9]+)/.test(this.agent_lc)?parseInt(RegExp.$2):0;else if(!this.vendver&&this.mz||this.agent.indexOf("Camino")>0)this.vendver= /rv:([0-9\.]+)/.test(this.agent)?parseFloat(RegExp.$1):0;else if(this.ie&&window.RegExp)this.vendver=/msie\s+([0-9\.]+)/.test(this.agent_lc)?parseFloat(RegExp.$1):0;else if(this.konq&&window.RegExp)this.vendver=/khtml\/([0-9\.]+)/.test(this.agent_lc)?parseFloat(RegExp.$1):0;if(this.safari&&/;\s+([a-z]{2})-[a-z]{2}\)/.test(this.agent_lc))this.lang=RegExp.$1;this.dhtml=this.ie4&&this.win||this.ie5||this.ie6||this.ns4||this.mz;this.vml=this.win&&this.ie&&this.dom&&!this.opera;this.pngalpha=this.mz|| -this.opera&&this.vendver>=6||this.ie&&this.mac&&this.vendver>=5||this.ie&&this.win&&this.vendver>=5.5||this.safari;this.opacity=this.mz||this.ie&&this.vendver>=5.5&&!this.opera||this.safari&&this.vendver>=100;this.cookies=a.cookieEnabled;this.xmlhttp_test=function(){var b=new Function("try{var o=new ActiveXObject('Microsoft.XMLHTTP');return true;}catch(err){return false;}");return this.xmlhttp=window.XMLHttpRequest||window.ActiveXObject&&b()};this.set_html_class=function(){var b=" js";if(this.ie){b+= -" ie";if(this.ie5)b+=" ie5";else if(this.ie6)b+=" ie6";else if(this.ie7)b+=" ie7";else if(this.ie8)b+=" ie8"}else if(this.opera)b+=" opera";else if(this.konq)b+=" konqueror";else if(this.safari)b+=" safari";if(this.chrome)b+=" chrome";else if(this.iphone)b+=" iphone";else if(this.ipad)b+=" ipad";else if(this.ns6)b+=" netscape6";else if(this.ns7)b+=" netscape7";if(document.documentElement)document.documentElement.className+=b}} -var rcube_event={get_target:function(a){return(a=a||window.event)&&a.target?a.target:a.srcElement},get_keycode:function(a){return(a=a||window.event)&&a.keyCode?a.keyCode:a&&a.which?a.which:0},get_button:function(a){return(a=a||window.event)&&typeof a.button!="undefined"?a.button:a&&a.which?a.which:0},get_modifier:function(a){var b=0;a=a||window.event;if(bw.mac&&a){b+=(a.metaKey&&CONTROL_KEY)+(a.shiftKey&&SHIFT_KEY);return b}if(a){b+=(a.ctrlKey&&CONTROL_KEY)+(a.shiftKey&&SHIFT_KEY);return b}},get_mouse_pos:function(a){if(!a)a= -window.event;var b=a.pageX?a.pageX:a.clientX,c=a.pageY?a.pageY:a.clientY;if(document.body&&document.all){b+=document.body.scrollLeft;c+=document.body.scrollTop}if(a._offset){b+=a._offset.left;c+=a._offset.top}return{x:b,y:c}},add_listener:function(a){if(a.object&&a.method){if(!a.element)a.element=document;if(!a.object._rc_events)a.object._rc_events=[];var b=a.event+"*"+a.method;a.object._rc_events[b]||(a.object._rc_events[b]=function(c){return a.object[a.method](c)});if(a.element.addEventListener)a.element.addEventListener(a.event, -a.object._rc_events[b],false);else if(a.element.attachEvent){a.element.detachEvent("on"+a.event,a.object._rc_events[b]);a.element.attachEvent("on"+a.event,a.object._rc_events[b])}else a.element["on"+a.event]=a.object._rc_events[b]}},remove_listener:function(a){if(!a.element)a.element=document;var b=a.event+"*"+a.method;if(a.object&&a.object._rc_events&&a.object._rc_events[b])if(a.element.removeEventListener)a.element.removeEventListener(a.event,a.object._rc_events[b],false);else if(a.element.detachEvent)a.element.detachEvent("on"+ -a.event,a.object._rc_events[b]);else a.element["on"+a.event]=null},cancel:function(a){a=a?a:window.event;a.preventDefault&&a.preventDefault();a.stopPropagation&&a.stopPropagation();a.cancelBubble=true;return a.returnValue=false},touchevent:function(a){return{pageX:a.pageX,pageY:a.pageY,offsetX:a.pageX-a.target.offsetLeft,offsetY:a.pageY-a.target.offsetTop,target:a.target,istouch:true}}};function rcube_event_engine(){this._events={}} -rcube_event_engine.prototype={addEventListener:function(a,b,c){if(!this._events)this._events={};this._events[a]||(this._events[a]=[]);this._events[a][this._events[a].length]={func:b,obj:c?c:window}},removeEventListener:function(a,b,c){if(typeof c=="undefined")c=window;for(var d,e=0;this._events&&this._events[a]&&e=6||this.ie&&this.mac&&this.vendver>=5||this.ie&&this.win&&this.vendver>=5.5||this.safari;this.opacity=this.mz||this.ie&&this.vendver>=5.5&&!this.opera||this.safari&&this.vendver>=100;this.cookies=a.cookieEnabled;this.xmlhttp_test=function(){var a=new Function("try{var o=new ActiveXObject('Microsoft.XMLHTTP');return true;}catch(err){return false;}");return this.xmlhttp=window.XMLHttpRequest||window.ActiveXObject&&a()};this.set_html_class=function(){var a=" js";this.ie?(a+= +" ie",this.ie5?a+=" ie5":this.ie6?a+=" ie6":this.ie7?a+=" ie7":this.ie8&&(a+=" ie8")):this.opera?a+=" opera":this.konq?a+=" konqueror":this.safari&&(a+=" safari");this.chrome?a+=" chrome":this.iphone?a+=" iphone":this.ipad?a+=" ipad":this.ns6?a+=" netscape6":this.ns7&&(a+=" netscape7");document.documentElement&&(document.documentElement.className+=a)}} +var rcube_event={get_target:function(a){return(a=a||window.event)&&a.target?a.target:a.srcElement},get_keycode:function(a){return(a=a||window.event)&&a.keyCode?a.keyCode:a&&a.which?a.which:0},get_button:function(a){return(a=a||window.event)&&typeof a.button!="undefined"?a.button:a&&a.which?a.which:0},get_modifier:function(a){var b=0,a=a||window.event;if(bw.mac&&a)return b+=(a.metaKey&&CONTROL_KEY)+(a.shiftKey&&SHIFT_KEY),b;if(a)return b+=(a.ctrlKey&&CONTROL_KEY)+(a.shiftKey&&SHIFT_KEY),b},get_mouse_pos:function(a){if(!a)a= +window.event;var b=a.pageX?a.pageX:a.clientX,c=a.pageY?a.pageY:a.clientY;document.body&&document.all&&(b+=document.body.scrollLeft,c+=document.body.scrollTop);a._offset&&(b+=a._offset.left,c+=a._offset.top);return{x:b,y:c}},add_listener:function(a){if(a.object&&a.method){if(!a.element)a.element=document;if(!a.object._rc_events)a.object._rc_events=[];var b=a.event+"*"+a.method;a.object._rc_events[b]||(a.object._rc_events[b]=function(c){return a.object[a.method](c)});a.element.addEventListener?a.element.addEventListener(a.event, +a.object._rc_events[b],!1):a.element.attachEvent?(a.element.detachEvent("on"+a.event,a.object._rc_events[b]),a.element.attachEvent("on"+a.event,a.object._rc_events[b])):a.element["on"+a.event]=a.object._rc_events[b]}},remove_listener:function(a){if(!a.element)a.element=document;var b=a.event+"*"+a.method;a.object&&a.object._rc_events&&a.object._rc_events[b]&&(a.element.removeEventListener?a.element.removeEventListener(a.event,a.object._rc_events[b],!1):a.element.detachEvent?a.element.detachEvent("on"+ +a.event,a.object._rc_events[b]):a.element["on"+a.event]=null)},cancel:function(a){a=a?a:window.event;a.preventDefault&&a.preventDefault();a.stopPropagation&&a.stopPropagation();a.cancelBubble=!0;return a.returnValue=!1},touchevent:function(a){return{pageX:a.pageX,pageY:a.pageY,offsetX:a.pageX-a.target.offsetLeft,offsetY:a.pageY-a.target.offsetTop,target:a.target,istouch:!0}}};function rcube_event_engine(){this._events={}} +rcube_event_engine.prototype={addEventListener:function(a,b,c){if(!this._events)this._events={};this._events[a]||(this._events[a]=[]);this._events[a][this._events[a].length]={func:b,obj:c?c:window}},removeEventListener:function(a,b,c){typeof c=="undefined"&&(c=window);for(var d,e=0;this._events&&this._events[a]&&e|[,;s\n])","i"): RegExp("^((([^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+|\\x22([^\\x0d\\x22\\x5c\\x80-\\xff]|\\x5c[\\x00-\\x7f])*\\x22)(\\x2e([^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+|\\x22([^\\x0d\\x22\\x5c\\x80-\\xff]|\\x5c[\\x00-\\x7f])*\\x22))*\\x40([^@\\x2e]+\\x2e)+([a-z]{2,}|xn--[a-z0-9]{2,}))|(mailtest\\x40(\\u0645\\u062b\\u0627\\u0644\\x2e\\u0625\\u062e\\u062a\\u0628\\u0627\\u0631|\\u4f8b\\u5b50\\x2e\\u6d4b\\u8bd5|\\u4f8b\\u5b50\\x2e\\u6e2c\\u8a66|\\u03c0\\u03b1\\u03c1\\u03ac\\u03b4\\u03b5\\u03b9\\u03b3\\u03bc\\u03b1\\x2e\\u03b4\\u03bf\\u03ba\\u03b9\\u03bc\\u03ae|\\u0909\\u0926\\u093e\\u0939\\u0930\\u0923\\x2e\\u092a\\u0930\\u0940\\u0915\\u094d\\u0937\\u093e|\\u4f8b\\u3048\\x2e\\u30c6\\u30b9\\u30c8|\\uc2e4\\ub840\\x2e\\ud14c\\uc2a4\\ud2b8|\\u0645\\u062b\\u0627\\u0644\\x2e\\u0622\\u0632\\u0645\\u0627\\u06cc\\u0634\u06cc|\\u043f\\u0440\\u0438\\u043c\\u0435\\u0440\\x2e\\u0438\\u0441\\u043f\\u044b\\u0442\\u0430\\u043d\\u0438\\u0435|\\u0b89\\u0ba4\\u0bbe\\u0bb0\\u0ba3\\u0bae\\u0bcd\\x2e\\u0baa\\u0bb0\\u0bbf\\u0b9f\\u0bcd\\u0b9a\\u0bc8|\\u05d1\\u05f2\\u05b7\\u05e9\\u05e4\\u05bc\\u05d9\\u05dc\\x2e\\u05d8\\u05e2\\u05e1\\u05d8)))$", -"i")).test(a)?true:false;return false}function rcube_clone_object(a){var b={},c;for(c in a)b[c]=a[c]&&typeof a[c]=="object"?clone_object(a[c]):a[c];return b}function urlencode(a){return window.encodeURIComponent?encodeURIComponent(a):escape(a)} -function rcube_find_object(a,b){var c,d;b||(b=document);if(b.getElementsByName&&(c=b.getElementsByName(a)))d=c[0];if(!d&&b.getElementById)d=b.getElementById(a);if(!d&&b.all)d=b.all[a];if(!d&&b.images.length)d=b.images[a];if(!d&&b.forms.length)for(c=0;c=d.left&&c.x=d.top&&c.y/g,">")};this.createXMLReq=function(a){return''+a+""}; -this.spellCheck=function(a){this.cnt_errors=this.cnt_errors_fixed=0;this.setStateChanged("checking_spell");this.main_controller&&this.appendIndicator(this.spell_span);this.error_links=[];this.ta_scroll_top=this.text_area.scrollTop;this.ignore=a;this.hideLangWindow();if($(this.text_area).val()==""||a){this.custom_no_spelling_error?this.custom_no_spelling_error(this):this.flashNoSpellingErrorState();this.removeIndicator()}else{this.createEditLayer(this.text_area.offsetWidth,this.text_area.offsetHeight); -this.createErrorWindow();$("body").append(this.error_window);try{netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead")}catch(c){}this.main_controller&&$(this.spell_span).unbind("click");this.orginal_text=$(this.text_area).val();a=this.escapeSpecial(this.orginal_text);var b=this;$.ajax({type:"POST",url:this.getUrl(),data:this.createXMLReq(a),dataType:"text",error:function(){b.custom_ajax_error?b.custom_ajax_error(b):alert("An error was encountered on the server. Please try again later."); -if(b.main_controller){$(b.spell_span).remove();b.removeIndicator()}b.checkSpellingState()},success:function(d){b.results=b.parseResult(d);if(d.match(//)!=null){b.showErrorsInIframe();b.resumeEditingState()}else b.custom_no_spelling_error?b.custom_no_spelling_error(b):b.flashNoSpellingErrorState();b.removeIndicator()}})}};this.parseResult=function(a){var c=/\w+="(\d+|true)"/g,b=/\t/g;a=a.match(/]*>[^<]*<\/c>/g);var d=[];if(a==null)return d;for(var e=0,f=a.length;e]*>/g,"").split(b);for(h=0;hd)this.results[b].attrs.o+=c};this.saveOldValue=function(a,c){a.is_changed=true;a.old_value=c};this.createListSeparator=function(){var a=document.createElement("td"), -c=document.createElement("tr");$(a).html(" ").attr("googie_action_btn","1").css({cursor:"default","font-size":"3px","border-top":"1px solid #ccc","padding-top":"3px"});c.appendChild(a);return c};this.correctError=function(a,c,b,d){var e=c.innerHTML;b=b.nodeType==3?b.nodeValue:b.innerHTML;var f=this.results[a].attrs.o;if(d){d=c.previousSibling.innerHTML;c.previousSibling.innerHTML=d.slice(0,d.length-1);e=" "+e;f--}this.hideErrorWindow();this.updateOrginalText(f,e,b,a);$(c).html(b).css("color","green").attr("is_corrected", -true);this.results[a].attrs.l=b.length;this.isDefined(c.old_value)||this.saveOldValue(c,e);this.errorFixed()};this.showErrorWindow=function(a,c){this.show_menu_observer&&this.show_menu_observer(this);var b=this,d=$(a).offset(),e=document.createElement("table"),f=document.createElement("tbody");$(this.error_window).html("");$(e).addClass("googie_list").attr("googie_action_btn","1");for(var j=false,g=0;g0&&f.appendChild(this.createListSeparator());var t=function(p){if(p").css({position:"absolute","z-index":-1});$("body").append(d);this.error_window_iframe=d}$(this.error_window_iframe).css({top:this.error_window.offsetTop, -left:this.error_window.offsetLeft,width:this.error_window.offsetWidth,height:this.error_window.offsetHeight}).show()}};this.createEditLayer=function(a,c){this.edit_layer=document.createElement("div");$(this.edit_layer).addClass("googie_edit_layer").attr("id","googie_edit_layer").width("auto").height(c);this.text_area.nodeName.toLowerCase()!="input"||$(this.text_area).val()==""?$(this.edit_layer).css("overflow","auto").height(c-4):$(this.edit_layer).css("overflow","hidden");var b=this;this.edit_layer_dbl_click&& -$(this.edit_layer).dblclick(function(d){if(d.target.className!="googie_link"&&!b.isErrorWindowShown()){b.resumeEditing();var e=function(){$(b.text_area).focus();e=null};window.setTimeout(e,10)}return false})};this.resumeEditing=function(){this.setStateChanged("ready");if(this.edit_layer)this.el_scroll_top=this.edit_layer.scrollTop;this.hideErrorWindow();this.main_controller&&$(this.spell_span).removeClass().addClass("googie_no_style");if(!this.ignore){if(this.use_focus){$(this.focus_link_t).remove(); -$(this.focus_link_b).remove()}$(this.edit_layer).remove();$(this.text_area).show();if(this.el_scroll_top!=undefined)this.text_area.scrollTop=this.el_scroll_top}this.checkSpellingState(false)};this.createErrorLink=function(a,c){var b=document.createElement("span"),d=this,e=function(){d.showErrorWindow(b,c);e=null;return false};$(b).html(a).addClass("googie_link").bind("click",e).attr({googie_action_btn:"1",g_id:c,is_corrected:false});return b};this.createPart=function(a){if(a==" ")return document.createTextNode(" "); -a=this.escapeSpecial(a);a=a.replace(/\n/g,"
    ");a=a.replace(/ /g,"  ");a=a.replace(/^ /g," ");a=a.replace(/ $/g," ");var c=document.createElement("span");$(c).html(a);return c};this.showErrorsInIframe=function(){var a=document.createElement("div"),c=0,b=this.results;if(b.length>0){for(var d=0,e=b.length;d").attr({src:this.img_dir+"change_lang.gif",alt:"Change language",googie_action_btn:"1"}),c=document.createElement("span"); -m=this;$(c).addClass("googie_lang_3d_on").append(a).bind("click",function(){var b=this.tagName.toLowerCase()=="img"?this.parentNode:this;if($(b).hasClass("googie_lang_3d_click")){b.className="googie_lang_3d_on";m.hideLangWindow()}else{b.className="googie_lang_3d_click";m.showLangWindow(b)}});return c};this.createSpellDiv=function(){var a=document.createElement("span");$(a).addClass("googie_check_spelling_link").text(this.lang_chck_spell);this.show_spell_img&&$(a).append(" ").append($("").attr("src", -this.img_dir+"spellc.gif"));return a};this.flashNoSpellingErrorState=function(a){this.setStateChanged("no_error_found");var c=this;if(this.main_controller){var b;b=a?function(){a();c.checkSpellingState()}:function(){c.checkSpellingState()};var d=$("").text(this.lang_no_error_found);$(this.switch_lan_pic).hide();$(this.spell_span).empty().append(d).removeClass().addClass("googie_check_spelling_ok");window.setTimeout(b,1E3)}};this.resumeEditingState=function(){this.setStateChanged("resume_editing"); -if(this.main_controller){var a=$("").text(this.lang_rsm_edt),c=this;$(this.switch_lan_pic).hide();$(this.spell_span).empty().unbind().append(a).bind("click",function(){c.resumeEditing()}).removeClass().addClass("googie_resume_editing")}try{this.edit_layer.scrollTop=this.ta_scroll_top}catch(b){}};this.checkSpellingState=function(a){a&&this.setStateChanged("ready");this.switch_lan_pic=this.show_change_lang_pic?this.createChangeLangPic():document.createElement("span");a=this.createSpellDiv();var c= -this;this.custom_spellcheck_starter?$(a).bind("click",function(){c.custom_spellcheck_starter()}):$(a).bind("click",function(){c.spellCheck()});if(this.main_controller)this.change_lang_pic_placement=="left"?$(this.spell_container).empty().append(this.switch_lan_pic).append(" ").append(a):$(this.spell_container).empty().append(a).append(" ").append(this.switch_lan_pic);this.spell_span=a};this.isDefined=function(a){return a!="undefined"&&a!=null};this.errorFixed=function(){this.cnt_errors_fixed++;if(this.all_errors_fixed_observer)if(this.cnt_errors_fixed== -this.cnt_errors){this.hideErrorWindow();this.all_errors_fixed_observer()}};this.errorFound=function(){this.cnt_errors++};this.createCloseButton=function(a){return this.createButton(this.lang_close,"googie_list_close",a)};this.createButton=function(a,c,b){var d=document.createElement("tr"),e=document.createElement("td"),f;if(c){f=document.createElement("span");$(f).addClass(c).html(a)}else f=document.createTextNode(a);$(e).bind("click",b).bind("mouseover",this.item_onmouseover).bind("mouseout",this.item_onmouseout); -e.appendChild(f);d.appendChild(e);return d};this.removeIndicator=function(){window.rcmail&&rcmail.set_busy(false,null,this.rc_msg_id)};this.appendIndicator=function(){if(window.rcmail)this.rc_msg_id=rcmail.set_busy(true,"checking")};this.createFocusLink=function(a){var c=document.createElement("a");$(c).attr({href:"javascript:;",name:a});return c};this.item_onmouseover=function(){if(this.className!="googie_list_revert"&&this.className!="googie_list_close")this.className="googie_list_onhover";else this.parentNode.className= -"googie_list_onhover"};this.item_onmouseout=function(){if(this.className!="googie_list_revert"&&this.className!="googie_list_close")this.className="googie_list_onout";else this.parentNode.className="googie_list_onout"}}; +this.spellCheck=function(a){this.cnt_errors=this.cnt_errors_fixed=0;this.setStateChanged("checking_spell");this.main_controller&&this.appendIndicator(this.spell_span);this.error_links=[];this.ta_scroll_top=this.text_area.scrollTop;this.ignore=a;this.hideLangWindow();if($(this.text_area).val()==""||a)this.custom_no_spelling_error?this.custom_no_spelling_error(this):this.flashNoSpellingErrorState(),this.removeIndicator();else{this.createEditLayer(this.text_area.offsetWidth,this.text_area.offsetHeight); +this.createErrorWindow();$("body").append(this.error_window);try{netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead")}catch(b){}this.main_controller&&$(this.spell_span).unbind("click");this.orginal_text=$(this.text_area).val();var a=this.escapeSpecial(this.orginal_text),c=this;$.ajax({type:"POST",url:this.getUrl(),data:this.createXMLReq(a),dataType:"text",error:function(){c.custom_ajax_error?c.custom_ajax_error(c):alert("An error was encountered on the server. Please try again later."); +c.main_controller&&($(c.spell_span).remove(),c.removeIndicator());c.checkSpellingState()},success:function(a){c.results=c.parseResult(a);a.match(//)!=null?(c.showErrorsInIframe(),c.resumeEditingState()):c.custom_no_spelling_error?c.custom_no_spelling_error(c):c.flashNoSpellingErrorState();c.removeIndicator()}})}};this.parseResult=function(a){var b=/\w+="(\d+|true)"/g,c=/\t/g,a=a.match(/]*>[^<]*<\/c>/g),d=[];if(a==null)return d;for(var e=0,f=a.length;e]*>/g,"").split(c);for(h=0;hd&&(this.results[c].attrs.o+=b)};this.saveOldValue=function(a,b){a.is_changed=!0;a.old_value=b};this.createListSeparator=function(){var a=document.createElement("td"), +b=document.createElement("tr");$(a).html(" ").attr("googie_action_btn","1").css({cursor:"default","font-size":"3px","border-top":"1px solid #ccc","padding-top":"3px"});b.appendChild(a);return b};this.correctError=function(a,b,c,d){var e=b.innerHTML,c=c.nodeType==3?c.nodeValue:c.innerHTML,f=this.results[a].attrs.o;if(d)d=b.previousSibling.innerHTML,b.previousSibling.innerHTML=d.slice(0,d.length-1),e=" "+e,f--;this.hideErrorWindow();this.updateOrginalText(f,e,c,a);$(b).html(c).css("color","green").attr("is_corrected", +!0);this.results[a].attrs.l=c.length;this.isDefined(b.old_value)||this.saveOldValue(b,e);this.errorFixed()};this.showErrorWindow=function(a,b){this.show_menu_observer&&this.show_menu_observer(this);var c=this,d=$(a).offset(),e=document.createElement("table"),f=document.createElement("tbody");$(this.error_window).html("");$(e).addClass("googie_list").attr("googie_action_btn","1");for(var j=!1,g=0;g0&&f.appendChild(this.createListSeparator());var q=function(b){if(b").css({position:"absolute","z-index":-1}),$("body").append(d),this.error_window_iframe=d;$(this.error_window_iframe).css({top:this.error_window.offsetTop,left:this.error_window.offsetLeft, +width:this.error_window.offsetWidth,height:this.error_window.offsetHeight}).show()}};this.createEditLayer=function(a,b){this.edit_layer=document.createElement("div");$(this.edit_layer).addClass("googie_edit_layer").attr("id","googie_edit_layer").width("auto").height(b);this.text_area.nodeName.toLowerCase()!="input"||$(this.text_area).val()==""?$(this.edit_layer).css("overflow","auto").height(b-4):$(this.edit_layer).css("overflow","hidden");var c=this;this.edit_layer_dbl_click&&$(this.edit_layer).dblclick(function(a){if(a.target.className!= +"googie_link"&&!c.isErrorWindowShown()){c.resumeEditing();var b=function(){$(c.text_area).focus();b=null};window.setTimeout(b,10)}return!1})};this.resumeEditing=function(){this.setStateChanged("ready");if(this.edit_layer)this.el_scroll_top=this.edit_layer.scrollTop;this.hideErrorWindow();this.main_controller&&$(this.spell_span).removeClass().addClass("googie_no_style");if(!this.ignore&&(this.use_focus&&($(this.focus_link_t).remove(),$(this.focus_link_b).remove()),$(this.edit_layer).remove(),$(this.text_area).show(), +this.el_scroll_top!=void 0))this.text_area.scrollTop=this.el_scroll_top;this.checkSpellingState(!1)};this.createErrorLink=function(a,b){var c=document.createElement("span"),d=this,e=function(){d.showErrorWindow(c,b);e=null;return!1};$(c).html(a).addClass("googie_link").bind("click",e).attr({googie_action_btn:"1",g_id:b,is_corrected:!1});return c};this.createPart=function(a){if(a==" ")return document.createTextNode(" ");var a=this.escapeSpecial(a),a=a.replace(/\n/g,"
    "),a=a.replace(/ /g,"  "), +a=a.replace(/^ /g," "),a=a.replace(/ $/g," "),b=document.createElement("span");$(b).html(a);return b};this.showErrorsInIframe=function(){var a=document.createElement("div"),b=0,c=this.results;if(c.length>0){for(var d=0,e=c.length;d").attr({src:this.img_dir+"change_lang.gif",alt:"Change language",googie_action_btn:"1"}),b=document.createElement("span");l=this;$(b).addClass("googie_lang_3d_on").append(a).bind("click",function(){var a=this.tagName.toLowerCase()== +"img"?this.parentNode:this;$(a).hasClass("googie_lang_3d_click")?(a.className="googie_lang_3d_on",l.hideLangWindow()):(a.className="googie_lang_3d_click",l.showLangWindow(a))});return b};this.createSpellDiv=function(){var a=document.createElement("span");$(a).addClass("googie_check_spelling_link").text(this.lang_chck_spell);this.show_spell_img&&$(a).append(" ").append($("").attr("src",this.img_dir+"spellc.gif"));return a};this.flashNoSpellingErrorState=function(a){this.setStateChanged("no_error_found"); +var b=this;if(this.main_controller){var c;c=a?function(){a();b.checkSpellingState()}:function(){b.checkSpellingState()};var d=$("").text(this.lang_no_error_found);$(this.switch_lan_pic).hide();$(this.spell_span).empty().append(d).removeClass().addClass("googie_check_spelling_ok");window.setTimeout(c,1E3)}};this.resumeEditingState=function(){this.setStateChanged("resume_editing");if(this.main_controller){var a=$("").text(this.lang_rsm_edt),b=this;$(this.switch_lan_pic).hide();$(this.spell_span).empty().unbind().append(a).bind("click", +function(){b.resumeEditing()}).removeClass().addClass("googie_resume_editing")}try{this.edit_layer.scrollTop=this.ta_scroll_top}catch(c){}};this.checkSpellingState=function(a){a&&this.setStateChanged("ready");this.switch_lan_pic=this.show_change_lang_pic?this.createChangeLangPic():document.createElement("span");var a=this.createSpellDiv(),b=this;this.custom_spellcheck_starter?$(a).bind("click",function(){b.custom_spellcheck_starter()}):$(a).bind("click",function(){b.spellCheck()});this.main_controller&& +(this.change_lang_pic_placement=="left"?$(this.spell_container).empty().append(this.switch_lan_pic).append(" ").append(a):$(this.spell_container).empty().append(a).append(" ").append(this.switch_lan_pic));this.spell_span=a};this.isDefined=function(a){return a!="undefined"&&a!=null};this.errorFixed=function(){this.cnt_errors_fixed++;this.all_errors_fixed_observer&&this.cnt_errors_fixed==this.cnt_errors&&(this.hideErrorWindow(),this.all_errors_fixed_observer())};this.errorFound=function(){this.cnt_errors++}; +this.createCloseButton=function(a){return this.createButton(this.lang_close,"googie_list_close",a)};this.createButton=function(a,b,c){var d=document.createElement("tr"),e=document.createElement("td"),f;b?(f=document.createElement("span"),$(f).addClass(b).html(a)):f=document.createTextNode(a);$(e).bind("click",c).bind("mouseover",this.item_onmouseover).bind("mouseout",this.item_onmouseout);e.appendChild(f);d.appendChild(e);return d};this.removeIndicator=function(){window.rcmail&&rcmail.set_busy(!1, +null,this.rc_msg_id)};this.appendIndicator=function(){if(window.rcmail)this.rc_msg_id=rcmail.set_busy(!0,"checking")};this.createFocusLink=function(a){var b=document.createElement("a");$(b).attr({href:"javascript:;",name:a});return b};this.item_onmouseover=function(){this.className!="googie_list_revert"&&this.className!="googie_list_close"?this.className="googie_list_onhover":this.parentNode.className="googie_list_onhover"};this.item_onmouseout=function(){this.className!="googie_list_revert"&&this.className!= +"googie_list_close"?this.className="googie_list_onout":this.parentNode.className="googie_list_onout"}}; diff --git a/program/js/list.js b/program/js/list.js index 5792ff9..00410b7 100644 --- a/program/js/list.js +++ b/program/js/list.js @@ -1,40 +1,39 @@ -function rcube_list_widget(a,b){this.ENTER_KEY=13;this.DELETE_KEY=46;this.BACKSPACE_KEY=8;this.list=a?a:null;this.frame=null;this.rows=[];this.selection=[];this.colcount=this.rowcount=0;this.subject_col=-1;this.col_drag_active=this.drag_active=this.dont_select=this.toggleselect=this.keyboard=this.column_movable=this.draggable=this.multi_selecting=this.multiexpand=this.multiselect=this.shiftkey=false;this.column_fixed=null;this.shift_start=this.last_selected=0;this.focused=this.in_selection_before= -false;this.drag_mouse_start=null;this.dblclick_time=600;this.row_init=function(){};if(b&&typeof b=="object")for(var c in b)this[c]=b[c]} -rcube_list_widget.prototype={init:function(){if(this.list&&this.list.tBodies[0]){this.rows=[];this.rowcount=0;var a,b,c=this.list.tBodies[0].rows;a=0;for(b=c.length;a1){this.drag_start=true;this.drag_mouse_start=rcube_event.get_mouse_pos(a);rcube_event.add_listener({event:"mousemove", -object:this,method:"column_drag_mouse_move"});rcube_event.add_listener({event:"mouseup",object:this,method:"column_drag_mouse_up"});this.add_dragfix();for(var c=0;c=f.depth-1){d=f.depth;$(c).css("display","");e.expanded=true;this.triggerEvent("expandcollapse",{uid:e.uid,expanded:e.expanded})}}else if(a&&(!f||f.depth<= -b))break}}}c=c.nextSibling}return false},collapse_all:function(a){var b,c,d;if(a){a.expanded=false;b=a.depth;c=a.obj.nextSibling;this.update_expando(a.uid);this.triggerEvent("expandcollapse",{uid:a.uid,expanded:a.expanded});if(b&&this.multiexpand)return false}else{c=this.list.tBodies[0].firstChild;b=0}for(;c;){if(c.nodeType==1)if(d=this.rows[c.uid]){if(a&&(!d.depth||d.depth<=b))break;if(a||d.depth)$(c).css("display","none");if(d.has_children&&d.expanded){d.expanded=false;this.update_expando(d.uid, -false);this.triggerEvent("expandcollapse",{uid:d.uid,expanded:d.expanded})}}c=c.nextSibling}return false},expand_all:function(a){var b,c,d;if(a){a.expanded=true;b=a.depth;c=a.obj.nextSibling;this.update_expando(a.uid,true);this.triggerEvent("expandcollapse",{uid:a.uid,expanded:a.expanded})}else{c=this.list.tBodies[0].firstChild;b=0}for(;c;){if(c.nodeType==1)if(d=this.rows[c.uid]){if(a&&d.depth<=b)break;$(c).css("display","");if(d.has_children&&!d.expanded){d.expanded=true;this.update_expando(d.uid, -true);this.triggerEvent("expandcollapse",{uid:d.uid,expanded:d.expanded})}}c=c.nextSibling}return false},update_expando:function(a,b){var c=document.getElementById("rcmexpando"+a);if(c)c.className=b?"expanded":"collapsed"},get_next_row:function(){if(!this.rows)return false;var a=this.rows[this.last_selected];for(a=a?a.obj.nextSibling:null;a&&(a.nodeType!=1||a.style.display=="none");)a=a.nextSibling;return a},get_prev_row:function(){if(!this.rows)return false;var a=this.rows[this.last_selected];for(a= -a?a.obj.previousSibling:null;a&&(a.nodeType!=1||a.style.display=="none");)a=a.previousSibling;return a},get_first_row:function(){if(this.rowcount){var a,b,c=this.list.tBodies[0].rows;a=0;for(b=c.length-1;a=0;a--)if(b[a].id&&String(b[a].id).match(/rcmrow([a-z0-9\-_=\+\/]+)/i)&& -this.rows[RegExp.$1]!=null)return RegExp.$1}return null},select_row:function(a,b,c){var d=this.selection.join(",");this.multiselect||(b=0);if(!this.shift_start)this.shift_start=a;if(b){switch(b){case SHIFT_KEY:this.shift_select(a,false);break;case CONTROL_KEY:c||this.highlight_row(a,true);break;case CONTROL_SHIFT_KEY:this.shift_select(a,true);break;default:this.highlight_row(a,false)}this.multi_selecting=true}else{this.shift_start=a;this.highlight_row(a,false);this.multi_selecting=false}this.selection.join(",")!= -d&&this.triggerEvent("select");this.last_selected!=0&&this.rows[this.last_selected]&&$(this.rows[this.last_selected].obj).removeClass("focused");if(this.toggleselect&&this.last_selected==a){this.clear_selection();a=null}else $(this.rows[a].obj).addClass("focused");if(!this.selection.length)this.shift_start=null;this.last_selected=a},select:function(a){this.select_row(a,false);this.scrollto(a)},select_next:function(){var a=this.get_next_row(),b=this.get_prev_row();(a=a?a:b)&&this.select_row(a.uid, -false,false)},select_first:function(a){var b=this.get_first_row();if(b&&a){this.shift_select(b,a);this.triggerEvent("select");this.scrollto(b)}else b&&this.select(b)},select_last:function(a){var b=this.get_last_row();if(b&&a){this.shift_select(b,a);this.triggerEvent("select");this.scrollto(b)}else b&&this.select(b)},select_childs:function(a){if(this.rows[a]&&this.rows[a].has_children){var b=this.rows[a].depth;for(a=this.rows[a].obj.nextSibling;a;){if(a.nodeType==1)if(r=this.rows[a.uid]){if(!r.depth|| -r.depth<=b)break;this.in_selection(r.uid)||this.select_row(r.uid,CONTROL_KEY)}a=a.nextSibling}}},shift_select:function(a,b){if(!this.rows[this.shift_start]||!this.selection.length)this.shift_start=a;var c=this.rows[this.shift_start].obj.rowIndex,d=this.rows[a].obj.rowIndex,e=cd?c:d;for(var f in this.rows)if(this.rows[f].obj.rowIndex>=e&&this.rows[f].obj.rowIndex<=c)this.in_selection(f)||this.highlight_row(f,true);else this.in_selection(f)&&!b&&this.highlight_row(f,true)},in_selection:function(a){for(var b in this.selection)if(this.selection[b]== -a)return true;return false},select_all:function(a){if(!this.rows||!this.rows.length)return false;var b=this.selection.join(",");this.selection=[];for(var c in this.rows)if(!a||this.rows[c][a]==true){this.last_selected=c;this.highlight_row(c,true)}else $(this.rows[c].obj).removeClass("selected").removeClass("unfocused");this.selection.join(",")!=b&&this.triggerEvent("select");this.focus();return true},invert_selection:function(){if(!this.rows||!this.rows.length)return false;var a=this.selection.join(","), -b;for(b in this.rows)this.highlight_row(b,true);this.selection.join(",")!=a&&this.triggerEvent("select");this.focus();return true},clear_selection:function(a){var b=this.selection.length;if(a)for(var c in this.selection){if(this.selection[c]==a){this.selection.splice(c,1);break}}else{for(c in this.selection)this.rows[this.selection[c]]&&$(this.rows[this.selection[c]].obj).removeClass("selected").removeClass("unfocused");this.selection=[]}b&&!this.selection.length&&this.triggerEvent("select")},get_selection:function(){return this.selection}, -get_single_selection:function(){return this.selection.length==1?this.selection[0]:null},highlight_row:function(a,b){if(this.rows[a]&&!b){if(this.selection.length>1||!this.in_selection(a)){this.clear_selection();this.selection[0]=a;$(this.rows[a].obj).addClass("selected")}}else if(this.rows[a])if(this.in_selection(a)){var c=$.inArray(a,this.selection),d=this.selection.slice(0,c);c=this.selection.slice(c+1,this.selection.length);this.selection=d.concat(c);$(this.rows[a].obj).removeClass("selected").removeClass("unfocused")}else{this.selection[this.selection.length]= -a;$(this.rows[a].obj).addClass("selected")}},key_press:function(a){if(this.focused!=true)return true;var b=rcube_event.get_keycode(a),c=rcube_event.get_modifier(a);switch(b){case 40:case 38:case 63233:case 63232:rcube_event.cancel(a);return this.use_arrow_key(b,c);case 61:case 107:case 109:case 32:rcube_event.cancel(a);a=this.use_plusminus_key(b,c);this.key_pressed=b;this.triggerEvent("keypress");return a;case 36:this.select_first(c);return rcube_event.cancel(a);case 35:this.select_last(c);return rcube_event.cancel(a); -default:this.shiftkey=a.shiftKey;this.key_pressed=b;this.triggerEvent("keypress");if(this.key_pressed==this.BACKSPACE_KEY)return rcube_event.cancel(a)}return true},key_down:function(a){switch(rcube_event.get_keycode(a)){case 27:if(this.drag_active)return this.drag_mouse_up(a);if(this.col_drag_active){this.selected_column=null;return this.column_drag_mouse_up(a)}case 40:case 38:case 63233:case 63232:case 61:case 107:case 109:case 32:if(!rcube_event.get_modifier(a)&&this.focused)return rcube_event.cancel(a)}return true}, -use_arrow_key:function(a,b){var c;if(a==40||a==63233)c=this.get_next_row();else if(a==38||a==63232)c=this.get_prev_row();if(c){this.select_row(c.uid,b,true);this.scrollto(c.uid)}return false},use_plusminus_key:function(a,b){var c=this.rows[this.last_selected];if(c){if(a==32)a=c.expanded?109:61;if(a==61||a==107)b==CONTROL_KEY||this.multiexpand?this.expand_all(c):this.expand(c);else b==CONTROL_KEY||this.multiexpand?this.collapse_all(c):this.collapse(c);this.update_expando(c.uid,c.expanded);return false}}, -scrollto:function(a){var b=this.rows[a].obj;if(b&&this.frame){var c=Number(b.offsetTop);if(!c&&this.rows[a].parent_uid){this.expand_all(this.rows[this.find_root(this.rows[a].uid)]);c=Number(b.offsetTop)}if(cNumber(this.frame.scrollTop)+Number(this.frame.offsetHeight))this.frame.scrollTop=c+Number(b.offsetHeight)-Number(this.frame.offsetHeight)}},drag_mouse_move:function(a){if(a.type=="touchmove")if(a.changedTouches.length== -1)a=rcube_event.touchevent(a.changedTouches[0]);else return rcube_event.cancel(a);if(this.drag_start){var b=rcube_event.get_mouse_pos(a);if(!this.drag_mouse_start||Math.abs(b.x-this.drag_mouse_start.x)<3&&Math.abs(b.y-this.drag_mouse_start.y)<3)return false;if(!this.draglayer)this.draglayer=$("
    ").attr("id","rcmdraglayer").css({position:"absolute",display:"none","z-index":2E3}).appendTo(document.body);var c,d,e=$.merge([],this.selection);for(c in e){d=e[c];this.rows[d].has_children&&!this.rows[d].expanded&& -this.select_childs(d)}this.draglayer.html("");for(c=0;c12){this.draglayer.append("...");break}if(e=this.rows[this.selection[c]].obj)for(d=b=0;d=0&&this.subject_col==b){var f,g,h=e.childNodes[d].childNodes;for(b=0;b50?d.substring(0,50)+"...":d;this.draglayer.append($("
    ").text(d));break}b++}}this.draglayer.show();this.drag_active=true;this.triggerEvent("dragstart")}if(this.drag_active&&this.draglayer){c=rcube_event.get_mouse_pos(a);this.draglayer.css({left:c.x+20+"px",top:c.y-5+(bw.ie?document.documentElement.scrollTop:0)+"px"});this.triggerEvent("dragmove",a?a:window.event)}return this.drag_start=false},drag_mouse_up:function(a){document.onmousemove=null;if(a.type== -"touchend")if(a.changedTouches.length!=1)return rcube_event.cancel(a);if(this.draglayer&&this.draglayer.is(":visible"))this.drag_start_pos?this.draglayer.animate(this.drag_start_pos,300,"swing").hide(20):this.draglayer.hide();this.drag_active&&this.focus();this.drag_active=false;rcube_event.remove_listener({event:"mousemove",object:this,method:"drag_mouse_move"});rcube_event.remove_listener({event:"mouseup",object:this,method:"drag_mouse_up"});if(bw.iphone||bw.ipad){rcube_event.remove_listener({event:"touchmove", -object:this,method:"drag_mouse_move"});rcube_event.remove_listener({event:"touchend",object:this,method:"drag_mouse_up"})}this.del_dragfix();this.triggerEvent("dragend");return rcube_event.cancel(a)},column_drag_mouse_move:function(a){if(this.drag_start){var b;b=rcube_event.get_mouse_pos(a);if(!this.drag_mouse_start||Math.abs(b.x-this.drag_mouse_start.x)<3&&Math.abs(b.y-this.drag_mouse_start.y)<3)return false;if(!this.col_draglayer){b=$(this.list).offset();var c=this.list.tHead.rows[0].cells;this.col_draglayer= -$("
    ").attr("id","rcmcoldraglayer").css(b).css({position:"absolute","z-index":2001,"background-color":"white",opacity:0.75,height:this.frame.offsetHeight-2+"px",width:this.frame.offsetWidth-2+"px"}).appendTo(document.body).append($("
    ").attr("id","rcmcolumnindicator").css({position:"absolute","border-right":"2px dotted #555","z-index":2002,height:this.frame.offsetHeight-2+"px"}));this.cols=[];this.list_pos=this.list_min_pos=b.left;for(b=0;b=this.cols[b]/2+this.list_pos+c)c+=this.cols[b];else break;if(b==0&&this.list_min_pos>d.x)c=this.list_min_pos-this.list_pos;else if(!this.list.rowcount&&b==this.cols.length)c-=2;$("#rcmcolumnindicator").css({width:c+"px"});this.triggerEvent("column_dragmove", -a?a:window.event)}return this.drag_start=false},column_drag_mouse_up:function(a){document.onmousemove=null;if(this.col_draglayer){this.col_draglayer.remove();this.col_draglayer=null}this.col_drag_active&&this.focus();this.col_drag_active=false;rcube_event.remove_listener({event:"mousemove",object:this,method:"column_drag_mouse_move"});rcube_event.remove_listener({event:"mouseup",object:this,method:"column_drag_mouse_up"});this.del_dragfix();if(this.selected_column!==null&&this.cols&&this.cols.length){var b, -c=0,d=rcube_event.get_mouse_pos(a);for(b=0;b=this.cols[b]/2+this.list_pos+c)c+=this.cols[b];else break;b!=this.selected_column&&b!=this.selected_column+1&&this.column_replace(this.selected_column,b)}this.triggerEvent("column_dragend");return rcube_event.cancel(a)},add_dragfix:function(){$("iframe").each(function(){$('
    ').css({background:"#fff",width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001", -zIndex:1E3}).css($(this).offset()).appendTo(document.body)})},del_dragfix:function(){$("div.iframe-dragdrop-fix").each(function(){this.parentNode.removeChild(this)})},column_replace:function(a,b){var c=this.list.tHead.rows[0].cells,d=c[a],e=c[b],f=document.createElement("td");e?c[0].parentNode.insertBefore(f,e):c[0].parentNode.appendChild(f);c[0].parentNode.replaceChild(d,f);for(r=0;ra?b-1:b;else if(this.subject_cola&&b>=this.subject_col&&this.subject_col--;this.triggerEvent("column_replace")}};rcube_list_widget.prototype.addEventListener=rcube_event_engine.prototype.addEventListener;rcube_list_widget.prototype.removeEventListener=rcube_event_engine.prototype.removeEventListener; -rcube_list_widget.prototype.triggerEvent=rcube_event_engine.prototype.triggerEvent; +function rcube_list_widget(a,b){this.ENTER_KEY=13;this.DELETE_KEY=46;this.BACKSPACE_KEY=8;this.list=a?a:null;this.frame=null;this.rows=[];this.selection=[];this.colcount=this.rowcount=0;this.subject_col=-1;this.col_drag_active=this.drag_active=this.dont_select=this.toggleselect=this.keyboard=this.column_movable=this.draggable=this.multi_selecting=this.multiexpand=this.multiselect=this.shiftkey=!1;this.column_fixed=null;this.shift_start=this.last_selected=0;this.focused=this.in_selection_before=!1; +this.drag_mouse_start=null;this.dblclick_time=600;this.row_init=function(){};if(b&&typeof b=="object")for(var c in b)this[c]=b[c]} +rcube_list_widget.prototype={init:function(){if(this.list&&this.list.tBodies[0]){this.rows=[];this.rowcount=0;var a,b,c=this.list.tBodies[0].rows;a=0;for(b=c.length;a1){this.drag_start=!0;this.drag_mouse_start=rcube_event.get_mouse_pos(a); +rcube_event.add_listener({event:"mousemove",object:this,method:"column_drag_mouse_move"});rcube_event.add_listener({event:"mouseup",object:this,method:"column_drag_mouse_up"});this.add_dragfix();for(var c=0;c=c.depth-1)f=c.depth,$(e).css("display",""),b.expanded=!0,this.triggerEvent("expandcollapse",{uid:b.uid,expanded:b.expanded})}else if(a&&(!c||c.depth<=d))break}e=e.nextSibling}return!1}, +collapse_all:function(a){var b,c,d;if(a){if(a.expanded=!1,b=a.depth,c=a.obj.nextSibling,this.update_expando(a.uid),this.triggerEvent("expandcollapse",{uid:a.uid,expanded:a.expanded}),b&&this.multiexpand)return!1}else c=this.list.tBodies[0].firstChild,b=0;for(;c;){if(c.nodeType==1&&(d=this.rows[c.uid])){if(a&&(!d.depth||d.depth<=b))break;(a||d.depth)&&$(c).css("display","none");if(d.has_children&&d.expanded)d.expanded=!1,this.update_expando(d.uid,!1),this.triggerEvent("expandcollapse",{uid:d.uid,expanded:d.expanded})}c= +c.nextSibling}return!1},expand_all:function(a){var b,c,d;a?(a.expanded=!0,b=a.depth,c=a.obj.nextSibling,this.update_expando(a.uid,!0),this.triggerEvent("expandcollapse",{uid:a.uid,expanded:a.expanded})):(c=this.list.tBodies[0].firstChild,b=0);for(;c;){if(c.nodeType==1&&(d=this.rows[c.uid])){if(a&&d.depth<=b)break;$(c).css("display","");if(d.has_children&&!d.expanded)d.expanded=!0,this.update_expando(d.uid,!0),this.triggerEvent("expandcollapse",{uid:d.uid,expanded:d.expanded})}c=c.nextSibling}return!1}, +update_expando:function(a,b){var c=document.getElementById("rcmexpando"+a);if(c)c.className=b?"expanded":"collapsed"},get_next_row:function(){if(!this.rows)return!1;for(var a=this.rows[this.last_selected],a=a?a.obj.nextSibling:null;a&&(a.nodeType!=1||a.style.display=="none");)a=a.nextSibling;return a},get_prev_row:function(){if(!this.rows)return!1;for(var a=this.rows[this.last_selected],a=a?a.obj.previousSibling:null;a&&(a.nodeType!=1||a.style.display=="none");)a=a.previousSibling;return a},get_first_row:function(){if(this.rowcount){var a, +b,c=this.list.tBodies[0].rows;a=0;for(b=c.length-1;a=0;a--)if(b[a].id&&String(b[a].id).match(/rcmrow([a-z0-9\-_=\+\/]+)/i)&&this.rows[RegExp.$1]!=null)return RegExp.$1}return null},select_row:function(a,b,c){var d=this.selection.join(",");this.multiselect||(b=0);if(!this.shift_start)this.shift_start= +a;if(b){switch(b){case SHIFT_KEY:this.shift_select(a,!1);break;case CONTROL_KEY:c||this.highlight_row(a,!0);break;case CONTROL_SHIFT_KEY:this.shift_select(a,!0);break;default:this.highlight_row(a,!1)}this.multi_selecting=!0}else this.shift_start=a,this.highlight_row(a,!1),this.multi_selecting=!1;this.selection.join(",")!=d&&this.triggerEvent("select");this.last_selected!=0&&this.rows[this.last_selected]&&$(this.rows[this.last_selected].obj).removeClass("focused");this.toggleselect&&this.last_selected== +a?(this.clear_selection(),a=null):$(this.rows[a].obj).addClass("focused");if(!this.selection.length)this.shift_start=null;this.last_selected=a},select:function(a){this.select_row(a,!1);this.scrollto(a)},select_next:function(){var a=this.get_next_row(),b=this.get_prev_row();(a=a?a:b)&&this.select_row(a.uid,!1,!1)},select_first:function(a){var b=this.get_first_row();b&&(a?(this.shift_select(b,a),this.triggerEvent("select"),this.scrollto(b)):this.select(b))},select_last:function(a){var b=this.get_last_row(); +b&&(a?(this.shift_select(b,a),this.triggerEvent("select"),this.scrollto(b)):this.select(b))},select_childs:function(a){if(this.rows[a]&&this.rows[a].has_children)for(var b=this.rows[a].depth,a=this.rows[a].obj.nextSibling;a;){if(a.nodeType==1&&(r=this.rows[a.uid])){if(!r.depth||r.depth<=b)break;this.in_selection(r.uid)||this.select_row(r.uid,CONTROL_KEY)}a=a.nextSibling}},shift_select:function(a,b){if(!this.rows[this.shift_start]||!this.selection.length)this.shift_start=a;var c,d=this.rows[this.shift_start].obj.rowIndex, +e=this.rows[a].obj.rowIndex,f=de?d:e;for(c in this.rows)this.rows[c].obj.rowIndex>=f&&this.rows[c].obj.rowIndex<=d?this.in_selection(c)||this.highlight_row(c,!0):this.in_selection(c)&&!b&&this.highlight_row(c,!0)},in_selection:function(a){for(var b in this.selection)if(this.selection[b]==a)return!0;return!1},select_all:function(a){if(!this.rows||!this.rows.length)return!1;var b,c=this.selection.join(",");this.selection=[];for(b in this.rows)!a||this.rows[b][a]==!0?(this.last_selected=b, +this.highlight_row(b,!0)):$(this.rows[b].obj).removeClass("selected").removeClass("unfocused");this.selection.join(",")!=c&&this.triggerEvent("select");this.focus();return!0},invert_selection:function(){if(!this.rows||!this.rows.length)return!1;var a,b=this.selection.join(",");for(a in this.rows)this.highlight_row(a,!0);this.selection.join(",")!=b&&this.triggerEvent("select");this.focus();return!0},clear_selection:function(a){var b,c=this.selection.length;if(a)for(b in this.selection){if(this.selection[b]== +a){this.selection.splice(b,1);break}}else{for(b in this.selection)this.rows[this.selection[b]]&&$(this.rows[this.selection[b]].obj).removeClass("selected").removeClass("unfocused");this.selection=[]}c&&!this.selection.length&&this.triggerEvent("select")},get_selection:function(){return this.selection},get_single_selection:function(){return this.selection.length==1?this.selection[0]:null},highlight_row:function(a,b){if(this.rows[a]&&!b){if(this.selection.length>1||!this.in_selection(a))this.clear_selection(), +this.selection[0]=a,$(this.rows[a].obj).addClass("selected")}else if(this.rows[a])if(this.in_selection(a)){var c=$.inArray(a,this.selection),d=this.selection.slice(0,c),c=this.selection.slice(c+1,this.selection.length);this.selection=d.concat(c);$(this.rows[a].obj).removeClass("selected").removeClass("unfocused")}else this.selection[this.selection.length]=a,$(this.rows[a].obj).addClass("selected")},key_press:function(a){if(this.focused!=!0)return!0;var b=rcube_event.get_keycode(a),c=rcube_event.get_modifier(a); +switch(b){case 40:case 38:case 63233:case 63232:return rcube_event.cancel(a),this.use_arrow_key(b,c);case 61:case 107:case 109:case 32:return rcube_event.cancel(a),a=this.use_plusminus_key(b,c),this.key_pressed=b,this.triggerEvent("keypress"),a;case 36:return this.select_first(c),rcube_event.cancel(a);case 35:return this.select_last(c),rcube_event.cancel(a);default:if(this.shiftkey=a.shiftKey,this.key_pressed=b,this.triggerEvent("keypress"),this.key_pressed==this.BACKSPACE_KEY)return rcube_event.cancel(a)}return!0}, +key_down:function(a){switch(rcube_event.get_keycode(a)){case 27:if(this.drag_active)return this.drag_mouse_up(a);if(this.col_drag_active)return this.selected_column=null,this.column_drag_mouse_up(a);case 40:case 38:case 63233:case 63232:case 61:case 107:case 109:case 32:if(!rcube_event.get_modifier(a)&&this.focused)return rcube_event.cancel(a)}return!0},use_arrow_key:function(a,b){var c;if(a==40||a==63233)c=this.get_next_row();else if(a==38||a==63232)c=this.get_prev_row();c&&(this.select_row(c.uid, +b,!0),this.scrollto(c.uid));return!1},use_plusminus_key:function(a,b){var c=this.rows[this.last_selected];if(c)return a==32&&(a=c.expanded?109:61),a==61||a==107?b==CONTROL_KEY||this.multiexpand?this.expand_all(c):this.expand(c):b==CONTROL_KEY||this.multiexpand?this.collapse_all(c):this.collapse(c),this.update_expando(c.uid,c.expanded),!1},scrollto:function(a){var b=this.rows[a].obj;if(b&&this.frame){var c=Number(b.offsetTop);!c&&this.rows[a].parent_uid&&(this.expand_all(this.rows[this.find_root(this.rows[a].uid)]), +c=Number(b.offsetTop));if(cNumber(this.frame.scrollTop)+Number(this.frame.offsetHeight))this.frame.scrollTop=c+Number(b.offsetHeight)-Number(this.frame.offsetHeight)}},drag_mouse_move:function(a){if(a.type=="touchmove")if(a.changedTouches.length==1)a=rcube_event.touchevent(a.changedTouches[0]);else return rcube_event.cancel(a);if(this.drag_start){var b=rcube_event.get_mouse_pos(a);if(!this.drag_mouse_start||Math.abs(b.x- +this.drag_mouse_start.x)<3&&Math.abs(b.y-this.drag_mouse_start.y)<3)return!1;if(!this.draglayer)this.draglayer=$("
    ").attr("id","rcmdraglayer").css({position:"absolute",display:"none","z-index":2E3}).appendTo(document.body);var c,d,e=$.merge([],this.selection);for(c in e)d=e[c],this.rows[d].has_children&&!this.rows[d].expanded&&this.select_childs(d);this.draglayer.html("");for(c=0;c12){this.draglayer.append("...");break}if(e=this.rows[this.selection[c]].obj)for(d= +b=0;d=0&&this.subject_col==b){for(var f,g,h=e.childNodes[d].childNodes,b=0;b50?d.substring(0,50)+"...":d;this.draglayer.append($("
    ").text(d));break}b++}}this.draglayer.show();this.drag_active=!0;this.triggerEvent("dragstart")}this.drag_active&& +this.draglayer&&(c=rcube_event.get_mouse_pos(a),this.draglayer.css({left:c.x+20+"px",top:c.y-5+(bw.ie?document.documentElement.scrollTop:0)+"px"}),this.triggerEvent("dragmove",a?a:window.event));return this.drag_start=!1},drag_mouse_up:function(a){document.onmousemove=null;if(a.type=="touchend"&&a.changedTouches.length!=1)return rcube_event.cancel(a);this.draglayer&&this.draglayer.is(":visible")&&(this.drag_start_pos?this.draglayer.animate(this.drag_start_pos,300,"swing").hide(20):this.draglayer.hide()); +this.drag_active&&this.focus();this.drag_active=!1;rcube_event.remove_listener({event:"mousemove",object:this,method:"drag_mouse_move"});rcube_event.remove_listener({event:"mouseup",object:this,method:"drag_mouse_up"});if(bw.iphone||bw.ipad)rcube_event.remove_listener({event:"touchmove",object:this,method:"drag_mouse_move"}),rcube_event.remove_listener({event:"touchend",object:this,method:"drag_mouse_up"});this.del_dragfix();this.triggerEvent("dragend");return rcube_event.cancel(a)},column_drag_mouse_move:function(a){if(this.drag_start){var b; +b=rcube_event.get_mouse_pos(a);if(!this.drag_mouse_start||Math.abs(b.x-this.drag_mouse_start.x)<3&&Math.abs(b.y-this.drag_mouse_start.y)<3)return!1;if(!this.col_draglayer){b=$(this.list).offset();var c=this.list.tHead.rows[0].cells;this.col_draglayer=$("
    ").attr("id","rcmcoldraglayer").css(b).css({position:"absolute","z-index":2001,"background-color":"white",opacity:0.75,height:this.frame.offsetHeight-2+"px",width:this.frame.offsetWidth-2+"px"}).appendTo(document.body).append($("
    ").attr("id", +"rcmcolumnindicator").css({position:"absolute","border-right":"2px dotted #555","z-index":2002,height:this.frame.offsetHeight-2+"px"}));this.cols=[];this.list_pos=this.list_min_pos=b.left;for(b=0;b=this.cols[b]/2+this.list_pos+c)c+=this.cols[b];else break;b==0&&this.list_min_pos>d.x?c=this.list_min_pos-this.list_pos:!this.list.rowcount&&b==this.cols.length&&(c-=2);$("#rcmcolumnindicator").css({width:c+"px"});this.triggerEvent("column_dragmove",a?a:window.event)}return this.drag_start=!1},column_drag_mouse_up:function(a){document.onmousemove=null;if(this.col_draglayer)this.col_draglayer.remove(),this.col_draglayer=null;this.col_drag_active&&this.focus();this.col_drag_active= +!1;rcube_event.remove_listener({event:"mousemove",object:this,method:"column_drag_mouse_move"});rcube_event.remove_listener({event:"mouseup",object:this,method:"column_drag_mouse_up"});this.del_dragfix();if(this.selected_column!==null&&this.cols&&this.cols.length){var b,c=0,d=rcube_event.get_mouse_pos(a);for(b=0;b=this.cols[b]/2+this.list_pos+c)c+=this.cols[b];else break;b!=this.selected_column&&b!=this.selected_column+1&&this.column_replace(this.selected_column,b)}this.triggerEvent("column_dragend"); +return rcube_event.cancel(a)},add_dragfix:function(){$("iframe").each(function(){$('
    ').css({background:"#fff",width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1E3}).css($(this).offset()).appendTo(document.body)})},del_dragfix:function(){$("div.iframe-dragdrop-fix").each(function(){this.parentNode.removeChild(this)})},column_replace:function(a,b){var c;c=this.list.tHead.rows[0].cells;var d=c[a],e=c[b],f=document.createElement("td"); +e?c[0].parentNode.insertBefore(f,e):c[0].parentNode.appendChild(f);c[0].parentNode.replaceChild(d,f);r=0;for(c=this.list.tBodies[0].rows.length;ra?b-1:b:this.subject_cola&&b>=this.subject_col&&this.subject_col--;this.triggerEvent("column_replace")}}; +rcube_list_widget.prototype.addEventListener=rcube_event_engine.prototype.addEventListener;rcube_list_widget.prototype.removeEventListener=rcube_event_engine.prototype.removeEventListener;rcube_list_widget.prototype.triggerEvent=rcube_event_engine.prototype.triggerEvent; diff --git a/program/js/list.js.src b/program/js/list.js.src index b028875..78cf994 100644 --- a/program/js/list.js.src +++ b/program/js/list.js.src @@ -13,7 +13,7 @@ | Requires: common.js | +-----------------------------------------------------------------------+ - $Id: list.js 4343 2010-12-16 09:26:30Z alec $ + $Id: list.js 4666 2011-04-17 09:34:02Z alec $ */ @@ -102,8 +102,8 @@ init_row: function(row) { // make references in internal array and set event handlers if (row && String(row.id).match(/rcmrow([a-z0-9\-_=\+\/]+)/i)) { - var self = this; - var uid = RegExp.$1; + var self = this, + uid = RegExp.$1; row.uid = uid; this.rows[uid] = {uid:uid, id:row.id, obj:row}; @@ -170,6 +170,10 @@ clear: function(sel) if (sel) this.clear_selection(); + + // reset scroll position (in Opera) + if (this.frame) + this.frame.scrollTop = 0; }, @@ -212,10 +216,10 @@ insert_row: function(row, attop) */ focus: function(e) { - var id; + var n, id; this.focused = true; - for (var n in this.selection) { + for (n in this.selection) { id = this.selection[n]; if (this.rows[id] && this.rows[id].obj) { $(this.rows[id].obj).addClass('selected').removeClass('unfocused'); @@ -236,9 +240,9 @@ focus: function(e) */ blur: function() { - var id; + var n, id; this.focused = false; - for (var n in this.selection) { + for (n in this.selection) { id = this.selection[n]; if (this.rows[id] && this.rows[id].obj) { $(this.rows[id].obj).removeClass('selected').addClass('unfocused'); @@ -430,8 +434,7 @@ collapse: function(row) expand: function(row) { - var depth, new_row; - var last_expanded_parent_depth; + var r, p, depth, new_row, last_expanded_parent_depth; if (row) { row.expanded = true; @@ -449,13 +452,13 @@ expand: function(row) while (new_row) { if (new_row.nodeType == 1) { - var r = this.rows[new_row.uid]; + r = this.rows[new_row.uid]; if (r) { if (row && (!r.depth || r.depth <= depth)) break; if (r.parent_uid) { - var p = this.rows[r.parent_uid]; + p = this.rows[r.parent_uid]; if (p && p.expanded) { if ((row && p == row) || last_expanded_parent_depth >= p.depth - 1) { last_expanded_parent_depth = p.depth; @@ -696,9 +699,10 @@ select: function(id) */ select_next: function() { - var next_row = this.get_next_row(); - var prev_row = this.get_prev_row(); - var new_row = (next_row) ? next_row : prev_row; + var 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); }, @@ -710,13 +714,16 @@ select_next: function() select_first: function(mod_key) { var row = this.get_first_row(); - if (row && mod_key) { - this.shift_select(row, mod_key); - this.triggerEvent('select'); - this.scrollto(row); + if (row) { + if (mod_key) { + this.shift_select(row, mod_key); + this.triggerEvent('select'); + this.scrollto(row); + } + else { + this.select(row); + } } - else if (row) - this.select(row); }, @@ -726,13 +733,16 @@ select_first: function(mod_key) select_last: function(mod_key) { var row = this.get_last_row(); - if (row && mod_key) { - this.shift_select(row, mod_key); - this.triggerEvent('select'); - this.scrollto(row); + if (row) { + if (mod_key) { + this.shift_select(row, mod_key); + this.triggerEvent('select'); + this.scrollto(row); + } + else { + this.select(row); + } } - else if (row) - this.select(row); }, @@ -744,8 +754,9 @@ select_childs: function(uid) if (!this.rows[uid] || !this.rows[uid].has_children) return; - var depth = this.rows[uid].depth; - var row = this.rows[uid].obj.nextSibling; + var depth = this.rows[uid].depth, + row = this.rows[uid].obj.nextSibling; + while (row) { if (row.nodeType == 1) { if ((r = this.rows[row.uid])) { @@ -768,20 +779,20 @@ shift_select: function(id, control) if (!this.rows[this.shift_start] || !this.selection.length) this.shift_start = id; - var from_rowIndex = this.rows[this.shift_start].obj.rowIndex, + var n, from_rowIndex = this.rows[this.shift_start].obj.rowIndex, to_rowIndex = this.rows[id].obj.rowIndex, i = ((from_rowIndex < to_rowIndex)? from_rowIndex : to_rowIndex), j = ((from_rowIndex > to_rowIndex)? from_rowIndex : to_rowIndex); // iterate through the entire message list - for (var n in this.rows) { + for (n in this.rows) { if (this.rows[n].obj.rowIndex >= i && this.rows[n].obj.rowIndex <= j) { if (!this.in_selection(n)) { this.highlight_row(n, true); } } else { - if (this.in_selection(n) && !control) { + if (this.in_selection(n) && !control) { this.highlight_row(n, true); } } @@ -794,7 +805,7 @@ shift_select: function(id, control) */ in_selection: function(id) { - for(var n in this.selection) + for (var n in this.selection) if (this.selection[n]==id) return true; @@ -811,10 +822,10 @@ select_all: function(filter) return false; // reset but remember selection first - var select_before = this.selection.join(','); + var n, select_before = this.selection.join(','); this.selection = []; - for (var n in this.rows) { + for (n in this.rows) { if (!filter || this.rows[n][filter] == true) { this.last_selected = n; this.highlight_row(n, true); @@ -843,9 +854,9 @@ invert_selection: function() return false; // remember old selection - var select_before = this.selection.join(','); + var n, select_before = this.selection.join(','); - for (var n in this.rows) + for (n in this.rows) this.highlight_row(n, true); // trigger event if selection changed @@ -863,11 +874,11 @@ invert_selection: function() */ clear_selection: function(id) { - var num_select = this.selection.length; + var n, num_select = this.selection.length; // one row if (id) { - for (var n in this.selection) + for (n in this.selection) if (this.selection[n] == id) { this.selection.splice(n,1); break; @@ -875,7 +886,7 @@ clear_selection: function(id) } // all rows else { - for (var n in this.selection) + for (n in this.selection) if (this.rows[this.selection[n]]) { $(this.rows[this.selection[n]].obj).removeClass('selected').removeClass('unfocused'); } @@ -927,9 +938,10 @@ highlight_row: function(id, multiple) $(this.rows[id].obj).addClass('selected'); } else { // unselect row - var p = $.inArray(id, this.selection); - var a_pre = this.selection.slice(0, p); - var a_post = this.selection.slice(p+1, this.selection.length); + var p = $.inArray(id, this.selection), + a_pre = this.selection.slice(0, p), + a_post = this.selection.slice(p+1, this.selection.length); + this.selection = a_pre.concat(a_post); $(this.rows[id].obj).removeClass('selected').removeClass('unfocused'); } @@ -945,8 +957,8 @@ key_press: function(e) if (this.focused != true) return true; - var keyCode = rcube_event.get_keycode(e); - var mod_key = rcube_event.get_modifier(e); + var keyCode = rcube_event.get_keycode(e), + mod_key = rcube_event.get_modifier(e); switch (keyCode) { case 40: @@ -1371,7 +1383,7 @@ del_dragfix: function() */ column_replace: function(from, to) { - var cells = this.list.tHead.rows[0].cells, + var len, cells = this.list.tHead.rows[0].cells, elem = cells[from], before = cells[to], td = document.createElement('td'); @@ -1384,7 +1396,7 @@ column_replace: function(from, to) cells[0].parentNode.replaceChild(elem, td); // replace list cells - for (r=0; r - -
    -
    {#emotions_dlg.title}:

    + + +
    +
    {#emotions_dlg.title}:

    - - +
    + - - + + - - + + - - + + - -
    {#emotions_dlg.cool} {#emotions_dlg.cry} {#emotions_dlg.embarassed} {#emotions_dlg.foot_in_mouth}
    {#emotions_dlg.frown} {#emotions_dlg.innocent} {#emotions_dlg.kiss} {#emotions_dlg.laughing}
    {#emotions_dlg.money_mouth} {#emotions_dlg.sealed} {#emotions_dlg.smile} {#emotions_dlg.surprised}
    {#emotions_dlg.tongue-out} {#emotions_dlg.undecided} {#emotions_dlg.wink} {#emotions_dlg.yell}
    -
    + + +
    diff --git a/program/js/tiny_mce/plugins/media/css/media.css b/program/js/tiny_mce/plugins/media/css/media.css index 2d08794..0c45c7f 100644 --- a/program/js/tiny_mce/plugins/media/css/media.css +++ b/program/js/tiny_mce/plugins/media/css/media.css @@ -1,12 +1,12 @@ -#id, #name, #hspace, #vspace, #class_name, #align { width: 100px } +#id, #name, #hspace, #vspace, #class_name, #align { width: 100px } #hspace, #vspace { width: 50px } #flash_quality, #flash_align, #flash_scale, #flash_salign, #flash_wmode { width: 100px } -#flash_base, #flash_flashvars { width: 240px } +#flash_base, #flash_flashvars, #html5_altsource1, #html5_altsource2, #html5_poster { width: 240px } #width, #height { width: 40px } #src, #media_type { width: 250px } #class { width: 120px } -#prev { margin: 0; border: 1px solid black; width: 380px; height: 230px; overflow: auto } -.panel_wrapper div.current { height: 390px; overflow: auto } +#prev { margin: 0; border: 1px solid black; width: 380px; height: 260px; overflow: auto } +.panel_wrapper div.current { height: 420px; overflow: auto } #flash_options, #shockwave_options, #qt_options, #wmp_options, #rmp_options { display: none } .mceAddSelectValue { background-color: #DDDDDD } #qt_starttime, #qt_endtime, #qt_fov, #qt_href, #qt_moveid, #qt_moviename, #qt_node, #qt_pan, #qt_qtsrc, #qt_qtsrcchokespeed, #qt_target, #qt_tilt, #qt_urlsubstituten, #qt_volume { width: 70px } @@ -14,3 +14,4 @@ #rmp_console, #rmp_numloop, #rmp_controls, #rmp_scriptcallbacks { width: 70px } #shockwave_swvolume, #shockwave_swframe, #shockwave_swurl, #shockwave_swstretchvalign, #shockwave_swstretchhalign, #shockwave_swstretchstyle { width: 90px } #qt_qtsrc { width: 200px } +iframe {border: 1px solid gray} diff --git a/program/js/tiny_mce/plugins/media/editor_plugin.js b/program/js/tiny_mce/plugins/media/editor_plugin.js index 4bbe367..6621907 100644 --- a/program/js/tiny_mce/plugins/media/editor_plugin.js +++ b/program/js/tiny_mce/plugins/media/editor_plugin.js @@ -1 +1 @@ -(function(){var a=tinymce.each;tinymce.create("tinymce.plugins.MediaPlugin",{init:function(b,c){var e=this;e.editor=b;e.url=c;function f(g){return/^(mceItemFlash|mceItemShockWave|mceItemWindowsMedia|mceItemQuickTime|mceItemRealMedia)$/.test(g.className)}b.onPreInit.add(function(){b.serializer.addRules("param[name|value|_mce_value]")});b.addCommand("mceMedia",function(){b.windowManager.open({file:c+"/media.htm",width:430+parseInt(b.getLang("media.delta_width",0)),height:470+parseInt(b.getLang("media.delta_height",0)),inline:1},{plugin_url:c})});b.addButton("media",{title:"media.desc",cmd:"mceMedia"});b.onNodeChange.add(function(h,g,i){g.setActive("media",i.nodeName=="IMG"&&f(i))});b.onInit.add(function(){var g={mceItemFlash:"flash",mceItemShockWave:"shockwave",mceItemWindowsMedia:"windowsmedia",mceItemQuickTime:"quicktime",mceItemRealMedia:"realmedia"};b.selection.onSetContent.add(function(){e._spansToImgs(b.getBody())});b.selection.onBeforeSetContent.add(e._objectsToSpans,e);if(b.settings.content_css!==false){b.dom.loadCSS(c+"/css/content.css")}if(b.theme&&b.theme.onResolveName){b.theme.onResolveName.add(function(h,i){if(i.name=="img"){a(g,function(l,j){if(b.dom.hasClass(i.node,j)){i.name=l;i.title=b.dom.getAttrib(i.node,"title");return false}})}})}if(b&&b.plugins.contextmenu){b.plugins.contextmenu.onContextMenu.add(function(i,h,j){if(j.nodeName=="IMG"&&/mceItem(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)/.test(j.className)){h.add({title:"media.edit",icon:"media",cmd:"mceMedia"})}})}});b.onBeforeSetContent.add(e._objectsToSpans,e);b.onSetContent.add(function(){e._spansToImgs(b.getBody())});b.onPreProcess.add(function(g,i){var h=g.dom;if(i.set){e._spansToImgs(i.node);a(h.select("IMG",i.node),function(k){var j;if(f(k)){j=e._parse(k.title);h.setAttrib(k,"width",h.getAttrib(k,"width",j.width||100));h.setAttrib(k,"height",h.getAttrib(k,"height",j.height||100))}})}if(i.get){a(h.select("IMG",i.node),function(m){var l,j,k;if(g.getParam("media_use_script")){if(f(m)){m.className=m.className.replace(/mceItem/g,"mceTemp")}return}switch(m.className){case"mceItemFlash":l="d27cdb6e-ae6d-11cf-96b8-444553540000";j="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0";k="application/x-shockwave-flash";break;case"mceItemShockWave":l="166b1bca-3f9c-11cf-8075-444553540000";j="http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=8,5,1,0";k="application/x-director";break;case"mceItemWindowsMedia":l=g.getParam("media_wmp6_compatible")?"05589fa1-c356-11ce-bf01-00aa0055595a":"6bf52a52-394a-11d3-b153-00c04f79faa6";j="http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701";k="application/x-mplayer2";break;case"mceItemQuickTime":l="02bf25d5-8c17-4b23-bc80-d3488abddc6b";j="http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0";k="video/quicktime";break;case"mceItemRealMedia":l="cfcdaa03-8be4-11cf-b84b-0020afbbccfa";j="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0";k="audio/x-pn-realaudio-plugin";break}if(l){h.replace(e._buildObj({classid:l,codebase:j,type:k},m),m)}})}});b.onPostProcess.add(function(g,h){h.content=h.content.replace(/_mce_value=/g,"value=")});function d(g,h){h=new RegExp(h+'="([^"]+)"',"g").exec(g);return h?b.dom.decode(h[1]):""}b.onPostProcess.add(function(g,h){if(g.getParam("media_use_script")){h.content=h.content.replace(/]+>/g,function(j){var i=d(j,"class");if(/^(mceTempFlash|mceTempShockWave|mceTempWindowsMedia|mceTempQuickTime|mceTempRealMedia)$/.test(i)){at=e._parse(d(j,"title"));at.width=d(j,"width");at.height=d(j,"height");j=''; - } + if (!url) + return url; - return im; - }); - } - }); + if (force_absolute) + return editor.documentBaseURI.toAbsolute(url); + + return urlConverter.call(urlConverterScope, url, 'src', 'object'); }, getInfo : function() { @@ -202,210 +220,548 @@ }; }, - // Private methods - _objectsToSpans : function(ed, o) { - var t = this, h = o.content; + /** + * Converts the JSON data object to an img node. + */ + dataToImg : function(data, force_absolute) { + var self = this, editor = self.editor, baseUri = editor.documentBaseURI, sources, attrs, img, i; + + data.params.src = self.convertUrl(data.params.src, force_absolute); - h = h.replace(/]*>\s*write(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)\(\{([^\)]*)\}\);\s*<\/script>/gi, function(a, b, c) { - var o = t._parse(c); + attrs = data.video.attrs; + if (attrs) + attrs.src = self.convertUrl(attrs.src, force_absolute); - return '' + if (attrs) + attrs.poster = self.convertUrl(attrs.poster, force_absolute); + + sources = toArray(data.video.sources); + if (sources) { + for (i = 0; i < sources.length; i++) + sources[i].src = self.convertUrl(sources[i].src, force_absolute); + } + + img = self.editor.dom.create('img', { + id : data.id, + style : data.style, + align : data.align, + src : self.editor.theme.url + '/img/trans.gif', + 'class' : 'mceItemMedia mceItem' + self.getType(data.type).name, + 'data-mce-json' : JSON.serialize(data, "'") }); - h = h.replace(/]*)>/gi, ''); - h = h.replace(/]*)\/?>/gi, ''); - h = h.replace(/]*)>/gi, ''); - h = h.replace(/<\/(object)([^>]*)>/gi, ''); - h = h.replace(/<\/embed>/gi, ''); - h = h.replace(/]*)>/gi, function(a, b) {return ''}); - h = h.replace(/\/ class=\"mceItemParam\"><\/span>/gi, 'class="mceItemParam">'); + img.width = data.width || "320"; + img.height = data.height || "240"; - o.content = h; + return img; }, - _buildObj : function(o, n) { - var ob, ed = this.editor, dom = ed.dom, p = this._parse(n.title), stc; - - stc = ed.getParam('media_strict', true) && o.type == 'application/x-shockwave-flash'; - - p.width = o.width = dom.getAttrib(n, 'width') || 100; - p.height = o.height = dom.getAttrib(n, 'height') || 100; - - if (p.src) - p.src = ed.convertURL(p.src, 'src', n); - - if (stc) { - ob = dom.create('span', { - id : p.id, - _mce_name : 'object', - type : 'application/x-shockwave-flash', - data : p.src, - style : dom.getAttrib(n, 'style'), - width : o.width, - height : o.height - }); - } else { - ob = dom.create('span', { - id : p.id, - _mce_name : 'object', - classid : "clsid:" + o.classid, - style : dom.getAttrib(n, 'style'), - codebase : o.codebase, - width : o.width, - height : o.height + /** + * Converts the JSON data object to a HTML string. + */ + dataToHtml : function(data, force_absolute) { + return this.editor.serializer.serialize(this.dataToImg(data, force_absolute), {force_absolute : force_absolute}); + }, + + /** + * Converts the JSON data object to a HTML string. + */ + htmlToData : function(html) { + var fragment, img, data; + + data = { + type : 'flash', + video: {sources:[]}, + params: {} + }; + + fragment = this.editor.parser.parse(html); + img = fragment.getAll('img')[0]; + + if (img) { + data = JSON.parse(img.attr('data-mce-json')); + data.type = this.getType(img.attr('class')).name.toLowerCase(); + + // Add some extra properties to the data object + tinymce.each(rootAttributes, function(name) { + var value = img.attr(name); + + if (value) + data[name] = value; }); } - each (p, function(v, k) { - if (!/^(width|height|codebase|classid|id|_cx|_cy)$/.test(k)) { - // Use url instead of src in IE for Windows media - if (o.type == 'application/x-mplayer2' && k == 'src' && !p.url) - k = 'url'; + return data; + }, + + /** + * Get type item by extension, class, clsid or mime type. + * + * @method getType + * @param {String} value Value to get type item by. + * @return {Object} Type item object or undefined. + */ + getType : function(value) { + var i, values, typeItem; + + // Find type by checking the classes + values = tinymce.explode(value, ' '); + for (i = 0; i < values.length; i++) { + typeItem = this.lookup[values[i]]; + + if (typeItem) + return typeItem; + } + }, + + /** + * Converts a tinymce.html.Node image element to video/object/embed. + */ + imgToObject : function(node, args) { + var self = this, editor = self.editor, video, object, embed, iframe, name, value, data, + source, sources, params, param, typeItem, i, item, mp4Source, replacement, + posterSrc, style; + + // Adds the flash player + function addPlayer(video_src, poster_src) { + var baseUri, flashVars, flashVarsOutput, params, flashPlayer; + + flashPlayer = editor.getParam('flash_video_player_url', self.convertUrl(self.url + '/moxieplayer.swf')); + if (flashPlayer) { + baseUri = editor.documentBaseURI; + data.params.src = flashPlayer; + + // Convert the movie url to absolute urls + if (editor.getParam('flash_video_player_absvideourl', true)) { + video_src = baseUri.toAbsolute(video_src || '', true); + poster_src = baseUri.toAbsolute(poster_src || '', true); + } + + // Generate flash vars + flashVarsOutput = ''; + flashVars = editor.getParam('flash_video_player_flashvars', {url : '$url', poster : '$poster'}); + tinymce.each(flashVars, function(value, name) { + // Replace $url and $poster variables in flashvars value + value = value.replace(/\$url/, video_src || ''); + value = value.replace(/\$poster/, poster_src || ''); + + if (value.length > 0) + flashVarsOutput += (flashVarsOutput ? '&' : '') + name + '=' + escape(value); + }); + + if (flashVarsOutput.length) + data.params.flashvars = flashVarsOutput; - if (v) - dom.add(ob, 'span', {_mce_name : 'param', name : k, '_mce_value' : v}); + params = editor.getParam('flash_video_player_params', { + allowfullscreen: true, + allowscriptaccess: true + }); + + tinymce.each(params, function(value, name) { + data.params[name] = "" + value; + }); } - }); + }; - if (!stc) - dom.add(ob, 'span', tinymce.extend({_mce_name : 'embed', type : o.type, style : dom.getAttrib(n, 'style')}, p)); + data = JSON.parse(node.attr('data-mce-json')); + typeItem = this.getType(node.attr('class')); - return ob; - }, + style = node.attr('data-mce-style') + if (!style) { + style = node.attr('style'); - _spansToImgs : function(p) { - var t = this, dom = t.editor.dom, im, ci; + if (style) + style = editor.dom.serializeStyle(editor.dom.parseStyle(style, 'img')); + } - each(dom.select('span', p), function(n) { - // Convert object into image - if (dom.getAttrib(n, 'class') == 'mceItemObject') { - ci = dom.getAttrib(n, "classid").toLowerCase().replace(/\s+/g, ''); + // Handle iframe + if (typeItem.name === 'Iframe') { + replacement = new Node('iframe', 1); - switch (ci) { - case 'clsid:d27cdb6e-ae6d-11cf-96b8-444553540000': - dom.replace(t._createImg('mceItemFlash', n), n); - break; + tinymce.each(rootAttributes, function(name) { + var value = node.attr(name); - case 'clsid:166b1bca-3f9c-11cf-8075-444553540000': - dom.replace(t._createImg('mceItemShockWave', n), n); - break; + if (name == 'class' && value) + value = value.replace(/mceItem.+ ?/g, ''); - case 'clsid:6bf52a52-394a-11d3-b153-00c04f79faa6': - case 'clsid:22d6f312-b0f6-11d0-94ab-0080c74c7e95': - case 'clsid:05589fa1-c356-11ce-bf01-00aa0055595a': - dom.replace(t._createImg('mceItemWindowsMedia', n), n); - break; + if (value && value.length > 0) + replacement.attr(name, value); + }); - case 'clsid:02bf25d5-8c17-4b23-bc80-d3488abddc6b': - dom.replace(t._createImg('mceItemQuickTime', n), n); - break; + for (name in data.params) + replacement.attr(name, data.params[name]); - case 'clsid:cfcdaa03-8be4-11cf-b84b-0020afbbccfa': - dom.replace(t._createImg('mceItemRealMedia', n), n); - break; + replacement.attr({ + style: style, + src: data.params.src + }); - default: - dom.replace(t._createImg('mceItemFlash', n), n); - } - - return; + node.replace(replacement); + + return; + } + + // Handle scripts + if (this.editor.settings.media_use_script) { + replacement = new Node('script', 1).attr('type', 'text/javascript'); + + value = new Node('#text', 3); + value.value = 'write' + typeItem.name + '(' + JSON.serialize(tinymce.extend(data.params, { + width: node.attr('width'), + height: node.attr('height') + })) + ');'; + + replacement.append(value); + node.replace(replacement); + + return; + } + + // Add HTML5 video element + if (typeItem.name === 'Video' && data.video.sources[0]) { + // Create new object element + video = new Node('video', 1).attr(tinymce.extend({ + id : node.attr('id'), + width: node.attr('width'), + height: node.attr('height'), + style : style + }, data.video.attrs)); + + // Get poster source and use that for flash fallback + if (data.video.attrs) + posterSrc = data.video.attrs.poster; + + sources = data.video.sources = toArray(data.video.sources); + for (i = 0; i < sources.length; i++) { + if (/\.mp4$/.test(sources[i].src)) + mp4Source = sources[i].src; } - // Convert embed into image - if (dom.getAttrib(n, 'class') == 'mceItemEmbed') { - switch (dom.getAttrib(n, 'type')) { - case 'application/x-shockwave-flash': - dom.replace(t._createImg('mceItemFlash', n), n); - break; + if (!sources[0].type) { + video.attr('src', sources[0].src); + sources.splice(0, 1); + } - case 'application/x-director': - dom.replace(t._createImg('mceItemShockWave', n), n); - break; + for (i = 0; i < sources.length; i++) { + source = new Node('source', 1).attr(sources[i]); + source.shortEnded = true; + video.append(source); + } - case 'application/x-mplayer2': - dom.replace(t._createImg('mceItemWindowsMedia', n), n); - break; + // Create flash fallback for video if we have a mp4 source + if (mp4Source) { + addPlayer(mp4Source, posterSrc); + typeItem = self.getType('flash'); + } else + data.params.src = ''; + } - case 'video/quicktime': - dom.replace(t._createImg('mceItemQuickTime', n), n); - break; + // Do we have a params src then we can generate object + if (data.params.src) { + // Is flv movie add player for it + if (/\.flv$/i.test(data.params.src)) + addPlayer(data.params.src, ''); + + if (args && args.force_absolute) + data.params.src = editor.documentBaseURI.toAbsolute(data.params.src); + + // Create new object element + object = new Node('object', 1).attr({ + id : node.attr('id'), + width: node.attr('width'), + height: node.attr('height'), + style : style + }); - case 'audio/x-pn-realaudio-plugin': - dom.replace(t._createImg('mceItemRealMedia', n), n); - break; + tinymce.each(rootAttributes, function(name) { + if (data[name] && name != 'type') + object.attr(name, data[name]); + }); - default: - dom.replace(t._createImg('mceItemFlash', n), n); - } - } - }); + // Add params + for (name in data.params) { + param = new Node('param', 1); + param.shortEnded = true; + value = data.params[name]; + + // Windows media needs to use url instead of src for the media URL + if (name === 'src' && typeItem.name === 'WindowsMedia') + name = 'url'; + + param.attr({name: name, value: value}); + object.append(param); + } + + // Setup add type and classid if strict is disabled + if (this.editor.getParam('media_strict', true)) { + object.attr({ + data: data.params.src, + type: typeItem.mimes[0] + }); + } else { + object.attr({ + classid: "clsid:" + typeItem.clsids[0], + codebase: typeItem.codebase + }); + + embed = new Node('embed', 1); + embed.shortEnded = true; + embed.attr({ + id: node.attr('id'), + width: node.attr('width'), + height: node.attr('height'), + style : style, + type: typeItem.mimes[0] + }); + + for (name in data.params) + embed.attr(name, data.params[name]); + + tinymce.each(rootAttributes, function(name) { + if (data[name] && name != 'type') + embed.attr(name, data[name]); + }); + + object.append(embed); + } + + // Insert raw HTML + if (data.object_html) { + value = new Node('#text', 3); + value.raw = true; + value.value = data.object_html; + object.append(value); + } + + // Append object to video element if it exists + if (video) + video.append(object); + } + + if (video) { + // Insert raw HTML + if (data.video_html) { + value = new Node('#text', 3); + value.raw = true; + value.value = data.video_html; + video.append(value); + } + } + + if (video || object) + node.replace(video || object); + else + node.remove(); }, - _createImg : function(cl, n) { - var im, dom = this.editor.dom, pa = {}, ti = '', args; + /** + * Converts a tinymce.html.Node video/object/embed to an img element. + * + * The video/object/embed will be converted into an image placeholder with a JSON data attribute like this: + * + * + * The JSON structure will be like this: + * {'params':{'flashvars':'something','quality':'high','src':'someurl'}, 'video':{'sources':[{src: 'someurl', type: 'video/mp4'}]}} + */ + objectToImg : function(node) { + var object, embed, video, iframe, img, name, id, width, height, style, i, html, + param, params, source, sources, data, type, lookup = this.lookup, + matches, attrs, urlConverter = this.editor.settings.url_converter, + urlConverterScope = this.editor.settings.url_converter_scope; + + function getInnerHTML(node) { + return new tinymce.html.Serializer({ + inner: true, + validate: false + }).serialize(node); + }; - args = ['id', 'name', 'width', 'height', 'bgcolor', 'align', 'flashvars', 'src', 'wmode', 'allowfullscreen', 'quality', 'data']; + // If node isn't in document + if (!node.parent) + return; - // Create image - im = dom.create('img', { - src : this.url + '/img/trans.gif', - width : dom.getAttrib(n, 'width') || 100, - height : dom.getAttrib(n, 'height') || 100, - style : dom.getAttrib(n, 'style'), - 'class' : cl - }); + // Handle media scripts + if (node.name === 'script') { + if (node.firstChild) + matches = scriptRegExp.exec(node.firstChild.value); - // Setup base parameters - each(args, function(na) { - var v = dom.getAttrib(n, na); + if (!matches) + return; - if (v) - pa[na] = v; - }); + type = matches[1]; + data = {video : {}, params : JSON.parse(matches[2])}; + width = data.params.width; + height = data.params.height; + } + + // Setup data objects + data = data || { + video : {}, + params : {} + }; - // Add optional parameters - each(dom.select('span', n), function(n) { - if (dom.hasClass(n, 'mceItemParam')) - pa[dom.getAttrib(n, 'name')] = dom.getAttrib(n, '_mce_value'); + // Setup new image object + img = new Node('img', 1); + img.attr({ + src : this.editor.theme.url + '/img/trans.gif' }); - // Use src not movie - if (pa.movie) { - pa.src = pa.movie; - delete pa.movie; + // Video element + name = node.name; + if (name === 'video') { + video = node; + object = node.getAll('object')[0]; + embed = node.getAll('embed')[0]; + width = video.attr('width'); + height = video.attr('height'); + id = video.attr('id'); + data.video = {attrs : {}, sources : []}; + + // Get all video attributes + attrs = data.video.attrs; + for (name in video.attributes.map) + attrs[name] = video.attributes.map[name]; + + source = node.attr('src'); + if (source) + data.video.sources.push({src : urlConverter.call(urlConverterScope, source, 'src', 'video')}); + + // Get all sources + sources = video.getAll("source"); + for (i = 0; i < sources.length; i++) { + source = sources[i].remove(); + + data.video.sources.push({ + src: urlConverter.call(urlConverterScope, source.attr('src'), 'src', 'source'), + type: source.attr('type'), + media: source.attr('media') + }); + } + + // Convert the poster URL + if (attrs.poster) + attrs.poster = urlConverter.call(urlConverterScope, attrs.poster, 'poster', 'video'); + } + + // Object element + if (node.name === 'object') { + object = node; + embed = node.getAll('embed')[0]; + } + + // Embed element + if (node.name === 'embed') + embed = node; + + // Iframe element + if (node.name === 'iframe') { + iframe = node; + type = 'Iframe'; + } + + if (object) { + // Get width/height + width = width || object.attr('width'); + height = height || object.attr('height'); + style = style || object.attr('style'); + id = id || object.attr('id'); + + // Get all object params + params = object.getAll("param"); + for (i = 0; i < params.length; i++) { + param = params[i]; + name = param.remove().attr('name'); + + if (!excludedAttrs[name]) + data.params[name] = param.attr('value'); + } + + data.params.src = data.params.src || object.attr('data'); } - // No src try data - if (!pa.src) { - pa.src = pa.data; - delete pa.data; + if (embed) { + // Get width/height + width = width || embed.attr('width'); + height = height || embed.attr('height'); + style = style || embed.attr('style'); + id = id || embed.attr('id'); + + // Get all embed attributes + for (name in embed.attributes.map) { + if (!excludedAttrs[name] && !data.params[name]) + data.params[name] = embed.attributes.map[name]; + } } - // Merge with embed args - n = dom.select('.mceItemEmbed', n)[0]; - if (n) { - each(args, function(na) { - var v = dom.getAttrib(n, na); + if (iframe) { + // Get width/height + width = iframe.attr('width'); + height = iframe.attr('height'); + style = style || iframe.attr('style'); + id = iframe.attr('id'); - if (v && !pa[na]) - pa[na] = v; + tinymce.each(rootAttributes, function(name) { + img.attr(name, iframe.attr(name)); }); + + // Get all iframe attributes + for (name in iframe.attributes.map) { + if (!excludedAttrs[name] && !data.params[name]) + data.params[name] = iframe.attributes.map[name]; + } } - delete pa.width; - delete pa.height; + // Use src not movie + if (data.params.movie) { + data.params.src = data.params.src || data.params.movie; + delete data.params.movie; + } - im.title = this._serialize(pa); + // Convert the URL to relative/absolute depending on configuration + if (data.params.src) + data.params.src = urlConverter.call(urlConverterScope, data.params.src, 'src', 'object'); - return im; - }, + if (video) + type = lookup.video.name; - _parse : function(s) { - return tinymce.util.JSON.parse('{' + s + '}'); - }, + if (object && !type) + type = (lookup[(object.attr('clsid') || '').toLowerCase()] || lookup[(object.attr('type') || '').toLowerCase()] || {}).name; - _serialize : function(o) { - return tinymce.util.JSON.serialize(o).replace(/[{}]/g, ''); + if (embed && !type) + type = (lookup[(embed.attr('type') || '').toLowerCase()] || {}).name; + + // Replace the video/object/embed element with a placeholder image containing the data + node.replace(img); + + // Remove embed + if (embed) + embed.remove(); + + // Serialize the inner HTML of the object element + if (object) { + html = getInnerHTML(object.remove()); + + if (html) + data.object_html = html; + } + + // Serialize the inner HTML of the video element + if (video) { + html = getInnerHTML(video.remove()); + + if (html) + data.video_html = html; + } + + // Set width/height of placeholder + img.attr({ + id : id, + 'class' : 'mceItemMedia mceItem' + (type || 'Flash'), + style : style, + width : width || "320", + height : height || "240", + "data-mce-json" : JSON.serialize(data, "'") + }); } }); diff --git a/program/js/tiny_mce/plugins/media/js/media.js b/program/js/tiny_mce/plugins/media/js/media.js index 86cfa98..30ad656 100644 --- a/program/js/tiny_mce/plugins/media/js/media.js +++ b/program/js/tiny_mce/plugins/media/js/media.js @@ -1,630 +1,354 @@ -tinyMCEPopup.requireLangPack(); +(function() { + var url; -var oldWidth, oldHeight, ed, url; + if (url = tinyMCEPopup.getParam("media_external_list_url")) + document.write(''); -if (url = tinyMCEPopup.getParam("media_external_list_url")) - document.write(''); - -function init() { - var pl = "", f, val; - var type = "flash", fe, i; - - ed = tinyMCEPopup.editor; - - tinyMCEPopup.resizeToInnerSize(); - f = document.forms[0] - - fe = ed.selection.getNode(); - if (/mceItem(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)/.test(ed.dom.getAttrib(fe, 'class'))) { - pl = fe.title; - - switch (ed.dom.getAttrib(fe, 'class')) { - case 'mceItemFlash': - type = 'flash'; - break; - - case 'mceItemFlashVideo': - type = 'flv'; - break; - - case 'mceItemShockWave': - type = 'shockwave'; - break; - - case 'mceItemWindowsMedia': - type = 'wmp'; - break; - - case 'mceItemQuickTime': - type = 'qt'; - break; - - case 'mceItemRealMedia': - type = 'rmp'; - break; - } - - document.forms[0].insert.value = ed.getLang('update', 'Insert', true); + function get(id) { + return document.getElementById(id); } - document.getElementById('filebrowsercontainer').innerHTML = getBrowserHTML('filebrowser','src','media','media'); - document.getElementById('qtsrcfilebrowsercontainer').innerHTML = getBrowserHTML('qtsrcfilebrowser','qt_qtsrc','media','media'); - document.getElementById('bgcolor_pickcontainer').innerHTML = getColorPickerHTML('bgcolor_pick','bgcolor'); - - var html = getMediaListHTML('medialist','src','media','media'); - if (html == "") - document.getElementById("linklistrow").style.display = 'none'; - else - document.getElementById("linklistcontainer").innerHTML = html; - - // Resize some elements - if (isVisible('filebrowser')) - document.getElementById('src').style.width = '230px'; - - // Setup form - if (pl != "") { - pl = tinyMCEPopup.editor.plugins.media._parse(pl); - - switch (type) { - case "flash": - setBool(pl, 'flash', 'play'); - setBool(pl, 'flash', 'loop'); - setBool(pl, 'flash', 'menu'); - setBool(pl, 'flash', 'swliveconnect'); - setStr(pl, 'flash', 'quality'); - setStr(pl, 'flash', 'scale'); - setStr(pl, 'flash', 'salign'); - setStr(pl, 'flash', 'wmode'); - setStr(pl, 'flash', 'base'); - setStr(pl, 'flash', 'flashvars'); - break; - - case "qt": - setBool(pl, 'qt', 'loop'); - setBool(pl, 'qt', 'autoplay'); - setBool(pl, 'qt', 'cache'); - setBool(pl, 'qt', 'controller'); - setBool(pl, 'qt', 'correction'); - setBool(pl, 'qt', 'enablejavascript'); - setBool(pl, 'qt', 'kioskmode'); - setBool(pl, 'qt', 'autohref'); - setBool(pl, 'qt', 'playeveryframe'); - setBool(pl, 'qt', 'tarsetcache'); - setStr(pl, 'qt', 'scale'); - setStr(pl, 'qt', 'starttime'); - setStr(pl, 'qt', 'endtime'); - setStr(pl, 'qt', 'tarset'); - setStr(pl, 'qt', 'qtsrcchokespeed'); - setStr(pl, 'qt', 'volume'); - setStr(pl, 'qt', 'qtsrc'); - break; - - case "shockwave": - setBool(pl, 'shockwave', 'sound'); - setBool(pl, 'shockwave', 'progress'); - setBool(pl, 'shockwave', 'autostart'); - setBool(pl, 'shockwave', 'swliveconnect'); - setStr(pl, 'shockwave', 'swvolume'); - setStr(pl, 'shockwave', 'swstretchstyle'); - setStr(pl, 'shockwave', 'swstretchhalign'); - setStr(pl, 'shockwave', 'swstretchvalign'); - break; - - case "wmp": - setBool(pl, 'wmp', 'autostart'); - setBool(pl, 'wmp', 'enabled'); - setBool(pl, 'wmp', 'enablecontextmenu'); - setBool(pl, 'wmp', 'fullscreen'); - setBool(pl, 'wmp', 'invokeurls'); - setBool(pl, 'wmp', 'mute'); - setBool(pl, 'wmp', 'stretchtofit'); - setBool(pl, 'wmp', 'windowlessvideo'); - setStr(pl, 'wmp', 'balance'); - setStr(pl, 'wmp', 'baseurl'); - setStr(pl, 'wmp', 'captioningid'); - setStr(pl, 'wmp', 'currentmarker'); - setStr(pl, 'wmp', 'currentposition'); - setStr(pl, 'wmp', 'defaultframe'); - setStr(pl, 'wmp', 'playcount'); - setStr(pl, 'wmp', 'rate'); - setStr(pl, 'wmp', 'uimode'); - setStr(pl, 'wmp', 'volume'); - break; - - case "rmp": - setBool(pl, 'rmp', 'autostart'); - setBool(pl, 'rmp', 'loop'); - setBool(pl, 'rmp', 'autogotourl'); - setBool(pl, 'rmp', 'center'); - setBool(pl, 'rmp', 'imagestatus'); - setBool(pl, 'rmp', 'maintainaspect'); - setBool(pl, 'rmp', 'nojava'); - setBool(pl, 'rmp', 'prefetch'); - setBool(pl, 'rmp', 'shuffle'); - setStr(pl, 'rmp', 'console'); - setStr(pl, 'rmp', 'controls'); - setStr(pl, 'rmp', 'numloop'); - setStr(pl, 'rmp', 'scriptcallbacks'); - break; - } - - setStr(pl, null, 'src'); - setStr(pl, null, 'id'); - setStr(pl, null, 'name'); - setStr(pl, null, 'vspace'); - setStr(pl, null, 'hspace'); - setStr(pl, null, 'bgcolor'); - setStr(pl, null, 'align'); - setStr(pl, null, 'width'); - setStr(pl, null, 'height'); - - if ((val = ed.dom.getAttrib(fe, "width")) != "") - pl.width = f.width.value = val; - - if ((val = ed.dom.getAttrib(fe, "height")) != "") - pl.height = f.height.value = val; - - oldWidth = pl.width ? parseInt(pl.width) : 0; - oldHeight = pl.height ? parseInt(pl.height) : 0; - } else - oldWidth = oldHeight = 0; - - selectByValue(f, 'media_type', type); - changedType(type); - updateColor('bgcolor_pick', 'bgcolor'); + function getVal(id) { + var elm = get(id); - TinyMCE_EditableSelects.init(); - generatePreview(); -} + if (elm.nodeName == "SELECT") + return elm.options[elm.selectedIndex].value; -function insertMedia() { - var fe, f = document.forms[0], h; + if (elm.type == "checkbox") + return elm.checked; - tinyMCEPopup.restoreSelection(); - - if (!AutoValidator.validate(f)) { - tinyMCEPopup.alert(ed.getLang('invalid_data')); - return false; + return elm.value; } - f.width.value = f.width.value == "" ? 100 : f.width.value; - f.height.value = f.height.value == "" ? 100 : f.height.value; - - fe = ed.selection.getNode(); - if (fe != null && /mceItem(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)/.test(ed.dom.getAttrib(fe, 'class'))) { - switch (f.media_type.options[f.media_type.selectedIndex].value) { - case "flash": - fe.className = "mceItemFlash"; - break; - - case "flv": - fe.className = "mceItemFlashVideo"; - break; - - case "shockwave": - fe.className = "mceItemShockWave"; - break; - - case "qt": - fe.className = "mceItemQuickTime"; - break; - - case "wmp": - fe.className = "mceItemWindowsMedia"; - break; - - case "rmp": - fe.className = "mceItemRealMedia"; - break; - } - - if (fe.width != f.width.value || fe.height != f.height.value) - ed.execCommand('mceRepaint'); - - fe.title = serializeParameters(); - fe.width = f.width.value; - fe.height = f.height.value; - fe.style.width = f.width.value + (f.width.value.indexOf('%') == -1 ? 'px' : ''); - fe.style.height = f.height.value + (f.height.value.indexOf('%') == -1 ? 'px' : ''); - fe.align = f.align.options[f.align.selectedIndex].value; - } else { - h = ' 0) { - var html = ""; - - html += ''; - - return html; - } - - return ""; -} - -function getType(v) { - var fo, i, c, el, x, f = document.forms[0]; - - fo = ed.getParam("media_types", "flash=swf;flv=flv;shockwave=dcr;qt=mov,qt,mpg,mp3,mp4,mpeg;shockwave=dcr;wmp=avi,wmv,wm,asf,asx,wmx,wvx;rmp=rm,ra,ram").split(';'); - - // YouTube - if (v.match(/watch\?v=(.+)(.*)/)) { - f.width.value = '425'; - f.height.value = '350'; - f.src.value = 'http://www.youtube.com/v/' + v.match(/v=(.*)(.*)/)[0].split('=')[1]; - return 'flash'; - } - - // Google video - if (v.indexOf('http://video.google.com/videoplay?docid=') == 0) { - f.width.value = '425'; - f.height.value = '326'; - f.src.value = 'http://video.google.com/googleplayer.swf?docId=' + v.substring('http://video.google.com/videoplay?docid='.length) + '&hl=en'; - return 'flash'; - } - - for (i=0; i 0 ? s.substring(0, s.length - 1) : s; - - return s; -} - -function setBool(pl, p, n) { - if (typeof(pl[n]) == "undefined") - return; - - document.forms[0].elements[p + "_" + n].checked = pl[n] != 'false'; -} - -function setStr(pl, p, n) { - var f = document.forms[0], e = f.elements[(p != null ? p + "_" : '') + n]; - - if (typeof(pl[n]) == "undefined") - return; - - if (e.type == "text") - e.value = pl[n]; - else - selectByValue(f, (p != null ? p + "_" : '') + n, pl[n]); -} - -function getBool(p, n, d, tv, fv) { - var v = document.forms[0].elements[p + "_" + n].checked; - - tv = typeof(tv) == 'undefined' ? 'true' : "'" + jsEncode(tv) + "'"; - fv = typeof(fv) == 'undefined' ? 'false' : "'" + jsEncode(fv) + "'"; - - return (v == d) ? '' : n + (v ? ':' + tv + ',' : ":\'" + fv + "\',"); -} - -function getStr(p, n, d) { - var e = document.forms[0].elements[(p != null ? p + "_" : "") + n]; - var v = e.type == "text" ? e.value : e.options[e.selectedIndex].value; - - if (n == 'src') - v = tinyMCEPopup.editor.convertURL(v, 'src', null); - - return ((n == d || v == '') ? '' : n + ":'" + jsEncode(v) + "',"); -} - -function getInt(p, n, d) { - var e = document.forms[0].elements[(p != null ? p + "_" : "") + n]; - var v = e.type == "text" ? e.value : e.options[e.selectedIndex].value; - - return ((n == d || v == '') ? '' : n + ":" + v.replace(/[^0-9]+/g, '') + ","); -} - -function jsEncode(s) { - s = s.replace(new RegExp('\\\\', 'g'), '\\\\'); - s = s.replace(new RegExp('"', 'g'), '\\"'); - s = s.replace(new RegExp("'", 'g'), "\\'"); + window.Media = { + init : function() { + var html, editor; + + this.editor = editor = tinyMCEPopup.editor; + + // Setup file browsers and color pickers + get('filebrowsercontainer').innerHTML = getBrowserHTML('filebrowser','src','media','media'); + get('qtsrcfilebrowsercontainer').innerHTML = getBrowserHTML('qtsrcfilebrowser','quicktime_qtsrc','media','media'); + get('bgcolor_pickcontainer').innerHTML = getColorPickerHTML('bgcolor_pick','bgcolor'); + get('video_altsource1_filebrowser').innerHTML = getBrowserHTML('filebrowser_altsource1','video_altsource1','media','media'); + get('video_altsource2_filebrowser').innerHTML = getBrowserHTML('filebrowser_altsource2','video_altsource2','media','media'); + get('video_poster_filebrowser').innerHTML = getBrowserHTML('filebrowser_poster','video_poster','media','image'); + + html = this.getMediaListHTML('medialist', 'src', 'media', 'media'); + if (html == "") + get("linklistrow").style.display = 'none'; + else + get("linklistcontainer").innerHTML = html; + + if (isVisible('filebrowser')) + get('src').style.width = '230px'; + + if (isVisible('filebrowser_altsource1')) + get('video_altsource1').style.width = '220px'; + + if (isVisible('filebrowser_altsource2')) + get('video_altsource2').style.width = '220px'; + + if (isVisible('filebrowser_poster')) + get('video_poster').style.width = '220px'; + + this.data = tinyMCEPopup.getWindowArg('data'); + this.dataToForm(); + this.preview(); + }, + + insert : function() { + var editor = tinyMCEPopup.editor; + + this.formToData(); + editor.execCommand('mceRepaint'); + tinyMCEPopup.restoreSelection(); + editor.selection.setNode(editor.plugins.media.dataToImg(this.data)); + tinyMCEPopup.close(); + }, + + preview : function() { + get('prev').innerHTML = this.editor.plugins.media.dataToHtml(this.data, true); + }, + + moveStates : function(to_form, field) { + var data = this.data, editor = this.editor, data = this.data, + mediaPlugin = editor.plugins.media, ext, src, typeInfo, defaultStates, src; + + defaultStates = { + // QuickTime + quicktime_autoplay : true, + quicktime_controller : true, + + // Flash + flash_play : true, + flash_loop : true, + flash_menu : true, + + // WindowsMedia + windowsmedia_autostart : true, + windowsmedia_enablecontextmenu : true, + windowsmedia_invokeurls : true, + + // RealMedia + realmedia_autogotourl : true, + realmedia_imagestatus : true + }; + + function parseQueryParams(str) { + var out = {}; + + if (str) { + tinymce.each(str.split('&'), function(item) { + var parts = item.split('='); + + out[unescape(parts[0])] = unescape(parts[1]); + }); + } + + return out; + }; + + function setOptions(type, names) { + var i, name, formItemName, value, list; + + if (type == data.type || type == 'global') { + names = tinymce.explode(names); + for (i = 0; i < names.length; i++) { + name = names[i]; + formItemName = type == 'global' ? name : type + '_' + name; + + if (type == 'global') + list = data; + else if (type == 'video') { + list = data.video.attrs; + + if (!list && !to_form) + data.video.attrs = list = {}; + } else + list = data.params; + + if (list) { + if (to_form) { + setVal(formItemName, list[name]); + } else { + delete list[name]; + + value = getVal(formItemName); + if (type == 'video' && value === true) + value = name; + + if (defaultStates[formItemName]) { + if (value !== defaultStates[formItemName]) { + value = "" + value; + list[name] = value; + } + } else if (value) { + value = "" + value; + list[name] = value; + } + } + } + } + } + } - return s; -} + if (!to_form) { + data.type = get('media_type').options[get('media_type').selectedIndex].value; + data.width = getVal('width'); + data.height = getVal('height'); -function generatePreview(c) { - var f = document.forms[0], p = document.getElementById('prev'), h = '', cls, pl, n, type, codebase, wp, hp, nw, nh; + // Switch type based on extension + src = getVal('src'); + if (field == 'src') { + ext = src.replace(/^.*\.([^.]+)$/, '$1'); + if (typeInfo = mediaPlugin.getType(ext)) + data.type = typeInfo.name.toLowerCase(); - p.innerHTML = ''; + setVal('media_type', data.type); + } - nw = parseInt(f.width.value); - nh = parseInt(f.height.value); + if (data.type == "video") { + if (!data.video.sources) + data.video.sources = []; - if (f.width.value != "" && f.height.value != "") { - if (f.constrain.checked) { - if (c == 'width' && oldWidth != 0) { - wp = nw / oldWidth; - nh = Math.round(wp * nh); - f.height.value = nh; - } else if (c == 'height' && oldHeight != 0) { - hp = nh / oldHeight; - nw = Math.round(hp * nw); - f.width.value = nw; + data.video.sources[0] = {src: getVal('src')}; + } } - } - } - if (f.width.value != "") - oldWidth = nw; - - if (f.height.value != "") - oldHeight = nh; - - // After constrain - pl = serializeParameters(); - - switch (f.media_type.options[f.media_type.selectedIndex].value) { - case "flash": - cls = 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000'; - codebase = 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0'; - type = 'application/x-shockwave-flash'; - break; - - case "shockwave": - cls = 'clsid:166B1BCA-3F9C-11CF-8075-444553540000'; - codebase = 'http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=8,5,1,0'; - type = 'application/x-director'; - break; - - case "qt": - cls = 'clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B'; - codebase = 'http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0'; - type = 'video/quicktime'; - break; - - case "wmp": - cls = ed.getParam('media_wmp6_compatible') ? 'clsid:05589FA1-C356-11CE-BF01-00AA0055595A' : 'clsid:6BF52A52-394A-11D3-B153-00C04F79FAA6'; - codebase = 'http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701'; - type = 'application/x-mplayer2'; - break; - - case "rmp": - cls = 'clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA'; - codebase = 'http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701'; - type = 'audio/x-pn-realaudio-plugin'; - break; - } - - if (pl == '') { - p.innerHTML = ''; - return; - } + // Hide all fieldsets and show the one active + get('video_options').style.display = 'none'; + get('flash_options').style.display = 'none'; + get('quicktime_options').style.display = 'none'; + get('shockwave_options').style.display = 'none'; + get('windowsmedia_options').style.display = 'none'; + get('realmedia_options').style.display = 'none'; + + if (get(data.type + '_options')) + get(data.type + '_options').style.display = 'block'; + + setVal('media_type', data.type); + + setOptions('flash', 'play,loop,menu,swliveconnect,quality,scale,salign,wmode,base,flashvars'); + setOptions('quicktime', 'loop,autoplay,cache,controller,correction,enablejavascript,kioskmode,autohref,playeveryframe,targetcache,scale,starttime,endtime,target,qtsrcchokespeed,volume,qtsrc'); + setOptions('shockwave', 'sound,progress,autostart,swliveconnect,swvolume,swstretchstyle,swstretchhalign,swstretchvalign'); + setOptions('windowsmedia', 'autostart,enabled,enablecontextmenu,fullscreen,invokeurls,mute,stretchtofit,windowlessvideo,balance,baseurl,captioningid,currentmarker,currentposition,defaultframe,playcount,rate,uimode,volume'); + setOptions('realmedia', 'autostart,loop,autogotourl,center,imagestatus,maintainaspect,nojava,prefetch,shuffle,console,controls,numloop,scriptcallbacks'); + setOptions('video', 'poster,autoplay,loop,preload,controls'); + setOptions('global', 'id,name,vspace,hspace,bgcolor,align,width,height'); + + if (to_form) { + if (data.type == 'video') { + if (data.video.sources[0]) + setVal('src', data.video.sources[0].src); + + src = data.video.sources[1]; + if (src) + setVal('video_altsource1', src.src); + + src = data.video.sources[2]; + if (src) + setVal('video_altsource2', src.src); + } else { + // Check flash vars + if (data.type == 'flash') { + tinymce.each(editor.getParam('flash_video_player_flashvars', {url : '$url', poster : '$poster'}), function(value, name) { + if (value == '$url') + data.params.src = parseQueryParams(data.params.flashvars)[name] || data.params.src; + }); + } + + setVal('src', data.params.src); + } + } else { + src = getVal("src"); + + // YouTube + if (src.match(/youtube.com(.+)v=([^&]+)/)) { + data.width = 425; + data.height = 350; + data.params.frameborder = '0'; + data.type = 'iframe'; + src = 'http://www.youtube.com/embed/' + src.match(/v=([^&]+)/)[1]; + setVal('src', src); + setVal('media_type', data.type); + } + + // Google video + if (src.match(/video.google.com(.+)docid=([^&]+)/)) { + data.width = 425; + data.height = 326; + data.type = 'flash'; + src = 'http://video.google.com/googleplayer.swf?docId=' + src.match(/docid=([^&]+)/)[1] + '&hl=en'; + setVal('src', src); + setVal('media_type', data.type); + } + + if (data.type == 'video') { + if (!data.video.sources) + data.video.sources = []; + + data.video.sources[0] = {src : src}; + + src = getVal("video_altsource1"); + if (src) + data.video.sources[1] = {src : src}; + + src = getVal("video_altsource2"); + if (src) + data.video.sources[2] = {src : src}; + } else + data.params.src = src; + + // Set default size + setVal('width', data.width || 320); + setVal('height', data.height || 240); + } + }, + + dataToForm : function() { + this.moveStates(true); + }, + + formToData : function(field) { + if (field == "width" || field == "height") + this.changeSize(field); + + if (field == 'source') { + this.moveStates(false, field); + setVal('source', this.editor.plugins.media.dataToHtml(this.data)); + this.panel = 'source'; + } else { + if (this.panel == 'source') { + this.data = this.editor.plugins.media.htmlToData(getVal('source')); + this.dataToForm(); + this.panel = ''; + } + + this.moveStates(false, field); + this.preview(); + } + }, + + beforeResize : function() { + this.width = parseInt(getVal('width') || "320", 10); + this.height = parseInt(getVal('height') || "240", 10); + }, + + changeSize : function(type) { + var width, height, scale, size; + + if (get('constrain').checked) { + width = parseInt(getVal('width') || "320", 10); + height = parseInt(getVal('height') || "240", 10); + + if (type == 'width') { + this.height = Math.round((width / this.width) * height); + setVal('height', this.height); + } else { + this.width = Math.round((height / this.height) * width); + setVal('width', this.width); + } + } + }, - pl = tinyMCEPopup.editor.plugins.media._parse(pl); + getMediaListHTML : function() { + if (typeof(tinyMCEMediaList) != "undefined" && tinyMCEMediaList.length > 0) { + var html = ""; - if (!pl.src) { - p.innerHTML = ''; - return; - } + html += ''; - for (n in pl) { - h += ''; + return html; + } - // Add extra url parameter if it's an absolute URL - if (n == 'src' && pl[n].indexOf('://') != -1) - h += ''; + return ""; } - } - - h += ' - -
    -
    + + + @@ -24,28 +25,29 @@
    {#media_dlg.general} - +
    -
    - + - - + - - + + +
    - - - + @@ -56,10 +58,10 @@
    + + + - +
     
    - +
    - - + +
    x    x   
    @@ -78,18 +80,18 @@
    {#media_dlg.advanced} - +
    - + - + - + - + + +
    - @@ -100,9 +102,9 @@ - +
    - +
     
    @@ -111,9 +113,91 @@
    +
    + +
    + {#media_dlg.html5_video_options} + + + + + + + + + + + + + + + + +
    + + + + + +
     
    +
    + + + + + +
     
    +
    + + + + + +
     
    +
    + + + + + + + + + +
    + + + + + +
    +
    + + + + + +
    +
    + + + + + +
    +
    + + + + + +
    +
    @@ -121,11 +205,11 @@
    {#media_dlg.flash_options} - +
    - @@ -137,7 +221,7 @@ - @@ -150,7 +234,7 @@
    - @@ -160,7 +244,7 @@ - @@ -176,18 +260,18 @@
    - +
    - +
    - +
    - +
    @@ -196,18 +280,18 @@
    - +
    - +
    - +
    - +
    @@ -215,134 +299,38 @@
    - +
    - + - - -
    -
    - -
    - {#media_dlg.flv_options} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
    - -
    - - - - - -
    -
    - - - - - -
    -
    - - - - - -
    -
    - - - - - -
    -
    - - - - - -
    -
    - - - - - -
    -
    -
    +
    {#media_dlg.qt_options} - +
    @@ -350,19 +338,19 @@ @@ -370,19 +358,19 @@ @@ -390,19 +378,19 @@ @@ -410,27 +398,27 @@ - - + - - + + - - + + - - + + - - + + - - + + - - + + - +
    - +
    - - + +
    - +
    - - + +
    - +
    - - + +
    - +
    - - + +
    - +
    - - + +
    - +
    - - + +
    - +
    - - + +
    - +
    - - + +
    - +
    - - + +
    - +
    - - + +
    - - - - - -
     
    + + + + + +
     
    -
    +
    {#media_dlg.wmp_options} - +
    @@ -504,19 +492,19 @@ @@ -524,19 +512,19 @@ @@ -544,86 +532,86 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + +
    - +
    - - + +
    - +
    - - + +
    - +
    - - + +
    - +
    - - + +
    - +
    - - + +
    - +
    - - + +
    - +
    - - + +
    - +
    - - + +
    -
    +
    {#media_dlg.rmp_options} - +
    @@ -631,19 +619,19 @@ @@ -651,19 +639,19 @@ @@ -671,19 +659,19 @@ @@ -691,10 +679,10 @@ @@ -705,19 +693,19 @@ - - + + - - + + - - + + - - + +
    - +
    - - + +
    - +
    - - + +
    - +
    - - + +
    - +
    - - + +
    - +
    - - + +
    - +
    - - + +
    - +
    - - + +
    - +
    - - + +
    - +
    - - + +
    @@ -725,11 +713,11 @@
    {#media_dlg.shockwave_options} - +
    - +
    - @@ -738,13 +726,13 @@
    - @@ -754,7 +742,7 @@ - @@ -765,18 +753,18 @@
    - +
    - +
    - +
    - +
    @@ -786,18 +774,18 @@
    - +
    - +
    - +
    - +
    @@ -806,6 +794,13 @@
    + +
    +
    + {#media_dlg.source} + +
    +
    diff --git a/program/js/tiny_mce/plugins/nonbreaking/editor_plugin.js b/program/js/tiny_mce/plugins/nonbreaking/editor_plugin.js index f2dbbff..7394735 100644 --- a/program/js/tiny_mce/plugins/nonbreaking/editor_plugin.js +++ b/program/js/tiny_mce/plugins/nonbreaking/editor_plugin.js @@ -1 +1 @@ -(function(){tinymce.create("tinymce.plugins.Nonbreaking",{init:function(a,b){var c=this;c.editor=a;a.addCommand("mceNonBreaking",function(){a.execCommand("mceInsertContent",false,(a.plugins.visualchars&&a.plugins.visualchars.state)?'·':" ")});a.addButton("nonbreaking",{title:"nonbreaking.nonbreaking_desc",cmd:"mceNonBreaking"});if(a.getParam("nonbreaking_force_tab")){a.onKeyDown.add(function(d,f){if(tinymce.isIE&&f.keyCode==9){d.execCommand("mceNonBreaking");d.execCommand("mceNonBreaking");d.execCommand("mceNonBreaking");tinymce.dom.Event.cancel(f)}})}},getInfo:function(){return{longname:"Nonbreaking space",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/nonbreaking",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("nonbreaking",tinymce.plugins.Nonbreaking)})(); \ No newline at end of file +(function(){tinymce.create("tinymce.plugins.Nonbreaking",{init:function(a,b){var c=this;c.editor=a;a.addCommand("mceNonBreaking",function(){a.execCommand("mceInsertContent",false,(a.plugins.visualchars&&a.plugins.visualchars.state)?' ':" ")});a.addButton("nonbreaking",{title:"nonbreaking.nonbreaking_desc",cmd:"mceNonBreaking"});if(a.getParam("nonbreaking_force_tab")){a.onKeyDown.add(function(d,f){if(tinymce.isIE&&f.keyCode==9){d.execCommand("mceNonBreaking");d.execCommand("mceNonBreaking");d.execCommand("mceNonBreaking");tinymce.dom.Event.cancel(f)}})}},getInfo:function(){return{longname:"Nonbreaking space",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/nonbreaking",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("nonbreaking",tinymce.plugins.Nonbreaking)})(); \ No newline at end of file diff --git a/program/js/tiny_mce/plugins/nonbreaking/editor_plugin_src.js b/program/js/tiny_mce/plugins/nonbreaking/editor_plugin_src.js index e3b078b..b3ea82e 100644 --- a/program/js/tiny_mce/plugins/nonbreaking/editor_plugin_src.js +++ b/program/js/tiny_mce/plugins/nonbreaking/editor_plugin_src.js @@ -17,7 +17,7 @@ // Register commands ed.addCommand('mceNonBreaking', function() { - ed.execCommand('mceInsertContent', false, (ed.plugins.visualchars && ed.plugins.visualchars.state) ? '·' : ' '); + ed.execCommand('mceInsertContent', false, (ed.plugins.visualchars && ed.plugins.visualchars.state) ? ' ' : ' '); }); // Register buttons diff --git a/program/js/tiny_mce/plugins/paste/editor_plugin.js b/program/js/tiny_mce/plugins/paste/editor_plugin.js index 3e7b250..6c65069 100644 --- a/program/js/tiny_mce/plugins/paste/editor_plugin.js +++ b/program/js/tiny_mce/plugins/paste/editor_plugin.js @@ -1 +1 @@ -(function(){var c=tinymce.each,d=null,a={paste_auto_cleanup_on_paste:true,paste_block_drop:false,paste_retain_style_properties:"none",paste_strip_class_attributes:"mso",paste_remove_spans:false,paste_remove_styles:false,paste_remove_styles_if_webkit:true,paste_convert_middot_lists:true,paste_convert_headers_to_strong:false,paste_dialog_width:"450",paste_dialog_height:"400",paste_text_use_dialog:false,paste_text_sticky:false,paste_text_notifyalways:false,paste_text_linebreaktype:"p",paste_text_replacements:[[/\u2026/g,"..."],[/[\x93\x94\u201c\u201d]/g,'"'],[/[\x60\x91\x92\u2018\u2019]/g,"'"]]};function b(e,f){return e.getParam(f,a[f])}tinymce.create("tinymce.plugins.PastePlugin",{init:function(e,f){var g=this;g.editor=e;g.url=f;g.onPreProcess=new tinymce.util.Dispatcher(g);g.onPostProcess=new tinymce.util.Dispatcher(g);g.onPreProcess.add(g._preProcess);g.onPostProcess.add(g._postProcess);g.onPreProcess.add(function(j,k){e.execCallback("paste_preprocess",j,k)});g.onPostProcess.add(function(j,k){e.execCallback("paste_postprocess",j,k)});e.pasteAsPlainText=false;function i(l,j){var k=e.dom;g.onPreProcess.dispatch(g,l);l.node=k.create("div",0,l.content);g.onPostProcess.dispatch(g,l);l.content=e.serializer.serialize(l.node,{getInner:1});if((!j)&&(e.pasteAsPlainText)){g._insertPlainText(e,k,l.content);if(!b(e,"paste_text_sticky")){e.pasteAsPlainText=false;e.controlManager.setActive("pastetext",false)}}else{if(/<(p|h[1-6]|ul|ol)/.test(l.content)){g._insertBlockContent(e,k,l.content)}else{g._insert(l.content)}}}e.addCommand("mceInsertClipboardContent",function(j,k){i(k,true)});if(!b(e,"paste_text_use_dialog")){e.addCommand("mcePasteText",function(k,j){var l=tinymce.util.Cookie;e.pasteAsPlainText=!e.pasteAsPlainText;e.controlManager.setActive("pastetext",e.pasteAsPlainText);if((e.pasteAsPlainText)&&(!l.get("tinymcePasteText"))){if(b(e,"paste_text_sticky")){e.windowManager.alert(e.translate("paste.plaintext_mode_sticky"))}else{e.windowManager.alert(e.translate("paste.plaintext_mode_sticky"))}if(!b(e,"paste_text_notifyalways")){l.set("tinymcePasteText","1",new Date(new Date().getFullYear()+1,12,31))}}})}e.addButton("pastetext",{title:"paste.paste_text_desc",cmd:"mcePasteText"});e.addButton("selectall",{title:"paste.selectall_desc",cmd:"selectall"});function h(s){var m,q,k,l=e.selection,p=e.dom,r=e.getBody(),j;if(e.pasteAsPlainText&&(s.clipboardData||p.doc.dataTransfer)){s.preventDefault();i({content:(s.clipboardData||p.doc.dataTransfer).getData("Text")},true);return}if(p.get("_mcePaste")){return}m=p.add(r,"div",{id:"_mcePaste","class":"mcePaste"},"\uFEFF");if(r!=e.getDoc().body){j=p.getPos(e.selection.getStart(),r).y}else{j=r.scrollTop}p.setStyles(m,{position:"absolute",left:-10000,top:j,width:1,height:1,overflow:"hidden"});if(tinymce.isIE){k=p.doc.body.createTextRange();k.moveToElementText(m);k.execCommand("Paste");p.remove(m);if(m.innerHTML==="\uFEFF"){e.execCommand("mcePasteWord");s.preventDefault();return}i({content:m.innerHTML});return tinymce.dom.Event.cancel(s)}else{function o(n){n.preventDefault()}p.bind(e.getDoc(),"mousedown",o);p.bind(e.getDoc(),"keydown",o);q=e.selection.getRng();m=m.firstChild;k=e.getDoc().createRange();k.setStart(m,0);k.setEnd(m,1);l.setRng(k);window.setTimeout(function(){var t="",n=p.select("div.mcePaste");c(n,function(u){c(p.select("div.mcePaste",u),function(v){p.remove(v,1)});c(p.select("span.Apple-style-span",u),function(v){p.remove(v,1)});t+=u.innerHTML});c(n,function(u){p.remove(u)});if(q){l.setRng(q)}i({content:t});p.unbind(e.getDoc(),"mousedown",o);p.unbind(e.getDoc(),"keydown",o)},0)}}if(b(e,"paste_auto_cleanup_on_paste")){if(tinymce.isOpera||/Firefox\/2/.test(navigator.userAgent)){e.onKeyDown.add(function(j,k){if(((tinymce.isMac?k.metaKey:k.ctrlKey)&&k.keyCode==86)||(k.shiftKey&&k.keyCode==45)){h(k)}})}else{e.onPaste.addToTop(function(j,k){return h(k)})}}if(b(e,"paste_block_drop")){e.onInit.add(function(){e.dom.bind(e.getBody(),["dragend","dragover","draggesture","dragdrop","drop","drag"],function(j){j.preventDefault();j.stopPropagation();return false})})}g._legacySupport()},getInfo:function(){return{longname:"Paste text/word",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/paste",version:tinymce.majorVersion+"."+tinymce.minorVersion}},_preProcess:function(i,f){var l=this.editor,k=f.content,q=tinymce.grep,p=tinymce.explode,g=tinymce.trim,m,j;function e(h){c(h,function(o){if(o.constructor==RegExp){k=k.replace(o,"")}else{k=k.replace(o[0],o[1])}})}if(/class="?Mso|style="[^"]*\bmso-|w:WordDocument/i.test(k)||f.wordContent){f.wordContent=true;e([/^\s*( )+/gi,/( |]*>)+\s*$/gi]);if(b(l,"paste_convert_headers_to_strong")){k=k.replace(/

    ]*class="?MsoHeading"?[^>]*>(.*?)<\/p>/gi,"

    $1

    ")}if(b(l,"paste_convert_middot_lists")){e([[//gi,"$&__MCE_ITEM__"],[/(]+(?:mso-list:|:\s*symbol)[^>]+>)/gi,"$1__MCE_ITEM__"]])}e([//gi,/<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi,[/<(\/?)s>/gi,"<$1strike>"],[/ /gi,"\u00a0"]]);do{m=k.length;k=k.replace(/(<[a-z][^>]*\s)(?:id|name|language|type|on\w+|\w+:\w+)=(?:"[^"]*"|\w+)\s?/gi,"$1")}while(m!=k.length);if(b(l,"paste_retain_style_properties").replace(/^none$/i,"").length==0){k=k.replace(/<\/?span[^>]*>/gi,"")}else{e([[/([\s\u00a0]*)<\/span>/gi,function(o,h){return(h.length>0)?h.replace(/./," ").slice(Math.floor(h.length/2)).split("").join("\u00a0"):""}],[/(<[a-z][^>]*)\sstyle="([^"]*)"/gi,function(u,h,t){var v=[],o=0,r=p(g(t).replace(/"/gi,"'"),";");c(r,function(s){var w,y,z=p(s,":");function x(A){return A+((A!=="0")&&(/\d$/.test(A)))?"px":""}if(z.length==2){w=z[0].toLowerCase();y=z[1].toLowerCase();switch(w){case"mso-padding-alt":case"mso-padding-top-alt":case"mso-padding-right-alt":case"mso-padding-bottom-alt":case"mso-padding-left-alt":case"mso-margin-alt":case"mso-margin-top-alt":case"mso-margin-right-alt":case"mso-margin-bottom-alt":case"mso-margin-left-alt":case"mso-table-layout-alt":case"mso-height":case"mso-width":case"mso-vertical-align-alt":v[o++]=w.replace(/^mso-|-alt$/g,"")+":"+x(y);return;case"horiz-align":v[o++]="text-align:"+y;return;case"vert-align":v[o++]="vertical-align:"+y;return;case"font-color":case"mso-foreground":v[o++]="color:"+y;return;case"mso-background":case"mso-highlight":v[o++]="background:"+y;return;case"mso-default-height":v[o++]="min-height:"+x(y);return;case"mso-default-width":v[o++]="min-width:"+x(y);return;case"mso-padding-between-alt":v[o++]="border-collapse:separate;border-spacing:"+x(y);return;case"text-line-through":if((y=="single")||(y=="double")){v[o++]="text-decoration:line-through"}return;case"mso-zero-height":if(y=="yes"){v[o++]="display:none"}return}if(/^(mso|column|font-emph|lang|layout|line-break|list-image|nav|panose|punct|row|ruby|sep|size|src|tab-|table-border|text-(?!align|decor|indent|trans)|top-bar|version|vnd|word-break)/.test(w)){return}v[o++]=w+":"+z[1]}});if(o>0){return h+' style="'+v.join(";")+'"'}else{return h}}]])}}if(b(l,"paste_convert_headers_to_strong")){e([[/]*>/gi,"

    "],[/<\/h[1-6][^>]*>/gi,"

    "]])}j=b(l,"paste_strip_class_attributes");if(j!=="none"){function n(r,o){if(j==="all"){return""}var h=q(p(o.replace(/^(["'])(.*)\1$/,"$2")," "),function(s){return(/^(?!mso)/i.test(s))});return h.length?' class="'+h.join(" ")+'"':""}k=k.replace(/ class="([^"]+)"/gi,n);k=k.replace(/ class=(\w+)/gi,n)}if(b(l,"paste_remove_spans")){k=k.replace(/<\/?span[^>]*>/gi,"")}f.content=k},_postProcess:function(h,j){var g=this,f=g.editor,i=f.dom,e;if(j.wordContent){c(i.select("a",j.node),function(k){if(!k.href||k.href.indexOf("#_Toc")!=-1){i.remove(k,1)}});if(b(f,"paste_convert_middot_lists")){g._convertLists(h,j)}e=b(f,"paste_retain_style_properties");if((tinymce.is(e,"string"))&&(e!=="all")&&(e!=="*")){e=tinymce.explode(e.replace(/^none$/i,""));c(i.select("*",j.node),function(n){var o={},l=0,m,p,k;if(e){for(m=0;m0){i.setStyles(n,o)}else{if(n.nodeName=="SPAN"&&!n.className){i.remove(n,true)}}})}}if(b(f,"paste_remove_styles")||(b(f,"paste_remove_styles_if_webkit")&&tinymce.isWebKit)){c(i.select("*[style]",j.node),function(k){k.removeAttribute("style");k.removeAttribute("_mce_style")})}else{if(tinymce.isWebKit){c(i.select("*",j.node),function(k){k.removeAttribute("_mce_style")})}}},_convertLists:function(h,f){var j=h.editor.dom,i,m,e=-1,g,n=[],l,k;c(j.select("p",f.node),function(u){var r,v="",t,s,o,q;for(r=u.firstChild;r&&r.nodeType==3;r=r.nextSibling){v+=r.nodeValue}v=u.innerHTML.replace(/<\/?\w+[^>]*>/gi,"").replace(/ /g,"\u00a0");if(/^(__MCE_ITEM__)+[\u2022\u00b7\u00a7\u00d8o]\s*\u00a0*/.test(v)){t="ul"}if(/^__MCE_ITEM__\s*\w+\.\s*\u00a0{2,}/.test(v)){t="ol"}if(t){g=parseFloat(u.style.marginLeft||0);if(g>e){n.push(g)}if(!i||t!=l){i=j.create(t);j.insertAfter(i,u)}else{if(g>e){i=m.appendChild(j.create(t))}else{if(g]*>/gi,"");if(t=="ul"&&/^[\u2022\u00b7\u00a7\u00d8o]/.test(p)){j.remove(w)}else{if(/^[\s\S]*\w+\.( |\u00a0)*\s*/.test(p)){j.remove(w)}}});s=u.innerHTML;if(t=="ul"){s=u.innerHTML.replace(/__MCE_ITEM__/g,"").replace(/^[\u2022\u00b7\u00a7\u00d8o]\s*( |\u00a0)+\s*/,"")}else{s=u.innerHTML.replace(/__MCE_ITEM__/g,"").replace(/^\s*\w+\.( |\u00a0)+\s*/,"")}m=i.appendChild(j.create("li",0,s));j.remove(u);e=g;l=t}else{i=e=0}});k=f.node.innerHTML;if(k.indexOf("__MCE_ITEM__")!=-1){f.node.innerHTML=k.replace(/__MCE_ITEM__/g,"")}},_insertBlockContent:function(l,h,m){var f,j,g=l.selection,q,n,e,o,i,k="mce_marker";function p(t){var s;if(tinymce.isIE){s=l.getDoc().body.createTextRange();s.moveToElementText(t);s.collapse(false);s.select()}else{g.select(t,1);g.collapse(false)}}this._insert(' ',1);j=h.get(k);f=h.getParent(j,"p,h1,h2,h3,h4,h5,h6,ul,ol,th,td");if(f&&!/TD|TH/.test(f.nodeName)){j=h.split(f,j);c(h.create("div",0,m).childNodes,function(r){q=j.parentNode.insertBefore(r.cloneNode(true),j)});p(q)}else{h.setOuterHTML(j,m);g.select(l.getBody(),1);g.collapse(0)}while(n=h.get(k)){h.remove(n)}n=g.getStart();e=h.getViewPort(l.getWin());o=l.dom.getPos(n).y;i=n.clientHeight;if(oe.y+e.h){l.getDoc().body.scrollTop=o0)){if(!d){d=("34,quot,38,amp,39,apos,60,lt,62,gt,"+j.serializer.settings.entities).split(",")}if(/<(?:p|br|h[1-6]|ul|ol|dl|table|t[rdh]|div|blockquote|fieldset|pre|address|center)[^>]*>/i.test(v)){q([/[\n\r]+/g])}else{q([/\r+/g])}q([[/<\/(?:p|h[1-6]|ul|ol|dl|table|div|blockquote|fieldset|pre|address|center)>/gi,"\n\n"],[/]*>|<\/tr>/gi,"\n"],[/<\/t[dh]>\s*]*>/gi,"\t"],/<[a-z!\/?][^>]*>/gi,[/ /gi," "],[/&(#\d+|[a-z0-9]{1,10});/gi,function(i,h){if(h.charAt(0)==="#"){return String.fromCharCode(h.slice(1))}else{return((i=y(d,h))>0)?String.fromCharCode(d[i-1]):" "}}],[/(?:(?!\n)\s)*(\n+)(?:(?!\n)\s)*/gi,"$1"],[/\n{3,}/g,"\n\n"],/^\s+|\s+$/g]);v=x.encode(v);if(!s.isCollapsed()){z.execCommand("Delete",false,null)}if(m(o,"array")||(m(o,"array"))){q(o)}else{if(m(o,"string")){q(new RegExp(o,"gi"))}}if(g=="none"){q([[/\n+/g," "]])}else{if(g=="br"){q([[/\n/g,"
    "]])}else{q([/^\s+|\s+$/g,[/\n\n/g,"

    "],[/\n/g,"
    "]])}}if((l=v.indexOf("

    "))!=-1){k=v.lastIndexOf("

    ");r=s.getNode();e=[];do{if(r.nodeType==1){if(r.nodeName=="TD"||r.nodeName=="BODY"){break}e[e.length]=r}}while(r=r.parentNode);if(e.length>0){p=v.substring(0,l);f="";for(t=0,u=e.length;t";f+="<"+e[e.length-t-1].nodeName.toLowerCase()+">"}if(l==k){v=p+f+v.substring(l+7)}else{v=p+v.substring(l+4,k+4)+f+v.substring(k+7)}}}j.execCommand("mceInsertRawHTML",false,v+' ');window.setTimeout(function(){var h=x.get("_plain_text_marker"),B,i,A,w;s.select(h,false);z.execCommand("Delete",false,null);h=null;B=s.getStart();i=x.getViewPort(n);A=x.getPos(B).y;w=B.clientHeight;if((Ai.y+i.h)){z.body.scrollTop=A")});return}}if(o.get("_mcePaste")){return}l=o.add(q,"div",{id:"_mcePaste","class":"mcePaste","data-mce-bogus":"1"},"\uFEFF\uFEFF");if(q!=d.getDoc().body){i=o.getPos(d.selection.getStart(),q).y}else{i=q.scrollTop+o.getViewPort().y}o.setStyles(l,{position:"absolute",left:-10000,top:i,width:1,height:1,overflow:"hidden"});if(tinymce.isIE){t=k.getRng();j=o.doc.body.createTextRange();j.moveToElementText(l);j.execCommand("Paste");o.remove(l);if(l.innerHTML==="\uFEFF\uFEFF"){d.execCommand("mcePasteWord");s.preventDefault();return}k.setRng(t);k.setContent("");setTimeout(function(){h({content:l.innerHTML})},0);return tinymce.dom.Event.cancel(s)}else{function m(n){n.preventDefault()}o.bind(d.getDoc(),"mousedown",m);o.bind(d.getDoc(),"keydown",m);p=d.selection.getRng();l=l.firstChild;j=d.getDoc().createRange();j.setStart(l,0);j.setEnd(l,2);k.setRng(j);window.setTimeout(function(){var u="",n;if(!o.select("div.mcePaste > div.mcePaste").length){n=o.select("div.mcePaste");c(n,function(w){var v=w.firstChild;if(v&&v.nodeName=="DIV"&&v.style.marginTop&&v.style.backgroundColor){o.remove(v,1)}c(o.select("span.Apple-style-span",w),function(x){o.remove(x,1)});c(o.select("br[data-mce-bogus]",w),function(x){o.remove(x)});if(w.parentNode.className!="mcePaste"){u+=w.innerHTML}})}else{u="

    "+o.encode(r).replace(/\r?\n/g,"
    ")+"
    "}c(o.select("div.mcePaste"),function(v){o.remove(v)});if(p){k.setRng(p)}h({content:u});o.unbind(d.getDoc(),"mousedown",m);o.unbind(d.getDoc(),"keydown",m)},0)}}if(b(d,"paste_auto_cleanup_on_paste")){if(tinymce.isOpera||/Firefox\/2/.test(navigator.userAgent)){d.onKeyDown.addToTop(function(i,j){if(((tinymce.isMac?j.metaKey:j.ctrlKey)&&j.keyCode==86)||(j.shiftKey&&j.keyCode==45)){g(j)}})}else{d.onPaste.addToTop(function(i,j){return g(j)})}}d.onInit.add(function(){d.controlManager.setActive("pastetext",d.pasteAsPlainText);if(b(d,"paste_block_drop")){d.dom.bind(d.getBody(),["dragend","dragover","draggesture","dragdrop","drop","drag"],function(i){i.preventDefault();i.stopPropagation();return false})}});f._legacySupport()},getInfo:function(){return{longname:"Paste text/word",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/paste",version:tinymce.majorVersion+"."+tinymce.minorVersion}},_preProcess:function(g,e){var k=this.editor,j=e.content,p=tinymce.grep,n=tinymce.explode,f=tinymce.trim,l,i;function d(h){c(h,function(o){if(o.constructor==RegExp){j=j.replace(o,"")}else{j=j.replace(o[0],o[1])}})}if(k.settings.paste_enable_default_filters==false){return}if(tinymce.isIE&&document.documentMode>=9){d([[/(?:
     [\s\r\n]+|
    )*(<\/?(h[1-6r]|p|div|address|pre|form|table|tbody|thead|tfoot|th|tr|td|li|ol|ul|caption|blockquote|center|dl|dt|dd|dir|fieldset)[^>]*>)(?:
     [\s\r\n]+|
    )*/g,"$1"]])}if(/class="?Mso|style="[^"]*\bmso-|w:WordDocument/i.test(j)||e.wordContent){e.wordContent=true;d([/^\s*( )+/gi,/( |]*>)+\s*$/gi]);if(b(k,"paste_convert_headers_to_strong")){j=j.replace(/

    ]*class="?MsoHeading"?[^>]*>(.*?)<\/p>/gi,"

    $1

    ")}if(b(k,"paste_convert_middot_lists")){d([[//gi,"$&__MCE_ITEM__"],[/(]+(?:mso-list:|:\s*symbol)[^>]+>)/gi,"$1__MCE_ITEM__"],[/(]+(?:MsoListParagraph)[^>]+>)/gi,"$1__MCE_ITEM__"]])}d([//gi,/<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi,[/<(\/?)s>/gi,"<$1strike>"],[/ /gi,"\u00a0"]]);do{l=j.length;j=j.replace(/(<[a-z][^>]*\s)(?:id|name|language|type|on\w+|\w+:\w+)=(?:"[^"]*"|\w+)\s?/gi,"$1")}while(l!=j.length);if(b(k,"paste_retain_style_properties").replace(/^none$/i,"").length==0){j=j.replace(/<\/?span[^>]*>/gi,"")}else{d([[/([\s\u00a0]*)<\/span>/gi,function(o,h){return(h.length>0)?h.replace(/./," ").slice(Math.floor(h.length/2)).split("").join("\u00a0"):""}],[/(<[a-z][^>]*)\sstyle="([^"]*)"/gi,function(t,h,r){var u=[],o=0,q=n(f(r).replace(/"/gi,"'"),";");c(q,function(s){var w,y,z=n(s,":");function x(A){return A+((A!=="0")&&(/\d$/.test(A)))?"px":""}if(z.length==2){w=z[0].toLowerCase();y=z[1].toLowerCase();switch(w){case"mso-padding-alt":case"mso-padding-top-alt":case"mso-padding-right-alt":case"mso-padding-bottom-alt":case"mso-padding-left-alt":case"mso-margin-alt":case"mso-margin-top-alt":case"mso-margin-right-alt":case"mso-margin-bottom-alt":case"mso-margin-left-alt":case"mso-table-layout-alt":case"mso-height":case"mso-width":case"mso-vertical-align-alt":u[o++]=w.replace(/^mso-|-alt$/g,"")+":"+x(y);return;case"horiz-align":u[o++]="text-align:"+y;return;case"vert-align":u[o++]="vertical-align:"+y;return;case"font-color":case"mso-foreground":u[o++]="color:"+y;return;case"mso-background":case"mso-highlight":u[o++]="background:"+y;return;case"mso-default-height":u[o++]="min-height:"+x(y);return;case"mso-default-width":u[o++]="min-width:"+x(y);return;case"mso-padding-between-alt":u[o++]="border-collapse:separate;border-spacing:"+x(y);return;case"text-line-through":if((y=="single")||(y=="double")){u[o++]="text-decoration:line-through"}return;case"mso-zero-height":if(y=="yes"){u[o++]="display:none"}return}if(/^(mso|column|font-emph|lang|layout|line-break|list-image|nav|panose|punct|row|ruby|sep|size|src|tab-|table-border|text-(?!align|decor|indent|trans)|top-bar|version|vnd|word-break)/.test(w)){return}u[o++]=w+":"+z[1]}});if(o>0){return h+' style="'+u.join(";")+'"'}else{return h}}]])}}if(b(k,"paste_convert_headers_to_strong")){d([[/]*>/gi,"

    "],[/<\/h[1-6][^>]*>/gi,"

    "]])}d([[/Version:[\d.]+\nStartHTML:\d+\nEndHTML:\d+\nStartFragment:\d+\nEndFragment:\d+/gi,""]]);i=b(k,"paste_strip_class_attributes");if(i!=="none"){function m(q,o){if(i==="all"){return""}var h=p(n(o.replace(/^(["'])(.*)\1$/,"$2")," "),function(r){return(/^(?!mso)/i.test(r))});return h.length?' class="'+h.join(" ")+'"':""}j=j.replace(/ class="([^"]+)"/gi,m);j=j.replace(/ class=([\-\w]+)/gi,m)}if(b(k,"paste_remove_spans")){j=j.replace(/<\/?span[^>]*>/gi,"")}e.content=j},_postProcess:function(g,i){var f=this,e=f.editor,h=e.dom,d;if(e.settings.paste_enable_default_filters==false){return}if(i.wordContent){c(h.select("a",i.node),function(j){if(!j.href||j.href.indexOf("#_Toc")!=-1){h.remove(j,1)}});if(b(e,"paste_convert_middot_lists")){f._convertLists(g,i)}d=b(e,"paste_retain_style_properties");if((tinymce.is(d,"string"))&&(d!=="all")&&(d!=="*")){d=tinymce.explode(d.replace(/^none$/i,""));c(h.select("*",i.node),function(m){var n={},k=0,l,o,j;if(d){for(l=0;l0){h.setStyles(m,n)}else{if(m.nodeName=="SPAN"&&!m.className){h.remove(m,true)}}})}}if(b(e,"paste_remove_styles")||(b(e,"paste_remove_styles_if_webkit")&&tinymce.isWebKit)){c(h.select("*[style]",i.node),function(j){j.removeAttribute("style");j.removeAttribute("data-mce-style")})}else{if(tinymce.isWebKit){c(h.select("*",i.node),function(j){j.removeAttribute("data-mce-style")})}}},_convertLists:function(g,e){var i=g.editor.dom,h,l,d=-1,f,m=[],k,j;c(i.select("p",e.node),function(t){var q,u="",s,r,n,o;for(q=t.firstChild;q&&q.nodeType==3;q=q.nextSibling){u+=q.nodeValue}u=t.innerHTML.replace(/<\/?\w+[^>]*>/gi,"").replace(/ /g,"\u00a0");if(/^(__MCE_ITEM__)+[\u2022\u00b7\u00a7\u00d8o\u25CF]\s*\u00a0*/.test(u)){s="ul"}if(/^__MCE_ITEM__\s*\w+\.\s*\u00a0+/.test(u)){s="ol"}if(s){f=parseFloat(t.style.marginLeft||0);if(f>d){m.push(f)}if(!h||s!=k){h=i.create(s);i.insertAfter(h,t)}else{if(f>d){h=l.appendChild(i.create(s))}else{if(f]*>/gi,"");if(s=="ul"&&/^__MCE_ITEM__[\u2022\u00b7\u00a7\u00d8o\u25CF]/.test(p)){i.remove(v)}else{if(/^__MCE_ITEM__[\s\S]*\w+\.( |\u00a0)*\s*/.test(p)){i.remove(v)}}});r=t.innerHTML;if(s=="ul"){r=t.innerHTML.replace(/__MCE_ITEM__/g,"").replace(/^[\u2022\u00b7\u00a7\u00d8o\u25CF]\s*( |\u00a0)+\s*/,"")}else{r=t.innerHTML.replace(/__MCE_ITEM__/g,"").replace(/^\s*\w+\.( |\u00a0)+\s*/,"")}l=h.appendChild(i.create("li",0,r));i.remove(t);d=f;k=s}else{h=d=0}});j=e.node.innerHTML;if(j.indexOf("__MCE_ITEM__")!=-1){e.node.innerHTML=j.replace(/__MCE_ITEM__/g,"")}},_insert:function(f,d){var e=this.editor,g=e.selection.getRng();if(!e.selection.isCollapsed()&&g.startContainer!=g.endContainer){e.getDoc().execCommand("Delete",false,null)}e.execCommand("mceInsertContent",false,f,{skip_undo:d})},_insertPlainText:function(j,x,v){var t,u,l,k,r,e,p,f,n=j.getWin(),z=j.getDoc(),s=j.selection,m=tinymce.is,y=tinymce.inArray,g=b(j,"paste_text_linebreaktype"),o=b(j,"paste_text_replacements");function q(d){c(d,function(h){if(h.constructor==RegExp){v=v.replace(h,"")}else{v=v.replace(h[0],h[1])}})}if((typeof(v)==="string")&&(v.length>0)){if(/<(?:p|br|h[1-6]|ul|ol|dl|table|t[rdh]|div|blockquote|fieldset|pre|address|center)[^>]*>/i.test(v)){q([/[\n\r]+/g])}else{q([/\r+/g])}q([[/<\/(?:p|h[1-6]|ul|ol|dl|table|div|blockquote|fieldset|pre|address|center)>/gi,"\n\n"],[/]*>|<\/tr>/gi,"\n"],[/<\/t[dh]>\s*]*>/gi,"\t"],/<[a-z!\/?][^>]*>/gi,[/ /gi," "],[/(?:(?!\n)\s)*(\n+)(?:(?!\n)\s)*/gi,"$1"],[/\n{3,}/g,"\n\n"],/^\s+|\s+$/g]);v=x.decode(tinymce.html.Entities.encodeRaw(v));if(!s.isCollapsed()){z.execCommand("Delete",false,null)}if(m(o,"array")||(m(o,"array"))){q(o)}else{if(m(o,"string")){q(new RegExp(o,"gi"))}}if(g=="none"){q([[/\n+/g," "]])}else{if(g=="br"){q([[/\n/g,"
    "]])}else{q([/^\s+|\s+$/g,[/\n\n/g,"

    "],[/\n/g,"
    "]])}}if((l=v.indexOf("

    "))!=-1){k=v.lastIndexOf("

    ");r=s.getNode();e=[];do{if(r.nodeType==1){if(r.nodeName=="TD"||r.nodeName=="BODY"){break}e[e.length]=r}}while(r=r.parentNode);if(e.length>0){p=v.substring(0,l);f="";for(t=0,u=e.length;t";f+="<"+e[e.length-t-1].nodeName.toLowerCase()+">"}if(l==k){v=p+f+v.substring(l+7)}else{v=p+v.substring(l+4,k+4)+f+v.substring(k+7)}}}j.execCommand("mceInsertRawHTML",false,v+' ');window.setTimeout(function(){var d=x.get("_plain_text_marker"),A,h,w,i;s.select(d,false);z.execCommand("Delete",false,null);d=null;A=s.getStart();h=x.getViewPort(n);w=x.getPos(A).y;i=A.clientHeight;if((wh.y+h.h)){z.body.scrollTop=w

    ' + dom.encode(textContent).replace(/\r?\n/g, '
    ') + '
    '; + } // Remove the nodes - each(nl, function(n) { + each(dom.select('div.mcePaste'), function(n) { dom.remove(n); }); @@ -244,7 +294,7 @@ if (getParam(ed, "paste_auto_cleanup_on_paste")) { // Is it's Opera or older FF use key handler if (tinymce.isOpera || /Firefox\/2/.test(navigator.userAgent)) { - ed.onKeyDown.add(function(ed, e) { + ed.onKeyDown.addToTop(function(ed, e) { if (((tinymce.isMac ? e.metaKey : e.ctrlKey) && e.keyCode == 86) || (e.shiftKey && e.keyCode == 45)) grabContent(e); }); @@ -256,17 +306,19 @@ } } - // Block all drag/drop events - if (getParam(ed, "paste_block_drop")) { - ed.onInit.add(function() { + ed.onInit.add(function() { + ed.controlManager.setActive("pastetext", ed.pasteAsPlainText); + + // Block all drag/drop events + if (getParam(ed, "paste_block_drop")) { ed.dom.bind(ed.getBody(), ['dragend', 'dragover', 'draggesture', 'dragdrop', 'drop', 'drag'], function(e) { e.preventDefault(); e.stopPropagation(); return false; }); - }); - } + } + }); // Add legacy support t._legacySupport(); @@ -283,8 +335,6 @@ }, _preProcess : function(pl, o) { - //console.log('Before preprocess:' + o.content); - var ed = this.editor, h = o.content, grep = tinymce.grep, @@ -292,6 +342,8 @@ trim = tinymce.trim, len, stripClass; + //console.log('Before preprocess:' + o.content); + function process(items) { each(items, function(v) { // Remove or replace @@ -301,6 +353,14 @@ h = h.replace(v[0], v[1]); }); } + + if (ed.settings.paste_enable_default_filters == false) { + return; + } + + // IE9 adds BRs before/after block elements when contents is pasted from word or for example another browser + if (tinymce.isIE && document.documentMode >= 9) + process([[/(?:
     [\s\r\n]+|
    )*(<\/?(h[1-6r]|p|div|address|pre|form|table|tbody|thead|tfoot|th|tr|td|li|ol|ul|caption|blockquote|center|dl|dt|dd|dir|fieldset)[^>]*>)(?:
     [\s\r\n]+|
    )*/g, '$1']]); // Detect Word content and process it more aggressive if (/class="?Mso|style="[^"]*\bmso-|w:WordDocument/i.test(h) || o.wordContent) { @@ -320,7 +380,8 @@ if (getParam(ed, "paste_convert_middot_lists")) { process([ [//gi, '$&__MCE_ITEM__'], // Convert supportLists to a list item marker - [/(]+(?:mso-list:|:\s*symbol)[^>]+>)/gi, '$1__MCE_ITEM__'] // Convert mso-list and symbol spans to item markers + [/(]+(?:mso-list:|:\s*symbol)[^>]+>)/gi, '$1__MCE_ITEM__'], // Convert mso-list and symbol spans to item markers + [/(]+(?:MsoListParagraph)[^>]+>)/gi, '$1__MCE_ITEM__'] // Convert mso-list and symbol paragraphs to item markers (FF) ]); } @@ -472,6 +533,11 @@ ]); } + process([ + // Copy paste from Java like Open Office will produce this junk on FF + [/Version:[\d.]+\nStartHTML:\d+\nEndHTML:\d+\nStartFragment:\d+\nEndFragment:\d+/gi, ''] + ]); + // Class attribute options are: leave all as-is ("none"), remove all ("all"), or remove only those starting with mso ("mso"). // Note:- paste_strip_class_attributes: "none", verify_css_classes: true is also a good variation. stripClass = getParam(ed, "paste_strip_class_attributes"); @@ -491,7 +557,7 @@ }; h = h.replace(/ class="([^"]+)"/gi, removeClasses); - h = h.replace(/ class=(\w+)/gi, removeClasses); + h = h.replace(/ class=([\-\w]+)/gi, removeClasses); } // Remove spans option @@ -510,6 +576,10 @@ _postProcess : function(pl, o) { var t = this, ed = t.editor, dom = ed.dom, styleProps; + if (ed.settings.paste_enable_default_filters == false) { + return; + } + if (o.wordContent) { // Remove named anchors or TOC links each(dom.select('a', o.node), function(a) { @@ -561,14 +631,14 @@ if (getParam(ed, "paste_remove_styles") || (getParam(ed, "paste_remove_styles_if_webkit") && tinymce.isWebKit)) { each(dom.select('*[style]', o.node), function(el) { el.removeAttribute('style'); - el.removeAttribute('_mce_style'); + el.removeAttribute('data-mce-style'); }); } else { if (tinymce.isWebKit) { // We need to compress the styles on WebKit since if you paste it will become // Removing the mce_style that contains the real value will force the Serializer engine to compress the styles each(dom.select('*', o.node), function(el) { - el.removeAttribute('_mce_style'); + el.removeAttribute('data-mce-style'); }); } } @@ -591,11 +661,11 @@ val = p.innerHTML.replace(/<\/?\w+[^>]*>/gi, '').replace(/ /g, '\u00a0'); // Detect unordered lists look for bullets - if (/^(__MCE_ITEM__)+[\u2022\u00b7\u00a7\u00d8o]\s*\u00a0*/.test(val)) + if (/^(__MCE_ITEM__)+[\u2022\u00b7\u00a7\u00d8o\u25CF]\s*\u00a0*/.test(val)) type = 'ul'; // Detect ordered lists 1., a. or ixv. - if (/^__MCE_ITEM__\s*\w+\.\s*\u00a0{2,}/.test(val)) + if (/^__MCE_ITEM__\s*\w+\.\s*\u00a0+/.test(val)) type = 'ol'; // Check if node value matches the list pattern: o   @@ -625,9 +695,9 @@ var html = span.innerHTML.replace(/<\/?\w+[^>]*>/gi, ''); // Remove span with the middot or the number - if (type == 'ul' && /^[\u2022\u00b7\u00a7\u00d8o]/.test(html)) + if (type == 'ul' && /^__MCE_ITEM__[\u2022\u00b7\u00a7\u00d8o\u25CF]/.test(html)) dom.remove(span); - else if (/^[\s\S]*\w+\.( |\u00a0)*\s*/.test(html)) + else if (/^__MCE_ITEM__[\s\S]*\w+\.( |\u00a0)*\s*/.test(html)) dom.remove(span); }); @@ -635,7 +705,7 @@ // Remove middot/list items if (type == 'ul') - html = p.innerHTML.replace(/__MCE_ITEM__/g, '').replace(/^[\u2022\u00b7\u00a7\u00d8o]\s*( |\u00a0)+\s*/, ''); + html = p.innerHTML.replace(/__MCE_ITEM__/g, '').replace(/^[\u2022\u00b7\u00a7\u00d8o\u25CF]\s*( |\u00a0)+\s*/, ''); else html = p.innerHTML.replace(/__MCE_ITEM__/g, '').replace(/^\s*\w+\.( |\u00a0)+\s*/, ''); @@ -655,65 +725,6 @@ o.node.innerHTML = html.replace(/__MCE_ITEM__/g, ''); }, - /** - * This method will split the current block parent and insert the contents inside the split position. - * This logic can be improved so text nodes at the start/end remain in the start/end block elements - */ - _insertBlockContent : function(ed, dom, content) { - var parentBlock, marker, sel = ed.selection, last, elm, vp, y, elmHeight, markerId = 'mce_marker'; - - function select(n) { - var r; - - if (tinymce.isIE) { - r = ed.getDoc().body.createTextRange(); - r.moveToElementText(n); - r.collapse(false); - r.select(); - } else { - sel.select(n, 1); - sel.collapse(false); - } - } - - // Insert a marker for the caret position - this._insert(' ', 1); - marker = dom.get(markerId); - parentBlock = dom.getParent(marker, 'p,h1,h2,h3,h4,h5,h6,ul,ol,th,td'); - - // If it's a parent block but not a table cell - if (parentBlock && !/TD|TH/.test(parentBlock.nodeName)) { - // Split parent block - marker = dom.split(parentBlock, marker); - - // Insert nodes before the marker - each(dom.create('div', 0, content).childNodes, function(n) { - last = marker.parentNode.insertBefore(n.cloneNode(true), marker); - }); - - // Move caret after marker - select(last); - } else { - dom.setOuterHTML(marker, content); - sel.select(ed.getBody(), 1); - sel.collapse(0); - } - - // Remove marker if it's left - while (elm = dom.get(markerId)) - dom.remove(elm); - - // Get element, position and height - elm = sel.getStart(); - vp = dom.getViewPort(ed.getWin()); - y = ed.dom.getPos(elm).y; - elmHeight = elm.clientHeight; - - // Is element within viewport if not then scroll it into view - if (y < vp.y || y + elmHeight > vp.y + vp.h) - ed.getDoc().body.scrollTop = y < vp.y ? y : y - vp.h + 25; - }, - /** * Inserts the specified contents at the caret position. */ @@ -724,8 +735,7 @@ if (!ed.selection.isCollapsed() && r.startContainer != r.endContainer) ed.getDoc().execCommand('Delete', false, null); - // It's better to use the insertHTML method on Gecko since it will combine paragraphs correctly before inserting the contents - ed.execCommand(tinymce.isGecko ? 'insertHTML' : 'mceInsertContent', false, h, {skip_undo : skip_undo}); + ed.execCommand('mceInsertContent', false, h, {skip_undo : skip_undo}); }, /** @@ -757,9 +767,6 @@ }; if ((typeof(h) === "string") && (h.length > 0)) { - if (!entities) - entities = ("34,quot,38,amp,39,apos,60,lt,62,gt," + ed.serializer.settings.entities).split(","); - // If HTML content with line-breaking tags, then remove all cr/lf chars because only tags will break a line if (/<(?:p|br|h[1-6]|ul|ol|dl|table|t[rdh]|div|blockquote|fieldset|pre|address|center)[^>]*>/i.test(h)) { process([ @@ -778,26 +785,12 @@ [/<\/t[dh]>\s*]*>/gi, "\t"], // Table cells get tabs betweem them /<[a-z!\/?][^>]*>/gi, // Delete all remaining tags [/ /gi, " "], // Convert non-break spaces to regular spaces (remember, *plain text*) - [ - // HTML entity - /&(#\d+|[a-z0-9]{1,10});/gi, - - // Replace with actual character - function(e, s) { - if (s.charAt(0) === "#") { - return String.fromCharCode(s.slice(1)); - } - else { - return ((e = inArray(entities, s)) > 0)? String.fromCharCode(entities[e-1]) : " "; - } - } - ], [/(?:(?!\n)\s)*(\n+)(?:(?!\n)\s)*/gi, "$1"], // Cool little RegExp deletes whitespace around linebreak chars. [/\n{3,}/g, "\n\n"], // Max. 2 consecutive linebreaks /^\s+|\s+$/g // Trim the front & back ]); - h = dom.encode(h); + h = dom.decode(tinymce.html.Entities.encodeRaw(h)); // Delete any highlighted text before pasting if (!sel.isCollapsed()) { diff --git a/program/js/tiny_mce/plugins/searchreplace/editor_plugin.js b/program/js/tiny_mce/plugins/searchreplace/editor_plugin.js index cd9c985..165bc12 100644 --- a/program/js/tiny_mce/plugins/searchreplace/editor_plugin.js +++ b/program/js/tiny_mce/plugins/searchreplace/editor_plugin.js @@ -1 +1 @@ -(function(){tinymce.create("tinymce.plugins.SearchReplacePlugin",{init:function(a,c){function b(d){a.windowManager.open({file:c+"/searchreplace.htm",width:420+parseInt(a.getLang("searchreplace.delta_width",0)),height:170+parseInt(a.getLang("searchreplace.delta_height",0)),inline:1,auto_focus:0},{mode:d,search_string:a.selection.getContent({format:"text"}),plugin_url:c})}a.addCommand("mceSearch",function(){b("search")});a.addCommand("mceReplace",function(){b("replace")});a.addButton("search",{title:"searchreplace.search_desc",cmd:"mceSearch"});a.addButton("replace",{title:"searchreplace.replace_desc",cmd:"mceReplace"});a.addShortcut("ctrl+f","searchreplace.search_desc","mceSearch")},getInfo:function(){return{longname:"Search/Replace",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/searchreplace",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("searchreplace",tinymce.plugins.SearchReplacePlugin)})(); \ No newline at end of file +(function(){tinymce.create("tinymce.plugins.SearchReplacePlugin",{init:function(a,c){function b(d){window.focus();a.windowManager.open({file:c+"/searchreplace.htm",width:420+parseInt(a.getLang("searchreplace.delta_width",0)),height:170+parseInt(a.getLang("searchreplace.delta_height",0)),inline:1,auto_focus:0},{mode:d,search_string:a.selection.getContent({format:"text"}),plugin_url:c})}a.addCommand("mceSearch",function(){b("search")});a.addCommand("mceReplace",function(){b("replace")});a.addButton("search",{title:"searchreplace.search_desc",cmd:"mceSearch"});a.addButton("replace",{title:"searchreplace.replace_desc",cmd:"mceReplace"});a.addShortcut("ctrl+f","searchreplace.search_desc","mceSearch")},getInfo:function(){return{longname:"Search/Replace",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/searchreplace",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("searchreplace",tinymce.plugins.SearchReplacePlugin)})(); \ No newline at end of file diff --git a/program/js/tiny_mce/plugins/searchreplace/editor_plugin_src.js b/program/js/tiny_mce/plugins/searchreplace/editor_plugin_src.js index 1433a06..4c87e8f 100644 --- a/program/js/tiny_mce/plugins/searchreplace/editor_plugin_src.js +++ b/program/js/tiny_mce/plugins/searchreplace/editor_plugin_src.js @@ -12,6 +12,10 @@ tinymce.create('tinymce.plugins.SearchReplacePlugin', { init : function(ed, url) { function open(m) { + // Keep IE from writing out the f/r character to the editor + // instance while initializing a new dialog. See: #3131190 + window.focus(); + ed.windowManager.open({ file : url + '/searchreplace.htm', width : 420 + parseInt(ed.getLang('searchreplace.delta_width', 0)), diff --git a/program/js/tiny_mce/plugins/searchreplace/js/searchreplace.js b/program/js/tiny_mce/plugins/searchreplace/js/searchreplace.js index c0a6243..80284b9 100644 --- a/program/js/tiny_mce/plugins/searchreplace/js/searchreplace.js +++ b/program/js/tiny_mce/plugins/searchreplace/js/searchreplace.js @@ -2,14 +2,18 @@ tinyMCEPopup.requireLangPack(); var SearchReplaceDialog = { init : function(ed) { - var f = document.forms[0], m = tinyMCEPopup.getWindowArg("mode"); + var t = this, f = document.forms[0], m = tinyMCEPopup.getWindowArg("mode"); - this.switchMode(m); + t.switchMode(m); f[m + '_panel_searchstring'].value = tinyMCEPopup.getWindowArg("search_string"); // Focus input field f[m + '_panel_searchstring'].focus(); + + mcTabs.onChange.add(function(tab_id, panel_id) { + t.switchMode(tab_id.substring(0, tab_id.indexOf('_'))); + }); }, switchMode : function(m) { @@ -42,21 +46,23 @@ var SearchReplaceDialog = { ca = f[m + '_panel_casesensitivebox'].checked; rs = f['replace_panel_replacestring'].value; + if (tinymce.isIE) { + r = ed.getDoc().selection.createRange(); + } + if (s == '') return; function fix() { // Correct Firefox graphics glitches + // TODO: Verify if this is actually needed any more, maybe it was for very old FF versions? r = se.getRng().cloneRange(); ed.getDoc().execCommand('SelectAll', false, null); se.setRng(r); }; function replace() { - if (tinymce.isIE) - ed.selection.getRng().duplicate().pasteHTML(rs); // Needs to be duplicated due to selection bug in IE - else - ed.getDoc().execCommand('InsertHTML', false, rs); + ed.selection.setContent(rs); // Needs to be duplicated due to selection bug in IE }; // IE flags @@ -70,6 +76,9 @@ var SearchReplaceDialog = { ed.selection.collapse(true); if (tinymce.isIE) { + ed.focus(); + r = ed.getDoc().selection.createRange(); + while (r.findText(s, b ? -1 : 1, fl)) { r.scrollIntoView(); r.select(); @@ -111,6 +120,9 @@ var SearchReplaceDialog = { return; if (tinymce.isIE) { + ed.focus(); + r = ed.getDoc().selection.createRange(); + if (r.findText(s, b ? -1 : 1, fl)) { r.scrollIntoView(); r.select(); diff --git a/program/js/tiny_mce/plugins/searchreplace/searchreplace.htm b/program/js/tiny_mce/plugins/searchreplace/searchreplace.htm index d0424cf..5a22d8a 100644 --- a/program/js/tiny_mce/plugins/searchreplace/searchreplace.htm +++ b/program/js/tiny_mce/plugins/searchreplace/searchreplace.htm @@ -8,27 +8,28 @@ - + +
    - +
    - +
    - - - +
    + + @@ -39,7 +40,7 @@