]> git.donarmstrong.com Git - roundcube.git/commitdiff
Imported Upstream version 0.7
authorVincent Bernat <bernat@luffy.cx>
Fri, 23 Dec 2011 21:03:08 +0000 (22:03 +0100)
committerVincent Bernat <bernat@luffy.cx>
Fri, 23 Dec 2011 21:03:08 +0000 (22:03 +0100)
240 files changed:
CHANGELOG
INSTALL
INSTALL.orig [new file with mode: 0644]
SQL/mssql.initial.sql
SQL/mssql.upgrade.sql
SQL/mysql.initial.sql
SQL/mysql.update.sql
SQL/postgres.initial.sql
SQL/postgres.update.sql
SQL/sqlite.initial.sql
SQL/sqlite.update.sql
bin/indexcontacts.sh
bin/installto.sh
bin/jsshrink.sh
config/db.inc.php.dist
config/main.inc.php.dist
index.php
installer/rcube_install.php
installer/test.php
plugins/acl/acl.js
plugins/acl/acl.php
plugins/acl/skins/default/acl.css
plugins/archive/archive.js
plugins/archive/archive.php
plugins/archive/localization/fr_FR.inc
plugins/archive/package.xml
plugins/enigma/README
plugins/enigma/config.inc.php [deleted file]
plugins/enigma/config.inc.php.dist [new file with mode: 0644]
plugins/enigma/lib/enigma_ui.php
plugins/http_authentication/http_authentication.php
plugins/managesieve/Changelog
plugins/managesieve/config.inc.php.dist
plugins/managesieve/lib/rcube_sieve.php
plugins/managesieve/lib/rcube_sieve_script.php
plugins/managesieve/localization/de_CH.inc
plugins/managesieve/localization/de_DE.inc
plugins/managesieve/localization/en_US.inc
plugins/managesieve/localization/es_ES.inc
plugins/managesieve/localization/lv_LV.inc [new file with mode: 0644]
plugins/managesieve/localization/pl_PL.inc
plugins/managesieve/localization/pt_BR.inc
plugins/managesieve/managesieve.js
plugins/managesieve/managesieve.php
plugins/managesieve/package.xml [new file with mode: 0644]
plugins/managesieve/skins/default/images/add.png [new file with mode: 0644]
plugins/managesieve/skins/default/images/del.png [new file with mode: 0644]
plugins/managesieve/skins/default/images/down_small.gif [new file with mode: 0644]
plugins/managesieve/skins/default/images/filter.png [new file with mode: 0644]
plugins/managesieve/skins/default/images/up_small.gif [new file with mode: 0644]
plugins/managesieve/skins/default/managesieve.css
plugins/managesieve/skins/default/managesieve_mail.css [new file with mode: 0644]
plugins/managesieve/skins/default/managesieve_toolbar.png [deleted file]
plugins/managesieve/skins/default/templates/filteredit.html
plugins/managesieve/skins/default/templates/managesieve.html
plugins/managesieve/tests/parser.phpt
plugins/managesieve/tests/parser_body.phpt [new file with mode: 0644]
plugins/managesieve/tests/parser_imapflags.phpt [new file with mode: 0644]
plugins/managesieve/tests/parser_include.phpt [new file with mode: 0644]
plugins/managesieve/tests/parser_kep14.phpt [new file with mode: 0644]
plugins/managesieve/tests/parser_prefix.phpt [new file with mode: 0644]
plugins/managesieve/tests/parser_relational.phpt [new file with mode: 0644]
plugins/managesieve/tests/parser_vacation.phpt [new file with mode: 0644]
plugins/managesieve/tests/parser_variables.phpt [new file with mode: 0644]
plugins/managesieve/tests/parset_subaddress.phpt [new file with mode: 0644]
plugins/new_user_dialog/localization/bg_BG.inc [new file with mode: 0644]
plugins/newmail_notifier/config.inc.php.dist
plugins/newmail_notifier/localization/de_CH.inc [new file with mode: 0644]
plugins/newmail_notifier/localization/de_DE.inc [new file with mode: 0644]
plugins/newmail_notifier/localization/en_US.inc
plugins/newmail_notifier/localization/lv_LV.inc [new file with mode: 0644]
plugins/newmail_notifier/localization/pl_PL.inc
plugins/newmail_notifier/localization/pt_BR.inc [new file with mode: 0644]
plugins/newmail_notifier/localization/ru_RU.inc [new file with mode: 0644]
plugins/newmail_notifier/mail.png [new file with mode: 0644]
plugins/newmail_notifier/newmail_notifier.js
plugins/newmail_notifier/newmail_notifier.php
plugins/password/config.inc.php.dist
plugins/password/drivers/ldap.php
plugins/password/drivers/ldap_simple.php
plugins/password/drivers/sql.php
plugins/password/package.xml
plugins/password/password.php
plugins/userinfo/localization/fr_FR.inc [new file with mode: 0644]
plugins/userinfo/localization/ro_RO.inc [new file with mode: 0644]
program/include/clisetup.php
program/include/iniset.php
program/include/main.inc
program/include/rcmail.php
program/include/rcmail.php.orig [new file with mode: 0644]
program/include/rcube_addressbook.php
program/include/rcube_browser.php
program/include/rcube_cache.php
program/include/rcube_config.php
program/include/rcube_contacts.php
program/include/rcube_html_page.php
program/include/rcube_imap.php
program/include/rcube_imap_cache.php [new file with mode: 0644]
program/include/rcube_imap_generic.php
program/include/rcube_json_output.php
program/include/rcube_ldap.php
program/include/rcube_mdb2.php
program/include/rcube_message.php
program/include/rcube_mime_struct.php
program/include/rcube_plugin.php
program/include/rcube_plugin_api.php
program/include/rcube_result_set.php
program/include/rcube_session.php
program/include/rcube_shared.inc
program/include/rcube_smtp.php
program/include/rcube_spellchecker.php
program/include/rcube_string_replacer.php
program/include/rcube_template.php
program/include/rcube_user.php
program/include/rcube_vcard.php
program/js/app.js
program/js/app.js.src
program/js/common.js
program/js/common.js.src
program/js/editor.js
program/js/googiespell.js
program/js/googiespell.js.src
program/js/list.js
program/js/list.js.src
program/lib/html2text.php
program/lib/washtml.php
program/localization/ar_SA/labels.inc
program/localization/ar_SA/messages.inc
program/localization/bg_BG/labels.inc
program/localization/bg_BG/messages.inc
program/localization/ca_ES/labels.inc
program/localization/ca_ES/messages.inc
program/localization/cs_CZ/labels.inc
program/localization/cs_CZ/messages.inc
program/localization/cy_GB/labels.inc
program/localization/cy_GB/messages.inc
program/localization/da_DK/labels.inc
program/localization/da_DK/messages.inc
program/localization/de_CH/labels.inc
program/localization/de_CH/messages.inc
program/localization/de_DE/labels.inc
program/localization/de_DE/messages.inc
program/localization/en_GB/labels.inc
program/localization/en_GB/messages.inc
program/localization/en_US/labels.inc
program/localization/en_US/messages.inc
program/localization/es_ES/labels.inc
program/localization/es_ES/messages.inc
program/localization/et_EE/messages.inc
program/localization/fr_FR/labels.inc
program/localization/fr_FR/messages.inc
program/localization/gl_ES/labels.inc
program/localization/gl_ES/messages.inc
program/localization/he_IL/labels.inc
program/localization/he_IL/messages.inc
program/localization/hr_HR/messages.inc
program/localization/hu_HU/labels.inc
program/localization/hu_HU/messages.inc
program/localization/id_ID/messages.inc
program/localization/it_IT/labels.inc
program/localization/it_IT/messages.inc
program/localization/ja_JP/labels.inc
program/localization/ja_JP/messages.inc
program/localization/ka_GE/labels.inc
program/localization/ka_GE/messages.inc
program/localization/lt_LT/labels.inc
program/localization/lt_LT/messages.inc
program/localization/lv_LV/labels.inc
program/localization/lv_LV/messages.inc
program/localization/nl_NL/labels.inc
program/localization/nl_NL/messages.inc
program/localization/nn_NO/labels.inc
program/localization/pl_PL/labels.inc
program/localization/pl_PL/messages.inc
program/localization/pt_BR/labels.inc
program/localization/pt_BR/messages.inc
program/localization/pt_PT/labels.inc
program/localization/pt_PT/messages.inc
program/localization/ru_RU/labels.inc
program/localization/ru_RU/messages.inc
program/localization/sk_SK/labels.inc
program/localization/sk_SK/messages.inc
program/localization/sl_SI/labels.inc
program/localization/sl_SI/messages.inc
program/localization/sv_SE/labels.inc
program/localization/sv_SE/messages.inc
program/localization/tr_TR/labels.inc
program/localization/tr_TR/messages.inc
program/localization/uk_UA/labels.inc
program/localization/uk_UA/messages.inc
program/localization/zh_CN/labels.inc
program/localization/zh_CN/messages.inc
program/steps/addressbook/copy.inc
program/steps/addressbook/export.inc
program/steps/addressbook/func.inc
program/steps/addressbook/import.inc
program/steps/addressbook/list.inc
program/steps/addressbook/mailto.inc
program/steps/addressbook/save.inc
program/steps/addressbook/search.inc
program/steps/addressbook/upload_photo.inc
program/steps/mail/addcontact.inc
program/steps/mail/attachments.inc
program/steps/mail/autocomplete.inc
program/steps/mail/check_recent.inc
program/steps/mail/compose.inc
program/steps/mail/folders.inc
program/steps/mail/func.inc
program/steps/mail/get.inc
program/steps/mail/list.inc
program/steps/mail/mark.inc
program/steps/mail/move_del.inc
program/steps/mail/search.inc
program/steps/mail/sendmail.inc
program/steps/mail/show.inc
program/steps/settings/edit_folder.inc
program/steps/settings/edit_identity.inc
program/steps/settings/folders.inc
program/steps/settings/func.inc
program/steps/settings/save_folder.inc
program/steps/settings/save_prefs.inc
program/steps/utils/killcache.inc
program/steps/utils/spell.inc
program/steps/utils/spell_html.inc
skins/default/addressbook.css
skins/default/common.css
skins/default/editor_content.css
skins/default/functions.js
skins/default/ie6hacks.css
skins/default/images/icons/folders.gif
skins/default/images/icons/folders.png
skins/default/images/messageicons.gif
skins/default/images/messageicons.png
skins/default/includes/messagetoolbar.html
skins/default/mail.css
skins/default/print.css
skins/default/templates/addressbook.html
skins/default/templates/mail.html
skins/default/templates/message.html
skins/default/templates/messagepreview.html

index f4daec427835436b174b8fcb134b1d0f5b2972c3..c872df37846db35d22b7a07b7bd53cdc5053e6b6 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,96 +1,80 @@
 CHANGELOG Roundcube Webmail
 ===========================
 
 CHANGELOG Roundcube Webmail
 ===========================
 
-- Fix bug where the last identity is used on reply (#1488101)
-- Fix locked folder rename option on servers supporting RFC2086 only (#1488089)
-- Fix encoding of LDAP contacts identifiers (#1488079)
-- Fix session race conditions when composing new messages
-- jQuery 1.6.4
-- Fix handling of binary attachments encoded with quoted-printable (#1488065)
-- Fix text-overflow:ellipsis issues on messages list in FF7 and Webkit (#1488061)
-- Fix handling of links with IP address
-- Fix bug where message list filter was reset on folder compacting (#1488076)
+RELEASE 0.7
+-----------
+- Make Roundcube render the Email Standards Project Acid Test correctly
+- Replace prompt() with jQuery UI dialog (#1485135)
+- Fix navigation in messages search results
+- Improved handling of some malformed values encoded with quoted-printable (#1488232)
+- Add possibility to do LDAP bind before searching for bind DN
+- Fix handling of empty <U> tags in HTML messages (#1488225)
+- Add content filter for embedded attachments to protect from XSS on IE (#1487895)
+- Use strpos() instead of strstr() when possible (#1488211)
+- Fix handling HTML entities when converting HTML to text (#1488212)
+- Fix fit_string_to_size() renders browser and ui unresponsive (#1488207)
+- Fix handling of invalid characters in request (#1488124)
+- Fix merging some configuration options in update.sh script (#1485864)
+- Fix so TEXT key will remove all HEADER keys in IMAP SEARCH (#1488208)
+- Fix handling contact photo url with https:// prefix (#1488202)
+- Fix possible infinite redirect on attachment preview (#1488199)
+- Improved clickjacking protection for browsers which don't support X-Frame-Options headers
+- Fixed bug where similiar folder names were highlighted wrong (#1487860)
+- Fixed bug in handling link with '!' character in it (#1488195)
+- Fixed bug where session ID's length was limited to 40 characters (#1488196)
+- TinyMCE security issue: removed moxieplayer (embedding flv and mp4 is not supported anymore)
 
 
-RELEASE 0.6-RC
---------------
-- jQuery 1.6.3
-- Fallback to mail_domain in LDAP variable replacements; added 'host' to 'user_create' hook arguments (#1488024)
-- Fixed wrong vCard type parameter mobile (#1488067)
-- Fixed vCard WORKFAX issue (#1488046)
-- Add vCard's Profile URL support (#1488062)
-- Fix imap_cache setting to values other than 'db' (#1488060)
-- Fix handling of attachments inside message/rfc822 parts (#1488026)
-- Make list of mimetypes that open in preview window configurable (#1487625)
-- Added plugin hook 'message_part_get' for attachment downloads
-- Fixed selecting identity on reply/forward (#1487981)
-- Fix image type check for contact photo uploads
-
-RELEASE 0.6-beta
+RELEASE 0.7-beta
 ----------------
 ----------------
-- Added unique connection identifier to IMAP debug messages
-- Add option to hide selected LDAP addressbook on the list
-- Add client-side checking of uploaded files size
-- Add newlines between organization, department, jobtitle (#1488028)
-- Recalculate date when replying to a message and localize the cite header (#1487675)
-- Fix handling of email addresses with quoted local part (#1487939)
-- Fix EOL character in vCard exports (#1487873)
-- Added optional "multithreading" autocomplete feature
-- Plugin API: Added 'config_get' hook
-- Fixed new_user_identity plugin to work with updated rcube_ldap class (#1487994)
-- Plugin API: added folder_delete and folder_rename hooks
-- Added possibility to undo last contact delete operation
-- Fix sorting of contact groups after group create (#1487747)
-- Add optional textual upload progress indicator (#1486039)
-- Fix parsing URLs containing commas (#1487970)
-- Added vertical splitter for books/groups list in addressbook (#1487923)
-- Improved namespace roots handling in folder manager
-- Added searching in all addressbook sources
-- Added addressbook source selection in contacts import
-- Implement LDAPv3 Virtual List View (VLV) for paged results listing
-- Use 'address_template' config option when adding a new address block (#1487944)
-- Added addressbook advanced search
-- Add popup with basic fields selection for addressbook search
-- Case-insensitive matching in autocompletion (#1487933)
-- Added option to force spellchecking before sending a message (#1485458)
-- Fix handling of "<" character in contact data, search fields and folder names (#1487864)
-- Fix saving "<" character in identity name and organization fields (#1487864)
-- Added option to specify to which address book add new contacts
-- Added plugin hook for keep-alive requests
-- Store user preferences in session when write-master is not available and session is stored in memcache, write them later
-- Improve performence of folder manager operations
-- Fix default_port option handling in Installer when config.inc.php file exists (#1487925)
-- Removed option focus_on_new_message, added newmail_notifier plugin
-- Added general rcube_cache class with Memcache and APC support
-- Improved caching performance by skipping writes of unchanged data
-- Option enable_caching replaced by imap_cache and messages_cache options
-- Fix WORKFAX saving in address book (#1487910)
-- Add forward-as-attachment feature
-- jQuery-1.6.2 (#1487913, #1487144)
-- Improve display name composition when saving contacts (#1487143)
-- Fix problems with subfolders of INBOX folder on some IMAP servers (#1487725)
-- Fix handling of folders that doesn't belong to any namespace (#1487637)
-- Enable multiselection for attachments uploading in capable browsers (#1485969)
-- Add possibility to change HTML editor configuration by skin
-- Fix a bug where selecting too many contacts would produce too large URI request (#1487892)
-- Improve performance by including files with absolute path (#1487849)
-- Move folder name truncation to client/skin (#1485412)
-- Added plugin hook for request token creation
-- Replace LDAP vars in group queries (#1487837)
-- Fix vcard folding with uncode characters (#1487868)
-- Keep all submitted data if contact form validation fails (#1487865)
-- Handle uncode strings in rcube_addressbook::normalize_string() (#1487866)
-- Fix handling of debug_level=4 in ajax requests (#1487831)
-- Enable TinyMCE's contextmenu (#1487014)
-- Allow multiple concurrent compose sessions
-- New config option for custom logo
-- Allow skins to define/override texts with <roundcube:label />
-- Add simple ACL rights/namespace handling in folder manager
-- Force IE to send referers (#1487806)
-- Better display of vcard import results (#1485457)
-- Improved vcard import
-- Interactive update script with improved DB schema check
-- Fix problem with contactgroupmembers table creation on MySQL 4.x, add index on contact_id column
-- Add LDAP SASL bind and proxy authentication (#1486692)
-- Replying to a sent message puts the old recipient as the new recipient (#1487074)
-- Fulltext search over (almost) all data for contacts
-- Extend address book with rich contact information
+- Fix handling of HTML form elements in messages (#1485137)
+- Fix regression in setting recipient to self when replying to a Sent message (#1487074)
+- Fix listing of folders in hidden namespaces (#1486796)
+- Don't consider \Noselect flag when building folders tree (#1488004)
+- Fix sorting autocomplete results (#1488084)
+- Add option to set session name (#1486433)
+- Add option to skip alternative email addresses in autocompletion
+- Fix inconsistent behaviour of Compose button in Drafts folder, add Edit button for drafts
+- Fix problem with parsing HTML message body with non-unicode characters (#1487813)
+- Add option to define matching method for addressbook search (#1486564, #1487907)
+- Make email recipients separator configurable
+- Fix so folders with \Noinferiors attribute aren't listed in parent selector
+- Fix handling of curly brackets in URLs (#1488168)
+- Fix handling of dates (birthday/anniversary) in contact data (#1488147)
+- Fix error on opening searched LDAP contact (#1488144)
+- Fix redundant line break in flowed format (#1488146)
+- Fix IDN address validation issue (#1488137)
+- Fix JS error when dst_active checkbox doesn't exist (#1488133)
+- Autocomplete LDAP records when adding contacts from mail (#1488073)
+- Plugin API: added 'ready' hook (#1488063)
+- Ignore DSN request when it isn't supported by SMTP server (#1487800)
+- Make sure LDAP name fields aren't arrays (#1488108)
+- Fixed imap test to non-default port when using ssl (#1488118)
+- Force all files to be overwritten when updating (#1488117)
+- Fix issue where it wasn't possible to change list view mode in folder manager for INBOX (#1488107)
+- Fix namespace handling in special folders settings (#1488112)
+- Disable time limit for CLI scripts (#1488109)
+- Fix misleading display when chaning editor type (#1488104)
+- Add loading indicator on contact delete
+- Fix bug where after delete message rows can be added to the list of another folder (#1487752)
+- Add notice on autocompletion that not all records were displayed
+- Add option 'searchonly' for LDAP address books
+- Add Priority filter to the messages list
+- Cache synchronization using QRESYNC/CONDSTORE
+- Trigger 'new_messages' hook for all checked folders (#1488083)
+- Make date/time format user configurable; drop 'date_today' config option
+- Fix setting title for truncated subject in IE (#1487128)
+- Fix displaying multipart/alternative messages with only one part (#1487938)
+- Rewritten messages caching:
+  Indexes are stored in a separate table, so there's no need to store all messages in a folder
+  Added threads data caching
+  Flags are stored separately, so flag change doesn't cause DELETE+INSERT, just UPDATE
+- Improved FETCH response handling
+- Improvements in response tokenization method
+- Use 'From' and 'To' labels instead of 'Sender' and 'Recipient'
+- Fix username case-insensitivity issue in MySQL (#1488021)
+- Addressbook Saved Searches
+- Added spellchecker exceptions dictionary (shared or per-user)
+- Added possibility to ignore words containing caps, numbers, symbols (spellcheck_ignore_* options)
+- Added 'priority' column on messages list (#1486782)
+- Localize forwarded message header (#1488058)
+
diff --git a/INSTALL b/INSTALL
index 9b07b2bcba5a3b21b497854d71275efb7d9a44f9..3fc6f5dfef03db456be5b70ead9a7105a6dbacd9 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -9,7 +9,7 @@ wiki page at http://trac.roundcube.net/wiki
 REQUIREMENTS
 ============
 
 REQUIREMENTS
 ============
 
-* The Apache or Lighttpd Webserver
+* The Apache, Lighttpd, Cherokee or Hiawatha web server
 * .htaccess support allowing overrides for DirectoryIndex
 * PHP Version 5.2.1 or greater including
    - PCRE, DOM, JSON, XML, Session, Sockets (required)
 * .htaccess support allowing overrides for DirectoryIndex
 * PHP Version 5.2.1 or greater including
    - PCRE, DOM, JSON, XML, Session, Sockets (required)
diff --git a/INSTALL.orig b/INSTALL.orig
new file mode 100644 (file)
index 0000000..493baf7
--- /dev/null
@@ -0,0 +1,233 @@
+INTRODUCTION
+============
+
+This file describes the basic steps to install Roundcube Webmail on your
+web server. For additional information, please also consult the project's
+wiki page at http://trac.roundcube.net/wiki
+
+
+REQUIREMENTS
+============
+
+* The Apache, Lighttpd, Cherokee or Hiawatha web server
+* .htaccess support allowing overrides for DirectoryIndex
+* PHP Version 5.2.1 or greater including
+   - PCRE, DOM, JSON, XML, Session, Sockets (required)
+   - libiconv (recommended)
+   - mbstring, fileinfo, mcrypt (optional)
+* PEAR packages distributed with Roundcube or external:
+   - 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)
+   - memory_limit > 16MB (increase as suitable to support large attachments)
+   - file_uploads enabled (for attachment upload features)
+   - session.auto_start disabled
+   - zend.ze1_compatibility_mode disabled
+   - suhosin.session.encrypt disabled
+   - mbstring.func_overload disabled
+   - magic_quotes_runtime disabled
+* PHP compiled with OpenSSL to connect to IMAPS and to use the spell checker
+* A MySQL (4.0.8 or newer), PostgreSQL, MSSQL database engine
+  or the SQLite extension for PHP
+* One of the above databases with permission to create tables
+* An SMTP server (recommended) or PHP configured for mail delivery
+
+
+INSTALLATION
+============
+
+1. Decompress and put this folder somewhere inside your document root
+2. Make sure that the following directories (and the files within)
+   are writable by the webserver
+   - /temp
+   - /logs
+3. Create a new database and a database user for Roundcube (see DATABASE SETUP)
+4. Point your browser to http://url-to-roundcube/installer/
+5. Follow the instructions of the install script (or see MANUAL CONFIGURATION)
+6. After creating and testing the configuration, remove the installer directory
+7. Done!
+
+
+CONFIGURATION HINTS
+===================
+
+Roundcube writes internal errors to the 'errors' log file located in the logs
+directory which can be configured in config/main.inc.php. If you want ordinary
+PHP errors to be logged there as well, enable the 'php_value error_log' line
+in the .htaccess file and set the path to the log file accordingly.
+
+By default the session_path settings of PHP are not modified by Roundcube.
+However if you want to limit the session cookies to the directory where
+Roundcube resides you can uncomment and configure the according line
+in the .htaccess file.
+
+
+DATABASE SETUP
+==============
+
+Note: Database for Roundcube must use UTF-8 character set.
+
+* MySQL
+-------
+Setting up the mysql database can be done by creating an empty database,
+importing the table layout and granting the proper permissions to the
+roundcube user. Here is an example of that procedure:
+
+# mysql
+> CREATE DATABASE roundcubemail /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
+> GRANT ALL PRIVILEGES ON roundcubemail.* TO roundcube@localhost
+    IDENTIFIED BY 'password';
+> quit
+
+# mysql roundcubemail < SQL/mysql.initial.sql
+
+Note 1: 'password' is the master password for the roundcube user. It is strongly
+recommended you replace this with a more secure password. Please keep in
+mind: You need to specify this password later in 'config/db.inc.php'.
+
+
+* SQLite
+--------
+You need sqlite 2 (preferably 2.8) to setup the sqlite db 
+(sqlite 3.x also doesn't work at the moment). Here is
+an example how you can setup the sqlite.db for roundcube:
+
+# sqlite -init SQL/sqlite.initial.sql sqlite.db
+Loading resources from SQL/sqlite.initial.sql
+SQLite version 2.8.16
+Enter ".help" for instructions
+sqlite> .exit
+# chmod o+rw sqlite.db
+
+Make sure your configuration points to the sqlite.db file and that the
+webserver can write to the file and the directory containing the file.
+
+
+* PostgreSQL
+------------
+To use Roundcube with PostgreSQL support you have to follow these
+simple steps, which have to be done as the postgres system user (or
+which ever is the database superuser):
+
+$ createuser roundcube
+$ createdb -O roundcube -E UNICODE roundcubemail
+$ psql roundcubemail
+
+roundcubemail =# ALTER USER roundcube WITH PASSWORD 'the_new_password';
+roundcubemail =# \c - roundcube
+roundcubemail => \i SQL/postgres.initial.sql
+
+All this has been tested with PostgreSQL 8.x and 7.4.x. Older
+versions don't have a -O option for the createdb, so if you are
+using that version you'll have to change ownership of the DB later.
+
+
+Database cleaning
+-----------------
+Do keep your database slick and clean we recommend to periodically execute
+bin/cleandb.sh which finally removes all records that are marked as deleted.
+Best solution is to install a cronjob running this script daily.
+
+
+
+MANUAL CONFIGURATION
+====================
+
+First of all, rename the files config/*.inc.php.dist to config/*.inc.php.
+You can then change these files according to your environment and your needs.
+Details about the config parameters can be found in the config files.
+See http://trac.roundcube.net/wiki/Howto_Install for even more guidance.
+
+You can also modify the default .htaccess file. This is necessary to
+increase the allowed size of file attachments, for example:
+       php_value       upload_max_filesize     2M
+
+
+UPGRADING
+=========
+
+If you already have a previous version of Roundcube installed,
+please refer to the instructions in UPGRADING guide.
+
+
+OPTIMISING
+==========
+
+There are two forms of optimisation here, compression and caching, both aimed
+at increasing an end user's experience using Roundcube Webmail. Compression
+allows the static web pages to be delivered with less bandwidth. The index.php
+of Roundcube Webmail already enables compression on its output. The settings
+below allow compression to occur for all static files. Caching sets HTTP 
+response headers that enable a user's web client to understand what is static
+and how to cache it.
+
+The caching directives used are:
+ * Etags - sets at tag so the client can request is the page has changed
+ * Cache-control - defines the age of the page and that the page is 'public'
+   This enables clients to cache javascript files that don't have private 
+   information between sessions even if using HTTPS. It also allows proxies
+   to share the same cached page between users.
+ * Expires - provides another hint to increase the lifetime of static pages.
+
+For more information refer to RFC 2616.
+
+Side effects:
+-------------
+These directives are designed for production use. If you are using this in
+a development environment you may get horribly confused if your webclient
+is caching stuff that you changed on the server. Disabling the expires 
+parts below should save you some grief.
+
+If you are changing the skins, it is recommended that you copy content to 
+a different directory apart from 'default'.
+
+Apache:
+-------
+To enable these features in apache the following modules need to be enabled:
+ * mod_deflate
+ * mod_expires
+ * mod_headers
+
+The optimisation is already included in the .htaccess file in the top 
+directory of your installation.
+
+If you are using Apache version 2.2.9 and later, in the .htaccess file
+change the 'append' word to 'merge' for a more correct response. Keeping
+as 'append' shouldn't cause any problems though changing to merge will 
+eliminate the possibility of duplicate 'public' headers in Cache-control.
+
+Lighttpd:
+---------
+With Lightty the addition of Expire: tags by mod_expire is incompatible with
+the addition of "Cache-control: public". Using Cache-control 'public' is 
+used below as it is assumed to give a better caching result.
+
+Enable modules in server.modules:
+    "mod_setenv"
+    "mod_compress"
+
+Mod_compress is a server side cache of compressed files to improve its performance.
+
+$HTTP["host"] == "www.example.com" {
+
+    static-file.etags = "enable"
+    # http://redmine.lighttpd.net/projects/lighttpd/wiki/Etag.use-mtimeDetails
+    etag.use-mtime = "enable"
+
+    # http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs:ModSetEnv
+    $HTTP["url"] =~ "^/roundcubemail/(plugins|skins|program)" {
+        setenv.add-response-header  = ( "Cache-Control" => "public, max-age=2592000")
+    }
+
+    # http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs:ModCompress
+    # set compress.cache-dir to somewhere outside the docroot.
+    compress.cache-dir   = var.statedir + "/cache/compress"
+
+    compress.filetype = ("text/plain", "text/html", "text/javascript", "text/css", "text/xml", "image/gif", "image/png")
+}
+
+
index 4aa6fc9f7516112bc5fb5e08184ff786321276cf..c14114100993d3d0aec6516da4a7528cbf82f777 100644 (file)
@@ -7,6 +7,33 @@ CREATE TABLE [dbo].[cache] (
 ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]\r
 GO\r
 \r
 ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]\r
 GO\r
 \r
+CREATE TABLE [dbo].[cache_index] (\r
+       [user_id] [int] NOT NULL ,\r
+       [mailbox] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,\r
+       [changed] [datetime] NOT NULL ,\r
+       [valid] [char] (1) COLLATE Latin1_General_CI_AI NOT NULL ,\r
+       [data] [text] COLLATE Latin1_General_CI_AI NOT NULL \r
+) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]\r
+GO\r
+\r
+CREATE TABLE [dbo].[cache_thread] (\r
+       [user_id] [int] NOT NULL ,\r
+       [mailbox] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,\r
+       [changed] [datetime] NOT NULL ,\r
+       [data] [text] COLLATE Latin1_General_CI_AI NOT NULL \r
+) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]\r
+GO\r
+\r
+CREATE TABLE [dbo].[cache_messages] (\r
+       [user_id] [int] NOT NULL ,\r
+       [mailbox] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,\r
+       [uid] [int] NOT NULL ,\r
+       [changed] [datetime] NOT NULL ,\r
+       [data] [text] COLLATE Latin1_General_CI_AI NOT NULL \r
+       [flags] [int](1) NOT NULL ,\r
+) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]\r
+GO\r
+\r
 CREATE TABLE [dbo].[contacts] (\r
        [contact_id] [int] IDENTITY (1, 1) NOT NULL ,\r
        [user_id] [int] NOT NULL ,\r
 CREATE TABLE [dbo].[contacts] (\r
        [contact_id] [int] IDENTITY (1, 1) NOT NULL ,\r
        [user_id] [int] NOT NULL ,\r
@@ -53,27 +80,8 @@ CREATE TABLE [dbo].[identities] (
 ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]\r
 GO\r
 \r
 ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]\r
 GO\r
 \r
-CREATE TABLE [dbo].[messages] (\r
-       [message_id] [int] IDENTITY (1, 1) NOT NULL ,\r
-       [user_id] [int] NOT NULL ,\r
-       [del] [tinyint] NOT NULL ,\r
-       [cache_key] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,\r
-       [created] [datetime] NOT NULL ,\r
-       [idx] [int] NOT NULL ,\r
-       [uid] [int] NOT NULL ,\r
-       [subject] [varchar] (255) COLLATE Latin1_General_CI_AI NOT NULL ,\r
-       [from] [varchar] (255) COLLATE Latin1_General_CI_AI NOT NULL ,\r
-       [to] [varchar] (255) COLLATE Latin1_General_CI_AI NOT NULL ,\r
-       [cc] [varchar] (255) COLLATE Latin1_General_CI_AI NOT NULL ,\r
-       [date] [datetime] NOT NULL ,\r
-       [size] [int] NOT NULL ,\r
-       [headers] [text] COLLATE Latin1_General_CI_AI NOT NULL ,\r
-       [structure] [text] COLLATE Latin1_General_CI_AI NULL \r
-) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]\r
-GO\r
-\r
 CREATE TABLE [dbo].[session] (\r
 CREATE TABLE [dbo].[session] (\r
-       [sess_id] [varchar] (32) COLLATE Latin1_General_CI_AI NOT NULL ,\r
+       [sess_id] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,\r
        [created] [datetime] NOT NULL ,\r
        [changed] [datetime] NULL ,\r
        [ip] [varchar] (40) COLLATE Latin1_General_CI_AI NOT NULL ,\r
        [created] [datetime] NOT NULL ,\r
        [changed] [datetime] NULL ,\r
        [ip] [varchar] (40) COLLATE Latin1_General_CI_AI NOT NULL ,\r
@@ -93,6 +101,22 @@ CREATE TABLE [dbo].[users] (
 ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]\r
 GO\r
 \r
 ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]\r
 GO\r
 \r
+CREATE TABLE [dbo].[dictionary] (\r
+       [user_id] [int] ,\r
+       [language] [varchar] (5) COLLATE Latin1_General_CI_AI NOT NULL ,\r
+       [data] [text] COLLATE Latin1_General_CI_AI NOT NULL \r
+) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]\r
+GO\r
+\r
+CREATE TABLE [dbo].[searches] (\r
+       [search_id] [int] IDENTITY (1, 1) NOT NULL ,\r
+       [user_id] [int] NOT NULL ,\r
+       [type] [tinyint] NOT NULL ,\r
+       [name] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,\r
+       [data] [text] COLLATE Latin1_General_CI_AI NOT NULL \r
+) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]\r
+GO\r
+\r
 ALTER TABLE [dbo].[cache] WITH NOCHECK ADD \r
         PRIMARY KEY  CLUSTERED \r
        (\r
 ALTER TABLE [dbo].[cache] WITH NOCHECK ADD \r
         PRIMARY KEY  CLUSTERED \r
        (\r
@@ -100,6 +124,27 @@ ALTER TABLE [dbo].[cache] WITH NOCHECK ADD
        )  ON [PRIMARY] \r
 GO\r
 \r
        )  ON [PRIMARY] \r
 GO\r
 \r
+ALTER TABLE [dbo].[cache_index] WITH NOCHECK ADD \r
+        PRIMARY KEY CLUSTERED \r
+       (\r
+               [user_id],[mailbox]\r
+       ) ON [PRIMARY] \r
+GO\r
+\r
+ALTER TABLE [dbo].[cache_thread] WITH NOCHECK ADD \r
+        PRIMARY KEY CLUSTERED \r
+       (\r
+               [user_id],[mailbox]\r
+       ) ON [PRIMARY] \r
+GO\r
+\r
+ALTER TABLE [dbo].[cache_messages] WITH NOCHECK ADD \r
+        PRIMARY KEY CLUSTERED \r
+       (\r
+               [user_id],[mailbox],[uid]\r
+       ) ON [PRIMARY] \r
+GO\r
+\r
 ALTER TABLE [dbo].[contacts] WITH NOCHECK ADD \r
        CONSTRAINT [PK_contacts_contact_id] PRIMARY KEY  CLUSTERED \r
        (\r
 ALTER TABLE [dbo].[contacts] WITH NOCHECK ADD \r
        CONSTRAINT [PK_contacts_contact_id] PRIMARY KEY  CLUSTERED \r
        (\r
@@ -128,13 +173,6 @@ ALTER TABLE [dbo].[identities] WITH NOCHECK ADD
        )  ON [PRIMARY] \r
 GO\r
 \r
        )  ON [PRIMARY] \r
 GO\r
 \r
-ALTER TABLE [dbo].[messages] WITH NOCHECK ADD \r
-        PRIMARY KEY  CLUSTERED \r
-       (\r
-               [message_id]\r
-       )  ON [PRIMARY] \r
-GO\r
-\r
 ALTER TABLE [dbo].[session] WITH NOCHECK ADD \r
        CONSTRAINT [PK_session_sess_id] PRIMARY KEY  CLUSTERED \r
        (\r
 ALTER TABLE [dbo].[session] WITH NOCHECK ADD \r
        CONSTRAINT [PK_session_sess_id] PRIMARY KEY  CLUSTERED \r
        (\r
@@ -149,6 +187,13 @@ ALTER TABLE [dbo].[users] WITH NOCHECK ADD
        )  ON [PRIMARY] \r
 GO\r
 \r
        )  ON [PRIMARY] \r
 GO\r
 \r
+ALTER TABLE [dbo].[searches] WITH NOCHECK ADD \r
+       CONSTRAINT [PK_searches_search_id] PRIMARY KEY CLUSTERED \r
+       (\r
+               [search_id]\r
+       ) ON [PRIMARY] \r
+GO\r
+\r
 ALTER TABLE [dbo].[cache] ADD \r
        CONSTRAINT [DF_cache_user_id] DEFAULT ('0') FOR [user_id],\r
        CONSTRAINT [DF_cache_cache_key] DEFAULT ('') FOR [cache_key],\r
 ALTER TABLE [dbo].[cache] ADD \r
        CONSTRAINT [DF_cache_user_id] DEFAULT ('0') FOR [user_id],\r
        CONSTRAINT [DF_cache_cache_key] DEFAULT ('') FOR [cache_key],\r
@@ -164,6 +209,29 @@ GO
 CREATE  INDEX [IX_cache_created] ON [dbo].[cache]([created]) ON [PRIMARY]\r
 GO\r
 \r
 CREATE  INDEX [IX_cache_created] ON [dbo].[cache]([created]) ON [PRIMARY]\r
 GO\r
 \r
+ALTER TABLE [dbo].[cache_index] ADD \r
+       CONSTRAINT [DF_cache_index_changed] DEFAULT (getdate()) FOR [changed],\r
+       CONSTRAINT [DF_cache_index_valid] DEFAULT ('0') FOR [valid]\r
+GO\r
+\r
+CREATE  INDEX [IX_cache_index_user_id] ON [dbo].[cache_index]([user_id]) ON [PRIMARY]\r
+GO\r
+\r
+ALTER TABLE [dbo].[cache_thread] ADD \r
+       CONSTRAINT [DF_cache_thread_changed] DEFAULT (getdate()) FOR [changed]\r
+GO\r
+\r
+CREATE  INDEX [IX_cache_thread_user_id] ON [dbo].[cache_thread]([user_id]) ON [PRIMARY]\r
+GO\r
+\r
+ALTER TABLE [dbo].[cache_messages] ADD \r
+       CONSTRAINT [DF_cache_messages_changed] DEFAULT (getdate()) FOR [changed],\r
+       CONSTRAINT [DF_cache_messages_flags] DEFAULT (0) FOR [flags],\r
+GO\r
+\r
+CREATE  INDEX [IX_cache_messages_user_id] ON [dbo].[cache_messages]([user_id]) ON [PRIMARY]\r
+GO\r
+\r
 ALTER TABLE [dbo].[contacts] ADD \r
        CONSTRAINT [DF_contacts_user_id] DEFAULT (0) FOR [user_id],\r
        CONSTRAINT [DF_contacts_changed] DEFAULT (getdate()) FOR [changed],\r
 ALTER TABLE [dbo].[contacts] ADD \r
        CONSTRAINT [DF_contacts_user_id] DEFAULT (0) FOR [user_id],\r
        CONSTRAINT [DF_contacts_changed] DEFAULT (getdate()) FOR [changed],\r
@@ -215,33 +283,6 @@ GO
 CREATE  INDEX [IX_identities_user_id] ON [dbo].[identities]([user_id]) ON [PRIMARY]\r
 GO\r
 \r
 CREATE  INDEX [IX_identities_user_id] ON [dbo].[identities]([user_id]) ON [PRIMARY]\r
 GO\r
 \r
-ALTER TABLE [dbo].[messages] ADD \r
-       CONSTRAINT [DF_messages_user_id] DEFAULT (0) FOR [user_id],\r
-       CONSTRAINT [DF_messages_del] DEFAULT (0) FOR [del],\r
-       CONSTRAINT [DF_messages_cache_key] DEFAULT ('') FOR [cache_key],\r
-       CONSTRAINT [DF_messages_created] DEFAULT (getdate()) FOR [created],\r
-       CONSTRAINT [DF_messages_idx] DEFAULT (0) FOR [idx],\r
-       CONSTRAINT [DF_messages_uid] DEFAULT (0) FOR [uid],\r
-       CONSTRAINT [DF_messages_subject] DEFAULT ('') FOR [subject],\r
-       CONSTRAINT [DF_messages_from] DEFAULT ('') FOR [from],\r
-       CONSTRAINT [DF_messages_to] DEFAULT ('') FOR [to],\r
-       CONSTRAINT [DF_messages_cc] DEFAULT ('') FOR [cc],\r
-       CONSTRAINT [DF_messages_date] DEFAULT (getdate()) FOR [date],\r
-       CONSTRAINT [DF_messages_size] DEFAULT (0) FOR [size]\r
-GO\r
-\r
-CREATE  INDEX [IX_messages_user_id] ON [dbo].[messages]([user_id]) ON [PRIMARY]\r
-GO\r
-\r
-CREATE  INDEX [IX_messages_cache_key] ON [dbo].[messages]([cache_key]) ON [PRIMARY]\r
-GO\r
-\r
-CREATE  INDEX [IX_messages_uid] ON [dbo].[messages]([uid]) ON [PRIMARY]\r
-GO\r
-\r
-CREATE  INDEX [IX_messages_created] ON [dbo].[messages]([created]) ON [PRIMARY]\r
-GO\r
-\r
 ALTER TABLE [dbo].[session] ADD \r
        CONSTRAINT [DF_session_sess_id] DEFAULT ('') FOR [sess_id],\r
        CONSTRAINT [DF_session_created] DEFAULT (getdate()) FOR [created],\r
 ALTER TABLE [dbo].[session] ADD \r
        CONSTRAINT [DF_session_sess_id] DEFAULT ('') FOR [sess_id],\r
        CONSTRAINT [DF_session_created] DEFAULT (getdate()) FOR [created],\r
@@ -264,6 +305,17 @@ GO
 CREATE  INDEX [IX_users_alias] ON [dbo].[users]([alias]) ON [PRIMARY]\r
 GO\r
 \r
 CREATE  INDEX [IX_users_alias] ON [dbo].[users]([alias]) ON [PRIMARY]\r
 GO\r
 \r
+CREATE  UNIQUE INDEX [IX_dictionary_user_language] ON [dbo].[dictionary]([user_id],[language]) ON [PRIMARY]\r
+GO\r
+\r
+ALTER TABLE [dbo].[searches] ADD \r
+       CONSTRAINT [DF_searches_user] DEFAULT (0) FOR [user_id],\r
+       CONSTRAINT [DF_searches_type] DEFAULT (0) FOR [type],\r
+GO\r
+\r
+CREATE UNIQUE INDEX [IX_searches_user_type_name] ON [dbo].[searches]([user_id],[type],[name]) ON [PRIMARY]\r
+GO\r
+\r
 ALTER TABLE [dbo].[identities] ADD CONSTRAINT [FK_identities_user_id] \r
     FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])\r
     ON DELETE CASCADE ON UPDATE CASCADE\r
 ALTER TABLE [dbo].[identities] ADD CONSTRAINT [FK_identities_user_id] \r
     FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])\r
     ON DELETE CASCADE ON UPDATE CASCADE\r
@@ -284,7 +336,17 @@ ALTER TABLE [dbo].[cache] ADD CONSTRAINT [FK_cache_user_id]
     ON DELETE CASCADE ON UPDATE CASCADE\r
 GO\r
 \r
     ON DELETE CASCADE ON UPDATE CASCADE\r
 GO\r
 \r
-ALTER TABLE [dbo].[messages] ADD CONSTRAINT [FK_messages_user_id]\r
+ALTER TABLE [dbo].[cache_index] ADD CONSTRAINT [FK_cache_index_user_id]\r
+    FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])\r
+    ON DELETE CASCADE ON UPDATE CASCADE\r
+GO\r
+\r
+ALTER TABLE [dbo].[cache_thread] ADD CONSTRAINT [FK_cache_thread_user_id]\r
+    FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])\r
+    ON DELETE CASCADE ON UPDATE CASCADE\r
+GO\r
+\r
+ALTER TABLE [dbo].[cache_messages] ADD CONSTRAINT [FK_cache_messages_user_id]\r
     FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])\r
     ON DELETE CASCADE ON UPDATE CASCADE\r
 GO\r
     FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])\r
     ON DELETE CASCADE ON UPDATE CASCADE\r
 GO\r
@@ -294,6 +356,11 @@ ALTER TABLE [dbo].[contactgroupmembers] ADD CONSTRAINT [FK_contactgroupmembers_c
     ON DELETE CASCADE ON UPDATE CASCADE\r
 GO\r
 \r
     ON DELETE CASCADE ON UPDATE CASCADE\r
 GO\r
 \r
+ALTER TABLE [dbo].[searches] ADD CONSTRAINT [FK_searches_user_id]\r
+    FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])\r
+    ON DELETE CASCADE ON UPDATE CASCADE\r
+GO\r
+\r
 -- Use trigger instead of foreign key (#1487112)\r
 -- "Introducing FOREIGN KEY constraint ... may cause cycles or multiple cascade paths."\r
 CREATE TRIGGER [contact_delete_member] ON [dbo].[contacts]\r
 -- Use trigger instead of foreign key (#1487112)\r
 -- "Introducing FOREIGN KEY constraint ... may cause cycles or multiple cascade paths."\r
 CREATE TRIGGER [contact_delete_member] ON [dbo].[contacts]\r
index 606db60466f71e108e8e13c921b49511493a31c8..eee5ae560a5ce3bb3af34d043fe257788c48e466 100644 (file)
@@ -110,3 +110,137 @@ DELETE FROM [dbo].[messages]
 GO\r
 DELETE FROM [dbo].[cache]\r
 GO\r
 GO\r
 DELETE FROM [dbo].[cache]\r
 GO\r
+\r
+-- Updates from version 0.6\r
+\r
+CREATE TABLE [dbo].[dictionary] (\r
+    [user_id] [int] ,\r
+    [language] [varchar] (5) COLLATE Latin1_General_CI_AI NOT NULL ,\r
+    [data] [text] COLLATE Latin1_General_CI_AI NOT NULL \r
+) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]\r
+GO\r
+CREATE  UNIQUE INDEX [IX_dictionary_user_language] ON [dbo].[dictionary]([user_id],[language]) ON [PRIMARY]\r
+GO\r
+\r
+CREATE TABLE [dbo].[searches] (\r
+       [search_id] [int] IDENTITY (1, 1) NOT NULL ,\r
+       [user_id] [int] NOT NULL ,\r
+       [type] [tinyint] NOT NULL ,\r
+       [name] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,\r
+       [data] [text] COLLATE Latin1_General_CI_AI NOT NULL \r
+) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]\r
+GO\r
+\r
+ALTER TABLE [dbo].[searches] WITH NOCHECK ADD \r
+       CONSTRAINT [PK_searches_search_id] PRIMARY KEY CLUSTERED \r
+       (\r
+               [search_id]\r
+       ) ON [PRIMARY] \r
+GO\r
+\r
+ALTER TABLE [dbo].[searches] ADD \r
+       CONSTRAINT [DF_searches_user] DEFAULT (0) FOR [user_id],\r
+       CONSTRAINT [DF_searches_type] DEFAULT (0) FOR [type],\r
+GO\r
+\r
+CREATE UNIQUE INDEX [IX_searches_user_type_name] ON [dbo].[searches]([user_id],[type],[name]) ON [PRIMARY]\r
+GO\r
+\r
+ALTER TABLE [dbo].[searches] ADD CONSTRAINT [FK_searches_user_id]\r
+    FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])\r
+    ON DELETE CASCADE ON UPDATE CASCADE\r
+GO\r
+\r
+DROP TABLE [dbo].[messages]\r
+GO\r
+CREATE TABLE [dbo].[cache_index] (\r
+       [user_id] [int] NOT NULL ,\r
+       [mailbox] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,\r
+       [changed] [datetime] NOT NULL ,\r
+       [valid] [char] (1) COLLATE Latin1_General_CI_AI NOT NULL ,\r
+       [data] [text] COLLATE Latin1_General_CI_AI NOT NULL \r
+) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]\r
+GO\r
+\r
+CREATE TABLE [dbo].[cache_thread] (\r
+       [user_id] [int] NOT NULL ,\r
+       [mailbox] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,\r
+       [changed] [datetime] NOT NULL ,\r
+       [data] [text] COLLATE Latin1_General_CI_AI NOT NULL \r
+) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]\r
+GO\r
+\r
+CREATE TABLE [dbo].[cache_messages] (\r
+       [user_id] [int] NOT NULL ,\r
+       [mailbox] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,\r
+       [uid] [int] NOT NULL ,\r
+       [changed] [datetime] NOT NULL ,\r
+       [data] [text] COLLATE Latin1_General_CI_AI NOT NULL \r
+       [flags] [int] NOT NULL ,\r
+) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]\r
+GO\r
+\r
+ALTER TABLE [dbo].[cache_index] WITH NOCHECK ADD \r
+        PRIMARY KEY CLUSTERED \r
+       (\r
+               [user_id],[mailbox]\r
+       ) ON [PRIMARY] \r
+GO\r
+\r
+ALTER TABLE [dbo].[cache_thread] WITH NOCHECK ADD \r
+        PRIMARY KEY CLUSTERED \r
+       (\r
+               [user_id],[mailbox]\r
+       ) ON [PRIMARY] \r
+GO\r
+\r
+ALTER TABLE [dbo].[cache_messages] WITH NOCHECK ADD \r
+        PRIMARY KEY CLUSTERED \r
+       (\r
+               [user_id],[mailbox],[uid]\r
+       ) ON [PRIMARY] \r
+GO\r
+\r
+ALTER TABLE [dbo].[cache_index] ADD \r
+       CONSTRAINT [DF_cache_index_changed] DEFAULT (getdate()) FOR [changed],\r
+       CONSTRAINT [DF_cache_index_valid] DEFAULT ('0') FOR [valid]\r
+GO\r
+\r
+CREATE  INDEX [IX_cache_index_user_id] ON [dbo].[cache_index]([user_id]) ON [PRIMARY]\r
+GO\r
+\r
+ALTER TABLE [dbo].[cache_thread] ADD \r
+       CONSTRAINT [DF_cache_thread_changed] DEFAULT (getdate()) FOR [changed]\r
+GO\r
+\r
+CREATE  INDEX [IX_cache_thread_user_id] ON [dbo].[cache_thread]([user_id]) ON [PRIMARY]\r
+GO\r
+\r
+ALTER TABLE [dbo].[cache_messages] ADD \r
+       CONSTRAINT [DF_cache_messages_changed] DEFAULT (getdate()) FOR [changed],\r
+       CONSTRAINT [DF_cache_messages_flags] DEFAULT (0) FOR [flags]\r
+GO\r
+\r
+CREATE  INDEX [IX_cache_messages_user_id] ON [dbo].[cache_messages]([user_id]) ON [PRIMARY]\r
+GO\r
+\r
+ALTER TABLE [dbo].[cache_index] ADD CONSTRAINT [FK_cache_index_user_id]\r
+    FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])\r
+    ON DELETE CASCADE ON UPDATE CASCADE\r
+GO\r
+\r
+ALTER TABLE [dbo].[cache_thread] ADD CONSTRAINT [FK_cache_thread_user_id]\r
+    FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])\r
+    ON DELETE CASCADE ON UPDATE CASCADE\r
+GO\r
+\r
+ALTER TABLE [dbo].[cache_messages] ADD CONSTRAINT [FK_cache_messages_user_id]\r
+    FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])\r
+    ON DELETE CASCADE ON UPDATE CASCADE\r
+GO\r
+\r
+-- Updates from version 0.7-beta
+
+ALTER TABLE [dbo].[session] ALTER COLUMN [sess_id] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL
+GO
+
index 14bbb968acfcf2df80cd536a0869baa84d456801..94679f20288346ad6e950fbf08380df0e537f40e 100644 (file)
@@ -6,7 +6,7 @@
 -- Table structure for table `session`
 
 CREATE TABLE `session` (
 -- Table structure for table `session`
 
 CREATE TABLE `session` (
- `sess_id` varchar(40) NOT NULL,
+ `sess_id` varchar(128) NOT NULL,
  `created` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
  `changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
  `ip` varchar(40) NOT NULL,
  `created` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
  `changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
  `ip` varchar(40) NOT NULL,
@@ -20,9 +20,9 @@ CREATE TABLE `session` (
 
 CREATE TABLE `users` (
  `user_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
 
 CREATE TABLE `users` (
  `user_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
- `username` varchar(128) NOT NULL,
+ `username` varchar(128) BINARY NOT NULL,
  `mail_host` varchar(128) NOT NULL,
  `mail_host` varchar(128) NOT NULL,
- `alias` varchar(128) NOT NULL,
+ `alias` varchar(128) BINARY NOT NULL,
  `created` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
  `last_login` datetime DEFAULT NULL,
  `language` varchar(5),
  `created` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
  `last_login` datetime DEFAULT NULL,
  `language` varchar(5),
@@ -33,33 +33,6 @@ CREATE TABLE `users` (
 ) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
 
 
 ) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
 
 
--- Table structure for table `messages`
-
-CREATE TABLE `messages` (
- `message_id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
- `user_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
- `del` tinyint(1) NOT NULL DEFAULT '0',
- `cache_key` varchar(128) /*!40101 CHARACTER SET ascii COLLATE ascii_general_ci */ NOT NULL,
- `created` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
- `idx` int(11) UNSIGNED NOT NULL DEFAULT '0',
- `uid` int(11) UNSIGNED NOT NULL DEFAULT '0',
- `subject` varchar(255) NOT NULL,
- `from` varchar(255) NOT NULL,
- `to` varchar(255) NOT NULL,
- `cc` varchar(255) NOT NULL,
- `date` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
- `size` int(11) UNSIGNED NOT NULL DEFAULT '0',
- `headers` text NOT NULL,
- `structure` text,
- PRIMARY KEY(`message_id`),
- CONSTRAINT `user_id_fk_messages` FOREIGN KEY (`user_id`)
-   REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
- INDEX `created_index` (`created`),
- INDEX `index_index` (`user_id`, `cache_key`, `idx`),
- UNIQUE `uniqueness` (`user_id`, `cache_key`, `uid`)
-) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
-
-
 -- Table structure for table `cache`
 
 CREATE TABLE `cache` (
 -- Table structure for table `cache`
 
 CREATE TABLE `cache` (
@@ -76,6 +49,51 @@ CREATE TABLE `cache` (
 ) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
 
 
 ) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
 
 
+-- Table structure for table `cache_index`
+
+CREATE TABLE `cache_index` (
+ `user_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
+ `mailbox` varchar(255) BINARY NOT NULL,
+ `changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
+ `valid` tinyint(1) NOT NULL DEFAULT '0',
+ `data` longtext NOT NULL,
+ CONSTRAINT `user_id_fk_cache_index` FOREIGN KEY (`user_id`)
+   REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
+ INDEX `changed_index` (`changed`),
+ PRIMARY KEY (`user_id`, `mailbox`)
+) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
+
+
+-- Table structure for table `cache_thread`
+
+CREATE TABLE `cache_thread` (
+ `user_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
+ `mailbox` varchar(255) BINARY NOT NULL,
+ `changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
+ `data` longtext NOT NULL,
+ CONSTRAINT `user_id_fk_cache_thread` FOREIGN KEY (`user_id`)
+   REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
+ INDEX `changed_index` (`changed`),
+ PRIMARY KEY (`user_id`, `mailbox`)
+) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
+
+
+-- Table structure for table `cache_messages`
+
+CREATE TABLE `cache_messages` (
+ `user_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
+ `mailbox` varchar(255) BINARY NOT NULL,
+ `uid` int(11) UNSIGNED NOT NULL DEFAULT '0',
+ `changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
+ `data` longtext NOT NULL,
+ `flags` int(11) NOT NULL DEFAULT '0',
+ CONSTRAINT `user_id_fk_cache_messages` FOREIGN KEY (`user_id`)
+   REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
+ INDEX `changed_index` (`changed`),
+ PRIMARY KEY (`user_id`, `mailbox`, `uid`)
+) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
+
+
 -- Table structure for table `contacts`
 
 CREATE TABLE `contacts` (
 -- Table structure for table `contacts`
 
 CREATE TABLE `contacts` (
@@ -144,4 +162,31 @@ CREATE TABLE `identities` (
 ) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
 
 
 ) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
 
 
+-- Table structure for table `dictionary`
+
+CREATE TABLE `dictionary` (
+  `user_id` int(10) UNSIGNED DEFAULT NULL,
+  `language` varchar(5) NOT NULL,
+  `data` longtext NOT NULL,
+  CONSTRAINT `user_id_fk_dictionary` FOREIGN KEY (`user_id`)
+    REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
+  UNIQUE `uniqueness` (`user_id`, `language`)
+) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
+
+
+-- Table structure for table `searches`
+
+CREATE TABLE `searches` (
+ `search_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `user_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
+ `type` int(3) NOT NULL DEFAULT '0',
+ `name` varchar(128) NOT NULL,
+ `data` text,
+ PRIMARY KEY(`search_id`),
+ CONSTRAINT `user_id_fk_searches` FOREIGN KEY (`user_id`)
+   REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
+ UNIQUE `uniqueness` (`user_id`, `type`, `name`)
+) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
+
+
 /*!40014 SET FOREIGN_KEY_CHECKS=1 */;
 /*!40014 SET FOREIGN_KEY_CHECKS=1 */;
index ed21bda2ecf191d626110d30b71842365dbaea00..07617316b3cf7b26f9315f83140938bd5bdc645f 100644 (file)
@@ -144,3 +144,71 @@ ALTER TABLE `contactgroupmembers` ADD INDEX `contactgroupmembers_contact_index`
 
 TRUNCATE TABLE `messages`;
 TRUNCATE TABLE `cache`;
 
 TRUNCATE TABLE `messages`;
 TRUNCATE TABLE `cache`;
+
+-- Updates from version 0.6
+
+ALTER TABLE `users` CHANGE `alias` `alias` varchar(128) BINARY NOT NULL;
+ALTER TABLE `users` CHANGE `username` `username` varchar(128) BINARY NOT NULL;
+
+CREATE TABLE `dictionary` (
+  `user_id` int(10) UNSIGNED DEFAULT NULL,
+  `language` varchar(5) NOT NULL,
+  `data` longtext NOT NULL,
+  CONSTRAINT `user_id_fk_dictionary` FOREIGN KEY (`user_id`)
+    REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
+  UNIQUE `uniqueness` (`user_id`, `language`)
+) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
+
+CREATE TABLE `searches` (
+  `search_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `user_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
+  `type` int(3) NOT NULL DEFAULT '0',
+  `name` varchar(128) NOT NULL,
+  `data` text,
+  PRIMARY KEY(`search_id`),
+  CONSTRAINT `user_id_fk_searches` FOREIGN KEY (`user_id`)
+    REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
+  UNIQUE `uniqueness` (`user_id`, `type`, `name`)
+) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
+
+DROP TABLE `messages`;
+
+CREATE TABLE `cache_index` (
+ `user_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
+ `mailbox` varchar(255) BINARY NOT NULL,
+ `changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
+ `valid` tinyint(1) NOT NULL DEFAULT '0',
+ `data` longtext NOT NULL,
+ CONSTRAINT `user_id_fk_cache_index` FOREIGN KEY (`user_id`)
+   REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
+ INDEX `changed_index` (`changed`),
+ PRIMARY KEY (`user_id`, `mailbox`)
+) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
+
+CREATE TABLE `cache_thread` (
+ `user_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
+ `mailbox` varchar(255) BINARY NOT NULL,
+ `changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
+ `data` longtext NOT NULL,
+ CONSTRAINT `user_id_fk_cache_thread` FOREIGN KEY (`user_id`)
+   REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
+ INDEX `changed_index` (`changed`),
+ PRIMARY KEY (`user_id`, `mailbox`)
+) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
+
+CREATE TABLE `cache_messages` (
+ `user_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
+ `mailbox` varchar(255) BINARY NOT NULL,
+ `uid` int(11) UNSIGNED NOT NULL DEFAULT '0',
+ `changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
+ `data` longtext NOT NULL,
+ `flags` int(11) NOT NULL DEFAULT '0',
+ CONSTRAINT `user_id_fk_cache_messages` FOREIGN KEY (`user_id`)
+   REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
+ INDEX `changed_index` (`changed`),
+ PRIMARY KEY (`user_id`, `mailbox`, `uid`)
+) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
+
+-- Updates from version 0.7-beta
+
+ALTER TABLE `session` CHANGE `sess_id` `sess_id` varchar(128) NOT NULL;
index 5350e791f71dc7904cc8ddac9fa20032999fae70..3710dac4a7f70c7bf2c40827bdf1b01b5dba54d0 100644 (file)
@@ -37,7 +37,7 @@ CREATE INDEX users_alias_id_idx ON users (alias);
 --
 
 CREATE TABLE "session" (
 --
 
 CREATE TABLE "session" (
-    sess_id varchar(40) DEFAULT '' PRIMARY KEY,
+    sess_id varchar(128) DEFAULT '' PRIMARY KEY,
     created timestamp with time zone DEFAULT now() NOT NULL,
     changed timestamp with time zone DEFAULT now() NOT NULL,
     ip varchar(41) NOT NULL,
     created timestamp with time zone DEFAULT now() NOT NULL,
     changed timestamp with time zone DEFAULT now() NOT NULL,
     ip varchar(41) NOT NULL,
@@ -67,7 +67,7 @@ CREATE SEQUENCE identity_ids
 CREATE TABLE identities (
     identity_id integer DEFAULT nextval('identity_ids'::text) PRIMARY KEY,
     user_id integer NOT NULL
 CREATE TABLE identities (
     identity_id integer DEFAULT nextval('identity_ids'::text) PRIMARY KEY,
     user_id integer NOT NULL
-       REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
+        REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
     changed timestamp with time zone DEFAULT now() NOT NULL,
     del smallint DEFAULT 0 NOT NULL,
     standard smallint DEFAULT 0 NOT NULL,
     changed timestamp with time zone DEFAULT now() NOT NULL,
     del smallint DEFAULT 0 NOT NULL,
     standard smallint DEFAULT 0 NOT NULL,
@@ -178,7 +178,7 @@ CREATE SEQUENCE cache_ids
 CREATE TABLE "cache" (
     cache_id integer DEFAULT nextval('cache_ids'::text) PRIMARY KEY,
     user_id integer NOT NULL
 CREATE TABLE "cache" (
     cache_id integer DEFAULT nextval('cache_ids'::text) PRIMARY KEY,
     user_id integer NOT NULL
-       REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
+       REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
     cache_key varchar(128) DEFAULT '' NOT NULL,
     created timestamp with time zone DEFAULT now() NOT NULL,
     data text NOT NULL
     cache_key varchar(128) DEFAULT '' NOT NULL,
     created timestamp with time zone DEFAULT now() NOT NULL,
     data text NOT NULL
@@ -188,40 +188,91 @@ CREATE INDEX cache_user_id_idx ON "cache" (user_id, cache_key);
 CREATE INDEX cache_created_idx ON "cache" (created);
 
 --
 CREATE INDEX cache_created_idx ON "cache" (created);
 
 --
--- Sequence "message_ids"
--- Name: message_ids; Type: SEQUENCE; Schema: public; Owner: postgres
+-- Table "cache_index"
+-- Name: cache_index; Type: TABLE; Schema: public; Owner: postgres
+--
+
+CREATE TABLE cache_index (
+    user_id integer NOT NULL
+       REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
+    mailbox varchar(255) NOT NULL,
+    changed timestamp with time zone DEFAULT now() NOT NULL,
+    valid smallint NOT NULL DEFAULT 0,
+    data text NOT NULL,
+    PRIMARY KEY (user_id, mailbox)
+);
+
+CREATE INDEX cache_index_changed_idx ON cache_index (changed);
+
+--
+-- Table "cache_thread"
+-- Name: cache_thread; Type: TABLE; Schema: public; Owner: postgres
+--
+
+CREATE TABLE cache_thread (
+    user_id integer NOT NULL
+       REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
+    mailbox varchar(255) NOT NULL,
+    changed timestamp with time zone DEFAULT now() NOT NULL,
+    data text NOT NULL,
+    PRIMARY KEY (user_id, mailbox)
+);
+
+CREATE INDEX cache_thread_changed_idx ON cache_thread (changed);
+
+--
+-- Table "cache_messages"
+-- Name: cache_messages; Type: TABLE; Schema: public; Owner: postgres
+--
+
+CREATE TABLE cache_messages (
+    user_id integer NOT NULL
+       REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
+    mailbox varchar(255) NOT NULL,
+    uid integer NOT NULL,
+    changed timestamp with time zone DEFAULT now() NOT NULL,
+    data text NOT NULL,
+    flags integer NOT NULL DEFAULT 0,
+    PRIMARY KEY (user_id, mailbox, uid)
+);
+
+CREATE INDEX cache_messages_changed_idx ON cache_messages (changed);
+
+--
+-- Table "dictionary"
+-- Name: dictionary; Type: TABLE; Schema: public; Owner: postgres
+--
+
+CREATE TABLE dictionary (
+    user_id integer DEFAULT NULL
+       REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
+   "language" varchar(5) NOT NULL,
+    data text NOT NULL,
+    CONSTRAINT dictionary_user_id_language_key UNIQUE (user_id, "language")
+);
+
+--
+-- Sequence "searches_ids"
+-- Name: searches_ids; Type: SEQUENCE; Schema: public; Owner: postgres
 --
 
 --
 
-CREATE SEQUENCE message_ids
+CREATE SEQUENCE search_ids
     INCREMENT BY 1
     NO MAXVALUE
     NO MINVALUE
     CACHE 1;
 
 --
     INCREMENT BY 1
     NO MAXVALUE
     NO MINVALUE
     CACHE 1;
 
 --
--- Table "messages"
--- Name: messages; Type: TABLE; Schema: public; Owner: postgres
+-- Table "searches"
+-- Name: searches; Type: TABLE; Schema: public; Owner: postgres
 --
 
 --
 
-CREATE TABLE messages (
-    message_id integer DEFAULT nextval('message_ids'::text) PRIMARY KEY,
+CREATE TABLE searches (
+    search_id integer DEFAULT nextval('search_ids'::text) PRIMARY KEY,
     user_id integer NOT NULL
     user_id integer NOT NULL
-       REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
-    del smallint DEFAULT 0 NOT NULL,
-    cache_key varchar(128) DEFAULT '' NOT NULL,
-    created timestamp with time zone DEFAULT now() NOT NULL,
-    idx integer DEFAULT 0 NOT NULL,
-    uid integer DEFAULT 0 NOT NULL,
-    subject varchar(128) DEFAULT '' NOT NULL,
-    "from" varchar(128) DEFAULT '' NOT NULL,
-    "to" varchar(128) DEFAULT '' NOT NULL,
-    cc varchar(128) DEFAULT '' NOT NULL,
-    date timestamp with time zone NOT NULL,
-    size integer DEFAULT 0 NOT NULL,
-    headers text NOT NULL,
-    structure text,
-    CONSTRAINT messages_user_id_key UNIQUE (user_id, cache_key, uid)
+        REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
+    "type" smallint DEFAULT 0 NOT NULL,
+    name varchar(128) NOT NULL,
+    data text NOT NULL,
+    CONSTRAINT searches_user_id_key UNIQUE (user_id, "type", name)
 );
 );
-
-CREATE INDEX messages_index_idx ON messages (user_id, cache_key, idx);
-CREATE INDEX messages_created_idx ON messages (created);
index 94513c53fef603c60718f8d3f4578d6a5c5686ec..c96669dc8ee1ccbc4dd30ad6904e0454b9cc3dbe 100644 (file)
@@ -100,3 +100,72 @@ CREATE INDEX contactgroupmembers_contact_id_idx ON contactgroupmembers (contact_
 
 TRUNCATE messages;
 TRUNCATE cache;
 
 TRUNCATE messages;
 TRUNCATE cache;
+
+-- Updates from version 0.6
+
+CREATE TABLE dictionary (
+    user_id integer DEFAULT NULL
+        REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
+   "language" varchar(5) NOT NULL,
+    data text NOT NULL,
+    CONSTRAINT dictionary_user_id_language_key UNIQUE (user_id, "language")
+);
+
+CREATE SEQUENCE search_ids
+    INCREMENT BY 1
+    NO MAXVALUE
+    NO MINVALUE
+    CACHE 1;
+
+CREATE TABLE searches (
+    search_id integer DEFAULT nextval('search_ids'::text) PRIMARY KEY,
+    user_id integer NOT NULL
+        REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
+    "type" smallint DEFAULT 0 NOT NULL,
+    name varchar(128) NOT NULL,
+    data text NOT NULL,
+    CONSTRAINT searches_user_id_key UNIQUE (user_id, "type", name)
+);
+
+DROP SEQUENCE messages_ids;
+DROP TABLE messages;
+
+CREATE TABLE cache_index (
+    user_id integer NOT NULL
+       REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
+    mailbox varchar(255) NOT NULL,
+    changed timestamp with time zone DEFAULT now() NOT NULL,
+    valid smallint NOT NULL DEFAULT 0,
+    data text NOT NULL,
+    PRIMARY KEY (user_id, mailbox)
+);
+
+CREATE INDEX cache_index_changed_idx ON cache_index (changed);
+
+CREATE TABLE cache_thread (
+    user_id integer NOT NULL
+       REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
+    mailbox varchar(255) NOT NULL,
+    changed timestamp with time zone DEFAULT now() NOT NULL,
+    data text NOT NULL,
+    PRIMARY KEY (user_id, mailbox)
+);
+
+CREATE INDEX cache_thread_changed_idx ON cache_thread (changed);
+
+CREATE TABLE cache_messages (
+    user_id integer NOT NULL
+       REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
+    mailbox varchar(255) NOT NULL,
+    uid integer NOT NULL,
+    changed timestamp with time zone DEFAULT now() NOT NULL,
+    data text NOT NULL,
+    flags integer NOT NULL DEFAULT 0,
+    PRIMARY KEY (user_id, mailbox, uid)
+);
+
+CREATE INDEX cache_messages_changed_idx ON cache_messages (changed);
+
+-- Updates from version 0.7-beta
+
+ALTER TABLE "session" ALTER sess_id TYPE varchar(128);
index d2885e9686d01b0e999d3d7d0d04a26da9faf1f8..8c8da5c0f6b0c9b906455689eccc2b73587e04b2 100644 (file)
@@ -1,7 +1,7 @@
 -- Roundcube Webmail initial database structure
 
 -- 
 -- Roundcube Webmail initial database structure
 
 -- 
--- Table structure for table `cache`
+-- Table structure for table cache
 -- 
 
 CREATE TABLE cache (
 -- 
 
 CREATE TABLE cache (
@@ -9,7 +9,7 @@ CREATE TABLE cache (
   user_id integer NOT NULL default 0,
   cache_key varchar(128) NOT NULL default '',
   created datetime NOT NULL default '0000-00-00 00:00:00',
   user_id integer NOT NULL default 0,
   cache_key varchar(128) NOT NULL default '',
   created datetime NOT NULL default '0000-00-00 00:00:00',
-  data longtext NOT NULL
+  data text NOT NULL
 );
 
 CREATE INDEX ix_cache_user_cache_key ON cache(user_id, cache_key);
 );
 
 CREATE INDEX ix_cache_user_cache_key ON cache(user_id, cache_key);
@@ -110,7 +110,7 @@ CREATE INDEX ix_users_alias ON users(alias);
 -- 
 
 CREATE TABLE session (
 -- 
 
 CREATE TABLE session (
-  sess_id varchar(40) NOT NULL PRIMARY KEY,
+  sess_id varchar(128) NOT NULL PRIMARY KEY,
   created datetime NOT NULL default '0000-00-00 00:00:00',
   changed datetime NOT NULL default '0000-00-00 00:00:00',
   ip varchar(40) NOT NULL default '',
   created datetime NOT NULL default '0000-00-00 00:00:00',
   changed datetime NOT NULL default '0000-00-00 00:00:00',
   ip varchar(40) NOT NULL default '',
@@ -121,28 +121,81 @@ CREATE INDEX ix_session_changed ON session (changed);
 
 -- --------------------------------------------------------
 
 
 -- --------------------------------------------------------
 
--- 
--- Table structure for table messages
--- 
+--
+-- Table structure for table dictionary
+--
 
 
-CREATE TABLE messages (
-  message_id integer NOT NULL PRIMARY KEY,
-  user_id integer NOT NULL default '0',
-  del tinyint NOT NULL default '0',
-  cache_key varchar(128) NOT NULL default '',
-  created datetime NOT NULL default '0000-00-00 00:00:00',
-  idx integer NOT NULL default '0',
-  uid integer NOT NULL default '0',
-  subject varchar(255) NOT NULL default '',
-  "from" varchar(255) NOT NULL default '',
-  "to" varchar(255) NOT NULL default '',
-  "cc" varchar(255) NOT NULL default '',
-  "date" datetime NOT NULL default '0000-00-00 00:00:00',
-  size integer NOT NULL default '0',
-  headers text NOT NULL,
-  structure text
+CREATE TABLE dictionary (
+    user_id integer DEFAULT NULL,
+   "language" varchar(5) NOT NULL,
+    data text NOT NULL
+);
+
+CREATE UNIQUE INDEX ix_dictionary_user_language ON dictionary (user_id, "language");
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table searches
+--
+
+CREATE TABLE searches (
+  search_id integer NOT NULL PRIMARY KEY,
+  user_id integer NOT NULL DEFAULT '0',
+  "type" smallint NOT NULL DEFAULT '0',
+  name varchar(128) NOT NULL,
+  data text NOT NULL
+);
+
+CREATE UNIQUE INDEX ix_searches_user_type_name (user_id, type, name);
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table cache_index
+--
+
+CREATE TABLE cache_index (
+    user_id integer NOT NULL,
+    mailbox varchar(255) NOT NULL,
+    changed datetime NOT NULL default '0000-00-00 00:00:00',
+    valid smallint NOT NULL DEFAULT '0',
+    data text NOT NULL,
+    PRIMARY KEY (user_id, mailbox)
+);
+
+CREATE INDEX ix_cache_index_changed ON cache_index (changed);
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table cache_thread
+--
+
+CREATE TABLE cache_thread (
+    user_id integer NOT NULL,
+    mailbox varchar(255) NOT NULL,
+    changed datetime NOT NULL default '0000-00-00 00:00:00',
+    data text NOT NULL,
+    PRIMARY KEY (user_id, mailbox)
+);
+
+CREATE INDEX ix_cache_thread_changed ON cache_thread (changed);
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table cache_messages
+--
+
+CREATE TABLE cache_messages (
+    user_id integer NOT NULL,
+    mailbox varchar(255) NOT NULL,
+    uid integer NOT NULL,
+    changed datetime NOT NULL default '0000-00-00 00:00:00',
+    data text NOT NULL,
+    flags integer NOT NULL DEFAULT '0',
+    PRIMARY KEY (user_id, mailbox, uid)
 );
 
 );
 
-CREATE UNIQUE INDEX ix_messages_user_cache_uid ON messages (user_id,cache_key,uid);
-CREATE INDEX ix_messages_index ON messages (user_id,cache_key,idx);
-CREATE INDEX ix_messages_created ON messages (created);
+CREATE INDEX ix_cache_messages_changed ON cache_messages (changed);
index 30c3ae90baac816dccf46f3decf104f941bab844..92f6da1423ac033cf97b4699af249ef6f7abc823 100644 (file)
@@ -223,6 +223,75 @@ INSERT INTO contacts (contact_id, user_id, changed, del, name, email, firstname,
 CREATE INDEX ix_contacts_user_id ON contacts(user_id, email);
 DROP TABLE contacts_tmp;
 
 CREATE INDEX ix_contacts_user_id ON contacts(user_id, email);
 DROP TABLE contacts_tmp;
 
+
 DELETE FROM messages;
 DELETE FROM cache;
 CREATE INDEX ix_contactgroupmembers_contact_id ON contactgroupmembers (contact_id);
 DELETE FROM messages;
 DELETE FROM cache;
 CREATE INDEX ix_contactgroupmembers_contact_id ON contactgroupmembers (contact_id);
+
+-- Updates from version 0.6
+
+CREATE TABLE dictionary (
+    user_id integer DEFAULT NULL,
+   "language" varchar(5) NOT NULL,
+    data text NOT NULL
+);
+
+CREATE UNIQUE INDEX ix_dictionary_user_language ON dictionary (user_id, "language");
+
+CREATE TABLE searches (
+  search_id integer NOT NULL PRIMARY KEY,
+  user_id integer NOT NULL DEFAULT '0',
+  "type" smallint NOT NULL DEFAULT '0',
+  name varchar(128) NOT NULL,
+  data text NOT NULL
+);
+
+CREATE UNIQUE INDEX ix_searches_user_type_name (user_id, type, name);
+
+DROP TABLE messages;
+
+CREATE TABLE cache_index (
+    user_id integer NOT NULL,
+    mailbox varchar(255) NOT NULL,
+    changed datetime NOT NULL default '0000-00-00 00:00:00',
+    valid smallint NOT NULL DEFAULT '0',
+    data text NOT NULL,
+    PRIMARY KEY (user_id, mailbox)
+);
+
+CREATE INDEX ix_cache_index_changed ON cache_index (changed);
+
+CREATE TABLE cache_thread (
+    user_id integer NOT NULL,
+    mailbox varchar(255) NOT NULL,
+    changed datetime NOT NULL default '0000-00-00 00:00:00',
+    data text NOT NULL,
+    PRIMARY KEY (user_id, mailbox)
+);
+
+CREATE INDEX ix_cache_thread_changed ON cache_thread (changed);
+
+CREATE TABLE cache_messages (
+    user_id integer NOT NULL,
+    mailbox varchar(255) NOT NULL,
+    uid integer NOT NULL,
+    changed datetime NOT NULL default '0000-00-00 00:00:00',
+    data text NOT NULL,
+    flags integer NOT NULL DEFAULT '0',
+    PRIMARY KEY (user_id, mailbox, uid)
+);
+
+CREATE INDEX ix_cache_messages_changed ON cache_messages (changed);
+
+-- Updates from version 0.7-beta
+
+DROP TABLE session;
+CREATE TABLE session (
+  sess_id varchar(128) NOT NULL PRIMARY KEY,
+  created datetime NOT NULL default '0000-00-00 00:00:00',
+  changed datetime NOT NULL default '0000-00-00 00:00:00',
+  ip varchar(40) NOT NULL default '',
+  vars text NOT NULL
+);
+
+CREATE INDEX ix_session_changed ON session (changed);
index d552be61f8f7b7bf30d6a3b18ca4902bc6eb21f3..cbeffe96b5353814d5f5f37665ebd6c82bd7ba41 100755 (executable)
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: indexcontacts.sh 4623 2011-03-28 06:49:02Z alec $
+ $Id: indexcontacts.sh 5307 2011-10-05 09:28:25Z alec $
 
 */
 
 define('INSTALL_PATH', realpath(dirname(__FILE__) . '/..') . '/' );
 
 require_once INSTALL_PATH.'program/include/clisetup.php';
 
 */
 
 define('INSTALL_PATH', realpath(dirname(__FILE__) . '/..') . '/' );
 
 require_once INSTALL_PATH.'program/include/clisetup.php';
-
+ini_set('memory_limit', -1);
 
 // connect to DB
 $RCMAIL = rcmail::get_instance();
 
 // connect to DB
 $RCMAIL = rcmail::get_instance();
@@ -47,7 +47,7 @@ while ($sql_result && ($sql_arr = $db->fetch_assoc($sql_result))) {
         unset($row['words']);
         $contacts->update($row['ID'], $row);
     }
         unset($row['words']);
         $contacts->update($row['ID'], $row);
     }
-    
+
     echo "done.\n";
 }
 
     echo "done.\n";
 }
 
index 33652dcc720b6c22b15a8965a5a6c6de212c53b2..bcba57c7586422477d9959877ac7da4803e1d1ec 100755 (executable)
@@ -15,7 +15,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: installto.sh 4677 2011-04-20 13:10:45Z alec $
+ $Id: installto.sh 5311 2011-10-06 08:20:11Z thomasb $
 
 */
 
 
 */
 
@@ -45,13 +45,13 @@ if (strtolower($input) == 'y') {
   $err = false;
   echo "Copying files to target location...";
   foreach (array('program','installer','bin','SQL','plugins','skins/default') as $dir) {
   $err = false;
   echo "Copying files to target location...";
   foreach (array('program','installer','bin','SQL','plugins','skins/default') as $dir) {
-    if (!system("rsync -avuC " . INSTALL_PATH . "$dir/* $target_dir/$dir/")) {
+    if (!system("rsync -avC " . INSTALL_PATH . "$dir/* $target_dir/$dir/")) {
       $err = true;
       break;
     }
   }
   foreach (array('index.php','.htaccess','config/main.inc.php.dist','config/db.inc.php.dist','CHANGELOG','README','UPGRADING') as $file) {
       $err = true;
       break;
     }
   }
   foreach (array('index.php','.htaccess','config/main.inc.php.dist','config/db.inc.php.dist','CHANGELOG','README','UPGRADING') as $file) {
-    if (!system("rsync -avu " . INSTALL_PATH . "$file $target_dir/$file")) {
+    if (!system("rsync -av " . INSTALL_PATH . "$file $target_dir/$file")) {
       $err = true;
       break;
     }
       $err = true;
       break;
     }
index be5aad16d1d96bab1421b230c5654e7914012561..9cfd660bb1446900c2c2b4710afff138a4599f4e 100755 (executable)
@@ -1,10 +1,11 @@
 #!/bin/sh
 JS_DIR=`dirname "$0"`/../program/js
 #!/bin/sh
 JS_DIR=`dirname "$0"`/../program/js
+JAR_DIR='/tmp'
 CLOSURE_COMPILER_URL='http://closure-compiler.googlecode.com/files/compiler-latest.zip'
 
 do_shrink() {
        rm -f "$2"
 CLOSURE_COMPILER_URL='http://closure-compiler.googlecode.com/files/compiler-latest.zip'
 
 do_shrink() {
        rm -f "$2"
-       java -jar compiler.jar --compilation_level=SIMPLE_OPTIMIZATIONS --js="$1" --js_output_file="$2"
+       java -jar $JAR_DIR/compiler.jar --compilation_level=SIMPLE_OPTIMIZATIONS --js="$1" --js_output_file="$2"
 }
 
 if [ ! -d "$JS_DIR" ]; then
 }
 
 if [ ! -d "$JS_DIR" ]; then
@@ -12,6 +13,10 @@ if [ ! -d "$JS_DIR" ]; then
        exit 1
 fi
 
        exit 1
 fi
 
+if [ ! -w "$JAR_DIR" ]; then
+       JAR_DIR=`dirname "$0"`
+fi
+
 if java -version >/dev/null 2>&1; then
        :
 else
 if java -version >/dev/null 2>&1; then
        :
 else
@@ -19,16 +24,16 @@ else
        exit 1
 fi
 
        exit 1
 fi
 
-if [ ! -r "compiler.jar" ]; then
+if [ ! -r "$JAR_DIR/compiler.jar" ]; then
        if which wget >/dev/null 2>&1 && which unzip >/dev/null 2>&1; then
                wget "$CLOSURE_COMPILER_URL" -O "/tmp/$$.zip"
        elif which curl >/dev/null 2>&1 && which unzip >/dev/null 2>&1; then
                curl "$CLOSURE_COMPILER_URL" -o "/tmp/$$.zip"
        else
        if which wget >/dev/null 2>&1 && which unzip >/dev/null 2>&1; then
                wget "$CLOSURE_COMPILER_URL" -O "/tmp/$$.zip"
        elif which curl >/dev/null 2>&1 && which unzip >/dev/null 2>&1; then
                curl "$CLOSURE_COMPILER_URL" -o "/tmp/$$.zip"
        else
-               echo "Please download $CLOSURE_COMPILER_URL and extract compiler.jar to this directory."
+               echo "Please download $CLOSURE_COMPILER_URL and extract compiler.jar to $JAR_DIR/."
                exit 1
        fi
                exit 1
        fi
-       unzip "/tmp/$$.zip" "compiler.jar"
+       (cd $JAR_DIR && unzip "/tmp/$$.zip" "compiler.jar")
        rm -f "/tmp/$$.zip"
 fi
 
        rm -f "/tmp/$$.zip"
 fi
 
index 78cd96882d9f00019d8a91c68f7dad2e3e1e740c..c1464f91470bcef76ae7b11ddba0e2aa660ea502 100644 (file)
@@ -39,34 +39,24 @@ $rcmail_config['db_persistent'] = FALSE;
 
 // you can define specific table names used to store webmail data
 $rcmail_config['db_table_users'] = 'users';
 
 // you can define specific table names used to store webmail data
 $rcmail_config['db_table_users'] = 'users';
-
 $rcmail_config['db_table_identities'] = 'identities';
 $rcmail_config['db_table_identities'] = 'identities';
-
 $rcmail_config['db_table_contacts'] = 'contacts';
 $rcmail_config['db_table_contacts'] = 'contacts';
-
 $rcmail_config['db_table_contactgroups'] = 'contactgroups';
 $rcmail_config['db_table_contactgroups'] = 'contactgroups';
-
 $rcmail_config['db_table_contactgroupmembers'] = 'contactgroupmembers';
 $rcmail_config['db_table_contactgroupmembers'] = 'contactgroupmembers';
-
 $rcmail_config['db_table_session'] = 'session';
 $rcmail_config['db_table_session'] = 'session';
-
 $rcmail_config['db_table_cache'] = 'cache';
 $rcmail_config['db_table_cache'] = 'cache';
-
-$rcmail_config['db_table_messages'] = 'messages';
+$rcmail_config['db_table_cache_index'] = 'cache_index';
+$rcmail_config['db_table_cache_thread'] = 'cache_thread';
+$rcmail_config['db_table_cache_messages'] = 'cache_messages';
 
 
 // you can define specific sequence names used in PostgreSQL
 $rcmail_config['db_sequence_users'] = 'user_ids';
 
 
 // you can define specific sequence names used in PostgreSQL
 $rcmail_config['db_sequence_users'] = 'user_ids';
-
 $rcmail_config['db_sequence_identities'] = 'identity_ids';
 $rcmail_config['db_sequence_identities'] = 'identity_ids';
-
 $rcmail_config['db_sequence_contacts'] = 'contact_ids';
 $rcmail_config['db_sequence_contacts'] = 'contact_ids';
-
 $rcmail_config['db_sequence_contactgroups'] = 'contactgroups_ids';
 $rcmail_config['db_sequence_contactgroups'] = 'contactgroups_ids';
-
 $rcmail_config['db_sequence_cache'] = 'cache_ids';
 $rcmail_config['db_sequence_cache'] = 'cache_ids';
-
-$rcmail_config['db_sequence_messages'] = 'message_ids';
+$rcmail_config['db_sequence_searches'] = 'search_ids';
 
 
 // end db config file
 
 
 // end db config file
index 824085c14ebb2d5302423ffaf3923e6570dcbad4..6957577b15009c362140e549cc7e50cf0e80de99 100644 (file)
@@ -5,7 +5,7 @@
  | Main configuration file                                               |
  |                                                                       |
  | This file is part of the Roundcube Webmail client                     |
  | Main configuration file                                               |
  |                                                                       |
  | This file is part of the Roundcube Webmail client                     |
- | Copyright (C) 2005-2010, The Roundcube Dev Team                       |
+ | Copyright (C) 2005-2011, The Roundcube Dev Team                       |
  | Licensed under the GNU GPL                                            |
  |                                                                       |
  +-----------------------------------------------------------------------+
  | Licensed under the GNU GPL                                            |
  |                                                                       |
  +-----------------------------------------------------------------------+
@@ -222,6 +222,9 @@ $rcmail_config['session_lifetime'] = 10;
 // session domain: .example.org
 $rcmail_config['session_domain'] = '';
 
 // session domain: .example.org
 $rcmail_config['session_domain'] = '';
 
+// session name. Default: 'roundcube_sessid'
+$rcmail_config['session_name'] = null;
+
 // Backend to use for session storage. Can either be 'db' (default) or 'memcache'
 // If set to memcache, a list of servers need to be specified in 'memcache_hosts'
 // Make sure the Memcache extension (http://pecl.php.net/package/memcache) version >= 2.0.0 is installed
 // Backend to use for session storage. Can either be 'db' (default) or 'memcache'
 // If set to memcache, a list of servers need to be specified in 'memcache_hosts'
 // Make sure the Memcache extension (http://pecl.php.net/package/memcache) version >= 2.0.0 is installed
@@ -369,25 +372,30 @@ $rcmail_config['message_sort_col'] = '';
 $rcmail_config['message_sort_order'] = 'DESC';
 
 // These cols are shown in the message list. Available cols are:
 $rcmail_config['message_sort_order'] = 'DESC';
 
 // These cols are shown in the message list. Available cols are:
-// subject, from, to, cc, replyto, date, size, status, flag, attachment
+// subject, from, to, cc, replyto, date, size, status, flag, attachment, 'priority'
 $rcmail_config['list_cols'] = array('subject', 'status', 'from', 'date', 'size', 'flag', 'attachment');
 
 // the default locale setting (leave empty for auto-detection)
 // RFC1766 formatted language name like en_US, de_DE, de_CH, fr_FR, pt_BR
 $rcmail_config['language'] = null;
 
 $rcmail_config['list_cols'] = array('subject', 'status', 'from', 'date', 'size', 'flag', 'attachment');
 
 // the default locale setting (leave empty for auto-detection)
 // RFC1766 formatted language name like en_US, de_DE, de_CH, fr_FR, pt_BR
 $rcmail_config['language'] = null;
 
-// use this format for short date display (date or strftime format)
-$rcmail_config['date_short'] = 'D H:i';
+// use this format for date display (date or strftime format)
+$rcmail_config['date_format'] = 'Y-m-d';
 
 
-// use this format for detailed date/time formatting (date or strftime format)
-$rcmail_config['date_long'] = 'd.m.Y H:i';
+// give this choice of date formats to the user to select from
+$rcmail_config['date_formats'] = array('Y-m-d', 'd-m-Y', 'Y/m/d', 'm/d/Y', 'd/m/Y', 'd.m.Y', 'j.n.Y');
 
 
-// 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';
+// use this format for time display (date or strftime format)
+$rcmail_config['time_format'] = 'H:i';
 
 
-// use this format for date display without time (date or strftime format)
-$rcmail_config['date_format'] = 'Y-m-d';
+// give this choice of time formats to the user to select from
+$rcmail_config['time_formats'] = array('G:i', 'H:i', 'g:i a', 'h:i A');
+
+// use this format for short date display (derived from date_format and time_format)
+$rcmail_config['date_short'] = 'D H:i';
+
+// use this format for detailed date/time formatting (derived from date_format and time_format)
+$rcmail_config['date_long'] = 'Y-m-d H:i';
 
 // store draft message is this mailbox
 // leave blank if draft messages should not be stored
 
 // store draft message is this mailbox
 // leave blank if draft messages should not be stored
@@ -413,7 +421,7 @@ $rcmail_config['trash_mbox'] = 'Trash';
 // NOTE: Use folder names with namespace prefix (INBOX. on Courier-IMAP)
 $rcmail_config['default_imap_folders'] = array('INBOX', 'Drafts', 'Sent', 'Junk', 'Trash');
 
 // NOTE: Use folder names with namespace prefix (INBOX. on Courier-IMAP)
 $rcmail_config['default_imap_folders'] = array('INBOX', 'Drafts', 'Sent', 'Junk', 'Trash');
 
-// automatically create the above listed default folders on login
+// automatically create the above listed default folders on first login
 $rcmail_config['create_default_folders'] = false;
 
 // protect the default folders from renames, deletes, and subscription changes
 $rcmail_config['create_default_folders'] = false;
 
 // protect the default folders from renames, deletes, and subscription changes
@@ -427,6 +435,10 @@ $rcmail_config['quota_zero_as_unlimited'] = false;
 // requires to be compiled with Open SSL support
 $rcmail_config['enable_spellcheck'] = true;
 
 // requires to be compiled with Open SSL support
 $rcmail_config['enable_spellcheck'] = true;
 
+// Enables spellchecker exceptions dictionary.
+// Setting it to 'shared' will make the dictionary shared by all users.
+$rcmail_config['spellcheck_dictionary'] = false;
+
 // Set the spell checking engine. 'googie' is the default. 'pspell' is also available,
 // but requires the Pspell extensions. When using Nox Spell Server, also set 'googie' here.
 $rcmail_config['spellcheck_engine'] = 'googie';
 // Set the spell checking engine. 'googie' is the default. 'pspell' is also available,
 // but requires the Pspell extensions. When using Nox Spell Server, also set 'googie' here.
 $rcmail_config['spellcheck_engine'] = 'googie';
@@ -442,6 +454,18 @@ $rcmail_config['spellcheck_uri'] = '';
 // Leave empty for default set of available language.
 $rcmail_config['spellcheck_languages'] = NULL;
 
 // Leave empty for default set of available language.
 $rcmail_config['spellcheck_languages'] = NULL;
 
+// Makes that words with all letters capitalized will be ignored (e.g. GOOGLE)
+$rcmail_config['spellcheck_ignore_caps'] = false;
+
+// Makes that words with numbers will be ignored (e.g. g00gle)
+$rcmail_config['spellcheck_ignore_nums'] = false;
+
+// Makes that words with symbols will be ignored (e.g. g@@gle)
+$rcmail_config['spellcheck_ignore_syms'] = false;
+
+// Use this char/string to separate recipients when composing a new message
+$rcmail_config['recipients_separator'] = ',';
+
 // don't let users set pagesize to more than this value if set
 $rcmail_config['max_pagesize'] = 200;
 
 // don't let users set pagesize to more than this value if set
 $rcmail_config['max_pagesize'] = 200;
 
@@ -517,14 +541,21 @@ $rcmail_config['ldap_public']['Verisign'] = array(
   // The login name is used to search for the DN to bind with
   'search_base_dn' => '',
   'search_filter'  => '',   // e.g. '(&(objectClass=posixAccount)(uid=%u))'
   // The login name is used to search for the DN to bind with
   'search_base_dn' => '',
   'search_filter'  => '',   // e.g. '(&(objectClass=posixAccount)(uid=%u))'
+  // DN and password to bind as before searching for bind DN, if anonymous search is not allowed
+  'search_bind_dn' => '',
+  'search_bind_pw' => '',
+  // Default for %dn variable if search doesn't return DN value
+  'search_dn_default' => '',
   // Optional authentication identifier to be used as SASL authorization proxy
   // bind_dn need to be empty
   'auth_cid'       => '',
   // SASL authentication method (for proxy auth), e.g. DIGEST-MD5
   'auth_method'    => '',
   // Optional authentication identifier to be used as SASL authorization proxy
   // bind_dn need to be empty
   'auth_cid'       => '',
   // SASL authentication method (for proxy auth), e.g. DIGEST-MD5
   'auth_method'    => '',
-  // Indicates if the addressbook shall be displayed on the list.
+  // Indicates if the addressbook shall be hidden from the list.
   // With this option enabled you can still search/view contacts.
   'hidden'        => false,
   // With this option enabled you can still search/view contacts.
   'hidden'        => false,
+  // Indicates if the addressbook shall not list contacts but only allows searching.
+  'searchonly'    => false,
   // Indicates if we can write to the LDAP directory or not.
   // If writable is true then these fields need to be populated:
   // LDAP_Object_Classes, required_fields, LDAP_rdn
   // Indicates if we can write to the LDAP directory or not.
   // If writable is true then these fields need to be populated:
   // LDAP_Object_Classes, required_fields, LDAP_rdn
@@ -564,6 +595,7 @@ $rcmail_config['ldap_public']['Verisign'] = array(
   'numsub_filter' => '(objectClass=organizationalUnit)',   // with VLV, we also use numSubOrdinates to query the total number of records. Set this filter to get all numSubOrdinates attributes for counting
   'sizelimit'     => '0',     // Enables you to limit the count of entries fetched. Setting this to 0 means no limit.
   'timelimit'     => '0',     // Sets the number of seconds how long is spend on the search. Setting this to 0 means no limit.
   'numsub_filter' => '(objectClass=organizationalUnit)',   // with VLV, we also use numSubOrdinates to query the total number of records. Set this filter to get all numSubOrdinates attributes for counting
   'sizelimit'     => '0',     // Enables you to limit the count of entries fetched. Setting this to 0 means no limit.
   'timelimit'     => '0',     // Sets the number of seconds how long is spend on the search. Setting this to 0 means no limit.
+  'referrals'     => true|false,  // Sets the LDAP_OPT_REFERRALS option. Mostly used in multi-domain Active Directory setups
 
   // definition for contact groups (uncomment if no groups are supported)
   // for the groups base_dn, the user replacements %fu, %u, $d and %dc work as for base_dn (see above)
 
   // definition for contact groups (uncomment if no groups are supported)
   // for the groups base_dn, the user replacements %fu, %u, $d and %dc work as for base_dn (see above)
@@ -573,8 +605,8 @@ $rcmail_config['ldap_public']['Verisign'] = array(
     'base_dn'     => '',
     'filter'      => '(objectClass=groupOfNames)',
     'object_classes' => array("top", "groupOfNames"),
     'base_dn'     => '',
     'filter'      => '(objectClass=groupOfNames)',
     'object_classes' => array("top", "groupOfNames"),
-    // name of the member attribute, e.g. uniqueMember
-    'member_attr'    => 'member',
+    'member_attr'  => 'member',   // name of the member attribute, e.g. uniqueMember
+    'name_attr'    => 'cn',       // attribute to be used as group name
   ),
 );
 */
   ),
 );
 */
@@ -601,6 +633,13 @@ $rcmail_config['autocomplete_max'] = 15;
 // available placeholders: {street}, {locality}, {zipcode}, {country}, {region}
 $rcmail_config['address_template'] = '{street}<br/>{locality} {zipcode}<br/>{country} {region}';
 
 // available placeholders: {street}, {locality}, {zipcode}, {country}, {region}
 $rcmail_config['address_template'] = '{street}<br/>{locality} {zipcode}<br/>{country} {region}';
 
+// Matching mode for addressbook search (including autocompletion)
+// 0 - partial (*abc*), default
+// 1 - strict (abc)
+// 2 - prefix (abc*)
+// Note: For LDAP sources fuzzy_search must be enabled to use 'partial' or 'prefix' mode
+$rcmail_config['addressbook_search_mode'] = 0;
+
 // ----------------------------------
 // USER PREFERENCES
 // ----------------------------------
 // ----------------------------------
 // USER PREFERENCES
 // ----------------------------------
@@ -617,8 +656,8 @@ $rcmail_config['pagesize'] = 40;
 // use this timezone to display date/time
 $rcmail_config['timezone'] = 'auto';
 
 // use this timezone to display date/time
 $rcmail_config['timezone'] = 'auto';
 
-// is daylight saving On?
-$rcmail_config['dst_active'] = (bool)date('I');
+// is daylight saving On? Default: (bool)date('I');
+$rcmail_config['dst_active'] = null;
 
 // prefer displaying HTML messages
 $rcmail_config['prefer_html'] = true;
 
 // prefer displaying HTML messages
 $rcmail_config['prefer_html'] = true;
@@ -748,4 +787,7 @@ $rcmail_config['default_addressbook'] = null;
 // Enables spell checking before sending a message.
 $rcmail_config['spellcheck_before_send'] = false;
 
 // Enables spell checking before sending a message.
 $rcmail_config['spellcheck_before_send'] = false;
 
+// Skip alternative email addresses in autocompletion (show one address per contact)
+$rcmail_config['autocomplete_single'] = false;
+
 // end of config file
 // end of config file
index e3e55d74b719c8ad3f92780b902d7a49b8364939..1a7fcebf3fddabc8acbbcf4969ffadcd821eff87 100644 (file)
--- a/index.php
+++ b/index.php
@@ -2,7 +2,7 @@
 /*
  +-------------------------------------------------------------------------+
  | Roundcube Webmail IMAP Client                                           |
 /*
  +-------------------------------------------------------------------------+
  | Roundcube Webmail IMAP Client                                           |
- | Version 0.6                                                             |
+ | Version 0.7                                                             |
  |                                                                         |
  | Copyright (C) 2005-2011, The Roundcube Dev Team                         |
  |                                                                         |
  |                                                                         |
  | Copyright (C) 2005-2011, The Roundcube Dev Team                         |
  |                                                                         |
@@ -23,7 +23,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                          |
  +-------------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                          |
  +-------------------------------------------------------------------------+
 
- $Id: index.php 5292 2011-09-28 19:16:41Z thomasb $
+ $Id: index.php 5582 2011-12-09 08:55:40Z thomasb $
 
 */
 
 
 */
 
@@ -33,6 +33,9 @@ require_once 'program/include/iniset.php';
 // init application, start session, init output class, etc.
 $RCMAIL = rcmail::get_instance();
 
 // init application, start session, init output class, etc.
 $RCMAIL = rcmail::get_instance();
 
+// Make the whole PHP output non-cacheable (#1487797)
+send_nocacheing_headers();
+
 // turn on output buffering
 ob_start();
 
 // turn on output buffering
 ob_start();
 
@@ -177,7 +180,7 @@ if (empty($RCMAIL->user->ID)) {
       )
     );
   }
       )
     );
   }
-  
+
   if ($session_error || $_REQUEST['_err'] == 'session')
     $OUTPUT->show_message('sessionerror', 'error', null, true, -1);
 
   if ($session_error || $_REQUEST['_err'] == 'session')
     $OUTPUT->show_message('sessionerror', 'error', null, true, -1);
 
@@ -192,7 +195,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() && !$RCMAIL->config->get('devel_mode')) {
   // check client X-header to verify request origin
   if ($OUTPUT->ajax_call) {
     if (rc_request_header('X-Roundcube-Request') != $RCMAIL->get_request_token() && !$RCMAIL->config->get('devel_mode')) {
-      header('HTTP/1.1 404 Not Found');
+      header('HTTP/1.1 403 Forbidden');
       die("Invalid Request");
     }
   }
       die("Invalid Request");
     }
   }
@@ -211,6 +214,12 @@ else {
   }
 }
 
   }
 }
 
+// we're ready, user is authenticated and the request is safe
+$plugin = $RCMAIL->plugins->exec_hook('ready', array('task' => $RCMAIL->task, 'action' => $RCMAIL->action));
+$RCMAIL->set_task($plugin['task']);
+$RCMAIL->action = $plugin['action'];
+
+
 // handle special actions
 if ($RCMAIL->action == 'keep-alive') {
   $OUTPUT->reset();
 // handle special actions
 if ($RCMAIL->action == 'keep-alive') {
   $OUTPUT->reset();
index ff3f7a4c3c5ec00897d076656be27131722bf30e..dbe662acff869750ea29244a98d22a848382ff32 100644 (file)
@@ -142,20 +142,22 @@ class rcube_install
 
     foreach ($this->config as $prop => $default) {
 
 
     foreach ($this->config as $prop => $default) {
 
-      $value = (isset($_POST["_$prop"]) || $this->bool_config_props[$prop]) ? $_POST["_$prop"] : $default;
+      $is_default = !isset($_POST["_$prop"]);
+      $value      = !$is_default || $this->bool_config_props[$prop] ? $_POST["_$prop"] : $default;
 
       // convert some form data
 
       // convert some form data
-      if ($prop == 'debug_level') {
-        $val = 0;
-        if (is_array($value))
+      if ($prop == 'debug_level' && !$is_default) {
+        if (is_array($value)) {
+          $val = 0;
           foreach ($value as $dbgval)
             $val += intval($dbgval);
           foreach ($value as $dbgval)
             $val += intval($dbgval);
-        $value = $val;
+          $value = $val;
+        }
       }
       else if ($which == 'db' && $prop == 'db_dsnw' && !empty($_POST['_dbtype'])) {
         if ($_POST['_dbtype'] == 'sqlite')
           $value = sprintf('%s://%s?mode=0646', $_POST['_dbtype'], $_POST['_dbname']{0} == '/' ? '/' . $_POST['_dbname'] : $_POST['_dbname']);
       }
       else if ($which == 'db' && $prop == 'db_dsnw' && !empty($_POST['_dbtype'])) {
         if ($_POST['_dbtype'] == 'sqlite')
           $value = sprintf('%s://%s?mode=0646', $_POST['_dbtype'], $_POST['_dbname']{0} == '/' ? '/' . $_POST['_dbname'] : $_POST['_dbname']);
-        else
+        else if ($_POST['_dbtype'])
           $value = sprintf('%s://%s:%s@%s/%s', $_POST['_dbtype'], 
             rawurlencode($_POST['_dbuser']), rawurlencode($_POST['_dbpass']), $_POST['_dbhost'], $_POST['_dbname']);
       }
           $value = sprintf('%s://%s:%s@%s/%s', $_POST['_dbtype'], 
             rawurlencode($_POST['_dbuser']), rawurlencode($_POST['_dbpass']), $_POST['_dbhost'], $_POST['_dbname']);
       }
@@ -177,9 +179,9 @@ class rcube_install
         $value = '%p';
       }
       else if ($prop == 'default_imap_folders') {
         $value = '%p';
       }
       else if ($prop == 'default_imap_folders') {
-           $value = Array();
+           $value = array();
            foreach ($this->config['default_imap_folders'] as $_folder) {
            foreach ($this->config['default_imap_folders'] as $_folder) {
-             switch($_folder) {
+             switch ($_folder) {
              case 'Drafts': $_folder = $this->config['drafts_mbox']; break;
              case 'Sent':   $_folder = $this->config['sent_mbox']; break;
              case 'Junk':   $_folder = $this->config['junk_mbox']; break;
              case 'Drafts': $_folder = $this->config['drafts_mbox']; break;
              case 'Sent':   $_folder = $this->config['sent_mbox']; break;
              case 'Junk':   $_folder = $this->config['junk_mbox']; break;
@@ -206,7 +208,7 @@ class rcube_install
       // replace the matching line in config file
       $out = preg_replace(
         '/(\$rcmail_config\[\''.preg_quote($prop).'\'\])\s+=\s+(.+);/Uie',
       // replace the matching line in config file
       $out = preg_replace(
         '/(\$rcmail_config\[\''.preg_quote($prop).'\'\])\s+=\s+(.+);/Uie',
-        "'\\1 = ' . rcube_install::_dump_var(\$value) . ';'",
+        "'\\1 = ' . rcube_install::_dump_var(\$value, \$prop) . ';'",
         $out);
     }
 
         $out);
     }
 
@@ -299,7 +301,7 @@ class rcube_install
     $current = $this->config;
     $this->config = array();
     $this->load_defaults();
     $current = $this->config;
     $this->config = array();
     $this->load_defaults();
-    
+
     foreach ($this->replaced_config as $prop => $replacement) {
       if (isset($current[$prop])) {
         if ($prop == 'skin_path')
     foreach ($this->replaced_config as $prop => $replacement) {
       if (isset($current[$prop])) {
         if ($prop == 'skin_path')
@@ -328,9 +330,9 @@ class rcube_install
     
     if ($current['keep_alive'] && $current['session_lifetime'] < $current['keep_alive'])
       $current['session_lifetime'] = max(10, ceil($current['keep_alive'] / 60) * 2);
     
     if ($current['keep_alive'] && $current['session_lifetime'] < $current['keep_alive'])
       $current['session_lifetime'] = max(10, ceil($current['keep_alive'] / 60) * 2);
-    
+
     $this->config  = array_merge($this->config, $current);
     $this->config  = array_merge($this->config, $current);
-    
+
     foreach ((array)$current['ldap_public'] as $key => $values) {
       $this->config['ldap_public'][$key] = $current['ldap_public'][$key];
     }
     foreach ((array)$current['ldap_public'] as $key => $values) {
       $this->config['ldap_public'][$key] = $current['ldap_public'][$key];
     }
@@ -614,7 +616,22 @@ class rcube_install
   }
   
   
   }
   
   
-  static function _dump_var($var) {
+  static function _dump_var($var, $name=null) {
+    // special values
+    switch ($name) {
+    case 'syslog_facility':
+      $list = array(32 => 'LOG_AUTH', 80 => 'LOG_AUTHPRIV', 72 => ' LOG_CRON',
+                    24 => 'LOG_DAEMON', 0 => 'LOG_KERN', 128 => 'LOG_LOCAL0',
+                    136 => 'LOG_LOCAL1', 144 => 'LOG_LOCAL2', 152 => 'LOG_LOCAL3',
+                    160 => 'LOG_LOCAL4', 168 => 'LOG_LOCAL5', 176 => 'LOG_LOCAL6',
+                    184 => 'LOG_LOCAL7', 48 => 'LOG_LPR', 16 => 'LOG_MAIL',
+                    56 => 'LOG_NEWS', 40 => 'LOG_SYSLOG', 8 => 'LOG_USER', 64 => 'LOG_UUCP');
+      if ($val = $list[$var])
+        return $val;
+      break;
+    }
+
+
     if (is_array($var)) {
       if (empty($var)) {
         return 'array()';
     if (is_array($var)) {
       if (empty($var)) {
         return 'array()';
index 02a1cebe27c40431971b7fa7dee54d6c81b9c1dd..2dd330531e5c36837fa7ba06a8e199dedef8a15d 100644 (file)
@@ -382,18 +382,20 @@ $pass_field = new html_passwordfield(array('name' => '_pass', 'id' => 'imappass'
 <?php
 
 if (isset($_POST['imaptest']) && !empty($_POST['_host']) && !empty($_POST['_user'])) {
 <?php
 
 if (isset($_POST['imaptest']) && !empty($_POST['_host']) && !empty($_POST['_user'])) {
-  
+
   echo '<p>Connecting to ' . Q($_POST['_host']) . '...<br />';
   echo '<p>Connecting to ' . Q($_POST['_host']) . '...<br />';
-  
-  $a_host = parse_url($_POST['_host']);
+
+  $imap_host = trim($_POST['_host']);
+  $imap_port = $RCI->getprop('default_port');
+  $a_host    = parse_url($imap_host);
+
   if ($a_host['host']) {
     $imap_host = $a_host['host'];
   if ($a_host['host']) {
     $imap_host = $a_host['host'];
-    $imap_ssl = (isset($a_host['scheme']) && in_array($a_host['scheme'], array('ssl','imaps','tls'))) ? $a_host['scheme'] : null;
-    $imap_port = isset($a_host['port']) ? $a_host['port'] : ($imap_ssl ? 993 : $CONFIG['default_port']);
-  }
-  else {
-    $imap_host = trim($_POST['_host']);
-    $imap_port = $RCI->getprop('default_port');
+    $imap_ssl  = (isset($a_host['scheme']) && in_array($a_host['scheme'], array('ssl','imaps','tls'))) ? $a_host['scheme'] : null;
+    if (isset($a_host['port']))
+      $imap_port = $a_host['port'];
+    else if ($imap_ssl && $imap_ssl != 'tls' && (!$imap_port || $imap_port == 143))
+      $imap_port = 993;
   }
 
   $imap_host = idn_to_ascii($imap_host);
   }
 
   $imap_host = idn_to_ascii($imap_host);
index 4b1431ac3106cef0e2baaa1bf70f814114582773..c4011a81c5af16faf1dc8d0c0013ce9940ccafc6 100644 (file)
@@ -1,7 +1,7 @@
 /**
  * ACL plugin script
  *
 /**
  * ACL plugin script
  *
- * @version 0.6.1
+ * @version 0.6.3
  * @author Aleksander Machniak <alec@alec.pl>
  */
 
  * @author Aleksander Machniak <alec@alec.pl>
  */
 
@@ -315,6 +315,9 @@ rcube_webmail.prototype.acl_init_form = function(id)
     this.acl_form.show();
     if (type == 'user')
         name_input.focus();
     this.acl_form.show();
     if (type == 'user')
         name_input.focus();
+
+    // unfocus the list, make backspace key in name input field working
+    this.acl_list.blur();
 }
 
 // Returns class name according to ACL comparision result
 }
 
 // Returns class name according to ACL comparision result
index 976b362608ea50c517264324b9fd6a8a3c5e0ae8..3a5fd1ac1f822264a441d6b14381746bbb2706a1 100644 (file)
@@ -3,7 +3,7 @@
 /**
  * Folders Access Control Lists Management (RFC4314, RFC2086)
  *
 /**
  * Folders Access Control Lists Management (RFC4314, RFC2086)
  *
- * @version 0.6.1
+ * @version @package_version@
  * @author Aleksander Machniak <alec@alec.pl>
  *
  *
  * @author Aleksander Machniak <alec@alec.pl>
  *
  *
@@ -87,11 +87,15 @@ class acl extends rcube_plugin
         $this->load_config();
 
         $search = get_input_value('_search', RCUBE_INPUT_GPC, true);
         $this->load_config();
 
         $search = get_input_value('_search', RCUBE_INPUT_GPC, true);
+        $sid    = get_input_value('_id', RCUBE_INPUT_GPC);
         $users  = array();
 
         if ($this->init_ldap()) {
         $users  = array();
 
         if ($this->init_ldap()) {
-            $this->ldap->set_pagesize(15);
-            $result = $this->ldap->search('*', $search);
+            $max  = (int) $this->rc->config->get('autocomplete_max', 15);
+            $mode = (int) $this->rc->config->get('addressbook_search_mode');
+
+            $this->ldap->set_pagesize($max);
+            $result = $this->ldap->search('*', $search, $mode);
 
             foreach ($result->records as $record) {
                 $user = $record['uid'];
 
             foreach ($result->records as $record) {
                 $user = $record['uid'];
@@ -112,7 +116,7 @@ class acl extends rcube_plugin
 
         sort($users, SORT_LOCALE_STRING);
 
 
         sort($users, SORT_LOCALE_STRING);
 
-        $this->rc->output->command('ksearch_query_results', $users, $search);
+        $this->rc->output->command('ksearch_query_results', $users, $search, $sid);
         $this->rc->output->send();
     }
 
         $this->rc->output->send();
     }
 
@@ -186,6 +190,10 @@ class acl extends rcube_plugin
             'aclrights' => array($this, 'templ_rights'),
         ));
 
             'aclrights' => array($this, 'templ_rights'),
         ));
 
+        $this->rc->output->set_env('autocomplete_max', (int)$this->rc->config->get('autocomplete_max', 15));
+        $this->rc->output->set_env('autocomplete_min_length', $this->rc->config->get('autocomplete_min_length'));
+        $this->rc->output->add_label('autocompletechars', 'autocompletemore');
+
         $args['form']['sharing'] = array(
             'name'    => Q($this->gettext('sharing')),
             'content' => $this->rc->output->parse('acl.table', false, false),
         $args['form']['sharing'] = array(
             'name'    => Q($this->gettext('sharing')),
             'content' => $this->rc->output->parse('acl.table', false, false),
@@ -619,7 +627,6 @@ class acl extends rcube_plugin
             $acl = $this->rc->imap->get_acl('INBOX');
             if (is_array($acl)) {
                 $regexp = '/^' . preg_quote($_SESSION['username'], '/') . '@(.*)$/';
             $acl = $this->rc->imap->get_acl('INBOX');
             if (is_array($acl)) {
                 $regexp = '/^' . preg_quote($_SESSION['username'], '/') . '@(.*)$/';
-                $regexp = '/^' . preg_quote('aleksander.machniak', '/') . '@(.*)$/';
                 foreach (array_keys($acl) as $name) {
                     if (preg_match($regexp, $name, $matches)) {
                         $domain = $matches[1];
                 foreach (array_keys($acl) as $name) {
                     if (preg_match($regexp, $name, $matches)) {
                         $domain = $matches[1];
index e46a1d00b2ae977441d0c0f7c637df3f0e3e6d7c..cf3391f4934cc5d018e3247bb0547280311570de 100644 (file)
   background-color: #CC3333;
 }
 
   background-color: #CC3333;
 }
 
+#acltable tr.unfocused td
+{
+  color: #FFFFFF;
+  background-color: #929292;
+}
+
 #acladvswitch
 {
   position: absolute;
 #acladvswitch
 {
   position: absolute;
index a837508192663c2640b48ca4bb836f7f917e8d70..5c576e1009444c23151fc0a33c971b0c85d460b4 100644 (file)
@@ -27,7 +27,9 @@ if (window.rcmail) {
     
     // set css style for archive folder
     var li;
     
     // set css style for archive folder
     var li;
-    if (rcmail.env.archive_folder && rcmail.env.archive_folder_icon && (li = rcmail.get_folder_li(rcmail.env.archive_folder)))
+    if (rcmail.env.archive_folder && rcmail.env.archive_folder_icon
+      && (li = rcmail.get_folder_li(rcmail.env.archive_folder, '', true))
+    )
       $(li).css('background-image', 'url(' + rcmail.env.archive_folder_icon + ')');
   })
 }
       $(li).css('background-image', 'url(' + rcmail.env.archive_folder_icon + ')');
   })
 }
index 843b61217612e611a96a4e410b7fd0fe30d28a38..a56806263c2fa2ed9af494a363015ff0d659d879 100644 (file)
@@ -100,7 +100,7 @@ class archive extends rcube_plugin
       // load folders list when needed
       if ($CURR_SECTION)
         $select = rcmail_mailbox_select(array('noselection' => '---', 'realnames' => true,
       // load folders list when needed
       if ($CURR_SECTION)
         $select = rcmail_mailbox_select(array('noselection' => '---', 'realnames' => true,
-          'maxlength' => 30, 'exceptions' => array('INBOX')));
+          'maxlength' => 30, 'exceptions' => array('INBOX'), 'folder_filter' => 'mail', 'folder_rights' => 'w'));
       else
         $select = new html_select();
 
       else
         $select = new html_select();
 
index f44f30f44e17696fa63996304d0a8a5d3452c67a..498a091fe82810c6af162bce0d5beb04021ded5d 100644 (file)
@@ -2,7 +2,7 @@
 
 $labels = array();
 $labels['buttontitle'] = 'Archiver ce message';
 
 $labels = array();
 $labels['buttontitle'] = 'Archiver ce message';
-$labels['archived'] = 'Message archivé avec success';
+$labels['archived'] = 'Message archivé avec success';
 $labels['archivefolder'] = 'Archive';
 
 ?>
 $labels['archivefolder'] = 'Archive';
 
 ?>
index c442a5c4d2233e938e0d9d84f966e9acecf0b16e..c549fc9b7b516c67b4ee4870173050483169949c 100644 (file)
                <email>roundcube@gmail.com</email>
                <active>yes</active>
        </lead>
                <email>roundcube@gmail.com</email>
                <active>yes</active>
        </lead>
-       <date>2010-02-06</date>
-       <time>12:12:00</time>
+       <date>2011-11-23</date>
        <version>
        <version>
-               <release>1.4</release>
+               <release>1.5</release>
                <api>1.4</api>
        </version>
        <stability>
                <api>1.4</api>
        </version>
        <stability>
                                <tasks:replace from="@name@" to="name" type="package-info"/>
                                <tasks:replace from="@package_version@" to="version" type="package-info"/>
                        </file>
                                <tasks:replace from="@name@" to="name" type="package-info"/>
                                <tasks:replace from="@package_version@" to="version" type="package-info"/>
                        </file>
-                       <file name="localization/en_US.inc" role="data"></file>
                        <file name="localization/cs_CZ.inc" role="data"></file>
                        <file name="localization/de_CH.inc" role="data"></file>
                        <file name="localization/de_DE.inc" role="data"></file>
                        <file name="localization/cs_CZ.inc" role="data"></file>
                        <file name="localization/de_CH.inc" role="data"></file>
                        <file name="localization/de_DE.inc" role="data"></file>
+                       <file name="localization/en_US.inc" role="data"></file>
+                       <file name="localization/es_AR.inc" role="data"></file>
+                       <file name="localization/es_ES.inc" role="data"></file>
                        <file name="localization/et_EE.inc" role="data"></file>
                        <file name="localization/fr_FR.inc" role="data"></file>
                        <file name="localization/et_EE.inc" role="data"></file>
                        <file name="localization/fr_FR.inc" role="data"></file>
+                       <file name="localization/gl_ES.inc" role="data"></file>
+                       <file name="localization/ja_JP.inc" role="data"></file>
+                       <file name="localization/nl_NL.inc" role="data"></file>
                        <file name="localization/pl_PL.inc" role="data"></file>
                        <file name="localization/pl_PL.inc" role="data"></file>
+                       <file name="localization/pt_BR.inc" role="data"></file>
                        <file name="localization/ru_RU.inc" role="data"></file>
                        <file name="localization/ru_RU.inc" role="data"></file>
+                       <file name="localization/sv_SE.inc" role="data"></file>
                        <file name="localization/zh_TW.inc" role="data"></file>
                        <file name="skins/default/archive_act.png" role="data"></file>
                        <file name="skins/default/archive_pas.png" role="data"></file>
                        <file name="localization/zh_TW.inc" role="data"></file>
                        <file name="skins/default/archive_act.png" role="data"></file>
                        <file name="skins/default/archive_pas.png" role="data"></file>
index afb23224ca7998cc4031010b481ab9d3ba0899db..22d6e513a2de7a25e50b2a3d68503d21cb4d5baf 100644 (file)
@@ -18,7 +18,7 @@ Enigma Plugin Status:
 - Parsing of decrypted messages into array (see rcube_mime_struct) and then into rcube_message_part structure
   (create core class rcube_mime_parser or take over PEAR::Mail_mimeDecode package and improve it)
 - Sending encrypted/signed messages (probably some changes in core will be needed)
 - Parsing of decrypted messages into array (see rcube_mime_struct) and then into rcube_message_part structure
   (create core class rcube_mime_parser or take over PEAR::Mail_mimeDecode package and improve it)
 - Sending encrypted/signed messages (probably some changes in core will be needed)
-- Per-Identity settings (including keys/certs) (+ split Identities details page into tabs)
+- Per-Identity settings (including keys/certs)
 - Handling big messages with temp files (including changes in Roundcube core)
 - Performance improvements (some caching, code review)
 - better (and more) icons
 - Handling big messages with temp files (including changes in Roundcube core)
 - Performance improvements (some caching, code review)
 - better (and more) icons
diff --git a/plugins/enigma/config.inc.php b/plugins/enigma/config.inc.php
deleted file mode 100644 (file)
index ca841d0..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-<?php
-
-// Enigma Plugin options
-// --------------------
-
-// A driver to use for PGP. Default: "gnupg".
-$rcmail_config['enigma_pgp_driver'] = 'gnupg';
-
-// A driver to use for S/MIME. Default: "phpssl".
-$rcmail_config['enigma_smime_driver'] = 'phpssl';
-
-// Keys directory for all users. Default 'enigma/home'.
-// Must be writeable by PHP process
-$rcmail_config['enigma_pgp_homedir'] = null;
diff --git a/plugins/enigma/config.inc.php.dist b/plugins/enigma/config.inc.php.dist
new file mode 100644 (file)
index 0000000..ca841d0
--- /dev/null
@@ -0,0 +1,14 @@
+<?php
+
+// Enigma Plugin options
+// --------------------
+
+// A driver to use for PGP. Default: "gnupg".
+$rcmail_config['enigma_pgp_driver'] = 'gnupg';
+
+// A driver to use for S/MIME. Default: "phpssl".
+$rcmail_config['enigma_smime_driver'] = 'phpssl';
+
+// Keys directory for all users. Default 'enigma/home'.
+// Must be writeable by PHP process
+$rcmail_config['enigma_pgp_homedir'] = null;
index b9ccff53db9b0e3378445dec8f193f8bcbc6eaa9..5901b58d9a1f6d68fd232db8e3a18ce0e4ecf044 100644 (file)
@@ -412,9 +412,6 @@ class enigma_ui
 
     private function compose_ui()
     {
 
     private function compose_ui()
     {
-        if (!is_array($_SESSION['compose']) || $_SESSION['compose']['id'] != get_input_value('_id', RCUBE_INPUT_GET))
-            return;
-
         // Options menu button
         // @TODO: make this work with non-default skins
         $this->enigma->add_button(array(
         // Options menu button
         // @TODO: make this work with non-default skins
         $this->enigma->add_button(array(
index fa074f09accdb243120b1245f0f3cde959ab4262..be49b52be0c70fe3a6b0b4fbd29d7c1fb0b7829e 100644 (file)
@@ -53,7 +53,7 @@ class http_authentication extends rcube_plugin
 
     return $args;
   }
 
     return $args;
   }
-
+  
   function logout($args)
   {
     // redirect to configured URL in order to clear HTTP auth credentials
   function logout($args)
   {
     // redirect to configured URL in order to clear HTTP auth credentials
index e35406459bc102c5f323847e2850dbfa5e905e9d..05506120e192ab9f0df28e651ca8a5d90db383cc 100644 (file)
@@ -1,4 +1,36 @@
+- Fixed setting test type to :is when none is specified
+- Fixed javascript error in IE8
+
+* version 5.0-rc1 [2011-11-17]
+-----------------------------------------------------------
+- Fixed sorting of scripts, scripts including aware of the sort order
+- Fixed import of rules with unsupported tests
+- Added 'address' and 'envelope' tests support
+- Added 'body' extension support (RFC5173)
+- Added 'subaddress' extension support (RFC5233)
+- Added comparators support
+- Changed Sender/Recipient labels to From/To
+- Fixed importing rule names from Ingo
+- Fixed handling of extensions disabled in config
+
+* version 5.0-beta [2011-10-17]
+-----------------------------------------------------------
+- Added possibility to create a filter based on selected message "in-place"
 - Fixed import from Horde-INGO (#1488064)
 - Fixed import from Horde-INGO (#1488064)
+- Add managesieve_script_name option for default name of the script (#1487956)
+- Fixed handling of enabled magic_quotes_gpc setting
+- Fixed PHP warning on connection error when submitting filter form
+- Fixed bug where new action row with flags wasn't handled properly
+- Added managesieve_connect hook for plugins
+- Fixed doubled Filter tab on page refresh
+- Added filters set selector in filter form when invoked in mail task
+- Improved script parser, added support for include and variables extensions
+- Added Kolab's KEP:14 support (http://wiki.kolab.org/User:Greve/Drafts/KEP:14)
+- Use smaller action/rule buttons
+- UI redesign: added possibility to move filter to any place using drag&drop
+  (instead of up/down buttons), added filter sets list object, added more
+  'loading' messages
+- Added option to hide some scripts (managesieve_filename_exceptions)
 
 * version 4.3 [2011-07-28]
 -----------------------------------------------------------
 
 * version 4.3 [2011-07-28]
 -----------------------------------------------------------
index 905cfef18c5da255cbd2997ce58ddac5aa625a85..cb9b2a97ffa36c41d61261605768449fd53b2445 100644 (file)
@@ -31,6 +31,9 @@ $rcmail_config['managesieve_usetls'] = false;
 // default contents of filters script (eg. default spam filter)
 $rcmail_config['managesieve_default'] = '/etc/dovecot/sieve/global';
 
 // default contents of filters script (eg. default spam filter)
 $rcmail_config['managesieve_default'] = '/etc/dovecot/sieve/global';
 
+// The name of the script which will be used when there's no user script
+$rcmail_config['managesieve_script_name'] = 'managesieve';
+
 // Sieve RFC says that we should use UTF-8 endcoding for mailbox names,
 // but some implementations does not covert UTF-8 to modified UTF-7.
 // Defaults to UTF7-IMAP
 // Sieve RFC says that we should use UTF-8 endcoding for mailbox names,
 // but some implementations does not covert UTF-8 to modified UTF-7.
 // Defaults to UTF7-IMAP
@@ -50,4 +53,15 @@ $rcmail_config['managesieve_disabled_extensions'] = array();
 // Enables debugging of conversation with sieve server. Logs it into <log_dir>/sieve
 $rcmail_config['managesieve_debug'] = false;
 
 // Enables debugging of conversation with sieve server. Logs it into <log_dir>/sieve
 $rcmail_config['managesieve_debug'] = false;
 
+// Enables features described in http://wiki.kolab.org/KEP:14
+$rcmail_config['managesieve_kolab_master'] = false;
+
+// Script name extension used for scripts including. Dovecot uses '.sieve',
+// Cyrus uses '.siv'. Doesn't matter if you have managesieve_kolab_master disabled.
+$rcmail_config['managesieve_filename_extension'] = '.sieve';
+
+// List of reserved script names (without extension).
+// Scripts listed here will be not presented to the user.
+$rcmail_config['managesieve_filename_exceptions'] = array();
+
 ?>
 ?>
index 3e52809137b320e5d8cbab18cfd270b59e153cf5..7c4f0aa31a20f8d7e257b6cced9688a59f0aa26e 100644 (file)
@@ -1,13 +1,27 @@
 <?php
 
 /**
 <?php
 
 /**
-  Classes for managesieve operations (using PEAR::Net_Sieve)
-
-  Author: Aleksander Machniak <alec@alec.pl>
-
-  $Id: rcube_sieve.php 5203 2011-09-12 06:44:56Z alec $
-
-*/
+ *  Classes for managesieve operations (using PEAR::Net_Sieve)
+ *
+ * Copyright (C) 2008-2011, The Roundcube Dev Team
+ * Copyright (C) 2011, Kolab Systems AG
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * $Id: rcube_sieve.php 5452 2011-11-18 14:44:48Z alec $
+ *
+ */
 
 // Managesieve Protocol: RFC5804
 
 
 // Managesieve Protocol: RFC5804
 
@@ -30,7 +44,6 @@ class rcube_sieve
 
     public $script;                 // rcube_sieve_script object
     public $current;                // name of currently loaded script
 
     public $script;                 // rcube_sieve_script object
     public $current;                // name of currently loaded script
-    private $disabled;              // array of disabled extensions
     private $exts;                  // array of supported extensions
 
 
     private $exts;                  // array of supported extensions
 
 
@@ -75,7 +88,17 @@ class rcube_sieve
         }
 
         $this->exts     = $this->get_extensions();
         }
 
         $this->exts     = $this->get_extensions();
-        $this->disabled = $disabled;
+
+        // disable features by config
+        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->exts)) !== false) {
+                    unset($this->exts[$idx]);
+                }
+            }
+        }
     }
 
     public function __destruct() {
     }
 
     public function __destruct() {
@@ -195,7 +218,7 @@ class rcube_sieve
     {
         if ($this->exts)
             return $this->exts;
     {
         if ($this->exts)
             return $this->exts;
-    
+
         if (!$this->sieve)
             return $this->_set_error(SIEVE_ERROR_INTERNAL);
 
         if (!$this->sieve)
             return $this->_set_error(SIEVE_ERROR_INTERNAL);
 
@@ -286,23 +309,28 @@ class rcube_sieve
      */
     private function _parse($txt)
     {
      */
     private function _parse($txt)
     {
-        // try to parse from Roundcube format
-        $script = new rcube_sieve_script($txt, $this->disabled, $this->exts);
-
-        // ... else try to import from different formats
-        if (empty($script->content)) {
-            $script = $this->_import_rules($txt);
-            $script = new rcube_sieve_script($script, $this->disabled, $this->exts);
+        // parse
+        $script = new rcube_sieve_script($txt, $this->exts);
 
 
+        // fix/convert to Roundcube format
+        if (!empty($script->content)) {
             // replace all elsif with if+stop, we support only ifs
             foreach ($script->content as $idx => $rule) {
             // replace all elsif with if+stop, we support only ifs
             foreach ($script->content as $idx => $rule) {
+                if (empty($rule['type']) || !preg_match('/^(if|elsif|else)$/', $rule['type'])) {
+                    continue;
+                }
+
+                $script->content[$idx]['type'] = 'if';
+
                 // 'stop' not found?
                 foreach ($rule['actions'] as $action) {
                     if (preg_match('/^(stop|vacation)$/', $action['type'])) {
                         continue 2;
                     }
                 }
                 // 'stop' not found?
                 foreach ($rule['actions'] as $action) {
                     if (preg_match('/^(stop|vacation)$/', $action['type'])) {
                         continue 2;
                     }
                 }
-                $script->content[$idx]['actions'][] = array('type' => 'stop');
+                if (empty($script->content[$idx+1]) || $script->content[$idx+1]['type'] != 'if') {
+                    $script->content[$idx]['actions'][] = array('type' => 'stop');
+                }
             }
         }
 
             }
         }
 
@@ -343,48 +371,6 @@ class rcube_sieve
         return $this->save_script($name, $content);
     }
 
         return $this->save_script($name, $content);
     }
 
-    private function _import_rules($script)
-    {
-        $i = 0;
-        $name = array();
-
-        // Squirrelmail (Avelsieve)
-        if (preg_match('/(#START_SIEVE_RULE.*END_SIEVE_RULE)\r?\n/', $script)) {
-            $tokens = preg_split('/(#START_SIEVE_RULE.*END_SIEVE_RULE)\r?\n/', $script, -1, PREG_SPLIT_DELIM_CAPTURE);
-            foreach ($tokens as $token) {
-                if (preg_match('/^#START_SIEVE_RULE.*/', $token, $matches)) {
-                    $name[$i] = "unnamed rule ".($i+1);
-                    $content .= "# rule:[".$name[$i]."]\n";
-                }
-                elseif (isset($name[$i])) {
-                    // This preg_replace is added because I've found some Avelsieve scripts
-                    // with rules containing "if" here. I'm not sure it was working
-                    // before without this or not.
-                    $token = preg_replace('/^if\s+/', '', trim($token));
-                    $content .= "if $token\n";
-                    $i++;
-                }
-            }
-        }
-        // Horde (INGO)
-        else if (preg_match('/(# .+)\r?\n/', $script)) {
-            $tokens = preg_split('/(# .+)\r?\n/', $script, -1, PREG_SPLIT_DELIM_CAPTURE);
-            foreach($tokens as $token) {
-                if (preg_match('/^# (.+)/', $token, $matches)) {
-                    $name[$i] = $matches[1];
-                    $content .= "# rule:[" . $name[$i] . "]\n";
-                }
-                elseif (isset($name[$i])) {
-                    $token = str_replace(":comparator \"i;ascii-casemap\" ", "", $token);
-                    $content .= $token . "\n";
-                    $i++;
-                }
-            }
-        }
-
-        return $content;
-    }
-
     private function _set_error($error)
     {
         $this->error = $error;
     private function _set_error($error)
     {
         $this->error = $error;
index 871fb1401623c94110e175b22dc3e7944478e8fa..04bcc4c139428939b99a5f4c09388fd03e707481 100644 (file)
@@ -1,20 +1,37 @@
 <?php
 
 /**
 <?php
 
 /**
-  Class for operations on Sieve scripts
-
-  Author: Aleksander Machniak <alec@alec.pl>
-
-  $Id: rcube_sieve_script.php 4806 2011-05-24 08:32:01Z alec $
-
-*/
+ *  Class for operations on Sieve scripts
+ *
+ * Copyright (C) 2008-2011, The Roundcube Dev Team
+ * Copyright (C) 2011, Kolab Systems AG
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * $Id: rcube_sieve_script.php 5452 2011-11-18 14:44:48Z alec $
+ *
+ */
 
 class rcube_sieve_script
 {
     public $content = array();      // script rules array
 
 
 class rcube_sieve_script
 {
     public $content = array();      // script rules array
 
-    private $supported = array(     // extensions supported by class
-        'fileinto',                 // RFC3028
+    private $vars = array();        // "global" variables
+    private $prefix = '';           // script header (comments)
+    private $supported = array(     // Sieve extensions supported by class
+        'fileinto',                 // RFC5228
+        'envelope',                 // RFC5228
         'reject',                   // RFC5429
         'ereject',                  // RFC5429
         'copy',                     // RFC3894
         'reject',                   // RFC5429
         'ereject',                  // RFC5429
         'copy',                     // RFC3894
@@ -23,57 +40,34 @@ class rcube_sieve_script
         'regex',                    // draft-ietf-sieve-regex-01
         'imapflags',                // draft-melnikov-sieve-imapflags-06
         'imap4flags',               // RFC5232
         'regex',                    // draft-ietf-sieve-regex-01
         'imapflags',                // draft-melnikov-sieve-imapflags-06
         'imap4flags',               // RFC5232
-        // TODO: body, notify
+        'include',                  // draft-ietf-sieve-include-12
+        'variables',                // RFC5229
+        'body',                     // RFC5173
+        'subaddress',               // RFC5233
+        // @TODO: enotify/notify, spamtest+virustest, mailbox, date
     );
 
     );
 
-    private $capabilities;
-
     /**
      * Object constructor
      *
      * @param  string  Script's text content
     /**
      * Object constructor
      *
      * @param  string  Script's text content
-     * @param  array   List of disabled extensions
      * @param  array   List of capabilities supported by server
      */
      * @param  array   List of capabilities supported by server
      */
-    public function __construct($script, $disabled=null, $capabilities=null)
+    public function __construct($script, $capabilities=array())
     {
     {
-        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) {
+        $capabilities = array_map('strtolower', (array) $capabilities);
+
+        // disable features by server capabilities
+        if (!empty($capabilities)) {
+            foreach ($this->supported as $idx => $ext) {
+                if (!in_array($ext, $capabilities)) {
                     unset($this->supported[$idx]);
                 }
             }
         }
 
                     unset($this->supported[$idx]);
                 }
             }
         }
 
-        $this->capabilities = $capabilities;
-        $this->content      = $this->_parse_text($script);
-    }
-
-    /**
-     * Adds script contents as text to the script array (at the end)
-     *
-     * @param    string    Text script contents
-     */
-    public function add_text($script)
-    {
-        $content = $this->_parse_text($script);
-        $result = false;
-
-        // check existsing script rules names
-        foreach ($this->content as $idx => $elem) {
-            $names[$elem['name']] = $idx;
-        }
-
-        foreach ($content as $elem) {
-            if (!isset($names[$elem['name']])) {
-                array_push($this->content, $elem);
-                $result = true;
-            }
-        }
-
-        return $result;
+        // Parse text content of the script
+        $this->_parse_text($script);
     }
 
     /**
     }
 
     /**
@@ -81,6 +75,8 @@ class rcube_sieve_script
      *
      * @param string Rule name
      * @param array  Rule content (as array)
      *
      * @param string Rule name
      * @param array  Rule content (as array)
+     *
+     * @return int The index of the new rule
      */
     public function add_rule($content)
     {
      */
     public function add_rule($content)
     {
@@ -113,162 +109,344 @@ class rcube_sieve_script
         return false;
     }
 
         return false;
     }
 
+    /**
+     * Sets "global" variable
+     *
+     * @param string $name  Variable name
+     * @param string $value Variable value
+     * @param array  $mods  Variable modifiers
+     */
+    public function set_var($name, $value, $mods = array())
+    {
+        // Check if variable exists
+        for ($i=0, $len=count($this->vars); $i<$len; $i++) {
+            if ($this->vars[$i]['name'] == $name) {
+                break;
+            }
+        }
+
+        $var = array_merge($mods, array('name' => $name, 'value' => $value));
+        $this->vars[$i] = $var;
+    }
+
+    /**
+     * Unsets "global" variable
+     *
+     * @param string $name  Variable name
+     */
+    public function unset_var($name)
+    {
+        // Check if variable exists
+        foreach ($this->vars as $idx => $var) {
+            if ($var['name'] == $name) {
+                unset($this->vars[$idx]);
+                break;
+            }
+        }
+    }
+
+    /**
+     * Gets the value of  "global" variable
+     *
+     * @param string $name  Variable name
+     *
+     * @return string Variable value
+     */
+    public function get_var($name)
+    {
+        // Check if variable exists
+        for ($i=0, $len=count($this->vars); $i<$len; $i++) {
+            if ($this->vars[$i]['name'] == $name) {
+                return $this->vars[$i]['name'];
+            }
+        }
+    }
+
+    /**
+     * Sets script header content
+     *
+     * @param string $text  Header content
+     */
+    public function set_prefix($text)
+    {
+        $this->prefix = $text;
+    }
+
     /**
      * Returns script as text
      */
     public function as_text()
     {
     /**
      * Returns script as text
      */
     public function as_text()
     {
-        $script = '';
-        $exts = array();
-        $idx = 0;
+        $output = '';
+        $exts   = array();
+        $idx    = 0;
+
+        if (!empty($this->vars)) {
+            if (in_array('variables', (array)$this->supported)) {
+                $has_vars = true;
+                array_push($exts, 'variables');
+            }
+            foreach ($this->vars as $var) {
+                if (empty($has_vars)) {
+                    // 'variables' extension not supported, put vars in comments
+                    $output .= sprintf("# %s %s\n", $var['name'], $var['value']);
+                }
+                else {
+                    $output .= 'set ';
+                    foreach (array_diff(array_keys($var), array('name', 'value')) as $opt) {
+                        $output .= ":$opt ";
+                    }
+                    $output .= self::escape_string($var['name']) . ' ' . self::escape_string($var['value']) . ";\n";
+                }
+            }
+        }
 
         // rules
         foreach ($this->content as $rule) {
             $extension = '';
 
         // rules
         foreach ($this->content as $rule) {
             $extension = '';
-            $tests = array();
-            $i = 0;
+            $script    = '';
+            $tests     = array();
+            $i         = 0;
 
             // header
 
             // header
-            $script .= '# rule:[' . $rule['name'] . "]\n";
+            if (!empty($rule['name']) && strlen($rule['name'])) {
+                $script .= '# rule:[' . $rule['name'] . "]\n";
+            }
 
             // constraints expressions
 
             // constraints expressions
-            foreach ($rule['tests'] as $test) {
-                $tests[$i] = '';
-                switch ($test['test']) {
-                case 'size':
-                    $tests[$i] .= ($test['not'] ? 'not ' : '');
-                    $tests[$i] .= 'size :' . ($test['type']=='under' ? 'under ' : 'over ') . $test['arg'];
-                    break;
-                case 'true':
-                    $tests[$i] .= ($test['not'] ? 'false' : 'true');
-                    break;
-                case 'exists':
-                    $tests[$i] .= ($test['not'] ? 'not ' : '');
-                    $tests[$i] .= 'exists ' . self::escape_string($test['arg']);
-                    break;
-                case 'header':
-                    $tests[$i] .= ($test['not'] ? 'not ' : '');
+            if (!empty($rule['tests'])) {
+                foreach ($rule['tests'] as $test) {
+                    $tests[$i] = '';
+                    switch ($test['test']) {
+                    case 'size':
+                        $tests[$i] .= ($test['not'] ? 'not ' : '');
+                        $tests[$i] .= 'size :' . ($test['type']=='under' ? 'under ' : 'over ') . $test['arg'];
+                        break;
 
 
-                    // relational operator + comparator
-                                       if (preg_match('/^(value|count)-([gteqnl]{2})/', $test['type'], $m)) {
-                                               array_push($exts, 'relational');
-                                               array_push($exts, 'comparator-i;ascii-numeric');
+                    case 'true':
+                        $tests[$i] .= ($test['not'] ? 'false' : 'true');
+                        break;
 
 
-                        $tests[$i] .= 'header :' . $m[1] . ' "' . $m[2] . '" :comparator "i;ascii-numeric"';
-                    }
-                    else {
-                                           if ($test['type'] == 'regex') {
-                                                   array_push($exts, 'regex');
+                    case 'exists':
+                        $tests[$i] .= ($test['not'] ? 'not ' : '');
+                        $tests[$i] .= 'exists ' . self::escape_string($test['arg']);
+                        break;
+
+                    case 'header':
+                        $tests[$i] .= ($test['not'] ? 'not ' : '');
+                        $tests[$i] .= 'header';
+
+                        if (!empty($test['type'])) {
+                            // relational operator + comparator
+                            if (preg_match('/^(value|count)-([gteqnl]{2})/', $test['type'], $m)) {
+                                array_push($exts, 'relational');
+                                array_push($exts, 'comparator-i;ascii-numeric');
+
+                                $tests[$i] .= ' :' . $m[1] . ' "' . $m[2] . '" :comparator "i;ascii-numeric"';
+                            }
+                            else {
+                                $this->add_comparator($test, $tests[$i], $exts);
+
+                                if ($test['type'] == 'regex') {
+                                    array_push($exts, 'regex');
+                                }
+
+                                $tests[$i] .= ' :' . $test['type'];
+                            }
                         }
 
                         }
 
-                        $tests[$i] .= 'header :' . $test['type'];
-                    }
+                        $tests[$i] .= ' ' . self::escape_string($test['arg1']);
+                        $tests[$i] .= ' ' . self::escape_string($test['arg2']);
+                        break;
 
 
-                    $tests[$i] .= ' ' . self::escape_string($test['arg1']);
-                    $tests[$i] .= ' ' . self::escape_string($test['arg2']);
-                    break;
+                    case 'address':
+                    case 'envelope':
+                        if ($test['test'] == 'envelope') {
+                            array_push($exts, 'envelope');
+                        }
+
+                        $tests[$i] .= ($test['not'] ? 'not ' : '');
+                        $tests[$i] .= $test['test'];
+
+                        if (!empty($test['part'])) {
+                            $tests[$i] .= ' :' . $test['part'];
+                            if ($test['part'] == 'user' || $test['part'] == 'detail') {
+                                array_push($exts, 'subaddress');
+                            }
+                        }
+
+                        $this->add_comparator($test, $tests[$i], $exts);
+
+                        if (!empty($test['type'])) {
+                            if ($test['type'] == 'regex') {
+                                array_push($exts, 'regex');
+                            }
+                            $tests[$i] .= ' :' . $test['type'];
+                        }
+
+                        $tests[$i] .= ' ' . self::escape_string($test['arg1']);
+                        $tests[$i] .= ' ' . self::escape_string($test['arg2']);
+                        break;
+
+                    case 'body':
+                        array_push($exts, 'body');
+
+                        $tests[$i] .= ($test['not'] ? 'not ' : '') . 'body';
+
+                        $this->add_comparator($test, $tests[$i], $exts);
+
+                        if (!empty($test['part'])) {
+                            $tests[$i] .= ' :' . $test['part'];
+
+                            if (!empty($test['content']) && $test['part'] == 'content') {
+                                $tests[$i] .= ' ' . self::escape_string($test['content']);
+                            }
+                        }
+
+                        if (!empty($test['type'])) {
+                            if ($test['type'] == 'regex') {
+                                array_push($exts, 'regex');
+                            }
+                            $tests[$i] .= ' :' . $test['type'];
+                        }
+
+                        $tests[$i] .= ' ' . self::escape_string($test['arg']);
+                        break;
+                    }
+                    $i++;
                 }
                 }
-                $i++;
             }
 
             // disabled rule: if false #....
             }
 
             // disabled rule: if false #....
-            $script .= 'if ' . ($rule['disabled'] ? 'false # ' : '');
+            if (!empty($tests)) {
+                $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 (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;
+                if ($rule['join'] || count($tests) > 1) {
+                    $script .= sprintf('%s (%s)', $rule['join'] ? 'allof' : 'anyof', $tests_str);
+                }
+                else {
+                    $script .= $tests_str;
+                }
+                $script .= "\n{\n";
             }
             }
-            $script .= "\n{\n";
 
             // action(s)
 
             // action(s)
-            foreach ($rule['actions'] as $action) {
-                switch ($action['type']) {
+            if (!empty($rule['actions'])) {
+                foreach ($rule['actions'] as $action) {
+                    $action_script = '';
+
+                    switch ($action['type']) {
+
+                    case 'fileinto':
+                        array_push($exts, 'fileinto');
+                        $action_script .= 'fileinto ';
+                        if ($action['copy']) {
+                            $action_script .= ':copy ';
+                            array_push($exts, 'copy');
+                        }
+                        $action_script .= self::escape_string($action['target']);
+                        break;
 
 
-                case 'fileinto':
-                    array_push($exts, 'fileinto');
-                    $script .= "\tfileinto ";
-                    if ($action['copy']) {
-                        $script .= ':copy ';
-                        array_push($exts, 'copy');
-                    }
-                    $script .= self::escape_string($action['target']) . ";\n";
-                    break;
+                    case 'redirect':
+                        $action_script .= 'redirect ';
+                        if ($action['copy']) {
+                            $action_script .= ':copy ';
+                            array_push($exts, 'copy');
+                        }
+                        $action_script .= self::escape_string($action['target']);
+                        break;
 
 
-                case 'redirect':
-                    $script .= "\tredirect ";
-                    if ($action['copy']) {
-                        $script .= ':copy ';
-                        array_push($exts, 'copy');
-                    }
-                    $script .= self::escape_string($action['target']) . ";\n";
-                    break;
+                    case 'reject':
+                    case 'ereject':
+                        array_push($exts, $action['type']);
+                        $action_script .= $action['type'].' '
+                            . self::escape_string($action['target']);
+                        break;
 
 
-                case 'reject':
-                case 'ereject':
-                    array_push($exts, $action['type']);
-                    $script .= "\t".$action['type']." "
-                        . self::escape_string($action['target']) . ";\n";
-                    break;
+                    case 'addflag':
+                    case 'setflag':
+                    case 'removeflag':
+                        if (in_array('imap4flags', $this->supported))
+                            array_push($exts, 'imap4flags');
+                        else
+                            array_push($exts, 'imapflags');
 
 
-                case 'addflag':
-                case 'setflag':
-                case 'removeflag':
-                    if (is_array($this->capabilities) && in_array('imap4flags', $this->capabilities))
-                        array_push($exts, 'imap4flags');
-                    else
-                        array_push($exts, 'imapflags');
+                        $action_script .= $action['type'].' '
+                            . self::escape_string($action['target']);
+                        break;
 
 
-                    $script .= "\t".$action['type']." "
-                        . self::escape_string($action['target']) . ";\n";
-                    break;
+                    case 'keep':
+                    case 'discard':
+                    case 'stop':
+                        $action_script .= $action['type'];
+                        break;
 
 
-                case 'keep':
-                case 'discard':
-                case 'stop':
-                    $script .= "\t" . $action['type'] .";\n";
-                    break;
+                    case 'include':
+                        array_push($exts, 'include');
+                        $action_script .= 'include ';
+                        foreach (array_diff(array_keys($action), array('target', 'type')) as $opt) {
+                            $action_script .= ":$opt ";
+                        }
+                        $action_script .= self::escape_string($action['target']);
+                        break;
 
 
-                case 'vacation':
-                    array_push($exts, 'vacation');
-                    $script .= "\tvacation";
-                    if (!empty($action['days']))
-                        $script .= " :days " . $action['days'];
-                    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";
-                    $script .= " " . self::escape_string($action['reason']) . ";\n";
-                    break;
+                    case 'set':
+                        array_push($exts, 'variables');
+                        $action_script .= 'set ';
+                        foreach (array_diff(array_keys($action), array('name', 'value', 'type')) as $opt) {
+                            $action_script .= ":$opt ";
+                        }
+                        $action_script .= self::escape_string($action['name']) . ' ' . self::escape_string($action['value']);
+                        break;
+
+                    case 'vacation':
+                        array_push($exts, 'vacation');
+                        $action_script .= 'vacation';
+                        if (!empty($action['days']))
+                            $action_script .= " :days " . $action['days'];
+                        if (!empty($action['addresses']))
+                            $action_script .= " :addresses " . self::escape_string($action['addresses']);
+                        if (!empty($action['subject']))
+                            $action_script .= " :subject " . self::escape_string($action['subject']);
+                        if (!empty($action['handle']))
+                            $action_script .= " :handle " . self::escape_string($action['handle']);
+                        if (!empty($action['from']))
+                            $action_script .= " :from " . self::escape_string($action['from']);
+                        if (!empty($action['mime']))
+                            $action_script .= " :mime";
+                        $action_script .= " " . self::escape_string($action['reason']);
+                        break;
+                    }
+
+                    if ($action_script) {
+                        $script .= !empty($tests) ? "\t" : '';
+                        $script .= $action_script . ";\n";
+                    }
                 }
             }
 
                 }
             }
 
-            $script .= "}\n";
-            $idx++;
+            if ($script) {
+                $output .= $script . (!empty($tests) ? "}\n" : '');
+                $idx++;
+            }
         }
 
         // requires
         if (!empty($exts))
         }
 
         // requires
         if (!empty($exts))
-            $script = 'require ["' . implode('","', array_unique($exts)) . "\"];\n" . $script;
+            $output = 'require ["' . implode('","', array_unique($exts)) . "\"];\n" . $output;
 
 
-        return $script;
+        if (!empty($this->prefix)) {
+            $output = $this->prefix . "\n\n" . $output;
+        }
+
+        return $output;
     }
 
     /**
     }
 
     /**
@@ -296,35 +474,89 @@ class rcube_sieve_script
      */
     private function _parse_text($script)
     {
      */
     private function _parse_text($script)
     {
-        $i = 0;
-        $content = array();
+        $prefix     = '';
+        $options = array();
+
+        while ($script) {
+            $script = trim($script);
+            $rule   = array();
+
+            // Comments
+            while (!empty($script) && $script[0] == '#') {
+                $endl = strpos($script, "\n");
+                $line = $endl ? substr($script, 0, $endl) : $script;
+
+                // Roundcube format
+                if (preg_match('/^# rule:\[(.*)\]/', $line, $matches)) {
+                    $rulename = $matches[1];
+                }
+                // KEP:14 variables
+                else if (preg_match('/^# (EDITOR|EDITOR_VERSION) (.+)$/', $line, $matches)) {
+                    $this->set_var($matches[1], $matches[2]);
+                }
+                // Horde-Ingo format
+                else if (!empty($options['format']) && $options['format'] == 'INGO'
+                    && preg_match('/^# (.*)/', $line, $matches)
+                ) {
+                    $rulename = $matches[1];
+                }
+                else if (empty($options['prefix'])) {
+                    $prefix .= $line . "\n";
+                }
+
+                $script = ltrim(substr($script, strlen($line) + 1));
+            }
+
+            // handle script header
+            if (empty($options['prefix'])) {
+                $options['prefix'] = true;
+                if ($prefix && strpos($prefix, 'horde.org/ingo')) {
+                    $options['format'] = 'INGO';
+                }
+            }
 
 
-        // tokenize rules
-        if ($tokens = preg_split('/(# rule:\[.*\])\r?\n/', $script, -1, PREG_SPLIT_DELIM_CAPTURE)) {
-            foreach($tokens as $token) {
-                if (preg_match('/^# rule:\[(.*)\]/', $token, $matches)) {
-                    $content[$i]['name'] = $matches[1];
+            // Control structures/blocks
+            if (preg_match('/^(if|else|elsif)/i', $script)) {
+                $rule = $this->_tokenize_rule($script);
+                if (strlen($rulename) && !empty($rule)) {
+                    $rule['name'] = $rulename;
                 }
                 }
-                else if (isset($content[$i]['name']) && sizeof($content[$i]) == 1) {
-                    if ($rule = $this->_tokenize_rule($token)) {
-                        $content[$i] = array_merge($content[$i], $rule);
-                        $i++;
+            }
+            // Simple commands
+            else {
+                $rule = $this->_parse_actions($script, ';');
+                if (!empty($rule[0]) && is_array($rule)) {
+                    // set "global" variables
+                    if ($rule[0]['type'] == 'set') {
+                        unset($rule[0]['type']);
+                        $this->vars[] = $rule[0];
+                    }
+                    else {
+                        $rule = array('actions' => $rule);
                     }
                     }
-                    else // unknown rule format
-                        unset($content[$i]);
                 }
             }
                 }
             }
+
+            $rulename = '';
+
+            if (!empty($rule)) {
+                $this->content[] = $rule;
+            }
         }
 
         }
 
-        return $content;
+        if (!empty($prefix)) {
+            $this->prefix = trim($prefix);
+        }
     }
 
     /**
      * Convert text script fragment to rule object
      *
      * @param string Text rule
     }
 
     /**
      * Convert text script fragment to rule object
      *
      * @param string Text rule
+     *
+     * @return array Rule data
      */
      */
-    private function _tokenize_rule($content)
+    private function _tokenize_rule(&$content)
     {
         $cond = strtolower(self::tokenize($content, 1));
 
     {
         $cond = strtolower(self::tokenize($content, 1));
 
@@ -389,7 +621,7 @@ class rcube_sieve_script
                 $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])) {
                 $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++;
+                        $header['comparator'] = $tokens[++$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('/^:(count|value)$/i', $tokens[$i])) {
                         $header['type'] = strtolower(substr($tokens[$i], 1)) . '-' . $tokens[++$i];
@@ -406,6 +638,52 @@ class rcube_sieve_script
                 $tests[] = $header;
                 break;
 
                 $tests[] = $header;
                 break;
 
+            case 'address':
+            case 'envelope':
+                $header = array('test' => $token, 'not' => $not, 'arg1' => '', 'arg2' => '');
+                for ($i=0, $len=count($tokens); $i<$len; $i++) {
+                    if (!is_array($tokens[$i]) && preg_match('/^:comparator$/i', $tokens[$i])) {
+                        $header['comparator'] = $tokens[++$i];
+                    }
+                    else if (!is_array($tokens[$i]) && preg_match('/^:(is|contains|matches|regex)$/i', $tokens[$i])) {
+                        $header['type'] = strtolower(substr($tokens[$i], 1));
+                    }
+                    else if (!is_array($tokens[$i]) && preg_match('/^:(localpart|domain|all|user|detail)$/i', $tokens[$i])) {
+                        $header['part'] = strtolower(substr($tokens[$i], 1));
+                    }
+                    else {
+                        $header['arg1'] = $header['arg2'];
+                        $header['arg2'] = $tokens[$i];
+                    }
+                }
+
+                $tests[] = $header;
+                break;
+
+            case 'body':
+                $header = array('test' => 'body', 'not' => $not, 'arg' => '');
+                for ($i=0, $len=count($tokens); $i<$len; $i++) {
+                    if (!is_array($tokens[$i]) && preg_match('/^:comparator$/i', $tokens[$i])) {
+                        $header['comparator'] = $tokens[++$i];
+                    }
+                    else if (!is_array($tokens[$i]) && preg_match('/^:(is|contains|matches|regex)$/i', $tokens[$i])) {
+                        $header['type'] = strtolower(substr($tokens[$i], 1));
+                    }
+                    else if (!is_array($tokens[$i]) && preg_match('/^:(raw|content|text)$/i', $tokens[$i])) {
+                        $header['part'] = strtolower(substr($tokens[$i], 1));
+
+                        if ($header['part'] == 'content') {
+                            $header['content'] = $tokens[++$i];
+                        }
+                    }
+                    else {
+                        $header['arg'] = $tokens[$i];
+                    }
+                }
+
+                $tests[] = $header;
+                break;
+
             case 'exists':
                 $tests[] = array('test' => 'exists', 'not'  => $not,
                     'arg'  => array_pop($tokens));
             case 'exists':
                 $tests[] = array('test' => 'exists', 'not'  => $not,
                     'arg'  => array_pop($tokens));
@@ -427,9 +705,7 @@ class rcube_sieve_script
         }
 
         // ...and actions block
         }
 
         // ...and actions block
-        if ($tests) {
-            $actions = $this->_parse_actions($content);
-        }
+        $actions = $this->_parse_actions($content);
 
         if ($tests && $actions) {
             $result = array(
 
         if ($tests && $actions) {
             $result = array(
@@ -447,10 +723,12 @@ class rcube_sieve_script
     /**
      * Parse body of actions section
      *
     /**
      * Parse body of actions section
      *
-     * @param string Text body
+     * @param string $content  Text body
+     * @param string $end      End of text separator
+     *
      * @return array Array of parsed action type/target pairs
      */
      * @return array Array of parsed action type/target pairs
      */
-    private function _parse_actions($content)
+    private function _parse_actions(&$content, $end = '}')
     {
         $result = null;
 
     {
         $result = null;
 
@@ -531,12 +809,72 @@ class rcube_sieve_script
                     'target' => $tokens[count($tokens)-1]
                 );
                 break;
                     'target' => $tokens[count($tokens)-1]
                 );
                 break;
+
+            case 'include':
+                $include = array('type' => 'include', 'target' => array_pop($tokens));
+
+                // Parameters: :once, :optional, :global, :personal
+                for ($i=0, $len=count($tokens); $i<$len; $i++) {
+                    $tok = strtolower($tokens[$i]);
+                    if ($tok[0] == ':') {
+                        $include[substr($tok, 1)] = true;
+                    }
+                }
+
+                $result[] = $include;
+                break;
+
+            case 'set':
+                $set = array('type' => 'set', 'value' => array_pop($tokens), 'name' => array_pop($tokens));
+
+                // Parameters: :lower :upper :lowerfirst :upperfirst :quotewildcard :length
+                for ($i=0, $len=count($tokens); $i<$len; $i++) {
+                    $tok = strtolower($tokens[$i]);
+                    if ($tok[0] == ':') {
+                        $set[substr($tok, 1)] = true;
+                    }
+                }
+
+                $result[] = $set;
+                break;
+
+            case 'require':
+                // skip, will be build according to used commands
+                // $result[] = array('type' => 'require', 'target' => $tokens);
+                break;
+
             }
             }
+
+            if ($separator == $end)
+                break;
         }
 
         return $result;
     }
 
         }
 
         return $result;
     }
 
+    /**
+     *
+     */
+    private function add_comparator($test, &$out, &$exts)
+    {
+        if (empty($test['comparator'])) {
+            return;
+        }
+
+        if ($test['comparator'] == 'i;ascii-numeric') {
+            array_push($exts, 'relational');
+            array_push($exts, 'comparator-i;ascii-numeric');
+        }
+        else if (!in_array($test['comparator'], array('i;octet', 'i;ascii-casemap'))) {
+            array_push($exts, 'comparator-' . $test['comparator']);
+        }
+
+        // skip default comparator
+        if ($test['comparator'] != 'i;ascii-casemap') {
+            $out .= ' :comparator ' . self::escape_string($test['comparator']);
+        }
+    }
+
     /**
      * Escape special chars into quoted string value or multi-line string
      * or list of strings
     /**
      * Escape special chars into quoted string value or multi-line string
      * or list of strings
@@ -595,7 +933,7 @@ class rcube_sieve_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 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 int    $in_list Enable to call recursively inside a list
      *
      * @return mixed Tokens array or string if $num=1
      */
      *
      * @return mixed Tokens array or string if $num=1
      */
@@ -654,7 +992,7 @@ class rcube_sieve_script
                 $str = substr($str, 1);
                 if ($num === true) {
                     $result[] = $sep;
                 $str = substr($str, 1);
                 if ($num === true) {
                     $result[] = $sep;
-                    break 2; 
+                    break 2;
                 }
                 break;
 
                 }
                 break;
 
@@ -684,7 +1022,7 @@ class rcube_sieve_script
             // String atom
             default:
                 // empty or one character
             // String atom
             default:
                 // empty or one character
-                if ($str === '') {
+                if ($str === '' || $str === null) {
                     break 2;
                 }
                 if (strlen($str) < 2) {
                     break 2;
                 }
                 if (strlen($str) < 2) {
index c0fe389f529732305b3af02243266c3600828a1d..1fcef1e362cb6b12fd6e2aa1e1dca3dc6e1fe950 100644 (file)
@@ -1,5 +1,20 @@
 <?php
 
 <?php
 
+/*
+ +-----------------------------------------------------------------------+
+ | localization/de_CH/labels.inc                                         |
+ |                                                                       |
+ | Language file of the Roundcube Webmail client                         |
+ | Copyright (C) 2011, The Roundcube Dev Team                            |
+ | Licensed under the GNU General Public License                         |
+ |                                                                       |
+ +-----------------------------------------------------------------------+
+ | Author: Thomas <Unknown>                                              |
+ +-----------------------------------------------------------------------+
+ @version : importgettext.sh 5558 2011-12-07 08:51:01Z thomasb $
+*/
+
+$labels = array();
 $labels['filters'] = 'Filter';
 $labels['managefilters'] = 'Verwalte eingehende Nachrichtenfilter';
 $labels['filtername'] = 'Filtername';
 $labels['filters'] = 'Filter';
 $labels['managefilters'] = 'Verwalte eingehende Nachrichtenfilter';
 $labels['filtername'] = 'Filtername';
@@ -17,12 +32,18 @@ $labels['filteris'] = 'ist gleich';
 $labels['filterisnot'] = 'ist ungleich';
 $labels['filterexists'] = 'ist vorhanden';
 $labels['filternotexists'] = 'nicht vorhanden';
 $labels['filterisnot'] = 'ist ungleich';
 $labels['filterexists'] = 'ist vorhanden';
 $labels['filternotexists'] = 'nicht vorhanden';
+$labels['filtermatches'] = 'entspricht Ausdruck';
+$labels['filternotmatches'] = 'entspricht nicht Ausdruck';
+$labels['filterregex'] = 'trifft regulären Ausdruck';
+$labels['filternotregex'] = 'entspricht regulärem Ausdruck';
 $labels['filterunder'] = 'unter';
 $labels['filterover'] = 'über';
 $labels['addrule'] = 'Regel hinzufügen';
 $labels['delrule'] = 'Regel löschen';
 $labels['messagemoveto'] = 'Verschiebe Nachricht nach';
 $labels['messageredirect'] = 'Leite Nachricht um nach';
 $labels['filterunder'] = 'unter';
 $labels['filterover'] = 'über';
 $labels['addrule'] = 'Regel hinzufügen';
 $labels['delrule'] = 'Regel löschen';
 $labels['messagemoveto'] = 'Verschiebe Nachricht nach';
 $labels['messageredirect'] = 'Leite Nachricht um nach';
+$labels['messagecopyto'] = 'Kopiere Nachricht nach';
+$labels['messagesendcopy'] = 'Sende Kopie an';
 $labels['messagereply'] = 'Antworte mit Nachricht';
 $labels['messagedelete'] = 'Nachricht löschen';
 $labels['messagediscard'] = 'Discard with message';
 $labels['messagereply'] = 'Antworte mit Nachricht';
 $labels['messagedelete'] = 'Nachricht löschen';
 $labels['messagediscard'] = 'Discard with message';
@@ -35,18 +56,64 @@ $labels['recipient'] = 'Empfänger';
 $labels['vacationaddresses'] = 'Zusätzliche Liste von Empfängern (Komma getrennt):';
 $labels['vacationdays'] = 'Antwort wird erneut gesendet nach (in Tagen):';
 $labels['vacationreason'] = 'Inhalt der Nachricht (Abwesenheitsgrund):';
 $labels['vacationaddresses'] = 'Zusätzliche Liste von Empfängern (Komma getrennt):';
 $labels['vacationdays'] = 'Antwort wird erneut gesendet nach (in Tagen):';
 $labels['vacationreason'] = 'Inhalt der Nachricht (Abwesenheitsgrund):';
+$labels['vacationsubject'] = 'Betreff';
 $labels['rulestop'] = 'Regelauswertung anhalten';
 $labels['rulestop'] = 'Regelauswertung anhalten';
+$labels['enable'] = 'Aktivieren/Deaktivieren';
+$labels['filterset'] = 'Filtersätze';
+$labels['filtersets'] = 'Filtersätze';
+$labels['filtersetadd'] = 'Filtersatz anlegen';
+$labels['filtersetdel'] = 'Aktuellen Filtersatz löschen';
+$labels['filtersetact'] = 'Aktuellen Filtersatz aktivieren';
+$labels['filtersetdeact'] = 'Aktuellen Filtersatz deaktivieren';
+$labels['filterdef'] = 'Filterdefinition';
+$labels['filtersetname'] = 'Filtersatzname';
+$labels['newfilterset'] = 'Neuer Filtersatz';
+$labels['active'] = 'aktiv';
+$labels['none'] = 'keine';
+$labels['fromset'] = 'aus Filtersatz';
+$labels['fromfile'] = 'aus Datei';
+$labels['filterdisabled'] = 'Filter deaktiviert';
+$labels['countisgreaterthan'] = 'Anzahl ist grösser als';
+$labels['countisgreaterthanequal'] = 'Anzahl ist gleich oder grösser als';
+$labels['countislessthan'] = 'Anzahl ist kleiner als';
+$labels['countislessthanequal'] = 'Anzahl ist gleich oder kleiner als';
+$labels['countequals'] = 'Anzahl ist gleich';
+$labels['countnotequals'] = 'Anzahl ist ungleich';
+$labels['valueisgreaterthan'] = 'Wert ist grösser als';
+$labels['valueisgreaterthanequal'] = 'Wert ist gleich oder grösser als';
+$labels['valueislessthan'] = 'Wert ist kleiner';
+$labels['valueislessthanequal'] = 'Wert ist gleich oder kleiner als';
+$labels['valueequals'] = 'Wert ist gleich';
+$labels['valuenotequals'] = 'Wert ist ungleich';
+$labels['setflags'] = 'Setze Markierungen';
+$labels['addflags'] = 'Füge Markierung hinzu';
+$labels['removeflags'] = 'Entferne Markierung';
+$labels['flagread'] = 'gelesen';
+$labels['flagdeleted'] = 'Gelöscht';
+$labels['flaganswered'] = 'Beantwortet';
+$labels['flagflagged'] = 'Markiert';
+$labels['flagdraft'] = 'Entwurf';
+$labels['filtercreate'] = 'Filter erstellen';
+$labels['usedata'] = 'Die folgenden Daten im Filter benutzen:';
+$labels['nextstep'] = 'Nächster Schritt';
+$labels['...'] = '';
+$labels['advancedopts'] = 'Erweiterte Optionen';
+$labels['body'] = 'Inhalt';
+$labels['address'] = 'Adresse';
+$labels['envelope'] = 'Umschlag';
+$labels['modifier'] = 'Wandler';
+$labels['text'] = 'Text';
+$labels['undecoded'] = 'kodiert (roh)';
+$labels['contenttype'] = 'Inhaltstyp';
+$labels['modtype'] = 'Typ:';
+$labels['allparts'] = 'alle';
+$labels['domain'] = 'Domain';
+$labels['localpart'] = 'lokaler Teil';
+$labels['user'] = 'Benutzer';
+$labels['detail'] = 'Detail';
+$labels['comparator'] = 'Komparator';
+$labels['default'] = 'Vorgabewert';
+$labels['octet'] = 'strikt (Oktet)';
+$labels['asciicasemap'] = 'Gross-/Kleinschreibung ignorieren';
+$labels['asciinumeric'] = 'numerisch (ascii-numeric)';
 
 
-$messages['filterunknownerror'] = 'Unbekannter Serverfehler';
-$messages['filterconnerror'] = 'Kann nicht zum Sieve-Server verbinden';
-$messages['filterdeleteerror'] = 'Fehler beim des löschen  Filters. Serverfehler';
-$messages['filterdeleted'] = 'Filter erfolgreich gelöscht';
-$messages['filterdeleteconfirm'] = 'Möchten Sie den Filter löschen ?';
-$messages['filtersaved'] = 'Filter gespeichert';
-$messages['filtersaveerror'] = 'Serverfehler, konnte den Filter nicht speichern.';
-$messages['ruledeleteconfirm'] = 'Sicher, dass Sie die Regel löschen wollen?';
-$messages['actiondeleteconfirm'] = 'Sicher, dass Sie die ausgewaehlte Aktion löschen wollen?';
-$messages['forbiddenchars'] = 'Unerlaubte Zeichen im Feld';
-$messages['cannotbeempty'] = 'Feld darf nicht leer sein';
-
-?>
index e71d7e00d6b9aa904595a5dcbdec65ec8b0f6a4b..d78220c619dcaf6b8cf63bb90cc08088f4c590fd 100644 (file)
@@ -1,9 +1,24 @@
 <?php
 
 <?php
 
+/*
+ +-----------------------------------------------------------------------+
+ | localization/de_DE/labels.inc                                         |
+ |                                                                       |
+ | Language file of the Roundcube Webmail client                         |
+ | Copyright (C) 2011, The Roundcube Dev Team                            |
+ | Licensed under the GNU General Public License                         |
+ |                                                                       |
+ +-----------------------------------------------------------------------+
+ | Author: Christoph Wickert <Unknown>                                   |
+ +-----------------------------------------------------------------------+
+ @version : importgettext.sh 5558 2011-12-07 08:51:01Z thomasb $
+*/
+
+$labels = array();
 $labels['filters'] = 'Filter';
 $labels['filters'] = 'Filter';
-$labels['managefilters'] = 'Posteingangs-Filter verwalten';
+$labels['managefilters'] = 'Filter für eingehende Nachrichten verwalten';
 $labels['filtername'] = 'Filtername';
 $labels['filtername'] = 'Filtername';
-$labels['newfilter'] = 'Filter anlegen';
+$labels['newfilter'] = 'Neuer Filter';
 $labels['filteradd'] = 'Filter hinzufügen';
 $labels['filterdel'] = 'Filter löschen';
 $labels['moveup'] = 'Nach oben';
 $labels['filteradd'] = 'Filter hinzufügen';
 $labels['filterdel'] = 'Filter löschen';
 $labels['moveup'] = 'Nach oben';
@@ -17,17 +32,21 @@ $labels['filteris'] = 'ist gleich';
 $labels['filterisnot'] = 'ist ungleich';
 $labels['filterexists'] = 'existiert';
 $labels['filternotexists'] = 'existiert nicht';
 $labels['filterisnot'] = 'ist ungleich';
 $labels['filterexists'] = 'existiert';
 $labels['filternotexists'] = 'existiert nicht';
+$labels['filtermatches'] = 'trifft auf Ausdruck zu';
+$labels['filternotmatches'] = 'trifft nicht auf Ausdruck zu';
+$labels['filterregex'] = 'trifft auf regulären Ausdruck zu';
+$labels['filternotregex'] = 'trifft nicht auf regulären Ausdruck zu';
 $labels['filterunder'] = 'unter';
 $labels['filterover'] = 'über';
 $labels['addrule'] = 'Regel hinzufügen';
 $labels['delrule'] = 'Regel löschen';
 $labels['filterunder'] = 'unter';
 $labels['filterover'] = 'über';
 $labels['addrule'] = 'Regel hinzufügen';
 $labels['delrule'] = 'Regel löschen';
-$labels['messagemoveto'] = 'Verschiebe Nachricht nach';
-$labels['messageredirect'] = 'Leite Nachricht um an';
-$labels['messagecopyto'] = 'Kopiere Nachricht nach';
-$labels['messagesendcopy'] = 'Sende Kopie an';
-$labels['messagereply'] = 'Antworte mit Nachricht';
-$labels['messagedelete'] = 'Lösche Nachricht';
-$labels['messagediscard'] = 'Weise ab mit Nachricht';
+$labels['messagemoveto'] = 'Nachricht verschieben nach';
+$labels['messageredirect'] = 'Nachricht umleiten an';
+$labels['messagecopyto'] = 'Nachricht kopieren nach';
+$labels['messagesendcopy'] = 'Kopie senden an';
+$labels['messagereply'] = 'Mit Nachricht antworten';
+$labels['messagedelete'] = 'Nachricht löschen';
+$labels['messagediscard'] = 'Abweisen mit Nachricht';
 $labels['messagesrules'] = 'Für eingehende Nachrichten:';
 $labels['messagesactions'] = '...führende folgende Aktionen aus:';
 $labels['add'] = 'Hinzufügen';
 $labels['messagesrules'] = 'Für eingehende Nachrichten:';
 $labels['messagesactions'] = '...führende folgende Aktionen aus:';
 $labels['add'] = 'Hinzufügen';
@@ -37,13 +56,15 @@ $labels['recipient'] = 'Empfänger';
 $labels['vacationaddresses'] = 'Zusätzliche Liste von E-Mail Empfängern (Komma getrennt):';
 $labels['vacationdays'] = 'Wie oft sollen Nachrichten gesendet werden (in Tagen):';
 $labels['vacationreason'] = 'Nachrichteninhalt (Abwesenheitsgrund):';
 $labels['vacationaddresses'] = 'Zusätzliche Liste von E-Mail Empfängern (Komma getrennt):';
 $labels['vacationdays'] = 'Wie oft sollen Nachrichten gesendet werden (in Tagen):';
 $labels['vacationreason'] = 'Nachrichteninhalt (Abwesenheitsgrund):';
+$labels['vacationsubject'] = 'Nachrichtenbetreff';
 $labels['rulestop'] = 'Regelauswertung anhalten';
 $labels['rulestop'] = 'Regelauswertung anhalten';
+$labels['enable'] = 'Aktivieren/Deaktivieren';
 $labels['filterset'] = 'Filtersätze';
 $labels['filterset'] = 'Filtersätze';
+$labels['filtersets'] = 'Filtersätze';
 $labels['filtersetadd'] = 'Filtersatz anlegen';
 $labels['filtersetdel'] = 'Aktuellen Filtersatz löschen';
 $labels['filtersetact'] = 'Aktuellen Filtersatz aktivieren';
 $labels['filtersetdeact'] = 'Aktuellen Filtersatz deaktivieren';
 $labels['filtersetadd'] = 'Filtersatz anlegen';
 $labels['filtersetdel'] = 'Aktuellen Filtersatz löschen';
 $labels['filtersetact'] = 'Aktuellen Filtersatz aktivieren';
 $labels['filtersetdeact'] = 'Aktuellen Filtersatz deaktivieren';
-$labels['filtersetget'] = 'Filtersatz im Textformat herunterladen';
 $labels['filterdef'] = 'Filterdefinition';
 $labels['filtersetname'] = 'Filtersatzname';
 $labels['newfilterset'] = 'Neuer Filtersatz';
 $labels['filterdef'] = 'Filterdefinition';
 $labels['filtersetname'] = 'Filtersatzname';
 $labels['newfilterset'] = 'Neuer Filtersatz';
@@ -64,29 +85,35 @@ $labels['valueislessthan'] = 'Wert ist kleiner';
 $labels['valueislessthanequal'] = 'Wert ist gleich oder kleiner als';
 $labels['valueequals'] = 'Wert ist gleich';
 $labels['valuenotequals'] = 'Wert ist ungleich';
 $labels['valueislessthanequal'] = 'Wert ist gleich oder kleiner als';
 $labels['valueequals'] = 'Wert ist gleich';
 $labels['valuenotequals'] = 'Wert ist ungleich';
+$labels['setflags'] = 'Markierung an der Nachricht setzen';
+$labels['addflags'] = 'Markierung zur Nachricht hinzufügen';
+$labels['removeflags'] = 'Markierungen von der Nachricht entfernen';
+$labels['flagread'] = 'Gelesen';
+$labels['flagdeleted'] = 'Gelöscht';
+$labels['flaganswered'] = 'Beantwortet';
+$labels['flagflagged'] = 'Markiert';
+$labels['flagdraft'] = 'Entwurf';
+$labels['filtercreate'] = 'Filter erstellen';
+$labels['usedata'] = 'Die folgenden Daten im Filter benutzen:';
+$labels['nextstep'] = 'Nächster Schritt';
+$labels['...'] = '...';
+$labels['advancedopts'] = 'Erweiterte Optionen';
+$labels['body'] = 'Textkörper';
+$labels['address'] = 'Adresse';
+$labels['envelope'] = 'Umschlag';
+$labels['modifier'] = 'Modifikator:';
+$labels['text'] = 'Text';
+$labels['undecoded'] = 'Nicht dekodiert';
+$labels['contenttype'] = 'Inhaltstyp';
+$labels['modtype'] = 'Typ:';
+$labels['allparts'] = 'Alle';
+$labels['domain'] = 'Domäne';
+$labels['localpart'] = 'lokaler Teil';
+$labels['user'] = 'Benutzer';
+$labels['detail'] = 'Detail';
+$labels['comparator'] = 'Komperator:';
+$labels['default'] = 'Vorgabewert';
+$labels['octet'] = 'strikt (Oktett)';
+$labels['asciicasemap'] = 'Groß-/Kleinschreibung ignorieren';
+$labels['asciinumeric'] = 'numerisch (ascii-numeric)';
 
 
-$messages = array();
-$messages['filterunknownerror'] = 'Unbekannter Serverfehler';
-$messages['filterconnerror'] = 'Kann keine Verbindung mit Managesieve-Server herstellen';
-$messages['filterdeleteerror'] = 'Fehler beim Löschen des Filters. Serverfehler';
-$messages['filterdeleted'] = 'Filter erfolgreich gelöscht';
-$messages['filtersaved'] = 'Filter erfolgreich gespeichert';
-$messages['filtersaveerror'] = 'Fehler beim Speichern des Filters. Serverfehler';
-$messages['filterdeleteconfirm'] = 'Möchten Sie den ausgewählten Filter wirklich löschen?';
-$messages['ruledeleteconfirm'] = 'Sind Sie sicher, dass Sie die ausgewählte Regel löschen möchten?';
-$messages['actiondeleteconfirm'] = 'Sind Sie sicher, dass Sie die ausgewählte Aktion löschen möchten?';
-$messages['forbiddenchars'] = 'Unzulässige Zeichen im Eingabefeld';
-$messages['cannotbeempty'] = 'Eingabefeld darf nicht leer sein';
-$messages['setactivateerror'] = 'Kann ausgewählten Filtersatz nicht aktivieren. Serverfehler';
-$messages['setdeactivateerror'] = 'Kann ausgewählten Filtersatz nicht deaktivieren. Serverfehler';
-$messages['setdeleteerror'] = 'Kann ausgewählten Filtersatz nicht löschen. Serverfehler';
-$messages['setactivated'] = 'Filtersatz wurde erfolgreich aktiviert';
-$messages['setdeactivated'] = 'Filtersatz wurde erfolgreich deaktiviert';
-$messages['setdeleted'] = 'Filtersatz wurde erfolgreich gelöscht';
-$messages['setdeleteconfirm'] = 'Sind Sie sicher, dass Sie den ausgewählten Filtersatz löschen möchten?';
-$messages['setcreateerror'] = 'Kann Filtersatz nicht erstellen. Serverfehler';
-$messages['setcreated'] = 'Filtersatz wurde erfolgreich erstellt';
-$messages['emptyname'] = 'Kann Filtersatz nicht erstellen. Kein Name vergeben';
-$messages['nametoolong'] = 'Kann Filtersatz nicht erstellen. Name zu lang'
-
-?>
index f08357ed9987922f606795ea379112504b77c6a0..94e0ba60c92381bc4521490ac77a4005de56d6a4 100644 (file)
@@ -43,12 +43,13 @@ $labels['vacationdays'] = 'How often send messages (in days):';
 $labels['vacationreason'] = 'Message body (vacation reason):';
 $labels['vacationsubject'] = 'Message subject:';
 $labels['rulestop'] = 'Stop evaluating rules';
 $labels['vacationreason'] = 'Message body (vacation reason):';
 $labels['vacationsubject'] = 'Message subject:';
 $labels['rulestop'] = 'Stop evaluating rules';
+$labels['enable'] = 'Enable/Disable';
 $labels['filterset'] = 'Filters set';
 $labels['filterset'] = 'Filters set';
+$labels['filtersets'] = 'Filter sets';
 $labels['filtersetadd'] = 'Add filters set';
 $labels['filtersetdel'] = 'Delete current filters set';
 $labels['filtersetact'] = 'Activate current filters set';
 $labels['filtersetdeact'] = 'Deactivate current filters set';
 $labels['filtersetadd'] = 'Add filters set';
 $labels['filtersetdel'] = 'Delete current filters set';
 $labels['filtersetact'] = 'Activate current filters set';
 $labels['filtersetdeact'] = 'Deactivate current filters set';
-$labels['filtersetget'] = 'Download filters set in text format';
 $labels['filterdef'] = 'Filter definition';
 $labels['filtersetname'] = 'Filters set name';
 $labels['newfilterset'] = 'New filters set';
 $labels['filterdef'] = 'Filter definition';
 $labels['filtersetname'] = 'Filters set name';
 $labels['newfilterset'] = 'New filters set';
@@ -77,29 +78,61 @@ $labels['flagdeleted'] = 'Deleted';
 $labels['flaganswered'] = 'Answered';
 $labels['flagflagged'] = 'Flagged';
 $labels['flagdraft'] = 'Draft';
 $labels['flaganswered'] = 'Answered';
 $labels['flagflagged'] = 'Flagged';
 $labels['flagdraft'] = 'Draft';
+$labels['filtercreate'] = 'Create filter';
+$labels['usedata'] = 'Use following data in the filter:';
+$labels['nextstep'] = 'Next Step';
+$labels['...'] = '...';
+$labels['advancedopts'] = 'Advanced options';
+$labels['body'] = 'Body';
+$labels['address'] = 'address';
+$labels['envelope'] = 'envelope';
+$labels['modifier'] = 'modifier:';
+$labels['text'] = 'text';
+$labels['undecoded'] = 'undecoded (raw)';
+$labels['contenttype'] = 'content type';
+$labels['modtype'] = 'type:';
+$labels['allparts'] = 'all';
+$labels['domain'] = 'domain';
+$labels['localpart'] = 'local part';
+$labels['user'] = 'user';
+$labels['detail'] = 'detail';
+$labels['comparator'] = 'comparator:';
+$labels['default'] = 'default';
+$labels['octet'] = 'strict (octet)';
+$labels['asciicasemap'] = 'case insensitive (ascii-casemap)';
+$labels['asciinumeric'] = 'numeric (ascii-numeric)';
 
 $messages = array();
 
 $messages = array();
-$messages['filterunknownerror'] = 'Unknown server error';
-$messages['filterconnerror'] = 'Unable to connect to managesieve server';
-$messages['filterdeleteerror'] = 'Unable to delete filter. Server error occured';
-$messages['filterdeleted'] = 'Filter deleted successfully';
-$messages['filtersaved'] = 'Filter saved successfully';
-$messages['filtersaveerror'] = 'Unable to save filter. Server error occured';
+$messages['filterunknownerror'] = 'Unknown server error.';
+$messages['filterconnerror'] = 'Unable to connect to server.';
+$messages['filterdeleteerror'] = 'Unable to delete filter. Server error occured.';
+$messages['filterdeleted'] = 'Filter deleted successfully.';
+$messages['filtersaved'] = 'Filter saved successfully.';
+$messages['filtersaveerror'] = 'Unable to save filter. Server error occured.';
 $messages['filterdeleteconfirm'] = 'Do you really want to delete selected filter?';
 $messages['ruledeleteconfirm'] = 'Are you sure, you want to delete selected rule?';
 $messages['actiondeleteconfirm'] = 'Are you sure, you want to delete selected action?';
 $messages['filterdeleteconfirm'] = 'Do you really want to delete selected filter?';
 $messages['ruledeleteconfirm'] = 'Are you sure, you want to delete selected rule?';
 $messages['actiondeleteconfirm'] = 'Are you sure, you want to delete selected action?';
-$messages['forbiddenchars'] = 'Forbidden characters in field';
-$messages['cannotbeempty'] = 'Field cannot be empty';
-$messages['setactivateerror'] = 'Unable to activate selected filters set. Server error occured';
-$messages['setdeactivateerror'] = 'Unable to deactivate selected filters set. Server error occured';
-$messages['setdeleteerror'] = 'Unable to delete selected filters set. Server error occured';
-$messages['setactivated'] = 'Filters set activated successfully';
-$messages['setdeactivated'] = 'Filters set deactivated successfully';
-$messages['setdeleted'] = 'Filters set deleted successfully';
+$messages['forbiddenchars'] = 'Forbidden characters in field.';
+$messages['cannotbeempty'] = 'Field cannot be empty.';
+$messages['ruleexist'] = 'Filter with specified name already exists.';
+$messages['setactivateerror'] = 'Unable to activate selected filters set. Server error occured.';
+$messages['setdeactivateerror'] = 'Unable to deactivate selected filters set. Server error occured.';
+$messages['setdeleteerror'] = 'Unable to delete selected filters set. Server error occured.';
+$messages['setactivated'] = 'Filters set activated successfully.';
+$messages['setdeactivated'] = 'Filters set deactivated successfully.';
+$messages['setdeleted'] = 'Filters set deleted successfully.';
 $messages['setdeleteconfirm'] = 'Are you sure, you want to delete selected filters set?';
 $messages['setdeleteconfirm'] = 'Are you sure, you want to delete selected filters set?';
-$messages['setcreateerror'] = 'Unable to create filters set. Server error occured';
-$messages['setcreated'] = 'Filters set created successfully';
-$messages['emptyname'] = 'Unable to create filters set. Empty set name';
-$messages['nametoolong'] = 'Unable to create filters set. Name too long'
+$messages['setcreateerror'] = 'Unable to create filters set. Server error occured.';
+$messages['setcreated'] = 'Filters set created successfully.';
+$messages['activateerror'] = 'Unable to enable selected filter(s). Server error occured.';
+$messages['deactivateerror'] = 'Unable to disable selected filter(s). Server error occured.';
+$messages['activated'] = 'Filter(s) disabled successfully.';
+$messages['deactivated'] = 'Filter(s) enabled successfully.';
+$messages['moved'] = 'Filter moved successfully.';
+$messages['moveerror'] = 'Unable to move selected filter. Server error occured.';
+$messages['nametoolong'] = 'Name too long.';
+$messages['namereserved'] = 'Reserved name.';
+$messages['setexist'] = 'Set already exists.';
+$messages['nodata'] = 'At least one position must be selected!';
 
 ?>
 
 ?>
index 1dad18d991f7e58eb5072e575b60713bbd9c48d7..b6dbf166b0f871da9334b4be5af381c750919257 100644 (file)
@@ -53,6 +53,31 @@ $labels['none'] = 'ninguno';
 $labels['fromset'] = 'de conjunto ';
 $labels['fromfile'] = 'de archivo';
 $labels['filterdisabled'] = 'Filtro desactivado';
 $labels['fromset'] = 'de conjunto ';
 $labels['fromfile'] = 'de archivo';
 $labels['filterdisabled'] = 'Filtro desactivado';
+$labels['filtermatches'] = 'coincide con la expresión';
+$labels['filternotmatches'] = 'no coincide con la expresión';
+$labels['filterregex'] = 'coincide con la expresión regular';
+$labels['filternotregex'] = 'no coincide con la expresión regular';
+$labels['vacationsubject'] = 'Asunto del Mensaje:';
+$labels['countisgreaterthan'] = 'contiene más que';
+$labels['countisgreaterthanequal'] = 'contiene más o igual que';
+$labels['countislessthan'] = 'contiene menos que';
+$labels['countislessthanequal'] = 'contiene menos o igual que';
+$labels['countequals'] = 'contiene igual que';
+$labels['countnotequals'] = 'contiene distinto que';
+$labels['valueisgreaterthan'] = 'el valor es mayor que';
+$labels['valueisgreaterthanequal'] = 'el valor es mayor o igual que';
+$labels['valueislessthan'] = 'el valor es menor que';
+$labels['valueislessthanequal'] = 'el valor es menor o igual que';
+$labels['valueequals'] = 'el valor es igual que';
+$labels['valuenotequals'] = 'el valor es distinto que';
+$labels['setflags'] = 'Etiquetar el mensaje';
+$labels['addflags'] = 'Agregar etiqueta al mensaje';
+$labels['removeflags'] = 'Eliminar etiquetas al mensaje';
+$labels['flagread'] = 'Leido';
+$labels['flagdeleted'] = 'Eliminado';
+$labels['flaganswered'] = 'Respondido';
+$labels['flagflagged'] = 'Marcado';
+$labels['flagdraft'] = 'Borrador';
 
 $messages = array();
 $messages['filterunknownerror'] = 'Error desconocido de servidor';
 
 $messages = array();
 $messages['filterunknownerror'] = 'Error desconocido de servidor';
@@ -76,6 +101,7 @@ $messages['setdeleteconfirm'] = '¿Está seguro de que desea borrar el conjunto
 $messages['setcreateerror'] = 'Imposible crear el conjunto de filtros. Ha ocurrido un error en el servidor';
 $messages['setcreated'] = 'Conjunto de filtros creado satisfactoriamente';
 $messages['emptyname'] = 'Imposible crear el conjunto de filtros. Sin nombre';
 $messages['setcreateerror'] = 'Imposible crear el conjunto de filtros. Ha ocurrido un error en el servidor';
 $messages['setcreated'] = 'Conjunto de filtros creado satisfactoriamente';
 $messages['emptyname'] = 'Imposible crear el conjunto de filtros. Sin nombre';
-$messages['nametoolong'] = 'Imposible crear el conjunto de filtros. Nombre demasiado largo'
+$messages['nametoolong'] = 'Imposible crear el conjunto de filtros. Nombre demasiado largo';
+$messages['setdeactivateerror'] = 'Imposible desactivar el conjunto de filtros seleccionado. Ha ocurrido un error en el servidor';
 
 ?>
 
 ?>
diff --git a/plugins/managesieve/localization/lv_LV.inc b/plugins/managesieve/localization/lv_LV.inc
new file mode 100644 (file)
index 0000000..b394588
--- /dev/null
@@ -0,0 +1,92 @@
+<?php
+
+$labels['filters'] = 'Vēstuļu filtri';
+$labels['managefilters'] = 'Rediģēt ienākošo vēstuļu filtrus';
+$labels['filtername'] = 'Filtra nosaukums';
+$labels['newfilter'] = 'Jauns filtrs';
+$labels['filteradd'] = 'Pievienot filtru';
+$labels['filterdel'] = 'Izdzēst filtru';
+$labels['moveup'] = 'Pārvietot augšup';
+$labels['movedown'] = 'Pārvietot lejup';
+$labels['filterallof'] = 'jāatbilst visiem no sekojošiem nosacījumiem';
+$labels['filteranyof'] = 'jāatbilst jebkuram no sekojošiem nosacījumiem';
+$labels['filterany'] = 'visām vēstulēm';
+$labels['filtercontains'] = 'satur';
+$labels['filternotcontains'] = 'nesatur';
+$labels['filteris'] = 'ir vienāds ar';
+$labels['filterisnot'] = 'nav vienāds ar';
+$labels['filterexists'] = 'eksistē';
+$labels['filternotexists'] = 'neeksistē';
+$labels['filterunder'] = 'zem';
+$labels['filterover'] = 'virs';
+$labels['addrule'] = 'Pievienot nosacījumu';
+$labels['delrule'] = 'Izdzēst nosacījumu';
+$labels['messagemoveto'] = 'Pārvietot vēstuli uz';
+$labels['messageredirect'] = 'Pāradresēt vēstuli uz';
+$labels['messagecopyto'] = 'Pārkopēt vēstuli uz';
+$labels['messagesendcopy'] = 'Pārsūtīt vēstules kopiju uz';
+$labels['messagereply'] = 'Automātiski atbildēt';
+$labels['messagedelete'] = 'Izdzēst vēstuli';
+$labels['messagediscard'] = 'Izdzēst vēstuli un atbildēt';
+$labels['messagesrules'] = 'Ienākošajām vēstulēm:';
+$labels['messagesactions'] = 'Izpildīt sekojošās darbības:';
+$labels['add'] = 'Pievienot';
+$labels['del'] = 'Dzēst';
+$labels['sender'] = 'Sūtītājs';
+$labels['recipient'] = 'Saņēmējs';
+$labels['vacationaddresses'] = 'Ievadiet savu(s) e-pastu(s) caur komatu:';
+$labels['vacationdays'] = 'Cik dienu laikā vienam un tam pašam sūtītājam neatbildēt atkārtoti (piem., 7):';
+$labels['vacationreason'] = 'Atvaļinājuma vēstules teksts:';
+$labels['rulestop'] = 'Apturēt nosacījumu pārbaudi';
+$labels['filterset'] = 'Filtru kopa';
+$labels['filtersetadd'] = 'Pievienot filtru kopu';
+$labels['filtersetdel'] = 'Izdzēst pašreizējo filtru kopu';
+$labels['filtersetact'] = 'Aktivizēt pašreizējo filtru kopu';
+$labels['filtersetdeact'] = 'Deaktivizēt pašreizējo filtru kopu';
+$labels['filtersetget'] = 'Lejupielādēt filtru kopu teksta formātā';
+$labels['filterdef'] = 'Filtra apraksts';
+$labels['filtersetname'] = 'Filtru kopas nosaukums';
+$labels['newfilterset'] = 'Jauna filtru kopa';
+$labels['active'] = 'aktīvs';
+$labels['none'] = 'nav';
+$labels['fromset'] = 'no kopas';
+$labels['fromfile'] = 'no faila';
+$labels['filterdisabled'] = 'Filtrs atslēgts';
+$labels['countisgreaterthan'] = 'skaits ir lielāks nekā';
+$labels['countisgreaterthanequal'] = 'skaits ir vienāds vai lielāks nekā';
+$labels['countislessthan'] = 'skaits ir mazāks nekā';
+$labels['countislessthanequal'] = 'skaits ir vienāds vai mazāks nekā';
+$labels['countequals'] = 'skaits ir vienāds ar';
+$labels['countnotequals'] = 'skaits nav vienāds ar';
+$labels['valueisgreaterthan'] = 'vērtība ir lielāka nekā';
+$labels['valueisgreaterthanequal'] = 'vērtība ir vienāda vai lielāka nekā';
+$labels['valueislessthan'] = 'vērtība ir mazāka nekā';
+$labels['valueislessthanequal'] = 'vērtība ir vienāda vai mazāka nekā';
+$labels['valueequals'] = 'vērtība ir vienāda ar';
+$labels['valuenotequals'] = 'vērtība nav vienāda ar';
+
+$messages = array();
+$messages['filterunknownerror'] = 'Nezināma servera kļūda';
+$messages['filterconnerror'] = 'Neizdevās pieslēgties ManageSieve serverim';
+$messages['filterdeleteerror'] = 'Neizdevās dzēst filtru. Servera iekšējā kļūda';
+$messages['filterdeleted'] = 'Filtrs veiksmīgi izdzēsts';
+$messages['filtersaved'] = 'Filtrs veiksmīgi saglabāts';
+$messages['filtersaveerror'] = 'Neizdevās saglabāt filtru. Servera iekšējā kļūda';
+$messages['filterdeleteconfirm'] = 'Vai tiešām vēlaties dzēst atzīmēto filtru?';
+$messages['ruledeleteconfirm'] = 'Vai tiešām vēlaties dzēst atzīmēto nosacījumu?';
+$messages['actiondeleteconfirm'] = 'Vai tiešām vēlaties dzēst atzīmēto darbību?';
+$messages['forbiddenchars'] = 'Lauks satur aizliegtus simbolus';
+$messages['cannotbeempty'] = 'Lauks nedrīkst būt tukšs';
+$messages['setactivateerror'] = 'Neizdevās aktivizēt atzīmēto filtru kopu. Servera iekšējā kļūda';
+$messages['setdeactivateerror'] = 'Neizdevās deaktivizēt atzīmēto filtru kopu. Servera iekšējā kļūda';
+$messages['setdeleteerror'] = 'Neizdevās izdzēst atzīmēto filtru kopu. Servera iekšējā kļūda';
+$messages['setactivated'] = 'Filtru kopa veiksmīgi aktivizēta';
+$messages['setdeactivated'] = 'Filtru kopa veiksmīgi deaktivizēta';
+$messages['setdeleted'] = 'Filtru kopa veiksmīgi izdzēsta';
+$messages['setdeleteconfirm'] = 'Vai tiešām vēlaties dzēst atzīmēto filtru kopu?';
+$messages['setcreateerror'] = 'Neizdevās izveidot filtru kopu. Servera iekšējā kļūda';
+$messages['setcreated'] = 'Filtru kopa veiksmīgi izveidota';
+$messages['emptyname'] = 'Neizdevās izveidot filtru kopu. Nav ievadīts kopas nosaukums';
+$messages['nametoolong'] = 'Neizdevās izveidot filtru kopu. Pārāk garš kopas nosaukums'
+
+?>
index 290dd1a46042660bcbf40a7495df2301c86f4849..c0ec2ede2bb2aae70f4cb6d8d8fc25de8ed1ecc0 100644 (file)
@@ -7,8 +7,8 @@ $labels['filtername'] = 'Nazwa filtru';
 $labels['newfilter'] = 'Nowy filtr';
 $labels['filteradd'] = 'Dodaj filtr';
 $labels['filterdel'] = 'Usuń filtr';
 $labels['newfilter'] = 'Nowy filtr';
 $labels['filteradd'] = 'Dodaj filtr';
 $labels['filterdel'] = 'Usuń filtr';
-$labels['moveup'] = 'Przenieś wyżej';
-$labels['movedown'] = 'Przenieś niżej';
+$labels['enable'] = 'Włącz/Wyłącz';
+$labels['filtersets'] = 'Zbiory fitrów';
 $labels['filterallof'] = 'spełniających wszystkie poniższe kryteria';
 $labels['filteranyof'] = 'spełniających dowolne z poniższych kryteriów';
 $labels['filterany'] = 'wszystkich';
 $labels['filterallof'] = 'spełniających wszystkie poniższe kryteria';
 $labels['filteranyof'] = 'spełniających dowolne z poniższych kryteriów';
 $labels['filterany'] = 'wszystkich';
@@ -49,7 +49,6 @@ $labels['filtersetadd'] = 'Dodaj zbiór filtrów';
 $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['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';
 $labels['filterdef'] = 'Definicja filtra';
 $labels['filtersetname'] = 'Nazwa zbioru';
 $labels['newfilterset'] = 'Nowy zbiór filtrów';
@@ -78,29 +77,61 @@ $labels['flagdeleted'] = 'Usunięta';
 $labels['flaganswered'] = 'Z odpowiedzią';
 $labels['flagflagged'] = 'Oflagowana';
 $labels['flagdraft'] = 'Szkic';
 $labels['flaganswered'] = 'Z odpowiedzią';
 $labels['flagflagged'] = 'Oflagowana';
 $labels['flagdraft'] = 'Szkic';
+$labels['filtercreate'] = 'Utwóż filtr';
+$labels['usedata'] = 'Użyj następujących danych do utworzenia filtra:';
+$labels['nextstep'] = 'Następny krok';
+$labels['...'] = '...';
+$labels['advancedopts'] = 'Zaawansowane opcje';
+$labels['body'] = 'Treść';
+$labels['address'] = 'adres';
+$labels['envelope'] = 'koperta (envelope)';
+$labels['modifier'] = 'modyfikator:';
+$labels['text'] = 'tekst';
+$labels['undecoded'] = 'nie (raw)';
+$labels['contenttype'] = 'typ części (content type)';
+$labels['modtype'] = 'typ:';
+$labels['allparts'] = 'wszystkie';
+$labels['domain'] = 'domena';
+$labels['localpart'] = 'część lokalna';
+$labels['user'] = 'użytkownik';
+$labels['detail'] = 'detal';
+$labels['comparator'] = 'komparator:';
+$labels['default'] = 'domyślny';
+$labels['octet'] = 'dokładny (octet)';
+$labels['asciicasemap'] = 'nierozróżniający wielkości liter (ascii-casemap)';
+$labels['asciinumeric'] = 'numeryczny (ascii-numeric)';
 
 $messages = array();
 
 $messages = array();
-$messages['filterunknownerror'] = 'Nieznany błąd serwera';
-$messages['filterconnerror'] = 'Nie można nawiązać połączenia z serwerem managesieve';
-$messages['filterdeleteerror'] = 'Nie można usunąć filtra. Wystąpił błąd serwera';
-$messages['filterdeleted'] = 'Filtr został usunięty pomyślnie';
+$messages['filterunknownerror'] = 'Nieznany błąd serwera.';
+$messages['filterconnerror'] = 'Nie można nawiązać połączenia z serwerem.';
+$messages['filterdeleteerror'] = 'Nie można usunąć filtra. Błąd serwera.';
+$messages['filterdeleted'] = 'Filtr został usunięty pomyślnie.';
 $messages['filterdeleteconfirm'] = 'Czy na pewno chcesz usunąć wybrany filtr?';
 $messages['filterdeleteconfirm'] = 'Czy na pewno chcesz usunąć wybrany filtr?';
-$messages['filtersaved'] = 'Filtr został zapisany pomyślnie';
+$messages['filtersaved'] = 'Filtr został zapisany pomyślnie.';
 $messages['filtersaveerror'] = 'Nie można zapisać filtra. Wystąpił błąd serwera.';
 $messages['ruledeleteconfirm'] = 'Czy na pewno chcesz usunąć wybraną regułę?';
 $messages['actiondeleteconfirm'] = 'Czy na pewno usunąć wybraną akcję?';
 $messages['filtersaveerror'] = 'Nie można zapisać filtra. Wystąpił błąd serwera.';
 $messages['ruledeleteconfirm'] = 'Czy na pewno chcesz usunąć wybraną regułę?';
 $messages['actiondeleteconfirm'] = 'Czy na pewno usunąć wybraną akcję?';
-$messages['forbiddenchars'] = 'Pole zawiera niedozwolone znaki';
-$messages['cannotbeempty'] = 'Pole nie może być puste';
-$messages['setactivateerror'] = 'Nie można aktywować wybranego zbioru filtrów. Błąd serwera';
-$messages['setdeactivateerror'] = 'Nie można deaktywować wybranego zbioru filtrów. Błąd serwera';
-$messages['setdeleteerror'] = 'Nie można usunąć wybranego zbioru filtrów. Błąd serwera';
-$messages['setactivated'] = 'Zbiór filtrów został aktywowany pomyślnie';
-$messages['setdeactivated'] = 'Zbiór filtrów został deaktywowany pomyślnie';
-$messages['setdeleted'] = 'Zbiór filtrów został usunięty pomyślnie';
+$messages['forbiddenchars'] = 'Pole zawiera niedozwolone znaki.';
+$messages['cannotbeempty'] = 'Pole nie może być puste.';
+$messages['setactivateerror'] = 'Nie można aktywować wybranego zbioru filtrów. Błąd serwera.';
+$messages['setdeactivateerror'] = 'Nie można deaktywować wybranego zbioru filtrów. Błąd serwera.';
+$messages['setdeleteerror'] = 'Nie można usunąć wybranego zbioru filtrów. Błąd serwera.';
+$messages['setactivated'] = 'Zbiór filtrów został aktywowany pomyślnie.';
+$messages['setdeactivated'] = 'Zbiór filtrów został deaktywowany pomyślnie.';
+$messages['setdeleted'] = 'Zbiór filtrów został usunięty pomyślnie.';
 $messages['setdeleteconfirm'] = 'Czy na pewno chcesz usunąć wybrany zbiór filtrów?';
 $messages['setdeleteconfirm'] = 'Czy na pewno chcesz usunąć wybrany zbiór filtrów?';
-$messages['setcreateerror'] = 'Nie można utworzyć zbioru filtrów. Błąd serwera';
-$messages['setcreated'] = 'Zbiór filtrów został utworzony pomyślnie';
-$messages['emptyname'] = 'Nie można utworzyć zbioru filtrów. Pusta nazwa zbioru';
-$messages['nametoolong'] = 'Nie można utworzyć zbioru filtrów. Nazwa zbyt długa'
+$messages['setcreateerror'] = 'Nie można utworzyć zbioru filtrów. Błąd serwera.';
+$messages['setcreated'] = 'Zbiór filtrów został utworzony pomyślnie.';
+$messages['nodata'] = 'Należy wybrać co najmniej jedną pozycję!';
+$messages['ruleexist'] = 'Filtr o podanej nazwie już istnieje.';
+$messages['activateerror'] = 'Nie można włączyć wybranych filtrów. Błąd serwera.';
+$messages['deactivateerror'] = 'Nie można wyłączyć wybranych filtrów. Błąd serwera.';
+$messages['activated'] = 'Filtr(y) wyłączono pomyślnie.';
+$messages['deactivated'] = 'Filtr(y) włączono pomyślnie.';
+$messages['moved'] = 'Filter został przeniesiony pomyślnie.';
+$messages['moveerror'] = 'Nie można przenieść wybranego filtra. Błąd serwera.';
+$messages['nametoolong'] = 'Zbyt długa nazwa.';
+$messages['namereserved'] = 'Nazwa zarezerwowana.';
+$messages['setexist'] = 'Zbiór już istnieje.';
 
 ?>
 
 ?>
index b48774e97ee62f82f05e5afa8d31eb40e07e4dc4..af3f05add501ebbcdd107a0091d4c0671ebba225 100644 (file)
@@ -32,7 +32,7 @@ $labels['add'] = 'Adicionar';
 $labels['del'] = 'Excluir';
 $labels['sender'] = 'Remetente';
 $labels['recipient'] = 'Destinatário';
 $labels['del'] = 'Excluir';
 $labels['sender'] = 'Remetente';
 $labels['recipient'] = 'Destinatário';
-$labels['vacationaddresses'] = 'Lista adicional de e-mails de remetente (separado por vírgula):';
+$labels['vacationaddresses'] = 'Lista adicional de e-mails destinatários (separado por vírgula):';
 $labels['vacationdays'] = 'Enviar mensagens com que frequência (em dias):';
 $labels['vacationreason'] = 'Corpo da mensagem (motivo de férias):';
 $labels['rulestop'] = 'Parar de avaliar regras';
 $labels['vacationdays'] = 'Enviar mensagens com que frequência (em dias):';
 $labels['vacationreason'] = 'Corpo da mensagem (motivo de férias):';
 $labels['rulestop'] = 'Parar de avaliar regras';
index ec6247aff8c203a12d99bf146a7316390fe3d630..a8bfaf203c5047a832b8febf4c206abbad23ea9d 100644 (file)
@@ -1,56 +1,97 @@
-/* Sieve Filters (tab) */
+/* (Manage)Sieve Filters */
 
 if (window.rcmail) {
   rcmail.addEventListener('init', function(evt) {
 
 if (window.rcmail) {
   rcmail.addEventListener('init', function(evt) {
+    // add managesieve-create command to message_commands array,
+    // so it's state will be updated on message selection/unselection
+    if (rcmail.env.task == 'mail') {
+      if (rcmail.env.action != 'show')
+        rcmail.env.message_commands.push('managesieve-create');
+      else
+        rcmail.enable_command('managesieve-create', true);
+    }
+    else {
+      var tab = $('<span>').attr('id', 'settingstabpluginmanagesieve').addClass('tablink'),
+        button = $('<a>').attr('href', rcmail.env.comm_path+'&_action=plugin.managesieve')
+          .attr('title', rcmail.gettext('managesieve.managefilters'))
+          .html(rcmail.gettext('managesieve.filters'))
+          .appendTo(tab);
+
+      // add tab
+      rcmail.add_element(tab, 'tabs');
+    }
+
+    if (rcmail.env.task == 'mail' || rcmail.env.action.indexOf('plugin.managesieve') != -1) {
+      // Create layer for form tips
+      if (!rcmail.env.framed) {
+        rcmail.env.ms_tip_layer = $('<div id="managesieve-tip" class="popupmenu"></div>');
+        rcmail.env.ms_tip_layer.appendTo(document.body);
+      }
+    }
 
 
-    var tab = $('<span>').attr('id', 'settingstabpluginmanagesieve').addClass('tablink');
-    var button = $('<a>').attr('href', rcmail.env.comm_path+'&_action=plugin.managesieve')
-      .attr('title', rcmail.gettext('managesieve.managefilters'))
-      .html(rcmail.gettext('managesieve.filters'))
-      .appendTo(tab);
-
-    // add button and register commands
-    rcmail.add_element(tab, 'tabs');
-    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);
-    rcmail.register_command('plugin.managesieve-up', function() { rcmail.managesieve_up() }, true);
-    rcmail.register_command('plugin.managesieve-down', function() { rcmail.managesieve_down() }, true);
-    rcmail.register_command('plugin.managesieve-set', function() { rcmail.managesieve_set() }, true);
-    rcmail.register_command('plugin.managesieve-setadd', function() { rcmail.managesieve_setadd() }, true);
-    rcmail.register_command('plugin.managesieve-setdel', function() { rcmail.managesieve_setdel() }, true);
-    rcmail.register_command('plugin.managesieve-setact', function() { rcmail.managesieve_setact() }, true);
-    rcmail.register_command('plugin.managesieve-setget', function() { rcmail.managesieve_setget() }, true);
-
-    if (rcmail.env.action == 'plugin.managesieve') {
+    // register commands
+    rcmail.register_command('plugin.managesieve-save', function() { rcmail.managesieve_save() });
+    rcmail.register_command('plugin.managesieve-act', function() { rcmail.managesieve_act() });
+    rcmail.register_command('plugin.managesieve-add', function() { rcmail.managesieve_add() });
+    rcmail.register_command('plugin.managesieve-del', function() { rcmail.managesieve_del() });
+    rcmail.register_command('plugin.managesieve-move', function() { rcmail.managesieve_move() });
+    rcmail.register_command('plugin.managesieve-setadd', function() { rcmail.managesieve_setadd() });
+    rcmail.register_command('plugin.managesieve-setdel', function() { rcmail.managesieve_setdel() });
+    rcmail.register_command('plugin.managesieve-setact', function() { rcmail.managesieve_setact() });
+    rcmail.register_command('plugin.managesieve-setget', function() { rcmail.managesieve_setget() });
+
+    if (rcmail.env.action == 'plugin.managesieve' || rcmail.env.action == 'plugin.managesieve-save') {
       if (rcmail.gui_objects.sieveform) {
         rcmail.enable_command('plugin.managesieve-save', true);
       if (rcmail.gui_objects.sieveform) {
         rcmail.enable_command('plugin.managesieve-save', true);
+
+        // small resize for header element
+        $('select[name="_header[]"]', rcmail.gui_objects.sieveform).each(function() {
+          if (this.value == '...') this.style.width = '40px';
+        });
+
+        // resize dialog window
+        if (rcmail.env.action == 'plugin.managesieve' && rcmail.env.task == 'mail') {
+          parent.rcmail.managesieve_dialog_resize(rcmail.gui_objects.sieveform);
+        }
+
+        $('input[type="text"]:first', rcmail.gui_objects.sieveform).focus();
       }
       else {
       }
       else {
-        rcmail.enable_command('plugin.managesieve-del', 'plugin.managesieve-up',
-          'plugin.managesieve-down', false);
         rcmail.enable_command('plugin.managesieve-add', 'plugin.managesieve-setadd', !rcmail.env.sieveconnerror);
       }
 
         rcmail.enable_command('plugin.managesieve-add', 'plugin.managesieve-setadd', !rcmail.env.sieveconnerror);
       }
 
-      // Create layer for form tips
-      if (!rcmail.env.framed) {
-        rcmail.env.ms_tip_layer = $('<div id="managesieve-tip" class="popupmenu"></div>');
-        rcmail.env.ms_tip_layer.appendTo(document.body);
-      }
+      var i, p = rcmail, setcnt, set = rcmail.env.currentset;
 
       if (rcmail.gui_objects.filterslist) {
 
       if (rcmail.gui_objects.filterslist) {
-        var p = rcmail;
-        rcmail.filters_list = new rcube_list_widget(rcmail.gui_objects.filterslist, {multiselect:false, draggable:false, keyboard:false});
+        rcmail.filters_list = new rcube_list_widget(rcmail.gui_objects.filterslist,
+          {multiselect:false, draggable:true, keyboard:false});
         rcmail.filters_list.addEventListener('select', function(o){ p.managesieve_select(o); });
         rcmail.filters_list.addEventListener('select', function(o){ p.managesieve_select(o); });
+        rcmail.filters_list.addEventListener('dragstart', function(o){ p.managesieve_dragstart(o); });
+        rcmail.filters_list.addEventListener('dragend', function(e){ p.managesieve_dragend(e); });
+        rcmail.filters_list.row_init = function (row) {
+          row.obj.onmouseover = function() { p.managesieve_focus_filter(row); };
+          row.obj.onmouseout = function() { p.managesieve_unfocus_filter(row); };
+        };
         rcmail.filters_list.init();
         rcmail.filters_list.focus();
         rcmail.filters_list.init();
         rcmail.filters_list.focus();
+      }
 
 
-        rcmail.enable_command('plugin.managesieve-set', true);
-        rcmail.enable_command('plugin.managesieve-setact', 'plugin.managesieve-setget', rcmail.gui_objects.filtersetslist.length);
-        rcmail.enable_command('plugin.managesieve-setdel', rcmail.gui_objects.filtersetslist.length > 1);
+      if (rcmail.gui_objects.filtersetslist) {
+        rcmail.filtersets_list = new rcube_list_widget(rcmail.gui_objects.filtersetslist, {multiselect:false, draggable:false, keyboard:false});
+        rcmail.filtersets_list.addEventListener('select', function(o){ p.managesieve_setselect(o); });
+        rcmail.filtersets_list.init();
+        rcmail.filtersets_list.focus();
 
 
-        $('#'+rcmail.buttons['plugin.managesieve-setact'][0].id).attr('title', rcmail.gettext('managesieve.filterset'
-          + (rcmail.gui_objects.filtersetslist.value == rcmail.env.active_set ? 'deact' : 'act')));
+        if (set != null) {
+          set = rcmail.managesieve_setid(set);
+          rcmail.filtersets_list.shift_start = set;
+          rcmail.filtersets_list.highlight_row(set, false);
+        }
+
+        setcnt = rcmail.filtersets_list.rowcount;
+        rcmail.enable_command('plugin.managesieve-set', true);
+        rcmail.enable_command('plugin.managesieve-setact', 'plugin.managesieve-setget', setcnt);
+        rcmail.enable_command('plugin.managesieve-setdel', setcnt > 1);
       }
     }
     if (rcmail.gui_objects.sieveform && rcmail.env.rule_disabled)
       }
     }
     if (rcmail.gui_objects.sieveform && rcmail.env.rule_disabled)
@@ -59,7 +100,7 @@ if (window.rcmail) {
 };
 
 /*********************************************************/
 };
 
 /*********************************************************/
-/*********     Managesieve filters methods       *********/
+/*********       Managesieve UI methods          *********/
 /*********************************************************/
 
 rcube_webmail.prototype.managesieve_add = function()
 /*********************************************************/
 
 rcube_webmail.prototype.managesieve_add = function()
@@ -71,23 +112,41 @@ rcube_webmail.prototype.managesieve_add = function()
 rcube_webmail.prototype.managesieve_del = function()
 {
   var id = this.filters_list.get_single_selection();
 rcube_webmail.prototype.managesieve_del = function()
 {
   var id = this.filters_list.get_single_selection();
-  if (confirm(this.get_label('managesieve.filterdeleteconfirm')))
-    this.http_request('plugin.managesieve',
-      '_act=delete&_fid='+this.filters_list.rows[id].uid, true);
+  if (confirm(this.get_label('managesieve.filterdeleteconfirm'))) {
+    var lock = this.set_busy(true, 'loading');
+    this.http_post('plugin.managesieve',
+      '_act=delete&_fid='+this.filters_list.rows[id].uid, lock);
+  }
 };
 
 };
 
-rcube_webmail.prototype.managesieve_up = function()
+rcube_webmail.prototype.managesieve_act = function()
 {
 {
-  var id = this.filters_list.get_single_selection();
-  this.http_request('plugin.managesieve',
-    '_act=up&_fid='+this.filters_list.rows[id].uid, true);
+  var id = this.filters_list.get_single_selection(),
+    lock = this.set_busy(true, 'loading');
+
+  this.http_post('plugin.managesieve',
+    '_act=act&_fid='+this.filters_list.rows[id].uid, lock);
 };
 
 };
 
-rcube_webmail.prototype.managesieve_down = function()
+// Filter selection
+rcube_webmail.prototype.managesieve_select = function(list)
 {
 {
-  var id = this.filters_list.get_single_selection();
-  this.http_request('plugin.managesieve',
-    '_act=down&_fid='+this.filters_list.rows[id].uid, true);
+  var id = list.get_single_selection();
+  if (id != null)
+    this.load_managesieveframe(list.rows[id].uid);
+};
+
+// Set selection
+rcube_webmail.prototype.managesieve_setselect = function(list)
+{
+  this.show_contentframe(false);
+  this.filters_list.clear(true);
+  this.enable_command('plugin.managesieve-setdel', list.rowcount > 1);
+  this.enable_command( 'plugin.managesieve-setact', 'plugin.managesieve-setget', true);
+
+  var id = list.get_single_selection();
+  if (id != null)
+    this.managesieve_list(this.env.filtersets[id]);
 };
 
 rcube_webmail.prototype.managesieve_rowid = function(id)
 };
 
 rcube_webmail.prototype.managesieve_rowid = function(id)
@@ -99,194 +158,275 @@ rcube_webmail.prototype.managesieve_rowid = function(id)
       return i;
 };
 
       return i;
 };
 
-rcube_webmail.prototype.managesieve_updatelist = function(action, name, id, disabled)
+// Returns set's identifier
+rcube_webmail.prototype.managesieve_setid = function(name)
+{
+  for (var i in this.env.filtersets)
+    if (this.env.filtersets[i] == name)
+      return i;
+};
+
+// Filters listing request
+rcube_webmail.prototype.managesieve_list = function(script)
+{
+  var lock = this.set_busy(true, 'loading');
+
+  this.http_post('plugin.managesieve', '_act=list&_set='+urlencode(script), lock);
+};
+
+// Script download request
+rcube_webmail.prototype.managesieve_setget = function()
+{
+  var id = this.filtersets_list.get_single_selection(),
+    script = this.env.filtersets[id];
+
+  location.href = this.env.comm_path+'&_action=plugin.managesieve&_act=setget&_set='+urlencode(script);
+};
+
+// Set activate/deactivate request
+rcube_webmail.prototype.managesieve_setact = function()
+{
+  var id = this.filtersets_list.get_single_selection(),
+   lock = this.set_busy(true, 'loading'),
+    script = this.env.filtersets[id],
+    action = $('#rcmrow'+id).hasClass('disabled') ? 'setact' : 'deact';
+
+  this.http_post('plugin.managesieve', '_act='+action+'&_set='+urlencode(script), lock);
+};
+
+// Set delete request
+rcube_webmail.prototype.managesieve_setdel = function()
+{
+  if (!confirm(this.get_label('managesieve.setdeleteconfirm')))
+    return false;
+
+  var id = this.filtersets_list.get_single_selection(),
+    lock = this.set_busy(true, 'loading'),
+    script = this.env.filtersets[id];
+
+  this.http_post('plugin.managesieve', '_act=setdel&_set='+urlencode(script), lock);
+};
+
+// Set add request
+rcube_webmail.prototype.managesieve_setadd = function()
+{
+  this.filters_list.clear_selection();
+  this.enable_command('plugin.managesieve-act', 'plugin.managesieve-del', false);
+
+  if (this.env.contentframe && window.frames && window.frames[this.env.contentframe]) {
+    var lock = this.set_busy(true, 'loading');
+    target = window.frames[this.env.contentframe];
+    target.location.href = this.env.comm_path+'&_action=plugin.managesieve&_framed=1&_newset=1&_unlock='+lock;
+  }
+};
+
+rcube_webmail.prototype.managesieve_updatelist = function(action, o)
 {
   this.set_busy(true);
 
   switch (action) {
 {
   this.set_busy(true);
 
   switch (action) {
-    case 'delete':
-      this.filters_list.remove_row(this.managesieve_rowid(id));
-      this.filters_list.clear_selection();
-      this.enable_command('plugin.managesieve-del', 'plugin.managesieve-up', 'plugin.managesieve-down', false);
+
+    // Delete filter row
+    case 'del':
+      var i, list = this.filters_list, rows = list.rows;
+
+      list.remove_row(this.managesieve_rowid(o.id));
+      list.clear_selection();
       this.show_contentframe(false);
       this.show_contentframe(false);
+      this.enable_command('plugin.managesieve-del', 'plugin.managesieve-act', false);
 
       // re-numbering filters
 
       // re-numbering filters
-      var i, rows = this.filters_list.rows;
       for (i=0; i<rows.length; i++) {
       for (i=0; i<rows.length; i++) {
-        if (rows[i] != null && rows[i].uid > id)
+        if (rows[i] != null && rows[i].uid > o.id)
           rows[i].uid = rows[i].uid-1;
       }
           rows[i].uid = rows[i].uid-1;
       }
+
       break;
 
       break;
 
-    case 'down':
-      var from, fromstatus, status, rows = this.filters_list.rows;
+    // Update filter row
+    case 'update':
+      var i, row = $('#rcmrow'+o.id);
+
+      if (o.name)
+        $('td', row).html(o.name);
+      if (o.disabled)
+        row.addClass('disabled');
+      else
+        row.removeClass('disabled');
+
+      $('#disabled', $('iframe').contents()).prop('checked', o.disabled);
 
 
-      // we need only to replace filter names...
-      for (var i=0; i<rows.length; i++) {
-        if (rows[i]==null) { // removed row
-          continue;
-        }
-        else if (rows[i].uid == id) {
-          from = rows[i].obj;
-          fromstatus = $(from).hasClass('disabled');
-        }
-        else if (rows[i].uid == id+1) {
-          name = rows[i].obj.cells[0].innerHTML;
-          status = $(rows[i].obj).hasClass('disabled');
-          rows[i].obj.cells[0].innerHTML = from.cells[0].innerHTML;
-          from.cells[0].innerHTML = name;
-          $(from)[status?'addClass':'removeClass']('disabled');
-          $(rows[i].obj)[fromstatus?'addClass':'removeClass']('disabled');
-          this.filters_list.highlight_row(i);
-          break;
-        }
-      }
-      // ... and disable/enable Down button
-      this.filters_listbuttons();
       break;
 
       break;
 
-    case 'up':
-      var from, status, fromstatus, rows = this.filters_list.rows;
+    // Add filter row to the list
+    case 'add':
+      var list = this.filters_list,
+        row = $('<tr><td class="name"></td></tr>');
+
+      $('td', row).html(o.name);
+      row.attr('id', 'rcmrow'+o.id);
+      if (o.disabled)
+        row.addClass('disabled');
+
+      list.insert_row(row.get(0));
+      list.highlight_row(o.id);
+
+      this.enable_command('plugin.managesieve-del', 'plugin.managesieve-act', true);
 
 
-      // we need only to replace filter names...
-      for (var i=0; i<rows.length; i++) {
-        if (rows[i] == null) { // removed row
-          continue;
-        }
-        else if (rows[i].uid == id-1) {
-          from = rows[i].obj;
-          fromstatus = $(from).hasClass('disabled');
-          this.filters_list.highlight_row(i);
-        }
-        else if (rows[i].uid == id) {
-          name = rows[i].obj.cells[0].innerHTML;
-          status = $(rows[i].obj).hasClass('disabled');
-          rows[i].obj.cells[0].innerHTML = from.cells[0].innerHTML;
-          from.cells[0].innerHTML = name;
-          $(from)[status?'addClass':'removeClass']('disabled');
-          $(rows[i].obj)[fromstatus?'addClass':'removeClass']('disabled');
-          break;
-        }
-      }
-      // ... and disable/enable Up button
-      this.filters_listbuttons();
       break;
 
       break;
 
-    case 'update':
-      var rows = parent.rcmail.filters_list.rows;
-      for (var i=0; i<rows.length; i++)
-        if (rows[i] && rows[i].uid == id) {
-          rows[i].obj.cells[0].innerHTML = name;
-          if (disabled)
-            $(rows[i].obj).addClass('disabled');
-          else
-            $(rows[i].obj).removeClass('disabled');
-          break;
-        }
+    // Filling rules list
+    case 'list':
+      var i, tr, td, el, list = this.filters_list;
+
+      if (o.clear)
+        list.clear();
+
+      for (i in o.list) {
+        el = o.list[i];
+        tr = document.createElement('TR');
+        td = document.createElement('TD');
+
+        td.innerHTML = el.name;
+        td.className = 'name';
+        tr.id = 'rcmrow' + el.id;
+        if (el['class'])
+            tr.className = el['class'];
+        tr.appendChild(td);
+
+        list.insert_row(tr);
+      }
+
+      if (o.set)
+        list.highlight_row(o.set);
+      else
+        this.enable_command('plugin.managesieve-del', 'plugin.managesieve-act', false);
+
       break;
 
       break;
 
-    case 'add':
-      var row, new_row, td, list = parent.rcmail.filters_list;
-
-      if (!list)
-        break;
-
-      for (var i=0; i<list.rows.length; i++)
-        if (list.rows[i] != null && String(list.rows[i].obj.id).match(/^rcmrow/))
-          row = list.rows[i].obj;
-
-      if (row) {
-        new_row = parent.document.createElement('tr');
-        new_row.id = 'rcmrow'+id;
-        td = parent.document.createElement('td');
-        new_row.appendChild(td);
-        list.insert_row(new_row, false);
-        if (disabled)
-          $(new_row).addClass('disabled');
-          if (row.cells[0].className)
-            td.className = row.cells[0].className;
-
-           td.innerHTML = name;
-        list.highlight_row(id);
-
-        parent.rcmail.enable_command('plugin.managesieve-del', 'plugin.managesieve-up', true);
+    // Sactivate/deactivate set
+    case 'setact':
+      var id = this.managesieve_setid(o.name), row = $('#rcmrow' + id);
+      if (o.active) {
+        if (o.all)
+          $('tr', this.gui_objects.filtersetslist).addClass('disabled');
+        row.removeClass('disabled');
       }
       }
-      else // refresh whole page
-        parent.rcmail.goto_url('plugin.managesieve');
+      else
+        row.addClass('disabled');
+
       break;
       break;
-  }
 
 
-  this.set_busy(false);
-};
+    // Delete set row
+    case 'setdel':
+      var id = this.managesieve_setid(o.name);
 
 
-rcube_webmail.prototype.managesieve_select = function(list)
-{
-  var id = list.get_single_selection();
-  if (id != null)
-    this.load_managesieveframe(list.rows[id].uid);
-};
+      this.filtersets_list.remove_row(id);
+      this.filters_list.clear();
+      this.show_contentframe(false);
+      this.enable_command('plugin.managesieve-setdel', 'plugin.managesieve-setact', 'plugin.managesieve-setget', false);
 
 
-rcube_webmail.prototype.managesieve_save = function()
-{
-  if (parent.rcmail && parent.rcmail.filters_list && this.gui_objects.sieveform.name != 'filtersetform') {
-    var id = parent.rcmail.filters_list.get_single_selection();
-    if (id != null)
-      this.gui_objects.sieveform.elements['_fid'].value = parent.rcmail.filters_list.rows[id].uid;
+      delete this.env.filtersets[id];
+
+      break;
+
+    // Create set row
+    case 'setadd':
+      var id = 'S' + new Date().getTime(),
+        list = this.filtersets_list,
+        row = $('<tr class="disabled"><td class="name"></td></tr>');
+
+      $('td', row).html(o.name);
+      row.attr('id', 'rcmrow'+id);
+
+      this.env.filtersets[id] = o.name;
+      list.insert_row(row.get(0));
+
+      // move row into its position on the list
+      if (o.index != list.rowcount-1) {
+        row.detach();
+        var elem = $('tr:visible', list.list).get(o.index);
+        row.insertBefore(elem);
+      }
+
+      list.select(id);
+
+      break;
   }
   }
-  this.gui_objects.sieveform.submit();
+
+  this.set_busy(false);
 };
 
 // load filter frame
 rcube_webmail.prototype.load_managesieveframe = function(id)
 {
 };
 
 // load filter frame
 rcube_webmail.prototype.load_managesieveframe = function(id)
 {
-  if (typeof(id) != 'undefined' && id != null) {
-    this.enable_command('plugin.managesieve-del', true);
-    this.filters_listbuttons();
-  }
-  else
-    this.enable_command('plugin.managesieve-up', 'plugin.managesieve-down', 'plugin.managesieve-del', false);
+  var has_id = typeof(id) != 'undefined' && id != null;
+  this.enable_command('plugin.managesieve-act', 'plugin.managesieve-del', has_id);
 
   if (this.env.contentframe && window.frames && window.frames[this.env.contentframe]) {
     target = window.frames[this.env.contentframe];
     var msgid = this.set_busy(true, 'loading');
 
   if (this.env.contentframe && window.frames && window.frames[this.env.contentframe]) {
     target = window.frames[this.env.contentframe];
     var msgid = this.set_busy(true, 'loading');
-    target.location.href = this.env.comm_path+'&_action=plugin.managesieve&_framed=1&_fid='+id+'&_unlock='+msgid;
+    target.location.href = this.env.comm_path+'&_action=plugin.managesieve&_framed=1'
+      +(id ? '&_fid='+id : '')+'&_unlock='+msgid;
   }
 };
 
   }
 };
 
-// enable/disable Up/Down buttons
-rcube_webmail.prototype.filters_listbuttons = function()
+// load filter frame
+rcube_webmail.prototype.managesieve_dragstart = function(list)
 {
 {
-  var id = this.filters_list.get_single_selection(),
-    rows = this.filters_list.rows;
+  var id = this.filters_list.get_single_selection();
 
 
-  for (var i=0; i<rows.length; i++) {
-    if (rows[i] == null) { // removed row
-    }
-    else if (i == id) {
-      this.enable_command('plugin.managesieve-up', false);
-      break;
-    }
-    else {
-      this.enable_command('plugin.managesieve-up', true);
-      break;
+  this.drag_active = true;
+  this.drag_filter = id;
+};
+
+rcube_webmail.prototype.managesieve_dragend = function(e)
+{
+  if (this.drag_active) {
+    if (this.drag_filter_target) {
+      var lock = this.set_busy(true, 'loading');
+
+      this.show_contentframe(false);
+      this.http_post('plugin.managesieve', '_act=move&_fid='+this.drag_filter
+        +'&_to='+this.drag_filter_target, lock);
     }
     }
+    this.drag_active = false;
   }
   }
+};
 
 
-  for (var i=rows.length-1; i>0; i--) {
-    if (rows[i] == null) { // removed row
-    }
-    else if (i == id) {
-      this.enable_command('plugin.managesieve-down', false);
-      break;
-    }
-    else {
-      this.enable_command('plugin.managesieve-down', true);
-      break;
-    }
-  } 
+rcube_webmail.prototype.managesieve_focus_filter = function(row)
+{
+  var id = row.id.replace(/^rcmrow/, '');
+  if (this.drag_active && id != this.drag_filter) {
+    this.drag_filter_target = id;
+    $(row.obj).addClass(id < this.drag_filter ? 'filtermoveup' : 'filtermovedown');
+  }
+};
+
+rcube_webmail.prototype.managesieve_unfocus_filter = function(row)
+{
+  if (this.drag_active) {
+    $(row.obj).removeClass('filtermoveup filtermovedown');
+    this.drag_filter_target = null;
+  }
+};
+
+/*********************************************************/
+/*********          Filter Form methods          *********/
+/*********************************************************/
+
+// Form submition
+rcube_webmail.prototype.managesieve_save = function()
+{
+  if (parent.rcmail && parent.rcmail.filters_list && this.gui_objects.sieveform.name != 'filtersetform') {
+    var id = parent.rcmail.filters_list.get_single_selection();
+    if (id != null)
+      this.gui_objects.sieveform.elements['_fid'].value = parent.rcmail.filters_list.rows[id].uid;
+  }
+  this.gui_objects.sieveform.submit();
 };
 
 };
 
-// operations on filters form
+// Operations on filters form
 rcube_webmail.prototype.managesieve_ruleadd = function(id)
 {
   this.http_post('plugin.managesieve', '_act=ruleadd&_rid='+id);
 rcube_webmail.prototype.managesieve_ruleadd = function(id)
 {
   this.http_post('plugin.managesieve', '_act=ruleadd&_rid='+id);
@@ -311,6 +451,9 @@ rcube_webmail.prototype.managesieve_rulefill = function(content, id, after)
 
 rcube_webmail.prototype.managesieve_ruledel = function(id)
 {
 
 rcube_webmail.prototype.managesieve_ruledel = function(id)
 {
+  if ($('#ruledel'+id).hasClass('disabled'))
+    return;
+
   if (confirm(this.get_label('managesieve.ruledeleteconfirm'))) {
     var row = document.getElementById('rulerow'+id);
     row.parentNode.removeChild(row);
   if (confirm(this.get_label('managesieve.ruledeleteconfirm'))) {
     var row = document.getElementById('rulerow'+id);
     row.parentNode.removeChild(row);
@@ -341,6 +484,9 @@ rcube_webmail.prototype.managesieve_actionfill = function(content, id, after)
 
 rcube_webmail.prototype.managesieve_actiondel = function(id)
 {
 
 rcube_webmail.prototype.managesieve_actiondel = function(id)
 {
+  if ($('#actiondel'+id).hasClass('disabled'))
+    return;
+
   if (confirm(this.get_label('managesieve.actiondeleteconfirm'))) {
     var row = document.getElementById('actionrow'+id);
     row.parentNode.removeChild(row);
   if (confirm(this.get_label('managesieve.actiondeleteconfirm'))) {
     var row = document.getElementById('actionrow'+id);
     row.parentNode.removeChild(row);
@@ -383,155 +529,44 @@ rcube_webmail.prototype.managesieve_formbuttons = function(div)
     button = document.getElementById(buttons[i]);
     if (i>0 || buttons.length>1) {
       $(button).removeClass('disabled');
     button = document.getElementById(buttons[i]);
     if (i>0 || buttons.length>1) {
       $(button).removeClass('disabled');
-      button.removeAttribute('disabled');
     }
     else {
       $(button).addClass('disabled');
     }
     else {
       $(button).addClass('disabled');
-      button.setAttribute('disabled', true);
     }
   }
 };
 
     }
   }
 };
 
-// Set change
-rcube_webmail.prototype.managesieve_set = function()
-{
-  var script = $(this.gui_objects.filtersetslist).val();
-  location.href = this.env.comm_path+'&_action=plugin.managesieve&_set='+script;
-};
-
-// Script download
-rcube_webmail.prototype.managesieve_setget = function()
-{
-  var script = $(this.gui_objects.filtersetslist).val();
-  location.href = this.env.comm_path+'&_action=plugin.managesieve&_act=setget&_set='+script;
-};
-
-// Set activate
-rcube_webmail.prototype.managesieve_setact = function()
-{
-  if (!this.gui_objects.filtersetslist)
-    return false;
-
-  var script = this.gui_objects.filtersetslist.value,
-    action = (script == rcmail.env.active_set ? 'deact' : 'setact');
-
-  this.http_post('plugin.managesieve', '_act='+action+'&_set='+script);
-};
-
-// Set activate flag in sets list after set activation
-rcube_webmail.prototype.managesieve_reset = function()
-{
-  if (!this.gui_objects.filtersetslist)
-    return false;
-
-  var list = this.gui_objects.filtersetslist,
-    opts = list.getElementsByTagName('option'),
-    label = ' (' + this.get_label('managesieve.active') + ')',
-    regx = new RegExp(RegExp.escape(label)+'$');
-
-  for (var x=0; x<opts.length; x++) {
-    if (opts[x].value != rcmail.env.active_set && opts[x].innerHTML.match(regx))
-      opts[x].innerHTML = opts[x].innerHTML.replace(regx, '');
-    else if (opts[x].value == rcmail.env.active_set)
-      opts[x].innerHTML = opts[x].innerHTML + label;
-  }
-
-  // change title of setact button
-  $('#'+rcmail.buttons['plugin.managesieve-setact'][0].id).attr('title', rcmail.gettext('managesieve.filterset'
-    + (list.value == rcmail.env.active_set ? 'deact' : 'act')));
-};
-
-// Set delete
-rcube_webmail.prototype.managesieve_setdel = function()
-{
-  if (!this.gui_objects.filtersetslist)
-    return false;
-
-  if (!confirm(this.get_label('managesieve.setdeleteconfirm')))
-    return false;
-
-  var script = this.gui_objects.filtersetslist.value;
-  this.http_post('plugin.managesieve', '_act=setdel&_set='+script);
-};
-
-// Set add
-rcube_webmail.prototype.managesieve_setadd = function()
-{
-  this.filters_list.clear_selection();
-  this.enable_command('plugin.managesieve-up', 'plugin.managesieve-down', 'plugin.managesieve-del', false);
-
-  if (this.env.contentframe && window.frames && window.frames[this.env.contentframe]) {
-    target = window.frames[this.env.contentframe];
-    var msgid = this.set_busy(true, 'loading');
-    target.location.href = this.env.comm_path+'&_action=plugin.managesieve&_framed=1&_newset=1&_unlock='+msgid;
-  }
-};
-
-rcube_webmail.prototype.managesieve_reload = function(set)
-{
-  this.env.reload_set = set;
-  window.setTimeout(function() {
-    location.href = rcmail.env.comm_path + '&_action=plugin.managesieve'
-      + (rcmail.env.reload_set ? '&_set=' + rcmail.env.reload_set : '')
-  }, 500);
-};
-
-// Register onmouse(leave/enter) events for tips on specified form element
-rcube_webmail.prototype.managesieve_tip_register = function(tips)
-{
-  for (var n in tips) {
-    $('#'+tips[n][0])
-      .bind('mouseenter', {str: tips[n][1]},
-        function(e) {
-          var offset = $(this).offset(),
-            tip = rcmail.env.framed ? parent.rcmail.env.ms_tip_layer : rcmail.env.ms_tip_layer,
-            left = offset.left,
-            top = offset.top - 12;
-
-          if (rcmail.env.framed) {
-            offset = $(parent.document.getElementById('filter-box')).offset();
-            top  += offset.top;
-            left += offset.left;
-          }
-
-          tip.html(e.data.str)
-          top -= tip.height();
-          
-          tip.css({left: left, top: top}).show();
-        })
-      .bind('mouseleave',
-        function(e) {
-          var tip = parent.rcmail && parent.rcmail.env.ms_tip_layer ? 
-            parent.rcmail.env.ms_tip_layer : rcmail.env.ms_tip_layer;
-          tip.hide();
-      });
-  }
-};
-
-/*********************************************************/
-/*********     Other Managesieve UI methods      *********/
-/*********************************************************/
-
 function rule_header_select(id)
 {
   var obj = document.getElementById('header' + id),
     size = document.getElementById('rule_size' + id),
     op = document.getElementById('rule_op' + id),
     target = document.getElementById('rule_target' + id),
 function rule_header_select(id)
 {
   var obj = document.getElementById('header' + id),
     size = document.getElementById('rule_size' + id),
     op = document.getElementById('rule_op' + id),
     target = document.getElementById('rule_target' + id),
-    header = document.getElementById('custom_header' + id);
+    header = document.getElementById('custom_header' + id),
+    mod = document.getElementById('rule_mod' + id),
+    trans = document.getElementById('rule_trans' + id),
+    comp = document.getElementById('rule_comp' + id);
 
   if (obj.value == 'size') {
     size.style.display = 'inline';
     op.style.display = 'none';
     target.style.display = 'none';
     header.style.display = 'none';
 
   if (obj.value == 'size') {
     size.style.display = 'inline';
     op.style.display = 'none';
     target.style.display = 'none';
     header.style.display = 'none';
+    mod.style.display = 'none';
+    trans.style.display = 'none';
+    comp.style.display = 'none';
   }
   else {
     header.style.display = obj.value != '...' ? 'none' : 'inline';
     size.style.display = 'none';
     op.style.display = 'inline';
   }
   else {
     header.style.display = obj.value != '...' ? 'none' : 'inline';
     size.style.display = 'none';
     op.style.display = 'inline';
+    comp.style.display = '';
     rule_op_select(id);
     rule_op_select(id);
+    mod.style.display = obj.value == 'body' ? 'none' : 'block';
+    trans.style.display = obj.value == 'body' ? 'block' : 'none';
   }
   }
+
+  obj.style.width = obj.value == '...' ? '40px' : '';
 };
 
 function rule_op_select(id)
 };
 
 function rule_op_select(id)
@@ -542,15 +577,45 @@ function rule_op_select(id)
   target.style.display = obj.value == 'exists' || obj.value == 'notexists' ? 'none' : 'inline';
 };
 
   target.style.display = obj.value == 'exists' || obj.value == 'notexists' ? 'none' : 'inline';
 };
 
+function rule_trans_select(id)
+{
+  var obj = document.getElementById('rule_trans_op' + id),
+    target = document.getElementById('rule_trans_type' + id);
+
+  target.style.display = obj.value != 'content' ? 'none' : 'inline';
+};
+
+function rule_mod_select(id)
+{
+  var obj = document.getElementById('rule_mod_op' + id),
+    target = document.getElementById('rule_mod_type' + id);
+
+  target.style.display = obj.value != 'address' && obj.value != 'envelope' ? 'none' : 'inline';
+};
+
 function rule_join_radio(value)
 {
   $('#rules').css('display', value == 'any' ? 'none' : 'block');
 };
 
 function rule_join_radio(value)
 {
   $('#rules').css('display', value == 'any' ? 'none' : 'block');
 };
 
+function rule_adv_switch(id, elem)
+{
+  var elem = $(elem), enabled = elem.hasClass('hide'), adv = $('#rule_advanced'+id);
+
+  if (enabled) {
+    adv.hide();
+    elem.removeClass('hide').addClass('show');
+  }
+  else {
+    adv.show();
+    elem.removeClass('show').addClass('hide');
+  }
+}
+
 function action_type_select(id)
 {
   var obj = document.getElementById('action_type' + id),
 function action_type_select(id)
 {
   var obj = document.getElementById('action_type' + id),
-       enabled = {},
+    enabled = {},
     elems = {
       mailbox: document.getElementById('action_mailbox' + id),
       target: document.getElementById('action_target' + id),
     elems = {
       mailbox: document.getElementById('action_mailbox' + id),
       target: document.getElementById('action_target' + id),
@@ -579,3 +644,126 @@ function action_type_select(id)
     elems[x].style.display = !enabled[x] ? 'none' : 'inline';
   }
 };
     elems[x].style.display = !enabled[x] ? 'none' : 'inline';
   }
 };
+
+// Register onmouse(leave/enter) events for tips on specified form element
+rcube_webmail.prototype.managesieve_tip_register = function(tips)
+{
+  var n, framed = parent.rcmail,
+    tip = framed ? parent.rcmail.env.ms_tip_layer : rcmail.env.ms_tip_layer;
+
+  for (var n in tips) {
+    $('#'+tips[n][0])
+      .bind('mouseenter', {str: tips[n][1]},
+        function(e) {
+          var offset = $(this).offset(),
+            left = offset.left,
+            top = offset.top - 12;
+
+          if (framed) {
+            offset = $((rcmail.env.task == 'mail'  ? '#sievefilterform > iframe' : '#filter-box'), parent.document).offset();
+            top  += offset.top;
+            left += offset.left;
+          }
+
+          tip.html(e.data.str)
+          top -= tip.height();
+
+          tip.css({left: left, top: top}).show();
+        })
+      .bind('mouseleave', function(e) { tip.hide(); });
+  }
+};
+
+/*********************************************************/
+/*********           Mail UI methods             *********/
+/*********************************************************/
+
+rcube_webmail.prototype.managesieve_create = function()
+{
+  if (!rcmail.env.sieve_headers || !rcmail.env.sieve_headers.length)
+    return;
+
+  var i, html, buttons = {}, dialog = $("#sievefilterform");
+
+  // create dialog window
+  if (!dialog.length) {
+    dialog = $('<div id="sievefilterform"></div>');
+    $('body').append(dialog);
+  }
+
+  // build dialog window content
+  html = '<fieldset><legend>'+this.gettext('managesieve.usedata')+'</legend><ul>';
+  for (i in rcmail.env.sieve_headers)
+    html += '<li><input type="checkbox" name="headers[]" id="sievehdr'+i+'" value="'+i+'" checked="checked" />'
+      +'<label for="sievehdr'+i+'">'+rcmail.env.sieve_headers[i][0]+':</label> '+rcmail.env.sieve_headers[i][1]+'</li>';
+  html += '</ul></fieldset>';
+
+  dialog.html(html);
+
+  // [Next Step] button action
+  buttons[this.gettext('managesieve.nextstep')] = function () {
+    // check if there's at least one checkbox checked
+    var hdrs = $('input[name="headers[]"]:checked', dialog);
+    if (!hdrs.length) {
+      alert(rcmail.gettext('managesieve.nodata'));
+      return;
+    }
+
+    // build frame URL
+    var url = rcmail.get_task_url('mail');
+    url = rcmail.add_url(url, '_action', 'plugin.managesieve');
+    url = rcmail.add_url(url, '_framed', 1);
+
+    hdrs.map(function() {
+      var val = rcmail.env.sieve_headers[this.value];
+      url = rcmail.add_url(url, 'r['+this.value+']', val[0]+':'+val[1]);
+    });
+
+    // load form in the iframe
+    var frame = $('<iframe>').attr({src: url, frameborder: 0})
+    dialog.empty().append(frame).dialog('dialog').resize();
+
+    // Change [Next Step] button with [Save] button
+    buttons = {};
+    buttons[rcmail.gettext('save')] = function() {
+      var win = $('iframe', dialog).get(0).contentWindow;
+      win.rcmail.managesieve_save();
+    };
+    dialog.dialog('option', 'buttons', buttons);
+  };
+
+  // show dialog window
+  dialog.dialog({
+    modal: false,
+    resizable: !bw.ie6,
+    closeOnEscape: (!bw.ie6 && !bw.ie7),  // disable for performance reasons
+    title: this.gettext('managesieve.newfilter'),
+    close: function() { rcmail.managesieve_dialog_close(); },
+    buttons: buttons,
+    minWidth: 600,
+    minHeight: 300,
+    height: 250
+  }).show();
+
+  this.env.managesieve_dialog = dialog;
+}
+
+rcube_webmail.prototype.managesieve_dialog_close = function()
+{
+  var dialog = this.env.managesieve_dialog;
+
+  // BUG(?): if we don't remove the iframe first, it will be reloaded
+  dialog.html('');
+  dialog.dialog('destroy').hide();
+}
+
+rcube_webmail.prototype.managesieve_dialog_resize = function(o)
+{
+  var dialog = this.env.managesieve_dialog,
+    win = $(window), form = $(o);
+    width = form.width(), height = form.height(),
+    w = win.width(), h = win.height();
+
+  dialog.dialog('option', { height: Math.min(h-20, height+120), width: Math.min(w-20, width+65) })
+    .dialog('option', 'position', ['center', 'center']);  // only works in a separate call (!?)
+}
index 2cb7122752613268769be390b548043646cb8192..d557907968d40e178c960275f3494cda8c543add 100644 (file)
@@ -7,12 +7,13 @@
  * It's clickable interface which operates on text scripts and communicates
  * with server using managesieve protocol. Adds Filters tab in Settings.
  *
  * It's clickable interface which operates on text scripts and communicates
  * with server using managesieve protocol. Adds Filters tab in Settings.
  *
- * @version 4.3
+ * @version 5.0
  * @author Aleksander Machniak <alec@alec.pl>
  *
  * Configuration (see config.inc.php.dist)
  *
  * Copyright (C) 2008-2011, The Roundcube Dev Team
  * @author Aleksander Machniak <alec@alec.pl>
  *
  * Configuration (see config.inc.php.dist)
  *
  * Copyright (C) 2008-2011, The Roundcube Dev Team
+ * Copyright (C) 2011, Kolab Systems AG
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- * $Id: managesieve.php 4983 2011-07-28 07:31:16Z alec $
+ * $Id: managesieve.php 5452 2011-11-18 14:44:48Z alec $
  */
 
 class managesieve extends rcube_plugin
 {
  */
 
 class managesieve extends rcube_plugin
 {
-    public $task = 'settings';
+    public $task = 'mail|settings';
 
     private $rc;
     private $sieve;
 
     private $rc;
     private $sieve;
@@ -41,29 +42,141 @@ class managesieve extends rcube_plugin
     private $tips = array();
     private $script = array();
     private $exts = array();
     private $tips = array();
     private $script = array();
     private $exts = array();
+    private $list;
+    private $active = array();
     private $headers = array(
     private $headers = array(
-        'subject'   => 'Subject',
-        'sender'    => 'From',
-        'recipient' => 'To',
+        'subject' => 'Subject',
+        'from'    => 'From',
+        'to'      => 'To',
     );
     );
+    private $addr_headers = array(
+        // Required
+        "from", "to", "cc", "bcc", "sender", "resent-from", "resent-to",
+        // Additional (RFC 822 / RFC 2822)
+        "reply-to", "resent-reply-to", "resent-sender", "resent-cc", "resent-bcc",
+        // Non-standard (RFC 2076, draft-palme-mailext-headers-08.txt)
+        "for-approval", "for-handling", "for-comment", "apparently-to", "errors-to",
+        "delivered-to", "return-receipt-to", "x-admin", "read-receipt-to",
+        "x-confirm-reading-to", "return-receipt-requested",
+        "registered-mail-reply-requested-by", "mail-followup-to", "mail-reply-to",
+        "abuse-reports-to", "x-complaints-to", "x-report-abuse-to",
+        // Undocumented
+        "x-beenthere",
+    );
+
+    const VERSION = '5.0';
+    const PROGNAME = 'Roundcube (Managesieve)';
 
 
     function init()
     {
 
 
     function init()
     {
-        // add Tab label/title
-        $this->add_texts('localization/', array('filters','managefilters'));
+        $this->rc = rcmail::get_instance();
 
         // register actions
         $this->register_action('plugin.managesieve', array($this, 'managesieve_actions'));
         $this->register_action('plugin.managesieve-save', array($this, 'managesieve_save'));
 
 
         // register actions
         $this->register_action('plugin.managesieve', array($this, 'managesieve_actions'));
         $this->register_action('plugin.managesieve-save', array($this, 'managesieve_save'));
 
-        // include main js script
+        if ($this->rc->task == 'settings') {
+            $this->init_ui();
+        }
+        else if ($this->rc->task == 'mail') {
+            // register message hook
+            $this->add_hook('message_headers_output', array($this, 'mail_headers'));
+
+            // inject Create Filter popup stuff
+            if (empty($this->rc->action) || $this->rc->action == 'show') {
+                $this->mail_task_handler();
+            }
+        }
+    }
+
+    /**
+     * Initializes plugin's UI (localization, js script)
+     */
+    private function init_ui()
+    {
+        if ($this->ui_initialized)
+            return;
+
+        // load localization
+        $this->add_texts('localization/', array('filters','managefilters'));
         $this->include_script('managesieve.js');
         $this->include_script('managesieve.js');
+
+        $this->ui_initialized = true;
+    }
+
+    /**
+     * Add UI elements to the 'mailbox view' and 'show message' UI.
+     */
+    function mail_task_handler()
+    {
+        // use jQuery for popup window
+        $this->require_plugin('jqueryui'); 
+
+        // include js script and localization
+        $this->init_ui();
+
+        // include styles
+        $skin = $this->rc->config->get('skin');
+        if (!file_exists($this->home."/skins/$skin/managesieve_mail.css"))
+            $skin = 'default';
+        $this->include_stylesheet("skins/$skin/managesieve_mail.css");
+
+        // add 'Create filter' item to message menu
+        $this->api->add_content(html::tag('li', null, 
+            $this->api->output->button(array(
+                'command'  => 'managesieve-create',
+                'label'    => 'managesieve.filtercreate',
+                'type'     => 'link',
+                'classact' => 'filterlink active',
+                'class'    => 'filterlink',
+            ))), 'messagemenu');
+
+        // register some labels/messages
+        $this->rc->output->add_label('managesieve.newfilter', 'managesieve.usedata',
+            'managesieve.nodata', 'managesieve.nextstep', 'save');
+
+        $this->rc->session->remove('managesieve_current');
     }
 
     }
 
+    /**
+     * Get message headers for popup window
+     */
+    function mail_headers($args)
+    {
+        $headers = $args['headers'];
+        $ret     = array();
+
+        if ($headers->subject)
+            $ret[] = array('Subject', $this->rc->imap->decode_header($headers->subject));
+
+        // @TODO: List-Id, others?
+        foreach (array('From', 'To') as $h) {
+            $hl = strtolower($h);
+            if ($headers->$hl) {
+                $list = $this->rc->imap->decode_address_list($headers->$hl);
+                foreach ($list as $item) {
+                    if ($item['mailto']) {
+                        $ret[] = array($h, $item['mailto']);
+                    }
+                }
+            }
+        }
+
+        if ($this->rc->action == 'preview')
+            $this->rc->output->command('parent.set_env', array('sieve_headers' => $ret));
+        else
+            $this->rc->output->set_env('sieve_headers', $ret);
+
+
+        return $args;
+    }
+
+    /**
+     * Loads configuration, initializes plugin (including sieve connection)
+     */
     function managesieve_start()
     {
     function managesieve_start()
     {
-        $this->rc = rcmail::get_instance();
         $this->load_config();
 
         // register UI objects
         $this->load_config();
 
         // register UI objects
@@ -85,33 +198,47 @@ class managesieve extends rcube_plugin
 
         $host = rcube_idn_to_ascii($host);
 
 
         $host = rcube_idn_to_ascii($host);
 
+        $plugin = $this->rc->plugins->exec_hook('managesieve_connect', array(
+            'user'      => $_SESSION['username'],
+            'password'  => $this->rc->decrypt($_SESSION['password']),
+            'host'      => $host,
+            'port'      => $port,
+            'auth_type' => $this->rc->config->get('managesieve_auth_type'),
+            'usetls'    => $this->rc->config->get('managesieve_usetls', false),
+            'disabled'  => $this->rc->config->get('managesieve_disabled_extensions'),
+            'debug'     => $this->rc->config->get('managesieve_debug', false),
+            'auth_cid'  => $this->rc->config->get('managesieve_auth_cid'),
+            'auth_pw'   => $this->rc->config->get('managesieve_auth_pw'),
+        ));
+
         // try to connect to managesieve server and to fetch the script
         // try to connect to managesieve server and to fetch the script
-        $this->sieve = new rcube_sieve($_SESSION['username'],
-            $this->rc->decrypt($_SESSION['password']), $host, $port,
-            $this->rc->config->get('managesieve_auth_type'),
-            $this->rc->config->get('managesieve_usetls', false),
-            $this->rc->config->get('managesieve_disabled_extensions'),
-            $this->rc->config->get('managesieve_debug', false),
-            $this->rc->config->get('managesieve_auth_cid'), 
-            $this->rc->config->get('managesieve_auth_pw')
+        $this->sieve = new rcube_sieve(
+            $plugin['user'],
+            $plugin['password'],
+            $plugin['host'],
+            $plugin['port'],
+            $plugin['auth_type'],
+            $plugin['usetls'],
+            $plugin['disabled'],
+            $plugin['debug'],
+            $plugin['auth_cid'],
+            $plugin['auth_pw']
         );
 
         if (!($error = $this->sieve->error())) {
         );
 
         if (!($error = $this->sieve->error())) {
+            // Get list of scripts
+            $list = $this->list_scripts();
 
 
-            $list = $this->sieve->get_scripts();
-            $active = $this->sieve->get_active();
-            $_SESSION['managesieve_active'] = $active;
-
-            if (!empty($_GET['_set'])) {
-                $script_name = get_input_value('_set', RCUBE_INPUT_GET);
+            if (!empty($_GET['_set']) || !empty($_POST['_set'])) {
+                $script_name = get_input_value('_set', RCUBE_INPUT_GPC, true);
             }
             else if (!empty($_SESSION['managesieve_current'])) {
                 $script_name = $_SESSION['managesieve_current'];
             }
             else {
             }
             else if (!empty($_SESSION['managesieve_current'])) {
                 $script_name = $_SESSION['managesieve_current'];
             }
             else {
-                // get active script
-                if ($active) {
-                    $script_name = $active;
+                // get (first) active script
+                if (!empty($this->active[0])) {
+                    $script_name = $this->active[0];
                 }
                 else if ($list) {
                     $script_name = $list[0];
                 }
                 else if ($list) {
                     $script_name = $list[0];
@@ -120,19 +247,25 @@ class managesieve extends rcube_plugin
                 else {
                     // if script not exists build default script contents
                     $script_file = $this->rc->config->get('managesieve_default');
                 else {
                     // if script not exists build default script contents
                     $script_file = $this->rc->config->get('managesieve_default');
-                    $script_name = 'roundcube';
+                    $script_name = $this->rc->config->get('managesieve_script_name');
+
+                    if (empty($script_name))
+                        $script_name = 'roundcube';
+
                     if ($script_file && is_readable($script_file))
                         $content = file_get_contents($script_file);
 
                     if ($script_file && is_readable($script_file))
                         $content = file_get_contents($script_file);
 
-                // add script and set it active
-                if ($this->sieve->save_script($script_name, $content))
-                    if ($this->sieve->activate($script_name))
-                        $_SESSION['managesieve_active'] = $script_name;
+                    // add script and set it active
+                    if ($this->sieve->save_script($script_name, $content)) {
+                        $this->activate_script($script_name);
+                        $this->list[] = $script_name;
+                    }
                 }
             }
 
                 }
             }
 
-            if ($script_name)
+            if ($script_name) {
                 $this->sieve->load($script_name);
                 $this->sieve->load($script_name);
+            }
 
             $error = $this->sieve->error();
         }
 
             $error = $this->sieve->error();
         }
@@ -158,9 +291,9 @@ class managesieve extends rcube_plugin
             $this->script = array();
         }
         else {
             $this->script = array();
         }
         else {
-            $this->script = $this->sieve->script->as_array();
             $this->exts = $this->sieve->get_extensions();
             $this->exts = $this->sieve->get_extensions();
-            $this->rc->output->set_env('active_set', $_SESSION['managesieve_active']);
+            $this->script = $this->sieve->script->as_array();
+            $this->rc->output->set_env('currentset', $this->sieve->current);
             $_SESSION['managesieve_current'] = $this->sieve->current;
         }
 
             $_SESSION['managesieve_current'] = $this->sieve->current;
         }
 
@@ -169,94 +302,131 @@ class managesieve extends rcube_plugin
 
     function managesieve_actions()
     {
 
     function managesieve_actions()
     {
-        // Init plugin and handle managesieve connection
+        $this->init_ui();
+
         $error = $this->managesieve_start();
 
         // Handle user requests
         if ($action = get_input_value('_act', RCUBE_INPUT_GPC)) {
         $error = $this->managesieve_start();
 
         // Handle user requests
         if ($action = get_input_value('_act', RCUBE_INPUT_GPC)) {
-            $fid = (int) get_input_value('_fid', RCUBE_INPUT_GET);
+            $fid = (int) get_input_value('_fid', RCUBE_INPUT_POST);
 
 
-            if ($action == 'up' && !$error) {
-                if ($fid && isset($this->script[$fid]) && isset($this->script[$fid-1])) {
-                    if ($this->sieve->script->update_rule($fid, $this->script[$fid-1]) !== false
-                        && $this->sieve->script->update_rule($fid-1, $this->script[$fid]) !== false) {
-                        $result = $this->sieve->save();
-                    }
+            if ($action == 'delete' && !$error) {
+                if (isset($this->script[$fid])) {
+                    if ($this->sieve->script->delete_rule($fid))
+                        $result = $this->save_script();
 
 
-                    if ($result) {
-//                      $this->rc->output->show_message('managesieve.filtersaved', 'confirmation');
-                        $this->rc->output->command('managesieve_updatelist', 'up', '', $fid);
-                    } else
-                        $this->rc->output->show_message('managesieve.filtersaveerror', 'error');
+                    if ($result === true) {
+                        $this->rc->output->show_message('managesieve.filterdeleted', 'confirmation');
+                        $this->rc->output->command('managesieve_updatelist', 'del', array('id' => $fid));
+                    } else {
+                        $this->rc->output->show_message('managesieve.filterdeleteerror', 'error');
+                    }
                 }
             }
                 }
             }
-            else if ($action == 'down' && !$error) {
-                if (isset($this->script[$fid]) && isset($this->script[$fid+1])) {
-                    if ($this->sieve->script->update_rule($fid, $this->script[$fid+1]) !== false
-                        && $this->sieve->script->update_rule($fid+1, $this->script[$fid]) !== false) {
-                        $result = $this->sieve->save();
+            else if ($action == 'move' && !$error) {
+                if (isset($this->script[$fid])) {
+                    $to   = (int) get_input_value('_to', RCUBE_INPUT_POST);
+                    $rule = $this->script[$fid];
+
+                    // remove rule
+                    unset($this->script[$fid]);
+                    $this->script = array_values($this->script);
+
+                    // add at target position
+                    if ($to >= count($this->script)) {
+                        $this->script[] = $rule;
+                    }
+                    else {
+                        $script = array();
+                        foreach ($this->script as $idx => $r) {
+                            if ($idx == $to)
+                                $script[] = $rule;
+                            $script[] = $r;
+                        }
+                        $this->script = $script;
                     }
 
                     }
 
+                    $this->sieve->script->content = $this->script;
+                    $result = $this->save_script();
+
                     if ($result === true) {
                     if ($result === true) {
-//                      $this->rc->output->show_message('managesieve.filtersaved', 'confirmation');
-                        $this->rc->output->command('managesieve_updatelist', 'down', '', $fid);
+                        $result = $this->list_rules();
+
+                        $this->rc->output->show_message('managesieve.moved', 'confirmation');
+                        $this->rc->output->command('managesieve_updatelist', 'list',
+                            array('list' => $result, 'clear' => true, 'set' => $to));
                     } else {
                     } else {
-                        $this->rc->output->show_message('managesieve.filtersaveerror', 'error');
+                        $this->rc->output->show_message('managesieve.moveerror', 'error');
                     }
                 }
             }
                     }
                 }
             }
-            else if ($action == 'delete' && !$error) {
+            else if ($action == 'act' && !$error) {
                 if (isset($this->script[$fid])) {
                 if (isset($this->script[$fid])) {
-                    if ($this->sieve->script->delete_rule($fid))
-                        $result = $this->sieve->save();
+                    $rule     = $this->script[$fid];
+                    $disabled = $rule['disabled'] ? true : false;
+                    $rule['disabled'] = !$disabled;
+                    $result = $this->sieve->script->update_rule($fid, $rule);
+
+                    if ($result !== false)
+                        $result = $this->save_script();
 
                     if ($result === true) {
 
                     if ($result === true) {
-                        $this->rc->output->show_message('managesieve.filterdeleted', 'confirmation');
-                        $this->rc->output->command('managesieve_updatelist', 'delete', '', $fid);
+                        if ($rule['disabled'])
+                            $this->rc->output->show_message('managesieve.deactivated', 'confirmation');
+                        else
+                            $this->rc->output->show_message('managesieve.activated', 'confirmation');
+                        $this->rc->output->command('managesieve_updatelist', 'update',
+                            array('id' => $fid, 'disabled' => $rule['disabled']));
                     } else {
                     } else {
-                        $this->rc->output->show_message('managesieve.filterdeleteerror', 'error');
+                        if ($rule['disabled'])
+                            $this->rc->output->show_message('managesieve.deactivateerror', 'error');
+                        else
+                            $this->rc->output->show_message('managesieve.activateerror', 'error');
                     }
                 }
             }
             else if ($action == 'setact' && !$error) {
                     }
                 }
             }
             else if ($action == 'setact' && !$error) {
-                $script_name = get_input_value('_set', RCUBE_INPUT_GPC);
-                $result = $this->sieve->activate($script_name);
+                $script_name = get_input_value('_set', RCUBE_INPUT_GPC, true);
+                $result = $this->activate_script($script_name);
+                $kep14  = $this->rc->config->get('managesieve_kolab_master');
 
                 if ($result === true) {
 
                 if ($result === true) {
-                    $this->rc->output->set_env('active_set', $script_name);
+                    $this->rc->output->set_env('active_sets', $this->active);
                     $this->rc->output->show_message('managesieve.setactivated', 'confirmation');
                     $this->rc->output->show_message('managesieve.setactivated', 'confirmation');
-                    $this->rc->output->command('managesieve_reset');
-                    $_SESSION['managesieve_active'] = $script_name;
+                    $this->rc->output->command('managesieve_updatelist', 'setact',
+                        array('name' => $script_name, 'active' => true, 'all' => !$kep14));
                 } else {
                     $this->rc->output->show_message('managesieve.setactivateerror', 'error');
                 }
             }
             else if ($action == 'deact' && !$error) {
                 } else {
                     $this->rc->output->show_message('managesieve.setactivateerror', 'error');
                 }
             }
             else if ($action == 'deact' && !$error) {
-                $result = $this->sieve->deactivate();
+                $script_name = get_input_value('_set', RCUBE_INPUT_GPC, true);
+                $result = $this->deactivate_script($script_name);
 
                 if ($result === true) {
 
                 if ($result === true) {
-                    $this->rc->output->set_env('active_set', '');
+                    $this->rc->output->set_env('active_sets', $this->active);
                     $this->rc->output->show_message('managesieve.setdeactivated', 'confirmation');
                     $this->rc->output->show_message('managesieve.setdeactivated', 'confirmation');
-                    $this->rc->output->command('managesieve_reset');
-                    $_SESSION['managesieve_active'] = '';
+                    $this->rc->output->command('managesieve_updatelist', 'setact',
+                        array('name' => $script_name, 'active' => false));
                 } else {
                     $this->rc->output->show_message('managesieve.setdeactivateerror', 'error');
                 }
             }
             else if ($action == 'setdel' && !$error) {
                 } else {
                     $this->rc->output->show_message('managesieve.setdeactivateerror', 'error');
                 }
             }
             else if ($action == 'setdel' && !$error) {
-                $script_name = get_input_value('_set', RCUBE_INPUT_GPC);
-                $result = $this->sieve->remove($script_name);
+                $script_name = get_input_value('_set', RCUBE_INPUT_GPC, true);
+                $result = $this->remove_script($script_name);
 
                 if ($result === true) {
                     $this->rc->output->show_message('managesieve.setdeleted', 'confirmation');
 
                 if ($result === true) {
                     $this->rc->output->show_message('managesieve.setdeleted', 'confirmation');
-                    $this->rc->output->command('managesieve_reload');
+                    $this->rc->output->command('managesieve_updatelist', 'setdel',
+                        array('name' => $script_name));
                     $this->rc->session->remove('managesieve_current');
                 } else {
                     $this->rc->output->show_message('managesieve.setdeleteerror', 'error');
                 }
             }
             else if ($action == 'setget') {
                     $this->rc->session->remove('managesieve_current');
                 } else {
                     $this->rc->output->show_message('managesieve.setdeleteerror', 'error');
                 }
             }
             else if ($action == 'setget') {
-                $script_name = get_input_value('_set', RCUBE_INPUT_GPC);
+                $script_name = get_input_value('_set', RCUBE_INPUT_GPC, true);
                 $script = $this->sieve->get_script($script_name);
 
                 if (PEAR::isError($script))
                 $script = $this->sieve->get_script($script_name);
 
                 if (PEAR::isError($script))
@@ -281,14 +451,19 @@ class managesieve extends rcube_plugin
                 echo $script;
                 exit;
             }
                 echo $script;
                 exit;
             }
-            elseif ($action == 'ruleadd') {
+            else if ($action == 'list') {
+                $result = $this->list_rules();
+
+                $this->rc->output->command('managesieve_updatelist', 'list', array('list' => $result));
+            }
+            else if ($action == 'ruleadd') {
                 $rid = get_input_value('_rid', RCUBE_INPUT_GPC);
                 $id = $this->genid();
                 $content = $this->rule_div($fid, $id, false);
 
                 $this->rc->output->command('managesieve_rulefill', $content, $id, $rid);
             }
                 $rid = get_input_value('_rid', RCUBE_INPUT_GPC);
                 $id = $this->genid();
                 $content = $this->rule_div($fid, $id, false);
 
                 $this->rc->output->command('managesieve_rulefill', $content, $id, $rid);
             }
-            elseif ($action == 'actionadd') {
+            else if ($action == 'actionadd') {
                 $aid = get_input_value('_aid', RCUBE_INPUT_GPC);
                 $id = $this->genid();
                 $content = $this->action_div($fid, $id, false);
                 $aid = get_input_value('_aid', RCUBE_INPUT_GPC);
                 $id = $this->genid();
                 $content = $this->action_div($fid, $id, false);
@@ -298,25 +473,76 @@ class managesieve extends rcube_plugin
 
             $this->rc->output->send();
         }
 
             $this->rc->output->send();
         }
+        else if ($this->rc->task == 'mail') {
+            // Initialize the form
+            $rules = get_input_value('r', RCUBE_INPUT_GET);
+            if (!empty($rules)) {
+                $i = 0;
+                foreach ($rules as $rule) {
+                    list($header, $value) = explode(':', $rule, 2);
+                    $tests[$i] = array(
+                        'type' => 'contains',
+                        'test' => 'header',
+                        'arg1' => $header,
+                        'arg2' => $value,
+                    );
+                    $i++;
+                }
+
+                $this->form = array(
+                    'join'  => count($tests) > 1 ? 'allof' : 'anyof',
+                    'name'  => '',
+                    'tests' => $tests,
+                    'actions' => array(
+                        0 => array('type' => 'fileinto'),
+                        1 => array('type' => 'stop'),
+                    ),
+                );
+            }
+        }
 
         $this->managesieve_send();
     }
 
     function managesieve_save()
     {
 
         $this->managesieve_send();
     }
 
     function managesieve_save()
     {
+        // load localization
+        $this->add_texts('localization/', array('filters','managefilters'));
+
+        // include main js script
+        if ($this->api->output->type == 'html') {
+            $this->include_script('managesieve.js');
+        }
+
         // Init plugin and handle managesieve connection
         $error = $this->managesieve_start();
 
         // filters set add action
         if (!empty($_POST['_newset'])) {
         // Init plugin and handle managesieve connection
         $error = $this->managesieve_start();
 
         // filters set add action
         if (!empty($_POST['_newset'])) {
-            $name = get_input_value('_name', RCUBE_INPUT_POST);
-            $copy = get_input_value('_copy', RCUBE_INPUT_POST);
-            $from = get_input_value('_from', RCUBE_INPUT_POST);
-
-            if (!$name)
-                $error = 'managesieve.emptyname';
-            else if (mb_strlen($name)>128)
-                $error = 'managesieve.nametoolong';
+
+            $name       = get_input_value('_name', RCUBE_INPUT_POST, true);
+            $copy       = get_input_value('_copy', RCUBE_INPUT_POST, true);
+            $from       = get_input_value('_from', RCUBE_INPUT_POST);
+            $exceptions = $this->rc->config->get('managesieve_filename_exceptions');
+            $kolab      = $this->rc->config->get('managesieve_kolab_master');
+            $name_uc    = mb_strtolower($name);
+            $list       = $this->list_scripts();
+
+            if (!$name) {
+                $this->errors['name'] = $this->gettext('cannotbeempty');
+            }
+            else if (mb_strlen($name) > 128) {
+                $this->errors['name'] = $this->gettext('nametoolong');
+            }
+            else if (!empty($exceptions) && in_array($name, (array)$exceptions)) {
+                $this->errors['name'] = $this->gettext('namereserved');
+            }
+            else if (!empty($kolab) && in_array($name_uc, array('MASTER', 'USER', 'MANAGEMENT'))) {
+                $this->errors['name'] = $this->gettext('namereserved');
+            }
+            else if (in_array($name, $list)) {
+                $this->errors['name'] = $this->gettext('setexist');
+            }
             else if ($from == 'file') {
                 // from file
                 if (is_uploaded_file($_FILES['_file']['tmp_name'])) {
             else if ($from == 'file') {
                 // from file
                 if (is_uploaded_file($_FILES['_file']['tmp_name'])) {
@@ -325,13 +551,12 @@ class managesieve extends rcube_plugin
                     // for security don't save script directly
                     // check syntax before, like this...
                     $this->sieve->load_script($file);
                     // for security don't save script directly
                     // check syntax before, like this...
                     $this->sieve->load_script($file);
-                    if (!$this->sieve->save($name)) {
-                        $error = 'managesieve.setcreateerror';
+                    if (!$this->save_script($name)) {
+                        $this->errors['file'] = $this->gettext('setcreateerror');
                     }
                 }
                 else {  // upload failed
                     $err = $_FILES['_file']['error'];
                     }
                 }
                 else {  // upload failed
                     $err = $_FILES['_file']['error'];
-                    $error = true;
 
                     if ($err == UPLOAD_ERR_INI_SIZE || $err == UPLOAD_ERR_FORM_SIZE) {
                         $msg = rcube_label(array('name' => 'filesizeerror',
 
                     if ($err == UPLOAD_ERR_INI_SIZE || $err == UPLOAD_ERR_FORM_SIZE) {
                         $msg = rcube_label(array('name' => 'filesizeerror',
@@ -339,7 +564,7 @@ class managesieve extends rcube_plugin
                                 show_bytes(parse_bytes(ini_get('upload_max_filesize'))))));
                     }
                     else {
                                 show_bytes(parse_bytes(ini_get('upload_max_filesize'))))));
                     }
                     else {
-                        $error = 'fileuploaderror';
+                        $this->errors['file'] = $this->gettext('fileuploaderror');
                     }
                 }
             }
                     }
                 }
             }
@@ -347,12 +572,19 @@ class managesieve extends rcube_plugin
                 $error = 'managesieve.setcreateerror';
             }
 
                 $error = 'managesieve.setcreateerror';
             }
 
-            if (!$error) {
+            if (!$error && empty($this->errors)) {
+                // Find position of the new script on the list
+                $list[] = $name;
+                asort($list, SORT_LOCALE_STRING);
+                $list  = array_values($list);
+                $index = array_search($name, $list);
+
                 $this->rc->output->show_message('managesieve.setcreated', 'confirmation');
                 $this->rc->output->show_message('managesieve.setcreated', 'confirmation');
-                $this->rc->output->command('parent.managesieve_reload', $name);
+                $this->rc->output->command('parent.managesieve_updatelist', 'setadd',
+                    array('name' => $name, 'index' => $index));
             } else if ($msg) {
                 $this->rc->output->command('display_message', $msg, 'error');
             } else if ($msg) {
                 $this->rc->output->command('display_message', $msg, 'error');
-            } else {
+            } else if ($error) {
                 $this->rc->output->show_message($error, 'error');
             }
         }
                 $this->rc->output->show_message($error, 'error');
             }
         }
@@ -363,22 +595,27 @@ class managesieve extends rcube_plugin
             $join = trim(get_input_value('_join', RCUBE_INPUT_POST));
 
             // and arrays
             $join = trim(get_input_value('_join', RCUBE_INPUT_POST));
 
             // and arrays
-            $headers = $_POST['_header'];
-            $cust_headers = $_POST['_custom_header'];
-            $ops = $_POST['_rule_op'];
-            $sizeops = $_POST['_rule_size_op'];
-            $sizeitems = $_POST['_rule_size_item'];
-            $sizetargets = $_POST['_rule_size_target'];
-            $targets = $_POST['_rule_target'];
-            $act_types = $_POST['_action_type'];
-            $mailboxes = $_POST['_action_mailbox'];
-            $act_targets = $_POST['_action_target'];
-            $area_targets = $_POST['_action_target_area'];
-            $reasons = $_POST['_action_reason'];
-            $addresses = $_POST['_action_addresses'];
-            $days = $_POST['_action_days'];
-            $subject = $_POST['_action_subject'];
-            $flags = $_POST['_action_flags'];
+            $headers        = get_input_value('_header', RCUBE_INPUT_POST);
+            $cust_headers   = get_input_value('_custom_header', RCUBE_INPUT_POST);
+            $ops            = get_input_value('_rule_op', RCUBE_INPUT_POST);
+            $sizeops        = get_input_value('_rule_size_op', RCUBE_INPUT_POST);
+            $sizeitems      = get_input_value('_rule_size_item', RCUBE_INPUT_POST);
+            $sizetargets    = get_input_value('_rule_size_target', RCUBE_INPUT_POST);
+            $targets        = get_input_value('_rule_target', RCUBE_INPUT_POST, true);
+            $mods           = get_input_value('_rule_mod', RCUBE_INPUT_POST);
+            $mod_types      = get_input_value('_rule_mod_type', RCUBE_INPUT_POST);
+            $body_trans     = get_input_value('_rule_trans', RCUBE_INPUT_POST);
+            $body_types     = get_input_value('_rule_trans_type', RCUBE_INPUT_POST, true);
+            $comparators    = get_input_value('_rule_comp', RCUBE_INPUT_POST);
+            $act_types      = get_input_value('_action_type', RCUBE_INPUT_POST, true);
+            $mailboxes      = get_input_value('_action_mailbox', RCUBE_INPUT_POST, true);
+            $act_targets    = get_input_value('_action_target', RCUBE_INPUT_POST, true);
+            $area_targets   = get_input_value('_action_target_area', RCUBE_INPUT_POST, true);
+            $reasons        = get_input_value('_action_reason', RCUBE_INPUT_POST, true);
+            $addresses      = get_input_value('_action_addresses', RCUBE_INPUT_POST, true);
+            $days           = get_input_value('_action_days', RCUBE_INPUT_POST);
+            $subject        = get_input_value('_action_subject', RCUBE_INPUT_POST, true);
+            $flags          = get_input_value('_action_flags', RCUBE_INPUT_POST);
 
             // we need a "hack" for radiobuttons
             foreach ($sizeitems as $item)
 
             // we need a "hack" for radiobuttons
             foreach ($sizeitems as $item)
@@ -407,23 +644,101 @@ class managesieve extends rcube_plugin
             }
             else {
                 foreach ($headers as $idx => $header) {
             }
             else {
                 foreach ($headers as $idx => $header) {
-                    $header = $this->strip_value($header);
-                    $target = $this->strip_value($targets[$idx], true);
-                    $op     = $this->strip_value($ops[$idx]);
+                    $header     = $this->strip_value($header);
+                    $target     = $this->strip_value($targets[$idx], true);
+                    $operator   = $this->strip_value($ops[$idx]);
+                    $comparator = $this->strip_value($comparators[$idx]);
+
+                    if ($header == 'size') {
+                        $sizeop     = $this->strip_value($sizeops[$idx]);
+                        $sizeitem   = $this->strip_value($items[$idx]);
+                        $sizetarget = $this->strip_value($sizetargets[$idx]);
+
+                        $this->form['tests'][$i]['test'] = 'size';
+                        $this->form['tests'][$i]['type'] = $sizeop;
+                        $this->form['tests'][$i]['arg']  = $sizetarget;
+
+                        if ($sizetarget == '')
+                            $this->errors['tests'][$i]['sizetarget'] = $this->gettext('cannotbeempty');
+                        else if (!preg_match('/^[0-9]+(K|M|G)?$/i', $sizetarget.$sizeitem, $m)) {
+                            $this->errors['tests'][$i]['sizetarget'] = $this->gettext('forbiddenchars');
+                            $this->form['tests'][$i]['item'] = $sizeitem;
+                        }
+                        else
+                            $this->form['tests'][$i]['arg'] .= $m[1];
+                    }
+                    else if ($header == 'body') {
+                        $trans      = $this->strip_value($body_trans[$idx]);
+                        $trans_type = $this->strip_value($body_types[$idx], true);
 
 
-                    // normal header
-                    if (in_array($header, $this->headers)) {
-                        if (preg_match('/^not/', $op))
+                        if (preg_match('/^not/', $operator))
                             $this->form['tests'][$i]['not'] = true;
                             $this->form['tests'][$i]['not'] = true;
-                        $type = preg_replace('/^not/', '', $op);
+                        $type = preg_replace('/^not/', '', $operator);
+
+                        if ($type == 'exists') {
+                            $this->errors['tests'][$i]['op'] = true;
+                        }
+
+                        $this->form['tests'][$i]['test'] = 'body';
+                        $this->form['tests'][$i]['type'] = $type;
+                        $this->form['tests'][$i]['arg']  = $target;
+
+                        if ($target == '' && $type != 'exists')
+                            $this->errors['tests'][$i]['target'] = $this->gettext('cannotbeempty');
+                        else if (preg_match('/^(value|count)-/', $type) && !preg_match('/[0-9]+/', $target))
+                            $this->errors['tests'][$i]['target'] = $this->gettext('forbiddenchars');
+
+                        $this->form['tests'][$i]['part'] = $trans;
+                        if ($trans == 'content') {
+                            $this->form['tests'][$i]['content'] = $trans_type;
+                        }
+                    }
+                    else {
+                        $cust_header = $headers = $this->strip_value($cust_headers[$idx]);
+                        $mod      = $this->strip_value($mods[$idx]);
+                        $mod_type = $this->strip_value($mod_types[$idx]);
+
+                        if (preg_match('/^not/', $operator))
+                            $this->form['tests'][$i]['not'] = true;
+                        $type = preg_replace('/^not/', '', $operator);
+
+                        if ($header == '...') {
+                            $headers = preg_split('/[\s,]+/', $cust_header, -1, PREG_SPLIT_NO_EMPTY);
+
+                            if (!count($headers))
+                                $this->errors['tests'][$i]['header'] = $this->gettext('cannotbeempty');
+                            else {
+                                foreach ($headers as $hr)
+                                    if (!preg_match('/^[a-z0-9-]+$/i', $hr))
+                                        $this->errors['tests'][$i]['header'] = $this->gettext('forbiddenchars');
+                            }
+
+                            if (empty($this->errors['tests'][$i]['header']))
+                                $cust_header = (is_array($headers) && count($headers) == 1) ? $headers[0] : $headers;
+                        }
 
                         if ($type == 'exists') {
                             $this->form['tests'][$i]['test'] = 'exists';
 
                         if ($type == 'exists') {
                             $this->form['tests'][$i]['test'] = 'exists';
-                            $this->form['tests'][$i]['arg'] = $header;
+                            $this->form['tests'][$i]['arg'] = $header == '...' ? $cust_header : $header;
                         }
                         else {
                         }
                         else {
+                            $test   = 'header';
+                            $header = $header == '...' ? $cust_header : $header;
+
+                            if ($mod == 'address' || $mod == 'envelope') {
+                                $found = false;
+                                if (empty($this->errors['tests'][$i]['header'])) {
+                                    foreach ((array)$header as $hdr) {
+                                        if (!in_array(strtolower(trim($hdr)), $this->addr_headers))
+                                            $found = true;
+                                    }
+                                }
+                                if (!$found)
+                                    $test = $mod;
+                            }
+
                             $this->form['tests'][$i]['type'] = $type;
                             $this->form['tests'][$i]['type'] = $type;
-                            $this->form['tests'][$i]['test'] = 'header';
+                            $this->form['tests'][$i]['test'] = $test;
                             $this->form['tests'][$i]['arg1'] = $header;
                             $this->form['tests'][$i]['arg2'] = $target;
 
                             $this->form['tests'][$i]['arg1'] = $header;
                             $this->form['tests'][$i]['arg2'] = $target;
 
@@ -431,65 +746,20 @@ class managesieve extends rcube_plugin
                                 $this->errors['tests'][$i]['target'] = $this->gettext('cannotbeempty');
                             else if (preg_match('/^(value|count)-/', $type) && !preg_match('/[0-9]+/', $target))
                                 $this->errors['tests'][$i]['target'] = $this->gettext('forbiddenchars');
                                 $this->errors['tests'][$i]['target'] = $this->gettext('cannotbeempty');
                             else if (preg_match('/^(value|count)-/', $type) && !preg_match('/[0-9]+/', $target))
                                 $this->errors['tests'][$i]['target'] = $this->gettext('forbiddenchars');
+
+                            if ($mod) {
+                                $this->form['tests'][$i]['part'] = $mod_type;
+                            }
                         }
                     }
                         }
                     }
-                    else
-                        switch ($header) {
-                        case 'size':
-                            $sizeop     = $this->strip_value($sizeops[$idx]);
-                            $sizeitem   = $this->strip_value($items[$idx]);
-                            $sizetarget = $this->strip_value($sizetargets[$idx]);
-
-                            $this->form['tests'][$i]['test'] = 'size';
-                            $this->form['tests'][$i]['type'] = $sizeop;
-                            $this->form['tests'][$i]['arg']  = $sizetarget.$sizeitem;
-
-                            if ($sizetarget == '')
-                                $this->errors['tests'][$i]['sizetarget'] = $this->gettext('cannotbeempty');
-                            else if (!preg_match('/^[0-9]+(K|M|G)*$/i', $sizetarget))
-                                $this->errors['tests'][$i]['sizetarget'] = $this->gettext('forbiddenchars');
-                            break;
-                        case '...':
-                            $cust_header = $headers = $this->strip_value($cust_headers[$idx]);
-
-                            if (preg_match('/^not/', $op))
-                                $this->form['tests'][$i]['not'] = true;
-                            $type = preg_replace('/^not/', '', $op);
-
-                            if ($cust_header == '')
-                                $this->errors['tests'][$i]['header'] = $this->gettext('cannotbeempty');
-                            else {
-                                $headers = preg_split('/[\s,]+/', $cust_header, -1, PREG_SPLIT_NO_EMPTY);
-
-                                if (!count($headers))
-                                    $this->errors['tests'][$i]['header'] = $this->gettext('cannotbeempty');
-                                else {
-                                    foreach ($headers as $hr)
-                                        if (!preg_match('/^[a-z0-9-]+$/i', $hr))
-                                            $this->errors['tests'][$i]['header'] = $this->gettext('forbiddenchars');
-                                }
-                            }
 
 
-                            if (empty($this->errors['tests'][$i]['header']))
-                                $cust_header = (is_array($headers) && count($headers) == 1) ? $headers[0] : $headers;
+                    if ($header != 'size' && $comparator) {
+                        if (preg_match('/^(value|count)/', $this->form['tests'][$i]['type']))
+                            $comparator = 'i;ascii-numeric';
+
+                        $this->form['tests'][$i]['comparator'] = $comparator;
+                    }
 
 
-                            if ($type == 'exists') {
-                                $this->form['tests'][$i]['test'] = 'exists';
-                                $this->form['tests'][$i]['arg']  = $cust_header;
-                            }
-                            else {
-                                $this->form['tests'][$i]['test'] = 'header';
-                                $this->form['tests'][$i]['type'] = $type;
-                                $this->form['tests'][$i]['arg1'] = $cust_header;
-                                $this->form['tests'][$i]['arg2'] = $target;
-
-                                if ($target == '')
-                                    $this->errors['tests'][$i]['target'] = $this->gettext('cannotbeempty');
-                                else if (preg_match('/^(value|count)-/', $type) && !preg_match('/[0-9]+/', $target))
-                                    $this->errors['tests'][$i]['target'] = $this->gettext('forbiddenchars');
-                            }
-                            break;
-                        }
                     $i++;
                 }
             }
                     $i++;
                 }
             }
@@ -583,7 +853,7 @@ class managesieve extends rcube_plugin
                 $i++;
             }
 
                 $i++;
             }
 
-            if (!$this->errors) {
+            if (!$this->errors && !$error) {
                 // zapis skryptu
                 if (!isset($this->script[$fid])) {
                     $fid = $this->sieve->script->add_rule($this->form);
                 // zapis skryptu
                 if (!isset($this->script[$fid])) {
                     $fid = $this->sieve->script->add_rule($this->form);
@@ -592,15 +862,23 @@ class managesieve extends rcube_plugin
                     $fid = $this->sieve->script->update_rule($fid, $this->form);
 
                 if ($fid !== false)
                     $fid = $this->sieve->script->update_rule($fid, $this->form);
 
                 if ($fid !== false)
-                    $save = $this->sieve->save();
+                    $save = $this->save_script();
 
                 if ($save && $fid !== false) {
                     $this->rc->output->show_message('managesieve.filtersaved', 'confirmation');
 
                 if ($save && $fid !== false) {
                     $this->rc->output->show_message('managesieve.filtersaved', 'confirmation');
-                    $this->rc->output->add_script(
-                        sprintf("rcmail.managesieve_updatelist('%s', '%s', %d, %d);",
-                            isset($new) ? 'add' : 'update', Q($this->form['name']),
-                            $fid, $this->form['disabled']),
-                        'foot');
+                    if ($this->rc->task != 'mail') {
+                        $this->rc->output->command('parent.managesieve_updatelist',
+                            isset($new) ? 'add' : 'update',
+                            array(
+                                'name' => Q($this->form['name']),
+                                'id' => $fid,
+                                'disabled' => $this->form['disabled']
+                        ));
+                    }
+                    else {
+                        $this->rc->output->command('managesieve_dialog_close');
+                        $this->rc->output->send('iframe');
+                    }
                 }
                 else {
                     $this->rc->output->show_message('managesieve.filtersaveerror', 'error');
                 }
                 else {
                     $this->rc->output->show_message('managesieve.filtersaveerror', 'error');
@@ -636,14 +914,9 @@ class managesieve extends rcube_plugin
             $attrib['id'] = 'rcmfilterslist';
 
         // define list of cols to be displayed
             $attrib['id'] = 'rcmfilterslist';
 
         // define list of cols to be displayed
-        $a_show_cols = array('managesieve.filtername');
+        $a_show_cols = array('name');
 
 
-        foreach($this->script as $idx => $filter)
-            $result[] = array(
-                'managesieve.filtername' => $filter['name'],
-                'id' => $idx,
-                'class' => $filter['disabled'] ? 'disabled' : '',
-            );
+        $result = $this->list_rules();
 
         // create XHTML table
         $out = rcube_table_output($attrib, $result, $a_show_cols, 'id');
 
         // create XHTML table
         $out = rcube_table_output($attrib, $result, $a_show_cols, 'id');
@@ -659,35 +932,56 @@ class managesieve extends rcube_plugin
     }
 
     // return the filters list as <SELECT>
     }
 
     // return the filters list as <SELECT>
-    function filtersets_list($attrib)
+    function filtersets_list($attrib, $no_env = false)
     {
         // add id to message list table if not specified
         if (!strlen($attrib['id']))
             $attrib['id'] = 'rcmfiltersetslist';
 
     {
         // add id to message list table if not specified
         if (!strlen($attrib['id']))
             $attrib['id'] = 'rcmfiltersetslist';
 
-        $list = $this->sieve->get_scripts();
-        $active = $this->sieve->get_active();
-
-        $select = new html_select(array('name' => '_set', 'id' => $attrib['id'],
-            'onchange' => 'rcmail.managesieve_set()'));
+        $list = $this->list_scripts();
 
         if ($list) {
             asort($list, SORT_LOCALE_STRING);
 
         if ($list) {
             asort($list, SORT_LOCALE_STRING);
+        }
+
+        if (!empty($attrib['type']) && $attrib['type'] == 'list') {
+            // define list of cols to be displayed
+            $a_show_cols = array('name');
+
+            if ($list) {
+                foreach ($list as $idx => $set) {
+                    $scripts['S'.$idx] = $set;
+                    $result[] = array(
+                        'name' => Q($set),
+                        'id' => 'S'.$idx,
+                        'class' => !in_array($set, $this->active) ? 'disabled' : '',
+                    );
+                }
+            }
+
+            // create XHTML table
+            $out = rcube_table_output($attrib, $result, $a_show_cols, 'id');
 
 
-            foreach ($list as $set)
-                $select->add($set . ($set == $active ? ' ('.$this->gettext('active').')' : ''), $set);
+            $this->rc->output->set_env('filtersets', $scripts);
+            $this->rc->output->include_script('list.js');
         }
         }
+        else {
+            $select = new html_select(array('name' => '_set', 'id' => $attrib['id'],
+                'onchange' => $this->rc->task != 'mail' ? 'rcmail.managesieve_set()' : ''));
+
+            if ($list) {
+                foreach ($list as $set)
+                    $select->add($set, $set);
+            }
 
 
-        $out = $select->show($this->sieve->current);
+            $out = $select->show($this->sieve->current);
+        }
 
         // set client env
 
         // set client env
-        $this->rc->output->add_gui_object('filtersetslist', $attrib['id']);
-        $this->rc->output->add_label(
-            'managesieve.setdeleteconfirm',
-            'managesieve.active',
-            'managesieve.filtersetact',
-            'managesieve.filtersetdeact'
-        );
+        if (!$no_env) {
+            $this->rc->output->add_gui_object('filtersetslist', $attrib['id']);
+            $this->rc->output->add_label('managesieve.setdeleteconfirm');
+        }
 
         return $out;
     }
 
         return $out;
     }
@@ -737,16 +1031,18 @@ class managesieve extends rcube_plugin
         $out .= sprintf('<label for="%s">%s</label> ', 'from_none', Q($this->gettext('none')));
 
         // filters set list
         $out .= sprintf('<label for="%s">%s</label> ', 'from_none', Q($this->gettext('none')));
 
         // filters set list
-        $list   = $this->sieve->get_scripts();
-        $active = $this->sieve->get_active();
-
+        $list   = $this->list_scripts();
         $select = new html_select(array('name' => '_copy', 'id' => '_copy'));
 
         if (is_array($list)) {
             asort($list, SORT_LOCALE_STRING);
 
         $select = new html_select(array('name' => '_copy', 'id' => '_copy'));
 
         if (is_array($list)) {
             asort($list, SORT_LOCALE_STRING);
 
-            foreach ($list as $set)
-                $select->add($set . ($set == $active ? ' ('.$this->gettext('active').')' : ''), $set);
+            if (!$copy)
+                $copy = $_SESSION['managesieve_current'];
+
+            foreach ($list as $set) {
+                $select->add($set, $set);
+            }
 
             $out .= '<br /><input type="radio" id="from_set" name="_from" value="set"'
                 .($selected=='set' ? ' checked="checked"' : '').'></input>';
 
             $out .= '<br /><input type="radio" id="from_set" name="_from" value="set"'
                 .($selected=='set' ? ' checked="checked"' : '').'></input>';
@@ -756,7 +1052,7 @@ class managesieve extends rcube_plugin
 
         // script upload box
         $upload = new html_inputfield(array('name' => '_file', 'id' => '_file', 'size' => 30,
 
         // script upload box
         $upload = new html_inputfield(array('name' => '_file', 'id' => '_file', 'size' => 30,
-            'type' => 'file', 'class' => ($this->errors['name'] ? 'error' : '')));
+            'type' => 'file', 'class' => ($this->errors['file'] ? 'error' : '')));
 
         $out .= '<br /><input type="radio" id="from_file" name="_from" value="file"'
             .($selected=='file' ? ' checked="checked"' : '').'></input>';
 
         $out .= '<br /><input type="radio" id="from_file" name="_from" value="file"'
             .($selected=='file' ? ' checked="checked"' : '').'></input>';
@@ -766,6 +1062,13 @@ class managesieve extends rcube_plugin
 
         $this->rc->output->add_gui_object('sieveform', 'filtersetform');
 
 
         $this->rc->output->add_gui_object('sieveform', 'filtersetform');
 
+        if ($this->errors['name'])
+            $this->add_tip('_name', $this->errors['name'], true);
+        if ($this->errors['file'])
+            $this->add_tip('_file', $this->errors['file'], true);
+
+        $this->print_tips();
+
         return $out;
     }
 
         return $out;
     }
 
@@ -803,10 +1106,17 @@ class managesieve extends rcube_plugin
         else
             $input_name = $input_name->show();
 
         else
             $input_name = $input_name->show();
 
-        $out .= sprintf("\n<label for=\"%s\"><b>%s:</b></label> %s<br /><br />\n",
+        $out .= sprintf("\n<label for=\"%s\"><b>%s:</b></label> %s\n",
             $field_id, Q($this->gettext('filtername')), $input_name);
 
             $field_id, Q($this->gettext('filtername')), $input_name);
 
-        $out .= '<fieldset><legend>' . Q($this->gettext('messagesrules')) . "</legend>\n";
+        // filter set selector
+        if ($this->rc->task == 'mail') {
+            $out .= sprintf("\n&nbsp;<label for=\"%s\"><b>%s:</b></label> %s\n",
+                $field_id, Q($this->gettext('filterset')),
+                $this->filtersets_list(array('id' => 'sievescriptname'), true));
+        }
+
+        $out .= '<br /><br /><fieldset><legend>' . Q($this->gettext('messagesrules')) . "</legend>\n";
 
         // any, allof, anyof radio buttons
         $field_id = '_allof';
 
         // any, allof, anyof radio buttons
         $field_id = '_allof';
@@ -882,50 +1192,60 @@ class managesieve extends rcube_plugin
         $rule     = isset($this->form) ? $this->form['tests'][$id] : $this->script[$fid]['tests'][$id];
         $rows_num = isset($this->form) ? sizeof($this->form['tests']) : sizeof($this->script[$fid]['tests']);
 
         $rule     = isset($this->form) ? $this->form['tests'][$id] : $this->script[$fid]['tests'][$id];
         $rows_num = isset($this->form) ? sizeof($this->form['tests']) : sizeof($this->script[$fid]['tests']);
 
-        $out = $div ? '<div class="rulerow" id="rulerow' .$id .'">'."\n" : '';
-
-        $out .= '<table><tr><td class="rowactions">';
-
         // headers select
         $select_header = new html_select(array('name' => "_header[]", 'id' => 'header'.$id,
             'onchange' => 'rule_header_select(' .$id .')'));
         foreach($this->headers as $name => $val)
             $select_header->add(Q($this->gettext($name)), Q($val));
         // headers select
         $select_header = new html_select(array('name' => "_header[]", 'id' => 'header'.$id,
             'onchange' => 'rule_header_select(' .$id .')'));
         foreach($this->headers as $name => $val)
             $select_header->add(Q($this->gettext($name)), Q($val));
+        if (in_array('body', $this->exts))
+            $select_header->add(Q($this->gettext('body')), 'body');
         $select_header->add(Q($this->gettext('size')), 'size');
         $select_header->add(Q($this->gettext('...')), '...');
 
         // TODO: list arguments
         $select_header->add(Q($this->gettext('size')), 'size');
         $select_header->add(Q($this->gettext('...')), '...');
 
         // TODO: list arguments
+        $aout = '';
 
 
-        if ((isset($rule['test']) && $rule['test'] == 'header')
-            && !is_array($rule['arg1']) && in_array($rule['arg1'], $this->headers))
-            $out .= $select_header->show($rule['arg1']);
+        if ((isset($rule['test']) && in_array($rule['test'], array('header', 'address', 'envelope')))
+            && !is_array($rule['arg1']) && in_array($rule['arg1'], $this->headers)
+        ) {
+            $aout .= $select_header->show($rule['arg1']);
+        }
         else if ((isset($rule['test']) && $rule['test'] == 'exists')
         else if ((isset($rule['test']) && $rule['test'] == 'exists')
-            && !is_array($rule['arg']) && in_array($rule['arg'], $this->headers))
-            $out .= $select_header->show($rule['arg']);
+            && !is_array($rule['arg']) && in_array($rule['arg'], $this->headers)
+        ) {
+            $aout .= $select_header->show($rule['arg']);
+        }
         else if (isset($rule['test']) && $rule['test'] == 'size')
         else if (isset($rule['test']) && $rule['test'] == 'size')
-            $out .= $select_header->show('size');
+            $aout .= $select_header->show('size');
+        else if (isset($rule['test']) && $rule['test'] == 'body')
+            $aout .= $select_header->show('body');
         else if (isset($rule['test']) && $rule['test'] != 'true')
         else if (isset($rule['test']) && $rule['test'] != 'true')
-            $out .= $select_header->show('...');
+            $aout .= $select_header->show('...');
         else
         else
-            $out .= $select_header->show();
-
-        $out .= '</td><td class="rowtargets">';
+            $aout .= $select_header->show();
 
 
-        if ((isset($rule['test']) && $rule['test'] == 'header')
-            && (is_array($rule['arg1']) || !in_array($rule['arg1'], $this->headers)))
-            $custom = is_array($rule['arg1']) ? implode(', ', $rule['arg1']) : $rule['arg1'];
-        else if ((isset($rule['test']) && $rule['test'] == 'exists')
-            && (is_array($rule['arg']) || !in_array($rule['arg'], $this->headers)))
-            $custom = is_array($rule['arg']) ? implode(', ', $rule['arg']) : $rule['arg'];
+        if (isset($rule['test']) && in_array($rule['test'], array('header', 'address', 'envelope'))) {
+            if (is_array($rule['arg1']))
+                $custom = implode(', ', $rule['arg1']);
+            else if (!in_array($rule['arg1'], $this->headers))
+                $custom = $rule['arg1'];
+        }
+        else if (isset($rule['test']) && $rule['test'] == 'exists') {
+            if (is_array($rule['arg']))
+                $custom = implode(', ', $rule['arg']);
+            else if (!in_array($rule['arg'], $this->headers))
+                $custom = $rule['arg'];
+        }
 
 
-        $out .= '<div id="custom_header' .$id. '" style="display:' .(isset($custom) ? 'inline' : 'none'). '">
+        $tout = '<div id="custom_header' .$id. '" style="display:' .(isset($custom) ? 'inline' : 'none'). '">
             <input type="text" name="_custom_header[]" id="custom_header_i'.$id.'" '
             . $this->error_class($id, 'test', 'header', 'custom_header_i')
             <input type="text" name="_custom_header[]" id="custom_header_i'.$id.'" '
             . $this->error_class($id, 'test', 'header', 'custom_header_i')
-            .' value="' .Q($custom). '" size="20" />&nbsp;</div>' . "\n";
+            .' value="' .Q($custom). '" size="15" />&nbsp;</div>' . "\n";
 
         // matching type select (operator)
         $select_op = new html_select(array('name' => "_rule_op[]", 'id' => 'rule_op'.$id,
             'style' => 'display:' .($rule['test']!='size' ? 'inline' : 'none'),
 
         // matching type select (operator)
         $select_op = new html_select(array('name' => "_rule_op[]", 'id' => 'rule_op'.$id,
             'style' => 'display:' .($rule['test']!='size' ? 'inline' : 'none'),
+            'class' => 'operator_selector',
             'onchange' => 'rule_op_select('.$id.')'));
         $select_op->add(Q($this->gettext('filtercontains')), 'contains');
         $select_op->add(Q($this->gettext('filternotcontains')), 'notcontains');
             'onchange' => 'rule_op_select('.$id.')'));
         $select_op->add(Q($this->gettext('filtercontains')), 'contains');
         $select_op->add(Q($this->gettext('filternotcontains')), 'notcontains');
@@ -935,54 +1255,64 @@ class managesieve extends rcube_plugin
         $select_op->add(Q($this->gettext('filternotexists')), 'notexists');
         $select_op->add(Q($this->gettext('filtermatches')), 'matches');
         $select_op->add(Q($this->gettext('filternotmatches')), 'notmatches');
         $select_op->add(Q($this->gettext('filternotexists')), 'notexists');
         $select_op->add(Q($this->gettext('filtermatches')), 'matches');
         $select_op->add(Q($this->gettext('filternotmatches')), 'notmatches');
-               if (in_array('regex', $this->exts)) {
+        if (in_array('regex', $this->exts)) {
             $select_op->add(Q($this->gettext('filterregex')), 'regex');
             $select_op->add(Q($this->gettext('filternotregex')), 'notregex');
         }
             $select_op->add(Q($this->gettext('filterregex')), 'regex');
             $select_op->add(Q($this->gettext('filternotregex')), 'notregex');
         }
-               if (in_array('relational', $this->exts)) {
-                       $select_op->add(Q($this->gettext('countisgreaterthan')), 'count-gt');
-                       $select_op->add(Q($this->gettext('countisgreaterthanequal')), 'count-ge');
-                       $select_op->add(Q($this->gettext('countislessthan')), 'count-lt');
-                       $select_op->add(Q($this->gettext('countislessthanequal')), 'count-le');
-                       $select_op->add(Q($this->gettext('countequals')), 'count-eq');
-                       $select_op->add(Q($this->gettext('countnotequals')), 'count-ne');
-                       $select_op->add(Q($this->gettext('valueisgreaterthan')), 'value-gt');
-                       $select_op->add(Q($this->gettext('valueisgreaterthanequal')), 'value-ge');
-                       $select_op->add(Q($this->gettext('valueislessthan')), 'value-lt');
-                       $select_op->add(Q($this->gettext('valueislessthanequal')), 'value-le');
-                       $select_op->add(Q($this->gettext('valueequals')), 'value-eq');
-                       $select_op->add(Q($this->gettext('valuenotequals')), 'value-ne');
-               }
+        if (in_array('relational', $this->exts)) {
+            $select_op->add(Q($this->gettext('countisgreaterthan')), 'count-gt');
+            $select_op->add(Q($this->gettext('countisgreaterthanequal')), 'count-ge');
+            $select_op->add(Q($this->gettext('countislessthan')), 'count-lt');
+            $select_op->add(Q($this->gettext('countislessthanequal')), 'count-le');
+            $select_op->add(Q($this->gettext('countequals')), 'count-eq');
+            $select_op->add(Q($this->gettext('countnotequals')), 'count-ne');
+            $select_op->add(Q($this->gettext('valueisgreaterthan')), 'value-gt');
+            $select_op->add(Q($this->gettext('valueisgreaterthanequal')), 'value-ge');
+            $select_op->add(Q($this->gettext('valueislessthan')), 'value-lt');
+            $select_op->add(Q($this->gettext('valueislessthanequal')), 'value-le');
+            $select_op->add(Q($this->gettext('valueequals')), 'value-eq');
+            $select_op->add(Q($this->gettext('valuenotequals')), 'value-ne');
+        }
 
         // target input (TODO: lists)
 
 
         // target input (TODO: lists)
 
-        if ($rule['test'] == 'header') {
-            $out .= $select_op->show(($rule['not'] ? 'not' : '').$rule['type']);
+        if (in_array($rule['test'], array('header', 'address', 'envelope'))) {
+            $test   = ($rule['not'] ? 'not' : '').($rule['type'] ? $rule['type'] : 'is');
             $target = $rule['arg2'];
         }
             $target = $rule['arg2'];
         }
+        else if ($rule['test'] == 'body') {
+            $test   = ($rule['not'] ? 'not' : '').($rule['type'] ? $rule['type'] : 'is');
+            $target = $rule['arg'];
+        }
         else if ($rule['test'] == 'size') {
         else if ($rule['test'] == 'size') {
-            $out .= $select_op->show();
-            if (preg_match('/^([0-9]+)(K|M|G)*$/', $rule['arg'], $matches)) {
+            $test   = '';
+            $target = '';
+            if (preg_match('/^([0-9]+)(K|M|G)?$/', $rule['arg'], $matches)) {
                 $sizetarget = $matches[1];
                 $sizeitem = $matches[2];
             }
                 $sizetarget = $matches[1];
                 $sizeitem = $matches[2];
             }
+            else {
+                $sizetarget = $rule['arg'];
+                $sizeitem = $rule['item'];
+            }
         }
         else {
         }
         else {
-            $out .= $select_op->show(($rule['not'] ? 'not' : '').$rule['test']);
-            $target = '';
+            $test   = ($rule['not'] ? 'not' : '').$rule['test'];
+            $target =  '';
         }
 
         }
 
-        $out .= '<input type="text" name="_rule_target[]" id="rule_target' .$id. '"
+        $tout .= $select_op->show($test);
+        $tout .= '<input type="text" name="_rule_target[]" id="rule_target' .$id. '"
             value="' .Q($target). '" size="20" ' . $this->error_class($id, 'test', 'target', 'rule_target')
             . ' style="display:' . ($rule['test']!='size' && $rule['test'] != 'exists' ? 'inline' : 'none') . '" />'."\n";
 
         $select_size_op = new html_select(array('name' => "_rule_size_op[]", 'id' => 'rule_size_op'.$id));
             value="' .Q($target). '" size="20" ' . $this->error_class($id, 'test', 'target', 'rule_target')
             . ' style="display:' . ($rule['test']!='size' && $rule['test'] != 'exists' ? 'inline' : 'none') . '" />'."\n";
 
         $select_size_op = new html_select(array('name' => "_rule_size_op[]", 'id' => 'rule_size_op'.$id));
-        $select_size_op->add(Q($this->gettext('filterunder')), 'under');
         $select_size_op->add(Q($this->gettext('filterover')), 'over');
         $select_size_op->add(Q($this->gettext('filterover')), 'over');
+        $select_size_op->add(Q($this->gettext('filterunder')), 'under');
 
 
-        $out .= '<div id="rule_size' .$id. '" style="display:' . ($rule['test']=='size' ? 'inline' : 'none') .'">';
-        $out .= $select_size_op->show($rule['test']=='size' ? $rule['type'] : '');
-        $out .= '<input type="text" name="_rule_size_target[]" id="rule_size_i'.$id.'" value="'.$sizetarget.'" size="10" ' 
+        $tout .= '<div id="rule_size' .$id. '" style="display:' . ($rule['test']=='size' ? 'inline' : 'none') .'">';
+        $tout .= $select_size_op->show($rule['test']=='size' ? $rule['type'] : '');
+        $tout .= '<input type="text" name="_rule_size_target[]" id="rule_size_i'.$id.'" value="'.$sizetarget.'" size="10" ' 
             . $this->error_class($id, 'test', 'sizetarget', 'rule_size_i') .' />
             <input type="radio" name="_rule_size_item['.$id.']" value=""'
                 . (!$sizeitem ? ' checked="checked"' : '') .' class="radio" />'.rcube_label('B').'
             . $this->error_class($id, 'test', 'sizetarget', 'rule_size_i') .' />
             <input type="radio" name="_rule_size_item['.$id.']" value=""'
                 . (!$sizeitem ? ' checked="checked"' : '') .' class="radio" />'.rcube_label('B').'
@@ -992,17 +1322,92 @@ class managesieve extends rcube_plugin
                 . ($sizeitem=='M' ? ' checked="checked"' : '') .' class="radio" />'.rcube_label('MB').'
             <input type="radio" name="_rule_size_item['.$id.']" value="G"'
                 . ($sizeitem=='G' ? ' checked="checked"' : '') .' class="radio" />'.rcube_label('GB');
                 . ($sizeitem=='M' ? ' checked="checked"' : '') .' class="radio" />'.rcube_label('MB').'
             <input type="radio" name="_rule_size_item['.$id.']" value="G"'
                 . ($sizeitem=='G' ? ' checked="checked"' : '') .' class="radio" />'.rcube_label('GB');
-        $out .= '</div>';
+        $tout .= '</div>';
+
+        // Advanced modifiers (address, envelope)
+        $select_mod = new html_select(array('name' => "_rule_mod[]", 'id' => 'rule_mod_op'.$id,
+            'onchange' => 'rule_mod_select(' .$id .')'));
+        $select_mod->add(Q($this->gettext('none')), '');
+        $select_mod->add(Q($this->gettext('address')), 'address');
+        if (in_array('envelope', $this->exts))
+            $select_mod->add(Q($this->gettext('envelope')), 'envelope');
+
+        $select_type = new html_select(array('name' => "_rule_mod_type[]", 'id' => 'rule_mod_type'.$id));
+        $select_type->add(Q($this->gettext('allparts')), 'all');
+        $select_type->add(Q($this->gettext('domain')), 'domain');
+        $select_type->add(Q($this->gettext('localpart')), 'localpart');
+        if (in_array('subaddress', $this->exts)) {
+            $select_type->add(Q($this->gettext('user')), 'user');
+            $select_type->add(Q($this->gettext('detail')), 'detail');
+        }
+
+        $need_mod = $rule['test'] != 'size' && $rule['test'] != 'body';
+        $mout = '<div id="rule_mod' .$id. '" class="adv" style="display:' . ($need_mod ? 'block' : 'none') .'">';
+        $mout .= ' <span>';
+        $mout .= Q($this->gettext('modifier')) . ' ';
+        $mout .= $select_mod->show($rule['test']);
+        $mout .= '</span>';
+        $mout .= ' <span id="rule_mod_type' . $id . '"';
+        $mout .= ' style="display:' . (in_array($rule['test'], array('address', 'envelope')) ? 'inline' : 'none') .'">';
+        $mout .= Q($this->gettext('modtype')) . ' ';
+        $mout .= $select_type->show($rule['part']);
+        $mout .= '</span>';
+        $mout .= '</div>';
+
+        // Advanced modifiers (body transformations)
+        $select_mod = new html_select(array('name' => "_rule_trans[]", 'id' => 'rule_trans_op'.$id,
+            'onchange' => 'rule_trans_select(' .$id .')'));
+        $select_mod->add(Q($this->gettext('text')), 'text');
+        $select_mod->add(Q($this->gettext('undecoded')), 'raw');
+        $select_mod->add(Q($this->gettext('contenttype')), 'content');
+
+        $mout .= '<div id="rule_trans' .$id. '" class="adv" style="display:' . ($rule['test'] == 'body' ? 'block' : 'none') .'">';
+        $mout .= ' <span>';
+        $mout .= Q($this->gettext('modifier')) . ' ';
+        $mout .= $select_mod->show($rule['part']);
+        $mout .= '<input type="text" name="_rule_trans_type[]" id="rule_trans_type'.$id
+            . '" value="'.(is_array($rule['content']) ? implode(',', $rule['content']) : $rule['content'])
+            .'" size="20" style="display:' . ($rule['part'] == 'content' ? 'inline' : 'none') .'"'
+            . $this->error_class($id, 'test', 'part', 'rule_trans_type') .' />';
+        $mout .= '</span>';
+        $mout .= '</div>';
+
+        // Advanced modifiers (body transformations)
+        $select_comp = new html_select(array('name' => "_rule_comp[]", 'id' => 'rule_comp_op'.$id));
+        $select_comp->add(Q($this->gettext('default')), '');
+        $select_comp->add(Q($this->gettext('octet')), 'i;octet');
+        $select_comp->add(Q($this->gettext('asciicasemap')), 'i;ascii-casemap');
+        if (in_array('comparator-i;ascii-numeric', $this->exts)) {
+            $select_comp->add(Q($this->gettext('asciinumeric')), 'i;ascii-numeric');
+        }
+
+        $mout .= '<div id="rule_comp' .$id. '" class="adv" style="display:' . ($rule['test'] != 'size' ? 'block' : 'none') .'">';
+        $mout .= ' <span>';
+        $mout .= Q($this->gettext('comparator')) . ' ';
+        $mout .= $select_comp->show($rule['comparator']);
+        $mout .= '</span>';
+        $mout .= '</div>';
+
+        // Build output table
+        $out = $div ? '<div class="rulerow" id="rulerow' .$id .'">'."\n" : '';
+        $out .= '<table><tr>';
+        $out .= '<td class="advbutton">';
+        $out .= '<a href="#" id="ruleadv' . $id .'" title="'. Q($this->gettext('advancedopts')). '"
+            onclick="rule_adv_switch(' . $id .', this)" class="show">&nbsp;&nbsp;</a>';
+        $out .= '</td>';
+        $out .= '<td class="rowactions">' . $aout . '</td>';
+        $out .= '<td class="rowtargets">' . $tout . "\n";
+        $out .= '<div id="rule_advanced' .$id. '" style="display:none">' . $mout . '</div>';
         $out .= '</td>';
 
         // add/del buttons
         $out .= '<td class="rowbuttons">';
         $out .= '</td>';
 
         // add/del buttons
         $out .= '<td class="rowbuttons">';
-        $out .= '<input type="button" id="ruleadd' . $id .'" value="'. Q($this->gettext('add')). '"
-            onclick="rcmail.managesieve_ruleadd(' . $id .')" class="button" /> ';
-        $out .= '<input type="button" id="ruledel' . $id .'" value="'. Q($this->gettext('del')). '"
-            onclick="rcmail.managesieve_ruledel(' . $id .')" class="button' . ($rows_num<2 ? ' disabled' : '') .'"'
-            . ($rows_num<2 ? ' disabled="disabled"' : '') .' />';
-        $out .= '</td></tr></table>';
+        $out .= '<a href="#" id="ruleadd' . $id .'" title="'. Q($this->gettext('add')). '"
+            onclick="rcmail.managesieve_ruleadd(' . $id .')" class="button add"></a>';
+        $out .= '<a href="#" id="ruledel' . $id .'" title="'. Q($this->gettext('del')). '"
+            onclick="rcmail.managesieve_ruledel(' . $id .')" class="button del' . ($rows_num<2 ? ' disabled' : '') .'"></a>';
+        $out .= '</td>';
+        $out .= '</tr></table>';
 
         $out .= $div ? "</div>\n" : '';
 
 
         $out .= $div ? "</div>\n" : '';
 
@@ -1019,7 +1424,7 @@ class managesieve extends rcube_plugin
         $out .= '<table><tr><td class="rowactions">';
 
         // action select
         $out .= '<table><tr><td class="rowactions">';
 
         // action select
-        $select_action = new html_select(array('name' => "_action_type[]", 'id' => 'action_type'.$id,
+        $select_action = new html_select(array('name' => "_action_type[$id]", 'id' => 'action_type'.$id,
             'onchange' => 'action_type_select(' .$id .')'));
         if (in_array('fileinto', $this->exts))
             $select_action->add(Q($this->gettext('messagemoveto')), 'fileinto');
             'onchange' => 'action_type_select(' .$id .')'));
         if (in_array('fileinto', $this->exts))
             $select_action->add(Q($this->gettext('messagemoveto')), 'fileinto');
@@ -1053,12 +1458,12 @@ class managesieve extends rcube_plugin
         // actions target inputs
         $out .= '<td class="rowtargets">';
         // shared targets
         // actions target inputs
         $out .= '<td class="rowtargets">';
         // shared targets
-        $out .= '<input type="text" name="_action_target[]" id="action_target' .$id. '" '
-            .'value="' .($action['type']=='redirect' ? Q($action['target'], 'strict', false) : ''). '" size="40" '
+        $out .= '<input type="text" name="_action_target['.$id.']" id="action_target' .$id. '" '
+            .'value="' .($action['type']=='redirect' ? Q($action['target'], 'strict', false) : ''). '" size="35" '
             .'style="display:' .($action['type']=='redirect' ? 'inline' : 'none') .'" '
             . $this->error_class($id, 'action', 'target', 'action_target') .' />';
             .'style="display:' .($action['type']=='redirect' ? 'inline' : 'none') .'" '
             . $this->error_class($id, 'action', 'target', 'action_target') .' />';
-        $out .= '<textarea name="_action_target_area[]" id="action_target_area' .$id. '" '
-            .'rows="3" cols="40" '. $this->error_class($id, 'action', 'targetarea', 'action_target_area')
+        $out .= '<textarea name="_action_target_area['.$id.']" id="action_target_area' .$id. '" '
+            .'rows="3" cols="35" '. $this->error_class($id, 'action', 'targetarea', 'action_target_area')
             .'style="display:' .(in_array($action['type'], array('reject', 'ereject')) ? 'inline' : 'none') .'">'
             . (in_array($action['type'], array('reject', 'ereject')) ? Q($action['target'], 'strict', false) : '')
             . "</textarea>\n";
             .'style="display:' .(in_array($action['type'], array('reject', 'ereject')) ? 'inline' : 'none') .'">'
             . (in_array($action['type'], array('reject', 'ereject')) ? Q($action['target'], 'strict', false) : '')
             . "</textarea>\n";
@@ -1066,19 +1471,19 @@ class managesieve extends rcube_plugin
         // vacation
         $out .= '<div id="action_vacation' .$id.'" style="display:' .($action['type']=='vacation' ? 'inline' : 'none') .'">';
         $out .= '<span class="label">'. Q($this->gettext('vacationreason')) .'</span><br />'
         // vacation
         $out .= '<div id="action_vacation' .$id.'" style="display:' .($action['type']=='vacation' ? 'inline' : 'none') .'">';
         $out .= '<span class="label">'. Q($this->gettext('vacationreason')) .'</span><br />'
-            .'<textarea name="_action_reason[]" id="action_reason' .$id. '" '
-            .'rows="3" cols="45" '. $this->error_class($id, 'action', 'reason', 'action_reason') . '>'
+            .'<textarea name="_action_reason['.$id.']" id="action_reason' .$id. '" '
+            .'rows="3" cols="35" '. $this->error_class($id, 'action', 'reason', 'action_reason') . '>'
             . Q($action['reason'], 'strict', false) . "</textarea>\n";
         $out .= '<br /><span class="label">' .Q($this->gettext('vacationsubject')) . '</span><br />'
             . Q($action['reason'], 'strict', false) . "</textarea>\n";
         $out .= '<br /><span class="label">' .Q($this->gettext('vacationsubject')) . '</span><br />'
-            .'<input type="text" name="_action_subject[]" id="action_subject'.$id.'" '
-            .'value="' . (is_array($action['subject']) ? Q(implode(', ', $action['subject']), 'strict', false) : $action['subject']) . '" size="50" '
+            .'<input type="text" name="_action_subject['.$id.']" id="action_subject'.$id.'" '
+            .'value="' . (is_array($action['subject']) ? Q(implode(', ', $action['subject']), 'strict', false) : $action['subject']) . '" size="35" '
             . $this->error_class($id, 'action', 'subject', 'action_subject') .' />';
         $out .= '<br /><span class="label">' .Q($this->gettext('vacationaddresses')) . '</span><br />'
             . $this->error_class($id, 'action', 'subject', 'action_subject') .' />';
         $out .= '<br /><span class="label">' .Q($this->gettext('vacationaddresses')) . '</span><br />'
-            .'<input type="text" name="_action_addresses[]" id="action_addr'.$id.'" '
-            .'value="' . (is_array($action['addresses']) ? Q(implode(', ', $action['addresses']), 'strict', false) : $action['addresses']) . '" size="50" '
+            .'<input type="text" name="_action_addresses['.$id.']" id="action_addr'.$id.'" '
+            .'value="' . (is_array($action['addresses']) ? Q(implode(', ', $action['addresses']), 'strict', false) : $action['addresses']) . '" size="35" '
             . $this->error_class($id, 'action', 'addresses', 'action_addr') .' />';
         $out .= '<br /><span class="label">' . Q($this->gettext('vacationdays')) . '</span><br />'
             . $this->error_class($id, 'action', 'addresses', 'action_addr') .' />';
         $out .= '<br /><span class="label">' . Q($this->gettext('vacationdays')) . '</span><br />'
-            .'<input type="text" name="_action_days[]" id="action_days'.$id.'" '
+            .'<input type="text" name="_action_days['.$id.']" id="action_days'.$id.'" '
             .'value="' .Q($action['days'], 'strict', false) . '" size="2" '
             . $this->error_class($id, 'action', 'days', 'action_days') .' />';
         $out .= '</div>';
             .'value="' .Q($action['days'], 'strict', false) . '" size="2" '
             . $this->error_class($id, 'action', 'days', 'action_days') .' />';
         $out .= '</div>';
@@ -1111,22 +1516,21 @@ class managesieve extends rcube_plugin
 
         $this->rc->imap_connect();
         $select = rcmail_mailbox_select(array(
 
         $this->rc->imap_connect();
         $select = rcmail_mailbox_select(array(
-               'realnames' => false,
-               'maxlength' => 100,
-               'id' => 'action_mailbox' . $id,
-               'name' => '_action_mailbox[]',
-               'style' => 'display:'.(!isset($action) || $action['type']=='fileinto' ? 'inline' : 'none')
-           ));
+            'realnames' => false,
+            'maxlength' => 100,
+            'id' => 'action_mailbox' . $id,
+            'name' => "_action_mailbox[$id]",
+            'style' => 'display:'.(!isset($action) || $action['type']=='fileinto' ? 'inline' : 'none')
+        ));
         $out .= $select->show($mailbox);
         $out .= '</td>';
 
         // add/del buttons
         $out .= '<td class="rowbuttons">';
         $out .= $select->show($mailbox);
         $out .= '</td>';
 
         // add/del buttons
         $out .= '<td class="rowbuttons">';
-        $out .= '<input type="button" id="actionadd' . $id .'" value="'. Q($this->gettext('add')). '"
-            onclick="rcmail.managesieve_actionadd(' . $id .')" class="button" /> ';
-        $out .= '<input type="button" id="actiondel' . $id .'" value="'. Q($this->gettext('del')). '"
-            onclick="rcmail.managesieve_actiondel(' . $id .')" class="button' . ($rows_num<2 ? ' disabled' : '') .'"'
-            . ($rows_num<2 ? ' disabled="disabled"' : '') .' />';
+        $out .= '<a href="#" id="actionadd' . $id .'" title="'. Q($this->gettext('add')). '"
+            onclick="rcmail.managesieve_actionadd(' . $id .')" class="button add"></a>';
+        $out .= '<a href="#" id="actiondel' . $id .'" title="'. Q($this->gettext('del')). '"
+            onclick="rcmail.managesieve_actiondel(' . $id .')" class="button del' . ($rows_num<2 ? ' disabled' : '') .'"></a>';
         $out .= '</td>';
 
         $out .= '</tr></table>';
         $out .= '</td>';
 
         $out .= '</tr></table>';
@@ -1208,4 +1612,267 @@ class managesieve extends rcube_plugin
 
         return $mailbox;
     }
 
         return $mailbox;
     }
+
+    /**
+     * List sieve scripts
+     *
+     * @return array Scripts list
+     */
+    public function list_scripts()
+    {
+        if ($this->list !== null) {
+            return $this->list;
+        }
+
+        $this->list = $this->sieve->get_scripts();
+
+        // Handle active script(s) and list of scripts according to Kolab's KEP:14
+        if ($this->rc->config->get('managesieve_kolab_master')) {
+
+            // Skip protected names
+            foreach ((array)$this->list as $idx => $name) {
+                $_name = strtoupper($name);
+                if ($_name == 'MASTER')
+                    $master_script = $name;
+                else if ($_name == 'MANAGEMENT')
+                    $management_script = $name;
+                else if($_name == 'USER')
+                    $user_script = $name;
+                else
+                    continue;
+
+                unset($this->list[$idx]);
+            }
+
+            // get active script(s), read USER script
+            if ($user_script) {
+                $extension = $this->rc->config->get('managesieve_filename_extension', '.sieve');
+                $filename_regex = '/'.preg_quote($extension, '/').'$/';
+                $_SESSION['managesieve_user_script'] = $user_script;
+
+                $this->sieve->load($user_script);
+
+                foreach ($this->sieve->script->as_array() as $rules) {
+                    foreach ($rules['actions'] as $action) {
+                        if ($action['type'] == 'include' && empty($action['global'])) {
+                            $name = preg_replace($filename_regex, '', $action['target']);
+                            $this->active[] = $name;
+                        }
+                    }
+                }
+            }
+            // create USER script if it doesn't exist
+            else {
+                $content = "# USER Management Script\n"
+                    ."#\n"
+                    ."# This script includes the various active sieve scripts\n"
+                    ."# it is AUTOMATICALLY GENERATED. DO NOT EDIT MANUALLY!\n"
+                    ."#\n"
+                    ."# For more information, see http://wiki.kolab.org/KEP:14#USER\n"
+                    ."#\n";
+                if ($this->sieve->save_script('USER', $content)) {
+                    $_SESSION['managesieve_user_script'] = 'USER';
+                    if (empty($this->master_file))
+                        $this->sieve->activate('USER');
+                }
+            }
+        }
+        else if (!empty($this->list)) {
+            // Get active script name
+            if ($active = $this->sieve->get_active()) {
+                $this->active = array($active);
+            }
+        }
+
+        return $this->list;
+    }
+
+    /**
+     * Removes sieve script
+     *
+     * @param string $name Script name
+     *
+     * @return bool True on success, False on failure
+     */
+    public function remove_script($name)
+    {
+        $result = $this->sieve->remove($name);
+
+        // Kolab's KEP:14
+        if ($result && $this->rc->config->get('managesieve_kolab_master')) {
+            $this->deactivate_script($name);
+        }
+
+        return $result;
+    }
+
+    /**
+     * Activates sieve script
+     *
+     * @param string $name Script name
+     *
+     * @return bool True on success, False on failure
+     */
+    public function activate_script($name)
+    {
+        // Kolab's KEP:14
+        if ($this->rc->config->get('managesieve_kolab_master')) {
+            $extension   = $this->rc->config->get('managesieve_filename_extension', '.sieve');
+            $user_script = $_SESSION['managesieve_user_script'];
+
+            // if the script is not active...
+            if ($user_script && ($key = array_search($name, $this->active)) === false) {
+                // ...rewrite USER file adding appropriate include command
+                if ($this->sieve->load($user_script)) {
+                    $script = $this->sieve->script->as_array();
+                    $list   = array();
+                    $regexp = '/' . preg_quote($extension, '/') . '$/';
+
+                    // Create new include entry
+                    $rule = array(
+                        'actions' => array(
+                            0 => array(
+                                'target'   => $name.$extension,
+                                'type'     => 'include',
+                                'personal' => true,
+                    )));
+
+                    // get all active scripts for sorting
+                    foreach ($script as $rid => $rules) {
+                        foreach ($rules['actions'] as $aid => $action) {
+                            if ($action['type'] == 'include' && empty($action['global'])) {
+                                $target = $extension ? preg_replace($regexp, '', $action['target']) : $action['target'];
+                                $list[] = $target;
+                            }
+                        }
+                    }
+                    $list[] = $name;
+
+                    // Sort and find current script position
+                    asort($list, SORT_LOCALE_STRING);
+                    $list = array_values($list);
+                    $index = array_search($name, $list);
+
+                    // add rule at the end of the script
+                    if ($index === false || $index == count($list)-1) {
+                        $this->sieve->script->add_rule($rule);
+                    }
+                    // add rule at index position
+                    else {
+                        $script2 = array();
+                        foreach ($script as $rid => $rules) {
+                            if ($rid == $index) {
+                                $script2[] = $rule;
+                            }
+                            $script2[] = $rules;
+                        }
+                        $this->sieve->script->content = $script2;
+                    }
+
+                    $result = $this->sieve->save();
+                    if ($result) {
+                        $this->active[] = $name;
+                    }
+                }
+            }
+        }
+        else {
+            $result = $this->sieve->activate($name);
+            if ($result)
+                $this->active = array($name);
+        }
+
+        return $result;
+    }
+
+    /**
+     * Deactivates sieve script
+     *
+     * @param string $name Script name
+     *
+     * @return bool True on success, False on failure
+     */
+    public function deactivate_script($name)
+    {
+        // Kolab's KEP:14
+        if ($this->rc->config->get('managesieve_kolab_master')) {
+            $extension   = $this->rc->config->get('managesieve_filename_extension', '.sieve');
+            $user_script = $_SESSION['managesieve_user_script'];
+
+            // if the script is active...
+            if ($user_script && ($key = array_search($name, $this->active)) !== false) {
+                // ...rewrite USER file removing appropriate include command
+                if ($this->sieve->load($user_script)) {
+                    $script = $this->sieve->script->as_array();
+                    $name   = $name.$extension;
+
+                    foreach ($script as $rid => $rules) {
+                        foreach ($rules['actions'] as $aid => $action) {
+                            if ($action['type'] == 'include' && empty($action['global'])
+                                && $action['target'] == $name
+                            ) {
+                                break 2;
+                            }
+                        }
+                    }
+
+                    // Entry found
+                    if ($rid < count($script)) {
+                        $this->sieve->script->delete_rule($rid);
+                        $result = $this->sieve->save();
+                        if ($result) {
+                            unset($this->active[$key]);
+                        }
+                    }
+                }
+            }
+        }
+        else {
+            $result = $this->sieve->deactivate();
+            if ($result)
+                $this->active = array();
+        }
+
+        return $result;
+    }
+
+    /**
+     * Saves current script (adding some variables)
+     */
+    public function save_script($name = null)
+    {
+        // Kolab's KEP:14
+        if ($this->rc->config->get('managesieve_kolab_master')) {
+            $this->sieve->script->set_var('EDITOR', self::PROGNAME);
+            $this->sieve->script->set_var('EDITOR_VERSION', self::VERSION);
+        }
+
+        return $this->sieve->save($name);
+    }
+
+    /**
+     * Returns list of rules from the current script
+     *
+     * @return array List of rules
+     */
+    public function list_rules()
+    {
+        $result = array();
+        $i      = 1;
+
+        foreach ($this->script as $idx => $filter) {
+            if ($filter['type'] != 'if') {
+                continue;
+            }
+            $fname = $filter['name'] ? $filter['name'] : "#$i";
+            $result[] = array(
+                'id'    => $idx,
+                'name'  => Q($fname),
+                'class' => $filter['disabled'] ? 'disabled' : '',
+            );
+            $i++;
+        }
+
+        return $result;
+    }
 }
 }
diff --git a/plugins/managesieve/package.xml b/plugins/managesieve/package.xml
new file mode 100644 (file)
index 0000000..56655d2
--- /dev/null
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<package xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" packagerversion="1.9.0" version="2.0" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
+    http://pear.php.net/dtd/tasks-1.0.xsd
+    http://pear.php.net/dtd/package-2.0
+    http://pear.php.net/dtd/package-2.0.xsd">
+       <name>managesieve</name>
+       <channel>pear.roundcube.net</channel>
+       <summary>Sieve filters manager for Roundcube</summary>
+       <description>
+           Adds a possibility to manage Sieve scripts (incoming mail filters).
+        It's clickable interface which operates on text scripts and communicates
+        with server using managesieve protocol. Adds Filters tab in Settings.
+       </description>
+       <lead>
+               <name>Aleksander Machniak</name>
+               <user>alec</user>
+               <email>alec@alec.pl</email>
+               <active>yes</active>
+       </lead>
+       <date>2011-11-17</date>
+       <version>
+               <release>5.0</release>
+               <api>5.0</api>
+       </version>
+       <stability>
+               <release>stable</release>
+               <api>stable</api>
+       </stability>
+       <license uri="http://www.gnu.org/licenses/gpl-2.0.html">GNU GPLv2</license>
+    <notes>-</notes>
+       <contents>
+               <dir baseinstalldir="/" name="/">
+                       <file name="managesieve.php" role="php">
+                               <tasks:replace from="@name@" to="name" type="package-info"/>
+                               <tasks:replace from="@package_version@" to="version" type="package-info"/>
+                       </file>
+                       <file name="managesieve.js" role="data">
+                               <tasks:replace from="@name@" to="name" type="package-info"/>
+                               <tasks:replace from="@package_version@" to="version" type="package-info"/>
+                       </file>
+                       <file name="localization/bg_BG.inc" role="data"></file>
+                       <file name="localization/cs_CZ.inc" role="data"></file>
+                       <file name="localization/de_CH.inc" role="data"></file>
+                       <file name="localization/de_DE.inc" role="data"></file>
+                       <file name="localization/el_GR.inc" role="data"></file>
+                       <file name="localization/en_GB.inc" role="data"></file>
+                       <file name="localization/en_US.inc" role="data"></file>
+                       <file name="localization/es_AR.inc" role="data"></file>
+                       <file name="localization/es_ES.inc" role="data"></file>
+                       <file name="localization/et_EE.inc" role="data"></file>
+                       <file name="localization/fi_FI.inc" role="data"></file>
+                       <file name="localization/fr_FR.inc" role="data"></file>
+                       <file name="localization/gl_ES.inc" role="data"></file>
+                       <file name="localization/hr_HR.inc" role="data"></file>
+                       <file name="localization/hu_HU.inc" role="data"></file>
+                       <file name="localization/it_IT.inc" role="data"></file>
+                       <file name="localization/ja_JP.inc" role="data"></file>
+                       <file name="localization/lv_LV.inc" role="data"></file>
+                       <file name="localization/nb_NO.inc" role="data"></file>
+                       <file name="localization/nl_NL.inc" role="data"></file>
+                       <file name="localization/pl_PL.inc" role="data"></file>
+                       <file name="localization/pt_BR.inc" role="data"></file>
+                       <file name="localization/pt_PT.inc" role="data"></file>
+                       <file name="localization/ru_RU.inc" role="data"></file>
+                       <file name="localization/sk_SK.inc" role="data"></file>
+                       <file name="localization/sl_SI.inc" role="data"></file>
+                       <file name="localization/sv_SE.inc" role="data"></file>
+                       <file name="localization/uk_UA.inc" role="data"></file>
+                       <file name="localization/zh_CN.inc" role="data"></file>
+                       <file name="localization/zh_TW.inc" role="data"></file>
+                       <file name="skins/default/managesieve.css" role="data"></file>
+                       <file name="skins/default/managesieve_mail.css" role="data"></file>
+                       <file name="skins/default/templates/filteredit.html" role="data"></file>
+                       <file name="skins/default/templates/managesieve.html" role="data"></file>
+                       <file name="skins/default/templates/setedit.html" role="data"></file>
+                       <file name="skins/default/images/add.png" role="data"></file>
+                       <file name="skins/default/images/del.png" role="data"></file>
+                       <file name="skins/default/images/down_small.gif" role="data"></file>
+                       <file name="skins/default/images/filter.png" role="data"></file>
+                       <file name="skins/default/images/up_small.gif" role="data"></file>
+                       <file name="managesieve.php" role="php"></file>
+                       <file name="lib/rcube_sieve.php" role="php"></file>
+                       <file name="lib/rcube_sieve_script.php" role="php"></file>
+                       <file name="lib/Net/Sieve.php" role="php"></file>
+                       <file name="config.inc.php.dist" role="data"></file>
+               </dir>
+               <!-- / -->
+       </contents>
+       <dependencies>
+               <required>
+                       <php>
+                               <min>5.2.1</min>
+                       </php>
+                       <pearinstaller>
+                               <min>1.7.0</min>
+                       </pearinstaller>
+               </required>
+       </dependencies>
+       <phprelease/>
+</package>
diff --git a/plugins/managesieve/skins/default/images/add.png b/plugins/managesieve/skins/default/images/add.png
new file mode 100644 (file)
index 0000000..97a6422
Binary files /dev/null and b/plugins/managesieve/skins/default/images/add.png differ
diff --git a/plugins/managesieve/skins/default/images/del.png b/plugins/managesieve/skins/default/images/del.png
new file mode 100644 (file)
index 0000000..518905b
Binary files /dev/null and b/plugins/managesieve/skins/default/images/del.png differ
diff --git a/plugins/managesieve/skins/default/images/down_small.gif b/plugins/managesieve/skins/default/images/down_small.gif
new file mode 100644 (file)
index 0000000..f865893
Binary files /dev/null and b/plugins/managesieve/skins/default/images/down_small.gif differ
diff --git a/plugins/managesieve/skins/default/images/filter.png b/plugins/managesieve/skins/default/images/filter.png
new file mode 100644 (file)
index 0000000..a79ba10
Binary files /dev/null and b/plugins/managesieve/skins/default/images/filter.png differ
diff --git a/plugins/managesieve/skins/default/images/up_small.gif b/plugins/managesieve/skins/default/images/up_small.gif
new file mode 100644 (file)
index 0000000..40deb89
Binary files /dev/null and b/plugins/managesieve/skins/default/images/up_small.gif differ
index 675c5d0dc9d8c589a12f51db6767466303aca9a4..60f632504a0af627d97bcabffc17f6394c635622 100644 (file)
-/***** Roundcube|Filters styles *****/
-
-
-#filterslist
+#filtersetslistbox
 {
   position: absolute;
 {
   position: absolute;
-  left: 20px;
-  top: 120px;
-  bottom: 20px;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  width: 195px;
   border: 1px solid #999999;
   border: 1px solid #999999;
-  overflow: auto;
+  background-color: #F9F9F9;
+  overflow: hidden;
   /* css hack for IE */
   /* css hack for IE */
-  height: expression((parseInt(document.documentElement.clientHeight)-140)+'px');
+  height: expression(parseInt(this.parentNode.offsetHeight)+'px');
 }
 
 }
 
-#filters-table
+#filtersscreen
 {
 {
-  width: 100%;
-  table-layout: fixed;
+  position: absolute;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 205px;
   /* css hack for IE */
   /* css hack for IE */
-  width: expression(document.getElementById('filterslist').clientWidth);
+  height: expression(parseInt(this.parentNode.offsetHeight)+'px');
 }
 
 }
 
-#filters-table tbody td
+#filterslistbox
 {
 {
-  cursor: pointer;
+  position: absolute;
+  left: 0;
+  top: 0;
+  bottom: 0;
+  border: 1px solid #999999;
+  overflow: auto;
+  /* css hack for IE */
+  height: expression(parseInt(this.parentNode.offsetHeight)+'px');
 }
 
 }
 
-#filters-table tbody tr.disabled td
+#filterslist,
+#filtersetslist
 {
 {
-  color: #999999;
+  width: 100%;
+  table-layout: fixed;
 }
 
 }
 
-#filtersbuttons
+#filterslist tbody td,
+#filtersetslist tbody td
 {
 {
-  position: absolute;
-  left: 20px;
-  top: 85px;
+  cursor: default;
+  text-overflow: ellipsis;
+  -o-text-overflow: ellipsis;
 }
 
 }
 
-#filtersetsbuttons
+#filterslist tbody tr.disabled td,
+#filtersetslist tbody tr.disabled td
 {
 {
-  position: absolute;
-  left: 230px;
-  top: 85px;
+  color: #999999;
 }
 
 }
 
-#filtersbuttons a,
-#filtersetsbuttons a
+#filtersetslist tbody td
 {
 {
-  display: block;
-  float: left;
+  font-weight: bold;
 }
 }
-
-#filtersbuttons a.button,
-#filtersbuttons a.buttonPas,
-#filtersetsbuttons a.button,
-#filtersetsbuttons a.buttonPas
+/*
+#filtersetslist tr.selected
 {
 {
-  display: block;
-  float: left;
-  width: 32px;
-  height: 32px;
-  padding: 0;
-  margin-right: 3px;
-  overflow: hidden;
-  background: url(managesieve_toolbar.png) 0 0 no-repeat transparent;
-  opacity: 0.99; /* this is needed to make buttons appear correctly in Chrome */
+  background-color: #929292;
+  border-bottom: 1px solid #898989;
+  color: #FFF;
+  font-weight: bold;
 }
 }
+*/
 
 
-#filtersbuttons a.buttonPas,
-#filtersetsbuttons a.buttonPas
+#filterslist tbody tr.filtermoveup td
 {
 {
-  filter: alpha(opacity=35);
-  opacity: 0.35;
-}
-
-#filtersbuttons a.add {
-  background-position: 0px 0px;
-}
-
-#filtersbuttons a.addsel {
-  background-position: 0 -32px;
-}
-
-#filtersbuttons a.del {
-  background-position: -32px 0px;
-}
-
-#filtersbuttons a.delsel {
-  background-position: -32px -32px;
-}
-
-#filtersbuttons a.up {
-  background-position: -64px 0px;
-}
-
-#filtersbuttons a.upsel {
-  background-position: -64px -32px;
-}
-
-#filtersbuttons a.down {
-  background-position: -96px 0px;
-}
-
-#filtersbuttons a.downsel {
-  background-position: -96px -32px;
-}
-
-#filtersetsbuttons a.setadd {
-  background-position: -128px 0px;
-}
-
-#filtersetsbuttons a.setaddsel {
-  background-position: -128px -32px;
-}
-
-#filtersetsbuttons a.setdel {
-  background-position: -160px 0px;
-}
-
-#filtersetsbuttons a.setdelsel {
-  background-position: -160px -32px;
-}
-
-#filtersetsbuttons a.setset {
-  background-position: -192px 0px;
-}
-
-#filtersetsbuttons a.setsetsel {
-  background-position: -192px -32px;
+  border-top: 2px dotted #555;
+  padding-top: 0px;
 }
 
 }
 
-#filtersetsbuttons a.setget {
-  background-position: -224px 0px;
-}
-
-#filtersetsbuttons a.setgetsel {
-  background-position: -224px -32px;
-}
-
-#filtersetselect
+#filterslist tbody tr.filtermovedown td
 {
 {
-  position: absolute;
-  left: 375px;
-  top: 90px;
+  border-bottom: 2px dotted #555;
+  padding-bottom: 1px;
 }
 
 #filter-box
 {
   position: absolute;
 }
 
 #filter-box
 {
   position: absolute;
-  top: 120px;
-  right: 20px;
-  bottom: 20px;
+  top: 0;
+  right: 0;
+  bottom: 0;
   border: 1px solid #999999;
   overflow: hidden;
   /* css hack for IE */
   border: 1px solid #999999;
   overflow: hidden;
   /* css hack for IE */
-  width: expression((parseInt(document.documentElement.clientWidth)-40-parseInt(document.getElementById('filterslist').offsetWidth))+'px');
-  height: expression((parseInt(document.documentElement.clientHeight)-140)+'px');
+  width: expression((parseInt(this.parentNode.offsetWidth)-20-parseInt(document.getElementById('filterslistbox').offsetWidth))+'px');
+  height: expression(parseInt(this.parentNode.offsetHeight)+'px');
 }
 
 #filter-frame
 }
 
 #filter-frame
 
 body.iframe
 {
 
 body.iframe
 {
-  min-width: 740px;
-  width: expression(Math.max(740, document.documentElement.clientWidth)+'px');
+  min-width: 620px;
+  width: expression(Math.max(620, document.documentElement.clientWidth)+'px');
+  background-color: #F2F2F2;
 }
 
 #filter-form
 {
 }
 
 #filter-form
 {
-  min-width: 650px;
+  min-width: 550px;
+  width: expression(Math.max(550, document.documentElement.clientWidth)+'px');
   white-space: nowrap;
   padding: 20px 10px 10px 10px;
 }
   white-space: nowrap;
   padding: 20px 10px 10px 10px;
 }
@@ -208,7 +146,37 @@ div.rulerow:hover, div.actionrow:hover
 div.rulerow table, div.actionrow table
 {
   padding: 0px;
 div.rulerow table, div.actionrow table
 {
   padding: 0px;
-  width: 100%;
+  min-width: 600px;
+  width: expression(Math.max(600, document.documentElement.clientWidth)+'px');
+}
+
+td
+{
+  vertical-align: top;
+}
+
+td.advbutton
+{
+  width: 1%;
+}
+
+td.advbutton a
+{
+  display: block;
+  padding-top: 14px;
+  height: 6px;
+  width: 12px;
+  text-decoration: none;
+}
+
+td.advbutton a.show
+{
+  background: url(images/down_small.gif) center no-repeat;
+}
+
+td.advbutton a.hide
+{
+  background: url(images/up_small.gif) center no-repeat;
 }
 
 td.rowbuttons
 }
 
 td.rowbuttons
@@ -222,13 +190,20 @@ td.rowactions
 {
   white-space: nowrap;
   width: 1%;
 {
   white-space: nowrap;
   width: 1%;
+  padding-top: 2px;
 }
 
 td.rowtargets
 {
   white-space: nowrap;
   width: 98%;
 }
 
 td.rowtargets
 {
   white-space: nowrap;
   width: 98%;
-  padding-left: 10px;
+  padding-left: 3px;
+  padding-top: 2px;
+}
+
+td.rowtargets div.adv
+{
+  padding-top: 3px;
 }
 
 input.disabled, input.disabled:hover
 }
 
 input.disabled, input.disabled:hover
@@ -245,8 +220,15 @@ input.box,
 input.radio
 {
   border: 0;
 input.radio
 {
   border: 0;
+  margin-top: 0;
 }
 
 }
 
+select.operator_selector
+{
+  width: 200px;
+}
+
+td.rowtargets span,
 span.label
 {
   color: #666666;
 span.label
 {
   color: #666666;
@@ -259,7 +241,7 @@ span.label
   padding-top: 5px;
   width: 100%;
 }
   padding-top: 5px;
   width: 100%;
 }
-  
+
 #footer .footerleft
 {
   padding-left: 2px;
 #footer .footerleft
 {
   padding-left: 2px;
@@ -294,3 +276,47 @@ span.sieve.error
 {
   width: 200px;
 }
 {
   width: 200px;
 }
+
+a.button.add
+{
+  background: url(images/add.png) no-repeat;
+  width: 30px;
+  height: 20px;
+  margin-right: 4px;
+  display: inline-block;
+}
+
+a.button.del
+{
+  background: url(images/del.png) no-repeat;
+  width: 30px;
+  height: 20px;
+  display: inline-block;
+}
+
+a.button.disabled
+{
+  opacity: 0.35;
+  filter: alpha(opacity=35);
+  cursor: default;
+}
+
+#filter-form select,
+#filter-form input,
+#filter-form textarea
+{
+  font-size: 11px;
+}
+
+/* fixes for popup window */
+
+body.iframe.mail
+{
+  margin: 0;
+  padding: 0;
+}
+
+body.iframe.mail #filter-form
+{
+  padding: 10px 5px 5px 5px;
+}
diff --git a/plugins/managesieve/skins/default/managesieve_mail.css b/plugins/managesieve/skins/default/managesieve_mail.css
new file mode 100644 (file)
index 0000000..7fefaed
--- /dev/null
@@ -0,0 +1,63 @@
+#messagemenu li a.filterlink {
+  background-image: url(images/filter.png);
+  background-position: 7px 0;
+}
+
+#sievefilterform {
+  top: 0;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  background-color: #F2F2F2;
+  border: 1px solid #999999;
+  padding: 0;
+  margin: 5px;
+}
+
+#sievefilterform iframe {
+  top: 0;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  width: 100%;
+  min-height: 100%; /* Chrome 14 bug */
+  background-color: #F2F2F2;
+  border: 0;
+  padding: 0;
+  margin: 0;
+}
+
+#sievefilterform ul {
+  list-style: none;
+  padding: 0;
+  margin: 0;
+  margin-top: 5px;
+}
+
+#sievefilterform fieldset {
+  margin: 5px;
+}
+
+#sievefilterform ul li {
+  margin-bottom: 5px;
+  white-space: nowrap;
+}
+
+#sievefilterform ul li input {
+  margin-right: 5px;
+}
+
+#sievefilterform label {
+  font-weight: bold;
+}
+
+#managesieve-tip
+{
+  width: 200px;
+  z-index: 100000;
+}
+
+span.sieve.error
+{
+  color: red;
+}
diff --git a/plugins/managesieve/skins/default/managesieve_toolbar.png b/plugins/managesieve/skins/default/managesieve_toolbar.png
deleted file mode 100644 (file)
index 473dbc8..0000000
Binary files a/plugins/managesieve/skins/default/managesieve_toolbar.png and /dev/null differ
index 8b1993528985fca4fdda5363ad066b1f3964e44e..6ecb03caef0260e6925abbc7480f709021b693e9 100644 (file)
@@ -5,13 +5,16 @@
 <roundcube:include file="/includes/links.html" />
 <link rel="stylesheet" type="text/css" href="/this/managesieve.css" />
 </head>
 <roundcube:include file="/includes/links.html" />
 <link rel="stylesheet" type="text/css" href="/this/managesieve.css" />
 </head>
-<body class="iframe">
+<body class="iframe<roundcube:exp expression="env:task != 'mail' ? '' : ' mail'" />">
 
 
+<roundcube:if condition="env:task != 'mail'" />
 <div id="filter-title" class="boxtitle"><roundcube:label name="managesieve.filterdef" /></div>
 <div id="filter-title" class="boxtitle"><roundcube:label name="managesieve.filterdef" /></div>
+<roundcube:endif />
 
 <div id="filter-form" class="boxcontent">
 <roundcube:object name="filterform" />
 
 
 <div id="filter-form" class="boxcontent">
 <roundcube:object name="filterform" />
 
+<roundcube:if condition="env:task != 'mail'" />
 <div id="footer">
 <div class="footerleft">
 <roundcube:button command="plugin.managesieve-save" type="input" class="button mainaction" label="save" />
 <div id="footer">
 <div class="footerleft">
 <roundcube:button command="plugin.managesieve-save" type="input" class="button mainaction" label="save" />
 <input type="checkbox" id="disabled" name="_disabled" value="1" />
 </div>
 </div>
 <input type="checkbox" id="disabled" name="_disabled" value="1" />
 </div>
 </div>
+<roundcube:endif />
 
 </form>
 </div>
 
 
 </form>
 </div>
 
-
 </body>
 </html>
 </body>
 </html>
index 94cd1f1cc11d9da57452e85a4f7eb9dc657b39f2..71eebe105559c98c56ab9dd3c79766c8bb0c9a6c 100644 (file)
@@ -8,46 +8,79 @@
 <script type="text/javascript" src="/splitter.js"></script>
 
 <style type="text/css">
 <script type="text/javascript" src="/splitter.js"></script>
 
 <style type="text/css">
-#filterslist { width: <roundcube:exp expression="!empty(cookie:sieveviewsplitter) ? cookie:sieveviewsplitter-5 : 210" />px; }
+#filterslistbox { width: <roundcube:exp expression="!empty(cookie:sieveviewsplitter) ? cookie:sieveviewsplitter-5 : 210" />px; }
 #filter-box { left: <roundcube:exp expression="!empty(cookie:sieveviewsplitter) ? cookie:sieveviewsplitter+5 : 220" />px;
 <roundcube:exp expression="browser:ie ? ('width:expression((parseInt(this.parentNode.offsetWidth)-'.(!empty(cookie:sieveviewsplitter) ? cookie:sieveviewsplitter+5 : 220).')+\\'px\\');') : ''" />
 }
 #filter-box { left: <roundcube:exp expression="!empty(cookie:sieveviewsplitter) ? cookie:sieveviewsplitter+5 : 220" />px;
 <roundcube:exp expression="browser:ie ? ('width:expression((parseInt(this.parentNode.offsetWidth)-'.(!empty(cookie:sieveviewsplitter) ? cookie:sieveviewsplitter+5 : 220).')+\\'px\\');') : ''" />
 }
+#filtersetslistbox { width: <roundcube:exp expression="!empty(cookie:sieveviewsplitter2) ? cookie:sieveviewsplitter2-5 : 175" />px; }
+#filtersscreen { left: <roundcube:exp expression="!empty(cookie:sieveviewsplitter2) ? cookie:sieveviewsplitter2+5 : 185" />px;
+<roundcube:exp expression="browser:ie ? ('width:expression((parseInt(this.parentNode.offsetWidth)-'.(!empty(cookie:sieveviewsplitter2) ? cookie:sieveviewsplitter2+5 : 185).')+\\'px\\');') : ''" />
+}
 </style>
 
 </head>
 </style>
 
 </head>
-<body>
+<body onload="rcube_init_mail_ui()">
 
 <roundcube:include file="/includes/taskbar.html" />
 <roundcube:include file="/includes/header.html" />
 <roundcube:include file="/includes/settingstabs.html" />
 
 
 <roundcube:include file="/includes/taskbar.html" />
 <roundcube:include file="/includes/header.html" />
 <roundcube:include file="/includes/settingstabs.html" />
 
-<div id="filtersbuttons">
-<roundcube:button command="plugin.managesieve-add" type="link" class="buttonPas add" classSel="button addsel" classAct="button add" title="managesieve.filteradd" content=" " />
-<roundcube:button command="plugin.managesieve-del" type="link" class="buttonPas del" classSel="button delsel" classAct="button del" title="managesieve.filterdel" content=" " />
-<roundcube:button command="plugin.managesieve-up" type="link" class="buttonPas up" classSel="button upsel" classAct="button up" title="managesieve.moveup" content=" " />
-<roundcube:button command="plugin.managesieve-down" type="link" class="buttonPas down" classSel="button downsel" classAct="button down" title="managesieve.movedown" content=" " />
-</div>
+<div id="mainscreen">
 
 
-<div id="filtersetsbuttons">
-<roundcube:button command="plugin.managesieve-setadd" type="link" class="buttonPas setadd" classSel="button setaddsel" classAct="button setadd" title="managesieve.filtersetadd" content=" " />
-<roundcube:button command="plugin.managesieve-setdel" type="link" class="buttonPas setdel" classSel="button setdelsel" classAct="button setdel" title="managesieve.filtersetdel" content=" " />
-<roundcube:button command="plugin.managesieve-setact" type="link" class="buttonPas setset" classSel="button setsetsel" classAct="button setset" content=" " />
-<roundcube:button command="plugin.managesieve-setget" type="link" class="buttonPas setget" classSel="button setgetsel" classAct="button setget" title="managesieve.filtersetget" content=" " />
+<div id="filtersetslistbox">
+<div id="filtersetslist-title" class="boxtitle"><roundcube:label name="managesieve.filtersets" /></div>
+<div class="boxlistcontent">
+  <roundcube:object name="filtersetslist" id="filtersetslist" class="records-table" cellspacing="0" summary="Filters list" type="list" noheader="true" />
+</div>
+<div class="boxfooter">
+  <roundcube:button command="plugin.managesieve-setadd" type="link" title="managesieve.filtersetadd" class="buttonPas addfilterset" classAct="button addfilterset" content=" " />
+  <roundcube:button name="filtersetmenulink" id="filtersetmenulink" type="link" title="moreactions" class="button groupactions" onclick="rcmail_ui.show_popup('filtersetmenu', undefined, {above:1});return false" content=" " />
 </div>
 </div>
-<div id="filtersetselect">
-<roundcube:label name="managesieve.filterset" />:
-<roundcube:object name="filtersetslist" id="filtersets-select" />
 </div>
 
 </div>
 
-<div id="filterslist">
-<roundcube:object name="filterslist" id="filters-table" class="records-table" cellspacing="0" summary="Filters list" />
+<div id="filtersscreen">
+<div id="filterslistbox">
+<div class="boxtitle"><roundcube:label name="managesieve.filters" /></div>
+<div class="boxlistcontent">
+  <roundcube:object name="filterslist" id="filterslist" class="records-table" cellspacing="0" summary="Filters list" noheader="true" />
+</div>
+<div class="boxfooter">
+  <roundcube:button command="plugin.managesieve-add" type="link" title="managesieve.filteradd" class="buttonPas addfilter" classAct="button addfilter" content=" " />
+  <roundcube:button name="filtermenulink" id="filtermenulink" type="link" title="moreactions" class="button groupactions" onclick="rcmail_ui.show_popup('filtermenu', undefined, {above:1});return false" content=" " />
 </div>
 </div>
+</div>
+
 <script type="text/javascript">
 <script type="text/javascript">
-  var sieveviewsplit = new rcube_splitter({id:'sieveviewsplitter', p1: 'filterslist', p2: 'filter-box', orientation: 'v', relative: true, start: 215});
+  var sieveviewsplit2 = new rcube_splitter({id:'sieveviewsplitter2', p1: 'filtersetslistbox', p2: 'filtersscreen', orientation: 'v', relative: true, start: 200});
+  rcmail.add_onload('sieveviewsplit2.init()');
+
+  var sieveviewsplit = new rcube_splitter({id:'sieveviewsplitter', p1: 'filterslistbox', p2: 'filter-box', orientation: 'v', relative: true, start: 215});
   rcmail.add_onload('sieveviewsplit.init()');
 </script>
   rcmail.add_onload('sieveviewsplit.init()');
 </script>
+
 <div id="filter-box">
 <div id="filter-box">
-<roundcube:object name="filterframe" id="filter-frame" width="100%" height="100%" frameborder="0" src="/watermark.html" />
+  <roundcube:object name="filterframe" id="filter-frame" width="100%" height="100%" frameborder="0" src="/watermark.html" />
+</div>
+
+</div>
+</div>
+</div>
+
+<div id="filtersetmenu" class="popupmenu">
+  <ul>
+    <li><roundcube:button command="plugin.managesieve-setact" label="managesieve.enable" classAct="active" /></li>
+    <li><roundcube:button command="plugin.managesieve-setdel" label="delete" classAct="active" /></li>
+    <li class="separator_above"><roundcube:button command="plugin.managesieve-setget" label="download" classAct="active" /></li>
+    <roundcube:container name="filtersetoptions" id="filtersetmenu" />
+  </ul>
+</div>
+
+<div id="filtermenu" class="popupmenu">
+  <ul>
+    <li><roundcube:button command="plugin.managesieve-act" label="managesieve.enable" classAct="active" /></li>
+    <li><roundcube:button command="plugin.managesieve-del" label="delete" classAct="active" /></li>
+    <roundcube:container name="filteroptions" id="filtermenu" />
+  </ul>
 </div>
 
 </body>
 </div>
 
 </body>
index d703534599fef9e1fa32eabdaa7da09c7b9f9e02..aec042187436e9c0ecfd6a2e7fab3a6d03d5d2fc 100644 (file)
@@ -6,7 +6,7 @@ Main test of script parser
 include '../lib/rcube_sieve_script.php';
 
 $txt = '
 include '../lib/rcube_sieve_script.php';
 
 $txt = '
-require ["fileinto","vacation","reject","relational","comparator-i;ascii-numeric","imapflags"];
+require ["fileinto","reject","envelope"];
 # rule:[spam]
 if anyof (header :contains "X-DSPAM-Result" "Spam")
 {
 # rule:[spam]
 if anyof (header :contains "X-DSPAM-Result" "Spam")
 {
@@ -14,28 +14,17 @@ if anyof (header :contains "X-DSPAM-Result" "Spam")
        stop;
 }
 # rule:[test1]
        stop;
 }
 # rule:[test1]
-if anyof (header :contains ["From","To"] "test@domain.tld")
+if anyof (header :comparator "i;ascii-casemap" :contains ["From","To"] "test@domain.tld")
 {
        discard;
        stop;
 }
 # rule:[test2]
 {
        discard;
        stop;
 }
 # rule:[test2]
-if anyof (not header :contains ["Subject"] "[test]", header :contains "Subject" "[test2]")
+if anyof (not header :comparator "i;octet" :contains ["Subject"] "[test]", header :contains "Subject" "[test2]")
 {
        fileinto "test";
        stop;
 }
 {
        fileinto "test";
        stop;
 }
-# rule:[test-vacation]
-if anyof (header :contains "Subject" "vacation")
-{
-       vacation :days 1 text:
-# test
-test test /* test */
-test
-.
-;
-       stop;
-}
 # rule:[comments]
 if anyof (true) /* comment
  * "comment" #comment */ {
 # rule:[comments]
 if anyof (true) /* comment
  * "comment" #comment */ {
@@ -44,24 +33,40 @@ if anyof (true) /* comment
 }
 # rule:[reject]
 if size :over 5000K {
 }
 # rule:[reject]
 if size :over 5000K {
-    reject "Message over 5MB size limit. Please contact me before sending this.";
+       reject "Message over 5MB size limit. Please contact me before sending this.";
+}
+# rule:[false]
+if false # size :over 5000K
+{
+       stop; /* rule disabled */
+}
+# rule:[true]
+if true
+{
+       stop;
 }
 }
-# rule:[redirect]
-if header :value "ge" :comparator "i;ascii-numeric"
-    ["X-Spam-score"] ["14"] {redirect "test@test.tld";}
-# rule:[imapflags]
-if header :matches "Subject" "^Test$" {
-    setflag "\\\\Seen";
-    addflag ["\\\\Answered","\\\\Deleted"];
+fileinto "Test";
+# rule:[address test]
+if address :all :is "From" "nagios@domain.tld"
+{
+       fileinto "domain.tld";
+       stop;
+}
+# rule:[envelope test]
+if envelope :domain :is "From" "domain.tld"
+{
+       fileinto "domain.tld";
+       stop;
 }
 ';
 
 $s = new rcube_sieve_script($txt);
 echo $s->as_text();
 
 }
 ';
 
 $s = new rcube_sieve_script($txt);
 echo $s->as_text();
 
+// -------------------------------------------------------------------------------
 ?>
 --EXPECT--
 ?>
 --EXPECT--
-require ["fileinto","vacation","reject","relational","comparator-i;ascii-numeric","imapflags"];
+require ["fileinto","reject","envelope"];
 # rule:[spam]
 if header :contains "X-DSPAM-Result" "Spam"
 {
 # rule:[spam]
 if header :contains "X-DSPAM-Result" "Spam"
 {
@@ -75,22 +80,11 @@ if header :contains ["From","To"] "test@domain.tld"
        stop;
 }
 # rule:[test2]
        stop;
 }
 # rule:[test2]
-if anyof (not header :contains "Subject" "[test]", header :contains "Subject" "[test2]")
+if anyof (not header :comparator "i;octet" :contains "Subject" "[test]", header :contains "Subject" "[test2]")
 {
        fileinto "test";
        stop;
 }
 {
        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
 {
 # rule:[comments]
 if true
 {
@@ -101,14 +95,26 @@ if size :over 5000K
 {
        reject "Message over 5MB size limit. Please contact me before sending this.";
 }
 {
        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"
+# rule:[false]
+if false # size :over 5000K
 {
 {
-       redirect "test@test.tld";
+       stop;
 }
 }
-# rule:[imapflags]
-if header :matches "Subject" "^Test$"
+# rule:[true]
+if true
 {
 {
-       setflag "\\Seen";
-       addflag ["\\Answered","\\Deleted"];
+       stop;
+}
+fileinto "Test";
+# rule:[address test]
+if address :all :is "From" "nagios@domain.tld"
+{
+       fileinto "domain.tld";
+       stop;
+}
+# rule:[envelope test]
+if envelope :domain :is "From" "domain.tld"
+{
+       fileinto "domain.tld";
+       stop;
 }
 }
diff --git a/plugins/managesieve/tests/parser_body.phpt b/plugins/managesieve/tests/parser_body.phpt
new file mode 100644 (file)
index 0000000..08ad549
--- /dev/null
@@ -0,0 +1,49 @@
+--TEST--
+Test of Sieve body extension (RFC5173)
+--SKIPIF--
+--FILE--
+<?php
+include '../lib/rcube_sieve_script.php';
+
+$txt = '
+require ["body","fileinto"];
+if body :raw :contains "MAKE MONEY FAST"
+{
+       stop;
+}
+if body :content "text" :contains ["missile","coordinates"]
+{
+       fileinto "secrets";
+}
+if body :content "audio/mp3" :contains ""
+{
+       fileinto "jukebox";
+}
+if body :text :contains "project schedule"
+{
+       fileinto "project/schedule";
+}
+';
+
+$s = new rcube_sieve_script($txt);
+echo $s->as_text();
+
+?>
+--EXPECT--
+require ["body","fileinto"];
+if body :raw :contains "MAKE MONEY FAST"
+{
+       stop;
+}
+if body :content "text" :contains ["missile","coordinates"]
+{
+       fileinto "secrets";
+}
+if body :content "audio/mp3" :contains ""
+{
+       fileinto "jukebox";
+}
+if body :text :contains "project schedule"
+{
+       fileinto "project/schedule";
+}
diff --git a/plugins/managesieve/tests/parser_imapflags.phpt b/plugins/managesieve/tests/parser_imapflags.phpt
new file mode 100644 (file)
index 0000000..a4bc465
--- /dev/null
@@ -0,0 +1,28 @@
+--TEST--
+Test of Sieve vacation extension (RFC5232)
+--SKIPIF--
+--FILE--
+<?php
+include '../lib/rcube_sieve_script.php';
+
+$txt = '
+require ["imapflags"];
+# rule:[imapflags]
+if header :matches "Subject" "^Test$" {
+    setflag "\\\\Seen";
+    addflag ["\\\\Answered","\\\\Deleted"];
+}
+';
+
+$s = new rcube_sieve_script($txt, array('imapflags'));
+echo $s->as_text();
+
+?>
+--EXPECT--
+require ["imapflags"];
+# rule:[imapflags]
+if header :matches "Subject" "^Test$"
+{
+       setflag "\\Seen";
+       addflag ["\\Answered","\\Deleted"];
+}
diff --git a/plugins/managesieve/tests/parser_include.phpt b/plugins/managesieve/tests/parser_include.phpt
new file mode 100644 (file)
index 0000000..addc0d4
--- /dev/null
@@ -0,0 +1,30 @@
+--TEST--
+Test of Sieve include extension
+--SKIPIF--
+--FILE--
+<?php
+include '../lib/rcube_sieve_script.php';
+
+$txt = '
+require ["include"];
+
+include "script.sieve";
+# rule:[two]
+if true
+{
+    include :optional "second.sieve";
+}
+';
+
+$s = new rcube_sieve_script($txt, array(), array('variables'));
+echo $s->as_text();
+
+?>
+--EXPECT--
+require ["include"];
+include "script.sieve";
+# rule:[two]
+if true
+{
+       include :optional "second.sieve";
+}
diff --git a/plugins/managesieve/tests/parser_kep14.phpt b/plugins/managesieve/tests/parser_kep14.phpt
new file mode 100644 (file)
index 0000000..dcdbd48
--- /dev/null
@@ -0,0 +1,19 @@
+--TEST--
+Test of Kolab's KEP:14 implementation
+--SKIPIF--
+--FILE--
+<?php
+include '../lib/rcube_sieve_script.php';
+
+$txt = '
+# EDITOR Roundcube
+# EDITOR_VERSION 123
+';
+
+$s = new rcube_sieve_script($txt, array('body'));
+echo $s->as_text();
+
+?>
+--EXPECT--
+# EDITOR Roundcube
+# EDITOR_VERSION 123
diff --git a/plugins/managesieve/tests/parser_prefix.phpt b/plugins/managesieve/tests/parser_prefix.phpt
new file mode 100644 (file)
index 0000000..c87e965
--- /dev/null
@@ -0,0 +1,25 @@
+--TEST--
+Test of prefix comments handling
+--SKIPIF--
+--FILE--
+<?php
+include '../lib/rcube_sieve_script.php';
+
+$txt = '
+# this is a comment
+# and the second line
+
+require ["variables"];
+set "b" "c";
+';
+
+$s = new rcube_sieve_script($txt, array(), array('variables'));
+echo $s->as_text();
+
+?>
+--EXPECT--
+# this is a comment
+# and the second line
+
+require ["variables"];
+set "b" "c";
diff --git a/plugins/managesieve/tests/parser_relational.phpt b/plugins/managesieve/tests/parser_relational.phpt
new file mode 100644 (file)
index 0000000..6b6f29f
--- /dev/null
@@ -0,0 +1,25 @@
+--TEST--
+Test of Sieve relational extension (RFC5231)
+--SKIPIF--
+--FILE--
+<?php
+include '../lib/rcube_sieve_script.php';
+
+$txt = '
+require ["relational","comparator-i;ascii-numeric"];
+# rule:[redirect]
+if header :value "ge" :comparator "i;ascii-numeric"
+    ["X-Spam-score"] ["14"] {redirect "test@test.tld";}
+';
+
+$s = new rcube_sieve_script($txt);
+echo $s->as_text();
+
+?>
+--EXPECT--
+require ["relational","comparator-i;ascii-numeric"];
+# rule:[redirect]
+if header :value "ge" :comparator "i;ascii-numeric" "X-Spam-score" "14"
+{
+       redirect "test@test.tld";
+}
diff --git a/plugins/managesieve/tests/parser_vacation.phpt b/plugins/managesieve/tests/parser_vacation.phpt
new file mode 100644 (file)
index 0000000..a603ff6
--- /dev/null
@@ -0,0 +1,39 @@
+--TEST--
+Test of Sieve vacation extension (RFC5230)
+--SKIPIF--
+--FILE--
+<?php
+include '../lib/rcube_sieve_script.php';
+
+$txt = '
+require ["vacation"];
+# rule:[test-vacation]
+if anyof (header :contains "Subject" "vacation")
+{
+       vacation :days 1 text:
+# test
+test test /* test */
+test
+.
+;
+       stop;
+}
+';
+
+$s = new rcube_sieve_script($txt);
+echo $s->as_text();
+
+?>
+--EXPECT--
+require ["vacation"];
+# rule:[test-vacation]
+if header :contains "Subject" "vacation"
+{
+       vacation :days 1 text:
+# test
+test test /* test */
+test
+.
+;
+       stop;
+}
diff --git a/plugins/managesieve/tests/parser_variables.phpt b/plugins/managesieve/tests/parser_variables.phpt
new file mode 100644 (file)
index 0000000..cf1f8fc
--- /dev/null
@@ -0,0 +1,39 @@
+--TEST--
+Test of Sieve variables extension
+--SKIPIF--
+--FILE--
+<?php
+include '../lib/rcube_sieve_script.php';
+
+$txt = '
+require ["variables"];
+set "honorific" "Mr";
+set "vacation" text:
+Dear ${HONORIFIC} ${last_name},
+I am out, please leave a message after the meep.
+.
+;
+set :length "b" "${a}";
+set :lower "b" "${a}";
+set :upperfirst "b" "${a}";
+set :upperfirst :lower "b" "${a}";
+set :quotewildcard "b" "Rock*";
+';
+
+$s = new rcube_sieve_script($txt, array(), array('variables'));
+echo $s->as_text();
+
+?>
+--EXPECT--
+require ["variables"];
+set "honorific" "Mr";
+set "vacation" text:
+Dear ${HONORIFIC} ${last_name},
+I am out, please leave a message after the meep.
+.
+;
+set :length "b" "${a}";
+set :lower "b" "${a}";
+set :upperfirst "b" "${a}";
+set :upperfirst :lower "b" "${a}";
+set :quotewildcard "b" "Rock*";
diff --git a/plugins/managesieve/tests/parset_subaddress.phpt b/plugins/managesieve/tests/parset_subaddress.phpt
new file mode 100644 (file)
index 0000000..6d4d03c
--- /dev/null
@@ -0,0 +1,38 @@
+--TEST--
+Test of Sieve subaddress extension (RFC5233)
+--SKIPIF--
+--FILE--
+<?php
+include '../lib/rcube_sieve_script.php';
+
+$txt = '
+require ["envelope","subaddress","fileinto"];
+if envelope :user "To" "postmaster"
+{
+       fileinto "postmaster";
+       stop;
+}
+if envelope :detail :is "To" "mta-filters"
+{
+       fileinto "mta-filters";
+       stop;
+}
+';
+
+$s = new rcube_sieve_script($txt);
+echo $s->as_text();
+
+// -------------------------------------------------------------------------------
+?>
+--EXPECT--
+require ["envelope","subaddress","fileinto"];
+if envelope :user "To" "postmaster"
+{
+       fileinto "postmaster";
+       stop;
+}
+if envelope :detail :is "To" "mta-filters"
+{
+       fileinto "mta-filters";
+       stop;
+}
diff --git a/plugins/new_user_dialog/localization/bg_BG.inc b/plugins/new_user_dialog/localization/bg_BG.inc
new file mode 100644 (file)
index 0000000..9dc0452
--- /dev/null
@@ -0,0 +1,7 @@
+<?php
+
+$labels = array();
+$labels['identitydialogtitle'] = 'Моля попълнете Вашите данни.';
+$labels['identitydialoghint'] = 'Това съобщение се появява само при първото влизане.';
+
+?>
\ No newline at end of file
index 21b3d96c2e8748e2ef4bc9664eef29bb022e2464..067fe19f168d93181077bb2b9fb2f9a5fa0da862 100644 (file)
@@ -6,4 +6,7 @@ $rcmail_config['newmail_notifier_basic'] = false;
 // Enables sound notification
 $rcmail_config['newmail_notifier_sound'] = false;
 
 // Enables sound notification
 $rcmail_config['newmail_notifier_sound'] = false;
 
+// Enables desktop notification
+$rcmail_config['newmail_notifier_desktop'] = false;
+
 ?>
 ?>
diff --git a/plugins/newmail_notifier/localization/de_CH.inc b/plugins/newmail_notifier/localization/de_CH.inc
new file mode 100644 (file)
index 0000000..55cfd71
--- /dev/null
@@ -0,0 +1,13 @@
+<?php
+
+$labels['basic'] = 'Anzeige im Browser bei neuer Nachricht';
+$labels['sound'] = 'Akustische Meldung bei neuer Nachricht';
+$labels['desktop'] = 'Desktop-Benachrichtigung bei neuer Nachricht';
+$labels['test'] = 'Test';
+$labels['title'] = 'Neue E-Mail!';
+$labels['body'] = 'Sie haben eine neue Nachricht';
+$labels['testbody'] = 'Dies ist eine Testbenachrichtigung';
+$labels['desktopdisabled'] = 'Desktop-Benachrichtigungen sind deaktiviert.';
+$labels['desktopunsupported'] = 'Ihr Browser unterstützt keine Desktop-Benachrichtigungen.';
+
+?>
diff --git a/plugins/newmail_notifier/localization/de_DE.inc b/plugins/newmail_notifier/localization/de_DE.inc
new file mode 100644 (file)
index 0000000..65381ca
--- /dev/null
@@ -0,0 +1,13 @@
+<?php
+
+$labels['basic'] = 'Benachrichtigung im Browser bei neuer Nachricht';
+$labels['sound'] = 'Akustische Meldung bei neuer Nachricht';
+$labels['desktop'] = 'Desktop-Benachrichtigung bei neuer Nachricht';
+$labels['test'] = 'Test';
+$labels['title'] = 'Neue E-Mail!';
+$labels['body'] = 'Sie haben eine neue Nachricht';
+$labels['testbody'] = 'Dies ist eine Testbenachrichtigung';
+$labels['desktopdisabled'] = 'Desktop-Benachrichtigungen sind deaktiviert.';
+$labels['desktopunsupported'] = 'Ihr Browser unterstützt keine Desktop-Benachrichtigungen.';
+
+?>
index fbb5d9aaece0f3d44a4209cc957d060ee1d4a507..3017c43dc545dfae0be155fb8fd79db26a07f7d2 100644 (file)
@@ -1,6 +1,13 @@
 <?php
 
 <?php
 
-$labels['basic'] = 'Display notifications on new message';
+$labels['basic'] = 'Display browser notifications on new message';
+$labels['desktop'] = 'Display desktop notifications on new message';
 $labels['sound'] = 'Play the sound on new message';
 $labels['sound'] = 'Play the sound on new message';
+$labels['test'] = 'Test';
+$labels['title'] = 'New Email!';
+$labels['body'] = 'You\'ve received a new message.';
+$labels['testbody'] = 'This is a test notification.';
+$labels['desktopdisabled'] = 'Desktop notifications are disabled in your browser.';
+$labels['desktopunsupported'] = 'Your browser does not support desktop notifications.';
 
 ?>
 
 ?>
diff --git a/plugins/newmail_notifier/localization/lv_LV.inc b/plugins/newmail_notifier/localization/lv_LV.inc
new file mode 100644 (file)
index 0000000..bab30f5
--- /dev/null
@@ -0,0 +1,13 @@
+<?php
+
+$labels['basic'] = 'Attēlot paziņojumu pie jaunas vēstules saņemšanas';
+$labels['desktop'] = 'Attēlot darbvirsmas paziņojumu pie jaunas vēstules saņemšanas';
+$labels['sound'] = 'Atskaņot skaņas signālu pie jaunas vēstules saņemšanas';
+$labels['test'] = 'Test';
+$labels['title'] = 'Jauns E-pasts!';
+$labels['body'] = 'Jūs esat saņēmis jaunu e-pastu.';
+$labels['testbody'] = 'Šis ir testa paziņojums.';
+$labels['desktopdisabled'] = 'Darbvirsmas paziņojumi ir atslēgti Jūsu pārlūkprogrammā.';
+$labels['desktopunsupported'] = 'Jūsu pārlūkprogramma neatbalsta darbvirsmas paziņojumus.';
+
+?>
index 5fe37903b67db4e8007b7e7ddf44200358f1ffac..d95e658af1d074cb365f9aa1f68218565a5a1db5 100644 (file)
@@ -1,6 +1,13 @@
 <?php
 
 <?php
 
-$labels['basic'] = 'Wyświetlaj powiadomienia o nadejściu nowej wiadomości';
+$labels['basic'] = 'Wyświetlaj powiadomienia o nadejściu nowej wiadomości w przeglądarce';
 $labels['sound'] = 'Odtwarzaj dźwięk o nadejściu nowej wiadomości';
 $labels['sound'] = 'Odtwarzaj dźwięk o nadejściu nowej wiadomości';
+$labels['desktop'] = 'Wyświetlaj powiadomienia o nadejściu nowej wiadomości na pulpicie';
+$labels['test'] = 'Testuj powiadomienie';
+$labels['title'] = 'Nowa wiadomość!';
+$labels['body'] = 'Nadeszła nowa wiadomość.';
+$labels['testbody'] = 'To jest testowe powiadomienie.';
+$labels['desktopdisabled'] = 'Powiadomienia na pulpicie zostały zablokowane w twojej przeglądarce.';
+$labels['desktopunsupported'] = 'Twoja przeglądarka nie obsługuje powiadomień na pulpicie.';
 
 ?>
 
 ?>
diff --git a/plugins/newmail_notifier/localization/pt_BR.inc b/plugins/newmail_notifier/localization/pt_BR.inc
new file mode 100644 (file)
index 0000000..66f8e93
--- /dev/null
@@ -0,0 +1,13 @@
+<?php
+
+$labels['basic'] = 'Exibir notificação quando uma nova mensagem chegar';
+$labels['desktop'] = 'Exibir notificação no desktop quando uma nova mensagem chegar';
+$labels['sound'] = 'Alerta sonoro quando uma nova mensagem chegar';
+$labels['test'] = 'Testar';
+$labels['title'] = 'Novo Email!';
+$labels['body'] = 'Você recebeu uma nova mensagem.';
+$labels['testbody'] = 'Essa é uma notificação de teste.';
+$labels['desktopdisabled'] = 'As notificações no desktop estão desabilitadas no seu navegador.';
+$labels['desktopunsupported'] = 'Seu navegador não suporta notificações no desktop';
+
+?>
diff --git a/plugins/newmail_notifier/localization/ru_RU.inc b/plugins/newmail_notifier/localization/ru_RU.inc
new file mode 100644 (file)
index 0000000..65abb74
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+
+/*
++-----------------------------------------------------------------------+
+| language/ru_RU/labels.inc                                             |
+|                                                                       |
+| Language file of the RoundCube Webmail client                         |
+| Copyright (C) 2008-2011, RoundQube Dev. - Switzerland                 |
+| Licensed under the GNU GPL                                            |
+|                                                                       |
++-----------------------------------------------------------------------+
+| Author:        Doubrovine S.                                          |
++-----------------------------------------------------------------------+
+
+*/
+
+$labels = array();
+$labels['basic'] = 'Визуальное уведомление по приходу нового сообщения';
+$labels['sound'] = 'Звуковое уведомление по приходу нового сообщения';
+
+?>
\ No newline at end of file
diff --git a/plugins/newmail_notifier/mail.png b/plugins/newmail_notifier/mail.png
new file mode 100644 (file)
index 0000000..79f3a53
Binary files /dev/null and b/plugins/newmail_notifier/mail.png differ
index 6afd66aee83fc689c5d51e5dd791a224c8707072..16e3edd42cba60680497082af2d65c5d0acfee28 100644 (file)
@@ -1,7 +1,7 @@
 /**
  * New Mail Notifier plugin script
  *
 /**
  * New Mail Notifier plugin script
  *
- * @version 0.2
+ * @version 0.3
  * @author Aleksander Machniak <alec@alec.pl>
  */
 
  * @author Aleksander Machniak <alec@alec.pl>
  */
 
@@ -22,6 +22,8 @@ function newmail_notifier_run(prop)
         newmail_notifier_basic();
     if (prop.sound)
         newmail_notifier_sound();
         newmail_notifier_basic();
     if (prop.sound)
         newmail_notifier_sound();
+    if (prop.desktop)
+        newmail_notifier_desktop(rcmail.gettext('body', 'newmail_notifier'));
 }
 
 // Stops notification
 }
 
 // Stops notification
@@ -37,11 +39,13 @@ function newmail_notifier_stop(prop)
 // Basic notification: window.focus and favicon change
 function newmail_notifier_basic()
 {
 // Basic notification: window.focus and favicon change
 function newmail_notifier_basic()
 {
-    window.focus();
+    var w = rcmail.is_framed() ? window.parent : window;
+
+    w.focus();
 
     // we cannot simply change a href attribute, we must to replace the link element (at least in FF)
     var link = $('<link rel="shortcut icon" href="plugins/newmail_notifier/favicon.ico"/>'),
 
     // we cannot simply change a href attribute, we must to replace the link element (at least in FF)
     var link = $('<link rel="shortcut icon" href="plugins/newmail_notifier/favicon.ico"/>'),
-        oldlink = $('link[rel="shortcut icon"]');
+        oldlink = $('link[rel="shortcut icon"]', w.document);
 
     rcmail.env.favicon_href = oldlink.attr('href');
     link.replaceAll(oldlink);
 
     rcmail.env.favicon_href = oldlink.attr('href');
     link.replaceAll(oldlink);
@@ -64,3 +68,53 @@ function newmail_notifier_sound()
         window.setTimeout("$('#sound').remove()", 5000);
     }
 }
         window.setTimeout("$('#sound').remove()", 5000);
     }
 }
+
+// Desktop notification (need Chrome or Firefox with a plugin)
+function newmail_notifier_desktop(body)
+{
+    var dn = window.webkitNotifications;
+
+    if (dn && !dn.checkPermission()) {
+        if (rcmail.newmail_popup)
+            rcmail.newmail_popup.cancel();
+        var popup = window.webkitNotifications.createNotification('plugins/newmail_notifier/mail.png',
+            rcmail.gettext('title', 'newmail_notifier'), body);
+        popup.onclick = function() {
+            this.cancel();
+        }
+        popup.show();
+        setTimeout(function() { popup.cancel(); }, 10000); // close after 10 seconds
+        rcmail.newmail_popup = popup;
+        return true;
+    }
+
+    return false;
+}
+
+function newmail_notifier_test_desktop()
+{
+    var dn = window.webkitNotifications,
+        txt = rcmail.gettext('testbody', 'newmail_notifier');
+
+    if (dn) {
+        if (!dn.checkPermission())
+            newmail_notifier_desktop(txt);
+        else
+            dn.requestPermission(function() {
+                if (!newmail_notifier_desktop(txt))
+                    rcmail.display_message(rcmail.gettext('desktopdisabled', 'newmail_notifier'), 'error');
+            });
+    }
+    else
+        rcmail.display_message(rcmail.gettext('desktopunsupported', 'newmail_notifier'), 'error');
+}
+
+function newmail_notifier_test_basic()
+{
+    newmail_notifier_basic();
+}
+
+function newmail_notifier_test_sound()
+{
+    newmail_notifier_sound();
+}
index a72d728dcb2e7da67b27ac36c717ebac432100d9..01e25984d5dee7620eb779449770fbd889d5dbf1 100644 (file)
@@ -6,8 +6,10 @@
  * Supports two methods of notification:
  * 1. Basic - focus browser window and change favicon
  * 2. Sound - play wav file
  * Supports two methods of notification:
  * 1. Basic - focus browser window and change favicon
  * 2. Sound - play wav file
+ * 3. Desktop - display desktop notification (using webkitNotifications feature,
+ *              supported by Chrome and Firefox with 'HTML5 Notifications' plugin)
  *
  *
- * @version 0.2
+ * @version 0.3
  * @author Aleksander Machniak <alec@alec.pl>
  *
  *
  * @author Aleksander Machniak <alec@alec.pl>
  *
  *
@@ -32,6 +34,7 @@ class newmail_notifier extends rcube_plugin
     public $task = 'mail|settings';
 
     private $rc;
     public $task = 'mail|settings';
 
     private $rc;
+    private $notified;
 
     /**
      * Plugin initialization
 
     /**
      * Plugin initialization
@@ -49,6 +52,8 @@ class newmail_notifier extends rcube_plugin
             $this->add_hook('new_messages', array($this, 'notify'));
             // add script when not in ajax and not in frame
             if (is_a($this->rc->output, 'rcube_template') && empty($_REQUEST['_framed'])) {
             $this->add_hook('new_messages', array($this, 'notify'));
             // add script when not in ajax and not in frame
             if (is_a($this->rc->output, 'rcube_template') && empty($_REQUEST['_framed'])) {
+                $this->add_texts('localization/');
+                $this->rc->output->add_label('newmail_notifier.title', 'newmail_notifier.body');
                 $this->include_script('newmail_notifier.js');
             }
         }
                 $this->include_script('newmail_notifier.js');
             }
         }
@@ -69,27 +74,29 @@ class newmail_notifier extends rcube_plugin
         // Load localization and configuration
         $this->add_texts('localization/');
 
         // Load localization and configuration
         $this->add_texts('localization/');
 
-        // Check that configuration is not disabled
-        $dont_override  = (array) $this->rc->config->get('dont_override', array());
-        $basic_override = in_array('newmail_notifier_basic', $dont_override);
-        $sound_override = in_array('newmail_notifier_sound', $dont_override);
-
-        if (!$basic_override) {
-            $field_id = '_newmail_notifier_basic';
-            $input    = new html_checkbox(array('name' => $field_id, 'id' => $field_id, 'value' => 1));
-            $args['blocks']['new_message']['options']['newmail_notifier_basic'] = array(
-                'title' => html::label($field_id, Q($this->gettext('basic'))),
-                'content' => $input->show($this->rc->config->get('newmail_notifier_basic')),
-            );
+        if (!empty($_REQUEST['_framed'])) {
+            $this->rc->output->add_label('newmail_notifier.title', 'newmail_notifier.testbody',
+                'newmail_notifier.desktopunsupported', 'newmail_notifier.desktopenabled', 'newmail_notifier.desktopdisabled');
+            $this->include_script('newmail_notifier.js');
         }
 
         }
 
-        if (!$sound_override) {
-            $field_id = '_newmail_notifier_sound';
-            $input    = new html_checkbox(array('name' => $field_id, 'id' => $field_id, 'value' => 1));
-            $args['blocks']['new_message']['options']['newmail_notifier_sound'] = array(
-                'title' => html::label($field_id, Q($this->gettext('sound'))),
-                'content' => $input->show($this->rc->config->get('newmail_notifier_sound')),
-            );
+        // Check that configuration is not disabled
+        $dont_override = (array) $this->rc->config->get('dont_override', array());
+
+        foreach (array('basic', 'desktop', 'sound') as $type) {
+            $key = 'newmail_notifier_' . $type;
+            if (!in_array($key, $dont_override)) {
+                $field_id = '_' . $key;
+                $input    = new html_checkbox(array('name' => $field_id, 'id' => $field_id, 'value' => 1));
+                $content  = $input->show($this->rc->config->get($key))
+                    . ' ' . html::a(array('href' => '#', 'onclick' => 'newmail_notifier_test_'.$type.'()'),
+                        $this->gettext('test'));
+
+                $args['blocks']['new_message']['options'][$key] = array(
+                    'title' => html::label($field_id, Q($this->gettext($type))),
+                    'content' => $content
+                );
+            }
         }
 
         return $args;
         }
 
         return $args;
@@ -108,17 +115,13 @@ class newmail_notifier extends rcube_plugin
         $this->load_config();
 
         // Check that configuration is not disabled
         $this->load_config();
 
         // Check that configuration is not disabled
-        $dont_override  = (array) $this->rc->config->get('dont_override', array());
-        $basic_override = in_array('newmail_notifier_basic', $dont_override);
-        $sound_override = in_array('newmail_notifier_sound', $dont_override);
+        $dont_override = (array) $this->rc->config->get('dont_override', array());
 
 
-        if (!$basic_override) {
-            $key = 'newmail_notifier_basic';
-            $args['prefs'][$key] = get_input_value('_'.$key, RCUBE_INPUT_POST) ? true : false;
-        }
-        if (!$sound_override) {
-            $key = 'newmail_notifier_sound';
-            $args['prefs'][$key] = get_input_value('_'.$key, RCUBE_INPUT_POST) ? true : false;
+        foreach (array('basic', 'desktop', 'sound') as $type) {
+            $key = 'newmail_notifier_' . $type;
+            if (!in_array($key, $dont_override)) {
+                $args['prefs'][$key] = get_input_value('_'.$key, RCUBE_INPUT_POST) ? true : false;
+            }
         }
 
         return $args;
         }
 
         return $args;
@@ -129,15 +132,22 @@ class newmail_notifier extends rcube_plugin
      */
     function notify($args)
     {
      */
     function notify($args)
     {
+        if ($this->notified || !empty($_GET['_refresh'])) {
+            return $args;
+        }
+
+        $this->notified = true;
+
         // Load configuration
         $this->load_config();
 
         // Load configuration
         $this->load_config();
 
-        $basic = $this->rc->config->get('newmail_notifier_basic');
-        $sound = $this->rc->config->get('newmail_notifier_sound');
+        $basic   = $this->rc->config->get('newmail_notifier_basic');
+        $sound   = $this->rc->config->get('newmail_notifier_sound');
+        $desktop = $this->rc->config->get('newmail_notifier_desktop');
 
 
-        if ($basic || $sound) {
+        if ($basic || $sound || $desktop) {
             $this->rc->output->command('plugin.newmail_notifier',
             $this->rc->output->command('plugin.newmail_notifier',
-                array('basic' => $basic, 'sound' => $sound));
+                array('basic' => $basic, 'sound' => $sound, 'desktop' => $desktop));
         }
 
         return $args;
         }
 
         return $args;
index 94af6d77690e55609dbd97b780035e2372f846da..313e47fdacbe8e76ca0e02a96cc0a3edddb4e9a1 100644 (file)
@@ -47,6 +47,10 @@ $rcmail_config['password_db_dsn'] = '';
 // Default: "SELECT update_passwd(%c, %u)"
 $rcmail_config['password_query'] = 'SELECT update_passwd(%c, %u)';
 
 // Default: "SELECT update_passwd(%c, %u)"
 $rcmail_config['password_query'] = 'SELECT update_passwd(%c, %u)';
 
+// By default domains in variables are using unicode.
+// Enable this option to use punycoded names
+$rcmail_config['password_idn_ascii'] = false;
+
 // Path for dovecotpw (if not in $PATH)
 // $rcmail_config['password_dovecotpw'] = '/usr/local/sbin/dovecotpw';
 
 // Path for dovecotpw (if not in $PATH)
 // $rcmail_config['password_dovecotpw'] = '/usr/local/sbin/dovecotpw';
 
index 3ea30a69c6b1eea5e24e67c10330eb4dff979caf..e6450e5e12fc6378eb3a461a83ae14404d819f26 100644 (file)
@@ -272,6 +272,7 @@ function hashPassword( $passwordClear, $encodageType )
         case 'samba':
             if (function_exists('hash')) {
                 $cryptedPassword = hash('md4', rcube_charset_convert($passwordClear, RCMAIL_CHARSET, 'UTF-16LE'));
         case 'samba':
             if (function_exists('hash')) {
                 $cryptedPassword = hash('md4', rcube_charset_convert($passwordClear, RCMAIL_CHARSET, 'UTF-16LE'));
+                $cryptedPassword = strtoupper($cryptedPassword);
             } else {
                                /* Your PHP install does not have the hash() function */
                                return false;
             } else {
                                /* Your PHP install does not have the hash() function */
                                return false;
index 482b7e56fc4ea27a5e5582b153c578344d0d1ba6..2f51b754791da7f8224e7796fb9d454d149eeb5b 100644 (file)
@@ -238,6 +238,7 @@ function ldap_simple_hash_password($password_clear, $encodage_type)
         case 'samba':
             if (function_exists('hash')) {
                 $crypted_password = hash('md4', rcube_charset_convert($password_clear, RCMAIL_CHARSET, 'UTF-16LE'));
         case 'samba':
             if (function_exists('hash')) {
                 $crypted_password = hash('md4', rcube_charset_convert($password_clear, RCMAIL_CHARSET, 'UTF-16LE'));
+                $crypted_password = strtoupper($crypted_password);
             } else {
                                /* Your PHP install does not have the hash() function */
                                return false;
             } else {
                                /* Your PHP install does not have the hash() function */
                                return false;
index 9ea33df2f4bbb49852a411fb1c8294b7ba67072a..06a6b75ffac4f0ad10ade9cb9da36c7d7f3a5485 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Driver for passwords stored in SQL database
  *
  *
  * Driver for passwords stored in SQL database
  *
- * @version 1.3
+ * @version 1.4
  * @author Aleksander 'A.L.E.C' Machniak <alec@alec.pl>
  *
  */
  * @author Aleksander 'A.L.E.C' Machniak <alec@alec.pl>
  *
  */
@@ -37,16 +37,21 @@ function password_save($curpass, $passwd)
     // crypted password
     if (strpos($sql, '%c') !== FALSE) {
         $salt = '';
     // crypted password
     if (strpos($sql, '%c') !== FALSE) {
         $salt = '';
-        if (CRYPT_MD5) { 
-           $len = rand(3, CRYPT_SALT_LENGTH);
+        if (CRYPT_MD5) {
+            // Always use eight salt characters for MD5 (#1488136)
+           $len = 8;
         } else if (CRYPT_STD_DES) {
            $len = 2;
         } else {
            return PASSWORD_CRYPT_ERROR;
         }
         } else if (CRYPT_STD_DES) {
            $len = 2;
         } else {
            return PASSWORD_CRYPT_ERROR;
         }
+
+        //Restrict the character set used as salt (#1488136)
+        $seedchars = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
         for ($i = 0; $i < $len ; $i++) {
         for ($i = 0; $i < $len ; $i++) {
-           $salt .= chr(rand(ord('.'), ord('z')));
+           $salt .= $seedchars[rand(0, 63)];
         }
         }
+
         $sql = str_replace('%c',  $db->quote(crypt($passwd, CRYPT_MD5 ? '$1$'.$salt.'$' : $salt)), $sql);
     }
 
         $sql = str_replace('%c',  $db->quote(crypt($passwd, CRYPT_MD5 ? '$1$'.$salt.'$' : $salt)), $sql);
     }
 
@@ -61,7 +66,7 @@ function password_save($curpass, $passwd)
         $tmp_dir = $rcmail->config->get('temp_dir');
         $tmpfile = tempnam($tmp_dir, 'roundcube-');
 
         $tmp_dir = $rcmail->config->get('temp_dir');
         $tmpfile = tempnam($tmp_dir, 'roundcube-');
 
-        $pipe = popen("'$dovecotpw' -s '$method' > '$tmpfile'", "w");
+        $pipe = popen("$dovecotpw -s '$method' > '$tmpfile'", "w");
         if (!$pipe) {
             unlink($tmpfile);
             return PASSWORD_CRYPT_ERROR;
         if (!$pipe) {
             unlink($tmpfile);
             return PASSWORD_CRYPT_ERROR;
@@ -97,15 +102,15 @@ function password_save($curpass, $passwd)
 
            if (!($hash_algo = strtolower($rcmail->config->get('password_hash_algorithm'))))
             $hash_algo = 'sha1';
 
            if (!($hash_algo = strtolower($rcmail->config->get('password_hash_algorithm'))))
             $hash_algo = 'sha1';
-        
+
            $hash_passwd = hash($hash_algo, $passwd);
         $hash_curpass = hash($hash_algo, $curpass);
            $hash_passwd = hash($hash_algo, $passwd);
         $hash_curpass = hash($hash_algo, $curpass);
-        
+
            if ($rcmail->config->get('password_hash_base64')) {
             $hash_passwd = base64_encode(pack('H*', $hash_passwd));
             $hash_curpass = base64_encode(pack('H*', $hash_curpass));
         }
            if ($rcmail->config->get('password_hash_base64')) {
             $hash_passwd = base64_encode(pack('H*', $hash_passwd));
             $hash_curpass = base64_encode(pack('H*', $hash_curpass));
         }
-       
+
            $sql = str_replace('%n', $db->quote($hash_passwd, 'text'), $sql);
            $sql = str_replace('%q', $db->quote($hash_curpass, 'text'), $sql);
     }
            $sql = str_replace('%n', $db->quote($hash_passwd, 'text'), $sql);
            $sql = str_replace('%q', $db->quote($hash_curpass, 'text'), $sql);
     }
@@ -125,11 +130,28 @@ function password_save($curpass, $passwd)
         }
     }
 
         }
     }
 
+    $local_part  = $rcmail->user->get_username('local');
+    $domain_part = $rcmail->user->get_username('domain');
+    $username    = $_SESSION['username'];
+    $host        = $_SESSION['imap_host'];
+
+    // convert domains to/from punnycode
+    if ($rcmail->config->get('password_idn_ascii')) {
+        $domain_part = rcube_idn_to_ascii($domain_part);
+        $username    = rcube_idn_to_ascii($username);
+        $host        = rcube_idn_to_ascii($host);
+    }
+    else {
+        $domain_part = rcube_idn_to_utf8($domain_part);
+        $username    = rcube_idn_to_utf8($username);
+        $host        = rcube_idn_to_utf8($host);
+    }
+
     // at least we should always have the local part
     // at least we should always have the local part
-    $sql = str_replace('%l', $db->quote($rcmail->user->get_username('local'), 'text'), $sql);
-    $sql = str_replace('%d', $db->quote($rcmail->user->get_username('domain'), 'text'), $sql);
-    $sql = str_replace('%u', $db->quote($_SESSION['username'],'text'), $sql);
-    $sql = str_replace('%h', $db->quote($_SESSION['imap_host'],'text'), $sql);
+    $sql = str_replace('%l', $db->quote($local_part, 'text'), $sql);
+    $sql = str_replace('%d', $db->quote($domain_part, 'text'), $sql);
+    $sql = str_replace('%u', $db->quote($username, 'text'), $sql);
+    $sql = str_replace('%h', $db->quote($host, 'text'), $sql);
 
     $res = $db->query($sql, $sql_vars);
 
 
     $res = $db->query($sql, $sql_vars);
 
index a4f74c19221ca44cc0a4ccaf9a6ba2db3a0dd057..45688e1188e97aa2b33ab5f8c1ac132d55c776ca 100644 (file)
                <email>alec@alec.pl</email>
                <active>yes</active>
        </lead>
                <email>alec@alec.pl</email>
                <active>yes</active>
        </lead>
-       <date></date>
-       <time></time>
+       <date>2011-11-23</date>
        <version>
        <version>
-               <release></release>
+               <release>2.4</release>
                <api>1.6</api>
        </version>
        <stability>
                <api>1.6</api>
        </version>
        <stability>
@@ -27,9 +26,8 @@
        </stability>
        <license uri="http://www.gnu.org/licenses/gpl-2.0.html">GNU GPLv2</license>
        <notes>
        </stability>
        <license uri="http://www.gnu.org/licenses/gpl-2.0.html">GNU GPLv2</license>
        <notes>
-- When old and new passwords are the same, do nothing, return success (#1487823)
-- Fixed Samba password hashing in 'ldap' driver
-- Added 'password_change' hook for plugin actions after successful password change
+- Added option to use punycode or unicode for domain names (#1488103)
+- Save Samba password hashes in capital letters (#1488197)
     </notes>
        <contents>
                <dir baseinstalldir="/" name="/">
     </notes>
        <contents>
                <dir baseinstalldir="/" name="/">
                        <file name="localization/de_CH.inc" role="data"></file>
                        <file name="localization/de_DE.inc" role="data"></file>
                        <file name="localization/en_US.inc" role="data"></file>
                        <file name="localization/de_CH.inc" role="data"></file>
                        <file name="localization/de_DE.inc" role="data"></file>
                        <file name="localization/en_US.inc" role="data"></file>
+                       <file name="localization/es_AR.inc" role="data"></file>
                        <file name="localization/es_ES.inc" role="data"></file>
                        <file name="localization/et_EE.inc" role="data"></file>
                        <file name="localization/fi_FI.inc" role="data"></file>
                        <file name="localization/fr_FR.inc" role="data"></file>
                        <file name="localization/gl_ES.inc" role="data"></file>
                        <file name="localization/es_ES.inc" role="data"></file>
                        <file name="localization/et_EE.inc" role="data"></file>
                        <file name="localization/fi_FI.inc" role="data"></file>
                        <file name="localization/fr_FR.inc" role="data"></file>
                        <file name="localization/gl_ES.inc" role="data"></file>
+                       <file name="localization/hr_HR.inc" role="data"></file>
                        <file name="localization/hu_HU.inc" role="data"></file>
                        <file name="localization/it_IT.inc" role="data"></file>
                        <file name="localization/hu_HU.inc" role="data"></file>
                        <file name="localization/it_IT.inc" role="data"></file>
+                       <file name="localization/ja_JA.inc" role="data"></file>
                        <file name="localization/lt_LT.inc" role="data"></file>
                        <file name="localization/lv_LV.inc" role="data"></file>
                        <file name="localization/nl_NL.inc" role="data"></file>
                        <file name="localization/pl_PL.inc" role="data"></file>
                        <file name="localization/pt_BR.inc" role="data"></file>
                        <file name="localization/pt_PT.inc" role="data"></file>
                        <file name="localization/lt_LT.inc" role="data"></file>
                        <file name="localization/lv_LV.inc" role="data"></file>
                        <file name="localization/nl_NL.inc" role="data"></file>
                        <file name="localization/pl_PL.inc" role="data"></file>
                        <file name="localization/pt_BR.inc" role="data"></file>
                        <file name="localization/pt_PT.inc" role="data"></file>
+                       <file name="localization/ru_RU.inc" role="data"></file>
+                       <file name="localization/sk_SK.inc" role="data"></file>
                        <file name="localization/sl_SI.inc" role="data"></file>
                        <file name="localization/sv_SE.inc" role="data"></file>
                        <file name="localization/sl_SI.inc" role="data"></file>
                        <file name="localization/sv_SE.inc" role="data"></file>
+                       <file name="localization/tr_TR.inc" role="data"></file>
                        <file name="localization/zh_TW.inc" role="data"></file>
 
                        <file name="drivers/chgsaslpasswd.c" role="data"></file>
                        <file name="localization/zh_TW.inc" role="data"></file>
 
                        <file name="drivers/chgsaslpasswd.c" role="data"></file>
 - Virtualmin driver: Add option for setting username format (#1487781)
             </notes>
         </release>
 - Virtualmin driver: Add option for setting username format (#1487781)
             </notes>
         </release>
+        <release>
+               <date>2011-10-26</date>
+               <time>12:00</time>
+               <version>
+                       <release>2.3</release>
+                       <api>1.6</api>
+               </version>
+               <stability>
+                       <release>stable</release>
+                       <api>stable</api>
+               </stability>
+               <license uri="http://www.gnu.org/licenses/gpl-2.0.html">GNU GPLv2</license>
+               <notes>
+- When old and new passwords are the same, do nothing, return success (#1487823)
+- Fixed Samba password hashing in 'ldap' driver
+- Added 'password_change' hook for plugin actions after successful password change
+- Fixed bug where 'doveadm pw' command was used as dovecotpw utility
+- Improve generated crypt() passwords (#1488136)
+            </notes>
+        </release>
     </changelog>
 </package>
     </changelog>
 </package>
index b1c7863fcea7ce7391d97fbd256ce4ade9c6b4dd..06e3448f0dfe529d8d1e29ad708f19a4d6f74c93 100644 (file)
@@ -223,7 +223,7 @@ class password extends rcube_plugin
     {
         $config = rcmail::get_instance()->config;
         $driver = $this->home.'/drivers/'.$config->get('password_driver', 'sql').'.php';
     {
         $config = rcmail::get_instance()->config;
         $driver = $this->home.'/drivers/'.$config->get('password_driver', 'sql').'.php';
-    
+
         if (!is_readable($driver)) {
             raise_error(array(
                 'code' => 600,
         if (!is_readable($driver)) {
             raise_error(array(
                 'code' => 600,
@@ -233,7 +233,7 @@ class password extends rcube_plugin
             ), true, false);
             return $this->gettext('internalerror');
         }
             ), true, false);
             return $this->gettext('internalerror');
         }
-    
+
         include($driver);
 
         if (!function_exists('password_save')) {
         include($driver);
 
         if (!function_exists('password_save')) {
@@ -270,5 +270,5 @@ class password extends rcube_plugin
         }
 
         return $reason;
         }
 
         return $reason;
-    }                                     
+    }
 }
 }
diff --git a/plugins/userinfo/localization/fr_FR.inc b/plugins/userinfo/localization/fr_FR.inc
new file mode 100644 (file)
index 0000000..ef7b8aa
--- /dev/null
@@ -0,0 +1,9 @@
+<?php
+
+$labels = array();
+$labels['userinfo'] = 'Info utilisateur';
+$labels['created'] = 'Date de création';
+$labels['lastlogin'] = 'Dernière connexion';
+$labels['defaultidentity'] = 'Identité principale';
+
+?>
diff --git a/plugins/userinfo/localization/ro_RO.inc b/plugins/userinfo/localization/ro_RO.inc
new file mode 100644 (file)
index 0000000..bf7a476
--- /dev/null
@@ -0,0 +1,9 @@
+<?php
+
+$labels = array();
+$labels['userinfo'] = 'Informatii utilisator';
+$labels['created'] = 'Data creatiei';
+$labels['lastlogin'] = 'Ultima conectare';
+$labels['defaultidentity'] = 'Identitate principala';
+
+?>
index 8d01bb1ad3ddeccf89fca639e6aebff173b04410..ae90562f08301fb63ff3cf588464bab30bc28520 100644 (file)
@@ -15,7 +15,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: clisetup.php 4678 2011-04-20 13:58:21Z alec $
+ $Id: clisetup.php 5299 2011-10-03 09:25:33Z alec $
 
 */
 
 
 */
 
@@ -25,6 +25,8 @@ if (php_sapi_name() != 'cli') {
 
 require_once INSTALL_PATH . 'program/include/iniset.php';
 
 
 require_once INSTALL_PATH . 'program/include/iniset.php';
 
+// Unset max. execution time limit, set to 120 seconds in iniset.php
+@set_time_limit(0);
 
 /**
  * Parse commandline arguments into a hash array
 
 /**
  * Parse commandline arguments into a hash array
index 10ae11e51b5eac9372132394c7404e566afb9c04..d8ead568cbbdf4e8ee96a0747f285d6ba42cec60 100755 (executable)
@@ -16,7 +16,7 @@
  |         Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  |         Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: iniset.php 5292 2011-09-28 19:16:41Z thomasb $
+ $Id: iniset.php 5582 2011-12-09 08:55:40Z thomasb $
 
 */
 
 
 */
 
@@ -37,7 +37,7 @@ foreach ($crit_opts as $optname => $optval) {
 }
 
 // application constants
 }
 
 // application constants
-define('RCMAIL_VERSION', '0.6');
+define('RCMAIL_VERSION', '0.7');
 define('RCMAIL_CHARSET', 'UTF-8');
 define('JS_OBJECT_NAME', 'rcmail');
 define('RCMAIL_START', microtime(true));
 define('RCMAIL_CHARSET', 'UTF-8');
 define('JS_OBJECT_NAME', 'rcmail');
 define('RCMAIL_START', microtime(true));
index 30d90993e7b36af08313cd170699da061dee33b7..f92976245328fabd52946f2b01195d47a0b4ae6a 100644 (file)
@@ -15,7 +15,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: main.inc 5151 2011-08-31 12:49:44Z alec $
+ $Id: main.inc 5591 2011-12-10 14:16:31Z thomasb $
 
 */
 
 
 */
 
@@ -97,9 +97,9 @@ function rcube_label($p, $domain=null)
  *
  * @see rcmail::text_exists()
  */
  *
  * @see rcmail::text_exists()
  */
-function rcube_label_exists($name, $domain=null)
+function rcube_label_exists($name, $domain=null, &$ref_domain = null)
 {
 {
-  return rcmail::get_instance()->text_exists($name, $domain);
+  return rcmail::get_instance()->text_exists($name, $domain, $ref_domain);
 }
 
 
 }
 
 
@@ -169,11 +169,17 @@ function rcmail_cache_gc()
   // get target timestamp
   $ts = get_offset_time($rcmail->config->get('message_cache_lifetime', '30d'), -1);
 
   // get target timestamp
   $ts = get_offset_time($rcmail->config->get('message_cache_lifetime', '30d'), -1);
 
-  $db->query("DELETE FROM ".get_table_name('messages')."
-             WHERE  created < " . $db->fromunixtime($ts));
+  $db->query("DELETE FROM ".get_table_name('cache_messages')
+        ." WHERE changed < " . $db->fromunixtime($ts));
 
 
-  $db->query("DELETE FROM ".get_table_name('cache')."
-              WHERE  created < " . $db->fromunixtime($ts));
+  $db->query("DELETE FROM ".get_table_name('cache_index')
+        ." WHERE changed < " . $db->fromunixtime($ts));
+
+  $db->query("DELETE FROM ".get_table_name('cache_thread')
+        ." WHERE changed < " . $db->fromunixtime($ts));
+
+  $db->query("DELETE FROM ".get_table_name('cache')
+        ." WHERE created < " . $db->fromunixtime($ts));
 }
 
 
 }
 
 
@@ -634,20 +640,23 @@ function JQ($str)
 function get_input_value($fname, $source, $allow_html=FALSE, $charset=NULL)
 {
   $value = NULL;
 function get_input_value($fname, $source, $allow_html=FALSE, $charset=NULL)
 {
   $value = NULL;
-  
-  if ($source==RCUBE_INPUT_GET && isset($_GET[$fname]))
-    $value = $_GET[$fname];
-  else if ($source==RCUBE_INPUT_POST && isset($_POST[$fname]))
-    $value = $_POST[$fname];
-  else if ($source==RCUBE_INPUT_GPC)
-    {
+
+  if ($source == RCUBE_INPUT_GET) {
+    if (isset($_GET[$fname]))
+      $value = $_GET[$fname];
+  }
+  else if ($source == RCUBE_INPUT_POST) {
+    if (isset($_POST[$fname]))
+      $value = $_POST[$fname];
+  }
+  else if ($source == RCUBE_INPUT_GPC) {
     if (isset($_POST[$fname]))
       $value = $_POST[$fname];
     else if (isset($_GET[$fname]))
       $value = $_GET[$fname];
     else if (isset($_COOKIE[$fname]))
       $value = $_COOKIE[$fname];
     if (isset($_POST[$fname]))
       $value = $_POST[$fname];
     else if (isset($_GET[$fname]))
       $value = $_GET[$fname];
     else if (isset($_COOKIE[$fname]))
       $value = $_COOKIE[$fname];
-    }
+  }
 
   return parse_input_value($value, $allow_html, $charset);
 }
 
   return parse_input_value($value, $allow_html, $charset);
 }
@@ -655,7 +664,7 @@ function get_input_value($fname, $source, $allow_html=FALSE, $charset=NULL)
 /**
  * Parse/validate input value. See get_input_value()
  * Performs stripslashes() and charset conversion if necessary
 /**
  * Parse/validate input value. See get_input_value()
  * Performs stripslashes() and charset conversion if necessary
- * 
+ *
  * @param  string   Input value
  * @param  boolean  Allow HTML tags in field value
  * @param  string   Charset to convert into
  * @param  string   Input value
  * @param  boolean  Allow HTML tags in field value
  * @param  string   Charset to convert into
@@ -681,15 +690,21 @@ function parse_input_value($value, $allow_html=FALSE, $charset=NULL)
   else if (get_magic_quotes_gpc() || get_magic_quotes_runtime())
     $value = stripslashes($value);
 
   else if (get_magic_quotes_gpc() || get_magic_quotes_runtime())
     $value = stripslashes($value);
 
-  // remove HTML tags if not allowed    
+  // remove HTML tags if not allowed
   if (!$allow_html)
     $value = strip_tags($value);
   if (!$allow_html)
     $value = strip_tags($value);
-  
+
+  $output_charset = is_object($OUTPUT) ? $OUTPUT->get_charset() : null;
+
+  // remove invalid characters (#1488124)
+  if ($output_charset == 'UTF-8')
+    $value = rc_utf8_clean($value);
+
   // convert to internal charset
   // convert to internal charset
-  if (is_object($OUTPUT) && $charset)
-    return rcube_charset_convert($value, $OUTPUT->get_charset(), $charset);
-  else
-    return $value;
+  if ($charset && $output_charset)
+    $value = rcube_charset_convert($value, $output_charset, $charset);
+
+  return $value;
 }
 
 /**
 }
 
 /**
@@ -699,15 +714,16 @@ function parse_input_value($value, $allow_html=FALSE, $charset=NULL)
  * @param  int   Source to get value from (GPC)
  * @return array Hash array with all request parameters
  */
  * @param  int   Source to get value from (GPC)
  * @return array Hash array with all request parameters
  */
-function request2param($mode = RCUBE_INPUT_GPC)
+function request2param($mode = RCUBE_INPUT_GPC, $ignore = 'task|action')
 {
   $out = array();
   $src = $mode == RCUBE_INPUT_GET ? $_GET : ($mode == RCUBE_INPUT_POST ? $_POST : $_REQUEST);
   foreach ($src as $key => $value) {
     $fname = $key[0] == '_' ? substr($key, 1) : $key;
 {
   $out = array();
   $src = $mode == RCUBE_INPUT_GET ? $_GET : ($mode == RCUBE_INPUT_POST ? $_POST : $_REQUEST);
   foreach ($src as $key => $value) {
     $fname = $key[0] == '_' ? substr($key, 1) : $key;
-    $out[$fname] = get_input_value($key, $mode);
+    if ($ignore && !preg_match('/^(' . $ignore . ')$/', $fname))
+      $out[$fname] = get_input_value($key, $mode);
   }
   }
-  
+
   return $out;
 }
 
   return $out;
 }
 
@@ -723,12 +739,14 @@ function asciiwords($str, $css_id = false, $replace_with = '')
 
 /**
  * Convert the given string into a valid HTML identifier
 
 /**
  * Convert the given string into a valid HTML identifier
- * Same functionality as done in app.js with this.identifier_expr
- *
+ * Same functionality as done in app.js with rcube_webmail.html_identifier()
  */
  */
-function html_identifier($str)
+function html_identifier($str, $encode=false)
 {
 {
-  return asciiwords($str, true, '_');
+  if ($encode)
+    return rtrim(strtr(base64_encode($str), '+/', '-_'), '=');
+  else
+    return asciiwords($str, true, '_');
 }
 
 /**
 }
 
 /**
@@ -765,52 +783,48 @@ function strip_newlines($str)
  * @return string HTML table code
  */
 function rcube_table_output($attrib, $table_data, $a_show_cols, $id_col)
  * @return string HTML table code
  */
 function rcube_table_output($attrib, $table_data, $a_show_cols, $id_col)
-  {
+{
   global $RCMAIL;
   global $RCMAIL;
-  
+
   $table = new html_table(/*array('cols' => count($a_show_cols))*/);
   $table = new html_table(/*array('cols' => count($a_show_cols))*/);
-    
+
   // add table header
   if (!$attrib['noheader'])
     foreach ($a_show_cols as $col)
       $table->add_header($col, Q(rcube_label($col)));
   // add table header
   if (!$attrib['noheader'])
     foreach ($a_show_cols as $col)
       $table->add_header($col, Q(rcube_label($col)));
-  
+
   $c = 0;
   $c = 0;
-  if (!is_array($table_data)) 
+  if (!is_array($table_data))
   {
     $db = $RCMAIL->get_dbh();
     while ($table_data && ($sql_arr = $db->fetch_assoc($table_data)))
     {
   {
     $db = $RCMAIL->get_dbh();
     while ($table_data && ($sql_arr = $db->fetch_assoc($table_data)))
     {
-      $zebra_class = $c % 2 ? 'even' : 'odd';
-      $table->add_row(array('id' => 'rcmrow' . html_identifier($sql_arr[$id_col]), 'class' => $zebra_class));
+      $table->add_row(array('id' => 'rcmrow' . html_identifier($sql_arr[$id_col])));
 
       // format each col
       foreach ($a_show_cols as $col)
         $table->add($col, Q($sql_arr[$col]));
 
       // format each col
       foreach ($a_show_cols as $col)
         $table->add($col, Q($sql_arr[$col]));
-      
+
       $c++;
     }
   }
       $c++;
     }
   }
-  else 
-  {
+  else {
     foreach ($table_data as $row_data)
     {
     foreach ($table_data as $row_data)
     {
-      $zebra_class = $c % 2 ? 'even' : 'odd';
-      if (!empty($row_data['class']))
-        $zebra_class .= ' '.$row_data['class'];
+      $class = !empty($row_data['class']) ? $row_data['class'] : '';
 
 
-      $table->add_row(array('id' => 'rcmrow' . html_identifier($row_data[$id_col]), 'class' => $zebra_class));
+      $table->add_row(array('id' => 'rcmrow' . html_identifier($row_data[$id_col]), 'class' => $class));
 
       // format each col
       foreach ($a_show_cols as $col)
         $table->add($col, Q(is_array($row_data[$col]) ? $row_data[$col][0] : $row_data[$col]));
 
       // format each col
       foreach ($a_show_cols as $col)
         $table->add($col, Q(is_array($row_data[$col]) ? $row_data[$col][0] : $row_data[$col]));
-        
+
       $c++;
     }
   }
 
   return $table->show($attrib);
       $c++;
     }
   }
 
   return $table->show($attrib);
-  }
+}
 
 
 /**
 
 
 /**
@@ -869,23 +883,37 @@ function rcmail_get_edit_field($col, $value, $attrib, $type='text')
  * @param string Container ID to use as prefix
  * @return string Modified CSS source
  */
  * @param string Container ID to use as prefix
  * @return string Modified CSS source
  */
-function rcmail_mod_css_styles($source, $container_id)
+function rcmail_mod_css_styles($source, $container_id, $allow_remote=false)
   {
   $last_pos = 0;
   $replacements = new rcube_string_replacer;
 
   // ignore the whole block if evil styles are detected
   {
   $last_pos = 0;
   $replacements = new rcube_string_replacer;
 
   // ignore the whole block if evil styles are detected
-  $stripped = preg_replace('/[^a-z\(:;]/', '', rcmail_xss_entity_decode($source));
-  if (preg_match('/expression|behavior|url\(|import[^a]/', $stripped))
+  $source = rcmail_xss_entity_decode($source);
+  $stripped = preg_replace('/[^a-z\(:;]/i', '', $source);
+  $evilexpr = 'expression|behavior|javascript:|import[^a]' . (!$allow_remote ? '|url\(' : '');
+  if (preg_match("/$evilexpr/i", $stripped))
     return '/* evil! */';
 
     return '/* evil! */';
 
-  // remove css comments (sometimes used for some ugly hacks)
-  $source = preg_replace('!/\*(.+)\*/!Ums', '', $source);
-
   // cut out all contents between { and }
   // cut out all contents between { and }
-  while (($pos = strpos($source, '{', $last_pos)) && ($pos2 = strpos($source, '}', $pos)))
-  {
-    $key = $replacements->add(substr($source, $pos+1, $pos2-($pos+1)));
+  while (($pos = strpos($source, '{', $last_pos)) && ($pos2 = strpos($source, '}', $pos))) {
+    $styles = substr($source, $pos+1, $pos2-($pos+1));
+
+    // check every line of a style block...
+    if ($allow_remote) {
+      $a_styles = preg_split('/;[\r\n]*/', $styles, -1, PREG_SPLIT_NO_EMPTY);
+      foreach ($a_styles as $line) {
+        $stripped = preg_replace('/[^a-z\(:;]/i', '', $line);
+        // ... and only allow strict url() values
+        if (stripos($stripped, 'url(') && !preg_match('!url\s*\([ "\'](https?:)//[a-z0-9/._+-]+["\' ]\)!Uims', $line)) {
+          $a_styles = array('/* evil! */');
+          break;
+        }
+      }
+      $styles = join(";\n", $a_styles);
+    }
+
+    $key = $replacements->add($styles);
     $source = substr($source, 0, $pos+1) . $replacements->get_replacement($key) . substr($source, $pos2, strlen($source)-$pos2);
     $last_pos = $pos+2;
   }
     $source = substr($source, 0, $pos+1) . $replacements->get_replacement($key) . substr($source, $pos2, strlen($source)-$pos2);
     $last_pos = $pos+2;
   }
@@ -923,7 +951,7 @@ function rcmail_xss_entity_decode($content)
 {
   $out = html_entity_decode(html_entity_decode($content));
   $out = preg_replace_callback('/\\\([0-9a-f]{4})/i', 'rcmail_xss_entity_decode_callback', $out);
 {
   $out = html_entity_decode(html_entity_decode($content));
   $out = preg_replace_callback('/\\\([0-9a-f]{4})/i', 'rcmail_xss_entity_decode_callback', $out);
-  $out = preg_replace('#/\*.*\*/#Um', '', $out);
+  $out = preg_replace('#/\*.*\*/#Ums', '', $out);
   return $out;
 }
 
   return $out;
 }
 
@@ -1015,15 +1043,15 @@ function rcube_strtotime($date)
  * Convert the given date to a human readable form
  * This uses the date formatting properties from config
  *
  * Convert the given date to a human readable form
  * This uses the date formatting properties from config
  *
- * @param mixed Date representation (string or timestamp)
+ * @param mixed  Date representation (string or timestamp)
  * @param string Date format to use
  * @param string Date format to use
+ * @param bool   Enables date convertion according to user timezone
+ *
  * @return string Formatted date string
  */
  * @return string Formatted date string
  */
-function format_date($date, $format=NULL)
+function format_date($date, $format=NULL, $convert=true)
 {
   global $RCMAIL, $CONFIG;
 {
   global $RCMAIL, $CONFIG;
-  
-  $ts = NULL;
 
   if (!empty($date))
     $ts = rcube_strtotime($date);
 
   if (!empty($date))
     $ts = rcube_strtotime($date);
@@ -1031,31 +1059,37 @@ function format_date($date, $format=NULL)
   if (empty($ts))
     return '';
 
   if (empty($ts))
     return '';
 
-  // get user's timezone
-  $tz = $RCMAIL->config->get_timezone();
-
-  // convert time to user's timezone
-  $timestamp = $ts - date('Z', $ts) + ($tz * 3600);
+  if ($convert) {
+    // get user's timezone offset
+    $tz = $RCMAIL->config->get_timezone();
 
 
-  // get current timestamp in user's timezone
-  $now = time();  // local time
-  $now -= (int)date('Z'); // make GMT time
-  $now += ($tz * 3600); // user's time
-  $now_date = getdate($now);
+    // convert time to user's timezone
+    $timestamp = $ts - date('Z', $ts) + ($tz * 3600);
 
 
-  $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']);
+    // get current timestamp in user's timezone
+    $now = time();  // local time
+    $now -= (int)date('Z'); // make GMT time
+    $now += ($tz * 3600); // user's time
+  }
+  else {
+    $now       = time();
+    $timestamp = $ts;
+  }
 
   // define date format depending on current time
   if (!$format) {
 
   // define date format depending on current time
   if (!$format) {
+    $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']);
+
     if ($CONFIG['prettydate'] && $timestamp > $today_limit && $timestamp < $now) {
     if ($CONFIG['prettydate'] && $timestamp > $today_limit && $timestamp < $now) {
-      $format = $CONFIG['date_today'] ? $CONFIG['date_today'] : 'H:i';
+      $format = $RCMAIL->config->get('date_today', $RCMAIL->config->get('time_format', 'H:i'));
       $today  = true;
     }
     else if ($CONFIG['prettydate'] && $timestamp > $week_limit && $timestamp < $now)
       $today  = true;
     }
     else if ($CONFIG['prettydate'] && $timestamp > $week_limit && $timestamp < $now)
-      $format = $CONFIG['date_short'] ? $CONFIG['date_short'] : 'D H:i';
+      $format = $RCMAIL->config->get('date_short', 'D H:i');
     else
     else
-      $format = $CONFIG['date_long'] ? $CONFIG['date_long'] : 'd.m.Y H:i';
+      $format = $RCMAIL->config->get('date_long', 'Y-m-d H:i');
   }
 
   // strftime() format
   }
 
   // strftime() format
@@ -1207,9 +1241,9 @@ function rcmail_mailbox_select($p = array())
     $p['folder_name'] = '*';
 
   if ($p['unsubscribed'])
     $p['folder_name'] = '*';
 
   if ($p['unsubscribed'])
-    $list = $RCMAIL->imap->list_unsubscribed('', $p['folder_name'], $p['folder_filter']);
+    $list = $RCMAIL->imap->list_unsubscribed('', $p['folder_name'], $p['folder_filter'], $p['folder_rights']);
   else
   else
-    $list = $RCMAIL->imap->list_mailboxes('', $p['folder_name'], $p['folder_filter']);
+    $list = $RCMAIL->imap->list_mailboxes('', $p['folder_name'], $p['folder_filter'], $p['folder_rights']);
 
   $delimiter = $RCMAIL->imap->get_hierarchy_delimiter();
 
 
   $delimiter = $RCMAIL->imap->get_hierarchy_delimiter();
 
@@ -1223,7 +1257,7 @@ function rcmail_mailbox_select($p = array())
   if ($p['noselection'])
     $select->add($p['noselection'], '');
 
   if ($p['noselection'])
     $select->add($p['noselection'], '');
 
-  rcmail_render_folder_tree_select($a_mailboxes, $mbox, $p['maxlength'], $select, $p['realnames'], 0, $p['exceptions']);
+  rcmail_render_folder_tree_select($a_mailboxes, $mbox, $p['maxlength'], $select, $p['realnames'], 0, $p);
 
   return $select;
 }
 
   return $select;
 }
@@ -1272,11 +1306,6 @@ function rcmail_build_folder_tree(&$arrFolders, $folder, $delm='/', $path='')
   $path .= $prefix.$currentFolder;
 
   if (!isset($arrFolders[$currentFolder])) {
   $path .= $prefix.$currentFolder;
 
   if (!isset($arrFolders[$currentFolder])) {
-    // Check \Noselect option (if options are in cache)
-    if (!$virtual && ($opts = $RCMAIL->imap->mailbox_options($path))) {
-      $virtual = in_array('\\Noselect', $opts);
-    }
-
     $arrFolders[$currentFolder] = array(
       'id' => $path,
       'name' => rcube_charset_convert($currentFolder, 'UTF7-IMAP'),
     $arrFolders[$currentFolder] = array(
       'id' => $path,
       'name' => rcube_charset_convert($currentFolder, 'UTF7-IMAP'),
@@ -1304,13 +1333,14 @@ function rcmail_render_folder_tree_html(&$arrFolders, &$mbox_name, &$jslist, $at
   $realnames = (bool)$attrib['realnames'];
   $msgcounts = $RCMAIL->imap->get_cache('messagecount');
 
   $realnames = (bool)$attrib['realnames'];
   $msgcounts = $RCMAIL->imap->get_cache('messagecount');
 
-  $idx = 0;
   $out = '';
   foreach ($arrFolders as $key => $folder) {
   $out = '';
   foreach ($arrFolders as $key => $folder) {
-    $zebra_class = (($nestLevel+1)*$idx) % 2 == 0 ? 'even' : 'odd';
-    $title = null;
+    $title        = null;
+    $folder_class = rcmail_folder_classname($folder['id']);
+    $collapsed    = strpos($CONFIG['collapsed_folders'], '&'.rawurlencode($folder['id']).'&') !== false;
+    $unread       = $msgcounts ? intval($msgcounts[$folder['id']]['UNSEEN']) : 0;
 
 
-    if (($folder_class = rcmail_folder_classname($folder['id'])) && !$realnames) {
+    if ($folder_class && !$realnames) {
       $foldername = rcube_label($folder_class);
     }
     else {
       $foldername = rcube_label($folder_class);
     }
     else {
@@ -1326,31 +1356,16 @@ function rcmail_render_folder_tree_html(&$arrFolders, &$mbox_name, &$jslist, $at
     }
 
     // make folder name safe for ids and class names
     }
 
     // make folder name safe for ids and class names
-    $folder_id = html_identifier($folder['id']);
+    $folder_id = html_identifier($folder['id'], true);
     $classes = array('mailbox');
 
     // set special class for Sent, Drafts, Trash and Junk
     $classes = array('mailbox');
 
     // set special class for Sent, Drafts, Trash and Junk
-    if ($folder['id'] == $CONFIG['sent_mbox'])
-      $classes[] = 'sent';
-    else if ($folder['id'] == $CONFIG['drafts_mbox'])
-      $classes[] = 'drafts';
-    else if ($folder['id'] == $CONFIG['trash_mbox'])
-      $classes[] = 'trash';
-    else if ($folder['id'] == $CONFIG['junk_mbox'])
-      $classes[] = 'junk';
-    else if ($folder['id'] == 'INBOX')
-      $classes[] = 'inbox';
-    else
-      $classes[] = '_'.asciiwords($folder_class ? $folder_class : strtolower($folder['id']), true);
-
-    $classes[] = $zebra_class;
+    if ($folder_class)
+      $classes[] = $folder_class;
 
     if ($folder['id'] == $mbox_name)
       $classes[] = 'selected';
 
 
     if ($folder['id'] == $mbox_name)
       $classes[] = 'selected';
 
-    $collapsed = strpos($CONFIG['collapsed_folders'], '&'.rawurlencode($folder['id']).'&') !== false;
-    $unread = $msgcounts ? intval($msgcounts[$folder['id']]['UNSEEN']) : 0;
-
     if ($folder['virtual'])
       $classes[] = 'virtual';
     else if ($unread)
     if ($folder['virtual'])
       $classes[] = 'virtual';
     else if ($unread)
@@ -1384,7 +1399,6 @@ function rcmail_render_folder_tree_html(&$arrFolders, &$mbox_name, &$jslist, $at
     }
 
     $out .= "</li>\n";
     }
 
     $out .= "</li>\n";
-    $idx++;
   }
 
   return $out;
   }
 
   return $out;
@@ -1396,30 +1410,40 @@ function rcmail_render_folder_tree_html(&$arrFolders, &$mbox_name, &$jslist, $at
  * @access private
  * @return string
  */
  * @access private
  * @return string
  */
-function rcmail_render_folder_tree_select(&$arrFolders, &$mbox_name, $maxlength, &$select, $realnames=false, $nestLevel=0, $exceptions=array())
+function rcmail_render_folder_tree_select(&$arrFolders, &$mbox_name, $maxlength, &$select, $realnames=false, $nestLevel=0, $opts=array())
 {
 {
+  global $RCMAIL;
+
   $out = '';
 
   foreach ($arrFolders as $key => $folder) {
   $out = '';
 
   foreach ($arrFolders as $key => $folder) {
-    if (empty($exceptions) || !in_array($folder['id'], $exceptions)) {
-      if (!$realnames && ($folder_class = rcmail_folder_classname($folder['id'])))
-        $foldername = rcube_label($folder_class);
-      else {
-        $foldername = $folder['name'];
-
-        // shorten the folder name to a given length
-        if ($maxlength && $maxlength>1)
-          $foldername = abbreviate_string($foldername, $maxlength);
-      }
-
-      $select->add(str_repeat('&nbsp;', $nestLevel*4) . $foldername, $folder['id']);
+    // skip exceptions (and its subfolders)
+    if (!empty($opts['exceptions']) && in_array($folder['id'], $opts['exceptions'])) {
+      continue;
     }
     }
-    else if ($nestLevel)
+
+    // skip folders in which it isn't possible to create subfolders
+    if (!empty($opts['skip_noinferiors']) && ($attrs = $RCMAIL->imap->mailbox_attributes($folder['id']))
+        && in_array('\\Noinferiors', $attrs)
+    ) {
       continue;
       continue;
+    }
+
+    if (!$realnames && ($folder_class = rcmail_folder_classname($folder['id'])))
+      $foldername = rcube_label($folder_class);
+    else {
+      $foldername = $folder['name'];
+
+      // shorten the folder name to a given length
+      if ($maxlength && $maxlength>1)
+        $foldername = abbreviate_string($foldername, $maxlength);
+    }
+
+    $select->add(str_repeat('&nbsp;', $nestLevel*4) . $foldername, $folder['id']);
 
     if (!empty($folder['folders']))
       $out .= rcmail_render_folder_tree_select($folder['folders'], $mbox_name, $maxlength,
 
     if (!empty($folder['folders']))
       $out .= rcmail_render_folder_tree_select($folder['folders'], $mbox_name, $maxlength,
-        $select, $realnames, $nestLevel+1, $exceptions);
+        $select, $realnames, $nestLevel+1, $opts);
   }
 
   return $out;
   }
 
   return $out;
@@ -1568,7 +1592,11 @@ function rcmail_display_server_error($fallback=null, $fallback_args=null)
         $RCMAIL->output->show_message('errorreadonly', 'error');
     }
     else if ($err_code && ($err_str = $RCMAIL->imap->get_error_str())) {
         $RCMAIL->output->show_message('errorreadonly', 'error');
     }
     else if ($err_code && ($err_str = $RCMAIL->imap->get_error_str())) {
-        $RCMAIL->output->show_message('servererrormsg', 'error', array('msg' => $err_str));
+        // try to detect access rights problem and display appropriate message
+        if (stripos($err_str, 'Permission denied') !== false)
+            $RCMAIL->output->show_message('errornoperm', 'error');
+        else
+            $RCMAIL->output->show_message('servererrormsg', 'error', array('msg' => $err_str));
     }
     else if ($fallback) {
         $RCMAIL->output->show_message($fallback, 'error', $fallback_args);
     }
     else if ($fallback) {
         $RCMAIL->output->show_message($fallback, 'error', $fallback_args);
@@ -1591,7 +1619,7 @@ function rcube_html_editor($mode='')
   $hook = $RCMAIL->plugins->exec_hook('html_editor', array('mode' => $mode));
 
   if ($hook['abort'])
   $hook = $RCMAIL->plugins->exec_hook('html_editor', array('mode' => $mode));
 
   if ($hook['abort'])
-    return;  
+    return;
 
   $lang = strtolower($_SESSION['language']);
 
 
   $lang = strtolower($_SESSION['language']);
 
@@ -1603,9 +1631,14 @@ function rcube_html_editor($mode='')
 
   $RCMAIL->output->include_script('tiny_mce/tiny_mce.js');
   $RCMAIL->output->include_script('editor.js');
 
   $RCMAIL->output->include_script('tiny_mce/tiny_mce.js');
   $RCMAIL->output->include_script('editor.js');
-  $RCMAIL->output->add_script(sprintf("rcmail_editor_init('\$__skin_path', '%s', %d, '%s');",
-    JQ($lang), intval($CONFIG['enable_spellcheck']), $mode),
-    'foot');
+  $RCMAIL->output->add_script(sprintf("rcmail_editor_init(%s)",
+    json_encode(array(
+        'mode'       => $mode,
+        'skin_path'  => '$__skin_path',
+        'lang'       => $lang,
+        'spellcheck' => intval($CONFIG['enable_spellcheck']),
+        'spelldict'  => intval($CONFIG['spellcheck_dictionary']),
+    ))), 'foot');
 }
 
 
 }
 
 
@@ -2369,5 +2402,5 @@ function rcube_autocomplete_init()
 
     $RCMAIL->output->set_env('autocomplete_max', (int)$RCMAIL->config->get('autocomplete_max', 15));
     $RCMAIL->output->set_env('autocomplete_min_length', $RCMAIL->config->get('autocomplete_min_length'));
 
     $RCMAIL->output->set_env('autocomplete_max', (int)$RCMAIL->config->get('autocomplete_max', 15));
     $RCMAIL->output->set_env('autocomplete_min_length', $RCMAIL->config->get('autocomplete_min_length'));
-    $RCMAIL->output->add_label('autocompletechars');
+    $RCMAIL->output->add_label('autocompletechars', 'autocompletemore');
 }
 }
index 5323b649f54ff371759e2869afdfde888573d6d7..aa3bade71e3e75d209c1a4ca3c00b4c5df4a1423 100644 (file)
@@ -6,6 +6,7 @@
  |                                                                       |
  | This file is part of the Roundcube Webmail client                     |
  | Copyright (C) 2008-2011, The Roundcube Dev Team                       |
  |                                                                       |
  | This file is part of the Roundcube Webmail client                     |
  | Copyright (C) 2008-2011, The Roundcube Dev Team                       |
+ | Copyright (C) 2011, Kolab Systems AG                                  |
  | Licensed under the GNU GPL                                            |
  |                                                                       |
  | PURPOSE:                                                              |
  | Licensed under the GNU GPL                                            |
  |                                                                       |
  | PURPOSE:                                                              |
@@ -15,7 +16,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: rcmail.php 5235 2011-09-19 06:43:57Z alec $
+ $Id: rcmail.php 5527 2011-12-02 09:58:03Z alec $
 
 */
 
 
 */
 
@@ -452,8 +453,7 @@ class rcmail
     }
 
     // add to the 'books' array for shutdown function
     }
 
     // add to the 'books' array for shutdown function
-    if (!isset($this->address_books[$id]))
-      $this->address_books[$id] = $contacts;
+    $this->address_books[$id] = $contacts;
 
     return $contacts;
   }
 
     return $contacts;
   }
@@ -482,7 +482,8 @@ class rcmail
         'name'     => rcube_label('personaladrbook'),
         'groups'   => $this->address_books['0']->groups,
         'readonly' => $this->address_books['0']->readonly,
         'name'     => rcube_label('personaladrbook'),
         'groups'   => $this->address_books['0']->groups,
         'readonly' => $this->address_books['0']->readonly,
-        'autocomplete' => in_array('sql', $autocomplete)
+        'autocomplete' => in_array('sql', $autocomplete),
+        'undelete' => $this->address_books['0']->undelete && $this->config->get('undo_timeout'),
       );
     }
 
       );
     }
 
@@ -592,7 +593,6 @@ class rcmail
       return;
 
     $this->imap = new rcube_imap();
       return;
 
     $this->imap = new rcube_imap();
-    $this->imap->debug_level = $this->config->get('debug_level');
     $this->imap->skip_deleted = $this->config->get('skip_deleted');
 
     // enable caching of imap data
     $this->imap->skip_deleted = $this->config->get('skip_deleted');
 
     // enable caching of imap data
@@ -614,7 +614,7 @@ class rcmail
     // Setting root and delimiter before establishing the connection
     // can save time detecting them using NAMESPACE and LIST
     $options = array(
     // 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_type'   => $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),
       'auth_cid'    => $this->config->get('imap_auth_cid'),
       'auth_pw'     => $this->config->get('imap_auth_pw'),
       'debug'       => (bool) $this->config->get('imap_debug', 0),
@@ -677,18 +677,21 @@ class rcmail
     if (session_id())
       return;
 
     if (session_id())
       return;
 
+    $sess_name   = $this->config->get('session_name');
+    $sess_domain = $this->config->get('session_domain');
+    $lifetime    = $this->config->get('session_lifetime', 0) * 60;
+
     // set session domain
     // set session domain
-    if ($domain = $this->config->get('session_domain')) {
-      ini_set('session.cookie_domain', $domain);
+    if ($sess_domain) {
+      ini_set('session.cookie_domain', $sess_domain);
     }
     // set session garbage collecting time according to session_lifetime
     }
     // set session garbage collecting time according to session_lifetime
-    $lifetime = $this->config->get('session_lifetime', 0) * 60;
     if ($lifetime) {
       ini_set('session.gc_maxlifetime', $lifetime * 2);
     }
 
     ini_set('session.cookie_secure', rcube_https_check());
     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.name', $sess_name ? $sess_name : 'roundcube_sessid');
     ini_set('session.use_cookies', 1);
     ini_set('session.use_only_cookies', 1);
     ini_set('session.serialize_handler', 'php');
     ini_set('session.use_cookies', 1);
     ini_set('session.use_only_cookies', 1);
     ini_set('session.serialize_handler', 'php');
@@ -728,7 +731,7 @@ class rcmail
       $keep_alive = max(60, $keep_alive);
       $this->session->set_keep_alive($keep_alive);
     }
       $keep_alive = max(60, $keep_alive);
       $this->session->set_keep_alive($keep_alive);
     }
-    
+
     $this->session->set_secret($this->config->get('des_key') . $_SERVER['HTTP_USER_AGENT']);
     $this->session->set_ip_check($this->config->get('ip_check'));
   }
     $this->session->set_secret($this->config->get('des_key') . $_SERVER['HTTP_USER_AGENT']);
     $this->session->set_ip_check($this->config->get('ip_check'));
   }
@@ -838,16 +841,8 @@ class rcmail
     if (!$imap_login)
       return false;
 
     if (!$imap_login)
       return false;
 
-    $this->set_imap_prop();
-
     // user already registered -> update user's record
     if (is_object($user)) {
     // user already registered -> update user's record
     if (is_object($user)) {
-      // fix some old settings according to namespace prefix
-      $this->fix_namespace_settings($user);
-
-      // create default folders on first login
-      if (!$user->data['last_login'] && $config['create_default_folders'])
-        $this->imap->create_default_folders();
       // update last login timestamp
       $user->touch();
     }
       // update last login timestamp
       $user->touch();
     }
@@ -855,13 +850,6 @@ class rcmail
     else if ($config['auto_create_user']) {
       if ($created = rcube_user::create($username, $host)) {
         $user = $created;
     else if ($config['auto_create_user']) {
       if ($created = rcube_user::create($username, $host)) {
         $user = $created;
-
-        // fix default settings according to namespace prefix
-        $this->fix_namespace_settings($user);
-
-        // create default folders on first login
-        if ($config['create_default_folders'])
-          $this->imap->create_default_folders();
       }
       else {
         raise_error(array(
       }
       else {
         raise_error(array(
@@ -881,9 +869,19 @@ class rcmail
 
     // login succeeded
     if (is_object($user) && $user->ID) {
 
     // login succeeded
     if (is_object($user) && $user->ID) {
+      // Configure environment
       $this->set_user($user);
       $this->set_user($user);
+      $this->set_imap_prop();
       $this->session_configure();
 
       $this->session_configure();
 
+      // fix some old settings according to namespace prefix
+      $this->fix_namespace_settings($user);
+
+      // create default folders on first login
+      if ($config['create_default_folders'] && (!empty($created) || empty($user->data['last_login']))) {
+        $this->imap->create_default_folders();
+      }
+
       // set session vars
       $_SESSION['user_id']   = $user->ID;
       $_SESSION['username']  = $user->data['username'];
       // set session vars
       $_SESSION['user_id']   = $user->ID;
       $_SESSION['username']  = $user->data['username'];
@@ -892,9 +890,11 @@ class rcmail
       $_SESSION['imap_ssl']  = $imap_ssl;
       $_SESSION['password']  = $this->encrypt($pass);
       $_SESSION['login_time'] = mktime();
       $_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']);
       if (isset($_REQUEST['_timezone']) && $_REQUEST['_timezone'] != '_default_')
         $_SESSION['timezone'] = floatval($_REQUEST['_timezone']);
+      if (isset($_REQUEST['_dstactive']) && $_REQUEST['_dstactive'] != '_default_')
+        $_SESSION['dst_active'] = intval($_REQUEST['_dstactive']);
 
       // force reloading complete list of subscribed mailboxes
       $this->imap->clear_cache('mailboxes', true);
 
       // force reloading complete list of subscribed mailboxes
       $this->imap->clear_cache('mailboxes', true);
@@ -973,7 +973,9 @@ class rcmail
   /**
    * Get localized text in the desired language
    *
   /**
    * Get localized text in the desired language
    *
-   * @param mixed Named parameters array or label name
+   * @param mixed   $attrib  Named parameters array or label name
+   * @param string  $domain  Label domain (plugin) name
+   *
    * @return string Localized text
    */
   public function gettext($attrib, $domain=null)
    * @return string Localized text
    */
   public function gettext($attrib, $domain=null)
@@ -988,7 +990,7 @@ class rcmail
 
     $nr = is_numeric($attrib['nr']) ? $attrib['nr'] : 1;
     $name = $attrib['name'] ? $attrib['name'] : '';
 
     $nr = is_numeric($attrib['nr']) ? $attrib['nr'] : 1;
     $name = $attrib['name'] ? $attrib['name'] : '';
-    
+
     // attrib contain text values: use them from now
     if (($setval = $attrib[strtolower($_SESSION['language'])]) || ($setval = $attrib['en_us']))
         $this->texts[$name] = $setval;
     // attrib contain text values: use them from now
     if (($setval = $attrib[strtolower($_SESSION['language'])]) || ($setval = $attrib['en_us']))
         $this->texts[$name] = $setval;
@@ -1044,19 +1046,40 @@ class rcmail
 
 
   /**
 
 
   /**
-   * Check if the given text lable exists
+   * Check if the given text label exists
+   *
+   * @param string  $name       Label name
+   * @param string  $domain     Label domain (plugin) name or '*' for all domains
+   * @param string  $ref_domain Sets domain name if label is found
    *
    *
-   * @param string Label name
    * @return boolean True if text exists (either in the current language or in en_US)
    */
    * @return boolean True if text exists (either in the current language or in en_US)
    */
-  public function text_exists($name, $domain=null)
+  public function text_exists($name, $domain = null, &$ref_domain = null)
   {
     // load localization files if not done yet
     if (empty($this->texts))
       $this->load_language();
 
   {
     // load localization files if not done yet
     if (empty($this->texts))
       $this->load_language();
 
-    // check for text with domain first
-    return ($domain && isset($this->texts[$domain.'.'.$name])) || isset($this->texts[$name]);
+    if (isset($this->texts[$name])) {
+        $ref_domain = '';
+        return true;
+    }
+
+    // any of loaded domains (plugins)
+    if ($domain == '*') {
+      foreach ($this->plugins->loaded_plugins() as $domain)
+        if (isset($this->texts[$domain.'.'.$name])) {
+          $ref_domain = $domain;
+          return true;
+        }
+    }
+    // specified domain
+    else if ($domain) {
+      $ref_domain = $domain;
+      return isset($this->texts[$domain.'.'.$name]);
+    }
+
+    return false;
   }
 
   /**
   }
 
   /**
@@ -1204,7 +1227,6 @@ class rcmail
 
     // before closing the database connection, write session data
     if ($_SERVER['REMOTE_ADDR'] && is_object($this->session)) {
 
     // before closing the database connection, write session data
     if ($_SERVER['REMOTE_ADDR'] && is_object($this->session)) {
-      $this->session->cleanup();
       session_write_close();
     }
 
       session_write_close();
     }
 
@@ -1246,7 +1268,7 @@ class rcmail
   {
     $sess_id = $_COOKIE[ini_get('session.name')];
     if (!$sess_id) $sess_id = session_id();
   {
     $sess_id = $_COOKIE[ini_get('session.name')];
     if (!$sess_id) $sess_id = session_id();
-    $plugin = $this->plugins->exec_hook('request_token', array('value' => md5('RT' . $this->task . $this->config->get('des_key') . $sess_id)));
+    $plugin = $this->plugins->exec_hook('request_token', array('value' => md5('RT' . $this->user->ID . $this->config->get('des_key') . $sess_id)));
     return $plugin['value'];
   }
 
     return $plugin['value'];
   }
 
@@ -1540,7 +1562,7 @@ class rcmail
 
     // use strtr behaviour of going through source string once
     $cmd = strtr($cmd, $replacements);
 
     // use strtr behaviour of going through source string once
     $cmd = strtr($cmd, $replacements);
-    
+
     return (string)shell_exec($cmd);
   }
 
     return (string)shell_exec($cmd);
   }
 
@@ -1576,7 +1598,7 @@ class rcmail
       }
     }
   }
       }
     }
   }
-  
+
   /**
    * Returns current action filename
    *
   /**
    * Returns current action filename
    *
@@ -1606,8 +1628,8 @@ class rcmail
     if (!$prefix_len)
       return;
 
     if (!$prefix_len)
       return;
 
-    $prefs = $user->get_prefs();
-    if (empty($prefs) || $prefs['namespace_fixed'])
+    $prefs = $this->config->all();
+    if (!empty($prefs['namespace_fixed']))
       return;
 
     // Build namespace prefix regexp
       return;
 
     // Build namespace prefix regexp
diff --git a/program/include/rcmail.php.orig b/program/include/rcmail.php.orig
new file mode 100644 (file)
index 0000000..7d0da0a
--- /dev/null
@@ -0,0 +1,1716 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | program/include/rcmail.php                                            |
+ |                                                                       |
+ | This file is part of the Roundcube Webmail client                     |
+ | Copyright (C) 2008-2011, The Roundcube Dev Team                       |
+ | Copyright (C) 2011, Kolab Systems AG                                  |
+ | Licensed under the GNU GPL                                            |
+ |                                                                       |
+ | PURPOSE:                                                              |
+ |   Application class providing core functions and holding              |
+ |   instances of all 'global' objects like db- and imap-connections     |
+ +-----------------------------------------------------------------------+
+ | Author: Thomas Bruederli <roundcube@gmail.com>                        |
+ +-----------------------------------------------------------------------+
+
+ $Id: rcmail.php 5527 2011-12-02 09:58:03Z 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 Memcache class.
+   *
+   * @var rcube_mdb2
+   */
+  public $memcache;
+
+  /**
+   * 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 $address_books = array();
+  private $caches = array();
+  private $action_map = array();
+  private $shutdown_functions = 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;
+  }
+  
+  
+  /**
+   * Get global handle for memcache access
+   *
+   * @return object Memcache
+   */
+  public function get_memcache()
+  {
+    if (!isset($this->memcache)) {
+      // no memcache support in PHP
+      if (!class_exists('Memcache')) {
+        $this->memcache = false;
+        return false;
+      }
+
+      $this->memcache = new Memcache;
+      $this->mc_available = 0;
+      
+      // add alll configured hosts to pool
+      $pconnect = $this->config->get('memcache_pconnect', true);
+      foreach ($this->config->get('memcache_hosts', array()) as $host) {
+        list($host, $port) = explode(':', $host);
+        if (!$port) $port = 11211;
+        $this->mc_available += intval($this->memcache->addServer($host, $port, $pconnect, 1, 1, 15, false, array($this, 'memcache_failure')));
+      }
+      
+      // test connection and failover (will result in $this->mc_available == 0 on complete failure)
+      $this->memcache->increment('__CONNECTIONTEST__', 1);  // NOP if key doesn't exist
+
+      if (!$this->mc_available)
+        $this->memcache = false;
+    }
+
+    return $this->memcache;
+  }
+  
+  /**
+   * Callback for memcache failure
+   */
+  public function memcache_failure($host, $port)
+  {
+    static $seen = array();
+    
+    // only report once
+    if (!$seen["$host:$port"]++) {
+      $this->mc_available--;
+      raise_error(array('code' => 604, 'type' => 'db',
+        'line' => __LINE__, 'file' => __FILE__,
+        'message' => "Memcache failure on host $host:$port"),
+        true, false);
+    }
+  }
+
+
+  /**
+   * Initialize and get cache object
+   *
+   * @param string $name   Cache identifier
+   * @param string $type   Cache type ('db', 'apc' or 'memcache')
+   * @param int    $ttl    Expiration time for cache items in seconds
+   * @param bool   $packed Enables/disables data serialization
+   *
+   * @return rcube_cache Cache object
+   */
+  public function get_cache($name, $type='db', $ttl=0, $packed=true)
+  {
+    if (!isset($this->caches[$name])) {
+      $this->caches[$name] = new rcube_cache($type, $_SESSION['user_id'], $name, $ttl, $packed);
+    }
+
+    return $this->caches[$name];
+  }
+
+
+  /**
+   * 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'));
+
+    // 'sql' is the alias for '0' used by autocomplete
+    if ($id == 'sql')
+        $id = '0';
+
+    // use existing instance
+    if (isset($this->address_books[$id]) && is_object($this->address_books[$id])
+      && is_a($this->address_books[$id], 'rcube_addressbook')
+      && (!$writeable || !$this->address_books[$id]->readonly)
+    ) {
+      $contacts = $this->address_books[$id];
+    }
+    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 {
+      $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'];
+      }
+      // get first source from the list
+      else if (!$id) {
+        $source = reset($this->get_address_sources($writeable));
+        if (!empty($source)) {
+          $contacts = $this->get_address_book($source['id']);
+          if ($contacts)
+            $id = $source['id'];
+        }
+      }
+    }
+
+    if (!$contacts) {
+      raise_error(array(
+        'code' => 700, 'type' => 'php',
+        'file' => __FILE__, 'line' => __LINE__,
+        'message' => "Addressbook source ($id) not found!"),
+        true, true);
+    }
+
+    // add to the 'books' array for shutdown function
+    $this->address_books[$id] = $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') {
+      if (!isset($this->address_books['0']))
+        $this->address_books['0'] = new rcube_contacts($this->db, $this->user->ID);
+      $list['0'] = array(
+        'id'       => '0',
+        'name'     => rcube_label('personaladrbook'),
+        'groups'   => $this->address_books['0']->groups,
+        'readonly' => $this->address_books['0']->readonly,
+        'autocomplete' => in_array('sql', $autocomplete),
+        'undelete' => $this->address_books['0']->undelete && $this->config->get('undo_timeout'),
+      );
+    }
+
+    if ($ldap_config) {
+      $ldap_config = (array) $ldap_config;
+      foreach ($ldap_config as $id => $prop)
+        $list[$id] = array(
+          'id'       => $id,
+          'name'     => $prop['name'],
+          'groups'   => is_array($prop['groups']),
+          'readonly' => !$prop['writable'],
+          'hidden'   => $prop['hidden'],
+          'autocomplete' => in_array($id, $autocomplete)
+        );
+    }
+
+    $plugin = $this->plugins->exec_hook('addressbooks_list', array('sources' => $list));
+    $list = $plugin['sources'];
+
+    foreach ($list as $idx => $item) {
+      // register source for shutdown function
+      if (!is_object($this->address_books[$item['id']]))
+        $this->address_books[$item['id']] = $item;
+      // remove from list if not writeable as requested
+      if ($writeable && $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 labels 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->imap->skip_deleted = $this->config->get('skip_deleted');
+
+    // enable caching of imap data
+    $imap_cache = $this->config->get('imap_cache');
+    $messages_cache = $this->config->get('messages_cache');
+    // for backward compatybility
+    if ($imap_cache === null && $messages_cache === null && $this->config->get('enable_caching')) {
+        $imap_cache     = 'db';
+        $messages_cache = true;
+    }
+    if ($imap_cache)
+        $this->imap->set_caching($imap_cache);
+    if ($messages_cache)
+        $this->imap->set_messages_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_type'   => $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;
+
+    $sess_name   = $this->config->get('session_name');
+    $sess_domain = $this->config->get('session_domain');
+    $lifetime    = $this->config->get('session_lifetime', 0) * 60;
+
+    // set session domain
+    if ($sess_domain) {
+      ini_set('session.cookie_domain', $sess_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', $sess_name ? $sess_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(), $this->config);
+
+    $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 (!$_SESSION['user_id'])
+      $_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);
+    }
+
+    $this->session->set_secret($this->config->get('des_key') . $_SERVER['HTTP_USER_AGENT']);
+    $this->session->set_ip_check($this->config->get('ip_check'));
+  }
+
+
+  /**
+   * 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 <P0L0_notspam_binware.org>
+    */
+    // 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;
+
+    // user already registered -> update user's record
+    if (is_object($user)) {
+      // update last login timestamp
+      $user->touch();
+    }
+    // create new system user
+    else if ($config['auto_create_user']) {
+      if ($created = rcube_user::create($username, $host)) {
+        $user = $created;
+      }
+      else {
+        raise_error(array(
+          'code' => 620, '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' => 621, 'type' => 'php',
+        'file' => __FILE__, 'line' => __LINE__,
+        'message' => "Access denied for new user $username. 'auto_create_user' is disabled"
+        ), true, false);
+    }
+
+    // login succeeded
+    if (is_object($user) && $user->ID) {
+      // Configure environment
+      $this->set_user($user);
+      $this->set_imap_prop();
+      $this->session_configure();
+
+      // fix some old settings according to namespace prefix
+      $this->fix_namespace_settings($user);
+
+      // create default folders on first login
+      if ($config['create_default_folders'] && (!empty($created) || empty($user->data['last_login']))) {
+        $this->imap->create_default_folders();
+      }
+
+      // 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']);
+      if (isset($_REQUEST['_dstactive']) && $_REQUEST['_dstactive'] != '_default_')
+        $_SESSION['dst_active'] = intval($_REQUEST['_dstactive']);
+
+      // force reloading complete list of subscribed mailboxes
+      $this->imap->clear_cache('mailboxes', true);
+
+      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   $attrib  Named parameters array or label name
+   * @param string  $domain  Label domain (plugin) 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'] : '';
+
+    // attrib contain text values: use them from now
+    if (($setval = $attrib[strtolower($_SESSION['language'])]) || ($setval = $attrib['en_us']))
+        $this->texts[$name] = $setval;
+
+    // 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;
+  }
+
+
+  /**
+   * Check if the given text label exists
+   *
+   * @param string  $name       Label name
+   * @param string  $domain     Label domain (plugin) name or '*' for all domains
+   * @param string  $ref_domain Sets domain name if label is found
+   *
+   * @return boolean True if text exists (either in the current language or in en_US)
+   */
+  public function text_exists($name, $domain = null, &$ref_domain = null)
+  {
+    // load localization files if not done yet
+    if (empty($this->texts))
+      $this->load_language();
+
+    if (isset($this->texts[$name])) {
+        $ref_domain = '';
+        return true;
+    }
+
+    // any of loaded domains (plugins)
+    if ($domain == '*') {
+      foreach ($this->plugins->loaded_plugins() as $domain)
+        if (isset($this->texts[$domain.'.'.$name])) {
+          $ref_domain = $domain;
+          return true;
+        }
+    }
+    // specified domain
+    else if ($domain) {
+      $ref_domain = $domain;
+      return isset($this->texts[$domain.'.'.$name]);
+    }
+
+    return false;
+  }
+
+  /**
+   * 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;
+  }
+
+
+  /**
+   * Destroy session data and remove cookie
+   */
+  public function kill_session()
+  {
+    $this->plugins->exec_hook('session_destroy');
+
+    $this->session->kill();
+    $_SESSION = array('language' => $this->user->language, 'temp' => true);
+    $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->session->check_auth())
+        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');
+    }
+
+    // Try to save unsaved user preferences
+    if (!empty($_SESSION['preferences'])) {
+      $this->user->save_prefs(unserialize($_SESSION['preferences']));
+    }
+  }
+
+
+  /**
+   * Function to be executed in script shutdown
+   * Registered with register_shutdown_function()
+   */
+  public function shutdown()
+  {
+    foreach ($this->shutdown_functions as $function)
+      call_user_func($function);
+
+    if (is_object($this->smtp))
+      $this->smtp->disconnect();
+
+    foreach ($this->address_books as $book) {
+      if (is_object($book) && is_a($book, 'rcube_addressbook'))
+        $book->close();
+    }
+
+    foreach ($this->caches as $cache) {
+        if (is_object($cache))
+            $cache->close();
+    }
+
+    if (is_object($this->imap))
+      $this->imap->close();
+
+    // before closing the database connection, write session data
+    if ($_SERVER['REMOTE_ADDR'] && is_object($this->session)) {
+      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);
+    }
+  }
+
+
+  /**
+   * Registers shutdown function to be executed on shutdown.
+   * The functions will be executed before destroying any
+   * objects like smtp, imap, session, etc.
+   *
+   * @param callback Function callback
+   */
+  public function add_shutdown_function($function)
+  {
+    $this->shutdown_functions[] = $function;
+  }
+
+
+  /**
+   * 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();
+    $plugin = $this->plugins->exec_hook('request_token', array('value' => md5('RT' . $this->user->ID . $this->config->get('des_key') . $sess_id)));
+    return $plugin['value'];
+  }
+
+
+  /**
+   * 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 '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);
+      }
+    }
+
+    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 '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 ($val !== '') {
+        $par = $key[0] == '_' ? $key : '_'.$key;
+        $url .= $delm.urlencode($par).'='.urlencode($val);
+        $delm = '&';
+      }
+    }
+    return $url;
+  }
+
+
+  /**
+   * Use imagemagick or GD lib to read image properties
+   *
+   * @param string Absolute file path
+   * @return mixed Hash array with image props like type, width, height or False on error
+   */
+  public static function imageprops($filepath)
+  {
+    $rcmail = rcmail::get_instance();
+    if ($cmd = $rcmail->config->get('im_identify_path', false)) {
+      list(, $type, $size) = explode(' ', strtolower(rcmail::exec($cmd. ' 2>/dev/null {in}', array('in' => $filepath))));
+      if ($size)
+        list($width, $height) = explode('x', $size);
+    }
+    else if (function_exists('getimagesize')) {
+      $imsize = @getimagesize($filepath);
+      $width = $imsize[0];
+      $height = $imsize[1];
+      $type = preg_replace('!image/!', '', $imsize['mime']);
+    }
+
+    return $type ? array('type' => $type, 'width' => $width, 'height' => $height) : false;
+  }
+
+
+  /**
+   * Convert an image to a given size and type using imagemagick (ensures input is an image)
+   *
+   * @param $p['in']  Input filename (mandatory)
+   * @param $p['out'] Output filename (mandatory)
+   * @param $p['size']  Width x height of resulting image, e.g. "160x60"
+   * @param $p['type']  Output file type, e.g. "jpg"
+   * @param $p['-opts'] Custom command line options to ImageMagick convert
+   * @return Success of convert as true/false
+   */
+  public static function imageconvert($p)
+  {
+    $result = false;
+    $rcmail = rcmail::get_instance();
+    $convert  = $rcmail->config->get('im_convert_path', false);
+    $identify = $rcmail->config->get('im_identify_path', false);
+
+    // imagemagick is required for this
+    if (!$convert)
+        return false;
+
+    if (!(($imagetype = @exif_imagetype($p['in'])) && ($type = image_type_to_extension($imagetype, false))))
+      list(, $type) = explode(' ', strtolower(rcmail::exec($identify . ' 2>/dev/null {in}', $p))); # for things like eps
+
+    $type = strtr($type, array("jpeg" => "jpg", "tiff" => "tif", "ps" => "eps", "ept" => "eps"));
+    $p += array('type' => $type, 'types' => "bmp,eps,gif,jp2,jpg,png,svg,tif", 'quality' => 75);
+    $p['-opts'] = array('-resize' => $p['size'].'>') + (array)$p['-opts'];
+
+    if (in_array($type, explode(',', $p['types']))) # Valid type?
+      $result = rcmail::exec($convert . ' 2>&1 -flatten -auto-orient -colorspace RGB -quality {quality} {-opts} {in} {type}:{out}', $p) === "";
+
+    return $result;
+  }
+
+
+  /**
+   * Construct shell command, execute it and return output as string.
+   * Keywords {keyword} are replaced with arguments
+   *
+   * @param $cmd Format string with {keywords} to be replaced
+   * @param $values (zero, one or more arrays can be passed)
+   * @return output of command. shell errors not detectable
+   */
+  public static function exec(/* $cmd, $values1 = array(), ... */)
+  {
+    $args = func_get_args();
+    $cmd = array_shift($args);
+    $values = $replacements = array();
+
+    // merge values into one array
+    foreach ($args as $arg)
+      $values += (array)$arg;
+
+    preg_match_all('/({(-?)([a-z]\w*)})/', $cmd, $matches, PREG_SET_ORDER);
+    foreach ($matches as $tags) {
+      list(, $tag, $option, $key) = $tags;
+      $parts = array();
+
+      if ($option) {
+        foreach ((array)$values["-$key"] as $key => $value) {
+          if ($value === true || $value === false || $value === null)
+            $parts[] = $value ? $key : "";
+          else foreach ((array)$value as $val)
+            $parts[] = "$key " . escapeshellarg($val);
+        }
+      }
+      else {
+        foreach ((array)$values[$key] as $value)
+          $parts[] = escapeshellarg($value);
+      }
+
+      $replacements[$tag] = join(" ", $parts);
+    }
+
+    // use strtr behaviour of going through source string once
+    $cmd = strtr($cmd, $replacements);
+
+    return (string)shell_exec($cmd);
+  }
+
+
+  /**
+   * 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);
+  }
+
+  /**
+   * Registers action aliases for current task
+   *
+   * @param array $map Alias-to-filename hash array
+   */
+  public function register_action_map($map)
+  {
+    if (is_array($map)) {
+      foreach ($map as $idx => $val) {
+        $this->action_map[$idx] = $val;
+      }
+    }
+  }
+
+  /**
+   * Returns current action filename
+   *
+   * @param array $map Alias-to-filename hash array
+   */
+  public function get_action_file()
+  {
+    if (!empty($this->action_map[$this->action])) {
+      return $this->action_map[$this->action];
+    }
+
+    return strtr($this->action, '-', '_') . '.inc';
+  }
+
+  /**
+   * Fixes some user preferences according to namespace handling change.
+   * Old Roundcube versions were using folder names with removed namespace prefix.
+   * Now we need to add the prefix on servers where personal namespace has prefix.
+   *
+   * @param rcube_user $user User object
+   */
+  private function fix_namespace_settings($user)
+  {
+    $prefix     = $this->imap->get_namespace('prefix');
+    $prefix_len = strlen($prefix);
+
+    if (!$prefix_len)
+      return;
+
+    $prefs = $this->config->all();
+    if (!empty($prefs['namespace_fixed']))
+      return;
+
+    // Build namespace prefix regexp
+    $ns     = $this->imap->get_namespace();
+    $regexp = array();
+
+    foreach ($ns as $entry) {
+      if (!empty($entry)) {
+        foreach ($entry as $item) {
+          if (strlen($item[0])) {
+            $regexp[] = preg_quote($item[0], '/');
+          }
+        }
+      }
+    }
+    $regexp = '/^('. implode('|', $regexp).')/';
+
+    // Fix preferences
+    $opts = array('drafts_mbox', 'junk_mbox', 'sent_mbox', 'trash_mbox', 'archive_mbox');
+    foreach ($opts as $opt) {
+      if ($value = $prefs[$opt]) {
+        if ($value != 'INBOX' && !preg_match($regexp, $value)) {
+          $prefs[$opt] = $prefix.$value;
+        }
+      }
+    }
+
+    if (!empty($prefs['default_imap_folders'])) {
+      foreach ($prefs['default_imap_folders'] as $idx => $name) {
+        if ($name != 'INBOX' && !preg_match($regexp, $name)) {
+          $prefs['default_imap_folders'][$idx] = $prefix.$name;
+        }
+      }
+    }
+
+    if (!empty($prefs['search_mods'])) {
+      $folders = array();
+      foreach ($prefs['search_mods'] as $idx => $value) {
+        if ($idx != 'INBOX' && $idx != '*' && !preg_match($regexp, $idx)) {
+          $idx = $prefix.$idx;
+        }
+        $folders[$idx] = $value;
+      }
+      $prefs['search_mods'] = $folders;
+    }
+
+    if (!empty($prefs['message_threading'])) {
+      $folders = array();
+      foreach ($prefs['message_threading'] as $idx => $value) {
+        if ($idx != 'INBOX' && !preg_match($regexp, $idx)) {
+          $idx = $prefix.$idx;
+        }
+        $folders[$prefix.$idx] = $value;
+      }
+      $prefs['message_threading'] = $folders;
+    }
+
+    if (!empty($prefs['collapsed_folders'])) {
+      $folders     = explode('&&', $prefs['collapsed_folders']);
+      $count       = count($folders);
+      $folders_str = '';
+
+      if ($count) {
+          $folders[0]        = substr($folders[0], 1);
+          $folders[$count-1] = substr($folders[$count-1], 0, -1);
+      }
+
+      foreach ($folders as $value) {
+        if ($value != 'INBOX' && !preg_match($regexp, $value)) {
+          $value = $prefix.$value;
+        }
+        $folders_str .= '&'.$value.'&';
+      }
+      $prefs['collapsed_folders'] = $folders_str;
+    }
+
+    $prefs['namespace_fixed'] = true;
+
+    // save updated preferences and reset imap settings (default folders)
+    $user->save_prefs($prefs);
+    $this->set_imap_prop();
+  }
+
+}
index fc8c44156457280fcb1a06096718a995beaeead3..b9a3acbfa192fc3fad1b7b9d22a9cb42d6a72615 100644 (file)
@@ -15,7 +15,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: rcube_addressbook.php 4965 2011-07-25 11:48:50Z alec $
+ $Id: rcube_addressbook.php 5415 2011-11-11 15:04:45Z alec $
 
 */
 
 
 */
 
@@ -30,7 +30,7 @@ abstract class rcube_addressbook
     /** constants for error reporting **/
     const ERROR_READ_ONLY = 1;
     const ERROR_NO_CONNECTION = 2;
     /** constants for error reporting **/
     const ERROR_READ_ONLY = 1;
     const ERROR_NO_CONNECTION = 2;
-    const ERROR_INCOMPLETE = 3;
+    const ERROR_VALIDATE = 3;
     const ERROR_SAVING = 4;
     const ERROR_SEARCH = 5;
 
     const ERROR_SAVING = 4;
     const ERROR_SEARCH = 5;
 
@@ -38,6 +38,7 @@ abstract class rcube_addressbook
     public $primary_key;
     public $groups = false;
     public $readonly = true;
     public $primary_key;
     public $groups = false;
     public $readonly = true;
+    public $searchonly = false;
     public $undelete = false;
     public $ready = false;
     public $group_id = null;
     public $undelete = false;
     public $ready = false;
     public $group_id = null;
@@ -95,12 +96,16 @@ abstract class rcube_addressbook
      *
      * @param array   List of fields to search in
      * @param string  Search value
      *
      * @param array   List of fields to search in
      * @param string  Search value
+     * @param int     Matching mode:
+     *                0 - partial (*abc*),
+     *                1 - strict (=),
+     *                2 - prefix (abc*)
      * @param boolean True if results are requested, False if count only
      * @param boolean True to skip the count query (select only)
      * @param array   List of fields that cannot be empty
      * @return object rcube_result_set List of contact records and 'count' value
      */
      * @param boolean True if results are requested, False if count only
      * @param boolean True to skip the count query (select only)
      * @param array   List of fields that cannot be empty
      * @return object rcube_result_set List of contact records and 'count' value
      */
-    abstract function search($fields, $value, $strict=false, $select=true, $nocount=false, $required=array());
+    abstract function search($fields, $value, $mode=0, $select=true, $nocount=false, $required=array());
 
     /**
      * Count number of available contacts in database
 
     /**
      * Count number of available contacts in database
@@ -181,15 +186,16 @@ abstract class rcube_addressbook
      * If input isn't valid, the message to display can be fetched using get_error()
      *
      * @param array Assoziative array with data to save
      * If input isn't valid, the message to display can be fetched using get_error()
      *
      * @param array Assoziative array with data to save
+     * @param boolean Attempt to fix/complete record automatically
      * @return boolean True if input is valid, False if not.
      */
      * @return boolean True if input is valid, False if not.
      */
-    public function validate($save_data)
+    public function validate(&$save_data, $autofix = false)
     {
         // check validity of email addresses
         foreach ($this->get_col_values('email', $save_data, true) as $email) {
             if (strlen($email)) {
                 if (!check_email(rcube_idn_to_ascii($email))) {
     {
         // check validity of email addresses
         foreach ($this->get_col_values('email', $save_data, true) as $email) {
             if (strlen($email)) {
                 if (!check_email(rcube_idn_to_ascii($email))) {
-                    $this->set_error('warning', rcube_label(array('name' => 'emailformaterror', 'vars' => array('email' => $email))));
+                    $this->set_error(self::ERROR_VALIDATE, rcube_label(array('name' => 'emailformaterror', 'vars' => array('email' => $email))));
                     return false;
                 }
             }
                     return false;
                 }
             }
@@ -293,6 +299,18 @@ abstract class rcube_addressbook
         return array();
     }
 
         return array();
     }
 
+    /**
+     * Get group properties such as name and email address(es)
+     *
+     * @param string Group identifier
+     * @return array Group properties as hash array
+     */
+    function get_group($group_id)
+    {
+        /* empty for address books don't supporting groups */
+        return null;
+    }
+
     /**
      * Create a contact group with the given name
      *
     /**
      * Create a contact group with the given name
      *
@@ -385,7 +403,7 @@ abstract class rcube_addressbook
     {
         $out = array();
         foreach ($data as $c => $values) {
     {
         $out = array();
         foreach ($data as $c => $values) {
-            if (strpos($c, $col) === 0) {
+            if ($c === $col || strpos($c, $col.':') === 0) {
                 if ($flat) {
                     $out = array_merge($out, (array)$values);
                 }
                 if ($flat) {
                     $out = array_merge($out, (array)$values);
                 }
index 10b214cf93df9bb746f15263df82c58f46f68a9e..1727586e41d743c2a8d7c200bac7cb9af4d786fa 100644 (file)
@@ -15,7 +15,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: rcube_browser.php 4971 2011-07-27 06:37:17Z alec $
+ $Id: rcube_browser.php 5499 2011-11-28 09:03:27Z alec $
 
 */
 
 
 */
 
@@ -33,19 +33,19 @@ class rcube_browser
         $HTTP_USER_AGENT = strtolower($_SERVER['HTTP_USER_AGENT']);
 
         $this->ver = 0;
         $HTTP_USER_AGENT = strtolower($_SERVER['HTTP_USER_AGENT']);
 
         $this->ver = 0;
-        $this->win = strstr($HTTP_USER_AGENT, 'win');
-        $this->mac = strstr($HTTP_USER_AGENT, 'mac');
-        $this->linux = strstr($HTTP_USER_AGENT, 'linux');
-        $this->unix  = strstr($HTTP_USER_AGENT, 'unix');
+        $this->win = strpos($HTTP_USER_AGENT, 'win') != false;
+        $this->mac = strpos($HTTP_USER_AGENT, 'mac') != false;
+        $this->linux = strpos($HTTP_USER_AGENT, 'linux') != false;
+        $this->unix  = strpos($HTTP_USER_AGENT, 'unix') != false;
 
 
-        $this->opera = strstr($HTTP_USER_AGENT, 'opera');
-        $this->ns4 = strstr($HTTP_USER_AGENT, 'mozilla/4') && !stristr($HTTP_USER_AGENT, 'msie');
-        $this->ns  = ($this->ns4 || strstr($HTTP_USER_AGENT, 'netscape'));
-        $this->ie  = !$this->opera && stristr($HTTP_USER_AGENT, 'compatible; msie');
-        $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'));
+        $this->opera = strpos($HTTP_USER_AGENT, 'opera') !== false;
+        $this->ns4 = strpos($HTTP_USER_AGENT, 'mozilla/4') !== false && strpos($HTTP_USER_AGENT, 'msie') === false;
+        $this->ns  = ($this->ns4 || strpos($HTTP_USER_AGENT, 'netscape') !== false);
+        $this->ie  = !$this->opera && strpos($HTTP_USER_AGENT, 'compatible; msie') !== false;
+        $this->mz  = !$this->ie && strpos($HTTP_USER_AGENT, 'mozilla/5') !== false;
+        $this->chrome = strpos($HTTP_USER_AGENT, 'chrome') !== false;
+        $this->khtml = strpos($HTTP_USER_AGENT, 'khtml') !== false;
+        $this->safari = !$this->chrome && ($this->khtml || strpos($HTTP_USER_AGENT, 'safari') !== false);
 
         if ($this->ns || $this->chrome) {
             $test = preg_match('/(mozilla|chrome)\/([0-9.]+)/', $HTTP_USER_AGENT, $regs);
 
         if ($this->ns || $this->chrome) {
             $test = preg_match('/(mozilla|chrome)\/([0-9.]+)/', $HTTP_USER_AGENT, $regs);
index 7224ee6bd505fe945933d523f17b2dc01bf69bde..cc472ae1cc864745dfbb44f7e073f9aadc5d96b1 100644 (file)
@@ -17,7 +17,7 @@
  | Author: Aleksander Machniak <alec@alec.pl>                            |
  +-----------------------------------------------------------------------+
 
  | Author: Aleksander Machniak <alec@alec.pl>                            |
  +-----------------------------------------------------------------------+
 
- $Id: rcube_cache.php 4909 2011-07-05 17:09:25Z alec $
+ $Id: rcube_cache.php 5305 2011-10-03 18:04:14Z alec $
 
 */
 
 
 */
 
@@ -28,7 +28,7 @@
  * @package    Cache
  * @author     Thomas Bruederli <roundcube@gmail.com>
  * @author     Aleksander Machniak <alec@alec.pl>
  * @package    Cache
  * @author     Thomas Bruederli <roundcube@gmail.com>
  * @author     Aleksander Machniak <alec@alec.pl>
- * @version    1.0
+ * @version    1.1
  */
 class rcube_cache
 {
  */
 class rcube_cache
 {
@@ -187,6 +187,24 @@ class rcube_cache
     }
 
 
     }
 
 
+    /**
+     * Remove cache records older than ttl
+     */
+    function expunge()
+    {
+        if ($this->type == 'db' && $this->db) {
+            $this->db->query(
+                "DELETE FROM ".get_table_name('cache').
+                " WHERE user_id = ?".
+                " AND cache_key LIKE ?".
+                " AND " . $this->db->unixtimestamp('created')." < ?",
+                $this->userid,
+                $this->prefix.'.%',
+                time() - $this->ttl);
+        }
+    }
+
+
     /**
      * Writes the cache back to the DB.
      */
     /**
      * Writes the cache back to the DB.
      */
@@ -227,26 +245,30 @@ class rcube_cache
             return null;
         }
 
             return null;
         }
 
-        if ($this->type == 'memcache') {
-            $data = $this->db->get($this->ckey($key));
-        }
-        else if ($this->type == 'apc') {
-            $data = apc_fetch($this->ckey($key));
-           }
+        if ($this->type != 'db') {
+            if ($this->type == 'memcache') {
+                $data = $this->db->get($this->ckey($key));
+            }
+            else if ($this->type == 'apc') {
+                $data = apc_fetch($this->ckey($key));
+               }
 
 
-        if ($data) {
-            $md5sum = md5($data);
-            $data   = $this->packed ? unserialize($data) : $data;
+            if ($data) {
+                $md5sum = md5($data);
+                $data   = $this->packed ? unserialize($data) : $data;
 
 
-            if ($nostore) {
-                return $data;
-            }
+                if ($nostore) {
+                    return $data;
+                }
 
 
-            $this->cache_sums[$key] = $md5sum;
-            $this->cache[$key]      = $data;
+                $this->cache_sums[$key] = $md5sum;
+                $this->cache[$key]      = $data;
+            }
+            else {
+                $this->cache[$key] = null;
+            }
         }
         }
-
-        if ($this->type == 'db') {
+        else {
             $sql_result = $this->db->limitquery(
                 "SELECT cache_id, data, cache_key".
                 " FROM ".get_table_name('cache').
             $sql_result = $this->db->limitquery(
                 "SELECT cache_id, data, cache_key".
                 " FROM ".get_table_name('cache').
@@ -272,6 +294,9 @@ class rcube_cache
                    $this->cache_sums[$key] = $md5sum;
                 $this->cache_keys[$key] = $sql_arr['cache_id'];
             }
                    $this->cache_sums[$key] = $md5sum;
                 $this->cache_keys[$key] = $sql_arr['cache_id'];
             }
+            else {
+                $this->cache[$key] = null;
+            }
         }
 
         return $this->cache[$key];
         }
 
         return $this->cache[$key];
index 7d46df05168c08e681a81ec5c19b522d33c1c5e2..ceada11fa84d96eda82d3df47d9c2225f58e8092 100644 (file)
@@ -15,7 +15,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: rcube_config.php 5151 2011-08-31 12:49:44Z alec $
+ $Id: rcube_config.php 5499 2011-11-28 09:03:27Z alec $
 
 */
 
 
 */
 
@@ -91,6 +91,15 @@ class rcube_config
         // enable display_errors in 'show' level, but not for ajax requests
         ini_set('display_errors', intval(empty($_REQUEST['_remote']) && ($this->prop['debug_level'] & 4)));
 
         // enable display_errors in 'show' level, but not for ajax requests
         ini_set('display_errors', intval(empty($_REQUEST['_remote']) && ($this->prop['debug_level'] & 4)));
 
+        // set timezone auto settings values
+        if ($this->prop['timezone'] == 'auto') {
+          $this->prop['dst_active'] = intval(date('I'));
+          $this->prop['_timezone_value'] = date('Z') / 3600 - $this->prop['dst_active'];
+        }
+        else if ($this->prop['dst_active'] === null) {
+          $this->prop['dst_active'] = intval(date('I'));
+        }
+
         // export config data
         $GLOBALS['CONFIG'] = &$this->prop;
     }
         // export config data
         $GLOBALS['CONFIG'] = &$this->prop;
     }
@@ -152,6 +161,9 @@ class rcube_config
     {
         $result = isset($this->prop[$name]) ? $this->prop[$name] : $def;
         $rcmail = rcmail::get_instance();
     {
         $result = isset($this->prop[$name]) ? $this->prop[$name] : $def;
         $rcmail = rcmail::get_instance();
+        
+        if ($name == 'timezone' && isset($this->prop['_timezone_value']))
+            $result = $this->prop['_timezone_value'];
 
         if (is_object($rcmail->plugins)) {
             $plugin = $rcmail->plugins->exec_hook('config_get', array(
 
         if (is_object($rcmail->plugins)) {
             $plugin = $rcmail->plugins->exec_hook('config_get', array(
@@ -207,6 +219,14 @@ class rcube_config
 
         $this->userprefs = $prefs;
         $this->prop      = array_merge($this->prop, $prefs);
 
         $this->userprefs = $prefs;
         $this->prop      = array_merge($this->prop, $prefs);
+
+        // override timezone settings with client values
+        if ($this->prop['timezone'] == 'auto') {
+            $this->prop['_timezone_value'] = isset($_SESSION['timezone']) ? $_SESSION['timezone'] : $this->prop['_timezone_value'];
+            $this->prop['dst_active'] = $this->userprefs['dst_active'] = isset($_SESSION['dst_active']) ? $_SESSION['dst_active'] : $this->prop['dst_active'];
+        }
+        else if (isset($this->prop['_timezone_value']))
+           unset($this->prop['_timezone_value']);
     }
 
 
     }
 
 
@@ -221,17 +241,13 @@ class rcube_config
     }
 
     /**
     }
 
     /**
-     * Special getter for user's timezone
+     * Special getter for user's timezone offset including DST
+     *
+     * @return float  Timezone offset (in hours)
      */
     public function get_timezone()
     {
      */
     public function get_timezone()
     {
-      $tz = $this->get('timezone');
-      if ($tz == 'auto')
-        $tz = isset($_SESSION['timezone']) ? $_SESSION['timezone'] : date('Z') / 3600;
-      else
-        $tz = intval($tz) + intval($this->get('dst_active'));
-
-      return $tz;
+      return floatval($this->get('timezone')) + intval($this->get('dst_active'));
     }
 
     /**
     }
 
     /**
index af07b32bedd9d91bf07c2ed3f1b3dc20afa22320..a2883156ae8448a60b2885e19686049ffadecb3b 100644 (file)
@@ -15,7 +15,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: rcube_contacts.php 5011 2011-08-03 09:32:45Z alec $
+ $Id: rcube_contacts.php 5415 2011-11-11 15:04:45Z alec $
 
 */
 
 
 */
 
@@ -41,7 +41,6 @@ class rcube_contacts extends rcube_addressbook
     private $user_id = 0;
     private $filter = null;
     private $result = null;
     private $user_id = 0;
     private $filter = null;
     private $result = null;
-    private $name;
     private $cache;
     private $table_cols = array('name', 'email', 'firstname', 'surname');
     private $fulltext_cols = array('name', 'firstname', 'surname', 'middlename', 'nickname',
     private $cache;
     private $table_cols = array('name', 'email', 'firstname', 'surname');
     private $fulltext_cols = array('name', 'firstname', 'surname', 'middlename', 'nickname',
@@ -50,6 +49,7 @@ class rcube_contacts extends rcube_addressbook
 
     // public properties
     public $primary_key = 'contact_id';
 
     // public properties
     public $primary_key = 'contact_id';
+    public $name;
     public $readonly = false;
     public $groups = true;
     public $undelete = true;
     public $readonly = false;
     public $groups = true;
     public $undelete = true;
@@ -163,6 +163,29 @@ class rcube_contacts extends rcube_addressbook
     }
 
 
     }
 
 
+    /**
+     * Get group properties such as name and email address(es)
+     *
+     * @param string Group identifier
+     * @return array Group properties as hash array
+     */
+    function get_group($group_id)
+    {
+        $sql_result = $this->db->query(
+            "SELECT * FROM ".get_table_name($this->db_groups).
+            " WHERE del<>1".
+            " AND contactgroup_id=?".
+            " AND user_id=?",
+            $group_id, $this->user_id);
+
+        if ($sql_result && ($sql_arr = $this->db->fetch_assoc($sql_result))) {
+            $sql_arr['ID'] = $sql_arr['contactgroup_id'];
+            return $sql_arr;
+        }
+
+        return null;
+    }
+
     /**
      * List the current set of contact records
      *
     /**
      * List the current set of contact records
      *
@@ -245,14 +268,17 @@ class rcube_contacts extends rcube_addressbook
      *
      * @param mixed   $fields   The field name of array of field names to search in
      * @param mixed   $value    Search value (or array of values when $fields is array)
      *
      * @param mixed   $fields   The field name of array of field names to search in
      * @param mixed   $value    Search value (or array of values when $fields is array)
-     * @param boolean $strict   True for strict (=), False for partial (LIKE) matching
+     * @param int     $mode     Matching mode:
+     *                          0 - partial (*abc*),
+     *                          1 - strict (=),
+     *                          2 - prefix (abc*)
      * @param boolean $select   True if results are requested, False if count only
      * @param boolean $nocount  True to skip the count query (select only)
      * @param array   $required List of fields that cannot be empty
      *
      * @return object rcube_result_set Contact records and 'count' value
      */
      * @param boolean $select   True if results are requested, False if count only
      * @param boolean $nocount  True to skip the count query (select only)
      * @param array   $required List of fields that cannot be empty
      *
      * @return object rcube_result_set Contact records and 'count' value
      */
-    function search($fields, $value, $strict=false, $select=true, $nocount=false, $required=array())
+    function search($fields, $value, $mode=0, $select=true, $nocount=false, $required=array())
     {
         if (!is_array($fields))
             $fields = array($fields);
     {
         if (!is_array($fields))
             $fields = array($fields);
@@ -260,6 +286,7 @@ class rcube_contacts extends rcube_addressbook
             $required = array($required);
 
         $where = $and_where = array();
             $required = array($required);
 
         $where = $and_where = array();
+        $mode = intval($mode);
 
         foreach ($fields as $idx => $col) {
             // direct ID search
 
         foreach ($fields as $idx => $col) {
             // direct ID search
@@ -272,26 +299,56 @@ class rcube_contacts extends rcube_addressbook
             // fulltext search in all fields
             else if ($col == '*') {
                 $words = array();
             // fulltext search in all fields
             else if ($col == '*') {
                 $words = array();
-                foreach (explode(" ", self::normalize_string($value)) as $word)
-                    $words[] = $this->db->ilike('words', '%'.$word.'%');
+                foreach (explode(" ", self::normalize_string($value)) as $word) {
+                    switch ($mode) {
+                    case 1: // strict
+                        $words[] = '(' . $this->db->ilike('words', $word.' %')
+                            . ' OR ' . $this->db->ilike('words', '% '.$word.' %')
+                            . ' OR ' . $this->db->ilike('words', '% '.$word) . ')';
+                        break;
+                    case 2: // prefix
+                        $words[] = '(' . $this->db->ilike('words', $word.'%')
+                            . ' OR ' . $this->db->ilike('words', '% '.$word.'%') . ')';
+                        break;
+                    default: // partial
+                        $words[] = $this->db->ilike('words', '%'.$word.'%');
+                    }
+                }
                 $where[] = '(' . join(' AND ', $words) . ')';
             }
             else {
                 $val = is_array($value) ? $value[$idx] : $value;
                 // table column
                 if (in_array($col, $this->table_cols)) {
                 $where[] = '(' . join(' AND ', $words) . ')';
             }
             else {
                 $val = is_array($value) ? $value[$idx] : $value;
                 // table column
                 if (in_array($col, $this->table_cols)) {
-                    if ($strict) {
+                    switch ($mode) {
+                    case 1: // strict
                         $where[] = $this->db->quoteIdentifier($col).' = '.$this->db->quote($val);
                         $where[] = $this->db->quoteIdentifier($col).' = '.$this->db->quote($val);
-                    }
-                    else {
+                        break;
+                    case 2: // prefix
+                        $where[] = $this->db->ilike($col, $val.'%');
+                        break;
+                    default: // partial
                         $where[] = $this->db->ilike($col, '%'.$val.'%');
                     }
                 }
                 // vCard field
                 else {
                     if (in_array($col, $this->fulltext_cols)) {
                         $where[] = $this->db->ilike($col, '%'.$val.'%');
                     }
                 }
                 // vCard field
                 else {
                     if (in_array($col, $this->fulltext_cols)) {
-                        foreach (explode(" ", self::normalize_string($val)) as $word)
-                            $words[] = $this->db->ilike('words', '%'.$word.'%');
+                        foreach (explode(" ", self::normalize_string($val)) as $word) {
+                            switch ($mode) {
+                            case 1: // strict
+                                $words[] = '(' . $this->db->ilike('words', $word.' %')
+                                    . ' OR ' . $this->db->ilike('words', '% '.$word.' %')
+                                    . ' OR ' . $this->db->ilike('words', '% '.$word) . ')';
+                                break;
+                            case 2: // prefix
+                                $words[] = '(' . $this->db->ilike('words', $word.'%')
+                                    . ' OR ' . $this->db->ilike('words', ' '.$word.'%') . ')';
+                                break;
+                            default: // partial
+                                $words[] = $this->db->ilike('words', '%'.$word.'%');
+                            }
+                        }
                         $where[] = '(' . join(' AND ', $words) . ')';
                     }
                     if (is_array($value))
                         $where[] = '(' . join(' AND ', $words) . ')';
                     }
                     if (is_array($value))
@@ -339,13 +396,24 @@ class rcube_contacts extends rcube_addressbook
                         $search  = $post_search[$colname];
                         foreach ((array)$row[$col] as $value) {
                             // composite field, e.g. address
                         $search  = $post_search[$colname];
                         foreach ((array)$row[$col] as $value) {
                             // composite field, e.g. address
-                            if (is_array($value)) {
-                                $value = implode($value);
-                            }
-                            $value = mb_strtolower($value);
-                            if (($strict && $value == $search) || (!$strict && strpos($value, $search) !== false)) {
-                                $found[$colname] = true;
-                                break;
+                            foreach ((array)$value as $val) {
+                                $val = mb_strtolower($val);
+                                switch ($mode) {
+                                case 1:
+                                    $got = ($val == $search);
+                                    break;
+                                case 2:
+                                    $got = ($search == substr($val, 0, strlen($search)));
+                                    break;
+                                default:
+                                    $got = (strpos($val, $search) !== false);
+                                    break;
+                                }
+
+                                if ($got) {
+                                    $found[$colname] = true;
+                                    break 2;
+                                }
                             }
                         }
                     }
                             }
                         }
                     }
@@ -500,16 +568,17 @@ class rcube_contacts extends rcube_addressbook
      * If input not valid, the message to display can be fetched using get_error()
      *
      * @param array Assoziative array with data to save
      * If input not valid, the message to display can be fetched using get_error()
      *
      * @param array Assoziative array with data to save
+     * @param boolean Try to fix/complete record automatically
      * @return boolean True if input is valid, False if not.
      */
      * @return boolean True if input is valid, False if not.
      */
-    public function validate($save_data)
+    public function validate(&$save_data, $autofix = false)
     {
         // validate e-mail addresses
     {
         // validate e-mail addresses
-        $valid = parent::validate($save_data);
+        $valid = parent::validate($save_data, $autofix);
 
         // require at least one e-mail address (syntax check is already done)
         if ($valid && !array_filter($this->get_col_values('email', $save_data, true))) {
 
         // require at least one e-mail address (syntax check is already done)
         if ($valid && !array_filter($this->get_col_values('email', $save_data, true))) {
-            $this->set_error('warning', 'noemailwarning');
+            $this->set_error(self::ERROR_VALIDATE, 'noemailwarning');
             $valid = false;
         }
 
             $valid = false;
         }
 
@@ -773,8 +842,9 @@ class rcube_contacts extends rcube_addressbook
         $sql_result = $this->db->query(
             "UPDATE ".get_table_name($this->db_groups).
             " SET del=1, changed=".$this->db->now().
         $sql_result = $this->db->query(
             "UPDATE ".get_table_name($this->db_groups).
             " SET del=1, changed=".$this->db->now().
-            " WHERE contactgroup_id=?",
-            $gid
+            " WHERE contactgroup_id=?".
+            " AND user_id=?",
+            $gid, $this->user_id
         );
 
         $this->cache = null;
         );
 
         $this->cache = null;
@@ -798,8 +868,9 @@ class rcube_contacts extends rcube_addressbook
         $sql_result = $this->db->query(
             "UPDATE ".get_table_name($this->db_groups).
             " SET name=?, changed=".$this->db->now().
         $sql_result = $this->db->query(
             "UPDATE ".get_table_name($this->db_groups).
             " SET name=?, changed=".$this->db->now().
-            " WHERE contactgroup_id=?",
-            $name, $gid
+            " WHERE contactgroup_id=?".
+            " AND user_id=?",
+            $name, $gid, $this->user_id
         );
 
         return $this->db->affected_rows() ? $name : false;
         );
 
         return $this->db->affected_rows() ? $name : false;
index f57f6a6c0a073d78fde1fac4976c58791118769a..77b7ff2d86db642ceab0a37b901419ce6e311c54 100644 (file)
@@ -15,7 +15,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: rcube_html_page.php 5151 2011-08-31 12:49:44Z alec $
+ $Id: rcube_html_page.php 5135 2011-08-26 09:22:53Z alec $
 
 */
 
 
 */
 
index 48627d890d2fe51a79c86a1f05bce29d09b9c4b3..b48adcfc8551efc4e61709ac18e99e14362b95c7 100644 (file)
@@ -5,7 +5,8 @@
  | program/include/rcube_imap.php                                        |
  |                                                                       |
  | This file is part of the Roundcube Webmail client                     |
  | program/include/rcube_imap.php                                        |
  |                                                                       |
  | This file is part of the Roundcube Webmail client                     |
- | Copyright (C) 2005-2010, The Roundcube Dev Team                       |
+ | Copyright (C) 2005-2011, The Roundcube Dev Team                       |
+ | Copyright (C) 2011, Kolab Systems AG                                  |
  | Licensed under the GNU GPL                                            |
  |                                                                       |
  | PURPOSE:                                                              |
  | Licensed under the GNU GPL                                            |
  |                                                                       |
  | PURPOSE:                                                              |
@@ -16,7 +17,7 @@
  | Author: Aleksander Machniak <alec@alec.pl>                            |
  +-----------------------------------------------------------------------+
 
  | Author: Aleksander Machniak <alec@alec.pl>                            |
  +-----------------------------------------------------------------------+
 
- $Id: rcube_imap.php 5281 2011-09-27 07:29:49Z alec $
+ $Id: rcube_imap.php 5601 2011-12-14 09:08:54Z alec $
 
 */
 
 
 */
 
@@ -31,7 +32,6 @@
  */
 class rcube_imap
 {
  */
 class rcube_imap
 {
-    public $debug_level = 1;
     public $skip_deleted = false;
     public $page_size = 10;
     public $list_page = 1;
     public $skip_deleted = false;
     public $page_size = 10;
     public $list_page = 1;
@@ -47,11 +47,11 @@ class rcube_imap
     public $conn;
 
     /**
     public $conn;
 
     /**
-     * Instance of rcube_mdb2
+     * Instance of rcube_imap_cache
      *
      *
-     * @var rcube_mdb2
+     * @var rcube_imap_cache
      */
      */
-    private $db;
+    private $mcache;
 
     /**
      * Instance of rcube_cache
 
     /**
      * Instance of rcube_cache
@@ -59,6 +59,14 @@ class rcube_imap
      * @var rcube_cache
      */
     private $cache;
      * @var rcube_cache
      */
     private $cache;
+
+    /**
+     * Internal (in-memory) cache
+     *
+     * @var array
+     */
+    private $icache = array();
+
     private $mailbox = 'INBOX';
     private $delimiter = NULL;
     private $namespace = NULL;
     private $mailbox = 'INBOX';
     private $delimiter = NULL;
     private $namespace = NULL;
@@ -67,8 +75,6 @@ class rcube_imap
     private $default_charset = 'ISO-8859-1';
     private $struct_charset = NULL;
     private $default_folders = array('INBOX');
     private $default_charset = 'ISO-8859-1';
     private $struct_charset = NULL;
     private $default_folders = array('INBOX');
-    private $messages_caching = false;
-    private $icache = array();
     private $uid_id_map = array();
     private $msg_headers = array();
     public  $search_set = NULL;
     private $uid_id_map = array();
     private $msg_headers = array();
     public  $search_set = NULL;
@@ -77,10 +83,10 @@ class rcube_imap
     private $search_sort_field = '';
     private $search_threads = false;
     private $search_sorted = false;
     private $search_sort_field = '';
     private $search_threads = false;
     private $search_sorted = false;
-    private $db_header_fields = array('idx', 'uid', 'subject', 'from', 'to', 'cc', 'date', 'size');
     private $options = array('auth_method' => 'check');
     private $host, $user, $pass, $port, $ssl;
     private $caching = false;
     private $options = array('auth_method' => 'check');
     private $host, $user, $pass, $port, $ssl;
     private $caching = false;
+    private $messages_caching = false;
 
     /**
      * All (additional) headers used (in any way) by Roundcube
 
     /**
      * All (additional) headers used (in any way) by Roundcube
@@ -96,7 +102,6 @@ class rcube_imap
         'MESSAGE-ID',
         'CONTENT-TRANSFER-ENCODING',
         'REFERENCES',
         'MESSAGE-ID',
         'CONTENT-TRANSFER-ENCODING',
         'REFERENCES',
-        'X-PRIORITY',
         'X-DRAFT-INFO',
         'MAIL-FOLLOWUP-TO',
         'MAIL-REPLY-TO',
         'X-DRAFT-INFO',
         'MAIL-FOLLOWUP-TO',
         'MAIL-REPLY-TO',
@@ -170,12 +175,13 @@ class rcube_imap
         $attempt = 0;
         do {
             $data = rcmail::get_instance()->plugins->exec_hook('imap_connect',
         $attempt = 0;
         do {
             $data = rcmail::get_instance()->plugins->exec_hook('imap_connect',
-                array('host' => $host, 'user' => $user, 'attempt' => ++$attempt));
+                array_merge($this->options, array('host' => $host, 'user' => $user,
+                    'attempt' => ++$attempt)));
 
             if (!empty($data['pass']))
                 $pass = $data['pass'];
 
 
             if (!empty($data['pass']))
                 $pass = $data['pass'];
 
-            $this->conn->connect($data['host'], $data['user'], $pass, $this->options);
+            $this->conn->connect($data['host'], $data['user'], $pass, $data);
         } while(!$this->conn->connected() && $data['retry']);
 
         $this->host = $data['host'];
         } while(!$this->conn->connected() && $data['retry']);
 
         $this->host = $data['host'];
@@ -214,6 +220,8 @@ class rcube_imap
     function close()
     {
         $this->conn->closeConnection();
     function close()
     {
         $this->conn->closeConnection();
+        if ($this->mcache)
+            $this->mcache->close();
     }
 
 
     }
 
 
@@ -308,6 +316,19 @@ class rcube_imap
     }
 
 
     }
 
 
+    /**
+     * Activate/deactivate debug mode
+     *
+     * @param boolean $dbg True if IMAP conversation should be logged
+     * @access public
+     */
+    function set_debug($dbg = true)
+    {
+        $this->options['debug'] = $dbg;
+        $this->conn->setDebug($dbg, array($this, 'debug_handler'));
+    }
+
+
     /**
      * Set default message charset
      *
     /**
      * Set default message charset
      *
@@ -457,7 +478,7 @@ class rcube_imap
      */
     function get_mailbox_name()
     {
      */
     function get_mailbox_name()
     {
-        return $this->conn->connected() ? $this->mailbox : '';
+        return $this->mailbox;
     }
 
 
     }
 
 
@@ -689,7 +710,7 @@ class rcube_imap
 
             if ($status) {
                 $this->set_folder_stats($mailbox, 'cnt', $res['msgcount']);
 
             if ($status) {
                 $this->set_folder_stats($mailbox, 'cnt', $res['msgcount']);
-                $this->set_folder_stats($mailbox, 'maxuid', $res['maxuid'] ? $this->_id2uid($res['maxuid'], $mailbox) : 0);
+                $this->set_folder_stats($mailbox, 'maxuid', $res['maxuid'] ? $this->id2uid($res['maxuid'], $mailbox) : 0);
             }
         }
         // RECENT count is fetched a bit different
             }
         }
         // RECENT count is fetched a bit different
@@ -722,9 +743,9 @@ class rcube_imap
             $count = is_array($index) ? $index['COUNT'] : 0;
 
             if ($mode == 'ALL') {
             $count = is_array($index) ? $index['COUNT'] : 0;
 
             if ($mode == 'ALL') {
-                if ($need_uid && $this->messages_caching) {
-                    // Save messages index for check_cache_status()
-                    $this->icache['all_undeleted_idx'] = $index['ALL'];
+                if ($this->messages_caching) {
+                    // Save additional info required by cache status check
+                    $this->icache['undeleted_idx'] = array($mailbox, $index['ALL'], $index['COUNT']);
                 }
                 if ($status) {
                     $this->set_folder_stats($mailbox, 'cnt', $count);
                 }
                 if ($status) {
                     $this->set_folder_stats($mailbox, 'cnt', $count);
@@ -739,7 +760,7 @@ class rcube_imap
                 $count = $this->conn->countMessages($mailbox);
                 if ($status) {
                     $this->set_folder_stats($mailbox,'cnt', $count);
                 $count = $this->conn->countMessages($mailbox);
                 if ($status) {
                     $this->set_folder_stats($mailbox,'cnt', $count);
-                    $this->set_folder_stats($mailbox, 'maxuid', $count ? $this->_id2uid($count, $mailbox) : 0);
+                    $this->set_folder_stats($mailbox, 'maxuid', $count ? $this->id2uid($count, $mailbox) : 0);
                 }
             }
         }
                 }
             }
         }
@@ -774,7 +795,7 @@ class rcube_imap
                 'maxuid'   => $dcount ? max(array_keys($this->icache['threads']['depth'])) : 0,
             );
         }
                 'maxuid'   => $dcount ? max(array_keys($this->icache['threads']['depth'])) : 0,
             );
         }
-        else if (is_array($result = $this->_fetch_threads($mailbox))) {
+        else if (is_array($result = $this->fetch_threads($mailbox))) {
             $dcount = count($result[1]);
             $result = array(
                 'count'    => count($result[0]),
             $dcount = count($result[1]);
             $result = array(
                 'count'    => count($result[0]),
@@ -805,7 +826,7 @@ class rcube_imap
             $mailbox = $this->mailbox;
         }
 
             $mailbox = $this->mailbox;
         }
 
-        return $this->_list_headers($mailbox, $page, $sort_field, $sort_order, false, $slice);
+        return $this->_list_headers($mailbox, $page, $sort_field, $sort_order, $slice);
     }
 
 
     }
 
 
@@ -817,11 +838,11 @@ class rcube_imap
      * @param   string   $sort_field Header field to sort by
      * @param   string   $sort_order Sort order [ASC|DESC]
      * @param   int      $slice      Number of slice items to extract from result array
      * @param   string   $sort_field Header field to sort by
      * @param   string   $sort_order Sort order [ASC|DESC]
      * @param   int      $slice      Number of slice items to extract from result array
+     *
      * @return  array    Indexed array with message header objects
      * @return  array    Indexed array with message header objects
-     * @access  private
      * @see     rcube_imap::list_headers
      */
      * @see     rcube_imap::list_headers
      */
-    private function _list_headers($mailbox='', $page=NULL, $sort_field=NULL, $sort_order=NULL, $recursive=false, $slice=0)
+    private function _list_headers($mailbox='', $page=NULL, $sort_field=NULL, $sort_order=NULL, $slice=0)
     {
         if (!strlen($mailbox))
             return array();
     {
         if (!strlen($mailbox))
             return array();
@@ -831,41 +852,39 @@ class rcube_imap
             return $this->_list_header_set($mailbox, $page, $sort_field, $sort_order, $slice);
 
         if ($this->threading)
             return $this->_list_header_set($mailbox, $page, $sort_field, $sort_order, $slice);
 
         if ($this->threading)
-            return $this->_list_thread_headers($mailbox, $page, $sort_field, $sort_order, $recursive, $slice);
+            return $this->_list_thread_headers($mailbox, $page, $sort_field, $sort_order, $slice);
 
         $this->_set_sort_order($sort_field, $sort_order);
 
 
         $this->_set_sort_order($sort_field, $sort_order);
 
-        $page         = $page ? $page : $this->list_page;
-        $cache_key    = $mailbox.'.msg';
-
-        if ($this->messages_caching) {
-            // cache is OK, we can get messages from local cache
-            // (assume cache is in sync when in recursive mode)
-            if ($recursive || $this->check_cache_status($mailbox, $cache_key)>0) {
-                $start_msg = ($page-1) * $this->page_size;
-                $a_msg_headers = $this->get_message_cache($cache_key, $start_msg,
-                    $start_msg+$this->page_size, $this->sort_field, $this->sort_order);
-                $result = array_values($a_msg_headers);
-                if ($slice)
-                    $result = array_slice($result, -$slice, $slice);
-                return $result;
-            }
-            // cache is incomplete, sync it (all messages in the folder)
-            else if (!$recursive) {
-                $this->sync_header_index($mailbox);
-                return $this->_list_headers($mailbox, $page, $this->sort_field, $this->sort_order, true, $slice);
-            }
-        }
+        $page = $page ? $page : $this->list_page;
 
 
-        // retrieve headers from IMAP
-        $a_msg_headers = array();
+        // Use messages cache
+        if ($mcache = $this->get_mcache_engine()) {
+            $msg_index = $mcache->get_index($mailbox, $this->sort_field, $this->sort_order);
+
+            if (empty($msg_index))
+                return array();
+
+            $from      = ($page-1) * $this->page_size;
+            $to        = $from + $this->page_size;
+            $msg_index = array_values($msg_index); // UIDs
+            $is_uid    = true;
+            $sorted    = true;
+
+            if ($from || $to)
+                $msg_index = array_slice($msg_index, $from, $to - $from);
 
 
+            if ($slice)
+                $msg_index = array_slice($msg_index, -$slice, $slice);
+
+            $a_msg_headers = $mcache->get_messages($mailbox, $msg_index);
+        }
+        // retrieve headers from IMAP
         // use message index sort as default sorting (for better performance)
         // use message index sort as default sorting (for better performance)
-        if (!$this->sort_field) {
+        else if (!$this->sort_field) {
             if ($this->skip_deleted) {
                 // @TODO: this could be cached
                 if ($msg_index = $this->_search_index($mailbox, 'ALL UNDELETED')) {
             if ($this->skip_deleted) {
                 // @TODO: this could be cached
                 if ($msg_index = $this->_search_index($mailbox, 'ALL UNDELETED')) {
-                    $max = max($msg_index);
                     list($begin, $end) = $this->_get_message_range(count($msg_index), $page);
                     $msg_index = array_slice($msg_index, $begin, $end-$begin);
                 }
                     list($begin, $end) = $this->_get_message_range(count($msg_index), $page);
                     $msg_index = array_slice($msg_index, $begin, $end-$begin);
                 }
@@ -882,30 +901,32 @@ class rcube_imap
 
             // fetch reqested headers from server
             if ($msg_index)
 
             // fetch reqested headers from server
             if ($msg_index)
-                $this->_fetch_headers($mailbox, join(",", $msg_index), $a_msg_headers, $cache_key);
+                $a_msg_headers = $this->fetch_headers($mailbox, $msg_index);
         }
         // use SORT command
         else if ($this->get_capability('SORT') &&
             // Courier-IMAP provides SORT capability but allows to disable it by admin (#1486959)
         }
         // use SORT command
         else if ($this->get_capability('SORT') &&
             // Courier-IMAP provides SORT capability but allows to disable it by admin (#1486959)
-            ($msg_index = $this->conn->sort($mailbox, $this->sort_field, $this->skip_deleted ? 'UNDELETED' : '')) !== false
+            ($msg_index = $this->conn->sort($mailbox, $this->sort_field,
+                $this->skip_deleted ? 'UNDELETED' : '', true)) !== false
         ) {
             if (!empty($msg_index)) {
                 list($begin, $end) = $this->_get_message_range(count($msg_index), $page);
         ) {
             if (!empty($msg_index)) {
                 list($begin, $end) = $this->_get_message_range(count($msg_index), $page);
-                $max = max($msg_index);
                 $msg_index = array_slice($msg_index, $begin, $end-$begin);
                 $msg_index = array_slice($msg_index, $begin, $end-$begin);
+                $is_uid    = true;
 
                 if ($slice)
                     $msg_index = array_slice($msg_index, ($this->sort_order == 'DESC' ? 0 : -$slice), $slice);
 
                 // fetch reqested headers from server
 
                 if ($slice)
                     $msg_index = array_slice($msg_index, ($this->sort_order == 'DESC' ? 0 : -$slice), $slice);
 
                 // fetch reqested headers from server
-                $this->_fetch_headers($mailbox, join(',', $msg_index), $a_msg_headers, $cache_key);
+                $a_msg_headers = $this->fetch_headers($mailbox, $msg_index, true);
             }
         }
         // fetch specified header for all messages and sort
             }
         }
         // fetch specified header for all messages and sort
-        else if ($a_index = $this->conn->fetchHeaderIndex($mailbox, "1:*", $this->sort_field, $this->skip_deleted)) {
-            asort($a_index); // ASC
-            $msg_index = array_keys($a_index);
-            $max = max($msg_index);
+        else if ($msg_index = $this->conn->fetchHeaderIndex($mailbox, "1:*",
+            $this->sort_field, $this->skip_deleted)
+        ) {
+            asort($msg_index); // ASC
+            $msg_index = array_keys($msg_index);
             list($begin, $end) = $this->_get_message_range(count($msg_index), $page);
             $msg_index = array_slice($msg_index, $begin, $end-$begin);
 
             list($begin, $end) = $this->_get_message_range(count($msg_index), $page);
             $msg_index = array_slice($msg_index, $begin, $end-$begin);
 
@@ -913,26 +934,19 @@ class rcube_imap
                 $msg_index = array_slice($msg_index, ($this->sort_order == 'DESC' ? 0 : -$slice), $slice);
 
             // fetch reqested headers from server
                 $msg_index = array_slice($msg_index, ($this->sort_order == 'DESC' ? 0 : -$slice), $slice);
 
             // fetch reqested headers from server
-            $this->_fetch_headers($mailbox, join(",", $msg_index), $a_msg_headers, $cache_key);
+            $a_msg_headers = $this->fetch_headers($mailbox, $msg_index);
         }
 
         }
 
-        // delete cached messages with a higher index than $max+1
-        // Changed $max to $max+1 to fix this bug : #1484295
-        $this->clear_message_cache($cache_key, $max + 1);
-
-        // kick child process to sync cache
-        // ...
-
         // return empty array if no messages found
         if (!is_array($a_msg_headers) || empty($a_msg_headers))
             return array();
 
         // use this class for message sorting
         $sorter = new rcube_header_sorter();
         // return empty array if no messages found
         if (!is_array($a_msg_headers) || empty($a_msg_headers))
             return array();
 
         // use this class for message sorting
         $sorter = new rcube_header_sorter();
-        $sorter->set_sequence_numbers($msg_index);
+        $sorter->set_index($msg_index, $is_uid);
         $sorter->sort_headers($a_msg_headers);
 
         $sorter->sort_headers($a_msg_headers);
 
-        if ($this->sort_order == 'DESC')
+        if ($this->sort_order == 'DESC' && !$sorted)
             $a_msg_headers = array_reverse($a_msg_headers);
 
         return array_values($a_msg_headers);
             $a_msg_headers = array_reverse($a_msg_headers);
 
         return array_values($a_msg_headers);
@@ -946,27 +960,28 @@ class rcube_imap
      * @param   int      $page       Current page to list
      * @param   string   $sort_field Header field to sort by
      * @param   string   $sort_order Sort order [ASC|DESC]
      * @param   int      $page       Current page to list
      * @param   string   $sort_field Header field to sort by
      * @param   string   $sort_order Sort order [ASC|DESC]
-     * @param   boolean  $recursive  True if called recursively
      * @param   int      $slice      Number of slice items to extract from result array
      * @param   int      $slice      Number of slice items to extract from result array
+     *
      * @return  array    Indexed array with message header objects
      * @return  array    Indexed array with message header objects
-     * @access  private
      * @see     rcube_imap::list_headers
      */
      * @see     rcube_imap::list_headers
      */
-    private function _list_thread_headers($mailbox, $page=NULL, $sort_field=NULL, $sort_order=NULL, $recursive=false, $slice=0)
+    private function _list_thread_headers($mailbox, $page=NULL, $sort_field=NULL, $sort_order=NULL, $slice=0)
     {
         $this->_set_sort_order($sort_field, $sort_order);
 
     {
         $this->_set_sort_order($sort_field, $sort_order);
 
-        $page = $page ? $page : $this->list_page;
-//    $cache_key = $mailbox.'.msg';
-//    $cache_status = $this->check_cache_status($mailbox, $cache_key);
+        $page   = $page ? $page : $this->list_page;
+        $mcache = $this->get_mcache_engine();
 
 
-        // get all threads (default sort order)
-        list ($thread_tree, $msg_depth, $has_children) = $this->_fetch_threads($mailbox);
+        // get all threads (not sorted)
+        if ($mcache)
+            list ($thread_tree, $msg_depth, $has_children) = $mcache->get_thread($mailbox);
+        else
+            list ($thread_tree, $msg_depth, $has_children) = $this->fetch_threads($mailbox);
 
         if (empty($thread_tree))
             return array();
 
 
         if (empty($thread_tree))
             return array();
 
-        $msg_index = $this->_sort_threads($mailbox, $thread_tree);
+        $msg_index = $this->sort_threads($mailbox, $thread_tree);
 
         return $this->_fetch_thread_headers($mailbox,
             $thread_tree, $msg_depth, $has_children, $msg_index, $page, $slice);
 
         return $this->_fetch_thread_headers($mailbox,
             $thread_tree, $msg_depth, $has_children, $msg_index, $page, $slice);
@@ -974,14 +989,20 @@ class rcube_imap
 
 
     /**
 
 
     /**
-     * Private method for fetching threads data
+     * Method for fetching threads data
+     *
+     * @param  string $mailbox  Folder name
+     * @param  bool   $force    Use IMAP server, no cache
      *
      *
-     * @param   string   $mailbox Mailbox/folder name
      * @return  array    Array with thread data
      * @return  array    Array with thread data
-     * @access  private
      */
      */
-    private function _fetch_threads($mailbox)
+    function fetch_threads($mailbox, $force = false)
     {
     {
+        if (!$force && ($mcache = $this->get_mcache_engine())) {
+            // don't store in self's internal cache, cache has it's own internal cache
+            return $mcache->get_thread($mailbox);
+        }
+
         if (empty($this->icache['threads'])) {
             // get all threads
             $result = $this->conn->thread($mailbox, $this->threading,
         if (empty($this->icache['threads'])) {
             // get all threads
             $result = $this->conn->thread($mailbox, $this->threading,
@@ -1012,12 +1033,12 @@ class rcube_imap
      * @param array   $msg_index    Messages index
      * @param int     $page         List page number
      * @param int     $slice        Number of threads to slice
      * @param array   $msg_index    Messages index
      * @param int     $page         List page number
      * @param int     $slice        Number of threads to slice
+     *
      * @return array  Messages headers
      * @access  private
      */
     private function _fetch_thread_headers($mailbox, $thread_tree, $msg_depth, $has_children, $msg_index, $page, $slice=0)
     {
      * @return array  Messages headers
      * @access  private
      */
     private function _fetch_thread_headers($mailbox, $thread_tree, $msg_depth, $has_children, $msg_index, $page, $slice=0)
     {
-        $cache_key = $mailbox.'.msg';
         // now get IDs for current page
         list($begin, $end) = $this->_get_message_range(count($msg_index), $page);
         $msg_index = array_slice($msg_index, $begin, $end-$begin);
         // now get IDs for current page
         list($begin, $end) = $this->_get_message_range(count($msg_index), $page);
         $msg_index = array_slice($msg_index, $begin, $end-$begin);
@@ -1038,7 +1059,7 @@ class rcube_imap
         }
 
         // fetch reqested headers from server
         }
 
         // fetch reqested headers from server
-        $this->_fetch_headers($mailbox, $all_ids, $a_msg_headers, $cache_key);
+        $a_msg_headers = $this->fetch_headers($mailbox, $all_ids);
 
         // return empty array if no messages found
         if (!is_array($a_msg_headers) || empty($a_msg_headers))
 
         // return empty array if no messages found
         if (!is_array($a_msg_headers) || empty($a_msg_headers))
@@ -1046,7 +1067,7 @@ class rcube_imap
 
         // use this class for message sorting
         $sorter = new rcube_header_sorter();
 
         // use this class for message sorting
         $sorter = new rcube_header_sorter();
-        $sorter->set_sequence_numbers($all_ids);
+        $sorter->set_index($all_ids);
         $sorter->sort_headers($a_msg_headers);
 
         // Set depth, has_children and unread_children fields in headers
         $sorter->sort_headers($a_msg_headers);
 
         // Set depth, has_children and unread_children fields in headers
@@ -1077,7 +1098,7 @@ class rcube_imap
 
             if (!empty($parents)) {
                 $headers[$idx]->parent_uid = end($parents);
 
             if (!empty($parents)) {
                 $headers[$idx]->parent_uid = end($parents);
-                if (!$header->seen)
+                if (empty($header->flags['SEEN']))
                     $headers[$parents[0]]->unread_children++;
             }
             array_push($parents, $header->uid);
                     $headers[$parents[0]]->unread_children++;
             }
             array_push($parents, $header->uid);
@@ -1135,11 +1156,11 @@ class rcube_imap
                 $msgs = array_slice($msgs, -$slice, $slice);
 
             // fetch headers
                 $msgs = array_slice($msgs, -$slice, $slice);
 
             // fetch headers
-            $this->_fetch_headers($mailbox, join(',',$msgs), $a_msg_headers, NULL);
+            $a_msg_headers = $this->fetch_headers($mailbox, $msgs);
 
             // I didn't found in RFC that FETCH always returns messages sorted by index
             $sorter = new rcube_header_sorter();
 
             // I didn't found in RFC that FETCH always returns messages sorted by index
             $sorter = new rcube_header_sorter();
-            $sorter->set_sequence_numbers($msgs);
+            $sorter->set_index($msgs);
             $sorter->sort_headers($a_msg_headers);
 
             return array_values($a_msg_headers);
             $sorter->sort_headers($a_msg_headers);
 
             return array_values($a_msg_headers);
@@ -1165,10 +1186,10 @@ class rcube_imap
                 $msgs = array_slice($msgs, -$slice, $slice);
 
             // fetch headers
                 $msgs = array_slice($msgs, -$slice, $slice);
 
             // fetch headers
-            $this->_fetch_headers($mailbox, join(',',$msgs), $a_msg_headers, NULL);
+            $a_msg_headers = $this->fetch_headers($mailbox, $msgs);
 
             $sorter = new rcube_header_sorter();
 
             $sorter = new rcube_header_sorter();
-            $sorter->set_sequence_numbers($msgs);
+            $sorter->set_index($msgs);
             $sorter->sort_headers($a_msg_headers);
 
             return array_values($a_msg_headers);
             $sorter->sort_headers($a_msg_headers);
 
             return array_values($a_msg_headers);
@@ -1184,21 +1205,22 @@ class rcube_imap
                 if ($slice)
                     $msgs = array_slice($msgs, -$slice, $slice);
                 // ...and fetch headers
                 if ($slice)
                     $msgs = array_slice($msgs, -$slice, $slice);
                 // ...and fetch headers
-                $this->_fetch_headers($mailbox, join(',', $msgs), $a_msg_headers, NULL);
+                $a_msg_headers = $this->fetch_headers($mailbox, $msgs);
+
 
                 // return empty array if no messages found
                 if (!is_array($a_msg_headers) || empty($a_msg_headers))
                     return array();
 
                 $sorter = new rcube_header_sorter();
 
                 // return empty array if no messages found
                 if (!is_array($a_msg_headers) || empty($a_msg_headers))
                     return array();
 
                 $sorter = new rcube_header_sorter();
-                $sorter->set_sequence_numbers($msgs);
+                $sorter->set_index($msgs);
                 $sorter->sort_headers($a_msg_headers);
 
                 return array_values($a_msg_headers);
             }
             else {
                 // for small result set we can fetch all messages headers
                 $sorter->sort_headers($a_msg_headers);
 
                 return array_values($a_msg_headers);
             }
             else {
                 // for small result set we can fetch all messages headers
-                $this->_fetch_headers($mailbox, join(',', $msgs), $a_msg_headers, NULL);
+                $a_msg_headers = $this->fetch_headers($mailbox, $msgs);
 
                 // return empty array if no messages found
                 if (!is_array($a_msg_headers) || empty($a_msg_headers))
 
                 // return empty array if no messages found
                 if (!is_array($a_msg_headers) || empty($a_msg_headers))
@@ -1256,7 +1278,7 @@ class rcube_imap
 
         $this->_set_sort_order($sort_field, $sort_order);
 
 
         $this->_set_sort_order($sort_field, $sort_order);
 
-        $msg_index = $this->_sort_threads($mailbox, $thread_tree, array_keys($msg_depth));
+        $msg_index = $this->sort_threads($mailbox, $thread_tree, array_keys($msg_depth));
 
         return $this->_fetch_thread_headers($mailbox,
             $thread_tree, $msg_depth, $has_children, $msg_index, $page, $slice=0);
 
         return $this->_fetch_thread_headers($mailbox,
             $thread_tree, $msg_depth, $has_children, $msg_index, $page, $slice=0);
@@ -1297,64 +1319,37 @@ class rcube_imap
 
 
     /**
 
 
     /**
-     * Fetches message headers (used for loop)
+     * Fetches messages headers
+     *
+     * @param  string  $mailbox  Mailbox name
+     * @param  array   $msgs     Messages sequence numbers
+     * @param  bool    $is_uid   Enable if $msgs numbers are UIDs
+     * @param  bool    $force    Disables cache use
      *
      *
-     * @param  string  $mailbox       Mailbox name
-     * @param  string  $msgs          Message index to fetch
-     * @param  array   $a_msg_headers Reference to message headers array
-     * @param  string  $cache_key     Cache index key
-     * @return int     Messages count
+     * @return array Messages headers indexed by UID
      * @access private
      */
      * @access private
      */
-    private function _fetch_headers($mailbox, $msgs, &$a_msg_headers, $cache_key)
+    function fetch_headers($mailbox, $msgs, $is_uid = false, $force = false)
     {
     {
-        // fetch reqested headers from server
-        $a_header_index = $this->conn->fetchHeaders(
-            $mailbox, $msgs, false, false, $this->get_fetch_headers());
-
-        if (empty($a_header_index))
-            return 0;
+        if (empty($msgs))
+            return array();
 
 
-        foreach ($a_header_index as $i => $headers) {
-            $a_msg_headers[$headers->uid] = $headers;
+        if (!$force && ($mcache = $this->get_mcache_engine())) {
+            return $mcache->get_messages($mailbox, $msgs, $is_uid);
         }
 
         }
 
-        // Update cache
-        if ($this->messages_caching && $cache_key) {
-            // cache is incomplete?
-            $cache_index = $this->get_message_cache_index($cache_key);
-
-            foreach ($a_header_index as $headers) {
-                // message in cache
-                if ($cache_index[$headers->id] == $headers->uid) {
-                    unset($cache_index[$headers->id]);
-                    continue;
-                }
-                // wrong UID at this position
-                if ($cache_index[$headers->id]) {
-                    $for_remove[] = $cache_index[$headers->id];
-                    unset($cache_index[$headers->id]);
-                }
-                // message UID in cache but at wrong position
-                if (is_int($key = array_search($headers->uid, $cache_index))) {
-                    $for_remove[] = $cache_index[$key];
-                    unset($cache_index[$key]);
-                }
-
-                $for_create[] = $headers->uid;
-            }
+        // fetch reqested headers from server
+        $index = $this->conn->fetchHeaders(
+            $mailbox, $msgs, $is_uid, false, $this->get_fetch_headers());
 
 
-            if ($for_remove)
-                $this->remove_message_cache($cache_key, $for_remove);
+        if (empty($index))
+            return array();
 
 
-            // add messages to cache
-            foreach ((array)$for_create as $uid) {
-                $headers = $a_msg_headers[$uid];
-                $this->add_message_cache($cache_key, $headers->id, $headers, NULL, true);
-            }
+        foreach ($index as $headers) {
+            $a_msg_headers[$headers->uid] = $headers;
         }
 
         }
 
-        return count($a_msg_headers);
+        return $a_msg_headers;
     }
 
 
     }
 
 
@@ -1378,6 +1373,11 @@ class rcube_imap
         $this->_messagecount($mailbox, 'ALL', true);
 
         $result = 0;
         $this->_messagecount($mailbox, 'ALL', true);
 
         $result = 0;
+
+        if (empty($old)) {
+            return $result;
+        }
+
         $new = $this->get_folder_stats($mailbox);
 
         // got new messages
         $new = $this->get_folder_stats($mailbox);
 
         // got new messages
@@ -1471,7 +1471,7 @@ class rcube_imap
             }
             else {
                 $a_index = $this->conn->fetchHeaderIndex($mailbox,
             }
             else {
                 $a_index = $this->conn->fetchHeaderIndex($mailbox,
-                       join(',', $this->search_set), $this->sort_field, $this->skip_deleted);
+                    join(',', $this->search_set), $this->sort_field, $this->skip_deleted);
 
                 if (is_array($a_index)) {
                     if ($this->sort_order=="ASC")
 
                 if (is_array($a_index)) {
                     if ($this->sort_order=="ASC")
@@ -1492,53 +1492,65 @@ class rcube_imap
             return $this->icache[$key];
 
         // check local cache
             return $this->icache[$key];
 
         // check local cache
-        $cache_key = $mailbox.'.msg';
-        $cache_status = $this->check_cache_status($mailbox, $cache_key);
-
-        // cache is OK
-        if ($cache_status>0) {
-            $a_index = $this->get_message_cache_index($cache_key,
-                $this->sort_field, $this->sort_order);
-            return array_keys($a_index);
+        if ($mcache = $this->get_mcache_engine()) {
+            $a_index = $mcache->get_index($mailbox, $this->sort_field, $this->sort_order);
+            $this->icache[$key] = array_keys($a_index);
+        }
+        // fetch from IMAP server
+        else {
+            $this->icache[$key] = $this->message_index_direct(
+                $mailbox, $this->sort_field, $this->sort_order);
         }
 
         }
 
+        return $this->icache[$key];
+    }
+
+
+    /**
+     * Return sorted array of message IDs (not UIDs) directly from IMAP server.
+     * Doesn't use cache and ignores current search settings.
+     *
+     * @param string $mailbox    Mailbox to get index from
+     * @param string $sort_field Sort column
+     * @param string $sort_order Sort order [ASC, DESC]
+     *
+     * @return array Indexed array with message IDs
+     */
+    function message_index_direct($mailbox, $sort_field = null, $sort_order = null)
+    {
         // use message index sort as default sorting
         // use message index sort as default sorting
-        if (!$this->sort_field) {
+        if (!$sort_field) {
             if ($this->skip_deleted) {
                 $a_index = $this->conn->search($mailbox, 'ALL UNDELETED');
                 // I didn't found that SEARCH should return sorted IDs
                 if (is_array($a_index))
                     sort($a_index);
             if ($this->skip_deleted) {
                 $a_index = $this->conn->search($mailbox, 'ALL UNDELETED');
                 // I didn't found that SEARCH should return sorted IDs
                 if (is_array($a_index))
                     sort($a_index);
-            } else if ($max = $this->_messagecount($mailbox)) {
+            } else if ($max = $this->_messagecount($mailbox, 'ALL', true, false)) {
                 $a_index = range(1, $max);
             }
 
                 $a_index = range(1, $max);
             }
 
-            if ($a_index !== false && $this->sort_order == 'DESC')
+            if ($a_index !== false && $sort_order == 'DESC')
                 $a_index = array_reverse($a_index);
                 $a_index = array_reverse($a_index);
-
-            $this->icache[$key] = $a_index;
         }
         // fetch complete message index
         else if ($this->get_capability('SORT') &&
             ($a_index = $this->conn->sort($mailbox,
         }
         // fetch complete message index
         else if ($this->get_capability('SORT') &&
             ($a_index = $this->conn->sort($mailbox,
-                $this->sort_field, $this->skip_deleted ? 'UNDELETED' : '')) !== false
+                $sort_field, $this->skip_deleted ? 'UNDELETED' : '')) !== false
         ) {
         ) {
-            if ($this->sort_order == 'DESC')
+            if ($sort_order == 'DESC')
                 $a_index = array_reverse($a_index);
                 $a_index = array_reverse($a_index);
-
-            $this->icache[$key] = $a_index;
         }
         else if ($a_index = $this->conn->fetchHeaderIndex(
         }
         else if ($a_index = $this->conn->fetchHeaderIndex(
-            $mailbox, "1:*", $this->sort_field, $this->skip_deleted)) {
-            if ($this->sort_order=="ASC")
+            $mailbox, "1:*", $sort_field, $skip_deleted)) {
+            if ($sort_order=="ASC")
                 asort($a_index);
                 asort($a_index);
-            else if ($this->sort_order=="DESC")
+            else if ($sort_order=="DESC")
                 arsort($a_index);
 
                 arsort($a_index);
 
-            $this->icache[$key] = array_keys($a_index);
+            $a_index = array_keys($a_index);
         }
 
         }
 
-        return $this->icache[$key] !== false ? $this->icache[$key] : array();
+        return $a_index !== false ? $a_index : array();
     }
 
 
     }
 
 
@@ -1570,19 +1582,9 @@ class rcube_imap
         // have stored it in RAM
         if (isset($this->icache[$key]))
             return $this->icache[$key];
         // have stored it in RAM
         if (isset($this->icache[$key]))
             return $this->icache[$key];
-/*
-        // check local cache
-        $cache_key = $mailbox.'.msg';
-        $cache_status = $this->check_cache_status($mailbox, $cache_key);
 
 
-        // cache is OK
-        if ($cache_status>0) {
-            $a_index = $this->get_message_cache_index($cache_key, $this->sort_field, $this->sort_order);
-            return array_keys($a_index);
-        }
-*/
         // get all threads (default sort order)
         // get all threads (default sort order)
-        list ($thread_tree) = $this->_fetch_threads($mailbox);
+        list ($thread_tree) = $this->fetch_threads($mailbox);
 
         $this->icache[$key] = $this->_flatten_threads($mailbox, $thread_tree);
 
 
         $this->icache[$key] = $this->_flatten_threads($mailbox, $thread_tree);
 
@@ -1594,7 +1596,7 @@ class rcube_imap
      * Return array of threaded messages (all, not only roots)
      *
      * @param string $mailbox     Mailbox to get index from
      * Return array of threaded messages (all, not only roots)
      *
      * @param string $mailbox     Mailbox to get index from
-     * @param array  $thread_tree Threaded messages array (see _fetch_threads())
+     * @param array  $thread_tree Threaded messages array (see fetch_threads())
      * @param array  $ids         Message IDs if we know what we need (e.g. search result)
      *                            for better performance
      * @return array Indexed array with message IDs
      * @param array  $ids         Message IDs if we know what we need (e.g. search result)
      *                            for better performance
      * @return array Indexed array with message IDs
@@ -1606,7 +1608,7 @@ class rcube_imap
         if (empty($thread_tree))
             return array();
 
         if (empty($thread_tree))
             return array();
 
-        $msg_index = $this->_sort_threads($mailbox, $thread_tree, $ids);
+        $msg_index = $this->sort_threads($mailbox, $thread_tree, $ids);
 
         if ($this->sort_order == 'DESC')
             $msg_index = array_reverse($msg_index);
 
         if ($this->sort_order == 'DESC')
             $msg_index = array_reverse($msg_index);
@@ -1625,99 +1627,6 @@ class rcube_imap
     }
 
 
     }
 
 
-    /**
-     * @param string $mailbox Mailbox name
-     * @access private
-     */
-    private function sync_header_index($mailbox)
-    {
-        $cache_key = $mailbox.'.msg';
-        $cache_index = $this->get_message_cache_index($cache_key);
-        $chunk_size = 1000;
-
-        // cache is empty, get all messages
-        if (is_array($cache_index) && empty($cache_index)) {
-            $max = $this->_messagecount($mailbox);
-            // syncing a big folder maybe slow
-            @set_time_limit(0);
-            $start = 1;
-            $end   = min($chunk_size, $max);
-            while (true) {
-                // do this in loop to save memory (1000 msgs ~= 10 MB)
-                if ($headers = $this->conn->fetchHeaders($mailbox,
-                    "$start:$end", false, false, $this->get_fetch_headers())
-                ) {
-                    foreach ($headers as $header) {
-                        $this->add_message_cache($cache_key, $header->id, $header, NULL, true);
-                    }
-                }
-                if ($end - $start < $chunk_size - 1)
-                    break;
-
-                $end   = min($end+$chunk_size, $max);
-                $start += $chunk_size;
-            }
-            return;
-        }
-
-        // fetch complete message index
-        if (isset($this->icache['folder_index']))
-            $a_message_index = &$this->icache['folder_index'];
-        else
-            $a_message_index = $this->conn->fetchHeaderIndex($mailbox, "1:*", 'UID', $this->skip_deleted);
-
-        if ($a_message_index === false || $cache_index === null)
-            return;
-
-        // compare cache index with real index
-        foreach ($a_message_index as $id => $uid) {
-            // message in cache at correct position
-            if ($cache_index[$id] == $uid) {
-                unset($cache_index[$id]);
-                continue;
-            }
-
-            // other message at this position
-            if (isset($cache_index[$id])) {
-                $for_remove[] = $cache_index[$id];
-                unset($cache_index[$id]);
-            }
-
-            // message in cache but at wrong position
-            if (is_int($key = array_search($uid, $cache_index))) {
-                $for_remove[] = $uid;
-                unset($cache_index[$key]);
-            }
-
-            $for_update[] = $id;
-        }
-
-        // remove messages at wrong positions and those deleted that are still in cache_index
-        if (!empty($for_remove))
-            $cache_index = array_merge($cache_index, $for_remove);
-
-        if (!empty($cache_index))
-            $this->remove_message_cache($cache_key, $cache_index);
-
-        // fetch complete headers and add to cache
-        if (!empty($for_update)) {
-            // syncing a big folder maybe slow
-            @set_time_limit(0);
-            // To save memory do this in chunks
-            $for_update = array_chunk($for_update, $chunk_size);
-            foreach ($for_update as $uids) {
-                if ($headers = $this->conn->fetchHeaders($mailbox,
-                    $uids, false, false, $this->get_fetch_headers())
-                ) {
-                    foreach ($headers as $header) {
-                        $this->add_message_cache($cache_key, $header->id, $header, NULL, true);
-                    }
-                }
-            }
-        }
-    }
-
-
     /**
      * Invoke search request to IMAP server
      *
     /**
      * Invoke search request to IMAP server
      *
@@ -1727,6 +1636,7 @@ class rcube_imap
      * @param  string  $sort_field Header field to sort by
      * @return array   search results as list of message IDs
      * @access public
      * @param  string  $sort_field Header field to sort by
      * @return array   search results as list of message IDs
      * @access public
+     * @todo: Search criteria should be provided in non-IMAP format, eg. array
      */
     function search($mailbox='', $str=NULL, $charset=NULL, $sort_field=NULL)
     {
      */
     function search($mailbox='', $str=NULL, $charset=NULL, $sort_field=NULL)
     {
@@ -1753,8 +1663,8 @@ class rcube_imap
      * @param string $criteria   Search criteria
      * @param string $charset    Charset
      * @param string $sort_field Sorting field
      * @param string $criteria   Search criteria
      * @param string $charset    Charset
      * @param string $sort_field Sorting field
+     *
      * @return array   search results as list of message ids
      * @return array   search results as list of message ids
-     * @access private
      * @see rcube_imap::search()
      */
     private function _search_index($mailbox, $criteria='ALL', $charset=NULL, $sort_field=NULL)
      * @see rcube_imap::search()
      */
     private function _search_index($mailbox, $criteria='ALL', $charset=NULL, $sort_field=NULL)
@@ -1776,9 +1686,9 @@ class rcube_imap
             if ($a_messages !== false) {
                 list ($thread_tree, $msg_depth, $has_children) = $a_messages;
                 $a_messages = array(
             if ($a_messages !== false) {
                 list ($thread_tree, $msg_depth, $has_children) = $a_messages;
                 $a_messages = array(
-                    'tree'     => $thread_tree,
-                       'depth' => $msg_depth,
-                       'children' => $has_children
+                    'tree' => $thread_tree,
+                    'depth'=> $msg_depth,
+                    'children' => $has_children
                 );
             }
 
                 );
             }
 
@@ -1790,7 +1700,7 @@ class rcube_imap
             $a_messages = $this->conn->sort($mailbox, $sort_field, $criteria, false, $charset);
 
             // Error, try with US-ASCII (RFC5256: SORT/THREAD must support US-ASCII and UTF-8,
             $a_messages = $this->conn->sort($mailbox, $sort_field, $criteria, false, $charset);
 
             // Error, try with US-ASCII (RFC5256: SORT/THREAD must support US-ASCII and UTF-8,
-            // but I've seen that Courier doesn't support UTF-8)
+            // but I've seen Courier with disabled UTF-8 support)
             if ($a_messages === false && $charset && $charset != 'US-ASCII')
                 $a_messages = $this->conn->sort($mailbox, $sort_field,
                     $this->convert_criteria($criteria, $charset), false, 'US-ASCII');
             if ($a_messages === false && $charset && $charset != 'US-ASCII')
                 $a_messages = $this->conn->sort($mailbox, $sort_field,
                     $this->convert_criteria($criteria, $charset), false, 'US-ASCII');
@@ -1802,7 +1712,7 @@ class rcube_imap
         }
 
         if ($orig_criteria == 'ALL') {
         }
 
         if ($orig_criteria == 'ALL') {
-            $max = $this->_messagecount($mailbox);
+            $max = $this->_messagecount($mailbox, 'ALL', true, false);
             $a_messages = $max ? range(1, $max) : array();
         }
         else {
             $a_messages = $max ? range(1, $max) : array();
         }
         else {
@@ -1832,8 +1742,8 @@ class rcube_imap
      * @param  string  $mailbox Mailbox name to search in
      * @param  string  $str     Search string
      * @param  boolean $ret_uid True if UIDs should be returned
      * @param  string  $mailbox Mailbox name to search in
      * @param  string  $str     Search string
      * @param  boolean $ret_uid True if UIDs should be returned
+     *
      * @return array   Search results as list of message IDs or UIDs
      * @return array   Search results as list of message IDs or UIDs
-     * @access public
      */
     function search_once($mailbox='', $str=NULL, $ret_uid=false)
     {
      */
     function search_once($mailbox='', $str=NULL, $ret_uid=false)
     {
@@ -1866,9 +1776,9 @@ class rcube_imap
                 $string_offset = $m[1] + strlen($m[0]) + 4; // {}\r\n
                 $string = substr($str, $string_offset - 1, $m[0]);
                 $string = rcube_charset_convert($string, $charset, $dest_charset);
                 $string_offset = $m[1] + strlen($m[0]) + 4; // {}\r\n
                 $string = substr($str, $string_offset - 1, $m[0]);
                 $string = rcube_charset_convert($string, $charset, $dest_charset);
-                if (!$string)
+                if ($string === false)
                     continue;
                     continue;
-                $res .= sprintf("%s{%d}\r\n%s", substr($str, $last, $m[1] - $last - 1), strlen($string), $string);
+                $res .= substr($str, $last, $m[1] - $last - 1) . rcube_imap_generic::escape($string);
                 $last = $m[0] + $string_offset - 1;
             }
             if ($last < strlen($str))
                 $last = $m[0] + $string_offset - 1;
             }
             if ($last < strlen($str))
@@ -1887,43 +1797,53 @@ class rcube_imap
      * @param string $mailbox     Mailbox name
      * @param  array $thread_tree Unsorted thread tree (rcube_imap_generic::thread() result)
      * @param  array $ids         Message IDs if we know what we need (e.g. search result)
      * @param string $mailbox     Mailbox name
      * @param  array $thread_tree Unsorted thread tree (rcube_imap_generic::thread() result)
      * @param  array $ids         Message IDs if we know what we need (e.g. search result)
+     *
      * @return array Sorted roots IDs
      * @return array Sorted roots IDs
-     * @access private
      */
      */
-    private function _sort_threads($mailbox, $thread_tree, $ids=NULL)
+    function sort_threads($mailbox, $thread_tree, $ids = null)
     {
     {
-        // THREAD=ORDEREDSUBJECT:      sorting by sent date of root message
-        // THREAD=REFERENCES:  sorting by sent date of root message
-        // THREAD=REFS:                sorting by the most recent date in each thread
+        // THREAD=ORDEREDSUBJECT: sorting by sent date of root message
+        // THREAD=REFERENCES:     sorting by sent date of root message
+        // THREAD=REFS:           sorting by the most recent date in each thread
+
         // default sorting
         if (!$this->sort_field || ($this->sort_field == 'date' && $this->threading == 'REFS')) {
             return array_keys((array)$thread_tree);
         // default sorting
         if (!$this->sort_field || ($this->sort_field == 'date' && $this->threading == 'REFS')) {
             return array_keys((array)$thread_tree);
-          }
-        // here we'll implement REFS sorting, for performance reason
-        else { // ($sort_field == 'date' && $this->threading != 'REFS')
+        }
+        // here we'll implement REFS sorting
+        else {
+            if ($mcache = $this->get_mcache_engine()) {
+                $a_index = $mcache->get_index($mailbox, $this->sort_field, 'ASC');
+                if (is_array($a_index)) {
+                    $a_index = array_keys($a_index);
+                    // now we must remove IDs that doesn't exist in $ids
+                    if (!empty($ids))
+                        $a_index = array_intersect($a_index, $ids);
+                }
+            }
             // use SORT command
             // use SORT command
-            if ($this->get_capability('SORT') && 
+            else if ($this->get_capability('SORT') &&
                 ($a_index = $this->conn->sort($mailbox, $this->sort_field,
                 ($a_index = $this->conn->sort($mailbox, $this->sort_field,
-                       !empty($ids) ? $ids : ($this->skip_deleted ? 'UNDELETED' : ''))) !== false
+                    !empty($ids) ? $ids : ($this->skip_deleted ? 'UNDELETED' : ''))) !== false
             ) {
             ) {
-                   // return unsorted tree if we've got no index data
-                   if (!$a_index)
-                       return array_keys((array)$thread_tree);
+                // do nothing
             }
             else {
                 // fetch specified headers for all messages and sort them
                 $a_index = $this->conn->fetchHeaderIndex($mailbox, !empty($ids) ? $ids : "1:*",
             }
             else {
                 // fetch specified headers for all messages and sort them
                 $a_index = $this->conn->fetchHeaderIndex($mailbox, !empty($ids) ? $ids : "1:*",
-                       $this->sort_field, $this->skip_deleted);
+                    $this->sort_field, $this->skip_deleted);
 
 
-                   // return unsorted tree if we've got no index data
-                   if (!$a_index)
-                       return array_keys((array)$thread_tree);
-
-                asort($a_index); // ASC
-                   $a_index = array_values($a_index);
+                // return unsorted tree if we've got no index data
+                if (!empty($a_index)) {
+                    asort($a_index); // ASC
+                    $a_index = array_values($a_index);
+                }
             }
 
             }
 
-               return $this->_sort_thread_refs($thread_tree, $a_index);
+            if (empty($a_index))
+                return array_keys((array)$thread_tree);
+
+            return $this->_sort_thread_refs($thread_tree, $a_index);
         }
     }
 
         }
     }
 
@@ -1931,10 +1851,10 @@ class rcube_imap
     /**
      * THREAD=REFS sorting implementation
      *
     /**
      * THREAD=REFS sorting implementation
      *
-     * @param  array $tree  Thread tree array (message identifiers as keys)
-     * @param  array $index Array of sorted message identifiers
+     * @param  array $tree   Thread tree array (message identifiers as keys)
+     * @param  array $index  Array of sorted message identifiers
+     *
      * @return array   Array of sorted roots messages
      * @return array   Array of sorted roots messages
-     * @access private
      */
     private function _sort_thread_refs($tree, $index)
     {
      */
     private function _sort_thread_refs($tree, $index)
     {
@@ -1983,7 +1903,7 @@ class rcube_imap
     {
         if (!empty($this->search_string))
             $this->search_set = $this->search('', $this->search_string, $this->search_charset,
     {
         if (!empty($this->search_string))
             $this->search_set = $this->search('', $this->search_string, $this->search_charset,
-               $this->search_sort_field, $this->search_threads, $this->search_sorted);
+                $this->search_sort_field, $this->search_threads, $this->search_sorted);
 
         return $this->get_search_set();
     }
 
         return $this->get_search_set();
     }
@@ -2011,32 +1931,25 @@ class rcube_imap
     /**
      * Return message headers object of a specific message
      *
     /**
      * Return message headers object of a specific message
      *
-     * @param int     $id       Message ID
+     * @param int     $id       Message sequence ID or UID
      * @param string  $mailbox  Mailbox to read from
      * @param string  $mailbox  Mailbox to read from
-     * @param boolean $is_uid   True if $id is the message UID
-     * @param boolean $bodystr  True if we need also BODYSTRUCTURE in headers
-     * @return object Message headers representation
+     * @param bool    $force    True to skip cache
+     *
+     * @return rcube_mail_header Message headers
      */
      */
-    function get_headers($id, $mailbox=null, $is_uid=true, $bodystr=false)
+    function get_headers($uid, $mailbox = null, $force = false)
     {
         if (!strlen($mailbox)) {
             $mailbox = $this->mailbox;
         }
     {
         if (!strlen($mailbox)) {
             $mailbox = $this->mailbox;
         }
-        $uid = $is_uid ? $id : $this->_id2uid($id, $mailbox);
 
         // get cached headers
 
         // get cached headers
-        if ($uid && ($headers = &$this->get_cached_message($mailbox.'.msg', $uid)))
-            return $headers;
-
-        $headers = $this->conn->fetchHeader(
-            $mailbox, $id, $is_uid, $bodystr, $this->get_fetch_headers());
-
-        // write headers cache
-        if ($headers) {
-            if ($headers->uid && $headers->id)
-                $this->uid_id_map[$mailbox][$headers->uid] = $headers->id;
-
-            $this->add_message_cache($mailbox.'.msg', $headers->id, $headers, NULL, false, true);
+        if (!$force && $uid && ($mcache = $this->get_mcache_engine())) {
+            $headers = $mcache->get_message($mailbox, $uid);
+        }
+        else {
+            $headers = $this->conn->fetchHeader(
+                $mailbox, $uid, true, true, $this->get_fetch_headers());
         }
 
         return $headers;
         }
 
         return $headers;
@@ -2044,33 +1957,47 @@ class rcube_imap
 
 
     /**
 
 
     /**
-     * Fetch body structure from the IMAP server and build
+     * Fetch message headers and body structure from the IMAP server and build
      * an object structure similar to the one generated by PEAR::Mail_mimeDecode
      *
      * an object structure similar to the one generated by PEAR::Mail_mimeDecode
      *
-     * @param int    $uid           Message UID to fetch
-     * @param string $structure_str Message BODYSTRUCTURE string (optional)
-     * @return object rcube_message_part Message part tree or False on failure
+     * @param int     $uid      Message UID to fetch
+     * @param string  $mailbox  Mailbox to read from
+     *
+     * @return object rcube_mail_header Message data
      */
      */
-    function &get_structure($uid, $structure_str='')
+    function get_message($uid, $mailbox = null)
     {
     {
-        $cache_key = $this->mailbox.'.msg';
-        $headers = &$this->get_cached_message($cache_key, $uid);
+        if (!strlen($mailbox)) {
+            $mailbox = $this->mailbox;
+        }
 
 
-        // return cached message structure
-        if (is_object($headers) && is_object($headers->structure)) {
-            return $headers->structure;
+        // Check internal cache
+        if (!empty($this->icache['message'])) {
+            if (($headers = $this->icache['message']) && $headers->uid == $uid) {
+                return $headers;
+            }
         }
 
         }
 
-        if (!$structure_str) {
-            $structure_str = $this->conn->fetchStructureString($this->mailbox, $uid, true);
+        $headers = $this->get_headers($uid, $mailbox);
+
+        // message doesn't exist?
+        if (empty($headers))
+            return null; 
+
+        // structure might be cached
+        if (!empty($headers->structure))
+            return $headers;
+
+        $this->_msg_uid = $uid;
+
+        if (empty($headers->bodystructure)) {
+            $headers->bodystructure = $this->conn->getStructure($mailbox, $uid, true);
         }
         }
-        $structure = rcube_mime_struct::parseStructure($structure_str);
-        $struct = false;
 
 
-        // parse structure and add headers
-        if (!empty($structure)) {
-            $headers = $this->get_headers($uid);
-            $this->_msg_id = $headers->id;
+        $structure = $headers->bodystructure;
+
+        if (empty($structure))
+            return $headers;
 
         // set message charset from message headers
         if ($headers->charset)
 
         // set message charset from message headers
         if ($headers->charset)
@@ -2093,26 +2020,21 @@ class rcube_imap
                 $structure[1] = $m[2];
             }
             else
                 $structure[1] = $m[2];
             }
             else
-                return false;
+                return $headers;
         }
 
         $struct = &$this->_structure_part($structure, 0, '', $headers);
         }
 
         $struct = &$this->_structure_part($structure, 0, '', $headers);
-        $struct->headers = get_object_vars($headers);
 
         // don't trust given content-type
 
         // don't trust given content-type
-        if (empty($struct->parts) && !empty($struct->headers['ctype'])) {
+        if (empty($struct->parts) && !empty($headers->ctype)) {
             $struct->mime_id = '1';
             $struct->mime_id = '1';
-            $struct->mimetype = strtolower($struct->headers['ctype']);
+            $struct->mimetype = strtolower($headers->ctype);
             list($struct->ctype_primary, $struct->ctype_secondary) = explode('/', $struct->mimetype);
         }
 
             list($struct->ctype_primary, $struct->ctype_secondary) = explode('/', $struct->mimetype);
         }
 
-        // write structure to cache
-        if ($this->messages_caching)
-            $this->add_message_cache($cache_key, $this->_msg_id, $headers, $struct,
-                $this->icache['message.id'][$uid], true);
-        }
+        $headers->structure = $struct;
 
 
-        return $struct;
+        return $this->icache['message'] = $headers;
     }
 
 
     }
 
 
@@ -2177,7 +2099,7 @@ class rcube_imap
             // headers for parts on all levels
             if ($mime_part_headers) {
                 $mime_part_headers = $this->conn->fetchMIMEHeaders($this->mailbox,
             // headers for parts on all levels
             if ($mime_part_headers) {
                 $mime_part_headers = $this->conn->fetchMIMEHeaders($this->mailbox,
-                    $this->_msg_id, $mime_part_headers);
+                    $this->_msg_uid, $mime_part_headers);
             }
 
             $struct->parts = array();
             }
 
             $struct->parts = array();
@@ -2279,7 +2201,7 @@ class rcube_imap
         if ($struct->ctype_primary == 'message' || ($struct->ctype_parameters['name'] && !$struct->content_id)) {
             if (empty($mime_headers)) {
                 $mime_headers = $this->conn->fetchPartHeader(
         if ($struct->ctype_primary == 'message' || ($struct->ctype_parameters['name'] && !$struct->content_id)) {
             if (empty($mime_headers)) {
                 $mime_headers = $this->conn->fetchPartHeader(
-                    $this->mailbox, $this->_msg_id, false, $struct->mime_id);
+                    $this->mailbox, $this->_msg_uid, true, $struct->mime_id);
             }
 
             if (is_string($mime_headers))
             }
 
             if (is_string($mime_headers))
@@ -2342,7 +2264,7 @@ class rcube_imap
             if ($i<2) {
                 if (!$headers) {
                     $headers = $this->conn->fetchPartHeader(
             if ($i<2) {
                 if (!$headers) {
                     $headers = $this->conn->fetchPartHeader(
-                        $this->mailbox, $this->_msg_id, false, $part->mime_id);
+                        $this->mailbox, $this->_msg_uid, true, $part->mime_id);
                 }
                 $filename_mime = '';
                 $i = 0;
                 }
                 $filename_mime = '';
                 $i = 0;
@@ -2361,7 +2283,7 @@ class rcube_imap
             if ($i<2) {
                 if (!$headers) {
                     $headers = $this->conn->fetchPartHeader(
             if ($i<2) {
                 if (!$headers) {
                     $headers = $this->conn->fetchPartHeader(
-                            $this->mailbox, $this->_msg_id, false, $part->mime_id);
+                            $this->mailbox, $this->_msg_uid, true, $part->mime_id);
                 }
                 $filename_encoded = '';
                 $i = 0; $matches = array();
                 }
                 $filename_encoded = '';
                 $i = 0; $matches = array();
@@ -2380,7 +2302,7 @@ class rcube_imap
             if ($i<2) {
                 if (!$headers) {
                     $headers = $this->conn->fetchPartHeader(
             if ($i<2) {
                 if (!$headers) {
                     $headers = $this->conn->fetchPartHeader(
-                        $this->mailbox, $this->_msg_id, false, $part->mime_id);
+                        $this->mailbox, $this->_msg_uid, true, $part->mime_id);
                 }
                 $filename_mime = '';
                 $i = 0; $matches = array();
                 }
                 $filename_mime = '';
                 $i = 0; $matches = array();
@@ -2399,7 +2321,7 @@ class rcube_imap
             if ($i<2) {
                 if (!$headers) {
                     $headers = $this->conn->fetchPartHeader(
             if ($i<2) {
                 if (!$headers) {
                     $headers = $this->conn->fetchPartHeader(
-                        $this->mailbox, $this->_msg_id, false, $part->mime_id);
+                        $this->mailbox, $this->_msg_uid, true, $part->mime_id);
                 }
                 $filename_encoded = '';
                 $i = 0; $matches = array();
                 }
                 $filename_encoded = '';
                 $i = 0; $matches = array();
@@ -2420,9 +2342,14 @@ class rcube_imap
 
         // decode filename
         if (!empty($filename_mime)) {
 
         // decode filename
         if (!empty($filename_mime)) {
-            $part->filename = rcube_imap::decode_mime_string($filename_mime,
-                $part->charset ? $part->charset : ($this->struct_charset ? $this->struct_charset :
-                rc_detect_encoding($filename_mime, $this->default_charset)));
+            if (!empty($part->charset))
+                $charset = $part->charset;
+            else if (!empty($this->struct_charset))
+                $charset = $this->struct_charset;
+            else
+                $charset = rc_detect_encoding($filename_mime, $this->default_charset);
+
+            $part->filename = rcube_imap::decode_mime_string($filename_mime, $charset);
         }
         else if (!empty($filename_encoded)) {
             // decode filename according to RFC 2231, Section 4
         }
         else if (!empty($filename_encoded)) {
             // decode filename according to RFC 2231, Section 4
@@ -2430,6 +2357,7 @@ class rcube_imap
                 $filename_charset = $fmatches[1];
                 $filename_encoded = $fmatches[2];
             }
                 $filename_charset = $fmatches[1];
                 $filename_encoded = $fmatches[2];
             }
+
             $part->filename = rcube_charset_convert(urldecode($filename_encoded), $filename_charset);
         }
     }
             $part->filename = rcube_charset_convert(urldecode($filename_encoded), $filename_charset);
         }
     }
@@ -2466,30 +2394,23 @@ class rcube_imap
      */
     function &get_message_part($uid, $part=1, $o_part=NULL, $print=NULL, $fp=NULL, $skip_charset_conv=false)
     {
      */
     function &get_message_part($uid, $part=1, $o_part=NULL, $print=NULL, $fp=NULL, $skip_charset_conv=false)
     {
-        // get part encoding if not provided
+        // get part data if not provided
         if (!is_object($o_part)) {
         if (!is_object($o_part)) {
-            $structure_str = $this->conn->fetchStructureString($this->mailbox, $uid, true);
-            $structure = new rcube_mime_struct();
-            // error or message not found
-            if (!$structure->loadStructure($structure_str)) {
-                return false;
-            }
+            $structure = $this->conn->getStructure($this->mailbox, $uid, true);
+            $part_data = rcube_imap_generic::getStructurePartData($structure, $part);
 
             $o_part = new rcube_message_part;
 
             $o_part = new rcube_message_part;
-            $o_part->ctype_primary = strtolower($structure->getPartType($part));
-            $o_part->encoding      = strtolower($structure->getPartEncoding($part));
-            $o_part->charset       = $structure->getPartCharset($part);
+            $o_part->ctype_primary = $part_data['type'];
+            $o_part->encoding      = $part_data['encoding'];
+            $o_part->charset       = $part_data['charset'];
+            $o_part->size          = $part_data['size'];
         }
 
         }
 
-        // TODO: Add caching for message parts
-
-        if (!$part) {
-            $part = 'TEXT';
+        if ($o_part && $o_part->size) {
+            $body = $this->conn->handlePartBody($this->mailbox, $uid, true,
+                $part ? $part : 'TEXT', $o_part->encoding, $print, $fp);
         }
 
         }
 
-        $body = $this->conn->handlePartBody($this->mailbox, $uid, true, $part,
-            $o_part->encoding, $print, $fp);
-
         if ($fp || $print) {
             return true;
         }
         if ($fp || $print) {
             return true;
         }
@@ -2501,7 +2422,11 @@ class rcube_imap
 
            if (!$skip_charset_conv) {
                 if (!$o_part->charset || strtoupper($o_part->charset) == 'US-ASCII') {
 
            if (!$skip_charset_conv) {
                 if (!$o_part->charset || strtoupper($o_part->charset) == 'US-ASCII') {
-                    $o_part->charset = $this->default_charset;
+                    // try to extract charset information from HTML meta tag (#1488125)
+                    if ($o_part->ctype_secondary == 'html' && preg_match('/<meta[^>]+charset=([a-z0-9-_]+)/i', $body, $m))
+                        $o_part->charset = strtoupper($m[1]);
+                    else
+                        $o_part->charset = $this->default_charset;
                 }
                 $body = rcube_charset_convert($body, $o_part->charset);
             }
                 }
                 $body = rcube_charset_convert($body, $o_part->charset);
             }
@@ -2590,12 +2515,12 @@ class rcube_imap
 
         if ($result) {
             // reload message headers if cached
 
         if ($result) {
             // reload message headers if cached
-            if ($this->messages_caching && !$skip_cache) {
-                $cache_key = $mailbox.'.msg';
-                if ($all_mode)
-                    $this->clear_message_cache($cache_key);
-                else
-                    $this->remove_message_cache($cache_key, explode(',', $uids));
+            // @TODO: update flags instead removing from cache
+            if (!$skip_cache && ($mcache = $this->get_mcache_engine())) {
+                $status = strpos($flag, 'UN') !== 0;
+                $mflag  = preg_replace('/^UN/', '', $flag);
+                $mcache->change_flag($mailbox, $all_mode ? null : explode(',', $uids),
+                    $mflag, $status);
             }
 
             // clear cached counters
             }
 
             // clear cached counters
@@ -2636,7 +2561,7 @@ class rcube_imap
      * @param string  $headers Headers string if $message contains only the body
      * @param boolean $is_file True if $message is a filename
      *
      * @param string  $headers Headers string if $message contains only the body
      * @param boolean $is_file True if $message is a filename
      *
-     * @return boolean True on success, False on error
+     * @return int|bool Appended message UID or True on success, False on error
      */
     function save_message($mailbox, &$message, $headers='', $is_file=false)
     {
      */
     function save_message($mailbox, &$message, $headers='', $is_file=false)
     {
@@ -2687,10 +2612,14 @@ class rcube_imap
 
         // make sure mailbox exists
         if ($to_mbox != 'INBOX' && !$this->mailbox_exists($to_mbox)) {
 
         // make sure mailbox exists
         if ($to_mbox != 'INBOX' && !$this->mailbox_exists($to_mbox)) {
-            if (in_array($to_mbox, $this->default_folders))
-                $this->create_mailbox($to_mbox, true);
-            else
+            if (in_array($to_mbox, $this->default_folders)) {
+                if (!$this->create_mailbox($to_mbox, true)) {
+                    return false;
+                }
+            }
+            else {
                 return false;
                 return false;
+            }
         }
 
         $config = rcmail::get_instance()->config;
         }
 
         $config = rcmail::get_instance()->config;
@@ -2727,19 +2656,18 @@ class rcube_imap
                 if ($this->search_threads || $all_mode)
                     $this->refresh_search();
                 else {
                 if ($this->search_threads || $all_mode)
                     $this->refresh_search();
                 else {
-                    $uids = explode(',', $uids);
-                    foreach ($uids as $uid)
-                        $a_mids[] = $this->_uid2id($uid, $from_mbox);
+                    $a_uids = explode(',', $uids);
+                    foreach ($a_uids as $uid)
+                        $a_mids[] = $this->uid2id($uid, $from_mbox);
                     $this->search_set = array_diff($this->search_set, $a_mids);
                 }
                     $this->search_set = array_diff($this->search_set, $a_mids);
                 }
+                unset($a_mids);
+                unset($a_uids);
             }
 
             }
 
-            // update cached message headers
-            $cache_key = $from_mbox.'.msg';
-            if ($all_mode || ($start_index = $this->get_message_cache_index_min($cache_key, $uids))) {
-                // clear cache from the lowest index on
-                $this->clear_message_cache($cache_key, $all_mode ? 1 : $start_index);
-            }
+            // remove cached messages
+            // @TODO: do cache update instead of clearing it
+            $this->clear_message_cache($from_mbox, $all_mode ? null : explode(',', $uids));
         }
 
         return $moved;
         }
 
         return $moved;
@@ -2769,10 +2697,14 @@ class rcube_imap
 
         // make sure mailbox exists
         if ($to_mbox != 'INBOX' && !$this->mailbox_exists($to_mbox)) {
 
         // make sure mailbox exists
         if ($to_mbox != 'INBOX' && !$this->mailbox_exists($to_mbox)) {
-            if (in_array($to_mbox, $this->default_folders))
-                $this->create_mailbox($to_mbox, true);
-            else
+            if (in_array($to_mbox, $this->default_folders)) {
+                if (!$this->create_mailbox($to_mbox, true)) {
+                    return false;
+                }
+            }
+            else {
                 return false;
                 return false;
+            }
         }
 
         // copy messages
         }
 
         // copy messages
@@ -2824,19 +2756,17 @@ class rcube_imap
                 if ($this->search_threads || $all_mode)
                     $this->refresh_search();
                 else {
                 if ($this->search_threads || $all_mode)
                     $this->refresh_search();
                 else {
-                    $uids = explode(',', $uids);
-                    foreach ($uids as $uid)
-                        $a_mids[] = $this->_uid2id($uid, $mailbox);
+                    $a_uids = explode(',', $uids);
+                    foreach ($a_uids as $uid)
+                        $a_mids[] = $this->uid2id($uid, $mailbox);
                     $this->search_set = array_diff($this->search_set, $a_mids);
                     $this->search_set = array_diff($this->search_set, $a_mids);
+                    unset($a_uids);
+                    unset($a_mids);
                 }
             }
 
                 }
             }
 
-            // remove deleted messages from cache
-            $cache_key = $mailbox.'.msg';
-            if ($all_mode || ($start_index = $this->get_message_cache_index_min($cache_key, $uids))) {
-                // clear cache from the lowest index on
-                $this->clear_message_cache($cache_key, $all_mode ? 1 : $start_index);
-            }
+            // remove cached messages
+            $this->clear_message_cache($mailbox, $all_mode ? null : explode(',', $uids));
         }
 
         return $deleted;
         }
 
         return $deleted;
@@ -2861,9 +2791,9 @@ class rcube_imap
             $cleared = $this->conn->clearFolder($mailbox);
         }
 
             $cleared = $this->conn->clearFolder($mailbox);
         }
 
-        // make sure the message count cache is cleared as well
+        // make sure the cache is cleared as well
         if ($cleared) {
         if ($cleared) {
-            $this->clear_message_cache($mailbox.'.msg');
+            $this->clear_message_cache($mailbox);
             $a_mailbox_cache = $this->get_cache('messagecount');
             unset($a_mailbox_cache[$mailbox]);
             $this->update_cache('messagecount', $a_mailbox_cache);
             $a_mailbox_cache = $this->get_cache('messagecount');
             unset($a_mailbox_cache[$mailbox]);
             $this->update_cache('messagecount', $a_mailbox_cache);
@@ -2904,9 +2834,9 @@ class rcube_imap
     private function _expunge($mailbox, $clear_cache=true, $uids=NULL)
     {
         if ($uids && $this->get_capability('UIDPLUS'))
     private function _expunge($mailbox, $clear_cache=true, $uids=NULL)
     {
         if ($uids && $this->get_capability('UIDPLUS'))
-            $a_uids = is_array($uids) ? join(',', $uids) : $uids;
+            list($uids, $all_mode) = $this->_parse_uids($uids, $mailbox);
         else
         else
-            $a_uids = NULL;
+            $uids = null;
 
         // force mailbox selection and check if mailbox is writeable
         // to prevent a situation when CLOSE is executed on closed
 
         // force mailbox selection and check if mailbox is writeable
         // to prevent a situation when CLOSE is executed on closed
@@ -2921,13 +2851,13 @@ class rcube_imap
         }
 
         // CLOSE(+SELECT) should be faster than EXPUNGE
         }
 
         // CLOSE(+SELECT) should be faster than EXPUNGE
-        if (empty($a_uids) || $a_uids == '1:*')
+        if (empty($uids) || $all_mode)
             $result = $this->conn->close();
         else
             $result = $this->conn->close();
         else
-            $result = $this->conn->expunge($mailbox, $a_uids);
+            $result = $this->conn->expunge($mailbox, $uids);
 
         if ($result && $clear_cache) {
 
         if ($result && $clear_cache) {
-            $this->clear_message_cache($mailbox.'.msg');
+            $this->clear_message_cache($mailbox, $all_mode ? null : explode(',', $uids));
             $this->_clear_messagecount($mailbox);
         }
 
             $this->_clear_messagecount($mailbox);
         }
 
@@ -2992,7 +2922,7 @@ class rcube_imap
             $mailbox = $this->mailbox;
         }
 
             $mailbox = $this->mailbox;
         }
 
-        return $this->_uid2id($uid, $mailbox);
+        return $this->uid2id($uid, $mailbox);
     }
 
 
     }
 
 
@@ -3010,7 +2940,7 @@ class rcube_imap
             $mailbox = $this->mailbox;
         }
 
             $mailbox = $this->mailbox;
         }
 
-        return $this->_id2uid($id, $mailbox);
+        return $this->id2uid($id, $mailbox);
     }
 
 
     }
 
 
@@ -3022,55 +2952,72 @@ class rcube_imap
     /**
      * Public method for listing subscribed folders
      *
     /**
      * Public method for listing subscribed folders
      *
-     * @param   string  $root   Optional root folder
-     * @param   string  $name   Optional name pattern
-     * @param   string  $filter Optional filter
+     * @param   string  $root      Optional root folder
+     * @param   string  $name      Optional name pattern
+     * @param   string  $filter    Optional filter
+     * @param   string  $rights    Optional ACL requirements
+     * @param   bool    $skip_sort Enable to return unsorted list (for better performance)
      *
      *
-     * @return  array   List of mailboxes/folders
+     * @return  array   List of folders
      * @access  public
      */
      * @access  public
      */
-    function list_mailboxes($root='', $name='*', $filter=null)
+    function list_mailboxes($root='', $name='*', $filter=null, $rights=null, $skip_sort=false)
     {
     {
-        $a_mboxes = $this->_list_mailboxes($root, $name, $filter);
+        $cache_key = $root.':'.$name;
+        if (!empty($filter)) {
+            $cache_key .= ':'.(is_string($filter) ? $filter : serialize($filter));
+        }
+        $cache_key .= ':'.$rights;
+        $cache_key = 'mailboxes.'.md5($cache_key);
+
+        // get cached folder list
+        $a_mboxes = $this->get_cache($cache_key);
+        if (is_array($a_mboxes)) {
+            return $a_mboxes;
+        }
+
+        $a_mboxes = $this->_list_mailboxes($root, $name, $filter, $rights);
+
+        if (!is_array($a_mboxes)) {
+            return array();
+        }
+
+        // filter folders list according to rights requirements
+        if ($rights && $this->get_capability('ACL')) {
+            $a_mboxes = $this->filter_rights($a_mboxes, $rights);
+        }
 
         // INBOX should always be available
         if ((!$filter || $filter == 'mail') && !in_array('INBOX', $a_mboxes)) {
             array_unshift($a_mboxes, 'INBOX');
         }
 
 
         // INBOX should always be available
         if ((!$filter || $filter == 'mail') && !in_array('INBOX', $a_mboxes)) {
             array_unshift($a_mboxes, 'INBOX');
         }
 
-        // sort mailboxes
-        $a_mboxes = $this->_sort_mailbox_list($a_mboxes);
+        // sort mailboxes (always sort for cache)
+        if (!$skip_sort || $this->cache) {
+            $a_mboxes = $this->_sort_mailbox_list($a_mboxes);
+        }
+
+        // write mailboxlist to cache
+        $this->update_cache($cache_key, $a_mboxes);
 
         return $a_mboxes;
     }
 
 
     /**
 
         return $a_mboxes;
     }
 
 
     /**
-     * Private method for mailbox listing
+     * Private method for mailbox listing (LSUB)
      *
      * @param   string  $root   Optional root folder
      * @param   string  $name   Optional name pattern
      * @param   mixed   $filter Optional filter
      *
      * @param   string  $root   Optional root folder
      * @param   string  $name   Optional name pattern
      * @param   mixed   $filter Optional filter
+     * @param   string  $rights Optional ACL requirements
      *
      *
-     * @return  array   List of mailboxes/folders
+     * @return  array   List of subscribed folders
      * @see     rcube_imap::list_mailboxes()
      * @access  private
      */
      * @see     rcube_imap::list_mailboxes()
      * @access  private
      */
-    private function _list_mailboxes($root='', $name='*', $filter=null)
+    private function _list_mailboxes($root='', $name='*', $filter=null, $rights=null)
     {
     {
-        $cache_key = $root.':'.$name;
-        if (!empty($filter)) {
-            $cache_key .= ':'.(is_string($filter) ? $filter : serialize($filter));
-        }
-
-        $cache_key = 'mailboxes.'.md5($cache_key);
-
-        // get cached folder list
-        $a_mboxes = $this->get_cache($cache_key);
-        if (is_array($a_mboxes)) {
-            return $a_mboxes;
-        }
-
         $a_defaults = $a_out = array();
 
         // Give plugins a chance to provide a list of mailboxes
         $a_defaults = $a_out = array();
 
         // Give plugins a chance to provide a list of mailboxes
@@ -3081,7 +3028,7 @@ class rcube_imap
             $a_folders = $data['folders'];
         }
         else if (!$this->conn->connected()) {
             $a_folders = $data['folders'];
         }
         else if (!$this->conn->connected()) {
-           return array();
+           return null;
         }
         else {
             // Server supports LIST-EXTENDED, we can use selection options
         }
         else {
             // Server supports LIST-EXTENDED, we can use selection options
@@ -3129,9 +3076,6 @@ class rcube_imap
             $a_folders = array();
         }
 
             $a_folders = array();
         }
 
-        // write mailboxlist to cache
-        $this->update_cache($cache_key, $a_folders);
-
         return $a_folders;
     }
 
         return $a_folders;
     }
 
@@ -3139,15 +3083,29 @@ class rcube_imap
     /**
      * Get a list of all folders available on the IMAP server
      *
     /**
      * Get a list of all folders available on the IMAP server
      *
-     * @param string $root   IMAP root dir
-     * @param string  $name   Optional name pattern
-     * @param mixed   $filter Optional filter
+     * @param string  $root      IMAP root dir
+     * @param string  $name      Optional name pattern
+     * @param mixed   $filter    Optional filter
+     * @param string  $rights    Optional ACL requirements
+     * @param bool    $skip_sort Enable to return unsorted list (for better performance)
      *
      * @return array Indexed array with folder names
      */
      *
      * @return array Indexed array with folder names
      */
-    function list_unsubscribed($root='', $name='*', $filter=null)
+    function list_unsubscribed($root='', $name='*', $filter=null, $rights=null, $skip_sort=false)
     {
     {
-        // @TODO: caching
+        $cache_key = $root.':'.$name;
+        if (!empty($filter)) {
+            $cache_key .= ':'.(is_string($filter) ? $filter : serialize($filter));
+        }
+        $cache_key .= ':'.$rights;
+        $cache_key = 'mailboxes.list.'.md5($cache_key);
+
+        // get cached folder list
+        $a_mboxes = $this->get_cache($cache_key);
+        if (is_array($a_mboxes)) {
+            return $a_mboxes;
+        }
+
         // Give plugins a chance to provide a list of mailboxes
         $data = rcmail::get_instance()->plugins->exec_hook('mailboxes_list',
             array('root' => $root, 'name' => $name, 'filter' => $filter, 'mode' => 'LIST'));
         // Give plugins a chance to provide a list of mailboxes
         $data = rcmail::get_instance()->plugins->exec_hook('mailboxes_list',
             array('root' => $root, 'name' => $name, 'filter' => $filter, 'mode' => 'LIST'));
@@ -3157,7 +3115,7 @@ class rcube_imap
         }
         else {
             // retrieve list of folders from IMAP server
         }
         else {
             // retrieve list of folders from IMAP server
-            $a_mboxes = $this->conn->listMailboxes($root, $name);
+            $a_mboxes = $this->_list_unsubscribed($root, $name);
         }
 
         if (!is_array($a_mboxes)) {
         }
 
         if (!is_array($a_mboxes)) {
@@ -3169,13 +3127,108 @@ class rcube_imap
             array_unshift($a_mboxes, 'INBOX');
         }
 
             array_unshift($a_mboxes, 'INBOX');
         }
 
+        // cache folder attributes
+        if ($root == '' && $name == '*' && empty($filter)) {
+            $this->update_cache('mailboxes.attributes', $this->conn->data['LIST']);
+        }
+
+        // filter folders list according to rights requirements
+        if ($rights && $this->get_capability('ACL')) {
+            $a_folders = $this->filter_rights($a_folders, $rights);
+        }
+
         // filter folders and sort them
         // filter folders and sort them
-        $a_mboxes = $this->_sort_mailbox_list($a_mboxes);
+        if (!$skip_sort) {
+            $a_mboxes = $this->_sort_mailbox_list($a_mboxes);
+        }
+
+        // write mailboxlist to cache
+        $this->update_cache($cache_key, $a_mboxes);
 
         return $a_mboxes;
     }
 
 
 
         return $a_mboxes;
     }
 
 
+    /**
+     * Private method for mailbox listing (LIST)
+     *
+     * @param   string  $root   Optional root folder
+     * @param   string  $name   Optional name pattern
+     *
+     * @return  array   List of folders
+     * @see     rcube_imap::list_unsubscribed()
+     */
+    private function _list_unsubscribed($root='', $name='*')
+    {
+        $result = $this->conn->listMailboxes($root, $name);
+
+        if (!is_array($result)) {
+            return array();
+        }
+
+        // #1486796: some server configurations doesn't
+        // return folders in all namespaces, we'll try to detect that situation
+        // and ask for these namespaces separately
+        if ($root == '' && $name == '*') {
+            $delim     = $this->get_hierarchy_delimiter();
+            $namespace = $this->get_namespace();
+            $search    = array();
+
+            // build list of namespace prefixes
+            foreach ((array)$namespace as $ns) {
+                if (is_array($ns)) {
+                    foreach ($ns as $ns_data) {
+                        if (strlen($ns_data[0])) {
+                            $search[] = $ns_data[0];
+                        }
+                    }
+                }
+            }
+
+            if (!empty($search)) {
+                // go through all folders detecting namespace usage
+                foreach ($result as $folder) {
+                    foreach ($search as $idx => $prefix) {
+                        if (strpos($folder, $prefix) === 0) {
+                            unset($search[$idx]);
+                        }
+                    }
+                    if (empty($search)) {
+                        break;
+                    }
+                }
+
+                // get folders in hidden namespaces and add to the result
+                foreach ($search as $prefix) {
+                    $list = $this->conn->listMailboxes($prefix, $name);
+
+                    if (!empty($list)) {
+                        $result = array_merge($result, $list);
+                    }
+                }
+            }
+        }
+
+        return $result;
+    }
+
+
+    /**
+     * Filter the given list of folders according to access rights
+     */
+    private function filter_rights($a_folders, $rights)
+    {
+        $regex = '/('.$rights.')/';
+        foreach ($a_folders as $idx => $folder) {
+            $myrights = join('', (array)$this->my_rights($folder));
+            if ($myrights !== null && !preg_match($regex, $myrights))
+                unset($a_folders[$idx]);
+        }
+
+        return $a_folders;
+    }
+
+
     /**
      * Get mailbox quota information
      * added by Nuny
     /**
      * Get mailbox quota information
      * added by Nuny
@@ -3308,11 +3361,14 @@ class rcube_imap
                     $this->conn->unsubscribe($c_subscribed);
                     $this->conn->subscribe(preg_replace('/^'.preg_quote($mailbox, '/').'/',
                         $new_name, $c_subscribed));
                     $this->conn->unsubscribe($c_subscribed);
                     $this->conn->subscribe(preg_replace('/^'.preg_quote($mailbox, '/').'/',
                         $new_name, $c_subscribed));
+
+                    // clear cache
+                    $this->clear_message_cache($c_subscribed);
                 }
             }
 
             // clear cache
                 }
             }
 
             // clear cache
-            $this->clear_message_cache($mailbox.'.msg');
+            $this->clear_message_cache($mailbox);
             $this->clear_cache('mailboxes', true);
         }
 
             $this->clear_cache('mailboxes', true);
         }
 
@@ -3348,13 +3404,13 @@ class rcube_imap
                 if (preg_match('/^'.preg_quote($mailbox.$delm, '/').'/', $c_mbox)) {
                     $this->conn->unsubscribe($c_mbox);
                     if ($this->conn->deleteFolder($c_mbox)) {
                 if (preg_match('/^'.preg_quote($mailbox.$delm, '/').'/', $c_mbox)) {
                     $this->conn->unsubscribe($c_mbox);
                     if ($this->conn->deleteFolder($c_mbox)) {
-                           $this->clear_message_cache($c_mbox.'.msg');
+                           $this->clear_message_cache($c_mbox);
                     }
                 }
             }
 
             // clear mailbox-related cache
                     }
                 }
             }
 
             // clear mailbox-related cache
-            $this->clear_message_cache($mailbox.'.msg');
+            $this->clear_message_cache($mailbox);
             $this->clear_cache('mailboxes', true);
         }
 
             $this->clear_cache('mailboxes', true);
         }
 
@@ -3429,8 +3485,8 @@ class rcube_imap
         foreach ($this->namespace as $type => $namespace) {
             if (is_array($namespace)) {
                 foreach ($namespace as $ns) {
         foreach ($this->namespace as $type => $namespace) {
             if (is_array($namespace)) {
                 foreach ($namespace as $ns) {
-                    if (strlen($ns[0])) {
-                        if ((strlen($ns[0])>1 && $mailbox == substr($ns[0], 0, -1))
+                    if ($len = strlen($ns[0])) {
+                        if (($len > 1 && $mailbox == substr($ns[0], 0, -1))
                             || strpos($mailbox, $ns[0]) === 0
                         ) {
                             return $type;
                             || strpos($mailbox, $ns[0]) === 0
                         ) {
                             return $type;
@@ -3484,35 +3540,66 @@ class rcube_imap
 
 
     /**
 
 
     /**
-     * Gets folder options from LIST response, e.g. \Noselect, \Noinferiors
+     * Gets folder attributes from LIST response, e.g. \Noselect, \Noinferiors
      *
      * @param string $mailbox Folder name
      *
      * @param string $mailbox Folder name
-     * @param bool   $force   Set to True if options should be refreshed
-     *                        Options are available after LIST command only
+     * @param bool   $force   Set to True if attributes should be refreshed
      *
      * @return array Options list
      */
      *
      * @return array Options list
      */
-    function mailbox_options($mailbox, $force=false)
+    function mailbox_attributes($mailbox, $force=false)
     {
     {
-        if ($mailbox == 'INBOX') {
-            return array();
+        // get attributes directly from LIST command
+        if (!empty($this->conn->data['LIST']) && is_array($this->conn->data['LIST'][$mailbox])) {
+            $opts = $this->conn->data['LIST'][$mailbox];
         }
         }
-
-        if (!is_array($this->conn->data['LIST']) || !is_array($this->conn->data['LIST'][$mailbox])) {
-            if ($force) {
-                $this->conn->listMailboxes('', $mailbox);
-            }
-            else {
-                return array();
-            }
+        // get cached folder attributes
+        else if (!$force) {
+            $opts = $this->get_cache('mailboxes.attributes');
+            $opts = $opts[$mailbox];
         }
 
         }
 
-        $opts = $this->conn->data['LIST'][$mailbox];
+        if (!is_array($opts)) {
+            $this->conn->listMailboxes('', $mailbox);
+            $opts = $this->conn->data['LIST'][$mailbox];
+        }
 
         return is_array($opts) ? $opts : array();
     }
 
 
 
         return is_array($opts) ? $opts : array();
     }
 
 
+    /**
+     * Gets connection (and current mailbox) data: UIDVALIDITY, EXISTS, RECENT,
+     * PERMANENTFLAGS, UIDNEXT, UNSEEN
+     *
+     * @param string $mailbox Folder name
+     *
+     * @return array Data
+     */
+    function mailbox_data($mailbox)
+    {
+        if (!strlen($mailbox))
+            $mailbox = $this->mailbox !== null ? $this->mailbox : 'INBOX';
+
+        if ($this->conn->selected != $mailbox) {
+            if ($this->conn->select($mailbox))
+                $this->mailbox = $mailbox;
+            else
+                return null;
+        }
+
+        $data = $this->conn->data;
+
+        // add (E)SEARCH result for ALL UNDELETED query
+        if (!empty($this->icache['undeleted_idx']) && $this->icache['undeleted_idx'][0] == $mailbox) {
+            $data['ALL_UNDELETED']   = $this->icache['undeleted_idx'][1];
+            $data['COUNT_UNDELETED'] = $this->icache['undeleted_idx'][2];
+        }
+
+        return $data;
+    }
+
+
     /**
      * Returns extended information about the folder
      *
     /**
      * Returns extended information about the folder
      *
@@ -3558,17 +3645,17 @@ class rcube_imap
             }
         }
 
             }
         }
 
-        $options['name']      = $mailbox;
-        $options['options']   = $this->mailbox_options($mailbox, true);
-        $options['namespace'] = $this->mailbox_namespace($mailbox);
-        $options['rights']    = $acl && !$options['is_root'] ? (array)$this->my_rights($mailbox) : array();
-        $options['special']   = in_array($mailbox, $this->default_folders);
+        $options['name']       = $mailbox;
+        $options['attributes'] = $this->mailbox_attributes($mailbox, true);
+        $options['namespace']  = $this->mailbox_namespace($mailbox);
+        $options['rights']     = $acl && !$options['is_root'] ? (array)$this->my_rights($mailbox) : array();
+        $options['special']    = in_array($mailbox, $this->default_folders);
 
         // Set 'noselect' and 'norename' flags
 
         // Set 'noselect' and 'norename' flags
-        if (is_array($options['options'])) {
-            foreach ($options['options'] as $opt) {
-                $opt = strtolower($opt);
-                if ($opt == '\noselect' || $opt == '\nonexistent') {
+        if (is_array($options['attributes'])) {
+            foreach ($options['attributes'] as $attrib) {
+                $attrib = strtolower($attrib);
+                if ($attrib == '\noselect' || $attrib == '\nonexistent') {
                     $options['noselect'] = true;
                 }
             }
                     $options['noselect'] = true;
                 }
             }
@@ -3594,6 +3681,19 @@ class rcube_imap
     }
 
 
     }
 
 
+    /**
+     * Synchronizes messages cache.
+     *
+     * @param string $mailbox Folder name
+     */
+    public function mailbox_sync($mailbox)
+    {
+        if ($mcache = $this->get_mcache_engine()) {
+            $mcache->synchronize($mailbox);
+        }
+    }
+
+
     /**
      * Get message header names for rcube_imap_generic::fetchHeader(s)
      *
     /**
      * Get message header names for rcube_imap_generic::fetchHeader(s)
      *
@@ -3855,7 +3955,7 @@ class rcube_imap
         else {
             if ($this->cache)
                 $this->cache->close();
         else {
             if ($this->cache)
                 $this->cache->close();
-            $this->cache = null;
+            $this->cache   = null;
             $this->caching = false;
         }
     }
             $this->caching = false;
         }
     }
@@ -3925,419 +4025,50 @@ class rcube_imap
      * Enable or disable messages caching
      *
      * @param boolean $set Flag
      * Enable or disable messages caching
      *
      * @param boolean $set Flag
-     * @access public
      */
     function set_messages_caching($set)
     {
      */
     function set_messages_caching($set)
     {
-        $rcmail = rcmail::get_instance();
-
-        if ($set && ($dbh = $rcmail->get_dbh())) {
-            $this->db = $dbh;
+        if ($set) {
             $this->messages_caching = true;
         }
         else {
             $this->messages_caching = true;
         }
         else {
+            if ($this->mcache)
+                $this->mcache->close();
+            $this->mcache = null;
             $this->messages_caching = false;
         }
     }
 
     /**
             $this->messages_caching = false;
         }
     }
 
     /**
-     * Checks if the cache is up-to-date
-     *
-     * @param string $mailbox   Mailbox name
-     * @param string $cache_key Internal cache key
-     * @return int   Cache status: -3 = off, -2 = incomplete, -1 = dirty, 1 = OK
-     */
-    private function check_cache_status($mailbox, $cache_key)
-    {
-        if (!$this->messages_caching)
-            return -3;
-
-        $cache_index = $this->get_message_cache_index($cache_key);
-        $msg_count = $this->_messagecount($mailbox);
-        $cache_count = count($cache_index);
-
-        // empty mailbox
-        if (!$msg_count) {
-            return $cache_count ? -2 : 1;
-        }
-
-        if ($cache_count == $msg_count) {
-            if ($this->skip_deleted) {
-                if (!empty($this->icache['all_undeleted_idx'])) {
-                    $uids = rcube_imap_generic::uncompressMessageSet($this->icache['all_undeleted_idx']);
-                    $uids = array_flip($uids);
-                    foreach ($cache_index as $uid) {
-                        unset($uids[$uid]);
-                    }
-                }
-                else {
-                    // get all undeleted messages excluding cached UIDs
-                    $uids = $this->search_once($mailbox, 'ALL UNDELETED NOT UID '.
-                        rcube_imap_generic::compressMessageSet($cache_index));
-                }
-                if (empty($uids)) {
-                    return 1;
-                }
-            } else {
-                // get UID of the message with highest index
-                $uid = $this->_id2uid($msg_count, $mailbox);
-                $cache_uid = array_pop($cache_index);
-
-                // uids of highest message matches -> cache seems OK
-                if ($cache_uid == $uid) {
-                    return 1;
-                }
-            }
-            // cache is dirty
-            return -1;
-        }
-
-        // if cache count differs less than 10% report as dirty
-        return (abs($msg_count - $cache_count) < $msg_count/10) ? -1 : -2;
-    }
-
-
-    /**
-     * @param string $key Cache key
-     * @param string $from
-     * @param string $to
-     * @param string $sort_field
-     * @param string $sort_order
-     * @access private
+     * Getter for messages cache object
      */
      */
-    private function get_message_cache($key, $from, $to, $sort_field, $sort_order)
+    private function get_mcache_engine()
     {
     {
-        if (!$this->messages_caching)
-            return NULL;
-
-        // use idx sort as default sorting
-        if (!$sort_field || !in_array($sort_field, $this->db_header_fields)) {
-            $sort_field = 'idx';
-        }
-
-        $result = array();
-
-        $sql_result = $this->db->limitquery(
-                "SELECT idx, uid, headers".
-                " FROM ".get_table_name('messages').
-                " WHERE user_id=?".
-                " AND cache_key=?".
-                " ORDER BY ".$this->db->quoteIdentifier($sort_field)." ".strtoupper($sort_order),
-                $from,
-                $to - $from,
-                $_SESSION['user_id'],
-                $key);
-
-        while ($sql_arr = $this->db->fetch_assoc($sql_result)) {
-            $uid = intval($sql_arr['uid']);
-            $result[$uid] = $this->db->decode(unserialize($sql_arr['headers']));
-
-            // featch headers if unserialize failed
-            if (empty($result[$uid]))
-                $result[$uid] = $this->conn->fetchHeader(
-                    preg_replace('/.msg$/', '', $key), $uid, true, false, $this->get_fetch_headers());
-        }
-
-        return $result;
-    }
-
-
-    /**
-     * @param string $key Cache key
-     * @param int    $uid Message UID
-     * @return mixed
-     * @access private
-     */
-    private function &get_cached_message($key, $uid)
-    {
-        $internal_key = 'message';
-
-        if ($this->messages_caching && !isset($this->icache[$internal_key][$uid])) {
-            $sql_result = $this->db->query(
-                "SELECT idx, headers, structure, message_id".
-                " FROM ".get_table_name('messages').
-                " WHERE user_id=?".
-                " AND cache_key=?".
-                " AND uid=?",
-                $_SESSION['user_id'],
-                $key,
-                $uid);
-
-            if ($sql_arr = $this->db->fetch_assoc($sql_result)) {
-                $this->icache['message.id'][$uid] = intval($sql_arr['message_id']);
-                   $this->uid_id_map[preg_replace('/\.msg$/', '', $key)][$uid] = intval($sql_arr['idx']);
-                $this->icache[$internal_key][$uid] = $this->db->decode(unserialize($sql_arr['headers']));
-
-                if (is_object($this->icache[$internal_key][$uid]) && !empty($sql_arr['structure']))
-                    $this->icache[$internal_key][$uid]->structure = $this->db->decode(unserialize($sql_arr['structure']));
+        if ($this->messages_caching && !$this->mcache) {
+            $rcmail = rcmail::get_instance();
+            if ($dbh = $rcmail->get_dbh()) {
+                $this->mcache = new rcube_imap_cache(
+                    $dbh, $this, $rcmail->user->ID, $this->skip_deleted);
             }
         }
 
             }
         }
 
-        return $this->icache[$internal_key][$uid];
-    }
-
-
-    /**
-     * @param string  $key        Cache key
-     * @param string  $sort_field Sorting column
-     * @param string  $sort_order Sorting order
-     * @return array Messages index
-     * @access private
-     */
-    private function get_message_cache_index($key, $sort_field='idx', $sort_order='ASC')
-    {
-        if (!$this->messages_caching || empty($key))
-            return NULL;
-
-        // use idx sort as default
-        if (!$sort_field || !in_array($sort_field, $this->db_header_fields))
-            $sort_field = 'idx';
-
-        if (array_key_exists('index', $this->icache)
-            && $this->icache['index']['key'] == $key
-            && $this->icache['index']['sort_field'] == $sort_field
-        ) {
-            if ($this->icache['index']['sort_order'] == $sort_order)
-                return $this->icache['index']['result'];
-            else
-                return array_reverse($this->icache['index']['result'], true);
-        }
-
-        $this->icache['index'] = array(
-            'result'     => array(),
-            'key'        => $key,
-            'sort_field' => $sort_field,
-            'sort_order' => $sort_order,
-        );
-
-        $sql_result = $this->db->query(
-            "SELECT idx, uid".
-            " FROM ".get_table_name('messages').
-            " WHERE user_id=?".
-            " AND cache_key=?".
-            " ORDER BY ".$this->db->quote_identifier($sort_field)." ".$sort_order,
-            $_SESSION['user_id'],
-            $key);
-
-        while ($sql_arr = $this->db->fetch_assoc($sql_result))
-            $this->icache['index']['result'][$sql_arr['idx']] = intval($sql_arr['uid']);
-
-        return $this->icache['index']['result'];
+        return $this->mcache;
     }
 
     }
 
-
     /**
     /**
-     * @access private
-     */
-    private function add_message_cache($key, $index, $headers, $struct=null, $force=false, $internal_cache=false)
-    {
-        if (empty($key) || !is_object($headers) || empty($headers->uid))
-            return;
-
-        // add to internal (fast) cache
-        if ($internal_cache) {
-            $this->icache['message'][$headers->uid] = clone $headers;
-            $this->icache['message'][$headers->uid]->structure = $struct;
-        }
-
-        // no further caching
-        if (!$this->messages_caching)
-            return;
-
-        // known message id
-        if (is_int($force) && $force > 0) {
-            $message_id = $force;
-        }
-        // check for an existing record (probably headers are cached but structure not)
-        else if (!$force) {
-            $sql_result = $this->db->query(
-                "SELECT message_id".
-                " FROM ".get_table_name('messages').
-                " WHERE user_id=?".
-                " AND cache_key=?".
-                " AND uid=?",
-                $_SESSION['user_id'],
-                $key,
-                $headers->uid);
-
-            if ($sql_arr = $this->db->fetch_assoc($sql_result))
-                $message_id = $sql_arr['message_id'];
-        }
-
-        // update cache record
-        if ($message_id) {
-            $this->db->query(
-                "UPDATE ".get_table_name('messages').
-                " SET idx=?, headers=?, structure=?".
-                " WHERE message_id=?",
-                $index,
-                serialize($this->db->encode(clone $headers)),
-                is_object($struct) ? serialize($this->db->encode(clone $struct)) : NULL,
-                $message_id
-            );
-        }
-        else { // insert new record
-            $this->db->query(
-                "INSERT INTO ".get_table_name('messages').
-                " (user_id, del, cache_key, created, idx, uid, subject, ".
-                $this->db->quoteIdentifier('from').", ".
-                $this->db->quoteIdentifier('to').", ".
-                "cc, date, size, headers, structure)".
-                " VALUES (?, 0, ?, ".$this->db->now().", ?, ?, ?, ?, ?, ?, ".
-                $this->db->fromunixtime($headers->timestamp).", ?, ?, ?)",
-                $_SESSION['user_id'],
-                $key,
-                $index,
-                $headers->uid,
-                (string)mb_substr($this->db->encode($this->decode_header($headers->subject, true)), 0, 128),
-                (string)mb_substr($this->db->encode($this->decode_header($headers->from, true)), 0, 128),
-                (string)mb_substr($this->db->encode($this->decode_header($headers->to, true)), 0, 128),
-                (string)mb_substr($this->db->encode($this->decode_header($headers->cc, true)), 0, 128),
-                (int)$headers->size,
-                serialize($this->db->encode(clone $headers)),
-                is_object($struct) ? serialize($this->db->encode(clone $struct)) : NULL
-            );
-        }
-
-        unset($this->icache['index']);
-    }
-
-
-    /**
-     * @access private
-     */
-    private function remove_message_cache($key, $ids, $idx=false)
-    {
-        if (!$this->messages_caching)
-            return;
-
-        $this->db->query(
-            "DELETE FROM ".get_table_name('messages').
-            " WHERE user_id=?".
-            " AND cache_key=?".
-            " AND ".($idx ? "idx" : "uid")." IN (".$this->db->array2list($ids, 'integer').")",
-            $_SESSION['user_id'],
-            $key);
-
-        unset($this->icache['index']);
-    }
-
-
-    /**
-     * @param string $key         Cache key
-     * @param int    $start_index Start index
-     * @access private
-     */
-    private function clear_message_cache($key, $start_index=1)
-    {
-        if (!$this->messages_caching)
-            return;
-
-        $this->db->query(
-            "DELETE FROM ".get_table_name('messages').
-            " WHERE user_id=?".
-            " AND cache_key=?".
-            " AND idx>=?",
-            $_SESSION['user_id'], $key, $start_index);
-
-        unset($this->icache['index']);
-    }
-
-
-    /**
-     * @access private
-     */
-    private function get_message_cache_index_min($key, $uids=NULL)
-    {
-        if (!$this->messages_caching)
-            return;
-
-        if (!empty($uids) && !is_array($uids)) {
-            if ($uids == '*' || $uids == '1:*')
-                $uids = NULL;
-            else
-                $uids = explode(',', $uids);
-        }
-
-        $sql_result = $this->db->query(
-            "SELECT MIN(idx) AS minidx".
-            " FROM ".get_table_name('messages').
-            " WHERE  user_id=?".
-            " AND    cache_key=?"
-            .(!empty($uids) ? " AND uid IN (".$this->db->array2list($uids, 'integer').")" : ''),
-            $_SESSION['user_id'],
-            $key);
-
-        if ($sql_arr = $this->db->fetch_assoc($sql_result))
-            return $sql_arr['minidx'];
-        else
-            return 0;
-    }
-
-
-    /**
-     * @param string $key Cache key
-     * @param int    $id  Message (sequence) ID
-     * @return int Message UID
-     * @access private
+     * Clears the messages cache.
+     *
+     * @param string $mailbox Folder name
+     * @param array  $uids    Optional message UIDs to remove from cache
      */
      */
-    private function get_cache_id2uid($key, $id)
+    function clear_message_cache($mailbox = null, $uids = null)
     {
     {
-        if (!$this->messages_caching)
-            return null;
-
-        if (array_key_exists('index', $this->icache)
-            && $this->icache['index']['key'] == $key
-        ) {
-            return $this->icache['index']['result'][$id];
+        if ($mcache = $this->get_mcache_engine()) {
+            $mcache->clear($mailbox, $uids);
         }
         }
-
-        $sql_result = $this->db->query(
-            "SELECT uid".
-            " FROM ".get_table_name('messages').
-            " WHERE user_id=?".
-            " AND cache_key=?".
-            " AND idx=?",
-            $_SESSION['user_id'], $key, $id);
-
-        if ($sql_arr = $this->db->fetch_assoc($sql_result))
-            return intval($sql_arr['uid']);
-
-        return null;
     }
 
 
     }
 
 
-    /**
-     * @param string $key Cache key
-     * @param int    $uid Message UID
-     * @return int Message (sequence) ID
-     * @access private
-     */
-    private function get_cache_uid2id($key, $uid)
-    {
-        if (!$this->messages_caching)
-            return null;
-
-        if (array_key_exists('index', $this->icache)
-            && $this->icache['index']['key'] == $key
-        ) {
-            return array_search($uid, $this->icache['index']['result']);
-        }
-
-        $sql_result = $this->db->query(
-            "SELECT idx".
-            " FROM ".get_table_name('messages').
-            " WHERE user_id=?".
-            " AND cache_key=?".
-            " AND uid=?",
-            $_SESSION['user_id'], $key, $uid);
-
-        if ($sql_arr = $this->db->fetch_assoc($sql_result))
-            return intval($sql_arr['idx']);
-
-        return null;
-    }
-
 
     /* --------------------------------
      *   encoding/decoding methods
 
     /* --------------------------------
      *   encoding/decoding methods
@@ -4432,7 +4163,7 @@ class rcube_imap
         $input = preg_replace("/\?=\s+=\?/", '?==?', $input);
 
         // encoded-word regexp
         $input = preg_replace("/\?=\s+=\?/", '?==?', $input);
 
         // encoded-word regexp
-        $re = '/=\?([^?]+)\?([BbQq])\?([^?\n]*)\?=/';
+        $re = '/=\?([^?]+)\?([BbQq])\?([^\n]*?)\?=/';
 
         // Find all RFC2047's encoded words
         if (preg_match_all($re, $input, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) {
 
         // Find all RFC2047's encoded words
         if (preg_match_all($re, $input, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) {
@@ -4634,36 +4365,46 @@ class rcube_imap
 
 
     /**
 
 
     /**
-     * @param int    $uid     Message UID
-     * @param string $mailbox Mailbox name
+     * Finds message sequence ID for specified UID
+     *
+     * @param int    $uid      Message UID
+     * @param string $mailbox  Mailbox name
+     * @param bool   $force    True to skip cache
+     *
      * @return int Message (sequence) ID
      * @return int Message (sequence) ID
-     * @access private
      */
      */
-    private function _uid2id($uid, $mailbox=NULL)
+    function uid2id($uid, $mailbox = null, $force = false)
     {
         if (!strlen($mailbox)) {
             $mailbox = $this->mailbox;
         }
 
     {
         if (!strlen($mailbox)) {
             $mailbox = $this->mailbox;
         }
 
-        if (!isset($this->uid_id_map[$mailbox][$uid])) {
-            if (!($id = $this->get_cache_uid2id($mailbox.'.msg', $uid)))
-                $id = $this->conn->UID2ID($mailbox, $uid);
-
-            $this->uid_id_map[$mailbox][$uid] = $id;
+        if (!empty($this->uid_id_map[$mailbox][$uid])) {
+            return $this->uid_id_map[$mailbox][$uid];
         }
 
         }
 
-        return $this->uid_id_map[$mailbox][$uid];
+        if (!$force && ($mcache = $this->get_mcache_engine()))
+            $id = $mcache->uid2id($mailbox, $uid);
+
+        if (empty($id))
+            $id = $this->conn->UID2ID($mailbox, $uid);
+
+        $this->uid_id_map[$mailbox][$uid] = $id;
+
+        return $id;
     }
 
 
     /**
     }
 
 
     /**
-     * @param int    $id      Message (sequence) ID
-     * @param string $mailbox Mailbox name
+     * Find UID of the specified message sequence ID
+     *
+     * @param int    $id       Message (sequence) ID
+     * @param string $mailbox  Mailbox name
+     * @param bool   $force    True to skip cache
      *
      * @return int Message UID
      *
      * @return int Message UID
-     * @access private
      */
      */
-    private function _id2uid($id, $mailbox=null)
+    function id2uid($id, $mailbox = null, $force = false)
     {
         if (!strlen($mailbox)) {
             $mailbox = $this->mailbox;
     {
         if (!strlen($mailbox)) {
             $mailbox = $this->mailbox;
@@ -4673,9 +4414,11 @@ class rcube_imap
             return $uid;
         }
 
             return $uid;
         }
 
-        if (!($uid = $this->get_cache_id2uid($mailbox.'.msg', $id))) {
+        if (!$force && ($mcache = $this->get_mcache_engine()))
+            $uid = $mcache->id2uid($mailbox, $id);
+
+        if (empty($uid))
             $uid = $this->conn->ID2UID($mailbox, $id);
             $uid = $this->conn->ID2UID($mailbox, $id);
-        }
 
         $this->uid_id_map[$mailbox][$uid] = $id;
 
 
         $this->uid_id_map[$mailbox][$uid] = $id;
 
@@ -4961,16 +4704,24 @@ class rcube_message_part
  */
 class rcube_header_sorter
 {
  */
 class rcube_header_sorter
 {
-    var $sequence_numbers = array();
+    private $seqs = array();
+    private $uids = array();
+
 
     /**
      * Set the predetermined sort order.
      *
 
     /**
      * Set the predetermined sort order.
      *
-     * @param array $seqnums Numerically indexed array of IMAP message sequence numbers
+     * @param array $index  Numerically indexed array of IMAP ID or UIDs
+     * @param bool  $is_uid Set to true if $index contains UIDs
      */
      */
-    function set_sequence_numbers($seqnums)
+    function set_index($index, $is_uid = false)
     {
     {
-        $this->sequence_numbers = array_flip($seqnums);
+        $index = array_flip($index);
+
+        if ($is_uid)
+            $this->uids = $index;
+        else
+            $this->seqs = $index;
     }
 
     /**
     }
 
     /**
@@ -4980,14 +4731,10 @@ class rcube_header_sorter
      */
     function sort_headers(&$headers)
     {
      */
     function sort_headers(&$headers)
     {
-        /*
-        * uksort would work if the keys were the sequence number, but unfortunately
-        * the keys are the UIDs.  We'll use uasort instead and dereference the value
-        * to get the sequence number (in the "id" field).
-        *
-        * uksort($headers, array($this, "compare_seqnums"));
-        */
-        uasort($headers, array($this, "compare_seqnums"));
+        if (!empty($this->uids))
+            uksort($headers, array($this, "compare_uids"));
+        else
+            uasort($headers, array($this, "compare_seqnums"));
     }
 
     /**
     }
 
     /**
@@ -5003,8 +4750,24 @@ class rcube_header_sorter
         $seqb = $b->id;
 
         // then find each sequence number in my ordered list
         $seqb = $b->id;
 
         // then find each sequence number in my ordered list
-        $posa = isset($this->sequence_numbers[$seqa]) ? intval($this->sequence_numbers[$seqa]) : -1;
-        $posb = isset($this->sequence_numbers[$seqb]) ? intval($this->sequence_numbers[$seqb]) : -1;
+        $posa = isset($this->seqs[$seqa]) ? intval($this->seqs[$seqa]) : -1;
+        $posb = isset($this->seqs[$seqb]) ? intval($this->seqs[$seqb]) : -1;
+
+        // return the relative position as the comparison value
+        return $posa - $posb;
+    }
+
+    /**
+     * Sort method called by uksort()
+     *
+     * @param int $a Array key (UID)
+     * @param int $b Array key (UID)
+     */
+    function compare_uids($a, $b)
+    {
+        // then find each sequence number in my ordered list
+        $posa = isset($this->uids[$a]) ? intval($this->uids[$a]) : -1;
+        $posb = isset($this->uids[$b]) ? intval($this->uids[$b]) : -1;
 
         // return the relative position as the comparison value
         return $posa - $posb;
 
         // return the relative position as the comparison value
         return $posa - $posb;
diff --git a/program/include/rcube_imap_cache.php b/program/include/rcube_imap_cache.php
new file mode 100644 (file)
index 0000000..75b9443
--- /dev/null
@@ -0,0 +1,1212 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | program/include/rcube_imap_cache.php                                  |
+ |                                                                       |
+ | This file is part of the Roundcube Webmail client                     |
+ | Copyright (C) 2005-2011, The Roundcube Dev Team                       |
+ | Licensed under the GNU GPL                                            |
+ |                                                                       |
+ | PURPOSE:                                                              |
+ |   Caching of IMAP folder contents (messages and index)                |
+ |                                                                       |
+ +-----------------------------------------------------------------------+
+ | Author: Thomas Bruederli <roundcube@gmail.com>                        |
+ | Author: Aleksander Machniak <alec@alec.pl>                            |
+ +-----------------------------------------------------------------------+
+
+ $Id: rcube_imap_cache.php 5366 2011-10-26 11:48:27Z thomasb $
+
+*/
+
+
+/**
+ * Interface class for accessing Roundcube messages cache
+ *
+ * @package    Cache
+ * @author     Thomas Bruederli <roundcube@gmail.com>
+ * @author     Aleksander Machniak <alec@alec.pl>
+ * @version    1.0
+ */
+class rcube_imap_cache
+{
+    /**
+     * Instance of rcube_imap
+     *
+     * @var rcube_imap
+     */
+    private $imap;
+
+    /**
+     * Instance of rcube_mdb2
+     *
+     * @var rcube_mdb2
+     */
+    private $db;
+
+    /**
+     * User ID
+     *
+     * @var int
+     */
+    private $userid;
+
+    /**
+     * Internal (in-memory) cache
+     *
+     * @var array
+     */
+    private $icache = array();
+
+    private $skip_deleted = false;
+
+    /**
+     * List of known flags. Thanks to this we can handle flag changes
+     * with good performance. Bad thing is we need to know used flags.
+     */
+    public $flags = array(
+        1       => 'SEEN',          // RFC3501
+        2       => 'DELETED',       // RFC3501
+        4       => 'ANSWERED',      // RFC3501
+        8       => 'FLAGGED',       // RFC3501
+        16      => 'DRAFT',         // RFC3501
+        32      => 'MDNSENT',       // RFC3503
+        64      => 'FORWARDED',     // RFC5550
+        128     => 'SUBMITPENDING', // RFC5550
+        256     => 'SUBMITTED',     // RFC5550
+        512     => 'JUNK',
+        1024    => 'NONJUNK',
+        2048    => 'LABEL1',
+        4096    => 'LABEL2',
+        8192    => 'LABEL3',
+        16384   => 'LABEL4',
+        32768   => 'LABEL5',
+    );
+
+
+    /**
+     * Object constructor.
+     */
+    function __construct($db, $imap, $userid, $skip_deleted)
+    {
+        $this->db           = $db;
+        $this->imap         = $imap;
+        $this->userid       = (int)$userid;
+        $this->skip_deleted = $skip_deleted;
+    }
+
+
+    /**
+     * Cleanup actions (on shutdown).
+     */
+    public function close()
+    {
+        $this->save_icache();
+        $this->icache = null;
+    }
+
+
+    /**
+     * Return (sorted) messages index.
+     * If index doesn't exist or is invalid, will be updated.
+     *
+     * @param string  $mailbox     Folder name
+     * @param string  $sort_field  Sorting column
+     * @param string  $sort_order  Sorting order (ASC|DESC)
+     * @param bool    $exiting     Skip index initialization if it doesn't exist in DB
+     *
+     * @return array Messages index
+     */
+    function get_index($mailbox, $sort_field = null, $sort_order = null, $existing = false)
+    {
+        if (empty($this->icache[$mailbox]))
+            $this->icache[$mailbox] = array();
+
+        $sort_order = strtoupper($sort_order) == 'ASC' ? 'ASC' : 'DESC';
+
+        // Seek in internal cache
+        if (array_key_exists('index', $this->icache[$mailbox])) {
+            // The index was fetched from database already, but not validated yet
+            if (!array_key_exists('result', $this->icache[$mailbox]['index'])) {
+                $index = $this->icache[$mailbox]['index'];
+            }
+            // We've got a valid index
+            else if ($sort_field == 'ANY' || $this->icache[$mailbox]['index']['sort_field'] == $sort_field
+            ) {
+                if ($this->icache[$mailbox]['index']['sort_order'] == $sort_order)
+                    return $this->icache[$mailbox]['index']['result'];
+                else
+                    return array_reverse($this->icache[$mailbox]['index']['result'], true);
+            }
+        }
+
+        // Get index from DB (if DB wasn't already queried)
+        if (empty($index) && empty($this->icache[$mailbox]['index_queried'])) {
+            $index = $this->get_index_row($mailbox);
+
+            // set the flag that DB was already queried for index
+            // this way we'll be able to skip one SELECT, when
+            // get_index() is called more than once
+            $this->icache[$mailbox]['index_queried'] = true;
+        }
+
+        $data = null;
+
+        // @TODO: Think about skipping validation checks.
+        // If we could check only every 10 minutes, we would be able to skip
+        // expensive checks, mailbox selection or even IMAP connection, this would require
+        // additional logic to force cache invalidation in some cases
+        // and many rcube_imap changes to connect when needed
+
+        // Entry exists, check cache status
+        if (!empty($index)) {
+            $exists = true;
+
+            if ($sort_field == 'ANY') {
+                $sort_field = $index['sort_field'];
+            }
+
+            if ($sort_field != $index['sort_field']) {
+                $is_valid = false;
+            }
+            else {
+                $is_valid = $this->validate($mailbox, $index, $exists);
+            }
+
+            if ($is_valid) {
+                // build index, assign sequence IDs to unique IDs
+                $data = array_combine($index['seq'], $index['uid']);
+                // revert the order if needed
+                if ($index['sort_order'] != $sort_order)
+                    $data = array_reverse($data, true);
+            }
+        }
+        else {
+            if ($existing) {
+                return null;
+            }
+            else if ($sort_field == 'ANY') {
+                $sort_field = '';
+            }
+
+            // Got it in internal cache, so the row already exist
+            $exists = array_key_exists('index', $this->icache[$mailbox]);
+        }
+
+        // Index not found, not valid or sort field changed, get index from IMAP server
+        if ($data === null) {
+            // Get mailbox data (UIDVALIDITY, counters, etc.) for status check
+            $mbox_data = $this->imap->mailbox_data($mailbox);
+            $data      = $this->get_index_data($mailbox, $sort_field, $sort_order, $mbox_data);
+
+            // insert/update
+            $this->add_index_row($mailbox, $sort_field, $sort_order, $data, $mbox_data,
+                $exists, $index['modseq']);
+        }
+
+        $this->icache[$mailbox]['index'] = array(
+            'result'     => $data,
+            'sort_field' => $sort_field,
+            'sort_order' => $sort_order,
+            'modseq'     => !empty($index['modseq']) ? $index['modseq'] : $mbox_data['HIGHESTMODSEQ']
+        );
+
+        return $data;
+    }
+
+
+    /**
+     * Return messages thread.
+     * If threaded index doesn't exist or is invalid, will be updated.
+     *
+     * @param string  $mailbox     Folder name
+     * @param string  $sort_field  Sorting column
+     * @param string  $sort_order  Sorting order (ASC|DESC)
+     *
+     * @return array Messages threaded index
+     */
+    function get_thread($mailbox)
+    {
+        if (empty($this->icache[$mailbox]))
+            $this->icache[$mailbox] = array();
+
+        // Seek in internal cache
+        if (array_key_exists('thread', $this->icache[$mailbox])) {
+            return array(
+                $this->icache[$mailbox]['thread']['tree'],
+                $this->icache[$mailbox]['thread']['depth'],
+                $this->icache[$mailbox]['thread']['children'],
+            );
+        }
+
+        // Get thread from DB (if DB wasn't already queried)
+        if (empty($this->icache[$mailbox]['thread_queried'])) {
+            $index = $this->get_thread_row($mailbox);
+
+            // set the flag that DB was already queried for thread
+            // this way we'll be able to skip one SELECT, when
+            // get_thread() is called more than once or after clear()
+            $this->icache[$mailbox]['thread_queried'] = true;
+        }
+
+        $data = null;
+
+        // Entry exist, check cache status
+        if (!empty($index)) {
+            $exists   = true;
+            $is_valid = $this->validate($mailbox, $index, $exists);
+
+            if (!$is_valid) {
+                $index = null;
+            }
+        }
+
+        // Index not found or not valid, get index from IMAP server
+        if ($index === null) {
+            // Get mailbox data (UIDVALIDITY, counters, etc.) for status check
+            $mbox_data = $this->imap->mailbox_data($mailbox);
+
+            if ($mbox_data['EXISTS']) {
+                // get all threads (default sort order)
+                list ($thread_tree, $msg_depth, $has_children) = $this->imap->fetch_threads($mailbox, true);
+            }
+
+            $index = array(
+                'tree'     => !empty($thread_tree) ? $thread_tree : array(),
+                'depth'    => !empty($msg_depth) ? $msg_depth : array(),
+                'children' => !empty($has_children) ? $has_children : array(),
+            );
+
+            // insert/update
+            $this->add_thread_row($mailbox, $index, $mbox_data, $exists);
+        }
+
+        $this->icache[$mailbox]['thread'] = $index;
+
+        return array($index['tree'], $index['depth'], $index['children']);
+    }
+
+
+    /**
+     * Returns list of messages (headers). See rcube_imap::fetch_headers().
+     *
+     * @param string $mailbox  Folder name
+     * @param array  $msgs     Message sequence numbers
+     * @param bool   $is_uid   True if $msgs contains message UIDs
+     *
+     * @return array The list of messages (rcube_mail_header) indexed by UID
+     */
+    function get_messages($mailbox, $msgs = array(), $is_uid = true)
+    {
+        if (empty($msgs)) {
+            return array();
+        }
+
+        // @TODO: it would be nice if we could work with UIDs only
+        // then index would be not needed. For now we need it to
+        // map id to uid here and to update message id for cached message
+
+        // Convert IDs to UIDs
+        $index = $this->get_index($mailbox, 'ANY');
+        if (!$is_uid) {
+            foreach ($msgs as $idx => $msgid)
+                if ($uid = $index[$msgid])
+                    $msgs[$idx] = $uid;
+        }
+
+        // Fetch messages from cache
+        $sql_result = $this->db->query(
+            "SELECT uid, data, flags"
+            ." FROM ".get_table_name('cache_messages')
+            ." WHERE user_id = ?"
+                ." AND mailbox = ?"
+                ." AND uid IN (".$this->db->array2list($msgs, 'integer').")",
+            $this->userid, $mailbox);
+
+        $msgs   = array_flip($msgs);
+        $result = array();
+
+        while ($sql_arr = $this->db->fetch_assoc($sql_result)) {
+            $uid          = intval($sql_arr['uid']);
+            $result[$uid] = $this->build_message($sql_arr);
+
+            // save memory, we don't need message body here (?)
+            $result[$uid]->body = null;
+
+            // update message ID according to index data
+            if (!empty($index) && ($id = array_search($uid, $index)))
+                $result[$uid]->id = $id;
+
+            if (!empty($result[$uid])) {
+                unset($msgs[$uid]);
+            }
+        }
+
+        // Fetch not found messages from IMAP server
+        if (!empty($msgs)) {
+            $messages = $this->imap->fetch_headers($mailbox, array_keys($msgs), true, true);
+
+            // Insert to DB and add to result list
+            if (!empty($messages)) {
+                foreach ($messages as $msg) {
+                    $this->add_message($mailbox, $msg, !array_key_exists($msg->uid, $result));
+                    $result[$msg->uid] = $msg;
+                }
+            }
+        }
+
+        return $result;
+    }
+
+
+    /**
+     * Returns message data.
+     *
+     * @param string $mailbox  Folder name
+     * @param int    $uid      Message UID
+     * @param bool   $update   If message doesn't exists in cache it will be fetched
+     *                         from IMAP server
+     * @param bool   $no_cache Enables internal cache usage
+     *
+     * @return rcube_mail_header Message data
+     */
+    function get_message($mailbox, $uid, $update = true, $cache = true)
+    {
+        // Check internal cache
+        if (($message = $this->icache['message'])
+            && $message['mailbox'] == $mailbox && $message['object']->uid == $uid
+        ) {
+            return $this->icache['message']['object'];
+        }
+
+        $sql_result = $this->db->query(
+            "SELECT flags, data"
+            ." FROM ".get_table_name('cache_messages')
+            ." WHERE user_id = ?"
+                ." AND mailbox = ?"
+                ." AND uid = ?",
+                $this->userid, $mailbox, (int)$uid);
+
+        if ($sql_arr = $this->db->fetch_assoc($sql_result)) {
+            $message = $this->build_message($sql_arr);
+            $found   = true;
+
+            // update message ID according to index data
+            $index = $this->get_index($mailbox, 'ANY');
+            if (!empty($index) && ($id = array_search($uid, $index)))
+                $message->id = $id;
+        }
+
+        // Get the message from IMAP server
+        if (empty($message) && $update) {
+            $message = $this->imap->get_headers($uid, $mailbox, true);
+            // cache will be updated in close(), see below
+        }
+
+        // Save the message in internal cache, will be written to DB in close()
+        // Common scenario: user opens unseen message
+        // - get message (SELECT)
+        // - set message headers/structure (INSERT or UPDATE)
+        // - set \Seen flag (UPDATE)
+        // This way we can skip one UPDATE
+        if (!empty($message) && $cache) {
+            // Save current message from internal cache
+            $this->save_icache();
+
+            $this->icache['message'] = array(
+                'object'  => $message,
+                'mailbox' => $mailbox,
+                'exists'  => $found,
+                'md5sum'  => md5(serialize($message)),
+            );
+        }
+
+        return $message;
+    }
+
+
+    /**
+     * Saves the message in cache.
+     *
+     * @param string            $mailbox  Folder name
+     * @param rcube_mail_header $message  Message data
+     * @param bool              $force    Skips message in-cache existance check
+     */
+    function add_message($mailbox, $message, $force = false)
+    {
+        if (!is_object($message) || empty($message->uid))
+            return;
+
+        $msg   = serialize($this->db->encode(clone $message));
+        $flags = 0;
+
+        if (!empty($message->flags)) {
+            foreach ($this->flags as $idx => $flag)
+                if (!empty($message->flags[$flag]))
+                    $flags += $idx;
+        }
+        unset($msg->flags);
+
+        // update cache record (even if it exists, the update
+        // here will work as select, assume row exist if affected_rows=0)
+        if (!$force) {
+            $res = $this->db->query(
+                "UPDATE ".get_table_name('cache_messages')
+                ." SET flags = ?, data = ?, changed = ".$this->db->now()
+                ." WHERE user_id = ?"
+                    ." AND mailbox = ?"
+                    ." AND uid = ?",
+                $flags, $msg, $this->userid, $mailbox, (int) $message->uid);
+
+            if ($this->db->affected_rows())
+                return;
+        }
+
+        // insert new record
+        $this->db->query(
+            "INSERT INTO ".get_table_name('cache_messages')
+            ." (user_id, mailbox, uid, flags, changed, data)"
+            ." VALUES (?, ?, ?, ?, ".$this->db->now().", ?)",
+            $this->userid, $mailbox, (int) $message->uid, $flags, $msg);
+    }
+
+
+    /**
+     * Sets the flag for specified message.
+     *
+     * @param string  $mailbox  Folder name
+     * @param array   $uids     Message UIDs or null to change flag
+     *                          of all messages in a folder
+     * @param string  $flag     The name of the flag
+     * @param bool    $enabled  Flag state
+     */
+    function change_flag($mailbox, $uids, $flag, $enabled = false)
+    {
+        $flag = strtoupper($flag);
+        $idx  = (int) array_search($flag, $this->flags);
+
+        if (!$idx) {
+            return;
+        }
+
+        // Internal cache update
+        if ($uids && count($uids) == 1 && ($uid = current($uids))
+            && ($message = $this->icache['message'])
+            && $message['mailbox'] == $mailbox && $message['object']->uid == $uid
+        ) {
+            $message['object']->flags[$flag] = $enabled;
+            return;
+        }
+
+        $this->db->query(
+            "UPDATE ".get_table_name('cache_messages')
+            ." SET changed = ".$this->db->now()
+            .", flags = flags ".($enabled ? "+ $idx" : "- $idx")
+            ." WHERE user_id = ?"
+                ." AND mailbox = ?"
+                .($uids !== null ? " AND uid IN (".$this->db->array2list((array)$uids, 'integer').")" : "")
+                ." AND (flags & $idx) ".($enabled ? "= 0" : "= $idx"),
+            $this->userid, $mailbox);
+    }
+
+
+    /**
+     * Removes message(s) from cache.
+     *
+     * @param string $mailbox  Folder name
+     * @param array  $uids     Message UIDs, NULL removes all messages
+     */
+    function remove_message($mailbox = null, $uids = null)
+    {
+        if (!strlen($mailbox)) {
+            $this->db->query(
+                "DELETE FROM ".get_table_name('cache_messages')
+                ." WHERE user_id = ?",
+                $this->userid);
+        }
+        else {
+            // Remove the message from internal cache
+            if (!empty($uids) && !is_array($uids) && ($message = $this->icache['message'])
+                && $message['mailbox'] == $mailbox && $message['object']->uid == $uids
+            ) {
+                $this->icache['message'] = null;
+            }
+
+            $this->db->query(
+                "DELETE FROM ".get_table_name('cache_messages')
+                ." WHERE user_id = ?"
+                    ." AND mailbox = ".$this->db->quote($mailbox)
+                    .($uids !== null ? " AND uid IN (".$this->db->array2list((array)$uids, 'integer').")" : ""),
+                $this->userid);
+        }
+
+    }
+
+
+    /**
+     * Clears index cache.
+     *
+     * @param string  $mailbox     Folder name
+     * @param bool    $remove      Enable to remove the DB row
+     */
+    function remove_index($mailbox = null, $remove = false)
+    {
+        // The index should be only removed from database when
+        // UIDVALIDITY was detected or the mailbox is empty
+        // otherwise use 'valid' flag to not loose HIGHESTMODSEQ value
+        if ($remove)
+            $this->db->query(
+                "DELETE FROM ".get_table_name('cache_index')
+                ." WHERE user_id = ".intval($this->userid)
+                    .(strlen($mailbox) ? " AND mailbox = ".$this->db->quote($mailbox) : "")
+            );
+        else
+            $this->db->query(
+                "UPDATE ".get_table_name('cache_index')
+                ." SET valid = 0"
+                ." WHERE user_id = ".intval($this->userid)
+                    .(strlen($mailbox) ? " AND mailbox = ".$this->db->quote($mailbox) : "")
+            );
+
+        if (strlen($mailbox)) {
+            unset($this->icache[$mailbox]['index']);
+            // Index removed, set flag to skip SELECT query in get_index()
+            $this->icache[$mailbox]['index_queried'] = true;
+        }
+        else
+            $this->icache = array();
+    }
+
+
+    /**
+     * Clears thread cache.
+     *
+     * @param string  $mailbox     Folder name
+     */
+    function remove_thread($mailbox = null)
+    {
+        $this->db->query(
+            "DELETE FROM ".get_table_name('cache_thread')
+            ." WHERE user_id = ".intval($this->userid)
+                .(strlen($mailbox) ? " AND mailbox = ".$this->db->quote($mailbox) : "")
+        );
+
+        if (strlen($mailbox)) {
+            unset($this->icache[$mailbox]['thread']);
+            // Thread data removed, set flag to skip SELECT query in get_thread()
+            $this->icache[$mailbox]['thread_queried'] = true;
+        }
+        else
+            $this->icache = array();
+    }
+
+
+    /**
+     * Clears the cache.
+     *
+     * @param string $mailbox  Folder name
+     * @param array  $uids     Message UIDs, NULL removes all messages in a folder
+     */
+    function clear($mailbox = null, $uids = null)
+    {
+        $this->remove_index($mailbox, true);
+        $this->remove_thread($mailbox);
+        $this->remove_message($mailbox, $uids);
+    }
+
+
+    /**
+     * @param string $mailbox Folder name
+     * @param int    $id      Message (sequence) ID
+     *
+     * @return int Message UID
+     */
+    function id2uid($mailbox, $id)
+    {
+        if (!empty($this->icache['pending_index_update']))
+            return null;
+
+        // get index if it exists
+        $index = $this->get_index($mailbox, 'ANY', null, true);
+
+        return $index[$id];
+    }
+
+
+    /**
+     * @param string $mailbox Folder name
+     * @param int    $uid     Message UID
+     *
+     * @return int Message (sequence) ID
+     */
+    function uid2id($mailbox, $uid)
+    {
+        if (!empty($this->icache['pending_index_update']))
+            return null;
+
+        // get index if it exists
+        $index = $this->get_index($mailbox, 'ANY', null, true);
+
+        return array_search($uid, (array)$index);
+    }
+
+    /**
+     * Fetches index data from database
+     */
+    private function get_index_row($mailbox)
+    {
+        // Get index from DB
+        $sql_result = $this->db->query(
+            "SELECT data, valid"
+            ." FROM ".get_table_name('cache_index')
+            ." WHERE user_id = ?"
+                ." AND mailbox = ?",
+            $this->userid, $mailbox);
+
+        if ($sql_arr = $this->db->fetch_assoc($sql_result)) {
+            $data = explode('@', $sql_arr['data']);
+
+            return array(
+                'valid'      => $sql_arr['valid'],
+                'seq'        => explode(',', $data[0]),
+                'uid'        => explode(',', $data[1]),
+                'sort_field' => $data[2],
+                'sort_order' => $data[3],
+                'deleted'    => $data[4],
+                'validity'   => $data[5],
+                'uidnext'    => $data[6],
+                'modseq'     => $data[7],
+            );
+        }
+
+        return null;
+    }
+
+
+    /**
+     * Fetches thread data from database
+     */
+    private function get_thread_row($mailbox)
+    {
+        // Get thread from DB
+        $sql_result = $this->db->query(
+            "SELECT data"
+            ." FROM ".get_table_name('cache_thread')
+            ." WHERE user_id = ?"
+                ." AND mailbox = ?",
+            $this->userid, $mailbox);
+
+        if ($sql_arr = $this->db->fetch_assoc($sql_result)) {
+            $data = explode('@', $sql_arr['data']);
+
+            // Uncompress data, see add_thread_row()
+  //          $data[0] = str_replace(array('*', '^', '#'), array(';a:0:{}', 'i:', ';a:1:'), $data[0]);
+            $data[0] = unserialize($data[0]);
+
+            // build 'depth' and 'children' arrays
+            $depth = $children = array();
+            $this->build_thread_data($data[0], $depth, $children);
+
+            return array(
+                'tree'     => $data[0],
+                'depth'    => $depth,
+                'children' => $children,
+                'deleted'  => $data[1],
+                'validity' => $data[2],
+                'uidnext'  => $data[3],
+            );
+        }
+
+        return null;
+    }
+
+
+    /**
+     * Saves index data into database
+     */
+    private function add_index_row($mailbox, $sort_field, $sort_order,
+        $data = array(), $mbox_data = array(), $exists = false, $modseq = null)
+    {
+        $data = array(
+            implode(',', array_keys($data)),
+            implode(',', array_values($data)),
+            $sort_field,
+            $sort_order,
+            (int) $this->skip_deleted,
+            (int) $mbox_data['UIDVALIDITY'],
+            (int) $mbox_data['UIDNEXT'],
+            $modseq ? $modseq : $mbox_data['HIGHESTMODSEQ'],
+        );
+        $data = implode('@', $data);
+
+        if ($exists)
+            $sql_result = $this->db->query(
+                "UPDATE ".get_table_name('cache_index')
+                ." SET data = ?, valid = 1, changed = ".$this->db->now()
+                ." WHERE user_id = ?"
+                    ." AND mailbox = ?",
+                $data, $this->userid, $mailbox);
+        else
+            $sql_result = $this->db->query(
+                "INSERT INTO ".get_table_name('cache_index')
+                ." (user_id, mailbox, data, valid, changed)"
+                ." VALUES (?, ?, ?, 1, ".$this->db->now().")",
+                $this->userid, $mailbox, $data);
+    }
+
+
+    /**
+     * Saves thread data into database
+     */
+    private function add_thread_row($mailbox, $data = array(), $mbox_data = array(), $exists = false)
+    {
+        $tree = serialize($data['tree']);
+        // This significantly reduces data length
+//        $tree = str_replace(array(';a:0:{}', 'i:', ';a:1:'), array('*', '^', '#'), $tree);
+
+        $data = array(
+            $tree,
+            (int) $this->skip_deleted,
+            (int) $mbox_data['UIDVALIDITY'],
+            (int) $mbox_data['UIDNEXT'],
+        );
+        $data = implode('@', $data);
+
+        if ($exists)
+            $sql_result = $this->db->query(
+                "UPDATE ".get_table_name('cache_thread')
+                ." SET data = ?, changed = ".$this->db->now()
+                ." WHERE user_id = ?"
+                    ." AND mailbox = ?",
+                $data, $this->userid, $mailbox);
+        else
+            $sql_result = $this->db->query(
+                "INSERT INTO ".get_table_name('cache_thread')
+                ." (user_id, mailbox, data, changed)"
+                ." VALUES (?, ?, ?, ".$this->db->now().")",
+                $this->userid, $mailbox, $data);
+    }
+
+
+    /**
+     * Checks index/thread validity
+     */
+    private function validate($mailbox, $index, &$exists = true)
+    {
+        $is_thread = isset($index['tree']);
+
+        // Get mailbox data (UIDVALIDITY, counters, etc.) for status check
+        $mbox_data = $this->imap->mailbox_data($mailbox);
+
+        // @TODO: Think about skipping validation checks.
+        // If we could check only every 10 minutes, we would be able to skip
+        // expensive checks, mailbox selection or even IMAP connection, this would require
+        // additional logic to force cache invalidation in some cases
+        // and many rcube_imap changes to connect when needed
+
+        // Check UIDVALIDITY
+        if ($index['validity'] != $mbox_data['UIDVALIDITY']) {
+            $this->clear($mailbox);
+            $exists = false;
+            return false;
+        }
+
+        // Folder is empty but cache isn't
+        if (empty($mbox_data['EXISTS'])) {
+            if (!empty($index['seq']) || !empty($index['tree'])) {
+                $this->clear($mailbox);
+                $exists = false;
+                return false;
+            }
+        }
+        // Folder is not empty but cache is
+        else if (empty($index['seq']) && empty($index['tree'])) {
+            unset($this->icache[$mailbox][$is_thread ? 'thread' : 'index']);
+            return false;
+        }
+
+        // Validation flag
+        if (!$is_thread && empty($index['valid'])) {
+            unset($this->icache[$mailbox][$is_thread ? 'thread' : 'index']);
+            return false;
+        }
+
+        // Index was created with different skip_deleted setting
+        if ($this->skip_deleted != $index['deleted']) {
+            return false;
+        }
+
+        // Check HIGHESTMODSEQ
+        if (!empty($index['modseq']) && !empty($mbox_data['HIGHESTMODSEQ'])
+            && $index['modseq'] == $mbox_data['HIGHESTMODSEQ']
+        ) {
+            return true;
+        }
+
+        // Check UIDNEXT
+        if ($index['uidnext'] != $mbox_data['UIDNEXT']) {
+            unset($this->icache[$mailbox][$is_thread ? 'thread' : 'index']);
+            return false;
+        }
+
+        // @TODO: find better validity check for threaded index
+        if ($is_thread) {
+            // check messages number...
+            if (!$this->skip_deleted && $mbox_data['EXISTS'] != @max(array_keys($index['depth']))) {
+                return false;
+            }
+            return true;
+        }
+
+        // The rest of checks, more expensive
+        if (!empty($this->skip_deleted)) {
+            // compare counts if available
+            if ($mbox_data['COUNT_UNDELETED'] != null
+                && $mbox_data['COUNT_UNDELETED'] != count($index['uid'])) {
+                return false;
+            }
+            // compare UID sets
+            if ($mbox_data['ALL_UNDELETED'] != null) {
+                $uids_new = rcube_imap_generic::uncompressMessageSet($mbox_data['ALL_UNDELETED']);
+                $uids_old = $index['uid'];
+
+                if (count($uids_new) != count($uids_old)) {
+                    return false;
+                }
+
+                sort($uids_new, SORT_NUMERIC);
+                sort($uids_old, SORT_NUMERIC);
+
+                if ($uids_old != $uids_new)
+                    return false;
+            }
+            else {
+                // get all undeleted messages excluding cached UIDs
+                $ids = $this->imap->search_once($mailbox, 'ALL UNDELETED NOT UID '.
+                    rcube_imap_generic::compressMessageSet($index['uid']));
+
+                if (!empty($ids)) {
+                    return false;
+                }
+            }
+        }
+        else {
+            // check messages number...
+            if ($mbox_data['EXISTS'] != max($index['seq'])) {
+                return false;
+            }
+            // ... and max UID
+            if (max($index['uid']) != $this->imap->id2uid($mbox_data['EXISTS'], $mailbox, true)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+
+    /**
+     * Synchronizes the mailbox.
+     *
+     * @param string $mailbox Folder name
+     */
+    function synchronize($mailbox)
+    {
+        // RFC4549: Synchronization Operations for Disconnected IMAP4 Clients
+        // RFC4551: IMAP Extension for Conditional STORE Operation
+        //          or Quick Flag Changes Resynchronization
+        // RFC5162: IMAP Extensions for Quick Mailbox Resynchronization
+
+        // @TODO: synchronize with other methods?
+        $qresync   = $this->imap->get_capability('QRESYNC');
+        $condstore = $qresync ? true : $this->imap->get_capability('CONDSTORE');
+
+        if (!$qresync && !$condstore) {
+            return;
+        }
+
+        // Get stored index
+        $index = $this->get_index_row($mailbox);
+
+        // database is empty
+        if (empty($index)) {
+            // set the flag that DB was already queried for index
+            // this way we'll be able to skip one SELECT in get_index()
+            $this->icache[$mailbox]['index_queried'] = true;
+            return;
+        }
+
+        $this->icache[$mailbox]['index'] = $index;
+
+        // no last HIGHESTMODSEQ value
+        if (empty($index['modseq'])) {
+            return;
+        }
+
+        // NOTE: make sure the mailbox isn't selected, before
+        // enabling QRESYNC and invoking SELECT
+        if ($this->imap->conn->selected !== null) {
+            $this->imap->conn->close();
+        }
+
+        // Enable QRESYNC
+        $res = $this->imap->conn->enable($qresync ? 'QRESYNC' : 'CONDSTORE');
+        if (!is_array($res)) {
+            return;
+        }
+
+        // Get mailbox data (UIDVALIDITY, HIGHESTMODSEQ, counters, etc.)
+        $mbox_data = $this->imap->mailbox_data($mailbox);
+
+        if (empty($mbox_data)) {
+             return;
+        }
+
+        // Check UIDVALIDITY
+        if ($index['validity'] != $mbox_data['UIDVALIDITY']) {
+            $this->clear($mailbox);
+            return;
+        }
+
+        // QRESYNC not supported on specified mailbox
+        if (!empty($mbox_data['NOMODSEQ']) || empty($mbox_data['HIGHESTMODSEQ'])) {
+            return;
+        }
+
+        // Nothing new
+        if ($mbox_data['HIGHESTMODSEQ'] == $index['modseq']) {
+            return;
+        }
+
+        // Get known uids
+        $uids = array();
+        $sql_result = $this->db->query(
+            "SELECT uid"
+            ." FROM ".get_table_name('cache_messages')
+            ." WHERE user_id = ?"
+                ." AND mailbox = ?",
+            $this->userid, $mailbox);
+
+        while ($sql_arr = $this->db->fetch_assoc($sql_result)) {
+          $uids[] = $sql_arr['uid'];
+        }
+
+        // No messages in database, nothing to sync
+        if (empty($uids)) {
+            return;
+        }
+
+        // Get modified flags and vanished messages
+        // UID FETCH 1:* (FLAGS) (CHANGEDSINCE 0123456789 VANISHED)
+        $result = $this->imap->conn->fetch($mailbox,
+            !empty($uids) ? $uids : '1:*', true, array('FLAGS'),
+            $index['modseq'], $qresync);
+
+        $invalidated = false;
+
+        if (!empty($result)) {
+            foreach ($result as $id => $msg) {
+                $uid = $msg->uid;
+                // Remove deleted message
+                if ($this->skip_deleted && !empty($msg->flags['DELETED'])) {
+                    $this->remove_message($mailbox, $uid);
+
+                    if (!$invalidated) {
+                        $invalidated = true;
+                        // Invalidate thread indexes (?)
+                        $this->remove_thread($mailbox);
+                        // Invalidate index
+                        $index['valid'] = false;
+                    }
+                    continue;
+                }
+
+                $flags = 0;
+                if (!empty($msg->flags)) {
+                    foreach ($this->flags as $idx => $flag)
+                        if (!empty($msg->flags[$flag]))
+                            $flags += $idx;
+                }
+
+                $this->db->query(
+                    "UPDATE ".get_table_name('cache_messages')
+                    ." SET flags = ?, changed = ".$this->db->now()
+                    ." WHERE user_id = ?"
+                        ." AND mailbox = ?"
+                        ." AND uid = ?"
+                        ." AND flags <> ?",
+                    $flags, $this->userid, $mailbox, $uid, $flags);
+            }
+        }
+
+        // Get VANISHED
+        if ($qresync) {
+            $mbox_data = $this->imap->mailbox_data($mailbox);
+
+            // Removed messages
+            if (!empty($mbox_data['VANISHED'])) {
+                $uids = rcube_imap_generic::uncompressMessageSet($mbox_data['VANISHED']);
+                if (!empty($uids)) {
+                    // remove messages from database
+                    $this->remove_message($mailbox, $uids);
+
+                    // Invalidate thread indexes (?)
+                    $this->remove_thread($mailbox);
+                    // Invalidate index
+                    $index['valid'] = false;
+                }
+            }
+        }
+
+        $sort_field = $index['sort_field'];
+        $sort_order = $index['sort_order'];
+        $exists     = true;
+
+        // Validate index
+        if (!$this->validate($mailbox, $index, $exists)) {
+            // Update index
+            $data = $this->get_index_data($mailbox, $sort_field, $sort_order, $mbox_data);
+        }
+        else {
+            $data = array_combine($index['seq'], $index['uid']);
+        }
+
+        // update index and/or HIGHESTMODSEQ value
+        $this->add_index_row($mailbox, $sort_field, $sort_order, $data, $mbox_data, $exists);
+
+        // update internal cache for get_index()
+        $this->icache[$mailbox]['index']['result'] = $data;
+    }
+
+
+    /**
+     * Converts cache row into message object.
+     *
+     * @param array $sql_arr Message row data
+     *
+     * @return rcube_mail_header Message object
+     */
+    private function build_message($sql_arr)
+    {
+        $message = $this->db->decode(unserialize($sql_arr['data']));
+
+        if ($message) {
+            $message->flags = array();
+            foreach ($this->flags as $idx => $flag)
+                if (($sql_arr['flags'] & $idx) == $idx)
+                    $message->flags[$flag] = true;
+        }
+
+        return $message;
+    }
+
+
+    /**
+     * Creates 'depth' and 'children' arrays from stored thread 'tree' data.
+     */
+    private function build_thread_data($data, &$depth, &$children, $level = 0)
+    {
+        foreach ((array)$data as $key => $val) {
+            $children[$key] = !empty($val);
+            $depth[$key] = $level;
+            if (!empty($val))
+                $this->build_thread_data($val, $depth, $children, $level + 1);
+        }
+    }
+
+
+    /**
+     * Saves message stored in internal cache
+     */
+    private function save_icache()
+    {
+        // Save current message from internal cache
+        if ($message = $this->icache['message']) {
+            // clean up some object's data
+            $object = $this->message_object_prepare($message['object']);
+
+            // calculate current md5 sum
+            $md5sum = md5(serialize($object));
+
+            if ($message['md5sum'] != $md5sum) {
+                $this->add_message($message['mailbox'], $object, !$message['exists']);
+            }
+
+            $this->icache['message']['md5sum'] = $md5sum;
+        }
+    }
+
+
+    /**
+     * Prepares message object to be stored in database.
+     */
+    private function message_object_prepare($msg)
+    {
+        // Remove body too big (>25kB)
+        if ($msg->body && strlen($msg->body) > 25 * 1024) {
+            unset($msg->body);
+        }
+
+        // Fix mimetype which might be broken by some code when message is displayed
+        // Another solution would be to use object's copy in rcube_message class
+        // to prevent related issues, however I'm not sure which is better
+        if ($msg->mimetype) {
+            list($msg->ctype_primary, $msg->ctype_secondary) = explode('/', $msg->mimetype);
+        }
+
+        if (is_array($msg->structure->parts)) {
+            foreach ($msg->structure->parts as $idx => $part) {
+                $msg->structure->parts[$idx] = $this->message_object_prepare($part);
+            }
+        }
+
+        return $msg;
+    }
+
+
+    /**
+     * Fetches index data from IMAP server
+     */
+    private function get_index_data($mailbox, $sort_field, $sort_order, $mbox_data = array())
+    {
+        $data = array();
+
+        if (empty($mbox_data)) {
+            $mbox_data = $this->imap->mailbox_data($mailbox);
+        }
+
+        // Prevent infinite loop.
+        // It happens when rcube_imap::message_index_direct() is called.
+        // There id2uid() is called which will again call get_index() and so on.
+        if (!$sort_field && !$this->skip_deleted)
+            $this->icache['pending_index_update'] = true;
+
+        if ($mbox_data['EXISTS']) {
+            // fetch sorted sequence numbers
+            $data_seq = $this->imap->message_index_direct($mailbox, $sort_field, $sort_order);
+            // fetch UIDs
+            if (!empty($data_seq)) {
+                // Seek in internal cache
+                if (array_key_exists('index', (array)$this->icache[$mailbox])
+                    && array_key_exists('result', (array)$this->icache[$mailbox]['index'])
+                )
+                    $data_uid = $this->icache[$mailbox]['index']['result'];
+                else
+                    $data_uid = $this->imap->conn->fetchUIDs($mailbox, $data_seq);
+
+                // build index
+                if (!empty($data_uid)) {
+                    foreach ($data_seq as $seq)
+                        if ($uid = $data_uid[$seq])
+                            $data[$seq] = $uid;
+                }
+            }
+        }
+
+        // Reset internal flags
+        $this->icache['pending_index_update'] = false;
+
+        return $data;
+    }
+}
index 7ae59bbd097a9aa7122a1ceeaa09de13dfd92b55..4c002fc14d5ef0a78ccbd2331cf2aaa62a493189 100644 (file)
@@ -6,6 +6,7 @@
  |                                                                       |
  | This file is part of the Roundcube Webmail client                     |
  | Copyright (C) 2005-2010, The Roundcube Dev Team                       |
  |                                                                       |
  | This file is part of the Roundcube Webmail client                     |
  | Copyright (C) 2005-2010, The Roundcube Dev Team                       |
+ | Copyright (C) 2011, Kolab Systems AG                                  |
  | Licensed under the GNU GPL                                            |
  |                                                                       |
  | PURPOSE:                                                              |
  | Licensed under the GNU GPL                                            |
  |                                                                       |
  | PURPOSE:                                                              |
@@ -21,7 +22,7 @@
  | Author: Ryo Chijiiwa <Ryo@IlohaMail.org>                              |
  +-----------------------------------------------------------------------+
 
  | Author: Ryo Chijiiwa <Ryo@IlohaMail.org>                              |
  +-----------------------------------------------------------------------+
 
- $Id: rcube_imap_generic.php 5213 2011-09-13 08:09:50Z alec $
+ $Id: rcube_imap_generic.php 5402 2011-11-09 10:03:54Z alec $
 
 */
 
 
 */
 
@@ -48,23 +49,14 @@ class rcube_mail_header
     public $encoding;
     public $charset;
     public $ctype;
     public $encoding;
     public $charset;
     public $ctype;
-    public $flags;
     public $timestamp;
     public $timestamp;
-    public $body_structure;
+    public $bodystructure;
     public $internaldate;
     public $references;
     public $priority;
     public $mdn_to;
     public $internaldate;
     public $references;
     public $priority;
     public $mdn_to;
-    public $mdn_sent = false;
-    public $seen = false;
-    public $deleted = false;
-    public $answered = false;
-    public $forwarded = false;
-    public $flagged = false;
-    public $has_children = false;
-    public $depth = 0;
-    public $unread_children = 0;
     public $others = array();
     public $others = array();
+    public $flags = array();
 }
 
 // For backward compatibility with cached messages (#1486602)
 }
 
 // For backward compatibility with cached messages (#1486602)
@@ -84,6 +76,7 @@ class rcube_imap_generic
     public $errornum;
     public $result;
     public $resultcode;
     public $errornum;
     public $result;
     public $resultcode;
+    public $selected;
     public $data = array();
     public $flags = array(
         'SEEN'     => '\\Seen',
     public $data = array();
     public $flags = array(
         'SEEN'     => '\\Seen',
@@ -96,7 +89,6 @@ class rcube_imap_generic
         '*'        => '\\*',
     );
 
         '*'        => '\\*',
     );
 
-    private $selected;
     private $fp;
     private $host;
     private $logged = false;
     private $fp;
     private $host;
     private $logged = false;
@@ -235,14 +227,14 @@ class rcube_imap_generic
         return $line;
     }
 
         return $line;
     }
 
-    function multLine($line, $escape=false)
+    function multLine($line, $escape = false)
     {
         $line = rtrim($line);
     {
         $line = rtrim($line);
-        if (preg_match('/\{[0-9]+\}$/', $line)) {
-            $out = '';
+        if (preg_match('/\{([0-9]+)\}$/', $line, $m)) {
+            $out   = '';
+            $str   = substr($line, 0, -strlen($m[0]));
+            $bytes = $m[1];
 
 
-            preg_match_all('/(.*)\{([0-9]+)\}$/', $line, $a);
-            $bytes = $a[2][0];
             while (strlen($out) < $bytes) {
                 $line = $this->readBytes($bytes);
                 if ($line === NULL)
             while (strlen($out) < $bytes) {
                 $line = $this->readBytes($bytes);
                 if ($line === NULL)
@@ -250,7 +242,7 @@ class rcube_imap_generic
                 $out .= $line;
             }
 
                 $out .= $line;
             }
 
-            $line = $a[1][0] . ($escape ? $this->escape($out) : $out);
+            $line = $str . ($escape ? $this->escape($out) : $out);
         }
 
         return $line;
         }
 
         return $line;
@@ -318,6 +310,10 @@ class rcube_imap_generic
                 }
                 else {
                     $this->resultcode = null;
                 }
                 else {
                     $this->resultcode = null;
+                    // parse response for [APPENDUID 1204196876 3456]
+                    if (preg_match("/^\[APPENDUID [0-9]+ ([0-9,:*]+)\]/i", $str, $m)) {
+                        $this->data['APPENDUID'] = $m[1];
+                    }
                 }
                 $this->result = $str;
 
                 }
                 $this->result = $str;
 
@@ -680,8 +676,8 @@ class rcube_imap_generic
             $this->prefs = $options;
         }
         // set auth method
             $this->prefs = $options;
         }
         // set auth method
-        if (!empty($this->prefs['auth_method'])) {
-            $auth_method = strtoupper($this->prefs['auth_method']);
+        if (!empty($this->prefs['auth_type'])) {
+            $auth_method = strtoupper($this->prefs['auth_type']);
         } else {
             $auth_method = 'CHECK';
         }
         } else {
             $auth_method = 'CHECK';
         }
@@ -691,7 +687,7 @@ class rcube_imap_generic
         // initialize connection
         $this->error    = '';
         $this->errornum = self::ERROR_OK;
         // initialize connection
         $this->error    = '';
         $this->errornum = self::ERROR_OK;
-        $this->selected = '';
+        $this->selected = null;
         $this->user     = $user;
         $this->host     = $host;
         $this->logged   = false;
         $this->user     = $user;
         $this->host     = $host;
         $this->logged   = false;
@@ -877,18 +873,18 @@ class rcube_imap_generic
     /**
      * Executes SELECT command (if mailbox is already not in selected state)
      *
     /**
      * Executes SELECT command (if mailbox is already not in selected state)
      *
-     * @param string $mailbox Mailbox name
+     * @param string $mailbox      Mailbox name
+     * @param array  $qresync_data QRESYNC data (RFC5162)
      *
      * @return boolean True on success, false on error
      *
      * @return boolean True on success, false on error
-     * @access public
      */
      */
-    function select($mailbox)
+    function select($mailbox, $qresync_data = null)
     {
         if (!strlen($mailbox)) {
             return false;
         }
 
     {
         if (!strlen($mailbox)) {
             return false;
         }
 
-        if ($this->selected == $mailbox) {
+        if ($this->selected === $mailbox) {
             return true;
         }
 /*
             return true;
         }
 /*
@@ -901,7 +897,21 @@ class rcube_imap_generic
             }
         }
 */
             }
         }
 */
-        list($code, $response) = $this->execute('SELECT', array($this->escape($mailbox)));
+        $params = array($this->escape($mailbox));
+
+        // QRESYNC data items
+        //    0. the last known UIDVALIDITY,
+        //    1. the last known modification sequence,
+        //    2. the optional set of known UIDs, and
+        //    3. an optional parenthesized list of known sequence ranges and their
+        //       corresponding UIDs.
+        if (!empty($qresync_data)) {
+            if (!empty($qresync_data[2]))
+                $qresync_data[2] = self::compressMessageSet($qresync_data[2]);
+            $params[] = array('QRESYNC', $qresync_data);
+        }
+
+        list($code, $response) = $this->execute('SELECT', $params);
 
         if ($code == self::ERROR_OK) {
             $response = explode("\r\n", $response);
 
         if ($code == self::ERROR_OK) {
             $response = explode("\r\n", $response);
@@ -909,11 +919,39 @@ class rcube_imap_generic
                 if (preg_match('/^\* ([0-9]+) (EXISTS|RECENT)$/i', $line, $m)) {
                     $this->data[strtoupper($m[2])] = (int) $m[1];
                 }
                 if (preg_match('/^\* ([0-9]+) (EXISTS|RECENT)$/i', $line, $m)) {
                     $this->data[strtoupper($m[2])] = (int) $m[1];
                 }
-                else if (preg_match('/^\* OK \[(UIDNEXT|UIDVALIDITY|UNSEEN) ([0-9]+)\]/i', $line, $match)) {
-                    $this->data[strtoupper($match[1])] = (int) $match[2];
+                else if (preg_match('/^\* OK \[/i', $line, $match)) {
+                    $line = substr($line, 6);
+                    if (preg_match('/^(UIDNEXT|UIDVALIDITY|UNSEEN) ([0-9]+)/i', $line, $match)) {
+                        $this->data[strtoupper($match[1])] = (int) $match[2];
+                    }
+                    else if (preg_match('/^(HIGHESTMODSEQ) ([0-9]+)/i', $line, $match)) {
+                        $this->data[strtoupper($match[1])] = (string) $match[2];
+                    }
+                    else if (preg_match('/^(NOMODSEQ)/i', $line, $match)) {
+                        $this->data[strtoupper($match[1])] = true;
+                    }
+                    else if (preg_match('/^PERMANENTFLAGS \(([^\)]+)\)/iU', $line, $match)) {
+                        $this->data['PERMANENTFLAGS'] = explode(' ', $match[1]);
+                    }
+                }
+                // QRESYNC FETCH response (RFC5162)
+                else if (preg_match('/^\* ([0-9+]) FETCH/i', $line, $match)) {
+                    $line       = substr($line, strlen($match[0]));
+                    $fetch_data = $this->tokenizeResponse($line, 1);
+                    $data       = array('id' => $match[1]);
+
+                    for ($i=0, $size=count($fetch_data); $i<$size; $i+=2) {
+                        $data[strtolower($fetch_data[$i])] = $fetch_data[$i+1];
+                    }
+
+                    $this->data['QRESYNC'][$data['uid']] = $data;
                 }
                 }
-                else if (preg_match('/^\* OK \[PERMANENTFLAGS \(([^\)]+)\)\]/iU', $line, $match)) {
-                    $this->data['PERMANENTFLAGS'] = explode(' ', $match[1]);
+                // QRESYNC VANISHED response (RFC5162)
+                else if (preg_match('/^\* VANISHED [()EARLIER]*/i', $line, $match)) {
+                    $line   = substr($line, strlen($match[0]));
+                    $v_data = $this->tokenizeResponse($line, 1);
+
+                    $this->data['VANISHED'] = $v_data;
                 }
             }
 
                 }
             }
 
@@ -935,7 +973,6 @@ class rcube_imap_generic
      *                        in RFC3501: UIDNEXT, UIDVALIDITY, RECENT
      *
      * @return array Status item-value hash
      *                        in RFC3501: UIDNEXT, UIDVALIDITY, RECENT
      *
      * @return array Status item-value hash
-     * @access public
      * @since 0.5-beta
      */
     function status($mailbox, $items=array())
      * @since 0.5-beta
      */
     function status($mailbox, $items=array())
@@ -971,7 +1008,7 @@ class rcube_imap_generic
             }
 
             for ($i=0, $len=count($items); $i<$len; $i += 2) {
             }
 
             for ($i=0, $len=count($items); $i<$len; $i += 2) {
-                $result[$items[$i]] = (int) $items[$i+1];
+                $result[$items[$i]] = $items[$i+1];
             }
 
             $this->data['STATUS:'.$mailbox] = $result;
             }
 
             $this->data['STATUS:'.$mailbox] = $result;
@@ -989,7 +1026,6 @@ class rcube_imap_generic
      * @param string $messages Message UIDs to expunge
      *
      * @return boolean True on success, False on error
      * @param string $messages Message UIDs to expunge
      *
      * @return boolean True on success, False on error
-     * @access public
      */
     function expunge($mailbox, $messages=NULL)
     {
      */
     function expunge($mailbox, $messages=NULL)
     {
@@ -1011,7 +1047,7 @@ class rcube_imap_generic
             $result = $this->execute('EXPUNGE', null, self::COMMAND_NORESPONSE);
 
         if ($result == self::ERROR_OK) {
             $result = $this->execute('EXPUNGE', null, self::COMMAND_NORESPONSE);
 
         if ($result == self::ERROR_OK) {
-            $this->selected = ''; // state has changed, need to reselect
+            $this->selected = null; // state has changed, need to reselect
             return true;
         }
 
             return true;
         }
 
@@ -1022,7 +1058,6 @@ class rcube_imap_generic
      * Executes CLOSE command
      *
      * @return boolean True on success, False on error
      * Executes CLOSE command
      *
      * @return boolean True on success, False on error
-     * @access public
      * @since 0.5
      */
     function close()
      * @since 0.5
      */
     function close()
@@ -1030,7 +1065,7 @@ class rcube_imap_generic
         $result = $this->execute('CLOSE', NULL, self::COMMAND_NORESPONSE);
 
         if ($result == self::ERROR_OK) {
         $result = $this->execute('CLOSE', NULL, self::COMMAND_NORESPONSE);
 
         if ($result == self::ERROR_OK) {
-            $this->selected = '';
+            $this->selected = null;
             return true;
         }
 
             return true;
         }
 
@@ -1043,7 +1078,6 @@ class rcube_imap_generic
      * @param string $mailbox Mailbox name
      *
      * @return boolean True on success, False on error
      * @param string $mailbox Mailbox name
      *
      * @return boolean True on success, False on error
-     * @access public
      */
     function subscribe($mailbox)
     {
      */
     function subscribe($mailbox)
     {
@@ -1059,7 +1093,6 @@ class rcube_imap_generic
      * @param string $mailbox Mailbox name
      *
      * @return boolean True on success, False on error
      * @param string $mailbox Mailbox name
      *
      * @return boolean True on success, False on error
-     * @access public
      */
     function unsubscribe($mailbox)
     {
      */
     function unsubscribe($mailbox)
     {
@@ -1075,7 +1108,6 @@ class rcube_imap_generic
      * @param string $mailbox Mailbox name
      *
      * @return boolean True on success, False on error
      * @param string $mailbox Mailbox name
      *
      * @return boolean True on success, False on error
-     * @access public
      */
     function deleteFolder($mailbox)
     {
      */
     function deleteFolder($mailbox)
     {
@@ -1091,7 +1123,6 @@ class rcube_imap_generic
      * @param string $mailbox Mailbox name
      *
      * @return boolean True on success, False on error
      * @param string $mailbox Mailbox name
      *
      * @return boolean True on success, False on error
-     * @access public
      */
     function clearFolder($mailbox)
     {
      */
     function clearFolder($mailbox)
     {
@@ -1101,7 +1132,7 @@ class rcube_imap_generic
         }
 
         if ($res) {
         }
 
         if ($res) {
-            if ($this->selected == $mailbox)
+            if ($this->selected === $mailbox)
                 $res = $this->close();
             else
                 $res = $this->expunge($mailbox);
                 $res = $this->close();
             else
                 $res = $this->expunge($mailbox);
@@ -1116,15 +1147,14 @@ class rcube_imap_generic
      * @param string $mailbox Mailbox name
      *
      * @return int Number of messages, False on error
      * @param string $mailbox Mailbox name
      *
      * @return int Number of messages, False on error
-     * @access public
      */
     function countMessages($mailbox, $refresh = false)
     {
         if ($refresh) {
      */
     function countMessages($mailbox, $refresh = false)
     {
         if ($refresh) {
-            $this->selected = '';
+            $this->selected = null;
         }
 
         }
 
-        if ($this->selected == $mailbox) {
+        if ($this->selected === $mailbox) {
             return $this->data['EXISTS'];
         }
 
             return $this->data['EXISTS'];
         }
 
@@ -1149,7 +1179,6 @@ class rcube_imap_generic
      * @param string $mailbox Mailbox name
      *
      * @return int Number of messages, False on error
      * @param string $mailbox Mailbox name
      *
      * @return int Number of messages, False on error
-     * @access public
      */
     function countRecent($mailbox)
     {
      */
     function countRecent($mailbox)
     {
@@ -1159,7 +1188,7 @@ class rcube_imap_generic
 
         $this->select($mailbox);
 
 
         $this->select($mailbox);
 
-        if ($this->selected == $mailbox) {
+        if ($this->selected === $mailbox) {
             return $this->data['RECENT'];
         }
 
             return $this->data['RECENT'];
         }
 
@@ -1172,7 +1201,6 @@ class rcube_imap_generic
      * @param string $mailbox Mailbox name
      *
      * @return int Number of messages, False on error
      * @param string $mailbox Mailbox name
      *
      * @return int Number of messages, False on error
-     * @access public
      */
     function countUnseen($mailbox)
     {
      */
     function countUnseen($mailbox)
     {
@@ -1203,7 +1231,6 @@ class rcube_imap_generic
      * @param array $items Client identification information key/value hash
      *
      * @return array Server identification information key/value hash
      * @param array $items Client identification information key/value hash
      *
      * @return array Server identification information key/value hash
-     * @access public
      * @since 0.6
      */
     function id($items=array())
      * @since 0.6
      */
     function id($items=array())
@@ -1235,6 +1262,37 @@ class rcube_imap_generic
         return false;
     }
 
         return false;
     }
 
+    /**
+     * Executes ENABLE command (RFC5161)
+     *
+     * @param mixed $extension Extension name to enable (or array of names)
+     *
+     * @return array|bool List of enabled extensions, False on error
+     * @since 0.6
+     */
+    function enable($extension)
+    {
+        if (empty($extension))
+            return false;
+
+        if (!$this->hasCapability('ENABLE'))
+            return false;
+
+        if (!is_array($extension))
+            $extension = array($extension);
+
+        list($code, $response) = $this->execute('ENABLE', $extension);
+
+        if ($code == self::ERROR_OK && preg_match('/\* ENABLED /i', $response)) {
+            $response = substr($response, 10); // remove prefix "* ENABLED "
+            $result   = (array) $this->tokenizeResponse($response);
+
+            return $result;
+        }
+
+        return false;
+    }
+
     function sort($mailbox, $field, $add='', $is_uid=FALSE, $encoding = 'US-ASCII')
     {
         $field = strtoupper($field);
     function sort($mailbox, $field, $add='', $is_uid=FALSE, $encoding = 'US-ASCII')
     {
         $field = strtoupper($field);
@@ -1472,7 +1530,6 @@ class rcube_imap_generic
      * @param int    $uid     Message unique identifier (UID)
      *
      * @return int Message sequence identifier
      * @param int    $uid     Message unique identifier (UID)
      *
      * @return int Message sequence identifier
-     * @access public
      */
     function UID2ID($mailbox, $uid)
     {
      */
     function UID2ID($mailbox, $uid)
     {
@@ -1492,12 +1549,11 @@ class rcube_imap_generic
      * @param int    $uid     Message sequence identifier
      *
      * @return int Message unique identifier
      * @param int    $uid     Message sequence identifier
      *
      * @return int Message unique identifier
-     * @access public
      */
     function ID2UID($mailbox, $id)
     {
         if (empty($id) || $id < 0) {
      */
     function ID2UID($mailbox, $id)
     {
         if (empty($id) || $id < 0) {
-            return     null;
+            return null;
         }
 
         if (!$this->select($mailbox)) {
         }
 
         if (!$this->select($mailbox)) {
@@ -1515,47 +1571,59 @@ class rcube_imap_generic
 
     function fetchUIDs($mailbox, $message_set=null)
     {
 
     function fetchUIDs($mailbox, $message_set=null)
     {
-        if (is_array($message_set))
-            $message_set = join(',', $message_set);
-        else if (empty($message_set))
+        if (empty($message_set))
             $message_set = '1:*';
 
         return $this->fetchHeaderIndex($mailbox, $message_set, 'UID', false);
     }
 
             $message_set = '1:*';
 
         return $this->fetchHeaderIndex($mailbox, $message_set, 'UID', false);
     }
 
-    function fetchHeaders($mailbox, $message_set, $uidfetch=false, $bodystr=false, $add='')
+    /**
+     * FETCH command (RFC3501)
+     *
+     * @param string $mailbox     Mailbox name
+     * @param mixed  $message_set Message(s) sequence identifier(s) or UID(s)
+     * @param bool   $is_uid      True if $message_set contains UIDs
+     * @param array  $query_items FETCH command data items
+     * @param string $mod_seq     Modification sequence for CHANGEDSINCE (RFC4551) query
+     * @param bool   $vanished    Enables VANISHED parameter (RFC5162) for CHANGEDSINCE query
+     *
+     * @return array List of rcube_mail_header elements, False on error
+     * @since 0.6
+     */
+    function fetch($mailbox, $message_set, $is_uid = false, $query_items = array(),
+        $mod_seq = null, $vanished = false)
     {
     {
-        $result = array();
-
         if (!$this->select($mailbox)) {
             return false;
         }
 
         $message_set = $this->compressMessageSet($message_set);
         if (!$this->select($mailbox)) {
             return false;
         }
 
         $message_set = $this->compressMessageSet($message_set);
+        $result      = array();
 
 
-        if ($add)
-            $add = ' '.trim($add);
-
-        /* FETCH uid, size, flags and headers */
         $key      = $this->nextTag();
         $key      = $this->nextTag();
-        $request  = $key . ($uidfetch ? ' UID' : '') . " FETCH $message_set ";
-        $request .= "(UID RFC822.SIZE FLAGS INTERNALDATE ";
-        if ($bodystr)
-            $request .= "BODYSTRUCTURE ";
-        $request .= "BODY.PEEK[HEADER.FIELDS (DATE FROM TO SUBJECT CONTENT-TYPE ";
-        $request .= "CC REPLY-TO LIST-POST DISPOSITION-NOTIFICATION-TO".$add.")])";
+        $request  = $key . ($is_uid ? ' UID' : '') . " FETCH $message_set ";
+        $request .= "(" . implode(' ', $query_items) . ")";
+
+        if ($mod_seq !== null && $this->hasCapability('CONDSTORE')) {
+            $request .= " (CHANGEDSINCE $mod_seq" . ($vanished ? " VANISHED" : '') .")";
+        }
 
         if (!$this->putLine($request)) {
             $this->setError(self::ERROR_COMMAND, "Unable to send command: $request");
             return false;
         }
 
         if (!$this->putLine($request)) {
             $this->setError(self::ERROR_COMMAND, "Unable to send command: $request");
             return false;
         }
+
         do {
             $line = $this->readLine(4096);
         do {
             $line = $this->readLine(4096);
-            $line = $this->multLine($line);
 
             if (!$line)
                 break;
 
 
             if (!$line)
                 break;
 
+            // Sample reply line:
+            // * 321 FETCH (UID 2417 RFC822.SIZE 2730 FLAGS (\Seen)
+            // INTERNALDATE "16-Nov-2008 21:08:46 +0100" BODYSTRUCTURE (...)
+            // BODY[HEADER.FIELDS ...
+
             if (preg_match('/^\* ([0-9]+) FETCH/', $line, $m)) {
                 $id = intval($m[1]);
 
             if (preg_match('/^\* ([0-9]+) FETCH/', $line, $m)) {
                 $id = intval($m[1]);
 
@@ -1565,101 +1633,91 @@ class rcube_imap_generic
                 $result[$id]->messageID = 'mid:' . $id;
 
                 $lines = array();
                 $result[$id]->messageID = 'mid:' . $id;
 
                 $lines = array();
-                $ln = 0;
-
-                // Sample reply line:
-                // * 321 FETCH (UID 2417 RFC822.SIZE 2730 FLAGS (\Seen)
-                // INTERNALDATE "16-Nov-2008 21:08:46 +0100" BODYSTRUCTURE (...)
-                // BODY[HEADER.FIELDS ...
+                $line  = substr($line, strlen($m[0]) + 2);
+                $ln    = 0;
 
 
-                if (preg_match('/^\* [0-9]+ FETCH \((.*) BODY/sU', $line, $matches)) {
-                    $str = $matches[1];
+                // get complete entry
+                while (preg_match('/\{([0-9]+)\}\r\n$/', $line, $m)) {
+                    $bytes = $m[1];
+                    $out   = '';
 
 
-                    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;
-                        }
+                    while (strlen($out) < $bytes) {
+                        $out = $this->readBytes($bytes);
+                        if ($out === NULL)
+                            break;
+                        $line .= $out;
                     }
 
                     }
 
-                    // BODYSTRUCTURE
-                    if ($bodystr) {
-                        while (!preg_match('/ BODYSTRUCTURE (.*) BODY\[HEADER.FIELDS/sU', $line, $m)) {
-                            $line2 = $this->readLine(1024);
-                            $line .= $this->multLine($line2, true);
-                        }
-                        $result[$id]->body_structure = $m[1];
+                    $str = $this->readLine(4096);
+                    if ($str === false)
+                        break;
+
+                    $line .= $str;
+                }
+
+                // Tokenize response and assign to object properties
+                while (list($name, $value) = $this->tokenizeResponse($line, 2)) {
+                    if ($name == 'UID') {
+                        $result[$id]->uid = intval($value);
+                    }
+                    else if ($name == 'RFC822.SIZE') {
+                        $result[$id]->size = intval($value);
                     }
                     }
+                    else if ($name == 'RFC822.TEXT') {
+                        $result[$id]->body = $value;
+                    }
+                    else if ($name == 'INTERNALDATE') {
+                        $result[$id]->internaldate = $value;
+                        $result[$id]->date         = $value;
+                        $result[$id]->timestamp    = $this->StrToTime($value);
+                    }
+                    else if ($name == 'FLAGS') {
+                        if (!empty($value)) {
+                            foreach ((array)$value as $flag) {
+                                $flag = str_replace(array('$', '\\'), '', $flag);
+                                $flag = strtoupper($flag);
 
 
-                    // the rest of the result
-                    if (preg_match('/ BODY\[HEADER.FIELDS \(.*?\)\]\s*(.*)$/s', $line, $m)) {
-                        $reslines = explode("\n", trim($m[1], '"'));
-                        // re-parse (see below)
-                        foreach ($reslines as $resln) {
-                            if (ord($resln[0])<=32) {
-                                $lines[$ln] .= (empty($lines[$ln])?'':"\n").trim($resln);
-                            } else {
-                                $lines[++$ln] = trim($resln);
+                                $result[$id]->flags[$flag] = true;
                             }
                         }
                     }
                             }
                         }
                     }
-                }
-
-                // Start parsing headers.  The problem is, some header "lines" take up multiple lines.
-                // So, we'll read ahead, and if the one we're reading now is a valid header, we'll
-                // process the previous line.  Otherwise, we'll keep adding the strings until we come
-                // to the next valid header line.
-
-                do {
-                    $line = rtrim($this->readLine(300), "\r\n");
-
-                    // The preg_match below works around communigate imap, which outputs " UID <number>)".
-                    // Without this, the while statement continues on and gets the "FH0 OK completed" message.
-                    // If this loop gets the ending message, then the outer loop does not receive it from radline on line 1249.
-                    // This in causes the if statement on line 1278 to never be true, which causes the headers to end up missing
-                    // If the if statement was changed to pick up the fh0 from this loop, then it causes the outer loop to spin
-                    // An alternative might be:
-                    // if (!preg_match("/:/",$line) && preg_match("/\)$/",$line)) break;
-                    // however, unsure how well this would work with all imap clients.
-                    if (preg_match("/^\s*UID [0-9]+\)$/", $line)) {
-                        break;
+                    else if ($name == 'MODSEQ') {
+                        $result[$id]->modseq = $value[0];
                     }
                     }
-
-                    // handle FLAGS reply after headers (AOL, Zimbra?)
-                    if (preg_match('/\s+FLAGS \((.*)\)\)$/', $line, $matches)) {
-                        $flags_a = $this->tokenizeResponse($matches[1]);
-                        break;
+                    else if ($name == 'ENVELOPE') {
+                        $result[$id]->envelope = $value;
                     }
                     }
-
-                    if (ord($line[0])<=32) {
-                        $lines[$ln] .= (empty($lines[$ln])?'':"\n").trim($line);
-                    } else {
-                        $lines[++$ln] = trim($line);
+                    else if ($name == 'BODYSTRUCTURE' || ($name == 'BODY' && count($value) > 2)) {
+                        if (!is_array($value[0]) && (strtolower($value[0]) == 'message' && strtolower($value[1]) == 'rfc822')) {
+                            $value = array($value);
+                        }
+                        $result[$id]->bodystructure = $value;
                     }
                     }
-                // patch from "Maksim Rubis" <siburny@hotmail.com>
-                } while ($line[0] != ')' && !$this->startsWith($line, $key, true));
-
-                if (strncmp($line, $key, strlen($key))) {
-                    // process header, fill rcube_mail_header obj.
-                    // initialize
-                    if (is_array($headers)) {
-                        reset($headers);
-                        while (list($k, $bar) = each($headers)) {
-                            $headers[$k] = '';
+                    else if ($name == 'RFC822') {
+                        $result[$id]->body = $value;
+                    }
+                    else if ($name == 'BODY') {
+                        $body = $this->tokenizeResponse($line, 1);
+                        if ($value[0] == 'HEADER.FIELDS')
+                            $headers = $body;
+                        else if (!empty($value))
+                            $result[$id]->bodypart[$value[0]] = $body;
+                        else
+                            $result[$id]->body = $body;
+                    }
+                }
+
+                // create array with header field:data
+                if (!empty($headers)) {
+                    $headers = explode("\n", trim($headers));
+                    foreach ($headers as $hid => $resln) {
+                        if (ord($resln[0]) <= 32) {
+                            $lines[$ln] .= (empty($lines[$ln]) ? '' : "\n") . trim($resln);
+                        } else {
+                            $lines[++$ln] = trim($resln);
                         }
                     }
 
                         }
                     }
 
-                    // create array with header field:data
                     while (list($lines_key, $str) = each($lines)) {
                         list($field, $string) = explode(':', $str, 2);
 
                     while (list($lines_key, $str) = each($lines)) {
                         list($field, $string) = explode(':', $str, 2);
 
@@ -1723,47 +1781,44 @@ class rcube_imap_generic
                                 $result[$id]->others[$field] = $string;
                             }
                             break;
                                 $result[$id]->others[$field] = $string;
                             }
                             break;
-                        } // end switch ()
-                    } // end while ()
-                }
-
-                // process flags
-                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;
                         }
                     }
                 }
             }
                         }
                     }
                 }
             }
+
+            // VANISHED response (QRESYNC RFC5162)
+            // Sample: * VANISHED (EARLIER) 300:310,405,411
+
+            else if (preg_match('/^\* VANISHED [()EARLIER]*/i', $line, $match)) {
+                $line   = substr($line, strlen($match[0]));
+                $v_data = $this->tokenizeResponse($line, 1);
+
+                $this->data['VANISHED'] = $v_data;
+            }
+
         } while (!$this->startsWith($line, $key, true));
 
         return $result;
     }
 
         } while (!$this->startsWith($line, $key, true));
 
         return $result;
     }
 
+    function fetchHeaders($mailbox, $message_set, $is_uid = false, $bodystr = false, $add = '')
+    {
+        $query_items = array('UID', 'RFC822.SIZE', 'FLAGS', 'INTERNALDATE');
+        if ($bodystr)
+            $query_items[] = 'BODYSTRUCTURE';
+        $query_items[] = 'BODY.PEEK[HEADER.FIELDS ('
+            . 'DATE FROM TO SUBJECT CONTENT-TYPE CC REPLY-TO LIST-POST DISPOSITION-NOTIFICATION-TO X-PRIORITY'
+            . ($add ? ' ' . trim($add) : '')
+            . ')]';
+
+        $result = $this->fetch($mailbox, $message_set, $is_uid, $query_items);
+
+        return $result;
+    }
+
     function fetchHeader($mailbox, $id, $uidfetch=false, $bodystr=false, $add='')
     {
     function fetchHeader($mailbox, $id, $uidfetch=false, $bodystr=false, $add='')
     {
-        $a  = $this->fetchHeaders($mailbox, $id, $uidfetch, $bodystr, $add);
+        $a = $this->fetchHeaders($mailbox, $id, $uidfetch, $bodystr, $add);
         if (is_array($a)) {
             return array_shift($a);
         }
         if (is_array($a)) {
             return array_shift($a);
         }
@@ -2043,6 +2098,7 @@ class rcube_imap_generic
             $params .= 'RETURN (' . implode(' ', $items) . ')';
         }
         if (!empty($criteria)) {
             $params .= 'RETURN (' . implode(' ', $items) . ')';
         }
         if (!empty($criteria)) {
+            $modseq = stripos($criteria, 'MODSEQ') !== false;
             $params .= ($params ? ' ' : '') . $criteria;
         }
         else {
             $params .= ($params ? ' ' : '') . $criteria;
         }
         else {
@@ -2054,20 +2110,27 @@ class rcube_imap_generic
 
         if ($code == self::ERROR_OK) {
             // remove prefix...
 
         if ($code == self::ERROR_OK) {
             // remove prefix...
-            $response = substr($response, stripos($response, 
+            $response = substr($response, stripos($response,
                 $esearch ? '* ESEARCH' : '* SEARCH') + ($esearch ? 10 : 9));
             // ...and unilateral untagged server responses
             if ($pos = strpos($response, '*')) {
                 $response = rtrim(substr($response, 0, $pos));
             }
 
                 $esearch ? '* ESEARCH' : '* SEARCH') + ($esearch ? 10 : 9));
             // ...and unilateral untagged server responses
             if ($pos = strpos($response, '*')) {
                 $response = rtrim(substr($response, 0, $pos));
             }
 
+            // remove MODSEQ response
+            if ($modseq) {
+                if (preg_match('/\(MODSEQ ([0-9]+)\)$/', $response, $m)) {
+                    $response = substr($response, 0, -strlen($m[0]));
+                }
+            }
+
             if ($esearch) {
                 // Skip prefix: ... (TAG "A285") UID ...
                 $this->tokenizeResponse($response, $return_uid ? 2 : 1);
 
                 $result = array();
                 for ($i=0; $i<count($items); $i++) {
             if ($esearch) {
                 // Skip prefix: ... (TAG "A285") UID ...
                 $this->tokenizeResponse($response, $return_uid ? 2 : 1);
 
                 $result = array();
                 for ($i=0; $i<count($items); $i++) {
-                    // If the SEARCH results in no matches, the server MUST NOT
+                    // If the SEARCH returns no matches, the server MUST NOT
                     // include the item result option in the ESEARCH response
                     if ($ret = $this->tokenizeResponse($response, 2)) {
                         list ($name, $value) = $ret;
                     // include the item result option in the ESEARCH response
                     if ($ret = $this->tokenizeResponse($response, 2)) {
                         list ($name, $value) = $ret;
@@ -2116,7 +2179,6 @@ class rcube_imap_generic
      *
      * @return array List of mailboxes or hash of options if $status_opts argument
      *               is non-empty.
      *
      * @return array List of mailboxes or hash of options if $status_opts argument
      *               is non-empty.
-     * @access public
      */
     function listMailboxes($ref, $mailbox, $status_opts=array(), $select_opts=array())
     {
      */
     function listMailboxes($ref, $mailbox, $status_opts=array(), $select_opts=array())
     {
@@ -2132,7 +2194,6 @@ class rcube_imap_generic
      *
      * @return array List of mailboxes or hash of options if $status_opts argument
      *               is non-empty.
      *
      * @return array List of mailboxes or hash of options if $status_opts argument
      *               is non-empty.
-     * @access public
      */
     function listSubscribed($ref, $mailbox, $status_opts=array())
     {
      */
     function listSubscribed($ref, $mailbox, $status_opts=array())
     {
@@ -2152,7 +2213,6 @@ class rcube_imap_generic
      *
      * @return array List of mailboxes or hash of options if $status_ops argument
      *               is non-empty.
      *
      * @return array List of mailboxes or hash of options if $status_ops argument
      *               is non-empty.
-     * @access private
      */
     private function _listMailboxes($ref, $mailbox, $subscribed=false,
         $status_opts=array(), $select_opts=array())
      */
     private function _listMailboxes($ref, $mailbox, $subscribed=false,
         $status_opts=array(), $select_opts=array())
@@ -2182,12 +2242,29 @@ class rcube_imap_generic
         list($code, $response) = $this->execute($subscribed ? 'LSUB' : 'LIST', $args);
 
         if ($code == self::ERROR_OK) {
         list($code, $response) = $this->execute($subscribed ? 'LSUB' : 'LIST', $args);
 
         if ($code == self::ERROR_OK) {
-            $folders = array();
-            while ($this->tokenizeResponse($response, 1) == '*') {
-                $cmd = strtoupper($this->tokenizeResponse($response, 1));
+            $folders  = array();
+            $last     = 0;
+            $pos      = 0;
+            $response .= "\r\n";
+
+            while ($pos = strpos($response, "\r\n", $pos+1)) {
+                // literal string, not real end-of-command-line
+                if ($response[$pos-1] == '}') {
+                    continue;
+                }
+
+                $line = substr($response, $last, $pos - $last);
+                $last = $pos + 2;
+
+                if (!preg_match('/^\* (LIST|LSUB|STATUS) /i', $line, $m)) {
+                    continue;
+                }
+                $cmd  = strtoupper($m[1]);
+                $line = substr($line, strlen($m[0]));
+
                 // * LIST (<options>) <delimiter> <mailbox>
                 if ($cmd == 'LIST' || $cmd == 'LSUB') {
                 // * LIST (<options>) <delimiter> <mailbox>
                 if ($cmd == 'LIST' || $cmd == 'LSUB') {
-                    list($opts, $delim, $mailbox) = $this->tokenizeResponse($response, 3);
+                    list($opts, $delim, $mailbox) = $this->tokenizeResponse($line, 3);
 
                     // Add to result array
                     if (!$lstatus) {
 
                     // Add to result array
                     if (!$lstatus) {
@@ -2198,31 +2275,21 @@ class rcube_imap_generic
                     }
 
                     // Add to options array
                     }
 
                     // Add to options array
-                    if (!empty($opts)) {
-                        if (empty($this->data['LIST'][$mailbox]))
-                            $this->data['LIST'][$mailbox] = $opts;
-                        else
-                            $this->data['LIST'][$mailbox] = array_unique(array_merge(
-                                $this->data['LIST'][$mailbox], $opts));
-                    }
+                    if (empty($this->data['LIST'][$mailbox]))
+                        $this->data['LIST'][$mailbox] = $opts;
+                    else if (!empty($opts))
+                        $this->data['LIST'][$mailbox] = array_unique(array_merge(
+                            $this->data['LIST'][$mailbox], $opts));
                 }
                 // * STATUS <mailbox> (<result>)
                 else if ($cmd == 'STATUS') {
                 }
                 // * STATUS <mailbox> (<result>)
                 else if ($cmd == 'STATUS') {
-                    list($mailbox, $status) = $this->tokenizeResponse($response, 2);
+                    list($mailbox, $status) = $this->tokenizeResponse($line, 2);
 
                     for ($i=0, $len=count($status); $i<$len; $i += 2) {
                         list($name, $value) = $this->tokenizeResponse($status, 2);
                         $folders[$mailbox][$name] = $value;
                     }
                 }
 
                     for ($i=0, $len=count($status); $i<$len; $i += 2) {
                         list($name, $value) = $this->tokenizeResponse($status, 2);
                         $folders[$mailbox][$name] = $value;
                     }
                 }
-                // other untagged response line, skip it
-                else {
-                    $response = ltrim($response);
-                    if (($position = strpos($response, "\n")) !== false)
-                        $response = substr($response, $position+1);
-                    else
-                        $response = '';
-                }
             }
 
             return $folders;
             }
 
             return $folders;
@@ -2231,7 +2298,7 @@ class rcube_imap_generic
         return false;
     }
 
         return false;
     }
 
-    function fetchMIMEHeaders($mailbox, $id, $parts, $mime=true)
+    function fetchMIMEHeaders($mailbox, $uid, $parts, $mime=true)
     {
         if (!$this->select($mailbox)) {
             return false;
     {
         if (!$this->select($mailbox)) {
             return false;
@@ -2240,16 +2307,15 @@ class rcube_imap_generic
         $result = false;
         $parts  = (array) $parts;
         $key    = $this->nextTag();
         $result = false;
         $parts  = (array) $parts;
         $key    = $this->nextTag();
-        $peeks  = '';
-        $idx    = 0;
+        $peeks  = array();
         $type   = $mime ? 'MIME' : 'HEADER';
 
         // format request
         $type   = $mime ? 'MIME' : 'HEADER';
 
         // format request
-        foreach($parts as $part) {
+        foreach ($parts as $part) {
             $peeks[] = "BODY.PEEK[$part.$type]";
         }
 
             $peeks[] = "BODY.PEEK[$part.$type]";
         }
 
-        $request = "$key FETCH $id (" . implode(' ', $peeks) . ')';
+        $request = "$key UID FETCH $uid (" . implode(' ', $peeks) . ')';
 
         // send request
         if (!$this->putLine($request)) {
 
         // send request
         if (!$this->putLine($request)) {
@@ -2259,13 +2325,25 @@ class rcube_imap_generic
 
         do {
             $line = $this->readLine(1024);
 
         do {
             $line = $this->readLine(1024);
-            $line = $this->multLine($line);
 
 
-            if (preg_match('/BODY\[([0-9\.]+)\.'.$type.'\]/', $line, $matches)) {
-                $idx = $matches[1];
-                $result[$idx] = preg_replace('/^(\* '.$id.' FETCH \()?\s*BODY\['.$idx.'\.'.$type.'\]\s+/', '', $line);
-                $result[$idx] = trim($result[$idx], '"');
-                $result[$idx] = rtrim($result[$idx], "\t\r\n\0\x0B");
+            if (preg_match('/^\* [0-9]+ FETCH [0-9UID( ]+BODY\[([0-9\.]+)\.'.$type.'\]/', $line, $matches)) {
+                $idx     = $matches[1];
+                $headers = '';
+
+                // get complete entry
+                if (preg_match('/\{([0-9]+)\}\r\n$/', $line, $m)) {
+                    $bytes = $m[1];
+                    $out   = '';
+
+                    while (strlen($out) < $bytes) {
+                        $out = $this->readBytes($bytes);
+                        if ($out === null)
+                            break;
+                        $headers .= $out;
+                    }
+                }
+
+                $result[$idx] = trim($headers);
             }
         } while (!$this->startsWith($line, $key, true));
 
             }
         } while (!$this->startsWith($line, $key, true));
 
@@ -2322,8 +2400,10 @@ class rcube_imap_generic
         $len    = strlen($line);
         $result = false;
 
         $len    = strlen($line);
         $result = false;
 
+        if ($a[2] != 'FETCH') {
+        }
         // handle empty "* X FETCH ()" response
         // handle empty "* X FETCH ()" response
-        if ($line[$len-1] == ')' && $line[$len-2] != '(') {
+        else if ($line[$len-1] == ')' && $line[$len-2] != '(') {
             // one line response, get everything between first and last quotes
             if (substr($line, -4, 3) == 'NIL') {
                 // NIL response
             // one line response, get everything between first and last quotes
             if (substr($line, -4, 3) == 'NIL') {
                 // NIL response
@@ -2442,8 +2522,18 @@ class rcube_imap_generic
         return ($result == self::ERROR_OK);
     }
 
         return ($result == self::ERROR_OK);
     }
 
+    /**
+     * Handler for IMAP APPEND command
+     *
+     * @param string $mailbox Mailbox name
+     * @param string $message Message content
+     *
+     * @return string|bool On success APPENDUID response (if available) or True, False on failure
+     */
     function append($mailbox, &$message)
     {
     function append($mailbox, &$message)
     {
+        unset($this->data['APPENDUID']);
+
         if (!$mailbox) {
             return false;
         }
         if (!$mailbox) {
             return false;
         }
@@ -2482,7 +2572,12 @@ class rcube_imap_generic
             // Clear internal status cache
             unset($this->data['STATUS:'.$mailbox]);
 
             // Clear internal status cache
             unset($this->data['STATUS:'.$mailbox]);
 
-            return ($this->parseResult($line, 'APPEND: ') == self::ERROR_OK);
+            if ($this->parseResult($line, 'APPEND: ') != self::ERROR_OK)
+                return false;
+            else if (!empty($this->data['APPENDUID']))
+                return $this->data['APPENDUID'];
+            else
+                return true;
         }
         else {
             $this->setError(self::ERROR_COMMAND, "Unable to send command: $request");
         }
         else {
             $this->setError(self::ERROR_COMMAND, "Unable to send command: $request");
@@ -2491,8 +2586,19 @@ class rcube_imap_generic
         return false;
     }
 
         return false;
     }
 
+    /**
+     * Handler for IMAP APPEND command.
+     *
+     * @param string $mailbox Mailbox name
+     * @param string $path    Path to the file with message body
+     * @param string $headers Message headers
+     *
+     * @return string|bool On success APPENDUID response (if available) or True, False on failure
+     */
     function appendFromFile($mailbox, $path, $headers=null)
     {
     function appendFromFile($mailbox, $path, $headers=null)
     {
+        unset($this->data['APPENDUID']);
+
         if (!$mailbox) {
             return false;
         }
         if (!$mailbox) {
             return false;
         }
@@ -2559,7 +2665,12 @@ class rcube_imap_generic
             // Clear internal status cache
             unset($this->data['STATUS:'.$mailbox]);
 
             // Clear internal status cache
             unset($this->data['STATUS:'.$mailbox]);
 
-            return ($this->parseResult($line, 'APPEND: ') == self::ERROR_OK);
+            if ($this->parseResult($line, 'APPEND: ') != self::ERROR_OK)
+                return false;
+            else if (!empty($this->data['APPENDUID']))
+                return $this->data['APPENDUID'];
+            else
+                return true;
         }
         else {
             $this->setError(self::ERROR_COMMAND, "Unable to send command: $request");
         }
         else {
             $this->setError(self::ERROR_COMMAND, "Unable to send command: $request");
@@ -2568,33 +2679,6 @@ class rcube_imap_generic
         return false;
     }
 
         return false;
     }
 
-    function fetchStructureString($mailbox, $id, $is_uid=false)
-    {
-        if (!$this->select($mailbox)) {
-            return false;
-        }
-
-        $key = $this->nextTag();
-        $result = false;
-        $command = $key . ($is_uid ? ' UID' : '') ." FETCH $id (BODYSTRUCTURE)";
-
-        if ($this->putLine($command)) {
-            do {
-                $line = $this->readLine(5000);
-                $line = $this->multLine($line, true);
-                if (!preg_match("/^$key /", $line))
-                    $result .= $line;
-            } while (!$this->startsWith($line, $key, true, true));
-
-            $result = trim(substr($result, strpos($result, 'BODYSTRUCTURE')+13, -1));
-        }
-        else {
-            $this->setError(self::ERROR_COMMAND, "Unable to send command: $command");
-        }
-
-        return $result;
-    }
-
     function getQuota()
     {
         /*
     function getQuota()
     {
         /*
@@ -2658,7 +2742,6 @@ class rcube_imap_generic
      *
      * @return boolean True on success, False on failure
      *
      *
      * @return boolean True on success, False on failure
      *
-     * @access public
      * @since 0.5-beta
      */
     function setACL($mailbox, $user, $acl)
      * @since 0.5-beta
      */
     function setACL($mailbox, $user, $acl)
@@ -2682,7 +2765,6 @@ class rcube_imap_generic
      *
      * @return boolean True on success, False on failure
      *
      *
      * @return boolean True on success, False on failure
      *
-     * @access public
      * @since 0.5-beta
      */
     function deleteACL($mailbox, $user)
      * @since 0.5-beta
      */
     function deleteACL($mailbox, $user)
@@ -2700,7 +2782,6 @@ class rcube_imap_generic
      * @param string $mailbox Mailbox name
      *
      * @return array User-rights array on success, NULL on error
      * @param string $mailbox Mailbox name
      *
      * @return array User-rights array on success, NULL on error
-     * @access public
      * @since 0.5-beta
      */
     function getACL($mailbox)
      * @since 0.5-beta
      */
     function getACL($mailbox)
@@ -2741,7 +2822,6 @@ class rcube_imap_generic
      * @param string $user    User name
      *
      * @return array List of user rights
      * @param string $user    User name
      *
      * @return array List of user rights
-     * @access public
      * @since 0.5-beta
      */
     function listRights($mailbox, $user)
      * @since 0.5-beta
      */
     function listRights($mailbox, $user)
@@ -2773,7 +2853,6 @@ class rcube_imap_generic
      * @param string $mailbox Mailbox name
      *
      * @return array MYRIGHTS response on success, NULL on error
      * @param string $mailbox Mailbox name
      *
      * @return array MYRIGHTS response on success, NULL on error
-     * @access public
      * @since 0.5-beta
      */
     function myRights($mailbox)
      * @since 0.5-beta
      */
     function myRights($mailbox)
@@ -2800,7 +2879,6 @@ class rcube_imap_generic
      * @param array  $entries Entry-value array (use NULL value as NIL)
      *
      * @return boolean True on success, False on failure
      * @param array  $entries Entry-value array (use NULL value as NIL)
      *
      * @return boolean True on success, False on failure
-     * @access public
      * @since 0.5-beta
      */
     function setMetadata($mailbox, $entries)
      * @since 0.5-beta
      */
     function setMetadata($mailbox, $entries)
@@ -2830,7 +2908,6 @@ class rcube_imap_generic
      *
      * @return boolean True on success, False on failure
      *
      *
      * @return boolean True on success, False on failure
      *
-     * @access public
      * @since 0.5-beta
      */
     function deleteMetadata($mailbox, $entries)
      * @since 0.5-beta
      */
     function deleteMetadata($mailbox, $entries)
@@ -2860,7 +2937,6 @@ class rcube_imap_generic
      *
      * @return array GETMETADATA result on success, NULL on error
      *
      *
      * @return array GETMETADATA result on success, NULL on error
      *
-     * @access public
      * @since 0.5-beta
      */
     function getMetadata($mailbox, $entries, $options=array())
      * @since 0.5-beta
      */
     function getMetadata($mailbox, $entries, $options=array())
@@ -2952,7 +3028,6 @@ class rcube_imap_generic
      *                        three elements: entry name, attribute name, value
      *
      * @return boolean True on success, False on failure
      *                        three elements: entry name, attribute name, value
      *
      * @return boolean True on success, False on failure
-     * @access public
      * @since 0.5-beta
      */
     function setAnnotation($mailbox, $data)
      * @since 0.5-beta
      */
     function setAnnotation($mailbox, $data)
@@ -2984,7 +3059,6 @@ class rcube_imap_generic
      *
      * @return boolean True on success, False on failure
      *
      *
      * @return boolean True on success, False on failure
      *
-     * @access public
      * @since 0.5-beta
      */
     function deleteAnnotation($mailbox, $data)
      * @since 0.5-beta
      */
     function deleteAnnotation($mailbox, $data)
@@ -3006,7 +3080,6 @@ class rcube_imap_generic
      *
      * @return array Annotations result on success, NULL on error
      *
      *
      * @return array Annotations result on success, NULL on error
      *
-     * @access public
      * @since 0.5-beta
      */
     function getAnnotation($mailbox, $entries, $attribs)
      * @since 0.5-beta
      */
     function getAnnotation($mailbox, $entries, $attribs)
@@ -3090,11 +3163,104 @@ class rcube_imap_generic
         return NULL;
     }
 
         return NULL;
     }
 
+    /**
+     * Returns BODYSTRUCTURE for the specified message.
+     *
+     * @param string $mailbox Folder name
+     * @param int    $id      Message sequence number or UID
+     * @param bool   $is_uid  True if $id is an UID
+     *
+     * @return array/bool Body structure array or False on error.
+     * @since 0.6
+     */
+    function getStructure($mailbox, $id, $is_uid = false)
+    {
+        $result = $this->fetch($mailbox, $id, $is_uid, array('BODYSTRUCTURE'));
+        if (is_array($result)) {
+            $result = array_shift($result);
+            return $result->bodystructure;
+        }
+        return false;
+    }
+
+    /**
+     * Returns data of a message part according to specified structure.
+     *
+     * @param array  $structure Message structure (getStructure() result)
+     * @param string $part      Message part identifier
+     *
+     * @return array Part data as hash array (type, encoding, charset, size)
+     */
+    static function getStructurePartData($structure, $part)
+    {
+           $part_a = self::getStructurePartArray($structure, $part);
+           $data   = array();
+
+           if (empty($part_a)) {
+            return $data;
+        }
+
+        // content-type
+        if (is_array($part_a[0])) {
+            $data['type'] = 'multipart';
+        }
+        else {
+            $data['type'] = strtolower($part_a[0]);
+
+            // encoding
+            $data['encoding'] = strtolower($part_a[5]);
+
+            // charset
+            if (is_array($part_a[2])) {
+               while (list($key, $val) = each($part_a[2])) {
+                    if (strcasecmp($val, 'charset') == 0) {
+                        $data['charset'] = $part_a[2][$key+1];
+                        break;
+                    }
+                }
+            }
+        }
+
+        // size
+        $data['size'] = intval($part_a[6]);
+
+        return $data;
+    }
+
+    static function getStructurePartArray($a, $part)
+    {
+           if (!is_array($a)) {
+            return false;
+        }
+           if (strpos($part, '.') > 0) {
+                   $original_part = $part;
+                   $pos = strpos($part, '.');
+                   $rest = substr($original_part, $pos+1);
+                   $part = substr($original_part, 0, $pos);
+                   if ((strcasecmp($a[0], 'message') == 0) && (strcasecmp($a[1], 'rfc822') == 0)) {
+                           $a = $a[8];
+                   }
+                   return self::getStructurePartArray($a[$part-1], $rest);
+           }
+        else if ($part>0) {
+                   if (!is_array($a[0]) && (strcasecmp($a[0], 'message') == 0)
+                && (strcasecmp($a[1], 'rfc822') == 0)) {
+                           $a = $a[8];
+                   }
+                   if (is_array($a[$part-1]))
+                return $a[$part-1];
+                   else
+                return $a;
+           }
+        else if (($part == 0) || (empty($part))) {
+                   return $a;
+           }
+    }
+
     /**
      * Creates next command identifier (tag)
      *
      * @return string Command identifier
     /**
      * Creates next command identifier (tag)
      *
      * @return string Command identifier
-     * @access public
      * @since 0.5-beta
      */
     function nextTag()
      * @since 0.5-beta
      */
     function nextTag()
@@ -3113,7 +3279,6 @@ class rcube_imap_generic
      * @param int    $options   Execution options
      *
      * @return mixed Response code or list of response code and data
      * @param int    $options   Execution options
      *
      * @return mixed Response code or list of response code and data
-     * @access public
      * @since 0.5-beta
      */
     function execute($command, $arguments=array(), $options=0)
      * @since 0.5-beta
      */
     function execute($command, $arguments=array(), $options=0)
@@ -3124,7 +3289,9 @@ class rcube_imap_generic
         $response = $noresp ? null : '';
 
         if (!empty($arguments)) {
         $response = $noresp ? null : '';
 
         if (!empty($arguments)) {
-            $query .= ' ' . implode(' ', $arguments);
+            foreach ($arguments as $arg) {
+                $query .= ' ' . self::r_implode($arg);
+            }
         }
 
         // Send command
         }
 
         // Send command
@@ -3171,7 +3338,6 @@ class rcube_imap_generic
      * @param int    $num  Number of tokens to return
      *
      * @return mixed Tokens array or string if $num=1
      * @param int    $num  Number of tokens to return
      *
      * @return mixed Tokens array or string if $num=1
-     * @access public
      * @since 0.5-beta
      */
     static function tokenizeResponse(&$str, $num=0)
      * @since 0.5-beta
      */
     static function tokenizeResponse(&$str, $num=0)
@@ -3192,7 +3358,7 @@ class rcube_imap_generic
                 if (!is_numeric(($bytes = substr($str, 1, $epos - 1)))) {
                     // error
                 }
                 if (!is_numeric(($bytes = substr($str, 1, $epos - 1)))) {
                     // error
                 }
-                $result[] = substr($str, $epos + 3, $bytes);
+                $result[] = $bytes ? substr($str, $epos + 3, $bytes) : '';
                 // Advance the string
                 $str = substr($str, $epos + 3 + $bytes);
                 break;
                 // Advance the string
                 $str = substr($str, $epos + 3 + $bytes);
                 break;
@@ -3221,28 +3387,25 @@ class rcube_imap_generic
 
             // Parenthesized list
             case '(':
 
             // Parenthesized list
             case '(':
+            case '[':
                 $str = substr($str, 1);
                 $result[] = self::tokenizeResponse($str);
                 break;
             case ')':
                 $str = substr($str, 1);
                 $result[] = self::tokenizeResponse($str);
                 break;
             case ')':
+            case ']':
                 $str = substr($str, 1);
                 return $result;
                 break;
 
             // String atom, number, NIL, *, %
             default:
                 $str = substr($str, 1);
                 return $result;
                 break;
 
             // String atom, number, NIL, *, %
             default:
-                // empty or one character
-                if ($str === '') {
+                // empty string
+                if ($str === '' || $str === null) {
                     break 2;
                 }
                     break 2;
                 }
-                if (strlen($str) < 2) {
-                    $result[] = $str;
-                    $str = '';
-                    break;
-                }
 
 
-                // excluded chars: SP, CTL, )
-                if (preg_match('/^([^\x00-\x20\x29\x7F]+)/', $str, $m)) {
+                // excluded chars: SP, CTL, ), [, ]
+                if (preg_match('/^([^\x00-\x20\x29\x5B\x5D\x7F]+)/', $str, $m)) {
                     $result[] = $m[1] == 'NIL' ? NULL : $m[1];
                     $str = substr($str, strlen($m[1]));
                 }
                     $result[] = $m[1] == 'NIL' ? NULL : $m[1];
                     $str = substr($str, strlen($m[1]));
                 }
@@ -3253,6 +3416,23 @@ class rcube_imap_generic
         return $num == 1 ? $result[0] : $result;
     }
 
         return $num == 1 ? $result[0] : $result;
     }
 
+    static function r_implode($element)
+    {
+        $string = '';
+
+        if (is_array($element)) {
+            reset($element);
+            while (list($key, $value) = each($element)) {
+                $string .= ' ' . self::r_implode($value);
+            }
+        }
+        else {
+            return $element;
+        }
+
+        return '(' . trim($string) . ')';
+    }
+
     private function _xor($string, $string2)
     {
         $result = '';
     private function _xor($string, $string2)
     {
         $result = '';
@@ -3346,7 +3526,6 @@ class rcube_imap_generic
      *
      * @param   boolean $debug      New value for the debugging flag.
      *
      *
      * @param   boolean $debug      New value for the debugging flag.
      *
-     * @access  public
      * @since   0.5-stable
      */
     function setDebug($debug, $handler = null)
      * @since   0.5-stable
      */
     function setDebug($debug, $handler = null)
@@ -3360,7 +3539,6 @@ class rcube_imap_generic
      *
      * @param   string  $message    Debug mesage text.
      *
      *
      * @param   string  $message    Debug mesage text.
      *
-     * @access  private
      * @since   0.5-stable
      */
     private function debug($message)
      * @since   0.5-stable
      */
     private function debug($message)
index 60b90ec7d5af99687834e5fbd2971b4a8467e5d5..6801a40962ce4ec01df35beb63b481dd08ee33b4 100644 (file)
@@ -16,7 +16,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: rcube_json_output.php 5037 2011-08-09 18:40:42Z alec $
+ $Id: rcube_json_output.php 5227 2011-09-16 17:54:07Z thomasb $
 
 */
 
 
 */
 
index 5db60c5dc12e560caa797f5465b6350548c67499..0cd179b823029a87dd4b04de629eeb65f128b844 100644 (file)
@@ -17,7 +17,7 @@
  |         Aleksander Machniak <machniak@kolabsys.com>                   |
  +-----------------------------------------------------------------------+
 
  |         Aleksander Machniak <machniak@kolabsys.com>                   |
  +-----------------------------------------------------------------------+
 
- $Id: rcube_ldap.php 5261 2011-09-21 12:22:40Z alec $
+ $Id: rcube_ldap.php 5541 2011-12-04 17:05:42Z thomasb $
 
 */
 
 
 */
 
@@ -53,8 +53,8 @@ class rcube_ldap extends rcube_addressbook
 
     private $base_dn = '';
     private $groups_base_dn = '';
 
     private $base_dn = '';
     private $groups_base_dn = '';
-    private $group_cache = array();
-    private $group_members = array();
+    private $group_url = null;
+    private $cache;
 
     private $vlv_active = false;
     private $vlv_count = 0;
 
     private $vlv_active = false;
     private $vlv_count = 0;
@@ -72,6 +72,9 @@ class rcube_ldap extends rcube_addressbook
     {
         $this->prop = $p;
 
     {
         $this->prop = $p;
 
+        if (isset($p['searchonly']))
+            $this->searchonly = $p['searchonly'];
+
         // check if groups are configured
         if (is_array($p['groups']) && count($p['groups'])) {
             $this->groups = true;
         // check if groups are configured
         if (is_array($p['groups']) && count($p['groups'])) {
             $this->groups = true;
@@ -80,6 +83,11 @@ class rcube_ldap extends rcube_addressbook
                 $this->prop['member_attr'] = strtolower($p['groups']['member_attr']);
             else if (empty($p['member_attr']))
                 $this->prop['member_attr'] = 'member';
                 $this->prop['member_attr'] = strtolower($p['groups']['member_attr']);
             else if (empty($p['member_attr']))
                 $this->prop['member_attr'] = 'member';
+            // set default name attribute to cn
+            if (empty($this->prop['groups']['name_attr']))
+                $this->prop['groups']['name_attr'] = 'cn';
+            if (empty($this->prop['groups']['scope']))
+                $this->prop['groups']['scope'] = 'sub';
         }
 
         // fieldmap property is given
         }
 
         // fieldmap property is given
@@ -125,6 +133,10 @@ class rcube_ldap extends rcube_addressbook
         $this->debug       = $debug;
         $this->mail_domain = $mail_domain;
 
         $this->debug       = $debug;
         $this->mail_domain = $mail_domain;
 
+        // initialize cache
+        $rcmail = rcmail::get_instance();
+        $this->cache = $rcmail->get_cache('LDAP.' . asciiwords($this->prop['name']), 'db', 600);
+
         $this->_connect();
     }
 
         $this->_connect();
     }
 
@@ -153,12 +165,14 @@ class rcube_ldap extends rcube_addressbook
 
         foreach ($this->prop['hosts'] as $host)
         {
 
         foreach ($this->prop['hosts'] as $host)
         {
-            $host = idn_to_ascii(rcube_parse_host($host));
-            $this->_debug("C: Connect [$host".($this->prop['port'] ? ':'.$this->prop['port'] : '')."]");
+            $host     = idn_to_ascii(rcube_parse_host($host));
+            $hostname = $host.($this->prop['port'] ? ':'.$this->prop['port'] : '');
+
+            $this->_debug("C: Connect [$hostname]");
 
             if ($lc = @ldap_connect($host, $this->prop['port']))
             {
 
             if ($lc = @ldap_connect($host, $this->prop['port']))
             {
-                if ($this->prop['use_tls']===true)
+                if ($this->prop['use_tls'] === true)
                     if (!ldap_start_tls($lc))
                         continue;
 
                     if (!ldap_start_tls($lc))
                         continue;
 
@@ -167,90 +181,117 @@ class rcube_ldap extends rcube_addressbook
                 ldap_set_option($lc, LDAP_OPT_PROTOCOL_VERSION, $this->prop['ldap_version']);
                 $this->prop['host'] = $host;
                 $this->conn = $lc;
                 ldap_set_option($lc, LDAP_OPT_PROTOCOL_VERSION, $this->prop['ldap_version']);
                 $this->prop['host'] = $host;
                 $this->conn = $lc;
+
+                if (isset($this->prop['referrals']))
+                    ldap_set_option($lc, LDAP_OPT_REFERRALS, $this->prop['referrals']);
                 break;
             }
             $this->_debug("S: NOT OK");
         }
 
                 break;
             }
             $this->_debug("S: NOT OK");
         }
 
-        if (is_resource($this->conn))
-        {
-            $this->ready = true;
+        // See if the directory is writeable.
+        if ($this->prop['writable']) {
+            $this->readonly = false;
+        }
 
 
-            $bind_pass = $this->prop['bind_pass'];
-            $bind_user = $this->prop['bind_user'];
-            $bind_dn   = $this->prop['bind_dn'];
+        if (!is_resource($this->conn)) {
+            raise_error(array('code' => 100, 'type' => 'ldap',
+                'file' => __FILE__, 'line' => __LINE__,
+                'message' => "Could not connect to any LDAP server, last tried $hostname"), true);
 
 
-            $this->base_dn        = $this->prop['base_dn'];
-            $this->groups_base_dn = ($this->prop['groups']['base_dn']) ?
-                $this->prop['groups']['base_dn'] : $this->base_dn;
+            return false;
+        }
 
 
-            // User specific access, generate the proper values to use.
-            if ($this->prop['user_specific']) {
-                // No password set, use the session password
-                if (empty($bind_pass)) {
-                    $bind_pass = $RCMAIL->decrypt($_SESSION['password']);
-                }
+        $bind_pass = $this->prop['bind_pass'];
+        $bind_user = $this->prop['bind_user'];
+        $bind_dn   = $this->prop['bind_dn'];
 
 
-                // Get the pieces needed for variable replacement.
-                if ($fu = $RCMAIL->user->get_username())
-                  list($u, $d) = explode('@', $fu);
-                else
-                  $d = $this->mail_domain;
+        $this->base_dn        = $this->prop['base_dn'];
+        $this->groups_base_dn = ($this->prop['groups']['base_dn']) ?
+        $this->prop['groups']['base_dn'] : $this->base_dn;
 
 
-                $dc = 'dc='.strtr($d, array('.' => ',dc=')); // hierarchal domain string
+        // User specific access, generate the proper values to use.
+        if ($this->prop['user_specific']) {
+            // No password set, use the session password
+            if (empty($bind_pass)) {
+                $bind_pass = $RCMAIL->decrypt($_SESSION['password']);
+            }
 
 
-                $replaces = array('%dc' => $dc, '%d' => $d, '%fu' => $fu, '%u' => $u);
+            // Get the pieces needed for variable replacement.
+            if ($fu = $RCMAIL->user->get_username())
+                list($u, $d) = explode('@', $fu);
+            else
+                $d = $this->mail_domain;
 
 
-                if ($this->prop['search_base_dn'] && $this->prop['search_filter']) {
-                    // Search for the dn to use to authenticate
-                    $this->prop['search_base_dn'] = strtr($this->prop['search_base_dn'], $replaces);
-                    $this->prop['search_filter'] = strtr($this->prop['search_filter'], $replaces);
+            $dc = 'dc='.strtr($d, array('.' => ',dc=')); // hierarchal domain string
 
 
-                    $this->_debug("S: searching with base {$this->prop['search_base_dn']} for {$this->prop['search_filter']}");
+            $replaces = array('%dn' => '', '%dc' => $dc, '%d' => $d, '%fu' => $fu, '%u' => $u);
 
 
-                    $res = @ldap_search($this->conn, $this->prop['search_base_dn'], $this->prop['search_filter'], array('uid'));
-                    if ($res && ($entry = ldap_first_entry($this->conn, $res))) {
-                        $bind_dn = ldap_get_dn($this->conn, $entry);
+            if ($this->prop['search_base_dn'] && $this->prop['search_filter']) {
+                if (!empty($this->prop['search_bind_dn']) && !empty($this->prop['search_bind_pw'])) {
+                    $this->bind($this->prop['search_bind_dn'], $this->prop['search_bind_pw']);
+                }
 
 
-                        $this->_debug("S: search returned dn: $bind_dn");
+                // Search for the dn to use to authenticate
+                $this->prop['search_base_dn'] = strtr($this->prop['search_base_dn'], $replaces);
+                $this->prop['search_filter'] = strtr($this->prop['search_filter'], $replaces);
 
 
-                        if ($bind_dn) {
-                            $dn = ldap_explode_dn($bind_dn, 1);
-                            $replaces['%dn'] = $dn[0];
-                        }
+                $this->_debug("S: searching with base {$this->prop['search_base_dn']} for {$this->prop['search_filter']}");
+
+                $res = @ldap_search($this->conn, $this->prop['search_base_dn'], $this->prop['search_filter'], array('uid'));
+                if ($res) {
+                    if (($entry = ldap_first_entry($this->conn, $res))
+                        && ($bind_dn = ldap_get_dn($this->conn, $entry))
+                    ) {
+                        $this->_debug("S: search returned dn: $bind_dn");
+                        $dn = ldap_explode_dn($bind_dn, 1);
+                        $replaces['%dn'] = $dn[0];
                     }
                 }
                     }
                 }
-                // Replace the bind_dn and base_dn variables.
-                $bind_dn              = strtr($bind_dn, $replaces);
-                $this->base_dn        = strtr($this->base_dn, $replaces);
-                $this->groups_base_dn = strtr($this->groups_base_dn, $replaces);
+                else {
+                    $this->_debug("S: ".ldap_error($this->conn));
+                }
 
 
-                if (empty($bind_user)) {
-                    $bind_user = $u;
+                // DN not found
+                if (empty($replaces['%dn'])) {
+                    if (!empty($this->prop['search_dn_default']))
+                        $replaces['%dn'] = $this->prop['search_dn_default'];
+                    else {
+                        raise_error(array(
+                            'code' => 100, 'type' => 'ldap',
+                            'file' => __FILE__, 'line' => __LINE__,
+                            'message' => "DN not found using LDAP search."), true);
+                        return false;
+                    }
                 }
             }
 
                 }
             }
 
-            if (!empty($bind_pass)) {
-                if (!empty($bind_dn)) {
-                    $this->ready = $this->_bind($bind_dn, $bind_pass);
-                }
-                else if (!empty($this->prop['auth_cid'])) {
-                    $this->ready = $this->_sasl_bind($this->prop['auth_cid'], $bind_pass, $bind_user);
-                }
-                else {
-                    $this->ready = $this->_sasl_bind($bind_user, $bind_pass);
-                }
+            // Replace the bind_dn and base_dn variables.
+            $bind_dn              = strtr($bind_dn, $replaces);
+            $this->base_dn        = strtr($this->base_dn, $replaces);
+            $this->groups_base_dn = strtr($this->groups_base_dn, $replaces);
+
+            if (empty($bind_user)) {
+                $bind_user = $u;
             }
         }
             }
         }
-        else
-            raise_error(array('code' => 100, 'type' => 'ldap',
-                'file' => __FILE__, 'line' => __LINE__,
-                'message' => "Could not connect to any LDAP server, last tried $host:{$this->prop[port]}"), true);
 
 
-        // See if the directory is writeable.
-        if ($this->prop['writable']) {
-            $this->readonly = false;
-        } // end if
+        if (empty($bind_pass)) {
+            $this->ready = true;
+        }
+        else {
+            if (!empty($bind_dn)) {
+                $this->ready = $this->bind($bind_dn, $bind_pass);
+            }
+            else if (!empty($this->prop['auth_cid'])) {
+                $this->ready = $this->sasl_bind($this->prop['auth_cid'], $bind_pass, $bind_user);
+            }
+            else {
+                $this->ready = $this->sasl_bind($bind_user, $bind_pass);
+            }
+        }
+
+        return $this->ready;
     }
 
 
     }
 
 
@@ -263,7 +304,7 @@ class rcube_ldap extends rcube_addressbook
      *
      * @return boolean True on success, False on error
      */
      *
      * @return boolean True on success, False on error
      */
-    private function _sasl_bind($authc, $pass, $authz=null)
+    public function sasl_bind($authc, $pass, $authz=null)
     {
         if (!$this->conn) {
             return false;
     {
         if (!$this->conn) {
             return false;
@@ -314,7 +355,7 @@ class rcube_ldap extends rcube_addressbook
      *
      * @return boolean True on success, False on error
      */
      *
      * @return boolean True on success, False on error
      */
-    private function _bind($dn, $pass)
+    public function bind($dn, $pass)
     {
         if (!$this->conn) {
             return false;
     {
         if (!$this->conn) {
             return false;
@@ -429,59 +470,219 @@ class rcube_ldap extends rcube_addressbook
      */
     function list_records($cols=null, $subset=0)
     {
      */
     function list_records($cols=null, $subset=0)
     {
-        // add general filter to query
-        if (!empty($this->prop['filter']) && empty($this->filter))
+        if ($this->prop['searchonly'] && empty($this->filter) && !$this->group_id)
         {
         {
-            $filter = $this->prop['filter'];
-            $this->set_search_set($filter);
+            $this->result = new rcube_result_set(0);
+            $this->result->searchonly = true;
+            return $this->result;
         }
 
         }
 
-        // exec LDAP search if no result resource is stored
-        if ($this->conn && !$this->ldap_result)
-            $this->_exec_search();
+        // fetch group members recursively
+        if ($this->group_id && $this->group_data['dn'])
+        {
+            $entries = $this->list_group_members($this->group_data['dn']);
 
 
-        // count contacts for this user
-        $this->result = $this->count();
+            // make list of entries unique and sort it
+            $seen = array();
+            foreach ($entries as $i => $rec) {
+                if ($seen[$rec['dn']]++)
+                    unset($entries[$i]);
+            }
+            usort($entries, array($this, '_entry_sort_cmp'));
 
 
-        // we have a search result resource
-        if ($this->ldap_result && $this->result->count > 0)
+            $entries['count'] = count($entries);
+            $this->result = new rcube_result_set($entries['count'], ($this->list_page-1) * $this->page_size);
+        }
+        else
         {
         {
-            // sorting still on the ldap server
-            if ($this->sort_col && $this->prop['scope'] !== 'base' && !$this->vlv_active)
-                ldap_sort($this->conn, $this->ldap_result, $this->sort_col);
+            // add general filter to query
+            if (!empty($this->prop['filter']) && empty($this->filter))
+                $this->set_search_set($this->prop['filter']);
 
 
-            // start and end of the page
-            $start_row = $this->vlv_active ? 0 : $this->result->first;
-            $start_row = $subset < 0 ? $start_row + $this->page_size + $subset : $start_row;
-            $last_row = $this->result->first + $this->page_size;
-            $last_row = $subset != 0 ? $start_row + abs($subset) : $last_row;
+            // exec LDAP search if no result resource is stored
+            if ($this->conn && !$this->ldap_result)
+                $this->_exec_search();
 
 
-            // get all entries from the ldap server
-            $entries = ldap_get_entries($this->conn, $this->ldap_result);
+            // count contacts for this user
+            $this->result = $this->count();
 
 
-            // filtering for group members
-            if ($this->groups and $this->group_id)
+            // we have a search result resource
+            if ($this->ldap_result && $this->result->count > 0)
             {
             {
-                $count = 0;
-                $members = array();
-                foreach ($entries as $entry)
-                {
-                    if ($this->group_members[self::dn_encode($entry['dn'])])
-                    {
-                        $members[] = $entry;
-                        $count++;
-                    }
+                // sorting still on the ldap server
+                if ($this->sort_col && $this->prop['scope'] !== 'base' && !$this->vlv_active)
+                    ldap_sort($this->conn, $this->ldap_result, $this->sort_col);
+
+                // get all entries from the ldap server
+                $entries = ldap_get_entries($this->conn, $this->ldap_result);
+            }
+
+        }  // end else
+
+        // start and end of the page
+        $start_row = $this->vlv_active ? 0 : $this->result->first;
+        $start_row = $subset < 0 ? $start_row + $this->page_size + $subset : $start_row;
+        $last_row = $this->result->first + $this->page_size;
+        $last_row = $subset != 0 ? $start_row + abs($subset) : $last_row;
+
+        // filter entries for this page
+        for ($i = $start_row; $i < min($entries['count'], $last_row); $i++)
+            $this->result->add($this->_ldap2result($entries[$i]));
+
+        return $this->result;
+    }
+
+    /**
+     * Get all members of the given group
+     *
+     * @param string Group DN
+     * @param array  Group entries (if called recursively)
+     * @return array Accumulated group members
+     */
+    function list_group_members($dn, $count = false, $entries = null)
+    {
+        $group_members = array();
+
+        // fetch group object
+        if (empty($entries)) {
+            $result = @ldap_read($this->conn, $dn, '(objectClass=*)', array('dn','objectClass','member','uniqueMember','memberURL'));
+            if ($result === false)
+            {
+                $this->_debug("S: ".ldap_error($this->conn));
+                return $group_members;
+            }
+
+            $entries = @ldap_get_entries($this->conn, $result);
+        }
+
+        for ($i=0; $i < $entries["count"]; $i++)
+        {
+            $entry = $entries[$i];
+
+            if (empty($entry['objectclass']))
+                continue;
+
+            foreach ((array)$entry['objectclass'] as $objectclass)
+            {
+                switch (strtolower($objectclass)) {
+                    case "groupofnames":
+                    case "kolabgroupofnames":
+                        $group_members = array_merge($group_members, $this->_list_group_members($dn, $entry, 'member', $count));
+                        break;
+                    case "groupofuniquenames":
+                    case "kolabgroupofuniquenames":
+                        $group_members = array_merge($group_members, $this->_list_group_members($dn, $entry, 'uniquemember', $count));
+                        break;
+                    case "groupofurls":
+                        $group_members = array_merge($group_members, $this->_list_group_memberurl($dn, $entry, $count));
+                        break;
                 }
                 }
-                $entries = $members;
-                $entries['count'] = $count;
-                $this->result->count = $count;
             }
             }
+            
+            if ($this->prop['sizelimit'] && count($group_members) > $this->prop['sizelimit'])
+              break;
+        }
+
+        return array_filter($group_members);
+    }
 
 
-            // filter entries for this page
-            for ($i = $start_row; $i < min($entries['count'], $last_row); $i++)
-                $this->result->add($this->_ldap2result($entries[$i]));
+    /**
+     * Fetch members of the given group entry from server
+     *
+     * @param string Group DN
+     * @param array  Group entry
+     * @param string Member attribute to use
+     * @return array Accumulated group members
+     */
+    private function _list_group_members($dn, $entry, $attr, $count)
+    {
+        // Use the member attributes to return an array of member ldap objects
+        // NOTE that the member attribute is supposed to contain a DN
+        $group_members = array();
+        if (empty($entry[$attr]))
+            return $group_members;
+
+        // read these attributes for all members
+        $attrib = $count ? array('dn') : array_values($this->fieldmap);
+        $attrib[] = 'objectClass';
+        $attrib[] = 'member';
+        $attrib[] = 'uniqueMember';
+        $attrib[] = 'memberURL';
+
+        for ($i=0; $i < $entry[$attr]['count']; $i++)
+        {
+            $result = @ldap_read($this->conn, $entry[$attr][$i], '(objectclass=*)',
+                $attrib, 0, (int)$this->prop['sizelimit'], (int)$this->prop['timelimit']);
+
+            $members = @ldap_get_entries($this->conn, $result);
+            if ($members == false)
+            {
+                $this->_debug("S: ".ldap_error($this->conn));
+                $members = array();
+            }
+
+            // for nested groups, call recursively
+            $nested_group_members = $this->list_group_members($entry[$attr][$i], $count, $members);
+
+            unset($members['count']);
+            $group_members = array_merge($group_members, array_filter($members), $nested_group_members);
         }
         }
-        return $this->result;
+
+        return $group_members;
+    }
+
+    /**
+     * List members of group class groupOfUrls
+     *
+     * @param string Group DN
+     * @param array  Group entry
+     * @param boolean True if only used for counting
+     * @return array Accumulated group members
+     */
+    private function _list_group_memberurl($dn, $entry, $count)
+    {
+        $group_members = array();
+
+        for ($i=0; $i < $entry['memberurl']['count']; $i++)
+        {
+            // extract components from url
+            if (!preg_match('!ldap:///([^\?]+)\?\?(\w+)\?(.*)$!', $entry['memberurl'][$i], $m))
+                continue;
+
+            // add search filter if any
+            $filter = $this->filter ? '(&(' . $m[3] . ')(' . $this->filter . '))' : $m[3];
+            $func = $m[2] == 'sub' ? 'ldap_search' : ($m[2] == 'base' ? 'ldap_read' : 'ldap_list');
+
+            $attrib = $count ? array('dn') : array_values($this->fieldmap);
+            if ($result = @$func($this->conn, $m[1], $filter,
+                $attrib, 0, (int)$this->prop['sizelimit'], (int)$this->prop['timelimit'])
+            ) {
+                $this->_debug("S: ".ldap_count_entries($this->conn, $result)." record(s) for ".$m[1]);
+            }
+            else {
+                $this->_debug("S: ".ldap_error($this->conn));
+                return $group_members;
+            }
+
+            $entries = @ldap_get_entries($this->conn, $result);
+            for ($j = 0; $j < $entries['count']; $j++)
+            {
+                if ($nested_group_members = $this->list_group_members($entries[$j]['dn'], $count))
+                    $group_members = array_merge($group_members, $nested_group_members);
+                else
+                    $group_members[] = $entries[$j];
+            }
+        }
+
+        return $group_members;
+    }
+
+    /**
+     * Callback for sorting entries
+     */
+    function _entry_sort_cmp($a, $b)
+    {
+        return strcmp($a[$this->sort_col][0], $b[$this->sort_col][0]);
     }
 
 
     }
 
 
@@ -490,15 +691,20 @@ class rcube_ldap extends rcube_addressbook
      *
      * @param mixed   $fields   The field name of array of field names to search in
      * @param mixed   $value    Search value (or array of values when $fields is array)
      *
      * @param mixed   $fields   The field name of array of field names to search in
      * @param mixed   $value    Search value (or array of values when $fields is array)
-     * @param boolean $strict   True for strict, False for partial (fuzzy) matching
+     * @param int     $mode     Matching mode:
+     *                          0 - partial (*abc*),
+     *                          1 - strict (=),
+     *                          2 - prefix (abc*)
      * @param boolean $select   True if results are requested, False if count only
      * @param boolean $nocount  (Not used)
      * @param array   $required List of fields that cannot be empty
      *
      * @return array  Indexed list of contact records and 'count' value
      */
      * @param boolean $select   True if results are requested, False if count only
      * @param boolean $nocount  (Not used)
      * @param array   $required List of fields that cannot be empty
      *
      * @return array  Indexed list of contact records and 'count' value
      */
-    function search($fields, $value, $strict=false, $select=true, $nocount=false, $required=array())
+    function search($fields, $value, $mode=0, $select=true, $nocount=false, $required=array())
     {
     {
+        $mode = intval($mode);
+
         // special treatment for ID-based search
         if ($fields == 'ID' || $fields == $this->primary_key)
         {
         // special treatment for ID-based search
         if ($fields == 'ID' || $fields == $this->primary_key)
         {
@@ -515,9 +721,70 @@ class rcube_ldap extends rcube_addressbook
             return $result;
         }
 
             return $result;
         }
 
+        // use VLV pseudo-search for autocompletion
+        if ($this->prop['vlv_search'] && $this->conn && join(',', (array)$fields) == 'email,name')
+        {
+            // add general filter to query
+            if (!empty($this->prop['filter']) && empty($this->filter))
+                $this->set_search_set($this->prop['filter']);
+
+            // set VLV controls with encoded search string
+            $this->_vlv_set_controls($this->prop, $this->list_page, $this->page_size, $value);
+
+            $function = $this->_scope2func($this->prop['scope']);
+            $this->ldap_result = @$function($this->conn, $this->base_dn, $this->filter ? $this->filter : '(objectclass=*)',
+                array_values($this->fieldmap), 0, $this->page_size, (int)$this->prop['timelimit']);
+
+            $this->result = new rcube_result_set(0);
+
+            if (!$this->ldap_result) {
+                $this->_debug("S: ".ldap_error($this->conn));
+                return $this->result;
+            }
+
+            $this->_debug("S: ".ldap_count_entries($this->conn, $this->ldap_result)." record(s)");
+
+            // get all entries of this page and post-filter those that really match the query
+            $search = mb_strtolower($value);
+            $entries = ldap_get_entries($this->conn, $this->ldap_result);
+
+            for ($i = 0; $i < $entries['count']; $i++) {
+                $rec = $this->_ldap2result($entries[$i]);
+                foreach (array('email', 'name') as $f) {
+                    $val = mb_strtolower($rec[$f]);
+                    switch ($mode) {
+                    case 1:
+                        $got = ($val == $search);
+                        break;
+                    case 2:
+                        $got = ($search == substr($val, 0, strlen($search)));
+                        break;
+                    default:
+                        $got = (strpos($val, $search) !== false);
+                        break;
+                    }
+
+                    if ($got) {
+                        $this->result->add($rec);
+                        $this->result->count++;
+                        break;
+                    }
+                }
+            }
+
+            return $this->result;
+        }
+
         // use AND operator for advanced searches
         $filter = is_array($value) ? '(&' : '(|';
         // use AND operator for advanced searches
         $filter = is_array($value) ? '(&' : '(|';
-        $wc     = !$strict && $this->prop['fuzzy_search'] ? '*' : '';
+        // set wildcards
+        $wp = $ws = '';
+        if (!empty($this->prop['fuzzy_search']) && $mode != 1) {
+            $ws = '*';
+            if (!$mode) {
+                $wp = '*';
+            }
+        }
 
         if ($fields == '*')
         {
 
         if ($fields == '*')
         {
@@ -531,7 +798,7 @@ class rcube_ldap extends rcube_addressbook
             if (is_array($this->prop['search_fields']))
             {
                 foreach ($this->prop['search_fields'] as $field) {
             if (is_array($this->prop['search_fields']))
             {
                 foreach ($this->prop['search_fields'] as $field) {
-                    $filter .= "($field=$wc" . $this->_quote_string($value) . "$wc)";
+                    $filter .= "($field=$wp" . $this->_quote_string($value) . "$ws)";
                 }
             }
         }
                 }
             }
         }
@@ -540,7 +807,7 @@ class rcube_ldap extends rcube_addressbook
             foreach ((array)$fields as $idx => $field) {
                 $val = is_array($value) ? $value[$idx] : $value;
                 if ($f = $this->_map_field($field)) {
             foreach ((array)$fields as $idx => $field) {
                 $val = is_array($value) ? $value[$idx] : $value;
                 if ($f = $this->_map_field($field)) {
-                    $filter .= "($f=$wc" . $this->_quote_string($val) . "$wc)";
+                    $filter .= "($f=$wp" . $this->_quote_string($val) . "$ws)";
                 }
             }
         }
                 }
             }
         }
@@ -585,18 +852,21 @@ class rcube_ldap extends rcube_addressbook
         $count = 0;
         if ($this->conn && $this->ldap_result) {
             $count = $this->vlv_active ? $this->vlv_count : ldap_count_entries($this->conn, $this->ldap_result);
         $count = 0;
         if ($this->conn && $this->ldap_result) {
             $count = $this->vlv_active ? $this->vlv_count : ldap_count_entries($this->conn, $this->ldap_result);
-        } // end if
-        elseif ($this->conn) {
+        }
+        else if ($this->group_id && $this->group_data['dn']) {
+            $count = count($this->list_group_members($this->group_data['dn'], true));
+        }
+        else if ($this->conn) {
             // We have a connection but no result set, attempt to get one.
             if (empty($this->filter)) {
                 // The filter is not set, set it.
                 $this->filter = $this->prop['filter'];
             // We have a connection but no result set, attempt to get one.
             if (empty($this->filter)) {
                 // The filter is not set, set it.
                 $this->filter = $this->prop['filter'];
-            } // end if
+            }
             $this->_exec_search(true);
             if ($this->ldap_result) {
                 $count = ldap_count_entries($this->conn, $this->ldap_result);
             $this->_exec_search(true);
             if ($this->ldap_result) {
                 $count = ldap_count_entries($this->conn, $this->ldap_result);
-            } // end if
-        } // end else
+            }
+        }
 
         return new rcube_result_set($count, ($this->list_page-1) * $this->page_size);
     }
 
         return new rcube_result_set($count, ($this->list_page-1) * $this->page_size);
     }
@@ -658,19 +928,49 @@ class rcube_ldap extends rcube_addressbook
      * If input not valid, the message to display can be fetched using get_error()
      *
      * @param array Assoziative array with data to save
      * If input not valid, the message to display can be fetched using get_error()
      *
      * @param array Assoziative array with data to save
-     *
+     * @param boolean Try to fix/complete record automatically
      * @return boolean True if input is valid, False if not.
      */
      * @return boolean True if input is valid, False if not.
      */
-    public function validate($save_data)
+    public function validate(&$save_data, $autofix = false)
     {
         // check for name input
         if (empty($save_data['name'])) {
     {
         // check for name input
         if (empty($save_data['name'])) {
-            $this->set_error('warning', 'nonamewarning');
+            $this->set_error(self::ERROR_VALIDATE, 'nonamewarning');
+            return false;
+        }
+
+        // Verify that the required fields are set.
+        $missing = null;
+        $ldap_data = $this->_map_data($save_data);
+        foreach ($this->prop['required_fields'] as $fld) {
+            if (!isset($ldap_data[$fld])) {
+                $missing[$fld] = 1;
+            }
+        }
+
+        if ($missing) {
+            // try to complete record automatically
+            if ($autofix) {
+                $reverse_map = array_flip($this->fieldmap);
+                $name_parts = preg_split('/[\s,.]+/', $save_data['name']);
+                if ($missing['sn']) {
+                    $sn_field = $reverse_map['sn'];
+                    $save_data[$sn_field] = array_pop ($name_parts);
+                }
+                if ($missing[($fn_field = $this->fieldmap['firstname'])]) {
+                    $save_data['firstname'] = array_shift($name_parts);
+                }
+
+                return $this->validate($save_data, false);
+            }
+
+            // TODO: generate message saying which fields are missing
+            $this->set_error(self::ERROR_VALIDATE, 'formincomplete');
             return false;
         }
 
         // validate e-mail addresses
             return false;
         }
 
         // validate e-mail addresses
-        return parent::validate($save_data);
+        return parent::validate($save_data, $autofix);
     }
 
 
     }
 
 
@@ -684,17 +984,8 @@ class rcube_ldap extends rcube_addressbook
     function insert($save_cols)
     {
         // Map out the column names to their LDAP ones to build the new entry.
     function insert($save_cols)
     {
         // Map out the column names to their LDAP ones to build the new entry.
-        $newentry = array();
+        $newentry = $this->_map_data($save_cols);
         $newentry['objectClass'] = $this->prop['LDAP_Object_Classes'];
         $newentry['objectClass'] = $this->prop['LDAP_Object_Classes'];
-        foreach ($this->fieldmap as $col => $fld) {
-            $val = $save_cols[$col];
-            if (is_array($val))
-                $val = array_filter($val);  // remove empty entries
-            if ($fld && $val) {
-                // The field does exist, add it to the entry.
-                $newentry[$fld] = $val;
-            } // end if
-        } // end foreach
 
         // Verify that the required fields are set.
         $missing = null;
 
         // Verify that the required fields are set.
         $missing = null;
@@ -707,7 +998,7 @@ class rcube_ldap extends rcube_addressbook
         // abort process if requiered fields are missing
         // TODO: generate message saying which fields are missing
         if ($missing) {
         // abort process if requiered fields are missing
         // TODO: generate message saying which fields are missing
         if ($missing) {
-            $this->set_error(self::ERROR_INCOMPLETE, 'formincomplete');
+            $this->set_error(self::ERROR_VALIDATE, 'formincomplete');
             return false;
         }
 
             return false;
         }
 
@@ -728,7 +1019,7 @@ class rcube_ldap extends rcube_addressbook
         $dn = self::dn_encode($dn);
 
         // add new contact to the selected group
         $dn = self::dn_encode($dn);
 
         // add new contact to the selected group
-        if ($this->groups)
+        if ($this->group_id)
             $this->add_to_group($this->group_id, $dn);
 
         return $dn;
             $this->add_to_group($this->group_id, $dn);
 
         return $dn;
@@ -753,39 +1044,33 @@ class rcube_ldap extends rcube_addressbook
         $replacedata = array();
         $deletedata = array();
 
         $replacedata = array();
         $deletedata = array();
 
-        // flatten composite fields in $record
-        if (is_array($record['address'])) {
-          foreach ($record['address'] as $i => $struct) {
-            foreach ($struct as $col => $val) {
-              $record[$col][$i] = $val;
-            }
-          }
-        }
+        $ldap_data = $this->_map_data($save_cols);
+        $old_data = $record['_raw_attrib'];
 
         foreach ($this->fieldmap as $col => $fld) {
 
         foreach ($this->fieldmap as $col => $fld) {
-            $val = $save_cols[$col];
+            $val = $ldap_data[$fld];
             if ($fld) {
                 // remove empty array values
                 if (is_array($val))
                     $val = array_filter($val);
                 // The field does exist compare it to the ldap record.
             if ($fld) {
                 // remove empty array values
                 if (is_array($val))
                     $val = array_filter($val);
                 // The field does exist compare it to the ldap record.
-                if ($record[$col] != $val) {
+                if ($old_data[$fld] != $val) {
                     // Changed, but find out how.
                     // Changed, but find out how.
-                    if (!isset($record[$col])) {
+                    if (!isset($old_data[$fld])) {
                         // Field was not set prior, need to add it.
                         $newdata[$fld] = $val;
                         // Field was not set prior, need to add it.
                         $newdata[$fld] = $val;
-                    } // end if
-                    elseif ($val == '') {
+                    }
+                    else if ($val == '') {
                         // Field supplied is empty, verify that it is not required.
                         if (!in_array($fld, $this->prop['required_fields'])) {
                             // It is not, safe to clear.
                         // Field supplied is empty, verify that it is not required.
                         if (!in_array($fld, $this->prop['required_fields'])) {
                             // It is not, safe to clear.
-                            $deletedata[$fld] = $record[$col];
-                        } // end if
+                            $deletedata[$fld] = $old_data[$fld];
+                        }
                     } // end elseif
                     else {
                         // The data was modified, save it out.
                         $replacedata[$fld] = $val;
                     } // end elseif
                     else {
                         // The data was modified, save it out.
                         $replacedata[$fld] = $val;
-                    } // end else
+                    }
                 } // end if
             } // end if
         } // end foreach
                 } // end if
             } // end if
         } // end foreach
@@ -917,14 +1202,14 @@ class rcube_ldap extends rcube_addressbook
         if ($this->ready)
         {
             $filter = $this->filter ? $this->filter : '(objectclass=*)';
         if ($this->ready)
         {
             $filter = $this->filter ? $this->filter : '(objectclass=*)';
-            $function = $this->prop['scope'] == 'sub' ? 'ldap_search' : ($this->prop['scope'] == 'base' ? 'ldap_read' : 'ldap_list');
+            $function = $this->_scope2func($this->prop['scope'], $ns_function);
 
 
-            $this->_debug("C: Search [$filter]");
+            $this->_debug("C: Search [$filter][dn: $this->base_dn]");
 
             // when using VLV, we get the total count by...
 
             // when using VLV, we get the total count by...
-            if (!$count && $function != 'ldap_read' && $this->prop['vlv']) {
+            if (!$count && $function != 'ldap_read' && $this->prop['vlv'] && !$this->group_id) {
                 // ...either reading numSubOrdinates attribute
                 // ...either reading numSubOrdinates attribute
-                if ($this->prop['numsub_filter'] && ($result_count = @$function($this->conn, $this->base_dn, $this->prop['numsub_filter'], array('numSubOrdinates'), 0, 0, 0))) {
+                if ($this->prop['numsub_filter'] && ($result_count = @$ns_function($this->conn, $this->base_dn, $this->prop['numsub_filter'], array('numSubOrdinates'), 0, 0, 0))) {
                     $counts = ldap_get_entries($this->conn, $result_count);
                     for ($this->vlv_count = $j = 0; $j < $counts['count']; $j++)
                         $this->vlv_count += $counts[$j]['numsubordinates'][0];
                     $counts = ldap_get_entries($this->conn, $result_count);
                     for ($this->vlv_count = $j = 0; $j < $counts['count']; $j++)
                         $this->vlv_count += $counts[$j]['numsubordinates'][0];
@@ -933,21 +1218,20 @@ class rcube_ldap extends rcube_addressbook
                 else  // ...or by fetching all records dn and count them
                     $this->vlv_count = $this->_exec_search(true);
 
                 else  // ...or by fetching all records dn and count them
                     $this->vlv_count = $this->_exec_search(true);
 
-                $this->vlv_active = $this->_vlv_set_controls();
+                $this->vlv_active = $this->_vlv_set_controls($this->prop, $this->list_page, $this->page_size);
             }
 
             // only fetch dn for count (should keep the payload low)
             $attrs = $count ? array('dn') : array_values($this->fieldmap);
             if ($this->ldap_result = @$function($this->conn, $this->base_dn, $filter,
             }
 
             // only fetch dn for count (should keep the payload low)
             $attrs = $count ? array('dn') : array_values($this->fieldmap);
             if ($this->ldap_result = @$function($this->conn, $this->base_dn, $filter,
-                $attrs, 0, (int)$this->prop['sizelimit'], (int)$this->prop['timelimit']))
-            {
-                $this->_debug("S: ".ldap_count_entries($this->conn, $this->ldap_result)." record(s)");
-                if ($err = ldap_errno($this->conn))
-                    $this->_debug("S: Error: " .ldap_err2str($err));
-                return true;
+                $attrs, 0, (int)$this->prop['sizelimit'], (int)$this->prop['timelimit'])
+            {
+                $entries_count = ldap_count_entries($this->conn, $this->ldap_result);
+                $this->_debug("S: $count_entries record(s)");
+
+                return $count ? $count_entries : true;
             }
             }
-            else
-            {
+            else {
                 $this->_debug("S: ".ldap_error($this->conn));
             }
         }
                 $this->_debug("S: ".ldap_error($this->conn));
             }
         }
@@ -955,16 +1239,38 @@ class rcube_ldap extends rcube_addressbook
         return false;
     }
 
         return false;
     }
 
+    /**
+     * Choose the right PHP function according to scope property
+     */
+    private function _scope2func($scope, &$ns_function = null)
+    {
+        switch ($scope) {
+          case 'sub':
+            $function = $ns_function  = 'ldap_search';
+            break;
+          case 'base':
+            $function = $ns_function = 'ldap_read';
+            break;
+          default:
+            $function = 'ldap_list';
+            $ns_function = 'ldap_read';
+            break;
+        }
+        
+        return $function;
+    }
+
     /**
      * Set server controls for Virtual List View (paginated listing)
      */
     /**
      * Set server controls for Virtual List View (paginated listing)
      */
-    private function _vlv_set_controls()
+    private function _vlv_set_controls($prop, $list_page, $page_size, $search = null)
     {
     {
-        $sort_ctrl = array('oid' => "1.2.840.113556.1.4.473",  'value' => $this->_sort_ber_encode((array)$this->prop['sort']));
-        $vlv_ctrl  = array('oid' => "2.16.840.1.113730.3.4.9", 'value' => $this->_vlv_ber_encode(($offset = ($this->list_page-1) * $this->page_size + 1), $this->page_size), 'iscritical' => true);
+        $sort_ctrl = array('oid' => "1.2.840.113556.1.4.473",  'value' => $this->_sort_ber_encode((array)$prop['sort']));
+        $vlv_ctrl  = array('oid' => "2.16.840.1.113730.3.4.9", 'value' => $this->_vlv_ber_encode(($offset = ($list_page-1) * $page_size + 1), $page_size, $search), 'iscritical' => true);
 
 
-        $this->_debug("C: set controls sort=" . join(' ', unpack('H'.(strlen($sort_ctrl['value'])*2), $sort_ctrl['value'])) . " ({$this->sort_col});"
-            . " vlv=" . join(' ', (unpack('H'.(strlen($vlv_ctrl['value'])*2), $vlv_ctrl['value']))) . " ($offset)");
+        $sort = (array)$prop['sort'];
+        $this->_debug("C: set controls sort=" . join(' ', unpack('H'.(strlen($sort_ctrl['value'])*2), $sort_ctrl['value'])) . " ($sort[0]);"
+            . " vlv=" . join(' ', (unpack('H'.(strlen($vlv_ctrl['value'])*2), $vlv_ctrl['value']))) . " ($offset/$page_size)");
 
         if (!ldap_set_option($this->conn, LDAP_OPT_SERVER_CONTROLS, array($sort_ctrl, $vlv_ctrl))) {
             $this->_debug("S: ".ldap_error($this->conn));
 
         if (!ldap_set_option($this->conn, LDAP_OPT_SERVER_CONTROLS, array($sort_ctrl, $vlv_ctrl))) {
             $this->_debug("S: ".ldap_error($this->conn));
@@ -991,6 +1297,9 @@ class rcube_ldap extends rcube_addressbook
             for ($i=0; $i < $rec[$lf]['count']; $i++) {
                 if (!($value = $rec[$lf][$i]))
                     continue;
             for ($i=0; $i < $rec[$lf]['count']; $i++) {
                 if (!($value = $rec[$lf][$i]))
                     continue;
+
+                $out['_raw_attrib'][$lf][$i] = $value;
+
                 if ($rf == 'email' && $this->mail_domain && !strpos($value, '@'))
                     $out[$rf][] = sprintf('%s@%s', $value, $this->mail_domain);
                 else if (in_array($rf, array('street','zipcode','locality','country','region')))
                 if ($rf == 'email' && $this->mail_domain && !strpos($value, '@'))
                     $out[$rf][] = sprintf('%s@%s', $value, $this->mail_domain);
                 else if (in_array($rf, array('street','zipcode','locality','country','region')))
@@ -1000,6 +1309,11 @@ class rcube_ldap extends rcube_addressbook
                 else
                     $out[$rf] = $value;
             }
                 else
                     $out[$rf] = $value;
             }
+
+            // Make sure name fields aren't arrays (#1488108)
+            if (is_array($out[$rf]) && in_array($rf, array('name', 'surname', 'firstname', 'middlename', 'nickname'))) {
+                $out[$rf] = $out['_raw_attrib'][$lf] = $out[$rf][0];
+            }
         }
 
         return $out;
         }
 
         return $out;
@@ -1015,6 +1329,40 @@ class rcube_ldap extends rcube_addressbook
     }
 
 
     }
 
 
+    /**
+     * Convert a record data set into LDAP field attributes
+     */
+    private function _map_data($save_cols)
+    {
+        // flatten composite fields first
+        foreach ($this->coltypes as $col => $colprop) {
+            if (is_array($colprop['childs']) && ($values = $this->get_col_values($col, $save_cols, false))) {
+                foreach ($values as $subtype => $childs) {
+                    $subtype = $subtype ? ':'.$subtype : '';
+                    foreach ($childs as $i => $child_values) {
+                        foreach ((array)$child_values as $childcol => $value) {
+                            $save_cols[$childcol.$subtype][$i] = $value;
+                        }
+                    }
+                }
+            }
+        }
+
+        $ldap_data = array();
+        foreach ($this->fieldmap as $col => $fld) {
+            $val = $save_cols[$col];
+            if (is_array($val))
+                $val = array_filter($val);  // remove empty entries
+            if ($fld && $val) {
+                // The field does exist, add it to the entry.
+                $ldap_data[$fld] = $val;
+            }
+        }
+        
+        return $ldap_data;
+    }
+
+
     /**
      * Returns unified attribute name (resolving aliases)
      */
     /**
      * Returns unified attribute name (resolving aliases)
      */
@@ -1042,6 +1390,18 @@ class rcube_ldap extends rcube_addressbook
     }
 
 
     }
 
 
+    /**
+     * Activate/deactivate debug mode
+     *
+     * @param boolean $dbg True if LDAP commands should be logged
+     * @access public
+     */
+    function set_debug($dbg = true)
+    {
+        $this->debug = $dbg;
+    }
+
+
     /**
      * Quotes attribute value string
      *
     /**
      * Quotes attribute value string
      *
@@ -1075,22 +1435,17 @@ class rcube_ldap extends rcube_addressbook
     {
         if ($group_id)
         {
     {
         if ($group_id)
         {
-            if (!$this->group_cache)
-                $this->list_groups();
-
-            $cache_members = $this->group_cache[$group_id]['members'];
+            if (($group_cache = $this->cache->get('groups')) === null)
+                $group_cache = $this->_fetch_groups();
 
 
-            $members = array();
-            for ($i=0; $i<$cache_members["count"]; $i++)
-            {
-                if (!empty($cache_members[$i]))
-                    $members[self::dn_encode($cache_members[$i])] = 1;
-            }
-            $this->group_members = $members;
             $this->group_id = $group_id;
             $this->group_id = $group_id;
+            $this->group_data = $group_cache[$group_id];
         }
         else
         }
         else
+        {
             $this->group_id = 0;
             $this->group_id = 0;
+            $this->group_data = null;
+        }
     }
 
     /**
     }
 
     /**
@@ -1104,12 +1459,49 @@ class rcube_ldap extends rcube_addressbook
         if (!$this->groups)
             return array();
 
         if (!$this->groups)
             return array();
 
+        // use cached list for searching
+        $this->cache->expunge();
+        if (!$search || ($group_cache = $this->cache->get('groups')) === null)
+            $group_cache = $this->_fetch_groups();
+
+        $groups = array();
+        if ($search) {
+            $search = mb_strtolower($search);
+            foreach ($group_cache as $group) {
+                if (strpos(mb_strtolower($group['name']), $search) !== false)
+                    $groups[] = $group;
+            }
+        }
+        else
+            $groups = $group_cache;
+
+        return array_values($groups);
+    }
+
+    /**
+     * Fetch groups from server
+     */
+    private function _fetch_groups($vlv_page = 0)
+    {
         $base_dn = $this->groups_base_dn;
         $filter = $this->prop['groups']['filter'];
         $base_dn = $this->groups_base_dn;
         $filter = $this->prop['groups']['filter'];
+        $name_attr = $this->prop['groups']['name_attr'];
+        $email_attr = $this->prop['groups']['email_attr'] ? $this->prop['groups']['email_attr'] : 'mail';
+        $sort_attrs = $this->prop['groups']['sort'] ? (array)$this->prop['groups']['sort'] : array($name_attr);
+        $sort_attr = $sort_attrs[0];
 
         $this->_debug("C: Search [$filter][dn: $base_dn]");
 
 
         $this->_debug("C: Search [$filter][dn: $base_dn]");
 
-        $res = @ldap_search($this->conn, $base_dn, $filter, array('cn', $this->prop['member_attr']));
+        // use vlv to list groups
+        if ($this->prop['groups']['vlv']) {
+            $page_size = 200;
+            if (!$this->prop['groups']['sort'])
+                $this->prop['groups']['sort'] = $sort_attrs;
+            $vlv_active = $this->_vlv_set_controls($this->prop['groups'], $vlv_page+1, $page_size);
+        }
+
+        $function = $this->_scope2func($this->prop['groups']['scope'], $ns_function);
+        $res = @$function($this->conn, $base_dn, $filter, array_unique(array('dn', 'objectClass', $name_attr, $email_attr, $sort_attr)));
         if ($res === false)
         {
             $this->_debug("S: ".ldap_error($this->conn));
         if ($res === false)
         {
             $this->_debug("S: ".ldap_error($this->conn));
@@ -1121,24 +1513,79 @@ class rcube_ldap extends rcube_addressbook
 
         $groups = array();
         $group_sortnames = array();
 
         $groups = array();
         $group_sortnames = array();
-        for ($i=0; $i<$ldap_data["count"]; $i++)
+        $group_count = $ldap_data["count"];
+        for ($i=0; $i < $group_count; $i++)
         {
         {
-            $group_name = $ldap_data[$i]['cn'][0];
-            if (!$search || strstr(strtolower($group_name), strtolower($search)))
-            {
-                $group_id = self::dn_encode($group_name);
-                $groups[$group_id]['ID'] = $group_id;
-                $groups[$group_id]['name'] = $group_name;
-                $groups[$group_id]['members'] = $ldap_data[$i][$this->prop['member_attr']];
-                $group_sortnames[] = strtolower($group_name);
+            $group_name = is_array($ldap_data[$i][$name_attr]) ? $ldap_data[$i][$name_attr][0] : $ldap_data[$i][$name_attr];
+            $group_id = self::dn_encode($group_name);
+            $groups[$group_id]['ID'] = $group_id;
+            $groups[$group_id]['dn'] = $ldap_data[$i]['dn'];
+            $groups[$group_id]['name'] = $group_name;
+            $groups[$group_id]['member_attr'] = $this->prop['member_attr'];
+
+            // check objectClass attributes of group and act accordingly
+            for ($j=0; $j < $ldap_data[$i]['objectclass']['count']; $j++) {
+                switch (strtolower($ldap_data[$i]['objectclass'][$j])) {
+                    case 'groupofnames':
+                    case 'kolabgroupofnames':
+                        $groups[$group_id]['member_attr'] = 'member';
+                        break;
+
+                    case 'groupofuniquenames':
+                    case 'kolabgroupofuniquenames':
+                        $groups[$group_id]['member_attr'] = 'uniqueMember';
+                        break;
+                }
             }
             }
+
+            // list email attributes of a group
+            for ($j=0; $ldap_data[$i][$email_attr] && $j < $ldap_data[$i][$email_attr]['count']; $j++) {
+                if (strpos($ldap_data[$i][$email_attr][$j], '@') > 0)
+                    $groups[$group_id]['email'][] = $ldap_data[$i][$email_attr][$j];
+            }
+
+            $group_sortnames[] = mb_strtolower($ldap_data[$i][$sort_attr][0]);
         }
         }
-        array_multisort($group_sortnames, SORT_ASC, SORT_STRING, $groups);
-        $this->group_cache = $groups;
+
+        // recursive call can exit here
+        if ($vlv_page > 0)
+            return $groups;
+
+        // call recursively until we have fetched all groups
+        while ($vlv_active && $group_count == $page_size)
+        {
+            $next_page = $this->_fetch_groups(++$vlv_page);
+            $groups = array_merge($groups, $next_page);
+            $group_count = count($next_page);
+        }
+
+        // when using VLV the list of groups is already sorted
+        if (!$this->prop['groups']['vlv'])
+            array_multisort($group_sortnames, SORT_ASC, SORT_STRING, $groups);
+
+        // cache this
+        $this->cache->set('groups', $groups);
 
         return $groups;
     }
 
 
         return $groups;
     }
 
+    /**
+     * Get group properties such as name and email address(es)
+     *
+     * @param string Group identifier
+     * @return array Group properties as hash array
+     */
+    function get_group($group_id)
+    {
+        if (($group_cache = $this->cache->get('groups')) === null)
+            $group_cache = $this->_fetch_groups();
+
+        $group_data = $group_cache[$group_id];
+        unset($group_data['dn'], $group_data['member_attr']);
+
+        return $group_data;
+    }
+
     /**
      * Create a contact group with the given name
      *
     /**
      * Create a contact group with the given name
      *
@@ -1147,17 +1594,16 @@ class rcube_ldap extends rcube_addressbook
      */
     function create_group($group_name)
     {
      */
     function create_group($group_name)
     {
-        if (!$this->group_cache)
-            $this->list_groups();
-
         $base_dn = $this->groups_base_dn;
         $new_dn = "cn=$group_name,$base_dn";
         $new_gid = self::dn_encode($group_name);
         $base_dn = $this->groups_base_dn;
         $new_dn = "cn=$group_name,$base_dn";
         $new_gid = self::dn_encode($group_name);
+        $member_attr = $this->prop['groups']['member_attr'];
+        $name_attr = $this->prop['groups']['name_attr'];
 
         $new_entry = array(
             'objectClass' => $this->prop['groups']['object_classes'],
 
         $new_entry = array(
             'objectClass' => $this->prop['groups']['object_classes'],
-            'cn' => $group_name,
-            $this->prop['member_attr'] => '',
+            $name_attr => $group_name,
+            $member_attr => '',
         );
 
         $this->_debug("C: Add [dn: $new_dn]: ".print_r($new_entry, true));
         );
 
         $this->_debug("C: Add [dn: $new_dn]: ".print_r($new_entry, true));
@@ -1171,6 +1617,7 @@ class rcube_ldap extends rcube_addressbook
         }
 
         $this->_debug("S: OK");
         }
 
         $this->_debug("S: OK");
+        $this->cache->remove('groups');
 
         return array('id' => $new_gid, 'name' => $group_name);
     }
 
         return array('id' => $new_gid, 'name' => $group_name);
     }
@@ -1183,11 +1630,11 @@ class rcube_ldap extends rcube_addressbook
      */
     function delete_group($group_id)
     {
      */
     function delete_group($group_id)
     {
-        if (!$this->group_cache)
-            $this->list_groups();
+        if (($group_cache = $this->cache->get('groups')) === null)
+            $group_cache = $this->_fetch_groups();
 
         $base_dn = $this->groups_base_dn;
 
         $base_dn = $this->groups_base_dn;
-        $group_name = $this->group_cache[$group_id]['name'];
+        $group_name = $group_cache[$group_id]['name'];
         $del_dn = "cn=$group_name,$base_dn";
 
         $this->_debug("C: Delete [dn: $del_dn]");
         $del_dn = "cn=$group_name,$base_dn";
 
         $this->_debug("C: Delete [dn: $del_dn]");
@@ -1201,6 +1648,7 @@ class rcube_ldap extends rcube_addressbook
         }
 
         $this->_debug("S: OK");
         }
 
         $this->_debug("S: OK");
+        $this->cache->remove('groups');
 
         return true;
     }
 
         return true;
     }
@@ -1215,11 +1663,11 @@ class rcube_ldap extends rcube_addressbook
      */
     function rename_group($group_id, $new_name, &$new_gid)
     {
      */
     function rename_group($group_id, $new_name, &$new_gid)
     {
-        if (!$this->group_cache)
-            $this->list_groups();
+        if (($group_cache = $this->cache->get('groups')) === null)
+            $group_cache = $this->_fetch_groups();
 
         $base_dn = $this->groups_base_dn;
 
         $base_dn = $this->groups_base_dn;
-        $group_name = $this->group_cache[$group_id]['name'];
+        $group_name = $group_cache[$group_id]['name'];
         $old_dn = "cn=$group_name,$base_dn";
         $new_rdn = "cn=$new_name";
         $new_gid = self::dn_encode($new_name);
         $old_dn = "cn=$group_name,$base_dn";
         $new_rdn = "cn=$new_name";
         $new_gid = self::dn_encode($new_name);
@@ -1235,6 +1683,7 @@ class rcube_ldap extends rcube_addressbook
         }
 
         $this->_debug("S: OK");
         }
 
         $this->_debug("S: OK");
+        $this->cache->remove('groups');
 
         return $new_name;
     }
 
         return $new_name;
     }
@@ -1248,16 +1697,19 @@ class rcube_ldap extends rcube_addressbook
      */
     function add_to_group($group_id, $contact_ids)
     {
      */
     function add_to_group($group_id, $contact_ids)
     {
-        if (!$this->group_cache)
-            $this->list_groups();
+        if (($group_cache = $this->cache->get('groups')) === null)
+            $group_cache = $this->_fetch_groups();
+
+        if (!is_array($contact_ids))
+            $contact_ids = explode(',', $contact_ids);
 
         $base_dn     = $this->groups_base_dn;
 
         $base_dn     = $this->groups_base_dn;
-        $group_name  = $this->group_cache[$group_id]['name'];
-        $member_attr = $this->prop['member_attr'];
+        $group_name  = $group_cache[$group_id]['name'];
+        $member_attr = $group_cache[$group_id]['member_attr'];
         $group_dn    = "cn=$group_name,$base_dn";
 
         $new_attrs = array();
         $group_dn    = "cn=$group_name,$base_dn";
 
         $new_attrs = array();
-        foreach (explode(",", $contact_ids) as $id)
+        foreach ($contact_ids as $id)
             $new_attrs[$member_attr][] = self::dn_decode($id);
 
         $this->_debug("C: Add [dn: $group_dn]: ".print_r($new_attrs, true));
             $new_attrs[$member_attr][] = self::dn_decode($id);
 
         $this->_debug("C: Add [dn: $group_dn]: ".print_r($new_attrs, true));
@@ -1271,6 +1723,7 @@ class rcube_ldap extends rcube_addressbook
         }
 
         $this->_debug("S: OK");
         }
 
         $this->_debug("S: OK");
+        $this->cache->remove('groups');
 
         return count($new_attrs['member']);
     }
 
         return count($new_attrs['member']);
     }
@@ -1284,12 +1737,12 @@ class rcube_ldap extends rcube_addressbook
      */
     function remove_from_group($group_id, $contact_ids)
     {
      */
     function remove_from_group($group_id, $contact_ids)
     {
-        if (!$this->group_cache)
-            $this->list_groups();
+        if (($group_cache = $this->cache->get('groups')) === null)
+            $group_cache = $this->_fetch_groups();
 
         $base_dn     = $this->groups_base_dn;
 
         $base_dn     = $this->groups_base_dn;
-        $group_name  = $this->group_cache[$group_id]['name'];
-        $member_attr = $this->prop['member_attr'];
+        $group_name  = $group_cache[$group_id]['name'];
+        $member_attr = $group_cache[$group_id]['member_attr'];
         $group_dn    = "cn=$group_name,$base_dn";
 
         $del_attrs = array();
         $group_dn    = "cn=$group_name,$base_dn";
 
         $del_attrs = array();
@@ -1307,6 +1760,7 @@ class rcube_ldap extends rcube_addressbook
         }
 
         $this->_debug("S: OK");
         }
 
         $this->_debug("S: OK");
+        $this->cache->remove('groups');
 
         return count($del_attrs['member']);
     }
 
         return count($del_attrs['member']);
     }
@@ -1326,12 +1780,16 @@ class rcube_ldap extends rcube_addressbook
 
         $base_dn     = $this->groups_base_dn;
         $contact_dn  = self::dn_decode($contact_id);
 
         $base_dn     = $this->groups_base_dn;
         $contact_dn  = self::dn_decode($contact_id);
+        $name_attr   = $this->prop['groups']['name_attr'];
         $member_attr = $this->prop['member_attr'];
         $member_attr = $this->prop['member_attr'];
-        $filter      = strtr("($member_attr=$contact_dn)", array('\\' => '\\\\'));
+        $add_filter  = '';
+        if ($member_attr != 'member' && $member_attr != 'uniqueMember')
+            $add_filter = "($member_attr=$contact_dn)";
+        $filter = strtr("(|(member=$contact_dn)(uniqueMember=$contact_dn)$add_filter)", array('\\' => '\\\\'));
 
         $this->_debug("C: Search [$filter][dn: $base_dn]");
 
 
         $this->_debug("C: Search [$filter][dn: $base_dn]");
 
-        $res = @ldap_search($this->conn, $base_dn, $filter, array('cn'));
+        $res = @ldap_search($this->conn, $base_dn, $filter, array($name_attr));
         if ($res === false)
         {
             $this->_debug("S: ".ldap_error($this->conn));
         if ($res === false)
         {
             $this->_debug("S: ".ldap_error($this->conn));
@@ -1343,7 +1801,7 @@ class rcube_ldap extends rcube_addressbook
         $groups = array();
         for ($i=0; $i<$ldap_data["count"]; $i++)
         {
         $groups = array();
         for ($i=0; $i<$ldap_data["count"]; $i++)
         {
-            $group_name = $ldap_data[$i]['cn'][0];
+            $group_name = $ldap_data[$i][$name_attr][0];
             $group_id = self::dn_encode($group_name);
             $groups[$group_id] = $group_id;
         }
             $group_id = self::dn_encode($group_name);
             $groups[$group_id] = $group_id;
         }
@@ -1358,17 +1816,23 @@ class rcube_ldap extends rcube_addressbook
      * @param integer Records per page
      * @return string BER encoded option value
      */
      * @param integer Records per page
      * @return string BER encoded option value
      */
-    private function _vlv_ber_encode($offset, $rpp)
+    private function _vlv_ber_encode($offset, $rpp, $search = '')
     {
         # this string is ber-encoded, php will prefix this value with:
         # 04 (octet string) and 10 (length of 16 bytes)
         # the code behind this string is broken down as follows:
         # 30 = ber sequence with a length of 0e (14) bytes following
     {
         # this string is ber-encoded, php will prefix this value with:
         # 04 (octet string) and 10 (length of 16 bytes)
         # the code behind this string is broken down as follows:
         # 30 = ber sequence with a length of 0e (14) bytes following
-        # 20 = type integer (in two's complement form) with 2 bytes following (beforeCount): 01 00 (ie 0)
-        # 20 = type integer (in two's complement form) with 2 bytes following (afterCount):  01 18 (ie 25-1=24)
+        # 02 = type integer (in two's complement form) with 2 bytes following (beforeCount): 01 00 (ie 0)
+        # 02 = type integer (in two's complement form) with 2 bytes following (afterCount):  01 18 (ie 25-1=24)
         # a0 = type context-specific/constructed with a length of 06 (6) bytes following
         # a0 = type context-specific/constructed with a length of 06 (6) bytes following
-        # 20 = type integer with 2 bytes following (offset): 01 01 (ie 1)
-        # 20 = type integer with 2 bytes following (contentCount):  01 00
+        # 02 = type integer with 2 bytes following (offset): 01 01 (ie 1)
+        # 02 = type integer with 2 bytes following (contentCount):  01 00
+        
+        # whith a search string present:
+        # 81 = type context-specific/constructed with a length of 04 (4) bytes following (the length will change here)
+        # 81 indicates a user string is present where as a a0 indicates just a offset search
+        # 81 = type context-specific/constructed with a length of 06 (6) bytes following
+        
         # the following info was taken from the ISO/IEC 8825-1:2003 x.690 standard re: the
         # encoding of integer values (note: these values are in
         # two-complement form so since offset will never be negative bit 8 of the
         # the following info was taken from the ISO/IEC 8825-1:2003 x.690 standard re: the
         # encoding of integer values (note: these values are in
         # two-complement form so since offset will never be negative bit 8 of the
@@ -1378,20 +1842,29 @@ class rcube_ldap extends rcube_addressbook
         # of the second (to the left of first octet) octet:
         # a) shall not all be ones; and
         # b) shall not all be zero
         # of the second (to the left of first octet) octet:
         # a) shall not all be ones; and
         # b) shall not all be zero
+        
+        if ($search)
+        {
+            $search = preg_replace('/[^-[:alpha:] ,.()0-9]+/', '', $search);
+            $ber_val = self::_string2hex($search);
+            $str = self::_ber_addseq($ber_val, '81');
+        }
+        else
+        {
+            # construct the string from right to left
+            $str = "020100"; # contentCount
 
 
-        # construct the string from right to left
-        $str = "020100"; # contentCount
-
-        $ber_val = self::_ber_encode_int($offset);  // returns encoded integer value in hex format
-
-        // calculate octet length of $ber_val
-        $str = self::_ber_addseq($ber_val, '02') . $str;
+            $ber_val = self::_ber_encode_int($offset);  // returns encoded integer value in hex format
 
 
-        // now compute length over $str
-        $str = self::_ber_addseq($str, 'a0');
+            // calculate octet length of $ber_val
+            $str = self::_ber_addseq($ber_val, '02') . $str;
 
 
+            // now compute length over $str
+            $str = self::_ber_addseq($str, 'a0');
+        }
+        
         // now tack on records per page
         // now tack on records per page
-        $str = sprintf("0201000201%02x", min(255, $rpp)-1) . $str;
+        $str = "020100" . self::_ber_addseq(self::_ber_encode_int($rpp-1), '02') . $str;
 
         // now tack on sequence identifier and length
         $str = self::_ber_addseq($str, '30');
 
         // now tack on sequence identifier and length
         $str = self::_ber_addseq($str, '30');
index e44826e956980134b54eabce2e9f8d24ee38f2f2..f25acef4df04f6f14e2fa1c6ea7e22239e74e538 100644 (file)
@@ -16,7 +16,7 @@
  | Author: Lukas Kahwe Smith <smith@pooteeweet.org>                      |
  +-----------------------------------------------------------------------+
 
  | Author: Lukas Kahwe Smith <smith@pooteeweet.org>                      |
  +-----------------------------------------------------------------------+
 
- $Id: rcube_mdb2.php 4810 2011-05-27 11:02:51Z alec $
+ $Id: rcube_mdb2.php 5543 2011-12-05 07:24:36Z alec $
 
 */
 
 
 */
 
  */
 class rcube_mdb2
 {
  */
 class rcube_mdb2
 {
-    var $db_dsnw;               // DSN for write operations
-    var $db_dsnr;               // DSN for read operations
-    var $db_connected = false;  // Already connected ?
-    var $db_mode = '';          // Connection mode
-    var $db_handle = 0;         // Connection handle
-    var $db_error = false;
-    var $db_error_msg = '';
+    public $db_dsnw;               // DSN for write operations
+    public $db_dsnr;               // DSN for read operations
+    public $db_connected = false;  // Already connected ?
+    public $db_mode = '';          // Connection mode
+    public $db_handle = 0;         // Connection handle
+    public $db_error = false;
+    public $db_error_msg = '';
 
     private $debug_mode = false;
 
     private $debug_mode = false;
-    private $write_failure = false;
+    private $conn_failure = false;
     private $a_query_results = array('dummy');
     private $last_res_id = 0;
     private $tables;
     private $a_query_results = array('dummy');
     private $last_res_id = 0;
     private $tables;
@@ -58,7 +58,7 @@ class rcube_mdb2
      */
     function __construct($db_dsnw, $db_dsnr='', $pconn=false)
     {
      */
     function __construct($db_dsnw, $db_dsnr='', $pconn=false)
     {
-        if ($db_dsnr == '')
+        if (empty($db_dsnr))
             $db_dsnr = $db_dsnw;
 
         $this->db_dsnw = $db_dsnw;
             $db_dsnr = $db_dsnw;
 
         $this->db_dsnw = $db_dsnw;
@@ -91,6 +91,8 @@ class rcube_mdb2
             $db_options['disable_smart_seqname'] = true;
             $db_options['seqname_format'] = '%s';
         }
             $db_options['disable_smart_seqname'] = true;
             $db_options['seqname_format'] = '%s';
         }
+        $this->db_error     = false;
+        $this->db_error_msg = null;
 
         $dbh = MDB2::connect($dsn, $db_options);
 
 
         $dbh = MDB2::connect($dsn, $db_options);
 
@@ -122,30 +124,40 @@ class rcube_mdb2
      */
     function db_connect($mode)
     {
      */
     function db_connect($mode)
     {
+        // previous connection failed, don't attempt to connect again
+        if ($this->conn_failure) {
+            return;
+        }
+
+        // no replication
+        if ($this->db_dsnw == $this->db_dsnr) {
+            $mode = 'w';
+        }
+
         // Already connected
         if ($this->db_connected) {
         // Already connected
         if ($this->db_connected) {
-            // connected to read-write db, current connection is ok
-            if ($this->db_mode == 'w' && !$this->write_failure)
-                return;
-
-            // no replication, current connection is ok for read and write
-            if (empty($this->db_dsnr) || $this->db_dsnw == $this->db_dsnr) {
-                $this->db_mode = 'w';
+            // connected to db with the same or "higher" mode
+            if ($this->db_mode == 'w' || $this->db_mode == $mode) {
                 return;
             }
                 return;
             }
-
-            // Same mode, current connection is ok
-            if ($this->db_mode == $mode)
-                return;
         }
 
         $dsn = ($mode == 'r') ? $this->db_dsnr : $this->db_dsnw;
 
         }
 
         $dsn = ($mode == 'r') ? $this->db_dsnr : $this->db_dsnw;
 
-        $this->db_handle = $this->dsn_connect($dsn);
+        $this->db_handle    = $this->dsn_connect($dsn);
         $this->db_connected = !PEAR::isError($this->db_handle);
 
         $this->db_connected = !PEAR::isError($this->db_handle);
 
+        // use write-master when read-only fails
+        if (!$this->db_connected && $mode == 'r') {
+            $mode = 'w';
+            $this->db_handle    = $this->dsn_connect($this->db_dsnw);
+            $this->db_connected = !PEAR::isError($this->db_handle);
+        }
+
         if ($this->db_connected)
         if ($this->db_connected)
-          $this->db_mode = $mode;
+            $this->db_mode = $mode;
+        else
+            $this->conn_failure = true;
     }
 
 
     }
 
 
@@ -256,10 +268,6 @@ class rcube_mdb2
         // Read or write ?
         $mode = (strtolower(substr(trim($query),0,6)) == 'select') ? 'r' : 'w';
 
         // Read or write ?
         $mode = (strtolower(substr(trim($query),0,6)) == 'select') ? 'r' : 'w';
 
-        // don't event attempt to connect if previous write-operation failed
-        if ($this->write_failure && $mode == 'w')
-            return false;
-
         $this->db_connect($mode);
 
         // check connection before proceeding
         $this->db_connect($mode);
 
         // check connection before proceeding
@@ -284,7 +292,7 @@ class rcube_mdb2
                 raise_error(array('code' => 500, 'type' => 'db',
                     'line' => __LINE__, 'file' => __FILE__,
                     'message' => $this->db_error_msg), true, false);
                 raise_error(array('code' => 500, 'type' => 'db',
                     'line' => __LINE__, 'file' => __FILE__,
                     'message' => $this->db_error_msg), true, false);
-                
+
                 $result = false;
             }
             else {
                 $result = false;
             }
             else {
@@ -293,10 +301,6 @@ class rcube_mdb2
             }
         }
 
             }
         }
 
-        // remember that write-operation failed
-        if ($mode == 'w' && ($result === false || PEAR::isError($result)))
-            $this->write_failure = true;
-
         // add result, even if it's an error
         return $this->_add_result($result);
     }
         // add result, even if it's an error
         return $this->_add_result($result);
     }
@@ -447,7 +451,7 @@ class rcube_mdb2
         if (!PEAR::isError($result = $this->db_handle->listTableFields($table))) {
             return $result;
         }
         if (!PEAR::isError($result = $this->db_handle->listTableFields($table))) {
             return $result;
         }
-        
+
         return null;
     }
 
         return null;
     }
 
@@ -530,7 +534,7 @@ class rcube_mdb2
      */
     function now()
     {
      */
     function now()
     {
-        switch($this->db_provider) {
+        switch ($this->db_provider) {
             case 'mssql':
             case 'sqlsrv':
                 return "getdate()";
             case 'mssql':
             case 'sqlsrv':
                 return "getdate()";
index 667657b5e9d925b15bb7778837f3854f6c26276e..05ae2b1396a0cb2d01132a26a2e3309b2e2ea606 100644 (file)
@@ -15,7 +15,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: rcube_message.php 5261 2011-09-21 12:22:40Z alec $
+ $Id: rcube_message.php 5514 2011-11-30 11:35:43Z alec $
 
 */
 
 
 */
 
@@ -48,7 +48,6 @@ class rcube_message
 
     public $uid = null;
     public $headers;
 
     public $uid = null;
     public $headers;
-    public $structure;
     public $parts = array();
     public $mime_parts = array();
     public $attachments = array();
     public $parts = array();
     public $mime_parts = array();
     public $attachments = array();
@@ -77,7 +76,7 @@ class rcube_message
         $this->imap->get_all_headers = true;
 
         $this->uid = $uid;
         $this->imap->get_all_headers = true;
 
         $this->uid = $uid;
-        $this->headers = $this->imap->get_headers($uid, NULL, true, true);
+        $this->headers = $this->imap->get_message($uid);
 
         if (!$this->headers)
             return;
 
         if (!$this->headers)
             return;
@@ -94,9 +93,9 @@ class rcube_message
                 '_mbox' => $this->imap->get_mailbox_name(), '_uid' => $uid))
         );
 
                 '_mbox' => $this->imap->get_mailbox_name(), '_uid' => $uid))
         );
 
-        if ($this->structure = $this->imap->get_structure($uid, $this->headers->body_structure)) {
-            $this->get_mime_numbers($this->structure);
-            $this->parse_structure($this->structure);
+        if (!empty($this->headers->structure)) {
+            $this->get_mime_numbers($this->headers->structure);
+            $this->parse_structure($this->headers->structure);
         }
         else {
             $this->body = $this->imap->get_body($uid);
         }
         else {
             $this->body = $this->imap->get_body($uid);
@@ -143,10 +142,10 @@ class rcube_message
      * @param string $mime_id Part MIME-ID
      * @return string URL or false if part does not exist
      */
      * @param string $mime_id Part MIME-ID
      * @return string URL or false if part does not exist
      */
-    public function get_part_url($mime_id)
+    public function get_part_url($mime_id, $embed = false)
     {
         if ($this->mime_parts[$mime_id])
     {
         if ($this->mime_parts[$mime_id])
-            return $this->opt['get_url'] . '&_part=' . $mime_id;
+            return $this->opt['get_url'] . '&_part=' . $mime_id . ($embed ? '&_embed=1' : '');
         else
             return false;
     }
         else
             return false;
     }
@@ -299,8 +298,10 @@ class rcube_message
             $structure->type = 'content';
             $this->parts[] = &$structure;
         }
             $structure->type = 'content';
             $this->parts[] = &$structure;
         }
-        // message contains alternative parts
-        else if ($mimetype == 'multipart/alternative' && is_array($structure->parts)) {
+        // message contains (more than one!) alternative parts
+        else if ($mimetype == 'multipart/alternative'
+            && is_array($structure->parts) && count($structure->parts) > 1
+        ) {
             // get html/plaintext parts
             $plain_part = $html_part = $print_part = $related_part = null;
 
             // get html/plaintext parts
             $plain_part = $html_part = $print_part = $related_part = null;
 
@@ -510,7 +511,7 @@ class rcube_message
                 $img_regexp = '/^image\/(gif|jpe?g|png|tiff|bmp|svg)/';
 
                 foreach ($this->inline_parts as $inline_object) {
                 $img_regexp = '/^image\/(gif|jpe?g|png|tiff|bmp|svg)/';
 
                 foreach ($this->inline_parts as $inline_object) {
-                    $part_url = $this->get_part_url($inline_object->mime_id);
+                    $part_url = $this->get_part_url($inline_object->mime_id, true);
                     if ($inline_object->content_id)
                         $a_replaces['cid:'.$inline_object->content_id] = $part_url;
                     if ($inline_object->content_location) {
                     if ($inline_object->content_id)
                         $a_replaces['cid:'.$inline_object->content_id] = $part_url;
                     if ($inline_object->content_location) {
index de283d24619a68bb87423b2f4d49eceebdff6813..ed28af31f0cb6f54e62bfd0adedae47ab4b4be37 100644 (file)
@@ -1,77 +1,7 @@
-<?php
 
 
-
-/*
- +-----------------------------------------------------------------------+
- | program/include/rcube_mime_struct.php                                 |
- |                                                                       |
- | This file is part of the Roundcube Webmail client                     |
- | Copyright (C) 2005-2011, The Roundcube Dev Team                       |
- | Licensed under the GNU GPL                                            |
- |                                                                       |
- | PURPOSE:                                                              |
- |   Provide functions for handling mime messages structure              |
- |                                                                       |
- |   Based on Iloha MIME Library. See http://ilohamail.org/ for details  |
- |                                                                       |
- +-----------------------------------------------------------------------+
- | Author: Aleksander Machniak <alec@alec.pl>                            |
- | Author: Ryo Chijiiwa <Ryo@IlohaMail.org>                              |
- +-----------------------------------------------------------------------+
-
- $Id: rcube_mime_struct.php 4980 2011-07-27 18:21:49Z alec $
-
-*/
-
-/**
- * Helper class to process IMAP's BODYSTRUCTURE string
- *
- * @package    Mail
- * @author     Aleksander Machniak <alec@alec.pl>
- */
-class rcube_mime_struct
-{
-    private $structure;
-
-
-    function __construct($str=null)
-    {
-        if ($str)
-            $this->structure = $this->parseStructure($str);
-    }
-
-    /*
-     * Parses IMAP's BODYSTRUCTURE string into array
-    */
-    function parseStructure($str)
-    {
-        $line = substr($str, 1, strlen($str) - 2);
-        $line = str_replace(')(', ') (', $line);
-
-           $struct = rcube_imap_generic::tokenizeResponse($line);
-       if (!is_array($struct[0]) && (strcasecmp($struct[0], 'message') == 0)
-                   && (strcasecmp($struct[1], 'rfc822') == 0)) {
-                   $struct = array($struct);
-           }
-
-        return $struct;
-    }
-
-    /*
-     * Parses IMAP's BODYSTRUCTURE string into array and loads it into class internal variable
-    */
-    function loadStructure($str)
+    function getStructurePartType($structure, $part)
     {
     {
-        if (empty($str))
-            return true;
-
-        $this->structure = $this->parseStructure($str);
-        return (!empty($this->structure));
-    }
-
-    function getPartType($part)
-    {
-           $part_a = $this->getPartArray($this->structure, $part);
+           $part_a = self::getPartArray($structure, $part);
            if (!empty($part_a)) {
                    if (is_array($part_a[0]))
                 return 'multipart';
            if (!empty($part_a)) {
                    if (is_array($part_a[0]))
                 return 'multipart';
@@ -82,9 +12,9 @@ class rcube_mime_struct
         return 'other';
     }
 
         return 'other';
     }
 
-    function getPartEncoding($part)
+    function getStructurePartEncoding($structure, $part)
     {
     {
-           $part_a = $this->getPartArray($this->structure, $part);
+           $part_a = self::getPartArray($structure, $part);
            if ($part_a) {
                    if (!is_array($part_a[0]))
                 return $part_a[5];
            if ($part_a) {
                    if (!is_array($part_a[0]))
                 return $part_a[5];
@@ -93,9 +23,9 @@ class rcube_mime_struct
         return '';
     }
 
         return '';
     }
 
-    function getPartCharset($part)
+    function getStructurePartCharset($structure, $part)
     {
     {
-           $part_a = $this->getPartArray($this->structure, $part);
+           $part_a = self::getPartArray($structure, $part);
            if ($part_a) {
                    if (is_array($part_a[0]))
                 return '';
            if ($part_a) {
                    if (is_array($part_a[0]))
                 return '';
@@ -112,7 +42,7 @@ class rcube_mime_struct
         return '';
     }
 
         return '';
     }
 
-    function getPartArray($a, $part)
+    function getStructurePartArray($a, $part)
     {
            if (!is_array($a)) {
             return false;
     {
            if (!is_array($a)) {
             return false;
@@ -137,9 +67,7 @@ class rcube_mime_struct
                    else
                 return $a;
            }
                    else
                 return $a;
            }
-        else if (($part==0) || (empty($part))) {
+        else if (($part == 0) || (empty($part))) {
                    return $a;
            }
     }
                    return $a;
            }
     }
-
-}
index c75a17cb4aab17790408eff339cc2772dce082ed..748d958e8ed1cb98eac1b73d778ef82f3178f2be 100644 (file)
@@ -15,7 +15,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: rcube_plugin.php 4870 2011-06-21 09:10:14Z alec $
+ $Id: rcube_plugin.php 5168 2011-09-05 11:08:48Z alec $
 
 */
 
 
 */
 
@@ -147,8 +147,11 @@ abstract class rcube_plugin
     ob_start();
 
     foreach (array('en_US', $lang) as $lng) {
     ob_start();
 
     foreach (array('en_US', $lang) as $lng) {
-      @include($locdir . $lng . '.inc');
-      $texts = (array)$labels + (array)$messages + (array)$texts;
+      $fpath = $locdir . $lng . '.inc';
+      if (is_file($fpath) && is_readable($fpath)) {
+        include($fpath);
+        $texts = (array)$labels + (array)$messages + (array)$texts;
+      }
     }
 
     ob_end_clean();
     }
 
     ob_end_clean();
index 6fa566b724a6a3a498c0405a6689c1b56047fa4e..e762fff0816ee16dcd9b3680f06205d62a4876c0 100644 (file)
@@ -15,7 +15,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: rcube_plugin_api.php 5151 2011-08-31 12:49:44Z alec $
+ $Id: rcube_plugin_api.php 5207 2011-09-12 12:52:01Z alec $
 
 */
 
 
 */
 
@@ -421,6 +421,17 @@ class rcube_plugin_api
   }
 
 
   }
 
 
+  /**
+   * Returns list of loaded plugins names
+   *
+   * @return array List of plugin names
+   */
+  public function loaded_plugins()
+  {
+    return array_keys($this->plugins);
+  }
+
+
   /**
    * Callback for template_container hooks
    *
   /**
    * Callback for template_container hooks
    *
index cf023d6363946b46849e34174a9528d95667ab59..e4a4ad4f3fd077950809de94d8bb4e34eee82a5c 100644 (file)
@@ -5,7 +5,7 @@
  | program/include/rcube_result_set.php                                  |
  |                                                                       |
  | This file is part of the Roundcube Webmail client                     |
  | program/include/rcube_result_set.php                                  |
  |                                                                       |
  | This file is part of the Roundcube Webmail client                     |
- | Copyright (C) 2006-2010, The Roundcube Dev Team                       |
+ | Copyright (C) 2006-2011, The Roundcube Dev Team                       |
  | Licensed under the GNU GPL                                            |
  |                                                                       |
  | PURPOSE:                                                              |
  | Licensed under the GNU GPL                                            |
  |                                                                       |
  | PURPOSE:                                                              |
@@ -15,7 +15,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: rcube_result_set.php 4834 2011-06-03 11:03:13Z alec $
+ $Id: rcube_result_set.php 5258 2011-09-21 11:17:46Z thomasb $
 
 */
 
 
 */
 
@@ -31,6 +31,7 @@ class rcube_result_set
     var $count = 0;
     var $first = 0;
     var $current = 0;
     var $count = 0;
     var $first = 0;
     var $current = 0;
+    var $searchonly = false;
     var $records = array();
 
 
     var $records = array();
 
 
index 01b93670cfe93a9943a574ef18191f94d015e276..bd0ce60e46f2eb2d948a0a0d3af1ce06b157f04b 100644 (file)
@@ -6,6 +6,7 @@
  |                                                                       |
  | This file is part of the Roundcube Webmail client                     |
  | Copyright (C) 2005-2011, The Roundcube Dev Team                       |
  |                                                                       |
  | This file is part of the Roundcube Webmail client                     |
  | Copyright (C) 2005-2011, The Roundcube Dev Team                       |
+ | Copyright (C) 2011, Kolab Systems AG                                  |
  | Licensed under the GNU GPL                                            |
  |                                                                       |
  | PURPOSE:                                                              |
  | Licensed under the GNU GPL                                            |
  |                                                                       |
  | PURPOSE:                                                              |
@@ -330,20 +331,7 @@ class rcube_session
   public function gc()
   {
     foreach ($this->gc_handlers as $fct)
   public function gc()
   {
     foreach ($this->gc_handlers as $fct)
-      $fct();
-  }
-
-
-  /**
-   * Cleanup session data before saving
-   */
-  public function cleanup()
-  {
-    // current compose information is stored in $_SESSION['compose'], move it to $_SESSION['compose_data_<ID>']
-    if ($compose_id = $_SESSION['compose']['id']) {
-      $_SESSION['compose_data_'.$compose_id] = $_SESSION['compose'];
-      $this->remove('compose');
-    }
+      call_user_func($fct);
   }
 
 
   }
 
 
@@ -403,6 +391,21 @@ class rcube_session
   }
 
 
   }
 
 
+  /**
+   * Re-read session data from storage backend
+   */
+  public function reload()
+  {
+    if ($this->key && $this->memcache)
+      $data = $this->mc_read($this->key);
+    else if ($this->key)
+      $data = $this->db_read($this->key);
+
+    if ($data)
+     session_decode($data);
+  }
+
+
   /**
    * Serialize session data
    */
   /**
    * Serialize session data
    */
index 3cd96c915108bc2e3e0dfb18469cbd6d6cfa966b..6e58ad86982c5293ae05d48ac77e1dd351a16403 100644 (file)
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: rcube_shared.inc 4710 2011-04-29 08:17:42Z alec $
+ $Id: rcube_shared.inc 5274 2011-09-23 10:11:27Z alec $
 
 */
 
 
 /**
  * Roundcube shared functions
 
 */
 
 
 /**
  * Roundcube shared functions
- * 
+ *
  * @package Core
  */
 
  * @package Core
  */
 
@@ -69,50 +69,6 @@ function send_future_expire_header($offset=2600000)
 }
 
 
 }
 
 
-/**
- * Check request for If-Modified-Since and send an according response.
- * This will terminate the current script if headers match the given values
- *
- * @param int Modified date as unix timestamp
- * @param string Etag value for caching
- */
-function send_modified_header($mdate, $etag=null, $skip_check=false)
-{
-  if (headers_sent())
-    return;
-    
-  $iscached = false;
-  $etag = $etag ? "\"$etag\"" : null;
-
-  if (!$skip_check)
-  {
-    if ($_SERVER['HTTP_IF_MODIFIED_SINCE'] && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $mdate)
-      $iscached = true;
-  
-    if ($etag)
-      $iscached = ($_SERVER['HTTP_IF_NONE_MATCH'] == $etag);
-  }
-  
-  if ($iscached)
-    header("HTTP/1.x 304 Not Modified");
-  else
-    header("Last-Modified: ".gmdate("D, d M Y H:i:s", $mdate)." GMT");
-  
-  header("Cache-Control: private, must-revalidate, max-age=0");
-  header("Expires: ");
-  header("Pragma: ");
-  
-  if ($etag)
-    header("Etag: $etag");
-  
-  if ($iscached)
-    {
-    ob_end_clean();
-    exit;
-    }
-}
-
-
 /**
  * Similar function as in_array() but case-insensitive
  *
 /**
  * Similar function as in_array() but case-insensitive
  *
@@ -126,7 +82,7 @@ function in_array_nocase($needle, $haystack)
   foreach ($haystack as $value)
     if ($needle===mb_strtolower($value))
       return true;
   foreach ($haystack as $value)
     if ($needle===mb_strtolower($value))
       return true;
-  
+
   return false;
 }
 
   return false;
 }
 
@@ -218,7 +174,7 @@ function make_absolute_url($path, $base_url)
 {
   $host_url = $base_url;
   $abs_path = $path;
 {
   $host_url = $base_url;
   $abs_path = $path;
-  
+
   // check if path is an absolute URL
   if (preg_match('/^[fhtps]+:\/\//', $path))
     return $path;
   // check if path is an absolute URL
   if (preg_match('/^[fhtps]+:\/\//', $path))
     return $path;
@@ -325,7 +281,7 @@ function rc_request_header($name)
   }
 
   return $hdrs[$key];
   }
 
   return $hdrs[$key];
-  }
+}
 
 
 /**
 
 
 /**
@@ -344,7 +300,7 @@ function unslashify($str)
 {
   return preg_replace('/\/$/', '', $str);
 }
 {
   return preg_replace('/\/$/', '', $str);
 }
-  
+
 
 /**
  * Delete all files within a folder
 
 /**
  * Delete all files within a folder
@@ -374,7 +330,7 @@ function clear_directory($dir_path)
  * @return int Unix timestamp
  */
 function get_offset_time($offset_str, $factor=1)
  * @return int Unix timestamp
  */
 function get_offset_time($offset_str, $factor=1)
-  {
+{
   if (preg_match('/^([0-9]+)\s*([smhdw])/i', $offset_str, $regs))
   {
     $amount = (int)$regs[1];
   if (preg_match('/^([0-9]+)\s*([smhdw])/i', $offset_str, $regs))
   {
     $amount = (int)$regs[1];
@@ -385,7 +341,7 @@ function get_offset_time($offset_str, $factor=1)
     $amount = (int)$offset_str;
     $unit = 's';
   }
     $amount = (int)$offset_str;
     $unit = 's';
   }
-    
+
   $ts = mktime();
   switch ($unit)
   {
   $ts = mktime();
   switch ($unit)
   {
@@ -418,7 +374,7 @@ function get_offset_time($offset_str, $factor=1)
 function abbreviate_string($str, $maxlength, $place_holder='...', $ending=false)
 {
   $length = mb_strlen($str);
 function abbreviate_string($str, $maxlength, $place_holder='...', $ending=false)
 {
   $length = mb_strlen($str);
-  
+
   if ($length > $maxlength)
   {
     if ($ending)
   if ($length > $maxlength)
   {
     if ($ending)
@@ -433,6 +389,7 @@ function abbreviate_string($str, $maxlength, $place_holder='...', $ending=false)
   return $str;
 }
 
   return $str;
 }
 
+
 /**
  * A method to guess the mime_type of an attachment.
  *
 /**
  * A method to guess the mime_type of an attachment.
  *
@@ -547,7 +504,7 @@ function rc_utf8_clean($input)
       $input[$idx] = rc_utf8_clean($val);
     return $input;
   }
       $input[$idx] = rc_utf8_clean($val);
     return $input;
   }
-  
+
   if (!is_string($input) || $input == '')
     return $input;
 
   if (!is_string($input) || $input == '')
     return $input;
 
@@ -569,7 +526,7 @@ function rc_utf8_clean($input)
     '|[\xF1-\xF3][\x80-\xBF][\x80-\xBF][\x80-\xBF]'.// UTF8-4
     '|\xF4[\x80-\x8F][\x80-\xBF][\x80-\xBF]'.       // UTF8-4
     ')$/';
     '|[\xF1-\xF3][\x80-\xBF][\x80-\xBF][\x80-\xBF]'.// UTF8-4
     '|\xF4[\x80-\x8F][\x80-\xBF][\x80-\xBF]'.       // UTF8-4
     ')$/';
-  
+
   $seq = '';
   $out = '';
 
   $seq = '';
   $out = '';
 
@@ -640,7 +597,7 @@ function rcube_explode_quoted_string($delimiter, $string)
       $p = $i + 1;
     }
   }
       $p = $i + 1;
     }
   }
-  
+
   $result[] = substr($string, $p);
   return $result;
 }
   $result[] = substr($string, $p);
   return $result;
 }
@@ -655,7 +612,7 @@ function rcube_explode_quoted_string($delimiter, $string)
 function array_keys_recursive($array)
 {
   $keys = array();
 function array_keys_recursive($array)
 {
   $keys = array();
-  
+
   if (!empty($array))
     foreach ($array as $key => $child) {
       $keys[] = $key;
   if (!empty($array))
     foreach ($array as $key => $child) {
       $keys[] = $key;
index 28df53ba5bad5fdab43cf5d0eae517328fd5e399..8c668c0a4b03fb46f1a08d57051ba7783f262f96 100644 (file)
@@ -15,7 +15,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: rcube_smtp.php 5033 2011-08-09 09:46:54Z alec $
+ $Id: rcube_smtp.php 5499 2011-11-28 09:03:27Z alec $
 
 */
 
 
 */
 
@@ -214,14 +214,10 @@ class rcube_smtp
     if ($opts['dsn']) {
       $exts = $this->conn->getServiceExtensions();
 
     if ($opts['dsn']) {
       $exts = $this->conn->getServiceExtensions();
 
-      if (!isset($exts['DSN'])) {
-        $this->error = array('label' => 'smtpdsnerror');
-        $this->response[] = "DSN not supported";
-        return false;
+      if (isset($exts['DSN'])) {
+        $from_params      = 'RET=HDRS';
+        $recipient_params = 'NOTIFY=SUCCESS,FAILURE';
       }
       }
-
-      $from_params      = 'RET=HDRS';
-      $recipient_params = 'NOTIFY=SUCCESS,FAILURE';
     }
 
     // RFC2298.3: remove envelope sender address
     }
 
     // RFC2298.3: remove envelope sender address
@@ -385,7 +381,7 @@ class rcube_smtp
           $from = $addresses[0];
 
         // Reject envelope From: addresses with spaces.
           $from = $addresses[0];
 
         // Reject envelope From: addresses with spaces.
-        if (strstr($from, ' '))
+        if (strpos($from, ' ') !== false)
           return false;
 
         $lines[] = $key . ': ' . $value;
           return false;
 
         $lines[] = $key . ': ' . $value;
index 804622321b053fabb119ce70a5e6625a6abe9fc5..3b565c3632ab6252a44ff19ed3100a3027623a01 100644 (file)
@@ -17,7 +17,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: rcube_spellchecker.php 4817 2011-05-30 17:08:47Z alec $
+ $Id: rcube_spellchecker.php 5181 2011-09-06 13:39:45Z alec $
 
 */
 
 
 */
 
@@ -34,8 +34,11 @@ class rcube_spellchecker
     private $lang;
     private $rc;
     private $error;
     private $lang;
     private $rc;
     private $error;
-    private $separator = '/[ !"#$%&()*+\\,\/\n:;<=>?@\[\]^_{|}-]+|\.[^\w]/';
-    
+    private $separator = '/[\s\r\n\t\(\)\/\[\]{}<>\\"]+|[:;?!,\.]([^\w]|$)/';
+    private $options = array();
+    private $dict;
+    private $have_dict;
+
 
     // default settings
     const GOOGLE_HOST = 'ssl://www.google.com';
 
     // default settings
     const GOOGLE_HOST = 'ssl://www.google.com';
@@ -50,9 +53,9 @@ class rcube_spellchecker
      */
     function __construct($lang = 'en')
     {
      */
     function __construct($lang = 'en')
     {
-        $this->rc = rcmail::get_instance();
+        $this->rc     = rcmail::get_instance();
         $this->engine = $this->rc->config->get('spellcheck_engine', 'googie');
         $this->engine = $this->rc->config->get('spellcheck_engine', 'googie');
-        $this->lang = $lang ? $lang : 'en';
+        $this->lang   = $lang ? $lang : 'en';
 
         if ($this->engine == 'pspell' && !extension_loaded('pspell')) {
             raise_error(array(
 
         if ($this->engine == 'pspell' && !extension_loaded('pspell')) {
             raise_error(array(
@@ -60,6 +63,13 @@ class rcube_spellchecker
                 'file' => __FILE__, 'line' => __LINE__,
                 'message' => "Pspell extension not available"), true, true);
         }
                 'file' => __FILE__, 'line' => __LINE__,
                 'message' => "Pspell extension not available"), true, true);
         }
+
+        $this->options = array(
+            'ignore_syms' => $this->rc->config->get('spellcheck_ignore_syms'),
+            'ignore_nums' => $this->rc->config->get('spellcheck_ignore_nums'),
+            'ignore_caps' => $this->rc->config->get('spellcheck_ignore_caps'),
+            'dictionary'  => $this->rc->config->get('spellcheck_dictionary'),
+        );
     }
 
 
     }
 
 
@@ -71,7 +81,7 @@ class rcube_spellchecker
      *
      * @return bool True when no mispelling found, otherwise false
      */
      *
      * @return bool True when no mispelling found, otherwise false
      */
-    function check($text, $is_html=false)
+    function check($text, $is_html = false)
     {
         // convert to plain text
         if ($is_html) {
     {
         // convert to plain text
         if ($is_html) {
@@ -116,9 +126,9 @@ class rcube_spellchecker
             return $this->_pspell_suggestions($word);
         }
 
             return $this->_pspell_suggestions($word);
         }
 
-        return $this->_googie_suggestions($word);    
+        return $this->_googie_suggestions($word);
     }
     }
-    
+
 
     /**
      * Returns mispelled words
 
     /**
      * Returns mispelled words
@@ -179,7 +189,7 @@ class rcube_spellchecker
             $result[$word] = is_array($item[4]) ? implode("\t", $item[4]) : $item[4];
         }
 
             $result[$word] = is_array($item[4]) ? implode("\t", $item[4]) : $item[4];
         }
 
-        return $out;
+        return $result;
     }
 
 
     }
 
 
@@ -211,15 +221,18 @@ class rcube_spellchecker
         // tokenize
         $text = preg_split($this->separator, $text, NULL, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE);
 
         // tokenize
         $text = preg_split($this->separator, $text, NULL, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE);
 
-        $diff = 0;
-        $matches = array();
+        $diff       = 0;
+        $matches    = array();
 
         foreach ($text as $w) {
             $word = trim($w[0]);
             $pos  = $w[1] - $diff;
             $len  = mb_strlen($word);
 
 
         foreach ($text as $w) {
             $word = trim($w[0]);
             $pos  = $w[1] - $diff;
             $len  = mb_strlen($word);
 
-            if ($word && preg_match('/[^0-9\.]/', $word) && !pspell_check($this->plink, $word)) {
+            // skip exceptions
+            if ($this->is_exception($word)) {
+            }
+            else if (!pspell_check($this->plink, $word)) {
                 $suggestions = pspell_suggest($this->plink, $word);
 
                    if (sizeof($suggestions) > self::MAX_SUGGESTIONS)
                 $suggestions = pspell_suggest($this->plink, $word);
 
                    if (sizeof($suggestions) > self::MAX_SUGGESTIONS)
@@ -240,6 +253,8 @@ class rcube_spellchecker
      */
     private function _pspell_words($text = null, $is_html=false)
     {
      */
     private function _pspell_words($text = null, $is_html=false)
     {
+        $result = array();
+
         if ($text) {
             // init spellchecker
             $this->_pspell_init();
         if ($text) {
             // init spellchecker
             $this->_pspell_init();
@@ -257,7 +272,13 @@ class rcube_spellchecker
 
             foreach ($text as $w) {
                 $word = trim($w[0]);
 
             foreach ($text as $w) {
                 $word = trim($w[0]);
-                if ($word && preg_match('/[^0-9\.]/', $word) && !pspell_check($this->plink, $word)) {
+
+                // skip exceptions
+                if ($this->is_exception($word)) {
+                    continue;
+                }
+
+                if (!pspell_check($this->plink, $word)) {
                     $result[] = $word;
                 }
             }
                     $result[] = $word;
                 }
             }
@@ -265,8 +286,6 @@ class rcube_spellchecker
             return $result;
         }
 
             return $result;
         }
 
-        $result = array();
-
         foreach ($this->matches as $m) {
             $result[] = $m[0];
         }
         foreach ($this->matches as $m) {
             $result[] = $m[0];
         }
@@ -330,21 +349,21 @@ class rcube_spellchecker
         }
 
         // Google has some problem with spaces, use \n instead
         }
 
         // Google has some problem with spaces, use \n instead
-        $text = str_replace(' ', "\n", $text);
+        $gtext = str_replace(' ', "\n", $text);
 
 
-        $text = '<?xml version="1.0" encoding="utf-8" ?>'
+        $gtext = '<?xml version="1.0" encoding="utf-8" ?>'
             .'<spellrequest textalreadyclipped="0" ignoredups="0" ignoredigits="1" ignoreallcaps="1">'
             .'<spellrequest textalreadyclipped="0" ignoredups="0" ignoredigits="1" ignoreallcaps="1">'
-            .'<text>' . $text . '</text>'
+            .'<text>' . $gtext . '</text>'
             .'</spellrequest>';
 
         $store = '';
         if ($fp = fsockopen($host, $port, $errno, $errstr, 30)) {
             $out = "POST $path HTTP/1.0\r\n";
             $out .= "Host: " . str_replace('ssl://', '', $host) . "\r\n";
             .'</spellrequest>';
 
         $store = '';
         if ($fp = fsockopen($host, $port, $errno, $errstr, 30)) {
             $out = "POST $path HTTP/1.0\r\n";
             $out .= "Host: " . str_replace('ssl://', '', $host) . "\r\n";
-            $out .= "Content-Length: " . strlen($text) . "\r\n";
+            $out .= "Content-Length: " . strlen($gtext) . "\r\n";
             $out .= "Content-Type: application/x-www-form-urlencoded\r\n";
             $out .= "Connection: Close\r\n\r\n";
             $out .= "Content-Type: application/x-www-form-urlencoded\r\n";
             $out .= "Connection: Close\r\n\r\n";
-            $out .= $text;
+            $out .= $gtext;
             fwrite($fp, $out);
 
             while (!feof($fp))
             fwrite($fp, $out);
 
             while (!feof($fp))
@@ -358,6 +377,19 @@ class rcube_spellchecker
 
         preg_match_all('/<c o="([^"]*)" l="([^"]*)" s="([^"]*)">([^<]*)<\/c>/', $store, $matches, PREG_SET_ORDER);
 
 
         preg_match_all('/<c o="([^"]*)" l="([^"]*)" s="([^"]*)">([^<]*)<\/c>/', $store, $matches, PREG_SET_ORDER);
 
+        // skip exceptions (if appropriate options are enabled)
+        if (!empty($this->options['ignore_syms']) || !empty($this->options['ignore_nums'])
+            || !empty($this->options['ignore_caps']) || !empty($this->options['dictionary'])
+        ) {
+            foreach ($matches as $idx => $m) {
+                $word = mb_substr($text, $m[1], $m[2], RCMAIL_CHARSET);
+                // skip  exceptions
+                if ($this->is_exception($word)) {
+                    unset($matches[$idx]);
+                }
+            }
+        }
+
         return $matches;
     }
 
         return $matches;
     }
 
@@ -413,4 +445,172 @@ class rcube_spellchecker
         $h2t = new html2text($text, false, true, 0);
         return $h2t->get_text();
     }
         $h2t = new html2text($text, false, true, 0);
         return $h2t->get_text();
     }
+
+
+    /**
+     * Check if the specified word is an exception accoring to 
+     * spellcheck options.
+     *
+     * @param string  $word  The word
+     *
+     * @return bool True if the word is an exception, False otherwise
+     */
+    public function is_exception($word)
+    {
+        // Contain only symbols (e.g. "+9,0", "2:2")
+        if (!$word || preg_match('/^[0-9@#$%^&_+~*=:;?!,.-]+$/', $word))
+            return true;
+
+        // Contain symbols (e.g. "g@@gle"), all symbols excluding separators
+        if (!empty($this->options['ignore_syms']) && preg_match('/[@#$%^&_+~*=-]/', $word))
+            return true;
+
+        // Contain numbers (e.g. "g00g13")
+        if (!empty($this->options['ignore_nums']) && preg_match('/[0-9]/', $word))
+            return true;
+
+        // Blocked caps (e.g. "GOOGLE")
+        if (!empty($this->options['ignore_caps']) && $word == mb_strtoupper($word))
+            return true;
+
+        // Use exceptions from dictionary
+        if (!empty($this->options['dictionary'])) {
+            $this->load_dict();
+
+            // @TODO: should dictionary be case-insensitive?
+            if (!empty($this->dict) && in_array($word, $this->dict))
+                return true;
+        }
+
+        return false;
+    }
+
+
+    /**
+     * Add a word to dictionary
+     *
+     * @param string  $word  The word to add
+     */
+    public function add_word($word)
+    {
+        $this->load_dict();
+
+        foreach (explode(' ', $word) as $word) {
+            // sanity check
+            if (strlen($word) < 512) {
+                $this->dict[] = $word;
+                $valid = true;
+            }
+        }
+
+        if ($valid) {
+            $this->dict = array_unique($this->dict);
+            $this->update_dict();
+        }
+    }
+
+
+    /**
+     * Remove a word from dictionary
+     *
+     * @param string  $word  The word to remove
+     */
+    public function remove_word($word)
+    {
+        $this->load_dict();
+
+        if (($key = array_search($word, $this->dict)) !== false) {
+            unset($this->dict[$key]);
+            $this->update_dict();
+        }
+    }
+
+
+    /**
+     * Update dictionary row in DB
+     */
+    private function update_dict()
+    {
+        if (strcasecmp($this->options['dictionary'], 'shared') != 0) {
+            $userid = (int) $this->rc->user->ID;
+        }
+
+        $plugin = $this->rc->plugins->exec_hook('spell_dictionary_save', array(
+            'userid' => $userid, 'language' => $this->lang, 'dictionary' => $this->dict));
+
+        if (!empty($plugin['abort'])) {
+            return;
+        }
+
+        if ($this->have_dict) {
+            if (!empty($this->dict)) {
+                $this->rc->db->query(
+                    "UPDATE ".get_table_name('dictionary')
+                    ." SET data = ?"
+                    ." WHERE user_id " . ($plugin['userid'] ? "= ".$plugin['userid'] : "IS NULL")
+                        ." AND " . $this->rc->db->quoteIdentifier('language') . " = ?",
+                    implode(' ', $plugin['dictionary']), $plugin['language']);
+            }
+            // don't store empty dict
+            else {
+                $this->rc->db->query(
+                    "DELETE FROM " . get_table_name('dictionary')
+                    ." WHERE user_id " . ($plugin['userid'] ? "= ".$plugin['userid'] : "IS NULL")
+                        ." AND " . $this->rc->db->quoteIdentifier('language') . " = ?",
+                    $plugin['language']);
+            }
+        }
+        else if (!empty($this->dict)) {
+            $this->rc->db->query(
+                "INSERT INTO " .get_table_name('dictionary')
+                ." (user_id, " . $this->rc->db->quoteIdentifier('language') . ", data) VALUES (?, ?, ?)",
+                $plugin['userid'], $plugin['language'], implode(' ', $plugin['dictionary']));
+        }
+    }
+
+
+    /**
+     * Get dictionary from DB
+     */
+    private function load_dict()
+    {
+        if (is_array($this->dict)) {
+            return $this->dict;
+        }
+
+        if (strcasecmp($this->options['dictionary'], 'shared') != 0) {
+            $userid = (int) $this->rc->user->ID;
+        }
+
+        $plugin = $this->rc->plugins->exec_hook('spell_dictionary_get', array(
+            'userid' => $userid, 'language' => $this->lang, 'dictionary' => array()));
+
+        if (empty($plugin['abort'])) {
+            $dict = array();
+            $this->rc->db->query(
+                "SELECT data FROM ".get_table_name('dictionary')
+                ." WHERE user_id ". ($plugin['userid'] ? "= ".$plugin['userid'] : "IS NULL")
+                    ." AND " . $this->rc->db->quoteIdentifier('language') . " = ?",
+                $plugin['language']);
+
+            if ($sql_arr = $this->rc->db->fetch_assoc($sql_result)) {
+                $this->have_dict = true;
+                if (!empty($sql_arr['data'])) {
+                    $dict = explode(' ', $sql_arr['data']);
+                }
+            }
+
+            $plugin['dictionary'] = array_merge((array)$plugin['dictionary'], $dict);
+        }
+
+        if (!empty($plugin['dictionary']) && is_array($plugin['dictionary'])) {
+            $this->dict = $plugin['dictionary'];
+        }
+        else {
+            $this->dict = array();
+        }
+
+        return $this->dict;
+    }
+
 }
 }
index f753aa81f9e3358c5720eed0d81fbd24a21b95d6..b69e9cf50b8814afd6ebe3a5ec06777666957eaf 100644 (file)
@@ -15,7 +15,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: rcube_string_replacer.php 5203 2011-09-12 06:44:56Z alec $
+ $Id: rcube_string_replacer.php 5481 2011-11-24 07:53:00Z alec $
 
 */
 
 
 */
 
@@ -39,7 +39,7 @@ class rcube_string_replacer
     // Support unicode/punycode in top-level domain part
     $utf_domain = '[^?&@"\'\\/()\s\r\t\n]+\\.([^\\x00-\\x2f\\x3b-\\x40\\x5b-\\x60\\x7b-\\x7f]{2,}|xn--[a-z0-9]{2,})';
     $url1 = '.:;,';
     // Support unicode/punycode in top-level domain part
     $utf_domain = '[^?&@"\'\\/()\s\r\t\n]+\\.([^\\x00-\\x2f\\x3b-\\x40\\x5b-\\x60\\x7b-\\x7f]{2,}|xn--[a-z0-9]{2,})';
     $url1 = '.:;,';
-    $url2 = 'a-z0-9%=#@+?&\\/_~\\[\\]-';
+    $url2 = 'a-z0-9%=#@+?!&\\/_~\\[\\]{}-';
 
     $this->link_pattern = "/([\w]+:\/\/|\Wwww\.)($utf_domain([$url1]?[$url2]+)*)/i";
     $this->mailto_pattern = "/("
 
     $this->link_pattern = "/([\w]+:\/\/|\Wwww\.)($utf_domain([$url1]?[$url2]+)*)/i";
     $this->mailto_pattern = "/("
index 9c208b332e56cd2fad13f0addad34f5214297f0c..5a09fca9200c882ab486ced150e55d87043dfc4f 100755 (executable)
@@ -16,7 +16,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: rcube_template.php 5165 2011-09-05 08:49:04Z thomasb $
+ $Id: rcube_template.php 5481 2011-11-24 07:53:00Z alec $
 
  */
 
 
  */
 
@@ -71,6 +71,7 @@ class rcube_template extends rcube_html_page
 
         //$this->framed = $framed;
         $this->set_env('task', $task);
 
         //$this->framed = $framed;
         $this->set_env('task', $task);
+        $this->set_env('x_frame_options', $this->app->config->get('x_frame_options', 'sameorigin'));
 
         // load the correct skin (in case user-defined)
         $this->set_skin($this->config['skin']);
 
         // load the correct skin (in case user-defined)
         $this->set_skin($this->config['skin']);
@@ -217,7 +218,9 @@ class rcube_template extends rcube_html_page
     public function command()
     {
         $cmd = func_get_args();
     public function command()
     {
         $cmd = func_get_args();
-        if (strpos($cmd[0], 'plugin.') === false)
+        if (strpos($cmd[0], 'plugin.') !== false)
+          $this->js_commands[] = array('triggerEvent', $cmd[0], $cmd[1]);
+        else
           $this->js_commands[] = $cmd;
     }
 
           $this->js_commands[] = $cmd;
     }
 
@@ -353,10 +356,6 @@ class rcube_template extends rcube_html_page
         $js .= $this->get_js_commands() . ($this->framed ? ' }' : '');
         $this->add_script($js, 'head_top');
 
         $js .= $this->get_js_commands() . ($this->framed ? ' }' : '');
         $this->add_script($js, 'head_top');
 
-        // make sure all <form> tags have a valid request token
-        $template = preg_replace_callback('/<form\s+([^>]+)>/Ui', array($this, 'alter_form_tag'), $template);
-        $this->footer = preg_replace_callback('/<form\s+([^>]+)>/Ui', array($this, 'alter_form_tag'), $this->footer);
-        
         // send clickjacking protection headers
         $iframe = $this->framed || !empty($_REQUEST['_framed']);
         if (!headers_sent() && ($xframe = $this->app->config->get('x_frame_options', 'sameorigin')))
         // send clickjacking protection headers
         $iframe = $this->framed || !empty($_REQUEST['_framed']);
         if (!headers_sent() && ($xframe = $this->app->config->get('x_frame_options', 'sameorigin')))
@@ -437,6 +436,10 @@ class rcube_template extends rcube_html_page
 
         $output = $this->parse_with_globals($hook['content']);
 
 
         $output = $this->parse_with_globals($hook['content']);
 
+        // make sure all <form> tags have a valid request token
+        $output = preg_replace_callback('/<form\s+([^>]+)>/Ui', array($this, 'alter_form_tag'), $output);
+        $this->footer = preg_replace_callback('/<form\s+([^>]+)>/Ui', array($this, 'alter_form_tag'), $this->footer);
+
         if ($write) {
             // add debug console
             if ($realname != 'error' && ($this->config['debug_level'] & 8)) {
         if ($write) {
             // add debug console
             if ($realname != 'error' && ($this->config['debug_level'] & 8)) {
@@ -689,7 +692,7 @@ class rcube_template extends rcube_html_page
                     $vars = $attrib + array('product' => $this->config['product_name']);
                     unset($vars['name'], $vars['command']);
                     $label = rcube_label($attrib + array('vars' => $vars));
                     $vars = $attrib + array('product' => $this->config['product_name']);
                     unset($vars['name'], $vars['command']);
                     $label = rcube_label($attrib + array('vars' => $vars));
-                    return !$attrbi['noshow'] ? Q($label) : '';
+                    return !$attrib['noshow'] ? (get_boolean((string)$attrib['html']) ? $label : Q($label)) : '';
                 }
                 break;
 
                 }
                 break;
 
@@ -913,6 +916,7 @@ class rcube_template extends rcube_html_page
             // make valid href to specific buttons
             if (in_array($attrib['command'], rcmail::$main_tasks)) {
                 $attrib['href'] = rcmail_url(null, null, $attrib['command']);
             // make valid href to specific buttons
             if (in_array($attrib['command'], rcmail::$main_tasks)) {
                 $attrib['href'] = rcmail_url(null, null, $attrib['command']);
+                $attrib['onclick'] = sprintf("%s.switch_task('%s');return false", JS_OBJECT_NAME, $attrib['command']);
             }
             else if ($attrib['task'] && in_array($attrib['task'], rcmail::$main_tasks)) {
                 $attrib['href'] = rcmail_url($attrib['command'], null, $attrib['task']);
             }
             else if ($attrib['task'] && in_array($attrib['task'], rcmail::$main_tasks)) {
                 $attrib['href'] = rcmail_url($attrib['command'], null, $attrib['task']);
@@ -1105,6 +1109,7 @@ class rcube_template extends rcube_html_page
         $input_task   = new html_hiddenfield(array('name' => '_task', 'value' => 'login'));
         $input_action = new html_hiddenfield(array('name' => '_action', 'value' => 'login'));
         $input_tzone  = new html_hiddenfield(array('name' => '_timezone', 'id' => 'rcmlogintz', 'value' => '_default_'));
         $input_task   = new html_hiddenfield(array('name' => '_task', 'value' => 'login'));
         $input_action = new html_hiddenfield(array('name' => '_action', 'value' => 'login'));
         $input_tzone  = new html_hiddenfield(array('name' => '_timezone', 'id' => 'rcmlogintz', 'value' => '_default_'));
+        $input_dst    = new html_hiddenfield(array('name' => '_dstactive', 'id' => 'rcmlogindst', 'value' => '_default_'));
         $input_url    = new html_hiddenfield(array('name' => '_url', 'id' => 'rcmloginurl', 'value' => $url));
         $input_user   = new html_inputfield(array('name' => '_user', 'id' => 'rcmloginuser')
             + $attrib + $user_attrib);
         $input_url    = new html_hiddenfield(array('name' => '_url', 'id' => 'rcmloginurl', 'value' => $url));
         $input_user   = new html_inputfield(array('name' => '_user', 'id' => 'rcmloginuser')
             + $attrib + $user_attrib);
@@ -1142,20 +1147,21 @@ class rcube_template extends rcube_html_page
         $table = new html_table(array('cols' => 2));
 
         $table->add('title', html::label('rcmloginuser', Q(rcube_label('username'))));
         $table = new html_table(array('cols' => 2));
 
         $table->add('title', html::label('rcmloginuser', Q(rcube_label('username'))));
-        $table->add(null, $input_user->show(get_input_value('_user', RCUBE_INPUT_GPC)));
+        $table->add('input', $input_user->show(get_input_value('_user', RCUBE_INPUT_GPC)));
 
         $table->add('title', html::label('rcmloginpwd', Q(rcube_label('password'))));
 
         $table->add('title', html::label('rcmloginpwd', Q(rcube_label('password'))));
-        $table->add(null, $input_pass->show());
+        $table->add('input', $input_pass->show());
 
         // add host selection row
         if (is_object($input_host) && !$hide_host) {
             $table->add('title', html::label('rcmloginhost', Q(rcube_label('server'))));
 
         // add host selection row
         if (is_object($input_host) && !$hide_host) {
             $table->add('title', html::label('rcmloginhost', Q(rcube_label('server'))));
-            $table->add(null, $input_host->show(get_input_value('_host', RCUBE_INPUT_GPC)));
+            $table->add('input', $input_host->show(get_input_value('_host', RCUBE_INPUT_GPC)));
         }
 
         $out  = $input_task->show();
         $out .= $input_action->show();
         $out .= $input_tzone->show();
         }
 
         $out  = $input_task->show();
         $out .= $input_action->show();
         $out .= $input_tzone->show();
+        $out .= $input_dst->show();
         $out .= $input_url->show();
         $out .= $table->show();
 
         $out .= $input_url->show();
         $out .= $table->show();
 
index 19d08117d7e5ffa2f02de41cd77ce04936987af2..cc006c0c13d1bea47e4053d488cd45835272328e 100644 (file)
@@ -16,7 +16,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: rcube_user.php 5165 2011-09-05 08:49:04Z thomasb $
+ $Id: rcube_user.php 5183 2011-09-06 17:18:12Z alec $
 
 */
 
 
 */
 
@@ -47,6 +47,8 @@ class rcube_user
      */
     private $rc;
 
      */
     private $rc;
 
+    const SEARCH_ADDRESSBOOK = 1;
+    const SEARCH_MAIL = 2;
 
     /**
      * Object constructor
 
     /**
      * Object constructor
@@ -397,11 +399,8 @@ class rcube_user
     {
         $dbh = rcmail::get_instance()->get_dbh();
 
     {
         $dbh = rcmail::get_instance()->get_dbh();
 
-        // use BINARY (case-sensitive) comparison on MySQL, other engines are case-sensitive
-        $mod = preg_match('/^mysql/', $dbh->db_provider) ? 'BINARY' : '';
-
         // query for matching user name
         // query for matching user name
-        $query = "SELECT * FROM ".get_table_name('users')." WHERE mail_host = ? AND %s = $mod ?";
+        $query = "SELECT * FROM ".get_table_name('users')." WHERE mail_host = ? AND %s = ?";
         $sql_result = $dbh->query(sprintf($query, 'username'), $host, $user);
 
         // query for matching alias
         $sql_result = $dbh->query(sprintf($query, 'username'), $host, $user);
 
         // query for matching alias
@@ -551,4 +550,129 @@ class rcube_user
         return empty($plugin['email']) ? NULL : $plugin['email'];
     }
 
         return empty($plugin['email']) ? NULL : $plugin['email'];
     }
 
+
+    /**
+     * Return a list of saved searches linked with this user
+     *
+     * @param int  $type  Search type
+     *
+     * @return array List of saved searches indexed by search ID
+     */
+    function list_searches($type)
+    {
+        $plugin = $this->rc->plugins->exec_hook('saved_search_list', array('type' => $type));
+
+        if ($plugin['abort']) {
+            return (array) $plugin['result'];
+        }
+
+        $result = array();
+
+        $sql_result = $this->db->query(
+            "SELECT search_id AS id, ".$this->db->quoteIdentifier('name')
+            ." FROM ".get_table_name('searches')
+            ." WHERE user_id = ?"
+                ." AND ".$this->db->quoteIdentifier('type')." = ?"
+            ." ORDER BY ".$this->db->quoteIdentifier('name'),
+            (int) $this->ID, (int) $type);
+
+        while ($sql_arr = $this->db->fetch_assoc($sql_result)) {
+            $sql_arr['data'] = unserialize($sql_arr['data']);
+            $result[$sql_arr['id']] = $sql_arr;
+        }
+
+        return $result;
+    }
+
+
+    /**
+     * Return saved search data.
+     *
+     * @param int  $id  Row identifier
+     *
+     * @return array Data
+     */
+    function get_search($id)
+    {
+        $plugin = $this->rc->plugins->exec_hook('saved_search_get', array('id' => $id));
+
+        if ($plugin['abort']) {
+            return $plugin['result'];
+        }
+
+        $sql_result = $this->db->query(
+            "SELECT ".$this->db->quoteIdentifier('name')
+                .", ".$this->db->quoteIdentifier('data')
+                .", ".$this->db->quoteIdentifier('type')
+            ." FROM ".get_table_name('searches')
+            ." WHERE user_id = ?"
+                ." AND search_id = ?",
+            (int) $this->ID, (int) $id);
+
+        while ($sql_arr = $this->db->fetch_assoc($sql_result)) {
+            return array(
+                'id'   => $id,
+                'name' => $sql_arr['name'],
+                'type' => $sql_arr['type'],
+                'data' => unserialize($sql_arr['data']),
+            );
+        }
+
+        return null;
+    }
+
+
+    /**
+     * Deletes given saved search record
+     *
+     * @param  int  $sid  Search ID
+     *
+     * @return boolean True if deleted successfully, false if nothing changed
+     */
+    function delete_search($sid)
+    {
+        if (!$this->ID)
+            return false;
+
+        $this->db->query(
+            "DELETE FROM ".get_table_name('searches')
+            ." WHERE user_id = ?"
+                ." AND search_id = ?",
+            (int) $this->ID, $sid);
+
+        return $this->db->affected_rows();
+    }
+
+
+    /**
+     * Create a new saved search record linked with this user
+     *
+     * @param array $data Hash array with col->value pairs to save
+     *
+     * @return int  The inserted search ID or false on error
+     */
+    function insert_search($data)
+    {
+        if (!$this->ID)
+            return false;
+
+        $insert_cols[]   = 'user_id';
+        $insert_values[] = (int) $this->ID;
+        $insert_cols[]   = $this->db->quoteIdentifier('type');
+        $insert_values[] = (int) $data['type'];
+        $insert_cols[]   = $this->db->quoteIdentifier('name');
+        $insert_values[] = $data['name'];
+        $insert_cols[]   = $this->db->quoteIdentifier('data');
+        $insert_values[] = serialize($data['data']);
+
+        $sql = "INSERT INTO ".get_table_name('searches')
+            ." (".join(', ', $insert_cols).")"
+            ." VALUES (".join(', ', array_pad(array(), sizeof($insert_values), '?')).")";
+
+        call_user_func_array(array($this->db, 'query'),
+            array_merge(array($sql), $insert_values));
+
+        return $this->db->insert_id('searches');
+    }
+
 }
 }
index c02210becd4e31f60d3e9ca1b6f1e741907cccbc..dba020af7d0727b1c35886d43cf0d34d953ab732 100644 (file)
@@ -14,7 +14,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: rcube_vcard.php 5165 2011-09-05 08:49:04Z thomasb $
+ $Id: rcube_vcard.php 5160 2011-09-05 07:40:18Z thomasb $
 
 */
 
 
 */
 
index 5957acf2b396e10ea7d4b372f690e8b4bbe3270b..c871cc66356370d9bb6541afcc1e6d2ede3dae96 100644 (file)
-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.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){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){typeof a=="string"?this.labels[a]=b:typeof a=="object"&&$.extend(this.labels,a)};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.loaded&&
-t(a,b)};this.gui_object=function(a,b){this.gui_objects[a]=this.loaded?rcube_find_object(b):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","save-pref","undo",!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.flag_for_deletion&&
-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,forward-attachment".split(",");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",!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","cancel","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){l.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&&(bw.safari?window.setTimeout("window.print()",10):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.update_group_commands();this.set_page_buttons();this.env.cid&&(this.enable_command("show","edit",!0),this.gui_objects.editform&&$("input.groupmember").change(function(){l.group_member_change(this.checked?"add":"del",l.env.cid,l.env.source,this.value)}));this.gui_objects.editform&&(this.enable_command("save",!0),(this.env.action=="add"||this.env.action=="edit")&&this.init_contact_form());this.gui_objects.qsearchbox&&this.enable_command("search","reset-search","moveto",!0);this.contact_list&&this.contact_list.rowcount>
-0&&this.enable_command("export",!0);this.enable_command("add","import",this.env.writable_source);this.enable_command("list","listgroup","advanced-search",!0);this.env.action||this.command("list",this.env.source);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).prop("disabled",!0);rcmail.display_message("","loading")}),this.enable_command("login",!0)}bw.ie&&$("input[type=file]").keydown(function(a){a.keyCode=="13"&&a.preventDefault()});
-this.loaded=!0;this.pending_message&&this.display_message(this.pending_message[0],this.pending_message[1],this.pending_message[2]);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.log=function(a){window.console&&console.log&&
-console.log(a)};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"){var e=this.command_handlers[a](b,d);return e!==void 0?e:d?!1:!0}else if(typeof this.command_handlers[a]===
-"string")return e=window[this.command_handlers[a]](b,d),e!==void 0?e:d?!1:!0;this.triggerEvent("actionbefore",{props:b,action:a});e=this.triggerEvent("before"+a,b);if(e!==void 0)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.env.flag_for_deletion&&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.writable_source));break;case "load-headers":this.load_headers(d);break;case "sort":var g;f=b;g=this.env.sort_col==f?this.env.sort_order=="ASC"?"DESC":"ASC":"ASC";this.set_list_sorting(f,g);this.list_mailbox("","",f+"_"+g);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 if(this.task=="addressbook"){var h=
-b?b:this.get_single_cid();h&&!(this.env.action=="show"&&h==this.env.cid)&&this.load_contact(h,"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"&&(h=this.get_single_cid()))this.load_contact(h,"edit");else if(this.task=="settings"&&b)this.load_identity(b,"edit-identity");else if(this.task=="mail"&&(h=this.get_single_uid()))g=this.env.mailbox==
-this.env.drafts_mailbox?"_draft_uid=":"_uid=",this.goto_url("compose",g+h+"&_mbox="+urlencode(this.env.mailbox),!0);break;case "save":var k;if(g=this.gui_objects.editform){if(this.env.action!="search")if((k=$("input[name='_pagesize']",g))&&k.length&&isNaN(parseInt(k.val()))){alert(this.get_label("nopagesizewarning"));k.focus();break}else{if(b=="reload")g.action+="?_reload=1";else if(this.task=="settings"&&this.env.identities_level%2==0&&(k=$("input[name='_email']",g))&&k.length&&!rcube_check_email(k.val())){alert(this.get_label("noemailwarning"));
-k.focus();break}$("input.placeholder").each(function(){if(this.value==this._placeholder)this.value=""})}if(parent.rcmail&&parent.rcmail.env.source)g.action=this.add_url(g.action,"_orig_source",parent.rcmail.env.source);g.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(){l.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":g="_mbox="+urlencode(this.env.mailbox)+"&_uid="+this.env.uid+"&_part="+b.part;if(this.env.uid&&b.mimetype&&this.env.mimetypes&&$.inArray(b.mimetype,this.env.mimetypes)>=0&&(b.mimetype=="text/html"&&(g+="&_safe=1"),this.attachment_win=window.open(this.env.comm_path+
-"&_action=get&"+g+"&_frame=1","rcubemailattachment"))){window.setTimeout(function(){l.attachment_win.focus()},10);break}this.goto_url("get",g+"&_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":g=this.env.comm_path+"&_action=compose";if(this.task=="mail")if(g+="&_mbox="+urlencode(this.env.mailbox),this.env.mailbox==this.env.drafts_mailbox){if(f=this.get_single_uid())g+="&_draft_uid="+f}else b&&(g+="&_to="+urlencode(b));else if(this.task=="addressbook"){if(b&&b.indexOf("@")>0){g=this.get_task_url("mail",g);this.redirect(g+"&_to="+urlencode(b));
-break}h=[];if(b)h.push(b);else if(this.contact_list){k=this.contact_list.get_selection();for(g=0,f=k.length;g<f;g++)h.push(k[g])}h.length&&this.http_post("mailto",{_cid:h.join(","),_source:this.env.source},!0);break}this.redirect(g);break;case "spellcheck":window.tinyMCE&&tinyMCE.get(this.env.composebody)?tinyMCE.execCommand("mceSpellCheck",!0):this.env.spellcheck&&this.env.spellcheck.spellCheck&&this.spellcheck_ready&&(this.env.spellcheck.spellCheck(),this.set_spellcheck_state("checking"));break;
-case "savedraft":self.clearTimeout(this.save_timer);if(!this.gui_objects.messageform)break;if(!this.env.drafts_mailbox||this.cmp_hash==this.compose_field_hash())break;g=this.gui_objects.messageform;f=this.set_busy(!0,"savingmessage");g.target="savetarget";g._draft.value="1";g.action=this.add_url(g.action,"_unlock",f);g.submit();break;case "send":if(!this.gui_objects.messageform)break;if(!this.check_compose_input())break;self.clearTimeout(this.save_timer);h=this.spellcheck_lang();g=this.gui_objects.messageform;
-f=this.set_busy(!0,"sendingmessage");g.target="savetarget";g._draft.value="";g.action=this.add_url(g.action,"_unlock",f);g.action=this.add_url(g.action,"_lang",h);g.submit();clearTimeout(this.request_timer);break;case "send-attachment":self.clearTimeout(this.save_timer);this.upload_file(b);break;case "insert-sig":this.change_identity($("[name='_from']")[0],!0);break;case "reply-all":case "reply-list":case "reply":if(f=this.get_single_uid())g="_reply_uid="+f+"&_mbox="+urlencode(this.env.mailbox),a==
-"reply-all"?g+="&_all="+(!b&&this.commands["reply-list"]?"list":"all"):a=="reply-list"&&(g+="&_all=list"),this.goto_url("compose",g,!0);break;case "forward-attachment":case "forward":if(f=this.get_single_uid()){g="_forward_uid="+f+"&_mbox="+urlencode(this.env.mailbox);if(a=="forward-attachment"||!b&&this.env.forward_attachment)g+="&_attachment=1";this.goto_url("compose",g,!0)}break;case "print":if(f=this.get_single_uid())l.printwin=window.open(this.env.comm_path+"&_action=print&_uid="+f+"&_mbox="+
-urlencode(this.env.mailbox)+(this.env.safemode?"&_safe=1":"")),this.printwin&&(window.setTimeout(function(){l.printwin.focus()},20),this.env.action!="show"&&this.mark_message("read",f));break;case "viewsource":if(f=this.get_single_uid())l.sourcewin=window.open(this.env.comm_path+"&_action=viewsource&_uid="+f+"&_mbox="+urlencode(this.env.mailbox)),this.sourcewin&&window.setTimeout(function(){l.sourcewin.focus()},20);break;case "download":(f=this.get_single_uid())&&this.goto_url("viewsource","&_uid="+
-f+"&_mbox="+urlencode(this.env.mailbox)+"&_save=1");break;case "search":if(!b&&this.gui_objects.qsearchbox)b=this.gui_objects.qsearchbox.value;if(b){this.qsearch(b);break}case "reset-search":f=this.env.search_request||this.env.qsearch;this.reset_qsearch();this.select_all_mode=!1;if(f&&this.env.mailbox)this.list_mailbox(this.env.mailbox,1);else if(f&&this.task=="addressbook"){if(this.env.source==""){for(g in this.env.address_sources)break;this.env.source=g;this.env.group=""}this.list_contacts(this.env.source,
-this.env.group,1)}break;case "listgroup":this.list_contacts(b.source,b.id);break;case "import":if(this.env.action=="import"&&this.gui_objects.importform){if((g=document.getElementById("rcmimportfile"))&&!g.value){alert(this.get_label("selectimportfile"));break}this.gui_objects.importform.submit();this.set_busy(!0,"importwait");this.lock_form(this.gui_objects.importform,!0)}else this.goto_url("import",this.env.source?"_target="+urlencode(this.env.source)+"&":"");break;case "export":this.contact_list.rowcount>
-0&&this.goto_url("export",{_source:this.env.source,_gid:this.env.group,_search:this.env.search_request});break;case "upload-photo":this.upload_contact_photo(b);break;case "delete-photo":this.replace_contact_photo("-del-");break;case "preferences":case "identities":case "folders":this.goto_url("settings/"+a);break;case "undo":this.http_request("undo","",this.display_message("","loading"));break;default:if(g=a.replace(/-/g,"_"),this[g]&&typeof this[g]==="function")this[g](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<a.length;e++)if(d=a[e],typeof d==="string")this.commands[d]=b,this.set_button(d,b?"act":"pas");else for(var f in d)a.push(d[f])};this.set_busy=function(a,b,d){a&&b?(d=this.get_label(b),d==b&&(d="Loading..."),d=this.display_message(d,"loading")):!a&&d&&this.hide_message(d);this.busy=a;this.gui_objects.editform&&this.lock_form(this.gui_objects.editform,
-a);this.request_timer&&clearTimeout(this.request_timer);if(a&&this.env.request_timeout)this.request_timer=window.setTimeout(function(){l.request_timed_out()},this.env.request_timeout*1E3);return d};this.gettext=this.get_label=function(a,b){return b&&this.labels[b+"."+a]?this.labels[b+"."+a]:this.labels[a]?this.labels[a]:a};this.switch_task=function(a){if(!(this.task===a&&a!="mail")){var b=this.get_task_url(a);a=="mail"&&(b+="&_mbox=INBOX");this.redirect(b)}};this.get_task_url=function(a,b){if(!b)b=
-this.env.comm_path;return b.replace(/_task=[a-z]+/,"_task="+a)};this.request_timed_out=function(){this.set_busy(!1);this.display_message("Request timed out!","error")};this.reload=function(a){if(this.is_framed())parent.rcmail.reload(a);else if(a)window.setTimeout(function(){rcmail.reload()},a);else if(window.location)location.href=this.env.comm_path+(this.env.action?"&_action="+this.env.action:"")};this.add_url=function(a,b,d){d=urlencode(d);if(/(\?.*)$/.test(a)){var e=RegExp.$1,f=RegExp("((\\?|&)"+
-RegExp.escape(b)+"=[^&]*)");f.test(e)?e=e.replace(f,RegExp.$2+b+"="+d):e+="&"+b+"="+d;return a.replace(/(\?.*)$/,e)}else return a+"?"+b+"="+d};this.is_framed=function(){return this.env.framed&&parent.rcmail&&parent.rcmail!=this&&parent.rcmail.command};this.save_pref=function(a){var b={_name:a.name,_value:a.value};if(a.session)b._session=a.session;if(a.env)this.env[a.env]=a.value;this.http_post("save-pref",b)};this.drag_menu=function(a,b){var d=rcube_event.get_modifier(a),e=this.gui_objects.message_dragmenu;
-return e&&d==SHIFT_KEY&&this.commands.copy?(d=rcube_event.get_mouse_pos(a),this.env.drag_target=b,$(e).css({top:d.y-10+"px",left:d.x-10+"px"}).show(),!0):!1};this.drag_menu_action=function(a){var b=this.gui_objects.message_dragmenu;b&&$(b).hide();this.command(a,this.env.drag_target);this.env.drag_target=null};this.drag_start=function(a){var b=this.task=="mail"?this.env.mailboxes:this.env.contactfolders;this.drag_active=!0;this.preview_timer&&clearTimeout(this.preview_timer);this.preview_read_timer&&
-clearTimeout(this.preview_read_timer);if(this.gui_objects.folderlist&&b){this.initialBodyScrollTop=bw.ie?0:window.pageYOffset;this.initialListScrollTop=this.gui_objects.folderlist.parentNode.scrollTop;var d,e,a=$(this.gui_objects.folderlist);d=a.offset();this.env.folderlist_coords={x1:d.left,y1:d.top,x2:d.left+a.width(),y2:d.top+a.height()};this.env.folder_coords=[];for(var f in b)if(a=this.get_folder_li(f))if(e=a.firstChild.offsetHeight)d=$(a.firstChild).offset(),this.env.folder_coords[f]={x1:d.left,
-y1:d.top,x2:d.left+a.firstChild.offsetWidth,y2:d.top+e,on:0}}};this.drag_end=function(){this.drag_active=!1;this.env.last_folder_target=null;if(this.folder_auto_timer)window.clearTimeout(this.folder_auto_timer),this.folder_auto_expand=this.folder_auto_timer=null;if(this.gui_objects.folderlist&&this.env.folder_coords)for(var a in this.env.folder_coords)this.env.folder_coords[a].on&&$(this.get_folder_li(a)).removeClass("droptarget")};this.drag_move=function(a){if(this.gui_objects.folderlist&&this.env.folder_coords){var b=
--(this.initialListScrollTop-this.gui_objects.folderlist.parentNode.scrollTop)-(bw.ie?-document.documentElement.scrollTop:this.initialBodyScrollTop),d,e,f;d="draglayernormal";this.contact_list&&this.contact_list.draglayer&&(f=this.contact_list.draglayer.attr("class"));a=rcube_event.get_mouse_pos(a);e=this.env.folderlist_coords;a.y+=b;if(a.x<e.x1||a.x>=e.x2||a.y<e.y1||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.x2&&a.y>=e.y1&&a.y<e.y2)if(b=this.check_droptarget(g)){d=this.get_folder_li(g);e=$(d.getElementsByTagName("div")[0]);if(e.hasClass("collapsed"))this.folder_auto_timer&&window.clearTimeout(this.folder_auto_timer),this.folder_auto_expand=g,this.folder_auto_timer=window.setTimeout(function(){rcmail.command("collapse-folder",rcmail.folder_auto_expand);rcmail.drag_start(null)},1E3);
-else if(this.folder_auto_timer)window.clearTimeout(this.folder_auto_timer),this.folder_auto_expand=this.folder_auto_timer=null;$(d).addClass("droptarget");this.env.folder_coords[g].on=1;this.env.last_folder_target=g;d="draglayer"+(b>1?"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.env.collapsed_folders=this.env.collapsed_folders.replace(RegExp("&"+urlencode(a)+"&"),"")):(e.hide(),d.removeClass("expanded").addClass("collapsed"),this.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.command("save-pref",{name:"collapsed_folders",value:this.env.collapsed_folders});this.set_unread_count_display(a,!1)}};this.doc_mouse_up=function(a){var b,d,e;(d=this.message_list)?(rcube_mouse_is_over(a,d.list.parentNode)?d.focus():d.blur(),b=this.env.mailboxes):(d=
-this.contact_list)?(rcube_mouse_is_over(a,d.list.parentNode)?d.focus():d.blur(),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(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","forward-attachment",!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(){l.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(){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);(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")};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=a.list.tHead.rows[0].cells;this.env.coltypes=[];for(a=0;a<d.length;a++)d[a].id&&d[a].id.match(/^rcm/)&&(b=d[a].id.replace(/^rcm/,""),this.env.coltypes.push(b==
-"to"?"from":b));if((a=$.inArray("flag",this.env.coltypes))>=0)this.env.flagged_col=a;if((a=$.inArray("subject",this.env.coltypes))>=0)this.env.subject_col=a;this.command("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,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":""),l=document.createElement("tr"),m=document.createElement("td");l.id="rcmrow"+a;l.className=
-j;j="msgicon";this.env.status_col===null&&(j+=" status",d.deleted?j+=" deleted":d.unread?j+=" unread":d.unread_children>0&&(j+=" unreadchildren"));d.replied&&(j+=" replied");d.forwarded&&(j+=" forwarded");f.selected&&!h.in_selection(a)&&h.selection.push(a);if(this.env.threading){m=f.depth*15;if(f.depth)k[f.parent_uid]&&k[f.parent_uid].expanded===!1||(this.env.autoexpand_threads==0||this.env.autoexpand_threads==2)&&(!k[f.parent_uid]||!k[f.parent_uid].expanded)?(l.style.display="none",f.expanded=!1):
-f.expanded=!0;else if(f.has_children&&f.expanded===void 0&&(this.env.autoexpand_threads==1||this.env.autoexpand_threads==2&&f.unread_children))f.expanded=!0;m&&(g+='<span id="rcmtab'+a+'" class="branch" style="width:'+m+'px;">&nbsp;&nbsp;</span>');f.has_children&&!f.depth&&(expando='<div id="rcmexpando'+a+'" class="'+(f.expanded?"expanded":"collapsed")+'">&nbsp;&nbsp;</div>')}g+='<span id="msgicn'+a+'" class="'+j+'">&nbsp;</span>';if(!bw.ie&&b.subject)m=d.mbox==this.env.drafts_mailbox?"_draft_uid":
-"_uid",b.subject='<a href="./?_task=mail&_action='+(d.mbox==this.env.drafts_mailbox?"compose":"show")+"&_mbox="+urlencode(d.mbox)+"&"+m+"="+a+'" onclick="return rcube_event.cancel(event)" onmouseover="rcube_webmail.long_subject_title(this,'+(f.depth+1)+')">'+b.subject+"</a>";for(var n in this.env.coltypes)f=this.env.coltypes[n],m=document.createElement("td"),m.className=String(f).toLowerCase(),f=="flag"?(j=d.flagged?"flagged":"unflagged",f='<span id="flagicn'+a+'" class="'+j+'">&nbsp;</span>'):f==
-"attachment"?f=/application\/|multipart\/m/.test(d.ctype)?'<span class="attachment">&nbsp;</span>':/multipart\/report/.test(d.ctype)?'<span class="report">&nbsp;</span>':"&nbsp;":f=="status"?(j=d.deleted?"deleted":d.unread?"unread":d.unread_children>0?"unreadchildren":"msgicon",f='<span id="statusicn'+a+'" class="'+j+'">&nbsp;</span>'):f=f=="threads"?expando:f=="subject"?g+b[f]:b[f],m.innerHTML=f,l.appendChild(m);h.insert_row(l,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(b===void 0)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,
-k,j=[],l=this.env.coltypes,e=0;e<l.length;e++)k=l[e]=="to"?"from":l[e],h=$.inArray(k,a),h!=-1&&(j.push(k),delete a[h]);for(e=0;e<a.length;e++)a[e]&&j.push(a[e]);j.join()!=l.join()&&(f=1,g+="&_cols="+j.join(","))}f&&this.list_mailbox("","",b+"_"+d,g)};this.show_message=function(a,b,d){if(a){var e=window,f=d?"preview":"show",g="&_action="+f+"&_uid="+a+"&_mbox="+urlencode(this.env.mailbox);d&&this.env.contentframe&&window.frames&&window.frames[this.env.contentframe]&&(e=window.frames[this.env.contentframe],
-g+="&_framed=1");b&&(g+="&_safe=1");this.env.search_request&&(g+="&_search="+this.env.search_request);if(f=="preview"&&String(e.location.href).indexOf(g)>=0)this.show_contentframe(!0);else if(this.location_href(this.env.comm_path+g,e,!0),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",!1);l.update_thread_root(a,"read");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(!1,null,this.env.frame_lock)};this.lock_frame=function(){if(!this.env.frame_lock)(this.is_framed()?parent.rcmail:this).env.frame_lock=this.set_busy(!0,"loading")};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;this.gui_objects.messagelist?this.list_mailbox_remote(a,b,f):(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"),this.location_href(this.env.comm_path+"&_mbox="+urlencode(a)+(b?"&_page="+b:"")+f,g)))};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<d;b++)this.add_tree_icons(a[b]);this.expand_threads()};this.add_tree_icons=function(a){var b,d,e,f,g=[],h=[],k,j=this.message_list.rows;for(k=a?j[a]?j[a].obj:null:this.message_list.list.tBodies[0].firstChild;k;){if(k.nodeType==
-1&&(d=j[k.uid]))if(d.depth){for(b=g.length-1;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&&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;d<g;d++)b[d]>2?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"]?'<div class="tree '+e[d]["class"]+'" />':'<div style="width:'+e[d].width+'px" />';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;b<h.length;b++)this.set_unread_children(h[b].uid);return d};this.delete_excessive_thread_rows=function(){for(var a=this.message_list.rows,b=this.message_list.list.tBodies[0].firstChild,d=this.env.pagesize+1;b;){if(b.nodeType==1&&(r=a[b.uid]))!r.depth&&d&&d--,d||this.message_list.remove_row(b.uid);b=b.nextSibling}};this.set_message_icon=function(a){var b=this.message_list.rows[a];if(!b)return!1;if(b.icon)a="msgicon",b.deleted?a+=" deleted":b.unread?a+=" unread":b.unread_children&&(a+=" unreadchildren"),
-b.msgicon==b.icon&&(b.replied&&(a+=" replied"),b.forwarded&&(a+=" forwarded"),a+=" status"),b.icon.className=a;if(b.msgicon&&b.msgicon!=b.icon)a="msgicon",!b.unread&&b.unread_children&&(a+=" unreadchildren"),b.replied&&(a+=" replied"),b.forwarded&&(a+=" forwarded"),b.msgicon.className=a;if(b.flagicon)a=b.flagged?"flagged":"unflagged",b.flagicon.className=a};this.set_message_status=function(a,b,d){a=this.message_list.rows[a];if(!a)return!1;if(b=="unread")a.unread=d;else if(b=="deleted")a.deleted=d;
-else if(b=="replied")a.replied=d;else if(b=="forwarded")a.forwarded=d;else if(b=="flagged")a.flagged=d};this.set_message=function(a,b,d){var e=this.message_list.rows[a];if(!e)return!1;b&&this.set_message_status(a,b,d);b=$(e.obj);e.unread&&!b.hasClass("unread")?b.addClass("unread"):!e.unread&&b.hasClass("unread")&&b.removeClass("unread");e.deleted&&!b.hasClass("deleted")?b.addClass("deleted"):!e.deleted&&b.hasClass("deleted")&&b.removeClass("deleted");e.flagged&&!b.hasClass("flagged")?b.addClass("flagged"):
-!e.flagged&&b.hasClass("flagged")&&b.removeClass("flagged");this.set_unread_children(a);this.set_message_icon(a)};this.set_unread_children=function(a){a=this.message_list.rows[a];a.parent_uid||(!a.unread&&a.unread_children&&!a.expanded?$(a.obj).addClass("unroot"):$(a.obj).removeClass("unroot"))};this.copy_messages=function(a){if(a&&typeof a==="object")a=a.id;if(a&&!(a==this.env.mailbox||!this.env.uid&&(!this.message_list||!this.message_list.get_selection().length))){var b=[],d=this.display_message(this.get_label("copyingmessage"),
-"loading"),a="&_target_mbox="+urlencode(a)+"&_from="+(this.env.action?this.env.action:"");if(this.env.uid)b[0]=this.env.uid;else{var e=this.message_list.get_selection(),f;for(f in e)b.push(e[f])}a+="&_uid="+this.uids_to_list(b);this.http_post("copy","_mbox="+urlencode(this.env.mailbox)+a,d)}};this.move_messages=function(a){if(a&&typeof a==="object")a=a.id;if(a&&!(a==this.env.mailbox||!this.env.uid&&(!this.message_list||!this.message_list.get_selection().length))){var b=!1,a="&_target_mbox="+urlencode(a)+
-"&_from="+(this.env.action?this.env.action:"");this.env.action=="show"?b=this.set_busy(!0,"movingmessage"):this.show_contentframe(!1);this.enable_command(this.env.message_commands,!1);this._with_selected_messages("moveto",b,a)}};this.delete_messages=function(){var a,b,d,e=this.env.trash_mailbox,f=this.message_list,g=f?$.merge([],f.get_selection()):[];if(this.env.uid||g.length){for(b=0,d=g.length;b<d;b++)a=g[b],f.rows[a].has_children&&!f.rows[a].expanded&&f.select_childs(a);if(this.env.flag_for_deletion)return this.mark_message("delete"),
-!1;else!e||this.env.mailbox==e?this.permanently_remove_messages():f&&f.shiftkey?confirm(this.get_label("deletemessagesconfirm"))&&this.permanently_remove_messages():this.move_messages(e);return!0}};this.permanently_remove_messages=function(){if(this.env.uid||this.message_list&&this.message_list.get_selection().length)this.show_contentframe(!1),this._with_selected_messages("delete",!1,"&_from="+(this.env.action?this.env.action:""))};this._with_selected_messages=function(a,b,d){var e=[],f=0;if(this.env.uid)e[0]=
-this.env.uid;else{var g,h,k,j=[],l=this.message_list.get_selection();for(g=0,len=l.length;g<len;g++)h=l[g],e.push(h),this.env.threading&&(f+=this.update_thread(h),k=this.message_list.find_root(h),k!=h&&$.inArray(k,j)<0&&j.push(k)),this.message_list.remove_row(h,this.env.display_next&&g==l.length-1);this.env.display_next||this.message_list.clear_selection();for(g=0,len=j.length;g<len;g++)this.add_tree_icons(j[g])}this.env.search_request&&(d+="&_search="+this.env.search_request);this.env.display_next&&
-this.env.next_uid&&(d+="&_next_uid="+this.env.next_uid);f<0?d+="&_count="+f*-1:f>0&&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)for(g=
-0,f=h.length;g<f;g++)d.push(h[g]);if(this.message_list)for(g=0,f=d.length;g<f;g++)h=d[g],(a=="read"&&this.message_list.rows[h].unread||a=="unread"&&!this.message_list.rows[h].unread||a=="delete"&&!this.message_list.rows[h].deleted||a=="undelete"&&this.message_list.rows[h].deleted||a=="flagged"&&!this.message_list.rows[h].flagged||a=="unflagged"&&this.message_list.rows[h].flagged)&&e.push(h);else e=d;if(e.length||this.select_all_mode)switch(a){case "read":case "unread":this.toggle_read_status(a,e);
-break;case "delete":case "undelete":this.toggle_delete_status(e);break;case "flagged":case "unflagged":this.toggle_flagged_status(a,d)}};this.toggle_read_status=function(a,b){var d,e=b.length,f="_uid="+this.uids_to_list(b)+"&_flag="+a,g=this.display_message(this.get_label("markingmessage"),"loading");for(d=0;d<e;d++)this.set_message(b[d],"unread",a=="unread"?!0:!1);this.env.search_request&&(f+="&_search="+this.env.search_request);this.http_post("mark",f,g);for(d=0;d<e;d++)this.update_thread_root(b[d],
-a)};this.toggle_flagged_status=function(a,b){var d,e=b.length,f="_uid="+this.uids_to_list(b)+"&_flag="+a,g=this.display_message(this.get_label("markingmessage"),"loading");for(d=0;d<e;d++)this.set_message(b[d],"flagged",a=="flagged"?!0:!1);this.env.search_request&&(f+="&_search="+this.env.search_request);this.http_post("mark",f,g)};this.toggle_delete_status=function(a){var b=a.length,d,e,f=!0,g=this.message_list?this.message_list.rows:[];if(b==1)return!g.length||g[a[0]]&&!g[a[0]].deleted?this.flag_as_deleted(a):
-this.flag_as_undeleted(a),!0;for(d=0;d<b;d++)if(e=a[d],g[e]&&!g[e].deleted){f=!1;break}f?this.flag_as_undeleted(a):this.flag_as_deleted(a);return!0};this.flag_as_undeleted=function(a){var b,d=a.length,e="_uid="+this.uids_to_list(a)+"&_flag=undelete",f=this.display_message(this.get_label("markingmessage"),"loading");for(b=0;b<d;b++)this.set_message(a[b],"deleted",!1);this.env.search_request&&(e+="&_search="+this.env.search_request);this.http_post("mark",e,f);return!0};this.flag_as_deleted=function(a){for(var b=
-"",d=[],b=this.message_list?this.message_list.rows:[],e=0,f=0,g=a.length;f<g;f++)uid=a[f],b[uid]&&(b[uid].unread&&(d[d.length]=uid),this.env.skip_deleted?(e+=this.update_thread(uid),this.message_list.remove_row(uid,this.env.display_next&&f==this.message_list.selection.length-1)):this.set_message(uid,"deleted",!0));this.env.skip_deleted&&this.message_list&&(this.env.display_next||this.message_list.clear_selection(),e<0||e>0&&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){var b,d,e,f=this.message_list?this.message_list.rows:[],a=String(a).split(",");for(d=0,e=a.length;d<
-e;d++)b=a[d],f[b]&&this.set_message(b,"unread",!1)};this.uids_to_list=function(a){return this.select_all_mode?"*":a.join(",")};this.expunge_mailbox=function(a){var b,d="_mbox="+urlencode(a);a==this.env.mailbox&&(b=this.set_busy(!0,"loading"),d+="&_reload=1",this.env.search_request&&(d+="&_search="+this.env.search_request));this.http_post("expunge",d,b)};this.purge_mailbox=function(a){var b=!1,d="_mbox="+urlencode(a);if(!confirm(this.get_label("purgefolderconfirm")))return!1;a==this.env.mailbox&&(b=
-this.set_busy(!0,"loading"),d+="&_reload=1");this.http_post("purge",d,b)};this.purge_mailbox_test=function(){return this.env.messagecount&&(this.env.mailbox==this.env.trash_mailbox||this.env.mailbox==this.env.junk_mailbox||this.env.mailbox.match("^"+RegExp.escape(this.env.trash_mailbox)+RegExp.escape(this.env.delimiter))||this.env.mailbox.match("^"+RegExp.escape(this.env.junk_mailbox)+RegExp.escape(this.env.delimiter)))};this.login_user_keyup=function(a){var b=rcube_event.get_keycode(a),d=$("#rcmloginpwd");
-return b==13&&d.length&&!d.val()?(d.focus(),rcube_event.cancel(a)):!0};this.init_messageform=function(){if(!this.gui_objects.messageform)return!1;var a=$("[name='_from']"),b=$("[name='_to']"),d=$("input[name='_subject']"),e=$("[name='_message']").get(0),f=$("input[name='_is_html']").val()=="1",g=["cc","bcc","replyto","followupto"],h;this.env.autocomplete_threads>0&&(h={threads:this.env.autocomplete_threads,sources:this.env.autocomplete_sources});this.init_address_input_events(b,h);for(var k in g)this.init_address_input_events($("[name='_"+
-g[k]+"']"),h);f||(this.set_caret_pos(e,this.env.top_posting?0:$(e).val().length),a.prop("type")=="select-one"&&$("input[name='_draft_saveid']").val()==""&&this.change_identity(a[0]));b.val()==""?b.focus():d.val()==""?d.focus():e&&e.focus();this.env.compose_focus_elem=document.activeElement;this.compose_field_hash(!0);this.auto_save_start()};this.init_address_input_events=function(a,b){a[bw.ie||bw.safari||bw.chrome?"keydown":"keypress"](function(a){return l.ksearch_keydown(a,this,b)}).attr("autocomplete",
-"off")};this.check_compose_input=function(){var a,b=$("[name='_to']"),d=$("[name='_cc']"),e=$("[name='_bcc']"),f=$("[name='_from']"),g=$("[name='_subject']"),h=$("[name='_message']");if(f.prop("type")=="text"&&!rcube_check_email(f.val(),!0))return alert(this.get_label("nosenderwarning")),f.focus(),!1;d=b.val()?b.val():d.val()?d.val():e.val();if(!rcube_check_email(d.replace(/^\s+/,"").replace(/[\s,;]+$/,""),!0))return alert(this.get_label("norecipientwarning")),b.focus(),!1;for(var k in this.env.attachments)if(typeof this.env.attachments[k]===
-"object"&&!this.env.attachments[k].complete)return alert(this.get_label("notuploadedwarning")),!1;if(g.val()=="")if(b=prompt(this.get_label("nosubjectwarning"),this.get_label("nosubject")),!b&&b!=="")return g.focus(),!1;else g.val(b?b:this.get_label("nosubject"));this.stop_spellchecking();window.tinyMCE&&(a=tinyMCE.get(this.env.composebody));if(!a&&h.val()==""&&!confirm(this.get_label("nobodywarning")))return h.focus(),!1;else if(a){if(!a.getContent()&&!confirm(this.get_label("nobodywarning")))return a.focus(),
-!1;tinyMCE.triggerSave()}return!0};this.toggle_editor=function(a){if(a.mode=="html")this.display_spellcheck_controls(!1),this.plain2html($("#"+a.id).val(),a.id),tinyMCE.execCommand("mceAddControl",!1,a.id);else{var b=tinyMCE.get(a.id);b.plugins.spellchecker&&b.plugins.spellchecker.active&&b.execCommand("mceSpellCheck",!1);if(b=b.getContent()){if(!confirm(this.get_label("editorwarning")))return!1;this.html2plain(b,a.id)}tinyMCE.execCommand("mceRemoveControl",!1,a.id);this.display_spellcheck_controls(!0)}return!0};
-this.stop_spellchecking=function(){var a;if(window.tinyMCE&&(a=tinyMCE.get(this.env.composebody)))a.plugins.spellchecker&&a.plugins.spellchecker.active&&a.execCommand("mceSpellCheck");else if((a=this.env.spellcheck)&&!this.spellcheck_ready)$(a.spell_span).trigger("click"),this.set_spellcheck_state("ready")};this.display_spellcheck_controls=function(a){this.env.spellcheck&&(a||this.stop_spellchecking(),$(this.env.spellcheck.spell_container).css("visibility",a?"visible":"hidden"))};this.set_spellcheck_state=
-function(a){this.spellcheck_ready=a=="ready"||a=="no_error_found";this.enable_command("spellcheck",this.spellcheck_ready)};this.spellcheck_lang=function(){var a;if(window.tinyMCE&&(a=tinyMCE.get(this.env.composebody))&&a.plugins.spellchecker)return a.plugins.spellchecker.selectedLang;else if(this.env.spellcheck)return GOOGIE_CUR_LANG};this.spellcheck_resume=function(a,b){if(a){var d=tinyMCE.get(this.env.composebody),e=d.plugins.spellchecker;e.active=1;e._markWords(b);d.nodeChanged()}else{var e=this.env.spellcheck;
-e.prepare(!1,!0);e.processData(b)}};this.set_draft_id=function(a){$("input[name='_draft_saveid']").val(a)};this.auto_save_start=function(){if(this.env.draft_autosave)this.save_timer=self.setTimeout(function(){l.command("savedraft")},this.env.draft_autosave*1E3);this.busy=!1};this.compose_field_hash=function(a){var b,d="",e=$("[name='_to']").val(),f=$("[name='_cc']").val(),g=$("[name='_bcc']").val(),h=$("[name='_subject']").val();e&&(d+=e+":");f&&(d+=f+":");g&&(d+=g+":");h&&(d+=h+":");d+=window.tinyMCE&&
-(b=tinyMCE.get(this.env.composebody))?b.getContent():$("[name='_message']").val();if(this.env.attachments)for(var k in this.env.attachments)d+=k;if(a)this.cmp_hash=d;return d};this.change_identity=function(a,b){if(!a||!a.options)return!1;if(!b)b=this.env.show_sig;var d,e=-1,f=a.options[a.selectedIndex].value,g=$("[name='_message']"),h=g.val(),k=$("input[name='_is_html']").val()=="1",j=this.env.identity;d=this.env.sig_above&&(this.env.compose_mode=="reply"||this.env.compose_mode=="forward")?"---":
-"-- ";this.env.signatures&&this.env.signatures[f]?(this.enable_command("insert-sig",!0),this.env.compose_commands.push("insert-sig")):this.enable_command("insert-sig",!1);if(k){if(b&&this.env.signatures&&(e=tinyMCE.get(this.env.composebody),g=e.dom.get("_rc_sig"),g||(j=e.getBody(),h=e.getDoc(),g=h.createElement("div"),g.setAttribute("id","_rc_sig"),this.env.sig_above?(e.getWin().focus(),e=e.selection.getNode(),e.nodeName=="BODY"?(j.insertBefore(g,j.firstChild),j.insertBefore(h.createElement("br"),
-j.firstChild)):(j.insertBefore(g,e.nextSibling),j.insertBefore(h.createElement("br"),e.nextSibling))):(bw.ie&&j.appendChild(h.createElement("br")),j.appendChild(g))),this.env.signatures[f]))this.env.signatures[f].is_html?(j=this.env.signatures[f].text,this.env.signatures[f].plain_text.match(/^--[ -]\r?\n/)||(j=d+"<br />"+j)):(j=this.env.signatures[f].text,j.match(/^--[ -]\r?\n/)||(j=d+"\n"+j),j="<pre>"+j+"</pre>"),g.innerHTML=j}else 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),e>=0&&(h=h.substring(0,e)+h.substring(e+j.length,h.length))),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),this.env.sig_above?e>=0?(h=h.substring(0,e)+j+h.substring(e,h.length),
-d=e-1):(pos=this.get_caret_pos(g.get(0)))?(h=h.substring(0,pos)+"\n"+j+"\n\n"+h.substring(pos,h.length),d=pos):(d=0,h="\n\n"+j+"\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"+j)):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;var b,d=0,e=$("input[type=file]",a).get(0),f=e.files?e.files.length:e.value?1:0;if(f){if(e.files&&this.env.max_filesize&&
-this.env.filesizeerror){for(b=0;b<f;b++)d+=e.files[b].size;if(d&&d>this.env.max_filesize){this.display_message(this.env.filesizeerror,"error");return}}b=this.async_upload_form(a,"upload",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});f="<span>"+this.get_label("uploading"+(f>1?"many":""))+"</span>";d=b.replace(/^rcmupload/,"");this.env.loadingicon&&(f='<img src="'+this.env.loadingicon+'" alt="" />'+f);this.env.cancelicon&&(f='<a title="'+this.get_label("cancel")+'" onclick="return rcmail.cancel_attachment_upload(\''+d+"', '"+b+'\');" href="#cancelupload"><img src="'+this.env.cancelicon+'" alt="" /></a>'+f);this.add2attachment_list(d,
-{name:"",html:f,complete:!1});this.env.upload_progress_time&&this.upload_progress_start("upload",d)}this.gui_objects.attachmentform=a;return!0};this.add2attachment_list=function(a,b,d){if(!this.gui_objects.attachmentlist)return!1;var e,f=$("<li>").attr("id",a).html(b.html);d&&(e=document.getElementById(d))?f.replaceAll(e):f.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<b.length;i++)b[i].id==a&&this.gui_objects.attachmentlist.removeChild(b[i])};this.remove_attachment=function(a){a&&this.env.attachments[a]&&this.http_post("remove-attachment",{_id:this.env.compose_id,_file:a});return!0};this.cancel_attachment_upload=function(a,b){if(!a||!b)return!1;this.remove_from_attachment_list(a);$("iframe[name='"+b+"']").remove();
-return!1};this.upload_progress_start=function(a,b){window.setTimeout(function(){rcmail.http_request(a,{_progress:b})},this.env.upload_progress_time*1E3)};this.upload_progress_update=function(a){var b=$("#"+a.name+"> span");b.length&&a.text&&(b.text(a.text),a.done||this.upload_progress_start(a.action,a.name))};this.add_contact=function(a){a&&this.http_post("addcontact","_address="+a);return!0};this.qsearch=function(a){if(a!=""){var b,d="",e=[],f=this.env.search_mods,g=this.env.mailbox,h=this.set_busy(!0,
-"searching");this.message_list?(this.clear_message_list(),f&&(f=f[g]?f[g]:f["*"])):this.contact_list&&this.list_contacts_clear();if(f){for(b in f)e.push(b);d+="&_headers="+e.join(",")}this.gui_objects.search_filter&&(d+="&_filter="+this.gui_objects.search_filter.value);this.env.current_page=1;a=this.http_request("search","_q="+urlencode(a)+(g?"&_mbox="+urlencode(g):"")+(this.env.source?"&_source="+urlencode(this.env.source):"")+(this.env.group?"&_gid="+urlencode(this.env.group):"")+(d?d:""),h);this.env.qsearch=
-{lock:h,request:a}}};this.reset_qsearch=function(){if(this.gui_objects.qsearchbox)this.gui_objects.qsearchbox.value="";this.env.qsearch&&this.abort_request(this.env.qsearch);this.env.qsearch=null;this.env.search_request=null};this.sent_successfully=function(a,b){this.display_message(b,a);window.setTimeout(function(){l.list_mailbox()},500)};this.ksearch_keydown=function(a,b,d){this.ksearch_timer&&clearTimeout(this.ksearch_timer);var e=rcube_event.get_keycode(a),f=rcube_event.get_modifier(a);switch(e){case 38:case 40:if(!this.ksearch_pane)break;
-e=e==38?1:0;b=document.getElementById("rcmksearchSelected");if(!b)b=this.ksearch_pane.__ul.firstChild;b&&this.ksearch_select(e?b.previousSibling:b.nextSibling);return rcube_event.cancel(a);case 9:if(f==SHIFT_KEY||!this.ksearch_visible()){this.ksearch_hide();return}case 13:if(!this.ksearch_visible())return!1;this.insert_recipient(this.ksearch_selected);this.ksearch_hide();return rcube_event.cancel(a);case 27:this.ksearch_hide();return;case 37:case 39:if(f!=SHIFT_KEY)return}this.ksearch_timer=window.setTimeout(function(){l.ksearch_get_results(d)},
-200);this.ksearch_input=b;return!0};this.ksearch_visible=function(){return this.ksearch_selected!==null&&this.ksearch_selected!==void 0&&this.ksearch_value};this.ksearch_select=function(a){var b=$("#rcmksearchSelected");b[0]&&a&&b.removeAttr("id").removeClass("selected");if(a)$(a).attr("id","rcmksearchSelected").addClass("selected"),this.ksearch_selected=a._rcm_id};this.insert_recipient=function(a){if(this.env.contacts[a]&&this.ksearch_input){var b=this.ksearch_input.value,d=this.get_caret_pos(this.ksearch_input),
-d=b.lastIndexOf(this.ksearch_value,d),e=!1,f="",g=b.substring(0,d),b=b.substring(d+this.ksearch_value.length,b.length);this.ksearch_destroy();typeof this.env.contacts[a]==="object"&&this.env.contacts[a].id?(f+=this.env.contacts[a].name+", ",this.group2expand=$.extend({},this.env.contacts[a]),this.group2expand.input=this.ksearch_input,this.http_request("mail/group-expand","_source="+urlencode(this.env.contacts[a].source)+"&_gid="+urlencode(this.env.contacts[a].id),!1)):typeof this.env.contacts[a]===
-"string"&&(f=this.env.contacts[a]+", ",e=!0);this.ksearch_input.value=g+f+b;d+=f.length;this.ksearch_input.setSelectionRange&&this.ksearch_input.setSelectionRange(d,d);e&&this.triggerEvent("autocomplete_insert",{field:this.ksearch_input,insert:f})}};this.replace_group_recipients=function(a,b){if(this.group2expand&&this.group2expand.id==a)this.group2expand.input.value=this.group2expand.input.value.replace(this.group2expand.name,b),this.triggerEvent("autocomplete_insert",{field:this.group2expand.input,
-insert:b}),this.group2expand=null};this.ksearch_get_results=function(a){var b=this.ksearch_input?this.ksearch_input.value:null;if(b!==null){this.ksearch_pane&&this.ksearch_pane.is(":visible")&&this.ksearch_pane.hide();var d=this.get_caret_pos(this.ksearch_input),e=b.lastIndexOf(",",d-1),b=b.substring(e+1,d),e=this.env.autocomplete_min_length,d=this.ksearch_data,b=$.trim(b);if(b!=this.ksearch_value)if(b.length&&b.length<e){if(!this.env.acinfo)this.env.acinfo=this.display_message(this.get_label("autocompletechars").replace("$min",
-e))}else if(this.env.acinfo&&this.hide_message(this.env.acinfo),e=this.ksearch_value,this.ksearch_value=b,this.ksearch_destroy(),b.length&&(!e||!e.length||!(b.indexOf(e)==0&&(!d||!d.num)&&this.env.contacts&&!this.env.contacts.length))){var f,g,h,d=(new Date).getTime(),e=a&&a.threads?a.threads:1;f=a&&a.sources?a.sources:[];a=a&&a.action?a.action:"mail/autocomplete";this.ksearch_data={id:d,sources:f.slice(),action:a,locks:[],requests:[],num:f.length};for(f=0;f<e;f++){h=this.ksearch_data.sources.shift();
-if(e>1&&h===null)break;g=this.display_message(this.get_label("searching"),"loading");h=this.http_post(a,"_search="+urlencode(b)+"&_id="+d+(h?"&_source="+urlencode(h):""),g);this.ksearch_data.locks.push(g);this.ksearch_data.requests.push(h)}}}};this.ksearch_query_results=function(a,b,d){if(this.ksearch_value&&!(this.ksearch_input&&b!=this.ksearch_value)){var e,f,g,b=this.ksearch_value,h=this.env.autocomplete_max?this.env.autocomplete_max:15;if(!this.ksearch_pane)e=$("<ul>"),this.ksearch_pane=$("<div>").attr("id",
-"rcmKSearchpane").css({position:"absolute","z-index":3E4}).append(e).appendTo(document.body),this.ksearch_pane.__ul=e[0];e=this.ksearch_pane.__ul;d&&this.ksearch_pane.data("reqid")==d?h-=e.childNodes.length:(this.ksearch_pane.data("reqid",d),e.innerHTML="",this.env.contacts=[],f=$(this.ksearch_input).offset(),this.ksearch_pane.css({left:f.left+"px",top:f.top+this.ksearch_input.offsetHeight+"px",display:"none"}));if(a&&a.length)for(i=0;i<a.length&&h>0;i++)g=typeof a[i]==="object"?a[i].name:a[i],f=
-document.createElement("LI"),f.innerHTML=g.replace(RegExp("("+RegExp.escape(b)+")","ig"),"##$1%%").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/##([^%]+)%%/g,"<b>$1</b>"),f.onmouseover=function(){l.ksearch_select(this)},f.onmouseup=function(){l.ksearch_click(this)},f._rcm_id=this.env.contacts.length+i,e.appendChild(f),h-=1;if(e.childNodes.length&&(this.ksearch_pane.show(),!this.env.contacts.length))$("li:first",e).attr("id","rcmksearchSelected").addClass("selected"),this.ksearch_selected=0;
-if(a&&a.length)this.env.contacts=this.env.contacts.concat(a);if(h>0&&this.ksearch_data.id==d&&this.ksearch_data.sources.length&&(e=this.ksearch_data,h=e.sources.shift()))data.num--,a=this.display_message(this.get_label("searching"),"loading"),d=this.http_post(e.action,"_search="+urlencode(b)+"&_id="+d+"&_source="+urlencode(h),a),this.ksearch_data.locks.push(a),this.ksearch_data.requests.push(d)}};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_input=null;this.ksearch_hide()};this.ksearch_hide=function(){this.ksearch_selected=null;this.ksearch_value="";this.ksearch_pane&&this.ksearch_pane.hide();this.ksearch_destroy()};this.ksearch_destroy=function(){var a,b,d=this.ksearch_data;if(d){for(a=0,b=d.locks.length;a<b;a++)this.abort_request({request:d.requests[a],lock:d.locks[a]});this.ksearch_data=null}};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,e,f=this,g=!1;e=this.env.source?this.env.address_sources[this.env.source]:null;(d=a.get_single_selection())?this.preview_timer=window.setTimeout(function(){f.load_contact(d,"show")},200):this.env.contentframe&&this.show_contentframe(!1);if(a.selection.length)if(e)g=!e.readonly;else for(b in a.selection)if((e=String(a.selection[b]).replace(/^[^-]+-/,
-""))&&this.env.address_sources[e]&&!this.env.address_sources[e].readonly){g=!0;break}this.enable_command("compose",a.selection.length>0);this.enable_command("edit",d&&g);this.enable_command("delete",a.selection.length&&g);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"),this.location_href(this.env.comm_path+
-(a?"&_source="+urlencode(a):"")+e,f))};this.list_contacts_remote=function(a,b,d){this.list_contacts_clear();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.list_contacts_clear=function(){this.contact_list.clear(!0);this.show_contentframe(!1);this.enable_command("delete","compose",!1)};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),a||(this.contact_list.clear_selection(),this.enable_command("delete","compose",!1));else if(d)return!1;if(b&&(a||b=="add")&&!this.drag_active)this.env.group&&(e+="&_gid="+urlencode(this.env.group)),this.location_href(this.env.comm_path+"&_action="+b+"&_source="+urlencode(this.env.source)+"&_cid="+urlencode(a)+
-e,f,!0);return!0};this.group_member_change=function(a,b,d,e){var a=a=="add"?"add":"del",f=this.display_message(this.get_label(a=="add"?"addingmember":"removingmember"),"loading");this.http_post("group-"+a+"members","_cid="+urlencode(b)+"&_source="+urlencode(d)+"&_gid="+urlencode(e),f)};this.copy_contact=function(a,b){a||(a=this.contact_list.get_selection().join(","));if(b.type=="group"&&b.source==this.env.source)this.group_member_change("add",a,b.source,b.id);else if(b.type=="group"&&!this.env.address_sources[b.source].readonly){var d=
-this.display_message(this.get_label("copyingcontact"),"loading");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):""),d)}else b.id!=this.env.source&&a&&this.env.address_sources[b.id]&&!this.env.address_sources[b.id].readonly&&(d=this.display_message(this.get_label("copyingcontact"),"loading"),this.http_post("copy","_cid="+urlencode(a)+"&_source="+urlencode(this.env.source)+
-"&_to="+urlencode(b.id)+(this.env.group?"&_gid="+urlencode(this.env.group):""),d))};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=[],f="";if(this.env.cid)e.push(this.env.cid);else{for(d=0;d<a.length;d++)b=a[d],e.push(b),this.contact_list.remove_row(b,d==a.length-1);a.length==1&&this.show_contentframe(!1)}this.env.group&&(f+="&_gid="+urlencode(this.env.group));this.env.search_request&&
-(f+="&_search="+this.env.search_request);this.http_post("delete","_cid="+urlencode(e.join(","))+"&_source="+urlencode(this.env.source)+"&_from="+(this.env.action?this.env.action:"")+f);return!0}};this.update_contact_row=function(a,b,d,e){var f,g=this.contact_list,a=String(a).replace(this.identifier_expr,"_");g.rows[a]||(a=a+"-"+e,d&&(d=d+"-"+e));if(g.rows[a]&&(f=g.rows[a].obj)){for(e=0;e<b.length;e++)f.cells[e]&&$(f.cells[e]).html(b[e]);if(d)d=String(d).replace(this.identifier_expr,"_"),f.id="rcmrow"+
-d,g.remove_row(a),g.init_row(f),g.selection[0]=d,f.style.display=""}};this.add_contact_row=function(a,b){if(!this.gui_objects.contactslist||!this.gui_objects.contactslist.tBodies[0])return!1;var d=this.gui_objects.contactslist.tBodies[0].rows.length%2,e=document.createElement("tr");e.id="rcmrow"+String(a).replace(this.identifier_expr,"_");e.className="contact "+(d?"even":"odd");this.contact_list.in_selection(a)&&(e.className+=" selected");for(var f in b)col=document.createElement("td"),col.className=
-String(f).toLowerCase(),col.innerHTML=b[f],e.appendChild(col);this.contact_list.insert_row(e);this.enable_command("export",this.contact_list.rowcount>0)};this.init_contact_form=function(){var a=this,b;this.set_photo_actions($("#ff_photo").val());for(b in this.env.coltypes)this.init_edit_field(b,null);$(".contactfieldgroup .row a.deletebutton").click(function(){a.delete_edit_field(this);return!1});$("select.addfieldmenu").change(function(){a.insert_edit_field($(this).val(),$(this).attr("rel"),this);
-this.selectedIndex=0});$("input[type='text']:visible").first().focus()};this.group_create=function(){if(this.gui_objects.folderlist){if(!this.name_input)this.name_input=$("<input>").attr("type","text"),this.name_input.bind("keydown",function(a){return rcmail.add_input_keydown(a)}),this.name_input_li=$("<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=$("<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(){if(this.env.group&&
-confirm(this.get_label("deletegroupconfirm"))){var a=this.set_busy(!0,"groupdeleting");this.http_post("group-delete","_source="+urlencode(this.env.source)+"&_gid="+urlencode(this.env.group),a)}};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,d=$("<a>").attr("href","#").attr("rel",a.source+":"+a.id).click(function(){return rcmail.command("listgroup",a,this)}).html(a.name),d=$("<li>").attr({id:"rcmli"+b.replace(this.identifier_expr,"_"),"class":"contactgroup"}).append(d);
-this.env.contactfolders[b]=this.env.contactgroups[b]=a;this.add_contact_group_row(a,d);this.triggerEvent("group_insert",{id:a.id,source:a.source,name:a.name,li:d[0]})};this.update_contact_group=function(a){this.reset_add_input();var b="G"+a.source+a.id,d=this.get_folder_li(b),e;if(d&&a.newid){e="G"+a.source+a.newid;var f=$.extend({},a);d.id=String("rcmli"+e).replace(this.identifier_expr,"_");this.env.contactfolders[e]=this.env.contactfolders[b];this.env.contactfolders[e].id=a.newid;this.env.group=
-a.newid;delete this.env.contactfolders[b];delete this.env.contactgroups[b];f.id=a.newid;f.type="group";e=$("<a>").attr("href","#").attr("rel",a.source+":"+a.newid).click(function(){return rcmail.command("listgroup",f,this)}).html(a.name);$(d).children().replaceWith(e)}else if(d&&(e=d.firstChild)&&e.tagName.toLowerCase()=="a")e.innerHTML=a.name;this.env.contactfolders[b].name=this.env.contactgroups[b].name=a.name;this.add_contact_group_row(a,$(d),!0);this.triggerEvent("group_update",{id:a.id,source:a.source,
-name:a.name,li:d[0],newid:a.newid})};this.add_contact_group_row=function(a,b,d){var e=a.name.toUpperCase(),f=this.get_folder_li(a.source),a="rcmliG"+a.source.replace(this.identifier_expr,"_");d?(d=b.clone(!0),b.remove()):d=b;$('li[id^="'+a+'"]',this.gui_objects.folderlist).each(function(a,b){if(e>=$(this).text().toUpperCase())f=b;else return!1});d.insertAfter(f)};this.update_group_commands=function(){var a=this.env.source!=""?this.env.address_sources[this.env.source]:null;this.enable_command("group-create",
-a&&a.groups&&!a.readonly);this.enable_command("group-rename","group-delete",a&&a.groups&&this.env.group&&!a.readonly)};this.init_edit_field=function(a,b){b||(b=$(".ff_"+a));b.focus(function(){l.focus_textfield(this)}).blur(function(){l.blur_textfield(this)}).each(function(){this._placeholder=this.title=l.env.coltypes[a].label;l.blur_textfield(this)})};this.insert_edit_field=function(a,b,d){var e=$("#ff_"+a);if(e.length)e.show().focus(),$(d).children('option[value="'+a+'"]').prop("disabled",!0);else if($(".ff_"+
-a),e=$("#contactsection"+b+" .contactcontroller"+a),e.length||(e=$("<fieldset>").addClass("contactfieldgroup contactcontroller"+a).insertAfter($("#contactsection"+b+" .contactfieldgroup").last())),e.length&&e.get(0).nodeName=="FIELDSET"){var f,b=this.env.coltypes[a],g=$("<div>").addClass("row"),h=$("<div>").addClass("contactfieldcontent data"),k=$("<div>").addClass("contactfieldlabel label");b.subtypes_select?k.html(b.subtypes_select):k.html(b.label);var j=b.limit!=1?"[]":"";if(b.type=="text"||b.type==
-"date")f=$("<input>").addClass("ff_"+a).attr({type:"text",name:"_"+a+j,size:b.size}).appendTo(h),this.init_edit_field(a,f);else if(b.type=="composite"){var o,m,n=[],p=[];if(f=this.env[a+"_template"])for(o=0;o<f.length;o++)n.push(f[o][1]),p.push(f[o][2]);else for(o in b.childs)n.push(o);for(var q=0;q<n.length;q++)o=n[q],f=b.childs[o],f=$("<input>").addClass("ff_"+o).attr({type:"text",name:"_"+o+j,size:f.size}).appendTo(h),h.append(p[q]||" "),this.init_edit_field(o,f),m||(m=f);f=m}else if(b.type=="select"){f=
-$("<select>").addClass("ff_"+a).attr("name","_"+a+j).appendTo(h);var s=f.attr("options");s[s.length]=new Option("---","");b.options&&$.each(b.options,function(a,b){s[s.length]=new Option(b,a)})}if(f){$('<a href="#del"></a>').addClass("contactfieldbutton deletebutton").attr({title:this.get_label("delete"),rel:a}).html(this.env.delbutton).click(function(){l.delete_edit_field(this);return!1}).appendTo(h);g.append(k).append(h).appendTo(e.show());f.first().focus();if(!b.count)b.count=0;++b.count==b.limit&&
-b.limit&&$(d).children('option[value="'+a+'"]').prop("disabled",!0)}}};this.delete_edit_field=function(a){var b=$(a).attr("rel"),d=this.env.coltypes[b],e=$(a).parents("fieldset.contactfieldgroup"),f=e.parent().find("select.addfieldmenu");--d.count<=0&&d.visible?$(a).parent().children("input").val("").blur():($(a).parents("div.row").remove(),e.children("div.row").length||e.hide());f.length&&(a=f.children('option[value="'+b+'"]'),a.length?a.prop("disabled",!1):$("<option>").attr("value",b).html(d.label).appendTo(f),
-f.show())};this.upload_contact_photo=function(a){if(a&&a.elements._photo.value)this.async_upload_form(a,"upload-photo",function(){rcmail.set_busy(!1,null,rcmail.photo_upload_id)}),this.photo_upload_id=this.set_busy(!0,"uploading")};this.replace_contact_photo=function(a){var b=a=="-del-"?this.env.photo_placeholder:this.env.comm_path+"&_action=photo&_source="+this.env.source+"&_cid="+this.env.cid+"&_photo="+a;this.set_photo_actions(a);$(this.gui_objects.contactphoto).children("img").attr("src",b)};
-this.photo_upload_end=function(){this.set_busy(!1,null,this.photo_upload_id);delete this.photo_upload_id};this.set_photo_actions=function(a){var b,d=this.buttons["upload-photo"];for(b=0;d&&b<d.length;b++)$("#"+d[b].id).html(this.get_label(a=="-del-"?"addphoto":"replacephoto"));$("#ff_photo").val(a);this.enable_command("upload-photo",this.env.coltypes.photo?!0:!1);this.enable_command("delete-photo",this.env.coltypes.photo&&a!="-del-")};this.advanced_search=function(){var a="&_form=1",b=window;this.env.contentframe&&
-window.frames&&window.frames[this.env.contentframe]&&(a+="&_framed=1",b=window.frames[this.env.contentframe],this.contact_list.clear_selection());this.location_href(this.env.comm_path+"&_action=search"+a,b,!0);return!0};this.unselect_directory=function(){if(this.env.address_sources.length>1||this.env.group!="")this.select_folder("",this.env.group?"G"+this.env.source+this.env.group:this.env.source),this.env.group="",this.env.source=""};this.section_select=function(a){var a=a.get_single_selection(),
-b="",d=window;a&&(this.env.contentframe&&window.frames&&window.frames[this.env.contentframe]&&(b="&_framed=1",d=window.frames[this.env.contentframe]),this.location_href(this.env.comm_path+"&_action=edit-prefs&_section="+a+b,d,!0));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),this.location_href(this.env.comm_path+"&_action="+b+"&_iid="+a+d,e);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.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();$("#mailboxroot").mouseover(function(){a.focus_subscription(this.id)}).mouseout(function(){a.unfocus_subscription(this.id)})};this.focus_subscription=function(a){var b,d,e=RegExp.escape(this.env.delimiter),e=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])!==null&&this.check_droptarget(d)&&!this.env.subscriptionrows[this.get_folder_row_id(this.env.mailbox)][2]&&
-d!=this.env.mailbox.replace(e,"")&&!d.match(RegExp("^"+RegExp.escape(this.env.mailbox+this.env.delimiter))))this.env.dstfolder=d,$(b).addClass("droptarget")};this.unfocus_subscription=function(a){var b=$("#"+a);this.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.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);this.env.mailbox&&this.env.dstfolder!==null&&this.env.dstfolder!=this.env.mailbox&&this.env.dstfolder!=this.env.mailbox.replace(RegExp("["+a+"]?[^"+a+"]+$"),"")&&(a=this.env.mailbox.replace(RegExp("[^"+a+"]*["+a+"]","g"),""),a=this.env.dstfolder===""?a:this.env.dstfolder+this.env.delimiter+
-a,a!=this.env.mailbox&&(this.http_post("rename-folder","_folder_oldname="+urlencode(this.env.mailbox)+"&_folder_newname="+urlencode(a),this.set_busy(!0,"foldermoving")),this.subscription_list.draglayer.hide()));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,f,g){if(!this.gui_objects.subscriptionlist)return!1;var h,k,j,l,m,n=[],p=[],q=this.gui_objects.subscriptionlist.tBodies[0];h=$("tr",q).get(1);var s="rcmrow"+(new Date).getTime();if(!h)return this.goto_url("folders"),!1;h=$(h).clone(!0);h.attr("id",s);h.attr("class",g);h.find("td:first").html(b);$('input[name="_subscribed[]"]',h).val(a).prop({checked:e?!0:!1,disabled:d?
-!0:!1});this.env.subscriptionrows[s]=[a,b,0];l=[];$.each(this.env.subscriptionrows,function(a,b){l.push(b)});l.sort(function(a,b){return a[0]<b[0]?-1:a[0]>b[0]?1:0});for(k in l)l[k][2]?(p.push(l[k][0]),j=l[k][0]+this.env.delimiter):j&&l[k][0].indexOf(j)==0?p.push(l[k][0]):(n.push(l[k][0]),j=null);for(k=0;k<p.length;k++)a.indexOf(p[k]+this.env.delimiter)==0&&(m=this.get_folder_row_id(p[k]));for(k=0;!m&&k<n.length;k++)k&&n[k]==a&&(m=this.get_folder_row_id(n[k-1]));m?$("#"+m).after(h):h.appendTo(q);
-this.subscription_list.clear_selection();f||this.init_subscription_list();h=h.get(0);h.scrollIntoView&&h.scrollIntoView();return h};this.replace_folder_row=function(a,b,d,e,f){if(!this.gui_objects.subscriptionlist)return!1;var g,h,k,j,l=this.get_folder_row_id(a),m=RegExp("^"+RegExp.escape(a));g=$('input[name="_subscribed[]"]',$("#"+l)).prop("checked");var n=this.get_subfolders(a);this._remove_folder_row(l);e=$(this.add_folder_row(b,d,e,g,!0,f));if(d=n.length)j=a.split(this.env.delimiter).length-b.split(this.env.delimiter).length;
-for(a=0;a<d;a++)if(l=n[a],g=this.env.subscriptionrows[l][0],f=this.env.subscriptionrows[l][1],h=$("#"+l),k=h.clone(!0),h.remove(),e.after(k),e=k,g=g.replace(m,b),$('input[name="_subscribed[]"]',e).val(g),this.env.subscriptionrows[l][0]=g,j!=0){if(j>0)for(g=j;g>0;g--)f=f.replace(/^&nbsp;&nbsp;&nbsp;&nbsp;/,"");else for(g=j;g<0;g++)f="&nbsp;&nbsp;&nbsp;&nbsp;"+f;e.find("td:first").html(f);this.env.subscriptionrows[l][1]=f}this.init_subscription_list()};this.remove_folder_row=function(a,b){var d,e,f=
-[];d=this.get_folder_row_id(a);b&&(f=this.get_subfolders(a));this._remove_folder_row(d);for(d=0,e=f.length;d<e;d++)this._remove_folder_row(f[d])};this._remove_folder_row=function(a){this.subscription_list.remove_row(a.replace(/^rcmrow/,""));$("#"+a).remove();delete this.env.subscriptionrows[a]};this.get_subfolders=function(a){for(var b=[],d=RegExp("^"+RegExp.escape(a)+RegExp.escape(this.env.delimiter)),e=$("#"+this.get_folder_row_id(a)).get(0);e=e.nextSibling;)if(e.id)if(a=this.env.subscriptionrows[e.id][0],
-d.test(a))b.push(e.id);else break;return b};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){var b,d=this.env.subscriptionrows;for(b in d)if(d[b]&&d[b][0]==a)break;return b};this.show_folder=
-function(a,b,d){var e=window,a="&_action=edit-folder&_mbox="+urlencode(a);b&&(a+="&_path="+urlencode(b));this.env.contentframe&&window.frames&&window.frames[this.env.contentframe]&&(e=window.frames[this.env.contentframe],a+="&_framed=1");String(e.location.href).indexOf(a)>=0&&!d?this.show_contentframe(!0):this.location_href(this.env.comm_path+a,e,!0)};this.disable_subscription=function(a){(a=this.get_folder_row_id(a))&&$('input[name="_subscribed[]"]',$("#"+a)).prop("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)};var t=function(a,b){var d=document.getElementById(b.id);if(d){var e=!1;if(b.type=="image")d=d.parentNode,e=!0;d._command=a;d._id=b.id;if(b.sel&&(d.onmousedown=function(){return rcmail.button_sel(this._command,this._id)},d.onmouseup=function(){return rcmail.button_out(this._command,this._id)},e))(new Image).src=b.sel;if(b.over&&(d.onmouseover=
-function(){return rcmail.button_over(this._command,this._id)},d.onmouseout=function(){return rcmail.button_out(this._command,this._id)},e))(new Image).src=b.over}};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<this.buttons[a].length;b++)t(a,this.buttons[a][b])};this.set_button=
-function(a,b){var d,e,f=this.buttons[a];if(!f||!f.length)return!1;for(var g=0;g<f.length;g++){d=f[g];if((e=document.getElementById(d.id))&&d.type=="image"&&!d.status){if(d.pas=e._original_src?e._original_src:e.src,e.runtimeStyle&&e.runtimeStyle.filter&&e.runtimeStyle.filter.match(/src=['"]([^'"]+)['"]/))d.pas=RegExp.$1}else if(e&&!d.status)d.pas=String(e.className);if(e&&d.type=="image"&&d[b])d.status=b,e.src=d[b];else if(e&&d[b]!==void 0)d.status=b,e.className=d[b];if(e&&d.type=="input")d.status=
-b,e.disabled=!b}};this.set_alttext=function(a,b){if(this.buttons[a]&&this.buttons[a].length)for(var d,e,f,g=0;g<this.buttons[a].length;g++)d=this.buttons[a][g],e=document.getElementById(d.id),d.type=="image"&&e?(e.setAttribute("alt",this.get_label(b)),(f=e.parentNode)&&f.tagName.toLowerCase()=="a"&&f.setAttribute("title",this.get_label(b))):e&&e.setAttribute("title",this.get_label(b))};this.button_over=function(a,b){var d,e,f=this.buttons[a];if(!f||!f.length)return!1;for(var g=0;g<f.length;g++)if(d=
-f[g],d.id==b&&d.status=="act"&&(e=document.getElementById(d.id))&&d.over)d.type=="image"?e.src=d.over:e.className=d.over};this.button_sel=function(a,b){var d,e,f=this.buttons[a];if(f&&f.length)for(var g=0;g<f.length;g++)if(d=f[g],d.id==b&&d.status=="act"){if((e=document.getElementById(d.id))&&d.sel)d.type=="image"?e.src=d.sel:e.className=d.sel;this.buttons_sel[b]=a}};this.button_out=function(a,b){var d,e,f=this.buttons[a];if(f&&f.length)for(var g=0;g<f.length;g++)if(d=f[g],d.id==b&&d.status=="act"&&
-(e=document.getElementById(d.id))&&d.act)d.type=="image"?e.src=d.act:e.className=d.act};this.focus_textfield=function(a){a._hasfocus=!0;var b=$(a);(b.hasClass("placeholder")||b.val()==a._placeholder)&&b.val("").removeClass("placeholder").attr("spellcheck",!0)};this.blur_textfield=function(a){a._hasfocus=!1;var b=$(a);a._placeholder&&(!b.val()||b.val()==a._placeholder)&&b.addClass("placeholder").attr("spellcheck",!1).val(a._placeholder)};this.set_pagetitle=function(a){if(a&&document.title)document.title=
-a};this.display_message=function(a,b,d){if(this.is_framed())return parent.rcmail.display_message(a,b,d);if(!this.gui_objects.message){if(b!="loading")this.pending_message=[a,b,d];return!1}var b=b?b:"notice",e=this,f=String(a).replace(this.identifier_expr,"_"),g=b+(new Date).getTime();d||(d=this.message_time*(b=="error"||b=="warning"?2:1));b=="loading"&&(f="loading",d=this.env.request_timeout*1E3,a||(a=this.get_label("loading")));if(this.messages[f])return this.messages[f].obj&&this.messages[f].obj.html(a),
-b=="loading"&&this.messages[f].labels.push({id:g,msg:a}),this.messages[f].elements.push(g),window.setTimeout(function(){e.hide_message(g,b=="loading")},d),g;var h=$("<div>").addClass(b).html(a).data("key",f);$(this.gui_objects.message).append(h).show();this.messages[f]={obj:h,elements:[g]};b=="loading"?this.messages[f].labels=[{id:g,msg:a}]:h.click(function(){return e.hide_message(h)});d>0&&window.setTimeout(function(){e.hide_message(g,b=="loading")},d);return g};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");return this.gui_objects.folderlist?(a=String(a).replace(this.identifier_expr,"_"),document.getElementById(b+a)):null};this.set_message_coltypes=function(a,b){var d=this.message_list,e=d?d.list.tHead:null,f,g,h,k;this.env.coltypes=
-a;if(e){if(b){g=document.createElement("thead");h=document.createElement("tr");for(c=0,k=b.length;c<k;c++){f=document.createElement("td");f.innerHTML=b[c].html;if(b[c].id)f.id=b[c].id;if(b[c].className)f.className=b[c].className;h.appendChild(f)}g.appendChild(h);e.parentNode.replaceChild(g,e);e=g}for(h=0,k=this.env.coltypes.length;h<k;h++)if(g=this.env.coltypes[h],(f=e.rows[0].cells[h])&&(g=="from"||g=="to")){f.id="rcm"+g;if(f.firstChild&&f.firstChild.tagName.toLowerCase()=="a")f=f.firstChild,f.onclick=
-function(){return rcmail.command("sort",this.__col,this)},f.__col=g;f.innerHTML=this.get_label(g)}}this.env.subject_col=null;this.env.flagged_col=null;this.env.status_col=null;if((h=$.inArray("subject",this.env.coltypes))>=0)if(this.env.subject_col=h,d)d.subject_col=h;if((h=$.inArray("flag",this.env.coltypes))>=0)this.env.flagged_col=h;if((h=$.inArray("status",this.env.coltypes))>=0)this.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;if(f=this.get_folder_li(a)){g=this.env.unread_counts[a]?this.env.unread_counts[a]:0;e=$(f).children("a").eq(0);d=e.children("span.unreadcount");!d.length&&g&&(d=$("<span>").addClass("unreadcount").appendTo(e));e=0;if((h=f.getElementsByTagName("div")[0])&&h.className.match(/collapsed/))for(var k in this.env.unread_counts)k.indexOf(a+this.env.delimiter)==0&&(e+=this.env.unread_counts[k]);g&&d.length?d.html(" ("+g+")"):d.length&&d.remove();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+e>0?$(f).addClass("unread"):$(f).removeClass("unread")}d=/^\([0-9]+\)\s+/i;b&&document.title&&(f="",f=String(document.title),f=g&&f.match(d)?f.replace(d,"("+g+") "):g?"("+g+") "+f:f.replace(d,""),this.set_pagetitle(f))};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);h.left=Math.max(0,h.left);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 k=$("<div>");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=$("<div>");j.css({position:"absolute",top:h.top+1,left:h.left+
-1,width:g+"px",height:e+"px",zIndex:99});g=$("<div>");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?(k.addClass(" quota_text_high"),j.addClass("quota_high")):f>=55?(k.addClass(" quota_text_mid"),j.addClass("quota_mid")):(k.addClass(" quota_text_low"),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(!0,"converting");
-this.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);d.log(a)}})};this.plain2html=function(a,b){var d=this.set_busy(!0,"converting");$(document.getElementById(b)).val("<pre>"+a+"</pre>");this.set_busy(!1,null,d)};this.url=function(a,b){var d=typeof b==="string"?"&"+b:"";if(typeof a!==
-"string")b=a;else if(!b||typeof b!=="object")b={};b._action=a?a:this.env.action;var e=this.env.comm_path;if(b._action.match(/([a-z]+)\/([a-z-_.]+)/))b._action=RegExp.$2,e=e.replace(/\_task=[a-z]+/,"_task="+RegExp.$1);var f={},g;for(g in b)b[g]!==void 0&&b[g]!==null&&(f[g]=b[g]);return e+"&"+$.param(f)+d};this.redirect=function(a,b){(b||b===null)&&this.set_busy(!0);this.is_framed()?parent.rcmail.redirect(a,b):this.location_href(a,window)};this.goto_url=function(a,b){this.redirect(this.url(a,b))};this.location_href=
-function(a,b,d){d&&this.lock_frame();bw.ie&&b==window?$("<a>").attr("href",a).appendTo(document.body).get(0).click():b.location.href=a};this.http_request=function(a,b,d){var e=this.url(a,b),a=this.triggerEvent("request"+a,b);if(a!==void 0)if(a===!1)return!1;else b=a;e+="&_remote=1";this.log("HTTP GET: "+e);return $.ajax({type:"GET",url:e,data:{_unlock:d?d:0},dataType:"json",success:function(a){l.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.url(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(a!==void 0)if(a===!1)return!1;else b=a;this.log("HTTP POST: "+e);return $.ajax({type:"POST",url:e,data:b,dataType:"json",success:function(a){l.http_response(a)},error:function(a,b,e){rcmail.http_error(a,b,e,d)}})};this.abort_request=function(a){a.request&&a.request.abort();a.lock&&this.set_busy(!1,null,a.lock)};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&&(this.log(a.exec),eval(a.exec));if(a.callbacks&&a.callbacks.length)for(b=0;b<a.callbacks.length;b++)this.triggerEvent(a.callbacks[b][0],a.callbacks[b][1]);switch(a.action){case "delete":if(this.task=="addressbook"){var d;b=this.contact_list.get_selection();
-d=!1;b&&this.contact_list.rows[b]&&(d=this.env.source==""?(d=String(b).replace(/^[^-]+-/,""))&&this.env.address_sources[d]&&!this.env.address_sources[d].readonly:!this.env.address_sources[this.env.source].readonly);this.enable_command("compose",b&&this.contact_list.rows[b]);this.enable_command("delete","edit",d);this.enable_command("export",this.contact_list&&this.contact_list.rowcount>0)}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":this.env.qsearch=null;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.update_group_commands(),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();a.status&&b&&this.display_message(this.get_label("servererror")+" ("+b+")","error")};this.async_upload_form=function(a,b,d){var e=(new Date).getTime(),f="rcmupload"+e;if(this.env.upload_progress_name){var g=this.env.upload_progress_name,h=$("input[name="+g+"]",a);h.length||(h=$("<input>").attr({type:"hidden",name:g}),h.prependTo(a));h.val(e)}document.all?document.body.insertAdjacentHTML("BeforeEnd",'<iframe name="'+f+'" src="program/blank.gif" style="width:0;height:0;visibility:hidden;"></iframe>'):
-(g=document.createElement("iframe"),g.name=f,g.style.border="none",g.style.width=0,g.style.height=0,g.style.visibility="hidden",document.body.appendChild(g));$(f).bind("load",{ts:e},d);$(a).attr({target:f,action:this.url(b,{_id:this.env.compose_id||"",_uploadid:e}),method:"POST"}).attr(a.encoding?"encoding":"enctype","multipart/form-data").submit();return f};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(!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(){l.keep_alive()},this.env.keep_alive*1E3)};this.keep_alive=function(){this.busy||this.http_request("keep-alive")};this.check_for_recent=function(a){if(!this.busy){var b,d="_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(a.selectionEnd!==void 0)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=[];for(d=0,e=a.elements.length;d<e;d++)if(f=a.elements[d],f.type!="hidden")if(b&&f.disabled)this.disabled_form_elements.push(f);else if(b||this.disabled_form_elements&&$.inArray(f,this.disabled_form_elements)<0)f.disabled=b}}}rcube_webmail.long_subject_title=function(l,t){if(!l.title){var a=$(l);if(a.width()+t*15>a.parent().width())l.title=a.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;
+function rcube_webmail(){this.env={recipients_separator:",",recipients_delimiter:", "};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 i=this;this.dblclick_time=500;this.message_time=4E3;this.identifier_expr=RegExp("[^0-9a-z-_]","gi");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){i.http_error(a,b,d)},beforeSend:function(a){a.setRequestHeader("X-Roundcube-Request",i.env.request_token)}});this.set_env=function(a,b){if(null!=a&&"object"===typeof a&&!b)for(var d in a)this.env[d]=a[d];else this.env[a]=b};this.add_label=function(a,b){"string"==typeof a?this.labels[a]=b:"object"==typeof a&&$.extend(this.labels,a)};this.register_button=function(a,b,d,e,f,h){this.buttons[a]||(this.buttons[a]=[]);b={id:b,type:d};if(e)b.act=e;if(f)b.sel=f;
+if(h)b.over=h;this.buttons[a].push(b);this.loaded&&s(a,b)};this.gui_object=function(a,b){this.gui_objects[a]=this.loaded?rcube_find_object(b):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,b=this;
+this.task=this.env.task;if(!bw.dom||!bw.xmlhttp_test())this.goto_url("error","_code=0x199");else{for(a in this.gui_containers)this.gui_containers[a]=$("#"+this.gui_containers[a]);for(a in this.gui_objects)this.gui_objects[a]=rcube_find_object(this.gui_objects[a]);if(this.env.x_frame_options)try{if("deny"==this.env.x_frame_options&&top.location.href!=self.location.href)top.location.href=self.location.href;else if(top.location.hostname!=self.location.hostname)throw 1;}catch(d){$("form").each(function(){i.lock_form(this,
+!0)});this.display_message("Blocked: possible clickjacking attack!","error");return}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","save-pref","compose","undo",!0);this.env.permaurl&&this.enable_command("permaurl",!0);switch(this.task){case "mail":this.enable_command("list","checkmail","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(a){b.init_message_row(a)},this.message_list.addEventListener("dblclick",function(a){b.msglist_dbl_click(a)}),this.message_list.addEventListener("click",function(a){b.msglist_click(a)}),this.message_list.addEventListener("keypress",function(a){b.msglist_keypress(a)}),this.message_list.addEventListener("select",
+function(a){b.msglist_select(a)}),this.message_list.addEventListener("dragstart",function(a){b.drag_start(a)}),this.message_list.addEventListener("dragmove",function(a){b.drag_move(a)}),this.message_list.addEventListener("dragend",function(a){b.drag_end(a)}),this.message_list.addEventListener("expandcollapse",function(a){b.msglist_expand(a)}),this.message_list.addEventListener("column_replace",function(a){b.msglist_set_coltypes(a)}),document.onmouseup=function(a){return b.doc_mouse_up(a)},this.gui_objects.messagelist.parentNode.onmousedown=
+function(a){return b.click_on_list(a)},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(null!=this.env.search_text)this.gui_objects.qsearchbox.value=this.env.search_text;$(this.gui_objects.qsearchbox).focusin(function(){rcmail.message_list.blur()})}!this.env.flag_for_deletion&&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,forward-attachment".split(",");if("show"==this.env.action||"preview"==this.env.action){this.enable_command(this.env.message_commands,this.env.uid);this.enable_command("reply-list",this.env.list_post);"show"==this.env.action&&this.http_request("pagenav","_uid="+this.env.uid+"&_mbox="+urlencode(this.env.mailbox)+(this.env.search_request?"&_search="+
+this.env.search_request:""),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)}"preview"==this.env.action&&this.is_framed()&&(this.enable_command("compose","add-contact",!1),parent.rcmail.show_contentframe(!0))}else if("compose"==this.env.action){this.env.compose_commands=["send-attachment","remove-attachment","send","cancel","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){i.set_spellcheck_state(a)},this.env.compose_commands.push("spellcheck"),this.set_spellcheck_state("ready"),"1"==$("input[name='_is_html']").val()&&this.display_spellcheck_controls(!1);document.onmouseup=function(a){return b.doc_mouse_up(a)};this.init_messageform()}else"print"==this.env.action&&
+this.env.uid&&(bw.safari?window.setTimeout("window.print()",10):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&&(a="_uid="+this.env.uid+"&_mbox="+urlencode(this.env.mailbox),confirm(this.get_label("mdnrequest"))?this.http_post("sendmdn",a):this.http_post("mark",a+"&_flag=mdnsent"));break;case "addressbook":if(this.gui_objects.folderlist)this.env.contactfolders=
+$.extend($.extend({},this.env.address_sources),this.env.contactgroups);this.enable_command("add","import",this.env.writable_source);this.enable_command("list","listgroup","listsearch","advanced-search",!0);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(a){b.triggerEvent("insertrow",{cid:a.uid,row:a})},this.contact_list.addEventListener("keypress",
+function(a){b.contactlist_keypress(a)}),this.contact_list.addEventListener("select",function(a){b.contactlist_select(a)}),this.contact_list.addEventListener("dragstart",function(a){b.drag_start(a)}),this.contact_list.addEventListener("dragmove",function(a){b.drag_move(a)}),this.contact_list.addEventListener("dragend",function(a){b.drag_end(a)}),this.contact_list.init(),this.env.cid&&this.contact_list.highlight_row(this.env.cid),this.gui_objects.contactslist.parentNode.onmousedown=function(a){return b.click_on_list(a)},
+document.onmouseup=function(a){return b.doc_mouse_up(a)},this.gui_objects.qsearchbox&&$(this.gui_objects.qsearchbox).focusin(function(){rcmail.contact_list.blur()}),this.update_group_commands(),this.command("list");this.set_page_buttons();this.env.cid&&(this.enable_command("show","edit",!0),this.gui_objects.editform&&$("input.groupmember").change(function(){i.group_member_change(this.checked?"add":"del",i.env.cid,i.env.source,this.value)}));this.gui_objects.editform&&(this.enable_command("save",!0),
+("add"==this.env.action||"edit"==this.env.action)&&this.init_contact_form());this.gui_objects.qsearchbox&&this.enable_command("search","reset-search","moveto",!0);break;case "settings":this.enable_command("preferences","identities","save","folders",!0);if("identities"==this.env.action)this.enable_command("add",2>this.env.identities_level);else if("edit-identity"==this.env.action||"add-identity"==this.env.action)this.enable_command("add",2>this.env.identities_level),this.enable_command("save","delete",
+"edit","toggle-editor",!0);else if("folders"==this.env.action)this.enable_command("subscribe","unsubscribe","create-folder","rename-folder",!0);else if("edit-folder"==this.env.action&&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(a){b.identity_select(a)}),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(a){b.section_select(a)}),this.sections_list.init(),this.sections_list.focus()):
+this.gui_objects.subscriptionlist&&this.init_subscription_list();break;case "login":a=$("#rcmloginuser");a.bind("keyup",function(a){return rcmail.login_user_keyup(a)});""==a.val()?a.focus():$("#rcmloginpwd").focus();var e=new Date;a=e.getTimezoneOffset()/-60;e=e.getStdTimezoneOffset()/-60;$("#rcmlogintz").val(e);$("#rcmlogindst").val(a>e?1:0);$("form").submit(function(){$("input[type=submit]",this).prop("disabled",!0);rcmail.display_message("","loading")});this.enable_command("login",!0)}bw.ie&&$("input[type=file]").keydown(function(a){"13"==
+a.keyCode&&a.preventDefault()});this.loaded=!0;this.pending_message&&this.display_message(this.pending_message[0],this.pending_message[1],this.pending_message[2]);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 f in this.onloads)if("string"===typeof this.onloads[f])eval(this.onloads[f]);else if("function"===typeof this.onloads[f])this.onloads[f]();this.start_keepalive()}};this.log=
+function(a){window.console&&console.log&&console.log(a)};this.command=function(a,b,d){var e,f,h,g;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("mail"==this.task&&"compose"==this.env.action&&0>$.inArray(a,this.env.compose_commands)&&this.cmp_hash!=this.compose_field_hash()&&!confirm(this.get_label("notsentwarning")))return!1;if("function"===typeof this.command_handlers[a])return e=this.command_handlers[a](b,d),void 0!==e?e:
+d?!1:!0;if("string"===typeof this.command_handlers[a])return e=window[this.command_handlers[a]](b,d),void 0!==e?e:d?!1:!0;this.triggerEvent("actionbefore",{props:b,action:a});e=this.triggerEvent("before"+a,b);if(void 0!==e){if(!1===e)return!1;b=e}e=void 0;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;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":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.reset_qsearch();"mail"==this.task?(this.list_mailbox(b),this.env.trash_mailbox&&!this.env.flag_for_deletion&&this.set_alttext("delete",this.env.mailbox!=this.env.trash_mailbox?"movemessagetotrash":"deletemessage")):"addressbook"==this.task&&
+this.list_contacts(b);break;case "load-headers":this.load_headers(d);break;case "sort":f=b;g=this.env.sort_col==f?"ASC"==this.env.sort_order?"DESC":"ASC":"ASC";this.set_list_sorting(f,g);this.list_mailbox("","",f+"_"+g);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("mail"==this.task){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"addressbook"==this.task&&(h=b?b:this.get_single_cid())&&!("show"==this.env.action&&h==this.env.cid)&&this.load_contact(h,"show");break;case "add":"addressbook"==this.task?this.load_contact(0,"add"):"settings"==this.task&&
+(this.identity_list.clear_selection(),this.load_identity(0,"add-identity"));break;case "edit":if("addressbook"==this.task&&(h=this.get_single_cid()))this.load_contact(h,"edit");else if("settings"==this.task&&b)this.load_identity(b,"edit-identity");else if("mail"==this.task&&(h=this.get_single_uid()))g=this.env.mailbox==this.env.drafts_mailbox?"_draft_uid=":"_uid=",this.goto_url("compose",g+h+"&_mbox="+urlencode(this.env.mailbox),!0);break;case "save":var k;if(g=this.gui_objects.editform){if("search"!=
+this.env.action)if((k=$("input[name='_pagesize']",g))&&k.length&&isNaN(parseInt(k.val()))){alert(this.get_label("nopagesizewarning"));k.focus();break}else{if("reload"==b)g.action+="?_reload=1";else if("settings"==this.task&&0==this.env.identities_level%2&&(k=$("input[name='_email']",g))&&k.length&&!rcube_check_email(k.val())){alert(this.get_label("noemailwarning"));k.focus();break}$("input.placeholder").each(function(){if(this.value==this._placeholder)this.value=""})}if(parent.rcmail&&parent.rcmail.env.source)g.action=
+this.add_url(g.action,"_orig_source",parent.rcmail.env.source);g.submit()}break;case "delete":"mail"==this.task?this.delete_messages():"addressbook"==this.task?this.delete_contacts():"settings"==this.task&&this.delete_identity();break;case "move":case "moveto":"mail"==this.task?this.move_messages(b):"addressbook"==this.task&&this.drag_active&&this.copy_contact(null,b);break;case "copy":"mail"==this.task&&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(){i.command("load-images")},300);break}case "load-images":this.env.uid&&
+this.show_message(this.env.uid,!0,"preview"==this.env.action);break;case "load-attachment":g="_mbox="+urlencode(this.env.mailbox)+"&_uid="+this.env.uid+"&_part="+b.part;if(this.env.uid&&b.mimetype&&this.env.mimetypes&&0<=$.inArray(b.mimetype,this.env.mimetypes)&&("text/html"==b.mimetype&&(g+="&_safe=1"),this.attachment_win=window.open(this.env.comm_path+"&_action=get&"+g+"&_frame=1","rcubemailattachment"))){window.setTimeout(function(){i.attachment_win.focus()},10);break}this.goto_url("get",g+"&_download=1",
+!1);break;case "select-all":this.select_all_mode=b?!1:!0;this.dummy_select=!0;"invert"==b?this.message_list.invert_selection():this.message_list.select_all("page"==b?"":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,"preview"==this.env.action);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,"preview"==this.env.action);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":g=this.url("mail/compose");
+if("mail"==this.task)g+="&_mbox="+urlencode(this.env.mailbox),b&&(g+="&_to="+urlencode(b));else if("addressbook"==this.task){if(b&&0<b.indexOf("@")){g=this.get_task_url("mail",g);this.redirect(g+"&_to="+urlencode(b));break}h=[];if(b)h.push(b);else if(this.contact_list){k=this.contact_list.get_selection();for(g=0,f=k.length;g<f;g++)h.push(k[g])}h.length?this.http_post("mailto",{_cid:h.join(","),_source:this.env.source},!0):this.env.group&&this.http_post("mailto",{_gid:this.env.group,_source:this.env.source},
+!0);break}else b&&(g+="&_to="+urlencode(b));this.redirect(g);break;case "spellcheck":window.tinyMCE&&tinyMCE.get(this.env.composebody)?tinyMCE.execCommand("mceSpellCheck",!0):this.env.spellcheck&&this.env.spellcheck.spellCheck&&this.spellcheck_ready&&(this.env.spellcheck.spellCheck(),this.set_spellcheck_state("checking"));break;case "savedraft":self.clearTimeout(this.save_timer);if(!this.gui_objects.messageform)break;if(!this.env.drafts_mailbox||this.cmp_hash==this.compose_field_hash())break;g=this.gui_objects.messageform;
+f=this.set_busy(!0,"savingmessage");g.target="savetarget";g._draft.value="1";g.action=this.add_url(g.action,"_unlock",f);g.submit();break;case "send":if(!this.gui_objects.messageform)break;if(!b.nocheck&&!this.check_compose_input(a))break;self.clearTimeout(this.save_timer);h=this.spellcheck_lang();g=this.gui_objects.messageform;f=this.set_busy(!0,"sendingmessage");g.target="savetarget";g._draft.value="";g.action=this.add_url(g.action,"_unlock",f);g.action=this.add_url(g.action,"_lang",h);g.submit();
+clearTimeout(this.request_timer);break;case "send-attachment":self.clearTimeout(this.save_timer);this.upload_file(b);break;case "insert-sig":this.change_identity($("[name='_from']")[0],!0);break;case "reply-all":case "reply-list":case "reply":if(f=this.get_single_uid())g="_reply_uid="+f+"&_mbox="+urlencode(this.env.mailbox),"reply-all"==a?g+="&_all="+(!b&&this.commands["reply-list"]?"list":"all"):"reply-list"==a&&(g+="&_all=list"),this.goto_url("compose",g,!0);break;case "forward-attachment":case "forward":if(f=
+this.get_single_uid()){g="_forward_uid="+f+"&_mbox="+urlencode(this.env.mailbox);if("forward-attachment"==a||!b&&this.env.forward_attachment)g+="&_attachment=1";this.goto_url("compose",g,!0)}break;case "print":if(f=this.get_single_uid())i.printwin=window.open(this.env.comm_path+"&_action=print&_uid="+f+"&_mbox="+urlencode(this.env.mailbox)+(this.env.safemode?"&_safe=1":"")),this.printwin&&(window.setTimeout(function(){i.printwin.focus()},20),"show"!=this.env.action&&this.mark_message("read",f));break;
+case "viewsource":if(f=this.get_single_uid())i.sourcewin=window.open(this.env.comm_path+"&_action=viewsource&_uid="+f+"&_mbox="+urlencode(this.env.mailbox)),this.sourcewin&&window.setTimeout(function(){i.sourcewin.focus()},20);break;case "download":(f=this.get_single_uid())&&this.goto_url("viewsource","&_uid="+f+"&_mbox="+urlencode(this.env.mailbox)+"&_save=1");break;case "search":if(!b&&this.gui_objects.qsearchbox)b=this.gui_objects.qsearchbox.value;if(b){this.qsearch(b);break}case "reset-search":f=
+this.env.search_request||this.env.qsearch;this.reset_qsearch();this.select_all_mode=!1;if(f&&this.env.mailbox)this.list_mailbox(this.env.mailbox,1);else if(f&&"addressbook"==this.task){if(""==this.env.source){for(g in this.env.address_sources)break;this.env.source=g;this.env.group=""}this.list_contacts(this.env.source,this.env.group,1)}break;case "listgroup":this.reset_qsearch();this.list_contacts(b.source,b.id);break;case "import":if("import"==this.env.action&&this.gui_objects.importform){if((g=
+document.getElementById("rcmimportfile"))&&!g.value){alert(this.get_label("selectimportfile"));break}this.gui_objects.importform.submit();this.set_busy(!0,"importwait");this.lock_form(this.gui_objects.importform,!0)}else this.goto_url("import",this.env.source?"_target="+urlencode(this.env.source)+"&":"");break;case "export":0<this.contact_list.rowcount&&this.goto_url("export",{_source:this.env.source,_gid:this.env.group,_search:this.env.search_request});break;case "upload-photo":this.upload_contact_photo(b);
+break;case "delete-photo":this.replace_contact_photo("-del-");break;case "preferences":case "identities":case "folders":this.goto_url("settings/"+a);break;case "undo":this.http_request("undo","",this.display_message("","loading"));break;default:g=a.replace(/-/g,"_"),this[g]&&"function"===typeof this[g]&&(e=this[g](b))}!1===this.triggerEvent("after"+a,b)&&(e=!1);this.triggerEvent("actionafter",{props:b,action:a});return!1===e?!1:d?!1:!0};this.enable_command=function(){var a,b,d=Array.prototype.slice.call(arguments),
+e=d.pop(),f;for(b=0;b<d.length;b++)if(f=d[b],"string"===typeof f)this.commands[f]=e,this.set_button(f,e?"act":"pas");else for(a in f)d.push(f[a])};this.set_busy=function(a,b,d){a&&b?(d=this.get_label(b),d==b&&(d="Loading..."),d=this.display_message(d,"loading")):!a&&d&&this.hide_message(d);this.busy=a;this.gui_objects.editform&&this.lock_form(this.gui_objects.editform,a);this.request_timer&&clearTimeout(this.request_timer);if(a&&this.env.request_timeout)this.request_timer=window.setTimeout(function(){i.request_timed_out()},
+1E3*this.env.request_timeout);return d};this.gettext=this.get_label=function(a,b){return b&&this.labels[b+"."+a]?this.labels[b+"."+a]:this.labels[a]?this.labels[a]:a};this.switch_task=function(a){if(!(this.task===a&&"mail"!=a)){var b=this.get_task_url(a);"mail"==a&&(b+="&_mbox=INBOX");this.redirect(b)}};this.get_task_url=function(a,b){if(!b)b=this.env.comm_path;return b.replace(/_task=[a-z]+/,"_task="+a)};this.request_timed_out=function(){this.set_busy(!1);this.display_message("Request timed out!",
+"error")};this.reload=function(a){if(this.is_framed())parent.rcmail.reload(a);else if(a)window.setTimeout(function(){rcmail.reload()},a);else if(window.location)location.href=this.env.comm_path+(this.env.action?"&_action="+this.env.action:"")};this.add_url=function(a,b,d){d=urlencode(d);if(/(\?.*)$/.test(a)){var e=RegExp.$1,f=RegExp("((\\?|&)"+RegExp.escape(b)+"=[^&]*)"),e=f.test(e)?e.replace(f,RegExp.$2+b+"="+d):e+("&"+b+"="+d);return a.replace(/(\?.*)$/,e)}return a+"?"+b+"="+d};this.is_framed=function(){return this.env.framed&&
+parent.rcmail&&parent.rcmail!=this&&parent.rcmail.command};this.save_pref=function(a){var b={_name:a.name,_value:a.value};if(a.session)b._session=a.session;if(a.env)this.env[a.env]=a.value;this.http_post("save-pref",b)};this.html_identifier=function(a,b){a=""+a;return b?Base64.encode(a).replace(/=+$/,"").replace(/\+/g,"-").replace(/\//g,"_"):a.replace(this.identifier_expr,"_")};this.html_identifier_decode=function(a){for(a=(""+a).replace(/-/g,"+").replace(/_/g,"/");a.length%4;)a+="=";return Base64.decode(a)};
+this.drag_menu=function(a,b){var d=rcube_event.get_modifier(a),e=this.gui_objects.message_dragmenu;return e&&d==SHIFT_KEY&&this.commands.copy?(d=rcube_event.get_mouse_pos(a),this.env.drag_target=b,$(e).css({top:d.y-10+"px",left:d.x-10+"px"}).show(),!0):!1};this.drag_menu_action=function(a){var b=this.gui_objects.message_dragmenu;b&&$(b).hide();this.command(a,this.env.drag_target);this.env.drag_target=null};this.drag_start=function(a){var b="mail"==this.task?this.env.mailboxes:this.env.contactfolders;
+this.drag_active=!0;this.preview_timer&&clearTimeout(this.preview_timer);this.preview_read_timer&&clearTimeout(this.preview_read_timer);if(this.gui_objects.folderlist&&b){this.initialBodyScrollTop=bw.ie?0:window.pageYOffset;this.initialListScrollTop=this.gui_objects.folderlist.parentNode.scrollTop;var d,e,a=$(this.gui_objects.folderlist);pos=a.offset();this.env.folderlist_coords={x1:pos.left,y1:pos.top,x2:pos.left+a.width(),y2:pos.top+a.height()};this.env.folder_coords=[];for(d in b)if(a=this.get_folder_li(d))if(e=
+a.firstChild.offsetHeight)pos=$(a.firstChild).offset(),this.env.folder_coords[d]={x1:pos.left,y1:pos.top,x2:pos.left+a.firstChild.offsetWidth,y2:pos.top+e,on:0}}};this.drag_end=function(){this.drag_active=!1;this.env.last_folder_target=null;if(this.folder_auto_timer)window.clearTimeout(this.folder_auto_timer),this.folder_auto_expand=this.folder_auto_timer=null;if(this.gui_objects.folderlist&&this.env.folder_coords)for(var a in this.env.folder_coords)this.env.folder_coords[a].on&&$(this.get_folder_li(a)).removeClass("droptarget")};
+this.drag_move=function(a){if(this.gui_objects.folderlist&&this.env.folder_coords){var b,d,e,f,h;d="draglayernormal";a=rcube_event.get_mouse_pos(a);f=this.env.folderlist_coords;e=bw.ie?-document.documentElement.scrollTop:this.initialBodyScrollTop;var g=this.initialListScrollTop-this.gui_objects.folderlist.parentNode.scrollTop;this.contact_list&&this.contact_list.draglayer&&(h=this.contact_list.draglayer.attr("class"));a.y+=-g-e;if(a.x<f.x1||a.x>=f.x2||a.y<f.y1||a.y>=f.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(b in this.env.folder_coords)if(f=this.env.folder_coords[b],a.x>=f.x1&&a.x<f.x2&&a.y>=f.y1&&a.y<f.y2)if(f=this.check_droptarget(b)){d=this.get_folder_li(b);e=$(d.getElementsByTagName("div")[0]);if(e.hasClass("collapsed"))this.folder_auto_timer&&window.clearTimeout(this.folder_auto_timer),this.folder_auto_expand=b,this.folder_auto_timer=window.setTimeout(function(){rcmail.command("collapse-folder",rcmail.folder_auto_expand);
+rcmail.drag_start(null)},1E3);else if(this.folder_auto_timer)window.clearTimeout(this.folder_auto_timer),this.folder_auto_expand=this.folder_auto_timer=null;$(d).addClass("droptarget");this.env.folder_coords[b].on=1;this.env.last_folder_target=b;d="draglayer"+(1<f?"copy":"normal")}else this.env.last_folder_target=null;else if(f.on)$(this.get_folder_li(b)).removeClass("droptarget"),this.env.folder_coords[b].on=0;d!=h&&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,"",!0),d=$("div:first",b),e=$("ul:first",b);if(d.hasClass("collapsed"))e.show(),d.removeClass("collapsed").addClass("expanded"),this.env.collapsed_folders=this.env.collapsed_folders.replace(RegExp("&"+urlencode(a)+"&"),"");else if(d.hasClass("expanded"))e.hide(),d.removeClass("expanded").addClass("collapsed"),this.env.collapsed_folders=this.env.collapsed_folders+"&"+urlencode(a)+"&",0==this.env.mailbox.indexOf(a+this.env.delimiter)&&
+this.command("list",a);else return;if(bw.ie6||bw.ie7)if((d=b.nextSibling?b.nextSibling.getElementsByTagName("ul"):null)&&d.length&&(b=d[0])&&b.style&&"none"!=b.style.display)b.style.display="none",b.style.display="";this.command("save-pref",{name:"collapsed_folders",value:this.env.collapsed_folders});this.set_unread_count_display(a,!1)};this.doc_mouse_up=function(a){var b,d,e;if(!$(rcube_event.get_target(a)).closest(".ui-dialog, .ui-widget-overlay").length){(d=this.message_list)?(rcube_mouse_is_over(a,
+d.list.parentNode)?d.focus():d.blur(),b=this.env.mailboxes):(d=this.contact_list)?(rcube_mouse_is_over(a,d.list.parentNode)?d.focus():d.blur(),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(e in this.buttons_sel)"function"!==
+typeof e&&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=null!=a.get_single_selection();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","forward-attachment",!1):this.env.messages[a.get_single_selection()].ml||this.enable_command("reply-list",!1));this.enable_command("delete","moveto","copy","mark",0<a.selection.length?!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(){i.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]&&0<=window.frames[this.env.contentframe].location.href.indexOf(this.env.blankpage))this.preview_timer&&clearTimeout(this.preview_timer),this.preview_read_timer&&clearTimeout(this.preview_read_timer),this.preview_timer=window.setTimeout(function(){i.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.modkey!=CONTROL_KEY&&(a.key_pressed==a.ENTER_KEY?this.command("show"):a.key_pressed==a.DELETE_KEY||a.key_pressed==a.BACKSPACE_KEY?this.command("delete"):
+33==a.key_pressed?this.command("previouspage"):34==a.key_pressed&&this.command("nextpage"))};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=a.list.tHead.rows[0].cells;this.env.coltypes=[];for(a=0;a<d.length;a++)d[a].id&&
+d[a].id.match(/^rcm/)&&(b=d[a].id.replace(/^rcm/,""),this.env.coltypes.push("to"==b?"from":b));if(0<=(a=$.inArray("flag",this.env.coltypes)))this.env.flagged_col=a;if(0<=(a=$.inArray("subject",this.env.coltypes)))this.env.subject_col=a;this.command("save-pref",{name:"list_cols",value:this.env.coltypes,session:"list_attrib/columns"})};this.check_droptarget=function(a){var b=!1,d=!1;if("mail"==this.task)b=this.env.mailboxes[a]&&this.env.mailboxes[a].id!=this.env.mailbox&&!this.env.mailboxes[a].virtual;
+else if("settings"==this.task)b=a!=this.env.mailbox;else if("addressbook"==this.task&&a!=this.env.source&&this.env.contactfolders[a])"group"==this.env.contactfolders[a].type?(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=(null!=this.env.status_col?"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=null!=this.env.status_col?document.getElementById("msgicn"+a.uid):a.icon;if(null!=this.env.flagged_col&&(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||d.mbox!=this.env.mailbox&&!d.skip_mbox_check)return!1;this.env.messages[a]||(this.env.messages[a]={});$.extend(this.env.messages[a],{deleted:d.deleted?1:0,replied:d.answered?1:0,unread:!d.seen?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,h,g,k="",j="",l=this.message_list;g=l.rows;var i=this.env.messages[a];f="message"+(!d.seen?" unread":"")+(d.deleted?" deleted":"")+(d.flagged?" flagged":"")+(d.unread_children&&d.seen&&!this.env.autoexpand_threads?" unroot":"")+(i.selected?" selected":"");var m=document.createElement("tr");
+m.id="rcmrow"+a;m.className=f;f="msgicon";null===this.env.status_col&&(f+=" status",d.deleted?f+=" deleted":d.seen?0<d.unread_children&&(f+=" unreadchildren"):f+=" unread");d.answered&&(f+=" replied");d.forwarded&&(f+=" forwarded");i.selected&&!l.in_selection(a)&&l.selection.push(a);if(this.env.threading)if(i.depth)k+='<span id="rcmtab'+a+'" class="branch" style="width:'+15*i.depth+'px;">&nbsp;&nbsp;</span>',g[i.parent_uid]&&!1===g[i.parent_uid].expanded||(0==this.env.autoexpand_threads||2==this.env.autoexpand_threads)&&
+(!g[i.parent_uid]||!g[i.parent_uid].expanded)?(m.style.display="none",i.expanded=!1):i.expanded=!0;else if(i.has_children){if(void 0===i.expanded&&(1==this.env.autoexpand_threads||2==this.env.autoexpand_threads&&i.unread_children))i.expanded=!0;j='<div id="rcmexpando'+a+'" class="'+(i.expanded?"expanded":"collapsed")+'">&nbsp;&nbsp;</div>'}k+='<span id="msgicn'+a+'" class="'+f+'">&nbsp;</span>';if(!bw.ie&&b.subject)g=d.mbox==this.env.drafts_mailbox?"_draft_uid":"_uid",b.subject='<a href="./?_task=mail&_action='+
+(d.mbox==this.env.drafts_mailbox?"compose":"show")+"&_mbox="+urlencode(d.mbox)+"&"+g+"="+a+'" onclick="return rcube_event.cancel(event)" onmouseover="rcube_webmail.long_subject_title(this,'+(i.depth+1)+')">'+b.subject+"</a>";for(h in this.env.coltypes){f=this.env.coltypes[h];g=document.createElement("td");g.className=(""+f).toLowerCase();if("flag"==f)f=d.flagged?"flagged":"unflagged",f='<span id="flagicn'+a+'" class="'+f+'">&nbsp;</span>';else if("attachment"==f)f=/application\/|multipart\/m/.test(d.ctype)?
+'<span class="attachment">&nbsp;</span>':/multipart\/report/.test(d.ctype)?'<span class="report">&nbsp;</span>':"&nbsp;";else if("status"==f)f=d.deleted?"deleted":d.seen?0<d.unread_children?"unreadchildren":"msgicon":"unread",f='<span id="statusicn'+a+'" class="'+f+'">&nbsp;</span>';else if("threads"==f)f=j;else if("subject"==f){if(bw.ie)g.onmouseover=function(){rcube_webmail.long_subject_title_ie(this,i.depth+1)};f=k+b[f]}else f="priority"==f?0<d.prio&&6>d.prio?'<span class="prio'+d.prio+'">&nbsp;</span>':
+"&nbsp;":b[f];g.innerHTML=f;m.appendChild(g)}l.insert_row(m,e);e&&this.env.pagesize&&l.rowcount>this.env.pagesize&&(a=l.get_last_row(),l.remove_row(a),l.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,h="";if(void 0===b)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,h+="&_threads="+e);if(a&&a.length){for(var g,k,j=[],i=this.env.coltypes,e=0;e<i.length;e++)k="to"==i[e]?"from":i[e],g=$.inArray(k,a),-1!=g&&(j.push(k),delete a[g]);for(e=0;e<a.length;e++)a[e]&&j.push(a[e]);j.join()!=i.join()&&(f=1,h+="&_cols="+j.join(","))}f&&this.list_mailbox("","",b+"_"+d,h)};this.show_message=function(a,b,d){if(a){var e=window,f=d?"preview":"show",h="&_action="+f+"&_uid="+a+"&_mbox="+urlencode(this.env.mailbox);
+d&&this.env.contentframe&&window.frames&&window.frames[this.env.contentframe]&&(e=window.frames[this.env.contentframe],h+="&_framed=1");b&&(h+="&_safe=1");this.env.search_request&&(h+="&_search="+this.env.search_request);if("preview"==f&&0<=(""+e.location.href).indexOf(h))this.show_contentframe(!0);else if(this.location_href(this.env.comm_path+h,e,!0),"preview"==f&&this.message_list&&this.message_list.rows[a]&&this.message_list.rows[a].unread&&0<=this.env.preview_pane_mark_read)this.preview_read_timer=
+window.setTimeout(function(){i.set_message(a,"unread",!1);i.update_thread_root(a,"read");i.env.unread_counts[i.env.mailbox]&&(i.env.unread_counts[i.env.mailbox]-=1,i.set_unread_count(i.env.mailbox,i.env.unread_counts[i.env.mailbox],"INBOX"==i.env.mailbox));0<i.env.preview_pane_mark_read&&i.http_post("mark","_uid="+a+"&_flag=read&_quiet=1")},1E3*this.env.preview_pane_mark_read)}};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&&0>d.location.href.indexOf(this.env.blankpage))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.lock_frame=function(){if(!this.env.frame_lock)(this.is_framed()?parent.rcmail:this).env.frame_lock=this.set_busy(!0,"loading")};this.list_page=function(a){"next"==a?a=this.env.current_page+1:"last"==a?a=this.env.pagecount:"prev"==a&&1<this.env.current_page?
+a=this.env.current_page-1:"first"==a&&1<this.env.current_page&&(a=1);if(0<a&&a<=this.env.pagecount)this.env.current_page=a,"mail"==this.task?this.list_mailbox(this.env.mailbox,a):"addressbook"==this.task&&this.list_contacts(this.env.source,this.env.group,a)};this.filter_mailbox=function(a){var b=this.set_busy(!0,"searching");this.clear_message_list();this.env.current_page=1;this.http_request("search",this.search_params(!1,a),b)};this.list_mailbox=function(a,b,d,e){var f="",h=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,"",!0);this.env.mailbox=a;this.gui_objects.messagelist?this.list_mailbox_remote(a,b,f):(this.env.contentframe&&window.frames&&window.frames[this.env.contentframe]&&(h=window.frames[this.env.contentframe],
+f+="&_framed=1"),a&&(this.set_busy(!0,"loading"),this.location_href(this.env.comm_path+"&_mbox="+urlencode(a)+(b?"&_page="+b:"")+f,h)))};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(1==b.nodeType&&(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,b){if(b&&b!=this.env.mailbox)return!1;for(var d=0,e=a.length;d<e;d++)this.add_tree_icons(a[d]);this.expand_threads()};this.add_tree_icons=function(a){var b,d,e,f,h=[],g=[],k,j=this.message_list.rows;for(k=
+a?j[a]?j[a].obj:null:this.message_list.list.tBodies[0].firstChild;k;){if(1==k.nodeType&&(d=j[k.uid]))if(d.depth){for(b=h.length-1;0<=b&&!(e=h[b].length,e>d.depth?(f=e-d.depth,h[b][f]&2||(h[b][f]=h[b][f]?h[b][f]+2:2)):e==d.depth&&(h[b][0]&2||(h[b][0]+=2)),d.depth>e);b--);h.push(Array(d.depth));h[h.length-1][0]=1;g.push(d.uid)}else{if(h.length){for(b in h)this.set_tree_icons(g[b],h[b]);h=[];g=[]}if(a&&k!=j[a].obj)break}k=k.nextSibling}if(h.length)for(b in h)this.set_tree_icons(g[b],h[b])};this.set_tree_icons=
+function(a,b){var d,e=[],f="",h=b.length;for(d=0;d<h;d++)2<b[d]?e.push({"class":"l3",width:15}):1<b[d]?e.push({"class":"l2",width:15}):0<b[d]?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;0<=d;d--)f=e[d]["class"]?f+('<div class="tree '+e[d]["class"]+'" />'):f+('<div style="width:'+e[d].width+'px" />');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("read"==b&&e.unread_children)e.unread_children--;else if("unread"==b&&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],h=e[a].depth,g=[];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(1==f.nodeType&&(b=e[f.uid])){if(!b.depth||b.depth<=h)break;b.depth--;$("#rcmtab"+b.uid).width(15*b.depth).html("");if(b.depth){if(b.depth==h)b.parent_uid=a;b.unread&&g.length&&g[g.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","none"!=b.obj.style.display?"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,g.push(b);"none"==b.obj.style.display&&$(b.obj).show()}}f=f.nextSibling}for(b=0;b<g.length;b++)this.set_unread_children(g[b].uid);return d};this.delete_excessive_thread_rows=function(){for(var a=this.message_list.rows,b=this.message_list.list.tBodies[0].firstChild,d=this.env.pagesize+1;b;){if(1==b.nodeType&&(r=a[b.uid]))!r.depth&&d&&d--,d||this.message_list.remove_row(b.uid);b=b.nextSibling}};this.set_message_icon=function(a){var b=this.message_list.rows[a];if(!b)return!1;if(b.icon)a=
+"msgicon",b.deleted?a+=" deleted":b.unread?a+=" unread":b.unread_children&&(a+=" unreadchildren"),b.msgicon==b.icon&&(b.replied&&(a+=" replied"),b.forwarded&&(a+=" forwarded"),a+=" status"),b.icon.className=a;if(b.msgicon&&b.msgicon!=b.icon)a="msgicon",!b.unread&&b.unread_children&&(a+=" unreadchildren"),b.replied&&(a+=" replied"),b.forwarded&&(a+=" forwarded"),b.msgicon.className=a;if(b.flagicon)a=b.flagged?"flagged":"unflagged",b.flagicon.className=a};this.set_message_status=function(a,b,d){a=this.message_list.rows[a];
+if(!a)return!1;if("unread"==b)a.unread=d;else if("deleted"==b)a.deleted=d;else if("replied"==b)a.replied=d;else if("forwarded"==b)a.forwarded=d;else if("flagged"==b)a.flagged=d};this.set_message=function(a,b,d){var e=this.message_list.rows[a];if(!e)return!1;b&&this.set_message_status(a,b,d);b=$(e.obj);e.unread&&!b.hasClass("unread")?b.addClass("unread"):!e.unread&&b.hasClass("unread")&&b.removeClass("unread");e.deleted&&!b.hasClass("deleted")?b.addClass("deleted"):!e.deleted&&b.hasClass("deleted")&&
+b.removeClass("deleted");e.flagged&&!b.hasClass("flagged")?b.addClass("flagged"):!e.flagged&&b.hasClass("flagged")&&b.removeClass("flagged");this.set_unread_children(a);this.set_message_icon(a)};this.set_unread_children=function(a){a=this.message_list.rows[a];a.parent_uid||(!a.unread&&a.unread_children&&!a.expanded?$(a.obj).addClass("unroot"):$(a.obj).removeClass("unroot"))};this.copy_messages=function(a){if(a&&"object"===typeof a)a=a.id;if(a&&!(a==this.env.mailbox||!this.env.uid&&(!this.message_list||
+!this.message_list.get_selection().length))){var b=[],d=this.display_message(this.get_label("copyingmessage"),"loading"),a="&_target_mbox="+urlencode(a)+"&_from="+(this.env.action?this.env.action:"");if(this.env.uid)b[0]=this.env.uid;else{var e=this.message_list.get_selection(),f;for(f in e)b.push(e[f])}a+="&_uid="+this.uids_to_list(b);this.http_post("copy","_mbox="+urlencode(this.env.mailbox)+a,d)}};this.move_messages=function(a){if(a&&"object"===typeof a)a=a.id;if(a&&!(a==this.env.mailbox||!this.env.uid&&
+(!this.message_list||!this.message_list.get_selection().length))){var b=!1,a="&_target_mbox="+urlencode(a)+"&_from="+(this.env.action?this.env.action:"");"show"==this.env.action?b=this.set_busy(!0,"movingmessage"):this.show_contentframe(!1);this.enable_command(this.env.message_commands,!1);this._with_selected_messages("moveto",b,a)}};this.delete_messages=function(){var a,b,d,e=this.env.trash_mailbox,f=this.message_list,h=f?$.merge([],f.get_selection()):[];if(this.env.uid||h.length){for(b=0,d=h.length;b<
+d;b++)a=h[b],f.rows[a].has_children&&!f.rows[a].expanded&&f.select_childs(a);if(this.env.flag_for_deletion)return this.mark_message("delete"),!1;!e||this.env.mailbox==e?this.permanently_remove_messages():f&&f.modkey==SHIFT_KEY?confirm(this.get_label("deletemessagesconfirm"))&&this.permanently_remove_messages():this.move_messages(e);return!0}};this.permanently_remove_messages=function(){if(this.env.uid||this.message_list&&this.message_list.get_selection().length)this.show_contentframe(!1),this._with_selected_messages("delete",
+!1,"&_from="+(this.env.action?this.env.action:""))};this._with_selected_messages=function(a,b,d){var e=[],f=0;if(this.env.uid)e[0]=this.env.uid;else{var h,g,k,j=[],i=this.message_list.get_selection();for(h=0,len=i.length;h<len;h++)g=i[h],e.push(g),this.env.threading&&(f+=this.update_thread(g),k=this.message_list.find_root(g),k!=g&&0>$.inArray(k,j)&&j.push(k)),this.message_list.remove_row(g,this.env.display_next&&h==i.length-1);this.env.display_next||this.message_list.clear_selection();for(h=0,len=
+j.length;h<len;h++)this.add_tree_icons(j[h])}this.env.search_request&&(d+="&_search="+this.env.search_request);this.env.display_next&&this.env.next_uid&&(d+="&_next_uid="+this.env.next_uid);0>f?d+="&_count="+-1*f:0<f&&this.delete_excessive_thread_rows();d+="&_uid="+this.uids_to_list(e);b||(b=this.display_message(this.get_label("moveto"==a?"movingmessage":"deletingmessage"),"loading"));this.http_post(a,"_mbox="+urlencode(this.env.mailbox)+d,b)};this.mark_message=function(a,b){var d=[],e=[],f,h,g;g=
+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)for(h=0,f=g.length;h<f;h++)d.push(g[h]);if(this.message_list)for(h=0,f=d.length;h<f;h++)g=d[h],("read"==a&&this.message_list.rows[g].unread||"unread"==a&&!this.message_list.rows[g].unread||"delete"==a&&!this.message_list.rows[g].deleted||"undelete"==a&&this.message_list.rows[g].deleted||"flagged"==a&&!this.message_list.rows[g].flagged||"unflagged"==a&&this.message_list.rows[g].flagged)&&
+e.push(g);else e=d;if(e.length||this.select_all_mode)switch(a){case "read":case "unread":this.toggle_read_status(a,e);break;case "delete":case "undelete":this.toggle_delete_status(e);break;case "flagged":case "unflagged":this.toggle_flagged_status(a,d)}};this.toggle_read_status=function(a,b){var d,e=b.length,f="_uid="+this.uids_to_list(b)+"&_flag="+a,h=this.display_message(this.get_label("markingmessage"),"loading");for(d=0;d<e;d++)this.set_message(b[d],"unread","unread"==a?!0:!1);this.env.search_request&&
+(f+="&_search="+this.env.search_request);this.http_post("mark",f,h);for(d=0;d<e;d++)this.update_thread_root(b[d],a)};this.toggle_flagged_status=function(a,b){var d,e=b.length,f="_uid="+this.uids_to_list(b)+"&_flag="+a,h=this.display_message(this.get_label("markingmessage"),"loading");for(d=0;d<e;d++)this.set_message(b[d],"flagged","flagged"==a?!0:!1);this.env.search_request&&(f+="&_search="+this.env.search_request);this.http_post("mark",f,h)};this.toggle_delete_status=function(a){var b=a.length,d,
+e,f=!0,h=this.message_list?this.message_list.rows:[];if(1==b)return!h.length||h[a[0]]&&!h[a[0]].deleted?this.flag_as_deleted(a):this.flag_as_undeleted(a),!0;for(d=0;d<b;d++)if(e=a[d],h[e]&&!h[e].deleted){f=!1;break}f?this.flag_as_undeleted(a):this.flag_as_deleted(a);return!0};this.flag_as_undeleted=function(a){var b,d=a.length,e="_uid="+this.uids_to_list(a)+"&_flag=undelete",f=this.display_message(this.get_label("markingmessage"),"loading");for(b=0;b<d;b++)this.set_message(a[b],"deleted",!1);this.env.search_request&&
+(e+="&_search="+this.env.search_request);this.http_post("mark",e,f);return!0};this.flag_as_deleted=function(a){for(var b="",d=[],b=this.message_list?this.message_list.rows:[],e=0,f=0,h=a.length;f<h;f++)uid=a[f],b[uid]&&(b[uid].unread&&(d[d.length]=uid),this.env.skip_deleted?(e+=this.update_thread(uid),this.message_list.remove_row(uid,this.env.display_next&&f==this.message_list.selection.length-1)):this.set_message(uid,"deleted",!0));this.env.skip_deleted&&this.message_list&&(this.env.display_next||
+this.message_list.clear_selection(),0>e||0<e&&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){var b,d,e,f=this.message_list?this.message_list.rows:[],a=(""+a).split(",");for(d=0,e=a.length;d<e;d++)b=a[d],f[b]&&this.set_message(b,"unread",!1)};this.uids_to_list=function(a){return this.select_all_mode?"*":a.join(",")};this.expunge_mailbox=function(a){var b,d="_mbox="+urlencode(a);a==this.env.mailbox&&(b=this.set_busy(!0,"loading"),d+="&_reload=1",this.env.search_request&&(d+="&_search="+this.env.search_request));this.http_post("expunge",d,b)};this.purge_mailbox=
+function(a){var b=!1,d="_mbox="+urlencode(a);if(!confirm(this.get_label("purgefolderconfirm")))return!1;a==this.env.mailbox&&(b=this.set_busy(!0,"loading"),d+="&_reload=1");this.http_post("purge",d,b)};this.purge_mailbox_test=function(){return this.env.messagecount&&(this.env.mailbox==this.env.trash_mailbox||this.env.mailbox==this.env.junk_mailbox||this.env.mailbox.match("^"+RegExp.escape(this.env.trash_mailbox)+RegExp.escape(this.env.delimiter))||this.env.mailbox.match("^"+RegExp.escape(this.env.junk_mailbox)+
+RegExp.escape(this.env.delimiter)))};this.login_user_keyup=function(a){var b=rcube_event.get_keycode(a),d=$("#rcmloginpwd");return 13==b&&d.length&&!d.val()?(d.focus(),rcube_event.cancel(a)):!0};this.init_messageform=function(){if(!this.gui_objects.messageform)return!1;var a=$("[name='_from']"),b=$("[name='_to']"),d=$("input[name='_subject']"),e=$("[name='_message']").get(0),f="1"==$("input[name='_is_html']").val(),h=["cc","bcc","replyto","followupto"],g;0<this.env.autocomplete_threads&&(g={threads:this.env.autocomplete_threads,
+sources:this.env.autocomplete_sources});this.init_address_input_events(b,g);for(var k in h)this.init_address_input_events($("[name='_"+h[k]+"']"),g);f||(this.set_caret_pos(e,this.env.top_posting?0:$(e).val().length),"select-one"==a.prop("type")&&""==$("input[name='_draft_saveid']").val()&&this.change_identity(a[0]));""==b.val()?b.focus():""==d.val()?d.focus():e&&e.focus();this.env.compose_focus_elem=document.activeElement;this.compose_field_hash(!0);this.auto_save_start()};this.init_address_input_events=
+function(a,b){this.env.recipients_delimiter=this.env.recipients_separator+" ";a[bw.ie||bw.safari||bw.chrome?"keydown":"keypress"](function(a){return i.ksearch_keydown(a,this,b)}).attr("autocomplete","off")};this.check_compose_input=function(a){var b,d=$("[name='_to']"),e=$("[name='_cc']"),f=$("[name='_bcc']"),h=$("[name='_from']"),g=$("[name='_subject']"),k=$("[name='_message']");if("text"==h.prop("type")&&!rcube_check_email(h.val(),!0))return alert(this.get_label("nosenderwarning")),h.focus(),!1;
+e=d.val()?d.val():e.val()?e.val():f.val();if(!rcube_check_email(e.replace(/^\s+/,"").replace(/[\s,;]+$/,""),!0))return alert(this.get_label("norecipientwarning")),d.focus(),!1;for(var j in this.env.attachments)if("object"===typeof this.env.attachments[j]&&!this.env.attachments[j].complete)return alert(this.get_label("notuploadedwarning")),!1;if(""==g.val()){b=$('<div class="prompt">').html('<div class="message">'+this.get_label("nosubjectwarning")+"</div>").appendTo(document.body);var l=$("<input>").attr("type",
+"text").attr("size",30).appendTo(b).val(this.get_label("nosubject")),d={};d[this.get_label("cancel")]=function(){g.focus();$(this).dialog("close")};d[this.get_label("sendmessage")]=function(){g.val(l.val());$(this).dialog("close");i.command(a,{nocheck:!0})};b.dialog({modal:!0,resizable:!1,buttons:d,close:function(){$(this).remove()}});l.select();return!1}this.stop_spellchecking();window.tinyMCE&&(b=tinyMCE.get(this.env.composebody));if(!b&&""==k.val()&&!confirm(this.get_label("nobodywarning")))return k.focus(),
+!1;if(b){if(!b.getContent()&&!confirm(this.get_label("nobodywarning")))return b.focus(),!1;tinyMCE.triggerSave()}return!0};this.toggle_editor=function(a){if("html"==a.mode)this.display_spellcheck_controls(!1),this.plain2html($("#"+a.id).val(),a.id),tinyMCE.execCommand("mceAddControl",!1,a.id);else{var b=tinyMCE.get(a.id);b.plugins.spellchecker&&b.plugins.spellchecker.active&&b.execCommand("mceSpellCheck",!1);if(b=b.getContent()){if(!confirm(this.get_label("editorwarning")))return!1;this.html2plain(b,
+a.id)}tinyMCE.execCommand("mceRemoveControl",!1,a.id);this.display_spellcheck_controls(!0)}return!0};this.stop_spellchecking=function(){var a;if(window.tinyMCE&&(a=tinyMCE.get(this.env.composebody)))a.plugins.spellchecker&&a.plugins.spellchecker.active&&a.execCommand("mceSpellCheck");else if((a=this.env.spellcheck)&&!this.spellcheck_ready)$(a.spell_span).trigger("click"),this.set_spellcheck_state("ready")};this.display_spellcheck_controls=function(a){this.env.spellcheck&&(a||this.stop_spellchecking(),
+$(this.env.spellcheck.spell_container).css("visibility",a?"visible":"hidden"))};this.set_spellcheck_state=function(a){this.spellcheck_ready="ready"==a||"no_error_found"==a;this.enable_command("spellcheck",this.spellcheck_ready)};this.spellcheck_lang=function(){var a;if(window.tinyMCE&&(a=tinyMCE.get(this.env.composebody))&&a.plugins.spellchecker)return a.plugins.spellchecker.selectedLang;if(this.env.spellcheck)return GOOGIE_CUR_LANG};this.spellcheck_resume=function(a,b){if(a){var d=tinyMCE.get(this.env.composebody),
+e=d.plugins.spellchecker;e.active=1;e._markWords(b);d.nodeChanged()}else{var e=this.env.spellcheck;e.prepare(!1,!0);e.processData(b)}};this.set_draft_id=function(a){$("input[name='_draft_saveid']").val(a)};this.auto_save_start=function(){if(this.env.draft_autosave)this.save_timer=self.setTimeout(function(){i.command("savedraft")},1E3*this.env.draft_autosave);this.busy=!1};this.compose_field_hash=function(a){var b,d="",e=$("[name='_to']").val(),f=$("[name='_cc']").val(),h=$("[name='_bcc']").val(),
+g=$("[name='_subject']").val();e&&(d+=e+":");f&&(d+=f+":");h&&(d+=h+":");g&&(d+=g+":");d=window.tinyMCE&&(b=tinyMCE.get(this.env.composebody))?d+b.getContent():d+$("[name='_message']").val();if(this.env.attachments)for(var k in this.env.attachments)d+=k;if(a)this.cmp_hash=d;return d};this.change_identity=function(a,b){if(!a||!a.options)return!1;if(!b)b=this.env.show_sig;var d,e=-1,f=a.options[a.selectedIndex].value,h=$("[name='_message']"),g=h.val(),k="1"==$("input[name='_is_html']").val(),j=this.env.identity;
+d=this.env.sig_above&&("reply"==this.env.compose_mode||"forward"==this.env.compose_mode)?"---":"-- ";this.env.signatures&&this.env.signatures[f]?(this.enable_command("insert-sig",!0),this.env.compose_commands.push("insert-sig")):this.enable_command("insert-sig",!1);if(k){if(b&&this.env.signatures&&(e=tinyMCE.get(this.env.composebody),h=e.dom.get("_rc_sig"),h||(j=e.getBody(),g=e.getDoc(),h=g.createElement("div"),h.setAttribute("id","_rc_sig"),this.env.sig_above?(e.getWin().focus(),e=e.selection.getNode(),
+"BODY"==e.nodeName?(j.insertBefore(h,j.firstChild),j.insertBefore(g.createElement("br"),j.firstChild)):(j.insertBefore(h,e.nextSibling),j.insertBefore(g.createElement("br"),e.nextSibling))):(bw.ie&&j.appendChild(g.createElement("br")),j.appendChild(h))),this.env.signatures[f]))this.env.signatures[f].is_html?(j=this.env.signatures[f].text,this.env.signatures[f].plain_text.match(/^--[ -]\r?\n/m)||(j=d+"<br />"+j)):(j=this.env.signatures[f].text,j.match(/^--[ -]\r?\n/m)||(j=d+"\n"+j),j="<pre>"+j+"</pre>"),
+h.innerHTML=j}else 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/m)||(j=d+"\n"+j),e=this.env.sig_above?g.indexOf(j):g.lastIndexOf(j),0<=e&&(g=g.substring(0,e)+g.substring(e+j.length,g.length))),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/m)||(j=d+"\n"+j),this.env.sig_above?0<=e?(g=g.substring(0,e)+j+g.substring(e,g.length),d=e-1):(pos=this.get_caret_pos(h.get(0)))?(g=g.substring(0,pos)+"\n"+j+"\n\n"+g.substring(pos,g.length),d=pos):(d=0,g="\n\n"+j+"\n\n"+g.replace(/^[\r\n]+/,"")):(g=g.replace(/[\r\n]+$/,""),d=!this.env.top_posting&&g.length?g.length+1:0,g+="\n\n"+j)):d=this.env.top_posting?0:g.length,h.val(g),this.set_caret_pos(h.get(0),d);this.env.identity=f;return!0};this.upload_file=function(a){if(!a)return!1;
+var b,d=0,e=$("input[type=file]",a).get(0),f=e.files?e.files.length:e.value?1:0;if(f){if(e.files&&this.env.max_filesize&&this.env.filesizeerror){for(b=0;b<f;b++)d+=e.files[b].size;if(d&&d>this.env.max_filesize){this.display_message(this.env.filesizeerror,"error");return}}b=this.async_upload_form(a,"upload",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});f="<span>"+this.get_label("uploading"+(1<f?"many":""))+"</span>";d=b.replace(/^rcmupload/,"");this.env.loadingicon&&(f='<img src="'+this.env.loadingicon+'" alt="" />'+f);this.env.cancelicon&&(f='<a title="'+this.get_label("cancel")+'" onclick="return rcmail.cancel_attachment_upload(\''+
+d+"', '"+b+'\');" href="#cancelupload"><img src="'+this.env.cancelicon+'" alt="" /></a>'+f);this.add2attachment_list(d,{name:"",html:f,complete:!1});this.env.upload_progress_time&&this.upload_progress_start("upload",d)}this.gui_objects.attachmentform=a;return!0};this.add2attachment_list=function(a,b,d){if(!this.gui_objects.attachmentlist)return!1;var e,f=$("<li>").attr("id",a).html(b.html);d&&(e=document.getElementById(d))?f.replaceAll(e):f.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){delete this.env.attachments[a];$("#"+a).remove()};this.remove_attachment=function(a){a&&this.env.attachments[a]&&this.http_post("remove-attachment",{_id:this.env.compose_id,_file:a});return!0};this.cancel_attachment_upload=function(a,b){if(!a||!b)return!1;this.remove_from_attachment_list(a);$("iframe[name='"+b+"']").remove();return!1};this.upload_progress_start=function(a,b){window.setTimeout(function(){rcmail.http_request(a,
+{_progress:b})},1E3*this.env.upload_progress_time)};this.upload_progress_update=function(a){var b=$("#"+a.name+"> span");b.length&&a.text&&(b.text(a.text),a.done||this.upload_progress_start(a.action,a.name))};this.add_contact=function(a){a&&this.http_post("addcontact","_address="+a);return!0};this.qsearch=function(a){if(""!=a){var b=this.set_busy(!0,"searching");this.message_list?this.clear_message_list():this.contact_list&&this.list_contacts_clear();this.env.current_page=1;r=this.http_request("search",
+this.search_params(a)+(this.env.source?"&_source="+urlencode(this.env.source):"")+(this.env.group?"&_gid="+urlencode(this.env.group):""),b);this.env.qsearch={lock:b,request:r}}};this.search_params=function(a,b){var d,e=[],f=[],h=this.env.search_mods,g=this.env.mailbox;if(!b&&this.gui_objects.search_filter)b=this.gui_objects.search_filter.value;if(!a&&this.gui_objects.qsearchbox)a=this.gui_objects.qsearchbox.value;b&&e.push("_filter="+urlencode(b));if(a&&(e.push("_q="+urlencode(a)),h&&this.message_list&&
+(h=h[g]?h[g]:h["*"]),h)){for(d in h)f.push(d);e.push("_headers="+f.join(","))}g&&e.push("_mbox="+urlencode(g));return e.join("&")};this.reset_qsearch=function(){if(this.gui_objects.qsearchbox)this.gui_objects.qsearchbox.value="";this.env.qsearch&&this.abort_request(this.env.qsearch);this.env.qsearch=null;this.env.search_request=null;this.env.search_id=null};this.sent_successfully=function(a,b){this.display_message(b,a);window.setTimeout(function(){i.list_mailbox()},500)};this.ksearch_keydown=function(a,
+b,d){this.ksearch_timer&&clearTimeout(this.ksearch_timer);var e=rcube_event.get_keycode(a),f=rcube_event.get_modifier(a);switch(e){case 38:case 40:if(!this.ksearch_pane)break;e=38==e?1:0;b=document.getElementById("rcmksearchSelected");if(!b)b=this.ksearch_pane.__ul.firstChild;b&&this.ksearch_select(e?b.previousSibling:b.nextSibling);return rcube_event.cancel(a);case 9:if(f==SHIFT_KEY||!this.ksearch_visible()){this.ksearch_hide();return}case 13:if(!this.ksearch_visible())return!1;this.insert_recipient(this.ksearch_selected);
+this.ksearch_hide();return rcube_event.cancel(a);case 27:this.ksearch_hide();return;case 37:case 39:if(f!=SHIFT_KEY)return}this.ksearch_timer=window.setTimeout(function(){i.ksearch_get_results(d)},200);this.ksearch_input=b;return!0};this.ksearch_visible=function(){return null!==this.ksearch_selected&&void 0!==this.ksearch_selected&&this.ksearch_value};this.ksearch_select=function(a){var b=$("#rcmksearchSelected");b[0]&&a&&b.removeAttr("id").removeClass("selected");if(a)$(a).attr("id","rcmksearchSelected").addClass("selected"),
+this.ksearch_selected=a._rcm_id};this.insert_recipient=function(a){if(!(null===a||!this.env.contacts[a]||!this.ksearch_input)){var b=this.ksearch_input.value,d=this.get_caret_pos(this.ksearch_input),d=b.lastIndexOf(this.ksearch_value,d),e=!1,f="",h=b.substring(0,d),b=b.substring(d+this.ksearch_value.length,b.length);this.ksearch_destroy();"object"===typeof this.env.contacts[a]&&this.env.contacts[a].id?(f+=this.env.contacts[a].name+this.env.recipients_delimiter,this.group2expand=$.extend({},this.env.contacts[a]),
+this.group2expand.input=this.ksearch_input,this.http_request("mail/group-expand","_source="+urlencode(this.env.contacts[a].source)+"&_gid="+urlencode(this.env.contacts[a].id),!1)):"string"===typeof this.env.contacts[a]&&(f=this.env.contacts[a]+this.env.recipients_delimiter,e=!0);this.ksearch_input.value=h+f+b;d+=f.length;this.ksearch_input.setSelectionRange&&this.ksearch_input.setSelectionRange(d,d);e&&this.triggerEvent("autocomplete_insert",{field:this.ksearch_input,insert:f})}};this.replace_group_recipients=
+function(a,b){if(this.group2expand&&this.group2expand.id==a)this.group2expand.input.value=this.group2expand.input.value.replace(this.group2expand.name,b),this.triggerEvent("autocomplete_insert",{field:this.group2expand.input,insert:b}),this.group2expand=null};this.ksearch_get_results=function(a){var b=this.ksearch_input?this.ksearch_input.value:null;if(null!==b){this.ksearch_pane&&this.ksearch_pane.is(":visible")&&this.ksearch_pane.hide();var d=this.get_caret_pos(this.ksearch_input),e=b.lastIndexOf(this.env.recipients_separator,
+d-1),b=b.substring(e+1,d),e=this.env.autocomplete_min_length,d=this.ksearch_data,b=$.trim(b);if(b!=this.ksearch_value)if(this.ksearch_destroy(),b.length&&b.length<e){if(!this.ksearch_info)this.ksearch_info=this.display_message(this.get_label("autocompletechars").replace("$min",e))}else if(e=this.ksearch_value,this.ksearch_value=b,b.length&&(!e||!e.length||!(0==b.indexOf(e)&&(!d||!d.num)&&this.env.contacts&&!this.env.contacts.length))){var f,h,g,d=(new Date).getTime(),e=a&&a.threads?a.threads:1;f=
+a&&a.sources?a.sources:[];a=a&&a.action?a.action:"mail/autocomplete";this.ksearch_data={id:d,sources:f.slice(),action:a,locks:[],requests:[],num:f.length};for(f=0;f<e;f++){g=this.ksearch_data.sources.shift();if(1<e&&null===g)break;h=this.display_message(this.get_label("searching"),"loading");g=this.http_post(a,"_search="+urlencode(b)+"&_id="+d+(g?"&_source="+urlencode(g):""),h);this.ksearch_data.locks.push(h);this.ksearch_data.requests.push(g)}}}};this.ksearch_query_results=function(a,b,d){if(this.ksearch_value&&
+!(this.ksearch_input&&b!=this.ksearch_value)){var e,f,h,g,k,b=this.ksearch_value,j=this.ksearch_data,l=this.env.autocomplete_max?this.env.autocomplete_max:15;if(!this.ksearch_pane)h=$("<ul>"),this.ksearch_pane=$("<div>").attr("id","rcmKSearchpane").css({position:"absolute","z-index":3E4}).append(h).appendTo(document.body),this.ksearch_pane.__ul=h[0];h=this.ksearch_pane.__ul;d&&this.ksearch_pane.data("reqid")==d?l-=h.childNodes.length:(this.ksearch_pane.data("reqid",d),h.innerHTML="",this.env.contacts=
+[],e=$(this.ksearch_input).offset(),this.ksearch_pane.css({left:e.left+"px",top:e.top+this.ksearch_input.offsetHeight+"px",display:"none"}));if(a&&(f=a.length))for(e=0;e<f&&0<l;e++)k="object"===typeof a[e]?a[e].name:a[e],g=document.createElement("LI"),g.innerHTML=k.replace(RegExp("("+RegExp.escape(b)+")","ig"),"##$1%%").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/##([^%]+)%%/g,"<b>$1</b>"),g.onmouseover=function(){i.ksearch_select(this)},g.onmouseup=function(){i.ksearch_click(this)},g._rcm_id=
+this.env.contacts.length+e,h.appendChild(g),l-=1;if(h.childNodes.length&&(this.ksearch_pane.show(),!this.env.contacts.length))$("li:first",h).attr("id","rcmksearchSelected").addClass("selected"),this.ksearch_selected=0;if(f)this.env.contacts=this.env.contacts.concat(a);if(j.id==d)if(j.num--,0<l&&j.sources.length){if(f=j.sources.shift())a=this.display_message(this.get_label("searching"),"loading"),d=this.http_post(j.action,"_search="+urlencode(b)+"&_id="+d+"&_source="+urlencode(f),a),this.ksearch_data.locks.push(a),
+this.ksearch_data.requests.push(d)}else if(!l){if(!this.ksearch_msg)this.ksearch_msg=this.display_message(this.get_label("autocompletemore"));this.ksearch_abort()}}};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_input=null;this.ksearch_hide()};this.ksearch_hide=function(){this.ksearch_selected=null;this.ksearch_value="";
+this.ksearch_pane&&this.ksearch_pane.hide();this.ksearch_destroy()};this.ksearch_destroy=function(){this.ksearch_abort();this.ksearch_info&&this.hide_message(this.ksearch_info);this.ksearch_msg&&this.hide_message(this.ksearch_msg);this.ksearch_msg=this.ksearch_info=this.ksearch_data=null};this.ksearch_abort=function(){var a,b,d=this.ksearch_data;if(d)for(a=0,b=d.locks.length;a<b;a++)this.abort_request({request:d.requests[a],lock:d.locks[a]})};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,e,f=this,h=!1;e=this.env.source?this.env.address_sources[this.env.source]:null;(d=a.get_single_selection())?this.preview_timer=window.setTimeout(function(){f.load_contact(d,"show")},200):this.env.contentframe&&this.show_contentframe(!1);if(a.selection.length)if(e)h=!e.readonly;else for(b in a.selection)if((e=(""+a.selection[b]).replace(/^[^-]+-/,""))&&this.env.address_sources[e]&&
+!this.env.address_sources[e].readonly){h=!0;break}this.enable_command("compose",this.env.group||0<a.selection.length);this.enable_command("edit",d&&h);this.enable_command("delete",a.selection.length&&h);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(this.env.search_id?
+"S"+this.env.search_id:b?"G"+a+b:a);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"),this.location_href(this.env.comm_path+(a?"&_source="+urlencode(a):"")+e,f))};this.list_contacts_remote=
+function(a,b,d){this.list_contacts_clear();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.list_contacts_clear=function(){this.contact_list.clear(!0);this.show_contentframe(!1);this.enable_command("delete",!1);this.enable_command("compose",this.env.group?!0:!1)};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),a||(this.contact_list.clear_selection(),this.enable_command("delete","compose",!1));else if(d)return!1;if(b&&(a||"add"==b)&&!this.drag_active)this.env.group&&(e+="&_gid="+urlencode(this.env.group)),this.location_href(this.env.comm_path+"&_action="+b+"&_source="+urlencode(this.env.source)+"&_cid="+urlencode(a)+e,f,!0);return!0};this.group_member_change=
+function(a,b,d,e){var a="add"==a?"add":"del",f=this.display_message(this.get_label("add"==a?"addingmember":"removingmember"),"loading");this.http_post("group-"+a+"members","_cid="+urlencode(b)+"&_source="+urlencode(d)+"&_gid="+urlencode(e),f)};this.copy_contact=function(a,b){a||(a=this.contact_list.get_selection().join(","));if("group"==b.type&&b.source==this.env.source)this.group_member_change("add",a,b.source,b.id);else if("group"==b.type&&!this.env.address_sources[b.source].readonly){var d=this.display_message(this.get_label("copyingcontact"),
+"loading");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):""),d)}else b.id!=this.env.source&&a&&this.env.address_sources[b.id]&&!this.env.address_sources[b.id].readonly&&(d=this.display_message(this.get_label("copyingcontact"),"loading"),this.http_post("copy","_cid="+urlencode(a)+"&_source="+urlencode(this.env.source)+"&_to="+urlencode(b.id)+(this.env.group?
+"&_gid="+urlencode(this.env.group):""),d))};this.delete_contacts=function(){var a=this.contact_list.get_selection(),b=this.env.source&&this.env.address_sources[this.env.source].undelete;if(!(!a.length&&!this.env.cid||!b&&!confirm(this.get_label("deletecontactconfirm")))){var d,e=[],f="";if(this.env.cid)e.push(this.env.cid);else{for(d=0;d<a.length;d++)b=a[d],e.push(b),this.contact_list.remove_row(b,d==a.length-1);1==a.length&&this.show_contentframe(!1)}this.env.group&&(f+="&_gid="+urlencode(this.env.group));
+this.env.search_request&&(f+="&_search="+this.env.search_request);this.http_post("delete","_cid="+urlencode(e.join(","))+"&_source="+urlencode(this.env.source)+"&_from="+(this.env.action?this.env.action:"")+f,this.display_message(this.get_label("contactdeleting"),"loading"));return!0}};this.update_contact_row=function(a,b,d,e){var f,h=this.contact_list,a=this.html_identifier(a);h.rows[a]||(a=a+"-"+e,d&&(d=d+"-"+e));if(h.rows[a]&&(f=h.rows[a].obj)){for(e=0;e<b.length;e++)f.cells[e]&&$(f.cells[e]).html(b[e]);
+if(d)d=this.html_identifier(d),f.id="rcmrow"+d,h.remove_row(a),h.init_row(f),h.selection[0]=d,f.style.display=""}};this.add_contact_row=function(a,b){if(!this.gui_objects.contactslist)return!1;var d,e=this.contact_list,f=document.createElement("tr");f.id="rcmrow"+this.html_identifier(a);f.className="contact";e.in_selection(a)&&(f.className+=" selected");for(d in b)col=document.createElement("td"),col.className=(""+d).toLowerCase(),col.innerHTML=b[d],f.appendChild(col);e.insert_row(f);this.enable_command("export",
+0<e.rowcount)};this.init_contact_form=function(){var a=this,b;this.set_photo_actions($("#ff_photo").val());for(b in this.env.coltypes)this.init_edit_field(b,null);$(".contactfieldgroup .row a.deletebutton").click(function(){a.delete_edit_field(this);return!1});$("select.addfieldmenu").change(function(){a.insert_edit_field($(this).val(),$(this).attr("rel"),this);this.selectedIndex=0});$.datepicker&&this.env.date_format&&($.datepicker.setDefaults({dateFormat:this.env.date_format,changeMonth:!0,changeYear:!0,
+yearRange:"-100:+10",showOtherMonths:!0,selectOtherMonths:!0,monthNamesShort:this.env.month_names,onSelect:function(a){$(this).focus().val(a)}}),$("input.datepicker").datepicker());$("input[type='text']:visible").first().focus()};this.group_create=function(){this.add_input_row("contactgroup")};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=$("<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(){if(this.env.group&&confirm(this.get_label("deletegroupconfirm"))){var a=this.set_busy(!0,"groupdeleting");this.http_post("group-delete","_source="+urlencode(this.env.source)+
+"&_gid="+urlencode(this.env.group),a)}};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_row=function(a){if(this.gui_objects.folderlist){if(!this.name_input)this.name_input=$("<input>").attr("type","text").data("tt",a),this.name_input.bind("keydown",function(a){return rcmail.add_input_keydown(a)}),
+this.name_input_li=$("<li>").addClass(a).append(this.name_input),this.name_input_li.insertAfter("contactsearch"==a?$("li:last",this.gui_objects.folderlist):this.get_folder_li(this.env.source));this.name_input.select().focus()}};this.add_input_keydown=function(a){var b=rcube_event.get_keycode(a),d=$(a.target),a=d.data("tt");if(13==b){if(b=d.val())d=this.set_busy(!0,"loading"),"contactsearch"==a?this.http_post("search-create","_search="+urlencode(this.env.search_request)+"&_name="+urlencode(b),d):this.env.group_renaming?
+this.http_post("group-rename","_source="+urlencode(this.env.source)+"&_gid="+urlencode(this.env.group)+"&_name="+urlencode(b),d):this.http_post("group-create","_source="+urlencode(this.env.source)+"&_name="+urlencode(b),d);return!1}27==b&&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,d=$("<a>").attr("href","#").attr("rel",a.source+":"+a.id).click(function(){return rcmail.command("listgroup",a,this)}).html(a.name),d=$("<li>").attr({id:"rcmli"+this.html_identifier(b),"class":"contactgroup"}).append(d);this.env.contactfolders[b]=this.env.contactgroups[b]=a;this.add_contact_group_row(a,d);this.triggerEvent("group_insert",
+{id:a.id,source:a.source,name:a.name,li:d[0]})};this.update_contact_group=function(a){this.reset_add_input();var b="G"+a.source+a.id,d=this.get_folder_li(b),e;if(d&&a.newid){e="G"+a.source+a.newid;var f=$.extend({},a);d.id="rcmli"+this.html_identifier(e);this.env.contactfolders[e]=this.env.contactfolders[b];this.env.contactfolders[e].id=a.newid;this.env.group=a.newid;delete this.env.contactfolders[b];delete this.env.contactgroups[b];f.id=a.newid;f.type="group";e=$("<a>").attr("href","#").attr("rel",
+a.source+":"+a.newid).click(function(){return rcmail.command("listgroup",f,this)}).html(a.name);$(d).children().replaceWith(e)}else if(d&&(e=d.firstChild)&&"a"==e.tagName.toLowerCase())e.innerHTML=a.name;this.env.contactfolders[b].name=this.env.contactgroups[b].name=a.name;this.add_contact_group_row(a,$(d),!0);this.triggerEvent("group_update",{id:a.id,source:a.source,name:a.name,li:d[0],newid:a.newid})};this.add_contact_group_row=function(a,b,d){var e=a.name.toUpperCase(),f=this.get_folder_li(a.source),
+a="rcmliG"+this.html_identifier(a.source);d?(d=b.clone(!0),b.remove()):d=b;$('li[id^="'+a+'"]',this.gui_objects.folderlist).each(function(a,b){if(e>=$(this).text().toUpperCase())f=b;else return!1});d.insertAfter(f)};this.update_group_commands=function(){var a=""!=this.env.source?this.env.address_sources[this.env.source]:null;this.enable_command("group-create",a&&a.groups&&!a.readonly);this.enable_command("group-rename","group-delete",a&&a.groups&&this.env.group&&!a.readonly)};this.init_edit_field=
+function(a,b){b||(b=$(".ff_"+a));b.focus(function(){i.focus_textfield(this)}).blur(function(){i.blur_textfield(this)}).each(function(){this._placeholder=this.title=i.env.coltypes[a].label;i.blur_textfield(this)})};this.insert_edit_field=function(a,b,d){var e=$("#ff_"+a);if(e.length)e.show().focus(),$(d).children('option[value="'+a+'"]').prop("disabled",!0);else if($(".ff_"+a),e=$("#contactsection"+b+" .contactcontroller"+a),e.length||(e=$("<fieldset>").addClass("contactfieldgroup contactcontroller"+
+a).insertAfter($("#contactsection"+b+" .contactfieldgroup").last())),e.length&&"FIELDSET"==e.get(0).nodeName){var f,b=this.env.coltypes[a],h=$("<div>").addClass("row"),g=$("<div>").addClass("contactfieldcontent data"),k=$("<div>").addClass("contactfieldlabel label");b.subtypes_select?k.html(b.subtypes_select):k.html(b.label);var j=1!=b.limit?"[]":"";if("text"==b.type||"date"==b.type)f=$("<input>").addClass("ff_"+a).attr({type:"text",name:"_"+a+j,size:b.size}).appendTo(g),this.init_edit_field(a,f),
+"date"==b.type&&$.datepicker&&f.datepicker();else if("composite"==b.type){var l,n,m=[],o=[];if(f=this.env[a+"_template"])for(l=0;l<f.length;l++)m.push(f[l][1]),o.push(f[l][2]);else for(l in b.childs)m.push(l);for(var p=0;p<m.length;p++)l=m[p],f=b.childs[l],f=$("<input>").addClass("ff_"+l).attr({type:"text",name:"_"+l+j,size:f.size}).appendTo(g),g.append(o[p]||" "),this.init_edit_field(l,f),n||(n=f);f=n}else if("select"==b.type){f=$("<select>").addClass("ff_"+a).attr("name","_"+a+j).appendTo(g);var q=
+f.attr("options");q[q.length]=new Option("---","");b.options&&$.each(b.options,function(a,b){q[q.length]=new Option(b,a)})}if(f){$('<a href="#del"></a>').addClass("contactfieldbutton deletebutton").attr({title:this.get_label("delete"),rel:a}).html(this.env.delbutton).click(function(){i.delete_edit_field(this);return!1}).appendTo(g);h.append(k).append(g).appendTo(e.show());f.first().focus();if(!b.count)b.count=0;++b.count==b.limit&&b.limit&&$(d).children('option[value="'+a+'"]').prop("disabled",!0)}}};
+this.delete_edit_field=function(a){var b=$(a).attr("rel"),d=this.env.coltypes[b],e=$(a).parents("fieldset.contactfieldgroup"),f=e.parent().find("select.addfieldmenu");0>=--d.count&&d.visible?$(a).parent().children("input").val("").blur():($(a).parents("div.row").remove(),e.children("div.row").length||e.hide());f.length&&(a=f.children('option[value="'+b+'"]'),a.length?a.prop("disabled",!1):$("<option>").attr("value",b).html(d.label).appendTo(f),f.show())};this.upload_contact_photo=function(a){if(a&&
+a.elements._photo.value)this.async_upload_form(a,"upload-photo",function(){rcmail.set_busy(!1,null,rcmail.photo_upload_id)}),this.photo_upload_id=this.set_busy(!0,"uploading")};this.replace_contact_photo=function(a){var b="-del-"==a?this.env.photo_placeholder:this.env.comm_path+"&_action=photo&_source="+this.env.source+"&_cid="+this.env.cid+"&_photo="+a;this.set_photo_actions(a);$(this.gui_objects.contactphoto).children("img").attr("src",b)};this.photo_upload_end=function(){this.set_busy(!1,null,
+this.photo_upload_id);delete this.photo_upload_id};this.set_photo_actions=function(a){var b,d=this.buttons["upload-photo"];for(b=0;d&&b<d.length;b++)$("#"+d[b].id).html(this.get_label("-del-"==a?"addphoto":"replacephoto"));$("#ff_photo").val(a);this.enable_command("upload-photo",this.env.coltypes.photo?!0:!1);this.enable_command("delete-photo",this.env.coltypes.photo&&"-del-"!=a)};this.advanced_search=function(){var a="&_form=1",b=window;this.env.contentframe&&window.frames&&window.frames[this.env.contentframe]&&
+(a+="&_framed=1",b=window.frames[this.env.contentframe],this.contact_list.clear_selection());this.location_href(this.env.comm_path+"&_action=search"+a,b,!0);return!0};this.unselect_directory=function(){this.select_folder("");this.enable_command("search-delete",!1)};this.insert_saved_search=function(a,b){this.reset_add_input();var d="S"+b,e=$("<a>").attr("href","#").attr("rel",b).click(function(){return rcmail.command("listsearch",b,this)}).html(a),d=$("<li>").attr({id:"rcmli"+this.html_identifier(d),
+"class":"contactsearch"}).append(e),e={name:a,id:b,li:d[0]};this.add_saved_search_row(e,d);this.select_folder("S"+b);this.enable_command("search-delete",!0);this.env.search_id=b;this.triggerEvent("abook_search_insert",e)};this.add_saved_search_row=function(a,b,d){var e,f=a.name.toUpperCase();d?(a=b.clone(!0),b.remove()):a=b;$('li[class~="contactsearch"]',this.gui_objects.folderlist).each(function(a,b){if(!e)e=this.previousSibling;if(f>=$(this).text().toUpperCase())e=b;else return!1});e?a.insertAfter(e):
+a.appendTo(this.gui_objects.folderlist)};this.search_create=function(){this.add_input_row("contactsearch")};this.search_delete=function(){if(this.env.search_request){var a=this.set_busy(!0,"savedsearchdeleting");this.http_post("search-delete","_sid="+urlencode(this.env.search_id),a)}};this.remove_search_item=function(a){var b;if(b=this.get_folder_li("S"+a))this.triggerEvent("search_delete",{id:a,li:b}),b.parentNode.removeChild(b);this.env.search_id=null;this.env.search_request=null;this.list_contacts_clear();
+this.reset_qsearch();this.enable_command("search-delete","search-create",!1)};this.listsearch=function(a){var b=this.set_busy(!0,"searching");this.contact_list&&this.list_contacts_clear();this.reset_qsearch();this.select_folder("S"+a);this.env.current_page=1;this.http_request("search","_sid="+urlencode(a),b)};this.section_select=function(a){var a=a.get_single_selection(),b="",d=window;a&&(this.env.contentframe&&window.frames&&window.frames[this.env.contentframe]&&(b="&_framed=1",d=window.frames[this.env.contentframe]),
+this.location_href(this.env.comm_path+"&_action=edit-prefs&_section="+a+b,d,!0));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("edit-identity"==b&&(!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||"add-identity"==b))this.set_busy(!0),this.location_href(this.env.comm_path+"&_action="+b+"&_iid="+a+d,e);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.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();$("#mailboxroot").mouseover(function(){a.focus_subscription(this.id)}).mouseout(function(){a.unfocus_subscription(this.id)})};
+this.focus_subscription=function(a){var b,d,e=RegExp.escape(this.env.delimiter),e=RegExp("["+e+"]?[^"+e+"]+$");if(this.drag_active&&this.env.mailbox&&(b=document.getElementById(a)))if(this.env.subscriptionrows[a]&&null!==(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(e,"")&&!d.match(RegExp("^"+RegExp.escape(this.env.mailbox+this.env.delimiter))))this.env.dstfolder=d,$(b).addClass("droptarget")};
+this.unfocus_subscription=function(a){var b=$("#"+a);this.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.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);this.env.mailbox&&null!==this.env.dstfolder&&this.env.dstfolder!=this.env.mailbox&&this.env.dstfolder!=this.env.mailbox.replace(RegExp("["+a+"]?[^"+a+"]+$"),"")&&(a=this.env.mailbox.replace(RegExp("[^"+a+"]*["+a+"]","g"),""),a=""===this.env.dstfolder?a:this.env.dstfolder+this.env.delimiter+a,a!=this.env.mailbox&&(this.http_post("rename-folder","_folder_oldname="+urlencode(this.env.mailbox)+"&_folder_newname="+urlencode(a),
+this.set_busy(!0,"foldermoving")),this.subscription_list.draglayer.hide()));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,f,h){if(!this.gui_objects.subscriptionlist)return!1;var g,k,j,i,n,m=[],o=[],p=this.gui_objects.subscriptionlist.tBodies[0];g=$("tr",p).get(1);var q="rcmrow"+(new Date).getTime();if(!g)return this.goto_url("folders"),!1;g=$(g).clone(!0);g.attr("id",q);g.attr("class",h);g.find("td:first").html(b);$('input[name="_subscribed[]"]',g).val(a).prop({checked:e?!0:!1,disabled:d?!0:!1});this.env.subscriptionrows[q]=[a,b,0];i=[];$.each(this.env.subscriptionrows,function(a,b){i.push(b)});i.sort(function(a,
+b){return a[0]<b[0]?-1:a[0]>b[0]?1:0});for(k in i)i[k][2]?(o.push(i[k][0]),j=i[k][0]+this.env.delimiter):j&&0==i[k][0].indexOf(j)?o.push(i[k][0]):(m.push(i[k][0]),j=null);for(k=0;k<o.length;k++)0==a.indexOf(o[k]+this.env.delimiter)&&(n=this.get_folder_row_id(o[k]));for(k=0;!n&&k<m.length;k++)k&&m[k]==a&&(n=this.get_folder_row_id(m[k-1]));n?$("#"+n).after(g):g.appendTo(p);this.subscription_list.clear_selection();f||this.init_subscription_list();g=g.get(0);g.scrollIntoView&&g.scrollIntoView();return g};
+this.replace_folder_row=function(a,b,d,e,f){if(!this.gui_objects.subscriptionlist)return!1;var h,g,i,j,l=this.get_folder_row_id(a),n=RegExp("^"+RegExp.escape(a));h=$('input[name="_subscribed[]"]',$("#"+l)).prop("checked");var m=this.get_subfolders(a);this._remove_folder_row(l);e=$(this.add_folder_row(b,d,e,h,!0,f));if(d=m.length)j=a.split(this.env.delimiter).length-b.split(this.env.delimiter).length;for(a=0;a<d;a++)if(l=m[a],h=this.env.subscriptionrows[l][0],f=this.env.subscriptionrows[l][1],g=$("#"+
+l),i=g.clone(!0),g.remove(),e.after(i),e=i,h=h.replace(n,b),$('input[name="_subscribed[]"]',e).val(h),this.env.subscriptionrows[l][0]=h,0!=j){if(0<j)for(h=j;0<h;h--)f=f.replace(/^&nbsp;&nbsp;&nbsp;&nbsp;/,"");else for(h=j;0>h;h++)f="&nbsp;&nbsp;&nbsp;&nbsp;"+f;e.find("td:first").html(f);this.env.subscriptionrows[l][1]=f}this.init_subscription_list()};this.remove_folder_row=function(a,b){var d,e,f=[];d=this.get_folder_row_id(a);b&&(f=this.get_subfolders(a));this._remove_folder_row(d);for(d=0,e=f.length;d<
+e;d++)this._remove_folder_row(f[d])};this._remove_folder_row=function(a){this.subscription_list.remove_row(a.replace(/^rcmrow/,""));$("#"+a).remove();delete this.env.subscriptionrows[a]};this.get_subfolders=function(a){for(var b=[],d=RegExp("^"+RegExp.escape(a)+RegExp.escape(this.env.delimiter)),e=$("#"+this.get_folder_row_id(a)).get(0);e=e.nextSibling;)if(e.id)if(a=this.env.subscriptionrows[e.id][0],d.test(a))b.push(e.id);else break;return b};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){var b,d=this.env.subscriptionrows;for(b in d)if(d[b]&&d[b][0]==a)break;return b};this.show_folder=function(a,b,d){var e=window,a="&_action=edit-folder&_mbox="+urlencode(a);b&&(a+="&_path="+urlencode(b));this.env.contentframe&&window.frames&&
+window.frames[this.env.contentframe]&&(e=window.frames[this.env.contentframe],a+="&_framed=1");0<=(""+e.location.href).indexOf(a)&&!d?this.show_contentframe(!0):this.location_href(this.env.comm_path+a,e,!0)};this.disable_subscription=function(a){(a=this.get_folder_row_id(a))&&$('input[name="_subscribed[]"]',$("#"+a)).prop("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)};
+var s=function(a,b){var d=document.getElementById(b.id);if(d){var e=!1;if("image"==b.type)d=d.parentNode,e=!0;d._command=a;d._id=b.id;if(b.sel&&(d.onmousedown=function(){return rcmail.button_sel(this._command,this._id)},d.onmouseup=function(){return rcmail.button_out(this._command,this._id)},e))(new Image).src=b.sel;if(b.over&&(d.onmouseover=function(){return rcmail.button_over(this._command,this._id)},d.onmouseout=function(){return rcmail.button_out(this._command,this._id)},e))(new Image).src=b.over}};
+this.set_page_buttons=function(){this.enable_command("nextpage","lastpage",this.env.pagecount>this.env.current_page);this.enable_command("previouspage","firstpage",1<this.env.current_page)};this.init_buttons=function(){for(var a in this.buttons)if("string"===typeof a)for(var b=0;b<this.buttons[a].length;b++)s(a,this.buttons[a][b]);this.set_button(this.task,"sel")};this.set_button=function(a,b){var d,e,f,h=this.buttons[a],g=h?h.length:0;for(d=0;d<g;d++){e=h[d];if((f=document.getElementById(e.id))&&
+"image"==e.type&&!e.status){if(e.pas=f._original_src?f._original_src:f.src,f.runtimeStyle&&f.runtimeStyle.filter&&f.runtimeStyle.filter.match(/src=['"]([^'"]+)['"]/))e.pas=RegExp.$1}else if(f&&!e.status)e.pas=""+f.className;if(f&&"image"==e.type&&e[b])e.status=b,f.src=e[b];else if(f&&void 0!==e[b])e.status=b,f.className=e[b];if(f&&"input"==e.type)e.status=b,f.disabled=!b}};this.set_alttext=function(a,b){var d,e,f,h,g=this.buttons[a],i=g?g.length:0;for(d=0;d<i;d++)e=g[d],f=document.getElementById(e.id),
+"image"==e.type&&f?(f.setAttribute("alt",this.get_label(b)),(h=f.parentNode)&&"a"==h.tagName.toLowerCase()&&h.setAttribute("title",this.get_label(b))):f&&f.setAttribute("title",this.get_label(b))};this.button_over=function(a,b){var d,e,f,h=this.buttons[a],g=h?h.length:0;for(d=0;d<g;d++)if(e=h[d],e.id==b&&"act"==e.status&&(f=document.getElementById(e.id))&&e.over)"image"==e.type?f.src=e.over:f.className=e.over};this.button_sel=function(a,b){var d,e,f,h=this.buttons[a],g=h?h.length:0;for(d=0;d<g;d++)if(e=
+h[d],e.id==b&&"act"==e.status){if((f=document.getElementById(e.id))&&e.sel)"image"==e.type?f.src=e.sel:f.className=e.sel;this.buttons_sel[b]=a}};this.button_out=function(a,b){var d,e,f,h=this.buttons[a],g=h?h.length:0;for(d=0;d<g;d++)if(e=h[d],e.id==b&&"act"==e.status&&(f=document.getElementById(e.id))&&e.act)"image"==e.type?f.src=e.act:f.className=e.act};this.focus_textfield=function(a){a._hasfocus=!0;var b=$(a);(b.hasClass("placeholder")||b.val()==a._placeholder)&&b.val("").removeClass("placeholder").attr("spellcheck",
+!0)};this.blur_textfield=function(a){a._hasfocus=!1;var b=$(a);a._placeholder&&(!b.val()||b.val()==a._placeholder)&&b.addClass("placeholder").attr("spellcheck",!1).val(a._placeholder)};this.set_pagetitle=function(a){if(a&&document.title)document.title=a};this.display_message=function(a,b,d){if(this.is_framed())return parent.rcmail.display_message(a,b,d);if(!this.gui_objects.message){if("loading"!=b)this.pending_message=[a,b,d];return!1}var b=b?b:"notice",e=this,f=this.html_identifier(a),h=b+(new Date).getTime();
+d||(d=this.message_time*("error"==b||"warning"==b?2:1));"loading"==b&&(f="loading",d=1E3*this.env.request_timeout,a||(a=this.get_label("loading")));if(this.messages[f])return this.messages[f].obj&&this.messages[f].obj.html(a),"loading"==b&&this.messages[f].labels.push({id:h,msg:a}),this.messages[f].elements.push(h),window.setTimeout(function(){e.hide_message(h,"loading"==b)},d),h;var g=$("<div>").addClass(b).html(a).data("key",f);$(this.gui_objects.message).append(g).show();this.messages[f]={obj:g,
+elements:[h]};"loading"==b?this.messages[f].labels=[{id:h,msg:a}]:g.click(function(){return e.hide_message(g)});0<d&&window.setTimeout(function(){e.hide_message(h,"loading"==b)},d);return h};this.hide_message=function(a,b){if(this.is_framed())return parent.rcmail.hide_message(a,b);var d,e,f,h,g=this.messages;if("object"===typeof a)$(a)[b?"fadeOut":"hide"](),h=$(a).data("key"),this.messages[h]&&delete this.messages[h];else for(d in g)for(e in g[d].elements)if(g[d]&&g[d].elements[e]==a)if(g[d].elements.splice(e,
+1),g[d].elements.length){if("loading"==d)for(f in g[d].labels)g[d].labels[f].id==a?delete g[d].labels[f]:h=g[d].labels[f].msg,g[d].obj.html(h)}else g[d].obj[b?"fadeOut":"hide"](),delete g[d]};this.select_folder=function(a,b,d){if(this.gui_objects.folderlist){var e,f;(e=$("li.selected",this.gui_objects.folderlist))&&e.removeClass("selected").addClass("unfocused");(f=this.get_folder_li(a,b,d))&&$(f).removeClass("unfocused").addClass("selected");this.triggerEvent("selectfolder",{folder:a,prefix:b})}};
+this.get_folder_li=function(a,b,d){b||(b="rcmli");return this.gui_objects.folderlist?(a=this.html_identifier(a,d),document.getElementById(b+a)):null};this.set_message_coltypes=function(a,b){var d=this.message_list,e=d?d.list.tHead:null,f,h,g,i;this.env.coltypes=a;if(e){if(b){h=document.createElement("thead");g=document.createElement("tr");for(c=0,i=b.length;c<i;c++){f=document.createElement("td");f.innerHTML=b[c].html;if(b[c].id)f.id=b[c].id;if(b[c].className)f.className=b[c].className;g.appendChild(f)}h.appendChild(g);
+e.parentNode.replaceChild(h,e);e=h}for(g=0,i=this.env.coltypes.length;g<i;g++)if(h=this.env.coltypes[g],(f=e.rows[0].cells[g])&&("from"==h||"to"==h)){f.id="rcm"+h;if(f.firstChild&&"a"==f.firstChild.tagName.toLowerCase())f=f.firstChild,f.onclick=function(){return rcmail.command("sort",this.__col,this)},f.__col=h;f.innerHTML=this.get_label(h)}}this.env.subject_col=null;this.env.flagged_col=null;this.env.status_col=null;if(0<=(g=$.inArray("subject",this.env.coltypes)))if(this.env.subject_col=g,d)d.subject_col=
+g;if(0<=(g=$.inArray("flag",this.env.coltypes)))this.env.flagged_col=g;if(0<=(g=$.inArray("status",this.env.coltypes)))this.env.status_col=g;d&&d.init_header()};this.set_rowcount=function(a,b){if(b&&b!=this.env.mailbox)return!1;$(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&&("object"===typeof a&&"image"==a.type?
+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,h,g;if(f=this.get_folder_li(a,"",!0)){h=this.env.unread_counts[a]?this.env.unread_counts[a]:0;e=$(f).children("a").eq(0);d=e.children("span.unreadcount");!d.length&&h&&(d=$("<span>").addClass("unreadcount").appendTo(e));
+e=0;if((g=f.getElementsByTagName("div")[0])&&g.className.match(/collapsed/))for(var i in this.env.unread_counts)0==i.indexOf(a+this.env.delimiter)&&(e+=this.env.unread_counts[i]);h&&d.length?d.html(" ("+h+")"):d.length&&d.remove();d=RegExp(RegExp.escape(this.env.delimiter)+"[^"+RegExp.escape(this.env.delimiter)+"]+$");a.match(d)&&this.set_unread_count_display(a.replace(d,""),!1);0<h+e?$(f).addClass("unread"):$(f).removeClass("unread")}d=/^\([0-9]+\)\s+/i;b&&document.title&&(f="",f=""+document.title,
+f=h&&f.match(d)?f.replace(d,"("+h+") "):h?"("+h+") "+f:f.replace(d,""),this.set_pagetitle(f))};this.toggle_prefer_html=function(a){$("#rcmfd_show_images").prop("disabled",!a.checked).val(0)};this.toggle_preview_pane=function(a){$("#rcmfd_preview_pane_mark_read").prop("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,h=parseInt(f/100*d),g=$(a).position();g.top=Math.max(0,g.top);g.left=Math.max(0,g.left);this.env.indicator_width=d;this.env.indicator_height=e;h>d&&(h=d,f=100);if(b.title)b.title=
+this.get_label("quota")+": "+b.title;var i=$("<div>");i.css({position:"absolute",top:g.top,left:g.left,width:d+"px",height:e+"px",zIndex:100,lineHeight:e+"px"}).attr("title",b.title).addClass("quota_text").html(f+"%");var j=$("<div>");j.css({position:"absolute",top:g.top+1,left:g.left+1,width:h+"px",height:e+"px",zIndex:99});h=$("<div>");h.css({position:"absolute",top:g.top+1,left:g.left+1,width:d+"px",height:e+"px",zIndex:98}).addClass("quota_bg");80<=f?(i.addClass(" quota_text_high"),j.addClass("quota_high")):
+55<=f?(i.addClass(" quota_text_mid"),j.addClass("quota_mid")):(i.addClass(" quota_text_low"),j.addClass("quota_low"));$(a).html("").append(j).append(h).append(i);$("#quotaimg").attr("title",b.title)};this.html2plain=function(a,b){var d=this,e=this.set_busy(!0,"converting");this.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,g){d.http_error(a,b,g,e)},success:function(a){d.set_busy(!1,
+null,e);$("#"+b).val(a);d.log(a)}})};this.plain2html=function(a,b){var d=this.set_busy(!0,"converting"),a=a.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;");$("#"+b).val(a?"<pre>"+a+"</pre>":"");this.set_busy(!1,null,d)};this.url=function(a,b){var d="string"===typeof b?"&"+b:"";if("string"!==typeof a)b=a;else if(!b||"object"!==typeof b)b={};b._action=a?a:this.env.action;var e=this.env.comm_path;if(b._action.match(/([a-z]+)\/([a-z0-9-_.]+)/))b._action=RegExp.$2,e=e.replace(/\_task=[a-z]+/,
+"_task="+RegExp.$1);var f={},h;for(h in b)void 0!==b[h]&&null!==b[h]&&(f[h]=b[h]);return e+"&"+$.param(f)+d};this.redirect=function(a,b){(b||null===b)&&this.set_busy(!0);this.is_framed()?parent.rcmail.redirect(a,b):this.location_href(a,window)};this.goto_url=function(a,b){this.redirect(this.url(a,b))};this.location_href=function(a,b,d){d&&this.lock_frame();bw.ie&&b==window?$("<a>").attr("href",a).appendTo(document.body).get(0).click():b.location.href=a};this.http_request=function(a,b,d){var e=this.url(a,
+b),a=this.triggerEvent("request"+a,b);if(void 0!==a){if(!1===a)return!1;b=a}e+="&_remote=1";this.log("HTTP GET: "+e);return $.ajax({type:"GET",url:e,data:{_unlock:d?d:0},dataType:"json",success:function(a){i.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.url(a);b&&"object"===typeof b?(b._remote=1,b._unlock=d?d:0):b+=(b?"&":"")+"_remote=1"+(d?"&_unlock="+d:"");a=this.triggerEvent("request"+a,b);if(void 0!==a){if(!1===a)return!1;b=a}this.log("HTTP POST: "+
+e);return $.ajax({type:"POST",url:e,data:b,dataType:"json",success:function(a){i.http_response(a)},error:function(a,b,e){rcmail.http_error(a,b,e,d)}})};this.abort_request=function(a){a.request&&a.request.abort();a.lock&&this.set_busy(!1,null,a.lock)};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("object"===typeof a.texts)for(var b in a.texts)"string"===
+typeof a.texts[b]&&this.add_label(b,a.texts[b]);a.exec&&(this.log(a.exec),eval(a.exec));if(a.callbacks&&a.callbacks.length)for(b=0;b<a.callbacks.length;b++)this.triggerEvent(a.callbacks[b][0],a.callbacks[b][1]);switch(a.action){case "delete":if("addressbook"==this.task){var d;b=this.contact_list.get_selection();d=!1;b&&this.contact_list.rows[b]&&(d=""==this.env.source?(d=(""+b).replace(/^[^-]+-/,""))&&this.env.address_sources[d]&&!this.env.address_sources[d].readonly:!this.env.address_sources[this.env.source].readonly);
+this.enable_command("compose",b&&this.contact_list.rows[b]);this.enable_command("delete","edit",d);this.enable_command("export",this.contact_list&&0<this.contact_list.rowcount)}case "moveto":"show"==this.env.action?(this.enable_command(this.env.message_commands,!0),this.env.list_post||this.enable_command("reply-list",!1)):"addressbook"==this.task&&this.triggerEvent("listupdate",{folder:this.env.source,rowcount:this.contact_list.rowcount});case "purge":case "expunge":"mail"==this.task&&(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":this.env.qsearch=null;case "list":if("mail"==this.task){if(this.enable_command("show","expunge","select-all","select-none","sort",0<
+this.env.messagecount),this.enable_command("purge",this.purge_mailbox_test()),this.enable_command("expand-all","expand-unread","collapse-all",this.env.threading&&this.env.messagecount),"list"==a.action||"search"==a.action)this.msglist_select(this.message_list),this.triggerEvent("listupdate",{folder:this.env.mailbox,rowcount:this.message_list.rowcount})}else if("addressbook"==this.task&&(this.enable_command("export",this.contact_list&&0<this.contact_list.rowcount),"list"==a.action||"search"==a.action))this.enable_command("search-create",
+""==this.env.source),this.enable_command("search-delete",this.env.search_id),this.update_group_commands(),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();a.status&&b&&this.display_message(this.get_label("servererror")+" ("+b+")",
+"error")};this.async_upload_form=function(a,b,d){var e=(new Date).getTime(),f="rcmupload"+e;if(this.env.upload_progress_name){var h=this.env.upload_progress_name,g=$("input[name="+h+"]",a);g.length||(g=$("<input>").attr({type:"hidden",name:h}),g.prependTo(a));g.val(e)}document.all?document.body.insertAdjacentHTML("BeforeEnd",'<iframe name="'+f+'" src="program/blank.gif" style="width:0;height:0;visibility:hidden;"></iframe>'):(h=document.createElement("iframe"),h.name=f,h.style.border="none",h.style.width=
+0,h.style.height=0,h.style.visibility="hidden",document.body.appendChild(h));$(f).bind("load",{ts:e},d);$(a).attr({target:f,action:this.url(b,{_id:this.env.compose_id||"",_uploadid:e}),method:"POST"}).attr(a.encoding?"encoding":"enctype","multipart/form-data").submit();return f};this.start_keepalive=function(){this._int&&clearInterval(this._int);if(this.env.keep_alive&&!this.env.framed&&"mail"==this.task&&this.gui_objects.mailboxlist)this._int=setInterval(function(){i.check_for_recent(!1)},1E3*this.env.keep_alive);
+else if(this.env.keep_alive&&!this.env.framed&&"login"!=this.task&&"print"!=this.env.action)this._int=setInterval(function(){i.keep_alive()},1E3*this.env.keep_alive)};this.keep_alive=function(){this.busy||this.http_request("keep-alive")};this.check_for_recent=function(a){if(!this.busy){var b,d="_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(void 0!==a.selectionEnd)return a.selectionEnd;if(document.selection&&document.selection.createRange){var b=
+document.selection.createRange();if(b.parentElement()!=a)return 0;var d=b.duplicate();"TEXTAREA"==a.tagName?d.moveToElementText(a):d.expand("textedit");d.setEndPoint("EndToStart",b);b=d.text.length;return b<=a.value.length?b:-1}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=[];for(d=0,e=a.elements.length;d<e;d++)if(f=a.elements[d],"hidden"!=f.type)if(b&&f.disabled)this.disabled_form_elements.push(f);else if(b||this.disabled_form_elements&&0>$.inArray(f,this.disabled_form_elements))f.disabled=b}}}rcube_webmail.long_subject_title=function(i,s){if(!i.title){var a=$(i);if(a.width()+15*s>a.parent().width())i.title=a.html()}};
+rcube_webmail.long_subject_title_ie=function(i,s){if(!i.title){var a=$(i),b=$.trim(a.text()),d=$("<span>").text(b).css({position:"absolute","float":"left",visibility:"hidden","font-size":a.css("font-size"),"font-weight":a.css("font-weight")}).appendTo($("body")),e=d.width();d.remove();if(e+15*s>a.width())i.title=b}};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;
index a127b29331cc56a5f55817b54c3f91588492d940..15d8884a2443faccdec647b0c6b64d2569de4730 100644 (file)
@@ -3,7 +3,8 @@
  | Roundcube Webmail Client Script                                       |
  |                                                                       |
  | This file is part of the Roundcube Webmail client                     |
  | Roundcube Webmail Client Script                                       |
  |                                                                       |
  | This file is part of the Roundcube Webmail client                     |
- | Copyright (C) 2005-2010, The Roundcube Dev Team                       |
+ | Copyright (C) 2005-2011, The Roundcube Dev Team                       |
+ | Copyright (C) 2011, Kolab Systems AG                                  |
  | Licensed under the GNU GPL                                            |
  |                                                                       |
  +-----------------------------------------------------------------------+
  | Licensed under the GNU GPL                                            |
  |                                                                       |
  +-----------------------------------------------------------------------+
  | Requires: jquery.js, common.js, list.js                               |
  +-----------------------------------------------------------------------+
 
  | Requires: jquery.js, common.js, list.js                               |
  +-----------------------------------------------------------------------+
 
-  $Id: app.js 5281 2011-09-27 07:29:49Z alec $
+  $Id: app.js 5554 2011-12-07 07:50:00Z alec $
 */
 
 function rcube_webmail()
 {
 */
 
 function rcube_webmail()
 {
-  this.env = {};
+  this.env = { recipients_separator:',', recipients_delimiter:', ' };
   this.labels = {};
   this.buttons = {};
   this.buttons_sel = {};
   this.labels = {};
   this.buttons = {};
   this.buttons_sel = {};
@@ -36,7 +37,7 @@ function rcube_webmail()
 
   // webmail client settings
   this.dblclick_time = 500;
 
   // webmail client settings
   this.dblclick_time = 500;
-  this.message_time = 2000;
+  this.message_time = 4000;
 
   this.identifier_expr = new RegExp('[^0-9a-z\-_]', 'gi');
 
 
   this.identifier_expr = new RegExp('[^0-9a-z\-_]', 'gi');
 
@@ -85,7 +86,7 @@ function rcube_webmail()
     if (over) button_prop.over = over;
 
     this.buttons[command].push(button_prop);
     if (over) button_prop.over = over;
 
     this.buttons[command].push(button_prop);
-    
+
     if (this.loaded)
       init_button(command, button_prop);
   };
     if (this.loaded)
       init_button(command, button_prop);
   };
@@ -127,7 +128,7 @@ function rcube_webmail()
   // initialize webmail client
   this.init = function()
   {
   // initialize webmail client
   this.init = function()
   {
-    var p = this;
+    var n, p = this;
     this.task = this.env.task;
 
     // check browser
     this.task = this.env.task;
 
     // check browser
@@ -137,13 +138,29 @@ function rcube_webmail()
     }
 
     // find all registered gui containers
     }
 
     // find all registered gui containers
-    for (var n in this.gui_containers)
+    for (n in this.gui_containers)
       this.gui_containers[n] = $('#'+this.gui_containers[n]);
 
     // find all registered gui objects
       this.gui_containers[n] = $('#'+this.gui_containers[n]);
 
     // find all registered gui objects
-    for (var n in this.gui_objects)
+    for (n in this.gui_objects)
       this.gui_objects[n] = rcube_find_object(this.gui_objects[n]);
 
       this.gui_objects[n] = rcube_find_object(this.gui_objects[n]);
 
+    // clickjacking protection
+    if (this.env.x_frame_options) {
+      try {
+        // bust frame if not allowed
+        if (this.env.x_frame_options == 'deny' && top.location.href != self.location.href)
+          top.location.href = self.location.href;
+        else if (top.location.hostname != self.location.hostname)
+          throw 1;
+      } catch (e) {
+        // possible clickjacking attack: disable all form elements
+        $('form').each(function(){ ref.lock_form(this, true); });
+        this.display_message("Blocked: possible clickjacking attack!", 'error');
+        return;
+      }
+    }
+
     // init registered buttons
     this.init_buttons();
 
     // init registered buttons
     this.init_buttons();
 
@@ -154,7 +171,7 @@ function rcube_webmail()
     }
 
     // enable general commands
     }
 
     // enable general commands
-    this.enable_command('logout', 'mail', 'addressbook', 'settings', 'save-pref', 'undo', true);
+    this.enable_command('logout', 'mail', 'addressbook', 'settings', 'save-pref', 'compose', 'undo', true);
 
     if (this.env.permaurl)
       this.enable_command('permaurl', true);
 
     if (this.env.permaurl)
       this.enable_command('permaurl', true);
@@ -163,7 +180,7 @@ function rcube_webmail()
 
       case 'mail':
         // enable mail commands
 
       case 'mail':
         // enable mail commands
-        this.enable_command('list', 'checkmail', 'compose', 'add-contact', 'search', 'reset-search', 'collapse-folder', true);
+        this.enable_command('list', 'checkmail', 'add-contact', 'search', 'reset-search', 'collapse-folder', true);
 
         if (this.gui_objects.messagelist) {
 
 
         if (this.gui_objects.messagelist) {
 
@@ -206,12 +223,13 @@ function rcube_webmail()
           'moveto', 'copy', 'delete', 'open', 'mark', 'edit', 'viewsource', 'download',
           'print', 'load-attachment', 'load-headers', 'forward-attachment'];
 
           'moveto', 'copy', 'delete', 'open', 'mark', 'edit', 'viewsource', 'download',
           'print', 'load-attachment', 'load-headers', 'forward-attachment'];
 
-        if (this.env.action=='show' || this.env.action=='preview') {
+        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);
 
           if (this.env.action == 'show') {
           this.enable_command(this.env.message_commands, this.env.uid);
           this.enable_command('reply-list', this.env.list_post);
 
           if (this.env.action == 'show') {
-            this.http_request('pagenav', '_uid='+this.env.uid+'&_mbox='+urlencode(this.env.mailbox),
+            this.http_request('pagenav', '_uid='+this.env.uid+'&_mbox='+urlencode(this.env.mailbox)
+              + (this.env.search_request ? '&_search='+this.env.search_request : ''),
               this.display_message('', 'loading'));
           }
 
               this.display_message('', 'loading'));
           }
 
@@ -277,6 +295,9 @@ function rcube_webmail()
         if (this.gui_objects.folderlist)
           this.env.contactfolders = $.extend($.extend({}, this.env.address_sources), this.env.contactgroups);
 
         if (this.gui_objects.folderlist)
           this.env.contactfolders = $.extend($.extend({}, this.env.address_sources), this.env.contactgroups);
 
+        this.enable_command('add', 'import', this.env.writable_source);
+        this.enable_command('list', 'listgroup', 'listsearch', 'advanced-search', true);
+
         if (this.gui_objects.contactslist) {
 
           this.contact_list = new rcube_list_widget(this.gui_objects.contactslist,
         if (this.gui_objects.contactslist) {
 
           this.contact_list = new rcube_list_widget(this.gui_objects.contactslist,
@@ -299,6 +320,7 @@ function rcube_webmail()
           }
 
           this.update_group_commands();
           }
 
           this.update_group_commands();
+          this.command('list');
         }
 
         this.set_page_buttons();
         }
 
         this.set_page_buttons();
@@ -318,22 +340,13 @@ function rcube_webmail()
           if (this.env.action == 'add' || this.env.action == 'edit')
               this.init_contact_form();
         }
           if (this.env.action == 'add' || this.env.action == 'edit')
               this.init_contact_form();
         }
+
         if (this.gui_objects.qsearchbox) {
           this.enable_command('search', 'reset-search', 'moveto', true);
         }
 
         if (this.gui_objects.qsearchbox) {
           this.enable_command('search', 'reset-search', 'moveto', true);
         }
 
-        if (this.contact_list && this.contact_list.rowcount > 0)
-          this.enable_command('export', true);
-
-        this.enable_command('add', 'import', this.env.writable_source);
-        this.enable_command('list', 'listgroup', 'advanced-search', true);
-
-        // load contacts of selected source
-        if (!this.env.action)
-          this.command('list', this.env.source);
         break;
 
         break;
 
-
       case 'settings':
         this.enable_command('preferences', 'identities', 'save', 'folders', true);
 
       case 'settings':
         this.enable_command('preferences', 'identities', 'save', 'folders', true);
 
@@ -384,7 +397,12 @@ function rcube_webmail()
           $('#rcmloginpwd').focus();
 
         // detect client timezone
           $('#rcmloginpwd').focus();
 
         // detect client timezone
-        $('#rcmlogintz').val(new Date().getTimezoneOffset() / -60);
+        var dt = new Date(),
+          tz = dt.getTimezoneOffset() / -60,
+          stdtz = dt.getStdTimezoneOffset() / -60;
+
+        $('#rcmlogintz').val(stdtz);
+        $('#rcmlogindst').val(tz > stdtz ? 1 : 0);
 
         // display 'loading' message on form submit, lock submit button
         $('form').submit(function () {
 
         // display 'loading' message on form submit, lock submit button
         $('form').submit(function () {
@@ -443,6 +461,8 @@ function rcube_webmail()
   // execute a specific command on the web client
   this.command = function(command, props, obj)
   {
   // execute a specific command on the web client
   this.command = function(command, props, obj)
   {
+    var ret, uid, cid, url, flag;
+
     if (obj && obj.blur)
       obj.blur();
 
     if (obj && obj.blur)
       obj.blur();
 
@@ -459,32 +479,34 @@ function rcube_webmail()
     }
 
     // check input before leaving compose step
     }
 
     // check input before leaving compose step
-    if (this.task=='mail' && this.env.action=='compose' && $.inArray(command, this.env.compose_commands)<0) {
+    if (this.task == 'mail' && this.env.action == 'compose' && $.inArray(command, this.env.compose_commands)<0) {
       if (this.cmp_hash != this.compose_field_hash() && !confirm(this.get_label('notsentwarning')))
         return false;
     }
 
     // process external commands
     if (typeof this.command_handlers[command] === 'function') {
       if (this.cmp_hash != this.compose_field_hash() && !confirm(this.get_label('notsentwarning')))
         return false;
     }
 
     // process external commands
     if (typeof this.command_handlers[command] === 'function') {
-      var ret = this.command_handlers[command](props, obj);
+      ret = this.command_handlers[command](props, obj);
       return ret !== undefined ? ret : (obj ? false : true);
     }
     else if (typeof this.command_handlers[command] === 'string') {
       return ret !== undefined ? ret : (obj ? false : true);
     }
     else if (typeof this.command_handlers[command] === 'string') {
-      var ret = window[this.command_handlers[command]](props, obj);
+      ret = window[this.command_handlers[command]](props, obj);
       return ret !== undefined ? ret : (obj ? false : true);
     }
 
     // trigger plugin hooks
     this.triggerEvent('actionbefore', {props:props, action:command});
       return ret !== undefined ? ret : (obj ? false : true);
     }
 
     // trigger plugin hooks
     this.triggerEvent('actionbefore', {props:props, action:command});
-    var ret = this.triggerEvent('before'+command, props);
+    ret = this.triggerEvent('before'+command, props);
     if (ret !== undefined) {
     if (ret !== undefined) {
-      // abort if one the handlers returned false
+      // abort if one of the handlers returned false
       if (ret === false)
         return false;
       else
         props = ret;
     }
 
       if (ret === false)
         return false;
       else
         props = ret;
     }
 
+    ret = undefined;
+
     // process internal command
     switch (command) {
 
     // process internal command
     switch (command) {
 
@@ -514,7 +536,6 @@ function rcube_webmail()
         return false;
 
       case 'open':
         return false;
 
       case 'open':
-        var uid;
         if (uid = this.get_single_uid()) {
           obj.href = '?_task='+this.env.task+'&_action=show&_mbox='+urlencode(this.env.mailbox)+'&_uid='+uid;
           return true;
         if (uid = this.get_single_uid()) {
           obj.href = '?_task='+this.env.task+'&_action=show&_mbox='+urlencode(this.env.mailbox)+'&_uid='+uid;
           return true;
@@ -522,21 +543,15 @@ function rcube_webmail()
         break;
 
       case 'list':
         break;
 
       case 'list':
-        if (this.task=='mail') {
-          if (!this.env.search_request || (props && props != this.env.mailbox))
-            this.reset_qsearch();
-
+        this.reset_qsearch();
+        if (this.task == 'mail') {
           this.list_mailbox(props);
 
           if (this.env.trash_mailbox && !this.env.flag_for_deletion)
             this.set_alttext('delete', this.env.mailbox != this.env.trash_mailbox ? 'movemessagetotrash' : 'deletemessage');
         }
         else if (this.task == 'addressbook') {
           this.list_mailbox(props);
 
           if (this.env.trash_mailbox && !this.env.flag_for_deletion)
             this.set_alttext('delete', this.env.mailbox != this.env.trash_mailbox ? 'movemessagetotrash' : 'deletemessage');
         }
         else if (this.task == 'addressbook') {
-          if (!this.env.search_request || (props != this.env.source))
-            this.reset_qsearch();
-
           this.list_contacts(props);
           this.list_contacts(props);
-          this.enable_command('add', 'import', this.env.writable_source);
         }
         break;
 
         }
         break;
 
@@ -589,7 +604,7 @@ function rcube_webmail()
       // common commands used in multiple tasks
       case 'show':
         if (this.task == 'mail') {
       // common commands used in multiple tasks
       case 'show':
         if (this.task == 'mail') {
-          var uid = this.get_single_uid();
+          uid = this.get_single_uid();
           if (uid && (!this.env.uid || uid != this.env.uid)) {
             if (this.env.mailbox == this.env.drafts_mailbox)
               this.goto_url('compose', '_draft_uid='+uid+'&_mbox='+urlencode(this.env.mailbox), true);
           if (uid && (!this.env.uid || uid != this.env.uid)) {
             if (this.env.mailbox == this.env.drafts_mailbox)
               this.goto_url('compose', '_draft_uid='+uid+'&_mbox='+urlencode(this.env.mailbox), true);
@@ -598,7 +613,7 @@ function rcube_webmail()
           }
         }
         else if (this.task == 'addressbook') {
           }
         }
         else if (this.task == 'addressbook') {
-          var cid = props ? props : this.get_single_cid();
+          cid = props ? props : this.get_single_cid();
           if (cid && !(this.env.action == 'show' && cid == this.env.cid))
             this.load_contact(cid, 'show');
         }
           if (cid && !(this.env.action == 'show' && cid == this.env.cid))
             this.load_contact(cid, 'show');
         }
@@ -614,13 +629,12 @@ function rcube_webmail()
         break;
 
       case 'edit':
         break;
 
       case 'edit':
-        var cid;
         if (this.task=='addressbook' && (cid = this.get_single_cid()))
           this.load_contact(cid, 'edit');
         else if (this.task=='settings' && props)
           this.load_identity(props, 'edit-identity');
         else if (this.task=='mail' && (cid = this.get_single_uid())) {
         if (this.task=='addressbook' && (cid = this.get_single_cid()))
           this.load_contact(cid, 'edit');
         else if (this.task=='settings' && props)
           this.load_identity(props, 'edit-identity');
         else if (this.task=='mail' && (cid = this.get_single_uid())) {
-          var url = (this.env.mailbox == this.env.drafts_mailbox) ? '_draft_uid=' : '_uid=';
+          url = (this.env.mailbox == this.env.drafts_mailbox) ? '_draft_uid=' : '_uid=';
           this.goto_url('compose', url+cid+'&_mbox='+urlencode(this.env.mailbox), true);
         }
         break;
           this.goto_url('compose', url+cid+'&_mbox='+urlencode(this.env.mailbox), true);
         }
         break;
@@ -698,7 +712,7 @@ function rcube_webmail()
         if (props && !props._row)
           break;
 
         if (props && !props._row)
           break;
 
-        var uid, flag = 'read';
+        flag = 'read';
 
         if (props._row.uid) {
           uid = props._row.uid;
 
         if (props._row.uid) {
           uid = props._row.uid;
@@ -718,7 +732,7 @@ function rcube_webmail()
         if (props && !props._row)
           break;
 
         if (props && !props._row)
           break;
 
-        var uid, flag = 'flagged';
+        flag = 'flagged';
 
         if (props._row.uid) {
           uid = props._row.uid;
 
         if (props._row.uid) {
           uid = props._row.uid;
@@ -814,17 +828,11 @@ function rcube_webmail()
         break;
 
       case 'compose':
         break;
 
       case 'compose':
-        var url = this.env.comm_path+'&_action=compose';
+        url = this.url('mail/compose');
 
         if (this.task == 'mail') {
           url += '&_mbox='+urlencode(this.env.mailbox);
 
         if (this.task == 'mail') {
           url += '&_mbox='+urlencode(this.env.mailbox);
-
-          if (this.env.mailbox == this.env.drafts_mailbox) {
-            var uid;
-            if (uid = this.get_single_uid())
-              url += '&_draft_uid='+uid;
-          }
-          else if (props)
+          if (props)
              url += '&_to='+urlencode(props);
         }
         // modify url if we're in addressbook
              url += '&_to='+urlencode(props);
         }
         // modify url if we're in addressbook
@@ -848,10 +856,14 @@ function rcube_webmail()
           }
 
           if (a_cids.length)
           }
 
           if (a_cids.length)
-            this.http_post('mailto', {_cid: a_cids.join(','), _source: this.env.source}, true);
+            this.http_post('mailto', { _cid: a_cids.join(','), _source: this.env.source}, true);
+          else if (this.env.group)
+            this.http_post('mailto', { _gid: this.env.group, _source: this.env.source}, true);
 
           break;
         }
 
           break;
         }
+        else if (props)
+          url += '&_to='+urlencode(props);
 
         this.redirect(url);
         break;
 
         this.redirect(url);
         break;
@@ -891,7 +903,7 @@ function rcube_webmail()
         if (!this.gui_objects.messageform)
           break;
 
         if (!this.gui_objects.messageform)
           break;
 
-        if (!this.check_compose_input())
+        if (!props.nocheck && !this.check_compose_input(command))
           break;
 
         // Reset the auto-save timer
           break;
 
         // Reset the auto-save timer
@@ -926,9 +938,8 @@ function rcube_webmail()
       case 'reply-all':
       case 'reply-list':
       case 'reply':
       case 'reply-all':
       case 'reply-list':
       case 'reply':
-        var uid;
         if (uid = this.get_single_uid()) {
         if (uid = this.get_single_uid()) {
-          var url = '_reply_uid='+uid+'&_mbox='+urlencode(this.env.mailbox);
+          url = '_reply_uid='+uid+'&_mbox='+urlencode(this.env.mailbox);
           if (command == 'reply-all')
             // do reply-list, when list is detected and popup menu wasn't used 
             url += '&_all=' + (!props && this.commands['reply-list'] ? 'list' : 'all');
           if (command == 'reply-all')
             // do reply-list, when list is detected and popup menu wasn't used 
             url += '&_all=' + (!props && this.commands['reply-list'] ? 'list' : 'all');
@@ -941,7 +952,6 @@ function rcube_webmail()
 
       case 'forward-attachment':
       case 'forward':
 
       case 'forward-attachment':
       case 'forward':
-        var uid, url;
         if (uid = this.get_single_uid()) {
           url = '_forward_uid='+uid+'&_mbox='+urlencode(this.env.mailbox);
           if (command == 'forward-attachment' || (!props && this.env.forward_attachment))
         if (uid = this.get_single_uid()) {
           url = '_forward_uid='+uid+'&_mbox='+urlencode(this.env.mailbox);
           if (command == 'forward-attachment' || (!props && this.env.forward_attachment))
@@ -951,7 +961,6 @@ function rcube_webmail()
         break;
 
       case 'print':
         break;
 
       case 'print':
-        var uid;
         if (uid = this.get_single_uid()) {
           ref.printwin = window.open(this.env.comm_path+'&_action=print&_uid='+uid+'&_mbox='+urlencode(this.env.mailbox)+(this.env.safemode ? '&_safe=1' : ''));
           if (this.printwin) {
         if (uid = this.get_single_uid()) {
           ref.printwin = window.open(this.env.comm_path+'&_action=print&_uid='+uid+'&_mbox='+urlencode(this.env.mailbox)+(this.env.safemode ? '&_safe=1' : ''));
           if (this.printwin) {
@@ -963,7 +972,6 @@ function rcube_webmail()
         break;
 
       case 'viewsource':
         break;
 
       case 'viewsource':
-        var uid;
         if (uid = this.get_single_uid()) {
           ref.sourcewin = window.open(this.env.comm_path+'&_action=viewsource&_uid='+uid+'&_mbox='+urlencode(this.env.mailbox));
           if (this.sourcewin)
         if (uid = this.get_single_uid()) {
           ref.sourcewin = window.open(this.env.comm_path+'&_action=viewsource&_uid='+uid+'&_mbox='+urlencode(this.env.mailbox));
           if (this.sourcewin)
@@ -972,7 +980,6 @@ function rcube_webmail()
         break;
 
       case 'download':
         break;
 
       case 'download':
-        var uid;
         if (uid = this.get_single_uid())
           this.goto_url('viewsource', '&_uid='+uid+'&_mbox='+urlencode(this.env.mailbox)+'&_save=1');
         break;
         if (uid = this.get_single_uid())
           this.goto_url('viewsource', '&_uid='+uid+'&_mbox='+urlencode(this.env.mailbox)+'&_save=1');
         break;
@@ -1006,6 +1013,7 @@ function rcube_webmail()
         break;
 
       case 'listgroup':
         break;
 
       case 'listgroup':
+        this.reset_qsearch();
         this.list_contacts(props.source, props.id);
         break;
 
         this.list_contacts(props.source, props.id);
         break;
 
@@ -1052,24 +1060,26 @@ function rcube_webmail()
       // unified command call (command name == function name)
       default:
         var func = command.replace(/-/g, '_');
       // unified command call (command name == function name)
       default:
         var func = command.replace(/-/g, '_');
-        if (this[func] && typeof this[func] === 'function')
-          this[func](props);
+        if (this[func] && typeof this[func] === 'function') {
+          ret = this[func](props);
+        }
         break;
     }
 
         break;
     }
 
-    this.triggerEvent('after'+command, props);
+    if (this.triggerEvent('after'+command, props) === false)
+      ret = false;
     this.triggerEvent('actionafter', {props:props, action:command});
 
     this.triggerEvent('actionafter', {props:props, action:command});
 
-    return obj ? false : true;
+    return ret === false ? false : obj ? false : true;
   };
 
   // set command(s) enabled or disabled
   this.enable_command = function()
   {
   };
 
   // set command(s) enabled or disabled
   this.enable_command = function()
   {
-    var args = Array.prototype.slice.call(arguments),
+    var i, n, args = Array.prototype.slice.call(arguments),
       enable = args.pop(), cmd;
 
       enable = args.pop(), cmd;
 
-    for (var n=0; n<args.length; n++) {
+    for (n=0; n<args.length; n++) {
       cmd = args[n];
       // argument of type array
       if (typeof cmd === 'string') {
       cmd = args[n];
       // argument of type array
       if (typeof cmd === 'string') {
@@ -1078,7 +1088,7 @@ function rcube_webmail()
       }
       // push array elements into commands array
       else {
       }
       // push array elements into commands array
       else {
-        for (var i in cmd)
+        for (i in cmd)
           args.push(cmd[i]);
       }
     }
           args.push(cmd[i]);
       }
     }
@@ -1205,6 +1215,24 @@ function rcube_webmail()
     this.http_post('save-pref', request);
   };
 
     this.http_post('save-pref', request);
   };
 
+  this.html_identifier = function(str, encode)
+  {
+    str = String(str);
+    if (encode)
+      return Base64.encode(str).replace(/=+$/, '').replace(/\+/g, '-').replace(/\//g, '_');
+    else
+      return str.replace(this.identifier_expr, '_');
+  };
+
+  this.html_identifier_decode = function(str)
+  {
+    str = String(str).replace(/-/g, '+').replace(/_/g, '/');
+
+    while (str.length % 4) str += '=';
+
+    return Base64.decode(str);
+  };
+
 
   /*********************************************************/
   /*********        event handling methods         *********/
 
   /*********************************************************/
   /*********        event handling methods         *********/
@@ -1251,13 +1279,14 @@ function rcube_webmail()
       this.initialBodyScrollTop = bw.ie ? 0 : window.pageYOffset;
       this.initialListScrollTop = this.gui_objects.folderlist.parentNode.scrollTop;
 
       this.initialBodyScrollTop = bw.ie ? 0 : window.pageYOffset;
       this.initialListScrollTop = this.gui_objects.folderlist.parentNode.scrollTop;
 
-      var li, pos, list, height;
-      list = $(this.gui_objects.folderlist);
-      pos = list.offset();
+      var k, li, height,
+        list = $(this.gui_objects.folderlist);
+        pos = list.offset();
+
       this.env.folderlist_coords = { x1:pos.left, y1:pos.top, x2:pos.left + list.width(), y2:pos.top + list.height() };
 
       this.env.folder_coords = [];
       this.env.folderlist_coords = { x1:pos.left, y1:pos.top, x2:pos.left + list.width(), y2:pos.top + list.height() };
 
       this.env.folder_coords = [];
-      for (var k in model) {
+      for (k in model) {
         if (li = this.get_folder_li(k)) {
           // only visible folders
           if (height = li.firstChild.offsetHeight) {
         if (li = this.get_folder_li(k)) {
           // only visible folders
           if (height = li.firstChild.offsetHeight) {
@@ -1293,19 +1322,18 @@ function rcube_webmail()
   this.drag_move = function(e)
   {
     if (this.gui_objects.folderlist && this.env.folder_coords) {
   this.drag_move = function(e)
   {
     if (this.gui_objects.folderlist && this.env.folder_coords) {
-      // offsets to compensate for scrolling while dragging a message
-      var boffset = bw.ie ? -document.documentElement.scrollTop : this.initialBodyScrollTop;
-      var moffset = this.initialListScrollTop-this.gui_objects.folderlist.parentNode.scrollTop;
-      var toffset = -moffset-boffset;
-      var li, div, pos, mouse, check, oldclass,
-        layerclass = 'draglayernormal';
+      var k, li, div, check, oldclass,
+        layerclass = 'draglayernormal',
+        mouse = rcube_event.get_mouse_pos(e),
+        pos = this.env.folderlist_coords,
+        // offsets to compensate for scrolling while dragging a message
+        boffset = bw.ie ? -document.documentElement.scrollTop : this.initialBodyScrollTop,
+        moffset = this.initialListScrollTop-this.gui_objects.folderlist.parentNode.scrollTop;
 
       if (this.contact_list && this.contact_list.draglayer)
         oldclass = this.contact_list.draglayer.attr('class');
 
 
       if (this.contact_list && this.contact_list.draglayer)
         oldclass = this.contact_list.draglayer.attr('class');
 
-      mouse = rcube_event.get_mouse_pos(e);
-      pos = this.env.folderlist_coords;
-      mouse.y += toffset;
+      mouse.y += -moffset-boffset;
 
       // if mouse pointer is outside of folderlist
       if (mouse.x < pos.x1 || mouse.x >= pos.x2 || mouse.y < pos.y1 || mouse.y >= pos.y2) {
 
       // if mouse pointer is outside of folderlist
       if (mouse.x < pos.x1 || mouse.x >= pos.x2 || mouse.y < pos.y1 || mouse.y >= pos.y2) {
@@ -1320,10 +1348,10 @@ function rcube_webmail()
       }
 
       // over the folders
       }
 
       // over the folders
-      for (var k in this.env.folder_coords) {
+      for (k in this.env.folder_coords) {
         pos = this.env.folder_coords[k];
         if (mouse.x >= pos.x1 && mouse.x < pos.x2 && mouse.y >= pos.y1 && mouse.y < pos.y2){
         pos = this.env.folder_coords[k];
         if (mouse.x >= pos.x1 && mouse.x < pos.x2 && mouse.y >= pos.y1 && mouse.y < pos.y2){
-         if ((check = this.check_droptarget(k))) {
+          if ((check = this.check_droptarget(k))) {
             li = this.get_folder_li(k);
             div = $(li.getElementsByTagName('div')[0]);
 
             li = this.get_folder_li(k);
             div = $(li.getElementsByTagName('div')[0]);
 
@@ -1334,9 +1362,9 @@ function rcube_webmail()
 
               this.folder_auto_expand = k;
               this.folder_auto_timer = window.setTimeout(function() {
 
               this.folder_auto_expand = k;
               this.folder_auto_timer = window.setTimeout(function() {
-                  rcmail.command('collapse-folder', rcmail.folder_auto_expand);
-                  rcmail.drag_start(null);
-                }, 1000);
+                rcmail.command('collapse-folder', rcmail.folder_auto_expand);
+                rcmail.drag_start(null);
+              }, 1000);
             } else if (this.folder_auto_timer) {
               window.clearTimeout(this.folder_auto_timer);
               this.folder_auto_timer = null;
             } else if (this.folder_auto_timer) {
               window.clearTimeout(this.folder_auto_timer);
               this.folder_auto_timer = null;
@@ -1362,31 +1390,29 @@ function rcube_webmail()
     }
   };
 
     }
   };
 
-  this.collapse_folder = function(id)
+  this.collapse_folder = function(name)
   {
   {
-    var li = this.get_folder_li(id),
-      div = $(li.getElementsByTagName('div')[0]);
-
-    if (!div || (!div.hasClass('collapsed') && !div.hasClass('expanded')))
-      return;
-
-    var ul = $(li.getElementsByTagName('ul')[0]);
+    var li = this.get_folder_li(name, '', true),
+      div = $('div:first', li),
+      ul = $('ul:first', li);
 
     if (div.hasClass('collapsed')) {
       ul.show();
       div.removeClass('collapsed').addClass('expanded');
 
     if (div.hasClass('collapsed')) {
       ul.show();
       div.removeClass('collapsed').addClass('expanded');
-      var reg = new RegExp('&'+urlencode(id)+'&');
+      var reg = new RegExp('&'+urlencode(name)+'&');
       this.env.collapsed_folders = this.env.collapsed_folders.replace(reg, '');
     }
       this.env.collapsed_folders = this.env.collapsed_folders.replace(reg, '');
     }
-    else {
+    else if (div.hasClass('expanded')) {
       ul.hide();
       div.removeClass('expanded').addClass('collapsed');
       ul.hide();
       div.removeClass('expanded').addClass('collapsed');
-      this.env.collapsed_folders = this.env.collapsed_folders+'&'+urlencode(id)+'&';
+      this.env.collapsed_folders = this.env.collapsed_folders+'&'+urlencode(name)+'&';
 
       // select parent folder if one of its childs is currently selected
 
       // select parent folder if one of its childs is currently selected
-      if (this.env.mailbox.indexOf(id + this.env.delimiter) == 0)
-        this.command('list', id);
+      if (this.env.mailbox.indexOf(name + this.env.delimiter) == 0)
+        this.command('list', name);
     }
     }
+    else
+      return;
 
     // Work around a bug in IE6 and IE7, see #1485309
     if (bw.ie6 || bw.ie7) {
 
     // Work around a bug in IE6 and IE7, see #1485309
     if (bw.ie6 || bw.ie7) {
@@ -1398,13 +1424,17 @@ function rcube_webmail()
     }
 
     this.command('save-pref', { name: 'collapsed_folders', value: this.env.collapsed_folders });
     }
 
     this.command('save-pref', { name: 'collapsed_folders', value: this.env.collapsed_folders });
-    this.set_unread_count_display(id, false);
+    this.set_unread_count_display(name, false);
   };
 
   this.doc_mouse_up = function(e)
   {
     var model, list, li, id;
 
   };
 
   this.doc_mouse_up = function(e)
   {
     var model, list, li, id;
 
+    // ignore event if jquery UI dialog is open
+    if ($(rcube_event.get_target(e)).closest('.ui-dialog, .ui-widget-overlay').length)
+      return;
+
     if (list = this.message_list) {
       if (!rcube_mouse_is_over(e, list.list.parentNode))
         list.blur();
     if (list = this.message_list) {
       if (!rcube_mouse_is_over(e, list.list.parentNode))
         list.blur();
@@ -1526,11 +1556,12 @@ function rcube_webmail()
 
   this.msglist_keypress = function(list)
   {
 
   this.msglist_keypress = function(list)
   {
+    if (list.modkey == CONTROL_KEY)
+      return;
+
     if (list.key_pressed == list.ENTER_KEY)
       this.command('show');
     if (list.key_pressed == list.ENTER_KEY)
       this.command('show');
-    else if (list.key_pressed == list.DELETE_KEY)
-      this.command('delete');
-    else if (list.key_pressed == list.BACKSPACE_KEY)
+    else if (list.key_pressed == list.DELETE_KEY || list.key_pressed == list.BACKSPACE_KEY)
       this.command('delete');
     else if (list.key_pressed == 33)
       this.command('previouspage');
       this.command('delete');
     else if (list.key_pressed == 33)
       this.command('previouspage');
@@ -1644,14 +1675,18 @@ function rcube_webmail()
     if (!this.gui_objects.messagelist || !this.message_list)
       return false;
 
     if (!this.gui_objects.messagelist || !this.message_list)
       return false;
 
+    // Prevent from adding messages from different folder (#1487752)
+    if (flags.mbox != this.env.mailbox && !flags.skip_mbox_check)
+      return false;
+
     if (!this.env.messages[uid])
       this.env.messages[uid] = {};
 
     // merge flags over local message object
     $.extend(this.env.messages[uid], {
       deleted: flags.deleted?1:0,
     if (!this.env.messages[uid])
       this.env.messages[uid] = {};
 
     // merge flags over local message object
     $.extend(this.env.messages[uid], {
       deleted: flags.deleted?1:0,
-      replied: flags.replied?1:0,
-      unread: flags.unread?1:0,
+      replied: flags.answered?1:0,
+      unread: !flags.seen?1:0,
       forwarded: flags.forwarded?1:0,
       flagged: flags.flagged?1:0,
       has_children: flags.has_children?1:0,
       forwarded: flags.forwarded?1:0,
       flagged: flags.flagged?1:0,
       has_children: flags.has_children?1:0,
@@ -1665,23 +1700,18 @@ function rcube_webmail()
       flags: flags.extra_flags
     });
 
       flags: flags.extra_flags
     });
 
-    var c, html, tree = expando = '',
+    var c, n, col, html, tree = '', expando = '',
       list = this.message_list,
       rows = list.rows,
       list = this.message_list,
       rows = list.rows,
-      tbody = this.gui_objects.messagelist.tBodies[0],
-      rowcount = tbody.rows.length,
-      even = rowcount%2,
       message = this.env.messages[uid],
       css_class = 'message'
       message = this.env.messages[uid],
       css_class = 'message'
-        + (even ? ' even' : ' odd')
-        + (flags.unread ? ' unread' : '')
+        + (!flags.seen ? ' unread' : '')
         + (flags.deleted ? ' deleted' : '')
         + (flags.flagged ? ' flagged' : '')
         + (flags.deleted ? ' deleted' : '')
         + (flags.flagged ? ' flagged' : '')
-        + (flags.unread_children && !flags.unread && !this.env.autoexpand_threads ? ' unroot' : '')
+        + (flags.unread_children && flags.seen && !this.env.autoexpand_threads ? ' unroot' : '')
         + (message.selected ? ' selected' : ''),
       // for performance use DOM instead of jQuery here
         + (message.selected ? ' selected' : ''),
       // for performance use DOM instead of jQuery here
-      row = document.createElement('tr'),
-      col = document.createElement('td');
+      row = document.createElement('tr');
 
     row.id = 'rcmrow'+uid;
     row.className = css_class;
 
     row.id = 'rcmrow'+uid;
     row.className = css_class;
@@ -1692,12 +1722,12 @@ function rcube_webmail()
       css_class += ' status';
       if (flags.deleted)
         css_class += ' deleted';
       css_class += ' status';
       if (flags.deleted)
         css_class += ' deleted';
-      else if (flags.unread)
+      else if (!flags.seen)
         css_class += ' unread';
       else if (flags.unread_children > 0)
         css_class += ' unreadchildren';
     }
         css_class += ' unread';
       else if (flags.unread_children > 0)
         css_class += ' unreadchildren';
     }
-    if (flags.replied)
+    if (flags.answered)
       css_class += ' replied';
     if (flags.forwarded)
       css_class += ' forwarded';
       css_class += ' replied';
     if (flags.forwarded)
       css_class += ' forwarded';
@@ -1708,9 +1738,10 @@ function rcube_webmail()
 
     // threads
     if (this.env.threading) {
 
     // threads
     if (this.env.threading) {
-      // This assumes that div width is hardcoded to 15px,
-      var width = message.depth * 15;
       if (message.depth) {
       if (message.depth) {
+        // This assumes that div width is hardcoded to 15px,
+        tree += '<span id="rcmtab' + uid + '" class="branch" style="width:' + (message.depth * 15) + 'px;">&nbsp;&nbsp;</span>';
+
         if ((rows[message.parent_uid] && rows[message.parent_uid].expanded === false)
           || ((this.env.autoexpand_threads == 0 || this.env.autoexpand_threads == 2) &&
             (!rows[message.parent_uid] || !rows[message.parent_uid].expanded))
         if ((rows[message.parent_uid] && rows[message.parent_uid].expanded === false)
           || ((this.env.autoexpand_threads == 0 || this.env.autoexpand_threads == 2) &&
             (!rows[message.parent_uid] || !rows[message.parent_uid].expanded))
@@ -1725,13 +1756,9 @@ function rcube_webmail()
         if (message.expanded === undefined && (this.env.autoexpand_threads == 1 || (this.env.autoexpand_threads == 2 && message.unread_children))) {
           message.expanded = true;
         }
         if (message.expanded === undefined && (this.env.autoexpand_threads == 1 || (this.env.autoexpand_threads == 2 && message.unread_children))) {
           message.expanded = true;
         }
-      }
 
 
-      if (width)
-        tree += '<span id="rcmtab' + uid + '" class="branch" style="width:' + width + 'px;">&nbsp;&nbsp;</span>';
-
-      if (message.has_children && !message.depth)
         expando = '<div id="rcmexpando' + uid + '" class="' + (message.expanded ? 'expanded' : 'collapsed') + '">&nbsp;&nbsp;</div>';
         expando = '<div id="rcmexpando' + uid + '" class="' + (message.expanded ? 'expanded' : 'collapsed') + '">&nbsp;&nbsp;</div>';
+      }
     }
 
     tree += '<span id="msgicn'+uid+'" class="'+css_class+'">&nbsp;</span>';
     }
 
     tree += '<span id="msgicn'+uid+'" class="'+css_class+'">&nbsp;</span>';
@@ -1745,7 +1772,7 @@ function rcube_webmail()
     }
 
     // add each submitted col
     }
 
     // add each submitted col
-    for (var n in this.env.coltypes) {
+    for (n in this.env.coltypes) {
       c = this.env.coltypes[n];
       col = document.createElement('td');
       col.className = String(c).toLowerCase();
       c = this.env.coltypes[n];
       col = document.createElement('td');
       col.className = String(c).toLowerCase();
@@ -1765,7 +1792,7 @@ function rcube_webmail()
       else if (c == 'status') {
         if (flags.deleted)
           css_class = 'deleted';
       else if (c == 'status') {
         if (flags.deleted)
           css_class = 'deleted';
-        else if (flags.unread)
+        else if (!flags.seen)
           css_class = 'unread';
         else if (flags.unread_children > 0)
           css_class = 'unreadchildren';
           css_class = 'unread';
         else if (flags.unread_children > 0)
           css_class = 'unreadchildren';
@@ -1775,8 +1802,17 @@ function rcube_webmail()
       }
       else if (c == 'threads')
         html = expando;
       }
       else if (c == 'threads')
         html = expando;
-      else if (c == 'subject')
+      else if (c == 'subject') {
+        if (bw.ie)
+          col.onmouseover = function() { rcube_webmail.long_subject_title_ie(this, message.depth+1); };
         html = tree + cols[c];
         html = tree + cols[c];
+      }
+      else if (c == 'priority') {
+        if (flags.prio > 0 && flags.prio < 6)
+          html = '<span class="prio'+flags.prio+'">&nbsp;</span>';
+        else
+          html = '&nbsp;';
+      }
       else
         html = cols[c];
 
       else
         html = cols[c];
 
@@ -1940,18 +1976,13 @@ function rcube_webmail()
   // list messages of a specific mailbox using filter
   this.filter_mailbox = function(filter)
   {
   // list messages of a specific mailbox using filter
   this.filter_mailbox = function(filter)
   {
-    var search, lock = this.set_busy(true, 'searching');
-
-    if (this.gui_objects.qsearchbox)
-      search = this.gui_objects.qsearchbox.value;
+    var lock = this.set_busy(true, 'searching');
 
     this.clear_message_list();
 
     // reset vars
     this.env.current_page = 1;
 
     this.clear_message_list();
 
     // reset vars
     this.env.current_page = 1;
-    this.http_request('search', '_filter='+filter
-        + (search ? '&_q='+urlencode(search) : '')
-        + (this.env.mailbox ? '&_mbox='+urlencode(this.env.mailbox) : ''), lock);
+    this.http_request('search', this.search_params(false, filter), lock);
   };
 
   // list messages of a specific mailbox
   };
 
   // list messages of a specific mailbox
@@ -1986,7 +2017,7 @@ function rcube_webmail()
     if (mbox != this.env.mailbox || (mbox == this.env.mailbox && !page && !sort))
       url += '&_refresh=1';
 
     if (mbox != this.env.mailbox || (mbox == this.env.mailbox && !page && !sort))
       url += '&_refresh=1';
 
-    this.select_folder(mbox, this.env.mailbox);
+    this.select_folder(mbox, '', true);
     this.env.mailbox = mbox;
 
     // load message list remotely
     this.env.mailbox = mbox;
 
     // load message list remotely
@@ -2050,8 +2081,7 @@ function rcube_webmail()
       new_row = tbody.firstChild;
 
     while (new_row) {
       new_row = tbody.firstChild;
 
     while (new_row) {
-      if (new_row.nodeType == 1 && (r = this.message_list.rows[new_row.uid])
-           && r.unread_children) {
+      if (new_row.nodeType == 1 && (r = this.message_list.rows[new_row.uid]) && r.unread_children) {
            this.message_list.expand_all(r);
            this.set_unread_children(r.uid);
       }
            this.message_list.expand_all(r);
            this.set_unread_children(r.uid);
       }
@@ -2086,8 +2116,12 @@ function rcube_webmail()
   };
 
   // Initializes threads indicators/expanders after list update
   };
 
   // Initializes threads indicators/expanders after list update
-  this.init_threads = function(roots)
+  this.init_threads = function(roots, mbox)
   {
   {
+    // #1487752
+    if (mbox && mbox != this.env.mailbox)
+      return false;
+
     for (var n=0, len=roots.length; n<len; n++)
       this.add_tree_icons(roots[n]);
     this.expand_threads();
     for (var n=0, len=roots.length; n<len; n++)
       this.add_tree_icons(roots[n]);
     this.expand_threads();
@@ -2491,7 +2525,7 @@ function rcube_webmail()
     // if there is a trash mailbox defined and we're not currently in it
     else {
       // if shift was pressed delete it immediately
     // if there is a trash mailbox defined and we're not currently in it
     else {
       // if shift was pressed delete it immediately
-      if (list && list.shiftkey) {
+      if (list && list.modkey == SHIFT_KEY) {
         if (confirm(this.get_label('deletemessagesconfirm')))
           this.permanently_remove_messages();
       }
         if (confirm(this.get_label('deletemessagesconfirm')))
           this.permanently_remove_messages();
       }
@@ -2914,12 +2948,14 @@ function rcube_webmail()
 
   this.init_address_input_events = function(obj, props)
   {
 
   this.init_address_input_events = function(obj, props)
   {
+    this.env.recipients_delimiter = this.env.recipients_separator + ' ';
+
     obj[bw.ie || bw.safari || bw.chrome ? 'keydown' : 'keypress'](function(e) { return ref.ksearch_keydown(e, this, props); })
       .attr('autocomplete', 'off');
   };
 
   // checks the input fields before sending a message
     obj[bw.ie || bw.safari || bw.chrome ? 'keydown' : 'keypress'](function(e) { return ref.ksearch_keydown(e, this, props); })
       .attr('autocomplete', 'off');
   };
 
   // checks the input fields before sending a message
-  this.check_compose_input = function()
+  this.check_compose_input = function(cmd)
   {
     // check input fields
     var ed, input_to = $("[name='_to']"),
   {
     // check input fields
     var ed, input_to = $("[name='_to']"),
@@ -2954,15 +2990,28 @@ function rcube_webmail()
 
     // display localized warning for missing subject
     if (input_subject.val() == '') {
 
     // display localized warning for missing subject
     if (input_subject.val() == '') {
-      var subject = prompt(this.get_label('nosubjectwarning'), this.get_label('nosubject'));
+      var myprompt = $('<div class="prompt">').html('<div class="message">' + this.get_label('nosubjectwarning') + '</div>').appendTo(document.body);
+      var prompt_value = $('<input>').attr('type', 'text').attr('size', 30).appendTo(myprompt).val(this.get_label('nosubject'));
 
 
-      // user hit cancel, so don't send
-      if (!subject && subject !== '') {
+      var buttons = {};
+      buttons[this.get_label('cancel')] = function(){
         input_subject.focus();
         input_subject.focus();
-        return false;
-      }
-      else
-        input_subject.val((subject ? subject : this.get_label('nosubject')));
+        $(this).dialog('close');
+      };
+      buttons[this.get_label('sendmessage')] = function(){
+        input_subject.val(prompt_value.val());
+        $(this).dialog('close');
+        ref.command(cmd, { nocheck:true });  // repeat command which triggered this
+      };
+
+      myprompt.dialog({
+        modal: true,
+        resizable: false,
+        buttons: buttons,
+        close: function(event, ui) { $(this).remove() }
+      });
+      prompt_value.select();
+      return false;
     }
 
     // Apply spellcheck changes if spell checker is active
     }
 
     // Apply spellcheck changes if spell checker is active
@@ -3151,7 +3200,7 @@ function rcube_webmail()
         sig = this.env.signatures[sig].is_html ? this.env.signatures[sig].plain_text : this.env.signatures[sig].text;
         sig = sig.replace(/\r\n/g, '\n');
 
         sig = this.env.signatures[sig].is_html ? this.env.signatures[sig].plain_text : this.env.signatures[sig].text;
         sig = sig.replace(/\r\n/g, '\n');
 
-        if (!sig.match(/^--[ -]\n/))
+        if (!sig.match(/^--[ -]\n/m))
           sig = sig_separator + '\n' + sig;
 
         p = this.env.sig_above ? message.indexOf(sig) : message.lastIndexOf(sig);
           sig = sig_separator + '\n' + sig;
 
         p = this.env.sig_above ? message.indexOf(sig) : message.lastIndexOf(sig);
@@ -3163,7 +3212,7 @@ function rcube_webmail()
         sig = this.env.signatures[id]['is_html'] ? this.env.signatures[id]['plain_text'] : this.env.signatures[id]['text'];
         sig = sig.replace(/\r\n/g, '\n');
 
         sig = this.env.signatures[id]['is_html'] ? this.env.signatures[id]['plain_text'] : this.env.signatures[id]['text'];
         sig = sig.replace(/\r\n/g, '\n');
 
-        if (!sig.match(/^--[ -]\n/))
+        if (!sig.match(/^--[ -]\n/m))
           sig = sig_separator + '\n' + sig;
 
         if (this.env.sig_above) {
           sig = sig_separator + '\n' + sig;
 
         if (this.env.sig_above) {
@@ -3232,12 +3281,12 @@ function rcube_webmail()
       if (this.env.signatures[id]) {
         if (this.env.signatures[id].is_html) {
           sig = this.env.signatures[id].text;
       if (this.env.signatures[id]) {
         if (this.env.signatures[id].is_html) {
           sig = this.env.signatures[id].text;
-          if (!this.env.signatures[id].plain_text.match(/^--[ -]\r?\n/))
+          if (!this.env.signatures[id].plain_text.match(/^--[ -]\r?\n/m))
             sig = sig_separator + '<br />' + sig;
         }
         else {
           sig = this.env.signatures[id].text;
             sig = sig_separator + '<br />' + sig;
         }
         else {
           sig = this.env.signatures[id].text;
-          if (!sig.match(/^--[ -]\r?\n/))
+          if (!sig.match(/^--[ -]\r?\n/m))
             sig = sig_separator + '\n' + sig;
           sig = '<pre>' + sig + '</pre>';
         }
             sig = sig_separator + '\n' + sig;
           sig = '<pre>' + sig + '</pre>';
         }
@@ -3341,16 +3390,8 @@ function rcube_webmail()
 
   this.remove_from_attachment_list = function(name)
   {
 
   this.remove_from_attachment_list = function(name)
   {
-    if (this.env.attachments[name])
-      delete this.env.attachments[name];
-
-    if (!this.gui_objects.attachmentlist)
-      return false;
-
-    var list = this.gui_objects.attachmentlist.getElementsByTagName("li");
-    for (i=0; i<list.length; i++)
-      if (list[i].id == name)
-        this.gui_objects.attachmentlist.removeChild(list[i]);
+    delete this.env.attachments[name];
+    $('#'+name).remove();
   };
 
   this.remove_attachment = function(name)
   };
 
   this.remove_attachment = function(name)
@@ -3403,40 +3444,58 @@ function rcube_webmail()
   this.qsearch = function(value)
   {
     if (value != '') {
   this.qsearch = function(value)
   {
     if (value != '') {
-      var n, r, addurl = '', mods_arr = [],
-        mods = this.env.search_mods,
-        mbox = this.env.mailbox,
-        lock = this.set_busy(true, 'searching');
+      var n, lock = this.set_busy(true, 'searching');
 
 
-      if (this.message_list) {
+      if (this.message_list)
         this.clear_message_list();
         this.clear_message_list();
-        if (mods)
-          mods = mods[mbox] ? mods[mbox] : mods['*'];
-      } else if (this.contact_list) {
+      else if (this.contact_list)
         this.list_contacts_clear();
         this.list_contacts_clear();
-      }
-
-      if (mods) {
-        for (n in mods)
-          mods_arr.push(n);
-        addurl += '&_headers='+mods_arr.join(',');
-      }
-
-      if (this.gui_objects.search_filter)
-        addurl += '&_filter=' + this.gui_objects.search_filter.value;
 
       // reset vars
       this.env.current_page = 1;
 
       // reset vars
       this.env.current_page = 1;
-      r = this.http_request('search', '_q='+urlencode(value)
-        + (mbox ? '&_mbox='+urlencode(mbox) : '')
+      r = this.http_request('search', this.search_params(value)
         + (this.env.source ? '&_source='+urlencode(this.env.source) : '')
         + (this.env.source ? '&_source='+urlencode(this.env.source) : '')
-        + (this.env.group ? '&_gid='+urlencode(this.env.group) : '')
-        + (addurl ? addurl : ''), lock);
+        + (this.env.group ? '&_gid='+urlencode(this.env.group) : ''), lock);
 
       this.env.qsearch = {lock: lock, request: r};
     }
   };
 
 
       this.env.qsearch = {lock: lock, request: r};
     }
   };
 
+  // build URL params for search
+  this.search_params = function(search, filter)
+  {
+    var n, url = [], mods_arr = [],
+      mods = this.env.search_mods,
+      mbox = this.env.mailbox;
+
+    if (!filter && this.gui_objects.search_filter)
+      filter = this.gui_objects.search_filter.value;
+
+    if (!search && this.gui_objects.qsearchbox)
+      search = this.gui_objects.qsearchbox.value;
+
+    if (filter)
+      url.push('_filter=' + urlencode(filter));
+
+    if (search) {
+      url.push('_q='+urlencode(search));
+
+      if (mods && this.message_list)
+        mods = mods[mbox] ? mods[mbox] : mods['*'];
+
+      if (mods) {
+        for (n in mods)
+          mods_arr.push(n);
+        url.push('_headers='+mods_arr.join(','));
+      }
+    }
+
+    if (mbox)
+      url.push('_mbox='+urlencode(mbox));
+
+    return url.join('&');
+  };
+
   // reset quick-search form
   this.reset_qsearch = function()
   {
   // reset quick-search form
   this.reset_qsearch = function()
   {
@@ -3448,6 +3507,7 @@ function rcube_webmail()
 
     this.env.qsearch = null;
     this.env.search_request = null;
 
     this.env.qsearch = null;
     this.env.search_request = null;
+    this.env.search_id = null;
   };
 
   this.sent_successfully = function(type, msg)
   };
 
   this.sent_successfully = function(type, msg)
@@ -3542,7 +3602,7 @@ function rcube_webmail()
 
   this.insert_recipient = function(id)
   {
 
   this.insert_recipient = function(id)
   {
-    if (!this.env.contacts[id] || !this.ksearch_input)
+    if (id === null || !this.env.contacts[id] || !this.ksearch_input)
       return;
 
     // get cursor pos
       return;
 
     // get cursor pos
@@ -3559,13 +3619,13 @@ function rcube_webmail()
 
     // insert all members of a group
     if (typeof this.env.contacts[id] === 'object' && this.env.contacts[id].id) {
 
     // insert all members of a group
     if (typeof this.env.contacts[id] === 'object' && this.env.contacts[id].id) {
-      insert += this.env.contacts[id].name + ', ';
+      insert += this.env.contacts[id].name + this.env.recipients_delimiter;
       this.group2expand = $.extend({}, this.env.contacts[id]);
       this.group2expand.input = this.ksearch_input;
       this.http_request('mail/group-expand', '_source='+urlencode(this.env.contacts[id].source)+'&_gid='+urlencode(this.env.contacts[id].id), false);
     }
     else if (typeof this.env.contacts[id] === 'string') {
       this.group2expand = $.extend({}, this.env.contacts[id]);
       this.group2expand.input = this.ksearch_input;
       this.http_request('mail/group-expand', '_source='+urlencode(this.env.contacts[id].source)+'&_gid='+urlencode(this.env.contacts[id].id), false);
     }
     else if (typeof this.env.contacts[id] === 'string') {
-      insert = this.env.contacts[id] + ', ';
+      insert = this.env.contacts[id] + this.env.recipients_delimiter;
       trigger = true;
     }
 
       trigger = true;
     }
 
@@ -3602,7 +3662,7 @@ function rcube_webmail()
 
     // get string from current cursor pos to last comma
     var cpos = this.get_caret_pos(this.ksearch_input),
 
     // get string from current cursor pos to last comma
     var cpos = this.get_caret_pos(this.ksearch_input),
-      p = inp_value.lastIndexOf(',', cpos-1),
+      p = inp_value.lastIndexOf(this.env.recipients_separator, cpos-1),
       q = inp_value.substring(p+1, cpos),
       min = this.env.autocomplete_min_length,
       ac = this.ksearch_data;
       q = inp_value.substring(p+1, cpos),
       min = this.env.autocomplete_min_length,
       ac = this.ksearch_data;
@@ -3614,22 +3674,19 @@ function rcube_webmail()
     if (q == this.ksearch_value)
       return;
 
     if (q == this.ksearch_value)
       return;
 
+    this.ksearch_destroy();
+
     if (q.length && q.length < min) {
     if (q.length && q.length < min) {
-      if (!this.env.acinfo) {
-        this.env.acinfo = this.display_message(
+      if (!this.ksearch_info) {
+        this.ksearch_info = this.display_message(
           this.get_label('autocompletechars').replace('$min', min));
       }
       return;
     }
           this.get_label('autocompletechars').replace('$min', min));
       }
       return;
     }
-    else if (this.env.acinfo) {
-      this.hide_message(this.env.acinfo);
-    }
 
     var old_value = this.ksearch_value;
     this.ksearch_value = q;
 
 
     var old_value = this.ksearch_value;
     this.ksearch_value = q;
 
-    this.ksearch_destroy();
-
     // ...string is empty
     if (!q.length)
       return;
     // ...string is empty
     if (!q.length)
       return;
@@ -3671,7 +3728,9 @@ function rcube_webmail()
       return;
 
     // display search results
       return;
 
     // display search results
-    var p, ul, li, text, init, s_val = this.ksearch_value,
+    var i, len, ul, li, text, init,
+      value = this.ksearch_value,
+      data = this.ksearch_data,
       maxlen = this.env.autocomplete_max ? this.env.autocomplete_max : 15;
 
     // create results pane if not present
       maxlen = this.env.autocomplete_max ? this.env.autocomplete_max : 15;
 
     // create results pane if not present
@@ -3700,11 +3759,11 @@ function rcube_webmail()
     }
 
     // add each result line to list
     }
 
     // add each result line to list
-    if (results && results.length) {
-      for (i=0; i < results.length && maxlen > 0; i++) {
+    if (results && (len = results.length)) {
+      for (i=0; i < len && maxlen > 0; i++) {
         text = typeof results[i] === 'object' ? results[i].name : results[i];
         li = document.createElement('LI');
         text = typeof results[i] === 'object' ? results[i].name : results[i];
         li = document.createElement('LI');
-        li.innerHTML = text.replace(new RegExp('('+RegExp.escape(s_val)+')', 'ig'), '##$1%%').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/##([^%]+)%%/g, '<b>$1</b>');
+        li.innerHTML = text.replace(new RegExp('('+RegExp.escape(value)+')', 'ig'), '##$1%%').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/##([^%]+)%%/g, '<b>$1</b>');
         li.onmouseover = function(){ ref.ksearch_select(this); };
         li.onmouseup = function(){ ref.ksearch_click(this) };
         li._rcm_id = this.env.contacts.length + i;
         li.onmouseover = function(){ ref.ksearch_select(this); };
         li.onmouseup = function(){ ref.ksearch_click(this) };
         li._rcm_id = this.env.contacts.length + i;
@@ -3722,20 +3781,28 @@ function rcube_webmail()
       }
     }
 
       }
     }
 
-    if (results && results.length)
+    if (len)
       this.env.contacts = this.env.contacts.concat(results);
 
     // run next parallel search
       this.env.contacts = this.env.contacts.concat(results);
 
     // run next parallel search
-    if (maxlen > 0 && this.ksearch_data.id == reqid && this.ksearch_data.sources.length) {
-      var lock, xhr, props = this.ksearch_data, source = props.sources.shift();
-      if (source) {
+    if (data.id == reqid) {
       data.num--;
       data.num--;
-        lock = this.display_message(this.get_label('searching'), 'loading');
-        xhr = this.http_post(props.action, '_search='+urlencode(s_val)+'&_id='+reqid
-          +'&_source='+urlencode(source), lock);
-
-        this.ksearch_data.locks.push(lock);
-        this.ksearch_data.requests.push(xhr);
+      if (maxlen > 0 && data.sources.length) {
+        var lock, xhr, source = data.sources.shift();
+        if (source) {
+          lock = this.display_message(this.get_label('searching'), 'loading');
+          xhr = this.http_post(data.action, '_search='+urlencode(value)+'&_id='+reqid
+            +'&_source='+urlencode(source), lock);
+
+          this.ksearch_data.locks.push(lock);
+          this.ksearch_data.requests.push(xhr);
+        }
+      }
+      else if (!maxlen) {
+        if (!this.ksearch_msg)
+          this.ksearch_msg = this.display_message(this.get_label('autocompletemore'));
+        // abort pending searches
+        this.ksearch_abort();
       }
     }
   };
       }
     }
   };
@@ -3769,8 +3836,24 @@ function rcube_webmail()
     this.ksearch_destroy();
   };
 
     this.ksearch_destroy();
   };
 
-  // Aborts pending autocomplete requests
+  // Clears autocomplete data/requests
   this.ksearch_destroy = function()
   this.ksearch_destroy = function()
+  {
+    this.ksearch_abort();
+
+    if (this.ksearch_info)
+      this.hide_message(this.ksearch_info);
+
+    if (this.ksearch_msg)
+      this.hide_message(this.ksearch_msg);
+
+    this.ksearch_data = null;
+    this.ksearch_info = null;
+    this.ksearch_msg = null;
+  }
+
+  // Aborts pending autocomplete requests
+  this.ksearch_abort = function()
   {
     var i, len, ac = this.ksearch_data;
 
   {
     var i, len, ac = this.ksearch_data;
 
@@ -3779,9 +3862,8 @@ function rcube_webmail()
 
     for (i=0, len=ac.locks.length; i<len; i++)
       this.abort_request({request: ac.requests[i], lock: ac.locks[i]});
 
     for (i=0, len=ac.locks.length; i<len; i++)
       this.abort_request({request: ac.requests[i], lock: ac.locks[i]});
+  };
 
 
-    this.ksearch_data = null;
-  }
 
   /*********************************************************/
   /*********         address book methods          *********/
 
   /*********************************************************/
   /*********         address book methods          *********/
@@ -3823,7 +3905,7 @@ function rcube_webmail()
       }
     }
 
       }
     }
 
-    this.enable_command('compose', list.selection.length > 0);
+    this.enable_command('compose', this.env.group || list.selection.length > 0);
     this.enable_command('edit', id && writable);
     this.enable_command('delete', list.selection.length && writable);
 
     this.enable_command('edit', id && writable);
     this.enable_command('delete', list.selection.length && writable);
 
@@ -3832,7 +3914,7 @@ function rcube_webmail()
 
   this.list_contacts = function(src, group, page)
   {
 
   this.list_contacts = function(src, group, page)
   {
-    var add_url = '',
+    var folder, add_url = '',
       target = window;
 
     if (!src)
       target = window;
 
     if (!src)
@@ -3848,7 +3930,12 @@ function rcube_webmail()
     else if (group != this.env.group)
       page = this.env.current_page = 1;
 
     else if (group != this.env.group)
       page = this.env.current_page = 1;
 
-    this.select_folder((group ? 'G'+src+group : src), (this.env.group ? 'G'+this.env.source+this.env.group : this.env.source));
+    if (this.env.search_id)
+      folder = 'S'+this.env.search_id;
+    else
+      folder = group ? 'G'+src+group : src;
+
+    this.select_folder(folder);
 
     this.env.source = src;
     this.env.group = group;
 
     this.env.source = src;
     this.env.group = group;
@@ -3893,8 +3980,8 @@ function rcube_webmail()
     if (group)
       url += '&_gid='+group;
 
     if (group)
       url += '&_gid='+group;
 
-    // also send search request to get the right messages 
-    if (this.env.search_request) 
+    // also send search request to get the right messages
+    if (this.env.search_request)
       url += '&_search='+this.env.search_request;
 
     this.http_request('list', url, lock);
       url += '&_search='+this.env.search_request;
 
     this.http_request('list', url, lock);
@@ -3904,7 +3991,8 @@ function rcube_webmail()
   {
     this.contact_list.clear(true);
     this.show_contentframe(false);
   {
     this.contact_list.clear(true);
     this.show_contentframe(false);
-    this.enable_command('delete', 'compose', false);
+    this.enable_command('delete', false);
+    this.enable_command('compose', this.env.group ? true : false);
   };
 
   // load contact record
   };
 
   // load contact record
@@ -3976,9 +4064,11 @@ function rcube_webmail()
 
   this.delete_contacts = function()
   {
 
   this.delete_contacts = function()
   {
+    var selection = this.contact_list.get_selection(),
+      undelete = this.env.source && this.env.address_sources[this.env.source].undelete;
+
     // exit if no mailbox specified or if selection is empty
     // exit if no mailbox specified or if selection is empty
-    var selection = this.contact_list.get_selection();
-    if (!(selection.length || this.env.cid) || !confirm(this.get_label('deletecontactconfirm')))
+    if (!(selection.length || this.env.cid) || (!undelete && !confirm(this.get_label('deletecontactconfirm'))))
       return;
 
     var id, n, a_cids = [], qs = '';
       return;
 
     var id, n, a_cids = [], qs = '';
@@ -4005,7 +4095,10 @@ function rcube_webmail()
       qs += '&_search='+this.env.search_request;
 
     // send request to server
       qs += '&_search='+this.env.search_request;
 
     // send request to server
-    this.http_post('delete', '_cid='+urlencode(a_cids.join(','))+'&_source='+urlencode(this.env.source)+'&_from='+(this.env.action ? this.env.action : '')+qs);
+    this.http_post('delete', '_cid='+urlencode(a_cids.join(','))
+      +'&_source='+urlencode(this.env.source)
+      +'&_from='+(this.env.action ? this.env.action : '')+qs,
+      this.display_message(this.get_label('contactdeleting'), 'loading'));
 
     return true;
   };
 
     return true;
   };
@@ -4015,7 +4108,7 @@ function rcube_webmail()
   {
     var c, row, list = this.contact_list;
 
   {
     var c, row, list = this.contact_list;
 
-    cid = String(cid).replace(this.identifier_expr, '_');
+    cid = this.html_identifier(cid);
 
     // when in searching mode, concat cid with the source name
     if (!list.rows[cid]) {
 
     // when in searching mode, concat cid with the source name
     if (!list.rows[cid]) {
@@ -4031,7 +4124,7 @@ function rcube_webmail()
 
       // cid change
       if (newcid) {
 
       // cid change
       if (newcid) {
-        newcid = String(newcid).replace(this.identifier_expr, '_');
+        newcid = this.html_identifier(newcid);
         row.id = 'rcmrow' + newcid;
         list.remove_row(cid);
         list.init_row(row);
         row.id = 'rcmrow' + newcid;
         list.remove_row(cid);
         list.init_row(row);
@@ -4044,31 +4137,29 @@ function rcube_webmail()
   // add row to contacts list
   this.add_contact_row = function(cid, cols, select)
   {
   // add row to contacts list
   this.add_contact_row = function(cid, cols, select)
   {
-    if (!this.gui_objects.contactslist || !this.gui_objects.contactslist.tBodies[0])
+    if (!this.gui_objects.contactslist)
       return false;
 
       return false;
 
-    var tbody = this.gui_objects.contactslist.tBodies[0],
-      rowcount = tbody.rows.length,
-      even = rowcount%2,
+    var c, list = this.contact_list,
       row = document.createElement('tr');
 
       row = document.createElement('tr');
 
-    row.id = 'rcmrow'+String(cid).replace(this.identifier_expr, '_');
-    row.className = 'contact '+(even ? 'even' : 'odd');
+    row.id = 'rcmrow'+this.html_identifier(cid);
+    row.className = 'contact';
 
 
-    if (this.contact_list.in_selection(cid))
+    if (list.in_selection(cid))
       row.className += ' selected';
 
     // add each submitted col
       row.className += ' selected';
 
     // add each submitted col
-    for (var c in cols) {
+    for (c in cols) {
       col = document.createElement('td');
       col.className = String(c).toLowerCase();
       col.innerHTML = cols[c];
       row.appendChild(col);
     }
 
       col = document.createElement('td');
       col.className = String(c).toLowerCase();
       col.innerHTML = cols[c];
       row.appendChild(col);
     }
 
-    this.contact_list.insert_row(row);
+    list.insert_row(row);
 
 
-    this.enable_command('export', (this.contact_list.rowcount > 0));
+    this.enable_command('export', list.rowcount > 0);
   };
 
   this.init_contact_form = function()
   };
 
   this.init_contact_form = function()
@@ -4090,24 +4181,27 @@ function rcube_webmail()
       this.selectedIndex = 0;
     });
 
       this.selectedIndex = 0;
     });
 
+    // enable date pickers on date fields
+    if ($.datepicker && this.env.date_format) {
+      $.datepicker.setDefaults({
+        dateFormat: this.env.date_format,
+        changeMonth: true,
+        changeYear: true,
+        yearRange: '-100:+10',
+        showOtherMonths: true,
+        selectOtherMonths: true,
+        monthNamesShort: this.env.month_names,
+        onSelect: function(dateText) { $(this).focus().val(dateText) }
+      });
+      $('input.datepicker').datepicker();
+    }
+
     $("input[type='text']:visible").first().focus();
   };
 
   this.group_create = function()
   {
     $("input[type='text']:visible").first().focus();
   };
 
   this.group_create = function()
   {
-    if (!this.gui_objects.folderlist)
-      return;
-
-    if (!this.name_input) {
-      this.name_input = $('<input>').attr('type', 'text');
-      this.name_input.bind('keydown', function(e){ return rcmail.add_input_keydown(e); });
-      this.name_input_li = $('<li>').addClass('contactgroup').append(this.name_input);
-
-      var li = this.get_folder_li(this.env.source)
-      this.name_input_li.insertAfter(li);
-    }
-
-    this.name_input.select().focus();
+    this.add_input_row('contactgroup');
   };
 
   this.group_rename = function()
   };
 
   this.group_rename = function()
@@ -4153,18 +4247,40 @@ function rcube_webmail()
     this.list_contacts(prop.source, 0);
   };
 
     this.list_contacts(prop.source, 0);
   };
 
+  // @TODO: maybe it would be better to use popup instead of inserting input to the list?
+  this.add_input_row = function(type)
+  {
+    if (!this.gui_objects.folderlist)
+      return;
+
+    if (!this.name_input) {
+      this.name_input = $('<input>').attr('type', 'text').data('tt', type);
+      this.name_input.bind('keydown', function(e){ return rcmail.add_input_keydown(e); });
+      this.name_input_li = $('<li>').addClass(type).append(this.name_input);
+
+      var li = type == 'contactsearch' ? $('li:last', this.gui_objects.folderlist) : this.get_folder_li(this.env.source);
+      this.name_input_li.insertAfter(li);
+    }
+
+    this.name_input.select().focus();
+  };
+
   // handler for keyboard events on the input field
   this.add_input_keydown = function(e)
   {
   // handler for keyboard events on the input field
   this.add_input_keydown = function(e)
   {
-    var key = rcube_event.get_keycode(e);
+    var key = rcube_event.get_keycode(e),
+      input = $(e.target), itype = input.data('tt');
 
     // enter
     if (key == 13) {
 
     // enter
     if (key == 13) {
-      var newname = this.name_input.val();
+      var newname = input.val();
 
       if (newname) {
         var lock = this.set_busy(true, 'loading');
 
       if (newname) {
         var lock = this.set_busy(true, 'loading');
-        if (this.env.group_renaming)
+
+        if (itype == 'contactsearch')
+          this.http_post('search-create', '_search='+urlencode(this.env.search_request)+'&_name='+urlencode(newname), lock);
+        else if (this.env.group_renaming)
           this.http_post('group-rename', '_source='+urlencode(this.env.source)+'&_gid='+urlencode(this.env.group)+'&_name='+urlencode(newname), lock);
         else
           this.http_post('group-create', '_source='+urlencode(this.env.source)+'&_name='+urlencode(newname), lock);
           this.http_post('group-rename', '_source='+urlencode(this.env.source)+'&_gid='+urlencode(this.env.group)+'&_name='+urlencode(newname), lock);
         else
           this.http_post('group-create', '_source='+urlencode(this.env.source)+'&_name='+urlencode(newname), lock);
@@ -4209,7 +4325,7 @@ function rcube_webmail()
         .attr('rel', prop.source+':'+prop.id)
         .click(function() { return rcmail.command('listgroup', prop, this); })
         .html(prop.name),
         .attr('rel', prop.source+':'+prop.id)
         .click(function() { return rcmail.command('listgroup', prop, this); })
         .html(prop.name),
-      li = $('<li>').attr({id: 'rcmli'+key.replace(this.identifier_expr, '_'), 'class': 'contactgroup'})
+      li = $('<li>').attr({id: 'rcmli'+this.html_identifier(key), 'class': 'contactgroup'})
         .append(link);
 
     this.env.contactfolders[key] = this.env.contactgroups[key] = prop;
         .append(link);
 
     this.env.contactfolders[key] = this.env.contactgroups[key] = prop;
@@ -4232,7 +4348,7 @@ function rcube_webmail()
       var newkey = 'G'+prop.source+prop.newid,
         newprop = $.extend({}, prop);;
 
       var newkey = 'G'+prop.source+prop.newid,
         newprop = $.extend({}, prop);;
 
-      li.id = String('rcmli'+newkey).replace(this.identifier_expr, '_');
+      li.id = 'rcmli' + this.html_identifier(newkey);
       this.env.contactfolders[newkey] = this.env.contactfolders[key];
       this.env.contactfolders[newkey].id = prop.newid;
       this.env.group = prop.newid;
       this.env.contactfolders[newkey] = this.env.contactfolders[key];
       this.env.contactfolders[newkey].id = prop.newid;
       this.env.group = prop.newid;
@@ -4264,7 +4380,7 @@ function rcube_webmail()
   {
     var row, name = prop.name.toUpperCase(),
       sibling = this.get_folder_li(prop.source),
   {
     var row, name = prop.name.toUpperCase(),
       sibling = this.get_folder_li(prop.source),
-      prefix = 'rcmliG'+(prop.source).replace(this.identifier_expr, '_');
+      prefix = 'rcmliG' + this.html_identifier(prop.source);
 
     // When renaming groups, we need to remove it from DOM and insert it in the proper place
     if (reloc) {
 
     // When renaming groups, we need to remove it from DOM and insert it in the proper place
     if (reloc) {
@@ -4335,6 +4451,9 @@ function rcube_webmail()
             .appendTo(cell);
 
           this.init_edit_field(col, input);
             .appendTo(cell);
 
           this.init_edit_field(col, input);
+
+          if (colprop.type == 'date' && $.datepicker)
+            input.datepicker();
         }
         else if (colprop.type == 'composite') {
           var childcol, cp, first, templ, cols = [], suffices = [];
         }
         else if (colprop.type == 'composite') {
           var childcol, cp, first, templ, cols = [], suffices = [];
@@ -4480,11 +4599,106 @@ function rcube_webmail()
   // unselect directory/group
   this.unselect_directory = function()
   {
   // unselect directory/group
   this.unselect_directory = function()
   {
-    if (this.env.address_sources.length > 1 || this.env.group != '') {
-      this.select_folder('', (this.env.group ? 'G'+this.env.source+this.env.group : this.env.source));
-      this.env.group = '';
-      this.env.source = '';
+    this.select_folder('');
+    this.enable_command('search-delete', false);
+  };
+
+  // callback for creating a new saved search record
+  this.insert_saved_search = function(name, id)
+  {
+    this.reset_add_input();
+
+    var key = 'S'+id,
+      link = $('<a>').attr('href', '#')
+        .attr('rel', id)
+        .click(function() { return rcmail.command('listsearch', id, this); })
+        .html(name),
+      li = $('<li>').attr({id: 'rcmli' + this.html_identifier(key), 'class': 'contactsearch'})
+        .append(link),
+      prop = {name:name, id:id, li:li[0]};
+
+    this.add_saved_search_row(prop, li);
+    this.select_folder('S'+id);
+    this.enable_command('search-delete', true);
+    this.env.search_id = id;
+
+    this.triggerEvent('abook_search_insert', prop);
+  };
+
+  // add saved search row to the list, with sorting
+  this.add_saved_search_row = function(prop, li, reloc)
+  {
+    var row, sibling, name = prop.name.toUpperCase();
+
+    // When renaming groups, we need to remove it from DOM and insert it in the proper place
+    if (reloc) {
+      row = li.clone(true);
+      li.remove();
     }
     }
+    else
+      row = li;
+
+    $('li[class~="contactsearch"]', this.gui_objects.folderlist).each(function(i, elem) {
+      if (!sibling)
+        sibling = this.previousSibling;
+
+      if (name >= $(this).text().toUpperCase())
+        sibling = elem;
+      else
+        return false;
+    });
+
+    if (sibling)
+      row.insertAfter(sibling);
+    else
+      row.appendTo(this.gui_objects.folderlist);
+  };
+
+  // creates an input for saved search name
+  this.search_create = function()
+  {
+    this.add_input_row('contactsearch');
+  };
+
+  this.search_delete = function()
+  {
+    if (this.env.search_request) {
+      var lock = this.set_busy(true, 'savedsearchdeleting');
+      this.http_post('search-delete', '_sid='+urlencode(this.env.search_id), lock);
+    }
+  };
+
+  // callback from server upon search-delete command
+  this.remove_search_item = function(id)
+  {
+    var li, key = 'S'+id;
+    if ((li = this.get_folder_li(key))) {
+      this.triggerEvent('search_delete', { id:id, li:li });
+
+      li.parentNode.removeChild(li);
+    }
+
+    this.env.search_id = null;
+    this.env.search_request = null;
+    this.list_contacts_clear();
+    this.reset_qsearch();
+    this.enable_command('search-delete', 'search-create', false);
+  };
+
+  this.listsearch = function(id)
+  {
+    var folder, lock = this.set_busy(true, 'searching');
+
+    if (this.contact_list) {
+      this.list_contacts_clear();
+    }
+
+    this.reset_qsearch();
+    this.select_folder('S'+id);
+
+    // reset vars
+    this.env.current_page = 1;
+    this.http_request('search', '_sid='+urlencode(id), lock);
   };
 
 
   };
 
 
@@ -4970,17 +5184,18 @@ function rcube_webmail()
         init_button(cmd, this.buttons[cmd][i]);
       }
     }
         init_button(cmd, this.buttons[cmd][i]);
       }
     }
+
+    // set active task button
+    this.set_button(this.task, 'sel');
   };
 
   // set button to a specific state
   this.set_button = function(command, state)
   {
   };
 
   // set button to a specific state
   this.set_button = function(command, state)
   {
-    var button, obj, a_buttons = this.buttons[command];
+    var n, button, obj, a_buttons = this.buttons[command],
+      len = a_buttons ? a_buttons.length : 0;
 
 
-    if (!a_buttons || !a_buttons.length)
-      return false;
-
-    for (var n=0; n<a_buttons.length; n++) {
+    for (n=0; n<len; n++) {
       button = a_buttons[n];
       obj = document.getElementById(button.id);
 
       button = a_buttons[n];
       obj = document.getElementById(button.id);
 
@@ -5015,15 +5230,14 @@ function rcube_webmail()
   // display a specific alttext
   this.set_alttext = function(command, label)
   {
   // display a specific alttext
   this.set_alttext = function(command, label)
   {
-    if (!this.buttons[command] || !this.buttons[command].length)
-      return;
+    var n, button, obj, link, a_buttons = this.buttons[command],
+      len = a_buttons ? a_buttons.length : 0;
 
 
-    var button, obj, link;
-    for (var n=0; n<this.buttons[command].length; n++) {
-      button = this.buttons[command][n];
+    for (n=0; n<len; n++) {
+      button = a_buttons[n];
       obj = document.getElementById(button.id);
 
       obj = document.getElementById(button.id);
 
-      if (button.type=='image' && obj) {
+      if (button.type == 'image' && obj) {
         obj.setAttribute('alt', this.get_label(label));
         if ((link = obj.parentNode) && link.tagName.toLowerCase() == 'a')
           link.setAttribute('title', this.get_label(label));
         obj.setAttribute('alt', this.get_label(label));
         if ((link = obj.parentNode) && link.tagName.toLowerCase() == 'a')
           link.setAttribute('title', this.get_label(label));
@@ -5036,20 +5250,18 @@ function rcube_webmail()
   // mouse over button
   this.button_over = function(command, id)
   {
   // mouse over button
   this.button_over = function(command, id)
   {
-    var button, elm, a_buttons = this.buttons[command];
-
-    if (!a_buttons || !a_buttons.length)
-      return false;
+    var n, button, obj, a_buttons = this.buttons[command],
+      len = a_buttons ? a_buttons.length : 0;
 
 
-    for (var n=0; n<a_buttons.length; n++) {
+    for (n=0; n<len; n++) {
       button = a_buttons[n];
       if (button.id == id && button.status == 'act') {
       button = a_buttons[n];
       if (button.id == id && button.status == 'act') {
-        elm = document.getElementById(button.id);
-        if (elm && button.over) {
+        obj = document.getElementById(button.id);
+        if (obj && button.over) {
           if (button.type == 'image')
           if (button.type == 'image')
-            elm.src = button.over;
+            obj.src = button.over;
           else
           else
-            elm.className = button.over;
+            obj.className = button.over;
         }
       }
     }
         }
       }
     }
@@ -5058,20 +5270,18 @@ function rcube_webmail()
   // mouse down on button
   this.button_sel = function(command, id)
   {
   // mouse down on button
   this.button_sel = function(command, id)
   {
-    var button, elm, a_buttons = this.buttons[command];
-
-    if (!a_buttons || !a_buttons.length)
-      return;
+    var n, button, obj, a_buttons = this.buttons[command],
+      len = a_buttons ? a_buttons.length : 0;
 
 
-    for (var n=0; n<a_buttons.length; n++) {
+    for (n=0; n<len; n++) {
       button = a_buttons[n];
       if (button.id == id && button.status == 'act') {
       button = a_buttons[n];
       if (button.id == id && button.status == 'act') {
-        elm = document.getElementById(button.id);
-        if (elm && button.sel) {
+        obj = document.getElementById(button.id);
+        if (obj && button.sel) {
           if (button.type == 'image')
           if (button.type == 'image')
-            elm.src = button.sel;
+            obj.src = button.sel;
           else
           else
-            elm.className = button.sel;
+            obj.className = button.sel;
         }
         this.buttons_sel[id] = command;
       }
         }
         this.buttons_sel[id] = command;
       }
@@ -5081,26 +5291,23 @@ function rcube_webmail()
   // mouse out of button
   this.button_out = function(command, id)
   {
   // mouse out of button
   this.button_out = function(command, id)
   {
-    var button, elm, a_buttons = this.buttons[command];
-
-    if (!a_buttons || !a_buttons.length)
-      return;
+    var n, button, obj, a_buttons = this.buttons[command],
+      len = a_buttons ? a_buttons.length : 0;
 
 
-    for (var n=0; n<a_buttons.length; n++) {
+    for (n=0; n<len; n++) {
       button = a_buttons[n];
       if (button.id == id && button.status == 'act') {
       button = a_buttons[n];
       if (button.id == id && button.status == 'act') {
-        elm = document.getElementById(button.id);
-        if (elm && button.act) {
+        obj = document.getElementById(button.id);
+        if (obj && button.act) {
           if (button.type == 'image')
           if (button.type == 'image')
-            elm.src = button.act;
+            obj.src = button.act;
           else
           else
-            elm.className = button.act;
+            obj.className = button.act;
         }
       }
     }
   };
 
         }
       }
     }
   };
 
-
   this.focus_textfield = function(elem)
   {
     elem._hasfocus = true;
   this.focus_textfield = function(elem)
   {
     elem._hasfocus = true;
@@ -5134,14 +5341,14 @@ function rcube_webmail()
     if (!this.gui_objects.message) {
       // save message in order to display after page loaded
       if (type != 'loading')
     if (!this.gui_objects.message) {
       // save message in order to display after page loaded
       if (type != 'loading')
-        this.pending_message = new Array(msg, type, timeout);
+        this.pending_message = [msg, type, timeout];
       return false;
     }
 
     type = type ? type : 'notice';
 
     var ref = this,
       return false;
     }
 
     type = type ? type : 'notice';
 
     var ref = this,
-      key = String(msg).replace(this.identifier_expr, '_'),
+      key = this.html_identifier(msg),
       date = new Date(),
       id = type + date.getTime();
 
       date = new Date(),
       id = type + date.getTime();
 
@@ -5234,31 +5441,31 @@ function rcube_webmail()
   };
 
   // mark a mailbox as selected and set environment variable
   };
 
   // mark a mailbox as selected and set environment variable
-  this.select_folder = function(name, old, prefix)
+  this.select_folder = function(name, prefix, encode)
   {
     if (this.gui_objects.folderlist) {
       var current_li, target_li;
 
   {
     if (this.gui_objects.folderlist) {
       var current_li, target_li;
 
-      if ((current_li = this.get_folder_li(old, prefix))) {
-        $(current_li).removeClass('selected').addClass('unfocused');
+      if ((current_li = $('li.selected', this.gui_objects.folderlist))) {
+        current_li.removeClass('selected').addClass('unfocused');
       }
       }
-      if ((target_li = this.get_folder_li(name, prefix))) {
+      if ((target_li = this.get_folder_li(name, prefix, encode))) {
         $(target_li).removeClass('unfocused').addClass('selected');
       }
 
       // trigger event hook
         $(target_li).removeClass('unfocused').addClass('selected');
       }
 
       // trigger event hook
-      this.triggerEvent('selectfolder', { folder:name, old:old, prefix:prefix });
+      this.triggerEvent('selectfolder', { folder:name, prefix:prefix });
     }
   };
 
   // helper method to find a folder list item
     }
   };
 
   // helper method to find a folder list item
-  this.get_folder_li = function(name, prefix)
+  this.get_folder_li = function(name, prefix, encode)
   {
     if (!prefix)
       prefix = 'rcmli';
 
     if (this.gui_objects.folderlist) {
   {
     if (!prefix)
       prefix = 'rcmli';
 
     if (this.gui_objects.folderlist) {
-      name = String(name).replace(this.identifier_expr, '_');
+      name = this.html_identifier(name, encode);
       return document.getElementById(prefix+name);
     }
 
       return document.getElementById(prefix+name);
     }
 
@@ -5327,8 +5534,12 @@ function rcube_webmail()
   };
 
   // replace content of row count display
   };
 
   // replace content of row count display
-  this.set_rowcount = function(text)
+  this.set_rowcount = function(text, mbox)
   {
   {
+    // #1487752
+    if (mbox && mbox != this.env.mailbox)
+      return false;
+
     $(this.gui_objects.countdisplay).html(text);
 
     // update page navigation buttons
     $(this.gui_objects.countdisplay).html(text);
 
     // update page navigation buttons
@@ -5368,7 +5579,7 @@ function rcube_webmail()
   {
     var reg, link, text_obj, item, mycount, childcount, div;
 
   {
     var reg, link, text_obj, item, mycount, childcount, div;
 
-    if (item = this.get_folder_li(mbox)) {
+    if (item = this.get_folder_li(mbox, '', true)) {
       mycount = this.env.unread_counts[mbox] ? this.env.unread_counts[mbox] : 0;
       link = $(item).children('a').eq(0);
       text_obj = link.children('span.unreadcount');
       mycount = this.env.unread_counts[mbox] ? this.env.unread_counts[mbox] : 0;
       link = $(item).children('a').eq(0);
       text_obj = link.children('span.unreadcount');
@@ -5380,7 +5591,7 @@ function rcube_webmail()
       if ((div = item.getElementsByTagName('div')[0]) &&
           div.className.match(/collapsed/)) {
         // add children's counters
       if ((div = item.getElementsByTagName('div')[0]) &&
           div.className.match(/collapsed/)) {
         // add children's counters
-        for (var k in this.env.unread_counts) 
+        for (var k in this.env.unread_counts)
           if (k.indexOf(mbox + this.env.delimiter) == 0)
             childcount += this.env.unread_counts[k];
       }
           if (k.indexOf(mbox + this.env.delimiter) == 0)
             childcount += this.env.unread_counts[k];
       }
@@ -5421,16 +5632,12 @@ function rcube_webmail()
 
   this.toggle_prefer_html = function(checkbox)
   {
 
   this.toggle_prefer_html = function(checkbox)
   {
-    var elem;
-    if (elem = document.getElementById('rcmfd_addrbook_show_images'))
-      elem.disabled = !checkbox.checked;
+    $('#rcmfd_show_images').prop('disabled', !checkbox.checked).val(0);
   };
 
   this.toggle_preview_pane = function(checkbox)
   {
   };
 
   this.toggle_preview_pane = function(checkbox)
   {
-    var elem;
-    if (elem = document.getElementById('rcmfd_preview_pane_mark_read'))
-      elem.disabled = !checkbox.checked;
+    $('#rcmfd_preview_pane_mark_read').prop('disabled', !checkbox.checked);
   };
 
   // display fetched raw headers
   };
 
   // display fetched raw headers
@@ -5546,14 +5753,17 @@ function rcube_webmail()
 
     $.ajax({ type: 'POST', url: url, data: htmlText, contentType: 'application/octet-stream',
       error: function(o, status, err) { rcmail.http_error(o, status, err, lock); },
 
     $.ajax({ type: 'POST', url: url, data: htmlText, contentType: 'application/octet-stream',
       error: function(o, status, err) { rcmail.http_error(o, status, err, lock); },
-      success: function(data) { rcmail.set_busy(false, null, lock); $(document.getElementById(id)).val(data); rcmail.log(data); }
+      success: function(data) { rcmail.set_busy(false, null, lock); $('#'+id).val(data); rcmail.log(data); }
     });
   };
 
     });
   };
 
-  this.plain2html = function(plainText, id)
+  this.plain2html = function(plain, id)
   {
     var lock = this.set_busy(true, 'converting');
   {
     var lock = this.set_busy(true, 'converting');
-    $(document.getElementById(id)).val('<pre>'+plainText+'</pre>');
+
+    plain = plain.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
+    $('#'+id).val(plain ? '<pre>'+plain+'</pre>' : '');
+
     this.set_busy(false, null, lock);
   };
 
     this.set_busy(false, null, lock);
   };
 
@@ -5580,7 +5790,7 @@ function rcube_webmail()
     var base = this.env.comm_path;
 
     // overwrite task name
     var base = this.env.comm_path;
 
     // overwrite task name
-    if (query._action.match(/([a-z]+)\/([a-z-_.]+)/)) {
+    if (query._action.match(/([a-z]+)\/([a-z0-9-_.]+)/)) {
       query._action = RegExp.$2;
       base = base.replace(/\_task=[a-z]+/, '_task='+RegExp.$1);
     }
       query._action = RegExp.$2;
       base = base.replace(/\_task=[a-z]+/, '_task='+RegExp.$1);
     }
@@ -5794,6 +6004,8 @@ function rcube_webmail()
           this.enable_command('export', (this.contact_list && this.contact_list.rowcount > 0));
 
           if (response.action == 'list' || response.action == 'search') {
           this.enable_command('export', (this.contact_list && this.contact_list.rowcount > 0));
 
           if (response.action == 'list' || response.action == 'search') {
+            this.enable_command('search-create', this.env.source == '');
+            this.enable_command('search-delete', this.env.search_id);
             this.update_group_commands();
             this.triggerEvent('listupdate', { folder:this.env.source, rowcount:this.contact_list.rowcount });
           }
             this.update_group_commands();
             this.triggerEvent('listupdate', { folder:this.env.source, rowcount:this.contact_list.rowcount });
           }
@@ -6008,6 +6220,23 @@ rcube_webmail.long_subject_title = function(elem, indent)
   }
 };
 
   }
 };
 
+rcube_webmail.long_subject_title_ie = function(elem, indent)
+{
+  if (!elem.title) {
+    var $elem = $(elem),
+      txt = $.trim($elem.text()),
+      tmp = $('<span>').text(txt)
+        .css({'position': 'absolute', 'float': 'left', 'visibility': 'hidden',
+          'font-size': $elem.css('font-size'), 'font-weight': $elem.css('font-weight')})
+        .appendTo($('body')),
+      w = tmp.width();
+
+    tmp.remove();
+    if (w + indent * 15 > $elem.width())
+      elem.title = txt;
+  }
+};
+
 // copy event engine prototype
 rcube_webmail.prototype.addEventListener = rcube_event_engine.prototype.addEventListener;
 rcube_webmail.prototype.removeEventListener = rcube_event_engine.prototype.removeEventListener;
 // copy event engine prototype
 rcube_webmail.prototype.addEventListener = rcube_event_engine.prototype.addEventListener;
 rcube_webmail.prototype.removeEventListener = rcube_event_engine.prototype.removeEventListener;
index a9b6f53addf81b5081fe2a11775a8c94066671aa..7d1f173396dddddfc6cdb60f3c2e5ae52c768e5c 100644 (file)
@@ -1,25 +1,28 @@
 var CONTROL_KEY=1,SHIFT_KEY=2,CONTROL_SHIFT_KEY=3;
 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?!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.ns=this.ver<5&&this.name=="Netscape"||this.ver>=5&&this.vendor.indexOf("Netscape")>=0;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.mz=this.dom&&!this.ie&&!this.ns&&!this.chrome&&!this.safari&&this.agent.indexOf("Mozilla")>=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 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+=
+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=(""+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=0<=this.platform.indexOf("win");this.mac=0<=this.platform.indexOf("mac");this.linux=0<=this.platform.indexOf("linux");this.unix=0<=this.platform.indexOf("unix");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&&0<this.appver.indexOf("MSIE 5");this.ie8=this.dom&&0<this.appver.indexOf("MSIE 8");this.ie7=this.dom&&0<this.appver.indexOf("MSIE 7");this.ie6=this.dom&&
+!this.ie8&&!this.ie7&&0<this.appver.indexOf("MSIE 6");this.ns=5>this.ver&&"Netscape"==this.name||5<=this.ver&&0<=this.vendor.indexOf("Netscape");this.chrome=0<this.agent_lc.indexOf("chrome");this.safari=!this.chrome&&(0<this.agent_lc.indexOf("safari")||0<this.agent_lc.indexOf("applewebkit"));this.mz=this.dom&&!this.ie&&!this.ns&&!this.chrome&&!this.safari&&0<=this.agent.indexOf("Mozilla");this.konq=0<this.agent_lc.indexOf("konqueror");this.iphone=this.safari&&0<this.agent_lc.indexOf("iphone");this.ipad=
+this.safari&&0<this.agent_lc.indexOf("ipad");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||0<this.agent.indexOf("Camino"))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&&6<=this.vendver||this.ie&&
+this.mac&&5<=this.vendver||this.ie&&this.win&&5.5<=this.vendver||this.safari;this.opacity=this.mz||this.ie&&5.5<=this.vendver&&!this.opera||this.safari&&100<=this.vendver;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");document.documentElement&&(document.documentElement.className+=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");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)&&a.button!==void 0?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,
+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)&&void 0!==a.button?a.button:a&&a.which?a.which:0},get_modifier:function(a){var b=0,a=a||window.event;bw.mac&&a?b+=(a.metaKey&&CONTROL_KEY)+(a.shiftKey&&SHIFT_KEY):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;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(b){return a.object[a.method](b)});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={}}
 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){c===void 0&&(c=window);for(var d,e=0;this._events&&this._events[a]&&e<this._events[a].length;e++)if((d=this._events[a][e])&&d.func==b&&d.obj==c)this._events[a][e]=null},triggerEvent:function(a,b){var c,d;if(b===void 0)b=this;else if(typeof b==="object")b.event=a;if(this._events&&
-this._events[a]&&!this._event_exec){this._event_exec=!0;for(var e=0;e<this._events[a].length;e++)if(d=this._events[a][e])if(typeof d.func==="function"?c=d.func.call?d.func.call(d.obj,b):d.func(b):typeof d.obj[d.func]==="function"&&(c=d.obj[d.func](b)),c!==void 0&&!c)break;if(c&&c.event)try{delete c.event}catch(g){$(c).removeAttr("event")}}this._event_exec=!1;if(b.event)try{delete b.event}catch(h){$(b).removeAttr("event")}return c}};
-function rcube_layer(a,b){this.name=a;this.create=function(a){var b=a.x?a.x:0,e=a.y?a.y:0,g=a.width,h=a.height,i=a.zindex,j=a.vis,a=a.parent,f=document.createElement("DIV");f.id=this.name;f.style.position="absolute";f.style.visibility=j?j==2?"inherit":"visible":"hidden";f.style.left=b+"px";f.style.top=e+"px";if(g)f.style.width=g.toString().match(/\%$/)?g:g+"px";if(h)f.style.height=h.toString().match(/\%$/)?h:h+"px";if(i)f.style.zIndex=i;a?a.appendChild(f):document.body.appendChild(f);this.elm=f};
-b!=null?(this.create(b),this.name=this.elm.id):this.elm=document.getElementById(a);if(!this.elm)return!1;this.css=this.elm.style;this.event=this.elm;this.width=this.elm.offsetWidth;this.height=this.elm.offsetHeight;this.x=parseInt(this.elm.offsetLeft);this.y=parseInt(this.elm.offsetTop);this.visible=this.css.visibility=="visible"||this.css.visibility=="show"||this.css.visibility=="inherit"?!0:!1;this.move=function(a,b){this.x=a;this.y=b;this.css.left=Math.round(this.x)+"px";this.css.top=Math.round(this.y)+
-"px"};this.resize=function(a,b){this.css.width=a+"px";this.css.height=b+"px";this.width=a;this.height=b};this.show=function(a){a==1?(this.css.visibility="visible",this.visible=!0):a==2?(this.css.visibility="inherit",this.visible=!0):(this.css.visibility="hidden",this.visible=!1)};this.write=function(a){this.elm.innerHTML=a}}
+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){void 0===c&&(c=window);for(var d,e=0;this._events&&this._events[a]&&e<this._events[a].length;e++)if((d=this._events[a][e])&&d.func==b&&d.obj==c)this._events[a][e]=null},triggerEvent:function(a,b){var c,d;if(void 0===b)b=this;else if("object"===typeof b)b.event=a;if(this._events&&
+this._events[a]&&!this._event_exec){this._event_exec=!0;for(var e=0;e<this._events[a].length;e++)if(d=this._events[a][e])if("function"===typeof d.func?c=d.func.call?d.func.call(d.obj,b):d.func(b):"function"===typeof d.obj[d.func]&&(c=d.obj[d.func](b)),void 0!==c&&!c)break;if(c&&c.event)try{delete c.event}catch(f){$(c).removeAttr("event")}}this._event_exec=!1;if(b.event)try{delete b.event}catch(h){$(b).removeAttr("event")}return c}};
+function rcube_layer(a,b){this.name=a;this.create=function(a){var b=a.x?a.x:0,e=a.y?a.y:0,f=a.width,h=a.height,i=a.zindex,g=a.vis,a=a.parent,j=document.createElement("DIV");j.id=this.name;j.style.position="absolute";j.style.visibility=g?2==g?"inherit":"visible":"hidden";j.style.left=b+"px";j.style.top=e+"px";if(f)j.style.width=f.toString().match(/\%$/)?f:f+"px";if(h)j.style.height=h.toString().match(/\%$/)?h:h+"px";if(i)j.style.zIndex=i;a?a.appendChild(j):document.body.appendChild(j);this.elm=j};
+null!=b?(this.create(b),this.name=this.elm.id):this.elm=document.getElementById(a);if(!this.elm)return!1;this.css=this.elm.style;this.event=this.elm;this.width=this.elm.offsetWidth;this.height=this.elm.offsetHeight;this.x=parseInt(this.elm.offsetLeft);this.y=parseInt(this.elm.offsetTop);this.visible="visible"==this.css.visibility||"show"==this.css.visibility||"inherit"==this.css.visibility?!0:!1;this.move=function(a,b){this.x=a;this.y=b;this.css.left=Math.round(this.x)+"px";this.css.top=Math.round(this.y)+
+"px"};this.resize=function(a,b){this.css.width=a+"px";this.css.height=b+"px";this.width=a;this.height=b};this.show=function(a){1==a?(this.css.visibility="visible",this.visible=!0):2==a?(this.css.visibility="inherit",this.visible=!0):(this.css.visibility="hidden",this.visible=!1)};this.write=function(a){this.elm.innerHTML=a}}
 function rcube_check_email(a,b){return a&&window.RegExp?(b?RegExp("(^|<|[,;s\n])((([^\\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)+([^\\x00-\\x40\\x5b-\\x60\\x7b-\\x7f]{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)))($|>|[,;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)+([^\\x00-\\x40\\x5b-\\x60\\x7b-\\x7f]{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)))$",
 function rcube_check_email(a,b){return a&&window.RegExp?(b?RegExp("(^|<|[,;s\n])((([^\\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)+([^\\x00-\\x40\\x5b-\\x60\\x7b-\\x7f]{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)))($|>|[,;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)+([^\\x00-\\x40\\x5b-\\x60\\x7b-\\x7f]{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)?!0:!1:!1}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)}
+"i")).test(a)?!0:!1:!1}function rcube_clone_object(a){var b={},c;for(c in a)b[c]=a[c]&&"object"===typeof a[c]?clone_object(a[c]):a[c];return b}function urlencode(a){return window.encodeURIComponent?encodeURIComponent(a).replace("*","%2A"):escape(a).replace("+","%2B").replace("*","%2A").replace("/","%2F").replace("@","%40")}
 function rcube_find_object(a,b){var c,d;b||(b=document);if(b.getElementsByName&&(c=b.getElementsByName(a)))d=c[0];!d&&b.getElementById&&(d=b.getElementById(a));!d&&b.all&&(d=b.all[a]);!d&&b.images.length&&(d=b.images[a]);if(!d&&b.forms.length)for(c=0;c<b.forms.length;c++)b.forms[c].name==a?d=b.forms[c]:b.forms[c].elements[a]&&(d=b.forms[c].elements[a]);if(!d&&b.layers){b.layers[a]&&(d=b.layers[a]);for(c=0;!d&&c<b.layers.length;c++)d=rcube_find_object(a,b.layers[c].document)}return d}
 function rcube_find_object(a,b){var c,d;b||(b=document);if(b.getElementsByName&&(c=b.getElementsByName(a)))d=c[0];!d&&b.getElementById&&(d=b.getElementById(a));!d&&b.all&&(d=b.all[a]);!d&&b.images.length&&(d=b.images[a]);if(!d&&b.forms.length)for(c=0;c<b.forms.length;c++)b.forms[c].name==a?d=b.forms[c]:b.forms[c].elements[a]&&(d=b.forms[c].elements[a]);if(!d&&b.layers){b.layers[a]&&(d=b.layers[a]);for(c=0;!d&&c<b.layers.length;c++)d=rcube_find_object(a,b.layers[c].document)}return d}
-function rcube_mouse_is_over(a,b){var c=rcube_event.get_mouse_pos(a),d=$(b).offset();return c.x>=d.left&&c.x<d.left+b.offsetWidth&&c.y>=d.top&&c.y<d.top+b.offsetHeight}function setCookie(a,b,c,d,e,g){a=a+"="+escape(b)+(c?"; expires="+c.toGMTString():"")+(d?"; path="+d:"")+(e?"; domain="+e:"")+(g?"; secure":"");document.cookie=a}
-function getCookie(a){var b=document.cookie;a+="=";var c=b.indexOf("; "+a);if(c==-1){if(c=b.indexOf(a),c!=0)return null}else c+=2;var d=b.indexOf(";",c);if(d==-1)d=b.length;return unescape(b.substring(c+a.length,d))}roundcube_browser.prototype.set_cookie=setCookie;roundcube_browser.prototype.get_cookie=getCookie;
-function rcube_console(){this.log=function(a){var b=rcube_find_object("dbgconsole");if(b)a+=a.charAt(a.length-1)=="\n"?"--------------------------------------\n":"\n--------------------------------------\n",bw.konq?(b.innerText+=a,b.value=b.innerText):b.value+=a};this.reset=function(){var a=rcube_find_object("dbgconsole");if(a)a.innerText=a.value=""}}var bw=new roundcube_browser;bw.set_html_class();RegExp.escape=function(a){return String(a).replace(/([.*+?^=!:${}()|[\]\/\\])/g,"\\$1")};
-if(bw.ie)document._getElementById=document.getElementById,document.getElementById=function(a){var b=0,c=document._getElementById(a);if(c&&c.id!=a)for(;(c=document.all[b])&&c.id!=a;)b++;return c};
+function rcube_mouse_is_over(a,b){var c=rcube_event.get_mouse_pos(a),d=$(b).offset();return c.x>=d.left&&c.x<d.left+b.offsetWidth&&c.y>=d.top&&c.y<d.top+b.offsetHeight}function setCookie(a,b,c,d,e,f){a=a+"="+escape(b)+(c?"; expires="+c.toGMTString():"")+(d?"; path="+d:"")+(e?"; domain="+e:"")+(f?"; secure":"");document.cookie=a}
+function getCookie(a){var b=document.cookie,a=a+"=",c=b.indexOf("; "+a);if(-1==c){if(c=b.indexOf(a),0!=c)return null}else c+=2;var d=b.indexOf(";",c);if(-1==d)d=b.length;return unescape(b.substring(c+a.length,d))}roundcube_browser.prototype.set_cookie=setCookie;roundcube_browser.prototype.get_cookie=getCookie;
+function rcube_console(){this.log=function(a){var b=rcube_find_object("dbgconsole");if(b)a="\n"==a.charAt(a.length-1)?a+"--------------------------------------\n":a+"\n--------------------------------------\n",bw.konq?(b.innerText+=a,b.value=b.innerText):b.value+=a};this.reset=function(){var a=rcube_find_object("dbgconsole");if(a)a.innerText=a.value=""}}var bw=new roundcube_browser;bw.set_html_class();RegExp.escape=function(a){return(""+a).replace(/([.*+?^=!:${}()|[\]\/\\])/g,"\\$1")};
+Date.prototype.getStdTimezoneOffset=function(){for(var a=12,b=new Date(null,a,1),c=b.getTimezoneOffset();--a;)if(b.setUTCMonth(a),c!=b.getTimezoneOffset())return Math.max(c,b.getTimezoneOffset());return c};if(bw.ie)document._getElementById=document.getElementById,document.getElementById=function(a){var b=0,c=document._getElementById(a);if(c&&c.id!=a)for(;(c=document.all[b])&&c.id!=a;)b++;return c};
+var Base64=function(){return{encode:function(a){if("function"===typeof window.btoa)return btoa(a);var b,c,d,e,f,h,i=0,g="",j=a.length;do b=a.charCodeAt(i++),c=a.charCodeAt(i++),d=a.charCodeAt(i++),e=b>>2,b=(b&3)<<4|c>>4,f=(c&15)<<2|d>>6,h=d&63,isNaN(c)?f=h=64:isNaN(d)&&(h=64),g=g+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(e)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(b)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(f)+
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(h);while(i<j);return g},decode:function(a){if("function"===typeof window.atob)return atob(a);var b,c,d,e,f,h,i=0,g="",a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");h=a.length;do b="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(a.charAt(i++)),c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(a.charAt(i++)),e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(a.charAt(i++)),
+f="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(a.charAt(i++)),b=b<<2|c>>4,c=(c&15)<<4|e>>2,d=(e&3)<<6|f,g+=String.fromCharCode(b),64!=e&&(g+=String.fromCharCode(c)),64!=f&&(g+=String.fromCharCode(d));while(i<h);return g}}}();
index 4a9b9aab9ecf5e744369d718d4edd9000d6a3447..d2558ce88f0fa3e77ce4e4abaa130e4a217a3c19 100644 (file)
@@ -10,7 +10,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
  
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
  
- $Id: common.js 5281 2011-09-27 07:29:49Z alec $
+ $Id: common.js 5481 2011-11-24 07:53:00Z alec $
 */
 
 // Constants
 */
 
 // Constants
@@ -171,14 +171,12 @@ get_modifier: function(e)
   var opcode = 0;
   e = e || window.event;
 
   var opcode = 0;
   e = e || window.event;
 
-  if (bw.mac && e) {
+  if (bw.mac && e)
     opcode += (e.metaKey && CONTROL_KEY) + (e.shiftKey && SHIFT_KEY);
     opcode += (e.metaKey && CONTROL_KEY) + (e.shiftKey && SHIFT_KEY);
-    return opcode;
-  }
-  if (e) {
+  else if (e)
     opcode += (e.ctrlKey && CONTROL_KEY) + (e.shiftKey && SHIFT_KEY);
     opcode += (e.ctrlKey && CONTROL_KEY) + (e.shiftKey && SHIFT_KEY);
-    return opcode;
-  }
+
+  return opcode;
 },
 
 /**
 },
 
 /**
@@ -544,10 +542,17 @@ function rcube_clone_object(obj)
   return out;
 };
 
   return out;
 };
 
-// make a string URL safe
+// make a string URL safe (and compatible with PHP's rawurlencode())
 function urlencode(str)
 {
 function urlencode(str)
 {
-  return window.encodeURIComponent ? encodeURIComponent(str) : escape(str);
+  if (window.encodeURIComponent)
+    return encodeURIComponent(str).replace('*', '%2A');
+
+  return escape(str)
+    .replace('+', '%2B')
+    .replace('*', '%2A')
+    .replace('/', '%2F')
+    .replace('@', '%40');
 };
 
 
 };
 
 
@@ -673,6 +678,23 @@ RegExp.escape = function(str)
   return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
 };
 
   return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
 };
 
+// Extend Date prototype to detect Standard timezone without DST
+// from http://www.michaelapproved.com/articles/timezone-detect-and-ignore-daylight-saving-time-dst/
+Date.prototype.getStdTimezoneOffset = function()
+{
+  var m = 12,
+    d = new Date(null, m, 1),
+    tzo = d.getTimezoneOffset();
+
+    while (--m) {
+      d.setUTCMonth(m);
+      if (tzo != d.getTimezoneOffset()) {
+        return Math.max(tzo, d.getTimezoneOffset());
+    }
+  }
+
+  return tzo;
+}
 
 // Make getElementById() case-sensitive on IE
 if (bw.ie)
 
 // Make getElementById() case-sensitive on IE
 if (bw.ie)
@@ -689,3 +711,82 @@ if (bw.ie)
     return obj;
   }
 }
     return obj;
   }
 }
+
+// This code was written by Tyler Akins and has been placed in the
+// public domain.  It would be nice if you left this header intact.
+// Base64 code from Tyler Akins -- http://rumkin.com
+var Base64 = (function () {
+  var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+
+  var obj = {
+    /**
+     * Encodes a string in base64
+     * @param {String} input The string to encode in base64.
+     */
+    encode: function (input) {
+      if (typeof(window.btoa) === 'function')
+        return btoa(input);
+
+      var chr1, chr2, chr3, enc1, enc2, enc3, enc4, i = 0, output = '', len = input.length;
+
+      do {
+        chr1 = input.charCodeAt(i++);
+        chr2 = input.charCodeAt(i++);
+        chr3 = input.charCodeAt(i++);
+
+        enc1 = chr1 >> 2;
+        enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
+        enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
+        enc4 = chr3 & 63;
+
+        if (isNaN(chr2))
+          enc3 = enc4 = 64;
+        else if (isNaN(chr3))
+          enc4 = 64;
+
+        output = output
+          + keyStr.charAt(enc1) + keyStr.charAt(enc2)
+          + keyStr.charAt(enc3) + keyStr.charAt(enc4);
+      } while (i < len);
+
+      return output;
+    },
+
+    /**
+     * Decodes a base64 string.
+     * @param {String} input The string to decode.
+     */
+    decode: function (input) {
+      if (typeof(window.atob) === 'function')
+         return atob(input);
+
+      var chr1, chr2, chr3, enc1, enc2, enc3, enc4, len, i = 0, output = '';
+
+      // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
+      input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
+      len = input.length;
+
+      do {
+        enc1 = keyStr.indexOf(input.charAt(i++));
+        enc2 = keyStr.indexOf(input.charAt(i++));
+        enc3 = keyStr.indexOf(input.charAt(i++));
+        enc4 = keyStr.indexOf(input.charAt(i++));
+
+        chr1 = (enc1 << 2) | (enc2 >> 4);
+        chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
+        chr3 = ((enc3 & 3) << 6) | enc4;
+
+        output = output + String.fromCharCode(chr1);
+
+        if (enc3 != 64)
+          output = output + String.fromCharCode(chr2);
+        if (enc4 != 64)
+          output = output + String.fromCharCode(chr3);
+      } while (i < len);
+
+      return output;
+    }
+  };
+
+  return obj;
+})();
index a3aef72a2f33a56e122f5d7ec504c038e620dd6f..63186fb02e5de3c6e90cfefe82b2a8c9d3537f35 100644 (file)
 */
 
 // Initialize HTML editor
 */
 
 // Initialize HTML editor
-function rcmail_editor_init(skin_path, editor_lang, spellcheck, mode)
+function rcmail_editor_init(config)
 {
   var ret, conf = {
       mode: 'textareas',
       editor_selector: 'mce_editor',
       apply_source_formatting: true,
       theme: 'advanced',
 {
   var ret, conf = {
       mode: 'textareas',
       editor_selector: 'mce_editor',
       apply_source_formatting: true,
       theme: 'advanced',
-      language: editor_lang,
-      content_css: skin_path + '/editor_content.css',
+      language: config.lang,
+      content_css: config.skin_path + '/editor_content.css',
       theme_advanced_toolbar_location: 'top',
       theme_advanced_toolbar_align: 'left',
       theme_advanced_buttons3: '',
       theme_advanced_toolbar_location: 'top',
       theme_advanced_toolbar_align: 'left',
       theme_advanced_buttons3: '',
@@ -35,7 +35,7 @@ function rcmail_editor_init(skin_path, editor_lang, spellcheck, mode)
       rc_client: rcmail
     };
 
       rc_client: rcmail
     };
 
-  if (mode == 'identity')
+  if (config.mode == 'identity')
     $.extend(conf, {
       plugins: 'paste,tabfocus',
       theme_advanced_buttons1: 'bold,italic,underline,strikethrough,justifyleft,justifycenter,justifyright,justifyfull,separator,outdent,indent,charmap,hr,link,unlink,code,forecolor',
     $.extend(conf, {
       plugins: 'paste,tabfocus',
       theme_advanced_buttons1: 'bold,italic,underline,strikethrough,justifyleft,justifycenter,justifyright,justifyfull,separator,outdent,indent,charmap,hr,link,unlink,code,forecolor',
@@ -43,11 +43,12 @@ function rcmail_editor_init(skin_path, editor_lang, spellcheck, mode)
     });
   else // mail compose
     $.extend(conf, {
     });
   else // mail compose
     $.extend(conf, {
-      plugins: 'paste,emotions,media,nonbreaking,table,searchreplace,visualchars,directionality,tabfocus' + (spellcheck ? ',spellchecker' : ''),
+      plugins: 'paste,emotions,media,nonbreaking,table,searchreplace,visualchars,directionality,tabfocus' + (config.spellcheck ? ',spellchecker' : ''),
       theme_advanced_buttons1: 'bold,italic,underline,|,justifyleft,justifycenter,justifyright,justifyfull,|,bullist,numlist,outdent,indent,ltr,rtl,blockquote,|,forecolor,backcolor,fontselect,fontsizeselect',
       theme_advanced_buttons1: 'bold,italic,underline,|,justifyleft,justifycenter,justifyright,justifyfull,|,bullist,numlist,outdent,indent,ltr,rtl,blockquote,|,forecolor,backcolor,fontselect,fontsizeselect',
-      theme_advanced_buttons2: 'link,unlink,table,|,emotions,charmap,image,media,|,code,search' + (spellcheck ? ',spellchecker' : '') + ',undo,redo',
+      theme_advanced_buttons2: 'link,unlink,table,|,emotions,charmap,image,media,|,code,search' + (config.spellcheck ? ',spellchecker' : '') + ',undo,redo',
       spellchecker_languages: (rcmail.env.spellcheck_langs ? rcmail.env.spellcheck_langs : 'Dansk=da,Deutsch=de,+English=en,Espanol=es,Francais=fr,Italiano=it,Nederlands=nl,Polski=pl,Portugues=pt,Suomi=fi,Svenska=sv'),
       spellchecker_rpc_url: '?_task=utils&_action=spell_html',
       spellchecker_languages: (rcmail.env.spellcheck_langs ? rcmail.env.spellcheck_langs : 'Dansk=da,Deutsch=de,+English=en,Espanol=es,Francais=fr,Italiano=it,Nederlands=nl,Polski=pl,Portugues=pt,Suomi=fi,Svenska=sv'),
       spellchecker_rpc_url: '?_task=utils&_action=spell_html',
+      spellchecker_enable_learn_rpc: config.spelldict,
       accessibility_focus: false,
       oninit: 'rcmail_editor_callback'
     });
       accessibility_focus: false,
       oninit: 'rcmail_editor_callback'
     });
@@ -114,13 +115,17 @@ function rcmail_toggle_editor(select, textAreaId, flagElement)
     if (flagElement && (flag = rcube_find_object(flagElement)))
       flag.value = '1';
   }
     if (flagElement && (flag = rcube_find_object(flagElement)))
       flag.value = '1';
   }
-  else {
-    if (!res && select.tagName == 'SELECT')
-      select.value = 'html';
+  else if (res) {
     if (flagElement && (flag = rcube_find_object(flagElement)))
       flag.value = '0';
 
     if (rcmail.env.composebody)
       rcube_find_object(rcmail.env.composebody).focus();
   }
     if (flagElement && (flag = rcube_find_object(flagElement)))
       flag.value = '0';
 
     if (rcmail.env.composebody)
       rcube_find_object(rcmail.env.composebody).focus();
   }
+  else { // !res
+    if (select.tagName == 'SELECT')
+      select.value = 'html';
+    else if (select.tagName == 'INPUT')
+      select.checked = true;
+  }
 }
 }
index 411740f01cf9a208e485ecea594638392c0e3c59..3618fe10a3c99e12da6542b720cdfb22995a504e 100644 (file)
@@ -1,38 +1,39 @@
 var GOOGIE_CUR_LANG,GOOGIE_DEFAULT_LANG="en";
 var GOOGIE_CUR_LANG,GOOGIE_DEFAULT_LANG="en";
-function GoogieSpell(s,t){var l=this,r=getCookie("language");GOOGIE_CUR_LANG=r!=null?r:GOOGIE_DEFAULT_LANG;this.array_keys=function(a){var b=[],c;for(c in a)b.push([c]);return b};this.img_dir=s;this.server_url=t;this.lang_to_word=this.org_lang_to_word={da:"Dansk",de:"Deutsch",en:"English",es:"Espa&#241;ol",fr:"Fran&#231;ais",it:"Italiano",nl:"Nederlands",pl:"Polski",pt:"Portugu&#234;s",fi:"Suomi",sv:"Svenska"};this.langlist_codes=this.array_keys(this.lang_to_word);this.show_change_lang_pic=!0;this.change_lang_pic_placement=
-"right";this.report_state_change=!0;this.el_scroll_top=this.ta_scroll_top=0;this.lang_chck_spell="Check spelling";this.lang_revert="Revert to";this.lang_close="Close";this.lang_rsm_edt="Resume editing";this.lang_no_error_found="No spelling errors found";this.lang_no_suggestions="No suggestions";this.show_spell_img=!1;this.decoration=!0;this.use_close_btn=!1;this.report_ta_not_found=this.edit_layer_dbl_click=!0;this.custom_no_spelling_error=this.custom_ajax_error=null;this.custom_menu_builder=[];this.custom_item_evaulator=
-null;this.extra_menu_items=[];this.custom_spellcheck_starter=null;this.main_controller=!0;this.all_errors_fixed_observer=this.show_menu_observer=this.spelling_state_observer=this.lang_state_observer=null;this.use_focus=!1;this.focus_link_b=this.focus_link_t=null;this.cnt_errors_fixed=this.cnt_errors=0;$(document).bind("click",function(a){a=$(a.target);a.attr("googie_action_btn")!="1"&&l.isLangWindowShown()&&l.hideLangWindow();a.attr("googie_action_btn")!="1"&&l.isErrorWindowShown()&&l.hideErrorWindow()});
-this.decorateTextarea=function(a){if(this.text_area=typeof a==="string"?document.getElementById(a):a){if(!this.spell_container&&this.decoration){var a=document.createElement("table"),b=document.createElement("tbody"),c=document.createElement("tr"),d=document.createElement("td"),e=this.isDefined(this.force_width)?this.force_width:this.text_area.offsetWidth,f=this.isDefined(this.force_height)?this.force_height:16;c.appendChild(d);b.appendChild(c);$(a).append(b).insertBefore(this.text_area).width("100%").height(f);
-$(d).height(f).width(e).css("text-align","right");this.spell_container=d}this.checkSpellingState()}else this.report_ta_not_found&&alert("Text area not found")};this.setSpellContainer=function(a){this.spell_container=typeof a==="string"?document.getElementById(a):a};this.setLanguages=function(a){this.lang_to_word=a;this.langlist_codes=this.array_keys(a)};this.setCurrentLanguage=function(a){GOOGIE_CUR_LANG=a;var b=new Date;b.setTime(b.getTime()+31536E6);setCookie("language",a,b)};this.setForceWidthHeight=
-function(a,b){this.force_width=a;this.force_height=b};this.setDecoration=function(a){this.decoration=a};this.dontUseCloseButtons=function(){this.use_close_btn=!1};this.appendNewMenuItem=function(a,b,c){this.extra_menu_items.push([a,b,c])};this.appendCustomMenuBuilder=function(a,b){this.custom_menu_builder.push([a,b])};this.setFocus=function(){try{return this.focus_link_b.focus(),this.focus_link_t.focus(),!0}catch(a){return!1}};this.setStateChanged=function(a){this.state=a;this.spelling_state_observer!=
-null&&this.report_state_change&&this.spelling_state_observer(a,this)};this.setReportStateChange=function(a){this.report_state_change=a};this.getUrl=function(){return this.server_url+GOOGIE_CUR_LANG};this.escapeSpecial=function(a){return a?a.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;"):""};this.createXMLReq=function(a){return'<?xml version="1.0" encoding="utf-8" ?><spellrequest textalreadyclipped="0" ignoredups="0" ignoredigits="1" ignoreallcaps="1"><text>'+a+"</text></spellrequest>"};
-this.spellCheck=function(a){this.prepare(a);var a=this.escapeSpecial(this.orginal_text),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.");b.main_controller&&($(b.spell_span).remove(),b.removeIndicator());b.checkSpellingState()},success:function(a){b.processData(a);b.results.length||(b.custom_no_spelling_error?b.custom_no_spelling_error(b):
-b.flashNoSpellingErrorState());b.removeIndicator()}})};this.prepare=function(a,b){this.cnt_errors=this.cnt_errors_fixed=0;this.setStateChanged("checking_spell");!b&&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()}};this.parseResult=function(a){var b=/\w+="(\d+|true)"/g,c=/\t/g,a=a.match(/<c[^>]*>[^<]*<\/c>/g),d=[];if(a==null)return d;for(var e=0,f=a.length;e<f;e++){var j=[];this.errorFound();j.attrs=[];for(var g,h,l=a[e].match(b),k=
-0;k<l.length;k++)g=l[k].split(/=/),h=g[1].replace(/"/g,""),j.attrs[g[0]]=h!="true"?parseInt(h):h;j.suggestions=[];g=a[e].replace(/<[^>]*>/g,"").split(c);for(h=0;h<g.length;h++)g[h]!=""&&j.suggestions.push(g[h]);d.push(j)}return d};this.processData=function(a){this.results=this.parseResult(a);this.results.length&&(this.showErrorsInIframe(),this.resumeEditingState())};this.createErrorWindow=function(){this.error_window=document.createElement("div");$(this.error_window).addClass("googie_window popupmenu").attr("googie_action_btn",
-"1")};this.isErrorWindowShown=function(){return $(this.error_window).is(":visible")};this.hideErrorWindow=function(){$(this.error_window).hide();$(this.error_window_iframe).hide()};this.updateOrginalText=function(a,b,c,d){var e=this.orginal_text.substring(0,a),a=this.orginal_text.substring(a+b.length),b=c.length-b.length;this.orginal_text=e+c+a;$(this.text_area).val(this.orginal_text);c=0;for(e=this.results.length;c<e;c++)c!=d&&c>d&&(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;g<this.custom_menu_builder.length;g++){var h=this.custom_menu_builder[g];if(h[0](this.results[b])){j=h[1](this,f,a);break}}if(!j){var j=this.results[b].suggestions,l=this.results[b].attrs.o,g=this.results[b].attrs.l,k,m;j.length==0&&(h=document.createElement("tr"),k=document.createElement("td"),m=document.createElement("span"),$(m).text(this.lang_no_suggestions),$(k).attr("googie_action_btn","1").css("cursor","default"),k.appendChild(m),h.appendChild(k),f.appendChild(h));for(var o=0,g=j.length;o<
-g;o++)h=document.createElement("tr"),k=document.createElement("td"),m=document.createElement("span"),$(m).html(j[o]),$(k).bind("mouseover",this.item_onmouseover).bind("mouseout",this.item_onmouseout).bind("click",function(d){c.correctError(b,a,d.target.firstChild)}),k.appendChild(m),h.appendChild(k),f.appendChild(h);if(a.is_changed&&a.innerHTML!=a.old_value){var p=a.old_value,j=document.createElement("tr"),g=document.createElement("td"),h=document.createElement("span");$(h).addClass("googie_list_revert").html(this.lang_revert+
-" "+p);$(g).bind("mouseover",this.item_onmouseover).bind("mouseout",this.item_onmouseout).bind("click",function(){c.updateOrginalText(l,a.innerHTML,p,b);$(a).attr("is_corrected",!0).css("color","#b91414").html(p);c.hideErrorWindow()});g.appendChild(h);j.appendChild(g);f.appendChild(j)}var j=document.createElement("tr"),g=document.createElement("td"),n=document.createElement("input"),h=document.createElement("img");k=document.createElement("form");m=function(){n.value!=""&&(c.isDefined(a.old_value)||
-c.saveOldValue(a,a.innerHTML),c.updateOrginalText(l,a.innerHTML,n.value,b),$(a).attr("is_corrected",!0).css("color","green").html(n.value),c.hideErrorWindow());return!1};$(n).width(120).css({margin:0,padding:0});$(n).val(a.innerHTML).attr("googie_action_btn","1");$(g).css("cursor","default").attr("googie_action_btn","1");$(h).attr("src",this.img_dir+"ok.gif").width(32).height(16).css({cursor:"pointer","margin-left":"2px","margin-right":"2px"}).bind("click",m);$(k).attr("googie_action_btn","1").css({margin:0,
-padding:0,cursor:"default","white-space":"nowrap"}).bind("submit",m);k.appendChild(n);k.appendChild(h);g.appendChild(k);j.appendChild(g);f.appendChild(j);this.extra_menu_items.length>0&&f.appendChild(this.createListSeparator());var q=function(b){if(b<c.extra_menu_items.length){var d=c.extra_menu_items[b];if(!d[2]||d[2](a,c)){var e=document.createElement("tr"),g=document.createElement("td");$(g).html(d[0]).bind("mouseover",c.item_onmouseover).bind("mouseout",c.item_onmouseout).bind("click",function(){return d[1](a,
+function GoogieSpell(s,t,u){var l=this,r=getCookie("language");GOOGIE_CUR_LANG=null!=r?r:GOOGIE_DEFAULT_LANG;this.array_keys=function(a){var b=[],c;for(c in a)b.push([c]);return b};this.img_dir=s;this.server_url=t;this.lang_to_word=this.org_lang_to_word={da:"Dansk",de:"Deutsch",en:"English",es:"Espa&#241;ol",fr:"Fran&#231;ais",it:"Italiano",nl:"Nederlands",pl:"Polski",pt:"Portugu&#234;s",fi:"Suomi",sv:"Svenska"};this.langlist_codes=this.array_keys(this.lang_to_word);this.show_change_lang_pic=!0;this.change_lang_pic_placement=
+"right";this.report_state_change=!0;this.el_scroll_top=this.ta_scroll_top=0;this.lang_chck_spell="Check spelling";this.lang_revert="Revert to";this.lang_close="Close";this.lang_rsm_edt="Resume editing";this.lang_no_error_found="No spelling errors found";this.lang_no_suggestions="No suggestions";this.lang_learn_word="Add to dictionary";this.show_spell_img=!1;this.decoration=!0;this.use_close_btn=!1;this.report_ta_not_found=this.edit_layer_dbl_click=!0;this.custom_no_spelling_error=this.custom_ajax_error=
+null;this.custom_menu_builder=[];this.custom_item_evaulator=null;this.extra_menu_items=[];this.custom_spellcheck_starter=null;this.main_controller=!0;this.has_dictionary=u;this.all_errors_fixed_observer=this.show_menu_observer=this.spelling_state_observer=this.lang_state_observer=null;this.use_focus=!1;this.focus_link_b=this.focus_link_t=null;this.cnt_errors_fixed=this.cnt_errors=0;$(document).bind("click",function(a){a=$(a.target);"1"!=a.attr("googie_action_btn")&&l.isLangWindowShown()&&l.hideLangWindow();
+"1"!=a.attr("googie_action_btn")&&l.isErrorWindowShown()&&l.hideErrorWindow()});this.decorateTextarea=function(a){if(this.text_area="string"===typeof a?document.getElementById(a):a){if(!this.spell_container&&this.decoration){var a=document.createElement("table"),b=document.createElement("tbody"),c=document.createElement("tr"),d=document.createElement("td"),e=this.isDefined(this.force_width)?this.force_width:this.text_area.offsetWidth,f=this.isDefined(this.force_height)?this.force_height:16;c.appendChild(d);
+b.appendChild(c);$(a).append(b).insertBefore(this.text_area).width("100%").height(f);$(d).height(f).width(e).css("text-align","right");this.spell_container=d}this.checkSpellingState()}else this.report_ta_not_found&&alert("Text area not found")};this.setSpellContainer=function(a){this.spell_container="string"===typeof a?document.getElementById(a):a};this.setLanguages=function(a){this.lang_to_word=a;this.langlist_codes=this.array_keys(a)};this.setCurrentLanguage=function(a){GOOGIE_CUR_LANG=a;var b=
+new Date;b.setTime(b.getTime()+31536E6);setCookie("language",a,b)};this.setForceWidthHeight=function(a,b){this.force_width=a;this.force_height=b};this.setDecoration=function(a){this.decoration=a};this.dontUseCloseButtons=function(){this.use_close_btn=!1};this.appendNewMenuItem=function(a,b,c){this.extra_menu_items.push([a,b,c])};this.appendCustomMenuBuilder=function(a,b){this.custom_menu_builder.push([a,b])};this.setFocus=function(){try{return this.focus_link_b.focus(),this.focus_link_t.focus(),!0}catch(a){return!1}};
+this.setStateChanged=function(a){this.state=a;null!=this.spelling_state_observer&&this.report_state_change&&this.spelling_state_observer(a,this)};this.setReportStateChange=function(a){this.report_state_change=a};this.getUrl=function(){return this.server_url+GOOGIE_CUR_LANG};this.escapeSpecial=function(a){return a?a.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;"):""};this.createXMLReq=function(a){return'<?xml version="1.0" encoding="utf-8" ?><spellrequest textalreadyclipped="0" ignoredups="0" ignoredigits="1" ignoreallcaps="1"><text>'+
+a+"</text></spellrequest>"};this.spellCheck=function(a){this.prepare(a);var a=this.escapeSpecial(this.orginal_text),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.");b.main_controller&&($(b.spell_span).remove(),b.removeIndicator());b.checkSpellingState()},success:function(a){b.processData(a);b.results.length||(b.custom_no_spelling_error?
+b.custom_no_spelling_error(b):b.flashNoSpellingErrorState());b.removeIndicator()}})};this.learnWord=function(a){var a=this.escapeSpecial(a.innerHTML),b=this,a='<?xml version="1.0" encoding="utf-8" ?><learnword><text>'+a+"</text></learnword>";$.ajax({type:"POST",url:this.getUrl(),data: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.")},success:function(){}})};this.prepare=function(a,b){this.cnt_errors=
+this.cnt_errors_fixed=0;this.setStateChanged("checking_spell");!b&&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()}};this.parseResult=function(a){var b=/\w+="(\d+|true)"/g,c=/\t/g,a=a.match(/<c[^>]*>[^<]*<\/c>/g),d=[];if(null==a)return d;for(var e=0,f=a.length;e<f;e++){var j=[];this.errorFound();j.attrs=[];for(var g,h,l=a[e].match(b),k=0;k<l.length;k++)g=l[k].split(/=/),h=g[1].replace(/"/g,""),j.attrs[g[0]]="true"!=h?parseInt(h):
+h;j.suggestions=[];g=a[e].replace(/<[^>]*>/g,"").split(c);for(h=0;h<g.length;h++)""!=g[h]&&j.suggestions.push(g[h]);d.push(j)}return d};this.processData=function(a){this.results=this.parseResult(a);this.results.length&&(this.showErrorsInIframe(),this.resumeEditingState())};this.createErrorWindow=function(){this.error_window=document.createElement("div");$(this.error_window).addClass("googie_window popupmenu").attr("googie_action_btn","1")};this.isErrorWindowShown=function(){return $(this.error_window).is(":visible")};
+this.hideErrorWindow=function(){$(this.error_window).hide();$(this.error_window_iframe).hide()};this.updateOrginalText=function(a,b,c,d){var e=this.orginal_text.substring(0,a),a=this.orginal_text.substring(a+b.length),b=c.length-b.length;this.orginal_text=e+c+a;$(this.text_area).val(this.orginal_text);c=0;for(e=this.results.length;c<e;c++)c!=d&&c>d&&(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=3==c.nodeType?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.ignoreError=function(a){$(a).removeAttr("class").css("color","").unbind();this.hideErrorWindow()};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;g<
+this.custom_menu_builder.length;g++){var h=this.custom_menu_builder[g];if(h[0](this.results[b])){j=h[1](this,f,a);break}}if(!j){var j=this.results[b].suggestions,l=this.results[b].attrs.o,g=this.results[b].attrs.l,k,m;this.has_dictionary&&!$(a).attr("is_corrected")&&(h=document.createElement("tr"),k=document.createElement("td"),m=document.createElement("span"),$(m).text(this.lang_learn_word),$(k).attr("googie_action_btn","1").css("cursor","default").mouseover(c.item_onmouseover).mouseout(c.item_onmouseout).click(function(){c.learnWord(a,
+b);c.ignoreError(a,b)}),k.appendChild(m),h.appendChild(k),f.appendChild(h));for(var o=0,g=j.length;o<g;o++)h=document.createElement("tr"),k=document.createElement("td"),m=document.createElement("span"),$(m).html(j[o]),$(k).mouseover(this.item_onmouseover).mouseout(this.item_onmouseout).click(function(d){c.correctError(b,a,d.target.firstChild)}),k.appendChild(m),h.appendChild(k),f.appendChild(h);if(a.is_changed&&a.innerHTML!=a.old_value){var p=a.old_value,j=document.createElement("tr"),g=document.createElement("td"),
+h=document.createElement("span");$(h).addClass("googie_list_revert").html(this.lang_revert+" "+p);$(g).mouseover(this.item_onmouseover).mouseout(this.item_onmouseout).click(function(){c.updateOrginalText(l,a.innerHTML,p,b);$(a).removeAttr("is_corrected").css("color","#b91414").html(p);c.hideErrorWindow()});g.appendChild(h);j.appendChild(g);f.appendChild(j)}var j=document.createElement("tr"),g=document.createElement("td"),n=document.createElement("input"),h=document.createElement("img");k=document.createElement("form");
+m=function(){""!=n.value&&(c.isDefined(a.old_value)||c.saveOldValue(a,a.innerHTML),c.updateOrginalText(l,a.innerHTML,n.value,b),$(a).attr("is_corrected",!0).css("color","green").html(n.value),c.hideErrorWindow());return!1};$(n).width(120).css({margin:0,padding:0});$(n).val(a.innerHTML).attr("googie_action_btn","1");$(g).css("cursor","default").attr("googie_action_btn","1");$(h).attr("src",this.img_dir+"ok.gif").width(32).height(16).css({cursor:"pointer","margin-left":"2px","margin-right":"2px"}).click(m);
+$(k).attr("googie_action_btn","1").css({margin:0,padding:0,cursor:"default","white-space":"nowrap"}).submit(m);k.appendChild(n);k.appendChild(h);g.appendChild(k);j.appendChild(g);f.appendChild(j);0<this.extra_menu_items.length&&f.appendChild(this.createListSeparator());var q=function(b){if(b<c.extra_menu_items.length){var d=c.extra_menu_items[b];if(!d[2]||d[2](a,c)){var e=document.createElement("tr"),g=document.createElement("td");$(g).html(d[0]).mouseover(c.item_onmouseover).mouseout(c.item_onmouseout).click(function(){return d[1](a,
 c)});e.appendChild(g);f.appendChild(e)}q(b+1)}};q(0);q=null;this.use_close_btn&&f.appendChild(this.createCloseButton(this.hideErrorWindow))}e.appendChild(f);this.error_window.appendChild(e);g=$(this.error_window).height();e=$(this.error_window).width();h=$(document).height();j=$(document).width();g=d.top+g+20<h?d.top+20:d.top-g;d=d.left+e<j?d.left:d.left-e;$(this.error_window).css({top:g+"px",left:d+"px"}).show();if($.browser.msie){if(!this.error_window_iframe)d=$("<iframe>").css({position:"absolute",
 c)});e.appendChild(g);f.appendChild(e)}q(b+1)}};q(0);q=null;this.use_close_btn&&f.appendChild(this.createCloseButton(this.hideErrorWindow))}e.appendChild(f);this.error_window.appendChild(e);g=$(this.error_window).height();e=$(this.error_window).width();h=$(document).height();j=$(document).width();g=d.top+g+20<h?d.top+20:d.top-g;d=d.left+e<j?d.left:d.left-e;$(this.error_window).css({top:g+"px",left:d+"px"}).show();if($.browser.msie){if(!this.error_window_iframe)d=$("<iframe>").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,"<br>"),a=a.replace(/    /g," &nbsp;"),a=a.replace(/^ /g,"&nbsp;"),a=a.replace(/ $/g,"&nbsp;"),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<e;d++){var f=c[d].attrs.o,j=c[d].attrs.l,g=this.createPart(this.orginal_text.substring(b,
+"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);"input"!=this.text_area.nodeName.toLowerCase()||""==$(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("googie_link"!=a.target.className&&!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(),void 0!=this.el_scroll_top))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").click(e).removeAttr("is_corrected").attr({googie_action_btn:"1",
+g_id:b});return c};this.createPart=function(a){if(" "==a)return document.createTextNode(" ");var a=this.escapeSpecial(a),a=a.replace(/\n/g,"<br>"),a=a.replace(/    /g," &nbsp;"),a=a.replace(/^ /g,"&nbsp;"),a=a.replace(/ $/g,"&nbsp;"),b=document.createElement("span");$(b).html(a);return b};this.showErrorsInIframe=function(){var a=document.createElement("div"),b=0,c=this.results;if(0<c.length){for(var d=0,e=c.length;d<e;d++){var f=c[d].attrs.o,j=c[d].attrs.l,g=this.createPart(this.orginal_text.substring(b,
 f));a.appendChild(g);b+=f-b;f=this.createErrorLink(this.orginal_text.substr(f,j),d);this.error_links.push(f);a.appendChild(f);b+=j}b=this.createPart(this.orginal_text.substr(b,this.orginal_text.length));a.appendChild(b)}else a.innerHTML=this.orginal_text;$(a).css("text-align","left");var h=this;this.custom_item_evaulator&&$.map(this.error_links,function(a){h.custom_item_evaulator(h,a)});$(this.edit_layer).append(a);$(this.text_area).hide();$(this.edit_layer).insertBefore(this.text_area);if(this.use_focus)this.focus_link_t=
 this.createFocusLink("focus_t"),this.focus_link_b=this.createFocusLink("focus_b"),$(this.focus_link_t).insertBefore(this.edit_layer),$(this.focus_link_b).insertAfter(this.edit_layer)};this.createLangWindow=function(){this.language_window=document.createElement("div");$(this.language_window).addClass("googie_window popupmenu").width(100).attr("googie_action_btn","1");var a=document.createElement("table"),b=document.createElement("tbody"),c=this,d,e,f;$(a).addClass("googie_list").width("100%");this.lang_elms=
 f));a.appendChild(g);b+=f-b;f=this.createErrorLink(this.orginal_text.substr(f,j),d);this.error_links.push(f);a.appendChild(f);b+=j}b=this.createPart(this.orginal_text.substr(b,this.orginal_text.length));a.appendChild(b)}else a.innerHTML=this.orginal_text;$(a).css("text-align","left");var h=this;this.custom_item_evaulator&&$.map(this.error_links,function(a){h.custom_item_evaulator(h,a)});$(this.edit_layer).append(a);$(this.text_area).hide();$(this.edit_layer).insertBefore(this.text_area);if(this.use_focus)this.focus_link_t=
 this.createFocusLink("focus_t"),this.focus_link_b=this.createFocusLink("focus_b"),$(this.focus_link_t).insertBefore(this.edit_layer),$(this.focus_link_b).insertAfter(this.edit_layer)};this.createLangWindow=function(){this.language_window=document.createElement("div");$(this.language_window).addClass("googie_window popupmenu").width(100).attr("googie_action_btn","1");var a=document.createElement("table"),b=document.createElement("tbody"),c=this,d,e,f;$(a).addClass("googie_list").width("100%");this.lang_elms=
-[];for(i=0;i<this.langlist_codes.length;i++)d=document.createElement("tr"),e=document.createElement("td"),f=document.createElement("span"),$(f).text(this.lang_to_word[this.langlist_codes[i]]),this.lang_elms.push(e),$(e).attr("googieId",this.langlist_codes[i]).bind("click",function(){c.deHighlightCurSel();c.setCurrentLanguage($(this).attr("googieId"));c.lang_state_observer!=null&&c.lang_state_observer();c.highlightCurSel();c.hideLangWindow()}).bind("mouseover",function(){if(this.className!="googie_list_selected")this.className=
-"googie_list_onhover"}).bind("mouseout",function(){if(this.className!="googie_list_selected")this.className="googie_list_onout"}),e.appendChild(f),d.appendChild(e),b.appendChild(d);this.use_close_btn&&b.appendChild(this.createCloseButton(function(){c.hideLangWindow.apply(c)}));this.highlightCurSel();a.appendChild(b);this.language_window.appendChild(a)};this.isLangWindowShown=function(){return $(this.language_window).is(":visible")};this.hideLangWindow=function(){$(this.language_window).hide();$(this.switch_lan_pic).removeClass().addClass("googie_lang_3d_on")};
-this.showLangWindow=function(a){this.show_menu_observer&&this.show_menu_observer(this);this.createLangWindow();$("body").append(this.language_window);var b=$(a).offset(),c=$(a).height(),d=$(a).width(),a=$(this.language_window).height(),e=$(document).height(),d=this.change_lang_pic_placement=="right"?b.left-100+d:b.left+d,b=b.top+a<e?b.top+c:b.top-a-4;$(this.language_window).css({top:b+"px",left:d+"px"}).show();this.highlightCurSel()};this.deHighlightCurSel=function(){$(this.lang_cur_elm).removeClass().addClass("googie_list_onout")};
-this.highlightCurSel=function(){GOOGIE_CUR_LANG==null&&(GOOGIE_CUR_LANG=GOOGIE_DEFAULT_LANG);for(var a=0;a<this.lang_elms.length;a++)$(this.lang_elms[a]).attr("googieId")==GOOGIE_CUR_LANG?(this.lang_elms[a].className="googie_list_selected",this.lang_cur_elm=this.lang_elms[a]):this.lang_elms[a].className="googie_list_onout"};this.createChangeLangPic=function(){var a=$("<img>").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($("<img>").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=$("<span>").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=$("<span>").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!==void 0&&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"}};
+[];for(i=0;i<this.langlist_codes.length;i++)d=document.createElement("tr"),e=document.createElement("td"),f=document.createElement("span"),$(f).text(this.lang_to_word[this.langlist_codes[i]]),this.lang_elms.push(e),$(e).attr("googieId",this.langlist_codes[i]).bind("click",function(){c.deHighlightCurSel();c.setCurrentLanguage($(this).attr("googieId"));null!=c.lang_state_observer&&c.lang_state_observer();c.highlightCurSel();c.hideLangWindow()}).bind("mouseover",function(){if("googie_list_selected"!=
+this.className)this.className="googie_list_onhover"}).bind("mouseout",function(){if("googie_list_selected"!=this.className)this.className="googie_list_onout"}),e.appendChild(f),d.appendChild(e),b.appendChild(d);this.use_close_btn&&b.appendChild(this.createCloseButton(function(){c.hideLangWindow.apply(c)}));this.highlightCurSel();a.appendChild(b);this.language_window.appendChild(a)};this.isLangWindowShown=function(){return $(this.language_window).is(":visible")};this.hideLangWindow=function(){$(this.language_window).hide();
+$(this.switch_lan_pic).removeClass().addClass("googie_lang_3d_on")};this.showLangWindow=function(a){this.show_menu_observer&&this.show_menu_observer(this);this.createLangWindow();$("body").append(this.language_window);var b=$(a).offset(),c=$(a).height(),d=$(a).width(),a=$(this.language_window).height(),e=$(document).height(),d="right"==this.change_lang_pic_placement?b.left-100+d:b.left+d,b=b.top+a<e?b.top+c:b.top-a-4;$(this.language_window).css({top:b+"px",left:d+"px"}).show();this.highlightCurSel()};
+this.deHighlightCurSel=function(){$(this.lang_cur_elm).removeClass().addClass("googie_list_onout")};this.highlightCurSel=function(){null==GOOGIE_CUR_LANG&&(GOOGIE_CUR_LANG=GOOGIE_DEFAULT_LANG);for(var a=0;a<this.lang_elms.length;a++)$(this.lang_elms[a]).attr("googieId")==GOOGIE_CUR_LANG?(this.lang_elms[a].className="googie_list_selected",this.lang_cur_elm=this.lang_elms[a]):this.lang_elms[a].className="googie_list_onout"};this.createChangeLangPic=function(){var a=$("<img>").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="img"==this.tagName.toLowerCase()?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($("<img>").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=$("<span>").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=$("<span>").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&&("left"==this.change_lang_pic_placement?$(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 void 0!==a&&null!==
+a};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(){"googie_list_revert"!=this.className&&
+"googie_list_close"!=this.className?this.className="googie_list_onhover":this.parentNode.className="googie_list_onhover"};this.item_onmouseout=function(){"googie_list_revert"!=this.className&&"googie_list_close"!=this.className?this.className="googie_list_onout":this.parentNode.className="googie_list_onout"}};
index de8890f5fb95e6ef010833a16b0a9dc255564c11..96d612ca23e1a812be247b06654744b8e0228ed2 100644 (file)
@@ -1,8 +1,11 @@
 /*
  SpellCheck
     jQuery'fied spell checker based on GoogieSpell 4.0
 /*
  SpellCheck
     jQuery'fied spell checker based on GoogieSpell 4.0
- Copyright Amir Salihefendic 2006
- Copyright Aleksander Machniak 2009
+      (which was published under GPL "version 2 or any later version")
+
+ Copyright (C) 2006 Amir Salihefendic
+ Copyright (C) 2009 Aleksander Machniak
+ Copyright (C) 2011 Kolab Systems AG
      LICENSE
          GPL
      AUTHORS
      LICENSE
          GPL
      AUTHORS
@@ -13,7 +16,8 @@
 var GOOGIE_CUR_LANG,
     GOOGIE_DEFAULT_LANG = 'en';
 
 var GOOGIE_CUR_LANG,
     GOOGIE_DEFAULT_LANG = 'en';
 
-function GoogieSpell(img_dir, server_url) {
+function GoogieSpell(img_dir, server_url, has_dict)
+{
     var ref = this,
         cookie_value = getCookie('language');
 
     var ref = this,
         cookie_value = getCookie('language');
 
@@ -49,6 +53,7 @@ function GoogieSpell(img_dir, server_url) {
     this.lang_rsm_edt = "Resume editing";
     this.lang_no_error_found = "No spelling errors found";
     this.lang_no_suggestions = "No suggestions";
     this.lang_rsm_edt = "Resume editing";
     this.lang_no_error_found = "No spelling errors found";
     this.lang_no_suggestions = "No suggestions";
+    this.lang_learn_word = "Add to dictionary";
 
     this.show_spell_img = false; // roundcube mod.
     this.decoration = true;
 
     this.show_spell_img = false; // roundcube mod.
     this.decoration = true;
@@ -64,6 +69,7 @@ function GoogieSpell(img_dir, server_url) {
     this.extra_menu_items = [];
     this.custom_spellcheck_starter = null;
     this.main_controller = true;
     this.extra_menu_items = [];
     this.custom_spellcheck_starter = null;
     this.main_controller = true;
+    this.has_dictionary = has_dict;
 
     // Observers
     this.lang_state_observer = null;
 
     // Observers
     this.lang_state_observer = null;
@@ -90,7 +96,8 @@ function GoogieSpell(img_dir, server_url) {
     });
 
 
     });
 
 
-this.decorateTextarea = function(id) {
+this.decorateTextarea = function(id)
+{
     this.text_area = typeof id === 'string' ? document.getElementById(id) : id;
 
     if (this.text_area) {
     this.text_area = typeof id === 'string' ? document.getElementById(id) : id;
 
     if (this.text_area) {
@@ -119,16 +126,19 @@ this.decorateTextarea = function(id) {
 //////
 // API Functions (the ones that you can call)
 /////
 //////
 // API Functions (the ones that you can call)
 /////
-this.setSpellContainer = function(id) {
+this.setSpellContainer = function(id)
+{
     this.spell_container = typeof id === 'string' ? document.getElementById(id) : id;
 };
 
     this.spell_container = typeof id === 'string' ? document.getElementById(id) : id;
 };
 
-this.setLanguages = function(lang_dict) {
+this.setLanguages = function(lang_dict)
+{
     this.lang_to_word = lang_dict;
     this.langlist_codes = this.array_keys(lang_dict);
 };
 
     this.lang_to_word = lang_dict;
     this.langlist_codes = this.array_keys(lang_dict);
 };
 
-this.setCurrentLanguage = function(lan_code) {
+this.setCurrentLanguage = function(lan_code)
+{
     GOOGIE_CUR_LANG = lan_code;
 
     //Set cookie
     GOOGIE_CUR_LANG = lan_code;
 
     //Set cookie
@@ -137,29 +147,35 @@ this.setCurrentLanguage = function(lan_code) {
     setCookie('language', lan_code, now);
 };
 
     setCookie('language', lan_code, now);
 };
 
-this.setForceWidthHeight = function(width, height) {
+this.setForceWidthHeight = function(width, height)
+{
     // Set to null if you want to use one of them
     this.force_width = width;
     this.force_height = height;
 };
 
     // Set to null if you want to use one of them
     this.force_width = width;
     this.force_height = height;
 };
 
-this.setDecoration = function(bool) {
+this.setDecoration = function(bool)
+{
     this.decoration = bool;
 };
 
     this.decoration = bool;
 };
 
-this.dontUseCloseButtons = function() {
+this.dontUseCloseButtons = function()
+{
     this.use_close_btn = false;
 };
 
     this.use_close_btn = false;
 };
 
-this.appendNewMenuItem = function(name, call_back_fn, checker) {
+this.appendNewMenuItem = function(name, call_back_fn, checker)
+{
     this.extra_menu_items.push([name, call_back_fn, checker]);
 };
 
     this.extra_menu_items.push([name, call_back_fn, checker]);
 };
 
-this.appendCustomMenuBuilder = function(eval_fn, builder) {
+this.appendCustomMenuBuilder = function(eval_fn, builder)
+{
     this.custom_menu_builder.push([eval_fn, builder]);
 };
 
     this.custom_menu_builder.push([eval_fn, builder]);
 };
 
-this.setFocus = function() {
+this.setFocus = function()
+{
     try {
         this.focus_link_b.focus();
         this.focus_link_t.focus();
     try {
         this.focus_link_b.focus();
         this.focus_link_t.focus();
@@ -174,13 +190,15 @@ this.setFocus = function() {
 //////
 // Set functions (internal)
 /////
 //////
 // Set functions (internal)
 /////
-this.setStateChanged = function(current_state) {
+this.setStateChanged = function(current_state)
+{
     this.state = current_state;
     if (this.spelling_state_observer != null && this.report_state_change)
         this.spelling_state_observer(current_state, this);
 };
 
     this.state = current_state;
     if (this.spelling_state_observer != null && this.report_state_change)
         this.spelling_state_observer(current_state, this);
 };
 
-this.setReportStateChange = function(bool) {
+this.setReportStateChange = function(bool)
+{
     this.report_state_change = bool;
 };
 
     this.report_state_change = bool;
 };
 
@@ -188,28 +206,31 @@ this.setReportStateChange = function(bool) {
 //////
 // Request functions
 /////
 //////
 // Request functions
 /////
-this.getUrl = function() {
+this.getUrl = function()
+{
     return this.server_url + GOOGIE_CUR_LANG;
 };
 
     return this.server_url + GOOGIE_CUR_LANG;
 };
 
-this.escapeSpecial = function(val) {
+this.escapeSpecial = function(val)
+{
     return val ? val.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;") : '';
 };
 
     return val ? val.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;") : '';
 };
 
-this.createXMLReq = function (text) {
+this.createXMLReq = function (text)
+{
     return '<?xml version="1.0" encoding="utf-8" ?>'
        + '<spellrequest textalreadyclipped="0" ignoredups="0" ignoredigits="1" ignoreallcaps="1">'
        + '<text>' + text + '</text></spellrequest>';
 };
 
     return '<?xml version="1.0" encoding="utf-8" ?>'
        + '<spellrequest textalreadyclipped="0" ignoredups="0" ignoredigits="1" ignoreallcaps="1">'
        + '<text>' + text + '</text></spellrequest>';
 };
 
-this.spellCheck = function(ignore) {
+this.spellCheck = function(ignore)
+{
     this.prepare(ignore);
 
     var req_text = this.escapeSpecial(this.orginal_text),
         ref = this;
 
     this.prepare(ignore);
 
     var req_text = this.escapeSpecial(this.orginal_text),
         ref = this;
 
-    $.ajax({ type: 'POST', url: this.getUrl(),
-       data: this.createXMLReq(req_text), dataType: 'text',
+    $.ajax({ type: 'POST', url: this.getUrl(), data: this.createXMLReq(req_text), dataType: 'text',
            error: function(o) {
             if (ref.custom_ajax_error)
                    ref.custom_ajax_error(ref);
            error: function(o) {
             if (ref.custom_ajax_error)
                    ref.custom_ajax_error(ref);
@@ -234,6 +255,25 @@ this.spellCheck = function(ignore) {
     });
 };
 
     });
 };
 
+this.learnWord = function(word, id)
+{
+    word = this.escapeSpecial(word.innerHTML);
+
+    var ref = this,
+        req_text = '<?xml version="1.0" encoding="utf-8" ?><learnword><text>' + word + '</text></learnword>';
+
+    $.ajax({ type: 'POST', url: this.getUrl(), data: req_text, dataType: 'text',
+           error: function(o) {
+            if (ref.custom_ajax_error)
+                   ref.custom_ajax_error(ref);
+            else
+                   alert('An error was encountered on the server. Please try again later.');
+           },
+        success: function(data) {
+           }
+    });
+};
+
 
 //////
 // Spell checking functions
 
 //////
 // Spell checking functions
@@ -274,7 +314,8 @@ this.prepare = function(ignore, no_indicator)
     this.orginal_text = $(this.text_area).val();
 };
 
     this.orginal_text = $(this.text_area).val();
 };
 
-this.parseResult = function(r_text) {
+this.parseResult = function(r_text)
+{
     // Returns an array: result[item] -> ['attrs'], ['suggestions']
     var re_split_attr_c = /\w+="(\d+|true)"/g,
         re_split_text = /\t/g,
     // Returns an array: result[item] -> ['attrs'], ['suggestions']
     var re_split_attr_c = /\w+="(\d+|true)"/g,
         re_split_text = /\t/g,
@@ -324,21 +365,25 @@ this.processData = function(data)
 //////
 // Error menu functions
 /////
 //////
 // Error menu functions
 /////
-this.createErrorWindow = function() {
+this.createErrorWindow = function()
+{
     this.error_window = document.createElement('div');
     $(this.error_window).addClass('googie_window popupmenu').attr('googie_action_btn', '1');
 };
 
     this.error_window = document.createElement('div');
     $(this.error_window).addClass('googie_window popupmenu').attr('googie_action_btn', '1');
 };
 
-this.isErrorWindowShown = function() {
+this.isErrorWindowShown = function()
+{
     return $(this.error_window).is(':visible');
 };
 
     return $(this.error_window).is(':visible');
 };
 
-this.hideErrorWindow = function() {
+this.hideErrorWindow = function()
+{
     $(this.error_window).hide();
     $(this.error_window_iframe).hide();
 };
 
     $(this.error_window).hide();
     $(this.error_window_iframe).hide();
 };
 
-this.updateOrginalText = function(offset, old_value, new_value, id) {
+this.updateOrginalText = function(offset, old_value, new_value, id)
+{
     var part_1 = this.orginal_text.substring(0, offset),
         part_2 = this.orginal_text.substring(offset+old_value.length),
         add_2_offset = new_value.length - old_value.length;
     var part_1 = this.orginal_text.substring(0, offset),
         part_2 = this.orginal_text.substring(offset+old_value.length),
         add_2_offset = new_value.length - old_value.length;
@@ -357,18 +402,20 @@ this.saveOldValue = function(elm, old_value) {
     elm.old_value = old_value;
 };
 
     elm.old_value = old_value;
 };
 
-this.createListSeparator = function() {
+this.createListSeparator = function()
+{
     var td = document.createElement('td'),
         tr = document.createElement('tr');
 
     $(td).html(' ').attr('googie_action_btn', '1')
     var td = document.createElement('td'),
         tr = document.createElement('tr');
 
     $(td).html(' ').attr('googie_action_btn', '1')
-       .css({'cursor': 'default', 'font-size': '3px', 'border-top': '1px solid #ccc', 'padding-top': '3px'});
+           .css({'cursor': 'default', 'font-size': '3px', 'border-top': '1px solid #ccc', 'padding-top': '3px'});
     tr.appendChild(td);
 
     return tr;
 };
 
     tr.appendChild(td);
 
     return tr;
 };
 
-this.correctError = function(id, elm, l_elm, rm_pre_space) {
+this.correctError = function(id, elm, l_elm, rm_pre_space)
+{
     var old_value = elm.innerHTML,
         new_value = l_elm.nodeType == 3 ? l_elm.nodeValue : l_elm.innerHTML,
         offset = this.results[id]['attrs']['o'];
     var old_value = elm.innerHTML,
         new_value = l_elm.nodeType == 3 ? l_elm.nodeValue : l_elm.innerHTML,
         offset = this.results[id]['attrs']['o'];
@@ -393,7 +440,15 @@ this.correctError = function(id, elm, l_elm, rm_pre_space) {
     this.errorFixed();
 };
 
     this.errorFixed();
 };
 
-this.showErrorWindow = function(elm, id) {
+this.ignoreError = function(elm, id)
+{
+    // @TODO: ignore all same words
+    $(elm).removeAttr('class').css('color', '').unbind();
+    this.hideErrorWindow();
+};
+
+this.showErrorWindow = function(elm, id)
+{
     if (this.show_menu_observer)
         this.show_menu_observer(this);
 
     if (this.show_menu_observer)
         this.show_menu_observer(this);
 
@@ -414,6 +469,7 @@ this.showErrorWindow = function(elm, id) {
             break;
         }
     }
             break;
         }
     }
+
     if (!changed) {
         // Build up the result list
         var suggestions = this.results[id]['suggestions'],
     if (!changed) {
         // Build up the result list
         var suggestions = this.results[id]['suggestions'],
@@ -421,6 +477,26 @@ this.showErrorWindow = function(elm, id) {
             len = this.results[id]['attrs']['l'],
             row, item, dummy;
 
             len = this.results[id]['attrs']['l'],
             row, item, dummy;
 
+        // [Add to dictionary] button
+        if (this.has_dictionary && !$(elm).attr('is_corrected')) {
+            row = document.createElement('tr'),
+            item = document.createElement('td'),
+            dummy = document.createElement('span');
+
+            $(dummy).text(this.lang_learn_word);
+            $(item).attr('googie_action_btn', '1').css('cursor', 'default')
+                .mouseover(ref.item_onmouseover)
+                .mouseout(ref.item_onmouseout)
+                           .click(function(e) {
+                               ref.learnWord(elm, id);
+                               ref.ignoreError(elm, id);
+                           });
+
+            item.appendChild(dummy);
+            row.appendChild(item);
+            list.appendChild(row);
+        }
+/*
         if (suggestions.length == 0) {
             row = document.createElement('tr'),
             item = document.createElement('td'),
         if (suggestions.length == 0) {
             row = document.createElement('tr'),
             item = document.createElement('td'),
@@ -433,7 +509,7 @@ this.showErrorWindow = function(elm, id) {
             row.appendChild(item);
             list.appendChild(row);
         }
             row.appendChild(item);
             list.appendChild(row);
         }
-
+*/
         for (var i=0, len=suggestions.length; i < len; i++) {
             row = document.createElement('tr'),
             item = document.createElement('td'),
         for (var i=0, len=suggestions.length; i < len; i++) {
             row = document.createElement('tr'),
             item = document.createElement('td'),
@@ -441,16 +517,15 @@ this.showErrorWindow = function(elm, id) {
 
             $(dummy).html(suggestions[i]);
 
 
             $(dummy).html(suggestions[i]);
 
-            $(item).bind('mouseover', this.item_onmouseover)
-                   .bind('mouseout', this.item_onmouseout)
-                   .bind('click', function(e) { ref.correctError(id, elm, e.target.firstChild) });
+            $(item).mouseover(this.item_onmouseover).mouseout(this.item_onmouseout)
+                   .click(function(e) { ref.correctError(id, elm, e.target.firstChild) });
 
             item.appendChild(dummy);
             row.appendChild(item);
             list.appendChild(row);
         }
 
 
             item.appendChild(dummy);
             row.appendChild(item);
             list.appendChild(row);
         }
 
-        //The element is changed, append the revert
+        // The element is changed, append the revert
         if (elm.is_changed && elm.innerHTML != elm.old_value) {
             var old_value = elm.old_value,
                 revert_row = document.createElement('tr'),
         if (elm.is_changed && elm.innerHTML != elm.old_value) {
             var old_value = elm.old_value,
                 revert_row = document.createElement('tr'),
@@ -459,11 +534,10 @@ this.showErrorWindow = function(elm, id) {
 
                $(rev_span).addClass('googie_list_revert').html(this.lang_revert + ' ' + old_value);
 
 
                $(rev_span).addClass('googie_list_revert').html(this.lang_revert + ' ' + old_value);
 
-            $(revert).bind('mouseover', this.item_onmouseover)
-                   .bind('mouseout', this.item_onmouseout)
-                   .bind('click', function(e) {
+            $(revert).mouseover(this.item_onmouseover).mouseout(this.item_onmouseout)
+                   .click(function(e) {
                    ref.updateOrginalText(offset, elm.innerHTML, old_value, id);
                    ref.updateOrginalText(offset, elm.innerHTML, old_value, id);
-                   $(elm).attr('is_corrected', true).css('color', '#b91414').html(old_value);
+                   $(elm).removeAttr('is_corrected').css('color', '#b91414').html(old_value);
                    ref.hideErrorWindow();
                    });
 
                    ref.hideErrorWindow();
                    });
 
@@ -498,11 +572,11 @@ this.showErrorWindow = function(elm, id) {
            $(ok_pic).attr('src', this.img_dir + 'ok.gif')
                .width(32).height(16)
            .css({'cursor': 'pointer', 'margin-left': '2px', 'margin-right': '2px'})
            $(ok_pic).attr('src', this.img_dir + 'ok.gif')
                .width(32).height(16)
            .css({'cursor': 'pointer', 'margin-left': '2px', 'margin-right': '2px'})
-               .bind('click', onsub);
+               .click(onsub);
 
         $(edit_form).attr('googie_action_btn', '1')
                .css({'margin': 0, 'padding': 0, 'cursor': 'default', 'white-space': 'nowrap'})
 
         $(edit_form).attr('googie_action_btn', '1')
                .css({'margin': 0, 'padding': 0, 'cursor': 'default', 'white-space': 'nowrap'})
-               .bind('submit', onsub);
+               .submit(onsub);
 
            edit_form.appendChild(edit_input);
            edit_form.appendChild(ok_pic);
 
            edit_form.appendChild(edit_input);
            edit_form.appendChild(ok_pic);
@@ -523,9 +597,9 @@ this.showErrorWindow = function(elm, id) {
                       e_col = document.createElement('td');
 
                                $(e_col).html(e_elm[0])
                       e_col = document.createElement('td');
 
                                $(e_col).html(e_elm[0])
-                        .bind('mouseover', ref.item_onmouseover)
-                       .bind('mouseout', ref.item_onmouseout)
-                                   .bind('click', function() { return e_elm[1](elm, ref) });
+                        .mouseover(ref.item_onmouseover)
+                       .mouseout(ref.item_onmouseout)
+                                   .click(function() { return e_elm[1](elm, ref) });
 
                                e_row.appendChild(e_col);
                     list.appendChild(e_row);
 
                                e_row.appendChild(e_col);
                     list.appendChild(e_row);
@@ -575,7 +649,8 @@ this.showErrorWindow = function(elm, id) {
 //////
 // Edit layer (the layer where the suggestions are stored)
 //////
 //////
 // Edit layer (the layer where the suggestions are stored)
 //////
-this.createEditLayer = function(width, height) {
+this.createEditLayer = function(width, height)
+{
     this.edit_layer = document.createElement('div');
     $(this.edit_layer).addClass('googie_edit_layer').attr('id', 'googie_edit_layer')
         .width('auto').height(height);
     this.edit_layer = document.createElement('div');
     $(this.edit_layer).addClass('googie_edit_layer').attr('id', 'googie_edit_layer')
         .width('auto').height(height);
@@ -603,7 +678,8 @@ this.createEditLayer = function(width, height) {
     }
 };
 
     }
 };
 
-this.resumeEditing = function() {
+this.resumeEditing = function()
+{
     this.setStateChanged('ready');
 
     if (this.edit_layer)
     this.setStateChanged('ready');
 
     if (this.edit_layer)
@@ -629,7 +705,8 @@ this.resumeEditing = function() {
     this.checkSpellingState(false);
 };
 
     this.checkSpellingState(false);
 };
 
-this.createErrorLink = function(text, id) {
+this.createErrorLink = function(text, id)
+{
     var elm = document.createElement('span'),
         ref = this,
         d = function (e) {
     var elm = document.createElement('span'),
         ref = this,
         d = function (e) {
@@ -638,13 +715,14 @@ this.createErrorLink = function(text, id) {
            return false;
         };
 
            return false;
         };
 
-    $(elm).html(text).addClass('googie_link').bind('click', d)
-           .attr({'googie_action_btn' : '1', 'g_id' : id, 'is_corrected' : false});
+    $(elm).html(text).addClass('googie_link').click(d).removeAttr('is_corrected')
+           .attr({'googie_action_btn' : '1', 'g_id' : id});
 
     return elm;
 };
 
 
     return elm;
 };
 
-this.createPart = function(txt_part) {
+this.createPart = function(txt_part)
+{
     if (txt_part == " ")
         return document.createTextNode(" ");
 
     if (txt_part == " ")
         return document.createTextNode(" ");
 
@@ -659,7 +737,8 @@ this.createPart = function(txt_part) {
     return span;
 };
 
     return span;
 };
 
-this.showErrorsInIframe = function() {
+this.showErrorsInIframe = function()
+{
     var output = document.createElement('div'),
         pointer = 0,
         results = this.results;
     var output = document.createElement('div'),
         pointer = 0,
         results = this.results;
@@ -717,7 +796,8 @@ this.showErrorsInIframe = function() {
 //////
 // Choose language menu
 //////
 //////
 // Choose language menu
 //////
-this.createLangWindow = function() {
+this.createLangWindow = function()
+{
     this.language_window = document.createElement('div');
     $(this.language_window).addClass('googie_window popupmenu')
            .width(100).attr('googie_action_btn', '1');
     this.language_window = document.createElement('div');
     $(this.language_window).addClass('googie_window popupmenu')
            .width(100).attr('googie_action_btn', '1');
@@ -776,16 +856,19 @@ this.createLangWindow = function() {
     this.language_window.appendChild(table);
 };
 
     this.language_window.appendChild(table);
 };
 
-this.isLangWindowShown = function() {
+this.isLangWindowShown = function()
+{
     return $(this.language_window).is(':visible');
 };
 
     return $(this.language_window).is(':visible');
 };
 
-this.hideLangWindow = function() {
+this.hideLangWindow = function()
+{
     $(this.language_window).hide();
     $(this.switch_lan_pic).removeClass().addClass('googie_lang_3d_on');
 };
 
     $(this.language_window).hide();
     $(this.switch_lan_pic).removeClass().addClass('googie_lang_3d_on');
 };
 
-this.showLangWindow = function(elm) {
+this.showLangWindow = function(elm)
+{
     if (this.show_menu_observer)
         this.show_menu_observer(this);
 
     if (this.show_menu_observer)
         this.show_menu_observer(this);
 
@@ -806,11 +889,13 @@ this.showLangWindow = function(elm) {
     this.highlightCurSel();
 };
 
     this.highlightCurSel();
 };
 
-this.deHighlightCurSel = function() {
+this.deHighlightCurSel = function()
+{
     $(this.lang_cur_elm).removeClass().addClass('googie_list_onout');
 };
 
     $(this.lang_cur_elm).removeClass().addClass('googie_list_onout');
 };
 
-this.highlightCurSel = function() {
+this.highlightCurSel = function()
+{
     if (GOOGIE_CUR_LANG == null)
         GOOGIE_CUR_LANG = GOOGIE_DEFAULT_LANG;
     for (var i=0; i < this.lang_elms.length; i++) {
     if (GOOGIE_CUR_LANG == null)
         GOOGIE_CUR_LANG = GOOGIE_DEFAULT_LANG;
     for (var i=0; i < this.lang_elms.length; i++) {
@@ -824,7 +909,8 @@ this.highlightCurSel = function() {
     }
 };
 
     }
 };
 
-this.createChangeLangPic = function() {
+this.createChangeLangPic = function()
+{
     var img = $('<img>')
            .attr({src: this.img_dir + 'change_lang.gif', 'alt': 'Change language', 'googie_action_btn': '1'}),
         switch_lan = document.createElement('span');
     var img = $('<img>')
            .attr({src: this.img_dir + 'change_lang.gif', 'alt': 'Change language', 'googie_action_btn': '1'}),
         switch_lan = document.createElement('span');
@@ -847,7 +933,8 @@ this.createChangeLangPic = function() {
     return switch_lan;
 };
 
     return switch_lan;
 };
 
-this.createSpellDiv = function() {
+this.createSpellDiv = function()
+{
     var span = document.createElement('span');
 
     $(span).addClass('googie_check_spelling_link').text(this.lang_chck_spell);
     var span = document.createElement('span');
 
     $(span).addClass('googie_check_spelling_link').text(this.lang_chck_spell);
@@ -862,7 +949,8 @@ this.createSpellDiv = function() {
 //////
 // State functions
 /////
 //////
 // State functions
 /////
-this.flashNoSpellingErrorState = function(on_finish) {
+this.flashNoSpellingErrorState = function(on_finish)
+{
     this.setStateChanged('no_error_found');
 
     var ref = this;
     this.setStateChanged('no_error_found');
 
     var ref = this;
@@ -888,7 +976,8 @@ this.flashNoSpellingErrorState = function(on_finish) {
     }
 };
 
     }
 };
 
-this.resumeEditingState = function() {
+this.resumeEditingState = function()
+{
     this.setStateChanged('resume_editing');
 
     //Change link text to resume
     this.setStateChanged('resume_editing');
 
     //Change link text to resume
@@ -906,7 +995,8 @@ this.resumeEditingState = function() {
     catch (e) {};
 };
 
     catch (e) {};
 };
 
-this.checkSpellingState = function(fire) {
+this.checkSpellingState = function(fire)
+{
     if (fire)
         this.setStateChanged('ready');
 
     if (fire)
         this.setStateChanged('ready');
 
@@ -939,12 +1029,14 @@ this.checkSpellingState = function(fire) {
 //////
 // Misc. functions
 /////
 //////
 // Misc. functions
 /////
-this.isDefined = function(o) {
+this.isDefined = function(o)
+{
     return (o !== undefined && o !== null)
 };
 
     return (o !== undefined && o !== null)
 };
 
-this.errorFixed = function() { 
-    this.cnt_errors_fixed++; 
+this.errorFixed = function()
+{
+    this.cnt_errors_fixed++;
     if (this.all_errors_fixed_observer)
         if (this.cnt_errors_fixed == this.cnt_errors) {
             this.hideErrorWindow();
     if (this.all_errors_fixed_observer)
         if (this.cnt_errors_fixed == this.cnt_errors) {
             this.hideErrorWindow();
@@ -952,15 +1044,18 @@ this.errorFixed = function() {
         }
 };
 
         }
 };
 
-this.errorFound = function() {
+this.errorFound = function()
+{
     this.cnt_errors++;
 };
 
     this.cnt_errors++;
 };
 
-this.createCloseButton = function(c_fn) {
+this.createCloseButton = function(c_fn)
+{
     return this.createButton(this.lang_close, 'googie_list_close', c_fn);
 };
 
     return this.createButton(this.lang_close, 'googie_list_close', c_fn);
 };
 
-this.createButton = function(name, css_class, c_fn) {
+this.createButton = function(name, css_class, c_fn)
+{
     var btn_row = document.createElement('tr'),
         btn = document.createElement('td'),
         spn_btn;
     var btn_row = document.createElement('tr'),
         btn = document.createElement('td'),
         spn_btn;
@@ -982,14 +1077,16 @@ this.createButton = function(name, css_class, c_fn) {
     return btn_row;
 };
 
     return btn_row;
 };
 
-this.removeIndicator = function(elm) {
+this.removeIndicator = function(elm)
+{
     //$(this.indicator).remove();
     // roundcube mod.
     if (window.rcmail)
         rcmail.set_busy(false, null, this.rc_msg_id);
 };
 
     //$(this.indicator).remove();
     // roundcube mod.
     if (window.rcmail)
         rcmail.set_busy(false, null, this.rc_msg_id);
 };
 
-this.appendIndicator = function(elm) {
+this.appendIndicator = function(elm)
+{
     // modified by roundcube
     if (window.rcmail)
            this.rc_msg_id = rcmail.set_busy(true, 'checking');
     // modified by roundcube
     if (window.rcmail)
            this.rc_msg_id = rcmail.set_busy(true, 'checking');
@@ -1005,19 +1102,23 @@ this.appendIndicator = function(elm) {
 */
 }
 
 */
 }
 
-this.createFocusLink = function(name) {
+this.createFocusLink = function(name)
+{
     var link = document.createElement('a');
     $(link).attr({'href': 'javascript:;', 'name': name});
     return link;
 };
 
     var link = document.createElement('a');
     $(link).attr({'href': 'javascript:;', 'name': name});
     return link;
 };
 
-this.item_onmouseover = function(e) {
+this.item_onmouseover = function(e)
+{
     if (this.className != 'googie_list_revert' && this.className != 'googie_list_close')
         this.className = 'googie_list_onhover';
     else
         this.parentNode.className = 'googie_list_onhover';
 };
     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(e) {
+
+this.item_onmouseout = function(e)
+{
     if (this.className != 'googie_list_revert' && this.className != 'googie_list_close')
         this.className = 'googie_list_onout';
     else
     if (this.className != 'googie_list_revert' && this.className != 'googie_list_close')
         this.className = 'googie_list_onout';
     else
index 1e326e27426058d3e1eeb8f7991ba6b93a99f3d3..5116df78b21ad40da321c2e59c88935530df1406 100644 (file)
@@ -1,39 +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=!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;for(a=0,b=c.length;a<b;a++)this.init_row(c[a]),this.rowcount++;this.init_header();this.frame=this.list.parentNode;this.keyboard&&(rcube_event.add_listener({event:bw.opera?"keypress":"keydown",object:this,method:"key_press"}),rcube_event.add_listener({event:"keydown",object:this,method:"key_down"}))}},init_row:function(a){if(a&&String(a.id).match(/^rcmrow([a-z0-9\-_=\+\/]+)/i)){var b=
-this,c=RegExp.$1;a.uid=c;this.rows[c]={uid:c,id:a.id,obj:a};a.onmousedown=function(a){return b.drag_row(a,this.uid)};a.onmouseup=function(a){return b.click_row(a,this.uid)};if(bw.iphone||bw.ipad)a.addEventListener("touchstart",function(a){a.touches.length==1&&(b.drag_row(rcube_event.touchevent(a.touches[0]),this.uid)||a.preventDefault())},!1),a.addEventListener("touchend",function(a){a.changedTouches.length==1&&(b.click_row(rcube_event.touchevent(a.changedTouches[0]),this.uid)||a.preventDefault())},
+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.modkey=0;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=!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&&"object"===typeof b)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;for(a=0,b=c.length;a<b;a++)this.init_row(c[a]),this.rowcount++;this.init_header();this.frame=this.list.parentNode;this.keyboard&&(rcube_event.add_listener({event:bw.opera?"keypress":"keydown",object:this,method:"key_press"}),rcube_event.add_listener({event:"keydown",object:this,method:"key_down"}))}},init_row:function(a){if(a&&(""+a.id).match(/^rcmrow([a-z0-9\-_=\+\/]+)/i)){var b=
+this,c=RegExp.$1;a.uid=c;this.rows[c]={uid:c,id:a.id,obj:a};a.onmousedown=function(a){return b.drag_row(a,this.uid)};a.onmouseup=function(a){return b.click_row(a,this.uid)};if(bw.iphone||bw.ipad)a.addEventListener("touchstart",function(a){1==a.touches.length&&(b.drag_row(rcube_event.touchevent(a.touches[0]),this.uid)||a.preventDefault())},!1),a.addEventListener("touchend",function(a){1==a.changedTouches.length&&(b.click_row(rcube_event.touchevent(a.changedTouches[0]),this.uid)||a.preventDefault())},
 !1);if(document.all)a.onselectstart=function(){return!1};this.row_init(this.rows[c])}},init_header:function(){if(this.list&&this.list.tHead){this.colcount=0;var a,b,c=this;if(this.column_movable&&this.list.tHead&&this.list.tHead.rows)for(b=0;b<this.list.tHead.rows[0].cells.length;b++)if(this.column_fixed!=b)a=this.list.tHead.rows[0].cells[b],a.onmousedown=function(a){return c.drag_column(a,this)},this.colcount++}},clear:function(a){this.list.insertBefore(document.createElement("tbody"),this.list.tBodies[0]);
 this.list.removeChild(this.list.tBodies[1]);this.rows=[];this.rowcount=0;a&&this.clear_selection();if(this.frame)this.frame.scrollTop=0},remove_row:function(a,b){if(this.rows[a].obj)this.rows[a].obj.style.display="none";b&&this.select_next();delete this.rows[a];this.rowcount--},insert_row:function(a,b){var c=this.list.tBodies[0];b&&c.rows.length?c.insertBefore(a,c.firstChild):c.appendChild(a);this.init_row(a);this.rowcount++},focus:function(a){var b,c;this.focused=!0;for(b in this.selection)c=this.selection[b],
 !1);if(document.all)a.onselectstart=function(){return!1};this.row_init(this.rows[c])}},init_header:function(){if(this.list&&this.list.tHead){this.colcount=0;var a,b,c=this;if(this.column_movable&&this.list.tHead&&this.list.tHead.rows)for(b=0;b<this.list.tHead.rows[0].cells.length;b++)if(this.column_fixed!=b)a=this.list.tHead.rows[0].cells[b],a.onmousedown=function(a){return c.drag_column(a,this)},this.colcount++}},clear:function(a){this.list.insertBefore(document.createElement("tbody"),this.list.tBodies[0]);
 this.list.removeChild(this.list.tBodies[1]);this.rows=[];this.rowcount=0;a&&this.clear_selection();if(this.frame)this.frame.scrollTop=0},remove_row:function(a,b){if(this.rows[a].obj)this.rows[a].obj.style.display="none";b&&this.select_next();delete this.rows[a];this.rowcount--},insert_row:function(a,b){var c=this.list.tBodies[0];b&&c.rows.length?c.insertBefore(a,c.firstChild):c.appendChild(a);this.init_row(a);this.rowcount++},focus:function(a){var b,c;this.focused=!0;for(b in this.selection)c=this.selection[b],
-this.rows[c]&&this.rows[c].obj&&$(this.rows[c].obj).addClass("selected").removeClass("unfocused");$("*:focus",window).blur();$("iframe").each(function(){this.blur()});(a||(a=window.event))&&rcube_event.cancel(a)},blur:function(){var a,b;this.focused=!1;for(a in this.selection)b=this.selection[a],this.rows[b]&&this.rows[b].obj&&$(this.rows[b].obj).removeClass("selected").addClass("unfocused")},drag_column:function(a,b){if(this.colcount>1){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<this.list.tHead.rows[0].cells.length;c++)if(b==this.list.tHead.rows[0].cells[c]){this.selected_column=c;break}}return!1},drag_row:function(a,b){var c=rcube_event.get_target(a),d=c.tagName.toLowerCase();if(this.dont_select||c&&(d=="input"||d=="img"))return!0;if(rcube_event.get_button(a)==2)return!0;
-this.in_selection_before=this.in_selection(b)?b:!1;this.in_selection_before||(c=rcube_event.get_modifier(a),this.select_row(b,c,!1));if(this.draggable&&this.selection.length){this.drag_start=!0;this.drag_mouse_start=rcube_event.get_mouse_pos(a);rcube_event.add_listener({event:"mousemove",object:this,method:"drag_mouse_move"});rcube_event.add_listener({event:"mouseup",object:this,method:"drag_mouse_up"});if(bw.iphone||bw.ipad)rcube_event.add_listener({event:"touchmove",object:this,method:"drag_mouse_move"}),
-rcube_event.add_listener({event:"touchend",object:this,method:"drag_mouse_up"});this.add_dragfix()}return!1},click_row:function(a,b){var c=(new Date).getTime(),d=rcube_event.get_modifier(a),e=rcube_event.get_target(a),f=e.tagName.toLowerCase();if(e&&(f=="input"||f=="img"))return!0;if(this.dont_select)return this.dont_select=!1;e=c-this.rows[b].clicked<this.dblclick_time;!this.drag_active&&this.in_selection_before==b&&!e&&this.select_row(b,d,!1);this.in_selection_before=this.drag_start=!1;this.rows&&
-e&&this.in_selection(b)?this.triggerEvent("dblclick"):this.triggerEvent("click");this.drag_active||(this.del_dragfix(),rcube_event.cancel(a));this.rows[b].clicked=c;return!1},find_root:function(a){var b=this.rows[a];return b&&b.parent_uid?this.find_root(b.parent_uid):a},expand_row:function(a,b){var c=this.rows[b],d=rcube_event.get_target(a),e=rcube_event.get_modifier(a);this.dont_select=!0;c.clicked=0;c.expanded?(d.className="collapsed",e==CONTROL_KEY||this.multiexpand?this.collapse_all(c):this.collapse(c)):
-(d.className="expanded",e==CONTROL_KEY||this.multiexpand?this.expand_all(c):this.expand(c))},collapse:function(a){a.expanded=!1;this.triggerEvent("expandcollapse",{uid:a.uid,expanded:a.expanded});for(var b=a.depth,a=a?a.obj.nextSibling:null,c;a;){if(a.nodeType==1){if((c=this.rows[a.uid])&&c.depth<=b)break;$(a).css("display","none");if(c.expanded)c.expanded=!1,this.triggerEvent("expandcollapse",{uid:c.uid,expanded:c.expanded})}a=a.nextSibling}return!1},expand:function(a){var b,c,d,e,f;a?(a.expanded=
-!0,d=a.depth,e=a.obj.nextSibling,this.update_expando(a.uid,!0),this.triggerEvent("expandcollapse",{uid:a.uid,expanded:a.expanded})):(e=this.list.tBodies[0].firstChild,f=d=0);for(;e;){if(e.nodeType==1&&(b=this.rows[e.uid])){if(a&&(!b.depth||b.depth<=d))break;if(b.parent_uid)if((c=this.rows[b.parent_uid])&&c.expanded){if(a&&c==a||f>=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;for(a=0,b=c.length-1;a<b;a++)if(c[a].id&&String(c[a].id).match(/^rcmrow([a-z0-9\-_=\+\/]+)/i)&&this.rows[RegExp.$1]!=null)return RegExp.$1}return null},get_last_row:function(){if(this.rowcount){var a,b=this.list.tBodies[0].rows;for(a=b.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=d<e?d:e,d=d>e?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.shiftkey=!1,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(c<Number(this.frame.scrollTop))this.frame.scrollTop=c;else if(c+Number(b.offsetHeight)>Number(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=$("<div>").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;c<this.selection.length;c++){if(c>12){this.draglayer.append("...");break}if(e=this.rows[this.selection[c]].obj)for(b=
-0,d=0;d<e.childNodes.length;d++)if(e.childNodes[d].nodeName=="TD"){if(c==0)this.drag_start_pos=$(e.childNodes[d]).offset();if(this.subject_col<0||this.subject_col>=0&&this.subject_col==b){for(var f,g,h=e.childNodes[d].childNodes,b=0;b<h.length;b++)if((g=e.childNodes[d].childNodes[b])&&(g.nodeType==3||g.nodeName=="A"))f=g;if(!f)break;d=$(f).text();d=$.trim(d);d=d.length>50?d.substring(0,50)+"...":d;this.draglayer.append($("<div>").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=$("<div>").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($("<div>").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<c.length;b++)this.cols[b]=c[b].offsetWidth,this.column_fixed!==null&&b<=this.column_fixed&&(this.list_min_pos+=this.cols[b])}this.col_draglayer.show();this.col_drag_active=!0;this.triggerEvent("column_dragstart")}if(this.col_drag_active&&this.col_draglayer){var c=0,d=rcube_event.get_mouse_pos(a);for(b=
-0;b<this.cols.length;b++)if(d.x>=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.length;b++)if(d.x>=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(){$('<div class="iframe-dragdrop-fix"></div>').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);for(r=0,c=this.list.tBodies[0].rows.length;r<c;r++)row=this.list.tBodies[0].rows[r],d=row.cells[a],e=row.cells[b],f=document.createElement("td"),e?row.insertBefore(f,e):row.appendChild(f),row.replaceChild(d,f);this.subject_col==a?this.subject_col=b>a?b-1:b:this.subject_col<a&&b<=this.subject_col?this.subject_col++:this.subject_col>a&&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;
+this.rows[c]&&this.rows[c].obj&&$(this.rows[c].obj).addClass("selected").removeClass("unfocused");$("*:focus",window).blur();$("iframe").each(function(){this.blur()});(a||(a=window.event))&&rcube_event.cancel(a)},blur:function(){var a,b;this.focused=!1;for(a in this.selection)b=this.selection[a],this.rows[b]&&this.rows[b].obj&&$(this.rows[b].obj).removeClass("selected").addClass("unfocused")},drag_column:function(a,b){if(1<this.colcount){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<this.list.tHead.rows[0].cells.length;c++)if(b==this.list.tHead.rows[0].cells[c]){this.selected_column=c;break}}return!1},drag_row:function(a,b){var c=rcube_event.get_target(a),d=c.tagName.toLowerCase();if(this.dont_select||c&&("input"==d||"img"==d)||2==rcube_event.get_button(a))return!0;this.in_selection_before=
+this.in_selection(b)?b:!1;this.in_selection_before||(c=rcube_event.get_modifier(a),this.select_row(b,c,!1));if(this.draggable&&this.selection.length){this.drag_start=!0;this.drag_mouse_start=rcube_event.get_mouse_pos(a);rcube_event.add_listener({event:"mousemove",object:this,method:"drag_mouse_move"});rcube_event.add_listener({event:"mouseup",object:this,method:"drag_mouse_up"});if(bw.iphone||bw.ipad)rcube_event.add_listener({event:"touchmove",object:this,method:"drag_mouse_move"}),rcube_event.add_listener({event:"touchend",
+object:this,method:"drag_mouse_up"});this.add_dragfix()}return!1},click_row:function(a,b){var c=(new Date).getTime(),d=rcube_event.get_modifier(a),e=rcube_event.get_target(a),f=e.tagName.toLowerCase();if(e&&("input"==f||"img"==f))return!0;if(this.dont_select)return this.dont_select=!1;e=c-this.rows[b].clicked<this.dblclick_time;!this.drag_active&&this.in_selection_before==b&&!e&&this.select_row(b,d,!1);this.in_selection_before=this.drag_start=!1;this.rows&&e&&this.in_selection(b)?this.triggerEvent("dblclick"):
+this.triggerEvent("click");this.drag_active||(this.del_dragfix(),rcube_event.cancel(a));this.rows[b].clicked=c;return!1},find_root:function(a){var b=this.rows[a];return b&&b.parent_uid?this.find_root(b.parent_uid):a},expand_row:function(a,b){var c=this.rows[b],d=rcube_event.get_target(a),e=rcube_event.get_modifier(a);this.dont_select=!0;c.clicked=0;c.expanded?(d.className="collapsed",e==CONTROL_KEY||this.multiexpand?this.collapse_all(c):this.collapse(c)):(d.className="expanded",e==CONTROL_KEY||this.multiexpand?
+this.expand_all(c):this.expand(c))},collapse:function(a){a.expanded=!1;this.triggerEvent("expandcollapse",{uid:a.uid,expanded:a.expanded});for(var b=a.depth,a=a?a.obj.nextSibling:null,c;a;){if(1==a.nodeType){if((c=this.rows[a.uid])&&c.depth<=b)break;$(a).css("display","none");if(c.expanded)c.expanded=!1,this.triggerEvent("expandcollapse",{uid:c.uid,expanded:c.expanded})}a=a.nextSibling}return!1},expand:function(a){var b,c,d,e,f;a?(a.expanded=!0,d=a.depth,e=a.obj.nextSibling,this.update_expando(a.uid,
+!0),this.triggerEvent("expandcollapse",{uid:a.uid,expanded:a.expanded})):(e=this.list.tBodies[0].firstChild,f=d=0);for(;e;){if(1==e.nodeType&&(b=this.rows[e.uid])){if(a&&(!b.depth||b.depth<=d))break;if(b.parent_uid)if((c=this.rows[b.parent_uid])&&c.expanded){if(a&&c==a||f>=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(1==c.nodeType&&(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(1==c.nodeType&&(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&&(1!=a.nodeType||"none"==a.style.display);)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&&(1!=a.nodeType||"none"==a.style.display);)a=a.previousSibling;return a},get_first_row:function(){if(this.rowcount){var a,b,c=this.list.tBodies[0].rows;
+for(a=0,b=c.length-1;a<b;a++)if(c[a].id&&(""+c[a].id).match(/^rcmrow([a-z0-9\-_=\+\/]+)/i)&&null!=this.rows[RegExp.$1])return RegExp.$1}return null},get_last_row:function(){if(this.rowcount){var a,b=this.list.tBodies[0].rows;for(a=b.length-1;0<=a;a--)if(b[a].id&&(""+b[a].id).match(/^rcmrow([a-z0-9\-_=\+\/]+)/i)&&null!=this.rows[RegExp.$1])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");0!=this.last_selected&&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(1==a.nodeType&&(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=d<e?d:e,d=d>e?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||!0==this.rows[b][a]?(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 1==this.selection.length?this.selection[0]:null},highlight_row:function(a,b){if(this.rows[a]&&!b){if(1<this.selection.length||!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){var b=a.target||{};if(!0!=this.focused||"INPUT"==b.nodeName||"TEXTAREA"==b.nodeName||"SELECT"==b.nodeName)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.modkey=c,this.triggerEvent("keypress"),this.modkey=0,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.key_pressed=b,this.modkey=c,this.triggerEvent("keypress"),this.modkey=0,this.key_pressed==this.BACKSPACE_KEY)return rcube_event.cancel(a)}return!0},key_down:function(a){var b=
+a.target||{};if(!0!=this.focused||"INPUT"==b.nodeName||"TEXTAREA"==b.nodeName||"SELECT"==b.nodeName)return!0;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(40==a||63233==a)c=this.get_next_row();
+else if(38==a||63232==a)c=this.get_prev_row();c&&(this.select_row(c.uid,b,!1),this.scrollto(c.uid));return!1},use_plusminus_key:function(a,b){var c=this.rows[this.last_selected];if(c)return 32==a&&(a=c.expanded?109:61),61==a||107==a?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(c<Number(this.frame.scrollTop))this.frame.scrollTop=c;else if(c+Number(b.offsetHeight)>Number(this.frame.scrollTop)+Number(this.frame.offsetHeight))this.frame.scrollTop=c+Number(b.offsetHeight)-Number(this.frame.offsetHeight)}},drag_mouse_move:function(a){if("touchmove"==a.type)if(1==a.changedTouches.length)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||3>Math.abs(b.x-this.drag_mouse_start.x)&&3>Math.abs(b.y-this.drag_mouse_start.y))return!1;if(!this.draglayer)this.draglayer=$("<div>").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;c<this.selection.length;c++){if(12<
+c){this.draglayer.append("...");break}if(e=this.rows[this.selection[c]].obj)for(b=0,d=0;d<e.childNodes.length;d++)if("TD"==e.childNodes[d].nodeName){if(0==c)this.drag_start_pos=$(e.childNodes[d]).offset();if(0>this.subject_col||0<=this.subject_col&&this.subject_col==b){for(var f,g,h=e.childNodes[d].childNodes,b=0;b<h.length;b++)if((g=e.childNodes[d].childNodes[b])&&(3==g.nodeType||"A"==g.nodeName))f=g;if(!f)break;d=$(f).text();d=$.trim(d);d=50<d.length?d.substring(0,50)+"...":d;this.draglayer.append($("<div>").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("touchend"==a.type&&1!=a.changedTouches.length)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||3>Math.abs(b.x-this.drag_mouse_start.x)&&3>Math.abs(b.y-this.drag_mouse_start.y))return!1;if(!this.col_draglayer){b=$(this.list).offset();var c=this.list.tHead.rows[0].cells;this.col_draglayer=$("<div>").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($("<div>").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<c.length;b++)this.cols[b]=c[b].offsetWidth,null!==this.column_fixed&&b<=this.column_fixed&&(this.list_min_pos+=this.cols[b])}this.col_draglayer.show();this.col_drag_active=
+!0;this.triggerEvent("column_dragstart")}if(this.col_drag_active&&this.col_draglayer){var c=0,d=rcube_event.get_mouse_pos(a);for(b=0;b<this.cols.length;b++)if(d.x>=this.cols[b]/2+this.list_pos+c)c+=this.cols[b];else break;0==b&&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(null!==this.selected_column&&this.cols&&this.cols.length){var b,c=0,d=rcube_event.get_mouse_pos(a);for(b=0;b<this.cols.length;b++)if(d.x>=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(){$('<div class="iframe-dragdrop-fix"></div>').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);for(r=0,c=this.list.tBodies[0].rows.length;r<c;r++)row=this.list.tBodies[0].rows[r],d=row.cells[a],e=row.cells[b],f=document.createElement("td"),e?row.insertBefore(f,e):row.appendChild(f),row.replaceChild(d,f);this.subject_col==a?this.subject_col=b>a?b-1:b:this.subject_col<a&&b<=this.subject_col?
+this.subject_col++:this.subject_col>a&&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;
index e47b5470d6692c222a1392f0c67fc2501e7fdda0..c8864c31897f815afcfdff63d065eb23059683ee 100644 (file)
@@ -13,7 +13,7 @@
  | Requires: common.js                                                   |
  +-----------------------------------------------------------------------+
 
  | Requires: common.js                                                   |
  +-----------------------------------------------------------------------+
 
-  $Id: list.js 4750 2011-05-12 09:27:17Z alec $
+  $Id: list.js 5271 2011-09-22 20:51:42Z thomasb $
 */
 
 
 */
 
 
@@ -36,7 +36,7 @@ function rcube_list_widget(list, p)
   this.colcount = 0;
 
   this.subject_col = -1;
   this.colcount = 0;
 
   this.subject_col = -1;
-  this.shiftkey = false;
+  this.modkey = 0;
   this.multiselect = false;
   this.multiexpand = false;
   this.multi_selecting = false;
   this.multiselect = false;
   this.multiexpand = false;
   this.multi_selecting = false;
@@ -648,7 +648,7 @@ select_row: function(id, mod_key, with_mouse)
       case CONTROL_KEY:
         if (!with_mouse)
           this.highlight_row(id, true);
       case CONTROL_KEY:
         if (!with_mouse)
           this.highlight_row(id, true);
-        break; 
+        break;
 
       case CONTROL_SHIFT_KEY:
         this.shift_select(id, true);
 
       case CONTROL_SHIFT_KEY:
         this.shift_select(id, true);
@@ -954,7 +954,8 @@ highlight_row: function(id, multiple)
  */
 key_press: function(e)
 {
  */
 key_press: function(e)
 {
-  if (this.focused != true)
+  var target = e.target || {};
+  if (this.focused != true || target.nodeName == 'INPUT' || target.nodeName == 'TEXTAREA' || target.nodeName == 'SELECT')
     return true;
 
   var keyCode = rcube_event.get_keycode(e),
     return true;
 
   var keyCode = rcube_event.get_keycode(e),
@@ -962,7 +963,7 @@ key_press: function(e)
 
   switch (keyCode) {
     case 40:
 
   switch (keyCode) {
     case 40:
-    case 38: 
+    case 38:
     case 63233: // "down", in safari keypress
     case 63232: // "up", in safari keypress
       // Stop propagation so that the browser doesn't scroll
     case 63233: // "down", in safari keypress
     case 63232: // "up", in safari keypress
       // Stop propagation so that the browser doesn't scroll
@@ -976,7 +977,9 @@ key_press: function(e)
       rcube_event.cancel(e);
       var ret = this.use_plusminus_key(keyCode, mod_key);
       this.key_pressed = keyCode;
       rcube_event.cancel(e);
       var ret = this.use_plusminus_key(keyCode, mod_key);
       this.key_pressed = keyCode;
+      this.modkey = mod_key;
       this.triggerEvent('keypress');
       this.triggerEvent('keypress');
+      this.modkey = 0;
       return ret;
     case 36: // Home
       this.select_first(mod_key);
       return ret;
     case 36: // Home
       this.select_first(mod_key);
@@ -985,11 +988,10 @@ key_press: function(e)
       this.select_last(mod_key);
       return rcube_event.cancel(e);
     default:
       this.select_last(mod_key);
       return rcube_event.cancel(e);
     default:
-      this.shiftkey = e.shiftKey;
       this.key_pressed = keyCode;
       this.key_pressed = keyCode;
+      this.modkey = mod_key;
       this.triggerEvent('keypress');
       this.triggerEvent('keypress');
-      // reset shiftkey flag, we need it only for registered events
-      this.shiftkey = false;
+      this.modkey = 0;
 
       if (this.key_pressed == this.BACKSPACE_KEY)
         return rcube_event.cancel(e);
 
       if (this.key_pressed == this.BACKSPACE_KEY)
         return rcube_event.cancel(e);
@@ -1003,13 +1005,17 @@ key_press: function(e)
  */
 key_down: function(e)
 {
  */
 key_down: function(e)
 {
+  var target = e.target || {};
+  if (this.focused != true || target.nodeName == 'INPUT' || target.nodeName == 'TEXTAREA' || target.nodeName == 'SELECT')
+    return true;
+  
   switch (rcube_event.get_keycode(e)) {
     case 27:
       if (this.drag_active)
   switch (rcube_event.get_keycode(e)) {
     case 27:
       if (this.drag_active)
-           return this.drag_mouse_up(e);
+      return this.drag_mouse_up(e);
       if (this.col_drag_active) {
         this.selected_column = null;
       if (this.col_drag_active) {
         this.selected_column = null;
-           return this.column_drag_mouse_up(e);
+        return this.column_drag_mouse_up(e);
       }
 
     case 40:
       }
 
     case 40:
@@ -1044,7 +1050,7 @@ use_arrow_key: function(keyCode, mod_key)
     new_row = this.get_prev_row();
 
   if (new_row) {
     new_row = this.get_prev_row();
 
   if (new_row) {
-    this.select_row(new_row.uid, mod_key, true);
+    this.select_row(new_row.uid, mod_key, false);
     this.scrollto(new_row.uid);
   }
 
     this.scrollto(new_row.uid);
   }
 
index 1ab16055bebb5aeb88733e37bc082fa101b2d34a..9fc96eac7bb519aeb951639babf4e1e5242d721c 100644 (file)
@@ -145,7 +145,6 @@ class html2text
     var $search = array(
         "/\r/",                                  // Non-legal carriage return
         "/[\n\t]+/",                             // Newlines and tabs
     var $search = array(
         "/\r/",                                  // Non-legal carriage return
         "/[\n\t]+/",                             // Newlines and tabs
-        '/[ ]{2,}/',                             // Runs of spaces, pre-handling
         '/<script[^>]*>.*?<\/script>/i',         // <script>s -- which strip_tags supposedly has problems with
         '/<style[^>]*>.*?<\/style>/i',           // <style>s -- which strip_tags supposedly has problems with
         '/<p[^>]*>/i',                           // <P>
         '/<script[^>]*>.*?<\/script>/i',         // <script>s -- which strip_tags supposedly has problems with
         '/<style[^>]*>.*?<\/style>/i',           // <style>s -- which strip_tags supposedly has problems with
         '/<p[^>]*>/i',                           // <P>
@@ -161,22 +160,6 @@ class html2text
         '/(<table[^>]*>|<\/table>)/i',           // <table> and </table>
         '/(<tr[^>]*>|<\/tr>)/i',                 // <tr> and </tr>
         '/<td[^>]*>(.*?)<\/td>/i',               // <td> and </td>
         '/(<table[^>]*>|<\/table>)/i',           // <table> and </table>
         '/(<tr[^>]*>|<\/tr>)/i',                 // <tr> and </tr>
         '/<td[^>]*>(.*?)<\/td>/i',               // <td> and </td>
-        '/&(nbsp|#160);/i',                      // Non-breaking space
-        '/&(quot|rdquo|ldquo|#8220|#8221|#147|#148);/i',
-                                                        // Double quotes
-        '/&(apos|rsquo|lsquo|#8216|#8217);/i',   // Single quotes
-        '/&gt;/i',                               // Greater-than
-        '/&lt;/i',                               // Less-than
-        '/&(copy|#169);/i',                      // Copyright
-        '/&(trade|#8482|#153);/i',               // Trademark
-        '/&(reg|#174);/i',                       // Registered
-        '/&(mdash|#151|#8212);/i',               // mdash
-        '/&(ndash|minus|#8211|#8722);/i',        // ndash
-        '/&(bull|#149|#8226);/i',                // Bullet
-        '/&(pound|#163);/i',                     // Pound sign
-        '/&(euro|#8364);/i',                     // Euro sign
-        '/&(amp|#38);/i',                        // Ampersand: see _converter()
-        '/[ ]{2,}/'                              // Runs of spaces, post-handling
     );
 
     /**
     );
 
     /**
@@ -189,7 +172,6 @@ class html2text
     var $replace = array(
         '',                                     // Non-legal carriage return
         ' ',                                    // Newlines and tabs
     var $replace = array(
         '',                                     // Non-legal carriage return
         ' ',                                    // Newlines and tabs
-        ' ',                                    // Runs of spaces, pre-handling
         '',                                     // <script>s -- which strip_tags supposedly has problems with
         '',                                     // <style>s -- which strip_tags supposedly has problems with
         "\n\n",                                 // <P>
         '',                                     // <script>s -- which strip_tags supposedly has problems with
         '',                                     // <style>s -- which strip_tags supposedly has problems with
         "\n\n",                                 // <P>
@@ -205,6 +187,43 @@ class html2text
         "\n\n",                                 // <table> and </table>
         "\n",                                   // <tr> and </tr>
         "\t\t\\1\n",                            // <td> and </td>
         "\n\n",                                 // <table> and </table>
         "\n",                                   // <tr> and </tr>
         "\t\t\\1\n",                            // <td> and </td>
+    );
+
+    /**
+     *  List of preg* regular expression patterns to search for,
+     *  used in conjunction with $ent_replace.
+     *
+     *  @var array $ent_search
+     *  @access public
+     *  @see $ent_replace
+     */
+    var $ent_search = array(
+        '/&(nbsp|#160);/i',                      // Non-breaking space
+        '/&(quot|rdquo|ldquo|#8220|#8221|#147|#148);/i',
+                                                        // Double quotes
+        '/&(apos|rsquo|lsquo|#8216|#8217);/i',   // Single quotes
+        '/&gt;/i',                               // Greater-than
+        '/&lt;/i',                               // Less-than
+        '/&(copy|#169);/i',                      // Copyright
+        '/&(trade|#8482|#153);/i',               // Trademark
+        '/&(reg|#174);/i',                       // Registered
+        '/&(mdash|#151|#8212);/i',               // mdash
+        '/&(ndash|minus|#8211|#8722);/i',        // ndash
+        '/&(bull|#149|#8226);/i',                // Bullet
+        '/&(pound|#163);/i',                     // Pound sign
+        '/&(euro|#8364);/i',                     // Euro sign
+        '/&(amp|#38);/i',                        // Ampersand: see _converter()
+        '/[ ]{2,}/',                             // Runs of spaces, post-handling
+    );
+
+    /**
+     *  List of pattern replacements corresponding to patterns searched.
+     *
+     *  @var array $ent_replace
+     *  @access public
+     *  @see $ent_search
+     */
+    var $ent_replace = array(
         ' ',                                    // Non-breaking space
         '"',                                    // Double quotes
         "'",                                    // Single quotes
         ' ',                                    // Non-breaking space
         '"',                                    // Double quotes
         "'",                                    // Single quotes
@@ -219,7 +238,7 @@ class html2text
         '£',
         'EUR',                                  // Euro sign. \80 ?
         '|+|amp|+|',                            // Ampersand: see _converter()
         '£',
         'EUR',                                  // Euro sign. \80 ?
         '|+|amp|+|',                            // Ampersand: see _converter()
-        ' '                                     // Runs of spaces, post-handling
+        ' ',                                    // Runs of spaces, post-handling
     );
 
     /**
     );
 
     /**
@@ -303,7 +322,7 @@ class html2text
      *  @see _build_link_list()
      */
     var $_link_list = '';
      *  @see _build_link_list()
      */
     var $_link_list = '';
-    
+
     /**
      *  Number of valid links detected in the text, used for plain text
      *  display (rendered similar to footnotes).
     /**
      *  Number of valid links detected in the text, used for plain text
      *  display (rendered similar to footnotes).
@@ -314,15 +333,15 @@ class html2text
      */
     var $_link_count = 0;
 
      */
     var $_link_count = 0;
 
-    /** 
-     * Boolean flag, true if a table of link URLs should be listed after the text. 
-     *  
-     * @var boolean $_do_links 
-     * @access private 
-     * @see html2text() 
+    /**
+     * Boolean flag, true if a table of link URLs should be listed after the text.
+     *
+     * @var boolean $_do_links
+     * @access private
+     * @see html2text()
      */
     var $_do_links = true;
      */
     var $_do_links = true;
+
     /**
      *  Constructor.
      *
     /**
      *  Constructor.
      *
@@ -492,15 +511,21 @@ class html2text
         // Convert <PRE>
         $this->_convert_pre($text);
 
         // Convert <PRE>
         $this->_convert_pre($text);
 
-        // Run our defined search-and-replace
+        // Run our defined tags search-and-replace
         $text = preg_replace($this->search, $this->replace, $text);
 
         $text = preg_replace($this->search, $this->replace, $text);
 
+        // Run our defined tags search-and-replace with callback
+        $text = preg_replace_callback($this->callback_search, array('html2text', '_preg_callback'), $text);
+
+        // Strip any other HTML tags
+        $text = strip_tags($text, $this->allowed_tags);
+
+        // Run our defined entities/characters search-and-replace
+        $text = preg_replace($this->ent_search, $this->ent_replace, $text);
+
         // Replace known html entities
         $text = html_entity_decode($text, ENT_COMPAT, 'UTF-8');
 
         // Replace known html entities
         $text = html_entity_decode($text, ENT_COMPAT, 'UTF-8');
 
-        // Run our defined search-and-replace with callback
-        $text = preg_replace_callback($this->callback_search, array('html2text', '_preg_callback'), $text);
-
         // Remove unknown/unhandled entities (this cannot be done in search-and-replace block)
         $text = preg_replace('/&([a-zA-Z0-9]{2,6}|#[0-9]{2,4});/', '', $text);
 
         // Remove unknown/unhandled entities (this cannot be done in search-and-replace block)
         $text = preg_replace('/&([a-zA-Z0-9]{2,6}|#[0-9]{2,4});/', '', $text);
 
@@ -508,15 +533,12 @@ class html2text
         // This properly handles situation of "&amp;quot;" in input string
         $text = str_replace('|+|amp|+|', '&', $text);
 
         // This properly handles situation of "&amp;quot;" in input string
         $text = str_replace('|+|amp|+|', '&', $text);
 
-        // Strip any other HTML tags
-        $text = strip_tags($text, $this->allowed_tags);
-
         // Bring down number of empty lines to 2 max
         $text = preg_replace("/\n\s+\n/", "\n\n", $text);
         $text = preg_replace("/[\n]{3,}/", "\n\n", $text);
 
         // remove leading empty lines (can be produced by eg. P tag on the beginning)
         // Bring down number of empty lines to 2 max
         $text = preg_replace("/\n\s+\n/", "\n\n", $text);
         $text = preg_replace("/[\n]{3,}/", "\n\n", $text);
 
         // remove leading empty lines (can be produced by eg. P tag on the beginning)
-        $text = preg_replace('/^\n+/', '', $text);
+        $text = ltrim($text, "\n");
 
         // Wrap the text to a readable format
         // for PHP versions >= 4.0.2. Default width is 75
 
         // Wrap the text to a readable format
         // for PHP versions >= 4.0.2. Default width is 75
@@ -544,9 +566,7 @@ class html2text
            if ( !$this->_do_links )
                return $display;
 
            if ( !$this->_do_links )
                return $display;
 
-           if ( substr($link, 0, 7) == 'http://' || substr($link, 0, 8) == 'https://' ||
-            substr($link, 0, 7) == 'mailto:'
-        ) {
+           if ( preg_match('!^(https?://|mailto:)!', $link) ) {
             $this->_link_count++;
             $this->_link_list .= '[' . $this->_link_count . "] $link\n";
             $additional = ' [' . $this->_link_count . ']';
             $this->_link_count++;
             $this->_link_list .= '[' . $this->_link_count . "] $link\n";
             $additional = ' [' . $this->_link_count . ']';
index a5eeb841b880413b213a9b1d24f6103627044f1e..f8c3251ad93eb9377ceb117b02061f2e3ec0f19e 100644 (file)
 class washtml
 {
   /* Allowed HTML elements (default) */
 class washtml
 {
   /* Allowed HTML elements (default) */
-  static $html_elements = array('a', 'abbr', 'acronym', 'address', 'area', 'b', 'basefont', 'bdo', 'big', 'blockquote', 'br', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'dd', 'del', 'dfn', 'dir', 'div', 'dl', 'dt', 'em', 'fieldset', 'font', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'ins', 'label', 'legend', 'li', 'map', 'menu', 'nobr', 'ol', 'p', 'pre', 'q', 's', 'samp', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'u', 'ul', 'var', 'wbr', 'img');
-  
+  static $html_elements = array('a', 'abbr', 'acronym', 'address', 'area', 'b',
+    'basefont', 'bdo', 'big', 'blockquote', 'br', 'caption', 'center',
+    'cite', 'code', 'col', 'colgroup', 'dd', 'del', 'dfn', 'dir', 'div', 'dl',
+    'dt', 'em', 'fieldset', 'font', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i',
+    'ins', 'label', 'legend', 'li', 'map', 'menu', 'nobr', 'ol', 'p', 'pre', 'q',
+    's', 'samp', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'table',
+    'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'u', 'ul', 'var', 'wbr', 'img',
+    // form elements
+    'button', 'input', 'textarea', 'select', 'option', 'optgroup'
+  );
+
   /* Ignore these HTML tags and their content */
   static $ignore_elements = array('script', 'applet', 'embed', 'object', 'style');
   /* Ignore these HTML tags and their content */
   static $ignore_elements = array('script', 'applet', 'embed', 'object', 'style');
-  
+
   /* Allowed HTML attributes */
   /* Allowed HTML attributes */
-  static $html_attribs = array('name', 'class', 'title', 'alt', 'width', 'height', 'align', 'nowrap', 'col', 'row', 'id', 'rowspan', 'colspan', 'cellspacing', 'cellpadding', 'valign', 'bgcolor', 'color', 'border', 'bordercolorlight', 'bordercolordark', 'face', 'marginwidth', 'marginheight', 'axis', 'border', 'abbr', 'char', 'charoff', 'clear', 'compact', 'coords', 'vspace', 'hspace', 'cellborder', 'size', 'lang', 'dir');  
+  static $html_attribs = array('name', 'class', 'title', 'alt', 'width', 'height',
+    'align', 'nowrap', 'col', 'row', 'id', 'rowspan', 'colspan', 'cellspacing',
+    'cellpadding', 'valign', 'bgcolor', 'color', 'border', 'bordercolorlight',
+    'bordercolordark', 'face', 'marginwidth', 'marginheight', 'axis', 'border',
+    'abbr', 'char', 'charoff', 'clear', 'compact', 'coords', 'vspace', 'hspace',
+    'cellborder', 'size', 'lang', 'dir',
+    // attributes of form elements
+    'type', 'rows', 'cols', 'disabled', 'readonly', 'checked', 'multiple', 'value'
+  );
 
   /* Block elements which could be empty but cannot be returned in short form (<tag />) */
 
   /* Block elements which could be empty but cannot be returned in short form (<tag />) */
-  static $block_elements = array('div', 'p', 'pre', 'blockquote', 'a', 'font', 'center', 'table', 'ul', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ol', 'dl', 'strong', 'i', 'b');
-  
+  static $block_elements = array('div', 'p', 'pre', 'blockquote', 'a', 'font', 'center',
+    'table', 'ul', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ol', 'dl', 'strong', 'i', 'b', 'u');
+
   /* State for linked objects in HTML */
   public $extlinks = false;
 
   /* State for linked objects in HTML */
   public $extlinks = false;
 
@@ -100,7 +118,7 @@ class washtml
 
   /* Registered callback functions for tags */
   private $handlers = array();
 
   /* Registered callback functions for tags */
   private $handlers = array();
-  
+
   /* Allowed HTML elements */
   private $_html_elements = array();
 
   /* Allowed HTML elements */
   private $_html_elements = array();
 
@@ -112,7 +130,7 @@ class washtml
 
   /* Allowed HTML attributes */
   private $_html_attribs = array();
 
   /* Allowed HTML attributes */
   private $_html_attribs = array();
-  
+
 
   /* Constructor */
   public function __construct($p = array()) {
 
   /* Constructor */
   public function __construct($p = array()) {
@@ -123,13 +141,13 @@ class washtml
     unset($p['html_elements'], $p['html_attribs'], $p['ignore_elements'], $p['block_elements']);
     $this->config = $p + array('show_washed'=>true, 'allow_remote'=>false, 'cid_map'=>array());
   }
     unset($p['html_elements'], $p['html_attribs'], $p['ignore_elements'], $p['block_elements']);
     $this->config = $p + array('show_washed'=>true, 'allow_remote'=>false, 'cid_map'=>array());
   }
-  
+
   /* Register a callback function for a certain tag */
   public function add_callback($tagName, $callback)
   {
     $this->handlers[$tagName] = $callback;
   }
   /* Register a callback function for a certain tag */
   public function add_callback($tagName, $callback)
   {
     $this->handlers[$tagName] = $callback;
   }
-  
+
   /* Check CSS style */
   private function wash_style($style) {
     $s = '';
   /* Check CSS style */
   private function wash_style($style) {
     $s = '';
@@ -143,14 +161,14 @@ class washtml
           preg_match('/^(url\(\s*[\'"]?([^\'"\)]*)[\'"]?\s*\)'./*1,2*/
                  '|rgb\(\s*[0-9]+\s*,\s*[0-9]+\s*,\s*[0-9]+\s*\)'.
                  '|-?[0-9.]+\s*(em|ex|px|cm|mm|in|pt|pc|deg|rad|grad|ms|s|hz|khz|%)?'.
           preg_match('/^(url\(\s*[\'"]?([^\'"\)]*)[\'"]?\s*\)'./*1,2*/
                  '|rgb\(\s*[0-9]+\s*,\s*[0-9]+\s*,\s*[0-9]+\s*\)'.
                  '|-?[0-9.]+\s*(em|ex|px|cm|mm|in|pt|pc|deg|rad|grad|ms|s|hz|khz|%)?'.
-                 '|#[0-9a-f]{3,6}|[a-z0-9\-]+'.
+                 '|#[0-9a-f]{3,6}|[a-z0-9", -]+'.
                  ')\s*/i', $str, $match)) {
           if ($match[2]) {
             if (($src = $this->config['cid_map'][$match[2]])
                 || ($src = $this->config['cid_map'][$this->config['base_url'].$match[2]])) {
               $value .= ' url('.htmlspecialchars($src, ENT_QUOTES) . ')';
             }
                  ')\s*/i', $str, $match)) {
           if ($match[2]) {
             if (($src = $this->config['cid_map'][$match[2]])
                 || ($src = $this->config['cid_map'][$this->config['base_url'].$match[2]])) {
               $value .= ' url('.htmlspecialchars($src, ENT_QUOTES) . ')';
             }
-            else if (preg_match('/^(http|https|ftp):.*$/i', $match[2], $url)) {
+            else if (preg_match('!^(https?:)?//[a-z0-9/._+-]+$!i', $match[2], $url)) {
               if ($this->config['allow_remote'])
                 $value .= ' url('.htmlspecialchars($url[0], ENT_QUOTES).')';
               else
               if ($this->config['allow_remote'])
                 $value .= ' url('.htmlspecialchars($url[0], ENT_QUOTES).')';
               else
@@ -160,8 +178,9 @@ class washtml
               $value .= ' url('.htmlspecialchars($match[2], ENT_QUOTES).')';
             }
           }
               $value .= ' url('.htmlspecialchars($match[2], ENT_QUOTES).')';
             }
           }
-          else if ($match[0] != 'url' && $match[0] != 'rbg') //whitelist ?
+          else if ($match[0] != 'url' && $match[0] != 'rgb') //whitelist ?
             $value .= ' ' . $match[0];
             $value .= ' ' . $match[0];
+
           $str = substr($str, strlen($match[0]));
         }
         if ($value)
           $str = substr($str, strlen($match[0]));
         }
         if ($value)
@@ -182,8 +201,10 @@ class washtml
       if (isset($this->_html_attribs[$key]) ||
          ($key == 'href' && preg_match('/^(http:|https:|ftp:|mailto:|#).+/i', $value)))
         $t .= ' ' . $key . '="' . htmlspecialchars($value, ENT_QUOTES) . '"';
       if (isset($this->_html_attribs[$key]) ||
          ($key == 'href' && preg_match('/^(http:|https:|ftp:|mailto:|#).+/i', $value)))
         $t .= ' ' . $key . '="' . htmlspecialchars($value, ENT_QUOTES) . '"';
-      else if ($key == 'style' && ($style = $this->wash_style($value)))
-        $t .= ' style="' . $style . '"';
+      else if ($key == 'style' && ($style = $this->wash_style($value))) {
+        $quot = strpos($style, '"') !== false ? "'" : '"';
+        $t .= ' style=' . $quot . $style . $quot;
+      }
       else if ($key == 'background' || ($key == 'src' && strtolower($node->tagName) == 'img')) { //check tagName anyway
         if (($src = $this->config['cid_map'][$value])
             || ($src = $this->config['cid_map'][$this->config['base_url'].$value])) {
       else if ($key == 'background' || ($key == 'src' && strtolower($node->tagName) == 'img')) { //check tagName anyway
         if (($src = $this->config['cid_map'][$value])
             || ($src = $this->config['cid_map'][$this->config['base_url'].$value])) {
@@ -222,7 +243,7 @@ class washtml
       case XML_ELEMENT_NODE: //Check element
         $tagName = strtolower($node->tagName);
         if ($callback = $this->handlers[$tagName]) {
       case XML_ELEMENT_NODE: //Check element
         $tagName = strtolower($node->tagName);
         if ($callback = $this->handlers[$tagName]) {
-          $dump .= call_user_func($callback, $tagName, $this->wash_attribs($node), $this->dumpHtml($node));
+          $dump .= call_user_func($callback, $tagName, $this->wash_attribs($node), $this->dumpHtml($node), $this);
         }
         else if (isset($this->_html_elements[$tagName])) {
           $content = $this->dumpHtml($node);
         }
         else if (isset($this->_html_elements[$tagName])) {
           $content = $this->dumpHtml($node);
@@ -280,6 +301,14 @@ class washtml
     return $this->dumpHtml($node);
   }
 
     return $this->dumpHtml($node);
   }
 
+  /**
+   * Getter for config parameters
+   */
+  public function get_config($prop)
+  {
+      return $this->config[$prop];
+  }
+
 }
 
 ?>
 }
 
 ?>
index 657917a2583af5fd9d74fec659faf4f760af2dca..04a48794a4e7bff1a1ca084f937935797c13e004 100644 (file)
@@ -13,7 +13,7 @@
 | Author: Ossama Khayat <okhayat@yahoo.com>                             |
 +-----------------------------------------------------------------------+
 
 | Author: Ossama Khayat <okhayat@yahoo.com>                             |
 +-----------------------------------------------------------------------+
 
-@version $Id: labels.inc 5067 2011-08-14 18:47:58Z thomasb $
+@version $Id: labels.inc 5569 2011-12-07 14:47:32Z thomasb $
 
 */
 
 
 */
 
@@ -117,7 +117,7 @@ $labels['markread'] = 'كمقروءة';
 $labels['markunread'] = 'كغير مقروءة';
 $labels['markflagged'] = 'كموْسومة';
 $labels['markunflagged'] = 'كغير موْسومة';
 $labels['markunread'] = 'كغير مقروءة';
 $labels['markflagged'] = 'كموْسومة';
 $labels['markunflagged'] = 'كغير موْسومة';
-$labels['messageactions'] = 'إجراءات إضافية...';
+$labels['moreactions'] = 'إجراءات إضافية...';
 $labels['select'] = 'تحديد';
 $labels['all'] = 'الكل';
 $labels['none'] = 'لا شيء';
 $labels['select'] = 'تحديد';
 $labels['all'] = 'الكل';
 $labels['none'] = 'لا شيء';
@@ -170,6 +170,8 @@ $labels['charset'] = 'مجموعة المحارف';
 $labels['editortype'] = 'نوع المُحرّر';
 $labels['returnreceipt'] = 'ايصال استلام';
 $labels['dsn'] = 'تنويه حالة التوصيل';
 $labels['editortype'] = 'نوع المُحرّر';
 $labels['returnreceipt'] = 'ايصال استلام';
 $labels['dsn'] = 'تنويه حالة التوصيل';
+$labels['mailreplyintro'] = 'كتب $sender في $date:';
+$labels['originalmessage'] = 'الرسالة الأساسية';
 $labels['editidents'] = 'تعديل الهويات';
 $labels['checkspelling'] = 'التدقيق الإملائي';
 $labels['resumeediting'] = 'متابعة التحرير';
 $labels['editidents'] = 'تعديل الهويات';
 $labels['checkspelling'] = 'التدقيق الإملائي';
 $labels['resumeediting'] = 'متابعة التحرير';
@@ -187,6 +189,7 @@ $labels['highest'] = 'الأعلى';
 $labels['nosubject'] = '(دون موضوع)';
 $labels['showimages'] = 'إظهار الصور';
 $labels['alwaysshow'] = 'دائماً أظهر الصّور القادمة من $sender';
 $labels['nosubject'] = '(دون موضوع)';
 $labels['showimages'] = 'إظهار الصور';
 $labels['alwaysshow'] = 'دائماً أظهر الصّور القادمة من $sender';
+$labels['isdraft'] = 'هذه مسودّة رسالة';
 $labels['htmltoggle'] = 'HTML';
 $labels['plaintoggle'] = 'نص مجرد';
 $labels['savesentmessagein'] = 'احفظ الرسالة المُرسلة في';
 $labels['htmltoggle'] = 'HTML';
 $labels['plaintoggle'] = 'نص مجرد';
 $labels['savesentmessagein'] = 'احفظ الرسالة المُرسلة في';
@@ -245,6 +248,8 @@ $labels['typepager'] = 'الرنان';
 $labels['typevideo'] = 'الفيديو';
 $labels['typeassistant'] = 'المساعد';
 $labels['typehomepage'] = 'الرئيسية';
 $labels['typevideo'] = 'الفيديو';
 $labels['typeassistant'] = 'المساعد';
 $labels['typehomepage'] = 'الرئيسية';
+$labels['typeblog'] = 'المدوّنة';
+$labels['typeprofile'] = 'الملف الشخصي';
 $labels['addfield'] = 'إضافة حقل...';
 $labels['addcontact'] = 'إضافة المراسل المحدد إلى دفتر عناويني';
 $labels['editcontact'] = 'تحرير بيانات المراسل';
 $labels['addfield'] = 'إضافة حقل...';
 $labels['addcontact'] = 'إضافة المراسل المحدد إلى دفتر عناويني';
 $labels['editcontact'] = 'تحرير بيانات المراسل';
@@ -266,7 +271,6 @@ $labels['print'] = 'طباعة';
 $labels['export'] = 'تصدير';
 $labels['exportvcards'] = 'صدّر المراسلين بنسق vCard';
 $labels['newcontactgroup'] = 'إنشاء مجموعة مراسلين جديدة';
 $labels['export'] = 'تصدير';
 $labels['exportvcards'] = 'صدّر المراسلين بنسق vCard';
 $labels['newcontactgroup'] = 'إنشاء مجموعة مراسلين جديدة';
-$labels['groupactions'] = 'إجراءات مجموعات المراسلين...';
 $labels['grouprename'] = 'تغيير اسم المجموعة';
 $labels['groupdelete'] = 'حذف المجموعة';
 $labels['previouspage'] = 'عرض المجموعة السابقة';
 $labels['grouprename'] = 'تغيير اسم المجموعة';
 $labels['groupdelete'] = 'حذف المجموعة';
 $labels['previouspage'] = 'عرض المجموعة السابقة';
@@ -276,6 +280,8 @@ $labels['lastpage'] = 'عرض المجموعة الأخيرة';
 $labels['group'] = 'مجموعة';
 $labels['groups'] = 'المجموعات';
 $labels['personaladrbook'] = 'العناوين الشخصية';
 $labels['group'] = 'مجموعة';
 $labels['groups'] = 'المجموعات';
 $labels['personaladrbook'] = 'العناوين الشخصية';
+$labels['searchsave'] = 'حفظ البحث';
+$labels['searchdelete'] = 'حذف البحث';
 $labels['import'] = 'استورد';
 $labels['importcontacts'] = 'استورد المراسلين';
 $labels['importfromfile'] = 'استورد من ملف:';
 $labels['import'] = 'استورد';
 $labels['importcontacts'] = 'استورد المراسلين';
 $labels['importfromfile'] = 'استورد من ملف:';
@@ -284,6 +290,7 @@ $labels['importreplace'] = 'استبدل دفتر العناوين بأكمله'
 $labels['importtext'] = 'يمكنك رفع قائمة المراسلين من دفتر عناوين موجود.<br/>ندعم حالياً استيراد العناوين من نسق بيانات <a href="http://en.wikipedia.org/wiki/VCard">vCard</a>.';
 $labels['done'] = 'تم';
 $labels['settingsfor'] = 'إعدادات';
 $labels['importtext'] = 'يمكنك رفع قائمة المراسلين من دفتر عناوين موجود.<br/>ندعم حالياً استيراد العناوين من نسق بيانات <a href="http://en.wikipedia.org/wiki/VCard">vCard</a>.';
 $labels['done'] = 'تم';
 $labels['settingsfor'] = 'إعدادات';
+$labels['about'] = 'نبذة';
 $labels['preferences'] = 'التفضيلات';
 $labels['userpreferences'] = 'تفضيلات المستخدم';
 $labels['editpreferences'] = 'تحرير تفضيلات المستخدم';
 $labels['preferences'] = 'التفضيلات';
 $labels['userpreferences'] = 'تفضيلات المستخدم';
 $labels['editpreferences'] = 'تحرير تفضيلات المستخدم';
@@ -295,6 +302,8 @@ $labels['edititem'] = 'تحرير عنصر';
 $labels['preferhtml'] = 'تفضيل صيغة HTML';
 $labels['defaultcharset'] = 'ترميز المحارف الافتراضي';
 $labels['htmlmessage'] = 'رسالة بنسق HTML';
 $labels['preferhtml'] = 'تفضيل صيغة HTML';
 $labels['defaultcharset'] = 'ترميز المحارف الافتراضي';
 $labels['htmlmessage'] = 'رسالة بنسق HTML';
+$labels['dateformat'] = 'نسق التاريخ';
+$labels['timeformat'] = 'نسق الوقت';
 $labels['prettydate'] = 'تواريخ منمقة';
 $labels['setdefault'] = 'تعيين كإفتراضي';
 $labels['autodetect'] = 'آلي';
 $labels['prettydate'] = 'تواريخ منمقة';
 $labels['setdefault'] = 'تعيين كإفتراضي';
 $labels['autodetect'] = 'آلي';
@@ -366,7 +375,13 @@ $labels['reqmdn'] = 'طلب إشعار استلام دائماً';
 $labels['reqdsn'] = 'طلب تنويه لحالة التوصيل دائماً';
 $labels['replysamefolder'] = 'وضع الردود في المجلد الذي يحوي الرسالة المردود عليها';
 $labels['defaultaddressbook'] = 'أضف المراسلين الجديد إلى دفتر العناوين المحدد';
 $labels['reqdsn'] = 'طلب تنويه لحالة التوصيل دائماً';
 $labels['replysamefolder'] = 'وضع الردود في المجلد الذي يحوي الرسالة المردود عليها';
 $labels['defaultaddressbook'] = 'أضف المراسلين الجديد إلى دفتر العناوين المحدد';
+$labels['autocompletesingle'] = 'تجاهل عنوان البريد الإلكتروني البديل في التكملة التلقائية';
 $labels['spellcheckbeforesend'] = 'تحقق من الإملاء قبل إرسال الرسائل';
 $labels['spellcheckbeforesend'] = 'تحقق من الإملاء قبل إرسال الرسائل';
+$labels['spellcheckoptions'] = 'خيارات التدقيق الإملاءي';
+$labels['spellcheckignoresyms'] = 'تجاهل الكلمات التي تحتوي رموز';
+$labels['spellcheckignorenums'] = 'تجاهل الكلمات التي تحتوي أرقام';
+$labels['spellcheckignorecaps'] = 'تجاهل الكلمات التي بها أحرف كبيرة';
+$labels['addtodict'] = 'إضافة إلى القامس';
 $labels['folder'] = 'مجلد';
 $labels['folders'] = 'مجلدات';
 $labels['foldername'] = 'اسم المجلد';
 $labels['folder'] = 'مجلد';
 $labels['folders'] = 'مجلدات';
 $labels['foldername'] = 'اسم المجلد';
@@ -391,6 +406,11 @@ $labels['sortby'] = 'ترتيب بحسب';
 $labels['sortasc'] = 'ترتيب تصاعدي';
 $labels['sortdesc'] = 'ترتيب تنازلي';
 $labels['undo'] = 'تراجع';
 $labels['sortasc'] = 'ترتيب تصاعدي';
 $labels['sortdesc'] = 'ترتيب تنازلي';
 $labels['undo'] = 'تراجع';
+$labels['plugin'] = 'إضافة';
+$labels['version'] = 'النسخة';
+$labels['source'] = 'المصدر';
+$labels['license'] = 'الترخيص';
+$labels['support'] = 'احصل على الدعم الفني';
 $labels['B'] = 'ب';
 $labels['KB'] = 'ك.ب';
 $labels['MB'] = 'م.ب';
 $labels['B'] = 'ب';
 $labels['KB'] = 'ك.ب';
 $labels['MB'] = 'م.ب';
index 8678cc28ce699ca19f98633d2892b0079748047a..8215d33b8a9a545802b59e041891da368bd34930 100644 (file)
@@ -13,7 +13,7 @@
 | Author: Ossama Khayat <okhayat@yahoo.com>                             |
 +-----------------------------------------------------------------------+
 
 | Author: Ossama Khayat <okhayat@yahoo.com>                             |
 +-----------------------------------------------------------------------+
 
-@version $Id: messages.inc 5067 2011-08-14 18:47:58Z thomasb $
+@version $Id: messages.inc 5569 2011-12-07 14:47:32Z thomasb $
 
 */
 
 
 */
 
@@ -24,7 +24,7 @@ $messages['sessionerror'] = 'انتهت صلاحية الجلسة الحالية
 $messages['imaperror'] = 'فشل الاتصال بخادم IMAP';
 $messages['servererror'] = 'خطأ في الخادم!';
 $messages['servererrormsg'] = 'خطأ خادم: $msg';
 $messages['imaperror'] = 'فشل الاتصال بخادم IMAP';
 $messages['servererror'] = 'خطأ في الخادم!';
 $messages['servererrormsg'] = 'خطأ خادم: $msg';
-$messages['databaserror'] = 'خطأ في قاعدة البيانات!';
+$messages['dberror'] = 'خطأ في قاعدة البيانات!';
 $messages['errorreadonly'] = 'تعذر تنفيذ العملية. المجلد للقراءة فقط.';
 $messages['errornoperm'] = 'تعذر تنفيذ العملية. ليست لديك الصلاحية.';
 $messages['invalidrequest'] = 'طلب غير صالح! لم تحفظ أية بيانات.';
 $messages['errorreadonly'] = 'تعذر تنفيذ العملية. المجلد للقراءة فقط.';
 $messages['errornoperm'] = 'تعذر تنفيذ العملية. ليست لديك الصلاحية.';
 $messages['invalidrequest'] = 'طلب غير صالح! لم تحفظ أية بيانات.';
@@ -48,6 +48,7 @@ $messages['blockedimages'] = 'لحماية خصوصيتك، تم حجب الصو
 $messages['encryptedmessage'] = 'هذه الرسالة مشفرة ولا يمكن عرضها. عذراً!';
 $messages['nocontactsfound'] = 'لم يعثر على أي مراسل';
 $messages['contactnotfound'] = 'تعذر العثور على المراسل المطلوب';
 $messages['encryptedmessage'] = 'هذه الرسالة مشفرة ولا يمكن عرضها. عذراً!';
 $messages['nocontactsfound'] = 'لم يعثر على أي مراسل';
 $messages['contactnotfound'] = 'تعذر العثور على المراسل المطلوب';
+$messages['contactsearchonly'] = 'اكتب بعض كلمات البحث للعثور على المُراسلين';
 $messages['sendingfailed'] = 'فشل إرسال الرسالة';
 $messages['senttooquickly'] = 'رجاء انتظر $sec ثوان قبل إرسال هذه الرسالة';
 $messages['errorsavingsent'] = 'حدث خطأ أثناء حفظ الرسالة المُرسلة';
 $messages['sendingfailed'] = 'فشل إرسال الرسالة';
 $messages['senttooquickly'] = 'رجاء انتظر $sec ثوان قبل إرسال هذه الرسالة';
 $messages['errorsavingsent'] = 'حدث خطأ أثناء حفظ الرسالة المُرسلة';
@@ -61,6 +62,7 @@ $messages['deletegroupconfirm'] = 'هل تريد فعلاً حذف المجمو
 $messages['deletemessagesconfirm'] = 'هل تريد حذف الرسائل المحددة؟';
 $messages['deletefolderconfirm'] = 'هل تريد حقاً حذف هذا المجلد؟';
 $messages['purgefolderconfirm'] = 'هل تريد حقاً حذف جميع الرسائل في هذا المجلد؟';
 $messages['deletemessagesconfirm'] = 'هل تريد حذف الرسائل المحددة؟';
 $messages['deletefolderconfirm'] = 'هل تريد حقاً حذف هذا المجلد؟';
 $messages['purgefolderconfirm'] = 'هل تريد حقاً حذف جميع الرسائل في هذا المجلد؟';
+$messages['contactdeleting'] = 'جاري حذف المُراسلين...';
 $messages['groupdeleting'] = 'جاري حذف المجموعة...';
 $messages['folderdeleting'] = 'جاري حذف المجلد...';
 $messages['foldermoving'] = 'جاري نقل المجلد...';
 $messages['groupdeleting'] = 'جاري حذف المجموعة...';
 $messages['folderdeleting'] = 'جاري حذف المجلد...';
 $messages['foldermoving'] = 'جاري نقل المجلد...';
@@ -76,10 +78,10 @@ $messages['nosubjectwarning'] = 'حقل \"الموضوع\" فارغ. هل تري
 $messages['nobodywarning'] = 'إرسال هذه الرسالة دون نص؟';
 $messages['notsentwarning'] = 'لم يتم إرسال الرسالة. هل تريد تجاهل الرسالة؟';
 $messages['noldapserver'] = 'الرجاء اختيار خادم ldap للبحث فيه';
 $messages['nobodywarning'] = 'إرسال هذه الرسالة دون نص؟';
 $messages['notsentwarning'] = 'لم يتم إرسال الرسالة. هل تريد تجاهل الرسالة؟';
 $messages['noldapserver'] = 'الرجاء اختيار خادم ldap للبحث فيه';
-$messages['nocontactsreturned'] = 'لم يعثر على أي مراسلين';
 $messages['nosearchname'] = 'الرجاء إدخال اسم مراسل أو عنوان بريد إلكتروني';
 $messages['notuploadedwarning'] = 'لم يتم رفع جميع المرفقات بعد. رجاءً الانتظار أو إلغاء عملية الرفع.';
 $messages['searchsuccessful'] = 'عثر على $nr رسائل';
 $messages['nosearchname'] = 'الرجاء إدخال اسم مراسل أو عنوان بريد إلكتروني';
 $messages['notuploadedwarning'] = 'لم يتم رفع جميع المرفقات بعد. رجاءً الانتظار أو إلغاء عملية الرفع.';
 $messages['searchsuccessful'] = 'عثر على $nr رسائل';
+$messages['contactsearchsuccessful'] = 'عُثر على $nr مُراسَل';
 $messages['searchnomatch'] = 'لم يعثر على شيء';
 $messages['searching'] = 'جاري البحث...';
 $messages['checking'] = 'جاري التحقق...';
 $messages['searchnomatch'] = 'لم يعثر على شيء';
 $messages['searching'] = 'جاري البحث...';
 $messages['checking'] = 'جاري التحقق...';
@@ -126,7 +128,6 @@ $messages['smtpautherror'] = 'خطأ SMTP ($code): تعذر التحقق من ه
 $messages['smtpfromerror'] = 'خطأ SMTP ($code): تعذر تحديد المرسل "$from" ($msg)';
 $messages['smtptoerror'] = 'خطأ SMTP ($code): تعذرت إضافة المستلم "$to" ($msg)';
 $messages['smtprecipientserror'] = 'خطأ SMTP: تعذرت قراءة قائمة المرسل إليهم';
 $messages['smtpfromerror'] = 'خطأ SMTP ($code): تعذر تحديد المرسل "$from" ($msg)';
 $messages['smtptoerror'] = 'خطأ SMTP ($code): تعذرت إضافة المستلم "$to" ($msg)';
 $messages['smtprecipientserror'] = 'خطأ SMTP: تعذرت قراءة قائمة المرسل إليهم';
-$messages['smtpdsnerror'] = 'خطأ SMTP: لا يوجد دعم لتنويهات حالة التوصيل';
 $messages['smtperror'] = 'خطأ SMTP: $msg';
 $messages['emailformaterror'] = 'عنوان بريد إلكتروني غير صالح: $email';
 $messages['toomanyrecipients'] = 'عدد المرسل إليهم كبير. قلص العدد إلى $max.';
 $messages['smtperror'] = 'خطأ SMTP: $msg';
 $messages['emailformaterror'] = 'عنوان بريد إلكتروني غير صالح: $email';
 $messages['toomanyrecipients'] = 'عدد المرسل إليهم كبير. قلص العدد إلى $max.';
@@ -139,11 +140,16 @@ $messages['contactrestored'] = 'تم استعادة المُراسل بنجاح.
 $messages['groupdeleted'] = 'تم حذف المجموعة بنجاح';
 $messages['grouprenamed'] = 'تم تغيير إسم المجموعة بنجاح';
 $messages['groupcreated'] = 'تم إنشاء المجموعة بنجاح';
 $messages['groupdeleted'] = 'تم حذف المجموعة بنجاح';
 $messages['grouprenamed'] = 'تم تغيير إسم المجموعة بنجاح';
 $messages['groupcreated'] = 'تم إنشاء المجموعة بنجاح';
+$messages['savedsearchdeleted'] = 'تم بنجاح حذف البحث المحفوظ.';
+$messages['savedsearchdeleteerror'] = 'تعذر حذف البحث المحفوظ';
+$messages['savedsearchcreated'] = 'تم بنجاح إنشاء البحث المحفوظ.';
+$messages['savedsearchcreateerror'] = 'تعذر إنشاء بحث محفوظ.';
 $messages['messagedeleted'] = 'تم حذف الرسائل بنجاح';
 $messages['messagemoved'] = 'تم نقل الرسائل بنجاح';
 $messages['messagecopied'] = 'تم نسخ الرسائل بنجاح';
 $messages['messagemarked'] = 'تم تحديد الرسائل بنجاح';
 $messages['autocompletechars'] = 'إكتب $min أحرف على الأقل للحصول على التكملة التلقائية';
 $messages['messagedeleted'] = 'تم حذف الرسائل بنجاح';
 $messages['messagemoved'] = 'تم نقل الرسائل بنجاح';
 $messages['messagecopied'] = 'تم نسخ الرسائل بنجاح';
 $messages['messagemarked'] = 'تم تحديد الرسائل بنجاح';
 $messages['autocompletechars'] = 'إكتب $min أحرف على الأقل للحصول على التكملة التلقائية';
+$messages['autocompletemore'] = 'هناك المزيد من النتائج المطابقة. رجاء اكتب كلمات بحث أكثر.';
 $messages['namecannotbeempty'] = 'لا يمكن ترك الإسم فارغاً';
 $messages['nametoolong'] = 'الإسم طويل جداً';
 $messages['folderupdated'] = 'تم تحديث المجلد بنجاح';
 $messages['namecannotbeempty'] = 'لا يمكن ترك الإسم فارغاً';
 $messages['nametoolong'] = 'الإسم طويل جداً';
 $messages['folderupdated'] = 'تم تحديث المجلد بنجاح';
@@ -151,5 +157,6 @@ $messages['foldercreated'] = 'تم إنشاء المجلد بنجاح';
 $messages['invalidimageformat'] = 'ليست صيغة صورة صحيحة';
 $messages['mispellingsfound'] = 'عُثر على أخطاء إملائية في الرسالة';
 $messages['parentnotwritable'] = 'تعذر إنشاء/نقل المجلد إلى المجلد المحدد. ليست لديك الصلاحية.';
 $messages['invalidimageformat'] = 'ليست صيغة صورة صحيحة';
 $messages['mispellingsfound'] = 'عُثر على أخطاء إملائية في الرسالة';
 $messages['parentnotwritable'] = 'تعذر إنشاء/نقل المجلد إلى المجلد المحدد. ليست لديك الصلاحية.';
+$messages['messagetoobig'] = 'جزء الرسالة أكبر بكثير مما يمكن معالجته.';
 
 ?>
 
 ?>
index da8c9c3a3bfa35a13803ec81fc5fa82b911012e6..dffa2c608aa2f74c895afee198be81ecb20bde69 100644 (file)
@@ -14,7 +14,7 @@
 |   Nickolay Bunev <just4nick@gmail.com>                                |
 +-----------------------------------------------------------------------+
 
 |   Nickolay Bunev <just4nick@gmail.com>                                |
 +-----------------------------------------------------------------------+
 
-@version $Id: labels.inc 4463 2011-01-28 16:03:31Z thomasb $
+@version $Id: labels.inc 5569 2011-12-07 14:47:32Z thomasb $
 
 */
 
 
 */
 
@@ -101,18 +101,16 @@ $labels['replytomessage'] = 'Отговори на писмото';
 $labels['replytoallmessage'] = 'Отговор до изпращача и всички получатели';
 $labels['replyall'] = 'Отговор на всички';
 $labels['replylist'] = 'Списък за отговор';
 $labels['replytoallmessage'] = 'Отговор до изпращача и всички получатели';
 $labels['replyall'] = 'Отговор на всички';
 $labels['replylist'] = 'Списък за отговор';
+$labels['forwardinline'] = 'Препрати като част от съобщението';
+$labels['forwardattachment'] = 'Препрати като прикачен файл';
 $labels['forwardmessage'] = 'Препрати писмото';
 $labels['deletemessage'] = 'Изтрий писмото';
 $labels['movemessagetotrash'] = 'Премести писмото в кошчето';
 $labels['printmessage'] = 'Разпечатай писмото';
 $labels['previousmessage'] = 'Предишно писмо';
 $labels['forwardmessage'] = 'Препрати писмото';
 $labels['deletemessage'] = 'Изтрий писмото';
 $labels['movemessagetotrash'] = 'Премести писмото в кошчето';
 $labels['printmessage'] = 'Разпечатай писмото';
 $labels['previousmessage'] = 'Предишно писмо';
-$labels['previousmessages'] = 'Предишна страница';
 $labels['firstmessage'] = 'Първо писмо';
 $labels['firstmessage'] = 'Първо писмо';
-$labels['firstmessages'] = 'Първа страница';
 $labels['nextmessage'] = 'Следващо писмо';
 $labels['nextmessage'] = 'Следващо писмо';
-$labels['nextmessages'] = 'Следваща страница';
 $labels['lastmessage'] = 'Последно писмо';
 $labels['lastmessage'] = 'Последно писмо';
-$labels['lastmessages'] = 'Последна страница';
 $labels['backtolist'] = 'Обратно към списъка';
 $labels['viewsource'] = 'Виж като код';
 $labels['markmessages'] = 'Маркирай писмата';
 $labels['backtolist'] = 'Обратно към списъка';
 $labels['viewsource'] = 'Виж като код';
 $labels['markmessages'] = 'Маркирай писмата';
@@ -120,7 +118,7 @@ $labels['markread'] = 'Като прочетени';
 $labels['markunread'] = 'Като нови';
 $labels['markflagged'] = 'Като отбелязани';
 $labels['markunflagged'] = 'Като неотбелязани';
 $labels['markunread'] = 'Като нови';
 $labels['markflagged'] = 'Като отбелязани';
 $labels['markunflagged'] = 'Като неотбелязани';
-$labels['messageactions'] = 'Още действия';
+$labels['moreactions'] = 'Повече действия...';
 $labels['select'] = 'Избери';
 $labels['all'] = 'Всички';
 $labels['none'] = 'Нищо';
 $labels['select'] = 'Избери';
 $labels['all'] = 'Всички';
 $labels['none'] = 'Нищо';
@@ -152,7 +150,7 @@ $labels['listcolumns'] = 'Колони за списък';
 $labels['listsorting'] = 'Колона за сортиране';
 $labels['listorder'] = 'Режим на сортиране';
 $labels['listmode'] = 'Кратък списък';
 $labels['listsorting'] = 'Колона за сортиране';
 $labels['listorder'] = 'Режим на сортиране';
 $labels['listmode'] = 'Кратък списък';
-$labels['folderactions'] = 'Десйтвия за папки...';
+$labels['folderactions'] = 'Действия за папки...';
 $labels['compact'] = 'Свий';
 $labels['empty'] = 'Изпразни';
 $labels['quota'] = 'Използвано място';
 $labels['compact'] = 'Свий';
 $labels['empty'] = 'Изпразни';
 $labels['quota'] = 'Използвано място';
@@ -173,12 +171,15 @@ $labels['charset'] = 'Кодировка';
 $labels['editortype'] = 'Вид редактор';
 $labels['returnreceipt'] = 'Обратна разписка';
 $labels['dsn'] = 'Информиране при доставка';
 $labels['editortype'] = 'Вид редактор';
 $labels['returnreceipt'] = 'Обратна разписка';
 $labels['dsn'] = 'Информиране при доставка';
+$labels['mailreplyintro'] = 'На $date, $sender написа:';
+$labels['originalmessage'] = 'Първоначалното съобщение';
 $labels['editidents'] = 'Редактиране на самоличности';
 $labels['checkspelling'] = 'Провери правописа';
 $labels['resumeediting'] = 'Продължи черновата';
 $labels['revertto'] = 'Върни се към';
 $labels['attachments'] = 'Прикачени файлове';
 $labels['upload'] = 'Качи';
 $labels['editidents'] = 'Редактиране на самоличности';
 $labels['checkspelling'] = 'Провери правописа';
 $labels['resumeediting'] = 'Продължи черновата';
 $labels['revertto'] = 'Върни се към';
 $labels['attachments'] = 'Прикачени файлове';
 $labels['upload'] = 'Качи';
+$labels['uploadprogress'] = '$percent ($current от $total)';
 $labels['close'] = 'Затвори';
 $labels['messageoptions'] = 'Настройки на съобщения...';
 $labels['low'] = 'Нисък';
 $labels['close'] = 'Затвори';
 $labels['messageoptions'] = 'Настройки на съобщения...';
 $labels['low'] = 'Нисък';
@@ -189,6 +190,7 @@ $labels['highest'] = 'Най-висок';
 $labels['nosubject'] = '(няма заглавие)';
 $labels['showimages'] = 'Показвай изображения';
 $labels['alwaysshow'] = 'Винаги показвай изображения от $ ';
 $labels['nosubject'] = '(няма заглавие)';
 $labels['showimages'] = 'Показвай изображения';
 $labels['alwaysshow'] = 'Винаги показвай изображения от $ ';
+$labels['isdraft'] = 'Това съобщение е чернова';
 $labels['htmltoggle'] = 'HTML';
 $labels['plaintoggle'] = 'текстов';
 $labels['savesentmessagein'] = 'Запази съобщението в';
 $labels['htmltoggle'] = 'HTML';
 $labels['plaintoggle'] = 'текстов';
 $labels['savesentmessagein'] = 'Запази съобщението в';
@@ -231,6 +233,24 @@ $labels['female'] = 'Жена';
 $labels['manager'] = 'Мениджър';
 $labels['assistant'] = 'Асистент';
 $labels['spouse'] = 'Съпруг (а)';
 $labels['manager'] = 'Мениджър';
 $labels['assistant'] = 'Асистент';
 $labels['spouse'] = 'Съпруг (а)';
+$labels['allfields'] = 'Всички полета';
+$labels['search'] = 'Търсене';
+$labels['advsearch'] = 'Разширено търсене';
+$labels['other'] = 'Други';
+$labels['typehome'] = 'Начало';
+$labels['typework'] = 'Работа';
+$labels['typeother'] = 'Други';
+$labels['typemobile'] = 'Мобилни';
+$labels['typemain'] = 'Главни';
+$labels['typehomefax'] = 'Домашен факс';
+$labels['typeworkfax'] = 'Служебен факс';
+$labels['typecar'] = 'Автомобил';
+$labels['typepager'] = 'Пейджър';
+$labels['typevideo'] = 'Видео';
+$labels['typeassistant'] = 'Асистент';
+$labels['typehomepage'] = 'Начална страница';
+$labels['typeblog'] = 'Блог';
+$labels['typeprofile'] = 'Профил';
 $labels['addfield'] = 'Добави поле';
 $labels['addcontact'] = 'Добави';
 $labels['editcontact'] = 'Редактирай';
 $labels['addfield'] = 'Добави поле';
 $labels['addcontact'] = 'Добави';
 $labels['editcontact'] = 'Редактирай';
@@ -252,7 +272,8 @@ $labels['print'] = 'Разпечатай';
 $labels['export'] = 'Изнасяне';
 $labels['exportvcards'] = 'Изнасяне във vCard формат';
 $labels['newcontactgroup'] = 'Създаване на нова група';
 $labels['export'] = 'Изнасяне';
 $labels['exportvcards'] = 'Изнасяне във vCard формат';
 $labels['newcontactgroup'] = 'Създаване на нова група';
-$labels['groupactions'] = 'Действия за групи от контакти...';
+$labels['grouprename'] = 'Преименувай група';
+$labels['groupdelete'] = 'Изтриване на група';
 $labels['previouspage'] = 'Предна страница';
 $labels['firstpage'] = 'Първа страница';
 $labels['nextpage'] = 'Следваща страница';
 $labels['previouspage'] = 'Предна страница';
 $labels['firstpage'] = 'Първа страница';
 $labels['nextpage'] = 'Следваща страница';
@@ -260,9 +281,12 @@ $labels['lastpage'] = 'Последна страница';
 $labels['group'] = 'Група';
 $labels['groups'] = 'Групи';
 $labels['personaladrbook'] = 'Лични адреси';
 $labels['group'] = 'Група';
 $labels['groups'] = 'Групи';
 $labels['personaladrbook'] = 'Лични адреси';
+$labels['searchsave'] = 'Запази търсенето';
+$labels['searchdelete'] = 'Изтрий търсенето';
 $labels['import'] = 'Внасяне';
 $labels['importcontacts'] = 'Внасяне';
 $labels['importfromfile'] = 'Внасяне от файл';
 $labels['import'] = 'Внасяне';
 $labels['importcontacts'] = 'Внасяне';
 $labels['importfromfile'] = 'Внасяне от файл';
+$labels['importtarget'] = 'Добави нови контакти в книгата с адреси';
 $labels['importreplace'] = 'Замени цялата книга с адреси';
 $labels['importtext'] = 'Можете да внесете контакти от съществуваща книга с адреси. В момента поддържане внасянето на адреси от vCard формат за данни.';
 $labels['done'] = 'Извършено';
 $labels['importreplace'] = 'Замени цялата книга с адреси';
 $labels['importtext'] = 'Можете да внесете контакти от съществуваща книга с адреси. В момента поддържане внасянето на адреси от vCard формат за данни.';
 $labels['done'] = 'Извършено';
@@ -278,6 +302,8 @@ $labels['edititem'] = 'Редактиране на самоличност';
 $labels['preferhtml'] = 'Показвай първо HTML версия';
 $labels['defaultcharset'] = 'Подразбиращо се кодиране';
 $labels['htmlmessage'] = 'HTML съобщение';
 $labels['preferhtml'] = 'Показвай първо HTML версия';
 $labels['defaultcharset'] = 'Подразбиращо се кодиране';
 $labels['htmlmessage'] = 'HTML съобщение';
+$labels['dateformat'] = 'Формат на датата';
+$labels['timeformat'] = 'Формат на времето';
 $labels['prettydate'] = 'Кратки дати';
 $labels['setdefault'] = 'По подразбиране';
 $labels['autodetect'] = 'Автоматично';
 $labels['prettydate'] = 'Кратки дати';
 $labels['setdefault'] = 'По подразбиране';
 $labels['autodetect'] = 'Автоматично';
@@ -348,6 +374,14 @@ $labels['afternseconds'] = 'след $n секунди';
 $labels['reqmdn'] = 'Винаги връщай обратна разписка';
 $labels['reqdsn'] = 'Винаги изисквай отговор при доставка на съобщение';
 $labels['replysamefolder'] = 'Постави отговора в папката на съобщението, на което се отговаря';
 $labels['reqmdn'] = 'Винаги връщай обратна разписка';
 $labels['reqdsn'] = 'Винаги изисквай отговор при доставка на съобщение';
 $labels['replysamefolder'] = 'Постави отговора в папката на съобщението, на което се отговаря';
+$labels['defaultaddressbook'] = 'Добави нови контакти в избраната книга с адреси';
+$labels['autocompletesingle'] = 'Пропусни алтернативните email адреси при автоматично попълване';
+$labels['spellcheckbeforesend'] = 'Провери за правописни грешки преди изпращане на съобщението';
+$labels['spellcheckoptions'] = 'Настройки на проверката за правопис';
+$labels['spellcheckignoresyms'] = 'Игнорирай думи съдържащи символи';
+$labels['spellcheckignorenums'] = 'Игнорирай думи съдържащи числа';
+$labels['spellcheckignorecaps'] = 'Игнорирай думи съдържащи единствено главни букви';
+$labels['addtodict'] = 'Добави в речника';
 $labels['folder'] = 'Папка';
 $labels['folders'] = 'Папки';
 $labels['foldername'] = 'Име на папката';
 $labels['folder'] = 'Папка';
 $labels['folders'] = 'Папки';
 $labels['foldername'] = 'Име на папката';
@@ -364,9 +398,14 @@ $labels['location'] = 'Местоположение';
 $labels['info'] = 'Информация';
 $labels['getfoldersize'] = 'Щракни за големина на папката';
 $labels['changesubscription'] = 'Щракни за промяна на абонамент';
 $labels['info'] = 'Информация';
 $labels['getfoldersize'] = 'Щракни за големина на папката';
 $labels['changesubscription'] = 'Щракни за промяна на абонамент';
+$labels['foldertype'] = 'Вид на папката';
+$labels['personalfolder'] = 'Лична папка';
+$labels['otherfolder'] = 'Папка на друг потребител';
+$labels['sharedfolder'] = 'Публична папка';
 $labels['sortby'] = 'Сортирай по';
 $labels['sortasc'] = 'Сортирай възходящо';
 $labels['sortdesc'] = 'Сортирай низходящо';
 $labels['sortby'] = 'Сортирай по';
 $labels['sortasc'] = 'Сортирай възходящо';
 $labels['sortdesc'] = 'Сортирай низходящо';
+$labels['undo'] = 'Отмени';
 $labels['B'] = 'Б';
 $labels['KB'] = 'КБ';
 $labels['MB'] = 'МБ';
 $labels['B'] = 'Б';
 $labels['KB'] = 'КБ';
 $labels['MB'] = 'МБ';
index a23a63c9b6bf419e5a7f22f51ecbb50399f8841b..17eb50c92b31896338b0cf6e885eebdf3d17b326 100644 (file)
@@ -14,7 +14,7 @@
 |        Nickolay Bunev <just4nick@gmail.com>                                                          |
 +-----------------------------------------------------------------------+
 
 |        Nickolay Bunev <just4nick@gmail.com>                                                          |
 +-----------------------------------------------------------------------+
 
-@version $Id: messages.inc 4463 2011-01-28 16:03:31Z thomasb $
+@version $Id: messages.inc 5569 2011-12-07 14:47:32Z thomasb $
 
 */
 
 
 */
 
@@ -25,6 +25,7 @@ $messages['sessionerror'] = 'Невалидна или изтекла сесия
 $messages['imaperror'] = 'Неуспешно свързване към IMAP сървъра';
 $messages['servererror'] = 'Грешка!';
 $messages['servererrormsg'] = 'Сървърна грешка: $msg';
 $messages['imaperror'] = 'Неуспешно свързване към IMAP сървъра';
 $messages['servererror'] = 'Грешка!';
 $messages['servererrormsg'] = 'Сървърна грешка: $msg';
+$messages['dberror'] = 'Грешка с базата данни!';
 $messages['errorreadonly'] = 'Операцията не може да бъде изпълнена. Папката е с права само за четене';
 $messages['errornoperm'] = 'Операцията не може да бъде изпълнена. Отказани права за достъп';
 $messages['invalidrequest'] = 'Невалидна заявка! Данните не са съхранени.';
 $messages['errorreadonly'] = 'Операцията не може да бъде изпълнена. Папката е с права само за четене';
 $messages['errornoperm'] = 'Операцията не може да бъде изпълнена. Отказани права за достъп';
 $messages['invalidrequest'] = 'Невалидна заявка! Данните не са съхранени.';
@@ -33,6 +34,7 @@ $messages['loggedout'] = 'Довиждане!';
 $messages['mailboxempty'] = 'Кутията е празна';
 $messages['loading'] = 'Зареждане...';
 $messages['uploading'] = 'Качване на файла...';
 $messages['mailboxempty'] = 'Кутията е празна';
 $messages['loading'] = 'Зареждане...';
 $messages['uploading'] = 'Качване на файла...';
+$messages['uploadingmany'] = 'Качване на файлове...';
 $messages['loadingdata'] = 'Зареждане на данни...';
 $messages['checkingmail'] = 'Проверка за нови писма...';
 $messages['sendingmessage'] = 'Изпращане на писмото...';
 $messages['loadingdata'] = 'Зареждане на данни...';
 $messages['checkingmail'] = 'Проверка за нови писма...';
 $messages['sendingmessage'] = 'Изпращане на писмото...';
@@ -42,10 +44,12 @@ $messages['messagesaved'] = 'Писмото е записано в Чернов
 $messages['successfullysaved'] = 'Записано';
 $messages['addedsuccessfully'] = 'Контакта е добавен в адресната книга';
 $messages['contactexists'] = 'Контакт с този e-mail адрес вече същестува';
 $messages['successfullysaved'] = 'Записано';
 $messages['addedsuccessfully'] = 'Контакта е добавен в адресната книга';
 $messages['contactexists'] = 'Контакт с този e-mail адрес вече същестува';
+$messages['contactnameexists'] = 'Контакт със същото име вече съществува';
 $messages['blockedimages'] = 'С оглед на Вашата сигурност, изображенията в това писмо са блокирани.';
 $messages['encryptedmessage'] = 'Това е кодирано писмо и не може да бъде показано. Съжаляваме!';
 $messages['blockedimages'] = 'С оглед на Вашата сигурност, изображенията в това писмо са блокирани.';
 $messages['encryptedmessage'] = 'Това е кодирано писмо и не може да бъде показано. Съжаляваме!';
-$messages['nocontactsfound'] = 'Няма контакти';
+$messages['nocontactsfound'] = 'Ð\9dÑ\8fма Ð½Ð°Ð¼ÐµÑ\80ени ÐºÐ¾Ð½Ñ\82акÑ\82и';
 $messages['contactnotfound'] = 'Исканият контакт не е намерен';
 $messages['contactnotfound'] = 'Исканият контакт не е намерен';
+$messages['contactsearchonly'] = 'Въведете нещо в полето за търсене за да търсите контакти';
 $messages['sendingfailed'] = 'Изпращането неуспешно';
 $messages['senttooquickly'] = 'Моля, изчакайте $sec секунда(и) преди да изпратите съобщението';
 $messages['errorsavingsent'] = 'Възникна грешка при записването на съобщението';
 $messages['sendingfailed'] = 'Изпращането неуспешно';
 $messages['senttooquickly'] = 'Моля, изчакайте $sec секунда(и) преди да изпратите съобщението';
 $messages['errorsavingsent'] = 'Възникна грешка при записването на съобщението';
@@ -55,9 +59,12 @@ $messages['errorcopying'] = 'Съобщенията не могат да бъд
 $messages['errordeleting'] = 'Писмото не може да бъде изтрито';
 $messages['errormarking'] = 'Съобщението не може да бъде маркирано';
 $messages['deletecontactconfirm'] = 'Искате ли да изтриете маркираните контакти?';
 $messages['errordeleting'] = 'Писмото не може да бъде изтрито';
 $messages['errormarking'] = 'Съобщението не може да бъде маркирано';
 $messages['deletecontactconfirm'] = 'Искате ли да изтриете маркираните контакти?';
+$messages['deletegroupconfirm'] = 'Искате ли да изтриете избраната група?';
 $messages['deletemessagesconfirm'] = 'Искате ли да изтриете маркираните съобщения?';
 $messages['deletefolderconfirm'] = 'Искате ли да изтриете тази папка?';
 $messages['purgefolderconfirm'] = 'Искате ли да изтриете всички писма в тази папка?';
 $messages['deletemessagesconfirm'] = 'Искате ли да изтриете маркираните съобщения?';
 $messages['deletefolderconfirm'] = 'Искате ли да изтриете тази папка?';
 $messages['purgefolderconfirm'] = 'Искате ли да изтриете всички писма в тази папка?';
+$messages['contactdeleting'] = 'Изтриване на контакт(и)...';
+$messages['groupdeleting'] = 'Изтриване на група...';
 $messages['folderdeleting'] = 'Изтриване на папка...';
 $messages['foldermoving'] = 'Преместване на папка...';
 $messages['foldersubscribing'] = 'Абониране...';
 $messages['folderdeleting'] = 'Изтриване на папка...';
 $messages['foldermoving'] = 'Преместване на папка...';
 $messages['foldersubscribing'] = 'Абониране...';
@@ -72,10 +79,10 @@ $messages['nosubjectwarning'] = 'Полето "Заглавие" е празно
 $messages['nobodywarning'] = 'Изпрати това писмо без текст?';
 $messages['notsentwarning'] = 'Писмото не е изпратено. Искате ли да бъде унищожено?';
 $messages['noldapserver'] = 'Изберете LDAP сървър за търсене';
 $messages['nobodywarning'] = 'Изпрати това писмо без текст?';
 $messages['notsentwarning'] = 'Писмото не е изпратено. Искате ли да бъде унищожено?';
 $messages['noldapserver'] = 'Изберете LDAP сървър за търсене';
-$messages['nocontactsreturned'] = 'Не са намерени контакти';
 $messages['nosearchname'] = 'Моля, въведете Име на контакта или e-mail адрес';
 $messages['notuploadedwarning'] = 'Все още не са качени всички прикачени файлове. Моля изчакайте или откажете качването.';
 $messages['searchsuccessful'] = '$nr намерени писма';
 $messages['nosearchname'] = 'Моля, въведете Име на контакта или e-mail адрес';
 $messages['notuploadedwarning'] = 'Все още не са качени всички прикачени файлове. Моля изчакайте или откажете качването.';
 $messages['searchsuccessful'] = '$nr намерени писма';
+$messages['contactsearchsuccessful'] = '$nr намерени контакти.';
 $messages['searchnomatch'] = 'Търсенето не откри съвпадения';
 $messages['searching'] = 'Търсене...';
 $messages['checking'] = 'Проверка...';
 $messages['searchnomatch'] = 'Търсенето не откри съвпадения';
 $messages['searching'] = 'Търсене...';
 $messages['checking'] = 'Проверка...';
@@ -94,10 +101,13 @@ $messages['copysuccess'] = 'Успешно копирани $nr адреса';
 $messages['copyerror'] = 'Грешка при копирането на адресите';
 $messages['sourceisreadonly'] = 'Този източник на адреси е само за четене';
 $messages['errorsavingcontact'] = 'Грешка при записването на адреса';
 $messages['copyerror'] = 'Грешка при копирането на адресите';
 $messages['sourceisreadonly'] = 'Този източник на адреси е само за четене';
 $messages['errorsavingcontact'] = 'Грешка при записването на адреса';
-$messages['movingmessage'] = 'Преместване на писмото...';
-$messages['copyingmessage'] = 'Копиране на съобщение...';
-$messages['deletingmessage'] = 'Изтриване на съобщение';
-$messages['markingmessage'] = 'Маркиране на съобщение';
+$messages['movingmessage'] = 'Преместване на съобщение...';
+$messages['copyingmessage'] = 'Копиране на съобщение(я)...';
+$messages['copyingcontact'] = 'Копиране на контакт(и)...';
+$messages['deletingmessage'] = 'Изтриване на съобщение(я)...';
+$messages['markingmessage'] = 'Маркиране на съобщение(я)...';
+$messages['addingmember'] = 'Добавяне на контакт(и) в групата...';
+$messages['removingmember'] = 'Премахване на контакт(и) от групата...';
 $messages['receiptsent'] = 'Обратната разписка е изпратена.';
 $messages['errorsendingreceipt'] = 'Грешка при изпращането на обратна разписка.';
 $messages['nodeletelastidentity'] = 'Не можете да изтриете тази самоличност, трябва да имате поне една.';
 $messages['receiptsent'] = 'Обратната разписка е изпратена.';
 $messages['errorsendingreceipt'] = 'Грешка при изпращането на обратна разписка.';
 $messages['nodeletelastidentity'] = 'Не можете да изтриете тази самоличност, трябва да имате поне една.';
@@ -109,6 +119,7 @@ $messages['contactremovedfromgroup'] = 'Контактите бяха успеш
 $messages['importwait'] = 'Внасяне, моля изчакайте...';
 $messages['importerror'] = 'Внасянето неуспешно! Каченият файл не е във валиден vCard формат.';
 $messages['importconfirm'] = '<b>Успешно са внесени $inserted контакта, вече съществуващите $skipped контакта са пропуснати</b>:<p><em>$names</em></p>';
 $messages['importwait'] = 'Внасяне, моля изчакайте...';
 $messages['importerror'] = 'Внасянето неуспешно! Каченият файл не е във валиден vCard формат.';
 $messages['importconfirm'] = '<b>Успешно са внесени $inserted контакта, вече съществуващите $skipped контакта са пропуснати</b>:<p><em>$names</em></p>';
+$messages['importconfirmskipped'] = 'b>Съществуващите записи $skipped са пропуснати</b>';
 $messages['opnotpermitted'] = 'Операцията не е позволена!';
 $messages['nofromaddress'] = 'Липсва e-mail адрес за избраната самоличност';
 $messages['editorwarning'] = 'Превключването на редактора в текстов режим ще доведе до загуба на форматирането на текса. Сигурни ли сте, че искате да продължите?';
 $messages['opnotpermitted'] = 'Операцията не е позволена!';
 $messages['nofromaddress'] = 'Липсва e-mail адрес за избраната самоличност';
 $messages['editorwarning'] = 'Превключването на редактора в текстов режим ще доведе до загуба на форматирането на текса. Сигурни ли сте, че искате да продължите?';
@@ -118,7 +129,6 @@ $messages['smtpautherror'] = 'SMTP грешка ($code): Грешни потре
 $messages['smtpfromerror'] = 'SMTP грешка ($code): Не може да бъде изпратено писмо от "$from" ($msg)';
 $messages['smtptoerror'] = 'SMTP грешка ($code): Не може да бъде изпратено писмо до "$to" ($msg)';
 $messages['smtprecipientserror'] = 'SMTP грешка: Не може да бъде обработен списъка с получатели';
 $messages['smtpfromerror'] = 'SMTP грешка ($code): Не може да бъде изпратено писмо от "$from" ($msg)';
 $messages['smtptoerror'] = 'SMTP грешка ($code): Не може да бъде изпратено писмо до "$to" ($msg)';
 $messages['smtprecipientserror'] = 'SMTP грешка: Не може да бъде обработен списъка с получатели';
-$messages['smtpdsnerror'] = 'SMTP грешка: Не се поддържа съобщаване за успешни получено съобщение';
 $messages['smtperror'] = 'SMTP грешка: $msg';
 $messages['emailformaterror'] = 'Невалиден e-mail адрес: $email';
 $messages['toomanyrecipients'] = 'Прекалено много адреси за изпращане (максимум: $max).';
 $messages['smtperror'] = 'SMTP грешка: $msg';
 $messages['emailformaterror'] = 'Невалиден e-mail адрес: $email';
 $messages['toomanyrecipients'] = 'Прекалено много адреси за изпращане (максимум: $max).';
@@ -126,18 +136,27 @@ $messages['maxgroupmembersreached'] = 'Броя на членовете на г
 $messages['internalerror'] = 'Възникна вътрешна грешка. Моля опитайте отново';
 $messages['contactdelerror'] = 'Не мога да изтрия контакта';
 $messages['contactdeleted'] = 'Контактът беше изтрит';
 $messages['internalerror'] = 'Възникна вътрешна грешка. Моля опитайте отново';
 $messages['contactdelerror'] = 'Не мога да изтрия контакта';
 $messages['contactdeleted'] = 'Контактът беше изтрит';
+$messages['contactrestoreerror'] = 'Неуспешно възстановяване на изтрите контакт(и).';
+$messages['contactrestored'] = 'Контактът(-ите) са възстановени успешно';
 $messages['groupdeleted'] = 'Групата беше  изтрита';
 $messages['grouprenamed'] = 'Групата беше преименувана ';
 $messages['groupcreated'] = 'Групата беше създадена';
 $messages['groupdeleted'] = 'Групата беше  изтрита';
 $messages['grouprenamed'] = 'Групата беше преименувана ';
 $messages['groupcreated'] = 'Групата беше създадена';
+$messages['savedsearchdeleted'] = 'Запазаните търсения са изтрити успешно.';
+$messages['savedsearchdeleteerror'] = 'Изтриването на запазените търсения е неуспешно.';
+$messages['savedsearchcreated'] = 'Запазените търсения са създадени успешно.';
+$messages['savedsearchcreateerror'] = 'Създаването на запазено търсене е неуспешно';
 $messages['messagedeleted'] = 'Съобщението  беше  изтрито';
 $messages['messagemoved'] = 'Съобщението беше преместено';
 $messages['messagecopied'] = 'Съобщението беше копирано';
 $messages['messagemarked'] = 'Съобщението беше маркирано';
 $messages['autocompletechars'] = 'Въведете минимум $min знака, за да започне автоматичното попълване';
 $messages['messagedeleted'] = 'Съобщението  беше  изтрито';
 $messages['messagemoved'] = 'Съобщението беше преместено';
 $messages['messagecopied'] = 'Съобщението беше копирано';
 $messages['messagemarked'] = 'Съобщението беше маркирано';
 $messages['autocompletechars'] = 'Въведете минимум $min знака, за да започне автоматичното попълване';
+$messages['autocompletemore'] = 'Намерените съвпадения са прекалено много. Моля напишете още символи.';
 $messages['namecannotbeempty'] = 'Полето за име не може да бъде празно';
 $messages['nametoolong'] = 'Името е прекалено дълго';
 $messages['folderupdated'] = 'Папката е обновена';
 $messages['foldercreated'] = 'Папката е създадена';
 $messages['invalidimageformat'] = 'Невалиден формат на изображението';
 $messages['namecannotbeempty'] = 'Полето за име не може да бъде празно';
 $messages['nametoolong'] = 'Името е прекалено дълго';
 $messages['folderupdated'] = 'Папката е обновена';
 $messages['foldercreated'] = 'Папката е създадена';
 $messages['invalidimageformat'] = 'Невалиден формат на изображението';
+$messages['mispellingsfound'] = 'В съобщението са намерени правописни грешки.';
+$messages['parentnotwritable'] = 'Създаването/преместването на папка в избраната родителска папка е неуспешно. Няма права за достъп.';
 
 ?>
 
 ?>
index 3127dd0d56b71cbcb323c5d662ec87f928c725a8..d4d99db5061a8837daf2f5a0a1658e5aaf821198 100644 (file)
@@ -15,7 +15,7 @@
 |         Jordi Sanfeliu <jordi@fibranet.cat>                           |
 +-----------------------------------------------------------------------+
 
 |         Jordi Sanfeliu <jordi@fibranet.cat>                           |
 +-----------------------------------------------------------------------+
 
-@version $Id: labels.inc 5291 2011-09-28 17:10:45Z thomasb $
+@version $Id: labels.inc 5290 2011-09-28 17:09:50Z thomasb $
 
 */
 
 
 */
 
index 30817b5827a4cccf420e75faf8c4a4cef6073224..e7b3d29e8df5b0ea507dfd63bb8de5f70b2bab22 100644 (file)
@@ -15,7 +15,7 @@
 |         Jordi Sanfeliu <jordi@fibranet.cat>                           |
 +-----------------------------------------------------------------------+
 
 |         Jordi Sanfeliu <jordi@fibranet.cat>                           |
 +-----------------------------------------------------------------------+
 
-@version $Id: messages.inc 5291 2011-09-28 17:10:45Z thomasb $
+@version $Id: messages.inc 5290 2011-09-28 17:09:50Z thomasb $
 
 */
 
 
 */
 
index f63271d7c825acbab45572fa2fff4ea12b3d247f..cf66e1bce1d7c980a438ee61fd9f8d38ecbb9f24 100644 (file)
@@ -17,7 +17,7 @@
 |        Ales Pospichal <ales@pospichalales.info>                       |
 +-----------------------------------------------------------------------+
 
 |        Ales Pospichal <ales@pospichalales.info>                       |
 +-----------------------------------------------------------------------+
 
-@version $Id: labels.inc 4671 2011-04-20 08:47:44Z thomasb $
+@version $Id: labels.inc 5569 2011-12-07 14:47:32Z thomasb $
 
 */
 
 
 */
 
@@ -103,6 +103,8 @@ $labels['replytomessage'] = 'Odpovědět odesílateli';
 $labels['replytoallmessage'] = 'Odpovědět všem';
 $labels['replyall'] = 'Odpovědět všem';
 $labels['replylist'] = 'Odpovědět do e-mailové konference';
 $labels['replytoallmessage'] = 'Odpovědět všem';
 $labels['replyall'] = 'Odpovědět všem';
 $labels['replylist'] = 'Odpovědět do e-mailové konference';
+$labels['forwardinline'] = 'Přeposlat v textu';
+$labels['forwardattachment'] = 'Přeposlat jako přílohu';
 $labels['forwardmessage'] = 'Předat zprávu';
 $labels['deletemessage'] = 'Odstranit zprávu';
 $labels['movemessagetotrash'] = 'Přesunout zprávu do koše';
 $labels['forwardmessage'] = 'Předat zprávu';
 $labels['deletemessage'] = 'Odstranit zprávu';
 $labels['movemessagetotrash'] = 'Přesunout zprávu do koše';
@@ -118,7 +120,7 @@ $labels['markread'] = 'Jako přečtené';
 $labels['markunread'] = 'Jako nepřečtené';
 $labels['markflagged'] = 'Jako označené';
 $labels['markunflagged'] = 'Jako neoznačené';
 $labels['markunread'] = 'Jako nepřečtené';
 $labels['markflagged'] = 'Jako označené';
 $labels['markunflagged'] = 'Jako neoznačené';
-$labels['messageactions'] = 'Další akce...';
+$labels['moreactions'] = 'Další akce...';
 $labels['select'] = 'Vybrat';
 $labels['all'] = 'Vše';
 $labels['none'] = 'Nic';
 $labels['select'] = 'Vybrat';
 $labels['all'] = 'Vše';
 $labels['none'] = 'Nic';
@@ -171,12 +173,15 @@ $labels['charset'] = 'Znaková sada';
 $labels['editortype'] = 'Typ editoru zpráv';
 $labels['returnreceipt'] = 'Doručenka';
 $labels['dsn'] = 'Stav doručení';
 $labels['editortype'] = 'Typ editoru zpráv';
 $labels['returnreceipt'] = 'Doručenka';
 $labels['dsn'] = 'Stav doručení';
+$labels['mailreplyintro'] = 'Dne $date, $sender napsal:';
+$labels['originalmessage'] = 'Původní zpráva';
 $labels['editidents'] = 'Editovat identity';
 $labels['checkspelling'] = 'Zkontrolovat pravopis';
 $labels['resumeediting'] = 'Pokračovat v úpravách';
 $labels['revertto'] = 'Přejít na';
 $labels['attachments'] = 'Přílohy';
 $labels['upload'] = 'Nahrát';
 $labels['editidents'] = 'Editovat identity';
 $labels['checkspelling'] = 'Zkontrolovat pravopis';
 $labels['resumeediting'] = 'Pokračovat v úpravách';
 $labels['revertto'] = 'Přejít na';
 $labels['attachments'] = 'Přílohy';
 $labels['upload'] = 'Nahrát';
+$labels['uploadprogress'] = '$percent ($current z $total)';
 $labels['close'] = 'Zavřít';
 $labels['messageoptions'] = 'Nastavení zprávy...';
 $labels['low'] = 'Nízká';
 $labels['close'] = 'Zavřít';
 $labels['messageoptions'] = 'Nastavení zprávy...';
 $labels['low'] = 'Nízká';
@@ -223,11 +228,16 @@ $labels['birthday'] = 'Datum narození';
 $labels['anniversary'] = 'Výročí';
 $labels['website'] = 'WWW';
 $labels['instantmessenger'] = 'Komunikace (ICQ, messenger...)';
 $labels['anniversary'] = 'Výročí';
 $labels['website'] = 'WWW';
 $labels['instantmessenger'] = 'Komunikace (ICQ, messenger...)';
+$labels['notes'] = 'Poznámky';
 $labels['male'] = 'Muž';
 $labels['female'] = 'Žena';
 $labels['manager'] = 'Manažer';
 $labels['assistant'] = 'Asistent';
 $labels['spouse'] = 'Manžel/ka';
 $labels['male'] = 'Muž';
 $labels['female'] = 'Žena';
 $labels['manager'] = 'Manažer';
 $labels['assistant'] = 'Asistent';
 $labels['spouse'] = 'Manžel/ka';
+$labels['allfields'] = 'Všechny položky';
+$labels['search'] = 'Hledat';
+$labels['advsearch'] = 'Pokročilé vyhledávání';
+$labels['other'] = 'Jiné';
 $labels['typehome'] = 'Domací';
 $labels['typework'] = 'Pracovní';
 $labels['typeother'] = 'Ostatní';
 $labels['typehome'] = 'Domací';
 $labels['typework'] = 'Pracovní';
 $labels['typeother'] = 'Ostatní';
@@ -239,6 +249,9 @@ $labels['typecar'] = 'Automobil';
 $labels['typepager'] = 'Pager';
 $labels['typevideo'] = 'Video';
 $labels['typeassistant'] = 'Asistent';
 $labels['typepager'] = 'Pager';
 $labels['typevideo'] = 'Video';
 $labels['typeassistant'] = 'Asistent';
+$labels['typehomepage'] = 'Domácí stránka';
+$labels['typeblog'] = 'Blog';
+$labels['typeprofile'] = 'Profil';
 $labels['addfield'] = 'Přidat položku';
 $labels['addcontact'] = 'Přidat kontakt';
 $labels['editcontact'] = 'Upravit kontakt';
 $labels['addfield'] = 'Přidat položku';
 $labels['addcontact'] = 'Přidat kontakt';
 $labels['editcontact'] = 'Upravit kontakt';
@@ -260,7 +273,8 @@ $labels['print'] = 'Tisk';
 $labels['export'] = 'Export';
 $labels['exportvcards'] = 'Exportovat kontakty ve formátu vCard';
 $labels['newcontactgroup'] = 'Vytvořit novou skupinu kontaktů';
 $labels['export'] = 'Export';
 $labels['exportvcards'] = 'Exportovat kontakty ve formátu vCard';
 $labels['newcontactgroup'] = 'Vytvořit novou skupinu kontaktů';
-$labels['groupactions'] = 'Akce pro skupiny kontaktů...';
+$labels['grouprename'] = 'Přejmenovat skupinu';
+$labels['groupdelete'] = 'Smazat skupinu';
 $labels['previouspage'] = 'Předchozí';
 $labels['firstpage'] = 'Zobrazit první zprávy';
 $labels['nextpage'] = 'Další';
 $labels['previouspage'] = 'Předchozí';
 $labels['firstpage'] = 'Zobrazit první zprávy';
 $labels['nextpage'] = 'Další';
@@ -268,9 +282,12 @@ $labels['lastpage'] = 'Zobrazit poslední zprávy';
 $labels['group'] = 'Skupina';
 $labels['groups'] = 'Skupiny';
 $labels['personaladrbook'] = 'Osobní kontakty';
 $labels['group'] = 'Skupina';
 $labels['groups'] = 'Skupiny';
 $labels['personaladrbook'] = 'Osobní kontakty';
+$labels['searchsave'] = 'Uložit hledání';
+$labels['searchdelete'] = 'Smazat hledání';
 $labels['import'] = 'Import';
 $labels['importcontacts'] = 'Importovat kontakty';
 $labels['importfromfile'] = 'Importovat ze souboru';
 $labels['import'] = 'Import';
 $labels['importcontacts'] = 'Importovat kontakty';
 $labels['importfromfile'] = 'Importovat ze souboru';
+$labels['importtarget'] = 'Přidat nové kontakty do seznamu kontaktů:';
 $labels['importreplace'] = 'Nahradit celý seznam kontaktů';
 $labels['importtext'] = 'Můžete nahrát kontakty z existujícího seznamu kontaktů. Podporujeme formát vCard.';
 $labels['done'] = 'Hotovo';
 $labels['importreplace'] = 'Nahradit celý seznam kontaktů';
 $labels['importtext'] = 'Můžete nahrát kontakty z existujícího seznamu kontaktů. Podporujeme formát vCard.';
 $labels['done'] = 'Hotovo';
@@ -286,6 +303,8 @@ $labels['edititem'] = 'Upravit položku';
 $labels['preferhtml'] = 'Upřednostňovat HTML zobrazení';
 $labels['defaultcharset'] = 'Výchozí kódování';
 $labels['htmlmessage'] = 'HTML zpráva';
 $labels['preferhtml'] = 'Upřednostňovat HTML zobrazení';
 $labels['defaultcharset'] = 'Výchozí kódování';
 $labels['htmlmessage'] = 'HTML zpráva';
+$labels['dateformat'] = 'Formát data';
+$labels['timeformat'] = 'Formát času';
 $labels['prettydate'] = 'Hezčí datum';
 $labels['setdefault'] = 'Nastavit výchozí';
 $labels['autodetect'] = 'Automaticky';
 $labels['prettydate'] = 'Hezčí datum';
 $labels['setdefault'] = 'Nastavit výchozí';
 $labels['autodetect'] = 'Automaticky';
@@ -356,6 +375,13 @@ $labels['afternseconds'] = 'po $n sekundách';
 $labels['reqmdn'] = 'Vždy požadovat doručenku';
 $labels['reqdsn'] = 'Vždy požádat o oznámení o stavu doručení';
 $labels['replysamefolder'] = 'Ukládat odpovědi ve stejné složce jako je zodpovězená zpráva';
 $labels['reqmdn'] = 'Vždy požadovat doručenku';
 $labels['reqdsn'] = 'Vždy požádat o oznámení o stavu doručení';
 $labels['replysamefolder'] = 'Ukládat odpovědi ve stejné složce jako je zodpovězená zpráva';
+$labels['defaultaddressbook'] = 'Přidávat nové kontakty do seznamu kontaktů';
+$labels['spellcheckbeforesend'] = 'Před odesláním zkontrolovat pravopis';
+$labels['spellcheckoptions'] = 'Nastavení pravopisu';
+$labels['spellcheckignoresyms'] = 'Ignorovat slova obsahující symboly';
+$labels['spellcheckignorenums'] = 'Ignorovat slova obsahující čísla';
+$labels['spellcheckignorecaps'] = 'Ignorovat slova psaná velkými písmeny';
+$labels['addtodict'] = 'Přidat do slovníku';
 $labels['folder'] = 'Složka';
 $labels['folders'] = 'Složky';
 $labels['foldername'] = 'Jméno složky';
 $labels['folder'] = 'Složka';
 $labels['folders'] = 'Složky';
 $labels['foldername'] = 'Jméno složky';
@@ -379,6 +405,7 @@ $labels['sharedfolder'] = 'Sdílená složka';
 $labels['sortby'] = 'Seřadit podle';
 $labels['sortasc'] = 'Seřadit vzestupně';
 $labels['sortdesc'] = 'Seřadit sestupně';
 $labels['sortby'] = 'Seřadit podle';
 $labels['sortasc'] = 'Seřadit vzestupně';
 $labels['sortdesc'] = 'Seřadit sestupně';
+$labels['undo'] = 'Vrátit zpět';
 $labels['B'] = 'B';
 $labels['KB'] = 'KB';
 $labels['MB'] = 'MB';
 $labels['B'] = 'B';
 $labels['KB'] = 'KB';
 $labels['MB'] = 'MB';
index 13c4dd44d47a04b16e96515c5e47be26f08754bf..a47b8d8d50debec1b39f9f5bcd98f72e76e597d5 100644 (file)
@@ -16,7 +16,7 @@
 |        Ales Pospichal <ales@pospichalales.info>                       |
 +-----------------------------------------------------------------------+
 
 |        Ales Pospichal <ales@pospichalales.info>                       |
 +-----------------------------------------------------------------------+
 
-@version $Id: messages.inc 4671 2011-04-20 08:47:44Z thomasb $
+@version $Id: messages.inc 5569 2011-12-07 14:47:32Z thomasb $
 
 */
 
 
 */
 
@@ -27,6 +27,7 @@ $messages['sessionerror'] = 'Vaše přihlášení je neplatné nebo vypršelo';
 $messages['imaperror'] = 'Připojení na IMAP server selhalo';
 $messages['servererror'] = 'Chyba serveru!';
 $messages['servererrormsg'] = 'Chyba serveru: $msg';
 $messages['imaperror'] = 'Připojení na IMAP server selhalo';
 $messages['servererror'] = 'Chyba serveru!';
 $messages['servererrormsg'] = 'Chyba serveru: $msg';
+$messages['dberror'] = 'Chyba v databázi!';
 $messages['errorreadonly'] = 'Příkaz nelze provést, složka je určena jen ke čtení.';
 $messages['errornoperm'] = 'Příkaz nelze provést, nemáte oprávnění.';
 $messages['invalidrequest'] = 'Nesprávný požadavek. Data nebyla uložena.';
 $messages['errorreadonly'] = 'Příkaz nelze provést, složka je určena jen ke čtení.';
 $messages['errornoperm'] = 'Příkaz nelze provést, nemáte oprávnění.';
 $messages['invalidrequest'] = 'Nesprávný požadavek. Data nebyla uložena.';
@@ -35,6 +36,7 @@ $messages['loggedout'] = 'Byli jste úspěšně odhlášeni. Nashledanou!';
 $messages['mailboxempty'] = 'Schránka je prázdná';
 $messages['loading'] = 'Načítám...';
 $messages['uploading'] = 'Nahrávám soubor...';
 $messages['mailboxempty'] = 'Schránka je prázdná';
 $messages['loading'] = 'Načítám...';
 $messages['uploading'] = 'Nahrávám soubor...';
+$messages['uploadingmany'] = 'Nahrávám soubory...';
 $messages['loadingdata'] = 'Načítám data...';
 $messages['checkingmail'] = 'Kontroluji nové zprávy...';
 $messages['sendingmessage'] = 'Odesílám zprávu...';
 $messages['loadingdata'] = 'Načítám data...';
 $messages['checkingmail'] = 'Kontroluji nové zprávy...';
 $messages['sendingmessage'] = 'Odesílám zprávu...';
@@ -44,10 +46,12 @@ $messages['messagesaved'] = 'Zpráva uložena do Rozepsané';
 $messages['successfullysaved'] = 'Uloženo';
 $messages['addedsuccessfully'] = 'Kontakt byl úspěšně přidán do adresáře';
 $messages['contactexists'] = 'Kontakt se zadanou e-mailovou adresou již existuje';
 $messages['successfullysaved'] = 'Uloženo';
 $messages['addedsuccessfully'] = 'Kontakt byl úspěšně přidán do adresáře';
 $messages['contactexists'] = 'Kontakt se zadanou e-mailovou adresou již existuje';
+$messages['contactnameexists'] = 'Kontakt se stejným jménem již existuje';
 $messages['blockedimages'] = 'Z bezpečnostních důvodů byly zablokovány obrázky ve zprávě.';
 $messages['encryptedmessage'] = 'Tato zpráva je zašifrovaná a nelze ji zobrazit.';
 $messages['blockedimages'] = 'Z bezpečnostních důvodů byly zablokovány obrázky ve zprávě.';
 $messages['encryptedmessage'] = 'Tato zpráva je zašifrovaná a nelze ji zobrazit.';
-$messages['nocontactsfound'] = 'Nemáte žádné kontakty';
+$messages['nocontactsfound'] = 'Kontakty nebyly nalezeny';
 $messages['contactnotfound'] = 'Požadovaný kontakt nebyl nalezen.';
 $messages['contactnotfound'] = 'Požadovaný kontakt nebyl nalezen.';
+$messages['contactsearchonly'] = 'Vyplňte některou z položek';
 $messages['sendingfailed'] = 'Odesílání zprávy selhalo';
 $messages['senttooquickly'] = 'Prosím počkejte $sec sekund před odesláním zprávy';
 $messages['errorsavingsent'] = 'Nastala chyba při ukládání odeslané zprávy';
 $messages['sendingfailed'] = 'Odesílání zprávy selhalo';
 $messages['senttooquickly'] = 'Prosím počkejte $sec sekund před odesláním zprávy';
 $messages['errorsavingsent'] = 'Nastala chyba při ukládání odeslané zprávy';
@@ -57,9 +61,12 @@ $messages['errorcopying'] = 'Nemohu zkopírovat zprávu';
 $messages['errordeleting'] = 'Nemohu smazat zprávu';
 $messages['errormarking'] = 'Zprávu nelze označit';
 $messages['deletecontactconfirm'] = 'Opravdu chcete smazat označené kontakty?';
 $messages['errordeleting'] = 'Nemohu smazat zprávu';
 $messages['errormarking'] = 'Zprávu nelze označit';
 $messages['deletecontactconfirm'] = 'Opravdu chcete smazat označené kontakty?';
+$messages['deletegroupconfirm'] = 'Opravdu chcete smazat skupinu?';
 $messages['deletemessagesconfirm'] = 'Opravdu chcete smazat označené zprávy?';
 $messages['deletefolderconfirm'] = 'Chcete opravdu smazat tento adresář?';
 $messages['purgefolderconfirm'] = 'Opravdu chcete smazat všechny zprávy v této složce?';
 $messages['deletemessagesconfirm'] = 'Opravdu chcete smazat označené zprávy?';
 $messages['deletefolderconfirm'] = 'Chcete opravdu smazat tento adresář?';
 $messages['purgefolderconfirm'] = 'Opravdu chcete smazat všechny zprávy v této složce?';
+$messages['contactdeleting'] = 'Mažu kontakty...';
+$messages['groupdeleting'] = 'Mažu skupinu...';
 $messages['folderdeleting'] = 'Odstraňuji složku...';
 $messages['foldermoving'] = 'Přesouvám složku...';
 $messages['foldersubscribing'] = 'Připojuji složku...';
 $messages['folderdeleting'] = 'Odstraňuji složku...';
 $messages['foldermoving'] = 'Přesouvám složku...';
 $messages['foldersubscribing'] = 'Připojuji složku...';
@@ -74,10 +81,10 @@ $messages['nosubjectwarning'] = 'Předmět nebyl vyplňen. Přejete si jej zadat
 $messages['nobodywarning'] = 'Opravdu chtete odeslat prázdnou zprávu?';
 $messages['notsentwarning'] = 'Zpráva nebyla odeslána. Přejete si zprávu zahodit?';
 $messages['noldapserver'] = 'Zvolte, prosím, LDAP server k hledání';
 $messages['nobodywarning'] = 'Opravdu chtete odeslat prázdnou zprávu?';
 $messages['notsentwarning'] = 'Zpráva nebyla odeslána. Přejete si zprávu zahodit?';
 $messages['noldapserver'] = 'Zvolte, prosím, LDAP server k hledání';
-$messages['nocontactsreturned'] = 'Nebyly nalezeny žádné kontakty';
 $messages['nosearchname'] = 'Zadejte, prosím, jméno nebo e-mail kontaktu';
 $messages['notuploadedwarning'] = 'Ještě nebyly nahrány všechny přílohy. Počkejte prosím nebo nahrávání zrušte.';
 $messages['nosearchname'] = 'Zadejte, prosím, jméno nebo e-mail kontaktu';
 $messages['notuploadedwarning'] = 'Ještě nebyly nahrány všechny přílohy. Počkejte prosím nebo nahrávání zrušte.';
-$messages['searchsuccessful'] = '$nr zpráv nalezeno';
+$messages['searchsuccessful'] = 'Nalezeno $nr zpráv';
+$messages['contactsearchsuccessful'] = 'Nalezeno $nr kontaktů';
 $messages['searchnomatch'] = 'Nenalezena žádná zpráva';
 $messages['searching'] = 'Vyhledávám...';
 $messages['checking'] = 'Kontroluji...';
 $messages['searchnomatch'] = 'Nenalezena žádná zpráva';
 $messages['searching'] = 'Vyhledávám...';
 $messages['checking'] = 'Kontroluji...';
@@ -98,8 +105,11 @@ $messages['sourceisreadonly'] = 'Tento zdroj adres je pouze pro čtení';
 $messages['errorsavingcontact'] = 'Nemohu uložit adresu kontaktu';
 $messages['movingmessage'] = 'Přesouvám zprávu...';
 $messages['copyingmessage'] = 'Kopíruji zprávu...';
 $messages['errorsavingcontact'] = 'Nemohu uložit adresu kontaktu';
 $messages['movingmessage'] = 'Přesouvám zprávu...';
 $messages['copyingmessage'] = 'Kopíruji zprávu...';
+$messages['copyingcontact'] = 'Kopíruji kontakty...';
 $messages['deletingmessage'] = 'Odstraňuji zprávu...';
 $messages['markingmessage'] = 'Označuji zprávu...';
 $messages['deletingmessage'] = 'Odstraňuji zprávu...';
 $messages['markingmessage'] = 'Označuji zprávu...';
+$messages['addingmember'] = 'Přidávám kontakty do skupiny...';
+$messages['removingmember'] = 'Odstraňuji kontakty ze skupiny...';
 $messages['receiptsent'] = 'Potvrzení o přřijetí zprávy odesláno';
 $messages['errorsendingreceipt'] = 'Potvrzení o přijetí zprávy nebylo možné odeslat';
 $messages['nodeletelastidentity'] = 'Alespoň jedna identita musí být ponechána. Identitu nelze odstranit.';
 $messages['receiptsent'] = 'Potvrzení o přřijetí zprávy odesláno';
 $messages['errorsendingreceipt'] = 'Potvrzení o přijetí zprávy nebylo možné odeslat';
 $messages['nodeletelastidentity'] = 'Alespoň jedna identita musí být ponechána. Identitu nelze odstranit.';
@@ -111,7 +121,7 @@ $messages['contactremovedfromgroup'] = 'Kontakty byly odstraněny z této skupin
 $messages['importwait'] = 'Importuji, prosím čekejte...';
 $messages['importerror'] = 'Během importu nastala chyba! Nahraný soubor není ve formátu vCard.';
 $messages['importconfirm'] = 'Úspěšně naimportováno $inserted kontaktů, $skipped existujících záznamů přeskočeno: $names';
 $messages['importwait'] = 'Importuji, prosím čekejte...';
 $messages['importerror'] = 'Během importu nastala chyba! Nahraný soubor není ve formátu vCard.';
 $messages['importconfirm'] = 'Úspěšně naimportováno $inserted kontaktů, $skipped existujících záznamů přeskočeno: $names';
-$messages['importconfirmskipped'] = '<b>Přeskočeno $skipped existing entries</b>';
+$messages['importconfirmskipped'] = '<b>Přeskočeno $skipped existujících položek</b>';
 $messages['opnotpermitted'] = 'Operace není povolena!';
 $messages['nofromaddress'] = 'Chybějící e-mailová adresa v označeném profilu';
 $messages['editorwarning'] = 'Přepnutím do režimu prostého textu ztratíte veškeré formátování. Chcete pokračovat?';
 $messages['opnotpermitted'] = 'Operace není povolena!';
 $messages['nofromaddress'] = 'Chybějící e-mailová adresa v označeném profilu';
 $messages['editorwarning'] = 'Přepnutím do režimu prostého textu ztratíte veškeré formátování. Chcete pokračovat?';
@@ -129,18 +139,27 @@ $messages['maxgroupmembersreached'] = 'Počet členských skupin dosáhl maximum
 $messages['internalerror'] = 'Došlo k interní chybě. Zkuste to znovu';
 $messages['contactdelerror'] = 'Kontakty nelze odstranit';
 $messages['contactdeleted'] = 'Kontakty byly odstraněny';
 $messages['internalerror'] = 'Došlo k interní chybě. Zkuste to znovu';
 $messages['contactdelerror'] = 'Kontakty nelze odstranit';
 $messages['contactdeleted'] = 'Kontakty byly odstraněny';
+$messages['contactrestoreerror'] = 'Nelze obnovit smazané kontakty';
+$messages['contactrestored'] = 'Kontakty byly obnoveny';
 $messages['groupdeleted'] = 'Skupina byla odstraněna';
 $messages['grouprenamed'] = 'Skupina byla přejmenována';
 $messages['groupcreated'] = 'Skupina vytvořena';
 $messages['groupdeleted'] = 'Skupina byla odstraněna';
 $messages['grouprenamed'] = 'Skupina byla přejmenována';
 $messages['groupcreated'] = 'Skupina vytvořena';
+$messages['savedsearchdeleted'] = 'Uložené hledání bylo ostraněno';
+$messages['savedsearchdeleteerror'] = 'Nelze odstranit uložené hledání';
+$messages['savedsearchcreated'] = 'Nové hledání bylo vytvořeno';
+$messages['savedsearchcreateerror'] = 'Nelze vytvořit uložené hledání';
 $messages['messagedeleted'] = 'Zpráva odstraněna';
 $messages['messagemoved'] = 'Zpráva byla přesunuta';
 $messages['messagecopied'] = 'Zpráva byla zkopirována';
 $messages['messagemarked'] = 'Zpráva označena';
 $messages['autocompletechars'] = 'Napište alespoň $min znaků pro automatické doplnění';
 $messages['messagedeleted'] = 'Zpráva odstraněna';
 $messages['messagemoved'] = 'Zpráva byla přesunuta';
 $messages['messagecopied'] = 'Zpráva byla zkopirována';
 $messages['messagemarked'] = 'Zpráva označena';
 $messages['autocompletechars'] = 'Napište alespoň $min znaků pro automatické doplnění';
+$messages['autocompletemore'] = 'Napište více znaků. Nalezeno příliš mnoho položek';
 $messages['namecannotbeempty'] = 'Jméno musí být vyplněno';
 $messages['nametoolong'] = 'Jméno je příliš dlouhé';
 $messages['folderupdated'] = 'Složka byla úspěšně aktualizována';
 $messages['foldercreated'] = 'Složka byla úspěšně vytvořena';
 $messages['invalidimageformat'] = 'Formát obrázku není podporován';
 $messages['namecannotbeempty'] = 'Jméno musí být vyplněno';
 $messages['nametoolong'] = 'Jméno je příliš dlouhé';
 $messages['folderupdated'] = 'Složka byla úspěšně aktualizována';
 $messages['foldercreated'] = 'Složka byla úspěšně vytvořena';
 $messages['invalidimageformat'] = 'Formát obrázku není podporován';
+$messages['mispellingsfound'] = 'Ve zprávě byly zjištěny pravopisné chyby';
+$messages['parentnotwritable'] = 'Nelze vytvořit/přesunout složku do vybrané rodičovské složky. Nemáte práva.';
 
 ?>
 
 ?>
index e1588d03319f4e603e86c5acfb6a479355db26e0..f3d521b9ba9e2d9aaa654055bb9b1e6b7204561a 100644 (file)
@@ -114,7 +114,7 @@ $labels['markread'] = 'Wedi eu darllen';
 $labels['markunread'] = 'Heb eu darllen';
 $labels['markflagged'] = 'Wedi eu fflagio';
 $labels['markunflagged'] = 'Heb eu fflagio';
 $labels['markunread'] = 'Heb eu darllen';
 $labels['markflagged'] = 'Wedi eu fflagio';
 $labels['markunflagged'] = 'Heb eu fflagio';
-$labels['messageactions'] = 'Mwy o weithredoedd...';
+$labels['moreactions'] = 'Mwy o weithredoedd...';
 $labels['select'] = 'Dewis';
 $labels['all'] = 'Popeth';
 $labels['none'] = 'Dim byd';
 $labels['select'] = 'Dewis';
 $labels['all'] = 'Popeth';
 $labels['none'] = 'Dim byd';
@@ -186,6 +186,7 @@ $labels['highest'] = 'Uchaf';
 $labels['nosubject'] = '(dim pwnc)';
 $labels['showimages'] = 'Dangos lluniau';
 $labels['alwaysshow'] = 'Dangos lluniau bob amser o $sender';
 $labels['nosubject'] = '(dim pwnc)';
 $labels['showimages'] = 'Dangos lluniau';
 $labels['alwaysshow'] = 'Dangos lluniau bob amser o $sender';
+$labels['isdraft'] = 'Mae hwn yn neges ddrafft';
 $labels['htmltoggle'] = 'HTML';
 $labels['plaintoggle'] = 'Testun plaen';
 $labels['savesentmessagein'] = 'Cadw negeseuon a ddanfonir yn';
 $labels['htmltoggle'] = 'HTML';
 $labels['plaintoggle'] = 'Testun plaen';
 $labels['savesentmessagein'] = 'Cadw negeseuon a ddanfonir yn';
@@ -267,7 +268,6 @@ $labels['print'] = 'Argraffu';
 $labels['export'] = 'Allforio';
 $labels['exportvcards'] = 'Allforio cysylltiadau mewn fformat vCard';
 $labels['newcontactgroup'] = 'Creu grŵp cysylltiadau newydd';
 $labels['export'] = 'Allforio';
 $labels['exportvcards'] = 'Allforio cysylltiadau mewn fformat vCard';
 $labels['newcontactgroup'] = 'Creu grŵp cysylltiadau newydd';
-$labels['groupactions'] = 'Gweithredoedd ar gyfer grwpiau cysylltiadau...';
 $labels['grouprename'] = 'Ail-enwi grŵp';
 $labels['groupdelete'] = 'Dileu grŵp';
 $labels['previouspage'] = 'Dangos y set flaenorol';
 $labels['grouprename'] = 'Ail-enwi grŵp';
 $labels['groupdelete'] = 'Dileu grŵp';
 $labels['previouspage'] = 'Dangos y set flaenorol';
@@ -277,6 +277,8 @@ $labels['lastpage'] = 'Dangos y set olaf';
 $labels['group'] = 'Grŵp';
 $labels['groups'] = 'Grwpiau';
 $labels['personaladrbook'] = 'Cyfeiriadau Personol';
 $labels['group'] = 'Grŵp';
 $labels['groups'] = 'Grwpiau';
 $labels['personaladrbook'] = 'Cyfeiriadau Personol';
+$labels['searchsave'] = 'Cadw chwiliad';
+$labels['searchdelete'] = 'Dileu chwiliad';
 $labels['import'] = 'Mewnforio';
 $labels['importcontacts'] = 'Mewnforio cysylltiadau';
 $labels['importfromfile'] = 'Mewnforio o ffeil:';
 $labels['import'] = 'Mewnforio';
 $labels['importcontacts'] = 'Mewnforio cysylltiadau';
 $labels['importfromfile'] = 'Mewnforio o ffeil:';
@@ -285,6 +287,7 @@ $labels['importreplace'] = 'Dileu y llyfr cyfeiriadau cyfan wrth lwytho';
 $labels['importtext'] = 'Fe allwch chi lwytho fyny cysylltiadau o lyfr cyfeiriadau sy\'n bodoli yn barod. Ar hyn o bryd rydyn\' ni\'n cefnogi mewnforio cyfeiriadau yn y fformat <a href="http://en.wikipedia.org/wiki/VCard">vCard</a>.';
 $labels['done'] = 'Wedi gorffen';
 $labels['settingsfor'] = 'Gosodiadau ar gyfer';
 $labels['importtext'] = 'Fe allwch chi lwytho fyny cysylltiadau o lyfr cyfeiriadau sy\'n bodoli yn barod. Ar hyn o bryd rydyn\' ni\'n cefnogi mewnforio cyfeiriadau yn y fformat <a href="http://en.wikipedia.org/wiki/VCard">vCard</a>.';
 $labels['done'] = 'Wedi gorffen';
 $labels['settingsfor'] = 'Gosodiadau ar gyfer';
+$labels['about'] = 'Amdan';
 $labels['preferences'] = 'Dewisiadau';
 $labels['userpreferences'] = 'Dewisiadau\'r defnyddiwr';
 $labels['editpreferences'] = 'Golygu dewisiadau\'r defnyddiwr';
 $labels['preferences'] = 'Dewisiadau';
 $labels['userpreferences'] = 'Dewisiadau\'r defnyddiwr';
 $labels['editpreferences'] = 'Golygu dewisiadau\'r defnyddiwr';
@@ -296,6 +299,8 @@ $labels['edititem'] = 'Golygu eitem';
 $labels['preferhtml'] = 'Dangos HTML';
 $labels['defaultcharset'] = 'Set Nodau Diofyn';
 $labels['htmlmessage'] = 'Neges HTML';
 $labels['preferhtml'] = 'Dangos HTML';
 $labels['defaultcharset'] = 'Set Nodau Diofyn';
 $labels['htmlmessage'] = 'Neges HTML';
+$labels['dateformat'] = 'Fformat dyddiad';
+$labels['timeformat'] = 'Fformat amser';
 $labels['prettydate'] = 'Dyddiadau pert';
 $labels['setdefault'] = 'Rhagosod';
 $labels['autodetect'] = 'Awto';
 $labels['prettydate'] = 'Dyddiadau pert';
 $labels['setdefault'] = 'Rhagosod';
 $labels['autodetect'] = 'Awto';
@@ -367,7 +372,13 @@ $labels['reqmdn'] = 'Bob amser gofyn am dderbynneb danfon';
 $labels['reqdsn'] = 'Gofyn am hysbysiad statws danfon bob amser';
 $labels['replysamefolder'] = 'Rhoi atebion yn yr un ffolder i\'r neges sy\'n cael ei ateb';
 $labels['defaultaddressbook'] = 'Ychwanegu cysylltiadau newydd i\'r llyfr cyfeiriad dewiswyd';
 $labels['reqdsn'] = 'Gofyn am hysbysiad statws danfon bob amser';
 $labels['replysamefolder'] = 'Rhoi atebion yn yr un ffolder i\'r neges sy\'n cael ei ateb';
 $labels['defaultaddressbook'] = 'Ychwanegu cysylltiadau newydd i\'r llyfr cyfeiriad dewiswyd';
+$labels['autocompletesingle'] = 'Hepgor cyfeiriadau ebost amgen wrth awto-gwblhau';
 $labels['spellcheckbeforesend'] = 'Gwirio sillafu cyn danfon neges';
 $labels['spellcheckbeforesend'] = 'Gwirio sillafu cyn danfon neges';
+$labels['spellcheckoptions'] = 'Dewisiadau gwirio sillafu';
+$labels['spellcheckignoresyms'] = 'Anwybyddu geiriau gyda symbolau';
+$labels['spellcheckignorenums'] = 'Anwybyddu geiriau gyda rhifau';
+$labels['spellcheckignorecaps'] = 'Anwybyddu geiriau sy\'n briflythrennau yn gyfangwbl';
+$labels['addtodict'] = 'Ychwanegu i\'r geiriadur';
 $labels['folder'] = 'Ffolder';
 $labels['folders'] = 'Ffolderi';
 $labels['foldername'] = 'Enw ffolder';
 $labels['folder'] = 'Ffolder';
 $labels['folders'] = 'Ffolderi';
 $labels['foldername'] = 'Enw ffolder';
@@ -392,6 +403,11 @@ $labels['sortby'] = 'Trefnu yn ôl';
 $labels['sortasc'] = 'Trefn esgynnol';
 $labels['sortdesc'] = 'Trefn ddisgynnol';
 $labels['undo'] = 'Dad-wneud';
 $labels['sortasc'] = 'Trefn esgynnol';
 $labels['sortdesc'] = 'Trefn ddisgynnol';
 $labels['undo'] = 'Dad-wneud';
+$labels['plugin'] = 'Ategyn';
+$labels['version'] = 'Fersiwn';
+$labels['source'] = 'Ffynhonnell';
+$labels['license'] = 'Trwydded';
+$labels['support'] = 'Gofyn am gymorth';
 $labels['B'] = 'B';
 $labels['KB'] = 'KB';
 $labels['MB'] = 'MB';
 $labels['B'] = 'B';
 $labels['KB'] = 'KB';
 $labels['MB'] = 'MB';
index 0e965971d30f9d944d578185e6824806c76f49ee..51223011bacd2d460257dffb40d0246788a5dd54 100644 (file)
@@ -45,6 +45,7 @@ $messages['blockedimages'] = 'I amddiffyn eich preifatrwydd, fe ataliwyd lluniau
 $messages['encryptedmessage'] = 'Mae hon yn neges amgryptedig a felly ni ellir ei ddangos. Flin iawn!';
 $messages['nocontactsfound'] = 'Ni gafwyd hyd i unrhyw gysylltiadau';
 $messages['contactnotfound'] = 'Ni gafwyd hyd i\'r cysylltiad gofynnwyd amdano';
 $messages['encryptedmessage'] = 'Mae hon yn neges amgryptedig a felly ni ellir ei ddangos. Flin iawn!';
 $messages['nocontactsfound'] = 'Ni gafwyd hyd i unrhyw gysylltiadau';
 $messages['contactnotfound'] = 'Ni gafwyd hyd i\'r cysylltiad gofynnwyd amdano';
+$messages['contactsearchonly'] = 'Rhowch dermau chwilio i ganfod cysylltiadau';
 $messages['sendingfailed'] = 'Methwyd danfon y neges';
 $messages['senttooquickly'] = 'Arhoswch $sec eiliad cyn danfon y neges';
 $messages['errorsavingsent'] = 'Fe gafwyd gwall wrth cadw\'r neges ddanfonwyd';
 $messages['sendingfailed'] = 'Methwyd danfon y neges';
 $messages['senttooquickly'] = 'Arhoswch $sec eiliad cyn danfon y neges';
 $messages['errorsavingsent'] = 'Fe gafwyd gwall wrth cadw\'r neges ddanfonwyd';
@@ -58,6 +59,7 @@ $messages['deletegroupconfirm'] = 'Ydych chi wir am ddileu\'r grŵp dewiswyd?';
 $messages['deletemessagesconfirm'] = 'Ydych chi wir am ddileu y neges(euon) ddewiswyd?';
 $messages['deletefolderconfirm'] = 'Ydych chi wir am ddileu y ffolder yma?';
 $messages['purgefolderconfirm'] = 'Ydych chi wir am ddileu yr holl negeseuon yn y ffolder yma?';
 $messages['deletemessagesconfirm'] = 'Ydych chi wir am ddileu y neges(euon) ddewiswyd?';
 $messages['deletefolderconfirm'] = 'Ydych chi wir am ddileu y ffolder yma?';
 $messages['purgefolderconfirm'] = 'Ydych chi wir am ddileu yr holl negeseuon yn y ffolder yma?';
+$messages['contactdeleting'] = 'Dileu cyswllt/cysylltiadau...';
 $messages['groupdeleting'] = 'Yn dileu grŵp...';
 $messages['folderdeleting'] = 'Yn dileu ffolder...';
 $messages['foldermoving'] = 'Yn symud ffolder...';
 $messages['groupdeleting'] = 'Yn dileu grŵp...';
 $messages['folderdeleting'] = 'Yn dileu ffolder...';
 $messages['foldermoving'] = 'Yn symud ffolder...';
@@ -73,10 +75,10 @@ $messages['nosubjectwarning'] = 'Mae\'r pennawd \"Pwnc\" yn wag. Hoffech chi roi
 $messages['nobodywarning'] = 'Danfon y neges hwn heb destun?';
 $messages['notsentwarning'] = 'Ni ddanfonwyd y neges. Hoffech chi gael gwared a\'r neges?';
 $messages['noldapserver'] = 'Dewiswch weinydd ldap i chwilio';
 $messages['nobodywarning'] = 'Danfon y neges hwn heb destun?';
 $messages['notsentwarning'] = 'Ni ddanfonwyd y neges. Hoffech chi gael gwared a\'r neges?';
 $messages['noldapserver'] = 'Dewiswch weinydd ldap i chwilio';
-$messages['nocontactsreturned'] = 'Ni gafwyd hyd i unrhyw gysylltiadau';
 $messages['nosearchname'] = 'Rhowch enw cyswllt neu gyfeiriad e-bost';
 $messages['notuploadedwarning'] = 'Nid yw pob atodiad wedi eu llwytho i fyny eto. Triwch eto neu canslo.';
 $messages['searchsuccessful'] = 'Cafwyd hyd i $nr neges';
 $messages['nosearchname'] = 'Rhowch enw cyswllt neu gyfeiriad e-bost';
 $messages['notuploadedwarning'] = 'Nid yw pob atodiad wedi eu llwytho i fyny eto. Triwch eto neu canslo.';
 $messages['searchsuccessful'] = 'Cafwyd hyd i $nr neges';
+$messages['contactsearchsuccessful'] = 'Canfuwyd $nr cyswllt.';
 $messages['searchnomatch'] = 'Ni gafwyd hyd i unrhyw ganlyniadau chwilio';
 $messages['searching'] = 'Yn chwilio...';
 $messages['checking'] = 'Yn gofyn...';
 $messages['searchnomatch'] = 'Ni gafwyd hyd i unrhyw ganlyniadau chwilio';
 $messages['searching'] = 'Yn chwilio...';
 $messages['checking'] = 'Yn gofyn...';
@@ -123,7 +125,6 @@ $messages['smtpautherror'] = 'Gwall SMTP ($code): Methwyd dilysu\'r cyfrif';
 $messages['smtpfromerror'] = 'Gwall SMTP ($code): Methwyd gosod y danfonwr "$from" ($msg)';
 $messages['smtptoerror'] = 'Gwall SMTP ($code): Methwyd ychwanegu derbynwr "$to" ($msg)';
 $messages['smtprecipientserror'] = 'Gwall SMTP: Nid oedd yn bosib darllen y rhestr o dderbynnwyr';
 $messages['smtpfromerror'] = 'Gwall SMTP ($code): Methwyd gosod y danfonwr "$from" ($msg)';
 $messages['smtptoerror'] = 'Gwall SMTP ($code): Methwyd ychwanegu derbynwr "$to" ($msg)';
 $messages['smtprecipientserror'] = 'Gwall SMTP: Nid oedd yn bosib darllen y rhestr o dderbynnwyr';
-$messages['smtpdsnerror'] = 'Gwall SMTP: Dim cefnogaeth i Hysbysiadau Statws Danfon';
 $messages['smtperror'] = 'Gwall SMTP: $msg';
 $messages['emailformaterror'] = 'Cyfeiriad e-bost anghywir: $email';
 $messages['toomanyrecipients'] = 'Gormod o dderbynnwyr. Lleihewch y nifer i $max';
 $messages['smtperror'] = 'Gwall SMTP: $msg';
 $messages['emailformaterror'] = 'Cyfeiriad e-bost anghywir: $email';
 $messages['toomanyrecipients'] = 'Gormod o dderbynnwyr. Lleihewch y nifer i $max';
@@ -136,11 +137,16 @@ $messages['contactrestored'] = 'Adferwyd y cyswllt/cysylltiadau';
 $messages['groupdeleted'] = 'Grŵp wedi ei ddileu yn llwyddiannus';
 $messages['grouprenamed'] = 'Grŵp wedi ei ailenwi yn llwyddiannus';
 $messages['groupcreated'] = 'Grŵp wedi ei greu yn llwyddiannus';
 $messages['groupdeleted'] = 'Grŵp wedi ei ddileu yn llwyddiannus';
 $messages['grouprenamed'] = 'Grŵp wedi ei ailenwi yn llwyddiannus';
 $messages['groupcreated'] = 'Grŵp wedi ei greu yn llwyddiannus';
+$messages['savedsearchdeleted'] = 'Dilëwyd y chwiliad yn llwyddiannus.';
+$messages['savedsearchdeleteerror'] = 'Methwyd dileu y chwiliad.';
+$messages['savedsearchcreated'] = 'Crëwyd y chwiliad yn llwyddiannus.';
+$messages['savedsearchcreateerror'] = 'Methwyd creu y chwiliad.';
 $messages['messagedeleted'] = 'Neges(euon) wedi eu dileu yn llwyddiannus';
 $messages['messagemoved'] = 'Neges(euon) wedi eu symud yn llwyddiannus';
 $messages['messagecopied'] = 'Neges(euon) wedi eu copïo yn llwyddiannus';
 $messages['messagemarked'] = 'Neges(euon) wedi eu marcio yn llwyddiannus';
 $messages['autocompletechars'] = 'Rhowch o leia $min llythyren ar gyfer awto-gwblhau';
 $messages['messagedeleted'] = 'Neges(euon) wedi eu dileu yn llwyddiannus';
 $messages['messagemoved'] = 'Neges(euon) wedi eu symud yn llwyddiannus';
 $messages['messagecopied'] = 'Neges(euon) wedi eu copïo yn llwyddiannus';
 $messages['messagemarked'] = 'Neges(euon) wedi eu marcio yn llwyddiannus';
 $messages['autocompletechars'] = 'Rhowch o leia $min llythyren ar gyfer awto-gwblhau';
+$messages['autocompletemore'] = 'Canfuwyd mwy o gofnodion sy\'n cyfateb. Teipiwch fwy o lythrennau.';
 $messages['namecannotbeempty'] = 'Ni all yr enw fod yn wag';
 $messages['nametoolong'] = 'Mae\'r enw yn rhy hir';
 $messages['folderupdated'] = 'Diweddarwyd y ffolder yn llwyddiannus';
 $messages['namecannotbeempty'] = 'Ni all yr enw fod yn wag';
 $messages['nametoolong'] = 'Mae\'r enw yn rhy hir';
 $messages['folderupdated'] = 'Diweddarwyd y ffolder yn llwyddiannus';
@@ -148,5 +154,6 @@ $messages['foldercreated'] = 'Crëwyd y ffolder yn llwyddiannus';
 $messages['invalidimageformat'] = 'Ddim yn fformat llun dilys.';
 $messages['mispellingsfound'] = 'Gwelwyd camsillafu yn y neges.';
 $messages['parentnotwritable'] = 'Methwyd creu/symud ffolder i\'r ffolder rhiant ddewiswyd. Dim hawl mynediad.';
 $messages['invalidimageformat'] = 'Ddim yn fformat llun dilys.';
 $messages['mispellingsfound'] = 'Gwelwyd camsillafu yn y neges.';
 $messages['parentnotwritable'] = 'Methwyd creu/symud ffolder i\'r ffolder rhiant ddewiswyd. Dim hawl mynediad.';
+$messages['messagetoobig'] = 'Mae darn y neges yn rhy fawr i\'w brosesu.';
 
 ?>
 
 ?>
index cf766eed901f63a886d6521c2e58acd651d43bd5..5922e6d7036a31f171485198b5be054d955afb22 100644 (file)
 | Author: Martin Moeller <martin@liga.dk>                               |
 |         Jesper R. Meyer <jrm@upthere.dk>                              |
 |         Søren Aggeboe <soren@aggeboe.dk>                              |
 | Author: Martin Moeller <martin@liga.dk>                               |
 |         Jesper R. Meyer <jrm@upthere.dk>                              |
 |         Søren Aggeboe <soren@aggeboe.dk>                              |
+|         John Loft Christiansen <john@nansensvej.dk>                   |
 +-----------------------------------------------------------------------+
 
 +-----------------------------------------------------------------------+
 
-@version $Id: labels.inc 4462 2011-01-28 16:01:03Z thomasb $
-
+@version $Id: labels.inc 5569 2011-12-07 14:47:32Z thomasb $
 */
 
 $labels = array();
 */
 
 $labels = array();
+
+// login page
 $labels['welcome'] = 'Velkommen til $product';
 $labels['username'] = 'Brugernavn';
 $labels['password'] = 'Adgangskode';
 $labels['server'] = 'Server';
 $labels['login'] = 'Log på';
 $labels['welcome'] = 'Velkommen til $product';
 $labels['username'] = 'Brugernavn';
 $labels['password'] = 'Adgangskode';
 $labels['server'] = 'Server';
 $labels['login'] = 'Log på';
+
+// Taskbar
 $labels['logout'] = 'Log af';
 $labels['mail'] = 'E-mail';
 $labels['settings'] = 'Personlige indstillinger';
 $labels['addressbook'] = 'Adressebog';
 $labels['logout'] = 'Log af';
 $labels['mail'] = 'E-mail';
 $labels['settings'] = 'Personlige indstillinger';
 $labels['addressbook'] = 'Adressebog';
+
+// mailbox names
 $labels['inbox'] = 'Indbakke';
 $labels['drafts'] = 'Kladder';
 $labels['sent'] = 'Sendt post';
 $labels['trash'] = 'Skrald';
 $labels['junk'] = 'Ragelse';
 $labels['inbox'] = 'Indbakke';
 $labels['drafts'] = 'Kladder';
 $labels['sent'] = 'Sendt post';
 $labels['trash'] = 'Skrald';
 $labels['junk'] = 'Ragelse';
+
+// message listing
 $labels['subject'] = 'Emne';
 $labels['from'] = 'Afsender';
 $labels['to'] = 'Modtager';
 $labels['subject'] = 'Emne';
 $labels['from'] = 'Afsender';
 $labels['to'] = 'Modtager';
@@ -45,17 +53,23 @@ $labels['size'] = 'Størrelse';
 $labels['priority'] = 'Prioritet';
 $labels['organization'] = 'Organisation';
 $labels['readstatus'] = 'Læst status';
 $labels['priority'] = 'Prioritet';
 $labels['organization'] = 'Organisation';
 $labels['readstatus'] = 'Læst status';
+
 $labels['mailboxlist'] = 'Mapper';
 $labels['messagesfromto'] = 'Besked $from til $to af $count';
 $labels['threadsfromto'] = 'Tråd $from til $to af $count';
 $labels['messagenrof'] = 'Besked $nr af $count';
 $labels['mailboxlist'] = 'Mapper';
 $labels['messagesfromto'] = 'Besked $from til $to af $count';
 $labels['threadsfromto'] = 'Tråd $from til $to af $count';
 $labels['messagenrof'] = 'Besked $nr af $count';
+
 $labels['copy'] = 'Kopier';
 $labels['move'] = 'Flyt';
 $labels['moveto'] = 'Flyt til...';
 $labels['download'] = 'Download';
 $labels['copy'] = 'Kopier';
 $labels['move'] = 'Flyt';
 $labels['moveto'] = 'Flyt til...';
 $labels['download'] = 'Download';
+
 $labels['filename'] = 'Filnavn';
 $labels['filesize'] = 'Filstørrelse';
 $labels['filename'] = 'Filnavn';
 $labels['filesize'] = 'Filstørrelse';
+
 $labels['addtoaddressbook'] = 'Tilføj til adressebogen';
 $labels['addtoaddressbook'] = 'Tilføj til adressebogen';
+
+// weekdays short
 $labels['sun'] = 'Søn';
 $labels['mon'] = 'Man';
 $labels['tue'] = 'Tir';
 $labels['sun'] = 'Søn';
 $labels['mon'] = 'Man';
 $labels['tue'] = 'Tir';
@@ -63,6 +77,8 @@ $labels['wed'] = 'Ons';
 $labels['thu'] = 'Tor';
 $labels['fri'] = 'Fre';
 $labels['sat'] = 'Lør';
 $labels['thu'] = 'Tor';
 $labels['fri'] = 'Fre';
 $labels['sat'] = 'Lør';
+
+// weekdays long
 $labels['sunday'] = 'Søndag';
 $labels['monday'] = 'Mandag';
 $labels['tuesday'] = 'Tirsdag';
 $labels['sunday'] = 'Søndag';
 $labels['monday'] = 'Mandag';
 $labels['tuesday'] = 'Tirsdag';
@@ -70,6 +86,8 @@ $labels['wednesday'] = 'Onsdag';
 $labels['thursday'] = 'Torsdag';
 $labels['friday'] = 'Fredag';
 $labels['saturday'] = 'Lørdag';
 $labels['thursday'] = 'Torsdag';
 $labels['friday'] = 'Fredag';
 $labels['saturday'] = 'Lørdag';
+
+// month short
 $labels['jan'] = 'Jan';
 $labels['feb'] = 'Feb';
 $labels['mar'] = 'Mar';
 $labels['jan'] = 'Jan';
 $labels['feb'] = 'Feb';
 $labels['mar'] = 'Mar';
@@ -82,6 +100,8 @@ $labels['sep'] = 'Sep';
 $labels['oct'] = 'Okt';
 $labels['nov'] = 'Nov';
 $labels['dec'] = 'Dec';
 $labels['oct'] = 'Okt';
 $labels['nov'] = 'Nov';
 $labels['dec'] = 'Dec';
+
+//months long
 $labels['longjan'] = 'Januar';
 $labels['longfeb'] = 'Februar';
 $labels['longmar'] = 'Marts';
 $labels['longjan'] = 'Januar';
 $labels['longfeb'] = 'Februar';
 $labels['longmar'] = 'Marts';
@@ -94,25 +114,26 @@ $labels['longsep'] = 'September';
 $labels['longoct'] = 'Oktober';
 $labels['longnov'] = 'November';
 $labels['longdec'] = 'December';
 $labels['longoct'] = 'Oktober';
 $labels['longnov'] = 'November';
 $labels['longdec'] = 'December';
+
 $labels['today'] = 'I dag';
 $labels['today'] = 'I dag';
+
+// toolbar buttons
 $labels['checkmail'] = 'Se efter nye beskeder';
 $labels['writenewmessage'] = 'Skriv en ny besked';
 $labels['replytomessage'] = 'Svar på denne besked';
 $labels['replytoallmessage'] = 'Svar til alle modtagere';
 $labels['replyall'] = 'Svar alle';
 $labels['replylist'] = 'Svar til listen';
 $labels['checkmail'] = 'Se efter nye beskeder';
 $labels['writenewmessage'] = 'Skriv en ny besked';
 $labels['replytomessage'] = 'Svar på denne besked';
 $labels['replytoallmessage'] = 'Svar til alle modtagere';
 $labels['replyall'] = 'Svar alle';
 $labels['replylist'] = 'Svar til listen';
+$labels['forwardinline']    = 'Videresend';
+$labels['forwardattachment'] = 'Videresend som vedhæftning';
 $labels['forwardmessage'] = 'Videresend denne besked';
 $labels['deletemessage'] = 'Slet besked';
 $labels['movemessagetotrash'] = 'Flyt besked til skrald';
 $labels['printmessage'] = 'Udskriv denne besked';
 $labels['previousmessage'] = 'Vis forrige besked';
 $labels['forwardmessage'] = 'Videresend denne besked';
 $labels['deletemessage'] = 'Slet besked';
 $labels['movemessagetotrash'] = 'Flyt besked til skrald';
 $labels['printmessage'] = 'Udskriv denne besked';
 $labels['previousmessage'] = 'Vis forrige besked';
-$labels['previousmessages'] = 'Vis forrige sæt beskeder';
 $labels['firstmessage'] = 'Vis første besked';
 $labels['firstmessage'] = 'Vis første besked';
-$labels['firstmessages'] = 'Vis første sæt beskeder';
 $labels['nextmessage'] = 'Vis næste besked';
 $labels['nextmessage'] = 'Vis næste besked';
-$labels['nextmessages'] = 'Vis næste sæt beskeder';
 $labels['lastmessage'] = 'Vis sidste besked';
 $labels['lastmessage'] = 'Vis sidste besked';
-$labels['lastmessages'] = 'Vis sidste sæt beskeder';
 $labels['backtolist'] = 'Tilbage til beskedlisten';
 $labels['viewsource'] = 'Vis rå besked';
 $labels['markmessages'] = 'Markér beskeder';
 $labels['backtolist'] = 'Tilbage til beskedlisten';
 $labels['viewsource'] = 'Vis rå besked';
 $labels['markmessages'] = 'Markér beskeder';
@@ -120,7 +141,9 @@ $labels['markread'] = 'Som læst';
 $labels['markunread'] = 'Som ulæst';
 $labels['markflagged'] = 'Som markeret';
 $labels['markunflagged'] = 'Som umarkeret';
 $labels['markunread'] = 'Som ulæst';
 $labels['markflagged'] = 'Som markeret';
 $labels['markunflagged'] = 'Som umarkeret';
+$labels['moreactions'] = 'Flere funktioner...';
 $labels['messageactions'] = 'Flere funktioner...';
 $labels['messageactions'] = 'Flere funktioner...';
+
 $labels['select'] = 'Vælg';
 $labels['all'] = 'Alle';
 $labels['none'] = 'Ingen';
 $labels['select'] = 'Vælg';
 $labels['all'] = 'Alle';
 $labels['none'] = 'Ingen';
@@ -136,7 +159,8 @@ $labels['threads'] = 'Tråde';
 $labels['expand-all'] = 'Udfold alle';
 $labels['expand-unread'] = 'Udfold ulæste';
 $labels['collapse-all'] = 'Fold alle';
 $labels['expand-all'] = 'Udfold alle';
 $labels['expand-unread'] = 'Udfold ulæste';
 $labels['collapse-all'] = 'Fold alle';
-$labels['threaded'] = 'Tråded';
+$labels['threaded'] = 'Trådet';
+
 $labels['autoexpand_threads'] = 'Udfold besked tråde';
 $labels['do_expand'] = 'alle tråde';
 $labels['expand_only_unread'] = 'kun dem med ulæste beskeder';
 $labels['autoexpand_threads'] = 'Udfold besked tråde';
 $labels['do_expand'] = 'alle tråde';
 $labels['expand_only_unread'] = 'kun dem med ulæste beskeder';
@@ -152,18 +176,24 @@ $labels['listcolumns'] = 'Vist kolonne';
 $labels['listsorting'] = 'Sorterings kolonne';
 $labels['listorder'] = 'Sorter efter';
 $labels['listmode'] = 'Listevisningsmode';
 $labels['listsorting'] = 'Sorterings kolonne';
 $labels['listorder'] = 'Sorter efter';
 $labels['listmode'] = 'Listevisningsmode';
+
 $labels['folderactions'] = 'Mappe handlinger...';
 $labels['compact'] = 'Ryd op';
 $labels['empty'] = 'Tøm';
 $labels['folderactions'] = 'Mappe handlinger...';
 $labels['compact'] = 'Ryd op';
 $labels['empty'] = 'Tøm';
+
 $labels['quota'] = 'Disk forbrug';
 $labels['unknown'] = 'ukendt';
 $labels['unlimited'] = 'ubegrænset';
 $labels['quota'] = 'Disk forbrug';
 $labels['unknown'] = 'ukendt';
 $labels['unlimited'] = 'ubegrænset';
+
 $labels['quicksearch'] = 'Hurtigsøgning';
 $labels['resetsearch'] = 'Nulstil søgning';
 $labels['searchmod'] = 'Søgeparametere';
 $labels['msgtext'] = 'Hele beskeden';
 $labels['quicksearch'] = 'Hurtigsøgning';
 $labels['resetsearch'] = 'Nulstil søgning';
 $labels['searchmod'] = 'Søgeparametere';
 $labels['msgtext'] = 'Hele beskeden';
+
 $labels['openinextwin'] = 'Åbn i nyt vindue';
 $labels['emlsave'] = 'Download (.eml)';
 $labels['openinextwin'] = 'Åbn i nyt vindue';
 $labels['emlsave'] = 'Download (.eml)';
+
+// message compose
 $labels['compose'] = 'Forfat en besked';
 $labels['editasnew'] = 'Redigér som ny';
 $labels['savemessage'] = 'Gem denne kladde';
 $labels['compose'] = 'Forfat en besked';
 $labels['editasnew'] = 'Redigér som ny';
 $labels['savemessage'] = 'Gem denne kladde';
@@ -173,41 +203,58 @@ $labels['charset'] = 'Tegnsæt';
 $labels['editortype'] = 'Tekstbehandler';
 $labels['returnreceipt'] = 'Anmod om kvittering';
 $labels['dsn'] = 'Notifikation om leveringstatus';
 $labels['editortype'] = 'Tekstbehandler';
 $labels['returnreceipt'] = 'Anmod om kvittering';
 $labels['dsn'] = 'Notifikation om leveringstatus';
+$labels['mailreplyintro'] = 'Den $date, $sender skrev:';
+$labels['originalmessage'] = 'Original besked';
+
 $labels['editidents'] = 'Ret identiteter';
 $labels['checkspelling'] = 'Stavekontrol';
 $labels['resumeediting'] = 'Genoptag redigering';
 $labels['revertto'] = 'Vend tilbage til';
 $labels['editidents'] = 'Ret identiteter';
 $labels['checkspelling'] = 'Stavekontrol';
 $labels['resumeediting'] = 'Genoptag redigering';
 $labels['revertto'] = 'Vend tilbage til';
+
 $labels['attachments'] = 'Vedhæftninger';
 $labels['upload'] = 'Upload';
 $labels['attachments'] = 'Vedhæftninger';
 $labels['upload'] = 'Upload';
+$labels['uploadprogress'] = '$percent ($current af $total)';
 $labels['close'] = 'Luk';
 $labels['messageoptions'] = 'Besked muligheder...';
 $labels['close'] = 'Luk';
 $labels['messageoptions'] = 'Besked muligheder...';
+
 $labels['low'] = 'Lav';
 $labels['lowest'] = 'Lavest';
 $labels['normal'] = 'Normal';
 $labels['high'] = 'Høj';
 $labels['highest'] = 'Højest';
 $labels['low'] = 'Lav';
 $labels['lowest'] = 'Lavest';
 $labels['normal'] = 'Normal';
 $labels['high'] = 'Høj';
 $labels['highest'] = 'Højest';
+
 $labels['nosubject'] = '(intet emne)';
 $labels['showimages'] = 'Vis billeder';
 $labels['alwaysshow'] = 'Vis altid billeder fra $sender';
 $labels['nosubject'] = '(intet emne)';
 $labels['showimages'] = 'Vis billeder';
 $labels['alwaysshow'] = 'Vis altid billeder fra $sender';
+$labels['isdraft']    = 'Dette er en kladde.';
+
 $labels['htmltoggle'] = 'HTML';
 $labels['plaintoggle'] = 'Almindelig tekst';
 $labels['savesentmessagein'] = 'Gem afsendt besked i';
 $labels['dontsave'] = 'gem ikke';
 $labels['maxuploadsize'] = 'Maksimale tilladte filstørrelse er $size';
 $labels['htmltoggle'] = 'HTML';
 $labels['plaintoggle'] = 'Almindelig tekst';
 $labels['savesentmessagein'] = 'Gem afsendt besked i';
 $labels['dontsave'] = 'gem ikke';
 $labels['maxuploadsize'] = 'Maksimale tilladte filstørrelse er $size';
+
 $labels['addcc'] = 'Tilføj Cc';
 $labels['addbcc'] = 'Tilføj Bcc';
 $labels['addreplyto'] = 'Tilføj Svar-Til adresse';
 $labels['addfollowupto'] = 'Tilføj følg-op adresse';
 $labels['addcc'] = 'Tilføj Cc';
 $labels['addbcc'] = 'Tilføj Bcc';
 $labels['addreplyto'] = 'Tilføj Svar-Til adresse';
 $labels['addfollowupto'] = 'Tilføj følg-op adresse';
+
+// mdn
 $labels['mdnrequest'] = 'Afsenderen af denne besked har bedt om at modtage en bekræftelse når du læser beskeden. Vil du sende kvittering for læsning?';
 $labels['receiptread'] = 'Send kvittering for læsning';
 $labels['yourmessage'] = 'Dette er en kvittering for at din besked er blevet vist';
 $labels['receiptnote'] = 'Bemærk: Denne kvittering bekræfter udelukkende at beskeden blev vist på modtagerens computer. Der er ingen garanti for at modtageren har læst eller forstået beskedens indhold.';
 $labels['mdnrequest'] = 'Afsenderen af denne besked har bedt om at modtage en bekræftelse når du læser beskeden. Vil du sende kvittering for læsning?';
 $labels['receiptread'] = 'Send kvittering for læsning';
 $labels['yourmessage'] = 'Dette er en kvittering for at din besked er blevet vist';
 $labels['receiptnote'] = 'Bemærk: Denne kvittering bekræfter udelukkende at beskeden blev vist på modtagerens computer. Der er ingen garanti for at modtageren har læst eller forstået beskedens indhold.';
+
+// address book
 $labels['name'] = 'Vist navn';
 $labels['firstname'] = 'Fornavn';
 $labels['surname'] = 'Efternavn';
 $labels['middlename'] = 'Mellemnavn';
 $labels['name'] = 'Vist navn';
 $labels['firstname'] = 'Fornavn';
 $labels['surname'] = 'Efternavn';
 $labels['middlename'] = 'Mellemnavn';
+$labels['nameprefix']   = 'Præfiks';
+$labels['namesuffix']   = 'Suffiks';
 $labels['nickname'] = 'Alias/Kaldenavn';
 $labels['jobtitle'] = 'Job titel';
 $labels['nickname'] = 'Alias/Kaldenavn';
 $labels['jobtitle'] = 'Job titel';
+$labels['organization'] = 'Firma';
 $labels['department'] = 'Afdeling';
 $labels['gender'] = 'Køn';
 $labels['maidenname'] = 'Pigenavn';
 $labels['department'] = 'Afdeling';
 $labels['gender'] = 'Køn';
 $labels['maidenname'] = 'Pigenavn';
@@ -229,11 +276,33 @@ $labels['female'] = 'Kvinde';
 $labels['manager'] = 'Manager';
 $labels['assistant'] = 'Assistent';
 $labels['spouse'] = 'Ægtefælle';
 $labels['manager'] = 'Manager';
 $labels['assistant'] = 'Assistent';
 $labels['spouse'] = 'Ægtefælle';
+$labels['allfields'] = 'Alle felter';
+$labels['search'] = 'Søg';
+$labels['advsearch'] = 'Avanceret søg';
+$labels['other'] = 'Andet';
+
+$labels['typehome']   = 'Hjem';
+$labels['typework']   = 'Arbejde';
+$labels['typeother']  = 'Andet';
+$labels['typemobile']  = 'Mobil';
+$labels['typemain']  = 'Fastnet';
+$labels['typehomefax']  = 'Hjemme fax';
+$labels['typeworkfax']  = 'Arbejde Fax';
+$labels['typecar']  = 'Bil';
+$labels['typepager']  = 'Personsøger';
+$labels['typevideo']  = 'Video';
+$labels['typeassistant']  = 'Assistent';
+$labels['typehomepage']  = 'Hjemmeside';
+$labels['typeblog'] = 'Blog';
+$labels['typeprofile'] = 'Profil';
+
 $labels['addfield'] = 'Tilføj felt...';
 $labels['addcontact'] = 'Tilføj en ny kontakt';
 $labels['editcontact'] = 'Redigér kontakt';
 $labels['contacts'] = 'Kontakter';
 $labels['contactproperties'] = 'Kontakt egenskaber';
 $labels['addfield'] = 'Tilføj felt...';
 $labels['addcontact'] = 'Tilføj en ny kontakt';
 $labels['editcontact'] = 'Redigér kontakt';
 $labels['contacts'] = 'Kontakter';
 $labels['contactproperties'] = 'Kontakt egenskaber';
+$labels['personalinfo'] = 'Personlig information';
+
 $labels['edit'] = 'Redigér';
 $labels['cancel'] = 'Afbryd';
 $labels['save'] = 'Gem';
 $labels['edit'] = 'Redigér';
 $labels['cancel'] = 'Afbryd';
 $labels['save'] = 'Gem';
@@ -241,6 +310,7 @@ $labels['delete'] = 'Slet';
 $labels['rename'] = 'Omdøb';
 $labels['addphoto'] = 'Tilføj';
 $labels['replacephoto'] = 'Erstat';
 $labels['rename'] = 'Omdøb';
 $labels['addphoto'] = 'Tilføj';
 $labels['replacephoto'] = 'Erstat';
+
 $labels['newcontact'] = 'Opret nyt kontaktkort';
 $labels['deletecontact'] = 'Slet valgte kontakter';
 $labels['composeto'] = 'Skriv brev til';
 $labels['newcontact'] = 'Opret nyt kontaktkort';
 $labels['deletecontact'] = 'Slet valgte kontakter';
 $labels['composeto'] = 'Skriv brev til';
@@ -250,31 +320,47 @@ $labels['export'] = 'Eksport';
 $labels['exportvcards'] = 'Eksportér kontakter i vCard format';
 $labels['newcontactgroup'] = 'Opret ny kontaktgruppe';
 $labels['groupactions'] = 'Funktioner for kontaktgrupper...';
 $labels['exportvcards'] = 'Eksportér kontakter i vCard format';
 $labels['newcontactgroup'] = 'Opret ny kontaktgruppe';
 $labels['groupactions'] = 'Funktioner for kontaktgrupper...';
+$labels['groupdelete']    = 'Slet gruppe';
+
 $labels['previouspage'] = 'Vis forrige sæt';
 $labels['firstpage'] = 'Vis første sæt';
 $labels['nextpage'] = 'Vis næste sæt';
 $labels['lastpage'] = 'Vis sidste sæt';
 $labels['previouspage'] = 'Vis forrige sæt';
 $labels['firstpage'] = 'Vis første sæt';
 $labels['nextpage'] = 'Vis næste sæt';
 $labels['lastpage'] = 'Vis sidste sæt';
+
 $labels['group'] = 'Gruppe';
 $labels['groups'] = 'Grupper';
 $labels['personaladrbook'] = 'Personlige Adresser';
 $labels['group'] = 'Gruppe';
 $labels['groups'] = 'Grupper';
 $labels['personaladrbook'] = 'Personlige Adresser';
+
+$labels['searchsave'] = 'Gem søgning';
+$labels['searchdelete'] = 'Slet søgning';
+
 $labels['import'] = 'Importér';
 $labels['importcontacts'] = 'Importér kontakter';
 $labels['importfromfile'] = 'Importér fra fil:';
 $labels['import'] = 'Importér';
 $labels['importcontacts'] = 'Importér kontakter';
 $labels['importfromfile'] = 'Importér fra fil:';
+$labels['importtarget'] = 'Tilføj nye kontakter til adressebogen:';
 $labels['importreplace'] = 'Overskriv hele adressebogen';
 $labels['importtext'] = 'Du kan uploade kontakter fra en eksisterende adressebog.Vi understøtter i øjeblikket import af adresser i vCard formatet.';
 $labels['done'] = 'Færdig';
 $labels['importreplace'] = 'Overskriv hele adressebogen';
 $labels['importtext'] = 'Du kan uploade kontakter fra en eksisterende adressebog.Vi understøtter i øjeblikket import af adresser i vCard formatet.';
 $labels['done'] = 'Færdig';
+
+// settings
 $labels['settingsfor'] = 'Indstillinger for';
 $labels['settingsfor'] = 'Indstillinger for';
+$labels['about'] = 'Om';
 $labels['preferences'] = 'Præferencer';
 $labels['userpreferences'] = 'Brugerpræferencer';
 $labels['editpreferences'] = 'Redigér brugerpræferencer';
 $labels['preferences'] = 'Præferencer';
 $labels['userpreferences'] = 'Brugerpræferencer';
 $labels['editpreferences'] = 'Redigér brugerpræferencer';
+
 $labels['identities'] = 'Identiteter';
 $labels['manageidentities'] = 'Styr identiteterne for denne konto';
 $labels['newidentity'] = 'Ny identitet';
 $labels['identities'] = 'Identiteter';
 $labels['manageidentities'] = 'Styr identiteterne for denne konto';
 $labels['newidentity'] = 'Ny identitet';
+
 $labels['newitem'] = 'Nyt punkt';
 $labels['edititem'] = 'Redigér punkt';
 $labels['newitem'] = 'Nyt punkt';
 $labels['edititem'] = 'Redigér punkt';
+
 $labels['preferhtml'] = 'Foretræk HTML';
 $labels['defaultcharset'] = 'Standard tegnkodning';
 $labels['htmlmessage'] = 'HTML-besked';
 $labels['preferhtml'] = 'Foretræk HTML';
 $labels['defaultcharset'] = 'Standard tegnkodning';
 $labels['htmlmessage'] = 'HTML-besked';
+$labels['dateformat'] = 'Dato format';
+$labels['timeformat'] = 'Tid format';
 $labels['prettydate'] = 'Pæn datovisning';
 $labels['setdefault'] = 'Sæt standard';
 $labels['autodetect'] = 'Automatisk';
 $labels['prettydate'] = 'Pæn datovisning';
 $labels['setdefault'] = 'Sæt standard';
 $labels['autodetect'] = 'Automatisk';
@@ -345,6 +431,15 @@ $labels['afternseconds'] = 'efter $n sekunder';
 $labels['reqmdn'] = 'Bed altid om at få besked om læsning';
 $labels['reqdsn'] = 'Bed altid om at få en status på levering';
 $labels['replysamefolder'] = 'Placer svar til en besked i samme mappe som beskeden der besvares';
 $labels['reqmdn'] = 'Bed altid om at få besked om læsning';
 $labels['reqdsn'] = 'Bed altid om at få en status på levering';
 $labels['replysamefolder'] = 'Placer svar til en besked i samme mappe som beskeden der besvares';
+$labels['defaultaddressbook'] = 'Tilføj nye kontakter til den valgte adressebog';
+$labels['autocompletesingle'] = 'Undgå alternative emailadresser under autofuldførelse';
+$labels['spellcheckbeforesend'] = 'Tjek stavning inden beskeden sendes';
+$labels['spellcheckoptions'] = 'Stavning muligheder';
+$labels['spellcheckignoresyms'] = 'Ignorer ord med symboler';
+$labels['spellcheckignorenums'] = 'Ignorer ord med tal';
+$labels['spellcheckignorecaps'] = 'Ignorer ord hvor alle bogstaver er versaler';
+$labels['addtodict'] = 'Tilføj til ordbog';
+
 $labels['folder'] = 'Mappe';
 $labels['folders'] = 'Mapper';
 $labels['foldername'] = 'Mappenavn';
 $labels['folder'] = 'Mappe';
 $labels['folders'] = 'Mapper';
 $labels['foldername'] = 'Mappenavn';
@@ -361,13 +456,29 @@ $labels['location'] = 'Placering';
 $labels['info'] = 'Information';
 $labels['getfoldersize'] = 'Klik for at hente mappestørrelse';
 $labels['changesubscription'] = 'Klik for at ændre abonnement';
 $labels['info'] = 'Information';
 $labels['getfoldersize'] = 'Klik for at hente mappestørrelse';
 $labels['changesubscription'] = 'Klik for at ændre abonnement';
+$labels['foldertype'] = 'Mappe Type';
+$labels['personalfolder']  = 'Privat mappe';
+$labels['otherfolder']  = 'Anden brugers mappe';
+$labels['sharedfolder']  = 'Offentlig mappe';
+
 $labels['sortby'] = 'Sortér efter';
 $labels['sortasc'] = 'Ældste først';
 $labels['sortdesc'] = 'Nyeste først';
 $labels['sortby'] = 'Sortér efter';
 $labels['sortasc'] = 'Ældste først';
 $labels['sortdesc'] = 'Nyeste først';
+$labels['undo'] = 'Fortryd';
+
+$labels['plugin'] = 'Plugin';
+$labels['version'] = 'Version';
+$labels['source'] = 'Kilde';
+$labels['license'] = 'Licens';
+$labels['support'] = 'Få support';
+
+// units
 $labels['B'] = 'B';
 $labels['KB'] = 'KB';
 $labels['MB'] = 'MB';
 $labels['GB'] = 'GB';
 $labels['B'] = 'B';
 $labels['KB'] = 'KB';
 $labels['MB'] = 'MB';
 $labels['GB'] = 'GB';
+
+// character sets
 $labels['unicode'] = 'Unicode';
 $labels['english'] = 'Engelsk';
 $labels['westerneuropean'] = 'Vestlig europæisk';
 $labels['unicode'] = 'Unicode';
 $labels['english'] = 'Engelsk';
 $labels['westerneuropean'] = 'Vestlig europæisk';
index c8ff45117d162522c845d91a5a7db3698ee604a9..0eb72dd0962f5d3ecb22e294858ef1716cdfa83e 100644 (file)
 | Author : Martin Moeller <martin@liga.dk>                              |
 |         Jesper R. Meyer <jesper@upthere.dk>                           |
 |         Søren Aggeboe <soren@aggeboe.dk>                              |
 | Author : Martin Moeller <martin@liga.dk>                              |
 |         Jesper R. Meyer <jesper@upthere.dk>                           |
 |         Søren Aggeboe <soren@aggeboe.dk>                              |
+|         John Loft Christiansen <john@nansensvej.dk>                   |
 +-----------------------------------------------------------------------+
 
 +-----------------------------------------------------------------------+
 
-@version $Id: messages.inc 4462 2011-01-28 16:01:03Z thomasb $
-
+@version $Id: messages.inc 5569 2011-12-07 14:47:32Z thomasb $
 */
 
 $messages = array();
 */
 
 $messages = array();
@@ -25,6 +25,7 @@ $messages['sessionerror'] = 'Din session er ugyldig eller udløbet';
 $messages['imaperror'] = 'Forbindelse til IMAP serveren fejlede';
 $messages['servererror'] = 'Server fejl!';
 $messages['servererrormsg'] = 'Server fejl: $msg';
 $messages['imaperror'] = 'Forbindelse til IMAP serveren fejlede';
 $messages['servererror'] = 'Server fejl!';
 $messages['servererrormsg'] = 'Server fejl: $msg';
+$messages['dberror'] = 'Database fejl!';
 $messages['errorreadonly'] = 'Kunne ikke udføre den ønskede handling. Mappen er skrivebeskyttet';
 $messages['errornoperm'] = 'Kunne ikke udføre den ønskede handling. Adgang nægtet';
 $messages['invalidrequest'] = 'Ugyldig forespørgsel! Ingen data blev gemt.';
 $messages['errorreadonly'] = 'Kunne ikke udføre den ønskede handling. Mappen er skrivebeskyttet';
 $messages['errornoperm'] = 'Kunne ikke udføre den ønskede handling. Adgang nægtet';
 $messages['invalidrequest'] = 'Ugyldig forespørgsel! Ingen data blev gemt.';
@@ -33,6 +34,7 @@ $messages['loggedout'] = 'Du er nu logget af webmail. Farvel så længe!';
 $messages['mailboxempty'] = 'Postkassen er tom!';
 $messages['loading'] = 'Indlæser...';
 $messages['uploading'] = 'Uploader fil...';
 $messages['mailboxempty'] = 'Postkassen er tom!';
 $messages['loading'] = 'Indlæser...';
 $messages['uploading'] = 'Uploader fil...';
+$messages['uploadingmany'] = 'Uploader filer...';
 $messages['loadingdata'] = 'Indlæser data...';
 $messages['checkingmail'] = 'Tjekker for nye beskeder...';
 $messages['sendingmessage'] = 'Sender besked...';
 $messages['loadingdata'] = 'Indlæser data...';
 $messages['checkingmail'] = 'Tjekker for nye beskeder...';
 $messages['sendingmessage'] = 'Sender besked...';
@@ -42,10 +44,12 @@ $messages['messagesaved'] = 'Beskeden er gemt i kladdemappen';
 $messages['successfullysaved'] = 'Det lykkedes at gemme';
 $messages['addedsuccessfully'] = 'Kontakten blev tilføjet adressebogen';
 $messages['contactexists'] = 'Der er allerede en kontakt med denne e-mail adresse';
 $messages['successfullysaved'] = 'Det lykkedes at gemme';
 $messages['addedsuccessfully'] = 'Kontakten blev tilføjet adressebogen';
 $messages['contactexists'] = 'Der er allerede en kontakt med denne e-mail adresse';
+$messages['contactnameexists'] = 'En kontakt med samme navn eksisterer allerede.';
 $messages['blockedimages'] = 'For at beskytte dit privatliv er billeder fra internetservere blokeret i denne besked.';
 $messages['encryptedmessage'] = 'Beskeden er krypteret og kan ikke vises. Beklager!';
 $messages['nocontactsfound'] = 'Ingen kontakter blev fundet';
 $messages['contactnotfound'] = 'Den søgte kontakt blev ikke fundet';
 $messages['blockedimages'] = 'For at beskytte dit privatliv er billeder fra internetservere blokeret i denne besked.';
 $messages['encryptedmessage'] = 'Beskeden er krypteret og kan ikke vises. Beklager!';
 $messages['nocontactsfound'] = 'Ingen kontakter blev fundet';
 $messages['contactnotfound'] = 'Den søgte kontakt blev ikke fundet';
+$messages['contactsearchonly'] = 'Indtast ord for at finde kontakten';
 $messages['sendingfailed'] = 'Beskeden kunne ikke sendes';
 $messages['senttooquickly'] = 'Vent venligst $sec sekunder før du sender denne besked';
 $messages['errorsavingsent'] = 'Der opstod en fejl da den sendte besked blev gemt';
 $messages['sendingfailed'] = 'Beskeden kunne ikke sendes';
 $messages['senttooquickly'] = 'Vent venligst $sec sekunder før du sender denne besked';
 $messages['errorsavingsent'] = 'Der opstod en fejl da den sendte besked blev gemt';
@@ -55,9 +59,12 @@ $messages['errorcopying'] = 'Beskeden kunne ikke kopieres';
 $messages['errordeleting'] = 'Beskeden kunne ikke slettes';
 $messages['errormarking'] = 'Beskeden kunne ikke markeres';
 $messages['deletecontactconfirm'] = 'Vil du virkelig slette den/de valgte kontakt(er)?';
 $messages['errordeleting'] = 'Beskeden kunne ikke slettes';
 $messages['errormarking'] = 'Beskeden kunne ikke markeres';
 $messages['deletecontactconfirm'] = 'Vil du virkelig slette den/de valgte kontakt(er)?';
+$messages['deletegroupconfirm']  = 'Vil du virkelig slette den/de valgte gruppe(r)?';
 $messages['deletemessagesconfirm'] = 'Vil du virkelig slette den/de valgte besked(er)?';
 $messages['deletefolderconfirm'] = 'Vil du virkelig slette den valgte mappe';
 $messages['purgefolderconfirm'] = 'Vil du virkelig slette alle beskeder i denne mappe?';
 $messages['deletemessagesconfirm'] = 'Vil du virkelig slette den/de valgte besked(er)?';
 $messages['deletefolderconfirm'] = 'Vil du virkelig slette den valgte mappe';
 $messages['purgefolderconfirm'] = 'Vil du virkelig slette alle beskeder i denne mappe?';
+$messages['contactdeleting'] = 'Sletter kontakt(er)...';
+$messages['groupdeleting'] = 'Sletter gruppe...';
 $messages['folderdeleting'] = 'Sletter mappen...';
 $messages['foldermoving'] = 'Flytter mappen...';
 $messages['foldersubscribing'] = 'Abonnere på mappen...';
 $messages['folderdeleting'] = 'Sletter mappen...';
 $messages['foldermoving'] = 'Flytter mappen...';
 $messages['foldersubscribing'] = 'Abonnere på mappen...';
@@ -96,8 +103,11 @@ $messages['sourceisreadonly'] = 'Denne adressekilde er kun til læsning';
 $messages['errorsavingcontact'] = 'Kunne ikke gemme kontakt adressen';
 $messages['movingmessage'] = 'Flytter besked...';
 $messages['copyingmessage'] = 'Kopierer besked...';
 $messages['errorsavingcontact'] = 'Kunne ikke gemme kontakt adressen';
 $messages['movingmessage'] = 'Flytter besked...';
 $messages['copyingmessage'] = 'Kopierer besked...';
+$messages['copyingcontact'] = 'Kopierer kontakt(er)...';
 $messages['deletingmessage'] = 'Sletter besked(er)...';
 $messages['markingmessage'] = 'Markerer besked(er)...';
 $messages['deletingmessage'] = 'Sletter besked(er)...';
 $messages['markingmessage'] = 'Markerer besked(er)...';
+$messages['addingmember'] = 'Tilføjer kontakt(er) til gruppen...';
+$messages['removingmember'] = 'Fjerner kontakt(er) fra gruppen...';
 $messages['receiptsent'] = 'Kvittering for læsning er sendt';
 $messages['errorsendingreceipt'] = 'Kvitteringen kunne ikke sendes';
 $messages['nodeletelastidentity'] = 'Du kan ikke slette denne identitet, da det er den eneste der er tilbage.';
 $messages['receiptsent'] = 'Kvittering for læsning er sendt';
 $messages['errorsendingreceipt'] = 'Kvitteringen kunne ikke sendes';
 $messages['nodeletelastidentity'] = 'Du kan ikke slette denne identitet, da det er den eneste der er tilbage.';
@@ -109,6 +119,7 @@ $messages['contactremovedfromgroup'] = 'Succesfuldt fjernet kontakten fra denne
 $messages['importwait'] = 'Importerer, vent venligst...';
 $messages['importerror'] = 'Fejl i importen! Den uploadede fil er ikke en gyldig vCard fil.';
 $messages['importconfirm'] = '<b>Importerede $inserted kontakter, sprang over $skipped allerede eksisterende kontakter</b>:<p><em>$names</em></p>';
 $messages['importwait'] = 'Importerer, vent venligst...';
 $messages['importerror'] = 'Fejl i importen! Den uploadede fil er ikke en gyldig vCard fil.';
 $messages['importconfirm'] = '<b>Importerede $inserted kontakter, sprang over $skipped allerede eksisterende kontakter</b>:<p><em>$names</em></p>';
+$messages['importconfirmskipped'] = '<b>Skipped $skipped existing entries</b>';
 $messages['opnotpermitted'] = 'Handlingen er ikke tilladt!';
 $messages['nofromaddress'] = 'Der mangler en email-adresse i den valgte identitet';
 $messages['editorwarning'] = 'Al formatering af teksten forsvinder, hvis der skiftes til ren tekst. Vil du fortsætte?';
 $messages['opnotpermitted'] = 'Handlingen er ikke tilladt!';
 $messages['nofromaddress'] = 'Der mangler en email-adresse i den valgte identitet';
 $messages['editorwarning'] = 'Al formatering af teksten forsvinder, hvis der skiftes til ren tekst. Vil du fortsætte?';
@@ -118,7 +129,6 @@ $messages['smtpautherror'] = 'SMTP fejl ($code): Autenticering fejlede';
 $messages['smtpfromerror'] = 'SMTP fejl ($code): Kunne ikke afsende som "$from" ($msg)';
 $messages['smtptoerror'] = 'SMTP fejl ($code): Kunne ikke tilføje modtageren "$to" ($msg)';
 $messages['smtprecipientserror'] = 'SMTP fejl: kan ikke fortolke listen af modtagere';
 $messages['smtpfromerror'] = 'SMTP fejl ($code): Kunne ikke afsende som "$from" ($msg)';
 $messages['smtptoerror'] = 'SMTP fejl ($code): Kunne ikke tilføje modtageren "$to" ($msg)';
 $messages['smtprecipientserror'] = 'SMTP fejl: kan ikke fortolke listen af modtagere';
-$messages['smtpdsnerror'] = 'SMTP fejl: Ingen understøttelse af leveringsnotifikation';
 $messages['smtperror'] = 'SMTP fejl: $msg';
 $messages['emailformaterror'] = 'Ugyldig email-adresse: $email';
 $messages['toomanyrecipients'] = 'For mange modtagere. Reducer antallet af modtagere til $max';
 $messages['smtperror'] = 'SMTP fejl: $msg';
 $messages['emailformaterror'] = 'Ugyldig email-adresse: $email';
 $messages['toomanyrecipients'] = 'For mange modtagere. Reducer antallet af modtagere til $max';
@@ -126,18 +136,28 @@ $messages['maxgroupmembersreached'] = 'Antallet af gruppemedlemmer overstiger ma
 $messages['internalerror'] = 'Der opstod en intern fejl - prøv venligst igen';
 $messages['contactdelerror'] = 'Kunne ikke slette kontakt(er)';
 $messages['contactdeleted'] = 'Kontakt(er) slettet';
 $messages['internalerror'] = 'Der opstod en intern fejl - prøv venligst igen';
 $messages['contactdelerror'] = 'Kunne ikke slette kontakt(er)';
 $messages['contactdeleted'] = 'Kontakt(er) slettet';
+$messages['contactrestoreerror'] = 'Kunne ikke gendanne slettede kontakt(er).';
+$messages['contactrestored'] = 'Kontakt(er) gendannet.';
 $messages['groupdeleted'] = 'Gruppen er slettet';
 $messages['grouprenamed'] = 'Gruppen er omdøbt';
 $messages['groupcreated'] = 'Gruppen er oprettet';
 $messages['groupdeleted'] = 'Gruppen er slettet';
 $messages['grouprenamed'] = 'Gruppen er omdøbt';
 $messages['groupcreated'] = 'Gruppen er oprettet';
+$messages['savedsearchdeleted'] = 'Gemt søgning slettet.';
+$messages['savedsearchdeleteerror'] = 'Kunne ikke slette Gemt søgning.';
+$messages['savedsearchcreated'] = 'Gemt søgning oprettet.';
+$messages['savedsearchcreateerror'] = 'Kunne ikke oprette Gemt søgning.';
 $messages['messagedeleted'] = 'Besked(er) slettet';
 $messages['messagemoved'] = 'Besked(er) flyttet';
 $messages['messagecopied'] = 'Besked(er) kopieret';
 $messages['messagemarked'] = 'Besked(er) markeret';
 $messages['autocompletechars'] = 'Du skal min. indtaste $min for at benytte autoopslag';
 $messages['messagedeleted'] = 'Besked(er) slettet';
 $messages['messagemoved'] = 'Besked(er) flyttet';
 $messages['messagecopied'] = 'Besked(er) kopieret';
 $messages['messagemarked'] = 'Besked(er) markeret';
 $messages['autocompletechars'] = 'Du skal min. indtaste $min for at benytte autoopslag';
+$messages['autocompletemore'] = 'Flere emner fundet. Task flere bogstaver.';
 $messages['namecannotbeempty'] = 'Navnet kan ikke været tomt';
 $messages['nametoolong'] = 'Navnet er for langt';
 $messages['folderupdated'] = 'Mappen er opdateret';
 $messages['foldercreated'] = 'Mappen er oprettet';
 $messages['invalidimageformat'] = 'Ikke et gyldigt billedformat';
 $messages['namecannotbeempty'] = 'Navnet kan ikke været tomt';
 $messages['nametoolong'] = 'Navnet er for langt';
 $messages['folderupdated'] = 'Mappen er opdateret';
 $messages['foldercreated'] = 'Mappen er oprettet';
 $messages['invalidimageformat'] = 'Ikke et gyldigt billedformat';
+$messages['mispellingsfound'] = 'Der er fundet stavefejl i beskeden.';
+$messages['parentnotwritable'] = 'Kan ikke oprette/flytte mappe ind i valgt mappe. Ingen adgangsrettigheder.';
+$messages['messagetoobig'] = 'Besked delen er for stor til at behandle.';
 
 ?>
 
 ?>
index c01cb7f1a390448eda9dcef38f75a1b046bec071..7a27bbeb5ff239dfbd5fa80e646d01028118dbc1 100644 (file)
@@ -13,7 +13,7 @@
 | Author:      Thomas Bruederli <roundcube@gmail.com>                   |
 +-----------------------------------------------------------------------+
 
 | Author:      Thomas Bruederli <roundcube@gmail.com>                   |
 +-----------------------------------------------------------------------+
 
-@version $Id: labels.inc 5067 2011-08-14 18:47:58Z thomasb $
+@version $Id: labels.inc 5569 2011-12-07 14:47:32Z thomasb $
 
 */
 
 
 */
 
@@ -285,6 +285,7 @@ $labels['importreplace'] = 'Bestehendes Adressbuch komplett ersetzen';
 $labels['importtext'] = 'Sie können Kontakte aus einem bestehenden Adressbuch hochladen.<br/>Es können Adressbücher im <a href="http://de.wikipedia.org/wiki/VCard">vCard-Format</a> importiert werden.';
 $labels['done'] = 'Fertig';
 $labels['settingsfor'] = 'Einstellungen für';
 $labels['importtext'] = 'Sie können Kontakte aus einem bestehenden Adressbuch hochladen.<br/>Es können Adressbücher im <a href="http://de.wikipedia.org/wiki/VCard">vCard-Format</a> importiert werden.';
 $labels['done'] = 'Fertig';
 $labels['settingsfor'] = 'Einstellungen für';
+$labels['about'] = 'Über';
 $labels['preferences'] = 'Einstellungen';
 $labels['userpreferences'] = 'Benutzereinstellungen';
 $labels['editpreferences'] = 'Einstellungen bearbeiten';
 $labels['preferences'] = 'Einstellungen';
 $labels['userpreferences'] = 'Benutzereinstellungen';
 $labels['editpreferences'] = 'Einstellungen bearbeiten';
@@ -296,6 +297,8 @@ $labels['edititem'] = 'Eintrag bearbeiten';
 $labels['preferhtml'] = 'HTML bevorzugen';
 $labels['defaultcharset'] = 'Standard-Zeichensatz';
 $labels['htmlmessage'] = 'HTML Nachricht';
 $labels['preferhtml'] = 'HTML bevorzugen';
 $labels['defaultcharset'] = 'Standard-Zeichensatz';
 $labels['htmlmessage'] = 'HTML Nachricht';
+$labels['dateformat'] = 'Datumsformat';
+$labels['timeformat'] = 'Zeitformat';
 $labels['prettydate'] = 'Kurze Datumsanzeige';
 $labels['setdefault'] = 'Als Standard';
 $labels['autodetect'] = 'Automatisch';
 $labels['prettydate'] = 'Kurze Datumsanzeige';
 $labels['setdefault'] = 'Als Standard';
 $labels['autodetect'] = 'Automatisch';
@@ -392,6 +395,11 @@ $labels['sortby'] = 'Sortieren nach';
 $labels['sortasc'] = 'aufsteigend sortieren';
 $labels['sortdesc'] = 'absteigend sortieren';
 $labels['undo'] = 'Rückgängig';
 $labels['sortasc'] = 'aufsteigend sortieren';
 $labels['sortdesc'] = 'absteigend sortieren';
 $labels['undo'] = 'Rückgängig';
+$labels['plugin'] = 'Plugin';
+$labels['version'] = 'Version';
+$labels['source'] = 'Quellcode';
+$labels['license'] = 'Lizenz';
+$labels['support'] = 'Support';
 $labels['B'] = 'B';
 $labels['KB'] = 'KB';
 $labels['MB'] = 'MB';
 $labels['B'] = 'B';
 $labels['KB'] = 'KB';
 $labels['MB'] = 'MB';
index b112ec958ad9ed5e04286b142d77c47cf41caa3b..fe4a07bc73fef77f9e4c1880f1eceb1f25b95632 100644 (file)
@@ -13,7 +13,7 @@
 | Author: Thomas Bruederli <roundcube@gmail.com>                        |
 +-----------------------------------------------------------------------+
 
 | Author: Thomas Bruederli <roundcube@gmail.com>                        |
 +-----------------------------------------------------------------------+
 
-@version $Id: messages.inc 5079 2011-08-16 19:57:45Z thomasb $
+@version $Id: messages.inc 5258 2011-09-21 11:17:46Z thomasb $
 
 */
 
 
 */
 
@@ -24,7 +24,7 @@ $messages['sessionerror'] = 'Ihre Session ist ungültig oder abgelaufen';
 $messages['imaperror'] = 'Keine Verbindung zum IMAP Server';
 $messages['servererror'] = 'Serverfehler!';
 $messages['servererrormsg'] = 'Serverfehler: $msg';
 $messages['imaperror'] = 'Keine Verbindung zum IMAP Server';
 $messages['servererror'] = 'Serverfehler!';
 $messages['servererrormsg'] = 'Serverfehler: $msg';
-$messages['databaserror'] = 'Datenbankfehler!';
+$messages['dberror'] = 'Datenbankfehler!';
 $messages['errorreadonly'] = 'Die Aktion kann nicht ausgeführt werden. Der Ordner ist schreibgeschützt.';
 $messages['errornoperm'] = 'Die Aktion kann nicht ausgeführt werden. Zugriff verweigert.';
 $messages['invalidrequest'] = 'Ungültige Anfrage! Es wurden keine Daten gespeichert.';
 $messages['errorreadonly'] = 'Die Aktion kann nicht ausgeführt werden. Der Ordner ist schreibgeschützt.';
 $messages['errornoperm'] = 'Die Aktion kann nicht ausgeführt werden. Zugriff verweigert.';
 $messages['invalidrequest'] = 'Ungültige Anfrage! Es wurden keine Daten gespeichert.';
@@ -48,6 +48,7 @@ $messages['blockedimages'] = 'Um Ihre Privatsphäre zur schützen, wurden extern
 $messages['encryptedmessage'] = 'Dies ist eine verschlüsselte Nachricht und kann leider nicht angezeigt werden.';
 $messages['nocontactsfound'] = 'Keine Kontakte gefunden';
 $messages['contactnotfound'] = 'Die gewählte Adresse wurde nicht gefunden';
 $messages['encryptedmessage'] = 'Dies ist eine verschlüsselte Nachricht und kann leider nicht angezeigt werden.';
 $messages['nocontactsfound'] = 'Keine Kontakte gefunden';
 $messages['contactnotfound'] = 'Die gewählte Adresse wurde nicht gefunden';
+$messages['contactsearchonly'] = 'Geben Sie einen Suchbegriff ein, um Kontakte zu finden';
 $messages['sendingfailed'] = 'Versand der Nachricht fehlgeschlagen';
 $messages['senttooquickly'] = 'Bitte warten Sie $sec Sekunde(n) vor dem Senden dieser Nachricht';
 $messages['errorsavingsent'] = 'Ein Fehler ist beim Speichern der gesendeten Nachricht aufgetreten';
 $messages['sendingfailed'] = 'Versand der Nachricht fehlgeschlagen';
 $messages['senttooquickly'] = 'Bitte warten Sie $sec Sekunde(n) vor dem Senden dieser Nachricht';
 $messages['errorsavingsent'] = 'Ein Fehler ist beim Speichern der gesendeten Nachricht aufgetreten';
index 1015185ef9cb3bd7b471825596c0f6dab047bfce..ea7e0a0a827354d2ff7a413345e15ccedf3bceb0 100644 (file)
 +-----------------------------------------------------------------------+
 | Author:      Thomas Bruederli <roundcube@gmail.com>                   |
 | Author: Marcel Schlesinger <info@marcel-schlesinger.de>               |
 +-----------------------------------------------------------------------+
 | Author:      Thomas Bruederli <roundcube@gmail.com>                   |
 | Author: Marcel Schlesinger <info@marcel-schlesinger.de>               |
+| Author: Roland Liebl <myroundcube@mail4us.net>                        |
 +-----------------------------------------------------------------------+
 
 +-----------------------------------------------------------------------+
 
-@version $Id: labels.inc 5040 2011-08-10 11:09:16Z thomasb $
+@version $Id: labels.inc 5569 2011-12-07 14:47:32Z thomasb $
 
 */
 
 
 */
 
@@ -101,18 +102,16 @@ $labels['replytomessage'] = 'Antwort verfassen';
 $labels['replytoallmessage'] = 'Antwort an Absender und alle Empfänger verfassen';
 $labels['replyall'] = 'Allen antworten';
 $labels['replylist'] = 'Liste antworten';
 $labels['replytoallmessage'] = 'Antwort an Absender und alle Empfänger verfassen';
 $labels['replyall'] = 'Allen antworten';
 $labels['replylist'] = 'Liste antworten';
+$labels['forwardinline'] = 'innerhalb der Nachricht';
+$labels['forwardattachment'] = 'als Dateianhang';
 $labels['forwardmessage'] = 'Nachricht weiterleiten';
 $labels['deletemessage'] = 'Nachricht löschen';
 $labels['movemessagetotrash'] = 'Nachricht in den Papierkorb verschieben';
 $labels['printmessage'] = 'Nachricht drucken';
 $labels['previousmessage'] = 'Vorherige Nachricht anzeigen';
 $labels['forwardmessage'] = 'Nachricht weiterleiten';
 $labels['deletemessage'] = 'Nachricht löschen';
 $labels['movemessagetotrash'] = 'Nachricht in den Papierkorb verschieben';
 $labels['printmessage'] = 'Nachricht drucken';
 $labels['previousmessage'] = 'Vorherige Nachricht anzeigen';
-$labels['previousmessages'] = 'Vorherige Nachrichten anzeigen';
 $labels['firstmessage'] = 'Die erste Nachricht anzeigen';
 $labels['firstmessage'] = 'Die erste Nachricht anzeigen';
-$labels['firstmessages'] = 'Die ersten Nachrichten anzeigen';
 $labels['nextmessage'] = 'Nächste Nachricht anzeigen';
 $labels['nextmessage'] = 'Nächste Nachricht anzeigen';
-$labels['nextmessages'] = 'Weitere Nachrichten anzeigen';
 $labels['lastmessage'] = 'Die letzte Nachricht anzeigen';
 $labels['lastmessage'] = 'Die letzte Nachricht anzeigen';
-$labels['lastmessages'] = 'Die letzten Nachrichten anzeigen';
 $labels['backtolist'] = 'Zurück zur Liste';
 $labels['viewsource'] = 'Quelltext anzeigen';
 $labels['markmessages'] = 'Nachrichten markieren';
 $labels['backtolist'] = 'Zurück zur Liste';
 $labels['viewsource'] = 'Quelltext anzeigen';
 $labels['markmessages'] = 'Nachrichten markieren';
@@ -120,7 +119,7 @@ $labels['markread'] = 'Als gelesen';
 $labels['markunread'] = 'Als ungelesen';
 $labels['markflagged'] = 'Stern hinzufügen';
 $labels['markunflagged'] = 'Stern entfernen';
 $labels['markunread'] = 'Als ungelesen';
 $labels['markflagged'] = 'Stern hinzufügen';
 $labels['markunflagged'] = 'Stern entfernen';
-$labels['messageactions'] = 'Weitere Aktionen...';
+$labels['moreactions'] = 'Mehr ...';
 $labels['select'] = 'Auswählen';
 $labels['all'] = 'Alle';
 $labels['none'] = 'Keine';
 $labels['select'] = 'Auswählen';
 $labels['all'] = 'Alle';
 $labels['none'] = 'Keine';
@@ -174,12 +173,14 @@ $labels['editortype'] = 'Editor Typ';
 $labels['returnreceipt'] = 'Empfangsbestätigung (MSN)';
 $labels['dsn'] = 'Übermittlungsbestätigung (DSN)';
 $labels['mailreplyintro'] = 'Am $date, schrieb $sender:';
 $labels['returnreceipt'] = 'Empfangsbestätigung (MSN)';
 $labels['dsn'] = 'Übermittlungsbestätigung (DSN)';
 $labels['mailreplyintro'] = 'Am $date, schrieb $sender:';
+$labels['originalmessage'] = 'Originalnachricht';
 $labels['editidents'] = 'Absender ändern';
 $labels['checkspelling'] = 'Rechtschreibung prüfen';
 $labels['resumeediting'] = 'Bearbeitung fortsetzen';
 $labels['revertto'] = 'Zurück zu';
 $labels['attachments'] = 'Anhänge';
 $labels['upload'] = 'Hochladen';
 $labels['editidents'] = 'Absender ändern';
 $labels['checkspelling'] = 'Rechtschreibung prüfen';
 $labels['resumeediting'] = 'Bearbeitung fortsetzen';
 $labels['revertto'] = 'Zurück zu';
 $labels['attachments'] = 'Anhänge';
 $labels['upload'] = 'Hochladen';
+$labels['uploadprogress'] = '$percent ($current von $total)';
 $labels['close'] = 'Schließen';
 $labels['messageoptions'] = 'Optionen...';
 $labels['low'] = 'Niedrig';
 $labels['close'] = 'Schließen';
 $labels['messageoptions'] = 'Optionen...';
 $labels['low'] = 'Niedrig';
@@ -232,6 +233,24 @@ $labels['female'] = 'weiblich';
 $labels['manager'] = 'Vorgesetze(r)';
 $labels['assistant'] = 'Assistent';
 $labels['spouse'] = 'Partner/in';
 $labels['manager'] = 'Vorgesetze(r)';
 $labels['assistant'] = 'Assistent';
 $labels['spouse'] = 'Partner/in';
+$labels['allfields'] = 'Alle Felder';
+$labels['search'] = 'Suche';
+$labels['advsearch'] = 'Detaillierte Suche';
+$labels['other'] = 'Sonstiges';
+$labels['typehome'] = 'Privat';
+$labels['typework'] = 'Dienstlich';
+$labels['typeother'] = 'Andere';
+$labels['typemobile'] = 'Mobil';
+$labels['typemain'] = 'Hauptnummer';
+$labels['typehomefax'] = 'Fax Privat';
+$labels['typeworkfax'] = 'Fax Dienst';
+$labels['typecar'] = 'Auto';
+$labels['typepager'] = 'Pager';
+$labels['typevideo'] = 'Video';
+$labels['typeassistant'] = 'Assistenz';
+$labels['typehomepage'] = 'Internet';
+$labels['typeblog'] = 'Blog';
+$labels['typeprofile'] = 'Profil';
 $labels['addfield'] = 'Feld hinzufügen...';
 $labels['addcontact'] = 'Kontakt hinzufügen';
 $labels['editcontact'] = 'Kontakt bearbeiten';
 $labels['addfield'] = 'Feld hinzufügen...';
 $labels['addcontact'] = 'Kontakt hinzufügen';
 $labels['editcontact'] = 'Kontakt bearbeiten';
@@ -253,7 +272,8 @@ $labels['print'] = 'Drucken';
 $labels['export'] = 'Exportieren';
 $labels['exportvcards'] = 'Kontakte im vCard-Format exportieren';
 $labels['newcontactgroup'] = 'Neue Kontaktgruppen erstellen';
 $labels['export'] = 'Exportieren';
 $labels['exportvcards'] = 'Kontakte im vCard-Format exportieren';
 $labels['newcontactgroup'] = 'Neue Kontaktgruppen erstellen';
-$labels['groupactions'] = 'Aktionen für Kontaktgruppen...';
+$labels['grouprename'] = 'Gruppe umbenennen';
+$labels['groupdelete'] = 'Gruppe löschen';
 $labels['previouspage'] = 'Seite zurück';
 $labels['firstpage'] = 'Erste Seite';
 $labels['nextpage'] = 'Nächste Seite';
 $labels['previouspage'] = 'Seite zurück';
 $labels['firstpage'] = 'Erste Seite';
 $labels['nextpage'] = 'Nächste Seite';
@@ -261,9 +281,12 @@ $labels['lastpage'] = 'Letzte Seite';
 $labels['group'] = 'Gruppe';
 $labels['groups'] = 'Gruppen';
 $labels['personaladrbook'] = 'Persönliches Adressbuch';
 $labels['group'] = 'Gruppe';
 $labels['groups'] = 'Gruppen';
 $labels['personaladrbook'] = 'Persönliches Adressbuch';
+$labels['searchsave'] = 'Suchergebnisse speichern';
+$labels['searchdelete'] = 'Suchergebnisse löschen';
 $labels['import'] = 'Importieren';
 $labels['importcontacts'] = 'Kontakte importieren';
 $labels['importfromfile'] = 'Import aus Datei:';
 $labels['import'] = 'Importieren';
 $labels['importcontacts'] = 'Kontakte importieren';
 $labels['importfromfile'] = 'Import aus Datei:';
+$labels['importtarget'] = 'Einen neuen Kontakt hinzufügen:';
 $labels['importreplace'] = 'Bestehendes Adressbuch komplett ersetzen';
 $labels['importtext'] = 'Sie können Kontakte aus einem bestehenden Adressbuch hochladen. Zur Zeit können Adressbücher im vCard-Format importiert werden.';
 $labels['done'] = 'Fertig';
 $labels['importreplace'] = 'Bestehendes Adressbuch komplett ersetzen';
 $labels['importtext'] = 'Sie können Kontakte aus einem bestehenden Adressbuch hochladen. Zur Zeit können Adressbücher im vCard-Format importiert werden.';
 $labels['done'] = 'Fertig';
@@ -279,6 +302,8 @@ $labels['edititem'] = 'Eintrag bearbeiten';
 $labels['preferhtml'] = 'HTML anzeigen';
 $labels['defaultcharset'] = 'Standard Zeichensatz';
 $labels['htmlmessage'] = 'HTML-Nachricht';
 $labels['preferhtml'] = 'HTML anzeigen';
 $labels['defaultcharset'] = 'Standard Zeichensatz';
 $labels['htmlmessage'] = 'HTML-Nachricht';
+$labels['dateformat'] = 'Datumsformatierung';
+$labels['timeformat'] = 'Zeitformatierung';
 $labels['prettydate'] = 'Kurze Datumsanzeige';
 $labels['setdefault'] = 'Als Standard';
 $labels['autodetect'] = 'Automatisch';
 $labels['prettydate'] = 'Kurze Datumsanzeige';
 $labels['setdefault'] = 'Als Standard';
 $labels['autodetect'] = 'Automatisch';
@@ -349,6 +374,13 @@ $labels['afternseconds'] = 'nach $n Sekunden';
 $labels['reqmdn'] = 'Empfangsbestätigung (MSN) immer anfordern';
 $labels['reqdsn'] = 'Übermittlungsbestätigung (DSN) immer anfordern';
 $labels['replysamefolder'] = 'Antworten im selben Ordner wie Original speichern';
 $labels['reqmdn'] = 'Empfangsbestätigung (MSN) immer anfordern';
 $labels['reqdsn'] = 'Übermittlungsbestätigung (DSN) immer anfordern';
 $labels['replysamefolder'] = 'Antworten im selben Ordner wie Original speichern';
+$labels['defaultaddressbook'] = 'Neue Kontakte zum ausgewählten Adressbuch hinzufügen';
+$labels['spellcheckbeforesend'] = 'Rechtschreibprüfung vor dem Absenden der Nachricht';
+$labels['spellcheckoptions'] = 'Rechtschreibprüfungsoptionen';
+$labels['spellcheckignoresyms'] = 'Wörter mit Symbolen überspringen';
+$labels['spellcheckignorenums'] = 'Wörter mit Ziffern überspringen';
+$labels['spellcheckignorecaps'] = 'Wörter überspringen, die nur aus Großbuchstaben bestehen';
+$labels['addtodict'] = 'Zum Wörterbuch hinzufügen';
 $labels['folder'] = 'Ordner';
 $labels['folders'] = 'Ordner';
 $labels['foldername'] = 'Ordnername';
 $labels['folder'] = 'Ordner';
 $labels['folders'] = 'Ordner';
 $labels['foldername'] = 'Ordnername';
@@ -365,9 +397,14 @@ $labels['location'] = 'Speicherort';
 $labels['info'] = 'Informationen';
 $labels['getfoldersize'] = 'Ordnergröße anzeigen';
 $labels['changesubscription'] = 'Abonnieren';
 $labels['info'] = 'Informationen';
 $labels['getfoldersize'] = 'Ordnergröße anzeigen';
 $labels['changesubscription'] = 'Abonnieren';
+$labels['foldertype'] = 'Ordnertyp';
+$labels['personalfolder'] = 'Privater Ordner';
+$labels['otherfolder'] = 'Ordner eines anderen Benutzers';
+$labels['sharedfolder'] = 'Öffentlicher Ordner';
 $labels['sortby'] = 'Sortieren nach';
 $labels['sortasc'] = 'Aufsteigend sortieren';
 $labels['sortdesc'] = 'Absteigend sortieren';
 $labels['sortby'] = 'Sortieren nach';
 $labels['sortasc'] = 'Aufsteigend sortieren';
 $labels['sortdesc'] = 'Absteigend sortieren';
+$labels['undo'] = 'Rückgängig machen';
 $labels['B'] = 'B';
 $labels['KB'] = 'KB';
 $labels['MB'] = 'MB';
 $labels['B'] = 'B';
 $labels['KB'] = 'KB';
 $labels['MB'] = 'MB';
index 104f60c3c759232a7bf4aa29d35b4330a7c28123..584146dda28e6eaa68dc870530ec605bd86f2403 100644 (file)
 +-----------------------------------------------------------------------+
 | Author: Thomas Bruederli <roundcube@gmail.com>                        |
 | Author: Marcel Schlesinger <info@marcel-schlesinger.de>               |
 +-----------------------------------------------------------------------+
 | Author: Thomas Bruederli <roundcube@gmail.com>                        |
 | Author: Marcel Schlesinger <info@marcel-schlesinger.de>               |
+| Author: Roland Liebl <myroundcube@mail4us.net>                        |
 +-----------------------------------------------------------------------+
 
 +-----------------------------------------------------------------------+
 
-@version $Id: messages.inc 5079 2011-08-16 19:57:45Z thomasb $
+@version $Id: messages.inc 5569 2011-12-07 14:47:32Z thomasb $
 
 */
 
 
 */
 
@@ -25,7 +26,7 @@ $messages['sessionerror'] = 'Ihre Session ist ungültig oder abgelaufen';
 $messages['imaperror'] = 'Keine Verbindung zum IMAP Server';
 $messages['servererror'] = 'Serverfehler!';
 $messages['servererrormsg'] = 'Serverfehler: $msg';
 $messages['imaperror'] = 'Keine Verbindung zum IMAP Server';
 $messages['servererror'] = 'Serverfehler!';
 $messages['servererrormsg'] = 'Serverfehler: $msg';
-$messages['databaserror'] = 'Datenbankfehler!';
+$messages['dberror'] = 'Datenbankfehler!';
 $messages['errorreadonly'] = 'Die Aktion kann nicht ausgeführt werden. Der Ordner ist schreibgeschützt.';
 $messages['errornoperm'] = 'Die Aktion kann nicht ausgeführt werden. Zugriff verweigert.';
 $messages['invalidrequest'] = 'Ungültige Anfrage! Es wurden keine Daten gespeichert.';
 $messages['errorreadonly'] = 'Die Aktion kann nicht ausgeführt werden. Der Ordner ist schreibgeschützt.';
 $messages['errornoperm'] = 'Die Aktion kann nicht ausgeführt werden. Zugriff verweigert.';
 $messages['invalidrequest'] = 'Ungültige Anfrage! Es wurden keine Daten gespeichert.';
@@ -49,6 +50,7 @@ $messages['blockedimages'] = 'Um Ihre Privatsphäre zur schützen, wurden extern
 $messages['encryptedmessage'] = 'Dies ist eine verschlüsselte Nachricht und kann leider nicht angezeigt werden.';
 $messages['nocontactsfound'] = 'Keine Kontakte gefunden';
 $messages['contactnotfound'] = 'Der angeforderte Kontakt wurde nicht gefunden';
 $messages['encryptedmessage'] = 'Dies ist eine verschlüsselte Nachricht und kann leider nicht angezeigt werden.';
 $messages['nocontactsfound'] = 'Keine Kontakte gefunden';
 $messages['contactnotfound'] = 'Der angeforderte Kontakt wurde nicht gefunden';
+$messages['contactsearchonly'] = 'Geben Sie einen Suchbegriff ein, um Kontakte zu finden';
 $messages['sendingfailed'] = 'Versenden der Nachricht fehlgeschlagen';
 $messages['senttooquickly'] = 'Bitte warten Sie $sec Sekunde(n) vor dem Senden dieser Nachricht';
 $messages['errorsavingsent'] = 'Ein Fehler ist beim Speichern der gesendeten Nachricht aufgetreten';
 $messages['sendingfailed'] = 'Versenden der Nachricht fehlgeschlagen';
 $messages['senttooquickly'] = 'Bitte warten Sie $sec Sekunde(n) vor dem Senden dieser Nachricht';
 $messages['errorsavingsent'] = 'Ein Fehler ist beim Speichern der gesendeten Nachricht aufgetreten';
@@ -77,10 +79,10 @@ $messages['nosubjectwarning'] = 'Die Betreffzeile ist leer. Möchten Sie jetzt e
 $messages['nobodywarning'] = 'Diese Nachricht ohne Inhalt senden?';
 $messages['notsentwarning'] = 'Ihre Nachricht wurde nicht gesendet. Wollen Sie die Nachricht verwerfen?';
 $messages['noldapserver'] = 'Bitte wählen Sie einen LDAP-Server aus';
 $messages['nobodywarning'] = 'Diese Nachricht ohne Inhalt senden?';
 $messages['notsentwarning'] = 'Ihre Nachricht wurde nicht gesendet. Wollen Sie die Nachricht verwerfen?';
 $messages['noldapserver'] = 'Bitte wählen Sie einen LDAP-Server aus';
-$messages['nocontactsreturned'] = 'Es wurden keine Kontakte gefunden';
 $messages['nosearchname'] = 'Bitte geben Sie einen Namen oder eine E-Mail-Adresse ein';
 $messages['notuploadedwarning'] = 'Es wurden noch nicht alle Dateien hochgeladen. Bitte warten oder Upload abbrechen.';
 $messages['searchsuccessful'] = '$nr Nachrichten gefunden';
 $messages['nosearchname'] = 'Bitte geben Sie einen Namen oder eine E-Mail-Adresse ein';
 $messages['notuploadedwarning'] = 'Es wurden noch nicht alle Dateien hochgeladen. Bitte warten oder Upload abbrechen.';
 $messages['searchsuccessful'] = '$nr Nachrichten gefunden';
+$messages['contactsearchsuccessful'] = '$nr Kontakte gefunden';
 $messages['searchnomatch'] = 'Die Suche lieferte keine Treffer';
 $messages['searching'] = 'Suche...';
 $messages['checking'] = 'Prüfe...';
 $messages['searchnomatch'] = 'Die Suche lieferte keine Treffer';
 $messages['searching'] = 'Suche...';
 $messages['checking'] = 'Prüfe...';
@@ -127,7 +129,6 @@ $messages['smtpautherror'] = 'SMTP Fehler ($code): Die Authentisierung ist fehlg
 $messages['smtpfromerror'] = 'SMTP Fehler ($code): Der Absender "$from" konnte nicht gesetzt werden ($msg)';
 $messages['smtptoerror'] = 'SMTP Fehler ($code): Der Empfänger "$to" konnte nicht gesetzt werden ($msg)';
 $messages['smtprecipientserror'] = 'SMTP Fehler: Die Empfängerliste konnte nicht verarbeitet werden';
 $messages['smtpfromerror'] = 'SMTP Fehler ($code): Der Absender "$from" konnte nicht gesetzt werden ($msg)';
 $messages['smtptoerror'] = 'SMTP Fehler ($code): Der Empfänger "$to" konnte nicht gesetzt werden ($msg)';
 $messages['smtprecipientserror'] = 'SMTP Fehler: Die Empfängerliste konnte nicht verarbeitet werden';
-$messages['smtpdsnerror'] = 'SMTP-Fehler: Übermittlungsbestätigungen werden nicht unterstützt';
 $messages['smtperror'] = 'SMTP Fehler: $msg';
 $messages['emailformaterror'] = 'Ungültige E-Mail-Adresse: $email';
 $messages['toomanyrecipients'] = 'Zuviele Empfänger. Reduzieren Sie die Anzahl Empfängeradressen auf $max.';
 $messages['smtperror'] = 'SMTP Fehler: $msg';
 $messages['emailformaterror'] = 'Ungültige E-Mail-Adresse: $email';
 $messages['toomanyrecipients'] = 'Zuviele Empfänger. Reduzieren Sie die Anzahl Empfängeradressen auf $max.';
@@ -140,11 +141,16 @@ $messages['contactrestored'] = 'Kontakte erfolgreich wiederhergestellt.';
 $messages['groupdeleted'] = 'Gruppe erfolgreich gelöscht';
 $messages['grouprenamed'] = 'Gruppe erlogreich umbenannt';
 $messages['groupcreated'] = 'Gruppe erlogreich erstellt';
 $messages['groupdeleted'] = 'Gruppe erfolgreich gelöscht';
 $messages['grouprenamed'] = 'Gruppe erlogreich umbenannt';
 $messages['groupcreated'] = 'Gruppe erlogreich erstellt';
+$messages['savedsearchdeleted'] = 'Suchergebnisse erfolgreich gelöscht';
+$messages['savedsearchdeleteerror'] = 'Suchergebnisse konnten nicht gelöscht werden';
+$messages['savedsearchcreated'] = 'Suchergebnisse wurden erfolgreich wiederherstellt';
+$messages['savedsearchcreateerror'] = 'Suchergebnisse konnten nicht wiederhergestellt werden';
 $messages['messagedeleted'] = 'Nachricht(en) erfolgreich gelöscht';
 $messages['messagemoved'] = 'Nachricht(en) erfolgreich verschoben';
 $messages['messagecopied'] = 'Nachricht(en) erfolgreich kopiert';
 $messages['messagemarked'] = 'Nachricht(en) erfolgreich markiert';
 $messages['autocompletechars'] = 'Geben Sie mind. $min Zeichen für die Auto-Vervollständigung ein';
 $messages['messagedeleted'] = 'Nachricht(en) erfolgreich gelöscht';
 $messages['messagemoved'] = 'Nachricht(en) erfolgreich verschoben';
 $messages['messagecopied'] = 'Nachricht(en) erfolgreich kopiert';
 $messages['messagemarked'] = 'Nachricht(en) erfolgreich markiert';
 $messages['autocompletechars'] = 'Geben Sie mind. $min Zeichen für die Auto-Vervollständigung ein';
+$messages['autocompletemore'] = 'Mehrere Treffer. Bitte geben Sie mehr Buchstaben ein';
 $messages['namecannotbeempty'] = 'Der Name darf nicht leer sein';
 $messages['nametoolong'] = 'Der Name ist zu lang';
 $messages['folderupdated'] = 'Der Ordner wurde erfolgreich aktualisiert';
 $messages['namecannotbeempty'] = 'Der Name darf nicht leer sein';
 $messages['nametoolong'] = 'Der Name ist zu lang';
 $messages['folderupdated'] = 'Der Ordner wurde erfolgreich aktualisiert';
index 70fd646d0045d53b950d6ab1c195b2bd498c7c9a..9bb70394ffef9ad4b6acebec85449b1e95195c7f 100644 (file)
 |                                                                       |
 +-----------------------------------------------------------------------+
 | Author: Weiran Zhang (weiran@weiran.co.uk)                            |
 |                                                                       |
 +-----------------------------------------------------------------------+
 | Author: Weiran Zhang (weiran@weiran.co.uk)                            |
+|         Phil Weir                                                     |
 +-----------------------------------------------------------------------+
 
 +-----------------------------------------------------------------------+
 
-@version $Id: labels.inc 5175 2011-09-05 18:42:24Z thomasb $
+@version $Id: labels.inc 5184 2011-09-07 06:33:15Z alec $
 
 */
 
 
 */
 
@@ -33,8 +34,8 @@ $labels['sent'] = 'Sent';
 $labels['trash'] = 'Deleted Items';
 $labels['junk'] = 'Junk';
 $labels['subject'] = 'Subject';
 $labels['trash'] = 'Deleted Items';
 $labels['junk'] = 'Junk';
 $labels['subject'] = 'Subject';
-$labels['from'] = 'Sender';
-$labels['to'] = 'Recipient';
+$labels['from'] = 'From';
+$labels['to'] = 'To';
 $labels['cc'] = 'Copy';
 $labels['bcc'] = 'Bcc';
 $labels['replyto'] = 'Reply-To';
 $labels['cc'] = 'Copy';
 $labels['bcc'] = 'Bcc';
 $labels['replyto'] = 'Reply-To';
@@ -137,7 +138,7 @@ $labels['threaded'] = 'Threaded';
 $labels['autoexpand_threads'] = 'Expand message threads';
 $labels['do_expand'] = 'all threads';
 $labels['expand_only_unread'] = 'only with unread messages';
 $labels['autoexpand_threads'] = 'Expand message threads';
 $labels['do_expand'] = 'all threads';
 $labels['expand_only_unread'] = 'only with unread messages';
-$labels['fromto'] = 'Sender/Recipient';
+$labels['fromto'] = 'From/To';
 $labels['flag'] = 'Flag';
 $labels['attachment'] = 'Attachment';
 $labels['nonesort'] = 'None';
 $labels['flag'] = 'Flag';
 $labels['attachment'] = 'Attachment';
 $labels['nonesort'] = 'None';
index 4a0807f33bc87462019b0eaddb5fdf2af6475342..6d344be5899a27597c450dd8261d06d0b20d1844 100644 (file)
 |                                                                       |
 +-----------------------------------------------------------------------+
 | Author: Weiran Zhang (weiran@weiran.co.uk)                            |
 |                                                                       |
 +-----------------------------------------------------------------------+
 | Author: Weiran Zhang (weiran@weiran.co.uk)                            |
+|         Phil Weir                                                     |
 +-----------------------------------------------------------------------+
 
 +-----------------------------------------------------------------------+
 
-@version $Id: messages.inc 5175 2011-09-05 18:42:24Z thomasb $
+@version $Id: messages.inc 5173 2011-09-05 18:41:04Z thomasb $
 
 */
 
 
 */
 
index e6dd58c49d6b835fb169bb1e3d5d06f27b34b813..4fbed2929cd885ecdf1a3fe16eff155b3ddee2e9 100644 (file)
@@ -13,7 +13,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- @version $Id: labels.inc 5165 2011-09-05 08:49:04Z thomasb $
+ @version $Id: labels.inc 5569 2011-12-07 14:47:32Z thomasb $
 
 */
 
 
 */
 
@@ -41,9 +41,9 @@ $labels['junk']   = 'Junk';
 
 // message listing
 $labels['subject'] = 'Subject';
 
 // message listing
 $labels['subject'] = 'Subject';
-$labels['from']    = 'Sender';
-$labels['to']      = 'Recipient';
-$labels['cc']      = 'Copy';
+$labels['from']    = 'From';
+$labels['to']      = 'To';
+$labels['cc']      = 'Cc';
 $labels['bcc']     = 'Bcc';
 $labels['replyto'] = 'Reply-To';
 $labels['followupto'] = 'Followup-To';
 $labels['bcc']     = 'Bcc';
 $labels['replyto'] = 'Reply-To';
 $labels['followupto'] = 'Followup-To';
@@ -140,7 +140,7 @@ $labels['markread']         = 'As read';
 $labels['markunread']       = 'As unread';
 $labels['markflagged']      = 'As flagged';
 $labels['markunflagged']    = 'As unflagged';
 $labels['markunread']       = 'As unread';
 $labels['markflagged']      = 'As flagged';
 $labels['markunflagged']    = 'As unflagged';
-$labels['messageactions']   = 'More actions...';
+$labels['moreactions']      = 'More actions...';
 
 $labels['select'] = 'Select';
 $labels['all'] = 'All';
 
 $labels['select'] = 'Select';
 $labels['all'] = 'All';
@@ -152,7 +152,6 @@ $labels['unanswered'] = 'Unanswered';
 $labels['deleted'] = 'Deleted';
 $labels['invert'] = 'Invert';
 $labels['filter'] = 'Filter';
 $labels['deleted'] = 'Deleted';
 $labels['invert'] = 'Invert';
 $labels['filter'] = 'Filter';
-
 $labels['list'] = 'List';
 $labels['threads'] = 'Threads';
 $labels['expand-all'] = 'Expand All';
 $labels['list'] = 'List';
 $labels['threads'] = 'Threads';
 $labels['expand-all'] = 'Expand All';
@@ -163,7 +162,7 @@ $labels['threaded'] = 'Threaded';
 $labels['autoexpand_threads'] = 'Expand message threads';
 $labels['do_expand'] = 'all threads';
 $labels['expand_only_unread'] = 'only with unread messages';
 $labels['autoexpand_threads'] = 'Expand message threads';
 $labels['do_expand'] = 'all threads';
 $labels['expand_only_unread'] = 'only with unread messages';
-$labels['fromto'] = 'Sender/Recipient';
+$labels['fromto'] = 'From/To';
 $labels['flag'] = 'Flag';
 $labels['attachment'] = 'Attachment';
 $labels['nonesort'] = 'None';
 $labels['flag'] = 'Flag';
 $labels['attachment'] = 'Attachment';
 $labels['nonesort'] = 'None';
@@ -203,6 +202,7 @@ $labels['editortype']     = 'Editor type';
 $labels['returnreceipt']  = 'Return receipt';
 $labels['dsn']            = 'Delivery status notification';
 $labels['mailreplyintro'] = 'On $date, $sender wrote:';
 $labels['returnreceipt']  = 'Return receipt';
 $labels['dsn']            = 'Delivery status notification';
 $labels['mailreplyintro'] = 'On $date, $sender wrote:';
+$labels['originalmessage'] = 'Original Message';
 
 $labels['editidents']    = 'Edit identities';
 $labels['checkspelling'] = 'Check spelling';
 
 $labels['editidents']    = 'Edit identities';
 $labels['checkspelling'] = 'Check spelling';
@@ -224,6 +224,7 @@ $labels['highest'] = 'Highest';
 $labels['nosubject']  = '(no subject)';
 $labels['showimages'] = 'Display images';
 $labels['alwaysshow'] = 'Always show images from $sender';
 $labels['nosubject']  = '(no subject)';
 $labels['showimages'] = 'Display images';
 $labels['alwaysshow'] = 'Always show images from $sender';
+$labels['isdraft']    = 'This is a draft message.';
 
 $labels['htmltoggle'] = 'HTML';
 $labels['plaintoggle'] = 'Plain text';
 
 $labels['htmltoggle'] = 'HTML';
 $labels['plaintoggle'] = 'Plain text';
@@ -316,7 +317,6 @@ $labels['print']          = 'Print';
 $labels['export']         = 'Export';
 $labels['exportvcards']   = 'Export contacts in vCard format';
 $labels['newcontactgroup'] = 'Create new contact group';
 $labels['export']         = 'Export';
 $labels['exportvcards']   = 'Export contacts in vCard format';
 $labels['newcontactgroup'] = 'Create new contact group';
-$labels['groupactions']   = 'Actions for contact groups...';
 $labels['grouprename']    = 'Rename group';
 $labels['groupdelete']    = 'Delete group';
 
 $labels['grouprename']    = 'Rename group';
 $labels['groupdelete']    = 'Delete group';
 
@@ -329,6 +329,9 @@ $labels['group'] = 'Group';
 $labels['groups'] = 'Groups';
 $labels['personaladrbook'] = 'Personal Addresses';
 
 $labels['groups'] = 'Groups';
 $labels['personaladrbook'] = 'Personal Addresses';
 
+$labels['searchsave'] = 'Save search';
+$labels['searchdelete'] = 'Delete search';
+
 $labels['import'] = 'Import';
 $labels['importcontacts'] = 'Import contacts';
 $labels['importfromfile'] = 'Import from file:';
 $labels['import'] = 'Import';
 $labels['importcontacts'] = 'Import contacts';
 $labels['importfromfile'] = 'Import from file:';
@@ -339,7 +342,7 @@ $labels['done'] = 'Done';
 
 // settings
 $labels['settingsfor']  = 'Settings for';
 
 // settings
 $labels['settingsfor']  = 'Settings for';
-
+$labels['about'] = 'About';
 $labels['preferences']  = 'Preferences';
 $labels['userpreferences']  = 'User preferences';
 $labels['editpreferences']  = 'Edit user preferences';
 $labels['preferences']  = 'Preferences';
 $labels['userpreferences']  = 'User preferences';
 $labels['editpreferences']  = 'Edit user preferences';
@@ -354,6 +357,8 @@ $labels['edititem']  = 'Edit item';
 $labels['preferhtml'] = 'Display HTML';
 $labels['defaultcharset'] = 'Default Character Set';
 $labels['htmlmessage'] = 'HTML Message';
 $labels['preferhtml'] = 'Display HTML';
 $labels['defaultcharset'] = 'Default Character Set';
 $labels['htmlmessage'] = 'HTML Message';
+$labels['dateformat'] = 'Date format';
+$labels['timeformat'] = 'Time format';
 $labels['prettydate'] = 'Pretty dates';
 $labels['setdefault']  = 'Set default';
 $labels['autodetect']  = 'Auto';
 $labels['prettydate'] = 'Pretty dates';
 $labels['setdefault']  = 'Set default';
 $labels['autodetect']  = 'Auto';
@@ -402,6 +407,7 @@ $labels['advancedoptions'] = 'Advanced options';
 $labels['focusonnewmessage'] = 'Focus browser window on new message';
 $labels['checkallfolders'] = 'Check all folders for new messages';
 $labels['displaynext'] = 'After message delete/move display the next message';
 $labels['focusonnewmessage'] = 'Focus browser window on new message';
 $labels['checkallfolders'] = 'Check all folders for new messages';
 $labels['displaynext'] = 'After message delete/move display the next message';
+$labels['defaultfont'] = 'Default font of HTML message';
 $labels['mainoptions'] = 'Main Options';
 $labels['section'] = 'Section';
 $labels['maintenance'] = 'Maintenance';
 $labels['mainoptions'] = 'Main Options';
 $labels['section'] = 'Section';
 $labels['maintenance'] = 'Maintenance';
@@ -425,7 +431,13 @@ $labels['reqmdn'] = 'Always request a return receipt';
 $labels['reqdsn'] = 'Always request a delivery status notification';
 $labels['replysamefolder'] = 'Place replies in the folder of the message being replied to';
 $labels['defaultaddressbook'] = 'Add new contacts to the selected addressbook';
 $labels['reqdsn'] = 'Always request a delivery status notification';
 $labels['replysamefolder'] = 'Place replies in the folder of the message being replied to';
 $labels['defaultaddressbook'] = 'Add new contacts to the selected addressbook';
+$labels['autocompletesingle'] = 'Skip alternative email addresses in autocompletion';
 $labels['spellcheckbeforesend'] = 'Check spelling before sending a message';
 $labels['spellcheckbeforesend'] = 'Check spelling before sending a message';
+$labels['spellcheckoptions'] = 'Spellcheck Options';
+$labels['spellcheckignoresyms'] = 'Ignore words with symbols';
+$labels['spellcheckignorenums'] = 'Ignore words with numbers';
+$labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized';
+$labels['addtodict'] = 'Add to dictionary';
 
 $labels['folder']  = 'Folder';
 $labels['folders']  = 'Folders';
 
 $labels['folder']  = 'Folder';
 $labels['folders']  = 'Folders';
@@ -453,6 +465,12 @@ $labels['sortasc']  = 'Sort ascending';
 $labels['sortdesc'] = 'Sort descending';
 $labels['undo'] = 'Undo';
 
 $labels['sortdesc'] = 'Sort descending';
 $labels['undo'] = 'Undo';
 
+$labels['plugin'] = 'Plugin';
+$labels['version'] = 'Version';
+$labels['source'] = 'Source';
+$labels['license'] = 'License';
+$labels['support'] = 'Get support';
+
 // units
 $labels['B'] = 'B';
 $labels['KB'] = 'KB';
 // units
 $labels['B'] = 'B';
 $labels['KB'] = 'KB';
index 5da8458f08515c597ddb584e9672e3cbd4efe2ef..10a7a4503b1b73ecbb8ab45faa52944080e3b53f 100644 (file)
@@ -13,7 +13,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- @version $Id: messages.inc 5022 2011-08-04 09:01:36Z alec $
+ @version $Id: messages.inc 5569 2011-12-07 14:47:32Z thomasb $
 
 */
 
 
 */
 
@@ -24,7 +24,7 @@ $messages['sessionerror'] = 'Your session is invalid or expired.';
 $messages['imaperror'] = 'Connection to IMAP server failed.';
 $messages['servererror'] = 'Server Error!';
 $messages['servererrormsg'] = 'Server Error: $msg';
 $messages['imaperror'] = 'Connection to IMAP server failed.';
 $messages['servererror'] = 'Server Error!';
 $messages['servererrormsg'] = 'Server Error: $msg';
-$messages['databaserror'] = 'Database Error!';
+$messages['dberror'] = 'Database Error!';
 $messages['errorreadonly'] = 'Unable to perform operation. Folder is read-only.';
 $messages['errornoperm'] = 'Unable to perform operation. Permission denied.';
 $messages['invalidrequest'] = 'Invalid request! No data was saved.';
 $messages['errorreadonly'] = 'Unable to perform operation. Folder is read-only.';
 $messages['errornoperm'] = 'Unable to perform operation. Permission denied.';
 $messages['invalidrequest'] = 'Invalid request! No data was saved.';
@@ -48,6 +48,7 @@ $messages['blockedimages'] = 'To protect your privacy, remote images are blocked
 $messages['encryptedmessage'] = 'This is an encrypted message and can not be displayed. Sorry!';
 $messages['nocontactsfound'] = 'No contacts found.';
 $messages['contactnotfound'] = 'The requested contact was not found.';
 $messages['encryptedmessage'] = 'This is an encrypted message and can not be displayed. Sorry!';
 $messages['nocontactsfound'] = 'No contacts found.';
 $messages['contactnotfound'] = 'The requested contact was not found.';
+$messages['contactsearchonly'] = 'Enter some search terms to find contacts';
 $messages['sendingfailed'] = 'Failed to send message.';
 $messages['senttooquickly'] = 'Please wait $sec sec(s). before sending this message.';
 $messages['errorsavingsent'] = 'An error occured while saving sent message.';
 $messages['sendingfailed'] = 'Failed to send message.';
 $messages['senttooquickly'] = 'Please wait $sec sec(s). before sending this message.';
 $messages['errorsavingsent'] = 'An error occured while saving sent message.';
@@ -61,6 +62,7 @@ $messages['deletegroupconfirm']  = 'Do you really want to delete selected group?
 $messages['deletemessagesconfirm'] = 'Do you really want to delete selected message(s)?';
 $messages['deletefolderconfirm']  = 'Do you really want to delete this folder?';
 $messages['purgefolderconfirm']  = 'Do you really want to delete all messages in this folder?';
 $messages['deletemessagesconfirm'] = 'Do you really want to delete selected message(s)?';
 $messages['deletefolderconfirm']  = 'Do you really want to delete this folder?';
 $messages['purgefolderconfirm']  = 'Do you really want to delete all messages in this folder?';
+$messages['contactdeleting'] = 'Deleting contact(s)...';
 $messages['groupdeleting'] = 'Deleting group...';
 $messages['folderdeleting'] = 'Deleting folder...';
 $messages['foldermoving'] = 'Moving folder...';
 $messages['groupdeleting'] = 'Deleting group...';
 $messages['folderdeleting'] = 'Deleting folder...';
 $messages['foldermoving'] = 'Moving folder...';
@@ -76,10 +78,10 @@ $messages['nosubjectwarning']  = 'The "Subject" field is empty. Would you like t
 $messages['nobodywarning'] = 'Send this message without text?';
 $messages['notsentwarning'] = 'Message has not been sent. Do you want to discard your message?';
 $messages['noldapserver'] = 'Please select an ldap server to search.';
 $messages['nobodywarning'] = 'Send this message without text?';
 $messages['notsentwarning'] = 'Message has not been sent. Do you want to discard your message?';
 $messages['noldapserver'] = 'Please select an ldap server to search.';
-$messages['nocontactsreturned'] = 'No contacts were found.';
 $messages['nosearchname'] = 'Please enter a contact name or email address.';
 $messages['notuploadedwarning'] = 'Not all attachments have been uploaded yet. Please wait or cancel the upload.';
 $messages['searchsuccessful'] = '$nr messages found.';
 $messages['nosearchname'] = 'Please enter a contact name or email address.';
 $messages['notuploadedwarning'] = 'Not all attachments have been uploaded yet. Please wait or cancel the upload.';
 $messages['searchsuccessful'] = '$nr messages found.';
+$messages['contactsearchsuccessful'] = '$nr contacts found.';
 $messages['searchnomatch'] = 'Search returned no matches.';
 $messages['searching'] = 'Searching...';
 $messages['checking'] = 'Checking...';
 $messages['searchnomatch'] = 'Search returned no matches.';
 $messages['searching'] = 'Searching...';
 $messages['checking'] = 'Checking...';
@@ -126,7 +128,6 @@ $messages['smtpautherror'] = 'SMTP Error ($code): Authentication failed.';
 $messages['smtpfromerror'] = 'SMTP Error ($code): Failed to set sender "$from" ($msg).';
 $messages['smtptoerror'] = 'SMTP Error ($code): Failed to add recipient "$to" ($msg).';
 $messages['smtprecipientserror'] = 'SMTP Error: Unable to parse recipients list.';
 $messages['smtpfromerror'] = 'SMTP Error ($code): Failed to set sender "$from" ($msg).';
 $messages['smtptoerror'] = 'SMTP Error ($code): Failed to add recipient "$to" ($msg).';
 $messages['smtprecipientserror'] = 'SMTP Error: Unable to parse recipients list.';
-$messages['smtpdsnerror'] = 'SMTP Error: No support for Delivery Status Notifications.';
 $messages['smtperror'] = 'SMTP Error: $msg';
 $messages['emailformaterror'] = 'Invalid e-mail address: $email';
 $messages['toomanyrecipients'] = 'Too many recipients. Reduce the number of recipients to $max.';
 $messages['smtperror'] = 'SMTP Error: $msg';
 $messages['emailformaterror'] = 'Invalid e-mail address: $email';
 $messages['toomanyrecipients'] = 'Too many recipients. Reduce the number of recipients to $max.';
@@ -139,11 +140,16 @@ $messages['contactrestored'] = 'Contact(s) restored successfully.';
 $messages['groupdeleted'] = 'Group deleted successfully.';
 $messages['grouprenamed'] = 'Group renamed successfully.';
 $messages['groupcreated'] = 'Group created successfully.';
 $messages['groupdeleted'] = 'Group deleted successfully.';
 $messages['grouprenamed'] = 'Group renamed successfully.';
 $messages['groupcreated'] = 'Group created successfully.';
+$messages['savedsearchdeleted'] = 'Saved search deleted successfully.';
+$messages['savedsearchdeleteerror'] = 'Could not delete saved search.';
+$messages['savedsearchcreated'] = 'Saved search created successfully.';
+$messages['savedsearchcreateerror'] = 'Could not create saved search.';
 $messages['messagedeleted'] = 'Message(s) deleted successfully.';
 $messages['messagemoved'] = 'Message(s) moved successfully.';
 $messages['messagecopied'] = 'Message(s) copied successfully.';
 $messages['messagemarked'] = 'Message(s) marked successfully.';
 $messages['autocompletechars'] = 'Enter at least $min characters for autocompletion.';
 $messages['messagedeleted'] = 'Message(s) deleted successfully.';
 $messages['messagemoved'] = 'Message(s) moved successfully.';
 $messages['messagecopied'] = 'Message(s) copied successfully.';
 $messages['messagemarked'] = 'Message(s) marked successfully.';
 $messages['autocompletechars'] = 'Enter at least $min characters for autocompletion.';
+$messages['autocompletemore'] = 'More matching entries found. Please type more characters.';
 $messages['namecannotbeempty'] = 'Name cannot be empty.';
 $messages['nametoolong'] = 'Name is too long.';
 $messages['folderupdated'] = 'Folder updated successfully.';
 $messages['namecannotbeempty'] = 'Name cannot be empty.';
 $messages['nametoolong'] = 'Name is too long.';
 $messages['folderupdated'] = 'Folder updated successfully.';
@@ -151,5 +157,6 @@ $messages['foldercreated'] = 'Folder created successfully.';
 $messages['invalidimageformat'] = 'Not a valid image format.';
 $messages['mispellingsfound'] = 'Spelling errors detected in the message.';
 $messages['parentnotwritable'] = 'Unable to create/move folder into selected parent folder. No access rights.';
 $messages['invalidimageformat'] = 'Not a valid image format.';
 $messages['mispellingsfound'] = 'Spelling errors detected in the message.';
 $messages['parentnotwritable'] = 'Unable to create/move folder into selected parent folder. No access rights.';
+$messages['messagetoobig'] = 'The message part is too big to process it.';
 
 ?>
 
 ?>
index fa0d824528a094870a50411b56aac864fcd45812..2e1a49da1ec7c69f358ef8f91fc004f4c50dbf88 100644 (file)
@@ -16,7 +16,7 @@
 |         José M. Ciordia <ciordia@gmail.com>                           |
 +-----------------------------------------------------------------------+
 
 |         José M. Ciordia <ciordia@gmail.com>                           |
 +-----------------------------------------------------------------------+
 
-@version $Id: labels.inc 4671 2011-04-20 08:47:44Z thomasb $
+@version $Id: labels.inc 5290 2011-09-28 17:09:50Z thomasb $
 
 */
 
 
 */
 
@@ -103,6 +103,8 @@ $labels['replytomessage'] = 'Responder mensaje';
 $labels['replytoallmessage'] = 'Responder al emisor y a todos los destinatarios';
 $labels['replyall'] = 'Responder a todos';
 $labels['replylist'] = 'Responder a la lista';
 $labels['replytoallmessage'] = 'Responder al emisor y a todos los destinatarios';
 $labels['replyall'] = 'Responder a todos';
 $labels['replylist'] = 'Responder a la lista';
+$labels['forwardinline'] = 'Reenviar directamente';
+$labels['forwardattachment'] = 'Reenviar como adjunto';
 $labels['forwardmessage'] = 'Reenviar mensaje';
 $labels['deletemessage'] = 'Eliminar mensaje';
 $labels['movemessagetotrash'] = 'Mover mensaje a la papelera';
 $labels['forwardmessage'] = 'Reenviar mensaje';
 $labels['deletemessage'] = 'Eliminar mensaje';
 $labels['movemessagetotrash'] = 'Mover mensaje a la papelera';
@@ -118,7 +120,7 @@ $labels['markread'] = 'Como leído';
 $labels['markunread'] = 'Como no leído';
 $labels['markflagged'] = 'Como marcado';
 $labels['markunflagged'] = 'Como no marcado';
 $labels['markunread'] = 'Como no leído';
 $labels['markflagged'] = 'Como marcado';
 $labels['markunflagged'] = 'Como no marcado';
-$labels['messageactions'] = 'Más acciones...';
+$labels['moreactions'] = 'Más acciones…';
 $labels['select'] = 'Elija';
 $labels['all'] = 'Todos';
 $labels['none'] = 'Ninguno';
 $labels['select'] = 'Elija';
 $labels['all'] = 'Todos';
 $labels['none'] = 'Ninguno';
@@ -171,12 +173,15 @@ $labels['charset'] = 'Codificación';
 $labels['editortype'] = 'Tipo de editor';
 $labels['returnreceipt'] = 'Acuse de recibo';
 $labels['dsn'] = 'Entrega de notificaciones de estado';
 $labels['editortype'] = 'Tipo de editor';
 $labels['returnreceipt'] = 'Acuse de recibo';
 $labels['dsn'] = 'Entrega de notificaciones de estado';
+$labels['mailreplyintro'] = 'El $date, $sender escribió:';
+$labels['originalmessage'] = 'Mensaje original';
 $labels['editidents'] = 'Editar identidades';
 $labels['checkspelling'] = 'Revisar ortografía';
 $labels['resumeediting'] = 'Continuar edición';
 $labels['revertto'] = 'Revertir a';
 $labels['attachments'] = 'Adjuntos';
 $labels['upload'] = 'Subir';
 $labels['editidents'] = 'Editar identidades';
 $labels['checkspelling'] = 'Revisar ortografía';
 $labels['resumeediting'] = 'Continuar edición';
 $labels['revertto'] = 'Revertir a';
 $labels['attachments'] = 'Adjuntos';
 $labels['upload'] = 'Subir';
+$labels['uploadprogress'] = '$percent ($current de $total)';
 $labels['close'] = 'Cerrar';
 $labels['messageoptions'] = 'Opciones de mensaje...';
 $labels['low'] = 'Bajo';
 $labels['close'] = 'Cerrar';
 $labels['messageoptions'] = 'Opciones de mensaje...';
 $labels['low'] = 'Bajo';
@@ -229,6 +234,10 @@ $labels['female'] = 'Mujer';
 $labels['manager'] = 'Director';
 $labels['assistant'] = 'Auxiliar';
 $labels['spouse'] = 'Cónyuge';
 $labels['manager'] = 'Director';
 $labels['assistant'] = 'Auxiliar';
 $labels['spouse'] = 'Cónyuge';
+$labels['allfields'] = 'Todos los campos';
+$labels['search'] = 'Buscar';
+$labels['advsearch'] = 'Búsqueda avanzada';
+$labels['other'] = 'Otro';
 $labels['typehome'] = 'Casa';
 $labels['typework'] = 'Trabajo';
 $labels['typeother'] = 'Otro';
 $labels['typehome'] = 'Casa';
 $labels['typework'] = 'Trabajo';
 $labels['typeother'] = 'Otro';
@@ -240,6 +249,9 @@ $labels['typecar'] = 'Coche';
 $labels['typepager'] = 'Busca';
 $labels['typevideo'] = 'Vídeo';
 $labels['typeassistant'] = 'Auxiliar';
 $labels['typepager'] = 'Busca';
 $labels['typevideo'] = 'Vídeo';
 $labels['typeassistant'] = 'Auxiliar';
+$labels['typehomepage'] = 'Inicio';
+$labels['typeblog'] = 'Blog';
+$labels['typeprofile'] = 'Perfil';
 $labels['addfield'] = 'Añadir campo...';
 $labels['addcontact'] = 'Añadir nuevo contacto';
 $labels['editcontact'] = 'Editar contacto';
 $labels['addfield'] = 'Añadir campo...';
 $labels['addcontact'] = 'Añadir nuevo contacto';
 $labels['editcontact'] = 'Editar contacto';
@@ -261,7 +273,8 @@ $labels['print'] = 'Imprimir';
 $labels['export'] = 'Exportar';
 $labels['exportvcards'] = 'Exportar contactos en formato vCard';
 $labels['newcontactgroup'] = 'Crear un nuevo grupo de contactos';
 $labels['export'] = 'Exportar';
 $labels['exportvcards'] = 'Exportar contactos en formato vCard';
 $labels['newcontactgroup'] = 'Crear un nuevo grupo de contactos';
-$labels['groupactions'] = 'Acciones para grupos de contactos...';
+$labels['grouprename'] = 'Renombrar grupo';
+$labels['groupdelete'] = 'Borrar grupo';
 $labels['previouspage'] = 'Mostrar grupo anterior';
 $labels['firstpage'] = 'Mostrar primer grupo';
 $labels['nextpage'] = 'Mostrar grupo siguiente';
 $labels['previouspage'] = 'Mostrar grupo anterior';
 $labels['firstpage'] = 'Mostrar primer grupo';
 $labels['nextpage'] = 'Mostrar grupo siguiente';
@@ -269,9 +282,12 @@ $labels['lastpage'] = 'Mostrar último grupo';
 $labels['group'] = 'Grupo';
 $labels['groups'] = 'Grupos';
 $labels['personaladrbook'] = 'Direcciones personales';
 $labels['group'] = 'Grupo';
 $labels['groups'] = 'Grupos';
 $labels['personaladrbook'] = 'Direcciones personales';
+$labels['searchsave'] = 'Guardar búsqueda';
+$labels['searchdelete'] = 'Borrar búsqueda';
 $labels['import'] = 'Importar';
 $labels['importcontacts'] = 'Importar contactos';
 $labels['importfromfile'] = 'Importar desde archivo:';
 $labels['import'] = 'Importar';
 $labels['importcontacts'] = 'Importar contactos';
 $labels['importfromfile'] = 'Importar desde archivo:';
+$labels['importtarget'] = 'Añadir un nuevo contacto a la los contactos:';
 $labels['importreplace'] = 'Reemplazar toda la lista de contactos';
 $labels['importtext'] = 'Puede importar contactos desde una lista existente.<br/>Actualmente sólo soportamos el formato <a href="http://es.wikipedia.org/wiki/VCard">vCard</a>.';
 $labels['done'] = 'Hecho';
 $labels['importreplace'] = 'Reemplazar toda la lista de contactos';
 $labels['importtext'] = 'Puede importar contactos desde una lista existente.<br/>Actualmente sólo soportamos el formato <a href="http://es.wikipedia.org/wiki/VCard">vCard</a>.';
 $labels['done'] = 'Hecho';
@@ -287,6 +303,8 @@ $labels['edititem'] = 'Editar';
 $labels['preferhtml'] = 'Prefiero HTML';
 $labels['defaultcharset'] = 'Juego de caracteres por defecto';
 $labels['htmlmessage'] = 'Mensaje HTML';
 $labels['preferhtml'] = 'Prefiero HTML';
 $labels['defaultcharset'] = 'Juego de caracteres por defecto';
 $labels['htmlmessage'] = 'Mensaje HTML';
+$labels['dateformat'] = 'Formato de fecha';
+$labels['timeformat'] = 'Formato de hora';
 $labels['prettydate'] = 'Fecha detallada';
 $labels['setdefault'] = 'Seleccionar opción por defecto';
 $labels['autodetect'] = 'Automático';
 $labels['prettydate'] = 'Fecha detallada';
 $labels['setdefault'] = 'Seleccionar opción por defecto';
 $labels['autodetect'] = 'Automático';
@@ -357,6 +375,13 @@ $labels['afternseconds'] = 'después de $n segundos';
 $labels['reqmdn'] = 'Solicitar siempre un acuse de recibo';
 $labels['reqdsn'] = 'Solicitar siempre la entrega de notificaciones de estado';
 $labels['replysamefolder'] = 'Coloque las respuestas en la bandeja del mensaje que se responde';
 $labels['reqmdn'] = 'Solicitar siempre un acuse de recibo';
 $labels['reqdsn'] = 'Solicitar siempre la entrega de notificaciones de estado';
 $labels['replysamefolder'] = 'Coloque las respuestas en la bandeja del mensaje que se responde';
+$labels['defaultaddressbook'] = 'Añadir nuevos contactos a la lista de contactos seleccionada';
+$labels['spellcheckbeforesend'] = 'Comprobar ortografía antes de enviar un mensaje';
+$labels['spellcheckoptions'] = 'Opciones de ortografía';
+$labels['spellcheckignoresyms'] = 'Ignorar palabras con símbolos';
+$labels['spellcheckignorenums'] = 'Ignorar palabras con números';
+$labels['spellcheckignorecaps'] = 'Ignorar palabras con todo mayúsculas';
+$labels['addtodict'] = 'Añadir al diccionario';
 $labels['folder'] = 'Bandeja';
 $labels['folders'] = 'Bandejas';
 $labels['foldername'] = 'Nombre de bandeja';
 $labels['folder'] = 'Bandeja';
 $labels['folders'] = 'Bandejas';
 $labels['foldername'] = 'Nombre de bandeja';
@@ -380,6 +405,7 @@ $labels['sharedfolder'] = 'Bandeja pública';
 $labels['sortby'] = 'Ordenar por';
 $labels['sortasc'] = 'Orden ascendente';
 $labels['sortdesc'] = 'Orden descendente';
 $labels['sortby'] = 'Ordenar por';
 $labels['sortasc'] = 'Orden ascendente';
 $labels['sortdesc'] = 'Orden descendente';
+$labels['undo'] = 'Deshacer';
 $labels['B'] = 'B';
 $labels['KB'] = 'KB';
 $labels['MB'] = 'MB';
 $labels['B'] = 'B';
 $labels['KB'] = 'KB';
 $labels['MB'] = 'MB';
index c23f3faa5fe1a5f5621a04f79ba6c31415086cd4..4ed0e5debb5ca1e8e90288cdc4a2f8187ec0849a 100644 (file)
@@ -17,7 +17,7 @@
 |          José M. Ciordia <ciordia@gmail.com>                           |
 +------------------------------------------------------------------------+
 
 |          José M. Ciordia <ciordia@gmail.com>                           |
 +------------------------------------------------------------------------+
 
-@version $Id: messages.inc 4671 2011-04-20 08:47:44Z thomasb $
+@version $Id: messages.inc 5290 2011-09-28 17:09:50Z thomasb $
 */
 
 $messages = array();
 */
 
 $messages = array();
@@ -27,6 +27,7 @@ $messages['sessionerror'] = 'Su sesión no es válida o ha expirado';
 $messages['imaperror'] = 'Error de conexión con el servidor IMAP';
 $messages['servererror'] = '¡Error del servidor!';
 $messages['servererrormsg'] = 'Error de servidor: $msg';
 $messages['imaperror'] = 'Error de conexión con el servidor IMAP';
 $messages['servererror'] = '¡Error del servidor!';
 $messages['servererrormsg'] = 'Error de servidor: $msg';
+$messages['dberror'] = '¡Error de base de datos!';
 $messages['errorreadonly'] = 'No se ha podido hacer. La bandeja es sólo de lectura';
 $messages['errornoperm'] = 'No se ha podido hacer. Permiso denegado';
 $messages['invalidrequest'] = '¡Petición no válida! No se han guardado los datos.';
 $messages['errorreadonly'] = 'No se ha podido hacer. La bandeja es sólo de lectura';
 $messages['errornoperm'] = 'No se ha podido hacer. Permiso denegado';
 $messages['invalidrequest'] = '¡Petición no válida! No se han guardado los datos.';
@@ -35,6 +36,7 @@ $messages['loggedout'] = 'Ha cerrado bien la sesión. ¡Hasta pronto!';
 $messages['mailboxempty'] = 'La casilla está vacía';
 $messages['loading'] = 'Cargando...';
 $messages['uploading'] = 'Subiendo fichero...';
 $messages['mailboxempty'] = 'La casilla está vacía';
 $messages['loading'] = 'Cargando...';
 $messages['uploading'] = 'Subiendo fichero...';
+$messages['uploadingmany'] = 'Subiendo archivos…';
 $messages['loadingdata'] = 'Cargando datos...';
 $messages['checkingmail'] = 'Verificando si hay nuevos mensajes...';
 $messages['sendingmessage'] = 'Enviando mensaje...';
 $messages['loadingdata'] = 'Cargando datos...';
 $messages['checkingmail'] = 'Verificando si hay nuevos mensajes...';
 $messages['sendingmessage'] = 'Enviando mensaje...';
@@ -44,6 +46,7 @@ $messages['messagesaved'] = 'Mensaje guardado en borradores';
 $messages['successfullysaved'] = 'Guardado correctamente';
 $messages['addedsuccessfully'] = 'Contacto añadido correctamente a la libreta de direcciones';
 $messages['contactexists'] = 'Ya existe un contacto con esta dirección de correo';
 $messages['successfullysaved'] = 'Guardado correctamente';
 $messages['addedsuccessfully'] = 'Contacto añadido correctamente a la libreta de direcciones';
 $messages['contactexists'] = 'Ya existe un contacto con esta dirección de correo';
+$messages['contactnameexists'] = 'Ya existe un contacto con el mismo nombre.';
 $messages['blockedimages'] = 'Para proteger su privacidad, las imágenes externas han sido bloqueadas en este mensaje';
 $messages['encryptedmessage'] = 'Este es un mensaje cifrado y no puede ser mostrado. ¡Lo siento!';
 $messages['nocontactsfound'] = 'No hay contactos';
 $messages['blockedimages'] = 'Para proteger su privacidad, las imágenes externas han sido bloqueadas en este mensaje';
 $messages['encryptedmessage'] = 'Este es un mensaje cifrado y no puede ser mostrado. ¡Lo siento!';
 $messages['nocontactsfound'] = 'No hay contactos';
@@ -57,9 +60,11 @@ $messages['errorcopying'] = 'No se ha podido copiar el/los mensaje(s)';
 $messages['errordeleting'] = 'No se ha podido eliminar el mensaje';
 $messages['errormarking'] = 'No se ha podido marcar el mensaje';
 $messages['deletecontactconfirm'] = '¿Realmente quiere eliminar los contactos seleccionados?';
 $messages['errordeleting'] = 'No se ha podido eliminar el mensaje';
 $messages['errormarking'] = 'No se ha podido marcar el mensaje';
 $messages['deletecontactconfirm'] = '¿Realmente quiere eliminar los contactos seleccionados?';
+$messages['deletegroupconfirm'] = '¿De verdad quiere borrar el grupo seleccionado?';
 $messages['deletemessagesconfirm'] = '¿Realmente quiere eliminar los mensajes seleccionados?';
 $messages['deletefolderconfirm'] = '¿Realmente quiere eliminar esta bandeja?';
 $messages['purgefolderconfirm'] = '¿Realmente quiere eliminar todos los mensajes de esta bandeja?';
 $messages['deletemessagesconfirm'] = '¿Realmente quiere eliminar los mensajes seleccionados?';
 $messages['deletefolderconfirm'] = '¿Realmente quiere eliminar esta bandeja?';
 $messages['purgefolderconfirm'] = '¿Realmente quiere eliminar todos los mensajes de esta bandeja?';
+$messages['groupdeleting'] = 'Borrando grupo…';
 $messages['folderdeleting'] = 'Borrando bandeja...';
 $messages['foldermoving'] = 'Moviendo bandeja...';
 $messages['foldersubscribing'] = 'Suscribiendo bandeja...';
 $messages['folderdeleting'] = 'Borrando bandeja...';
 $messages['foldermoving'] = 'Moviendo bandeja...';
 $messages['foldersubscribing'] = 'Suscribiendo bandeja...';
@@ -74,10 +79,10 @@ $messages['nosubjectwarning'] = 'El campo "Asunto" está vacío. ¿Desea complet
 $messages['nobodywarning'] = '¿Quiere enviar este mensaje sin texto?';
 $messages['notsentwarning'] = 'El mensaje no ha sido enviado. ¿Desea descartar su mensaje?';
 $messages['noldapserver'] = 'Por favor, seleccione un servidor LDAP para buscar';
 $messages['nobodywarning'] = '¿Quiere enviar este mensaje sin texto?';
 $messages['notsentwarning'] = 'El mensaje no ha sido enviado. ¿Desea descartar su mensaje?';
 $messages['noldapserver'] = 'Por favor, seleccione un servidor LDAP para buscar';
-$messages['nocontactsreturned'] = 'No se han encontrado contactos';
 $messages['nosearchname'] = 'Por favor, introduzca un nombre o la dirección de e-mail';
 $messages['notuploadedwarning'] = 'No se han subido aún todos los adjuntos. Por favor espere o cancele la subida.';
 $messages['searchsuccessful'] = 'Se encontraron $nr mensajes';
 $messages['nosearchname'] = 'Por favor, introduzca un nombre o la dirección de e-mail';
 $messages['notuploadedwarning'] = 'No se han subido aún todos los adjuntos. Por favor espere o cancele la subida.';
 $messages['searchsuccessful'] = 'Se encontraron $nr mensajes';
+$messages['contactsearchsuccessful'] = 'Encontrados $nr contactos.';
 $messages['searchnomatch'] = 'No se obtuvieron resultados';
 $messages['searching'] = 'Buscando...';
 $messages['checking'] = 'Revisando...';
 $messages['searchnomatch'] = 'No se obtuvieron resultados';
 $messages['searching'] = 'Buscando...';
 $messages['checking'] = 'Revisando...';
@@ -98,8 +103,11 @@ $messages['sourceisreadonly'] = 'Esta dirección es de sólo lectura';
 $messages['errorsavingcontact'] = 'No se pudo guardar la dirección de contacto';
 $messages['movingmessage'] = 'Moviendo mensaje...';
 $messages['copyingmessage'] = 'Copiando mensaje...';
 $messages['errorsavingcontact'] = 'No se pudo guardar la dirección de contacto';
 $messages['movingmessage'] = 'Moviendo mensaje...';
 $messages['copyingmessage'] = 'Copiando mensaje...';
+$messages['copyingcontact'] = 'Copiando contacto(s)…';
 $messages['deletingmessage'] = 'Eliminando mensaje(s)...';
 $messages['markingmessage'] = 'Marcando mensaje(s)...';
 $messages['deletingmessage'] = 'Eliminando mensaje(s)...';
 $messages['markingmessage'] = 'Marcando mensaje(s)...';
+$messages['addingmember'] = 'Añadiendo contacto(s) al grupo…';
+$messages['removingmember'] = 'Quitando contacto(s) del grupo…';
 $messages['receiptsent'] = 'La notificación de lectura se ha enviado correctamente.';
 $messages['errorsendingreceipt'] = 'No se ha podido enviar la notificación de lectura.';
 $messages['nodeletelastidentity'] = 'No se puede borrar esta identidad puesto que es la última.';
 $messages['receiptsent'] = 'La notificación de lectura se ha enviado correctamente.';
 $messages['errorsendingreceipt'] = 'No se ha podido enviar la notificación de lectura.';
 $messages['nodeletelastidentity'] = 'No se puede borrar esta identidad puesto que es la última.';
@@ -129,9 +137,15 @@ $messages['maxgroupmembersreached'] = 'El número de miembros del grupo excede e
 $messages['internalerror'] = 'Ocurrió un error interno. Por favor, inténtalo de nuevo';
 $messages['contactdelerror'] = 'No se ha podido eliminar el contacto(s)';
 $messages['contactdeleted'] = 'Contacto(s) eliminado(s) correctamente';
 $messages['internalerror'] = 'Ocurrió un error interno. Por favor, inténtalo de nuevo';
 $messages['contactdelerror'] = 'No se ha podido eliminar el contacto(s)';
 $messages['contactdeleted'] = 'Contacto(s) eliminado(s) correctamente';
+$messages['contactrestoreerror'] = 'No se han podido restaurar los contactos borrados.';
+$messages['contactrestored'] = 'Los contactos se han restaurado con éxito.';
 $messages['groupdeleted'] = 'Grupo eliminado correctamente';
 $messages['grouprenamed'] = 'Grupo renombrado correctamente';
 $messages['groupcreated'] = 'Grupo creado correctamente';
 $messages['groupdeleted'] = 'Grupo eliminado correctamente';
 $messages['grouprenamed'] = 'Grupo renombrado correctamente';
 $messages['groupcreated'] = 'Grupo creado correctamente';
+$messages['savedsearchdeleted'] = 'La búsqueda guardada se ha borrado con éxito.';
+$messages['savedsearchdeleteerror'] = 'No se ha podido borrar la búsqueda guardada.';
+$messages['savedsearchcreated'] = 'Se ha guardado correctamente la búsqueda.';
+$messages['savedsearchcreateerror'] = 'No se ha podido guardar la búsqueda.';
 $messages['messagedeleted'] = 'Mensaje(s) eliminado(s) correctamente';
 $messages['messagemoved'] = 'Mensaje(s) movido(s) correctamente';
 $messages['messagecopied'] = 'Mensaje(s) copiado(s) correctamente';
 $messages['messagedeleted'] = 'Mensaje(s) eliminado(s) correctamente';
 $messages['messagemoved'] = 'Mensaje(s) movido(s) correctamente';
 $messages['messagecopied'] = 'Mensaje(s) copiado(s) correctamente';
@@ -142,5 +156,7 @@ $messages['nametoolong'] = 'El nombre es demasiado largo';
 $messages['folderupdated'] = 'Bandeja actualizada correctamente';
 $messages['foldercreated'] = 'Bandeja creada correctamente';
 $messages['invalidimageformat'] = 'No es un formato de imagen válido';
 $messages['folderupdated'] = 'Bandeja actualizada correctamente';
 $messages['foldercreated'] = 'Bandeja creada correctamente';
 $messages['invalidimageformat'] = 'No es un formato de imagen válido';
+$messages['mispellingsfound'] = 'Se han detectado errores ortográficos en el mensaje.';
+$messages['parentnotwritable'] = 'No se puede crear/mover la carpeta a la carpeta superior elegida. No tiene permisos de acceso.';
 
 ?>
 
 ?>
index 70cc69f776f6632d99cca3931474ad942ac3128d..40e0082cdf07eeb3cca85ddd32818d0e53b2c700 100644 (file)
@@ -15,7 +15,7 @@
 |         Elan Ruusamäe <glen@delfi.ee>                                 |
 +-----------------------------------------------------------------------+
 
 |         Elan Ruusamäe <glen@delfi.ee>                                 |
 +-----------------------------------------------------------------------+
 
-@version $Id: messages.inc 5067 2011-08-14 18:47:58Z thomasb $
+@version $Id: messages.inc 5139 2011-08-28 09:47:15Z alec $
 
 */
 
 
 */
 
@@ -26,7 +26,7 @@ $messages['sessionerror'] = 'Sinu seanss on aegunud või vigane';
 $messages['imaperror'] = 'Ei õnnestunud IMAP serveriga ühendust luua';
 $messages['servererror'] = 'Serveri tõrge!';
 $messages['servererrormsg'] = 'Serveri tõrge: $msg';
 $messages['imaperror'] = 'Ei õnnestunud IMAP serveriga ühendust luua';
 $messages['servererror'] = 'Serveri tõrge!';
 $messages['servererrormsg'] = 'Serveri tõrge: $msg';
-$messages['databaserror'] = 'Andmebaasi tõrge!';
+$messages['dberror'] = 'Andmebaasi tõrge!';
 $messages['errorreadonly'] = 'Operatsioon nurjus. Kaustale on vaid lugemisõigus';
 $messages['errornoperm'] = 'Operatsioon nurjus. Ligipääsu õigused puuduvad';
 $messages['invalidrequest'] = 'Lubamatu päring! Andmeid ei salvestatud.';
 $messages['errorreadonly'] = 'Operatsioon nurjus. Kaustale on vaid lugemisõigus';
 $messages['errornoperm'] = 'Operatsioon nurjus. Ligipääsu õigused puuduvad';
 $messages['invalidrequest'] = 'Lubamatu päring! Andmeid ei salvestatud.';
index b56a6c90351c261507b6da1e820c3f04aaa17204..205dcaaf14568d8dae67119dbe573a2a9c267abe 100644 (file)
@@ -6,7 +6,7 @@
 | language/fr_FR/labels.inc                                             |
 |                                                                       |
 | Language file of the Roundcube Webmail client                         |
 | language/fr_FR/labels.inc                                             |
 |                                                                       |
 | Language file of the Roundcube Webmail client                         |
-| Copyright (C) 2005-2010, The Roundcube Dev Team                       |
+| Copyright (C) 2005-2011, The Roundcube Dev Team                       |
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 +-----------------------------------------------------------------------+
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 +-----------------------------------------------------------------------+
@@ -15,7 +15,7 @@
 |         Maximilien Cuony <theglu@theglu.org>                          |
 +-----------------------------------------------------------------------+
 
 |         Maximilien Cuony <theglu@theglu.org>                          |
 +-----------------------------------------------------------------------+
 
-@version $Id: labels.inc 5291 2011-09-28 17:10:45Z thomasb $
+@version $Id: labels.inc 5569 2011-12-07 14:47:32Z thomasb $
 
 */
 
 
 */
 
@@ -119,7 +119,7 @@ $labels['markread'] = 'Comme lus';
 $labels['markunread'] = 'Comme non lus';
 $labels['markflagged'] = 'Comme suivi';
 $labels['markunflagged'] = 'Comme non-suivi';
 $labels['markunread'] = 'Comme non lus';
 $labels['markflagged'] = 'Comme suivi';
 $labels['markunflagged'] = 'Comme non-suivi';
-$labels['messageactions'] = 'Actions supplémentaires...';
+$labels['moreactions'] = 'Plus d\'actions...';
 $labels['select'] = 'Sélectionner';
 $labels['all'] = 'Tous';
 $labels['none'] = 'Aucun';
 $labels['select'] = 'Sélectionner';
 $labels['all'] = 'Tous';
 $labels['none'] = 'Aucun';
@@ -191,6 +191,7 @@ $labels['highest'] = 'La plus élevée';
 $labels['nosubject'] = '(pas de sujet)';
 $labels['showimages'] = 'Afficher les images';
 $labels['alwaysshow'] = 'Toujours afficher les images de $sender';
 $labels['nosubject'] = '(pas de sujet)';
 $labels['showimages'] = 'Afficher les images';
 $labels['alwaysshow'] = 'Toujours afficher les images de $sender';
+$labels['isdraft'] = 'Ceci est un brouillon.';
 $labels['htmltoggle'] = 'HTML';
 $labels['plaintoggle'] = 'texte brut';
 $labels['savesentmessagein'] = 'Enregistrer le message envoyé dans';
 $labels['htmltoggle'] = 'HTML';
 $labels['plaintoggle'] = 'texte brut';
 $labels['savesentmessagein'] = 'Enregistrer le message envoyé dans';
@@ -226,7 +227,7 @@ $labels['country'] = 'Pays';
 $labels['birthday'] = 'Date de naissance';
 $labels['anniversary'] = 'Anniversaire';
 $labels['website'] = 'Site Web';
 $labels['birthday'] = 'Date de naissance';
 $labels['anniversary'] = 'Anniversaire';
 $labels['website'] = 'Site Web';
-$labels['instantmessenger'] = 'Messagerie instantannée';
+$labels['instantmessenger'] = 'Messagerie instantanée';
 $labels['notes'] = 'Notes';
 $labels['male'] = 'Homme';
 $labels['female'] = 'Femme';
 $labels['notes'] = 'Notes';
 $labels['male'] = 'Homme';
 $labels['female'] = 'Femme';
@@ -234,7 +235,7 @@ $labels['manager'] = 'Manager';
 $labels['assistant'] = 'Assistant';
 $labels['spouse'] = 'Épouse';
 $labels['allfields'] = 'Tous les champs';
 $labels['assistant'] = 'Assistant';
 $labels['spouse'] = 'Épouse';
 $labels['allfields'] = 'Tous les champs';
-$labels['search'] = 'Rechecher';
+$labels['search'] = 'Rechercher';
 $labels['advsearch'] = 'Recherche avancée';
 $labels['other'] = 'Autre';
 $labels['typehome'] = 'Domicile';
 $labels['advsearch'] = 'Recherche avancée';
 $labels['other'] = 'Autre';
 $labels['typehome'] = 'Domicile';
@@ -272,7 +273,6 @@ $labels['print'] = 'Imprimer';
 $labels['export'] = 'Exporter';
 $labels['exportvcards'] = 'Exporter les contacts au format vCard';
 $labels['newcontactgroup'] = 'Créer un nouveau groupe de contacts';
 $labels['export'] = 'Exporter';
 $labels['exportvcards'] = 'Exporter les contacts au format vCard';
 $labels['newcontactgroup'] = 'Créer un nouveau groupe de contacts';
-$labels['groupactions'] = 'Actions pour les groupes de contacts';
 $labels['grouprename'] = 'Renommer le groupe';
 $labels['groupdelete'] = 'Supprimer le groupe';
 $labels['previouspage'] = 'Montrer page précédente';
 $labels['grouprename'] = 'Renommer le groupe';
 $labels['groupdelete'] = 'Supprimer le groupe';
 $labels['previouspage'] = 'Montrer page précédente';
@@ -282,6 +282,8 @@ $labels['lastpage'] = 'Voir la dernière page';
 $labels['group'] = 'Groupe';
 $labels['groups'] = 'Groupes';
 $labels['personaladrbook'] = 'Adresses personnelles';
 $labels['group'] = 'Groupe';
 $labels['groups'] = 'Groupes';
 $labels['personaladrbook'] = 'Adresses personnelles';
+$labels['searchsave'] = 'Enregistrer la recherche';
+$labels['searchdelete'] = 'Supprimer la recherche';
 $labels['import'] = 'Importer';
 $labels['importcontacts'] = 'Importer les contacts';
 $labels['importfromfile'] = 'Importer depuis un fichier :';
 $labels['import'] = 'Importer';
 $labels['importcontacts'] = 'Importer les contacts';
 $labels['importfromfile'] = 'Importer depuis un fichier :';
@@ -290,6 +292,7 @@ $labels['importreplace'] = 'Remplacer le carnet d\'adresse entier';
 $labels['importtext'] = 'Vous pouvez envoyer des contacts depuis un carnet d\'adresse existant. Nous supportons actuellement l\'importation d\'adresses au format vCard.';
 $labels['done'] = 'Terminé';
 $labels['settingsfor'] = 'Paramètres pour';
 $labels['importtext'] = 'Vous pouvez envoyer des contacts depuis un carnet d\'adresse existant. Nous supportons actuellement l\'importation d\'adresses au format vCard.';
 $labels['done'] = 'Terminé';
 $labels['settingsfor'] = 'Paramètres pour';
+$labels['about'] = 'A propos';
 $labels['preferences'] = 'Préférences';
 $labels['userpreferences'] = 'Préférences utilisateur';
 $labels['editpreferences'] = 'Modifier les préférences utilisateur';
 $labels['preferences'] = 'Préférences';
 $labels['userpreferences'] = 'Préférences utilisateur';
 $labels['editpreferences'] = 'Modifier les préférences utilisateur';
@@ -301,6 +304,8 @@ $labels['edititem'] = 'Modifier l\'élément';
 $labels['preferhtml'] = 'Afficher en HTML';
 $labels['defaultcharset'] = 'Encodage par défaut';
 $labels['htmlmessage'] = 'Message en HTML';
 $labels['preferhtml'] = 'Afficher en HTML';
 $labels['defaultcharset'] = 'Encodage par défaut';
 $labels['htmlmessage'] = 'Message en HTML';
+$labels['dateformat'] = 'Format de la date';
+$labels['timeformat'] = 'Format de l\'heure';
 $labels['prettydate'] = 'Affichage court des dates';
 $labels['setdefault'] = 'Paramètres par défaut';
 $labels['autodetect'] = 'Automatique';
 $labels['prettydate'] = 'Affichage court des dates';
 $labels['setdefault'] = 'Paramètres par défaut';
 $labels['autodetect'] = 'Automatique';
@@ -372,7 +377,13 @@ $labels['reqmdn'] = 'Toujours demander un avis de réception';
 $labels['reqdsn'] = 'Toujours demander une notification d\'état de distribution';
 $labels['replysamefolder'] = 'Placer les réponses dans le dossier du message auquel il est répondu';
 $labels['defaultaddressbook'] = 'Ajouter de nouveaux contacts au carnet d’adresses sélectionné';
 $labels['reqdsn'] = 'Toujours demander une notification d\'état de distribution';
 $labels['replysamefolder'] = 'Placer les réponses dans le dossier du message auquel il est répondu';
 $labels['defaultaddressbook'] = 'Ajouter de nouveaux contacts au carnet d’adresses sélectionné';
+$labels['autocompletesingle'] = 'Ne pas tenir compte des adresses emails alternatives dans l\'autoremplissage';
 $labels['spellcheckbeforesend'] = 'Vérifier l’orthographe avant l’envoie d’un message';
 $labels['spellcheckbeforesend'] = 'Vérifier l’orthographe avant l’envoie d’un message';
+$labels['spellcheckoptions'] = 'Options du vérificateur d\'orthographe';
+$labels['spellcheckignoresyms'] = 'Ignorer les mots avec des symboles';
+$labels['spellcheckignorenums'] = 'Ignorer les mots avec des nombres';
+$labels['spellcheckignorecaps'] = 'Ignorer les mots entièrement en majuscule';
+$labels['addtodict'] = 'Ajouter au dictionnaire';
 $labels['folder'] = 'Dossier';
 $labels['folders'] = 'Dossiers';
 $labels['foldername'] = 'Nom du dossier';
 $labels['folder'] = 'Dossier';
 $labels['folders'] = 'Dossiers';
 $labels['foldername'] = 'Nom du dossier';
@@ -397,6 +408,11 @@ $labels['sortby'] = 'Trier par';
 $labels['sortasc'] = 'Tri ascendant';
 $labels['sortdesc'] = 'Tri descendant';
 $labels['undo'] = 'Annuler';
 $labels['sortasc'] = 'Tri ascendant';
 $labels['sortdesc'] = 'Tri descendant';
 $labels['undo'] = 'Annuler';
+$labels['plugin'] = 'Plugin';
+$labels['version'] = 'Version';
+$labels['source'] = 'Source';
+$labels['license'] = 'Licence';
+$labels['support'] = 'Support';
 $labels['B'] = 'o';
 $labels['KB'] = 'ko';
 $labels['MB'] = 'Mo';
 $labels['B'] = 'o';
 $labels['KB'] = 'ko';
 $labels['MB'] = 'Mo';
@@ -420,4 +436,4 @@ $labels['japanese'] = 'Japonais';
 $labels['korean'] = 'Coréen';
 $labels['chinese'] = 'Chinois';
 
 $labels['korean'] = 'Coréen';
 $labels['chinese'] = 'Chinois';
 
-?>
+?>
\ No newline at end of file
index 41f3108866c73adccb0f02a808912e107bb73417..8df142d86286c34223b77db70b8e7dd9fac384d1 100644 (file)
@@ -6,7 +6,7 @@
 | language/fr_FR/messages.inc                                           |
 |                                                                       |
 | Language file of the Roundcube Webmail client                         |
 | language/fr_FR/messages.inc                                           |
 |                                                                       |
 | Language file of the Roundcube Webmail client                         |
-| Copyright (C) 2005-2010, The Roundcube Dev Team                       |
+| Copyright (C) 2005-2011, The Roundcube Dev Team                       |
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 +-----------------------------------------------------------------------+
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 +-----------------------------------------------------------------------+
@@ -15,7 +15,7 @@
 |         Maximilien Cuony <theglu@theglu.org>                          |
 +-----------------------------------------------------------------------+
 
 |         Maximilien Cuony <theglu@theglu.org>                          |
 +-----------------------------------------------------------------------+
 
-@version $Id: messages.inc 5291 2011-09-28 17:10:45Z thomasb $
+@version $Id: messages.inc 5609 2011-12-14 12:58:13Z thomasb $
 
 */
 
 
 */
 
@@ -50,6 +50,7 @@ $messages['blockedimages'] = 'Afin de préserver votre vie privée, les images d
 $messages['encryptedmessage'] = 'Ceci est un message crypté et il ne peut pas être affiché. Désolé !';
 $messages['nocontactsfound'] = 'Aucun contact n\'a pu être trouvé';
 $messages['contactnotfound'] = 'Le contact demandé n\'a pas été trouvé';
 $messages['encryptedmessage'] = 'Ceci est un message crypté et il ne peut pas être affiché. Désolé !';
 $messages['nocontactsfound'] = 'Aucun contact n\'a pu être trouvé';
 $messages['contactnotfound'] = 'Le contact demandé n\'a pas été trouvé';
+$messages['contactsearchonly'] = 'Entrez un ou plusieurs mots clés pour trouver des contacts';
 $messages['sendingfailed'] = 'L\'envoi du message a échoué';
 $messages['senttooquickly'] = 'Vous devez attendre $sec sec. pour envoyer le message';
 $messages['errorsavingsent'] = 'Une erreur est survenue pendant la sauvegarde du message envoyé';
 $messages['sendingfailed'] = 'L\'envoi du message a échoué';
 $messages['senttooquickly'] = 'Vous devez attendre $sec sec. pour envoyer le message';
 $messages['errorsavingsent'] = 'Une erreur est survenue pendant la sauvegarde du message envoyé';
@@ -63,6 +64,7 @@ $messages['deletegroupconfirm'] = 'Êtes-vous sûr de vouloir supprimer le group
 $messages['deletemessagesconfirm'] = 'Voulez-vous vraiment supprimer le(s) message(s) sélectionné(s) ?';
 $messages['deletefolderconfirm'] = 'Voulez-vous vraiment effacer ce dossier ?';
 $messages['purgefolderconfirm'] = 'Voulez-vous vraiment effacer tous les messages de ce dossier ?';
 $messages['deletemessagesconfirm'] = 'Voulez-vous vraiment supprimer le(s) message(s) sélectionné(s) ?';
 $messages['deletefolderconfirm'] = 'Voulez-vous vraiment effacer ce dossier ?';
 $messages['purgefolderconfirm'] = 'Voulez-vous vraiment effacer tous les messages de ce dossier ?';
+$messages['contactdeleting'] = 'Suppression de contact(s)...';
 $messages['groupdeleting'] = 'Suppression du groupe ...';
 $messages['folderdeleting'] = 'Suppression du dossier...';
 $messages['foldermoving'] = 'Déplacement du dossier...';
 $messages['groupdeleting'] = 'Suppression du groupe ...';
 $messages['folderdeleting'] = 'Suppression du dossier...';
 $messages['foldermoving'] = 'Déplacement du dossier...';
@@ -74,14 +76,14 @@ $messages['nonamewarning'] = 'Veuillez fournir un nom';
 $messages['nopagesizewarning'] = 'Veuillez indiquer une taille de page';
 $messages['nosenderwarning'] = 'Veuillez renseigner l\'adresse d\'expéditeur';
 $messages['norecipientwarning'] = 'Veuillez ajouter au moins un destinataire';
 $messages['nopagesizewarning'] = 'Veuillez indiquer une taille de page';
 $messages['nosenderwarning'] = 'Veuillez renseigner l\'adresse d\'expéditeur';
 $messages['norecipientwarning'] = 'Veuillez ajouter au moins un destinataire';
-$messages['nosubjectwarning'] = 'Le champ « Objet » est vide. Souhaitez-vous le renseigner maintenant ?';
+$messages['nosubjectwarning'] = 'Le champ «Objet» est vide. Souhaitez-vous le renseigner maintenant ?';
 $messages['nobodywarning'] = 'Envoyer ce message sans texte ?';
 $messages['notsentwarning'] = 'Le message n\'a pas été envoyé. Voulez-vous abandonner ce message ?';
 $messages['noldapserver'] = 'Choisissez un serveur LDAP pour la recherche';
 $messages['nobodywarning'] = 'Envoyer ce message sans texte ?';
 $messages['notsentwarning'] = 'Le message n\'a pas été envoyé. Voulez-vous abandonner ce message ?';
 $messages['noldapserver'] = 'Choisissez un serveur LDAP pour la recherche';
-$messages['nocontactsreturned'] = 'Aucun contact trouvé';
 $messages['nosearchname'] = 'Entrez un nom de contact ou un courriel';
 $messages['notuploadedwarning'] = 'Toutes les pièces jointes ne sont pas encore envoyées pour le moment. Merci d\'attendre ou d\'annuler l\'envoi.';
 $messages['searchsuccessful'] = '$nr messages trouvés';
 $messages['nosearchname'] = 'Entrez un nom de contact ou un courriel';
 $messages['notuploadedwarning'] = 'Toutes les pièces jointes ne sont pas encore envoyées pour le moment. Merci d\'attendre ou d\'annuler l\'envoi.';
 $messages['searchsuccessful'] = '$nr messages trouvés';
+$messages['contactsearchsuccessful'] = '$nr contact(s) trouvé(s).';
 $messages['searchnomatch'] = 'La recherche ne donne aucun résultat';
 $messages['searching'] = 'En cours de recherche...';
 $messages['checking'] = 'Vérification...';
 $messages['searchnomatch'] = 'La recherche ne donne aucun résultat';
 $messages['searching'] = 'En cours de recherche...';
 $messages['checking'] = 'Vérification...';
@@ -90,7 +92,7 @@ $messages['folderdeleted'] = 'Dossier effacé';
 $messages['foldersubscribed'] = 'Le dossier a bien été inscrit';
 $messages['folderunsubscribed'] = 'Le dossier a bien été désinscrit';
 $messages['folderpurged'] = 'Le dossier a bien été vidé';
 $messages['foldersubscribed'] = 'Le dossier a bien été inscrit';
 $messages['folderunsubscribed'] = 'Le dossier a bien été désinscrit';
 $messages['folderpurged'] = 'Le dossier a bien été vidé';
-$messages['folderexpunged'] = 'Le dossier a bien été comptacté';
+$messages['folderexpunged'] = 'Le dossier a bien été compacté';
 $messages['deletedsuccessfully'] = 'Supprimé(s) avec succès';
 $messages['converting'] = 'Suppression de la mise en forme...';
 $messages['messageopenerror'] = 'Impossible de charger le message depuis serveur';
 $messages['deletedsuccessfully'] = 'Supprimé(s) avec succès';
 $messages['converting'] = 'Suppression de la mise en forme...';
 $messages['messageopenerror'] = 'Impossible de charger le message depuis serveur';
@@ -128,7 +130,6 @@ $messages['smtpautherror'] = 'Erreur SMTP ($code): Echec de l\'authentification'
 $messages['smtpfromerror'] = 'Erreur SMTP ($code): Impossible de définir l\'expéditeur "$from" ($msg)';
 $messages['smtptoerror'] = 'Erreur SMTP ($code): Impossible d\'ajouter le destinataire "$to" ($msg)';
 $messages['smtprecipientserror'] = 'Erreur SMTP: Impossible de lire la liste des destinataires';
 $messages['smtpfromerror'] = 'Erreur SMTP ($code): Impossible de définir l\'expéditeur "$from" ($msg)';
 $messages['smtptoerror'] = 'Erreur SMTP ($code): Impossible d\'ajouter le destinataire "$to" ($msg)';
 $messages['smtprecipientserror'] = 'Erreur SMTP: Impossible de lire la liste des destinataires';
-$messages['smtpdsnerror'] = 'Erreur SMTP: Pas de support des notifications d\'état de distribution';
 $messages['smtperror'] = 'Erreur SMTP: $msg';
 $messages['emailformaterror'] = 'Adresse email incorrecte: $email';
 $messages['toomanyrecipients'] = 'Trop de destinataires. Réduisez leur nombre à $max maximum.';
 $messages['smtperror'] = 'Erreur SMTP: $msg';
 $messages['emailformaterror'] = 'Adresse email incorrecte: $email';
 $messages['toomanyrecipients'] = 'Trop de destinataires. Réduisez leur nombre à $max maximum.';
@@ -141,11 +142,16 @@ $messages['contactrestored'] = 'Les contacts ont bien été restaurés.';
 $messages['groupdeleted'] = 'Le groupe a bien été supprimé';
 $messages['grouprenamed'] = 'Le groupe a bien été renommé';
 $messages['groupcreated'] = 'Le groupe a bien été créé';
 $messages['groupdeleted'] = 'Le groupe a bien été supprimé';
 $messages['grouprenamed'] = 'Le groupe a bien été renommé';
 $messages['groupcreated'] = 'Le groupe a bien été créé';
+$messages['savedsearchdeleted'] = 'La recherche enregistrée a bien été supprimée.';
+$messages['savedsearchdeleteerror'] = 'Impossible de supprimer la recherche enregistrée.';
+$messages['savedsearchcreated'] = 'La recherche enregistrée a bien été crée.';
+$messages['savedsearchcreateerror'] = 'Impossible de créer la recherche enregistrée.';
 $messages['messagedeleted'] = 'Les messages ont bien été supprimés';
 $messages['messagemoved'] = 'Les messages ont bien été déplacés';
 $messages['messagecopied'] = 'Les messages ont bien été copiés';
 $messages['messagemarked'] = 'Les messages ont bien été marqués';
 $messages['autocompletechars'] = 'Entrez au moins $min caractères pour l\'auto-complétion';
 $messages['messagedeleted'] = 'Les messages ont bien été supprimés';
 $messages['messagemoved'] = 'Les messages ont bien été déplacés';
 $messages['messagecopied'] = 'Les messages ont bien été copiés';
 $messages['messagemarked'] = 'Les messages ont bien été marqués';
 $messages['autocompletechars'] = 'Entrez au moins $min caractères pour l\'auto-complétion';
+$messages['autocompletemore'] = 'Plusieurs entrées trouvées. Tapez plus de caractères.';
 $messages['namecannotbeempty'] = 'Le nom ne peut pas être vide';
 $messages['nametoolong'] = 'Le nom est trop long';
 $messages['folderupdated'] = 'Le dossier a bien été mis à jour';
 $messages['namecannotbeempty'] = 'Le nom ne peut pas être vide';
 $messages['nametoolong'] = 'Le nom est trop long';
 $messages['folderupdated'] = 'Le dossier a bien été mis à jour';
@@ -153,5 +159,6 @@ $messages['foldercreated'] = 'Le dossier a bien été créé';
 $messages['invalidimageformat'] = 'Format d\'image invalide';
 $messages['mispellingsfound'] = 'Des fautes d\'orthographe ont été détectées dans le message.';
 $messages['parentnotwritable'] = 'Impossible de créer/déplacer le dossier dans le dossier parent sélectionné. Aucun droit d\'accès.';
 $messages['invalidimageformat'] = 'Format d\'image invalide';
 $messages['mispellingsfound'] = 'Des fautes d\'orthographe ont été détectées dans le message.';
 $messages['parentnotwritable'] = 'Impossible de créer/déplacer le dossier dans le dossier parent sélectionné. Aucun droit d\'accès.';
+$messages['messagetoobig'] = 'Le message est trop gros pour être traité.';
 
 
-?>
+?>
\ No newline at end of file
index 17f1fba66868852f9a84097cf349a7251b083202..bdceb7ef0fd6d73b742dd341977e2f86630bbbe7 100644 (file)
@@ -5,7 +5,7 @@
 | language/gl_ES/labels.inc                                             |
 |                                                                       |
 | Language file of the Roundcube Webmail client                         |
 | language/gl_ES/labels.inc                                             |
 |                                                                       |
 | Language file of the Roundcube Webmail client                         |
-| Copyright (C) 2005-2010, The Roundcube Dev Team                       |
+| Copyright (C) 2005-2011, The Roundcube Dev Team                       |
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 +-----------------------------------------------------------------------+
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 +-----------------------------------------------------------------------+
@@ -26,14 +26,14 @@ $labels['settings'] = 'Axustes persoais';
 $labels['addressbook'] = 'Caderno de enderezos';
 $labels['inbox'] = 'Caixa de entrada';
 $labels['drafts'] = 'Borradores';
 $labels['addressbook'] = 'Caderno de enderezos';
 $labels['inbox'] = 'Caixa de entrada';
 $labels['drafts'] = 'Borradores';
-$labels['sent'] = 'Enviado';
+$labels['sent'] = 'Enviados';
 $labels['trash'] = 'Cubo do lixo';
 $labels['junk'] = 'Correo lixo';
 $labels['subject'] = 'Asunto';
 $labels['from'] = 'Remitente';
 $labels['to'] = 'Destinatario';
 $labels['trash'] = 'Cubo do lixo';
 $labels['junk'] = 'Correo lixo';
 $labels['subject'] = 'Asunto';
 $labels['from'] = 'Remitente';
 $labels['to'] = 'Destinatario';
-$labels['cc'] = 'Copia (CC)';
-$labels['bcc'] = 'Copia oculta (BCC)';
+$labels['cc'] = 'Copia (Cc)';
+$labels['bcc'] = 'Copia oculta (Cco)';
 $labels['replyto'] = 'Respostar a (Reply-To)';
 $labels['followupto'] = 'Respostar a todos (Followup-To)';
 $labels['date'] = 'Data';
 $labels['replyto'] = 'Respostar a (Reply-To)';
 $labels['followupto'] = 'Respostar a todos (Followup-To)';
 $labels['date'] = 'Data';
@@ -42,7 +42,7 @@ $labels['priority'] = 'Prioridade';
 $labels['organization'] = 'Organización';
 $labels['readstatus'] = 'Estado da lectura';
 $labels['mailboxlist'] = 'Cartafoles';
 $labels['organization'] = 'Organización';
 $labels['readstatus'] = 'Estado da lectura';
 $labels['mailboxlist'] = 'Cartafoles';
-$labels['messagesfromto'] = 'Mensaxes do $from ao $to de $count';
+$labels['messagesfromto'] = 'Mensaxes da $from á $to de $count';
 $labels['threadsfromto'] = 'Fíos do $from ao $to de $count';
 $labels['messagenrof'] = 'Mensaxe $nr de $count';
 $labels['copy'] = 'Copiar';
 $labels['threadsfromto'] = 'Fíos do $from ao $to de $count';
 $labels['messagenrof'] = 'Mensaxe $nr de $count';
 $labels['copy'] = 'Copiar';
@@ -92,31 +92,29 @@ $labels['longnov'] = 'Novembro';
 $labels['longdec'] = 'Decembro';
 $labels['today'] = 'Hoxe';
 $labels['checkmail'] = 'Procurar novas mensaxes';
 $labels['longdec'] = 'Decembro';
 $labels['today'] = 'Hoxe';
 $labels['checkmail'] = 'Procurar novas mensaxes';
-$labels['writenewmessage'] = 'Crear unha nova mensaxe';
+$labels['writenewmessage'] = 'Redactar unha mensaxe nova';
 $labels['replytomessage'] = 'Respostar a mensaxe';
 $labels['replytoallmessage'] = 'Respostar á lista ou ao remitente e a tódolos destinatarios';
 $labels['replyall'] = 'Respostar a todos';
 $labels['replylist'] = 'Respostar á lista de correo';
 $labels['replytomessage'] = 'Respostar a mensaxe';
 $labels['replytoallmessage'] = 'Respostar á lista ou ao remitente e a tódolos destinatarios';
 $labels['replyall'] = 'Respostar a todos';
 $labels['replylist'] = 'Respostar á lista de correo';
+$labels['forwardinline'] = 'Reenviar inserido';
+$labels['forwardattachment'] = 'Reenviar como anexo';
 $labels['forwardmessage'] = 'Reenviar a mensaxe';
 $labels['deletemessage'] = 'Eliminar a mensaxe';
 $labels['movemessagetotrash'] = 'Mover a mensaxe ao cubo do lixo';
 $labels['printmessage'] = 'Imprimir esta mensaxe';
 $labels['previousmessage'] = 'Amosar a mensaxe anterior';
 $labels['forwardmessage'] = 'Reenviar a mensaxe';
 $labels['deletemessage'] = 'Eliminar a mensaxe';
 $labels['movemessagetotrash'] = 'Mover a mensaxe ao cubo do lixo';
 $labels['printmessage'] = 'Imprimir esta mensaxe';
 $labels['previousmessage'] = 'Amosar a mensaxe anterior';
-$labels['previousmessages'] = 'Amosar o grupo anterior de mensaxes';
 $labels['firstmessage'] = 'Amosar a primeira mensaxe';
 $labels['firstmessage'] = 'Amosar a primeira mensaxe';
-$labels['firstmessages'] = 'Amosar o primeiro grupo de mensaxes';
 $labels['nextmessage'] = 'Amosar a seguinte mensaxe';
 $labels['nextmessage'] = 'Amosar a seguinte mensaxe';
-$labels['nextmessages'] = 'Amosar o seguinte grupo de mensaxes';
 $labels['lastmessage'] = 'Amosar a última mensaxe';
 $labels['lastmessage'] = 'Amosar a última mensaxe';
-$labels['lastmessages'] = 'Amosar o último grupo de mensaxes';
 $labels['backtolist'] = 'Voltar á lista de mensaxes';
 $labels['backtolist'] = 'Voltar á lista de mensaxes';
-$labels['viewsource'] = 'Ver fonte';
+$labels['viewsource'] = 'Ver código fonte';
 $labels['markmessages'] = 'Marcar mensaxes';
 $labels['markread'] = 'Como lidas';
 $labels['markunread'] = 'Como non lidas';
 $labels['markflagged'] = 'Como marcadas';
 $labels['markunflagged'] = 'Como non marcadas';
 $labels['markmessages'] = 'Marcar mensaxes';
 $labels['markread'] = 'Como lidas';
 $labels['markunread'] = 'Como non lidas';
 $labels['markflagged'] = 'Como marcadas';
 $labels['markunflagged'] = 'Como non marcadas';
-$labels['messageactions'] = 'Máis accións...';
+$labels['moreactions'] = 'Máis accións...';
 $labels['select'] = 'Seleccionar';
 $labels['all'] = 'Todas';
 $labels['none'] = 'Ningunha';
 $labels['select'] = 'Seleccionar';
 $labels['all'] = 'Todas';
 $labels['none'] = 'Ningunha';
@@ -126,14 +124,14 @@ $labels['flagged'] = 'Marcadas';
 $labels['unanswered'] = 'Non respostadas';
 $labels['deleted'] = 'Marcadas como eliminadas';
 $labels['invert'] = 'Inverter';
 $labels['unanswered'] = 'Non respostadas';
 $labels['deleted'] = 'Marcadas como eliminadas';
 $labels['invert'] = 'Inverter';
-$labels['filter'] = 'Filtro';
+$labels['filter'] = 'Filtrar';
 $labels['list'] = 'Lista';
 $labels['threads'] = 'Fíos';
 $labels['expand-all'] = 'Expandir todos';
 $labels['expand-unread'] = 'Expandir os non lidos';
 $labels['collapse-all'] = 'Contraer todos';
 $labels['list'] = 'Lista';
 $labels['threads'] = 'Fíos';
 $labels['expand-all'] = 'Expandir todos';
 $labels['expand-unread'] = 'Expandir os non lidos';
 $labels['collapse-all'] = 'Contraer todos';
-$labels['threaded'] = 'Como fíos de discusión';
-$labels['autoexpand_threads'] = 'Expandir os fíos das mensaxes';
+$labels['threaded'] = 'Agrupar conversas';
+$labels['autoexpand_threads'] = 'Expandir os fíos de mensaxes';
 $labels['do_expand'] = 'tódolos fíos';
 $labels['expand_only_unread'] = 'só con mensaxes non lidas';
 $labels['fromto'] = 'Remitente/Destinatario';
 $labels['do_expand'] = 'tódolos fíos';
 $labels['expand_only_unread'] = 'só con mensaxes non lidas';
 $labels['fromto'] = 'Remitente/Destinatario';
@@ -169,12 +167,15 @@ $labels['charset'] = 'Codificación';
 $labels['editortype'] = 'Tipo de editor';
 $labels['returnreceipt'] = 'Notificación da entrega';
 $labels['dsn'] = 'Notificación do estado de envío (DSN)';
 $labels['editortype'] = 'Tipo de editor';
 $labels['returnreceipt'] = 'Notificación da entrega';
 $labels['dsn'] = 'Notificación do estado de envío (DSN)';
+$labels['mailreplyintro'] = 'O $date, $sender escribiu:';
+$labels['originalmessage'] = 'Mensaxe orixinal';
 $labels['editidents'] = 'Modificar identidades';
 $labels['checkspelling'] = 'Revisar a ortografía';
 $labels['resumeediting'] = 'Voltar á edición';
 $labels['revertto'] = 'Voltar a';
 $labels['attachments'] = 'Ficheiros anexos';
 $labels['upload'] = 'Cargar';
 $labels['editidents'] = 'Modificar identidades';
 $labels['checkspelling'] = 'Revisar a ortografía';
 $labels['resumeediting'] = 'Voltar á edición';
 $labels['revertto'] = 'Voltar a';
 $labels['attachments'] = 'Ficheiros anexos';
 $labels['upload'] = 'Cargar';
+$labels['uploadprogress'] = '$percent ($current de $total)';
 $labels['close'] = 'Pechar';
 $labels['messageoptions'] = 'Opcións da mensaxe...';
 $labels['low'] = 'Baixa';
 $labels['close'] = 'Pechar';
 $labels['messageoptions'] = 'Opcións da mensaxe...';
 $labels['low'] = 'Baixa';
@@ -183,13 +184,14 @@ $labels['normal'] = 'Normal';
 $labels['high'] = 'Alta';
 $labels['highest'] = 'A máis alta';
 $labels['nosubject'] = '(Sen asunto)';
 $labels['high'] = 'Alta';
 $labels['highest'] = 'A máis alta';
 $labels['nosubject'] = '(Sen asunto)';
-$labels['showimages'] = 'Amosar imaxes';
-$labels['alwaysshow'] = 'Amosar sempre as imaxes nas mensaxes remitidas por $sender';
+$labels['showimages'] = 'Amosar as imaxes';
+$labels['alwaysshow'] = 'Amosar sempre as imaxes nas mensaxes de $sender';
+$labels['isdraft'] = 'Esta mensaxe é un borrador';
 $labels['htmltoggle'] = 'HTML';
 $labels['htmltoggle'] = 'HTML';
-$labels['plaintoggle'] = 'Texto claro';
+$labels['plaintoggle'] = 'Só texto';
 $labels['savesentmessagein'] = 'Gardar a mensaxe enviada en';
 $labels['dontsave'] = 'non gardar';
 $labels['savesentmessagein'] = 'Gardar a mensaxe enviada en';
 $labels['dontsave'] = 'non gardar';
-$labels['maxuploadsize'] = 'O tamaño máximo permitido de ficheiro é de $size';
+$labels['maxuploadsize'] = 'O tamaño máximo permitido por ficheiro é de $size';
 $labels['addcc'] = 'Engadir copia (CC)';
 $labels['addbcc'] = 'Engadir copia oculta (BCC)';
 $labels['addreplyto'] = 'Engadir respostar a (Reply-To)';
 $labels['addcc'] = 'Engadir copia (CC)';
 $labels['addbcc'] = 'Engadir copia oculta (BCC)';
 $labels['addreplyto'] = 'Engadir respostar a (Reply-To)';
@@ -197,29 +199,77 @@ $labels['addfollowupto'] = 'Engadir respostar a todos (Followup-To)';
 $labels['mdnrequest'] = 'O remitente desta mensaxe pediu ser notificado cando vostede a lea. Quere notificar ao remitente?';
 $labels['receiptread'] = 'Notificación da entrega da mensaxe (lectura)';
 $labels['yourmessage'] = 'Esta é unha notificación da entrega da súa mensaxe';
 $labels['mdnrequest'] = 'O remitente desta mensaxe pediu ser notificado cando vostede a lea. Quere notificar ao remitente?';
 $labels['receiptread'] = 'Notificación da entrega da mensaxe (lectura)';
 $labels['yourmessage'] = 'Esta é unha notificación da entrega da súa mensaxe';
-$labels['receiptnote'] = 'Nota: Esta notificación só confirma que a mensaxe se abriu no computador do destinatario. Non asegura que o destinatario o lera ou entendera o seu contido.';
+$labels['receiptnote'] = 'Nota: Esta notificación só confirma que a mensaxe se abriu no computador do destinatario. Non asegura que o destinatario a lera ou entendera o seu contido.';
 $labels['name'] = 'Nome completo';
 $labels['firstname'] = 'Nome';
 $labels['surname'] = 'Apelidos';
 $labels['name'] = 'Nome completo';
 $labels['firstname'] = 'Nome';
 $labels['surname'] = 'Apelidos';
+$labels['middlename'] = 'Segundo nome';
+$labels['nameprefix'] = 'Prefixo';
+$labels['namesuffix'] = 'Sufixo';
+$labels['nickname'] = 'Alcume';
+$labels['jobtitle'] = 'Titulación';
+$labels['department'] = 'Departamento';
+$labels['gender'] = 'Xénero';
+$labels['maidenname'] = 'Nome de solteira';
 $labels['email'] = 'Correo Electrónico';
 $labels['email'] = 'Correo Electrónico';
+$labels['phone'] = 'Teléfono';
+$labels['address'] = 'Enderezo';
+$labels['street'] = 'Rúa';
+$labels['locality'] = 'Poboación';
+$labels['zipcode'] = 'Código postal';
+$labels['region'] = 'Provincia';
+$labels['country'] = 'País';
+$labels['birthday'] = 'Aniversario';
+$labels['anniversary'] = 'Aniversario';
+$labels['website'] = 'Sitio web';
+$labels['instantmessenger'] = 'Mensaxería instantánea';
+$labels['notes'] = 'Notes';
+$labels['male'] = 'home';
+$labels['female'] = 'muller';
+$labels['manager'] = 'Xerente';
+$labels['assistant'] = 'Asistente/a';
+$labels['spouse'] = 'Cónxuxe';
+$labels['allfields'] = 'Tódolos campos';
+$labels['search'] = 'Procurar';
+$labels['advsearch'] = 'Procura avanzada';
+$labels['other'] = 'Outro';
+$labels['typehome'] = 'Casa';
+$labels['typework'] = 'Traballo';
+$labels['typeother'] = 'Outro';
+$labels['typemobile'] = 'Móbil';
+$labels['typemain'] = 'Principal';
+$labels['typehomefax'] = 'Fax da casa';
+$labels['typeworkfax'] = 'Fax do traballo';
+$labels['typecar'] = 'Coche';
+$labels['typepager'] = 'Buscapersonas';
+$labels['typevideo'] = 'Vídeo';
+$labels['typeassistant'] = 'Asistente';
+$labels['typehomepage'] = 'Páxina principal';
+$labels['typeblog'] = 'Blogue';
+$labels['typeprofile'] = 'Perfil';
+$labels['addfield'] = 'Engadir campo';
 $labels['addcontact'] = 'Engadir novo contacto';
 $labels['addcontact'] = 'Engadir novo contacto';
-$labels['editcontact'] = 'Editar contacto';
+$labels['editcontact'] = 'Modificar este contacto';
 $labels['contacts'] = 'Contactos';
 $labels['contactproperties'] = 'Propiedades do contacto';
 $labels['contacts'] = 'Contactos';
 $labels['contactproperties'] = 'Propiedades do contacto';
+$labels['personalinfo'] = 'Información persoal';
 $labels['edit'] = 'Editar';
 $labels['cancel'] = 'Cancelar';
 $labels['save'] = 'Gardar';
 $labels['delete'] = 'Eliminar';
 $labels['rename'] = 'Mudar o nome';
 $labels['edit'] = 'Editar';
 $labels['cancel'] = 'Cancelar';
 $labels['save'] = 'Gardar';
 $labels['delete'] = 'Eliminar';
 $labels['rename'] = 'Mudar o nome';
-$labels['newcontact'] = 'Crear novo contacto';
+$labels['addphoto'] = 'Engadir';
+$labels['replacephoto'] = 'Substituír';
+$labels['newcontact'] = 'Novo contacto';
 $labels['deletecontact'] = 'Eliminar os contactos seleccionados';
 $labels['deletecontact'] = 'Eliminar os contactos seleccionados';
-$labels['composeto'] = 'Redactar mensaxe a';
+$labels['composeto'] = 'Redactar mensaxe para';
 $labels['contactsfromto'] = 'Contactos do $from ao $to de $count';
 $labels['print'] = 'Imprimir';
 $labels['export'] = 'Exportar';
 $labels['exportvcards'] = 'Exportar os contactos en formato vCard';
 $labels['newcontactgroup'] = 'Crear novo grupo de contactos';
 $labels['contactsfromto'] = 'Contactos do $from ao $to de $count';
 $labels['print'] = 'Imprimir';
 $labels['export'] = 'Exportar';
 $labels['exportvcards'] = 'Exportar os contactos en formato vCard';
 $labels['newcontactgroup'] = 'Crear novo grupo de contactos';
-$labels['groupactions'] = 'Accións cos grupos de contactos...';
+$labels['grouprename'] = 'Mudar o nome do grupo';
+$labels['groupdelete'] = 'Borrar o grupo';
 $labels['previouspage'] = 'Amosar o grupo anterior';
 $labels['firstpage'] = 'Amosar o primeiro grupo';
 $labels['nextpage'] = 'Amosar o seguinte grupo';
 $labels['previouspage'] = 'Amosar o grupo anterior';
 $labels['firstpage'] = 'Amosar o primeiro grupo';
 $labels['nextpage'] = 'Amosar o seguinte grupo';
@@ -227,13 +277,17 @@ $labels['lastpage'] = 'Amosar o último grupo';
 $labels['group'] = 'Grupo';
 $labels['groups'] = 'Grupos';
 $labels['personaladrbook'] = 'Enderezos persoais';
 $labels['group'] = 'Grupo';
 $labels['groups'] = 'Grupos';
 $labels['personaladrbook'] = 'Enderezos persoais';
+$labels['searchsave'] = 'Gardar procura';
+$labels['searchdelete'] = 'Eliminar procura';
 $labels['import'] = 'Importar';
 $labels['importcontacts'] = 'Importar contactos';
 $labels['importfromfile'] = 'Importar desde ficheiro:';
 $labels['import'] = 'Importar';
 $labels['importcontacts'] = 'Importar contactos';
 $labels['importfromfile'] = 'Importar desde ficheiro:';
+$labels['importtarget'] = 'Engadir contactos ao caderno de enderezos:';
 $labels['importreplace'] = 'Substituír completamente o caderno de enderezos';
 $labels['importtext'] = 'Pode cargar contactos desde un caderno de enderezos xa existente.<br/>Polo de agora pódense importar enderezos usando o formato <a href="http://en.wikipedia.org/wiki/VCard">vCard</a>  ';
 $labels['done'] = 'Rematado';
 $labels['settingsfor'] = 'Axustes de';
 $labels['importreplace'] = 'Substituír completamente o caderno de enderezos';
 $labels['importtext'] = 'Pode cargar contactos desde un caderno de enderezos xa existente.<br/>Polo de agora pódense importar enderezos usando o formato <a href="http://en.wikipedia.org/wiki/VCard">vCard</a>  ';
 $labels['done'] = 'Rematado';
 $labels['settingsfor'] = 'Axustes de';
+$labels['about'] = 'Acerca de';
 $labels['preferences'] = 'Preferencias';
 $labels['userpreferences'] = 'Preferencias de usuario';
 $labels['editpreferences'] = 'Editar preferencias de usuario';
 $labels['preferences'] = 'Preferencias';
 $labels['userpreferences'] = 'Preferencias de usuario';
 $labels['editpreferences'] = 'Editar preferencias de usuario';
@@ -245,6 +299,8 @@ $labels['edititem'] = 'Editar';
 $labels['preferhtml'] = 'Prefiro HTML';
 $labels['defaultcharset'] = 'Xogo de caracteres por omisión';
 $labels['htmlmessage'] = 'Mensaxe HTML';
 $labels['preferhtml'] = 'Prefiro HTML';
 $labels['defaultcharset'] = 'Xogo de caracteres por omisión';
 $labels['htmlmessage'] = 'Mensaxe HTML';
+$labels['dateformat'] = 'Formato da data';
+$labels['timeformat'] = 'Formato da hora';
 $labels['prettydate'] = 'Data decorada';
 $labels['setdefault'] = 'Usar como predeterminada';
 $labels['autodetect'] = 'Detectar automáticamente';
 $labels['prettydate'] = 'Data decorada';
 $labels['setdefault'] = 'Usar como predeterminada';
 $labels['autodetect'] = 'Detectar automáticamente';
@@ -252,11 +308,11 @@ $labels['language'] = 'Linguaxe';
 $labels['timezone'] = 'Zona horaria';
 $labels['pagesize'] = 'Liñas por páxina';
 $labels['signature'] = 'Sinatura';
 $labels['timezone'] = 'Zona horaria';
 $labels['pagesize'] = 'Liñas por páxina';
 $labels['signature'] = 'Sinatura';
-$labels['dstactive'] = 'Cambio de hora';
+$labels['dstactive'] = 'Cambio de hora según horario de verán';
 $labels['htmleditor'] = 'Redactar mensaxes HTML';
 $labels['htmlonreply'] = 'só cando se resposte a unha mensaxe HTML';
 $labels['htmlsignature'] = 'Sinatura HTML';
 $labels['htmleditor'] = 'Redactar mensaxes HTML';
 $labels['htmlonreply'] = 'só cando se resposte a unha mensaxe HTML';
 $labels['htmlsignature'] = 'Sinatura HTML';
-$labels['previewpane'] = 'Amosar panel de previsualización';
+$labels['previewpane'] = 'Amosar previsualización';
 $labels['skin'] = 'Aspecto da interface';
 $labels['logoutclear'] = 'Baleirar o cubo do lixo ao saír';
 $labels['logoutcompact'] = 'Compactar a caixa de entrada ao saír';
 $labels['skin'] = 'Aspecto da interface';
 $labels['logoutclear'] = 'Baleirar o cubo do lixo ao saír';
 $labels['logoutcompact'] = 'Compactar a caixa de entrada ao saír';
@@ -272,8 +328,8 @@ $labels['ignore'] = 'ignorar';
 $labels['readwhendeleted'] = 'Marcar a mensaxe como lida ao eliminar';
 $labels['flagfordeletion'] = 'Marcar a mensaxe para eliminar no canto de eliminar';
 $labels['skipdeleted'] = 'Non amosar as mensaxes marcadas como eliminadas';
 $labels['readwhendeleted'] = 'Marcar a mensaxe como lida ao eliminar';
 $labels['flagfordeletion'] = 'Marcar a mensaxe para eliminar no canto de eliminar';
 $labels['skipdeleted'] = 'Non amosar as mensaxes marcadas como eliminadas';
-$labels['deletealways'] = 'Borrar as mensaxes aínda se non se poden gardar na papeleira';
-$labels['showremoteimages'] = 'Amosar imaxes anexas remotas';
+$labels['deletealways'] = 'Eliminar as mensaxes aínda que non se poidan gardar no cubo do lixo';
+$labels['showremoteimages'] = 'Amosar as imaxes remotas';
 $labels['fromknownsenders'] = 'de remitentes coñecidos';
 $labels['always'] = 'sempre';
 $labels['showinlineimages'] = 'Amosar as imaxes anexas baixo a mensaxe';
 $labels['fromknownsenders'] = 'de remitentes coñecidos';
 $labels['always'] = 'sempre';
 $labels['showinlineimages'] = 'Amosar as imaxes anexas baixo a mensaxe';
@@ -287,26 +343,26 @@ $labels['messagescomposition'] = 'Composición das mensaxes';
 $labels['mimeparamfolding'] = 'Nomes dos ficheiros anexos';
 $labels['2231folding'] = 'Conforme ao RFC 2231 (Thunderbird)';
 $labels['miscfolding'] = 'RFC 2047/2231 (MS Outlook)';
 $labels['mimeparamfolding'] = 'Nomes dos ficheiros anexos';
 $labels['2231folding'] = 'Conforme ao RFC 2231 (Thunderbird)';
 $labels['miscfolding'] = 'RFC 2047/2231 (MS Outlook)';
-$labels['2047folding'] = 'Conforme ao RFC 2047 (other)';
+$labels['2047folding'] = 'Conforme ao RFC 2047 (outros)';
 $labels['force7bit'] = 'Usar MIME para codificar caracteres de 8 bits';
 $labels['advancedoptions'] = 'Opcións avanzadas';
 $labels['focusonnewmessage'] = 'Enfocar o navegador se hai mensaxes novas';
 $labels['checkallfolders'] = 'Procurar novas mensaxes en tódolos cartafoles';
 $labels['force7bit'] = 'Usar MIME para codificar caracteres de 8 bits';
 $labels['advancedoptions'] = 'Opcións avanzadas';
 $labels['focusonnewmessage'] = 'Enfocar o navegador se hai mensaxes novas';
 $labels['checkallfolders'] = 'Procurar novas mensaxes en tódolos cartafoles';
-$labels['displaynext'] = 'Amosar a seguinte mensaxe despois de borrar ou mover unha mensaxe';
+$labels['displaynext'] = 'Logo de eliminar ou mover unha mensaxe ir á mensaxe seguinte';
 $labels['mainoptions'] = 'Opcións principais';
 $labels['section'] = 'Sección';
 $labels['maintenance'] = 'Mantemento';
 $labels['mainoptions'] = 'Opcións principais';
 $labels['section'] = 'Sección';
 $labels['maintenance'] = 'Mantemento';
-$labels['newmessage'] = 'Nova mensaxe';
+$labels['newmessage'] = 'Mensaxes novas';
 $labels['listoptions'] = 'Opcións de lista';
 $labels['signatureoptions'] = 'Opcións da firma';
 $labels['whenreplying'] = 'Ao respostar';
 $labels['replytopposting'] = 'comezar a nova mensaxe enriba da orixinal';
 $labels['replybottomposting'] = 'comezar a nova mensaxe embaixo da orixinal';
 $labels['listoptions'] = 'Opcións de lista';
 $labels['signatureoptions'] = 'Opcións da firma';
 $labels['whenreplying'] = 'Ao respostar';
 $labels['replytopposting'] = 'comezar a nova mensaxe enriba da orixinal';
 $labels['replybottomposting'] = 'comezar a nova mensaxe embaixo da orixinal';
-$labels['replyremovesignature'] = 'Eliminar a firma orixinal da mensaxe ao respostar';
+$labels['replyremovesignature'] = 'Eliminar a firma do remitente ao respostar';
 $labels['autoaddsignature'] = 'Engadir firma automáticamente';
 $labels['autoaddsignature'] = 'Engadir firma automáticamente';
-$labels['newmessageonly'] = 'só nas novas mensaxes';
+$labels['newmessageonly'] = 'só nas mensaxes novas';
 $labels['replyandforwardonly'] = 'só nas respostas e reenvíos';
 $labels['replyandforwardonly'] = 'só nas respostas e reenvíos';
-$labels['replysignaturepos'] = 'Ao  respostar ou reenviar colocar a firma ';
+$labels['replysignaturepos'] = 'Ao respostar ou reenviar colocar a firma ';
 $labels['belowquote'] = 'embaixo do texto citado';
 $labels['abovequote'] = 'enriba do texto citado';
 $labels['insertsignature'] = 'Engadir firma';
 $labels['belowquote'] = 'embaixo do texto citado';
 $labels['abovequote'] = 'enriba do texto citado';
 $labels['insertsignature'] = 'Engadir firma';
@@ -315,6 +371,14 @@ $labels['afternseconds'] = 'logo de $n segundos';
 $labels['reqmdn'] = 'Solicitar sempre unha notificación da entrega';
 $labels['reqdsn'] = 'Solicitar sempre unha notificación do estado de envío';
 $labels['replysamefolder'] = 'Deixar as respostas no cartafol onde está a mensaxe á que se responde';
 $labels['reqmdn'] = 'Solicitar sempre unha notificación da entrega';
 $labels['reqdsn'] = 'Solicitar sempre unha notificación do estado de envío';
 $labels['replysamefolder'] = 'Deixar as respostas no cartafol onde está a mensaxe á que se responde';
+$labels['defaultaddressbook'] = 'Engadir contactos ao caderno de enderezos seleccionado';
+$labels['autocompletesingle'] = 'Ignorar as direccións alternativas no autocompletado';
+$labels['spellcheckbeforesend'] = 'Revisar a ortografía antes de enviar unha mensaxe';
+$labels['spellcheckoptions'] = 'Opción da revisión ortográfica';
+$labels['spellcheckignoresyms'] = 'Ignorar as palabras con símbolos';
+$labels['spellcheckignorenums'] = 'Ignorar as palabras con números';
+$labels['spellcheckignorecaps'] = 'Ignorar as palabras escritas en maiúsculas';
+$labels['addtodict'] = 'Engadir ao diccionario';
 $labels['folder'] = 'Cartafol';
 $labels['folders'] = 'Cartafoles';
 $labels['foldername'] = 'Nome do cartafol';
 $labels['folder'] = 'Cartafol';
 $labels['folders'] = 'Cartafoles';
 $labels['foldername'] = 'Nome do cartafol';
@@ -331,9 +395,19 @@ $labels['location'] = 'Situación';
 $labels['info'] = 'Información';
 $labels['getfoldersize'] = 'Prema para calcular o tamaño do cartafol';
 $labels['changesubscription'] = 'Prema para trocar a subscrición';
 $labels['info'] = 'Información';
 $labels['getfoldersize'] = 'Prema para calcular o tamaño do cartafol';
 $labels['changesubscription'] = 'Prema para trocar a subscrición';
+$labels['foldertype'] = 'Tipo do cartafol';
+$labels['personalfolder'] = 'Cartafol privado';
+$labels['otherfolder'] = 'Cartafol de outro usuario';
+$labels['sharedfolder'] = 'Cartafol público';
 $labels['sortby'] = 'Ordenar por';
 $labels['sortasc'] = 'Orde ascendente';
 $labels['sortdesc'] = 'Orde descendente';
 $labels['sortby'] = 'Ordenar por';
 $labels['sortasc'] = 'Orde ascendente';
 $labels['sortdesc'] = 'Orde descendente';
+$labels['undo'] = 'Desfacer';
+$labels['plugin'] = 'Complemento';
+$labels['version'] = 'Versión';
+$labels['source'] = 'Fonte';
+$labels['license'] = 'Licencia';
+$labels['support'] = 'Obter axuda';
 $labels['B'] = 'B';
 $labels['KB'] = 'KiB';
 $labels['MB'] = 'MiB';
 $labels['B'] = 'B';
 $labels['KB'] = 'KiB';
 $labels['MB'] = 'MiB';
index 521a67a8bbf0df8589098a9bfda185cecf0d200b..c872c8e83b5bb29aa8b39df7f1e615ac51d9e154 100644 (file)
@@ -5,7 +5,7 @@
 | language/gl_ES/messages.inc                                           |
 |                                                                       |
 | Language file of the Roundcube Webmail client                         |
 | language/gl_ES/messages.inc                                           |
 |                                                                       |
 | Language file of the Roundcube Webmail client                         |
-| Copyright (C) 2005-2010, The Roundcube Dev Team                       |
+| Copyright (C) 2005-2011, The Roundcube Dev Team                       |
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 +-----------------------------------------------------------------------+
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 +-----------------------------------------------------------------------+
 */
 
 $messages = array();
 */
 
 $messages = array();
-$messages['loginfailed'] = 'Fallou o acceso';
-$messages['cookiesdisabled'] = 'O seu navegador non acepta galletas';
-$messages['sessionerror'] = 'A súa sesión non é válida ou expirou';
-$messages['imaperror'] = 'Fallou a conexión co servidor IMAP';
+$messages['loginfailed'] = 'O contrasinal ou o nome de usuario son incorrectos.';
+$messages['cookiesdisabled'] = 'O seu navegador non acepta galletas.';
+$messages['sessionerror'] = 'A súa sesión non é válida ou expirou.';
+$messages['imaperror'] = 'Fallou a conexión co servidor IMAP.';
 $messages['servererror'] = 'Erro do servidor!';
 $messages['servererrormsg'] = 'Erro do servidor: $msg';
 $messages['servererror'] = 'Erro do servidor!';
 $messages['servererrormsg'] = 'Erro do servidor: $msg';
-$messages['errorreadonly'] = 'Non foi posible realizar a operación. O cartafol é de só lectura';
+$messages['dberror'] = 'Erro na base de datos!';
+$messages['errorreadonly'] = 'Non foi posible realizar a operación. O cartafol é de só lectura.';
 $messages['errornoperm'] = 'Non foi posible realizar a operación. Permiso denegado.';
 $messages['invalidrequest'] = 'Petición inválida!. Non se gardou ningún dato.';
 $messages['errornoperm'] = 'Non foi posible realizar a operación. Permiso denegado.';
 $messages['invalidrequest'] = 'Petición inválida!. Non se gardou ningún dato.';
-$messages['nomessagesfound'] = 'Non se atoparon mensaxes nesta caixa de correo';
+$messages['nomessagesfound'] = 'Non se atoparon mensaxes nesta caixa de correo.';
 $messages['loggedout'] = 'Rematou correctamente a súa sesión. Ata logo!';
 $messages['loggedout'] = 'Rematou correctamente a súa sesión. Ata logo!';
-$messages['mailboxempty'] = 'A caixa de correo está vacía';
+$messages['mailboxempty'] = 'A caixa de correo está vacía.';
 $messages['loading'] = 'Cargando...';
 $messages['uploading'] = 'Cargando ficheiro...';
 $messages['loading'] = 'Cargando...';
 $messages['uploading'] = 'Cargando ficheiro...';
+$messages['uploadingmany'] = 'Cargando ficheiros...';
 $messages['loadingdata'] = 'Cargando datos...';
 $messages['checkingmail'] = 'Á procura de novas mensaxes...';
 $messages['sendingmessage'] = 'Enviando mensaxe...';
 $messages['loadingdata'] = 'Cargando datos...';
 $messages['checkingmail'] = 'Á procura de novas mensaxes...';
 $messages['sendingmessage'] = 'Enviando mensaxe...';
-$messages['messagesent'] = 'A mensaxe enviouse correctamente';
+$messages['messagesent'] = 'A mensaxe enviouse correctamente.';
 $messages['savingmessage'] = 'Gardando mensaxe...';
 $messages['messagesaved'] = 'A mensaxe gardouse en "Borradores"';
 $messages['savingmessage'] = 'Gardando mensaxe...';
 $messages['messagesaved'] = 'A mensaxe gardouse en "Borradores"';
-$messages['successfullysaved'] = 'Gardada correctamente';
-$messages['addedsuccessfully'] = 'O contacto engadiuse correctamente ao caderno de enderezos';
-$messages['contactexists'] = 'Xa existe un contacto con este enderezo de correo electrónico';
-$messages['blockedimages'] = 'Estanse a bloquear as imaxes remotas para protexer a súa privacidade';
-$messages['encryptedmessage'] = 'Síntoo!. Non se pode amosar a mensaxe porque está cifrada';
-$messages['nocontactsfound'] = 'Non se atoparon contactos';
-$messages['contactnotfound'] = 'Non se atopou o contacto solicitado';
-$messages['sendingfailed'] = 'Fallou o envío da mensaxe';
-$messages['senttooquickly'] = 'Por favor, espere $sec segundos antes de enviar esta mensaxe';
-$messages['errorsavingsent'] = 'Ocurriu un erro mentres se gardaba a mensaxe enviada';
-$messages['errorsaving'] = 'Ocurriu un erro mentres se gardaba';
-$messages['errormoving'] = 'Non foi posible mover a(s) mensaxe(s)';
-$messages['errorcopying'] = 'Non foi posible copiar a(s) mensaxe(s)';
-$messages['errordeleting'] = 'Non foi posible eliminar a(s) mensaxe(s)';
-$messages['errormarking'] = 'Non foi posible marcar a(s) mensaxe(s)';
+$messages['successfullysaved'] = 'Gardado correctamente.';
+$messages['addedsuccessfully'] = 'O contacto engadiuse correctamente ao caderno de enderezos.';
+$messages['contactexists'] = 'Xa existe un contacto con este enderezo de correo electrónico.';
+$messages['contactnameexists'] = 'Xa existe un contacto con este nome.';
+$messages['blockedimages'] = 'Estanse a bloquear as imaxes remotas para protexer a súa privacidade.';
+$messages['encryptedmessage'] = 'Non se pode amosar a mensaxe porque está cifrada.';
+$messages['nocontactsfound'] = 'Non se atoparon contactos.';
+$messages['contactnotfound'] = 'Non se atopou o contacto solicitado.';
+$messages['contactsearchonly'] = 'Introduza algún termo para atopar contactos';
+$messages['sendingfailed'] = 'Fallou o envío da mensaxe.';
+$messages['senttooquickly'] = 'Por favor, espere $sec segundos antes de enviar esta mensaxe.';
+$messages['errorsavingsent'] = 'Ocurriu un erro mentres se gardaba a mensaxe enviada.';
+$messages['errorsaving'] = 'Ocurriu un erro mentres se gardaba.';
+$messages['errormoving'] = 'Non foi posible mover a(s) mensaxe(s).';
+$messages['errorcopying'] = 'Non foi posible copiar a(s) mensaxe(s).';
+$messages['errordeleting'] = 'Non foi posible eliminar a(s) mensaxe(s).';
+$messages['errormarking'] = 'Non foi posible marcar a(s) mensaxe(s).';
 $messages['deletecontactconfirm'] = 'Quere eliminar o(s) contacto(s) seleccionado(s)?';
 $messages['deletecontactconfirm'] = 'Quere eliminar o(s) contacto(s) seleccionado(s)?';
+$messages['deletegroupconfirm'] = 'Quere eliminar o grupo seleccionado?';
 $messages['deletemessagesconfirm'] = 'Quere eliminar a(s) mensaxe(s) seleccionadas?';
 $messages['deletefolderconfirm'] = 'Quere eliminar este cartafol?';
 $messages['purgefolderconfirm'] = 'Quere eliminar tódalas mensaxes neste cartafol?';
 $messages['deletemessagesconfirm'] = 'Quere eliminar a(s) mensaxe(s) seleccionadas?';
 $messages['deletefolderconfirm'] = 'Quere eliminar este cartafol?';
 $messages['purgefolderconfirm'] = 'Quere eliminar tódalas mensaxes neste cartafol?';
+$messages['contactdeleting'] = 'Eliminando o(s) contacto(s)...';
+$messages['groupdeleting'] = 'Eliminando o grupo...';
 $messages['folderdeleting'] = 'Eliminando o cartafol...';
 $messages['foldermoving'] = 'Movendo o cartafol...';
 $messages['foldersubscribing'] = 'Subscribindo o cartafol...';
 $messages['folderunsubscribing'] = 'Desubscribindo o cartafol...';
 $messages['folderdeleting'] = 'Eliminando o cartafol...';
 $messages['foldermoving'] = 'Movendo o cartafol...';
 $messages['foldersubscribing'] = 'Subscribindo o cartafol...';
 $messages['folderunsubscribing'] = 'Desubscribindo o cartafol...';
-$messages['formincomplete'] = 'Non se cumprimentou completamente o formulario';
-$messages['noemailwarning'] = 'Por favor, introduza un enderezo de correo electrónico válido';
-$messages['nonamewarning'] = 'Por favor, introduza un nome';
-$messages['nopagesizewarning'] = 'Por favor, introduza un tamaño de páxina';
-$messages['nosenderwarning'] = 'Por favor, introduza o enderezo de correo electrónico do remitente';
-$messages['norecipientwarning'] = 'Por favor, introduza polo menos un destinatario';
-$messages['nosubjectwarning'] = 'O campo "Asunto" está baleiro. Quere introducir un?';
+$messages['formincomplete'] = 'Non se cumprimentou completamente o formulario.';
+$messages['noemailwarning'] = 'Por favor, introduza un enderezo de correo electrónico válido.';
+$messages['nonamewarning'] = 'Por favor, introduza un nome.';
+$messages['nopagesizewarning'] = 'Por favor, introduza un tamaño de páxina.';
+$messages['nosenderwarning'] = 'Por favor, introduza o enderezo de correo electrónico do remitente.';
+$messages['norecipientwarning'] = 'Por favor, introduza polo menos un destinatario.';
+$messages['nosubjectwarning'] = 'O campo "Asunto" está baleiro. Desexa completalo?';
 $messages['nobodywarning'] = 'Quere enviar esta mensaxe sen texto?';
 $messages['notsentwarning'] = 'A mensaxe non se enviou. Quere descartala?';
 $messages['nobodywarning'] = 'Quere enviar esta mensaxe sen texto?';
 $messages['notsentwarning'] = 'A mensaxe non se enviou. Quere descartala?';
-$messages['noldapserver'] = 'Por favor, elixa un servidor LDAP para buscar';
-$messages['nocontactsreturned'] = 'Non se atoparon contactos';
-$messages['nosearchname'] = 'Por favor, introduza un contacto ou un enderezo de correo electrónico';
+$messages['noldapserver'] = 'Por favor, elixa un servidor LDAP para buscar.';
+$messages['nosearchname'] = 'Por favor, introduza un nome ou un enderezo de correo electrónico.';
 $messages['notuploadedwarning'] = 'Aínda non se cargaron tódolos ficheiros. Por favor, agarde ou cancele a carga.';
 $messages['notuploadedwarning'] = 'Aínda non se cargaron tódolos ficheiros. Por favor, agarde ou cancele a carga.';
-$messages['searchsuccessful'] = 'Atopáronse $nr mensaxes';
-$messages['searchnomatch'] = 'A busca non atopou coincidencias';
+$messages['searchsuccessful'] = 'Atopáronse $nr mensaxes.';
+$messages['contactsearchsuccessful'] = 'Atopáronse $nr contactos.';
+$messages['searchnomatch'] = 'A busca non atopou coincidencias.';
 $messages['searching'] = 'Buscando...';
 $messages['checking'] = 'Comprobando...';
 $messages['searching'] = 'Buscando...';
 $messages['checking'] = 'Comprobando...';
-$messages['nospellerrors'] = 'Non hai erros ortográficos';
-$messages['folderdeleted'] = 'O cartafol eliminouse correctamente';
-$messages['foldersubscribed'] = 'O cartafol suscribiuse correctamente';
-$messages['folderunsubscribed'] = 'O cartafol desuscribiuse correctamente';
-$messages['folderpurged'] = 'O cartafol purgouse correctamente';
-$messages['folderexpunged'] = 'O cartafol baleirouse correctamente';
-$messages['deletedsuccessfully'] = 'Eliminouse correctamente';
+$messages['nospellerrors'] = 'Non hai erros ortográficos.';
+$messages['folderdeleted'] = 'O cartafol eliminouse correctamente.';
+$messages['foldersubscribed'] = 'O cartafol suscribiuse correctamente.';
+$messages['folderunsubscribed'] = 'O cartafol desuscribiuse correctamente.';
+$messages['folderpurged'] = 'O cartafol purgouse correctamente.';
+$messages['folderexpunged'] = 'O cartafol baleirouse correctamente.';
+$messages['deletedsuccessfully'] = 'Eliminouse correctamente.';
 $messages['converting'] = 'Eliminando o formato da mensaxe...';
 $messages['converting'] = 'Eliminando o formato da mensaxe...';
-$messages['messageopenerror'] = 'Non foi posible cargar a mensaxe desde o servidor';
-$messages['fileuploaderror'] = 'Fallou a carga do ficheiro';
-$messages['filesizeerror'] = 'O ficheiro cargado é máis grande que o tamaño máximo de $size';
-$messages['copysuccess'] = 'Copiáronse correctamente $nr enderezos';
-$messages['copyerror'] = 'Non foi posible copiar ningún enderezo';
-$messages['sourceisreadonly'] = 'A orixe é de só lectura';
-$messages['errorsavingcontact'] = 'Non foi posible gardar o contacto';
+$messages['messageopenerror'] = 'Non foi posible cargar a mensaxe desde o servidor.';
+$messages['fileuploaderror'] = 'Fallou a carga do ficheiro.';
+$messages['filesizeerror'] = 'O ficheiro cargado é máis grande que o tamaño máximo de $size.';
+$messages['copysuccess'] = 'Copiáronse correctamente $nr enderezos.';
+$messages['copyerror'] = 'Non foi posible copiar ningún enderezo.';
+$messages['sourceisreadonly'] = 'A orixe é de só lectura.';
+$messages['errorsavingcontact'] = 'Non foi posible gardar o contacto.';
 $messages['movingmessage'] = 'Movendo a(s) mensaxe(s)...';
 $messages['copyingmessage'] = 'Copiando a(s) mensaxe(s)...';
 $messages['movingmessage'] = 'Movendo a(s) mensaxe(s)...';
 $messages['copyingmessage'] = 'Copiando a(s) mensaxe(s)...';
+$messages['copyingcontact'] = 'Copiando o(s) contacto(s)...';
 $messages['deletingmessage'] = 'Eliminando a(s) mensaxe(s)...';
 $messages['markingmessage'] = 'Marcando a(s) mensaxe(s)...';
 $messages['deletingmessage'] = 'Eliminando a(s) mensaxe(s)...';
 $messages['markingmessage'] = 'Marcando a(s) mensaxe(s)...';
-$messages['receiptsent'] = 'A notificación da entrega enviouse correctamente';
-$messages['errorsendingreceipt'] = 'Non foi posible enviar a notificación da entrega';
-$messages['nodeletelastidentity'] = 'Non pode eliminar esta identidade, é a última';
-$messages['forbiddencharacter'] = 'O nome do cartafol contén un carácter non válido';
-$messages['selectimportfile'] = 'Por favor, escolla un ficheiro para cargar';
-$messages['addresswriterror'] = 'Non se pode escribir no caderno de enderezos que escolleu';
-$messages['contactaddedtogroup'] = 'Engadíronse correctamente os contactos a este grupo';
-$messages['contactremovedfromgroup'] = 'Suprimíronse correctamente os contactos de este grupo';
-$messages['importwait'] = 'Estou a importar. Por favor, agarde...';
-$messages['importerror'] = 'Fallou a importación! O ficheiro que cargou non é un vCard correcto.';
+$messages['addingmember'] = 'Engadindo o(s) contacto(s) ao grupo...';
+$messages['removingmember'] = 'Eliminando o(s) contacto(s) do grupo...';
+$messages['receiptsent'] = 'A notificación da entrega enviouse correctamente.';
+$messages['errorsendingreceipt'] = 'Non foi posible enviar a notificación da entrega.';
+$messages['nodeletelastidentity'] = 'Non pode eliminar esta identidade, é a última.';
+$messages['forbiddencharacter'] = 'O nome do cartafol contén un carácter non válido.';
+$messages['selectimportfile'] = 'Por favor, escolla un ficheiro para cargar.';
+$messages['addresswriterror'] = 'Non se pode escribir no caderno de enderezos que escolleu.';
+$messages['contactaddedtogroup'] = 'Engadiuse correctamente o contacto a este grupo.';
+$messages['contactremovedfromgroup'] = 'Suprimiuse correctamente o contacto deste grupo.';
+$messages['importwait'] = 'A importar. Por favor, agarde...';
+$messages['importerror'] = 'Produciuse un erro na importación. O ficheiro que cargou non é un vCard correcto.';
 $messages['importconfirm'] = '<b>Importáronse correctamente $inserted contactos. Ignoráronse $skipped contactos que xa existían</b>:<p><em>$names</em></p>';
 $messages['importconfirm'] = '<b>Importáronse correctamente $inserted contactos. Ignoráronse $skipped contactos que xa existían</b>:<p><em>$names</em></p>';
-$messages['opnotpermitted'] = 'Operación non permitida';
-$messages['nofromaddress'] = 'Falta o enderezo de correo electrónico na identidade que escolleu';
+$messages['importconfirmskipped'] = '<b>Ignoráronse $skipped existing entradas</b>';
+$messages['opnotpermitted'] = 'Operación non permitida!';
+$messages['nofromaddress'] = 'Falta o enderezo de correo electrónico na identidade que escolleu.';
 $messages['editorwarning'] = 'Se troca neste intre ao editor de texto plano, vai perder todo o formato do texto. Quere continuar?';
 $messages['editorwarning'] = 'Se troca neste intre ao editor de texto plano, vai perder todo o formato do texto. Quere continuar?';
-$messages['httpreceivedencrypterror'] = 'Produciuse un erro fatal de configuración. Contacte ao administrador inmediatamente. <b>Non foi posible enviar a súa mensaxe.</b>';
-$messages['smtpconnerror'] = 'Erro SMTP ($code): Fallou a conexión co servidor';
-$messages['smtpautherror'] = 'Erro SMTP ($code): Fallou a autenticación';
-$messages['smtpfromerror'] = 'Erro SMTP ($code): Non foi posible establecer o remitente "$from" ($msg)';
-$messages['smtptoerror'] = 'Erro SMTP ($code): Non foi posible engadir o destinatario "$to" ($msg)';
-$messages['smtprecipientserror'] = 'Erro SMTP: Non se pode analizar a lista de destinatarios';
-$messages['smtpdsnerror'] = 'Erro SMTP: Non hai soporte para notificacións do estado de envío (DSN)';
+$messages['httpreceivedencrypterror'] = 'Produciuse un erro fatal de configuración. Contacte ao administrador inmediatamente. <b>Non se enviou a súa mensaxe.</b>';
+$messages['smtpconnerror'] = 'Erro SMTP ($code): Fallou a conexión co servidor.';
+$messages['smtpautherror'] = 'Erro SMTP ($code): Fallou a autenticación.';
+$messages['smtpfromerror'] = 'Erro SMTP ($code): Non foi posible establecer o remitente "$from" ($msg).';
+$messages['smtptoerror'] = 'Erro SMTP ($code): Non foi posible engadir o destinatario "$to" ($msg).';
+$messages['smtprecipientserror'] = 'Erro SMTP: Non se pode analizar a lista de destinatarios.';
+$messages['smtpdsnerror'] = 'Erro SMTP: Non hai soporte para notificacións do estado de envío (DSN).';
 $messages['smtperror'] = 'Erro SMTP: $msg';
 $messages['smtperror'] = 'Erro SMTP: $msg';
-$messages['emailformaterror'] = 'O enderezo de correo electrónico é incorrecto: $email';
+$messages['emailformaterror'] = 'O enderezo de correo electrónico é incorrecto: $email.';
 $messages['toomanyrecipients'] = 'Especificou destinatarios de máis. Por favor, redúzaos a un máximo de $max.';
 $messages['maxgroupmembersreached'] = 'O número de membros do grupo excede o máximo de $max.';
 $messages['internalerror'] = 'Ocurriu un erro interno. Por favor, probe outra vez.';
 $messages['toomanyrecipients'] = 'Especificou destinatarios de máis. Por favor, redúzaos a un máximo de $max.';
 $messages['maxgroupmembersreached'] = 'O número de membros do grupo excede o máximo de $max.';
 $messages['internalerror'] = 'Ocurriu un erro interno. Por favor, probe outra vez.';
-$messages['contactdelerror'] = 'Non foi posible borrar o(s) contacto(s)';
-$messages['contactdeleted'] = 'Borráronse correctamente o(s) contacto(s)';
-$messages['groupdeleted'] = 'Borrouse correctamente o grupo';
-$messages['grouprenamed'] = 'Mudouse correctamente o nome do grupo';
-$messages['groupcreated'] = 'Creouse correctamente o grupo';
-$messages['messagedeleted'] = 'Borráronse correctamente a(s) mensaxe(s)';
-$messages['messagemoved'] = 'Movéronse correctamente a(s) mensaxe(s)';
-$messages['messagecopied'] = 'Copiáronse correctamente a(s) mensaxe(s)';
-$messages['messagemarked'] = 'Marcáronse correctamente a(s) mensaxe(s)';
-$messages['autocompletechars'] = 'Introduza polo menos $min caracteres para autocompletar';
-$messages['namecannotbeempty'] = 'O nome non pode estar baleiro';
-$messages['nametoolong'] = 'O nome é longo de máis';
-$messages['folderupdated'] = 'O cartafol actualizouse correctamente';
-$messages['foldercreated'] = 'O cartafol creouse correctamente';
+$messages['contactdelerror'] = 'Non foi posible eliminar o(s) contacto(s).';
+$messages['contactdeleted'] = 'Borráronse correctamente o(s) contacto(s).';
+$messages['contactrestoreerror'] = 'Non foi posible restaurar o(s) contacto(s) borrado(s).';
+$messages['contactrestored'] = 'Restauráronse correctamente o(s) contacto(s).';
+$messages['groupdeleted'] = 'Borrouse correctamente o grupo.';
+$messages['grouprenamed'] = 'Mudouse correctamente o nome do grupo.';
+$messages['groupcreated'] = 'Creouse correctamente o grupo.';
+$messages['savedsearchdeleted'] = 'Borrouse correctamente a procura gardada. ';
+$messages['savedsearchdeleteerror'] = 'Non foi posible borrar a procura gardada.';
+$messages['savedsearchcreated'] = 'Creouse correctamente a procura gardada.';
+$messages['savedsearchcreateerror'] = 'Non foi posible crear a procura gardada.';
+$messages['messagedeleted'] = 'Borráronse correctamente a(s) mensaxe(s).';
+$messages['messagemoved'] = 'Movéronse correctamente a(s) mensaxe(s).';
+$messages['messagecopied'] = 'Copiáronse correctamente a(s) mensaxe(s).';
+$messages['messagemarked'] = 'Marcáronse correctamente a(s) mensaxe(s).';
+$messages['autocompletechars'] = 'Introduza polo menos $min caracteres para autocompletar.';
+$messages['autocompletemore'] = 'Atopáronse máis entradas concidintes. Por favor, introduza máis caracteres.';
+$messages['namecannotbeempty'] = 'O nome non pode estar baleiro.';
+$messages['nametoolong'] = 'O nome é longo de máis.';
+$messages['folderupdated'] = 'O cartafol actualizouse correctamente.';
+$messages['foldercreated'] = 'O cartafol creouse correctamente.';
+$messages['invalidimageformat'] = 'O formato da imaxe non é válido.';
+$messages['mispellingsfound'] = 'Atopáronse erros ortográficos na mensaxe.';
+$messages['parentnotwritable'] = 'Non foi posible crear/mover o cartafol no cartafol padre escollido porque non ten permisos.';
 
 ?>
 
 ?>
index 105897998cebf0432fca70bae136dcd22c2f63dc..1dd15f45e5411a09a9acfb76a80e84ce097f4397 100644 (file)
@@ -11,7 +11,7 @@
 +-----------------------------------------------------------------------+
 | Author: Moshe Leibovitch  <moish@mln.co.il>                           |
 | Updates: Noor Dawod <noor@comrax.com>                                 |
 +-----------------------------------------------------------------------+
 | Author: Moshe Leibovitch  <moish@mln.co.il>                           |
 | Updates: Noor Dawod <noor@comrax.com>                                 |
-| Updates: Moshe Leibovitch  <moish@mln.co.il>  05092011                |
+| Updates: Moshe Leibovitch  <moish@mln.co.il>  28112011                |
 +-----------------------------------------------------------------------+
 */
 
 +-----------------------------------------------------------------------+
 */
 
@@ -115,7 +115,7 @@ $labels['markread'] = 'כנקראו';
 $labels['markunread'] = 'כלא נקראו';
 $labels['markflagged'] = 'כמסומן';
 $labels['markunflagged'] = 'כלא מסומן';
 $labels['markunread'] = 'כלא נקראו';
 $labels['markflagged'] = 'כמסומן';
 $labels['markunflagged'] = 'כלא מסומן';
-$labels['messageactions'] = 'פעולות נוספות';
+$labels['moreactions'] = 'פעולות נוספות...';
 $labels['select'] = 'בחירה';
 $labels['all'] = 'הכל';
 $labels['none'] = 'כלום';
 $labels['select'] = 'בחירה';
 $labels['all'] = 'הכל';
 $labels['none'] = 'כלום';
@@ -187,6 +187,7 @@ $labels['highest'] = 'גבוה ביותר';
 $labels['nosubject'] = '(ללא נושא)';
 $labels['showimages'] = 'הצגת תמונות';
 $labels['alwaysshow'] = '$sender תמיד להציג תמונות מאת ';
 $labels['nosubject'] = '(ללא נושא)';
 $labels['showimages'] = 'הצגת תמונות';
 $labels['alwaysshow'] = '$sender תמיד להציג תמונות מאת ';
+$labels['isdraft'] = 'זו טיוטה של הודעה';
 $labels['htmltoggle'] = 'HTML';
 $labels['plaintoggle'] = 'ללא עיצוב';
 $labels['savesentmessagein'] = 'היכן לשמור ההודעה?';
 $labels['htmltoggle'] = 'HTML';
 $labels['plaintoggle'] = 'ללא עיצוב';
 $labels['savesentmessagein'] = 'היכן לשמור ההודעה?';
@@ -268,7 +269,6 @@ $labels['print'] = 'הדפסה';
 $labels['export'] = 'ייצוא';
 $labels['exportvcards'] = 'ייצוא אנשי קשר בפורמט  vCard ';
 $labels['newcontactgroup'] = 'יצירת קבוצה חדשה של אנשי קשר';
 $labels['export'] = 'ייצוא';
 $labels['exportvcards'] = 'ייצוא אנשי קשר בפורמט  vCard ';
 $labels['newcontactgroup'] = 'יצירת קבוצה חדשה של אנשי קשר';
-$labels['groupactions'] = 'פעולות על קבוצת אנשי הקשר...';
 $labels['grouprename'] = 'שינוי שם קבוצה';
 $labels['groupdelete'] = 'מחיקת קבוצה';
 $labels['previouspage'] = 'הצגת הקבוצה הקודמת';
 $labels['grouprename'] = 'שינוי שם קבוצה';
 $labels['groupdelete'] = 'מחיקת קבוצה';
 $labels['previouspage'] = 'הצגת הקבוצה הקודמת';
@@ -278,6 +278,8 @@ $labels['lastpage'] = 'הצגת הקבוצה האחרונה';
 $labels['group'] = 'קבוצה';
 $labels['groups'] = 'קבוצות';
 $labels['personaladrbook'] = 'כתובות פרטיות';
 $labels['group'] = 'קבוצה';
 $labels['groups'] = 'קבוצות';
 $labels['personaladrbook'] = 'כתובות פרטיות';
+$labels['searchsave'] = 'שמירת החיפוש';
+$labels['searchdelete'] = 'מחיקת החיפוש';
 $labels['import'] = 'ייבוא';
 $labels['importcontacts'] = 'ייבוא אנשי קשר';
 $labels['importfromfile'] = 'ייבוא מקובץ';
 $labels['import'] = 'ייבוא';
 $labels['importcontacts'] = 'ייבוא אנשי קשר';
 $labels['importfromfile'] = 'ייבוא מקובץ';
@@ -286,6 +288,7 @@ $labels['importreplace'] = 'החלפת כל פנקס הכתובות';
 $labels['importtext'] = '<a href="http://en.wikipedia.org/wiki/VCard">vCard</a>  ניתן לייבא אנשי קשר מפנקס כתובות קיים.  אנו תומכים בפורמט';
 $labels['done'] = 'בוצע';
 $labels['settingsfor'] = 'הגדרות עבור';
 $labels['importtext'] = '<a href="http://en.wikipedia.org/wiki/VCard">vCard</a>  ניתן לייבא אנשי קשר מפנקס כתובות קיים.  אנו תומכים בפורמט';
 $labels['done'] = 'בוצע';
 $labels['settingsfor'] = 'הגדרות עבור';
+$labels['about'] = 'אודות';
 $labels['preferences'] = 'העדפות';
 $labels['userpreferences'] = 'העדפות משתמש';
 $labels['editpreferences'] = 'עריכה של העדפות משתמש';
 $labels['preferences'] = 'העדפות';
 $labels['userpreferences'] = 'העדפות משתמש';
 $labels['editpreferences'] = 'עריכה של העדפות משתמש';
@@ -297,6 +300,8 @@ $labels['edititem'] = 'עריכת רשומה';
 $labels['preferhtml'] = 'הצגת HTML';
 $labels['defaultcharset'] = 'ברירת מחדל של תווים';
 $labels['htmlmessage'] = 'תוכן HTML';
 $labels['preferhtml'] = 'הצגת HTML';
 $labels['defaultcharset'] = 'ברירת מחדל של תווים';
 $labels['htmlmessage'] = 'תוכן HTML';
+$labels['dateformat'] = 'פורמט התאריך';
+$labels['timeformat'] = 'פורמט השעה';
 $labels['prettydate'] = 'תאריכים מעוצבים';
 $labels['setdefault'] = 'קביעה כברירת מחדל';
 $labels['autodetect'] = 'אוטומטי';
 $labels['prettydate'] = 'תאריכים מעוצבים';
 $labels['setdefault'] = 'קביעה כברירת מחדל';
 $labels['autodetect'] = 'אוטומטי';
@@ -368,7 +373,13 @@ $labels['reqmdn'] = 'תמיד יש לדרוש אישור קבלה';
 $labels['reqdsn'] = 'תמיד לבקש הודעה על מצב המסירה';
 $labels['replysamefolder'] = 'המענה ישמר בתיקיה של ההודעה המקורית';
 $labels['defaultaddressbook'] = 'הוספת אנשי קשר לספר הכתובות שנבחר';
 $labels['reqdsn'] = 'תמיד לבקש הודעה על מצב המסירה';
 $labels['replysamefolder'] = 'המענה ישמר בתיקיה של ההודעה המקורית';
 $labels['defaultaddressbook'] = 'הוספת אנשי קשר לספר הכתובות שנבחר';
+$labels['autocompletesingle'] = 'לדלג על כתובת דואר חילופית בעת שימוש בהשלמה אוטומטית של הקלדה';
 $labels['spellcheckbeforesend'] = 'בדיקת איות לפני המשלוח';
 $labels['spellcheckbeforesend'] = 'בדיקת איות לפני המשלוח';
+$labels['spellcheckoptions'] = 'אפשריות בדיקת איות';
+$labels['spellcheckignoresyms'] = 'התעלמות ממילים המכילות סמלים';
+$labels['spellcheckignorenums'] = 'התעלמות ממילים המכילות מספרים';
+$labels['spellcheckignorecaps'] = 'התעלמות ממילים עם אותציות ראשיות';
+$labels['addtodict'] = 'הוספה למילון';
 $labels['folder'] = 'תיק';
 $labels['folders'] = 'תיקים';
 $labels['foldername'] = 'שם תיק';
 $labels['folder'] = 'תיק';
 $labels['folders'] = 'תיקים';
 $labels['foldername'] = 'שם תיק';
@@ -393,6 +404,11 @@ $labels['sortby'] = 'מיון לפי';
 $labels['sortasc'] = 'מיון בסדר עולה';
 $labels['sortdesc'] = 'מיון בסדר יורד';
 $labels['undo'] = 'ביטול שינוי';
 $labels['sortasc'] = 'מיון בסדר עולה';
 $labels['sortdesc'] = 'מיון בסדר יורד';
 $labels['undo'] = 'ביטול שינוי';
+$labels['plugin'] = 'תוסף תוכנה';
+$labels['version'] = 'גירסה';
+$labels['source'] = 'מקור';
+$labels['license'] = 'רשיון';
+$labels['support'] = 'קבלת תמיכה';
 $labels['B'] = 'בייט';
 $labels['KB'] = 'ק"ב';
 $labels['MB'] = 'מ"ב';
 $labels['B'] = 'בייט';
 $labels['KB'] = 'ק"ב';
 $labels['MB'] = 'מ"ב';
index affa0d996e566db9bf54e5f1c0540e31fb38effa..51de7c79d7feb7f6ac1fb690539234de0e00599b 100644 (file)
@@ -11,7 +11,7 @@
 +-----------------------------------------------------------------------+
 | Author: Moshe Leibovitch    <moish@mln.co.il>                         |
 | Updates: Noor Dawod <noor@comrax.com>                                 |
 +-----------------------------------------------------------------------+
 | Author: Moshe Leibovitch    <moish@mln.co.il>                         |
 | Updates: Noor Dawod <noor@comrax.com>                                 |
-| Updates: Moshe Leibovitch  <moish@mln.co.il>  08082011                |
+| Updates: Moshe Leibovitch  <moish@mln.co.il>  28112011                |
 +-----------------------------------------------------------------------+
 
 */
 +-----------------------------------------------------------------------+
 
 */
@@ -47,6 +47,7 @@ $messages['blockedimages'] = 'תמונות משרת אחר נחסמו כדי ל
 $messages['encryptedmessage'] = 'זו הודעת מוצפנת ולא ניתן להציגה';
 $messages['nocontactsfound'] = 'לא נמצאו אנשי קשר';
 $messages['contactnotfound'] = 'איש הקשר המבוקש לא נמצא';
 $messages['encryptedmessage'] = 'זו הודעת מוצפנת ולא ניתן להציגה';
 $messages['nocontactsfound'] = 'לא נמצאו אנשי קשר';
 $messages['contactnotfound'] = 'איש הקשר המבוקש לא נמצא';
+$messages['contactsearchonly'] = 'יש להקיש מפתחות חיפוש כדי למצוא אנשי קשר';
 $messages['sendingfailed'] = 'שליחת ההודעה נכשלה';
 $messages['senttooquickly'] = 'נא להמתין $sec שניות לפני מסירת הודעה זו';
 $messages['errorsavingsent'] = 'נגרמה שגיאה במהלך שמירת ההודעה בתיק הודעות יוצאות';
 $messages['sendingfailed'] = 'שליחת ההודעה נכשלה';
 $messages['senttooquickly'] = 'נא להמתין $sec שניות לפני מסירת הודעה זו';
 $messages['errorsavingsent'] = 'נגרמה שגיאה במהלך שמירת ההודעה בתיק הודעות יוצאות';
@@ -60,6 +61,7 @@ $messages['deletegroupconfirm'] = 'האם אכן ברצונך למחוק את ה
 $messages['deletemessagesconfirm'] = 'האם למחוק את ההודעות המסומנות?';
 $messages['deletefolderconfirm'] = 'האם למחוק תיק זה?';
 $messages['purgefolderconfirm'] = 'האם למחוק את כל ההודעות בתיק זה?';
 $messages['deletemessagesconfirm'] = 'האם למחוק את ההודעות המסומנות?';
 $messages['deletefolderconfirm'] = 'האם למחוק תיק זה?';
 $messages['purgefolderconfirm'] = 'האם למחוק את כל ההודעות בתיק זה?';
+$messages['contactdeleting'] = 'אנשי קשר נמחקים...';
 $messages['groupdeleting'] = 'מחיקת קבוצה...';
 $messages['folderdeleting'] = 'התיקיה נמחקת...';
 $messages['foldermoving'] = 'העברת תיקיה...';
 $messages['groupdeleting'] = 'מחיקת קבוצה...';
 $messages['folderdeleting'] = 'התיקיה נמחקת...';
 $messages['foldermoving'] = 'העברת תיקיה...';
@@ -75,10 +77,10 @@ $messages['nosubjectwarning'] = 'שורת הנושא ריקה. האם ברצונ
 $messages['nobodywarning'] = 'האם לשלוח הודעה ללא תוכן?';
 $messages['notsentwarning'] = 'ההודעה לא נשלחה. האם לבטל?';
 $messages['noldapserver'] = 'נא לבחור שרת כתובות לחיפוש';
 $messages['nobodywarning'] = 'האם לשלוח הודעה ללא תוכן?';
 $messages['notsentwarning'] = 'ההודעה לא נשלחה. האם לבטל?';
 $messages['noldapserver'] = 'נא לבחור שרת כתובות לחיפוש';
-$messages['nocontactsreturned'] = 'לא נמצאו אנשי קשר';
 $messages['nosearchname'] = 'נא להוסיף איש קשר או כתובת דוא\"ל';
 $messages['notuploadedwarning'] = 'עדיין לא הועלו כל הקבצים. נא לחכות או לבטל הפעולה.';
 $messages['searchsuccessful'] = 'נמצאו $nr הודעות';
 $messages['nosearchname'] = 'נא להוסיף איש קשר או כתובת דוא\"ל';
 $messages['notuploadedwarning'] = 'עדיין לא הועלו כל הקבצים. נא לחכות או לבטל הפעולה.';
 $messages['searchsuccessful'] = 'נמצאו $nr הודעות';
+$messages['contactsearchsuccessful'] = 'נמצאו $nr אנשי קשר';
 $messages['searchnomatch'] = 'תוצאת החיפוש ריקה';
 $messages['searching'] = 'חיפוש...';
 $messages['checking'] = 'בדיקה...';
 $messages['searchnomatch'] = 'תוצאת החיפוש ריקה';
 $messages['searching'] = 'חיפוש...';
 $messages['checking'] = 'בדיקה...';
@@ -125,7 +127,6 @@ $messages['smtpautherror'] = 'SMTP ($code): ההזדהות נכשלה';
 $messages['smtpfromerror'] = ' ($msg) SMTP ($code): "$from" לא נרשמה כתובת השולח';
 $messages['smtptoerror'] = ' ($msg) SMTP ($code): "$to" לא נרשמה כתובת המקבל';
 $messages['smtprecipientserror'] = 'SMTP : לא ניתן לפענח רשימת נמענים';
 $messages['smtpfromerror'] = ' ($msg) SMTP ($code): "$from" לא נרשמה כתובת השולח';
 $messages['smtptoerror'] = ' ($msg) SMTP ($code): "$to" לא נרשמה כתובת המקבל';
 $messages['smtprecipientserror'] = 'SMTP : לא ניתן לפענח רשימת נמענים';
-$messages['smtpdsnerror'] = 'שגיאת SMTP: אין תמיכה בהודעה על מצב מסירה';
 $messages['smtperror'] = 'SMTP: $msg';
 $messages['emailformaterror'] = '$email  כתובת דוא"ל שגויה';
 $messages['toomanyrecipients'] = 'יותר מדי נמענים. יש להקטין מספרם ל - $max';
 $messages['smtperror'] = 'SMTP: $msg';
 $messages['emailformaterror'] = '$email  כתובת דוא"ל שגויה';
 $messages['toomanyrecipients'] = 'יותר מדי נמענים. יש להקטין מספרם ל - $max';
@@ -138,11 +139,16 @@ $messages['contactrestored'] = 'איש הקשר שוחזר בהצלחה';
 $messages['groupdeleted'] = 'הקבוצה נמחקה בהצלחה';
 $messages['grouprenamed'] = 'שם הקבוצה שונה בהצלחה';
 $messages['groupcreated'] = 'הקבוצה נוצרה בהצלחה';
 $messages['groupdeleted'] = 'הקבוצה נמחקה בהצלחה';
 $messages['grouprenamed'] = 'שם הקבוצה שונה בהצלחה';
 $messages['groupcreated'] = 'הקבוצה נוצרה בהצלחה';
+$messages['savedsearchdeleted'] = 'נמחק החיפוש שנשמר';
+$messages['savedsearchdeleteerror'] = 'לא ניתן למחוק החיפוש שנשמר';
+$messages['savedsearchcreated'] = 'החיפוש נשמר בהצלחה';
+$messages['savedsearchcreateerror'] = 'לא ניתן לשמור את החיפוש';
 $messages['messagedeleted'] = 'ההודעה נמחקה בהצלחה';
 $messages['messagemoved'] = 'ההודעה הועברה בהצלחה';
 $messages['messagecopied'] = 'ההודעה הועתקה בהצלחה';
 $messages['messagemarked'] = 'ההודעה סומנה בהצלחה';
 $messages['autocompletechars'] = 'יש להקיש לפחות $min תווים להשלמה אוטומטית של המחרוזת';
 $messages['messagedeleted'] = 'ההודעה נמחקה בהצלחה';
 $messages['messagemoved'] = 'ההודעה הועברה בהצלחה';
 $messages['messagecopied'] = 'ההודעה הועתקה בהצלחה';
 $messages['messagemarked'] = 'ההודעה סומנה בהצלחה';
 $messages['autocompletechars'] = 'יש להקיש לפחות $min תווים להשלמה אוטומטית של המחרוזת';
+$messages['autocompletemore'] = 'נמצאו רשומות נוספות. נא להקיש תווים נוספים.';
 $messages['namecannotbeempty'] = 'השם אינו יכול להיות ריק';
 $messages['nametoolong'] = 'השם ארוך מדי';
 $messages['folderupdated'] = 'התיק עודכן בהצלחה';
 $messages['namecannotbeempty'] = 'השם אינו יכול להיות ריק';
 $messages['nametoolong'] = 'השם ארוך מדי';
 $messages['folderupdated'] = 'התיק עודכן בהצלחה';
@@ -150,5 +156,6 @@ $messages['foldercreated'] = 'התיק נוצר בהצלחה';
 $messages['invalidimageformat'] = 'פורמט תמונה לא חוקי';
 $messages['mispellingsfound'] = 'התגלו שגיאות כתיב בהודעה';
 $messages['parentnotwritable'] = 'לא ניתן ליצור/להעביר תיקיה לתוך תיקית האב שנבחרה. אין הרשאה לגישה.';
 $messages['invalidimageformat'] = 'פורמט תמונה לא חוקי';
 $messages['mispellingsfound'] = 'התגלו שגיאות כתיב בהודעה';
 $messages['parentnotwritable'] = 'לא ניתן ליצור/להעביר תיקיה לתוך תיקית האב שנבחרה. אין הרשאה לגישה.';
+$messages['messagetoobig'] = 'ההודעה גדולה מעבר ליכולת העיבוד של התוכנה';
 
 ?>
 
 ?>
index ad0974e0f5387b248bcc9dbb4e0fdafedd96e492..725a7eb895a718fc3854e56ea02f9c28a91929e6 100644 (file)
@@ -14,7 +14,7 @@
 |       Tanja Dobričić <tanja.dobricic@everymail.info>                  |
 +-----------------------------------------------------------------------+
 
 |       Tanja Dobričić <tanja.dobricic@everymail.info>                  |
 +-----------------------------------------------------------------------+
 
-@version $Id: messages.inc 5067 2011-08-14 18:47:58Z thomasb $
+@version $Id: messages.inc 5139 2011-08-28 09:47:15Z alec $
 
 */
 
 
 */
 
@@ -25,7 +25,7 @@ $messages['sessionerror'] = 'Morate se ponovno ulogirati';
 $messages['imaperror'] = 'Neuspješna veza na IMAP server';
 $messages['servererror'] = 'Greška poslužitelja';
 $messages['servererrormsg'] = 'Greška na serveru: $msg';
 $messages['imaperror'] = 'Neuspješna veza na IMAP server';
 $messages['servererror'] = 'Greška poslužitelja';
 $messages['servererrormsg'] = 'Greška na serveru: $msg';
-$messages['databaserror'] = 'Greška baze podataka!';
+$messages['dberror'] = 'Greška baze podataka!';
 $messages['errorreadonly'] = 'Nemoguća izvedba operacije. Mapa je samo za čitanje.';
 $messages['errornoperm'] = 'Nemoguća izvedba operacije. Dozvola odbijena.';
 $messages['invalidrequest'] = 'Nepravilan zahtijev! Podaci nisu spremljeni.';
 $messages['errorreadonly'] = 'Nemoguća izvedba operacije. Mapa je samo za čitanje.';
 $messages['errornoperm'] = 'Nemoguća izvedba operacije. Dozvola odbijena.';
 $messages['invalidrequest'] = 'Nepravilan zahtijev! Podaci nisu spremljeni.';
index 467371734b2cc62500077125530d595aa8b1ff36..3982a64f9d076cb46c72bcfd8ac36d3cce48e241 100644 (file)
 | Author: Zark Bonfire <ikkhares at gmail dot com>                      |
 |         Peter Szabo <pete at teamlupus dot hu>                        |
 |         Barnabas Bona <bsi at hosember dot hu>                        |
 | Author: Zark Bonfire <ikkhares at gmail dot com>                      |
 |         Peter Szabo <pete at teamlupus dot hu>                        |
 |         Barnabas Bona <bsi at hosember dot hu>                        |
+|         Gabor Veliczky <hosting at jugiter dot net>                   |
 +-----------------------------------------------------------------------+
 
 +-----------------------------------------------------------------------+
 
-@version $Id: labels.inc 5067 2011-08-14 18:47:58Z thomasb $
+@version $Id: labels.inc 5569 2011-12-07 14:47:32Z thomasb $
 
 */
 
 
 */
 
@@ -27,7 +28,7 @@ $labels['server'] = 'Szerver';
 $labels['login'] = 'Belépés';
 $labels['logout'] = 'Kijelentkezés';
 $labels['mail'] = 'E-mail';
 $labels['login'] = 'Belépés';
 $labels['logout'] = 'Kijelentkezés';
 $labels['mail'] = 'E-mail';
-$labels['settings'] = 'Egyéni beállítások';
+$labels['settings'] = 'Beállítások';
 $labels['addressbook'] = 'Címjegyzék';
 $labels['inbox'] = 'Érkezett levelek';
 $labels['drafts'] = 'Piszkozatok';
 $labels['addressbook'] = 'Címjegyzék';
 $labels['inbox'] = 'Érkezett levelek';
 $labels['drafts'] = 'Piszkozatok';
@@ -119,7 +120,7 @@ $labels['markread'] = 'Olvasottként';
 $labels['markunread'] = 'Olvasatlanként';
 $labels['markflagged'] = 'Jelöltként';
 $labels['markunflagged'] = 'Jelöletlenként';
 $labels['markunread'] = 'Olvasatlanként';
 $labels['markflagged'] = 'Jelöltként';
 $labels['markunflagged'] = 'Jelöletlenként';
-$labels['messageactions'] = 'További lehetőségek...';
+$labels['moreactions'] = 'További műveletek...';
 $labels['select'] = 'Kijelölés';
 $labels['all'] = 'Összes';
 $labels['none'] = 'Nincs';
 $labels['select'] = 'Kijelölés';
 $labels['all'] = 'Összes';
 $labels['none'] = 'Nincs';
@@ -172,12 +173,15 @@ $labels['charset'] = 'Karakterkészlet';
 $labels['editortype'] = 'Szerkesztő típusa';
 $labels['returnreceipt'] = 'Olvasási visszaigazolás';
 $labels['dsn'] = 'Kézbesítési visszaigazolás';
 $labels['editortype'] = 'Szerkesztő típusa';
 $labels['returnreceipt'] = 'Olvasási visszaigazolás';
 $labels['dsn'] = 'Kézbesítési visszaigazolás';
+$labels['mailreplyintro'] = '$date időpontban $sender ezt írta:';
+$labels['originalmessage'] = 'Eredeti üzenet';
 $labels['editidents'] = 'Azonosítók szerkesztése';
 $labels['checkspelling'] = 'Helyesírás-ellenőrzés';
 $labels['resumeediting'] = 'Helyesírás-ellenőrzés vége';
 $labels['revertto'] = 'Visszaállítás erre';
 $labels['attachments'] = 'Csatolmányok';
 $labels['upload'] = 'Feltöltés';
 $labels['editidents'] = 'Azonosítók szerkesztése';
 $labels['checkspelling'] = 'Helyesírás-ellenőrzés';
 $labels['resumeediting'] = 'Helyesírás-ellenőrzés vége';
 $labels['revertto'] = 'Visszaállítás erre';
 $labels['attachments'] = 'Csatolmányok';
 $labels['upload'] = 'Feltöltés';
+$labels['uploadprogress'] = '$percent ($current / $total)';
 $labels['close'] = 'Bezárás';
 $labels['messageoptions'] = 'Üzenetbeállítások...';
 $labels['low'] = 'Alacsony';
 $labels['close'] = 'Bezárás';
 $labels['messageoptions'] = 'Üzenetbeállítások...';
 $labels['low'] = 'Alacsony';
@@ -187,7 +191,8 @@ $labels['high'] = 'Magas';
 $labels['highest'] = 'Legmagasabb';
 $labels['nosubject'] = '(nincs tárgy)';
 $labels['showimages'] = 'Képek megjelenítése';
 $labels['highest'] = 'Legmagasabb';
 $labels['nosubject'] = '(nincs tárgy)';
 $labels['showimages'] = 'Képek megjelenítése';
-$labels['alwaysshow'] = 'Képek megjelenítése mindig ha a feladó $sender';
+$labels['alwaysshow'] = 'Képek megjelenítése mindig, ha a feladó $sender';
+$labels['isdraft'] = 'TRANSLATE!';
 $labels['htmltoggle'] = 'HTML';
 $labels['plaintoggle'] = 'Egyszerű szöveg';
 $labels['savesentmessagein'] = 'Elküldött üzenet mentése ide';
 $labels['htmltoggle'] = 'HTML';
 $labels['plaintoggle'] = 'Egyszerű szöveg';
 $labels['savesentmessagein'] = 'Elküldött üzenet mentése ide';
@@ -238,14 +243,16 @@ $labels['typehome'] = 'Otthon';
 $labels['typework'] = 'Munkahely';
 $labels['typeother'] = 'Egyéb';
 $labels['typemobile'] = 'Mobil';
 $labels['typework'] = 'Munkahely';
 $labels['typeother'] = 'Egyéb';
 $labels['typemobile'] = 'Mobil';
-$labels['typemain'] = 'Fővonal';
+$labels['typemain'] = 'Vezetékes';
 $labels['typehomefax'] = 'Otthoni fax';
 $labels['typeworkfax'] = 'Munkahelyi fax';
 $labels['typecar'] = 'Gépkocsi';
 $labels['typepager'] = 'Személyhívó';
 $labels['typevideo'] = 'Videó';
 $labels['typeassistant'] = 'Asszisztens';
 $labels['typehomefax'] = 'Otthoni fax';
 $labels['typeworkfax'] = 'Munkahelyi fax';
 $labels['typecar'] = 'Gépkocsi';
 $labels['typepager'] = 'Személyhívó';
 $labels['typevideo'] = 'Videó';
 $labels['typeassistant'] = 'Asszisztens';
-$labels['typehomepage']  = 'Weboldal';
+$labels['typehomepage'] = 'Weboldal';
+$labels['typeblog'] = 'Blog';
+$labels['typeprofile'] = 'Profil';
 $labels['addfield'] = 'Új mező hozzáadása...';
 $labels['addcontact'] = 'Új kapcsolat hozzáadása';
 $labels['editcontact'] = 'Kapcsolat szerkesztése';
 $labels['addfield'] = 'Új mező hozzáadása...';
 $labels['addcontact'] = 'Új kapcsolat hozzáadása';
 $labels['editcontact'] = 'Kapcsolat szerkesztése';
@@ -267,16 +274,17 @@ $labels['print'] = 'Nyomtatás';
 $labels['export'] = 'Exportálás';
 $labels['exportvcards'] = 'Kapcsolatok exportálása vCard formátumban';
 $labels['newcontactgroup'] = 'Új csoport';
 $labels['export'] = 'Exportálás';
 $labels['exportvcards'] = 'Kapcsolatok exportálása vCard formátumban';
 $labels['newcontactgroup'] = 'Új csoport';
-$labels['groupactions'] = 'Műveletek csoportokkal...';
-$labels['grouprename']    = 'Csoport átnevezése';
-$labels['groupdelete']    = 'Csoport törlése';
-$labels['previouspage'] = 'Előző lap';
-$labels['firstpage'] = 'Első lap';
-$labels['nextpage'] = 'Következő lap';
-$labels['lastpage'] = 'Utolsó lap';
+$labels['grouprename'] = 'Csoport átnevezése';
+$labels['groupdelete'] = 'Csoport törlése';
+$labels['previouspage'] = 'Előző oldal';
+$labels['firstpage'] = 'Első oldal';
+$labels['nextpage'] = 'Következő oldal';
+$labels['lastpage'] = 'Utolsó oldal';
 $labels['group'] = 'Csoport';
 $labels['groups'] = 'Csoportok';
 $labels['personaladrbook'] = 'Személyes címjegyzék';
 $labels['group'] = 'Csoport';
 $labels['groups'] = 'Csoportok';
 $labels['personaladrbook'] = 'Személyes címjegyzék';
+$labels['searchsave'] = 'Keresés mentése';
+$labels['searchdelete'] = 'Keresés törlése';
 $labels['import'] = 'Importálás';
 $labels['importcontacts'] = 'Kapcsolatok importálása';
 $labels['importfromfile'] = 'Importálás fájlból:';
 $labels['import'] = 'Importálás';
 $labels['importcontacts'] = 'Kapcsolatok importálása';
 $labels['importfromfile'] = 'Importálás fájlból:';
@@ -296,6 +304,8 @@ $labels['edititem'] = 'Elem szerkesztése';
 $labels['preferhtml'] = 'HTML megjelenítés';
 $labels['defaultcharset'] = 'Alapértelmezett karakterkódolás';
 $labels['htmlmessage'] = 'HTML üzenet';
 $labels['preferhtml'] = 'HTML megjelenítés';
 $labels['defaultcharset'] = 'Alapértelmezett karakterkódolás';
 $labels['htmlmessage'] = 'HTML üzenet';
+$labels['dateformat'] = 'Dátumformátum';
+$labels['timeformat'] = 'Időformátum';
 $labels['prettydate'] = 'Rövid dátumok';
 $labels['setdefault'] = 'Beállítás alapértelmezettnek';
 $labels['autodetect'] = 'Automatikus';
 $labels['prettydate'] = 'Rövid dátumok';
 $labels['setdefault'] = 'Beállítás alapértelmezettnek';
 $labels['autodetect'] = 'Automatikus';
@@ -321,7 +331,7 @@ $labels['autosendknown'] = 'visszaigazolás küldése csak a kapcsolataimnak, eg
 $labels['autosendknownignore'] = 'visszaigazolás küldése csak a kapcsolataimnak, egyéb esetben hagyja figyelmen kívül';
 $labels['ignore'] = 'hagyja figyelmen kívül';
 $labels['readwhendeleted'] = 'Üzenet olvasottként jelölése törléskor';
 $labels['autosendknownignore'] = 'visszaigazolás küldése csak a kapcsolataimnak, egyéb esetben hagyja figyelmen kívül';
 $labels['ignore'] = 'hagyja figyelmen kívül';
 $labels['readwhendeleted'] = 'Üzenet olvasottként jelölése törléskor';
-$labels['flagfordeletion'] = 'Üzenet törlendőnek jelölése törlés helyett ';
+$labels['flagfordeletion'] = 'Üzenet törlendőnek jelölése törlés helyett';
 $labels['skipdeleted'] = 'Törölt üzenetek ne legyenek megjelenítve';
 $labels['deletealways'] = 'Üzenet törlése, ha nem sikerül áthelyezni a törölt elemek mappába';
 $labels['showremoteimages'] = 'Távoli beágyazott képek mutatása';
 $labels['skipdeleted'] = 'Törölt üzenetek ne legyenek megjelenítve';
 $labels['deletealways'] = 'Üzenet törlése, ha nem sikerül áthelyezni a törölt elemek mappába';
 $labels['showremoteimages'] = 'Távoli beágyazott képek mutatása';
@@ -367,7 +377,13 @@ $labels['reqmdn'] = 'Olvasási visszaigazolás megkövetelése';
 $labels['reqdsn'] = 'Kézbesítési visszaigazolás megkövetelése';
 $labels['replysamefolder'] = 'Válaszok azonos mappába helyezése';
 $labels['defaultaddressbook'] = 'Új kapcsolatok hozzáadása a kiválasztott címjegyzékhez';
 $labels['reqdsn'] = 'Kézbesítési visszaigazolás megkövetelése';
 $labels['replysamefolder'] = 'Válaszok azonos mappába helyezése';
 $labels['defaultaddressbook'] = 'Új kapcsolatok hozzáadása a kiválasztott címjegyzékhez';
+$labels['autocompletesingle'] = 'TRANSLATE!';
 $labels['spellcheckbeforesend'] = 'Helyesírás-ellenőrzés az üzenet elküldése előtt';
 $labels['spellcheckbeforesend'] = 'Helyesírás-ellenőrzés az üzenet elküldése előtt';
+$labels['spellcheckoptions'] = 'Helyesírás-ellenőrzés opciók';
+$labels['spellcheckignoresyms'] = 'Speciális karaktereket tartalmazó szavak kihagyása';
+$labels['spellcheckignorenums'] = 'Számot tartalmazó szavak kihagyása';
+$labels['spellcheckignorecaps'] = 'Csak nagybetűt tartalmazó szavak kihagyása';
+$labels['addtodict'] = 'Hozzáadás a szótárhoz';
 $labels['folder'] = 'Mappa';
 $labels['folders'] = 'Mappák';
 $labels['foldername'] = 'Mappa neve';
 $labels['folder'] = 'Mappa';
 $labels['folders'] = 'Mappák';
 $labels['foldername'] = 'Mappa neve';
@@ -386,11 +402,12 @@ $labels['getfoldersize'] = 'Mappa mérete';
 $labels['changesubscription'] = 'Feliratkozás megváltoztatása';
 $labels['foldertype'] = 'Mappa típusa';
 $labels['personalfolder'] = 'Privát mappa';
 $labels['changesubscription'] = 'Feliratkozás megváltoztatása';
 $labels['foldertype'] = 'Mappa típusa';
 $labels['personalfolder'] = 'Privát mappa';
-$labels['otherfolder'] = 'Más felhasználó mappája';
+$labels['otherfolder'] = 'Más felhasználó(k) mappája';
 $labels['sharedfolder'] = 'Megosztott mappa';
 $labels['sortby'] = 'Rendezés';
 $labels['sortasc'] = 'növekvő';
 $labels['sortdesc'] = 'csökkenő';
 $labels['sharedfolder'] = 'Megosztott mappa';
 $labels['sortby'] = 'Rendezés';
 $labels['sortasc'] = 'növekvő';
 $labels['sortdesc'] = 'csökkenő';
+$labels['undo'] = 'Visszavonás';
 $labels['B'] = 'B';
 $labels['KB'] = 'KB';
 $labels['MB'] = 'MB';
 $labels['B'] = 'B';
 $labels['KB'] = 'KB';
 $labels['MB'] = 'MB';
index 1c070ced0ad6ab56622c474d295f60ca21337302..321486e4a88f894599258a65d4fb01cbb7586dfb 100644 (file)
 | Author: Zark Bonfire <ikkhares at gmail dot com>                      |
 |         Peter Szabo <pete at teamlupus dot hu>                        |
 |         Barnabas Bona <bsi at hosember dot hu>                        |
 | Author: Zark Bonfire <ikkhares at gmail dot com>                      |
 |         Peter Szabo <pete at teamlupus dot hu>                        |
 |         Barnabas Bona <bsi at hosember dot hu>                        |
+|         Gabor Veliczky <hosting at jugiter dot net>                   |
 +-----------------------------------------------------------------------+
 
 +-----------------------------------------------------------------------+
 
-@version $Id: messages.inc 5067 2011-08-14 18:47:58Z thomasb $
+@version $Id: messages.inc 5569 2011-12-07 14:47:32Z thomasb $
 
 */
 
 
 */
 
@@ -23,12 +24,12 @@ $messages = array();
 $messages['loginfailed'] = 'Sikertelen belépés';
 $messages['cookiesdisabled'] = 'A böngésző nem támogatja a sütik használatát';
 $messages['sessionerror'] = 'Érvénytelen vagy lejárt munkamenet';
 $messages['loginfailed'] = 'Sikertelen belépés';
 $messages['cookiesdisabled'] = 'A böngésző nem támogatja a sütik használatát';
 $messages['sessionerror'] = 'Érvénytelen vagy lejárt munkamenet';
-$messages['imaperror'] = 'Nem sikerült a kapcsolódás az IMAP szerverhez';
+$messages['imaperror'] = 'Nem sikerült csatlakozni az IMAP szerverhez';
 $messages['servererror'] = 'Szerverhiba!';
 $messages['servererrormsg'] = 'Szerverhiba: $msg';
 $messages['servererror'] = 'Szerverhiba!';
 $messages['servererrormsg'] = 'Szerverhiba: $msg';
-$messages['databaserror'] = 'Adatbázishiba!';
-$messages['errorreadonly'] = 'A műveletet nem sikerült végrehajtani. A mappa írásvédett';
-$messages['errornoperm'] = 'A műveletet nem sikerült végrehajtani. Hozzáférés megtagadva';
+$messages['dberror'] = 'Adatbázishiba!';
+$messages['errorreadonly'] = 'A műveletet nem sikerült végrehajtani. A mappa írásvédett.';
+$messages['errornoperm'] = 'A műveletet nem sikerült végrehajtani. Hozzáférés megtagadva.';
 $messages['invalidrequest'] = 'Érvénytelen kérés! Az adatok nem lettek elmentve.';
 $messages['nomessagesfound'] = 'A fiók nem tartalmaz leveleket';
 $messages['loggedout'] = 'Sikeres kijelentkezés. Viszontlátásra!';
 $messages['invalidrequest'] = 'Érvénytelen kérés! Az adatok nem lettek elmentve.';
 $messages['nomessagesfound'] = 'A fiók nem tartalmaz leveleket';
 $messages['loggedout'] = 'Sikeres kijelentkezés. Viszontlátásra!';
@@ -44,11 +45,13 @@ $messages['savingmessage'] = 'Az üzenet mentése...';
 $messages['messagesaved'] = 'Az üzenet elmentve a Piszkozatokhoz';
 $messages['successfullysaved'] = 'A mentés sikerült';
 $messages['addedsuccessfully'] = 'A kapcsolat hozzáadása a címjegyzékhez megtörtént';
 $messages['messagesaved'] = 'Az üzenet elmentve a Piszkozatokhoz';
 $messages['successfullysaved'] = 'A mentés sikerült';
 $messages['addedsuccessfully'] = 'A kapcsolat hozzáadása a címjegyzékhez megtörtént';
-$messages['contactexists'] = 'A kapcsolat már létezik ezzel az e-mail címmel';
-$messages['blockedimages'] = 'Biztonsági okokból a távoli képek letöltése tiltott.';
-$messages['encryptedmessage'] = 'Az üzenet titkosított, ezért nem megjeleníthető.';
+$messages['contactexists'] = 'Ezzel az e-mail címmel már létezik kapcsolat';
+$messages['contactnameexists'] = 'Ezzel a névvel már létezik kapcsolat';
+$messages['blockedimages'] = 'Biztonsági okokból a távoli képek letöltése tiltott';
+$messages['encryptedmessage'] = 'Az üzenet titkosított, ezért nem megjeleníthető';
 $messages['nocontactsfound'] = 'Nem találhatóak kapcsolatok';
 $messages['contactnotfound'] = 'A kiválasztott kapcsolat nem található';
 $messages['nocontactsfound'] = 'Nem találhatóak kapcsolatok';
 $messages['contactnotfound'] = 'A kiválasztott kapcsolat nem található';
+$messages['contactsearchonly'] = 'Adjon meg keresőkifejezéseket a kapcsolatok közti kereséshez';
 $messages['sendingfailed'] = 'Az üzenet elküldése nem sikerült';
 $messages['senttooquickly'] = 'Kérem várjon még $sec másodpercet az üzenet elküldése előtt';
 $messages['errorsavingsent'] = 'Hiba történt az elküldött üzenet mentése közben';
 $messages['sendingfailed'] = 'Az üzenet elküldése nem sikerült';
 $messages['senttooquickly'] = 'Kérem várjon még $sec másodpercet az üzenet elküldése előtt';
 $messages['errorsavingsent'] = 'Hiba történt az elküldött üzenet mentése közben';
@@ -58,9 +61,12 @@ $messages['errorcopying'] = 'Az üzenet(ek)et nem sikerült másolni';
 $messages['errordeleting'] = 'Az üzenet(ek)et nem sikerült törölni';
 $messages['errormarking'] = 'Az üzenet(ek)et nem sikerült megjelölni';
 $messages['deletecontactconfirm'] = 'Biztos, hogy törölni szeretné a kijelölt kapcsolato(ka)t?';
 $messages['errordeleting'] = 'Az üzenet(ek)et nem sikerült törölni';
 $messages['errormarking'] = 'Az üzenet(ek)et nem sikerült megjelölni';
 $messages['deletecontactconfirm'] = 'Biztos, hogy törölni szeretné a kijelölt kapcsolato(ka)t?';
+$messages['deletegroupconfirm'] = 'Biztos, hogy törölni szeretné a kijelölt csoportot?';
 $messages['deletemessagesconfirm'] = 'Biztos, hogy törölni szeretné a kijelölt üzenete(ke)t?';
 $messages['deletefolderconfirm'] = 'Biztos, hogy törölni szeretné ezt a mappát?';
 $messages['purgefolderconfirm'] = 'Biztos benne, hogy az összes üzenet törölhető?';
 $messages['deletemessagesconfirm'] = 'Biztos, hogy törölni szeretné a kijelölt üzenete(ke)t?';
 $messages['deletefolderconfirm'] = 'Biztos, hogy törölni szeretné ezt a mappát?';
 $messages['purgefolderconfirm'] = 'Biztos benne, hogy az összes üzenet törölhető?';
+$messages['contactdeleting'] = 'Kapcsolat(ok) törlése...';
+$messages['groupdeleting'] = 'Csoport törlése...';
 $messages['folderdeleting'] = 'Mappa törlése...';
 $messages['foldermoving'] = 'Mappa mozgatása...';
 $messages['foldersubscribing'] = 'Feliratkozás a mappára...';
 $messages['folderdeleting'] = 'Mappa törlése...';
 $messages['foldermoving'] = 'Mappa mozgatása...';
 $messages['foldersubscribing'] = 'Feliratkozás a mappára...';
@@ -75,17 +81,17 @@ $messages['nosubjectwarning'] = 'A Tárgy mező üres. Szeretné most kitölteni
 $messages['nobodywarning'] = 'Elküldi az üzenetet üresen?';
 $messages['notsentwarning'] = 'Az üzenet még nem lett elküldve. Eldobja az üzenetet?';
 $messages['noldapserver'] = 'Adjon meg egy LDAP szervert a kereséshez';
 $messages['nobodywarning'] = 'Elküldi az üzenetet üresen?';
 $messages['notsentwarning'] = 'Az üzenet még nem lett elküldve. Eldobja az üzenetet?';
 $messages['noldapserver'] = 'Adjon meg egy LDAP szervert a kereséshez';
-$messages['nocontactsreturned'] = 'Nem található kapcsolat';
 $messages['nosearchname'] = 'Adja meg a kapcsolat nevét vagy e-mail címét';
 $messages['notuploadedwarning'] = 'Még nem került feltöltésre minden csatolmány. Kérem várjon vagy állítsa le a feltöltést!';
 $messages['searchsuccessful'] = '$nr üzenet található';
 $messages['nosearchname'] = 'Adja meg a kapcsolat nevét vagy e-mail címét';
 $messages['notuploadedwarning'] = 'Még nem került feltöltésre minden csatolmány. Kérem várjon vagy állítsa le a feltöltést!';
 $messages['searchsuccessful'] = '$nr üzenet található';
+$messages['contactsearchsuccessful'] = '$nr találat';
 $messages['searchnomatch'] = 'Nincs találat';
 $messages['searching'] = 'Keresés...';
 $messages['checking'] = 'Ellenőrzés...';
 $messages['nospellerrors'] = 'Nem található helyesírási hiba';
 $messages['folderdeleted'] = 'A mappa sikeresen törölve';
 $messages['searchnomatch'] = 'Nincs találat';
 $messages['searching'] = 'Keresés...';
 $messages['checking'] = 'Ellenőrzés...';
 $messages['nospellerrors'] = 'Nem található helyesírási hiba';
 $messages['folderdeleted'] = 'A mappa sikeresen törölve';
-$messages['foldersubscribed'] = 'A feliratkozás a mappára sikeres';
-$messages['folderunsubscribed'] = 'A leiratkozás a mappáról sikeres';
+$messages['foldersubscribed'] = 'Sikerült a mappára feliratkozni';
+$messages['folderunsubscribed'] = 'Sikerült a mappáról leiratkozni';
 $messages['folderpurged'] = 'Mappa sikeresen törölve';
 $messages['folderexpunged'] = 'Mappa sikeresen kiürítve';
 $messages['deletedsuccessfully'] = 'Törölve';
 $messages['folderpurged'] = 'Mappa sikeresen törölve';
 $messages['folderexpunged'] = 'Mappa sikeresen kiürítve';
 $messages['deletedsuccessfully'] = 'Törölve';
@@ -99,11 +105,14 @@ $messages['sourceisreadonly'] = 'Ez a címforrás csak olvasható';
 $messages['errorsavingcontact'] = 'A kapcsolat címe nem menthető';
 $messages['movingmessage'] = 'Üzenet(ek) mozgatása...';
 $messages['copyingmessage'] = 'Üzenet(ek) másolása...';
 $messages['errorsavingcontact'] = 'A kapcsolat címe nem menthető';
 $messages['movingmessage'] = 'Üzenet(ek) mozgatása...';
 $messages['copyingmessage'] = 'Üzenet(ek) másolása...';
+$messages['copyingcontact'] = 'Kapcsolat(ok) másolása...';
 $messages['deletingmessage'] = 'Üzenet(ek) törlése....';
 $messages['markingmessage'] = 'Üzenet(ek) megjelölése...';
 $messages['deletingmessage'] = 'Üzenet(ek) törlése....';
 $messages['markingmessage'] = 'Üzenet(ek) megjelölése...';
+$messages['addingmember'] = 'Kapcsolat(ok) hozzáadása a csoporthoz...';
+$messages['removingmember'] = 'Kapcsolat(ok) törlése a csoportból...';
 $messages['receiptsent'] = 'Az olvasási visszaigazolás el lett küldve';
 $messages['errorsendingreceipt'] = 'Az olvasási visszaigazolást nem sikerült elküldeni';
 $messages['receiptsent'] = 'Az olvasási visszaigazolás el lett küldve';
 $messages['errorsendingreceipt'] = 'Az olvasási visszaigazolást nem sikerült elküldeni';
-$messages['nodeletelastidentity'] = 'Nem törölheti ezt az azonosítót, ez az egyetlen';
+$messages['nodeletelastidentity'] = 'Az azonosító nem törölhető, lennie kell legalább egy azonosítónak!';
 $messages['forbiddencharacter'] = 'A mappa neve tiltott karaktert tartalmaz';
 $messages['selectimportfile'] = 'Kérjük válassza ki a feltölteni kívánt fájlt';
 $messages['addresswriterror'] = 'A kiválasztott címjegyzék nem írható';
 $messages['forbiddencharacter'] = 'A mappa neve tiltott karaktert tartalmaz';
 $messages['selectimportfile'] = 'Kérjük válassza ki a feltölteni kívánt fájlt';
 $messages['addresswriterror'] = 'A kiválasztott címjegyzék nem írható';
@@ -114,7 +123,7 @@ $messages['importerror'] = 'Az importálás sikertelen! A feltöltött állomán
 $messages['importconfirm'] = '<b>Sikeresen importálásra került $inserted kapcsolat, kihagyva $skipped már létező bejegyzés</b>:<p><em>$names</em></p>';
 $messages['importconfirmskipped'] = '<b>Kihagyva $skipped már létező bejegyzés</b>';
 $messages['opnotpermitted'] = 'A művelet nem megengedett!';
 $messages['importconfirm'] = '<b>Sikeresen importálásra került $inserted kapcsolat, kihagyva $skipped már létező bejegyzés</b>:<p><em>$names</em></p>';
 $messages['importconfirmskipped'] = '<b>Kihagyva $skipped már létező bejegyzés</b>';
 $messages['opnotpermitted'] = 'A művelet nem megengedett!';
-$messages['nofromaddress'] = 'Hiányzó e-mail cím a kiválasztott feladónál';
+$messages['nofromaddress'] = 'A kiválasztott feladónál hiányzik az e-mail cím!';
 $messages['editorwarning'] = 'Az egyszerű szöveges formátumra való váltás az összes formázás elvesztésével jár. Biztosan folytatja?';
 $messages['httpreceivedencrypterror'] = 'Végzetes konfigurációs hiba történt, azonnal lépjen kapcsolatba az üzemeltetővel. <b>Az üzenet nem küldhető el.</b>';
 $messages['smtpconnerror'] = 'SMTP hiba ($code): Sikertelen kapcsolódás a szerverhez';
 $messages['editorwarning'] = 'Az egyszerű szöveges formátumra való váltás az összes formázás elvesztésével jár. Biztosan folytatja?';
 $messages['httpreceivedencrypterror'] = 'Végzetes konfigurációs hiba történt, azonnal lépjen kapcsolatba az üzemeltetővel. <b>Az üzenet nem küldhető el.</b>';
 $messages['smtpconnerror'] = 'SMTP hiba ($code): Sikertelen kapcsolódás a szerverhez';
@@ -122,27 +131,34 @@ $messages['smtpautherror'] = 'SMTP hiba ($code): Sikertelen bejelentkezés';
 $messages['smtpfromerror'] = 'SMTP hiba ($code): Nem sikerült a feladó beállítása: "$from" ($msg)';
 $messages['smtptoerror'] = 'SMTP hiba ($code): Nem sikerült a következő címzett hozzáadása: "$to" ($msg)';
 $messages['smtprecipientserror'] = 'SMTP hiba ($code): A címzettlista feldolgozása sikertelen';
 $messages['smtpfromerror'] = 'SMTP hiba ($code): Nem sikerült a feladó beállítása: "$from" ($msg)';
 $messages['smtptoerror'] = 'SMTP hiba ($code): Nem sikerült a következő címzett hozzáadása: "$to" ($msg)';
 $messages['smtprecipientserror'] = 'SMTP hiba ($code): A címzettlista feldolgozása sikertelen';
-$messages['smtpdsnerror'] = 'SMTP hiba: A kézbesítési visszaigazolásokat a szerver nem támogatja';
 $messages['smtperror'] = 'SMTP hiba ($code): $msg';
 $messages['emailformaterror'] = 'Helytelen formátumú e-mail cím: $email';
 $messages['smtperror'] = 'SMTP hiba ($code): $msg';
 $messages['emailformaterror'] = 'Helytelen formátumú e-mail cím: $email';
-$messages['toomanyrecipients'] = 'Túl sok a címzett. Csökkentse a címzettek számát $max címre.';
-$messages['maxgroupmembersreached'] = 'A csoport létszáma meghaladja a maximum $max értéket';
+$messages['toomanyrecipients'] = 'Túl sok a címzett. Csökkentse a címzettek számát maximum $max címre!';
+$messages['maxgroupmembersreached'] = 'A csoport létszáma meghaladja a maximum $max t';
 $messages['internalerror'] = 'Belső hiba történt, kérjük próbálja újra!';
 $messages['contactdelerror'] = 'Hiba a kapcsolat(ok) törlésekor';
 $messages['contactdeleted'] = 'Kapcsolat(ok) sikeresen törölve';
 $messages['internalerror'] = 'Belső hiba történt, kérjük próbálja újra!';
 $messages['contactdelerror'] = 'Hiba a kapcsolat(ok) törlésekor';
 $messages['contactdeleted'] = 'Kapcsolat(ok) sikeresen törölve';
+$messages['contactrestoreerror'] = 'Nem sikerült a törölt kapcsolat(ok) helyreállítása';
+$messages['contactrestored'] = 'Kapcsolat(ok) sikeresen helyreállítva';
 $messages['groupdeleted'] = 'Csoport sikeresen törölve';
 $messages['grouprenamed'] = 'Csoport sikeresen átnevezve';
 $messages['groupcreated'] = 'Csoport sikeresen létrehozva';
 $messages['groupdeleted'] = 'Csoport sikeresen törölve';
 $messages['grouprenamed'] = 'Csoport sikeresen átnevezve';
 $messages['groupcreated'] = 'Csoport sikeresen létrehozva';
+$messages['savedsearchdeleted'] = 'Mentett keresés sikeresen törölve';
+$messages['savedsearchdeleteerror'] = 'Nem sikerült törölni a mentett keresést';
+$messages['savedsearchcreated'] = 'Keresés sikeresen mentve';
+$messages['savedsearchcreateerror'] = 'Nem sikerült létrehozni mentett keresést';
 $messages['messagedeleted'] = 'Üzenet(ek) sikeresen törölve';
 $messages['messagemoved'] = 'Üzenet(ek) sikeresen átmozgatva';
 $messages['messagecopied'] = 'Üzenet(ek) sikeresen másolva';
 $messages['messagemarked'] = 'Üzenet(ek) sikeresen megjelölve';
 $messages['autocompletechars'] = 'Az automatikus kiegészítéshez legalább $min karakter szükséges';
 $messages['messagedeleted'] = 'Üzenet(ek) sikeresen törölve';
 $messages['messagemoved'] = 'Üzenet(ek) sikeresen átmozgatva';
 $messages['messagecopied'] = 'Üzenet(ek) sikeresen másolva';
 $messages['messagemarked'] = 'Üzenet(ek) sikeresen megjelölve';
 $messages['autocompletechars'] = 'Az automatikus kiegészítéshez legalább $min karakter szükséges';
+$messages['autocompletemore'] = 'Több egyezés található. Kérem adjon meg további karaktereket!';
 $messages['namecannotbeempty'] = 'A név nem lehet üres';
 $messages['nametoolong'] = 'A név túl hosszú';
 $messages['folderupdated'] = 'Mappa sikeresen frissítve';
 $messages['foldercreated'] = 'Mappa sikeresen létrehozva';
 $messages['invalidimageformat'] = 'Érvénytelen képformátum';
 $messages['mispellingsfound'] = 'Az üzenetben helyesírási hibák találhatók';
 $messages['namecannotbeempty'] = 'A név nem lehet üres';
 $messages['nametoolong'] = 'A név túl hosszú';
 $messages['folderupdated'] = 'Mappa sikeresen frissítve';
 $messages['foldercreated'] = 'Mappa sikeresen létrehozva';
 $messages['invalidimageformat'] = 'Érvénytelen képformátum';
 $messages['mispellingsfound'] = 'Az üzenetben helyesírási hibák találhatók';
+$messages['parentnotwritable'] = 'Nem sikerült a mappa létrehozása/mozgatása a kijelölt mappába. Nincs jogosultsága a művelethez!';
 
 ?>
 
 ?>
index c16a1ca464bbb9e6e687a8ab2c326a9726a0d6b5..bf1f25269433ae3f1ab99bef7e478c264a619639 100644 (file)
@@ -13,7 +13,7 @@
 | Author: Putu Arya Sabda Wijaya <ptaryasw@isi-dps.ac.id>                    |
 +-----------------------------------------------------------------------+
 
 | Author: Putu Arya Sabda Wijaya <ptaryasw@isi-dps.ac.id>                    |
 +-----------------------------------------------------------------------+
 
-@version $Id: messages.inc 4748 2011-05-11 13:17:43Z yllar $
+@version $Id: messages.inc 5139 2011-08-28 09:47:15Z alec $
 
 */
 
 
 */
 
@@ -24,7 +24,7 @@ $messages['sessionerror'] = 'Session Anda invalid atau kadaluwarsa';
 $messages['imaperror'] = 'Koneksi ke IMAP server gagal';
 $messages['servererror'] = 'Server Error!';
 $messages['servererrormsg'] = 'Server Error: $msg';
 $messages['imaperror'] = 'Koneksi ke IMAP server gagal';
 $messages['servererror'] = 'Server Error!';
 $messages['servererrormsg'] = 'Server Error: $msg';
-$messages['databaserror'] = 'Basis data Error!';
+$messages['dberror'] = 'Basis data Error!';
 $messages['errorreadonly'] = 'Tidak bisa melakukan operasi. Folder hanya bisa dibaca';
 $messages['errornoperm'] = 'Tidak bisa melakukan operasi. Ijin ditolak';
 $messages['invalidrequest'] = 'Permintaan tidak valid! Tidak ada data yang tersimpan.';
 $messages['errorreadonly'] = 'Tidak bisa melakukan operasi. Folder hanya bisa dibaca';
 $messages['errornoperm'] = 'Tidak bisa melakukan operasi. Ijin ditolak';
 $messages['invalidrequest'] = 'Permintaan tidak valid! Tidak ada data yang tersimpan.';
index 74da7e50520af2bdd14d81b01ceb445ae64e9b56..52950a38d743153bab1060b83273d90fb00f8e3e 100644 (file)
@@ -14,7 +14,7 @@
 |         Yusef Maali <contact@yusefmaali.net>                          |
 +-----------------------------------------------------------------------+
 
 |         Yusef Maali <contact@yusefmaali.net>                          |
 +-----------------------------------------------------------------------+
 
-@version $Id: labels.inc 5175 2011-09-05 18:42:24Z thomasb $
+@version $Id: labels.inc 5569 2011-12-07 14:47:32Z thomasb $
 
 */
 
 
 */
 
@@ -118,7 +118,7 @@ $labels['markread'] = 'Letti';
 $labels['markunread'] = 'Non letti';
 $labels['markflagged'] = 'Contrassegnato';
 $labels['markunflagged'] = 'Non contrassegnato';
 $labels['markunread'] = 'Non letti';
 $labels['markflagged'] = 'Contrassegnato';
 $labels['markunflagged'] = 'Non contrassegnato';
-$labels['messageactions'] = 'Altre azioni...';
+$labels['moreactions'] = 'Altre operazioni...';
 $labels['select'] = 'Seleziona';
 $labels['all'] = 'Tutti';
 $labels['none'] = 'Nessuno';
 $labels['select'] = 'Seleziona';
 $labels['all'] = 'Tutti';
 $labels['none'] = 'Nessuno';
@@ -150,7 +150,7 @@ $labels['listcolumns'] = 'Elenco Colonne';
 $labels['listsorting'] = 'Ordina per';
 $labels['listorder'] = 'Ordinamento';
 $labels['listmode'] = 'Modalità di visualizzazione';
 $labels['listsorting'] = 'Ordina per';
 $labels['listorder'] = 'Ordinamento';
 $labels['listmode'] = 'Modalità di visualizzazione';
-$labels['folderactions'] = 'Azione cartella';
+$labels['folderactions'] = 'Operazioni cartella';
 $labels['compact'] = 'Compatta';
 $labels['empty'] = 'Svuota';
 $labels['quota'] = 'Spazio utilizzato';
 $labels['compact'] = 'Compatta';
 $labels['empty'] = 'Svuota';
 $labels['quota'] = 'Spazio utilizzato';
@@ -172,6 +172,7 @@ $labels['editortype'] = 'Tipo editor';
 $labels['returnreceipt'] = 'Ricevuta di ritorno';
 $labels['dsn'] = 'Notifica di consegna';
 $labels['mailreplyintro'] = 'Il $date $sender ha scritto:';
 $labels['returnreceipt'] = 'Ricevuta di ritorno';
 $labels['dsn'] = 'Notifica di consegna';
 $labels['mailreplyintro'] = 'Il $date $sender ha scritto:';
+$labels['originalmessage'] = 'Messaggio originale';
 $labels['editidents'] = 'Modifica indentità';
 $labels['checkspelling'] = 'Controlla ortografia';
 $labels['resumeediting'] = 'Torna al messaggio';
 $labels['editidents'] = 'Modifica indentità';
 $labels['checkspelling'] = 'Controlla ortografia';
 $labels['resumeediting'] = 'Torna al messaggio';
@@ -189,6 +190,7 @@ $labels['highest'] = 'Molto alta';
 $labels['nosubject'] = '(nessun oggetto)';
 $labels['showimages'] = 'Visualizza immagini';
 $labels['alwaysshow'] = 'Mostra sempre immagini da $sender';
 $labels['nosubject'] = '(nessun oggetto)';
 $labels['showimages'] = 'Visualizza immagini';
 $labels['alwaysshow'] = 'Mostra sempre immagini da $sender';
+$labels['isdraft'] = 'Questa è una bozza.';
 $labels['htmltoggle'] = 'HTML';
 $labels['plaintoggle'] = 'Testo semplice';
 $labels['savesentmessagein'] = 'Salva i messaggi inviati in';
 $labels['htmltoggle'] = 'HTML';
 $labels['plaintoggle'] = 'Testo semplice';
 $labels['savesentmessagein'] = 'Salva i messaggi inviati in';
@@ -247,6 +249,8 @@ $labels['typepager'] = 'Teledrin';
 $labels['typevideo'] = 'Video';
 $labels['typeassistant'] = 'Assistente';
 $labels['typehomepage'] = 'Home page';
 $labels['typevideo'] = 'Video';
 $labels['typeassistant'] = 'Assistente';
 $labels['typehomepage'] = 'Home page';
+$labels['typeblog'] = 'Blog';
+$labels['typeprofile'] = 'Profilo';
 $labels['addfield'] = 'Aggiungi campo...';
 $labels['addcontact'] = 'Aggiungi contatto alla rubrica';
 $labels['editcontact'] = 'Modifica contatto';
 $labels['addfield'] = 'Aggiungi campo...';
 $labels['addcontact'] = 'Aggiungi contatto alla rubrica';
 $labels['editcontact'] = 'Modifica contatto';
@@ -268,7 +272,6 @@ $labels['print'] = 'Stampa';
 $labels['export'] = 'Esporta';
 $labels['exportvcards'] = 'Esporta i contatti in formato vCard';
 $labels['newcontactgroup'] = 'Crea un nuovo gruppo';
 $labels['export'] = 'Esporta';
 $labels['exportvcards'] = 'Esporta i contatti in formato vCard';
 $labels['newcontactgroup'] = 'Crea un nuovo gruppo';
-$labels['groupactions'] = 'Azioni per i gruppi';
 $labels['grouprename'] = 'Rinomina il gruppo';
 $labels['groupdelete'] = 'Cancella il gruppo';
 $labels['previouspage'] = 'Pagina precedente';
 $labels['grouprename'] = 'Rinomina il gruppo';
 $labels['groupdelete'] = 'Cancella il gruppo';
 $labels['previouspage'] = 'Pagina precedente';
@@ -278,6 +281,8 @@ $labels['lastpage'] = 'Ultima pagina';
 $labels['group'] = 'Gruppo';
 $labels['groups'] = 'Gruppi';
 $labels['personaladrbook'] = 'Rubrica Personale';
 $labels['group'] = 'Gruppo';
 $labels['groups'] = 'Gruppi';
 $labels['personaladrbook'] = 'Rubrica Personale';
+$labels['searchsave'] = 'Salva ricerca';
+$labels['searchdelete'] = 'Elimina ricerca';
 $labels['import'] = 'Importa';
 $labels['importcontacts'] = 'Importa contatti';
 $labels['importfromfile'] = 'Importa da file:';
 $labels['import'] = 'Importa';
 $labels['importcontacts'] = 'Importa contatti';
 $labels['importfromfile'] = 'Importa da file:';
@@ -286,6 +291,7 @@ $labels['importreplace'] = 'Sostituisci l\'intera rubrica';
 $labels['importtext'] = 'Puoi caricare i contatti da una rubrica esistente. Al momento è supportata l\'importazione dei contatti dal formato vCard.';
 $labels['done'] = 'Fatto';
 $labels['settingsfor'] = 'Impostazioni per ';
 $labels['importtext'] = 'Puoi caricare i contatti da una rubrica esistente. Al momento è supportata l\'importazione dei contatti dal formato vCard.';
 $labels['done'] = 'Fatto';
 $labels['settingsfor'] = 'Impostazioni per ';
+$labels['about'] = 'Informazioni';
 $labels['preferences'] = 'Preferenze';
 $labels['userpreferences'] = 'Preferenze utente';
 $labels['editpreferences'] = 'Modifica le preferenze per l\'utente';
 $labels['preferences'] = 'Preferenze';
 $labels['userpreferences'] = 'Preferenze utente';
 $labels['editpreferences'] = 'Modifica le preferenze per l\'utente';
@@ -297,6 +303,8 @@ $labels['edititem'] = 'Modifica elemento';
 $labels['preferhtml'] = 'Mostra HTML';
 $labels['defaultcharset'] = 'Set di caratteri predefinito';
 $labels['htmlmessage'] = 'Messaggio HTML';
 $labels['preferhtml'] = 'Mostra HTML';
 $labels['defaultcharset'] = 'Set di caratteri predefinito';
 $labels['htmlmessage'] = 'Messaggio HTML';
+$labels['dateformat'] = 'Formato data';
+$labels['timeformat'] = 'Formato orario';
 $labels['prettydate'] = 'Date più leggibili';
 $labels['setdefault'] = 'Imposta predefinita';
 $labels['autodetect'] = 'Auto';
 $labels['prettydate'] = 'Date più leggibili';
 $labels['setdefault'] = 'Imposta predefinita';
 $labels['autodetect'] = 'Auto';
@@ -368,7 +376,13 @@ $labels['reqmdn'] = 'Richiedi sempre la ricevuta di ritorno';
 $labels['reqdsn'] = 'Richiedi sempre la notifica di consegna';
 $labels['replysamefolder'] = 'Salva risposta nella cartella del messaggio a cui si risponde';
 $labels['defaultaddressbook'] = 'Aggiungi nuovi contatti alla rubrica selezionata';
 $labels['reqdsn'] = 'Richiedi sempre la notifica di consegna';
 $labels['replysamefolder'] = 'Salva risposta nella cartella del messaggio a cui si risponde';
 $labels['defaultaddressbook'] = 'Aggiungi nuovi contatti alla rubrica selezionata';
+$labels['autocompletesingle'] = 'Non considerare gli indirizzi secondari nell\'autocompletamento';
 $labels['spellcheckbeforesend'] = 'Esegui il controllo ortografico prima di inviare un messaggio';
 $labels['spellcheckbeforesend'] = 'Esegui il controllo ortografico prima di inviare un messaggio';
+$labels['spellcheckoptions'] = 'Opzioni controllo ortografico';
+$labels['spellcheckignoresyms'] = 'Ignora le parole contenenti simboli';
+$labels['spellcheckignorenums'] = 'Ignora le parole contenenti numeri';
+$labels['spellcheckignorecaps'] = 'Ignora le parole con tutte le lettere maiuscole';
+$labels['addtodict'] = 'Aggiungi al dizionario';
 $labels['folder'] = 'Cartella';
 $labels['folders'] = 'Cartelle';
 $labels['foldername'] = 'Nome cartella';
 $labels['folder'] = 'Cartella';
 $labels['folders'] = 'Cartelle';
 $labels['foldername'] = 'Nome cartella';
@@ -393,6 +407,11 @@ $labels['sortby'] = 'Ordina per';
 $labels['sortasc'] = 'Ordinamento crescente';
 $labels['sortdesc'] = 'Ordinamento decrescente';
 $labels['undo'] = 'Annulla';
 $labels['sortasc'] = 'Ordinamento crescente';
 $labels['sortdesc'] = 'Ordinamento decrescente';
 $labels['undo'] = 'Annulla';
+$labels['plugin'] = 'Plugin';
+$labels['version'] = 'Versione';
+$labels['source'] = 'Sorgente';
+$labels['license'] = 'Licenza';
+$labels['support'] = 'Ottieni supporto';
 $labels['B'] = 'B';
 $labels['KB'] = 'KB';
 $labels['MB'] = 'MB';
 $labels['B'] = 'B';
 $labels['KB'] = 'KB';
 $labels['MB'] = 'MB';
index 8e2c118e95e4fda270119eaafd3eff0912bbd353..bafcbb073206729f3fb1dd9ec70f8c46fda0ba68 100644 (file)
@@ -14,7 +14,7 @@
 |         Yusef Maali <contact@yusefmaali.net>                          |
 +-----------------------------------------------------------------------+
 
 |         Yusef Maali <contact@yusefmaali.net>                          |
 +-----------------------------------------------------------------------+
 
-@version $Id: messages.inc 5175 2011-09-05 18:42:24Z thomasb $
+@version $Id: messages.inc 5569 2011-12-07 14:47:32Z thomasb $
 
 */
 
 
 */
 
@@ -25,7 +25,7 @@ $messages['sessionerror'] = 'Sessione non valida o scaduta';
 $messages['imaperror'] = 'Impossibile connettersi al server IMAP';
 $messages['servererror'] = 'Errore del server!';
 $messages['servererrormsg'] = 'Errore del server: $msg';
 $messages['imaperror'] = 'Impossibile connettersi al server IMAP';
 $messages['servererror'] = 'Errore del server!';
 $messages['servererrormsg'] = 'Errore del server: $msg';
-$messages['databaserror'] = 'Errore del database!';
+$messages['dberror'] = 'Errore del database!';
 $messages['errorreadonly'] = 'Impossibile eseguire l\'operazione. Cartella in sola lettura';
 $messages['errornoperm'] = 'Impossibile eseguire l\'operazione. Permesso negato';
 $messages['invalidrequest'] = 'Richiesta non valida! Nessun dato salvato.';
 $messages['errorreadonly'] = 'Impossibile eseguire l\'operazione. Cartella in sola lettura';
 $messages['errornoperm'] = 'Impossibile eseguire l\'operazione. Permesso negato';
 $messages['invalidrequest'] = 'Richiesta non valida! Nessun dato salvato.';
@@ -49,6 +49,7 @@ $messages['blockedimages'] = 'Per proteggere la tua privacy, le immagini remote
 $messages['encryptedmessage'] = 'Questo messaggio é cifrato e non può essere visualizzato. Spiacenti!';
 $messages['nocontactsfound'] = 'Nessun contatto trovato';
 $messages['contactnotfound'] = 'Il contatto richiesto non è stato trovato';
 $messages['encryptedmessage'] = 'Questo messaggio é cifrato e non può essere visualizzato. Spiacenti!';
 $messages['nocontactsfound'] = 'Nessun contatto trovato';
 $messages['contactnotfound'] = 'Il contatto richiesto non è stato trovato';
+$messages['contactsearchonly'] = 'Inserisci dei termini per cercare i contatti';
 $messages['sendingfailed'] = 'Impossibile inviare il messaggio';
 $messages['senttooquickly'] = 'Per favore, attendi $sec secondi prima di inviare questo messaggio';
 $messages['errorsavingsent'] = 'C\'è stato un errore nel salvare il messaggio inviato';
 $messages['sendingfailed'] = 'Impossibile inviare il messaggio';
 $messages['senttooquickly'] = 'Per favore, attendi $sec secondi prima di inviare questo messaggio';
 $messages['errorsavingsent'] = 'C\'è stato un errore nel salvare il messaggio inviato';
@@ -62,6 +63,7 @@ $messages['deletegroupconfirm'] = 'Sei sicuro di voler eliminare i gruppi selezi
 $messages['deletemessagesconfirm'] = 'Sei sicuro di voler eliminare i messaggi selezionati?';
 $messages['deletefolderconfirm'] = 'Sei sicuro di voler eliminare la cartella selezionata?';
 $messages['purgefolderconfirm'] = 'Sei sicuro di voler eliminare tutti i messaggi in questa cartella?';
 $messages['deletemessagesconfirm'] = 'Sei sicuro di voler eliminare i messaggi selezionati?';
 $messages['deletefolderconfirm'] = 'Sei sicuro di voler eliminare la cartella selezionata?';
 $messages['purgefolderconfirm'] = 'Sei sicuro di voler eliminare tutti i messaggi in questa cartella?';
+$messages['contactdeleting'] = 'Eliminazione contatti...';
 $messages['groupdeleting'] = 'Eliminazione gruppo...';
 $messages['folderdeleting'] = 'Eliminazione cartella...';
 $messages['foldermoving'] = 'Spostamento cartella...';
 $messages['groupdeleting'] = 'Eliminazione gruppo...';
 $messages['folderdeleting'] = 'Eliminazione cartella...';
 $messages['foldermoving'] = 'Spostamento cartella...';
@@ -77,10 +79,10 @@ $messages['nosubjectwarning'] = 'L\'oggetto è vuoto. Vuoi inserirlo adesso?';
 $messages['nobodywarning'] = 'Inviare il messaggio senza testo?';
 $messages['notsentwarning'] = 'Il messaggio non è stato inviato. Vuoi annullare questo messaggio?';
 $messages['noldapserver'] = 'Per favore, scegli un server LDAP in cui ricercare';
 $messages['nobodywarning'] = 'Inviare il messaggio senza testo?';
 $messages['notsentwarning'] = 'Il messaggio non è stato inviato. Vuoi annullare questo messaggio?';
 $messages['noldapserver'] = 'Per favore, scegli un server LDAP in cui ricercare';
-$messages['nocontactsreturned'] = 'Nessun contatto trovato';
 $messages['nosearchname'] = 'Per favore, immetti un nome o un indirizzo e-mail';
 $messages['notuploadedwarning'] = 'Non tutti gli allegati sono stati ancora caricati. Prego attendere, oppure cancellare il caricamento.';
 $messages['searchsuccessful'] = '$nr messaggi trovati';
 $messages['nosearchname'] = 'Per favore, immetti un nome o un indirizzo e-mail';
 $messages['notuploadedwarning'] = 'Non tutti gli allegati sono stati ancora caricati. Prego attendere, oppure cancellare il caricamento.';
 $messages['searchsuccessful'] = '$nr messaggi trovati';
+$messages['contactsearchsuccessful'] = '$nr contatti trovati';
 $messages['searchnomatch'] = 'La ricerca non ha dato nessun risultato';
 $messages['searching'] = 'Ricerca...';
 $messages['checking'] = 'Controllo...';
 $messages['searchnomatch'] = 'La ricerca non ha dato nessun risultato';
 $messages['searching'] = 'Ricerca...';
 $messages['checking'] = 'Controllo...';
@@ -127,7 +129,6 @@ $messages['smtpautherror'] = 'Errore SMTP ($code): Autenticazione fallita';
 $messages['smtpfromerror'] = 'Errore SMTP ($code): Fallita l\'impostazione del mittente "$from" ($msg)';
 $messages['smtptoerror'] = 'Errore SMTP ($code): Fallito l\'inserimento del destinatario "$to" ($msg)';
 $messages['smtprecipientserror'] = 'Errore SMTP: Impossibile processare la lista dei destinatari';
 $messages['smtpfromerror'] = 'Errore SMTP ($code): Fallita l\'impostazione del mittente "$from" ($msg)';
 $messages['smtptoerror'] = 'Errore SMTP ($code): Fallito l\'inserimento del destinatario "$to" ($msg)';
 $messages['smtprecipientserror'] = 'Errore SMTP: Impossibile processare la lista dei destinatari';
-$messages['smtpdsnerror'] = 'Errore SMTP: Ricevuta di consegna non supportata';
 $messages['smtperror'] = 'Errore SMTP: $msg';
 $messages['emailformaterror'] = 'Indirizzo e-mail non corretto: $email';
 $messages['toomanyrecipients'] = 'Numero eccessivo di destinatari, ridurlo a $max';
 $messages['smtperror'] = 'Errore SMTP: $msg';
 $messages['emailformaterror'] = 'Indirizzo e-mail non corretto: $email';
 $messages['toomanyrecipients'] = 'Numero eccessivo di destinatari, ridurlo a $max';
@@ -140,11 +141,16 @@ $messages['contactrestored'] = 'Contatto/i ripristinato/i';
 $messages['groupdeleted'] = 'Gruppo correttamente eliminato';
 $messages['grouprenamed'] = 'Gruppo correttamente rinominato';
 $messages['groupcreated'] = 'Gruppo creato correttamente';
 $messages['groupdeleted'] = 'Gruppo correttamente eliminato';
 $messages['grouprenamed'] = 'Gruppo correttamente rinominato';
 $messages['groupcreated'] = 'Gruppo creato correttamente';
+$messages['savedsearchdeleted'] = 'Le ricerca salvata è stata eliminata con successo.';
+$messages['savedsearchdeleteerror'] = 'Impossibile eliminare la ricerca salvata.';
+$messages['savedsearchcreated'] = 'Ricerca salvata creata con successo.';
+$messages['savedsearchcreateerror'] = 'Impossibile creare la ricerca salvata.';
 $messages['messagedeleted'] = 'Messaggi/o cancellato correttamente';
 $messages['messagemoved'] = 'Messaggi/o spostato correttamente';
 $messages['messagecopied'] = 'Messaggi/o copiato correttamente';
 $messages['messagemarked'] = 'Messaggi/o marcato correttamente';
 $messages['autocompletechars'] = 'Inserisci almeno $min caratteri per l\'autocompletamento';
 $messages['messagedeleted'] = 'Messaggi/o cancellato correttamente';
 $messages['messagemoved'] = 'Messaggi/o spostato correttamente';
 $messages['messagecopied'] = 'Messaggi/o copiato correttamente';
 $messages['messagemarked'] = 'Messaggi/o marcato correttamente';
 $messages['autocompletechars'] = 'Inserisci almeno $min caratteri per l\'autocompletamento';
+$messages['autocompletemore'] = 'Più risultati ottenuti. Inserisci per favore più caratteri.';
 $messages['namecannotbeempty'] = 'Il nome non può essere vuoto';
 $messages['nametoolong'] = 'Nome troppo lungo';
 $messages['folderupdated'] = 'Cartella aggiornata correttamente';
 $messages['namecannotbeempty'] = 'Il nome non può essere vuoto';
 $messages['nametoolong'] = 'Nome troppo lungo';
 $messages['folderupdated'] = 'Cartella aggiornata correttamente';
@@ -152,5 +158,6 @@ $messages['foldercreated'] = 'Cartella creata correttamente';
 $messages['invalidimageformat'] = 'Formato immagine non valido';
 $messages['mispellingsfound'] = 'Sono stati riscontrati errori ortografici nel messaggio';
 $messages['parentnotwritable'] = 'Impossibile creare o muovere la cartella: accesso negato';
 $messages['invalidimageformat'] = 'Formato immagine non valido';
 $messages['mispellingsfound'] = 'Sono stati riscontrati errori ortografici nel messaggio';
 $messages['parentnotwritable'] = 'Impossibile creare o muovere la cartella: accesso negato';
+$messages['messagetoobig'] = 'La parte del messaggio è troppo grande per essere processata.';
 
 ?>
 
 ?>
index 5a3f3ec3ca4228a79984b8745733666ca58e31d1..f9e854830245904032caade1edec0146f3966c2d 100644 (file)
@@ -14,9 +14,9 @@
 |         Takashi Takamatsu <taka717@gmail.com>                         |
 +-----------------------------------------------------------------------+
 
 |         Takashi Takamatsu <taka717@gmail.com>                         |
 +-----------------------------------------------------------------------+
 
-@version $Id: labels.inc 5291 2011-09-28 17:10:45Z thomasb $
+@version $Id: labels.inc 5569 2011-12-07 14:47:32Z thomasb $
 
 
-EN-Revision: 5210
+EN-Revision: 5490
 
 */
 
 
 */
 
@@ -154,7 +154,6 @@ $labels['unanswered'] = '未返信';
 $labels['deleted'] = '削除済み';
 $labels['invert'] = '反転';
 $labels['filter'] = 'フィルター';
 $labels['deleted'] = '削除済み';
 $labels['invert'] = '反転';
 $labels['filter'] = 'フィルター';
-
 $labels['list'] = '一覧';
 $labels['threads'] = 'スレッド';
 $labels['expand-all'] = 'すべて展開';
 $labels['list'] = '一覧';
 $labels['threads'] = 'スレッド';
 $labels['expand-all'] = 'すべて展開';
@@ -227,6 +226,7 @@ $labels['highest'] = '最高';
 $labels['nosubject'] = '(件名なし)';
 $labels['showimages'] = '画像の表示';
 $labels['alwaysshow'] = '$sender から届いた画像は常に表示';
 $labels['nosubject'] = '(件名なし)';
 $labels['showimages'] = '画像の表示';
 $labels['alwaysshow'] = '$sender から届いた画像は常に表示';
+$labels['isdraft']    = 'これは下書きのメッセージです。';
 
 $labels['htmltoggle'] = 'HTML';
 $labels['plaintoggle'] = 'テキスト';
 
 $labels['htmltoggle'] = 'HTML';
 $labels['plaintoggle'] = 'テキスト';
@@ -344,7 +344,7 @@ $labels['done'] = '完了';
 
 // settings
 $labels['settingsfor']  = '次の設定:';
 
 // settings
 $labels['settingsfor']  = '次の設定:';
-
+$labels['about'] = 'Roundcube Webmail について';
 $labels['preferences']  = '設定';
 $labels['userpreferences']  = 'ユーザー設定';
 $labels['editpreferences']  = 'ユーザー設定の変更';
 $labels['preferences']  = '設定';
 $labels['userpreferences']  = 'ユーザー設定';
 $labels['editpreferences']  = 'ユーザー設定の変更';
@@ -432,6 +432,7 @@ $labels['reqmdn'] = '常に開封確認通知を要求する';
 $labels['reqdsn'] = '常に配送状況の通知を要求する';
 $labels['replysamefolder'] = '返信されたメールを返信元メールと同じフォルダに保存';
 $labels['defaultaddressbook'] = '次のアドレス帳に新規連絡先を追加する';
 $labels['reqdsn'] = '常に配送状況の通知を要求する';
 $labels['replysamefolder'] = '返信されたメールを返信元メールと同じフォルダに保存';
 $labels['defaultaddressbook'] = '次のアドレス帳に新規連絡先を追加する';
+$labels['autocompletesingle'] = '自動補完で代替メールアドレスを飛ばす';
 $labels['spellcheckbeforesend'] = 'メールの送信前にスペル チェック';
 $labels['spellcheckoptions'] = 'スペルチェックのオプション';
 $labels['spellcheckignoresyms'] = '記号の単語を無視する';
 $labels['spellcheckbeforesend'] = 'メールの送信前にスペル チェック';
 $labels['spellcheckoptions'] = 'スペルチェックのオプション';
 $labels['spellcheckignoresyms'] = '記号の単語を無視する';
@@ -465,6 +466,12 @@ $labels['sortasc']  = '昇順で並び替え';
 $labels['sortdesc'] = '降順で並び替え';
 $labels['undo'] = '取り消し';
 
 $labels['sortdesc'] = '降順で並び替え';
 $labels['undo'] = '取り消し';
 
+$labels['plugin'] = 'プラグイン';
+$labels['version'] = 'バージョン';
+$labels['source'] = 'ソース';
+$labels['license'] = 'ライセンス';
+$labels['support'] = 'ヘルプを受ける';
+
 // units
 $labels['B'] = 'バイト';
 $labels['KB'] = 'KB';
 // units
 $labels['B'] = 'バイト';
 $labels['KB'] = 'KB';
index fefd7a507705d0c272adf635aa0923bfebc16aab..e728b03fc1d0f8875cf87368dd69227c33ddc1a2 100644 (file)
@@ -14,9 +14,9 @@
 |         Takashi Takamatsu <taka717@gmail.com>                         |
 +-----------------------------------------------------------------------+
 
 |         Takashi Takamatsu <taka717@gmail.com>                         |
 +-----------------------------------------------------------------------+
 
-@version $Id: messages.inc 5291 2011-09-28 17:10:45Z thomasb $
+@version $Id: messages.inc 5569 2011-12-07 14:47:32Z thomasb $
 
 
-//  EN-Revision: 5276
+//  EN-Revision: 5490
 
 */
 
 
 */
 
@@ -136,7 +136,6 @@ $messages['smtpautherror'] = 'SMTP Error ($code): 認証に失敗しました。
 $messages['smtpfromerror'] = 'SMTP Error ($code): 差出人 "$from" を設定できません ($msg)';
 $messages['smtptoerror'] = 'SMTP Error ($code): 宛先 "$to" を追加できません ($msg)';
 $messages['smtprecipientserror'] = 'SMTP Error: 宛先の一覧を解析できません。';
 $messages['smtpfromerror'] = 'SMTP Error ($code): 差出人 "$from" を設定できません ($msg)';
 $messages['smtptoerror'] = 'SMTP Error ($code): 宛先 "$to" を追加できません ($msg)';
 $messages['smtprecipientserror'] = 'SMTP Error: 宛先の一覧を解析できません。';
-$messages['smtpdsnerror'] = 'SMTP エラー: 配送状況通知をサポートしていません。';
 $messages['smtperror'] = 'SMTP エラー: $msg';
 $messages['emailformaterror'] = 'メールアドレスが正しくありません: $email';
 $messages['toomanyrecipients'] = '宛先が多すぎます。$max 件以内にしてください。';
 $messages['smtperror'] = 'SMTP エラー: $msg';
 $messages['emailformaterror'] = 'メールアドレスが正しくありません: $email';
 $messages['toomanyrecipients'] = '宛先が多すぎます。$max 件以内にしてください。';
@@ -166,5 +165,6 @@ $messages['foldercreated'] = 'フォルダーを作成しました。';
 $messages['invalidimageformat'] = '画像の形式が正しくありません。';
 $messages['mispellingsfound'] = 'メッセージにスペル エラーを見つけました。';
 $messages['parentnotwritable'] = '選択した親フォルダーへの作成、移動に失敗しました。アクセス権限がありません。';
 $messages['invalidimageformat'] = '画像の形式が正しくありません。';
 $messages['mispellingsfound'] = 'メッセージにスペル エラーを見つけました。';
 $messages['parentnotwritable'] = '選択した親フォルダーへの作成、移動に失敗しました。アクセス権限がありません。';
+$messages['messagetoobig'] = 'その処理をするにはメッセージ部分が大きすぎます。';
 
 ?>
 
 ?>
index 2a9701c18e4e891de7fd87c50ac9621e39a4197e..fd3811467418251dbd4d6a439e97743883f50aa2 100755 (executable)
@@ -9,7 +9,7 @@
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 +-----------------------------------------------------------------------+
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 +-----------------------------------------------------------------------+
-| Author: Zaza Zviadadze                                                                       |
+| Author: Zaza Zviadadze, George Machitidze                            |
 +-----------------------------------------------------------------------+
 
 @version $Id: labels.inc 842 2009-10-03 19:00:00  zaza$
 +-----------------------------------------------------------------------+
 
 @version $Id: labels.inc 842 2009-10-03 19:00:00  zaza$
@@ -23,38 +23,35 @@ $labels['password'] = 'პაროლი';
 $labels['server'] = 'სერვერი';
 $labels['login'] = 'შესვლა';
 $labels['logout'] = 'გამოსვლა';
 $labels['server'] = 'სერვერი';
 $labels['login'] = 'შესვლა';
 $labels['logout'] = 'გამოსვლა';
-$labels['mail'] = 'ელფოსტა';
+$labels['mail'] = 'ელფოსტა';
 $labels['settings'] = 'პარამეტრები';
 $labels['addressbook'] = 'მისამართები';
 $labels['inbox'] = 'მიღებული';
 $labels['drafts'] = 'დროებითი';
 $labels['settings'] = 'პარამეტრები';
 $labels['addressbook'] = 'მისამართები';
 $labels['inbox'] = 'მიღებული';
 $labels['drafts'] = 'დროებითი';
-$labels['sent'] = 'á\83\92á\83\90á\83\92á\83\96á\83\90á\83\95á\83\9cá\83\98á\83\9aá\83\94á\83\91á\83\98';
-$labels['trash'] = 'á\83¬á\83\90á\83¨á\83\9aá\83\98á\83\9aá\83\94á\83\91á\83\98';
+$labels['sent'] = 'გაგზავნილი';
+$labels['trash'] = 'წაშლილი';
 $labels['junk'] = 'სპამი';
 $labels['subject'] = 'სათაური';
 $labels['from'] = 'გამგზავნი';
 $labels['junk'] = 'სპამი';
 $labels['subject'] = 'სათაური';
 $labels['from'] = 'გამგზავნი';
-$labels['to'] = 'á\83\9bá\83\98á\83\9bá\83¦á\83\94á\83\91á\83\98';
-$labels['cc'] = 'á\83\99á\83\9dá\83\9eá\83\98á\83\90';
+$labels['to'] = 'á\83\95á\83\98á\83¡';
+$labels['cc'] = 'á\83\90á\83¡á\83\9aá\83\98';
 $labels['bcc'] = 'ფარული';
 $labels['bcc'] = 'ფარული';
-$labels['replyto'] = 'á\83\93á\83\90á\83\91á\83 á\83£á\83\9cá\83\94á\83\91á\83\90';
+$labels['replyto'] = 'á\83\9eá\83\90á\83¡á\83£á\83®á\83\98';
 $labels['date'] = 'თარიღი';
 $labels['size'] = 'ზომა';
 $labels['priority'] = 'პრიორიტეტი';
 $labels['organization'] = 'ორგანიზაცია';
 $labels['date'] = 'თარიღი';
 $labels['size'] = 'ზომა';
 $labels['priority'] = 'პრიორიტეტი';
 $labels['organization'] = 'ორგანიზაცია';
-$labels['reply-to'] = 'დაბრუნება';
 $labels['mailboxlist'] = 'საქაღალდეები';
 $labels['mailboxlist'] = 'საქაღალდეები';
-$labels['messagesfromto'] = 'შეტყობინება $from  $to დან $count';
 $labels['messagenrof'] = 'შეტყობინება $nr დან $count';
 $labels['messagenrof'] = 'შეტყობინება $nr დან $count';
+$labels['copy'] = 'ასლი';
+$labels['move'] = 'გადატანა';
 $labels['moveto'] = 'გადატანა...';
 $labels['download'] = 'გადმოწერა';
 $labels['filename'] = 'ფაილის სახელი';
 $labels['filesize'] = 'ფაილის ზომა';
 $labels['moveto'] = 'გადატანა...';
 $labels['download'] = 'გადმოწერა';
 $labels['filename'] = 'ფაილის სახელი';
 $labels['filesize'] = 'ფაილის ზომა';
-$labels['preferhtml'] = 'როგორც HTML';
-$labels['htmlmessage'] = 'HTML შეტყობინება';
-$labels['prettydate'] = 'კარგი თარიღები';
 $labels['addtoaddressbook'] = 'მისამართებში დამატება';
 $labels['addtoaddressbook'] = 'მისამართებში დამატება';
-$labels['sun'] = 'კვ';
-$labels['mon'] = 'ორ';
+$labels['sun'] = 'კვ';
+$labels['mon'] = 'ორ';
 $labels['tue'] = 'სამ';
 $labels['wed'] = 'ოთხ';
 $labels['thu'] = 'ხუთ';
 $labels['tue'] = 'სამ';
 $labels['wed'] = 'ოთხ';
 $labels['thu'] = 'ხუთ';
@@ -101,13 +98,9 @@ $labels['deletemessage'] = 'წაშლა';
 $labels['movemessagetotrash'] = 'შეტყობინების წაშლილებში გადატანა';
 $labels['printmessage'] = 'შეტყობინების ამობეჭვდა';
 $labels['previousmessage'] = 'წინა შეტყობინების ნახვა';
 $labels['movemessagetotrash'] = 'შეტყობინების წაშლილებში გადატანა';
 $labels['printmessage'] = 'შეტყობინების ამობეჭვდა';
 $labels['previousmessage'] = 'წინა შეტყობინების ნახვა';
-$labels['previousmessages'] = 'წინა შეტყობინებების ნახვა';
 $labels['firstmessage'] = 'პირველი შეტყობინების ნახვა';
 $labels['firstmessage'] = 'პირველი შეტყობინების ნახვა';
-$labels['firstmessages'] = 'პრველი შეტყობინებები';
 $labels['nextmessage'] = 'შემდეგი შეტყობინების ნახვა';
 $labels['nextmessage'] = 'შემდეგი შეტყობინების ნახვა';
-$labels['nextmessages'] = 'შემდეგი შეტყობინებების ნახვა';
 $labels['lastmessage'] = 'ბოლო შეტყობინების ნახვა';
 $labels['lastmessage'] = 'ბოლო შეტყობინების ნახვა';
-$labels['lastmessages'] = 'ბოლო შეტყობინებების ნახვა';
 $labels['backtolist'] = 'უკან ჩამონათვალში';
 $labels['viewsource'] = 'შიგთავსი';
 $labels['markmessages'] = 'მონიშნეთ შეტყობინებები';
 $labels['backtolist'] = 'უკან ჩამონათვალში';
 $labels['viewsource'] = 'შიგთავსი';
 $labels['markmessages'] = 'მონიშნეთ შეტყობინებები';
@@ -115,19 +108,30 @@ $labels['markread'] = 'როგორც წაკითხული';
 $labels['markunread'] = 'როგორც წაუკითხავი';
 $labels['markflagged'] = 'როგორც მონიშნული';
 $labels['markunflagged'] = 'როგორც მოუნიშნავი';
 $labels['markunread'] = 'როგორც წაუკითხავი';
 $labels['markflagged'] = 'როგორც მონიშნული';
 $labels['markunflagged'] = 'როგორც მოუნიშნავი';
-$labels['messageactions'] = 'მეტი ფუნქციები';
+$labels['moreactions'] = 'მეტი მოქმედება...';
 $labels['select'] = 'მონიშვნა';
 $labels['all'] = 'ყველა';
 $labels['none'] = 'არცერთი';
 $labels['select'] = 'მონიშვნა';
 $labels['all'] = 'ყველა';
 $labels['none'] = 'არცერთი';
+$labels['currpage'] = 'მიმდინარე გვერდი';
 $labels['unread'] = 'წაუკითხავი';
 $labels['flagged'] = 'მონიშნული';
 $labels['unanswered'] = 'უპასუხო';
 $labels['deleted'] = 'წაშლილი';
 $labels['invert'] = 'შებრუნებული';
 $labels['filter'] = 'ფილტრი';
 $labels['unread'] = 'წაუკითხავი';
 $labels['flagged'] = 'მონიშნული';
 $labels['unanswered'] = 'უპასუხო';
 $labels['deleted'] = 'წაშლილი';
 $labels['invert'] = 'შებრუნებული';
 $labels['filter'] = 'ფილტრი';
+$labels['list'] = 'სია';
+$labels['expand-all'] = 'ყველას გაშლა';
+$labels['expand-unread'] = 'წაუკითხავის გაშლა';
+$labels['collapse-all'] = 'ყველას დაკეცვა';
+$labels['fromto'] = 'ვისგან/ვის';
+$labels['flag'] = 'დროშა';
+$labels['attachment'] = 'მიმაგრებული ფაილი';
+$labels['sentdate'] = 'გაგზავნის თარიღი';
+$labels['asc'] = 'ზრდადობით';
+$labels['desc'] = 'კლებადობით';
+$labels['listorder'] = 'დალაგება';
 $labels['compact'] = 'შეკუმშვა';
 $labels['empty'] = 'გაცარიელება';
 $labels['compact'] = 'შეკუმშვა';
 $labels['empty'] = 'გაცარიელება';
-$labels['purge'] = 'გასუფთავება';
 $labels['quota'] = 'შეზღუდვა';
 $labels['unknown'] = 'უცნობი';
 $labels['unlimited'] = 'შეუზღუდავი';
 $labels['quota'] = 'შეზღუდვა';
 $labels['unknown'] = 'უცნობი';
 $labels['unlimited'] = 'შეუზღუდავი';
@@ -174,13 +178,49 @@ $labels['receiptnote'] = 'განმარტება: ეს ნიშნა
 $labels['name'] = 'სრული სახელი';
 $labels['firstname'] = 'სახელი';
 $labels['surname'] = 'გვარი';
 $labels['name'] = 'სრული სახელი';
 $labels['firstname'] = 'სახელი';
 $labels['surname'] = 'გვარი';
+$labels['department'] = 'დეპარტამენტი';
+$labels['gender'] = 'სქესი';
 $labels['email'] = 'ელ–ფოსტა';
 $labels['email'] = 'ელ–ფოსტა';
+$labels['phone'] = 'ტელეფონი';
+$labels['address'] = 'მისამართი';
+$labels['street'] = 'ქუჩა';
+$labels['locality'] = 'ქალაქი';
+$labels['zipcode'] = 'ZIP კოდი';
+$labels['region'] = 'შტატი/პროვინცია';
+$labels['country'] = 'ქვეყანა';
+$labels['birthday'] = 'დაბადების დღე';
+$labels['website'] = 'ვებგვერდი';
+$labels['male'] = 'მამრობითი';
+$labels['female'] = 'მდედრობით';
+$labels['manager'] = 'მენეჯერი';
+$labels['allfields'] = 'ყველა ველი';
+$labels['search'] = 'ძებნა';
+$labels['advsearch'] = 'გაფართოებული ძებნა';
+$labels['other'] = 'სხვა';
+$labels['typehome'] = 'სახლი';
+$labels['typework'] = 'სამსახური';
+$labels['typeother'] = 'სხვა';
+$labels['typemobile'] = 'მობილური';
+$labels['typemain'] = 'ძირითადი';
+$labels['typehomefax'] = 'სახლის ფაქსი';
+$labels['typeworkfax'] = 'სამსახურის ფაქსი';
+$labels['typecar'] = 'მანქანა';
+$labels['typepager'] = 'პეიჯერი';
+$labels['typevideo'] = 'ვიდეო';
+$labels['typeblog'] = 'ბლოგი';
+$labels['typeprofile'] = 'პროფილი';
+$labels['addfield'] = 'ველის დამატება...';
 $labels['addcontact'] = 'კონტაქტებში დამატება';
 $labels['editcontact'] = 'კონტაქტის რედაქტირება';
 $labels['addcontact'] = 'კონტაქტებში დამატება';
 $labels['editcontact'] = 'კონტაქტის რედაქტირება';
+$labels['contacts'] = 'კონტაქტები';
+$labels['personalinfo'] = 'პირადი ინფორმაცია';
 $labels['edit'] = 'რედაქტირება';
 $labels['cancel'] = 'გაუქმება';
 $labels['save'] = 'შენახვა';
 $labels['delete'] = 'წაშლა';
 $labels['edit'] = 'რედაქტირება';
 $labels['cancel'] = 'გაუქმება';
 $labels['save'] = 'შენახვა';
 $labels['delete'] = 'წაშლა';
+$labels['rename'] = 'გადარქმევა';
+$labels['addphoto'] = 'დამატება';
+$labels['replacephoto'] = 'გამოცვლა';
 $labels['newcontact'] = 'კონტაქტის შექმნა';
 $labels['deletecontact'] = 'მონიშნელი კონტაქტის წაშლა';
 $labels['composeto'] = 'ფოსტის გაგზავნა შერჩეულ ადრესატებთან';
 $labels['newcontact'] = 'კონტაქტის შექმნა';
 $labels['deletecontact'] = 'მონიშნელი კონტაქტის წაშლა';
 $labels['composeto'] = 'ფოსტის გაგზავნა შერჩეულ ადრესატებთან';
@@ -188,12 +228,18 @@ $labels['contactsfromto'] = 'კონტაქტები $from დან $to
 $labels['print'] = 'დაბეჭვდა';
 $labels['export'] = 'ექსპორტი';
 $labels['exportvcards'] = 'კონტაქტების ექსპორტი vCard ფორმატში';
 $labels['print'] = 'დაბეჭვდა';
 $labels['export'] = 'ექსპორტი';
 $labels['exportvcards'] = 'კონტაქტების ექსპორტი vCard ფორმატში';
+$labels['newcontactgroup'] = 'ახალი საკონტაქტო ჯგუფის შექმნა';
+$labels['grouprename'] = 'ჯგუფის სახელის შეცვლა';
+$labels['groupdelete'] = 'ჯგუფის წაშლა';
 $labels['previouspage'] = 'წინას ჩვენება';
 $labels['firstpage'] = 'პირველის ჩვენება';
 $labels['nextpage'] = 'შემდეგის ჩვენება';
 $labels['lastpage'] = 'ბოლოს ჩვენება';
 $labels['previouspage'] = 'წინას ჩვენება';
 $labels['firstpage'] = 'პირველის ჩვენება';
 $labels['nextpage'] = 'შემდეგის ჩვენება';
 $labels['lastpage'] = 'ბოლოს ჩვენება';
+$labels['group'] = 'ჯგუფი';
 $labels['groups'] = 'ჯგუფები';
 $labels['personaladrbook'] = 'პერსონალური მისამართები';
 $labels['groups'] = 'ჯგუფები';
 $labels['personaladrbook'] = 'პერსონალური მისამართები';
+$labels['searchsave'] = 'ძებნის შენახვა';
+$labels['searchdelete'] = 'ძებნის წაშლა';
 $labels['import'] = 'შემოტანა';
 $labels['importcontacts'] = 'კონტაქტების შემოტანა';
 $labels['importfromfile'] = 'შემოტანა ფაილიდან:';
 $labels['import'] = 'შემოტანა';
 $labels['importcontacts'] = 'კონტაქტების შემოტანა';
 $labels['importfromfile'] = 'შემოტანა ფაილიდან:';
@@ -209,6 +255,12 @@ $labels['manageidentities'] = 'პროფილების მართვა
 $labels['newidentity'] = 'ახალი პროფილი';
 $labels['newitem'] = 'ახალი';
 $labels['edititem'] = 'რედაქტირება';
 $labels['newidentity'] = 'ახალი პროფილი';
 $labels['newitem'] = 'ახალი';
 $labels['edititem'] = 'რედაქტირება';
+$labels['preferhtml'] = 'როგორც HTML';
+$labels['defaultcharset'] = 'ნაგულისხმები სიმბოლოთა ნაკრები';
+$labels['htmlmessage'] = 'HTML შეტყობინება';
+$labels['dateformat'] = 'თარიღის ფორმატი';
+$labels['timeformat'] = 'დროის ფორმატი';
+$labels['prettydate'] = 'კარგი თარიღები';
 $labels['setdefault'] = 'როგორც ზოგაგად';
 $labels['autodetect'] = 'ავტომატური';
 $labels['language'] = 'ენა';
 $labels['setdefault'] = 'როგორც ზოგაგად';
 $labels['autodetect'] = 'ავტომატური';
 $labels['language'] = 'ენა';
@@ -240,12 +292,14 @@ $labels['autosavedraft'] = 'ავტომატური შენახვა
 $labels['everynminutes'] = 'ყოველ $n წუთში';
 $labels['keepalive'] = 'შეამოწმე ახალ შეტყობინებაზე';
 $labels['never'] = 'არასდროს';
 $labels['everynminutes'] = 'ყოველ $n წუთში';
 $labels['keepalive'] = 'შეამოწმე ახალ შეტყობინებაზე';
 $labels['never'] = 'არასდროს';
+$labels['immediately'] = 'დაუყონებლივ';
 $labels['messagesdisplaying'] = 'გამოაჩინე შეტყობინებები';
 $labels['messagescomposition'] = 'შეტყობინებების შექმნა';
 $labels['mimeparamfolding'] = 'ბმულის სახელები';
 $labels['2231folding'] = 'Full RFC 2231 (Thunderbird)';
 $labels['miscfolding'] = 'RFC 2047/2231 (MS Outlook)';
 $labels['2047folding'] = 'Full RFC 2047 (other)';
 $labels['messagesdisplaying'] = 'გამოაჩინე შეტყობინებები';
 $labels['messagescomposition'] = 'შეტყობინებების შექმნა';
 $labels['mimeparamfolding'] = 'ბმულის სახელები';
 $labels['2231folding'] = 'Full RFC 2231 (Thunderbird)';
 $labels['miscfolding'] = 'RFC 2047/2231 (MS Outlook)';
 $labels['2047folding'] = 'Full RFC 2047 (other)';
+$labels['force7bit'] = 'MIME კოდირების გამოყენება 8 ბიტიანი სიმბოლოებისთვის';
 $labels['advancedoptions'] = 'დამატებითი პარამეტრები';
 $labels['focusonnewmessage'] = 'ფოკუსირება ახალ შეტყობინებებზე';
 $labels['checkallfolders'] = 'შეამოწმე ყველა საქაღალდე ახალ შეტყობინებაზე';
 $labels['advancedoptions'] = 'დამატებითი პარამეტრები';
 $labels['focusonnewmessage'] = 'ფოკუსირება ახალ შეტყობინებებზე';
 $labels['checkallfolders'] = 'შეამოწმე ყველა საქაღალდე ახალ შეტყობინებაზე';
@@ -267,6 +321,8 @@ $labels['replysignaturepos'] = 'მხოლოდ პასუხის ან
 $labels['belowquote'] = 'ციტატის შემდეგ';
 $labels['abovequote'] = 'ციტატამდე';
 $labels['insertsignature'] = 'ხელმოცერის ჩასმა';
 $labels['belowquote'] = 'ციტატის შემდეგ';
 $labels['abovequote'] = 'ციტატამდე';
 $labels['insertsignature'] = 'ხელმოცერის ჩასმა';
+$labels['afternseconds'] = '$n წამის შემდეგ';
+$labels['addtodict'] = 'ლექსიკონში დამატება';
 $labels['folder'] = 'საქაღალდე';
 $labels['folders'] = 'საქაღალდეები';
 $labels['foldername'] = 'საქაღალდის დასახელება';
 $labels['folder'] = 'საქაღალდე';
 $labels['folders'] = 'საქაღალდეები';
 $labels['foldername'] = 'საქაღალდის დასახელება';
@@ -276,12 +332,34 @@ $labels['create'] = 'შექმნა';
 $labels['createfolder'] = 'საქაღალდის შექმნა';
 $labels['managefolders'] = 'საქაღალდეების მართვა';
 $labels['specialfolders'] = 'სპეციალური საქაღალდე';
 $labels['createfolder'] = 'საქაღალდის შექმნა';
 $labels['managefolders'] = 'საქაღალდეების მართვა';
 $labels['specialfolders'] = 'სპეციალური საქაღალდე';
+$labels['location'] = 'მდებარეობა';
+$labels['info'] = 'ინფორმაცია';
+$labels['foldertype'] = 'დასტის ტიპი';
+$labels['personalfolder'] = 'კერძო დასტა';
+$labels['sharedfolder'] = 'საჯარო დასტა';
 $labels['sortby'] = 'დალაგება';
 $labels['sortasc'] = 'დალაგება ზრდადობით';
 $labels['sortdesc'] = 'დალაგება კლებადობით';
 $labels['sortby'] = 'დალაგება';
 $labels['sortasc'] = 'დალაგება ზრდადობით';
 $labels['sortdesc'] = 'დალაგება კლებადობით';
-$labels['B'] = 'ბ';
-$labels['KB'] = 'კბ';
-$labels['MB'] = 'მბ';
-$labels['GB'] = 'გბ';
+$labels['undo'] = 'დაბრუნება';
+$labels['B'] = 'ბტ';
+$labels['KB'] = 'კბტ';
+$labels['MB'] = 'მბტ';
+$labels['GB'] = 'გბტ';
+$labels['unicode'] = 'უნიკოდი';
+$labels['english'] = 'ინსგლისური';
+$labels['westerneuropean'] = 'დასავლურევროპული';
+$labels['easterneuropean'] = 'აღმოსავლეთევროპული';
+$labels['baltic'] = 'ბალტიური';
+$labels['cyrillic'] = 'კირილიცა';
+$labels['arabic'] = 'არაბული';
+$labels['greek'] = 'ბერძნული';
+$labels['hebrew'] = 'ებრაული';
+$labels['turkish'] = 'თურქული';
+$labels['thai'] = 'ტაი';
+$labels['celtic'] = 'კელტური';
+$labels['vietnamese'] = 'ვიეტნამური';
+$labels['japanese'] = 'იაპონური';
+$labels['korean'] = 'კორეული';
+$labels['chinese'] = 'ჩინური';
 
 ?>
 
 ?>
index 4865847aad35d289bdf06e2a3003247526bd9bda..55d3333d82ccdd073c4cec823392b3bf88789b93 100755 (executable)
@@ -9,7 +9,7 @@
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 +-----------------------------------------------------------------------+
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 +-----------------------------------------------------------------------+
-| Author: Zaza Zviadadze                                                |
+| Author: Zaza Zviadadze, George Machitidze                             |
 +-----------------------------------------------------------------------+
 
 @version $Id: messages.inc 842 2009-10-03 19:30:00  zaza$
 +-----------------------------------------------------------------------+
 
 @version $Id: messages.inc 842 2009-10-03 19:30:00  zaza$
@@ -22,12 +22,16 @@ $messages['cookiesdisabled'] = 'თქვენი ბროუზერი კ
 $messages['sessionerror'] = 'თქვენი სესია არის მცდარი ან ვადაგასული';
 $messages['imaperror'] = 'IMAP სერვერთან დაკავშირება შეუძლებელია';
 $messages['servererror'] = 'შეცდომა სერვერზე!';
 $messages['sessionerror'] = 'თქვენი სესია არის მცდარი ან ვადაგასული';
 $messages['imaperror'] = 'IMAP სერვერთან დაკავშირება შეუძლებელია';
 $messages['servererror'] = 'შეცდომა სერვერზე!';
+$messages['servererrormsg'] = 'სერვერის შეცდომა: $msg';
+$messages['dberror'] = 'მონაცემთა ბაზის შეცდომა!';
+$messages['errornoperm'] = 'მოქმედების შესრულება შეუძლებალია. წვდომა აკრძალულია.';
 $messages['invalidrequest'] = 'არასწორი მოთხოვნა! მონაცემების შენახვა არ მოხერხდა.';
 $messages['nomessagesfound'] = 'არ არის ახალი შეტყობინება';
 $messages['loggedout'] = 'წარმატებით დაიხურა თქვენი სესია';
 $messages['mailboxempty'] = 'საფოსტო ყუთი ცარიელია';
 $messages['loading'] = 'იტვირთება...';
 $messages['uploading'] = 'ფაილი იტვირთება...';
 $messages['invalidrequest'] = 'არასწორი მოთხოვნა! მონაცემების შენახვა არ მოხერხდა.';
 $messages['nomessagesfound'] = 'არ არის ახალი შეტყობინება';
 $messages['loggedout'] = 'წარმატებით დაიხურა თქვენი სესია';
 $messages['mailboxempty'] = 'საფოსტო ყუთი ცარიელია';
 $messages['loading'] = 'იტვირთება...';
 $messages['uploading'] = 'ფაილი იტვირთება...';
+$messages['uploadingmany'] = 'ფაილების ატვირთვა...';
 $messages['loadingdata'] = 'მონაცემების ჩატვირთვა...';
 $messages['checkingmail'] = 'ახალი შეტყობინების ნახვა';
 $messages['sendingmessage'] = 'შეტყობინების გაგზავნა';
 $messages['loadingdata'] = 'მონაცემების ჩატვირთვა...';
 $messages['checkingmail'] = 'ახალი შეტყობინების ნახვა';
 $messages['sendingmessage'] = 'შეტყობინების გაგზავნა';
@@ -52,6 +56,7 @@ $messages['deletecontactconfirm'] = 'ნამდვილად გსურთ
 $messages['deletemessagesconfirm'] = 'ნამდვილად გსურთ მონიშნული შეტყობინებების წაშლა?';
 $messages['deletefolderconfirm'] = 'ნამდვილად გსურთ ამ საქაღალდის წაშლა?';
 $messages['purgefolderconfirm'] = 'ნამდვილად გსურთ ყველა შეტყობინების წაშლა აღნიშნულ საქაღალდეში?';
 $messages['deletemessagesconfirm'] = 'ნამდვილად გსურთ მონიშნული შეტყობინებების წაშლა?';
 $messages['deletefolderconfirm'] = 'ნამდვილად გსურთ ამ საქაღალდის წაშლა?';
 $messages['purgefolderconfirm'] = 'ნამდვილად გსურთ ყველა შეტყობინების წაშლა აღნიშნულ საქაღალდეში?';
+$messages['groupdeleting'] = 'ჯგუფის წაშლა...';
 $messages['folderdeleting'] = 'საქაღალდის წაშლა...';
 $messages['foldermoving'] = 'საქაღალდის გადატანა...';
 $messages['formincomplete'] = 'ყველა ველი არ არის შევსებული';
 $messages['folderdeleting'] = 'საქაღალდის წაშლა...';
 $messages['foldermoving'] = 'საქაღალდის გადატანა...';
 $messages['formincomplete'] = 'ყველა ველი არ არის შევსებული';
@@ -64,10 +69,10 @@ $messages['nosubjectwarning'] = 'გსურთ თუ არა შეტყ
 $messages['nobodywarning'] = 'გსურთ თუ არა შეტყობინების გაგზავნა უტექსტოდ?';
 $messages['notsentwarning'] = 'შეტყობინება ვერ იქნა გაგზავნილი. გსურთ თუ არა გზავნილის გაუქმება?';
 $messages['noldapserver'] = 'მიუთითეთ LDAP სერვერი ძიებისთვის';
 $messages['nobodywarning'] = 'გსურთ თუ არა შეტყობინების გაგზავნა უტექსტოდ?';
 $messages['notsentwarning'] = 'შეტყობინება ვერ იქნა გაგზავნილი. გსურთ თუ არა გზავნილის გაუქმება?';
 $messages['noldapserver'] = 'მიუთითეთ LDAP სერვერი ძიებისთვის';
-$messages['nocontactsreturned'] = 'კონტაქტები ვერ მოძებნა';
 $messages['nosearchname'] = 'მიუთითეთ სახელი ან ელ–ფოსტის მისამართი';
 $messages['notuploadedwarning'] = 'ჯერ არ ატვირთულა ყველა მიმაგრებული ფაილი. დაელოდეთ ან გააუქმეთ ატვირთვა.';
 $messages['searchsuccessful'] = '$nr შეტყობინეა მოიძებნა';
 $messages['nosearchname'] = 'მიუთითეთ სახელი ან ელ–ფოსტის მისამართი';
 $messages['notuploadedwarning'] = 'ჯერ არ ატვირთულა ყველა მიმაგრებული ფაილი. დაელოდეთ ან გააუქმეთ ატვირთვა.';
 $messages['searchsuccessful'] = '$nr შეტყობინეა მოიძებნა';
+$messages['contactsearchsuccessful'] = 'ნაპოვნია $nr კონტაქტი';
 $messages['searchnomatch'] = 'შეტყობინება ვერ მოიძებნა';
 $messages['searching'] = 'ძიება...';
 $messages['checking'] = 'შემოწმება...';
 $messages['searchnomatch'] = 'შეტყობინება ვერ მოიძებნა';
 $messages['searching'] = 'ძიება...';
 $messages['checking'] = 'შემოწმება...';
@@ -103,5 +108,17 @@ $messages['smtptoerror'] = 'SMTP Error ($code): ვერ დაემატა
 $messages['smtprecipientserror'] = 'SMTP Error: მიმღებთა ჩამონათვალის დამუშავება ვერ მოხერხდა';
 $messages['smtperror'] = 'SMTP Error: $msg';
 $messages['emailformaterror'] = 'ელ-ფოსტის მისამართი არასწორია $email';
 $messages['smtprecipientserror'] = 'SMTP Error: მიმღებთა ჩამონათვალის დამუშავება ვერ მოხერხდა';
 $messages['smtperror'] = 'SMTP Error: $msg';
 $messages['emailformaterror'] = 'ელ-ფოსტის მისამართი არასწორია $email';
+$messages['contactdeleted'] = 'კონტაქტ(ებ)ი წარმატებით წაიშალა.';
+$messages['contactrestored'] = 'კონრაქტ(ებ)ი წარმატებით აღდგა,';
+$messages['groupdeleted'] = 'ჯგუფი წარმატებით წაიშალა.';
+$messages['groupcreated'] = 'ჯგუფი წარმატებით შეიქმნა.';
+$messages['messagedeleted'] = 'შეტყობინებები წარმატებით წაიშალა.';
+$messages['messagemoved'] = 'შეტყობინებები გადატანილია წარმატებით.';
+$messages['messagemarked'] = 'შეტყობინებები წარმატებით მოინიშნა.';
+$messages['namecannotbeempty'] = 'სახელი არ შეიძლება იყოს ცარიელი.';
+$messages['nametoolong'] = 'სახელი ძალიან მოკლეა.';
+$messages['folderupdated'] = 'დასტა წარმატებით განახლდა.';
+$messages['foldercreated'] = 'დასტა წარმატებით შეიქმნა.';
+$messages['invalidimageformat'] = 'გამოსახულების ფორმატი არასწორია.';
 
 ?>
 
 ?>
index 623fd1e23ea232c9dfbf895495109378ed5bc9c3..9f9af61f8780cef86f1bbd8b0d226cc134628b0d 100644 (file)
@@ -14,7 +14,7 @@
 |          Rimas Kudelis <rq@akl.lt>                                    |
 +-----------------------------------------------------------------------+'
 
 |          Rimas Kudelis <rq@akl.lt>                                    |
 +-----------------------------------------------------------------------+'
 
-@version $Id: labels.inc 5175 2011-09-05 18:42:24Z thomasb $
+@version $Id: labels.inc 5569 2011-12-07 14:47:32Z thomasb $
 
 */
 
 
 */
 
@@ -118,7 +118,7 @@ $labels['markread'] = 'Kaip skaitytus';
 $labels['markunread'] = 'Kaip neskaitytus';
 $labels['markflagged'] = 'Pažymėti gairele';
 $labels['markunflagged'] = 'Pašalinti gairelę';
 $labels['markunread'] = 'Kaip neskaitytus';
 $labels['markflagged'] = 'Pažymėti gairele';
 $labels['markunflagged'] = 'Pašalinti gairelę';
-$labels['messageactions'] = 'Daugiau veiksmų…';
+$labels['moreactions'] = 'Kiti veiksmai…';
 $labels['select'] = 'Pažymėti';
 $labels['all'] = 'visus';
 $labels['none'] = 'nieko';
 $labels['select'] = 'Pažymėti';
 $labels['all'] = 'visus';
 $labels['none'] = 'nieko';
@@ -151,7 +151,7 @@ $labels['listsorting'] = 'Stulpelis rikiavimui';
 $labels['listorder'] = 'Rikiavimo tvarka';
 $labels['listmode'] = 'Sąrašo rodymo veiksena';
 $labels['folderactions'] = 'Veiksmai su aplankais…';
 $labels['listorder'] = 'Rikiavimo tvarka';
 $labels['listmode'] = 'Sąrašo rodymo veiksena';
 $labels['folderactions'] = 'Veiksmai su aplankais…';
-$labels['compact'] = 'Suspausti';
+$labels['compact'] = 'Suglaudinti';
 $labels['empty'] = 'Ištuštinti';
 $labels['quota'] = 'Disko naudojimas';
 $labels['unknown'] = 'nežinomas';
 $labels['empty'] = 'Ištuštinti';
 $labels['quota'] = 'Disko naudojimas';
 $labels['unknown'] = 'nežinomas';
@@ -172,6 +172,7 @@ $labels['editortype'] = 'Laiško tipas';
 $labels['returnreceipt'] = 'Prašyti pristatymo pažymos';
 $labels['dsn'] = 'Laiško pristatymo pažyma';
 $labels['mailreplyintro'] = '$date, $sender rašė:';
 $labels['returnreceipt'] = 'Prašyti pristatymo pažymos';
 $labels['dsn'] = 'Laiško pristatymo pažyma';
 $labels['mailreplyintro'] = '$date, $sender rašė:';
+$labels['originalmessage'] = 'Originalus laiškas';
 $labels['editidents'] = 'Tvarkyti tapatybes';
 $labels['checkspelling'] = 'Tikrinti rašybą';
 $labels['resumeediting'] = 'Tęsti redagavimą';
 $labels['editidents'] = 'Tvarkyti tapatybes';
 $labels['checkspelling'] = 'Tikrinti rašybą';
 $labels['resumeediting'] = 'Tęsti redagavimą';
@@ -189,6 +190,7 @@ $labels['highest'] = 'Aukščiausias';
 $labels['nosubject'] = '(tema nenurodyta)';
 $labels['showimages'] = 'Rodyti paveikslėlius';
 $labels['alwaysshow'] = 'Visada rodyti paveikslėlius $sender laiškuose';
 $labels['nosubject'] = '(tema nenurodyta)';
 $labels['showimages'] = 'Rodyti paveikslėlius';
 $labels['alwaysshow'] = 'Visada rodyti paveikslėlius $sender laiškuose';
+$labels['isdraft'] = 'Tai – laiško juodraštis.';
 $labels['htmltoggle'] = 'HTML';
 $labels['plaintoggle'] = 'Grynasis tekstas';
 $labels['savesentmessagein'] = 'Išsiųstus laiškus įrašyti į';
 $labels['htmltoggle'] = 'HTML';
 $labels['plaintoggle'] = 'Grynasis tekstas';
 $labels['savesentmessagein'] = 'Išsiųstus laiškus įrašyti į';
@@ -247,6 +249,8 @@ $labels['typepager'] = 'Pranešimų gaviklis';
 $labels['typevideo'] = 'Vaizdo';
 $labels['typeassistant'] = 'Padėjėjo(-os)';
 $labels['typehomepage'] = 'Tinklalapis';
 $labels['typevideo'] = 'Vaizdo';
 $labels['typeassistant'] = 'Padėjėjo(-os)';
 $labels['typehomepage'] = 'Tinklalapis';
+$labels['typeblog'] = 'Tinklaraštis';
+$labels['typeprofile'] = 'Profilis';
 $labels['addfield'] = 'Pridėti lauką…';
 $labels['addcontact'] = 'Pridėti adresatą';
 $labels['editcontact'] = 'Taisyti adresatą';
 $labels['addfield'] = 'Pridėti lauką…';
 $labels['addcontact'] = 'Pridėti adresatą';
 $labels['editcontact'] = 'Taisyti adresatą';
@@ -268,7 +272,6 @@ $labels['print'] = 'Spausdinti';
 $labels['export'] = 'Eksportuoti';
 $labels['exportvcards'] = 'Eksportuoti adresatus  „vCard“ formatu';
 $labels['newcontactgroup'] = 'Kurti adresatų grupę';
 $labels['export'] = 'Eksportuoti';
 $labels['exportvcards'] = 'Eksportuoti adresatus  „vCard“ formatu';
 $labels['newcontactgroup'] = 'Kurti adresatų grupę';
-$labels['groupactions'] = 'Adresatų grupėms taikomi veiksmai…';
 $labels['grouprename'] = 'Pervardinti grupę';
 $labels['groupdelete'] = 'Pašalinti grupę';
 $labels['previouspage'] = 'Rodyti ankstesnį puslapį';
 $labels['grouprename'] = 'Pervardinti grupę';
 $labels['groupdelete'] = 'Pašalinti grupę';
 $labels['previouspage'] = 'Rodyti ankstesnį puslapį';
@@ -278,6 +281,8 @@ $labels['lastpage'] = 'Rodyti paskutinį puslapį';
 $labels['group'] = 'Grupė';
 $labels['groups'] = 'Grupės';
 $labels['personaladrbook'] = 'Asmeniniai adresai';
 $labels['group'] = 'Grupė';
 $labels['groups'] = 'Grupės';
 $labels['personaladrbook'] = 'Asmeniniai adresai';
+$labels['searchsave'] = 'Įrašyti kaip radinių aplanką';
+$labels['searchdelete'] = 'Pašalinti radinių aplanką';
 $labels['import'] = 'Importuoti';
 $labels['importcontacts'] = 'Importuoti adresatus';
 $labels['importfromfile'] = 'Importuoti iš failo:';
 $labels['import'] = 'Importuoti';
 $labels['importcontacts'] = 'Importuoti adresatus';
 $labels['importfromfile'] = 'Importuoti iš failo:';
@@ -286,6 +291,7 @@ $labels['importreplace'] = 'Perrašyti visą adresų knygą';
 $labels['importtext'] = 'Jūs galite įkelti adresatus iš egzistuojančios adresų knygos.<br/>Šiuo metu galima importuoti adresus iš <a href="http://en.wikipedia.org/wiki/VCard">vCard</a> tipo failų.';
 $labels['done'] = 'Baigta';
 $labels['settingsfor'] = 'Nustatymai';
 $labels['importtext'] = 'Jūs galite įkelti adresatus iš egzistuojančios adresų knygos.<br/>Šiuo metu galima importuoti adresus iš <a href="http://en.wikipedia.org/wiki/VCard">vCard</a> tipo failų.';
 $labels['done'] = 'Baigta';
 $labels['settingsfor'] = 'Nustatymai';
+$labels['about'] = 'Apie';
 $labels['preferences'] = 'Nustatymai';
 $labels['userpreferences'] = 'Naudotojo nustatymai';
 $labels['editpreferences'] = 'Redaguoti naudotojo nustatymus';
 $labels['preferences'] = 'Nustatymai';
 $labels['userpreferences'] = 'Naudotojo nustatymai';
 $labels['editpreferences'] = 'Redaguoti naudotojo nustatymus';
@@ -297,6 +303,8 @@ $labels['edititem'] = 'Redaguoti elementą';
 $labels['preferhtml'] = 'Rodyti HTML';
 $labels['defaultcharset'] = 'Numatytoji koduotė';
 $labels['htmlmessage'] = 'HTML laiškas';
 $labels['preferhtml'] = 'Rodyti HTML';
 $labels['defaultcharset'] = 'Numatytoji koduotė';
 $labels['htmlmessage'] = 'HTML laiškas';
+$labels['dateformat'] = 'Datos formatas';
+$labels['timeformat'] = 'Laiko formatas';
 $labels['prettydate'] = 'Dailios datos';
 $labels['setdefault'] = 'Laikyti numatytąja';
 $labels['autodetect'] = 'Aptikti automatiškai';
 $labels['prettydate'] = 'Dailios datos';
 $labels['setdefault'] = 'Laikyti numatytąja';
 $labels['autodetect'] = 'Aptikti automatiškai';
@@ -311,7 +319,7 @@ $labels['htmlsignature'] = 'HTML parašas';
 $labels['previewpane'] = 'Rodyti laiško peržiūros polangį';
 $labels['skin'] = 'Grafinis apvalkalas';
 $labels['logoutclear'] = 'Išvalyti Šiukšlinę atsijungiant';
 $labels['previewpane'] = 'Rodyti laiško peržiūros polangį';
 $labels['skin'] = 'Grafinis apvalkalas';
 $labels['logoutclear'] = 'Išvalyti Šiukšlinę atsijungiant';
-$labels['logoutcompact'] = 'Suspausti Gautų laiškų aplanką atsijungiant';
+$labels['logoutcompact'] = 'Suglaudinti gautųjų laiškų aplanką atsijungiant';
 $labels['uisettings'] = 'Naudotojo sąsaja';
 $labels['serversettings'] = 'Serverio nustatymai';
 $labels['mailboxview'] = 'Pašto dėžutės rodymas';
 $labels['uisettings'] = 'Naudotojo sąsaja';
 $labels['serversettings'] = 'Serverio nustatymai';
 $labels['mailboxview'] = 'Pašto dėžutės rodymas';
@@ -368,7 +376,13 @@ $labels['reqmdn'] = 'Visuomet prašyti patvirtinimo, jog laiškas perskaitytas';
 $labels['reqdsn'] = 'Visuomet prašyti laiško pristatymo pažymos';
 $labels['replysamefolder'] = 'Atsakymus talpinti į tą patį aplanką, kuriame yra pirminis laiškas';
 $labels['defaultaddressbook'] = 'Pridėti naujus adresatus į pasirinktąją adresų knygą';
 $labels['reqdsn'] = 'Visuomet prašyti laiško pristatymo pažymos';
 $labels['replysamefolder'] = 'Atsakymus talpinti į tą patį aplanką, kuriame yra pirminis laiškas';
 $labels['defaultaddressbook'] = 'Pridėti naujus adresatus į pasirinktąją adresų knygą';
+$labels['autocompletesingle'] = 'Užbaigiant adresus, praleisti antrinius';
 $labels['spellcheckbeforesend'] = 'Tikrinti rašybą prieš išsiunčiant laišką';
 $labels['spellcheckbeforesend'] = 'Tikrinti rašybą prieš išsiunčiant laišką';
+$labels['spellcheckoptions'] = 'Rašybos tikrinimo nuostatos';
+$labels['spellcheckignoresyms'] = 'Nepaisyti žodžių su spec. simboliais';
+$labels['spellcheckignorenums'] = 'Nepaisyti žodžių su skaitmenimis';
+$labels['spellcheckignorecaps'] = 'Nepaisyti žodžių vien iš didžiųjų raidžių';
+$labels['addtodict'] = 'Įtraukti į žodyną';
 $labels['folder'] = 'Aplankas';
 $labels['folders'] = 'Aplankai';
 $labels['foldername'] = 'Aplanko vardas';
 $labels['folder'] = 'Aplankas';
 $labels['folders'] = 'Aplankai';
 $labels['foldername'] = 'Aplanko vardas';
@@ -393,6 +407,11 @@ $labels['sortby'] = 'Rikiuoti pagal';
 $labels['sortasc'] = 'Rikiuoti didėjančiai';
 $labels['sortdesc'] = 'Rikiuoti mažėjančiai';
 $labels['undo'] = 'Atšaukti';
 $labels['sortasc'] = 'Rikiuoti didėjančiai';
 $labels['sortdesc'] = 'Rikiuoti mažėjančiai';
 $labels['undo'] = 'Atšaukti';
+$labels['plugin'] = 'Papildinys';
+$labels['version'] = 'Versija';
+$labels['source'] = 'Šaltinis';
+$labels['license'] = 'Licencija';
+$labels['support'] = 'Gauti pagalbos';
 $labels['B'] = 'B';
 $labels['KB'] = 'KB';
 $labels['MB'] = 'MB';
 $labels['B'] = 'B';
 $labels['KB'] = 'KB';
 $labels['MB'] = 'MB';
index 151277ea29f211ddd345517ed9b4a2796444c531..4cff2b0139ea54f6c17b8eb840e3b3fca78b1773 100644 (file)
@@ -14,7 +14,7 @@
 |          Rimas Kudelis <rq@akl.lt>                                    |
 +-----------------------------------------------------------------------+
 
 |          Rimas Kudelis <rq@akl.lt>                                    |
 +-----------------------------------------------------------------------+
 
-@version $Id: messages.inc 5175 2011-09-05 18:42:24Z thomasb $
+@version $Id: messages.inc 5569 2011-12-07 14:47:32Z thomasb $
 
 */
 
 
 */
 
@@ -25,7 +25,7 @@ $messages['sessionerror'] = 'Jūsų sesija negaliojanti.';
 $messages['imaperror'] = 'Nepavyko prisijungti prie IMAP serverio.';
 $messages['servererror'] = 'Serverio klaida!';
 $messages['servererrormsg'] = 'Serverio klaida: $msg';
 $messages['imaperror'] = 'Nepavyko prisijungti prie IMAP serverio.';
 $messages['servererror'] = 'Serverio klaida!';
 $messages['servererrormsg'] = 'Serverio klaida: $msg';
-$messages['databaserror'] = 'Duomenų bazės klaida!';
+$messages['dberror'] = 'Duomenų bazės klaida!';
 $messages['errorreadonly'] = 'Nepavyko atlikti veiksmo – aplankas prieinamas tik skaitymui.';
 $messages['errornoperm'] = 'Nepavyko atlikti veiksmo – nepakanka teisių.';
 $messages['invalidrequest'] = 'Netinkama užklausa! Duomenys neišsaugoti.';
 $messages['errorreadonly'] = 'Nepavyko atlikti veiksmo – aplankas prieinamas tik skaitymui.';
 $messages['errornoperm'] = 'Nepavyko atlikti veiksmo – nepakanka teisių.';
 $messages['invalidrequest'] = 'Netinkama užklausa! Duomenys neišsaugoti.';
@@ -49,6 +49,7 @@ $messages['blockedimages'] = 'Siekiant apsaugoti Jūsų privatumą, paveikslėli
 $messages['encryptedmessage'] = 'Apgailestaujame, tačiau šis laiškas užšifruotas ir negali būti parodytas.';
 $messages['nocontactsfound'] = 'Adresatų nerasta.';
 $messages['contactnotfound'] = 'Ieškotas adresatas nerastas.';
 $messages['encryptedmessage'] = 'Apgailestaujame, tačiau šis laiškas užšifruotas ir negali būti parodytas.';
 $messages['nocontactsfound'] = 'Adresatų nerasta.';
 $messages['contactnotfound'] = 'Ieškotas adresatas nerastas.';
+$messages['contactsearchonly'] = 'Įveskite reikšminius žodžius adresatų paieškai';
 $messages['sendingfailed'] = 'Laiško išsiųsti nepavyko.';
 $messages['senttooquickly'] = 'Turite luktelėti $sec sek., kad galėtumėte išsiųsti laišką.';
 $messages['errorsavingsent'] = 'Įrašant išsiųstą laišką įvyko klaida.';
 $messages['sendingfailed'] = 'Laiško išsiųsti nepavyko.';
 $messages['senttooquickly'] = 'Turite luktelėti $sec sek., kad galėtumėte išsiųsti laišką.';
 $messages['errorsavingsent'] = 'Įrašant išsiųstą laišką įvyko klaida.';
@@ -62,6 +63,7 @@ $messages['deletegroupconfirm'] = 'Ar tikrai pašalinti pažymėtą grupę?';
 $messages['deletemessagesconfirm'] = 'Ar tikrai pašalinti pažymėtą(-us) laišką(-us)?';
 $messages['deletefolderconfirm'] = 'Ar tikrai pašalinti šį aplanką?';
 $messages['purgefolderconfirm'] = 'Ar tikrai pašalinti visus šiame aplanke esančius laiškus?';
 $messages['deletemessagesconfirm'] = 'Ar tikrai pašalinti pažymėtą(-us) laišką(-us)?';
 $messages['deletefolderconfirm'] = 'Ar tikrai pašalinti šį aplanką?';
 $messages['purgefolderconfirm'] = 'Ar tikrai pašalinti visus šiame aplanke esančius laiškus?';
+$messages['contactdeleting'] = 'Adresatas(-ai) šalinamas(-i)…';
 $messages['groupdeleting'] = 'Grupė šalinama…';
 $messages['folderdeleting'] = 'Aplankas šalinamas…';
 $messages['foldermoving'] = 'Aplankas perkeliamas…';
 $messages['groupdeleting'] = 'Grupė šalinama…';
 $messages['folderdeleting'] = 'Aplankas šalinamas…';
 $messages['foldermoving'] = 'Aplankas perkeliamas…';
@@ -77,10 +79,10 @@ $messages['nosubjectwarning'] = 'Temos laukelis tuščias. Ar norite temą įves
 $messages['nobodywarning'] = 'Išsiųsti šį laišką be teksto?';
 $messages['notsentwarning'] = 'Laiškas neišsiųstas. Ar jūs tikrai norite jo atsikratyti?';
 $messages['noldapserver'] = 'Prašome pasirinkti LDAP serverį paieškai.';
 $messages['nobodywarning'] = 'Išsiųsti šį laišką be teksto?';
 $messages['notsentwarning'] = 'Laiškas neišsiųstas. Ar jūs tikrai norite jo atsikratyti?';
 $messages['noldapserver'] = 'Prašome pasirinkti LDAP serverį paieškai.';
-$messages['nocontactsreturned'] = 'Jokių adresatų nerasta.';
 $messages['nosearchname'] = 'Prašom įvesti vardą arba el. pašto adresą.';
 $messages['notuploadedwarning'] = 'Įkelti dar ne visi priedai. Prašom palaukti arba atšaukti jų įkėlimą.';
 $messages['searchsuccessful'] = 'Rasta laiškų: $nr.';
 $messages['nosearchname'] = 'Prašom įvesti vardą arba el. pašto adresą.';
 $messages['notuploadedwarning'] = 'Įkelti dar ne visi priedai. Prašom palaukti arba atšaukti jų įkėlimą.';
 $messages['searchsuccessful'] = 'Rasta laiškų: $nr.';
+$messages['contactsearchsuccessful'] = 'Rasta adresatų: $nr.';
 $messages['searchnomatch'] = 'Paiešką atitinkančių rezultatų nėra.';
 $messages['searching'] = 'Ieškoma…';
 $messages['checking'] = 'Tikrinama…';
 $messages['searchnomatch'] = 'Paiešką atitinkančių rezultatų nėra.';
 $messages['searching'] = 'Ieškoma…';
 $messages['checking'] = 'Tikrinama…';
@@ -127,7 +129,6 @@ $messages['smtpautherror'] = 'SMTP klaida ($code): nepavyko autentikuotis.';
 $messages['smtpfromerror'] = 'SMTP klaida ($code): nepavyko nurodyti siuntėjo „$from“ ($msg).';
 $messages['smtptoerror'] = 'SMTP klaida ($code): nepavyko pridėti gavėjo „$to“ ($msg).';
 $messages['smtprecipientserror'] = 'SMTP klaida: nepavyko apdoroti gavėjų sąrašo.';
 $messages['smtpfromerror'] = 'SMTP klaida ($code): nepavyko nurodyti siuntėjo „$from“ ($msg).';
 $messages['smtptoerror'] = 'SMTP klaida ($code): nepavyko pridėti gavėjo „$to“ ($msg).';
 $messages['smtprecipientserror'] = 'SMTP klaida: nepavyko apdoroti gavėjų sąrašo.';
-$messages['smtpdsnerror'] = 'SMTP klaida: laiškų pristatymo pažymos nepalaikomos.';
 $messages['smtperror'] = 'SMTP klaida: $msg';
 $messages['emailformaterror'] = 'Netinkamas el. pašto adresas: $email';
 $messages['toomanyrecipients'] = 'Per daug gavėjų. Sumažinkite jų bent iki $max.';
 $messages['smtperror'] = 'SMTP klaida: $msg';
 $messages['emailformaterror'] = 'Netinkamas el. pašto adresas: $email';
 $messages['toomanyrecipients'] = 'Per daug gavėjų. Sumažinkite jų bent iki $max.';
@@ -140,11 +141,16 @@ $messages['contactrestored'] = 'Adresatas(-ai) sėkmingai atkurtas(-i).';
 $messages['groupdeleted'] = 'Grupė sėkmingai pašalinta.';
 $messages['grouprenamed'] = 'Grupė sėkmingai pervardinta.';
 $messages['groupcreated'] = 'Grupė sėkmingai sukurta.';
 $messages['groupdeleted'] = 'Grupė sėkmingai pašalinta.';
 $messages['grouprenamed'] = 'Grupė sėkmingai pervardinta.';
 $messages['groupcreated'] = 'Grupė sėkmingai sukurta.';
+$messages['savedsearchdeleted'] = 'Radinių aplankas sėkmingai pašalintas.';
+$messages['savedsearchdeleteerror'] = 'Radinių aplanko pašalinti nepavyko.';
+$messages['savedsearchcreated'] = 'Radinių aplankas sėkmingai sukurtas.';
+$messages['savedsearchcreateerror'] = 'Radinių aplanko sukurti nepavyko.';
 $messages['messagedeleted'] = 'Laiškas(-ai) sėkmingai pašalintas(-i).';
 $messages['messagemoved'] = 'Laiškas(-ai) sėkmingai perkeltas(-i).';
 $messages['messagecopied'] = 'Laiškas(-ai) sėkmingai nukopijuotas(-i).';
 $messages['messagemarked'] = 'Laiškas(-ai) sėkmingai pažymėtas(-i).';
 $messages['autocompletechars'] = 'Automatiniam užbaigimui būtini bent $min simboliai.';
 $messages['messagedeleted'] = 'Laiškas(-ai) sėkmingai pašalintas(-i).';
 $messages['messagemoved'] = 'Laiškas(-ai) sėkmingai perkeltas(-i).';
 $messages['messagecopied'] = 'Laiškas(-ai) sėkmingai nukopijuotas(-i).';
 $messages['messagemarked'] = 'Laiškas(-ai) sėkmingai pažymėtas(-i).';
 $messages['autocompletechars'] = 'Automatiniam užbaigimui būtini bent $min simboliai.';
+$messages['autocompletemore'] = 'Rasta daugiau atitikmenų. Įveskite dar porą simbolių.';
 $messages['namecannotbeempty'] = 'Vardas negali būti tuščias.';
 $messages['nametoolong'] = 'Vardas yra per ilgas.';
 $messages['folderupdated'] = 'Aplanko savybės sėkmingai atnaujintos.';
 $messages['namecannotbeempty'] = 'Vardas negali būti tuščias.';
 $messages['nametoolong'] = 'Vardas yra per ilgas.';
 $messages['folderupdated'] = 'Aplanko savybės sėkmingai atnaujintos.';
@@ -152,5 +158,6 @@ $messages['foldercreated'] = 'Aplankas sėkmingai sukurtas.';
 $messages['invalidimageformat'] = 'Paveikslo formatas netinkamas.';
 $messages['mispellingsfound'] = 'Laiške rasta rašybos klaidų.';
 $messages['parentnotwritable'] = 'Nepavyko sukurti arba perkelti aplanko į parinktą tėvinį aplanką. Trūksta prieigos teisių.';
 $messages['invalidimageformat'] = 'Paveikslo formatas netinkamas.';
 $messages['mispellingsfound'] = 'Laiške rasta rašybos klaidų.';
 $messages['parentnotwritable'] = 'Nepavyko sukurti arba perkelti aplanko į parinktą tėvinį aplanką. Trūksta prieigos teisių.';
+$messages['messagetoobig'] = 'Laiško dalis yra per didelė, kad galėtų būti apdorota.';
 
 ?>
 
 ?>
index 46bcf80428d5b6d0fa4409a80fe4913ea82374c4..d0df66678610318226aa735e4b3c067b0207b32a 100644 (file)
@@ -16,7 +16,7 @@
 |         Kaspars Tenters <kaspars.tenters@va.lv>                       |
 +-----------------------------------------------------------------------+
 
 |         Kaspars Tenters <kaspars.tenters@va.lv>                       |
 +-----------------------------------------------------------------------+
 
-@version $Id: labels.inc 5175 2011-09-05 18:42:24Z thomasb $
+@version $Id: labels.inc 5173 2011-09-05 18:41:04Z thomasb $
 
 */
 
 
 */
 
index 8c6ab5a158772ea0c304904337f120cf4a5861a8..698baca05bd62a1156e9c9735f552f1242824f28 100644 (file)
@@ -16,7 +16,7 @@
 |         Kaspars Tenters <kaspars.tenters@va.lv>                       |
 +-----------------------------------------------------------------------+
 
 |         Kaspars Tenters <kaspars.tenters@va.lv>                       |
 +-----------------------------------------------------------------------+
 
-@version $Id: messages.inc 5175 2011-09-05 18:42:24Z thomasb $
+@version $Id: messages.inc 5173 2011-09-05 18:41:04Z thomasb $
 
 */
 
 
 */
 
index 1c616a179a15fd414cdc4ff2f5b663a515e96bf9..0186f472c1702fc975126bdd4f055b1ddf570d5a 100644 (file)
@@ -17,7 +17,7 @@
 |         Justin van Beusekom <j.v.beusekom@beus-it.nl>                 |
 +-----------------------------------------------------------------------+
 
 |         Justin van Beusekom <j.v.beusekom@beus-it.nl>                 |
 +-----------------------------------------------------------------------+
 
-@version $Id: labels.inc 4549 2011-02-15 14:33:45Z robin $
+@version $Id: labels.inc 5569 2011-12-07 14:47:32Z thomasb $
 
 */
 
 
 */
 
@@ -104,18 +104,16 @@ $labels['replytomessage'] = 'Beantwoord het bericht';
 $labels['replytoallmessage'] = 'Beantwoord lijst of afzender en alle ontvangers';
 $labels['replyall'] = 'Beantwoord alle ontvangers';
 $labels['replylist'] = 'Beantwoord lijst';
 $labels['replytoallmessage'] = 'Beantwoord lijst of afzender en alle ontvangers';
 $labels['replyall'] = 'Beantwoord alle ontvangers';
 $labels['replylist'] = 'Beantwoord lijst';
+$labels['forwardinline'] = 'Doorsturen in bericht';
+$labels['forwardattachment'] = 'Doorsturen als bijlage';
 $labels['forwardmessage'] = 'Bericht doorsturen';
 $labels['deletemessage'] = 'Verwijder het bericht';
 $labels['movemessagetotrash'] = 'Verplaats het bericht naar de prullenbak';
 $labels['printmessage'] = 'Dit bericht afdrukken';
 $labels['previousmessage'] = 'Toon het vorige bericht';
 $labels['forwardmessage'] = 'Bericht doorsturen';
 $labels['deletemessage'] = 'Verwijder het bericht';
 $labels['movemessagetotrash'] = 'Verplaats het bericht naar de prullenbak';
 $labels['printmessage'] = 'Dit bericht afdrukken';
 $labels['previousmessage'] = 'Toon het vorige bericht';
-$labels['previousmessages'] = 'Toon vorige lijst met berichten';
 $labels['firstmessage'] = 'Toon het eerste bericht';
 $labels['firstmessage'] = 'Toon het eerste bericht';
-$labels['firstmessages'] = 'Toon eerste lijst met berichten';
 $labels['nextmessage'] = 'Toon het volgende bericht';
 $labels['nextmessage'] = 'Toon het volgende bericht';
-$labels['nextmessages'] = 'Toon volgende lijst met berichten';
 $labels['lastmessage'] = 'Toon het laatste bericht';
 $labels['lastmessage'] = 'Toon het laatste bericht';
-$labels['lastmessages'] = 'Toon laatste lijst met berichten';
 $labels['backtolist'] = 'Terug naar berichtenoverzicht';
 $labels['viewsource'] = 'Toon bron';
 $labels['markmessages'] = 'Markeer berichten';
 $labels['backtolist'] = 'Terug naar berichtenoverzicht';
 $labels['viewsource'] = 'Toon bron';
 $labels['markmessages'] = 'Markeer berichten';
@@ -123,7 +121,7 @@ $labels['markread'] = 'Gelezen';
 $labels['markunread'] = 'Ongelezen';
 $labels['markflagged'] = 'Selecteren';
 $labels['markunflagged'] = 'Niet selecteren';
 $labels['markunread'] = 'Ongelezen';
 $labels['markflagged'] = 'Selecteren';
 $labels['markunflagged'] = 'Niet selecteren';
-$labels['messageactions'] = 'Meer acties...';
+$labels['moreactions'] = 'Meer acties';
 $labels['select'] = 'Selecteer';
 $labels['all'] = 'Allemaal';
 $labels['none'] = 'Geen';
 $labels['select'] = 'Selecteer';
 $labels['all'] = 'Allemaal';
 $labels['none'] = 'Geen';
@@ -176,12 +174,15 @@ $labels['charset'] = 'Karakterset';
 $labels['editortype'] = 'Opmaak';
 $labels['returnreceipt'] = 'Ontvangstbevestiging';
 $labels['dsn'] = 'Afleverings status notificatie (DSN)';
 $labels['editortype'] = 'Opmaak';
 $labels['returnreceipt'] = 'Ontvangstbevestiging';
 $labels['dsn'] = 'Afleverings status notificatie (DSN)';
+$labels['mailreplyintro'] = '$sender schreef op $date:';
+$labels['originalmessage'] = 'Originele bericht';
 $labels['editidents'] = 'Bewerk identiteiten';
 $labels['checkspelling'] = 'Controleer spelling';
 $labels['resumeediting'] = 'Doorgaan met opstellen';
 $labels['revertto'] = 'Wijzig terug in';
 $labels['attachments'] = 'Bijlages';
 $labels['upload'] = 'Toevoegen';
 $labels['editidents'] = 'Bewerk identiteiten';
 $labels['checkspelling'] = 'Controleer spelling';
 $labels['resumeediting'] = 'Doorgaan met opstellen';
 $labels['revertto'] = 'Wijzig terug in';
 $labels['attachments'] = 'Bijlages';
 $labels['upload'] = 'Toevoegen';
+$labels['uploadprogress'] = '$percent ($current van $total)';
 $labels['close'] = 'Sluit';
 $labels['messageoptions'] = 'Acties voor bericht...';
 $labels['low'] = 'Laag';
 $labels['close'] = 'Sluit';
 $labels['messageoptions'] = 'Acties voor bericht...';
 $labels['low'] = 'Laag';
@@ -192,6 +193,7 @@ $labels['highest'] = 'Hoogste';
 $labels['nosubject'] = '(geen onderwerp)';
 $labels['showimages'] = 'Toon afbeeldingen';
 $labels['alwaysshow'] = 'Afbeeldingen van $sender altijd tonen';
 $labels['nosubject'] = '(geen onderwerp)';
 $labels['showimages'] = 'Toon afbeeldingen';
 $labels['alwaysshow'] = 'Afbeeldingen van $sender altijd tonen';
+$labels['isdraft'] = 'Dit is een concept.';
 $labels['htmltoggle'] = 'HTML';
 $labels['plaintoggle'] = 'Gewone tekst';
 $labels['savesentmessagein'] = 'Bewaar verzonden bericht in';
 $labels['htmltoggle'] = 'HTML';
 $labels['plaintoggle'] = 'Gewone tekst';
 $labels['savesentmessagein'] = 'Bewaar verzonden bericht in';
@@ -234,6 +236,10 @@ $labels['female'] = 'Vrouw';
 $labels['manager'] = 'Manager';
 $labels['assistant'] = 'Assistent';
 $labels['spouse'] = 'Echtgenoot';
 $labels['manager'] = 'Manager';
 $labels['assistant'] = 'Assistent';
 $labels['spouse'] = 'Echtgenoot';
+$labels['allfields'] = 'Alle velden';
+$labels['search'] = 'Zoeken';
+$labels['advsearch'] = 'Geavanceerd zoeken';
+$labels['other'] = 'Anders';
 $labels['typehome'] = 'Thuis';
 $labels['typework'] = 'Werk';
 $labels['typeother'] = 'Anders';
 $labels['typehome'] = 'Thuis';
 $labels['typework'] = 'Werk';
 $labels['typeother'] = 'Anders';
@@ -245,6 +251,9 @@ $labels['typecar'] = 'Auto';
 $labels['typepager'] = 'Pieper';
 $labels['typevideo'] = 'Video';
 $labels['typeassistant'] = 'Assistent';
 $labels['typepager'] = 'Pieper';
 $labels['typevideo'] = 'Video';
 $labels['typeassistant'] = 'Assistent';
+$labels['typehomepage'] = 'Website';
+$labels['typeblog'] = 'Blog';
+$labels['typeprofile'] = 'Profiel';
 $labels['addfield'] = 'Veld toevoegen...';
 $labels['addcontact'] = 'Nieuwe contactpersoon toevoegen';
 $labels['editcontact'] = 'Contactpersoon wijzigen';
 $labels['addfield'] = 'Veld toevoegen...';
 $labels['addcontact'] = 'Nieuwe contactpersoon toevoegen';
 $labels['editcontact'] = 'Contactpersoon wijzigen';
@@ -266,7 +275,8 @@ $labels['print'] = 'Afdrukken';
 $labels['export'] = 'Exporteren';
 $labels['exportvcards'] = 'Exporteer contactpersonen in vCard formaat';
 $labels['newcontactgroup'] = 'Maak een nieuwe contactgroep';
 $labels['export'] = 'Exporteren';
 $labels['exportvcards'] = 'Exporteer contactpersonen in vCard formaat';
 $labels['newcontactgroup'] = 'Maak een nieuwe contactgroep';
-$labels['groupactions'] = 'Acties voor contactgroepen...';
+$labels['grouprename'] = 'Groep hernoemen';
+$labels['groupdelete'] = 'Groep verwijderen';
 $labels['previouspage'] = 'Vorige pagina';
 $labels['firstpage'] = 'Eerste pagina';
 $labels['nextpage'] = 'Volgende pagina';
 $labels['previouspage'] = 'Vorige pagina';
 $labels['firstpage'] = 'Eerste pagina';
 $labels['nextpage'] = 'Volgende pagina';
@@ -274,9 +284,12 @@ $labels['lastpage'] = 'Laatste pagina';
 $labels['group'] = 'Groep';
 $labels['groups'] = 'Groepen';
 $labels['personaladrbook'] = 'Persoonlijk Adresboek';
 $labels['group'] = 'Groep';
 $labels['groups'] = 'Groepen';
 $labels['personaladrbook'] = 'Persoonlijk Adresboek';
+$labels['searchsave'] = 'Zoekopdracht opslaan';
+$labels['searchdelete'] = 'Zoekopdracht verwijderen';
 $labels['import'] = 'Importeer';
 $labels['importcontacts'] = 'Contactpersonen importeren';
 $labels['importfromfile'] = 'Importeer van bestand:';
 $labels['import'] = 'Importeer';
 $labels['importcontacts'] = 'Contactpersonen importeren';
 $labels['importfromfile'] = 'Importeer van bestand:';
+$labels['importtarget'] = 'Voeg nieuwe contactpersonen toe aan adresboek:';
 $labels['importreplace'] = 'Vervang het complete adresboek';
 $labels['importtext'] = 'U kunt hier contactpersonen importeren vanuit een bestaand adresboek.<br />Op dit moment ondersteunen wij het <a href="http://nl.wikipedia.org/wiki/VCard">vCard</a> bestandsformaat.';
 $labels['done'] = 'Klaar';
 $labels['importreplace'] = 'Vervang het complete adresboek';
 $labels['importtext'] = 'U kunt hier contactpersonen importeren vanuit een bestaand adresboek.<br />Op dit moment ondersteunen wij het <a href="http://nl.wikipedia.org/wiki/VCard">vCard</a> bestandsformaat.';
 $labels['done'] = 'Klaar';
@@ -292,6 +305,8 @@ $labels['edititem'] = 'Wijzig item';
 $labels['preferhtml'] = 'Toon HTML';
 $labels['defaultcharset'] = 'Standaard karakterset';
 $labels['htmlmessage'] = 'HTML-Bericht';
 $labels['preferhtml'] = 'Toon HTML';
 $labels['defaultcharset'] = 'Standaard karakterset';
 $labels['htmlmessage'] = 'HTML-Bericht';
+$labels['dateformat'] = 'Datum formaat';
+$labels['timeformat'] = 'Tijd formaat';
 $labels['prettydate'] = 'Gebruiksvriendelijke data';
 $labels['setdefault'] = 'Stel in als standaard';
 $labels['autodetect'] = 'Automatisch';
 $labels['prettydate'] = 'Gebruiksvriendelijke data';
 $labels['setdefault'] = 'Stel in als standaard';
 $labels['autodetect'] = 'Automatisch';
@@ -362,6 +377,14 @@ $labels['afternseconds'] = 'Na $n seconden';
 $labels['reqmdn'] = 'Vraag altijd een ontvangstbevestiging';
 $labels['reqdsn'] = 'Vraag altijd een afleverings status notificatie (DSN)';
 $labels['replysamefolder'] = 'Plaats antwoorden in de folder van het beantwoorde bericht';
 $labels['reqmdn'] = 'Vraag altijd een ontvangstbevestiging';
 $labels['reqdsn'] = 'Vraag altijd een afleverings status notificatie (DSN)';
 $labels['replysamefolder'] = 'Plaats antwoorden in de folder van het beantwoorde bericht';
+$labels['defaultaddressbook'] = 'Voeg nieuw contactpersoon toe aan geselecteerd adresboek';
+$labels['autocompletesingle'] = 'Sla alternatieve E-mail adressen over bij automatisch aanvullen';
+$labels['spellcheckbeforesend'] = 'Controleer slepping voordat het bericht wordt verzonden';
+$labels['spellcheckoptions'] = 'Instellingen spellingscontrole';
+$labels['spellcheckignoresyms'] = 'Negeer woorden met symbolen';
+$labels['spellcheckignorenums'] = 'Negeer woorden met cijfers';
+$labels['spellcheckignorecaps'] = 'Negeer woorden welke volledig uit hoofdletters bestaan';
+$labels['addtodict'] = 'Voeg toe aan woordenboek';
 $labels['folder'] = 'Map';
 $labels['folders'] = 'Mappen';
 $labels['foldername'] = 'Mapnaam';
 $labels['folder'] = 'Map';
 $labels['folders'] = 'Mappen';
 $labels['foldername'] = 'Mapnaam';
@@ -378,9 +401,14 @@ $labels['location'] = 'Locatie';
 $labels['info'] = 'Informatie';
 $labels['getfoldersize'] = 'Klik hier voor de map grootte';
 $labels['changesubscription'] = 'Klik voor het wijzigen van de inschrijving';
 $labels['info'] = 'Informatie';
 $labels['getfoldersize'] = 'Klik hier voor de map grootte';
 $labels['changesubscription'] = 'Klik voor het wijzigen van de inschrijving';
+$labels['foldertype'] = 'Mapgrootte';
+$labels['personalfolder'] = 'Privé map';
+$labels['otherfolder'] = 'Map van andere gebruiker';
+$labels['sharedfolder'] = 'Publieke map';
 $labels['sortby'] = 'Sorteer op';
 $labels['sortasc'] = 'Sorteer oplopend';
 $labels['sortdesc'] = 'Sorteer aflopend';
 $labels['sortby'] = 'Sorteer op';
 $labels['sortasc'] = 'Sorteer oplopend';
 $labels['sortdesc'] = 'Sorteer aflopend';
+$labels['undo'] = 'Ongedaan maken';
 $labels['B'] = 'B';
 $labels['KB'] = 'KB';
 $labels['MB'] = 'MB';
 $labels['B'] = 'B';
 $labels['KB'] = 'KB';
 $labels['MB'] = 'MB';
index 8c5038362330cf657a988267301e27ec32716a20..37ece88eb6f63c2009e56fb57c9abd27b66f2095 100644 (file)
 |         Justin van Beusekom <j.v.beusekom@beus-it.nl>                 |
 +-----------------------------------------------------------------------+
 
 |         Justin van Beusekom <j.v.beusekom@beus-it.nl>                 |
 +-----------------------------------------------------------------------+
 
-@version $Id: messages.inc 5067 2011-08-14 18:47:58Z thomasb $
+@version $Id: messages.inc 5569 2011-12-07 14:47:32Z thomasb $
 
 */
 
 $messages = array();
 
 */
 
 $messages = array();
-$messages['loginfailed'] = 'Inloggen mislukt';
-$messages['cookiesdisabled'] = 'Uw browser accepteert geen cookies';
-$messages['sessionerror'] = 'Uw sessie is verlopen of ongeldig';
-$messages['imaperror'] = 'Connectie met IMAP server mislukt';
+$messages['loginfailed'] = 'Inloggen mislukt.';
+$messages['cookiesdisabled'] = 'Uw browser accepteert geen cookies.';
+$messages['sessionerror'] = 'Uw sessie is verlopen of ongeldig.';
+$messages['imaperror'] = 'Connectie met IMAP server mislukt.';
 $messages['servererror'] = 'Server Fout!';
 $messages['servererrormsg'] = 'Server Fout: $msg';
 $messages['servererror'] = 'Server Fout!';
 $messages['servererrormsg'] = 'Server Fout: $msg';
-$messages['databaserror'] = 'Database Fout!';
-$messages['errorreadonly'] = 'Niet in staat om de bewerking uit te voeren. Map is alleen-lezen';
-$messages['errornoperm'] = 'Niet in staat om de bewerking uit te voeren. Toestemming geweigerd';
+$messages['dberror'] = 'Database Fout!';
+$messages['errorreadonly'] = 'Niet in staat om de bewerking uit te voeren. Map is alleen-lezen.';
+$messages['errornoperm'] = 'Niet in staat om de bewerking uit te voeren. Toestemming geweigerd.';
 $messages['invalidrequest'] = 'Ongeldige aanvraag! Er zijn geen gegevens opgeslagen.';
 $messages['invalidrequest'] = 'Ongeldige aanvraag! Er zijn geen gegevens opgeslagen.';
-$messages['nomessagesfound'] = 'Geen berichten gevonden in deze mailbox';
+$messages['nomessagesfound'] = 'Geen berichten gevonden in deze mailbox.';
 $messages['loggedout'] = 'Succesvol uitgelogd. Tot ziens!';
 $messages['loggedout'] = 'Succesvol uitgelogd. Tot ziens!';
-$messages['mailboxempty'] = 'Mailbox is leeg';
+$messages['mailboxempty'] = 'Mailbox is leeg.';
 $messages['loading'] = 'Laden...';
 $messages['loading'] = 'Laden...';
-$messages['uploading'] = 'Bezig met uploaden...';
+$messages['uploading'] = 'Bestand wordt geüpload...';
+$messages['uploadingmany'] = 'Bestanden worden geüpload...';
 $messages['loadingdata'] = 'Laden van data...';
 $messages['checkingmail'] = 'Controleren op nieuwe berichten...';
 $messages['sendingmessage'] = 'Bezig met bericht versturen...';
 $messages['loadingdata'] = 'Laden van data...';
 $messages['checkingmail'] = 'Controleren op nieuwe berichten...';
 $messages['sendingmessage'] = 'Bezig met bericht versturen...';
-$messages['messagesent'] = 'Bericht succesvol verstuurd';
+$messages['messagesent'] = 'Bericht succesvol verstuurd.';
 $messages['savingmessage'] = 'Bezig met bericht opslaan...';
 $messages['savingmessage'] = 'Bezig met bericht opslaan...';
-$messages['messagesaved'] = 'Bericht bewaard als concept';
-$messages['successfullysaved'] = 'Succesvol opgeslagen';
-$messages['addedsuccessfully'] = 'Contact is succesvol toegevoegd aan het adresboek';
-$messages['contactexists'] = 'Er bestaat al een contactpersoon met dit e-mailadres';
+$messages['messagesaved'] = 'Bericht bewaard als concept.';
+$messages['successfullysaved'] = 'Succesvol opgeslagen.';
+$messages['addedsuccessfully'] = 'Contact is succesvol toegevoegd aan het adresboek.';
+$messages['contactexists'] = 'Er bestaat al een contactpersoon met dit e-mailadres.';
+$messages['contactnameexists'] = 'Er bestaat al een contactpersoon met deze naam.';
 $messages['blockedimages'] = 'Uit privacyoverwegingen zijn niet bijgevoegde afbeeldingen geblokkeerd in dit bericht.';
 $messages['encryptedmessage'] = 'Dit is een gecodeerd bericht en kan niet weergegeven worden. Excuses!';
 $messages['blockedimages'] = 'Uit privacyoverwegingen zijn niet bijgevoegde afbeeldingen geblokkeerd in dit bericht.';
 $messages['encryptedmessage'] = 'Dit is een gecodeerd bericht en kan niet weergegeven worden. Excuses!';
-$messages['nocontactsfound'] = 'Geen contactpersonen gevonden';
-$messages['contactnotfound'] = 'Contactpersoon niet gevonden';
-$messages['sendingfailed'] = 'Verzenden van bericht is mislukt';
+$messages['nocontactsfound'] = 'Geen contactpersonen gevonden.';
+$messages['contactnotfound'] = 'Contactpersoon niet gevonden.';
+$messages['contactsearchonly'] = 'Voer enkele zoektermen in om contactpersonen te zoeken.';
+$messages['sendingfailed'] = 'Verzenden van bericht is mislukt.';
 $messages['senttooquickly'] = 'Je moet $sec seconden wachten om het bericht te versturen.';
 $messages['senttooquickly'] = 'Je moet $sec seconden wachten om het bericht te versturen.';
-$messages['errorsavingsent'] = 'Er is een fout opgetreden tijdens het opslaan van het verzonden bericht';
-$messages['errorsaving'] = 'Er is een fout opgetreden tijdens het opslaan';
-$messages['errormoving'] = 'Kan het bericht niet verplaatsen';
-$messages['errorcopying'] = 'Kan de bericht(en) niet kopiëren';
-$messages['errordeleting'] = 'Kan het bericht niet verwijderen';
-$messages['errormarking'] = 'Kon bericht niet markeren';
+$messages['errorsavingsent'] = 'Er is een fout opgetreden tijdens het opslaan van het verzonden bericht.';
+$messages['errorsaving'] = 'Er is een fout opgetreden tijdens het opslaan.';
+$messages['errormoving'] = 'Kan het bericht niet verplaatsen.';
+$messages['errorcopying'] = 'Kan de bericht(en) niet kopiëren.';
+$messages['errordeleting'] = 'Kan het bericht niet verwijderen.';
+$messages['errormarking'] = 'Kon bericht niet markeren.';
 $messages['deletecontactconfirm'] = 'Weet u zeker dat u de geselecteerde contactperso(o)n/en wilt verwijderen?';
 $messages['deletecontactconfirm'] = 'Weet u zeker dat u de geselecteerde contactperso(o)n/en wilt verwijderen?';
+$messages['deletegroupconfirm'] = 'Weet u zeker dat u de geselecteerde groep wilt verwijderen?';
 $messages['deletemessagesconfirm'] = 'Weet u zeker dat u de geselecteerde bericht(en) wilt verwijderen?';
 $messages['deletefolderconfirm'] = 'Weet u zeker dat u deze map wilt verwijderen?';
 $messages['purgefolderconfirm'] = 'Weet u zeker dat u alle berichten in deze map wilt verwijderen?';
 $messages['deletemessagesconfirm'] = 'Weet u zeker dat u de geselecteerde bericht(en) wilt verwijderen?';
 $messages['deletefolderconfirm'] = 'Weet u zeker dat u deze map wilt verwijderen?';
 $messages['purgefolderconfirm'] = 'Weet u zeker dat u alle berichten in deze map wilt verwijderen?';
-$messages['folderdeleting'] = 'Map verwijderen...';
-$messages['foldermoving'] = 'Map verplaatsen...';
-$messages['foldersubscribing'] = 'Abonneren map...';
-$messages['folderunsubscribing'] = 'Afmelding map ...';
-$messages['formincomplete'] = 'Het formulier was niet volledig ingevuld';
-$messages['noemailwarning'] = 'Geef een geldig e-mailadres op';
-$messages['nonamewarning'] = 'Vul een naam in';
-$messages['nopagesizewarning'] = 'Geef een paginagrootte op';
-$messages['nosenderwarning'] = 'Geef een e-mailadres van de afzender op';
-$messages['norecipientwarning'] = 'Geef tenminste één ontvanger op';
+$messages['contactdeleting'] = 'Bezig met verwijderen één of meer contactpersonen...';
+$messages['groupdeleting'] = 'Groep wordt verwijderd...';
+$messages['folderdeleting'] = 'Map wordt verwijderd...';
+$messages['foldermoving'] = 'Map wordt verplaatst...';
+$messages['foldersubscribing'] = 'Bezig met abonneren op map...';
+$messages['folderunsubscribing'] = 'Abonnement op map wordt opgezegd...';
+$messages['formincomplete'] = 'Het formulier was niet volledig ingevuld.';
+$messages['noemailwarning'] = 'Geef een geldig e-mailadres op.';
+$messages['nonamewarning'] = 'Vul een naam in.';
+$messages['nopagesizewarning'] = 'Geef een paginagrootte op.';
+$messages['nosenderwarning'] = 'Geef een e-mailadres van de afzender op.';
+$messages['norecipientwarning'] = 'Geef tenminste één ontvanger op.';
 $messages['nosubjectwarning'] = 'Het \'Onderwerp\' veld is leeg. Wilt u nu alsnog een onderwerp opgeven?';
 $messages['nobodywarning'] = 'Dit bericht zonder inhoud versturen?';
 $messages['notsentwarning'] = 'Bericht is niet verstuurd. Weet u zeker dat u het niet wilt bewaren?';
 $messages['nosubjectwarning'] = 'Het \'Onderwerp\' veld is leeg. Wilt u nu alsnog een onderwerp opgeven?';
 $messages['nobodywarning'] = 'Dit bericht zonder inhoud versturen?';
 $messages['notsentwarning'] = 'Bericht is niet verstuurd. Weet u zeker dat u het niet wilt bewaren?';
-$messages['noldapserver'] = 'Geef een LDAP adresboek server op om te doorzoeken';
-$messages['nocontactsreturned'] = 'Er zijn geen contactpersonen gevonden';
-$messages['nosearchname'] = 'Geef de naam of e-mail op van de contactpersoon';
+$messages['noldapserver'] = 'Geef een LDAP adresboek server op om te doorzoeken.';
+$messages['nosearchname'] = 'Geef de naam of e-mail op van de contactpersoon.';
 $messages['notuploadedwarning'] = 'Nog niet alle bijlagen zijn geüpload. Wacht even of annuleer de upload.';
 $messages['notuploadedwarning'] = 'Nog niet alle bijlagen zijn geüpload. Wacht even of annuleer de upload.';
-$messages['searchsuccessful'] = '$nr berichten gevonden';
-$messages['searchnomatch'] = 'Zoekopdracht heeft geen resultaten opgeleverd';
+$messages['searchsuccessful'] = '$nr berichten gevonden.';
+$messages['contactsearchsuccessful'] = '$nr contactpersonen gevonden.';
+$messages['searchnomatch'] = 'Zoekopdracht heeft geen resultaten opgeleverd.';
 $messages['searching'] = 'Zoeken...';
 $messages['checking'] = 'Controleren...';
 $messages['searching'] = 'Zoeken...';
 $messages['checking'] = 'Controleren...';
-$messages['nospellerrors'] = 'Geen spelfouten gevonden';
-$messages['folderdeleted'] = 'Map successvol verwijderd';
-$messages['foldersubscribed'] = 'Folder succesvol geabonneerd';
-$messages['folderunsubscribed'] = 'Folder succesvol uitgeschreven';
-$messages['folderpurged'] = 'Folder met succes geleegd';
-$messages['folderexpunged'] = 'Folder succesvol geleegd';
-$messages['deletedsuccessfully'] = 'Successvol verwijderd';
+$messages['nospellerrors'] = 'Geen spelfouten gevonden.';
+$messages['folderdeleted'] = 'Map successvol verwijderd.';
+$messages['foldersubscribed'] = 'Folder succesvol geabonneerd.';
+$messages['folderunsubscribed'] = 'Folder succesvol uitgeschreven.';
+$messages['folderpurged'] = 'Folder met succes geleegd.';
+$messages['folderexpunged'] = 'Folder succesvol geleegd.';
+$messages['deletedsuccessfully'] = 'Successvol verwijderd.';
 $messages['converting'] = 'Opmaak van bericht verwijderen...';
 $messages['converting'] = 'Opmaak van bericht verwijderen...';
-$messages['messageopenerror'] = 'Kan het bericht niet van de server laden';
-$messages['fileuploaderror'] = 'Bestand uploaden mislukt';
-$messages['filesizeerror'] = 'Het bestand overschrijdt de maximale grootte van $size';
-$messages['copysuccess'] = '$nr adressen succesvol gekopieerd';
-$messages['copyerror'] = 'Kan geen adressen kopiëren';
-$messages['sourceisreadonly'] = 'Het adres is alleen-lezen';
-$messages['errorsavingcontact'] = 'Kan het ontvanger-adres niet opslaan';
+$messages['messageopenerror'] = 'Kan het bericht niet van de server laden.';
+$messages['fileuploaderror'] = 'Bestand uploaden mislukt.';
+$messages['filesizeerror'] = 'Het bestand overschrijdt de maximale grootte van $size.';
+$messages['copysuccess'] = '$nr adressen succesvol gekopieerd.';
+$messages['copyerror'] = 'Kan geen adressen kopiëren.';
+$messages['sourceisreadonly'] = 'Het adres is alleen-lezen.';
+$messages['errorsavingcontact'] = 'Kan het ontvanger-adres niet opslaan.';
 $messages['movingmessage'] = 'Bericht verplaatsen...';
 $messages['copyingmessage'] = 'Kopiëren bericht...';
 $messages['movingmessage'] = 'Bericht verplaatsen...';
 $messages['copyingmessage'] = 'Kopiëren bericht...';
+$messages['copyingcontact'] = 'Kopiëren contactpersonen...';
 $messages['deletingmessage'] = 'Verwijderen bericht(en)...';
 $messages['markingmessage'] = 'Markeren bericht(en)...';
 $messages['deletingmessage'] = 'Verwijderen bericht(en)...';
 $messages['markingmessage'] = 'Markeren bericht(en)...';
-$messages['receiptsent'] = 'Ontvangstbevestiging is verstuurd';
-$messages['errorsendingreceipt'] = 'Kan de ontvangstbevestiging niet versturen';
-$messages['nodeletelastidentity'] = 'U kunt uw enige identiteit niet verwijderen';
-$messages['forbiddencharacter'] = 'De naam van de map bevat een karakter dat niet is toegestaan';
-$messages['selectimportfile'] = 'Selecteer een bestand om de uploaden';
-$messages['addresswriterror'] = 'Het geselecteerde adresboek is alleen lezen';
-$messages['contactaddedtogroup'] = 'Contact(en) met succes toegevoegd aan de groep';
-$messages['contactremovedfromgroup'] = 'Contact(en) met succes verwijderd aan de groep';
+$messages['addingmember'] = 'Contactpersonen worden toegevoegd aan de groep...';
+$messages['removingmember'] = 'Contactpersonen worden verwijderd uit de groep...';
+$messages['receiptsent'] = 'Ontvangstbevestiging is verstuurd.';
+$messages['errorsendingreceipt'] = 'Kan de ontvangstbevestiging niet versturen.';
+$messages['nodeletelastidentity'] = 'U kunt uw enige identiteit niet verwijderen.';
+$messages['forbiddencharacter'] = 'De naam van de map bevat een karakter dat niet is toegestaan.';
+$messages['selectimportfile'] = 'Selecteer een bestand om de uploaden.';
+$messages['addresswriterror'] = 'Het geselecteerde adresboek is alleen lezen.';
+$messages['contactaddedtogroup'] = 'Contact(en) met succes toegevoegd aan de groep.';
+$messages['contactremovedfromgroup'] = 'Contact(en) met succes verwijderd aan de groep.';
 $messages['importwait'] = 'Importeren, even geduld...';
 $messages['importerror'] = 'Importeren mislukt! Het verstuurde bestand is geen geldig vCard bestand.';
 $messages['importconfirm'] = '<b>Er zijn $inserted contactpersonen succesvol geïmporteerd, en $skipped bestaande overgeslagen</b>:<p><em>$names</em></p>';
 $messages['importconfirmskipped'] = '<b>$skipped bestaande contactpersonen overgeslagen</b>';
 $messages['opnotpermitted'] = 'Deze verrichting is niet toegestaan!';
 $messages['importwait'] = 'Importeren, even geduld...';
 $messages['importerror'] = 'Importeren mislukt! Het verstuurde bestand is geen geldig vCard bestand.';
 $messages['importconfirm'] = '<b>Er zijn $inserted contactpersonen succesvol geïmporteerd, en $skipped bestaande overgeslagen</b>:<p><em>$names</em></p>';
 $messages['importconfirmskipped'] = '<b>$skipped bestaande contactpersonen overgeslagen</b>';
 $messages['opnotpermitted'] = 'Deze verrichting is niet toegestaan!';
-$messages['nofromaddress'] = 'Het e-mailadres mist in de geselecteerde identiteit';
+$messages['nofromaddress'] = 'Het e-mailadres mist in de geselecteerde identiteit.';
 $messages['editorwarning'] = 'Door het overschakelen naar de platte tekst editor gaat alle opmaak verloren. Weet je zeker dat je verder wil gaan?';
 $messages['httpreceivedencrypterror'] = 'Er is een fatale fout opgetreden. Neem direct contact op met uw systeembeheerder. <b>Uw bericht kon niet worden verzonden.</b>';
 $messages['editorwarning'] = 'Door het overschakelen naar de platte tekst editor gaat alle opmaak verloren. Weet je zeker dat je verder wil gaan?';
 $messages['httpreceivedencrypterror'] = 'Er is een fatale fout opgetreden. Neem direct contact op met uw systeembeheerder. <b>Uw bericht kon niet worden verzonden.</b>';
-$messages['smtpconnerror'] = 'SMTP Fout ($code): Verbinding met server mislukt';
-$messages['smtpautherror'] = 'SMTP Fout ($code): Autenticatie mislukt';
-$messages['smtpfromerror'] = 'SMTP Fout ($code): Kon afzender "$from" niet instellen ($msg)';
-$messages['smtptoerror'] = 'SMTP Fout ($code): Kon ontvanger "$to" niet toevoegen ($msg)';
-$messages['smtprecipientserror'] = 'SMTP Fout: Kon lijst van ontvangers niet verwerken';
-$messages['smtpdsnerror'] = 'SMTP Fout: Delivery Status Notifications worden niet ondersteund';
+$messages['smtpconnerror'] = 'SMTP Fout ($code): Verbinding met server mislukt.';
+$messages['smtpautherror'] = 'SMTP Fout ($code): Autenticatie mislukt.';
+$messages['smtpfromerror'] = 'SMTP Fout ($code): Kon afzender "$from" niet instellen ($msg).';
+$messages['smtptoerror'] = 'SMTP Fout ($code): Kon ontvanger "$to" niet toevoegen ($msg).';
+$messages['smtprecipientserror'] = 'SMTP Fout: Kon lijst van ontvangers niet verwerken.';
 $messages['smtperror'] = 'SMTP Fout: $msg';
 $messages['emailformaterror'] = 'Ongeldig e-mailadres: $email';
 $messages['smtperror'] = 'SMTP Fout: $msg';
 $messages['emailformaterror'] = 'Ongeldig e-mailadres: $email';
-$messages['toomanyrecipients'] = 'Te veel geadresseerden. Verminder de hoeveelheid geadresseerden tot $max';
-$messages['maxgroupmembersreached'] = 'Het aantal leden van de groep groter is dan de maximale van $max';
-$messages['internalerror'] = 'Er is een interne fout opgetreden. Probeer het nogmaals';
-$messages['contactdelerror'] = 'Kon contact(en) niet verwijderen';
-$messages['contactdeleted'] = 'Contact(en) succesvol verwijderd';
+$messages['toomanyrecipients'] = 'Te veel geadresseerden. Verminder de hoeveelheid geadresseerden tot $max.';
+$messages['maxgroupmembersreached'] = 'Het aantal leden van de groep groter is dan de maximale van $max.';
+$messages['internalerror'] = 'Er is een interne fout opgetreden. Probeer het nogmaals.';
+$messages['contactdelerror'] = 'Kon contact(en) niet verwijderen.';
+$messages['contactdeleted'] = 'Contact(en) succesvol verwijderd.';
 $messages['contactrestoreerror'] = 'Verwijderde contactpersonen konden niet hersteld worden';
 $messages['contactrestoreerror'] = 'Verwijderde contactpersonen konden niet hersteld worden';
-$messages['contactrestored'] = 'Contactpersonen succesvol hersteld';
-$messages['groupdeleted'] = 'Groep succesvol verwijderd';
-$messages['grouprenamed'] = 'Groep succesvol hernoemd';
-$messages['groupcreated'] = 'Groep succesvol aangemaakt';
-$messages['messagedeleted'] = 'Bericht(en) succesvol verwijderd';
-$messages['messagemoved'] = 'Bericht(en) succesvol verplaatst';
-$messages['messagecopied'] = 'Bericht(en) succesvol gekopieerd';
-$messages['messagemarked'] = 'Bericht(en) succesvol gemarkeerd';
-$messages['autocompletechars'] = 'Voer ten minste $min karakters in voor automatisch aanvullen';
+$messages['contactrestored'] = 'Contactpersonen succesvol hersteld.';
+$messages['groupdeleted'] = 'Groep succesvol verwijderd.';
+$messages['grouprenamed'] = 'Groep succesvol hernoemd.';
+$messages['groupcreated'] = 'Groep succesvol aangemaakt.';
+$messages['savedsearchdeleted'] = 'Opgeslagen zoekopdracht successvol verwijderd.';
+$messages['savedsearchdeleteerror'] = 'Opgeslagen zoekopdracht kon niet worden verwijderd.';
+$messages['savedsearchcreated'] = 'Zoekopdracht successvol opgeslagen.';
+$messages['savedsearchcreateerror'] = 'Zoekopdracht kon niet worden opgeslagen.';
+$messages['messagedeleted'] = 'Bericht(en) succesvol verwijderd.';
+$messages['messagemoved'] = 'Bericht(en) succesvol verplaatst.';
+$messages['messagecopied'] = 'Bericht(en) succesvol gekopieerd.';
+$messages['messagemarked'] = 'Bericht(en) succesvol gemarkeerd.';
+$messages['autocompletechars'] = 'Voer ten minste $min karakters in voor automatisch aanvullen.';
+$messages['autocompletemore'] = 'Meerdere resultaten gevonden. Verfijn uw zoekopdracht.';
 $messages['namecannotbeempty'] = 'Naam kan niet leeg zijn';
 $messages['nametoolong'] = 'Naam is te lang';
 $messages['folderupdated'] = 'Map succesvol bijgewerkt';
 $messages['foldercreated'] = 'Map succesvol aangemaakt';
 $messages['invalidimageformat'] = 'Geen geldig afbeeldings formaat';
 $messages['mispellingsfound'] = 'Spelfouten gedetecteerd in bericht';
 $messages['namecannotbeempty'] = 'Naam kan niet leeg zijn';
 $messages['nametoolong'] = 'Naam is te lang';
 $messages['folderupdated'] = 'Map succesvol bijgewerkt';
 $messages['foldercreated'] = 'Map succesvol aangemaakt';
 $messages['invalidimageformat'] = 'Geen geldig afbeeldings formaat';
 $messages['mispellingsfound'] = 'Spelfouten gedetecteerd in bericht';
-$messages['itemsdeleted'] = '$num items zijn verwijderd';
+$messages['parentnotwritable'] = 'U heeft niet voldoende rechten een map te maken / verplaatsen in deze map.';
 
 ?>
 
 ?>
index a4e6d31eaa20ad86aba73941e9de17d0ef2cb749..9146517fb93808648f6c1bd8b428a71ed6edf4fa 100644 (file)
@@ -14,7 +14,7 @@
 | Update: Odin Omdal Hørthe <odin.omdal@gmail.com>                      |
 +-----------------------------------------------------------------------+
 
 | Update: Odin Omdal Hørthe <odin.omdal@gmail.com>                      |
 +-----------------------------------------------------------------------+
 
-@version $Id: labels.inc 4410 2011-01-12 18:25:02Z thomasb $
+@version $Id: labels.inc 5290 2011-09-28 17:09:50Z thomasb $
 
 */
 
 
 */
 
@@ -39,11 +39,11 @@ $labels['to'] = 'Mottakar';
 $labels['cc'] = 'Kopi';
 $labels['bcc'] = 'Blindkopi';
 $labels['replyto'] = 'Svar-til';
 $labels['cc'] = 'Kopi';
 $labels['bcc'] = 'Blindkopi';
 $labels['replyto'] = 'Svar-til';
+$labels['followupto'] = 'Oppfylging-til';
 $labels['date'] = 'Dato';
 $labels['size'] = 'Storleik';
 $labels['priority'] = 'Prioritet';
 $labels['organization'] = 'Organisasjon';
 $labels['date'] = 'Dato';
 $labels['size'] = 'Storleik';
 $labels['priority'] = 'Prioritet';
 $labels['organization'] = 'Organisasjon';
-$labels['reply-to'] = 'Svar-til';
 $labels['mailboxlist'] = 'Katalogar';
 $labels['messagesfromto'] = 'Meldingar $from til $to av $count';
 $labels['threadsfromto'] = 'Trådar $from til $to ($count stk)';
 $labels['mailboxlist'] = 'Katalogar';
 $labels['messagesfromto'] = 'Meldingar $from til $to av $count';
 $labels['threadsfromto'] = 'Trådar $from til $to ($count stk)';
@@ -98,18 +98,18 @@ $labels['checkmail'] = 'Sjå etter nye meldingar';
 $labels['writenewmessage'] = 'Skriv ei ny melding';
 $labels['replytomessage'] = 'Svar på meldinga';
 $labels['replytoallmessage'] = 'Svar til sendar og alle mottakarar';
 $labels['writenewmessage'] = 'Skriv ei ny melding';
 $labels['replytomessage'] = 'Svar på meldinga';
 $labels['replytoallmessage'] = 'Svar til sendar og alle mottakarar';
+$labels['replyall'] = 'Svar til alle';
+$labels['replylist'] = 'Svar til liste';
+$labels['forwardinline'] = 'Send vidare innebygd';
+$labels['forwardattachment'] = 'Send vidare som vedlegg';
 $labels['forwardmessage'] = 'Vidaresend meldinga';
 $labels['deletemessage'] = 'Slett melding';
 $labels['movemessagetotrash'] = 'Flytt melding til «sletta element»';
 $labels['printmessage'] = 'Skriv ut meldinga';
 $labels['previousmessage'] = 'Vis føregåande melding';
 $labels['forwardmessage'] = 'Vidaresend meldinga';
 $labels['deletemessage'] = 'Slett melding';
 $labels['movemessagetotrash'] = 'Flytt melding til «sletta element»';
 $labels['printmessage'] = 'Skriv ut meldinga';
 $labels['previousmessage'] = 'Vis føregåande melding';
-$labels['previousmessages'] = 'Vis føregåande side med meldingar';
 $labels['firstmessage'] = 'Vis den fyrste meldinga';
 $labels['firstmessage'] = 'Vis den fyrste meldinga';
-$labels['firstmessages'] = 'Vis fyrste side med meldingar';
 $labels['nextmessage'] = 'Vis den neste meldinga';
 $labels['nextmessage'] = 'Vis den neste meldinga';
-$labels['nextmessages'] = 'Vis neste side med med meldingar';
 $labels['lastmessage'] = 'Vis den siste meldinga';
 $labels['lastmessage'] = 'Vis den siste meldinga';
-$labels['lastmessages'] = 'Vis den siste sida med meldingar';
 $labels['backtolist'] = 'Tilbake til meldingslista';
 $labels['viewsource'] = 'Vis kjelde';
 $labels['markmessages'] = 'Marker meldingar';
 $labels['backtolist'] = 'Tilbake til meldingslista';
 $labels['viewsource'] = 'Vis kjelde';
 $labels['markmessages'] = 'Marker meldingar';
@@ -117,7 +117,7 @@ $labels['markread'] = 'Som lese';
 $labels['markunread'] = 'Som ulese';
 $labels['markflagged'] = 'Som flagga';
 $labels['markunflagged'] = 'Som uflagga';
 $labels['markunread'] = 'Som ulese';
 $labels['markflagged'] = 'Som flagga';
 $labels['markunflagged'] = 'Som uflagga';
-$labels['messageactions'] = 'Fleire handlingar...';
+$labels['moreactions'] = 'Fleire handlingar';
 $labels['select'] = 'Vel';
 $labels['all'] = 'Alle';
 $labels['none'] = 'Ingen';
 $labels['select'] = 'Vel';
 $labels['all'] = 'Alle';
 $labels['none'] = 'Ingen';
@@ -149,9 +149,9 @@ $labels['listcolumns'] = 'Vis kolonner';
 $labels['listsorting'] = 'Sorteringskolonne';
 $labels['listorder'] = 'Sorteringsveg';
 $labels['listmode'] = 'Listevisningmodus';
 $labels['listsorting'] = 'Sorteringskolonne';
 $labels['listorder'] = 'Sorteringsveg';
 $labels['listmode'] = 'Listevisningmodus';
+$labels['folderactions'] = 'Mappehandlingar';
 $labels['compact'] = 'Kompakt';
 $labels['empty'] = 'Tom';
 $labels['compact'] = 'Kompakt';
 $labels['empty'] = 'Tom';
-$labels['purge'] = 'Reinska opp';
 $labels['quota'] = 'Plassbruk';
 $labels['unknown'] = 'ukjend';
 $labels['unlimited'] = 'ubegrensa';
 $labels['quota'] = 'Plassbruk';
 $labels['unknown'] = 'ukjend';
 $labels['unlimited'] = 'ubegrensa';
@@ -169,12 +169,18 @@ $labels['addattachment'] = 'Legg ved ei fil';
 $labels['charset'] = 'Teiknkoding';
 $labels['editortype'] = 'Redigeringstype';
 $labels['returnreceipt'] = 'Epost-er-lest-kvittering';
 $labels['charset'] = 'Teiknkoding';
 $labels['editortype'] = 'Redigeringstype';
 $labels['returnreceipt'] = 'Epost-er-lest-kvittering';
+$labels['dsn'] = 'Leveringsstatus';
+$labels['mailreplyintro'] = 'Den $date skreiv $sender:';
+$labels['originalmessage'] = 'Opphavleg melding';
+$labels['editidents'] = 'Redigere identitetar';
 $labels['checkspelling'] = 'Stavekontroll';
 $labels['checkspelling'] = 'Stavekontroll';
-$labels['resumeediting'] = 'Fortsett redigering';
+$labels['resumeediting'] = 'Hald fram redigering';
 $labels['revertto'] = 'Tilbakestill til';
 $labels['attachments'] = 'Vedlegg';
 $labels['upload'] = 'Last opp';
 $labels['revertto'] = 'Tilbakestill til';
 $labels['attachments'] = 'Vedlegg';
 $labels['upload'] = 'Last opp';
+$labels['uploadprogress'] = '$percent ($current frå $total)';
 $labels['close'] = 'Steng';
 $labels['close'] = 'Steng';
+$labels['messageoptions'] = 'Meldingsalternativ';
 $labels['low'] = 'Låg';
 $labels['lowest'] = 'Lågast';
 $labels['normal'] = 'Normal';
 $labels['low'] = 'Låg';
 $labels['lowest'] = 'Lågast';
 $labels['normal'] = 'Normal';
@@ -191,6 +197,7 @@ $labels['maxuploadsize'] = 'Maksimalt tillatte storleik på filar er $size';
 $labels['addcc'] = 'Legg til kopi';
 $labels['addbcc'] = 'Legg til blindkopi';
 $labels['addreplyto'] = 'Legg til svaradressa';
 $labels['addcc'] = 'Legg til kopi';
 $labels['addbcc'] = 'Legg til blindkopi';
 $labels['addreplyto'] = 'Legg til svaradressa';
+$labels['addfollowupto'] = 'Legg til oppfylgjing';
 $labels['mdnrequest'] = 'Sendaren av denne meldinga ynskjer å få kvittering når du har lest meldinga. Ynskjer du å senda denne kvitteringa?';
 $labels['receiptread'] = 'Svarkvittering (eposten-er-lest-kvittering)';
 $labels['yourmessage'] = 'Dette er ein retur-kvittering for meldinga di.';
 $labels['mdnrequest'] = 'Sendaren av denne meldinga ynskjer å få kvittering når du har lest meldinga. Ynskjer du å senda denne kvitteringa?';
 $labels['receiptread'] = 'Svarkvittering (eposten-er-lest-kvittering)';
 $labels['yourmessage'] = 'Dette er ein retur-kvittering for meldinga di.';
@@ -198,13 +205,55 @@ $labels['receiptnote'] = 'Hugs: Denne kvitteringa seier berre at meldinga di var
 $labels['name'] = 'Visingsnamn';
 $labels['firstname'] = 'Førenamn';
 $labels['surname'] = 'Etternamn';
 $labels['name'] = 'Visingsnamn';
 $labels['firstname'] = 'Førenamn';
 $labels['surname'] = 'Etternamn';
+$labels['middlename'] = 'Mellomnamn';
+$labels['nickname'] = 'Kallenamn';
+$labels['jobtitle'] = 'Jobbtittel';
+$labels['department'] = 'Avdeling';
+$labels['gender'] = 'Kjønn';
+$labels['maidenname'] = 'Pikenamn';
 $labels['email'] = 'E-post';
 $labels['email'] = 'E-post';
+$labels['phone'] = 'Telefon';
+$labels['address'] = 'Adresse';
+$labels['street'] = 'Gate';
+$labels['locality'] = 'By';
+$labels['zipcode'] = 'Postnummer';
+$labels['country'] = 'Land';
+$labels['birthday'] = 'Fødselsdag';
+$labels['website'] = 'Internettside';
+$labels['notes'] = 'Notatar';
+$labels['male'] = 'Mann';
+$labels['female'] = 'Kvinne';
+$labels['assistant'] = 'Assistent';
+$labels['allfields'] = 'Alle felt';
+$labels['search'] = 'Søk';
+$labels['advsearch'] = 'Avansert søk';
+$labels['other'] = 'Andre';
+$labels['typehome'] = 'Heim';
+$labels['typework'] = 'Jobb';
+$labels['typeother'] = 'Andre';
+$labels['typemobile'] = 'Mobil';
+$labels['typemain'] = 'Hovud';
+$labels['typehomefax'] = 'Heimefax';
+$labels['typeworkfax'] = 'Jobbfax';
+$labels['typecar'] = 'Bil';
+$labels['typepager'] = 'Personsøkjar';
+$labels['typevideo'] = 'VIdeo';
+$labels['typeassistant'] = 'Assistent';
+$labels['typehomepage'] = 'Heimeside';
+$labels['typeblog'] = 'Blogg';
+$labels['typeprofile'] = 'Profil';
+$labels['addfield'] = 'Legg til felt...';
 $labels['addcontact'] = 'Legg til ny kontakt';
 $labels['editcontact'] = 'Redigere kontakt';
 $labels['addcontact'] = 'Legg til ny kontakt';
 $labels['editcontact'] = 'Redigere kontakt';
+$labels['contacts'] = 'Kontakter';
+$labels['personalinfo'] = 'Personleg informasjon';
 $labels['edit'] = 'Redigere';
 $labels['cancel'] = 'Avbryt';
 $labels['save'] = 'Lagre';
 $labels['delete'] = 'Slette';
 $labels['edit'] = 'Redigere';
 $labels['cancel'] = 'Avbryt';
 $labels['save'] = 'Lagre';
 $labels['delete'] = 'Slette';
+$labels['rename'] = 'Gi nytt namn';
+$labels['addphoto'] = 'Legg til';
+$labels['replacephoto'] = 'Erstatt';
 $labels['newcontact'] = 'Opprett nytt kontaktkort';
 $labels['deletecontact'] = 'Slett valde kontaktar';
 $labels['composeto'] = 'Ny melding til';
 $labels['newcontact'] = 'Opprett nytt kontaktkort';
 $labels['deletecontact'] = 'Slett valde kontaktar';
 $labels['composeto'] = 'Ny melding til';
@@ -213,7 +262,8 @@ $labels['print'] = 'Skriv ut';
 $labels['export'] = 'Eksport';
 $labels['exportvcards'] = 'Eksporter kontaktar i vCard-format';
 $labels['newcontactgroup'] = 'Lag ny kontaktgruppe';
 $labels['export'] = 'Eksport';
 $labels['exportvcards'] = 'Eksporter kontaktar i vCard-format';
 $labels['newcontactgroup'] = 'Lag ny kontaktgruppe';
-$labels['groupactions'] = 'Handlingar for kontaktgruppar...';
+$labels['grouprename'] = 'Endre namn på gruppe';
+$labels['groupdelete'] = 'Slett gruppe';
 $labels['previouspage'] = 'Førre side';
 $labels['firstpage'] = 'Fyrste side';
 $labels['nextpage'] = 'Neste side';
 $labels['previouspage'] = 'Førre side';
 $labels['firstpage'] = 'Fyrste side';
 $labels['nextpage'] = 'Neste side';
@@ -221,9 +271,12 @@ $labels['lastpage'] = 'Siste side';
 $labels['group'] = 'Gruppe';
 $labels['groups'] = 'Gruppar';
 $labels['personaladrbook'] = 'Personlege adresser';
 $labels['group'] = 'Gruppe';
 $labels['groups'] = 'Gruppar';
 $labels['personaladrbook'] = 'Personlege adresser';
+$labels['searchsave'] = 'Lagre søk';
+$labels['searchdelete'] = 'Slett søk';
 $labels['import'] = 'Importer';
 $labels['importcontacts'] = 'Importer kontaktar';
 $labels['importfromfile'] = 'Importer frå fil:';
 $labels['import'] = 'Importer';
 $labels['importcontacts'] = 'Importer kontaktar';
 $labels['importfromfile'] = 'Importer frå fil:';
+$labels['importtarget'] = 'Legg til kontakter i adresseboka';
 $labels['importreplace'] = 'Byt ut heile adresseboka';
 $labels['importtext'] = 'Du kan lasta opp kontaktar frå ei eksisterande adressebok.Me stør innlasting frå vCard-formatet.';
 $labels['done'] = 'Ferdig';
 $labels['importreplace'] = 'Byt ut heile adresseboka';
 $labels['importtext'] = 'Du kan lasta opp kontaktar frå ei eksisterande adressebok.Me stør innlasting frå vCard-formatet.';
 $labels['done'] = 'Ferdig';
@@ -239,6 +292,8 @@ $labels['edititem'] = 'Redigere element';
 $labels['preferhtml'] = 'Føretrekk HTML';
 $labels['defaultcharset'] = 'Standard karaktersett (charset)';
 $labels['htmlmessage'] = 'HTML-melding';
 $labels['preferhtml'] = 'Føretrekk HTML';
 $labels['defaultcharset'] = 'Standard karaktersett (charset)';
 $labels['htmlmessage'] = 'HTML-melding';
+$labels['dateformat'] = 'Datoformat';
+$labels['timeformat'] = 'Tidsformat';
 $labels['prettydate'] = 'Pene datoar';
 $labels['setdefault'] = 'Set som standard';
 $labels['autodetect'] = 'Automatisk';
 $labels['prettydate'] = 'Pene datoar';
 $labels['setdefault'] = 'Set som standard';
 $labels['autodetect'] = 'Automatisk';
@@ -312,9 +367,16 @@ $labels['create'] = 'Opprette';
 $labels['createfolder'] = 'Opprett ny mappe';
 $labels['managefolders'] = 'Mappehandsaming';
 $labels['specialfolders'] = 'Spesialmapper';
 $labels['createfolder'] = 'Opprett ny mappe';
 $labels['managefolders'] = 'Mappehandsaming';
 $labels['specialfolders'] = 'Spesialmapper';
+$labels['getfoldersize'] = 'Klikk for å få mappestørrelse';
+$labels['changesubscription'] = 'Klikk for å endre abonnement';
+$labels['foldertype'] = 'Mappetype';
+$labels['personalfolder'] = 'Privat mappe';
+$labels['otherfolder'] = 'Annan brukar si mappe';
+$labels['sharedfolder'] = 'Offentleg mappe';
 $labels['sortby'] = 'Sorter etter';
 $labels['sortasc'] = 'Sorter stigande';
 $labels['sortdesc'] = 'Sorter søkkjande';
 $labels['sortby'] = 'Sorter etter';
 $labels['sortasc'] = 'Sorter stigande';
 $labels['sortdesc'] = 'Sorter søkkjande';
+$labels['undo'] = 'Gjer om';
 $labels['B'] = 'B';
 $labels['KB'] = 'KB';
 $labels['MB'] = 'MB';
 $labels['B'] = 'B';
 $labels['KB'] = 'KB';
 $labels['MB'] = 'MB';
index 85cb94d0d5d7bbf0b458f559043fe604ee19243d..ed3c4c425333b64976f05ff20424d4b4225a768b 100644 (file)
@@ -18,7 +18,7 @@
 |         Aleksander Machniak <alec@alec.pl>                            |
 +-----------------------------------------------------------------------+
 
 |         Aleksander Machniak <alec@alec.pl>                            |
 +-----------------------------------------------------------------------+
 
-@version $Id: labels.inc 5165 2011-09-05 08:49:04Z thomasb $
+@version $Id: labels.inc 5569 2011-12-07 14:47:32Z thomasb $
 
 */
 
 
 */
 
@@ -38,8 +38,8 @@ $labels['sent'] = 'Wysłane';
 $labels['trash'] = 'Kosz';
 $labels['junk'] = 'Spam';
 $labels['subject'] = 'Temat';
 $labels['trash'] = 'Kosz';
 $labels['junk'] = 'Spam';
 $labels['subject'] = 'Temat';
-$labels['from'] = 'Nadawca';
-$labels['to'] = 'Odbiorca';
+$labels['from'] = 'Od';
+$labels['to'] = 'Do';
 $labels['cc'] = 'Kopia';
 $labels['bcc'] = 'Ukryta kopia';
 $labels['replyto'] = 'Odpowiedź do';
 $labels['cc'] = 'Kopia';
 $labels['bcc'] = 'Ukryta kopia';
 $labels['replyto'] = 'Odpowiedź do';
@@ -137,7 +137,7 @@ $labels['threaded'] = 'Powątkowane';
 $labels['autoexpand_threads'] = 'Rozwijaj wątki';
 $labels['do_expand'] = 'wszystkie';
 $labels['expand_only_unread'] = 'tylko nieprzeczytane';
 $labels['autoexpand_threads'] = 'Rozwijaj wątki';
 $labels['do_expand'] = 'wszystkie';
 $labels['expand_only_unread'] = 'tylko nieprzeczytane';
-$labels['fromto'] = 'Nadawca/Odbiorca';
+$labels['fromto'] = 'Od/Do';
 $labels['flag'] = 'Flaga';
 $labels['attachment'] = 'Załącznik';
 $labels['nonesort'] = 'Brak';
 $labels['flag'] = 'Flaga';
 $labels['attachment'] = 'Załącznik';
 $labels['nonesort'] = 'Brak';
@@ -419,5 +419,27 @@ $labels['importtarget'] = 'Dodaj nowe kontakty do książki adresowej:';
 $labels['grouprename'] = 'Zmień nazwę grupy';
 $labels['groupdelete'] = 'Usuń grupę';
 $labels['undo'] = 'Cofnij';
 $labels['grouprename'] = 'Zmień nazwę grupy';
 $labels['groupdelete'] = 'Usuń grupę';
 $labels['undo'] = 'Cofnij';
+$labels['mailreplyintro'] = 'W dniu $date, $sender napisał(a):';
+$labels['uploadprogress'] = '$percent ($current z $total)';
+$labels['originalmessage'] = 'Wiadomość oryginalna';
+$labels['moreactions'] = 'Więcej akcji...';
+$labels['searchsave'] = 'Zapisz wyszukiwanie';
+$labels['searchdelete'] = 'Usuń wyszukiwanie';
+$labels['spellcheckoptions'] = 'Opcje sprawdzania pisowni';
+$labels['spellcheckignoresyms'] = 'Ignoruj słowa zawierające symbole';
+$labels['spellcheckignorenums'] = 'Ignoruj słowa zawierające cyfry';
+$labels['spellcheckignorecaps'] = 'Ignoruj słowa pisane wielkimi literami';
+$labels['addtodict'] = 'Dodaj do słownika';
+$labels['dateformat'] = 'Format daty';
+$labels['timeformat'] = 'Format czasu';
+$labels['isdraft'] = 'To jest kopia robocza wiadomości.';
+$labels['autocompletesingle'] = 'Nie pokazuj alternatywnych adresów przy autouzupełnianiu';
+$labels['plugin'] = 'Wtyczka';
+$labels['version'] = 'Wersja';
+$labels['source'] = 'Źródła';
+$labels['license'] = 'Licencja';
+$labels['about'] = 'O programie';
+$labels['support'] = 'Wsparcie techniczne';
+$labels['defaultfont'] = 'Czcionka wiadomości HTML';
 
 ?>
 
 ?>
index 6593a80538a4ab0f110c722db090dd611e9ef196..6a509a6e3eca30484c53e39215497241f6ba06f0 100644 (file)
@@ -18,7 +18,7 @@
 |         Aleksander Machniak <alec@alec.pl>                            |
 +-----------------------------------------------------------------------+
 
 |         Aleksander Machniak <alec@alec.pl>                            |
 +-----------------------------------------------------------------------+
 
-@version $Id: messages.inc 5003 2011-08-02 09:22:02Z alec $
+@version $Id: messages.inc 5569 2011-12-07 14:47:32Z thomasb $
 
 */
 
 
 */
 
@@ -117,7 +117,6 @@ $messages['smtpautherror'] = 'Błąd SMTP ($code): Uwierzytelnianie nie powiodł
 $messages['smtpfromerror'] = 'Błąd SMTP ($code): Nie można ustawić nadawcy "$from" ($msg).';
 $messages['smtptoerror'] = 'Błąd SMTP ($code): Nie można dodać odbiorcy "$to" ($msg).';
 $messages['smtprecipientserror'] = 'Błąd SMTP: Parsowanie listy odbiorców nie powiodło się.';
 $messages['smtpfromerror'] = 'Błąd SMTP ($code): Nie można ustawić nadawcy "$from" ($msg).';
 $messages['smtptoerror'] = 'Błąd SMTP ($code): Nie można dodać odbiorcy "$to" ($msg).';
 $messages['smtprecipientserror'] = 'Błąd SMTP: Parsowanie listy odbiorców nie powiodło się.';
-$messages['smtpdsnerror'] = 'Błąd SMTP: Statusy dostarczenia (DSN) nie są obsługiwane przez serwer.';
 $messages['smtperror'] = 'Błąd SMTP: $msg';
 $messages['emailformaterror'] = 'Błędny adres e-mail: $email';
 $messages['toomanyrecipients'] = 'Zbyt wielu odbiorców. Zmniejsz ich liczbę do $max.';
 $messages['smtperror'] = 'Błąd SMTP: $msg';
 $messages['emailformaterror'] = 'Błędny adres e-mail: $email';
 $messages['toomanyrecipients'] = 'Zbyt wielu odbiorców. Zmniejsz ich liczbę do $max.';
@@ -150,5 +149,20 @@ $messages['invalidimageformat'] = 'Niepoprawny format obrazka.';
 $messages['mispellingsfound'] = 'Wykryto błędy pisowni w tej wiadomości.';
 $messages['contactrestoreerror'] = 'Przywracanie kontaktów nie powiodło się.';
 $messages['contactrestored'] = 'Kontakt(y) zostały przywrócone.';
 $messages['mispellingsfound'] = 'Wykryto błędy pisowni w tej wiadomości.';
 $messages['contactrestoreerror'] = 'Przywracanie kontaktów nie powiodło się.';
 $messages['contactrestored'] = 'Kontakt(y) zostały przywrócone.';
+$messages['dberror'] = 'Błąd bazy danych!';
+$messages['contactnameexists'] = 'Kontakt z podaną nazwą już istnieje!';
+$messages['copyingcontact'] = 'Kopiowanie kontaktów...';
+$messages['addingmember'] = 'Dodawanie kontaktów do grupy...';
+$messages['removingmember'] = 'Usuwanie kontaktów z grupy...';
+$messages['parentnotwritable'] = 'Nie można utworzyć/przenieść folderu w wybrane miejsce. Brak upranień.';
+$messages['contactsearchsuccessful'] = 'Znaleziono $nr kontaktów.';
+$messages['savedsearchdeleted'] = 'Wyszukiwanie usunięto pomyślnie.';
+$messages['savedsearchdeleteerror'] = 'Nie można usunąć wyszukiwania.';
+$messages['savedsearchcreated'] = 'Wyszukiwanie zapisano pomyślnie.';
+$messages['savedsearchcreateerror'] = 'Nie można zapisać wyszukiwania.';
+$messages['contactsearchonly'] = 'Użyj wyszukiwarki aby wyświetlić kontakty.';
+$messages['contactdeleting'] = 'Usuwanie kontaktów...';
+$messages['autocompletemore'] = 'Znaleziono więcej pasujących wpisów. Wprowadź więcej znaków.';
+$messages['messagetoobig'] = 'Ta część wiadomości jest zbyt duża aby ją przetworzyć.';
 
 ?>
 
 ?>
index 0255286723c2e27b70b5650608a619ed4859944f..6a2d9db8abc594529197229f87fd92b29307dd72 100644 (file)
@@ -18,7 +18,7 @@
 |         Jarbas Peixoto Junior <jarbas.peixoto@gmail.com>              |
 +-----------------------------------------------------------------------+
 
 |         Jarbas Peixoto Junior <jarbas.peixoto@gmail.com>              |
 +-----------------------------------------------------------------------+
 
-@version $Id: labels.inc 5067 2011-08-14 18:47:58Z thomasb $
+@version $Id: labels.inc 5326 2011-10-10 09:39:58Z netbit $
 
 */
 
 
 */
 
@@ -122,7 +122,7 @@ $labels['markread'] = 'como lidas';
 $labels['markunread'] = 'como não lidas';
 $labels['markflagged'] = 'como sinalizadas';
 $labels['markunflagged'] = 'como não sinalizadas';
 $labels['markunread'] = 'como não lidas';
 $labels['markflagged'] = 'como sinalizadas';
 $labels['markunflagged'] = 'como não sinalizadas';
-$labels['messageactions'] = 'Mais ações...';
+$labels['moreactions'] = 'Mais ações...';
 $labels['select'] = 'Selecionar';
 $labels['all'] = 'Todas';
 $labels['none'] = 'Nenhuma';
 $labels['select'] = 'Selecionar';
 $labels['all'] = 'Todas';
 $labels['none'] = 'Nenhuma';
@@ -175,6 +175,8 @@ $labels['charset'] = 'Codificação';
 $labels['editortype'] = 'Tipo de editor';
 $labels['returnreceipt'] = 'Solicitar confirmação de recebimento';
 $labels['dsn'] = 'Recibo de entrega';
 $labels['editortype'] = 'Tipo de editor';
 $labels['returnreceipt'] = 'Solicitar confirmação de recebimento';
 $labels['dsn'] = 'Recibo de entrega';
+$labels['mailreplyintro'] = 'Em $date, $sender escreveu:';
+$labels['originalmessage'] = 'Mensagem original';
 $labels['editidents'] = 'Editar identidades';
 $labels['checkspelling'] = 'Verificar ortografia';
 $labels['resumeediting'] = 'Continuar a edição';
 $labels['editidents'] = 'Editar identidades';
 $labels['checkspelling'] = 'Verificar ortografia';
 $labels['resumeediting'] = 'Continuar a edição';
@@ -222,7 +224,7 @@ $labels['address'] = 'Endereço';
 $labels['street'] = 'Rua';
 $labels['locality'] = 'Cidade';
 $labels['zipcode'] = 'CEP';
 $labels['street'] = 'Rua';
 $labels['locality'] = 'Cidade';
 $labels['zipcode'] = 'CEP';
-$labels['region'] = 'Região';
+$labels['region'] = 'Estado';
 $labels['country'] = 'País';
 $labels['birthday'] = 'Nascimento';
 $labels['anniversary'] = 'Aniversário';
 $labels['country'] = 'País';
 $labels['birthday'] = 'Nascimento';
 $labels['anniversary'] = 'Aniversário';
@@ -249,6 +251,9 @@ $labels['typecar'] = 'Carro';
 $labels['typepager'] = 'Pager';
 $labels['typevideo'] = 'Video';
 $labels['typeassistant'] = 'Assistente';
 $labels['typepager'] = 'Pager';
 $labels['typevideo'] = 'Video';
 $labels['typeassistant'] = 'Assistente';
+$labels['typehomepage'] = 'Página pessoal';
+$labels['typeblog'] = 'Blog';
+$labels['typeprofile'] = 'Perfil';
 $labels['addfield'] = 'Adicionar campo...';
 $labels['addcontact'] = 'Incluir novo contato';
 $labels['editcontact'] = 'Editar contato';
 $labels['addfield'] = 'Adicionar campo...';
 $labels['addcontact'] = 'Incluir novo contato';
 $labels['editcontact'] = 'Editar contato';
@@ -270,7 +275,6 @@ $labels['print'] = 'Imprimir';
 $labels['export'] = 'Exportar';
 $labels['exportvcards'] = 'Exportar os contatos em formato vCard';
 $labels['newcontactgroup'] = 'Criar novo grupo de contatos';
 $labels['export'] = 'Exportar';
 $labels['exportvcards'] = 'Exportar os contatos em formato vCard';
 $labels['newcontactgroup'] = 'Criar novo grupo de contatos';
-$labels['groupactions'] = 'Ações para grupos de contatos...';
 $labels['grouprename'] = 'Renomear grupo';
 $labels['groupdelete'] = 'Excluir grupo';
 $labels['previouspage'] = 'Página Anterior';
 $labels['grouprename'] = 'Renomear grupo';
 $labels['groupdelete'] = 'Excluir grupo';
 $labels['previouspage'] = 'Página Anterior';
@@ -280,6 +284,8 @@ $labels['lastpage'] = 'Última Página';
 $labels['group'] = 'Grupo';
 $labels['groups'] = 'Grupos';
 $labels['personaladrbook'] = 'Endereços pessoais';
 $labels['group'] = 'Grupo';
 $labels['groups'] = 'Grupos';
 $labels['personaladrbook'] = 'Endereços pessoais';
+$labels['searchsave'] = 'Salvar pesquisa';
+$labels['searchdelete'] = 'Excluir pesquisa';
 $labels['import'] = 'Importar';
 $labels['importcontacts'] = 'Importar contatos';
 $labels['importfromfile'] = 'Importar de arquivo:';
 $labels['import'] = 'Importar';
 $labels['importcontacts'] = 'Importar contatos';
 $labels['importfromfile'] = 'Importar de arquivo:';
@@ -299,6 +305,8 @@ $labels['edititem'] = 'Editar item';
 $labels['preferhtml'] = 'Exibir formatação HTML em mensagens';
 $labels['defaultcharset'] = 'Conjunto padrão de caracteres';
 $labels['htmlmessage'] = 'Mensagem HTML';
 $labels['preferhtml'] = 'Exibir formatação HTML em mensagens';
 $labels['defaultcharset'] = 'Conjunto padrão de caracteres';
 $labels['htmlmessage'] = 'Mensagem HTML';
+$labels['dateformat'] = 'Formato da data';
+$labels['timeformat'] = 'Formato da hora';
 $labels['prettydate'] = 'Exibir datas amigáveis';
 $labels['setdefault'] = 'Padrão';
 $labels['autodetect'] = 'Automático';
 $labels['prettydate'] = 'Exibir datas amigáveis';
 $labels['setdefault'] = 'Padrão';
 $labels['autodetect'] = 'Automático';
@@ -371,6 +379,11 @@ $labels['reqdsn'] = 'Sempre pedir confirmação de entrega';
 $labels['replysamefolder'] = 'Guardar as respostas na mesma pasta da mensagem original';
 $labels['defaultaddressbook'] = 'Adicionar novos contatos para o catálogo de endereços:';
 $labels['spellcheckbeforesend'] = 'Verificar ortografia antes de enviar uma mensagem';
 $labels['replysamefolder'] = 'Guardar as respostas na mesma pasta da mensagem original';
 $labels['defaultaddressbook'] = 'Adicionar novos contatos para o catálogo de endereços:';
 $labels['spellcheckbeforesend'] = 'Verificar ortografia antes de enviar uma mensagem';
+$labels['spellcheckoptions'] = 'Opções do Verificador de Ortografia';
+$labels['spellcheckignoresyms'] = 'Ignorar palavras com símbolos';
+$labels['spellcheckignorenums'] = 'Ignorar palavras com números';
+$labels['spellcheckignorecaps'] = 'Ignorar palavras em maiúsculo';
+$labels['addtodict'] = 'Adicionar ao dicionário';
 $labels['folder'] = 'Pasta';
 $labels['folders'] = 'Pastas';
 $labels['foldername'] = 'Nome da pasta';
 $labels['folder'] = 'Pasta';
 $labels['folders'] = 'Pastas';
 $labels['foldername'] = 'Nome da pasta';
index f0c99076b71d533f0a6630b48fe5cffda6ed2141..5f2df76416af6f95ae87b87820c9115f1ee9642a 100644 (file)
@@ -18,7 +18,7 @@
 |         Jarbas Peixoto Junior <jarbas.peixoto@gmail.com>              |
 +-----------------------------------------------------------------------+
 
 |         Jarbas Peixoto Junior <jarbas.peixoto@gmail.com>              |
 +-----------------------------------------------------------------------+
 
-@version $Id: messages.inc 5067 2011-08-14 18:47:58Z thomasb $
+@version $Id: messages.inc 5326 2011-10-10 09:39:58Z netbit $
 
 */
 
 
 */
 
@@ -29,7 +29,7 @@ $messages['sessionerror'] = 'A sessão do seu navegador é inválida ou expirou'
 $messages['imaperror'] = 'Falha na conexão com o servidor IMAP';
 $messages['servererror'] = 'Erro no Servidor!';
 $messages['servererrormsg'] = 'Erro no Servidor: $msg';
 $messages['imaperror'] = 'Falha na conexão com o servidor IMAP';
 $messages['servererror'] = 'Erro no Servidor!';
 $messages['servererrormsg'] = 'Erro no Servidor: $msg';
-$messages['databaserror'] = 'Erro no banco de dados!';
+$messages['dberror'] = 'Erro no banco de dados!';
 $messages['errorreadonly'] = 'Não foi possível realizar a operação. Pasta somente leitura';
 $messages['errornoperm'] = 'Não foi possível realizar a operação. Acesso negado';
 $messages['invalidrequest'] = 'Requisição inválida! Nenhum dado foi salvo.';
 $messages['errorreadonly'] = 'Não foi possível realizar a operação. Pasta somente leitura';
 $messages['errornoperm'] = 'Não foi possível realizar a operação. Acesso negado';
 $messages['invalidrequest'] = 'Requisição inválida! Nenhum dado foi salvo.';
@@ -46,24 +46,29 @@ $messages['messagesent'] = 'Mensagem enviada com sucesso';
 $messages['savingmessage'] = 'Salvando Mensagem...';
 $messages['messagesaved'] = 'Mensagem gravada como rascunho';
 $messages['successfullysaved'] = 'Gravado com sucesso';
 $messages['savingmessage'] = 'Salvando Mensagem...';
 $messages['messagesaved'] = 'Mensagem gravada como rascunho';
 $messages['successfullysaved'] = 'Gravado com sucesso';
-$messages['addedsuccessfully'] = 'Contato incluído com sucesso';
-$messages['contactexists'] = 'Já existe um contato com esse e-mail';
-$messages['blockedimages'] = 'Para proteger sua privacidade, as imagens desta mensagem foram bloqueadas';
+$messages['addedsuccessfully'] = 'Contato incluído com sucesso.';
+$messages['contactexists'] = 'Já existe um contato com esse mesmo e-mail.';
+$messages['contactnameexists'] = 'Já existe um contato com o mesmo nome.';
+$messages['blockedimages'] = 'Para proteger sua privacidade, as imagens desta mensagem foram bloqueadas.';
 $messages['encryptedmessage'] = 'Esta mensagem está criptografada e não pode ser exibida. Desculpe.';
 $messages['encryptedmessage'] = 'Esta mensagem está criptografada e não pode ser exibida. Desculpe.';
-$messages['nocontactsfound'] = 'Nenhum contato foi encontrado';
-$messages['contactnotfound'] = 'O contato solicitado não foi encontrado';
-$messages['sendingfailed'] = 'Falha no envio da mensagem';
-$messages['senttooquickly'] = 'Aguarde $sec s para enviar a mensagem';
-$messages['errorsavingsent'] = 'Ocorreu um erro ao salvar a mensagem enviada';
-$messages['errorsaving'] = 'Ocorreu um erro ao salvar';
-$messages['errormoving'] = 'Não foi possível mover a mensagem';
-$messages['errorcopying'] = 'Não foi possível copiar a(s) mensagem(ns)';
-$messages['errordeleting'] = 'Não foi possível apagar a mensagem';
-$messages['errormarking'] = 'Não foi possível marcar a mensagem';
+$messages['nocontactsfound'] = 'Nenhum contato foi encontrado.';
+$messages['contactnotfound'] = 'O contato solicitado não foi encontrado.';
+$messages['contactsearchonly'] = 'Informe os termos de pesquisa para localizar os contatos';
+$messages['sendingfailed'] = 'Falha no envio da mensagem.';
+$messages['senttooquickly'] = 'Aguarde $sec s para enviar a mensagem.';
+$messages['errorsavingsent'] = 'Ocorreu um erro ao salvar a mensagem enviada.';
+$messages['errorsaving'] = 'Ocorreu um erro ao salvar.';
+$messages['errormoving'] = 'Não foi possível mover a mensagem.';
+$messages['errorcopying'] = 'Não foi possível copiar a(s) mensagem(ns).';
+$messages['errordeleting'] = 'Não foi possível apagar a mensagem.';
+$messages['errormarking'] = 'Não foi possível marcar a mensagem.';
 $messages['deletecontactconfirm'] = 'Deseja realmente excluir o(s) contato(s) selecionado(s)?';
 $messages['deletecontactconfirm'] = 'Deseja realmente excluir o(s) contato(s) selecionado(s)?';
+$messages['deletegroupconfirm'] = 'Deseja realmente excluir o grupo selecionado?';
 $messages['deletemessagesconfirm'] = 'Deseja realmente excluir a(s) mensagem(s) selecionada(s)?';
 $messages['deletefolderconfirm'] = 'Deseja realmente excluir esta pasta?';
 $messages['purgefolderconfirm'] = 'Deseja realmente excluir todas mensagens desta pasta?';
 $messages['deletemessagesconfirm'] = 'Deseja realmente excluir a(s) mensagem(s) selecionada(s)?';
 $messages['deletefolderconfirm'] = 'Deseja realmente excluir esta pasta?';
 $messages['purgefolderconfirm'] = 'Deseja realmente excluir todas mensagens desta pasta?';
+$messages['contactdeleting'] = 'Apagando contato(s)...';
+$messages['groupdeleting'] = 'Excluindo grupo...';
 $messages['folderdeleting'] = 'Apagando pasta...';
 $messages['foldermoving'] = 'Movendo pasta...';
 $messages['foldersubscribing'] = 'Ativando pasta...';
 $messages['folderdeleting'] = 'Apagando pasta...';
 $messages['foldermoving'] = 'Movendo pasta...';
 $messages['foldersubscribing'] = 'Ativando pasta...';
@@ -78,10 +83,10 @@ $messages['nosubjectwarning'] = 'O campo "Assunto" não foi preenchido. Deseja i
 $messages['nobodywarning'] = 'Enviar a mensagem sem texto?';
 $messages['notsentwarning'] = 'A mensagem não foi enviada, deseja excluí-la?';
 $messages['noldapserver'] = 'Por favor, selecione um servidor LDAP para a pesquisa';
 $messages['nobodywarning'] = 'Enviar a mensagem sem texto?';
 $messages['notsentwarning'] = 'A mensagem não foi enviada, deseja excluí-la?';
 $messages['noldapserver'] = 'Por favor, selecione um servidor LDAP para a pesquisa';
-$messages['nocontactsreturned'] = 'Nenhum contato foi encontrado';
 $messages['nosearchname'] = 'Por favor, informe o nome do contado ou seu endereço de e-mail';
 $messages['notuploadedwarning'] = 'Há anexos ainda não enviados. Aguarde ou cancele o envio.';
 $messages['nosearchname'] = 'Por favor, informe o nome do contado ou seu endereço de e-mail';
 $messages['notuploadedwarning'] = 'Há anexos ainda não enviados. Aguarde ou cancele o envio.';
-$messages['searchsuccessful'] = '$nr mensagens encontradas';
+$messages['searchsuccessful'] = '$nr mensagens encontradas.';
+$messages['contactsearchsuccessful'] = '$nr contatos encontrados.';
 $messages['searchnomatch'] = 'A pesquisa não encontrou resultados';
 $messages['searching'] = 'Pesquisando...';
 $messages['checking'] = 'Verificando...';
 $messages['searchnomatch'] = 'A pesquisa não encontrou resultados';
 $messages['searching'] = 'Pesquisando...';
 $messages['checking'] = 'Verificando...';
@@ -102,8 +107,11 @@ $messages['sourceisreadonly'] = 'Esta fonte de endereço é somente leitura';
 $messages['errorsavingcontact'] = 'Não foi possível salvar o endereço de contato';
 $messages['movingmessage'] = 'Movendo mensagem...';
 $messages['copyingmessage'] = 'Copiando mensagem...';
 $messages['errorsavingcontact'] = 'Não foi possível salvar o endereço de contato';
 $messages['movingmessage'] = 'Movendo mensagem...';
 $messages['copyingmessage'] = 'Copiando mensagem...';
+$messages['copyingcontact'] = 'Copiando contato(s)...';
 $messages['deletingmessage'] = 'Excluindo mensagem(s)...';
 $messages['markingmessage'] = 'Marcando mensagem(s)...';
 $messages['deletingmessage'] = 'Excluindo mensagem(s)...';
 $messages['markingmessage'] = 'Marcando mensagem(s)...';
+$messages['addingmember'] = 'Adicionando contato(s) para o grupo...';
+$messages['removingmember'] = 'Removendo contato(s) do grupo...';
 $messages['receiptsent'] = 'Confirmação de recebimento enviada com sucesso';
 $messages['errorsendingreceipt'] = 'Não foi possível enviar a confirmação de recebimento';
 $messages['nodeletelastidentity'] = 'Você não pode excluir a única identidade';
 $messages['receiptsent'] = 'Confirmação de recebimento enviada com sucesso';
 $messages['errorsendingreceipt'] = 'Não foi possível enviar a confirmação de recebimento';
 $messages['nodeletelastidentity'] = 'Você não pode excluir a única identidade';
@@ -125,7 +133,6 @@ $messages['smtpautherror'] = 'Erro SMTP ($code): Falha na autenticação';
 $messages['smtpfromerror'] = 'Erro SMTP ($code): Falha ao definir o remetente "$from" ($msg)';
 $messages['smtptoerror'] = 'Erro SMTP ($code): Falha ao adicionar o destinatário "$to" ($msg)';
 $messages['smtprecipientserror'] = 'Erro SMTP: Não é possível processar a lista destinatários';
 $messages['smtpfromerror'] = 'Erro SMTP ($code): Falha ao definir o remetente "$from" ($msg)';
 $messages['smtptoerror'] = 'Erro SMTP ($code): Falha ao adicionar o destinatário "$to" ($msg)';
 $messages['smtprecipientserror'] = 'Erro SMTP: Não é possível processar a lista destinatários';
-$messages['smtpdsnerror'] = 'Erro SMTP: Sem suporte para Confirmação de Entrega (DSN)';
 $messages['smtperror'] = 'Erro SMTP: $msg';
 $messages['emailformaterror'] = 'Endereço de e-mail inválido: $email';
 $messages['toomanyrecipients'] = 'Muitos destinatários. Reduza o número de destinatários para $max.';
 $messages['smtperror'] = 'Erro SMTP: $msg';
 $messages['emailformaterror'] = 'Endereço de e-mail inválido: $email';
 $messages['toomanyrecipients'] = 'Muitos destinatários. Reduza o número de destinatários para $max.';
@@ -138,16 +145,22 @@ $messages['contactrestored'] = 'Contato(s) recuperado(s) com sucesso.';
 $messages['groupdeleted'] = 'Grupo excluído com sucesso';
 $messages['grouprenamed'] = 'Grupo renomeado com sucesso';
 $messages['groupcreated'] = 'Grupo criado com sucesso';
 $messages['groupdeleted'] = 'Grupo excluído com sucesso';
 $messages['grouprenamed'] = 'Grupo renomeado com sucesso';
 $messages['groupcreated'] = 'Grupo criado com sucesso';
+$messages['savedsearchdeleted'] = 'Pesquisa excluída com sucesso.';
+$messages['savedsearchdeleteerror'] = 'Não foi possível excluir a pesquisa.';
+$messages['savedsearchcreated'] = 'Pesquisa criada com sucesso.';
+$messages['savedsearchcreateerror'] = 'Não foi possível criar a pesquisa.';
 $messages['messagedeleted'] = 'Mensagem(s) excluída(s) com sucesso';
 $messages['messagemoved'] = 'Mensagem(s) movida(s) com sucesso';
 $messages['messagecopied'] = 'Mensagem(s) copiada(s) com sucesso';
 $messages['messagemarked'] = 'Mensagem(s) marcada(s) com sucesso';
 $messages['autocompletechars'] = 'Digite pelo menos $min caractere(s) para auto-completar';
 $messages['messagedeleted'] = 'Mensagem(s) excluída(s) com sucesso';
 $messages['messagemoved'] = 'Mensagem(s) movida(s) com sucesso';
 $messages['messagecopied'] = 'Mensagem(s) copiada(s) com sucesso';
 $messages['messagemarked'] = 'Mensagem(s) marcada(s) com sucesso';
 $messages['autocompletechars'] = 'Digite pelo menos $min caractere(s) para auto-completar';
+$messages['autocompletemore'] = 'Muitos registros encontrados. Por favor, digite mais caracteres.';
 $messages['namecannotbeempty'] = 'Nome não pode ser vazio';
 $messages['nametoolong'] = 'Nome é muito longo';
 $messages['folderupdated'] = 'Pasta atualizada com sucesso';
 $messages['foldercreated'] = 'Pasta criada com sucesso';
 $messages['invalidimageformat'] = 'Formato de imagem inválido.';
 $messages['mispellingsfound'] = 'Foram detectados erros de ortografia.';
 $messages['namecannotbeempty'] = 'Nome não pode ser vazio';
 $messages['nametoolong'] = 'Nome é muito longo';
 $messages['folderupdated'] = 'Pasta atualizada com sucesso';
 $messages['foldercreated'] = 'Pasta criada com sucesso';
 $messages['invalidimageformat'] = 'Formato de imagem inválido.';
 $messages['mispellingsfound'] = 'Foram detectados erros de ortografia.';
+$messages['parentnotwritable'] = 'Sem permissão para criar/mover a pasta dentro da pasta selecionada.';
 
 ?>
 
 ?>
index 9c047dd26900630b2244644f8146d39b95a504a0..e864c65a3dee2cea870dff24951bdc8d56d521de 100644 (file)
@@ -17,7 +17,7 @@
 |          Teotónio Ricardo <teotonio.ricardo@webtuga.pt>              |
 +-----------------------------------------------------------------------+
 
 |          Teotónio Ricardo <teotonio.ricardo@webtuga.pt>              |
 +-----------------------------------------------------------------------+
 
-@version $Id: labels.inc 5175 2011-09-05 18:42:24Z thomasb $
+@version $Id: labels.inc 5569 2011-12-07 14:47:32Z thomasb $
 
 */
 
 
 */
 
@@ -121,7 +121,7 @@ $labels['markread'] = 'Como lidas';
 $labels['markunread'] = 'Como não lidas';
 $labels['markflagged'] = 'Com sinalização';
 $labels['markunflagged'] = 'Sem sinalização';
 $labels['markunread'] = 'Como não lidas';
 $labels['markflagged'] = 'Com sinalização';
 $labels['markunflagged'] = 'Sem sinalização';
-$labels['messageactions'] = 'Mais acções...';
+$labels['moreactions'] = 'Mais acções...';
 $labels['select'] = 'Seleccionar';
 $labels['all'] = 'Todas';
 $labels['none'] = 'Nenhuma';
 $labels['select'] = 'Seleccionar';
 $labels['all'] = 'Todas';
 $labels['none'] = 'Nenhuma';
@@ -193,6 +193,7 @@ $labels['highest'] = 'Mais alta';
 $labels['nosubject'] = '(sem assunto)';
 $labels['showimages'] = 'Exibir imagens';
 $labels['alwaysshow'] = 'Mostrar sempre imagens a partir de $sender';
 $labels['nosubject'] = '(sem assunto)';
 $labels['showimages'] = 'Exibir imagens';
 $labels['alwaysshow'] = 'Mostrar sempre imagens a partir de $sender';
+$labels['isdraft'] = 'Esta é uma mensagem de rascunho.';
 $labels['htmltoggle'] = 'HTML';
 $labels['plaintoggle'] = 'Texto simples';
 $labels['savesentmessagein'] = 'Guardar mensagem enviada em';
 $labels['htmltoggle'] = 'HTML';
 $labels['plaintoggle'] = 'Texto simples';
 $labels['savesentmessagein'] = 'Guardar mensagem enviada em';
@@ -274,7 +275,6 @@ $labels['print'] = 'Imprimir';
 $labels['export'] = 'Exportar';
 $labels['exportvcards'] = 'Exportar contactos no formato vCard';
 $labels['newcontactgroup'] = 'Criar novo grupo de contactos';
 $labels['export'] = 'Exportar';
 $labels['exportvcards'] = 'Exportar contactos no formato vCard';
 $labels['newcontactgroup'] = 'Criar novo grupo de contactos';
-$labels['groupactions'] = 'Acções para grupo de contactos...';
 $labels['grouprename'] = 'Renomear grupo';
 $labels['groupdelete'] = 'Eliminar grupo';
 $labels['previouspage'] = 'Exibir página anterior';
 $labels['grouprename'] = 'Renomear grupo';
 $labels['groupdelete'] = 'Eliminar grupo';
 $labels['previouspage'] = 'Exibir página anterior';
@@ -284,6 +284,8 @@ $labels['lastpage'] = 'Exibir última página';
 $labels['group'] = 'Grupo';
 $labels['groups'] = 'Grupos';
 $labels['personaladrbook'] = 'Endereços pessoais';
 $labels['group'] = 'Grupo';
 $labels['groups'] = 'Grupos';
 $labels['personaladrbook'] = 'Endereços pessoais';
+$labels['searchsave'] = 'Guardar pesquisa';
+$labels['searchdelete'] = 'Eliminar pesquisa';
 $labels['import'] = 'Importar';
 $labels['importcontacts'] = 'Importar contactos';
 $labels['importfromfile'] = 'Importar do ficheiro:';
 $labels['import'] = 'Importar';
 $labels['importcontacts'] = 'Importar contactos';
 $labels['importfromfile'] = 'Importar do ficheiro:';
@@ -292,6 +294,7 @@ $labels['importreplace'] = 'Substituir todo o livro de endereços';
 $labels['importtext'] = 'Pode submeter contactos a partir de um livro de endereços. Actualmente suportamos importação de endereços no formato vCard.';
 $labels['done'] = 'Terminado';
 $labels['settingsfor'] = 'Configurações para';
 $labels['importtext'] = 'Pode submeter contactos a partir de um livro de endereços. Actualmente suportamos importação de endereços no formato vCard.';
 $labels['done'] = 'Terminado';
 $labels['settingsfor'] = 'Configurações para';
+$labels['about'] = 'Acerca';
 $labels['preferences'] = 'Preferências';
 $labels['userpreferences'] = 'Preferências do utilizador';
 $labels['editpreferences'] = 'Editar preferências do utilizador';
 $labels['preferences'] = 'Preferências';
 $labels['userpreferences'] = 'Preferências do utilizador';
 $labels['editpreferences'] = 'Editar preferências do utilizador';
@@ -303,6 +306,8 @@ $labels['edititem'] = 'Editar item';
 $labels['preferhtml'] = 'Exibir mensagens em HTML';
 $labels['defaultcharset'] = 'Conjunto de caracteres predefinido';
 $labels['htmlmessage'] = 'Mensagem em HTML';
 $labels['preferhtml'] = 'Exibir mensagens em HTML';
 $labels['defaultcharset'] = 'Conjunto de caracteres predefinido';
 $labels['htmlmessage'] = 'Mensagem em HTML';
+$labels['dateformat'] = 'Formato da data';
+$labels['timeformat'] = 'Formato da hora';
 $labels['prettydate'] = 'Formatar datas';
 $labels['setdefault'] = 'Marcar como predefinido';
 $labels['autodetect'] = 'Auto';
 $labels['prettydate'] = 'Formatar datas';
 $labels['setdefault'] = 'Marcar como predefinido';
 $labels['autodetect'] = 'Auto';
@@ -374,7 +379,13 @@ $labels['reqmdn'] = 'Pedir sempre um recibo de leitura';
 $labels['reqdsn'] = 'Pedir sempre um recibo de entrega';
 $labels['replysamefolder'] = 'Guardar as respostas na mesma pasta da mensagem original';
 $labels['defaultaddressbook'] = 'Adicionar novo contacto ao livro de endereços selecionado';
 $labels['reqdsn'] = 'Pedir sempre um recibo de entrega';
 $labels['replysamefolder'] = 'Guardar as respostas na mesma pasta da mensagem original';
 $labels['defaultaddressbook'] = 'Adicionar novo contacto ao livro de endereços selecionado';
+$labels['autocompletesingle'] = 'Ignorar endereços de email alternativos no preenchimento automático';
 $labels['spellcheckbeforesend'] = 'Verificar ortografia antes de enviar a mensagem';
 $labels['spellcheckbeforesend'] = 'Verificar ortografia antes de enviar a mensagem';
+$labels['spellcheckoptions'] = 'Opções de verificação ortográfica';
+$labels['spellcheckignoresyms'] = 'Ignorar palavras com símbolos';
+$labels['spellcheckignorenums'] = 'Ignorar palavras com números';
+$labels['spellcheckignorecaps'] = 'Ignorar palavras em maiúsculas';
+$labels['addtodict'] = 'Adicionar ao dicionário';
 $labels['folder'] = 'Pasta';
 $labels['folders'] = 'Pastas';
 $labels['foldername'] = 'Nome da pasta';
 $labels['folder'] = 'Pasta';
 $labels['folders'] = 'Pastas';
 $labels['foldername'] = 'Nome da pasta';
@@ -399,6 +410,11 @@ $labels['sortby'] = 'Ordenar por';
 $labels['sortasc'] = 'Ordenação Ascendente';
 $labels['sortdesc'] = 'Ordenação Descendente';
 $labels['undo'] = 'Anular';
 $labels['sortasc'] = 'Ordenação Ascendente';
 $labels['sortdesc'] = 'Ordenação Descendente';
 $labels['undo'] = 'Anular';
+$labels['plugin'] = 'Plugin';
+$labels['version'] = 'Versão';
+$labels['source'] = 'Fonte';
+$labels['license'] = 'Licença';
+$labels['support'] = 'Obter suporte';
 $labels['B'] = 'B';
 $labels['KB'] = 'KB';
 $labels['MB'] = 'MB';
 $labels['B'] = 'B';
 $labels['KB'] = 'KB';
 $labels['MB'] = 'MB';
index 65bea81614d45f41e6f0cb5387c552ddd8f1780d..ccf8791022ff5df3a717cbbf569e1f82e16b0ac2 100644 (file)
 +-----------------------------------------------------------------------+
 | Authors: Sergio Rocha <sergio.rocha@makeitsimple.pt>                  |
 |          João Vale <jpvale@gmail.com>                                |
 +-----------------------------------------------------------------------+
 | Authors: Sergio Rocha <sergio.rocha@makeitsimple.pt>                  |
 |          João Vale <jpvale@gmail.com>                                |
-|         Nuno Costa <nuno@criacaoweb.net>                              |
-|         Teotónio Ricardo <teotonio.ricardo@webtuga.pt>               |
+|          Nuno Costa <nuno@criacaoweb.net>                              |
+|          Teotónio Ricardo <teotonio.ricardo@webtuga.pt>               |
 +-----------------------------------------------------------------------+
 
 +-----------------------------------------------------------------------+
 
-@version $Id: messages.inc 5175 2011-09-05 18:42:24Z thomasb $
+@version $Id: messages.inc 5569 2011-12-07 14:47:32Z thomasb $
 
 */
 
 
 */
 
@@ -27,7 +27,7 @@ $messages['sessionerror'] = 'A sua sessão é inválida ou expirou';
 $messages['imaperror'] = 'A ligação ao servidor IMAP falhou';
 $messages['servererror'] = 'Erro do Servidor!';
 $messages['servererrormsg'] = 'Erro do Servidor: $msg';
 $messages['imaperror'] = 'A ligação ao servidor IMAP falhou';
 $messages['servererror'] = 'Erro do Servidor!';
 $messages['servererrormsg'] = 'Erro do Servidor: $msg';
-$messages['databaserror'] = 'Erro de base de dados!';
+$messages['dberror'] = 'Erro na base de dados!';
 $messages['errorreadonly'] = 'Não foi possível efectuar a operação. A pasta é só de leitura.';
 $messages['errornoperm'] = 'Não tem permissões para efectuar esta operação.';
 $messages['invalidrequest'] = 'Pedido inválido! Não foi guardada nenhuma informação.';
 $messages['errorreadonly'] = 'Não foi possível efectuar a operação. A pasta é só de leitura.';
 $messages['errornoperm'] = 'Não tem permissões para efectuar esta operação.';
 $messages['invalidrequest'] = 'Pedido inválido! Não foi guardada nenhuma informação.';
@@ -51,6 +51,7 @@ $messages['blockedimages'] = 'Para proteger a sua privacidade, as imagens desta
 $messages['encryptedmessage'] = 'Esta mensagem está encriptada e não pode ser exibida. Desculpe.';
 $messages['nocontactsfound'] = 'Nenhum contacto encontrado';
 $messages['contactnotfound'] = 'O contacto especificado não foi encontrado';
 $messages['encryptedmessage'] = 'Esta mensagem está encriptada e não pode ser exibida. Desculpe.';
 $messages['nocontactsfound'] = 'Nenhum contacto encontrado';
 $messages['contactnotfound'] = 'O contacto especificado não foi encontrado';
+$messages['contactsearchonly'] = 'Insira os termos de pesquisa para localizar os contactos';
 $messages['sendingfailed'] = 'Falha no envio da mensagem';
 $messages['senttooquickly'] = 'Por favor espere $sec seg(s). antes de enviar esta mensagem';
 $messages['errorsavingsent'] = 'Ocorreu um erro ao guardar a mensagem enviada';
 $messages['sendingfailed'] = 'Falha no envio da mensagem';
 $messages['senttooquickly'] = 'Por favor espere $sec seg(s). antes de enviar esta mensagem';
 $messages['errorsavingsent'] = 'Ocorreu um erro ao guardar a mensagem enviada';
@@ -64,6 +65,7 @@ $messages['deletegroupconfirm'] = 'Tem a certeza que pretende eliminar o grupo s
 $messages['deletemessagesconfirm'] = 'Deseja realmente eliminar a(s) mensagem(ns) selecionada(s)?';
 $messages['deletefolderconfirm'] = 'Deseja realmente eliminar esta pasta?';
 $messages['purgefolderconfirm'] = 'Deseja realmente eliminar todas mensagens desta pasta?';
 $messages['deletemessagesconfirm'] = 'Deseja realmente eliminar a(s) mensagem(ns) selecionada(s)?';
 $messages['deletefolderconfirm'] = 'Deseja realmente eliminar esta pasta?';
 $messages['purgefolderconfirm'] = 'Deseja realmente eliminar todas mensagens desta pasta?';
+$messages['contactdeleting'] = 'A eliminar contacto(s)...';
 $messages['groupdeleting'] = 'A eliminar grupo...';
 $messages['folderdeleting'] = 'A eliminar pasta...';
 $messages['foldermoving'] = 'A mover pasta...';
 $messages['groupdeleting'] = 'A eliminar grupo...';
 $messages['folderdeleting'] = 'A eliminar pasta...';
 $messages['foldermoving'] = 'A mover pasta...';
@@ -79,10 +81,10 @@ $messages['nosubjectwarning'] = 'O campo "Assunto" não foi preenchido. Deseja i
 $messages['nobodywarning'] = 'Enviar a mensagem sem texto?';
 $messages['notsentwarning'] = 'A mensagem não foi enviada, deseja apagá-la?';
 $messages['noldapserver'] = 'Seleccione um servidor LDAP para a pesquisa';
 $messages['nobodywarning'] = 'Enviar a mensagem sem texto?';
 $messages['notsentwarning'] = 'A mensagem não foi enviada, deseja apagá-la?';
 $messages['noldapserver'] = 'Seleccione um servidor LDAP para a pesquisa';
-$messages['nocontactsreturned'] = 'Não foi encontrado nenhum contacto';
 $messages['nosearchname'] = 'Por favor, escreva o nome do contacto ou endereço de e-mail';
 $messages['notuploadedwarning'] = 'Nem todos os anexos foram ainda enviados. Por favor aguarde ou cancele o envio.';
 $messages['searchsuccessful'] = '$nr mensagens encontradas';
 $messages['nosearchname'] = 'Por favor, escreva o nome do contacto ou endereço de e-mail';
 $messages['notuploadedwarning'] = 'Nem todos os anexos foram ainda enviados. Por favor aguarde ou cancele o envio.';
 $messages['searchsuccessful'] = '$nr mensagens encontradas';
+$messages['contactsearchsuccessful'] = '$nr contactos encontrados.';
 $messages['searchnomatch'] = 'A pesquisa não devolveu resultados';
 $messages['searching'] = 'A pesquisar...';
 $messages['checking'] = 'A verificar...';
 $messages['searchnomatch'] = 'A pesquisa não devolveu resultados';
 $messages['searching'] = 'A pesquisar...';
 $messages['checking'] = 'A verificar...';
@@ -129,7 +131,6 @@ $messages['smtpautherror'] = 'Erro SMTP ($code): A autenticação falhou';
 $messages['smtpfromerror'] = 'Erro SMTP ($code): Falha ao definir o remetente "$from" ($msg)';
 $messages['smtptoerror'] = 'Erro SMTP ($code): Falha ao adicionar o destinatário: "$to" ($msg)';
 $messages['smtprecipientserror'] = 'Erro SMTP: Impossível analisar a lista de destinatários';
 $messages['smtpfromerror'] = 'Erro SMTP ($code): Falha ao definir o remetente "$from" ($msg)';
 $messages['smtptoerror'] = 'Erro SMTP ($code): Falha ao adicionar o destinatário: "$to" ($msg)';
 $messages['smtprecipientserror'] = 'Erro SMTP: Impossível analisar a lista de destinatários';
-$messages['smtpdsnerror'] = 'Erro SMTP: Não há suporte para recibo de entrega';
 $messages['smtperror'] = 'Erro SMTP: $msg';
 $messages['emailformaterror'] = 'Endereço de e-mail incorrecto: $email';
 $messages['toomanyrecipients'] = 'Demasiados destinatários. Reduza o numero de destinatários para o máximo de $max.';
 $messages['smtperror'] = 'Erro SMTP: $msg';
 $messages['emailformaterror'] = 'Endereço de e-mail incorrecto: $email';
 $messages['toomanyrecipients'] = 'Demasiados destinatários. Reduza o numero de destinatários para o máximo de $max.';
@@ -142,11 +143,16 @@ $messages['contactrestored'] = 'Contacto(s) restaurado(s) com sucesso.';
 $messages['groupdeleted'] = 'Grupo eliminado com sucesso';
 $messages['grouprenamed'] = 'Grupo renomeado com sucesso';
 $messages['groupcreated'] = 'Grupo criado com sucesso';
 $messages['groupdeleted'] = 'Grupo eliminado com sucesso';
 $messages['grouprenamed'] = 'Grupo renomeado com sucesso';
 $messages['groupcreated'] = 'Grupo criado com sucesso';
+$messages['savedsearchdeleted'] = 'Pesquisa guardada eliminada com sucesso.';
+$messages['savedsearchdeleteerror'] = 'Não foi possível eliminar a pesquisa guardada.';
+$messages['savedsearchcreated'] = 'Pesquisa guardada criada com sucesso.';
+$messages['savedsearchcreateerror'] = 'Não foi possível criar a pesquisa guardada.';
 $messages['messagedeleted'] = 'Mensagens eliminadas com sucesso';
 $messages['messagemoved'] = 'Mensagens movidas com sucesso';
 $messages['messagecopied'] = 'Mensagens copiadas com sucesso';
 $messages['messagemarked'] = 'Mensagens marcadas com sucesso';
 $messages['autocompletechars'] = 'Indique pelo menos $min caracteres para auto completar';
 $messages['messagedeleted'] = 'Mensagens eliminadas com sucesso';
 $messages['messagemoved'] = 'Mensagens movidas com sucesso';
 $messages['messagecopied'] = 'Mensagens copiadas com sucesso';
 $messages['messagemarked'] = 'Mensagens marcadas com sucesso';
 $messages['autocompletechars'] = 'Indique pelo menos $min caracteres para auto completar';
+$messages['autocompletemore'] = 'Muitos registros encontrados. Por favor, insira mais caracteres.';
 $messages['namecannotbeempty'] = 'O nome não pode estar em branco';
 $messages['nametoolong'] = 'O nome é demasiado longo';
 $messages['folderupdated'] = 'Actualização da pasta concluída com sucesso';
 $messages['namecannotbeempty'] = 'O nome não pode estar em branco';
 $messages['nametoolong'] = 'O nome é demasiado longo';
 $messages['folderupdated'] = 'Actualização da pasta concluída com sucesso';
@@ -154,5 +160,6 @@ $messages['foldercreated'] = 'Pasta criada com sucesso';
 $messages['invalidimageformat'] = 'Formato de imagem não suportado';
 $messages['mispellingsfound'] = 'Foram detectados erros de ortografia nesta mensagem';
 $messages['parentnotwritable'] = 'Não é possível criar/mover esta pasta para a pasta seleccionada. Acesso negado.';
 $messages['invalidimageformat'] = 'Formato de imagem não suportado';
 $messages['mispellingsfound'] = 'Foram detectados erros de ortografia nesta mensagem';
 $messages['parentnotwritable'] = 'Não é possível criar/mover esta pasta para a pasta seleccionada. Acesso negado.';
+$messages['messagetoobig'] = 'A mensagem é demasiado grande para ser processada.';
 
 ?>
 
 ?>
index d4649c2ab9950da3fc794a9c1ffc5530f31d7ab1..a89e530361c56adfd638f1626c9b983f63b729f3 100644 (file)
@@ -15,7 +15,7 @@
 | Support: www.roundcube.ru                                             |
 +-----------------------------------------------------------------------+
 
 | Support: www.roundcube.ru                                             |
 +-----------------------------------------------------------------------+
 
-@version $Id: labels.inc 5291 2011-09-28 17:10:45Z thomasb $
+@version $Id: labels.inc 5290 2011-09-28 17:09:50Z thomasb $
 
 */
 
 
 */
 
index c6b2aab75352cd961911e5410c7f6a114bf81eb1..52e848403a710c8421a67544a8d98ad16067b47c 100644 (file)
@@ -14,7 +14,7 @@
 | Updates: Sergey Dukachev <iam@dukess.ru>                              |
 +-----------------------------------------------------------------------+
 
 | Updates: Sergey Dukachev <iam@dukess.ru>                              |
 +-----------------------------------------------------------------------+
 
-@version $Id: messages.inc 5291 2011-09-28 17:10:45Z thomasb $
+@version $Id: messages.inc 5290 2011-09-28 17:09:50Z thomasb $
 
 */
 
 
 */
 
index 367b23dc2cdf6a7c5a2e6550d7782921d9934790..367338991872e6faadcb187db718e4ee078f7f16 100644 (file)
@@ -17,7 +17,7 @@
 |         Martin Lacina        <martin@whistler.sk>                            |
 +-----------------------------------------------------------------------+
 
 |         Martin Lacina        <martin@whistler.sk>                            |
 +-----------------------------------------------------------------------+
 
-@version $Id: labels.inc 5067 2011-08-14 18:47:58Z thomasb $
+@version $Id: labels.inc 5585 2011-12-09 19:28:20Z alec $
 
 */
 
 
 */
 
@@ -365,7 +365,7 @@ $labels['belowquote'] = 'nad citáciu';
 $labels['abovequote'] = 'pod citáciu';
 $labels['insertsignature'] = 'Vložit podpis';
 $labels['previewpanemarkread'] = 'Označiť zobrazenej správy ako prečítané';
 $labels['abovequote'] = 'pod citáciu';
 $labels['insertsignature'] = 'Vložit podpis';
 $labels['previewpanemarkread'] = 'Označiť zobrazenej správy ako prečítané';
-$labels['afternseconds'] = 'po $ sekundách';
+$labels['afternseconds'] = 'po $n sekundách';
 $labels['reqmdn'] = 'Vždy požadovať doručenku';
 $labels['reqdsn'] = 'Vždy vyžadovať potvrdenie o doručení správy';
 $labels['replysamefolder'] = 'Umietniť odpoveď do adresára, kde je umiestnená správa, na ktorú sa odpovedalo';
 $labels['reqmdn'] = 'Vždy požadovať doručenku';
 $labels['reqdsn'] = 'Vždy vyžadovať potvrdenie o doručení správy';
 $labels['replysamefolder'] = 'Umietniť odpoveď do adresára, kde je umiestnená správa, na ktorú sa odpovedalo';
index 3365111b2b8d325d88f0f9853c06bc6002fbfb0e..ef5bbf403bf76e4a12a00bc0973428d3492877e4 100644 (file)
@@ -17,7 +17,7 @@
 |         Martin Lacina        <martin@whistler.sk>                            |
 +-----------------------------------------------------------------------+
 
 |         Martin Lacina        <martin@whistler.sk>                            |
 +-----------------------------------------------------------------------+
 
-@version $Id: messages.inc 5067 2011-08-14 18:47:58Z thomasb $
+@version $Id: messages.inc 5139 2011-08-28 09:47:15Z alec $
 
 */
 
 
 */
 
@@ -28,7 +28,7 @@ $messages['sessionerror'] = 'Vaše prihlásenie je neplatné alebo vypršala jeh
 $messages['imaperror'] = 'Nepodarilo sa spojiť s IMAP serverom';
 $messages['servererror'] = 'Chyba servera!';
 $messages['servererrormsg'] = 'Chyba servera: $msg';
 $messages['imaperror'] = 'Nepodarilo sa spojiť s IMAP serverom';
 $messages['servererror'] = 'Chyba servera!';
 $messages['servererrormsg'] = 'Chyba servera: $msg';
-$messages['databaserror'] = 'Databázová chyba!';
+$messages['dberror'] = 'Databázová chyba!';
 $messages['errorreadonly'] = 'Nemožno vykonať operáciu. Adresár je len na čítanie';
 $messages['errornoperm'] = 'Nemožno vykonať operáciu. Prístup odmietnutý';
 $messages['invalidrequest'] = 'Chybný požiadavek. Žiadne údaje neboli uložené.';
 $messages['errorreadonly'] = 'Nemožno vykonať operáciu. Adresár je len na čítanie';
 $messages['errornoperm'] = 'Nemožno vykonať operáciu. Prístup odmietnutý';
 $messages['invalidrequest'] = 'Chybný požiadavek. Žiadne údaje neboli uložené.';
index ad437cb18829679fb50378269b3e4648f1376528..8a460f0b2531b80289d4f81e0e5ad8581bc18c59 100644 (file)
@@ -14,7 +14,7 @@
 |         Barbara Krasovec <barbarak@arnes.si>                          |
 +-----------------------------------------------------------------------+
 
 |         Barbara Krasovec <barbarak@arnes.si>                          |
 +-----------------------------------------------------------------------+
 
-@version $Id: labels.inc 5067 2011-08-14 18:47:58Z thomasb $
+@version $Id: labels.inc 5569 2011-12-07 14:47:32Z thomasb $
 
 */
 
 
 */
 
@@ -118,7 +118,7 @@ $labels['markread'] = 'Kot prebrano';
 $labels['markunread'] = 'Kot neprebrano';
 $labels['markflagged'] = 'Kot označeno';
 $labels['markunflagged'] = 'Kot neoznačeno';
 $labels['markunread'] = 'Kot neprebrano';
 $labels['markflagged'] = 'Kot označeno';
 $labels['markunflagged'] = 'Kot neoznačeno';
-$labels['messageactions'] = 'Več možnosti';
+$labels['moreactions'] = 'Več možnosti...';
 $labels['select'] = 'Izberi';
 $labels['all'] = 'Vse';
 $labels['none'] = 'Ničesar';
 $labels['select'] = 'Izberi';
 $labels['all'] = 'Vse';
 $labels['none'] = 'Ničesar';
@@ -171,12 +171,15 @@ $labels['charset'] = 'Nabor znakov';
 $labels['editortype'] = 'Vrsta urejevalnika';
 $labels['returnreceipt'] = 'Potrdilo prejemnika';
 $labels['dsn'] = 'Status dostave sporočila';
 $labels['editortype'] = 'Vrsta urejevalnika';
 $labels['returnreceipt'] = 'Potrdilo prejemnika';
 $labels['dsn'] = 'Status dostave sporočila';
+$labels['mailreplyintro'] = '$date, je $sender napisal';
+$labels['originalmessage'] = 'Izvorno sporočilo';
 $labels['editidents'] = 'Uredi identitete';
 $labels['checkspelling'] = 'Preglej pravopis';
 $labels['resumeediting'] = 'Nadaljuj z urejanjem';
 $labels['revertto'] = 'Razveljavi';
 $labels['attachments'] = 'Priponke';
 $labels['upload'] = 'Naloži';
 $labels['editidents'] = 'Uredi identitete';
 $labels['checkspelling'] = 'Preglej pravopis';
 $labels['resumeediting'] = 'Nadaljuj z urejanjem';
 $labels['revertto'] = 'Razveljavi';
 $labels['attachments'] = 'Priponke';
 $labels['upload'] = 'Naloži';
+$labels['uploadprogress'] = '$percent ($current od $total)';
 $labels['close'] = 'Zapri';
 $labels['messageoptions'] = 'Možnosti';
 $labels['low'] = 'Nizka';
 $labels['close'] = 'Zapri';
 $labels['messageoptions'] = 'Možnosti';
 $labels['low'] = 'Nizka';
@@ -187,6 +190,7 @@ $labels['highest'] = 'Najvišja';
 $labels['nosubject'] = '(brez naslova)';
 $labels['showimages'] = 'Prikaži slike';
 $labels['alwaysshow'] = 'Vedno prikaži slike od $sender';
 $labels['nosubject'] = '(brez naslova)';
 $labels['showimages'] = 'Prikaži slike';
 $labels['alwaysshow'] = 'Vedno prikaži slike od $sender';
+$labels['isdraft'] = 'To je osnutek sporočila.';
 $labels['htmltoggle'] = 'Obogateno besedilo (HTML)';
 $labels['plaintoggle'] = 'Samo besedilo';
 $labels['savesentmessagein'] = 'Shrani poslana sporočila v';
 $labels['htmltoggle'] = 'Obogateno besedilo (HTML)';
 $labels['plaintoggle'] = 'Samo besedilo';
 $labels['savesentmessagein'] = 'Shrani poslana sporočila v';
@@ -245,6 +249,8 @@ $labels['typepager'] = 'Pozivnik';
 $labels['typevideo'] = 'Video';
 $labels['typeassistant'] = 'Pomoč';
 $labels['typehomepage'] = 'Domača stran';
 $labels['typevideo'] = 'Video';
 $labels['typeassistant'] = 'Pomoč';
 $labels['typehomepage'] = 'Domača stran';
+$labels['typeblog'] = 'Blog';
+$labels['typeprofile'] = 'Profil';
 $labels['addfield'] = 'Dodaj polje...';
 $labels['addcontact'] = 'Dodaj izbrane stike v imenik';
 $labels['editcontact'] = 'Uredi vizitko';
 $labels['addfield'] = 'Dodaj polje...';
 $labels['addcontact'] = 'Dodaj izbrane stike v imenik';
 $labels['editcontact'] = 'Uredi vizitko';
@@ -266,7 +272,6 @@ $labels['print'] = 'Natisni';
 $labels['export'] = 'Izvozi';
 $labels['exportvcards'] = 'Izvozi stike v formatu vCard';
 $labels['newcontactgroup'] = 'Ustvari novo skupino stikov';
 $labels['export'] = 'Izvozi';
 $labels['exportvcards'] = 'Izvozi stike v formatu vCard';
 $labels['newcontactgroup'] = 'Ustvari novo skupino stikov';
-$labels['groupactions'] = 'Dejanja za skupine stikov...';
 $labels['grouprename'] = 'Preimenuj skupino';
 $labels['groupdelete'] = 'Izbriši skupino';
 $labels['previouspage'] = 'Prejšnja stran';
 $labels['grouprename'] = 'Preimenuj skupino';
 $labels['groupdelete'] = 'Izbriši skupino';
 $labels['previouspage'] = 'Prejšnja stran';
@@ -276,6 +281,8 @@ $labels['lastpage'] = 'Zadnja stran';
 $labels['group'] = 'Skupina';
 $labels['groups'] = 'Skupine';
 $labels['personaladrbook'] = 'Stiki';
 $labels['group'] = 'Skupina';
 $labels['groups'] = 'Skupine';
 $labels['personaladrbook'] = 'Stiki';
+$labels['searchsave'] = 'Shrani iskanje';
+$labels['searchdelete'] = 'Izbriši iskanje';
 $labels['import'] = 'Uvozi';
 $labels['importcontacts'] = 'Uvozi stike';
 $labels['importfromfile'] = 'Uvozi iz datoteke:';
 $labels['import'] = 'Uvozi';
 $labels['importcontacts'] = 'Uvozi stike';
 $labels['importfromfile'] = 'Uvozi iz datoteke:';
@@ -284,6 +291,7 @@ $labels['importreplace'] = 'Zamenjaj celoten imenik';
 $labels['importtext'] = 'Stike lahko prenesete iz obstoječega imenika<br/> Trenutno je podprto uvažanje naslovov v  formatu <a href="http://en.wikipedia.org/wiki/VCard">vCard</a>';
 $labels['done'] = 'Dokončano';
 $labels['settingsfor'] = 'Nastavitve za';
 $labels['importtext'] = 'Stike lahko prenesete iz obstoječega imenika<br/> Trenutno je podprto uvažanje naslovov v  formatu <a href="http://en.wikipedia.org/wiki/VCard">vCard</a>';
 $labels['done'] = 'Dokončano';
 $labels['settingsfor'] = 'Nastavitve za';
+$labels['about'] = 'Vizitka';
 $labels['preferences'] = 'Nastavitve';
 $labels['userpreferences'] = 'Uporabniške nastavitve';
 $labels['editpreferences'] = 'Uredi uporabniške nastavitve';
 $labels['preferences'] = 'Nastavitve';
 $labels['userpreferences'] = 'Uporabniške nastavitve';
 $labels['editpreferences'] = 'Uredi uporabniške nastavitve';
@@ -295,6 +303,8 @@ $labels['edititem'] = 'Uredi predmet';
 $labels['preferhtml'] = 'Prednostno HTML';
 $labels['defaultcharset'] = 'Privzeto kodiranje znakov';
 $labels['htmlmessage'] = 'HTML sporočilo';
 $labels['preferhtml'] = 'Prednostno HTML';
 $labels['defaultcharset'] = 'Privzeto kodiranje znakov';
 $labels['htmlmessage'] = 'HTML sporočilo';
+$labels['dateformat'] = 'Prikaz datuma';
+$labels['timeformat'] = 'Prikaz časa';
 $labels['prettydate'] = 'Bolj čitljivi datumi';
 $labels['setdefault'] = 'Nastavi privzeto';
 $labels['autodetect'] = 'Samodejno';
 $labels['prettydate'] = 'Bolj čitljivi datumi';
 $labels['setdefault'] = 'Nastavi privzeto';
 $labels['autodetect'] = 'Samodejno';
@@ -366,7 +376,13 @@ $labels['reqmdn'] = 'Vedno zahtevaj povratnico';
 $labels['reqdsn'] = 'Vedno zahtevaj obvestilo o statusu dostave';
 $labels['replysamefolder'] = 'Shrani odgovore na sporočilo v mapo izvornega sporočila';
 $labels['defaultaddressbook'] = 'Dodaj nove stike v izbran imenik';
 $labels['reqdsn'] = 'Vedno zahtevaj obvestilo o statusu dostave';
 $labels['replysamefolder'] = 'Shrani odgovore na sporočilo v mapo izvornega sporočila';
 $labels['defaultaddressbook'] = 'Dodaj nove stike v izbran imenik';
+$labels['autocompletesingle'] = 'Preskoči nadomestni e-naslov pri samodejnem dokončanju';
 $labels['spellcheckbeforesend'] = 'Preveri črkovanje pred pošiljanjem sporočila';
 $labels['spellcheckbeforesend'] = 'Preveri črkovanje pred pošiljanjem sporočila';
+$labels['spellcheckoptions'] = 'Možnosti črkovanja';
+$labels['spellcheckignoresyms'] = 'Ne upoštevaj besed, ki vsebujejo simbole';
+$labels['spellcheckignorenums'] = 'Ne upoštevaj besed, ki vsebujejo številke';
+$labels['spellcheckignorecaps'] = 'Ne upoštevaj besed, ki vsebujejo samo velike črke';
+$labels['addtodict'] = 'Dodaj v slovar';
 $labels['folder'] = 'Mapa';
 $labels['folders'] = 'Mape';
 $labels['foldername'] = 'Ime mape';
 $labels['folder'] = 'Mapa';
 $labels['folders'] = 'Mape';
 $labels['foldername'] = 'Ime mape';
@@ -390,6 +406,12 @@ $labels['sharedfolder'] = 'Javna mapa';
 $labels['sortby'] = 'Uredi po';
 $labels['sortasc'] = 'Uredi naraščajoče';
 $labels['sortdesc'] = 'Uredi padajoče';
 $labels['sortby'] = 'Uredi po';
 $labels['sortasc'] = 'Uredi naraščajoče';
 $labels['sortdesc'] = 'Uredi padajoče';
+$labels['undo'] = 'Prekliči';
+$labels['plugin'] = 'Vtičnik';
+$labels['version'] = 'Različica';
+$labels['source'] = 'Vir';
+$labels['license'] = 'Licenca';
+$labels['support'] = 'Podpora';
 $labels['B'] = 'B';
 $labels['KB'] = 'KB';
 $labels['MB'] = 'MB';
 $labels['B'] = 'B';
 $labels['KB'] = 'KB';
 $labels['MB'] = 'MB';
index 996a0fd40590c5382e7d1f91a316f9432a049ade..1aa199ce392d3b08127af9a6f65343d02520ea68 100644 (file)
@@ -21,7 +21,7 @@ $messages['sessionerror'] = 'Seja je neveljavna ali je potekla.';
 $messages['imaperror'] = 'Povezava z IMAP strežnikom je spodletela.';
 $messages['servererror'] = 'Napaka strežnika!';
 $messages['servererrormsg'] = 'Napaka strežnikaČ $msg';
 $messages['imaperror'] = 'Povezava z IMAP strežnikom je spodletela.';
 $messages['servererror'] = 'Napaka strežnika!';
 $messages['servererrormsg'] = 'Napaka strežnikaČ $msg';
-$messages['databaserror'] = 'Napaka v bazi';
+$messages['dberror'] = 'Napaka v bazi';
 $messages['errorreadonly'] = 'Operacije ni bilo mogoče izvršiti. Mapa je na voljo samo za branje.';
 $messages['errornoperm'] = 'Operacije ni bilo mogoče izvršiti. Dostop zavrnjen.';
 $messages['invalidrequest'] = 'Neveljavna zahteva. Podatki niso bili shranjeni.';
 $messages['errorreadonly'] = 'Operacije ni bilo mogoče izvršiti. Mapa je na voljo samo za branje.';
 $messages['errornoperm'] = 'Operacije ni bilo mogoče izvršiti. Dostop zavrnjen.';
 $messages['invalidrequest'] = 'Neveljavna zahteva. Podatki niso bili shranjeni.';
@@ -40,10 +40,12 @@ $messages['messagesaved'] = 'Sporočilo je bilo shranjeno v Osnutke';
 $messages['successfullysaved'] = 'Uspešno shranjeno.';
 $messages['addedsuccessfully'] = 'Stik je bil uspešno dodan v imenik.';
 $messages['contactexists'] = 'Stik s tem elektronskim naslovom že obstaja.';
 $messages['successfullysaved'] = 'Uspešno shranjeno.';
 $messages['addedsuccessfully'] = 'Stik je bil uspešno dodan v imenik.';
 $messages['contactexists'] = 'Stik s tem elektronskim naslovom že obstaja.';
+$messages['contactnameexists'] = 'Stik s tem imenom že obstaja';
 $messages['blockedimages'] = 'Zaradi zaščite zasebnosti je prikaz slik v sporočilu onemogočen.';
 $messages['encryptedmessage'] = 'Sporočilo je šifrirano in ne more biti prikazano.';
 $messages['nocontactsfound'] = 'Ni stikov.';
 $messages['contactnotfound'] = 'Iskanega stika ni bilo mogoče najti.';
 $messages['blockedimages'] = 'Zaradi zaščite zasebnosti je prikaz slik v sporočilu onemogočen.';
 $messages['encryptedmessage'] = 'Sporočilo je šifrirano in ne more biti prikazano.';
 $messages['nocontactsfound'] = 'Ni stikov.';
 $messages['contactnotfound'] = 'Iskanega stika ni bilo mogoče najti.';
+$messages['contactsearchonly'] = 'Vpišite iskalni parameter za iskanje stika';
 $messages['sendingfailed'] = 'Sporočila ni bilo mogoče poslati.';
 $messages['senttooquickly'] = 'Počakajte $sec sekund in nato znova poskusite s pošiljanjem sporočila.';
 $messages['errorsavingsent'] = 'Pri shranjevanju poslanega sporočila je prišlo do napake.';
 $messages['sendingfailed'] = 'Sporočila ni bilo mogoče poslati.';
 $messages['senttooquickly'] = 'Počakajte $sec sekund in nato znova poskusite s pošiljanjem sporočila.';
 $messages['errorsavingsent'] = 'Pri shranjevanju poslanega sporočila je prišlo do napake.';
@@ -53,9 +55,12 @@ $messages['errorcopying'] = 'Sporočila ni bilo mogoče kopirati.';
 $messages['errordeleting'] = 'Sporočila ni bilo mogoče izbrisati.';
 $messages['errormarking'] = 'Sporočila ni bilo mogoče označiti.';
 $messages['deletecontactconfirm'] = 'Ste prepričani, da želite izbrisati označen(e) stik(e)?';
 $messages['errordeleting'] = 'Sporočila ni bilo mogoče izbrisati.';
 $messages['errormarking'] = 'Sporočila ni bilo mogoče označiti.';
 $messages['deletecontactconfirm'] = 'Ste prepričani, da želite izbrisati označen(e) stik(e)?';
+$messages['deletegroupconfirm'] = 'Ste prepričani, da želite izbrisati izbrano skupino?';
 $messages['deletemessagesconfirm'] = 'Ste prepričani, da želite izbrisati označeno(a) sporočilo(a)?';
 $messages['deletefolderconfirm'] = 'Ste prepričani, da želite to mapo izbrisati?';
 $messages['purgefolderconfirm'] = 'Ste prepričani, da želite izbrisati vsa sporočila v mapi?';
 $messages['deletemessagesconfirm'] = 'Ste prepričani, da želite izbrisati označeno(a) sporočilo(a)?';
 $messages['deletefolderconfirm'] = 'Ste prepričani, da želite to mapo izbrisati?';
 $messages['purgefolderconfirm'] = 'Ste prepričani, da želite izbrisati vsa sporočila v mapi?';
+$messages['contactdeleting'] = 'Brisanje stika/ov...';
+$messages['groupdeleting'] = 'Brisanje skupine...';
 $messages['folderdeleting'] = 'Brisanje mape...';
 $messages['foldermoving'] = 'Premikanje mape...';
 $messages['foldersubscribing'] = 'Prijavljanje mape...';
 $messages['folderdeleting'] = 'Brisanje mape...';
 $messages['foldermoving'] = 'Premikanje mape...';
 $messages['foldersubscribing'] = 'Prijavljanje mape...';
@@ -70,10 +75,10 @@ $messages['nosubjectwarning'] = 'Polje "Zadeva" je prazno. Želite dodati tekst
 $messages['nobodywarning'] = 'Želite poslati sporočilo brez vsebine?';
 $messages['notsentwarning'] = 'Sporočilo ni bilo poslano. Želite zavreči to sporočilo?';
 $messages['noldapserver'] = 'Izberite LDAP strežnik, v katerem želite iskati?';
 $messages['nobodywarning'] = 'Želite poslati sporočilo brez vsebine?';
 $messages['notsentwarning'] = 'Sporočilo ni bilo poslano. Želite zavreči to sporočilo?';
 $messages['noldapserver'] = 'Izberite LDAP strežnik, v katerem želite iskati?';
-$messages['nocontactsreturned'] = 'Nobenega stika ni bilo mogoče najti';
 $messages['nosearchname'] = 'Vnesite ime ali elektronski naslov stika';
 $messages['notuploadedwarning'] = 'Priponke se še nalagajo na strežnik. Počakajte ali prekinite prenos.';
 $messages['searchsuccessful'] = '$nr najdenih sporočil';
 $messages['nosearchname'] = 'Vnesite ime ali elektronski naslov stika';
 $messages['notuploadedwarning'] = 'Priponke se še nalagajo na strežnik. Počakajte ali prekinite prenos.';
 $messages['searchsuccessful'] = '$nr najdenih sporočil';
+$messages['contactsearchsuccessful'] = '$nr najdenih stikov.';
 $messages['searchnomatch'] = 'Ni zadetkov';
 $messages['searching'] = 'Iskanje...';
 $messages['checking'] = 'Preverjanje...';
 $messages['searchnomatch'] = 'Ni zadetkov';
 $messages['searching'] = 'Iskanje...';
 $messages['checking'] = 'Preverjanje...';
@@ -94,8 +99,11 @@ $messages['sourceisreadonly'] = 'Ta naslov je na voljo samo za branje';
 $messages['errorsavingcontact'] = 'Stika ni bilo mogoče shraniti';
 $messages['movingmessage'] = 'Premikanje sporočila...';
 $messages['copyingmessage'] = 'Kopiranje sporočila...';
 $messages['errorsavingcontact'] = 'Stika ni bilo mogoče shraniti';
 $messages['movingmessage'] = 'Premikanje sporočila...';
 $messages['copyingmessage'] = 'Kopiranje sporočila...';
+$messages['copyingcontact'] = 'Kopiranje stika/ov';
 $messages['deletingmessage'] = 'Brisanje sporočil/a';
 $messages['markingmessage'] = 'Označevanje sporočil/a';
 $messages['deletingmessage'] = 'Brisanje sporočil/a';
 $messages['markingmessage'] = 'Označevanje sporočil/a';
+$messages['addingmember'] = 'Dodajanje stika/ov v skupino...';
+$messages['removingmember'] = 'Odstranjevanje stika/ov iz skupine..';
 $messages['receiptsent'] = 'Sporočilo o branju je bilo uspešno poslano';
 $messages['errorsendingreceipt'] = 'Sporočila o branju ni bilo mogoče poslati';
 $messages['nodeletelastidentity'] = 'Te identitete ni mogoče izbrisati, saj je edina.';
 $messages['receiptsent'] = 'Sporočilo o branju je bilo uspešno poslano';
 $messages['errorsendingreceipt'] = 'Sporočila o branju ni bilo mogoče poslati';
 $messages['nodeletelastidentity'] = 'Te identitete ni mogoče izbrisati, saj je edina.';
@@ -117,7 +125,6 @@ $messages['smtpautherror'] = 'Napaka pri pošiljanju($code): Avtentikacija je sp
 $messages['smtpfromerror'] = 'Napaka pri pošiljanju ($code): Neveljaven elektronski naslov pošiljatelja "$from" ($msg)';
 $messages['smtptoerror'] = 'Napaka pri pošiljanju ($code): Neveljaven elektronski naslov prejemnika "$to" ($msg)';
 $messages['smtprecipientserror'] = 'Napaka pri pošiljanju: Seznama prejemnikov ni bilo mogoče razčleniti';
 $messages['smtpfromerror'] = 'Napaka pri pošiljanju ($code): Neveljaven elektronski naslov pošiljatelja "$from" ($msg)';
 $messages['smtptoerror'] = 'Napaka pri pošiljanju ($code): Neveljaven elektronski naslov prejemnika "$to" ($msg)';
 $messages['smtprecipientserror'] = 'Napaka pri pošiljanju: Seznama prejemnikov ni bilo mogoče razčleniti';
-$messages['smtpdsnerror'] = 'Napaka pri pošiljanju: Ni podpore za pošiljanje obvestil o statusu dostave';
 $messages['smtperror'] = 'Napaka pri pošiljanju:$msg';
 $messages['emailformaterror'] = 'Nepravilen elektronski naslov: $email';
 $messages['toomanyrecipients'] = 'Navedli ste preveč prejemnikov. Zmanjšajte število prejemnikov na $max';
 $messages['smtperror'] = 'Napaka pri pošiljanju:$msg';
 $messages['emailformaterror'] = 'Nepravilen elektronski naslov: $email';
 $messages['toomanyrecipients'] = 'Navedli ste preveč prejemnikov. Zmanjšajte število prejemnikov na $max';
@@ -125,19 +132,27 @@ $messages['maxgroupmembersreached'] = 'Število članov skupine presega največj
 $messages['internalerror'] = 'Prišlo je do napake. Poskusite znova.';
 $messages['contactdelerror'] = 'Stika/ov ni bilo mogoče izbrisati';
 $messages['contactdeleted'] = 'Stik/i so bili uspešno izbrisani';
 $messages['internalerror'] = 'Prišlo je do napake. Poskusite znova.';
 $messages['contactdelerror'] = 'Stika/ov ni bilo mogoče izbrisati';
 $messages['contactdeleted'] = 'Stik/i so bili uspešno izbrisani';
+$messages['contactrestoreerror'] = 'Ni bilo mogoče obnoviti izbrisanih stikov.';
+$messages['contactrestored'] = 'Stiki so bili uspešno obnovljeni.';
 $messages['groupdeleted'] = 'Skupina je bila uspešno izbrisana';
 $messages['grouprenamed'] = 'Skupina je bila uspešno preimenovana';
 $messages['groupcreated'] = 'Skupina je bila uspešno ustvarjena';
 $messages['groupdeleted'] = 'Skupina je bila uspešno izbrisana';
 $messages['grouprenamed'] = 'Skupina je bila uspešno preimenovana';
 $messages['groupcreated'] = 'Skupina je bila uspešno ustvarjena';
+$messages['savedsearchdeleted'] = 'Shranjeno iskanje je bilo uspešno izbrisano.';
+$messages['savedsearchdeleteerror'] = 'Ni bilo mogoče izbrisati shranjenega iskanja.';
+$messages['savedsearchcreated'] = 'Iskanje je bilo uspešno shranjeno.';
+$messages['savedsearchcreateerror'] = 'Iskanja ni bilo mogoče shraniti.';
 $messages['messagedeleted'] = 'Sporočila so bila uspešno izbrisana';
 $messages['messagemoved'] = 'Sporočila so bila uspešno premaknjena';
 $messages['messagecopied'] = 'Sporočila so bila uspešno kopirana';
 $messages['messagemarked'] = 'Sporočila so bila uspešno označena';
 $messages['autocompletechars'] = 'Vnesite vsaj $min znakov za samodejno dokončanje';
 $messages['messagedeleted'] = 'Sporočila so bila uspešno izbrisana';
 $messages['messagemoved'] = 'Sporočila so bila uspešno premaknjena';
 $messages['messagecopied'] = 'Sporočila so bila uspešno kopirana';
 $messages['messagemarked'] = 'Sporočila so bila uspešno označena';
 $messages['autocompletechars'] = 'Vnesite vsaj $min znakov za samodejno dokončanje';
+$messages['autocompletemore'] = 'Z iskanjem se ujema več vnosov. Vnesite dodatne črke.';
 $messages['namecannotbeempty'] = 'Imena ni mogoče izbrisati';
 $messages['nametoolong'] = 'Ime je predolgo';
 $messages['folderupdated'] = 'Mapa je bila uspešno posodobljena';
 $messages['foldercreated'] = 'Mapa je bila uspešno ustvarjena';
 $messages['invalidimageformat'] = 'Neveljaven format slike';
 $messages['mispellingsfound'] = 'V sporočilu so bile najdene napake v črkovanju';
 $messages['namecannotbeempty'] = 'Imena ni mogoče izbrisati';
 $messages['nametoolong'] = 'Ime je predolgo';
 $messages['folderupdated'] = 'Mapa je bila uspešno posodobljena';
 $messages['foldercreated'] = 'Mapa je bila uspešno ustvarjena';
 $messages['invalidimageformat'] = 'Neveljaven format slike';
 $messages['mispellingsfound'] = 'V sporočilu so bile najdene napake v črkovanju';
+$messages['parentnotwritable'] = 'Podmape v tej mapi ni bilo mogoče ustvariti/premakniti. Nimate pravic.';
 
 ?>
 
 ?>
index c864c5ed68b7f23c30d6103f9739b3f5a4ac35d3..947a5aedc62e279b3ced65eaf66e0225b1d6d831 100644 (file)
@@ -1,4 +1,4 @@
-<?php
+a<?php
 
 /*
 
 
 /*
 
@@ -15,7 +15,7 @@
 |         Andreas Henriksson <andreas@fatal.se>                         |
 +-----------------------------------------------------------------------+
 
 |         Andreas Henriksson <andreas@fatal.se>                         |
 +-----------------------------------------------------------------------+
 
-@version $Id: labels.inc 5175 2011-09-05 18:42:24Z thomasb $
+@version $Id: labels.inc 5290 2011-09-28 17:09:50Z thomasb $
 
 */
 
 
 */
 
@@ -119,7 +119,7 @@ $labels['markread'] = 'Läst';
 $labels['markunread'] = 'Oläst';
 $labels['markflagged'] = 'Flaggat';
 $labels['markunflagged'] = 'Oflaggat';
 $labels['markunread'] = 'Oläst';
 $labels['markflagged'] = 'Flaggat';
 $labels['markunflagged'] = 'Oflaggat';
-$labels['messageactions'] = 'Hantera meddelande';
+$labels['moreactions'] = 'Ytterligare hantering...';
 $labels['select'] = 'Välj';
 $labels['all'] = 'Alla';
 $labels['none'] = 'Ingen';
 $labels['select'] = 'Välj';
 $labels['all'] = 'Alla';
 $labels['none'] = 'Ingen';
@@ -173,6 +173,7 @@ $labels['editortype'] = 'Textredigerare';
 $labels['returnreceipt'] = 'Mottagarkvitto';
 $labels['dsn'] = 'Leveransstatusmeddelande';
 $labels['mailreplyintro'] = '$date skrev $sender:';
 $labels['returnreceipt'] = 'Mottagarkvitto';
 $labels['dsn'] = 'Leveransstatusmeddelande';
 $labels['mailreplyintro'] = '$date skrev $sender:';
+$labels['originalmessage'] = 'Ursprungligt meddelande';
 $labels['editidents'] = 'Ändra identiteter';
 $labels['checkspelling'] = 'Kontrollera stavning';
 $labels['resumeediting'] = 'Återuppta redigering';
 $labels['editidents'] = 'Ändra identiteter';
 $labels['checkspelling'] = 'Kontrollera stavning';
 $labels['resumeediting'] = 'Återuppta redigering';
@@ -248,6 +249,8 @@ $labels['typepager'] = 'Personsökare';
 $labels['typevideo'] = 'Video';
 $labels['typeassistant'] = 'Assistent';
 $labels['typehomepage'] = 'Webbsida';
 $labels['typevideo'] = 'Video';
 $labels['typeassistant'] = 'Assistent';
 $labels['typehomepage'] = 'Webbsida';
+$labels['typeblog'] = 'Blog';
+$labels['typeprofile'] = 'Profil';
 $labels['addfield'] = 'Lägg till fält...';
 $labels['addcontact'] = 'Lägg till ny kontakt';
 $labels['editcontact'] = 'Ändra kontakt';
 $labels['addfield'] = 'Lägg till fält...';
 $labels['addcontact'] = 'Lägg till ny kontakt';
 $labels['editcontact'] = 'Ändra kontakt';
@@ -269,7 +272,6 @@ $labels['print'] = 'Skriv ut';
 $labels['export'] = 'Exportera';
 $labels['exportvcards'] = 'Exportera kontakter';
 $labels['newcontactgroup'] = 'Ny kontaktgrupp';
 $labels['export'] = 'Exportera';
 $labels['exportvcards'] = 'Exportera kontakter';
 $labels['newcontactgroup'] = 'Ny kontaktgrupp';
-$labels['groupactions'] = 'Hantera kontaktgrupper';
 $labels['grouprename'] = 'Ändra gruppnamn';
 $labels['groupdelete'] = 'Ta bort grupp';
 $labels['previouspage'] = 'Visa föregående sida';
 $labels['grouprename'] = 'Ändra gruppnamn';
 $labels['groupdelete'] = 'Ta bort grupp';
 $labels['previouspage'] = 'Visa föregående sida';
@@ -279,6 +281,8 @@ $labels['lastpage'] = 'Visa sista sidan';
 $labels['group'] = 'Grupp';
 $labels['groups'] = 'Kontaktgrupper';
 $labels['personaladrbook'] = 'Personliga adresser';
 $labels['group'] = 'Grupp';
 $labels['groups'] = 'Kontaktgrupper';
 $labels['personaladrbook'] = 'Personliga adresser';
+$labels['searchsave'] = 'Lägg till sökning';
+$labels['searchdelete'] = 'Ta bort sökning';
 $labels['import'] = 'Importera';
 $labels['importcontacts'] = 'Importera kontakter';
 $labels['importfromfile'] = 'Importera från fil:';
 $labels['import'] = 'Importera';
 $labels['importcontacts'] = 'Importera kontakter';
 $labels['importfromfile'] = 'Importera från fil:';
@@ -298,6 +302,8 @@ $labels['edititem'] = 'Ändra information';
 $labels['preferhtml'] = 'Visa meddelanden i HTML-format';
 $labels['defaultcharset'] = 'Förvald teckenkodning';
 $labels['htmlmessage'] = 'HTML-meddelande';
 $labels['preferhtml'] = 'Visa meddelanden i HTML-format';
 $labels['defaultcharset'] = 'Förvald teckenkodning';
 $labels['htmlmessage'] = 'HTML-meddelande';
+$labels['dateformat'] = 'Datumformat';
+$labels['timeformat'] = 'Tidformat';
 $labels['prettydate'] = 'Fina datum';
 $labels['setdefault'] = 'Sätt som standard';
 $labels['autodetect'] = 'Automatiskt';
 $labels['prettydate'] = 'Fina datum';
 $labels['setdefault'] = 'Sätt som standard';
 $labels['autodetect'] = 'Automatiskt';
@@ -370,6 +376,11 @@ $labels['reqdsn'] = 'Begär alltid leveransstatusmeddelande';
 $labels['replysamefolder'] = 'Placera svar i samma katalog som besvarat meddelande';
 $labels['defaultaddressbook'] = 'Lägg till nya kontakter i vald adressbok';
 $labels['spellcheckbeforesend'] = 'Kontrollera stavning innan meddelanden skickas';
 $labels['replysamefolder'] = 'Placera svar i samma katalog som besvarat meddelande';
 $labels['defaultaddressbook'] = 'Lägg till nya kontakter i vald adressbok';
 $labels['spellcheckbeforesend'] = 'Kontrollera stavning innan meddelanden skickas';
+$labels['spellcheckoptions'] = 'Rättstavningsalternativ';
+$labels['spellcheckignoresyms'] = 'Ignorera ord med symboler';
+$labels['spellcheckignorenums'] = 'Ignorera ord med siffror';
+$labels['spellcheckignorecaps'] = 'Ignorera ord med enbart stora bokstäver';
+$labels['addtodict'] = 'Lägg till i ordlista';
 $labels['folder'] = 'Katalog';
 $labels['folders'] = 'Kataloger';
 $labels['foldername'] = 'Katalognamn';
 $labels['folder'] = 'Katalog';
 $labels['folders'] = 'Kataloger';
 $labels['foldername'] = 'Katalognamn';
index 3e1cf346388904574e62873ddca1114822787d1b..5af843f1ad61a9c74bf1c8977bc057f53d39afb2 100644 (file)
@@ -15,7 +15,7 @@
 |         Andreas Henriksson <andreas@fatal.se>                         |
 +-----------------------------------------------------------------------+
 
 |         Andreas Henriksson <andreas@fatal.se>                         |
 +-----------------------------------------------------------------------+
 
-@version $Id: messages.inc 5175 2011-09-05 18:42:24Z thomasb $
+@version $Id: messages.inc 5290 2011-09-28 17:09:50Z thomasb $
 
 */
 
 
 */
 
@@ -26,7 +26,7 @@ $messages['sessionerror'] = 'Din inloggning är felaktig eller har gått ut';
 $messages['imaperror'] = 'Anslutning till IMAP-servern misslyckades';
 $messages['servererror'] = 'Serverfel!';
 $messages['servererrormsg'] = 'Serverfel: $msg';
 $messages['imaperror'] = 'Anslutning till IMAP-servern misslyckades';
 $messages['servererror'] = 'Serverfel!';
 $messages['servererrormsg'] = 'Serverfel: $msg';
-$messages['databaserror'] = 'Databasfel!';
+$messages['dberror'] = 'Databasfel!';
 $messages['errorreadonly'] = 'Åtgärden kunde inte utföras. Katalogen är skrivskyddad';
 $messages['errornoperm'] = 'Åtgärden kunde inte utföras. Otillräcklig befogenhet';
 $messages['invalidrequest'] = 'Ogiltig begäran! Informationen sparades inte.';
 $messages['errorreadonly'] = 'Åtgärden kunde inte utföras. Katalogen är skrivskyddad';
 $messages['errornoperm'] = 'Åtgärden kunde inte utföras. Otillräcklig befogenhet';
 $messages['invalidrequest'] = 'Ogiltig begäran! Informationen sparades inte.';
@@ -50,6 +50,7 @@ $messages['blockedimages'] = 'Externt länkade bilder i meddelandet har blockera
 $messages['encryptedmessage'] = 'Meddelandet är krypterat och kan tyvärr inte visas.';
 $messages['nocontactsfound'] = 'Inga kontakter hittades';
 $messages['contactnotfound'] = 'Efterfrågad kontakt hittades inte';
 $messages['encryptedmessage'] = 'Meddelandet är krypterat och kan tyvärr inte visas.';
 $messages['nocontactsfound'] = 'Inga kontakter hittades';
 $messages['contactnotfound'] = 'Efterfrågad kontakt hittades inte';
+$messages['contactsearchonly'] = 'Ange sökord för att hitta kontakter';
 $messages['sendingfailed'] = 'Meddelandet kunde inte skickas';
 $messages['senttooquickly'] = 'Vänta ytterligare $sec sekunder med att skicka meddelandet';
 $messages['errorsavingsent'] = 'Ett fel inträffade när det skickade meddelandet skulle sparas';
 $messages['sendingfailed'] = 'Meddelandet kunde inte skickas';
 $messages['senttooquickly'] = 'Vänta ytterligare $sec sekunder med att skicka meddelandet';
 $messages['errorsavingsent'] = 'Ett fel inträffade när det skickade meddelandet skulle sparas';
@@ -63,6 +64,7 @@ $messages['deletegroupconfirm'] = 'Vill du verkligen ta bort den valda gruppen?'
 $messages['deletemessagesconfirm'] = 'Vill du verkligen ta bort valda meddelanden?';
 $messages['deletefolderconfirm'] = 'Vill du verkligen ta bort den här katalogen?';
 $messages['purgefolderconfirm'] = 'Vill du verkligen ta bort alla meddelanden i den här katalogen?';
 $messages['deletemessagesconfirm'] = 'Vill du verkligen ta bort valda meddelanden?';
 $messages['deletefolderconfirm'] = 'Vill du verkligen ta bort den här katalogen?';
 $messages['purgefolderconfirm'] = 'Vill du verkligen ta bort alla meddelanden i den här katalogen?';
+$messages['contactdeleting'] = 'Tar bort kontakt...';
 $messages['groupdeleting'] = 'Tar bort grupp...';
 $messages['folderdeleting'] = 'Tar bort katalog...';
 $messages['foldermoving'] = 'Flyttar katalog...';
 $messages['groupdeleting'] = 'Tar bort grupp...';
 $messages['folderdeleting'] = 'Tar bort katalog...';
 $messages['foldermoving'] = 'Flyttar katalog...';
@@ -78,10 +80,10 @@ $messages['nosubjectwarning'] = 'Ämnesraden är tom. Vill du ange ämne nu?';
 $messages['nobodywarning'] = 'Skicka det här meddelandet utan text?';
 $messages['notsentwarning'] = 'Meddelandet har inte skickats. Vill du avbryta meddelandet?';
 $messages['noldapserver'] = 'Ange en LDAP-server för att söka';
 $messages['nobodywarning'] = 'Skicka det här meddelandet utan text?';
 $messages['notsentwarning'] = 'Meddelandet har inte skickats. Vill du avbryta meddelandet?';
 $messages['noldapserver'] = 'Ange en LDAP-server för att söka';
-$messages['nocontactsreturned'] = 'Inga kontakter hittades';
 $messages['nosearchname'] = 'Ange ett kontaktnamn eller en adress';
 $messages['notuploadedwarning'] = 'Alla bilagor har inte överförts ännu. Vänligen vänta eller avbryt överföringen.';
 $messages['searchsuccessful'] = '$nr meddelanden hittades';
 $messages['nosearchname'] = 'Ange ett kontaktnamn eller en adress';
 $messages['notuploadedwarning'] = 'Alla bilagor har inte överförts ännu. Vänligen vänta eller avbryt överföringen.';
 $messages['searchsuccessful'] = '$nr meddelanden hittades';
+$messages['contactsearchsuccessful'] = '$nr kontakter hittades';
 $messages['searchnomatch'] = 'Sökningen gav inget resultat';
 $messages['searching'] = 'Söker...';
 $messages['checking'] = 'Kontrollerar...';
 $messages['searchnomatch'] = 'Sökningen gav inget resultat';
 $messages['searching'] = 'Söker...';
 $messages['checking'] = 'Kontrollerar...';
@@ -141,11 +143,16 @@ $messages['contactrestored'] = 'Kontakter återskapade';
 $messages['groupdeleted'] = 'Grupp borttagen';
 $messages['grouprenamed'] = 'Gruppnamn ändrat';
 $messages['groupcreated'] = 'Grupp skapad';
 $messages['groupdeleted'] = 'Grupp borttagen';
 $messages['grouprenamed'] = 'Gruppnamn ändrat';
 $messages['groupcreated'] = 'Grupp skapad';
+$messages['savedsearchdeleted'] = 'Sparad sökning borttagen';
+$messages['savedsearchdeleteerror'] = 'Kunde inte ta bort sparad sökning';
+$messages['savedsearchcreated'] = 'Sparad sökning tillagd';
+$messages['savedsearchcreateerror'] = 'Kunde inte lägga till sparad sökning';
 $messages['messagedeleted'] = 'Meddelande borttaget';
 $messages['messagemoved'] = 'Meddelande flyttat';
 $messages['messagecopied'] = 'Meddelande kopierat';
 $messages['messagemarked'] = 'Meddelande markerat';
 $messages['autocompletechars'] = 'Ange minst $min tecken för automatisk komplettering';
 $messages['messagedeleted'] = 'Meddelande borttaget';
 $messages['messagemoved'] = 'Meddelande flyttat';
 $messages['messagecopied'] = 'Meddelande kopierat';
 $messages['messagemarked'] = 'Meddelande markerat';
 $messages['autocompletechars'] = 'Ange minst $min tecken för automatisk komplettering';
+$messages['autocompletemore'] = 'Flera passande informationsposter funna. Skriv fler tecken.';
 $messages['namecannotbeempty'] = 'Namnet får inte vara tomt';
 $messages['nametoolong'] = 'Namnet är för långt';
 $messages['folderupdated'] = 'Katalog uppdaterad';
 $messages['namecannotbeempty'] = 'Namnet får inte vara tomt';
 $messages['nametoolong'] = 'Namnet är för långt';
 $messages['folderupdated'] = 'Katalog uppdaterad';
index 089e0b121990b04c6ac3b15f772a7b3cff342cca..9409f953e4c54285661b810b7b55ee1a623a7d4e 100644 (file)
@@ -14,7 +14,7 @@
 | Author: Gökdeniz Karadağ <gokdenizk@gmail.com>                        |
 +-----------------------------------------------------------------------+
 
 | Author: Gökdeniz Karadağ <gokdenizk@gmail.com>                        |
 +-----------------------------------------------------------------------+
 
-@version $Id: labels.inc 5291 2011-09-28 17:10:45Z thomasb $
+@version $Id: labels.inc 5290 2011-09-28 17:09:50Z thomasb $
 
 */
 
 
 */
 
index 004644f58e9756b02eb9e357cfb7f03f10528427..aed1172060fb8ab76618bffe760d2eb2a3178652 100644 (file)
@@ -14,7 +14,7 @@
 | Author: Gökdeniz Karadağ <gokdenizk@gmail.com>                        |
 +-----------------------------------------------------------------------+
 
 | Author: Gökdeniz Karadağ <gokdenizk@gmail.com>                        |
 +-----------------------------------------------------------------------+
 
-@version $Id: messages.inc 5291 2011-09-28 17:10:45Z thomasb $
+@version $Id: messages.inc 5290 2011-09-28 17:09:50Z thomasb $
 
 */
 
 
 */
 
index 99f2d2eb0c91ef51550d853c2c4efa24496bf6ef..d4fbd75ad21f841dfe5e90c77aef6986039d300f 100644 (file)
@@ -13,7 +13,7 @@
 | Author: Volodymyr M. Kononenko aka kvm <vmkononenko@gmail.com>        |
 +-----------------------------------------------------------------------+
 
 | Author: Volodymyr M. Kononenko aka kvm <vmkononenko@gmail.com>        |
 +-----------------------------------------------------------------------+
 
-@version $Id: labels.inc 4671 2011-04-20 08:47:44Z thomasb $
+@version $Id: labels.inc 5569 2011-12-07 14:47:32Z thomasb $
 
 */
 
 
 */
 
@@ -100,6 +100,8 @@ $labels['replytomessage'] = 'Відповісти відправнику';
 $labels['replytoallmessage'] = 'Відповісти до листа або відправнику та усім отримувачам';
 $labels['replyall'] = 'Відповісти усім';
 $labels['replylist'] = 'Відповісти до листа';
 $labels['replytoallmessage'] = 'Відповісти до листа або відправнику та усім отримувачам';
 $labels['replyall'] = 'Відповісти усім';
 $labels['replylist'] = 'Відповісти до листа';
+$labels['forwardinline'] = 'Переслати у тілі листа';
+$labels['forwardattachment'] = 'Переслати як прикріплення';
 $labels['forwardmessage'] = 'Переслати повідомлення';
 $labels['deletemessage'] = 'У кошик';
 $labels['movemessagetotrash'] = 'Перемістити лист у кошик';
 $labels['forwardmessage'] = 'Переслати повідомлення';
 $labels['deletemessage'] = 'У кошик';
 $labels['movemessagetotrash'] = 'Перемістити лист у кошик';
@@ -115,7 +117,7 @@ $labels['markread'] = 'Позначити як прочитане';
 $labels['markunread'] = 'Позначити як непрочитане';
 $labels['markflagged'] = 'Додати зірочку';
 $labels['markunflagged'] = 'Зняти зірочку';
 $labels['markunread'] = 'Позначити як непрочитане';
 $labels['markflagged'] = 'Додати зірочку';
 $labels['markunflagged'] = 'Зняти зірочку';
-$labels['messageactions'] = 'Додаткові дії...';
+$labels['moreactions'] = 'Інші дії...';
 $labels['select'] = 'Вибрати';
 $labels['all'] = 'Всі';
 $labels['none'] = 'Жодного';
 $labels['select'] = 'Вибрати';
 $labels['all'] = 'Всі';
 $labels['none'] = 'Жодного';
@@ -168,12 +170,15 @@ $labels['charset'] = 'Кодування';
 $labels['editortype'] = 'Редактор';
 $labels['returnreceipt'] = 'Запит відповіді';
 $labels['dsn'] = 'Повідомлення про доставку';
 $labels['editortype'] = 'Редактор';
 $labels['returnreceipt'] = 'Запит відповіді';
 $labels['dsn'] = 'Повідомлення про доставку';
+$labels['mailreplyintro'] = '$date, $sender написав:';
+$labels['originalmessage'] = 'Оригінальне повідомлення';
 $labels['editidents'] = 'Змінити данні';
 $labels['checkspelling'] = 'Перевірити орфографію';
 $labels['resumeediting'] = 'Продовжити редагування';
 $labels['revertto'] = 'Відмінити редагування';
 $labels['attachments'] = 'Вкладені файли';
 $labels['upload'] = 'Вкласти';
 $labels['editidents'] = 'Змінити данні';
 $labels['checkspelling'] = 'Перевірити орфографію';
 $labels['resumeediting'] = 'Продовжити редагування';
 $labels['revertto'] = 'Відмінити редагування';
 $labels['attachments'] = 'Вкладені файли';
 $labels['upload'] = 'Вкласти';
+$labels['uploadprogress'] = '$percent ($current з $total)';
 $labels['close'] = 'Закрити';
 $labels['messageoptions'] = 'Налаштування листів';
 $labels['low'] = 'Низький';
 $labels['close'] = 'Закрити';
 $labels['messageoptions'] = 'Налаштування листів';
 $labels['low'] = 'Низький';
@@ -226,6 +231,10 @@ $labels['female'] = 'жіночий';
 $labels['manager'] = 'Менеждер';
 $labels['assistant'] = 'Помічник';
 $labels['spouse'] = 'Шлюбний партнер';
 $labels['manager'] = 'Менеждер';
 $labels['assistant'] = 'Помічник';
 $labels['spouse'] = 'Шлюбний партнер';
+$labels['allfields'] = 'Усі поля';
+$labels['search'] = 'Пошук';
+$labels['advsearch'] = 'Розширений пошук';
+$labels['other'] = 'Інше';
 $labels['typehome'] = 'Дім';
 $labels['typework'] = 'Робота';
 $labels['typeother'] = 'Інше';
 $labels['typehome'] = 'Дім';
 $labels['typework'] = 'Робота';
 $labels['typeother'] = 'Інше';
@@ -237,6 +246,9 @@ $labels['typecar'] = 'Автомобіль';
 $labels['typepager'] = 'Пейджер';
 $labels['typevideo'] = 'Відео';
 $labels['typeassistant'] = 'Помічник';
 $labels['typepager'] = 'Пейджер';
 $labels['typevideo'] = 'Відео';
 $labels['typeassistant'] = 'Помічник';
+$labels['typehomepage'] = 'Домашня сторінка';
+$labels['typeblog'] = 'Блог';
+$labels['typeprofile'] = 'Профіль';
 $labels['addfield'] = 'Додати поле...';
 $labels['addcontact'] = 'Додати вибрані контакти до списку контактів';
 $labels['editcontact'] = 'Редагувати контакт';
 $labels['addfield'] = 'Додати поле...';
 $labels['addcontact'] = 'Додати вибрані контакти до списку контактів';
 $labels['editcontact'] = 'Редагувати контакт';
@@ -258,7 +270,8 @@ $labels['print'] = 'Друкувати';
 $labels['export'] = 'Експортувати';
 $labels['exportvcards'] = 'Експортувати контакти у формат vCard';
 $labels['newcontactgroup'] = 'Створити нову групу контактів';
 $labels['export'] = 'Експортувати';
 $labels['exportvcards'] = 'Експортувати контакти у формат vCard';
 $labels['newcontactgroup'] = 'Створити нову групу контактів';
-$labels['groupactions'] = 'Дії з групами контактів';
+$labels['grouprename'] = 'Перейменувати групу';
+$labels['groupdelete'] = 'Видалити групу';
 $labels['previouspage'] = 'Попередня сторінка';
 $labels['firstpage'] = 'Перша сторінка';
 $labels['nextpage'] = 'Наступна сторінка';
 $labels['previouspage'] = 'Попередня сторінка';
 $labels['firstpage'] = 'Перша сторінка';
 $labels['nextpage'] = 'Наступна сторінка';
@@ -266,9 +279,12 @@ $labels['lastpage'] = 'Остання сторінка';
 $labels['group'] = 'Група';
 $labels['groups'] = 'Групи';
 $labels['personaladrbook'] = 'Персональні адреси';
 $labels['group'] = 'Група';
 $labels['groups'] = 'Групи';
 $labels['personaladrbook'] = 'Персональні адреси';
+$labels['searchsave'] = 'Зберегти пошук';
+$labels['searchdelete'] = 'Видалити пошук';
 $labels['import'] = 'Імпорт';
 $labels['importcontacts'] = 'Імпортувати контакти';
 $labels['importfromfile'] = 'Імпортувати з файлу:';
 $labels['import'] = 'Імпорт';
 $labels['importcontacts'] = 'Імпортувати контакти';
 $labels['importfromfile'] = 'Імпортувати з файлу:';
+$labels['importtarget'] = 'Додати нові контакти до адресної книги';
 $labels['importreplace'] = 'Замінити всю адресну книгу';
 $labels['importtext'] = 'Ви можете завантажити контакти з існуючої адресної книги. На даний момент підтримується імпортування контактів з формату vCard';
 $labels['done'] = 'Готово';
 $labels['importreplace'] = 'Замінити всю адресну книгу';
 $labels['importtext'] = 'Ви можете завантажити контакти з існуючої адресної книги. На даний момент підтримується імпортування контактів з формату vCard';
 $labels['done'] = 'Готово';
@@ -284,6 +300,8 @@ $labels['edititem'] = 'Редагувати';
 $labels['preferhtml'] = 'Показувати в HTML';
 $labels['defaultcharset'] = 'Кодування за замовчуваннням';
 $labels['htmlmessage'] = 'Лист у HTML';
 $labels['preferhtml'] = 'Показувати в HTML';
 $labels['defaultcharset'] = 'Кодування за замовчуваннням';
 $labels['htmlmessage'] = 'Лист у HTML';
+$labels['dateformat'] = 'Формат дати';
+$labels['timeformat'] = 'Формат часу';
 $labels['prettydate'] = 'Дати у зручному форматі';
 $labels['setdefault'] = 'Встановити за замовчуванням';
 $labels['autodetect'] = 'Визначати автоматично';
 $labels['prettydate'] = 'Дати у зручному форматі';
 $labels['setdefault'] = 'Встановити за замовчуванням';
 $labels['autodetect'] = 'Визначати автоматично';
@@ -354,6 +372,13 @@ $labels['afternseconds'] = 'через $n секунд';
 $labels['reqmdn'] = 'Завжди вимагати повідомлення про доставку';
 $labels['reqdsn'] = 'Завжди вимагати повідомлення про статус доставки';
 $labels['replysamefolder'] = 'Розмістити відповіді у тій же папці, де знаходиться оригінал';
 $labels['reqmdn'] = 'Завжди вимагати повідомлення про доставку';
 $labels['reqdsn'] = 'Завжди вимагати повідомлення про статус доставки';
 $labels['replysamefolder'] = 'Розмістити відповіді у тій же папці, де знаходиться оригінал';
+$labels['defaultaddressbook'] = 'Додати нові контакти до обраної адресної книги';
+$labels['spellcheckbeforesend'] = 'Перевірити орфографію перед відправкою повідомлення';
+$labels['spellcheckoptions'] = 'Налаштування перевірки орфографії';
+$labels['spellcheckignoresyms'] = 'Ігнорувати слова із символами';
+$labels['spellcheckignorenums'] = 'Ігнорувати слова із числами';
+$labels['spellcheckignorecaps'] = 'Ігнорувати слова із великими буквами';
+$labels['addtodict'] = 'Додати до словника';
 $labels['folder'] = 'Папка';
 $labels['folders'] = 'Папки';
 $labels['foldername'] = 'Назва папки';
 $labels['folder'] = 'Папка';
 $labels['folders'] = 'Папки';
 $labels['foldername'] = 'Назва папки';
@@ -377,6 +402,7 @@ $labels['sharedfolder'] = 'Публічний каталог';
 $labels['sortby'] = 'Відсортувати за';
 $labels['sortasc'] = 'Сортувати за зростанням';
 $labels['sortdesc'] = 'Сортувати за спаданням';
 $labels['sortby'] = 'Відсортувати за';
 $labels['sortasc'] = 'Сортувати за зростанням';
 $labels['sortdesc'] = 'Сортувати за спаданням';
+$labels['undo'] = 'Відмінити';
 $labels['B'] = 'б';
 $labels['KB'] = 'Кб';
 $labels['MB'] = 'Мб';
 $labels['B'] = 'б';
 $labels['KB'] = 'Кб';
 $labels['MB'] = 'Мб';
index 341f0ba8e089f982c88dde0bb84e40328b574d33..e302710097d965d14f968820b470135dbbf66ff9 100644 (file)
@@ -13,7 +13,7 @@
 | Author: Volodymyr M. Kononenko aka kvm <vmkononenko@gmail.com>        |
 +-----------------------------------------------------------------------+
 
 | Author: Volodymyr M. Kononenko aka kvm <vmkononenko@gmail.com>        |
 +-----------------------------------------------------------------------+
 
-@version $Id: messages.inc 4671 2011-04-20 08:47:44Z thomasb $
+@version $Id: messages.inc 5569 2011-12-07 14:47:32Z thomasb $
 
 */
 
 
 */
 
@@ -24,6 +24,7 @@ $messages['sessionerror'] = 'Ваша сесія застаріла';
 $messages['imaperror'] = 'Невдале з`єднання з IMAP сервером';
 $messages['servererror'] = 'Помилка сервера!';
 $messages['servererrormsg'] = 'Помилка сервера: $msg';
 $messages['imaperror'] = 'Невдале з`єднання з IMAP сервером';
 $messages['servererror'] = 'Помилка сервера!';
 $messages['servererrormsg'] = 'Помилка сервера: $msg';
+$messages['dberror'] = 'Помилка бази даних!';
 $messages['errorreadonly'] = 'Неможливо виконати операцію. Папка доступна тільки для читання.';
 $messages['errornoperm'] = 'Неможливо виконати операцію. Доступ заборонено';
 $messages['invalidrequest'] = 'Невірний запит! Дані не збережено.';
 $messages['errorreadonly'] = 'Неможливо виконати операцію. Папка доступна тільки для читання.';
 $messages['errornoperm'] = 'Неможливо виконати операцію. Доступ заборонено';
 $messages['invalidrequest'] = 'Невірний запит! Дані не збережено.';
@@ -32,6 +33,7 @@ $messages['loggedout'] = 'Вашу сесію завершено. Всього 
 $messages['mailboxempty'] = 'Поштова скринька порожня';
 $messages['loading'] = 'Завантаження...';
 $messages['uploading'] = 'Файл відправляється...';
 $messages['mailboxempty'] = 'Поштова скринька порожня';
 $messages['loading'] = 'Завантаження...';
 $messages['uploading'] = 'Файл відправляється...';
+$messages['uploadingmany'] = 'Завантаження файлів...';
 $messages['loadingdata'] = 'Завантаження даних...';
 $messages['checkingmail'] = 'Перевірка нових листів...';
 $messages['sendingmessage'] = 'Відправка листа...';
 $messages['loadingdata'] = 'Завантаження даних...';
 $messages['checkingmail'] = 'Перевірка нових листів...';
 $messages['sendingmessage'] = 'Відправка листа...';
@@ -41,10 +43,12 @@ $messages['messagesaved'] = 'Збережено в Чернетках';
 $messages['successfullysaved'] = 'Збережено';
 $messages['addedsuccessfully'] = 'Контакт успішно доданий до списку контактів';
 $messages['contactexists'] = 'Контакт з такою електронною адресою вже існує';
 $messages['successfullysaved'] = 'Збережено';
 $messages['addedsuccessfully'] = 'Контакт успішно доданий до списку контактів';
 $messages['contactexists'] = 'Контакт з такою електронною адресою вже існує';
+$messages['contactnameexists'] = 'Контакт з таким самим іменем вже існує.';
 $messages['blockedimages'] = 'З метою безпеки зображення з зовнішніх джерел заблоковано у цьому листі.';
 $messages['encryptedmessage'] = 'Лист зашифровано і не може бути відображено.';
 $messages['nocontactsfound'] = 'Контакти не знайдені';
 $messages['contactnotfound'] = 'Запитаний контакт не знайдений';
 $messages['blockedimages'] = 'З метою безпеки зображення з зовнішніх джерел заблоковано у цьому листі.';
 $messages['encryptedmessage'] = 'Лист зашифровано і не може бути відображено.';
 $messages['nocontactsfound'] = 'Контакти не знайдені';
 $messages['contactnotfound'] = 'Запитаний контакт не знайдений';
+$messages['contactsearchonly'] = 'Введіть деякі критерії пошуку, щоб знайти контакти';
 $messages['sendingfailed'] = 'Не вдалося відправити листа';
 $messages['senttooquickly'] = 'Будь ласка, зачекайте $sec секунд для відправки листа';
 $messages['errorsavingsent'] = 'Помилка при збереженні відправленого листа';
 $messages['sendingfailed'] = 'Не вдалося відправити листа';
 $messages['senttooquickly'] = 'Будь ласка, зачекайте $sec секунд для відправки листа';
 $messages['errorsavingsent'] = 'Помилка при збереженні відправленого листа';
@@ -54,9 +58,12 @@ $messages['errorcopying'] = 'Не вдалося зкопіювати листи
 $messages['errordeleting'] = 'Не вдалося видалити листи';
 $messages['errormarking'] = 'Не вдалося позначити листи';
 $messages['deletecontactconfirm'] = 'Ви дійсно бажаєте видалити вибрані контакти?';
 $messages['errordeleting'] = 'Не вдалося видалити листи';
 $messages['errormarking'] = 'Не вдалося позначити листи';
 $messages['deletecontactconfirm'] = 'Ви дійсно бажаєте видалити вибрані контакти?';
+$messages['deletegroupconfirm'] = 'Ви дійсно хочете видалити обрану групу?';
 $messages['deletemessagesconfirm'] = 'Ви дійсно бажаєте видалити вибрані листи?';
 $messages['deletefolderconfirm'] = 'Ви дійсно бажаєте видалити цю папку?';
 $messages['purgefolderconfirm'] = 'Ви дійсно бажаєте видалити всі листи у цій папці?';
 $messages['deletemessagesconfirm'] = 'Ви дійсно бажаєте видалити вибрані листи?';
 $messages['deletefolderconfirm'] = 'Ви дійсно бажаєте видалити цю папку?';
 $messages['purgefolderconfirm'] = 'Ви дійсно бажаєте видалити всі листи у цій папці?';
+$messages['contactdeleting'] = 'Видалення контакту(ів)...';
+$messages['groupdeleting'] = 'Видалення групи...';
 $messages['folderdeleting'] = 'Видалення папки...';
 $messages['foldermoving'] = 'Переміщення папки...';
 $messages['foldersubscribing'] = 'Підписати папку...';
 $messages['folderdeleting'] = 'Видалення папки...';
 $messages['foldermoving'] = 'Переміщення папки...';
 $messages['foldersubscribing'] = 'Підписати папку...';
@@ -71,10 +78,10 @@ $messages['nosubjectwarning'] = 'Не вказано тему листа. Баж
 $messages['nobodywarning'] = 'Відправити листа без тексту?';
 $messages['notsentwarning'] = 'Лист не було відправлено. Ви бажаєте відхилити відправку?';
 $messages['noldapserver'] = 'Будь ласка, виберіть LDAP сервер для пошуку';
 $messages['nobodywarning'] = 'Відправити листа без тексту?';
 $messages['notsentwarning'] = 'Лист не було відправлено. Ви бажаєте відхилити відправку?';
 $messages['noldapserver'] = 'Будь ласка, виберіть LDAP сервер для пошуку';
-$messages['nocontactsreturned'] = 'Контакти не знайдені';
 $messages['nosearchname'] = 'Будь ласка, введіть ім`я чи електронну адресу';
 $messages['notuploadedwarning'] = 'Деякі вкладення не було завантажено. Будь ласка, почекайте або відмініть завантаження.';
 $messages['searchsuccessful'] = 'Зайдено $nr листів';
 $messages['nosearchname'] = 'Будь ласка, введіть ім`я чи електронну адресу';
 $messages['notuploadedwarning'] = 'Деякі вкладення не було завантажено. Будь ласка, почекайте або відмініть завантаження.';
 $messages['searchsuccessful'] = 'Зайдено $nr листів';
+$messages['contactsearchsuccessful'] = '$nr контактів знайдено.';
 $messages['searchnomatch'] = 'Листів не знайдено';
 $messages['searching'] = 'Пошук...';
 $messages['checking'] = 'Перевірка...';
 $messages['searchnomatch'] = 'Листів не знайдено';
 $messages['searching'] = 'Пошук...';
 $messages['checking'] = 'Перевірка...';
@@ -95,8 +102,11 @@ $messages['sourceisreadonly'] = 'Дане джерело адрес доступ
 $messages['errorsavingcontact'] = 'Неможливо зберегти адресу контакту';
 $messages['movingmessage'] = 'Переміщення листа...';
 $messages['copyingmessage'] = 'Копіювання листа...';
 $messages['errorsavingcontact'] = 'Неможливо зберегти адресу контакту';
 $messages['movingmessage'] = 'Переміщення листа...';
 $messages['copyingmessage'] = 'Копіювання листа...';
+$messages['copyingcontact'] = 'Копіювання контакту(ів)...';
 $messages['deletingmessage'] = 'Видалення листа (ів)';
 $messages['markingmessage'] = 'Позначення листа (ів)';
 $messages['deletingmessage'] = 'Видалення листа (ів)';
 $messages['markingmessage'] = 'Позначення листа (ів)';
+$messages['addingmember'] = 'Додання контакту(ів) до групи...';
+$messages['removingmember'] = 'Видалення контакту(ів) з групи...';
 $messages['receiptsent'] = 'Повідомлення про прочитання відправлено';
 $messages['errorsendingreceipt'] = 'Не вдалося відправити повідомлення про прочитання';
 $messages['nodeletelastidentity'] = 'Ви не можете видалити цей профіль, він у Вас останній.';
 $messages['receiptsent'] = 'Повідомлення про прочитання відправлено';
 $messages['errorsendingreceipt'] = 'Не вдалося відправити повідомлення про прочитання';
 $messages['nodeletelastidentity'] = 'Ви не можете видалити цей профіль, він у Вас останній.';
@@ -126,18 +136,27 @@ $messages['maxgroupmembersreached'] = 'Число адрес у групі пе
 $messages['internalerror'] = 'Виникла внутрішня помилка. Будь ласка, спробуйте ще раз';
 $messages['contactdelerror'] = 'Неможливо видалити контакт(и)';
 $messages['contactdeleted'] = 'Контакт(и) видалено успішно';
 $messages['internalerror'] = 'Виникла внутрішня помилка. Будь ласка, спробуйте ще раз';
 $messages['contactdelerror'] = 'Неможливо видалити контакт(и)';
 $messages['contactdeleted'] = 'Контакт(и) видалено успішно';
+$messages['contactrestoreerror'] = 'Неможливо відновити видалений(і) контакт(и).';
+$messages['contactrestored'] = 'Контакт(и) вдало відновлено.';
 $messages['groupdeleted'] = 'Група видалена успішно';
 $messages['grouprenamed'] = 'Група перейменована успішно';
 $messages['groupcreated'] = 'Група створена успішно';
 $messages['groupdeleted'] = 'Група видалена успішно';
 $messages['grouprenamed'] = 'Група перейменована успішно';
 $messages['groupcreated'] = 'Група створена успішно';
+$messages['savedsearchdeleted'] = 'Збережений пошук вдало видалено.';
+$messages['savedsearchdeleteerror'] = 'Неможливо видалити збережений пошук.';
+$messages['savedsearchcreated'] = 'Збережений пошук вдало створено.';
+$messages['savedsearchcreateerror'] = 'Не вдалось створити збережений пошук. ';
 $messages['messagedeleted'] = 'Лист(и) видалено успішно';
 $messages['messagemoved'] = 'Лист(и) переміщено успішно';
 $messages['messagecopied'] = 'Лист(и) скопійовано успішно';
 $messages['messagemarked'] = 'Лист(и) помічено успішно';
 $messages['autocompletechars'] = 'Введіть щонайменьше $min символів для автозаповнення';
 $messages['messagedeleted'] = 'Лист(и) видалено успішно';
 $messages['messagemoved'] = 'Лист(и) переміщено успішно';
 $messages['messagecopied'] = 'Лист(и) скопійовано успішно';
 $messages['messagemarked'] = 'Лист(и) помічено успішно';
 $messages['autocompletechars'] = 'Введіть щонайменьше $min символів для автозаповнення';
+$messages['autocompletemore'] = 'Знайдено багато відповідних записів. Будь ласка введіть більше символів.';
 $messages['namecannotbeempty'] = 'Ім’я не може бути пустим';
 $messages['nametoolong'] = 'Занадто довге ім’я';
 $messages['folderupdated'] = 'Папка відновлена';
 $messages['foldercreated'] = 'Папка створена';
 $messages['invalidimageformat'] = 'Невірний формат зображення';
 $messages['namecannotbeempty'] = 'Ім’я не може бути пустим';
 $messages['nametoolong'] = 'Занадто довге ім’я';
 $messages['folderupdated'] = 'Папка відновлена';
 $messages['foldercreated'] = 'Папка створена';
 $messages['invalidimageformat'] = 'Невірний формат зображення';
+$messages['mispellingsfound'] = 'Знайдено орфографічні помилки у повідомленні.';
+$messages['parentnotwritable'] = 'Неможливо створити/перемістити папку до обраної батьківської папки. Нема прав доступу.';
 
 ?>
 
 ?>
index 68fd505bb520b216a8fb44f4c6ef64c12b1a33e2..442f4a6032b4927c5dc61d1f86bb9c61307ad568 100644 (file)
 +-----------------------------------------------------------------------+
 | Author: Xue zhong sheng <xue.zhongsheng@gmail.com>                    |
 |         Zhang Huang bin <michaelbibby@gmail.com>                      |
 +-----------------------------------------------------------------------+
 | Author: Xue zhong sheng <xue.zhongsheng@gmail.com>                    |
 |         Zhang Huang bin <michaelbibby@gmail.com>                      |
+|         Kelphon Tang <kelphon@kingstor.com>                          |
 +-----------------------------------------------------------------------+
 
 +-----------------------------------------------------------------------+
 
-@version $Id: labels.inc 5067 2011-08-14 18:47:58Z thomasb $
+@version $Id: labels.inc 5569 2011-12-07 14:47:32Z thomasb $
 
 */
 
 $labels = array();
 
 */
 
 $labels = array();
+
+// login page
 $labels['welcome'] = '欢迎使用 $product';
 $labels['username'] = '用户名';
 $labels['password'] = '密码';
 $labels['welcome'] = '欢迎使用 $product';
 $labels['username'] = '用户名';
 $labels['password'] = '密码';
@@ -27,8 +30,8 @@ $labels['login'] = '登录';
 
 // taskbar
 $labels['logout'] = '注销';
 
 // taskbar
 $labels['logout'] = '注销';
-$labels['mail'] = '电子邮件';
-$labels['settings'] = '邮箱设置';
+$labels['mail'] = '邮件';
+$labels['settings'] = '设置';
 $labels['addressbook'] = '通讯录';
 
 // mailbox names
 $labels['addressbook'] = '通讯录';
 
 // mailbox names
@@ -122,18 +125,16 @@ $labels['replytomessage'] = '回复发件人';
 $labels['replytoallmessage'] = '回复所有';
 $labels['replyall']         = '回复全部';
 $labels['replylist']        = '回复列表';
 $labels['replytoallmessage'] = '回复所有';
 $labels['replyall']         = '回复全部';
 $labels['replylist']        = '回复列表';
+$labels['forwardinline']    = '直接转发';
+$labels['forwardattachment'] = '以附件转发';
 $labels['forwardmessage'] = '转发邮件';
 $labels['deletemessage'] = '删除邮件';
 $labels['movemessagetotrash'] = '移动邮件到回收站';
 $labels['printmessage'] = '打印邮件';
 $labels['previousmessage'] = '显示上一封邮件';
 $labels['forwardmessage'] = '转发邮件';
 $labels['deletemessage'] = '删除邮件';
 $labels['movemessagetotrash'] = '移动邮件到回收站';
 $labels['printmessage'] = '打印邮件';
 $labels['previousmessage'] = '显示上一封邮件';
-$labels['previousmessages'] = '上一页';
 $labels['firstmessage'] = '显示第一封邮件';
 $labels['firstmessage'] = '显示第一封邮件';
-$labels['firstmessages'] = '第一页';
 $labels['nextmessage'] = '下一封';
 $labels['nextmessage'] = '下一封';
-$labels['nextmessages'] = '下一页';
 $labels['lastmessage'] = '最后一封';
 $labels['lastmessage'] = '最后一封';
-$labels['lastmessages'] = '最后一页';
 $labels['backtolist'] = '返回邮件列表';
 $labels['viewsource'] = '显示邮件源文件';
 $labels['markmessages'] = '标记邮件';
 $labels['backtolist'] = '返回邮件列表';
 $labels['viewsource'] = '显示邮件源文件';
 $labels['markmessages'] = '标记邮件';
@@ -160,6 +161,7 @@ $labels['expand-all'] = '展开全部';
 $labels['expand-unread'] = '展开未读';
 $labels['collapse-all'] = '收合全部';
 $labels['threaded'] = '线索';
 $labels['expand-unread'] = '展开未读';
 $labels['collapse-all'] = '收合全部';
 $labels['threaded'] = '线索';
+
 $labels['autoexpand_threads'] = '展开消息主题';
 $labels['do_expand'] = '所有主题';
 $labels['expand_only_unread'] = '仅未读消息';
 $labels['autoexpand_threads'] = '展开消息主题';
 $labels['do_expand'] = '所有主题';
 $labels['expand_only_unread'] = '仅未读消息';
@@ -179,16 +181,19 @@ $labels['listmode'] = '列表视图样式';
 $labels['folderactions'] = '目录操作...';
 $labels['compact'] = '压缩';
 $labels['empty'] = '清空';
 $labels['folderactions'] = '目录操作...';
 $labels['compact'] = '压缩';
 $labels['empty'] = '清空';
-$labels['purge'] = '清除';
+
 $labels['quota'] = '邮箱容量';
 $labels['unknown'] = '未知';
 $labels['unlimited'] = '无限制';
 $labels['quota'] = '邮箱容量';
 $labels['unknown'] = '未知';
 $labels['unlimited'] = '无限制';
+
 $labels['quicksearch'] = '快速查找';
 $labels['resetsearch'] = '清空查找内容';
 $labels['searchmod'] = '搜寻模式';
 $labels['msgtext'] = '整个邮件';
 $labels['quicksearch'] = '快速查找';
 $labels['resetsearch'] = '清空查找内容';
 $labels['searchmod'] = '搜寻模式';
 $labels['msgtext'] = '整个邮件';
+
 $labels['openinextwin'] = '在新窗口中打开';
 $labels['emlsave'] = '下载(.eml)';
 $labels['openinextwin'] = '在新窗口中打开';
 $labels['emlsave'] = '下载(.eml)';
+
 // message compose
 $labels['compose']        = '写新邮件';
 $labels['editasnew'] = '编辑为新邮件';
 // message compose
 $labels['compose']        = '写新邮件';
 $labels['editasnew'] = '编辑为新邮件';
@@ -199,6 +204,7 @@ $labels['charset'] = '字符集';
 $labels['editortype'] = '编辑器类型';
 $labels['returnreceipt'] = '邮件回执';
 $labels['dsn']            = '投递状态提示';
 $labels['editortype'] = '编辑器类型';
 $labels['returnreceipt'] = '邮件回执';
 $labels['dsn']            = '投递状态提示';
+$labels['mailreplyintro'] = '于 $date, $sender 回复:';
 
 $labels['editidents']    = '编辑身份';
 $labels['checkspelling'] = '拼写检查';
 
 $labels['editidents']    = '编辑身份';
 $labels['checkspelling'] = '拼写检查';
@@ -207,6 +213,7 @@ $labels['revertto'] = '恢复至';
 
 $labels['attachments'] = '附件';
 $labels['upload'] = '上传';
 
 $labels['attachments'] = '附件';
 $labels['upload'] = '上传';
+$labels['uploadprogress'] = '$percent ($current / $total)';
 $labels['close'] = '关闭';
 $labels['messageoptions']  = '邮件选项...';
 
 $labels['close'] = '关闭';
 $labels['messageoptions']  = '邮件选项...';
 
@@ -241,18 +248,67 @@ $labels['receiptnote'] = '注意:回执只表示邮件在收件人的电脑上
 $labels['name'] = '显示名称';
 $labels['firstname'] = '名字';
 $labels['surname'] = '姓氏';
 $labels['name'] = '显示名称';
 $labels['firstname'] = '名字';
 $labels['surname'] = '姓氏';
-$labels['email'] = '邮件地址';
-
+$labels['middlename']   = '中名';
+$labels['nameprefix']   = '前缀';
+$labels['namesuffix']   = '后缀';
+$labels['nickname']     = '昵称';
+$labels['jobtitle']     = '职位';
+$labels['organization'] = '公司';
+$labels['department']   = '部门';
+$labels['gender']       = 'Gender';
+$labels['maidenname']   = '娘家姓';
+$labels['email']        = 'Email';
+$labels['phone']        = '电话';
+$labels['address']      = '地址';
+$labels['street']       = '街道';
+$labels['locality']     = '城市';
+$labels['zipcode']      = '邮编';
+$labels['region']       = '省份';
+$labels['country']      = '国家';
+$labels['birthday']     = '生日';
+$labels['anniversary']  = '纪念日';
+$labels['website']      = '主页';
+$labels['instantmessenger'] = 'QQ';
+$labels['notes'] = '备注';
+$labels['male']   = '男';
+$labels['female'] = '女';
+$labels['manager'] = '经理';
+$labels['assistant'] = '助理';
+$labels['spouse'] = '配偶';
+$labels['allfields'] = '所有项目';
+$labels['search'] = '查询';
+$labels['advsearch'] = '高级查询';
+$labels['other'] = '其他';
+
+$labels['typehome']   = '家庭';
+$labels['typework']   = '工作';
+$labels['typeother']  = '其他';
+$labels['typemobile']  = '手机';
+$labels['typemain']  = '主';
+$labels['typehomefax']  = '家庭传真';
+$labels['typeworkfax']  = '工作传真';
+$labels['typecar']  = '车牌';
+$labels['typepager']  = '呼机';
+$labels['typevideo']  = '视频';
+$labels['typeassistant']  = '助理';
+$labels['typehomepage']  = '主页';
+$labels['typeblog'] = '博客';
+$labels['typeprofile'] = '资历';
+
+$labels['addfield'] = '增加项..';
 $labels['addcontact'] = '添加联系人';
 $labels['editcontact'] = '编辑联系人';
 $labels['contacts'] = '联系人';
 $labels['contactproperties'] = '联系人信息';
 $labels['addcontact'] = '添加联系人';
 $labels['editcontact'] = '编辑联系人';
 $labels['contacts'] = '联系人';
 $labels['contactproperties'] = '联系人信息';
+$labels['personalinfo'] = '个人信息';
 
 $labels['edit'] = '编辑';
 $labels['cancel'] = '取消';
 $labels['save'] = '保存';
 $labels['delete'] = '删除';
 $labels['rename'] = '更名';
 
 $labels['edit'] = '编辑';
 $labels['cancel'] = '取消';
 $labels['save'] = '保存';
 $labels['delete'] = '删除';
 $labels['rename'] = '更名';
+$labels['addphoto'] = '上传';
+$labels['replacephoto'] = '覆盖';
 
 $labels['newcontact'] = '新建联系人';
 $labels['deletecontact'] = '删除选中的联系人';
 
 $labels['newcontact'] = '新建联系人';
 $labels['deletecontact'] = '删除选中的联系人';
@@ -261,8 +317,10 @@ $labels['contactsfromto'] = '第 $from 到 $to 个联系人,共 $count 个';
 $labels['print'] = '打印';
 $labels['export'] = '导出';
 $labels['exportvcards'] = '以 vCard 格式导出联系人';
 $labels['print'] = '打印';
 $labels['export'] = '导出';
 $labels['exportvcards'] = '以 vCard 格式导出联系人';
-$labels['newcontactgroup'] = '创建新的联系人组';
-$labels['groupactions'] = '联系人组操作...';
+$labels['newcontactgroup'] = '创建新的组';
+$labels['groupactions'] = '组操作...';
+$labels['grouprename']    = '重命名组';
+$labels['groupdelete']    = '删除组';
 
 $labels['previouspage'] = '上一页';
 $labels['firstpage'] = '第一页';
 
 $labels['previouspage'] = '上一页';
 $labels['firstpage'] = '第一页';
@@ -271,11 +329,12 @@ $labels['lastpage'] = '最后一页';
 
 $labels['group'] = '分组';
 $labels['groups'] = '分组';
 
 $labels['group'] = '分组';
 $labels['groups'] = '分组';
-$labels['personaladrbook'] = '个人地址';
+$labels['personaladrbook'] = '个人通讯录';
 
 $labels['import'] = '导入';
 $labels['importcontacts'] = '导入联系人';
 $labels['importfromfile'] = '从文件导入';
 
 $labels['import'] = '导入';
 $labels['importcontacts'] = '导入联系人';
 $labels['importfromfile'] = '从文件导入';
+$labels['importtarget'] = '增加新联系人到通讯录:';
 $labels['importreplace'] = '替换整个地址簿';
 $labels['importtext'] = '你可以从已有的地址簿导入联系人。目前支持从 vCard 数据格式导入地址簿。';
 $labels['done'] = '完成';
 $labels['importreplace'] = '替换整个地址簿';
 $labels['importtext'] = '你可以从已有的地址簿导入联系人。目前支持从 vCard 数据格式导入地址簿。';
 $labels['done'] = '完成';
@@ -287,7 +346,7 @@ $labels['preferences'] = '偏好设置';
 $labels['userpreferences'] = '个人偏好';
 $labels['editpreferences'] = '修改个人偏好';
 
 $labels['userpreferences'] = '个人偏好';
 $labels['editpreferences'] = '修改个人偏好';
 
-$labels['identities'] = '发邮件的身份';
+$labels['identities'] = '发身份';
 $labels['manageidentities'] = '管理此账号的身份';
 $labels['newidentity'] = '添加身份';
 
 $labels['manageidentities'] = '管理此账号的身份';
 $labels['newidentity'] = '添加身份';
 
@@ -314,7 +373,7 @@ $labels['logoutclear'] = '退出时清空回收站';
 $labels['logoutcompact'] = '退出时压缩收件箱';
 $labels['uisettings'] = '用户界面';
 $labels['serversettings'] = '服务器设置';
 $labels['logoutcompact'] = '退出时压缩收件箱';
 $labels['uisettings'] = '用户界面';
 $labels['serversettings'] = '服务器设置';
-$labels['mailboxview'] = '邮箱查看方式';
+$labels['mailboxview'] = '显示邮件';
 $labels['mdnrequests'] = '发件人请求回执';
 $labels['askuser'] = '询问用户';
 $labels['autosend'] = '自动发送';
 $labels['mdnrequests'] = '发件人请求回执';
 $labels['askuser'] = '询问用户';
 $labels['autosend'] = '自动发送';
@@ -334,8 +393,8 @@ $labels['everynminutes'] = '每隔 $n 分钟';
 $labels['keepalive'] = '检查新邮件';
 $labels['never'] = '从不';
 $labels['immediately'] = '立即';
 $labels['keepalive'] = '检查新邮件';
 $labels['never'] = '从不';
 $labels['immediately'] = '立即';
-$labels['messagesdisplaying'] = '邮件显示设置';
-$labels['messagescomposition'] = '写邮件';
+$labels['messagesdisplaying'] = '显示参数';
+$labels['messagescomposition'] = '写邮件';
 $labels['mimeparamfolding'] = '附件名';
 $labels['2231folding'] = '完整的 RFC 2231(Thunderbird)';
 $labels['miscfolding'] = 'RFC 2047/2232(MS Outlook)';
 $labels['mimeparamfolding'] = '附件名';
 $labels['2231folding'] = '完整的 RFC 2231(Thunderbird)';
 $labels['miscfolding'] = 'RFC 2047/2232(MS Outlook)';
@@ -367,16 +426,18 @@ $labels['afternseconds'] = '$n 秒之后';
 $labels['reqmdn'] = '总是要求回执';
 $labels['reqdsn'] = '总是要求投递状态通知';
 $labels['replysamefolder'] = '保存回复邮件到邮件相同的目录';
 $labels['reqmdn'] = '总是要求回执';
 $labels['reqdsn'] = '总是要求投递状态通知';
 $labels['replysamefolder'] = '保存回复邮件到邮件相同的目录';
+$labels['defaultaddressbook'] = '增加联系人到所选通讯录';
+$labels['spellcheckbeforesend'] = '发邮件前进行拼写检查';
 
 
-$labels['folder'] = '邮件夹';
-$labels['folders'] = '邮件夹';
+$labels['folder'] = '目录管理';
+$labels['folders'] = '目录管理';
 $labels['foldername'] = '邮件夹名称';
 $labels['subscribed'] = '已订阅';
 $labels['messagecount'] = '邮件数量';
 $labels['create'] = '建立';
 $labels['createfolder'] = '建立新邮件夹';
 $labels['managefolders'] = '管理邮件夹';
 $labels['foldername'] = '邮件夹名称';
 $labels['subscribed'] = '已订阅';
 $labels['messagecount'] = '邮件数量';
 $labels['create'] = '建立';
 $labels['createfolder'] = '建立新邮件夹';
 $labels['managefolders'] = '管理邮件夹';
-$labels['specialfolders'] = '指定邮件夹';
+$labels['specialfolders'] = '定义邮件夹';
 $labels['properties'] = '属性';
 $labels['folderproperties'] = '文件夹属性';
 $labels['parentfolder'] = '父文件夹';
 $labels['properties'] = '属性';
 $labels['folderproperties'] = '文件夹属性';
 $labels['parentfolder'] = '父文件夹';
@@ -384,10 +445,15 @@ $labels['location'] = '位置';
 $labels['info'] = '信息';
 $labels['getfoldersize'] = '获得文件夹容量';
 $labels['changesubscription'] = '更改订阅';
 $labels['info'] = '信息';
 $labels['getfoldersize'] = '获得文件夹容量';
 $labels['changesubscription'] = '更改订阅';
+$labels['foldertype'] = '目录类型';
+$labels['personalfolder']  = '私有目录';
+$labels['otherfolder']  = '他人目录';
+$labels['sharedfolder']  = '共享目录';
 
 $labels['sortby'] = '排序';
 $labels['sortasc'] = '递增排序';
 $labels['sortdesc'] = '递减排序';
 
 $labels['sortby'] = '排序';
 $labels['sortasc'] = '递增排序';
 $labels['sortdesc'] = '递减排序';
+$labels['undo'] = '撤销';
 
 // units
 $labels['B'] = 'B';
 
 // units
 $labels['B'] = 'B';
@@ -415,4 +481,4 @@ $labels['japanese'] = '日文';
 $labels['korean'] = '韩语';
 $labels['chinese'] = '中文';
 
 $labels['korean'] = '韩语';
 $labels['chinese'] = '中文';
 
-?>
+?>
\ No newline at end of file
index f14d1b5a68afacc2e28f6ba741e4a26ee8db9c2b..28df0e54c6ce2870b669f598e9b3ba3cdec162b1 100644 (file)
 +-----------------------------------------------------------------------+
 | Author: Xue zhong sheng <xue.zhongsheng@gmail.com>                    |
 |         Zhang Huang bin <michaelbibby@gmail.com>                      |
 +-----------------------------------------------------------------------+
 | Author: Xue zhong sheng <xue.zhongsheng@gmail.com>                    |
 |         Zhang Huang bin <michaelbibby@gmail.com>                      |
+|         Kelphon Tang <kelphon@kingstor.com>                          |
 +-----------------------------------------------------------------------+
 
 +-----------------------------------------------------------------------+
 
-@version $Id: messages.inc 5067 2011-08-14 18:47:58Z thomasb $
+@version $Id: messages.inc 5569 2011-12-07 14:47:32Z thomasb $
 
 */
 
 
 */
 
@@ -25,6 +26,7 @@ $messages['sessionerror'] = '会话已过期';
 $messages['imaperror'] = '连接到邮件服务器失败';
 $messages['servererror'] = '服务器错误!';
 $messages['servererrormsg'] = '服务器错误: $msg';
 $messages['imaperror'] = '连接到邮件服务器失败';
 $messages['servererror'] = '服务器错误!';
 $messages['servererrormsg'] = '服务器错误: $msg';
+$messages['databaserror'] = '数据库错误!';
 $messages['errorreadonly'] = '不可对只读文件夹进行操作';
 $messages['errornoperm'] = '无权限操作';
 $messages['invalidrequest'] = '无效的请求!数据保存失败。';
 $messages['errorreadonly'] = '不可对只读文件夹进行操作';
 $messages['errornoperm'] = '无权限操作';
 $messages['invalidrequest'] = '无效的请求!数据保存失败。';
@@ -33,6 +35,7 @@ $messages['loggedout'] = '您已成功注销';
 $messages['mailboxempty'] = '邮件夹为空';
 $messages['loading'] = '正在加载...';
 $messages['uploading'] = '正在上传文件...';
 $messages['mailboxempty'] = '邮件夹为空';
 $messages['loading'] = '正在加载...';
 $messages['uploading'] = '正在上传文件...';
+$messages['uploadingmany'] = '正在上传多个文件...';
 $messages['loadingdata'] = '正在加载数据...';
 $messages['checkingmail'] = '检查新邮件...';
 $messages['sendingmessage'] = '正在发送邮件...';
 $messages['loadingdata'] = '正在加载数据...';
 $messages['checkingmail'] = '检查新邮件...';
 $messages['sendingmessage'] = '正在发送邮件...';
@@ -42,6 +45,7 @@ $messages['messagesaved'] = '邮件已暂存到草稿箱';
 $messages['successfullysaved'] = '保存成功';
 $messages['addedsuccessfully'] = '成功添加联系人';
 $messages['contactexists'] = '当前联系人的电子邮件地址已存在';
 $messages['successfullysaved'] = '保存成功';
 $messages['addedsuccessfully'] = '成功添加联系人';
 $messages['contactexists'] = '当前联系人的电子邮件地址已存在';
+$messages['contactnameexists'] = '已存在同名的联系人.';
 $messages['blockedimages'] = '为保护隐私,此邮件中的远程图片未显示';
 $messages['encryptedmessage'] = '因此邮件已加密,无法正常显示';
 $messages['nocontactsfound'] = '未找到联系人';
 $messages['blockedimages'] = '为保护隐私,此邮件中的远程图片未显示';
 $messages['encryptedmessage'] = '因此邮件已加密,无法正常显示';
 $messages['nocontactsfound'] = '未找到联系人';
@@ -55,9 +59,11 @@ $messages['errorcopying'] = '无法复制邮件';
 $messages['errordeleting'] = '无法删除邮件';
 $messages['errormarking'] = '无法标记邮件';
 $messages['deletecontactconfirm'] = '确定要删除已选中的联系人?';
 $messages['errordeleting'] = '无法删除邮件';
 $messages['errormarking'] = '无法标记邮件';
 $messages['deletecontactconfirm'] = '确定要删除已选中的联系人?';
+$messages['deletegroupconfirm']  = '确定要删除以选中的组?';
 $messages['deletemessagesconfirm'] = '确定要删除已选中的邮件?';
 $messages['deletefolderconfirm'] = '确定要删除已选中的邮件夹?';
 $messages['purgefolderconfirm'] = '是否确认要删除当前邮件夹中的所有邮件?';
 $messages['deletemessagesconfirm'] = '确定要删除已选中的邮件?';
 $messages['deletefolderconfirm'] = '确定要删除已选中的邮件夹?';
 $messages['purgefolderconfirm'] = '是否确认要删除当前邮件夹中的所有邮件?';
+$messages['groupdeleting'] = '正在删除组...';
 $messages['folderdeleting'] = '正在删除邮件夹';
 $messages['foldermoving'] = '正在移动目录...';
 $messages['foldersubscribing'] = '注册文件夹中...';
 $messages['folderdeleting'] = '正在删除邮件夹';
 $messages['foldermoving'] = '正在移动目录...';
 $messages['foldersubscribing'] = '注册文件夹中...';
@@ -96,8 +102,11 @@ $messages['sourceisreadonly'] = '源地址为只读';
 $messages['errorsavingcontact'] = '无法保存联系人的地址';
 $messages['movingmessage'] = '移动邮件到...';
 $messages['copyingmessage'] = '复制邮件到...';
 $messages['errorsavingcontact'] = '无法保存联系人的地址';
 $messages['movingmessage'] = '移动邮件到...';
 $messages['copyingmessage'] = '复制邮件到...';
+$messages['copyingcontact'] = '复制联系人...';
 $messages['deletingmessage'] = '正在删除邮件...';
 $messages['markingmessage'] = '正在标记邮件...';
 $messages['deletingmessage'] = '正在删除邮件...';
 $messages['markingmessage'] = '正在标记邮件...';
+$messages['addingmember'] = '正在添加联系人到组...';
+$messages['removingmember'] = '正在从组中删除联系人...';
 $messages['receiptsent'] = '成功发送了一个已读回执';
 $messages['errorsendingreceipt'] = '无法发送回执';
 $messages['nodeletelastidentity'] = '无法删除这个身份,这是最后一个。';
 $messages['receiptsent'] = '成功发送了一个已读回执';
 $messages['errorsendingreceipt'] = '无法发送回执';
 $messages['nodeletelastidentity'] = '无法删除这个身份,这是最后一个。';
@@ -109,6 +118,7 @@ $messages['contactremovedfromgroup'] = '成功从这个分组移除联系人';
 $messages['importwait'] = '正在导入,请稍后...';
 $messages['importerror'] = '导入失败!所上传的文件不是有效的 vCard 文件。';
 $messages['importconfirm'] = '<b>成功导入 $inserted 联系人,$skipped 乎略已存在的联系人</b>:<p><em>$names</em></p>';
 $messages['importwait'] = '正在导入,请稍后...';
 $messages['importerror'] = '导入失败!所上传的文件不是有效的 vCard 文件。';
 $messages['importconfirm'] = '<b>成功导入 $inserted 联系人,$skipped 乎略已存在的联系人</b>:<p><em>$names</em></p>';
+$messages['importconfirmskipped'] = '<b>跳过已存在 $skipped 项目</b>';
 $messages['opnotpermitted'] = '不允许的操作';
 $messages['nofromaddress'] = '选种的身份中没有邮件地址';
 $messages['editorwarning'] = '切换到纯文本编辑器将导致邮件正文中的所有文本格式失效,您确定要这样做吗?';
 $messages['opnotpermitted'] = '不允许的操作';
 $messages['nofromaddress'] = '选种的身份中没有邮件地址';
 $messages['editorwarning'] = '切换到纯文本编辑器将导致邮件正文中的所有文本格式失效,您确定要这样做吗?';
@@ -126,9 +136,11 @@ $messages['maxgroupmembersreached'] = '组员数量超过最大值 $max';
 $messages['internalerror'] = '遇到一个内部错误,请重试';
 $messages['contactdelerror'] = '无法删除联系人';
 $messages['contactdeleted'] = '删除联系人成功';
 $messages['internalerror'] = '遇到一个内部错误,请重试';
 $messages['contactdelerror'] = '无法删除联系人';
 $messages['contactdeleted'] = '删除联系人成功';
-$messages['groupdeleted'] = '成功删除联系人组';
-$messages['grouprenamed'] = '联系人组改名成功';
-$messages['groupcreated'] = '成功创建联系人组';
+$messages['contactrestoreerror'] = '无法恢复已删除的联系人.';
+$messages['contactrestored'] = '联系人恢复成功.';
+$messages['groupdeleted'] = '成功删除组';
+$messages['grouprenamed'] = '组改名成功';
+$messages['groupcreated'] = '成功创建组';
 $messages['messagedeleted'] = '删除邮件成功';
 $messages['messagemoved'] = '转移邮件成功';
 $messages['messagecopied'] = '复制邮件成功';
 $messages['messagedeleted'] = '删除邮件成功';
 $messages['messagemoved'] = '转移邮件成功';
 $messages['messagecopied'] = '复制邮件成功';
@@ -138,4 +150,7 @@ $messages['namecannotbeempty'] = '必须输入名字';
 $messages['nametoolong'] = '名字太长';
 $messages['folderupdated'] = '成功更新文件夹';
 $messages['foldercreated'] = '成功创建文件夹';
 $messages['nametoolong'] = '名字太长';
 $messages['folderupdated'] = '成功更新文件夹';
 $messages['foldercreated'] = '成功创建文件夹';
+$messages['invalidimageformat'] = '非法的图像类型.';
+$messages['mispellingsfound'] = '检查到拼写错误.';
+$messages['parentnotwritable'] = '无法创建和转移到所选的目录,权限不足.';
 ?>
 ?>
index e07d62af973c51d8441ddcc9f568597ffd048eb9..5e526e1aa1ffddc89fd7b0000fa95689b59b75bf 100644 (file)
@@ -60,9 +60,9 @@ foreach ($cids as $source => $cid)
         // Check if contact exists, if so, we'll need it's ID
         // Note: Some addressbooks allows empty email address field
         if (!empty($a_record['email']))
         // Check if contact exists, if so, we'll need it's ID
         // Note: Some addressbooks allows empty email address field
         if (!empty($a_record['email']))
-            $result = $TARGET->search('email', $a_record['email'], true, true, true);
+            $result = $TARGET->search('email', $a_record['email'], 1, true, true);
         else if (!empty($a_record['name']))
         else if (!empty($a_record['name']))
-            $result = $TARGET->search('name', $a_record['name'], true, true, true);
+            $result = $TARGET->search('name', $a_record['name'], 1, true, true);
         else
             $result = new rcube_result_set();
 
         else
             $result = new rcube_result_set();
 
index a710aa20437478b7dd40e860c9e1a4e39cdc3ffa..8ba1c08b617a9b1a6b7413d7060d31fc1199b6fd 100644 (file)
@@ -66,7 +66,6 @@ else {
 }
 
 // send downlaod headers
 }
 
 // send downlaod headers
-send_nocacheing_headers();
 header('Content-Type: text/x-vcard; charset='.RCMAIL_CHARSET);
 header('Content-Disposition: attachment; filename="rcube_contacts.vcf"');
 
 header('Content-Type: text/x-vcard; charset='.RCMAIL_CHARSET);
 header('Content-Disposition: attachment; filename="rcube_contacts.vcf"');
 
index c03f3e35990cc54245e3df666d40ffc8797487fc..40a23d746d0d015fff5851f82bbb6819795b1335 100644 (file)
@@ -15,7 +15,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: func.inc 5165 2011-09-05 08:49:04Z thomasb $
+ $Id: func.inc 5499 2011-11-28 09:03:27Z alec $
 
 */
 
 
 */
 
@@ -227,7 +227,32 @@ function rcmail_directory_list($attrib)
         $out = $groupdata['out'];
     }
 
         $out = $groupdata['out'];
     }
 
-    $OUTPUT->set_env('contactgroups', $jsdata); 
+    $line_templ = html::tag('li', array(
+        'id' => 'rcmliS%s', 'class' => '%s'),
+        html::a(array('href' => '#', 'rel' => 'S%s',
+            'onclick' => "return ".JS_OBJECT_NAME.".command('listsearch', '%s', this)"), '%s'));
+
+    // Saved searches
+    $sources = $RCMAIL->user->list_searches(rcube_user::SEARCH_ADDRESSBOOK);
+    foreach ($sources as $j => $source) {
+        $id = $source['id'];
+        $js_id = JQ($id);
+
+        // set class name(s)
+        $class_name = 'contactsearch';
+        if ($current === $id)
+            $class_name .= ' selected';
+        if ($source['class_name'])
+            $class_name .= ' ' . $source['class_name'];
+
+        $out .= sprintf($line_templ,
+            html_identifier($id),
+            $class_name,
+            $id,
+            $js_id, (!empty($source['name']) ? Q($source['name']) : Q($id)));
+    }
+
+    $OUTPUT->set_env('contactgroups', $jsdata);
     $OUTPUT->add_gui_object('folderlist', $attrib['id']);
     // add some labels to client
     $OUTPUT->add_label('deletegroupconfirm', 'groupdeleting', 'addingmember', 'removingmember');
     $OUTPUT->add_gui_object('folderlist', $attrib['id']);
     // add some labels to client
     $OUTPUT->add_label('deletegroupconfirm', 'groupdeleting', 'addingmember', 'removingmember');
@@ -287,7 +312,7 @@ function rcmail_contacts_list($attrib)
     $OUTPUT->include_script('list.js');
 
     // add some labels to client
     $OUTPUT->include_script('list.js');
 
     // add some labels to client
-    $OUTPUT->add_label('deletecontactconfirm', 'copyingcontact');
+    $OUTPUT->add_label('deletecontactconfirm', 'copyingcontact', 'contactdeleting');
 
     return $out;
 }
 
     return $out;
 }
@@ -383,12 +408,12 @@ function rcmail_get_rowcount_text($result=null)
 function rcmail_get_type_label($type)
 {
     $label = 'type'.$type;
 function rcmail_get_type_label($type)
 {
     $label = 'type'.$type;
-    if (rcube_label_exists($label))
-        return rcube_label($label);
+    if (rcube_label_exists($label, '*', $domain))
+        return rcube_label($label, $domain);
     else if (preg_match('/\w+(\d+)$/', $label, $m)
             && ($label = preg_replace('/(\d+)$/', '', $label))
     else if (preg_match('/\w+(\d+)$/', $label, $m)
             && ($label = preg_replace('/(\d+)$/', '', $label))
-            && rcube_label_exists($label))
-        return rcube_label($label) . ' ' . $m[1];
+            && rcube_label_exists($label, '*', $domain))
+        return rcube_label($label, $domain) . ' ' . $m[1];
 
     return ucfirst($type);
 }
 
     return ucfirst($type);
 }
@@ -397,6 +422,7 @@ function rcmail_get_type_label($type)
 function rcmail_contact_form($form, $record, $attrib = null)
 {
     global $RCMAIL, $CONFIG;
 function rcmail_contact_form($form, $record, $attrib = null)
 {
     global $RCMAIL, $CONFIG;
+    static $jqueryui_loaded = 0;
 
     // Allow plugins to modify contact form content
     $plugin = $RCMAIL->plugins->exec_hook('contact_form', array(
 
     // Allow plugins to modify contact form content
     $plugin = $RCMAIL->plugins->exec_hook('contact_form', array(
@@ -583,6 +609,19 @@ function rcmail_contact_form($form, $record, $attrib = null)
                         if ($colprop['subtypes'] || $colprop['limit'] != 1)
                             $colprop['array'] = true;
 
                         if ($colprop['subtypes'] || $colprop['limit'] != 1)
                             $colprop['array'] = true;
 
+                        // load jquery UI datepickert for date fields
+                        if ($colprop['type'] == 'date') {
+                            if (!$jqueryui_loaded++) {
+                                $RCMAIL->plugins->load_plugin('jqueryui');
+                                $RCMAIL->output->set_env('date_format', strtr($RCMAIL->config->get('date_format', 'Y-m-d'), array('y'=>'y', 'Y'=>'yy', 'm'=>'mm', 'n'=>'m', 'd'=>'dd', 'j'=>'d')));
+                                foreach (array('jan','feb','mar','apr','may','jun','jul','aug','sep','oct','nov','dec') as $month)
+                                    $month_names[] = rcube_label($month);
+                                $RCMAIL->output->set_env('month_names', $month_names);
+                            }
+                            $colprop['class'] .= ($colprop['class'] ? ' ' : '') . 'datepicker';
+                            $val = format_date($val, $RCMAIL->config->get('date_format', 'Y-m-d'), false);
+                        }
+
                         $val = rcmail_get_edit_field($col, $val, $colprop, $colprop['type']);
                         $coltypes[$field]['count']++;
                     }
                         $val = rcmail_get_edit_field($col, $val, $colprop, $colprop['type']);
                         $coltypes[$field]['count']++;
                     }
@@ -618,11 +657,16 @@ function rcmail_contact_form($form, $record, $attrib = null)
                 }
 
                 // wrap rows in fieldgroup container
                 }
 
                 // wrap rows in fieldgroup container
-                $content .= html::tag('fieldset', array('class' => 'contactfieldgroup ' . ($colprop['subtypes'] ? 'contactfieldgroupmulti ' : '') . 'contactcontroller' . $col, 'style' => ($rows ? null : 'display:none')),
-                  ($colprop['subtypes'] ? html::tag('legend', null, Q($colprop['label'])) : ' ') .
-                  $rows);
+                if ($rows) {
+                    $content .= html::tag('fieldset', array('class' => 'contactfieldgroup ' . ($colprop['subtypes'] ? 'contactfieldgroupmulti ' : '') . 'contactcontroller' . $col, 'style' => ($rows ? null : 'display:none')),
+                      ($colprop['subtypes'] ? html::tag('legend', null, Q($colprop['label'])) : ' ') .
+                      $rows);
+                }
             }
 
             }
 
+            if (!$content)
+                continue;
+
             // also render add-field selector
             if ($edit_mode)
                 $content .= html::p('addfield', $select_add->show(null, array('style' => $select_add->_count ? null : 'display:none')));
             // also render add-field selector
             if ($edit_mode)
                 $content .= html::p('addfield', $select_add->show(null, array('style' => $select_add->_count ? null : 'display:none')));
@@ -633,7 +677,8 @@ function rcmail_contact_form($form, $record, $attrib = null)
             $content = $fieldset['content'];
         }
 
             $content = $fieldset['content'];
         }
 
-        $out .= html::tag('fieldset', null, html::tag('legend', null, Q($fieldset['name'])) . $content) ."\n";
+        if ($content)
+            $out .= html::tag('fieldset', null, html::tag('legend', null, Q($fieldset['name'])) . $content) ."\n";
     }
 
     if ($edit_mode) {
     }
 
     if ($edit_mode) {
@@ -660,7 +705,7 @@ function rcmail_contact_photo($attrib)
     $RCMAIL->output->set_env('photo_placeholder', $photo_img);
     unset($attrib['placeholder']);
 
     $RCMAIL->output->set_env('photo_placeholder', $photo_img);
     unset($attrib['placeholder']);
 
-    if (strpos($record['photo'], 'http:') === 0)
+    if (preg_match('!^https?://!i', $record['photo']))
         $photo_img = $record['photo'];
     else if ($record['photo'])
         $photo_img = $RCMAIL->url(array('_action' => 'photo', '_cid' => $record['ID'], '_source' => $SOURCE_ID));
         $photo_img = $record['photo'];
     else if ($record['photo'])
         $photo_img = $RCMAIL->url(array('_action' => 'photo', '_cid' => $record['ID'], '_source' => $SOURCE_ID));
@@ -683,7 +728,7 @@ function rcmail_contact_photo($attrib)
 function rcmail_format_date_col($val)
 {
     global $RCMAIL;
 function rcmail_format_date_col($val)
 {
     global $RCMAIL;
-    return format_date($val, $RCMAIL->config->get('date_format', 'Y-m-d'));
+    return format_date($val, $RCMAIL->config->get('date_format', 'Y-m-d'), false);
 }
 
 
 }
 
 
@@ -713,9 +758,12 @@ function rcmail_get_cids()
     foreach ($cid as $id) {
         // if _source is not specified we'll find it from decoded ID
         if (!$got_source) {
     foreach ($cid as $id) {
         // if _source is not specified we'll find it from decoded ID
         if (!$got_source) {
-            list ($c, $s) = explode('-', $id, 2);
-            if (strlen($s)) {
-                $result[(string)$s][] = $c;
+            if ($sep = strrpos($id, '-')) {
+                $contact_id = substr($id, 0, $sep);
+                $source_id  = substr($id, $sep+1);
+                if (strlen($source_id)) {
+                    $result[(string)$source_id][] = $contact_id;
+                }
             }
         }
         else {
             }
         }
         else {
@@ -745,4 +793,6 @@ $RCMAIL->register_action_map(array(
     'group-delete' => 'groups.inc',
     'group-addmembers' => 'groups.inc',
     'group-delmembers' => 'groups.inc',
     'group-delete' => 'groups.inc',
     'group-addmembers' => 'groups.inc',
     'group-delmembers' => 'groups.inc',
+    'search-create' => 'search.inc',
+    'search-delete' => 'search.inc',
 ));
 ));
index 1b9aea18a15c2689858500a8223a7af7d8e38200..63a6dae30928f48be02c41c7467af8a19e20953c 100644 (file)
@@ -174,9 +174,9 @@ if ($_FILES['_file']['tmp_name'] && is_uploaded_file($_FILES['_file']['tmp_name'
 
       if (!$replace && $email) {
         // compare e-mail address
 
       if (!$replace && $email) {
         // compare e-mail address
-        $existing = $CONTACTS->search('email', $email, false, false);
+        $existing = $CONTACTS->search('email', $email, 1, false);
         if (!$existing->count && $vcard->displayname) {  // compare display name
         if (!$existing->count && $vcard->displayname) {  // compare display name
-          $existing = $CONTACTS->search('name', $vcard->displayname, false, false);
+          $existing = $CONTACTS->search('name', $vcard->displayname, 1, false);
         }
         if ($existing->count) {
           $IMPORT_STATS->skipped++;
         }
         if ($existing->count) {
           $IMPORT_STATS->skipped++;
index ab82faf66e24702938f47860c3007b72841b4793..6b00a824f1efcf688cbfaacd3a025b02d79c9182 100644 (file)
@@ -15,7 +15,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: list.inc 4850 2011-06-14 13:45:26Z alec $
+ $Id: list.inc 5315 2011-10-06 12:31:38Z thomasb $
 
 */
 
 
 */
 
@@ -73,6 +73,11 @@ else {
 
     // get contacts for this user
     $result = $CONTACTS->list_records(array('name'));
 
     // get contacts for this user
     $result = $CONTACTS->list_records(array('name'));
+    
+    if (!$result->count && $result->searchonly) {
+        $OUTPUT->show_message('contactsearchonly', 'notice');
+        $OUTPUT->command('command', 'advanced-search');
+    }
 }
 
 // update message count display
 }
 
 // update message count display
index 5996b9da7645e5d7c1ef55416ca59a9894d543d0..c40ecdf72192a59b2c512725533faceb27bb9dda 100644 (file)
@@ -21,6 +21,7 @@
 
 $cids   = rcmail_get_cids();
 $mailto = array();
 
 $cids   = rcmail_get_cids();
 $mailto = array();
+$recipients = null;
 
 foreach ($cids as $source => $cid)
 {
 
 foreach ($cids as $source => $cid)
 {
@@ -30,12 +31,35 @@ foreach ($cids as $source => $cid)
     {
         $CONTACTS->set_page(1);
         $CONTACTS->set_pagesize(count($cid) + 2); // +2 to skip counting query
     {
         $CONTACTS->set_page(1);
         $CONTACTS->set_pagesize(count($cid) + 2); // +2 to skip counting query
-        $recipients = $CONTACTS->search($CONTACTS->primary_key, $cid, false, true, true, 'email');
+        $recipients = $CONTACTS->search($CONTACTS->primary_key, $cid, 0, true, true, 'email');
+    }
+}
+
+if (!empty($_REQUEST['_gid']) && isset($_REQUEST['_source']))
+{
+    $source = get_input_value('_source', RCUBE_INPUT_GPC);
+    $CONTACTS = $RCMAIL->get_address_book($source);
+    
+    $group_id = get_input_value('_gid', RCUBE_INPUT_GPC);
+    $group_data = $CONTACTS->get_group($group_id);
+    
+    // group has an email address assigned: use that
+    if ($group_data['email']) {
+        $mailto[] = format_email_recipient($group_data['email'][0], $group_data['name']);
+    }
+    else if ($CONTACTS->ready) {
+        $CONTACTS->set_group($group_id);
+        $CONTACTS->set_page(1);
+        $CONTACTS->set_pagesize(200); // limit somehow
+        $recipients = $CONTACTS->list_records();
+    }
+}
 
 
-        while (is_object($recipients) && ($rec = $recipients->iterate())) {
-            $emails = $CONTACTS->get_col_values('email', $rec, true);
-            $mailto[] = format_email_recipient($emails[0], $rec['name']);
-        }
+if ($recipients)
+{
+    while (is_object($recipients) && ($rec = $recipients->iterate())) {
+        $emails = $CONTACTS->get_col_values('email', $rec, true);
+        $mailto[] = format_email_recipient($emails[0], $rec['name']);
     }
 }
 
     }
 }
 
index ef4387afd282684984ceb7d64b335f349a7a037a..d573b0ea484b8617e5914d8dda27d055a3b47f3a 100644 (file)
@@ -15,7 +15,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: save.inc 5130 2011-08-25 08:30:01Z alec $
+ $Id: save.inc 5541 2011-12-04 17:05:42Z thomasb $
 
 */
 
 
 */
 
@@ -50,10 +50,12 @@ foreach ($GLOBALS['CONTACT_COLTYPES'] as $col => $colprop) {
       foreach ((array)$vals as $i => $val)
         $values[$i][$childcol] = $val;
     }
       foreach ((array)$vals as $i => $val)
         $values[$i][$childcol] = $val;
     }
-    $subtypes = get_input_value('_subtype_' . $col, RCUBE_INPUT_POST);
-    foreach ($subtypes as $i => $subtype)
+    $subtypes = isset($_REQUEST['_subtype_' . $col]) ? (array)get_input_value('_subtype_' . $col, RCUBE_INPUT_POST) : array('');
+    foreach ($subtypes as $i => $subtype) {
+      $suffix = $subtype ? ':'.$subtype : '';
       if ($values[$i])
       if ($values[$i])
-        $a_record[$col.':'.$subtype][] = $values[$i];
+        $a_record[$col.$suffix][] = $values[$i];
+     }
   }
   // assign values and subtypes
   else if (is_array($_POST[$fname])) {
   }
   // assign values and subtypes
   else if (is_array($_POST[$fname])) {
@@ -162,7 +164,7 @@ else {
   // show notice if existing contacts with same e-mail are found
   $existing = false;
   foreach ($CONTACTS->get_col_values('email', $a_record, true) as $email) {
   // show notice if existing contacts with same e-mail are found
   $existing = false;
   foreach ($CONTACTS->get_col_values('email', $a_record, true) as $email) {
-      if ($email && ($res = $CONTACTS->search('email', $email, false, false, true)) && $res->count) {
+      if ($email && ($res = $CONTACTS->search('email', $email, 1, false, true)) && $res->count) {
           $OUTPUT->show_message('contactexists', 'notice', null, false);
           break;
       }
           $OUTPUT->show_message('contactexists', 'notice', null, false);
           break;
       }
index 352556de0e4d9ee5c8dea96a9555a5a6e33b6950..643cc60a834b022fa5f2ed2e0dd9591845cf0977 100644 (file)
 
 */
 
 
 */
 
+if ($RCMAIL->action == 'search-create') {
+    $id   = get_input_value('_search', RCUBE_INPUT_POST);
+    $name = get_input_value('_name', RCUBE_INPUT_POST, true);
+
+    if (($params = $_SESSION['search_params']) && $params['id'] == $id) {
+
+        $data = array(
+            'type' => rcube_user::SEARCH_ADDRESSBOOK,
+            'name' => $name,
+            'data' => array(
+                'fields' => $params['data'][0],
+                'search' => $params['data'][1],
+            ),
+        );
+
+        $plugin = $RCMAIL->plugins->exec_hook('saved_search_create', array('data' => $data));
+
+        if (!$plugin['abort'])
+            $result = $RCMAIL->user->insert_search($plugin['data']);
+        else
+            $result = $plugin['result'];
+    }
+
+    if ($result) {
+        $OUTPUT->show_message('savedsearchcreated', 'confirmation');
+        $OUTPUT->command('insert_saved_search', Q($name), Q($result));
+    }
+    else
+        $OUTPUT->show_message($plugin['message'] ? $plugin['message'] : 'savedsearchcreateerror', 'error');
+
+    $OUTPUT->send();
+}
+
+if ($RCMAIL->action == 'search-delete') {
+    $id = get_input_value('_sid', RCUBE_INPUT_POST);
+
+    $plugin = $RCMAIL->plugins->exec_hook('saved_search_delete', array('id' => $id));
+
+    if (!$plugin['abort'])
+        $result = $RCMAIL->user->delete_search($id);
+    else
+        $result = $plugin['result'];
+
+    if ($result) {
+        $OUTPUT->show_message('savedsearchdeleted', 'confirmation');
+        $OUTPUT->command('remove_search_item', Q($id));
+        // contact list will be cleared, clear also page counter
+        $OUTPUT->command('set_rowcount', rcube_label('nocontactsfound'));
+        $OUTPUT->set_env('pagecount', 0);
+    }
+    else
+        $OUTPUT->show_message($plugin['message'] ? $plugin['message'] : 'savedsearchdeleteerror', 'error');
+
+    $OUTPUT->send();
+}
+
+
 if (!isset($_GET['_form'])) {
     rcmail_contact_search();
 }
 if (!isset($_GET['_form'])) {
     rcmail_contact_search();
 }
@@ -34,9 +91,15 @@ function rcmail_contact_search()
     global $RCMAIL, $OUTPUT, $CONFIG, $SEARCH_MODS_DEFAULT;
 
     $adv = isset($_POST['_adv']);
     global $RCMAIL, $OUTPUT, $CONFIG, $SEARCH_MODS_DEFAULT;
 
     $adv = isset($_POST['_adv']);
+    $sid = get_input_value('_sid', RCUBE_INPUT_GET);
 
 
+    // get search criteria from saved search
+    if ($sid && ($search = $RCMAIL->user->get_search($sid))) {
+        $fields = $search['data']['fields'];
+        $search = $search['data']['search'];
+    }
     // get fields/values from advanced search form
     // get fields/values from advanced search form
-    if ($adv) {
+    else if ($adv) {
         foreach (array_keys($_POST) as $key) {
             $s = trim(get_input_value($key, RCUBE_INPUT_POST, true));
             if (strlen($s) && preg_match('/^_search_([a-zA-Z0-9_-]+)$/', $key, $m)) {
         foreach (array_keys($_POST) as $key) {
             $s = trim(get_input_value($key, RCUBE_INPUT_POST, true));
             if (strlen($s) && preg_match('/^_search_([a-zA-Z0-9_-]+)$/', $key, $m)) {
@@ -74,6 +137,9 @@ function rcmail_contact_search()
         }
     }
 
         }
     }
 
+    // Values matching mode
+    $mode = (int) $RCMAIL->config->get('addressbook_search_mode');
+
     // get sources list
     $sources    = $RCMAIL->get_address_sources();
     $search_set = array();
     // get sources list
     $sources    = $RCMAIL->get_address_sources();
     $search_set = array();
@@ -105,7 +171,7 @@ function rcmail_contact_search()
         $source->set_pagesize(9999);
 
         // get contacts count
         $source->set_pagesize(9999);
 
         // get contacts count
-        $result = $source->search($fields, $search, false, false);
+        $result = $source->search($fields, $search, $mode, false);
 
         if (!$result->count) {
             continue;
 
         if (!$result->count) {
             continue;
@@ -145,6 +211,7 @@ function rcmail_contact_search()
 
     // save search settings in session
     $_SESSION['search'][$search_request] = $search_set;
 
     // save search settings in session
     $_SESSION['search'][$search_request] = $search_set;
+    $_SESSION['search_params'] = array('id' => $search_request, 'data' => array($fields, $search));
     $_SESSION['page'] = 1;
 
     if ($adv)
     $_SESSION['page'] = 1;
 
     if ($adv)
@@ -153,6 +220,7 @@ function rcmail_contact_search()
     if ($result->count > 0) {
         // create javascript list
         rcmail_js_contacts_list($result);
     if ($result->count > 0) {
         // create javascript list
         rcmail_js_contacts_list($result);
+        $OUTPUT->show_message('contactsearchsuccessful', 'confirmation', array('nr' => $result->count));
     }
     else {
         $OUTPUT->show_message('nocontactsfound', 'notice');
     }
     else {
         $OUTPUT->show_message('nocontactsfound', 'notice');
@@ -162,9 +230,14 @@ function rcmail_contact_search()
     $OUTPUT->command('set_env', 'search_request', $search_request);
     $OUTPUT->command('set_env', 'pagecount', ceil($result->count / $CONFIG['pagesize']));
     $OUTPUT->command('set_rowcount', rcmail_get_rowcount_text($result));
     $OUTPUT->command('set_env', 'search_request', $search_request);
     $OUTPUT->command('set_env', 'pagecount', ceil($result->count / $CONFIG['pagesize']));
     $OUTPUT->command('set_rowcount', rcmail_get_rowcount_text($result));
+    // Re-set current source
+    $OUTPUT->command('set_env', 'search_id', $sid);
+    $OUTPUT->command('set_env', 'source', '');
+    $OUTPUT->command('set_env', 'group', '');
 
     // unselect currently selected directory/group
 
     // unselect currently selected directory/group
-    $OUTPUT->command('unselect_directory');
+    if (!$sid)
+        $OUTPUT->command('unselect_directory');
     $OUTPUT->command('update_group_commands');
 
     // send response
     $OUTPUT->command('update_group_commands');
 
     // send response
index bd9b8399328c7a8bb7f64849771410373a6d9944..6aeaea6c86ad2b6404ae8f85d204d19ad47bf7d1 100644 (file)
@@ -15,7 +15,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: upload_photo.inc 5130 2011-08-25 08:30:01Z alec $
+ $Id: upload_photo.inc 5110 2011-08-22 14:33:02Z alec $
 
 */
 
 
 */
 
index 4df3a78979cce41c873a045274d686753d8572f5..5b77b56e81ec68cea6c693cb20aaa751c91fb8e6 100644 (file)
@@ -15,7 +15,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: addcontact.inc 4933 2011-07-18 16:57:15Z thomasb $
+ $Id: addcontact.inc 5415 2011-11-11 15:04:45Z alec $
 
 */
 
 
 */
 
@@ -50,7 +50,7 @@ if (!empty($_POST['_address']) && is_object($CONTACTS))
       $OUTPUT->show_message('errorsavingcontact', 'error');
       $OUTPUT->send();
     }
       $OUTPUT->show_message('errorsavingcontact', 'error');
       $OUTPUT->send();
     }
-    
+
     $email = rcube_idn_to_ascii($contact['email']);
     if (!check_email($email, false)) {
       $OUTPUT->show_message('emailformaterror', 'error', array('email' => $contact['email']));
     $email = rcube_idn_to_ascii($contact['email']);
     if (!check_email($email, false)) {
       $OUTPUT->show_message('emailformaterror', 'error', array('email' => $contact['email']));
@@ -60,8 +60,18 @@ if (!empty($_POST['_address']) && is_object($CONTACTS))
     $contact['email'] = rcube_idn_to_utf8($contact['email']);
     $contact['name'] = rcube_addressbook::compose_display_name($contact);
 
     $contact['email'] = rcube_idn_to_utf8($contact['email']);
     $contact['name'] = rcube_addressbook::compose_display_name($contact);
 
+    // validate contact record
+    if (!$CONTACTS->validate($contact, true)) {
+      $error = $CONTACTS->get_error();
+      // TODO: show dialog to complete record
+      // if ($error['type'] == rcube_addressbook::ERROR_VALIDATE) { }
+
+      $OUTPUT->show_message($error['message'] ? $error['message'] : 'errorsavingcontact', 'error');
+      $OUTPUT->send();
+    }
+
     // check for existing contacts
     // check for existing contacts
-    $existing = $CONTACTS->search('email', $contact['email'], true, false);
+    $existing = $CONTACTS->search('email', $contact['email'], 1, false);
 
     if ($done = $existing->count)
       $OUTPUT->show_message('contactexists', 'warning');
 
     if ($done = $existing->count)
       $OUTPUT->show_message('contactexists', 'warning');
index a5bc21f3c8b751e429dc40d2ecfacb1a015e65b6..3a85fa5a02acd32b26e8470054e5ce8b1b0e7268 100644 (file)
@@ -15,7 +15,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: attachments.inc 5229 2011-09-16 19:13:27Z thomasb $
+ $Id: attachments.inc 5543 2011-12-05 07:24:36Z alec $
 
 */
 
 
 */
 
@@ -25,9 +25,12 @@ if (!empty($_GET['_progress'])) {
 }
 
 $COMPOSE_ID = get_input_value('_id', RCUBE_INPUT_GPC);
 }
 
 $COMPOSE_ID = get_input_value('_id', RCUBE_INPUT_GPC);
-$_SESSION['compose'] = $_SESSION['compose_data_'.$COMPOSE_ID];
+$COMPOSE    = null;
 
 
-if (!$_SESSION['compose']) {
+if ($COMPOSE_ID && $_SESSION['compose_data_'.$COMPOSE_ID])
+  $COMPOSE =& $_SESSION['compose_data_'.$COMPOSE_ID];
+
+if (!$COMPOSE) {
   die("Invalid session var!");
 }
 
   die("Invalid session var!");
 }
 
@@ -38,15 +41,15 @@ if ($RCMAIL->action=='remove-attachment')
   $id = 'undefined';
   if (preg_match('/^rcmfile(\w+)$/', $_POST['_file'], $regs))
     $id = $regs[1];
   $id = 'undefined';
   if (preg_match('/^rcmfile(\w+)$/', $_POST['_file'], $regs))
     $id = $regs[1];
-  if ($attachment = $_SESSION['compose']['attachments'][$id])
+  if ($attachment = $COMPOSE['attachments'][$id])
     $attachment = $RCMAIL->plugins->exec_hook('attachment_delete', $attachment);
   if ($attachment['status']) {
     $attachment = $RCMAIL->plugins->exec_hook('attachment_delete', $attachment);
   if ($attachment['status']) {
-    if (is_array($_SESSION['compose']['attachments'][$id])) {
-      unset($_SESSION['compose']['attachments'][$id]);
+    if (is_array($COMPOSE['attachments'][$id])) {
+      unset($COMPOSE['attachments'][$id]);
       $OUTPUT->command('remove_from_attachment_list', "rcmfile$id");
     }
   }
       $OUTPUT->command('remove_from_attachment_list', "rcmfile$id");
     }
   }
-  
+
   $OUTPUT->send();
   exit;
 }
   $OUTPUT->send();
   exit;
 }
@@ -56,16 +59,16 @@ if ($RCMAIL->action=='display-attachment')
   $id = 'undefined';
   if (preg_match('/^rcmfile(\w+)$/', $_GET['_file'], $regs))
     $id = $regs[1];
   $id = 'undefined';
   if (preg_match('/^rcmfile(\w+)$/', $_GET['_file'], $regs))
     $id = $regs[1];
-  if ($attachment = $_SESSION['compose']['attachments'][$id])
+  if ($attachment = $COMPOSE['attachments'][$id])
     $attachment = $RCMAIL->plugins->exec_hook('attachment_display', $attachment);
     $attachment = $RCMAIL->plugins->exec_hook('attachment_display', $attachment);
-    
+
   if ($attachment['status']) {
     if (empty($attachment['size']))
       $attachment['size'] = $attachment['data'] ? strlen($attachment['data']) : @filesize($attachment['path']);
 
     header('Content-Type: ' . $attachment['mimetype']);
     header('Content-Length: ' . $attachment['size']);
   if ($attachment['status']) {
     if (empty($attachment['size']))
       $attachment['size'] = $attachment['data'] ? strlen($attachment['data']) : @filesize($attachment['path']);
 
     header('Content-Type: ' . $attachment['mimetype']);
     header('Content-Length: ' . $attachment['size']);
-    
+
     if ($attachment['data'])
       echo $attachment['data'];
     else if ($attachment['path'])
     if ($attachment['data'])
       echo $attachment['data'];
     else if ($attachment['path'])
@@ -76,8 +79,8 @@ if ($RCMAIL->action=='display-attachment')
 
 // attachment upload action
 
 
 // attachment upload action
 
-if (!is_array($_SESSION['compose']['attachments'])) {
-  $_SESSION['compose']['attachments'] = array();
+if (!is_array($COMPOSE['attachments'])) {
+  $COMPOSE['attachments'] = array();
 }
 
 // clear all stored output properties (like scripts and env vars)
 }
 
 // clear all stored output properties (like scripts and env vars)
@@ -107,9 +110,9 @@ if (is_array($_FILES['_attachments']['tmp_name'])) {
 
       // store new attachment in session
       unset($attachment['status'], $attachment['abort']);
 
       // store new attachment in session
       unset($attachment['status'], $attachment['abort']);
-      $_SESSION['compose']['attachments'][$id] = $attachment;
+      $COMPOSE['attachments'][$id] = $attachment;
 
 
-      if (($icon = $_SESSION['compose']['deleteicon']) && is_file($icon)) {
+      if (($icon = $COMPOSE['deleteicon']) && is_file($icon)) {
         $button = html::img(array(
           'src' => $icon,
           'alt' => rcube_label('delete')
         $button = html::img(array(
           'src' => $icon,
           'alt' => rcube_label('delete')
index d92f10858172011b12d1847a926a2b476cbe7611..7769ec87db2ce8d349fdbbfec2c9de03083e611c 100644 (file)
@@ -5,7 +5,8 @@
  | program/steps/mail/autocomplete.inc                                   |
  |                                                                       |
  | This file is part of the Roundcube Webmail client                     |
  | program/steps/mail/autocomplete.inc                                   |
  |                                                                       |
  | This file is part of the Roundcube Webmail client                     |
- | Copyright (C) 2008-2010, Roundcube Dev Team                           |
+ | Copyright (C) 2008-2011, Roundcube Dev Team                           |
+ | Copyright (C) 2011, Kolab Systems AG                                  |
  | Licensed under the GNU GPL                                            |
  |                                                                       |
  | PURPOSE:                                                              |
  | Licensed under the GNU GPL                                            |
  |                                                                       |
  | PURPOSE:                                                              |
@@ -15,7 +16,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: autocomplete.inc 4963 2011-07-25 10:49:39Z alec $
+ $Id: autocomplete.inc 5426 2011-11-15 10:50:30Z alec $
 
 */
 
 
 */
 
@@ -31,14 +32,17 @@ if ($RCMAIL->action == 'group-expand') {
         $members[] = format_email_recipient($email, $sql_arr['name']);
     }
 
         $members[] = format_email_recipient($email, $sql_arr['name']);
     }
 
-    $OUTPUT->command('replace_group_recipients', $gid, join(', ', $members));
+    $separator = trim($RCMAIL->config->get('recipients_separator', ',')) . ' ';
+    $OUTPUT->command('replace_group_recipients', $gid, join($separator, array_unique($members)));
   }
 
   $OUTPUT->send();
 }
 
 
   }
 
   $OUTPUT->send();
 }
 
 
-$MAXNUM = (int)$RCMAIL->config->get('autocomplete_max', 15);
+$MAXNUM = (int) $RCMAIL->config->get('autocomplete_max', 15);
+$mode   = (int) $RCMAIL->config->get('addressbook_search_mode');
+$single = (bool) $RCMAIL->config->get('autocomplete_single');
 $search = get_input_value('_search', RCUBE_INPUT_GPC, true);
 $source = get_input_value('_source', RCUBE_INPUT_GPC);
 $sid    = get_input_value('_id', RCUBE_INPUT_GPC);
 $search = get_input_value('_search', RCUBE_INPUT_GPC, true);
 $source = get_input_value('_source', RCUBE_INPUT_GPC);
 $sid    = get_input_value('_id', RCUBE_INPUT_GPC);
@@ -49,45 +53,73 @@ else
   $book_types = (array) $RCMAIL->config->get('autocomplete_addressbooks', 'sql');
 
 if (!empty($book_types) && strlen($search)) {
   $book_types = (array) $RCMAIL->config->get('autocomplete_addressbooks', 'sql');
 
 if (!empty($book_types) && strlen($search)) {
-  $contacts = array();
+  $contacts  = array();
+  $sort_keys = array();
   $books_num = count($book_types);
   $books_num = count($book_types);
+  $search_lc = mb_strtolower($search);
 
   foreach ($book_types as $id) {
     $abook = $RCMAIL->get_address_book($id);
     $abook->set_pagesize($MAXNUM);
 
 
   foreach ($book_types as $id) {
     $abook = $RCMAIL->get_address_book($id);
     $abook->set_pagesize($MAXNUM);
 
-    if ($result = $abook->search(array('email','name'), $search, false, true, true, 'email')) {
+    if ($result = $abook->search(array('email','name'), $search, $mode, true, true, 'email')) {
       while ($sql_arr = $result->iterate()) {
         // Contact can have more than one e-mail address
         $email_arr = (array)$abook->get_col_values('email', $sql_arr, true);
         $email_cnt = count($email_arr);
       while ($sql_arr = $result->iterate()) {
         // Contact can have more than one e-mail address
         $email_arr = (array)$abook->get_col_values('email', $sql_arr, true);
         $email_cnt = count($email_arr);
+        $idx = 0;
         foreach ($email_arr as $email) {
         foreach ($email_arr as $email) {
-          if (empty($email))
+          if (empty($email)) {
             continue;
             continue;
+          }
+
           $contact = format_email_recipient($email, $sql_arr['name']);
           $contact = format_email_recipient($email, $sql_arr['name']);
+
           // skip entries that don't match
           // skip entries that don't match
-          if ($email_cnt > 1 && stripos($contact, $search) === false) {
+          if ($email_cnt > 1 && strpos(mb_strtolower($contact), $search_lc) === false) {
             continue;
           }
             continue;
           }
-          // when we've got more than one book, we need to skip duplicates
-          if ($books_num == 1 || !in_array($contact, $contacts)) {
-            $contacts[] = $contact;
+
+          // skip duplicates
+          if (!in_array($contact, $contacts)) {
+            $contacts[]  = $contact;
+            $sort_keys[] = sprintf('%s %03d', $sql_arr['name'] , $idx++);
+
             if (count($contacts) >= $MAXNUM)
               break 2;
           }
             if (count($contacts) >= $MAXNUM)
               break 2;
           }
+
+          // skip redundant entries (show only first email address)
+          if ($single) {
+            break;
+          }
         }
       }
     }
 
     // also list matching contact groups
         }
       }
     }
 
     // also list matching contact groups
-    if ($abook->groups) {
+    if ($abook->groups && count($contacts) < $MAXNUM) {
       foreach ($abook->list_groups($search) as $group) {
         $abook->reset();
         $abook->set_group($group['ID']);
       foreach ($abook->list_groups($search) as $group) {
         $abook->reset();
         $abook->set_group($group['ID']);
-        $result = $abook->count();
+        $group_prop = $abook->get_group($group['ID']);
+
+        // group (distribution list) with email address(es)
+        if ($group_prop['email']) {
+            $idx = 0;
+            foreach ((array)$group_prop['email'] as $email) {
+                $contacts[]  = format_email_recipient($email, $group['name']);
+                $sort_keys[] = sprintf('%s %03d', $group['name'] , $idx++);
+
+                if (count($contacts) >= $MAXNUM)
+                  break 2;
+            }
+        }
+        // show group with count
+        else if (($result = $abook->count()) && $result->count) {
+          $contacts[]  = array('name' => $group['name'] . ' (' . intval($result->count) . ')', 'id' => $group['ID'], 'source' => $id);
+          $sort_keys[] = $group['name'];
 
 
-        if ($result->count) {
-          $contacts[] = array('name' => $group['name'] . ' (' . intval($result->count) . ')', 'id' => $group['ID'], 'source' => $id);
           if (count($contacts) >= $MAXNUM)
             break;
         }
           if (count($contacts) >= $MAXNUM)
             break;
         }
@@ -95,17 +127,16 @@ if (!empty($book_types) && strlen($search)) {
     }
   }
 
     }
   }
 
-  usort($contacts, 'contact_results_sort');
+  if (count($contacts)) {
+    // sort contacts index
+    asort($sort_keys, SORT_LOCALE_STRING);
+    // re-sort contacts according to index
+    foreach ($sort_keys as $idx => $val) {
+      $sort_keys[$idx] = $contacts[$idx];
+    }
+    $contacts = array_values($sort_keys);
+  }
 }
 
 $OUTPUT->command('ksearch_query_results', $contacts, $search, $sid);
 $OUTPUT->send();
 }
 
 $OUTPUT->command('ksearch_query_results', $contacts, $search, $sid);
 $OUTPUT->send();
-
-
-function contact_results_sort($a, $b)
-{
-  $name_a = is_array($a) ? $a['name'] : $a;
-  $name_b = is_array($b) ? $b['name'] : $b;
-  return strcoll(trim($name_a, '" '), trim($name_b, '" '));
-}
-
index f3c9be0805d3f1c6a4babda60ed57ea8b6f4be0e..3b6b4ecad17ef79877a345b94f717a6b625a2f36 100644 (file)
@@ -15,7 +15,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: check_recent.inc 4872 2011-06-22 05:52:48Z thomasb $
+ $Id: check_recent.inc 5266 2011-09-22 07:49:33Z alec $
 
 */
 
 
 */
 
@@ -34,10 +34,24 @@ else {
 
 // check recent/unseen counts
 foreach ($a_mailboxes as $mbox_name) {
 
 // check recent/unseen counts
 foreach ($a_mailboxes as $mbox_name) {
-    if ($mbox_name == $current && ($status = $IMAP->mailbox_status($mbox_name))) {
+    $is_current = $mbox_name == $current;
+    if ($is_current) {
+        // Synchronize mailbox cache, handle flag changes
+        $IMAP->mailbox_sync($mbox_name);
+    }
+
+    // Get mailbox status
+    $status = $IMAP->mailbox_status($mbox_name);
+
+    if ($status & 1) {
+        // trigger plugin hook
+        $RCMAIL->plugins->exec_hook('new_messages',
+            array('mailbox' => $mbox_name, 'is_current' => $is_current));
+    }
 
 
-        rcmail_send_unread_count($mbox_name, true);
+    rcmail_send_unread_count($mbox_name, true);
 
 
+    if ($status && $is_current) {
         // refresh saved search set
         $search_request = get_input_value('_search', RCUBE_INPUT_GPC);
         if ($search_request && isset($_SESSION['search'])
         // refresh saved search set
         $search_request = get_input_value('_search', RCUBE_INPUT_GPC);
         if ($search_request && isset($_SESSION['search'])
@@ -67,14 +81,9 @@ foreach ($a_mailboxes as $mbox_name) {
 
         $OUTPUT->set_env('messagecount', $all_count);
         $OUTPUT->set_env('pagecount', ceil($all_count/$IMAP->page_size));
 
         $OUTPUT->set_env('messagecount', $all_count);
         $OUTPUT->set_env('pagecount', ceil($all_count/$IMAP->page_size));
-        $OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($all_count));
+        $OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($all_count), $mbox_name);
         $OUTPUT->set_env('current_page', $all_count ? $IMAP->list_page : 1);
 
         $OUTPUT->set_env('current_page', $all_count ? $IMAP->list_page : 1);
 
-        if ($status & 1) {
-            // trigger plugin hook
-            $RCMAIL->plugins->exec_hook('new_messages', array('mailbox' => $mbox_name));
-        }
-
         // remove old rows (and clear selection if new list is empty)
         $OUTPUT->command('message_list.clear', $all_count ? false : true);
 
         // remove old rows (and clear selection if new list is empty)
         $OUTPUT->command('message_list.clear', $all_count ? false : true);
 
@@ -86,9 +95,6 @@ foreach ($a_mailboxes as $mbox_name) {
             $OUTPUT->command('update_selection');
         }
     }
             $OUTPUT->command('update_selection');
         }
     }
-    else {
-        rcmail_send_unread_count($mbox_name, true);
-    }
 }
 
 $RCMAIL->plugins->exec_hook('keep_alive', array());
 }
 
 $RCMAIL->plugins->exec_hook('keep_alive', array());
index 8c60a7ea24822fb3c77e9f61ef5fec10004b5683..ca10898015720cc2e57be4c90e210a8fdf441294 100644 (file)
@@ -5,7 +5,7 @@
  | program/steps/mail/compose.inc                                        |
  |                                                                       |
  | This file is part of the Roundcube Webmail client                     |
  | program/steps/mail/compose.inc                                        |
  |                                                                       |
  | This file is part of the Roundcube Webmail client                     |
- | Copyright (C) 2005-2009, The Roundcube Dev Team                       |
+ | Copyright (C) 2005-2011, The Roundcube Dev Team                       |
  | Licensed under the GNU GPL                                            |
  |                                                                       |
  | PURPOSE:                                                              |
  | Licensed under the GNU GPL                                            |
  |                                                                       |
  | PURPOSE:                                                              |
@@ -15,7 +15,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: compose.inc 5281 2011-09-27 07:29:49Z alec $
+ $Id: compose.inc 5545 2011-12-05 12:59:21Z thomasb $
 
 */
 
 
 */
 
@@ -25,15 +25,26 @@ define('RCUBE_COMPOSE_FORWARD', 0x0107);
 define('RCUBE_COMPOSE_DRAFT', 0x0108);
 define('RCUBE_COMPOSE_EDIT', 0x0109);
 
 define('RCUBE_COMPOSE_DRAFT', 0x0108);
 define('RCUBE_COMPOSE_EDIT', 0x0109);
 
-$MESSAGE_FORM = NULL;
-$MESSAGE = NULL;
-
-$COMPOSE_ID = get_input_value('_id', RCUBE_INPUT_GET);
-$_SESSION['compose'] = $_SESSION['compose_data_'.$COMPOSE_ID];
+$MESSAGE_FORM = null;
+$MESSAGE      = null;
+$COMPOSE_ID   = get_input_value('_id', RCUBE_INPUT_GET);
+$COMPOSE      = null;
+
+if ($COMPOSE_ID && $_SESSION['compose_data_'.$COMPOSE_ID])
+  $COMPOSE =& $_SESSION['compose_data_'.$COMPOSE_ID];
+
+// give replicated session storage some time to synchronize
+$retries = 0;
+while ($COMPOSE_ID && !is_array($COMPOSE) && $RCMAIL->db->is_replicated() && $retries++ < 5) {
+  usleep(500000);
+  $RCMAIL->session->reload();
+  if ($_SESSION['compose_data_'.$COMPOSE_ID])
+    $COMPOSE =& $_SESSION['compose_data_'.$COMPOSE_ID];
+}
 
 // Nothing below is called during message composition, only at "new/forward/reply/draft" initialization or
 // if a compose-ID is given (i.e. when the compose step is opened in a new window/tab).
 
 // Nothing below is called during message composition, only at "new/forward/reply/draft" initialization or
 // if a compose-ID is given (i.e. when the compose step is opened in a new window/tab).
-if (!is_array($_SESSION['compose']))
+if (!is_array($COMPOSE))
 {
   // Infinite redirect prevention in case of broken session (#1487028)
   if ($COMPOSE_ID)
 {
   // Infinite redirect prevention in case of broken session (#1487028)
   if ($COMPOSE_ID)
@@ -41,31 +52,33 @@ if (!is_array($_SESSION['compose']))
       'file' => __FILE__, 'line' => __LINE__,
       'message' => "Invalid compose ID"), true, true);
 
       'file' => __FILE__, 'line' => __LINE__,
       'message' => "Invalid compose ID"), true, true);
 
-  $_SESSION['compose'] = array(
-    'id' => uniqid(mt_rand()),
-    'param' => request2param(RCUBE_INPUT_GET),
+  $COMPOSE_ID = uniqid(mt_rand());
+  $_SESSION['compose_data_'.$COMPOSE_ID] = array(
+    'id'      => $COMPOSE_ID,
+    'param'   => request2param(RCUBE_INPUT_GET),
     'mailbox' => $IMAP->get_mailbox_name(),
   );
     'mailbox' => $IMAP->get_mailbox_name(),
   );
+  $COMPOSE =& $_SESSION['compose_data_'.$COMPOSE_ID];
 
   // process values like "mailto:foo@bar.com?subject=new+message&cc=another"
 
   // process values like "mailto:foo@bar.com?subject=new+message&cc=another"
-  if ($_SESSION['compose']['param']['to']) {
+  if ($COMPOSE['param']['to']) {
     // #1486037: remove "mailto:" prefix
     // #1486037: remove "mailto:" prefix
-    $_SESSION['compose']['param']['to'] = preg_replace('/^mailto:/i', '', $_SESSION['compose']['param']['to']);
-    $mailto = explode('?', $_SESSION['compose']['param']['to']);
+    $COMPOSE['param']['to'] = preg_replace('/^mailto:/i', '', $COMPOSE['param']['to']);
+    $mailto = explode('?', $COMPOSE['param']['to']);
     if (count($mailto) > 1) {
     if (count($mailto) > 1) {
-      $_SESSION['compose']['param']['to'] = $mailto[0];
+      $COMPOSE['param']['to'] = $mailto[0];
       parse_str($mailto[1], $query);
       foreach ($query as $f => $val)
       parse_str($mailto[1], $query);
       foreach ($query as $f => $val)
-        $_SESSION['compose']['param'][$f] = $val;
+        $COMPOSE['param'][$f] = $val;
     }
   }
 
   // select folder where to save the sent message
     }
   }
 
   // select folder where to save the sent message
-  $_SESSION['compose']['param']['sent_mbox'] = $RCMAIL->config->get('sent_mbox');
+  $COMPOSE['param']['sent_mbox'] = $RCMAIL->config->get('sent_mbox');
 
   // pipe compose parameters thru plugins
 
   // pipe compose parameters thru plugins
-  $plugin = $RCMAIL->plugins->exec_hook('message_compose', $_SESSION['compose']);
-  $_SESSION['compose']['param'] = array_merge($_SESSION['compose']['param'], $plugin['param']);
+  $plugin = $RCMAIL->plugins->exec_hook('message_compose', $COMPOSE);
+  $COMPOSE['param'] = array_merge($COMPOSE['param'], $plugin['param']);
 
   // add attachments listed by message_compose hook
   if (is_array($plugin['attachments'])) {
 
   // add attachments listed by message_compose hook
   if (is_array($plugin['attachments'])) {
@@ -92,18 +105,18 @@ if (!is_array($_SESSION['compose']))
 
       if ($attachment['status'] && !$attachment['abort']) {
         unset($attachment['data'], $attachment['status'], $attachment['abort']);
 
       if ($attachment['status'] && !$attachment['abort']) {
         unset($attachment['data'], $attachment['status'], $attachment['abort']);
-        $_SESSION['compose']['attachments'][$attachment['id']] = $attachment;
+        $COMPOSE['attachments'][$attachment['id']] = $attachment;
       }
     }
   }
 
   // check if folder for saving sent messages exists and is subscribed (#1486802)
       }
     }
   }
 
   // check if folder for saving sent messages exists and is subscribed (#1486802)
-  if ($sent_folder = $_SESSION['compose']['param']['sent_mbox']) {
+  if ($sent_folder = $COMPOSE['param']['sent_mbox']) {
     rcmail_check_sent_folder($sent_folder, true);
   }
 
   // redirect to a unique URL with all parameters stored in session
     rcmail_check_sent_folder($sent_folder, true);
   }
 
   // redirect to a unique URL with all parameters stored in session
-  $OUTPUT->redirect(array('_action' => 'compose', '_id' => $_SESSION['compose']['id']));
+  $OUTPUT->redirect(array('_action' => 'compose', '_id' => $COMPOSE['id']));
 }
 
 
 }
 
 
@@ -111,9 +124,9 @@ if (!is_array($_SESSION['compose']))
 $OUTPUT->add_label('nosubject', 'nosenderwarning', 'norecipientwarning', 'nosubjectwarning', 'cancel',
     'nobodywarning', 'notsentwarning', 'notuploadedwarning', 'savingmessage', 'sendingmessage', 
     'messagesaved', 'converting', 'editorwarning', 'searching', 'uploading', 'uploadingmany',
 $OUTPUT->add_label('nosubject', 'nosenderwarning', 'norecipientwarning', 'nosubjectwarning', 'cancel',
     'nobodywarning', 'notsentwarning', 'notuploadedwarning', 'savingmessage', 'sendingmessage', 
     'messagesaved', 'converting', 'editorwarning', 'searching', 'uploading', 'uploadingmany',
-    'fileuploaderror');
+    'fileuploaderror', 'sendmessage');
 
 
-$OUTPUT->set_env('compose_id', $COMPOSE_ID);
+$OUTPUT->set_env('compose_id', $COMPOSE['id']);
 
 // add config parameters to client script
 if (!empty($CONFIG['drafts_mbox'])) {
 
 // add config parameters to client script
 if (!empty($CONFIG['drafts_mbox'])) {
@@ -122,19 +135,23 @@ if (!empty($CONFIG['drafts_mbox'])) {
 }
 // set current mailbox in client environment
 $OUTPUT->set_env('mailbox', $IMAP->get_mailbox_name());
 }
 // set current mailbox in client environment
 $OUTPUT->set_env('mailbox', $IMAP->get_mailbox_name());
-$OUTPUT->set_env('sig_above', $CONFIG['sig_above']);
-$OUTPUT->set_env('top_posting', $CONFIG['top_posting']);
+$OUTPUT->set_env('sig_above', $RCMAIL->config->get('sig_above', false));
+$OUTPUT->set_env('top_posting', $RCMAIL->config->get('top_posting', false));
+$OUTPUT->set_env('recipients_separator', trim($RCMAIL->config->get('recipients_separator', ',')));
+
+// use jquery UI for showing prompt() dialogs
+$RCMAIL->plugins->load_plugin('jqueryui');
 
 // get reference message and set compose mode
 
 // get reference message and set compose mode
-if ($msg_uid = $_SESSION['compose']['param']['draft_uid']) {
+if ($msg_uid = $COMPOSE['param']['draft_uid']) {
   $RCMAIL->imap->set_mailbox($CONFIG['drafts_mbox']);
   $compose_mode = RCUBE_COMPOSE_DRAFT;
 }
   $RCMAIL->imap->set_mailbox($CONFIG['drafts_mbox']);
   $compose_mode = RCUBE_COMPOSE_DRAFT;
 }
-else if ($msg_uid = $_SESSION['compose']['param']['reply_uid'])
+else if ($msg_uid = $COMPOSE['param']['reply_uid'])
   $compose_mode = RCUBE_COMPOSE_REPLY;
   $compose_mode = RCUBE_COMPOSE_REPLY;
-else if ($msg_uid = $_SESSION['compose']['param']['forward_uid'])
+else if ($msg_uid = $COMPOSE['param']['forward_uid'])
   $compose_mode = RCUBE_COMPOSE_FORWARD;
   $compose_mode = RCUBE_COMPOSE_FORWARD;
-else if ($msg_uid = $_SESSION['compose']['param']['uid'])
+else if ($msg_uid = $COMPOSE['param']['uid'])
   $compose_mode = RCUBE_COMPOSE_EDIT;
 
 $config_show_sig = $RCMAIL->config->get('show_sig', 1);
   $compose_mode = RCUBE_COMPOSE_EDIT;
 
 $config_show_sig = $RCMAIL->config->get('show_sig', 1);
@@ -156,30 +173,30 @@ if (!empty($msg_uid))
   // re-set 'prefer_html' to have possibility to use html part for compose
   $CONFIG['prefer_html'] = $CONFIG['prefer_html'] || $CONFIG['htmleditor'] || $compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT;
   $MESSAGE = new rcube_message($msg_uid);
   // re-set 'prefer_html' to have possibility to use html part for compose
   $CONFIG['prefer_html'] = $CONFIG['prefer_html'] || $CONFIG['htmleditor'] || $compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT;
   $MESSAGE = new rcube_message($msg_uid);
-  
+
   // make sure message is marked as read
   // make sure message is marked as read
-  if ($MESSAGE && $MESSAGE->headers && !$MESSAGE->headers->seen)
+  if ($MESSAGE && $MESSAGE->headers && empty($MESSAGE->headers->flags['SEEN']))
     $IMAP->set_flag($msg_uid, 'SEEN');
 
   if (!empty($MESSAGE->headers->charset))
     $IMAP->set_charset($MESSAGE->headers->charset);
     $IMAP->set_flag($msg_uid, 'SEEN');
 
   if (!empty($MESSAGE->headers->charset))
     $IMAP->set_charset($MESSAGE->headers->charset);
-    
+
   if ($compose_mode == RCUBE_COMPOSE_REPLY)
   {
   if ($compose_mode == RCUBE_COMPOSE_REPLY)
   {
-    $_SESSION['compose']['reply_uid'] = $msg_uid;
-    $_SESSION['compose']['reply_msgid'] = $MESSAGE->headers->messageID;
-    $_SESSION['compose']['references']  = trim($MESSAGE->headers->references . " " . $MESSAGE->headers->messageID);
+    $COMPOSE['reply_uid'] = $msg_uid;
+    $COMPOSE['reply_msgid'] = $MESSAGE->headers->messageID;
+    $COMPOSE['references']  = trim($MESSAGE->headers->references . " " . $MESSAGE->headers->messageID);
 
 
-    if (!empty($_SESSION['compose']['param']['all']))
-      $MESSAGE->reply_all = $_SESSION['compose']['param']['all'];
+    if (!empty($COMPOSE['param']['all']))
+      $MESSAGE->reply_all = $COMPOSE['param']['all'];
 
     $OUTPUT->set_env('compose_mode', 'reply');
 
     // Save the sent message in the same folder of the message being replied to
 
     $OUTPUT->set_env('compose_mode', 'reply');
 
     // Save the sent message in the same folder of the message being replied to
-    if ($RCMAIL->config->get('reply_same_folder') && ($sent_folder = $_SESSION['compose']['mailbox'])
+    if ($RCMAIL->config->get('reply_same_folder') && ($sent_folder = $COMPOSE['mailbox'])
       && rcmail_check_sent_folder($sent_folder, false)
     ) {
       && rcmail_check_sent_folder($sent_folder, false)
     ) {
-      $_SESSION['compose']['param']['sent_mbox'] = $sent_folder;
+      $COMPOSE['param']['sent_mbox'] = $sent_folder;
     }
   }
   else if ($compose_mode == RCUBE_COMPOSE_DRAFT)
     }
   }
   else if ($compose_mode == RCUBE_COMPOSE_DRAFT)
@@ -190,31 +207,31 @@ if (!empty($msg_uid))
       $info = rcmail_draftinfo_decode($MESSAGE->headers->others['x-draft-info']);
 
       if ($info['type'] == 'reply')
       $info = rcmail_draftinfo_decode($MESSAGE->headers->others['x-draft-info']);
 
       if ($info['type'] == 'reply')
-        $_SESSION['compose']['reply_uid'] = $info['uid'];
+        $COMPOSE['reply_uid'] = $info['uid'];
       else if ($info['type'] == 'forward')
       else if ($info['type'] == 'forward')
-        $_SESSION['compose']['forward_uid'] = $info['uid'];
+        $COMPOSE['forward_uid'] = $info['uid'];
 
 
-      $_SESSION['compose']['mailbox'] = $info['folder'];
+      $COMPOSE['mailbox'] = $info['folder'];
 
       // Save the sent message in the same folder of the message being replied to
       if ($RCMAIL->config->get('reply_same_folder') && ($sent_folder = $info['folder'])
         && rcmail_check_sent_folder($sent_folder, false)
       ) {
 
       // Save the sent message in the same folder of the message being replied to
       if ($RCMAIL->config->get('reply_same_folder') && ($sent_folder = $info['folder'])
         && rcmail_check_sent_folder($sent_folder, false)
       ) {
-        $_SESSION['compose']['param']['sent_mbox'] = $sent_folder;
+        $COMPOSE['param']['sent_mbox'] = $sent_folder;
       }
     }
 
     if ($MESSAGE->headers->in_reply_to)
       }
     }
 
     if ($MESSAGE->headers->in_reply_to)
-      $_SESSION['compose']['reply_msgid'] = '<'.$MESSAGE->headers->in_reply_to.'>';
+      $COMPOSE['reply_msgid'] = '<'.$MESSAGE->headers->in_reply_to.'>';
 
 
-    $_SESSION['compose']['references']  = $MESSAGE->headers->references;
+    $COMPOSE['references']  = $MESSAGE->headers->references;
   }
   else if ($compose_mode == RCUBE_COMPOSE_FORWARD)
   {
   }
   else if ($compose_mode == RCUBE_COMPOSE_FORWARD)
   {
-    $_SESSION['compose']['forward_uid'] = $msg_uid;
+    $COMPOSE['forward_uid'] = $msg_uid;
     $OUTPUT->set_env('compose_mode', 'forward');
 
     $OUTPUT->set_env('compose_mode', 'forward');
 
-    if (!empty($_SESSION['compose']['param']['attachment']))
+    if (!empty($COMPOSE['param']['attachment']))
       $MESSAGE->forward_attachment = true;
   }
 }
       $MESSAGE->forward_attachment = true;
   }
 }
@@ -238,8 +255,8 @@ if (count($MESSAGE->identities))
 if (!empty($_POST['_from'])) {
   $MESSAGE->compose['from'] = get_input_value('_from', RCUBE_INPUT_POST);
 }
 if (!empty($_POST['_from'])) {
   $MESSAGE->compose['from'] = get_input_value('_from', RCUBE_INPUT_POST);
 }
-else if (!empty($_SESSION['compose']['param']['from'])) {
-  $MESSAGE->compose['from'] = $_SESSION['compose']['param']['from'];
+else if (!empty($COMPOSE['param']['from'])) {
+  $MESSAGE->compose['from'] = $COMPOSE['param']['from'];
 }
 else if (count($MESSAGE->identities)) {
   $a_recipients = array();
 }
 else if (count($MESSAGE->identities)) {
   $a_recipients = array();
@@ -324,23 +341,28 @@ else if (count($MESSAGE->identities)) {
 // Set other headers
 $a_recipients = array();
 $parts        = array('to', 'cc', 'bcc', 'replyto', 'followupto');
 // Set other headers
 $a_recipients = array();
 $parts        = array('to', 'cc', 'bcc', 'replyto', 'followupto');
+$separator    = trim($RCMAIL->config->get('recipients_separator', ',')) . ' ';
 
 foreach ($parts as $header) {
   $fvalue = '';
   $decode_header = true;
 
   // we have a set of recipients stored is session
 
 foreach ($parts as $header) {
   $fvalue = '';
   $decode_header = true;
 
   // we have a set of recipients stored is session
-  if ($header == 'to' && ($mailto_id = $_SESSION['compose']['param']['mailto'])
+  if ($header == 'to' && ($mailto_id = $COMPOSE['param']['mailto'])
       && $_SESSION['mailto'][$mailto_id]
   ) {
     $fvalue = urldecode($_SESSION['mailto'][$mailto_id]);
     $decode_header = false;
       && $_SESSION['mailto'][$mailto_id]
   ) {
     $fvalue = urldecode($_SESSION['mailto'][$mailto_id]);
     $decode_header = false;
+
+    // make session to not grow up too much
+    unset($_SESSION['mailto'][$mailto_id]);
+    $COMPOSE['param']['to'] = $fvalue;
   }
   else if (!empty($_POST['_'.$header])) {
     $fvalue = get_input_value('_'.$header, RCUBE_INPUT_POST, TRUE);
   }
   }
   else if (!empty($_POST['_'.$header])) {
     $fvalue = get_input_value('_'.$header, RCUBE_INPUT_POST, TRUE);
   }
-  else if (!empty($_SESSION['compose']['param'][$header])) {
-    $fvalue = $_SESSION['compose']['param'][$header];
+  else if (!empty($COMPOSE['param'][$header])) {
+    $fvalue = $COMPOSE['param'][$header];
   }
   else if ($compose_mode == RCUBE_COMPOSE_REPLY) {
     // get recipent address(es) out of the message headers
   }
   else if ($compose_mode == RCUBE_COMPOSE_REPLY) {
     // get recipent address(es) out of the message headers
@@ -348,11 +370,13 @@ foreach ($parts as $header) {
       $mailfollowup = $MESSAGE->headers->others['mail-followup-to'];
       $mailreplyto  = $MESSAGE->headers->others['mail-reply-to'];
 
       $mailfollowup = $MESSAGE->headers->others['mail-followup-to'];
       $mailreplyto  = $MESSAGE->headers->others['mail-reply-to'];
 
+      // Reply to mailing list...
       if ($MESSAGE->reply_all == 'list' && $mailfollowup)
         $fvalue = $mailfollowup;
       else if ($MESSAGE->reply_all == 'list'
         && preg_match('/<mailto:([^>]+)>/i', $MESSAGE->headers->others['list-post'], $m))
         $fvalue = $m[1];
       if ($MESSAGE->reply_all == 'list' && $mailfollowup)
         $fvalue = $mailfollowup;
       else if ($MESSAGE->reply_all == 'list'
         && preg_match('/<mailto:([^>]+)>/i', $MESSAGE->headers->others['list-post'], $m))
         $fvalue = $m[1];
+      // Reply to...
       else if ($MESSAGE->reply_all && $mailfollowup)
         $fvalue = $mailfollowup;
       else if ($mailreplyto)
       else if ($MESSAGE->reply_all && $mailfollowup)
         $fvalue = $mailfollowup;
       else if ($mailreplyto)
@@ -361,13 +385,18 @@ foreach ($parts as $header) {
         $fvalue = $MESSAGE->headers->replyto;
       else if (!empty($MESSAGE->headers->from))
         $fvalue = $MESSAGE->headers->from;
         $fvalue = $MESSAGE->headers->replyto;
       else if (!empty($MESSAGE->headers->from))
         $fvalue = $MESSAGE->headers->from;
+
+      // Reply to message sent by yourself (#1487074)
+      if (!empty($ident) && $fvalue == $ident['ident']) {
+        $fvalue = $MESSAGE->headers->to;
+      }
     }
     // add recipient of original message if reply to all
     else if ($header == 'cc' && !empty($MESSAGE->reply_all) && $MESSAGE->reply_all != 'list') {
       if ($v = $MESSAGE->headers->to)
         $fvalue .= $v;
       if ($v = $MESSAGE->headers->cc)
     }
     // add recipient of original message if reply to all
     else if ($header == 'cc' && !empty($MESSAGE->reply_all) && $MESSAGE->reply_all != 'list') {
       if ($v = $MESSAGE->headers->to)
         $fvalue .= $v;
       if ($v = $MESSAGE->headers->cc)
-        $fvalue .= (!empty($fvalue) ? ', ' : '') . $v;
+        $fvalue .= (!empty($fvalue) ? $separator : '') . $v;
     }
   }
   else if (in_array($compose_mode, array(RCUBE_COMPOSE_DRAFT, RCUBE_COMPOSE_EDIT))) {
     }
   }
   else if (in_array($compose_mode, array(RCUBE_COMPOSE_DRAFT, RCUBE_COMPOSE_EDIT))) {
@@ -410,7 +439,7 @@ foreach ($parts as $header) {
       }
     }
 
       }
     }
 
-    $fvalue = implode(', ', $fvalue);
+    $fvalue = implode($separator, $fvalue);
   }
 
   $MESSAGE->compose[$header] = $fvalue;
   }
 
   $MESSAGE->compose[$header] = $fvalue;
@@ -513,7 +542,7 @@ function rcmail_compose_header_from($attrib)
       $select_from->add(format_email_recipient($sql_arr['email'], $sql_arr['name']), $identity_id);
 
       // add signature to array
       $select_from->add(format_email_recipient($sql_arr['email'], $sql_arr['name']), $identity_id);
 
       // add signature to array
-      if (!empty($sql_arr['signature']) && empty($_SESSION['compose']['param']['nosig']))
+      if (!empty($sql_arr['signature']) && empty($COMPOSE['param']['nosig']))
       {
         $a_signatures[$identity_id]['text'] = $sql_arr['signature'];
         $a_signatures[$identity_id]['is_html'] = ($sql_arr['html_signature'] == 1) ? true : false;
       {
         $a_signatures[$identity_id]['text'] = $sql_arr['signature'];
         $a_signatures[$identity_id]['is_html'] = ($sql_arr['html_signature'] == 1) ? true : false;
@@ -567,22 +596,22 @@ function rcmail_compose_editor_mode()
 
 function rcmail_prepare_message_body()
 {
 
 function rcmail_prepare_message_body()
 {
-  global $RCMAIL, $MESSAGE, $compose_mode, $LINE_LENGTH, $HTML_MODE;
+  global $RCMAIL, $MESSAGE, $COMPOSE, $compose_mode, $LINE_LENGTH, $HTML_MODE;
 
   // use posted message body
   if (!empty($_POST['_message'])) {
     $body = get_input_value('_message', RCUBE_INPUT_POST, true);
     $isHtml = (bool) get_input_value('_is_html', RCUBE_INPUT_POST);
   }
 
   // use posted message body
   if (!empty($_POST['_message'])) {
     $body = get_input_value('_message', RCUBE_INPUT_POST, true);
     $isHtml = (bool) get_input_value('_is_html', RCUBE_INPUT_POST);
   }
-  else if ($_SESSION['compose']['param']['body']) {
-    $body = $_SESSION['compose']['param']['body'];
+  else if ($COMPOSE['param']['body']) {
+    $body = $COMPOSE['param']['body'];
     $isHtml = false;
   }
   // forward as attachment
   else if ($compose_mode == RCUBE_COMPOSE_FORWARD && $MESSAGE->forward_attachment) {
     $isHtml = rcmail_compose_editor_mode();
     $body = '';
     $isHtml = false;
   }
   // forward as attachment
   else if ($compose_mode == RCUBE_COMPOSE_FORWARD && $MESSAGE->forward_attachment) {
     $isHtml = rcmail_compose_editor_mode();
     $body = '';
-    if (empty($_SESSION['compose']['attachments']))
+    if (empty($COMPOSE['attachments']))
       rcmail_write_forward_attachment($MESSAGE);
   }
   // reply/edit/draft/forward
       rcmail_write_forward_attachment($MESSAGE);
   }
   // reply/edit/draft/forward
@@ -645,9 +674,9 @@ function rcmail_prepare_message_body()
   // add blocked.gif attachment (#1486516)
   if ($isHtml && preg_match('#<img src="\./program/blocked\.gif"#', $body)) {
     if ($attachment = rcmail_save_image('program/blocked.gif', 'image/gif')) {
   // add blocked.gif attachment (#1486516)
   if ($isHtml && preg_match('#<img src="\./program/blocked\.gif"#', $body)) {
     if ($attachment = rcmail_save_image('program/blocked.gif', 'image/gif')) {
-      $_SESSION['compose']['attachments'][$attachment['id']] = $attachment;
+      $COMPOSE['attachments'][$attachment['id']] = $attachment;
       $body = preg_replace('#\./program/blocked\.gif#',
       $body = preg_replace('#\./program/blocked\.gif#',
-        $RCMAIL->comm_path.'&_action=display-attachment&_file=rcmfile'.$attachment['id'].'&_id='.$_SESSION['compose']['id'],
+        $RCMAIL->comm_path.'&_action=display-attachment&_file=rcmfile'.$attachment['id'].'&_id='.$COMPOSE['id'],
         $body);
     }
   }
         $body);
     }
   }
@@ -706,8 +735,8 @@ function rcmail_compose_body($attrib)
 
   // include GoogieSpell
   if (!empty($CONFIG['enable_spellcheck'])) {
 
   // include GoogieSpell
   if (!empty($CONFIG['enable_spellcheck'])) {
-
-    $engine = $RCMAIL->config->get('spellcheck_engine','googie');
+    $engine           = $RCMAIL->config->get('spellcheck_engine','googie');
+    $dictionary       = (bool) $RCMAIL->config->get('spellcheck_dictionary');
     $spellcheck_langs = (array) $RCMAIL->config->get('spellcheck_languages',
       array('da'=>'Dansk', 'de'=>'Deutsch', 'en' => 'English', 'es'=>'Español',
             'fr'=>'Français', 'it'=>'Italiano', 'nl'=>'Nederlands', 'pl'=>'Polski',
     $spellcheck_langs = (array) $RCMAIL->config->get('spellcheck_languages',
       array('da'=>'Dansk', 'de'=>'Deutsch', 'en' => 'English', 'es'=>'Español',
             'fr'=>'Français', 'it'=>'Italiano', 'nl'=>'Nederlands', 'pl'=>'Polski',
@@ -737,25 +766,28 @@ function rcmail_compose_body($attrib)
     foreach ($spellcheck_langs as $key => $name) {
       $editor_lang_set[] = ($key == $lang ? '+' : '') . JQ($name).'='.JQ($key);
     }
     foreach ($spellcheck_langs as $key => $name) {
       $editor_lang_set[] = ($key == $lang ? '+' : '') . JQ($name).'='.JQ($key);
     }
-    
+
     $OUTPUT->include_script('googiespell.js');
     $OUTPUT->add_script(sprintf(
     $OUTPUT->include_script('googiespell.js');
     $OUTPUT->add_script(sprintf(
-      "var googie = new GoogieSpell('\$__skin_path/images/googiespell/','?_task=utils&_action=spell&lang=');\n".
+      "var googie = new GoogieSpell('\$__skin_path/images/googiespell/','?_task=utils&_action=spell&lang=', %s);\n".
       "googie.lang_chck_spell = \"%s\";\n".
       "googie.lang_rsm_edt = \"%s\";\n".
       "googie.lang_close = \"%s\";\n".
       "googie.lang_revert = \"%s\";\n".
       "googie.lang_no_error_found = \"%s\";\n".
       "googie.lang_chck_spell = \"%s\";\n".
       "googie.lang_rsm_edt = \"%s\";\n".
       "googie.lang_close = \"%s\";\n".
       "googie.lang_revert = \"%s\";\n".
       "googie.lang_no_error_found = \"%s\";\n".
+      "googie.lang_learn_word = \"%s\";\n".
       "googie.setLanguages(%s);\n".
       "googie.setCurrentLanguage('%s');\n".
       "googie.setSpellContainer('spellcheck-control');\n".
       "googie.decorateTextarea('%s');\n".
       "%s.set_env('spellcheck', googie);",
       "googie.setLanguages(%s);\n".
       "googie.setCurrentLanguage('%s');\n".
       "googie.setSpellContainer('spellcheck-control');\n".
       "googie.decorateTextarea('%s');\n".
       "%s.set_env('spellcheck', googie);",
+      !empty($dictionary) ? 'true' : 'false',
       JQ(Q(rcube_label('checkspelling'))),
       JQ(Q(rcube_label('resumeediting'))),
       JQ(Q(rcube_label('close'))),
       JQ(Q(rcube_label('revertto'))),
       JQ(Q(rcube_label('nospellerrors'))),
       JQ(Q(rcube_label('checkspelling'))),
       JQ(Q(rcube_label('resumeediting'))),
       JQ(Q(rcube_label('close'))),
       JQ(Q(rcube_label('revertto'))),
       JQ(Q(rcube_label('nospellerrors'))),
+      JQ(Q(rcube_label('addtodict'))),
       json_serialize($spellcheck_langs),
       $lang,
       $attrib['id'],
       json_serialize($spellcheck_langs),
       $lang,
       $attrib['id'],
@@ -828,24 +860,27 @@ function rcmail_create_reply_body($body, $bodyIsHtml)
 
 function rcmail_create_forward_body($body, $bodyIsHtml)
 {
 
 function rcmail_create_forward_body($body, $bodyIsHtml)
 {
-  global $IMAP, $MESSAGE, $OUTPUT;
+  global $RCMAIL, $MESSAGE, $COMPOSE;
 
   // add attachments
 
   // add attachments
-  if (!isset($_SESSION['compose']['forward_attachments']) && is_array($MESSAGE->mime_parts))
+  if (!isset($COMPOSE['forward_attachments']) && is_array($MESSAGE->mime_parts))
     $cid_map = rcmail_write_compose_attachments($MESSAGE, $bodyIsHtml);
 
     $cid_map = rcmail_write_compose_attachments($MESSAGE, $bodyIsHtml);
 
+  $date    = format_date($MESSAGE->headers->date, $RCMAIL->config->get('date_long'));
+  $charset = $RCMAIL->output->get_charset();
+
   if (!$bodyIsHtml)
   {
   if (!$bodyIsHtml)
   {
-    $prefix = "\n\n\n-------- Original Message --------\n";
-    $prefix .= 'Subject: ' . $MESSAGE->subject . "\n";
-    $prefix .= 'Date: ' . $MESSAGE->headers->date . "\n";
-    $prefix .= 'From: ' . $MESSAGE->get_header('from') . "\n";
-    $prefix .= 'To: ' . $MESSAGE->get_header('to') . "\n";
+    $prefix = "\n\n\n-------- " . rcube_label('originalmessage') . " --------\n";
+    $prefix .= rcube_label('subject') . ': ' . $MESSAGE->subject . "\n";
+    $prefix .= rcube_label('date')    . ': ' . $date . "\n";
+    $prefix .= rcube_label('from')    . ': ' . $MESSAGE->get_header('from') . "\n";
+    $prefix .= rcube_label('to')      . ': ' . $MESSAGE->get_header('to') . "\n";
 
     if ($MESSAGE->headers->cc)
 
     if ($MESSAGE->headers->cc)
-      $prefix .= 'Cc: ' . $MESSAGE->get_header('cc') . "\n";
+      $prefix .= rcube_label('cc') . ': ' . $MESSAGE->get_header('cc') . "\n";
     if ($MESSAGE->headers->replyto && $MESSAGE->headers->replyto != $MESSAGE->headers->from)
     if ($MESSAGE->headers->replyto && $MESSAGE->headers->replyto != $MESSAGE->headers->from)
-      $prefix .= 'Reply-To: ' . $MESSAGE->get_header('replyto') . "\n";
+      $prefix .= rcube_label('replyto') . ': ' . $MESSAGE->get_header('replyto') . "\n";
 
     $prefix .= "\n";
   }
 
     $prefix .= "\n";
   }
@@ -857,24 +892,26 @@ function rcmail_create_forward_body($body, $bodyIsHtml)
     $body = rcmail_wash_html($body, array('safe' => $MESSAGE->is_safe), $cid_map);
 
     $prefix = sprintf(
     $body = rcmail_wash_html($body, array('safe' => $MESSAGE->is_safe), $cid_map);
 
     $prefix = sprintf(
-      "<br /><p>-------- Original Message --------</p>" .
+      "<br /><p>-------- " . rcube_label('originalmessage') . " --------</p>" .
         "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody>" .
         "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody>" .
-        "<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">Subject: </th><td>%s</td></tr>" .
-        "<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">Date: </th><td>%s</td></tr>" .
-        "<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">From: </th><td>%s</td></tr>" .
-        "<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">To: </th><td>%s</td></tr>",
-      Q($MESSAGE->subject),
-      Q($MESSAGE->headers->date),
-      htmlspecialchars(Q($MESSAGE->get_header('from'), 'replace'), ENT_COMPAT, $OUTPUT->get_charset()),
-      htmlspecialchars(Q($MESSAGE->get_header('to'), 'replace'), ENT_COMPAT, $OUTPUT->get_charset()));
+        "<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>" .
+        "<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>" .
+        "<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>" .
+        "<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>",
+      rcube_label('subject'), Q($MESSAGE->subject),
+      rcube_label('date'), Q($date),
+      rcube_label('from'), htmlspecialchars(Q($MESSAGE->get_header('from'), 'replace'), ENT_COMPAT, $charset),
+      rcube_label('to'), htmlspecialchars(Q($MESSAGE->get_header('to'), 'replace'), ENT_COMPAT, $charset));
 
     if ($MESSAGE->headers->cc)
 
     if ($MESSAGE->headers->cc)
-      $prefix .= sprintf("<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">Cc: </th><td>%s</td></tr>",
-        htmlspecialchars(Q($MESSAGE->get_header('cc'), 'replace'), ENT_COMPAT, $OUTPUT->get_charset()));
+      $prefix .= sprintf("<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>",
+        rcube_label('cc'),
+        htmlspecialchars(Q($MESSAGE->get_header('cc'), 'replace'), ENT_COMPAT, $charset));
 
     if ($MESSAGE->headers->replyto && $MESSAGE->headers->replyto != $MESSAGE->headers->from)
 
     if ($MESSAGE->headers->replyto && $MESSAGE->headers->replyto != $MESSAGE->headers->from)
-      $prefix .= sprintf("<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">Reply-To: </th><td>%s</td></tr>",
-        htmlspecialchars(Q($MESSAGE->get_header('replyto'), 'replace'), ENT_COMPAT, $OUTPUT->get_charset()));
+      $prefix .= sprintf("<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>",
+        rcube_label('replyto'),
+        htmlspecialchars(Q($MESSAGE->get_header('replyto'), 'replace'), ENT_COMPAT, $charset));
 
     $prefix .= "</tbody></table><br>";
   }
 
     $prefix .= "</tbody></table><br>";
   }
@@ -885,13 +922,13 @@ function rcmail_create_forward_body($body, $bodyIsHtml)
 
 function rcmail_create_draft_body($body, $bodyIsHtml)
 {
 
 function rcmail_create_draft_body($body, $bodyIsHtml)
 {
-  global $MESSAGE, $OUTPUT;
+  global $MESSAGE, $OUTPUT, $COMPOSE;
 
   /**
    * add attachments
    * sizeof($MESSAGE->mime_parts can be 1 - e.g. attachment, but no text!
    */
 
   /**
    * add attachments
    * sizeof($MESSAGE->mime_parts can be 1 - e.g. attachment, but no text!
    */
-  if (empty($_SESSION['compose']['forward_attachments'])
+  if (empty($COMPOSE['forward_attachments'])
       && is_array($MESSAGE->mime_parts)
       && count($MESSAGE->mime_parts) > 0)
   {
       && is_array($MESSAGE->mime_parts)
       && count($MESSAGE->mime_parts) > 0)
   {
@@ -929,7 +966,7 @@ function rcmail_remove_signature($body)
 
 function rcmail_write_compose_attachments(&$message, $bodyIsHtml)
 {
 
 function rcmail_write_compose_attachments(&$message, $bodyIsHtml)
 {
-  global $RCMAIL;
+  global $RCMAIL, $COMPOSE;
 
   $cid_map = $messages = array();
   foreach ((array)$message->mime_parts as $pid => $part)
 
   $cid_map = $messages = array();
   foreach ((array)$message->mime_parts as $pid => $part)
@@ -951,9 +988,9 @@ function rcmail_write_compose_attachments(&$message, $bodyIsHtml)
       }
 
       if (!$skip && ($attachment = rcmail_save_attachment($message, $pid))) {
       }
 
       if (!$skip && ($attachment = rcmail_save_attachment($message, $pid))) {
-        $_SESSION['compose']['attachments'][$attachment['id']] = $attachment;
+        $COMPOSE['attachments'][$attachment['id']] = $attachment;
         if ($bodyIsHtml && ($part->content_id || $part->content_location)) {
         if ($bodyIsHtml && ($part->content_id || $part->content_location)) {
-          $url = $RCMAIL->comm_path.'&_action=display-attachment&_file=rcmfile'.$attachment['id'].'&_id='.$_SESSION['compose']['id'];
+          $url = $RCMAIL->comm_path.'&_action=display-attachment&_file=rcmfile'.$attachment['id'].'&_id='.$COMPOSE['id'];
           if ($part->content_id)
             $cid_map['cid:'.$part->content_id] = $url;
           else
           if ($part->content_id)
             $cid_map['cid:'.$part->content_id] = $url;
           else
@@ -963,7 +1000,7 @@ function rcmail_write_compose_attachments(&$message, $bodyIsHtml)
     }
   }
 
     }
   }
 
-  $_SESSION['compose']['forward_attachments'] = true;
+  $COMPOSE['forward_attachments'] = true;
 
   return $cid_map;
 }
 
   return $cid_map;
 }
@@ -971,14 +1008,14 @@ function rcmail_write_compose_attachments(&$message, $bodyIsHtml)
 
 function rcmail_write_inline_attachments(&$message)
 {
 
 function rcmail_write_inline_attachments(&$message)
 {
-  global $RCMAIL;
+  global $RCMAIL, $COMPOSE;
 
   $cid_map = array();
   foreach ((array)$message->mime_parts as $pid => $part) {
     if (($part->content_id || $part->content_location) && $part->filename) {
       if ($attachment = rcmail_save_attachment($message, $pid)) {
 
   $cid_map = array();
   foreach ((array)$message->mime_parts as $pid => $part) {
     if (($part->content_id || $part->content_location) && $part->filename) {
       if ($attachment = rcmail_save_attachment($message, $pid)) {
-        $_SESSION['compose']['attachments'][$attachment['id']] = $attachment;
-        $url = $RCMAIL->comm_path.'&_action=display-attachment&_file=rcmfile'.$attachment['id'].'&_id='.$_SESSION['compose']['id'];
+        $COMPOSE['attachments'][$attachment['id']] = $attachment;
+        $url = $RCMAIL->comm_path.'&_action=display-attachment&_file=rcmfile'.$attachment['id'].'&_id='.$COMPOSE['id'];
         if ($part->content_id)
           $cid_map['cid:'.$part->content_id] = $url;
         else
         if ($part->content_id)
           $cid_map['cid:'.$part->content_id] = $url;
         else
@@ -993,7 +1030,7 @@ function rcmail_write_inline_attachments(&$message)
 // Creates an attachment from the forwarded message
 function rcmail_write_forward_attachment(&$message)
 {
 // Creates an attachment from the forwarded message
 function rcmail_write_forward_attachment(&$message)
 {
-  global $RCMAIL;
+  global $RCMAIL, $COMPOSE;
 
   if (strlen($message->subject)) {
     $name = mb_substr($message->subject, 0, 64) . '.eml';
 
   if (strlen($message->subject)) {
     $name = mb_substr($message->subject, 0, 64) . '.eml';
@@ -1020,7 +1057,7 @@ function rcmail_write_forward_attachment(&$message)
   }
 
   $attachment = array(
   }
 
   $attachment = array(
-    'group' => $_SESSION['compose']['id'],
+    'group' => $COMPOSE['id'],
     'name' => $name,
     'mimetype' => 'message/rfc822',
     'data' => $data,
     'name' => $name,
     'mimetype' => 'message/rfc822',
     'data' => $data,
@@ -1032,7 +1069,7 @@ function rcmail_write_forward_attachment(&$message)
 
   if ($attachment['status']) {
     unset($attachment['data'], $attachment['status'], $attachment['content_id'], $attachment['abort']);
 
   if ($attachment['status']) {
     unset($attachment['data'], $attachment['status'], $attachment['content_id'], $attachment['abort']);
-    $_SESSION['compose']['attachments'][$attachment['id']] = $attachment;
+    $COMPOSE['attachments'][$attachment['id']] = $attachment;
     return true;
   } else if ($path) {
     @unlink($path);
     return true;
   } else if ($path) {
     @unlink($path);
@@ -1044,6 +1081,8 @@ function rcmail_write_forward_attachment(&$message)
 
 function rcmail_save_attachment(&$message, $pid)
 {
 
 function rcmail_save_attachment(&$message, $pid)
 {
+  global $COMPOSE;
+
   $rcmail = rcmail::get_instance();
   $part = $message->mime_parts[$pid];
   $mem_limit = parse_bytes(ini_get('memory_limit'));
   $rcmail = rcmail::get_instance();
   $part = $message->mime_parts[$pid];
   $mem_limit = parse_bytes(ini_get('memory_limit'));
@@ -1064,7 +1103,7 @@ function rcmail_save_attachment(&$message, $pid)
   }
 
   $attachment = array(
   }
 
   $attachment = array(
-    'group' => $_SESSION['compose']['id'],
+    'group' => $COMPOSE['id'],
     'name' => $part->filename ? $part->filename : 'Part_'.$pid.'.'.$part->ctype_secondary,
     'mimetype' => $part->ctype_primary . '/' . $part->ctype_secondary,
     'content_id' => $part->content_id,
     'name' => $part->filename ? $part->filename : 'Part_'.$pid.'.'.$part->ctype_secondary,
     'mimetype' => $part->ctype_primary . '/' . $part->ctype_secondary,
     'content_id' => $part->content_id,
@@ -1087,11 +1126,13 @@ function rcmail_save_attachment(&$message, $pid)
 
 function rcmail_save_image($path, $mimetype='')
 {
 
 function rcmail_save_image($path, $mimetype='')
 {
+  global $COMPOSE;
+
   // handle attachments in memory
   $data = file_get_contents($path);
 
   $attachment = array(
   // handle attachments in memory
   $data = file_get_contents($path);
 
   $attachment = array(
-    'group' => $_SESSION['compose']['id'],
+    'group' => $COMPOSE['id'],
     'name' => rcmail_basename($path),
     'mimetype' => $mimetype ? $mimetype : rc_mime_content_type($path, $name),
     'data' => $data,
     'name' => rcmail_basename($path),
     'mimetype' => $mimetype ? $mimetype : rc_mime_content_type($path, $name),
     'data' => $data,
@@ -1120,11 +1161,11 @@ function rcmail_basename($filename)
 
 function rcmail_compose_subject($attrib)
 {
 
 function rcmail_compose_subject($attrib)
 {
-  global $MESSAGE, $compose_mode;
-  
+  global $MESSAGE, $COMPOSE, $compose_mode;
+
   list($form_start, $form_end) = get_form_tags($attrib);
   unset($attrib['form']);
   list($form_start, $form_end) = get_form_tags($attrib);
   unset($attrib['form']);
-  
+
   $attrib['name'] = '_subject';
   $attrib['spellcheck'] = 'true';
   $textfield = new html_inputfield($attrib);
   $attrib['name'] = '_subject';
   $attrib['spellcheck'] = 'true';
   $textfield = new html_inputfield($attrib);
@@ -1153,10 +1194,10 @@ function rcmail_compose_subject($attrib)
   else if ($compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT) {
     $subject = $MESSAGE->subject;
   }
   else if ($compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT) {
     $subject = $MESSAGE->subject;
   }
-  else if (!empty($_SESSION['compose']['param']['subject'])) {
-    $subject = $_SESSION['compose']['param']['subject'];
+  else if (!empty($COMPOSE['param']['subject'])) {
+    $subject = $COMPOSE['param']['subject'];
   }
   }
-  
+
   $out = $form_start ? "$form_start\n" : '';
   $out .= $textfield->show($subject);
   $out .= $form_end ? "\n$form_end" : '';
   $out = $form_start ? "$form_start\n" : '';
   $out .= $textfield->show($subject);
   $out .= $form_end ? "\n$form_end" : '';
@@ -1167,17 +1208,16 @@ function rcmail_compose_subject($attrib)
 
 function rcmail_compose_attachment_list($attrib)
 {
 
 function rcmail_compose_attachment_list($attrib)
 {
-  global $OUTPUT, $CONFIG;
-  
+  global $OUTPUT, $CONFIG, $COMPOSE;
+
   // add ID if not given
   if (!$attrib['id'])
     $attrib['id'] = 'rcmAttachmentList';
   // add ID if not given
   if (!$attrib['id'])
     $attrib['id'] = 'rcmAttachmentList';
-  
+
   $out = "\n";
   $jslist = array();
 
   $out = "\n";
   $jslist = array();
 
-  if (is_array($_SESSION['compose']['attachments']))
-  {
+  if (is_array($COMPOSE['attachments'])) {
     if ($attrib['deleteicon']) {
       $button = html::img(array(
         'src' => $CONFIG['skin_path'] . $attrib['deleteicon'],
     if ($attrib['deleteicon']) {
       $button = html::img(array(
         'src' => $CONFIG['skin_path'] . $attrib['deleteicon'],
@@ -1187,11 +1227,11 @@ function rcmail_compose_attachment_list($attrib)
     else
       $button = Q(rcube_label('delete'));
 
     else
       $button = Q(rcube_label('delete'));
 
-    foreach ($_SESSION['compose']['attachments'] as $id => $a_prop)
+    foreach ($COMPOSE['attachments'] as $id => $a_prop)
     {
       if (empty($a_prop))
         continue;
     {
       if (empty($a_prop))
         continue;
-      
+
       $out .= html::tag('li', array('id' => 'rcmfile'.$id),
         html::a(array(
             'href' => "#delete",
       $out .= html::tag('li', array('id' => 'rcmfile'.$id),
         html::a(array(
             'href' => "#delete",
@@ -1204,7 +1244,7 @@ function rcmail_compose_attachment_list($attrib)
   }
 
   if ($attrib['deleteicon'])
   }
 
   if ($attrib['deleteicon'])
-    $_SESSION['compose']['deleteicon'] = $CONFIG['skin_path'] . $attrib['deleteicon'];
+    $COMPOSE['deleteicon'] = $CONFIG['skin_path'] . $attrib['deleteicon'];
   if ($attrib['cancelicon'])
     $OUTPUT->set_env('cancelicon', $CONFIG['skin_path'] . $attrib['cancelicon']);
   if ($attrib['loadingicon'])
   if ($attrib['cancelicon'])
     $OUTPUT->set_env('cancelicon', $CONFIG['skin_path'] . $attrib['cancelicon']);
   if ($attrib['loadingicon'])
@@ -1372,12 +1412,15 @@ function rcmail_editor_selector($attrib)
 
 function rcmail_store_target_selection($attrib)
 {
 
 function rcmail_store_target_selection($attrib)
 {
+  global $COMPOSE;
+
   $attrib['name'] = '_store_target';
   $select = rcmail_mailbox_select(array_merge($attrib, array(
     'noselection' => '- '.rcube_label('dontsave').' -',
   $attrib['name'] = '_store_target';
   $select = rcmail_mailbox_select(array_merge($attrib, array(
     'noselection' => '- '.rcube_label('dontsave').' -',
-    'folder_filter' => 'mail'
+    'folder_filter' => 'mail',
+    'folder_rights' => 'w',
   )));
   )));
-  return $select->show($_SESSION['compose']['param']['sent_mbox'], $attrib);
+  return $select->show($COMPOSE['param']['sent_mbox'], $attrib);
 }
 
 
 }
 
 
@@ -1403,14 +1446,14 @@ function rcmail_check_sent_folder($folder, $create=false)
 
 function get_form_tags($attrib)
 {
 
 function get_form_tags($attrib)
 {
-  global $RCMAIL, $MESSAGE_FORM;
+  global $RCMAIL, $MESSAGE_FORM, $COMPOSE;
 
   $form_start = '';
   if (!$MESSAGE_FORM)
   {
     $hiddenfields = new html_hiddenfield(array('name' => '_task', 'value' => $RCMAIL->task));
     $hiddenfields->add(array('name' => '_action', 'value' => 'send'));
 
   $form_start = '';
   if (!$MESSAGE_FORM)
   {
     $hiddenfields = new html_hiddenfield(array('name' => '_task', 'value' => $RCMAIL->task));
     $hiddenfields->add(array('name' => '_action', 'value' => 'send'));
-    $hiddenfields->add(array('name' => '_id', 'value' => $_SESSION['compose']['id']));
+    $hiddenfields->add(array('name' => '_id', 'value' => $COMPOSE['id']));
 
     $form_start = empty($attrib['form']) ? $RCMAIL->output->form_tag(array('name' => "form", 'method' => "post")) : '';
     $form_start .= $hiddenfields->show();
 
     $form_start = empty($attrib['form']) ? $RCMAIL->output->form_tag(array('name' => "form", 'method' => "post")) : '';
     $form_start .= $hiddenfields->show();
index 7e0399e47fb569709da73ce1d96c44fac50df40e..80936a0049c2b2880de439c7f6bc3fe2d700343f 100644 (file)
@@ -15,7 +15,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: folders.inc 4410 2011-01-12 18:25:02Z thomasb $
+ $Id: folders.inc 5266 2011-09-22 07:49:33Z alec $
 */
 
 // only process ajax requests
 */
 
 // only process ajax requests
@@ -65,7 +65,7 @@ else if ($RCMAIL->action == 'purge')
                 $OUTPUT->set_env('messagecount', 0);
                 $OUTPUT->set_env('pagecount', 0);
                 $OUTPUT->command('message_list.clear');
                 $OUTPUT->set_env('messagecount', 0);
                 $OUTPUT->set_env('pagecount', 0);
                 $OUTPUT->command('message_list.clear');
-                $OUTPUT->command('set_rowcount', rcmail_get_messagecount_text());
+                $OUTPUT->command('set_rowcount', rcmail_get_messagecount_text(), $mbox);
                 $OUTPUT->command('set_unread_count', $mbox, 0);
                 $OUTPUT->command('set_quota', rcmail_quota_content());
                 rcmail_set_unseen_count($mbox, 0);
                 $OUTPUT->command('set_unread_count', $mbox, 0);
                 $OUTPUT->command('set_quota', rcmail_quota_content());
                 rcmail_set_unseen_count($mbox, 0);
index 8b0e58943d45ae6afe8cc8c21df21af14fb681dc..3c93cda1d993acdf1e6c2a9e88726b8223281e98 100644 (file)
@@ -15,7 +15,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: func.inc 5235 2011-09-19 06:43:57Z alec $
+ $Id: func.inc 5601 2011-12-14 09:08:54Z alec $
 
 */
 
 
 */
 
@@ -253,7 +253,7 @@ function rcmail_js_message_list($a_headers, $insert_top=FALSE, $a_show_cols=null
     return;
 
   // remove 'threads', 'attachment', 'flag', 'status' columns, we don't need them here
     return;
 
   // remove 'threads', 'attachment', 'flag', 'status' columns, we don't need them here
-  foreach (array('threads', 'attachment', 'flag', 'status') as $col) {
+  foreach (array('threads', 'attachment', 'flag', 'status', 'priority') as $col) {
     if (($key = array_search($col, $a_show_cols)) !== FALSE)
       unset($a_show_cols[$key]);
   }
     if (($key = array_search($col, $a_show_cols)) !== FALSE)
       unset($a_show_cols[$key]);
   }
@@ -287,6 +287,7 @@ function rcmail_js_message_list($a_headers, $insert_top=FALSE, $a_show_cols=null
       $a_msg_cols[$col] = $cont;
     }
 
       $a_msg_cols[$col] = $cont;
     }
 
+    $a_msg_flags = array_change_key_case(array_map('intval', (array) $header->flags));
     if ($header->depth)
       $a_msg_flags['depth'] = $header->depth;
     else if ($header->has_children)
     if ($header->depth)
       $a_msg_flags['depth'] = $header->depth;
     else if ($header->has_children)
@@ -297,23 +298,15 @@ function rcmail_js_message_list($a_headers, $insert_top=FALSE, $a_show_cols=null
       $a_msg_flags['has_children'] = $header->has_children;
     if ($header->unread_children)
       $a_msg_flags['unread_children'] = $header->unread_children;
       $a_msg_flags['has_children'] = $header->has_children;
     if ($header->unread_children)
       $a_msg_flags['unread_children'] = $header->unread_children;
-    if ($header->deleted)
-      $a_msg_flags['deleted'] = 1;
-    if (!$header->seen)
-      $a_msg_flags['unread'] = 1;
-    if ($header->answered)
-      $a_msg_flags['replied'] = 1;
-    if ($header->forwarded)
-      $a_msg_flags['forwarded'] = 1;
-    if ($header->flagged)
-      $a_msg_flags['flagged'] = 1;
     if ($header->others['list-post'])
       $a_msg_flags['ml'] = 1;
     if ($header->others['list-post'])
       $a_msg_flags['ml'] = 1;
+    if ($header->priority)
+      $a_msg_flags['prio'] = (int) $header->priority;
 
     $a_msg_flags['ctype'] = Q($header->ctype);
     $a_msg_flags['mbox'] = $mbox;
 
 
     $a_msg_flags['ctype'] = Q($header->ctype);
     $a_msg_flags['mbox'] = $mbox;
 
-    // merge with plugin result
+    // merge with plugin result (Deprecated, use $header->flags)
     if (!empty($header->list_flags) && is_array($header->list_flags))
       $a_msg_flags = array_merge($a_msg_flags, $header->list_flags);
     if (!empty($header->list_cols) && is_array($header->list_cols))
     if (!empty($header->list_flags) && is_array($header->list_flags))
       $a_msg_flags = array_merge($a_msg_flags, $header->list_flags);
     if (!empty($header->list_cols) && is_array($header->list_cols))
@@ -327,7 +320,7 @@ function rcmail_js_message_list($a_headers, $insert_top=FALSE, $a_show_cols=null
   }
 
   if ($IMAP->threading) {
   }
 
   if ($IMAP->threading) {
-    $OUTPUT->command('init_threads', (array) $roots);
+    $OUTPUT->command('init_threads', (array) $roots, $mbox);
   }
 }
 
   }
 }
 
@@ -372,6 +365,7 @@ function rcmail_message_list_head($attrib, $a_show_cols)
         $col_name = '<span class="flagged">&nbsp;</span>';
         break;
       case 'attachment':
         $col_name = '<span class="flagged">&nbsp;</span>';
         break;
       case 'attachment':
+      case 'priority':
       case 'status':
         $col_name = '<span class="' . $col .'">&nbsp;</span>';
         break;
       case 'status':
         $col_name = '<span class="' . $col .'">&nbsp;</span>';
         break;
@@ -556,7 +550,7 @@ function rcmail_check_safe(&$message)
  * @param array  CID map replaces (inline images)
  * @return string Clean HTML
  */
  * @param array  CID map replaces (inline images)
  * @return string Clean HTML
  */
-function rcmail_wash_html($html, $p = array(), $cid_replaces)
+function rcmail_wash_html($html, $p, $cid_replaces)
 {
   global $REMOTE_OBJECTS;
 
 {
   global $REMOTE_OBJECTS;
 
@@ -565,7 +559,7 @@ function rcmail_wash_html($html, $p = array(), $cid_replaces)
   // special replacements (not properly handled by washtml class)
   $html_search = array(
     '/(<\/nobr>)(\s+)(<nobr>)/i',      // space(s) between <NOBR>
   // special replacements (not properly handled by washtml class)
   $html_search = array(
     '/(<\/nobr>)(\s+)(<nobr>)/i',      // space(s) between <NOBR>
-    '/<title[^>]*>.*<\/title>/i',      // PHP bug #32547 workaround: remove title tag
+    '/<title[^>]*>[^<]*<\/title>/i',   // PHP bug #32547 workaround: remove title tag
     '/^(\0\0\xFE\xFF|\xFF\xFE\0\0|\xFE\xFF|\xFF\xFE|\xEF\xBB\xBF)/',   // byte-order mark (only outlook?)
     '/<html\s[^>]+>/i',                        // washtml/DOMDocument cannot handle xml namespaces
   );
     '/^(\0\0\xFE\xFF|\xFF\xFE\0\0|\xFE\xFF|\xFF\xFE|\xEF\xBB\xBF)/',   // byte-order mark (only outlook?)
     '/<html\s[^>]+>/i',                        // washtml/DOMDocument cannot handle xml namespaces
   );
@@ -596,16 +590,16 @@ function rcmail_wash_html($html, $p = array(), $cid_replaces)
   $html = preg_replace_callback('/(<[\/]*)([^\s>]+)/', 'rcmail_html_tag_callback', $html);
 
   // charset was converted to UTF-8 in rcube_imap::get_message_part(),
   $html = preg_replace_callback('/(<[\/]*)([^\s>]+)/', 'rcmail_html_tag_callback', $html);
 
   // charset was converted to UTF-8 in rcube_imap::get_message_part(),
-  // -> change charset specification in HTML accordingly
-  $charset_pattern = '(<meta\s+[^>]*content=)[\'"]?(\w+\/\w+;\s*charset=)([a-z0-9-_]+[\'"]?)';
-  if (preg_match("/$charset_pattern/Ui", $html)) {
-    $html = preg_replace("/$charset_pattern/i", '\\1"\\2'.RCMAIL_CHARSET.'"', $html);
-  }
-  else {
-    // add meta content-type to malformed messages, washtml cannot work without that
-    if (!preg_match('/<head[^>]*>(.*)<\/head>/Uims', $html))
-      $html = '<head></head>'. $html;
-    $html = substr_replace($html, '<meta http-equiv="Content-Type" content="text/html; charset='.RCMAIL_CHARSET.'" />', intval(stripos($html, '<head>')+6), 0);
+  // change/add charset specification in HTML accordingly,
+  // washtml cannot work without that
+  $meta = '<meta http-equiv="Content-Type" content="text/html; charset='.RCMAIL_CHARSET.'" />';
+
+  // remove old meta tag and add the new one, making sure
+  // that it is placed in the head (#1488093)
+  $html = preg_replace('/<meta[^>]+charset=[a-z0-9-_]+[^>]*>/Ui', '', $html);
+  $html = preg_replace('/(<head[^>]*>)/Ui', '\\1'.$meta, $html, -1, $rcount);
+  if (!$rcount) {
+    $html = '<head>' . $meta . '</head>' . $html;
   }
 
   // turn relative into absolute urls
   }
 
   // turn relative into absolute urls
@@ -645,6 +639,9 @@ function rcmail_wash_html($html, $p = array(), $cid_replaces)
   if (!$p['skip_washer_style_callback'])
     $washer->add_callback('style', 'rcmail_washtml_callback');
 
   if (!$p['skip_washer_style_callback'])
     $washer->add_callback('style', 'rcmail_washtml_callback');
 
+  // Remove non-UTF8 characters (#1487813)
+  $html = rc_utf8_clean($html);
+
   $html = $washer->wash($html);
   $REMOTE_OBJECTS = $washer->extlinks;
 
   $html = $washer->wash($html);
   $REMOTE_OBJECTS = $washer->extlinks;
 
@@ -772,7 +769,7 @@ function rcmail_plain_body($body, $flowed=false)
 
           // previous line is flowed?
           if (isset($body[$last]) && $body[$n]
 
           // previous line is flowed?
           if (isset($body[$last]) && $body[$n]
-            && $last != $last_sig
+            && $last !== $last_sig
             && $body[$last][strlen($body[$last])-1] == ' '
           ) {
             $body[$last] .= $body[$n];
             && $body[$last][strlen($body[$last])-1] == ' '
           ) {
             $body[$last] .= $body[$n];
@@ -824,7 +821,7 @@ function rcmail_plain_body($body, $flowed=false)
 /**
  * Callback function for washtml cleaning class
  */
 /**
  * Callback function for washtml cleaning class
  */
-function rcmail_washtml_callback($tagname, $attrib, $content)
+function rcmail_washtml_callback($tagname, $attrib, $content, $washtml)
 {
   switch ($tagname) {
     case 'form':
 {
   switch ($tagname) {
     case 'form':
@@ -836,8 +833,11 @@ function rcmail_washtml_callback($tagname, $attrib, $content)
       $stripped = preg_replace('/[^a-zA-Z\(:;]/', '', rcmail_xss_entity_decode($content));
 
       // now check for evil strings like expression, behavior or url()
       $stripped = preg_replace('/[^a-zA-Z\(:;]/', '', rcmail_xss_entity_decode($content));
 
       // now check for evil strings like expression, behavior or url()
-      if (!preg_match('/expression|behavior|url\(|import[^a]/', $stripped)) {
-        $out = html::tag('style', array('type' => 'text/css'), $content);
+      if (!preg_match('/expression|behavior|javascript:|import[^a]/i', $stripped)) {
+        if (!$washtml->get_config('allow_remote') && stripos($stripped, 'url('))
+          $washtml->extlinks = true;
+        else
+          $out = html::tag('style', array('type' => 'text/css'), $content);
         break;
       }
 
         break;
       }
 
@@ -1017,7 +1017,7 @@ function rcmail_message_body($attrib)
         $body = rcmail_print_body($part, array('safe' => $safe_mode, 'plain' => !$CONFIG['prefer_html']));
 
         if ($part->ctype_secondary == 'html') {
         $body = rcmail_print_body($part, array('safe' => $safe_mode, 'plain' => !$CONFIG['prefer_html']));
 
         if ($part->ctype_secondary == 'html') {
-          $body = rcmail_html4inline($body, $attrib['id'], 'rcmBody', $attrs);
+          $body = rcmail_html4inline($body, $attrib['id'], 'rcmBody', $attrs, $safe_mode);
           $div_attr = array('class' => 'message-htmlpart');
           $style = array();
 
           $div_attr = array('class' => 'message-htmlpart');
           $style = array();
 
@@ -1043,15 +1043,14 @@ function rcmail_message_body($attrib)
       rcmail_plain_body(Q($MESSAGE->body, 'strict', false))));
     }
 
       rcmail_plain_body(Q($MESSAGE->body, 'strict', false))));
     }
 
-  $ctype_primary = strtolower($MESSAGE->structure->ctype_primary);
-  $ctype_secondary = strtolower($MESSAGE->structure->ctype_secondary);
-
   // list images after mail body
   // list images after mail body
-  if ($CONFIG['inline_images']
-      && $ctype_primary == 'multipart'
-      && !empty($MESSAGE->attachments))
-    {
+  if ($CONFIG['inline_images'] && !empty($MESSAGE->attachments)) {
     foreach ($MESSAGE->attachments as $attach_prop) {
     foreach ($MESSAGE->attachments as $attach_prop) {
+      // skip inline images
+      if ($attach_prop->content_id && $attach_prop->disposition == 'inline') {
+        continue;
+      }
+
       // Content-Type: image/*...
       if (preg_match('/^image\//i', $attach_prop->mimetype) ||
         // ...or known file extension: many clients are using application/octet-stream
       // Content-Type: image/*...
       if (preg_match('/^image\//i', $attach_prop->mimetype) ||
         // ...or known file extension: many clients are using application/octet-stream
@@ -1061,7 +1060,7 @@ function rcmail_message_body($attrib)
       ) {
         $out .= html::tag('hr') . html::p(array('align' => "center"),
           html::img(array(
       ) {
         $out .= html::tag('hr') . html::p(array('align' => "center"),
           html::img(array(
-            'src' => $MESSAGE->get_part_url($attach_prop->mime_id),
+            'src' => $MESSAGE->get_part_url($attach_prop->mime_id, true),
             'title' => $attach_prop->filename,
             'alt' => $attach_prop->filename,
           )));
             'title' => $attach_prop->filename,
             'alt' => $attach_prop->filename,
           )));
@@ -1097,7 +1096,7 @@ function rcmail_resolve_base($body)
 /**
  * modify a HTML message that it can be displayed inside a HTML page
  */
 /**
  * modify a HTML message that it can be displayed inside a HTML page
  */
-function rcmail_html4inline($body, $container_id, $body_id='', &$attributes=null)
+function rcmail_html4inline($body, $container_id, $body_id='', &$attributes=null, $allow_remote=false)
 {
   $last_style_pos = 0;
   $body_lc = strtolower($body);
 {
   $last_style_pos = 0;
   $body_lc = strtolower($body);
@@ -1110,7 +1109,7 @@ function rcmail_html4inline($body, $container_id, $body_id='', &$attributes=null
 
     // replace all css definitions with #container [def]
     $styles = rcmail_mod_css_styles(
 
     // replace all css definitions with #container [def]
     $styles = rcmail_mod_css_styles(
-      substr($body, $pos, $pos2-$pos), $cont_id);
+      substr($body, $pos, $pos2-$pos), $cont_id, $allow_remote);
 
     $body = substr($body, 0, $pos) . $styles . substr($body, $pos2);
     $body_lc = strtolower($body);
 
     $body = substr($body, 0, $pos) . $styles . substr($body, $pos2);
     $body_lc = strtolower($body);
@@ -1288,6 +1287,7 @@ function rcmail_address_string($input, $max=null, $linked=false, $addicon=null)
             'href' => "#add",
             'onclick' => sprintf("return %s.command('add-contact','%s',this)", JS_OBJECT_NAME, urlencode($string)),
             'title' => rcube_label('addtoaddressbook'),
             'href' => "#add",
             'onclick' => sprintf("return %s.command('add-contact','%s',this)", JS_OBJECT_NAME, urlencode($string)),
             'title' => rcube_label('addtoaddressbook'),
+            'class' => 'rcmaddcontact',
           ),
           html::img(array(
             'src' => $CONFIG['skin_path'] . $addicon,
           ),
           html::img(array(
             'src' => $CONFIG['skin_path'] . $addicon,
@@ -1451,7 +1451,7 @@ function rcmail_send_mdn($message, &$smtp_error)
   if (!is_object($message) || !is_a($message, 'rcube_message'))
     $message = new rcube_message($message);
 
   if (!is_object($message) || !is_a($message, 'rcube_message'))
     $message = new rcube_message($message);
 
-  if ($message->headers->mdn_to && !$message->headers->mdn_sent &&
+  if ($message->headers->mdn_to && empty($message->headers->flags['MDNSENT']) &&
     ($IMAP->check_permflag('MDNSENT') || $IMAP->check_permflag('*')))
   {
     $identity = $RCMAIL->user->get_identity();
     ($IMAP->check_permflag('MDNSENT') || $IMAP->check_permflag('*')))
   {
     $identity = $RCMAIL->user->get_identity();
@@ -1551,6 +1551,11 @@ function rcmail_search_filter($attrib)
   $select_filter->add(rcube_label('unanswered'), 'UNANSWERED');
   if (!$CONFIG['skip_deleted'])
     $select_filter->add(rcube_label('deleted'), 'DELETED');
   $select_filter->add(rcube_label('unanswered'), 'UNANSWERED');
   if (!$CONFIG['skip_deleted'])
     $select_filter->add(rcube_label('deleted'), 'DELETED');
+  $select_filter->add(rcube_label('priority').': '.rcube_label('highest'), 'HEADER X-PRIORITY 1');
+  $select_filter->add(rcube_label('priority').': '.rcube_label('high'), 'HEADER X-PRIORITY 2');
+  $select_filter->add(rcube_label('priority').': '.rcube_label('normal'), 'NOT HEADER X-PRIORITY 1 NOT HEADER X-PRIORITY 2 NOT HEADER X-PRIORITY 4 NOT HEADER X-PRIORITY 5');
+  $select_filter->add(rcube_label('priority').': '.rcube_label('low'), 'HEADER X-PRIORITY 4');
+  $select_filter->add(rcube_label('priority').': '.rcube_label('lowest'), 'HEADER X-PRIORITY 5');
 
   $out = $select_filter->show($_SESSION['search_filter']);
 
 
   $out = $select_filter->show($_SESSION['search_filter']);
 
index bf35d0178202fde1ac2f77c0e96bf3729b821c0e..16f7acf63b67aa6aab2a8bf70ce4b79131dd4c80 100644 (file)
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: get.inc 5151 2011-08-31 12:49:44Z alec $
+ $Id: get.inc 5514 2011-11-30 11:35:43Z alec $
 
 */
 
 
 // show loading page
 if (!empty($_GET['_preload'])) {
 
 */
 
 
 // show loading page
 if (!empty($_GET['_preload'])) {
-  $url = str_replace('&_preload=1', '', $_SERVER['REQUEST_URI']);
+  $url = preg_replace('/[&?]+_preload=1/', '', $_SERVER['REQUEST_URI']);
   $message = rcube_label('loadingdata');
 
   header('Content-Type: text/html; charset=' . RCMAIL_CHARSET);
   $message = rcube_label('loadingdata');
 
   header('Content-Type: text/html; charset=' . RCMAIL_CHARSET);
@@ -64,8 +64,6 @@ if (!empty($_GET['_uid'])) {
   $MESSAGE = new rcube_message(get_input_value('_uid', RCUBE_INPUT_GET));
 }
 
   $MESSAGE = new rcube_message(get_input_value('_uid', RCUBE_INPUT_GET));
 }
 
-send_nocacheing_headers();
-
 // show part page
 if (!empty($_GET['_frame'])) {
   $OUTPUT->send('messagepart');
 // show part page
 if (!empty($_GET['_frame'])) {
   $OUTPUT->send('messagepart');
@@ -136,11 +134,24 @@ else if ($pid = get_input_value('_part', RCUBE_INPUT_GET)) {
 
       header("Content-Disposition: $disposition; filename=\"$filename\"");
 
 
       header("Content-Disposition: $disposition; filename=\"$filename\"");
 
-      // turn off output buffering and print part content
-      if ($part->body)
-        echo $part->body;
-      else if ($part->size)
-        $IMAP->get_message_part($MESSAGE->uid, $part->mime_id, $part, true);
+      // do content filtering to avoid XSS through fake images
+      if (!empty($_REQUEST['_embed']) && $browser->ie && $browser->ver <= 8) {
+        if ($part->body)
+          echo preg_match('/<(script|iframe|object)/i', $part->body) ? '' : $part->body;
+        else if ($part->size) {
+          $stdout = fopen('php://output', 'w');
+          stream_filter_register('rcube_content', 'rcube_content_filter') or die('Failed to register content filter');
+          stream_filter_append($stdout, 'rcube_content');
+          $IMAP->get_message_part($MESSAGE->uid, $part->mime_id, $part, false, $stdout);
+        }
+      }
+      else {
+        // turn off output buffering and print part content
+        if ($part->body)
+          echo $part->body;
+        else if ($part->size)
+          $IMAP->get_message_part($MESSAGE->uid, $part->mime_id, $part, true);
+      }
     }
 
     exit;
     }
 
     exit;
@@ -168,3 +179,39 @@ header('HTTP/1.1 404 Not Found');
 exit;
 
 
 exit;
 
 
+
+/**
+ * PHP stream filter to detect html/javascript code in attachments
+ */
+class rcube_content_filter extends php_user_filter
+{
+  private $buffer = '';
+  private $cutoff = 2048;
+
+  function onCreate()
+  {
+    $this->cutoff = rand(2048, 3027);
+    return true;
+  }
+
+  function filter($in, $out, &$consumed, $closing)
+  {
+    while ($bucket = stream_bucket_make_writeable($in)) {
+      $this->buffer .= $bucket->data;
+
+      // check for evil content and abort
+      if (preg_match('/<(script|iframe|object)/i', $this->buffer))
+        return PSFS_ERR_FATAL;
+
+      // keep buffer small enough
+      if (strlen($this->buffer) > 4096)
+        $this->buffer = substr($this->buffer, $this->cutoff);
+
+      $consumed += $bucket->datalen;
+      stream_bucket_append($out, $bucket);
+    }
+
+    return PSFS_PASS_ON;
+  }
+}
+
index 70d7508a56accb67aacd5977976f8059627e1375..3505d481ac1d98db4f30aea1aa27838597efb6f2 100644 (file)
@@ -15,7 +15,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: list.inc 4410 2011-01-12 18:25:02Z thomasb $
+ $Id: list.inc 5266 2011-09-22 07:49:33Z alec $
 
 */
 
 
 */
 
@@ -53,6 +53,9 @@ if ($save_arr)
 
 $mbox_name = $IMAP->get_mailbox_name();
 
 
 $mbox_name = $IMAP->get_mailbox_name();
 
+// Synchronize mailbox cache, handle flag changes
+$IMAP->mailbox_sync($mbox_name);
+
 // initialize searching result if search_filter is used
 if ($_SESSION['search_filter'] && $_SESSION['search_filter'] != 'ALL')
 {
 // initialize searching result if search_filter is used
 if ($_SESSION['search_filter'] && $_SESSION['search_filter'] != 'ALL')
 {
@@ -93,7 +96,7 @@ $OUTPUT->set_env('messagecount', $count);
 $OUTPUT->set_env('pagecount', $pages);
 $OUTPUT->set_env('threading', (bool) $IMAP->threading);
 $OUTPUT->set_env('current_page', $count ? $IMAP->list_page : 1);
 $OUTPUT->set_env('pagecount', $pages);
 $OUTPUT->set_env('threading', (bool) $IMAP->threading);
 $OUTPUT->set_env('current_page', $count ? $IMAP->list_page : 1);
-$OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($count));
+$OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($count), $mbox_name);
 $OUTPUT->command('set_mailboxname', rcmail_get_mailbox_name_text());
 
 // add message rows
 $OUTPUT->command('set_mailboxname', rcmail_get_mailbox_name_text());
 
 // add message rows
@@ -116,5 +119,3 @@ else {
 
 // send response
 $OUTPUT->send();
 
 // send response
 $OUTPUT->send();
-
-
index 94009fbc7612cf003a066db2934f742d4a510fa1..2d50391a2fdcf55c9017c74044258c66f16a0e53 100644 (file)
@@ -14,7 +14,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: mark.inc 4410 2011-01-12 18:25:02Z thomasb $
+ $Id: mark.inc 5266 2011-09-22 07:49:33Z alec $
 
 */
 
 
 */
 
@@ -104,7 +104,7 @@ if (($uids = get_input_value('_uid', RCUBE_INPUT_POST)) && ($flag = get_input_va
         $OUTPUT->command('set_unread_count', $mbox, $unseen_count, ($mbox == 'INBOX'));
         rcmail_set_unseen_count($mbox, $unseen_count);
       }
         $OUTPUT->command('set_unread_count', $mbox, $unseen_count, ($mbox == 'INBOX'));
         rcmail_set_unseen_count($mbox, $unseen_count);
       }
-      $OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($msg_count));
+      $OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($msg_count), $mbox);
 
       if ($IMAP->threading)
            $count = get_input_value('_count', RCUBE_INPUT_POST);
 
       if ($IMAP->threading)
            $count = get_input_value('_count', RCUBE_INPUT_POST);
index b575e58a150cac9ae6a5d917cd63fb7cf1a0a533..30928d499aa0d0f3e8ebd09b7ec1852a5af6d920 100644 (file)
@@ -15,7 +15,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: move_del.inc 4410 2011-01-12 18:25:02Z thomasb $
+ $Id: move_del.inc 5266 2011-09-22 07:49:33Z alec $
 
 */
 
 
 */
 
@@ -116,12 +116,12 @@ else
     rcmail_set_unseen_count($mbox, $unseen_count);
   }
 
     rcmail_set_unseen_count($mbox, $unseen_count);
   }
 
-  if ($RCMAIL->action=='moveto' && strlen($target)) {
+  if ($RCMAIL->action == 'moveto' && strlen($target)) {
     rcmail_send_unread_count($target, true);
   }
 
   $OUTPUT->command('set_quota', rcmail_quota_content());
     rcmail_send_unread_count($target, true);
   }
 
   $OUTPUT->command('set_quota', rcmail_quota_content());
-  $OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($msg_count));
+  $OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($msg_count), $mbox);
 
   if ($IMAP->threading)
     $count = get_input_value('_count', RCUBE_INPUT_POST);
 
   if ($IMAP->threading)
     $count = get_input_value('_count', RCUBE_INPUT_POST);
index 27bc531b0925a3fb8c7df1b074e2d029159978a7..e6fb629ab8c02133c398a18a5ed41bf14819326c 100644 (file)
@@ -11,7 +11,7 @@
  |         Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  |         Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: search.inc 4812 2011-05-27 13:01:05Z alec $
+ $Id: search.inc 5527 2011-12-02 09:58:03Z alec $
 
 */
 
 
 */
 
@@ -31,6 +31,7 @@ $str     = get_input_value('_q', RCUBE_INPUT_GET, true);
 $mbox    = get_input_value('_mbox', RCUBE_INPUT_GET, true);
 $filter  = get_input_value('_filter', RCUBE_INPUT_GET);
 $headers = get_input_value('_headers', RCUBE_INPUT_GET);
 $mbox    = get_input_value('_mbox', RCUBE_INPUT_GET, true);
 $filter  = get_input_value('_filter', RCUBE_INPUT_GET);
 $headers = get_input_value('_headers', RCUBE_INPUT_GET);
+$subject = array();
 
 $search_request = md5($mbox.$filter.$str);
 
 
 $search_request = md5($mbox.$filter.$str);
 
@@ -70,15 +71,20 @@ else if (preg_match("/^body:.*/i", $str))
   list(,$srch) = explode(":", $str);
   $subject['text'] = "TEXT";
 }
   list(,$srch) = explode(":", $str);
   $subject['text'] = "TEXT";
 }
-else if(trim($str))
+else if (strlen(trim($str)))
 {
   if ($headers) {
 {
   if ($headers) {
-    foreach(explode(',', $headers) as $header)
-      switch ($header) {
-        case 'text': $subject['text'] = 'TEXT'; break;
-        default:     $subject[$header] = 'HEADER '.strtoupper($header);
+    foreach (explode(',', $headers) as $header) {
+      if ($header == 'text') {
+        // #1488208: get rid of other headers when searching by "TEXT"
+        $subject = array('text' => 'TEXT');
+        break;
       }
       }
-    
+      else {
+        $subject[$header] = 'HEADER '.strtoupper($header);
+      }
+    }
+
     // save search modifiers for the current folder to user prefs
     $search_mods = $RCMAIL->config->get('search_mods', $SEARCH_MODS_DEFAULT);
     $search_mods[$mbox] = array_fill_keys(array_keys($subject), 1);
     // save search modifiers for the current folder to user prefs
     $search_mods = $RCMAIL->config->get('search_mods', $SEARCH_MODS_DEFAULT);
     $search_mods[$mbox] = array_fill_keys(array_keys($subject), 1);
@@ -89,9 +95,9 @@ else if(trim($str))
   }
 }
 
   }
 }
 
-$search = $srch ? trim($srch) : trim($str);
+$search = isset($srch) ? trim($srch) : trim($str);
 
 
-if ($subject) {
+if (!empty($subject)) {
   $search_str .= str_repeat(' OR', count($subject)-1);
   foreach ($subject as $sub)
     $search_str .= sprintf(" %s {%d}\r\n%s", $sub, strlen($search), $search);
   $search_str .= str_repeat(' OR', count($subject)-1);
   foreach ($subject as $sub)
     $search_str .= sprintf(" %s {%d}\r\n%s", $sub, strlen($search), $search);
@@ -101,7 +107,7 @@ $search_str = trim($search_str);
 
 // execute IMAP search
 if ($search_str)
 
 // execute IMAP search
 if ($search_str)
-  $result = $IMAP->search($mbox, $search_str, $imap_charset, $_SESSION['sort_col']);
+  $IMAP->search($mbox, $search_str, $imap_charset, $_SESSION['sort_col']);
 
 // Get the headers
 $result_h = $IMAP->list_headers($mbox, 1, $_SESSION['sort_col'], $_SESSION['sort_order']);
 
 // Get the headers
 $result_h = $IMAP->list_headers($mbox, 1, $_SESSION['sort_col'], $_SESSION['sort_order']);
@@ -135,7 +141,7 @@ else {
 $OUTPUT->set_env('search_request', $search_str ? $search_request : '');
 $OUTPUT->set_env('messagecount', $count);
 $OUTPUT->set_env('pagecount', ceil($count/$IMAP->page_size));
 $OUTPUT->set_env('search_request', $search_str ? $search_request : '');
 $OUTPUT->set_env('messagecount', $count);
 $OUTPUT->set_env('pagecount', ceil($count/$IMAP->page_size));
-$OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($count, 1));
+$OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($count, 1), $mbox);
 $OUTPUT->send();
 
 
 $OUTPUT->send();
 
 
index 4c4f0d1bf60e56b63a705653603e860edb79ed72..8ea9f55dde748383f55e31ffb9bb41f92de0dba8 100644 (file)
@@ -5,7 +5,7 @@
  | program/steps/mail/sendmail.inc                                       |
  |                                                                       |
  | This file is part of the Roundcube Webmail client                     |
  | program/steps/mail/sendmail.inc                                       |
  |                                                                       |
  | This file is part of the Roundcube Webmail client                     |
- | Copyright (C) 2005-2010, The Roundcube Dev Team                       |
+ | Copyright (C) 2005-2011, The Roundcube Dev Team                       |
  | Licensed under the GNU GPL                                            |
  |                                                                       |
  | PURPOSE:                                                              |
  | Licensed under the GNU GPL                                            |
  |                                                                       |
  | PURPOSE:                                                              |
@@ -16,7 +16,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: sendmail.inc 5229 2011-09-16 19:13:27Z thomasb $
+ $Id: sendmail.inc 5527 2011-12-02 09:58:03Z alec $
 
 */
 
 
 */
 
@@ -27,11 +27,11 @@ $OUTPUT->framed = TRUE;
 $savedraft = !empty($_POST['_draft']) ? true : false;
 
 $COMPOSE_ID = get_input_value('_id', RCUBE_INPUT_GPC);
 $savedraft = !empty($_POST['_draft']) ? true : false;
 
 $COMPOSE_ID = get_input_value('_id', RCUBE_INPUT_GPC);
-$_SESSION['compose'] = $_SESSION['compose_data_'.$COMPOSE_ID];
+$COMPOSE    =& $_SESSION['compose_data_'.$COMPOSE_ID];
 
 /****** checks ********/
 
 
 /****** checks ********/
 
-if (!isset($_SESSION['compose']['id'])) {
+if (!isset($COMPOSE['id'])) {
   raise_error(array('code' => 500, 'type' => 'php',
     'file' => __FILE__, 'line' => __LINE__,
     'message' => "Invalid compose ID"), true, false);
   raise_error(array('code' => 500, 'type' => 'php',
     'file' => __FILE__, 'line' => __LINE__,
     'message' => "Invalid compose ID"), true, false);
@@ -138,47 +138,47 @@ function rcmail_fix_emoticon_paths(&$mime_message)
   return $body;
 }
 
   return $body;
 }
 
-// parse email address input (and count addresses)
+/**
+ * Parse and cleanup email address input (and count addresses)
+ *
+ * @param string  Address input
+ * @param boolean Do count recipients (saved in global $RECIPIENT_COUNT)
+ * @param boolean Validate addresses (errors saved in global $EMAIL_FORMAT_ERROR)
+ * @return string Canonical recipients string separated by comma
+ */
 function rcmail_email_input_format($mailto, $count=false, $check=true)
 {
 function rcmail_email_input_format($mailto, $count=false, $check=true)
 {
-  global $EMAIL_FORMAT_ERROR, $RECIPIENT_COUNT;
+  global $RCMAIL, $EMAIL_FORMAT_ERROR, $RECIPIENT_COUNT;
 
   // simplified email regexp, supporting quoted local part
   $email_regexp = '(\S+|("[^"]+"))@\S+';
 
 
   // simplified email regexp, supporting quoted local part
   $email_regexp = '(\S+|("[^"]+"))@\S+';
 
-  $regexp  = array('/[,;]\s*[\r\n]+/', '/[\r\n]+/', '/[,;]\s*$/m', '/;/', '/(\S{1})(<'.$email_regexp.'>)/U');
-  $replace = array(', ', ', ', '', ',', '\\1 \\2');
+  $delim = trim($RCMAIL->config->get('recipients_separator', ','));
+  $regexp  = array("/[,;$delim]\s*[\r\n]+/", '/[\r\n]+/', "/[,;$delim]\s*\$/m", '/;/', '/(\S{1})(<'.$email_regexp.'>)/U');
+  $replace = array($delim.' ', ', ', '', $delim, '\\1 \\2');
 
   // replace new lines and strip ending ', ', make address input more valid
   $mailto = trim(preg_replace($regexp, $replace, $mailto));
 
   $result = array();
 
   // replace new lines and strip ending ', ', make address input more valid
   $mailto = trim(preg_replace($regexp, $replace, $mailto));
 
   $result = array();
-  $items = rcube_explode_quoted_string(',', $mailto);
+  $items = rcube_explode_quoted_string($delim, $mailto);
 
   foreach($items as $item) {
     $item = trim($item);
     // address in brackets without name (do nothing)
     if (preg_match('/^<'.$email_regexp.'>$/', $item)) {
 
   foreach($items as $item) {
     $item = trim($item);
     // address in brackets without name (do nothing)
     if (preg_match('/^<'.$email_regexp.'>$/', $item)) {
-      $item = rcube_idn_to_ascii($item);
-      $result[] = $item;
+      $item = rcube_idn_to_ascii(trim($item, '<>'));
+      $result[] = '<' . $item . '>';
     // address without brackets and without name (add brackets)
     } else if (preg_match('/^'.$email_regexp.'$/', $item)) {
       $item = rcube_idn_to_ascii($item);
     // address without brackets and without name (add brackets)
     } else if (preg_match('/^'.$email_regexp.'$/', $item)) {
       $item = rcube_idn_to_ascii($item);
-      $result[] = '<'.$item.'>';
+      $result[] = '<' . $item . '>';
     // address with name (handle name)
     // address with name (handle name)
-    } else if (preg_match('/'.$email_regexp.'>*$/', $item, $matches)) {
+    } else if (preg_match('/<*'.$email_regexp.'>*$/', $item, $matches)) {
       $address = $matches[0];
       $address = $matches[0];
-      $name = str_replace($address, '', $item);
-      $name = trim($name);
-      if ($name && ($name[0] != '"' || $name[strlen($name)-1] != '"')
-          && preg_match('/[\(\)\<\>\\\.\[\]@,;:"]/', $name)) {
-            $name = '"'.addcslashes($name, '"').'"';
-      }
-      $address = rcube_idn_to_ascii($address);
-      if (!preg_match('/^<'.$email_regexp.'>$/', $address))
-        $address = '<'.$address.'>';
-
-      $result[] = $name.' '.$address;
+      $name = trim(str_replace($address, '', $item), '" ');
+      $address = rcube_idn_to_ascii(trim($address, '<>'));
+      $result[] = format_email_recipient($address, $name);
       $item = $address;
     } else if (trim($item)) {
       continue;
       $item = $address;
     } else if (trim($item)) {
       continue;
@@ -340,20 +340,20 @@ if (!empty($headers['Reply-To'])) {
 if (!empty($_POST['_followupto'])) {
   $headers['Mail-Followup-To'] = rcmail_email_input_format(get_input_value('_followupto', RCUBE_INPUT_POST, TRUE, $message_charset));
 }
 if (!empty($_POST['_followupto'])) {
   $headers['Mail-Followup-To'] = rcmail_email_input_format(get_input_value('_followupto', RCUBE_INPUT_POST, TRUE, $message_charset));
 }
-if (!empty($_SESSION['compose']['reply_msgid'])) {
-  $headers['In-Reply-To'] = $_SESSION['compose']['reply_msgid'];
+if (!empty($COMPOSE['reply_msgid'])) {
+  $headers['In-Reply-To'] = $COMPOSE['reply_msgid'];
 }
 
 // remember reply/forward UIDs in special headers
 }
 
 // remember reply/forward UIDs in special headers
-if (!empty($_SESSION['compose']['reply_uid']) && $savedraft) {
-  $headers['X-Draft-Info'] = array('type' => 'reply', 'uid' => $_SESSION['compose']['reply_uid']);
+if (!empty($COMPOSE['reply_uid']) && $savedraft) {
+  $headers['X-Draft-Info'] = array('type' => 'reply', 'uid' => $COMPOSE['reply_uid']);
 }
 }
-else if (!empty($_SESSION['compose']['forward_uid']) && $savedraft) {
-  $headers['X-Draft-Info'] = array('type' => 'forward', 'uid' => $_SESSION['compose']['forward_uid']);
+else if (!empty($COMPOSE['forward_uid']) && $savedraft) {
+  $headers['X-Draft-Info'] = array('type' => 'forward', 'uid' => $COMPOSE['forward_uid']);
 }
 
 }
 
-if (!empty($_SESSION['compose']['references'])) {
-  $headers['References'] = $_SESSION['compose']['references'];
+if (!empty($COMPOSE['references'])) {
+  $headers['References'] = $COMPOSE['references'];
 }
 
 if (!empty($_POST['_priority'])) {
 }
 
 if (!empty($_POST['_priority'])) {
@@ -374,7 +374,7 @@ $headers['Message-ID'] = $message_id;
 $headers['X-Sender'] = $from;
 
 if (is_array($headers['X-Draft-Info'])) {
 $headers['X-Sender'] = $from;
 
 if (is_array($headers['X-Draft-Info'])) {
-  $headers['X-Draft-Info'] = rcmail_draftinfo_encode($headers['X-Draft-Info'] + array('folder' => $_SESSION['compose']['mailbox']));
+  $headers['X-Draft-Info'] = rcmail_draftinfo_encode($headers['X-Draft-Info'] + array('folder' => $COMPOSE['mailbox']));
 }
 if (!empty($CONFIG['useragent'])) {
   $headers['User-Agent'] = $CONFIG['useragent'];
 }
 if (!empty($CONFIG['useragent'])) {
   $headers['User-Agent'] = $CONFIG['useragent'];
@@ -414,12 +414,12 @@ if (!$savedraft) {
 
   // Check spelling before send
   if ($CONFIG['spellcheck_before_send'] && $CONFIG['enable_spellcheck']
 
   // Check spelling before send
   if ($CONFIG['spellcheck_before_send'] && $CONFIG['enable_spellcheck']
-    && empty($_SESSION['compose']['spell_checked']) && !empty($message_body)
+    && empty($COMPOSE['spell_checked']) && !empty($message_body)
   ) {
     $spellchecker = new rcube_spellchecker(get_input_value('_lang', RCUBE_INPUT_GPC));
     $spell_result = $spellchecker->check($message_body, $isHtml);
 
   ) {
     $spellchecker = new rcube_spellchecker(get_input_value('_lang', RCUBE_INPUT_GPC));
     $spell_result = $spellchecker->check($message_body, $isHtml);
 
-    $_SESSION['compose']['spell_checked'] = true;
+    $COMPOSE['spell_checked'] = true;
 
     if (!$spell_result) {
       $result = $isHtml ? $spellchecker->get_words() : $spellchecker->get_xml();
 
     if (!$spell_result) {
       $result = $isHtml ? $spellchecker->get_words() : $spellchecker->get_xml();
@@ -458,12 +458,12 @@ $MAIL_MIME = new Mail_mime("\r\n");
 
 // Check if we have enough memory to handle the message in it
 // It's faster than using files, so we'll do this if we only can
 
 // Check if we have enough memory to handle the message in it
 // It's faster than using files, so we'll do this if we only can
-if (is_array($_SESSION['compose']['attachments']) && $CONFIG['smtp_server']
+if (is_array($COMPOSE['attachments']) && $CONFIG['smtp_server']
   && ($mem_limit = parse_bytes(ini_get('memory_limit'))))
 {
   $memory = function_exists('memory_get_usage') ? memory_get_usage() : 16*1024*1024; // safe value: 16MB
 
   && ($mem_limit = parse_bytes(ini_get('memory_limit'))))
 {
   $memory = function_exists('memory_get_usage') ? memory_get_usage() : 16*1024*1024; // safe value: 16MB
 
-  foreach ($_SESSION['compose']['attachments'] as $id => $attachment)
+  foreach ($COMPOSE['attachments'] as $id => $attachment)
     $memory += $attachment['size'];
 
   // Yeah, Net_SMTP needs up to 12x more memory, 1.33 is for base64
     $memory += $attachment['size'];
 
   // Yeah, Net_SMTP needs up to 12x more memory, 1.33 is for base64
@@ -527,9 +527,9 @@ else {
 }
 
 // add stored attachments, if any
 }
 
 // add stored attachments, if any
-if (is_array($_SESSION['compose']['attachments']))
+if (is_array($COMPOSE['attachments']))
 {
 {
-  foreach ($_SESSION['compose']['attachments'] as $id => $attachment) {
+  foreach ($COMPOSE['attachments'] as $id => $attachment) {
     // This hook retrieves the attachment contents from the file storage backend
     $attachment = $RCMAIL->plugins->exec_hook('attachment_get', $attachment);
 
     // This hook retrieves the attachment contents from the file storage backend
     $attachment = $RCMAIL->plugins->exec_hook('attachment_get', $attachment);
 
@@ -624,12 +624,12 @@ if (!$savedraft)
   // save message sent time
   if (!empty($CONFIG['sendmail_delay']))
     $RCMAIL->user->save_prefs(array('last_message_time' => time()));
   // save message sent time
   if (!empty($CONFIG['sendmail_delay']))
     $RCMAIL->user->save_prefs(array('last_message_time' => time()));
-  
+
   // set replied/forwarded flag
   // set replied/forwarded flag
-  if ($_SESSION['compose']['reply_uid'])
-    $IMAP->set_flag($_SESSION['compose']['reply_uid'], 'ANSWERED', $_SESSION['compose']['mailbox']);
-  else if ($_SESSION['compose']['forward_uid'])
-    $IMAP->set_flag($_SESSION['compose']['forward_uid'], 'FORWARDED', $_SESSION['compose']['mailbox']);
+  if ($COMPOSE['reply_uid'])
+    $IMAP->set_flag($COMPOSE['reply_uid'], 'ANSWERED', $COMPOSE['mailbox']);
+  else if ($COMPOSE['forward_uid'])
+    $IMAP->set_flag($COMPOSE['forward_uid'], 'FORWARDED', $COMPOSE['mailbox']);
 
 } // End of SMTP Delivery Block
 
 
 } // End of SMTP Delivery Block
 
@@ -637,11 +637,10 @@ if (!$savedraft)
 // Determine which folder to save message
 if ($savedraft)
   $store_target = $CONFIG['drafts_mbox'];
 // Determine which folder to save message
 if ($savedraft)
   $store_target = $CONFIG['drafts_mbox'];
-else   
+else
   $store_target = isset($_POST['_store_target']) ? get_input_value('_store_target', RCUBE_INPUT_POST) : $CONFIG['sent_mbox'];
 
   $store_target = isset($_POST['_store_target']) ? get_input_value('_store_target', RCUBE_INPUT_POST) : $CONFIG['sent_mbox'];
 
-if ($store_target)
-  {
+if ($store_target) {
   // check if folder is subscribed
   if ($IMAP->mailbox_exists($store_target, true))
     $store_folder = true;
   // check if folder is subscribed
   if ($IMAP->mailbox_exists($store_target, true))
     $store_folder = true;
@@ -653,11 +652,10 @@ if ($store_target)
 
   // append message to sent box
   if ($store_folder) {
 
   // append message to sent box
   if ($store_folder) {
-
     // message body in file
     if ($mailbody_file || $MAIL_MIME->getParam('delay_file_io')) {
       $headers = $MAIL_MIME->txtHeaders();
     // message body in file
     if ($mailbody_file || $MAIL_MIME->getParam('delay_file_io')) {
       $headers = $MAIL_MIME->txtHeaders();
-      
+
       // file already created
       if ($mailbody_file)
         $msg = $mailbody_file;
       // file already created
       if ($mailbody_file)
         $msg = $mailbody_file;
@@ -666,12 +664,12 @@ if ($store_target)
         $mailbody_file = tempnam($temp_dir, 'rcmMsg');
         if (!PEAR::isError($msg = $MAIL_MIME->saveMessageBody($mailbody_file)))
           $msg = $mailbody_file;
         $mailbody_file = tempnam($temp_dir, 'rcmMsg');
         if (!PEAR::isError($msg = $MAIL_MIME->saveMessageBody($mailbody_file)))
           $msg = $mailbody_file;
-        }
       }
       }
+    }
     else {
       $msg = $MAIL_MIME->getMessage();
       $headers = '';
     else {
       $msg = $MAIL_MIME->getMessage();
       $headers = '';
-      }
+    }
 
     if (PEAR::isError($msg))
       raise_error(array('code' => 650, 'type' => 'php',
 
     if (PEAR::isError($msg))
       raise_error(array('code' => 650, 'type' => 'php',
@@ -680,53 +678,58 @@ if ($store_target)
             TRUE, FALSE);
     else {
       $saved = $IMAP->save_message($store_target, $msg, $headers, $mailbody_file ? true : false);
             TRUE, FALSE);
     else {
       $saved = $IMAP->save_message($store_target, $msg, $headers, $mailbody_file ? true : false);
-      }
+    }
 
     if ($mailbody_file) {
       unlink($mailbody_file);
       $mailbody_file = null;
 
     if ($mailbody_file) {
       unlink($mailbody_file);
       $mailbody_file = null;
-      }
+    }
 
     // raise error if saving failed
     if (!$saved) {
       raise_error(array('code' => 800, 'type' => 'imap',
            'file' => __FILE__, 'line' => __LINE__,
             'message' => "Could not save message in $store_target"), TRUE, FALSE);
 
     // raise error if saving failed
     if (!$saved) {
       raise_error(array('code' => 800, 'type' => 'imap',
            'file' => __FILE__, 'line' => __LINE__,
             'message' => "Could not save message in $store_target"), TRUE, FALSE);
-    
+
       if ($savedraft) {
         $OUTPUT->show_message('errorsaving', 'error');
         $OUTPUT->send('iframe');
       if ($savedraft) {
         $OUTPUT->show_message('errorsaving', 'error');
         $OUTPUT->send('iframe');
-        }
       }
     }
       }
     }
+  }
 
 
-  if ($olddraftmessageid)
-    {
+  if ($olddraftmessageid) {
     // delete previous saved draft
     // delete previous saved draft
+    // @TODO: use message UID (remember to check UIDVALIDITY) to skip this SEARCH
     $a_deleteid = $IMAP->search_once($CONFIG['drafts_mbox'],
         'HEADER Message-ID '.$olddraftmessageid, true);
     $a_deleteid = $IMAP->search_once($CONFIG['drafts_mbox'],
         'HEADER Message-ID '.$olddraftmessageid, true);
-    $deleted = $IMAP->delete_message($a_deleteid, $CONFIG['drafts_mbox']);
 
 
-    // raise error if deletion of old draft failed
-    if (!$deleted)
-      raise_error(array('code' => 800, 'type' => 'imap',
-               'file' => __FILE__, 'line' => __LINE__,
-                'message' => "Could not delete message from ".$CONFIG['drafts_mbox']), TRUE, FALSE);
+    if (!empty($a_deleteid)) {
+      $deleted = $IMAP->delete_message($a_deleteid, $CONFIG['drafts_mbox']);
+
+      // raise error if deletion of old draft failed
+      if (!$deleted)
+        raise_error(array('code' => 800, 'type' => 'imap',
+          'file' => __FILE__, 'line' => __LINE__,
+          'message' => "Could not delete message from ".$CONFIG['drafts_mbox']), TRUE, FALSE);
     }
   }
     }
   }
+}
 // remove temp file
 else if ($mailbody_file) {
   unlink($mailbody_file);
 // remove temp file
 else if ($mailbody_file) {
   unlink($mailbody_file);
-  }
+}
 
 
 
 
-if ($savedraft)
-  {
+if ($savedraft) {
   $msgid = strtr($message_id, array('>' => '', '<' => ''));
   $msgid = strtr($message_id, array('>' => '', '<' => ''));
-  
-  // remember new draft-uid
-  $draftuids = $IMAP->search_once($CONFIG['drafts_mbox'], 'HEADER Message-ID '.$msgid, true);
-  $_SESSION['compose']['param']['draft_uid'] = $draftuids[0];
+
+  // remember new draft-uid ($saved could be an UID or TRUE here)
+  if (is_bool($saved)) {
+    $draftuids = $IMAP->search_once($CONFIG['drafts_mbox'], 'HEADER Message-ID '.$msgid, true);
+    $saved     = $draftuids[0];
+  }
+  $COMPOSE['param']['draft_uid'] = $saved;
 
   // display success
   $OUTPUT->show_message('messagesaved', 'confirmation');
 
   // display success
   $OUTPUT->show_message('messagesaved', 'confirmation');
@@ -739,9 +742,8 @@ if ($savedraft)
   $OUTPUT->command('auto_save_start');
 
   $OUTPUT->send('iframe');
   $OUTPUT->command('auto_save_start');
 
   $OUTPUT->send('iframe');
-  }
-else
-  {
+}
+else {
   rcmail_compose_cleanup($COMPOSE_ID);
 
   if ($store_folder && !$saved)
   rcmail_compose_cleanup($COMPOSE_ID);
 
   if ($store_folder && !$saved)
@@ -749,6 +751,4 @@ else
   else
     $OUTPUT->command('sent_successfully', 'confirmation', rcube_label('messagesent'));
   $OUTPUT->send('iframe');
   else
     $OUTPUT->command('sent_successfully', 'confirmation', rcube_label('messagesent'));
   $OUTPUT->send('iframe');
-  }
-
-
+}
index a1f9977e1e3cac6dd565a5b7ab2b6e5b246398d4..2f28adeb089249f3cd2363aaa0b0d087b24c7e61 100644 (file)
@@ -15,7 +15,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: show.inc 5151 2011-08-31 12:49:44Z alec $
+ $Id: show.inc 5514 2011-11-30 11:35:43Z alec $
 
 */
 
 
 */
 
@@ -30,8 +30,6 @@ if ($uid = get_input_value('_uid', RCUBE_INPUT_GET)) {
     rcmail_message_error($uid);
   }
 
     rcmail_message_error($uid);
   }
 
-  send_nocacheing_headers();
-
   $mbox_name = $IMAP->get_mailbox_name();
 
   // show images?
   $mbox_name = $IMAP->get_mailbox_name();
 
   // show images?
@@ -76,12 +74,13 @@ if ($uid = get_input_value('_uid', RCUBE_INPUT_GET)) {
       'movingmessage', 'deletingmessage');
 
   // check for unset disposition notification
       'movingmessage', 'deletingmessage');
 
   // check for unset disposition notification
-  if ($MESSAGE->headers->mdn_to &&
-      !$MESSAGE->headers->mdn_sent && !$MESSAGE->headers->seen &&
-      ($IMAP->check_permflag('MDNSENT') || $IMAP->check_permflag('*')) &&
-      $mbox_name != $CONFIG['drafts_mbox'] &&
-      $mbox_name != $CONFIG['sent_mbox'])
-  {
+  if ($MESSAGE->headers->mdn_to
+      && empty($MESSAGE->headers->flags['MDNSENT'])
+      && empty($MESSAGE->headers->flags['SEEN'])
+      && ($IMAP->check_permflag('MDNSENT') || $IMAP->check_permflag('*'))
+      && $mbox_name != $CONFIG['drafts_mbox']
+      && $mbox_name != $CONFIG['sent_mbox']
+  ) {
     $mdn_cfg = intval($CONFIG['mdn_requests']);
 
     if ($mdn_cfg == 1 || (($mdn_cfg == 3 || $mdn_cfg ==  4) && rcmail_contact_exists($MESSAGE->sender['mailto']))) {
     $mdn_cfg = intval($CONFIG['mdn_requests']);
 
     if ($mdn_cfg == 1 || (($mdn_cfg == 3 || $mdn_cfg ==  4) && rcmail_contact_exists($MESSAGE->sender['mailto']))) {
@@ -100,9 +99,12 @@ if ($uid = get_input_value('_uid', RCUBE_INPUT_GET)) {
     }
   }
 
     }
   }
 
-  if (!$MESSAGE->headers->seen && ($RCMAIL->action == 'show' || ($RCMAIL->action == 'preview' && intval($CONFIG['preview_pane_mark_read']) == 0)))
+  if (empty($MESSAGE->headers->flags['SEEN'])
+    && ($RCMAIL->action == 'show' || ($RCMAIL->action == 'preview' && intval($CONFIG['preview_pane_mark_read']) == 0))
+  ) {
     $RCMAIL->plugins->exec_hook('message_read', array('uid' => $MESSAGE->uid,
       'mailbox' => $mbox_name, 'message' => $MESSAGE));
     $RCMAIL->plugins->exec_hook('message_read', array('uid' => $MESSAGE->uid,
       'mailbox' => $mbox_name, 'message' => $MESSAGE));
+  }
 }
 
 
 }
 
 
@@ -130,7 +132,7 @@ function rcmail_message_attachments($attrib)
 
         $ol .= html::tag('li', null,
           html::a(array(
 
         $ol .= html::tag('li', null,
           html::a(array(
-            'href' => $MESSAGE->get_part_url($attach_prop->mime_id),
+            'href' => $MESSAGE->get_part_url($attach_prop->mime_id, false),
             'onclick' => sprintf(
               'return %s.command(\'load-attachment\',{part:\'%s\', mimetype:\'%s\'},this)',
               JS_OBJECT_NAME,
             'onclick' => sprintf(
               'return %s.command(\'load-attachment\',{part:\'%s\', mimetype:\'%s\'},this)',
               JS_OBJECT_NAME,
@@ -148,12 +150,13 @@ function rcmail_message_attachments($attrib)
   return $out;
 }
 
   return $out;
 }
 
-function rcmail_remote_objects_msg($attrib)
+function rcmail_remote_objects_msg()
 {
   global $MESSAGE, $RCMAIL;
 
 {
   global $MESSAGE, $RCMAIL;
 
-  if (!$attrib['id'])
-    $attrib['id'] = 'rcmremoteobjmsg';
+  $attrib['id']    = 'remote-objects-message';
+  $attrib['class'] = 'notice';
+  $attrib['style'] = 'display: none';
 
   $msg = Q(rcube_label('blockedimages')) . '&nbsp;';
   $msg .= html::a(array('href' => "#loadimages", 'onclick' => JS_OBJECT_NAME.".command('load-images')"), Q(rcube_label('showimages')));
 
   $msg = Q(rcube_label('blockedimages')) . '&nbsp;';
   $msg .= html::a(array('href' => "#loadimages", 'onclick' => JS_OBJECT_NAME.".command('load-images')"), Q(rcube_label('showimages')));
@@ -168,6 +171,48 @@ function rcmail_remote_objects_msg($attrib)
   return html::div($attrib, $msg);
 }
 
   return html::div($attrib, $msg);
 }
 
+function rcmail_message_buttons()
+{
+  global $MESSAGE, $RCMAIL, $CONFIG;
+
+  $mbox  = $RCMAIL->imap->get_mailbox_name();
+  $delim = $RCMAIL->imap->get_hierarchy_delimiter();
+  $dbox  = $CONFIG['drafts_mbox'];
+
+  // the message is not a draft
+  if ($mbox != $dbox && strpos($mbox, $dbox.$delim) !== 0) {
+    return '';
+  }
+
+  $attrib['id']    = 'message-buttons';
+  $attrib['class'] = 'notice';
+
+  $msg = Q(rcube_label('isdraft')) . '&nbsp;';
+  $msg .= html::a(array('href' => "#edit", 'onclick' => JS_OBJECT_NAME.".command('edit')"), Q(rcube_label('edit')));
+
+  return html::div($attrib, $msg);
+}
+
+function rcmail_message_objects($attrib)
+{
+  global $RCMAIL, $MESSAGE;
+
+  if (!$attrib['id'])
+    $attrib['id'] = 'message-objects';
+
+  $content = array(
+    rcmail_message_buttons(),
+    rcmail_remote_objects_msg(),
+  );
+
+  $plugin = $RCMAIL->plugins->exec_hook('message_objects',
+    array('content' => $content, 'message' => $MESSAGE));
+
+  $content = implode("\n", $plugin['content']);
+
+  return html::div($attrib, $content);
+}
+
 function rcmail_contact_exists($email)
 {
   global $RCMAIL;
 function rcmail_contact_exists($email)
 {
   global $RCMAIL;
@@ -187,7 +232,8 @@ function rcmail_contact_exists($email)
 $OUTPUT->add_handlers(array(
   'messageattachments' => 'rcmail_message_attachments',
   'mailboxname' => 'rcmail_mailbox_name_display',
 $OUTPUT->add_handlers(array(
   'messageattachments' => 'rcmail_message_attachments',
   'mailboxname' => 'rcmail_mailbox_name_display',
-  'blockedobjects' => 'rcmail_remote_objects_msg'));
+  'messageobjects' => 'rcmail_message_objects',
+));
 
 
 if ($RCMAIL->action=='print' && $OUTPUT->template_exists('messageprint'))
 
 
 if ($RCMAIL->action=='print' && $OUTPUT->template_exists('messageprint'))
@@ -199,7 +245,7 @@ else
 
 
 // mark message as read
 
 
 // mark message as read
-if ($MESSAGE && $MESSAGE->headers && !$MESSAGE->headers->seen &&
+if ($MESSAGE && $MESSAGE->headers && empty($MESSAGE->headers->flags['SEEN']) &&
   ($RCMAIL->action == 'show' || ($RCMAIL->action == 'preview' && intval($CONFIG['preview_pane_mark_read']) == 0)))
 {
   if ($IMAP->set_flag($MESSAGE->uid, 'SEEN')) {
   ($RCMAIL->action == 'show' || ($RCMAIL->action == 'preview' && intval($CONFIG['preview_pane_mark_read']) == 0)))
 {
   if ($IMAP->set_flag($MESSAGE->uid, 'SEEN')) {
index 46ccb40e1075684458ae7397580afd5d1b3dff49..e7db49c02b155199e1a853f0af28a33ab9a75577 100644 (file)
@@ -15,7 +15,7 @@
  | Author: Aleksander Machniak <alec@alec.pl>                            |
  +-----------------------------------------------------------------------+
 
  | Author: Aleksander Machniak <alec@alec.pl>                            |
  +-----------------------------------------------------------------------+
 
- $Id: edit_folder.inc 5022 2011-08-04 09:01:36Z alec $
+ $Id: edit_folder.inc 5402 2011-11-09 10:03:54Z alec $
 
 */
 
 
 */
 
@@ -119,7 +119,8 @@ function rcmail_folder_form($attrib)
             'realnames'   => false,
             'maxlength'   => 150,
             'unsubscribed' => true,
             'realnames'   => false,
             'maxlength'   => 150,
             'unsubscribed' => true,
-            'exceptions' => array($mbox_imap),
+            'skip_noinferiors' => true,
+            'exceptions'  => array($mbox_imap),
         ));
 
         $form['props']['fieldsets']['location']['content']['path'] = array(
         ));
 
         $form['props']['fieldsets']['location']['content']['path'] = array(
@@ -134,7 +135,7 @@ function rcmail_folder_form($attrib)
     );
 
     // Settings: threading
     );
 
     // Settings: threading
-    if ($threading_supported && !$options['noselect'] && !$options['is_root']) {
+    if ($threading_supported && ($mbox_imap == 'INBOX' || (!$options['noselect'] && !$options['is_root']))) {
         $select = new html_select(array('name' => '_viewmode', 'id' => '_listmode'));
         $select->add(rcube_label('list'), 0);
         $select->add(rcube_label('threads'), 1);
         $select = new html_select(array('name' => '_viewmode', 'id' => '_listmode'));
         $select->add(rcube_label('list'), 0);
         $select->add(rcube_label('threads'), 1);
@@ -191,7 +192,7 @@ function rcmail_folder_form($attrib)
             'content' => array()
         );
 
             'content' => array()
         );
 
-        if (!$options['noselect'] && !$options['is_root']) {
+        if ((!$options['noselect'] && !$options['is_root']) || $mbox_imap == 'INBOX') {
             $msgcount = $RCMAIL->imap->messagecount($mbox_imap, 'ALL', true, false);
 
             // Size
             $msgcount = $RCMAIL->imap->messagecount($mbox_imap, 'ALL', true, false);
 
             // Size
index 5cc6e0c60c14c4b2bb61b08f98dec2b12314aa75..599fddb7f02d727ba8413f6b26667d1d19796d57 100644 (file)
@@ -15,7 +15,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: edit_identity.inc 4668 2011-04-19 20:41:24Z thomasb $
+ $Id: edit_identity.inc 5139 2011-08-28 09:47:15Z alec $
 
 */
 
 
 */
 
@@ -28,7 +28,7 @@ if (($_GET['_iid'] || $_POST['_iid']) && $RCMAIL->action=='edit-identity') {
   if (is_array($IDENTITY_RECORD))
     $OUTPUT->set_env('iid', $IDENTITY_RECORD['identity_id']);
   else {
   if (is_array($IDENTITY_RECORD))
     $OUTPUT->set_env('iid', $IDENTITY_RECORD['identity_id']);
   else {
-    $OUTPUT->show_message('databaserror', 'error');
+    $OUTPUT->show_message('dberror', 'error');
     // go to identities page
     rcmail_overwrite_action('identities');
     return;
     // go to identities page
     rcmail_overwrite_action('identities');
     return;
index 69339e29a3a09ee5f9fb2f1f275070402bcfc9fe..2cc863ab109b689a95ef6228771ca56bead115c3 100644 (file)
@@ -16,7 +16,7 @@
  | Author: Aleksander Machniak <alec@alec.pl>                            |
  +-----------------------------------------------------------------------+
 
  | Author: Aleksander Machniak <alec@alec.pl>                            |
  +-----------------------------------------------------------------------+
 
- $Id: folders.inc 5091 2011-08-18 18:34:56Z thomasb $
+ $Id: folders.inc 5402 2011-11-09 10:03:54Z alec $
 
 */
 
 
 */
 
@@ -203,7 +203,7 @@ function rcube_subscription_form($attrib)
     $IMAP->clear_cache('mailboxes', true);
 
     $a_unsubscribed = $IMAP->list_unsubscribed();
     $IMAP->clear_cache('mailboxes', true);
 
     $a_unsubscribed = $IMAP->list_unsubscribed();
-    $a_subscribed   = $IMAP->list_mailboxes();
+    $a_subscribed   = $IMAP->list_mailboxes('', '*', null, null, true); // unsorted
     $delimiter      = $IMAP->get_hierarchy_delimiter();
     $namespace      = $IMAP->get_namespace();
     $a_js_folders   = array();
     $delimiter      = $IMAP->get_hierarchy_delimiter();
     $namespace      = $IMAP->get_namespace();
     $a_js_folders   = array();
@@ -283,8 +283,8 @@ function rcube_subscription_form($attrib)
         }
 
         if (!$protected) {
         }
 
         if (!$protected) {
-            $opts = $IMAP->mailbox_options($folder['id']);
-            $noselect = in_array('\\Noselect', $opts);
+            $attrs = $IMAP->mailbox_attributes($folder['id']);
+            $noselect = in_array('\\Noselect', $attrs);
         }
 
         $disabled = (($protected && $subscribed) || $noselect);
         }
 
         $disabled = (($protected && $subscribed) || $noselect);
index 9df9cab54597d2f8b7c87f00f6bfc91e9140e3d2..8df3ce8d3300ad9c5d83f6beab18d6791cd150e9 100644 (file)
@@ -15,7 +15,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: func.inc 4875 2011-06-23 17:43:44Z alec $
+ $Id: func.inc 5481 2011-11-24 07:53:00Z alec $
 
 */
 
 
 */
 
@@ -178,7 +178,7 @@ function rcmail_user_prefs($current=null)
     // show page size selection
     if (!isset($no_override['timezone'])) {
       $field_id = 'rcmfd_timezone';
     // show page size selection
     if (!isset($no_override['timezone'])) {
       $field_id = 'rcmfd_timezone';
-      $select_timezone = new html_select(array('name' => '_timezone', 'id' => $field_id, 'onchange' => "document.getElementById('rcmfd_dst').disabled=this.selectedIndex==0"));
+      $select_timezone = new html_select(array('name' => '_timezone', 'id' => $field_id, 'onchange' => "$('#rcmfd_dst').attr('disabled', this.selectedIndex==0)"));
       $select_timezone->add(rcube_label('autodetect'), 'auto');
       $select_timezone->add('(GMT -11:00) Midway Island, Samoa', '-11');
       $select_timezone->add('(GMT -10:00) Hawaii', '-10');
       $select_timezone->add(rcube_label('autodetect'), 'auto');
       $select_timezone->add('(GMT -11:00) Midway Island, Samoa', '-11');
       $select_timezone->add('(GMT -10:00) Hawaii', '-10');
@@ -237,6 +237,33 @@ function rcmail_user_prefs($current=null)
       );
     }
 
       );
     }
 
+    // date/time formatting
+    if (!isset($no_override['time_format'])) {
+      $reftime = mktime(7,30,0);
+      $field_id = 'rcmfd_time_format';
+      $select_time = new html_select(array('name' => '_time_format', 'id' => $field_id));
+      foreach ((array)$RCMAIL->config->get('time_formats', array('G:i', 'H:i', 'g:i a', 'h:i A')) as $choice)
+        $select_time->add(date($choice, $reftime), $choice);
+
+      $blocks['main']['options']['time_format'] = array(
+        'title' => html::label($field_id, Q(rcube_label('timeformat'))),
+        'content' => $select_time->show($RCMAIL->config->get('time_format')),
+      );
+    }
+
+    if (!isset($no_override['date_format'])) {
+      $refdate = mktime(12,30,0,7,24);
+      $field_id = 'rcmfd_date_format';
+      $select_date = new html_select(array('name' => '_date_format', 'id' => $field_id));
+      foreach ((array)$RCMAIL->config->get('date_formats', array('Y-m-d','d-m-Y','Y/m/d','m/d/Y','d/m/Y','d.m.Y','j.n.Y')) as $choice)
+        $select_date->add(date($choice, $refdate), $choice);
+
+      $blocks['main']['options']['date_format'] = array(
+        'title' => html::label($field_id, Q(rcube_label('dateformat'))),
+        'content' => $select_date->show($config['date_format']),
+      );
+    }
+
     // MM: Show checkbox for toggling 'pretty dates' 
     if (!isset($no_override['prettydate'])) {
       $field_id = 'rcmfd_prettydate';
     // MM: Show checkbox for toggling 'pretty dates' 
     if (!isset($no_override['prettydate'])) {
       $field_id = 'rcmfd_prettydate';
@@ -410,14 +437,15 @@ function rcmail_user_prefs($current=null)
 
     if (!isset($no_override['show_images'])) {
       $field_id = 'rcmfd_show_images';
 
     if (!isset($no_override['show_images'])) {
       $field_id = 'rcmfd_show_images';
-      $input_show_images = new html_select(array('name' => '_show_images', 'id' => $field_id));
+      $input_show_images = new html_select(array('name' => '_show_images', 'id' => $field_id,
+        'disabled' => !$config['prefer_html']));
       $input_show_images->add(rcube_label('never'), 0);
       $input_show_images->add(rcube_label('fromknownsenders'), 1);
       $input_show_images->add(rcube_label('always'), 2);
 
       $blocks['main']['options']['show_images'] = array(
         'title' => html::label($field_id, Q(rcube_label('showremoteimages'))),
       $input_show_images->add(rcube_label('never'), 0);
       $input_show_images->add(rcube_label('fromknownsenders'), 1);
       $input_show_images->add(rcube_label('always'), 2);
 
       $blocks['main']['options']['show_images'] = array(
         'title' => html::label($field_id, Q(rcube_label('showremoteimages'))),
-        'content' => $input_show_images->show($config['show_images']),
+        'content' => $input_show_images->show($config['prefer_html'] ? $config['show_images'] : 0),
       );
     }
 
       );
     }
 
@@ -448,8 +476,9 @@ function rcmail_user_prefs($current=null)
     case 'compose':
 
     $blocks = array(
     case 'compose':
 
     $blocks = array(
-      'main' => array('name' => Q(rcube_label('mainoptions'))),
-      'sig' => array('name' => Q(rcube_label('signatureoptions'))),
+      'main'       => array('name' => Q(rcube_label('mainoptions'))),
+      'spellcheck' => array('name' => Q(rcube_label('spellcheckoptions'))),
+      'sig'        => array('name' => Q(rcube_label('signatureoptions'))),
     );
 
     // Show checkbox for HTML Editor
     );
 
     // Show checkbox for HTML Editor
@@ -549,12 +578,26 @@ function rcmail_user_prefs($current=null)
       $field_id = 'rcmfd_spellcheck_before_send';
       $input_spellcheck = new html_checkbox(array('name' => '_spellcheck_before_send', 'id' => $field_id, 'value' => 1));
 
       $field_id = 'rcmfd_spellcheck_before_send';
       $input_spellcheck = new html_checkbox(array('name' => '_spellcheck_before_send', 'id' => $field_id, 'value' => 1));
 
-      $blocks['main']['options']['spellcheck_before_send'] = array(
+      $blocks['spellcheck']['options']['spellcheck_before_send'] = array(
         'title' => html::label($field_id, Q(rcube_label('spellcheckbeforesend'))),
         'content' => $input_spellcheck->show($config['spellcheck_before_send']?1:0),
       );
     }
 
         'title' => html::label($field_id, Q(rcube_label('spellcheckbeforesend'))),
         'content' => $input_spellcheck->show($config['spellcheck_before_send']?1:0),
       );
     }
 
+    if ($config['enable_spellcheck']) {
+      foreach (array('syms', 'nums', 'caps') as $key) {
+        $key = 'spellcheck_ignore_'.$key;
+        if (!isset($no_override[$key])) {
+          $input_spellcheck = new html_checkbox(array('name' => '_'.$key, 'id' => 'rcmfd_'.$key, 'value' => 1));
+
+          $blocks['spellcheck']['options'][$key] = array(
+            'title' => html::label($field_id, Q(rcube_label(str_replace('_', '', $key)))),
+            'content' => $input_spellcheck->show($config[$key]?1:0),
+          );
+        }
+      }
+    }
+
     if (!isset($no_override['show_sig'])) {
       $field_id = 'rcmfd_show_sig';
       $select_show_sig = new html_select(array('name' => '_show_sig', 'id' => $field_id));
     if (!isset($no_override['show_sig'])) {
       $field_id = 'rcmfd_show_sig';
       $select_show_sig = new html_select(array('name' => '_show_sig', 'id' => $field_id));
@@ -617,6 +660,16 @@ function rcmail_user_prefs($current=null)
       );
     }
 
       );
     }
 
+    if (!isset($no_override['autocomplete_single'])) {
+      $field_id = 'rcmfd_autocomplete_single';
+      $checkbox = new html_checkbox(array('name' => '_autocomplete_single', 'id' => $field_id, 'value' => 1));
+
+      $blocks['main']['options']['autocomplete_single'] = array(
+        'title' => html::label($field_id, Q(rcube_label('autocompletesingle'))),
+        'content' => $checkbox->show($config['autocomplete_single']?1:0),
+      );
+    }
+
     break;
 
     // Special IMAP folders
     break;
 
     // Special IMAP folders
@@ -634,7 +687,7 @@ function rcmail_user_prefs($current=null)
       // load folders list only when needed
       if ($current) {
         $select = rcmail_mailbox_select(array('noselection' => '---', 'realnames' => true,
       // load folders list only when needed
       if ($current) {
         $select = rcmail_mailbox_select(array('noselection' => '---', 'realnames' => true,
-          'maxlength' => 30, 'exceptions' => array('INBOX')));
+          'maxlength' => 30, 'exceptions' => array('INBOX'), 'folder_filter' => 'mail', 'folder_rights' => 'w'));
       }
       else // dummy select
         $select = new html_select();
       }
       else // dummy select
         $select = new html_select();
index 27d94b3289b67b02eb512e8fb9e4e66b1037bba5..7af2c316e5355747394309816c0a7dd6d4d91d1b 100644 (file)
@@ -15,7 +15,7 @@
  | Author: Aleksander Machniak <alec@alec.pl>                            |
  +-----------------------------------------------------------------------+
 
  | Author: Aleksander Machniak <alec@alec.pl>                            |
  +-----------------------------------------------------------------------+
 
- $Id: save_folder.inc 5102 2011-08-19 16:32:38Z thomasb $
+ $Id: save_folder.inc 5096 2011-08-19 08:07:05Z alec $
 
 */
 
 
 */
 
index e5dfdd9fc7022f1a5531ab8f7634b040a6439956..2fefef193e1dec081f8c273a812e218f1e0c85ea 100644 (file)
@@ -15,7 +15,7 @@
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  +-----------------------------------------------------------------------+
 
- $Id: save_prefs.inc 5151 2011-08-31 12:49:44Z alec $
+ $Id: save_prefs.inc 5543 2011-12-05 07:24:36Z alec $
 
 */
 
 
 */
 
@@ -32,9 +32,17 @@ switch ($CURR_SECTION)
       'timezone'     => isset($_POST['_timezone']) ? (is_numeric($_POST['_timezone']) ? floatval($_POST['_timezone']) : get_input_value('_timezone', RCUBE_INPUT_POST)) : $CONFIG['timezone'],
       'dst_active'   => isset($_POST['_dst_active']) ? TRUE : FALSE,
       'pagesize'     => is_numeric($_POST['_pagesize']) ? max(2, intval($_POST['_pagesize'])) : $CONFIG['pagesize'],
       'timezone'     => isset($_POST['_timezone']) ? (is_numeric($_POST['_timezone']) ? floatval($_POST['_timezone']) : get_input_value('_timezone', RCUBE_INPUT_POST)) : $CONFIG['timezone'],
       'dst_active'   => isset($_POST['_dst_active']) ? TRUE : FALSE,
       'pagesize'     => is_numeric($_POST['_pagesize']) ? max(2, intval($_POST['_pagesize'])) : $CONFIG['pagesize'],
+      'date_format'  => isset($_POST['_date_format']) ? get_input_value('_date_format', RCUBE_INPUT_POST) : $CONFIG['date_format'],
+      'time_format'  => isset($_POST['_time_format']) ? get_input_value('_time_format', RCUBE_INPUT_POST) : ($CONFIG['time_format'] ? $CONFIG['time_format'] : 'H:i'),
       'prettydate'   => isset($_POST['_pretty_date']) ? TRUE : FALSE,
       'skin'        => isset($_POST['_skin']) ? get_input_value('_skin', RCUBE_INPUT_POST) : $CONFIG['skin'],
     );
       'prettydate'   => isset($_POST['_pretty_date']) ? TRUE : FALSE,
       'skin'        => isset($_POST['_skin']) ? get_input_value('_skin', RCUBE_INPUT_POST) : $CONFIG['skin'],
     );
+    
+    // compose derived date/time format strings
+    if ((isset($_POST['_date_format']) || isset($_POST['_time_format'])) && $a_user_prefs['date_format'] && $a_user_prefs['time_format']) {
+      $a_user_prefs['date_short'] = 'D ' . $a_user_prefs['time_format'];
+      $a_user_prefs['date_long'] = $a_user_prefs['date_format'] . ' ' . $a_user_prefs['time_format'];
+    }
 
   break;
 
 
   break;
 
@@ -71,6 +79,9 @@ switch ($CURR_SECTION)
       'dsn_default'        => isset($_POST['_dsn_default']) ? TRUE : FALSE,
       'reply_same_folder'  => isset($_POST['_reply_same_folder']) ? TRUE : FALSE,
       'spellcheck_before_send' => isset($_POST['_spellcheck_before_send']) ? TRUE : FALSE,
       'dsn_default'        => isset($_POST['_dsn_default']) ? TRUE : FALSE,
       'reply_same_folder'  => isset($_POST['_reply_same_folder']) ? TRUE : FALSE,
       'spellcheck_before_send' => isset($_POST['_spellcheck_before_send']) ? TRUE : FALSE,
+      'spellcheck_ignore_syms' => isset($_POST['_spellcheck_ignore_syms']) ? TRUE : FALSE,
+      'spellcheck_ignore_nums' => isset($_POST['_spellcheck_ignore_nums']) ? TRUE : FALSE,
+      'spellcheck_ignore_caps' => isset($_POST['_spellcheck_ignore_caps']) ? TRUE : FALSE,
       'show_sig'           => isset($_POST['_show_sig']) ? intval($_POST['_show_sig']) : 1,
       'top_posting'        => !empty($_POST['_top_posting']),
       'strip_existing_sig' => isset($_POST['_strip_existing_sig']),
       'show_sig'           => isset($_POST['_show_sig']) ? intval($_POST['_show_sig']) : 1,
       'top_posting'        => !empty($_POST['_top_posting']),
       'strip_existing_sig' => isset($_POST['_strip_existing_sig']),
@@ -82,6 +93,7 @@ switch ($CURR_SECTION)
   case 'addressbook':
     $a_user_prefs = array(
       'default_addressbook' => get_input_value('_default_addressbook', RCUBE_INPUT_POST, true),
   case 'addressbook':
     $a_user_prefs = array(
       'default_addressbook' => get_input_value('_default_addressbook', RCUBE_INPUT_POST, true),
+      'autocomplete_single' => isset($_POST['_autocomplete_single']) ? TRUE : FALSE,
     );
 
   break;
     );
 
   break;
@@ -133,6 +145,8 @@ switch ($CURR_SECTION)
     // switch skin (if valid, otherwise unset the pref and fall back to default)
     if (!$OUTPUT->set_skin($a_user_prefs['skin']))
       unset($a_user_prefs['skin']);
     // switch skin (if valid, otherwise unset the pref and fall back to default)
     if (!$OUTPUT->set_skin($a_user_prefs['skin']))
       unset($a_user_prefs['skin']);
+    else if ($RCMAIL->config->get('skin') != $a_user_prefs['skin'])
+      $OUTPUT->command('reload', 500);
 
     // force min size
     if ($a_user_prefs['pagesize'] < 1)
 
     // force min size
     if ($a_user_prefs['pagesize'] < 1)
@@ -167,7 +181,7 @@ switch ($CURR_SECTION)
           $a_user_prefs['default_imap_folders'][] = $a_user_prefs[$p];
       }
     }
           $a_user_prefs['default_imap_folders'][] = $a_user_prefs[$p];
       }
     }
-  
+
   break;
 }
 
   break;
 }
 
index 73c6c979c8b951f03c08306024b93e89b0081fc0..fd366a3aa2abf892726a0228da7093ef90c51042 100644 (file)
@@ -9,13 +9,13 @@
  | Licensed under the GNU GPL                                            |
  |                                                                       |
  | PURPOSE:                                                              |
  | Licensed under the GNU GPL                                            |
  |                                                                       |
  | PURPOSE:                                                              |
- |   Delete rows from cache and messages tables                          |
+ |   Delete rows from cache tables                                       |
  |                                                                       |
  +-----------------------------------------------------------------------+
  | Author: Dennis P. Nikolaenko <dennis@nikolaenko.ru>                   |
  +-----------------------------------------------------------------------+
 
  |                                                                       |
  +-----------------------------------------------------------------------+
  | Author: Dennis P. Nikolaenko <dennis@nikolaenko.ru>                   |
  +-----------------------------------------------------------------------+
 
- $Id: killcache.inc 4410 2011-01-12 18:25:02Z thomasb $
+ $Id: killcache.inc 5578 2011-12-09 07:23:04Z alec $
 
 */
 
 
 */
 
@@ -41,12 +41,20 @@ if (PEAR::isError($res)) {
     exit($res->getMessage());
 }
 
     exit($res->getMessage());
 }
 
-$res = $RCMAIL->db->query("DELETE FROM messages");
+$res = $RCMAIL->db->query("DELETE FROM cache_messages");
 if (PEAR::isError($res)) {
     exit($res->getMessage());
 }
 
 if (PEAR::isError($res)) {
     exit($res->getMessage());
 }
 
-echo "Cache cleared\n";
-exit;
+$res = $RCMAIL->db->query("DELETE FROM cache_index");
+if (PEAR::isError($res)) {
+    exit($res->getMessage());
+}
 
 
+$res = $RCMAIL->db->query("DELETE FROM cache_thread");
+if (PEAR::isError($res)) {
+    exit($res->getMessage());
+}
 
 
+echo "Cache cleared\n";
+exit;
index b45ff39d051768b23c35d41ac18973be4ab666cd..65623ecb558cf266ac91309b441cefe8a26c9836 100644 (file)
@@ -15,7 +15,7 @@
  | Author: Kris Steinhoff <steinhof@umich.edu>                           |
  +-----------------------------------------------------------------------+
 
  | Author: Kris Steinhoff <steinhof@umich.edu>                           |
  +-----------------------------------------------------------------------+
 
- $Id: spell.inc 4815 2011-05-30 15:08:26Z alec $
+ $Id: spell.inc 5181 2011-09-06 13:39:45Z alec $
 
 */
 
 
 */
 
@@ -23,6 +23,8 @@
 $lang = get_input_value('lang', RCUBE_INPUT_GET);
 $data = file_get_contents('php://input');
 
 $lang = get_input_value('lang', RCUBE_INPUT_GET);
 $data = file_get_contents('php://input');
 
+$learn_word = strpos($data, '<learnword>');
+
 // Get data string
 $left = strpos($data, '<text>');
 $right = strrpos($data, '</text>');
 // Get data string
 $left = strpos($data, '<text>');
 $right = strrpos($data, '</text>');
@@ -30,8 +32,15 @@ $data = substr($data, $left+6, $right-($left+6));
 $data = html_entity_decode($data, ENT_QUOTES, RCMAIL_CHARSET);
 
 $spellchecker = new rcube_spellchecker($lang);
 $data = html_entity_decode($data, ENT_QUOTES, RCMAIL_CHARSET);
 
 $spellchecker = new rcube_spellchecker($lang);
-$spellchecker->check($data);
-$result = $spellchecker->get_xml();
+
+if ($learn_word) {
+    $spellchecker->add_word($data);
+    $result = '<?xml version="1.0" encoding="'.RCMAIL_CHARSET.'"?><learnwordresult></learnwordresult>';
+}
+else {
+    $spellchecker->check($data);
+    $result = $spellchecker->get_xml();
+}
 
 // set response length
 header("Content-Length: " . strlen($result));
 
 // set response length
 header("Content-Length: " . strlen($result));
index d0324c6176174f36aa6be59ef4341e44f09e3b47..4567e13ba83a227205067c5d52d39dcb36d56c13 100644 (file)
@@ -15,7 +15,7 @@
  | Author: Aleksander Machniak <alec@alec.pl>                            |
  +-----------------------------------------------------------------------+
 
  | Author: Aleksander Machniak <alec@alec.pl>                            |
  +-----------------------------------------------------------------------+
 
- $Id: spell_html.inc 4815 2011-05-30 15:08:26Z alec $
+ $Id: spell_html.inc 5181 2011-09-06 13:39:45Z alec $
 
 */
 
 
 */
 
@@ -40,6 +40,10 @@ if ($request['method'] == 'checkWords') {
 else if ($request['method'] == 'getSuggestions') {
     $result['result'] = $spellchecker->get_suggestions($data);
 }
 else if ($request['method'] == 'getSuggestions') {
     $result['result'] = $spellchecker->get_suggestions($data);
 }
+else if ($request['method'] == 'learnWord') {
+    $spellchecker->add_word($data);
+    $result['result'] = true;
+}
 
 if ($error = $spellchecker->error()) {
     echo '{"error":{"errstr":"' . addslashes($error) . '","errfile":"","errline":null,"errcontext":"","level":"FATAL"}}';
 
 if ($error = $spellchecker->error()) {
     echo '{"error":{"errstr":"' . addslashes($error) . '","errfile":"","errline":null,"errcontext":"","level":"FATAL"}}';
index f3b52c806f729e8e5f1827ab24c1a508f41d5b56..c604c7549412866b1dbcb98430a5c2715c3917d1 100644 (file)
 
 #directorylistbox input
 {
 
 #directorylistbox input
 {
-  margin: 2px;
+  margin: 0px;
+  font-size: 11px;
   width: 90%;
 }
 
   width: 90%;
 }
 
 #directorylist li.contactgroup
 {
   padding-left: 15px;
 #directorylist li.contactgroup
 {
   padding-left: 15px;
-  background-position: 20px -144px;
+  background-position: 20px -143px;
+}
+
+#directorylist li.contactsearch
+{
+  background-position: 6px -162px;
 }
 
 #directorylist li.selected
 }
 
 #directorylist li.selected
index f5b1d3de92693908e9e95fb02b54a1845b95a589..bf00dc35177a25772f0f1e5c1004f08e71e407c8 100644 (file)
@@ -2,9 +2,11 @@
 
 body
 {
 
 body
 {
+  font-family: "Lucida Grande", Verdana, Arial, Helvetica, sans-serif;
   margin: 8px;
   background-color: #F6F6F6;
   margin: 8px;
   background-color: #F6F6F6;
-  color: #000000;
+  color: #000;
+  font-size: 12px;
 }
 
 body.iframe
 }
 
 body.iframe
@@ -18,10 +20,10 @@ body.extwin
   margin: 10px;
 }
 
   margin: 10px;
 }
 
-body, td, th, div, p, h3, select, input, textarea
+td, th, div, p, select, input, textarea
 {
 {
-  font-family: "Lucida Grande", Verdana, Arial, Helvetica, sans-serif;
   font-size: 12px;
   font-size: 12px;
+  font-family: inherit;
 }
 
 th
 }
 
 th
@@ -36,13 +38,13 @@ h3
 
 a, a:active, a:visited
 {
 
 a, a:active, a:visited
 {
-  color: #000000;
+  color: #000;
   outline: none;
 }
 
 a.button, a.button:visited, a.tab, a.tab:visited, a.axislist
 {
   outline: none;
 }
 
 a.button, a.button:visited, a.tab, a.tab:visited, a.axislist
 {
-  color: #000000;
+  color: #000;
   text-decoration: none;
 }
 
   text-decoration: none;
 }
 
@@ -56,7 +58,7 @@ a.tab
 hr
 {
   height: 1px;
 hr
 {
   height: 1px;
-  background-color: #666666;
+  background-color: #666;
   border-style: none;
 }
 
   border-style: none;
 }
 
@@ -65,9 +67,9 @@ input[type="button"],
 input[type="password"],
 textarea
 {
 input[type="password"],
 textarea
 {
-  border: 1px solid #666666;
-  color: #333333;
-  background-color: #ffffff;
+  border: 1px solid #666;
+  color: #333;
+  background-color: #FFF;
 }
 
 input, textarea
 }
 
 input, textarea
@@ -230,7 +232,7 @@ img
 }
 
 #message div.notice,
 }
 
 #message div.notice,
-#remote-objects-message
+#message-objects div.notice
 {
   background: url(images/display/icons.png) 6px 3px no-repeat;
   background-color: #F7FDCB;
 {
   background: url(images/display/icons.png) 6px 3px no-repeat;
   background-color: #F7FDCB;
@@ -238,21 +240,25 @@ img
 }
 
 #message div.error,
 }
 
 #message div.error,
-#message div.warning
+#message div.warning,
+#message-objects div.warning,
+#message-objects div.error
 {
   background: url(images/display/icons.png) 6px -97px no-repeat;
   background-color: #EF9398;
   border: 1px solid #DC5757;
 }
 
 {
   background: url(images/display/icons.png) 6px -97px no-repeat;
   background-color: #EF9398;
   border: 1px solid #DC5757;
 }
 
-#message div.confirmation
+#message div.confirmation,
+#message-objects div.confirmation
 {
   background: url(images/display/icons.png) 6px -47px no-repeat;
   background-color: #A6EF7B;
   border: 1px solid #76C83F;
 }
 
 {
   background: url(images/display/icons.png) 6px -47px no-repeat;
   background-color: #A6EF7B;
   border: 1px solid #76C83F;
 }
 
-#message div.loading
+#message div.loading,
+#message-objects div.loading
 {
   background: url(images/display/loading.gif) 6px 3px no-repeat;
   background-color: #EBEBEB;
 {
   background: url(images/display/loading.gif) 6px 3px no-repeat;
   background-color: #EBEBEB;
@@ -279,6 +285,9 @@ img
   font-size: 11px;
   font-weight: bold;
   overflow: hidden;
   font-size: 11px;
   font-weight: bold;
   overflow: hidden;
+  text-overflow: ellipsis;
+  -o-text-overflow: ellipsis;
+  white-space: nowrap;
   background: url(images/listheader.gif) top left repeat-x #CCC;
 }
 
   background: url(images/listheader.gif) top left repeat-x #CCC;
 }
 
@@ -738,7 +747,7 @@ a.rcmContactAddress:hover
   margin: auto;
 }
 
   margin: auto;
 }
 
-#rcmloginuser, #rcmloginpwd, #rcmloginhost
+#login-form table td.input input
 {
   width: 200px;
 }
 {
   width: 200px;
 }
index 2ddc87fe97352f968db7ca0dce3722fd4b5b12a7..aabed07b5798d894c6728abf7a9b1aea5295a13f 100644 (file)
@@ -1,5 +1,4 @@
 /* This file contains the CSS data for the editable area(iframe) of TinyMCE */
 /* This file contains the CSS data for the editable area(iframe) of TinyMCE */
-/* You can extend this CSS by adding your own CSS file with the the content_css option */
 
 body, td, pre {
        font-family: "Lucida Grande", Verdana,  Arial, Helvetica, sans-serif;
 
 body, td, pre {
        font-family: "Lucida Grande", Verdana,  Arial, Helvetica, sans-serif;
@@ -25,8 +24,8 @@ pre
 
 blockquote
 {
 
 blockquote
 {
-       padding-left:5px;
-       border-left:#1010ff 2px solid;
-       margin-left:5px;
-       width:100%;
+       padding-left: 5px;
+       border-left: #1010ff 2px solid;
+       margin-left: 5px;
+       width: 100%;
 }
 }
index 32c0a73688d6466f0f9f5d803ac96cc0ecc3ce7a..8482e375a8af082b7dd39f02738c53e4613fa927 100644 (file)
@@ -108,8 +108,13 @@ function rcube_mail_ui()
 
 rcube_mail_ui.prototype = {
 
 
 rcube_mail_ui.prototype = {
 
-show_popup: function(popup, show)
+show_popup: function(popup, show, config)
 {
 {
+  var obj;
+  // auto-register menu object
+  if (!this.popups[popup] && (obj = $('#'+popup)) && obj.length)
+    this.popups[popup] = $.extend(config, {id: popup, obj: obj});
+
   if (typeof this[popup] == 'function')
     return this[popup](show);
   else
   if (typeof this[popup] == 'function')
     return this[popup](show);
   else
@@ -141,7 +146,7 @@ show_popupmenu: function(popup, show)
   }
 
   obj[show?'show':'hide']();
   }
 
   obj[show?'show':'hide']();
-  
+
   if (bw.ie6 && this.popups[popup].overlap) {
     $('select').css('visibility', show?'hidden':'inherit');
     $('select', obj).css('visibility', 'inherit');
   if (bw.ie6 && this.popups[popup].overlap) {
     $('select').css('visibility', show?'hidden':'inherit');
     $('select', obj).css('visibility', 'inherit');
@@ -187,29 +192,32 @@ searchmenu: function(show)
 
   if (show && ref) {
     var pos = $(ref).offset();
 
   if (show && ref) {
     var pos = $(ref).offset();
-    obj.css({ left:pos.left, top:(pos.top + ref.offsetHeight + 2)})
-        .find(':checked').prop('checked', false);
+    obj.css({left:pos.left, top:(pos.top + ref.offsetHeight + 2)});
 
     if (rcmail.env.search_mods) {
 
     if (rcmail.env.search_mods) {
-      var n, mbox = rcmail.env.mailbox, mods = rcmail.env.search_mods;
+      var n, all,
+        list = $('input:checkbox[name="s_mods[]"]', obj),
+        mbox = rcmail.env.mailbox,
+        mods = rcmail.env.search_mods;
 
 
-      if (rcmail.env.task != 'addressbook') {
+      if (rcmail.env.task == 'mail') {
         mods = mods[mbox] ? mods[mbox] : mods['*'];
         mods = mods[mbox] ? mods[mbox] : mods['*'];
+        all = 'text';
+      }
+      else {
+        all = '*';
+      }
 
 
+      if (mods[all])
+        list.map(function() {
+          this.checked = true;
+          this.disabled = this.value != all;
+        });
+      else {
+        list.prop('disabled', false).prop('checked', false);
         for (n in mods)
           $('#s_mod_' + n).prop('checked', true);
       }
         for (n in mods)
           $('#s_mod_' + n).prop('checked', true);
       }
-      else {
-        if (mods['*'])
-          $('input:checkbox[name="s_mods[]"]').map(function() {
-            this.checked = true;
-            this.disabled = this.value != '*';
-          });
-        else {
-          for (n in mods)
-            $('#s_mod_' + n).prop('checked', true);
-        }
-      }
     }
   }
   obj[show?'show':'hide']();
     }
   }
   obj[show?'show':'hide']();
@@ -217,7 +225,7 @@ searchmenu: function(show)
 
 set_searchmod: function(elem)
 {
 
 set_searchmod: function(elem)
 {
-  var task = rcmail.env.task,
+  var all, m, task = rcmail.env.task,
     mods = rcmail.env.search_mods,
     mbox = rcmail.env.mailbox;
 
     mods = rcmail.env.search_mods,
     mbox = rcmail.env.mailbox;
 
@@ -227,36 +235,37 @@ set_searchmod: function(elem)
   if (task == 'mail') {
     if (!mods[mbox])
       mods[mbox] = rcube_clone_object(mods['*']);
   if (task == 'mail') {
     if (!mods[mbox])
       mods[mbox] = rcube_clone_object(mods['*']);
-    if (!elem.checked)
-      delete(mods[mbox][elem.value]);
-    else
-      mods[mbox][elem.value] = 1;
+    m = mods[mbox];
+    all = 'text';
   }
   else { //addressbook
   }
   else { //addressbook
-    if (!elem.checked)
-      delete(mods[elem.value]);
-    else
-      mods[elem.value] = 1;
+    m = mods;
+    all = '*';
+  }
 
 
-    // mark all fields
-    if (elem.value == '*') {
-      $('input:checkbox[name="s_mods[]"]').map(function() {
-        if (this == elem)
-          return;
+  if (!elem.checked)
+    delete(m[elem.value]);
+  else
+    m[elem.value] = 1;
 
 
-        if (elem.checked) {
-          mods[this.value] = 1;
-          this.checked = true;
-          this.disabled = true;
-        }
-        else {
-          this.disabled = false;
-        }
-      });
-    }
-  }
+  // mark all fields
+  if (elem.value != all)
+    return;
+
+  $('input:checkbox[name="s_mods[]"]').map(function() {
+    if (this == elem)
+      return;
 
 
-  rcmail.env.search_mods = mods;
+    this.checked = true;
+    if (elem.checked) {
+      this.disabled = true;
+      delete m[this.value];
+    }
+    else {
+      this.disabled = false;
+      m[this.value] = 1;
+    }
+  });
 },
 
 listmenu: function(show)
 },
 
 listmenu: function(show)
@@ -561,7 +570,6 @@ function rcube_init_mail_ui()
       rcmail.addEventListener('responseaftergetunread', rcube_render_mailboxlist);
       rcmail.addEventListener('responseaftercheck-recent', rcube_render_mailboxlist);
       rcmail.addEventListener('aftercollapse-folder', rcube_render_mailboxlist);
       rcmail.addEventListener('responseaftergetunread', rcube_render_mailboxlist);
       rcmail.addEventListener('responseaftercheck-recent', rcube_render_mailboxlist);
       rcmail.addEventListener('aftercollapse-folder', rcube_render_mailboxlist);
-      rcube_render_mailboxlist();
     }
 
     if (rcmail.env.action == 'compose')
     }
 
     if (rcmail.env.action == 'compose')
@@ -583,12 +591,16 @@ function iframe_events()
 // Abbreviate mailbox names to fit width of the container
 function rcube_render_mailboxlist()
 {
 // Abbreviate mailbox names to fit width of the container
 function rcube_render_mailboxlist()
 {
-  if (bw.ie6)  // doesn't work well on IE6
+  var list = $('#mailboxlist > li a, #mailboxlist ul:visible > li a');
+
+  // it's too slow with really big number of folders, especially on IE
+  if (list.length > 500 * (bw.ie ? 0.2 : 1))
     return;
 
     return;
 
-  $('#mailboxlist > li a, #mailboxlist ul:visible > li a').each(function(){
-    var elem = $(this);
-    var text = elem.data('text');
+  list.each(function(){
+    var elem = $(this),
+      text = elem.data('text');
+
     if (!text) {
       text = elem.text().replace(/\s+\(.+$/, '');
       elem.data('text', text);
     if (!text) {
       text = elem.text().replace(/\s+\(.+$/, '');
       elem.data('text', text);
@@ -606,34 +618,45 @@ function rcube_render_mailboxlist()
 // inspired by https://gist.github.com/24261/7fdb113f1e26111bd78c0c6fe515f6c0bf418af5
 function fit_string_to_size(str, elem, len)
 {
 // inspired by https://gist.github.com/24261/7fdb113f1e26111bd78c0c6fe515f6c0bf418af5
 function fit_string_to_size(str, elem, len)
 {
-    var result = str;
-    var ellip = '...';
-    var span = $('<b>').css({ visibility:'hidden', padding:'0px' }).appendTo(elem).get(0);
-
-    // on first run, check if string fits into the length already.
-    span.innerHTML = result;
-    if (span.offsetWidth > len) {
-        var cut = Math.max(1, Math.floor(str.length * ((span.offsetWidth - len) / span.offsetWidth) / 2)),
-          mid = Math.floor(str.length / 2);
-        var offLeft = mid, offRight = mid;
-        while (true) {
-            offLeft = mid - cut;
-            offRight = mid + cut;
-            span.innerHTML = str.substring(0,offLeft) + ellip + str.substring(offRight);
-
-            // break loop if string fits size
-            if (span.offsetWidth <= len || offLeft < 3)
-              break;
-
-            cut++;
-        }
-
-        // build resulting string
-        result = str.substring(0,offLeft) + ellip + str.substring(offRight);
+  var w, span, result = str, ellip = '...';
+
+  if (!rcmail.env.tmp_span) {
+    // it should be appended to elem to use the same css style
+    // but for performance reasons we'll append it to body (once)
+    span = $('<b>').css({visibility: 'hidden', padding: '0px'})
+      .appendTo($('body', document)).get(0);
+    rcmail.env.tmp_span = span;
+  }
+  else {
+    span = rcmail.env.tmp_span;
+  }
+  span.innerHTML = result;
+
+  // on first run, check if string fits into the length already.
+  w = span.offsetWidth;
+  if (w > len) {
+    var cut = Math.max(1, Math.floor(str.length * ((w - len) / w) / 2)),
+      mid = Math.floor(str.length / 2),
+      offLeft = mid,
+      offRight = mid;
+
+    while (true) {
+      offLeft = mid - cut;
+      offRight = mid + cut;
+      span.innerHTML = str.substring(0,offLeft) + ellip + str.substring(offRight);
+
+      // break loop if string fits size
+      if (offLeft < 3 || span.offsetWidth)
+        break;
+
+      cut++;
     }
     }
-    
-    span.parentNode.removeChild(span);
-    return result;
+
+    // build resulting string
+    result = str.substring(0,offLeft) + ellip + str.substring(offRight);
+  }
+
+  return result;
 }
 
 // Optional parameters used by TinyMCE
 }
 
 // Optional parameters used by TinyMCE
index bfdb6f08733c042e8c45fd29905fbc0b8cd2be49..dc7f24a2eec496ee7b6c7e1fb58421b97bb9ba5a 100644 (file)
@@ -20,7 +20,10 @@ img
 #message div.error,
 #message div.warning,
 #message div.confirmation,
 #message div.error,
 #message div.warning,
 #message div.confirmation,
-#remote-objects-message
+#message-objects div.notice,
+#message-objects div.error,
+#message-objects div.warning,
+#message-objects div.confirmation
 {
   background-image: url(images/display/icons.gif);
 }
 {
   background-image: url(images/display/icons.gif);
 }
@@ -131,6 +134,12 @@ ul.toolbarmenu li.separator_below
 #messagelist tr td.threads div.listmenu,
 #messagelist tr td.attachment span.attachment,
 #messagelist tr td.attachment span.report,
 #messagelist tr td.threads div.listmenu,
 #messagelist tr td.attachment span.attachment,
 #messagelist tr td.attachment span.report,
+#messagelist tr td.priority span.priority,
+#messagelist tr td.priority span.prio1,
+#messagelist tr td.priority span.prio2,
+#messagelist tr td.priority span.prio3,
+#messagelist tr td.priority span.prio4,
+#messagelist tr td.priority span.prio5,
 #messagelist tr td.flag span.flagged,
 #messagelist tr td.flag span.unflagged:hover,
 #messagelist tr td.status span.status,
 #messagelist tr td.flag span.flagged,
 #messagelist tr td.flag span.unflagged:hover,
 #messagelist tr td.status span.status,
index 0fccb2c18a1d19c7d537552a7c3713123c3726d3..eb06bd8c10d560461a89af7eabe9214f1f93e897 100644 (file)
Binary files a/skins/default/images/icons/folders.gif and b/skins/default/images/icons/folders.gif differ
index 5013318f8584a6c7d9661d2d3d7ffa245e0b4475..2580fd1be79a1ed4dc127a343ba7c7f487ed082b 100644 (file)
Binary files a/skins/default/images/icons/folders.png and b/skins/default/images/icons/folders.png differ
index 60526f1f32df297cb9b4297e0c6d713b75d1705a..80423dd1e50f2fe04b9fc64aa7262c851e83af8f 100644 (file)
Binary files a/skins/default/images/messageicons.gif and b/skins/default/images/messageicons.gif differ
index 3dd37606ef47683abc6924942580314a981dee47..d45f065ea2b62f50594339a85e1372593e671122 100644 (file)
Binary files a/skins/default/images/messageicons.png and b/skins/default/images/messageicons.png differ
index f670182a02d3f8d1c2898d4688963002c5522850..57bed8a34af86c7de33f7ff6f6770b262f19a91c 100644 (file)
@@ -19,7 +19,7 @@
 <roundcube:if condition="template:name == 'mail'" />
 <roundcube:button name="markmenulink" id="markmenulink" type="link" class="button markmessage" title="markmessages" onclick="rcmail_ui.show_popup('markmenu');return false" content=" " />                                                                   
 <roundcube:endif />
 <roundcube:if condition="template:name == 'mail'" />
 <roundcube:button name="markmenulink" id="markmenulink" type="link" class="button markmessage" title="markmessages" onclick="rcmail_ui.show_popup('markmenu');return false" content=" " />                                                                   
 <roundcube:endif />
-<roundcube:button name="messagemenulink" id="messagemenulink" type="link" class="button messagemenu" title="messageactions" onclick="rcmail_ui.show_popup('messagemenu');return false" content=" " />
+<roundcube:button name="messagemenulink" id="messagemenulink" type="link" class="button messagemenu" title="moreactions" onclick="rcmail_ui.show_popup('messagemenu');return false" content=" " />
 <roundcube:if condition="template:name == 'message'" />
 <roundcube:object name="mailboxlist" type="select" noSelection="moveto" maxlength="25" onchange="rcmail.command('moveto', this.options[this.selectedIndex].value)" class="mboxlist" folder_filter="mail" />
 <roundcube:endif />
 <roundcube:if condition="template:name == 'message'" />
 <roundcube:object name="mailboxlist" type="select" noSelection="moveto" maxlength="25" onchange="rcmail.command('moveto', this.options[this.selectedIndex].value)" class="mboxlist" folder_filter="mail" />
 <roundcube:endif />
index a4ae57d2ef13bca626be7d86efe132a5fd9397d0..4dfc206741146bdb1508c52cf051e94b841ec22a 100644 (file)
   padding-top: 2px;
   padding-bottom: 2px;
   text-decoration: none;
   padding-top: 2px;
   padding-bottom: 2px;
   text-decoration: none;
+  height: 15px;
 }
 
 #mailboxlist li.unread
 }
 
 #mailboxlist li.unread
@@ -701,7 +702,8 @@ body.messagelist
 
 #messagelist tr td.flag span,
 #messagelist tr td.status span,
 
 #messagelist tr td.flag span,
 #messagelist tr td.status span,
-#messagelist tr td.attachment span
+#messagelist tr td.attachment span,
+#messagelist tr td.priority span
 {
   display: block;
   width: 15px;
 {
   display: block;
   width: 15px;
@@ -712,6 +714,12 @@ body.messagelist
 #messagelist tr td.threads div.listmenu,
 #messagelist tr td.attachment span.attachment,
 #messagelist tr td.attachment span.report,
 #messagelist tr td.threads div.listmenu,
 #messagelist tr td.attachment span.attachment,
 #messagelist tr td.attachment span.report,
+#messagelist tr td.priority span.priority,
+#messagelist tr td.priority span.prio1,
+#messagelist tr td.priority span.prio2,
+#messagelist tr td.priority span.prio3,
+#messagelist tr td.priority span.prio4,
+#messagelist tr td.priority span.prio5,
 #messagelist tr td.flag span.flagged,
 #messagelist tr td.flag span.unflagged,
 #messagelist tr td.flag span.unflagged:hover,
 #messagelist tr td.flag span.flagged,
 #messagelist tr td.flag span.unflagged,
 #messagelist tr td.flag span.unflagged:hover,
@@ -744,6 +752,36 @@ body.messagelist
   background-position: 0 -255px;
 }
 
   background-position: 0 -255px;
 }
 
+#messagelist tr td.priority span.priority
+{
+  background-position: 0 -309px;
+}
+
+#messagelist tr td.priority span.prio5
+{
+  background-position: 0 -358px;
+}
+
+#messagelist tr td.priority span.prio4
+{
+  background-position: 0 -340px;
+}
+
+#messagelist tr td.priority span.prio3
+{
+  background-position: 0 -324px;
+}
+
+#messagelist tr td.priority span.prio2
+{
+  background-position: 0 -309px;
+}
+
+#messagelist tr td.priority span.prio1
+{
+  background-position: 0 -290px;
+}
+
 #messagelist tr td.flag span.flagged
 {
   background-position: 0 -153px;
 #messagelist tr td.flag span.flagged
 {
   background-position: 0 -153px;
@@ -839,7 +877,8 @@ body.messagelist
 #messagelist tr td.attachment,
 #messagelist tr td.threads,
 #messagelist tr td.status,
 #messagelist tr td.attachment,
 #messagelist tr td.threads,
 #messagelist tr td.status,
-#messagelist tr td.flag
+#messagelist tr td.flag,
+#messagelist tr td.priority
 {
   width: 17px;
   padding: 0 0 0 2px;
 {
   width: 17px;
   padding: 0 0 0 2px;
@@ -872,13 +911,6 @@ body.messagelist
   background-color: #FFF;
 }
 
   background-color: #FFF;
 }
 
-/*
-#messagelist tr.odd
-{
-  background-color: #F9F9F9;
-}
-*/
-
 #messagelist tr.unread
 {
   font-weight: bold;
 #messagelist tr.unread
 {
   font-weight: bold;
@@ -1166,21 +1198,20 @@ div.message-htmlpart div.rcmBody
   margin: 8px;
 }
 
   margin: 8px;
 }
 
-#remote-objects-message
+#message-objects div
 {
 {
-  display: none;
   margin: 8px;
   min-height: 20px;
   padding: 10px 10px 6px 46px;
 }
 
   margin: 8px;
   min-height: 20px;
   padding: 10px 10px 6px 46px;
 }
 
-#remote-objects-message a
+#message-objects div a
 {
   color: #666666;
   padding-left: 10px;
 }
 
 {
   color: #666666;
   padding-left: 10px;
 }
 
-#remote-objects-message a:hover
+#message-objects div a:hover
 {
   color: #333333;
 }
 {
   color: #333333;
 }
index 76c3e0c9159a5dbc42272a8fbedfc1979b0e1f48..afdf6741800bcde45a14df61991cfa2a801e366a 100644 (file)
@@ -2,14 +2,14 @@
 
 body
 {
 
 body
 {
+  font-family: "Lucida Grande", Verdana, Arial, Helvetica, sans-serif;
   background-color: #ffffff;
   color: #000000;
   margin: 2mm;
 }
 
   background-color: #ffffff;
   color: #000000;
   margin: 2mm;
 }
 
-body, td, th, span, div, p, h3
+body, td, th, span, div, p
 {
 {
-  font-family: "Lucida Grande", Verdana, Arial, Helvetica, sans-serif;
   font-size: 9pt;
   color: #000000;
 }
   font-size: 9pt;
   color: #000000;
 }
index a85c889c0cf3438cb61904ccf33e9cc60aeb976a..1930debf1c9c434f4a6f2800b1394614c7458124 100644 (file)
@@ -58,7 +58,7 @@
 </div>
 <div class="boxfooter">
   <roundcube:button command="group-create" type="link" title="newcontactgroup" class="buttonPas addgroup" classAct="button addgroup" content=" " />
 </div>
 <div class="boxfooter">
   <roundcube:button command="group-create" type="link" title="newcontactgroup" class="buttonPas addgroup" classAct="button addgroup" content=" " />
-  <roundcube:button name="groupmenulink" id="groupmenulink" type="link" title="groupactions" class="button groupactions" onclick="rcmail_ui.show_popup('groupmenu');return false" content=" " />
+  <roundcube:button name="groupmenulink" id="groupmenulink" type="link" title="moreactions" class="button groupactions" onclick="rcmail_ui.show_popup('groupmenu');return false" content=" " />
 </div>
 </div>
 
 </div>
 </div>
 
@@ -99,6 +99,8 @@
   <ul>
     <li><roundcube:button command="group-rename" label="grouprename" classAct="active" /></li>
     <li><roundcube:button command="group-delete" label="groupdelete" classAct="active" /></li>
   <ul>
     <li><roundcube:button command="group-rename" label="grouprename" classAct="active" /></li>
     <li><roundcube:button command="group-delete" label="groupdelete" classAct="active" /></li>
+    <li class="separator_above"><roundcube:button command="search-create" label="searchsave" classAct="active" /></li>
+    <li><roundcube:button command="search-delete" label="searchdelete" classAct="active" /></li>
     <roundcube:container name="groupoptions" id="groupoptionsmenu" />
   </ul>
 </div>
     <roundcube:container name="groupoptions" id="groupoptionsmenu" />
   </ul>
 </div>
index ea6a2f71c767949694d17d15f8c07e2833c534a2..30b56aa4135f57b8f2b3dff58c7d3ce44d86b8d2 100644 (file)
     <li><input type="checkbox" name="list_col[]" value="status" id="cols_status" /><label for="cols_status"><roundcube:label name="readstatus" /></label></li>
     <li><input type="checkbox" name="list_col[]" value="attachment" id="cols_attachment" /><label for="cols_attachment"><roundcube:label name="attachment" /></label></li>
     <li><input type="checkbox" name="list_col[]" value="flag" id="cols_flag" /><label for="cols_flag"><roundcube:label name="flag" /></label></li>
     <li><input type="checkbox" name="list_col[]" value="status" id="cols_status" /><label for="cols_status"><roundcube:label name="readstatus" /></label></li>
     <li><input type="checkbox" name="list_col[]" value="attachment" id="cols_attachment" /><label for="cols_attachment"><roundcube:label name="attachment" /></label></li>
     <li><input type="checkbox" name="list_col[]" value="flag" id="cols_flag" /><label for="cols_flag"><roundcube:label name="flag" /></label></li>
+    <li><input type="checkbox" name="list_col[]" value="priority" id="cols_priority" /><label for="cols_priority"><roundcube:label name="priority" /></label></li>
   </ul>
 </fieldset>
 <roundcube:endif />
   </ul>
 </fieldset>
 <roundcube:endif />
index 8e2bb2cb3af8b821beef3bb2e69bb05c055452cd..714540b7859b2bac9d328b3f921cdfe2c67fc90f 100644 (file)
@@ -36,8 +36,7 @@
 <roundcube:object name="messageHeaders" class="headers-table" cellspacing="0" cellpadding="2" addicon="/images/icons/silhouette.png" summary="Message headers" />
 <roundcube:object name="messageFullHeaders" id="full-headers" />
 <roundcube:object name="messageAttachments" id="attachment-list" />
 <roundcube:object name="messageHeaders" class="headers-table" cellspacing="0" cellpadding="2" addicon="/images/icons/silhouette.png" summary="Message headers" />
 <roundcube:object name="messageFullHeaders" id="full-headers" />
 <roundcube:object name="messageAttachments" id="attachment-list" />
-
-<roundcube:object name="blockedObjects" id="remote-objects-message" />
+<roundcube:object name="messageObjects" id="message-objects" />
 <roundcube:object name="messageBody" id="messagebody" />
 </div>
 <div class="boxfooter">
 <roundcube:object name="messageBody" id="messagebody" />
 </div>
 <div class="boxfooter">
index bfd7d7d9206918ec41d24d7aaa94e35c698db302..a606311e1f8c70dca3d149a593e3b011f900e540 100644 (file)
@@ -13,7 +13,7 @@
 <roundcube:object name="messageAttachments" id="attachment-list" />
 </div>
 
 <roundcube:object name="messageAttachments" id="attachment-list" />
 </div>
 
-<roundcube:object name="blockedObjects" id="remote-objects-message" />
+<roundcube:object name="messageObjects" id="message-objects" />
 <roundcube:object name="messageBody" id="messagebody" />
 
 </body>
 <roundcube:object name="messageBody" id="messagebody" />
 
 </body>