summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.tx/config2
-rw-r--r--CHANGELOG78
-rw-r--r--INSTALL52
-rw-r--r--SQL/mssql.initial.sql54
-rw-r--r--SQL/mssql/2013052500.sql17
-rw-r--r--SQL/mssql/2013061000.sql44
-rw-r--r--SQL/mysql.initial.sql31
-rw-r--r--SQL/mysql/2013052500.sql7
-rw-r--r--SQL/mysql/2013061000.sql24
-rw-r--r--SQL/postgres.initial.sql42
-rw-r--r--SQL/postgres/2013052500.sql8
-rw-r--r--SQL/postgres/2013061000.sql24
-rw-r--r--SQL/sqlite.initial.sql78
-rw-r--r--SQL/sqlite/2013052500.sql8
-rw-r--r--SQL/sqlite/2013061000.sql48
-rw-r--r--UPGRADING16
-rwxr-xr-xbin/gc.sh27
-rwxr-xr-xbin/installto.sh2
-rwxr-xr-xbin/update.sh89
-rw-r--r--composer.json-dist2
-rw-r--r--config/config.inc.php.sample85
-rw-r--r--config/db.inc.php.dist35
-rw-r--r--config/defaults.inc.php (renamed from config/main.inc.php.dist)491
-rw-r--r--index.php2
-rw-r--r--installer/check.php46
-rw-r--r--installer/config.php42
-rw-r--r--installer/index.php31
-rw-r--r--installer/rcube_install.php222
-rw-r--r--installer/test.php148
-rw-r--r--plugins/acl/acl.php13
-rw-r--r--plugins/acl/config.inc.php.dist6
-rw-r--r--plugins/acl/localization/en_US.inc2
-rw-r--r--plugins/acl/localization/et_EE.inc4
-rw-r--r--plugins/acl/localization/gl_ES.inc64
-rw-r--r--plugins/acl/localization/he_IL.inc2
-rw-r--r--plugins/acl/localization/lb_LU.inc99
-rw-r--r--plugins/acl/localization/pl_PL.inc2
-rw-r--r--plugins/acl/localization/tr_TR.inc2
-rw-r--r--plugins/acl/package.xml2
-rw-r--r--plugins/additional_message_headers/additional_message_headers.php6
-rw-r--r--plugins/archive/archive.js18
-rw-r--r--plugins/archive/archive.php6
-rw-r--r--plugins/archive/localization/lb_LU.inc34
-rw-r--r--plugins/archive/localization/lv_LV.inc22
-rwxr-xr-xplugins/attachment_reminder/attachment_reminder.php10
-rw-r--r--plugins/attachment_reminder/localization/lb_LU.inc22
-rw-r--r--plugins/database_attachments/config.inc.php.dist12
-rw-r--r--plugins/database_attachments/database_attachments.php118
-rw-r--r--plugins/database_attachments/package.xml6
-rw-r--r--plugins/debug_logger/debug_logger.php4
-rw-r--r--plugins/enigma/skins/classic/templates/keys.html6
-rw-r--r--plugins/example_addressbook/example_addressbook.php3
-rw-r--r--plugins/filesystem_attachments/filesystem_attachments.php1
-rw-r--r--plugins/filesystem_attachments/package.xml2
-rw-r--r--plugins/help/config.inc.php.dist34
-rw-r--r--plugins/help/content/about.html27
-rw-r--r--plugins/help/content/license.html2
-rw-r--r--plugins/help/help.js25
-rw-r--r--plugins/help/help.php67
-rw-r--r--plugins/help/localization/de_DE.inc2
-rw-r--r--plugins/help/localization/gl_ES.inc2
-rw-r--r--plugins/help/localization/lb_LU.inc24
-rw-r--r--plugins/help/package.xml9
-rw-r--r--plugins/help/skins/classic/help.css16
-rw-r--r--plugins/help/skins/classic/templates/help.html17
-rw-r--r--plugins/help/skins/larry/help.css1
-rw-r--r--plugins/help/skins/larry/templates/help.html8
-rw-r--r--plugins/hide_blockquote/localization/lb_LU.inc24
-rw-r--r--plugins/http_authentication/http_authentication.php2
-rw-r--r--plugins/jqueryui/jqueryui.php1
-rw-r--r--plugins/managesieve/Changelog32
-rw-r--r--plugins/managesieve/lib/Roundcube/rcube_sieve.php12
-rw-r--r--plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php2122
-rw-r--r--plugins/managesieve/lib/Roundcube/rcube_sieve_script.php12
-rw-r--r--plugins/managesieve/localization/az_AZ.inc2
-rw-r--r--plugins/managesieve/localization/be_BE.inc2
-rw-r--r--plugins/managesieve/localization/bg_BG.inc2
-rw-r--r--plugins/managesieve/localization/bs_BA.inc2
-rw-r--r--plugins/managesieve/localization/ca_ES.inc2
-rw-r--r--plugins/managesieve/localization/cs_CZ.inc2
-rw-r--r--plugins/managesieve/localization/cy_GB.inc2
-rw-r--r--plugins/managesieve/localization/da_DK.inc2
-rw-r--r--plugins/managesieve/localization/de_CH.inc2
-rw-r--r--plugins/managesieve/localization/de_DE.inc2
-rw-r--r--plugins/managesieve/localization/el_GR.inc2
-rw-r--r--plugins/managesieve/localization/en_GB.inc2
-rw-r--r--plugins/managesieve/localization/en_US.inc25
-rw-r--r--plugins/managesieve/localization/eo.inc2
-rw-r--r--plugins/managesieve/localization/es_AR.inc2
-rw-r--r--plugins/managesieve/localization/es_ES.inc31
-rw-r--r--plugins/managesieve/localization/et_EE.inc29
-rw-r--r--plugins/managesieve/localization/fa_IR.inc1
-rw-r--r--plugins/managesieve/localization/fi_FI.inc2
-rw-r--r--plugins/managesieve/localization/fr_FR.inc39
-rw-r--r--plugins/managesieve/localization/gl_ES.inc2
-rw-r--r--plugins/managesieve/localization/he_IL.inc1
-rw-r--r--plugins/managesieve/localization/hu_HU.inc2
-rw-r--r--plugins/managesieve/localization/hy_AM.inc2
-rw-r--r--plugins/managesieve/localization/ia.inc2
-rw-r--r--plugins/managesieve/localization/id_ID.inc2
-rw-r--r--plugins/managesieve/localization/it_IT.inc2
-rw-r--r--plugins/managesieve/localization/ja_JP.inc2
-rw-r--r--plugins/managesieve/localization/ko_KR.inc2
-rw-r--r--plugins/managesieve/localization/lb_LU.inc196
-rw-r--r--plugins/managesieve/localization/lt_LT.inc2
-rw-r--r--plugins/managesieve/localization/lv_LV.inc163
-rw-r--r--plugins/managesieve/localization/ml_IN.inc1
-rw-r--r--plugins/managesieve/localization/mr_IN.inc2
-rw-r--r--plugins/managesieve/localization/nb_NO.inc2
-rw-r--r--plugins/managesieve/localization/nl_NL.inc2
-rw-r--r--plugins/managesieve/localization/nn_NO.inc2
-rw-r--r--plugins/managesieve/localization/pl_PL.inc31
-rw-r--r--plugins/managesieve/localization/pt_BR.inc27
-rw-r--r--plugins/managesieve/localization/pt_PT.inc2
-rw-r--r--plugins/managesieve/localization/ro_RO.inc2
-rw-r--r--plugins/managesieve/localization/ru_RU.inc27
-rw-r--r--plugins/managesieve/localization/si_LK.inc1
-rw-r--r--plugins/managesieve/localization/sk_SK.inc2
-rw-r--r--plugins/managesieve/localization/sl_SI.inc31
-rw-r--r--plugins/managesieve/localization/sv_SE.inc2
-rw-r--r--plugins/managesieve/localization/tr_TR.inc8
-rw-r--r--plugins/managesieve/localization/uk_UA.inc2
-rw-r--r--plugins/managesieve/localization/vi_VN.inc2
-rw-r--r--plugins/managesieve/localization/zh_CN.inc2
-rw-r--r--plugins/managesieve/localization/zh_TW.inc2
-rw-r--r--plugins/managesieve/managesieve.js194
-rw-r--r--plugins/managesieve/managesieve.php1923
-rw-r--r--plugins/managesieve/package.xml10
-rw-r--r--plugins/managesieve/skins/classic/images/erase.pngbin0 -> 453 bytes
-rw-r--r--plugins/managesieve/skins/classic/managesieve.css90
-rw-r--r--plugins/managesieve/skins/classic/templates/managesieve.html6
-rw-r--r--plugins/managesieve/skins/larry/images/erase.pngbin0 -> 453 bytes
-rw-r--r--plugins/managesieve/skins/larry/managesieve.css98
-rw-r--r--plugins/markasjunk/localization/lb_LU.inc24
-rw-r--r--plugins/markasjunk/localization/lv_LV.inc6
-rw-r--r--plugins/new_user_dialog/localization/lb_LU.inc23
-rw-r--r--plugins/new_user_dialog/localization/lv_LV.inc4
-rw-r--r--plugins/new_user_identity/new_user_identity.php1
-rw-r--r--plugins/new_user_identity/package.xml2
-rw-r--r--plugins/newmail_notifier/localization/lb_LU.inc29
-rw-r--r--plugins/newmail_notifier/localization/lv_LV.inc16
-rw-r--r--plugins/newmail_notifier/newmail_notifier.php12
-rw-r--r--plugins/newmail_notifier/package.xml2
-rw-r--r--plugins/password/README20
-rw-r--r--plugins/password/localization/gl_ES.inc2
-rw-r--r--plugins/password/localization/lb_LU.inc37
-rw-r--r--plugins/password/localization/lv_LV.inc16
-rw-r--r--plugins/password/package.xml2
-rw-r--r--plugins/password/password.php48
-rw-r--r--plugins/redundant_attachments/config.inc.php.dist6
-rw-r--r--plugins/redundant_attachments/redundant_attachments.php7
-rw-r--r--plugins/show_additional_headers/package.xml2
-rw-r--r--plugins/show_additional_headers/show_additional_headers.php4
-rw-r--r--plugins/subscriptions_option/localization/gl_ES.inc2
-rw-r--r--plugins/subscriptions_option/localization/lb_LU.inc22
-rw-r--r--plugins/subscriptions_option/package.xml2
-rw-r--r--plugins/subscriptions_option/subscriptions_option.php3
-rw-r--r--plugins/userinfo/localization/lb_LU.inc25
-rw-r--r--plugins/vcard_attachments/localization/gl_ES.inc4
-rw-r--r--plugins/vcard_attachments/localization/lb_LU.inc23
-rw-r--r--plugins/virtuser_file/virtuser_file.php90
-rw-r--r--plugins/virtuser_query/package.xml2
-rw-r--r--plugins/virtuser_query/virtuser_query.php3
-rw-r--r--plugins/zipdownload/localization/lb_LU.inc23
-rw-r--r--plugins/zipdownload/zipdownload.php6
-rw-r--r--program/include/bc.php12
-rw-r--r--program/include/rcmail.php50
-rw-r--r--program/include/rcmail_output_html.php86
-rw-r--r--program/js/app.js469
-rw-r--r--program/js/common.js115
-rw-r--r--program/js/editor.js4
-rw-r--r--program/js/list.js57
-rw-r--r--program/lib/Mail/mime.php114
-rw-r--r--program/lib/Mail/mimePart.php40
-rw-r--r--program/lib/Roundcube/bootstrap.php30
-rw-r--r--program/lib/Roundcube/html.php4
-rw-r--r--program/lib/Roundcube/rcube.php98
-rw-r--r--program/lib/Roundcube/rcube_addressbook.php6
-rw-r--r--program/lib/Roundcube/rcube_cache.php78
-rw-r--r--program/lib/Roundcube/rcube_cache_shared.php581
-rw-r--r--program/lib/Roundcube/rcube_config.php93
-rw-r--r--program/lib/Roundcube/rcube_db.php118
-rw-r--r--program/lib/Roundcube/rcube_db_mssql.php32
-rw-r--r--program/lib/Roundcube/rcube_db_mysql.php21
-rw-r--r--program/lib/Roundcube/rcube_db_pgsql.php66
-rw-r--r--program/lib/Roundcube/rcube_db_sqlite.php47
-rw-r--r--program/lib/Roundcube/rcube_db_sqlsrv.php29
-rw-r--r--program/lib/Roundcube/rcube_image.php8
-rw-r--r--program/lib/Roundcube/rcube_imap.php249
-rw-r--r--program/lib/Roundcube/rcube_imap_cache.php204
-rw-r--r--program/lib/Roundcube/rcube_imap_generic.php197
-rw-r--r--program/lib/Roundcube/rcube_ldap.php1298
-rw-r--r--program/lib/Roundcube/rcube_ldap_generic.php1049
-rw-r--r--program/lib/Roundcube/rcube_ldap_result.php130
-rw-r--r--program/lib/Roundcube/rcube_mime.php52
-rw-r--r--program/lib/Roundcube/rcube_session.php142
-rw-r--r--program/lib/Roundcube/rcube_spellchecker.php146
-rw-r--r--program/lib/Roundcube/rcube_storage.php15
-rw-r--r--program/lib/Roundcube/rcube_user.php9
-rw-r--r--program/lib/Roundcube/rcube_utils.php38
-rw-r--r--program/lib/Roundcube/rcube_vcard.php10
-rw-r--r--program/lib/Roundcube/rcube_washtml.php17
-rw-r--r--program/localization/ar_SA/labels.inc5
-rw-r--r--program/localization/ast/labels.inc5
-rw-r--r--program/localization/az_AZ/labels.inc5
-rw-r--r--program/localization/be_BE/labels.inc5
-rw-r--r--program/localization/bg_BG/labels.inc5
-rw-r--r--program/localization/bn_BD/labels.inc5
-rw-r--r--program/localization/br/labels.inc5
-rw-r--r--program/localization/bs_BA/labels.inc7
-rw-r--r--program/localization/ca_ES/labels.inc5
-rw-r--r--program/localization/cs_CZ/labels.inc7
-rw-r--r--program/localization/cs_CZ/messages.inc6
-rw-r--r--program/localization/cy_GB/labels.inc7
-rw-r--r--program/localization/da_DK/labels.inc7
-rw-r--r--program/localization/de_CH/labels.inc5
-rw-r--r--program/localization/de_CH/messages.inc2
-rw-r--r--program/localization/de_DE/labels.inc7
-rw-r--r--program/localization/el_GR/labels.inc5
-rw-r--r--program/localization/en_GB/labels.inc5
-rw-r--r--program/localization/en_US/labels.inc6
-rw-r--r--program/localization/en_US/messages.inc9
-rw-r--r--program/localization/eo/labels.inc5
-rw-r--r--program/localization/es_AR/labels.inc5
-rw-r--r--program/localization/es_ES/labels.inc7
-rw-r--r--program/localization/es_ES/messages.inc2
-rw-r--r--program/localization/et_EE/labels.inc15
-rw-r--r--program/localization/et_EE/messages.inc6
-rw-r--r--program/localization/eu_ES/labels.inc5
-rw-r--r--program/localization/fa_AF/labels.inc5
-rw-r--r--program/localization/fa_IR/labels.inc5
-rw-r--r--program/localization/fi_FI/labels.inc13
-rw-r--r--program/localization/fr_FR/labels.inc79
-rw-r--r--program/localization/fy_NL/labels.inc5
-rw-r--r--program/localization/fy_NL/messages.inc171
-rwxr-xr-xprogram/localization/ga_IE/labels.inc5
-rw-r--r--program/localization/gl_ES/labels.inc7
-rw-r--r--program/localization/gl_ES/messages.inc2
-rw-r--r--program/localization/he_IL/labels.inc5
-rw-r--r--program/localization/he_IL/messages.inc2
-rw-r--r--program/localization/hi_IN/labels.inc5
-rw-r--r--program/localization/hr_HR/labels.inc5
-rw-r--r--program/localization/hu_HU/labels.inc5
-rw-r--r--program/localization/hy_AM/labels.inc5
-rw-r--r--program/localization/ia/labels.inc5
-rw-r--r--program/localization/id_ID/labels.inc5
-rw-r--r--program/localization/index.inc2
-rw-r--r--program/localization/is_IS/labels.inc5
-rw-r--r--program/localization/it_IT/labels.inc5
-rw-r--r--program/localization/ja_JP/labels.inc5
-rwxr-xr-xprogram/localization/ka_GE/labels.inc5
-rw-r--r--program/localization/km_KH/labels.inc5
-rw-r--r--program/localization/ko_KR/labels.inc5
-rw-r--r--program/localization/ku/labels.inc5
-rw-r--r--program/localization/lb_LU/labels.inc544
-rw-r--r--program/localization/lb_LU/messages.inc176
-rw-r--r--program/localization/lt_LT/labels.inc5
-rw-r--r--program/localization/lv_LV/labels.inc323
-rw-r--r--program/localization/lv_LV/messages.inc90
-rwxr-xr-xprogram/localization/mk_MK/labels.inc5
-rw-r--r--program/localization/ml_IN/labels.inc5
-rwxr-xr-xprogram/localization/mr_IN/labels.inc5
-rw-r--r--program/localization/ms_MY/labels.inc5
-rw-r--r--program/localization/nb_NO/labels.inc5
-rw-r--r--program/localization/ne_NP/labels.inc5
-rw-r--r--program/localization/nl_BE/labels.inc5
-rw-r--r--program/localization/nl_NL/labels.inc5
-rw-r--r--program/localization/nn_NO/labels.inc5
-rw-r--r--program/localization/pl_PL/labels.inc5
-rw-r--r--program/localization/pl_PL/messages.inc2
-rwxr-xr-xprogram/localization/ps/labels.inc5
-rw-r--r--program/localization/pt_BR/labels.inc9
-rw-r--r--program/localization/pt_PT/labels.inc5
-rw-r--r--program/localization/ro_RO/labels.inc79
-rw-r--r--program/localization/ru_RU/labels.inc5
-rw-r--r--program/localization/si_LK/labels.inc5
-rw-r--r--program/localization/sk_SK/labels.inc5
-rw-r--r--program/localization/sl_SI/labels.inc13
-rw-r--r--program/localization/sl_SI/messages.inc2
-rw-r--r--program/localization/sq_AL/labels.inc5
-rw-r--r--program/localization/sr_CS/labels.inc5
-rw-r--r--program/localization/sv_SE/labels.inc5
-rw-r--r--program/localization/ta_IN/labels.inc5
-rw-r--r--program/localization/th_TH/labels.inc5
-rw-r--r--program/localization/tr_TR/labels.inc7
-rw-r--r--program/localization/tr_TR/messages.inc2
-rw-r--r--program/localization/uk_UA/labels.inc5
-rw-r--r--program/localization/vi_VN/labels.inc5
-rw-r--r--program/localization/zh_CN/labels.inc5
-rw-r--r--program/localization/zh_TW/labels.inc5
-rw-r--r--program/steps/addressbook/copy.inc12
-rw-r--r--program/steps/addressbook/delete.inc38
-rw-r--r--program/steps/addressbook/func.inc137
-rw-r--r--program/steps/addressbook/list.inc49
-rw-r--r--program/steps/addressbook/move.inc208
-rw-r--r--program/steps/addressbook/save.inc4
-rw-r--r--program/steps/addressbook/show.inc5
-rw-r--r--program/steps/addressbook/undo.inc25
-rw-r--r--program/steps/mail/check_recent.inc5
-rw-r--r--program/steps/mail/compose.inc72
-rw-r--r--program/steps/mail/func.inc150
-rw-r--r--program/steps/mail/get.inc76
-rw-r--r--program/steps/mail/import.inc105
-rw-r--r--program/steps/mail/list_contacts.inc43
-rw-r--r--program/steps/mail/move_del.inc4
-rw-r--r--program/steps/mail/search_contacts.inc19
-rw-r--r--program/steps/mail/sendmail.inc7
-rw-r--r--program/steps/mail/show.inc10
-rw-r--r--program/steps/settings/folders.inc13
-rw-r--r--program/steps/settings/func.inc1971
-rw-r--r--program/steps/settings/save_prefs.inc3
-rw-r--r--skins/classic/addressbook.css31
-rw-r--r--skins/classic/common.css9
-rw-r--r--skins/classic/functions.js235
-rw-r--r--skins/classic/images/contactgroup.pngbin0 -> 1038 bytes
-rw-r--r--skins/classic/images/mail_toolbar.pngbin36649 -> 40806 bytes
-rw-r--r--skins/classic/includes/messagetoolbar.html2
-rw-r--r--skins/classic/mail.css292
-rw-r--r--skins/classic/print.css29
-rw-r--r--skins/classic/settings.css14
-rw-r--r--skins/classic/templates/about.html7
-rw-r--r--skins/classic/templates/addressbook.html15
-rw-r--r--skins/classic/templates/compose.html10
-rw-r--r--skins/classic/templates/contact.html2
-rw-r--r--skins/classic/templates/contactadd.html9
-rw-r--r--skins/classic/templates/contactedit.html9
-rw-r--r--skins/classic/templates/folders.html6
-rw-r--r--skins/classic/templates/login.html2
-rw-r--r--skins/classic/templates/mail.html16
-rw-r--r--skins/classic/templates/message.html8
-rw-r--r--skins/classic/templates/messageerror.html6
-rw-r--r--skins/classic/templates/messagepart.html38
-rw-r--r--skins/classic/templates/messagepreview.html6
-rw-r--r--skins/larry/addressbook.css49
-rw-r--r--skins/larry/ie7hacks.css1
-rw-r--r--skins/larry/images/buttons.pngbin37956 -> 50162 bytes
-rw-r--r--skins/larry/images/contactgroup.pngbin0 -> 2104 bytes
-rw-r--r--skins/larry/images/listicons.pngbin25486 -> 26384 bytes
-rw-r--r--skins/larry/includes/header.html6
-rw-r--r--skins/larry/mail.css316
-rw-r--r--skins/larry/print.css25
-rw-r--r--skins/larry/settings.css10
-rw-r--r--skins/larry/styles.css27
-rw-r--r--skins/larry/templates/about.html4
-rw-r--r--skins/larry/templates/addressbook.html9
-rw-r--r--skins/larry/templates/compose.html2
-rw-r--r--skins/larry/templates/contact.html2
-rw-r--r--skins/larry/templates/contactedit.html2
-rw-r--r--skins/larry/templates/login.html2
-rw-r--r--skins/larry/templates/mail.html15
-rw-r--r--skins/larry/templates/message.html4
-rw-r--r--skins/larry/templates/messagepart.html34
-rw-r--r--skins/larry/ui.js101
-rw-r--r--tests/Framework/ImapGeneric.php23
-rw-r--r--tests/Framework/Utils.php65
-rw-r--r--tests/Framework/Washtml.php15
-rw-r--r--tests/Selenium/bootstrap.php4
-rw-r--r--tests/bootstrap.php4
358 files changed, 13409 insertions, 6755 deletions
diff --git a/.tx/config b/.tx/config
index 31c1eabdf..e183fb999 100644
--- a/.tx/config
+++ b/.tx/config
@@ -1,6 +1,6 @@
[main]
host = https://www.transifex.com
-lang_map = be: be_BE, sr: sr_CS, fa: fa_AF
+lang_map = be: be_BE, sr: sr_CS, fa: fa_AF, lb: lb_LU
type = PHP_ALT_ARRAY
[roundcube-webmail.labels]
diff --git a/CHANGELOG b/CHANGELOG
index 2709373d5..b779086e0 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,14 +1,48 @@
CHANGELOG Roundcube Webmail
===========================
-- Fix handling of comma when adding contact from contacts widget (#1489107)
-- Fix bug where a message was opened in both preview pane and new window on double-click (#1489122)
-- Fix fatal error when xdebug.max_nesting_level was exceeded in rcube_washtml (#1489110)
-- Fix PHP warning in html_table::set_row_attribs() in PHP 5.4 (#1489094)
-- Fix invalid option selected in default_font selector when font is unset (#1489112)
-- Fix displaying contact with ID divisible by 100 in sql addressbook (#1489121)
-- Fix browser warnings on PDF plugin detection (#1489118)
-- Fix fatal error when parsing UUencoded messages (#1489119)
+- Respect HTTP_X_FORWARDED_FOR and HTTP_X_REAL_IP variables for session IP check
+- Simplified configuration by merging it into one file + defaults (#1487311)
+- Make message list header stay on top when scrolling (#1295420)
+- Fix bug where signature wasn't changed on identity selection when editing a draft (#1489229)
+- Fix IMAP SETMETADATA parameters quoting (#1489231)
+- Add support for 'enchant' spellcheck engine
+- Fix "could not load message" error on valid empty message body (#1489228)
+- Check filetype detection in installer and update script (#1489193)
+- Fix handling of message/rfc822 attachments on message forward and edit (#1489214)
+- Fix folder names truncation in Classic skin (#1489220)
+- Fix parsing of square bracket characters in IMAP response strings (#1489223)
+- Don't clear References and in-Reply-To when a message is "edited as new" (#1489216)
+- Make possible to disable some (broken) IMAP extensions with imap_disable_caps option (#1489184)
+- Contacts drag-n-drop default action is to move contacts (#1488751)
+- Added possibility to choose to move or copy contacts from drag-n-drop menu (#1488751)
+- Fix messages list sorting with THREAD=REFS
+- Fix Close link and remove About link on error pages (#1489109)
+- Remove deprecated (in PHP 5.5) PREG /e modifier usage (#1489174)
+- Fix empty messages list when register_globals is enabled (#1489157)
+- Improved/unified attachment preview screen, added print button
+- Fix lack of space between searchfiler and quicksearchbar in Larry skin (#1489158)
+- Fix so valid and set date.timezone is not required by installer checks (#1489180)
+- Canonize boolean ini_get() results (#1489189)
+- Cache LDAP's user_specific search and use vlv for better performance (#1489186)
+- LDAP: auto-detect and use VLV indices for all search operations
+- LDAP: additional group configuration options for address books
+- LDAP: separated address book implementation from a generic LDAP wrapper class
+- Allow address books to browse a multi-level group hierarchy in the contacts list
+- Fix so install do not fail when one of DB driver checks fails but other drivers exist (#1489178)
+- Fix so exported vCard specifies encoding in v3-compatible format (#1489183)
+- Fix session issues when local and database time differs (#1486132)
+- Fix thread cache syncronization/validation (#1489028)
+- Added feature to import messages to the currently selected folder
+- Add option show_real_foldernames to disable localization of special folders
+- Fix database cache expunge issues (#1489149)
+- Fix date format issues on MS SQL Server (#1488918)
+- Add imap_cache_ttl option to configure TTL of imap_cache
+- Make LDAP cache engine configurable via ldap_cache and ldap_cache_ttl options
+- Fix "duplicate entry" errors on inserts to imap cache tables (#1489146)
+- Improved handling of Reply-To/Bcc addresses of identity in compose form (#1489016)
+- Added user preference to open all popups as standard windows
+- Implemented shared cache (rcube_cache_shared)
- Change Reply-All button label/title when mailing list is detected (#1488938)
- Fix SMTP connection using IPv6 address in smtp_server option (#1489024)
- Added attachment_reminder plugin
@@ -31,6 +65,34 @@ CHANGELOG Roundcube Webmail
- Fix export of selected contacts from search result (#1488905)
- Feature to export only selected contacts from addressbook (by Phil Weir)
+RELEASE 0.9.2
+-------------
+- Fix image thumbnails display in print mode (#1489134)
+- Fix height of message headers block (#1489108)
+- Fix timeout issue on drag&drop uploads (#1489170)
+- Fix default sorting of threaded list when THREAD=REFS isn't supported
+- Fix list mode switch to 'List' after saving list settings in Larry skin (#1489164)
+- Fix error when there's no writeable addressbook source (#1489162)
+- Fix zipdownload plugin issue with filenames charset (#1489156)
+- Fix so non-inline images aren't skipped on forward (#1489150)
+- Fix "null" instead of empty string on messages list in IE10 (#1489145)
+- Fix legacy options handling
+- Fix so bounces addresses in Sender headers are skipped on Reply-All (#1489011)
+- Fix bug where serialized strings were truncated in PDO::quote() (#1489142)
+- Fix displaying messages with invalid self-closing HTML tags (#1489137)
+- Fix PHP warning when responding to a message with many Return-Path headers (#1489136)
+- Fix unintentional compose window resize (#1489114)
+- Fix performance regression in text wrapping function (#1489133)
+- Fix connection to posgtres db using unix socket (#1489132)
+- Fix handling of comma when adding contact from contacts widget (#1489107)
+- Fix bug where a message was opened in both preview pane and new window on double-click (#1489122)
+- Fix fatal error when xdebug.max_nesting_level was exceeded in rcube_washtml (#1489110)
+- Fix PHP warning in html_table::set_row_attribs() in PHP 5.4 (#1489094)
+- Fix invalid option selected in default_font selector when font is unset (#1489112)
+- Fix displaying contact with ID divisible by 100 in sql addressbook (#1489121)
+- Fix browser warnings on PDF plugin detection (#1489118)
+- Fix fatal error when parsing UUencoded messages (#1489119)
+
RELEASE 0.9.1
-------------
- Better German labels for from/to to avoid conflicts with 'sender' (#1489084)
diff --git a/INSTALL b/INSTALL
index 3abf0d198..5b1c21dac 100644
--- a/INSTALL
+++ b/INSTALL
@@ -52,14 +52,15 @@ INSTALLATION
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!
+7. Check Known Issues section of this file
+8. 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
+directory which can be configured in config/config.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.
@@ -95,18 +96,9 @@ 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
+Versions of sqlite database engine older than 3 aren't supported.
+Database file and structure is created automatically by Roundcube.
+Make sure your configuration points to some file location and that the
webserver can write to the file and the directory containing the file.
@@ -116,17 +108,12 @@ 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
+$ createuser -P roundcube
$ createdb -O roundcube -E UNICODE roundcubemail
-$ psql roundcubemail
+$ psql -U roundcube -f SQL/postgres.initial.sql 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.
+Note: in some system configurations you might need to add '-U postgres' to
+createuser and createdb commands.
* Microsoft SQL Server
@@ -142,14 +129,16 @@ 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.
+First of all, copy the sample configuration file config/config.inc.php.sample
+to config/config.inc.php and make the necessary adjustments according to your
+environment and your needs. More configuration options can be copied from the
+config/defaults.inc.php file into your local config.inc.php file as needed.
+Read the comments above the individual configuration options to find out what
+they do or read 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:
@@ -238,3 +227,10 @@ $HTTP["host"] == "www.example.com" {
compress.filetype = ("text/plain", "text/html", "text/javascript", "text/css", "text/xml", "image/gif", "image/png")
}
+
+
+KNOWN ISSUES
+============
+
+Installations with uw-imap server should set imap_disabled_caps = array('ESEARCH')
+in main configuration file. ESEARCH implementation in this server is broken (#1489184).
diff --git a/SQL/mssql.initial.sql b/SQL/mssql.initial.sql
index d43676ff9..1027867e3 100644
--- a/SQL/mssql.initial.sql
+++ b/SQL/mssql.initial.sql
@@ -2,6 +2,15 @@ CREATE TABLE [dbo].[cache] (
[user_id] [int] NOT NULL ,
[cache_key] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
[created] [datetime] NOT NULL ,
+ [expires] [datetime] NULL ,
+ [data] [text] COLLATE Latin1_General_CI_AI NOT NULL
+) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
+GO
+
+CREATE TABLE [dbo].[cache_shared] (
+ [cache_key] [varchar] (255) COLLATE Latin1_General_CI_AI NOT NULL ,
+ [created] [datetime] NOT NULL ,
+ [expires] [datetime] NULL ,
[data] [text] COLLATE Latin1_General_CI_AI NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
@@ -9,7 +18,7 @@ GO
CREATE TABLE [dbo].[cache_index] (
[user_id] [int] NOT NULL ,
[mailbox] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
- [changed] [datetime] NOT NULL ,
+ [expires] [datetime] NULL ,
[valid] [char] (1) COLLATE Latin1_General_CI_AI NOT NULL ,
[data] [text] COLLATE Latin1_General_CI_AI NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
@@ -18,7 +27,7 @@ GO
CREATE TABLE [dbo].[cache_thread] (
[user_id] [int] NOT NULL ,
[mailbox] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
- [changed] [datetime] NOT NULL ,
+ [expires] [datetime] NULL ,
[data] [text] COLLATE Latin1_General_CI_AI NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
@@ -27,7 +36,7 @@ CREATE TABLE [dbo].[cache_messages] (
[user_id] [int] NOT NULL ,
[mailbox] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
[uid] [int] NOT NULL ,
- [changed] [datetime] NOT NULL ,
+ [expires] [datetime] NULL ,
[data] [text] COLLATE Latin1_General_CI_AI NOT NULL ,
[flags] [int] NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
@@ -204,36 +213,49 @@ ALTER TABLE [dbo].[cache] ADD
CONSTRAINT [DF_cache_created] DEFAULT (getdate()) FOR [created]
GO
+ALTER TABLE [dbo].[cache_shared] ADD
+ CONSTRAINT [DF_cache_shared_created] DEFAULT (getdate()) FOR [created]
+GO
+
+ALTER TABLE [dbo].[cache_index] ADD
+ CONSTRAINT [DF_cache_index_valid] DEFAULT ('0') FOR [valid]
+GO
+
+ALTER TABLE [dbo].[cache_messages] ADD
+ CONSTRAINT [DF_cache_messages_flags] DEFAULT (0) FOR [flags]
+GO
+
CREATE INDEX [IX_cache_user_id] ON [dbo].[cache]([user_id]) ON [PRIMARY]
GO
CREATE INDEX [IX_cache_cache_key] ON [dbo].[cache]([cache_key]) ON [PRIMARY]
GO
-CREATE INDEX [IX_cache_created] ON [dbo].[cache]([created]) ON [PRIMARY]
+CREATE INDEX [IX_cache_shared_cache_key] ON [dbo].[cache_shared]([cache_key]) ON [PRIMARY]
GO
-ALTER TABLE [dbo].[cache_index] ADD
- CONSTRAINT [DF_cache_index_changed] DEFAULT (getdate()) FOR [changed],
- CONSTRAINT [DF_cache_index_valid] DEFAULT ('0') FOR [valid]
+CREATE INDEX [IX_cache_index_user_id] ON [dbo].[cache_index]([user_id]) ON [PRIMARY]
GO
-CREATE INDEX [IX_cache_index_user_id] ON [dbo].[cache_index]([user_id]) ON [PRIMARY]
+CREATE INDEX [IX_cache_thread_user_id] ON [dbo].[cache_thread]([user_id]) ON [PRIMARY]
+GO
+
+CREATE INDEX [IX_cache_messages_user_id] ON [dbo].[cache_messages]([user_id]) ON [PRIMARY]
GO
-ALTER TABLE [dbo].[cache_thread] ADD
- CONSTRAINT [DF_cache_thread_changed] DEFAULT (getdate()) FOR [changed]
+CREATE INDEX [IX_cache_expires] ON [dbo].[cache]([expires]) ON [PRIMARY]
GO
-CREATE INDEX [IX_cache_thread_user_id] ON [dbo].[cache_thread]([user_id]) ON [PRIMARY]
+CREATE INDEX [IX_cache_shared_expires] ON [dbo].[cache_shared]([expires]) ON [PRIMARY]
GO
-ALTER TABLE [dbo].[cache_messages] ADD
- CONSTRAINT [DF_cache_messages_changed] DEFAULT (getdate()) FOR [changed],
- CONSTRAINT [DF_cache_messages_flags] DEFAULT (0) FOR [flags]
+CREATE INDEX [IX_cache_index_expires] ON [dbo].[cache_index]([expires]) ON [PRIMARY]
GO
-CREATE INDEX [IX_cache_messages_user_id] ON [dbo].[cache_messages]([user_id]) ON [PRIMARY]
+CREATE INDEX [IX_cache_thread_expires] ON [dbo].[cache_thread]([expires]) ON [PRIMARY]
+GO
+
+CREATE INDEX [IX_cache_messages_expires] ON [dbo].[cache_messages]([expires]) ON [PRIMARY]
GO
ALTER TABLE [dbo].[contacts] ADD
@@ -371,6 +393,6 @@ CREATE TRIGGER [contact_delete_member] ON [dbo].[contacts]
WHERE [contact_id] IN (SELECT [contact_id] FROM deleted)
GO
-INSERT INTO [dbo].[system] ([name], [value]) VALUES ('roundcube-version', '2013042700')
+INSERT INTO [dbo].[system] ([name], [value]) VALUES ('roundcube-version', '2013061000')
GO
\ No newline at end of file
diff --git a/SQL/mssql/2013052500.sql b/SQL/mssql/2013052500.sql
new file mode 100644
index 000000000..6a7e31d46
--- /dev/null
+++ b/SQL/mssql/2013052500.sql
@@ -0,0 +1,17 @@
+CREATE TABLE [dbo].[cache_shared] (
+ [cache_key] [varchar] (255) COLLATE Latin1_General_CI_AI NOT NULL ,
+ [created] [datetime] NOT NULL ,
+ [data] [text] COLLATE Latin1_General_CI_AI NOT NULL
+) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
+GO
+
+ALTER TABLE [dbo].[cache_shared] ADD
+ CONSTRAINT [DF_cache_shared_created] DEFAULT (getdate()) FOR [created]
+GO
+
+CREATE INDEX [IX_cache_shared_cache_key] ON [dbo].[cache_shared]([cache_key]) ON [PRIMARY]
+GO
+
+CREATE INDEX [IX_cache_shared_created] ON [dbo].[cache_shared]([created]) ON [PRIMARY]
+GO
+
diff --git a/SQL/mssql/2013061000.sql b/SQL/mssql/2013061000.sql
new file mode 100644
index 000000000..55b5ec3a5
--- /dev/null
+++ b/SQL/mssql/2013061000.sql
@@ -0,0 +1,44 @@
+ALTER TABLE [dbo].[cache] ADD COLUMN [expires] [datetime] NULL
+GO
+ALTER TABLE [dbo].[cache_shared] ADD COLUMN [expires] [datetime] NULL
+GO
+ALTER TABLE [dbo].[cache_index] ADD COLUMN [expires] [datetime] NULL
+GO
+ALTER TABLE [dbo].[cache_thread] ADD COLUMN [expires] [datetime] NULL
+GO
+ALTER TABLE [dbo].[cache_messages] ADD COLUMN [expires] [datetime] NULL
+GO
+
+UPDATE [dbo].[cache] SET [expires] = DATEADD(second, 604800, [created])
+GO
+UPDATE [dbo].[cache_shared] SET [expires] = DATEADD(second, 604800, [created])
+GO
+UPDATE [dbo].[cache_index] SET [expires] = DATEADD(second, 604800, [changed])
+GO
+UPDATE [dbo].[cache_thread] SET [expires] = DATEADD(second, 604800, [changed])
+GO
+UPDATE [dbo].[cache_messages] SET [expires] = DATEADD(second, 604800, [changed])
+GO
+
+DROP INDEX [IX_cache_created]
+GO
+DROP INDEX [IX_cache_shared_created]
+GO
+ALTER TABLE [dbo].[cache_index] DROP COLUMN [changed]
+GO
+ALTER TABLE [dbo].[cache_thread] DROP COLUMN [changed]
+GO
+ALTER TABLE [dbo].[cache_messages] DROP COLUMN [changed]
+GO
+
+CREATE INDEX [IX_cache_expires] ON [dbo].[cache]([expires]) ON [PRIMARY]
+GO
+CREATE INDEX [IX_cache_shared_expires] ON [dbo].[cache_shared]([expires]) ON [PRIMARY]
+GO
+CREATE INDEX [IX_cache_index_expires] ON [dbo].[cache_index]([expires]) ON [PRIMARY]
+GO
+CREATE INDEX [IX_cache_thread_expires] ON [dbo].[cache_thread]([expires]) ON [PRIMARY]
+GO
+CREATE INDEX [IX_cache_messages_expires] ON [dbo].[cache_messages]([expires]) ON [PRIMARY]
+GO
+ \ No newline at end of file
diff --git a/SQL/mysql.initial.sql b/SQL/mysql.initial.sql
index 5a86dd8f8..4e4833a62 100644
--- a/SQL/mysql.initial.sql
+++ b/SQL/mysql.initial.sql
@@ -35,27 +35,40 @@ CREATE TABLE `users` (
CREATE TABLE `cache` (
`user_id` int(10) UNSIGNED NOT NULL,
- `cache_key` varchar(128) /*!40101 CHARACTER SET ascii COLLATE ascii_general_ci */ NOT NULL ,
+ `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',
+ `expires` datetime DEFAULT NULL,
`data` longtext NOT NULL,
CONSTRAINT `user_id_fk_cache` FOREIGN KEY (`user_id`)
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
- INDEX `created_index` (`created`),
+ INDEX `expires_index` (`expires`),
INDEX `user_cache_index` (`user_id`,`cache_key`)
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
+-- Table structure for table `cache_shared`
+
+CREATE TABLE `cache_shared` (
+ `cache_key` varchar(255) /*!40101 CHARACTER SET ascii COLLATE ascii_general_ci */ NOT NULL,
+ `created` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
+ `expires` datetime DEFAULT NULL,
+ `data` longtext NOT NULL,
+ INDEX `expires_index` (`expires`),
+ INDEX `cache_key_index` (`cache_key`)
+) /*!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,
`mailbox` varchar(255) BINARY NOT NULL,
- `changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
+ `expires` datetime DEFAULT NULL,
`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`),
+ INDEX `expires_index` (`expires`),
PRIMARY KEY (`user_id`, `mailbox`)
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
@@ -65,11 +78,11 @@ CREATE TABLE `cache_index` (
CREATE TABLE `cache_thread` (
`user_id` int(10) UNSIGNED NOT NULL,
`mailbox` varchar(255) BINARY NOT NULL,
- `changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
+ `expires` datetime DEFAULT NULL,
`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`),
+ INDEX `expires_index` (`expires`),
PRIMARY KEY (`user_id`, `mailbox`)
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
@@ -80,12 +93,12 @@ CREATE TABLE `cache_messages` (
`user_id` int(10) UNSIGNED NOT NULL,
`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',
+ `expires` datetime DEFAULT NULL,
`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`),
+ INDEX `expires_index` (`expires`),
PRIMARY KEY (`user_id`, `mailbox`, `uid`)
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
@@ -196,4 +209,4 @@ CREATE TABLE `system` (
/*!40014 SET FOREIGN_KEY_CHECKS=1 */;
-INSERT INTO system (name, value) VALUES ('roundcube-version', '2013042700');
+INSERT INTO system (name, value) VALUES ('roundcube-version', '2013061000');
diff --git a/SQL/mysql/2013052500.sql b/SQL/mysql/2013052500.sql
new file mode 100644
index 000000000..b5f72b8ab
--- /dev/null
+++ b/SQL/mysql/2013052500.sql
@@ -0,0 +1,7 @@
+CREATE TABLE `cache_shared` (
+ `cache_key` varchar(255) /*!40101 CHARACTER SET ascii COLLATE ascii_general_ci */ NOT NULL,
+ `created` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
+ `data` longtext NOT NULL,
+ INDEX `created_index` (`created`),
+ INDEX `cache_key_index` (`cache_key`)
+) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
diff --git a/SQL/mysql/2013061000.sql b/SQL/mysql/2013061000.sql
new file mode 100644
index 000000000..54041b340
--- /dev/null
+++ b/SQL/mysql/2013061000.sql
@@ -0,0 +1,24 @@
+ALTER TABLE `cache` ADD `expires` datetime DEFAULT NULL;
+ALTER TABLE `cache_shared` ADD `expires` datetime DEFAULT NULL;
+ALTER TABLE `cache_index` ADD `expires` datetime DEFAULT NULL;
+ALTER TABLE `cache_thread` ADD `expires` datetime DEFAULT NULL;
+ALTER TABLE `cache_messages` ADD `expires` datetime DEFAULT NULL;
+
+-- initialize expires column with created/changed date + 7days
+UPDATE `cache` SET `expires` = `created` + interval 604800 second;
+UPDATE `cache_shared` SET `expires` = `created` + interval 604800 second;
+UPDATE `cache_index` SET `expires` = `changed` + interval 604800 second;
+UPDATE `cache_thread` SET `expires` = `changed` + interval 604800 second;
+UPDATE `cache_messages` SET `expires` = `changed` + interval 604800 second;
+
+ALTER TABLE `cache` DROP INDEX `created_index`;
+ALTER TABLE `cache_shared` DROP INDEX `created_index`;
+ALTER TABLE `cache_index` DROP `changed`;
+ALTER TABLE `cache_thread` DROP `changed`;
+ALTER TABLE `cache_messages` DROP `changed`;
+
+ALTER TABLE `cache` ADD INDEX `expires_index` (`expires`);
+ALTER TABLE `cache_shared` ADD INDEX `expires_index` (`expires`);
+ALTER TABLE `cache_index` ADD INDEX `expires_index` (`expires`);
+ALTER TABLE `cache_thread` ADD INDEX `expires_index` (`expires`);
+ALTER TABLE `cache_messages` ADD INDEX `expires_index` (`expires`);
diff --git a/SQL/postgres.initial.sql b/SQL/postgres.initial.sql
index f3b368f7d..f18cb6ad0 100644
--- a/SQL/postgres.initial.sql
+++ b/SQL/postgres.initial.sql
@@ -164,14 +164,30 @@ CREATE INDEX contactgroupmembers_contact_id_idx ON contactgroupmembers (contact_
CREATE TABLE "cache" (
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,
+ expires timestamp with time zone DEFAULT NULL,
data text NOT NULL
);
CREATE INDEX cache_user_id_idx ON "cache" (user_id, cache_key);
-CREATE INDEX cache_created_idx ON "cache" (created);
+CREATE INDEX cache_expires_idx ON "cache" (expires);
+
+--
+-- Table "cache_shared"
+-- Name: cache_shared; Type: TABLE; Schema: public; Owner: postgres
+--
+
+CREATE TABLE "cache_shared" (
+ cache_key varchar(255) NOT NULL,
+ created timestamp with time zone DEFAULT now() NOT NULL,
+ expires timestamp with time zone DEFAULT NULL,
+ data text NOT NULL
+);
+
+CREATE INDEX cache_shared_cache_key_idx ON "cache_shared" (cache_key);
+CREATE INDEX cache_shared_expires_idx ON "cache_shared" (expires);
--
-- Table "cache_index"
@@ -180,15 +196,15 @@ CREATE INDEX cache_created_idx ON "cache" (created);
CREATE TABLE cache_index (
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,
mailbox varchar(255) NOT NULL,
- changed timestamp with time zone DEFAULT now() NOT NULL,
+ expires timestamp with time zone DEFAULT 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 INDEX cache_index_expires_idx ON cache_index (expires);
--
-- Table "cache_thread"
@@ -197,14 +213,14 @@ 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,
+ REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
mailbox varchar(255) NOT NULL,
- changed timestamp with time zone DEFAULT now() NOT NULL,
+ expires timestamp with time zone DEFAULT NULL,
data text NOT NULL,
PRIMARY KEY (user_id, mailbox)
);
-CREATE INDEX cache_thread_changed_idx ON cache_thread (changed);
+CREATE INDEX cache_thread_expires_idx ON cache_thread (expires);
--
-- Table "cache_messages"
@@ -213,16 +229,16 @@ 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,
+ 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,
+ expires timestamp with time zone DEFAULT 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);
+CREATE INDEX cache_messages_expires_idx ON cache_messages (expires);
--
-- Table "dictionary"
@@ -231,7 +247,7 @@ CREATE INDEX cache_messages_changed_idx ON cache_messages (changed);
CREATE TABLE dictionary (
user_id integer DEFAULT NULL
- REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
+ 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")
@@ -274,4 +290,4 @@ CREATE TABLE "system" (
value text
);
-INSERT INTO system (name, value) VALUES ('roundcube-version', '2013042700');
+INSERT INTO system (name, value) VALUES ('roundcube-version', '2013061000');
diff --git a/SQL/postgres/2013052500.sql b/SQL/postgres/2013052500.sql
new file mode 100644
index 000000000..471e57176
--- /dev/null
+++ b/SQL/postgres/2013052500.sql
@@ -0,0 +1,8 @@
+CREATE TABLE "cache_shared" (
+ cache_key varchar(255) NOT NULL,
+ created timestamp with time zone DEFAULT now() NOT NULL,
+ data text NOT NULL
+);
+
+CREATE INDEX cache_shared_cache_key_idx ON "cache_shared" (cache_key);
+CREATE INDEX cache_shared_created_idx ON "cache_shared" (created);
diff --git a/SQL/postgres/2013061000.sql b/SQL/postgres/2013061000.sql
new file mode 100644
index 000000000..9db0ebcd7
--- /dev/null
+++ b/SQL/postgres/2013061000.sql
@@ -0,0 +1,24 @@
+ALTER TABLE "cache" ADD expires timestamp with time zone DEFAULT NULL;
+ALTER TABLE "cache_shared" ADD expires timestamp with time zone DEFAULT NULL;
+ALTER TABLE "cache_index" ADD expires timestamp with time zone DEFAULT NULL;
+ALTER TABLE "cache_thread" ADD expires timestamp with time zone DEFAULT NULL;
+ALTER TABLE "cache_messages" ADD expires timestamp with time zone DEFAULT NULL;
+
+-- initialize expires column with created/changed date + 7days
+UPDATE "cache" SET expires = created + interval '604800 seconds';
+UPDATE "cache_shared" SET expires = created + interval '604800 seconds';
+UPDATE "cache_index" SET expires = changed + interval '604800 seconds';
+UPDATE "cache_thread" SET expires = changed + interval '604800 seconds';
+UPDATE "cache_messages" SET expires = changed + interval '604800 seconds';
+
+DROP INDEX cache_created_idx;
+DROP INDEX cache_shared_created_idx;
+ALTER TABLE "cache_index" DROP "changed";
+ALTER TABLE "cache_thread" DROP "changed";
+ALTER TABLE "cache_messages" DROP "changed";
+
+CREATE INDEX cache_expires_idx ON "cache" (expires);
+CREATE INDEX cache_shared_expires_idx ON "cache_shared" (expires);
+CREATE INDEX cache_index_expires_idx ON "cache_index" (expires);
+CREATE INDEX cache_thread_expires_idx ON "cache_thread" (expires);
+CREATE INDEX cache_messages_expires_idx ON "cache_messages" (expires);
diff --git a/SQL/sqlite.initial.sql b/SQL/sqlite.initial.sql
index d9bafb7e0..e7f74ddfc 100644
--- a/SQL/sqlite.initial.sql
+++ b/SQL/sqlite.initial.sql
@@ -1,23 +1,6 @@
-- Roundcube Webmail initial database structure
--
--- Table structure for table cache
---
-
-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',
- data text NOT NULL
-);
-
-CREATE INDEX ix_cache_user_cache_key ON cache(user_id, cache_key);
-CREATE INDEX ix_cache_created ON cache(created);
-
-
--- --------------------------------------------------------
-
---
-- Table structure for table contacts and related
--
@@ -57,9 +40,6 @@ CREATE TABLE contactgroupmembers (
CREATE INDEX ix_contactgroupmembers_contact_id ON contactgroupmembers (contact_id);
-
--- --------------------------------------------------------
-
--
-- Table structure for table identities
--
@@ -82,9 +62,6 @@ CREATE TABLE identities (
CREATE INDEX ix_identities_user_id ON identities(user_id, del);
CREATE INDEX ix_identities_email ON identities(email, del);
-
--- --------------------------------------------------------
-
--
-- Table structure for table users
--
@@ -101,8 +78,6 @@ CREATE TABLE users (
CREATE UNIQUE INDEX ix_users_username ON users(username, mail_host);
--- --------------------------------------------------------
-
--
-- Table structure for table session
--
@@ -117,8 +92,6 @@ CREATE TABLE session (
CREATE INDEX ix_session_changed ON session (changed);
--- --------------------------------------------------------
-
--
-- Table structure for table dictionary
--
@@ -131,8 +104,6 @@ CREATE TABLE dictionary (
CREATE UNIQUE INDEX ix_dictionary_user_language ON dictionary (user_id, "language");
--- --------------------------------------------------------
-
--
-- Table structure for table searches
--
@@ -147,7 +118,34 @@ CREATE TABLE searches (
CREATE UNIQUE INDEX ix_searches_user_type_name ON searches (user_id, type, name);
--- --------------------------------------------------------
+--
+-- Table structure for table cache
+--
+
+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',
+ expires datetime DEFAULT NULL,
+ data text NOT NULL
+);
+
+CREATE INDEX ix_cache_user_cache_key ON cache(user_id, cache_key);
+CREATE INDEX ix_cache_expires ON cache(expires);
+
+--
+-- Table structure for table cache_shared
+--
+
+CREATE TABLE cache_shared (
+ cache_key varchar(255) NOT NULL,
+ created datetime NOT NULL default '0000-00-00 00:00:00',
+ expires datetime DEFAULT NULL,
+ data text NOT NULL
+);
+
+CREATE INDEX ix_cache_shared_cache_key ON cache_shared(cache_key);
+CREATE INDEX ix_cache_shared_expires ON cache_shared(expires);
--
-- Table structure for table cache_index
@@ -156,15 +154,13 @@ CREATE UNIQUE INDEX ix_searches_user_type_name ON searches (user_id, type, name)
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',
+ expires datetime DEFAULT NULL,
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 INDEX ix_cache_index_expires ON cache_index (expires);
--
-- Table structure for table cache_thread
@@ -173,14 +169,12 @@ 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',
+ expires datetime DEFAULT NULL,
data text NOT NULL,
PRIMARY KEY (user_id, mailbox)
);
-CREATE INDEX ix_cache_thread_changed ON cache_thread (changed);
-
--- --------------------------------------------------------
+CREATE INDEX ix_cache_thread_expires ON cache_thread (expires);
--
-- Table structure for table cache_messages
@@ -190,15 +184,13 @@ 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',
+ expires datetime DEFAULT NULL,
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);
-
--- --------------------------------------------------------
+CREATE INDEX ix_cache_messages_expires ON cache_messages (expires);
--
-- Table structure for table system
@@ -209,4 +201,4 @@ CREATE TABLE system (
value text NOT NULL
);
-INSERT INTO system (name, value) VALUES ('roundcube-version', '2013042700');
+INSERT INTO system (name, value) VALUES ('roundcube-version', '2013061000');
diff --git a/SQL/sqlite/2013052500.sql b/SQL/sqlite/2013052500.sql
new file mode 100644
index 000000000..19ae1b110
--- /dev/null
+++ b/SQL/sqlite/2013052500.sql
@@ -0,0 +1,8 @@
+CREATE TABLE cache_shared (
+ cache_key varchar(255) NOT NULL,
+ created datetime NOT NULL default '0000-00-00 00:00:00',
+ data text NOT NULL
+);
+
+CREATE INDEX ix_cache_shared_cache_key ON cache_shared(cache_key);
+CREATE INDEX ix_cache_shared_created ON cache_shared(created);
diff --git a/SQL/sqlite/2013061000.sql b/SQL/sqlite/2013061000.sql
new file mode 100644
index 000000000..3c6b43eac
--- /dev/null
+++ b/SQL/sqlite/2013061000.sql
@@ -0,0 +1,48 @@
+DROP TABLE cache_index;
+DROP TABLE cache_thread;
+DROP TABLE cache_messages;
+
+ALTER TABLE cache ADD expires datetime DEFAULT NULL;
+DROP INDEX ix_cache_created;
+
+ALTER TABLE cache_shared ADD expires datetime DEFAULT NULL;
+DROP INDEX ix_cache_shared_created;
+
+UPDATE cache SET expires = datetime(created, '+604800 seconds');
+UPDATE cache_shared SET expires = datetime(created, '+604800 seconds');
+
+CREATE INDEX ix_cache_expires ON cache(expires);
+CREATE INDEX ix_cache_shared_expires ON cache_shared(expires);
+
+CREATE TABLE cache_index (
+ user_id integer NOT NULL,
+ mailbox varchar(255) NOT NULL,
+ expires datetime DEFAULT NULL,
+ valid smallint NOT NULL DEFAULT '0',
+ data text NOT NULL,
+ PRIMARY KEY (user_id, mailbox)
+);
+
+CREATE INDEX ix_cache_index_expires ON cache_index (expires);
+
+CREATE TABLE cache_thread (
+ user_id integer NOT NULL,
+ mailbox varchar(255) NOT NULL,
+ expires datetime DEFAULT NULL,
+ data text NOT NULL,
+ PRIMARY KEY (user_id, mailbox)
+);
+
+CREATE INDEX ix_cache_thread_expires ON cache_thread (expires);
+
+CREATE TABLE cache_messages (
+ user_id integer NOT NULL,
+ mailbox varchar(255) NOT NULL,
+ uid integer NOT NULL,
+ expires datetime DEFAULT NULL,
+ data text NOT NULL,
+ flags integer NOT NULL DEFAULT '0',
+ PRIMARY KEY (user_id, mailbox, uid)
+);
+
+CREATE INDEX ix_cache_messages_expires ON cache_messages (expires);
diff --git a/UPGRADING b/UPGRADING
index 03d549920..86ddde620 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -32,19 +32,23 @@ it on a unix system, you need to do the following operations by hand:
- ./bin/
- ./SQL/
- ./program/
-2. rsync the contents of the following folders from your installation
+ - ./installer/
+2. Replace the configuration defaults files:
+ - config/defaults.inc.php
+ - config/mimetypes.php
+3. rsync the contents of the following folders from your installation
directory into the target folder:
./skins/
./plugins/
-3. Run ./bin/update.sh from the commandline OR
+4. Run ./bin/update.sh from the commandline OR
open http://url-to-roundcube/installer/ in a browser and choose "3 Test config".
To enable the latter one, you have to temporary set 'enable_installer'
- to true in your local config/main.inc.php file.
+ to true in your local config/config.inc.php file.
WARNING: See SQLite database upgrade below.
-4. Let the update script/installer check your configuration and
+5. Let the update script/installer check your configuration and
update your config files and database schema as suggested by the updater.
-5. Make sure 'enable_installer' is set to false again.
-6. See Post-Upgrade Activities section.
+6. Make sure 'enable_installer' is set to false again.
+7. See Post-Upgrade Activities section.
Post-Upgrade Activities
diff --git a/bin/gc.sh b/bin/gc.sh
new file mode 100755
index 000000000..1ee610741
--- /dev/null
+++ b/bin/gc.sh
@@ -0,0 +1,27 @@
+#!/usr/bin/env php
+<?php
+/*
+ +-----------------------------------------------------------------------+
+ | bin/gc.sh |
+ | |
+ | This file is part of the Roundcube Webmail client |
+ | Copyright (C) 2013, The Roundcube Dev Team |
+ | |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
+ | |
+ | PURPOSE: |
+ | Trigger garbage collecting routines manually (e.g. via cronjob) |
+ | |
+ +-----------------------------------------------------------------------+
+ | Author: Thomas Bruederli <roundcube@gmail.com> |
+ +-----------------------------------------------------------------------+
+*/
+
+define('INSTALL_PATH', realpath(dirname(__FILE__) . '/..') . '/' );
+
+require INSTALL_PATH.'program/include/clisetup.php';
+
+$rcmail = rcube::get_instance();
+$rcmail->gc();
diff --git a/bin/installto.sh b/bin/installto.sh
index 8e1ab1fbf..269a5dc06 100755
--- a/bin/installto.sh
+++ b/bin/installto.sh
@@ -50,7 +50,7 @@ if (strtolower($input) == 'y') {
break;
}
}
- foreach (array('index.php','.htaccess','config/main.inc.php.dist','config/db.inc.php.dist','CHANGELOG','README.md','UPGRADING','LICENSE') as $file) {
+ foreach (array('index.php','.htaccess','config/defaults.inc.php','CHANGELOG','README.md','UPGRADING','LICENSE') as $file) {
if (!system("rsync -av " . INSTALL_PATH . "$file $target_dir/$file")) {
$err = true;
break;
diff --git a/bin/update.sh b/bin/update.sh
index 05956b933..71e2c630a 100755
--- a/bin/update.sh
+++ b/bin/update.sh
@@ -5,7 +5,7 @@
| bin/update.sh |
| |
| This file is part of the Roundcube Webmail client |
- | Copyright (C) 2010-2011, The Roundcube Dev Team |
+ | Copyright (C) 2010-2013, The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
@@ -25,7 +25,7 @@ require_once INSTALL_PATH . 'program/include/clisetup.php';
require_once INSTALL_PATH . 'installer/rcube_install.php';
// get arguments
-$opts = rcube_utils::get_opt(array('v' => 'version'));
+$opts = rcube_utils::get_opt(array('v' => 'version', 'y' => 'accept'));
// ask user if no version is specified
if (!$opts['version']) {
@@ -36,32 +36,16 @@ if (!$opts['version']) {
$opts['version'] = RCMAIL_VERSION;
}
-if ($opts['version'] && version_compare(version_parse($opts['version']), version_parse(RCMAIL_VERSION), '>='))
- die("Nothing to be done here. Bye!\n");
-
-
$RCI = rcube_install::get_instance();
$RCI->load_config();
if ($RCI->configured) {
$success = true;
-
- if ($messages = $RCI->check_config()) {
+
+ if (($messages = $RCI->check_config()) || $RCI->legacy_config) {
$success = false;
$err = 0;
- // list missing config options
- if (is_array($messages['missing'])) {
- echo "WARNING: Missing config options:\n";
- echo "(These config options should be present in the current configuration)\n";
-
- foreach ($messages['missing'] as $msg) {
- echo "- '" . $msg['prop'] . ($msg['name'] ? "': " . $msg['name'] : "'") . "\n";
- $err++;
- }
- echo "\n";
- }
-
// list old/replaced config options
if (is_array($messages['replaced'])) {
echo "WARNING: Replaced config options:\n";
@@ -86,31 +70,42 @@ if ($RCI->configured) {
echo "\n";
}
+ if (!$err && $RCI->legacy_config) {
+ echo "WARNING: Your configuration needs to be migrated!\n";
+ echo "We changed the configuration files structure and your two config files main.inc.php and db.inc.php have to be merged into one single file.\n";
+ $err++;
+ }
+
// ask user to update config files
if ($err) {
- echo "Do you want me to fix your local configuration? (y/N)\n";
- $input = trim(fgets(STDIN));
+ if (!$opts['accept']) {
+ echo "Do you want me to fix your local configuration? (y/N)\n";
+ $input = trim(fgets(STDIN));
+ }
// positive: let's merge the local config with the defaults
- if (strtolower($input) == 'y') {
- $copy1 = $copy2 = $write1 = $write2 = false;
-
+ if ($opts['accept'] || strtolower($input) == 'y') {
+ $error = $written = false;
+
// backup current config
- echo ". backing up the current config files...\n";
- $copy1 = copy(RCMAIL_CONFIG_DIR . '/main.inc.php', RCMAIL_CONFIG_DIR . '/main.old.php');
- $copy2 = copy(RCMAIL_CONFIG_DIR . '/db.inc.php', RCMAIL_CONFIG_DIR . '/db.old.php');
-
- if ($copy1 && $copy2) {
+ echo ". backing up the current config file(s)...\n";
+
+ foreach (array('config', 'main', 'db') as $file) {
+ if (file_exists(RCMAIL_CONFIG_DIR . '/' . $file . '.inc.php')) {
+ if (!copy(RCMAIL_CONFIG_DIR . '/' . $file . '.inc.php', RCMAIL_CONFIG_DIR . '/' . $file . '.old.php')) {
+ $error = true;
+ }
+ }
+ }
+
+ if (!$error) {
$RCI->merge_config();
-
- echo ". writing " . RCMAIL_CONFIG_DIR . "/main.inc.php...\n";
- $write1 = file_put_contents(RCMAIL_CONFIG_DIR . '/main.inc.php', $RCI->create_config('main', true));
- echo ". writing " . RCMAIL_CONFIG_DIR . "/main.db.php...\n";
- $write2 = file_put_contents(RCMAIL_CONFIG_DIR . '/db.inc.php', $RCI->create_config('db', true));
+ echo ". writing " . RCMAIL_CONFIG_DIR . "/config.inc.php...\n";
+ $written = file_put_contents(RCMAIL_CONFIG_DIR . '/config.inc.php', $RCI->create_config());
}
-
+
// Success!
- if ($write1 && $write2) {
+ if ($written) {
echo "Done.\n";
echo "Your configuration files are now up-to-date!\n";
@@ -119,9 +114,15 @@ if ($RCI->configured) {
foreach ($messages['missing'] as $msg)
echo "- '" . $msg['prop'] . ($msg['name'] ? "': " . $msg['name'] : "'") . "\n";
}
+
+ if ($RCI->legacy_config) {
+ foreach (array('main', 'db') as $file) {
+ @unlink(RCMAIL_CONFIG_DIR . '/' . $file . '.inc.php');
+ }
+ }
}
else {
- echo "Failed to write config files!\n";
+ echo "Failed to write config file(s)!\n";
echo "Grant write privileges to the current user or update the files manually according to the above messages.\n";
}
}
@@ -143,6 +144,16 @@ if ($RCI->configured) {
}
}
+ // check file type detection
+ if ($RCI->check_mime_detection()) {
+ echo "WARNING: File type detection doesn't work properly!\n";
+ echo "Please check the 'mime_magic' config option or the finfo functions of PHP andrun this script again.\n";
+ }
+ if ($RCI->check_mime_extensions()) {
+ echo "WARNING: Mimetype to file extension mapping doesn't work properly!\n";
+ echo "Please check the 'mime_types' config option and run this script again.\n";
+ }
+
// check database schema
if ($RCI->config['db_dsnw']) {
echo "Executing database schema update.\n";
@@ -153,7 +164,7 @@ if ($RCI->configured) {
}
// index contacts for fulltext searching
- if (version_compare(version_parse($opts['version']), '0.6.0', '<')) {
+ if ($opts['version'] && version_compare(version_parse($opts['version']), '0.6.0', '<')) {
system(INSTALL_PATH . 'bin/indexcontacts.sh');
}
diff --git a/composer.json-dist b/composer.json-dist
index 1c2ac80bd..e7462038d 100644
--- a/composer.json-dist
+++ b/composer.json-dist
@@ -10,7 +10,7 @@
],
"require": {
"php": ">=5.3.0",
- "roundcube/plugin-installer": ">=0.1.2"
+ "roundcube/plugin-installer": ">=0.1.3"
},
"minimum-stability": "dev"
}
diff --git a/config/config.inc.php.sample b/config/config.inc.php.sample
new file mode 100644
index 000000000..9a42ba9f5
--- /dev/null
+++ b/config/config.inc.php.sample
@@ -0,0 +1,85 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | Local configuration for the Roundcube Webmail installation. |
+ | |
+ | This is a sample configuration file only containing the minumum |
+ | setup required for a functional installation. Copy more options |
+ | from defaults.inc.php to this file to override the defaults. |
+ | |
+ | This file is part of the Roundcube Webmail client |
+ | Copyright (C) 2005-2013, The Roundcube Dev Team |
+ | |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
+ +-----------------------------------------------------------------------+
+*/
+
+$config = array();
+
+// Database connection string (DSN) for read+write operations
+// Format (compatible with PEAR MDB2): db_provider://user:password@host/database
+// Currently supported db_providers: mysql, pgsql, sqlite, mssql or sqlsrv
+// For examples see http://pear.php.net/manual/en/package.database.mdb2.intro-dsn.php
+// NOTE: for SQLite use absolute path: 'sqlite:////full/path/to/sqlite.db?mode=0646'
+$config['db_dsnw'] = 'mysql://roundcube:pass@localhost/roundcubemail';
+
+// The mail host chosen to perform the log-in.
+// Leave blank to show a textbox at login, give a list of hosts
+// to display a pulldown menu or set one host as string.
+// To use SSL/TLS connection, enter hostname with prefix ssl:// or tls://
+// Supported replacement variables:
+// %n - hostname ($_SERVER['SERVER_NAME'])
+// %t - hostname without the first part
+// %d - domain (http hostname $_SERVER['HTTP_HOST'] without the first part)
+// %s - domain name after the '@' from e-mail address provided at login screen
+// For example %n = mail.domain.tld, %t = domain.tld
+$config['default_host'] = 'localhost';
+
+// SMTP server host (for sending mails).
+// To use SSL/TLS connection, enter hostname with prefix ssl:// or tls://
+// If left blank, the PHP mail() function is used
+// Supported replacement variables:
+// %h - user's IMAP hostname
+// %n - hostname ($_SERVER['SERVER_NAME'])
+// %t - hostname without the first part
+// %d - domain (http hostname $_SERVER['HTTP_HOST'] without the first part)
+// %z - IMAP domain (IMAP hostname without the first part)
+// For example %n = mail.domain.tld, %t = domain.tld
+$config['smtp_server'] = '';
+
+// SMTP port (default is 25; use 587 for STARTTLS or 465 for the
+// deprecated SSL over SMTP (aka SMTPS))
+$config['smtp_port'] = 25;
+
+// SMTP username (if required) if you use %u as the username Roundcube
+// will use the current username for login
+$config['smtp_user'] = '';
+
+// SMTP password (if required) if you use %p as the password Roundcube
+// will use the current user's password for login
+$config['smtp_pass'] = '';
+
+// provide an URL where a user can get support for this Roundcube installation
+// PLEASE DO NOT LINK TO THE ROUNDCUBE.NET WEBSITE HERE!
+$config['support_url'] = '';
+
+// Name your service. This is displayed on the login screen and in the window title
+$config['product_name'] = 'Roundcube Webmail';
+
+// this key is used to encrypt the users imap password which is stored
+// in the session record (and the client cookie if remember password is enabled).
+// please provide a string of exactly 24 chars.
+// YOUR KEY MUST BE DIFFERENT THAN THE SAMPLE VALUE FOR SECURITY REASONS
+$config['des_key'] = 'rcmail-!24ByteDESkey*Str';
+
+// List of active plugins (in plugins/ directory)
+$config['plugins'] = array(
+ 'archive',
+ 'zipdownload',
+);
+
+// skin name: folder from skins/
+$config['skin'] = 'larry';
diff --git a/config/db.inc.php.dist b/config/db.inc.php.dist
deleted file mode 100644
index b1f142e56..000000000
--- a/config/db.inc.php.dist
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php
-
-/*
- +-----------------------------------------------------------------------+
- | Configuration file for database access |
- | |
- | This file is part of the Roundcube Webmail client |
- | Copyright (C) 2005-2013, The Roundcube Dev Team |
- | |
- | Licensed under the GNU General Public License version 3 or |
- | any later version with exceptions for skins & plugins. |
- | See the README file for a full license statement. |
- +-----------------------------------------------------------------------+
-*/
-
-$rcmail_config = array();
-
-// Database connection string (DSN) for read+write operations
-// Format (compatible with PEAR MDB2): db_provider://user:password@host/database
-// Currently supported db_providers: mysql, pgsql, sqlite, mssql or sqlsrv
-// For examples see http://pear.php.net/manual/en/package.database.mdb2.intro-dsn.php
-// NOTE: for SQLite use absolute path: 'sqlite:////full/path/to/sqlite.db?mode=0646'
-$rcmail_config['db_dsnw'] = 'mysql://roundcube:pass@localhost/roundcubemail';
-
-// Database DSN for read-only operations (if empty write database will be used)
-// useful for database replication
-$rcmail_config['db_dsnr'] = '';
-
-// use persistent db-connections
-// beware this will not "always" work as expected
-// see: http://www.php.net/manual/en/features.persistent-connections.php
-$rcmail_config['db_persistent'] = FALSE;
-
-// you can define specific table (and sequence) names prefix
-$rcmail_config['db_prefix'] = '';
diff --git a/config/main.inc.php.dist b/config/defaults.inc.php
index 4a73ff119..32dba4918 100644
--- a/config/main.inc.php.dist
+++ b/config/defaults.inc.php
@@ -2,62 +2,84 @@
/*
+-----------------------------------------------------------------------+
- | Main configuration file |
+ | Main configuration file with default settings |
| |
| This file is part of the Roundcube Webmail client |
- | Copyright (C) 2005-2011, The Roundcube Dev Team |
+ | Copyright (C) 2005-2013, The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
- | |
+-----------------------------------------------------------------------+
-
*/
-$rcmail_config = array();
+$config = array();
+
+// ----------------------------------
+// SQL DATABASE
+// ----------------------------------
+
+// Database connection string (DSN) for read+write operations
+// Format (compatible with PEAR MDB2): db_provider://user:password@host/database
+// Currently supported db_providers: mysql, pgsql, sqlite, mssql or sqlsrv
+// For examples see http://pear.php.net/manual/en/package.database.mdb2.intro-dsn.php
+// NOTE: for SQLite use absolute path: 'sqlite:////full/path/to/sqlite.db?mode=0646'
+$config['db_dsnw'] = 'mysql://roundcube:@localhost/roundcubemail';
+
+// Database DSN for read-only operations (if empty write database will be used)
+// useful for database replication
+$config['db_dsnr'] = '';
+
+// use persistent db-connections
+// beware this will not "always" work as expected
+// see: http://www.php.net/manual/en/features.persistent-connections.php
+$config['db_persistent'] = false;
+
+// you can define specific table (and sequence) names prefix
+$config['db_prefix'] = '';
+
// ----------------------------------
// LOGGING/DEBUGGING
// ----------------------------------
// system error reporting, sum of: 1 = log; 4 = show, 8 = trace
-$rcmail_config['debug_level'] = 1;
+$config['debug_level'] = 1;
// log driver: 'syslog' or 'file'.
-$rcmail_config['log_driver'] = 'file';
+$config['log_driver'] = 'file';
// date format for log entries
// (read http://php.net/manual/en/function.date.php for all format characters)
-$rcmail_config['log_date_format'] = 'd-M-Y H:i:s O';
+$config['log_date_format'] = 'd-M-Y H:i:s O';
// Syslog ident string to use, if using the 'syslog' log driver.
-$rcmail_config['syslog_id'] = 'roundcube';
+$config['syslog_id'] = 'roundcube';
// Syslog facility to use, if using the 'syslog' log driver.
// For possible values see installer or http://php.net/manual/en/function.openlog.php
-$rcmail_config['syslog_facility'] = LOG_USER;
+$config['syslog_facility'] = LOG_USER;
// Log sent messages to <log_dir>/sendmail or to syslog
-$rcmail_config['smtp_log'] = true;
+$config['smtp_log'] = true;
// Log successful logins to <log_dir>/userlogins or to syslog
-$rcmail_config['log_logins'] = false;
+$config['log_logins'] = false;
// Log session authentication errors to <log_dir>/session or to syslog
-$rcmail_config['log_session'] = false;
+$config['log_session'] = false;
// Log SQL queries to <log_dir>/sql or to syslog
-$rcmail_config['sql_debug'] = false;
+$config['sql_debug'] = false;
// Log IMAP conversation to <log_dir>/imap or to syslog
-$rcmail_config['imap_debug'] = false;
+$config['imap_debug'] = false;
// Log LDAP conversation to <log_dir>/ldap or to syslog
-$rcmail_config['ldap_debug'] = false;
+$config['ldap_debug'] = false;
// Log SMTP conversation to <log_dir>/smtp or to syslog
-$rcmail_config['smtp_debug'] = false;
+$config['smtp_debug'] = false;
// ----------------------------------
// IMAP
@@ -75,18 +97,18 @@ $rcmail_config['smtp_debug'] = false;
// For example %n = mail.domain.tld, %t = domain.tld
// WARNING: After hostname change update of mail_host column in users table is
// required to match old user data records with the new host.
-$rcmail_config['default_host'] = '';
+$config['default_host'] = 'localhost';
// TCP port used for IMAP connections
-$rcmail_config['default_port'] = 143;
+$config['default_port'] = 143;
// IMAP AUTH type (DIGEST-MD5, CRAM-MD5, LOGIN, PLAIN or null to use
// best server supported one)
-$rcmail_config['imap_auth_type'] = null;
+$config['imap_auth_type'] = null;
// If you know your imap's folder delimiter, you can specify it here.
// Otherwise it will be determined automatically
-$rcmail_config['imap_delimiter'] = null;
+$config['imap_delimiter'] = null;
// If IMAP server doesn't support NAMESPACE extension, but you're
// using shared folders or personal root folder is non-empty, you'll need to
@@ -94,40 +116,53 @@ $rcmail_config['imap_delimiter'] = null;
// Folders need to be ended with directory separator, e.g. "INBOX."
// (special directory "~" is an exception to this rule)
// These can be used also to overwrite server's namespaces
-$rcmail_config['imap_ns_personal'] = null;
-$rcmail_config['imap_ns_other'] = null;
-$rcmail_config['imap_ns_shared'] = null;
+$config['imap_ns_personal'] = null;
+$config['imap_ns_other'] = null;
+$config['imap_ns_shared'] = null;
// By default IMAP capabilities are readed after connection to IMAP server
// In some cases, e.g. when using IMAP proxy, there's a need to refresh the list
// after login. Set to True if you've got this case.
-$rcmail_config['imap_force_caps'] = false;
+$config['imap_force_caps'] = false;
// By default list of subscribed folders is determined using LIST-EXTENDED
// extension if available. Some servers (dovecot 1.x) returns wrong results
// for shared namespaces in this case. http://trac.roundcube.net/ticket/1486225
// Enable this option to force LSUB command usage instead.
-$rcmail_config['imap_force_lsub'] = false;
+// Deprecated: Use imap_disabled_caps = array('LIST-EXTENDED')
+$config['imap_force_lsub'] = false;
// Some server configurations (e.g. Courier) doesn't list folders in all namespaces
// Enable this option to force listing of folders in all namespaces
-$rcmail_config['imap_force_ns'] = false;
+$config['imap_force_ns'] = false;
+
+// List of disabled imap extensions.
+// Use if your IMAP server has broken implementation of some feature
+// and you can't remove it from CAPABILITY string on server-side.
+// For example UW-IMAP server has broken ESEARCH.
+// Note: Because the list is cached, re-login is required after change.
+$config['imap_disabled_caps'] = array();
// IMAP connection timeout, in seconds. Default: 0 (no limit)
-$rcmail_config['imap_timeout'] = 0;
+$config['imap_timeout'] = 0;
// Optional IMAP authentication identifier to be used as authorization proxy
-$rcmail_config['imap_auth_cid'] = null;
+$config['imap_auth_cid'] = null;
// Optional IMAP authentication password to be used for imap_auth_cid
-$rcmail_config['imap_auth_pw'] = null;
+$config['imap_auth_pw'] = null;
// Type of IMAP indexes cache. Supported values: 'db', 'apc' and 'memcache'.
-$rcmail_config['imap_cache'] = null;
+$config['imap_cache'] = null;
// Enables messages cache. Only 'db' cache is supported.
-$rcmail_config['messages_cache'] = false;
+$config['messages_cache'] = false;
+// Lifetime of IMAP indexes cache. Possible units: s, m, h, d, w
+$config['imap_cache_ttl'] = '10d';
+
+// Lifetime of messages cache. Possible units: s, m, h, d, w
+$config['messages_cache_ttl'] = '10d';
// ----------------------------------
// SMTP
@@ -143,38 +178,50 @@ $rcmail_config['messages_cache'] = false;
// %d - domain (http hostname $_SERVER['HTTP_HOST'] without the first part)
// %z - IMAP domain (IMAP hostname without the first part)
// For example %n = mail.domain.tld, %t = domain.tld
-$rcmail_config['smtp_server'] = '';
+$config['smtp_server'] = '';
// SMTP port (default is 25; use 587 for STARTTLS or 465 for the
// deprecated SSL over SMTP (aka SMTPS))
-$rcmail_config['smtp_port'] = 25;
+$config['smtp_port'] = 25;
// SMTP username (if required) if you use %u as the username Roundcube
// will use the current username for login
-$rcmail_config['smtp_user'] = '';
+$config['smtp_user'] = '';
// SMTP password (if required) if you use %p as the password Roundcube
// will use the current user's password for login
-$rcmail_config['smtp_pass'] = '';
+$config['smtp_pass'] = '';
// SMTP AUTH type (DIGEST-MD5, CRAM-MD5, LOGIN, PLAIN or empty to use
// best server supported one)
-$rcmail_config['smtp_auth_type'] = '';
+$config['smtp_auth_type'] = '';
// Optional SMTP authentication identifier to be used as authorization proxy
-$rcmail_config['smtp_auth_cid'] = null;
+$config['smtp_auth_cid'] = null;
// Optional SMTP authentication password to be used for smtp_auth_cid
-$rcmail_config['smtp_auth_pw'] = null;
+$config['smtp_auth_pw'] = null;
// SMTP HELO host
// Hostname to give to the remote server for SMTP 'HELO' or 'EHLO' messages
// Leave this blank and you will get the server variable 'server_name' or
-// localhost if that isn't defined.
-$rcmail_config['smtp_helo_host'] = '';
+// localhost if that isn't defined.
+$config['smtp_helo_host'] = '';
// SMTP connection timeout, in seconds. Default: 0 (no limit)
-$rcmail_config['smtp_timeout'] = 0;
+// Note: There's a known issue where using ssl connection with
+// timeout > 0 causes connection errors (https://bugs.php.net/bug.php?id=54511)
+$config['smtp_timeout'] = 0;
+
+// ----------------------------------
+// LDAP
+// ----------------------------------
+
+// Type of LDAP cache. Supported values: 'db', 'apc' and 'memcache'.
+$config['ldap_cache'] = 'db';
+
+// Lifetime of LDAP cache. Possible units: s, m, h, d, w
+$config['ldap_cache_ttl'] = '10m';
// ----------------------------------
// SYSTEM
@@ -182,101 +229,98 @@ $rcmail_config['smtp_timeout'] = 0;
// THIS OPTION WILL ALLOW THE INSTALLER TO RUN AND CAN EXPOSE SENSITIVE CONFIG DATA.
// ONLY ENABLE IT IF YOU'RE REALLY SURE WHAT YOU'RE DOING!
-$rcmail_config['enable_installer'] = false;
+$config['enable_installer'] = false;
// don't allow these settings to be overriden by the user
-$rcmail_config['dont_override'] = array();
+$config['dont_override'] = array();
// provide an URL where a user can get support for this Roundcube installation
// PLEASE DO NOT LINK TO THE ROUNDCUBE.NET WEBSITE HERE!
-$rcmail_config['support_url'] = '';
+$config['support_url'] = '';
// replace Roundcube logo with this image
// specify an URL relative to the document root of this Roundcube installation
-$rcmail_config['skin_logo'] = null;
+$config['skin_logo'] = null;
// automatically create a new Roundcube user when log-in the first time.
// a new user will be created once the IMAP login succeeds.
// set to false if only registered users can use this service
-$rcmail_config['auto_create_user'] = true;
+$config['auto_create_user'] = true;
// Enables possibility to log in using email address from user identities
-$rcmail_config['user_aliases'] = false;
+$config['user_aliases'] = false;
// use this folder to store log files (must be writeable for apache user)
// This is used by the 'file' log driver.
-$rcmail_config['log_dir'] = 'logs/';
+$config['log_dir'] = 'logs/';
// use this folder to store temp files (must be writeable for apache user)
-$rcmail_config['temp_dir'] = 'temp/';
-
-// lifetime of message cache
-// possible units: s, m, h, d, w
-$rcmail_config['message_cache_lifetime'] = '10d';
+$config['temp_dir'] = 'temp/';
// enforce connections over https
// with this option enabled, all non-secure connections will be redirected.
// set the port for the ssl connection as value of this option if it differs from the default 443
-$rcmail_config['force_https'] = false;
+$config['force_https'] = false;
// tell PHP that it should work as under secure connection
// even if it doesn't recognize it as secure ($_SERVER['HTTPS'] is not set)
// e.g. when you're running Roundcube behind a https proxy
// this option is mutually exclusive to 'force_https' and only either one of them should be set to true.
-$rcmail_config['use_https'] = false;
+$config['use_https'] = false;
// Allow browser-autocompletion on login form.
// 0 - disabled, 1 - username and host only, 2 - username, host, password
-$rcmail_config['login_autocomplete'] = 0;
+$config['login_autocomplete'] = 0;
// Forces conversion of logins to lower case.
// 0 - disabled, 1 - only domain part, 2 - domain and local part.
// If users authentication is case-insensitive this must be enabled.
// Note: After enabling it all user records need to be updated, e.g. with query:
// UPDATE users SET username = LOWER(username);
-$rcmail_config['login_lc'] = 2;
+$config['login_lc'] = 2;
// Includes should be interpreted as PHP files
-$rcmail_config['skin_include_php'] = false;
+$config['skin_include_php'] = false;
// display software version on login screen
-$rcmail_config['display_version'] = false;
+$config['display_version'] = false;
// Session lifetime in minutes
-$rcmail_config['session_lifetime'] = 10;
+$config['session_lifetime'] = 10;
// Session domain: .example.org
-$rcmail_config['session_domain'] = '';
+$config['session_domain'] = '';
// Session name. Default: 'roundcube_sessid'
-$rcmail_config['session_name'] = null;
+$config['session_name'] = null;
// Session path. Defaults to PHP session.cookie_path setting.
-$rcmail_config['session_path'] = null;
+$config['session_path'] = 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'
+// Backend to use for session storage. Can either be 'db' (default), 'memcache' or 'php'
+// 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
-$rcmail_config['session_storage'] = 'db';
+// Setting this value to 'php' will use the default session save handler configured in PHP
+$config['session_storage'] = 'db';
// Use these hosts for accessing memcached
// Define any number of hosts in the form of hostname:port or unix:///path/to/socket.file
-$rcmail_config['memcache_hosts'] = null; // e.g. array( 'localhost:11211', '192.168.1.12:11211', 'unix:///var/tmp/memcached.sock' );
+$config['memcache_hosts'] = null; // e.g. array( 'localhost:11211', '192.168.1.12:11211', 'unix:///var/tmp/memcached.sock' );
// check client IP in session athorization
-$rcmail_config['ip_check'] = false;
+$config['ip_check'] = false;
// check referer of incoming requests
-$rcmail_config['referer_check'] = false;
+$config['referer_check'] = false;
// X-Frame-Options HTTP header value sent to prevent from Clickjacking.
// Possible values: sameorigin|deny. Set to false in order to disable sending them
-$rcmail_config['x_frame_options'] = 'sameorigin';
+$config['x_frame_options'] = 'sameorigin';
// this key is used to encrypt the users imap password which is stored
// in the session record (and the client cookie if remember password is enabled).
// please provide a string of exactly 24 chars.
-$rcmail_config['des_key'] = 'rcmail-!24ByteDESkey*Str';
+$config['des_key'] = 'rcmail-!24ByteDESkey*Str';
// Automatically add this domain to user names for login
// Only for IMAP servers that require full e-mail addresses for login
@@ -288,7 +332,7 @@ $rcmail_config['des_key'] = 'rcmail-!24ByteDESkey*Str';
// %d - domain (http hostname $_SERVER['HTTP_HOST'] without the first part)
// %z - IMAP domain (IMAP hostname without the first part)
// For example %n = mail.domain.tld, %t = domain.tld
-$rcmail_config['username_domain'] = '';
+$config['username_domain'] = '';
// This domain will be used to form e-mail addresses of new users
// Specify an array with 'host' => 'domain' values to support multiple hosts
@@ -298,64 +342,64 @@ $rcmail_config['username_domain'] = '';
// %d - domain (http hostname without the first part)
// %z - IMAP domain (IMAP hostname without the first part)
// For example %n = mail.domain.tld, %t = domain.tld
-$rcmail_config['mail_domain'] = '';
+$config['mail_domain'] = '';
// Password charset.
// Use it if your authentication backend doesn't support UTF-8.
// Defaults to ISO-8859-1 for backward compatibility
-$rcmail_config['password_charset'] = 'ISO-8859-1';
+$config['password_charset'] = 'ISO-8859-1';
// How many seconds must pass between emails sent by a user
-$rcmail_config['sendmail_delay'] = 0;
+$config['sendmail_delay'] = 0;
// Maximum number of recipients per message. Default: 0 (no limit)
-$rcmail_config['max_recipients'] = 0;
+$config['max_recipients'] = 0;
// Maximum allowednumber of members of an address group. Default: 0 (no limit)
// If 'max_recipients' is set this value should be less or equal
-$rcmail_config['max_group_members'] = 0;
+$config['max_group_members'] = 0;
-// add this user-agent to message headers when sending
-$rcmail_config['useragent'] = 'Roundcube Webmail/'.RCMAIL_VERSION;
+// Name your service. This is displayed on the login screen and in the window title
+$config['product_name'] = 'Roundcube Webmail';
-// use this name to compose page titles
-$rcmail_config['product_name'] = 'Roundcube Webmail';
+// Add this user-agent to message headers when sending
+$config['useragent'] = 'Roundcube Webmail/'.RCMAIL_VERSION;
// try to load host-specific configuration
// see http://trac.roundcube.net/wiki/Howto_Config for more details
-$rcmail_config['include_host_config'] = false;
+$config['include_host_config'] = false;
// path to a text file which will be added to each sent message
// paths are relative to the Roundcube root folder
-$rcmail_config['generic_message_footer'] = '';
+$config['generic_message_footer'] = '';
// path to a text file which will be added to each sent HTML message
// paths are relative to the Roundcube root folder
-$rcmail_config['generic_message_footer_html'] = '';
+$config['generic_message_footer_html'] = '';
// add a received header to outgoing mails containing the creators IP and hostname
-$rcmail_config['http_received_header'] = false;
+$config['http_received_header'] = false;
// Whether or not to encrypt the IP address and the host name
// these could, in some circles, be considered as sensitive information;
// however, for the administrator, these could be invaluable help
// when tracking down issues.
-$rcmail_config['http_received_header_encrypt'] = false;
+$config['http_received_header_encrypt'] = false;
// This string is used as a delimiter for message headers when sending
// a message via mail() function. Leave empty for auto-detection
-$rcmail_config['mail_header_delimiter'] = NULL;
+$config['mail_header_delimiter'] = NULL;
// number of chars allowed for line when wrapping text.
// text wrapping is done when composing/sending messages
-$rcmail_config['line_length'] = 72;
+$config['line_length'] = 72;
// send plaintext messages as format=flowed
-$rcmail_config['send_format_flowed'] = true;
+$config['send_format_flowed'] = true;
// According to RFC2298, return receipt envelope sender address must be empty.
// If this option is true, Roundcube will use user's identity as envelope sender for MDN responses.
-$rcmail_config['mdn_use_from'] = false;
+$config['mdn_use_from'] = false;
// Set identities access level:
// 0 - many identities with possibility to edit all params
@@ -363,50 +407,50 @@ $rcmail_config['mdn_use_from'] = false;
// 2 - one identity with possibility to edit all params
// 3 - one identity with possibility to edit all params but not email address
// 4 - one identity with possibility to edit only signature
-$rcmail_config['identities_level'] = 0;
+$config['identities_level'] = 0;
// Mimetypes supported by the browser.
// attachments of these types will open in a preview window
// either a comma-separated list or an array: 'text/plain,text/html,text/xml,image/jpeg,image/gif,image/png,application/pdf'
-$rcmail_config['client_mimetypes'] = null; # null == default
+$config['client_mimetypes'] = null; # null == default
// Path to a local mime magic database file for PHPs finfo extension.
// Set to null if the default path should be used.
-$rcmail_config['mime_magic'] = null;
+$config['mime_magic'] = null;
// Absolute path to a local mime.types mapping table file.
// This is used to derive mime-types from the filename extension or vice versa.
// Such a file is usually part of the apache webserver. If you don't find a file named mime.types on your system,
// download it from http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
-$rcmail_config['mime_types'] = null;
+$config['mime_types'] = null;
// path to imagemagick identify binary
-$rcmail_config['im_identify_path'] = null;
+$config['im_identify_path'] = null;
// path to imagemagick convert binary
-$rcmail_config['im_convert_path'] = null;
+$config['im_convert_path'] = null;
// Size of thumbnails from image attachments displayed below the message content.
// Note: whether images are displayed at all depends on the 'inline_images' option.
// Set to 0 to display images in full size.
-$rcmail_config['image_thumbnail_size'] = 240;
+$config['image_thumbnail_size'] = 240;
// maximum size of uploaded contact photos in pixel
-$rcmail_config['contact_photo_size'] = 160;
+$config['contact_photo_size'] = 160;
// Enable DNS checking for e-mail address validation
-$rcmail_config['email_dns_check'] = false;
+$config['email_dns_check'] = false;
// Disables saving sent messages in Sent folder (like gmail) (Default: false)
// Note: useful when SMTP server stores sent mail in user mailbox
-$rcmail_config['no_save_sent_messages'] = false;
+$config['no_save_sent_messages'] = false;
// ----------------------------------
// PLUGINS
// ----------------------------------
// List of active plugins (in plugins/ directory)
-$rcmail_config['plugins'] = array();
+$config['plugins'] = array();
// ----------------------------------
// USER INTERFACE
@@ -414,121 +458,125 @@ $rcmail_config['plugins'] = array();
// default messages sort column. Use empty value for default server's sorting,
// or 'arrival', 'date', 'subject', 'from', 'to', 'fromto', 'size', 'cc'
-$rcmail_config['message_sort_col'] = '';
+$config['message_sort_col'] = '';
// default messages sort order
-$rcmail_config['message_sort_order'] = 'DESC';
+$config['message_sort_order'] = 'DESC';
// These cols are shown in the message list. Available cols are:
// subject, from, to, fromto, cc, replyto, date, size, status, flag, attachment, 'priority'
-$rcmail_config['list_cols'] = array('subject', 'status', 'fromto', 'date', 'size', 'flag', 'attachment');
+$config['list_cols'] = array('subject', 'status', 'fromto', '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;
+$config['language'] = null;
// use this format for date display (date or strftime format)
-$rcmail_config['date_format'] = 'Y-m-d';
+$config['date_format'] = 'Y-m-d';
// 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');
+$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 time display (date or strftime format)
-$rcmail_config['time_format'] = 'H:i';
+$config['time_format'] = 'H:i';
// 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');
+$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';
+$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';
+$config['date_long'] = 'Y-m-d H:i';
// store draft message is this mailbox
// leave blank if draft messages should not be stored
// NOTE: Use folder names with namespace prefix (INBOX. on Courier-IMAP)
-$rcmail_config['drafts_mbox'] = 'Drafts';
+$config['drafts_mbox'] = 'Drafts';
// store spam messages in this mailbox
// NOTE: Use folder names with namespace prefix (INBOX. on Courier-IMAP)
-$rcmail_config['junk_mbox'] = 'Junk';
+$config['junk_mbox'] = 'Junk';
// store sent message is this mailbox
// leave blank if sent messages should not be stored
// NOTE: Use folder names with namespace prefix (INBOX. on Courier-IMAP)
-$rcmail_config['sent_mbox'] = 'Sent';
+$config['sent_mbox'] = 'Sent';
// move messages to this folder when deleting them
// leave blank if they should be deleted directly
// NOTE: Use folder names with namespace prefix (INBOX. on Courier-IMAP)
-$rcmail_config['trash_mbox'] = 'Trash';
+$config['trash_mbox'] = 'Trash';
// display these folders separately in the mailbox list.
// these folders will also be displayed with localized names
// NOTE: Use folder names with namespace prefix (INBOX. on Courier-IMAP)
-$rcmail_config['default_folders'] = array('INBOX', 'Drafts', 'Sent', 'Junk', 'Trash');
+$config['default_folders'] = array('INBOX', 'Drafts', 'Sent', 'Junk', 'Trash');
+
+// Disable localization of the default folder names listed above
+$config['show_real_foldernames'] = false;
// automatically create the above listed default folders on first login
-$rcmail_config['create_default_folders'] = false;
+$config['create_default_folders'] = false;
// protect the default folders from renames, deletes, and subscription changes
-$rcmail_config['protect_default_folders'] = true;
+$config['protect_default_folders'] = true;
// if in your system 0 quota means no limit set this option to true
-$rcmail_config['quota_zero_as_unlimited'] = false;
+$config['quota_zero_as_unlimited'] = false;
// Make use of the built-in spell checker. It is based on GoogieSpell.
// Since Google only accepts connections over https your PHP installatation
// requires to be compiled with Open SSL support
-$rcmail_config['enable_spellcheck'] = true;
+$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;
+$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' and 'enchant' are also available, but they require
+// PHP Pspell or Enchant extensions. When using Nox Spell Server, also set 'googie' here.
+$config['spellcheck_engine'] = 'googie';
// For a locally installed Nox Spell Server, please specify the URI to call it.
// Get Nox Spell Server from http://orangoo.com/labs/?page_id=72
// Leave empty to use the Google spell checking service, what means
// that the message content will be sent to Google in order to check spelling
-$rcmail_config['spellcheck_uri'] = '';
+$config['spellcheck_uri'] = '';
// These languages can be selected for spell checking.
// Configure as a PHP style hash array: array('en'=>'English', 'de'=>'Deutsch');
// Leave empty for default set of available language.
-$rcmail_config['spellcheck_languages'] = NULL;
+$config['spellcheck_languages'] = NULL;
// Makes that words with all letters capitalized will be ignored (e.g. GOOGLE)
-$rcmail_config['spellcheck_ignore_caps'] = false;
+$config['spellcheck_ignore_caps'] = false;
// Makes that words with numbers will be ignored (e.g. g00gle)
-$rcmail_config['spellcheck_ignore_nums'] = false;
+$config['spellcheck_ignore_nums'] = false;
// Makes that words with symbols will be ignored (e.g. g@@gle)
-$rcmail_config['spellcheck_ignore_syms'] = false;
+$config['spellcheck_ignore_syms'] = false;
// Use this char/string to separate recipients when composing a new message
-$rcmail_config['recipients_separator'] = ',';
+$config['recipients_separator'] = ',';
// don't let users set pagesize to more than this value if set
-$rcmail_config['max_pagesize'] = 200;
+$config['max_pagesize'] = 200;
// Minimal value of user's 'refresh_interval' setting (in seconds)
-$rcmail_config['min_refresh_interval'] = 60;
+$config['min_refresh_interval'] = 60;
// Enables files upload indicator. Requires APC installed and enabled apc.rfc1867 option.
// By default refresh time is set to 1 second. You can set this value to true
// or any integer value indicating number of seconds.
-$rcmail_config['upload_progress'] = false;
+$config['upload_progress'] = false;
// Specifies for how many seconds the Undo button will be available
// after object delete action. Currently used with supporting address book sources.
// Setting it to 0, disables the feature.
-$rcmail_config['undo_timeout'] = 0;
+$config['undo_timeout'] = 0;
// ----------------------------------
// ADDRESSBOOK SETTINGS
@@ -541,12 +589,12 @@ $rcmail_config['undo_timeout'] = 0;
// SQL address book in the 'Address Book' view.
// If set to '' then no address book will be displayed or only the
// addressbook which is created by a plugin (like CardDAV).
-$rcmail_config['address_book_type'] = 'sql';
+$config['address_book_type'] = 'sql';
// In order to enable public ldap search, configure an array like the Verisign
// example further below. if you would like to test, simply uncomment the example.
// Array key must contain only safe characters, ie. a-zA-Z0-9_
-$rcmail_config['ldap_public'] = array();
+$config['ldap_public'] = array();
// If you are going to use LDAP for individual address books, you will need to
// set 'user_specific' to true and use the variables to generate the appropriate DNs to access it.
@@ -564,7 +612,7 @@ $rcmail_config['ldap_public'] = array();
/*
* example config for Verisign directory
*
-$rcmail_config['ldap_public']['Verisign'] = array(
+$config['ldap_public']['Verisign'] = array(
'name' => 'Verisign.com',
// Replacement variables supported in host names:
// %h - user's IMAP hostname
@@ -575,7 +623,7 @@ $rcmail_config['ldap_public']['Verisign'] = array(
// For example %n = mail.domain.tld, %t = domain.tld
'hosts' => array('directory.verisign.com'),
'port' => 389,
- 'use_tls' => false,
+ 'use_tls' => false,
'ldap_version' => 3, // using LDAPv3
'network_timeout' => 10, // The timeout (in seconds) for connect + bind arrempts. This is only supported in PHP >= 5.3.0 with OpenLDAP 2.x
'user_specific' => false, // If true the base_dn, bind_dn and bind_pass default to the user's IMAP login.
@@ -636,6 +684,7 @@ $rcmail_config['ldap_public']['Verisign'] = array(
'phone:work' => 'telephoneNumber',
'phone:mobile' => 'mobile',
'phone:pager' => 'pager',
+ 'phone:workfax' => 'facsimileTelephoneNumber',
'street' => 'street',
'zipcode' => 'postalCode',
'region' => 'st',
@@ -646,9 +695,8 @@ $rcmail_config['ldap_public']['Verisign'] = array(
'department' => 'ou',
'jobtitle' => 'title',
'notes' => 'description',
+ 'photo' => 'jpegPhoto',
// these currently don't work:
- // 'phone:workfax' => 'facsimileTelephoneNumber',
- // 'photo' => 'jpegPhoto',
// 'manager' => 'manager',
// 'assistant' => 'secretary',
),
@@ -659,236 +707,263 @@ $rcmail_config['ldap_public']['Verisign'] = array(
// 'uid' => 'md5(microtime())', // You may specify PHP code snippets which are then eval'ed
// 'mail' => '{givenname}.{sn}@mydomain.com', // or composite strings with placeholders for existing attributes
),
- 'sort' => 'cn', // The field to sort the listing by.
- 'scope' => 'sub', // search mode: sub|base|list
- 'filter' => '(objectClass=inetOrgPerson)', // used for basic listing (if not empty) and will be &'d with search queries. example: status=act
- 'fuzzy_search' => true, // server allows wildcard search
- 'vlv' => false, // Enable Virtual List View to more efficiently fetch paginated data (if server supports it)
- '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
+ 'sort' => 'cn', // The field to sort the listing by.
+ 'scope' => 'sub', // search mode: sub|base|list
+ 'filter' => '(objectClass=inetOrgPerson)', // used for basic listing (if not empty) and will be &'d with search queries. example: status=act
+ 'fuzzy_search' => true, // server allows wildcard search
+ 'vlv' => false, // Enable Virtual List View to more efficiently fetch paginated data (if server supports it)
+ 'vlv_search' => false, // Use Virtual List View functions for autocompletion searches (if server supports it)
+ '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
+ 'config_root_dn' => 'cn=config', // Root DN to search config entries (e.g. vlv indexes)
+ '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' => 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)
// if the groups base_dn is empty, the contact base_dn is used for the groups as well
// -> in this case, assure that groups and contacts are separated due to the concernig filters!
- 'groups' => array(
- 'base_dn' => '',
- 'scope' => 'sub', // search mode: sub|base|list
- 'filter' => '(objectClass=groupOfNames)',
+ 'groups' => array(
+ 'base_dn' => '',
+ 'scope' => 'sub', // Search mode: sub|base|list
+ 'filter' => '(objectClass=groupOfNames)',
'object_classes' => array("top", "groupOfNames"),
- 'member_attr' => 'member', // name of the member attribute, e.g. uniqueMember
- 'name_attr' => 'cn', // attribute to be used as group name
+ 'member_attr' => 'member', // Name of the member attribute, e.g. uniqueMember
+ 'name_attr' => 'cn', // Attribute to be used as group name
+ 'member_filter' => '(objectclass=*)', // Optional filter to use when querying for group members
+ 'vlv' => false, // Use VLV controls to list groups
+ ),
+ // this configuration replaces the regular groups listing in the directory tree with
+ // a hard-coded list of groups, each listing entries with the configured base DN and filter.
+ // if the 'groups' option from above is set, it'll be shown as the first entry with the name 'Groups'
+ 'group_filters' => array(
+ 'departments' => array(
+ 'name' => 'Company Departments',
+ 'scope' => 'list',
+ 'base_dn' => 'ou=Groups,dc=mydomain,dc=com',
+ 'filter' => '(|(objectclass=groupofuniquenames)(objectclass=groupofurls))',
+ 'name_attr' => 'cn',
+ ),
+ 'customers' => array(
+ 'name' => 'Customers',
+ 'scope' => 'sub',
+ 'base_dn' => 'ou=Customers,dc=mydomain,dc=com',
+ 'filter' => '(objectClass=inetOrgPerson)',
+ 'name_attr' => 'sn',
+ ),
),
);
*/
// An ordered array of the ids of the addressbooks that should be searched
// when populating address autocomplete fields server-side. ex: array('sql','Verisign');
-$rcmail_config['autocomplete_addressbooks'] = array('sql');
+$config['autocomplete_addressbooks'] = array('sql');
// The minimum number of characters required to be typed in an autocomplete field
// before address books will be searched. Most useful for LDAP directories that
// may need to do lengthy results building given overly-broad searches
-$rcmail_config['autocomplete_min_length'] = 1;
+$config['autocomplete_min_length'] = 1;
// Number of parallel autocomplete requests.
// If there's more than one address book, n parallel (async) requests will be created,
// where each request will search in one address book. By default (0), all address
// books are searched in one request.
-$rcmail_config['autocomplete_threads'] = 0;
+$config['autocomplete_threads'] = 0;
// Max. numer of entries in autocomplete popup. Default: 15.
-$rcmail_config['autocomplete_max'] = 15;
+$config['autocomplete_max'] = 15;
// show address fields in this order
// available placeholders: {street}, {locality}, {zipcode}, {country}, {region}
-$rcmail_config['address_template'] = '{street}<br/>{locality} {zipcode}<br/>{country} {region}';
+$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;
+$config['addressbook_search_mode'] = 0;
// ----------------------------------
// USER PREFERENCES
// ----------------------------------
// Use this charset as fallback for message decoding
-$rcmail_config['default_charset'] = 'ISO-8859-1';
+$config['default_charset'] = 'ISO-8859-1';
// skin name: folder from skins/
-$rcmail_config['skin'] = 'larry';
+$config['skin'] = 'larry';
+
+// Enables using standard browser windows (that can be handled as tabs)
+// instead of popup windows
+$config['standard_windows'] = false;
// show up to X items in messages list view
-$rcmail_config['mail_pagesize'] = 50;
+$config['mail_pagesize'] = 50;
// show up to X items in contacts list view
-$rcmail_config['addressbook_pagesize'] = 50;
+$config['addressbook_pagesize'] = 50;
// sort contacts by this col (preferably either one of name, firstname, surname)
-$rcmail_config['addressbook_sort_col'] = 'surname';
+$config['addressbook_sort_col'] = 'surname';
// the way how contact names are displayed in the list
// 0: display name
// 1: (prefix) firstname middlename surname (suffix)
// 2: (prefix) surname firstname middlename (suffix)
// 3: (prefix) surname, firstname middlename (suffix)
-$rcmail_config['addressbook_name_listing'] = 0;
+$config['addressbook_name_listing'] = 0;
// use this timezone to display date/time
// valid timezone identifers are listed here: php.net/manual/en/timezones.php
// 'auto' will use the browser's timezone settings
-$rcmail_config['timezone'] = 'auto';
+$config['timezone'] = 'auto';
// prefer displaying HTML messages
-$rcmail_config['prefer_html'] = true;
+$config['prefer_html'] = true;
// display remote inline images
// 0 - Never, always ask
// 1 - Ask if sender is not in address book
// 2 - Always show inline images
-$rcmail_config['show_images'] = 0;
+$config['show_images'] = 0;
// open messages in new window
-$rcmail_config['message_extwin'] = false;
+$config['message_extwin'] = false;
// open message compose form in new window
-$rcmail_config['compose_extwin'] = false;
+$config['compose_extwin'] = false;
// compose html formatted messages by default
// 0 - never, 1 - always, 2 - on reply to HTML message, 3 - on forward or reply to HTML message
-$rcmail_config['htmleditor'] = 0;
+$config['htmleditor'] = 0;
// show pretty dates as standard
-$rcmail_config['prettydate'] = true;
+$config['prettydate'] = true;
// save compose message every 300 seconds (5min)
-$rcmail_config['draft_autosave'] = 300;
+$config['draft_autosave'] = 300;
// default setting if preview pane is enabled
-$rcmail_config['preview_pane'] = false;
+$config['preview_pane'] = false;
// Mark as read when viewed in preview pane (delay in seconds)
// Set to -1 if messages in preview pane should not be marked as read
-$rcmail_config['preview_pane_mark_read'] = 0;
+$config['preview_pane_mark_read'] = 0;
// Clear Trash on logout
-$rcmail_config['logout_purge'] = false;
+$config['logout_purge'] = false;
// Compact INBOX on logout
-$rcmail_config['logout_expunge'] = false;
+$config['logout_expunge'] = false;
// Display attached images below the message body
-$rcmail_config['inline_images'] = true;
+$config['inline_images'] = true;
// Encoding of long/non-ascii attachment names:
// 0 - Full RFC 2231 compatible
// 1 - RFC 2047 for 'name' and RFC 2231 for 'filename' parameter (Thunderbird's default)
// 2 - Full 2047 compatible
-$rcmail_config['mime_param_folding'] = 1;
+$config['mime_param_folding'] = 1;
// Set true if deleted messages should not be displayed
// This will make the application run slower
-$rcmail_config['skip_deleted'] = false;
+$config['skip_deleted'] = false;
// Set true to Mark deleted messages as read as well as deleted
// False means that a message's read status is not affected by marking it as deleted
-$rcmail_config['read_when_deleted'] = true;
+$config['read_when_deleted'] = true;
// Set to true to never delete messages immediately
// Use 'Purge' to remove messages marked as deleted
-$rcmail_config['flag_for_deletion'] = false;
+$config['flag_for_deletion'] = false;
// Default interval for auto-refresh requests (in seconds)
// These are requests for system state updates e.g. checking for new messages, etc.
// Setting it to 0 disables the feature.
-$rcmail_config['refresh_interval'] = 60;
+$config['refresh_interval'] = 60;
// If true all folders will be checked for recent messages
-$rcmail_config['check_all_folders'] = false;
+$config['check_all_folders'] = false;
// If true, after message delete/move, the next message will be displayed
-$rcmail_config['display_next'] = true;
+$config['display_next'] = true;
// 0 - Do not expand threads
// 1 - Expand all threads automatically
// 2 - Expand only threads with unread messages
-$rcmail_config['autoexpand_threads'] = 0;
+$config['autoexpand_threads'] = 0;
// When replying:
// -1 - don't cite the original message
// 0 - place cursor below the original message
// 1 - place cursor above original message (top posting)
-$rcmail_config['reply_mode'] = 0;
+$config['reply_mode'] = 0;
// When replying strip original signature from message
-$rcmail_config['strip_existing_sig'] = true;
+$config['strip_existing_sig'] = true;
// Show signature:
// 0 - Never
// 1 - Always
// 2 - New messages only
// 3 - Forwards and Replies only
-$rcmail_config['show_sig'] = 1;
+$config['show_sig'] = 1;
// Use MIME encoding (quoted-printable) for 8bit characters in message body
-$rcmail_config['force_7bit'] = false;
+$config['force_7bit'] = false;
// Defaults of the search field configuration.
// The array can contain a per-folder list of header fields which should be considered when searching
// The entry with key '*' stands for all folders which do not have a specific list set.
-// Please note that folder names should to be in sync with $rcmail_config['default_folders']
-$rcmail_config['search_mods'] = null; // Example: array('*' => array('subject'=>1, 'from'=>1), 'Sent' => array('subject'=>1, 'to'=>1));
+// Please note that folder names should to be in sync with $config['default_folders']
+$config['search_mods'] = null; // Example: array('*' => array('subject'=>1, 'from'=>1), 'Sent' => array('subject'=>1, 'to'=>1));
// Defaults of the addressbook search field configuration.
-$rcmail_config['addressbook_search_mods'] = null; // Example: array('name'=>1, 'firstname'=>1, 'surname'=>1, 'email'=>1, '*'=>1);
+$config['addressbook_search_mods'] = null; // Example: array('name'=>1, 'firstname'=>1, 'surname'=>1, 'email'=>1, '*'=>1);
// 'Delete always'
// This setting reflects if mail should be always deleted
// when moving to Trash fails. This is necessary in some setups
// when user is over quota and Trash is included in the quota.
-$rcmail_config['delete_always'] = false;
+$config['delete_always'] = false;
// Directly delete messages in Junk instead of moving to Trash
-$rcmail_config['delete_junk'] = false;
+$config['delete_junk'] = false;
// Behavior if a received message requests a message delivery notification (read receipt)
// 0 = ask the user, 1 = send automatically, 2 = ignore (never send or ask)
// 3 = send automatically if sender is in addressbook, otherwise ask the user
// 4 = send automatically if sender is in addressbook, otherwise ignore
-$rcmail_config['mdn_requests'] = 0;
+$config['mdn_requests'] = 0;
// Return receipt checkbox default state
-$rcmail_config['mdn_default'] = 0;
+$config['mdn_default'] = 0;
// Delivery Status Notification checkbox default state
-$rcmail_config['dsn_default'] = 0;
+$config['dsn_default'] = 0;
// Place replies in the folder of the message being replied to
-$rcmail_config['reply_same_folder'] = false;
+$config['reply_same_folder'] = false;
// Sets default mode of Forward feature to "forward as attachment"
-$rcmail_config['forward_attachment'] = false;
+$config['forward_attachment'] = false;
// Defines address book (internal index) to which new contacts will be added
// By default it is the first writeable addressbook.
// Note: Use '0' for built-in address book.
-$rcmail_config['default_addressbook'] = null;
+$config['default_addressbook'] = null;
// Enables spell checking before sending a message.
-$rcmail_config['spellcheck_before_send'] = false;
+$config['spellcheck_before_send'] = false;
// Skip alternative email addresses in autocompletion (show one address per contact)
-$rcmail_config['autocomplete_single'] = false;
+$config['autocomplete_single'] = false;
// Default font for composed HTML message.
// Supported values: Andale Mono, Arial, Arial Black, Book Antiqua, Courier New,
// Georgia, Helvetica, Impact, Tahoma, Terminal, Times New Roman, Trebuchet MS, Verdana
-$rcmail_config['default_font'] = 'Verdana';
+$config['default_font'] = 'Verdana';
// Enables display of email address with name instead of a name (and address in title)
-$rcmail_config['message_show_email'] = false;
+$config['message_show_email'] = false;
diff --git a/index.php b/index.php
index 5d5257142..2d220dede 100644
--- a/index.php
+++ b/index.php
@@ -39,7 +39,7 @@
require_once 'program/include/iniset.php';
// init application, start session, init output class, etc.
-$RCMAIL = rcmail::get_instance();
+$RCMAIL = rcmail::get_instance($GLOBALS['env']);
// Make the whole PHP output non-cacheable (#1487797)
$RCMAIL->output->nocacheing_headers();
diff --git a/installer/check.php b/installer/check.php
index fcf35025e..ee0c9f367 100644
--- a/installer/check.php
+++ b/installer/check.php
@@ -42,12 +42,13 @@ $ini_checks = array(
'suhosin.session.encrypt' => 0,
'magic_quotes_runtime' => 0,
'magic_quotes_sybase' => 0,
- 'date.timezone' => '-NOTEMPTY-',
);
$optional_checks = array(
// required for utils/modcss.inc, should we require this?
'allow_url_fopen' => 1,
+ 'date.timezone' => '-VALID-',
+ 'register_globals' => 0, // #1489157
);
$source_urls = array(
@@ -139,10 +140,11 @@ foreach ($RCI->supported_dbs as $database => $ext) {
if (extension_loaded($ext)) {
// MySQL driver requires PHP >= 5.3 (#1488875)
if ($ext == 'pdo_mysql' && version_compare(PHP_VERSION, '5.3.0', '<')) {
- $RCI->fail($database, 'PHP >= 5.3 required');
+ $RCI->fail($database, 'PHP >= 5.3 required', null, true);
}
else {
$RCI->pass($database);
+ $found_db_driver = true;
}
}
else {
@@ -152,6 +154,9 @@ foreach ($RCI->supported_dbs as $database => $ext) {
}
echo '<br />';
}
+if (empty($found_db_driver)) {
+ $RCI->failures++;
+}
?>
@@ -185,23 +190,15 @@ foreach ($ini_checks as $var => $val) {
if ($val === '-NOTEMPTY-') {
if (empty($status)) {
$RCI->fail($var, "empty value detected");
- } else if ($var == 'date.timezone') {
- try {
- $tz = new DateTimeZone($status);
- $RCI->pass($var);
- }
- catch (Exception $e) {
- $RCI->fail($var, "invalid value detected: $status");
- }
- } else {
+ }
+ else {
$RCI->pass($var);
}
- echo '<br />';
- continue;
}
- if ($status == $val) {
+ else if (filter_var($status, FILTER_VALIDATE_BOOLEAN) == $val) {
$RCI->pass($var);
- } else {
+ }
+ else {
$RCI->fail($var, "is '$status', should be '$val'");
}
echo '<br />';
@@ -223,9 +220,24 @@ foreach ($optional_checks as $var => $val) {
echo '<br />';
continue;
}
- if ($status == $val) {
+ if ($val === '-VALID-') {
+ if ($var == 'date.timezone') {
+ try {
+ $tz = new DateTimeZone($status);
+ $RCI->pass($var);
+ }
+ catch (Exception $e) {
+ $RCI->optfail($var, empty($status) ? "not set" : "invalid value detected: $status");
+ }
+ }
+ else {
+ $RCI->pass($var);
+ }
+ }
+ else if (filter_var($status, FILTER_VALIDATE_BOOLEAN) == $val) {
$RCI->pass($var);
- } else {
+ }
+ else {
$RCI->optfail($var, "is '$status', could be '$val'");
}
echo '<br />';
diff --git a/installer/config.php b/installer/config.php
index b9a051ba0..f990fc23f 100644
--- a/installer/config.php
+++ b/installer/config.php
@@ -9,13 +9,9 @@ if (!class_exists('rcube_install') || !is_object($RCI)) {
<input type="hidden" name="_step" value="2" />
<?php
-// also load the default config to fill in the fields
-$RCI->load_defaults();
-
// register these boolean fields
$RCI->bool_config_props = array(
'ip_check' => 1,
- 'enable_caching' => 1,
'enable_spellcheck' => 1,
'auto_create_user' => 1,
'smtp_log' => 1,
@@ -28,24 +24,24 @@ $RCI->bool_config_props = array(
$_SESSION['allowinstaller'] = true;
if (!empty($_POST['submit'])) {
-
- echo '<p class="notice">Copy or download the following configurations and save them in two files';
- echo ' (names above the text box) within the <tt>'.RCMAIL_CONFIG_DIR.'</tt> directory of your Roundcube installation.<br/>';
- echo ' Make sure that there are no characters outside the <tt>&lt;?php ?&gt;</tt> brackets when saving the files.</p>';
-
+ echo '<p class="notice">Copy or download the following configuration and save it';
+ echo ' as <tt><b>config.inc.php</b></tt> within the <tt>'.RCUBE_CONFIG_DIR.'</tt> directory of your Roundcube installation.<br/>';
+ echo ' Make sure that there are no characters outside the <tt>&lt;?php ?&gt;</tt> brackets when saving the file.';
+ echo '&nbsp;<input type="button" onclick="location.href=\'index.php?_getconfig=1\'" value="Download" />';
+ if ($RCI->legacy_config) {
+ echo '<br/><br/>Afterwards, please <b>remove</b> the old configuration files <tt>main.inc.php</tt> and <tt>db.inc.php</tt>';
+ echo ' from the config directory.';
+ }
+ echo '</p>';
+
$textbox = new html_textarea(array('rows' => 16, 'cols' => 60, 'class' => "configfile"));
-
- echo '<div><em>main.inc.php (<a href="index.php?_getfile=main">download</a>)</em></div>';
- echo $textbox->show(($_SESSION['main.inc.php'] = $RCI->create_config('main')));
-
- echo '<div style="margin-top:1em"><em>db.inc.php (<a href="index.php?_getfile=db">download</a>)</em></div>';
- echo $textbox->show($_SESSION['db.inc.php'] = $RCI->create_config('db'));
+ echo $textbox->show(($_SESSION['config'] = $RCI->create_config()));
echo '<p class="hint">Of course there are more options to configure.
- Have a look at the config files or visit <a href="http://trac.roundcube.net/wiki/Howto_Config">Howto_Config</a> to find out.</p>';
+ Have a look at the defaults.inc.php file or visit <a href="http://trac.roundcube.net/wiki/Howto_Config">Howto_Config</a> to find out.</p>';
echo '<p><input type="button" onclick="location.href=\'./index.php?_step=3\'" value="CONTINUE" /></p>';
-
+
// echo '<style type="text/css"> .configblock { display:none } </style>';
echo "\n<hr style='margin-bottom:1.6em' />\n";
}
@@ -127,16 +123,6 @@ echo $check_ipcheck->show(intval($RCI->getprop('ip_check')), array('value' => 1)
<p class="hint">This increases security but can cause sudden logouts when someone uses a proxy with changing IPs.</p>
</dd>
-<dt class="propname">enable_caching</dt>
-<dd>
-<?php
-
-$check_caching = new html_checkbox(array('name' => '_enable_caching', 'id' => "cfgcache"));
-echo $check_caching->show(intval($RCI->getprop('enable_caching')), array('value' => 1));
-
-?>
-<label for="cfgcache">Cache messages in local database</label><br />
-</dd>
<dt class="propname">enable_spellcheck</dt>
<dd>
@@ -659,7 +645,7 @@ $select_param_folding->add('Full RFC 2231 (Roundcube, Thunderbird)', '0');
$select_param_folding->add('RFC 2047/2231 (MS Outlook, OE)', '1');
$select_param_folding->add('Full RFC 2047 (deprecated)', '2');
-echo $select_param_folding->show(intval($RCI->getprop('mime_param_folding')));
+echo $select_param_folding->show(strval($RCI->getprop('mime_param_folding')));
?>
<div>How to encode attachment long/non-ascii names</div>
diff --git a/installer/index.php b/installer/index.php
index 0e80b1cd6..d084c8aa5 100644
--- a/installer/index.php
+++ b/installer/index.php
@@ -5,7 +5,7 @@
| Roundcube Webmail setup tool |
| Version 0.9-git |
| |
- | Copyright (C) 2009-2012, The Roundcube Dev Team |
+ | Copyright (C) 2009-2013, The Roundcube Dev Team |
| |
| This program is free software: you can redistribute it and/or modify |
| it under the terms of the GNU General Public License (with exceptions |
@@ -54,17 +54,18 @@ require_once 'rcube_install.php';
// deprecated aliases (to be removed)
require_once 'bc.php';
-session_start();
+if (function_exists('session_start'))
+ session_start();
$RCI = rcube_install::get_instance();
$RCI->load_config();
-if (isset($_GET['_getfile']) && in_array($_GET['_getfile'], array('main', 'db'))) {
- $filename = $_GET['_getfile'] . '.inc.php';
- if (!empty($_SESSION[$filename])) {
+if (isset($_GET['_getconfig'])) {
+ $filename = 'config.inc.php';
+ if (!empty($_SESSION['config'])) {
header('Content-type: text/plain');
header('Content-Disposition: attachment; filename="'.$filename.'"');
- echo $_SESSION[$filename];
+ echo $_SESSION['config'];
exit;
}
else {
@@ -74,14 +75,14 @@ if (isset($_GET['_getfile']) && in_array($_GET['_getfile'], array('main', 'db'))
}
if ($RCI->configured && ($RCI->getprop('enable_installer') || $_SESSION['allowinstaller']) &&
- isset($_GET['_mergeconfig']) && in_array($_GET['_mergeconfig'], array('main', 'db'))) {
- $filename = $_GET['_mergeconfig'] . '.inc.php';
+ !empty($_GET['_mergeconfig'])) {
+ $filename = 'config.inc.php';
header('Content-type: text/plain');
header('Content-Disposition: attachment; filename="'.$filename.'"');
$RCI->merge_config();
- echo $RCI->create_config($_GET['_mergeconfig'], true);
+ echo $RCI->create_config();
exit;
}
@@ -121,8 +122,16 @@ if ($RCI->configured && empty($_REQUEST['_step'])) {
// exit if installation is complete
if ($RCI->configured && !$RCI->getprop('enable_installer') && !$_SESSION['allowinstaller']) {
// header("HTTP/1.0 404 Not Found");
- echo '<h2 class="error">The installer is disabled!</h2>';
- echo '<p>To enable it again, set <tt>$rcmail_config[\'enable_installer\'] = true;</tt> in RCUBE_CONFIG_DIR/main.inc.php</p>';
+ if ($RCI->configured && $RCI->legacy_config) {
+ echo '<h2 class="error">Your configuration needs to be migrated!</h2>';
+ echo '<p>We changed the configuration files structure and your installation needs to be updated accordingly.</p>';
+ echo '<p>Please run the <tt>bin/update.sh</tt> script from the command line or set <p>&nbsp; <tt>$rcmail_config[\'enable_installer\'] = true;</tt></p>';
+ echo ' in your RCUBE_CONFIG_DIR/main.inc.php to let the installer help you migrating it.</p>';
+ }
+ else {
+ echo '<h2 class="error">The installer is disabled!</h2>';
+ echo '<p>To enable it again, set <tt>$rcmail_config[\'enable_installer\'] = true;</tt> in RCUBE_CONFIG_DIR/config.inc.php</p>';
+ }
echo '</div></body></html>';
exit;
}
diff --git a/installer/rcube_install.php b/installer/rcube_install.php
index 0b5956471..0f1bfe23e 100644
--- a/installer/rcube_install.php
+++ b/installer/rcube_install.php
@@ -28,10 +28,12 @@ class rcube_install
var $failures = 0;
var $config = array();
var $configured = false;
+ var $legacy_config = false;
var $last_error = null;
var $email_pattern = '([a-z0-9][a-z0-9\-\.\+\_]*@[a-z0-9]([a-z0-9\-][.]?)*[a-z0-9])';
var $bool_config_props = array();
+ var $local_config = array('db_dsnw', 'default_host', 'support_url', 'des_key', 'plugins');
var $obsolete_config = array('db_backend', 'double_auth');
var $replaced_config = array(
'skin_path' => 'skin',
@@ -44,11 +46,6 @@ class rcube_install
'top_posting' => 'reply_mode',
);
- // these config options are required for a working system
- var $required_config = array(
- 'db_dsnw', 'des_key', 'session_lifetime',
- );
-
// list of supported database drivers
var $supported_dbs = array(
'MySQL' => 'pdo_mysql',
@@ -83,43 +80,75 @@ class rcube_install
}
/**
- * Read the default config files and store properties
- */
- function load_defaults()
- {
- $this->_load_config('.php.dist');
- }
-
-
- /**
* Read the local config files and store properties
*/
function load_config()
{
- $this->config = array();
- $this->_load_config('.php');
- $this->configured = !empty($this->config);
+ // defaults
+ if ($config = $this->load_config_file(RCUBE_CONFIG_DIR . 'defaults.inc.php')) {
+ $this->config = (array) $config;
+ $this->defaults = $this->config;
+ }
+
+ $config = null;
+
+ // config
+ if ($config = $this->load_config_file(RCUBE_CONFIG_DIR . 'config.inc.php')) {
+ $this->config = array_merge($this->config, $config);
+ }
+ else {
+ if ($config = $this->load_config_file(RCUBE_CONFIG_DIR . 'main.inc.php')) {
+ $this->config = array_merge($this->config, $config);
+ $this->legacy_config = true;
+ }
+ if ($config = $this->load_config_file(RCUBE_CONFIG_DIR . 'db.inc.php')) {
+ $this->config = array_merge($this->config, $config);
+ $this->legacy_config = true;
+ }
+ }
+
+ $this->configured = !empty($config);
}
/**
* Read the default config file and store properties
- * @access private
*/
- function _load_config($suffix)
+ public function load_config_file($file)
{
- if (is_readable($main_inc = RCUBE_CONFIG_DIR . 'main.inc' . $suffix)) {
- include($main_inc);
- if (is_array($rcmail_config))
- $this->config += $rcmail_config;
- }
- if (is_readable($db_inc = RCUBE_CONFIG_DIR . 'db.inc'. $suffix)) {
- include($db_inc);
- if (is_array($rcmail_config))
- $this->config += $rcmail_config;
+ if (is_readable($file)) {
+ include $file;
+
+ // read comments from config file
+ if (function_exists('token_get_all')) {
+ $tokens = token_get_all(file_get_contents($file));
+ $in_config = false;
+ $buffer = '';
+ for ($i=0; $i < count($tokens); $i++) {
+ $token = $tokens[$i];
+ if ($token[0] == T_VARIABLE && $token[1] == '$config' || $token[1] == '$rcmail_config') {
+ $in_config = true;
+ if ($buffer && $tokens[$i+1] == '[' && $tokens[$i+2][0] == T_CONSTANT_ENCAPSED_STRING) {
+ $propname = trim($tokens[$i+2][1], "'\"");
+ $this->comments[$propname] = $buffer;
+ $buffer = '';
+ $i += 3;
+ }
+ }
+ else if ($in_config && $token[0] == T_COMMENT) {
+ $buffer .= strtr($token[1], array('\n' => "\n"));
+ }
+ }
+ }
+
+ // deprecated name of config variable
+ if (is_array($rcmail_config)) {
+ return $rcmail_config;
+ }
+
+ return $config;
}
}
-
/**
* Getter for a certain config property
*
@@ -139,24 +168,31 @@ class rcube_install
/**
- * Take the default config file and replace the parameters
- * with the submitted form data
+ * Create configuration file that contains parameters
+ * that differ from default values.
*
- * @param string Which config file (either 'main' or 'db')
* @return string The complete config file content
*/
- function create_config($which, $force = false)
+ function create_config()
{
- $out = @file_get_contents(RCUBE_CONFIG_DIR . $which . '.inc.php.dist');
-
- if (!$out)
- return '[Warning: could not read the config template file]';
+ $config = array();
foreach ($this->config as $prop => $default) {
-
$is_default = !isset($_POST["_$prop"]);
$value = !$is_default || $this->bool_config_props[$prop] ? $_POST["_$prop"] : $default;
+ // always disable installer
+ if ($prop == 'enable_installer')
+ $value = false;
+
+ // reset useragent to default (keeps version up-to-date)
+ if ($prop == 'useragent' && stripos($value, 'Roundcube Webmail/') !== false)
+ $value = $this->defaults[$prop];
+
+ // generate new encryption key, never use the default value
+ if ($prop == 'des_key' && $value == $this->defaults[$prop])
+ $value = $this->random_key(24);
+
// convert some form data
if ($prop == 'debug_level' && !$is_default) {
if (is_array($value)) {
@@ -166,7 +202,7 @@ class rcube_install
$value = $val;
}
}
- else if ($which == 'db' && $prop == 'db_dsnw' && !empty($_POST['_dbtype'])) {
+ else if ($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 ($_POST['_dbtype'])
@@ -211,20 +247,24 @@ class rcube_install
}
// skip this property
- if (!$force && !$this->configured && ($value == $default))
+ if ((!array_key_exists($prop, $this->defaults) || ($value == $this->defaults[$prop])) && !in_array($prop, $this->local_config)) {
continue;
+ }
// save change
$this->config[$prop] = $value;
+ $config[$prop] = $value;
+ }
- // replace the matching line in config file
- $out = preg_replace(
- '/(\$rcmail_config\[\''.preg_quote($prop).'\'\])\s+=\s+(.+);/Uie',
- "'\\1 = ' . rcube_install::_dump_var(\$value, \$prop) . ';'",
- $out);
+ $out = "<?php\n\n";
+ $out .= "/* Local configuration for Roundcube Webmail */\n\n";
+ foreach ($config as $prop => $value) {
+ // copy option descriptions from existing config or defaults.inc.php
+ $out .= $this->comments[$prop];
+ $out .= "\$config['$prop'] = " . rcube_install::_dump_var($value, $prop) . ";\n\n";
}
- return trim($out);
+ return $out;
}
@@ -236,16 +276,13 @@ class rcube_install
*/
function check_config()
{
- $this->config = array();
- $this->load_defaults();
- $defaults = $this->config;
-
$this->load_config();
- if (!$this->configured)
+
+ if (!$this->configured) {
return null;
+ }
$out = $seen = array();
- $required = array_flip($this->required_config);
// iterate over the current configuration
foreach ($this->config as $prop => $value) {
@@ -264,12 +301,6 @@ class rcube_install
$out['obsolete'][] = array('prop' => 'mime_magic', 'explain' => "Set value to null in order to use system default");
}
- // iterate over default config
- foreach ($defaults as $prop => $value) {
- if (!isset($seen[$prop]) && isset($required[$prop]) && !(is_bool($this->config[$prop]) || strlen($this->config[$prop])))
- $out['missing'][] = array('prop' => $prop);
- }
-
// check config dependencies and contradictions
if ($this->config['enable_spellcheck'] && $this->config['spellcheck_engine'] == 'pspell') {
if (!extension_loaded('pspell')) {
@@ -317,7 +348,6 @@ class rcube_install
{
$current = $this->config;
$this->config = array();
- $this->load_defaults();
foreach ($this->replaced_config as $prop => $replacement) {
if (isset($current[$prop])) {
@@ -345,7 +375,7 @@ class rcube_install
}
}
- $this->config = array_merge($this->config, $current);
+ $this->config = array_merge($this->config, $current);
foreach (array_keys((array)$current['ldap_public']) as $key) {
$this->config['ldap_public'][$key] = $current['ldap_public'][$key];
@@ -411,6 +441,51 @@ class rcube_install
return $schema;
}
+ /**
+ * Try to detect some file's mimetypes to test the correct behavior of fileinfo
+ */
+ function check_mime_detection()
+ {
+ $files = array(
+ 'installer/images/roundcube_logo.png' => 'image/png',
+ 'program/resources/blank.tif' => 'image/tiff',
+ 'skins/larry/templates/login.html' => 'text/html',
+ );
+
+ $errors = array();
+ foreach ($files as $path => $expected) {
+ $mimetype = rcube_mime::file_content_type(INSTALL_PATH . $path, basename($path));
+ if ($mimetype != $expected) {
+ $errors[] = array($path, $mimetype, $expected);
+ }
+ }
+
+ return $errors;
+ }
+
+ /**
+ * Check the correct configuration of the 'mime_types' mapping option
+ */
+ function check_mime_extensions()
+ {
+ $types = array(
+ 'application/zip' => 'zip',
+ 'application/x-tar' => 'tar',
+ 'application/java-archive' => 'jar',
+ 'image/bmp' => 'bmp',
+ 'image/svg+xml' => 'svg',
+ );
+
+ $errors = array();
+ foreach ($types as $mimetype => $expected) {
+ $ext = rcube_mime::get_mime_extensions($mimetype);
+ if ($ext[0] != $expected) {
+ $errors[] = array($mimetype, $ext, $expected);
+ }
+ }
+
+ return $errors;
+ }
/**
* Getter for the last error message
@@ -456,7 +531,8 @@ class rcube_install
'0.6-beta', '0.6',
'0.7-beta', '0.7', '0.7.1', '0.7.2', '0.7.3', '0.7.4',
'0.8-beta', '0.8-rc', '0.8.0', '0.8.1', '0.8.2', '0.8.3', '0.8.4', '0.8.5', '0.8.6',
- '0.9-beta', '0.9-rc', '0.9-rc2', '0.9.0', '0.9.1'
+ '0.9-beta', '0.9-rc', '0.9-rc2',
+ // Note: Do not add newer versions here
));
return $select;
}
@@ -495,10 +571,13 @@ class rcube_install
* @param string Test name
* @param string Error message
* @param string URL for details
+ * @param bool Do not count this failure
*/
- function fail($name, $message = '', $url = '')
+ function fail($name, $message = '', $url = '', $optional=false)
{
- $this->failures++;
+ if (!$optional) {
+ $this->failures++;
+ }
echo Q($name) . ':&nbsp; <span class="fail">NOT OK</span>';
$this->_showhint($message, $url);
@@ -562,7 +641,8 @@ class rcube_install
}
- static function _dump_var($var, $name=null) {
+ static function _dump_var($var, $name=null)
+ {
// special values
switch ($name) {
case 'syslog_facility':
@@ -575,8 +655,20 @@ class rcube_install
if ($val = $list[$var])
return $val;
break;
- }
+ case 'mail_header_delimiter':
+ $var = str_replace(array("\r", "\n"), array('\r', '\n'), $var);
+ return '"' . $var. '"';
+ break;
+/*
+ // RCMAIL_VERSION is undefined here
+ case 'useragent':
+ if (preg_match('|^(.*)/('.preg_quote(RCMAIL_VERSION, '|').')$|i', $var, $m)) {
+ return '"' . addcslashes($var, '"') . '/" . RCMAIL_VERSION';
+ }
+ break;
+*/
+ }
if (is_array($var)) {
if (empty($var)) {
diff --git a/installer/test.php b/installer/test.php
index fb3e7e937..f834308ad 100644
--- a/installer/test.php
+++ b/installer/test.php
@@ -7,52 +7,44 @@ if (!class_exists('rcube_install') || !is_object($RCI)) {
?>
<form action="index.php?_step=3" method="post">
-<h3>Check config files</h3>
+<h3>Check config file</h3>
<?php
-$read_main = is_readable(RCUBE_CONFIG_DIR . 'main.inc.php');
-$read_db = is_readable(RCUBE_CONFIG_DIR . 'db.inc.php');
-
-if ($read_main && !empty($RCI->config)) {
- $RCI->pass('main.inc.php');
-}
-else if ($read_main) {
- $RCI->fail('main.inc.php', 'Syntax error');
+if ($read_config = is_readable(RCUBE_CONFIG_DIR . 'defaults.inc.php')) {
+ $config = $RCI->load_config_file(RCUBE_CONFIG_DIR . 'defaults.inc.php');
+ if (!empty($config)) {
+ $RCI->pass('defaults.inc.php');
+ }
+ else {
+ $RCI->fail('defaults.inc.php', 'Syntax error');
+ }
}
-else if (!$read_main) {
- $RCI->fail('main.inc.php', 'Unable to read file. Did you create the config files?');
+else {
+ $RCI->fail('defaults.inc.php', 'Unable to read default config file?');
}
echo '<br />';
-if ($read_db && !empty($RCI->config['db_dsnw'])) {
- $RCI->pass('db.inc.php');
-}
-else if ($read_db) {
- $RCI->fail('db.inc.php', 'Syntax error');
+if ($read_config = is_readable(RCUBE_CONFIG_DIR . 'config.inc.php')) {
+ $config = $RCI->load_config_file(RCUBE_CONFIG_DIR . 'config.inc.php');
+ if (!empty($config)) {
+ $RCI->pass('config.inc.php');
+ }
+ else {
+ $RCI->fail('config.inc.php', 'Syntax error');
+ }
}
-else if (!$read_db) {
- $RCI->fail('db.inc.php', 'Unable to read file. Did you create the config files?');
+else {
+ $RCI->fail('config.inc.php', 'Unable to read file. Did you create the config file?');
}
+echo '<br />';
-if ($RCI->configured && ($messages = $RCI->check_config())) {
-
- if (is_array($messages['missing'])) {
- echo '<h3 class="warning">Missing config options</h3>';
- echo '<p class="hint">The following config options are not set (not present or empty) in the current configuration.<br/>';
- echo 'Please check the default config files and set the missing properties in your local config files.</p>';
-
- echo '<ul class="configwarnings">';
- foreach ($messages['missing'] as $msg) {
- echo html::tag('li', null, html::span('propname', $msg['prop']) . ($msg['name'] ? ':&nbsp;' . $msg['name'] : ''));
- }
- echo '</ul>';
- }
+if ($RCI->configured && ($messages = $RCI->check_config())) {
if (is_array($messages['replaced'])) {
echo '<h3 class="warning">Replaced config options</h3>';
echo '<p class="hint">The following config options have been replaced or renamed. ';
echo 'Please update them accordingly in your config files.</p>';
-
+
echo '<ul class="configwarings">';
foreach ($messages['replaced'] as $msg) {
echo html::tag('li', null, html::span('propname', $msg['prop']) .
@@ -64,32 +56,28 @@ if ($RCI->configured && ($messages = $RCI->check_config())) {
if (is_array($messages['obsolete'])) {
echo '<h3>Obsolete config options</h3>';
echo '<p class="hint">You still have some obsolete or inexistent properties set. This isn\'t a problem but should be noticed.</p>';
-
+
echo '<ul class="configwarings">';
foreach ($messages['obsolete'] as $msg) {
echo html::tag('li', null, html::span('propname', $msg['prop']) . ($msg['name'] ? ':&nbsp;' . $msg['name'] : ''));
}
echo '</ul>';
}
-
- echo '<p class="suggestion">OK, lazy people can download the updated config files here: ';
- echo html::a(array('href' => './?_mergeconfig=main'), 'main.inc.php') . ' &nbsp;';
- echo html::a(array('href' => './?_mergeconfig=db'), 'db.inc.php');
+
+ echo '<p class="suggestion">OK, lazy people can download the updated config file here: ';
+ echo html::a(array('href' => './?_mergeconfig=1'), 'config.inc.php') . ' &nbsp;';
echo "</p>";
-
-
+
if (is_array($messages['dependencies'])) {
echo '<h3 class="warning">Dependency check failed</h3>';
echo '<p class="hint">Some of your configuration settings require other options to be configured or additional PHP modules to be installed</p>';
-
+
echo '<ul class="configwarings">';
foreach ($messages['dependencies'] as $msg) {
echo html::tag('li', null, html::span('propname', $msg['prop']) . ': ' . $msg['explain']);
}
echo '</ul>';
}
-
-
}
?>
@@ -98,30 +86,24 @@ if ($RCI->configured && ($messages = $RCI->check_config())) {
<p>Roundcube may need to write/save files into these directories</p>
<?php
-if ($RCI->configured) {
- $pass = false;
-
- $dirs[] = $RCI->config['temp_dir'] ? $RCI->config['temp_dir'] : 'temp';
- if($RCI->config['log_driver'] != 'syslog')
- $dirs[] = $RCI->config['log_dir'] ? $RCI->config['log_dir'] : 'logs';
+$dirs[] = $RCI->config['temp_dir'] ? $RCI->config['temp_dir'] : 'temp';
+if ($RCI->config['log_driver'] != 'syslog')
+ $dirs[] = $RCI->config['log_dir'] ? $RCI->config['log_dir'] : 'logs';
- foreach ($dirs as $dir) {
- $dirpath = $dir[0] == '/' ? $dir : INSTALL_PATH . $dir;
- if (is_writable(realpath($dirpath))) {
- $RCI->pass($dir);
- $pass = true;
- }
- else {
- $RCI->fail($dir, 'not writeable for the webserver');
- }
- echo '<br />';
+foreach ($dirs as $dir) {
+ $dirpath = $dir[0] == '/' ? $dir : INSTALL_PATH . $dir;
+ if (is_writable(realpath($dirpath))) {
+ $RCI->pass($dir);
+ $pass = true;
}
-
- if (!$pass)
- echo '<p class="hint">Use <tt>chmod</tt> or <tt>chown</tt> to grant write privileges to the webserver</p>';
+ else {
+ $RCI->fail($dir, 'not writeable for the webserver');
+ }
+ echo '<br />';
}
-else {
- $RCI->fail('Config', 'Could not read config files');
+
+if (!$pass) {
+ echo '<p class="hint">Use <tt>chmod</tt> or <tt>chown</tt> to grant write privileges to the webserver</p>';
}
?>
@@ -151,7 +133,7 @@ if ($RCI->configured) {
}
}
else {
- $RCI->fail('Config', 'Could not read config files');
+ $RCI->fail('DSN (write)', 'Could not read config file');
}
// initialize db with schema found in /SQL/*
@@ -225,6 +207,42 @@ if ($db_working) {
?>
+<h3>Test filetype detection</h3>
+
+<p>
+<?php
+
+if ($errors = $RCI->check_mime_detection()) {
+ $RCI->fail('Fileinfo/mime_content_type configuration');
+ if (!empty($RCI->config['mime_magic'])) {
+ echo '<p class="hint">Try setting the <tt>mime_magic</tt> config option to <tt>null</tt>.</p>';
+ }
+ else {
+ echo '<p class="hint">Check the <a href="http://www.php.net/manual/en/function.finfo-open.php">Fileinfo functions</a> of your PHP installation.<br/>';
+ echo 'The path to the magic.mime file can be set using the <tt>mime_magic</tt> config option in Roundcube.</p>';
+ }
+}
+else {
+ $RCI->pass('Fileinfo/mime_content_type configuration');
+}
+
+?>
+</p>
+<p>
+<?php
+
+if ($errors = $RCI->check_mime_extensions()) {
+ $RCI->fail('Mimetype to file extension mapping');
+ echo '<p class="hint">Please set a valid path to your webserver\'s mime.types file to the <tt>mime_types</tt> config option.<br/>';
+ echo 'If you can\'t find such a file, download it from <a href="http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types">svn.apache.org</a>.</p>';
+}
+else {
+ $RCI->pass('Mimetype to file extension mapping');
+}
+
+?>
+
+
<h3>Test SMTP config</h3>
<p>
@@ -427,7 +445,7 @@ if (isset($_POST['imaptest']) && !empty($_POST['_host']) && !empty($_POST['_user
After completing the installation and the final tests please <b>remove</b> the whole
installer folder from the document root of the webserver or make sure that
-<tt>enable_installer</tt> option in config/main.inc.php is disabled.<br />
+<tt>enable_installer</tt> option in <tt>config.inc.php</tt> is disabled.<br />
<br />
These files may expose sensitive configuration data like server passwords and encryption keys
diff --git a/plugins/acl/acl.php b/plugins/acl/acl.php
index 28139e92c..a840bcd58 100644
--- a/plugins/acl/acl.php
+++ b/plugins/acl/acl.php
@@ -9,18 +9,18 @@
*
* Copyright (C) 2011-2012, 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 free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
* 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.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
*/
class acl extends rcube_plugin
@@ -148,6 +148,7 @@ class acl extends rcube_plugin
// Load localization and include scripts
$this->load_config();
+ $this->specials = $this->rc->config->get('acl_specials', $this->specials);
$this->add_texts('localization/', array('deleteconfirm', 'norights',
'nouser', 'deleting', 'saving'));
$this->include_script('acl.js');
diff --git a/plugins/acl/config.inc.php.dist b/plugins/acl/config.inc.php.dist
index f957a233a..d0e1a0932 100644
--- a/plugins/acl/config.inc.php.dist
+++ b/plugins/acl/config.inc.php.dist
@@ -16,4 +16,10 @@ $rcmail_config['acl_users_field'] = 'mail';
// The LDAP search filter will be &'d with search queries
$rcmail_config['acl_users_filter'] = '';
+// Include the following 'special' access control subjects in the ACL dialog;
+// Defaults to array('anyone', 'anonymous') (not when set to an empty array)
+// Example: array('anyone') to exclude 'anonymous'.
+// Set to an empty array to exclude all special aci subjects.
+$rcmail_config['acl_specials'] = array('anyone', 'anonymous');
+
?>
diff --git a/plugins/acl/localization/en_US.inc b/plugins/acl/localization/en_US.inc
index 033ac29b2..3c61266be 100644
--- a/plugins/acl/localization/en_US.inc
+++ b/plugins/acl/localization/en_US.inc
@@ -89,7 +89,7 @@ $messages['saving'] = 'Saving access rights...';
$messages['updatesuccess'] = 'Successfully changed access rights';
$messages['deletesuccess'] = 'Successfully deleted access rights';
$messages['createsuccess'] = 'Successfully added access rights';
-$messages['updateerror'] = 'Ubable to update access rights';
+$messages['updateerror'] = 'Unable to update access rights';
$messages['deleteerror'] = 'Unable to delete access rights';
$messages['createerror'] = 'Unable to add access rights';
$messages['deleteconfirm'] = 'Are you sure, you want to remove access rights of selected user(s)?';
diff --git a/plugins/acl/localization/et_EE.inc b/plugins/acl/localization/et_EE.inc
index f89e7d6b7..ceec4cd0c 100644
--- a/plugins/acl/localization/et_EE.inc
+++ b/plugins/acl/localization/et_EE.inc
@@ -73,8 +73,8 @@ $labels['longacli'] = 'Messages can be written or copied to the folder';
$labels['longaclp'] = 'Messages can be posted to this folder';
$labels['longaclc'] = 'Folders can be created (or renamed) directly under this folder';
$labels['longaclk'] = 'Folders can be created (or renamed) directly under this folder';
-$labels['longacld'] = 'Messages Delete flag can be changed';
-$labels['longaclt'] = 'Messages Delete flag can be changed';
+$labels['longacld'] = 'Kirja kustutamis lippu saab muuta';
+$labels['longaclt'] = 'Kirja kustutamis lippu saab muuta';
$labels['longacle'] = 'Kirju saab eemaldada';
$labels['longaclx'] = 'Seda kausta ei saa kustutada ega ümber nimetada';
$labels['longacla'] = 'Selle kausta ligipääsuõigusi saab muuta';
diff --git a/plugins/acl/localization/gl_ES.inc b/plugins/acl/localization/gl_ES.inc
index bb8837190..2349975de 100644
--- a/plugins/acl/localization/gl_ES.inc
+++ b/plugins/acl/localization/gl_ES.inc
@@ -28,15 +28,15 @@ $labels['identifier'] = 'Identificador';
$labels['acll'] = 'Bloquear';
$labels['aclr'] = 'Ler mensaxes';
-$labels['acls'] = 'Keep Seen state';
-$labels['aclw'] = 'Write flags';
-$labels['acli'] = 'Insert (Copy into)';
-$labels['aclp'] = 'Post';
+$labels['acls'] = 'Manter o estado coma visto';
+$labels['aclw'] = 'Marcas de lectura';
+$labels['acli'] = 'Engadir (Copiar en)';
+$labels['aclp'] = 'Envío';
$labels['aclc'] = 'Crear subcartafoles';
$labels['aclk'] = 'Crear subcartafoles';
$labels['acld'] = 'Borrar mensaxes';
$labels['aclt'] = 'Borrar mensaxes';
-$labels['acle'] = 'Expunge';
+$labels['acle'] = 'Expurga';
$labels['aclx'] = 'Eliminar carpeta';
$labels['acla'] = 'Administrar';
@@ -51,12 +51,12 @@ $labels['shortaclr'] = 'Ler';
$labels['shortacls'] = 'Manter';
$labels['shortaclw'] = 'Escribir';
$labels['shortacli'] = 'Insertar';
-$labels['shortaclp'] = 'Post';
+$labels['shortaclp'] = 'Envío';
$labels['shortaclc'] = 'Crear';
$labels['shortaclk'] = 'Crear';
$labels['shortacld'] = 'Borrar';
$labels['shortaclt'] = 'Borrar';
-$labels['shortacle'] = 'Expunge';
+$labels['shortacle'] = 'Expurga';
$labels['shortaclx'] = 'Borrar cartafol';
$labels['shortacla'] = 'Administrar';
@@ -66,33 +66,33 @@ $labels['shortaclwrite'] = 'Escritura';
$labels['shortacldelete'] = 'Borrado';
$labels['longacll'] = 'O cartafol é visible e pode ser suscrito';
-$labels['longaclr'] = 'The folder can be opened for reading';
-$labels['longacls'] = 'Messages Seen flag can be changed';
-$labels['longaclw'] = 'Messages flags and keywords can be changed, except Seen and Deleted';
-$labels['longacli'] = 'Messages can be written or copied to the folder';
-$labels['longaclp'] = 'Messages can be posted to this folder';
-$labels['longaclc'] = 'Folders can be created (or renamed) directly under this folder';
-$labels['longaclk'] = 'Folders can be created (or renamed) directly under this folder';
-$labels['longacld'] = 'Messages Delete flag can be changed';
-$labels['longaclt'] = 'Messages Delete flag can be changed';
-$labels['longacle'] = 'Messages can be expunged';
-$labels['longaclx'] = 'The folder can be deleted or renamed';
-$labels['longacla'] = 'The folder access rights can be changed';
+$labels['longaclr'] = 'Pódese abrir o cartafol para lectura';
+$labels['longacls'] = 'Pódese mudar o marcador de Mensaxes Enviadas';
+$labels['longaclw'] = 'Pódense mudar marcadores e palabras chave agás Olladas e Borradas';
+$labels['longacli'] = 'Pódense escreber ou copiar as mensaxes a este cartafol';
+$labels['longaclp'] = 'Pódense enviar as mensaxes a este cartafol';
+$labels['longaclc'] = 'Pódense crear (ou renomear) os cartafois directamente baixo deste cartafol';
+$labels['longaclk'] = 'Pódense crear (ou renomear) os cartafois directamente baixo deste cartafol';
+$labels['longacld'] = 'Pódense mudar as mensaxes coa marca de Borrado';
+$labels['longaclt'] = 'Pódense mudar as mensaxes coa marca de Borrado';
+$labels['longacle'] = 'Pódense eliminar as mensaxes';
+$labels['longaclx'] = 'Pódese borrar ou renomear o cartafol';
+$labels['longacla'] = 'Pódense mudar os dereitos de acceso ao cartafol';
-$labels['longaclfull'] = 'Full control including folder administration';
-$labels['longaclread'] = 'The folder can be opened for reading';
-$labels['longaclwrite'] = 'Messages can be marked, written or copied to the folder';
-$labels['longacldelete'] = 'Messages can be deleted';
+$labels['longaclfull'] = 'Control total inclúe administración de cartafois';
+$labels['longaclread'] = 'Pódese abrir o cartafol para lectura';
+$labels['longaclwrite'] = 'Pódense marcar, escribir ou copiar as mensaxes no cartafol';
+$labels['longacldelete'] = 'Pódense borrar as mensaxes';
-$messages['deleting'] = 'Deleting access rights...';
-$messages['saving'] = 'Saving access rights...';
-$messages['updatesuccess'] = 'Successfully changed access rights';
-$messages['deletesuccess'] = 'Successfully deleted access rights';
-$messages['createsuccess'] = 'Successfully added access rights';
-$messages['updateerror'] = 'Ubable to update access rights';
-$messages['deleteerror'] = 'Unable to delete access rights';
-$messages['createerror'] = 'Unable to add access rights';
-$messages['deleteconfirm'] = 'Are you sure, you want to remove access rights of selected user(s)?';
+$messages['deleting'] = 'Borrando dereitos de acceso...';
+$messages['saving'] = 'Gardando dereitos de acceso...';
+$messages['updatesuccess'] = 'Mudados con éxito os dereitos de acceso';
+$messages['deletesuccess'] = 'Borrados con éxito os dereitos de acceso';
+$messages['createsuccess'] = 'Engadidos con éxito os dereitos de acceso';
+$messages['updateerror'] = 'Non se poden actualizar os dereitos de acceso';
+$messages['deleteerror'] = 'Non se poden borrar os dereitos de acceso';
+$messages['createerror'] = 'Non se poden engadir dereitos de acceso';
+$messages['deleteconfirm'] = 'De certo quere eliminar os dereitos de acceso do usuario(s) escollido?';
$messages['norights'] = 'Non se especificaron permisos!';
$messages['nouser'] = 'Non se especificou o nome de usuario!';
diff --git a/plugins/acl/localization/he_IL.inc b/plugins/acl/localization/he_IL.inc
index d7b027a40..9ca305d32 100644
--- a/plugins/acl/localization/he_IL.inc
+++ b/plugins/acl/localization/he_IL.inc
@@ -89,7 +89,7 @@ $messages['saving'] = 'זכויות גישה נשמרות...';
$messages['updatesuccess'] = 'זכויות גישה שונו בהצלחה';
$messages['deletesuccess'] = 'זכויות גישה נמחקו בהצלחה';
$messages['createsuccess'] = 'זכויות גישה נוספו בהצלחה';
-$messages['updateerror'] = '×œ× × ×™×ª×Ÿ לעדכן זכויות גישה';
+$messages['updateerror'] = '×œ× × ×™×ª×Ÿ לעדכן הרש×ות גישה';
$messages['deleteerror'] = '×œ× × ×™×ª×Ÿ למחוק זכויות גישה';
$messages['createerror'] = '×œ× × ×™×ª×Ÿ להוסיף זכויות גישה';
$messages['deleteconfirm'] = '×”×× ×•×“××™ שברצונך להסיר זכויות גישה של המשתמש(×™×) שנבחרו?';
diff --git a/plugins/acl/localization/lb_LU.inc b/plugins/acl/localization/lb_LU.inc
new file mode 100644
index 000000000..b9891931c
--- /dev/null
+++ b/plugins/acl/localization/lb_LU.inc
@@ -0,0 +1,99 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | plugins/acl/localization/<lang>.inc |
+ | |
+ | Localization file of the Roundcube Webmail ACL plugin |
+ | Copyright (C) 2012-2013, The Roundcube Dev Team |
+ | |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
+ | |
+ +-----------------------------------------------------------------------+
+
+ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/
+*/
+
+$labels['sharing'] = 'Sharing';
+$labels['myrights'] = 'Zougrëffsrechter';
+$labels['username'] = 'Benotzer:';
+$labels['advanced'] = 'avancéierte Modus';
+$labels['newuser'] = 'Element dobäisetzen';
+$labels['actions'] = 'Optioune fir d\'Zougrëffsrechter';
+$labels['anyone'] = 'All d\'Benotzer (jiddwereen)';
+$labels['anonymous'] = 'Gaascht (anonym)';
+$labels['identifier'] = 'Identifiant';
+
+$labels['acll'] = 'Noschloen';
+$labels['aclr'] = 'Messagë liesen';
+$labels['acls'] = 'Lies-Status behalen';
+$labels['aclw'] = 'Write flags';
+$labels['acli'] = 'Insert (Copy into)';
+$labels['aclp'] = 'Post';
+$labels['aclc'] = 'Create subfolders';
+$labels['aclk'] = 'Create subfolders';
+$labels['acld'] = 'Messagë läschen';
+$labels['aclt'] = 'Messagë läschen';
+$labels['acle'] = 'Ausläschen';
+$labels['aclx'] = 'Dossier läschen';
+$labels['acla'] = 'Administréieren';
+
+$labels['aclfull'] = 'Voll Kontroll';
+$labels['aclother'] = 'Aner';
+$labels['aclread'] = 'Liesen';
+$labels['aclwrite'] = 'Schreiwen';
+$labels['acldelete'] = 'Läschen';
+
+$labels['shortacll'] = 'Noschloen';
+$labels['shortaclr'] = 'Liesen';
+$labels['shortacls'] = 'Halen';
+$labels['shortaclw'] = 'Schreiwen';
+$labels['shortacli'] = 'Drasetze';
+$labels['shortaclp'] = 'Schécken';
+$labels['shortaclc'] = 'Erstellen';
+$labels['shortaclk'] = 'Erstellen';
+$labels['shortacld'] = 'Läschen';
+$labels['shortaclt'] = 'Läschen';
+$labels['shortacle'] = 'Ausläschen';
+$labels['shortaclx'] = 'Dossier läschen';
+$labels['shortacla'] = 'Administréieren';
+
+$labels['shortaclother'] = 'Aner';
+$labels['shortaclread'] = 'Liesen';
+$labels['shortaclwrite'] = 'Schreiwen';
+$labels['shortacldelete'] = 'Läschen';
+
+$labels['longacll'] = 'The folder is visible on lists and can be subscribed to';
+$labels['longaclr'] = 'The folder can be opened for reading';
+$labels['longacls'] = 'Messages Seen flag can be changed';
+$labels['longaclw'] = 'Messages flags and keywords can be changed, except Seen and Deleted';
+$labels['longacli'] = 'Messages can be written or copied to the folder';
+$labels['longaclp'] = 'Messages can be posted to this folder';
+$labels['longaclc'] = 'Folders can be created (or renamed) directly under this folder';
+$labels['longaclk'] = 'Folders can be created (or renamed) directly under this folder';
+$labels['longacld'] = 'Messages Delete flag can be changed';
+$labels['longaclt'] = 'Messages Delete flag can be changed';
+$labels['longacle'] = 'Messages can be expunged';
+$labels['longaclx'] = 'The folder can be deleted or renamed';
+$labels['longacla'] = 'The folder access rights can be changed';
+
+$labels['longaclfull'] = 'Full control including folder administration';
+$labels['longaclread'] = 'The folder can be opened for reading';
+$labels['longaclwrite'] = 'Messages can be marked, written or copied to the folder';
+$labels['longacldelete'] = 'Messagë kënne geläscht ginn';
+
+$messages['deleting'] = 'Zougrëffsrechter gi geläscht...';
+$messages['saving'] = 'Zougrëffsrechter gi gespäichert...';
+$messages['updatesuccess'] = 'Rechter erfollegräich geännert';
+$messages['deletesuccess'] = 'Rechter erfollegräich geläscht';
+$messages['createsuccess'] = 'Rechter erfollegräich dobäigesat';
+$messages['updateerror'] = 'D\'Zougrëffsrechter kënnen net aktualiséiert ginn';
+$messages['deleteerror'] = 'Rechter kënnen net geläscht ginn';
+$messages['createerror'] = 'Zougrëffsrechter kënnen net dobäigesat ginn';
+$messages['deleteconfirm'] = 'Bass du dir sécher, dass du d\'Zougrëffsrechter fir déi ausgewielte Benotzer wëlls ewechhuelen?';
+$messages['norights'] = 'Et goufe keng Rechter uginn! ';
+$messages['nouser'] = 'Et gouf kee Benotzernumm uginn!';
+
+?>
diff --git a/plugins/acl/localization/pl_PL.inc b/plugins/acl/localization/pl_PL.inc
index 73c0fc4fb..69a5e0c05 100644
--- a/plugins/acl/localization/pl_PL.inc
+++ b/plugins/acl/localization/pl_PL.inc
@@ -89,7 +89,7 @@ $messages['saving'] = 'Zapisywanie praw dostępu...';
$messages['updatesuccess'] = 'Pomyślnie zmieniono prawa dostępu';
$messages['deletesuccess'] = 'Pomyślnie usunięto prawa dostępu';
$messages['createsuccess'] = 'Pomyślnie dodano prawa dostępu';
-$messages['updateerror'] = 'Nie udało się zmienić praw dostępu';
+$messages['updateerror'] = 'Nie udało się zaktualizować praw dostępu';
$messages['deleteerror'] = 'Nie udało się usunąć praw dostępu';
$messages['createerror'] = 'Nie udało się dodać praw dostępu';
$messages['deleteconfirm'] = 'Czy na pewno chcesz usunąć prawa wybranym użytkownikom?';
diff --git a/plugins/acl/localization/tr_TR.inc b/plugins/acl/localization/tr_TR.inc
index 1569b5926..f3d60324b 100644
--- a/plugins/acl/localization/tr_TR.inc
+++ b/plugins/acl/localization/tr_TR.inc
@@ -89,7 +89,7 @@ $messages['saving'] = 'Erişim hakları saklanıyor...';
$messages['updatesuccess'] = 'Erişim hakları başarıyla değiştirildi';
$messages['deletesuccess'] = 'Erişim hakları başarıyla silindi';
$messages['createsuccess'] = 'Erişim hakları başarıyla eklendi';
-$messages['updateerror'] = 'Erişim haklarını güncellenemedi';
+$messages['updateerror'] = 'Erişim hakları güncellenemedi';
$messages['deleteerror'] = 'Erişim haklarını silinemedi';
$messages['createerror'] = 'Erişim hakları eklenemedi';
$messages['deleteconfirm'] = 'Seçilen kullanıcılar için erişim haklarını silmek istediğinizden emin misiniz?';
diff --git a/plugins/acl/package.xml b/plugins/acl/package.xml
index 52e234f37..98460e82f 100644
--- a/plugins/acl/package.xml
+++ b/plugins/acl/package.xml
@@ -22,7 +22,7 @@
<release>stable</release>
<api>stable</api>
</stability>
- <license uri="http://www.gnu.org/licenses/gpl-2.0.html">GNU GPLv2</license>
+ <license uri="http://www.gnu.org/licenses/gpl.html">GNU GPLv3+</license>
<notes>-</notes>
<contents>
<dir baseinstalldir="/" name="/">
diff --git a/plugins/additional_message_headers/additional_message_headers.php b/plugins/additional_message_headers/additional_message_headers.php
index 80c58d58b..a43018176 100644
--- a/plugins/additional_message_headers/additional_message_headers.php
+++ b/plugins/additional_message_headers/additional_message_headers.php
@@ -6,7 +6,7 @@
* Very simple plugin which will add additional headers
* to or remove them from outgoing messages.
*
- * Enable the plugin in config/main.inc.php and add your desired headers:
+ * Enable the plugin in config.inc.php and add your desired headers:
* $rcmail_config['additional_message_headers'] = array('User-Agent');
*
* @version @package_version@
@@ -24,7 +24,7 @@ class additional_message_headers extends rcube_plugin
function message_headers($args)
{
- $this->load_config();
+ $this->load_config();
// additional email headers
$additional_headers = rcmail::get_instance()->config->get('additional_message_headers',array());
@@ -39,5 +39,3 @@ class additional_message_headers extends rcube_plugin
return $args;
}
}
-
-?>
diff --git a/plugins/archive/archive.js b/plugins/archive/archive.js
index eee41d336..3500b9fe4 100644
--- a/plugins/archive/archive.js
+++ b/plugins/archive/archive.js
@@ -7,18 +7,16 @@ function rcmail_archive(prop)
{
if (!rcmail.env.uid && (!rcmail.message_list || !rcmail.message_list.get_selection().length))
return;
-
+
if (rcmail.env.mailbox.indexOf(rcmail.env.archive_folder) != 0) {
if (!rcmail.env.archive_type) {
// simply move to archive folder (if no partition type is set)
- rcmail.command('moveto', rcmail.env.archive_folder);
+ rcmail.command('move', rcmail.env.archive_folder);
}
else {
// let the server sort the messages to the according subfolders
- rcmail.http_post(
- 'plugin.move2archive',
- { _uid: rcmail.message_list.get_selection().join(','), _mbox: rcmail.env.mailbox }
- );
+ var post_data = { _uid: rcmail.message_list.get_selection().join(','), _mbox: rcmail.env.mailbox };
+ rcmail.http_post('plugin.move2archive', post_data);
}
}
}
@@ -26,16 +24,15 @@ function rcmail_archive(prop)
// callback for app-onload event
if (window.rcmail) {
rcmail.addEventListener('init', function(evt) {
-
// register command (directly enable in message view mode)
rcmail.register_command('plugin.archive', rcmail_archive, (rcmail.env.uid && rcmail.env.mailbox != rcmail.env.archive_folder));
-
+
// add event-listener to message list
if (rcmail.message_list)
- rcmail.message_list.addEventListener('select', function(list){
+ rcmail.message_list.addEventListener('select', function(list) {
rcmail.enable_command('plugin.archive', (list.get_selection().length > 0 && rcmail.env.mailbox != rcmail.env.archive_folder));
});
-
+
// set css style for archive folder
var li;
if (rcmail.env.archive_folder && (li = rcmail.get_folder_li(rcmail.env.archive_folder, '', true)))
@@ -48,4 +45,3 @@ if (window.rcmail) {
});
})
}
-
diff --git a/plugins/archive/archive.php b/plugins/archive/archive.php
index 38b4f9fcb..7a81606ab 100644
--- a/plugins/archive/archive.php
+++ b/plugins/archive/archive.php
@@ -41,7 +41,7 @@ class archive extends rcube_plugin
'domain' => $this->ID,
),
'toolbar');
-
+
// register hook to localize the archive folder
$this->add_hook('render_mailboxlist', array($this, 'render_mailboxlist'));
@@ -75,10 +75,10 @@ class archive extends rcube_plugin
{
$rcmail = rcmail::get_instance();
$archive_folder = $rcmail->config->get('archive_mbox');
- $localize_name = $rcmail->config->get('archive_localize_name', true);
+ $show_real_name = $rcmail->config->get('show_real_foldernames');
// set localized name for the configured archive folder
- if ($archive_folder && $localize_name) {
+ if ($archive_folder && !$show_real_name) {
if (isset($p['list'][$archive_folder]))
$p['list'][$archive_folder]['name'] = $this->gettext('archivefolder');
else // search in subfolders
diff --git a/plugins/archive/localization/lb_LU.inc b/plugins/archive/localization/lb_LU.inc
new file mode 100644
index 000000000..6e9e6db22
--- /dev/null
+++ b/plugins/archive/localization/lb_LU.inc
@@ -0,0 +1,34 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | plugins/archive/localization/<lang>.inc |
+ | |
+ | Localization file of the Roundcube Webmail Archive plugin |
+ | Copyright (C) 2013, The Roundcube Dev Team |
+ | |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
+ | |
+ +-----------------------------------------------------------------------+
+
+ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-archive/
+*/
+
+$labels = array();
+$labels['buttontext'] = 'Archivéieren';
+$labels['buttontitle'] = 'Dëse Message archivéieren';
+$labels['archived'] = 'Erfollegräich archivéiert';
+$labels['archivedreload'] = 'Erfollegräich archivéiert. Lued d\'Säit nei fir déi neisten Archiv-Dossieren ze gesinn.';
+$labels['archiveerror'] = 'Verschidde Messagë konnten net archivéiert ginn';
+$labels['archivefolder'] = 'Archiv';
+$labels['settingstitle'] = 'Archiv';
+$labels['archivetype'] = 'Archiv dividéieren duerch';
+$labels['archivetypeyear'] = 'Joer (z.B. Archiv/2013)';
+$labels['archivetypemonth'] = 'Mount (z.B. Archiv/2013/06)';
+$labels['archivetypefolder'] = 'Original-Dossier';
+$labels['archivetypesender'] = 'Sender-E-Mail';
+$labels['unkownsender'] = 'onbekannt';
+
+?>
diff --git a/plugins/archive/localization/lv_LV.inc b/plugins/archive/localization/lv_LV.inc
index ad2812fba..d4c892705 100644
--- a/plugins/archive/localization/lv_LV.inc
+++ b/plugins/archive/localization/lv_LV.inc
@@ -18,17 +18,17 @@
$labels = array();
$labels['buttontext'] = 'Arhīvs';
-$labels['buttontitle'] = 'Arhivēt vēstuli';
-$labels['archived'] = 'Vēstule sekmīgi arhivēta';
-$labels['archivedreload'] = 'Successfully archived. Reload the page to see the new archive folders.';
-$labels['archiveerror'] = 'Some messages could not be archived';
+$labels['buttontitle'] = 'Arhivēt šo vēstuli';
+$labels['archived'] = 'Vēstule veiksmīgi arhivēta';
+$labels['archivedreload'] = 'ArhÄ«vs veiksmÄ«gi izveidots. Lai redzÄ“tu jaunÄs arhÄ«va mapes, pÄrlÄdÄ“jiet lapu.';
+$labels['archiveerror'] = 'Dažas vēstules nebija iespējams arhivēt';
$labels['archivefolder'] = 'Arhīvs';
-$labels['settingstitle'] = 'Archive';
-$labels['archivetype'] = 'Divide archive by';
-$labels['archivetypeyear'] = 'Year (e.g. Archive/2012)';
-$labels['archivetypemonth'] = 'Month (e.g. Archive/2012/06)';
-$labels['archivetypefolder'] = 'Original folder';
-$labels['archivetypesender'] = 'Sender email';
-$labels['unkownsender'] = 'unknown';
+$labels['settingstitle'] = 'Arhīvs';
+$labels['archivetype'] = 'Sadalīt arhīvu pa';
+$labels['archivetypeyear'] = 'Gadiem (piem. Arhīvs/2012)';
+$labels['archivetypemonth'] = 'Mēnešiem (piem. Arhīvs/2012/06)';
+$labels['archivetypefolder'] = 'SÄkotnÄ“jÄ mape';
+$labels['archivetypesender'] = 'SÅ«tÄ«tÄja e-pasts';
+$labels['unkownsender'] = 'nezinÄms';
?>
diff --git a/plugins/attachment_reminder/attachment_reminder.php b/plugins/attachment_reminder/attachment_reminder.php
index a215ff57c..84cc5f3b3 100755
--- a/plugins/attachment_reminder/attachment_reminder.php
+++ b/plugins/attachment_reminder/attachment_reminder.php
@@ -22,7 +22,7 @@
* 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, see <http://www.gnu.org/licenses/>
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
*/
class attachment_reminder extends rcube_plugin
@@ -36,9 +36,11 @@ class attachment_reminder extends rcube_plugin
$rcmail = rcube::get_instance();
if ($rcmail->task == 'mail' && $rcmail->action == 'compose') {
- $this->include_script('attachment_reminder.js');
- $this->add_texts('localization/', array('keywords', 'forgotattachment'));
- $rcmail->output->add_label('addattachment', 'send');
+ if ($rcmail->config->get('attachment_reminder')) {
+ $this->include_script('attachment_reminder.js');
+ $this->add_texts('localization/', array('keywords', 'forgotattachment'));
+ $rcmail->output->add_label('addattachment', 'send');
+ }
}
if ($rcmail->task == 'settings') {
diff --git a/plugins/attachment_reminder/localization/lb_LU.inc b/plugins/attachment_reminder/localization/lb_LU.inc
new file mode 100644
index 000000000..cdfe031d1
--- /dev/null
+++ b/plugins/attachment_reminder/localization/lb_LU.inc
@@ -0,0 +1,22 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | plugins/attachment_reminder/localization/<lang>.inc |
+ | |
+ | Localization file of the Roundcube Webmail Archive plugin |
+ | Copyright (C) 2013, The Roundcube Dev Team |
+ | |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
+ | |
+ +-----------------------------------------------------------------------+
+
+ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-attachment_reminder/
+*/
+
+$messages = array();
+$messages['forgotattachment'] = "Hues du vergiess e Fichier drunzehänken?";
+$messages['reminderoption'] = "U vergiessen Unhäng erënneren";
+$messages['keywords'] = "Attachment,Fichier,Unhank,Unhang,Unhäng,ugehaangen,unhänken,attachment,file,attach,attached,attaching,enclosed,CV,cover letter,fichier joint";
diff --git a/plugins/database_attachments/config.inc.php.dist b/plugins/database_attachments/config.inc.php.dist
new file mode 100644
index 000000000..b23a9a1be
--- /dev/null
+++ b/plugins/database_attachments/config.inc.php.dist
@@ -0,0 +1,12 @@
+<?php
+
+// By default this plugin stores attachments in filesystem
+// and copies them into sql database.
+// You can change it to use 'memcache' or 'apc'.
+$rcmail_config['database_attachments_cache'] = 'db';
+
+// Attachment data expires after specied TTL time in seconds (max.2592000).
+// Default is 12 hours.
+$rcmail_config['database_attachments_cache_ttl'] = 12 * 60 * 60;
+
+?>
diff --git a/plugins/database_attachments/database_attachments.php b/plugins/database_attachments/database_attachments.php
index 2511dbbb2..47e2b5222 100644
--- a/plugins/database_attachments/database_attachments.php
+++ b/plugins/database_attachments/database_attachments.php
@@ -1,6 +1,6 @@
<?php
/**
- * Filesystem Attachments
+ * Database Attachments
*
* This plugin which provides database backed storage for temporary
* attachment file handling. The primary advantage of this plugin
@@ -16,18 +16,11 @@
require_once('plugins/filesystem_attachments/filesystem_attachments.php');
class database_attachments extends filesystem_attachments
{
+ // Cache object
+ protected $cache;
// A prefix for the cache key used in the session and in the key field of the cache table
- private $cache_prefix = "db_attach";
-
- /**
- * Helper method to generate a unique key for the given attachment file
- */
- private function _key($args)
- {
- $uname = $args['path'] ? $args['path'] : $args['name'];
- return $this->cache_prefix . $args['group'] . md5(mktime() . $uname . $_SESSION['user_id']);
- }
+ protected $prefix = "db_attach";
/**
* Save a newly uploaded attachment
@@ -35,23 +28,17 @@ class database_attachments extends filesystem_attachments
function upload($args)
{
$args['status'] = false;
- $rcmail = rcmail::get_instance();
- $key = $this->_key($args);
- $data = file_get_contents($args['path']);
+ $cache = $this->get_cache();
+ $key = $this->_key($args);
+ $data = file_get_contents($args['path']);
- if ($data === false)
+ if ($data === false) {
return $args;
+ }
- $data = base64_encode($data);
-
- $status = $rcmail->db->query(
- "INSERT INTO ".$rcmail->db->table_name('cache')
- ." (created, user_id, cache_key, data)"
- ." VALUES (".$rcmail->db->now().", ?, ?, ?)",
- $_SESSION['user_id'],
- $key,
- $data);
+ $data = base64_encode($data);
+ $status = $cache->write($key, $data);
if ($status) {
$args['id'] = $key;
@@ -68,26 +55,20 @@ class database_attachments extends filesystem_attachments
function save($args)
{
$args['status'] = false;
- $rcmail = rcmail::get_instance();
- $key = $this->_key($args);
+ $cache = $this->get_cache();
+ $key = $this->_key($args);
if ($args['path']) {
$args['data'] = file_get_contents($args['path']);
- if ($args['data'] === false)
+ if ($args['data'] === false) {
return $args;
+ }
}
- $data = base64_encode($args['data']);
-
- $status = $rcmail->db->query(
- "INSERT INTO ".$rcmail->db->table_name('cache')
- ." (created, user_id, cache_key, data)"
- ." VALUES (".$rcmail->db->now().", ?, ?, ?)",
- $_SESSION['user_id'],
- $key,
- $data);
+ $data = base64_encode($args['data']);
+ $status = $cache->write($key, $data);
if ($status) {
$args['id'] = $key;
@@ -104,13 +85,9 @@ class database_attachments extends filesystem_attachments
function remove($args)
{
$args['status'] = false;
- $rcmail = rcmail::get_instance();
- $status = $rcmail->db->query(
- "DELETE FROM ".$rcmail->db->table_name('cache')
- ." WHERE user_id = ?"
- ." AND cache_key = ?",
- $_SESSION['user_id'],
- $args['id']);
+
+ $cache = $this->get_cache();
+ $status = $cache->remove($args['id']);
if ($status) {
$args['status'] = true;
@@ -135,18 +112,11 @@ class database_attachments extends filesystem_attachments
*/
function get($args)
{
- $rcmail = rcmail::get_instance();
-
- $sql_result = $rcmail->db->query(
- "SELECT data"
- ." FROM ".$rcmail->db->table_name('cache')
- ." WHERE user_id=?"
- ." AND cache_key=?",
- $_SESSION['user_id'],
- $args['id']);
-
- if ($sql_arr = $rcmail->db->fetch_assoc($sql_result)) {
- $args['data'] = base64_decode($sql_arr['data']);
+ $cache = $this->get_cache();
+ $data = $cache->read($args['id']);
+
+ if ($data) {
+ $args['data'] = base64_decode($data);
$args['status'] = true;
}
@@ -158,12 +128,36 @@ class database_attachments extends filesystem_attachments
*/
function cleanup($args)
{
- $prefix = $this->cache_prefix . $args['group'];
- $rcmail = rcmail::get_instance();
- $rcmail->db->query(
- "DELETE FROM ".$rcmail->db->table_name('cache')
- ." WHERE user_id = ?"
- ." AND cache_key LIKE '{$prefix}%'",
- $_SESSION['user_id']);
+ $cache = $this->get_cache();
+ $cache->remove($args['group'], true);
+ }
+
+ /**
+ * Helper method to generate a unique key for the given attachment file
+ */
+ protected function _key($args)
+ {
+ $uname = $args['path'] ? $args['path'] : $args['name'];
+ return $args['group'] . md5(mktime() . $uname . $_SESSION['user_id']);
+ }
+
+ /**
+ * Initialize and return cache object
+ */
+ protected function get_cache()
+ {
+ if (!$this->cache) {
+ $this->load_config();
+
+ $rcmail = rcube::get_instance();
+ $ttl = 12 * 60 * 60; // default: 12 hours
+ $ttl = $rcmail->config->get('database_attachments_cache_ttl', $ttl);
+ $type = $rcmail->config->get('database_attachments_cache', 'db');
+
+ // Init SQL cache (disable cache data serialization)
+ $this->cache = $rcmail->get_cache($this->prefix, 'db', $ttl, false);
+ }
+
+ return $this->cache;
}
}
diff --git a/plugins/database_attachments/package.xml b/plugins/database_attachments/package.xml
index 40db858a4..44adc219e 100644
--- a/plugins/database_attachments/package.xml
+++ b/plugins/database_attachments/package.xml
@@ -5,7 +5,7 @@
http://pear.php.net/dtd/package-2.0.xsd">
<name>database_attachments</name>
<channel>pear.roundcube.net</channel>
- <summary>SQL database storage for uploaded attachments</summary>
+ <summary>Database storage for uploaded attachments</summary>
<description>
This plugin which provides database backed storage for temporary
attachment file handling. The primary advantage of this plugin
@@ -24,9 +24,9 @@
<email>ziba@umich.edu</email>
<active>yes</active>
</developer>
- <date>2011-11-21</date>
+ <date>2013-06-13</date>
<version>
- <release>1.0</release>
+ <release>1.1</release>
<api>1.0</api>
</version>
<stability>
diff --git a/plugins/debug_logger/debug_logger.php b/plugins/debug_logger/debug_logger.php
index 87a163785..deb6deb91 100644
--- a/plugins/debug_logger/debug_logger.php
+++ b/plugins/debug_logger/debug_logger.php
@@ -12,7 +12,7 @@
* which can redirect messages to files. The resulting log files
* provide timing and tag quantity results.
*
- * Enable the plugin in config/main.inc.php and add your desired
+ * Enable the plugin in config.inc.php and add your desired
* log types and files.
*
* @version @package_version@
@@ -21,7 +21,7 @@
*
* Example:
*
- * config/main.inc.php:
+ * config.inc.php:
*
* // $rcmail_config['debug_logger'][type of logging] = name of file in log_dir
* // The 'master' log includes timing information
diff --git a/plugins/enigma/skins/classic/templates/keys.html b/plugins/enigma/skins/classic/templates/keys.html
index 4271eccb7..f581c457b 100644
--- a/plugins/enigma/skins/classic/templates/keys.html
+++ b/plugins/enigma/skins/classic/templates/keys.html
@@ -13,7 +13,7 @@
}
</style>
</head>
-<body class="iframe" onload="rcube_init_mail_ui()">
+<body class="iframe">
<div id="prefs-title" class="boxtitle"><roundcube:label name="enigma.enigmakeys" /></div>
<div id="prefs-details" class="boxcontent">
@@ -72,5 +72,9 @@
</ul>
</div>
+<script type="text/javascript">
+rcube_init_mail_ui();
+</script>
+
</body>
</html>
diff --git a/plugins/example_addressbook/example_addressbook.php b/plugins/example_addressbook/example_addressbook.php
index a15461f44..31077adf7 100644
--- a/plugins/example_addressbook/example_addressbook.php
+++ b/plugins/example_addressbook/example_addressbook.php
@@ -5,6 +5,9 @@ require_once(dirname(__FILE__) . '/example_addressbook_backend.php');
/**
* Sample plugin to add a new address book
* with just a static list of contacts
+ *
+ * @license GNU GPLv3+
+ * @author Thomas Bruederli
*/
class example_addressbook extends rcube_plugin
{
diff --git a/plugins/filesystem_attachments/filesystem_attachments.php b/plugins/filesystem_attachments/filesystem_attachments.php
index d952e5a75..8d995ca0d 100644
--- a/plugins/filesystem_attachments/filesystem_attachments.php
+++ b/plugins/filesystem_attachments/filesystem_attachments.php
@@ -13,6 +13,7 @@
* require_once('plugins/filesystem_attachments/filesystem_attachments.php');
* class myCustom_attachments extends filesystem_attachments
*
+ * @license GNU GPLv3+
* @author Ziba Scott <ziba@umich.edu>
* @author Thomas Bruederli <roundcube@gmail.com>
*
diff --git a/plugins/filesystem_attachments/package.xml b/plugins/filesystem_attachments/package.xml
index 031a74297..49ec51934 100644
--- a/plugins/filesystem_attachments/package.xml
+++ b/plugins/filesystem_attachments/package.xml
@@ -34,7 +34,7 @@
<release>stable</release>
<api>stable</api>
</stability>
- <license uri="http://www.gnu.org/licenses/gpl-2.0.html">GNU GPLv2</license>
+ <license uri="http://www.gnu.org/licenses/gpl.html">GNU GPLv3+</license>
<notes>-</notes>
<contents>
<dir baseinstalldir="/" name="/">
diff --git a/plugins/help/config.inc.php.dist b/plugins/help/config.inc.php.dist
index d440dbbcc..1dbc21753 100644
--- a/plugins/help/config.inc.php.dist
+++ b/plugins/help/config.inc.php.dist
@@ -1,5 +1,35 @@
<?php
// Help content iframe source
-// $rcmail_config['help_source'] = 'http://trac.roundcube.net/wiki';
-$rcmail_config['help_source'] = '';
+// %l will be replaced by the language code resolved using the 'help_language_map' option
+$rcmail_config['help_source'] = 'http://roundcube.net/doc/help/0.9/%l/';
+
+// Map task/action combinations to deep-links
+// Use '<task>/<action>' or only '<task>' strings as keys
+// The values will be appended to the 'help_source' URL
+$rcmail_config['help_index_map'] = array(
+ 'login' => 'login.html',
+ 'mail' => 'mail/index.html',
+ 'mail/compose' => 'mail/compose.html',
+ 'addressbook' => 'addressbook/index.html',
+ 'settings' => 'settings/index.html',
+ 'settings/preferences' => 'settings/preferences.html',
+ 'settings/folders' => 'settings/folders.html',
+ 'settings/identities' => 'settings/identities.html',
+);
+
+// Map to translate Roundcube language codes into help document languages
+// The '*' entry will be used as default
+$rcmail_config['help_language_map'] = array('*' => 'en_US');
+
+// Enter an absolute URL to a page displaying information about this webmail
+// Alternatively, create a HTML file under <this-plugin-dir>/content/about.html
+$rcmail_config['help_about_url'] = null;
+
+// Enter an absolute URL to a page displaying information about this webmail
+// Alternatively, put your license text to <this-plugin-dir>/content/license.html
+$rcmail_config['help_license_url'] = null;
+
+// Determine whether to open the help in a new window
+$rcmail_config['help_open_extwin'] = false;
+
diff --git a/plugins/help/content/about.html b/plugins/help/content/about.html
deleted file mode 100644
index 6e9632bec..000000000
--- a/plugins/help/content/about.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<div id="helpabout" class="readtext">
-<h2 align="center">Copyright &copy; 2005-2012, The Roundcube Dev Team</h2>
-
-<p>
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License (with exceptions
-for skins &amp; plugins) as published by the Free Software Foundation,
-either version 3 of the License, or (at your option) any later version.
-</p>
-<p>
-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.
-</p>
-<p>
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <a href="http://www.gnu.org/licenses/">www.gnu.org/licenses</a>.
-</p>
-
-<p>
-For more details about licensing and the expections for skins and plugins
-see <a href="http://roundcube.net/license">roundcube.net/license</a>.
-</p>
-
-<p><br/>Website: <a href="http://roundcube.net">roundcube.net</a></p>
-</div>
diff --git a/plugins/help/content/license.html b/plugins/help/content/license.html
index 371dbffe1..9034d46f8 100644
--- a/plugins/help/content/license.html
+++ b/plugins/help/content/license.html
@@ -655,7 +655,7 @@ the &ldquo;copyright&rdquo; line and a pointer to where the full notice is found
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, see &lt;http://www.gnu.org/licenses/&gt;.
+ along with this program. If not, see &lt;http://www.gnu.org/licenses/&gt;.
</pre>
<p>Also add information on how to contact you by electronic and paper mail.</p>
diff --git a/plugins/help/help.js b/plugins/help/help.js
new file mode 100644
index 000000000..59a93c537
--- /dev/null
+++ b/plugins/help/help.js
@@ -0,0 +1,25 @@
+/*
+ * Help plugin client script
+ * @version 1.4
+ */
+
+// hook into switch-task event to open the help window
+if (window.rcmail) {
+ rcmail.addEventListener('beforeswitch-task', function(prop) {
+ // catch clicks to help task button
+ if (prop == 'help') {
+ if (rcmail.task == 'help') // we're already there
+ return false;
+
+ var url = rcmail.url('help/index', { _rel: rcmail.task + (rcmail.env.action ? '/'+rcmail.env.action : '') });
+ if (rcmail.env.help_open_extwin) {
+ rcmail.open_window(url, 1020, false);
+ }
+ else {
+ rcmail.redirect(url, false);
+ }
+
+ return false;
+ }
+ });
+}
diff --git a/plugins/help/help.php b/plugins/help/help.php
index 69da6828e..37fd908a3 100644
--- a/plugins/help/help.php
+++ b/plugins/help/help.php
@@ -1,9 +1,10 @@
<?php
/**
- * Help Plugin
+ * Roundcube Help Plugin
*
* @author Aleksander 'A.L.E.C' Machniak
+ * @author Thomas Bruederli <thomas@roundcube.net>
* @license GNU GPLv3+
*
* Configuration (see config.inc.php.dist)
@@ -21,6 +22,7 @@ class help extends rcube_plugin
function init()
{
+ $this->load_config();
$this->add_texts('localization/', false);
// register task
@@ -31,6 +33,8 @@ class help extends rcube_plugin
$this->register_action('about', array($this, 'action'));
$this->register_action('license', array($this, 'action'));
+ $rcmail = rcmail::get_instance();
+
// add taskbar button
$this->add_button(array(
'command' => 'help',
@@ -40,6 +44,9 @@ class help extends rcube_plugin
'label' => 'help.help',
), 'taskbar');
+ $this->include_script('help.js');
+ $rcmail->output->set_env('help_open_extwin', $rcmail->config->get('help_open_extwin', false), true);
+
// add style for taskbar button (must be here) and Help UI
$skin_path = $this->local_skin_path();
if (is_file($this->home . "/$skin_path/help.css")) {
@@ -51,11 +58,10 @@ class help extends rcube_plugin
{
$rcmail = rcmail::get_instance();
- $this->load_config();
-
// register UI objects
$rcmail->output->add_handlers(array(
'helpcontent' => array($this, 'content'),
+ 'tablink' => array($this, 'tablink'),
));
if ($rcmail->action == 'about')
@@ -68,20 +74,52 @@ class help extends rcube_plugin
$rcmail->output->send('help.help');
}
+ function tablink($attrib)
+ {
+ $rcmail = rcmail::get_instance();
+ $attrib['name'] = 'helplink' . $attrib['action'];
+ $attrib['href'] = $rcmail->url(array('_action' => $attrib['action'], '_extwin' => !empty($_REQUEST['_extwin']) ? 1 : null));
+ return $rcmail->output->button($attrib);
+ }
+
function content($attrib)
{
$rcmail = rcmail::get_instance();
- if ($rcmail->action == 'about') {
- return @file_get_contents($this->home.'/content/about.html');
- }
- else if ($rcmail->action == 'license') {
- return @file_get_contents($this->home.'/content/license.html');
+ switch ($rcmail->action) {
+ case 'about':
+ if (is_readable($this->home . '/content/about.html')) {
+ return @file_get_contents($this->home . '/content/about.html');
+ }
+ $default = $rcmail->url(array('_task' => 'settings', '_action' => 'about', '_framed' => 1));
+ $src = $rcmail->config->get('help_about_url', $default);
+ break;
+
+ case 'license':
+ if (is_readable($this->home . '/content/license.html')) {
+ return @file_get_contents($this->home . '/content/license.html');
+ }
+ $src = $rcmail->config->get('help_license_url', 'http://www.gnu.org/licenses/gpl-3.0-standalone.html');
+ break;
+
+ default:
+ $src = $rcmail->config->get('help_source');
+
+ // resolve task/action for depp linking
+ $index_map = $rcmail->config->get('help_index_map', array());
+ $rel = $_REQUEST['_rel'];
+ list($task,$action) = explode('/', $rel);
+ if ($add = $index_map[$rel])
+ $src .= $add;
+ else if ($add = $index_map[$task])
+ $src .= $add;
+ break;
}
// default content: iframe
- if ($src = $rcmail->config->get('help_source'))
- $attrib['src'] = $src;
+ if (!empty($src)) {
+ $attrib['src'] = $this->resolve_language($src);
+ }
if (empty($attrib['id']))
$attrib['id'] = 'rcmailhelpcontent';
@@ -91,4 +129,13 @@ class help extends rcube_plugin
return $rcmail->output->frame($attrib);
}
+
+ private function resolve_language($path)
+ {
+ // resolve language placeholder
+ $rcmail = rcmail::get_instance();
+ $langmap = $rcmail->config->get('help_language_map', array('*' => 'en_US'));
+ $lang = !empty($langmap[$_SESSION['language']]) ? $langmap[$_SESSION['language']] : $langmap['*'];
+ return str_replace('%l', $lang, $path);
+ }
}
diff --git a/plugins/help/localization/de_DE.inc b/plugins/help/localization/de_DE.inc
index 70c50646e..250657da6 100644
--- a/plugins/help/localization/de_DE.inc
+++ b/plugins/help/localization/de_DE.inc
@@ -18,7 +18,7 @@
$labels = array();
$labels['help'] = 'Hilfe';
-$labels['about'] = '&Uuml;ber';
+$labels['about'] = 'Ãœber';
$labels['license'] = 'Lizenz';
?>
diff --git a/plugins/help/localization/gl_ES.inc b/plugins/help/localization/gl_ES.inc
index 432623751..e3e9e36ca 100644
--- a/plugins/help/localization/gl_ES.inc
+++ b/plugins/help/localization/gl_ES.inc
@@ -19,6 +19,6 @@
$labels = array();
$labels['help'] = 'Axuda';
$labels['about'] = 'Acerca de';
-$labels['license'] = 'Licencia';
+$labels['license'] = 'Licenza';
?>
diff --git a/plugins/help/localization/lb_LU.inc b/plugins/help/localization/lb_LU.inc
new file mode 100644
index 000000000..0a7ec6eef
--- /dev/null
+++ b/plugins/help/localization/lb_LU.inc
@@ -0,0 +1,24 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | plugins/help/localization/<lang>.inc |
+ | |
+ | Localization file of the Roundcube Webmail Help plugin |
+ | Copyright (C) 2012-2013, The Roundcube Dev Team |
+ | |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
+ | |
+ +-----------------------------------------------------------------------+
+
+ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-help/
+*/
+
+$labels = array();
+$labels['help'] = 'Hëllef';
+$labels['about'] = 'Iwwert';
+$labels['license'] = 'Lizenz';
+
+?>
diff --git a/plugins/help/package.xml b/plugins/help/package.xml
index 889efd17d..d39143ba1 100644
--- a/plugins/help/package.xml
+++ b/plugins/help/package.xml
@@ -5,7 +5,7 @@
http://pear.php.net/dtd/package-2.0.xsd">
<name>help</name>
<channel>pear.roundcube.net</channel>
- <summary>Help for Roundcube</summary>
+ <summary>Online Help for Roundcube</summary>
<description>Plugin adds a new item (Help) in taskbar.</description>
<lead>
<name>Aleksander Machniak</name>
@@ -13,10 +13,10 @@
<email>alec@alec.pl</email>
<active>yes</active>
</lead>
- <date>2012-11-11</date>
+ <date>2013-07-03</date>
<version>
- <release>1.3</release>
- <api>1.2</api>
+ <release>1.4</release>
+ <api>1.4</api>
</version>
<stability>
<release>stable</release>
@@ -31,7 +31,6 @@
<tasks:replace from="@package_version@" to="version" type="package-info"/>
</file>
<file name="config.inc.php.dist" role="data"></file>
- <file name="content/about.html" role="data"></file>
<file name="content/license.html" role="data"></file>
<file name="localization/bs_BA.inc" role="data"></file>
<file name="localization/ca_ES.inc" role="data"></file>
diff --git a/plugins/help/skins/classic/help.css b/plugins/help/skins/classic/help.css
index 8f67f111e..c45b8f0b0 100644
--- a/plugins/help/skins/classic/help.css
+++ b/plugins/help/skins/classic/help.css
@@ -5,9 +5,23 @@
background-image: url('help.gif');
}
+.extwin #tabsbar
+{
+ top: 21px;
+ left: 20px;
+ right: 100px;
+ border-bottom: 0;
+}
+
+.closelink {
+ position: absolute;
+ top: 20px;
+ right: 20px;
+}
+
.help-box
{
- overflow: auto;
+ overflow: auto;
background-color: #F2F2F2;
}
diff --git a/plugins/help/skins/classic/templates/help.html b/plugins/help/skins/classic/templates/help.html
index 2e430ecf3..3d5b22869 100644
--- a/plugins/help/skins/classic/templates/help.html
+++ b/plugins/help/skins/classic/templates/help.html
@@ -7,23 +7,28 @@
<script type="text/javascript">
function help_init_settings_tabs()
{
- var action, tab = '#helptabdefault';
+ var action, tab = '#helptabindex';
if (window.rcmail && (action = rcmail.env.action)) {
- tab = '#helptab' + (action ? action : 'default');
+ tab = '#helptab' + (action ? action : 'index');
}
$(tab).addClass('tablink-selected');
}
</script>
</head>
+<roundcube:if condition="env:extwin" />
+<body class="extwin">
+<roundcube:object name="message" id="message" />
+<roundcube:button name="close" type="link" label="close" class="closelink" onclick="self.close()" />
+<roundcube:else />
<body>
-
<roundcube:include file="/includes/taskbar.html" />
<roundcube:include file="/includes/header.html" />
+<roundcube:endif />
<div id="tabsbar">
-<span id="helptabdefault" class="tablink"><roundcube:button name="helpdefault" href="?_task=help" type="link" label="help.help" title="help.help" /></span>
-<span id="helptababout" class="tablink"><roundcube:button name="helpabout" href="?_task=help&_action=about" type="link" label="help.about" title="help.about" class="tablink" /></span>
-<span id="helptablicense" class="tablink"><roundcube:button name="helplicense" href="?_task=help&_action=license" type="link" label="help.license" title="help.license" class="tablink" /></span>
+<span id="helptabindex" class="tablink"><roundcube:object name="tablink" action="index" type="link" label="help.help" title="help.help" /></span>
+<span id="helptababout" class="tablink"><roundcube:object name="tablink" action="about" type="link" label="help.about" title="help.about" class="tablink" /></span>
+<span id="helptablicense" class="tablink"><roundcube:object name="tablink" action="license" type="link" label="help.license" title="help.license" class="tablink" /></span>
<roundcube:container name="helptabs" id="helptabsbar" />
<script type="text/javascript"> if (window.rcmail) rcmail.add_onload(help_init_settings_tabs);</script>
</div>
diff --git a/plugins/help/skins/larry/help.css b/plugins/help/skins/larry/help.css
index c2e369af6..d9af6e15e 100644
--- a/plugins/help/skins/larry/help.css
+++ b/plugins/help/skins/larry/help.css
@@ -39,7 +39,6 @@
background: url(help.png) center -130px no-repeat;
}
-.iframebox.help_about,
.iframebox.help_license {
overflow: auto;
}
diff --git a/plugins/help/skins/larry/templates/help.html b/plugins/help/skins/larry/templates/help.html
index 39caaa62f..bfd3f1141 100644
--- a/plugins/help/skins/larry/templates/help.html
+++ b/plugins/help/skins/larry/templates/help.html
@@ -4,16 +4,16 @@
<title><roundcube:object name="pagetitle" /></title>
<roundcube:include file="/includes/links.html" />
</head>
-<body>
+<roundcube:if condition="env:extwin" /><body class="extwin"><roundcube:else /><body><roundcube:endif />
<roundcube:include file="/includes/header.html" />
<div id="mainscreen">
<div id="helptoolbar" class="toolbar">
-<roundcube:button name="helpdefault" href="?_task=help" type="link" label="help.help" title="help.help" class="button help" />
-<roundcube:button name="helpabout" href="?_task=help&amp;_action=about" type="link" label="help.about" title="help.about" class="button about" />
-<roundcube:button name="helplicense" href="?_task=help&amp;_action=license" type="link" label="help.license" title="help.license" class="button license" />
+<roundcube:object name="tablink" action="index" type="link" label="help.help" title="help.help" class="button help" />
+<roundcube:object name="tablink" action="about" type="link" label="help.about" title="help.about" class="button about" />
+<roundcube:object name="tablink" action="license" type="link" label="help.license" title="help.license" class="button license" />
<roundcube:container name="helptabs" id="helptabsbar" />
</div>
diff --git a/plugins/hide_blockquote/localization/lb_LU.inc b/plugins/hide_blockquote/localization/lb_LU.inc
new file mode 100644
index 000000000..98e0f6936
--- /dev/null
+++ b/plugins/hide_blockquote/localization/lb_LU.inc
@@ -0,0 +1,24 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | plugins/hide_blockquote/localization/<lang>.inc |
+ | |
+ | Localization file of the Roundcube Webmail Hide-Blockquote plugin |
+ | Copyright (C) 2012-2013, The Roundcube Dev Team |
+ | |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
+ | |
+ +-----------------------------------------------------------------------+
+
+ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-hide_blockquote/
+*/
+
+$labels = array();
+$labels['hide'] = 'Verstoppen';
+$labels['show'] = 'Weisen';
+$labels['quotelimit'] = 'Zitat verstoppe wann d\'Zeilenunzuel méi grouss ass ewéi';
+
+?>
diff --git a/plugins/http_authentication/http_authentication.php b/plugins/http_authentication/http_authentication.php
index 57227cb03..2631537a0 100644
--- a/plugins/http_authentication/http_authentication.php
+++ b/plugins/http_authentication/http_authentication.php
@@ -52,7 +52,7 @@ class http_authentication extends rcube_plugin
$this->load_config();
$host = rcmail::get_instance()->config->get('http_authentication_host');
- if (is_string($host) && trim($host) !== '')
+ if (is_string($host) && trim($host) !== '' && empty($args['host']))
$args['host'] = rcube_utils::idn_to_ascii(rcube_utils::parse_host($host));
// Allow entering other user data in login form,
diff --git a/plugins/jqueryui/jqueryui.php b/plugins/jqueryui/jqueryui.php
index db640d1aa..e9b3c215e 100644
--- a/plugins/jqueryui/jqueryui.php
+++ b/plugins/jqueryui/jqueryui.php
@@ -8,6 +8,7 @@
* @version 1.9.1
* @author Cor Bosman <roundcube@wa.ter.net>
* @author Thomas Bruederli <roundcube@gmail.com>
+ * @license GNU GPLv3+
*/
class jqueryui extends rcube_plugin
{
diff --git a/plugins/managesieve/Changelog b/plugins/managesieve/Changelog
index 305fb1e56..daee91a70 100644
--- a/plugins/managesieve/Changelog
+++ b/plugins/managesieve/Changelog
@@ -1,5 +1,9 @@
- Add vacation-seconds extension support (RFC 6131)
- Several script parser code improvements
+- Support string list arguments in filter form (#1489018)
+- Support date, currendate and index tests - RFC5260 (#1488120)
+- Split plugin file into two files
+- Fix handling of &, <, > characters in scripts/filter names (#1489208)
* version 6.2 [2013-02-17]
-----------------------------------------------------------
@@ -206,18 +210,18 @@
- Added it_IT localization
* version 1.1 [2009-05-27]
------------------------------------------------------------
+-----------------------------------------------------------
- Added new icons
- Added support for headers lists (coma-separated) in rules
- Added de_CH localization
* version 1.0 [2009-05-21]
------------------------------------------------------------
+-----------------------------------------------------------
- Rewritten using plugin API
- Added hu_HU localization (Tamas Tevesz)
* version beta7 (svn-r2300) [2009-03-01]
------------------------------------------------------------
+-----------------------------------------------------------
- Added SquirrelMail script auto-import (Jonathan Ernst)
- Added 'vacation' support (Jonathan Ernst & alec)
- Added 'stop' support (Jonathan Ernst)
@@ -226,47 +230,47 @@
- Small style fixes
* version 0.2-stable1 (svn-r2205) [2009-01-03]
------------------------------------------------------------
+-----------------------------------------------------------
- Fix moving down filter row
- Fixes for compressed js files in stable release package
- Created patch for svn version r2205
* version 0.2-stable [2008-12-31]
------------------------------------------------------------
+-----------------------------------------------------------
- Added ru_RU, fr_FR, zh_CN translation
- Fixes for Roundcube 0.2-stable
-* version rc0.2beta [2008-09-21]
------------------------------------------------------------
+* version 0.2-beta [2008-09-21]
+-----------------------------------------------------------
- Small css fixes for IE
- Fixes for Roundcube 0.2-beta
* version beta6 [2008-08-08]
------------------------------------------------------------
+-----------------------------------------------------------
- Added de_DE translation
- Fix for Roundcube r1634
* version beta5 [2008-06-10]
------------------------------------------------------------
+-----------------------------------------------------------
- Fixed 'exists' operators
- Fixed 'not*' operators for custom headers
- Fixed filters deleting
* version beta4 [2008-06-09]
------------------------------------------------------------
+-----------------------------------------------------------
- Fix for Roundcube r1490
* version beta3 [2008-05-22]
------------------------------------------------------------
+-----------------------------------------------------------
- Fixed textarea error class setting
- Added pagetitle setting
- Added option 'managesieve_replace_delimiter'
- Fixed errors on IE (still need some css fixes)
-
+
* version beta2 [2008-05-20]
------------------------------------------------------------
+-----------------------------------------------------------
- Use 'if' only for first filter and 'elsif' for the rest
* version beta1 [2008-05-15]
------------------------------------------------------------
+-----------------------------------------------------------
- Initial version for Roundcube r1388.
diff --git a/plugins/managesieve/lib/Roundcube/rcube_sieve.php b/plugins/managesieve/lib/Roundcube/rcube_sieve.php
index a04e3c2a4..3bd2978da 100644
--- a/plugins/managesieve/lib/Roundcube/rcube_sieve.php
+++ b/plugins/managesieve/lib/Roundcube/rcube_sieve.php
@@ -6,18 +6,18 @@
* 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 free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
* 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.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
*/
// Managesieve Protocol: RFC5804
diff --git a/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php b/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php
new file mode 100644
index 000000000..e92ba04d6
--- /dev/null
+++ b/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php
@@ -0,0 +1,2122 @@
+<?php
+
+/**
+ * Managesieve (Sieve Filters) Engine
+ *
+ * Engine part of Managesieve plugin implementing UI and backend access.
+ *
+ * Copyright (C) 2008-2013, The Roundcube Dev Team
+ * Copyright (C) 2011-2013, 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 as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see http://www.gnu.org/licenses/.
+ */
+
+class rcube_sieve_engine
+{
+ private $rc;
+ private $sieve;
+ private $errors;
+ private $form;
+ private $tips = array();
+ private $script = array();
+ private $exts = array();
+ private $list;
+ private $active = array();
+ private $headers = array(
+ '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 = '7.0';
+ const PROGNAME = 'Roundcube (Managesieve)';
+ const PORT = 4190;
+
+
+ /**
+ * Class constructor
+ */
+ function __construct($plugin)
+ {
+ $this->rc = rcmail::get_instance();
+ $this->plugin = $plugin;
+ }
+
+ /**
+ * Loads configuration, initializes plugin (including sieve connection)
+ */
+ function start()
+ {
+ // register UI objects
+ $this->rc->output->add_handlers(array(
+ 'filterslist' => array($this, 'filters_list'),
+ 'filtersetslist' => array($this, 'filtersets_list'),
+ 'filterframe' => array($this, 'filter_frame'),
+ 'filterform' => array($this, 'filter_form'),
+ 'filtersetform' => array($this, 'filterset_form'),
+ ));
+
+ // Get connection parameters
+ $host = $this->rc->config->get('managesieve_host', 'localhost');
+ $port = $this->rc->config->get('managesieve_port');
+ $tls = $this->rc->config->get('managesieve_usetls', false);
+
+ $host = rcube_utils::parse_host($host);
+ $host = rcube_utils::idn_to_ascii($host);
+
+ // remove tls:// prefix, set TLS flag
+ if (($host = preg_replace('|^tls://|i', '', $host, 1, $cnt)) && $cnt) {
+ $tls = true;
+ }
+
+ if (empty($port)) {
+ $port = getservbyname('sieve', 'tcp');
+ if (empty($port)) {
+ $port = self::PORT;
+ }
+ }
+
+ $plugin = $this->rc->plugins->exec_hook('managesieve_connect', array(
+ 'user' => $_SESSION['username'],
+ 'password' => $this->rc->decrypt($_SESSION['password']),
+ 'host' => $host,
+ 'port' => $port,
+ 'usetls' => $tls,
+ 'auth_type' => $this->rc->config->get('managesieve_auth_type'),
+ '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
+ $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())) {
+ // Get list of scripts
+ $list = $this->list_scripts();
+
+ if (!empty($_GET['_set']) || !empty($_POST['_set'])) {
+ $script_name = rcube_utils::get_input_value('_set', rcube_utils::INPUT_GPC, true);
+ }
+ else if (!empty($_SESSION['managesieve_current'])) {
+ $script_name = $_SESSION['managesieve_current'];
+ }
+ else {
+ // get (first) active script
+ if (!empty($this->active[0])) {
+ $script_name = $this->active[0];
+ }
+ else if ($list) {
+ $script_name = $list[0];
+ }
+ // create a new (initial) script
+ else {
+ // if script not exists build default script contents
+ $script_file = $this->rc->config->get('managesieve_default');
+ $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);
+
+ // 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) {
+ $this->sieve->load($script_name);
+ }
+
+ $error = $this->sieve->error();
+ }
+
+ // finally set script objects
+ if ($error) {
+ switch ($error) {
+ case SIEVE_ERROR_CONNECTION:
+ case SIEVE_ERROR_LOGIN:
+ $this->rc->output->show_message('managesieve.filterconnerror', 'error');
+ break;
+ default:
+ $this->rc->output->show_message('managesieve.filterunknownerror', 'error');
+ break;
+ }
+
+ rcube::raise_error(array('code' => 403, 'type' => 'php',
+ 'file' => __FILE__, 'line' => __LINE__,
+ 'message' => "Unable to connect to managesieve on $host:$port"), true, false);
+
+ // to disable 'Add filter' button set env variable
+ $this->rc->output->set_env('filterconnerror', true);
+ $this->script = array();
+ }
+ else {
+ $this->exts = $this->sieve->get_extensions();
+ $this->script = $this->sieve->script->as_array();
+ $this->rc->output->set_env('currentset', $this->sieve->current);
+ $_SESSION['managesieve_current'] = $this->sieve->current;
+ }
+
+ return $error;
+ }
+
+ function actions()
+ {
+ $error = $this->start();
+
+ // Handle user requests
+ if ($action = rcube_utils::get_input_value('_act', rcube_utils::INPUT_GPC)) {
+ $fid = (int) rcube_utils::get_input_value('_fid', rcube_utils::INPUT_POST);
+
+ if ($action == 'delete' && !$error) {
+ if (isset($this->script[$fid])) {
+ if ($this->sieve->script->delete_rule($fid))
+ $result = $this->save_script();
+
+ 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 == 'move' && !$error) {
+ if (isset($this->script[$fid])) {
+ $to = (int) rcube_utils::get_input_value('_to', rcube_utils::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) {
+ $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 {
+ $this->rc->output->show_message('managesieve.moveerror', 'error');
+ }
+ }
+ }
+ else if ($action == 'act' && !$error) {
+ if (isset($this->script[$fid])) {
+ $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 ($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 {
+ 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) {
+ $script_name = rcube_utils::get_input_value('_set', rcube_utils::INPUT_GPC, true);
+ $result = $this->activate_script($script_name);
+ $kep14 = $this->rc->config->get('managesieve_kolab_master');
+
+ if ($result === true) {
+ $this->rc->output->set_env('active_sets', $this->active);
+ $this->rc->output->show_message('managesieve.setactivated', 'confirmation');
+ $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) {
+ $script_name = rcube_utils::get_input_value('_set', rcube_utils::INPUT_GPC, true);
+ $result = $this->deactivate_script($script_name);
+
+ if ($result === true) {
+ $this->rc->output->set_env('active_sets', $this->active);
+ $this->rc->output->show_message('managesieve.setdeactivated', 'confirmation');
+ $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) {
+ $script_name = rcube_utils::get_input_value('_set', rcube_utils::INPUT_GPC, true);
+ $result = $this->remove_script($script_name);
+
+ if ($result === true) {
+ $this->rc->output->show_message('managesieve.setdeleted', 'confirmation');
+ $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') {
+ $script_name = rcube_utils::get_input_value('_set', rcube_utils::INPUT_GPC, true);
+ $script = $this->sieve->get_script($script_name);
+
+ if (PEAR::isError($script))
+ exit;
+
+ $browser = new rcube_browser;
+
+ // send download headers
+ header("Content-Type: application/octet-stream");
+ header("Content-Length: ".strlen($script));
+
+ if ($browser->ie)
+ header("Content-Type: application/force-download");
+ if ($browser->ie && $browser->ver < 7)
+ $filename = rawurlencode(abbreviate_string($script_name, 55));
+ else if ($browser->ie)
+ $filename = rawurlencode($script_name);
+ else
+ $filename = addcslashes($script_name, '\\"');
+
+ header("Content-Disposition: attachment; filename=\"$filename.txt\"");
+ echo $script;
+ exit;
+ }
+ else if ($action == 'list') {
+ $result = $this->list_rules();
+
+ $this->rc->output->command('managesieve_updatelist', 'list', array('list' => $result));
+ }
+ else if ($action == 'ruleadd') {
+ $rid = rcube_utils::get_input_value('_rid', rcube_utils::INPUT_GPC);
+ $id = $this->genid();
+ $content = $this->rule_div($fid, $id, false);
+
+ $this->rc->output->command('managesieve_rulefill', $content, $id, $rid);
+ }
+ else if ($action == 'actionadd') {
+ $aid = rcube_utils::get_input_value('_aid', rcube_utils::INPUT_GPC);
+ $id = $this->genid();
+ $content = $this->action_div($fid, $id, false);
+
+ $this->rc->output->command('managesieve_actionfill', $content, $id, $aid);
+ }
+
+ $this->rc->output->send();
+ }
+ else if ($this->rc->task == 'mail') {
+ // Initialize the form
+ $rules = rcube_utils::get_input_value('r', rcube_utils::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->send();
+ }
+
+ function save()
+ {
+ // Init plugin and handle managesieve connection
+ $error = $this->start();
+
+ // get request size limits (#1488648)
+ $max_post = max(array(
+ ini_get('max_input_vars'),
+ ini_get('suhosin.request.max_vars'),
+ ini_get('suhosin.post.max_vars'),
+ ));
+ $max_depth = max(array(
+ ini_get('suhosin.request.max_array_depth'),
+ ini_get('suhosin.post.max_array_depth'),
+ ));
+
+ // check request size limit
+ if ($max_post && count($_POST, COUNT_RECURSIVE) >= $max_post) {
+ rcube::raise_error(array(
+ 'code' => 500, 'type' => 'php',
+ 'file' => __FILE__, 'line' => __LINE__,
+ 'message' => "Request size limit exceeded (one of max_input_vars/suhosin.request.max_vars/suhosin.post.max_vars)"
+ ), true, false);
+ $this->rc->output->show_message('managesieve.filtersaveerror', 'error');
+ }
+ // check request depth limits
+ else if ($max_depth && count($_POST['_header']) > $max_depth) {
+ rcube::raise_error(array(
+ 'code' => 500, 'type' => 'php',
+ 'file' => __FILE__, 'line' => __LINE__,
+ 'message' => "Request size limit exceeded (one of suhosin.request.max_array_depth/suhosin.post.max_array_depth)"
+ ), true, false);
+ $this->rc->output->show_message('managesieve.filtersaveerror', 'error');
+ }
+ // filters set add action
+ else if (!empty($_POST['_newset'])) {
+ $name = rcube_utils::get_input_value('_name', rcube_utils::INPUT_POST, true);
+ $copy = rcube_utils::get_input_value('_copy', rcube_utils::INPUT_POST, true);
+ $from = rcube_utils::get_input_value('_from', rcube_utils::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->plugin->gettext('cannotbeempty');
+ }
+ else if (mb_strlen($name) > 128) {
+ $this->errors['name'] = $this->plugin->gettext('nametoolong');
+ }
+ else if (!empty($exceptions) && in_array($name, (array)$exceptions)) {
+ $this->errors['name'] = $this->plugin->gettext('namereserved');
+ }
+ else if (!empty($kolab) && in_array($name_uc, array('MASTER', 'USER', 'MANAGEMENT'))) {
+ $this->errors['name'] = $this->plugin->gettext('namereserved');
+ }
+ else if (in_array($name, $list)) {
+ $this->errors['name'] = $this->plugin->gettext('setexist');
+ }
+ else if ($from == 'file') {
+ // from file
+ if (is_uploaded_file($_FILES['_file']['tmp_name'])) {
+ $file = file_get_contents($_FILES['_file']['tmp_name']);
+ $file = preg_replace('/\r/', '', $file);
+ // for security don't save script directly
+ // check syntax before, like this...
+ $this->sieve->load_script($file);
+ if (!$this->save_script($name)) {
+ $this->errors['file'] = $this->plugin->gettext('setcreateerror');
+ }
+ }
+ else { // upload failed
+ $err = $_FILES['_file']['error'];
+
+ if ($err == UPLOAD_ERR_INI_SIZE || $err == UPLOAD_ERR_FORM_SIZE) {
+ $msg = $this->rc->gettext(array('name' => 'filesizeerror',
+ 'vars' => array('size' =>
+ $this->rc->show_bytes(parse_bytes(ini_get('upload_max_filesize'))))));
+ }
+ else {
+ $this->errors['file'] = $this->plugin->gettext('fileuploaderror');
+ }
+ }
+ }
+ else if (!$this->sieve->copy($name, $from == 'set' ? $copy : '')) {
+ $error = 'managesieve.setcreateerror';
+ }
+
+ 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->command('parent.managesieve_updatelist', 'setadd',
+ array('name' => $name, 'index' => $index));
+ } else if ($msg) {
+ $this->rc->output->command('display_message', $msg, 'error');
+ } else if ($error) {
+ $this->rc->output->show_message($error, 'error');
+ }
+ }
+ // filter add/edit action
+ else if (isset($_POST['_name'])) {
+ $name = trim(rcube_utils::get_input_value('_name', rcube_utils::INPUT_POST, true));
+ $fid = trim(rcube_utils::get_input_value('_fid', rcube_utils::INPUT_POST));
+ $join = trim(rcube_utils::get_input_value('_join', rcube_utils::INPUT_POST));
+
+ // and arrays
+ $headers = rcube_utils::get_input_value('_header', rcube_utils::INPUT_POST);
+ $cust_headers = rcube_utils::get_input_value('_custom_header', rcube_utils::INPUT_POST);
+ $ops = rcube_utils::get_input_value('_rule_op', rcube_utils::INPUT_POST);
+ $sizeops = rcube_utils::get_input_value('_rule_size_op', rcube_utils::INPUT_POST);
+ $sizeitems = rcube_utils::get_input_value('_rule_size_item', rcube_utils::INPUT_POST);
+ $sizetargets = rcube_utils::get_input_value('_rule_size_target', rcube_utils::INPUT_POST);
+ $targets = rcube_utils::get_input_value('_rule_target', rcube_utils::INPUT_POST, true);
+ $mods = rcube_utils::get_input_value('_rule_mod', rcube_utils::INPUT_POST);
+ $mod_types = rcube_utils::get_input_value('_rule_mod_type', rcube_utils::INPUT_POST);
+ $body_trans = rcube_utils::get_input_value('_rule_trans', rcube_utils::INPUT_POST);
+ $body_types = rcube_utils::get_input_value('_rule_trans_type', rcube_utils::INPUT_POST, true);
+ $comparators = rcube_utils::get_input_value('_rule_comp', rcube_utils::INPUT_POST);
+ $indexes = rcube_utils::get_input_value('_rule_index', rcube_utils::INPUT_POST);
+ $lastindexes = rcube_utils::get_input_value('_rule_index_last', rcube_utils::INPUT_POST);
+ $dateheaders = rcube_utils::get_input_value('_rule_date_header', rcube_utils::INPUT_POST);
+ $dateparts = rcube_utils::get_input_value('_rule_date_part', rcube_utils::INPUT_POST);
+ $act_types = rcube_utils::get_input_value('_action_type', rcube_utils::INPUT_POST, true);
+ $mailboxes = rcube_utils::get_input_value('_action_mailbox', rcube_utils::INPUT_POST, true);
+ $act_targets = rcube_utils::get_input_value('_action_target', rcube_utils::INPUT_POST, true);
+ $area_targets = rcube_utils::get_input_value('_action_target_area', rcube_utils::INPUT_POST, true);
+ $reasons = rcube_utils::get_input_value('_action_reason', rcube_utils::INPUT_POST, true);
+ $addresses = rcube_utils::get_input_value('_action_addresses', rcube_utils::INPUT_POST, true);
+ $intervals = rcube_utils::get_input_value('_action_interval', rcube_utils::INPUT_POST);
+ $interval_types = rcube_utils::get_input_value('_action_interval_type', rcube_utils::INPUT_POST);
+ $subject = rcube_utils::get_input_value('_action_subject', rcube_utils::INPUT_POST, true);
+ $flags = rcube_utils::get_input_value('_action_flags', rcube_utils::INPUT_POST);
+ $varnames = rcube_utils::get_input_value('_action_varname', rcube_utils::INPUT_POST);
+ $varvalues = rcube_utils::get_input_value('_action_varvalue', rcube_utils::INPUT_POST);
+ $varmods = rcube_utils::get_input_value('_action_varmods', rcube_utils::INPUT_POST);
+ $notifyaddrs = rcube_utils::get_input_value('_action_notifyaddress', rcube_utils::INPUT_POST);
+ $notifybodies = rcube_utils::get_input_value('_action_notifybody', rcube_utils::INPUT_POST);
+ $notifymessages = rcube_utils::get_input_value('_action_notifymessage', rcube_utils::INPUT_POST);
+ $notifyfrom = rcube_utils::get_input_value('_action_notifyfrom', rcube_utils::INPUT_POST);
+ $notifyimp = rcube_utils::get_input_value('_action_notifyimportance', rcube_utils::INPUT_POST);
+
+ // we need a "hack" for radiobuttons
+ foreach ($sizeitems as $item)
+ $items[] = $item;
+
+ $this->form['disabled'] = $_POST['_disabled'] ? true : false;
+ $this->form['join'] = $join=='allof' ? true : false;
+ $this->form['name'] = $name;
+ $this->form['tests'] = array();
+ $this->form['actions'] = array();
+
+ if ($name == '')
+ $this->errors['name'] = $this->plugin->gettext('cannotbeempty');
+ else {
+ foreach($this->script as $idx => $rule)
+ if($rule['name'] == $name && $idx != $fid) {
+ $this->errors['name'] = $this->plugin->gettext('ruleexist');
+ break;
+ }
+ }
+
+ $i = 0;
+ // rules
+ if ($join == 'any') {
+ $this->form['tests'][0]['test'] = 'true';
+ }
+ else {
+ foreach ($headers as $idx => $header) {
+ // targets are indexed differently (assume form order)
+ $target = $this->strip_value(array_shift($targets), true);
+ $header = $this->strip_value($header);
+ $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->plugin->gettext('cannotbeempty');
+ else if (!preg_match('/^[0-9]+(K|M|G)?$/i', $sizetarget.$sizeitem, $m)) {
+ $this->errors['tests'][$i]['sizetarget'] = $this->plugin->gettext('forbiddenchars');
+ $this->form['tests'][$i]['item'] = $sizeitem;
+ }
+ else
+ $this->form['tests'][$i]['arg'] .= $m[1];
+ }
+ else if ($header == 'currentdate') {
+ $datepart = $this->strip_value($dateparts[$idx]);
+
+ if (preg_match('/^not/', $operator))
+ $this->form['tests'][$i]['not'] = true;
+ $type = preg_replace('/^not/', '', $operator);
+
+ if ($type == 'exists') {
+ $this->errors['tests'][$i]['op'] = true;
+ }
+
+ $this->form['tests'][$i]['test'] = 'currentdate';
+ $this->form['tests'][$i]['type'] = $type;
+ $this->form['tests'][$i]['part'] = $datepart;
+ $this->form['tests'][$i]['arg'] = $target;
+
+ if ($type != 'exists') {
+ if (!count($target)) {
+ $this->errors['tests'][$i]['target'] = $this->plugin->gettext('cannotbeempty');
+ }
+ else if ($type != 'regex' && $type != 'matches') {
+ foreach ($target as $arg) {
+ if (!$this->validate_date_part($datepart, $arg)) {
+ $this->errors['tests'][$i]['target'] = $this->plugin->gettext('invaliddateformat');
+ break;
+ }
+ }
+ }
+ }
+ }
+ else if ($header == 'date') {
+ $datepart = $this->strip_value($dateparts[$idx]);
+ $dateheader = $this->strip_value($dateheaders[$idx]);
+ $index = $this->strip_value($indexes[$idx]);
+ $indexlast = $this->strip_value($lastindexes[$idx]);
+
+ if (preg_match('/^not/', $operator))
+ $this->form['tests'][$i]['not'] = true;
+ $type = preg_replace('/^not/', '', $operator);
+
+ if ($type == 'exists') {
+ $this->errors['tests'][$i]['op'] = true;
+ }
+
+ if (!empty($index) && $mod != 'envelope') {
+ $this->form['tests'][$i]['index'] = intval($index);
+ $this->form['tests'][$i]['last'] = !empty($indexlast);
+ }
+
+ if (empty($dateheader)) {
+ $dateheader = 'Date';
+ }
+ else if (!preg_match('/^[\x21-\x39\x41-\x7E]+$/i', $dateheader)) {
+ $this->errors['tests'][$i]['dateheader'] = $this->plugin->gettext('forbiddenchars');
+ }
+
+ $this->form['tests'][$i]['test'] = 'date';
+ $this->form['tests'][$i]['type'] = $type;
+ $this->form['tests'][$i]['part'] = $datepart;
+ $this->form['tests'][$i]['arg'] = $target;
+ $this->form['tests'][$i]['header'] = $dateheader;
+
+ if ($type != 'exists') {
+ if (!count($target)) {
+ $this->errors['tests'][$i]['target'] = $this->plugin->gettext('cannotbeempty');
+ }
+ else if ($type != 'regex' && $type != 'matches') {
+ foreach ($target as $arg) {
+ if (!$this->validate_date_part($datepart, $arg)) {
+ $this->errors['tests'][$i]['target'] = $this->plugin->gettext('invaliddateformat');
+ break;
+ }
+ }
+ }
+ }
+ }
+ else if ($header == 'body') {
+ $trans = $this->strip_value($body_trans[$idx]);
+ $trans_type = $this->strip_value($body_types[$idx], true);
+
+ if (preg_match('/^not/', $operator))
+ $this->form['tests'][$i]['not'] = true;
+ $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 (empty($target) && $type != 'exists') {
+ $this->errors['tests'][$i]['target'] = $this->plugin->gettext('cannotbeempty');
+ }
+ else if (preg_match('/^(value|count)-/', $type)) {
+ foreach ($target as $target_value) {
+ if (!preg_match('/[0-9]+/', $target_value)) {
+ $this->errors['tests'][$i]['target'] = $this->plugin->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(array_shift($cust_headers));
+ $mod = $this->strip_value($mods[$idx]);
+ $mod_type = $this->strip_value($mod_types[$idx]);
+ $index = $this->strip_value($indexes[$idx]);
+ $indexlast = $this->strip_value($lastindexes[$idx]);
+
+ if (preg_match('/^not/', $operator))
+ $this->form['tests'][$i]['not'] = true;
+ $type = preg_replace('/^not/', '', $operator);
+
+ if (!empty($index) && $mod != 'envelope') {
+ $this->form['tests'][$i]['index'] = intval($index);
+ $this->form['tests'][$i]['last'] = !empty($indexlast);
+ }
+
+ if ($header == '...') {
+ if (!count($headers))
+ $this->errors['tests'][$i]['header'] = $this->plugin->gettext('cannotbeempty');
+ else {
+ foreach ($headers as $hr) {
+ // RFC2822: printable ASCII except colon
+ if (!preg_match('/^[\x21-\x39\x41-\x7E]+$/i', $hr)) {
+ $this->errors['tests'][$i]['header'] = $this->plugin->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';
+ $this->form['tests'][$i]['arg'] = $header == '...' ? $cust_header : $header;
+ }
+ 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]['test'] = $test;
+ $this->form['tests'][$i]['arg1'] = $header;
+ $this->form['tests'][$i]['arg2'] = $target;
+
+ if (empty($target)) {
+ $this->errors['tests'][$i]['target'] = $this->plugin->gettext('cannotbeempty');
+ }
+ else if (preg_match('/^(value|count)-/', $type)) {
+ foreach ($target as $target_value) {
+ if (!preg_match('/[0-9]+/', $target_value)) {
+ $this->errors['tests'][$i]['target'] = $this->plugin->gettext('forbiddenchars');
+ }
+ }
+ }
+
+ if ($mod) {
+ $this->form['tests'][$i]['part'] = $mod_type;
+ }
+ }
+ }
+
+ if ($header != 'size' && $comparator) {
+ if (preg_match('/^(value|count)/', $this->form['tests'][$i]['type']))
+ $comparator = 'i;ascii-numeric';
+
+ $this->form['tests'][$i]['comparator'] = $comparator;
+ }
+
+ $i++;
+ }
+ }
+
+ $i = 0;
+ // actions
+ foreach($act_types as $idx => $type) {
+ $type = $this->strip_value($type);
+ $target = $this->strip_value($act_targets[$idx]);
+
+ switch ($type) {
+
+ case 'fileinto':
+ case 'fileinto_copy':
+ $mailbox = $this->strip_value($mailboxes[$idx], false, false);
+ $this->form['actions'][$i]['target'] = $this->mod_mailbox($mailbox, 'in');
+ if ($type == 'fileinto_copy') {
+ $type = 'fileinto';
+ $this->form['actions'][$i]['copy'] = true;
+ }
+ break;
+
+ case 'reject':
+ case 'ereject':
+ $target = $this->strip_value($area_targets[$idx]);
+ $this->form['actions'][$i]['target'] = str_replace("\r\n", "\n", $target);
+
+ // if ($target == '')
+// $this->errors['actions'][$i]['targetarea'] = $this->plugin->gettext('cannotbeempty');
+ break;
+
+ case 'redirect':
+ case 'redirect_copy':
+ $this->form['actions'][$i]['target'] = $target;
+
+ if ($this->form['actions'][$i]['target'] == '')
+ $this->errors['actions'][$i]['target'] = $this->plugin->gettext('cannotbeempty');
+ else if (!rcube_utils::check_email($this->form['actions'][$i]['target']))
+ $this->errors['actions'][$i]['target'] = $this->plugin->gettext('noemailwarning');
+
+ if ($type == 'redirect_copy') {
+ $type = 'redirect';
+ $this->form['actions'][$i]['copy'] = true;
+ }
+ break;
+
+ case 'addflag':
+ case 'setflag':
+ case 'removeflag':
+ $_target = array();
+ if (empty($flags[$idx])) {
+ $this->errors['actions'][$i]['target'] = $this->plugin->gettext('noflagset');
+ }
+ else {
+ foreach ($flags[$idx] as $flag) {
+ $_target[] = $this->strip_value($flag);
+ }
+ }
+ $this->form['actions'][$i]['target'] = $_target;
+ break;
+
+ case 'vacation':
+ $reason = $this->strip_value($reasons[$idx]);
+ $interval_type = $interval_types[$idx] == 'seconds' ? 'seconds' : 'days';
+ $this->form['actions'][$i]['reason'] = str_replace("\r\n", "\n", $reason);
+ $this->form['actions'][$i]['subject'] = $subject[$idx];
+ $this->form['actions'][$i]['addresses'] = array_shift($addresses);
+ $this->form['actions'][$i][$interval_type] = $intervals[$idx];
+// @TODO: vacation :mime, :from, :handle
+
+ foreach ((array)$this->form['actions'][$i]['addresses'] as $aidx => $address) {
+ if (!rcube_utils::check_email($address)) {
+ $this->errors['actions'][$i]['addresses'] = $this->plugin->gettext('noemailwarning');
+ break;
+ }
+ }
+
+ if ($this->form['actions'][$i]['reason'] == '')
+ $this->errors['actions'][$i]['reason'] = $this->plugin->gettext('cannotbeempty');
+ if ($this->form['actions'][$i][$interval_type] && !preg_match('/^[0-9]+$/', $this->form['actions'][$i][$interval_type]))
+ $this->errors['actions'][$i]['interval'] = $this->plugin->gettext('forbiddenchars');
+ break;
+
+ case 'set':
+ $this->form['actions'][$i]['name'] = $varnames[$idx];
+ $this->form['actions'][$i]['value'] = $varvalues[$idx];
+ foreach ((array)$varmods[$idx] as $v_m) {
+ $this->form['actions'][$i][$v_m] = true;
+ }
+
+ if (empty($varnames[$idx])) {
+ $this->errors['actions'][$i]['name'] = $this->plugin->gettext('cannotbeempty');
+ }
+ else if (!preg_match('/^[0-9a-z_]+$/i', $varnames[$idx])) {
+ $this->errors['actions'][$i]['name'] = $this->plugin->gettext('forbiddenchars');
+ }
+
+ if (!isset($varvalues[$idx]) || $varvalues[$idx] === '') {
+ $this->errors['actions'][$i]['value'] = $this->plugin->gettext('cannotbeempty');
+ }
+ break;
+
+ case 'notify':
+ if (empty($notifyaddrs[$idx])) {
+ $this->errors['actions'][$i]['address'] = $this->plugin->gettext('cannotbeempty');
+ }
+ else if (!rcube_utils::check_email($notifyaddrs[$idx])) {
+ $this->errors['actions'][$i]['address'] = $this->plugin->gettext('noemailwarning');
+ }
+ if (!empty($notifyfrom[$idx]) && !rcube_utils::check_email($notifyfrom[$idx])) {
+ $this->errors['actions'][$i]['from'] = $this->plugin->gettext('noemailwarning');
+ }
+ $this->form['actions'][$i]['address'] = $notifyaddrs[$idx];
+ $this->form['actions'][$i]['body'] = $notifybodies[$idx];
+ $this->form['actions'][$i]['message'] = $notifymessages[$idx];
+ $this->form['actions'][$i]['from'] = $notifyfrom[$idx];
+ $this->form['actions'][$i]['importance'] = $notifyimp[$idx];
+ break;
+ }
+
+ $this->form['actions'][$i]['type'] = $type;
+ $i++;
+ }
+
+ if (!$this->errors && !$error) {
+ // zapis skryptu
+ if (!isset($this->script[$fid])) {
+ $fid = $this->sieve->script->add_rule($this->form);
+ $new = true;
+ } else
+ $fid = $this->sieve->script->update_rule($fid, $this->form);
+
+ if ($fid !== false)
+ $save = $this->save_script();
+
+ if ($save && $fid !== false) {
+ $this->rc->output->show_message('managesieve.filtersaved', 'confirmation');
+ if ($this->rc->task != 'mail') {
+ $this->rc->output->command('parent.managesieve_updatelist',
+ isset($new) ? 'add' : 'update',
+ array(
+ 'name' => $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');
+// $this->rc->output->send();
+ }
+ }
+ }
+
+ $this->send();
+ }
+
+ private function send()
+ {
+ // Handle form action
+ if (isset($_GET['_framed']) || isset($_POST['_framed'])) {
+ if (isset($_GET['_newset']) || isset($_POST['_newset'])) {
+ $this->rc->output->send('managesieve.setedit');
+ }
+ else {
+ $this->rc->output->send('managesieve.filteredit');
+ }
+ } else {
+ $this->rc->output->set_pagetitle($this->plugin->gettext('filters'));
+ $this->rc->output->send('managesieve.managesieve');
+ }
+ }
+
+ // return the filters list as HTML table
+ function filters_list($attrib)
+ {
+ // add id to message list table if not specified
+ if (!strlen($attrib['id']))
+ $attrib['id'] = 'rcmfilterslist';
+
+ // define list of cols to be displayed
+ $a_show_cols = array('name');
+
+ $result = $this->list_rules();
+
+ // create XHTML table
+ $out = $this->rc->table_output($attrib, $result, $a_show_cols, 'id');
+
+ // set client env
+ $this->rc->output->add_gui_object('filterslist', $attrib['id']);
+ $this->rc->output->include_script('list.js');
+
+ // add some labels to client
+ $this->rc->output->add_label('managesieve.filterdeleteconfirm');
+
+ return $out;
+ }
+
+ // return the filters list as <SELECT>
+ function filtersets_list($attrib, $no_env = false)
+ {
+ // add id to message list table if not specified
+ if (!strlen($attrib['id']))
+ $attrib['id'] = 'rcmfiltersetslist';
+
+ $list = $this->list_scripts();
+
+ 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' => $set,
+ 'id' => 'S'.$idx,
+ 'class' => !in_array($set, $this->active) ? 'disabled' : '',
+ );
+ }
+ }
+
+ // create XHTML table
+ $out = $this->rc->table_output($attrib, $result, $a_show_cols, 'id');
+
+ $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);
+ }
+
+ // set client env
+ if (!$no_env) {
+ $this->rc->output->add_gui_object('filtersetslist', $attrib['id']);
+ $this->rc->output->add_label('managesieve.setdeleteconfirm');
+ }
+
+ return $out;
+ }
+
+ function filter_frame($attrib)
+ {
+ if (!$attrib['id'])
+ $attrib['id'] = 'rcmfilterframe';
+
+ $attrib['name'] = $attrib['id'];
+
+ $this->rc->output->set_env('contentframe', $attrib['name']);
+ $this->rc->output->set_env('blankpage', $attrib['src'] ?
+ $this->rc->output->abs_url($attrib['src']) : 'program/resources/blank.gif');
+
+ return $this->rc->output->frame($attrib);
+ }
+
+ function filterset_form($attrib)
+ {
+ if (!$attrib['id'])
+ $attrib['id'] = 'rcmfiltersetform';
+
+ $out = '<form name="filtersetform" action="./" method="post" enctype="multipart/form-data">'."\n";
+
+ $hiddenfields = new html_hiddenfield(array('name' => '_task', 'value' => $this->rc->task));
+ $hiddenfields->add(array('name' => '_action', 'value' => 'plugin.managesieve-save'));
+ $hiddenfields->add(array('name' => '_framed', 'value' => ($_POST['_framed'] || $_GET['_framed'] ? 1 : 0)));
+ $hiddenfields->add(array('name' => '_newset', 'value' => 1));
+
+ $out .= $hiddenfields->show();
+
+ $name = rcube_utils::get_input_value('_name', rcube_utils::INPUT_POST);
+ $copy = rcube_utils::get_input_value('_copy', rcube_utils::INPUT_POST);
+ $selected = rcube_utils::get_input_value('_from', rcube_utils::INPUT_POST);
+
+ // filter set name input
+ $input_name = new html_inputfield(array('name' => '_name', 'id' => '_name', 'size' => 30,
+ 'class' => ($this->errors['name'] ? 'error' : '')));
+
+ $out .= sprintf('<label for="%s"><b>%s:</b></label> %s<br /><br />',
+ '_name', rcube::Q($this->plugin->gettext('filtersetname')), $input_name->show($name));
+
+ $out .="\n<fieldset class=\"itemlist\"><legend>" . $this->plugin->gettext('filters') . ":</legend>\n";
+ $out .= '<input type="radio" id="from_none" name="_from" value="none"'
+ .(!$selected || $selected=='none' ? ' checked="checked"' : '').'></input>';
+ $out .= sprintf('<label for="%s">%s</label> ', 'from_none', rcube::Q($this->plugin->gettext('none')));
+
+ // filters set list
+ $list = $this->list_scripts();
+ $select = new html_select(array('name' => '_copy', 'id' => '_copy'));
+
+ if (is_array($list)) {
+ asort($list, SORT_LOCALE_STRING);
+
+ 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 .= sprintf('<label for="%s">%s:</label> ', 'from_set', rcube::Q($this->plugin->gettext('fromset')));
+ $out .= $select->show($copy);
+ }
+
+ // script upload box
+ $upload = new html_inputfield(array('name' => '_file', 'id' => '_file', 'size' => 30,
+ '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 .= sprintf('<label for="%s">%s:</label> ', 'from_file', rcube::Q($this->plugin->gettext('fromfile')));
+ $out .= $upload->show();
+ $out .= '</fieldset>';
+
+ $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;
+ }
+
+
+ function filter_form($attrib)
+ {
+ if (!$attrib['id'])
+ $attrib['id'] = 'rcmfilterform';
+
+ $fid = rcube_utils::get_input_value('_fid', rcube_utils::INPUT_GPC);
+ $scr = isset($this->form) ? $this->form : $this->script[$fid];
+
+ $hiddenfields = new html_hiddenfield(array('name' => '_task', 'value' => $this->rc->task));
+ $hiddenfields->add(array('name' => '_action', 'value' => 'plugin.managesieve-save'));
+ $hiddenfields->add(array('name' => '_framed', 'value' => ($_POST['_framed'] || $_GET['_framed'] ? 1 : 0)));
+ $hiddenfields->add(array('name' => '_fid', 'value' => $fid));
+
+ $out = '<form name="filterform" action="./" method="post">'."\n";
+ $out .= $hiddenfields->show();
+
+ // 'any' flag
+ if (sizeof($scr['tests']) == 1 && $scr['tests'][0]['test'] == 'true' && !$scr['tests'][0]['not'])
+ $any = true;
+
+ // filter name input
+ $field_id = '_name';
+ $input_name = new html_inputfield(array('name' => '_name', 'id' => $field_id, 'size' => 30,
+ 'class' => ($this->errors['name'] ? 'error' : '')));
+
+ if ($this->errors['name'])
+ $this->add_tip($field_id, $this->errors['name'], true);
+
+ if (isset($scr))
+ $input_name = $input_name->show($scr['name']);
+ else
+ $input_name = $input_name->show();
+
+ $out .= sprintf("\n<label for=\"%s\"><b>%s:</b></label> %s\n",
+ $field_id, rcube::Q($this->plugin->gettext('filtername')), $input_name);
+
+ // filter set selector
+ if ($this->rc->task == 'mail') {
+ $out .= sprintf("\n&nbsp;<label for=\"%s\"><b>%s:</b></label> %s\n",
+ $field_id, rcube::Q($this->plugin->gettext('filterset')),
+ $this->filtersets_list(array('id' => 'sievescriptname'), true));
+ }
+
+ $out .= '<br /><br /><fieldset><legend>' . rcube::Q($this->plugin->gettext('messagesrules')) . "</legend>\n";
+
+ // any, allof, anyof radio buttons
+ $field_id = '_allof';
+ $input_join = new html_radiobutton(array('name' => '_join', 'id' => $field_id, 'value' => 'allof',
+ 'onclick' => 'rule_join_radio(\'allof\')', 'class' => 'radio'));
+
+ if (isset($scr) && !$any)
+ $input_join = $input_join->show($scr['join'] ? 'allof' : '');
+ else
+ $input_join = $input_join->show();
+
+ $out .= sprintf("%s<label for=\"%s\">%s</label>&nbsp;\n",
+ $input_join, $field_id, rcube::Q($this->plugin->gettext('filterallof')));
+
+ $field_id = '_anyof';
+ $input_join = new html_radiobutton(array('name' => '_join', 'id' => $field_id, 'value' => 'anyof',
+ 'onclick' => 'rule_join_radio(\'anyof\')', 'class' => 'radio'));
+
+ if (isset($scr) && !$any)
+ $input_join = $input_join->show($scr['join'] ? '' : 'anyof');
+ else
+ $input_join = $input_join->show('anyof'); // default
+
+ $out .= sprintf("%s<label for=\"%s\">%s</label>\n",
+ $input_join, $field_id, rcube::Q($this->plugin->gettext('filteranyof')));
+
+ $field_id = '_any';
+ $input_join = new html_radiobutton(array('name' => '_join', 'id' => $field_id, 'value' => 'any',
+ 'onclick' => 'rule_join_radio(\'any\')', 'class' => 'radio'));
+
+ $input_join = $input_join->show($any ? 'any' : '');
+
+ $out .= sprintf("%s<label for=\"%s\">%s</label>\n",
+ $input_join, $field_id, rcube::Q($this->plugin->gettext('filterany')));
+
+ $rows_num = isset($scr) ? sizeof($scr['tests']) : 1;
+
+ $out .= '<div id="rules"'.($any ? ' style="display: none"' : '').'>';
+ for ($x=0; $x<$rows_num; $x++)
+ $out .= $this->rule_div($fid, $x);
+ $out .= "</div>\n";
+
+ $out .= "</fieldset>\n";
+
+ // actions
+ $out .= '<fieldset><legend>' . rcube::Q($this->plugin->gettext('messagesactions')) . "</legend>\n";
+
+ $rows_num = isset($scr) ? sizeof($scr['actions']) : 1;
+
+ $out .= '<div id="actions">';
+ for ($x=0; $x<$rows_num; $x++)
+ $out .= $this->action_div($fid, $x);
+ $out .= "</div>\n";
+
+ $out .= "</fieldset>\n";
+
+ $this->print_tips();
+
+ if ($scr['disabled']) {
+ $this->rc->output->set_env('rule_disabled', true);
+ }
+ $this->rc->output->add_label(
+ 'managesieve.ruledeleteconfirm',
+ 'managesieve.actiondeleteconfirm'
+ );
+ $this->rc->output->add_gui_object('sieveform', 'filterform');
+
+ return $out;
+ }
+
+ function rule_div($fid, $id, $div=true)
+ {
+ $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']);
+
+ // 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(rcube::Q($this->plugin->gettext($name)), Q($val));
+ $select_header->add(rcube::Q($this->plugin->gettext('...')), '...');
+ if (in_array('body', $this->exts))
+ $select_header->add(rcube::Q($this->plugin->gettext('body')), 'body');
+ $select_header->add(rcube::Q($this->plugin->gettext('size')), 'size');
+ if (in_array('date', $this->exts)) {
+ $select_header->add(rcube::Q($this->plugin->gettext('datetest')), 'date');
+ $select_header->add(rcube::Q($this->plugin->gettext('currdate')), 'currentdate');
+ }
+
+ if (isset($rule['test'])) {
+ if (in_array($rule['test'], array('header', 'address', 'envelope'))
+ && !is_array($rule['arg1']) && in_array($rule['arg1'], $this->headers)
+ ) {
+ $test = $rule['arg1'];
+ }
+ else if ($rule['test'] == 'exists'
+ && !is_array($rule['arg']) && in_array($rule['arg'], $this->headers)
+ ) {
+ $test = $rule['arg'];
+ }
+ else if (in_array($rule['test'], array('size', 'body', 'date', 'currentdate'))) {
+ $test = $rule['test'];
+ }
+ else if ($rule['test'] != 'true') {
+ $test = '...';
+ }
+ }
+
+ $aout = $select_header->show($test);
+
+ // custom headers input
+ if (isset($rule['test']) && in_array($rule['test'], array('header', 'address', 'envelope'))) {
+ $custom = (array) $rule['arg1'];
+ if (count($custom) == 1 && isset($this->headers[strtolower($custom[0])])) {
+ unset($custom);
+ }
+ }
+ else if (isset($rule['test']) && $rule['test'] == 'exists') {
+ $custom = (array) $rule['arg'];
+ if (count($custom) == 1 && isset($this->headers[strtolower($custom[0])])) {
+ unset($custom);
+ }
+ }
+
+ $tout = $this->list_input($id, 'custom_header', $custom, isset($custom),
+ $this->error_class($id, 'test', 'header', 'custom_header'), 15) . "\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'),
+ 'class' => 'operator_selector',
+ 'onchange' => 'rule_op_select(this, '.$id.')'));
+ $select_op->add(rcube::Q($this->plugin->gettext('filtercontains')), 'contains');
+ $select_op->add(rcube::Q($this->plugin->gettext('filternotcontains')), 'notcontains');
+ $select_op->add(rcube::Q($this->plugin->gettext('filteris')), 'is');
+ $select_op->add(rcube::Q($this->plugin->gettext('filterisnot')), 'notis');
+ $select_op->add(rcube::Q($this->plugin->gettext('filterexists')), 'exists');
+ $select_op->add(rcube::Q($this->plugin->gettext('filternotexists')), 'notexists');
+ $select_op->add(rcube::Q($this->plugin->gettext('filtermatches')), 'matches');
+ $select_op->add(rcube::Q($this->plugin->gettext('filternotmatches')), 'notmatches');
+ if (in_array('regex', $this->exts)) {
+ $select_op->add(rcube::Q($this->plugin->gettext('filterregex')), 'regex');
+ $select_op->add(rcube::Q($this->plugin->gettext('filternotregex')), 'notregex');
+ }
+ if (in_array('relational', $this->exts)) {
+ $select_op->add(rcube::Q($this->plugin->gettext('countisgreaterthan')), 'count-gt');
+ $select_op->add(rcube::Q($this->plugin->gettext('countisgreaterthanequal')), 'count-ge');
+ $select_op->add(rcube::Q($this->plugin->gettext('countislessthan')), 'count-lt');
+ $select_op->add(rcube::Q($this->plugin->gettext('countislessthanequal')), 'count-le');
+ $select_op->add(rcube::Q($this->plugin->gettext('countequals')), 'count-eq');
+ $select_op->add(rcube::Q($this->plugin->gettext('countnotequals')), 'count-ne');
+ $select_op->add(rcube::Q($this->plugin->gettext('valueisgreaterthan')), 'value-gt');
+ $select_op->add(rcube::Q($this->plugin->gettext('valueisgreaterthanequal')), 'value-ge');
+ $select_op->add(rcube::Q($this->plugin->gettext('valueislessthan')), 'value-lt');
+ $select_op->add(rcube::Q($this->plugin->gettext('valueislessthanequal')), 'value-le');
+ $select_op->add(rcube::Q($this->plugin->gettext('valueequals')), 'value-eq');
+ $select_op->add(rcube::Q($this->plugin->gettext('valuenotequals')), 'value-ne');
+ }
+
+ // (current)date part select
+ if (in_array('date', $this->exts) || in_array('currentdate', $this->exts)) {
+ $date_parts = array('date', 'iso8601', 'std11', 'julian', 'time',
+ 'year', 'month', 'day', 'hour', 'minute', 'second', 'weekday', 'zone');
+ $select_dp = new html_select(array('name' => "_rule_date_part[]", 'id' => 'rule_date_part'.$id,
+ 'style' => $rule['test'] == 'currentdate' || $rule['test'] == 'date' ? '' : 'display:none',
+ 'class' => 'datepart_selector',
+ ));
+
+ foreach ($date_parts as $part) {
+ $select_dp->add(rcube::Q($this->plugin->gettext($part)), $part);
+ }
+
+ $tout .= $select_dp->show($rule['test'] == 'currentdate' || $rule['test'] == 'date' ? $rule['part'] : '');
+ }
+
+ // target(s) input
+ if (in_array($rule['test'], array('header', 'address', 'envelope'))) {
+ $test = ($rule['not'] ? 'not' : '').($rule['type'] ? $rule['type'] : 'is');
+ $target = $rule['arg2'];
+ }
+ else if (in_array($rule['test'], array('body', 'date', 'currentdate'))) {
+ $test = ($rule['not'] ? 'not' : '').($rule['type'] ? $rule['type'] : 'is');
+ $target = $rule['arg'];
+ }
+ else if ($rule['test'] == 'size') {
+ $test = '';
+ $target = '';
+ if (preg_match('/^([0-9]+)(K|M|G)?$/', $rule['arg'], $matches)) {
+ $sizetarget = $matches[1];
+ $sizeitem = $matches[2];
+ }
+ else {
+ $sizetarget = $rule['arg'];
+ $sizeitem = $rule['item'];
+ }
+ }
+ else {
+ $test = ($rule['not'] ? 'not' : '').$rule['test'];
+ $target = '';
+ }
+
+ $tout .= $select_op->show($test);
+ $tout .= $this->list_input($id, 'rule_target', $target,
+ $rule['test'] != 'size' && $rule['test'] != 'exists',
+ $this->error_class($id, 'test', 'target', 'rule_target')) . "\n";
+
+ $select_size_op = new html_select(array('name' => "_rule_size_op[]", 'id' => 'rule_size_op'.$id));
+ $select_size_op->add(rcube::Q($this->plugin->gettext('filterover')), 'over');
+ $select_size_op->add(rcube::Q($this->plugin->gettext('filterunder')), 'under');
+
+ $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') .' />
+ <label><input type="radio" name="_rule_size_item['.$id.']" value=""'
+ . (!$sizeitem ? ' checked="checked"' : '') .' class="radio" />'.$this->rc->gettext('B').'</label>
+ <label><input type="radio" name="_rule_size_item['.$id.']" value="K"'
+ . ($sizeitem=='K' ? ' checked="checked"' : '') .' class="radio" />'.$this->rc->gettext('KB').'</label>
+ <label><input type="radio" name="_rule_size_item['.$id.']" value="M"'
+ . ($sizeitem=='M' ? ' checked="checked"' : '') .' class="radio" />'.$this->rc->gettext('MB').'</label>
+ <label><input type="radio" name="_rule_size_item['.$id.']" value="G"'
+ . ($sizeitem=='G' ? ' checked="checked"' : '') .' class="radio" />'.$this->rc->gettext('GB').'</label>';
+ $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(rcube::Q($this->plugin->gettext('none')), '');
+ $select_mod->add(rcube::Q($this->plugin->gettext('address')), 'address');
+ if (in_array('envelope', $this->exts))
+ $select_mod->add(rcube::Q($this->plugin->gettext('envelope')), 'envelope');
+
+ $select_type = new html_select(array('name' => "_rule_mod_type[]", 'id' => 'rule_mod_type'.$id));
+ $select_type->add(rcube::Q($this->plugin->gettext('allparts')), 'all');
+ $select_type->add(rcube::Q($this->plugin->gettext('domain')), 'domain');
+ $select_type->add(rcube::Q($this->plugin->gettext('localpart')), 'localpart');
+ if (in_array('subaddress', $this->exts)) {
+ $select_type->add(rcube::Q($this->plugin->gettext('user')), 'user');
+ $select_type->add(rcube::Q($this->plugin->gettext('detail')), 'detail');
+ }
+
+ $need_mod = $rule['test'] != 'size' && $rule['test'] != 'body';
+ $mout = '<div id="rule_mod' .$id. '" class="adv"' . (!$need_mod ? ' style="display:none"' : '') . '>';
+ $mout .= ' <span class="label">' . rcube::Q($this->plugin->gettext('modifier')) . ' </span>';
+ $mout .= $select_mod->show($rule['test']);
+ $mout .= ' <span id="rule_mod_type' . $id . '"';
+ $mout .= ' style="display:' . (in_array($rule['test'], array('address', 'envelope')) ? 'inline' : 'none') .'">';
+ $mout .= rcube::Q($this->plugin->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(rcube::Q($this->plugin->gettext('text')), 'text');
+ $select_mod->add(rcube::Q($this->plugin->gettext('undecoded')), 'raw');
+ $select_mod->add(rcube::Q($this->plugin->gettext('contenttype')), 'content');
+
+ $mout .= '<div id="rule_trans' .$id. '" class="adv"' . ($rule['test'] != 'body' ? ' style="display:none"' : '') . '>';
+ $mout .= '<span class="label">' . rcube::Q($this->plugin->gettext('modifier')) . '</span>';
+ $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"' . ($rule['part'] != 'content' ? ' style="display:none"' : '')
+ . $this->error_class($id, 'test', 'part', 'rule_trans_type') .' />';
+ $mout .= '</div>';
+
+ // Advanced modifiers (body transformations)
+ $select_comp = new html_select(array('name' => "_rule_comp[]", 'id' => 'rule_comp_op'.$id));
+ $select_comp->add(rcube::Q($this->plugin->gettext('default')), '');
+ $select_comp->add(rcube::Q($this->plugin->gettext('octet')), 'i;octet');
+ $select_comp->add(rcube::Q($this->plugin->gettext('asciicasemap')), 'i;ascii-casemap');
+ if (in_array('comparator-i;ascii-numeric', $this->exts)) {
+ $select_comp->add(rcube::Q($this->plugin->gettext('asciinumeric')), 'i;ascii-numeric');
+ }
+
+ // Comparators
+ $mout .= '<div id="rule_comp' .$id. '" class="adv"' . ($rule['test'] == 'size' ? ' style="display:none"' : '') . '>';
+ $mout .= '<span class="label">' . rcube::Q($this->plugin->gettext('comparator')) . '</span>';
+ $mout .= $select_comp->show($rule['comparator']);
+ $mout .= '</div>';
+
+ // Date header
+ if (in_array('date', $this->exts)) {
+ $mout .= '<div id="rule_date_header_div' .$id. '" class="adv"'. ($rule['test'] != 'date' ? ' style="display:none"' : '') .'>';
+ $mout .= '<span class="label">' . rcube::Q($this->plugin->gettext('dateheader')) . '</span>';
+ $mout .= '<input type="text" name="_rule_date_header[]" id="rule_date_header'.$id
+ . '" value="'. Q($rule['test'] == 'date' ? $rule['header'] : '')
+ . '" size="15"' . $this->error_class($id, 'test', 'dateheader', 'rule_date_header') .' />';
+ $mout .= '</div>';
+ }
+
+ // Index
+ if (in_array('index', $this->exts)) {
+ $need_index = in_array($rule['test'], array('header', ', address', 'date'));
+ $mout .= '<div id="rule_index_div' .$id. '" class="adv"'. (!$need_index ? ' style="display:none"' : '') .'>';
+ $mout .= '<span class="label">' . rcube::Q($this->plugin->gettext('index')) . '</span>';
+ $mout .= '<input type="text" name="_rule_index[]" id="rule_index'.$id
+ . '" value="'. ($rule['index'] ? intval($rule['index']) : '')
+ . '" size="3"' . $this->error_class($id, 'test', 'index', 'rule_index') .' />';
+ $mout .= '&nbsp;<input type="checkbox" name="_rule_index_last[]" id="rule_index_last'.$id
+ . '" value="1"' . (!empty($rule['last']) ? ' checked="checked"' : '') . ' />'
+ . '<label for="rule_index_last'.$id.'">'.rcube::Q($this->plugin->gettext('indexlast')).'</label>';
+ $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="'. rcube::Q($this->plugin->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 .= '<a href="#" id="ruleadd' . $id .'" title="'. rcube::Q($this->plugin->gettext('add')). '"
+ onclick="rcmail.managesieve_ruleadd(' . $id .')" class="button add"></a>';
+ $out .= '<a href="#" id="ruledel' . $id .'" title="'. rcube::Q($this->plugin->gettext('del')). '"
+ onclick="rcmail.managesieve_ruledel(' . $id .')" class="button del' . ($rows_num<2 ? ' disabled' : '') .'"></a>';
+ $out .= '</td>';
+ $out .= '</tr></table>';
+
+ $out .= $div ? "</div>\n" : '';
+
+ return $out;
+ }
+
+ function action_div($fid, $id, $div=true)
+ {
+ $action = isset($this->form) ? $this->form['actions'][$id] : $this->script[$fid]['actions'][$id];
+ $rows_num = isset($this->form) ? sizeof($this->form['actions']) : sizeof($this->script[$fid]['actions']);
+
+ $out = $div ? '<div class="actionrow" id="actionrow' .$id .'">'."\n" : '';
+
+ $out .= '<table><tr><td class="rowactions">';
+
+ // action select
+ $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(rcube::Q($this->plugin->gettext('messagemoveto')), 'fileinto');
+ if (in_array('fileinto', $this->exts) && in_array('copy', $this->exts))
+ $select_action->add(rcube::Q($this->plugin->gettext('messagecopyto')), 'fileinto_copy');
+ $select_action->add(rcube::Q($this->plugin->gettext('messageredirect')), 'redirect');
+ if (in_array('copy', $this->exts))
+ $select_action->add(rcube::Q($this->plugin->gettext('messagesendcopy')), 'redirect_copy');
+ if (in_array('reject', $this->exts))
+ $select_action->add(rcube::Q($this->plugin->gettext('messagediscard')), 'reject');
+ else if (in_array('ereject', $this->exts))
+ $select_action->add(rcube::Q($this->plugin->gettext('messagediscard')), 'ereject');
+ if (in_array('vacation', $this->exts))
+ $select_action->add(rcube::Q($this->plugin->gettext('messagereply')), 'vacation');
+ $select_action->add(rcube::Q($this->plugin->gettext('messagedelete')), 'discard');
+ if (in_array('imapflags', $this->exts) || in_array('imap4flags', $this->exts)) {
+ $select_action->add(rcube::Q($this->plugin->gettext('setflags')), 'setflag');
+ $select_action->add(rcube::Q($this->plugin->gettext('addflags')), 'addflag');
+ $select_action->add(rcube::Q($this->plugin->gettext('removeflags')), 'removeflag');
+ }
+ if (in_array('variables', $this->exts)) {
+ $select_action->add(rcube::Q($this->plugin->gettext('setvariable')), 'set');
+ }
+ if (in_array('enotify', $this->exts) || in_array('notify', $this->exts)) {
+ $select_action->add(rcube::Q($this->plugin->gettext('notify')), 'notify');
+ }
+ $select_action->add(rcube::Q($this->plugin->gettext('rulestop')), 'stop');
+
+ $select_type = $action['type'];
+ if (in_array($action['type'], array('fileinto', 'redirect')) && $action['copy']) {
+ $select_type .= '_copy';
+ }
+
+ $out .= $select_action->show($select_type);
+ $out .= '</td>';
+
+ // actions target inputs
+ $out .= '<td class="rowtargets">';
+ // shared targets
+ $out .= '<input type="text" name="_action_target['.$id.']" id="action_target' .$id. '" '
+ .'value="' .($action['type']=='redirect' ? rcube::Q($action['target'], 'strict', false) : ''). '" size="35" '
+ .'style="display:' .($action['type']=='redirect' ? 'inline' : 'none') .'" '
+ . $this->error_class($id, 'action', 'target', 'action_target') .' />';
+ $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')) ? rcube::Q($action['target'], 'strict', false) : '')
+ . "</textarea>\n";
+
+ // vacation
+ $vsec = in_array('vacation-seconds', $this->exts);
+ $out .= '<div id="action_vacation' .$id.'" style="display:' .($action['type']=='vacation' ? 'inline' : 'none') .'">';
+ $out .= '<span class="label">'. rcube::Q($this->plugin->gettext('vacationreason')) .'</span><br />'
+ .'<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">' .rcube::Q($this->plugin->gettext('vacationsubject')) . '</span><br />'
+ .'<input type="text" name="_action_subject['.$id.']" id="action_subject'.$id.'" '
+ .'value="' . (is_array($action['subject']) ? rcube::Q(implode(', ', $action['subject']), 'strict', false) : $action['subject']) . '" size="35" '
+ . $this->error_class($id, 'action', 'subject', 'action_subject') .' />';
+ $out .= '<br /><span class="label">' .rcube::Q($this->plugin->gettext('vacationaddr')) . '</span><br />'
+ . $this->list_input($id, 'action_addresses', $action['addresses'], true,
+ $this->error_class($id, 'action', 'addresses', 'action_addresses'), 30);
+ $out .= '<br /><span class="label">' . rcube::Q($this->plugin->gettext($vsec ? 'vacationinterval' : 'vacationdays')) . '</span><br />'
+ .'<input type="text" name="_action_interval['.$id.']" id="action_interval'.$id.'" '
+ .'value="' .rcube::Q(isset($action['seconds']) ? $action['seconds'] : $action['days'], 'strict', false) . '" size="2" '
+ . $this->error_class($id, 'action', 'interval', 'action_interval') .' />';
+ if ($vsec) {
+ $out .= '&nbsp;<label><input type="radio" name="_action_interval_type['.$id.']" value="days"'
+ . (!isset($action['seconds']) ? ' checked="checked"' : '') .' class="radio" />'.$this->plugin->gettext('days').'</label>'
+ . '&nbsp;<label><input type="radio" name="_action_interval_type['.$id.']" value="seconds"'
+ . (isset($action['seconds']) ? ' checked="checked"' : '') .' class="radio" />'.$this->plugin->gettext('seconds').'</label>';
+ }
+ $out .= '</div>';
+
+ // flags
+ $flags = array(
+ 'read' => '\\Seen',
+ 'answered' => '\\Answered',
+ 'flagged' => '\\Flagged',
+ 'deleted' => '\\Deleted',
+ 'draft' => '\\Draft',
+ );
+ $flags_target = (array)$action['target'];
+
+ $out .= '<div id="action_flags' .$id.'" style="display:'
+ . (preg_match('/^(set|add|remove)flag$/', $action['type']) ? 'inline' : 'none') . '"'
+ . $this->error_class($id, 'action', 'flags', 'action_flags') . '>';
+ foreach ($flags as $fidx => $flag) {
+ $out .= '<input type="checkbox" name="_action_flags[' .$id .'][]" value="' . $flag . '"'
+ . (in_array_nocase($flag, $flags_target) ? 'checked="checked"' : '') . ' />'
+ . rcube::Q($this->plugin->gettext('flag'.$fidx)) .'<br>';
+ }
+ $out .= '</div>';
+
+ // set variable
+ $set_modifiers = array(
+ 'lower',
+ 'upper',
+ 'lowerfirst',
+ 'upperfirst',
+ 'quotewildcard',
+ 'length'
+ );
+
+ $out .= '<div id="action_set' .$id.'" style="display:' .($action['type']=='set' ? 'inline' : 'none') .'">';
+ $out .= '<span class="label">' .rcube::Q($this->plugin->gettext('setvarname')) . '</span><br />'
+ .'<input type="text" name="_action_varname['.$id.']" id="action_varname'.$id.'" '
+ .'value="' . rcube::Q($action['name']) . '" size="35" '
+ . $this->error_class($id, 'action', 'name', 'action_varname') .' />';
+ $out .= '<br /><span class="label">' .rcube::Q($this->plugin->gettext('setvarvalue')) . '</span><br />'
+ .'<input type="text" name="_action_varvalue['.$id.']" id="action_varvalue'.$id.'" '
+ .'value="' . rcube::Q($action['value']) . '" size="35" '
+ . $this->error_class($id, 'action', 'value', 'action_varvalue') .' />';
+ $out .= '<br /><span class="label">' .rcube::Q($this->plugin->gettext('setvarmodifiers')) . '</span><br />';
+ foreach ($set_modifiers as $s_m) {
+ $s_m_id = 'action_varmods' . $id . $s_m;
+ $out .= sprintf('<input type="checkbox" name="_action_varmods[%s][]" value="%s" id="%s"%s />%s<br>',
+ $id, $s_m, $s_m_id,
+ (array_key_exists($s_m, (array)$action) && $action[$s_m] ? ' checked="checked"' : ''),
+ rcube::Q($this->plugin->gettext('var' . $s_m)));
+ }
+ $out .= '</div>';
+
+ // notify
+ // skip :options tag - not used by the mailto method
+ $out .= '<div id="action_notify' .$id.'" style="display:' .($action['type']=='notify' ? 'inline' : 'none') .'">';
+ $out .= '<span class="label">' .rcube::Q($this->plugin->gettext('notifyaddress')) . '</span><br />'
+ .'<input type="text" name="_action_notifyaddress['.$id.']" id="action_notifyaddress'.$id.'" '
+ .'value="' . rcube::Q($action['address']) . '" size="35" '
+ . $this->error_class($id, 'action', 'address', 'action_notifyaddress') .' />';
+ $out .= '<br /><span class="label">'. rcube::Q($this->plugin->gettext('notifybody')) .'</span><br />'
+ .'<textarea name="_action_notifybody['.$id.']" id="action_notifybody' .$id. '" '
+ .'rows="3" cols="35" '. $this->error_class($id, 'action', 'method', 'action_notifybody') . '>'
+ . rcube::Q($action['body'], 'strict', false) . "</textarea>\n";
+ $out .= '<br /><span class="label">' .rcube::Q($this->plugin->gettext('notifysubject')) . '</span><br />'
+ .'<input type="text" name="_action_notifymessage['.$id.']" id="action_notifymessage'.$id.'" '
+ .'value="' . rcube::Q($action['message']) . '" size="35" '
+ . $this->error_class($id, 'action', 'message', 'action_notifymessage') .' />';
+ $out .= '<br /><span class="label">' .rcube::Q($this->plugin->gettext('notifyfrom')) . '</span><br />'
+ .'<input type="text" name="_action_notifyfrom['.$id.']" id="action_notifyfrom'.$id.'" '
+ .'value="' . rcube::Q($action['from']) . '" size="35" '
+ . $this->error_class($id, 'action', 'from', 'action_notifyfrom') .' />';
+ $importance_options = array(
+ 3 => 'notifyimportancelow',
+ 2 => 'notifyimportancenormal',
+ 1 => 'notifyimportancehigh'
+ );
+ $select_importance = new html_select(array(
+ 'name' => '_action_notifyimportance[' . $id . ']',
+ 'id' => '_action_notifyimportance' . $id,
+ 'class' => $this->error_class($id, 'action', 'importance', 'action_notifyimportance')));
+ foreach ($importance_options as $io_v => $io_n) {
+ $select_importance->add(rcube::Q($this->plugin->gettext($io_n)), $io_v);
+ }
+ $out .= '<br /><span class="label">' . rcube::Q($this->plugin->gettext('notifyimportance')) . '</span><br />';
+ $out .= $select_importance->show($action['importance'] ? $action['importance'] : 2);
+ $out .= '</div>';
+
+ // mailbox select
+ if ($action['type'] == 'fileinto')
+ $mailbox = $this->mod_mailbox($action['target'], 'out');
+ else
+ $mailbox = '';
+
+ $select = $this->rc->folder_selector(array(
+ '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 .= '<a href="#" id="actionadd' . $id .'" title="'. rcube::Q($this->plugin->gettext('add')). '"
+ onclick="rcmail.managesieve_actionadd(' . $id .')" class="button add"></a>';
+ $out .= '<a href="#" id="actiondel' . $id .'" title="'. rcube::Q($this->plugin->gettext('del')). '"
+ onclick="rcmail.managesieve_actiondel(' . $id .')" class="button del' . ($rows_num<2 ? ' disabled' : '') .'"></a>';
+ $out .= '</td>';
+
+ $out .= '</tr></table>';
+
+ $out .= $div ? "</div>\n" : '';
+
+ return $out;
+ }
+
+ private function genid()
+ {
+ return preg_replace('/[^0-9]/', '', microtime(true));
+ }
+
+ private function strip_value($str, $allow_html = false, $trim = true)
+ {
+ if (is_array($str)) {
+ foreach ($str as $idx => $val) {
+ $val = $this->strip_value($val, $allow_html, $trim);
+
+ if ($val === '') {
+ unset($str[$idx]);
+ }
+ }
+
+ return $str;
+ }
+
+ if (!$allow_html) {
+ $str = strip_tags($str);
+ }
+
+ return $trim ? trim($str) : $str;
+ }
+
+ private function error_class($id, $type, $target, $elem_prefix='')
+ {
+ // TODO: tooltips
+ if (($type == 'test' && ($str = $this->errors['tests'][$id][$target])) ||
+ ($type == 'action' && ($str = $this->errors['actions'][$id][$target]))
+ ) {
+ $this->add_tip($elem_prefix.$id, $str, true);
+ return ' class="error"';
+ }
+
+ return '';
+ }
+
+ private function add_tip($id, $str, $error=false)
+ {
+ if ($error)
+ $str = html::span('sieve error', $str);
+
+ $this->tips[] = array($id, $str);
+ }
+
+ private function print_tips()
+ {
+ if (empty($this->tips))
+ return;
+
+ $script = rcmail_output::JS_OBJECT_NAME.'.managesieve_tip_register('.json_encode($this->tips).');';
+ $this->rc->output->add_script($script, 'foot');
+ }
+
+ private function list_input($id, $name, $value, $enabled, $class, $size=null)
+ {
+ $value = (array) $value;
+ $value = array_map(array('rcube', 'Q'), $value);
+ $value = implode("\n", $value);
+
+ return '<textarea data-type="list" name="_' . $name . '['.$id.']" id="' . $name.$id . '"'
+ . ($enabled ? '' : ' disabled="disabled"')
+ . ($size ? ' data-size="'.$size.'"' : '')
+ . $class
+ . ' style="display:none">' . $value . '</textarea>';
+ }
+
+ /**
+ * Validate input for date part elements
+ */
+ private function validate_date_part($type, $value)
+ {
+ // we do simple validation of date/part format
+ switch ($type) {
+ case 'date': // yyyy-mm-dd
+ return preg_match('/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/', $value);
+ case 'iso8601':
+ return preg_match('/^[0-9: .,ZWT+-]+$/', $value);
+ case 'std11':
+ return preg_match('/^((Sun|Mon|Tue|Wed|Thu|Fri|Sat),\s+)?[0-9]{1,2}\s+'
+ . '(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s+[0-9]{2,4}\s+'
+ . '[0-9]{2}:[0-9]{2}(:[0-9]{2})?\s+([+-]*[0-9]{4}|[A-Z]{1,3})$', $value);
+ case 'julian':
+ return preg_match('/^[0-9]+$/', $value);
+ case 'time': // hh:mm:ss
+ return preg_match('/^[0-9]{2}:[0-9]{2}:[0-9]{2}$/', $value);
+ case 'year':
+ return preg_match('/^[0-9]{4}$/', $value);
+ case 'month':
+ return preg_match('/^[0-9]{2}$/', $value) && $value > 0 && $value < 13;
+ case 'day':
+ return preg_match('/^[0-9]{2}$/', $value) && $value > 0 && $value < 32;
+ case 'hour':
+ return preg_match('/^[0-9]{2}$/', $value) && $value < 24;
+ case 'minute':
+ return preg_match('/^[0-9]{2}$/', $value) && $value < 60;
+ case 'second':
+ // According to RFC5260, seconds can be from 00 to 60
+ return preg_match('/^[0-9]{2}$/', $value) && $value < 61;
+ case 'weekday':
+ return preg_match('/^[0-9]$/', $value) && $value < 7;
+ case 'zone':
+ return preg_match('/^[+-][0-9]{4}$/', $value);
+ }
+ }
+
+ /**
+ * Converts mailbox name from/to UTF7-IMAP from/to internal Sieve encoding
+ * with delimiter replacement.
+ *
+ * @param string $mailbox Mailbox name
+ * @param string $mode Conversion direction ('in'|'out')
+ *
+ * @return string Mailbox name
+ */
+ private function mod_mailbox($mailbox, $mode = 'out')
+ {
+ $delimiter = $_SESSION['imap_delimiter'];
+ $replace_delimiter = $this->rc->config->get('managesieve_replace_delimiter');
+ $mbox_encoding = $this->rc->config->get('managesieve_mbox_encoding', 'UTF7-IMAP');
+
+ if ($mode == 'out') {
+ $mailbox = rcube_charset::convert($mailbox, $mbox_encoding, 'UTF7-IMAP');
+ if ($replace_delimiter && $replace_delimiter != $delimiter)
+ $mailbox = str_replace($replace_delimiter, $delimiter, $mailbox);
+ }
+ else {
+ $mailbox = rcube_charset::convert($mailbox, 'UTF7-IMAP', $mbox_encoding);
+ if ($replace_delimiter && $replace_delimiter != $delimiter)
+ $mailbox = str_replace($delimiter, $replace_delimiter, $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);
+ }
+
+ // Hide scripts from config
+ $exceptions = $this->rc->config->get('managesieve_filename_exceptions');
+ if (!empty($exceptions)) {
+ $this->list = array_diff($this->list, (array)$exceptions);
+ }
+ }
+
+ 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 && 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 $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 $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' => $fname,
+ 'class' => $filter['disabled'] ? 'disabled' : '',
+ );
+ $i++;
+ }
+
+ return $result;
+ }
+}
diff --git a/plugins/managesieve/lib/Roundcube/rcube_sieve_script.php b/plugins/managesieve/lib/Roundcube/rcube_sieve_script.php
index 78b4bc625..a614c3b15 100644
--- a/plugins/managesieve/lib/Roundcube/rcube_sieve_script.php
+++ b/plugins/managesieve/lib/Roundcube/rcube_sieve_script.php
@@ -6,18 +6,18 @@
* 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 free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
* 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.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
*/
class rcube_sieve_script
diff --git a/plugins/managesieve/localization/az_AZ.inc b/plugins/managesieve/localization/az_AZ.inc
index b1bfae5e9..670162552 100644
--- a/plugins/managesieve/localization/az_AZ.inc
+++ b/plugins/managesieve/localization/az_AZ.inc
@@ -55,7 +55,7 @@ $labels['add'] = 'ÆlavÉ™ et';
$labels['del'] = 'Sil';
$labels['sender'] = 'Göndərən';
$labels['recipient'] = 'Qəbul edən';
-$labels['vacationaddresses'] = 'ÆlavÉ™ ünvanlarım üçün siyahı (vergüllÉ™r ilÉ™ ayrılmış):';
+$labels['vacationaddr'] = 'ÆlavÉ™ ünvanlarım üçün siyahı:';
$labels['vacationdays'] = 'Məktub neçə müddətdən bir göndərilsin (gündə):';
$labels['vacationinterval'] = 'How often send messages:';
$labels['days'] = 'days';
diff --git a/plugins/managesieve/localization/be_BE.inc b/plugins/managesieve/localization/be_BE.inc
index 64f81599e..ff54c0546 100644
--- a/plugins/managesieve/localization/be_BE.inc
+++ b/plugins/managesieve/localization/be_BE.inc
@@ -55,7 +55,7 @@ $labels['add'] = 'Дадаць';
$labels['del'] = 'Выдаліць';
$labels['sender'] = 'Ðд каго';
$labels['recipient'] = 'Каму';
-$labels['vacationaddresses'] = 'Дадатковы ÑÐ¿Ñ–Ñ Ð°Ñ‚Ñ€Ñ‹Ð¼Ð°Ð»ÑŒÐ½Ñ–ÐºÐ°Ñž (праз коÑку):';
+$labels['vacationaddr'] = 'Дадатковы ÑÐ¿Ñ–Ñ Ð°Ñ‚Ñ€Ñ‹Ð¼Ð°Ð»ÑŒÐ½Ñ–ÐºÐ°Ñž:';
$labels['vacationdays'] = 'Як чаÑта даÑылаць паведамленні (Ñž днÑÑ…):';
$labels['vacationinterval'] = 'How often send messages:';
$labels['days'] = 'days';
diff --git a/plugins/managesieve/localization/bg_BG.inc b/plugins/managesieve/localization/bg_BG.inc
index a8f75df04..e22290cff 100644
--- a/plugins/managesieve/localization/bg_BG.inc
+++ b/plugins/managesieve/localization/bg_BG.inc
@@ -55,7 +55,7 @@ $labels['add'] = 'ДобавÑне';
$labels['del'] = 'Изтриване';
$labels['sender'] = 'Подател';
$labels['recipient'] = 'Получател';
-$labels['vacationaddresses'] = 'Допълнителни e-mail адреÑи (разделени ÑÑŠÑ Ð·Ð°Ð¿ÐµÑ‚Ð°Ñ):';
+$labels['vacationaddr'] = 'Допълнителни e-mail адреÑи:';
$labels['vacationdays'] = 'Колко чеÑто пращате ÑÑŠÐ¾Ð±Ñ‰ÐµÐ½Ð¸Ñ (в дни):';
$labels['vacationinterval'] = 'How often send messages:';
$labels['days'] = 'days';
diff --git a/plugins/managesieve/localization/bs_BA.inc b/plugins/managesieve/localization/bs_BA.inc
index 7d21dbd9f..df9083129 100644
--- a/plugins/managesieve/localization/bs_BA.inc
+++ b/plugins/managesieve/localization/bs_BA.inc
@@ -55,7 +55,7 @@ $labels['add'] = 'Dodaj';
$labels['del'] = 'Obriši';
$labels['sender'] = 'Pošiljaoc';
$labels['recipient'] = 'Primaoc';
-$labels['vacationaddresses'] = 'Moje dodatne email adrese (odvojite zarezima):';
+$labels['vacationaddr'] = 'Moje dodatne email adrese:';
$labels['vacationdays'] = 'Frekvencija slanja poruka (u danima):';
$labels['vacationinterval'] = 'Frekvencija slanja poruka:';
$labels['days'] = 'dana';
diff --git a/plugins/managesieve/localization/ca_ES.inc b/plugins/managesieve/localization/ca_ES.inc
index df1cdec89..7ebd2c049 100644
--- a/plugins/managesieve/localization/ca_ES.inc
+++ b/plugins/managesieve/localization/ca_ES.inc
@@ -55,7 +55,7 @@ $labels['add'] = 'Afegeix';
$labels['del'] = 'Suprimeix';
$labels['sender'] = 'Remitent';
$labels['recipient'] = 'Destinatari/a';
-$labels['vacationaddresses'] = 'Altres adreces electròniques meves (separades per coma)';
+$labels['vacationaddr'] = 'Altres adreces electròniques meves:';
$labels['vacationdays'] = 'Cada quan enviar un missatge (en dies):';
$labels['vacationinterval'] = 'How often send messages:';
$labels['days'] = 'days';
diff --git a/plugins/managesieve/localization/cs_CZ.inc b/plugins/managesieve/localization/cs_CZ.inc
index 26baeff2b..c14873bb7 100644
--- a/plugins/managesieve/localization/cs_CZ.inc
+++ b/plugins/managesieve/localization/cs_CZ.inc
@@ -55,7 +55,7 @@ $labels['add'] = 'Přidej';
$labels['del'] = 'Smaž';
$labels['sender'] = 'Odesílatel';
$labels['recipient'] = 'Příjemce';
-$labels['vacationaddresses'] = 'Moje další e-mailové adresy (aliasy) spojené s tímto úÄtem (oddÄ›lené Äárkou):';
+$labels['vacationaddr'] = 'Moje další e-mailové adresy (aliasy) spojené s tímto úÄtem:';
$labels['vacationdays'] = 'PoÄet dnů mezi automatickými odpovÄ›Ämi:';
$labels['vacationinterval'] = 'Prodleva mezi automatickými odpovÄ›Ämi:';
$labels['days'] = 'dnů';
diff --git a/plugins/managesieve/localization/cy_GB.inc b/plugins/managesieve/localization/cy_GB.inc
index 800d14b65..63d2e7100 100644
--- a/plugins/managesieve/localization/cy_GB.inc
+++ b/plugins/managesieve/localization/cy_GB.inc
@@ -55,7 +55,7 @@ $labels['add'] = 'Ychwanegu';
$labels['del'] = 'Dileu';
$labels['sender'] = 'Anfonwr';
$labels['recipient'] = 'Derbynnwr';
-$labels['vacationaddresses'] = 'Fy chyfeiriadau ebost ychwanegol (gwahanir gyda coma):';
+$labels['vacationaddr'] = 'Fy chyfeiriadau ebost ychwanegol:';
$labels['vacationdays'] = 'Pa mor aml i ddanfon negeseuon (mewn dyddiau):';
$labels['vacationinterval'] = 'How often send messages:';
$labels['days'] = 'days';
diff --git a/plugins/managesieve/localization/da_DK.inc b/plugins/managesieve/localization/da_DK.inc
index 6bc43cf58..058481031 100644
--- a/plugins/managesieve/localization/da_DK.inc
+++ b/plugins/managesieve/localization/da_DK.inc
@@ -55,7 +55,7 @@ $labels['add'] = 'Tilføje';
$labels['del'] = 'Fjern';
$labels['sender'] = 'Afsender';
$labels['recipient'] = 'Modtager';
-$labels['vacationaddresses'] = 'Mine alternative e-mailadresser (kommasepareret):';
+$labels['vacationaddr'] = 'Mine alternative e-mailadresser:';
$labels['vacationdays'] = 'Hvor tit skal besked sendes (i dage):';
$labels['vacationinterval'] = 'How often send messages:';
$labels['days'] = 'days';
diff --git a/plugins/managesieve/localization/de_CH.inc b/plugins/managesieve/localization/de_CH.inc
index b30625fe9..19a9b9de3 100644
--- a/plugins/managesieve/localization/de_CH.inc
+++ b/plugins/managesieve/localization/de_CH.inc
@@ -55,7 +55,7 @@ $labels['add'] = 'Hinzufügen';
$labels['del'] = 'Löschen';
$labels['sender'] = 'Absender';
$labels['recipient'] = 'Empfänger';
-$labels['vacationaddresses'] = 'Zusätzliche Liste von Empfängern (Komma getrennt):';
+$labels['vacationaddr'] = 'Zusätzliche Liste von Empfängern:';
$labels['vacationdays'] = 'Antwort wird erneut gesendet nach (in Tagen):';
$labels['vacationinterval'] = 'Wie oft senden:';
$labels['days'] = 'Tage';
diff --git a/plugins/managesieve/localization/de_DE.inc b/plugins/managesieve/localization/de_DE.inc
index 1b741efc6..4894904d6 100644
--- a/plugins/managesieve/localization/de_DE.inc
+++ b/plugins/managesieve/localization/de_DE.inc
@@ -55,7 +55,7 @@ $labels['add'] = 'Hinzufügen';
$labels['del'] = 'Löschen';
$labels['sender'] = 'Absender';
$labels['recipient'] = 'Empfänger';
-$labels['vacationaddresses'] = 'Zusätzliche Liste von E-Mail Empfängern (Komma getrennt):';
+$labels['vacationaddr'] = 'Zusätzliche Liste von E-Mail Empfängern:';
$labels['vacationdays'] = 'Wie oft sollen Nachrichten gesendet werden (in Tagen):';
$labels['vacationinterval'] = 'How often send messages:';
$labels['days'] = 'days';
diff --git a/plugins/managesieve/localization/el_GR.inc b/plugins/managesieve/localization/el_GR.inc
index 714b7240f..e5a1b792d 100644
--- a/plugins/managesieve/localization/el_GR.inc
+++ b/plugins/managesieve/localization/el_GR.inc
@@ -55,7 +55,7 @@ $labels['add'] = 'ΠÏοσθήκη';
$labels['del'] = 'ΔιαγÏαφή';
$labels['sender'] = 'Αποστολέας';
$labels['recipient'] = 'ΠαÏαλήπτης';
-$labels['vacationaddresses'] = 'ΠÏόσθετη λίστα email παÏαληπτών (διαχωÏισμένη με κόμματα):';
+$labels['vacationaddr'] = 'ΠÏόσθετη λίστα email παÏαληπτών:';
$labels['vacationdays'] = 'Συχνότητα αποστολής μηνυμάτων (σε ημέÏες):';
$labels['vacationinterval'] = 'How often send messages:';
$labels['days'] = 'days';
diff --git a/plugins/managesieve/localization/en_GB.inc b/plugins/managesieve/localization/en_GB.inc
index 4dd4f7d8b..ff4965ca0 100644
--- a/plugins/managesieve/localization/en_GB.inc
+++ b/plugins/managesieve/localization/en_GB.inc
@@ -55,7 +55,7 @@ $labels['add'] = 'Add';
$labels['del'] = 'Delete';
$labels['sender'] = 'Sender';
$labels['recipient'] = 'Recipient';
-$labels['vacationaddresses'] = 'Additional list of recipient e-mails (comma separated):';
+$labels['vacationaddr'] = 'Additional list of recipient e-mails:';
$labels['vacationdays'] = 'How often send messages (in days):';
$labels['vacationinterval'] = 'How often send messages:';
$labels['days'] = 'days';
diff --git a/plugins/managesieve/localization/en_US.inc b/plugins/managesieve/localization/en_US.inc
index 2b391e0c5..72bbf9d41 100644
--- a/plugins/managesieve/localization/en_US.inc
+++ b/plugins/managesieve/localization/en_US.inc
@@ -55,7 +55,7 @@ $labels['add'] = 'Add';
$labels['del'] = 'Delete';
$labels['sender'] = 'Sender';
$labels['recipient'] = 'Recipient';
-$labels['vacationaddresses'] = 'My additional e-mail addresse(s) (comma-separated):';
+$labels['vacationaddr'] = 'My additional e-mail addresse(s):';
$labels['vacationdays'] = 'How often send messages (in days):';
$labels['vacationinterval'] = 'How often send messages:';
$labels['days'] = 'days';
@@ -83,13 +83,13 @@ $labels['countisgreaterthanequal'] = 'count is greater than or equal to';
$labels['countislessthan'] = 'count is less than';
$labels['countislessthanequal'] = 'count is less than or equal to';
$labels['countequals'] = 'count is equal to';
-$labels['countnotequals'] = 'count does not equal';
+$labels['countnotequals'] = 'count is not equal to';
$labels['valueisgreaterthan'] = 'value is greater than';
$labels['valueisgreaterthanequal'] = 'value is greater than or equal to';
$labels['valueislessthan'] = 'value is less than';
$labels['valueislessthanequal'] = 'value is less than or equal to';
$labels['valueequals'] = 'value is equal to';
-$labels['valuenotequals'] = 'value does not equal';
+$labels['valuenotequals'] = 'value is not equal to';
$labels['setflags'] = 'Set flags to the message';
$labels['addflags'] = 'Add flags to the message';
$labels['removeflags'] = 'Remove flags from the message';
@@ -121,6 +121,22 @@ $labels['filtercreate'] = 'Create filter';
$labels['usedata'] = 'Use following data in the filter:';
$labels['nextstep'] = 'Next Step';
$labels['...'] = '...';
+$labels['currdate'] = 'Current date';
+$labels['datetest'] = 'Date';
+$labels['dateheader'] = 'header:';
+$labels['year'] = 'year';
+$labels['month'] = 'month';
+$labels['day'] = 'day';
+$labels['date'] = 'date (yyyy-mm-dd)';
+$labels['julian'] = 'date (julian)';
+$labels['hour'] = 'hour';
+$labels['minute'] = 'minute';
+$labels['second'] = 'second';
+$labels['time'] = 'time (hh:mm:ss)';
+$labels['iso8601'] = 'date (ISO8601)';
+$labels['std11'] = 'date (RFC2822)';
+$labels['zone'] = 'time-zone';
+$labels['weekday'] = 'weekday (0-6)';
$labels['advancedopts'] = 'Advanced options';
$labels['body'] = 'Body';
$labels['address'] = 'address';
@@ -140,6 +156,8 @@ $labels['default'] = 'default';
$labels['octet'] = 'strict (octet)';
$labels['asciicasemap'] = 'case insensitive (ascii-casemap)';
$labels['asciinumeric'] = 'numeric (ascii-numeric)';
+$labels['index'] = 'index:';
+$labels['indexlast'] = 'backwards';
$messages = array();
$messages['filterunknownerror'] = 'Unknown server error.';
@@ -173,5 +191,6 @@ $messages['nametoolong'] = 'Name too long.';
$messages['namereserved'] = 'Reserved name.';
$messages['setexist'] = 'Set already exists.';
$messages['nodata'] = 'At least one position must be selected!';
+$messages['invaliddateformat'] = 'Invalid date or date part format';
?>
diff --git a/plugins/managesieve/localization/eo.inc b/plugins/managesieve/localization/eo.inc
index 3ce49ddb2..3f54e2391 100644
--- a/plugins/managesieve/localization/eo.inc
+++ b/plugins/managesieve/localization/eo.inc
@@ -55,7 +55,7 @@ $labels['add'] = 'Aldoni';
$labels['del'] = 'Forigi';
$labels['sender'] = 'Sendanto';
$labels['recipient'] = 'Ricevanto';
-$labels['vacationaddresses'] = 'My additional e-mail addresse(s) (comma-separated):';
+$labels['vacationaddr'] = 'My additional e-mail addresse(s):';
$labels['vacationdays'] = 'How often send messages (in days):';
$labels['vacationinterval'] = 'How often send messages:';
$labels['days'] = 'days';
diff --git a/plugins/managesieve/localization/es_AR.inc b/plugins/managesieve/localization/es_AR.inc
index c9c6e70f8..e8d90efcf 100644
--- a/plugins/managesieve/localization/es_AR.inc
+++ b/plugins/managesieve/localization/es_AR.inc
@@ -55,7 +55,7 @@ $labels['add'] = 'Agregar';
$labels['del'] = 'Eliminar';
$labels['sender'] = 'Remitente';
$labels['recipient'] = 'Destinatario';
-$labels['vacationaddresses'] = 'Lista de direcciones de correo de destinatarios adicionales (separados por comas):';
+$labels['vacationaddr'] = 'Lista de direcciones de correo de destinatarios adicionales:';
$labels['vacationdays'] = 'Cada cuanto enviar mensajes (en días):';
$labels['vacationinterval'] = 'How often send messages:';
$labels['days'] = 'days';
diff --git a/plugins/managesieve/localization/es_ES.inc b/plugins/managesieve/localization/es_ES.inc
index 9673a9959..65ed461c4 100644
--- a/plugins/managesieve/localization/es_ES.inc
+++ b/plugins/managesieve/localization/es_ES.inc
@@ -55,11 +55,11 @@ $labels['add'] = 'Agregar';
$labels['del'] = 'Eliminar';
$labels['sender'] = 'Remitente';
$labels['recipient'] = 'Destinatario';
-$labels['vacationaddresses'] = 'Lista de direcciones de correo de destinatarios adicionales (separados por comas):';
+$labels['vacationaddr'] = 'Mis direcciones de correo electrónico adicionales:';
$labels['vacationdays'] = 'Cada cuánto enviar mensajes (en días):';
-$labels['vacationinterval'] = 'How often send messages:';
-$labels['days'] = 'days';
-$labels['seconds'] = 'seconds';
+$labels['vacationinterval'] = 'Cada cuánto enviar mensajes:';
+$labels['days'] = 'días';
+$labels['seconds'] = 'segundos';
$labels['vacationreason'] = 'Cuerpo del mensaje (razón de vacaciones):';
$labels['vacationsubject'] = 'Asunto del Mensaje:';
$labels['rulestop'] = 'Parar de evaluar reglas';
@@ -83,13 +83,13 @@ $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['countnotequals'] = 'la cuenta no es igual a';
$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['valuenotequals'] = 'el valor no es igual a';
$labels['setflags'] = 'Etiquetar el mensaje';
$labels['addflags'] = 'Agregar etiquetas al mensaje';
$labels['removeflags'] = 'Eliminar etiquetas al mensaje';
@@ -121,6 +121,22 @@ $labels['filtercreate'] = 'Crear Filtro';
$labels['usedata'] = 'Usar los siguientes datos en el filtro:';
$labels['nextstep'] = 'Siguiente paso';
$labels['...'] = '...';
+$labels['currdate'] = 'Fecha actual';
+$labels['datetest'] = 'Fecha';
+$labels['dateheader'] = 'cabecera:';
+$labels['year'] = 'año';
+$labels['month'] = 'mes';
+$labels['day'] = 'día';
+$labels['date'] = 'fecha (aaaa-mm-dd)';
+$labels['julian'] = 'fecha (juliano)';
+$labels['hour'] = 'hora';
+$labels['minute'] = 'minuto';
+$labels['second'] = 'segundo';
+$labels['time'] = 'hora (hh:mm:ss)';
+$labels['iso8601'] = 'fecha (ISO8601)';
+$labels['std11'] = 'fecha (RFC2822)';
+$labels['zone'] = 'zona horaria';
+$labels['weekday'] = 'día de la semana (0-6)';
$labels['advancedopts'] = 'Opciones avanzadas';
$labels['body'] = 'Cuerpo del mensaje';
$labels['address'] = 'dirección';
@@ -140,6 +156,8 @@ $labels['default'] = 'predeterminado';
$labels['octet'] = 'estricto (octeto)';
$labels['asciicasemap'] = 'no sensible a mayúsculas (ascii-casemap)';
$labels['asciinumeric'] = 'numerico (ascii-numeric)';
+$labels['index'] = 'índice:';
+$labels['indexlast'] = 'hacia atrás';
$messages = array();
$messages['filterunknownerror'] = 'Error desconocido de servidor.';
@@ -173,5 +191,6 @@ $messages['nametoolong'] = 'Imposible crear el conjunto de filtros. Nombre demas
$messages['namereserved'] = 'Nombre reservado.';
$messages['setexist'] = 'El conjunto ya existe.';
$messages['nodata'] = '¡Al menos una posición debe ser seleccionada!';
+$messages['invaliddateformat'] = 'Fecha o formato de parte de la fecha no válido';
?>
diff --git a/plugins/managesieve/localization/et_EE.inc b/plugins/managesieve/localization/et_EE.inc
index 334a65cee..dff15dfb4 100644
--- a/plugins/managesieve/localization/et_EE.inc
+++ b/plugins/managesieve/localization/et_EE.inc
@@ -55,11 +55,11 @@ $labels['add'] = 'Lisa';
$labels['del'] = 'Kustuta';
$labels['sender'] = 'Saatja';
$labels['recipient'] = 'Saaja';
-$labels['vacationaddresses'] = 'Lisanimekiri saaja e-posti aadressidest (komadega eraldatud):';
+$labels['vacationaddr'] = 'Minu teised e-posti aadress(id):';
$labels['vacationdays'] = 'Kui tihti kirju saata (päevades):';
-$labels['vacationinterval'] = 'How often send messages:';
-$labels['days'] = 'days';
-$labels['seconds'] = 'seconds';
+$labels['vacationinterval'] = 'Kui tihti kirju saata:';
+$labels['days'] = 'päeva';
+$labels['seconds'] = 'sekundit';
$labels['vacationreason'] = 'Kirja sisu (puhkuse põhjus):';
$labels['vacationsubject'] = 'Kirja teema:';
$labels['rulestop'] = 'Peata reeglite otsimine';
@@ -83,7 +83,7 @@ $labels['countisgreaterthanequal'] = 'koguarv on suurem kui või võrdne';
$labels['countislessthan'] = 'koguarv on väiksem';
$labels['countislessthanequal'] = 'koguarv on väiksem kui või võrdne';
$labels['countequals'] = 'koguarv on võrdne';
-$labels['countnotequals'] = 'koguarv ei ole võrdne';
+$labels['countnotequals'] = 'summa ei ole võrdne';
$labels['valueisgreaterthan'] = 'väärtus on suurem kui';
$labels['valueisgreaterthanequal'] = 'väärtus on suurem kui või võrdne';
$labels['valueislessthan'] = 'väärtus on väiksem kui';
@@ -121,6 +121,22 @@ $labels['filtercreate'] = 'Loo filter';
$labels['usedata'] = 'Kasuta filtris järgmisi andmeid:';
$labels['nextstep'] = 'Järgmine samm';
$labels['...'] = '…';
+$labels['currdate'] = 'Praegune kuupäev';
+$labels['datetest'] = 'Kuupäev';
+$labels['dateheader'] = 'päis:';
+$labels['year'] = 'aasta';
+$labels['month'] = 'kuu';
+$labels['day'] = 'päev';
+$labels['date'] = 'kuupäev (aaaa-kk-pp)';
+$labels['julian'] = 'kuupäev (Juliuse)';
+$labels['hour'] = 'tund';
+$labels['minute'] = 'minut';
+$labels['second'] = 'sekund';
+$labels['time'] = 'aeg (tt:mm:ss)';
+$labels['iso8601'] = 'kuupäev (ISO8601)';
+$labels['std11'] = 'kuupäev (RCF2822)';
+$labels['zone'] = 'ajatsoon';
+$labels['weekday'] = 'nädalapäev (0-6)';
$labels['advancedopts'] = 'Lisaseadistused';
$labels['body'] = 'Põhitekst';
$labels['address'] = 'aadress';
@@ -140,6 +156,8 @@ $labels['default'] = 'vaikimisi';
$labels['octet'] = 'range (octet)';
$labels['asciicasemap'] = 'tõstutundetu (ascii-casemap)';
$labels['asciinumeric'] = 'numbriline (ascii-numeric)';
+$labels['index'] = 'indeks:';
+$labels['indexlast'] = 'tagasisuunas';
$messages = array();
$messages['filterunknownerror'] = 'Tundmatu serveri tõrge';
@@ -173,5 +191,6 @@ $messages['nametoolong'] = 'Nimi on liiga pikk.';
$messages['namereserved'] = 'Nimi on reserveeritud.';
$messages['setexist'] = 'Kogum on juba olemas.';
$messages['nodata'] = 'Valitud peab olema vähemalt üks asukoht!';
+$messages['invaliddateformat'] = 'Vigane kuupäev või kuupäeva formaat';
?>
diff --git a/plugins/managesieve/localization/fa_IR.inc b/plugins/managesieve/localization/fa_IR.inc
index 91dfcb605..1c8eace27 100644
--- a/plugins/managesieve/localization/fa_IR.inc
+++ b/plugins/managesieve/localization/fa_IR.inc
@@ -55,7 +55,6 @@ $labels['add'] = 'اÙزودن';
$labels['del'] = 'حذÙ';
$labels['sender'] = 'Ùرستنده';
$labels['recipient'] = 'گیرنده';
-$labels['vacationaddresses'] = 'آدرس‌های ایمیل دیگر من (جدا شده با ویرگول):';
$labels['vacationdays'] = 'پیغام ها در Ú†Ù‡ مواقعی Ùرستاده شدند (در روزهای):';
$labels['vacationinterval'] = 'How often send messages:';
$labels['days'] = 'days';
diff --git a/plugins/managesieve/localization/fi_FI.inc b/plugins/managesieve/localization/fi_FI.inc
index 71856c95f..f006f6d23 100644
--- a/plugins/managesieve/localization/fi_FI.inc
+++ b/plugins/managesieve/localization/fi_FI.inc
@@ -55,7 +55,7 @@ $labels['add'] = 'Lisää';
$labels['del'] = 'Poista';
$labels['sender'] = 'Lähettäjä';
$labels['recipient'] = 'Vastaanottaja';
-$labels['vacationaddresses'] = 'My additional e-mail addresse(s) (comma-separated):';
+$labels['vacationaddr'] = 'My additional e-mail addresse(s):';
$labels['vacationdays'] = 'How often send messages (in days):';
$labels['vacationinterval'] = 'How often send messages:';
$labels['days'] = 'days';
diff --git a/plugins/managesieve/localization/fr_FR.inc b/plugins/managesieve/localization/fr_FR.inc
index 9be9f1054..821f9caab 100644
--- a/plugins/managesieve/localization/fr_FR.inc
+++ b/plugins/managesieve/localization/fr_FR.inc
@@ -18,7 +18,7 @@
$labels['filters'] = 'Filtres';
-$labels['managefilters'] = 'Gestion des filtres sur les mails entrants';
+$labels['managefilters'] = 'Gérer les filtres sur les courriels entrants';
$labels['filtername'] = 'Nom du filtre';
$labels['newfilter'] = 'Nouveau filtre';
$labels['filteradd'] = 'Ajouter un filtre';
@@ -49,17 +49,17 @@ $labels['messagesendcopy'] = 'Envoyer une copie du message à';
$labels['messagereply'] = 'Répondre avec le message';
$labels['messagedelete'] = 'Supprimer le message';
$labels['messagediscard'] = 'Rejeter avec le message';
-$labels['messagesrules'] = 'Pour les mails entrants:';
+$labels['messagesrules'] = 'Pour les courriels entrants :';
$labels['messagesactions'] = '...exécuter les actions suivantes:';
$labels['add'] = 'Ajouter';
$labels['del'] = 'Supprimer';
$labels['sender'] = 'Expéditeur';
$labels['recipient'] = 'Destinataire';
-$labels['vacationaddresses'] = 'Liste des destinataires (séparés par une virgule) :';
+$labels['vacationaddr'] = 'Mon/Mes adresse(s) de courriel additionnelle(s):';
$labels['vacationdays'] = 'Ne pas renvoyer un message avant (jours) :';
-$labels['vacationinterval'] = 'How often send messages:';
-$labels['days'] = 'days';
-$labels['seconds'] = 'seconds';
+$labels['vacationinterval'] = 'Comment envoyer les messages :';
+$labels['days'] = 'jours';
+$labels['seconds'] = 'secondes';
$labels['vacationreason'] = 'Corps du message (raison de l\'absence) :';
$labels['vacationsubject'] = 'Sujet du message:';
$labels['rulestop'] = 'Arrêter d\'évaluer les prochaines règles';
@@ -83,13 +83,13 @@ $labels['countisgreaterthanequal'] = 'total supérieur ou égal à';
$labels['countislessthan'] = 'total inférieur à';
$labels['countislessthanequal'] = 'total inférieur à';
$labels['countequals'] = 'total égal à';
-$labels['countnotequals'] = 'total différent de';
+$labels['countnotequals'] = 'le comptage n\'est pas égal à';
$labels['valueisgreaterthan'] = 'valeur supérieure à';
$labels['valueisgreaterthanequal'] = 'valeur supérieure ou égale à';
$labels['valueislessthan'] = 'valeur inférieure à';
$labels['valueislessthanequal'] = 'valeur inférieure ou égale à';
$labels['valueequals'] = 'valeur égale à';
-$labels['valuenotequals'] = 'valeur différente de';
+$labels['valuenotequals'] = 'la valeur n\'est pas égale à';
$labels['setflags'] = 'Mettre les marqueurs au message';
$labels['addflags'] = 'Ajouter les marqueurs au message';
$labels['removeflags'] = 'Supprimer les marqueurs du message';
@@ -121,6 +121,22 @@ $labels['filtercreate'] = 'Créer un filtre';
$labels['usedata'] = 'Utiliser les informations suivantes dans le filtre';
$labels['nextstep'] = 'Étape suivante';
$labels['...'] = '...';
+$labels['currdate'] = 'Date actuelle';
+$labels['datetest'] = 'Date';
+$labels['dateheader'] = 'header:';
+$labels['year'] = 'année';
+$labels['month'] = 'mois';
+$labels['day'] = 'jour';
+$labels['date'] = 'date (yyyy-mm-dd)';
+$labels['julian'] = 'date (julien)';
+$labels['hour'] = 'heure';
+$labels['minute'] = 'minute';
+$labels['second'] = 'seconde';
+$labels['time'] = 'heure (hh:mm:ss)';
+$labels['iso8601'] = 'date (ISO8601)';
+$labels['std11'] = 'date (RFC2822)';
+$labels['zone'] = 'fuseau horaire';
+$labels['weekday'] = 'jour de la semaine (0-6)';
$labels['advancedopts'] = 'Options avancées';
$labels['body'] = 'Corps du message';
$labels['address'] = 'adresse';
@@ -140,6 +156,8 @@ $labels['default'] = 'par défaut';
$labels['octet'] = 'strict (octet)';
$labels['asciicasemap'] = 'insensible à la casse (ascii-casemap)';
$labels['asciinumeric'] = 'numérique (ascii-numeric)';
+$labels['index'] = 'index:';
+$labels['indexlast'] = 'retour arrière';
$messages = array();
$messages['filterunknownerror'] = 'Erreur du serveur inconnue';
@@ -165,13 +183,14 @@ $messages['setcreateerror'] = 'Impossible de créer le groupe de filtres. Le ser
$messages['setcreated'] = 'Le groupe de filtres a bien été créé.';
$messages['activateerror'] = 'Impossible d\'activer le(s) filtre(s) sélectionné(s). Une erreur serveur s\'est produite.';
$messages['deactivateerror'] = 'Impossible de désactiver le(s) filtre(s) sélectionné(s). Une erreur serveur s\'est produite.';
-$messages['deactivated'] = 'Filtre(s) activé(s) avec succès';
-$messages['activated'] = 'Filtre(s) désactivé(s) avec succès';
+$messages['deactivated'] = 'Filtre(s) désactivé(s) avec succès.';
+$messages['activated'] = 'Filtre(s) activé(s) avec succès.';
$messages['moved'] = 'Filtre déplacé avec succès.';
$messages['moveerror'] = 'Déplacement du filtre sélectionné impossible. Le serveur a renvoyé une erreur.';
$messages['nametoolong'] = 'Nom trop long.';
$messages['namereserved'] = 'Nom réservé.';
$messages['setexist'] = 'Ce groupe existe déjà.';
$messages['nodata'] = 'Au moins un élément doit être selectionné !';
+$messages['invaliddateformat'] = 'Date non valide ou format d\'une partie de la date';
?>
diff --git a/plugins/managesieve/localization/gl_ES.inc b/plugins/managesieve/localization/gl_ES.inc
index 3f492ad46..185490a94 100644
--- a/plugins/managesieve/localization/gl_ES.inc
+++ b/plugins/managesieve/localization/gl_ES.inc
@@ -55,7 +55,7 @@ $labels['add'] = 'Engadir';
$labels['del'] = 'Eliminar';
$labels['sender'] = 'Remitente';
$labels['recipient'] = 'Destinatario';
-$labels['vacationaddresses'] = 'Lista de enderezos de correo de destinatarios adicionais (separados por comas):';
+$labels['vacationaddr'] = 'Lista de enderezos de correo de destinatarios adicionais:';
$labels['vacationdays'] = 'Cada canto enviar mensaxes (en días):';
$labels['vacationinterval'] = 'How often send messages:';
$labels['days'] = 'days';
diff --git a/plugins/managesieve/localization/he_IL.inc b/plugins/managesieve/localization/he_IL.inc
index 0b2f67ede..932d4e5d6 100644
--- a/plugins/managesieve/localization/he_IL.inc
+++ b/plugins/managesieve/localization/he_IL.inc
@@ -55,7 +55,6 @@ $labels['add'] = 'הוספה';
$labels['del'] = 'מחיקה';
$labels['sender'] = 'השולח';
$labels['recipient'] = 'הנמען';
-$labels['vacationaddresses'] = 'כתובות דו×"ל נוספות שלי (מופרדות ×¢"×™ פסיקי×)';
$labels['vacationdays'] = 'ב×יזו תדירות ( ×‘×™×ž×™× ) לשלוח הודעות:';
$labels['vacationinterval'] = 'How often send messages:';
$labels['days'] = 'days';
diff --git a/plugins/managesieve/localization/hu_HU.inc b/plugins/managesieve/localization/hu_HU.inc
index 9d39ffac3..ea59fa717 100644
--- a/plugins/managesieve/localization/hu_HU.inc
+++ b/plugins/managesieve/localization/hu_HU.inc
@@ -55,7 +55,7 @@ $labels['add'] = 'Hozzáadás';
$labels['del'] = 'Törlés';
$labels['sender'] = 'Feladó';
$labels['recipient'] = 'Címzett';
-$labels['vacationaddresses'] = 'További címzettek (vesszővel elválasztva):';
+$labels['vacationaddr'] = 'További címzettek:';
$labels['vacationdays'] = 'Válaszüzenet küldése ennyi naponként:';
$labels['vacationinterval'] = 'Milyen gyakran küld üzeneteket:';
$labels['days'] = 'napok';
diff --git a/plugins/managesieve/localization/hy_AM.inc b/plugins/managesieve/localization/hy_AM.inc
index 908175f1d..68837b065 100644
--- a/plugins/managesieve/localization/hy_AM.inc
+++ b/plugins/managesieve/localization/hy_AM.inc
@@ -55,7 +55,7 @@ $labels['add'] = 'Ô±Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬';
$labels['del'] = 'Õ‹Õ¶Õ»Õ¥Õ¬';
$labels['sender'] = 'ÕˆÖ‚Õ²Õ¡Ö€Õ¯Õ¸Õ²';
$labels['recipient'] = 'ÕÕ¿Õ¡ÖÕ¸Õ²';
-$labels['vacationaddresses'] = 'Ô»Õ´ Õ°Õ¡Õ¾Õ¥Õ¬ÕµÕ¡Õ¬ Õ§Õ¬ÖƒÕ¸Õ½Õ¿Õ« Õ°Õ¡Õ½ÖÕ¥Õ¶Õ¥Ö€ (Õ¢Õ¡ÕªÕ¡Õ¶Õ¾Õ¡Õ® Õ½Õ¿Õ¸Ö€Õ¡Õ¯Õ¥Õ¿Õ¶Õ¥Ö€Õ¸Õ¾).';
+$labels['vacationaddr'] = 'Ô»Õ´ Õ°Õ¡Õ¾Õ¥Õ¬ÕµÕ¡Õ¬ Õ§Õ¬ÖƒÕ¸Õ½Õ¿Õ« Õ°Õ¡Õ½ÖÕ¥Õ¶Õ¥Ö€.';
$labels['vacationdays'] = 'Ô»Õ¶Õ¹ Õ°Õ¡Õ³Õ¡Õ­Õ¸Ö‚Õ©ÕµÕ¡Õ´Õ¢ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬ Õ°Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨ (Ö…Ö€Õ¥Ö€)`';
$labels['vacationinterval'] = 'How often send messages:';
$labels['days'] = 'days';
diff --git a/plugins/managesieve/localization/ia.inc b/plugins/managesieve/localization/ia.inc
index 45f6e5263..945de27d8 100644
--- a/plugins/managesieve/localization/ia.inc
+++ b/plugins/managesieve/localization/ia.inc
@@ -55,7 +55,7 @@ $labels['add'] = 'Add';
$labels['del'] = 'Delete';
$labels['sender'] = 'Sender';
$labels['recipient'] = 'Recipient';
-$labels['vacationaddresses'] = 'My additional e-mail addresse(s) (comma-separated):';
+$labels['vacationaddr'] = 'My additional e-mail addresse(s):';
$labels['vacationdays'] = 'How often send messages (in days):';
$labels['vacationinterval'] = 'How often send messages:';
$labels['days'] = 'days';
diff --git a/plugins/managesieve/localization/id_ID.inc b/plugins/managesieve/localization/id_ID.inc
index a30c2a0b0..d98a326c1 100644
--- a/plugins/managesieve/localization/id_ID.inc
+++ b/plugins/managesieve/localization/id_ID.inc
@@ -55,7 +55,7 @@ $labels['add'] = 'Tambah';
$labels['del'] = 'Hapus';
$labels['sender'] = 'Pengirim';
$labels['recipient'] = 'Penerima';
-$labels['vacationaddresses'] = 'Alamat email tambahan saya (dipisahkan koma):';
+$labels['vacationaddr'] = 'Alamat email tambahan saya:';
$labels['vacationdays'] = 'Seberapa sering mengirim pesan (dalam hari):';
$labels['vacationinterval'] = 'How often send messages:';
$labels['days'] = 'days';
diff --git a/plugins/managesieve/localization/it_IT.inc b/plugins/managesieve/localization/it_IT.inc
index 6fb2c424f..b54c46d9a 100644
--- a/plugins/managesieve/localization/it_IT.inc
+++ b/plugins/managesieve/localization/it_IT.inc
@@ -55,7 +55,7 @@ $labels['add'] = 'Aggiungi';
$labels['del'] = 'Elimina';
$labels['sender'] = 'Mittente';
$labels['recipient'] = 'Destinatario';
-$labels['vacationaddresses'] = 'Lista di indirizzi e-mail di destinatari addizionali (separati da virgola):';
+$labels['vacationaddr'] = 'Lista di indirizzi e-mail di destinatari addizionali:';
$labels['vacationdays'] = 'Ogni quanti giorni ribadire il messaggio allo stesso mittente';
$labels['vacationinterval'] = 'How often send messages:';
$labels['days'] = 'days';
diff --git a/plugins/managesieve/localization/ja_JP.inc b/plugins/managesieve/localization/ja_JP.inc
index 0cd4f44b9..c8927d3f2 100644
--- a/plugins/managesieve/localization/ja_JP.inc
+++ b/plugins/managesieve/localization/ja_JP.inc
@@ -55,7 +55,7 @@ $labels['add'] = '追加';
$labels['del'] = '削除';
$labels['sender'] = 'é€ä¿¡è€…';
$labels['recipient'] = '宛先';
-$labels['vacationaddresses'] = 'é›»å­ãƒ¡ãƒ¼ãƒ«ã®å®›å…ˆã®(コンマ区切ã£ãŸ)追加ã®ãƒªã‚¹ãƒˆ:';
+$labels['vacationaddr'] = 'é›»å­ãƒ¡ãƒ¼ãƒ«ã®å®›å…ˆã®è¿½åŠ ã®ãƒªã‚¹ãƒˆ:';
$labels['vacationdays'] = 'メッセージを(1æ—¥ã«)é€ä¿¡ã™ã‚‹é »åº¦:';
$labels['vacationinterval'] = 'メッセージをé€ä¿¡ã™ã‚‹é »åº¦:';
$labels['days'] = 'æ—¥';
diff --git a/plugins/managesieve/localization/ko_KR.inc b/plugins/managesieve/localization/ko_KR.inc
index 5ab4fc220..1085f624d 100644
--- a/plugins/managesieve/localization/ko_KR.inc
+++ b/plugins/managesieve/localization/ko_KR.inc
@@ -55,7 +55,7 @@ $labels['add'] = '추가';
$labels['del'] = '삭제';
$labels['sender'] = '발신ì¸';
$labels['recipient'] = '수신ì¸';
-$labels['vacationaddresses'] = 'ë‚˜ì˜ ì¶”ê°€ ì´ë©”ì¼ ì£¼ì†Œ (쉼표로 구분ë¨):';
+$labels['vacationaddr'] = 'ë‚˜ì˜ ì¶”ê°€ ì´ë©”ì¼ ì£¼ì†Œ:';
$labels['vacationdays'] = '메시지 발신 주기 (ì¼):';
$labels['vacationinterval'] = 'How often send messages:';
$labels['days'] = 'days';
diff --git a/plugins/managesieve/localization/lb_LU.inc b/plugins/managesieve/localization/lb_LU.inc
new file mode 100644
index 000000000..7494c0eb5
--- /dev/null
+++ b/plugins/managesieve/localization/lb_LU.inc
@@ -0,0 +1,196 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | plugins/managesieve/localization/<lang>.inc |
+ | |
+ | Localization file of the Roundcube Webmail Managesieve plugin |
+ | Copyright (C) 2012-2013, The Roundcube Dev Team |
+ | |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
+ | |
+ +-----------------------------------------------------------------------+
+
+ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-managesieve/
+*/
+
+
+$labels['filters'] = 'Filteren';
+$labels['managefilters'] = 'Filtere geréieren fir Mailen déi erakommen';
+$labels['filtername'] = 'Numm vum Filter';
+$labels['newfilter'] = 'Neie Filter';
+$labels['filteradd'] = 'Filter dobäisetzen';
+$labels['filterdel'] = 'Filter läschen';
+$labels['moveup'] = 'Eropréckelen';
+$labels['movedown'] = 'Erofréckelen';
+$labels['filterallof'] = 'all dës Reegele mussen zoutreffen';
+$labels['filteranyof'] = 'just eng vun de Reegele muss zoutreffen';
+$labels['filterany'] = 'all d\'Messagen';
+$labels['filtercontains'] = 'enthält';
+$labels['filternotcontains'] = 'enthält net';
+$labels['filteris'] = 'ass gläich';
+$labels['filterisnot'] = 'ass net gläich';
+$labels['filterexists'] = 'existéiert';
+$labels['filternotexists'] = 'existéiert net';
+$labels['filtermatches'] = 'matches expression';
+$labels['filternotmatches'] = 'not matches expression';
+$labels['filterregex'] = 'matches regular expression';
+$labels['filternotregex'] = 'not matches regular expression';
+$labels['filterunder'] = 'ënner';
+$labels['filterover'] = 'iwwer';
+$labels['addrule'] = 'Reegel dobäisetzen';
+$labels['delrule'] = 'Reegel läschen';
+$labels['messagemoveto'] = 'Message verréckelen an';
+$labels['messageredirect'] = 'Message ëmleeden an';
+$labels['messagecopyto'] = 'Message kopéieren an';
+$labels['messagesendcopy'] = 'Kopie vum Message schécken un';
+$labels['messagereply'] = 'Mat dësem Message äntweren';
+$labels['messagedelete'] = 'Message läschen';
+$labels['messagediscard'] = 'Discard with message';
+$labels['messagesrules'] = 'For incoming mail:';
+$labels['messagesactions'] = '...execute the following actions:';
+$labels['add'] = 'Dobäisetzen';
+$labels['del'] = 'Läschen';
+$labels['sender'] = 'Ofsender';
+$labels['recipient'] = 'Empfänger';
+$labels['vacationaddr'] = 'My additional e-mail addresse(s):';
+$labels['vacationdays'] = 'How often send messages (in days):';
+$labels['vacationinterval'] = 'How often send messages:';
+$labels['days'] = 'days';
+$labels['seconds'] = 'seconds';
+$labels['vacationreason'] = 'Message body (vacation reason):';
+$labels['vacationsubject'] = 'Message subject:';
+$labels['rulestop'] = 'Stop evaluating rules';
+$labels['enable'] = 'Enable/Disable';
+$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['filterdef'] = 'Filter definition';
+$labels['filtersetname'] = 'Filters set name';
+$labels['newfilterset'] = 'New filters set';
+$labels['active'] = 'active';
+$labels['none'] = 'none';
+$labels['fromset'] = 'from set';
+$labels['fromfile'] = 'from file';
+$labels['filterdisabled'] = 'Filter disabled';
+$labels['countisgreaterthan'] = 'count is greater than';
+$labels['countisgreaterthanequal'] = 'count is greater than or equal to';
+$labels['countislessthan'] = 'count is less than';
+$labels['countislessthanequal'] = 'count is less than or equal to';
+$labels['countequals'] = 'count is equal to';
+$labels['countnotequals'] = 'count is not equal to';
+$labels['valueisgreaterthan'] = 'value is greater than';
+$labels['valueisgreaterthanequal'] = 'value is greater than or equal to';
+$labels['valueislessthan'] = 'value is less than';
+$labels['valueislessthanequal'] = 'value is less than or equal to';
+$labels['valueequals'] = 'value is equal to';
+$labels['valuenotequals'] = 'value is not equal to';
+$labels['setflags'] = 'Set flags to the message';
+$labels['addflags'] = 'Add flags to the message';
+$labels['removeflags'] = 'Remove flags from the message';
+$labels['flagread'] = 'Read';
+$labels['flagdeleted'] = 'Deleted';
+$labels['flaganswered'] = 'Answered';
+$labels['flagflagged'] = 'Flagged';
+$labels['flagdraft'] = 'Draft';
+$labels['setvariable'] = 'Set variable';
+$labels['setvarname'] = 'Variable name:';
+$labels['setvarvalue'] = 'Variable value:';
+$labels['setvarmodifiers'] = 'Modifiers:';
+$labels['varlower'] = 'lower-case';
+$labels['varupper'] = 'upper-case';
+$labels['varlowerfirst'] = 'first character lower-case';
+$labels['varupperfirst'] = 'first character upper-case';
+$labels['varquotewildcard'] = 'quote special characters';
+$labels['varlength'] = 'length';
+$labels['notify'] = 'Send notification';
+$labels['notifyaddress'] = 'To e-mail address:';
+$labels['notifybody'] = 'Notification body:';
+$labels['notifysubject'] = 'Notification subject:';
+$labels['notifyfrom'] = 'Notification sender:';
+$labels['notifyimportance'] = 'Importance:';
+$labels['notifyimportancelow'] = 'low';
+$labels['notifyimportancenormal'] = 'normal';
+$labels['notifyimportancehigh'] = 'high';
+$labels['filtercreate'] = 'Create filter';
+$labels['usedata'] = 'Use following data in the filter:';
+$labels['nextstep'] = 'Next Step';
+$labels['...'] = '...';
+$labels['currdate'] = 'Current date';
+$labels['datetest'] = 'Date';
+$labels['dateheader'] = 'header:';
+$labels['year'] = 'year';
+$labels['month'] = 'month';
+$labels['day'] = 'day';
+$labels['date'] = 'date (yyyy-mm-dd)';
+$labels['julian'] = 'date (julian)';
+$labels['hour'] = 'hour';
+$labels['minute'] = 'minute';
+$labels['second'] = 'second';
+$labels['time'] = 'time (hh:mm:ss)';
+$labels['iso8601'] = 'date (ISO8601)';
+$labels['std11'] = 'date (RFC2822)';
+$labels['zone'] = 'time-zone';
+$labels['weekday'] = 'weekday (0-6)';
+$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)';
+$labels['index'] = 'index:';
+$labels['indexlast'] = 'backwards';
+
+$messages = array();
+$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['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['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['deactivated'] = 'Filter(s) disabled successfully.';
+$messages['activated'] = '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!';
+$messages['invaliddateformat'] = 'Invalid date or date part format';
+
+?>
diff --git a/plugins/managesieve/localization/lt_LT.inc b/plugins/managesieve/localization/lt_LT.inc
index fecd3d6bc..3b6f4eec4 100644
--- a/plugins/managesieve/localization/lt_LT.inc
+++ b/plugins/managesieve/localization/lt_LT.inc
@@ -55,7 +55,7 @@ $labels['add'] = 'PridÄ—ti';
$labels['del'] = 'Pašalinti';
$labels['sender'] = 'SiuntÄ—jas';
$labels['recipient'] = 'GavÄ—jas';
-$labels['vacationaddresses'] = 'Papildomas gavėjų adresų sąrašas (skirti kableliais):';
+$labels['vacationaddr'] = 'Papildomas gavėjų adresų sąrašas:';
$labels['vacationdays'] = 'Kaip dažnai išsiųsti laiškus (dienomis):';
$labels['vacationinterval'] = 'How often send messages:';
$labels['days'] = 'days';
diff --git a/plugins/managesieve/localization/lv_LV.inc b/plugins/managesieve/localization/lv_LV.inc
index f1f85c2e0..02b4eeffa 100644
--- a/plugins/managesieve/localization/lv_LV.inc
+++ b/plugins/managesieve/localization/lv_LV.inc
@@ -30,7 +30,7 @@ $labels['filteranyof'] = 'jÄatbilst jebkuram no sekojoÅ¡ajiem nosacÄ«jumiem';
$labels['filterany'] = 'visÄm vÄ“stulÄ“m';
$labels['filtercontains'] = 'satur';
$labels['filternotcontains'] = 'nesatur';
-$labels['filteris'] = 'vienÄds ar';
+$labels['filteris'] = 'ir vienÄds ar';
$labels['filterisnot'] = 'nav vienÄds ar';
$labels['filterexists'] = 'eksistē';
$labels['filternotexists'] = 'neeksistē';
@@ -46,20 +46,20 @@ $labels['messagemoveto'] = 'PÄrvietot vÄ“stuli uz';
$labels['messageredirect'] = 'PÄradresÄ“t vÄ“stuli uz';
$labels['messagecopyto'] = 'Kopēt vēstuli uz';
$labels['messagesendcopy'] = 'PÄrsÅ«tÄ«t vÄ“stules kopiju uz';
-$labels['messagereply'] = 'Atbildēt ar';
+$labels['messagereply'] = 'Atbildēt ar vēstuli';
$labels['messagedelete'] = 'Dzēst vēstuli';
$labels['messagediscard'] = 'Dzēst vēstuli un atbildēt';
$labels['messagesrules'] = 'IenÄkoÅ¡ajÄm vÄ“stulÄ“m:';
-$labels['messagesactions'] = 'IzpildÄ«t sekojoÅ¡Äs darbÄ«bas:';
+$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 vienu vai vairÄkus e-pastu(s), atdalot tos komatu:';
+$labels['vacationaddr'] = 'Mana(s) papildus e-pasta adrese(s):';
$labels['vacationdays'] = 'Cik dienu laikÄ vienam un tam paÅ¡am sÅ«tÄ«tÄjam neatbildÄ“t atkÄrtoti (piem., 7):';
-$labels['vacationinterval'] = 'How often send messages:';
-$labels['days'] = 'days';
-$labels['seconds'] = 'seconds';
+$labels['vacationinterval'] = 'Cik bieži sūtīt vēstules:';
+$labels['days'] = 'dienas';
+$labels['seconds'] = 'sekundes';
$labels['vacationreason'] = 'AtvaļinÄjuma paziņojuma teksts:';
$labels['vacationsubject'] = 'Vēstules tēma:';
$labels['rulestop'] = 'ApturÄ“t nosacÄ«jumu pÄrbaudi';
@@ -78,16 +78,16 @@ $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['countisgreaterthan'] = 'skaits ir lielÄks kÄ';
+$labels['countisgreaterthanequal'] = 'skaits ir vienÄds vai lielÄks kÄ';
+$labels['countislessthan'] = 'skaits ir mazÄks kÄ';
+$labels['countislessthanequal'] = 'skaits ir vienÄds vai mazÄks kÄ';
$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['valueisgreaterthan'] = 'vÄ“rtÄ«ba ir lielÄka kÄ';
+$labels['valueisgreaterthanequal'] = 'vÄ“rtÄ«ba ir vienÄda vai lielÄka kÄ';
+$labels['valueislessthan'] = 'vÄ“rtÄ«ba ir mazÄka kÄ';
+$labels['valueislessthanequal'] = 'vÄ“rtÄ«ba ir vienÄda vai mazÄka kÄ';
$labels['valueequals'] = 'vÄ“rtÄ«ba ir vienÄda ar';
$labels['valuenotequals'] = 'vÄ“rtÄ«ba nav vienÄda ar';
$labels['setflags'] = 'Marķēt vēstuli';
@@ -96,82 +96,101 @@ $labels['removeflags'] = 'Noņemt vēstulei marķierus';
$labels['flagread'] = 'Lasītas';
$labels['flagdeleted'] = 'Dzēstas';
$labels['flaganswered'] = 'Atbildētas';
-$labels['flagflagged'] = 'IezÄ«mÄ“tÄs';
+$labels['flagflagged'] = 'MarÄ·Ä“tas';
$labels['flagdraft'] = 'Melnraksts';
-$labels['setvariable'] = 'Set variable';
-$labels['setvarname'] = 'Variable name:';
-$labels['setvarvalue'] = 'Variable value:';
-$labels['setvarmodifiers'] = 'Modifiers:';
-$labels['varlower'] = 'lower-case';
-$labels['varupper'] = 'upper-case';
-$labels['varlowerfirst'] = 'first character lower-case';
-$labels['varupperfirst'] = 'first character upper-case';
-$labels['varquotewildcard'] = 'quote special characters';
-$labels['varlength'] = 'length';
-$labels['notify'] = 'Send notification';
-$labels['notifyaddress'] = 'To e-mail address:';
-$labels['notifybody'] = 'Notification body:';
-$labels['notifysubject'] = 'Notification subject:';
-$labels['notifyfrom'] = 'Notification sender:';
-$labels['notifyimportance'] = 'Importance:';
-$labels['notifyimportancelow'] = 'low';
-$labels['notifyimportancenormal'] = 'normal';
-$labels['notifyimportancehigh'] = 'high';
+$labels['setvariable'] = 'Iestatīt mainīgo';
+$labels['setvarname'] = 'MainÄ«gÄ nosaukums:';
+$labels['setvarvalue'] = 'MainÄ«gÄ vÄ“rtÄ«ba:';
+$labels['setvarmodifiers'] = 'Modifikatori:';
+$labels['varlower'] = 'mazie burti';
+$labels['varupper'] = 'lielie burti';
+$labels['varlowerfirst'] = 'pirmais burts kÄ mazais burts';
+$labels['varupperfirst'] = 'pirmais burts kÄ lielais burts';
+$labels['varquotewildcard'] = '"citÄ“t" speciÄlÄs rakstzÄ«mes';
+$labels['varlength'] = 'garums';
+$labels['notify'] = 'Sūtīt paziņojumus';
+$labels['notifyaddress'] = 'Uz e-pasta adresi:';
+$labels['notifybody'] = 'Paziņojuma teksts:';
+$labels['notifysubject'] = 'Paziņojuma tēma:';
+$labels['notifyfrom'] = 'Paziņojuma sÅ«tÄ«tÄjs:';
+$labels['notifyimportance'] = 'Svarīgums:';
+$labels['notifyimportancelow'] = 'zems';
+$labels['notifyimportancenormal'] = 'parasts';
+$labels['notifyimportancehigh'] = 'augsts';
$labels['filtercreate'] = 'Izveidot filtru';
$labels['usedata'] = 'FiltrÄ izmantot sekojoÅ¡us datus';
$labels['nextstep'] = 'NÄkamais solis';
$labels['...'] = '...';
-$labels['advancedopts'] = 'PaplaÅ¡inÄti iestatÄ«jumi';
+$labels['currdate'] = 'Pašreizējais datums';
+$labels['datetest'] = 'Datums';
+$labels['dateheader'] = 'galvene:';
+$labels['year'] = 'gads';
+$labels['month'] = 'mēnesis';
+$labels['day'] = 'diena';
+$labels['date'] = 'datums (gggg-mm-dd)';
+$labels['julian'] = 'datums (JÅ«lija kalendÄrs)';
+$labels['hour'] = 'stunda';
+$labels['minute'] = 'minūte';
+$labels['second'] = 'sekunde';
+$labels['time'] = 'laiks (hh:mm:ss)';
+$labels['iso8601'] = 'datums (ISO8601)';
+$labels['std11'] = 'datums (RFC2822)';
+$labels['zone'] = 'laikajosla';
+$labels['weekday'] = 'nedēļas diena (0-6)';
+$labels['advancedopts'] = 'PaplaÅ¡inÄtie iestatÄ«jumi';
$labels['body'] = 'Pamatteksts';
$labels['address'] = 'adresÄts';
$labels['envelope'] = 'aploksne';
$labels['modifier'] = 'modifikators:';
$labels['text'] = 'teksts';
-$labels['undecoded'] = 'neatkodēts (jēldati)';
+$labels['undecoded'] = 'neatkodÄ“ts (neapstrÄdÄti dati)';
$labels['contenttype'] = 'satura tips';
$labels['modtype'] = 'tips:';
$labels['allparts'] = 'viss';
$labels['domain'] = 'domēns';
-$labels['localpart'] = 'vietÄ“jÄ daļa';
+$labels['localpart'] = 'lokÄlÄ daļa';
$labels['user'] = 'lietotÄjs';
$labels['detail'] = 'detaļas';
-$labels['comparator'] = 'komparators';
-$labels['default'] = 'noklusējums';
-$labels['octet'] = 'strikti (oktets)';
+$labels['comparator'] = 'salÄ«dzinÄtÄjs';
+$labels['default'] = 'noklusÄ“tÄ vÄ“rtÄ«ba';
+$labels['octet'] = 'precīzs (oktets)';
$labels['asciicasemap'] = 'reģistrnejutīgs (ascii tabula)';
$labels['asciinumeric'] = 'skaitļu (ascii skaitļu)';
+$labels['index'] = 'indekss:';
+$labels['indexlast'] = '"backwards"';
$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['ruleexist'] = 'Filter with specified name already exists.';
-$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['activateerror'] = 'Unable to enable selected filter(s). Server error occured.';
-$messages['deactivateerror'] = 'Unable to disable selected filter(s). Server error occured.';
-$messages['deactivated'] = 'Filter(s) disabled successfully.';
-$messages['activated'] = 'Filter(s) enabled successfully.';
-$messages['moved'] = 'Filter moved successfully.';
-$messages['moveerror'] = 'Unable to move selected filter. Server error occured.';
-$messages['nametoolong'] = 'NeizdevÄs izveidot filtru kopu. PÄrÄk garÅ¡ kopas nosaukums';
-$messages['namereserved'] = 'Reserved name.';
-$messages['setexist'] = 'Set already exists.';
-$messages['nodata'] = 'At least one position must be selected!';
+$messages['filterunknownerror'] = 'NezinÄma servera kļūda.';
+$messages['filterconnerror'] = 'NeizdevÄs pieslÄ“gties ManageSieve serverim.';
+$messages['filterdeleteerror'] = 'NeizdevÄs izdzÄ“st filtru - servera kļūda.';
+$messages['filterdeleted'] = 'Filtrs veiksmīgi izdzēsts.';
+$messages['filtersaved'] = 'Filtrs veiksmÄ«gi saglabÄts.';
+$messages['filtersaveerror'] = 'NeizdevÄs saglabÄt filtru - servera kļūda.';
+$messages['filterdeleteconfirm'] = 'Vai JÅ«s tieÅ¡Äm vÄ“laties dzÄ“st atzÄ«mÄ“to filtru?';
+$messages['ruledeleteconfirm'] = 'Vai JÅ«s tieÅ¡Äm vÄ“laties dzÄ“st atzÄ«mÄ“to nosacÄ«jumu?';
+$messages['actiondeleteconfirm'] = 'Vai JÅ«s 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['ruleexist'] = 'Filtrs ar tÄdu nosaukumu jau pastÄv.';
+$messages['setactivateerror'] = 'NeizdevÄs aktivizÄ“t atzÄ«mÄ“to filtru kopu - servera kļūda.';
+$messages['setdeactivateerror'] = 'NeizdevÄs deaktivizÄ“t atzÄ«mÄ“to filtru kopu - servera kļūda.';
+$messages['setdeleteerror'] = 'NeizdevÄs izdzÄ“st atzÄ«mÄ“to filtru kopu - servera 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 JÅ«s vÄ“laties dzÄ“st atzÄ«mÄ“to filtru kopu?';
+$messages['setcreateerror'] = 'NeizdevÄs izveidot filtru kopu - servera kļūda.';
+$messages['setcreated'] = 'Filtru kopa veiksmīgi izveidota.';
+$messages['activateerror'] = 'Nav iespējams ieslēgt izvēlēto(s) filtru(s) - servera kļūda.';
+$messages['deactivateerror'] = 'Nav iespējams atslēgt izvēlēto(s) filtru(s) - servera kļūda.';
+$messages['deactivated'] = 'Filtrs(i) veiksmīgi atslēgts(i).';
+$messages['activated'] = 'Filtrs(i) veiksmīgi ieslēgts(i).';
+$messages['moved'] = 'Filtrs veiksmÄ«gi pÄrvietots.';
+$messages['moveerror'] = 'Nav iespÄ“jams pÄrvietot izvÄ“lÄ“to filtru - servera kļūda.';
+$messages['nametoolong'] = 'NeizdevÄs izveidot filtru kopu. PÄrÄk garÅ¡ kopas nosaukums.';
+$messages['namereserved'] = 'Rezervētais nosaukums.';
+$messages['setexist'] = 'Kopa jau eksistē.';
+$messages['nodata'] = 'Ir jÄbÅ«t atzÄ«mÄ“tai vismaz vienai pozÄ«cijai!';
+$messages['invaliddateformat'] = 'NederÄ«gs datums vai datuma formÄts';
?>
diff --git a/plugins/managesieve/localization/ml_IN.inc b/plugins/managesieve/localization/ml_IN.inc
index 67cd6829f..761b4305b 100644
--- a/plugins/managesieve/localization/ml_IN.inc
+++ b/plugins/managesieve/localization/ml_IN.inc
@@ -55,7 +55,6 @@ $labels['add'] = 'ചേരàµâ€à´•àµà´•àµ';
$labels['del'] = 'നീകàµà´•à´‚ ചെയàµà´¯àµà´•';
$labels['sender'] = 'അയചയാളàµâ€';
$labels['recipient'] = 'à´¸àµà´µàµ€à´•à´°àµâ€à´¤àµà´¤à´¾à´µàµ';
-$labels['vacationaddresses'] = 'à´¸àµà´µàµ€à´•à´°àµâ€à´¤àµà´¤à´¾à´µà´¿à´¨àµà´±àµ† ഇമെയിലàµâ€ വിലാസങàµà´™à´³àµà´Ÿàµ† അധികമàµà´³àµà´³ പടàµà´Ÿà´¿à´• (കോമയിടàµà´Ÿàµ തിരിചàµà´š)';
$labels['vacationdays'] = 'à´Žà´¤àµà´° ഭിവസം കൂടàµà´®àµà´ªàµ‹à´³àµâ€ സനàµà´¦àµ‡à´¶à´‚ അയകàµà´•à´£à´‚:';
$labels['vacationinterval'] = 'How often send messages:';
$labels['days'] = 'days';
diff --git a/plugins/managesieve/localization/mr_IN.inc b/plugins/managesieve/localization/mr_IN.inc
index 3339737e0..082ea9bc6 100644
--- a/plugins/managesieve/localization/mr_IN.inc
+++ b/plugins/managesieve/localization/mr_IN.inc
@@ -55,7 +55,7 @@ $labels['add'] = 'समावेश करा';
$labels['del'] = 'नषà¥à¤Ÿ करा';
$labels['sender'] = 'पà¥à¤°à¥‡à¤·à¤•';
$labels['recipient'] = 'Recipient';
-$labels['vacationaddresses'] = 'My additional e-mail addresse(s) (comma-separated):';
+$labels['vacationaddr'] = 'My additional e-mail addresse(s):';
$labels['vacationdays'] = 'How often send messages (in days):';
$labels['vacationinterval'] = 'How often send messages:';
$labels['days'] = 'days';
diff --git a/plugins/managesieve/localization/nb_NO.inc b/plugins/managesieve/localization/nb_NO.inc
index c2c17b23c..c3bf98f8b 100644
--- a/plugins/managesieve/localization/nb_NO.inc
+++ b/plugins/managesieve/localization/nb_NO.inc
@@ -55,7 +55,7 @@ $labels['add'] = 'Legg til';
$labels['del'] = 'Slett';
$labels['sender'] = 'Avsender';
$labels['recipient'] = 'Mottaker';
-$labels['vacationaddresses'] = 'Liste med mottakeradresser (adskilt med komma):';
+$labels['vacationaddr'] = 'Liste med mottakeradresser:';
$labels['vacationdays'] = 'Periode mellom meldinger (i dager):';
$labels['vacationinterval'] = 'Periode mellom meldinger:';
$labels['days'] = 'dager';
diff --git a/plugins/managesieve/localization/nl_NL.inc b/plugins/managesieve/localization/nl_NL.inc
index 1fd6eee4e..80c2274b1 100644
--- a/plugins/managesieve/localization/nl_NL.inc
+++ b/plugins/managesieve/localization/nl_NL.inc
@@ -55,7 +55,7 @@ $labels['add'] = 'Toevoegen';
$labels['del'] = 'Verwijderen';
$labels['sender'] = 'Afzender';
$labels['recipient'] = 'Ontvanger';
-$labels['vacationaddresses'] = 'Aanvullende lijst van geadresseerden (gescheiden met komma\'s):';
+$labels['vacationaddr'] = 'Aanvullende lijst van geadresseerden:';
$labels['vacationdays'] = 'Hoe vaak moet een bericht verstuurd worden (in dagen):';
$labels['vacationinterval'] = 'Hoe vaak moet een bericht verstuurd worden:';
$labels['days'] = 'dagen';
diff --git a/plugins/managesieve/localization/nn_NO.inc b/plugins/managesieve/localization/nn_NO.inc
index 69af8cde4..03563a72b 100644
--- a/plugins/managesieve/localization/nn_NO.inc
+++ b/plugins/managesieve/localization/nn_NO.inc
@@ -55,7 +55,7 @@ $labels['add'] = 'Legg til';
$labels['del'] = 'Slett';
$labels['sender'] = 'Avsendar';
$labels['recipient'] = 'Mottakar';
-$labels['vacationaddresses'] = 'Liste med mottakaradresser (komma-separert):';
+$labels['vacationaddr'] = 'Liste med mottakaradresser:';
$labels['vacationdays'] = 'Periode mellom meldingar (i dagar):';
$labels['vacationreason'] = 'Innhald (grunngjeving for fråvær)';
$labels['vacationsubject'] = 'Meldingsemne:';
diff --git a/plugins/managesieve/localization/pl_PL.inc b/plugins/managesieve/localization/pl_PL.inc
index f2ec96eb9..799f0fb54 100644
--- a/plugins/managesieve/localization/pl_PL.inc
+++ b/plugins/managesieve/localization/pl_PL.inc
@@ -55,11 +55,11 @@ $labels['add'] = 'Dodaj';
$labels['del'] = 'Usuń';
$labels['sender'] = 'Nadawca';
$labels['recipient'] = 'Odbiorca';
-$labels['vacationaddresses'] = 'Lista dodatkowych adresów odbiorców (oddzielonych przecinkami):';
+$labels['vacationaddr'] = 'Dodatkowy/e adres(y) e-mail:';
$labels['vacationdays'] = 'Częstotliwość wysyłania wiadomości (w dniach):';
-$labels['vacationinterval'] = 'How often send messages:';
-$labels['days'] = 'days';
-$labels['seconds'] = 'seconds';
+$labels['vacationinterval'] = 'Jak często wysyłać wiadomości:';
+$labels['days'] = 'dni';
+$labels['seconds'] = 'sekundy';
$labels['vacationreason'] = 'Treść (przyczyna nieobecności):';
$labels['vacationsubject'] = 'Temat wiadomości:';
$labels['rulestop'] = 'Przerwij przetwarzanie reguł';
@@ -83,13 +83,13 @@ $labels['countisgreaterthanequal'] = 'ilość jest równa lub większa od';
$labels['countislessthan'] = 'ilość jest mniejsza od';
$labels['countislessthanequal'] = 'ilość jest równa lub mniejsza od';
$labels['countequals'] = 'ilość jest równa';
-$labels['countnotequals'] = 'ilość jest różna od';
+$labels['countnotequals'] = 'ilość nie jest równa';
$labels['valueisgreaterthan'] = 'wartość jest większa od';
$labels['valueisgreaterthanequal'] = 'wartość jest równa lub większa od';
$labels['valueislessthan'] = 'wartość jest mniejsza od';
$labels['valueislessthanequal'] = 'wartość jest równa lub mniejsza od';
$labels['valueequals'] = 'wartość jest równa';
-$labels['valuenotequals'] = 'wartość jest różna od';
+$labels['valuenotequals'] = 'wartość nie jest równa';
$labels['setflags'] = 'Ustaw flagi wiadomości';
$labels['addflags'] = 'Dodaj flagi do wiadomości';
$labels['removeflags'] = 'Usuń flagi wiadomości';
@@ -121,6 +121,22 @@ $labels['filtercreate'] = 'Utwórz filtr';
$labels['usedata'] = 'Użyj następujących danych do utworzenia filtra:';
$labels['nextstep'] = 'Następny krok';
$labels['...'] = '...';
+$labels['currdate'] = 'Bieżąca data';
+$labels['datetest'] = 'Data';
+$labels['dateheader'] = 'nagłówek:';
+$labels['year'] = 'rok';
+$labels['month'] = 'miesiÄ…c';
+$labels['day'] = 'dzień';
+$labels['date'] = 'data (rrrr-mm-dd)';
+$labels['julian'] = 'data (kalendarz juliański)';
+$labels['hour'] = 'godzina';
+$labels['minute'] = 'minuta';
+$labels['second'] = 'sekunda';
+$labels['time'] = 'czas (gg:mm:ss)';
+$labels['iso8601'] = 'data (ISO8601)';
+$labels['std11'] = 'data (RFC2822)';
+$labels['zone'] = 'Strefa czasowa';
+$labels['weekday'] = 'dzień tygodnia (0-6)';
$labels['advancedopts'] = 'Zaawansowane opcje';
$labels['body'] = 'Treść';
$labels['address'] = 'adres';
@@ -140,6 +156,8 @@ $labels['default'] = 'domyślny';
$labels['octet'] = 'dokładny (octet)';
$labels['asciicasemap'] = 'nierozróżniający wielkości liter (ascii-casemap)';
$labels['asciinumeric'] = 'numeryczny (ascii-numeric)';
+$labels['index'] = 'indeks:';
+$labels['indexlast'] = 'wstecz';
$messages = array();
$messages['filterunknownerror'] = 'Nieznany błąd serwera.';
@@ -173,5 +191,6 @@ $messages['nametoolong'] = 'Zbyt długa nazwa.';
$messages['namereserved'] = 'Nazwa zarezerwowana.';
$messages['setexist'] = 'Zbiór już istnieje.';
$messages['nodata'] = 'Należy wybrać co najmniej jedną pozycję!';
+$messages['invaliddateformat'] = 'Nieprawidłowy format daty lub fragmentu daty';
?>
diff --git a/plugins/managesieve/localization/pt_BR.inc b/plugins/managesieve/localization/pt_BR.inc
index fb4699fd2..cd96c49ca 100644
--- a/plugins/managesieve/localization/pt_BR.inc
+++ b/plugins/managesieve/localization/pt_BR.inc
@@ -55,11 +55,11 @@ $labels['add'] = 'Adicionar';
$labels['del'] = 'Excluir';
$labels['sender'] = 'Remetente';
$labels['recipient'] = 'Destinatário';
-$labels['vacationaddresses'] = 'Lista adicional de e-mails destinatários (separado por vírgula):';
+$labels['vacationaddr'] = 'Meus endereços de e-mail adicionais:';
$labels['vacationdays'] = 'Enviar mensagens com que frequência (em dias):';
-$labels['vacationinterval'] = 'How often send messages:';
-$labels['days'] = 'days';
-$labels['seconds'] = 'seconds';
+$labels['vacationinterval'] = 'Como geralmente enviam mensagens:';
+$labels['days'] = 'dias';
+$labels['seconds'] = 'segundos';
$labels['vacationreason'] = 'Corpo da mensagem (motivo de férias):';
$labels['vacationsubject'] = 'Título da mensagem:';
$labels['rulestop'] = 'Parar de avaliar regras';
@@ -121,6 +121,22 @@ $labels['filtercreate'] = 'Criar filtro';
$labels['usedata'] = 'Usar os seguintes dados no filtro:';
$labels['nextstep'] = 'Próximo Passo';
$labels['...'] = '...';
+$labels['currdate'] = 'Data atual';
+$labels['datetest'] = 'Data';
+$labels['dateheader'] = 'cabeçalho:';
+$labels['year'] = 'ano';
+$labels['month'] = 'mês';
+$labels['day'] = 'dia';
+$labels['date'] = 'data (aaaa-mm-dd)';
+$labels['julian'] = 'data (calendário juliano)';
+$labels['hour'] = 'hora';
+$labels['minute'] = 'minuto';
+$labels['second'] = 'segundo';
+$labels['time'] = 'hora (hh:mm:ss)';
+$labels['iso8601'] = 'data (ISO8601)';
+$labels['std11'] = 'data (RFC2822)';
+$labels['zone'] = 'fuso horário';
+$labels['weekday'] = 'dia da semana (0-6)';
$labels['advancedopts'] = 'Opções avançadas';
$labels['body'] = 'Corpo';
$labels['address'] = 'endereço';
@@ -140,6 +156,8 @@ $labels['default'] = 'padrão';
$labels['octet'] = 'estrito (octeto)';
$labels['asciicasemap'] = 'caso insensível (mapa de caracteres ascii)';
$labels['asciinumeric'] = 'numérico (ascii-numeric)';
+$labels['index'] = 'índice:';
+$labels['indexlast'] = 'retroceder';
$messages = array();
$messages['filterunknownerror'] = 'Erro desconhecido de servidor';
@@ -173,5 +191,6 @@ $messages['nametoolong'] = 'Nome muito longo.';
$messages['namereserved'] = 'Nome reservado.';
$messages['setexist'] = 'Conjunto já existe.';
$messages['nodata'] = 'Pelo menos uma posição precisa ser selecionada!';
+$messages['invaliddateformat'] = 'Data inválida';
?>
diff --git a/plugins/managesieve/localization/pt_PT.inc b/plugins/managesieve/localization/pt_PT.inc
index bfb3f296a..f51e8bf5e 100644
--- a/plugins/managesieve/localization/pt_PT.inc
+++ b/plugins/managesieve/localization/pt_PT.inc
@@ -55,7 +55,7 @@ $labels['add'] = 'Adicionar';
$labels['del'] = 'Eliminar';
$labels['sender'] = 'Remetente';
$labels['recipient'] = 'Destinatário';
-$labels['vacationaddresses'] = 'Lista adicional de destinatários de e-mails (separados por vírgula):';
+$labels['vacationaddr'] = 'Lista adicional de destinatários de e-mails:';
$labels['vacationdays'] = 'Enviar mensagens com que frequência (em dias):';
$labels['vacationinterval'] = 'Com que frequência envia mensagens:';
$labels['days'] = 'dias';
diff --git a/plugins/managesieve/localization/ro_RO.inc b/plugins/managesieve/localization/ro_RO.inc
index 2c917cbdd..8d6e9c96f 100644
--- a/plugins/managesieve/localization/ro_RO.inc
+++ b/plugins/managesieve/localization/ro_RO.inc
@@ -55,7 +55,7 @@ $labels['add'] = 'Adaugă';
$labels['del'] = 'Șterge';
$labels['sender'] = 'Expeditor';
$labels['recipient'] = 'Destinatar';
-$labels['vacationaddresses'] = 'Adresele mele de e-mail adiționale (împărțite cu virgulă):';
+$labels['vacationaddr'] = 'Adresele mele de e-mail adiționale:';
$labels['vacationdays'] = 'Cât de des să trimit mesajele (în zile):';
$labels['vacationinterval'] = 'How often send messages:';
$labels['days'] = 'days';
diff --git a/plugins/managesieve/localization/ru_RU.inc b/plugins/managesieve/localization/ru_RU.inc
index b05074c22..f922bcf22 100644
--- a/plugins/managesieve/localization/ru_RU.inc
+++ b/plugins/managesieve/localization/ru_RU.inc
@@ -55,11 +55,11 @@ $labels['add'] = 'Добавить';
$labels['del'] = 'Удалить';
$labels['sender'] = 'Отправитель';
$labels['recipient'] = 'Получатель';
-$labels['vacationaddresses'] = 'СпиÑок моих дополнительных адреÑов (разделённых запÑтыми):';
+$labels['vacationaddr'] = 'Мои дополнительные адреÑа:';
$labels['vacationdays'] = 'Как чаÑто отправлÑÑ‚ÑŒ ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ (в днÑÑ…):';
-$labels['vacationinterval'] = 'How often send messages:';
-$labels['days'] = 'days';
-$labels['seconds'] = 'seconds';
+$labels['vacationinterval'] = 'Как чаÑто отправлÑÑ‚ÑŒ ÑообщениÑ:';
+$labels['days'] = 'дней';
+$labels['seconds'] = 'Ñекунд';
$labels['vacationreason'] = 'ТекÑÑ‚ ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ (причина отÑутÑтвиÑ):';
$labels['vacationsubject'] = 'Тема ÑообщениÑ:';
$labels['rulestop'] = 'Закончить выполнение';
@@ -121,6 +121,22 @@ $labels['filtercreate'] = 'Создать фильтр';
$labels['usedata'] = 'ИÑпользовать Ñледующие данные в фильтре:';
$labels['nextstep'] = 'Далее';
$labels['...'] = '...';
+$labels['currdate'] = 'Ð¢ÐµÐºÑƒÑ‰Ð°Ñ Ð´Ð°Ñ‚Ð°';
+$labels['datetest'] = 'Дата';
+$labels['dateheader'] = 'заголовок:';
+$labels['year'] = 'год';
+$labels['month'] = 'меÑÑц';
+$labels['day'] = 'день';
+$labels['date'] = 'дата (гггг-мм-дд)';
+$labels['julian'] = 'дата (юлианÑкаÑ)';
+$labels['hour'] = 'чаÑ';
+$labels['minute'] = 'минута';
+$labels['second'] = 'Ñекунда';
+$labels['time'] = 'Ð²Ñ€ÐµÐ¼Ñ (чч:мм:ÑÑ)';
+$labels['iso8601'] = 'дата (ISO8601)';
+$labels['std11'] = 'дата (RFC2822)';
+$labels['zone'] = 'чаÑовой поÑÑ';
+$labels['weekday'] = 'день недели (0-6)';
$labels['advancedopts'] = 'Дополнительные параметры';
$labels['body'] = 'Тело пиÑьма';
$labels['address'] = 'адреÑ';
@@ -140,6 +156,8 @@ $labels['default'] = 'по умолчанию';
$labels['octet'] = 'Строгий (octet)';
$labels['asciicasemap'] = 'РегиÑтронезавиÑимый (ascii-casemap)';
$labels['asciinumeric'] = 'ЧиÑловой (ascii-numeric)';
+$labels['index'] = 'индекÑ:';
+$labels['indexlast'] = 'наоборот';
$messages = array();
$messages['filterunknownerror'] = 'ÐеизвеÑÑ‚Ð½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ° Ñервера';
@@ -173,5 +191,6 @@ $messages['nametoolong'] = 'Ðевозможно Ñоздать набор фиÐ
$messages['namereserved'] = 'Зарезервированное имÑ.';
$messages['setexist'] = 'Ðабор уже ÑущеÑтвует.';
$messages['nodata'] = 'Ðужно выбрать Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ одну позицию!';
+$messages['invaliddateformat'] = 'ÐÐµÐ²ÐµÑ€Ð½Ð°Ñ Ð´Ð°Ñ‚Ð° или формат чаÑти даты';
?>
diff --git a/plugins/managesieve/localization/si_LK.inc b/plugins/managesieve/localization/si_LK.inc
index afc2e3851..378fcf15d 100644
--- a/plugins/managesieve/localization/si_LK.inc
+++ b/plugins/managesieve/localization/si_LK.inc
@@ -55,7 +55,6 @@ $labels['add'] = 'එක් කරන්න';
$labels['del'] = 'මකන්න';
$labels['sender'] = 'යවන්නà·';
$labels['recipient'] = 'ලබන්නà·';
-$labels['vacationaddresses'] = 'My additional e-mail addresse(s) (comma-separated):';
$labels['vacationdays'] = 'How often send messages (in days):';
$labels['vacationinterval'] = 'How often send messages:';
$labels['days'] = 'days';
diff --git a/plugins/managesieve/localization/sk_SK.inc b/plugins/managesieve/localization/sk_SK.inc
index f336cf2c5..9bfb2ef8f 100644
--- a/plugins/managesieve/localization/sk_SK.inc
+++ b/plugins/managesieve/localization/sk_SK.inc
@@ -55,7 +55,7 @@ $labels['add'] = 'Pridaj';
$labels['del'] = 'Zmaž';
$labels['sender'] = 'Odosielateľ';
$labels['recipient'] = 'Adresát';
-$labels['vacationaddresses'] = 'DodatoÄní príjemcovia správy (oddelení Äiarkami):';
+$labels['vacationaddr'] = 'DodatoÄní príjemcovia správy:';
$labels['vacationdays'] = 'PoÄet dní medzi odoslaním správy:';
$labels['vacationinterval'] = 'How often send messages:';
$labels['days'] = 'days';
diff --git a/plugins/managesieve/localization/sl_SI.inc b/plugins/managesieve/localization/sl_SI.inc
index f1c3b983b..aa82078f1 100644
--- a/plugins/managesieve/localization/sl_SI.inc
+++ b/plugins/managesieve/localization/sl_SI.inc
@@ -55,11 +55,11 @@ $labels['add'] = 'Dodaj';
$labels['del'] = 'Izbriši';
$labels['sender'] = 'Pošiljatelj';
$labels['recipient'] = 'Prejemnik';
-$labels['vacationaddresses'] = 'Dodaten seznam naslovov prejemnikov (loÄenih z vejico):';
+$labels['vacationaddr'] = 'Moji dodatni e-naslovi';
$labels['vacationdays'] = 'Kako pogosto naj bodo sporoÄila poslana (v dnevih):';
-$labels['vacationinterval'] = 'How often send messages:';
-$labels['days'] = 'days';
-$labels['seconds'] = 'seconds';
+$labels['vacationinterval'] = 'SporoÄila poÅ¡lji na:';
+$labels['days'] = 'dni';
+$labels['seconds'] = 'sekund';
$labels['vacationreason'] = 'Vsebina sporoÄila (vzrok za odsotnost):';
$labels['vacationsubject'] = 'Zadeva sporoÄila';
$labels['rulestop'] = 'Prekini z izvajanjem pravil';
@@ -83,13 +83,13 @@ $labels['countisgreaterthanequal'] = 'seÅ¡tevek je veÄji ali enak';
$labels['countislessthan'] = 'seštevek je manjši od';
$labels['countislessthanequal'] = 'seštevel je manjši ali enak';
$labels['countequals'] = 'seštevek je enak';
-$labels['countnotequals'] = 'seštevek ni enak';
+$labels['countnotequals'] = 'vsota ne ustreza';
$labels['valueisgreaterthan'] = 'vrednost je veÄja od';
$labels['valueisgreaterthanequal'] = 'vrednost je veÄja ali enaka';
$labels['valueislessthan'] = 'vrednost je manjša od';
$labels['valueislessthanequal'] = 'vrednost je manjša ali enaka';
$labels['valueequals'] = 'vrednost je enaka';
-$labels['valuenotequals'] = 'vrednost je neenaka';
+$labels['valuenotequals'] = 'vrednost ni enaka';
$labels['setflags'] = 'OznaÄi sporoÄilo';
$labels['addflags'] = 'OznaÄi sporoÄilo';
$labels['removeflags'] = 'Odstrani zaznamke s sporoÄil';
@@ -121,6 +121,22 @@ $labels['filtercreate'] = 'Ustvari filter';
$labels['usedata'] = 'Pri stvarjanju filtra uporabi naslednje podatke';
$labels['nextstep'] = 'Naslednji korak';
$labels['...'] = '...';
+$labels['currdate'] = 'Današnji datum';
+$labels['datetest'] = 'Datum';
+$labels['dateheader'] = 'glava:';
+$labels['year'] = 'leto';
+$labels['month'] = 'mesec';
+$labels['day'] = 'dan';
+$labels['date'] = 'datum(yyyy-mm-dd)';
+$labels['julian'] = 'datum (julijanski)';
+$labels['hour'] = 'ura';
+$labels['minute'] = 'minuta';
+$labels['second'] = 'sekunda';
+$labels['time'] = 'Äas';
+$labels['iso8601'] = 'datum (ISO8601)';
+$labels['std11'] = 'datum (RFC2822)';
+$labels['zone'] = 'Äasovni pas';
+$labels['weekday'] = 'dan v tednu (0-6)';
$labels['advancedopts'] = 'Dodatne možnosti';
$labels['body'] = 'Vsebina';
$labels['address'] = 'naslov';
@@ -140,6 +156,8 @@ $labels['default'] = 'privzeto';
$labels['octet'] = 'strict (octet)';
$labels['asciicasemap'] = 'ni obÄutljiv na velike/male Ärke (ascii-casemap)';
$labels['asciinumeric'] = 'numeriÄno (ascii-numeric)';
+$labels['index'] = 'indeks:';
+$labels['indexlast'] = 'obraten vrstni red';
$messages = array();
$messages['filterunknownerror'] = 'Prišlo je do neznane napake.';
@@ -173,5 +191,6 @@ $messages['nametoolong'] = 'Ime je predolgo.';
$messages['namereserved'] = 'Rezervirano ime.';
$messages['setexist'] = 'Nastavitev filtra že obstaja.';
$messages['nodata'] = 'Izbrana mora biti vsaj ena nastavitev!';
+$messages['invaliddateformat'] = 'Neveljaven datum ali oblika zapisa datuma';
?>
diff --git a/plugins/managesieve/localization/sv_SE.inc b/plugins/managesieve/localization/sv_SE.inc
index 49d5b1222..f2aeddd9f 100644
--- a/plugins/managesieve/localization/sv_SE.inc
+++ b/plugins/managesieve/localization/sv_SE.inc
@@ -55,7 +55,7 @@ $labels['add'] = 'Lägg till';
$labels['del'] = 'Ta bort';
$labels['sender'] = 'Avsändare';
$labels['recipient'] = 'Mottagare';
-$labels['vacationaddresses'] = 'Ytterligare mottagaradresser (avdelade med kommatecken)';
+$labels['vacationaddr'] = 'Ytterligare mottagaradresser:';
$labels['vacationdays'] = 'Antal dagar mellan auto-svar:';
$labels['vacationinterval'] = 'Tid mellan auto-svar:';
$labels['days'] = 'Dagar';
diff --git a/plugins/managesieve/localization/tr_TR.inc b/plugins/managesieve/localization/tr_TR.inc
index c36869d29..19bbb2e8e 100644
--- a/plugins/managesieve/localization/tr_TR.inc
+++ b/plugins/managesieve/localization/tr_TR.inc
@@ -55,8 +55,8 @@ $labels['add'] = 'Ekle';
$labels['del'] = 'Sil';
$labels['sender'] = 'Gönderici';
$labels['recipient'] = 'Alıcı';
-$labels['vacationaddresses'] = 'İlave e-posta adreslerim(virgül ile ayrılmış)';
-$labels['vacationdays'] = 'Ne sıklıkla mesajlar gönderilir(gün)';
+$labels['vacationaddr'] = 'Ä°lave e-posta adreslerim:';
+$labels['vacationdays'] = 'Ne sıklıkla mesajlar gönderilir(gün):';
$labels['vacationinterval'] = 'Ne kadar sıklıkla mesaj gönderirsiniz:';
$labels['days'] = 'günler';
$labels['seconds'] = 'saniyeler';
@@ -165,8 +165,8 @@ $messages['setcreateerror'] = 'Filtre setleri oluşturulamadı. Sunucuda hata ol
$messages['setcreated'] = 'Filtre setleri başarıyla oluşturuldu.';
$messages['activateerror'] = 'Seçilen filtre(ler) etkinleştirilemedi. Sunucuda hata oluştu.';
$messages['deactivateerror'] = 'Seçilen filtre(ler) pasifleştirilemedi. Sunucuda hata oluştu.';
-$messages['deactivated'] = 'Filtre(ler) başarıyla etkinleştirildi.';
-$messages['activated'] = 'Filtre(ler) başarıyla iptal edildi.';
+$messages['deactivated'] = 'Filtre(ler) başarıyla iptal edildi.';
+$messages['activated'] = 'Filtre(ler) başarıyla etkinleştirildi.';
$messages['moved'] = 'Filtre başarıyla taşındı.';
$messages['moveerror'] = 'Seçilen filtre(ler) taşınamadı. Sunucuda hata oluştu.';
$messages['nametoolong'] = 'İsim çok uzun.';
diff --git a/plugins/managesieve/localization/uk_UA.inc b/plugins/managesieve/localization/uk_UA.inc
index 41623df35..57cab9ea5 100644
--- a/plugins/managesieve/localization/uk_UA.inc
+++ b/plugins/managesieve/localization/uk_UA.inc
@@ -55,7 +55,7 @@ $labels['add'] = 'Додати';
$labels['del'] = 'Видалити';
$labels['sender'] = 'Відправник';
$labels['recipient'] = 'Отримувач';
-$labels['vacationaddresses'] = 'Додатковий ÑпиÑок Ð°Ð´Ñ€ÐµÑ Ð¾Ñ‚Ñ€Ð¸Ð¼ÑƒÐ²Ð°Ñ‡Ñ–Ð² (розділених комою)';
+$labels['vacationaddr'] = 'Додатковий ÑпиÑок Ð°Ð´Ñ€ÐµÑ Ð¾Ñ‚Ñ€Ð¸Ð¼ÑƒÐ²Ð°Ñ‡Ñ–Ð²:';
$labels['vacationdays'] = 'Як чаÑто повторювати (у днÑÑ…):';
$labels['vacationinterval'] = 'How often send messages:';
$labels['days'] = 'days';
diff --git a/plugins/managesieve/localization/vi_VN.inc b/plugins/managesieve/localization/vi_VN.inc
index 8d6fcd348..6e65cccf5 100644
--- a/plugins/managesieve/localization/vi_VN.inc
+++ b/plugins/managesieve/localization/vi_VN.inc
@@ -55,7 +55,7 @@ $labels['add'] = 'Thêm';
$labels['del'] = 'Xoá';
$labels['sender'] = 'NgÆ°á»i gá»­i';
$labels['recipient'] = 'NgÆ°á»i nhận';
-$labels['vacationaddresses'] = 'Äịa chỉ email bổ sung của tôi ( phân cách bằng dấu phẩy)';
+$labels['vacationaddr'] = 'Äịa chỉ email bổ sung của tôi';
$labels['vacationdays'] = 'Số lần gửi thư (trong ngày)';
$labels['vacationreason'] = 'Nội dung chính';
$labels['vacationsubject'] = 'Tiêu đỠthư';
diff --git a/plugins/managesieve/localization/zh_CN.inc b/plugins/managesieve/localization/zh_CN.inc
index 79b705c54..106fb40fc 100644
--- a/plugins/managesieve/localization/zh_CN.inc
+++ b/plugins/managesieve/localization/zh_CN.inc
@@ -55,7 +55,7 @@ $labels['add'] = '添加';
$labels['del'] = '删除';
$labels['sender'] = 'å‘件人';
$labels['recipient'] = '收件人';
-$labels['vacationaddresses'] = '收件人地å€çš„附加åå•ï¼ˆä»¥åŠè§’逗å·åˆ†éš”)';
+$labels['vacationaddr'] = '收件人地å€çš„附加åå•';
$labels['vacationdays'] = 'å‘é€é‚®ä»¶é¢‘率(å•ä½ï¼šå¤©):';
$labels['vacationinterval'] = 'How often send messages:';
$labels['days'] = 'days';
diff --git a/plugins/managesieve/localization/zh_TW.inc b/plugins/managesieve/localization/zh_TW.inc
index 3f3fc1313..047ebcccc 100644
--- a/plugins/managesieve/localization/zh_TW.inc
+++ b/plugins/managesieve/localization/zh_TW.inc
@@ -55,7 +55,7 @@ $labels['add'] = '新增';
$labels['del'] = '刪除';
$labels['sender'] = '寄件者';
$labels['recipient'] = '收件者';
-$labels['vacationaddresses'] = '其他收件者(用åŠå½¢é€—號隔開):';
+$labels['vacationaddr'] = '其他收件者:';
$labels['vacationdays'] = '多久回覆一次(單ä½ï¼šå¤©ï¼‰ï¼š';
$labels['vacationinterval'] = 'How often send messages:';
$labels['days'] = 'days';
diff --git a/plugins/managesieve/managesieve.js b/plugins/managesieve/managesieve.js
index 04b9a76af..5201284fa 100644
--- a/plugins/managesieve/managesieve.js
+++ b/plugins/managesieve/managesieve.js
@@ -55,6 +55,11 @@ if (window.rcmail) {
}
$('input[type="text"]:first', rcmail.gui_objects.sieveform).focus();
+
+ // initialize smart list inputs
+ $('textarea[data-type="list"]', rcmail.gui_objects.sieveform).each(function() {
+ smart_field_init(this);
+ });
}
else {
rcmail.enable_command('plugin.managesieve-add', 'plugin.managesieve-setadd', !rcmail.env.sieveconnerror);
@@ -258,7 +263,7 @@ rcube_webmail.prototype.managesieve_updatelist = function(action, o)
var i, row = $('#rcmrow'+this.managesieve_rowid(o.id));
if (o.name)
- $('td', row).html(o.name);
+ $('td', row).text(o.name);
if (o.disabled)
row.addClass('disabled');
else
@@ -273,7 +278,7 @@ rcube_webmail.prototype.managesieve_updatelist = function(action, o)
var list = this.filters_list,
row = $('<tr><td class="name"></td></tr>');
- $('td', row).html(o.name);
+ $('td', row).text(o.name);
row.attr('id', 'rcmrow'+o.id);
if (o.disabled)
row.addClass('disabled');
@@ -297,7 +302,7 @@ rcube_webmail.prototype.managesieve_updatelist = function(action, o)
tr = document.createElement('TR');
td = document.createElement('TD');
- td.innerHTML = el.name;
+ $(td).text(el.name);
td.className = 'name';
tr.id = 'rcmrow' + el.id;
if (el['class'])
@@ -346,7 +351,7 @@ rcube_webmail.prototype.managesieve_updatelist = function(action, o)
list = this.filtersets_list,
row = $('<tr class="disabled"><td class="name"></td></tr>');
- $('td', row).html(o.name);
+ $('td', row).text(o.name);
row.attr('id', 'rcmrow'+id);
this.env.filtersets[id] = o.name;
@@ -469,6 +474,11 @@ rcube_webmail.prototype.managesieve_rulefill = function(content, id, after)
row.className = 'rulerow';
row.innerHTML = content;
+ // initialize smart list inputs
+ $('textarea[data-type="list"]', row).each(function() {
+ smart_field_init(this);
+ });
+
this.managesieve_formbuttons(div);
}
};
@@ -565,40 +575,45 @@ 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 + '_list'),
mod = document.getElementById('rule_mod' + id),
trans = document.getElementById('rule_trans' + id),
- comp = document.getElementById('rule_comp' + id);
+ comp = document.getElementById('rule_comp' + id),
+ datepart = document.getElementById('rule_date_part' + id),
+ dateheader = document.getElementById('rule_date_header_div' + id),
+ h = obj.value;
- if (obj.value == 'size') {
+ if (h == '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';
+ $.each([op, header, mod, trans, comp], function() { this.style.display = 'none'; });
}
else {
- header.style.display = obj.value != '...' ? 'none' : 'inline';
+ header.style.display = h != '...' ? 'none' : 'inline-block';
size.style.display = 'none';
op.style.display = 'inline';
comp.style.display = '';
- rule_op_select(id);
- mod.style.display = obj.value == 'body' ? 'none' : 'block';
- trans.style.display = obj.value == 'body' ? 'block' : 'none';
+ mod.style.display = h == 'body' || h == 'currentdate' || h == 'date' ? 'none' : 'block';
+ trans.style.display = h == 'body' ? 'block' : 'none';
}
- obj.style.width = obj.value == '...' ? '40px' : '';
+ if (datepart)
+ datepart.style.display = h == 'currentdate' || h == 'date' ? 'inline' : 'none';
+ if (dateheader)
+ dateheader.style.display = h == 'date' ? '' : 'none';
+
+ rule_op_select(op, id, h);
+ rule_mod_select(id, h);
+ obj.style.width = h == '...' ? '40px' : '';
};
-function rule_op_select(id)
+function rule_op_select(obj, id, header)
{
- var obj = document.getElementById('rule_op' + id),
- target = document.getElementById('rule_target' + id);
+ var target = document.getElementById('rule_target' + id + '_list');
- target.style.display = obj.value == 'exists' || obj.value == 'notexists' ? 'none' : 'inline';
+ if (!header)
+ header = document.getElementById('header' + id).value;
+
+ target.style.display = obj.value == 'exists' || obj.value == 'notexists' || header == 'size' ? 'none' : 'inline-block';
};
function rule_trans_select(id)
@@ -609,12 +624,19 @@ function rule_trans_select(id)
target.style.display = obj.value != 'content' ? 'none' : 'inline';
};
-function rule_mod_select(id)
+function rule_mod_select(id, header)
{
var obj = document.getElementById('rule_mod_op' + id),
- target = document.getElementById('rule_mod_type' + id);
+ target = document.getElementById('rule_mod_type' + id),
+ index = document.getElementById('rule_index_div' + id);
+
+ if (!header)
+ header = document.getElementById('header' + id).value;
target.style.display = obj.value != 'address' && obj.value != 'envelope' ? 'none' : 'inline';
+
+ if (index)
+ index.style.display = header != 'body' && header != 'currentdate' && header != 'size' && obj.value != 'envelope' ? '' : 'none';
};
function rule_join_radio(value)
@@ -638,8 +660,9 @@ function rule_adv_switch(id, elem)
function action_type_select(id)
{
+console.log(id);
var obj = document.getElementById('action_type' + id),
- enabled = {},
+ v = obj.value, enabled = {},
elems = {
mailbox: document.getElementById('action_mailbox' + id),
target: document.getElementById('action_target' + id),
@@ -650,25 +673,25 @@ function action_type_select(id)
notify: document.getElementById('action_notify' + id)
};
- if (obj.value == 'fileinto' || obj.value == 'fileinto_copy') {
+ if (v == 'fileinto' || v == 'fileinto_copy') {
enabled.mailbox = 1;
}
- else if (obj.value == 'redirect' || obj.value == 'redirect_copy') {
+ else if (v == 'redirect' || v == 'redirect_copy') {
enabled.target = 1;
}
- else if (obj.value.match(/^reject|ereject$/)) {
+ else if (v.match(/^reject|ereject$/)) {
enabled.target_area = 1;
}
- else if (obj.value.match(/^(add|set|remove)flag$/)) {
+ else if (v.match(/^(add|set|remove)flag$/)) {
enabled.flags = 1;
}
- else if (obj.value == 'vacation') {
+ else if (v == 'vacation') {
enabled.vacation = 1;
}
- else if (obj.value == 'set') {
+ else if (v == 'set') {
enabled.set = 1;
}
- else if (obj.value == 'notify') {
+ else if (v == 'notify') {
enabled.notify = 1;
}
@@ -677,6 +700,72 @@ function action_type_select(id)
}
};
+// Inititalizes smart list input
+function smart_field_init(field)
+{
+ var id = field.id + '_list',
+ area = $('<span class="listarea"></span>'),
+ list = field.value ? field.value.split("\n") : [''];
+
+ if ($('#'+id).length)
+ return;
+
+ // add input rows
+ $.each(list, function(i, v) {
+ area.append(smart_field_row(v, field.name, i, $(field).data('size')));
+ });
+
+ area.attr('id', id);
+ field = $(field);
+
+ if (field.attr('disabled'))
+ area.hide();
+
+ field.after(area);
+
+ if (field.hasClass('error')) {
+ area.addClass('error');
+ rcmail.managesieve_tip_register([[id, field.data('tip')]]);
+ }
+};
+
+function smart_field_row(value, name, idx, size)
+{
+ // build row element content
+ var input, content = '<span class="listelement">'
+ + '<span class="reset"></span><input type="text"></span>',
+ elem = $(content),
+ attrs = {value: value, name: name + '[]'};
+
+ if (size)
+ attrs.size = size;
+
+ input = $('input', elem).attr(attrs).keydown(function(e) {
+ var input = $(this);
+ // element creation event (on Enter)
+ if (e.which == 13) {
+ var name = input.attr('name').replace(/\[\]$/, ''),
+ dt = (new Date()).getTime(),
+ elem = smart_field_row('', name, dt, size);
+
+ input.parent().after(elem);
+ $('input', elem).focus();
+ }
+ });
+
+ // element deletion event
+ $('span[class="reset"]', elem).click(function() {
+ var span = $(this.parentNode);
+
+ if (span.parent().children().length > 1)
+ span.remove();
+ else
+ $('input', span).val('').focus();
+ });
+
+ return elem;
+}
+
// Register onmouse(leave/enter) events for tips on specified form element
rcube_webmail.prototype.managesieve_tip_register = function(tips)
{
@@ -685,25 +774,26 @@ 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(),
- left = offset.left,
- top = offset.top - 12,
- minwidth = $(this).width();
-
- 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, minWidth: (minwidth-2) + 'px'}).show();
- })
- .bind('mouseleave', function(e) { tip.hide(); });
+ .data('tip', tips[n][1])
+ .bind('mouseenter', function(e) {
+ var elem = $(this),
+ offset = elem.offset(),
+ left = offset.left,
+ top = offset.top - 12,
+ minwidth = elem.width();
+
+ if (framed) {
+ offset = $((rcmail.env.task == 'mail' ? '#sievefilterform > iframe' : '#filter-box'), parent.document).offset();
+ top += offset.top;
+ left += offset.left;
+ }
+
+ tip.html(elem.data('tip'));
+ top -= tip.height();
+
+ tip.css({left: left, top: top, minWidth: (minwidth-2) + 'px'}).show();
+ })
+ .bind('mouseleave', function(e) { tip.hide(); });
}
};
diff --git a/plugins/managesieve/managesieve.php b/plugins/managesieve/managesieve.php
index f451a810e..6970193c2 100644
--- a/plugins/managesieve/managesieve.php
+++ b/plugins/managesieve/managesieve.php
@@ -12,60 +12,28 @@
*
* Configuration (see config.inc.php.dist)
*
- * Copyright (C) 2008-2012, The Roundcube Dev Team
- * Copyright (C) 2011-2012, Kolab Systems AG
+ * Copyright (C) 2008-2013, The Roundcube Dev Team
+ * Copyright (C) 2011-2013, 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 free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
* 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.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
*/
class managesieve extends rcube_plugin
{
public $task = 'mail|settings';
-
private $rc;
- private $sieve;
- private $errors;
- private $form;
- private $tips = array();
- private $script = array();
- private $exts = array();
- private $list;
- private $active = array();
- private $headers = array(
- '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 = '6.2';
- const PROGNAME = 'Roundcube (Managesieve)';
- const PORT = 4190;
-
+ private $engine;
function init()
{
@@ -92,10 +60,11 @@ class managesieve extends rcube_plugin
/**
* Initializes plugin's UI (localization, js script)
*/
- private function init_ui()
+ function init_ui()
{
- if ($this->ui_initialized)
+ if ($this->ui_initialized) {
return;
+ }
// load localization
$this->add_texts('localization/', array('filters','managefilters'));
@@ -185,352 +154,18 @@ class managesieve extends rcube_plugin
}
/**
- * Loads configuration, initializes plugin (including sieve connection)
+ * Plugin action handler
*/
- function managesieve_start()
- {
- $this->load_config();
-
- // register UI objects
- $this->rc->output->add_handlers(array(
- 'filterslist' => array($this, 'filters_list'),
- 'filtersetslist' => array($this, 'filtersets_list'),
- 'filterframe' => array($this, 'filter_frame'),
- 'filterform' => array($this, 'filter_form'),
- 'filtersetform' => array($this, 'filterset_form'),
- ));
-
- // Add include path for internal classes
- $include_path = $this->home . '/lib' . PATH_SEPARATOR;
- $include_path .= ini_get('include_path');
- set_include_path($include_path);
-
- // Get connection parameters
- $host = $this->rc->config->get('managesieve_host', 'localhost');
- $port = $this->rc->config->get('managesieve_port');
- $tls = $this->rc->config->get('managesieve_usetls', false);
-
- $host = rcube_utils::parse_host($host);
- $host = rcube_utils::idn_to_ascii($host);
-
- // remove tls:// prefix, set TLS flag
- if (($host = preg_replace('|^tls://|i', '', $host, 1, $cnt)) && $cnt) {
- $tls = true;
- }
-
- if (empty($port)) {
- $port = getservbyname('sieve', 'tcp');
- if (empty($port)) {
- $port = self::PORT;
- }
- }
-
- $plugin = $this->rc->plugins->exec_hook('managesieve_connect', array(
- 'user' => $_SESSION['username'],
- 'password' => $this->rc->decrypt($_SESSION['password']),
- 'host' => $host,
- 'port' => $port,
- 'usetls' => $tls,
- 'auth_type' => $this->rc->config->get('managesieve_auth_type'),
- '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
- $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())) {
- // Get list of scripts
- $list = $this->list_scripts();
-
- if (!empty($_GET['_set']) || !empty($_POST['_set'])) {
- $script_name = rcube_utils::get_input_value('_set', rcube_utils::INPUT_GPC, true);
- }
- else if (!empty($_SESSION['managesieve_current'])) {
- $script_name = $_SESSION['managesieve_current'];
- }
- else {
- // get (first) active script
- if (!empty($this->active[0])) {
- $script_name = $this->active[0];
- }
- else if ($list) {
- $script_name = $list[0];
- }
- // create a new (initial) script
- else {
- // if script not exists build default script contents
- $script_file = $this->rc->config->get('managesieve_default');
- $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);
-
- // 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) {
- $this->sieve->load($script_name);
- }
-
- $error = $this->sieve->error();
- }
-
- // finally set script objects
- if ($error) {
- switch ($error) {
- case SIEVE_ERROR_CONNECTION:
- case SIEVE_ERROR_LOGIN:
- $this->rc->output->show_message('managesieve.filterconnerror', 'error');
- break;
- default:
- $this->rc->output->show_message('managesieve.filterunknownerror', 'error');
- break;
- }
-
- rcube::raise_error(array('code' => 403, 'type' => 'php',
- 'file' => __FILE__, 'line' => __LINE__,
- 'message' => "Unable to connect to managesieve on $host:$port"), true, false);
-
- // to disable 'Add filter' button set env variable
- $this->rc->output->set_env('filterconnerror', true);
- $this->script = array();
- }
- else {
- $this->exts = $this->sieve->get_extensions();
- $this->script = $this->sieve->script->as_array();
- $this->rc->output->set_env('currentset', $this->sieve->current);
- $_SESSION['managesieve_current'] = $this->sieve->current;
- }
-
- return $error;
- }
-
function managesieve_actions()
{
$this->init_ui();
-
- $error = $this->managesieve_start();
-
- // Handle user requests
- if ($action = rcube_utils::get_input_value('_act', rcube_utils::INPUT_GPC)) {
- $fid = (int) rcube_utils::get_input_value('_fid', rcube_utils::INPUT_POST);
-
- if ($action == 'delete' && !$error) {
- if (isset($this->script[$fid])) {
- if ($this->sieve->script->delete_rule($fid))
- $result = $this->save_script();
-
- 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 == 'move' && !$error) {
- if (isset($this->script[$fid])) {
- $to = (int) rcube_utils::get_input_value('_to', rcube_utils::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) {
- $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 {
- $this->rc->output->show_message('managesieve.moveerror', 'error');
- }
- }
- }
- else if ($action == 'act' && !$error) {
- if (isset($this->script[$fid])) {
- $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 ($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 {
- 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) {
- $script_name = rcube_utils::get_input_value('_set', rcube_utils::INPUT_GPC, true);
- $result = $this->activate_script($script_name);
- $kep14 = $this->rc->config->get('managesieve_kolab_master');
-
- if ($result === true) {
- $this->rc->output->set_env('active_sets', $this->active);
- $this->rc->output->show_message('managesieve.setactivated', 'confirmation');
- $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) {
- $script_name = rcube_utils::get_input_value('_set', rcube_utils::INPUT_GPC, true);
- $result = $this->deactivate_script($script_name);
-
- if ($result === true) {
- $this->rc->output->set_env('active_sets', $this->active);
- $this->rc->output->show_message('managesieve.setdeactivated', 'confirmation');
- $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) {
- $script_name = rcube_utils::get_input_value('_set', rcube_utils::INPUT_GPC, true);
- $result = $this->remove_script($script_name);
-
- if ($result === true) {
- $this->rc->output->show_message('managesieve.setdeleted', 'confirmation');
- $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') {
- $script_name = rcube_utils::get_input_value('_set', rcube_utils::INPUT_GPC, true);
- $script = $this->sieve->get_script($script_name);
-
- if (PEAR::isError($script))
- exit;
-
- $browser = new rcube_browser;
-
- // send download headers
- header("Content-Type: application/octet-stream");
- header("Content-Length: ".strlen($script));
-
- if ($browser->ie)
- header("Content-Type: application/force-download");
- if ($browser->ie && $browser->ver < 7)
- $filename = rawurlencode(abbreviate_string($script_name, 55));
- else if ($browser->ie)
- $filename = rawurlencode($script_name);
- else
- $filename = addcslashes($script_name, '\\"');
-
- header("Content-Disposition: attachment; filename=\"$filename.txt\"");
- echo $script;
- exit;
- }
- else if ($action == 'list') {
- $result = $this->list_rules();
-
- $this->rc->output->command('managesieve_updatelist', 'list', array('list' => $result));
- }
- else if ($action == 'ruleadd') {
- $rid = rcube_utils::get_input_value('_rid', rcube_utils::INPUT_GPC);
- $id = $this->genid();
- $content = $this->rule_div($fid, $id, false);
-
- $this->rc->output->command('managesieve_rulefill', $content, $id, $rid);
- }
- else if ($action == 'actionadd') {
- $aid = rcube_utils::get_input_value('_aid', rcube_utils::INPUT_GPC);
- $id = $this->genid();
- $content = $this->action_div($fid, $id, false);
-
- $this->rc->output->command('managesieve_actionfill', $content, $id, $aid);
- }
-
- $this->rc->output->send();
- }
- else if ($this->rc->task == 'mail') {
- // Initialize the form
- $rules = rcube_utils::get_input_value('r', rcube_utils::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();
+ $engine = $this->get_engine();
+ $engine->actions();
}
+ /**
+ * Forms save action handler
+ */
function managesieve_save()
{
// load localization
@@ -541,1524 +176,26 @@ class managesieve extends rcube_plugin
$this->include_script('managesieve.js');
}
- // Init plugin and handle managesieve connection
- $error = $this->managesieve_start();
-
- // get request size limits (#1488648)
- $max_post = max(array(
- ini_get('max_input_vars'),
- ini_get('suhosin.request.max_vars'),
- ini_get('suhosin.post.max_vars'),
- ));
- $max_depth = max(array(
- ini_get('suhosin.request.max_array_depth'),
- ini_get('suhosin.post.max_array_depth'),
- ));
-
- // check request size limit
- if ($max_post && count($_POST, COUNT_RECURSIVE) >= $max_post) {
- rcube::raise_error(array(
- 'code' => 500, 'type' => 'php',
- 'file' => __FILE__, 'line' => __LINE__,
- 'message' => "Request size limit exceeded (one of max_input_vars/suhosin.request.max_vars/suhosin.post.max_vars)"
- ), true, false);
- $this->rc->output->show_message('managesieve.filtersaveerror', 'error');
- }
- // check request depth limits
- else if ($max_depth && count($_POST['_header']) > $max_depth) {
- rcube::raise_error(array(
- 'code' => 500, 'type' => 'php',
- 'file' => __FILE__, 'line' => __LINE__,
- 'message' => "Request size limit exceeded (one of suhosin.request.max_array_depth/suhosin.post.max_array_depth)"
- ), true, false);
- $this->rc->output->show_message('managesieve.filtersaveerror', 'error');
- }
- // filters set add action
- else if (!empty($_POST['_newset'])) {
- $name = rcube_utils::get_input_value('_name', rcube_utils::INPUT_POST, true);
- $copy = rcube_utils::get_input_value('_copy', rcube_utils::INPUT_POST, true);
- $from = rcube_utils::get_input_value('_from', rcube_utils::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'])) {
- $file = file_get_contents($_FILES['_file']['tmp_name']);
- $file = preg_replace('/\r/', '', $file);
- // for security don't save script directly
- // check syntax before, like this...
- $this->sieve->load_script($file);
- if (!$this->save_script($name)) {
- $this->errors['file'] = $this->gettext('setcreateerror');
- }
- }
- else { // upload failed
- $err = $_FILES['_file']['error'];
-
- if ($err == UPLOAD_ERR_INI_SIZE || $err == UPLOAD_ERR_FORM_SIZE) {
- $msg = $this->rc->gettext(array('name' => 'filesizeerror',
- 'vars' => array('size' =>
- $this->rc->show_bytes(parse_bytes(ini_get('upload_max_filesize'))))));
- }
- else {
- $this->errors['file'] = $this->gettext('fileuploaderror');
- }
- }
- }
- else if (!$this->sieve->copy($name, $from == 'set' ? $copy : '')) {
- $error = 'managesieve.setcreateerror';
- }
-
- 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->command('parent.managesieve_updatelist', 'setadd',
- array('name' => $name, 'index' => $index));
- } else if ($msg) {
- $this->rc->output->command('display_message', $msg, 'error');
- } else if ($error) {
- $this->rc->output->show_message($error, 'error');
- }
- }
- // filter add/edit action
- else if (isset($_POST['_name'])) {
- $name = trim(rcube_utils::get_input_value('_name', rcube_utils::INPUT_POST, true));
- $fid = trim(rcube_utils::get_input_value('_fid', rcube_utils::INPUT_POST));
- $join = trim(rcube_utils::get_input_value('_join', rcube_utils::INPUT_POST));
-
- // and arrays
- $headers = rcube_utils::get_input_value('_header', rcube_utils::INPUT_POST);
- $cust_headers = rcube_utils::get_input_value('_custom_header', rcube_utils::INPUT_POST);
- $ops = rcube_utils::get_input_value('_rule_op', rcube_utils::INPUT_POST);
- $sizeops = rcube_utils::get_input_value('_rule_size_op', rcube_utils::INPUT_POST);
- $sizeitems = rcube_utils::get_input_value('_rule_size_item', rcube_utils::INPUT_POST);
- $sizetargets = rcube_utils::get_input_value('_rule_size_target', rcube_utils::INPUT_POST);
- $targets = rcube_utils::get_input_value('_rule_target', rcube_utils::INPUT_POST, true);
- $mods = rcube_utils::get_input_value('_rule_mod', rcube_utils::INPUT_POST);
- $mod_types = rcube_utils::get_input_value('_rule_mod_type', rcube_utils::INPUT_POST);
- $body_trans = rcube_utils::get_input_value('_rule_trans', rcube_utils::INPUT_POST);
- $body_types = rcube_utils::get_input_value('_rule_trans_type', rcube_utils::INPUT_POST, true);
- $comparators = rcube_utils::get_input_value('_rule_comp', rcube_utils::INPUT_POST);
- $act_types = rcube_utils::get_input_value('_action_type', rcube_utils::INPUT_POST, true);
- $mailboxes = rcube_utils::get_input_value('_action_mailbox', rcube_utils::INPUT_POST, true);
- $act_targets = rcube_utils::get_input_value('_action_target', rcube_utils::INPUT_POST, true);
- $area_targets = rcube_utils::get_input_value('_action_target_area', rcube_utils::INPUT_POST, true);
- $reasons = rcube_utils::get_input_value('_action_reason', rcube_utils::INPUT_POST, true);
- $addresses = rcube_utils::get_input_value('_action_addresses', rcube_utils::INPUT_POST, true);
- $intervals = rcube_utils::get_input_value('_action_interval', rcube_utils::INPUT_POST);
- $interval_types = rcube_utils::get_input_value('_action_interval_type', rcube_utils::INPUT_POST);
- $subject = rcube_utils::get_input_value('_action_subject', rcube_utils::INPUT_POST, true);
- $flags = rcube_utils::get_input_value('_action_flags', rcube_utils::INPUT_POST);
- $varnames = rcube_utils::get_input_value('_action_varname', rcube_utils::INPUT_POST);
- $varvalues = rcube_utils::get_input_value('_action_varvalue', rcube_utils::INPUT_POST);
- $varmods = rcube_utils::get_input_value('_action_varmods', rcube_utils::INPUT_POST);
- $notifyaddrs = rcube_utils::get_input_value('_action_notifyaddress', rcube_utils::INPUT_POST);
- $notifybodies = rcube_utils::get_input_value('_action_notifybody', rcube_utils::INPUT_POST);
- $notifymessages = rcube_utils::get_input_value('_action_notifymessage', rcube_utils::INPUT_POST);
- $notifyfrom = rcube_utils::get_input_value('_action_notifyfrom', rcube_utils::INPUT_POST);
- $notifyimp = rcube_utils::get_input_value('_action_notifyimportance', rcube_utils::INPUT_POST);
-
- // we need a "hack" for radiobuttons
- foreach ($sizeitems as $item)
- $items[] = $item;
-
- $this->form['disabled'] = $_POST['_disabled'] ? true : false;
- $this->form['join'] = $join=='allof' ? true : false;
- $this->form['name'] = $name;
- $this->form['tests'] = array();
- $this->form['actions'] = array();
-
- if ($name == '')
- $this->errors['name'] = $this->gettext('cannotbeempty');
- else {
- foreach($this->script as $idx => $rule)
- if($rule['name'] == $name && $idx != $fid) {
- $this->errors['name'] = $this->gettext('ruleexist');
- break;
- }
- }
-
- $i = 0;
- // rules
- if ($join == 'any') {
- $this->form['tests'][0]['test'] = 'true';
- }
- else {
- foreach ($headers as $idx => $header) {
- $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);
-
- if (preg_match('/^not/', $operator))
- $this->form['tests'][$i]['not'] = true;
- $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) {
- // RFC2822: printable ASCII except colon
- if (!preg_match('/^[\x21-\x39\x41-\x7E]+$/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';
- $this->form['tests'][$i]['arg'] = $header == '...' ? $cust_header : $header;
- }
- 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]['test'] = $test;
- $this->form['tests'][$i]['arg1'] = $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');
-
- if ($mod) {
- $this->form['tests'][$i]['part'] = $mod_type;
- }
- }
- }
-
- if ($header != 'size' && $comparator) {
- if (preg_match('/^(value|count)/', $this->form['tests'][$i]['type']))
- $comparator = 'i;ascii-numeric';
-
- $this->form['tests'][$i]['comparator'] = $comparator;
- }
-
- $i++;
- }
- }
-
- $i = 0;
- // actions
- foreach($act_types as $idx => $type) {
- $type = $this->strip_value($type);
- $target = $this->strip_value($act_targets[$idx]);
-
- switch ($type) {
-
- case 'fileinto':
- case 'fileinto_copy':
- $mailbox = $this->strip_value($mailboxes[$idx], false, false);
- $this->form['actions'][$i]['target'] = $this->mod_mailbox($mailbox, 'in');
- if ($type == 'fileinto_copy') {
- $type = 'fileinto';
- $this->form['actions'][$i]['copy'] = true;
- }
- break;
-
- case 'reject':
- case 'ereject':
- $target = $this->strip_value($area_targets[$idx]);
- $this->form['actions'][$i]['target'] = str_replace("\r\n", "\n", $target);
-
- // if ($target == '')
-// $this->errors['actions'][$i]['targetarea'] = $this->gettext('cannotbeempty');
- break;
-
- case 'redirect':
- case 'redirect_copy':
- $this->form['actions'][$i]['target'] = $target;
-
- if ($this->form['actions'][$i]['target'] == '')
- $this->errors['actions'][$i]['target'] = $this->gettext('cannotbeempty');
- else if (!rcube_utils::check_email($this->form['actions'][$i]['target']))
- $this->errors['actions'][$i]['target'] = $this->gettext('noemailwarning');
-
- if ($type == 'redirect_copy') {
- $type = 'redirect';
- $this->form['actions'][$i]['copy'] = true;
- }
- break;
-
- case 'addflag':
- case 'setflag':
- case 'removeflag':
- $_target = array();
- if (empty($flags[$idx])) {
- $this->errors['actions'][$i]['target'] = $this->gettext('noflagset');
- }
- else {
- foreach ($flags[$idx] as $flag) {
- $_target[] = $this->strip_value($flag);
- }
- }
- $this->form['actions'][$i]['target'] = $_target;
- break;
-
- case 'vacation':
- $reason = $this->strip_value($reasons[$idx]);
- $interval_type = $interval_types[$idx] == 'seconds' ? 'seconds' : 'days';
- $this->form['actions'][$i]['reason'] = str_replace("\r\n", "\n", $reason);
- $this->form['actions'][$i]['subject'] = $subject[$idx];
- $this->form['actions'][$i]['addresses'] = explode(',', $addresses[$idx]);
- $this->form['actions'][$i][$interval_type] = $intervals[$idx];
-// @TODO: vacation :mime, :from, :handle
-
- if ($this->form['actions'][$i]['addresses']) {
- foreach($this->form['actions'][$i]['addresses'] as $aidx => $address) {
- $address = trim($address);
- if (!$address)
- unset($this->form['actions'][$i]['addresses'][$aidx]);
- else if(!rcube_utils::check_email($address)) {
- $this->errors['actions'][$i]['addresses'] = $this->gettext('noemailwarning');
- break;
- } else
- $this->form['actions'][$i]['addresses'][$aidx] = $address;
- }
- }
-
- if ($this->form['actions'][$i]['reason'] == '')
- $this->errors['actions'][$i]['reason'] = $this->gettext('cannotbeempty');
- if ($this->form['actions'][$i][$interval_type] && !preg_match('/^[0-9]+$/', $this->form['actions'][$i][$interval_type]))
- $this->errors['actions'][$i]['interval'] = $this->gettext('forbiddenchars');
- break;
-
- case 'set':
- $this->form['actions'][$i]['name'] = $varnames[$idx];
- $this->form['actions'][$i]['value'] = $varvalues[$idx];
- foreach ((array)$varmods[$idx] as $v_m) {
- $this->form['actions'][$i][$v_m] = true;
- }
-
- if (empty($varnames[$idx])) {
- $this->errors['actions'][$i]['name'] = $this->gettext('cannotbeempty');
- }
- else if (!preg_match('/^[0-9a-z_]+$/i', $varnames[$idx])) {
- $this->errors['actions'][$i]['name'] = $this->gettext('forbiddenchars');
- }
-
- if (!isset($varvalues[$idx]) || $varvalues[$idx] === '') {
- $this->errors['actions'][$i]['value'] = $this->gettext('cannotbeempty');
- }
- break;
-
- case 'notify':
- if (empty($notifyaddrs[$idx])) {
- $this->errors['actions'][$i]['address'] = $this->gettext('cannotbeempty');
- }
- else if (!rcube_utils::check_email($notifyaddrs[$idx])) {
- $this->errors['actions'][$i]['address'] = $this->gettext('noemailwarning');
- }
- if (!empty($notifyfrom[$idx]) && !rcube_utils::check_email($notifyfrom[$idx])) {
- $this->errors['actions'][$i]['from'] = $this->gettext('noemailwarning');
- }
- $this->form['actions'][$i]['address'] = $notifyaddrs[$idx];
- $this->form['actions'][$i]['body'] = $notifybodies[$idx];
- $this->form['actions'][$i]['message'] = $notifymessages[$idx];
- $this->form['actions'][$i]['from'] = $notifyfrom[$idx];
- $this->form['actions'][$i]['importance'] = $notifyimp[$idx];
- break;
- }
-
- $this->form['actions'][$i]['type'] = $type;
- $i++;
- }
-
- if (!$this->errors && !$error) {
- // zapis skryptu
- if (!isset($this->script[$fid])) {
- $fid = $this->sieve->script->add_rule($this->form);
- $new = true;
- } else
- $fid = $this->sieve->script->update_rule($fid, $this->form);
-
- if ($fid !== false)
- $save = $this->save_script();
-
- if ($save && $fid !== false) {
- $this->rc->output->show_message('managesieve.filtersaved', 'confirmation');
- if ($this->rc->task != 'mail') {
- $this->rc->output->command('parent.managesieve_updatelist',
- isset($new) ? 'add' : 'update',
- array(
- 'name' => rcube::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');
-// $this->rc->output->send();
- }
- }
- }
-
- $this->managesieve_send();
- }
-
- private function managesieve_send()
- {
- // Handle form action
- if (isset($_GET['_framed']) || isset($_POST['_framed'])) {
- if (isset($_GET['_newset']) || isset($_POST['_newset'])) {
- $this->rc->output->send('managesieve.setedit');
- }
- else {
- $this->rc->output->send('managesieve.filteredit');
- }
- } else {
- $this->rc->output->set_pagetitle($this->gettext('filters'));
- $this->rc->output->send('managesieve.managesieve');
- }
- }
-
- // return the filters list as HTML table
- function filters_list($attrib)
- {
- // add id to message list table if not specified
- if (!strlen($attrib['id']))
- $attrib['id'] = 'rcmfilterslist';
-
- // define list of cols to be displayed
- $a_show_cols = array('name');
-
- $result = $this->list_rules();
-
- // create XHTML table
- $out = $this->rc->table_output($attrib, $result, $a_show_cols, 'id');
-
- // set client env
- $this->rc->output->add_gui_object('filterslist', $attrib['id']);
- $this->rc->output->include_script('list.js');
-
- // add some labels to client
- $this->rc->output->add_label('managesieve.filterdeleteconfirm');
-
- return $out;
- }
-
- // return the filters list as <SELECT>
- function filtersets_list($attrib, $no_env = false)
- {
- // add id to message list table if not specified
- if (!strlen($attrib['id']))
- $attrib['id'] = 'rcmfiltersetslist';
-
- $list = $this->list_scripts();
-
- 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' => rcube::Q($set),
- 'id' => 'S'.$idx,
- 'class' => !in_array($set, $this->active) ? 'disabled' : '',
- );
- }
- }
-
- // create XHTML table
- $out = $this->rc->table_output($attrib, $result, $a_show_cols, 'id');
-
- $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);
- }
-
- // set client env
- if (!$no_env) {
- $this->rc->output->add_gui_object('filtersetslist', $attrib['id']);
- $this->rc->output->add_label('managesieve.setdeleteconfirm');
- }
-
- return $out;
- }
-
- function filter_frame($attrib)
- {
- if (!$attrib['id'])
- $attrib['id'] = 'rcmfilterframe';
-
- $attrib['name'] = $attrib['id'];
-
- $this->rc->output->set_env('contentframe', $attrib['name']);
- $this->rc->output->set_env('blankpage', $attrib['src'] ?
- $this->rc->output->abs_url($attrib['src']) : 'program/resources/blank.gif');
-
- return $this->rc->output->frame($attrib);
- }
-
- function filterset_form($attrib)
- {
- if (!$attrib['id'])
- $attrib['id'] = 'rcmfiltersetform';
-
- $out = '<form name="filtersetform" action="./" method="post" enctype="multipart/form-data">'."\n";
-
- $hiddenfields = new html_hiddenfield(array('name' => '_task', 'value' => $this->rc->task));
- $hiddenfields->add(array('name' => '_action', 'value' => 'plugin.managesieve-save'));
- $hiddenfields->add(array('name' => '_framed', 'value' => ($_POST['_framed'] || $_GET['_framed'] ? 1 : 0)));
- $hiddenfields->add(array('name' => '_newset', 'value' => 1));
-
- $out .= $hiddenfields->show();
-
- $name = rcube_utils::get_input_value('_name', rcube_utils::INPUT_POST);
- $copy = rcube_utils::get_input_value('_copy', rcube_utils::INPUT_POST);
- $selected = rcube_utils::get_input_value('_from', rcube_utils::INPUT_POST);
-
- // filter set name input
- $input_name = new html_inputfield(array('name' => '_name', 'id' => '_name', 'size' => 30,
- 'class' => ($this->errors['name'] ? 'error' : '')));
-
- $out .= sprintf('<label for="%s"><b>%s:</b></label> %s<br /><br />',
- '_name', rcube::Q($this->gettext('filtersetname')), $input_name->show($name));
-
- $out .="\n<fieldset class=\"itemlist\"><legend>" . $this->gettext('filters') . ":</legend>\n";
- $out .= '<input type="radio" id="from_none" name="_from" value="none"'
- .(!$selected || $selected=='none' ? ' checked="checked"' : '').'></input>';
- $out .= sprintf('<label for="%s">%s</label> ', 'from_none', rcube::Q($this->gettext('none')));
-
- // filters set list
- $list = $this->list_scripts();
- $select = new html_select(array('name' => '_copy', 'id' => '_copy'));
-
- if (is_array($list)) {
- asort($list, SORT_LOCALE_STRING);
-
- 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 .= sprintf('<label for="%s">%s:</label> ', 'from_set', rcube::Q($this->gettext('fromset')));
- $out .= $select->show($copy);
- }
-
- // script upload box
- $upload = new html_inputfield(array('name' => '_file', 'id' => '_file', 'size' => 30,
- '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 .= sprintf('<label for="%s">%s:</label> ', 'from_file', rcube::Q($this->gettext('fromfile')));
- $out .= $upload->show();
- $out .= '</fieldset>';
-
- $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;
- }
-
-
- function filter_form($attrib)
- {
- if (!$attrib['id'])
- $attrib['id'] = 'rcmfilterform';
-
- $fid = rcube_utils::get_input_value('_fid', rcube_utils::INPUT_GPC);
- $scr = isset($this->form) ? $this->form : $this->script[$fid];
-
- $hiddenfields = new html_hiddenfield(array('name' => '_task', 'value' => $this->rc->task));
- $hiddenfields->add(array('name' => '_action', 'value' => 'plugin.managesieve-save'));
- $hiddenfields->add(array('name' => '_framed', 'value' => ($_POST['_framed'] || $_GET['_framed'] ? 1 : 0)));
- $hiddenfields->add(array('name' => '_fid', 'value' => $fid));
-
- $out = '<form name="filterform" action="./" method="post">'."\n";
- $out .= $hiddenfields->show();
-
- // 'any' flag
- if (sizeof($scr['tests']) == 1 && $scr['tests'][0]['test'] == 'true' && !$scr['tests'][0]['not'])
- $any = true;
-
- // filter name input
- $field_id = '_name';
- $input_name = new html_inputfield(array('name' => '_name', 'id' => $field_id, 'size' => 30,
- 'class' => ($this->errors['name'] ? 'error' : '')));
-
- if ($this->errors['name'])
- $this->add_tip($field_id, $this->errors['name'], true);
-
- if (isset($scr))
- $input_name = $input_name->show($scr['name']);
- else
- $input_name = $input_name->show();
-
- $out .= sprintf("\n<label for=\"%s\"><b>%s:</b></label> %s\n",
- $field_id, rcube::Q($this->gettext('filtername')), $input_name);
-
- // filter set selector
- if ($this->rc->task == 'mail') {
- $out .= sprintf("\n&nbsp;<label for=\"%s\"><b>%s:</b></label> %s\n",
- $field_id, rcube::Q($this->gettext('filterset')),
- $this->filtersets_list(array('id' => 'sievescriptname'), true));
- }
-
- $out .= '<br /><br /><fieldset><legend>' . rcube::Q($this->gettext('messagesrules')) . "</legend>\n";
-
- // any, allof, anyof radio buttons
- $field_id = '_allof';
- $input_join = new html_radiobutton(array('name' => '_join', 'id' => $field_id, 'value' => 'allof',
- 'onclick' => 'rule_join_radio(\'allof\')', 'class' => 'radio'));
-
- if (isset($scr) && !$any)
- $input_join = $input_join->show($scr['join'] ? 'allof' : '');
- else
- $input_join = $input_join->show();
-
- $out .= sprintf("%s<label for=\"%s\">%s</label>&nbsp;\n",
- $input_join, $field_id, rcube::Q($this->gettext('filterallof')));
-
- $field_id = '_anyof';
- $input_join = new html_radiobutton(array('name' => '_join', 'id' => $field_id, 'value' => 'anyof',
- 'onclick' => 'rule_join_radio(\'anyof\')', 'class' => 'radio'));
-
- if (isset($scr) && !$any)
- $input_join = $input_join->show($scr['join'] ? '' : 'anyof');
- else
- $input_join = $input_join->show('anyof'); // default
-
- $out .= sprintf("%s<label for=\"%s\">%s</label>\n",
- $input_join, $field_id, rcube::Q($this->gettext('filteranyof')));
-
- $field_id = '_any';
- $input_join = new html_radiobutton(array('name' => '_join', 'id' => $field_id, 'value' => 'any',
- 'onclick' => 'rule_join_radio(\'any\')', 'class' => 'radio'));
-
- $input_join = $input_join->show($any ? 'any' : '');
-
- $out .= sprintf("%s<label for=\"%s\">%s</label>\n",
- $input_join, $field_id, rcube::Q($this->gettext('filterany')));
-
- $rows_num = isset($scr) ? sizeof($scr['tests']) : 1;
-
- $out .= '<div id="rules"'.($any ? ' style="display: none"' : '').'>';
- for ($x=0; $x<$rows_num; $x++)
- $out .= $this->rule_div($fid, $x);
- $out .= "</div>\n";
-
- $out .= "</fieldset>\n";
-
- // actions
- $out .= '<fieldset><legend>' . rcube::Q($this->gettext('messagesactions')) . "</legend>\n";
-
- $rows_num = isset($scr) ? sizeof($scr['actions']) : 1;
-
- $out .= '<div id="actions">';
- for ($x=0; $x<$rows_num; $x++)
- $out .= $this->action_div($fid, $x);
- $out .= "</div>\n";
-
- $out .= "</fieldset>\n";
-
- $this->print_tips();
-
- if ($scr['disabled']) {
- $this->rc->output->set_env('rule_disabled', true);
- }
- $this->rc->output->add_label(
- 'managesieve.ruledeleteconfirm',
- 'managesieve.actiondeleteconfirm'
- );
- $this->rc->output->add_gui_object('sieveform', 'filterform');
-
- return $out;
- }
-
- function rule_div($fid, $id, $div=true)
- {
- $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']);
-
- // 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(rcube::Q($this->gettext($name)), Q($val));
- if (in_array('body', $this->exts))
- $select_header->add(rcube::Q($this->gettext('body')), 'body');
- $select_header->add(rcube::Q($this->gettext('size')), 'size');
- $select_header->add(rcube::Q($this->gettext('...')), '...');
-
- // TODO: list arguments
- $aout = '';
-
- 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')
- && !is_array($rule['arg']) && in_array($rule['arg'], $this->headers)
- ) {
- $aout .= $select_header->show($rule['arg']);
- }
- else if (isset($rule['test']) && $rule['test'] == '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')
- $aout .= $select_header->show('...');
- else
- $aout .= $select_header->show();
-
- 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'];
- }
-
- $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')
- .' value="' .rcube::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'),
- 'class' => 'operator_selector',
- 'onchange' => 'rule_op_select('.$id.')'));
- $select_op->add(rcube::Q($this->gettext('filtercontains')), 'contains');
- $select_op->add(rcube::Q($this->gettext('filternotcontains')), 'notcontains');
- $select_op->add(rcube::Q($this->gettext('filteris')), 'is');
- $select_op->add(rcube::Q($this->gettext('filterisnot')), 'notis');
- $select_op->add(rcube::Q($this->gettext('filterexists')), 'exists');
- $select_op->add(rcube::Q($this->gettext('filternotexists')), 'notexists');
- $select_op->add(rcube::Q($this->gettext('filtermatches')), 'matches');
- $select_op->add(rcube::Q($this->gettext('filternotmatches')), 'notmatches');
- if (in_array('regex', $this->exts)) {
- $select_op->add(rcube::Q($this->gettext('filterregex')), 'regex');
- $select_op->add(rcube::Q($this->gettext('filternotregex')), 'notregex');
- }
- if (in_array('relational', $this->exts)) {
- $select_op->add(rcube::Q($this->gettext('countisgreaterthan')), 'count-gt');
- $select_op->add(rcube::Q($this->gettext('countisgreaterthanequal')), 'count-ge');
- $select_op->add(rcube::Q($this->gettext('countislessthan')), 'count-lt');
- $select_op->add(rcube::Q($this->gettext('countislessthanequal')), 'count-le');
- $select_op->add(rcube::Q($this->gettext('countequals')), 'count-eq');
- $select_op->add(rcube::Q($this->gettext('countnotequals')), 'count-ne');
- $select_op->add(rcube::Q($this->gettext('valueisgreaterthan')), 'value-gt');
- $select_op->add(rcube::Q($this->gettext('valueisgreaterthanequal')), 'value-ge');
- $select_op->add(rcube::Q($this->gettext('valueislessthan')), 'value-lt');
- $select_op->add(rcube::Q($this->gettext('valueislessthanequal')), 'value-le');
- $select_op->add(rcube::Q($this->gettext('valueequals')), 'value-eq');
- $select_op->add(rcube::Q($this->gettext('valuenotequals')), 'value-ne');
- }
-
- // target input (TODO: lists)
-
- if (in_array($rule['test'], array('header', 'address', 'envelope'))) {
- $test = ($rule['not'] ? 'not' : '').($rule['type'] ? $rule['type'] : 'is');
- $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') {
- $test = '';
- $target = '';
- if (preg_match('/^([0-9]+)(K|M|G)?$/', $rule['arg'], $matches)) {
- $sizetarget = $matches[1];
- $sizeitem = $matches[2];
- }
- else {
- $sizetarget = $rule['arg'];
- $sizeitem = $rule['item'];
- }
- }
- else {
- $test = ($rule['not'] ? 'not' : '').$rule['test'];
- $target = '';
- }
-
- $tout .= $select_op->show($test);
- $tout .= '<input type="text" name="_rule_target[]" id="rule_target' .$id. '"
- value="' .rcube::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(rcube::Q($this->gettext('filterover')), 'over');
- $select_size_op->add(rcube::Q($this->gettext('filterunder')), 'under');
-
- $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') .' />
- <label><input type="radio" name="_rule_size_item['.$id.']" value=""'
- . (!$sizeitem ? ' checked="checked"' : '') .' class="radio" />'.$this->rc->gettext('B').'</label>
- <label><input type="radio" name="_rule_size_item['.$id.']" value="K"'
- . ($sizeitem=='K' ? ' checked="checked"' : '') .' class="radio" />'.$this->rc->gettext('KB').'</label>
- <label><input type="radio" name="_rule_size_item['.$id.']" value="M"'
- . ($sizeitem=='M' ? ' checked="checked"' : '') .' class="radio" />'.$this->rc->gettext('MB').'</label>
- <label><input type="radio" name="_rule_size_item['.$id.']" value="G"'
- . ($sizeitem=='G' ? ' checked="checked"' : '') .' class="radio" />'.$this->rc->gettext('GB').'</label>';
- $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(rcube::Q($this->gettext('none')), '');
- $select_mod->add(rcube::Q($this->gettext('address')), 'address');
- if (in_array('envelope', $this->exts))
- $select_mod->add(rcube::Q($this->gettext('envelope')), 'envelope');
-
- $select_type = new html_select(array('name' => "_rule_mod_type[]", 'id' => 'rule_mod_type'.$id));
- $select_type->add(rcube::Q($this->gettext('allparts')), 'all');
- $select_type->add(rcube::Q($this->gettext('domain')), 'domain');
- $select_type->add(rcube::Q($this->gettext('localpart')), 'localpart');
- if (in_array('subaddress', $this->exts)) {
- $select_type->add(rcube::Q($this->gettext('user')), 'user');
- $select_type->add(rcube::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 .= rcube::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 .= rcube::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(rcube::Q($this->gettext('text')), 'text');
- $select_mod->add(rcube::Q($this->gettext('undecoded')), 'raw');
- $select_mod->add(rcube::Q($this->gettext('contenttype')), 'content');
-
- $mout .= '<div id="rule_trans' .$id. '" class="adv" style="display:' . ($rule['test'] == 'body' ? 'block' : 'none') .'">';
- $mout .= ' <span>';
- $mout .= rcube::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(rcube::Q($this->gettext('default')), '');
- $select_comp->add(rcube::Q($this->gettext('octet')), 'i;octet');
- $select_comp->add(rcube::Q($this->gettext('asciicasemap')), 'i;ascii-casemap');
- if (in_array('comparator-i;ascii-numeric', $this->exts)) {
- $select_comp->add(rcube::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 .= rcube::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="'. rcube::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 .= '<a href="#" id="ruleadd' . $id .'" title="'. rcube::Q($this->gettext('add')). '"
- onclick="rcmail.managesieve_ruleadd(' . $id .')" class="button add"></a>';
- $out .= '<a href="#" id="ruledel' . $id .'" title="'. rcube::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" : '';
-
- return $out;
- }
-
- function action_div($fid, $id, $div=true)
- {
- $action = isset($this->form) ? $this->form['actions'][$id] : $this->script[$fid]['actions'][$id];
- $rows_num = isset($this->form) ? sizeof($this->form['actions']) : sizeof($this->script[$fid]['actions']);
-
- $out = $div ? '<div class="actionrow" id="actionrow' .$id .'">'."\n" : '';
-
- $out .= '<table><tr><td class="rowactions">';
-
- // action select
- $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(rcube::Q($this->gettext('messagemoveto')), 'fileinto');
- if (in_array('fileinto', $this->exts) && in_array('copy', $this->exts))
- $select_action->add(rcube::Q($this->gettext('messagecopyto')), 'fileinto_copy');
- $select_action->add(rcube::Q($this->gettext('messageredirect')), 'redirect');
- if (in_array('copy', $this->exts))
- $select_action->add(rcube::Q($this->gettext('messagesendcopy')), 'redirect_copy');
- if (in_array('reject', $this->exts))
- $select_action->add(rcube::Q($this->gettext('messagediscard')), 'reject');
- else if (in_array('ereject', $this->exts))
- $select_action->add(rcube::Q($this->gettext('messagediscard')), 'ereject');
- if (in_array('vacation', $this->exts))
- $select_action->add(rcube::Q($this->gettext('messagereply')), 'vacation');
- $select_action->add(rcube::Q($this->gettext('messagedelete')), 'discard');
- if (in_array('imapflags', $this->exts) || in_array('imap4flags', $this->exts)) {
- $select_action->add(rcube::Q($this->gettext('setflags')), 'setflag');
- $select_action->add(rcube::Q($this->gettext('addflags')), 'addflag');
- $select_action->add(rcube::Q($this->gettext('removeflags')), 'removeflag');
- }
- if (in_array('variables', $this->exts)) {
- $select_action->add(rcube::Q($this->gettext('setvariable')), 'set');
- }
- if (in_array('enotify', $this->exts) || in_array('notify', $this->exts)) {
- $select_action->add(rcube::Q($this->gettext('notify')), 'notify');
- }
- $select_action->add(rcube::Q($this->gettext('rulestop')), 'stop');
-
- $select_type = $action['type'];
- if (in_array($action['type'], array('fileinto', 'redirect')) && $action['copy']) {
- $select_type .= '_copy';
- }
-
- $out .= $select_action->show($select_type);
- $out .= '</td>';
-
- // actions target inputs
- $out .= '<td class="rowtargets">';
- // shared targets
- $out .= '<input type="text" name="_action_target['.$id.']" id="action_target' .$id. '" '
- .'value="' .($action['type']=='redirect' ? rcube::Q($action['target'], 'strict', false) : ''). '" size="35" '
- .'style="display:' .($action['type']=='redirect' ? 'inline' : 'none') .'" '
- . $this->error_class($id, 'action', 'target', 'action_target') .' />';
- $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')) ? rcube::Q($action['target'], 'strict', false) : '')
- . "</textarea>\n";
-
- // vacation
- $vsec = in_array('vacation-seconds', $this->exts);
- $out .= '<div id="action_vacation' .$id.'" style="display:' .($action['type']=='vacation' ? 'inline' : 'none') .'">';
- $out .= '<span class="label">'. rcube::Q($this->gettext('vacationreason')) .'</span><br />'
- .'<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">' .rcube::Q($this->gettext('vacationsubject')) . '</span><br />'
- .'<input type="text" name="_action_subject['.$id.']" id="action_subject'.$id.'" '
- .'value="' . (is_array($action['subject']) ? rcube::Q(implode(', ', $action['subject']), 'strict', false) : $action['subject']) . '" size="35" '
- . $this->error_class($id, 'action', 'subject', 'action_subject') .' />';
- $out .= '<br /><span class="label">' .rcube::Q($this->gettext('vacationaddresses')) . '</span><br />'
- .'<input type="text" name="_action_addresses['.$id.']" id="action_addr'.$id.'" '
- .'value="' . (is_array($action['addresses']) ? rcube::Q(implode(', ', $action['addresses']), 'strict', false) : $action['addresses']) . '" size="35" '
- . $this->error_class($id, 'action', 'addresses', 'action_addr') .' />';
- $out .= '<br /><span class="label">' . rcube::Q($this->gettext($vsec ? 'vacationinterval' : 'vacationdays')) . '</span><br />'
- .'<input type="text" name="_action_interval['.$id.']" id="action_interval'.$id.'" '
- .'value="' .rcube::Q(isset($action['seconds']) ? $action['seconds'] : $action['days'], 'strict', false) . '" size="2" '
- . $this->error_class($id, 'action', 'interval', 'action_interval') .' />';
- if ($vsec) {
- $out .= '&nbsp;<label><input type="radio" name="_action_interval_type['.$id.']" value="days"'
- . (!isset($action['seconds']) ? ' checked="checked"' : '') .' class="radio" />'.$this->gettext('days').'</label>'
- . '&nbsp;<label><input type="radio" name="_action_interval_type['.$id.']" value="seconds"'
- . (isset($action['seconds']) ? ' checked="checked"' : '') .' class="radio" />'.$this->gettext('seconds').'</label>';
- }
- $out .= '</div>';
-
- // flags
- $flags = array(
- 'read' => '\\Seen',
- 'answered' => '\\Answered',
- 'flagged' => '\\Flagged',
- 'deleted' => '\\Deleted',
- 'draft' => '\\Draft',
- );
- $flags_target = (array)$action['target'];
-
- $out .= '<div id="action_flags' .$id.'" style="display:'
- . (preg_match('/^(set|add|remove)flag$/', $action['type']) ? 'inline' : 'none') . '"'
- . $this->error_class($id, 'action', 'flags', 'action_flags') . '>';
- foreach ($flags as $fidx => $flag) {
- $out .= '<input type="checkbox" name="_action_flags[' .$id .'][]" value="' . $flag . '"'
- . (in_array_nocase($flag, $flags_target) ? 'checked="checked"' : '') . ' />'
- . rcube::Q($this->gettext('flag'.$fidx)) .'<br>';
- }
- $out .= '</div>';
-
- // set variable
- $set_modifiers = array(
- 'lower',
- 'upper',
- 'lowerfirst',
- 'upperfirst',
- 'quotewildcard',
- 'length'
- );
-
- $out .= '<div id="action_set' .$id.'" style="display:' .($action['type']=='set' ? 'inline' : 'none') .'">';
- $out .= '<span class="label">' .rcube::Q($this->gettext('setvarname')) . '</span><br />'
- .'<input type="text" name="_action_varname['.$id.']" id="action_varname'.$id.'" '
- .'value="' . rcube::Q($action['name']) . '" size="35" '
- . $this->error_class($id, 'action', 'name', 'action_varname') .' />';
- $out .= '<br /><span class="label">' .rcube::Q($this->gettext('setvarvalue')) . '</span><br />'
- .'<input type="text" name="_action_varvalue['.$id.']" id="action_varvalue'.$id.'" '
- .'value="' . rcube::Q($action['value']) . '" size="35" '
- . $this->error_class($id, 'action', 'value', 'action_varvalue') .' />';
- $out .= '<br /><span class="label">' .rcube::Q($this->gettext('setvarmodifiers')) . '</span><br />';
- foreach ($set_modifiers as $s_m) {
- $s_m_id = 'action_varmods' . $id . $s_m;
- $out .= sprintf('<input type="checkbox" name="_action_varmods[%s][]" value="%s" id="%s"%s />%s<br>',
- $id, $s_m, $s_m_id,
- (array_key_exists($s_m, (array)$action) && $action[$s_m] ? ' checked="checked"' : ''),
- rcube::Q($this->gettext('var' . $s_m)));
- }
- $out .= '</div>';
-
- // notify
- // skip :options tag - not used by the mailto method
- $out .= '<div id="action_notify' .$id.'" style="display:' .($action['type']=='notify' ? 'inline' : 'none') .'">';
- $out .= '<span class="label">' .rcube::Q($this->gettext('notifyaddress')) . '</span><br />'
- .'<input type="text" name="_action_notifyaddress['.$id.']" id="action_notifyaddress'.$id.'" '
- .'value="' . rcube::Q($action['address']) . '" size="35" '
- . $this->error_class($id, 'action', 'address', 'action_notifyaddress') .' />';
- $out .= '<br /><span class="label">'. rcube::Q($this->gettext('notifybody')) .'</span><br />'
- .'<textarea name="_action_notifybody['.$id.']" id="action_notifybody' .$id. '" '
- .'rows="3" cols="35" '. $this->error_class($id, 'action', 'method', 'action_notifybody') . '>'
- . rcube::Q($action['body'], 'strict', false) . "</textarea>\n";
- $out .= '<br /><span class="label">' .rcube::Q($this->gettext('notifysubject')) . '</span><br />'
- .'<input type="text" name="_action_notifymessage['.$id.']" id="action_notifymessage'.$id.'" '
- .'value="' . rcube::Q($action['message']) . '" size="35" '
- . $this->error_class($id, 'action', 'message', 'action_notifymessage') .' />';
- $out .= '<br /><span class="label">' .rcube::Q($this->gettext('notifyfrom')) . '</span><br />'
- .'<input type="text" name="_action_notifyfrom['.$id.']" id="action_notifyfrom'.$id.'" '
- .'value="' . rcube::Q($action['from']) . '" size="35" '
- . $this->error_class($id, 'action', 'from', 'action_notifyfrom') .' />';
- $importance_options = array(
- 3 => 'notifyimportancelow',
- 2 => 'notifyimportancenormal',
- 1 => 'notifyimportancehigh'
- );
- $select_importance = new html_select(array(
- 'name' => '_action_notifyimportance[' . $id . ']',
- 'id' => '_action_notifyimportance' . $id,
- 'class' => $this->error_class($id, 'action', 'importance', 'action_notifyimportance')));
- foreach ($importance_options as $io_v => $io_n) {
- $select_importance->add(rcube::Q($this->gettext($io_n)), $io_v);
- }
- $out .= '<br /><span class="label">' . rcube::Q($this->gettext('notifyimportance')) . '</span><br />';
- $out .= $select_importance->show($action['importance'] ? $action['importance'] : 2);
- $out .= '</div>';
-
- // mailbox select
- if ($action['type'] == 'fileinto')
- $mailbox = $this->mod_mailbox($action['target'], 'out');
- else
- $mailbox = '';
-
- $select = $this->rc->folder_selector(array(
- '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 .= '<a href="#" id="actionadd' . $id .'" title="'. rcube::Q($this->gettext('add')). '"
- onclick="rcmail.managesieve_actionadd(' . $id .')" class="button add"></a>';
- $out .= '<a href="#" id="actiondel' . $id .'" title="'. rcube::Q($this->gettext('del')). '"
- onclick="rcmail.managesieve_actiondel(' . $id .')" class="button del' . ($rows_num<2 ? ' disabled' : '') .'"></a>';
- $out .= '</td>';
-
- $out .= '</tr></table>';
-
- $out .= $div ? "</div>\n" : '';
-
- return $out;
- }
-
- private function genid()
- {
- return preg_replace('/[^0-9]/', '', microtime(true));
- }
-
- private function strip_value($str, $allow_html = false, $trim = true)
- {
- if (!$allow_html) {
- $str = strip_tags($str);
- }
-
- return $trim ? trim($str) : $str;
- }
-
- private function error_class($id, $type, $target, $elem_prefix='')
- {
- // TODO: tooltips
- if (($type == 'test' && ($str = $this->errors['tests'][$id][$target])) ||
- ($type == 'action' && ($str = $this->errors['actions'][$id][$target]))
- ) {
- $this->add_tip($elem_prefix.$id, $str, true);
- return ' class="error"';
- }
-
- return '';
- }
-
- private function add_tip($id, $str, $error=false)
- {
- if ($error)
- $str = html::span('sieve error', $str);
-
- $this->tips[] = array($id, $str);
- }
-
- private function print_tips()
- {
- if (empty($this->tips))
- return;
-
- $script = rcmail_output::JS_OBJECT_NAME.'.managesieve_tip_register('.json_encode($this->tips).');';
- $this->rc->output->add_script($script, 'foot');
+ $engine = $this->get_engine();
+ $engine->save();
}
/**
- * Converts mailbox name from/to UTF7-IMAP from/to internal Sieve encoding
- * with delimiter replacement.
- *
- * @param string $mailbox Mailbox name
- * @param string $mode Conversion direction ('in'|'out')
- *
- * @return string Mailbox name
+ * Initializes engine object
*/
- private function mod_mailbox($mailbox, $mode = 'out')
+ private function get_engine()
{
- $delimiter = $_SESSION['imap_delimiter'];
- $replace_delimiter = $this->rc->config->get('managesieve_replace_delimiter');
- $mbox_encoding = $this->rc->config->get('managesieve_mbox_encoding', 'UTF7-IMAP');
-
- if ($mode == 'out') {
- $mailbox = rcube_charset::convert($mailbox, $mbox_encoding, 'UTF7-IMAP');
- if ($replace_delimiter && $replace_delimiter != $delimiter)
- $mailbox = str_replace($replace_delimiter, $delimiter, $mailbox);
- }
- else {
- $mailbox = rcube_charset::convert($mailbox, 'UTF7-IMAP', $mbox_encoding);
- if ($replace_delimiter && $replace_delimiter != $delimiter)
- $mailbox = str_replace($delimiter, $replace_delimiter, $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')) {
+ if (!$this->engine) {
+ $this->load_config();
- // 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;
+ // Add include path for internal classes
+ $include_path = $this->home . '/lib' . PATH_SEPARATOR;
+ $include_path .= ini_get('include_path');
+ set_include_path($include_path);
- 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);
- }
-
- // Hide scripts from config
- $exceptions = $this->rc->config->get('managesieve_filename_exceptions');
- if (!empty($exceptions)) {
- $this->list = array_diff($this->list, (array)$exceptions);
- }
- }
-
- 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 && 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 $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 $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' => rcube::Q($fname),
- 'class' => $filter['disabled'] ? 'disabled' : '',
- );
- $i++;
+ $this->engine = new rcube_sieve_engine($this);
}
- return $result;
+ return $this->engine;
}
}
diff --git a/plugins/managesieve/package.xml b/plugins/managesieve/package.xml
index a0c38b82d..9c02957a5 100644
--- a/plugins/managesieve/package.xml
+++ b/plugins/managesieve/package.xml
@@ -26,7 +26,7 @@
<release>stable</release>
<api>stable</api>
</stability>
- <license uri="http://www.gnu.org/licenses/gpl-2.0.html">GNU GPLv2</license>
+ <license uri="http://www.gnu.org/licenses/gpl.html">GNU GPLv3+</license>
<notes>-</notes>
<contents>
<dir baseinstalldir="/" name="/">
@@ -93,6 +93,7 @@
<file name="skins/classic/images/add.png" role="data"></file>
<file name="skins/classic/images/del.png" role="data"></file>
<file name="skins/classic/images/down_small.gif" role="data"></file>
+ <file name="skins/classic/images/erase.png" role="data"></file>
<file name="skins/classic/images/filter.png" role="data"></file>
<file name="skins/classic/images/up_small.gif" role="data"></file>
<file name="skins/larry/managesieve.css" role="data"></file>
@@ -103,10 +104,11 @@
<file name="skins/larry/images/add.png" role="data"></file>
<file name="skins/larry/images/del.png" role="data"></file>
<file name="skins/larry/images/down_small.gif" role="data"></file>
+ <file name="skins/larry/images/erase.png" role="data"></file>
<file name="skins/larry/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/Roundcube/rcube_sieve.php" role="php"></file>
+ <file name="lib/Roundcube/rcube_sieve_engine.php" role="php"></file>
+ <file name="lib/Roundcube/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>
diff --git a/plugins/managesieve/skins/classic/images/erase.png b/plugins/managesieve/skins/classic/images/erase.png
new file mode 100644
index 000000000..ddd3a9782
--- /dev/null
+++ b/plugins/managesieve/skins/classic/images/erase.png
Binary files differ
diff --git a/plugins/managesieve/skins/classic/managesieve.css b/plugins/managesieve/skins/classic/managesieve.css
index 86a0d197d..59d88cb46 100644
--- a/plugins/managesieve/skins/classic/managesieve.css
+++ b/plugins/managesieve/skins/classic/managesieve.css
@@ -201,11 +201,30 @@ td.rowtargets
padding-top: 2px;
}
+td.rowtargets > div
+{
+ vertical-align: top;
+ margin-top: 2px;
+}
+
td.rowtargets div.adv
{
padding-top: 3px;
}
+td.rowtargets div.adv span.label
+{
+ display: inline-block;
+ padding-right: 10px;
+ min-width: 65px;
+}
+
+html.mozilla #filter-form select
+{
+ padding-top: 3px;
+ padding-bottom: 3px;
+}
+
input.disabled, input.disabled:hover
{
color: #999999;
@@ -226,6 +245,7 @@ input.radio
select.operator_selector
{
width: 200px;
+ vertical-align: top;
}
td.rowtargets span,
@@ -306,8 +326,78 @@ a.button.disabled
#filter-form textarea
{
font-size: 11px;
+ vertical-align: middle;
+}
+
+/* smart multi-row input field */
+.listarea
+{
+ border: 1px solid #666;
+ margin: 0;
+ padding: 1px;
+ display: inline-block;
+ max-height: 67px;
+ overflow-y: auto;
+}
+
+td.rowtargets > span.listarea
+{
+ vertical-align: top;
+ margin-top: 2px;
+}
+
+.listelement
+{
+ display: block;
+ white-space: nowrap;
+ background-color: #fff;
+ border-top: 1px solid #e2e2e2;
+ height: 16px;
+ padding: 0;
+ margin: 0;
+ overflow: hidden;
+ line-height: 16px;
}
+.listarea.error .listelement
+{
+ background-color: #FFFFC4;
+}
+
+.listelement:first-child
+{
+ border-top: none;
+}
+
+#filter-form .listelement input
+{
+ border: none;
+ border-radius: 0;
+ box-shadow: none;
+ outline: none;
+ vertical-align: top;
+ height: 16px;
+ padding-top: 0;
+ padding-bottom: 0;
+ line-height: 16px;
+ background-color: transparent;
+}
+
+.listelement input:focus
+{
+ box-shadow: none;
+}
+
+.listelement .reset
+{
+ display: inline-block;
+ width: 16px;
+ height: 16px;
+ background: url(images/erase.png) -1px 0 no-repeat #eee;
+ cursor: pointer;
+}
+
+
/* fixes for popup window */
body.iframe.mail
diff --git a/plugins/managesieve/skins/classic/templates/managesieve.html b/plugins/managesieve/skins/classic/templates/managesieve.html
index 71eebe105..869e3ac36 100644
--- a/plugins/managesieve/skins/classic/templates/managesieve.html
+++ b/plugins/managesieve/skins/classic/templates/managesieve.html
@@ -19,7 +19,7 @@
</style>
</head>
-<body onload="rcube_init_mail_ui()">
+<body>
<roundcube:include file="/includes/taskbar.html" />
<roundcube:include file="/includes/header.html" />
@@ -83,5 +83,9 @@
</ul>
</div>
+<script type="text/javascript">
+rcube_init_mail_ui();
+</script>
+
</body>
</html>
diff --git a/plugins/managesieve/skins/larry/images/erase.png b/plugins/managesieve/skins/larry/images/erase.png
new file mode 100644
index 000000000..ddd3a9782
--- /dev/null
+++ b/plugins/managesieve/skins/larry/images/erase.png
Binary files differ
diff --git a/plugins/managesieve/skins/larry/managesieve.css b/plugins/managesieve/skins/larry/managesieve.css
index 099f05f0d..2144fe13f 100644
--- a/plugins/managesieve/skins/larry/managesieve.css
+++ b/plugins/managesieve/skins/larry/managesieve.css
@@ -43,7 +43,7 @@
#filtersetslist
{
width: 100%;
- table-layout: fixed;
+ table-layout: fixed;
}
#filterslist tbody td,
@@ -175,9 +175,23 @@ td.rowtargets
padding-top: 2px;
}
+td.rowtargets > div
+{
+ vertical-align: top;
+ margin-top: 2px;
+}
+
td.rowtargets div.adv
{
padding-top: 3px;
+ font-size: 10px;
+}
+
+td.rowtargets div.adv span.label
+{
+ display: inline-block;
+ padding-right: 5px;
+ min-width: 70px;
}
input.disabled, input.disabled:hover
@@ -205,6 +219,7 @@ input.radio
select.operator_selector
{
width: 200px;
+ vertical-align: top;
}
td.rowtargets span,
@@ -290,6 +305,13 @@ a.button.disabled
{
font-size: 11px;
padding: 1px;
+ vertical-align: middle;
+}
+
+html.mozilla #filter-form select
+{
+ padding-top: 3px;
+ padding-bottom: 3px;
}
/* revert larry style button */
@@ -306,6 +328,80 @@ fieldset
border-radius: 4px;
}
+/* smart multi-row input field */
+.listarea
+{
+ border: 1px solid #B2B2B2;
+ border-radius: 4px;
+ box-shadow: inset 0 0 2px 1px rgba(0,0,0, 0.1);
+ -moz-box-shadow: inset 0 0 2px 1px rgba(0,0,0, 0.1);
+ -webkit-box-shadow: inset 0 0 2px 1px rgba(0,0,0, 0.1);
+ -o-box-shadow: inset 0 0 2px 1px rgba(0,0,0, 0.1);
+ margin: 0;
+ padding: 2px;
+ display: inline-block;
+ max-height: 59px;
+ overflow-y: auto;
+}
+
+td.rowtargets > span.listarea
+{
+ vertical-align: top;
+ margin-top: 2px;
+}
+
+.listelement
+{
+ display: block;
+ white-space: nowrap;
+ background-color: #fff;
+ border-top: 1px solid #e2e2e2;
+ height: 14px;
+ padding: 0;
+ margin: 0;
+ overflow: hidden;
+ line-height: 14px;
+}
+
+.listarea.error .listelement
+{
+ background-color: #FFFFC4;
+}
+
+.listelement:first-child
+{
+ border-top: none;
+}
+
+#filter-form .listelement input
+{
+ border: none;
+ border-radius: 0;
+ box-shadow: none;
+ outline: none;
+ vertical-align: top;
+ height: 14px;
+ padding-top: 0;
+ padding-bottom: 0;
+ line-height: 14px;
+ background-color: transparent;
+}
+
+.listelement input:focus
+{
+ box-shadow: none;
+}
+
+.listelement .reset
+{
+ display: inline-block;
+ width: 16px;
+ height: 16px;
+ background: url(images/erase.png) -1px -1px no-repeat #eee;
+ cursor: pointer;
+}
+
+
/* fixes for popup window */
body.iframe.mail
diff --git a/plugins/markasjunk/localization/lb_LU.inc b/plugins/markasjunk/localization/lb_LU.inc
new file mode 100644
index 000000000..eb211d66c
--- /dev/null
+++ b/plugins/markasjunk/localization/lb_LU.inc
@@ -0,0 +1,24 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | plugins/markasjunk/localization/<lang>.inc |
+ | |
+ | Localization file of the Roundcube Webmail Mark-As-Junk plugin |
+ | Copyright (C) 2012-2013, The Roundcube Dev Team |
+ | |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
+ | |
+ +-----------------------------------------------------------------------+
+
+ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-markasjunk/
+*/
+
+$labels = array();
+$labels['buttontext'] = 'Spam';
+$labels['buttontitle'] = 'Als Spam markéieren';
+$labels['reportedasjunk'] = 'Erfollegräich als Spam gemellt';
+
+?> \ No newline at end of file
diff --git a/plugins/markasjunk/localization/lv_LV.inc b/plugins/markasjunk/localization/lv_LV.inc
index f0ea921ba..5389ae399 100644
--- a/plugins/markasjunk/localization/lv_LV.inc
+++ b/plugins/markasjunk/localization/lv_LV.inc
@@ -17,8 +17,8 @@
*/
$labels = array();
-$labels['buttontext'] = 'Junk';
-$labels['buttontitle'] = 'IezÄ«mÄ“t kÄ mÄ“stuli';
-$labels['reportedasjunk'] = 'SekmÄ«gi iezÄ«mÄ“ta kÄ mÄ“stule';
+$labels['buttontext'] = 'MÄ“stules';
+$labels['buttontitle'] = 'AtzÄ«mÄ“t kÄ mÄ“stuli';
+$labels['reportedasjunk'] = 'SekmÄ«gi iatzÄ«mÄ“ta kÄ mÄ“stule';
?> \ No newline at end of file
diff --git a/plugins/new_user_dialog/localization/lb_LU.inc b/plugins/new_user_dialog/localization/lb_LU.inc
new file mode 100644
index 000000000..36da96e5e
--- /dev/null
+++ b/plugins/new_user_dialog/localization/lb_LU.inc
@@ -0,0 +1,23 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | plugins/new_user_dialog/localization/<lang>.inc |
+ | |
+ | Localization file of the Roundcube Webmail New User Dialog plugin |
+ | Copyright (C) 2012-2013, The Roundcube Dev Team |
+ | |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
+ | |
+ +-----------------------------------------------------------------------+
+
+ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-new_user_dialog/
+*/
+
+$labels = array();
+$labels['identitydialogtitle'] = 'Vervollstänneg w.e.gl deng Sender-Identitéit';
+$labels['identitydialoghint'] = 'Dës Këscht erschéngt just beim éischte Login.';
+
+?> \ No newline at end of file
diff --git a/plugins/new_user_dialog/localization/lv_LV.inc b/plugins/new_user_dialog/localization/lv_LV.inc
index 2e3642330..0447d995a 100644
--- a/plugins/new_user_dialog/localization/lv_LV.inc
+++ b/plugins/new_user_dialog/localization/lv_LV.inc
@@ -17,7 +17,7 @@
*/
$labels = array();
-$labels['identitydialogtitle'] = 'LÅ«dzu, aizpildiet nosÅ«tÄ«tÄja identifikÄcijas informÄciju';
-$labels['identitydialoghint'] = 'Å is logs parÄdÄ«sies tikai pirmajÄ pieteikÅ¡anÄs reizÄ“';
+$labels['identitydialogtitle'] = 'LÅ«dzu aizpildiet JÅ«su, kÄ sÅ«tÄ«tÄja, identitÄtes informÄciju';
+$labels['identitydialoghint'] = 'Å is logs parÄdÄ«sies tikai pirmajÄ autorizÄcijas reizÄ“.';
?> \ No newline at end of file
diff --git a/plugins/new_user_identity/new_user_identity.php b/plugins/new_user_identity/new_user_identity.php
index d32051e00..bb0821a53 100644
--- a/plugins/new_user_identity/new_user_identity.php
+++ b/plugins/new_user_identity/new_user_identity.php
@@ -8,6 +8,7 @@
*
* @version @package_version@
* @author Kris Steinhoff
+ * @license GNU GPLv3+
*
* Example configuration:
*
diff --git a/plugins/new_user_identity/package.xml b/plugins/new_user_identity/package.xml
index e50cd9255..45a3c4c8d 100644
--- a/plugins/new_user_identity/package.xml
+++ b/plugins/new_user_identity/package.xml
@@ -24,7 +24,7 @@
<release>stable</release>
<api>stable</api>
</stability>
- <license uri="http://www.gnu.org/licenses/gpl-2.0.html">GNU GPLv2</license>
+ <license uri="http://www.gnu.org/licenses/gpl.html">GNU GPLv3+</license>
<notes>-</notes>
<contents>
<dir baseinstalldir="/" name="/">
diff --git a/plugins/newmail_notifier/localization/lb_LU.inc b/plugins/newmail_notifier/localization/lb_LU.inc
new file mode 100644
index 000000000..c4b014819
--- /dev/null
+++ b/plugins/newmail_notifier/localization/lb_LU.inc
@@ -0,0 +1,29 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | plugins/newmail_notifier/localization/<lang>.inc |
+ | |
+ | Localization file of the Roundcube Webmail New Mail Notifier plugin |
+ | Copyright (C) 2012-2013, The Roundcube Dev Team |
+ | |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
+ | |
+ +-----------------------------------------------------------------------+
+
+ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-newmail_notifier/
+*/
+
+$labels['basic'] = 'Browser-Notifikatioun bei neiem Message uweisen';
+$labels['desktop'] = 'Desktop-Notifikatioun bei neiem Message uweisen';
+$labels['sound'] = 'Dësen Toun bei neiem Message spillen';
+$labels['test'] = 'Test';
+$labels['title'] = 'Nei E-Mail!';
+$labels['body'] = 'Du hues en neie Message kritt.';
+$labels['testbody'] = 'Dëst ass eng Test-Benoorichtegung.';
+$labels['desktopdisabled'] = 'Desktop-Notifikatioune sinn an dengem Browser ausgeschalt.';
+$labels['desktopunsupported'] = 'Däi Browser ënnerstëtzt keng Desktop-Notifikatiounen.';
+
+?>
diff --git a/plugins/newmail_notifier/localization/lv_LV.inc b/plugins/newmail_notifier/localization/lv_LV.inc
index 9df738b25..da9603cd5 100644
--- a/plugins/newmail_notifier/localization/lv_LV.inc
+++ b/plugins/newmail_notifier/localization/lv_LV.inc
@@ -16,14 +16,14 @@
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-newmail_notifier/
*/
-$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['basic'] = 'Saņemot jaunu vÄ“stuli, parÄdÄ«t paziņojumu';
+$labels['desktop'] = 'Saņemot jaunu vÄ“stuli, parÄdÄ«t darbavirsmas paziņojumu';
+$labels['sound'] = 'Saņemot jaunu vÄ“stuli, atskaņot skaņas signÄlu';
+$labels['test'] = 'PÄrbaudÄ«t';
+$labels['title'] = 'Jauns e-pasts!';
+$labels['body'] = 'Jūs esat saņēmis jaunu vēstuli.';
$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.';
+$labels['desktopdisabled'] = 'Darbavirsmas paziņojumi JÅ«su pÄrlÅ«kprogrammÄ ir atslÄ“gti.';
+$labels['desktopunsupported'] = 'JÅ«su pÄrlÅ«kprogramma neatbalsta darbavirsmas paziņojumus.';
?>
diff --git a/plugins/newmail_notifier/newmail_notifier.php b/plugins/newmail_notifier/newmail_notifier.php
index 61f7bdbaa..ca1c2ff67 100644
--- a/plugins/newmail_notifier/newmail_notifier.php
+++ b/plugins/newmail_notifier/newmail_notifier.php
@@ -15,18 +15,18 @@
*
* 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 free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
* 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.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
*/
class newmail_notifier extends rcube_plugin
diff --git a/plugins/newmail_notifier/package.xml b/plugins/newmail_notifier/package.xml
index ea0fcd9c1..b8ef34933 100644
--- a/plugins/newmail_notifier/package.xml
+++ b/plugins/newmail_notifier/package.xml
@@ -28,7 +28,7 @@
<release>stable</release>
<api>stable</api>
</stability>
- <license uri="http://www.gnu.org/licenses/gpl-2.0.html">GNU GPLv2</license>
+ <license uri="http://www.gnu.org/licenses/gpl.html">GNU GPLv3+</license>
<notes>-</notes>
<contents>
<dir baseinstalldir="/" name="/">
diff --git a/plugins/password/README b/plugins/password/README
index 0ccc8ad23..af70156a6 100644
--- a/plugins/password/README
+++ b/plugins/password/README
@@ -1,26 +1,24 @@
-----------------------------------------------------------------------
Password Plugin for Roundcube
-----------------------------------------------------------------------
-
Plugin that adds a possibility to change user password using many
methods (drivers) via Settings/Password tab.
-
-----------------------------------------------------------------------
- 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 free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
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
+ 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.
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see http://www.gnu.org/licenses/.
@version @package_version@
- @author Aleksander 'A.L.E.C' Machniak <alec@alec.pl>
+ @author Aleksander Machniak <alec@alec.pl>
@author <see driver files for driver authors>
-----------------------------------------------------------------------
@@ -65,7 +63,7 @@
-------------------
You can specify which database to connect by 'password_db_dsn' option and
- what SQL query to execute by 'password_query'. See main.inc.php.dist file for
+ what SQL query to execute by 'password_query'. See config.inc.php.dist file for
more info.
Example implementations of an update_passwd function:
diff --git a/plugins/password/localization/gl_ES.inc b/plugins/password/localization/gl_ES.inc
index 245d1c634..93c505a6a 100644
--- a/plugins/password/localization/gl_ES.inc
+++ b/plugins/password/localization/gl_ES.inc
@@ -26,7 +26,7 @@ $messages = array();
$messages['nopassword'] = 'Por favor, introduza un contrasinal novo.';
$messages['nocurpassword'] = 'Por favor, introduza o contrasinal actual.';
$messages['passwordincorrect'] = 'O contrasinal actual é incorrecto.';
-$messages['passwordinconsistency'] = 'Os contrasinals non coinciden. Por favor, inténteo de novo.';
+$messages['passwordinconsistency'] = 'Os contrasinais non cadran. Por favor, inténteo outra vez.';
$messages['crypterror'] = 'Non foi posible gardar o contrasinal novo. Falta a función de cifrado.';
$messages['connecterror'] = 'Non foi posible gardar o contrasinal novo. Erro de conexión';
$messages['internalerror'] = 'Non foi posible gardar o contrasinal novo.';
diff --git a/plugins/password/localization/lb_LU.inc b/plugins/password/localization/lb_LU.inc
new file mode 100644
index 000000000..9962aed28
--- /dev/null
+++ b/plugins/password/localization/lb_LU.inc
@@ -0,0 +1,37 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | plugins/password/localization/<lang>.inc |
+ | |
+ | Localization file of the Roundcube Webmail Password plugin |
+ | Copyright (C) 2012-2013, The Roundcube Dev Team |
+ | |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
+ | |
+ +-----------------------------------------------------------------------+
+
+ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-password/
+*/
+
+$labels = array();
+$labels['changepasswd'] = 'Passwuert änneren';
+$labels['curpasswd'] = 'Aktuellt Passwuert:';
+$labels['newpasswd'] = 'Neit Passwuert:';
+$labels['confpasswd'] = 'Neit Passwuert bestätegen:';
+
+$messages = array();
+$messages['nopassword'] = 'Gëff wann ech gelift en neit Passwuert an.';
+$messages['nocurpassword'] = 'Gëff wann ech gelift dat aktuellt Passwuert an.';
+$messages['passwordincorrect'] = 'Aktuellt Passwuert net korrekt.';
+$messages['passwordinconsistency'] = 'D\'Passwierder passen net, probéier wann ech gelift nach eng Kéier.';
+$messages['crypterror'] = 'Passwuert konnt net gespäichert ginn. Verschlësselungs-Funktioun feelt.';
+$messages['connecterror'] = 'Passwuert konnt net gespäichert ginn. Connectiouns-Feeler.';
+$messages['internalerror'] = 'Neit Passwuert konnt net gespäichert ginn.';
+$messages['passwordshort'] = 'D\'Passwuert muss mindestens $length Zeeche laang sinn.';
+$messages['passwordweak'] = 'D\'Passwuert muss mindestens eng Zuel an ee Sazzeechen enthalen.';
+$messages['passwordforbidden'] = 'D\'Passwuert enthält verbueden Zeechen.';
+
+?>
diff --git a/plugins/password/localization/lv_LV.inc b/plugins/password/localization/lv_LV.inc
index 650d31b2c..ac0e5da79 100644
--- a/plugins/password/localization/lv_LV.inc
+++ b/plugins/password/localization/lv_LV.inc
@@ -20,18 +20,18 @@ $labels = array();
$labels['changepasswd'] = 'Nomainīt paroli';
$labels['curpasswd'] = 'PaÅ¡reizÄ“jÄ parole:';
$labels['newpasswd'] = 'JaunÄ parole:';
-$labels['confpasswd'] = 'VÄ“lreiz jauno paroli:';
+$labels['confpasswd'] = 'ApstiprinÄt jauno paroli:';
$messages = array();
-$messages['nopassword'] = 'LÅ«dzu, ievadiet jauno paroli.';
-$messages['nocurpassword'] = 'Lūdzu, ievadiet pašreizējo paroli.';
-$messages['passwordincorrect'] = 'PaÅ¡reizÄ“jÄ parole nepareiza.';
+$messages['nopassword'] = 'LÅ«dzu ievadiet jauno paroli.';
+$messages['nocurpassword'] = 'Lūdzu ievadiet pašreizējo paroli.';
+$messages['passwordincorrect'] = 'PaÅ¡reizÄ“jÄ parole nav pareiza.';
$messages['passwordinconsistency'] = 'Paroles nesakrīt. Lūdzu, ievadiet vēlreiz.';
-$messages['crypterror'] = 'NevarÄ“ja saglabÄt jauno paroli. TrÅ«kst kriptÄ“Å¡anas funkcija.';
+$messages['crypterror'] = 'NevarÄ“ja saglabÄt jauno paroli. TrÅ«kst kriptÄ“Å¡anas funkcijas.';
$messages['connecterror'] = 'NevarÄ“ja saglabÄt jauno paroli. Savienojuma kļūda.';
$messages['internalerror'] = 'NevarÄ“ja saglabÄt jauno paroli.';
-$messages['passwordshort'] = 'Jaunajai parolei jÄbÅ«t vismaz $length simbola garai.';
-$messages['passwordweak'] = 'Jaunajai parolei jÄsatur vismaz viens cipars un punktuÄcijas simbols.';
-$messages['passwordforbidden'] = 'Password contains forbidden characters.';
+$messages['passwordshort'] = 'Jaunajai parolei jÄbÅ«t vismaz $length simbolu garai.';
+$messages['passwordweak'] = 'Jaunajai parolei jÄsatur vismaz viens cipars un speciÄlais simbols.';
+$messages['passwordforbidden'] = 'Parole satur neatļautus simbolus.';
?>
diff --git a/plugins/password/package.xml b/plugins/password/package.xml
index 81427a986..16eda1ad0 100644
--- a/plugins/password/package.xml
+++ b/plugins/password/package.xml
@@ -24,7 +24,7 @@
<release>stable</release>
<api>stable</api>
</stability>
- <license uri="http://www.gnu.org/licenses/gpl-2.0.html">GNU GPLv2</license>
+ <license uri="http://www.gnu.org/licenses/gpl.html">GNU GPLv3+</license>
<notes>
Added password_force_save option
</notes>
diff --git a/plugins/password/password.php b/plugins/password/password.php
index e16b4d0b9..f1a3e17b9 100644
--- a/plugins/password/password.php
+++ b/plugins/password/password.php
@@ -1,32 +1,26 @@
<?php
-/*
- +-------------------------------------------------------------------------+
- | Password Plugin for Roundcube |
- | @version @package_version@ |
- | |
- | Copyright (C) 2009-2010, Roundcube Dev. |
- | |
- | 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. |
- | |
- +-------------------------------------------------------------------------+
- | Author: Aleksander Machniak <alec@alec.pl> |
- +-------------------------------------------------------------------------+
-
- $Id: index.php 2645 2009-06-15 07:01:36Z alec $
-
-*/
+/**
+ * Password Plugin for Roundcube
+ *
+ * @version @package_version@
+ * @author Aleksander Machniak <alec@alec.pl>
+ *
+ * Copyright (C) 2005-2013, The Roundcube Dev Team
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see http://www.gnu.org/licenses/.
+ */
define('PASSWORD_CRYPT_ERROR', 1);
define('PASSWORD_ERROR', 2);
diff --git a/plugins/redundant_attachments/config.inc.php.dist b/plugins/redundant_attachments/config.inc.php.dist
index 6c317ead1..a0be3755e 100644
--- a/plugins/redundant_attachments/config.inc.php.dist
+++ b/plugins/redundant_attachments/config.inc.php.dist
@@ -6,8 +6,8 @@
// to use memcache as a fallback when write-master is unavailable.
$rcmail_config['redundant_attachments_memcache'] = false;
-// When memcache is used, attachment data expires after
-// specied TTL time in seconds (max.2592000). Default is 12 hours.
-$rcmail_config['redundant_attachments_memcache_ttl'] = 12 * 60 * 60;
+// Attachment data expires after specied TTL time in seconds (max.2592000).
+// Default is 12 hours.
+$rcmail_config['redundant_attachments_cache_ttl'] = 12 * 60 * 60;
?>
diff --git a/plugins/redundant_attachments/redundant_attachments.php b/plugins/redundant_attachments/redundant_attachments.php
index 4ebc8dad7..c0affad3c 100644
--- a/plugins/redundant_attachments/redundant_attachments.php
+++ b/plugins/redundant_attachments/redundant_attachments.php
@@ -68,13 +68,14 @@ class redundant_attachments extends filesystem_attachments
// load configuration
$this->load_config();
+ $ttl = 12 * 60 * 60; // 12 hours
+ $ttl = $rcmail->config->get('redundant_attachments_cache_ttl', $ttl);
+
// Init SQL cache (disable cache data serialization)
- $this->cache = $rcmail->get_cache($this->prefix, 'db', 0, false);
+ $this->cache = $rcmail->get_cache($this->prefix, 'db', $ttl, false);
// Init memcache (fallback) cache
if ($rcmail->config->get('redundant_attachments_memcache')) {
- $ttl = 12 * 60 * 60; // 12 hours
- $ttl = (int) $rcmail->config->get('redundant_attachments_memcache_ttl', $ttl);
$this->mem_cache = $rcmail->get_cache($this->prefix, 'memcache', $ttl, false);
}
diff --git a/plugins/show_additional_headers/package.xml b/plugins/show_additional_headers/package.xml
index 7297916c3..9ca60baa9 100644
--- a/plugins/show_additional_headers/package.xml
+++ b/plugins/show_additional_headers/package.xml
@@ -24,7 +24,7 @@
<release>stable</release>
<api>stable</api>
</stability>
- <license uri="http://www.gnu.org/licenses/gpl-2.0.html">GNU GPLv2</license>
+ <license uri="http://www.gnu.org/licenses/gpl.html">GNU GPLv3+</license>
<notes>-</notes>
<contents>
<dir baseinstalldir="/" name="/">
diff --git a/plugins/show_additional_headers/show_additional_headers.php b/plugins/show_additional_headers/show_additional_headers.php
index 1375348c2..c2b0ca1d3 100644
--- a/plugins/show_additional_headers/show_additional_headers.php
+++ b/plugins/show_additional_headers/show_additional_headers.php
@@ -6,12 +6,12 @@
* Proof-of-concept plugin which will fetch additional headers
* and display them in the message view.
*
- * Enable the plugin in config/main.inc.php and add your desired headers:
+ * Enable the plugin in config.inc.php and add your desired headers:
* $rcmail_config['show_additional_headers'] = array('User-Agent');
*
* @version @package_version@
* @author Thomas Bruederli
- * @website http://roundcube.net
+ * @license GNU GPLv3+
*/
class show_additional_headers extends rcube_plugin
{
diff --git a/plugins/subscriptions_option/localization/gl_ES.inc b/plugins/subscriptions_option/localization/gl_ES.inc
index bbff10c3b..a273777da 100644
--- a/plugins/subscriptions_option/localization/gl_ES.inc
+++ b/plugins/subscriptions_option/localization/gl_ES.inc
@@ -17,6 +17,6 @@
*/
$labels = array();
-$labels['useimapsubscriptions'] = 'Usar suscripcións IMAP';
+$labels['useimapsubscriptions'] = 'Usar subscricións IMAP';
?>
diff --git a/plugins/subscriptions_option/localization/lb_LU.inc b/plugins/subscriptions_option/localization/lb_LU.inc
new file mode 100644
index 000000000..d9432634b
--- /dev/null
+++ b/plugins/subscriptions_option/localization/lb_LU.inc
@@ -0,0 +1,22 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | plugins/subscriptions_option/localization/<lang>.inc |
+ | |
+ | Localization file of the Roundcube Webmail Subscriptions plugin |
+ | Copyright (C) 2012-2013, The Roundcube Dev Team |
+ | |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
+ | |
+ +-----------------------------------------------------------------------+
+
+ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-subscriptions_option/
+*/
+
+$labels = array();
+$labels['useimapsubscriptions'] = 'IMAP-Abonnementer benotzen';
+
+?>
diff --git a/plugins/subscriptions_option/package.xml b/plugins/subscriptions_option/package.xml
index 79d44f8c2..04f2c1b3c 100644
--- a/plugins/subscriptions_option/package.xml
+++ b/plugins/subscriptions_option/package.xml
@@ -32,7 +32,7 @@
<release>stable</release>
<api>stable</api>
</stability>
- <license uri="http://www.gnu.org/licenses/gpl-2.0.html">GNU GPLv2</license>
+ <license uri="http://www.gnu.org/licenses/gpl.html">GNU GPLv3+</license>
<notes>-</notes>
<contents>
<dir baseinstalldir="/" name="/">
diff --git a/plugins/subscriptions_option/subscriptions_option.php b/plugins/subscriptions_option/subscriptions_option.php
index 7678d8e94..284c048df 100644
--- a/plugins/subscriptions_option/subscriptions_option.php
+++ b/plugins/subscriptions_option/subscriptions_option.php
@@ -7,7 +7,7 @@
* It includes a toggle on the settings page under "Server Settings".
* The preference can also be locked
*
- * Add it to the plugins list in config/main.inc.php to enable the user option
+ * Add it to the plugins list in config.inc.php to enable the user option
* The user option can be hidden and set globally by adding 'use_subscriptions'
* to the 'dont_override' configure line:
* $rcmail_config['dont_override'] = array('use_subscriptions');
@@ -21,6 +21,7 @@
*
* @version @package_version@
* @author Ziba Scott
+ * @license GNU GPLv3+
*/
class subscriptions_option extends rcube_plugin
{
diff --git a/plugins/userinfo/localization/lb_LU.inc b/plugins/userinfo/localization/lb_LU.inc
new file mode 100644
index 000000000..d8394f6d8
--- /dev/null
+++ b/plugins/userinfo/localization/lb_LU.inc
@@ -0,0 +1,25 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | plugins/userinfo/localization/<lang>.inc |
+ | |
+ | Localization file of the Roundcube Webmail Userinfo plugin |
+ | Copyright (C) 2012-2013, The Roundcube Dev Team |
+ | |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
+ | |
+ +-----------------------------------------------------------------------+
+
+ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-userinfo/
+*/
+
+$labels = array();
+$labels['userinfo'] = 'Benotzer-Info';
+$labels['created'] = 'Erstallt';
+$labels['lastlogin'] = 'Leschte Login';
+$labels['defaultidentity'] = 'Standard-Identitéit';
+
+?> \ No newline at end of file
diff --git a/plugins/vcard_attachments/localization/gl_ES.inc b/plugins/vcard_attachments/localization/gl_ES.inc
index b502c85c7..806f6bb7d 100644
--- a/plugins/vcard_attachments/localization/gl_ES.inc
+++ b/plugins/vcard_attachments/localization/gl_ES.inc
@@ -17,7 +17,7 @@
*/
$labels = array();
-$labels['addvcardmsg'] = 'Engadir a tarxeta ao caderno de enderezos';
-$labels['vcardsavefailed'] = 'Non foi posible gardar a tarxeta';
+$labels['addvcardmsg'] = 'Engadir vCard ao caderno de enderezos';
+$labels['vcardsavefailed'] = 'Non foi posible gardar a vCard';
?> \ No newline at end of file
diff --git a/plugins/vcard_attachments/localization/lb_LU.inc b/plugins/vcard_attachments/localization/lb_LU.inc
new file mode 100644
index 000000000..b9d23eaa5
--- /dev/null
+++ b/plugins/vcard_attachments/localization/lb_LU.inc
@@ -0,0 +1,23 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | plugins/vcard_attachments/localization/<lang>.inc |
+ | |
+ | Localization file of the Roundcube Webmail Vcard Attachments plugin |
+ | Copyright (C) 2012-2013, The Roundcube Dev Team |
+ | |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
+ | |
+ +-----------------------------------------------------------------------+
+
+ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-vcard_attachments/
+*/
+
+$labels = array();
+$labels['addvcardmsg'] = 'vCard an d\'Adressbuch setzen';
+$labels['vcardsavefailed'] = 'vCard kann net gespäichert ginn';
+
+?> \ No newline at end of file
diff --git a/plugins/virtuser_file/virtuser_file.php b/plugins/virtuser_file/virtuser_file.php
index 2c705b2d0..ed0eba189 100644
--- a/plugins/virtuser_file/virtuser_file.php
+++ b/plugins/virtuser_file/virtuser_file.php
@@ -3,7 +3,7 @@
/**
* File based User-to-Email and Email-to-User lookup
*
- * Add it to the plugins list in config/main.inc.php and set
+ * Add it to the plugins list in config.inc.php and set
* path to a virtuser table file to resolve user names and e-mail
* addresses
* $rcmail_config['virtuser_file'] = '';
@@ -19,13 +19,13 @@ class virtuser_file extends rcube_plugin
function init()
{
- $this->app = rcmail::get_instance();
- $this->file = $this->app->config->get('virtuser_file');
+ $this->app = rcmail::get_instance();
+ $this->file = $this->app->config->get('virtuser_file');
- if ($this->file) {
- $this->add_hook('user2email', array($this, 'user2email'));
- $this->add_hook('email2user', array($this, 'email2user'));
- }
+ if ($this->file) {
+ $this->add_hook('user2email', array($this, 'user2email'));
+ $this->add_hook('email2user', array($this, 'email2user'));
+ }
}
/**
@@ -34,25 +34,24 @@ class virtuser_file extends rcube_plugin
function user2email($p)
{
$r = $this->findinvirtual('/\s' . preg_quote($p['user'], '/') . '\s*$/');
- $result = array();
+ $result = array();
- for ($i=0; $i<count($r); $i++)
- {
- $arr = preg_split('/\s+/', $r[$i]);
+ for ($i=0; $i<count($r); $i++) {
+ $arr = preg_split('/\s+/', $r[$i]);
- if (count($arr) > 0 && strpos($arr[0], '@')) {
- $result[] = rcube_utils::idn_to_ascii(trim(str_replace('\\@', '@', $arr[0])));
+ if (count($arr) > 0 && strpos($arr[0], '@')) {
+ $result[] = rcube_utils::idn_to_ascii(trim(str_replace('\\@', '@', $arr[0])));
- if ($p['first']) {
- $p['email'] = $result[0];
- break;
- }
- }
- }
+ if ($p['first']) {
+ $p['email'] = $result[0];
+ break;
+ }
+ }
+ }
- $p['email'] = empty($result) ? NULL : $result;
+ $p['email'] = empty($result) ? NULL : $result;
- return $p;
+ return $p;
}
/**
@@ -60,18 +59,18 @@ class virtuser_file extends rcube_plugin
*/
function email2user($p)
{
- $r = $this->findinvirtual('/^' . preg_quote($p['email'], '/') . '\s/');
+ $r = $this->findinvirtual('/^' . preg_quote($p['email'], '/') . '\s/');
- for ($i=0; $i<count($r); $i++) {
- $arr = preg_split('/\s+/', trim($r[$i]));
+ for ($i=0; $i<count($r); $i++) {
+ $arr = preg_split('/\s+/', trim($r[$i]));
- if (count($arr) > 0) {
- $p['user'] = trim($arr[count($arr)-1]);
- break;
- }
- }
+ if (count($arr) > 0) {
+ $p['user'] = trim($arr[count($arr)-1]);
+ break;
+ }
+ }
- return $p;
+ return $p;
}
/**
@@ -82,26 +81,25 @@ class virtuser_file extends rcube_plugin
*/
private function findinvirtual($pattern)
{
- $result = array();
- $virtual = null;
+ $result = array();
+ $virtual = null;
- if ($this->file)
- $virtual = file($this->file);
+ if ($this->file)
+ $virtual = file($this->file);
- if (empty($virtual))
- return $result;
+ if (empty($virtual))
+ return $result;
- // check each line for matches
- foreach ($virtual as $line) {
- $line = trim($line);
- if (empty($line) || $line[0]=='#')
- continue;
+ // check each line for matches
+ foreach ($virtual as $line) {
+ $line = trim($line);
+ if (empty($line) || $line[0]=='#')
+ continue;
- if (preg_match($pattern, $line))
- $result[] = $line;
- }
+ if (preg_match($pattern, $line))
+ $result[] = $line;
+ }
- return $result;
+ return $result;
}
-
}
diff --git a/plugins/virtuser_query/package.xml b/plugins/virtuser_query/package.xml
index b7ea565d8..9430bf69d 100644
--- a/plugins/virtuser_query/package.xml
+++ b/plugins/virtuser_query/package.xml
@@ -22,7 +22,7 @@
<release>stable</release>
<api>stable</api>
</stability>
- <license uri="http://www.gnu.org/licenses/gpl-2.0.html">GNU GPLv2</license>
+ <license uri="http://www.gnu.org/licenses/gpl.html">GNU GPLv3+</license>
<notes>-</notes>
<contents>
<dir baseinstalldir="/" name="/">
diff --git a/plugins/virtuser_query/virtuser_query.php b/plugins/virtuser_query/virtuser_query.php
index 9cf27e61c..3181cda94 100644
--- a/plugins/virtuser_query/virtuser_query.php
+++ b/plugins/virtuser_query/virtuser_query.php
@@ -3,7 +3,7 @@
/**
* DB based User-to-Email and Email-to-User lookup
*
- * Add it to the plugins list in config/main.inc.php and set
+ * Add it to the plugins list in config.inc.php and set
* SQL queries to resolve usernames, e-mail addresses and hostnames from the database
* %u will be replaced with the current username for login.
* %m will be replaced with the current e-mail address for login.
@@ -24,6 +24,7 @@
* @author Aleksander Machniak <alec@alec.pl>
* @author Steffen Vogel
* @author Tim Gerundt
+ * @license GNU GPLv3+
*/
class virtuser_query extends rcube_plugin
{
diff --git a/plugins/zipdownload/localization/lb_LU.inc b/plugins/zipdownload/localization/lb_LU.inc
new file mode 100644
index 000000000..6721c51cb
--- /dev/null
+++ b/plugins/zipdownload/localization/lb_LU.inc
@@ -0,0 +1,23 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | plugins/zipdownload/localization/<lang>.inc |
+ | |
+ | Localization file of the Roundcube Webmail Zipdownload plugin |
+ | Copyright (C) 2012-2013, The Roundcube Dev Team |
+ | |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
+ | |
+ +-----------------------------------------------------------------------+
+
+ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-zipdownload/
+*/
+
+$labels = array();
+$labels['downloadall'] = 'All d\'Unhäng eroflueden';
+$labels['downloadfolder'] = 'Dossier eroflueden';
+
+?> \ No newline at end of file
diff --git a/plugins/zipdownload/zipdownload.php b/plugins/zipdownload/zipdownload.php
index fbf1d2342..59431267d 100644
--- a/plugins/zipdownload/zipdownload.php
+++ b/plugins/zipdownload/zipdownload.php
@@ -108,7 +108,7 @@ class zipdownload extends rcube_plugin
foreach ($message->attachments as $part) {
$pid = $part->mime_id;
$part = $message->mime_parts[$pid];
- $disp_name = $this->_convert_filename($part->filename, $part->charset);
+ $disp_name = $this->_convert_filename($part->filename);
if ($part->body) {
$orig_message_raw = $part->body;
@@ -263,9 +263,9 @@ class zipdownload extends rcube_plugin
/**
* Helper function to convert filenames to the configured charset
*/
- private function _convert_filename($str, $from = RCUBE_CHARSET)
+ private function _convert_filename($str)
{
- $str = rcube_charset::convert($str, $from == '' ? RCUBE_CHARSET : $from, $this->charset);
+ $str = rcube_charset::convert($str, RCUBE_CHARSET, $this->charset);
return strtr($str, array(':'=>'', '/'=>'-'));
}
diff --git a/program/include/bc.php b/program/include/bc.php
index 0ddfb3215..a7d7b5ac1 100644
--- a/program/include/bc.php
+++ b/program/include/bc.php
@@ -62,7 +62,7 @@ function rcmail_url($action, $p=array(), $task=null)
function rcmail_temp_gc()
{
- rcmail::get_instance()->temp_gc();
+ rcmail::get_instance()->gc_temp();
}
function rcube_charset_convert($str, $from, $to=NULL)
@@ -405,6 +405,16 @@ function enriched_to_html($data)
return rcube_enriched::to_html($data);
}
+function strip_quotes($str)
+{
+ return str_replace(array("'", '"'), '', $str);
+}
+
+function strip_newlines($str)
+{
+ return preg_replace('/[\r\n]/', '', $str);
+}
+
class rcube_html_page extends rcmail_html_page
{
}
diff --git a/program/include/rcmail.php b/program/include/rcmail.php
index 89f2f9647..800eddac6 100644
--- a/program/include/rcmail.php
+++ b/program/include/rcmail.php
@@ -51,6 +51,7 @@ class rcmail extends rcube
*/
public $action = '';
public $comm_path = './';
+ public $filename = '';
private $address_books = array();
private $action_map = array();
@@ -65,12 +66,13 @@ class rcmail extends rcube
/**
* This implements the 'singleton' design pattern
*
+ * @param string Environment name to run (e.g. live, dev, test)
* @return rcmail The one and only instance
*/
- static function get_instance()
+ static function get_instance($env = '')
{
if (!self::$instance || !is_a(self::$instance, 'rcmail')) {
- self::$instance = new rcmail();
+ self::$instance = new rcmail($env);
self::$instance->startup(); // init AFTER object was linked with self::$instance
}
@@ -86,6 +88,10 @@ class rcmail extends rcube
{
$this->init(self::INIT_WITH_DB | self::INIT_WITH_PLUGINS);
+ // set filename if not index.php
+ if (($basename = basename($_SERVER['SCRIPT_FILENAME'])) && $basename != 'index.php')
+ $this->filename = $basename;
+
// start session
$this->session_init();
@@ -162,7 +168,7 @@ class rcmail extends rcube
setlocale(LC_ALL, $lang . '.utf8', $lang . '.UTF-8', 'en_US.utf8', 'en_US.UTF-8');
// workaround for http://bugs.php.net/bug.php?id=18556
- if (in_array($lang, array('tr_TR', 'ku', 'az_AZ'))) {
+ if (version_compare(PHP_VERSION, '5.5.0', '<') && in_array($lang, array('tr_TR', 'ku', 'az_AZ'))) {
setlocale(LC_CTYPE, 'en_US.utf8', 'en_US.UTF-8');
}
}
@@ -228,6 +234,11 @@ class rcmail extends rcube
}
if (!$contacts) {
+ // there's no default, just return
+ if ($default) {
+ return null;
+ }
+
self::raise_error(array(
'code' => 700, 'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
@@ -289,7 +300,7 @@ class rcmail extends rcube
$list[$id] = array(
'id' => $id,
'name' => html::quote($prop['name']),
- 'groups' => is_array($prop['groups']),
+ 'groups' => !empty($prop['groups']) || !empty($prop['group_filters']),
'readonly' => !$prop['writable'],
'hidden' => $prop['hidden'],
'autocomplete' => in_array($id, $autocomplete)
@@ -719,7 +730,7 @@ class rcmail extends rcube
$p['_task'] = $task;
unset($p['task']);
- $url = './';
+ $url = './' . $this->filename;
$delm = '?';
foreach (array_reverse($p) as $key => $val) {
if ($val !== '' && $val !== null) {
@@ -744,11 +755,6 @@ class rcmail extends rcube
$book->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'))
@@ -1325,6 +1331,7 @@ class rcmail extends rcube
$realnames = (bool)$attrib['realnames'];
$msgcounts = $this->storage->get_cache('messagecount');
$collapsed = $this->config->get('collapsed_folders');
+ $realnames = $this->config->get('show_real_foldernames');
$out = '';
foreach ($arrFolders as $folder) {
@@ -1481,8 +1488,10 @@ class rcmail extends rcube
*/
public function localize_foldername($name, $with_path = true)
{
+ $realnames = $this->config->get('show_real_foldernames');
+
// try to localize path of the folder
- if ($with_path) {
+ if ($with_path && !$realnames) {
$storage = $this->get_storage();
$delimiter = $storage->get_hierarchy_delimiter();
$path = explode($delimiter, $name);
@@ -1499,12 +1508,11 @@ class rcmail extends rcube
}
}
- if ($folder_class = $this->folder_classname($name)) {
+ if (!$realnames && ($folder_class = $this->folder_classname($name))) {
return $this->gettext($folder_class);
}
- else {
- return rcube_charset::convert($name, 'UTF7-IMAP');
- }
+
+ return rcube_charset::convert($name, 'UTF7-IMAP');
}
@@ -1559,11 +1567,7 @@ class rcmail extends rcube
$quota_result = (array) $quota;
$quota_result['type'] = isset($_SESSION['quota_display']) ? $_SESSION['quota_display'] : '';
- if (!$quota['total'] && $this->config->get('quota_zero_as_unlimited')) {
- $quota_result['title'] = $this->gettext('unlimited');
- $quota_result['percent'] = 0;
- }
- else if ($quota['total']) {
+ if ($quota['total'] > 0) {
if (!isset($quota['percent'])) {
$quota_result['percent'] = min(100, round(($quota['used']/max(1,$quota['total']))*100));
}
@@ -1582,7 +1586,8 @@ class rcmail extends rcube
}
}
else {
- $quota_result['title'] = $this->gettext('unknown');
+ $unlimited = $this->config->get('quota_zero_as_unlimited');
+ $quota_result['title'] = $this->gettext($unlimited ? 'unlimited' : 'unknown');
$quota_result['percent'] = 0;
}
@@ -1761,7 +1766,8 @@ class rcmail extends rcube
public function upload_init()
{
// Enable upload progress bar
- if (($seconds = $this->config->get('upload_progress')) && ini_get('apc.rfc1867')) {
+ $rfc1867 = filter_var(ini_get('apc.rfc1867'), FILTER_VALIDATE_BOOLEAN);
+ if ($rfc1867 && ($seconds = $this->config->get('upload_progress'))) {
if ($field_name = ini_get('apc.rfc1867_name')) {
$this->output->set_env('upload_progress_name', $field_name);
$this->output->set_env('upload_progress_time', (int) $seconds);
diff --git a/program/include/rcmail_output_html.php b/program/include/rcmail_output_html.php
index 02eef2fd1..998779509 100644
--- a/program/include/rcmail_output_html.php
+++ b/program/include/rcmail_output_html.php
@@ -67,11 +67,12 @@ class rcmail_output_html extends rcmail_output
//$this->framed = $framed;
$this->set_env('task', $task);
$this->set_env('x_frame_options', $this->config->get('x_frame_options', 'sameorigin'));
+ $this->set_env('standard_windows', (bool) $this->config->get('standard_windows'));
// add cookie info
$this->set_env('cookie_domain', ini_get('session.cookie_domain'));
$this->set_env('cookie_path', ini_get('session.cookie_path'));
- $this->set_env('cookie_secure', ini_get('session.cookie_secure'));
+ $this->set_env('cookie_secure', filter_var(ini_get('session.cookie_secure'), FILTER_VALIDATE_BOOLEAN));
// load the correct skin (in case user-defined)
$skin = $this->config->get('skin');
@@ -105,7 +106,6 @@ class rcmail_output_html extends rcmail_output
));
}
-
/**
* Set environment variable
*
@@ -121,7 +121,6 @@ class rcmail_output_html extends rcmail_output
}
}
-
/**
* Getter for the current page title
*
@@ -145,17 +144,17 @@ class rcmail_output_html extends rcmail_output
return $title;
}
-
/**
* Set skin
*/
public function set_skin($skin)
{
$valid = false;
+ $path = RCUBE_INSTALL_PATH . 'skins/';
- if (!empty($skin) && is_dir('skins/'.$skin) && is_readable('skins/'.$skin)) {
- $skin_path = 'skins/'.$skin;
- $valid = true;
+ if (!empty($skin) && is_dir($path . $skin) && is_readable($path . $skin)) {
+ $skin_path = 'skins/' . $skin;
+ $valid = true;
}
else {
$skin_path = $this->config->get('skin_path');
@@ -183,13 +182,16 @@ class rcmail_output_html extends rcmail_output
$this->skin_paths[] = $skin_path;
// read meta file and check for dependecies
- $meta = @json_decode(@file_get_contents($skin_path.'/meta.json'), true);
- if ($meta['extends'] && is_dir('skins/' . $meta['extends'])) {
- $this->load_skin('skins/' . $meta['extends']);
+ $meta = @file_get_contents(RCUBE_INSTALL_PATH . $skin_path . '/meta.json');
+ $meta = @json_decode($meta, true);
+ if ($meta['extends']) {
+ $path = RCUBE_INSTALL_PATH . 'skins/';
+ if (is_dir($path . $meta['extends']) && is_readable($path . $meta['extends'])) {
+ $this->load_skin('skins/' . $meta['extends']);
+ }
}
}
-
/**
* Check if a specific template exists
*
@@ -198,16 +200,17 @@ class rcmail_output_html extends rcmail_output
*/
public function template_exists($name)
{
- $found = false;
foreach ($this->skin_paths as $skin_path) {
- $filename = $skin_path . '/templates/' . $name . '.html';
- $found = (is_file($filename) && is_readable($filename)) || ($this->deprecated_templates[$name] && $this->template_exists($this->deprecated_templates[$name]));
- if ($found)
- break;
+ $filename = RCUBE_INSTALL_PATH . $skin_path . '/templates/' . $name . '.html';
+ if ((is_file($filename) && is_readable($filename))
+ || ($this->deprecated_templates[$name] && $this->template_exists($this->deprecated_templates[$name]))
+ ) {
+ return true;
+ }
}
- return $found;
- }
+ return false;
+ }
/**
* Find the given file in the current skin path stack
@@ -233,7 +236,6 @@ class rcmail_output_html extends rcmail_output
return false;
}
-
/**
* Register a GUI object to the client script
*
@@ -246,7 +248,6 @@ class rcmail_output_html extends rcmail_output
$this->add_script(self::JS_OBJECT_NAME.".gui_object('$obj', '$id');");
}
-
/**
* Call a client method
*
@@ -262,7 +263,6 @@ class rcmail_output_html extends rcmail_output
$this->js_commands[] = $cmd;
}
-
/**
* Add a localized label to the client environment
*/
@@ -277,7 +277,6 @@ class rcmail_output_html extends rcmail_output
}
}
-
/**
* Invoke display_message command
*
@@ -304,7 +303,6 @@ class rcmail_output_html extends rcmail_output
}
}
-
/**
* Delete all stored env variables and commands
*
@@ -327,7 +325,6 @@ class rcmail_output_html extends rcmail_output
$this->body = '';
}
-
/**
* Redirect to a certain url
*
@@ -343,7 +340,6 @@ class rcmail_output_html extends rcmail_output
exit;
}
-
/**
* Send the request output to the client.
* This will either parse a skin tempalte or send an AJAX response
@@ -377,7 +373,6 @@ class rcmail_output_html extends rcmail_output
}
}
-
/**
* Process template and write to stdOut
*
@@ -413,7 +408,6 @@ class rcmail_output_html extends rcmail_output
$this->_write($template, $this->config->get('skin_path'));
}
-
/**
* Parse a specific skin template and deliver to stdout (or return)
*
@@ -538,7 +532,6 @@ class rcmail_output_html extends rcmail_output
}
}
-
/**
* Return executable javascript code for all registered commands
*
@@ -570,7 +563,6 @@ class rcmail_output_html extends rcmail_output
return $out;
}
-
/**
* Make URLs starting with a slash point to skin directory
*
@@ -590,7 +582,6 @@ class rcmail_output_html extends rcmail_output
return $str;
}
-
/**
* Show error page and terminate script execution
*
@@ -625,7 +616,6 @@ class rcmail_output_html extends rcmail_output
array($this, 'globals_callback'), $input);
}
-
/**
* Callback funtion for preg_replace_callback() in parse_with_globals()
*/
@@ -634,7 +624,6 @@ class rcmail_output_html extends rcmail_output
return $GLOBALS[$matches[1]];
}
-
/**
* Correct absolute paths in images and other tags
* add timestamp to .js and .css filename
@@ -646,7 +635,6 @@ class rcmail_output_html extends rcmail_output
array($this, 'file_callback'), $output);
}
-
/**
* Callback function for preg_replace_callback in write()
*
@@ -655,7 +643,7 @@ class rcmail_output_html extends rcmail_output
protected function file_callback($matches)
{
$file = $matches[3];
- $file[0] = preg_replace('!^/this/!', '/', $file[0]);
+ $file = preg_replace('!^/this/!', '/', $file);
// correct absolute paths
if ($file[0] == '/') {
@@ -672,7 +660,6 @@ class rcmail_output_html extends rcmail_output
return $matches[1] . '=' . $matches[2] . $file . $matches[4];
}
-
/**
* Public wrapper to dipp into template parsing.
*
@@ -689,7 +676,6 @@ class rcmail_output_html extends rcmail_output
return $input;
}
-
/**
* Parse for conditional tags
*
@@ -727,7 +713,6 @@ class rcmail_output_html extends rcmail_output
return $input;
}
-
/**
* Determines if a given condition is met
*
@@ -740,7 +725,6 @@ class rcmail_output_html extends rcmail_output
return $this->eval_expression($condition);
}
-
/**
* Inserts hidden field with CSRF-prevention-token into POST forms
*/
@@ -757,7 +741,6 @@ class rcmail_output_html extends rcmail_output
return $out;
}
-
/**
* Parse & evaluate a given expression and return its result.
*
@@ -804,7 +787,6 @@ class rcmail_output_html extends rcmail_output
return $fn($this->app, $this->browser, $this->env);
}
-
/**
* Search for special tags in input and replace them
* with the appropriate content
@@ -819,7 +801,6 @@ class rcmail_output_html extends rcmail_output
return preg_replace_callback('/<roundcube:([-_a-z]+)\s+((?:[^>]|\\\\>)+)(?<!\\\\)>/Ui', array($this, 'xml_command'), $input);
}
-
/**
* Callback function for parsing an xml command tag
* and turn it into real html content
@@ -1023,12 +1004,13 @@ class rcmail_output_html extends rcmail_output
}
return html::quote($value);
- break;
+
+ case 'form':
+ return $this->form_tag($attrib);
}
return '';
}
-
/**
* Include a specific file and return it's contents
*
@@ -1045,7 +1027,6 @@ class rcmail_output_html extends rcmail_output
return $out;
}
-
/**
* Create and register a button
*
@@ -1201,7 +1182,6 @@ class rcmail_output_html extends rcmail_output
return $out;
}
-
/**
* Link an external script file
*
@@ -1232,7 +1212,6 @@ class rcmail_output_html extends rcmail_output
$this->script_files[$position][] = $file;
}
-
/**
* Add inline javascript code
*
@@ -1249,7 +1228,6 @@ class rcmail_output_html extends rcmail_output
}
}
-
/**
* Link an external css file
*
@@ -1260,7 +1238,6 @@ class rcmail_output_html extends rcmail_output
$this->css_files[] = $file;
}
-
/**
* Add HTML code to the page header
*
@@ -1271,7 +1248,6 @@ class rcmail_output_html extends rcmail_output
$this->header .= "\n" . $str;
}
-
/**
* Add HTML code to the page footer
* To be added right befor </body>
@@ -1283,7 +1259,6 @@ class rcmail_output_html extends rcmail_output
$this->footer .= "\n" . $str;
}
-
/**
* Process template and write to stdOut
*
@@ -1408,7 +1383,6 @@ class rcmail_output_html extends rcmail_output
}
}
-
/**
* Returns iframe object, registers some related env variables
*
@@ -1439,7 +1413,6 @@ class rcmail_output_html extends rcmail_output
/* ************* common functions delivering gui objects ************** */
-
/**
* Create a form tag with the necessary hidden fields
*
@@ -1461,12 +1434,11 @@ class rcmail_output_html extends rcmail_output
$attrib['noclose'] = true;
return html::tag('form',
- $attrib + array('action' => "./", 'method' => "get"),
+ $attrib + array('action' => $this->app->comm_path, 'method' => "get"),
$hidden . $content,
array('id','class','style','name','method','action','enctype','onsubmit'));
}
-
/**
* Build a form tag with a unique request token
*
@@ -1497,7 +1469,6 @@ class rcmail_output_html extends rcmail_output
return $this->form_tag($attrib, $hidden->show() . $content);
}
-
/**
* GUI object 'username'
* Showing IMAP username of the current session
@@ -1529,7 +1500,6 @@ class rcmail_output_html extends rcmail_output
return rcube_utils::idn_to_utf8($username);
}
-
/**
* GUI object 'loginform'
* Returns code for the webmail login form
@@ -1629,7 +1599,6 @@ class rcmail_output_html extends rcmail_output
return $out;
}
-
/**
* GUI object 'preloader'
* Loads javascript code for images preloading
@@ -1652,7 +1621,6 @@ class rcmail_output_html extends rcmail_output
}', 'docready');
}
-
/**
* GUI object 'searchform'
* Returns code for search function
@@ -1691,7 +1659,6 @@ class rcmail_output_html extends rcmail_output
return $out;
}
-
/**
* Builder for GUI object 'message'
*
@@ -1709,7 +1676,6 @@ class rcmail_output_html extends rcmail_output
return html::div($attrib, '');
}
-
/**
* GUI object 'charsetselector'
*
diff --git a/program/js/app.js b/program/js/app.js
index 101be65a3..45a17d640 100644
--- a/program/js/app.js
+++ b/program/js/app.js
@@ -44,7 +44,9 @@ function rcube_webmail()
comm_path: './',
blankpage: 'program/resources/blank.gif',
recipients_separator: ',',
- recipients_delimiter: ', '
+ recipients_delimiter: ', ',
+ popup_width: 1150,
+ popup_width_small: 900
};
// create protected reference to myself
@@ -189,7 +191,7 @@ function rcube_webmail()
case 'mail':
// enable mail commands
- this.enable_command('list', 'checkmail', 'add-contact', 'search', 'reset-search', 'collapse-folder', true);
+ this.enable_command('list', 'checkmail', 'add-contact', 'search', 'reset-search', 'collapse-folder', 'import-messages', true);
if (this.gui_objects.messagelist) {
this.message_list = new rcube_list_widget(this.gui_objects.messagelist, {
@@ -227,7 +229,7 @@ function rcube_webmail()
this.set_button_titles();
this.env.message_commands = ['show', 'reply', 'reply-all', 'reply-list',
- 'moveto', 'copy', 'delete', 'open', 'mark', 'edit', 'viewsource',
+ 'move', 'copy', 'delete', 'open', 'mark', 'edit', 'viewsource',
'print', 'load-attachment', 'download-attachment', 'show-headers', 'hide-headers', 'download',
'forward', 'forward-inline', 'forward-attachment', 'change-format'];
@@ -253,7 +255,8 @@ function rcube_webmail()
}
}
else if (this.env.action == 'compose') {
- this.env.compose_commands = ['send-attachment', 'remove-attachment', 'send', 'cancel', 'toggle-editor', 'list-adresses', 'search', 'reset-search', 'extwin'];
+ this.env.address_group_stack = [];
+ this.env.compose_commands = ['send-attachment', 'remove-attachment', 'send', 'cancel', 'toggle-editor', 'list-adresses', 'pushgroup', 'search', 'reset-search', 'extwin'];
if (this.env.drafts_mailbox)
this.env.compose_commands.push('savedraft')
@@ -274,12 +277,15 @@ function rcube_webmail()
// init message compose form
this.init_messageform();
}
+ else if (this.env.action == 'get')
+ this.enable_command('download', 'print', true);
// show printing dialog
- else if (this.env.action == 'print' && this.env.uid)
+ else if (this.env.action == 'print' && this.env.uid) {
if (bw.safari)
setTimeout('window.print()', 10);
else
window.print();
+ }
// get unread count for each mailbox
if (this.gui_objects.mailboxlist) {
@@ -320,11 +326,13 @@ function rcube_webmail()
break;
case 'addressbook':
+ this.env.address_group_stack = [];
+
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);
+ this.enable_command('list', 'listgroup', 'pushgroup', 'popgroup', 'listsearch', 'advanced-search', true);
if (this.gui_objects.contactslist) {
this.contact_list = new rcube_list_widget(this.gui_objects.contactslist,
@@ -368,7 +376,7 @@ function rcube_webmail()
}
if (this.gui_objects.qsearchbox)
- this.enable_command('search', 'reset-search', 'moveto', true);
+ this.enable_command('search', 'reset-search', true);
break;
@@ -596,15 +604,16 @@ function rcube_webmail()
case 'extwin':
if (this.env.action == 'compose') {
- var form = this.gui_objects.messageform;
+ var form = this.gui_objects.messageform,
+ win = this.open_window('');
$("input[name='_action']", form).val('compose');
form.action = this.url('mail/compose', { _id: this.env.compose_id, _extwin: 1 });
- form.target = this.open_window('', 1100, 900);
+ form.target = win.name;
form.submit();
}
else {
- this.open_window(this.env.permaurl, 900, 900);
+ this.open_window(this.env.permaurl, true);
}
break;
@@ -786,16 +795,18 @@ function rcube_webmail()
// mail task commands
case 'move':
- case 'moveto':
+ case 'moveto': // deprecated
if (this.task == 'mail')
this.move_messages(props);
else if (this.task == 'addressbook')
- this.copy_contact(null, props);
+ this.move_contacts(props);
break;
case 'copy':
if (this.task == 'mail')
this.copy_messages(props);
+ else if (this.task == 'addressbook')
+ this.copy_contacts(props);
break;
case 'mark':
@@ -857,11 +868,8 @@ function rcube_webmail()
// open attachment in frame if it's of a supported mimetype
if (command != 'download-attachment' && mimetype && this.env.mimetypes && $.inArray(mimetype, this.env.mimetypes) >= 0) {
- var attachment_win = window.open(this.env.comm_path+'&_action=get&'+qstring+'&_frame=1', this.html_identifier('rcubemailattachment'+this.env.uid+props));
- if (attachment_win) {
- setTimeout(function(){ attachment_win.focus(); }, 10);
+ if (this.open_window(this.env.comm_path+'&_action=get&'+qstring+'&_frame=1'))
break;
- }
}
this.goto_url('get', qstring+'&_download=1', false);
@@ -1000,7 +1008,7 @@ function rcube_webmail()
// Reset the auto-save timer
clearTimeout(this.save_timer);
- this.upload_file(props || this.gui_objects.uploadform);
+ this.upload_file(props || this.gui_objects.uploadform, 'upload');
break;
case 'insert-sig':
@@ -1044,10 +1052,12 @@ function rcube_webmail()
break;
case 'print':
- 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.env.action == 'get') {
+ this.gui_objects.messagepartframe.contentWindow.print();
+ }
+ else if (uid = this.get_single_uid()) {
+ ref.printwin = this.open_window(this.env.comm_path+'&_action=print&_uid='+uid+'&_mbox='+urlencode(this.env.mailbox)+(this.env.safemode ? '&_safe=1' : ''), true, true);
if (this.printwin) {
- setTimeout(function(){ ref.printwin.focus(); }, 20);
if (this.env.action != 'show')
this.mark_message('read', uid);
}
@@ -1055,15 +1065,15 @@ function rcube_webmail()
break;
case 'viewsource':
- 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)
- setTimeout(function(){ ref.sourcewin.focus(); }, 20);
- }
+ if (uid = this.get_single_uid())
+ this.open_window(this.env.comm_path+'&_action=viewsource&_uid='+uid+'&_mbox='+urlencode(this.env.mailbox), true, true);
break;
case 'download':
- if (uid = this.get_single_uid())
+ if (this.env.action == 'get') {
+ location.href = location.href.replace(/_frame=/, '_download=');
+ }
+ else if (uid = this.get_single_uid())
this.goto_url('viewsource', { _uid: uid, _mbox: this.env.mailbox, _save: 1 });
break;
@@ -1100,11 +1110,31 @@ function rcube_webmail()
}
break;
+ case 'pushgroup':
+ // add group ID to stack
+ this.env.address_group_stack.push(props.id);
+ if (obj && event)
+ rcube_event.cancel(event);
+
case 'listgroup':
this.reset_qsearch();
this.list_contacts(props.source, props.id);
break;
+ case 'popgroup':
+ if (this.env.address_group_stack.length > 1) {
+ this.env.address_group_stack.pop();
+ this.reset_qsearch();
+ this.list_contacts(props.source, this.env.address_group_stack[this.env.address_group_stack.length-1]);
+ }
+ break;
+
+ case 'import-messages':
+ var form = props || this.gui_objects.importform;
+ $('input[name="_unlock"]', form).val(this.set_busy(true, 'importwait'));
+ this.upload_file(form, 'import');
+ break;
+
case 'import':
if (this.env.action == 'import' && this.gui_objects.importform) {
var file = document.getElementById('rcmimportfile');
@@ -1322,7 +1352,7 @@ function rcube_webmail()
this.drag_menu = function(e, target)
{
var modkey = rcube_event.get_modifier(e),
- menu = this.gui_objects.message_dragmenu;
+ menu = this.gui_objects.dragmenu;
if (menu && modkey == SHIFT_KEY && this.commands['copy']) {
var pos = rcube_event.get_mouse_pos(e);
@@ -1336,7 +1366,7 @@ function rcube_webmail()
this.drag_menu_action = function(action)
{
- var menu = this.gui_objects.message_dragmenu;
+ var menu = this.gui_objects.dragmenu;
if (menu) {
$(menu).hide();
}
@@ -1451,8 +1481,12 @@ function rcube_webmail()
list.draglayer.hide();
this.drag_end(e);
- if (!this.drag_menu(e, target))
- this.command('moveto', target);
+ if (this.contact_list) {
+ if (!this.contacts_drag_menu(e, target))
+ this.command('move', target);
+ }
+ else if (!this.drag_menu(e, target))
+ this.command('move', target);
}
// reset 'pressed' buttons
@@ -1499,7 +1533,7 @@ function rcube_webmail()
}
}
// Multi-message commands
- this.enable_command('delete', 'moveto', 'copy', 'mark', 'forward', 'forward-attachment', list.selection.length > 0);
+ this.enable_command('delete', 'move', 'copy', 'mark', 'forward', 'forward-attachment', list.selection.length > 0);
// reset all-pages-selection
if (selected || (list.selection.length && list.selection.length != list.rowcount))
@@ -1602,46 +1636,55 @@ function rcube_webmail()
this.check_droptarget = function(id)
{
- if (this.task == 'mail')
- return (this.env.mailboxes[id] && this.env.mailboxes[id].id != this.env.mailbox && !this.env.mailboxes[id].virtual) ? 1 : 0;
+ switch (this.task) {
+ case 'mail':
+ return (this.env.mailboxes[id] && this.env.mailboxes[id].id != this.env.mailbox && !this.env.mailboxes[id].virtual) ? 1 : 0;
- if (this.task == 'settings')
- return id != this.env.mailbox ? 1 : 0;
+ case 'settings':
+ return id != this.env.mailbox ? 1 : 0;
- if (this.task == 'addressbook') {
- if (id != this.env.source && this.env.contactfolders[id]) {
- // droptarget is a group - contact add to group action
- if (this.env.contactfolders[id].type == 'group') {
- var target_abook = this.env.contactfolders[id].source;
- if (this.env.contactfolders[id].id != this.env.group && !this.env.contactfolders[target_abook].readonly) {
- // search result may contain contacts from many sources
- return (this.env.selection_sources.length > 1 || $.inArray(target_abook, this.env.selection_sources) == -1) ? 2 : 1;
+ case 'addressbook':
+ var target;
+ if (id != this.env.source && (target = this.env.contactfolders[id])) {
+ // droptarget is a group
+ if (target.type == 'group') {
+ if (target.id != this.env.group && !this.env.contactfolders[target.source].readonly) {
+ var is_other = this.env.selection_sources.length > 1 || $.inArray(target.source, this.env.selection_sources) == -1;
+ return !is_other || this.commands.move ? 1 : 2;
+ }
+ }
+ // droptarget is a (writable) addressbook and it's not the source
+ else if (!target.readonly && (this.env.selection_sources.length > 1 || $.inArray(id, this.env.selection_sources) == -1)) {
+ return this.commands.move ? 1 : 2;
}
}
- // droptarget is a (writable) addressbook - contact copy action
- else if (!this.env.contactfolders[id].readonly) {
- // search result may contain contacts from many sources
- return (this.env.selection_sources.length > 1 || $.inArray(id, this.env.selection_sources) == -1) ? 2 : 0;
- }
- }
}
return 0;
};
- this.open_window = function(url, width, height)
+ // open popup window
+ this.open_window = function(url, small, toolbar)
{
- var dh = (window.outerHeight || 0) - (window.innerHeight || 0),
- dw = (window.outerWidth || 0) - (window.innerWidth || 0),
- sh = screen.availHeight || screen.height,
- sw = screen.availWidth || screen.width,
- w = Math.min(width, sw),
- h = Math.min(height, sh),
- l = Math.max(0, (sw - w) / 2 + (screen.left || 0)),
- t = Math.max(0, (sh - h) / 2 + (screen.top || 0)),
- wname = 'rcmextwin' + new Date().getTime(),
- extwin = window.open(url + (url.match(/\?/) ? '&' : '?') + '_extwin=1', wname,
- 'width='+(w-dw)+',height='+(h-dh)+',top='+t+',left='+l+',resizable=yes,toolbar=no,status=no,location=no');
+ var wname = 'rcmextwin' + new Date().getTime();
+
+ url += (url.match(/\?/) ? '&' : '?') + '_extwin=1';
+
+ if (this.env.standard_windows)
+ extwin = window.open(url, wname);
+ else {
+ var win = this.is_framed() ? parent.window : window,
+ page = $(win),
+ page_width = page.width(),
+ page_height = bw.mz ? $('body', win).height() : page.height(),
+ w = Math.min(small ? this.env.popup_width_small : this.env.popup_width, page_width),
+ h = page_height, // always use same height
+ l = (win.screenLeft || win.screenX) + 20,
+ t = (win.screenTop || win.screenY) + 20,
+ extwin = window.open(url, wname,
+ 'width='+w+',height='+h+',top='+t+',left='+l+',resizable=yes,location=no,scrollbars=yes'
+ +(toolbar ? ',toolbar=yes,menubar=yes,status=yes' : ',toolbar=no,menubar=no,status=no'));
+ }
// write loading... message to empty windows
if (!url && extwin.document) {
@@ -1651,7 +1694,7 @@ function rcube_webmail()
// focus window, delayed to bring to front
window.setTimeout(function() { extwin.focus(); }, 10);
- return wname;
+ return extwin;
};
@@ -1945,7 +1988,7 @@ function rcube_webmail()
}
else {
if (!preview && this.env.message_extwin && !this.env.extwin)
- this.open_window(this.env.comm_path+url, 1000, 1200);
+ this.open_window(this.env.comm_path+url, true);
else
this.location_href(this.env.comm_path+url, target, true);
@@ -1971,14 +2014,18 @@ function rcube_webmail()
if (name && (frame = this.get_frame_element(name))) {
if (!show && (win = this.get_frame_window(name))) {
- if (win.location && win.location.href.indexOf(this.env.blankpage)<0)
- win.location.href = this.env.blankpage;
+ if (win.stop)
+ win.stop();
+ else // IE
+ win.document.execCommand('Stop');
+
+ win.location.href = this.env.blankpage;
}
else if (!bw.safari && !bw.konq)
$(frame)[show ? 'show' : 'hide']();
}
- if (!show && this.busy)
+ if (!show && this.env.frame_lock)
this.set_busy(false, null, this.env.frame_lock);
};
@@ -2106,12 +2153,12 @@ function rcube_webmail()
this.clear_message_list = function()
{
- this.env.messages = {};
- this.last_selected = 0;
+ this.env.messages = {};
+ this.last_selected = 0;
- this.show_contentframe(false);
- if (this.message_list)
- this.message_list.clear(true);
+ this.show_contentframe(false);
+ if (this.message_list)
+ this.message_list.clear(true);
};
// send remote request to load message list
@@ -2556,7 +2603,7 @@ function rcube_webmail()
// Hide message command buttons until a message is selected
this.enable_command(this.env.message_commands, false);
- this._with_selected_messages('moveto', post_data, lock);
+ this._with_selected_messages('move', post_data, lock);
};
// delete selected messages from the current mailbox
@@ -2615,7 +2662,7 @@ function rcube_webmail()
this._with_selected_messages('delete', post_data);
};
- // Send a specifc moveto/delete request with UIDs of all selected messages
+ // Send a specifc move/delete request with UIDs of all selected messages
// @private
this._with_selected_messages = function(action, post_data, lock)
{
@@ -2657,7 +2704,7 @@ function rcube_webmail()
this.delete_excessive_thread_rows();
if (!lock) {
- msg = action == 'moveto' ? 'movingmessage' : 'deletingmessage';
+ msg = action == 'move' ? 'movingmessage' : 'deletingmessage';
lock = this.display_message(this.get_label(msg), 'loading');
}
@@ -2971,11 +3018,12 @@ function rcube_webmail()
// open new compose window
if (this.env.compose_extwin && !this.env.extwin) {
- this.open_window(url, 1150, 900);
+ this.open_window(url);
}
else {
this.redirect(url);
- window.resizeTo(Math.max(1150, $(window).width()), Math.max(900, $(window).height()));
+ if (this.env.extwin)
+ window.resizeTo(Math.max(this.env.popup_width, $(window).width()), $(window).height() + 24);
}
};
@@ -3017,7 +3065,7 @@ function rcube_webmail()
this.set_caret_pos(input_message, this.env.top_posting ? 0 : $(input_message).val().length);
// add signature according to selected identity
// if we have HTML editor, signature is added in callback
- if (input_from.prop('type') == 'select-one' && !this.env.opened_extwin) {
+ if (input_from.prop('type') == 'select-one') {
this.change_identity(input_from[0]);
}
}
@@ -3078,7 +3126,13 @@ function rcube_webmail()
this.compose_recipient_select = function(list)
{
- this.enable_command('add-recipient', list.selection.length > 0);
+ var id, n, recipients = 0;
+ for (n=0; n < list.selection.length; n++) {
+ id = list.selection[n];
+ if (this.env.contactdata[id])
+ recipients++;
+ }
+ this.enable_command('add-recipient', recipients);
};
this.compose_add_recipient = function(field)
@@ -3348,12 +3402,54 @@ function rcube_webmail()
if (!show_sig)
show_sig = this.env.show_sig;
- var cursor_pos, p = -1,
+ // first function execution
+ if (!this.env.identities_initialized) {
+ this.env.identities_initialized = true;
+ if (this.env.show_sig_later)
+ this.env.show_sig = true;
+ if (this.env.opened_extwin)
+ return;
+ }
+
+ var i, rx, cursor_pos, p = -1,
id = obj.options[obj.selectedIndex].value,
input_message = $("[name='_message']"),
message = input_message.val(),
is_html = ($("input[name='_is_html']").val() == '1'),
- sig = this.env.identity;
+ sig = this.env.identity,
+ delim = this.env.recipients_delimiter,
+ headers = ['replyto', 'bcc'];
+
+ // update reply-to/bcc fields with addresses defined in identities
+ for (i in headers) {
+ var key = headers[i],
+ old_val = sig && this.env.identities[sig] ? this.env.identities[sig][key] : '',
+ new_val = id && this.env.identities[id] ? this.env.identities[id][key] : '',
+ input = $('[name="_'+key+'"]'), input_val = input.val();
+
+ // remove old address(es)
+ if (old_val && input_val) {
+ rx = new RegExp('\\s*' + RegExp.escape(old_val) + '\\s*');
+ input_val = input_val.replace(rx, '');
+ }
+
+ // cleanup
+ rx = new RegExp(RegExp.escape(delim) + '\\s*' + RegExp(delim), 'g');
+ input_val = input_val.replace(rx, delim)
+ rx = new RegExp('^\\s*' + RegExp.escape(delim) + '\\s*$');
+ input_val = input_val.replace(rx, '')
+
+ // add new address(es)
+ if (new_val) {
+ rx = new RegExp(RegExp.escape(delim) + '\\s*$');
+ if (input_val && !rx.test(input_val))
+ input_val += delim + ' ';
+ input_val += new_val + delim + ' ';
+ }
+
+ if (old_val || new_val)
+ input.val(input_val).change();
+ }
// enable manual signature insert
if (this.env.signatures && this.env.signatures[id]) {
@@ -3453,8 +3549,8 @@ function rcube_webmail()
return true;
};
- // upload attachment file
- this.upload_file = function(form)
+ // upload (attachment) file
+ this.upload_file = function(form, action)
{
if (!form)
return false;
@@ -3481,7 +3577,7 @@ function rcube_webmail()
return;
}
- var frame_name = this.async_upload_form(form, 'upload', function(e) {
+ var frame_name = this.async_upload_form(form, action || 'upload', function(e) {
var d, content = '';
try {
if (this.contentDocument) {
@@ -4063,7 +4159,7 @@ function rcube_webmail()
if (this.preview_timer)
clearTimeout(this.preview_timer);
- var n, id, sid, ref = this, writable = false,
+ var n, id, sid, contact, ref = this, writable = false,
source = this.env.source ? this.env.address_sources[this.env.source] : null;
// we don't have dblclick handler here, so use 200 instead of this.dblclick_time
@@ -4073,34 +4169,45 @@ function rcube_webmail()
this.show_contentframe(false);
if (list.selection.length) {
+ list.draggable = false;
+
// no source = search result, we'll need to detect if any of
// selected contacts are in writable addressbook to enable edit/delete
// we'll also need to know sources used in selection for copy
// and group-addmember operations (drag&drop)
this.env.selection_sources = [];
- if (!source) {
- for (n in list.selection) {
+
+ if (source) {
+ this.env.selection_sources.push(this.env.source);
+ }
+
+ for (n in list.selection) {
+ contact = list.data[list.selection[n]];
+ if (!source) {
sid = String(list.selection[n]).replace(/^[^-]+-/, '');
if (sid && this.env.address_sources[sid]) {
- writable = writable || !this.env.address_sources[sid].readonly;
+ writable = writable || (!this.env.address_sources[sid].readonly && !contact.readonly);
this.env.selection_sources.push(sid);
}
}
- this.env.selection_sources = $.unique(this.env.selection_sources);
- }
- else {
- this.env.selection_sources.push(this.env.source);
- writable = !source.readonly;
+ else {
+ writable = writable || (!source.readonly && !contact.readonly);
+ }
+
+ if (contact._type != 'group')
+ list.draggable = true;
}
+
+ this.env.selection_sources = $.unique(this.env.selection_sources);
}
// if a group is currently selected, and there is at least one contact selected
// thend we can enable the group-remove-selected command
- this.enable_command('group-remove-selected', this.env.group && list.selection.length > 0);
+ this.enable_command('group-remove-selected', this.env.group && list.selection.length > 0 && writable);
this.enable_command('compose', this.env.group || list.selection.length > 0);
- this.enable_command('export-selected', list.selection.length > 0);
+ this.enable_command('export-selected', 'copy', list.selection.length > 0);
this.enable_command('edit', id && writable);
- this.enable_command('delete', list.selection.length && writable);
+ this.enable_command('delete', 'move', list.selection.length > 0 && writable);
return false;
};
@@ -4128,11 +4235,29 @@ function rcube_webmail()
else if (!this.env.search_request)
folder = group ? 'G'+src+group : src;
- this.select_folder(folder, '', true);
-
this.env.source = src;
this.env.group = group;
+ // truncate groups listing stack
+ var index = $.inArray(this.env.group, this.env.address_group_stack);
+ if (index < 0)
+ this.env.address_group_stack = [];
+ else
+ this.env.address_group_stack = this.env.address_group_stack.slice(0,index);
+
+ // make sure the current group is on top of the stack
+ if (this.env.group) {
+ this.env.address_group_stack.push(this.env.group);
+
+ // mark the first group on the stack as selected in the directory list
+ folder = 'G'+src+this.env.address_group_stack[0];
+ }
+ else if (this.gui_objects.addresslist_title) {
+ $(this.gui_objects.addresslist_title).html(this.get_label('contacts'));
+ }
+
+ this.select_folder(folder, '', true);
+
// load contacts remotely
if (this.gui_objects.contactslist) {
this.list_contacts_remote(src, group, page);
@@ -4187,16 +4312,38 @@ function rcube_webmail()
this.list_contacts_clear = function()
{
+ this.contact_list.data = {};
this.contact_list.clear(true);
this.show_contentframe(false);
- this.enable_command('delete', false);
+ this.enable_command('delete', 'move', 'copy', false);
this.enable_command('compose', this.env.group ? true : false);
};
+ this.set_group_prop = function(prop)
+ {
+ if (this.gui_objects.addresslist_title) {
+ var boxtitle = $(this.gui_objects.addresslist_title).html(''); // clear contents
+
+ // add link to pop back to parent group
+ if (this.env.address_group_stack.length > 1) {
+ $('<a href="#list">...</a>')
+ .addClass('poplink')
+ .appendTo(boxtitle)
+ .click(function(e){ return ref.command('popgroup','',this); });
+ boxtitle.append('&nbsp;&raquo;&nbsp;');
+ }
+
+ boxtitle.append($('<span>'+prop.name+'</span>'));
+ }
+
+ this.triggerEvent('groupupdate', prop);
+ };
+
// load contact record
this.load_contact = function(cid, action, framed)
{
- var win, url = {}, target = window;
+ var win, url = {}, target = window,
+ rec = this.contact_list ? this.contact_list.data[cid] : null;
if (win = this.get_frame_window(this.env.contentframe)) {
url._framed = 1;
@@ -4206,7 +4353,9 @@ function rcube_webmail()
// load dummy content, unselect selected row(s)
if (!cid)
this.contact_list.clear_selection();
- this.enable_command('delete', 'compose', 'export-selected', cid);
+
+ this.enable_command('compose', rec && rec.email);
+ this.enable_command('export-selected', rec && rec._type != 'group');
}
else if (framed)
return false;
@@ -4236,14 +4385,38 @@ function rcube_webmail()
this.http_post('group-'+what+'members', post_data, lock);
};
- // copy a contact to the specified target (group or directory)
- this.copy_contact = function(cid, to)
+ this.contacts_drag_menu = function(e, to)
+ {
+ var dest = to.type == 'group' ? to.source : to.id,
+ source = this.env.source;
+
+ if (!this.env.address_sources[dest] || this.env.address_sources[dest].readonly)
+ return true;
+
+ // search result may contain contacts from many sources, but if there is only one...
+ if (source == '' && this.env.selection_sources.length == 1)
+ source = this.env.selection_sources[0];
+
+ if (to.type == 'group' && dest == source) {
+ var cid = this.contact_list.get_selection().join(',');
+ this.group_member_change('add', cid, dest, to.id);
+ return true;
+ }
+ // move action is not possible, "redirect" to copy if menu wasn't requested
+ else if (!this.commands.move && rcube_event.get_modifier(e) != SHIFT_KEY) {
+ this.copy_contacts(to);
+ return true;
+ }
+
+ return this.drag_menu(e, to);
+ };
+
+ // copy contact(s) to the specified target (group or directory)
+ this.copy_contacts = function(to)
{
var n, dest = to.type == 'group' ? to.source : to.id,
source = this.env.source,
- group = this.env.group ? this.env.group : '';
-
- if (!cid)
+ group = this.env.group ? this.env.group : '',
cid = this.contact_list.get_selection().join(',');
if (!cid || !this.env.address_sources[dest] || this.env.address_sources[dest].readonly)
@@ -4256,13 +4429,12 @@ function rcube_webmail()
// tagret is a group
if (to.type == 'group') {
if (dest == source)
- this.group_member_change('add', cid, dest, to.id);
- else {
- var lock = this.display_message(this.get_label('copyingcontact'), 'loading'),
- post_data = {_cid: cid, _source: this.env.source, _to: dest, _togid: to.id, _gid: group};
+ return;
- this.http_post('copy', post_data, lock);
- }
+ var lock = this.display_message(this.get_label('copyingcontact'), 'loading'),
+ post_data = {_cid: cid, _source: this.env.source, _to: dest, _togid: to.id, _gid: group};
+
+ this.http_post('copy', post_data, lock);
}
// target is an addressbook
else if (to.id != source) {
@@ -4273,19 +4445,53 @@ function rcube_webmail()
}
};
+ // move contact(s) to the specified target (group or directory)
+ this.move_contacts = function(to)
+ {
+ var dest = to.type == 'group' ? to.source : to.id,
+ source = this.env.source,
+ group = this.env.group ? this.env.group : '';
+
+ if (!this.env.address_sources[dest] || this.env.address_sources[dest].readonly)
+ return;
+
+ // search result may contain contacts from many sources, but if there is only one...
+ if (source == '' && this.env.selection_sources.length == 1)
+ source = this.env.selection_sources[0];
+
+ if (to.type == 'group') {
+ if (dest == source)
+ return;
+
+ this._with_selected_contacts('move', {_to: dest, _togid: to.id});
+ }
+ // target is an addressbook
+ else if (to.id != source)
+ this._with_selected_contacts('move', {_to: to.id});
+ };
+
+ // delete contact(s)
this.delete_contacts = function()
{
- var selection = this.contact_list.get_selection(),
- undelete = this.env.source && this.env.address_sources[this.env.source].undelete;
+ var undelete = this.env.source && this.env.address_sources[this.env.source].undelete;
- // exit if no mailbox specified or if selection is empty
- if (!(selection.length || this.env.cid) || (!undelete && !confirm(this.get_label('deletecontactconfirm'))))
+ if (!undelete && !confirm(this.get_label('deletecontactconfirm')))
return;
- var id, n, a_cids = [],
- post_data = {_source: this.env.source, _from: (this.env.action ? this.env.action : '')},
- lock = this.display_message(this.get_label('contactdeleting'), 'loading');
+ return this._with_selected_contacts('delete');
+ };
+ this._with_selected_contacts = function(action, post_data)
+ {
+ var selection = this.contact_list ? this.contact_list.get_selection() : [];
+
+ // exit if no mailbox specified or if selection is empty
+ if (!selection.length && !this.env.cid)
+ return;
+
+ var n, a_cids = [],
+ label = action == 'delete' ? 'contactdeleting' : 'movingcontact',
+ lock = this.display_message(this.get_label(label), 'loading');
if (this.env.cid)
a_cids.push(this.env.cid);
else {
@@ -4300,6 +4506,11 @@ function rcube_webmail()
this.show_contentframe(false);
}
+ if (!post_data)
+ post_data = {};
+
+ post_data._source = this.env.source;
+ post_data._from = this.env.action;
post_data._cid = a_cids.join(',');
if (this.env.group)
@@ -4310,13 +4521,13 @@ function rcube_webmail()
post_data._search = this.env.search_request;
// send request to server
- this.http_post('delete', post_data, lock)
+ this.http_post(action, post_data, lock)
return true;
};
// update a contact record in the list
- this.update_contact_row = function(cid, cols_arr, newcid, source)
+ this.update_contact_row = function(cid, cols_arr, newcid, source, data)
{
var c, row, list = this.contact_list;
@@ -4330,10 +4541,11 @@ function rcube_webmail()
}
list.update_row(cid, cols_arr, newcid, true);
+ list.data[cid] = data;
};
// add row to contacts list
- this.add_contact_row = function(cid, cols, classes)
+ this.add_contact_row = function(cid, cols, classes, data)
{
if (!this.gui_objects.contactslist)
return false;
@@ -4355,6 +4567,8 @@ function rcube_webmail()
row.cols.push(col);
}
+ // store data in list member
+ list.data[cid] = data;
list.insert_row(row);
this.enable_command('export', list.rowcount > 0);
@@ -5765,14 +5979,14 @@ function rcube_webmail()
for (c=0, len=repl.length; c < len; c++) {
cell = document.createElement('td');
- cell.innerHTML = repl[c].html;
+ cell.innerHTML = repl[c].html || '';
if (repl[c].id) cell.id = repl[c].id;
if (repl[c].className) cell.className = repl[c].className;
tr.appendChild(cell);
}
th.appendChild(tr);
thead.parentNode.replaceChild(th, thead);
- thead = th;
+ list.thead = thead = th;
}
for (n=0, len=this.env.coltypes.length; n<len; n++) {
@@ -6182,7 +6396,7 @@ function rcube_webmail()
this.enable_command('export-selected', false);
}
- case 'moveto':
+ case 'move':
if (this.env.action == 'show') {
// re-enable commands on move/delete error
this.enable_command(this.env.message_commands, true);
@@ -6223,6 +6437,7 @@ function rcube_webmail()
if ((response.action == 'list' || response.action == 'search') && this.message_list) {
this.msglist_select(this.message_list);
+ this.message_list.resize();
this.triggerEvent('listupdate', { folder:this.env.mailbox, rowcount:this.message_list.rowcount });
}
}
@@ -6233,6 +6448,7 @@ function rcube_webmail()
this.enable_command('search-create', this.env.source == '');
this.enable_command('search-delete', this.env.search_id);
this.update_group_commands();
+ this.contact_list.resize();
this.triggerEvent('listupdate', { folder:this.env.source, rowcount:this.contact_list.rowcount });
}
}
@@ -6394,9 +6610,10 @@ function rcube_webmail()
url: ref.url(ref.env.filedrop.action||'upload', { _id:ref.env.compose_id||ref.env.cid||'', _uploadid:ts, _remote:1 }),
contentType: formdata ? false : 'multipart/form-data; boundary=' + boundary,
processData: false,
+ timeout: 0, // disable default timeout set in ajaxSetup()
data: formdata || multipart,
headers: {'X-Roundcube-Request': ref.env.request_token},
- beforeSend: function(xhr, s) { if (!formdata && xhr.sendAsBinary) xhr.send = xhr.sendAsBinary; },
+ xhr: function() { var xhr = jQuery.ajaxSettings.xhr(); if (!formdata && xhr.sendAsBinary) xhr.send = xhr.sendAsBinary; return xhr; },
success: function(data){ ref.http_response(data); },
error: function(o, status, err) { ref.http_error(o, status, err, null, 'attachment'); }
});
@@ -6436,7 +6653,7 @@ function rcube_webmail()
multipart += '; filename="' + (f.name_bin || file.name) + '"' + crlf;
multipart += 'Content-Length: ' + file.size + crlf;
multipart += 'Content-Type: ' + file.type + crlf + crlf;
- multipart += e.target.result + crlf;
+ multipart += reader.result + crlf;
multipart += dashdash + boundary + crlf;
if (j == last) // we're done, submit the data
diff --git a/program/js/common.js b/program/js/common.js
index 53dce8cc2..de07ec131 100644
--- a/program/js/common.js
+++ b/program/js/common.js
@@ -251,7 +251,7 @@ remove_listener: function(p)
},
/**
- * Prevent event propagation and bubbeling
+ * Prevent event propagation and bubbling
*/
cancel: function(evt)
{
@@ -371,117 +371,6 @@ triggerEvent: function(evt, e)
}; // end rcube_event_engine.prototype
-
-/**
- * Roundcube generic layer (floating box) class
- *
- * @constructor
- */
-function rcube_layer(id, attributes)
-{
- this.name = id;
-
- // create a new layer in the current document
- this.create = function(arg)
- {
- var l = (arg.x) ? arg.x : 0,
- t = (arg.y) ? arg.y : 0,
- w = arg.width,
- h = arg.height,
- z = arg.zindex,
- vis = arg.vis,
- parent = arg.parent,
- obj = document.createElement('DIV');
-
- obj.id = this.name;
- obj.style.position = 'absolute';
- obj.style.visibility = (vis) ? (vis==2) ? 'inherit' : 'visible' : 'hidden';
- obj.style.left = l+'px';
- obj.style.top = t+'px';
- if (w)
- obj.style.width = w.toString().match(/\%$/) ? w : w+'px';
- if (h)
- obj.style.height = h.toString().match(/\%$/) ? h : h+'px';
- if (z)
- obj.style.zIndex = z;
-
- if (parent)
- parent.appendChild(obj);
- else
- document.body.appendChild(obj);
-
- this.elm = obj;
- };
-
- // create new layer
- if (attributes != null) {
- this.create(attributes);
- this.name = this.elm.id;
- }
- else // just refer to the object
- this.elm = document.getElementById(id);
-
- if (!this.elm)
- return false;
-
-
- // ********* layer object properties *********
-
- 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') ? true : false;
-
-
- // ********* layer object methods *********
-
- // move the layer to a specific position
- this.move = function(x, y)
- {
- this.x = x;
- this.y = y;
- this.css.left = Math.round(this.x)+'px';
- this.css.top = Math.round(this.y)+'px';
- };
-
- // change the layers width and height
- this.resize = function(w,h)
- {
- this.css.width = w+'px';
- this.css.height = h+'px';
- this.width = w;
- this.height = h;
- };
-
- // show or hide the layer
- this.show = function(a)
- {
- if(a == 1) {
- this.css.visibility = 'visible';
- this.visible = true;
- }
- else if(a == 2) {
- this.css.visibility = 'inherit';
- this.visible = true;
- }
- else {
- this.css.visibility = 'hidden';
- this.visible = false;
- }
- };
-
- // write new content into a Layer
- this.write = function(cont)
- {
- this.elm.innerHTML = cont;
- };
-
-};
-
-
// check if input is a valid email address
// By Cal Henderson <cal@iamcal.com>
// http://code.iamcal.com/php/rfc822/
@@ -536,7 +425,7 @@ function rcube_clone_object(obj)
for (var key in obj) {
if (obj[key] && typeof obj[key] === 'object')
- out[key] = clone_object(obj[key]);
+ out[key] = rcube_clone_object(obj[key]);
else
out[key] = obj[key];
}
diff --git a/program/js/editor.js b/program/js/editor.js
index 3782de869..e403d1f63 100644
--- a/program/js/editor.js
+++ b/program/js/editor.js
@@ -41,7 +41,7 @@ function rcmail_editor_init(config)
$.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',
- theme_advanced_buttons2: ',fontselect,fontsizeselect'
+ theme_advanced_buttons2: 'fontselect,fontsizeselect'
});
else { // mail compose
$.extend(conf, {
@@ -80,7 +80,7 @@ function rcmail_editor_callback()
if (rcmail.env.default_font)
$(tinyMCE.get(rcmail.env.composebody).getBody()).css('font-family', rcmail.env.default_font);
- if (elem && elem.type == 'select-one' && !rcmail.env.opened_extwin) {
+ if (elem && elem.type == 'select-one') {
rcmail.change_identity(elem);
// Focus previously focused element
if (fe && fe.id != rcmail.env.composebody) {
diff --git a/program/js/list.js b/program/js/list.js
index 8b8a7196e..08e4444e1 100644
--- a/program/js/list.js
+++ b/program/js/list.js
@@ -33,6 +33,7 @@ function rcube_list_widget(list, p)
this.tagname = this.list ? this.list.nodeName.toLowerCase() : 'table';
this.thead;
this.tbody;
+ this.fixed_header;
this.frame = null;
this.rows = [];
this.selection = [];
@@ -152,6 +153,14 @@ init_header: function()
if (this.thead) {
this.colcount = 0;
+ if (this.fixed_header) { // copy (modified) fixed header back to the actual table
+ $(this.list.tHead).replaceWith($(this.fixed_header).find('thead').clone());
+ $(this.list.tHead).find('tr td').attr('style', ''); // remove fixed widths
+ }
+ else if (this.list.className.indexOf('fixedheader') >= 0) {
+ this.init_fixed_header();
+ }
+
var col, r, p = this;
// add events for list columns moving
if (this.column_movable && this.thead && this.thead.rows) {
@@ -166,6 +175,47 @@ init_header: function()
}
},
+init_fixed_header: function()
+{
+ var clone = $(this.list.tHead).clone();
+
+ if (!this.fixed_header) {
+ this.fixed_header = $('<table>')
+ .attr('class', this.list.className + ' fixedcopy')
+ .css({ position:'fixed' })
+ .append(clone)
+ .append('<tbody></tbody>');
+ $(this.list).before(this.fixed_header);
+
+ var me = this;
+ $(window).resize(function(){ me.resize() });
+ }
+ else {
+ $(this.fixed_header).find('thead').replaceWith(clone);
+ }
+
+ this.thead = clone.get(0);
+ this.resize();
+},
+
+resize: function()
+{
+ if (!this.fixed_header)
+ return;
+
+ var column_widths = [];
+
+ // get column widths from original thead
+ $(this.tbody).parent().find('thead tr td').each(function(index) {
+ column_widths[index] = $(this).width();
+ });
+
+ // apply fixed widths to fixed table header
+ $(this.thead).parent().width($(this.tbody).parent().width());
+ $(this.thead).find('tr td').each(function(index) {
+ $(this).css('width', column_widths[index]);
+ });
+},
/**
* Remove all list rows
@@ -494,6 +544,7 @@ collapse: function(row)
new_row = new_row.nextSibling;
}
+ this.resize();
this.triggerEvent('listupdate');
return false;
},
@@ -542,6 +593,7 @@ expand: function(row)
new_row = new_row.nextSibling;
}
+ this.resize();
this.triggerEvent('listupdate');
return false;
},
@@ -585,6 +637,7 @@ collapse_all: function(row)
new_row = new_row.nextSibling;
}
+ this.resize();
this.triggerEvent('listupdate');
return false;
},
@@ -623,6 +676,7 @@ expand_all: function(row)
new_row = new_row.nextSibling;
}
+ this.resize();
this.triggerEvent('listupdate');
return false;
},
@@ -1531,6 +1585,9 @@ column_replace: function(from, to)
else if (this.subject_col > from && to >= this.subject_col)
this.subject_col--;
+ if (this.fixed_header)
+ this.init_header();
+
this.triggerEvent('column_replace');
}
diff --git a/program/lib/Mail/mime.php b/program/lib/Mail/mime.php
index 69a032cb8..e079af7e9 100644
--- a/program/lib/Mail/mime.php
+++ b/program/lib/Mail/mime.php
@@ -48,7 +48,7 @@
* @author Aleksander Machniak <alec@php.net>
* @copyright 2003-2006 PEAR <pear-group@php.net>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
- * @version Release: 1.8.7
+ * @version CVS: $Id$
* @link http://pear.php.net/package/Mail_mime
*
* This class is based on HTML Mime Mail class from
@@ -89,7 +89,7 @@ require_once 'Mail/mimePart.php';
* @author Sean Coates <sean@php.net>
* @copyright 2003-2006 PEAR <pear-group@php.net>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
- * @version Release: 1.8.7
+ * @version Release: @package_version@
* @link http://pear.php.net/package/Mail_mime
*/
class Mail_mime
@@ -254,6 +254,7 @@ class Mail_mime
$this->_txtbody .= $cont;
}
}
+
return true;
}
@@ -347,7 +348,7 @@ class Mail_mime
}
if (!$content_id) {
- $content_id = md5(uniqid(time()));
+ $content_id = preg_replace('/[^0-9a-zA-Z]/', '', uniqid(time(), true));
}
$this->_html_images[] = array(
@@ -429,8 +430,7 @@ class Mail_mime
if (!strlen($filename)) {
$msg = "The supplied filename for the attachment can't be empty";
- $err = PEAR::raiseError($msg);
- return $err;
+ return $this->_raiseError($msg);
}
$this->_parts[] = array(
@@ -465,16 +465,13 @@ class Mail_mime
{
// Check state of file and raise an error properly
if (!file_exists($file_name)) {
- $err = PEAR::raiseError('File not found: ' . $file_name);
- return $err;
+ return $this->_raiseError('File not found: ' . $file_name);
}
if (!is_file($file_name)) {
- $err = PEAR::raiseError('Not a regular file: ' . $file_name);
- return $err;
+ return $this->_raiseError('Not a regular file: ' . $file_name);
}
if (!is_readable($file_name)) {
- $err = PEAR::raiseError('File is not readable: ' . $file_name);
- return $err;
+ return $this->_raiseError('File is not readable: ' . $file_name);
}
// Temporarily reset magic_quotes_runtime and read file contents
@@ -500,7 +497,7 @@ class Mail_mime
* @return object The text mimePart object
* @access private
*/
- function _addTextPart(&$obj, $text)
+ function &_addTextPart(&$obj = null, $text = '')
{
$params['content_type'] = 'text/plain';
$params['encoding'] = $this->_build_params['text_encoding'];
@@ -509,11 +506,11 @@ class Mail_mime
if (is_object($obj)) {
$ret = $obj->addSubpart($text, $params);
- return $ret;
} else {
$ret = new Mail_mimePart($text, $params);
- return $ret;
}
+
+ return $ret;
}
/**
@@ -526,7 +523,7 @@ class Mail_mime
* @return object The html mimePart object
* @access private
*/
- function _addHtmlPart(&$obj)
+ function &_addHtmlPart(&$obj = null)
{
$params['content_type'] = 'text/html';
$params['encoding'] = $this->_build_params['html_encoding'];
@@ -535,11 +532,11 @@ class Mail_mime
if (is_object($obj)) {
$ret = $obj->addSubpart($this->_htmlbody, $params);
- return $ret;
} else {
$ret = new Mail_mimePart($this->_htmlbody, $params);
- return $ret;
}
+
+ return $ret;
}
/**
@@ -550,9 +547,8 @@ class Mail_mime
* @return object The multipart/mixed mimePart object
* @access private
*/
- function _addMixedPart()
+ function &_addMixedPart()
{
- $params = array();
$params['content_type'] = 'multipart/mixed';
$params['eol'] = $this->_build_params['eol'];
@@ -572,17 +568,18 @@ class Mail_mime
* @return object The multipart/mixed mimePart object
* @access private
*/
- function _addAlternativePart(&$obj)
+ function &_addAlternativePart(&$obj = null)
{
$params['content_type'] = 'multipart/alternative';
$params['eol'] = $this->_build_params['eol'];
if (is_object($obj)) {
- return $obj->addSubpart('', $params);
+ $ret = $obj->addSubpart('', $params);
} else {
$ret = new Mail_mimePart('', $params);
- return $ret;
}
+
+ return $ret;
}
/**
@@ -596,17 +593,18 @@ class Mail_mime
* @return object The multipart/mixed mimePart object
* @access private
*/
- function _addRelatedPart(&$obj)
+ function &_addRelatedPart(&$obj = null)
{
$params['content_type'] = 'multipart/related';
$params['eol'] = $this->_build_params['eol'];
if (is_object($obj)) {
- return $obj->addSubpart('', $params);
+ $ret = $obj->addSubpart('', $params);
} else {
$ret = new Mail_mimePart('', $params);
- return $ret;
}
+
+ return $ret;
}
/**
@@ -619,7 +617,7 @@ class Mail_mime
* @return object The image mimePart object
* @access private
*/
- function _addHtmlImagePart(&$obj, $value)
+ function &_addHtmlImagePart(&$obj, $value)
{
$params['content_type'] = $value['c_type'];
$params['encoding'] = 'base64';
@@ -650,7 +648,7 @@ class Mail_mime
* @return object The image mimePart object
* @access private
*/
- function _addAttachmentPart(&$obj, $value)
+ function &_addAttachmentPart(&$obj, $value)
{
$params['eol'] = $this->_build_params['eol'];
$params['filename'] = $value['name'];
@@ -700,9 +698,9 @@ class Mail_mime
*
* @param string $separation The separation between these two parts.
* @param array $params The Build parameters passed to the
- * &get() function. See &get for more info.
+ * get() function. See get() for more info.
* @param array $headers The extra headers that should be passed
- * to the &headers() function.
+ * to the headers() method.
* See that function for more info.
* @param bool $overwrite Overwrite the existing headers with new.
*
@@ -722,9 +720,7 @@ class Mail_mime
return $body;
}
- $head = $this->txtHeaders($headers, $overwrite);
- $mail = $head . $separation . $body;
- return $mail;
+ return $this->txtHeaders($headers, $overwrite) . $separation . $body;
}
/**
@@ -732,7 +728,7 @@ class Mail_mime
* mail delivery method.
*
* @param array $params The Build parameters passed to the
- * &get() function. See &get for more info.
+ * get() method. See get() for more info.
*
* @return mixed The e-mail body or PEAR error object
* @access public
@@ -748,9 +744,9 @@ class Mail_mime
*
* @param string $filename Output file location
* @param array $params The Build parameters passed to the
- * &get() function. See &get for more info.
+ * get() method. See get() for more info.
* @param array $headers The extra headers that should be passed
- * to the &headers() function.
+ * to the headers() function.
* See that function for more info.
* @param bool $overwrite Overwrite the existing headers with new.
*
@@ -762,8 +758,7 @@ class Mail_mime
{
// Check state of file and raise an error properly
if (file_exists($filename) && !is_writable($filename)) {
- $err = PEAR::raiseError('File is not writable: ' . $filename);
- return $err;
+ return $this->_raiseError('File is not writable: ' . $filename);
}
// Temporarily reset magic_quotes_runtime and read file contents
@@ -772,15 +767,13 @@ class Mail_mime
}
if (!($fh = fopen($filename, 'ab'))) {
- $err = PEAR::raiseError('Unable to open file: ' . $filename);
- return $err;
+ return $this->_raiseError('Unable to open file: ' . $filename);
}
// Write message headers into file (skipping Content-* headers)
$head = $this->txtHeaders($headers, $overwrite, true);
if (fwrite($fh, $head) === false) {
- $err = PEAR::raiseError('Error writing to file: ' . $filename);
- return $err;
+ return $this->_raiseError('Error writing to file: ' . $filename);
}
fclose($fh);
@@ -797,10 +790,10 @@ class Mail_mime
/**
* Writes (appends) the complete e-mail body into file.
- *
+ *
* @param string $filename Output file location
* @param array $params The Build parameters passed to the
- * &get() function. See &get for more info.
+ * get() method. See get() for more info.
*
* @return mixed True or PEAR error object
* @access public
@@ -810,8 +803,7 @@ class Mail_mime
{
// Check state of file and raise an error properly
if (file_exists($filename) && !is_writable($filename)) {
- $err = PEAR::raiseError('File is not writable: ' . $filename);
- return $err;
+ return $this->_raiseError('File is not writable: ' . $filename);
}
// Temporarily reset magic_quotes_runtime and read file contents
@@ -820,8 +812,7 @@ class Mail_mime
}
if (!($fh = fopen($filename, 'ab'))) {
- $err = PEAR::raiseError('Unable to open file: ' . $filename);
- return $err;
+ return $this->_raiseError('Unable to open file: ' . $filename);
}
// Write the rest of the message into file
@@ -844,7 +835,7 @@ class Mail_mime
* @return mixed The MIME message content string, null or PEAR error object
* @access public
*/
- function &get($params = null, $filename = null, $skip_head = false)
+ function get($params = null, $filename = null, $skip_head = false)
{
if (isset($params)) {
while (list($key, $value) = each($params)) {
@@ -1004,8 +995,7 @@ class Mail_mime
}
if (!isset($message)) {
- $ret = null;
- return $ret;
+ return null;
}
// Use saved boundary
@@ -1023,16 +1013,14 @@ class Mail_mime
return $headers;
}
$this->_headers = array_merge($this->_headers, $headers);
- $ret = null;
- return $ret;
+ return null;
} else {
$output = $message->encode($boundary, $skip_head);
if ($this->_isError($output)) {
return $output;
}
$this->_headers = array_merge($this->_headers, $output['headers']);
- $body = $output['body'];
- return $body;
+ return $output['body'];
}
}
@@ -1050,7 +1038,7 @@ class Mail_mime
* @return array Assoc array with the mime headers
* @access public
*/
- function &headers($xtra_headers = null, $overwrite = false, $skip_content = false)
+ function headers($xtra_headers = null, $overwrite = false, $skip_content = false)
{
// Add mime version header
$headers['MIME-Version'] = '1.0';
@@ -1473,7 +1461,7 @@ class Mail_mime
}
/**
- * PEAR::isError wrapper
+ * PEAR::isError implementation
*
* @param mixed $data Object
*
@@ -1490,4 +1478,18 @@ class Mail_mime
return false;
}
+ /**
+ * PEAR::raiseError implementation
+ *
+ * @param $message A text error message
+ *
+ * @return PEAR_Error Instance of PEAR_Error
+ * @access private
+ */
+ function _raiseError($message)
+ {
+ // PEAR::raiseError() is not PHP 5.4 compatible
+ return new PEAR_Error($message);
+ }
+
} // End of class
diff --git a/program/lib/Mail/mimePart.php b/program/lib/Mail/mimePart.php
index f3e75dd10..c6e9f4aa8 100644
--- a/program/lib/Mail/mimePart.php
+++ b/program/lib/Mail/mimePart.php
@@ -48,7 +48,7 @@
* @author Aleksander Machniak <alec@php.net>
* @copyright 2003-2006 PEAR <pear-group@php.net>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
- * @version Release: 1.8.7
+ * @version CVS: $Id$
* @link http://pear.php.net/package/Mail_mime
*/
@@ -70,7 +70,7 @@
* @author Aleksander Machniak <alec@php.net>
* @copyright 2003-2006 PEAR <pear-group@php.net>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
- * @version Release: 1.8.7
+ * @version Release: @package_version@
* @link http://pear.php.net/package/Mail_mime
*/
class Mail_mimePart
@@ -368,12 +368,12 @@ class Mail_mimePart
function encodeToFile($filename, $boundary=null, $skip_head=false)
{
if (file_exists($filename) && !is_writable($filename)) {
- $err = PEAR::raiseError('File is not writeable: ' . $filename);
+ $err = $this->_raiseError('File is not writeable: ' . $filename);
return $err;
}
if (!($fh = fopen($filename, 'ab'))) {
- $err = PEAR::raiseError('Unable to open file: ' . $filename);
+ $err = $this->_raiseError('Unable to open file: ' . $filename);
return $err;
}
@@ -456,7 +456,7 @@ class Mail_mimePart
* @param array $params The parameters for the subpart, same
* as the $params argument for constructor.
*
- * @return Mail_mimePart A reference to the part you just added. It is
+ * @return Mail_mimePart A reference to the part you just added. In PHP4, it is
* crucial if using multipart/* in your subparts that
* you use =& in your script when calling this function,
* otherwise you will not be able to add further subparts.
@@ -464,8 +464,8 @@ class Mail_mimePart
*/
function &addSubpart($body, $params)
{
- $this->_subparts[] = new Mail_mimePart($body, $params);
- return $this->_subparts[count($this->_subparts) - 1];
+ $this->_subparts[] = $part = new Mail_mimePart($body, $params);
+ return $part;
}
/**
@@ -511,12 +511,12 @@ class Mail_mimePart
function _getEncodedDataFromFile($filename, $encoding, $fh=null)
{
if (!is_readable($filename)) {
- $err = PEAR::raiseError('Unable to read file: ' . $filename);
+ $err = $this->_raiseError('Unable to read file: ' . $filename);
return $err;
}
if (!($fd = fopen($filename, 'rb'))) {
- $err = PEAR::raiseError('Could not open file: ' . $filename);
+ $err = $this->_raiseError('Could not open file: ' . $filename);
return $err;
}
@@ -648,7 +648,7 @@ class Mail_mimePart
}
/**
- * Encodes the paramater of a header.
+ * Encodes the parameter of a header.
*
* @param string $name The name of the header-parameter
* @param string $value The value of the paramter
@@ -1013,7 +1013,7 @@ class Mail_mimePart
$value = substr($value, $cutpoint);
$cutpoint = $maxLength;
// RFC 2047 specifies that any split header should
- // be seperated by a CRLF SPACE.
+ // be separated by a CRLF SPACE.
if ($output) {
$output .= $eol . ' ';
}
@@ -1055,7 +1055,7 @@ class Mail_mimePart
}
// RFC 2047 specifies that any split header should
- // be seperated by a CRLF SPACE
+ // be separated by a CRLF SPACE
if ($output) {
$output .= $eol . ' ';
}
@@ -1227,7 +1227,7 @@ class Mail_mimePart
}
/**
- * PEAR::isError wrapper
+ * PEAR::isError implementation
*
* @param mixed $data Object
*
@@ -1244,4 +1244,18 @@ class Mail_mimePart
return false;
}
+ /**
+ * PEAR::raiseError implementation
+ *
+ * @param $message A text error message
+ *
+ * @return PEAR_Error Instance of PEAR_Error
+ * @access private
+ */
+ function _raiseError($message)
+ {
+ // PEAR::raiseError() is not PHP 5.4 compatible
+ return new PEAR_Error($message);
+ }
+
} // End of class
diff --git a/program/lib/Roundcube/bootstrap.php b/program/lib/Roundcube/bootstrap.php
index b7e69cb2a..182ea1232 100644
--- a/program/lib/Roundcube/bootstrap.php
+++ b/program/lib/Roundcube/bootstrap.php
@@ -39,13 +39,13 @@ $config = array(
if (php_sapi_name() != 'cli') {
$config += array(
'suhosin.session.encrypt' => 0,
- 'session.auto_start' => 0,
'file_uploads' => 1,
);
}
foreach ($config as $optname => $optval) {
- if ($optval != ini_get($optname) && @ini_set($optname, $optval) === false) {
+ $ini_optval = filter_var(ini_get($optname), FILTER_VALIDATE_BOOLEAN);
+ if ($optval != $ini_optval && @ini_set($optname, $optval) === false) {
$error = "ERROR: Wrong '$optname' option value and it wasn't possible to set it to required value ($optval).\n"
. "Check your PHP configuration (including php_admin_flag).";
if (defined('STDERR')) fwrite(STDERR, $error); else echo $error;
@@ -293,32 +293,6 @@ function is_ascii($str, $control_chars = true)
/**
- * Remove single and double quotes from a given string
- *
- * @param string Input value
- *
- * @return string Dequoted string
- */
-function strip_quotes($str)
-{
- return str_replace(array("'", '"'), '', $str);
-}
-
-
-/**
- * Remove new lines characters from given string
- *
- * @param string $str Input value
- *
- * @return string Stripped string
- */
-function strip_newlines($str)
-{
- return preg_replace('/[\r\n]/', '', $str);
-}
-
-
-/**
* Compose a valid representation of name and e-mail address
*
* @param string $email E-mail address
diff --git a/program/lib/Roundcube/html.php b/program/lib/Roundcube/html.php
index eb23c8b2e..3e6e47a56 100644
--- a/program/lib/Roundcube/html.php
+++ b/program/lib/Roundcube/html.php
@@ -360,8 +360,8 @@ class html_inputfield extends html
protected $allowed = array(
'type','name','value','size','tabindex','autocapitalize',
'autocomplete','checked','onchange','onclick','disabled','readonly',
- 'spellcheck','results','maxlength','src','multiple','placeholder',
- 'autofocus',
+ 'spellcheck','results','maxlength','src','multiple','accept',
+ 'placeholder','autofocus',
);
/**
diff --git a/program/lib/Roundcube/rcube.php b/program/lib/Roundcube/rcube.php
index eea2fde84..ce97cd0a5 100644
--- a/program/lib/Roundcube/rcube.php
+++ b/program/lib/Roundcube/rcube.php
@@ -99,20 +99,20 @@ class rcube
protected $texts;
protected $caches = array();
protected $shutdown_functions = array();
- protected $expunge_cache = false;
/**
* This implements the 'singleton' design pattern
*
* @param integer Options to initialize with this instance. See rcube::INIT_WITH_* constants
+ * @param string Environment name to run (e.g. live, dev, test)
*
* @return rcube The one and only instance
*/
- static function get_instance($mode = 0)
+ static function get_instance($mode = 0, $env = '')
{
if (!self::$instance) {
- self::$instance = new rcube();
+ self::$instance = new rcube($env);
self::$instance->init($mode);
}
@@ -123,10 +123,10 @@ class rcube
/**
* Private constructor
*/
- protected function __construct()
+ protected function __construct($env = '')
{
// load configuration
- $this->config = new rcube_config;
+ $this->config = new rcube_config($env);
$this->plugins = new rcube_dummy_plugin_api;
register_shutdown_function(array($this, 'shutdown'));
@@ -258,6 +258,39 @@ class rcube
/**
+ * Initialize and get shared cache object
+ *
+ * @param string $name Cache identifier
+ * @param bool $packed Enables/disables data serialization
+ *
+ * @return rcube_cache_shared Cache object
+ */
+ public function get_cache_shared($name, $packed=true)
+ {
+ $shared_name = "shared_$name";
+
+ if (!array_key_exists($shared_name, $this->caches)) {
+ $opt = strtolower($name) . '_cache';
+ $type = $this->config->get($opt);
+ $ttl = $this->config->get($opt . '_ttl');
+
+ if (!$type) {
+ // cache is disabled
+ return $this->caches[$shared_name] = null;
+ }
+
+ if ($ttl === null) {
+ $ttl = $this->config->get('shared_cache_ttl', '10d');
+ }
+
+ $this->caches[$shared_name] = new rcube_cache_shared($type, $name, $ttl, $packed);
+ }
+
+ return $this->caches[$shared_name];
+ }
+
+
+ /**
* Create SMTP object and connect to server
*
* @param boolean True if connection should be established
@@ -345,6 +378,7 @@ class rcube
'auth_pw' => $this->config->get("{$driver}_auth_pw"),
'debug' => (bool) $this->config->get("{$driver}_debug"),
'force_caps' => (bool) $this->config->get("{$driver}_force_caps"),
+ 'disabled_caps' => $this->config->get("{$driver}_disabled_caps"),
'timeout' => (int) $this->config->get("{$driver}_timeout"),
'skip_deleted' => (bool) $this->config->get('skip_deleted'),
'driver' => $driver,
@@ -424,30 +458,40 @@ class rcube
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.cookie_httponly', 1);
// use database for storing session data
$this->session = new rcube_session($this->get_dbh(), $this->config);
- $this->session->register_gc_handler(array($this, 'temp_gc'));
- $this->session->register_gc_handler(array($this, 'cache_gc'));
-
+ $this->session->register_gc_handler(array($this, 'gc'));
$this->session->set_secret($this->config->get('des_key') . dirname($_SERVER['SCRIPT_NAME']));
$this->session->set_ip_check($this->config->get('ip_check'));
// start PHP session (if not in CLI mode)
if ($_SERVER['REMOTE_ADDR']) {
- session_start();
+ $this->session->start();
}
}
/**
+ * Garbage collector - cache/temp cleaner
+ */
+ public function gc()
+ {
+ rcube_cache::gc();
+ rcube_cache_shared::gc();
+ $this->get_storage()->cache_gc();
+
+ $this->gc_temp();
+ }
+
+
+ /**
* Garbage collector function for temp files.
* Remove temp files older than two days
*/
- public function temp_gc()
+ public function gc_temp()
{
$tmp = unslashify($this->config->get('temp_dir'));
$expire = time() - 172800; // expire in 48 hours
@@ -469,14 +513,21 @@ class rcube
/**
- * Garbage collector for cache entries.
- * Set flag to expunge caches on shutdown
+ * Runs garbage collector with probability based on
+ * session settings. This is intended for environments
+ * without a session.
*/
- public function cache_gc()
+ public function gc_run()
{
- // because this gc function is called before storage is initialized,
- // we just set a flag to expunge storage cache on shutdown.
- $this->expunge_cache = true;
+ $probability = (int) ini_get('session.gc_probability');
+ $divisor = (int) ini_get('session.gc_divisor');
+
+ if ($divisor > 0 && $probability > 0) {
+ $random = mt_rand(1, $divisor);
+ if ($random <= $probability) {
+ $this->gc();
+ }
+ }
}
@@ -860,6 +911,14 @@ class rcube
call_user_func($function);
}
+ // write session data as soon as possible and before
+ // closing database connection, don't do this before
+ // registered shutdown functions, they may need the session
+ // Note: this will run registered gc handlers (ie. cache gc)
+ if ($_SERVER['REMOTE_ADDR'] && is_object($this->session)) {
+ $this->session->write_close();
+ }
+
if (is_object($this->smtp)) {
$this->smtp->disconnect();
}
@@ -871,9 +930,6 @@ class rcube
}
if (is_object($this->storage)) {
- if ($this->expunge_cache) {
- $this->storage->expunge_cache();
- }
$this->storage->close();
}
}
@@ -1433,7 +1489,7 @@ class rcube
$subject = str_replace("\r\n", $delim, $subject);
}
- if (ini_get('safe_mode'))
+ if (filter_var(ini_get('safe_mode'), FILTER_VALIDATE_BOOLEAN))
$sent = mail($to, $subject, $msg_body, $header_str);
else
$sent = mail($to, $subject, $msg_body, $header_str, "-f$from");
diff --git a/program/lib/Roundcube/rcube_addressbook.php b/program/lib/Roundcube/rcube_addressbook.php
index d23ad3687..4ed139c45 100644
--- a/program/lib/Roundcube/rcube_addressbook.php
+++ b/program/lib/Roundcube/rcube_addressbook.php
@@ -539,10 +539,10 @@ abstract class rcube_addressbook
// add email to a key to not skip contacts with the same name (#1488375)
if (!empty($contact['email'])) {
- $key .= ':' . implode(':', (array)$contact['email']);
- }
+ $key .= ':' . implode(':', (array)$contact['email']);
+ }
- return $key;
+ return $key;
}
/**
diff --git a/program/lib/Roundcube/rcube_cache.php b/program/lib/Roundcube/rcube_cache.php
index 92f12a8bf..a708cb292 100644
--- a/program/lib/Roundcube/rcube_cache.php
+++ b/program/lib/Roundcube/rcube_cache.php
@@ -38,6 +38,7 @@ class rcube_cache
private $type;
private $userid;
private $prefix;
+ private $table;
private $ttl;
private $packed;
private $index;
@@ -71,8 +72,9 @@ class rcube_cache
$this->db = function_exists('apc_exists'); // APC 3.1.4 required
}
else {
- $this->type = 'db';
- $this->db = $rcube->get_dbh();
+ $this->type = 'db';
+ $this->db = $rcube->get_dbh();
+ $this->table = $this->db->table_name('cache');
}
// convert ttl string to seconds
@@ -145,7 +147,7 @@ class rcube_cache
*/
function write($key, $data)
{
- return $this->write_record($key, $this->packed ? serialize($data) : $data);
+ return $this->write_record($key, $this->serialize($data));
}
@@ -192,20 +194,31 @@ class rcube_cache
*/
function expunge()
{
- if ($this->type == 'db' && $this->db) {
+ if ($this->type == 'db' && $this->db && $this->ttl) {
$this->db->query(
- "DELETE FROM ".$this->db->table_name('cache').
+ "DELETE FROM ".$this->table.
" WHERE user_id = ?".
" AND cache_key LIKE ?".
- " AND " . $this->db->unixtimestamp('created')." < ?",
+ " AND expires < " . $this->db->now(),
$this->userid,
- $this->prefix.'.%',
- time() - $this->ttl);
+ $this->prefix.'.%');
}
}
/**
+ * Remove expired records of all caches
+ */
+ static function gc()
+ {
+ $rcube = rcube::get_instance();
+ $db = $rcube->get_dbh();
+
+ $db->query("DELETE FROM " . $db->table_name('cache') . " WHERE expires < " . $db->now());
+ }
+
+
+ /**
* Writes the cache back to the DB.
*/
function close()
@@ -219,7 +232,7 @@ class rcube_cache
if ($this->cache_changes[$key]) {
// Make sure we're not going to write unchanged data
// by comparing current md5 sum with the sum calculated on DB read
- $data = $this->packed ? serialize($data) : $data;
+ $data = $this->serialize($data);
if (!$this->cache_sums[$key] || $this->cache_sums[$key] != md5($data)) {
$this->write_record($key, $data);
@@ -255,7 +268,7 @@ class rcube_cache
if ($data) {
$md5sum = md5($data);
- $data = $this->packed ? unserialize($data) : $data;
+ $data = $this->unserialize($data);
if ($nostore) {
return $data;
@@ -271,7 +284,7 @@ class rcube_cache
else {
$sql_result = $this->db->limitquery(
"SELECT data, cache_key".
- " FROM ".$this->db->table_name('cache').
+ " FROM " . $this->table.
" WHERE user_id = ?".
" AND cache_key = ?".
// for better performance we allow more records for one key
@@ -283,7 +296,7 @@ class rcube_cache
$key = substr($sql_arr['cache_key'], strlen($this->prefix)+1);
$md5sum = $sql_arr['data'] ? md5($sql_arr['data']) : null;
if ($sql_arr['data']) {
- $data = $this->packed ? unserialize($sql_arr['data']) : $sql_arr['data'];
+ $data = $this->unserialize($sql_arr['data']);
}
if ($nostore) {
@@ -326,7 +339,7 @@ class rcube_cache
// Remove NULL rows (here we don't need to check if the record exist)
if ($data == 'N;') {
$this->db->query(
- "DELETE FROM ".$this->db->table_name('cache').
+ "DELETE FROM " . $this->table.
" WHERE user_id = ?".
" AND cache_key = ?",
$this->userid, $key);
@@ -337,8 +350,10 @@ class rcube_cache
// update existing cache record
if ($key_exists) {
$result = $this->db->query(
- "UPDATE ".$this->db->table_name('cache').
- " SET created = ". $this->db->now().", data = ?".
+ "UPDATE " . $this->table.
+ " SET created = " . $this->db->now().
+ ", expires = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL').
+ ", data = ?".
" WHERE user_id = ?".
" AND cache_key = ?",
$data, $this->userid, $key);
@@ -348,9 +363,9 @@ class rcube_cache
// for better performance we allow more records for one key
// so, no need to check if record exist (see rcube_cache::read_record())
$result = $this->db->query(
- "INSERT INTO ".$this->db->table_name('cache').
- " (created, user_id, cache_key, data)".
- " VALUES (".$this->db->now().", ?, ?, ?)",
+ "INSERT INTO " . $this->table.
+ " (created, expires, user_id, cache_key, data)".
+ " VALUES (" . $this->db->now() . ", " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL') . ", ?, ?, ?)",
$this->userid, $key, $data);
}
@@ -364,7 +379,6 @@ class rcube_cache
* @param string $key Cache key name or pattern
* @param boolean $prefix_mode Enable it to clear all keys starting
* with prefix specified in $key
- *
*/
private function remove_record($key=null, $prefix_mode=false)
{
@@ -412,7 +426,7 @@ class rcube_cache
}
$this->db->query(
- "DELETE FROM ".$this->db->table_name('cache').
+ "DELETE FROM " . $this->table.
" WHERE user_id = ?" . $where,
$this->userid);
}
@@ -553,4 +567,28 @@ class rcube_cache
// This way each cache will have its own index
return sprintf('%d:%s%s', $this->userid, $this->prefix, 'INDEX');
}
+
+ /**
+ * Serializes data for storing
+ */
+ private function serialize($data)
+ {
+ if ($this->type == 'db') {
+ return $this->db->encode($data, $this->packed);
+ }
+
+ return $this->packed ? serialize($data) : $data;
+ }
+
+ /**
+ * Unserializes serialized data
+ */
+ private function unserialize($data)
+ {
+ if ($this->type == 'db') {
+ return $this->db->decode($data, $this->packed);
+ }
+
+ return $this->packed ? @unserialize($data) : $data;
+ }
}
diff --git a/program/lib/Roundcube/rcube_cache_shared.php b/program/lib/Roundcube/rcube_cache_shared.php
new file mode 100644
index 000000000..8f2574046
--- /dev/null
+++ b/program/lib/Roundcube/rcube_cache_shared.php
@@ -0,0 +1,581 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | This file is part of the Roundcube Webmail client |
+ | Copyright (C) 2011-2013, The Roundcube Dev Team |
+ | Copyright (C) 2011-2013, Kolab Systems AG |
+ | |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
+ | |
+ | PURPOSE: |
+ | Shared (cross-user) caching engine |
+ +-----------------------------------------------------------------------+
+ | Author: Thomas Bruederli <roundcube@gmail.com> |
+ | Author: Aleksander Machniak <alec@alec.pl> |
+ +-----------------------------------------------------------------------+
+*/
+
+
+/**
+ * Interface class for accessing Roundcube shared cache
+ *
+ * @package Framework
+ * @subpackage Cache
+ * @author Thomas Bruederli <roundcube@gmail.com>
+ * @author Aleksander Machniak <alec@alec.pl>
+ */
+class rcube_cache_shared
+{
+ /**
+ * Instance of database handler
+ *
+ * @var rcube_db|Memcache|bool
+ */
+ private $db;
+ private $type;
+ private $prefix;
+ private $ttl;
+ private $packed;
+ private $index;
+ private $table;
+ private $cache = array();
+ private $cache_changes = array();
+ private $cache_sums = array();
+
+
+ /**
+ * Object constructor.
+ *
+ * @param string $type Engine type ('db' or 'memcache' or 'apc')
+ * @param string $prefix Key name prefix
+ * @param string $ttl Expiration time of memcache/apc items
+ * @param bool $packed Enables/disabled data serialization.
+ * It's possible to disable data serialization if you're sure
+ * stored data will be always a safe string
+ */
+ function __construct($type, $prefix='', $ttl=0, $packed=true)
+ {
+ $rcube = rcube::get_instance();
+ $type = strtolower($type);
+
+ if ($type == 'memcache') {
+ $this->type = 'memcache';
+ $this->db = $rcube->get_memcache();
+ }
+ else if ($type == 'apc') {
+ $this->type = 'apc';
+ $this->db = function_exists('apc_exists'); // APC 3.1.4 required
+ }
+ else {
+ $this->type = 'db';
+ $this->db = $rcube->get_dbh();
+ $this->table = $this->db->table_name('cache_shared');
+ }
+
+ // convert ttl string to seconds
+ $ttl = get_offset_sec($ttl);
+ if ($ttl > 2592000) $ttl = 2592000;
+
+ $this->ttl = $ttl;
+ $this->packed = $packed;
+ $this->prefix = $prefix;
+ }
+
+
+ /**
+ * Returns cached value.
+ *
+ * @param string $key Cache key name
+ *
+ * @return mixed Cached value
+ */
+ function get($key)
+ {
+ if (!array_key_exists($key, $this->cache)) {
+ return $this->read_record($key);
+ }
+
+ return $this->cache[$key];
+ }
+
+
+ /**
+ * Sets (add/update) value in cache.
+ *
+ * @param string $key Cache key name
+ * @param mixed $data Cache data
+ */
+ function set($key, $data)
+ {
+ $this->cache[$key] = $data;
+ $this->cache_changed = true;
+ $this->cache_changes[$key] = true;
+ }
+
+
+ /**
+ * Returns cached value without storing it in internal memory.
+ *
+ * @param string $key Cache key name
+ *
+ * @return mixed Cached value
+ */
+ function read($key)
+ {
+ if (array_key_exists($key, $this->cache)) {
+ return $this->cache[$key];
+ }
+
+ return $this->read_record($key, true);
+ }
+
+
+ /**
+ * Sets (add/update) value in cache and immediately saves
+ * it in the backend, no internal memory will be used.
+ *
+ * @param string $key Cache key name
+ * @param mixed $data Cache data
+ *
+ * @param boolean True on success, False on failure
+ */
+ function write($key, $data)
+ {
+ return $this->write_record($key, $this->serialize($data));
+ }
+
+
+ /**
+ * Clears the cache.
+ *
+ * @param string $key Cache key name or pattern
+ * @param boolean $prefix_mode Enable it to clear all keys starting
+ * with prefix specified in $key
+ */
+ function remove($key=null, $prefix_mode=false)
+ {
+ // Remove all keys
+ if ($key === null) {
+ $this->cache = array();
+ $this->cache_changed = false;
+ $this->cache_changes = array();
+ $this->cache_sums = array();
+ }
+ // Remove keys by name prefix
+ else if ($prefix_mode) {
+ foreach (array_keys($this->cache) as $k) {
+ if (strpos($k, $key) === 0) {
+ $this->cache[$k] = null;
+ $this->cache_changes[$k] = false;
+ unset($this->cache_sums[$k]);
+ }
+ }
+ }
+ // Remove one key by name
+ else {
+ $this->cache[$key] = null;
+ $this->cache_changes[$key] = false;
+ unset($this->cache_sums[$key]);
+ }
+
+ // Remove record(s) from the backend
+ $this->remove_record($key, $prefix_mode);
+ }
+
+
+ /**
+ * Remove cache records older than ttl
+ */
+ function expunge()
+ {
+ if ($this->type == 'db' && $this->db && $this->ttl) {
+ $this->db->query(
+ "DELETE FROM " . $this->table
+ . " WHERE cache_key LIKE ?"
+ . " AND expires < " . $this->db->now(),
+ $this->prefix . '.%');
+ }
+ }
+
+
+ /**
+ * Remove expired records of all caches
+ */
+ static function gc()
+ {
+ $rcube = rcube::get_instance();
+ $db = $rcube->get_dbh();
+
+ $db->query("DELETE FROM " . $db->table_name('cache_shared') . " WHERE expires < " . $db->now());
+ }
+
+
+ /**
+ * Writes the cache back to the DB.
+ */
+ function close()
+ {
+ if (!$this->cache_changed) {
+ return;
+ }
+
+ foreach ($this->cache as $key => $data) {
+ // The key has been used
+ if ($this->cache_changes[$key]) {
+ // Make sure we're not going to write unchanged data
+ // by comparing current md5 sum with the sum calculated on DB read
+ $data = $this->serialize($data);
+
+ if (!$this->cache_sums[$key] || $this->cache_sums[$key] != md5($data)) {
+ $this->write_record($key, $data);
+ }
+ }
+ }
+
+ $this->write_index();
+ }
+
+
+ /**
+ * Reads cache entry.
+ *
+ * @param string $key Cache key name
+ * @param boolean $nostore Enable to skip in-memory store
+ *
+ * @return mixed Cached value
+ */
+ private function read_record($key, $nostore=false)
+ {
+ if (!$this->db) {
+ return null;
+ }
+
+ 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->unserialize($data);
+
+ if ($nostore) {
+ return $data;
+ }
+
+ $this->cache_sums[$key] = $md5sum;
+ $this->cache[$key] = $data;
+ }
+ else {
+ $this->cache[$key] = null;
+ }
+ }
+ else {
+ $sql_result = $this->db->limitquery(
+ "SELECT data, cache_key".
+ " FROM " . $this->table .
+ " WHERE cache_key = ?".
+ // for better performance we allow more records for one key
+ // get the newer one
+ " ORDER BY created DESC",
+ 0, 1, $this->prefix . '.' . $key);
+
+ if ($sql_arr = $this->db->fetch_assoc($sql_result)) {
+ $md5sum = $sql_arr['data'] ? md5($sql_arr['data']) : null;
+ if ($sql_arr['data']) {
+ $data = $this->unserialize($sql_arr['data']);
+ }
+
+ if ($nostore) {
+ return $data;
+ }
+
+ $this->cache[$key] = $data;
+ $this->cache_sums[$key] = $md5sum;
+ }
+ else {
+ $this->cache[$key] = null;
+ }
+ }
+
+ return $this->cache[$key];
+ }
+
+
+ /**
+ * Writes single cache record into DB.
+ *
+ * @param string $key Cache key name
+ * @param mxied $data Serialized cache data
+ *
+ * @param boolean True on success, False on failure
+ */
+ private function write_record($key, $data)
+ {
+ if (!$this->db) {
+ return false;
+ }
+
+ if ($this->type == 'memcache' || $this->type == 'apc') {
+ return $this->add_record($this->ckey($key), $data);
+ }
+
+ $key_exists = array_key_exists($key, $this->cache_sums);
+ $key = $this->prefix . '.' . $key;
+
+ // Remove NULL rows (here we don't need to check if the record exist)
+ if ($data == 'N;') {
+ $this->db->query("DELETE FROM " . $this->table . " WHERE cache_key = ?", $key);
+ return true;
+ }
+
+ // update existing cache record
+ if ($key_exists) {
+ $result = $this->db->query(
+ "UPDATE " . $this->table .
+ " SET created = " . $this->db->now() .
+ ", expires = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL') .
+ ", data = ?".
+ " WHERE cache_key = ?",
+ $data, $key);
+ }
+ // add new cache record
+ else {
+ // for better performance we allow more records for one key
+ // so, no need to check if record exist (see rcube_cache::read_record())
+ $result = $this->db->query(
+ "INSERT INTO ".$this->table.
+ " (created, expires, cache_key, data)".
+ " VALUES (".$this->db->now().", " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL') . ", ?, ?)",
+ $key, $data);
+ }
+
+ return $this->db->affected_rows($result);
+ }
+
+
+ /**
+ * Deletes the cache record(s).
+ *
+ * @param string $key Cache key name or pattern
+ * @param boolean $prefix_mode Enable it to clear all keys starting
+ * with prefix specified in $key
+ */
+ private function remove_record($key=null, $prefix_mode=false)
+ {
+ if (!$this->db) {
+ return;
+ }
+
+ if ($this->type != 'db') {
+ $this->load_index();
+
+ // Remove all keys
+ if ($key === null) {
+ foreach ($this->index as $key) {
+ $this->delete_record($key, false);
+ }
+ $this->index = array();
+ }
+ // Remove keys by name prefix
+ else if ($prefix_mode) {
+ foreach ($this->index as $k) {
+ if (strpos($k, $key) === 0) {
+ $this->delete_record($k);
+ }
+ }
+ }
+ // Remove one key by name
+ else {
+ $this->delete_record($key);
+ }
+
+ return;
+ }
+
+ // Remove all keys (in specified cache)
+ if ($key === null) {
+ $where = " WHERE cache_key LIKE " . $this->db->quote($this->prefix.'.%');
+ }
+ // Remove keys by name prefix
+ else if ($prefix_mode) {
+ $where = " WHERE cache_key LIKE " . $this->db->quote($this->prefix.'.'.$key.'%');
+ }
+ // Remove one key by name
+ else {
+ $where = " WHERE cache_key = " . $this->db->quote($this->prefix.'.'.$key);
+ }
+
+ $this->db->query("DELETE FROM " . $this->table . $where);
+ }
+
+
+ /**
+ * Adds entry into memcache/apc DB.
+ *
+ * @param string $key Cache key name
+ * @param mxied $data Serialized cache data
+ * @param bollean $index Enables immediate index update
+ *
+ * @param boolean True on success, False on failure
+ */
+ private function add_record($key, $data, $index=false)
+ {
+ if ($this->type == 'memcache') {
+ $result = $this->db->replace($key, $data, MEMCACHE_COMPRESSED, $this->ttl);
+ if (!$result) {
+ $result = $this->db->set($key, $data, MEMCACHE_COMPRESSED, $this->ttl);
+ }
+ }
+ else if ($this->type == 'apc') {
+ if (apc_exists($key)) {
+ apc_delete($key);
+ }
+ $result = apc_store($key, $data, $this->ttl);
+ }
+
+ // Update index
+ if ($index && $result) {
+ $this->load_index();
+
+ if (array_search($key, $this->index) === false) {
+ $this->index[] = $key;
+ $data = serialize($this->index);
+ $this->add_record($this->ikey(), $data);
+ }
+ }
+
+ return $result;
+ }
+
+
+ /**
+ * Deletes entry from memcache/apc DB.
+ */
+ private function delete_record($key, $index=true)
+ {
+ if ($this->type == 'memcache') {
+ // #1488592: use 2nd argument
+ $this->db->delete($this->ckey($key), 0);
+ }
+ else {
+ apc_delete($this->ckey($key));
+ }
+
+ if ($index) {
+ if (($idx = array_search($key, $this->index)) !== false) {
+ unset($this->index[$idx]);
+ }
+ }
+ }
+
+
+ /**
+ * Writes the index entry into memcache/apc DB.
+ */
+ private function write_index()
+ {
+ if (!$this->db) {
+ return;
+ }
+
+ if ($this->type == 'db') {
+ return;
+ }
+
+ $this->load_index();
+
+ // Make sure index contains new keys
+ foreach ($this->cache as $key => $value) {
+ if ($value !== null) {
+ if (array_search($key, $this->index) === false) {
+ $this->index[] = $key;
+ }
+ }
+ }
+
+ $data = serialize($this->index);
+ $this->add_record($this->ikey(), $data);
+ }
+
+
+ /**
+ * Gets the index entry from memcache/apc DB.
+ */
+ private function load_index()
+ {
+ if (!$this->db) {
+ return;
+ }
+
+ if ($this->index !== null) {
+ return;
+ }
+
+ $index_key = $this->ikey();
+
+ if ($this->type == 'memcache') {
+ $data = $this->db->get($index_key);
+ }
+ else if ($this->type == 'apc') {
+ $data = apc_fetch($index_key);
+ }
+
+ $this->index = $data ? unserialize($data) : array();
+ }
+
+
+ /**
+ * Creates cache key name (for memcache and apc)
+ *
+ * @param string $key Cache key name
+ *
+ * @return string Cache key
+ */
+ private function ckey($key)
+ {
+ return $this->prefix . ':' . $key;
+ }
+
+
+ /**
+ * Creates index cache key name (for memcache and apc)
+ *
+ * @return string Cache key
+ */
+ private function ikey()
+ {
+ // This way each cache will have its own index
+ return $this->prefix . 'INDEX';
+ }
+
+ /**
+ * Serializes data for storing
+ */
+ private function serialize($data)
+ {
+ if ($this->type == 'db') {
+ return $this->db->encode($data, $this->packed);
+ }
+
+ return $this->packed ? serialize($data) : $data;
+ }
+
+ /**
+ * Unserializes serialized data
+ */
+ private function unserialize($data)
+ {
+ if ($this->type == 'db') {
+ return $this->db->decode($data, $this->packed);
+ }
+
+ return $this->packed ? @unserialize($data) : $data;
+ }
+}
diff --git a/program/lib/Roundcube/rcube_config.php b/program/lib/Roundcube/rcube_config.php
index 2190dc4c2..62567a0e0 100644
--- a/program/lib/Roundcube/rcube_config.php
+++ b/program/lib/Roundcube/rcube_config.php
@@ -26,6 +26,8 @@ class rcube_config
{
const DEFAULT_SKIN = 'larry';
+ private $env = '';
+ private $basedir = 'config/';
private $prop = array();
private $errors = array();
private $userprefs = array();
@@ -43,14 +45,21 @@ class rcube_config
'reply_mode' => 'top_posting',
'refresh_interval' => 'keep_alive',
'min_refresh_interval' => 'min_keep_alive',
+ 'messages_cache_ttl' => 'message_cache_lifetime',
+ 'redundant_attachments_cache_ttl' => 'redundant_attachments_memcache_ttl',
);
/**
* Object constructor
+ *
+ * @param string Environment suffix for config files to load
*/
- public function __construct()
+ public function __construct($env = '')
{
+ $this->env = $env;
+ $this->basedir = RCUBE_CONFIG_DIR;
+
$this->load();
// Defaults, that we do not require you to configure,
@@ -67,16 +76,26 @@ class rcube_config
*/
private function load()
{
- // load main config file
- if (!$this->load_from_file(RCUBE_CONFIG_DIR . 'main.inc.php'))
- $this->errors[] = 'main.inc.php was not found.';
+ // Load default settings
+ if (!$this->load_from_file('defaults.inc.php')) {
+ $this->errors[] = 'defaults.inc.php was not found.';
+ }
- // load database config
- if (!$this->load_from_file(RCUBE_CONFIG_DIR . 'db.inc.php'))
- $this->errors[] = 'db.inc.php was not found.';
+ // load main config file
+ if (!$this->load_from_file('config.inc.php')) {
+ // Old configuration files
+ if (!$this->load_from_file('main.inc.php') ||
+ !$this->load_from_file('db.inc.php')) {
+ $this->errors[] = 'config.inc.php was not found.';
+ }
+ else if (rand(1,100) == 10) { // log warning on every 100th request (average)
+ trigger_error("config.inc.php was not found. Please migrate your config by running bin/update.sh", E_USER_WARNING);
+ }
+ }
// load host-specific configuration
- $this->load_host_config();
+ if (!empty($_SERVER['HTTP_HOST']))
+ $this->load_host_config();
// set skin (with fallback to old 'skin_path' property)
if (empty($this->prop['skin'])) {
@@ -153,7 +172,7 @@ class rcube_config
}
if ($fname) {
- $this->load_from_file(RCUBE_CONFIG_DIR . $fname);
+ $this->load_from_file($fname);
}
}
@@ -162,19 +181,25 @@ class rcube_config
* Read configuration from a file
* and merge with the already stored config values
*
- * @param string $fpath Full path to the config file to be loaded
+ * @param string $file Name of the config file to be loaded
* @return booelan True on success, false on failure
*/
- public function load_from_file($fpath)
+ public function load_from_file($file)
{
- if (is_file($fpath) && is_readable($fpath)) {
+ $fpath = $this->resolve_path($file);
+ if ($fpath && is_file($fpath) && is_readable($fpath)) {
// use output buffering, we don't need any output here
ob_start();
include($fpath);
ob_end_clean();
- if (is_array($rcmail_config)) {
- $this->prop = array_merge($this->prop, $rcmail_config, $this->userprefs);
+ if (is_array($config)) {
+ $this->merge($config);
+ return true;
+ }
+ // deprecated name of config variable
+ else if (is_array($rcmail_config)) {
+ $this->merge($rcmail_config);
return true;
}
}
@@ -182,6 +207,26 @@ class rcube_config
return false;
}
+ /**
+ * Helper method to resolve the absolute path to the given config file.
+ * This also takes the 'env' property into account.
+ */
+ public function resolve_path($file, $use_env = true)
+ {
+ if (strpos($file, '/') === false) {
+ $file = realpath($this->basedir . '/' . $file);
+ }
+
+ // check if <file>-env.ini exists
+ if ($file && $use_env && !empty($this->env)) {
+ $envfile = preg_replace('/\.(inc.php)$/', '-' . $this->env . '.\\1', $file);
+ if (is_file($envfile))
+ return $envfile;
+ }
+
+ return $file;
+ }
+
/**
* Getter for a specific config parameter
@@ -195,9 +240,6 @@ class rcube_config
if (isset($this->prop[$name])) {
$result = $this->prop[$name];
}
- else if (isset($this->legacy_props[$name])) {
- return $this->get($this->legacy_props[$name], $def);
- }
else {
$result = $def;
}
@@ -241,6 +283,7 @@ class rcube_config
public function merge($prefs)
{
$this->prop = array_merge($this->prop, $prefs, $this->userprefs);
+ $this->fix_legacy_props();
}
@@ -273,6 +316,8 @@ class rcube_config
$this->userprefs = $prefs;
$this->prop = array_merge($this->prop, $prefs);
+ $this->fix_legacy_props();
+
// override timezone settings with client values
if ($this->prop['timezone'] == 'auto') {
$this->prop['_timezone_value'] = isset($_SESSION['timezone']) ? $this->client_timezone() : $this->prop['_timezone_value'];
@@ -435,4 +480,18 @@ class rcube_config
return date_default_timezone_get();
}
+ /**
+ * Convert legacy options into new ones
+ */
+ private function fix_legacy_props()
+ {
+ foreach ($this->legacy_props as $new => $old) {
+ if (isset($this->prop[$old])) {
+ if (!isset($this->prop[$new])) {
+ $this->prop[$new] = $this->prop[$old];
+ }
+ unset($this->prop[$old]);
+ }
+ }
+ }
}
diff --git a/program/lib/Roundcube/rcube_db.php b/program/lib/Roundcube/rcube_db.php
index 5da38c899..852070073 100644
--- a/program/lib/Roundcube/rcube_db.php
+++ b/program/lib/Roundcube/rcube_db.php
@@ -100,27 +100,15 @@ class rcube_db
$this->db_dsnw_array = self::parse_dsn($db_dsnw);
$this->db_dsnr_array = self::parse_dsn($db_dsnr);
-
- // Initialize driver class
- $this->init();
- }
-
- /**
- * Initialization of the object with driver specific code
- */
- protected function init()
- {
- // To be used by driver classes
}
/**
* Connect to specific database
*
- * @param array $dsn DSN for DB connections
- *
- * @return PDO database handle
+ * @param array $dsn DSN for DB connections
+ * @param string $mode Connection mode (r|w)
*/
- protected function dsn_connect($dsn)
+ protected function dsn_connect($dsn, $mode)
{
$this->db_error = false;
$this->db_error_msg = null;
@@ -158,9 +146,10 @@ class rcube_db
return null;
}
+ $this->dbh = $dbh;
+ $this->db_mode = $mode;
+ $this->db_connected = true;
$this->conn_configure($dsn, $dbh);
-
- return $dbh;
}
/**
@@ -183,16 +172,6 @@ class rcube_db
}
/**
- * Driver-specific database character set setting
- *
- * @param string $charset Character set name
- */
- protected function set_charset($charset)
- {
- $this->query("SET NAMES 'utf8'");
- }
-
- /**
* Connect to appropriate database depending on the operation
*
* @param string $mode Connection mode (r|w)
@@ -219,23 +198,14 @@ class rcube_db
$dsn = ($mode == 'r') ? $this->db_dsnr_array : $this->db_dsnw_array;
- $this->dbh = $this->dsn_connect($dsn);
- $this->db_connected = is_object($this->dbh);
+ $this->dsn_connect($dsn, $mode);
// use write-master when read-only fails
if (!$this->db_connected && $mode == 'r' && $this->is_replicated()) {
- $mode = 'w';
- $this->dbh = $this->dsn_connect($this->db_dsnw_array);
- $this->db_connected = is_object($this->dbh);
+ $this->dsn_connect($this->db_dsnw_array, 'w');
}
- if ($this->db_connected) {
- $this->db_mode = $mode;
- $this->set_charset('utf8');
- }
- else {
- $this->conn_failure = true;
- }
+ $this->conn_failure = !$this->db_connected;
}
/**
@@ -368,8 +338,10 @@ class rcube_db
*/
protected function _query($query, $offset, $numrows, $params)
{
+ $query = trim($query);
+
// Read or write ?
- $mode = preg_match('/^(select|show)/i', ltrim($query)) ? 'r' : 'w';
+ $mode = preg_match('/^(select|show|set)/i', $query) ? 'r' : 'w';
$this->db_connect($mode);
@@ -415,13 +387,16 @@ class rcube_db
if ($result === false) {
$error = $this->dbh->errorInfo();
- $this->db_error = true;
- $this->db_error_msg = sprintf('[%s] %s', $error[1], $error[2]);
- rcube::raise_error(array('code' => 500, 'type' => 'db',
- 'line' => __LINE__, 'file' => __FILE__,
- 'message' => $this->db_error_msg . " (SQL Query: $query)"
- ), true, false);
+ if (empty($this->options['ignore_key_errors']) || $error[0] != '23000') {
+ $this->db_error = true;
+ $this->db_error_msg = sprintf('[%s] %s', $error[1], $error[2]);
+
+ rcube::raise_error(array('code' => 500, 'type' => 'db',
+ 'line' => __LINE__, 'file' => __FILE__,
+ 'message' => $this->db_error_msg . " (SQL Query: $query)"
+ ), true, false);
+ }
}
$this->last_result = $result;
@@ -708,11 +683,19 @@ class rcube_db
/**
* Return SQL function for current time and date
*
+ * @param int $interval Optional interval (in seconds) to add/subtract
+ *
* @return string SQL function to use in query
*/
- public function now()
+ public function now($interval = 0)
{
- return "now()";
+ if ($interval) {
+ $add = ' ' . ($interval > 0 ? '+' : '-') . ' INTERVAL ';
+ $add .= $interval > 0 ? intval($interval) : intval($interval) * -1;
+ $add .= ' SECOND';
+ }
+
+ return "now()" . $add;
}
/**
@@ -795,12 +778,19 @@ class rcube_db
/**
* Encodes non-UTF-8 characters in string/array/object (recursive)
*
- * @param mixed $input Data to fix
+ * @param mixed $input Data to fix
+ * @param bool $serialized Enable serialization
*
* @return mixed Properly UTF-8 encoded data
*/
- public static function encode($input)
+ public static function encode($input, $serialized = false)
{
+ // use Base64 encoding to workaround issues with invalid
+ // or null characters in serialized string (#1489142)
+ if ($serialized) {
+ return base64_encode(serialize($input));
+ }
+
if (is_object($input)) {
foreach (get_object_vars($input) as $idx => $value) {
$input->$idx = self::encode($value);
@@ -811,6 +801,7 @@ class rcube_db
foreach ($input as $idx => $value) {
$input[$idx] = self::encode($value);
}
+
return $input;
}
@@ -820,12 +811,24 @@ class rcube_db
/**
* Decodes encoded UTF-8 string/object/array (recursive)
*
- * @param mixed $input Input data
+ * @param mixed $input Input data
+ * @param bool $serialized Enable serialization
*
* @return mixed Decoded data
*/
- public static function decode($input)
+ public static function decode($input, $serialized = false)
{
+ // use Base64 encoding to workaround issues with invalid
+ // or null characters in serialized string (#1489142)
+ if ($serialized) {
+ // Keep backward compatybility where base64 wasn't used
+ if (strpos(substr($input, 0, 16), ':') !== false) {
+ return self::decode(@unserialize($input));
+ }
+
+ return @unserialize(base64_decode($input));
+ }
+
if (is_object($input)) {
foreach (get_object_vars($input) as $idx => $value) {
$input->$idx = self::decode($value);
@@ -862,6 +865,17 @@ class rcube_db
}
/**
+ * Set class option value
+ *
+ * @param string $name Option name
+ * @param mixed $value Option value
+ */
+ public function set_option($name, $value)
+ {
+ $this->options[$name] = $value;
+ }
+
+ /**
* MDB2 DSN string parser
*
* @param string $sequence Secuence name
diff --git a/program/lib/Roundcube/rcube_db_mssql.php b/program/lib/Roundcube/rcube_db_mssql.php
index 37a42678a..3c1b9d71f 100644
--- a/program/lib/Roundcube/rcube_db_mssql.php
+++ b/program/lib/Roundcube/rcube_db_mssql.php
@@ -29,38 +29,52 @@ class rcube_db_mssql extends rcube_db
public $db_provider = 'mssql';
/**
- * Driver initialization
+ * Object constructor
+ *
+ * @param string $db_dsnw DSN for read/write operations
+ * @param string $db_dsnr Optional DSN for read only operations
+ * @param bool $pconn Enables persistent connections
*/
- protected function init()
+ public function __construct($db_dsnw, $db_dsnr = '', $pconn = false)
{
+ parent::__construct($db_dsnw, $db_dsnr, $pconn);
+
$this->options['identifier_start'] = '[';
$this->options['identifier_end'] = ']';
}
/**
- * Character setting
+ * Driver-specific configuration of database connection
+ *
+ * @param array $dsn DSN for DB connections
+ * @param PDO $dbh Connection handler
*/
- protected function set_charset($charset)
+ protected function conn_configure($dsn, $dbh)
{
- // UTF-8 is default
+ // Set date format in case of non-default language (#1488918)
+ $this->query("SET DATEFORMAT ymd");
}
/**
* Return SQL function for current time and date
*
+ * @param int $interval Optional interval (in seconds) to add/subtract
+ *
* @return string SQL function to use in query
*/
- public function now()
+ public function now($interval = 0)
{
+ if ($interval) {
+ $interval = intval($interval);
+ return "dateadd(second, $interval, getdate())";
+ }
+
return "getdate()";
}
/**
* Return SQL statement to convert a field value into a unix timestamp
*
- * This method is deprecated and should not be used anymore due to limitations
- * of timestamp functions in Mysql (year 2038 problem)
- *
* @param string $field Field name
*
* @return string SQL statement to use in query
diff --git a/program/lib/Roundcube/rcube_db_mysql.php b/program/lib/Roundcube/rcube_db_mysql.php
index 2d42610b6..6fa5ad768 100644
--- a/program/lib/Roundcube/rcube_db_mysql.php
+++ b/program/lib/Roundcube/rcube_db_mysql.php
@@ -30,9 +30,13 @@ class rcube_db_mysql extends rcube_db
public $db_provider = 'mysql';
/**
- * Driver initialization/configuration
+ * Object constructor
+ *
+ * @param string $db_dsnw DSN for read/write operations
+ * @param string $db_dsnr Optional DSN for read only operations
+ * @param bool $pconn Enables persistent connections
*/
- protected function init()
+ public function __construct($db_dsnw, $db_dsnr = '', $pconn = false)
{
if (version_compare(PHP_VERSION, '5.3.0', '<')) {
rcube::raise_error(array('code' => 600, 'type' => 'db',
@@ -41,12 +45,25 @@ class rcube_db_mysql extends rcube_db
true, true);
}
+ parent::__construct($db_dsnw, $db_dsnr, $pconn);
+
// SQL identifiers quoting
$this->options['identifier_start'] = '`';
$this->options['identifier_end'] = '`';
}
/**
+ * Driver-specific configuration of database connection
+ *
+ * @param array $dsn DSN for DB connections
+ * @param PDO $dbh Connection handler
+ */
+ protected function conn_configure($dsn, $dbh)
+ {
+ $this->query("SET NAMES 'utf8'");
+ }
+
+ /**
* Abstract SQL statement for value concatenation
*
* @return string SQL statement to be used in query
diff --git a/program/lib/Roundcube/rcube_db_pgsql.php b/program/lib/Roundcube/rcube_db_pgsql.php
index adfd2207b..d72c9d6b3 100644
--- a/program/lib/Roundcube/rcube_db_pgsql.php
+++ b/program/lib/Roundcube/rcube_db_pgsql.php
@@ -29,6 +29,17 @@ class rcube_db_pgsql extends rcube_db
public $db_provider = 'postgres';
/**
+ * Driver-specific configuration of database connection
+ *
+ * @param array $dsn DSN for DB connections
+ * @param PDO $dbh Connection handler
+ */
+ protected function conn_configure($dsn, $dbh)
+ {
+ $this->query("SET NAMES 'utf8'");
+ }
+
+ /**
* Get last inserted record ID
*
* @param string $table Table name (to find the incremented sequence)
@@ -75,9 +86,6 @@ class rcube_db_pgsql extends rcube_db
/**
* Return SQL statement to convert a field value into a unix timestamp
*
- * This method is deprecated and should not be used anymore due to limitations
- * of timestamp functions in Mysql (year 2038 problem)
- *
* @param string $field Field name
*
* @return string SQL statement to use in query
@@ -89,6 +97,24 @@ class rcube_db_pgsql extends rcube_db
}
/**
+ * Return SQL function for current time and date
+ *
+ * @param int $interval Optional interval (in seconds) to add/subtract
+ *
+ * @return string SQL function to use in query
+ */
+ public function now($interval = 0)
+ {
+ if ($interval) {
+ $add = ' ' . ($interval > 0 ? '+' : '-') . " interval '";
+ $add .= $interval > 0 ? intval($interval) : intval($interval) * -1;
+ $add .= " seconds'";
+ }
+
+ return "now()" . $add;
+ }
+
+ /**
* Return SQL statement for case insensitive LIKE
*
* @param string $column Field name
@@ -130,4 +156,38 @@ class rcube_db_pgsql extends rcube_db
return isset($this->variables[$varname]) ? $this->variables[$varname] : $default;
}
+ /**
+ * Returns PDO DSN string from DSN array
+ *
+ * @param array $dsn DSN parameters
+ *
+ * @return string DSN string
+ */
+ protected function dsn_string($dsn)
+ {
+ $params = array();
+ $result = 'pgsql:';
+
+ if ($dsn['hostspec']) {
+ $params[] = 'host=' . $dsn['hostspec'];
+ }
+ else if ($dsn['socket']) {
+ $params[] = 'host=' . $dsn['socket'];
+ }
+
+ if ($dsn['port']) {
+ $params[] = 'port=' . $dsn['port'];
+ }
+
+ if ($dsn['database']) {
+ $params[] = 'dbname=' . $dsn['database'];
+ }
+
+ if (!empty($params)) {
+ $result .= implode(';', $params);
+ }
+
+ return $result;
+ }
+
}
diff --git a/program/lib/Roundcube/rcube_db_sqlite.php b/program/lib/Roundcube/rcube_db_sqlite.php
index 145b8a371..b66c56097 100644
--- a/program/lib/Roundcube/rcube_db_sqlite.php
+++ b/program/lib/Roundcube/rcube_db_sqlite.php
@@ -29,13 +29,6 @@ class rcube_db_sqlite extends rcube_db
public $db_provider = 'sqlite';
/**
- * Database character set
- */
- protected function set_charset($charset)
- {
- }
-
- /**
* Prepare connection
*/
protected function conn_prepare($dsn)
@@ -56,10 +49,6 @@ class rcube_db_sqlite extends rcube_db
*/
protected function conn_configure($dsn, $dbh)
{
- // we emulate via callback some missing functions
- $dbh->sqliteCreateFunction('unix_timestamp', array('rcube_db_sqlite', 'sqlite_unix_timestamp'), 1);
- $dbh->sqliteCreateFunction('now', array('rcube_db_sqlite', 'sqlite_now'), 0);
-
// Initialize database structure in file is empty
if (!empty($dsn['database']) && !filesize($dsn['database'])) {
$data = file_get_contents(RCUBE_INSTALL_PATH . 'SQL/sqlite.initial.sql');
@@ -83,30 +72,32 @@ class rcube_db_sqlite extends rcube_db
}
/**
- * Callback for sqlite: unix_timestamp()
+ * Return SQL statement to convert a field value into a unix timestamp
+ *
+ * @param string $field Field name
+ *
+ * @return string SQL statement to use in query
+ * @deprecated
*/
- public static function sqlite_unix_timestamp($timestamp = '')
+ public function unixtimestamp($field)
{
- $timestamp = trim($timestamp);
- if (!$timestamp) {
- $ret = time();
- }
- else if (!preg_match('/^[0-9]+$/s', $timestamp)) {
- $ret = strtotime($timestamp);
- }
- else {
- $ret = $timestamp;
- }
-
- return $ret;
+ return "strftime('%s', $field)";
}
/**
- * Callback for sqlite: now()
+ * Return SQL function for current time and date
+ *
+ * @param int $interval Optional interval (in seconds) to add/subtract
+ *
+ * @return string SQL function to use in query
*/
- public static function sqlite_now()
+ public function now($interval = 0)
{
- return date("Y-m-d H:i:s");
+ if ($interval) {
+ $add = ($interval > 0 ? '+' : '') . intval($interval) . ' seconds';
+ }
+
+ return "datetime('now'" . ($add ? ",'$add'" : "") . ")";
}
/**
diff --git a/program/lib/Roundcube/rcube_db_sqlsrv.php b/program/lib/Roundcube/rcube_db_sqlsrv.php
index e5dfb1154..45c41cdaf 100644
--- a/program/lib/Roundcube/rcube_db_sqlsrv.php
+++ b/program/lib/Roundcube/rcube_db_sqlsrv.php
@@ -29,29 +29,46 @@ class rcube_db_sqlsrv extends rcube_db
public $db_provider = 'mssql';
/**
- * Driver initialization
+ * Object constructor
+ *
+ * @param string $db_dsnw DSN for read/write operations
+ * @param string $db_dsnr Optional DSN for read only operations
+ * @param bool $pconn Enables persistent connections
*/
- protected function init()
+ public function __construct($db_dsnw, $db_dsnr = '', $pconn = false)
{
+ parent::__construct($db_dsnw, $db_dsnr, $pconn);
+
$this->options['identifier_start'] = '[';
$this->options['identifier_end'] = ']';
}
/**
- * Database character set setting
+ * Driver-specific configuration of database connection
+ *
+ * @param array $dsn DSN for DB connections
+ * @param PDO $dbh Connection handler
*/
- protected function set_charset($charset)
+ protected function conn_configure($dsn, $dbh)
{
- // UTF-8 is default
+ // Set date format in case of non-default language (#1488918)
+ $this->query("SET DATEFORMAT ymd");
}
/**
* Return SQL function for current time and date
*
+ * @param int $interval Optional interval (in seconds) to add/subtract
+ *
* @return string SQL function to use in query
*/
- public function now()
+ public function now($interval = 0)
{
+ if ($interval) {
+ $interval = intval($interval);
+ return "dateadd(second, $interval, getdate())";
+ }
+
return "getdate()";
}
diff --git a/program/lib/Roundcube/rcube_image.php b/program/lib/Roundcube/rcube_image.php
index 735a0df01..09bb4e81b 100644
--- a/program/lib/Roundcube/rcube_image.php
+++ b/program/lib/Roundcube/rcube_image.php
@@ -93,6 +93,10 @@ class rcube_image
$convert = $rcube->config->get('im_convert_path', false);
$props = $this->props();
+ if (empty($props)) {
+ return false;
+ }
+
if (!$filename) {
$filename = $this->image_file;
}
@@ -148,6 +152,10 @@ class rcube_image
return false;
}
+ if ($image === false) {
+ return false;
+ }
+
$scale = $size / max($props['width'], $props['height']);
// Imagemagick resize is implemented in shrinking mode (see -resize argument above)
diff --git a/program/lib/Roundcube/rcube_imap.php b/program/lib/Roundcube/rcube_imap.php
index 43c61fd81..b60aefc5f 100644
--- a/program/lib/Roundcube/rcube_imap.php
+++ b/program/lib/Roundcube/rcube_imap.php
@@ -308,14 +308,7 @@ class rcube_imap extends rcube_storage
*/
public function set_folder($folder)
{
- if ($this->folder == $folder) {
- return;
- }
-
$this->folder = $folder;
-
- // clear messagecount cache for this folder
- $this->clear_messagecount($folder);
}
@@ -626,7 +619,7 @@ class rcube_imap extends rcube_storage
}
if ($mode == 'THREADS') {
- $res = $this->fetch_threads($folder, $force);
+ $res = $this->threads($folder);
$count = $res->count();
if ($status) {
@@ -656,11 +649,11 @@ class rcube_imap extends rcube_storage
$keys[] = 'ALL';
}
if ($status) {
- $keys[] = 'MAX';
+ $keys[] = 'MAX';
}
}
- // @TODO: if $force==false && $mode == 'ALL' we could try to use cache index here
+ // @TODO: if $mode == 'ALL' we could try to use cache index here
// get message count using (E)SEARCH
// not very performant but more precise (using UNDELETED)
@@ -791,7 +784,7 @@ class rcube_imap extends rcube_storage
$threads = $mcache->get_thread($folder);
}
else {
- $threads = $this->fetch_threads($folder);
+ $threads = $this->threads($folder);
}
return $this->fetch_thread_headers($folder, $threads, $page, $slice);
@@ -800,32 +793,47 @@ class rcube_imap extends rcube_storage
/**
* Method for fetching threads data
*
- * @param string $folder Folder name
- * @param bool $force Use IMAP server, no cache
+ * @param string $folder Folder name
*
* @return rcube_imap_thread Thread data object
*/
- function fetch_threads($folder, $force = false)
+ function threads($folder)
{
- if (!$force && ($mcache = $this->get_mcache_engine())) {
+ if ($mcache = $this->get_mcache_engine()) {
// don't store in self's internal cache, cache has it's own internal cache
return $mcache->get_thread($folder);
}
- if (empty($this->icache['threads'])) {
- if (!$this->check_connection()) {
- return new rcube_result_thread();
+ if (!empty($this->icache['threads'])) {
+ if ($this->icache['threads']->get_parameters('MAILBOX') == $folder) {
+ return $this->icache['threads'];
}
+ }
- // get all threads
- $result = $this->conn->thread($folder, $this->threading,
- $this->options['skip_deleted'] ? 'UNDELETED' : '', true);
+ // get all threads
+ $result = $this->threads_direct($folder);
- // add to internal (fast) cache
- $this->icache['threads'] = $result;
+ // add to internal (fast) cache
+ return $this->icache['threads'] = $result;
+ }
+
+
+ /**
+ * Method for direct fetching of threads data
+ *
+ * @param string $folder Folder name
+ *
+ * @return rcube_imap_thread Thread data object
+ */
+ function threads_direct($folder)
+ {
+ if (!$this->check_connection()) {
+ return new rcube_result_thread();
}
- return $this->icache['threads'];
+ // get all threads
+ return $this->conn->thread($folder, $this->threading,
+ $this->options['skip_deleted'] ? 'UNDELETED' : '', true);
}
@@ -1180,12 +1188,15 @@ class rcube_imap extends rcube_storage
* @param string $folder Folder to get index from
* @param string $sort_field Sort column
* @param string $sort_order Sort order [ASC, DESC]
+ * @param bool $no_threads Get not threaded index
+ * @param bool $no_search Get index not limited to search result (optionally)
*
* @return rcube_result_index|rcube_result_thread List of messages (UIDs)
*/
- public function index($folder = '', $sort_field = NULL, $sort_order = NULL)
- {
- if ($this->threading) {
+ public function index($folder = '', $sort_field = NULL, $sort_order = NULL,
+ $no_threads = false, $no_search = false
+ ) {
+ if (!$no_threads && $this->threading) {
return $this->thread_index($folder, $sort_field, $sort_order);
}
@@ -1197,43 +1208,50 @@ class rcube_imap extends rcube_storage
// we have a saved search result, get index from there
if ($this->search_string) {
- if ($this->search_threads) {
- $this->search($folder, $this->search_string, $this->search_charset, $this->sort_field);
+ if ($this->search_set->is_empty()) {
+ return new rcube_result_index($folder, '* SORT');
}
- // use message index sort as default sorting
- if (!$this->sort_field || $this->search_sorted) {
- if ($this->sort_field && $this->search_sort_field != $this->sort_field) {
- $this->search($folder, $this->search_string, $this->search_charset, $this->sort_field);
- }
+ // search result is an index with the same sorting?
+ if (($this->search_set instanceof rcube_result_index)
+ && ((!$this->sort_field && !$this->search_sorted) ||
+ ($this->search_sorted && $this->search_sort_field == $this->sort_field))
+ ) {
$index = $this->search_set;
}
- else if (!$this->check_connection()) {
- return new rcube_result_index();
- }
- else {
- $index = $this->conn->index($folder, $this->search_set->get(),
- $this->sort_field, $this->options['skip_deleted'], true, true);
+ // $no_search is enabled when we are not interested in
+ // fetching index for search result, e.g. to sort
+ // threaded search result we can use full mailbox index.
+ // This makes possible to use index from cache
+ else if (!$no_search) {
+ if (!$this->sort_field) {
+ // No sorting needed, just build index from the search result
+ // @TODO: do we need to sort by UID here?
+ $search = $this->search_set->get_compressed();
+ $index = new rcube_result_index($folder, '* ESEARCH ALL ' . $search);
+ }
+ else {
+ $index = $this->index_direct($folder, $this->search_charset,
+ $this->sort_field, $this->search_set);
+ }
}
- if ($this->sort_order != $index->get_parameters('ORDER')) {
- $index->revert();
- }
+ if (isset($index)) {
+ if ($this->sort_order != $index->get_parameters('ORDER')) {
+ $index->revert();
+ }
- return $index;
+ return $index;
+ }
}
// check local cache
if ($mcache = $this->get_mcache_engine()) {
- $index = $mcache->get_index($folder, $this->sort_field, $this->sort_order);
- }
- // fetch from IMAP server
- else {
- $index = $this->index_direct(
- $folder, $this->sort_field, $this->sort_order);
+ return $mcache->get_index($folder, $this->sort_field, $this->sort_order);
}
- return $index;
+ // fetch from IMAP server
+ return $this->index_direct($folder, $this->sort_field, $this->sort_order);
}
@@ -1241,22 +1259,24 @@ class rcube_imap extends rcube_storage
* Return sorted list of message UIDs ignoring current search settings.
* Doesn't uses cache by default.
*
- * @param string $folder Folder to get index from
- * @param string $sort_field Sort column
- * @param string $sort_order Sort order [ASC, DESC]
- * @param bool $skip_cache Disables cache usage
+ * @param string $folder Folder to get index from
+ * @param string $sort_field Sort column
+ * @param string $sort_order Sort order [ASC, DESC]
+ * @param rcube_result_* $search Optional messages set to limit the result
*
* @return rcube_result_index Sorted list of message UIDs
*/
- public function index_direct($folder, $sort_field = null, $sort_order = null, $skip_cache = true)
+ public function index_direct($folder, $sort_field = null, $sort_order = null, $search = null)
{
- if (!$skip_cache && ($mcache = $this->get_mcache_engine())) {
- $index = $mcache->get_index($folder, $sort_field, $sort_order);
+ if (!empty($search)) {
+ $search = $this->search_set->get_compressed();
}
+
// use message index sort as default sorting
- else if (!$sort_field) {
+ if (!$sort_field) {
// use search result from count() if possible
- if ($this->options['skip_deleted'] && !empty($this->icache['undeleted_idx'])
+ if (empty($search) && $this->options['skip_deleted']
+ && !empty($this->icache['undeleted_idx'])
&& $this->icache['undeleted_idx']->get_parameters('ALL') !== null
&& $this->icache['undeleted_idx']->get_parameters('MAILBOX') == $folder
) {
@@ -1266,8 +1286,12 @@ class rcube_imap extends rcube_storage
return new rcube_result_index();
}
else {
- $index = $this->conn->search($folder,
- 'ALL' .($this->options['skip_deleted'] ? ' UNDELETED' : ''), true);
+ $query = $this->options['skip_deleted'] ? 'UNDELETED' : '';
+ if ($search) {
+ $query = trim($query . ' UID ' . $search);
+ }
+
+ $index = $this->conn->search($folder, $query, true);
}
}
else if (!$this->check_connection()) {
@@ -1276,13 +1300,18 @@ class rcube_imap extends rcube_storage
// fetch complete message index
else {
if ($this->get_capability('SORT')) {
- $index = $this->conn->sort($folder, $sort_field,
- $this->options['skip_deleted'] ? 'UNDELETED' : '', true);
+ $query = $this->options['skip_deleted'] ? 'UNDELETED' : '';
+ if ($search) {
+ $query = trim($query . ' UID ' . $search);
+ }
+
+ $index = $this->conn->sort($folder, $sort_field, $query, true);
}
if (empty($index) || $index->is_error()) {
- $index = $this->conn->index($folder, "1:*", $sort_field,
- $this->options['skip_deleted'], false, true);
+ $index = $this->conn->index($folder, $search ? $search : "1:*",
+ $sort_field, $this->options['skip_deleted'],
+ $search ? true : false, true);
}
}
@@ -1315,7 +1344,7 @@ class rcube_imap extends rcube_storage
}
else {
// get all threads (default sort order)
- $threads = $this->fetch_threads($folder);
+ $threads = $this->threads($folder);
}
$this->set_sort_order($sort_field, $sort_order);
@@ -1326,9 +1355,10 @@ class rcube_imap extends rcube_storage
/**
- * Sort threaded result, using THREAD=REFS method
+ * Sort threaded result, using THREAD=REFS method if available.
+ * If not, use any method and re-sort the result in THREAD=REFS way.
*
- * @param rcube_result_thread $threads Threads result set
+ * @param rcube_result_thread $threads Threads result set
*/
protected function sort_threads($threads)
{
@@ -1340,17 +1370,16 @@ class rcube_imap extends rcube_storage
// THREAD=REFERENCES: sorting by sent date of root message
// THREAD=REFS: sorting by the most recent date in each thread
- if ($this->sort_field && ($this->sort_field != 'date' || $this->get_capability('THREAD') != 'REFS')) {
- $index = $this->index_direct($this->folder, $this->sort_field, $this->sort_order, false);
+ if ($this->threading != 'REFS' || ($this->sort_field && $this->sort_field != 'date')) {
+ $sortby = $this->sort_field ? $this->sort_field : 'date';
+ $index = $this->index($this->folder, $sortby, $this->sort_order, true, true);
if (!$index->is_empty()) {
$threads->sort($index);
}
}
- else {
- if ($this->sort_order != $threads->get_parameters('ORDER')) {
- $threads->revert();
- }
+ else if ($this->sort_order != $threads->get_parameters('ORDER')) {
+ $threads->revert();
}
}
@@ -2238,13 +2267,14 @@ class rcube_imap extends rcube_storage
/**
* Append a mail message (source) to a specific folder
*
- * @param string $folder Target folder
- * @param string $message The message source string or filename
- * @param string $headers Headers string if $message contains only the body
- * @param boolean $is_file True if $message is a filename
- * @param array $flags Message flags
- * @param mixed $date Message internal date
- * @param bool $binary Enables BINARY append
+ * @param string $folder Target folder
+ * @param string|array $message The message source string or filename
+ * or array (of strings and file pointers)
+ * @param string $headers Headers string if $message contains only the body
+ * @param boolean $is_file True if $message is a filename
+ * @param array $flags Message flags
+ * @param mixed $date Message internal date
+ * @param bool $binary Enables BINARY append
*
* @return int|bool Appended message UID or True on success, False on error
*/
@@ -2637,7 +2667,6 @@ class rcube_imap extends rcube_storage
if ($list_extended) {
// unsubscribe non-existent folders, remove from the list
- // we can do this only when LIST response is available
if (is_array($a_folders) && $name == '*' && !empty($this->conn->data['LIST'])) {
foreach ($a_folders as $idx => $folder) {
if (($opts = $this->conn->data['LIST'][$folder])
@@ -2650,19 +2679,14 @@ class rcube_imap extends rcube_storage
}
}
else {
- // unsubscribe non-existent folders, remove them from the list,
- // we can do this only when LIST response is available
- if (is_array($a_folders) && $name == '*' && !empty($this->conn->data['LIST'])) {
- foreach ($a_folders as $idx => $folder) {
- if (!isset($this->conn->data['LIST'][$folder])
- || in_array('\\Noselect', $this->conn->data['LIST'][$folder])
- ) {
- // Some servers returns \Noselect for existing folders
- if (!$this->folder_exists($folder)) {
- $this->conn->unsubscribe($folder);
- unset($a_folders[$idx]);
- }
- }
+ // unsubscribe non-existent folders, remove them from the list
+ if (is_array($a_folders) && !empty($a_folders) && $name == '*') {
+ $existing = $this->list_folders($root, $name);
+ $nonexisting = array_diff($a_folders, $existing);
+ $a_folders = array_diff($a_folders, $nonexisting);
+
+ foreach ($nonexisting as $folder) {
+ $this->conn->unsubscribe($folder);
}
}
}
@@ -3691,7 +3715,7 @@ class rcube_imap extends rcube_storage
{
if ($this->caching && !$this->cache) {
$rcube = rcube::get_instance();
- $ttl = $rcube->config->get('message_cache_lifetime', '10d');
+ $ttl = $rcube->config->get('imap_cache_ttl', '10d');
$this->cache = $rcube->get_cache('IMAP', $this->caching, $ttl);
}
@@ -3739,21 +3763,6 @@ class rcube_imap extends rcube_storage
}
}
- /**
- * Delete outdated cache entries
- */
- public function expunge_cache()
- {
- if ($this->mcache) {
- $ttl = rcube::get_instance()->config->get('message_cache_lifetime', '10d');
- $this->mcache->expunge($ttl);
- }
-
- if ($this->cache) {
- $this->cache->expunge();
- }
- }
-
/* --------------------------------
* message caching methods
@@ -3787,8 +3796,9 @@ class rcube_imap extends rcube_storage
if ($this->messages_caching && !$this->mcache) {
$rcube = rcube::get_instance();
if (($dbh = $rcube->get_dbh()) && ($userid = $rcube->get_user_id())) {
+ $ttl = $rcube->config->get('messages_cache_ttl', '10d');
$this->mcache = new rcube_imap_cache(
- $dbh, $this, $userid, $this->options['skip_deleted']);
+ $dbh, $this, $userid, $this->options['skip_deleted'], $ttl);
}
}
@@ -3810,6 +3820,15 @@ class rcube_imap extends rcube_storage
}
+ /**
+ * Delete outdated cache entries
+ */
+ function cache_gc()
+ {
+ rcube_imap_cache::gc();
+ }
+
+
/* --------------------------------
* protected methods
* --------------------------------*/
@@ -4103,9 +4122,9 @@ class rcube_imap extends rcube_storage
return $this->index($folder, $sort_field, $sort_order);
}
- public function message_index_direct($folder, $sort_field = null, $sort_order = null, $skip_cache = true)
+ public function message_index_direct($folder, $sort_field = null, $sort_order = null)
{
- return $this->index_direct($folder, $sort_field, $sort_order, $skip_cache);
+ return $this->index_direct($folder, $sort_field, $sort_order);
}
public function list_mailboxes($root='', $name='*', $filter=null, $rights=null, $skip_sort=false)
diff --git a/program/lib/Roundcube/rcube_imap_cache.php b/program/lib/Roundcube/rcube_imap_cache.php
index 47d9aaf4a..061ac546d 100644
--- a/program/lib/Roundcube/rcube_imap_cache.php
+++ b/program/lib/Roundcube/rcube_imap_cache.php
@@ -49,6 +49,13 @@ class rcube_imap_cache
private $userid;
/**
+ * Expiration time in seconds
+ *
+ * @var int
+ */
+ private $ttl;
+
+ /**
* Internal (in-memory) cache
*
* @var array
@@ -83,13 +90,25 @@ class rcube_imap_cache
/**
* Object constructor.
+ *
+ * @param rcube_db $db DB handler
+ * @param rcube_imap $imap IMAP handler
+ * @param int $userid User identifier
+ * @param bool $skip_deleted skip_deleted flag
+ * @param string $ttl Expiration time of memcache/apc items
+ *
*/
- function __construct($db, $imap, $userid, $skip_deleted)
+ function __construct($db, $imap, $userid, $skip_deleted, $ttl=0)
{
+ // convert ttl string to seconds
+ $ttl = get_offset_sec($ttl);
+ if ($ttl > 2592000) $ttl = 2592000;
+
$this->db = $db;
$this->imap = $imap;
$this->userid = $userid;
$this->skip_deleted = $skip_deleted;
+ $this->ttl = $ttl;
}
@@ -215,9 +234,7 @@ class rcube_imap_cache
* 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)
+ * @param string $mailbox Folder name
*
* @return array Messages threaded index
*/
@@ -256,19 +273,11 @@ class rcube_imap_cache
if ($index === null) {
// Get mailbox data (UIDVALIDITY, counters, etc.) for status check
$mbox_data = $this->imap->folder_data($mailbox);
-
- if ($mbox_data['EXISTS']) {
- // get all threads (default sort order)
- $threads = $this->imap->fetch_threads($mailbox, true);
- }
- else {
- $threads = new rcube_result_thread($mailbox, '* THREAD');
- }
-
- $index['object'] = $threads;
+ // Get THREADS result
+ $index['object'] = $this->get_thread_data($mailbox, $mbox_data);
// insert/update
- $this->add_thread_row($mailbox, $threads, $mbox_data, $exists);
+ $this->add_thread_row($mailbox, $index['object'], $mbox_data, $exists);
}
$this->icache[$mailbox]['thread'] = $index;
@@ -407,8 +416,8 @@ class rcube_imap_cache
return;
}
- $msg = serialize($this->db->encode(clone $message));
$flags = 0;
+ $msg = clone $message;
if (!empty($message->flags)) {
foreach ($this->flags as $idx => $flag) {
@@ -417,14 +426,16 @@ class rcube_imap_cache
}
}
}
+
unset($msg->flags);
+ $msg = $this->db->encode($msg, true);
// 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 ".$this->db->table_name('cache_messages')
- ." SET flags = ?, data = ?, changed = ".$this->db->now()
+ ." SET flags = ?, data = ?, expires = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL')
." WHERE user_id = ?"
." AND mailbox = ?"
." AND uid = ?",
@@ -435,12 +446,29 @@ class rcube_imap_cache
}
}
+ $this->db->set_option('ignore_key_errors', true);
+
// insert new record
- $this->db->query(
+ $res = $this->db->query(
"INSERT INTO ".$this->db->table_name('cache_messages')
- ." (user_id, mailbox, uid, flags, changed, data)"
- ." VALUES (?, ?, ?, ?, ".$this->db->now().", ?)",
+ ." (user_id, mailbox, uid, flags, expires, data)"
+ ." VALUES (?, ?, ?, ?, ". ($this->ttl ? $this->db->now($this->ttl) : 'NULL') . ", ?)",
$this->userid, $mailbox, (int) $message->uid, $flags, $msg);
+
+ // race-condition, insert failed so try update (#1489146)
+ // thanks to ignore_key_errors "duplicate row" errors will be ignored
+ if ($force && !$res && !$this->db->is_error($res)) {
+ $this->db->query(
+ "UPDATE ".$this->db->table_name('cache_messages')
+ ." SET expires = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL')
+ .", flags = ?, data = ?"
+ ." WHERE user_id = ?"
+ ." AND mailbox = ?"
+ ." AND uid = ?",
+ $flags, $msg, $this->userid, $mailbox, (int) $message->uid);
+ }
+
+ $this->db->set_option('ignore_key_errors', false);
}
@@ -481,7 +509,7 @@ class rcube_imap_cache
$this->db->query(
"UPDATE ".$this->db->table_name('cache_messages')
- ." SET changed = ".$this->db->now()
+ ." SET expires = ". ($this->ttl ? $this->db->now($this->ttl) : 'NULL')
.", flags = flags ".($enabled ? "+ $idx" : "- $idx")
." WHERE user_id = ?"
." AND mailbox = ?"
@@ -604,23 +632,21 @@ class rcube_imap_cache
/**
- * Delete cache entries older than TTL
- *
- * @param string $ttl Lifetime of message cache entries
+ * Delete expired cache entries
*/
- function expunge($ttl)
+ static function gc()
{
- // get expiration timestamp
- $ts = get_offset_time($ttl, -1);
+ $rcube = rcube::get_instance();
+ $db = $rcube->get_dbh();
- $this->db->query("DELETE FROM ".$this->db->table_name('cache_messages')
- ." WHERE changed < " . $this->db->fromunixtime($ts));
+ $db->query("DELETE FROM ".$db->table_name('cache_messages')
+ ." WHERE expires < " . $db->now());
- $this->db->query("DELETE FROM ".$this->db->table_name('cache_index')
- ." WHERE changed < " . $this->db->fromunixtime($ts));
+ $db->query("DELETE FROM ".$db->table_name('cache_index')
+ ." WHERE expires < " . $db->now());
- $this->db->query("DELETE FROM ".$this->db->table_name('cache_thread')
- ." WHERE changed < " . $this->db->fromunixtime($ts));
+ $db->query("DELETE FROM ".$db->table_name('cache_thread')
+ ." WHERE expires < " . $db->now());
}
@@ -639,7 +665,7 @@ class rcube_imap_cache
if ($sql_arr = $this->db->fetch_assoc($sql_result)) {
$data = explode('@', $sql_arr['data']);
- $index = @unserialize($data[0]);
+ $index = $this->db->decode($data[0], true);
unset($data[0]);
if (empty($index)) {
@@ -676,7 +702,7 @@ class rcube_imap_cache
if ($sql_arr = $this->db->fetch_assoc($sql_result)) {
$data = explode('@', $sql_arr['data']);
- $thread = @unserialize($data[0]);
+ $thread = $this->db->decode($data[0], true);
unset($data[0]);
if (empty($thread)) {
@@ -702,7 +728,7 @@ class rcube_imap_cache
$data, $mbox_data = array(), $exists = false, $modseq = null)
{
$data = array(
- serialize($data),
+ $this->db->encode($data, true),
$sort_field,
(int) $this->skip_deleted,
(int) $mbox_data['UIDVALIDITY'],
@@ -712,20 +738,38 @@ class rcube_imap_cache
$data = implode('@', $data);
if ($exists) {
- $sql_result = $this->db->query(
+ $res = $this->db->query(
"UPDATE ".$this->db->table_name('cache_index')
- ." SET data = ?, valid = 1, changed = ".$this->db->now()
+ ." SET data = ?, valid = 1, expires = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL')
." WHERE user_id = ?"
." AND mailbox = ?",
$data, $this->userid, $mailbox);
+
+ if ($this->db->affected_rows($res)) {
+ return;
+ }
}
- else {
- $sql_result = $this->db->query(
- "INSERT INTO ".$this->db->table_name('cache_index')
- ." (user_id, mailbox, data, valid, changed)"
- ." VALUES (?, ?, ?, 1, ".$this->db->now().")",
- $this->userid, $mailbox, $data);
+
+ $this->db->set_option('ignore_key_errors', true);
+
+ $res = $this->db->query(
+ "INSERT INTO ".$this->db->table_name('cache_index')
+ ." (user_id, mailbox, valid, expires, data)"
+ ." VALUES (?, ?, 1, ". ($this->ttl ? $this->db->now($this->ttl) : 'NULL') .", ?)",
+ $this->userid, $mailbox, $data);
+
+ // race-condition, insert failed so try update (#1489146)
+ // thanks to ignore_key_errors "duplicate row" errors will be ignored
+ if (!$exists && !$res && !$this->db->is_error($res)) {
+ $res = $this->db->query(
+ "UPDATE ".$this->db->table_name('cache_index')
+ ." SET data = ?, valid = 1, expires = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL')
+ ." WHERE user_id = ?"
+ ." AND mailbox = ?",
+ $data, $this->userid, $mailbox);
}
+
+ $this->db->set_option('ignore_key_errors', false);
}
@@ -735,28 +779,48 @@ class rcube_imap_cache
private function add_thread_row($mailbox, $data, $mbox_data = array(), $exists = false)
{
$data = array(
- serialize($data),
+ $this->db->encode($data, true),
(int) $this->skip_deleted,
(int) $mbox_data['UIDVALIDITY'],
(int) $mbox_data['UIDNEXT'],
);
$data = implode('@', $data);
+ $expires = ($this->ttl ? $this->db->now($this->ttl) : 'NULL');
+
if ($exists) {
- $sql_result = $this->db->query(
+ $res = $this->db->query(
"UPDATE ".$this->db->table_name('cache_thread')
- ." SET data = ?, changed = ".$this->db->now()
+ ." SET data = ?, expires = $expires"
." WHERE user_id = ?"
." AND mailbox = ?",
$data, $this->userid, $mailbox);
+
+ if ($this->db->affected_rows($res)) {
+ return;
+ }
}
- else {
- $sql_result = $this->db->query(
- "INSERT INTO ".$this->db->table_name('cache_thread')
- ." (user_id, mailbox, data, changed)"
- ." VALUES (?, ?, ?, ".$this->db->now().")",
- $this->userid, $mailbox, $data);
+
+ $this->db->set_option('ignore_key_errors', true);
+
+ $res = $this->db->query(
+ "INSERT INTO ".$this->db->table_name('cache_thread')
+ ." (user_id, mailbox, expires, data)"
+ ." VALUES (?, ?, $expires, ?)",
+ $this->userid, $mailbox, $data);
+
+ // race-condition, insert failed so try update (#1489146)
+ // thanks to ignore_key_errors "duplicate row" errors will be ignored
+ if (!$exists && !$res && !$this->db->is_error($res)) {
+ $this->db->query(
+ "UPDATE ".$this->db->table_name('cache_thread')
+ ." SET expires = $expires, data = ?"
+ ." WHERE user_id = ?"
+ ." AND mailbox = ?",
+ $data, $this->userid, $mailbox);
}
+
+ $this->db->set_option('ignore_key_errors', false);
}
@@ -1004,7 +1068,7 @@ class rcube_imap_cache
$this->db->query(
"UPDATE ".$this->db->table_name('cache_messages')
- ." SET flags = ?, changed = ".$this->db->now()
+ ." SET flags = ?, expires = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL')
." WHERE user_id = ?"
." AND mailbox = ?"
." AND uid = ?"
@@ -1032,17 +1096,18 @@ class rcube_imap_cache
}
}
- // Invalidate thread index (?)
- if (!$index['valid']) {
- $this->remove_thread($mailbox);
- }
-
$sort_field = $index['sort_field'];
$sort_order = $index['object']->get_parameters('ORDER');
$exists = true;
// Validate index
if (!$this->validate($mailbox, $index, $exists)) {
+ // Invalidate (remove) thread index
+ // if $exists=false it was already removed in validate()
+ if ($exists) {
+ $this->remove_thread($mailbox);
+ }
+
// Update index
$data = $this->get_index_data($mailbox, $sort_field, $sort_order, $mbox_data);
}
@@ -1067,7 +1132,7 @@ class rcube_imap_cache
*/
private function build_message($sql_arr)
{
- $message = $this->db->decode(unserialize($sql_arr['data']));
+ $message = $this->db->decode($sql_arr['data'], true);
if ($message) {
$message->flags = array();
@@ -1150,6 +1215,25 @@ class rcube_imap_cache
return $index;
}
+
+
+ /**
+ * Fetches thread data from IMAP server
+ */
+ private function get_thread_data($mailbox, $mbox_data = array())
+ {
+ if (empty($mbox_data)) {
+ $mbox_data = $this->imap->folder_data($mailbox);
+ }
+
+ if ($mbox_data['EXISTS']) {
+ // get all threads (default sort order)
+ return $this->imap->threads_direct($mailbox);
+ }
+
+ return new rcube_result_thread($mailbox, '* THREAD');
+ }
+
}
// for backward compat.
diff --git a/program/lib/Roundcube/rcube_imap_generic.php b/program/lib/Roundcube/rcube_imap_generic.php
index 292b932e1..920c7184a 100644
--- a/program/lib/Roundcube/rcube_imap_generic.php
+++ b/program/lib/Roundcube/rcube_imap_generic.php
@@ -715,6 +715,10 @@ class rcube_imap_generic
$auth_method = 'CHECK';
}
+ if (!empty($this->prefs['disabled_caps'])) {
+ $this->prefs['disabled_caps'] = array_map('strtoupper', (array)$this->prefs['disabled_caps']);
+ }
+
$result = false;
// initialize connection
@@ -1329,9 +1333,8 @@ class rcube_imap_generic
$folders[$mailbox] = array();
}
- // store LSUB options only if not empty, this way
- // we can detect a situation when LIST doesn't return specified folder
- if (!empty($opts) || $cmd == 'LIST') {
+ // store folder options
+ if ($cmd == 'LIST') {
// Add to options array
if (empty($this->data['LIST'][$mailbox]))
$this->data['LIST'][$mailbox] = $opts;
@@ -1563,11 +1566,12 @@ class rcube_imap_generic
}
// message IDs
- if (!empty($add))
+ if (!empty($add)) {
$add = $this->compressMessageSet($add);
+ }
list($code, $response) = $this->execute($return_uid ? 'UID SORT' : 'SORT',
- array("($field)", $encoding, 'ALL' . (!empty($add) ? ' '.$add : '')));
+ array("($field)", $encoding, !empty($add) ? $add : 'ALL'));
if ($code != self::ERROR_OK) {
$response = null;
@@ -2158,14 +2162,18 @@ class rcube_imap_generic
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 if (stripos($name, 'BODY[') === 0) {
+ $name = str_replace(']', '', substr($name, 5));
+
+ if ($name == 'HEADER.FIELDS') {
+ // skip ']' after headers list
+ $this->tokenizeResponse($line, 1);
+ $headers = $this->tokenizeResponse($line, 1);
+ }
+ else if (strlen($name))
+ $result[$id]->bodypart[$name] = $value;
else
- $result[$id]->body = $body;
+ $result[$id]->body = $value;
}
}
@@ -2505,6 +2513,7 @@ class rcube_imap_generic
// handle one line response
if ($line[0] == '(' && substr($line, -1) == ')') {
// tokenize content inside brackets
+ // the content can be e.g.: (UID 9844 BODY[2.4] NIL)
$tokens = $this->tokenizeResponse(preg_replace('/(^\(|\)$)/', '', $line));
for ($i=0; $i<count($tokens); $i+=2) {
@@ -2533,7 +2542,11 @@ class rcube_imap_generic
$prev = '';
$found = true;
- while ($bytes > 0) {
+ // empty body
+ if (!$bytes) {
+ $result = '';
+ }
+ else while ($bytes > 0) {
$line = $this->readLine(8192);
if ($line === NULL) {
@@ -2615,11 +2628,11 @@ class rcube_imap_generic
/**
* Handler for IMAP APPEND command
*
- * @param string $mailbox Mailbox name
- * @param string $message Message content
- * @param array $flags Message flags
- * @param string $date Message internal date
- * @param bool $binary Enable BINARY append (RFC3516)
+ * @param string $mailbox Mailbox name
+ * @param string|array $message The message source string or array (of strings and file pointers)
+ * @param array $flags Message flags
+ * @param string $date Message internal date
+ * @param bool $binary Enable BINARY append (RFC3516)
*
* @return string|bool On success APPENDUID response (if available) or True, False on failure
*/
@@ -2633,13 +2646,28 @@ class rcube_imap_generic
$binary = $binary && $this->getCapability('BINARY');
$literal_plus = !$binary && $this->prefs['literal+'];
+ $len = 0;
+ $msg = is_array($message) ? $message : array(&$message);
+ $chunk_size = 512000;
+
+ for ($i=0, $cnt=count($msg); $i<$cnt; $i++) {
+ if (is_resource($msg[$i])) {
+ $stat = fstat($msg[$i]);
+ if ($stat === false) {
+ return false;
+ }
+ $len += $stat['size'];
+ }
+ else {
+ if (!$binary) {
+ $msg[$i] = str_replace("\r", '', $msg[$i]);
+ $msg[$i] = str_replace("\n", "\r\n", $msg[$i]);
+ }
- if (!$binary) {
- $message = str_replace("\r", '', $message);
- $message = str_replace("\n", "\r\n", $message);
+ $len += strlen($msg[$i]);
+ }
}
- $len = strlen($message);
if (!$len) {
return false;
}
@@ -2664,7 +2692,32 @@ class rcube_imap_generic
}
}
- if (!$this->putLine($message)) {
+ foreach ($msg as $msg_part) {
+ // file pointer
+ if (is_resource($msg_part)) {
+ rewind($msg_part);
+ while (!feof($msg_part) && $this->fp) {
+ $buffer = fread($msg_part, $chunk_size);
+ $this->putLine($buffer, false);
+ }
+ fclose($msg_part);
+ }
+ // string
+ else {
+ $size = strlen($msg_part);
+
+ // Break up the data by sending one chunk (up to 512k) at a time.
+ // This approach reduces our peak memory usage
+ for ($offset = 0; $offset < $size; $offset += $chunk_size) {
+ $chunk = substr($msg_part, $offset, $chunk_size);
+ if (!$this->putLine($chunk, false)) {
+ return false;
+ }
+ }
+ }
+ }
+
+ if (!$this->putLine('')) { // \r\n
return false;
}
@@ -2703,94 +2756,23 @@ class rcube_imap_generic
*/
function appendFromFile($mailbox, $path, $headers=null, $flags = array(), $date = null, $binary = false)
{
- unset($this->data['APPENDUID']);
-
- if ($mailbox === null || $mailbox === '') {
- return false;
- }
-
// open message file
- $in_fp = false;
if (file_exists(realpath($path))) {
- $in_fp = fopen($path, 'r');
+ $fp = fopen($path, 'r');
}
- if (!$in_fp) {
+ if (!$fp) {
$this->setError(self::ERROR_UNKNOWN, "Couldn't open $path for reading");
return false;
}
- $body_separator = "\r\n\r\n";
- $len = filesize($path);
-
- if (!$len) {
- return false;
- }
-
+ $message = array();
if ($headers) {
- $headers = preg_replace('/[\r\n]+$/', '', $headers);
- $len += strlen($headers) + strlen($body_separator);
+ $message[] = trim($headers, "\r\n") . "\r\n\r\n";
}
+ $message[] = $fp;
- $binary = $binary && $this->getCapability('BINARY');
- $literal_plus = !$binary && $this->prefs['literal+'];
-
- // build APPEND command
- $key = $this->nextTag();
- $request = "$key APPEND " . $this->escape($mailbox) . ' (' . $this->flagsToStr($flags) . ')';
- if (!empty($date)) {
- $request .= ' ' . $this->escape($date);
- }
- $request .= ' ' . ($binary ? '~' : '') . '{' . $len . ($literal_plus ? '+' : '') . '}';
-
- // send APPEND command
- if ($this->putLine($request)) {
- // Don't wait when LITERAL+ is supported
- if (!$literal_plus) {
- $line = $this->readReply();
-
- if ($line[0] != '+') {
- $this->parseResult($line, 'APPEND: ');
- return false;
- }
- }
-
- // send headers with body separator
- if ($headers) {
- $this->putLine($headers . $body_separator, false);
- }
-
- // send file
- while (!feof($in_fp) && $this->fp) {
- $buffer = fgets($in_fp, 4096);
- $this->putLine($buffer, false);
- }
- fclose($in_fp);
-
- if (!$this->putLine('')) { // \r\n
- return false;
- }
-
- // read response
- do {
- $line = $this->readLine();
- } while (!$this->startsWith($line, $key, true, true));
-
- // Clear internal status cache
- unset($this->data['STATUS:'.$mailbox]);
-
- 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");
- }
-
- return false;
+ return $this->append($mailbox, $message, $flags, $date, $binary);
}
/**
@@ -3008,7 +2990,7 @@ class rcube_imap_generic
}
foreach ($entries as $name => $value) {
- $entries[$name] = $this->escape($name) . ' ' . $this->escape($value);
+ $entries[$name] = $this->escape($name) . ' ' . $this->escape($value, true);
}
$entries = implode(' ', $entries);
@@ -3505,25 +3487,24 @@ class rcube_imap_generic
// Parenthesized list
case '(':
- case '[':
$str = substr($str, 1);
$result[] = self::tokenizeResponse($str);
break;
case ')':
- case ']':
$str = substr($str, 1);
return $result;
break;
- // String atom, number, NIL, *, %
+ // String atom, number, astring, NIL, *, %
default:
// empty string
if ($str === '' || $str === null) {
break 2;
}
- // excluded chars: SP, CTL, ), [, ]
- if (preg_match('/^([^\x00-\x20\x29\x5B\x5D\x7F]+)/', $str, $m)) {
+ // excluded chars: SP, CTL, ), DEL
+ // we do not exclude [ and ] (#1489223)
+ if (preg_match('/^([^\x00-\x20\x29\x7F]+)/', $str, $m)) {
$result[] = $m[1] == 'NIL' ? NULL : $m[1];
$str = substr($str, strlen($m[1]));
}
@@ -3714,6 +3695,10 @@ class rcube_imap_generic
$this->capability = explode(' ', strtoupper($str));
+ if (!empty($this->prefs['disabled_caps'])) {
+ $this->capability = array_diff($this->capability, $this->prefs['disabled_caps']);
+ }
+
if (!isset($this->prefs['literal+']) && in_array('LITERAL+', $this->capability)) {
$this->prefs['literal+'] = true;
}
diff --git a/program/lib/Roundcube/rcube_ldap.php b/program/lib/Roundcube/rcube_ldap.php
index 70163b21c..555a56471 100644
--- a/program/lib/Roundcube/rcube_ldap.php
+++ b/program/lib/Roundcube/rcube_ldap.php
@@ -3,8 +3,8 @@
/*
+-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client |
- | Copyright (C) 2006-2012, The Roundcube Dev Team |
- | Copyright (C) 2011-2012, Kolab Systems AG |
+ | Copyright (C) 2006-2013, The Roundcube Dev Team |
+ | Copyright (C) 2011-2013, Kolab Systems AG |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
@@ -27,38 +27,50 @@
*/
class rcube_ldap extends rcube_addressbook
{
- /** public properties */
+ // public properties
public $primary_key = 'ID';
- public $groups = false;
- public $readonly = true;
- public $ready = false;
- public $group_id = 0;
- public $coltypes = array();
-
- /** private properties */
- protected $conn;
- protected $prop = array();
+ public $groups = false;
+ public $readonly = true;
+ public $ready = false;
+ public $group_id = 0;
+ public $coltypes = array();
+
+ // private properties
+ protected $ldap;
+ protected $prop = array();
protected $fieldmap = array();
+ protected $filter = '';
protected $sub_filter;
- protected $filter = '';
- protected $result = null;
- protected $ldap_result = null;
+ protected $result;
+ protected $ldap_result;
protected $mail_domain = '';
protected $debug = false;
- private $base_dn = '';
+ /**
+ * Group objectclass (lowercase) to member attribute mapping
+ *
+ * @var array
+ */
+ private static $group_types = array(
+ 'group' => 'member',
+ 'groupofnames' => 'member',
+ 'kolabgroupofnames' => 'member',
+ 'groupofuniquenames' => 'uniqueMember',
+ 'kolabgroupofuniquenames' => 'uniqueMember',
+ 'univentiongroup' => 'uniqueMember',
+ 'groupofurls' => null,
+ );
+
+ private $base_dn = '';
private $groups_base_dn = '';
- private $group_url = null;
+ private $group_url;
private $cache;
- private $vlv_active = false;
- private $vlv_count = 0;
-
/**
* Object constructor
*
- * @param array $p LDAP connection properties
+ * @param array $p LDAP connection properties
* @param boolean $debug Enables debug mode
* @param string $mail_domain Current user mail domain name
*/
@@ -66,8 +78,7 @@ class rcube_ldap extends rcube_addressbook
{
$this->prop = $p;
- if (isset($p['searchonly']))
- $this->searchonly = $p['searchonly'];
+ $fetch_attributes = array('objectClass');
// check if groups are configured
if (is_array($p['groups']) && count($p['groups'])) {
@@ -82,6 +93,21 @@ class rcube_ldap extends rcube_addressbook
$this->prop['groups']['name_attr'] = 'cn';
if (empty($this->prop['groups']['scope']))
$this->prop['groups']['scope'] = 'sub';
+
+ // add group name attrib to the list of attributes to be fetched
+ $fetch_attributes[] = $this->prop['groups']['name_attr'];
+ }
+ if (is_array($p['group_filters']) && count($p['group_filters'])) {
+ $this->groups = true;
+
+ foreach ($p['group_filters'] as $k => $group_filter) {
+ // set default name attribute to cn
+ if (empty($group_filter['name_attr']) && empty($this->prop['groups']['name_attr']))
+ $this->prop['group_filters'][$k]['name_attr'] = $group_filter['name_attr'] = 'cn';
+
+ if ($group_filter['name_attr'])
+ $fetch_attributes[] = $group_filter['name_attr'];
+ }
}
// fieldmap property is given
@@ -186,7 +212,24 @@ class rcube_ldap extends rcube_addressbook
// initialize cache
$rcube = rcube::get_instance();
- $this->cache = $rcube->get_cache('LDAP.' . asciiwords($this->prop['name']), 'db', 600);
+ if ($cache_type = $rcube->config->get('ldap_cache', 'db')) {
+ $cache_ttl = $rcube->config->get('ldap_cache_ttl', '10m');
+ $cache_name = 'LDAP.' . asciiwords($this->prop['name']);
+
+ $this->cache = $rcube->get_cache($cache_name, $cache_type, $cache_ttl);
+ }
+
+ // determine which attributes to fetch
+ $this->prop['list_attributes'] = array_unique($fetch_attributes);
+ $this->prop['attributes'] = array_merge(array_values($this->fieldmap), $fetch_attributes);
+ foreach ($rcube->config->get('contactlist_fields') as $col) {
+ $this->prop['list_attributes'] = array_merge($this->prop['list_attributes'], $this->_map_field($col));
+ }
+
+ // initialize ldap wrapper object
+ $this->ldap = new rcube_ldap_generic($this->prop);
+ $this->ldap->set_cache($this->cache);
+ $this->ldap->set_debug($this->debug);
$this->_connect();
}
@@ -199,49 +242,18 @@ class rcube_ldap extends rcube_addressbook
{
$rcube = rcube::get_instance();
- if (!function_exists('ldap_connect'))
- rcube::raise_error(array('code' => 100, 'type' => 'ldap',
- 'file' => __FILE__, 'line' => __LINE__,
- 'message' => "No ldap support in this installation of PHP"),
- true, true);
-
- if (is_resource($this->conn))
+ if ($this->ready)
return true;
if (!is_array($this->prop['hosts']))
$this->prop['hosts'] = array($this->prop['hosts']);
- if (empty($this->prop['ldap_version']))
- $this->prop['ldap_version'] = 3;
-
// try to connect + bind for every host configured
// with OpenLDAP 2.x ldap_connect() always succeeds but ldap_bind will fail if host isn't reachable
// see http://www.php.net/manual/en/function.ldap-connect.php
foreach ($this->prop['hosts'] as $host) {
- $host = rcube_utils::idn_to_ascii(rcube_utils::parse_host($host));
- $hostname = $host.($this->prop['port'] ? ':'.$this->prop['port'] : '');
-
- $this->_debug("C: Connect [$hostname] [{$this->prop['name']}]");
-
- if ($lc = @ldap_connect($host, $this->prop['port'])) {
- if ($this->prop['use_tls'] === true)
- if (!ldap_start_tls($lc))
- continue;
-
- $this->_debug("S: OK");
-
- ldap_set_option($lc, LDAP_OPT_PROTOCOL_VERSION, $this->prop['ldap_version']);
- $this->prop['host'] = $host;
- $this->conn = $lc;
-
- if (!empty($this->prop['network_timeout']))
- ldap_set_option($lc, LDAP_OPT_NETWORK_TIMEOUT, $this->prop['network_timeout']);
-
- if (isset($this->prop['referrals']))
- ldap_set_option($lc, LDAP_OPT_REFERRALS, $this->prop['referrals']);
- }
- else {
- $this->_debug("S: NOT OK");
+ // skip host if connection failed
+ if (!$this->ldap->connect($host)) {
continue;
}
@@ -256,7 +268,7 @@ class rcube_ldap extends rcube_addressbook
$this->base_dn = $this->prop['base_dn'];
$this->groups_base_dn = ($this->prop['groups']['base_dn']) ?
- $this->prop['groups']['base_dn'] : $this->base_dn;
+ $this->prop['groups']['base_dn'] : $this->base_dn;
// User specific access, generate the proper values to use.
if ($this->prop['user_specific']) {
@@ -275,29 +287,46 @@ class rcube_ldap extends rcube_addressbook
$replaces = array('%dn' => '', '%dc' => $dc, '%d' => $d, '%fu' => $fu, '%u' => $u);
+ // Search for the dn to use to authenticate
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']);
- }
-
- // 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);
+ $search_bind_dn = strtr($this->prop['search_bind_dn'], $replaces);
+ $search_base_dn = strtr($this->prop['search_base_dn'], $replaces);
+ $search_filter = strtr($this->prop['search_filter'], $replaces);
- $this->_debug("S: searching with base {$this->prop['search_base_dn']} for {$this->prop['search_filter']}");
+ $cache_key = 'DN.' . md5("$host:$search_bind_dn:$search_base_dn:$search_filter:"
+ .$this->prop['search_bind_pw']);
- $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];
- }
+ if ($this->cache && ($dn = $this->cache->get($cache_key))) {
+ $replaces['%dn'] = $dn;
}
else {
- $this->_debug("S: ".ldap_error($this->conn));
+ $ldap = $this->ldap;
+ if (!empty($search_bind_dn) && !empty($this->prop['search_bind_pw'])) {
+ // To protect from "Critical extension is unavailable" error
+ // we need to use a separate LDAP connection
+ if (!empty($this->prop['vlv'])) {
+ $ldap = new rcube_ldap_generic($this->prop);
+ $ldap->set_debug($this->debug);
+ $ldap->set_cache($this->cache);
+ if (!$ldap->connect($host)) {
+ continue;
+ }
+ }
+
+ if (!$ldap->bind($search_bind_dn, $this->prop['search_bind_pw'])) {
+ continue; // bind failed, try next host
+ }
+ }
+
+ $res = $ldap->search($search_base_dn, $search_filter, 'sub', array('uid'));
+ if ($res) {
+ $res->rewind();
+ $replaces['%dn'] = $res->get_dn();
+ }
+
+ if ($ldap != $this->ldap) {
+ $ldap->close();
+ }
}
// DN not found
@@ -309,9 +338,13 @@ class rcube_ldap extends rcube_addressbook
'code' => 100, 'type' => 'ldap',
'file' => __FILE__, 'line' => __LINE__,
'message' => "DN not found using LDAP search."), true);
- return false;
+ continue;
}
}
+
+ if ($this->cache && !empty($replaces['%dn'])) {
+ $this->cache->set($cache_key, $replaces['%dn']);
+ }
}
// Replace the bind_dn and base_dn variables.
@@ -329,13 +362,13 @@ class rcube_ldap extends rcube_addressbook
}
else {
if (!empty($bind_dn)) {
- $this->ready = $this->bind($bind_dn, $bind_pass);
+ $this->ready = $this->ldap->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);
+ $this->ready = $this->ldap->sasl_bind($this->prop['auth_cid'], $bind_pass, $bind_user);
}
else {
- $this->ready = $this->sasl_bind($bind_user, $bind_pass);
+ $this->ready = $this->ldap->sasl_bind($bind_user, $bind_pass);
}
}
@@ -346,10 +379,10 @@ class rcube_ldap extends rcube_addressbook
} // end foreach hosts
- if (!is_resource($this->conn)) {
+ if (!is_resource($this->ldap->conn)) {
rcube::raise_error(array('code' => 100, 'type' => 'ldap',
'file' => __FILE__, 'line' => __LINE__,
- 'message' => "Could not connect to any LDAP server, last tried $hostname"), true);
+ 'message' => "Could not connect to any LDAP server, last tried $host"), true);
return false;
}
@@ -359,112 +392,47 @@ class rcube_ldap extends rcube_addressbook
/**
- * Bind connection with (SASL-) user and password
- *
- * @param string $authc Authentication user
- * @param string $pass Bind password
- * @param string $authz Autorization user
- *
- * @return boolean True on success, False on error
+ * Close connection to LDAP server
*/
- public function sasl_bind($authc, $pass, $authz=null)
+ function close()
{
- if (!$this->conn) {
- return false;
- }
-
- if (!function_exists('ldap_sasl_bind')) {
- rcube::raise_error(array('code' => 100, 'type' => 'ldap',
- 'file' => __FILE__, 'line' => __LINE__,
- 'message' => "Unable to bind: ldap_sasl_bind() not exists"),
- true, true);
+ if ($this->ldap) {
+ $this->ldap->close();
}
-
- if (!empty($authz)) {
- $authz = 'u:' . $authz;
- }
-
- if (!empty($this->prop['auth_method'])) {
- $method = $this->prop['auth_method'];
- }
- else {
- $method = 'DIGEST-MD5';
- }
-
- $this->_debug("C: Bind [mech: $method, authc: $authc, authz: $authz] [pass: $pass]");
-
- if (ldap_sasl_bind($this->conn, NULL, $pass, $method, NULL, $authc, $authz)) {
- $this->_debug("S: OK");
- return true;
- }
-
- $this->_debug("S: ".ldap_error($this->conn));
-
- rcube::raise_error(array(
- 'code' => ldap_errno($this->conn), 'type' => 'ldap',
- 'file' => __FILE__, 'line' => __LINE__,
- 'message' => "Bind failed for authcid=$authc ".ldap_error($this->conn)),
- true);
-
- return false;
}
/**
- * Bind connection with DN and password
- *
- * @param string Bind DN
- * @param string Bind password
+ * Returns address book name
*
- * @return boolean True on success, False on error
+ * @return string Address book name
*/
- public function bind($dn, $pass)
+ function get_name()
{
- if (!$this->conn) {
- return false;
- }
-
- $this->_debug("C: Bind [dn: $dn] [pass: $pass]");
-
- if (@ldap_bind($this->conn, $dn, $pass)) {
- $this->_debug("S: OK");
- return true;
- }
-
- $this->_debug("S: ".ldap_error($this->conn));
-
- rcube::raise_error(array(
- 'code' => ldap_errno($this->conn), 'type' => 'ldap',
- 'file' => __FILE__, 'line' => __LINE__,
- 'message' => "Bind failed for dn=$dn: ".ldap_error($this->conn)),
- true);
-
- return false;
+ return $this->prop['name'];
}
/**
- * Close connection to LDAP server
+ * Set internal list page
+ *
+ * @param number Page number to list
*/
- function close()
+ function set_page($page)
{
- if ($this->conn)
- {
- $this->_debug("C: Close");
- ldap_unbind($this->conn);
- $this->conn = null;
- }
+ $this->list_page = (int)$page;
+ $this->ldap->set_vlv_page($this->list_page, $this->page_size);
}
-
/**
- * Returns address book name
+ * Set internal page size
*
- * @return string Address book name
+ * @param number Number of records to display on one page
*/
- function get_name()
+ function set_pagesize($size)
{
- return $this->prop['name'];
+ $this->page_size = (int)$size;
+ $this->ldap->set_vlv_page($this->list_page, $this->page_size);
}
@@ -524,16 +492,14 @@ class rcube_ldap extends rcube_addressbook
*/
function list_records($cols=null, $subset=0)
{
- if ($this->prop['searchonly'] && empty($this->filter) && !$this->group_id)
- {
+ if ($this->prop['searchonly'] && empty($this->filter) && !$this->group_id) {
$this->result = new rcube_result_set(0);
$this->result->searchonly = true;
return $this->result;
}
// fetch group members recursively
- if ($this->group_id && $this->group_data['dn'])
- {
+ if ($this->group_id && $this->group_data['dn']) {
$entries = $this->list_group_members($this->group_data['dn']);
// make list of entries unique and sort it
@@ -547,34 +513,34 @@ class rcube_ldap extends rcube_addressbook
$entries['count'] = count($entries);
$this->result = new rcube_result_set($entries['count'], ($this->list_page-1) * $this->page_size);
}
- else
- {
- // add general filter to query
- if (!empty($this->prop['filter']) && empty($this->filter))
- $this->set_search_set($this->prop['filter']);
+ else {
+ $prop = $this->group_id ? $this->group_data : $this->prop;
+
+ // use global search filter
+ if (!empty($this->filter))
+ $prop['filter'] = $this->filter;
// exec LDAP search if no result resource is stored
- if ($this->conn && !$this->ldap_result)
- $this->_exec_search();
+ if ($this->ready && !$this->ldap_result)
+ $this->ldap_result = $this->ldap->search($prop['base_dn'], $prop['filter'], $prop['scope'], $this->prop['attributes'], $prop);
// count contacts for this user
$this->result = $this->count();
// we have a search result resource
- if ($this->ldap_result && $this->result->count > 0)
- {
+ if ($this->ldap_result && $this->result->count > 0) {
// 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);
+ if ($this->sort_col && $prop['scope'] !== 'base' && !$this->ldap->vlv_active)
+ $this->ldap_result->sort($this->sort_col);
// get all entries from the ldap server
- $entries = ldap_get_entries($this->conn, $this->ldap_result);
+ $entries = $this->ldap_result->entries();
}
} // end else
// start and end of the page
- $start_row = $this->vlv_active ? 0 : $this->result->first;
+ $start_row = $this->ldap->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;
@@ -599,43 +565,34 @@ class rcube_ldap extends rcube_addressbook
// 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));
+ $attribs = array('dn','objectClass','member','uniqueMember','memberURL');
+ $entries = $this->ldap->read_entries($dn, '(objectClass=*)', $attribs);
+ if ($entries === false) {
return $group_members;
}
-
- $entries = @ldap_get_entries($this->conn, $result);
}
- for ($i=0; $i < $entries['count']; $i++)
- {
+ for ($i=0; $i < $entries['count']; $i++) {
$entry = $entries[$i];
+ $attrs = array();
- if (empty($entry['objectclass']))
- continue;
+ foreach ((array)$entry['objectclass'] as $objectclass) {
+ if (strtolower($objectclass) == 'groupofurls') {
+ $members = $this->_list_group_memberurl($dn, $entry, $count);
+ $group_members = array_merge($group_members, $members);
+ }
+ else if (($member_attr = $this->get_group_member_attr(array($objectclass), ''))
+ && ($member_attr = strtolower($member_attr)) && !in_array($member_attr, $attrs)
+ ) {
+ $members = $this->_list_group_members($dn, $entry, $member_attr, $count);
+ $group_members = array_merge($group_members, $members);
+ $attrs[] = $member_attr;
+ }
- foreach ((array)$entry['objectclass'] as $objectclass)
- {
- switch (strtolower($objectclass)) {
- case "group":
- 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;
+ if ($this->prop['sizelimit'] && count($group_members) > $this->prop['sizelimit']) {
+ break 2;
}
}
-
- if ($this->prop['sizelimit'] && count($group_members) > $this->prop['sizelimit'])
- break;
}
return array_filter($group_members);
@@ -654,28 +611,24 @@ class rcube_ldap extends rcube_addressbook
// 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]))
+ if (empty($entry[$attr])) {
return $group_members;
+ }
// read these attributes for all members
- $attrib = $count ? array('dn') : array_values($this->fieldmap);
- $attrib[] = 'objectClass';
+ $attrib = $count ? array('dn','objectClass') : $this->prop['list_attributes'];
$attrib[] = 'member';
$attrib[] = 'uniqueMember';
$attrib[] = 'memberURL';
- for ($i=0; $i < $entry[$attr]['count']; $i++)
- {
+ $filter = $this->prop['groups']['member_filter'] ? $this->prop['groups']['member_filter'] : '(objectclass=*)';
+
+ for ($i=0; $i < $entry[$attr]['count']; $i++) {
if (empty($entry[$attr][$i]))
continue;
- $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 = $this->ldap->read_entries($entry[$attr][$i], $filter, $attrib);
+ if ($members == false) {
$members = array();
}
@@ -701,34 +654,22 @@ class rcube_ldap extends rcube_addressbook
{
$group_members = array();
- for ($i=0; $i < $entry['memberurl']['count']; $i++)
- {
+ 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];
+ $attrs = $count ? array('dn','objectClass') : $this->prop['list_attributes'];
+ if ($result = $this->ldap->search($m[1], $filter, $m[2], $attrs, $this->group_data)) {
+ $entries = $result->entries();
+ for ($j = 0; $j < $entries['count']; $j++) {
+ if (self::is_group_entry($entries[$j]) && ($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];
+ }
}
}
@@ -764,14 +705,11 @@ class rcube_ldap extends rcube_addressbook
$mode = intval($mode);
// special treatment for ID-based search
- if ($fields == 'ID' || $fields == $this->primary_key)
- {
+ if ($fields == 'ID' || $fields == $this->primary_key) {
$ids = !is_array($value) ? explode(',', $value) : $value;
$result = new rcube_result_set();
- foreach ($ids as $id)
- {
- if ($rec = $this->get_record($id, true))
- {
+ foreach ($ids as $id) {
+ if ($rec = $this->get_record($id, true)) {
$result->add($rec);
$result->count++;
}
@@ -783,34 +721,20 @@ class rcube_ldap extends rcube_addressbook
$rcube = rcube::get_instance();
$list_fields = $rcube->config->get('contactlist_fields');
- if ($this->prop['vlv_search'] && $this->conn && join(',', (array)$fields) == join(',', $list_fields))
- {
- // 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']);
-
+ if ($this->prop['vlv_search'] && $this->ready && join(',', (array)$fields) == join(',', $list_fields)) {
$this->result = new rcube_result_set(0);
- if (!$this->ldap_result) {
- $this->_debug("S: ".ldap_error($this->conn));
+ $search_suffix = $this->prop['fuzzy_search'] && $mode != 1 ? '*' : '';
+ $ldap_data = $this->ldap->search($this->base_dn, $this->prop['filter'], $this->prop['scope'], $this->prop['attributes'],
+ array('search' => $value . $search_suffix /*, 'sort' => $this->prop['sort'] */));
+ if ($ldap_data === false) {
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]);
+ $search = mb_strtolower($value);
+ foreach ($ldap_data as $i => $entry) {
+ $rec = $this->_ldap2result($entry);
foreach ($fields as $f) {
foreach ((array)$rec[$f] as $val) {
if ($this->compare_search_value($f, $val, $search, $mode)) {
@@ -836,31 +760,27 @@ class rcube_ldap extends rcube_addressbook
}
}
- if ($fields == '*')
- {
+ if ($fields == '*') {
// search_fields are required for fulltext search
- if (empty($this->prop['search_fields']))
- {
+ if (empty($this->prop['search_fields'])) {
$this->set_error(self::ERROR_SEARCH, 'nofulltextsearch');
$this->result = new rcube_result_set();
return $this->result;
}
- if (is_array($this->prop['search_fields']))
- {
+ if (is_array($this->prop['search_fields'])) {
foreach ($this->prop['search_fields'] as $field) {
- $filter .= "($field=$wp" . $this->_quote_string($value) . "$ws)";
+ $filter .= "($field=$wp" . rcube_ldap_generic::quote_string($value) . "$ws)";
}
}
}
- else
- {
+ else {
foreach ((array)$fields as $idx => $field) {
$val = is_array($value) ? $value[$idx] : $value;
if ($attrs = $this->_map_field($field)) {
if (count($attrs) > 1)
$filter .= '(|';
foreach ($attrs as $f)
- $filter .= "($f=$wp" . $this->_quote_string($val) . "$ws)";
+ $filter .= "($f=$wp" . rcube_ldap_generic::quote_string($val) . "$ws)";
if (count($attrs) > 1)
$filter .= ')';
}
@@ -871,6 +791,8 @@ class rcube_ldap extends rcube_addressbook
// add required (non empty) fields filter
$req_filter = '';
foreach ((array)$required as $field) {
+ if (in_array($field, (array)$fields)) // required field is already in search filter
+ continue;
if ($attrs = $this->_map_field($field)) {
if (count($attrs) > 1)
$req_filter .= '(|';
@@ -893,7 +815,6 @@ class rcube_ldap extends rcube_addressbook
// set filter string and execute search
$this->set_search_set($filter);
- $this->_exec_search();
if ($select)
$this->list_records();
@@ -912,20 +833,20 @@ class rcube_ldap extends rcube_addressbook
function count()
{
$count = 0;
- if ($this->conn && $this->ldap_result) {
- $count = $this->vlv_active ? $this->vlv_count : ldap_count_entries($this->conn, $this->ldap_result);
+ if ($this->ldap_result) {
+ $count = $this->ldap_result->count();
}
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.
+ else if ($this->ready) {
+ $prop = $this->group_id ? $this->group_data : $this->prop;
- $count = (int) $this->_exec_search(true);
+ if (!empty($this->filter)) { // Use global search filter
+ $prop['filter'] = $this->filter;
+ }
+ $count = $this->ldap->search($prop['base_dn'], $prop['filter'], $prop['scope'], array('dn'), $prop, true);
}
return new rcube_result_set($count, ($this->list_page-1) * $this->page_size);
@@ -955,28 +876,16 @@ class rcube_ldap extends rcube_addressbook
{
$res = $this->result = null;
- if ($this->conn && $dn)
- {
+ if ($this->ready && $dn) {
$dn = self::dn_decode($dn);
- $this->_debug("C: Read [dn: $dn] [(objectclass=*)]");
-
- if ($ldap_result = @ldap_read($this->conn, $dn, '(objectclass=*)', array_values($this->fieldmap))) {
- $this->_debug("S: OK");
-
- $entry = ldap_first_entry($this->conn, $ldap_result);
-
- if ($entry && ($rec = ldap_get_attributes($this->conn, $entry))) {
- $rec = array_change_key_case($rec, CASE_LOWER);
- }
- }
- else {
- $this->_debug("S: ".ldap_error($this->conn));
+ if ($rec = $this->ldap->get_entry($dn)) {
+ $rec = array_change_key_case($rec, CASE_LOWER);
}
// Use ldap_list to get subentries like country (c) attribute (#1488123)
if (!empty($rec) && $this->sub_filter) {
- if ($entries = $this->ldap_list($dn, $this->sub_filter, array_keys($this->prop['sub_fields']))) {
+ if ($entries = $this->ldap->list_entries($dn, $this->sub_filter, array_keys($this->prop['sub_fields']))) {
foreach ($entries as $entry) {
$lrec = array_change_key_case($entry, CASE_LOWER);
$rec = array_merge($lrec, $rec);
@@ -988,7 +897,7 @@ class rcube_ldap extends rcube_addressbook
// Add in the dn for the entry.
$rec['dn'] = $dn;
$res = $this->_ldap2result($rec);
- $this->result = new rcube_result_set();
+ $this->result = new rcube_result_set(1);
$this->result->add($res);
}
}
@@ -1101,7 +1010,7 @@ class rcube_ldap extends rcube_addressbook
}
// Build the new entries DN.
- $dn = $this->prop['LDAP_rdn'].'='.$this->_quote_string($newentry[$this->prop['LDAP_rdn']], true).','.$this->base_dn;
+ $dn = $this->prop['LDAP_rdn'].'='.rcube_ldap_generic::quote_string($newentry[$this->prop['LDAP_rdn']], true).','.$this->base_dn;
// Remove attributes that need to be added separately (child objects)
$xfields = array();
@@ -1114,19 +1023,19 @@ class rcube_ldap extends rcube_addressbook
}
}
- if (!$this->ldap_add($dn, $newentry)) {
+ if (!$this->ldap->add($dn, $newentry)) {
$this->set_error(self::ERROR_SAVING, 'errorsaving');
return false;
}
foreach ($xfields as $xidx => $xf) {
- $xdn = $xidx.'='.$this->_quote_string($xf).','.$dn;
+ $xdn = $xidx.'='.rcube_ldap_generic::quote_string($xf).','.$dn;
$xf = array(
$xidx => $xf,
'objectClass' => (array) $this->prop['sub_fields'][$xidx],
);
- $this->ldap_add($xdn, $xf);
+ $this->ldap->add($xdn, $xf);
}
$dn = self::dn_encode($dn);
@@ -1232,7 +1141,7 @@ class rcube_ldap extends rcube_addressbook
// Update the entry as required.
if (!empty($deletedata)) {
// Delete the fields.
- if (!$this->ldap_mod_del($dn, $deletedata)) {
+ if (!$this->ldap->mod_del($dn, $deletedata)) {
$this->set_error(self::ERROR_SAVING, 'errorsaving');
return false;
}
@@ -1242,17 +1151,17 @@ class rcube_ldap extends rcube_addressbook
// Handle RDN change
if ($replacedata[$this->prop['LDAP_rdn']]) {
$newdn = $this->prop['LDAP_rdn'].'='
- .$this->_quote_string($replacedata[$this->prop['LDAP_rdn']], true)
+ .rcube_ldap_generic::quote_string($replacedata[$this->prop['LDAP_rdn']], true)
.','.$this->base_dn;
if ($dn != $newdn) {
$newrdn = $this->prop['LDAP_rdn'].'='
- .$this->_quote_string($replacedata[$this->prop['LDAP_rdn']], true);
+ .rcube_ldap_generic::quote_string($replacedata[$this->prop['LDAP_rdn']], true);
unset($replacedata[$this->prop['LDAP_rdn']]);
}
}
// Replace the fields.
if (!empty($replacedata)) {
- if (!$this->ldap_mod_replace($dn, $replacedata)) {
+ if (!$this->ldap->mod_replace($dn, $replacedata)) {
$this->set_error(self::ERROR_SAVING, 'errorsaving');
return false;
}
@@ -1268,8 +1177,8 @@ class rcube_ldap extends rcube_addressbook
// remove sub-entries
if (!empty($subdeldata)) {
foreach ($subdeldata as $fld => $val) {
- $subdn = $fld.'='.$this->_quote_string($val).','.$dn;
- if (!$this->ldap_delete($subdn)) {
+ $subdn = $fld.'='.rcube_ldap_generic::quote_string($val).','.$dn;
+ if (!$this->ldap->delete($subdn)) {
return false;
}
}
@@ -1277,7 +1186,7 @@ class rcube_ldap extends rcube_addressbook
if (!empty($newdata)) {
// Add the fields.
- if (!$this->ldap_mod_add($dn, $newdata)) {
+ if (!$this->ldap->mod_add($dn, $newdata)) {
$this->set_error(self::ERROR_SAVING, 'errorsaving');
return false;
}
@@ -1285,7 +1194,7 @@ class rcube_ldap extends rcube_addressbook
// Handle RDN change
if (!empty($newrdn)) {
- if (!$this->ldap_rename($dn, $newrdn, null, true)) {
+ if (!$this->ldap->rename($dn, $newrdn, null, true)) {
$this->set_error(self::ERROR_SAVING, 'errorsaving');
return false;
}
@@ -1296,8 +1205,7 @@ class rcube_ldap extends rcube_addressbook
// change the group membership of the contact
if ($this->groups) {
$group_ids = $this->get_record_groups($dn);
- foreach ($group_ids as $group_id)
- {
+ foreach (array_keys($group_ids) as $group_id) {
$this->remove_from_group($group_id, $dn);
$this->add_to_group($group_id, $newdn);
}
@@ -1309,12 +1217,12 @@ class rcube_ldap extends rcube_addressbook
// add sub-entries
if (!empty($subnewdata)) {
foreach ($subnewdata as $fld => $val) {
- $subdn = $fld.'='.$this->_quote_string($val).','.$dn;
+ $subdn = $fld.'='.rcube_ldap_generic::quote_string($val).','.$dn;
$xf = array(
$fld => $val,
'objectClass' => (array) $this->prop['sub_fields'][$fld],
);
- $this->ldap_add($subdn, $xf);
+ $this->ldap->add($subdn, $xf);
}
}
@@ -1342,9 +1250,9 @@ class rcube_ldap extends rcube_addressbook
// Need to delete all sub-entries first
if ($this->sub_filter) {
- if ($entries = $this->ldap_list($dn, $this->sub_filter)) {
+ if ($entries = $this->ldap->list_entries($dn, $this->sub_filter)) {
foreach ($entries as $entry) {
- if (!$this->ldap_delete($entry['dn'])) {
+ if (!$this->ldap->delete($entry['dn'])) {
$this->set_error(self::ERROR_SAVING, 'errorsaving');
return false;
}
@@ -1353,7 +1261,7 @@ class rcube_ldap extends rcube_addressbook
}
// Delete the record.
- if (!$this->ldap_delete($dn)) {
+ if (!$this->ldap->delete($dn)) {
$this->set_error(self::ERROR_SAVING, 'errorsaving');
return false;
}
@@ -1362,7 +1270,7 @@ class rcube_ldap extends rcube_addressbook
if ($this->groups) {
$dn = self::dn_encode($dn);
$group_ids = $this->get_record_groups($dn);
- foreach ($group_ids as $group_id) {
+ foreach (array_keys($group_ids) as $group_id) {
$this->remove_from_group($group_id, $dn);
}
}
@@ -1377,8 +1285,8 @@ class rcube_ldap extends rcube_addressbook
*/
function delete_all()
{
- //searching for contact entries
- $dn_list = $this->ldap_list($this->base_dn, $this->prop['filter'] ? $this->prop['filter'] : '(objectclass=*)');
+ // searching for contact entries
+ $dn_list = $this->ldap->list_entries($this->base_dn, $this->prop['filter'] ? $this->prop['filter'] : '(objectclass=*)');
if (!empty($dn_list)) {
foreach ($dn_list as $idx => $entry) {
@@ -1428,120 +1336,26 @@ class rcube_ldap extends rcube_addressbook
}
}
- /**
- * Execute the LDAP search based on the stored credentials
- */
- private function _exec_search($count = false)
- {
- if ($this->ready)
- {
- $filter = $this->filter ? $this->filter : '(objectclass=*)';
- $function = $this->_scope2func($this->prop['scope'], $ns_function);
-
- $this->_debug("C: Search [$filter][dn: $this->base_dn]");
-
- // when using VLV, we get the total count by...
- if (!$count && $function != 'ldap_read' && $this->prop['vlv'] && !$this->group_id) {
- // ...either reading numSubOrdinates attribute
- 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];
- $this->_debug("D: total numsubordinates = " . $this->vlv_count);
- }
- else if (!function_exists('ldap_parse_virtuallist_control')) // ...or by fetching all records dn and count them
- $this->vlv_count = $this->_exec_search(true);
-
- $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,
- $attrs, 0, (int)$this->prop['sizelimit'], (int)$this->prop['timelimit'])
- ) {
- // when running on a patched PHP we can use the extended functions to retrieve the total count from the LDAP search result
- if ($this->vlv_active && function_exists('ldap_parse_virtuallist_control')) {
- if (ldap_parse_result($this->conn, $this->ldap_result,
- $errcode, $matcheddn, $errmsg, $referrals, $serverctrls)
- && $serverctrls // can be null e.g. in case of adm. limit error
- ) {
- ldap_parse_virtuallist_control($this->conn, $serverctrls,
- $last_offset, $this->vlv_count, $vresult);
- $this->_debug("S: VLV result: last_offset=$last_offset; content_count=$this->vlv_count");
- }
- else {
- $this->_debug("S: ".($errmsg ? $errmsg : ldap_error($this->conn)));
- }
- }
-
- $entries_count = ldap_count_entries($this->conn, $this->ldap_result);
- $this->_debug("S: $entries_count record(s)");
-
- return $count ? $entries_count : true;
- }
- else {
- $this->_debug("S: ".ldap_error($this->conn));
- }
- }
-
- 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)
- */
- 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)$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);
-
- $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));
- $this->set_error(self::ERROR_SEARCH, 'vlvnotsupported');
- return false;
- }
-
- return true;
- }
-
/**
* Converts LDAP entry into an array
*/
private function _ldap2result($rec)
{
- $out = array();
+ $out = array('_type' => 'person');
+ $fieldmap = $this->fieldmap;
if ($rec['dn'])
$out[$this->primary_key] = self::dn_encode($rec['dn']);
- foreach ($this->fieldmap as $rf => $lf)
+ // determine record type
+ if (self::is_group_entry($rec)) {
+ $out['_type'] = 'group';
+ $out['readonly'] = true;
+ $fieldmap['name'] = $this->group_data['name_attr'] ? $this->group_data['name_attr'] : $this->prop['groups']['name_attr'];
+ }
+
+ foreach ($fieldmap as $rf => $lf)
{
for ($i=0; $i < $rec[$lf]['count']; $i++) {
if (!($value = $rec[$lf][$i]))
@@ -1603,8 +1417,10 @@ class rcube_ldap extends rcube_addressbook
if (is_array($colprop['serialized'])) {
foreach ($colprop['serialized'] as $subtype => $delim) {
$key = $col.':'.$subtype;
- foreach ((array)$save_cols[$key] as $i => $val)
- $save_cols[$key][$i] = join($delim, array($val['street'], $val['locality'], $val['zipcode'], $val['country']));
+ foreach ((array)$save_cols[$key] as $i => $val) {
+ $values = array($val['street'], $val['locality'], $val['zipcode'], $val['country']);
+ $save_cols[$key][$i] = count(array_filter($values)) ? join($delim, $values) : null;
+ }
}
}
}
@@ -1642,11 +1458,11 @@ class rcube_ldap extends rcube_addressbook
{
// list of known attribute aliases
static $aliases = array(
- 'gn' => 'givenname',
+ 'gn' => 'givenname',
'rfc822mailbox' => 'email',
- 'userid' => 'uid',
- 'emailaddress' => 'email',
- 'pkcs9email' => 'email',
+ 'userid' => 'uid',
+ 'emailaddress' => 'email',
+ 'pkcs9email' => 'email',
);
list($name, $limit) = explode(':', $namev, 2);
@@ -1655,6 +1471,15 @@ class rcube_ldap extends rcube_addressbook
return (isset($aliases[$name]) ? $aliases[$name] : $name) . $suffix;
}
+ /**
+ * Determines whether the given LDAP entry is a group record
+ */
+ private static function is_group_entry($entry)
+ {
+ $classes = array_map('strtolower', (array)$entry['objectclass']);
+
+ return count(array_intersect(array_keys(self::$group_types), $classes)) > 0;
+ }
/**
* Prints debug info to the log
@@ -1671,55 +1496,27 @@ 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
- *
- * @param string $str Attribute value
- * @param bool $dn True if the attribute is a DN
- *
- * @return string Quoted string
- */
- private static function _quote_string($str, $dn=false)
- {
- // take firt entry if array given
- if (is_array($str))
- $str = reset($str);
-
- if ($dn)
- $replace = array(','=>'\2c', '='=>'\3d', '+'=>'\2b', '<'=>'\3c',
- '>'=>'\3e', ';'=>'\3b', '\\'=>'\5c', '"'=>'\22', '#'=>'\23');
- else
- $replace = array('*'=>'\2a', '('=>'\28', ')'=>'\29', '\\'=>'\5c',
- '/'=>'\2f');
- return strtr($str, $replace);
+ if ($this->ldap) {
+ $this->ldap->set_debug($dbg);
+ }
}
/**
* Setter for the current group
- * (empty, has to be re-implemented by extending class)
*/
function set_group($group_id)
{
- if ($group_id)
- {
- if (($group_cache = $this->cache->get('groups')) === null)
- $group_cache = $this->_fetch_groups();
-
+ if ($group_id) {
$this->group_id = $group_id;
- $this->group_data = $group_cache[$group_id];
+ $this->group_data = $this->get_group_entry($group_id);
}
- else
- {
+ else {
$this->group_id = 0;
$this->group_data = null;
}
@@ -1738,15 +1535,13 @@ class rcube_ldap extends rcube_addressbook
*/
function list_groups($search = null, $mode = 0)
{
- if (!$this->groups)
+ 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();
+ $group_cache = $this->_fetch_groups();
+ $groups = array();
- $groups = array();
if ($search) {
foreach ($group_cache as $group) {
if ($this->compare_search_value('name', $group['name'], $search, $mode)) {
@@ -1754,8 +1549,9 @@ class rcube_ldap extends rcube_addressbook
}
}
}
- else
+ else {
$groups = $group_cache;
+ }
return array_values($groups);
}
@@ -1763,80 +1559,139 @@ class rcube_ldap extends rcube_addressbook
/**
* Fetch groups from server
*/
- private function _fetch_groups($vlv_page = 0)
+ private function _fetch_groups($vlv_page = null)
{
- $base_dn = $this->groups_base_dn;
- $filter = $this->prop['groups']['filter'];
- $name_attr = $this->prop['groups']['name_attr'];
+ // special case: list groups from 'group_filters' config
+ if ($vlv_page === null && !empty($this->prop['group_filters'])) {
+ $groups = array();
+
+ // list regular groups configuration as special filter
+ if (!empty($this->prop['groups']['filter'])) {
+ $id = '__groups__';
+ $groups[$id] = array('ID' => $id, 'name' => rcube_label('groups'), 'virtual' => true) + $this->prop['groups'];
+ }
+
+ foreach ($this->prop['group_filters'] as $id => $prop) {
+ $groups[$id] = $prop + array('ID' => $id, 'name' => ucfirst($id), 'virtual' => true, 'base_dn' => $this->base_dn);
+ }
+
+ return $groups;
+ }
+
+ if ($this->cache && $vlv_page === null && ($groups = $this->cache->get('groups')) !== null) {
+ return $groups;
+ }
+
+ $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];
+ $sort_attr = $sort_attrs[0];
- $this->_debug("C: Search [$filter][dn: $base_dn]");
+ $ldap = $this->ldap;
// use vlv to list groups
if ($this->prop['groups']['vlv']) {
$page_size = 200;
- if (!$this->prop['groups']['sort'])
+ 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);
+ }
+
+ $ldap = clone $this->ldap;
+ $ldap->set_config($this->prop['groups']);
+ $ldap->set_vlv_page($vlv_page+1, $page_size);
}
- $function = $this->_scope2func($this->prop['groups']['scope']);
- $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));
+ $attrs = array_unique(array('dn', 'objectClass', $name_attr, $email_attr, $sort_attr));
+ $ldap_data = $ldap->search($base_dn, $filter, $this->prop['groups']['scope'], $attrs, $this->prop['groups']);
+
+ if ($ldap_data === false) {
return array();
}
- $ldap_data = ldap_get_entries($this->conn, $res);
- $this->_debug("S: ".ldap_count_entries($this->conn, $res)." record(s)");
-
- $groups = array();
+ $groups = array();
$group_sortnames = array();
- $group_count = $ldap_data["count"];
- for ($i=0; $i < $group_count; $i++)
- {
- $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);
+ $group_count = $ldap_data->count();
+
+ foreach ($ldap_data as $entry) {
+ if (!$entry['dn']) // DN is mandatory
+ $entry['dn'] = $ldap_data->get_dn();
+
+ $group_name = is_array($entry[$name_attr]) ? $entry[$name_attr][0] : $entry[$name_attr];
+ $group_id = self::dn_encode($entry['dn']);
$groups[$group_id]['ID'] = $group_id;
- $groups[$group_id]['dn'] = $ldap_data[$i]['dn'];
+ $groups[$group_id]['dn'] = $entry['dn'];
$groups[$group_id]['name'] = $group_name;
- $groups[$group_id]['member_attr'] = $this->get_group_member_attr($ldap_data[$i]['objectclass']);
+ $groups[$group_id]['member_attr'] = $this->get_group_member_attr($entry['objectclass']);
// 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];
+ for ($j=0; $entry[$email_attr] && $j < $entry[$email_attr]['count']; $j++) {
+ if (strpos($entry[$email_attr][$j], '@') > 0)
+ $groups[$group_id]['email'][] = $entry[$email_attr][$j];
}
- $group_sortnames[] = mb_strtolower($ldap_data[$i][$sort_attr][0]);
+ $group_sortnames[] = mb_strtolower($entry[$sort_attr][0]);
}
// recursive call can exit here
- if ($vlv_page > 0)
+ 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);
+ while ($this->prop['groups']['vlv'] && $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'])
+ if (!$this->prop['groups']['vlv']) {
array_multisort($group_sortnames, SORT_ASC, SORT_STRING, $groups);
+ }
// cache this
- $this->cache->set('groups', $groups);
+ if ($this->cache) {
+ $this->cache->set('groups', $groups);
+ }
return $groups;
}
/**
+ * Fetch a group entry from LDAP and save in local cache
+ */
+ private function get_group_entry($group_id)
+ {
+ $group_cache = $this->_fetch_groups();
+
+ // add group record to cache if it isn't yet there
+ if (!isset($group_cache[$group_id])) {
+ $name_attr = $this->prop['groups']['name_attr'];
+ $dn = self::dn_decode($group_id);
+
+ if ($list = $this->ldap->read_entries($dn, '(objectClass=*)', array('dn','objectClass','member','uniqueMember','memberURL',$name_attr,$this->fieldmap['email']))) {
+ $entry = $list[0];
+ $group_name = is_array($entry[$name_attr]) ? $entry[$name_attr][0] : $entry[$name_attr];
+ $group_cache[$group_id]['ID'] = $group_id;
+ $group_cache[$group_id]['dn'] = $dn;
+ $group_cache[$group_id]['name'] = $group_name;
+ $group_cache[$group_id]['member_attr'] = $this->get_group_member_attr($entry['objectclass']);
+ }
+ else {
+ $group_cache[$group_id] = false;
+ }
+
+ if ($this->cache) {
+ $this->cache->set('groups', $group_cache);
+ }
+ }
+
+ return $group_cache[$group_id];
+ }
+
+ /**
* Get group properties such as name and email address(es)
*
* @param string Group identifier
@@ -1844,10 +1699,7 @@ class rcube_ldap extends rcube_addressbook
*/
function get_group($group_id)
{
- if (($group_cache = $this->cache->get('groups')) === null)
- $group_cache = $this->_fetch_groups();
-
- $group_data = $group_cache[$group_id];
+ $group_data = $this->get_group_entry($group_id);
unset($group_data['dn'], $group_data['member_attr']);
return $group_data;
@@ -1861,24 +1713,24 @@ class rcube_ldap extends rcube_addressbook
*/
function create_group($group_name)
{
- $base_dn = $this->groups_base_dn;
- $new_dn = "cn=$group_name,$base_dn";
- $new_gid = self::dn_encode($group_name);
+ $new_dn = 'cn=' . rcube_ldap_generic::quote_string($group_name, true) . ',' . $this->groups_base_dn;
+ $new_gid = self::dn_encode($new_dn);
$member_attr = $this->get_group_member_attr();
- $name_attr = $this->prop['groups']['name_attr'] ? $this->prop['groups']['name_attr'] : 'cn';
-
- $new_entry = array(
+ $name_attr = $this->prop['groups']['name_attr'] ? $this->prop['groups']['name_attr'] : 'cn';
+ $new_entry = array(
'objectClass' => $this->prop['groups']['object_classes'],
$name_attr => $group_name,
$member_attr => '',
);
- if (!$this->ldap_add($new_dn, $new_entry)) {
+ if (!$this->ldap->add($new_dn, $new_entry)) {
$this->set_error(self::ERROR_SAVING, 'errorsaving');
return false;
}
- $this->cache->remove('groups');
+ if ($this->cache) {
+ $this->cache->remove('groups');
+ }
return array('id' => $new_gid, 'name' => $group_name);
}
@@ -1891,19 +1743,18 @@ class rcube_ldap extends rcube_addressbook
*/
function delete_group($group_id)
{
- if (($group_cache = $this->cache->get('groups')) === null)
- $group_cache = $this->_fetch_groups();
-
- $base_dn = $this->groups_base_dn;
- $group_name = $group_cache[$group_id]['name'];
- $del_dn = "cn=$group_name,$base_dn";
+ $group_cache = $this->_fetch_groups();
+ $del_dn = $group_cache[$group_id]['dn'];
- if (!$this->ldap_delete($del_dn)) {
+ if (!$this->ldap->delete($del_dn)) {
$this->set_error(self::ERROR_SAVING, 'errorsaving');
return false;
}
- $this->cache->remove('groups');
+ if ($this->cache) {
+ unset($group_cache[$group_id]);
+ $this->cache->set('groups', $group_cache);
+ }
return true;
}
@@ -1918,21 +1769,19 @@ class rcube_ldap extends rcube_addressbook
*/
function rename_group($group_id, $new_name, &$new_gid)
{
- if (($group_cache = $this->cache->get('groups')) === null)
- $group_cache = $this->_fetch_groups();
+ $group_cache = $this->_fetch_groups();
+ $old_dn = $group_cache[$group_id]['dn'];
+ $new_rdn = "cn=" . rcube_ldap_generic::quote_string($new_name, true);
+ $new_gid = self::dn_encode($new_rdn . ',' . $this->groups_base_dn);
- $base_dn = $this->groups_base_dn;
- $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);
-
- if (!$this->ldap_rename($old_dn, $new_rdn, null, true)) {
+ if (!$this->ldap->rename($old_dn, $new_rdn, null, true)) {
$this->set_error(self::ERROR_SAVING, 'errorsaving');
return false;
}
- $this->cache->remove('groups');
+ if ($this->cache) {
+ $this->cache->remove('groups');
+ }
return $new_name;
}
@@ -1947,27 +1796,27 @@ class rcube_ldap extends rcube_addressbook
*/
function add_to_group($group_id, $contact_ids)
{
- 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;
- $group_name = $group_cache[$group_id]['name'];
+ $group_cache = $this->_fetch_groups();
$member_attr = $group_cache[$group_id]['member_attr'];
- $group_dn = "cn=$group_name,$base_dn";
+ $group_dn = $group_cache[$group_id]['dn'];
$new_attrs = array();
- foreach ($contact_ids as $id)
+ if (!is_array($contact_ids)) {
+ $contact_ids = explode(',', $contact_ids);
+ }
+
+ foreach ($contact_ids as $id) {
$new_attrs[$member_attr][] = self::dn_decode($id);
+ }
- if (!$this->ldap_mod_add($group_dn, $new_attrs)) {
+ if (!$this->ldap->mod_add($group_dn, $new_attrs)) {
$this->set_error(self::ERROR_SAVING, 'errorsaving');
return 0;
}
- $this->cache->remove('groups');
+ if ($this->cache) {
+ $this->cache->remove('groups');
+ }
return count($new_attrs[$member_attr]);
}
@@ -1982,27 +1831,27 @@ class rcube_ldap extends rcube_addressbook
*/
function remove_from_group($group_id, $contact_ids)
{
- 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;
- $group_name = $group_cache[$group_id]['name'];
+ $group_cache = $this->_fetch_groups();
$member_attr = $group_cache[$group_id]['member_attr'];
- $group_dn = "cn=$group_name,$base_dn";
+ $group_dn = $group_cache[$group_id]['dn'];
$del_attrs = array();
- foreach ($contact_ids as $id)
+ if (!is_array($contact_ids)) {
+ $contact_ids = explode(',', $contact_ids);
+ }
+
+ foreach ($contact_ids as $id) {
$del_attrs[$member_attr][] = self::dn_decode($id);
+ }
- if (!$this->ldap_mod_del($group_dn, $del_attrs)) {
+ if (!$this->ldap->mod_del($group_dn, $del_attrs)) {
$this->set_error(self::ERROR_SAVING, 'errorsaving');
return 0;
}
- $this->cache->remove('groups');
+ if ($this->cache) {
+ $this->cache->remove('groups');
+ }
return count($del_attrs[$member_attr]);
}
@@ -2017,206 +1866,63 @@ class rcube_ldap extends rcube_addressbook
*/
function get_record_groups($contact_id)
{
- if (!$this->groups)
+ if (!$this->groups) {
return array();
+ }
$base_dn = $this->groups_base_dn;
$contact_dn = self::dn_decode($contact_id);
$name_attr = $this->prop['groups']['name_attr'] ? $this->prop['groups']['name_attr'] : 'cn';
$member_attr = $this->get_group_member_attr();
$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]");
-
- $res = @ldap_search($this->conn, $base_dn, $filter, array($name_attr));
- if ($res === false)
- {
- $this->_debug("S: ".ldap_error($this->conn));
+ $ldap_data = $this->ldap->search($base_dn, $filter, 'sub', array('dn', $name_attr));
+ if ($res === false) {
return array();
}
- $ldap_data = ldap_get_entries($this->conn, $res);
- $this->_debug("S: ".ldap_count_entries($this->conn, $res)." record(s)");
$groups = array();
- for ($i=0; $i<$ldap_data["count"]; $i++)
- {
- $group_name = $ldap_data[$i][$name_attr][0];
- $group_id = self::dn_encode($group_name);
- $groups[$group_id] = $group_id;
+ foreach ($ldap_data as $entry) {
+ if (!$entry['dn'])
+ $entry['dn'] = $ldap_data->get_dn();
+ $group_name = $entry[$name_attr][0];
+ $group_id = self::dn_encode($entry['dn']);
+ $groups[$group_id] = $group_name;
}
+
return $groups;
}
/**
* Detects group member attribute name
*/
- private function get_group_member_attr($object_classes = array())
+ private function get_group_member_attr($object_classes = array(), $default = 'member')
{
if (empty($object_classes)) {
$object_classes = $this->prop['groups']['object_classes'];
}
+
if (!empty($object_classes)) {
foreach ((array)$object_classes as $oc) {
- switch (strtolower($oc)) {
- case 'group':
- case 'groupofnames':
- case 'kolabgroupofnames':
- $member_attr = 'member';
- break;
-
- case 'groupofuniquenames':
- case 'kolabgroupofuniquenames':
- $member_attr = 'uniqueMember';
- break;
+ if ($attr = self::$group_types[strtolower($oc)]) {
+ return $attr;
}
}
}
- if (!empty($member_attr)) {
- return $member_attr;
- }
-
if (!empty($this->prop['groups']['member_attr'])) {
return $this->prop['groups']['member_attr'];
}
- return 'member';
+ return $default;
}
/**
- * Generate BER encoded string for Virtual List View option
- *
- * @param integer List offset (first record)
- * @param integer Records per page
- * @return string BER encoded option value
- */
- 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
- # 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
- # 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
- # leftmost octet should never by set to 1):
- # 8.3.2: If the contents octets of an integer value encoding consist
- # of more than one octet, then the bits of the first octet (rightmost) and bit 8
- # 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
-
- $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;
-
- // now compute length over $str
- $str = self::_ber_addseq($str, 'a0');
- }
-
- // now tack on records per page
- $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');
-
- return pack('H'.strlen($str), $str);
- }
-
-
- /**
- * create ber encoding for sort control
- *
- * @param array List of cols to sort by
- * @return string BER encoded option value
- */
- private function _sort_ber_encode($sortcols)
- {
- $str = '';
- foreach (array_reverse((array)$sortcols) as $col) {
- $ber_val = self::_string2hex($col);
-
- # 30 = ber sequence with a length of octet value
- # 04 = octet string with a length of the ascii value
- $oct = self::_ber_addseq($ber_val, '04');
- $str = self::_ber_addseq($oct, '30') . $str;
- }
-
- // now tack on sequence identifier and length
- $str = self::_ber_addseq($str, '30');
-
- return pack('H'.strlen($str), $str);
- }
-
- /**
- * Add BER sequence with correct length and the given identifier
- */
- private static function _ber_addseq($str, $identifier)
- {
- $len = dechex(strlen($str)/2);
- if (strlen($len) % 2 != 0)
- $len = '0'.$len;
-
- return $identifier . $len . $str;
- }
-
- /**
- * Returns BER encoded integer value in hex format
- */
- private static function _ber_encode_int($offset)
- {
- $val = dechex($offset);
- $prefix = '';
-
- // check if bit 8 of high byte is 1
- if (preg_match('/^[89abcdef]/', $val))
- $prefix = '00';
-
- if (strlen($val)%2 != 0)
- $prefix .= '0';
-
- return $prefix . $val;
- }
-
- /**
- * Returns ascii string encoded in hex
- */
- private static function _string2hex($str)
- {
- $hex = '';
- for ($i=0; $i < strlen($str); $i++)
- $hex .= dechex(ord($str[$i]));
- return $hex;
- }
-
- /**
* HTML-safe DN string encoding
*
* @param string $str DN string
@@ -2243,130 +1949,4 @@ class rcube_ldap extends rcube_addressbook
return base64_decode($str);
}
- /**
- * Wrapper for ldap_add()
- */
- protected function ldap_add($dn, $entry)
- {
- $this->_debug("C: Add [dn: $dn]: ".print_r($entry, true));
-
- $res = ldap_add($this->conn, $dn, $entry);
- if ($res === false) {
- $this->_debug("S: ".ldap_error($this->conn));
- return false;
- }
-
- $this->_debug("S: OK");
- return true;
- }
-
- /**
- * Wrapper for ldap_delete()
- */
- protected function ldap_delete($dn)
- {
- $this->_debug("C: Delete [dn: $dn]");
-
- $res = ldap_delete($this->conn, $dn);
- if ($res === false) {
- $this->_debug("S: ".ldap_error($this->conn));
- return false;
- }
-
- $this->_debug("S: OK");
- return true;
- }
-
- /**
- * Wrapper for ldap_mod_replace()
- */
- protected function ldap_mod_replace($dn, $entry)
- {
- $this->_debug("C: Replace [dn: $dn]: ".print_r($entry, true));
-
- if (!ldap_mod_replace($this->conn, $dn, $entry)) {
- $this->_debug("S: ".ldap_error($this->conn));
- return false;
- }
-
- $this->_debug("S: OK");
- return true;
- }
-
- /**
- * Wrapper for ldap_mod_add()
- */
- protected function ldap_mod_add($dn, $entry)
- {
- $this->_debug("C: Add [dn: $dn]: ".print_r($entry, true));
-
- if (!ldap_mod_add($this->conn, $dn, $entry)) {
- $this->_debug("S: ".ldap_error($this->conn));
- return false;
- }
-
- $this->_debug("S: OK");
- return true;
- }
-
- /**
- * Wrapper for ldap_mod_del()
- */
- protected function ldap_mod_del($dn, $entry)
- {
- $this->_debug("C: Delete [dn: $dn]: ".print_r($entry, true));
-
- if (!ldap_mod_del($this->conn, $dn, $entry)) {
- $this->_debug("S: ".ldap_error($this->conn));
- return false;
- }
-
- $this->_debug("S: OK");
- return true;
- }
-
- /**
- * Wrapper for ldap_rename()
- */
- protected function ldap_rename($dn, $newrdn, $newparent = null, $deleteoldrdn = true)
- {
- $this->_debug("C: Rename [dn: $dn] [dn: $newrdn]");
-
- if (!ldap_rename($this->conn, $dn, $newrdn, $newparent, $deleteoldrdn)) {
- $this->_debug("S: ".ldap_error($this->conn));
- return false;
- }
-
- $this->_debug("S: OK");
- return true;
- }
-
- /**
- * Wrapper for ldap_list()
- */
- protected function ldap_list($dn, $filter, $attrs = array(''))
- {
- $list = array();
- $this->_debug("C: List [dn: $dn] [{$filter}]");
-
- if ($result = ldap_list($this->conn, $dn, $filter, $attrs)) {
- $list = ldap_get_entries($this->conn, $result);
-
- if ($list === false) {
- $this->_debug("S: ".ldap_error($this->conn));
- return array();
- }
-
- $count = $list['count'];
- unset($list['count']);
-
- $this->_debug("S: $count record(s)");
- }
- else {
- $this->_debug("S: ".ldap_error($this->conn));
- }
-
- return $list;
- }
-
}
diff --git a/program/lib/Roundcube/rcube_ldap_generic.php b/program/lib/Roundcube/rcube_ldap_generic.php
new file mode 100644
index 000000000..88378dc22
--- /dev/null
+++ b/program/lib/Roundcube/rcube_ldap_generic.php
@@ -0,0 +1,1049 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | Roundcube/rcube_ldap_generic.php |
+ | |
+ | This file is part of the Roundcube Webmail client |
+ | Copyright (C) 2006-2013, The Roundcube Dev Team |
+ | Copyright (C) 2012-2013, Kolab Systems AG |
+ | |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
+ | |
+ | PURPOSE: |
+ | Provide basic functionality for accessing LDAP directories |
+ | |
+ +-----------------------------------------------------------------------+
+ | Author: Thomas Bruederli <roundcube@gmail.com> |
+ | Aleksander Machniak <machniak@kolabsys.com> |
+ +-----------------------------------------------------------------------+
+*/
+
+
+/*
+ LDAP connection properties
+ --------------------------
+
+ $prop = array(
+ 'host' => '<ldap-server-address>',
+ // or
+ 'hosts' => array('directory.verisign.com'),
+ 'port' => 389,
+ 'use_tls' => true|false,
+ 'ldap_version' => 3, // using LDAPv3
+ 'auth_method' => '', // SASL authentication method (for proxy auth), e.g. DIGEST-MD5
+ 'attributes' => array('dn'), // List of attributes to read from the server
+ 'vlv' => false, // Enable Virtual List View to more efficiently fetch paginated data (if server supports it)
+ 'config_root_dn' => 'cn=config', // Root DN to read config (e.g. vlv indexes) from
+ '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.
+ 'network_timeout' => 10, // The timeout (in seconds) for connect + bind arrempts. This is only supported in PHP >= 5.3.0 with OpenLDAP 2.x
+ 'referrals' => true|false, // Sets the LDAP_OPT_REFERRALS option. Mostly used in multi-domain Active Directory setups
+ );
+*/
+
+/**
+ * Model class to access an LDAP directories
+ *
+ * @package Framework
+ * @subpackage LDAP
+ */
+class rcube_ldap_generic
+{
+ const UPDATE_MOD_ADD = 1;
+ const UPDATE_MOD_DELETE = 2;
+ const UPDATE_MOD_REPLACE = 4;
+ const UPDATE_MOD_FULL = 7;
+
+ public $conn;
+ public $vlv_active = false;
+
+ /** private properties */
+ protected $cache = null;
+ protected $config = array();
+ protected $attributes = array('dn');
+ protected $entries = null;
+ protected $result = null;
+ protected $debug = false;
+ protected $list_page = 1;
+ protected $page_size = 10;
+ protected $vlv_config = null;
+
+
+ /**
+ * Object constructor
+ *
+ * @param array $p LDAP connection properties
+ */
+ function __construct($p)
+ {
+ $this->config = $p;
+
+ if (is_array($p['attributes']))
+ $this->attributes = $p['attributes'];
+
+ if (!is_array($p['hosts']) && !empty($p['host']))
+ $this->config['hosts'] = array($p['host']);
+ }
+
+ /**
+ * Activate/deactivate debug mode
+ *
+ * @param boolean $dbg True if LDAP commands should be logged
+ */
+ public function set_debug($dbg = true)
+ {
+ $this->debug = $dbg;
+ }
+
+ /**
+ * Set connection options
+ *
+ * @param mixed $opt Option name as string or hash array with multiple options
+ * @param mixed $val Option value
+ */
+ public function set_config($opt, $val = null)
+ {
+ if (is_array($opt))
+ $this->config = array_merge($this->config, $opt);
+ else
+ $this->config[$opt] = $value;
+ }
+
+ /**
+ * Enable caching by passing an instance of rcube_cache to be used by this object
+ *
+ * @param object rcube_cache Instance or False to disable caching
+ */
+ public function set_cache($cache_engine)
+ {
+ $this->cache = $cache_engine;
+ }
+
+ /**
+ * Set properties for VLV-based paging
+ *
+ * @param number $page Page number to list (starting at 1)
+ * @param number $size Number of entries to display on one page
+ */
+ public function set_vlv_page($page, $size = 10)
+ {
+ $this->list_page = $page;
+ $this->page_size = $size;
+ }
+
+ /**
+ * Establish a connection to the LDAP server
+ */
+ public function connect($host = null)
+ {
+ if (!function_exists('ldap_connect')) {
+ rcube::raise_error(array('code' => 100, 'type' => 'ldap',
+ 'file' => __FILE__, 'line' => __LINE__,
+ 'message' => "No ldap support in this installation of PHP"),
+ true);
+ return false;
+ }
+
+ if (is_resource($this->conn) && $this->config['host'] == $host)
+ return true;
+
+ if (empty($this->config['ldap_version']))
+ $this->config['ldap_version'] = 3;
+
+ // iterate over hosts if none specified
+ if (!$host) {
+ if (!is_array($this->config['hosts']))
+ $this->config['hosts'] = array($this->config['hosts']);
+
+ foreach ($this->config['hosts'] as $host) {
+ if ($this->connect($host)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ // open connection to the given $host
+ $host = rcube_utils::idn_to_ascii(rcube_utils::parse_host($host));
+ $hostname = $host . ($this->config['port'] ? ':'.$this->config['port'] : '');
+
+ $this->_debug("C: Connect to $hostname [{$this->config['name']}]");
+
+ if ($lc = @ldap_connect($host, $this->config['port'])) {
+ if ($this->config['use_tls'] === true)
+ if (!ldap_start_tls($lc))
+ continue;
+
+ $this->_debug("S: OK");
+
+ ldap_set_option($lc, LDAP_OPT_PROTOCOL_VERSION, $this->config['ldap_version']);
+ $this->config['host'] = $host;
+ $this->conn = $lc;
+
+ if (!empty($this->config['network_timeout']))
+ ldap_set_option($lc, LDAP_OPT_NETWORK_TIMEOUT, $this->config['network_timeout']);
+
+ if (isset($this->config['referrals']))
+ ldap_set_option($lc, LDAP_OPT_REFERRALS, $this->config['referrals']);
+ }
+ else {
+ $this->_debug("S: NOT OK");
+ }
+
+ if (!is_resource($this->conn)) {
+ rcube::raise_error(array('code' => 100, 'type' => 'ldap',
+ 'file' => __FILE__, 'line' => __LINE__,
+ 'message' => "Could not connect to any LDAP server, last tried $hostname"),
+ true);
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Bind connection with (SASL-) user and password
+ *
+ * @param string $authc Authentication user
+ * @param string $pass Bind password
+ * @param string $authz Autorization user
+ *
+ * @return boolean True on success, False on error
+ */
+ public function sasl_bind($authc, $pass, $authz=null)
+ {
+ if (!$this->conn) {
+ return false;
+ }
+
+ if (!function_exists('ldap_sasl_bind')) {
+ rcube::raise_error(array('code' => 100, 'type' => 'ldap',
+ 'file' => __FILE__, 'line' => __LINE__,
+ 'message' => "Unable to bind: ldap_sasl_bind() not exists"),
+ true);
+ return false;
+ }
+
+ if (!empty($authz)) {
+ $authz = 'u:' . $authz;
+ }
+
+ if (!empty($this->config['auth_method'])) {
+ $method = $this->config['auth_method'];
+ }
+ else {
+ $method = 'DIGEST-MD5';
+ }
+
+ $this->_debug("C: SASL Bind [mech: $method, authc: $authc, authz: $authz, pass: $pass]");
+
+ if (ldap_sasl_bind($this->conn, NULL, $pass, $method, NULL, $authc, $authz)) {
+ $this->_debug("S: OK");
+ return true;
+ }
+
+ $this->_debug("S: ".ldap_error($this->conn));
+
+ rcube::raise_error(array(
+ 'code' => ldap_errno($this->conn), 'type' => 'ldap',
+ 'file' => __FILE__, 'line' => __LINE__,
+ 'message' => "SASL Bind failed for authcid=$authc ".ldap_error($this->conn)),
+ true);
+ return false;
+ }
+
+ /**
+ * Bind connection with DN and password
+ *
+ * @param string $dn Bind DN
+ * @param string $pass Bind password
+ *
+ * @return boolean True on success, False on error
+ */
+ public function bind($dn, $pass)
+ {
+ if (!$this->conn) {
+ return false;
+ }
+
+ $this->_debug("C: Bind $dn [pass: $pass]");
+
+ if (@ldap_bind($this->conn, $dn, $pass)) {
+ $this->_debug("S: OK");
+ return true;
+ }
+
+ $this->_debug("S: ".ldap_error($this->conn));
+
+ rcube::raise_error(array(
+ 'code' => ldap_errno($this->conn), 'type' => 'ldap',
+ 'file' => __FILE__, 'line' => __LINE__,
+ 'message' => "Bind failed for dn=$dn: ".ldap_error($this->conn)),
+ true);
+
+ return false;
+ }
+
+ /**
+ * Close connection to LDAP server
+ */
+ public function close()
+ {
+ if ($this->conn) {
+ $this->_debug("C: Close");
+ ldap_unbind($this->conn);
+ $this->conn = null;
+ }
+ }
+
+ /**
+ * Return the last result set
+ *
+ * @return object rcube_ldap_result Result object
+ */
+ function get_result()
+ {
+ return $this->result;
+ }
+
+ /**
+ * Get a specific LDAP entry, identified by its DN
+ *
+ * @param string $dn Record identifier
+ * @return array Hash array
+ */
+ function get_entry($dn)
+ {
+ $rec = null;
+
+ if ($this->conn && $dn) {
+ $this->_debug("C: Read $dn [(objectclass=*)]");
+
+ if ($ldap_result = @ldap_read($this->conn, $dn, '(objectclass=*)', $this->attributes)) {
+ $this->_debug("S: OK");
+
+ if ($entry = ldap_first_entry($this->conn, $ldap_result)) {
+ $rec = ldap_get_attributes($this->conn, $entry);
+ }
+ }
+ else {
+ $this->_debug("S: ".ldap_error($this->conn));
+ }
+
+ if (!empty($rec)) {
+ $rec['dn'] = $dn; // Add in the dn for the entry.
+ }
+ }
+
+ return $rec;
+ }
+
+ /**
+ * Execute the LDAP search based on the stored credentials
+ *
+ * @param string $base_dn The base DN to query
+ * @param string $filter The LDAP filter for search
+ * @param string $scope The LDAP scope (list|sub|base)
+ * @param array $attrs List of entry attributes to read
+ * @param array $prop Hash array with query configuration properties:
+ * - sort: array of sort attributes (has to be in sync with the VLV index)
+ * - search: search string used for VLV controls
+ * @param boolean $count_only Set to true if only entry count is requested
+ *
+ * @return mixed rcube_ldap_result object or number of entries (if count_only=true) or false on error
+ */
+ public function search($base_dn, $filter = '', $scope = 'sub', $attrs = array('dn'), $prop = array(), $count_only = false)
+ {
+ if (!$this->conn) {
+ return false;
+ }
+
+ if (empty($filter)) {
+ $filter = '(objectclass=*)';
+ }
+
+ $this->_debug("C: Search $base_dn for $filter");
+
+ $function = self::scope2func($scope, $ns_function);
+
+ // find available VLV index for this query
+ if (!$count_only && ($vlv_sort = $this->_find_vlv($base_dn, $filter, $scope, $prop['sort']))) {
+ // when using VLV, we get the total count by...
+ // ...either reading numSubOrdinates attribute
+ if (($sub_filter = $this->config['numsub_filter']) &&
+ ($result_count = @$ns_function($this->conn, $base_dn, $sub_filter, array('numSubOrdinates'), 0, 0, 0))
+ ) {
+ $counts = ldap_get_entries($this->conn, $result_count);
+ for ($vlv_count = $j = 0; $j < $counts['count']; $j++)
+ $vlv_count += $counts[$j]['numsubordinates'][0];
+ $this->_debug("D: total numsubordinates = " . $vlv_count);
+ }
+ // ...or by fetching all records dn and count them
+ else if (!function_exists('ldap_parse_virtuallist_control')) {
+ $vlv_count = $this->search($base_dn, $filter, $scope, array('dn'), $prop, true);
+ }
+
+ $this->vlv_active = $this->_vlv_set_controls($vlv_sort, $this->list_page, $this->page_size, $prop['search']);
+ }
+ else {
+ $this->vlv_active = false;
+ }
+
+ // only fetch dn for count (should keep the payload low)
+ if ($ldap_result = @$function($this->conn, $base_dn, $filter,
+ $attrs, 0, (int)$this->config['sizelimit'], (int)$this->config['timelimit'])
+ ) {
+ // when running on a patched PHP we can use the extended functions
+ // to retrieve the total count from the LDAP search result
+ if ($this->vlv_active && function_exists('ldap_parse_virtuallist_control')) {
+ if (ldap_parse_result($this->conn, $ldap_result, $errcode, $matcheddn, $errmsg, $referrals, $serverctrls)) {
+ ldap_parse_virtuallist_control($this->conn, $serverctrls, $last_offset, $vlv_count, $vresult);
+ $this->_debug("S: VLV result: last_offset=$last_offset; content_count=$vlv_count");
+ }
+ else {
+ $this->_debug("S: ".($errmsg ? $errmsg : ldap_error($this->conn)));
+ }
+ }
+ else if ($this->debug) {
+ $this->_debug("S: ".ldap_count_entries($this->conn, $ldap_result)." record(s) found");
+ }
+
+ $this->result = new rcube_ldap_result($this->conn, $ldap_result, $base_dn, $filter, $vlv_count);
+
+ return $count_only ? $this->result->count() : $this->result;
+ }
+ else {
+ $this->_debug("S: ".ldap_error($this->conn));
+ }
+
+ return false;
+ }
+
+ /**
+ * Modify an LDAP entry on the server
+ *
+ * @param string $dn Entry DN
+ * @param array $params Hash array of entry attributes
+ * @param int $mode Update mode (UPDATE_MOD_ADD | UPDATE_MOD_DELETE | UPDATE_MOD_REPLACE)
+ */
+ public function modify($dn, $parms, $mode = 255)
+ {
+ // TODO: implement this
+
+ return false;
+ }
+
+ /**
+ * Wrapper for ldap_add()
+ *
+ * @see ldap_add()
+ */
+ public function add($dn, $entry)
+ {
+ $this->_debug("C: Add $dn: ".print_r($entry, true));
+
+ $res = ldap_add($this->conn, $dn, $entry);
+ if ($res === false) {
+ $this->_debug("S: ".ldap_error($this->conn));
+ return false;
+ }
+
+ $this->_debug("S: OK");
+ return true;
+ }
+
+ /**
+ * Wrapper for ldap_delete()
+ *
+ * @see ldap_delete()
+ */
+ public function delete($dn)
+ {
+ $this->_debug("C: Delete $dn");
+
+ $res = ldap_delete($this->conn, $dn);
+ if ($res === false) {
+ $this->_debug("S: ".ldap_error($this->conn));
+ return false;
+ }
+
+ $this->_debug("S: OK");
+ return true;
+ }
+
+ /**
+ * Wrapper for ldap_mod_replace()
+ *
+ * @see ldap_mod_replace()
+ */
+ public function mod_replace($dn, $entry)
+ {
+ $this->_debug("C: Replace $dn: ".print_r($entry, true));
+
+ if (!ldap_mod_replace($this->conn, $dn, $entry)) {
+ $this->_debug("S: ".ldap_error($this->conn));
+ return false;
+ }
+
+ $this->_debug("S: OK");
+ return true;
+ }
+
+ /**
+ * Wrapper for ldap_mod_add()
+ *
+ * @see ldap_mod_add()
+ */
+ public function mod_add($dn, $entry)
+ {
+ $this->_debug("C: Add $dn: ".print_r($entry, true));
+
+ if (!ldap_mod_add($this->conn, $dn, $entry)) {
+ $this->_debug("S: ".ldap_error($this->conn));
+ return false;
+ }
+
+ $this->_debug("S: OK");
+ return true;
+ }
+
+ /**
+ * Wrapper for ldap_mod_del()
+ *
+ * @see ldap_mod_del()
+ */
+ public function mod_del($dn, $entry)
+ {
+ $this->_debug("C: Delete $dn: ".print_r($entry, true));
+
+ if (!ldap_mod_del($this->conn, $dn, $entry)) {
+ $this->_debug("S: ".ldap_error($this->conn));
+ return false;
+ }
+
+ $this->_debug("S: OK");
+ return true;
+ }
+
+ /**
+ * Wrapper for ldap_rename()
+ *
+ * @see ldap_rename()
+ */
+ public function rename($dn, $newrdn, $newparent = null, $deleteoldrdn = true)
+ {
+ $this->_debug("C: Rename $dn to $newrdn");
+
+ if (!ldap_rename($this->conn, $dn, $newrdn, $newparent, $deleteoldrdn)) {
+ $this->_debug("S: ".ldap_error($this->conn));
+ return false;
+ }
+
+ $this->_debug("S: OK");
+ return true;
+ }
+
+ /**
+ * Wrapper for ldap_list() + ldap_get_entries()
+ *
+ * @see ldap_list()
+ * @see ldap_get_entries()
+ */
+ public function list_entries($dn, $filter, $attributes = array('dn'))
+ {
+ $list = array();
+ $this->_debug("C: List $dn [{$filter}]");
+
+ if ($result = ldap_list($this->conn, $dn, $filter, $attributes)) {
+ $list = ldap_get_entries($this->conn, $result);
+
+ if ($list === false) {
+ $this->_debug("S: ".ldap_error($this->conn));
+ return array();
+ }
+
+ $count = $list['count'];
+ unset($list['count']);
+
+ $this->_debug("S: $count record(s)");
+ }
+ else {
+ $this->_debug("S: ".ldap_error($this->conn));
+ }
+
+ return $list;
+ }
+
+ /**
+ * Wrapper for ldap_read() + ldap_get_entries()
+ *
+ * @see ldap_read()
+ * @see ldap_get_entries()
+ */
+ public function read_entries($dn, $filter, $attributes = null)
+ {
+ $this->_debug("C: Read $dn [{$filter}]");
+
+ if ($this->conn && $dn) {
+ if (!$attributes)
+ $attributes = $this->attributes;
+
+ $result = @ldap_read($this->conn, $dn, $filter, $attributes, 0, (int)$this->config['sizelimit'], (int)$this->config['timelimit']);
+ if ($result === false) {
+ $this->_debug("S: ".ldap_error($this->conn));
+ return false;
+ }
+
+ $this->_debug("S: OK");
+ return ldap_get_entries($this->conn, $result);
+ }
+
+ return false;
+ }
+
+ /**
+ * Choose the right PHP function according to scope property
+ *
+ * @param string $scope The LDAP scope (sub|base|list)
+ * @param string $ns_function Function to be used for numSubOrdinates queries
+ * @return string PHP function to be used to query directory
+ */
+ public static 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;
+ }
+
+ /**
+ * Convert the given scope integer value to a string representation
+ */
+ public static function scopeint2str($scope)
+ {
+ switch ($scope) {
+ case 2: return 'sub';
+ case 1: return 'one';
+ case 0: return 'base';
+ default: $this->_debug("Scope $scope is not a valid scope integer");
+ }
+
+ return '';
+ }
+
+ /**
+ * Escapes the given value according to RFC 2254 so that it can be safely used in LDAP filters.
+ *
+ * @param string $val Value to quote
+ * @return string The escaped value
+ */
+ public static function escape_value($val)
+ {
+ return strtr($str, array('*'=>'\2a', '('=>'\28', ')'=>'\29',
+ '\\'=>'\5c', '/'=>'\2f'));
+ }
+
+ /**
+ * Escapes a DN value according to RFC 2253
+ *
+ * @param string $dn DN value o quote
+ * @return string The escaped value
+ */
+ public static function escape_dn($dn)
+ {
+ return strtr($str, array(','=>'\2c', '='=>'\3d', '+'=>'\2b',
+ '<'=>'\3c', '>'=>'\3e', ';'=>'\3b', '\\'=>'\5c',
+ '"'=>'\22', '#'=>'\23'));
+ }
+
+ /**
+ * Normalize a LDAP result by converting entry attributes arrays into single values
+ *
+ * @param array $result LDAP result set fetched with ldap_get_entries()
+ * @return array Hash array with normalized entries, indexed by their DNs
+ */
+ public static function normalize_result($result)
+ {
+ if (!is_array($result)) {
+ return array();
+ }
+
+ $entries = array();
+ for ($i = 0; $i < $result['count']; $i++) {
+ $key = $result[$i]['dn'] ? $result[$i]['dn'] : $i;
+ $entries[$key] = self::normalize_entry($result[$i]);
+ }
+
+ return $entries;
+ }
+
+ /**
+ * Turn an LDAP entry into a regular PHP array with attributes as keys.
+ *
+ * @param array $entry Attributes array as retrieved from ldap_get_attributes() or ldap_get_entries()
+ * @return array Hash array with attributes as keys
+ */
+ public static function normalize_entry($entry)
+ {
+ $rec = array();
+ for ($i=0; $i < $entry['count']; $i++) {
+ $attr = $entry[$i];
+ if ($entry[$attr]['count'] == 1) {
+ switch ($attr) {
+ case 'objectclass':
+ $rec[$attr] = array(strtolower($entry[$attr][0]));
+ break;
+ default:
+ $rec[$attr] = $entry[$attr][0];
+ break;
+ }
+ }
+ else {
+ for ($j=0; $j < $entry[$attr]['count']; $j++) {
+ $rec[$attr][$j] = $entry[$attr][$j];
+ }
+ }
+ }
+
+ return $rec;
+ }
+
+ /**
+ * Set server controls for Virtual List View (paginated listing)
+ */
+ private function _vlv_set_controls($sort, $list_page, $page_size, $search = null)
+ {
+ $sort_ctrl = array('oid' => "1.2.840.113556.1.4.473", 'value' => self::_sort_ber_encode((array)$sort));
+ $vlv_ctrl = array('oid' => "2.16.840.1.113730.3.4.9", 'value' => self::_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'])) . " ($sort[0]);"
+ . " vlv=" . join(' ', (unpack('H'.(strlen($vlv_ctrl['value'])*2), $vlv_ctrl['value']))) . " ($offset/$page_size; $search)");
+
+ if (!ldap_set_option($this->conn, LDAP_OPT_SERVER_CONTROLS, array($sort_ctrl, $vlv_ctrl))) {
+ $this->_debug("S: ".ldap_error($this->conn));
+ $this->set_error(self::ERROR_SEARCH, 'vlvnotsupported');
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns unified attribute name (resolving aliases)
+ */
+ private static function _attr_name($namev)
+ {
+ // list of known attribute aliases
+ static $aliases = array(
+ 'gn' => 'givenname',
+ 'rfc822mailbox' => 'email',
+ 'userid' => 'uid',
+ 'emailaddress' => 'email',
+ 'pkcs9email' => 'email',
+ );
+
+ list($name, $limit) = explode(':', $namev, 2);
+ $suffix = $limit ? ':'.$limit : '';
+
+ return (isset($aliases[$name]) ? $aliases[$name] : $name) . $suffix;
+ }
+
+ /**
+ * Quotes attribute value string
+ *
+ * @param string $str Attribute value
+ * @param bool $dn True if the attribute is a DN
+ *
+ * @return string Quoted string
+ */
+ public static function quote_string($str, $dn=false)
+ {
+ // take firt entry if array given
+ if (is_array($str))
+ $str = reset($str);
+
+ if ($dn)
+ $replace = array(','=>'\2c', '='=>'\3d', '+'=>'\2b', '<'=>'\3c',
+ '>'=>'\3e', ';'=>'\3b', '\\'=>'\5c', '"'=>'\22', '#'=>'\23');
+ else
+ $replace = array('*'=>'\2a', '('=>'\28', ')'=>'\29', '\\'=>'\5c',
+ '/'=>'\2f');
+
+ return strtr($str, $replace);
+ }
+
+ /**
+ * Prints debug info to the log
+ */
+ private function _debug($str)
+ {
+ if ($this->debug && class_exists('rcube')) {
+ rcube::write_log('ldap', $str);
+ }
+ }
+
+
+ /***************** Virtual List View (VLV) related utility functions **************** */
+
+ /**
+ * Return the search string value to be used in VLV controls
+ */
+ private function _vlv_search($sort, $search)
+ {
+ foreach ($search as $attr => $value) {
+ if (!in_array(strtolower($attr), $sort)) {
+ $this->_debug("d: Cannot use VLV search using attribute not indexed: $attr (not in " . var_export($sort, true) . ")");
+ return null;
+ } else {
+ return $value;
+ }
+ }
+ }
+
+ /**
+ * Find a VLV index matching the given query attributes
+ *
+ * @return string Sort attribute or False if no match
+ */
+ private function _find_vlv($base_dn, $filter, $scope, $sort_attrs = null)
+ {
+ if (!$this->config['vlv'] || $scope == 'base') {
+ return false;
+ }
+
+ // get vlv config
+ $vlv_config = $this->_read_vlv_config();
+
+ if ($vlv = $vlv_config[$base_dn]) {
+ $this->_debug("D: Found a VLV for $base_dn");
+
+ if ($vlv['filter'] == strtolower($filter) || stripos($filter, '(&'.$vlv['filter'].'(') === 0) {
+ $this->_debug("D: Filter matches");
+ if ($vlv['scope'] == $scope) {
+ // Not passing any sort attributes means you don't care
+ if (empty($sort_attrs) || in_array($sort_attrs, $vlv['sort'])) {
+ return $vlv['sort'][0];
+ }
+ }
+ else {
+ $this->_debug("D: Scope does not match");
+ }
+ }
+ else {
+ $this->_debug("D: Filter does not match");
+ }
+ }
+ else {
+ $this->_debug("D: No VLV for $base_dn");
+ }
+
+ return false;
+ }
+
+ /**
+ * Return VLV indexes and searches including necessary configuration
+ * details.
+ */
+ private function _read_vlv_config()
+ {
+ if (empty($this->config['vlv']) || empty($this->config['config_root_dn'])) {
+ return array();
+ }
+ // return hard-coded VLV config
+ else if (is_array($this->config['vlv'])) {
+ return $this->config['vlv'];
+ }
+
+ // return cached result
+ if (is_array($this->vlv_config)) {
+ return $this->vlv_config;
+ }
+
+ if ($this->cache && ($cached_config = $this->cache->get('vlvconfig'))) {
+ $this->vlv_config = $cached_config;
+ return $this->vlv_config;
+ }
+
+ $this->vlv_config = array();
+
+ $ldap_result = ldap_search($this->conn, $this->config['config_root_dn'], '(objectclass=vlvsearch)', array('*'), 0, 0, 0);
+ $vlv_searches = new rcube_ldap_result($this->conn, $ldap_result, $this->config['config_root_dn'], '(objectclass=vlvsearch)');
+
+ if ($vlv_searches->count() < 1) {
+ $this->_debug("D: Empty result from search for '(objectclass=vlvsearch)' on '$config_root_dn'");
+ return array();
+ }
+
+ foreach ($vlv_searches->entries(true) as $vlv_search_dn => $vlv_search_attrs) {
+ // Multiple indexes may exist
+ $ldap_result = ldap_search($this->conn, $vlv_search_dn, '(objectclass=vlvindex)', array('*'), 0, 0, 0);
+ $vlv_indexes = new rcube_ldap_result($this->conn, $ldap_result, $vlv_search_dn, '(objectclass=vlvindex)');
+
+ // Reset this one for each VLV search.
+ $_vlv_sort = array();
+ foreach ($vlv_indexes->entries(true) as $vlv_index_dn => $vlv_index_attrs) {
+ $_vlv_sort[] = explode(' ', $vlv_index_attrs['vlvsort']);
+ }
+
+ $this->vlv_config[$vlv_search_attrs['vlvbase']] = array(
+ 'scope' => self::scopeint2str($vlv_search_attrs['vlvscope']),
+ 'filter' => strtolower($vlv_search_attrs['vlvfilter']),
+ 'sort' => $_vlv_sort,
+ );
+ }
+
+ // cache this
+ if ($this->cache)
+ $this->cache->set('vlvconfig', $this->vlv_config);
+
+ $this->_debug("D: Refreshed VLV config: " . var_export($this->vlv_config, true));
+
+ return $this->vlv_config;
+ }
+
+ /**
+ * Generate BER encoded string for Virtual List View option
+ *
+ * @param integer List offset (first record)
+ * @param integer Records per page
+ *
+ * @return string BER encoded option value
+ */
+ private static 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
+ 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
+ 02 = type integer with 2 bytes following (offset): 01 01 (ie 1)
+ 02 = type integer with 2 bytes following (contentCount): 01 00
+
+ with 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
+ leftmost octet should never by set to 1):
+ 8.3.2: If the contents octets of an integer value encoding consist
+ of more than one octet, then the bits of the first octet (rightmost)
+ and bit 8 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
+
+ $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;
+
+ // now compute length over $str
+ $str = self::_ber_addseq($str, 'a0');
+ }
+
+ // now tack on records per page
+ $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');
+
+ return pack('H'.strlen($str), $str);
+ }
+
+ /**
+ * create ber encoding for sort control
+ *
+ * @param array List of cols to sort by
+ * @return string BER encoded option value
+ */
+ private static function _sort_ber_encode($sortcols)
+ {
+ $str = '';
+ foreach (array_reverse((array)$sortcols) as $col) {
+ $ber_val = self::_string2hex($col);
+
+ // 30 = ber sequence with a length of octet value
+ // 04 = octet string with a length of the ascii value
+ $oct = self::_ber_addseq($ber_val, '04');
+ $str = self::_ber_addseq($oct, '30') . $str;
+ }
+
+ // now tack on sequence identifier and length
+ $str = self::_ber_addseq($str, '30');
+
+ return pack('H'.strlen($str), $str);
+ }
+
+ /**
+ * Add BER sequence with correct length and the given identifier
+ */
+ private static function _ber_addseq($str, $identifier)
+ {
+ $len = dechex(strlen($str)/2);
+ if (strlen($len) % 2 != 0)
+ $len = '0'.$len;
+
+ return $identifier . $len . $str;
+ }
+
+ /**
+ * Returns BER encoded integer value in hex format
+ */
+ private static function _ber_encode_int($offset)
+ {
+ $val = dechex($offset);
+ $prefix = '';
+
+ // check if bit 8 of high byte is 1
+ if (preg_match('/^[89abcdef]/', $val))
+ $prefix = '00';
+
+ if (strlen($val)%2 != 0)
+ $prefix .= '0';
+
+ return $prefix . $val;
+ }
+
+ /**
+ * Returns ascii string encoded in hex
+ */
+ private static function _string2hex($str)
+ {
+ $hex = '';
+ for ($i=0; $i < strlen($str); $i++) {
+ $hex .= dechex(ord($str[$i]));
+ }
+ return $hex;
+ }
+
+}
diff --git a/program/lib/Roundcube/rcube_ldap_result.php b/program/lib/Roundcube/rcube_ldap_result.php
new file mode 100644
index 000000000..efc3331bc
--- /dev/null
+++ b/program/lib/Roundcube/rcube_ldap_result.php
@@ -0,0 +1,130 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | Roundcube/rcube_ldap_result.php |
+ | |
+ | This file is part of the Roundcube Webmail client |
+ | Copyright (C) 2006-2013, The Roundcube Dev Team |
+ | Copyright (C) 2013, Kolab Systems AG |
+ | |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
+ | |
+ | PURPOSE: |
+ | Model class that represents an LDAP search result |
+ | |
+ +-----------------------------------------------------------------------+
+ | Author: Thomas Bruederli <roundcube@gmail.com> |
+ +-----------------------------------------------------------------------+
+*/
+
+
+/**
+ * Model class representing an LDAP search result
+ *
+ * @package Framework
+ * @subpackage LDAP
+ */
+class rcube_ldap_result implements Iterator
+{
+ public $conn;
+ public $ldap;
+ public $base_dn;
+ public $filter;
+
+ private $count = null;
+ private $current = null;
+ private $iteratorkey = 0;
+
+ /**
+ * Default constructor
+ *
+ * @param resource $conn LDAP link identifier
+ * @param resource $ldap LDAP result entry identifier
+ * @param string $base_dn Base DN used to get this result
+ * @param string $filter Filter query used to get this result
+ * @param integer $count Record count value (pre-calculated)
+ */
+ function __construct($conn, $ldap, $base_dn, $filter, $count = null)
+ {
+ $this->conn = $conn;
+ $this->ldap = $ldap;
+ $this->base_dn = $base_dn;
+ $this->filter = $filter;
+ $this->count = $count;
+ }
+
+ /**
+ * Wrapper for ldap_sort()
+ */
+ public function sort($attr)
+ {
+ return ldap_sort($this->conn, $this->ldap, $attr);
+ }
+
+ /**
+ * Get entries count
+ */
+ public function count()
+ {
+ if (!isset($this->count))
+ $this->count = ldap_count_entries($this->conn, $this->ldap);
+
+ return $this->count;
+ }
+
+ /**
+ * Wrapper for ldap_get_entries()
+ *
+ * @param boolean $normalize Optionally normalize the entries to a list of hash arrays
+ * @return array List of LDAP entries
+ */
+ public function entries($normalize = false)
+ {
+ $entries = ldap_get_entries($this->conn, $this->ldap);
+ return $normalize ? rcube_ldap_generic::normalize_result($entries) : $entries;
+ }
+
+ /**
+ * Wrapper for ldap_get_dn() using the current entry pointer
+ */
+ public function get_dn()
+ {
+ return $this->current ? ldap_get_dn($this->conn, $this->current) : null;
+ }
+
+
+ /*** Implements the PHP 5 Iterator interface to make foreach work ***/
+
+ function current()
+ {
+ $attrib = ldap_get_attributes($this->conn, $this->current);
+ $attrib['dn'] = ldap_get_dn($this->conn, $this->current);
+ return $attrib;
+ }
+
+ function key()
+ {
+ return $this->iteratorkey;
+ }
+
+ function rewind()
+ {
+ $this->iteratorkey = 0;
+ $this->current = ldap_first_entry($this->conn, $this->ldap);
+ }
+
+ function next()
+ {
+ $this->iteratorkey++;
+ $this->current = ldap_next_entry($this->conn, $this->current);
+ }
+
+ function valid()
+ {
+ return (bool)$this->current;
+ }
+
+}
diff --git a/program/lib/Roundcube/rcube_mime.php b/program/lib/Roundcube/rcube_mime.php
index 5258af5bf..572540f47 100644
--- a/program/lib/Roundcube/rcube_mime.php
+++ b/program/lib/Roundcube/rcube_mime.php
@@ -587,23 +587,20 @@ class rcube_mime
*/
public static function wordwrap($string, $width=75, $break="\n", $cut=false, $charset=null, $wrap_quoted=true)
{
- if (!$charset) {
- $charset = RCUBE_CHARSET;
- }
+ // Note: Never try to use iconv instead of mbstring functions here
+ // Iconv's substr/strlen are 100x slower (#1489113)
- // detect available functions
- $strlen_func = function_exists('iconv_strlen') ? 'iconv_strlen' : 'mb_strlen';
- $strpos_func = function_exists('iconv_strpos') ? 'iconv_strpos' : 'mb_strpos';
- $strrpos_func = function_exists('iconv_strrpos') ? 'iconv_strrpos' : 'mb_strrpos';
- $substr_func = function_exists('iconv_substr') ? 'iconv_substr' : 'mb_substr';
+ if ($charset && $charset != RCUBE_CHARSET && function_exists('mb_internal_encoding')) {
+ mb_internal_encoding($charset);
+ }
// Convert \r\n to \n, this is our line-separator
$string = str_replace("\r\n", "\n", $string);
$separator = "\n"; // must be 1 character length
$result = array();
- while (($stringLength = $strlen_func($string, $charset)) > 0) {
- $breakPos = $strpos_func($string, $separator, 0, $charset);
+ while (($stringLength = mb_strlen($string)) > 0) {
+ $breakPos = mb_strpos($string, $separator, 0);
// quoted line (do not wrap)
if ($wrap_quoted && $string[0] == '>') {
@@ -612,7 +609,7 @@ class rcube_mime
$cutLength = null;
}
else {
- $subString = $substr_func($string, 0, $breakPos, $charset);
+ $subString = mb_substr($string, 0, $breakPos);
$cutLength = $breakPos + 1;
}
}
@@ -623,39 +620,34 @@ class rcube_mime
$cutLength = null;
}
else {
- $subString = $substr_func($string, 0, $breakPos, $charset);
+ $subString = mb_substr($string, 0, $breakPos);
$cutLength = $breakPos + 1;
}
}
else {
- $subString = $substr_func($string, 0, $width, $charset);
+ $subString = mb_substr($string, 0, $width);
// last line
if ($breakPos === false && $subString === $string) {
$cutLength = null;
}
else {
- $nextChar = $substr_func($string, $width, 1, $charset);
+ $nextChar = mb_substr($string, $width, 1);
if ($nextChar === ' ' || $nextChar === $separator) {
- $afterNextChar = $substr_func($string, $width + 1, 1, $charset);
+ $afterNextChar = mb_substr($string, $width + 1, 1);
if ($afterNextChar === false) {
$subString .= $nextChar;
}
- $cutLength = $strlen_func($subString, $charset) + 1;
+ $cutLength = mb_strlen($subString) + 1;
}
else {
- if ($strrpos_func[0] == 'm') {
- $spacePos = $strrpos_func($subString, ' ', 0, $charset);
- }
- else {
- $spacePos = $strrpos_func($subString, ' ', $charset);
- }
+ $spacePos = mb_strrpos($subString, ' ', 0);
if ($spacePos !== false) {
- $subString = $substr_func($subString, 0, $spacePos, $charset);
+ $subString = mb_substr($subString, 0, $spacePos);
$cutLength = $spacePos + 1;
}
else if ($cut === false && $breakPos === false) {
@@ -663,19 +655,19 @@ class rcube_mime
$cutLength = null;
}
else if ($cut === false) {
- $spacePos = $strpos_func($string, ' ', 0, $charset);
+ $spacePos = mb_strpos($string, ' ', 0);
if ($spacePos !== false && $spacePos < $breakPos) {
- $subString = $substr_func($string, 0, $spacePos, $charset);
+ $subString = mb_substr($string, 0, $spacePos);
$cutLength = $spacePos + 1;
}
else {
- $subString = $substr_func($string, 0, $breakPos, $charset);
+ $subString = mb_substr($string, 0, $breakPos);
$cutLength = $breakPos + 1;
}
}
else {
- $subString = $substr_func($subString, 0, $width, $charset);
+ $subString = mb_substr($subString, 0, $width);
$cutLength = $width;
}
}
@@ -685,13 +677,17 @@ class rcube_mime
$result[] = $subString;
if ($cutLength !== null) {
- $string = $substr_func($string, $cutLength, ($stringLength - $cutLength), $charset);
+ $string = mb_substr($string, $cutLength, ($stringLength - $cutLength));
}
else {
break;
}
}
+ if ($charset && $charset != RCUBE_CHARSET && function_exists('mb_internal_encoding')) {
+ mb_internal_encoding(RCUBE_CHARSET);
+ }
+
return implode($break, $result);
}
diff --git a/program/lib/Roundcube/rcube_session.php b/program/lib/Roundcube/rcube_session.php
index dedde2284..646933b71 100644
--- a/program/lib/Roundcube/rcube_session.php
+++ b/program/lib/Roundcube/rcube_session.php
@@ -32,6 +32,7 @@ class rcube_session
private $ip;
private $start;
private $changed;
+ private $time_diff = 0;
private $reloaded = false;
private $unsets = array();
private $gc_handlers = array();
@@ -42,6 +43,7 @@ class rcube_session
private $secret = '';
private $ip_check = false;
private $logging = false;
+ private $storage;
private $memcache;
@@ -52,18 +54,21 @@ class rcube_session
{
$this->db = $db;
$this->start = microtime(true);
- $this->ip = $_SERVER['REMOTE_ADDR'];
+ $this->ip = rcube_utils::remote_addr();
$this->logging = $config->get('log_session', false);
$lifetime = $config->get('session_lifetime', 1) * 60;
$this->set_lifetime($lifetime);
// use memcache backend
- if ($config->get('session_storage', 'db') == 'memcache') {
+ $this->storage = $config->get('session_storage', 'db');
+ if ($this->storage == 'memcache') {
$this->memcache = rcube::get_instance()->get_memcache();
// set custom functions for PHP session management if memcache is available
if ($this->memcache) {
+ ini_set('session.serialize_handler', 'php');
+
session_set_save_handler(
array($this, 'open'),
array($this, 'close'),
@@ -79,7 +84,9 @@ class rcube_session
true, true);
}
}
- else {
+ else if ($this->storage != 'php') {
+ ini_set('session.serialize_handler', 'php');
+
// set custom functions for PHP session management
session_set_save_handler(
array($this, 'open'),
@@ -87,7 +94,23 @@ class rcube_session
array($this, 'db_read'),
array($this, 'db_write'),
array($this, 'db_destroy'),
- array($this, 'db_gc'));
+ array($this, 'gc'));
+ }
+ }
+
+
+ /**
+ * Wrapper for session_start()
+ */
+ public function start()
+ {
+ session_start();
+
+ // copy some session properties to object vars
+ if ($this->storage == 'php') {
+ $this->key = session_id();
+ $this->ip = $_SESSION['__IP'];
+ $this->changed = $_SESSION['__MTIME'];
}
}
@@ -116,6 +139,25 @@ class rcube_session
/**
+ * Wrapper for session_write_close()
+ */
+ public function write_close()
+ {
+ if ($this->storage == 'php') {
+ $_SESSION['__IP'] = $this->ip;
+ $_SESSION['__MTIME'] = time();
+ }
+
+ session_write_close();
+
+ // write_close() is called on script shutdown, see rcube::shutdown()
+ // execute cleanup functionality if enabled by session gc handler
+ // we do this after closing the session for better performance
+ $this->gc_shutdown();
+ }
+
+
+ /**
* Read session data from database
*
* @param string Session ID
@@ -125,14 +167,16 @@ class rcube_session
public function db_read($key)
{
$sql_result = $this->db->query(
- "SELECT vars, ip, changed FROM ".$this->db->table_name('session')
- ." WHERE sess_id = ?", $key);
+ "SELECT vars, ip, changed, " . $this->db->now() . " AS ts"
+ . " FROM " . $this->db->table_name('session')
+ . " WHERE sess_id = ?", $key);
if ($sql_result && ($sql_arr = $this->db->fetch_assoc($sql_result))) {
- $this->changed = strtotime($sql_arr['changed']);
- $this->ip = $sql_arr['ip'];
- $this->vars = base64_decode($sql_arr['vars']);
- $this->key = $key;
+ $this->time_diff = time() - strtotime($sql_arr['ts']);
+ $this->changed = strtotime($sql_arr['changed']);
+ $this->ip = $sql_arr['ip'];
+ $this->vars = base64_decode($sql_arr['vars']);
+ $this->key = $key;
return !empty($this->vars) ? (string) $this->vars : '';
}
@@ -152,8 +196,9 @@ class rcube_session
*/
public function db_write($key, $vars)
{
- $ts = microtime(true);
- $now = $this->db->fromunixtime((int)$ts);
+ $now = $this->db->now();
+ $table = $this->db->table_name('session');
+ $ts = microtime(true);
// no session row in DB (db_read() returns false)
if (!$this->key) {
@@ -171,22 +216,19 @@ class rcube_session
$newvars = $this->_fixvars($vars, $oldvars);
if ($newvars !== $oldvars) {
- $this->db->query(
- sprintf("UPDATE %s SET vars=?, changed=%s WHERE sess_id=?",
- $this->db->table_name('session'), $now),
- base64_encode($newvars), $key);
+ $this->db->query("UPDATE $table "
+ . "SET changed = $now, vars = ? WHERE sess_id = ?",
+ base64_encode($newvars), $key);
}
- else if ($ts - $this->changed > $this->lifetime / 2) {
- $this->db->query("UPDATE ".$this->db->table_name('session')
- ." SET changed=$now WHERE sess_id=?", $key);
+ else if ($ts - $this->changed + $this->time_diff > $this->lifetime / 2) {
+ $this->db->query("UPDATE $table SET changed = $now"
+ . " WHERE sess_id = ?", $key);
}
}
else {
- $this->db->query(
- sprintf("INSERT INTO %s (sess_id, vars, ip, created, changed) ".
- "VALUES (?, ?, ?, %s, %s)",
- $this->db->table_name('session'), $now, $now),
- $key, base64_encode($vars), (string)$this->ip);
+ $this->db->query("INSERT INTO $table (sess_id, vars, ip, created, changed)"
+ . " VALUES (?, ?, ?, $now, $now)",
+ $key, base64_encode($vars), (string)$this->ip);
}
return true;
@@ -246,25 +288,6 @@ class rcube_session
/**
- * Garbage collecting function
- *
- * @param string Session lifetime in seconds
- * @return boolean True on success
- */
- public function db_gc($maxlifetime)
- {
- // just delete all expired sessions
- $this->db->query(
- sprintf("DELETE FROM %s WHERE changed < %s",
- $this->db->table_name('session'), $this->db->fromunixtime(time() - $maxlifetime)));
-
- $this->gc();
-
- return true;
- }
-
-
- /**
* Read session data from memcache
*
* @param string Session ID
@@ -340,11 +363,11 @@ class rcube_session
/**
* Execute registered garbage collector routines
*/
- public function gc()
+ public function gc($maxlifetime)
{
- foreach ($this->gc_handlers as $fct) {
- call_user_func($fct);
- }
+ // move gc execution to the script shutdown function
+ // see rcube::shutdown() and rcube_session::write_close()
+ return $this->gc_enabled = $maxlifetime;
}
@@ -366,6 +389,25 @@ class rcube_session
/**
+ * Garbage collector handler to run on script shutdown
+ */
+ protected function gc_shutdown()
+ {
+ if ($this->gc_enabled) {
+ // just delete all expired sessions
+ if ($this->storage == 'db') {
+ $this->db->query("DELETE FROM " . $this->db->table_name('session')
+ . " WHERE changed < " . $this->db->now(-$this->gc_enabled));
+ }
+
+ foreach ($this->gc_handlers as $fct) {
+ call_user_func($fct);
+ }
+ }
+ }
+
+
+ /**
* Generate and set new session id
*
* @param boolean $destroy If enabled the current session will be destroyed
@@ -438,7 +480,7 @@ class rcube_session
public function kill()
{
$this->vars = null;
- $this->ip = $_SERVER['REMOTE_ADDR']; // update IP (might have changed)
+ $this->ip = rcube_utils::remote_addr(); // update IP (might have changed)
$this->destroy(session_id());
rcube_utils::setcookie($this->cookiename, '-del-', time() - 60);
}
@@ -652,10 +694,10 @@ class rcube_session
function check_auth()
{
$this->cookie = $_COOKIE[$this->cookiename];
- $result = $this->ip_check ? $_SERVER['REMOTE_ADDR'] == $this->ip : true;
+ $result = $this->ip_check ? rcube_utils::remote_addr() == $this->ip : true;
if (!$result) {
- $this->log("IP check failed for " . $this->key . "; expected " . $this->ip . "; got " . $_SERVER['REMOTE_ADDR']);
+ $this->log("IP check failed for " . $this->key . "; expected " . $this->ip . "; got " . rcube_utils::remote_addr());
}
if ($result && $this->_mkcookie($this->now) != $this->cookie) {
diff --git a/program/lib/Roundcube/rcube_spellchecker.php b/program/lib/Roundcube/rcube_spellchecker.php
index 60aec500f..df4365223 100644
--- a/program/lib/Roundcube/rcube_spellchecker.php
+++ b/program/lib/Roundcube/rcube_spellchecker.php
@@ -84,6 +84,9 @@ class rcube_spellchecker
if ($this->engine == 'pspell') {
$this->matches = $this->_pspell_check($this->content);
}
+ else if ($this->engine == 'enchant') {
+ $this->matches = $this->_enchant_check($this->content);
+ }
else {
$this->matches = $this->_googie_check($this->content);
}
@@ -115,6 +118,9 @@ class rcube_spellchecker
if ($this->engine == 'pspell') {
return $this->_pspell_suggestions($word);
}
+ else if ($this->engine == 'enchant') {
+ return $this->_enchant_suggestions($word);
+ }
return $this->_googie_suggestions($word);
}
@@ -133,6 +139,9 @@ class rcube_spellchecker
if ($this->engine == 'pspell') {
return $this->_pspell_words($text, $is_html);
}
+ else if ($this->engine == 'enchant') {
+ return $this->_enchant_words($text, $is_html);
+ }
return $this->_googie_words($text, $is_html);
}
@@ -326,6 +335,141 @@ class rcube_spellchecker
}
+ /**
+ * Checks the text using enchant
+ *
+ * @param string $text Text content for spellchecking
+ */
+ private function _enchant_check($text)
+ {
+ // init spellchecker
+ $this->_enchant_init();
+
+ if (!$this->enchant_dictionary) {
+ return array();
+ }
+
+ // tokenize
+ $text = preg_split($this->separator, $text, NULL, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE);
+
+ $diff = 0;
+ $matches = array();
+
+ foreach ($text as $w) {
+ $word = trim($w[0]);
+ $pos = $w[1] - $diff;
+ $len = mb_strlen($word);
+
+ // skip exceptions
+ if ($this->is_exception($word)) {
+ }
+ else if (!enchant_dict_check($this->enchant_dictionary, $word)) {
+ $suggestions = enchant_dict_suggest($this->enchant_dictionary, $word);
+
+ if (sizeof($suggestions) > self::MAX_SUGGESTIONS) {
+ $suggestions = array_slice($suggestions, 0, self::MAX_SUGGESTIONS);
+ }
+
+ $matches[] = array($word, $pos, $len, null, $suggestions);
+ }
+
+ $diff += (strlen($word) - $len);
+ }
+
+ return $matches;
+ }
+
+
+ /**
+ * Returns the misspelled words
+ */
+ private function _enchant_words($text = null, $is_html=false)
+ {
+ $result = array();
+
+ if ($text) {
+ // init spellchecker
+ $this->_enchant_init();
+
+ if (!$this->enchant_dictionary) {
+ return array();
+ }
+
+ // With Enchant we don't need to get suggestions to return misspelled words
+ if ($is_html) {
+ $text = $this->html2text($text);
+ }
+
+ $text = preg_split($this->separator, $text, NULL, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE);
+
+ foreach ($text as $w) {
+ $word = trim($w[0]);
+
+ // skip exceptions
+ if ($this->is_exception($word)) {
+ continue;
+ }
+
+ if (!enchant_dict_check($this->enchant_dictionary, $word)) {
+ $result[] = $word;
+ }
+ }
+
+ return $result;
+ }
+
+ foreach ($this->matches as $m) {
+ $result[] = $m[0];
+ }
+
+ return $result;
+ }
+
+
+ /**
+ * Returns suggestions for misspelled word
+ */
+ private function _enchant_suggestions($word)
+ {
+ // init spellchecker
+ $this->_enchant_init();
+
+ if (!$this->enchant_dictionary) {
+ return array();
+ }
+
+ $suggestions = enchant_dict_suggest($this->enchant_dictionary, $word);
+
+ if (sizeof($suggestions) > self::MAX_SUGGESTIONS)
+ $suggestions = array_slice($suggestions, 0, self::MAX_SUGGESTIONS);
+
+ return is_array($suggestions) ? $suggestions : array();
+ }
+
+
+ /**
+ * Initializes PSpell dictionary
+ */
+ private function _enchant_init()
+ {
+ if (!$this->enchant_broker) {
+ if (!extension_loaded('enchant')) {
+ $this->error = "Enchant extension not available";
+ return;
+ }
+
+ $this->enchant_broker = enchant_broker_init();
+ }
+
+ if (!enchant_broker_dict_exists($this->enchant_broker, $this->lang)) {
+ $this->error = "Unable to load dictionary for selected language using Enchant";
+ return;
+ }
+
+ $this->enchant_dictionary = enchant_broker_request_dict($this->enchant_broker, $this->lang);
+ }
+
+
private function _googie_check($text)
{
// spell check uri is configured
@@ -377,7 +521,7 @@ class rcube_spellchecker
if (!$store) {
$this->error = "Empty result from spelling engine";
}
- else if (preg_match('/<spellresult error="([^"]+)"/', $store, $m)) {
+ else if (preg_match('/<spellresult error="([^"]+)"/', $store, $m) && $m[1]) {
$this->error = "Error code $m[1] returned";
}
diff --git a/program/lib/Roundcube/rcube_storage.php b/program/lib/Roundcube/rcube_storage.php
index 700d12ffb..4b336f210 100644
--- a/program/lib/Roundcube/rcube_storage.php
+++ b/program/lib/Roundcube/rcube_storage.php
@@ -540,12 +540,13 @@ abstract class rcube_storage
/**
* Append a mail message (source) to a specific folder.
*
- * @param string $folder Target folder
- * @param string $message The message source string or filename
- * @param string $headers Headers string if $message contains only the body
- * @param boolean $is_file True if $message is a filename
- * @param array $flags Message flags
- * @param mixed $date Message internal date
+ * @param string $folder Target folder
+ * @param string|array $message The message source string or filename
+ * or array (of strings and file pointers)
+ * @param string $headers Headers string if $message contains only the body
+ * @param boolean $is_file True if $message is a filename
+ * @param array $flags Message flags
+ * @param mixed $date Message internal date
*
* @return int|bool Appended message UID or True on success, False on error
*/
@@ -986,6 +987,6 @@ abstract class rcube_storage
/**
* Delete outdated cache entries
*/
- abstract function expunge_cache();
+ abstract function cache_gc();
} // end class rcube_storage
diff --git a/program/lib/Roundcube/rcube_user.php b/program/lib/Roundcube/rcube_user.php
index 505b190d1..5e9c9af80 100644
--- a/program/lib/Roundcube/rcube_user.php
+++ b/program/lib/Roundcube/rcube_user.php
@@ -495,9 +495,9 @@ class rcube_user
"INSERT INTO ".$dbh->table_name('users').
" (created, last_login, username, mail_host, language)".
" VALUES (".$dbh->now().", ".$dbh->now().", ?, ?, ?)",
- strip_newlines($data['user']),
- strip_newlines($data['host']),
- strip_newlines($data['language']));
+ $data['user'],
+ $data['host'],
+ $data['language']);
if ($user_id = $dbh->insert_id('users')) {
// create rcube_user instance to make plugin hooks work
@@ -517,7 +517,7 @@ class rcube_user
if (empty($user_email)) {
$user_email = strpos($data['user'], '@') ? $user : sprintf('%s@%s', $data['user'], $mail_domain);
}
- $email_list[] = strip_newlines($user_email);
+ $email_list[] = $user_email;
}
// identities_level check
else if (count($email_list) > 1 && $rcube->config->get('identities_level', 0) > 1) {
@@ -547,7 +547,6 @@ class rcube_user
$record['name'] = $user_name != $record['email'] ? $user_name : '';
}
- $record['name'] = strip_newlines($record['name']);
$record['user_id'] = $user_id;
$record['standard'] = $standard;
diff --git a/program/lib/Roundcube/rcube_utils.php b/program/lib/Roundcube/rcube_utils.php
index 8467107fe..cf87dedb7 100644
--- a/program/lib/Roundcube/rcube_utils.php
+++ b/program/lib/Roundcube/rcube_utils.php
@@ -360,12 +360,8 @@ class rcube_utils
return $value;
}
- // strip single quotes if magic_quotes_sybase is enabled
- if (ini_get('magic_quotes_sybase')) {
- $value = str_replace("''", "'", $value);
- }
// strip slashes if magic_quotes enabled
- else if (get_magic_quotes_gpc() || get_magic_quotes_runtime()) {
+ if (get_magic_quotes_gpc() || get_magic_quotes_runtime()) {
$value = stripslashes($value);
}
@@ -510,17 +506,24 @@ class rcube_utils
*/
public static function file2class($mimetype, $filename)
{
+ $mimetype = strtolower($mimetype);
+ $filename = strtolower($filename);
+
list($primary, $secondary) = explode('/', $mimetype);
$classes = array($primary ? $primary : 'unknown');
+
if ($secondary) {
$classes[] = $secondary;
}
- if (preg_match('/\.([a-z0-9]+)$/i', $filename, $m)) {
- $classes[] = $m[1];
+
+ if (preg_match('/\.([a-z0-9]+)$/', $filename, $m)) {
+ if (!in_array($m[1], $classes)) {
+ $classes[] = $m[1];
+ }
}
- return strtolower(join(" ", $classes));
+ return join(" ", $classes);
}
@@ -663,6 +666,21 @@ class rcube_utils
/**
+ * Returns the real remote IP address
+ *
+ * @return string Remote IP address
+ */
+ public static function remote_addr()
+ {
+ foreach (array('HTTP_X_FORWARDED_FOR','HTTP_X_REAL_IP','REMOTE_ADDR') as $prop) {
+ if (!empty($_SERVER[$prop]))
+ return $_SERVER[$prop];
+ }
+
+ return '';
+ }
+
+ /**
* Read a specific HTTP request header.
*
* @param string $name Header name
@@ -726,7 +744,7 @@ class rcube_utils
return mktime(0,0,0, intval($matches[2]), intval($matches[3]), intval($matches[1]));
}
else if (is_numeric($date)) {
- return $date;
+ return (int) $date;
}
// Clean malformed data
@@ -755,7 +773,7 @@ class rcube_utils
$date = implode(' ', $d);
}
- return $ts;
+ return (int) $ts;
}
diff --git a/program/lib/Roundcube/rcube_vcard.php b/program/lib/Roundcube/rcube_vcard.php
index 90acb2110..a71305c4b 100644
--- a/program/lib/Roundcube/rcube_vcard.php
+++ b/program/lib/Roundcube/rcube_vcard.php
@@ -714,9 +714,15 @@ class rcube_vcard
$value[] = $attrvalues;
}
else if (is_bool($attrvalues)) {
- // true means just tag, not tag=value, as in PHOTO;BASE64:...
+ // true means just a tag, not tag=value, as in PHOTO;BASE64:...
if ($attrvalues) {
- $attr .= strtoupper(";$attrname");
+ // vCard v3 uses ENCODING=B (#1489183)
+ if ($attrname == 'base64') {
+ $attr .= ";ENCODING=B";
+ }
+ else {
+ $attr .= strtoupper(";$attrname");
+ }
}
}
else {
diff --git a/program/lib/Roundcube/rcube_washtml.php b/program/lib/Roundcube/rcube_washtml.php
index a11371c61..6b2efcc78 100644
--- a/program/lib/Roundcube/rcube_washtml.php
+++ b/program/lib/Roundcube/rcube_washtml.php
@@ -113,10 +113,9 @@ class rcube_washtml
'type', 'rows', 'cols', 'disabled', 'readonly', 'checked', 'multiple', 'value'
);
- /* 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', 'u', 'span',
+ /* Elements which could be empty and be returned in short form (<tag />) */
+ static $void_elements = array('area', 'base', 'br', 'col', 'command', 'embed', 'hr',
+ 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr'
);
/* State for linked objects in HTML */
@@ -134,8 +133,8 @@ class rcube_washtml
/* Ignore these HTML tags but process their content */
private $_ignore_elements = array();
- /* Block elements which could be empty but cannot be returned in short form (<tag />) */
- private $_block_elements = array();
+ /* Elements which could be empty and be returned in short form (<tag />) */
+ private $_void_elements = array();
/* Allowed HTML attributes */
private $_html_attribs = array();
@@ -152,9 +151,9 @@ class rcube_washtml
$this->_html_elements = array_flip((array)$p['html_elements']) + array_flip(self::$html_elements) ;
$this->_html_attribs = array_flip((array)$p['html_attribs']) + array_flip(self::$html_attribs);
$this->_ignore_elements = array_flip((array)$p['ignore_elements']) + array_flip(self::$ignore_elements);
- $this->_block_elements = array_flip((array)$p['block_elements']) + array_flip(self::$block_elements);
+ $this->_void_elements = array_flip((array)$p['void_elements']) + array_flip(self::$void_elements);
- unset($p['html_elements'], $p['html_attribs'], $p['ignore_elements'], $p['block_elements']);
+ unset($p['html_elements'], $p['html_attribs'], $p['ignore_elements'], $p['void_elements']);
$this->config = $p + array('show_washed' => true, 'allow_remote' => false, 'cid_map' => array());
}
@@ -321,7 +320,7 @@ class rcube_washtml
else if (isset($this->_html_elements[$tagName])) {
$content = $this->dumpHtml($node, $level);
$dump .= '<' . $tagName . $this->wash_attribs($node) .
- ($content != '' || isset($this->_block_elements[$tagName]) ? ">$content</$tagName>" : ' />');
+ ($content === '' && isset($this->_void_elements[$tagName]) ? ' />' : ">$content</$tagName>");
}
else if (isset($this->_ignore_elements[$tagName])) {
$dump .= '<!-- ' . htmlspecialchars($tagName, ENT_QUOTES) . ' not allowed -->';
diff --git a/program/localization/ar_SA/labels.inc b/program/localization/ar_SA/labels.inc
index af08cc301..bc1764b0f 100644
--- a/program/localization/ar_SA/labels.inc
+++ b/program/localization/ar_SA/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'المسودات';
$labels['sent'] = 'المرسل';
$labels['trash'] = 'المهملات';
$labels['junk'] = 'غير المرغوب';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'الموضوع';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'وضع طريقة السرد';
$labels['folderactions'] = 'إجراءات المجلد...';
$labels['compact'] = 'ضغط';
$labels['empty'] = 'تÙريغ';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'المساحة المستخدمة';
$labels['unknown'] = 'مجهول';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'استعادة البحث للاÙتراضي';
$labels['searchmod'] = 'أماكن البحث';
$labels['msgtext'] = 'كامل الرسالة';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'اÙتح ÙÙŠ ناÙذة جديدة';
$labels['emlsave'] = 'تنزيل (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'عرض المجموعة الأخيرة';
$labels['group'] = 'مجموعة';
$labels['groups'] = 'المجموعات';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'العناوين الشخصية';
$labels['searchsave'] = 'Ø­Ùظ البحث';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'تجاهل الكلمات التي تحتوي
$labels['spellcheckignorecaps'] = 'تجاهل الكلمات التي بها أحر٠كبيرة';
$labels['addtodict'] = 'إضاÙØ© إلى القامس';
$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Messages forwarding';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'as attachment';
diff --git a/program/localization/ast/labels.inc b/program/localization/ast/labels.inc
index 49f85689b..8c1985eef 100644
--- a/program/localization/ast/labels.inc
+++ b/program/localization/ast/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Borradores';
$labels['sent'] = 'Unviaos';
$labels['trash'] = 'Papelera';
$labels['junk'] = 'Puxarra';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'Asuntu';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode';
$labels['folderactions'] = 'Folder actions...';
$labels['compact'] = 'Compautar';
$labels['empty'] = 'Vaciar';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Espaciu en discu';
$labels['unknown'] = 'desconocíu';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Anovar la búsqueda';
$labels['searchmod'] = 'Guetar modificadores';
$labels['msgtext'] = 'Mensax completu';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Abrir en una ventana nueva';
$labels['emlsave'] = 'Baxar (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Amosar l\'últimu grupu';
$labels['group'] = 'Group';
$labels['groups'] = 'Grupos';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Direiciones personales';
$labels['searchsave'] = 'Save search';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers';
$labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized';
$labels['addtodict'] = 'Add to dictionary';
$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Messages forwarding';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'as attachment';
diff --git a/program/localization/az_AZ/labels.inc b/program/localization/az_AZ/labels.inc
index 0cb4b3e82..129315ec0 100644
--- a/program/localization/az_AZ/labels.inc
+++ b/program/localization/az_AZ/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Qaralamalar';
$labels['sent'] = 'Göndərilənlər';
$labels['trash'] = 'Səbət';
$labels['junk'] = 'Spam';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'Mövzu';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'Görünüş rejimi';
$labels['folderactions'] = 'Qovluq işləri...';
$labels['compact'] = 'Sıx';
$labels['empty'] = 'BoÅŸalt';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Disk istifadəsi';
$labels['unknown'] = 'naməlum';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Axtarışı yenilə';
$labels['searchmod'] = 'Axtarış variantları';
$labels['msgtext'] = 'Bütün məktub';
$labels['body'] = 'Mətn';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Yeni pəncərədə aç';
$labels['emlsave'] = 'Saxla (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Sonuncunu göstər';
$labels['group'] = 'Qrup';
$labels['groups'] = 'Qruplar';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Şəxsi ünvanlar';
$labels['searchsave'] = 'SorÄŸunu saxla';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Rəqəmlər ilə sözləri keç';
$labels['spellcheckignorecaps'] = 'Böyük hərfləri olan sözlərdən keç';
$labels['addtodict'] = 'Lüğətə əlavə et';
$labels['mailtoprotohandler'] = 'mailto: keçid üçün protokol qeyd et';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Məktubların yönəldilməsi';
$labels['inline'] = 'mətndə';
$labels['asattachment'] = 'fayl kimi';
diff --git a/program/localization/be_BE/labels.inc b/program/localization/be_BE/labels.inc
index a5489a454..56339a926 100644
--- a/program/localization/be_BE/labels.inc
+++ b/program/localization/be_BE/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Чарнавікі';
$labels['sent'] = 'ДаÑланыÑ';
$labels['trash'] = 'Сметніца';
$labels['junk'] = 'Спам';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'ТÑма';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode';
$labels['folderactions'] = 'Folder actions...';
$labels['compact'] = 'Compact';
$labels['empty'] = 'Empty';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Disk usage';
$labels['unknown'] = 'unknown';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Reset search';
$labels['searchmod'] = 'Search modifiers';
$labels['msgtext'] = 'Entire message';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Open in new window';
$labels['emlsave'] = 'Download (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Show last page';
$labels['group'] = 'Group';
$labels['groups'] = 'Groups';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Personal Addresses';
$labels['searchsave'] = 'Save search';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers';
$labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized';
$labels['addtodict'] = 'Add to dictionary';
$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Messages forwarding';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'as attachment';
diff --git a/program/localization/bg_BG/labels.inc b/program/localization/bg_BG/labels.inc
index 6542cfc53..dd5be6e64 100644
--- a/program/localization/bg_BG/labels.inc
+++ b/program/localization/bg_BG/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Чернови';
$labels['sent'] = 'Изпратени';
$labels['trash'] = 'Кошче';
$labels['junk'] = 'Спам';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'Заглавие';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'Кратък ÑпиÑък';
$labels['folderactions'] = 'ДейÑÑ‚Ð²Ð¸Ñ Ð·Ð° папки...';
$labels['compact'] = 'Свиване';
$labels['empty'] = 'Изпразни';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Използвано мÑÑто';
$labels['unknown'] = 'нÑма информациÑ';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'ИзчиÑти Ñ‚ÑŠÑ€Ñенето и покажи вÑ
$labels['searchmod'] = 'ТърÑене във';
$labels['msgtext'] = 'ЦÑлото Ñъобщение';
$labels['body'] = 'ОÑновен текÑÑ‚';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Отвори в нов прозорец';
$labels['emlsave'] = 'Изтегли като .eml';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'ПоÑледна Ñтраница';
$labels['group'] = 'Група';
$labels['groups'] = 'Групи';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Лични адреÑи';
$labels['searchsave'] = 'Запази Ñ‚ÑŠÑ€Ñенето';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Игнорирай думи ÑъдържащÐ
$labels['spellcheckignorecaps'] = 'Игнорирай думи Ñъдържащи единÑтвено главни букви';
$labels['addtodict'] = 'Добави в речника';
$labels['mailtoprotohandler'] = 'РегиÑтриран протокол за mailto: връзките';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Препращане на ÑъобщениÑ';
$labels['inline'] = 'вградено';
$labels['asattachment'] = 'като прикачен файл';
diff --git a/program/localization/bn_BD/labels.inc b/program/localization/bn_BD/labels.inc
index a0866a3a7..1273ef192 100644
--- a/program/localization/bn_BD/labels.inc
+++ b/program/localization/bn_BD/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'খসড়া';
$labels['sent'] = 'পà§à¦°à§‡à¦°à¦¿à¦¤(পাঠানো মেইল)';
$labels['trash'] = 'ডাসà§à¦Ÿà¦¬à¦¿à¦¨';
$labels['junk'] = 'আজেবাজে মেইল';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'বিষয়';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode';
$labels['folderactions'] = 'Folder actions...';
$labels['compact'] = 'টাইটকরà§à¦¨';
$labels['empty'] = 'খালিকরà§à¦¨';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'ডিসà§à¦• ঠখালি যায়গা';
$labels['unknown'] = 'অজানা';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'নতà§à¦¨à¦•à¦°à§‡ খà§à¦œà§à¦¨';
$labels['searchmod'] = 'Search modifiers';
$labels['msgtext'] = 'Entire message';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'নতà§à¦¨ উইনà§à¦¡à§‹ তে দেখà§à¦¨';
$labels['emlsave'] = 'Download (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'শেষের গà§à¦²à§‹ দেখান';
$labels['group'] = 'Group';
$labels['groups'] = 'গà§à¦°à§à¦ª';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'নিজের ঠিকানা';
$labels['searchsave'] = 'Save search';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers';
$labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized';
$labels['addtodict'] = 'Add to dictionary';
$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Messages forwarding';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'as attachment';
diff --git a/program/localization/br/labels.inc b/program/localization/br/labels.inc
index 537a887df..c88fd92a6 100644
--- a/program/localization/br/labels.inc
+++ b/program/localization/br/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Brouilhedoù';
$labels['sent'] = 'Kaset';
$labels['trash'] = 'Pod-lastez';
$labels['junk'] = 'Stroboù';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'Sujed';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode';
$labels['folderactions'] = 'Folder actions...';
$labels['compact'] = 'Stummaat';
$labels['empty'] = 'Skarzhañ';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Implijadur pladenn';
$labels['unknown'] = 'Dianav';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Aderaouekaat ar glask';
$labels['searchmod'] = 'Search modifiers';
$labels['msgtext'] = 'Entire message';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Open in new window';
$labels['emlsave'] = 'Download (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Gwelout ar bajenn diwezhañ';
$labels['group'] = 'Group';
$labels['groups'] = 'Strolladoù';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Chomlec\'h personel';
$labels['searchsave'] = 'Save search';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers';
$labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized';
$labels['addtodict'] = 'Add to dictionary';
$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Messages forwarding';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'as attachment';
diff --git a/program/localization/bs_BA/labels.inc b/program/localization/bs_BA/labels.inc
index 5afdcad1f..61989e6b3 100644
--- a/program/localization/bs_BA/labels.inc
+++ b/program/localization/bs_BA/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Skice';
$labels['sent'] = 'Poslano';
$labels['trash'] = 'Smeće';
$labels['junk'] = 'Spam';
+$labels['show_real_foldernames'] = 'Prikaži prava imena specijalnih foldera';
// message listing
$labels['subject'] = 'Naslov';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'NaÄin prikaza liste';
$labels['folderactions'] = 'Akcije za foldere...';
$labels['compact'] = 'Optimiziraj';
$labels['empty'] = 'Isprazni';
+$labels['importmessages'] = 'Uvezi poruke';
$labels['quota'] = 'Zauzeće diska';
$labels['unknown'] = 'nepoznato';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Resetuj pretragu';
$labels['searchmod'] = 'Modifikacija pretrage';
$labels['msgtext'] = 'Cijela poruka';
$labels['body'] = 'Tijelo';
+$labels['type'] = 'Vrsta';
$labels['openinextwin'] = 'Otvori u novom prozoru';
$labels['emlsave'] = 'Preuzmi (.eml)';
@@ -223,7 +226,7 @@ $labels['mailreplyintro'] = '$date, $sender je napisao/la:';
$labels['originalmessage'] = 'Originalna poruka';
$labels['editidents'] = 'Uredi identitete';
-$labels['spellcheck'] = 'Spelovanje';
+$labels['spellcheck'] = 'Pravopis';
$labels['checkspelling'] = 'Provjera pravopisa';
$labels['resumeediting'] = 'Nastavi uređivanje';
$labels['revertto'] = 'Vrati na';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Prikaži zadnju stranicu';
$labels['group'] = 'Grupa';
$labels['groups'] = 'Grupe';
+$labels['listgroup'] = 'Izlistaj Älanove grupe';
$labels['personaladrbook'] = 'LiÄne adrese';
$labels['searchsave'] = 'SaÄuvaj pretragu';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Zanemari rijeÄi sa brojevima';
$labels['spellcheckignorecaps'] = 'Zanemari rijeÄi napisane velikim slovima';
$labels['addtodict'] = 'Dodaj u rjeÄnik';
$labels['mailtoprotohandler'] = 'Registruj upravljaÄ protokola za mailto: linkovi';
+$labels['standardwindows'] = 'Tretiraj popup-ove kao standardne prozore';
$labels['forwardmode'] = 'Prosljeđivanje poruka';
$labels['inline'] = 'u istom redu';
$labels['asattachment'] = 'kao prilog';
diff --git a/program/localization/ca_ES/labels.inc b/program/localization/ca_ES/labels.inc
index 3be753b68..ca0129de4 100644
--- a/program/localization/ca_ES/labels.inc
+++ b/program/localization/ca_ES/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Esborranys';
$labels['sent'] = 'Enviats';
$labels['trash'] = 'Paperera';
$labels['junk'] = 'Correu brossa';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'Assumpte';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'Mode de vista de llista';
$labels['folderactions'] = 'Accions de carpeta';
$labels['compact'] = 'Compacta';
$labels['empty'] = 'Buida';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Ús del disc';
$labels['unknown'] = 'desconegut';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Neteja cerca';
$labels['searchmod'] = 'Cerca modificadors';
$labels['msgtext'] = 'Missatge sencer';
$labels['body'] = 'Cos';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Obre a una nova finestra';
$labels['emlsave'] = 'Descarrega (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Mostra la darrera pàgina';
$labels['group'] = 'Grup';
$labels['groups'] = 'Grups';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Llibreta d\'adreces';
$labels['searchsave'] = 'Desa la cerca';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignora paraules amb números';
$labels['spellcheckignorecaps'] = 'Ignora paraules amb lletres capitalitzades';
$labels['addtodict'] = 'Afegeix al diccionari';
$labels['mailtoprotohandler'] = 'Registra controlador de protocol pels enllaços mailto:';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Reenviament de missatges';
$labels['inline'] = 'en línia';
$labels['asattachment'] = 'com adjunt';
diff --git a/program/localization/cs_CZ/labels.inc b/program/localization/cs_CZ/labels.inc
index 8fb7ffade..b5cc093d8 100644
--- a/program/localization/cs_CZ/labels.inc
+++ b/program/localization/cs_CZ/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Rozepsané';
$labels['sent'] = 'Odeslané';
$labels['trash'] = 'Koš';
$labels['junk'] = 'Spam';
+$labels['show_real_foldernames'] = 'Zobrazit skuteÄná jména speciálních složek';
// message listing
$labels['subject'] = 'Předmět';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'Režim zobrazení seznamu';
$labels['folderactions'] = 'Akce se složkou...';
$labels['compact'] = 'Zmenšit';
$labels['empty'] = 'Vymazat';
+$labels['importmessages'] = 'Import zpráv';
$labels['quota'] = 'Využití schránky';
$labels['unknown'] = 'neznámý';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Zrušit vyhledávání';
$labels['searchmod'] = 'Parametry hledání';
$labels['msgtext'] = 'Celá zpráva';
$labels['body'] = 'Tělo';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Otevřít v novém okně';
$labels['emlsave'] = 'Stáhnout (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Zobrazit poslední zprávy';
$labels['group'] = 'Skupina';
$labels['groups'] = 'Skupiny';
+$labels['listgroup'] = ' Seznam Älenů skupiny';
$labels['personaladrbook'] = 'Osobní kontakty';
$labels['searchsave'] = 'Uložit hledání';
@@ -402,7 +406,7 @@ $labels['htmleditor'] = 'Vytvářet HTML zprávy';
$labels['htmlonreply'] = 'jen při odpovědi na HTML zprávy';
$labels['htmlonreplyandforward'] = 'při přeposlání nebo odpovědi na HTML zprávu';
$labels['htmlsignature'] = 'HTML podpis';
-$labels['showemail'] = 'Show email address with display name';
+$labels['showemail'] = 'Zobrazit e-mailovou adresu se skuteÄným jménem';
$labels['previewpane'] = 'Zobrazit panel náhledu';
$labels['skin'] = 'Vzhled';
$labels['logoutclear'] = 'Vyprázdnit koš při odhlášení';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignorovat slova obsahující Äísla';
$labels['spellcheckignorecaps'] = 'Ignorovat slova psaná velkými písmeny';
$labels['addtodict'] = 'Přidat do slovníku';
$labels['mailtoprotohandler'] = 'Zaregistrovat handler pro odkazy „mailto:“';
+$labels['standardwindows'] = 'Zacházet s vyskakovacími okny jako se standardními okny';
$labels['forwardmode'] = 'Přeposlat zprávu';
$labels['inline'] = 'vloženě';
$labels['asattachment'] = 'jako přílohu';
diff --git a/program/localization/cs_CZ/messages.inc b/program/localization/cs_CZ/messages.inc
index 9800b2412..59b2c6bd6 100644
--- a/program/localization/cs_CZ/messages.inc
+++ b/program/localization/cs_CZ/messages.inc
@@ -24,7 +24,7 @@ $messages['sessionerror'] = 'Vaše přihlášení je neplatné nebo vypršelo';
$messages['storageerror'] = 'Připojení na IMAP server selhalo';
$messages['servererror'] = 'Chyba serveru!';
$messages['servererrormsg'] = 'Chyba serveru: $msg';
-$messages['dberror'] = 'Chyba v databázi!';
+$messages['dberror'] = 'Chyba databáze!';
$messages['requesttimedout'] = 'Došlo k vypršení požadavku';
$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í.';
@@ -33,7 +33,7 @@ $messages['erroroverquotadelete'] = 'Není volné místo na disku. Použijte SHI
$messages['invalidrequest'] = 'Nesprávný požadavek. Data nebyla uložena.';
$messages['invalidhost'] = 'Špatné jméno serveru.';
$messages['nomessagesfound'] = 'Ve schránce nebyla nalezena žádná zpráva';
-$messages['loggedout'] = 'Byli jste úspěšně odhlášeni. Nashledanou!';
+$messages['loggedout'] = 'Byli jste úspěšně odhlášeni. Na shledanou!';
$messages['mailboxempty'] = 'Schránka je prázdná';
$messages['refreshing'] = 'Obnovuji...';
$messages['loading'] = 'NaÄítám...';
@@ -126,6 +126,8 @@ $messages['importwait'] = 'Importuji, prosím Äekejte...';
$messages['importformaterror'] = 'Import se nezdařil! Typ souboru není podporován.';
$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 existujících položek</b>';
+$messages['importmessagesuccess'] = 'Úspěšně naimportováno $nr zpráv';
+$messages['importmessageerror'] = 'Import se nezdařil! Nahraný soubor není platnou zprávou nebo souborem mailboxu';
$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?';
diff --git a/program/localization/cy_GB/labels.inc b/program/localization/cy_GB/labels.inc
index 3e4f136bc..ca1f17426 100644
--- a/program/localization/cy_GB/labels.inc
+++ b/program/localization/cy_GB/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Drafftiau';
$labels['sent'] = 'Danfonwyd';
$labels['trash'] = 'Sbwriel';
$labels['junk'] = 'Sothach';
+$labels['show_real_foldernames'] = 'Dangos enwau go-iawn ar gyfer ffolderi arbennig';
// message listing
$labels['subject'] = 'Pwnc';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'Golwg rhestr';
$labels['folderactions'] = 'Gweithredoedd ffolder...';
$labels['compact'] = 'Crynhoi';
$labels['empty'] = 'Gwagio';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Defnydd';
$labels['unknown'] = 'anhysbys';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Ail-osod chwiliad';
$labels['searchmod'] = 'Addasyddion chwilio';
$labels['msgtext'] = 'Y neges yn llawn';
$labels['body'] = 'Corff';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Agor mewn ffenest newydd';
$labels['emlsave'] = 'Llwytho lawr (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Dangos y set olaf';
$labels['group'] = 'Grŵp';
$labels['groups'] = 'Grwpiau';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Cyfeiriadau Personol';
$labels['searchsave'] = 'Cadw chwiliad';
@@ -402,7 +406,7 @@ $labels['htmleditor'] = 'Ysgrifennu negeseuon HTML';
$labels['htmlonreply'] = 'wrth ateb i neges HTML yn unig';
$labels['htmlonreplyandforward'] = 'wrth ddanfon ymlaen neu ymateb i neges HTML';
$labels['htmlsignature'] = 'Llofnod HTML';
-$labels['showemail'] = 'Show email address with display name';
+$labels['showemail'] = 'Dangos cyfeiriad ebost gyda\'r enw gweledig';
$labels['previewpane'] = 'Dangos ffenest rhagolwg';
$labels['skin'] = 'Croen rhyngwyneb';
$labels['logoutclear'] = 'Clirio\'r Sbwriel wrth allgofnodi';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Anwybyddu geiriau gyda rhifau';
$labels['spellcheckignorecaps'] = 'Anwybyddu geiriau sy\'n briflythrennau yn gyfangwbl';
$labels['addtodict'] = 'Ychwanegu i\'r geiriadur';
$labels['mailtoprotohandler'] = 'Cofrestru trafodwr protocol ar gyfer dolenni mailto:';
+$labels['standardwindows'] = 'Trin ffenestri naid fel ffenestri arferol';
$labels['forwardmode'] = 'Danfon neges ymlaen';
$labels['inline'] = 'mewnlin';
$labels['asattachment'] = 'fel atodiad';
diff --git a/program/localization/da_DK/labels.inc b/program/localization/da_DK/labels.inc
index 02d7dd9e3..a5b9b3bc8 100644
--- a/program/localization/da_DK/labels.inc
+++ b/program/localization/da_DK/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Kladder';
$labels['sent'] = 'Sendt post';
$labels['trash'] = 'Papirkurv';
$labels['junk'] = 'Spam';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'Emne';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'Listevisningsmode';
$labels['folderactions'] = 'Mappehandlinger...';
$labels['compact'] = 'Ryd op';
$labels['empty'] = 'Tøm';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Diskforbrug';
$labels['unknown'] = 'ukendt';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Nulstil søgning';
$labels['searchmod'] = 'Søgeparametre';
$labels['msgtext'] = 'Hele beskeden';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Ã…bn i nyt vindue';
$labels['emlsave'] = 'Download (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Vis sidste side';
$labels['group'] = 'Gruppe';
$labels['groups'] = 'Grupper';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Personlige adresser';
$labels['searchsave'] = 'Gem søgning';
@@ -402,7 +406,7 @@ $labels['htmleditor'] = 'Skriv HTML-besked';
$labels['htmlonreply'] = 'kun når jeg besvarer HTML-beskeder';
$labels['htmlonreplyandforward'] = 'ved videresendelse eller besvarelse af HTML beskeder';
$labels['htmlsignature'] = 'HTML-signatur';
-$labels['showemail'] = 'Show email address with display name';
+$labels['showemail'] = 'Vis email-adresse med vist navn';
$labels['previewpane'] = 'Forhåndsvisning';
$labels['skin'] = 'Brugerflade';
$labels['logoutclear'] = 'Tøm Papirkurv når jeg logger af';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignorer ord med tal';
$labels['spellcheckignorecaps'] = 'Ignorer ord hvor alle bogstaver er versaler';
$labels['addtodict'] = 'Tilføj til ordbog';
$labels['mailtoprotohandler'] = 'Registrer håndtering af \'mailto:\' links';
+$labels['standardwindows'] = 'Behandl popups som standardvinduer';
$labels['forwardmode'] = 'Videresendelse af besked';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'som vedhæftning';
diff --git a/program/localization/de_CH/labels.inc b/program/localization/de_CH/labels.inc
index e64859d2c..67d42bb05 100644
--- a/program/localization/de_CH/labels.inc
+++ b/program/localization/de_CH/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Entwürfe';
$labels['sent'] = 'Gesendet';
$labels['trash'] = 'Gelöscht';
$labels['junk'] = 'Spam';
+$labels['show_real_foldernames'] = 'Spezialordner nicht übersetzen';
// message listing
$labels['subject'] = 'Betreff';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'Anzeigemodus';
$labels['folderactions'] = 'Ordneraktionen...';
$labels['compact'] = 'Packen';
$labels['empty'] = 'Leeren';
+$labels['importmessages'] = 'Nachrichten importieren';
$labels['quota'] = 'Verwendeter Speicherplatz';
$labels['unknown'] = 'unbekannt';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Löschen';
$labels['searchmod'] = 'Suchkriterien ändern';
$labels['msgtext'] = 'Ganze Nachricht';
$labels['body'] = 'Inhalt';
+$labels['type'] = 'Typ';
$labels['openinextwin'] = 'In neuem Fenster öffnen';
$labels['emlsave'] = 'Herunterladen (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Letzte Seite';
$labels['group'] = 'Gruppe';
$labels['groups'] = 'Gruppen';
+$labels['listgroup'] = 'Gruppenmitglieder anzeigen';
$labels['personaladrbook'] = 'Persönliches Adressbuch';
$labels['searchsave'] = 'Suche speichern';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Wörter mit Ziffern überspringen';
$labels['spellcheckignorecaps'] = 'Wörter überspringen, die nur aus Grossbuchstaben bestehen';
$labels['addtodict'] = 'Zum Wörterbuch hinzufügen';
$labels['mailtoprotohandler'] = 'Als Empfänger für mailto: Links einrichten';
+$labels['standardwindows'] = 'Popups als normale Browserfenster öffnen';
$labels['forwardmode'] = 'Weiterleiten einer Nachricht';
$labels['inline'] = 'eingebettet';
$labels['asattachment'] = 'als Anhang';
diff --git a/program/localization/de_CH/messages.inc b/program/localization/de_CH/messages.inc
index f3697a825..27175be9e 100644
--- a/program/localization/de_CH/messages.inc
+++ b/program/localization/de_CH/messages.inc
@@ -126,6 +126,8 @@ $messages['importwait'] = 'Daten werden importiert, bitte warten...';
$messages['importformaterror'] = 'Import fehlgeschlagen! Die hochgeladene Datei enthält keines der unterstützten Datenformate.';
$messages['importconfirm'] = '<b>Es wurden $inserted Adressen erfolgreich importiert</b>';
$messages['importconfirmskipped'] = '<b>$skipped bestehende Einträge wurden übersprungen</b>';
+$messages['importmessagesuccess'] = '$nr Nachricht(n) erfolgreich importiert';
+$messages['importmessageerror'] = 'Import fehlgeschlagen! Die hochgeladene Datei ist keine E-Mail-Nachricht oder Mailbox-Datei.';
$messages['opnotpermitted'] = 'Operation nicht erlaubt!';
$messages['nofromaddress'] = 'Fehlende E-Mail-Adresse in ausgewählter Identität.';
$messages['editorwarning'] = 'Beim Wechseln in den Texteditor gehen alle Textformatierungen verloren. Möchten Sie fortfahren?';
diff --git a/program/localization/de_DE/labels.inc b/program/localization/de_DE/labels.inc
index d497a6bc6..662ad2c70 100644
--- a/program/localization/de_DE/labels.inc
+++ b/program/localization/de_DE/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Entwürfe';
$labels['sent'] = 'Gesendet';
$labels['trash'] = 'Gelöscht';
$labels['junk'] = 'Spam';
+$labels['show_real_foldernames'] = 'Echte Namen für Spezialordner anzeigen';
// message listing
$labels['subject'] = 'Betreff';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'Anzeigemodus';
$labels['folderactions'] = 'Ordneraktionen...';
$labels['compact'] = 'Packen';
$labels['empty'] = 'Leeren';
+$labels['importmessages'] = 'Nachrichten importieren';
$labels['quota'] = 'Speicherplatz';
$labels['unknown'] = 'unbekannt';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Suche zurücksetzen';
$labels['searchmod'] = 'Suchkriterien ändern';
$labels['msgtext'] = 'Nachricht';
$labels['body'] = 'Inhalt';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'In neuem Fenster öffnen';
$labels['emlsave'] = 'Lokal speichern (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Letzte Seite';
$labels['group'] = 'Gruppe';
$labels['groups'] = 'Gruppen';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Persönliches Adressbuch';
$labels['searchsave'] = 'Suchergebnisse speichern';
@@ -402,7 +406,7 @@ $labels['htmleditor'] = 'HTML-Nachrichten verfassen';
$labels['htmlonreply'] = 'nur Antworten auf HTML-Nachrichten';
$labels['htmlonreplyandforward'] = 'beim Weiterleiten und Beantworten auf HTML-Nachrichten';
$labels['htmlsignature'] = 'HTML-Signatur';
-$labels['showemail'] = 'Show email address with display name';
+$labels['showemail'] = 'E-Mail-Adresse mit dem Display Namen anzeigen';
$labels['previewpane'] = 'Nachrichtenvorschau anzeigen';
$labels['skin'] = 'Oberflächendesign';
$labels['logoutclear'] = 'Papierkorb beim Abmelden leeren';
@@ -472,6 +476,7 @@ $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['mailtoprotohandler'] = 'Als Empfänger für mailto: Links einrichten';
+$labels['standardwindows'] = 'Popups als Standard Windows behandeln';
$labels['forwardmode'] = 'Nachrichtenweiterleitung';
$labels['inline'] = 'eingebettet';
$labels['asattachment'] = 'als Anhang';
diff --git a/program/localization/el_GR/labels.inc b/program/localization/el_GR/labels.inc
index 9f5d81839..d3030e574 100644
--- a/program/localization/el_GR/labels.inc
+++ b/program/localization/el_GR/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'ΠÏόχειÏα';
$labels['sent'] = 'Απεσταλμένα';
$labels['trash'] = 'Κάδος ΑποÏÏιμάτων';
$labels['junk'] = 'ΑνεπιθÏμητα';
+$labels['show_real_foldernames'] = 'Εμφάνιση Ï€Ïαγματικών ονομάτων για ειδικοÏÏ‚ φακέλους';
// message listing
$labels['subject'] = 'Θέμα';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'ΠÏοβολή σε λίστα';
$labels['folderactions'] = 'ΕνέÏγειες στους φακέλους';
$labels['compact'] = 'Συμπίεση';
$labels['empty'] = 'Άδειασμα';
+$labels['importmessages'] = 'Εισαγωγή μηνυμάτων';
$labels['quota'] = 'ΧÏήση δίσκου';
$labels['unknown'] = 'άγνωστο';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'ΕπαναφοÏά Αναζήτησης';
$labels['searchmod'] = 'Aλλαγή αναζήτησης';
$labels['msgtext'] = 'Σε όλο το μήνυμα';
$labels['body'] = 'Σώμα';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Άνοιγμα σε νέο παÏάθυÏο';
$labels['emlsave'] = 'Λήψη αÏχείου (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Εμφάνιση της τελευταίας σελ
$labels['group'] = 'Ομάδα';
$labels['groups'] = 'Ομάδες';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'ΠÏοσωπικές ΔιυθÏνσεις';
$labels['searchsave'] = 'Αποθήκευση αναζήτησης';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Οι λέξεις που πεÏιέχουν Î
$labels['spellcheckignorecaps'] = 'Οι λέξεις γÏαμμένες με ΚΕΦΑΛΑΙΑ να αγνοοÏνται';
$labels['addtodict'] = 'ΠÏοσθήκη στο λεξικό';
$labels['mailtoprotohandler'] = 'ΚαταχώÏηση διαχείÏισης Ï€Ïωτοκόλλου δεσμών mailto:';
+$labels['standardwindows'] = 'ΧειÏιστείτε τα αναδυόμενα παÏάθυÏα ως Ï€Ïότυπο των Windows';
$labels['forwardmode'] = 'ΠÏοώθηση μηνυμάτων';
$labels['inline'] = 'με εσνωμάτωση';
$labels['asattachment'] = 'σαν επισÏναψη';
diff --git a/program/localization/en_GB/labels.inc b/program/localization/en_GB/labels.inc
index 275208a98..f903b0cf5 100644
--- a/program/localization/en_GB/labels.inc
+++ b/program/localization/en_GB/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Drafts';
$labels['sent'] = 'Sent';
$labels['trash'] = 'Deleted Items';
$labels['junk'] = 'Junk';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'Subject';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode';
$labels['folderactions'] = 'Folder actions...';
$labels['compact'] = 'Compact';
$labels['empty'] = 'Empty';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Disk usage';
$labels['unknown'] = 'unknown';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Reset search';
$labels['searchmod'] = 'Search modifiers';
$labels['msgtext'] = 'Entire message';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Open in new window';
$labels['emlsave'] = 'Download (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Show last set';
$labels['group'] = 'Group';
$labels['groups'] = 'Groups';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Personal Addresses';
$labels['searchsave'] = 'Save search';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers';
$labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalised';
$labels['addtodict'] = 'Add to dictionary';
$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Messages forwarding';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'as attachment';
diff --git a/program/localization/en_US/labels.inc b/program/localization/en_US/labels.inc
index ab57007dd..1865bcb3d 100644
--- a/program/localization/en_US/labels.inc
+++ b/program/localization/en_US/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Drafts';
$labels['sent'] = 'Sent';
$labels['trash'] = 'Trash';
$labels['junk'] = 'Junk';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'Subject';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode';
$labels['folderactions'] = 'Folder actions...';
$labels['compact'] = 'Compact';
$labels['empty'] = 'Empty';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Disk usage';
$labels['unknown'] = 'unknown';
@@ -203,6 +205,8 @@ $labels['resetsearch'] = 'Reset search';
$labels['searchmod'] = 'Search modifiers';
$labels['msgtext'] = 'Entire message';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
+$labels['namex'] = 'Name';
$labels['openinextwin'] = 'Open in new window';
$labels['emlsave'] = 'Download (.eml)';
@@ -354,6 +358,7 @@ $labels['lastpage'] = 'Show last page';
$labels['group'] = 'Group';
$labels['groups'] = 'Groups';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Personal Addresses';
$labels['searchsave'] = 'Save search';
@@ -472,6 +477,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers';
$labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized';
$labels['addtodict'] = 'Add to dictionary';
$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Messages forwarding';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'as attachment';
diff --git a/program/localization/en_US/messages.inc b/program/localization/en_US/messages.inc
index f9b5e00a6..47b0f797d 100644
--- a/program/localization/en_US/messages.inc
+++ b/program/localization/en_US/messages.inc
@@ -101,13 +101,16 @@ $messages['converting'] = 'Removing formatting...';
$messages['messageopenerror'] = 'Could not load message from server.';
$messages['fileuploaderror'] = 'File upload failed.';
$messages['filesizeerror'] = 'The uploaded file exceeds the maximum size of $size.';
-$messages['copysuccess'] = 'Successfully copied $nr addresses.';
-$messages['copyerror'] = 'Could not copy any addresses.';
+$messages['copysuccess'] = 'Successfully copied $nr contacts.';
+$messages['movesuccess'] = 'Successfully moved $nr contacts.';
+$messages['copyerror'] = 'Could not copy any contacts.';
+$messages['moveerror'] = 'Could not move any contacts.';
$messages['sourceisreadonly'] = 'This address source is read only.';
$messages['errorsavingcontact'] = 'Could not save the contact address.';
$messages['movingmessage'] = 'Moving message(s)...';
$messages['copyingmessage'] = 'Copying message(s)...';
$messages['copyingcontact'] = 'Copying contact(s)...';
+$messages['movingcontact'] = 'Moving contact(s)...';
$messages['deletingmessage'] = 'Deleting message(s)...';
$messages['markingmessage'] = 'Marking message(s)...';
$messages['addingmember'] = 'Adding contact(s) to the group...';
@@ -126,6 +129,8 @@ $messages['importwait'] = 'Importing, please wait...';
$messages['importformaterror'] = 'Import failed! The uploaded file is not a valid import data file.';
$messages['importconfirm'] = '<b>Successfully imported $inserted contacts</b>';
$messages['importconfirmskipped'] = '<b>Skipped $skipped existing entries</b>';
+$messages['importmessagesuccess'] = 'Successfully imported $nr messages';
+$messages['importmessageerror'] = 'Import failed! The uploaded file is not a valid message or mailbox file';
$messages['opnotpermitted'] = 'Operation not permitted!';
$messages['nofromaddress'] = 'Missing e-mail address in selected identity.';
$messages['editorwarning'] = 'Switching to the plain text editor will cause all text formatting to be lost. Do you wish to continue?';
diff --git a/program/localization/eo/labels.inc b/program/localization/eo/labels.inc
index c088fc50e..3c2930c89 100644
--- a/program/localization/eo/labels.inc
+++ b/program/localization/eo/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Malnetujo';
$labels['sent'] = 'Senditujo';
$labels['trash'] = 'Rubujo';
$labels['junk'] = 'Spamujo';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'Temo';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode';
$labels['folderactions'] = 'Dosierujo-agoj';
$labels['compact'] = 'Kompakta';
$labels['empty'] = 'Malplena';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Diskuzo';
$labels['unknown'] = 'nekonata';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Vakigu serĉon';
$labels['searchmod'] = 'Serĉ-opcioj';
$labels['msgtext'] = 'Tuta mesaÄo';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Malfermu en nova fenestro';
$labels['emlsave'] = 'ElÅutu (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Montru lastan';
$labels['group'] = 'Group';
$labels['groups'] = 'Grupoj';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Persona Adresoj';
$labels['searchsave'] = 'Save search';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers';
$labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized';
$labels['addtodict'] = 'Add to dictionary';
$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Messages forwarding';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'as attachment';
diff --git a/program/localization/es_AR/labels.inc b/program/localization/es_AR/labels.inc
index d9a83be75..5bc53f7f0 100644
--- a/program/localization/es_AR/labels.inc
+++ b/program/localization/es_AR/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Borradores';
$labels['sent'] = 'Enviados';
$labels['trash'] = 'Papelera';
$labels['junk'] = 'Basura';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'Asunto';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode';
$labels['folderactions'] = 'Acciones de carpeta...';
$labels['compact'] = 'Compactar';
$labels['empty'] = 'Vaciar';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Uso de disco';
$labels['unknown'] = 'desconocido';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Reajustar la búsqueda';
$labels['searchmod'] = 'Opciones de búsqueda';
$labels['msgtext'] = 'Mensaje completo';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Abrir en ventana nueva';
$labels['emlsave'] = 'Guardar (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Mostrar último grupo';
$labels['group'] = 'Grupo';
$labels['groups'] = 'Grupos';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Direcciones personales';
$labels['searchsave'] = 'Guardar búsqueda';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers';
$labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized';
$labels['addtodict'] = 'Add to dictionary';
$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Messages forwarding';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'as attachment';
diff --git a/program/localization/es_ES/labels.inc b/program/localization/es_ES/labels.inc
index 03f6b489a..11d14fa08 100644
--- a/program/localization/es_ES/labels.inc
+++ b/program/localization/es_ES/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Borradores';
$labels['sent'] = 'Enviados';
$labels['trash'] = 'Papelera';
$labels['junk'] = 'SPAM';
+$labels['show_real_foldernames'] = 'Mostrar nombres reales para carpetas especiales';
// message listing
$labels['subject'] = 'Asunto';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'Modo de vista de lista';
$labels['folderactions'] = 'Acciones de bandeja...';
$labels['compact'] = 'Compactar';
$labels['empty'] = 'Vaciar';
+$labels['importmessages'] = 'Importar mensajes';
$labels['quota'] = 'Uso de disco';
$labels['unknown'] = 'desconocido';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Reiniciar la búsqueda';
$labels['searchmod'] = 'Opciones de búsqueda';
$labels['msgtext'] = 'Mensaje completo';
$labels['body'] = 'Cuerpo';
+$labels['type'] = 'Tipo';
$labels['openinextwin'] = 'Abrir en nueva ventana';
$labels['emlsave'] = 'Descargar (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Mostrar último grupo';
$labels['group'] = 'Grupo';
$labels['groups'] = 'Grupos';
+$labels['listgroup'] = 'Listar miembros del grupo';
$labels['personaladrbook'] = 'Direcciones personales';
$labels['searchsave'] = 'Guardar búsqueda';
@@ -402,7 +406,7 @@ $labels['htmleditor'] = 'Componer mensaje en HTML';
$labels['htmlonreply'] = 'sólo en respuesta a un mensaje HTML';
$labels['htmlonreplyandforward'] = 'en reenvío o respuesta al mensaje HTML';
$labels['htmlsignature'] = 'Firma HTML';
-$labels['showemail'] = 'Show email address with display name';
+$labels['showemail'] = 'Mostrar dirección de correo electrónico al visualizar el nombre';
$labels['previewpane'] = 'Mostrar vista preliminar';
$labels['skin'] = 'Apariencia de la interfaz';
$labels['logoutclear'] = 'Vaciar papelera al cerrar sesión';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignorar palabras con números';
$labels['spellcheckignorecaps'] = 'Ignorar palabras con todo mayúsculas';
$labels['addtodict'] = 'Añadir al diccionario';
$labels['mailtoprotohandler'] = 'Registrar controlador de protocolo para enlaces mailto:';
+$labels['standardwindows'] = 'Gestionar ventanas emergentes como ventanas estándar';
$labels['forwardmode'] = 'Reenvío de mensajes';
$labels['inline'] = 'en línea';
$labels['asattachment'] = 'como adjunto';
diff --git a/program/localization/es_ES/messages.inc b/program/localization/es_ES/messages.inc
index 6c031df29..d4bd81402 100644
--- a/program/localization/es_ES/messages.inc
+++ b/program/localization/es_ES/messages.inc
@@ -126,6 +126,8 @@ $messages['importwait'] = 'Importando, espere...';
$messages['importformaterror'] = '¡La importación falló! El fichero enviado no es un fichero válido de importación de datos';
$messages['importconfirm'] = '<b>Se han importado $inserted contactos correctamente</b>';
$messages['importconfirmskipped'] = '<b>Ignoradas $skipped entradas existentes</b>';
+$messages['importmessagesuccess'] = '$nr mensajes importados con éxito';
+$messages['importmessageerror'] = '¡Ha fallado la importación! El fichero subido no es un fichero válido de mensaje o buzón de correo';
$messages['opnotpermitted'] = '¡Operación no permitida!';
$messages['nofromaddress'] = 'El contacto seleccionado no tiene dirección de e-mail';
$messages['editorwarning'] = 'Cambiando a texto plano perderá el formato del mensaje. ¿Desea continuar?';
diff --git a/program/localization/et_EE/labels.inc b/program/localization/et_EE/labels.inc
index c3b3aa954..a8bc28403 100644
--- a/program/localization/et_EE/labels.inc
+++ b/program/localization/et_EE/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Mustandid';
$labels['sent'] = 'Saadetud';
$labels['trash'] = 'Prügikast';
$labels['junk'] = 'Rämps';
+$labels['show_real_foldernames'] = 'Näita eriliste kaustade päris nimesid';
// message listing
$labels['subject'] = 'Pealkiri';
@@ -64,7 +65,7 @@ $labels['copy'] = 'Kopeeri';
$labels['move'] = 'Liiguta';
$labels['moveto'] = 'liiguta kausta...';
$labels['download'] = 'laadi arvutisse';
-$labels['open'] = 'Open';
+$labels['open'] = 'Ava';
$labels['showattachment'] = 'Näita';
$labels['showanyway'] = 'Näita ikka';
@@ -162,7 +163,7 @@ $labels['currpage'] = 'Praegune leht';
$labels['unread'] = 'Lugemata';
$labels['flagged'] = 'Märgistatud';
$labels['unanswered'] = 'Vastamata';
-$labels['withattachment'] = 'With attachment';
+$labels['withattachment'] = 'Koos manusega';
$labels['deleted'] = 'Kustutatud';
$labels['undeleted'] = 'Pole kustutatud';
$labels['invert'] = 'Vaheta';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'Nimekirja vaatamise režiim';
$labels['folderactions'] = 'Kausta tegevused...';
$labels['compact'] = 'Tihenda';
$labels['empty'] = 'Tühjenda';
+$labels['importmessages'] = 'Impordi kirju';
$labels['quota'] = 'Kettakasutus';
$labels['unknown'] = 'teadmata';
@@ -203,11 +205,12 @@ $labels['resetsearch'] = 'Lähtesta otsing';
$labels['searchmod'] = 'Otsingu laiendid';
$labels['msgtext'] = 'Kogu kirjast';
$labels['body'] = 'Keha';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Ava uues aknas';
$labels['emlsave'] = 'Salvesta (.eml)';
-$labels['changeformattext'] = 'Display in plain text format';
-$labels['changeformathtml'] = 'Display in HTML format';
+$labels['changeformattext'] = 'Näita lihttekstina';
+$labels['changeformathtml'] = 'Näita HTMLis';
// message compose
$labels['editasnew'] = 'Kasuta uue kirja põhjana';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Näita viimast komplekti';
$labels['group'] = 'Grupp';
$labels['groups'] = 'Grupid';
+$labels['listgroup'] = 'Näita grupi liikmeid';
$labels['personaladrbook'] = 'Isiklikud aadressid';
$labels['searchsave'] = 'Salvesta otsing';
@@ -402,7 +406,7 @@ $labels['htmleditor'] = 'Kasuta HTML redaktorit';
$labels['htmlonreply'] = 'vaid HTML-vormingus kirjale vastamisel';
$labels['htmlonreplyandforward'] = 'edastamisel või HTML kirjale vastates';
$labels['htmlsignature'] = 'HTML allkiri';
-$labels['showemail'] = 'Show email address with display name';
+$labels['showemail'] = 'Näita nime juures e-posti aadressi';
$labels['previewpane'] = 'Näita eelvaate akent';
$labels['skin'] = 'Kliendi välimus';
$labels['logoutclear'] = 'Tühjenda väljumisel prügikast';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignoreeri sõnu, milles on numbreid';
$labels['spellcheckignorecaps'] = 'Ignoreeri suurte tähtedega kirjutatud sõnu';
$labels['addtodict'] = 'Lisa sõnastikku';
$labels['mailtoprotohandler'] = 'Kasuta mailto: linkide avamisel';
+$labels['standardwindows'] = 'Käsitle hüpikaknaid tavaliste akendena';
$labels['forwardmode'] = 'Kirja edastamine';
$labels['inline'] = 'kirja sees';
$labels['asattachment'] = 'manusena';
diff --git a/program/localization/et_EE/messages.inc b/program/localization/et_EE/messages.inc
index 0064eaf9d..4d58b0a75 100644
--- a/program/localization/et_EE/messages.inc
+++ b/program/localization/et_EE/messages.inc
@@ -28,8 +28,8 @@ $messages['dberror'] = 'Andmebaasi tõrge!';
$messages['requesttimedout'] = 'Päring aegus';
$messages['errorreadonly'] = 'Operatsioon nurjus. Kaustale on vaid lugemisõigus';
$messages['errornoperm'] = 'Operatsioon nurjus. Ligipääsu õigused puuduvad';
-$messages['erroroverquota'] = 'Unable to perform operation. No free disk space.';
-$messages['erroroverquotadelete'] = 'No free disk space. Use SHIFT+DEL to delete a message.';
+$messages['erroroverquota'] = 'Operatsioon nurjus. Ketas on täis.';
+$messages['erroroverquotadelete'] = 'Ketas on täis. Kirja kustutamiseks vajuta SHIFT+DEL.';
$messages['invalidrequest'] = 'Lubamatu päring! Andmeid ei salvestatud.';
$messages['invalidhost'] = 'Lubamatu serveri nimi.';
$messages['nomessagesfound'] = 'Postkast paistab tühi olevat';
@@ -126,6 +126,8 @@ $messages['importwait'] = 'Impordin, palun oota...';
$messages['importformaterror'] = 'Import nurjus! Laaditud fail ei sisalda sobilikke andmeid.';
$messages['importconfirm'] = '<b>Edukalt imporditud $inserted kontakti, $skipped olemasolevat sissekannet vahele jäetud</b>:<p><em>$names</em></p>';
$messages['importconfirmskipped'] = '<b> $skipped olemasolevat kirjet jäeti vahele</b>';
+$messages['importmessagesuccess'] = '$nr kirja edukalt imporditud';
+$messages['importmessageerror'] = 'Import nurjus! Laaditud fail ei ole kirja ega postkasti fail';
$messages['opnotpermitted'] = 'Tegevus pole lubatud!';
$messages['nofromaddress'] = 'Valitud identiteedil puudub e-posti aadress';
$messages['editorwarning'] = 'Klaarteksti redaktorile lülitamine kaotab kogu teksti vorminduse. Soovid jätkata?';
diff --git a/program/localization/eu_ES/labels.inc b/program/localization/eu_ES/labels.inc
index 8052d69e8..fedce7de5 100644
--- a/program/localization/eu_ES/labels.inc
+++ b/program/localization/eu_ES/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Zirriborroak';
$labels['sent'] = 'Bidalitakoak';
$labels['trash'] = 'Zakarrontzia';
$labels['junk'] = 'Zabor-posta';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'Gaia';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode';
$labels['folderactions'] = 'Folder actions...';
$labels['compact'] = 'Trinkotu';
$labels['empty'] = 'Hustu';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Disko erabilera';
$labels['unknown'] = 'ezezaguna';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Bilaketa berrabiarazi';
$labels['searchmod'] = 'Search modifiers';
$labels['msgtext'] = 'Entire message';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Lehio berrian ireki';
$labels['emlsave'] = 'Download (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Azken sorta ikusi';
$labels['group'] = 'Group';
$labels['groups'] = 'Taldeak';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Helbide pertsonalak';
$labels['searchsave'] = 'Save search';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers';
$labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized';
$labels['addtodict'] = 'Add to dictionary';
$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Messages forwarding';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'as attachment';
diff --git a/program/localization/fa_AF/labels.inc b/program/localization/fa_AF/labels.inc
index 70113bc49..38154c23c 100644
--- a/program/localization/fa_AF/labels.inc
+++ b/program/localization/fa_AF/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'نامه های ناتکمیل';
$labels['sent'] = 'ارسال شده';
$labels['trash'] = 'اشغال دانی';
$labels['junk'] = 'بیکاره';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'مضمون';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode';
$labels['folderactions'] = 'Folder actions...';
$labels['compact'] = 'خلاصه';
$labels['empty'] = 'خالي';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = '‌طريقه استعمال ديسک';
$labels['unknown'] = 'نامعلوم';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'بازنشاندن جستجو';
$labels['searchmod'] = 'Search modifiers';
$labels['msgtext'] = 'Entire message';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'در پینجره ای جدید باز کنید';
$labels['emlsave'] = 'Download (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'بسته اخير را نشان دهيد';
$labels['group'] = 'Group';
$labels['groups'] = 'گروه ها';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'ادرس های شخصي';
$labels['searchsave'] = 'Save search';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers';
$labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized';
$labels['addtodict'] = 'Add to dictionary';
$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Messages forwarding';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'as attachment';
diff --git a/program/localization/fa_IR/labels.inc b/program/localization/fa_IR/labels.inc
index 221e4b891..79bfbbe9d 100644
--- a/program/localization/fa_IR/labels.inc
+++ b/program/localization/fa_IR/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'پیش‌نویس‌ها';
$labels['sent'] = 'Ùرستاده شده';
$labels['trash'] = 'سطل آشغال';
$labels['junk'] = 'بنجل';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'موضوع';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'نوع مشاهده Ùهرست';
$labels['folderactions'] = 'اعمال پوشه...';
$labels['compact'] = 'Ùشرده';
$labels['empty'] = 'خالی';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Ùضای استÙاده شده';
$labels['unknown'] = 'ناشناخته';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'جستجوی دوباره';
$labels['searchmod'] = 'اصلاحات جستجو';
$labels['msgtext'] = 'کل پیغام';
$labels['body'] = 'بدنه';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'باز کردن در پنجره‌ی جدید';
$labels['emlsave'] = 'بارگیری (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'نمایش صÙحه آخر';
$labels['group'] = 'گروه';
$labels['groups'] = 'گروه‌ها';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'نشانی‌های شخصی';
$labels['searchsave'] = 'ذخیره جستجو';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'نادیده گرÙتن کلمات دارای
$labels['spellcheckignorecaps'] = 'نادیده گرÙتن کلمات با حرو٠بزرگ';
$labels['addtodict'] = 'اضاÙÙ‡ کردن به واژه‌نامه';
$labels['mailtoprotohandler'] = 'ثبت نگه‌دارنده پروتوکل برای mailto: پیوندها';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'بازگردانی پیغام';
$labels['inline'] = 'خطی';
$labels['asattachment'] = 'به عنوان پیوست';
diff --git a/program/localization/fi_FI/labels.inc b/program/localization/fi_FI/labels.inc
index 006f62947..ef0f0bff0 100644
--- a/program/localization/fi_FI/labels.inc
+++ b/program/localization/fi_FI/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Luonnokset';
$labels['sent'] = 'Lähetetyt';
$labels['trash'] = 'Roskakori';
$labels['junk'] = 'Roskaposti';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'Aihe';
@@ -162,7 +163,7 @@ $labels['currpage'] = 'Nykyinen sivu';
$labels['unread'] = 'Lukemattomat';
$labels['flagged'] = 'Korostettu';
$labels['unanswered'] = 'Vastaamaton';
-$labels['withattachment'] = 'With attachment';
+$labels['withattachment'] = 'Liitteen kera';
$labels['deleted'] = 'Poistettu';
$labels['undeleted'] = 'Ei poistettu';
$labels['invert'] = 'Käännä';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'Listausnäkymä';
$labels['folderactions'] = 'Kansiotoiminnot...';
$labels['compact'] = 'Tiivistä';
$labels['empty'] = 'Tyhjennä';
+$labels['importmessages'] = 'Tuo viestejä';
$labels['quota'] = 'Levytila';
$labels['unknown'] = 'tuntematon';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Nollaa haku';
$labels['searchmod'] = 'Hakukriteerit';
$labels['msgtext'] = 'Koko viesti';
$labels['body'] = 'Runko';
+$labels['type'] = 'Tyyppi';
$labels['openinextwin'] = 'Avaa uudessa ikkunassa';
$labels['emlsave'] = 'Tallenna (.eml)';
@@ -245,9 +248,9 @@ $labels['nosubject'] = '(ei otsikkoa)';
$labels['showimages'] = 'Näytä kuvat';
$labels['alwaysshow'] = 'Näytä aina lähettäjältä $sender saapuneet kuvat';
$labels['isdraft'] = 'Tämä on luonnosviesti.';
-$labels['andnmore'] = '$nr more...';
+$labels['andnmore'] = '$nr lisää...';
$labels['togglemoreheaders'] = 'Näytä lisää viestiotsakkeita';
-$labels['togglefullheaders'] = 'Toggle raw message headers';
+$labels['togglefullheaders'] = 'Viestin otsakkeet päällä/pois';
$labels['htmltoggle'] = 'HTML';
$labels['plaintoggle'] = 'Tavallinen teksti';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Näytä viimeinen luettelo';
$labels['group'] = 'Ryhmä';
$labels['groups'] = 'Ryhmät';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Henkilökohtaiset osoitteet';
$labels['searchsave'] = 'Tallenna haku';
@@ -400,7 +404,7 @@ $labels['showinextwin'] = 'Avaa viesti uudessa ikkunassa';
$labels['composeextwin'] = 'Lähetä viesti uudessa ikkunassa';
$labels['htmleditor'] = 'Kirjoita HTML-muodossa';
$labels['htmlonreply'] = 'Vain vastatessa HTML-viesteihin';
-$labels['htmlonreplyandforward'] = 'on forward or reply to HTML message';
+$labels['htmlonreplyandforward'] = 'välittäessä tai vastatessa HTML-viestiin';
$labels['htmlsignature'] = 'HTML-allekirjoitus';
$labels['showemail'] = 'Näytä sähköpostiosoite näyttönimen kanssa';
$labels['previewpane'] = 'Näytä esikatselulehti';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Jätä huomiotta sanat, joissa on numeroita';
$labels['spellcheckignorecaps'] = 'Jätä huomiotta sanat, joissa kaikki kirjaimet on isoja';
$labels['addtodict'] = 'Lisää sanakirjaan';
$labels['mailtoprotohandler'] = 'Rekisteröi mailto:-linkkien protokollakäsitteljä';
+$labels['standardwindows'] = 'Käsittele popup-ikkunoita tavallisina ikkunoina';
$labels['forwardmode'] = 'Viestin välitys';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'liitteenä';
diff --git a/program/localization/fr_FR/labels.inc b/program/localization/fr_FR/labels.inc
index 6731ecc3f..2a4f3a169 100644
--- a/program/localization/fr_FR/labels.inc
+++ b/program/localization/fr_FR/labels.inc
@@ -26,9 +26,9 @@ $labels['server'] = 'Serveur';
$labels['login'] = 'Connexion';
// taskbar
-$labels['logout'] = 'Quitter';
+$labels['logout'] = 'Déconnexion';
$labels['mail'] = 'Courriel';
-$labels['settings'] = 'Préférences';
+$labels['settings'] = 'Paramètres';
$labels['addressbook'] = 'Carnet d\'adresses';
// mailbox names
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Brouillons';
$labels['sent'] = 'Messages envoyés';
$labels['trash'] = 'Corbeille';
$labels['junk'] = 'Indésirables';
+$labels['show_real_foldernames'] = 'Montrer les noms réels pour les dossiers spéciaux';
// message listing
$labels['subject'] = 'Objet';
@@ -127,7 +128,7 @@ $labels['checkmail'] = 'Vérification des nouveaux messages';
$labels['compose'] = 'Composer un nouveau message';
$labels['writenewmessage'] = 'Écrire un nouveau message';
$labels['reply'] = 'Répondre';
-$labels['replytomessage'] = 'Répondre au message';
+$labels['replytomessage'] = 'Répondre à l\'expéditeur';
$labels['replytoallmessage'] = 'Répondre à tous';
$labels['replyall'] = 'Répondre à tous';
$labels['replylist'] = 'Répondre à la liste';
@@ -146,10 +147,10 @@ $labels['backtolist'] = 'Retourner à la liste des messages';
$labels['viewsource'] = 'Voir la source';
$labels['mark'] = 'Marquer';
$labels['markmessages'] = 'Marquer les messages';
-$labels['markread'] = 'Comme lus';
-$labels['markunread'] = 'Comme non lus';
-$labels['markflagged'] = 'Comme suivi';
-$labels['markunflagged'] = 'Comme non-suivi';
+$labels['markread'] = 'Comme lu(s)';
+$labels['markunread'] = 'Comme non lu(s)';
+$labels['markflagged'] = 'Comme suivi(s)';
+$labels['markunflagged'] = 'Comme non-suivi(s)';
$labels['moreactions'] = 'Plus d\'actions...';
$labels['more'] = 'Plus';
$labels['back'] = 'Retour';
@@ -159,19 +160,19 @@ $labels['select'] = 'Sélectionner';
$labels['all'] = 'Tous';
$labels['none'] = 'Aucun';
$labels['currpage'] = 'Page courante';
-$labels['unread'] = 'Non lus';
-$labels['flagged'] = 'Marqué';
-$labels['unanswered'] = 'Non répondu';
+$labels['unread'] = 'Non lu(s)';
+$labels['flagged'] = 'Marqué(s)';
+$labels['unanswered'] = 'Non répondu(s)';
$labels['withattachment'] = 'Avec pièce jointe';
-$labels['deleted'] = 'Supprimé';
-$labels['undeleted'] = 'Non supprimé';
+$labels['deleted'] = 'Supprimé(s)';
+$labels['undeleted'] = 'Non supprimé(s)';
$labels['invert'] = 'Inverser';
$labels['filter'] = 'Filtre';
$labels['list'] = 'Lister';
$labels['threads'] = 'Sujets';
-$labels['expand-all'] = 'Afficher Tous';
-$labels['expand-unread'] = 'Afficher Non-lus';
-$labels['collapse-all'] = 'Fermer Tous';
+$labels['expand-all'] = 'Tout afficher';
+$labels['expand-unread'] = 'Afficher non-lu(s)';
+$labels['collapse-all'] = 'Fermer tous';
$labels['threaded'] = 'Par sujet';
$labels['autoexpand_threads'] = 'Développer les sujets';
@@ -190,9 +191,10 @@ $labels['listsorting'] = 'Colonne de tri';
$labels['listorder'] = 'Ordre de tri';
$labels['listmode'] = 'Mode d\'affichage de la liste';
-$labels['folderactions'] = 'Actions du dossier';
+$labels['folderactions'] = 'Actions du dossier...';
$labels['compact'] = 'Compacter';
$labels['empty'] = 'Vider';
+$labels['importmessages'] = 'Importer des messages';
$labels['quota'] = 'Occupation disque';
$labels['unknown'] = 'inconnue';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Réinitialiser la recherche';
$labels['searchmod'] = 'Portée de la recherche';
$labels['msgtext'] = 'Message entier';
$labels['body'] = 'Corps';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Ouvrir dans une nouvelle fenêtre';
$labels['emlsave'] = 'Télécharger (.eml)';
@@ -212,8 +215,8 @@ $labels['changeformathtml'] = 'Afficher au format HTML';
// message compose
$labels['editasnew'] = 'Éditer en tant que nouveau message';
$labels['send'] = 'Envoyer';
-$labels['sendmessage'] = 'Envoyer';
-$labels['savemessage'] = 'Enregistrer';
+$labels['sendmessage'] = 'Envoyer un message';
+$labels['savemessage'] = 'Sauvegarder comme brouillon';
$labels['addattachment'] = 'Joindre un fichier';
$labels['charset'] = 'Encodage';
$labels['editortype'] = 'Type d\'éditeur';
@@ -223,14 +226,14 @@ $labels['mailreplyintro'] = 'Le $date, $sender a écrit :';
$labels['originalmessage'] = 'Message original';
$labels['editidents'] = 'Modifier les identités';
-$labels['spellcheck'] = 'Vérifier l\'orthographe';
+$labels['spellcheck'] = 'Orthographe';
$labels['checkspelling'] = 'Vérifier l\'orthographe';
$labels['resumeediting'] = 'Retourner à l\'édition';
$labels['revertto'] = 'Revenir à';
$labels['attach'] = 'Joindre';
$labels['attachments'] = 'Fichiers joints';
-$labels['upload'] = 'Joindre';
+$labels['upload'] = 'Transférer';
$labels['uploadprogress'] = '$percent ($current sur $total)';
$labels['close'] = 'Fermer';
$labels['messageoptions'] = 'Options du message';
@@ -250,7 +253,7 @@ $labels['togglemoreheaders'] = 'Afficher plus d\'en-têtes du message';
$labels['togglefullheaders'] = 'Afficher/Cacher l\'entête du message';
$labels['htmltoggle'] = 'HTML';
-$labels['plaintoggle'] = 'texte brut';
+$labels['plaintoggle'] = 'Texte brut';
$labels['savesentmessagein'] = 'Enregistrer le message envoyé dans';
$labels['dontsave'] = 'ne pas enregistrer';
$labels['maxuploadsize'] = 'La taille maximum autorisée pour un fichier est $size';
@@ -264,7 +267,7 @@ $labels['addfollowupto'] = 'Ajouter Faire suivre à';
$labels['mdnrequest'] = 'L\'expéditeur de ce message a demandé d\'être prévenu quand vous lirez ce message. Souhaitez-vous prévenir l\'expéditeur ?';
$labels['receiptread'] = 'Accusé de réception (lu)';
$labels['yourmessage'] = 'Ceci est un accusé de réception pour votre message';
-$labels['receiptnote'] = 'Note : Cet accusé de réception indique seulement que le message a été affiché sur l\'ordinateur du destinataire. Il n\'y a aucune garantie que le destinataire a lu ou compris le contenu du message.';
+$labels['receiptnote'] = 'Note : Cet accusé de réception indique seulement que le message a été affiché sur l\'ordinateur du destinataire. Il n\'y a aucune garantie que le destinataire ait lu ou compris le contenu du message.';
// address boook
$labels['name'] = 'Nom à afficher';
@@ -275,9 +278,9 @@ $labels['nameprefix'] = 'Préfixe';
$labels['namesuffix'] = 'Suffixe';
$labels['nickname'] = 'Surnom';
$labels['jobtitle'] = 'Fonction';
-$labels['department'] = 'Département';
+$labels['department'] = 'Service';
$labels['gender'] = 'Sexe';
-$labels['maidenname'] = 'Nom de naissance';
+$labels['maidenname'] = 'Nom de jeune fille';
$labels['email'] = 'Courriel';
$labels['phone'] = 'Téléphone';
$labels['address'] = 'Adresse';
@@ -318,7 +321,7 @@ $labels['typeblog'] = 'Blog';
$labels['typeprofile'] = 'Profil';
$labels['addfield'] = 'Ajouter un champ...';
-$labels['addcontact'] = 'Ajouter le contact sélectionné à votre Carnet d\'adresses';
+$labels['addcontact'] = 'Ajouter le contact sélectionné à votre carnet d\'adresses';
$labels['editcontact'] = 'Modifier le contact';
$labels['contacts'] = 'Contacts';
$labels['contactproperties'] = 'Propriétés du contact';
@@ -331,7 +334,7 @@ $labels['delete'] = 'Supprimer';
$labels['rename'] = 'Renommer';
$labels['addphoto'] = 'Ajouter';
$labels['replacephoto'] = 'Remplacer';
-$labels['uploadphoto'] = 'Envoyer une photo';
+$labels['uploadphoto'] = 'Transférer une photo';
$labels['newcontact'] = 'Créer un nouveau contact';
$labels['deletecontact'] = 'Supprimer les contacts sélectionnés';
@@ -345,7 +348,7 @@ $labels['exportvcards'] = 'Exporter les contacts au format vCard';
$labels['newcontactgroup'] = 'Créer un nouveau groupe de contacts';
$labels['grouprename'] = 'Renommer le groupe';
$labels['groupdelete'] = 'Supprimer le groupe';
-$labels['groupremoveselected'] = 'Retiré les contacts sélectionnés du groupe';
+$labels['groupremoveselected'] = 'Retirer les contacts sélectionnés du groupe';
$labels['previouspage'] = 'Montrer page précédente';
$labels['firstpage'] = 'Voir la première page';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Voir la dernière page';
$labels['group'] = 'Groupe';
$labels['groups'] = 'Groupes';
+$labels['listgroup'] = 'Liste des membres du groupe';
$labels['personaladrbook'] = 'Adresses personnelles';
$labels['searchsave'] = 'Enregistrer la recherche';
@@ -362,9 +366,9 @@ $labels['searchdelete'] = 'Supprimer la recherche';
$labels['import'] = 'Importer';
$labels['importcontacts'] = 'Importer les contacts';
$labels['importfromfile'] = 'Importer depuis un fichier :';
-$labels['importtarget'] = 'Ajouter de nouveaux contact au carnet d’adresse :';
-$labels['importreplace'] = 'Remplacer le carnet d\'adresse entier';
-$labels['importdesc'] = 'Vous pouvez télécharger des contacts à partir d\'un carnet d\'adresses existant.<br/>Nous supportons actuellement l\'importation d\'adresses à partir des format de données <a href="http://en.wikipedia.org/wiki/VCard">vCard</a> ou CSV (comma -séparés).';
+$labels['importtarget'] = 'Ajouter de nouveaux contact au carnet d’adresses :';
+$labels['importreplace'] = 'Remplacer le carnet d\'adresses entier';
+$labels['importdesc'] = 'Vous pouvez transférer des contacts à partir d\'un carnet d\'adresses existant.<br/>Nous supportons actuellement l\'importation d\'adresses à partir des format de données <a href="http://en.wikipedia.org/wiki/VCard">vCard</a> ou CSV (champs séparés par une virgule).';
$labels['done'] = 'Terminé';
// settings
@@ -402,13 +406,13 @@ $labels['htmleditor'] = 'Composer un message au format HTML';
$labels['htmlonreply'] = 'en réponse aux messages HTML uniquement';
$labels['htmlonreplyandforward'] = 'Transférer ou répondre au message HTML';
$labels['htmlsignature'] = 'Signature HTML';
-$labels['showemail'] = 'Show email address with display name';
+$labels['showemail'] = 'Montrer l\'adresse de courriel avec le nom complet';
$labels['previewpane'] = 'Afficher le panneau d\'aperçu';
$labels['skin'] = 'Thème de l\'interface';
$labels['logoutclear'] = 'Vider la corbeille à la déconnexion';
$labels['logoutcompact'] = 'Compacter la boite de réception à la déconnexion';
$labels['uisettings'] = 'Interface utilisateur';
-$labels['serversettings'] = 'Préférences du serveur';
+$labels['serversettings'] = 'Paramètres du serveur';
$labels['mailboxview'] = 'Vue du courrier';
$labels['mdnrequests'] = 'Notifications à l\'expéditeur';
$labels['askuser'] = 'demander à l\'utilisateur';
@@ -452,7 +456,7 @@ $labels['whenreplying'] = 'En répondant';
$labels['replyempty'] = 'Ne pas citer le message original';
$labels['replytopposting'] = 'commencer le nouveau message au-dessus de l\'original';
$labels['replybottomposting'] = 'commencer le nouveau message en-dessous de l\'original';
-$labels['replyremovesignature'] = 'En répondant, supprimer la signature d\'origine du message';
+$labels['replyremovesignature'] = 'Supprimer la signature d\'origine du message lors de la réponse';
$labels['autoaddsignature'] = 'Ajouter la signature automatiquement';
$labels['newmessageonly'] = 'nouveau message uniquement';
$labels['replyandforwardonly'] = 'réponses et transferts uniquement';
@@ -462,16 +466,17 @@ $labels['afternseconds'] = 'après $n secondes';
$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['defaultabook'] = 'Carnet d\'adresse par défaut';
-$labels['autocompletesingle'] = 'Ne pas tenir compte des adresses emails alternatives dans l\'autoremplissage';
+$labels['defaultabook'] = 'Carnet d\'adresses par défaut';
+$labels['autocompletesingle'] = 'Ne pas tenir compte des adresses de courriel alternatives dans l\'autoremplissage';
$labels['listnamedisplay'] = 'Lister les contacts comme';
-$labels['spellcheckbeforesend'] = 'Vérifier l’orthographe avant l’envoie d’un message';
+$labels['spellcheckbeforesend'] = 'Vérifier l’orthographe avant l’envoi 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['mailtoprotohandler'] = 'Enregistrer le gestionnaire de protocole pour les liens mailto:';
+$labels['standardwindows'] = 'Manipuler les menus surgissants comme des fenêtres standards';
$labels['forwardmode'] = 'Transfert des messages';
$labels['inline'] = 'dans le corps';
$labels['asattachment'] = 'en pièce jointe';
@@ -507,7 +512,7 @@ $labels['plugin'] = 'Plugin';
$labels['version'] = 'Version';
$labels['source'] = 'Source';
$labels['license'] = 'Licence';
-$labels['support'] = 'Support';
+$labels['support'] = 'Obtenir un support technique';
// units
$labels['B'] = 'o';
diff --git a/program/localization/fy_NL/labels.inc b/program/localization/fy_NL/labels.inc
index 891371f58..5ffd906eb 100644
--- a/program/localization/fy_NL/labels.inc
+++ b/program/localization/fy_NL/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Konsepten';
$labels['sent'] = 'Stjoerd';
$labels['trash'] = 'Jiskefet';
$labels['junk'] = 'Junk';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'Ûnderwerp';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode';
$labels['folderactions'] = 'Folder actions...';
$labels['compact'] = 'Compact';
$labels['empty'] = 'Empty';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Disk usage';
$labels['unknown'] = 'unknown';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Reset search';
$labels['searchmod'] = 'Search modifiers';
$labels['msgtext'] = 'Entire message';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Open in new window';
$labels['emlsave'] = 'Download (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Show last page';
$labels['group'] = 'Group';
$labels['groups'] = 'Groups';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Personal Addresses';
$labels['searchsave'] = 'Save search';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers';
$labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized';
$labels['addtodict'] = 'Add to dictionary';
$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Messages forwarding';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'as attachment';
diff --git a/program/localization/fy_NL/messages.inc b/program/localization/fy_NL/messages.inc
index 1dacf4adc..16f4c67bf 100644
--- a/program/localization/fy_NL/messages.inc
+++ b/program/localization/fy_NL/messages.inc
@@ -2,15 +2,172 @@
/*
+-----------------------------------------------------------------------+
- | localization/fy_NL/messages.inc |
+ | localization/<lang>/messages.inc |
| |
- | Language file of the Roundcube Webmail client |
- | Copyright (C) 2012, The Roundcube Dev Team |
- | Licensed under the GNU General Public License |
+ | Localization file of the Roundcube Webmail client |
+ | Copyright (C) 2005-2013, The Roundcube Dev Team |
+ | |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
| |
+-----------------------------------------------------------------------+
- | Author: unknown |
- +-----------------------------------------------------------------------+
+
+ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/messages/
*/
-$messages = array(); \ No newline at end of file
+$messages = array();
+$messages['errortitle'] = 'An error occurred!';
+$messages['loginfailed'] = 'Login failed.';
+$messages['cookiesdisabled'] = 'Your browser does not accept cookies.';
+$messages['sessionerror'] = 'Your session is invalid or expired.';
+$messages['storageerror'] = 'Connection to storage server failed.';
+$messages['servererror'] = 'Server Error!';
+$messages['servererrormsg'] = 'Server Error: $msg';
+$messages['dberror'] = 'Database Error!';
+$messages['requesttimedout'] = 'Request timed out';
+$messages['errorreadonly'] = 'Unable to perform operation. Folder is read-only.';
+$messages['errornoperm'] = 'Unable to perform operation. Permission denied.';
+$messages['erroroverquota'] = 'Unable to perform operation. No free disk space.';
+$messages['erroroverquotadelete'] = 'No free disk space. Use SHIFT+DEL to delete a message.';
+$messages['invalidrequest'] = 'Invalid request! No data was saved.';
+$messages['invalidhost'] = 'Invalid server name.';
+$messages['nomessagesfound'] = 'No messages found in this mailbox.';
+$messages['loggedout'] = 'You have successfully terminated the session. Good bye!';
+$messages['mailboxempty'] = 'Mailbox is empty.';
+$messages['refreshing'] = 'Refreshing...';
+$messages['loading'] = 'Loading...';
+$messages['uploading'] = 'Uploading file...';
+$messages['uploadingmany'] = 'Uploading files...';
+$messages['loadingdata'] = 'Loading data...';
+$messages['checkingmail'] = 'Checking for new messages...';
+$messages['sendingmessage'] = 'Sending message...';
+$messages['messagesent'] = 'Message sent successfully.';
+$messages['savingmessage'] = 'Saving message...';
+$messages['messagesaved'] = 'Message saved to Drafts.';
+$messages['successfullysaved'] = 'Successfully saved.';
+$messages['addedsuccessfully'] = 'Contact added successfully to address book.';
+$messages['contactexists'] = 'A contact with the same e-mail address already exists.';
+$messages['contactnameexists'] = 'A contact with the same name already exists.';
+$messages['blockedimages'] = 'To protect your privacy, remote images are blocked in this message.';
+$messages['encryptedmessage'] = 'This is an encrypted message and can not be displayed. Sorry!';
+$messages['nocontactsfound'] = 'No contacts found.';
+$messages['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['errorsaving'] = 'An error occured while saving.';
+$messages['errormoving'] = 'Could not move the message(s).';
+$messages['errorcopying'] = 'Could not copy the message(s).';
+$messages['errordeleting'] = 'Could not delete the message(s).';
+$messages['errormarking'] = 'Could not mark the message(s).';
+$messages['deletecontactconfirm'] = 'Do you really want to delete selected contact(s)?';
+$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['contactdeleting'] = 'Deleting contact(s)...';
+$messages['groupdeleting'] = 'Deleting group...';
+$messages['folderdeleting'] = 'Deleting folder...';
+$messages['foldermoving'] = 'Moving folder...';
+$messages['foldersubscribing'] = 'Subscribing folder...';
+$messages['folderunsubscribing'] = 'Unsubscribing folder...';
+$messages['formincomplete'] = 'The form was not completely filled out.';
+$messages['noemailwarning'] = 'Please enter a valid email address.';
+$messages['nonamewarning'] = 'Please enter a name.';
+$messages['nopagesizewarning'] = 'Please enter a page size.';
+$messages['nosenderwarning'] = 'Please enter sender e-mail address.';
+$messages['norecipientwarning'] = 'Please enter at least one recipient.';
+$messages['nosubjectwarning'] = 'The "Subject" field is empty. Would you like to enter one now?';
+$messages['nobodywarning'] = 'Send this message without text?';
+$messages['notsentwarning'] = 'Message has not been sent. Do you want to discard your message?';
+$messages['noldapserver'] = 'Please select an ldap server to search.';
+$messages['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['nospellerrors'] = 'No spelling errors found.';
+$messages['folderdeleted'] = 'Folder successfully deleted.';
+$messages['foldersubscribed'] = 'Folder successfully subscribed.';
+$messages['folderunsubscribed'] = 'Folder successfully unsubscribed.';
+$messages['folderpurged'] = 'Folder has successfully been emptied.';
+$messages['folderexpunged'] = 'Folder has successfully been compacted.';
+$messages['deletedsuccessfully'] = 'Successfully deleted.';
+$messages['converting'] = 'Removing formatting...';
+$messages['messageopenerror'] = 'Could not load message from server.';
+$messages['fileuploaderror'] = 'File upload failed.';
+$messages['filesizeerror'] = 'The uploaded file exceeds the maximum size of $size.';
+$messages['copysuccess'] = 'Successfully copied $nr addresses.';
+$messages['copyerror'] = 'Could not copy any addresses.';
+$messages['sourceisreadonly'] = 'This address source is read only.';
+$messages['errorsavingcontact'] = 'Could not save the contact address.';
+$messages['movingmessage'] = 'Moving message(s)...';
+$messages['copyingmessage'] = 'Copying message(s)...';
+$messages['copyingcontact'] = 'Copying contact(s)...';
+$messages['deletingmessage'] = 'Deleting message(s)...';
+$messages['markingmessage'] = 'Marking message(s)...';
+$messages['addingmember'] = 'Adding contact(s) to the group...';
+$messages['removingmember'] = 'Removing contact(s) from the group...';
+$messages['receiptsent'] = 'Successfully sent a read receipt.';
+$messages['errorsendingreceipt'] = 'Could not send the receipt.';
+$messages['deleteidentityconfirm'] = 'Do you really want to delete this identity?';
+$messages['nodeletelastidentity'] = 'You cannot delete this identity, it\'s your last one.';
+$messages['forbiddencharacter'] = 'Folder name contains a forbidden character.';
+$messages['selectimportfile'] = 'Please select a file to upload.';
+$messages['addresswriterror'] = 'The selected address book is not writeable.';
+$messages['contactaddedtogroup'] = 'Successfully added the contacts to this group.';
+$messages['contactremovedfromgroup'] = 'Successfully removed contacts from this group.';
+$messages['nogroupassignmentschanged'] = 'No group assignments changed.';
+$messages['importwait'] = 'Importing, please wait...';
+$messages['importformaterror'] = 'Import failed! The uploaded file is not a valid import data file.';
+$messages['importconfirm'] = '<b>Successfully imported $inserted contacts</b>';
+$messages['importconfirmskipped'] = '<b>Skipped $skipped existing entries</b>';
+$messages['importmessagesuccess'] = 'Successfully imported $nr messages';
+$messages['importmessageerror'] = 'Import failed! The uploaded file is not a valid message or mailbox file';
+$messages['opnotpermitted'] = 'Operation not permitted!';
+$messages['nofromaddress'] = 'Missing e-mail address in selected identity.';
+$messages['editorwarning'] = 'Switching to the plain text editor will cause all text formatting to be lost. Do you wish to continue?';
+$messages['httpreceivedencrypterror'] = 'A fatal configuration error occurred. Contact your administrator immediately. <b>Your message can not be sent.</b>';
+$messages['smtpconnerror'] = 'SMTP Error ($code): Connection to server failed.';
+$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['smtperror'] = 'SMTP Error: $msg';
+$messages['emailformaterror'] = 'Invalid e-mail address: $email';
+$messages['toomanyrecipients'] = 'Too many recipients. Reduce the number of recipients to $max.';
+$messages['maxgroupmembersreached'] = 'The number of group members exceeds the maximum of $max.';
+$messages['internalerror'] = 'An internal error occured. Please try again.';
+$messages['contactdelerror'] = 'Could not delete contact(s).';
+$messages['contactdeleted'] = 'Contact(s) deleted successfully.';
+$messages['contactrestoreerror'] = 'Could not restore deleted contact(s).';
+$messages['contactrestored'] = 'Contact(s) restored 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['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['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['messagetoobig'] = 'The message part is too big to process it.';
+$messages['attachmentvalidationerror'] = 'WARNING! This attachment is suspicious because its type doesn\'t match the type declared in the message. If you do not trust the sender, you shouldn\'t open it in the browser because it may contain malicious contents.<br/><br/><em>Expected: $expected; found: $detected</em>';
+$messages['noscriptwarning'] = 'Warning: This webmail service requires Javascript! In order to use it please enable Javascript in your browser\'s settings.';
+
+?>
diff --git a/program/localization/ga_IE/labels.inc b/program/localization/ga_IE/labels.inc
index 9f0da6550..9fffaf42a 100755
--- a/program/localization/ga_IE/labels.inc
+++ b/program/localization/ga_IE/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Dréachtaí';
$labels['sent'] = 'Amach';
$labels['trash'] = 'Bosca bruscair';
$labels['junk'] = 'Dramhaíl';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'Ãbhair';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode';
$labels['folderactions'] = 'Folder actions...';
$labels['compact'] = 'Comhbhrúigh';
$labels['empty'] = 'Folmhaigh';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Toilleadh diosca atá athláimhe';
$labels['unknown'] = 'gan aithne';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Athshocraigh an cuardach';
$labels['searchmod'] = 'Search modifiers';
$labels['msgtext'] = 'Entire message';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Open in new window';
$labels['emlsave'] = 'Download (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Taispeáin an foireann deireanach';
$labels['group'] = 'Group';
$labels['groups'] = 'Grúpaí';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Seoltaí Pearsanta';
$labels['searchsave'] = 'Save search';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers';
$labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized';
$labels['addtodict'] = 'Add to dictionary';
$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Messages forwarding';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'as attachment';
diff --git a/program/localization/gl_ES/labels.inc b/program/localization/gl_ES/labels.inc
index 5905ea4b9..c624c462e 100644
--- a/program/localization/gl_ES/labels.inc
+++ b/program/localization/gl_ES/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Borradores';
$labels['sent'] = 'Enviados';
$labels['trash'] = 'Cubo do lixo';
$labels['junk'] = 'Correo lixo';
+$labels['show_real_foldernames'] = 'Amosar nomes reáis para cartafois especiáis';
// message listing
$labels['subject'] = 'Asunto';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'Modo de vista da lista';
$labels['folderactions'] = 'Accións cos cartafoles';
$labels['compact'] = 'Compactar';
$labels['empty'] = 'Baleirar';
+$labels['importmessages'] = 'Importar mensaxes';
$labels['quota'] = 'Uso de disco';
$labels['unknown'] = 'descoñecido';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Restablecer a busca';
$labels['searchmod'] = 'Modificadores de busca';
$labels['msgtext'] = 'Mensaxe enteira';
$labels['body'] = 'Corpo';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Abrir nunha nova fiestra';
$labels['emlsave'] = 'Gardar (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Amosar o último grupo';
$labels['group'] = 'Grupo';
$labels['groups'] = 'Grupos';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Enderezos persoais';
$labels['searchsave'] = 'Gardar procura';
@@ -402,7 +406,7 @@ $labels['htmleditor'] = 'Redactar mensaxes HTML';
$labels['htmlonreply'] = 'só cando se resposte a unha mensaxe HTML';
$labels['htmlonreplyandforward'] = 'ao reenviar ou respostar a unha mensaxe HTML';
$labels['htmlsignature'] = 'Sinatura HTML';
-$labels['showemail'] = 'Show email address with display name';
+$labels['showemail'] = 'Amosar enderezo de correo co nome en pantalla';
$labels['previewpane'] = 'Amosar previsualización';
$labels['skin'] = 'Aspecto da interface';
$labels['logoutclear'] = 'Baleirar o cubo do lixo ao saír';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignorar as palabras con números';
$labels['spellcheckignorecaps'] = 'Ignorar as palabras escritas en maiúsculas';
$labels['addtodict'] = 'Engadir ao diccionario';
$labels['mailtoprotohandler'] = 'Rexistrar o manexador de protocolo para as ligazóns "mailto:"';
+$labels['standardwindows'] = 'Manexar avisos emerxentes como xanelas estándar';
$labels['forwardmode'] = 'Reenvio de mensaxes';
$labels['inline'] = 'inserido';
$labels['asattachment'] = 'coma anexo';
diff --git a/program/localization/gl_ES/messages.inc b/program/localization/gl_ES/messages.inc
index 207a016a1..8fc2cb424 100644
--- a/program/localization/gl_ES/messages.inc
+++ b/program/localization/gl_ES/messages.inc
@@ -126,6 +126,8 @@ $messages['importwait'] = 'A importar. Por favor, agarde...';
$messages['importformaterror'] = 'Fallou a importación! O ficheiro cargado non contén datos válidos.';
$messages['importconfirm'] = '<b>Importáronse correctamente $inserted contactos. Ignoráronse $skipped contactos que xa existían</b>:<p><em>$names</em></p>';
$messages['importconfirmskipped'] = '<b>Ignoráronse $skipped existing entradas</b>';
+$messages['importmessagesuccess'] = 'Importados $nr mensaxes con éxito';
+$messages['importmessageerror'] = 'Fallou a importación! O arquivo subido non é unha mensaxe válida ou un ficheiro de caixa de correo';
$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?';
diff --git a/program/localization/he_IL/labels.inc b/program/localization/he_IL/labels.inc
index bfb9e2fef..7ad04ab4a 100644
--- a/program/localization/he_IL/labels.inc
+++ b/program/localization/he_IL/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'טיוטות';
$labels['sent'] = 'נשלח';
$labels['trash'] = '×שפה';
$labels['junk'] = 'זבל';
+$labels['show_real_foldernames'] = 'הצגת שמות ××ž×™×ª×™×™× ×©×œ תיקיות מיוחדות';
// message listing
$labels['subject'] = 'נוש×';
@@ -193,6 +194,7 @@ $labels['listmode'] = '×ופן הצגת רשימה';
$labels['folderactions'] = 'פעולות על תיקי×';
$labels['compact'] = 'פינוי שטח ×œ× ×ž× ×•×¦×œ';
$labels['empty'] = 'ריקון';
+$labels['importmessages'] = '×™×™×‘×•× ×”×•×“×¢×•×ª';
$labels['quota'] = 'ניצול קיבולת';
$labels['unknown'] = '×œ× ×™×“×•×¢';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'ניקוי תיבת החיפוש';
$labels['searchmod'] = 'מ×פייני חיפוש';
$labels['msgtext'] = 'כל ההודעה';
$labels['body'] = 'גוף ההודעה';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'פתיחה בחלון חדש';
$labels['emlsave'] = 'הורדת הודעה בפורמט EML';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'הצגת הקבוצה ×”×חרונה';
$labels['group'] = 'קבוצה';
$labels['groups'] = 'קבוצות';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'כתובות פרטיות';
$labels['searchsave'] = 'שמירת החיפוש';
@@ -474,6 +478,7 @@ $labels['spellcheckignorenums'] = 'התעלמות ×ž×ž×™×œ×™× ×”×ž×›×™×œ×•×ª מ
$labels['spellcheckignorecaps'] = 'התעלמות ×ž×ž×™×œ×™× ×¢× ×ותציות ר×שיות';
$labels['addtodict'] = 'הוספה למילון';
$labels['mailtoprotohandler'] = 'קביעת הפרוטוקול לטיפול בקישור מסוג mailto:links';
+$labels['standardwindows'] = 'חלונות ×§×•×¤×¦×™× ×™×˜×•×¤×œ×• כחלונות רגילי×';
$labels['forwardmode'] = 'הפנית הודעות';
$labels['inline'] = 'חלק מההודעה';
$labels['asattachment'] = 'כצרופה';
diff --git a/program/localization/he_IL/messages.inc b/program/localization/he_IL/messages.inc
index 7d9b87c06..37ebcea01 100644
--- a/program/localization/he_IL/messages.inc
+++ b/program/localization/he_IL/messages.inc
@@ -126,6 +126,8 @@ $messages['importwait'] = 'ייבו×, × × ×œ×”×ž×ª×™×Ÿ..';
$messages['importformaterror'] = '×”×™×‘×•× × ×›×©×œ ! הקובץ שהועלה ×ינו מת××™×.';
$messages['importconfirm'] = '<b>יוב×ו $inserted ×נשי קשר, $skipped היו ×§×™×™×ž×™× </b>:<p><em>$names</em></p>';
$messages['importconfirmskipped'] = '<b> דילוג של $skipped × ×ª×•× ×™× ×§×™×™×ž×™× <b>';
+$messages['importmessagesuccess'] = 'יוב×ו בהצלחה $nr הודעות ';
+$messages['importmessageerror'] = '×”×™×‘×•× × ×›×©×œ ! הקובץ שהועלה ×ינו הודעה ×ו קובץ הודעות במבנה מת××™×';
$messages['opnotpermitted'] = 'פעולה ×סורה!';
$messages['nofromaddress'] = 'לזהות שנבחרה חסרה כתובת דו×ר';
$messages['editorwarning'] = 'המעבר לעורך רגיל ×™×’×¨×•× ×œ×יבוד ×ת העריכה הקיימת. ×”×× ×œ×”×ž×©×™×š?';
diff --git a/program/localization/hi_IN/labels.inc b/program/localization/hi_IN/labels.inc
index 3b8279f71..303e0b5fb 100644
--- a/program/localization/hi_IN/labels.inc
+++ b/program/localization/hi_IN/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'डà¥à¤°à¤¾à¤«à¤¼à¤Ÿ';
$labels['sent'] = 'भेजा गया';
$labels['trash'] = 'रदà¥à¤¦à¥€';
$labels['junk'] = 'सà¥à¤ªà¥ˆà¤®';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'विशय';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode';
$labels['folderactions'] = 'Folder actions...';
$labels['compact'] = 'छोटा करें';
$labels['empty'] = 'मेल रदà¥à¤¦à¥€ में डालें';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'डिसà¥à¤• उपयोग';
$labels['unknown'] = 'अजà¥à¤žà¤¾à¤¤';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'खोज खाली करें';
$labels['searchmod'] = 'Search modifiers';
$labels['msgtext'] = 'Entire message';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Open in new window';
$labels['emlsave'] = 'Download (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'आखिरी बनà¥à¤¡à¤² दिखाà¤à¤‚'
$labels['group'] = 'Group';
$labels['groups'] = 'Groups';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Personal Addresses';
$labels['searchsave'] = 'Save search';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers';
$labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized';
$labels['addtodict'] = 'Add to dictionary';
$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Messages forwarding';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'as attachment';
diff --git a/program/localization/hr_HR/labels.inc b/program/localization/hr_HR/labels.inc
index 506d50f1f..4578fed2b 100644
--- a/program/localization/hr_HR/labels.inc
+++ b/program/localization/hr_HR/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Predlošci';
$labels['sent'] = 'Poslano';
$labels['trash'] = 'Smeće';
$labels['junk'] = 'Spam';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'Naslov';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'Model pregleda listi';
$labels['folderactions'] = 'Akcije mapa';
$labels['compact'] = 'Kompresiranje';
$labels['empty'] = 'Isprazni';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Kvota';
$labels['unknown'] = 'nepoznato';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Prikaži sve poruke';
$labels['searchmod'] = 'Postavke pretrage';
$labels['msgtext'] = 'Cijela poruka';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Otvori u novom prozoru';
$labels['emlsave'] = 'Download (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Zadnja strana';
$labels['group'] = 'Grupa';
$labels['groups'] = 'Grupe';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Privatna adresa';
$labels['searchsave'] = 'Pohrani pretragu';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignoriraj rijeÄi koje sadrže brojeve';
$labels['spellcheckignorecaps'] = 'Ignoriraj rijeÄi sa sa svim velikim slovima';
$labels['addtodict'] = 'Dodaj u rjeÄnik';
$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Messages forwarding';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'as attachment';
diff --git a/program/localization/hu_HU/labels.inc b/program/localization/hu_HU/labels.inc
index 3cc5da1aa..abdc7e891 100644
--- a/program/localization/hu_HU/labels.inc
+++ b/program/localization/hu_HU/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Piszkozatok';
$labels['sent'] = 'Küldött levelek';
$labels['trash'] = 'Törölt elemek';
$labels['junk'] = 'Kéretlen levelek';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'Tárgy';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'Megjelenítési mód';
$labels['folderactions'] = 'Mappaműveletek...';
$labels['compact'] = 'Tömörítés';
$labels['empty'] = 'Kiürítés';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Helyfoglalás';
$labels['unknown'] = 'ismeretlen';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Alapállapot';
$labels['searchmod'] = 'Keresési opciók';
$labels['msgtext'] = 'Teljes üzenet';
$labels['body'] = 'Törzs';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Megnyitás új ablakban';
$labels['emlsave'] = 'Letöltés (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Utolsó oldal';
$labels['group'] = 'Csoport';
$labels['groups'] = 'Csoportok';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Személyes címjegyzék';
$labels['searchsave'] = 'Keresés mentése';
@@ -472,6 +476,7 @@ $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['mailtoprotohandler'] = 'Beállítás a mailto: linkek kezelőjeként';
+$labels['standardwindows'] = 'A felugró ablakok használata szokásos ablakként';
$labels['forwardmode'] = 'Üzenet továbbítás';
$labels['inline'] = 'beágyazott';
$labels['asattachment'] = 'csatolmányként';
diff --git a/program/localization/hy_AM/labels.inc b/program/localization/hy_AM/labels.inc
index 99cee4ab9..8ee9316c4 100644
--- a/program/localization/hy_AM/labels.inc
+++ b/program/localization/hy_AM/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'ÕÖ‡Õ¡Õ£Ö€Õ¥Ö€';
$labels['sent'] = 'ÕˆÖ‚Õ²Õ¡Ö€Õ¯Õ¾Õ¡Õ®';
$labels['trash'] = 'Ô±Õ²Õ¢Õ¡Ö€Õ¯Õ²';
$labels['junk'] = 'Ô¹Õ¡ÖƒÕ¸Õ¶';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'ÕŽÕ¥Ö€Õ¶Õ¡Õ£Õ«Ö€';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'Õ‘Õ¸Ö‚ÖÕ¡Õ¯Õ¸Õ¾ Õ¿Õ¥Õ½Ö„Õ« Õ¿Õ¡Ö€Õ¢Õ¥Ö€Õ¡Õ¯Õ¨';
$labels['folderactions'] = 'Պանակի գործողություններ…';
$labels['compact'] = 'ÕÕ¥Õ²Õ´Õ¥Õ¬';
$labels['empty'] = 'Ô´Õ¡Õ¿Õ¡Ö€Õ¯Õ¥Õ¬';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Ô´Õ«Õ½Õ¯Õ¡ÕµÕ«Õ¶ Õ¿Õ¡Ö€Õ¡Õ®Ö„';
$labels['unknown'] = 'Õ¡Õ¶Õ°Õ¡ÕµÕ¿';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'ÕŽÕ¥Ö€Õ½Õ¯Õ½Õ¥Õ¬ Õ¸Ö€Õ¸Õ¶Õ¸Ö‚Õ´Õ¨';
$labels['searchmod'] = 'ÕˆÖ€Õ¸Õ¶Õ´Õ¡Õ¶ ÖƒÕ¸ÖƒÕ¸Õ­Õ«Õ¹Õ¶Õ¥Ö€';
$labels['msgtext'] = 'ÕˆÕ²Õ» Õ°Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Ô²Õ¡ÖÕ¥Õ¬ Õ¶Õ¸Ö€ ÕºÕ¡Õ¿Õ¸Ö‚Õ°Õ¡Õ¶Õ¸Ö‚Õ´';
$labels['emlsave'] = 'Õ†Õ¥Ö€Õ¢Õ¥Õ¼Õ¶Õ¥Õ¬ (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ Õ¾Õ¥Ö€Õ»Õ«Õ¶ Õ§Õ»Õ¨';
$labels['group'] = 'Ô½Õ¸Ö‚Õ´Õ¢';
$labels['groups'] = 'Ô½Õ´Õ¢Õ¥Ö€';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Ô±Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ°Õ¡Õ½ÖÕ¥Õ¶Õ¥Ö€';
$labels['searchsave'] = 'ÕŠÕ¡Õ°ÕºÕ¡Õ¶Õ¥Õ¬ Õ¸Ö€Õ¸Õ¶Õ¸Ö‚Õ´Õ¨';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ô±Õ¶Õ¿Õ¥Õ½Õ¥Õ¬ Õ©Õ¾Õ¥Ö€Õ¸Õ¾ Õ¢Õ¡Õ¼Õ¥Ö€Õ¨';
$labels['spellcheckignorecaps'] = 'Ô±Õ¶Õ¿Õ¥Õ½Õ¥Õ¬ Õ¬Ö€Õ«Õ¾ Õ´Õ¥Õ®Õ¡Õ¿Õ¡Õ¼ Õ¢Õ¡Õ¼Õ¥Ö€Õ¨';
$labels['addtodict'] = 'Ô±Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬ Õ¢Õ¡Õ¼Õ¡Ö€Õ¡Õ¶Õ¸Ö‚Õ´';
$labels['mailtoprotohandler'] = 'mailto: Õ°Õ²Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ« Õ½ÕºÕ¡Õ½Õ¡Ö€Õ¯Õ¸Õ²';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Messages forwarding';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'as attachment';
diff --git a/program/localization/ia/labels.inc b/program/localization/ia/labels.inc
index 2a9501168..1cd614d35 100644
--- a/program/localization/ia/labels.inc
+++ b/program/localization/ia/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Drafts';
$labels['sent'] = 'Inviate';
$labels['trash'] = 'Trash';
$labels['junk'] = 'Junk';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'Subjecto';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode';
$labels['folderactions'] = 'Actiones de dossier...';
$labels['compact'] = 'Compacte';
$labels['empty'] = 'Vacue';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Disk usage';
$labels['unknown'] = 'incognite';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Reinitialisar cerca';
$labels['searchmod'] = 'Search modifiers';
$labels['msgtext'] = 'Message complete';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Aperir in nove fenestra';
$labels['emlsave'] = 'Download (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Show last page';
$labels['group'] = 'Gruppo';
$labels['groups'] = 'Gruppos';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Adresses personal';
$labels['searchsave'] = 'Salveguardar cerca';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers';
$labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized';
$labels['addtodict'] = 'Adder al dictionario';
$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Messages forwarding';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'as attachment';
diff --git a/program/localization/id_ID/labels.inc b/program/localization/id_ID/labels.inc
index eea3132cd..73bb0156d 100644
--- a/program/localization/id_ID/labels.inc
+++ b/program/localization/id_ID/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Daftar tunggu';
$labels['sent'] = 'Terkirim';
$labels['trash'] = 'Surat Terhapus';
$labels['junk'] = 'Sampah';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'Judul';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'Perlihatkan mode tinjauan';
$labels['folderactions'] = 'Tindakan pada folder...';
$labels['compact'] = 'Rampingkan';
$labels['empty'] = 'Kosong';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Penggunaan ruang';
$labels['unknown'] = 'Tidak dikenal';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Atur ulang pencarian';
$labels['searchmod'] = 'Peubah pencarian';
$labels['msgtext'] = 'Seluruh pesan';
$labels['body'] = 'Badan';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Buka dalam jendela baru';
$labels['emlsave'] = 'Unduh (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Perlihatkan himpunan terakhir';
$labels['group'] = 'Kelompok';
$labels['groups'] = 'Kelompok';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Alamat pribadi';
$labels['searchsave'] = 'Simpan pencarian';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Abaikan kata-kata yang bernomor';
$labels['spellcheckignorecaps'] = 'Abaikan kata-kata dengan huruf besar semua';
$labels['addtodict'] = 'Tambahkan ke kamus';
$labels['mailtoprotohandler'] = 'Daftarkan pengampu protokol untuk link mailto:';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Meneruskan pesan';
$labels['inline'] = 'dalam surat';
$labels['asattachment'] = 'sebagai sisipan';
diff --git a/program/localization/index.inc b/program/localization/index.inc
index bfb770cac..4b848dc49 100644
--- a/program/localization/index.inc
+++ b/program/localization/index.inc
@@ -70,6 +70,7 @@ $rcube_languages = array(
'ku' => 'Kurdish (Kurmancî)',
'lv_LV' => 'Latvian (Latviešu)',
'lt_LT' => 'Lithuanian (Lietuviškai)',
+ 'lb_LU' => 'Luxembourgish (Lëtzebuergesch)',
'mk_MK' => 'Macedonian (МакедонÑки)',
'ms_MY' => 'Malay (Bahasa Melayu)',
'ml_IN' => 'Malayalam (മലയാളം)',
@@ -133,6 +134,7 @@ $rcube_language_aliases = array(
'kh' => 'km_KH',
'kh_KH' => 'km_KH',
'km' => 'km_KH',
+ 'lb' => 'lb_LU',
'ne' => 'ne_NP',
'no' => 'nn_NO',
'ms' => 'ms_MY',
diff --git a/program/localization/is_IS/labels.inc b/program/localization/is_IS/labels.inc
index 80443dd3a..c2859ce75 100644
--- a/program/localization/is_IS/labels.inc
+++ b/program/localization/is_IS/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Drög';
$labels['sent'] = 'Sent';
$labels['trash'] = 'Rusl';
$labels['junk'] = 'Ruslpóstur';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'Titill';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'Listayfirlit';
$labels['folderactions'] = 'Möppuaðgerðir...';
$labels['compact'] = 'Pakka';
$labels['empty'] = 'Tæma';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Gagnamagn';
$labels['unknown'] = 'óþekkt';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Tæma leit';
$labels['searchmod'] = 'Leitarskilyrði';
$labels['msgtext'] = 'Allt skeytið';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Opna í nýjum glugga';
$labels['emlsave'] = 'Niðurhlaða (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Sýna síðustu síðu';
$labels['group'] = 'Hópur';
$labels['groups'] = 'Hópar';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Persónuleg heimilisföng';
$labels['searchsave'] = 'Vista leit';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Hunsa orð með tölum';
$labels['spellcheckignorecaps'] = 'Hunsa orð sem eru í hástöfum';
$labels['addtodict'] = 'Bæta við orðalista';
$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Messages forwarding';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'as attachment';
diff --git a/program/localization/it_IT/labels.inc b/program/localization/it_IT/labels.inc
index 75a24c5fd..55cd432f7 100644
--- a/program/localization/it_IT/labels.inc
+++ b/program/localization/it_IT/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Bozze';
$labels['sent'] = 'Inviata';
$labels['trash'] = 'Cestino';
$labels['junk'] = 'Spam';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'Oggetto';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'Modalità di visualizzazione';
$labels['folderactions'] = 'Operazioni cartella';
$labels['compact'] = 'Compatta';
$labels['empty'] = 'Svuota';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Spazio utilizzato';
$labels['unknown'] = 'sconosciuto';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Annulla ricerca';
$labels['searchmod'] = 'Ambito di ricerca';
$labels['msgtext'] = 'Intero messaggio';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Apri in una nuova finestra';
$labels['emlsave'] = 'Scarica (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Ultima pagina';
$labels['group'] = 'Gruppo';
$labels['groups'] = 'Gruppi';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Rubrica Personale';
$labels['searchsave'] = 'Salva ricerca';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignora le parole contenenti numeri';
$labels['spellcheckignorecaps'] = 'Ignora le parole con tutte le lettere maiuscole';
$labels['addtodict'] = 'Aggiungi al dizionario';
$labels['mailtoprotohandler'] = 'Registra gestore per mailto:';
+$labels['standardwindows'] = 'Gestisci i popup come finestre standard';
$labels['forwardmode'] = 'Inoltro messaggi';
$labels['inline'] = 'In linea';
$labels['asattachment'] = 'come allegato';
diff --git a/program/localization/ja_JP/labels.inc b/program/localization/ja_JP/labels.inc
index 6998f0623..767aff23a 100644
--- a/program/localization/ja_JP/labels.inc
+++ b/program/localization/ja_JP/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = '下書ã';
$labels['sent'] = 'é€ä¿¡æ¸ˆã¿';
$labels['trash'] = 'ã”ã¿ç®±';
$labels['junk'] = '迷惑メール';
+$labels['show_real_foldernames'] = '特殊フォルダーã®å®Ÿéš›ã®åå‰ã‚’表示';
// message listing
$labels['subject'] = '件å';
@@ -193,6 +194,7 @@ $labels['listmode'] = '一覧表示モード';
$labels['folderactions'] = 'フォルダーã®æ“作...';
$labels['compact'] = '圧縮';
$labels['empty'] = '空';
+$labels['importmessages'] = 'メッセージをインãƒãƒ¼ãƒˆ';
$labels['quota'] = 'ディスクã®ä½¿ç”¨çŠ¶æ³';
$labels['unknown'] = 'ä¸æ˜Ž';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = '検索を解除';
$labels['searchmod'] = '検索ã®æ¡ä»¶';
$labels['msgtext'] = 'メッセージ全体';
$labels['body'] = '本文';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'æ–°ã—ã„ウィンドウã§é–‹ã';
$labels['emlsave'] = 'ダウンロード(.emlå½¢å¼)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = '最後ã®ãƒšãƒ¼ã‚¸ã‚’表示';
$labels['group'] = 'グループ';
$labels['groups'] = 'グループ';
+$labels['listgroup'] = 'グループã®ãƒ¡ãƒ³ãƒãƒ¼ã‚’一覧';
$labels['personaladrbook'] = '個人ã®ä½æ‰€';
$labels['searchsave'] = '検索情報をä¿å­˜';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'æ•°å­—ã‚’å«ã‚€å˜èªžã‚’無視';
$labels['spellcheckignorecaps'] = 'ã™ã¹ã¦å¤§æ–‡å­—ã®å˜èªžã‚’無視';
$labels['addtodict'] = '辞書ã«è¿½åŠ ';
$labels['mailtoprotohandler'] = 'mailto: ã®ãƒªãƒ³ã‚¯ã‚’扱ã†ãƒ—ロトコル処ç†ã®ç™»éŒ²';
+$labels['standardwindows'] = 'ãƒãƒƒãƒ—アップを通常ã®ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã¨ã—ã¦å‡¦ç†';
$labels['forwardmode'] = 'メッセージã®è»¢é€å½¢å¼';
$labels['inline'] = 'インライン';
$labels['asattachment'] = '添付ファイル';
diff --git a/program/localization/ka_GE/labels.inc b/program/localization/ka_GE/labels.inc
index 3ab3b6e63..b0126c44e 100755
--- a/program/localization/ka_GE/labels.inc
+++ b/program/localization/ka_GE/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'დრáƒáƒ”ბითი';
$labels['sent'] = 'გáƒáƒ’ზáƒáƒ•áƒœáƒ˜áƒšáƒ˜';
$labels['trash'] = 'წáƒáƒ¨áƒšáƒ˜áƒšáƒ˜';
$labels['junk'] = 'სპáƒáƒ›áƒ˜';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'სáƒáƒ—áƒáƒ£áƒ áƒ˜';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode';
$labels['folderactions'] = 'Folder actions...';
$labels['compact'] = 'შეკუმშვáƒ';
$labels['empty'] = 'გáƒáƒªáƒáƒ áƒ˜áƒ”ლებáƒ';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'შეზღუდვáƒ';
$labels['unknown'] = 'უცნáƒáƒ‘ი';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'ძიების გáƒáƒ¡áƒ£áƒ¤áƒ—áƒáƒ•áƒ”ბáƒ'
$labels['searchmod'] = 'ძებნის ვáƒáƒ áƒ˜áƒáƒœáƒ¢áƒ”ბი';
$labels['msgtext'] = 'ყველრშეტყáƒáƒ‘ინებáƒ';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'გáƒáƒ®áƒ¡áƒœáƒ áƒáƒ®áƒáƒš ფáƒáƒœáƒ¯áƒáƒ áƒáƒ¨áƒ˜';
$labels['emlsave'] = 'გáƒáƒ“მáƒáƒ¬áƒ”რრ(.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'ბáƒáƒšáƒáƒ¡ ჩვენებáƒ';
$labels['group'] = 'ჯგუფი';
$labels['groups'] = 'ჯგუფები';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'პერსáƒáƒœáƒáƒšáƒ£áƒ áƒ˜ მისáƒáƒ›áƒáƒ áƒ—ები';
$labels['searchsave'] = 'ძებნის შენáƒáƒ®áƒ•áƒ';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers';
$labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized';
$labels['addtodict'] = 'ლექსიკáƒáƒœáƒ¨áƒ˜ დáƒáƒ›áƒáƒ¢áƒ”ბáƒ';
$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Messages forwarding';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'as attachment';
diff --git a/program/localization/km_KH/labels.inc b/program/localization/km_KH/labels.inc
index 7b10b5f7f..bc2836a53 100644
--- a/program/localization/km_KH/labels.inc
+++ b/program/localization/km_KH/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'សំបុážáŸ’រពង្រៀង';
$labels['sent'] = 'សំបុážáŸ’រដែលបានបញ្ជូន';
$labels['trash'] = 'ធុងសំរាម';
$labels['junk'] = 'សំបុážáŸ’រមិនល្អ';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'ចំណងជើង';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'បង្ហាញជាážáž¶ážšáž¶áž„';
$labels['folderactions'] = 'មុážáž„ារážáž';
$labels['compact'] = 'បង្រួម';
$labels['empty'] = 'áž‘áž‘áŸážš';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'ទំហំសំបុážáŸ’រទាំងអស់ដែលមាន';
$labels['unknown'] = 'មិនស្គាល់';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'កំណážáŸ‹áž›áž€áŸ’ážážáŸážŽáŸ’ឌស្វáŸ
$labels['searchmod'] = 'កែសំរួលលក្ážážáŸážŽáŸ’ឌស្វែងរក';
$labels['msgtext'] = 'សំបុážáŸ’រទាំងមូល';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'បើកក្នុងវីនដូវážáŸ’មី';
$labels['emlsave'] = 'រក្សាទុកទិន្ននáŸáž™áž‡áž¶áž¯áž€ážŸáž¶ážšáž”្រភáŸáž‘(.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'ទំពáŸážšáž…ុងក្រោយ';
$labels['group'] = 'ក្រុម';
$labels['groups'] = 'ក្រុម';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'អាសយដ្ឋានផ្ទាល់ážáŸ’លួន';
$labels['searchsave'] = 'Save search';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers';
$labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized';
$labels['addtodict'] = 'Add to dictionary';
$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Messages forwarding';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'as attachment';
diff --git a/program/localization/ko_KR/labels.inc b/program/localization/ko_KR/labels.inc
index 950928767..60a9275ac 100644
--- a/program/localization/ko_KR/labels.inc
+++ b/program/localization/ko_KR/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = '임시 보관함';
$labels['sent'] = '보낸 편지함';
$labels['trash'] = '휴지통';
$labels['junk'] = '스팸 편지함';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = '제목';
@@ -193,6 +194,7 @@ $labels['listmode'] = '화면 모드 ëª©ë¡ ë³´ê¸°';
$labels['folderactions'] = 'í´ë” 명령';
$labels['compact'] = '간단하게';
$labels['empty'] = '비어 있ìŒ';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'ë””ìŠ¤í¬ ì‚¬ìš©ëŸ‰';
$labels['unknown'] = 'ì•Œ 수 ì—†ìŒ';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = '검색 재설정';
$labels['searchmod'] = 'ìˆ˜ì •ìž ê²€ìƒ‰';
$labels['msgtext'] = '전체 메시지';
$labels['body'] = '본문';
+$labels['type'] = 'Type';
$labels['openinextwin'] = '새 ì°½ì—ì„œ 열기';
$labels['emlsave'] = '다운로드(.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = '마지막 페ì´ì§€ 보기';
$labels['group'] = '그룹';
$labels['groups'] = '그룹';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'ê°œì¸ ì£¼ì†Œ';
$labels['searchsave'] = '검색 저장';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = '숫ìžê°€ í¬í•¨ëœ 단어 무시';
$labels['spellcheckignorecaps'] = 'ëª¨ë‘ ëŒ€ë¬¸ìžë¡œ í‘œê¸°ëœ ë‹¨ì–´ 무시';
$labels['addtodict'] = 'ì‚¬ì „ì— ì¶”ê°€';
$labels['mailtoprotohandler'] = 'mailto: ë§í¬ì˜ 프로토콜 ì²˜ë¦¬ìž ë“±ë¡';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = '메시지 전달';
$labels['inline'] = '본문 내용으로';
$labels['asattachment'] = '첨부파ì¼ë¡œ';
diff --git a/program/localization/ku/labels.inc b/program/localization/ku/labels.inc
index a4f6cb568..6a3c16a5f 100644
--- a/program/localization/ku/labels.inc
+++ b/program/localization/ku/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Hilanînî';
$labels['sent'] = 'Şandî';
$labels['trash'] = 'Çop';
$labels['junk'] = 'Biikêrnehatî';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'Mijar';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode';
$labels['folderactions'] = 'Folder actions...';
$labels['compact'] = 'Kompakt';
$labels['empty'] = 'Vala Bike';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Bikaranîna dîskê';
$labels['unknown'] = 'nayê zanîn';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Lêgerînê reset bike';
$labels['searchmod'] = 'Search modifiers';
$labels['msgtext'] = 'Entire message';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Open in new window';
$labels['emlsave'] = 'Download (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Seta dawî nîşan bide';
$labels['group'] = 'Group';
$labels['groups'] = 'Kom';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Navnîşanên Takekesî';
$labels['searchsave'] = 'Save search';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers';
$labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized';
$labels['addtodict'] = 'Add to dictionary';
$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Messages forwarding';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'as attachment';
diff --git a/program/localization/lb_LU/labels.inc b/program/localization/lb_LU/labels.inc
new file mode 100644
index 000000000..1dff3a9e7
--- /dev/null
+++ b/program/localization/lb_LU/labels.inc
@@ -0,0 +1,544 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | localization/<lang>/labels.inc |
+ | |
+ | Localization file of the Roundcube Webmail client |
+ | Copyright (C) 2005-2013, The Roundcube Dev Team |
+ | |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
+ | |
+ +-----------------------------------------------------------------------+
+
+ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/labels/
+*/
+
+$labels = array();
+
+// login page
+$labels['welcome'] = 'Wëllkomm bei $product';
+$labels['username'] = 'Benotzernumm';
+$labels['password'] = 'Passwuert';
+$labels['server'] = 'Server';
+$labels['login'] = 'Aloggen';
+
+// taskbar
+$labels['logout'] = 'Ausloggen';
+$labels['mail'] = 'Mailen';
+$labels['settings'] = 'Astellungen';
+$labels['addressbook'] = 'Adressbuch';
+
+// mailbox names
+$labels['inbox'] = 'Mailbox';
+$labels['drafts'] = 'Brouillonen';
+$labels['sent'] = 'Verschéckt';
+$labels['trash'] = 'Poubelle';
+$labels['junk'] = 'Spam';
+$labels['show_real_foldernames'] = 'Richteg Nimm vu de speziellen Dossieren uweisen';
+
+// message listing
+$labels['subject'] = 'Sujet';
+$labels['from'] = 'Vun';
+$labels['sender'] = 'Geschéckt vun';
+$labels['to'] = 'Un';
+$labels['cc'] = 'CC';
+$labels['bcc'] = 'BCC';
+$labels['replyto'] = 'Äntwert un';
+$labels['followupto'] = 'Noverfollgung un';
+$labels['date'] = 'Datum';
+$labels['size'] = 'Gréisst';
+$labels['priority'] = 'Prioritéit';
+$labels['organization'] = 'Organisatioun';
+$labels['readstatus'] = 'Lies-Status';
+$labels['listoptions'] = 'Optiounen oplëschten';
+
+$labels['mailboxlist'] = 'Dossieren';
+$labels['messagesfromto'] = 'Messagen $from bis $to vun $count';
+$labels['threadsfromto'] = 'Diskussiounen $from bis $to vun $count';
+$labels['messagenrof'] = 'Message $nr vun $count';
+$labels['fromtoshort'] = '$from bis $to vun $count';
+
+$labels['copy'] = 'Kopéieren';
+$labels['move'] = 'Réckelen';
+$labels['moveto'] = 'Réckelen an...';
+$labels['download'] = 'Eroflueden';
+$labels['open'] = 'Opmaachen';
+$labels['showattachment'] = 'Weisen';
+$labels['showanyway'] = 'Trotzdeem weisen';
+
+$labels['filename'] = 'Numm vum Fichier';
+$labels['filesize'] = 'Gréisst vum Fichier';
+
+$labels['addtoaddressbook'] = 'An d\'Adressbuch setzen';
+
+// weekdays short
+$labels['sun'] = 'Son';
+$labels['mon'] = 'Méi';
+$labels['tue'] = 'Dën';
+$labels['wed'] = 'Don';
+$labels['thu'] = 'Fre';
+$labels['fri'] = 'Sam';
+$labels['sat'] = 'Son';
+
+// weekdays long
+$labels['sunday'] = 'Sonndeg';
+$labels['monday'] = 'Méindeg';
+$labels['tuesday'] = 'Dënschdeg';
+$labels['wednesday'] = 'Mëttwoch';
+$labels['thursday'] = 'Donneschdeg';
+$labels['friday'] = 'Freideg';
+$labels['saturday'] = 'Samschdeg';
+
+// months short
+$labels['jan'] = 'Jan';
+$labels['feb'] = 'Feb';
+$labels['mar'] = 'Mäe';
+$labels['apr'] = 'Abr';
+$labels['may'] = 'Mee';
+$labels['jun'] = 'Jun';
+$labels['jul'] = 'Jul';
+$labels['aug'] = 'Aug';
+$labels['sep'] = 'Sep';
+$labels['oct'] = 'Okt';
+$labels['nov'] = 'Nov';
+$labels['dec'] = 'Dez';
+
+// months long
+$labels['longjan'] = 'Januar';
+$labels['longfeb'] = 'Februar';
+$labels['longmar'] = 'Mäerz';
+$labels['longapr'] = 'Abrëll';
+$labels['longmay'] = 'Mee';
+$labels['longjun'] = 'Juni';
+$labels['longjul'] = 'Juli';
+$labels['longaug'] = 'August';
+$labels['longsep'] = 'September';
+$labels['longoct'] = 'Oktober';
+$labels['longnov'] = 'November';
+$labels['longdec'] = 'Dezember';
+
+$labels['today'] = 'Haut';
+
+// toolbar buttons
+$labels['refresh'] = 'Nei lueden';
+$labels['checkmail'] = 'Nei Messagen ofruffen';
+$labels['compose'] = 'Schreiwen';
+$labels['writenewmessage'] = 'Neie Message schreiwen';
+$labels['reply'] = 'Äntweren';
+$labels['replytomessage'] = 'Dem Ofsender äntweren';
+$labels['replytoallmessage'] = 'Dem Ofsender an allen Empfänger äntweren';
+$labels['replyall'] = 'U jiddwereen äntweren';
+$labels['replylist'] = 'Äntwert-Lëscht';
+$labels['forward'] = 'Weiderleeden';
+$labels['forwardinline'] = 'Am Message weiderleeden';
+$labels['forwardattachment'] = 'Als Unhank weiderleeden';
+$labels['forwardmessage'] = 'De Message weiderleeden';
+$labels['deletemessage'] = 'Message läschen';
+$labels['movemessagetotrash'] = 'Message an d\'Poubelle réckelen';
+$labels['printmessage'] = 'Dëse Message drécken';
+$labels['previousmessage'] = 'Message virdru weisen';
+$labels['firstmessage'] = 'Éischte Message weisen';
+$labels['nextmessage'] = 'Nächste Message weisen';
+$labels['lastmessage'] = 'Leschte Message weisen';
+$labels['backtolist'] = 'Zréck bei d\'Lëscht vun de Messagen';
+$labels['viewsource'] = 'Source weisen';
+$labels['mark'] = 'Markéieren';
+$labels['markmessages'] = 'Messagë markéieren';
+$labels['markread'] = 'Als gelies';
+$labels['markunread'] = 'Als ongelies';
+$labels['markflagged'] = 'Mat Fändel';
+$labels['markunflagged'] = 'Ouni Fändel';
+$labels['moreactions'] = 'Mei Aktiounen...';
+$labels['more'] = 'Méi';
+$labels['back'] = 'Zréck';
+$labels['options'] = 'Optiounen';
+
+$labels['select'] = 'Auswielen';
+$labels['all'] = 'All';
+$labels['none'] = 'Keng';
+$labels['currpage'] = 'Aktuell Säit';
+$labels['unread'] = 'Ongelies';
+$labels['flagged'] = 'Mat Fändel';
+$labels['unanswered'] = 'Net beäntwert';
+$labels['withattachment'] = 'Mat Unhank';
+$labels['deleted'] = 'Geläscht';
+$labels['undeleted'] = 'Net geläscht';
+$labels['invert'] = 'Ëmdréinen';
+$labels['filter'] = 'Filter';
+$labels['list'] = 'Lëscht';
+$labels['threads'] = 'Diskussiounen';
+$labels['expand-all'] = 'All opfächeren';
+$labels['expand-unread'] = 'Ongelies opfächeren';
+$labels['collapse-all'] = 'All zesummefächeren';
+$labels['threaded'] = 'Diskussiounen zesummefaassen';
+
+$labels['autoexpand_threads'] = 'Diskussiounen auserneefächeren';
+$labels['do_expand'] = 'All d\'Diskussiounen';
+$labels['expand_only_unread'] = 'just ongeliese Messagen';
+$labels['fromto'] = 'Vun/Un';
+$labels['flag'] = 'Fändel';
+$labels['attachment'] = 'Unhank';
+$labels['nonesort'] = 'Keng';
+$labels['sentdate'] = 'Verschéckt';
+$labels['arrival'] = 'Ukomm';
+$labels['asc'] = 'opsteigend';
+$labels['desc'] = 'ofsteigend';
+$labels['listcolumns'] = 'Kolonnen oplëschten';
+$labels['listsorting'] = 'Kolonne sortéieren';
+$labels['listorder'] = 'Sortéier-Reiefolleg';
+$labels['listmode'] = 'Oplëschtungs-Modus';
+
+$labels['folderactions'] = 'Dossiers-Aktiounen...';
+$labels['compact'] = 'Kompaktéieren';
+$labels['empty'] = 'Eidel';
+$labels['importmessages'] = 'Messagen importéieren';
+
+$labels['quota'] = 'Plazverbrauch';
+$labels['unknown'] = 'onbekannt';
+$labels['unlimited'] = 'onlimitéiert';
+
+$labels['quicksearch'] = 'Séier Sich';
+$labels['resetsearch'] = 'Sich zerécksetzen';
+$labels['searchmod'] = 'Sich-Parameter';
+$labels['msgtext'] = 'Ganze Message';
+$labels['body'] = 'Kierper';
+$labels['type'] = 'Typ';
+$labels['namex'] = 'Numm';
+
+$labels['openinextwin'] = 'An enger neier Fënster opmaachen';
+$labels['emlsave'] = 'Eroflueden (.eml)';
+$labels['changeformattext'] = 'Als Text ouni Formatéierungen uweisen';
+$labels['changeformathtml'] = 'Als formatéierten Text uweisen';
+
+// message compose
+$labels['editasnew'] = 'Als nei editéieren';
+$labels['send'] = 'Schécken';
+$labels['sendmessage'] = 'Message schécken';
+$labels['savemessage'] = 'Als Brouillon späicheren';
+$labels['addattachment'] = 'E Fichier drunhänken';
+$labels['charset'] = 'Zeechesaz';
+$labels['editortype'] = 'Editor-Typ';
+$labels['returnreceipt'] = 'Empfanksbestätegung';
+$labels['dsn'] = 'Empfanks-Status-Meldung';
+$labels['mailreplyintro'] = 'Den $date, $sender schreift:';
+$labels['originalmessage'] = 'Original-Message';
+
+$labels['editidents'] = 'Identitéiten editéieren';
+$labels['spellcheck'] = 'Orthographie';
+$labels['checkspelling'] = 'Orthographie kontrolléieren';
+$labels['resumeediting'] = 'Weider editéieren';
+$labels['revertto'] = 'Zréck bei';
+
+$labels['attach'] = 'Drunhänken';
+$labels['attachments'] = 'Unhäng';
+$labels['upload'] = 'Eroplueden';
+$labels['uploadprogress'] = '$percent ($current vun $total)';
+$labels['close'] = 'Zoumaachen';
+$labels['messageoptions'] = 'Message-Optiounen...';
+
+$labels['low'] = 'Niddreg';
+$labels['lowest'] = 'Am niddregsten';
+$labels['normal'] = 'Normal';
+$labels['high'] = 'Héich';
+$labels['highest'] = 'Am héchsten';
+
+$labels['nosubject'] = '(kee Sujet)';
+$labels['showimages'] = 'Biller uweisen';
+$labels['alwaysshow'] = 'Biller vun $sender ëmmer uweisen';
+$labels['isdraft'] = 'Dëst ass e Brouillon.';
+$labels['andnmore'] = '$nr more...';
+$labels['togglemoreheaders'] = 'Méi Message-Headeren uweisen';
+$labels['togglefullheaders'] = 'Réi Message-Headeren an-/ausblenden';
+
+$labels['htmltoggle'] = 'Text mat Formatéierungen';
+$labels['plaintoggle'] = 'Text ouni Formatéierungen';
+$labels['savesentmessagein'] = 'Dee verschéckte Message späicheren an';
+$labels['dontsave'] = 'net späicheren';
+$labels['maxuploadsize'] = 'Déi maximal erlaabte Fichiers-Gréisst ass $size';
+
+$labels['addcc'] = 'CC dobäisetzen';
+$labels['addbcc'] = 'BCC dobäisetzen';
+$labels['addreplyto'] = '"Äntwert un" dobäisetzen';
+$labels['addfollowupto'] = '"Noverfollgung un" dobäisetzen';
+
+// mdn
+$labels['mdnrequest'] = 'De Sender vun dësem Message huet gefrot fir informéiert ze gi wann de Message gelies gëtt. Wëlls du de Sender informéieren?';
+$labels['receiptread'] = 'Empfanksbestätegung (gelies)';
+$labels['yourmessage'] = 'Dëst ass eng Empfanksbestätegung fir Äre Message.';
+$labels['receiptnote'] = 'Bemierkung: Dës Bestätegung bezeit just datt de Message beim Empfänger ugewise ginn ass. Et gëtt keng Garantie dass den Empfänger den Inhalt vum Message gelies oder verstanen huet.';
+
+// address boook
+$labels['name'] = 'Ganzen Numm';
+$labels['firstname'] = 'Virnumm';
+$labels['surname'] = 'Nonumm';
+$labels['middlename'] = 'Mëttelnumm';
+$labels['nameprefix'] = 'Präfix';
+$labels['namesuffix'] = 'Suffix';
+$labels['nickname'] = 'Spëtznumm';
+$labels['jobtitle'] = 'Job-Titel';
+$labels['department'] = 'Departement';
+$labels['gender'] = 'Geschlecht';
+$labels['maidenname'] = 'Meedechersnumm';
+$labels['email'] = 'E-Mail';
+$labels['phone'] = 'Telefon';
+$labels['address'] = 'Adress';
+$labels['street'] = 'Strooss';
+$labels['locality'] = 'Uertschaft';
+$labels['zipcode'] = 'Postleitzuel';
+$labels['region'] = 'Staat';
+$labels['country'] = 'Land';
+$labels['birthday'] = 'Gebuertsdatum';
+$labels['anniversary'] = 'Anniversaire';
+$labels['website'] = 'Websäit';
+$labels['instantmessenger'] = 'Instant-Messenger';
+$labels['notes'] = 'Notizen';
+$labels['male'] = 'männlech';
+$labels['female'] = 'weiblech';
+$labels['manager'] = 'Manager';
+$labels['assistant'] = 'Assistent';
+$labels['spouse'] = 'Liewenspartner';
+$labels['allfields'] = 'All d\'Felder';
+$labels['search'] = 'Sichen';
+$labels['advsearch'] = 'Avancéiert Sich';
+$labels['advanced'] = 'Avancéiert';
+$labels['other'] = 'Aneres';
+
+$labels['typehome'] = 'Doheem';
+$labels['typework'] = 'Aarbecht';
+$labels['typeother'] = 'Aneres';
+$labels['typemobile'] = 'Mobil';
+$labels['typemain'] = 'Haapt';
+$labels['typehomefax'] = 'Fax Doheem';
+$labels['typeworkfax'] = 'Fax Aarbecht';
+$labels['typecar'] = 'Auto';
+$labels['typepager'] = 'Pager';
+$labels['typevideo'] = 'Video';
+$labels['typeassistant'] = 'Assistent';
+$labels['typehomepage'] = 'Websäit';
+$labels['typeblog'] = 'Blog';
+$labels['typeprofile'] = 'Profil';
+
+$labels['addfield'] = 'Feld dobäisetzen...';
+$labels['addcontact'] = 'Neie Kontakt dobäisetzen';
+$labels['editcontact'] = 'Kontakt editéieren';
+$labels['contacts'] = 'Kontakter';
+$labels['contactproperties'] = 'Kontakt-Eegeschaften';
+$labels['personalinfo'] = 'Perséinlech Informatioun';
+
+$labels['edit'] = 'Änneren';
+$labels['cancel'] = 'Ofbriechen';
+$labels['save'] = 'Späicheren';
+$labels['delete'] = 'Läschen';
+$labels['rename'] = 'Ëmbenennen';
+$labels['addphoto'] = 'Dobäisetzen';
+$labels['replacephoto'] = 'Ersetzen';
+$labels['uploadphoto'] = 'Foto eroplueden';
+
+$labels['newcontact'] = 'Nei Kontakt-Kaart erstellen';
+$labels['deletecontact'] = 'Déi ausgewielte Kontakter läschen';
+$labels['composeto'] = 'Mail schreiwen un';
+$labels['contactsfromto'] = 'Kontakter $from bis $to vun $count';
+$labels['print'] = 'Drécke';
+$labels['export'] = 'Exportéieren';
+$labels['exportall'] = 'All exportéieren';
+$labels['exportsel'] = 'Déi ausgewielten exportéieren';
+$labels['exportvcards'] = 'Kontakter am vCard-Format exportéieren';
+$labels['newcontactgroup'] = 'Nei Kontakt-Grupp erstellen';
+$labels['grouprename'] = 'Grupp ëmbenennen';
+$labels['groupdelete'] = 'Grupp läschen';
+$labels['groupremoveselected'] = 'Ausgewielte Kontakter aus Grupp eraushuele';
+
+$labels['previouspage'] = 'Säit virdru weisen';
+$labels['firstpage'] = 'Éischt Säit weisen';
+$labels['nextpage'] = 'Nächst Säit weisen';
+$labels['lastpage'] = 'Lescht Säit weisen';
+
+$labels['group'] = 'Grup';
+$labels['groups'] = 'Gruppen';
+$labels['listgroup'] = 'Gruppe-Memberen oplëschten';
+$labels['personaladrbook'] = 'Perséinlech Adressen';
+
+$labels['searchsave'] = 'Sich späicheren';
+$labels['searchdelete'] = 'Sich läschen';
+
+$labels['import'] = 'Importéieren';
+$labels['importcontacts'] = 'Kontakter importéieren';
+$labels['importfromfile'] = 'Aus Fichier importéieren:';
+$labels['importtarget'] = 'Nei Kontakter an d\'Adressbuch setzen:';
+$labels['importreplace'] = 'Dat ganzt Adressbuch ersetzen';
+$labels['importdesc'] = 'Du kanns Kontakter aus engem existéierenden Adressbuch eroplueden.<br/>Mir ënnerstëtze momentan en Adress-Import vum <a href="http://en.wikipedia.org/wiki/VCard">vCard</a>- oder CSV (mat Komma getrennt)-Date-Format.';
+$labels['done'] = 'Erleedegt';
+
+// settings
+$labels['settingsfor'] = 'Astellunge fir';
+$labels['about'] = 'Iwwert';
+$labels['preferences'] = 'Astellungen';
+$labels['userpreferences'] = 'Benotzer-Astellungen';
+$labels['editpreferences'] = 'Benotzer-Astellungen änneren';
+
+$labels['identities'] = 'Identitéiten';
+$labels['manageidentities'] = 'Identitéite fir dësen Account geréieren';
+$labels['newidentity'] = 'Nei Identitéit';
+
+$labels['newitem'] = 'Neit Element';
+$labels['edititem'] = 'Element änneren';
+
+$labels['preferhtml'] = 'HTML uweisen';
+$labels['defaultcharset'] = 'Standard Zeechesaz';
+$labels['htmlmessage'] = 'HTML-Message';
+$labels['messagepart'] = 'Deel';
+$labels['digitalsig'] = 'Digital Signatur';
+$labels['dateformat'] = 'Datums-Format';
+$labels['timeformat'] = 'Zäit-Format';
+$labels['prettydate'] = 'Schéin Daten';
+$labels['setdefault'] = 'Als standard definéieren';
+$labels['autodetect'] = 'Automatesch';
+$labels['language'] = 'Sprooch';
+$labels['timezone'] = 'Zäitzon';
+$labels['pagesize'] = 'Reie pro Säit';
+$labels['signature'] = 'Ënnerschrëft';
+$labels['dstactive'] = 'Summerzäit';
+$labels['showinextwin'] = 'Message an neier Fënster opmaache';
+$labels['composeextwin'] = 'An enger neier Fënster schreiwen';
+$labels['htmleditor'] = 'HTML-Messagë schreiwen';
+$labels['htmlonreply'] = 'bei Äntwert op e Message mat Formatéierungen';
+$labels['htmlonreplyandforward'] = 'bei Weiderleedung oder Äntwert op e Message mat Formatéierungen';
+$labels['htmlsignature'] = 'Formatéiert Ënnerschrëft';
+$labels['showemail'] = 'Email-Adress mat ganzem Numm uweisen';
+$labels['previewpane'] = 'Virschau-Panneau uweisen';
+$labels['skin'] = 'Opmaachung vum Interface';
+$labels['logoutclear'] = 'Poubelle beim Logout eidelmaachen';
+$labels['logoutcompact'] = 'Mailbox beim Logout eidelmaachen';
+$labels['uisettings'] = 'Benotzer-Interface';
+$labels['serversettings'] = 'Server-Astellungen';
+$labels['mailboxview'] = 'Mailbox-Usiicht';
+$labels['mdnrequests'] = 'Bei Ufro no Empfanksbestätegung';
+$labels['askuser'] = 'mech froen';
+$labels['autosend'] = 'Bestätegung schécken';
+$labels['autosendknown'] = 'Bestätegung u meng Kontakter schécken, anerefalls nofroen';
+$labels['autosendknownignore'] = 'Bestätegung u meng Kontakter schécken, anerefalls ignoréieren';
+$labels['ignore'] = 'ignoréieren';
+$labels['readwhendeleted'] = 'Beim Läschen de Message als gelies markéieren';
+$labels['flagfordeletion'] = 'De Message als "läschbar" markéieren amplaz en ze läschen';
+$labels['skipdeleted'] = 'Geläschte Messagen net uweisen';
+$labels['deletealways'] = 'Falls Messagen net an d\'Poubelle kënne geréckelt ginn, läsch se';
+$labels['deletejunk'] = 'Messagen am Spam-Dossier direkt läschen';
+$labels['showremoteimages'] = 'Biller an de Maile vun externe Serveren nolueden';
+$labels['fromknownsenders'] = 'vu bekannte Senderen';
+$labels['always'] = 'ëmmer';
+$labels['showinlineimages'] = 'Biller déi drunhänken ënnert dem Message uweisen';
+$labels['autosavedraft'] = 'Brouillon automatesch späicheren';
+$labels['everynminutes'] = 'all $n Minutt(en)';
+$labels['refreshinterval'] = 'Frësch lueden (nei Messagen ofruffen, etc.)';
+$labels['never'] = 'ni';
+$labels['immediately'] = 'direkt';
+$labels['messagesdisplaying'] = 'Messagen uweisen';
+$labels['messagescomposition'] = 'Messagë schreiwen';
+$labels['mimeparamfolding'] = 'Nimm vun den Unhäng';
+$labels['2231folding'] = 'Kompletten RFC 2231 (Thunderbird)';
+$labels['miscfolding'] = 'RFC 2047/2231 (Microsoft Outlook)';
+$labels['2047folding'] = 'Kompletten RFC 2047 (anerer)';
+$labels['force7bit'] = 'MIME-Kodéierung fir 8-Bit-Zeeche benotzen';
+$labels['advancedoptions'] = 'Avancéiert Optiounen';
+$labels['focusonnewmessage'] = 'Browser-Fënster fokusséiere wann en neie Message ukënnt';
+$labels['checkallfolders'] = 'Nei Messagen an allen Dossieren opruffen';
+$labels['displaynext'] = 'Nom Réckelen/Läsche vun engem Message deen nächsten uweisen';
+$labels['defaultfont'] = 'Standard-Schrëft fir e Message mat Formatéierungen';
+$labels['mainoptions'] = 'Haapt-Optiounen';
+$labels['browseroptions'] = 'Browser-Optiounen';
+$labels['section'] = 'Beräich';
+$labels['maintenance'] = 'Maintenance';
+$labels['newmessage'] = 'Neie Message';
+$labels['signatureoptions'] = 'Optioune vun der Ënnerschrëft';
+$labels['whenreplying'] = 'Bei enger Äntwert';
+$labels['replyempty'] = 'den Original-Message net zitéieren';
+$labels['replytopposting'] = 'neie Message iwwert dem Zitat ufänken';
+$labels['replybottomposting'] = 'neie Message ënnert dem Zitat ufänken';
+$labels['replyremovesignature'] = 'Bei enger Äntwert d\'Original-Ënnerschrëft aus dem Message huelen';
+$labels['autoaddsignature'] = 'Ënnerschrëft automatesch drasetzen';
+$labels['newmessageonly'] = 'just bei neie Messagen';
+$labels['replyandforwardonly'] = 'just bei Äntwerten a Weiderleedungen';
+$labels['insertsignature'] = 'Ënnerschrëft drasetzen';
+$labels['previewpanemarkread'] = 'D\'Messagen an der Virschau als gelies markéieren';
+$labels['afternseconds'] = 'no $n Sekonnen';
+$labels['reqmdn'] = 'Ëmmer eng Empfanksbestätegung ufroen';
+$labels['reqdsn'] = 'Ëmmer eng Empfanks-Status-Meldung ufroen';
+$labels['replysamefolder'] = 'Äntwert an de selweschten Dossier setze wéi de Message op dee geäntwert gëtt';
+$labels['defaultabook'] = 'Standard Adress-Buch';
+$labels['autocompletesingle'] = 'Alternativ Email-Adressen bei der automatescher Vervollstänneung iwwersprangen';
+$labels['listnamedisplay'] = 'Kontakter oplëschten als';
+$labels['spellcheckbeforesend'] = 'Orthographie kontrolléieren bevir de Message verschéckt gëtt';
+$labels['spellcheckoptions'] = 'Orthographie-Korrektur-Optiounen';
+$labels['spellcheckignoresyms'] = 'Wierder mat Symboler ignoréieren';
+$labels['spellcheckignorenums'] = 'Wierder mat Zuelen ignoréieren';
+$labels['spellcheckignorecaps'] = 'Wierder mat just Groussbuschtawen ignoréieren';
+$labels['addtodict'] = 'An den Dictionnaire setzen';
+$labels['mailtoprotohandler'] = 'Protokoll-Handhaber fir "mailto:"-Links registréieren';
+$labels['standardwindows'] = 'Popup-Fënstere wéi normal Fënstere behandelen';
+$labels['forwardmode'] = 'Messagë-Weiderleedung';
+$labels['inline'] = 'am Message';
+$labels['asattachment'] = 'als Unhank';
+
+$labels['folder'] = 'Dossier';
+$labels['folders'] = 'Dossieren';
+$labels['foldername'] = 'Dossiersnumm';
+$labels['subscribed'] = 'Abonnéiert';
+$labels['messagecount'] = 'Messagen';
+$labels['create'] = 'Erstellen';
+$labels['createfolder'] = 'Neien Dossier erstellen';
+$labels['managefolders'] = 'Dossieren geréieren';
+$labels['specialfolders'] = 'Speziell Dossieren';
+$labels['properties'] = 'Astellungen';
+$labels['folderproperties'] = 'Dossiers-Astellungen';
+$labels['parentfolder'] = 'Elteren-Dossier';
+$labels['location'] = 'Plaz';
+$labels['info'] = 'Informatioun';
+$labels['getfoldersize'] = 'Klick fir d\'Dossiers-Gréisst ze kréien';
+$labels['changesubscription'] = 'Klick fir den Abonnement ze änneren';
+$labels['foldertype'] = 'Dossiers-Typ';
+$labels['personalfolder'] = 'Privaten Dossier';
+$labels['otherfolder'] = 'Dossier vun anerem Benotzer';
+$labels['sharedfolder'] = 'Ëffentlechen Dossier';
+
+$labels['sortby'] = 'Sortéieren no';
+$labels['sortasc'] = 'Opsteigend sortéieren';
+$labels['sortdesc'] = 'Ofsteigend sortéieren';
+$labels['undo'] = 'Réckgängeg maachen';
+
+$labels['installedplugins'] = 'Installéiert Plugins';
+$labels['plugin'] = 'Plugin';
+$labels['version'] = 'Versioun';
+$labels['source'] = 'Source';
+$labels['license'] = 'Lizenz';
+$labels['support'] = 'Support ufroen';
+
+// units
+$labels['B'] = 'B';
+$labels['KB'] = 'kB';
+$labels['MB'] = 'MB';
+$labels['GB'] = 'GB';
+
+// character sets
+$labels['unicode'] = 'Unicode';
+$labels['english'] = 'Englesch';
+$labels['westerneuropean'] = 'West-Europäesch';
+$labels['easterneuropean'] = 'Ost-Europäesch';
+$labels['southeasterneuropean'] = 'Süd-Ost-Europäesch';
+$labels['baltic'] = 'Baltesch';
+$labels['cyrillic'] = 'Kyrilesch';
+$labels['arabic'] = 'Arabesch';
+$labels['greek'] = 'Griechesch';
+$labels['hebrew'] = 'Häbräesch';
+$labels['turkish'] = 'Türkesch';
+$labels['nordic'] = 'Nordesch';
+$labels['thai'] = 'Thai';
+$labels['celtic'] = 'Keltesch';
+$labels['vietnamese'] = 'Vietnamesesch';
+$labels['japanese'] = 'Japanesch';
+$labels['korean'] = 'Koreanesch';
+$labels['chinese'] = 'Chinesesch';
+
+?>
diff --git a/program/localization/lb_LU/messages.inc b/program/localization/lb_LU/messages.inc
new file mode 100644
index 000000000..5599f227b
--- /dev/null
+++ b/program/localization/lb_LU/messages.inc
@@ -0,0 +1,176 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | localization/<lang>/messages.inc |
+ | |
+ | Localization file of the Roundcube Webmail client |
+ | Copyright (C) 2005-2013, The Roundcube Dev Team |
+ | |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
+ | |
+ +-----------------------------------------------------------------------+
+
+ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/messages/
+*/
+
+$messages = array();
+$messages['errortitle'] = 'Ee Feeler ass opgetrueden!';
+$messages['loginfailed'] = 'Login feelgeschloen.';
+$messages['cookiesdisabled'] = 'Däi Browser acceptéiert keng Cookien.';
+$messages['sessionerror'] = 'Deng Sessioun ass ongëlteg oder verfall.';
+$messages['storageerror'] = 'D\'Verbindung mam Späicher-Server ass feelgeschloen.';
+$messages['servererror'] = 'Server-Feeler!';
+$messages['servererrormsg'] = 'Server-Feeler: $msg';
+$messages['dberror'] = 'Datebank-Feeler!';
+$messages['requesttimedout'] = 'D\'Ufro huet ze laang gedauert';
+$messages['errorreadonly'] = 'D\'Operatioun kann net ofgeschloss ginn. Den Dossier ass schreifgeschützt.';
+$messages['errornoperm'] = 'D\'Operatioun kann net ofgeschloss ginn. Zougrëff verweigert.';
+$messages['erroroverquota'] = 'D\'Operatioun konnt net ausgefouert ginn. Et ass net méi genuch Plaz um Disk.';
+$messages['erroroverquotadelete'] = 'Et ass net méi genuch Plaz um Disk. Benotz Shift+Delete fir e message ze läschen.';
+$messages['invalidrequest'] = 'Ongëlteg Ufro! Et goufe keng Date gespäichert.';
+$messages['invalidhost'] = 'Ongëltege Server-Numm.';
+$messages['nomessagesfound'] = 'Keng Messagen an der Mailbox fonnt.';
+$messages['loggedout'] = 'Du hues dech erfollegräich ofgemellt. Äddi!';
+$messages['mailboxempty'] = 'D\'Mailbox ass eidel.';
+$messages['refreshing'] = 'Lueden nei...';
+$messages['loading'] = 'Lueden...';
+$messages['uploading'] = 'Fichier gëtt eropgelueden...';
+$messages['uploadingmany'] = 'Fichiere ginn eropgelueden...';
+$messages['loadingdata'] = 'Date gi gelueden..';
+$messages['checkingmail'] = 'Nei Messagë ginn ofgeruff...';
+$messages['sendingmessage'] = 'Message gëtt geschéckt...';
+$messages['messagesent'] = 'Message erfollegräich verschéckt.';
+$messages['savingmessage'] = 'Message gëtt gespäichert...';
+$messages['messagesaved'] = 'Message als Brouillon gespäichert.';
+$messages['successfullysaved'] = 'Erfollegräich gespäichert.';
+$messages['addedsuccessfully'] = 'Kontakt erfollegräich an d\'Adressbuch gesat.';
+$messages['contactexists'] = 'Et existéiert schon e Kontakt mat der selweschter E-Mail-Adress.';
+$messages['contactnameexists'] = 'Et existéiert schon e Kontakt mam selweschten Numm.';
+$messages['blockedimages'] = 'Fir deng Privatsphär ze schütze, gi Biller vun externe Serveren an dësem Message net gelueden.';
+$messages['encryptedmessage'] = 'Dëst ass e verschlësselte Message a kann net ugewise ginn. Et deet eis Leed!';
+$messages['nocontactsfound'] = 'Keng Kontakter fonnt.';
+$messages['contactnotfound'] = 'Den ugefrotene Kontakt gouf net fonnt.';
+$messages['contactsearchonly'] = 'Gëff e puer Sichbegrëffer a fir Kontakter ze fannen';
+$messages['sendingfailed'] = 'De Message konnt net verschéckt ginn.';
+$messages['senttooquickly'] = 'Waart wann ech gelift $sec Sekonn(en) bevir s du de Message verschécks. ';
+$messages['errorsavingsent'] = 'Beim Späichere vum verschéckte Message ass e Feeler opgetrueden';
+$messages['errorsaving'] = 'Beim Späicheren ass e Feeler opgetrueden.';
+$messages['errormoving'] = 'D\'Messagë konnten net verréckelt ginn.';
+$messages['errorcopying'] = 'D\'Messagë konnten net kopéiert ginn.';
+$messages['errordeleting'] = 'D\'Messagë konnten net geläscht ginn.';
+$messages['errormarking'] = 'D\'Messagë konnten net markéiert ginn.';
+$messages['deletecontactconfirm'] = 'Wëlls du wierklech déi ausgewielte Kontakter läschen?';
+$messages['deletegroupconfirm'] = 'Wëlls du wierklech déi ausgewielte Gruppe läschen?';
+$messages['deletemessagesconfirm'] = 'Wëlls du wierklech déi ausgewielte Messagë läschen?';
+$messages['deletefolderconfirm'] = 'Wëlls du dësen Dossier wierklech läschen?';
+$messages['purgefolderconfirm'] = 'Wëlls du wierklech all d\'Messagen an dësem Dossier läschen?';
+$messages['contactdeleting'] = 'Kontakter gi geläscht...';
+$messages['groupdeleting'] = 'Grupp gëtt geläscht...';
+$messages['folderdeleting'] = 'Dossier gëtt geläscht...';
+$messages['foldermoving'] = 'Dossier gëtt geréckelt...';
+$messages['foldersubscribing'] = 'Dossier gëtt abonnéiert...';
+$messages['folderunsubscribing'] = 'Dossier gëtt desabonnéiert...';
+$messages['formincomplete'] = 'De Formular war net komplett ausgefëlt.';
+$messages['noemailwarning'] = 'Gëff w.e.gl eng gëlteg Email-Adress an.';
+$messages['nonamewarning'] = 'Gëff w.e.gl en Numm an.';
+$messages['nopagesizewarning'] = 'Gëff w.e.gl eng Säitegréisst an.';
+$messages['nosenderwarning'] = 'Gëff w.e.gl d\'Adress vum Ofsender an.';
+$messages['norecipientwarning'] = 'Gëff w.e.gl op mannst een Empfänger an.';
+$messages['nosubjectwarning'] = 'D\'Feld "Sujet" ass eidel. Wëlls du elo eent uginn?';
+$messages['nobodywarning'] = 'Soll dëse Message ouni Text verschéckt ginn?';
+$messages['notsentwarning'] = 'De Message gouf net verschéckt. Wëlls du e verwerfen?';
+$messages['noldapserver'] = 'Wiel w.e.gl en LDAP-Server fir d\'Sich aus.';
+$messages['nosearchname'] = 'Gëff w.e.gl en Numm oder eng E-Mail-Adress fir de Kontakt an.';
+$messages['notuploadedwarning'] = 'Net all d\'Unhäng goufen eropgelueden. Waart w.e.gl e Moment oder briech den Upload of.';
+$messages['searchsuccessful'] = '$nr Messagë fonnt.';
+$messages['contactsearchsuccessful'] = '$nr Kontakter fonnt.';
+$messages['searchnomatch'] = 'D\'Sich huet keng Treffer bruecht.';
+$messages['searching'] = 'Sichen...';
+$messages['checking'] = 'Kontrolléieren...';
+$messages['nospellerrors'] = 'Et goufe keng Schreiffeeler fonnt.';
+$messages['folderdeleted'] = 'Dossier erfollegräich geläscht.';
+$messages['foldersubscribed'] = 'Dossier erfollegräich abonnéiert.';
+$messages['folderunsubscribed'] = 'Dossier erfollegräich desabonnéiert.';
+$messages['folderpurged'] = 'Dossier erfollegräich eidelgemaach.';
+$messages['folderexpunged'] = 'Dossier erfollegräich kompaktéiert.';
+$messages['deletedsuccessfully'] = 'Erfollegräich geläscht.';
+$messages['converting'] = 'Formatéierunge gi geläscht...';
+$messages['messageopenerror'] = 'Message konnt net vum Server geluede ginn.';
+$messages['fileuploaderror'] = 'Upload vum Fichier feelgeschloen.';
+$messages['filesizeerror'] = 'Den eropgeluedene Fichier ass méi grouss wéi déi maximal erlaabte Gréisst vun $size.';
+$messages['copysuccess'] = 'Et goufen erfollegräich $nr Kontakter kopéiert.';
+$messages['movesuccess'] = 'Et goufen erfollegräich $nr Kontakter geréckelt.';
+$messages['copyerror'] = 'Konnt d\'Kontakter net kopéieren';
+$messages['moveerror'] = 'Konnt d\'Kontakter net réckelen.';
+$messages['sourceisreadonly'] = 'D\'Adresse-Quell ass schreifgeschützt.';
+$messages['errorsavingcontact'] = 'D\'Kontakt-Adress konnt net gespäichert ginn.';
+$messages['movingmessage'] = 'Messagë gi geréckelt...';
+$messages['copyingmessage'] = 'Messagë gi kopéiert...';
+$messages['copyingcontact'] = 'Kontakter gi kopéiert...';
+$messages['movingcontact'] = 'Kontakter gi geréckelt...';
+$messages['deletingmessage'] = 'Messagë gi geläscht...';
+$messages['markingmessage'] = 'Messagë gi markéiert...';
+$messages['addingmember'] = 'Kontakter ginn an d\'grupp gesat...';
+$messages['removingmember'] = 'Kontakter ginn aus der Grupp erausgeholl...';
+$messages['receiptsent'] = 'Empfanksbestätegung erfollegräich verschéckt.';
+$messages['errorsendingreceipt'] = 'Konnt d\'Bestätegung net verschécken.';
+$messages['deleteidentityconfirm'] = 'Wëlls du dës Identitéit wierklech läschen?';
+$messages['nodeletelastidentity'] = 'Du kanns dës Identitéit net läschen, well et deng lescht ass.';
+$messages['forbiddencharacter'] = 'Den Numm vum Dossier enthält verbueden Zeechen.';
+$messages['selectimportfile'] = 'Wuel w.e.gl e Fichier aus fir eropzelueden.';
+$messages['addresswriterror'] = 'Dat ausgewieltent Adressbucht ass schreifgeschützt.';
+$messages['contactaddedtogroup'] = 'Kontakter erfollegräich an d\'Grupp gesat.';
+$messages['contactremovedfromgroup'] = 'Kontakter erfollegräich aus der Grupp erausgeholl.';
+$messages['nogroupassignmentschanged'] = 'Keng Gruppen-Zouuerdnung geännert.';
+$messages['importwait'] = 'Import leeft, ee Moment w.e.gl...';
+$messages['importformaterror'] = 'Import feelgeschloen! Den eropgeluedene Fichier ass kee gëltegen Date-Fichier.';
+$messages['importconfirm'] = '<b>$inserted Kontakter erfollegräich importéiert</b>';
+$messages['importconfirmskipped'] = '<b>$skipped existéierend Anträg iwwersprongen</b>';
+$messages['importmessagesuccess'] = 'Erfollegräich $nr Messagen importéiert';
+$messages['importmessageerror'] = 'Import feelgeschloen! Den eropgeluedene Fichier ass kee gëltege Message oder kee Mailbox-Fichier.';
+$messages['opnotpermitted'] = 'Operatioun net zougelooss!';
+$messages['nofromaddress'] = 'An der ausgewieltener Identitéit feelt d\'E-Mail-Adress.';
+$messages['editorwarning'] = 'Bei engem Wiessel op den Text-Editor ginn all d\'Formatéierunge verluer. Wëlls du sécher weidermaachen?';
+$messages['httpreceivedencrypterror'] = 'E fatale Konfiguratiouns-Feeler ass opgetrueden. Kontaktéier w.e.gl. den Administrator esou séier ewéi méiglech. <b>Däi Message kann net geschéckt ginn.</b> ';
+$messages['smtpconnerror'] = 'SMTP-Feeler ($code): Et konnt keng Verbindung mam Server hirgestallt ginn.';
+$messages['smtpautherror'] = 'SMTP-Feeler ($code): Authentifizéierung feelgeschloen.';
+$messages['smtpfromerror'] = 'SMTP-Feeler ($code): Den Ofsender "$from" konnt net gesat ginn ($msg).';
+$messages['smtptoerror'] = 'SMTP-Feeler ($code): Den Empfänger "$to" konnt net dobäigesat ginn ($msg).';
+$messages['smtprecipientserror'] = 'SMTP-Feeler: D\'Empfänger-Lëscht kann net verschafft ginn.';
+$messages['smtperror'] = 'SMTP-Feeler: $msg';
+$messages['emailformaterror'] = 'Ongëlteg E-Mail-Adress: $email';
+$messages['toomanyrecipients'] = 'Zevill Empfänger. Reduzéier d\'Zuel vun den Empfänger op $max.';
+$messages['maxgroupmembersreached'] = 'D\'Unzuel vu Gruppememberen iwwersteigt de Maximum vun $max.';
+$messages['internalerror'] = 'En interne Feeler ass opgetrueden. Probéier w.e.gl nach eng Kéier.';
+$messages['contactdelerror'] = 'Kontakter konnten net geläscht ginn.';
+$messages['contactdeleted'] = 'Kontakter erfollegräich geläscht.';
+$messages['contactrestoreerror'] = 'Déi geläschte Kontakter konnten net recuperéiert ginn.';
+$messages['contactrestored'] = 'Kontakter erfollegräich recuperéiert.';
+$messages['groupdeleted'] = 'Grupp erfollegräich geläscht.';
+$messages['grouprenamed'] = 'Grupp erfollegräich ëmbenannt.';
+$messages['groupcreated'] = 'Grupp erfollegräich creéiert.';
+$messages['savedsearchdeleted'] = 'Déi gespäicherte Sich gouf erfollegräich geläscht.';
+$messages['savedsearchdeleteerror'] = 'Déi gespäicherte Sich konnt net geläscht ginn.';
+$messages['savedsearchcreated'] = 'Déi gespäicherte Sich gouf erfollegräich erstallt.';
+$messages['savedsearchcreateerror'] = 'Déi gespäicherte Sich konnt net erstallt ginn.';
+$messages['messagedeleted'] = 'Messagen erfollegräich geläscht.';
+$messages['messagemoved'] = 'Messagen erfollegräich geréckelt.';
+$messages['messagecopied'] = 'Messagen erfollegräich kopéiert.';
+$messages['messagemarked'] = 'Messagen erfollegräich markéiert.';
+$messages['autocompletechars'] = 'Gëff e mimumum vun $min Zeechen u fir déi automatesch Vervollstänegung.';
+$messages['autocompletemore'] = 'Et goufe méi passend Treffer fonnt. Tipp w.e.gl. nach e puer Buschtawe méi.';
+$messages['namecannotbeempty'] = 'Den Numm kann net eidel sinn.';
+$messages['nametoolong'] = 'Den Numm ass ze laang.';
+$messages['folderupdated'] = 'Dossier erfollegräich aktualiséiert.';
+$messages['foldercreated'] = 'Dossier erfollegräich ugeluecht.';
+$messages['invalidimageformat'] = 'Kee gëltegt Bild-Format';
+$messages['mispellingsfound'] = 'Et goufe Schreiffeeler am Message fonnt.';
+$messages['parentnotwritable'] = 'Den Dossier konnt net am ausgewielten Dossier erstallt oder an den Dossier erageréckelt ginn. Keng Zougrëffsrechter.';
+$messages['messagetoobig'] = 'Den Messagen-Deel ass ze grouss fir verschafft ze ginn.';
+$messages['attachmentvalidationerror'] = 'WARNUNG! Dësen Unhank ass verdächteg well den tatsächlechen Typ vum Fichier net mam Typ deen am Message deklaréiert ass iwwertenee stëmmt. Falls du dem Ofsender net traus sollts du den Unhank net am Browser opmaache well e béisaartegen Inhalt enthaale kéint.<br/><br/><em>Erwaart: $expected; fonnt: $detected</em>';
+$messages['noscriptwarning'] = 'Warnung: Dëse Webmail brauch JavaScript! Fir de Service benotzen ze kënnen, aktivéier w.e.gl JavaScript an denge Browser-Astellungen.';
+
+?>
diff --git a/program/localization/lt_LT/labels.inc b/program/localization/lt_LT/labels.inc
index 6398a3683..31cb44d27 100644
--- a/program/localization/lt_LT/labels.inc
+++ b/program/localization/lt_LT/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'JuodraÅ¡Äiai';
$labels['sent'] = 'Išsiųsti laiškai';
$labels['trash'] = 'Šiukšlinė';
$labels['junk'] = 'Brukalas';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'Tema';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'Sąrašo rodymo veiksena';
$labels['folderactions'] = 'Veiksmai su aplankais…';
$labels['compact'] = 'Suglaudinti';
$labels['empty'] = 'Ištuštinti';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Disko naudojimas';
$labels['unknown'] = 'nežinomas';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Atšaukti paiešką';
$labels['searchmod'] = 'Paieškos modifikatoriai';
$labels['msgtext'] = 'Visas laiškas';
$labels['body'] = 'Laiško tekstas';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Atverti naujame lange';
$labels['emlsave'] = 'Parsisiųsti (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Rodyti paskutinį puslapį';
$labels['group'] = 'GrupÄ—';
$labels['groups'] = 'GrupÄ—s';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Asmeniniai adresai';
$labels['searchsave'] = 'Įrašyti kaip radinių aplanką';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Nepaisyti žodžių su skaitmenimis';
$labels['spellcheckignorecaps'] = 'Nepaisyti žodžių vien iš didžiųjų raidžių';
$labels['addtodict'] = 'Įtraukti į žodyną';
$labels['mailtoprotohandler'] = 'Užregistruoti svetainÄ™ kaip dirbanÄiÄ… su „mailto:“ saitais';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Laiškų persiuntimo būdas';
$labels['inline'] = 'kaip citatÄ…';
$labels['asattachment'] = 'kaip priedas';
diff --git a/program/localization/lv_LV/labels.inc b/program/localization/lv_LV/labels.inc
index 7d4de2564..0fe5b0faf 100644
--- a/program/localization/lv_LV/labels.inc
+++ b/program/localization/lv_LV/labels.inc
@@ -23,50 +23,51 @@ $labels['welcome'] = 'Esiet laipni lūgti $product';
$labels['username'] = 'LietotÄjvÄrds';
$labels['password'] = 'Parole';
$labels['server'] = 'Serveris';
-$labels['login'] = 'Pieslēgties';
+$labels['login'] = 'Autorizēties';
// taskbar
-$labels['logout'] = 'Atslēgties';
+$labels['logout'] = 'Iziet';
$labels['mail'] = 'E-pasts';
-$labels['settings'] = 'Personīgie iestatījumi';
+$labels['settings'] = 'Iestatījumi';
$labels['addressbook'] = 'AdreÅ¡u grÄmata';
// mailbox names
$labels['inbox'] = 'IenÄkoÅ¡Äs';
$labels['drafts'] = 'Uzmetumi';
$labels['sent'] = 'NosÅ«tÄ«tÄs';
-$labels['trash'] = 'Miskaste';
+$labels['trash'] = 'Papīrgrozs';
$labels['junk'] = 'MÄ“stules';
+$labels['show_real_foldernames'] = 'SistÄ“mas mapÄ“m rÄdÄ«t Ä«stos nosaukumus';
// message listing
$labels['subject'] = 'Temats';
$labels['from'] = 'No';
-$labels['sender'] = 'Sender';
+$labels['sender'] = 'SÅ«tÄ«tÄjs';
$labels['to'] = 'Kam';
$labels['cc'] = 'Cc';
$labels['bcc'] = 'Bcc';
-$labels['replyto'] = 'Reply-To';
-$labels['followupto'] = 'Followup-To';
+$labels['replyto'] = 'Atbildēt-Uz';
+$labels['followupto'] = 'Sekot-Uz';
$labels['date'] = 'Datums';
$labels['size'] = 'Izmērs';
$labels['priority'] = 'PrioritÄte';
$labels['organization'] = 'Uzņēmums';
$labels['readstatus'] = 'Izlasīšanas statuss';
-$labels['listoptions'] = 'List options...';
+$labels['listoptions'] = 'Vēstuļu saraksta attēlošanas iestatījumi...';
$labels['mailboxlist'] = 'Mapes';
$labels['messagesfromto'] = 'Vēstules $from līdz $to no $count';
$labels['threadsfromto'] = 'Vijumi $from līdz $to no $count';
-$labels['messagenrof'] = '$nr. vēstule no $count';
-$labels['fromtoshort'] = '$from – $to of $count';
+$labels['messagenrof'] = '$nr. vēstule no $count';
+$labels['fromtoshort'] = '$from – $to no $count';
$labels['copy'] = 'Kopēt';
$labels['move'] = 'PÄrvietot';
-$labels['moveto'] = 'pÄrvietot uz...';
+$labels['moveto'] = 'PÄrvietot uz...';
$labels['download'] = 'lejupielÄdÄ“t';
-$labels['open'] = 'Open';
-$labels['showattachment'] = 'Show';
-$labels['showanyway'] = 'Show it anyway';
+$labels['open'] = 'Atvērt';
+$labels['showattachment'] = 'RÄdÄ«t';
+$labels['showanyway'] = 'Vienalga rÄdÄ«t';
$labels['filename'] = 'Faila nosaukums';
$labels['filesize'] = 'Faila izmērs';
@@ -122,77 +123,78 @@ $labels['longdec'] = 'Decembris';
$labels['today'] = 'Å odien';
// toolbar buttons
-$labels['refresh'] = 'Refresh';
-$labels['checkmail'] = 'PÄrbaudÄ«t pastu';
+$labels['refresh'] = 'Atjaunot';
+$labels['checkmail'] = 'PÄrbaudÄ«t e-pastu';
$labels['compose'] = 'Rakstīt vēstuli';
$labels['writenewmessage'] = 'Rakstīt jaunu vēstuli';
-$labels['reply'] = 'Reply';
-$labels['replytomessage'] = 'Atbildēt';
-$labels['replytoallmessage'] = 'AtbildÄ“t sÅ«tÄ«tÄjam un visiem saņēmÄ“jiem';
+$labels['reply'] = 'Atbildēt';
+$labels['replytomessage'] = 'AtbildÄ“t sÅ«tÄ«tÄjam';
+$labels['replytoallmessage'] = 'AtbildÄ“t sÅ«tÄ«tÄjam vai listei un visiem adresÄtiem';
$labels['replyall'] = 'Atbildēt visiem';
$labels['replylist'] = 'Atbildēt listei';
-$labels['forward'] = 'Forward';
+$labels['forward'] = 'PÄrsÅ«tÄ«t';
$labels['forwardinline'] = 'PÄrsÅ«tÄ«t iekļaujot vÄ“stulÄ“';
$labels['forwardattachment'] = 'PÄrsÅ«tÄ«t kÄ pielikumu';
$labels['forwardmessage'] = 'PÄrsÅ«tÄ«t vÄ“stuli';
$labels['deletemessage'] = 'Dzēst vēstuli';
-$labels['movemessagetotrash'] = 'PÄrvietot vÄ“stuli uz miskasti';
-$labels['printmessage'] = 'izdrukÄt';
+$labels['movemessagetotrash'] = 'PÄrvietot vÄ“stuli uz papÄ«rgrozu';
+$labels['printmessage'] = 'IzdrukÄt Å¡o vÄ“stuli';
$labels['previousmessage'] = 'ParÄdÄ«t iepriekÅ¡Ä“jo vÄ“stuli';
$labels['firstmessage'] = 'ParÄdÄ«t pirmo vÄ“stuli';
$labels['nextmessage'] = 'ParÄdÄ«t nÄkamo vÄ“stuli';
$labels['lastmessage'] = 'ParÄdÄ«t pÄ“dÄ“jo vÄ“stuli';
$labels['backtolist'] = 'Atpakaļ uz vēstuļu sarakstu';
-$labels['viewsource'] = 'parÄdÄ«t pirmtekstu';
-$labels['mark'] = 'Mark';
-$labels['markmessages'] = 'MarÄ·Ä“t vÄ“stules kÄ:';
-$labels['markread'] = 'lasītas';
-$labels['markunread'] = 'nelasītas';
-$labels['markflagged'] = 'iezīmētas';
-$labels['markunflagged'] = 'neiezīmētas';
-$labels['moreactions'] = 'Citas darbības...';
-$labels['more'] = 'More';
-$labels['back'] = 'Back';
-$labels['options'] = 'Options';
-
-$labels['select'] = 'Iezīmēt';
-$labels['all'] = 'visas';
-$labels['none'] = 'Neviens';
+$labels['viewsource'] = 'ParÄdÄ«t pirmtekstu';
+$labels['mark'] = 'Atzīmēt';
+$labels['markmessages'] = 'AtzÄ«mÄ“t vÄ“stules kÄ:';
+$labels['markread'] = 'KÄ lasÄ«tas';
+$labels['markunread'] = 'KÄ nelasÄ«tas';
+$labels['markflagged'] = 'KÄ atÄ«mÄ“tas';
+$labels['markunflagged'] = 'KÄ neatzÄ«mÄ“tas';
+$labels['moreactions'] = 'Papildus darbības...';
+$labels['more'] = 'VairÄk';
+$labels['back'] = 'Atpakaļ';
+$labels['options'] = 'Opcijas';
+
+$labels['select'] = 'Atzīmēt';
+$labels['all'] = 'Visas';
+$labels['none'] = 'Nevienu';
$labels['currpage'] = 'PaÅ¡reizÄ“jÄ lapa';
-$labels['unread'] = 'nelasÄ«tÄs';
-$labels['flagged'] = 'iezÄ«mÄ“tÄs';
-$labels['unanswered'] = 'neatbildÄ“tÄs';
-$labels['withattachment'] = 'With attachment';
-$labels['deleted'] = 'dzÄ“stÄs';
-$labels['undeleted'] = 'Not deleted';
-$labels['invert'] = 'invertēt';
+$labels['unread'] = 'NelasÄ«tÄs';
+$labels['flagged'] = 'AtzÄ«mÄ“tÄs';
+$labels['unanswered'] = 'NeatbildÄ“tÄs';
+$labels['withattachment'] = 'Ar pielikumu';
+$labels['deleted'] = 'DzÄ“stÄs';
+$labels['undeleted'] = 'Nav izdzēstas';
+$labels['invert'] = 'Pretēji';
$labels['filter'] = 'Filtrēt';
-$labels['list'] = 'Saraksts';
-$labels['threads'] = 'Vijumi';
+$labels['list'] = 'RÄdÄ«t kÄ sarakstu';
+$labels['threads'] = 'RÄdÄ«t kÄ vijumus';
$labels['expand-all'] = 'Izvērst visus';
-$labels['expand-unread'] = 'Izvērst neizlasītos';
-$labels['collapse-all'] = 'Savērst visu';
-$labels['threaded'] = 'Savīts';
+$labels['expand-unread'] = 'IzvÄ“rst neizlasÄ«tÄs';
+$labels['collapse-all'] = 'Sakļaut visas';
+$labels['threaded'] = 'RÄdÄ«t vijumus';
$labels['autoexpand_threads'] = 'Izvērst vēstuļu vijumus';
-$labels['do_expand'] = 'visiem vijumiem';
-$labels['expand_only_unread'] = 'tikai tad, ja ir neizlasītas vēstules';
-$labels['fromto'] = 'SÅ«tÄ«tÄjs/SaņēmÄ“js';
-$labels['flag'] = 'Iezīmēts';
+$labels['do_expand'] = 'visus vijumus';
+$labels['expand_only_unread'] = 'tikai ar neizlasÄ«tÄm vÄ“stulÄ“m';
+$labels['fromto'] = 'No/Kam';
+$labels['flag'] = 'Atzīmēt';
$labels['attachment'] = 'Pielikums';
-$labels['nonesort'] = 'Neviens';
+$labels['nonesort'] = 'Neviena';
$labels['sentdate'] = 'Nosūtīšanas datums';
$labels['arrival'] = 'PienÄkÅ¡anas datums';
$labels['asc'] = 'augoša';
$labels['desc'] = 'dilstoša';
$labels['listcolumns'] = 'Saraksta kolonnas';
-$labels['listsorting'] = 'KÄrtot pÄ“c kolonnas';
+$labels['listsorting'] = 'KÄrtoÅ¡anas kolonnas';
$labels['listorder'] = 'KÄrtoÅ¡anas secÄ«ba';
-$labels['listmode'] = 'Saraksta režīms';
+$labels['listmode'] = 'Attēlošanas veids';
$labels['folderactions'] = 'Darbības ar mapēm...';
-$labels['compact'] = 'saspiest';
-$labels['empty'] = 'iztukšot';
+$labels['compact'] = 'Saspiest';
+$labels['empty'] = 'Iztukšot';
+$labels['importmessages'] = 'Importēt vēstules';
$labels['quota'] = 'Kvota';
$labels['unknown'] = 'nezinÄms';
@@ -200,35 +202,36 @@ $labels['unlimited'] = 'neierobežots';
$labels['quicksearch'] = 'Ä€rtÄ meklÄ“Å¡ana';
$labels['resetsearch'] = 'Atstatīt meklēšanu';
-$labels['searchmod'] = 'Meklēt laukos:';
-$labels['msgtext'] = 'VÄ“stules tekstÄ';
-$labels['body'] = 'Body';
+$labels['searchmod'] = 'Meklēšanas modifikatori:';
+$labels['msgtext'] = 'VisÄ vÄ“stulÄ“';
+$labels['body'] = 'Pamatteksts';
+$labels['type'] = 'Tips';
-$labels['openinextwin'] = 'atvÄ“rt jaunÄ logÄ';
+$labels['openinextwin'] = 'AtvÄ“rt jaunÄ logÄ';
$labels['emlsave'] = 'lejupielÄdÄ“t (.eml)';
-$labels['changeformattext'] = 'Display in plain text format';
-$labels['changeformathtml'] = 'Display in HTML format';
+$labels['changeformattext'] = 'RÄdÄ«t kÄ neformatÄ“tu tekstu';
+$labels['changeformathtml'] = 'RÄdÄ«t kÄ HTML formatÄ“tu';
// message compose
-$labels['editasnew'] = 'rediģēt kÄ jaunu';
-$labels['send'] = 'Send';
+$labels['editasnew'] = 'Rediģēt kÄ jaunu';
+$labels['send'] = 'Sūtīt';
$labels['sendmessage'] = 'Sūtīt vēstuli';
-$labels['savemessage'] = 'SaglabÄt uzmetumu';
+$labels['savemessage'] = 'SaglabÄt kÄ uzmetumu';
$labels['addattachment'] = 'Pievienot failu';
$labels['charset'] = 'Rakstzīmju kopa';
$labels['editortype'] = 'Redaktora tips';
$labels['returnreceipt'] = 'SaņemÅ¡anas apstiprinÄjums';
-$labels['dsn'] = 'Atskaite par piegÄdi';
+$labels['dsn'] = 'PiegÄdes atskaite';
$labels['mailreplyintro'] = '$sender @ $date rakstīja:';
$labels['originalmessage'] = 'SÄkotnÄ“jÄ vÄ“stule';
$labels['editidents'] = 'Rediģēt identitÄtes';
-$labels['spellcheck'] = 'Spell';
+$labels['spellcheck'] = 'IzrunÄt';
$labels['checkspelling'] = 'PÄrbaudÄ«t pareizrakstÄ«bu';
$labels['resumeediting'] = 'TurpinÄt rediģēšanu';
$labels['revertto'] = 'Atgriezt uz';
-$labels['attach'] = 'Attach';
+$labels['attach'] = 'Pievienot';
$labels['attachments'] = 'Pielikumi';
$labels['upload'] = 'AugÅ¡upielÄdÄ“t';
$labels['uploadprogress'] = '$percent ($current no $total)';
@@ -241,13 +244,13 @@ $labels['normal'] = 'NormÄla';
$labels['high'] = 'Augsta';
$labels['highest'] = 'AugstÄkÄ';
-$labels['nosubject'] = '(no subject)';
+$labels['nosubject'] = '(bez tēmas)';
$labels['showimages'] = 'RÄdÄ«t attÄ“lus';
-$labels['alwaysshow'] = 'VienmÄ“r rÄdÄ«t attÄ“lus no $sender';
+$labels['alwaysshow'] = 'VienmÄ“r rÄdÄ«t attÄ“lus vÄ“stulÄ“s, kuras sÅ«tÄ«jis $sender';
$labels['isdraft'] = 'Å is ir melnraksts.';
-$labels['andnmore'] = '$nr more...';
-$labels['togglemoreheaders'] = 'Show more message headers';
-$labels['togglefullheaders'] = 'Toggle raw message headers';
+$labels['andnmore'] = '$nr vairÄk...';
+$labels['togglemoreheaders'] = 'RÄdÄ«t galvenes papildus informÄciju';
+$labels['togglefullheaders'] = 'SlÄ“pt galvenes papildus informÄciju';
$labels['htmltoggle'] = 'HTML';
$labels['plaintoggle'] = 'VienkÄrÅ¡s teksts';
@@ -257,14 +260,14 @@ $labels['maxuploadsize'] = 'MaksimÄlais atļautais faila izmÄ“rs ir $size';
$labels['addcc'] = 'Pievienot Cc';
$labels['addbcc'] = 'Pievienot Bcc';
-$labels['addreplyto'] = 'Pievienot Reply-To';
+$labels['addreplyto'] = 'Pievienot Atbildēt-Uz';
$labels['addfollowupto'] = 'Pievienot Followup-To';
// mdn
-$labels['mdnrequest'] = 'Å Ä«s vÄ“stules sÅ«tÄ«tÄjs vÄ“las redzÄ“t vÄ“stules saņemÅ¡anas apstiprinÄjumu. Vai jÅ«s vÄ“laties nosÅ«tÄ«t apstiprinÄjumu?';
+$labels['mdnrequest'] = 'Å Ä«s vÄ“stules sÅ«tÄ«tÄjs vÄ“las redzÄ“t vÄ“stules saņemÅ¡anas apstiprinÄjumu. Vai JÅ«s vÄ“laties nosÅ«tÄ«t Å¡o apstiprinÄjumu?';
$labels['receiptread'] = 'SaņemÅ¡anas apstiprinÄjums';
-$labels['yourmessage'] = 'Å Ä«s ir jÅ«su vÄ“stules saņemÅ¡anas apstiprinÄjums';
-$labels['receiptnote'] = 'PiezÄ«me: Å Ä«s apsiprinÄjums nozÄ«mÄ“ tikai to, ka vÄ“stule tika parÄdÄ«ta uz saņēmÄja datora. Tas nenozÄ«mÄ“, ka saņēmÄ“js ir izlasÄ«jis vai izpratis vÄ“stules saturu.';
+$labels['yourmessage'] = 'Å is ir JÅ«su nosÅ«tÄ«tÄs vÄ“stules saņemÅ¡anas apstiprinÄjums';
+$labels['receiptnote'] = 'PiezÄ«me: Å is apsiprinÄjums nozÄ«mÄ“ tikai to, ka vÄ“stule tika parÄdÄ«ta uz saņēmÄja datora. Tas nenozÄ«mÄ“, ka saņēmÄ“js ir izlasÄ«jis vai sapratis vÄ“stules saturu.';
// address boook
$labels['name'] = 'UzrÄdÄ«tais vÄrds';
@@ -273,33 +276,33 @@ $labels['surname'] = 'UzvÄrds';
$labels['middlename'] = 'Otrais vÄrds';
$labels['nameprefix'] = 'Prefikss';
$labels['namesuffix'] = 'Sufikss';
-$labels['nickname'] = 'Iesauka (nick)';
+$labels['nickname'] = 'SegvÄrds';
$labels['jobtitle'] = 'Amats';
$labels['department'] = 'Nodaļa';
$labels['gender'] = 'Dzimums';
-$labels['maidenname'] = 'PirmslaulÄ«bu uzvÄrds';
+$labels['maidenname'] = 'PirmslaulÄ«bas uzvÄrds';
$labels['email'] = 'E-pasts';
$labels['phone'] = 'TÄlrunis';
$labels['address'] = 'Adrese';
$labels['street'] = 'Iela';
$labels['locality'] = 'Pilsēta';
-$labels['zipcode'] = 'Pasta kods';
+$labels['zipcode'] = 'Pasta indekss';
$labels['region'] = 'Novads';
$labels['country'] = 'Pilsēta';
$labels['birthday'] = 'Dzimšanas diena';
$labels['anniversary'] = 'Gadadiena';
-$labels['website'] = 'Web lapa';
+$labels['website'] = 'MÄjaslapa';
$labels['instantmessenger'] = 'IM';
$labels['notes'] = 'Piezīmes';
$labels['male'] = 'vīrietis';
$labels['female'] = 'sieviete';
$labels['manager'] = 'Menedžeris';
$labels['assistant'] = 'Asistents';
-$labels['spouse'] = 'LaulÄtais draugs';
+$labels['spouse'] = 'LaulÄtais';
$labels['allfields'] = 'Visi lauki';
$labels['search'] = 'Meklēt';
$labels['advsearch'] = 'PaplaÅ¡inÄtÄ meklÄ“Å¡ana';
-$labels['advanced'] = 'Advanced';
+$labels['advanced'] = 'PaplaÅ¡inÄtie iestatÄ«jumi';
$labels['other'] = 'Cits';
$labels['typehome'] = 'MÄjas';
@@ -307,22 +310,22 @@ $labels['typework'] = 'Darbs';
$labels['typeother'] = 'Cits';
$labels['typemobile'] = 'Mobilais tÄlrunis';
$labels['typemain'] = 'Galvenais';
-$labels['typehomefax'] = 'MÄjas Fax';
-$labels['typeworkfax'] = 'Darba Fax';
+$labels['typehomefax'] = 'Fakss mÄjÄs';
+$labels['typeworkfax'] = 'Fakss darbÄ';
$labels['typecar'] = 'Auto';
$labels['typepager'] = 'Peidžeris';
$labels['typevideo'] = 'Video';
$labels['typeassistant'] = 'Asistents';
-$labels['typehomepage'] = 'Web lapa';
+$labels['typehomepage'] = 'MÄjaslapa';
$labels['typeblog'] = 'Blogs';
$labels['typeprofile'] = 'Profils';
$labels['addfield'] = 'Pievienot lauku...';
-$labels['addcontact'] = 'Pievienot iezÄ«mÄ“to ierakstu adreÅ¡u grÄmatai';
-$labels['editcontact'] = 'Rediģēt adreÅ¡u grÄmatas ierakstu';
+$labels['addcontact'] = 'Pievienot jaunu kontaktu';
+$labels['editcontact'] = 'Rediģēt kontaktu';
$labels['contacts'] = 'Kontakti';
$labels['contactproperties'] = 'Kontakta īpašības';
-$labels['personalinfo'] = 'PersoniskÄ informÄcija';
+$labels['personalinfo'] = 'PersonÄ«gÄ informÄcija';
$labels['edit'] = 'Rediģēt';
$labels['cancel'] = 'Atcelt';
@@ -331,29 +334,30 @@ $labels['delete'] = 'Dzēst';
$labels['rename'] = 'PÄrdÄ“vÄ“t';
$labels['addphoto'] = 'Pievienot';
$labels['replacephoto'] = 'Aizvietot';
-$labels['uploadphoto'] = 'Upload photo';
+$labels['uploadphoto'] = 'AugÅ¡upielÄdÄ“t fotogrÄfiju';
-$labels['newcontact'] = 'Izveidot jaunu ierakstu';
-$labels['deletecontact'] = 'Dzēst iezīmētos ierakstus';
+$labels['newcontact'] = 'Izveidot jaunu kontaktu';
+$labels['deletecontact'] = 'Dzēst atzīmētos kontaktus';
$labels['composeto'] = 'Rakstīt vēstuli';
-$labels['contactsfromto'] = 'Ieraksti $from līdz $to no $count';
+$labels['contactsfromto'] = 'Ieraksti no $from lÄ«dz $to - kopÄ $count';
$labels['print'] = 'DrukÄt';
$labels['export'] = 'Eksportēt';
-$labels['exportall'] = 'Export all';
-$labels['exportsel'] = 'Export selected';
+$labels['exportall'] = 'Eksportēt visu';
+$labels['exportsel'] = 'Eksportēt atzīmēto';
$labels['exportvcards'] = 'EksportÄ“t kontaktus vCard formÄtÄ';
$labels['newcontactgroup'] = 'Izveidot jaunu kontaktu grupu';
$labels['grouprename'] = 'PÄrdÄ“vÄ“t grupu';
$labels['groupdelete'] = 'Izdzēst grupu';
-$labels['groupremoveselected'] = 'Remove selected contacts from group';
+$labels['groupremoveselected'] = 'Dzēst atzīmētos kontaktus no grupas';
-$labels['previouspage'] = 'ParÄdÄ«t iepriekÅ¡Ä“jo kopu';
-$labels['firstpage'] = 'ParÄdÄ«t pirmo kopu';
-$labels['nextpage'] = 'ParÄdÄ«t nÄkamo kopu';
-$labels['lastpage'] = 'ParÄdÄ«t pÄ“dÄ“jo kopu';
+$labels['previouspage'] = 'ParÄdÄ«t iepriekÅ¡Ä“jo lapu';
+$labels['firstpage'] = 'ParÄdÄ«t pirmo lapu';
+$labels['nextpage'] = 'ParÄdÄ«t nÄkamo lapu';
+$labels['lastpage'] = 'ParÄdÄ«t pÄ“dÄ“jo lapu';
$labels['group'] = 'Grupa';
$labels['groups'] = 'Grupas';
+$labels['listgroup'] = 'RÄdÄ«t grupas kontaktus';
$labels['personaladrbook'] = 'PersonÄ«gÄs adreses';
$labels['searchsave'] = 'SaglabÄt meklÄ“Å¡anas pieprasÄ«jumu';
@@ -362,72 +366,72 @@ $labels['searchdelete'] = 'DzÄ“st saglabÄto meklÄ“Å¡anas pieprasÄ«jumu';
$labels['import'] = 'Importēt';
$labels['importcontacts'] = 'Importēt kontaktus';
$labels['importfromfile'] = 'Importēt no faila:';
-$labels['importtarget'] = 'Pievienot jaunus kontaktus adreÅ¡u grÄmatai';
+$labels['importtarget'] = 'Pievienot jaunus kontaktus adreÅ¡u grÄmatai:';
$labels['importreplace'] = 'Aizvietot visu adreÅ¡u grÄmatu';
-$labels['importdesc'] = 'You can upload contacts from an existing address book.<br/>We currently support importing addresses from the <a href="http://en.wikipedia.org/wiki/VCard">vCard</a> or CSV (comma-separated) data format.';
+$labels['importdesc'] = 'JÅ«s varat ieimportÄ“t kontaktus no jau esoÅ¡as adreÅ¡u grÄmatas.<br/>Uz doto brÄ«di tiek atbalstÄ«ti <a href="http://en.wikipedia.org/wiki/VCard">vCard</a> vai CSV (ar komatu atdalÄ«tie) datu formÄti.';
$labels['done'] = 'Pabeigts';
// settings
$labels['settingsfor'] = 'Iestatījumi';
$labels['about'] = 'Par';
$labels['preferences'] = 'Iestatījumi';
-$labels['userpreferences'] = 'LietotÄja preferences';
-$labels['editpreferences'] = 'Rediģēt lietotÄja preferences';
+$labels['userpreferences'] = 'LietotÄja iestatÄ«jumi';
+$labels['editpreferences'] = 'Rediģēt iestatījumus';
$labels['identities'] = 'IdentitÄtes';
-$labels['manageidentities'] = 'Rediģēt Å¡Ä« konta identitÄtes';
+$labels['manageidentities'] = 'Rediģēt identitÄtes';
$labels['newidentity'] = 'Jauna identitÄte';
$labels['newitem'] = 'Jauns';
$labels['edititem'] = 'Rediģēt';
-$labels['preferhtml'] = 'Dot priekÅ¡roku HTML formatÄ“tÄm vÄ“stulÄ“m';
+$labels['preferhtml'] = 'RÄdÄ«t HTML formatÄ“tÄs vÄ“stules';
$labels['defaultcharset'] = 'NoklusÄ“tÄ rakstzÄ«mju kopa';
-$labels['htmlmessage'] = 'HTML vēstule';
-$labels['messagepart'] = 'Part';
-$labels['digitalsig'] = 'Digital Signature';
+$labels['htmlmessage'] = 'HTML formatēta vēstule';
+$labels['messagepart'] = 'Daļa';
+$labels['digitalsig'] = 'DigitÄlais paraksts';
$labels['dateformat'] = 'Datuma formÄts';
$labels['timeformat'] = 'Laika formÄts';
-$labels['prettydate'] = 'Formatēt datumus';
+$labels['prettydate'] = 'RÄdÄ«t Ä«sos datumus';
$labels['setdefault'] = 'Uzlikt kÄ noklusÄ“to';
-$labels['autodetect'] = 'AutomÄtiski';
+$labels['autodetect'] = 'AutomÄtiska';
$labels['language'] = 'Valoda';
$labels['timezone'] = 'Laika zona';
$labels['pagesize'] = 'Rindas lapÄ';
$labels['signature'] = 'Paraksts';
$labels['dstactive'] = 'Vasaras/ziemas laiks';
-$labels['showinextwin'] = 'Open message in a new window';
-$labels['composeextwin'] = 'Compose in a new window';
-$labels['htmleditor'] = 'Rakstīt HTML vēstules';
+$labels['showinextwin'] = 'VÄ“stules atvÄ“rt jaunÄ logÄ';
+$labels['composeextwin'] = 'VÄ“stuli rakstÄ«t jaunÄ logÄ';
+$labels['htmleditor'] = 'Rakstīt HTML formatētas vēstules';
$labels['htmlonreply'] = 'tikai atbildot uz HTML formatÄ“tÄm vÄ“stulÄ“m';
-$labels['htmlonreplyandforward'] = 'on forward or reply to HTML message';
-$labels['htmlsignature'] = 'HTML paraksts';
-$labels['showemail'] = 'Show email address with display name';
+$labels['htmlonreplyandforward'] = 'tikai pÄrsÅ«tot vai atbildot uz HTML formatÄ“tu vÄ“stuli';
+$labels['htmlsignature'] = 'HTML formatēts paraksts';
+$labels['showemail'] = 'Pie vÄrda rÄdÄ«t arÄ« e-pasta adresi';
$labels['previewpane'] = 'RÄdÄ«t priekÅ¡skatÄ«juma paneli';
-$labels['skin'] = 'Interfeisa izskats';
-$labels['logoutclear'] = 'Izejot no sistēmas, iztīrīt miskasti';
-$labels['logoutcompact'] = 'Izejot no sistēmas, saspiest iesūtni';
+$labels['skin'] = 'Saskarnes izskats';
+$labels['logoutclear'] = 'Izejot no e-pasta, iztīrīt papīrgrozu';
+$labels['logoutcompact'] = 'Izejot no e-pasta, saspiest iesūtni';
$labels['uisettings'] = 'LietotÄja saskarne';
$labels['serversettings'] = 'Servera iestatījumi';
$labels['mailboxview'] = 'Pastkastes skats';
$labels['mdnrequests'] = 'Vēstules izlasīšanas atskaites sūtīšana';
-$labels['askuser'] = 'jautÄt lietotÄjam';
+$labels['askuser'] = 'jautÄt man vai sÅ«tÄ«t';
$labels['autosend'] = 'sÅ«tÄ«t automÄtiski';
-$labels['autosendknown'] = 'automÄtiski sÅ«tÄ«t maniem kontaktiem, par citiem jautÄt';
-$labels['autosendknownignore'] = 'automÄtiski sÅ«tÄ«t maniem kontaktiem, citiem nesÅ«tÄ«t';
-$labels['ignore'] = 'ignorēt';
-$labels['readwhendeleted'] = 'AtzÄ«mÄ“t dzÄ“stÄs vÄ“stules kÄ izlasÄ«tas';
-$labels['flagfordeletion'] = 'DzÄ“Å¡ot marÄ·Ä“t vÄ“stules kÄ dzÄ“stas, bet nedzÄ“st';
+$labels['autosendknown'] = 'automÄtiski sÅ«tÄ«t ja pieprasÄ«tÄjs ir manos kontaktos, par citiem jautÄt';
+$labels['autosendknownignore'] = 'automÄtiski sÅ«tÄ«t ja pieprasÄ«tÄjs ir manos kontaktos, citiem ignorÄ“t un nesÅ«tÄ«t';
+$labels['ignore'] = 'ignorēt un nesūtīt';
+$labels['readwhendeleted'] = 'DzÄ“Å¡ot vÄ“stules tÄs atzÄ«mÄ“t kÄ izlasÄ«tas';
+$labels['flagfordeletion'] = 'DzÄ“Å¡ot vÄ“stules tÄs nedzÄ“st, bet marÄ·Ä“t kÄ dzÄ“Å¡amas';
$labels['skipdeleted'] = 'NerÄdÄ«t dzÄ“stÄs vÄ“stules';
-$labels['deletealways'] = 'IzdzÄ“st vÄ“stules, ja tÄs neizdodas pÄrvietot uz miskasti';
-$labels['deletejunk'] = 'Directly delete messages in Junk';
-$labels['showremoteimages'] = 'RÄdÄ«t attÄ“lus, kas atrodas uz cita servera';
-$labels['fromknownsenders'] = 'no zinÄmiem sÅ«tÄ«tÄjiem';
+$labels['deletealways'] = 'IzdzÄ“st vÄ“stules, ja tÄs neizdodas pÄrvietot uz papÄ«rgrozu';
+$labels['deletejunk'] = 'AutomÄtiski dzÄ“st vÄ“stules no mÄ“stuļu mapÄ«tes';
+$labels['showremoteimages'] = 'RÄdÄ«t vÄ“stulÄ“s attÄ“lus, kuri atrodas uz cita servera';
+$labels['fromknownsenders'] = 'tikai no zinÄmiem sÅ«tÄ«tÄjiem';
$labels['always'] = 'vienmēr';
$labels['showinlineimages'] = 'RÄdÄ«t pielikuma attÄ“lus zem vÄ“stules';
-$labels['autosavedraft'] = 'AutomÄtiski saglabÄt uzmetumu';
-$labels['everynminutes'] = 'ik pa $n minūti(ēm)';
-$labels['refreshinterval'] = 'Refresh (check for new messages, etc.)';
+$labels['autosavedraft'] = 'AutomÄtiski saglabÄt vÄ“stules uzmetumu';
+$labels['everynminutes'] = 'ik pēc $n minūtes(ēm)';
+$labels['refreshinterval'] = 'PÄrbaudÄ«t jaunÄs vÄ“stules';
$labels['never'] = 'nekad';
$labels['immediately'] = 'nekavējoties';
$labels['messagesdisplaying'] = 'Vēstuļu attēlošana';
@@ -437,44 +441,45 @@ $labels['2231folding'] = 'Pilns RFC 2231 (Thunderbird)';
$labels['miscfolding'] = 'RFC 2047/2231 (MS Outlook)';
$labels['2047folding'] = 'Pilns RFC 2047 (citi)';
$labels['force7bit'] = 'Izmantot MIME kodējumu 8-bitu simboliem';
-$labels['advancedoptions'] = 'PaplaÅ¡inÄti iestatÄ«jumi';
-$labels['focusonnewmessage'] = 'UztÄdÄ«t pÄrlÅ«ka fokusu uz jaunu vÄ“stuli';
-$labels['checkallfolders'] = 'PÄrbaudÄ«t visas mapes pÄ“c jaunÄm vÄ“stulÄ“m';
-$labels['displaynext'] = 'RÄdÄ«t nÄkamo vÄ“stuli pÄ“c dzÄ“Å¡anas/pÄrvietoÅ¡anas';
-$labels['defaultfont'] = 'NoklusÄ“tais fonts vÄ“stulei HTML formÄtÄ';
+$labels['advancedoptions'] = 'PaplaÅ¡inÄtie iestatÄ«jumi';
+$labels['focusonnewmessage'] = 'UzstÄdÄ«t pÄrlÅ«ka fokusu uz jaunu vÄ“stuli';
+$labels['checkallfolders'] = 'MeklÄ“t visÄs mapÄ“s jaunÄs vÄ“stules';
+$labels['displaynext'] = 'PÄ“c vÄ“stules dzÄ“Å¡anas/pÄrvietoÅ¡anas rÄdÄ«t nÄkamo vÄ“stuli';
+$labels['defaultfont'] = 'NoklusÄ“tais fonts vÄ“stulÄ“m HTML formÄtÄ';
$labels['mainoptions'] = 'Galvenie iestatījumi';
-$labels['browseroptions'] = 'Browser Options';
-$labels['section'] = 'Kategorija';
+$labels['browseroptions'] = 'PÄrlÅ«ka iestatÄ«jumi';
+$labels['section'] = 'Sadaļa';
$labels['maintenance'] = 'Uzturēšana';
$labels['newmessage'] = 'VÄ“stuļu pienÄkÅ¡ana';
$labels['signatureoptions'] = 'Paraksta iestatījumi';
$labels['whenreplying'] = 'Atbildot';
-$labels['replyempty'] = 'do not quote the original message';
+$labels['replyempty'] = 'neiekļaut vÄ“stules sÄkotnÄ“jo tekstu';
$labels['replytopposting'] = 'sÄkt jaunu vÄ“stuli virs oriÄ£inÄla';
$labels['replybottomposting'] = 'sÄkt jaunu vÄ“stuli zem oriÄ£inÄla';
$labels['replyremovesignature'] = 'Atbildot izņemt oriÄ£inÄlo parakstu no vÄ“stules';
$labels['autoaddsignature'] = 'AutomÄtiski pievienot parakstu';
-$labels['newmessageonly'] = 'tikai jaunas vēstules';
-$labels['replyandforwardonly'] = 'tikai atbildes un pÄrsÅ«tÄ«jumi';
+$labels['newmessageonly'] = 'tikai jaunÄm vÄ“stulÄ“m';
+$labels['replyandforwardonly'] = 'tikai atbildÄ“m un pÄrsÅ«tÄ«jumiem';
$labels['insertsignature'] = 'Ievietot parakstu';
$labels['previewpanemarkread'] = 'AtzÄ«mÄ“t priekÅ¡skatÄ«tÄs vÄ“stules kÄ lasÄ«tas';
$labels['afternseconds'] = 'pēc $n sekundēm';
-$labels['reqmdn'] = 'Vienmēr pieprasīt atskati par vēstules izlasīšanu';
-$labels['reqdsn'] = 'VienmÄ“r pieprasÄ«t atskati par vÄ“stules piegÄdÄÅ¡anu saņēmÄ“ja serverim';
+$labels['reqmdn'] = 'VienmÄ“r pieprasÄ«t saņemÅ¡anas apstiprinÄjumu';
+$labels['reqdsn'] = 'VienmÄ“r pieprasÄ«t atskati par piegÄdi';
$labels['replysamefolder'] = 'GlabÄt atbildes tajÄ paÅ¡Ä mapÄ“, kurÄ ir vÄ“stule, uz kuru tika atbildÄ“ts';
-$labels['defaultabook'] = 'Default address book';
-$labels['autocompletesingle'] = 'AutomÄtiski aizpildot, izlaist alternatÄ«vÄs e-pasta adreses';
-$labels['listnamedisplay'] = 'List contacts as';
-$labels['spellcheckbeforesend'] = 'PÄrbaudÄ«t pareizrakstÄ«bu pirms vÄ“stules nosÅ«tÄ«Å¡anas';
+$labels['defaultabook'] = 'NoklusÄ“tÄ adreÅ¡u grÄmata';
+$labels['autocompletesingle'] = 'AutomÄtiski aizpildot, nerÄdÄ«t alternatÄ«vÄs e-pasta adreses';
+$labels['listnamedisplay'] = 'RÄdÄ«t kontaktus kÄ';
+$labels['spellcheckbeforesend'] = 'Pirms vÄ“stules nosÅ«tÄ«Å¡anas pÄrbaudÄ«t pareizrakstÄ«bu';
$labels['spellcheckoptions'] = 'Pareizrakstības iestatījumi';
$labels['spellcheckignoresyms'] = 'IgnorÄ“t vÄrdus, kuri satur simbolus';
$labels['spellcheckignorenums'] = 'IgnorÄ“t vÄrdus, kuri satur skaitļus';
$labels['spellcheckignorecaps'] = 'IgnorÄ“t vÄrdus, kuri rakstÄ«ti ar lielajiem burtiem';
$labels['addtodict'] = 'Pievienot vÄrdnÄ«cai';
-$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
-$labels['forwardmode'] = 'Messages forwarding';
-$labels['inline'] = 'inline';
-$labels['asattachment'] = 'as attachment';
+$labels['mailtoprotohandler'] = 'Atverot mailto: saites, lietot Å¡o e-pasta programmu';
+$labels['standardwindows'] = 'IzlÄ“coÅ¡ie logi kÄ parasti logi';
+$labels['forwardmode'] = 'VÄ“stuļu pÄrsÅ«tÄ«Å¡ana';
+$labels['inline'] = 'iekļaujot';
+$labels['asattachment'] = 'kÄ pielikumu';
$labels['folder'] = 'Mapi';
$labels['folders'] = 'Mapes';
@@ -491,8 +496,8 @@ $labels['parentfolder'] = 'Virsmape';
$labels['location'] = 'AtraÅ¡anÄs vieta';
$labels['info'] = 'InformÄcija';
$labels['getfoldersize'] = 'UzklikÅ¡Ä·iniet, lai uzzinÄtu mapes izmÄ“ru';
-$labels['changesubscription'] = 'Uzklikšķiniet, lai mainītu abonēšanu';
-$labels['foldertype'] = 'Mapes veids';
+$labels['changesubscription'] = 'Uzklikšķiniet, lai mainītu abonēšanas iestatījumus';
+$labels['foldertype'] = 'Mapes tips';
$labels['personalfolder'] = 'PrivÄta mape';
$labels['otherfolder'] = 'Cita lietotÄja mape';
$labels['sharedfolder'] = 'Publiska mape';
@@ -502,7 +507,7 @@ $labels['sortasc'] = 'KÄrtot augoÅ¡Ä secÄ«bÄ';
$labels['sortdesc'] = 'KÄrtot dilstoÅ¡Ä secÄ«bÄ';
$labels['undo'] = 'Atsaukt';
-$labels['installedplugins'] = 'Installed plugins';
+$labels['installedplugins'] = 'UzstÄdÄ«tie spraudņi';
$labels['plugin'] = 'Spraudnis';
$labels['version'] = 'Versija';
$labels['source'] = 'OriÄ£inÄls';
@@ -516,7 +521,7 @@ $labels['MB'] = 'MB';
$labels['GB'] = 'GB';
// character sets
-$labels['unicode'] = 'Unikoda';
+$labels['unicode'] = 'Unikods';
$labels['english'] = 'Angļu';
$labels['westerneuropean'] = 'Rietumeiropas';
$labels['easterneuropean'] = 'Austrumeiropas';
diff --git a/program/localization/lv_LV/messages.inc b/program/localization/lv_LV/messages.inc
index b69a73e2b..37ceb0463 100644
--- a/program/localization/lv_LV/messages.inc
+++ b/program/localization/lv_LV/messages.inc
@@ -28,7 +28,7 @@ $messages['dberror'] = 'DatubÄzes kļūda!';
$messages['requesttimedout'] = 'PieprasÄ«jumam iestÄjÄs noilgums';
$messages['errorreadonly'] = 'NeizdevÄs veikt darbÄ«bu: mape ir tikai lasÄma (read only)';
$messages['errornoperm'] = 'NeizdevÄs veikt darbÄ«bu: piekļuve liegta';
-$messages['erroroverquota'] = 'OperÄciju nav iespÄ“jams veikt. Uz diska nav brÄ«vas veitas.';
+$messages['erroroverquota'] = 'OperÄciju veikt nav iespÄ“jams. Uz diska nav brÄ«vas veitas.';
$messages['erroroverquotadelete'] = 'Uz diska nav brīvas vietas. Lai dzēstu vēstuli, lietojiet SHIFT+DEL.';
$messages['invalidrequest'] = 'NederÄ«gs pieprasÄ«jums! Dati netika saglabÄti ...';
$messages['invalidhost'] = 'Nederīgs servera nosaukums';
@@ -45,7 +45,7 @@ $messages['sendingmessage'] = 'Tiek sūtīta vēstule ...';
$messages['messagesent'] = 'Vēstule nosūtīta veiksmīgi';
$messages['savingmessage'] = 'VÄ“stule tiek saglabÄta ...';
$messages['messagesaved'] = 'VÄ“stule saglabÄta Uzmetumos';
-$messages['successfullysaved'] = 'VÄ“stule veiksmÄ«gi saglabÄta';
+$messages['successfullysaved'] = 'VeiksmÄ«gi saglabÄts.';
$messages['addedsuccessfully'] = 'Kontakts veiksmÄ«gi pievienots adreÅ¡u grÄmatai';
$messages['contactexists'] = 'Kontakts ar Å¡Ädu e-pasta adresi jau eksistÄ“';
$messages['contactnameexists'] = 'Kontakts ar Å¡Ädu vÄrdu jau eksistÄ“.';
@@ -100,72 +100,74 @@ $messages['deletedsuccessfully'] = 'Veiksmīgi izdzēsts';
$messages['converting'] = 'Tiek noņemts vēstules formatējums...';
$messages['messageopenerror'] = 'NevarÄ“ja ielÄdÄ“t vÄ“stuli no servera';
$messages['fileuploaderror'] = 'Faila augÅ¡upielÄde neveiksmÄ«ga';
-$messages['filesizeerror'] = 'IelÄdÄ“tais fails pÄrsniedz pieļaujamo $size apjomu';
-$messages['copysuccess'] = 'Veiksmīgi nokopētas $nr vēstules';
-$messages['copyerror'] = 'Nevarēja nokopēt nevienu adresi';
+$messages['filesizeerror'] = 'AugÅ¡upielÄdÄ“tais fails pÄrsniedz pieļaujamo $size izmÄ“ru.';
+$messages['copysuccess'] = 'Veiksmīgi nokopētas $nr adreses.';
+$messages['copyerror'] = 'Nevarēja nokopēt nevienu adresi.';
$messages['sourceisreadonly'] = 'Adreses avots ir lasÄ«Å¡anas režīmÄ tikai';
-$messages['errorsavingcontact'] = 'NevarÄ“ja saglabÄt kontakta adreses';
-$messages['movingmessage'] = 'PÄrvietoju vÄ“stules...';
+$messages['errorsavingcontact'] = 'Kontakta adresi nevarÄ“ja saglabÄt.';
+$messages['movingmessage'] = 'PÄrvieto vÄ“stules...';
$messages['copyingmessage'] = 'Kopē vēstules...';
$messages['copyingcontact'] = 'Kopē kontaktus...';
$messages['deletingmessage'] = 'Dzēš vēstules...';
$messages['markingmessage'] = 'Atzīmē vēstules...';
-$messages['addingmember'] = 'Pievieno kontaktu(s) grupai...';
-$messages['removingmember'] = 'Atvieno kontaktu(s) no grupas...';
-$messages['receiptsent'] = 'SaņemÅ¡anas apstiprinÄjums nosÅ«tÄ«ts';
-$messages['errorsendingreceipt'] = 'NeizdevÄs nosÅ«tÄ«t apstiprinÄjumu';
-$messages['deleteidentityconfirm'] = 'Vai tieÅ¡Äm vÄ“laties dzÄ“st Å¡o identitÄti?';
-$messages['nodeletelastidentity'] = 'Å o identitÄti nevar izdzÄ“st, tÄ ir pati pÄ“dÄ“jÄ.';
-$messages['forbiddencharacter'] = 'Mapes nosaukums satur aizliegtus simbolus';
-$messages['selectimportfile'] = 'LÅ«dzu izvÄ“lieties failu, ko vÄ“laties augÅ¡upielÄdÄ“t';
-$messages['addresswriterror'] = 'IzvÄ“lÄ“tÄs adreÅ¡u grÄmatas datus nevar labot';
+$messages['addingmember'] = 'Kontaktus pievieno grupai...';
+$messages['removingmember'] = 'Kontaktus atvieno no grupas...';
+$messages['receiptsent'] = 'SaņemÅ¡anas apstiprinÄjums nosÅ«tÄ«ts veiksmÄ«gi.';
+$messages['errorsendingreceipt'] = 'NeizdevÄs nosÅ«tÄ«t saņemÅ¡anas apstiprinÄjumu.';
+$messages['deleteidentityconfirm'] = 'Vai JÅ«s tieÅ¡Äm vÄ“laties dzÄ“st Å¡o identitÄti?';
+$messages['nodeletelastidentity'] = 'Å o identitÄti nav iespÄ“jams izdzÄ“st, jo tÄ ir pati pÄ“dÄ“jÄ.';
+$messages['forbiddencharacter'] = 'Mapes nosaukums satur aizliegtus simbolus.';
+$messages['selectimportfile'] = 'LÅ«dzu norÄdiet failu, kuru vÄ“laties augÅ¡upielÄdÄ“t.';
+$messages['addresswriterror'] = 'IzvÄ“lÄ“tÄs adreÅ¡u grÄmatas datus nav iespÄ“jams rediģēt.';
$messages['contactaddedtogroup'] = 'Kontakti tika veiksmīgi pievienoti šai grupai.';
$messages['contactremovedfromgroup'] = 'Kontakti tika veiksmīgi atvienoti no šīs grupas.';
$messages['nogroupassignmentschanged'] = 'GrupÄ nekas netika mainÄ«ts.';
$messages['importwait'] = 'Importēju, lūdzu uzgaidiet...';
$messages['importformaterror'] = 'Imports neizdevÄs! AugÅ¡upielÄdÄ“tais fails nav derÄ«gs importam.';
-$messages['importconfirm'] = '<b>Veiksmīgi ieimportēti $inserted kontakti, netika importēti $skipped esoši ieraksti</b>:<p><em>$names</em></p>';
+$messages['importconfirm'] = '<b>Veiksmīgi ieimportēti $inserted kontakti</b>';
$messages['importconfirmskipped'] = '<b>Izlaida $skipped jau eksistējošus ierakstus</b>';
+$messages['importmessagesuccess'] = 'Veiksmīgi ieimportētas $nr vēstules';
+$messages['importmessageerror'] = 'ImportÄ“Å¡anas kļūda! AugÅ¡upielÄdÄ“tÄ datne satur nekorektus datus';
$messages['opnotpermitted'] = 'Darbība nav atļauta!';
-$messages['nofromaddress'] = 'IzvÄ“lÄ“tajai identitÄtei nav norÄdÄ«ta e-pasta adrese';
-$messages['editorwarning'] = 'PÄrslÄ“dzoties uz vienkÄrÅ¡otu teksta redaktoru, tiks pazaudÄ“ts esoÅ¡ais teksta formatÄ“jums. Vai vÄ“laties turpinÄt?';
-$messages['httpreceivedencrypterror'] = 'Kļūme. Lūdzu sazinieties ar administratoru. <b>Nav iespējams nosūtīt vēstuli.</b>';
+$messages['nofromaddress'] = 'IzvÄ“lÄ“tajai identitÄtei nav norÄdÄ«ta e-pasta adrese.';
+$messages['editorwarning'] = 'PÄrslÄ“dzoties uz vienkÄrÅ¡otu teksta redaktoru, tiks pazaudÄ“ts esoÅ¡ais teksta formatÄ“jums. Vai tieÅ¡Äm vÄ“laties turpinÄt?';
+$messages['httpreceivedencrypterror'] = 'Notika kritiska kļūme. Lūdzu nekavējoties sazinieties ar Jūsu administratoru. <b>Jūsu vēstuli nosūtīt nav iespējams.</b>';
$messages['smtpconnerror'] = 'SMTP kļūme ($code): NeizdevÄs pieslÄ“gties serverim';
-$messages['smtpautherror'] = 'SMTP kļūme ($code): NeizdevÄs autentificÄ“ties';
-$messages['smtpfromerror'] = 'SMTP kļūme ($code): NeizdevÄs iestatÄ«t sÅ«tÄ«tÄju "$from" ($msg)';
-$messages['smtptoerror'] = 'SMTP kļūme ($code): NeizdevÄs pievienot saņēmÄ“ju "$to" ($msg)';
-$messages['smtprecipientserror'] = 'SMTP kļūme: Nav iespējams parsēt saņēmēju sarakstu';
-$messages['smtperror'] = 'SMTP kļūme: $msg';
+$messages['smtpautherror'] = 'SMTP kļūda ($code): NeizdevÄs autorizÄ“ties.';
+$messages['smtpfromerror'] = 'SMTP kļūda ($code): NeizdevÄs iestatÄ«t sÅ«tÄ«tÄju "$from" ($msg).';
+$messages['smtptoerror'] = 'SMTP kļūda ($code): NeizdevÄs pievienot saņēmÄ“ju "$to" ($msg).';
+$messages['smtprecipientserror'] = 'SMTP kļūda: Nav iespÄ“jams aptrÄdÄt saņēmÄ“ju sarakstu.';
+$messages['smtperror'] = 'SMTP kļūda: $msg';
$messages['emailformaterror'] = 'Nepareiza e-pasta adrese: $email';
$messages['toomanyrecipients'] = 'PÄrÄk daudz saņēmÄ“ju. Samaziniet skaitu lÄ«dz $max.';
$messages['maxgroupmembersreached'] = 'Grupas dalÄ«bnieku skaits pÄrsniedz limitu $max.';
-$messages['internalerror'] = 'Servera iekÅ¡Ä“jÄ kļūda. LÅ«dzu mÄ“Ä£iniet vÄ“lreiz.';
-$messages['contactdelerror'] = 'NeizdevÄs izdzÄ“st kontaktu(s).';
-$messages['contactdeleted'] = 'Kontakti veiksmīgi izdzēsti.';
-$messages['contactrestoreerror'] = 'NeizdevÄs atjaunot izdzÄ“stos kontaktus.';
-$messages['contactrestored'] = 'Kontakti veiksmīgi atjaunoti.';
-$messages['groupdeleted'] = 'Grupa veiksmīgi izdzēsta.';
-$messages['grouprenamed'] = 'Grupa veiksmÄ«gi pÄrdÄ“vÄ“ta.';
-$messages['groupcreated'] = 'Grupa veiksmīgi izveidota.';
-$messages['savedsearchdeleted'] = 'SaglabÄtais meklÄ“Å¡anas pieprasÄ«jums veiksmÄ«gi dzÄ“sts.';
-$messages['savedsearchdeleteerror'] = 'NeizdevÄs nodzÄ“st saglabÄto meklÄ“Å¡anas pieprasÄ«jumu.';
-$messages['savedsearchcreated'] = 'SaglabÄtais meklÄ“Å¡anas pieprasÄ«jums veiksmÄ«gi saglabÄts.';
-$messages['savedsearchcreateerror'] = 'NeizdevÄs saglabÄt meklÄ“Å¡anas pieprasÄ«jumu.';
+$messages['internalerror'] = 'Notika servera iekÅ¡Ä“jÄ kļūda. LÅ«dzu mÄ“Ä£iniet vÄ“lreiz.';
+$messages['contactdelerror'] = 'Kontaktus izdzÄ“st neizdevÄs.';
+$messages['contactdeleted'] = 'Kontakti izdzēsti veiksmīgi.';
+$messages['contactrestoreerror'] = 'IzdzÄ“stos kontaktus atjaunot neizdevÄs.';
+$messages['contactrestored'] = 'Kontakti atjaunoti veiksmīgi.';
+$messages['groupdeleted'] = 'Grupa izdzēsta veiksmīgi.';
+$messages['grouprenamed'] = 'Grupa pÄrdÄ“vÄ“ta veiksmÄ«gi.';
+$messages['groupcreated'] = 'Grupa izveidota veiksmīgi.';
+$messages['savedsearchdeleted'] = 'SaglabÄtais meklÄ“Å¡anas pieprasÄ«jums izdzÄ“sts veiksmÄ«gi.';
+$messages['savedsearchdeleteerror'] = 'SaglabÄto meklÄ“Å¡anas pieprasÄ«jumu izdzÄ“st neizdevÄs.';
+$messages['savedsearchcreated'] = 'SaglabÄtais meklÄ“Å¡anas pieprasÄ«jums saglabÄts veiksmÄ«gi.';
+$messages['savedsearchcreateerror'] = 'MeklÄ“Å¡anas pieprasÄ«jumu izveidot neizdevÄs.';
$messages['messagedeleted'] = 'Vēstule(s) veiksmīgi izdzēsta(s).';
$messages['messagemoved'] = 'VÄ“stule(s) veiksmÄ«gi pÄrvietota(s).';
$messages['messagecopied'] = 'VÄ“stule(s) veiksmÄ«gi pÄrkopÄ“ta(s).';
-$messages['messagemarked'] = 'Vēstule(s) veiksmīgi iezīmēta(s).';
-$messages['autocompletechars'] = 'Ievadiet vismaz $min burtus, lai meklÄ“tu automÄtiski.';
-$messages['autocompletemore'] = 'Atrasti vairÄki ieraksti. Papildiniet meklÄ“Å¡anas kritÄ“riju.';
+$messages['messagemarked'] = 'Vēstule(s) veiksmīgi atzīmēta(s).';
+$messages['autocompletechars'] = 'Lai automÄtiski meklÄ“tu, ievadiet vismaz $min burtus.';
+$messages['autocompletemore'] = 'Atrasti vairÄki ieraksti. Papildiniet meklÄ“Å¡anas kritÄ“riju ar vairÄk burtiem.';
$messages['namecannotbeempty'] = 'LÅ«dzu ievadiet vÄrdu.';
-$messages['nametoolong'] = 'VÄrds ir par garu.';
+$messages['nametoolong'] = 'VÄrds ir pÄrÄk garÅ¡.';
$messages['folderupdated'] = 'Mape vieksmīgi atjaunota.';
$messages['foldercreated'] = 'Mape veiksmīgi izveidota.';
$messages['invalidimageformat'] = 'NederÄ«gs attÄ“la formÄts.';
$messages['mispellingsfound'] = 'Vēstulē atrastas pareizrakstības kļūdas.';
-$messages['parentnotwritable'] = 'NeizdevÄs izveidot/pÄrvietot mapi uz atzÄ«mÄ“to virsmapi. Nav piekļuves tiesÄ«bu.';
-$messages['messagetoobig'] = 'VÄ“stule ir pÄrÄk liela, lai to varÄ“tu apstrÄdÄt.';
+$messages['parentnotwritable'] = 'NeizdevÄs izveidot/pÄrvietot mapi atzÄ«mÄ“tajÄ virsmapÄ“. Nav piekļuves tiesÄ«bu.';
+$messages['messagetoobig'] = 'VÄ“stule daļa ir pÄrÄk liela, lai to varÄ“tu apstrÄdÄt.';
$messages['attachmentvalidationerror'] = 'BRĪDINÄ€JUMS! Å is pielikums ir aizdomÄ«gs, jo tÄ tips neatbilst tipam, kurÅ¡ ir uzrÄdÄ«ts e-pasta ziņojumÄ. Ja jÅ«s neuzticaties sÅ«tÄ«tÄjam, Å¡o failu Jums vaÄ¼Ä vÄ“rt nevajadzÄ“tu, jo tas var saturÄ“t ļaunprÄtÄ«gu saturu. <br/><br/><em>BÅ«tu jÄbÅ«t: $expected; Bet ir: $detected</em>';
-$messages['noscriptwarning'] = 'UzmanÄ«bu: lai lasÄ«tu e-pastus, JÅ«su tÄ«mekļa pÄrlÅ«kÄ jÄbÅ«t iespÄ“jotiem JavaScript.';
+$messages['noscriptwarning'] = 'UzmanÄ«bu: lai lasÄ«tu e-pastus, JÅ«su pÄrlÅ«kprogrammÄ jÄbÅ«t ieslÄ“gtiem JavaScript.';
?>
diff --git a/program/localization/mk_MK/labels.inc b/program/localization/mk_MK/labels.inc
index bb9606e6a..519df5823 100755
--- a/program/localization/mk_MK/labels.inc
+++ b/program/localization/mk_MK/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Ðепратени';
$labels['sent'] = 'Пратени';
$labels['trash'] = 'Корпа';
$labels['junk'] = 'Ѓубре';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'ÐаÑлов';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode';
$labels['folderactions'] = 'Folder actions...';
$labels['compact'] = 'Компактно';
$labels['empty'] = 'ИÑпразни';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'ИÑкориÑтен проÑтор';
$labels['unknown'] = 'непознато';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Ðово пребарување';
$labels['searchmod'] = 'Модификатори на пребарувањето';
$labels['msgtext'] = 'Цело пиÑмо';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Отвори во нов прозорец';
$labels['emlsave'] = 'Преземи (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Прикажи ја поÑледната Ñтран
$labels['group'] = 'Group';
$labels['groups'] = 'Групи';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Лични адреÑи';
$labels['searchsave'] = 'Save search';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers';
$labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized';
$labels['addtodict'] = 'Add to dictionary';
$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Messages forwarding';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'as attachment';
diff --git a/program/localization/ml_IN/labels.inc b/program/localization/ml_IN/labels.inc
index ed0e7402a..7d3fdc501 100644
--- a/program/localization/ml_IN/labels.inc
+++ b/program/localization/ml_IN/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'പൂരàµâ€à´¤àµà´¤à´¿à´¯à´¾à´•à´¾à´¤àµà´¤à´µ';
$labels['sent'] = 'അയചàµà´šà´µ';
$labels['trash'] = 'ചവറàµà´±àµà´•àµà´Ÿàµà´Ÿ';
$labels['junk'] = 'ആവശàµà´¯à´®à´¿à´²àµà´²à´¾à´¤àµà´¤à´µ';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'വിഷയം';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode';
$labels['folderactions'] = 'Folder actions...';
$labels['compact'] = 'à´šàµà´°àµà´•àµà´•àµ';
$labels['empty'] = 'ശൂനàµà´¯à´‚';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'à´¡à´¿à´¸àµà´•àµà´•àµ ഉപയോഗം';
$labels['unknown'] = 'അറിയാതàµà´¤';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Reset search';
$labels['searchmod'] = 'Search modifiers';
$labels['msgtext'] = 'à´®àµà´´àµà´µà´¨àµâ€ സനàµà´¦àµ‡à´¶à´µàµà´‚';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'à´ªàµà´¤à´¿à´¯ വിനàµâ€à´¡àµ‹à´¯à´¿à´²àµâ€ à´¤àµà´±à´•àµà´•àµà´•';
$labels['emlsave'] = 'Download (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Show last page';
$labels['group'] = 'കൂടàµà´Ÿà´‚';
$labels['groups'] = 'കൂടàµà´Ÿà´™àµà´™à´³àµâ€';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'à´¸àµà´µà´•à´¾à´°àµà´¯ വിലാസങàµà´™à´³àµâ€';
$labels['searchsave'] = 'തിരയലàµâ€ സൂകàµà´·à´¿à´•àµà´•àµà´•';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'à´…à´•àµà´•à´™àµà´™à´³àµâ€ ഉളàµà´³ à
$labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized';
$labels['addtodict'] = 'നിഘണàµà´Ÿàµà´µà´¿à´²àµâ€ ചേരàµâ€à´•àµà´•àµà´•';
$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Messages forwarding';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'as attachment';
diff --git a/program/localization/mr_IN/labels.inc b/program/localization/mr_IN/labels.inc
index 02b129e0b..d26583d4d 100755
--- a/program/localization/mr_IN/labels.inc
+++ b/program/localization/mr_IN/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'मसà¥à¤¦à¤¾';
$labels['sent'] = 'पाठवलेले';
$labels['trash'] = 'कचरा पेटी';
$labels['junk'] = 'नको असलेले कचरा संदेश';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'विषय';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'यादी दरà¥à¤¶à¤• पधà¥â€à¤¦à¤¤';
$labels['folderactions'] = 'फोलà¥à¤¡à¤° कृती..';
$labels['compact'] = 'छोटा';
$labels['empty'] = 'रिकामा';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'डिसà¥à¤•à¤šà¤¾ वापर';
$labels['unknown'] = 'माहित नसलेला';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'परत शोध';
$labels['searchmod'] = 'बदलकरà¥à¤¤à¥â€à¤¯à¤¾à¤‚ना शोधा';
$labels['msgtext'] = 'संपूरà¥à¤£ संदेश';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'नवीन खिडकी उघडा';
$labels['emlsave'] = 'इà¤à¤®à¤à¤² सà¥â€à¤µà¤°à¥‚पात उतरवून घà¥à¤¯à¤¾';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'शेवटचा संच दाखवा';
$labels['group'] = 'गट';
$labels['groups'] = 'अनेक गट';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'वैयकà¥à¤¤à¤¿à¤• पतà¥à¤¤à¥‡';
$labels['searchsave'] = 'शोध जतन करा';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers';
$labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized';
$labels['addtodict'] = 'Add to dictionary';
$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Messages forwarding';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'as attachment';
diff --git a/program/localization/ms_MY/labels.inc b/program/localization/ms_MY/labels.inc
index 318af05ad..a6bdfbfa0 100644
--- a/program/localization/ms_MY/labels.inc
+++ b/program/localization/ms_MY/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Draf';
$labels['sent'] = 'Hantar';
$labels['trash'] = 'Tong Sampah';
$labels['junk'] = 'Junk';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'Subjek';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'Mod senarai paparan';
$labels['folderactions'] = 'Aksi folder';
$labels['compact'] = 'Kompak';
$labels['empty'] = 'Kosong';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Penggunaan cakera';
$labels['unknown'] = 'tidak diketahui';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Set semula carian';
$labels['searchmod'] = 'Pengubah carian';
$labels['msgtext'] = 'Keseluruhan mesej';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Buka dalam tetingkap baru';
$labels['emlsave'] = 'Muat-turun (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Papar set akhir';
$labels['group'] = 'Group';
$labels['groups'] = 'Kumpulan';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Alamat-alamat Peribadi';
$labels['searchsave'] = 'Save search';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers';
$labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized';
$labels['addtodict'] = 'Add to dictionary';
$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Messages forwarding';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'as attachment';
diff --git a/program/localization/nb_NO/labels.inc b/program/localization/nb_NO/labels.inc
index cba58dc9c..b5c8ce4c6 100644
--- a/program/localization/nb_NO/labels.inc
+++ b/program/localization/nb_NO/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Kladd';
$labels['sent'] = 'Sendt';
$labels['trash'] = 'Slettet';
$labels['junk'] = 'Spam';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'Emne';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'Listevisningsmodus';
$labels['folderactions'] = 'Mappehandlinger...';
$labels['compact'] = 'Rydd opp';
$labels['empty'] = 'Tøm';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Plassforbruk';
$labels['unknown'] = 'ukjent';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Nullstill søk';
$labels['searchmod'] = 'Søke felt';
$labels['msgtext'] = 'Hele meldingen';
$labels['body'] = 'Meldingstekst';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Ã…pne i nytt vindu';
$labels['emlsave'] = 'Last ned (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Vis siste sett';
$labels['group'] = 'Gruppe';
$labels['groups'] = 'Grupper';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Egne adresser';
$labels['searchsave'] = 'Lagre søk';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignorer ord med tall';
$labels['spellcheckignorecaps'] = 'Ignorer ord med kun store bokstaver';
$labels['addtodict'] = 'Legg til i ordbok';
$labels['mailtoprotohandler'] = 'Registrer protokollhåndtering for mailto-lenker';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Meldinger videresendes';
$labels['inline'] = 'i teksten';
$labels['asattachment'] = 'som vedlegg';
diff --git a/program/localization/ne_NP/labels.inc b/program/localization/ne_NP/labels.inc
index 29d43ef9c..5f69e1916 100644
--- a/program/localization/ne_NP/labels.inc
+++ b/program/localization/ne_NP/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'डà¥à¤°à¤¾à¤«à¥à¤Ÿà¤¹à¤°à¥‚';
$labels['sent'] = 'पठईà¤à¤•à¤¾ मेलहरà¥';
$labels['trash'] = 'रदà¥à¤¦à¥€ टोकरी';
$labels['junk'] = 'सà¥à¤ªà¤¾à¤®';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'विषय';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode';
$labels['folderactions'] = 'Folder actions...';
$labels['compact'] = 'छोटो गरà¥à¤¨à¥à¤¹à¥‹à¤¸';
$labels['empty'] = 'खाली गरà¥à¤¨à¥‡';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'डिसà¥à¤•à¤•à¥‹ उपभोग';
$labels['unknown'] = 'अजà¥à¤žà¤¾à¤¤';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'पन: खोज';
$labels['searchmod'] = 'Search modifiers';
$labels['msgtext'] = 'Entire message';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Open in new window';
$labels['emlsave'] = 'Download (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'अनà¥à¤¤à¤¿à¤® सेट देखाउनà¥à
$labels['group'] = 'Group';
$labels['groups'] = 'समूहहरà¥';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'वà¥à¤¯à¤•à¥à¤¤à¤¿à¤—त ठेगानाहरà¥';
$labels['searchsave'] = 'Save search';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers';
$labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized';
$labels['addtodict'] = 'Add to dictionary';
$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Messages forwarding';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'as attachment';
diff --git a/program/localization/nl_BE/labels.inc b/program/localization/nl_BE/labels.inc
index eb44eefc0..1e6bb2d2f 100644
--- a/program/localization/nl_BE/labels.inc
+++ b/program/localization/nl_BE/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Concepten';
$labels['sent'] = 'Verzonden berichten';
$labels['trash'] = 'Prullenbak';
$labels['junk'] = 'Spam';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'Onderwerp';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'Lijstweergave mode';
$labels['folderactions'] = 'Acties voor map...';
$labels['compact'] = 'Comprimeren';
$labels['empty'] = 'Legen';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Gebruikte schijfruimte';
$labels['unknown'] = 'onbekend';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Zoek opnieuw';
$labels['searchmod'] = 'Zoekopties';
$labels['msgtext'] = 'Volledig bericht';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Openen in een nieuw venster';
$labels['emlsave'] = 'Opslaan (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Toon laatste';
$labels['group'] = 'Groep';
$labels['groups'] = 'Groepen';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Personlijke adressen';
$labels['searchsave'] = 'Save search';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers';
$labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized';
$labels['addtodict'] = 'Add to dictionary';
$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Messages forwarding';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'as attachment';
diff --git a/program/localization/nl_NL/labels.inc b/program/localization/nl_NL/labels.inc
index 7bd48bd4a..8a6f994fa 100644
--- a/program/localization/nl_NL/labels.inc
+++ b/program/localization/nl_NL/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Concepten';
$labels['sent'] = 'Verzonden';
$labels['trash'] = 'Prullenbak';
$labels['junk'] = 'Spam';
+$labels['show_real_foldernames'] = 'Toon echte namen voor speciale mappen';
// message listing
$labels['subject'] = 'Onderwerp';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'Lijstweergave';
$labels['folderactions'] = 'Mapacties...';
$labels['compact'] = 'Opschonen';
$labels['empty'] = 'Legen';
+$labels['importmessages'] = 'Berichten importeren';
$labels['quota'] = 'Opslagverbruik';
$labels['unknown'] = 'onbekend';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Wis zoekopdracht';
$labels['searchmod'] = 'Zoekopties';
$labels['msgtext'] = 'Gehele bericht';
$labels['body'] = 'Inhoud';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Openen in een nieuw venster';
$labels['emlsave'] = 'Opslaan (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Laatste pagina';
$labels['group'] = 'Groep';
$labels['groups'] = 'Groepen';
+$labels['listgroup'] = 'Toon groepsleden';
$labels['personaladrbook'] = 'Persoonlijk adresboek';
$labels['searchsave'] = 'Zoekopdracht opslaan';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Negeer woorden met cijfers';
$labels['spellcheckignorecaps'] = 'Negeer woorden welke volledig uit hoofdletters bestaan';
$labels['addtodict'] = 'Voeg toe aan woordenboek';
$labels['mailtoprotohandler'] = 'Registreer protocolhandler voor mailto: links';
+$labels['standardwindows'] = 'Behandel pop-ups als normale vensters';
$labels['forwardmode'] = 'Berichten doorsturen';
$labels['inline'] = 'invoegen';
$labels['asattachment'] = 'als bijlage';
diff --git a/program/localization/nn_NO/labels.inc b/program/localization/nn_NO/labels.inc
index d1a1c5700..5934a01d9 100644
--- a/program/localization/nn_NO/labels.inc
+++ b/program/localization/nn_NO/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Kladd';
$labels['sent'] = 'Sendt';
$labels['trash'] = 'Sletta';
$labels['junk'] = 'Søppel';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'Emne';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'Listevisningmodus';
$labels['folderactions'] = 'Mappehandlingar';
$labels['compact'] = 'Kompakt';
$labels['empty'] = 'Tom';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Plassbruk';
$labels['unknown'] = 'ukjend';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Tilbakestill søk';
$labels['searchmod'] = 'Søkeutsagn';
$labels['msgtext'] = 'Heile eposten';
$labels['body'] = 'Meldingstekst';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Opna i nytt vindauga';
$labels['emlsave'] = 'Last ned (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Siste side';
$labels['group'] = 'Gruppe';
$labels['groups'] = 'Gruppar';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Personlege adresser';
$labels['searchsave'] = 'Lagre søk';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignorer ord med tal';
$labels['spellcheckignorecaps'] = 'Ignorer ord med berre store bokstavar';
$labels['addtodict'] = 'Legg til i ordliste';
$labels['mailtoprotohandler'] = 'Registrer protokollhandsaming for mailto-lenkjer';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Meldingar vidaresendast';
$labels['inline'] = 'i teksten';
$labels['asattachment'] = 'som vedlegg';
diff --git a/program/localization/pl_PL/labels.inc b/program/localization/pl_PL/labels.inc
index 426ac381e..d7b9cd2d4 100644
--- a/program/localization/pl_PL/labels.inc
+++ b/program/localization/pl_PL/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Kopie robocze';
$labels['sent'] = 'Wysłane';
$labels['trash'] = 'Kosz';
$labels['junk'] = 'Spam';
+$labels['show_real_foldernames'] = 'Pokaż prawdziwe nazwy dla folderów specjalnych';
// message listing
$labels['subject'] = 'Temat';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'Typ listy';
$labels['folderactions'] = 'Działania na folderach...';
$labels['compact'] = 'PorzÄ…dkuj';
$labels['empty'] = 'Opróżnij';
+$labels['importmessages'] = 'Import wiadomości';
$labels['quota'] = 'Użyte miejsce';
$labels['unknown'] = 'nieznane';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Wyczyść filtr';
$labels['searchmod'] = 'Parametry wyszukiwania';
$labels['msgtext'] = 'Cała wiadomość';
$labels['body'] = 'Treść';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Otwórz w nowym oknie';
$labels['emlsave'] = 'Pobierz (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Ostatnia strona';
$labels['group'] = 'Grupa';
$labels['groups'] = 'Grupy';
+$labels['listgroup'] = 'Członkowie grupy';
$labels['personaladrbook'] = 'Kontakty osobiste';
$labels['searchsave'] = 'Zapisz wyszukiwanie';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignoruj słowa zawierające cyfry';
$labels['spellcheckignorecaps'] = 'Ignoruj słowa pisane wielkimi literami';
$labels['addtodict'] = 'Dodaj do słownika';
$labels['mailtoprotohandler'] = 'Zainstaluj obsługę linków mailto:';
+$labels['standardwindows'] = 'Traktuj okna wyskakujÄ…ce jako standardowe okna';
$labels['forwardmode'] = 'Przekazywanie wiadomości';
$labels['inline'] = 'w treści';
$labels['asattachment'] = 'jako załącznik';
diff --git a/program/localization/pl_PL/messages.inc b/program/localization/pl_PL/messages.inc
index fb7ad6c97..3cac0c426 100644
--- a/program/localization/pl_PL/messages.inc
+++ b/program/localization/pl_PL/messages.inc
@@ -126,6 +126,8 @@ $messages['importwait'] = 'Importowanie, proszę czekać...';
$messages['importformaterror'] = 'Import nieudany! Użyty plik nie jest poprawnym plikiem importu danych.';
$messages['importconfirm'] = '<b>Pomyślnie dodano $inserted kontaktów, pominięto $skipped istniejących wpisów</b>:<p><em>$names</em></p>.';
$messages['importconfirmskipped'] = '<b>Pominięto $skipped istniejących wpisów.</b>';
+$messages['importmessagesuccess'] = 'Pomyślnie zaimportowano następującą liczbę wiadomości: $nr';
+$messages['importmessageerror'] = 'Import nieudany! Wgrywany plik nie jest poprawną wiadomością lub plikiem skrzynki pocztowej';
$messages['opnotpermitted'] = 'Niedozwolona operacja!';
$messages['nofromaddress'] = 'Brak adresu e-mail w wybranej tożsamości.';
$messages['editorwarning'] = 'Zmiana edytora spowoduje utratę formatowania tekstu. Czy jesteś pewien, że chcesz to zrobić?';
diff --git a/program/localization/ps/labels.inc b/program/localization/ps/labels.inc
index 262e3d490..d5e513419 100755
--- a/program/localization/ps/labels.inc
+++ b/program/localization/ps/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'بارليک';
$labels['sent'] = 'Ù„ÛÚ–Ù„ شوي ليکونه';
$labels['trash'] = 'کثاÙت دانÛ';
$labels['junk'] = 'جنک';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'مضمون';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode';
$labels['folderactions'] = 'Folder actions...';
$labels['compact'] = 'Ú©ÛÚšÚ©Ù„ÛŒ';
$labels['empty'] = 'تش';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'ټيکلي لارښود';
$labels['unknown'] = 'نامعلوم';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'د Ù¾Ù„Ù¼Ù†Û Ø¨ÙŠØ§Ø³Ù…ÙˆÙ†';
$labels['searchmod'] = 'Search modifiers';
$labels['msgtext'] = 'Entire message';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'په نوي Ú©Ú“Ú©Û Ú©Û Ù¾Ø±Ø§Ù†ÙŠØ²Ù‡';
$labels['emlsave'] = 'Download (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'پای غونډ وښيه';
$labels['group'] = 'Group';
$labels['groups'] = 'Ú‰Ù„Û';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Úاني پتÛ';
$labels['searchsave'] = 'Save search';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers';
$labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized';
$labels['addtodict'] = 'Add to dictionary';
$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Messages forwarding';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'as attachment';
diff --git a/program/localization/pt_BR/labels.inc b/program/localization/pt_BR/labels.inc
index 9a1946eee..e70ae35b9 100644
--- a/program/localization/pt_BR/labels.inc
+++ b/program/localization/pt_BR/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Rascunhos';
$labels['sent'] = 'Enviados';
$labels['trash'] = 'Lixeira';
$labels['junk'] = 'Spam';
+$labels['show_real_foldernames'] = 'Exibir o nome real das pastas de sistema';
// message listing
$labels['subject'] = 'Assunto';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'Visualização em lista';
$labels['folderactions'] = 'Ações para as pastas...';
$labels['compact'] = 'Compactar';
$labels['empty'] = 'Esvaziar';
+$labels['importmessages'] = 'Importar mensagens';
$labels['quota'] = 'Uso de disco';
$labels['unknown'] = 'desconhecido';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Limpar pesquisa';
$labels['searchmod'] = 'Opções da pesquisa';
$labels['msgtext'] = 'Mensagem inteira';
$labels['body'] = 'Conteúdo';
+$labels['type'] = 'Tipo';
$labels['openinextwin'] = 'Abrir em nova janela';
$labels['emlsave'] = 'Baixar (formato .eml)';
@@ -267,7 +270,7 @@ $labels['yourmessage'] = 'Esta é uma confirmação de leitura da sua mensagem';
$labels['receiptnote'] = 'Nota: Esta confirmação de leitura somente informa que a mensagem foi aberta no computador do destinatário. Não há garantia que o destinatário tenha lido ou compreendido o conteúdo da mensagem.';
// address boook
-$labels['name'] = 'Nome de exibição';
+$labels['name'] = 'Nome';
$labels['firstname'] = 'Primeiro Nome';
$labels['surname'] = 'Sobrenome';
$labels['middlename'] = 'Segundo Nome';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Última Página';
$labels['group'] = 'Grupo';
$labels['groups'] = 'Grupos';
+$labels['listgroup'] = 'Listar membros do grupo';
$labels['personaladrbook'] = 'Endereços pessoais';
$labels['searchsave'] = 'Salvar pesquisa';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignorar palavras com números';
$labels['spellcheckignorecaps'] = 'Ignorar palavras com todas letras maiúsculas';
$labels['addtodict'] = 'Adicionar ao dicionário';
$labels['mailtoprotohandler'] = 'Associar links de e-mail (mailto:) para envio de mensagem através do webmail';
+$labels['standardwindows'] = 'Usar popups como janelas do navegador';
$labels['forwardmode'] = 'Encaminhamento de mensagens';
$labels['inline'] = 'Em linha (no corpo da mensagem)';
$labels['asattachment'] = 'como anexo';
@@ -484,7 +489,7 @@ $labels['messagecount'] = 'Mensagens';
$labels['create'] = 'Criar';
$labels['createfolder'] = 'Criar nova pasta';
$labels['managefolders'] = 'Gerenciar pastas';
-$labels['specialfolders'] = 'Pastas especiais';
+$labels['specialfolders'] = 'Pastas de sistema';
$labels['properties'] = 'Propriedades';
$labels['folderproperties'] = 'Propriedades da pasta';
$labels['parentfolder'] = 'Pasta pai';
diff --git a/program/localization/pt_PT/labels.inc b/program/localization/pt_PT/labels.inc
index 316255e5e..cc4c534e0 100644
--- a/program/localization/pt_PT/labels.inc
+++ b/program/localization/pt_PT/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Rascunhos';
$labels['sent'] = 'Itens Enviados';
$labels['trash'] = 'Reciclagem';
$labels['junk'] = 'Spam';
+$labels['show_real_foldernames'] = 'Mostrar nomes reais para as pastas especiais';
// message listing
$labels['subject'] = 'Assunto';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'Modo de visualização';
$labels['folderactions'] = 'Acções para pastas...';
$labels['compact'] = 'Compactar';
$labels['empty'] = 'Esvaziar';
+$labels['importmessages'] = 'Importar mensagens';
$labels['quota'] = 'Espaço utilizado';
$labels['unknown'] = 'desconhecido';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Limpar pesquisa';
$labels['searchmod'] = 'Pesquisar em';
$labels['msgtext'] = 'Mensagem completa';
$labels['body'] = 'Corpo';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Abrir numa nova janela';
$labels['emlsave'] = 'Guardar como (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Última página';
$labels['group'] = 'Grupo';
$labels['groups'] = 'Grupos';
+$labels['listgroup'] = 'Lista de membros do grupo';
$labels['personaladrbook'] = 'Endereços pessoais';
$labels['searchsave'] = 'Guardar pesquisa';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignorar palavras com números';
$labels['spellcheckignorecaps'] = 'Ignorar palavras em maiúsculas';
$labels['addtodict'] = 'Adicionar ao dicionário';
$labels['mailtoprotohandler'] = 'Registar manipulador de protocolo para mailto: links';
+$labels['standardwindows'] = 'Lidar com popups como janelas padrão';
$labels['forwardmode'] = 'Reencaminhamento de mensagens';
$labels['inline'] = 'em linha';
$labels['asattachment'] = 'como anexo';
diff --git a/program/localization/ro_RO/labels.inc b/program/localization/ro_RO/labels.inc
index 6b59da313..4f6ddb1fa 100644
--- a/program/localization/ro_RO/labels.inc
+++ b/program/localization/ro_RO/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Ciorne';
$labels['sent'] = 'Trimise';
$labels['trash'] = 'Gunoi';
$labels['junk'] = 'Spam';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'Subiect';
@@ -46,25 +47,25 @@ $labels['to'] = 'Destinatar';
$labels['cc'] = 'Copie (CC)';
$labels['bcc'] = 'Copie oarbă (BCC)';
$labels['replyto'] = 'Răspunde la';
-$labels['followupto'] = 'Followup-To';
+$labels['followupto'] = 'Followup La';
$labels['date'] = 'Data';
$labels['size'] = 'Mărime';
$labels['priority'] = 'Prioritate';
$labels['organization'] = 'Organizaţie';
-$labels['readstatus'] = 'Starea de citit';
+$labels['readstatus'] = 'Citit/Necitit';
$labels['listoptions'] = 'Listează opţiunile...';
$labels['mailboxlist'] = 'Dosare';
$labels['messagesfromto'] = 'Mesaje de la $from până la $to din $count';
$labels['threadsfromto'] = 'Grupuri de la $from până la $to din $count';
-$labels['messagenrof'] = '$nr mesaje din $count';
+$labels['messagenrof'] = 'Mesajul $nr din $count';
$labels['fromtoshort'] = '$from - $to din $count';
$labels['copy'] = 'Copiază';
$labels['move'] = 'Mută';
$labels['moveto'] = 'Mută in...';
$labels['download'] = 'Descarcă';
-$labels['open'] = 'Open';
+$labels['open'] = 'Deschide';
$labels['showattachment'] = 'Arată';
$labels['showanyway'] = 'Arată oricum';
@@ -127,22 +128,22 @@ $labels['checkmail'] = 'Verifică mesaje noi';
$labels['compose'] = 'Scrie un mesaj';
$labels['writenewmessage'] = 'Scrie mesaj nou';
$labels['reply'] = 'Răspunde';
-$labels['replytomessage'] = 'Răspunde la mesaj';
+$labels['replytomessage'] = 'Răspunde expeditorului';
$labels['replytoallmessage'] = 'Răspunde la toţi';
$labels['replyall'] = 'Răspunde la toţi';
-$labels['replylist'] = 'Lista de răspuns';
+$labels['replylist'] = 'Răspunde listei';
$labels['forward'] = 'Înaintează';
$labels['forwardinline'] = 'Înaintează ca citat';
$labels['forwardattachment'] = 'Înaintează ca ataşament';
$labels['forwardmessage'] = 'Trimite mesajul mai departe';
-$labels['deletemessage'] = 'Trimite mesajul la gunoi';
+$labels['deletemessage'] = 'Șterge mesajul';
$labels['movemessagetotrash'] = 'Mută mesajul la gunoi';
$labels['printmessage'] = 'Listează mesajul';
$labels['previousmessage'] = 'Afişează mesajul anterior';
$labels['firstmessage'] = 'Afişează primul mesaj';
$labels['nextmessage'] = 'Afişează următorul mesaj';
$labels['lastmessage'] = 'Afişează ultimul mesaj';
-$labels['backtolist'] = 'ÃŽnapoi la lista cu mesaje';
+$labels['backtolist'] = 'ÃŽnapoi la mesaje';
$labels['viewsource'] = 'Afişează sursa';
$labels['mark'] = 'Marchează';
$labels['markmessages'] = 'Marchează mesajele';
@@ -157,12 +158,12 @@ $labels['options'] = 'Opţiuni';
$labels['select'] = 'Selectează';
$labels['all'] = 'Toate';
-$labels['none'] = 'Fără sortare';
+$labels['none'] = 'Niciunul';
$labels['currpage'] = 'Pagina curentă';
$labels['unread'] = 'Necitite';
$labels['flagged'] = 'Marcat';
$labels['unanswered'] = 'Fără răspuns';
-$labels['withattachment'] = 'With attachment';
+$labels['withattachment'] = 'Cu atașament';
$labels['deleted'] = 'Åžterse';
$labels['undeleted'] = 'Nu a fost șters';
$labels['invert'] = 'Inversează';
@@ -190,9 +191,10 @@ $labels['listsorting'] = 'Sortează după';
$labels['listorder'] = 'Ordinea de sortare';
$labels['listmode'] = 'Mod de vizualizare';
-$labels['folderactions'] = 'Actiuni asupra folder-ului...';
+$labels['folderactions'] = 'Acțiuni dosar...';
$labels['compact'] = 'Compactează';
$labels['empty'] = 'GoleÅŸte';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Spaţiu folosit';
$labels['unknown'] = 'necunoscut';
@@ -203,17 +205,18 @@ $labels['resetsearch'] = 'Anulează căutarea';
$labels['searchmod'] = 'Parametrii de căutare';
$labels['msgtext'] = 'Tot mesajul';
$labels['body'] = 'Corp';
+$labels['type'] = 'Type';
-$labels['openinextwin'] = 'Deschide într-o fereastră nouă';
+$labels['openinextwin'] = 'Deschide în fereastră nouă';
$labels['emlsave'] = 'Salvează în format .eml';
-$labels['changeformattext'] = 'Display in plain text format';
-$labels['changeformathtml'] = 'Display in HTML format';
+$labels['changeformattext'] = 'Afișează în format text';
+$labels['changeformathtml'] = 'Afișează în format HTML';
// message compose
$labels['editasnew'] = 'Editează ca nou';
$labels['send'] = 'Trimite';
$labels['sendmessage'] = 'Trimite mesaj';
-$labels['savemessage'] = 'Salvează această ciornă';
+$labels['savemessage'] = 'Salvează ciornă';
$labels['addattachment'] = 'Ataşează fişier';
$labels['charset'] = 'Set de caractere';
$labels['editortype'] = 'Tip de editor';
@@ -244,21 +247,21 @@ $labels['highest'] = 'Cea mai mare';
$labels['nosubject'] = '(fără subiect)';
$labels['showimages'] = 'Afişează imagini';
$labels['alwaysshow'] = 'Afişează întotdeauna imaginile de la $sender';
-$labels['isdraft'] = 'Acesta este un mesaj schiţă.';
+$labels['isdraft'] = 'Acest mesaj este o ciornă.';
$labels['andnmore'] = '$nr mai multe...';
$labels['togglemoreheaders'] = 'Arată mai mult din antet';
$labels['togglefullheaders'] = 'Arată mai puțin din antet';
$labels['htmltoggle'] = 'HTML';
$labels['plaintoggle'] = 'Text simplu';
-$labels['savesentmessagein'] = 'Salvează mesajele în';
+$labels['savesentmessagein'] = 'Salvează mesajele trimise în';
$labels['dontsave'] = 'Nu salva';
-$labels['maxuploadsize'] = 'Mărimea maximă admisă a fişierului este $size';
+$labels['maxuploadsize'] = 'Mărimea maxim admisă a fişierului este $size';
-$labels['addcc'] = 'Adaugă Cc';
-$labels['addbcc'] = 'Adaugă Bcc';
+$labels['addcc'] = 'Adaugă CC';
+$labels['addbcc'] = 'Adaugă BCC';
$labels['addreplyto'] = 'Adaugă Raspunde-La';
-$labels['addfollowupto'] = 'Adaugă Followup-To';
+$labels['addfollowupto'] = 'Adaugă Followup-La';
// mdn
$labels['mdnrequest'] = 'Expeditorul acestui mesaj a solicitat să fie notificat la cititrea mesajului. Doriţi să notificaţi expeditorul?';
@@ -267,7 +270,7 @@ $labels['yourmessage'] = 'Aceasta este o confirmare de primire a mesajului dumne
$labels['receiptnote'] = 'Notă: Această confirmare doar vă informează că mesajul a fost afişat pe calculatorul destinatarului. Nu există nici o garanţie că destinatarul a citit sau a inţeles conţinutul mesajului.';
// address boook
-$labels['name'] = 'Numele Contactului';
+$labels['name'] = 'Numele Contact';
$labels['firstname'] = 'Nume';
$labels['surname'] = 'Prenume';
$labels['middlename'] = 'Iniţiala tatălui';
@@ -281,11 +284,11 @@ $labels['maidenname'] = 'Nume de fată';
$labels['email'] = 'E-Mail';
$labels['phone'] = 'Telefon';
$labels['address'] = 'Adresă';
-$labels['street'] = 'Stradă';
+$labels['street'] = 'Strada';
$labels['locality'] = 'OraÈ™';
$labels['zipcode'] = 'Cod poÅŸtal';
$labels['region'] = 'Stat/Judeţ';
-$labels['country'] = 'Țară';
+$labels['country'] = 'Èšara';
$labels['birthday'] = 'Ziua de naÅŸtere:';
$labels['anniversary'] = 'Aniversare';
$labels['website'] = 'Pagină web';
@@ -302,8 +305,8 @@ $labels['advsearch'] = 'Căutare avansată';
$labels['advanced'] = 'Avansat';
$labels['other'] = 'Altele';
-$labels['typehome'] = 'Pagina Principală';
-$labels['typework'] = 'Servici';
+$labels['typehome'] = 'Acasă';
+$labels['typework'] = 'Serviciu';
$labels['typeother'] = 'Altele';
$labels['typemobile'] = 'Mobil';
$labels['typemain'] = 'Principal';
@@ -318,7 +321,7 @@ $labels['typeblog'] = 'Blog';
$labels['typeprofile'] = 'Profil';
$labels['addfield'] = 'Adaugă câmp...';
-$labels['addcontact'] = 'Adaugă contactul selectat în agendă';
+$labels['addcontact'] = 'Adaugă contact nou';
$labels['editcontact'] = 'Modifică contact';
$labels['contacts'] = 'Contacte';
$labels['contactproperties'] = 'Proprietăţile contactului...';
@@ -331,7 +334,7 @@ $labels['delete'] = 'Åžterge';
$labels['rename'] = 'RedenumeÅŸte';
$labels['addphoto'] = 'Adaugă';
$labels['replacephoto'] = 'Înlocuiește';
-$labels['uploadphoto'] = 'Încarcă poya';
+$labels['uploadphoto'] = 'Încarcă imagine';
$labels['newcontact'] = 'Creează contact nou';
$labels['deletecontact'] = 'Åžterge contactul selectat';
@@ -348,12 +351,13 @@ $labels['groupdelete'] = 'Șterge grupul';
$labels['groupremoveselected'] = 'Șterge contactele selectate din grup';
$labels['previouspage'] = 'Pagina anterioară';
-$labels['firstpage'] = 'Arată primul set';
+$labels['firstpage'] = 'Prima pagină';
$labels['nextpage'] = 'Pagina următoare';
-$labels['lastpage'] = 'Arată ultimul set';
+$labels['lastpage'] = 'Ultima pagină';
$labels['group'] = 'Grup';
$labels['groups'] = 'Grupuri';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Adrese personale';
$labels['searchsave'] = 'Salvează căutarea';
@@ -364,7 +368,7 @@ $labels['importcontacts'] = 'Importă contacte';
$labels['importfromfile'] = 'Importă din fişier:';
$labels['importtarget'] = 'Adaugă contactele noi în agenda:';
$labels['importreplace'] = 'Înlocuieşte întreaga agendă';
-$labels['importdesc'] = 'Puteți încărcat contacte dintr-o agendă existentă.<br/>Momentan este suportat importul în formatul <a href="http://en.wikipedia.org/wiki/VCard">vCard</a> sau în formatul CSV (comma-separated).';
+$labels['importdesc'] = 'Puteți încărca contacte dintr-o agendă existentă.<br/>Momentan este suportat importul în formatul <a href="http://en.wikipedia.org/wiki/VCard">vCard</a> sau în formatul CSV (comma-separated).';
$labels['done'] = 'Finalizat';
// settings
@@ -395,14 +399,14 @@ $labels['language'] = 'Limba';
$labels['timezone'] = 'Fus orar';
$labels['pagesize'] = 'Rânduri pe pagină';
$labels['signature'] = 'Semnătură';
-$labels['dstactive'] = 'Reglare automată oră de vară';
+$labels['dstactive'] = 'Reglare ora de vară';
$labels['showinextwin'] = 'Deschide mesajul în fereastră nouă';
$labels['composeextwin'] = 'Compune mesajul în fereastră nouă';
$labels['htmleditor'] = 'Scrie mesaje HTML';
$labels['htmlonreply'] = 'la răspunsul doar către un mesaj HTML';
$labels['htmlonreplyandforward'] = 'la trimitere mai departe sau la răspuns la mesaj HTML';
$labels['htmlsignature'] = 'Semnatură HTML';
-$labels['showemail'] = 'Show email address with display name';
+$labels['showemail'] = 'Arată adresa email alături de nume afișat';
$labels['previewpane'] = 'Previzualizare mail';
$labels['skin'] = 'Temă interfaţă';
$labels['logoutclear'] = 'GoleÅŸte CoÅŸul de Gunoi la deconectare';
@@ -411,15 +415,15 @@ $labels['uisettings'] = 'Interfaţă utilizator';
$labels['serversettings'] = 'Configuraţii server';
$labels['mailboxview'] = 'Afişare căsuţă poştală';
$labels['mdnrequests'] = 'Notificări expeditor';
-$labels['askuser'] = 'întreabă utilizatorul';
+$labels['askuser'] = 'întreabă-mă';
$labels['autosend'] = 'trimite automat';
$labels['autosendknown'] = 'trimite confirmarea de primire către contactele mele, în rest întreabă-mă';
$labels['autosendknownignore'] = 'trimite confirmarea de primire către contactele mele, în rest ignoră';
$labels['ignore'] = 'ignoră';
-$labels['readwhendeleted'] = 'Marchează mesajul ca şi citit la ştergere';
+$labels['readwhendeleted'] = 'Marchează mesajul ca citit la ştergere';
$labels['flagfordeletion'] = 'Marchează mesajul pentru ştergere în loc de a-l şterge direct';
$labels['skipdeleted'] = 'Nu arăta mesajele şterse';
-$labels['deletealways'] = 'Dacă mutarea mesajelor în coş eşuează, se vor şterge';
+$labels['deletealways'] = 'Dacă mutarea mesajelor în Coş eşuează, șterge-le';
$labels['deletejunk'] = 'Șterge direct mesajele în Junk';
$labels['showremoteimages'] = 'Arată imaginile care nu fac parte din e-mail';
$labels['fromknownsenders'] = 'de la expeditori cunoscuţi';
@@ -443,7 +447,7 @@ $labels['checkallfolders'] = 'Verifică toate dosarele pentru mesaje noi';
$labels['displaynext'] = 'După ştergerea sau mutarea unui mesaj afişează-l pe următorul din listă';
$labels['defaultfont'] = 'Font-ul implicit al mesajului HTML';
$labels['mainoptions'] = 'Opţiuni principale';
-$labels['browseroptions'] = 'Optiuni browser';
+$labels['browseroptions'] = 'Opțiuni browser';
$labels['section'] = 'Secţiune';
$labels['maintenance'] = 'Mentenanţă';
$labels['newmessage'] = 'Mesaj nou';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignoră cuvintele cu numere';
$labels['spellcheckignorecaps'] = 'Ignoră cuvintele din litere mari';
$labels['addtodict'] = 'Adaugă la dicţionar';
$labels['mailtoprotohandler'] = 'Îregistrează handler protocol pentru mailto: link-uri';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Trimitere mai departe mesaj';
$labels['inline'] = 'într-e linii';
$labels['asattachment'] = 'ca atașament';
diff --git a/program/localization/ru_RU/labels.inc b/program/localization/ru_RU/labels.inc
index 8a136aa77..d2b8e75c4 100644
--- a/program/localization/ru_RU/labels.inc
+++ b/program/localization/ru_RU/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Черновики';
$labels['sent'] = 'Отправленные';
$labels['trash'] = 'Корзина';
$labels['junk'] = 'СПÐÐœ';
+$labels['show_real_foldernames'] = 'Показывать наÑтоÑщие Ð½Ð°Ð·Ð²Ð°Ð½Ð¸Ñ Ñпециальных папок';
// message listing
$labels['subject'] = 'Тема';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'Режим проÑмотра';
$labels['folderactions'] = 'Операции над папкой...';
$labels['compact'] = 'Сжать';
$labels['empty'] = 'ОпуÑтошить';
+$labels['importmessages'] = 'Импорт Ñообщений';
$labels['quota'] = 'Квота';
$labels['unknown'] = 'неизвеÑтно';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'СброÑ';
$labels['searchmod'] = 'Варианты поиÑка';
$labels['msgtext'] = 'Ð’ÑÑ‘ Ñообщение';
$labels['body'] = 'Тело пиÑьма';
+$labels['type'] = 'Тип';
$labels['openinextwin'] = 'Открыть в новом окне';
$labels['emlsave'] = 'Сохранить (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Показать поÑледнюю ÑтраницÑ
$labels['group'] = 'Группа';
$labels['groups'] = 'Группы';
+$labels['listgroup'] = 'СпиÑок членов группы';
$labels['personaladrbook'] = 'ПерÑональные адреÑа';
$labels['searchsave'] = 'Сохранить запроÑ';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'ПропуÑкать Ñлова Ñ Ñ†Ð¸Ñ„Ñ€Ð°
$labels['spellcheckignorecaps'] = 'ПропуÑкать Ñлова из пропиÑных букв';
$labels['addtodict'] = 'Добавить в Ñловарь';
$labels['mailtoprotohandler'] = 'ЗарегиÑтрировать обработчик Ð´Ð»Ñ ÑÑылок mailto:';
+$labels['standardwindows'] = 'Обрабатывать вÑплывающие окна как обычные';
$labels['forwardmode'] = 'ПереÑылка Ñообщений';
$labels['inline'] = 'в текÑте';
$labels['asattachment'] = 'как вложение';
diff --git a/program/localization/si_LK/labels.inc b/program/localization/si_LK/labels.inc
index d8cd71662..92d33d3b7 100644
--- a/program/localization/si_LK/labels.inc
+++ b/program/localization/si_LK/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'කටු සටහන්';
$labels['sent'] = 'යà·à·€à·–';
$labels['trash'] = 'ඉවතලන බඳුන';
$labels['junk'] = 'සුන්බුන්';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'මà·à¶­à·˜à¶šà·à·€';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode';
$labels['folderactions'] = 'බහà·à¶½à·”ම් ක්â€à¶»à·’යà·...';
$labels['compact'] = 'සංයුක්ත';
$labels['empty'] = 'හිස්';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Disk usage';
$labels['unknown'] = 'නොදනී';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'සෙවුම යලි පිහිටවීම';
$labels['searchmod'] = 'Search modifiers';
$labels['msgtext'] = 'සම්පූර්ණ පණිවිඩය';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'නව කවුළුවක විවෘත කරන්න';
$labels['emlsave'] = 'Download (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'අවසà·à¶± පිටුව පෙන්වනà
$labels['group'] = 'කණ්ඩà·à¶ºà¶¸';
$labels['groups'] = 'කණ්ඩà·à¶ºà¶¸à·Š';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'පුද්ගලික ලිපිනය';
$labels['searchsave'] = 'Save search';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'අංක සහිත වචන නොසල
$labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized';
$labels['addtodict'] = 'à·à¶¶à·Šà¶¯ කà·à·‚යට එක් කරන්න';
$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Messages forwarding';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'as attachment';
diff --git a/program/localization/sk_SK/labels.inc b/program/localization/sk_SK/labels.inc
index 10673382a..465252409 100644
--- a/program/localization/sk_SK/labels.inc
+++ b/program/localization/sk_SK/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Rozpísané';
$labels['sent'] = 'Odoslané';
$labels['trash'] = 'Kôš';
$labels['junk'] = 'Nevyžiadaná pošta';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'Predmet';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'Režim zobrazenia zoznamu';
$labels['folderactions'] = 'Akcie so zložkou...';
$labels['compact'] = 'ZhustiÅ¥ prieÄinok';
$labels['empty'] = 'Vyprázdniť';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Zaplnenie schránky';
$labels['unknown'] = 'neznáme';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'VyÄistiÅ¥ vyhľadávanie';
$labels['searchmod'] = 'Parametre hľadanie';
$labels['msgtext'] = 'Celá správa';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Otvoriť v novom okne';
$labels['emlsave'] = 'Stiahnuť';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Posledná stránka';
$labels['group'] = 'Skupina';
$labels['groups'] = 'Skupiny';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Osobné adresy';
$labels['searchsave'] = 'Uložiť vyhľadávanie';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'IgnorovaÅ¥ slová s Äíslami';
$labels['spellcheckignorecaps'] = 'Ignorovať slová písané veľkými písmenami';
$labels['addtodict'] = 'Pridať do slovníka';
$labels['mailtoprotohandler'] = 'Zaregistrovať handler pre odkazy „mailto:“';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Preposielanie správ';
$labels['inline'] = 'v tele spávy';
$labels['asattachment'] = 'ako príloha';
diff --git a/program/localization/sl_SI/labels.inc b/program/localization/sl_SI/labels.inc
index 6b9ba2d41..c33ea479c 100644
--- a/program/localization/sl_SI/labels.inc
+++ b/program/localization/sl_SI/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Osnutki';
$labels['sent'] = 'Poslano';
$labels['trash'] = 'Smeti';
$labels['junk'] = 'Nezaželena sporoÄila';
+$labels['show_real_foldernames'] = 'Prikaži prava imena za posebne mape';
// message listing
$labels['subject'] = 'Zadeva';
@@ -162,7 +163,7 @@ $labels['currpage'] = 'Trenutna stran';
$labels['unread'] = 'Neprebrano';
$labels['flagged'] = 'OznaÄeno';
$labels['unanswered'] = 'NeoznaÄeno';
-$labels['withattachment'] = 'With attachment';
+$labels['withattachment'] = 'S priponko';
$labels['deleted'] = 'Izbrisano';
$labels['undeleted'] = 'Ni izbrisano';
$labels['invert'] = 'Zamenjaj';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'NaÄin prikaza seznama';
$labels['folderactions'] = 'Upravljanje map...';
$labels['compact'] = 'Stisni';
$labels['empty'] = 'Izprazni';
+$labels['importmessages'] = 'Uvozi sporoÄila';
$labels['quota'] = 'Poraba prostora';
$labels['unknown'] = 'neznana';
@@ -203,11 +205,12 @@ $labels['resetsearch'] = 'PrekliÄi iskanje';
$labels['searchmod'] = 'Spremembe iskanja';
$labels['msgtext'] = 'Celotno sporoÄilo';
$labels['body'] = 'Vsebina sporoÄila';
+$labels['type'] = 'Tip';
$labels['openinextwin'] = 'Odpri v novem oknu';
$labels['emlsave'] = 'Prenos datoteke (.eml)';
-$labels['changeformattext'] = 'Display in plain text format';
-$labels['changeformathtml'] = 'Display in HTML format';
+$labels['changeformattext'] = 'Prikaži kot golo besedilo';
+$labels['changeformathtml'] = 'Prikaži v formatu HTML';
// message compose
$labels['editasnew'] = 'Uredi kot novo';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Zadnja stran';
$labels['group'] = 'Skupina';
$labels['groups'] = 'Skupine';
+$labels['listgroup'] = 'IzpiÅ¡i seznam Älanov skupine';
$labels['personaladrbook'] = 'Stiki';
$labels['searchsave'] = 'Shrani iskanje';
@@ -402,7 +406,7 @@ $labels['htmleditor'] = 'Sestavi sporoÄila z obogatenim besedilom';
$labels['htmlonreply'] = 'le pri odgovoru na sporoÄila z obogatenim besedilom';
$labels['htmlonreplyandforward'] = 'le pri posredovanju ali odgovoru na sporoÄila z obogatenim besedilom';
$labels['htmlsignature'] = 'Podpis z obogatenim besedilom';
-$labels['showemail'] = 'Show email address with display name';
+$labels['showemail'] = 'Prikaži e-naslove poleg imen';
$labels['previewpane'] = 'Prikaži predogled';
$labels['skin'] = 'Tema uporabniškega vmesnika';
$labels['logoutclear'] = 'Izprazni mapo Smeti ob odjavi';
@@ -472,6 +476,7 @@ $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['mailtoprotohandler'] = 'Registriraj upravljavca protokola za e-naslov: povezave';
+$labels['standardwindows'] = 'Prikaži pojavna okna kot obiÄajna';
$labels['forwardmode'] = 'Posredovanje sporoÄil';
$labels['inline'] = 'medvrstiÄno';
$labels['asattachment'] = 'Kot priponka';
diff --git a/program/localization/sl_SI/messages.inc b/program/localization/sl_SI/messages.inc
index 081d912c1..dc731d01b 100644
--- a/program/localization/sl_SI/messages.inc
+++ b/program/localization/sl_SI/messages.inc
@@ -126,6 +126,8 @@ $messages['importwait'] = 'Uvažanje poteka...';
$messages['importformaterror'] = 'Uvoz ni uspel! Uvožena datoteka ni pravega formata.';
$messages['importconfirm'] = '<b>Uspešno uvoženi $inserted stiki, $skipped stikov že obstaja v imeniku</b>:<p><em>$names</em></p>';
$messages['importconfirmskipped'] = '<b>PreskoÄeni že obstojeÄi vnosi $skipped </b>';
+$messages['importmessagesuccess'] = 'UpeÅ¡no ste uvozili $nr sporoÄil.';
+$messages['importmessageerror'] = 'Uvoz je spodletel. Naložena datoteka ni veljavno sporoÄilo ali poÅ¡tna datoteka';
$messages['opnotpermitted'] = 'Operacija ni dovoljena.';
$messages['nofromaddress'] = 'V izbrani identiteti manjka elektronski naslov.';
$messages['editorwarning'] = 'Preklop v sploÅ¡en urejevalnik onemogoÄa uporabo izbranih nastavitev oblikovanja. Želite nadaljevati?';
diff --git a/program/localization/sq_AL/labels.inc b/program/localization/sq_AL/labels.inc
index ba9b559d8..e2cb6791b 100644
--- a/program/localization/sq_AL/labels.inc
+++ b/program/localization/sq_AL/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Drafte';
$labels['sent'] = 'Dërguar';
$labels['trash'] = 'Fshirë';
$labels['junk'] = 'Reklama';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'Tema';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode';
$labels['folderactions'] = 'Folder actions...';
$labels['compact'] = 'Zvogëlo';
$labels['empty'] = 'Boshatis';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Përdorimi i diskut';
$labels['unknown'] = 'i panjohur';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Pastro kërkimin';
$labels['searchmod'] = 'Search modifiers';
$labels['msgtext'] = 'Entire message';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Open in new window';
$labels['emlsave'] = 'Download (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Shfaq grupin e fundit';
$labels['group'] = 'Group';
$labels['groups'] = 'Grupet';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Adresat Personale';
$labels['searchsave'] = 'Save search';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers';
$labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized';
$labels['addtodict'] = 'Add to dictionary';
$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Messages forwarding';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'as attachment';
diff --git a/program/localization/sr_CS/labels.inc b/program/localization/sr_CS/labels.inc
index 130d3a7a6..4bdf25020 100644
--- a/program/localization/sr_CS/labels.inc
+++ b/program/localization/sr_CS/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'U pripremi';
$labels['sent'] = 'ПоÑлате';
$labels['trash'] = 'Канта';
$labels['junk'] = 'Смеће';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'ÐаÑлов';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'ЛиÑÑ‚ режим приказивања';
$labels['folderactions'] = 'ПоÑтавке фаÑцикле';
$labels['compact'] = 'Компакција';
$labels['empty'] = 'ИÑпразни';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Квота';
$labels['unknown'] = 'непозната';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Прикажи Ñве поруке';
$labels['searchmod'] = 'Search modifiers';
$labels['msgtext'] = 'Цела порука';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Отвори у новом прозору';
$labels['emlsave'] = 'Довнлоад (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Прикажи поÑледњи Ñкуп';
$labels['group'] = 'Група';
$labels['groups'] = 'Групе';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Личне адреÑе';
$labels['searchsave'] = 'Сачувај претрагу';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'игнориши речи Ñа бројевÐ
$labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized';
$labels['addtodict'] = 'Додај у речник';
$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Messages forwarding';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'as attachment';
diff --git a/program/localization/sv_SE/labels.inc b/program/localization/sv_SE/labels.inc
index f61433527..7169aeba8 100644
--- a/program/localization/sv_SE/labels.inc
+++ b/program/localization/sv_SE/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Utkast';
$labels['sent'] = 'Skickat';
$labels['trash'] = 'Papperskorg';
$labels['junk'] = 'Skräp';
+$labels['show_real_foldernames'] = 'Visa verkliga namn på särskilda kataloger';
// message listing
$labels['subject'] = 'Ämne';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'Visningsläge';
$labels['folderactions'] = 'Hantera kataloger';
$labels['compact'] = 'Packa';
$labels['empty'] = 'Töm';
+$labels['importmessages'] = 'Importera meddelanden';
$labels['quota'] = 'Diskutrymme';
$labels['unknown'] = 'okänt';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Återställ sökning';
$labels['searchmod'] = 'Sökalternativ';
$labels['msgtext'] = 'Hela meddelandet';
$labels['body'] = 'Innehåll';
+$labels['type'] = 'Typ';
$labels['openinextwin'] = 'Öppna i nytt fönster';
$labels['emlsave'] = 'Spara (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Visa sista sidan';
$labels['group'] = 'Grupp';
$labels['groups'] = 'Kontaktgrupper';
+$labels['listgroup'] = 'Visa gruppmedlemmar';
$labels['personaladrbook'] = 'Personliga adresser';
$labels['searchsave'] = 'Lägg till sökning';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignorera ord med siffror';
$labels['spellcheckignorecaps'] = 'Ignorera ord med enbart stora bokstäver';
$labels['addtodict'] = 'Lägg till i ordlista';
$labels['mailtoprotohandler'] = 'Ange program för hantering av mailto-länkar';
+$labels['standardwindows'] = 'Hantera popup-rutor som standardfönster';
$labels['forwardmode'] = 'Vidarebefordra meddelande';
$labels['inline'] = 'Infogat';
$labels['asattachment'] = 'Bilaga';
diff --git a/program/localization/ta_IN/labels.inc b/program/localization/ta_IN/labels.inc
index bc1db7d00..197e80606 100644
--- a/program/localization/ta_IN/labels.inc
+++ b/program/localization/ta_IN/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'வரைவà¯à®•à®³à¯';
$labels['sent'] = 'அனà¯à®ªà¯à®ªà®¿à®¯ அஞà¯à®šà®²à¯';
$labels['trash'] = 'கà¯à®ªà¯à®ªà¯ˆ';
$labels['junk'] = 'எரிதமà¯';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'தலைபà¯à®ªà¯';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode';
$labels['folderactions'] = 'Folder actions...';
$labels['compact'] = 'கà¯à®±à¯à®•à®¿à®¯';
$labels['empty'] = 'காலி';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'பயனà¯à®ªà®¾à®Ÿà¯à®Ÿà¯ அளவà¯';
$labels['unknown'] = 'தெரியாத';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'தேடலை மறà¯à®…மை';
$labels['searchmod'] = 'மாறà¯à®±à®¿à®•à®³à¯ˆ தேடà¯';
$labels['msgtext'] = 'à®®à¯à®´à¯ செயà¯à®¤à®¿';
$labels['body'] = 'Body';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'பà¯à®¤à¯ சாளரதà¯à®¤à®¿à®²à¯ திற';
$labels['emlsave'] = 'பதிவிறகà¯à®•à¯ (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'கடைசி கà¯à®´à¯à®µà¯ˆ காடà¯à®Ÿà
$labels['group'] = 'Group';
$labels['groups'] = 'கà¯à®´à¯à®•à¯à®•à®³à¯';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'சà¯à®¯ à®®à¯à®•à®µà®°à®¿';
$labels['searchsave'] = 'Save search';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers';
$labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized';
$labels['addtodict'] = 'Add to dictionary';
$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Messages forwarding';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'as attachment';
diff --git a/program/localization/th_TH/labels.inc b/program/localization/th_TH/labels.inc
index 03b4161fb..85b091e5b 100644
--- a/program/localization/th_TH/labels.inc
+++ b/program/localization/th_TH/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'à¸à¸¥à¹ˆà¸­à¸‡à¸ˆà¸”หมายร่าง';
$labels['sent'] = 'à¸à¸¥à¹ˆà¸­à¸‡à¸‚าออà¸';
$labels['trash'] = 'ถังขยะ';
$labels['junk'] = 'à¸à¸¥à¹ˆà¸­à¸‡à¸ˆà¸”หมายขยะ';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'หัวจดหมาย';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode';
$labels['folderactions'] = 'Folder actions...';
$labels['compact'] = 'à¹à¸šà¸šà¸¢à¹ˆà¸­';
$labels['empty'] = 'ว่างเปล่า';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'พื้นที่ใช้งาน';
$labels['unknown'] = 'ไม่ทราบ';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'ล้างà¸à¸²à¸£à¸„้นหา';
$labels['searchmod'] = 'Search modifiers';
$labels['msgtext'] = 'Entire message';
$labels['body'] = 'เนื้อหา';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Open in new window';
$labels['emlsave'] = 'Download (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Show last page';
$labels['group'] = 'Group';
$labels['groups'] = 'Groups';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Personal Addresses';
$labels['searchsave'] = 'Save search';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers';
$labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized';
$labels['addtodict'] = 'Add to dictionary';
$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Messages forwarding';
$labels['inline'] = 'inline';
$labels['asattachment'] = 'เป็นไฟล์à¹à¸™à¸š';
diff --git a/program/localization/tr_TR/labels.inc b/program/localization/tr_TR/labels.inc
index 9e78ea3fa..c62c5c079 100644
--- a/program/localization/tr_TR/labels.inc
+++ b/program/localization/tr_TR/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Taslaklar';
$labels['sent'] = 'Giden';
$labels['trash'] = 'Çöp';
$labels['junk'] = 'Ä°stenmeyen';
+$labels['show_real_foldernames'] = 'Özel klasörler için gerçek isimleri göster';
// message listing
$labels['subject'] = 'Konu';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'Liste görünümü';
$labels['folderactions'] = 'Klasör eylemleri...';
$labels['compact'] = 'Sıklaştır';
$labels['empty'] = 'BoÅŸalt';
+$labels['importmessages'] = 'Mesajları içe aktar';
$labels['quota'] = 'Disk kullanımı';
$labels['unknown'] = 'bilinmeyen';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Aramayı bitir';
$labels['searchmod'] = 'Arama detayları';
$labels['msgtext'] = 'Tüm posta gövdesi';
$labels['body'] = 'Gövde';
+$labels['type'] = 'Tip';
$labels['openinextwin'] = 'Yeni pencerede aç';
$labels['emlsave'] = 'Ä°ndir (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Sonuncuyu göster';
$labels['group'] = 'Grup';
$labels['groups'] = 'Gruplar';
+$labels['listgroup'] = 'Grup üyelerini listele';
$labels['personaladrbook'] = 'Adresler';
$labels['searchsave'] = 'Aramayı kaydet';
@@ -402,7 +406,7 @@ $labels['htmleditor'] = 'HTML postaları oluştur';
$labels['htmlonreply'] = 'sadece HTML postaları yanıtlarken';
$labels['htmlonreplyandforward'] = 'HTML biçimindeki posta yanıtlandığında veye iletildiğinde';
$labels['htmlsignature'] = 'HTML imza';
-$labels['showemail'] = 'Show email address with display name';
+$labels['showemail'] = 'Eposta adresini görünüm ismi ile görüntüle';
$labels['previewpane'] = 'Önizleme panelini göster';
$labels['skin'] = 'Arayüz görünümü';
$labels['logoutclear'] = 'Oturumu kapatınca Çöpü temizle';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'İçinde rakam geçen kelimleri göz ardı et
$labels['spellcheckignorecaps'] = 'Tümü büyük harf olan kelimleri göz ardı et';
$labels['addtodict'] = 'Sözlüğe Ekle';
$labels['mailtoprotohandler'] = 'mailto: bağlantıları için protokol işleyici kayıt et';
+$labels['standardwindows'] = 'Popup pencerelerini standart pencere olarak yönet';
$labels['forwardmode'] = 'Posta yönlendirme';
$labels['inline'] = 'postanın içinde';
$labels['asattachment'] = 'ek olarak';
diff --git a/program/localization/tr_TR/messages.inc b/program/localization/tr_TR/messages.inc
index 3b451d556..3f728b523 100644
--- a/program/localization/tr_TR/messages.inc
+++ b/program/localization/tr_TR/messages.inc
@@ -126,6 +126,8 @@ $messages['importwait'] = 'Aktarılıyor, lütfen bekleyin...';
$messages['importformaterror'] = 'İçe aktarım başarısız. Yüklenen dosya geçerli bir içe aktarım dosyası değil.';
$messages['importconfirm'] = '<b>$inserted kişi başarıyla aktarıldı</b>';
$messages['importconfirmskipped'] = '<b>Var olan $skipped girdi atlandı</b>';
+$messages['importmessagesuccess'] = '$nr adet mesaj başarıyla içe aktarıldı';
+$messages['importmessageerror'] = 'İçe aktarım başarısız. Yüklenen dosya geçerli bir içe aktarım dosyası değil.';
$messages['opnotpermitted'] = 'Bu iÅŸleme izin verilmedi!';
$messages['nofromaddress'] = 'Seçili kimlikte e-posta adresi yok';
$messages['editorwarning'] = 'Düz metin düzenleyiciye geçmek, metin üzerindeki bütün biçimlendirmeleri kaldıracak. Devam etmek istiyor musunuz?';
diff --git a/program/localization/uk_UA/labels.inc b/program/localization/uk_UA/labels.inc
index 4605bb98d..6ff37ee21 100644
--- a/program/localization/uk_UA/labels.inc
+++ b/program/localization/uk_UA/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Чернетки';
$labels['sent'] = 'ÐадіÑлані';
$labels['trash'] = 'Кошик';
$labels['junk'] = 'Спам';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'Тема';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'Режим переглÑду';
$labels['folderactions'] = 'Операції з папкою...';
$labels['compact'] = 'СтиÑнути';
$labels['empty'] = 'Спорожнити';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'ВикориÑтано';
$labels['unknown'] = 'невідомо';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'ОчиÑтити пошук';
$labels['searchmod'] = 'Де шукати';
$labels['msgtext'] = 'Ð’ уÑьому лиÑÑ‚Ñ–';
$labels['body'] = 'Тіло повідомленнÑ';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Відкрити в новому вікні';
$labels['emlsave'] = 'Зберегти (.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'ОÑÑ‚Ð°Ð½Ð½Ñ Ñторінка';
$labels['group'] = 'Група';
$labels['groups'] = 'Групи';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'ПерÑональні адреÑи';
$labels['searchsave'] = 'Зберегти пошук';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ігнорувати Ñлова із чиÑл
$labels['spellcheckignorecaps'] = 'Ігнорувати Ñлова із великими буквами';
$labels['addtodict'] = 'Додати до Ñловника';
$labels['mailtoprotohandler'] = 'ЗареєÑтрувати обробник Ð´Ð»Ñ Ð¿Ð¾Ñилань mailto';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'ПереÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½ÑŒ';
$labels['inline'] = 'у текÑÑ‚Ñ–';
$labels['asattachment'] = 'Ñк вкладеннÑ';
diff --git a/program/localization/vi_VN/labels.inc b/program/localization/vi_VN/labels.inc
index f1cf95149..aad0dafe6 100644
--- a/program/localization/vi_VN/labels.inc
+++ b/program/localization/vi_VN/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'Thư nháp';
$labels['sent'] = 'Äã gá»­i';
$labels['trash'] = 'Sá»t rác';
$labels['junk'] = 'Thư rác';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = 'Tiêu Ä‘á»';
@@ -193,6 +194,7 @@ $labels['listmode'] = 'Xem dạng danh sách';
$labels['folderactions'] = 'Thao tác với thư mục';
$labels['compact'] = 'Nén';
$labels['empty'] = 'Trống';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'Lượng đĩa sử dụng';
$labels['unknown'] = 'Không rõ';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Thiết lập lại tìm kiếm';
$labels['searchmod'] = 'Tìm kiếm với từ khóa và ký tự đặc biệt [() : " - ]';
$labels['msgtext'] = 'Toàn bộ thư';
$labels['body'] = 'Ná»™i dung thÆ°';
+$labels['type'] = 'Type';
$labels['openinextwin'] = 'Mở trong khung cửa mới';
$labels['emlsave'] = 'Tải vỠtheo định dạng .eml';
@@ -354,6 +357,7 @@ $labels['lastpage'] = 'Hiển thị trang cuối';
$labels['group'] = 'Nhóm';
$labels['groups'] = 'Các nhóm';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Các địa chỉ cá nhân';
$labels['searchsave'] = 'Lưu tìm kiếm';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'BỠqua các từ kèm số';
$labels['spellcheckignorecaps'] = 'BỠqua các từ được viết hoa';
$labels['addtodict'] = 'Thêm vào từ điển';
$labels['mailtoprotohandler'] = 'Xác định cách xử lý giao thức mailto: liên kết';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = 'Chuyển tiếp thư';
$labels['inline'] = 'nội tuyến';
$labels['asattachment'] = 'dạng gửi kèm';
diff --git a/program/localization/zh_CN/labels.inc b/program/localization/zh_CN/labels.inc
index 23a42b96d..b568a7008 100644
--- a/program/localization/zh_CN/labels.inc
+++ b/program/localization/zh_CN/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'è‰ç¨¿ç®±';
$labels['sent'] = 'å·²å‘é€é‚®ä»¶';
$labels['trash'] = '已删除邮件';
$labels['junk'] = '垃圾邮件';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = '主题';
@@ -193,6 +194,7 @@ $labels['listmode'] = '列表视图样å¼';
$labels['folderactions'] = '文件夹æ“作...';
$labels['compact'] = '压缩';
$labels['empty'] = '清空';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = '邮箱容é‡';
$labels['unknown'] = '未知';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = '清空';
$labels['searchmod'] = '修改æœç´¢';
$labels['msgtext'] = 'æ•´å°é‚®ä»¶';
$labels['body'] = '正文';
+$labels['type'] = 'Type';
$labels['openinextwin'] = '在新窗å£ä¸­æ‰“å¼€';
$labels['emlsave'] = '下载(.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = '最åŽä¸€é¡µ';
$labels['group'] = '分组';
$labels['groups'] = '分组';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = '个人通讯录';
$labels['searchsave'] = 'ä¿å­˜æœç´¢';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = '忽略带数字的å•è¯';
$labels['spellcheckignorecaps'] = '忽略所有大写字æ¯çš„å•è¯';
$labels['addtodict'] = '添加到字典中';
$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = '邮件转å‘æ–¹å¼';
$labels['inline'] = '内嵌';
$labels['asattachment'] = '作为附件';
diff --git a/program/localization/zh_TW/labels.inc b/program/localization/zh_TW/labels.inc
index a545f2f81..7726da5dd 100644
--- a/program/localization/zh_TW/labels.inc
+++ b/program/localization/zh_TW/labels.inc
@@ -37,6 +37,7 @@ $labels['drafts'] = 'è‰ç¨¿åŒ£';
$labels['sent'] = '寄件備份';
$labels['trash'] = '垃圾桶';
$labels['junk'] = '垃圾郵件';
+$labels['show_real_foldernames'] = 'Show real names for special folders';
// message listing
$labels['subject'] = '主旨';
@@ -193,6 +194,7 @@ $labels['listmode'] = '清單檢視模å¼';
$labels['folderactions'] = '資料夾動作...';
$labels['compact'] = '壓縮';
$labels['empty'] = '清空';
+$labels['importmessages'] = 'Import messages';
$labels['quota'] = 'ç£ç¢Ÿä½¿ç”¨é‡';
$labels['unknown'] = '未知';
@@ -203,6 +205,7 @@ $labels['resetsearch'] = 'é‡è¨­æœå°‹';
$labels['searchmod'] = '修改æœå°‹';
$labels['msgtext'] = 'æ•´å°éƒµä»¶';
$labels['body'] = '內文';
+$labels['type'] = 'Type';
$labels['openinextwin'] = '在新視窗開啟';
$labels['emlsave'] = '下載(.eml)';
@@ -354,6 +357,7 @@ $labels['lastpage'] = '顯示最後一é ';
$labels['group'] = '群組';
$labels['groups'] = '群組';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = '個人通訊錄';
$labels['searchsave'] = '儲存æœå°‹çµæžœ';
@@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = '忽略數字';
$labels['spellcheckignorecaps'] = '忽略大寫字æ¯';
$labels['addtodict'] = '加入詞典';
$labels['mailtoprotohandler'] = '註冊mailto:å”定處ç†ç¨‹å¼';
+$labels['standardwindows'] = 'Handle popups as standard windows';
$labels['forwardmode'] = '郵件轉寄方å¼';
$labels['inline'] = '放入內文';
$labels['asattachment'] = '當æˆé™„件';
diff --git a/program/steps/addressbook/copy.inc b/program/steps/addressbook/copy.inc
index 480a9b52e..d4387194a 100644
--- a/program/steps/addressbook/copy.inc
+++ b/program/steps/addressbook/copy.inc
@@ -57,10 +57,16 @@ foreach ($cids as $source => $cid)
foreach ($cid as $cid) {
$a_record = $CONTACTS->get_record($cid, true);
+ // avoid copying groups
+ if ($a_record['_type'] == 'group')
+ continue;
+
// 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'], 1, true, true);
+ // @TODO: should we check all email addresses?
+ $email = $CONTACTS->get_col_values('email', $a_record, true);
+ if (!empty($email))
+ $result = $TARGET->search('email', $email[0], 1, true, true);
else if (!empty($a_record['name']))
$result = $TARGET->search('name', $a_record['name'], 1, true, true);
else
@@ -114,7 +120,7 @@ foreach ($cids as $source => $cid)
}
}
-if ($success == 0)
+if (!$success)
$OUTPUT->show_message($errormsg, 'error');
else
$OUTPUT->show_message('copysuccess', 'notice', array('nr' => $success));
diff --git a/program/steps/addressbook/delete.inc b/program/steps/addressbook/delete.inc
index 56118583c..3bb2ef500 100644
--- a/program/steps/addressbook/delete.inc
+++ b/program/steps/addressbook/delete.inc
@@ -68,48 +68,14 @@ foreach ($cids as $source => $cid)
$page = isset($_SESSION['page']) ? $_SESSION['page'] : 1;
// update saved search after data changed
-if (($search_request = $_REQUEST['_search']) && isset($_SESSION['search'][$search_request])) {
- $sort_col = $RCMAIL->config->get('addressbook_sort_col', 'name');
- $afields = $RCMAIL->config->get('contactlist_fields');
- $search = (array)$_SESSION['search'][$search_request];
- $records = array();
-
- // Get records from all sources (refresh search)
- foreach ($search as $s => $set) {
- $source = $RCMAIL->get_address_book($s);
-
- // reset page
- $source->set_page(1);
- $source->set_pagesize(9999);
- $source->set_search_set($set);
-
- // get records
- $result = $source->list_records($afields);
-
- if (!$result->count) {
- unset($search[$s]);
- continue;
- }
-
- while ($row = $result->next()) {
- $row['sourceid'] = $s;
- $key = rcube_addressbook::compose_contact_key($row, $sort_col);
- $records[$key] = $row;
- }
- unset($result);
-
- $search[$s] = $source->get_search_set();
- }
-
- $_SESSION['search'][$search_request] = $search;
-
+if (($records = rcmail_search_update(true)) !== false) {
// create resultset object
$count = count($records);
$first = ($page-1) * $PAGE_SIZE;
$result = new rcube_result_set($count, $first);
+ $pages = ceil((count($records) + $delcnt) / $PAGE_SIZE);
// get records from the next page to add to the list
- $pages = ceil((count($records) + $delcnt) / $PAGE_SIZE);
if ($_GET['_from'] != 'show' && $pages > 1 && $page < $pages) {
// sort the records
ksort($records, SORT_LOCALE_STRING);
diff --git a/program/steps/addressbook/func.inc b/program/steps/addressbook/func.inc
index d416cc14f..8ec581f9a 100644
--- a/program/steps/addressbook/func.inc
+++ b/program/steps/addressbook/func.inc
@@ -307,7 +307,7 @@ function rcmail_contacts_list($attrib)
global $CONTACTS, $OUTPUT;
// define list of cols to be displayed
- $a_show_cols = array('name');
+ $a_show_cols = array('name','action');
// add id to message list table if not specified
if (!strlen($attrib['id']))
@@ -322,7 +322,7 @@ function rcmail_contacts_list($attrib)
$OUTPUT->include_script('list.js');
// add some labels to client
- $OUTPUT->add_label('deletecontactconfirm', 'copyingcontact', 'contactdeleting');
+ $OUTPUT->add_label('deletecontactconfirm', 'copyingcontact', 'movingcontact', 'contactdeleting');
return $out;
}
@@ -336,31 +336,73 @@ function rcmail_js_contacts_list($result, $prefix='')
return;
// define list of cols to be displayed
- $a_show_cols = array('name');
+ $a_show_cols = array('name','action');
while ($row = $result->next()) {
+ $row['CID'] = $row['ID'];
+ $row['email'] = reset(rcube_addressbook::get_col_values('email', $row, true));
+
+ $source_id = $OUTPUT->get_env('source');
$a_row_cols = array();
- $classes = array('person'); // org records will follow some day
+ $classes = array($row['_type'] ? $row['_type'] : 'person');
// build contact ID with source ID
if (isset($row['sourceid'])) {
$row['ID'] = $row['ID'].'-'.$row['sourceid'];
+ $source_id = $row['sourceid'];
}
// format each col
foreach ($a_show_cols as $col) {
- $val = $col == 'name' ? rcube_addressbook::compose_list_name($row) : $row[$col];
- $a_row_cols[$col] = Q($val);
+ $val = '';
+ switch ($col) {
+ case 'name':
+ $val = Q(rcube_addressbook::compose_list_name($row));
+ break;
+
+ case 'action':
+ if ($row['_type'] == 'group') {
+ $val = html::a(array(
+ 'href' => '#list',
+ 'rel' => $row['ID'],
+ 'title' => rcube_label('listgroup'),
+ 'onclick' => sprintf("return %s.command('pushgroup',{'source':'%s','id':'%s'},this,event)", JS_OBJECT_NAME, $source_id, $row['CID']),
+ ), '&raquo;');
+ }
+ else
+ $val = '&nbsp;';
+ break;
+
+ default:
+ $val = Q($row[$col]);
+ break;
+ }
+
+ $a_row_cols[$col] = $val;
}
if ($row['readonly'])
$classes[] = 'readonly';
- $OUTPUT->command($prefix.'add_contact_row', $row['ID'], $a_row_cols, join(' ', $classes));
+ $OUTPUT->command($prefix.'add_contact_row', $row['ID'], $a_row_cols, join(' ', $classes), array_intersect_key($row, array('ID'=>1,'readonly'=>1,'_type'=>1,'email'=>1,'name'=>1)));
}
}
+function rcmail_contacts_list_title($attrib)
+{
+ global $OUTPUT;
+
+ $attrib += array('label' => 'contacts', 'id' => 'rcmabooklisttitle', 'tag' => 'span');
+ unset($attrib['name']);
+
+ $OUTPUT->add_gui_object('addresslist_title', $attrib['id']);
+ $OUTPUT->add_label('contacts');
+
+ return html::tag($attrib['tag'], $attrib, rcube_label($attrib['label']), html::$common_attrib);
+}
+
+
// similar function as /steps/settings/identities.inc::rcmail_identity_frame()
function rcmail_contact_frame($attrib)
{
@@ -429,7 +471,7 @@ function rcmail_get_type_label($type)
function rcmail_contact_form($form, $record, $attrib = null)
{
- global $RCMAIL, $CONFIG;
+ global $RCMAIL;
// Allow plugins to modify contact form content
$plugin = $RCMAIL->plugins->exec_hook('contact_form', array(
@@ -438,7 +480,7 @@ function rcmail_contact_form($form, $record, $attrib = null)
$form = $plugin['form'];
$record = $plugin['record'];
$edit_mode = $RCMAIL->action != 'show';
- $del_button = $attrib['deleteicon'] ? html::img(array('src' => $CONFIG['skin_path'] . $attrib['deleteicon'], 'alt' => rcube_label('delete'))) : rcube_label('delete');
+ $del_button = $attrib['deleteicon'] ? html::img(array('src' => $RCMAIL->output->get_skin_file($attrib['deleteicon']), 'alt' => rcube_label('delete'))) : rcube_label('delete');
unset($attrib['deleteicon']);
$out = '';
@@ -551,22 +593,13 @@ function rcmail_contact_form($form, $record, $attrib = null)
// iterate over possible subtypes and collect values with their subtype
if (is_array($colprop['subtypes'])) {
$values = $subtypes = array();
- foreach ($colprop['subtypes'] as $i => $st) {
- $newval = false;
- if ($record[$field.':'.$st]) {
- $subtypes[count($values)] = $st;
- $newval = $record[$field.':'.$st];
- }
- else if ($i == 0 && $record[$field]) {
- $subtypes[count($values)] = $st;
- $newval = $record[$field];
- }
- if ($newval !== false) {
- if (is_array($newval) && isset($newval[0]))
- $values = array_merge($values, $newval);
- else
- $values[] = $newval;
+ foreach (rcube_addressbook::get_col_values($field, $record) as $st => $vals) {
+ foreach((array)$vals as $value) {
+ $i = count($values);
+ $subtypes[$i] = $st;
+ $values[$i] = $value;
}
+ // TODO: add $st to $select_subtype if missing ?
}
}
else {
@@ -704,12 +737,15 @@ function rcmail_contact_form($form, $record, $attrib = null)
function rcmail_contact_photo($attrib)
{
- global $SOURCE_ID, $CONTACTS, $CONTACT_COLTYPES, $RCMAIL, $CONFIG;
+ global $SOURCE_ID, $CONTACTS, $CONTACT_COLTYPES, $RCMAIL;
if ($result = $CONTACTS->get_result())
$record = $result->first();
- $photo_img = $attrib['placeholder'] ? $CONFIG['skin_path'] . $attrib['placeholder'] : 'program/resources/blank.gif';
+ $photo_img = $attrib['placeholder'] ? $RCMAIL->output->get_skin_file($attrib['placeholder']) : 'program/resources/blank.gif';
+ if ($record['_type'] == 'group' && $attrib['placeholdergroup'])
+ $photo_img = $RCMAIL->output->get_skin_file($attrib['placeholdergroup']);
+
$RCMAIL->output->set_env('photo_placeholder', $photo_img);
unset($attrib['placeholder']);
@@ -743,6 +779,54 @@ function rcmail_format_date_col($val)
return format_date($val, $RCMAIL->config->get('date_format', 'Y-m-d'), false);
}
+/**
+ * Updates saved search after data changed
+ */
+function rcmail_search_update($return = false)
+{
+ global $RCMAIL;
+
+ if (($search_request = $_REQUEST['_search']) && isset($_SESSION['search'][$search_request])) {
+ $search = (array)$_SESSION['search'][$search_request];
+ $sort_col = $RCMAIL->config->get('addressbook_sort_col', 'name');
+ $afields = $return ? $RCMAIL->config->get('contactlist_fields') : array('name', 'email');
+ $records = array();
+
+ foreach ($search as $s => $set) {
+ $source = $RCMAIL->get_address_book($s);
+
+ // reset page
+ $source->set_page(1);
+ $source->set_pagesize(9999);
+ $source->set_search_set($set);
+
+ // get records
+ $result = $source->list_records($afields);
+
+ if (!$result->count) {
+ unset($search[$s]);
+ continue;
+ }
+
+ if ($return) {
+ while ($row = $result->next()) {
+ $row['sourceid'] = $s;
+ $key = rcube_addressbook::compose_contact_key($row, $sort_col);
+ $records[$key] = $row;
+ }
+ unset($result);
+ }
+
+ $search[$s] = $source->get_search_set();
+ }
+
+ $_SESSION['search'][$search_request] = $search;
+
+ return $records;
+ }
+
+ return false;
+}
/**
* Returns contact ID(s) and source(s) from GET/POST data
@@ -800,6 +884,7 @@ $OUTPUT->add_handlers(array(
'directorylist' => 'rcmail_directory_list',
// 'groupslist' => 'rcmail_contact_groups',
'addresslist' => 'rcmail_contacts_list',
+ 'addresslisttitle' => 'rcmail_contacts_list_title',
'addressframe' => 'rcmail_contact_frame',
'recordscountdisplay' => 'rcmail_rowcount_display',
'searchform' => array($OUTPUT, 'search_form')
diff --git a/program/steps/addressbook/list.inc b/program/steps/addressbook/list.inc
index 1bb28658b..aca58d279 100644
--- a/program/steps/addressbook/list.inc
+++ b/program/steps/addressbook/list.inc
@@ -19,47 +19,20 @@
+-----------------------------------------------------------------------+
*/
-$afields = $RCMAIL->config->get('contactlist_fields');
+if (!empty($_GET['_page']))
+ $page = intval($_GET['_page']);
+else
+ $page = !empty($_SESSION['page']) ? $_SESSION['page'] : 1;
-// Use search result
-if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search']]))
-{
- $search = (array)$_SESSION['search'][$_REQUEST['_search']];
- $records = array();
-
- if (!empty($_GET['_page']))
- $page = intval($_GET['_page']);
- else
- $page = isset($_SESSION['page']) ? $_SESSION['page'] : 1;
-
- $_SESSION['page'] = $page;
- $sort_col = $RCMAIL->config->get('addressbook_sort_col', 'name');
-
- // Get records from all sources
- foreach ($search as $s => $set) {
- $source = $RCMAIL->get_address_book($s);
-
- // reset page
- $source->set_page(1);
- $source->set_pagesize(9999);
- $source->set_search_set($set);
-
- // get records
- $result = $source->list_records($afields);
-
- while ($row = $result->next()) {
- $row['sourceid'] = $s;
- $key = rcube_addressbook::compose_contact_key($row, $sort_col);
- $records[$key] = $row;
- }
- unset($result);
- }
+$_SESSION['page'] = $page;
+// Use search result
+if (($records = rcmail_search_update(true)) !== false) {
// sort the records
ksort($records, SORT_LOCALE_STRING);
// create resultset object
- $count = count($records);
+ $count = count($records);
$first = ($page-1) * $PAGE_SIZE;
$result = new rcube_result_set($count, $first);
@@ -72,6 +45,7 @@ if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search
}
// List selected directory
else {
+ $afields = $RCMAIL->config->get('contactlist_fields');
$CONTACTS = rcmail_contact_source(null, true);
// get contacts for this user
@@ -81,6 +55,11 @@ else {
$OUTPUT->show_message('contactsearchonly', 'notice');
$OUTPUT->command('command', 'advanced-search');
}
+
+ if ($CONTACTS->group_id) {
+ $OUTPUT->command('set_group_prop', array('ID' => $CONTACTS->group_id)
+ + array_intersect_key((array)$CONTACTS->get_group($CONTACTS->group_id), array('name'=>1,'email'=>1)));
+ }
}
// update message count display
diff --git a/program/steps/addressbook/move.inc b/program/steps/addressbook/move.inc
new file mode 100644
index 000000000..f8204e9ee
--- /dev/null
+++ b/program/steps/addressbook/move.inc
@@ -0,0 +1,208 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | program/steps/addressbook/move.inc |
+ | |
+ | This file is part of the Roundcube Webmail client |
+ | Copyright (C) 2007-2013, The Roundcube Dev Team |
+ | |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
+ | |
+ | PURPOSE: |
+ | Move a contact record from one direcotry to another |
+ +-----------------------------------------------------------------------+
+ | Author: Thomas Bruederli <roundcube@gmail.com> |
+ | Author: Aleksander Machniak <alec@alec.pl> |
+ +-----------------------------------------------------------------------+
+*/
+
+// only process ajax requests
+if (!$OUTPUT->ajax_call) {
+ return;
+}
+
+$cids = rcmail_get_cids();
+$target = get_input_value('_to', RCUBE_INPUT_POST);
+$target_group = get_input_value('_togid', RCUBE_INPUT_POST);
+
+$all = 0;
+$deleted = 0;
+$success = 0;
+$errormsg = 'moveerror';
+$maxnum = $RCMAIL->config->get('max_group_members', 0);
+$page = !empty($_SESSION['page']) ? $_SESSION['page'] : 1;
+
+foreach ($cids as $source => $source_cids) {
+ // Something wrong, target not specified
+ if (!strlen($target)) {
+ break;
+ }
+
+ // It maight happen when moving records from search result
+ // Do nothing, go to next source
+ if ((string)$target === (string)$source) {
+ continue;
+ }
+
+ $CONTACTS = $RCMAIL->get_address_book($source);
+ $TARGET = $RCMAIL->get_address_book($target);
+
+ if (!$TARGET || !$TARGET->ready || $TARGET->readonly) {
+ break;
+ }
+
+ if (!$CONTACTS || !$CONTACTS->ready || $CONTACTS->readonly) {
+ continue;
+ }
+
+ $ids = array();
+
+ foreach ($source_cids as $idx => $cid) {
+ $a_record = $CONTACTS->get_record($cid, true);
+
+ // avoid moving groups
+ if ($a_record['_type'] == 'group') {
+ unset($source_cids[$idx]);
+ continue;
+ }
+
+ // Check if contact exists, if so, we'll need it's ID
+ // Note: Some addressbooks allows empty email address field
+ // @TODO: should we check all email addresses?
+ $email = $CONTACTS->get_col_values('email', $a_record, true);
+ if (!empty($email))
+ $result = $TARGET->search('email', $email[0], 1, true, true);
+ else if (!empty($a_record['name']))
+ $result = $TARGET->search('name', $a_record['name'], 1, true, true);
+ else
+ $result = new rcube_result_set();
+
+ // insert contact record
+ if (!$result->count) {
+ $plugin = $RCMAIL->plugins->exec_hook('contact_create', array(
+ 'record' => $a_record, 'source' => $target, 'group' => $target_group));
+
+ if (!$plugin['abort']) {
+ if ($insert_id = $TARGET->insert($plugin['record'], false)) {
+ $ids[] = $insert_id;
+ $success++;
+ }
+ }
+ else if ($plugin['result']) {
+ $ids = array_merge($ids, $plugin['result']);
+ $success++;
+ }
+ }
+ else {
+ $record = $result->first();
+ $ids[] = $record['ID'];
+ $errormsg = empty($a_record['email']) ? 'contactnameexists' : 'contactexists';
+ }
+ }
+
+ // remove source contacts
+ if ($success && !empty($source_cids)) {
+ $all += count($source_cids);
+ $plugin = $RCMAIL->plugins->exec_hook('contact_delete', array(
+ 'id' => $source_cids, 'source' => $source));
+
+ $del_status = !$plugin['abort'] ? $CONTACTS->delete($source_cids) : $plugin['result'];
+
+ if ($del_status) {
+ $deleted += $del_status;
+ }
+ }
+
+ // assign to group
+ if ($target_group && $TARGET->groups && !empty($ids)) {
+ $plugin = $RCMAIL->plugins->exec_hook('group_addmembers', array(
+ 'group_id' => $target_group, 'ids' => $ids, 'source' => $target));
+
+ if (!$plugin['abort']) {
+ $TARGET->reset();
+ $TARGET->set_group($target_group);
+
+ if ($maxnum && ($TARGET->count()->count + count($plugin['ids']) > $maxnum)) {
+ $OUTPUT->show_message('maxgroupmembersreached', 'warning', array('max' => $maxnum));
+ $OUTPUT->send();
+ }
+
+ if (($cnt = $TARGET->add_to_group($target_group, $plugin['ids'])) && $cnt > $success)
+ $success = $cnt;
+ }
+ else if ($plugin['result']) {
+ $success = $plugin['result'];
+ }
+
+ $errormsg = $plugin['message'] ? $plugin['message'] : 'moveerror';
+ }
+}
+
+if (!$deleted || $deleted != $all) {
+ // update saved search after data changed
+ if ($deleted) {
+ rcmail_search_update();
+ }
+ $OUTPUT->command('list_contacts');
+}
+else {
+ // update saved search after data changed
+ if (($records = rcmail_search_update(true)) !== false) {
+ // create resultset object
+ $count = count($records);
+ $first = ($page-1) * $PAGE_SIZE;
+ $result = new rcube_result_set($count, $first);
+ $pages = ceil((count($records) + $delcnt) / $PAGE_SIZE);
+
+ // get records from the next page to add to the list
+ if ($_GET['_from'] != 'show' && $pages > 1 && $page < $pages) {
+ // sort the records
+ ksort($records, SORT_LOCALE_STRING);
+
+ $first += $PAGE_SIZE;
+ // create resultset object
+ $res = new rcube_result_set($count, $first - $deleted);
+
+ if ($PAGE_SIZE < $count) {
+ $records = array_slice($records, $first - $deleted, $deleted);
+ }
+
+ $res->records = array_values($records);
+ $records = $res;
+ }
+ else {
+ unset($records);
+ }
+ }
+ else {
+ // count contacts for this user
+ $result = $CONTACTS->count();
+ // get records from the next page to add to the list
+ $pages = ceil(($result->count + $deleted) / $PAGE_SIZE);
+
+ if ($_GET['_from'] != 'show' && $pages > 1 && $page < $pages) {
+ $CONTACTS->set_page($page);
+ $records = $CONTACTS->list_records(null, -$deleted);
+ }
+ }
+
+ // update message count display
+ $OUTPUT->set_env('pagecount', ceil($result->count / $PAGE_SIZE));
+ $OUTPUT->command('set_rowcount', rcmail_get_rowcount_text($result));
+
+ // add new rows from next page (if any)
+ if (!empty($records)) {
+ rcmail_js_contacts_list($records);
+ }
+}
+
+if (!$success)
+ $OUTPUT->show_message($errormsg, 'error');
+else
+ $OUTPUT->show_message('movesuccess', 'notice', array('nr' => $success));
+
+// send response
+$OUTPUT->send();
diff --git a/program/steps/addressbook/save.inc b/program/steps/addressbook/save.inc
index 25bfbd48b..e7e5efc63 100644
--- a/program/steps/addressbook/save.inc
+++ b/program/steps/addressbook/save.inc
@@ -134,11 +134,11 @@ if (!empty($cid))
$record['email'] = reset($CONTACTS->get_col_values('email', $record, true));
$record['name'] = rcube_addressbook::compose_list_name($record);
- foreach (array('name', 'email') as $col)
+ foreach (array('name') as $col)
$a_js_cols[] = Q((string)$record[$col]);
// update the changed col in list
- $OUTPUT->command('parent.update_contact_row', $cid, $a_js_cols, $newcid, $source);
+ $OUTPUT->command('parent.update_contact_row', $cid, $a_js_cols, $newcid, $source, $record);
// show confirmation
$OUTPUT->show_message('successfullysaved', 'confirmation', null, false);
diff --git a/program/steps/addressbook/show.inc b/program/steps/addressbook/show.inc
index 1a97c65b1..950764bb1 100644
--- a/program/steps/addressbook/show.inc
+++ b/program/steps/addressbook/show.inc
@@ -207,9 +207,8 @@ function rcmail_contact_record_groups($contact_id)
return '';
}
- $table = new html_table(array('cols' => 2, 'cellspacing' => 0, 'border' => 0));
-
- $members = $CONTACTS->get_record_groups($contact_id);
+ $members = $CONTACTS->get_record_groups($contact_id);
+ $table = new html_table(array('cols' => 2, 'cellspacing' => 0, 'border' => 0));
$checkbox = new html_checkbox(array('name' => '_gid[]',
'class' => 'groupmember', 'disabled' => $CONTACTS->readonly));
diff --git a/program/steps/addressbook/undo.inc b/program/steps/addressbook/undo.inc
index 9c171143c..c23bd1cb6 100644
--- a/program/steps/addressbook/undo.inc
+++ b/program/steps/addressbook/undo.inc
@@ -46,30 +46,7 @@ foreach ((array)$undo['data'] as $source => $cid)
}
// update saved search after data changed
-if ($delcnt && ($search_request = $_REQUEST['_search']) && isset($_SESSION['search'][$search_request])) {
- $search = (array)$_SESSION['search'][$search_request];
-
- foreach ($search as $s => $set) {
- $source = $RCMAIL->get_address_book($s);
-
- // reset page
- $source->set_page(1);
- $source->set_pagesize(9999);
- $source->set_search_set($set);
-
- // get records
- $result = $source->list_records(array('name', 'email'));
-
- if (!$result->count) {
- unset($search[$s]);
- continue;
- }
-
- $search[$s] = $source->get_search_set();
- }
-
- $_SESSION['search'][$search_request] = $search;
-}
+rcmail_search_update();
$RCMAIL->session->remove('contact_undo');
diff --git a/program/steps/mail/check_recent.inc b/program/steps/mail/check_recent.inc
index 3649d148c..8c0b1ffc0 100644
--- a/program/steps/mail/check_recent.inc
+++ b/program/steps/mail/check_recent.inc
@@ -81,9 +81,10 @@ foreach ($a_mailboxes as $mbox_name) {
if (empty($_GET['_list']))
continue;
- // get overall message count; allow caching because rcube_storage::folder_status() did a refresh
+ // get overall message count; allow caching because rcube_storage::folder_status()
+ // did a refresh but only in list mode
$list_mode = $RCMAIL->storage->get_threading() ? 'THREADS' : 'ALL';
- $all_count = $RCMAIL->storage->count($mbox_name, $list_mode, false, false);
+ $all_count = $RCMAIL->storage->count($mbox_name, $list_mode, $list_mode == 'THREADS', false);
$page = $RCMAIL->storage->get_page();
$page_size = $RCMAIL->storage->get_pagesize();
diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc
index 9ee57d31e..9ffde8a57 100644
--- a/program/steps/mail/compose.inc
+++ b/program/steps/mail/compose.inc
@@ -170,6 +170,9 @@ $OUTPUT->set_env('compose_mode', $compose_mode);
$config_show_sig = $RCMAIL->config->get('show_sig', 1);
if ($compose_mode == RCUBE_COMPOSE_EDIT || $compose_mode == RCUBE_COMPOSE_DRAFT) {
// don't add signature in draft/edit mode, we'll also not remove the old-one
+ // but only on page display, later we should be able to change identity/sig (#1489229)
+ if ($config_show_sig == 1 || $config_show_sig == 2)
+ $OUTPUT->set_env('show_sig_later', true);
}
else if ($config_show_sig == 1)
$OUTPUT->set_env('show_sig', true);
@@ -219,8 +222,8 @@ if (!empty($msg_uid) && empty($COMPOSE['as_attachment']))
$COMPOSE['param']['sent_mbox'] = $sent_folder;
}
}
- else if ($compose_mode == RCUBE_COMPOSE_DRAFT) {
- if ($draft_info = $MESSAGE->headers->get('x-draft-info')) {
+ else if ($compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT) {
+ if ($compose_mode == RCUBE_COMPOSE_DRAFT && ($draft_info = $MESSAGE->headers->get('x-draft-info'))) {
// get reply_uid/forward_uid to flag the original message when sending
$info = rcmail_draftinfo_decode($draft_info);
@@ -242,7 +245,7 @@ if (!empty($msg_uid) && empty($COMPOSE['as_attachment']))
if ($in_reply_to = $MESSAGE->headers->get('in-reply-to'))
$COMPOSE['reply_msgid'] = '<' . $in_reply_to . '>';
- $COMPOSE['references'] = $MESSAGE->headers->references;
+ $COMPOSE['references'] = $MESSAGE->headers->references;
}
}
else {
@@ -327,7 +330,8 @@ foreach ($parts as $header) {
$fvalue .= $v;
if ($v = $MESSAGE->headers->cc)
$fvalue .= (!empty($fvalue) ? $separator : '') . $v;
- if ($v = $MESSAGE->headers->get('Sender', false))
+ // Use Sender header (#1489011)
+ if (($v = $MESSAGE->headers->get('Sender', false)) && strpos($v, '-bounces@') === false)
$fvalue .= (!empty($fvalue) ? $separator : '') . $v;
// When To: and Reply-To: are the same we add From: address to the list (#1489037)
@@ -474,6 +478,7 @@ function rcmail_compose_header_from($attrib)
if (count($MESSAGE->identities))
{
$a_signatures = array();
+ $identities = array();
$separator = intval($RCMAIL->config->get('reply_mode')) > 0
&& ($compose_mode == RCUBE_COMPOSE_REPLY || $compose_mode == RCUBE_COMPOSE_FORWARD) ? '---' : '-- ';
@@ -511,12 +516,21 @@ function rcmail_compose_header_from($attrib)
$a_signatures[$identity_id]['text'] = $text;
$a_signatures[$identity_id]['html'] = $html;
}
+
+ // add bcc and reply-to
+ if (!empty($sql_arr['reply-to'])) {
+ $identities[$identity_id]['replyto'] = $sql_arr['reply-to'];
+ }
+ if (!empty($sql_arr['bcc'])) {
+ $identities[$identity_id]['bcc'] = $sql_arr['bcc'];
+ }
}
- $out = $select_from->show($MESSAGE->compose['from']);
+ $out = $select_from->show((int)$MESSAGE->compose['from']);
// add signatures to client
$OUTPUT->set_env('signatures', $a_signatures);
+ $OUTPUT->set_env('identities', $identities);
}
// no identities, display text input field
else {
@@ -585,15 +599,32 @@ function rcmail_prepare_message_body()
}
// reply/edit/draft/forward
else if ($compose_mode && ($compose_mode != RCUBE_COMPOSE_REPLY || intval($RCMAIL->config->get('reply_mode')) != -1)) {
- $isHtml = rcmail_compose_editor_mode();
+ $isHtml = rcmail_compose_editor_mode();
+ $messages = array();
if (!empty($MESSAGE->parts)) {
+ // collect IDs of message/rfc822 parts
+ if ($compose_mode == RCUBE_COMPOSE_EDIT || $compose_mode == RCUBE_COMPOSE_DRAFT) {
+ foreach ($MESSAGE->attachments as $part) {
+ if ($part->mimetype == 'message/rfc822') {
+ $messages[] = $part->mime_id;
+ }
+ }
+ }
+
foreach ($MESSAGE->parts as $part) {
// skip no-content and attachment parts (#1488557)
if ($part->type != 'content' || !$part->size || $MESSAGE->is_attachment($part)) {
continue;
}
+ // skip all content parts inside the message/rfc822 part in DRAFT/EDIT mode
+ foreach ($messages as $mimeid) {
+ if (strpos($part->mime_id, $mimeid . '.') === 0) {
+ continue 2;
+ }
+ }
+
if ($part_body = rcmail_compose_part_body($part, $isHtml)) {
$body .= ($body ? ($isHtml ? '<br/>' : "\n") : '') . $part_body;
}
@@ -1010,7 +1041,9 @@ function rcmail_write_compose_attachments(&$message, $bodyIsHtml)
$loaded_attachments[$attachment['name'] . $attachment['mimetype']] = $attachment;
}
- $cid_map = $messages = array();
+ $cid_map = array();
+ $messages = array();
+
foreach ((array)$message->mime_parts as $pid => $part)
{
if ($part->disposition == 'attachment' || ($part->disposition == 'inline' && $bodyIsHtml) || $part->filename) {
@@ -1022,25 +1055,32 @@ function rcmail_write_compose_attachments(&$message, $bodyIsHtml)
if ($part->ctype_primary == 'message' && $compose_mode == RCUBE_COMPOSE_REPLY) {
continue;
}
- // skip inline images when forwarding in plain text
- if ($part->content_id && !$bodyIsHtml && $compose_mode == RCUBE_COMPOSE_FORWARD) {
+ // skip inline images when forwarding in text mode
+ if ($part->content_id && $part->disposition == 'inline' && !$bodyIsHtml && $compose_mode == RCUBE_COMPOSE_FORWARD) {
continue;
}
- $skip = false;
+ // skip message/rfc822 attachments on forwards (#1489214)
+ // Thunderbird when forwarding in inline mode displays such attachments
+ // and skips any attachments from inside of such part, this however
+ // skipped e.g. images used in HTML body or other attachments. So,
+ // better to skip .eml attachments but not their content (included files).
if ($part->mimetype == 'message/rfc822') {
+ if ($compose_mode == RCUBE_COMPOSE_FORWARD) {
+ continue;
+ }
$messages[] = $part->mime_id;
- } else if ($messages) {
+ }
+ else if ($compose_mode != RCUBE_COMPOSE_FORWARD) {
// skip attachments included in message/rfc822 attachment (#1486487)
foreach ($messages as $mimeid)
- if (strpos($part->mime_id, $mimeid.'.') === 0) {
- $skip = true;
- break;
+ if (strpos($part->mime_id, $mimeid . '.') === 0) {
+ continue 2;
}
}
- if (!$skip && (($attachment = $loaded_attachments[rcmail_attachment_name($part) . $part->mimetype])
- || ($attachment = rcmail_save_attachment($message, $pid)))) {
+ if (($attachment = $loaded_attachments[rcmail_attachment_name($part) . $part->mimetype])
+ || ($attachment = rcmail_save_attachment($message, $pid))) {
$COMPOSE['attachments'][$attachment['id']] = $attachment;
if ($bodyIsHtml && ($part->content_id || $part->content_location)) {
$url = sprintf('%s&_id=%s&_action=display-attachment&_file=rcmfile%s',
diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc
index ab4b41155..454650628 100644
--- a/program/steps/mail/func.inc
+++ b/program/steps/mail/func.inc
@@ -120,7 +120,7 @@ if (empty($RCMAIL->action) || $RCMAIL->action == 'list') {
if (!$OUTPUT->ajax_call)
$OUTPUT->add_label('checkingmail', 'deletemessage', 'movemessagetotrash',
'movingmessage', 'copyingmessage', 'deletingmessage', 'markingmessage',
- 'copy', 'move', 'quota', 'replyall', 'replylist');
+ 'copy', 'move', 'quota', 'replyall', 'replylist', 'importwait');
$pagetitle = $RCMAIL->localize_foldername($RCMAIL->storage->mod_folder($mbox_name), true);
$pagetitle = str_replace($delimiter, " \xC2\xBB ", $pagetitle);
@@ -128,6 +128,40 @@ if (empty($RCMAIL->action) || $RCMAIL->action == 'list') {
$OUTPUT->set_pagetitle($pagetitle);
}
+// register UI objects
+$OUTPUT->add_handlers(array(
+ 'mailboxlist' => 'rcmail_mailbox_list',
+ 'messages' => 'rcmail_message_list',
+ 'messagecountdisplay' => 'rcmail_messagecount_display',
+ 'quotadisplay' => 'rcmail_quota_display',
+ 'mailboxname' => 'rcmail_mailbox_name_display',
+ 'messageheaders' => 'rcmail_message_headers',
+ 'messagefullheaders' => 'rcmail_message_full_headers',
+ 'messagebody' => 'rcmail_message_body',
+ 'messagecontentframe' => 'rcmail_messagecontent_frame',
+ 'messageimportform' => 'rcmail_message_import_form',
+ 'searchfilter' => 'rcmail_search_filter',
+ 'searchform' => array($OUTPUT, 'search_form'),
+));
+
+// register action aliases
+$RCMAIL->register_action_map(array(
+ 'refresh' => 'check_recent.inc',
+ 'preview' => 'show.inc',
+ 'print' => 'show.inc',
+ 'move' => 'move_del.inc',
+ 'delete' => 'move_del.inc',
+ 'send' => 'sendmail.inc',
+ 'expunge' => 'folders.inc',
+ 'purge' => 'folders.inc',
+ 'remove-attachment' => 'attachments.inc',
+ 'display-attachment' => 'attachments.inc',
+ 'upload' => 'attachments.inc',
+ 'group-expand' => 'autocomplete.inc',
+));
+
+
+
/**
* Returns 'to' if current folder is configured Sent or Drafts
* or their subfolders, otherwise returns 'from'.
@@ -900,7 +934,7 @@ function rcmail_message_headers($attrib, $headers=null)
$value = $headers[$hkey];
else if ($headers['others'][$hkey])
$value = $headers['others'][$hkey];
- else
+ else if (!$attrib['valueof'])
continue;
if (in_array($hkey, $exclude_headers))
@@ -1579,45 +1613,6 @@ function rcmail_draftinfo_decode($str)
}
-function rcmail_message_part_controls($attrib)
-{
- global $MESSAGE, $RCMAIL;
-
- $part = asciiwords(get_input_value('_part', RCUBE_INPUT_GPC));
- if (!is_object($MESSAGE) || !is_array($MESSAGE->parts) || !($_GET['_uid'] && $_GET['_part']) || !$MESSAGE->mime_parts[$part])
- return '';
-
- $part = $MESSAGE->mime_parts[$part];
- $table = new html_table(array('cols' => 3));
-
- $filename = rcmail_attachment_name($part);
-
- if (!empty($filename)) {
- $table->add('title', Q(rcube_label('filename')));
- $table->add('header', Q($filename));
- $table->add('download-link', html::a(array('href' => './?'.str_replace('_frame=', '_download=', $_SERVER['QUERY_STRING'])), Q(rcube_label('download'))));
- }
-
- $table->add('title', Q(rcube_label('filesize')));
- $table->add('header', Q($RCMAIL->message_part_size($part)));
-
- return $table->show($attrib);
-}
-
-
-function rcmail_message_part_frame($attrib)
-{
- global $MESSAGE;
-
- $part = $MESSAGE->mime_parts[asciiwords(get_input_value('_part', RCUBE_INPUT_GPC))];
- $ctype_primary = strtolower($part->ctype_primary);
-
- $attrib['src'] = './?' . str_replace('_frame=', ($ctype_primary=='text' ? '_embed=' : '_preload='), $_SERVER['QUERY_STRING']);
-
- return html::iframe($attrib);
-}
-
-
/**
* clear message composing settings
*/
@@ -1786,9 +1781,12 @@ function rcmail_identity_select($MESSAGE, $identities = null, $compose_mode = 'r
// Try Return-Path
if ($from_idx === null && ($return_path = $MESSAGE->headers->others['return-path'])) {
foreach ($identities as $idx => $ident) {
- if (strpos($return_path, str_replace('@', '=', $ident['email_ascii']).'@') !== false) {
- $from_idx = $idx;
- break;
+ $ident = str_replace('@', '=', $ident['email_ascii']) . '@';
+ foreach ((array)$return_path as $path) {
+ if (strpos($path, $ident) !== false) {
+ $from_idx = $idx;
+ break 2;
+ }
}
}
}
@@ -1919,35 +1917,37 @@ function rcmail_message_error($uid=null)
$RCMAIL->output->send('messageerror');
}
-// register UI objects
-$OUTPUT->add_handlers(array(
- 'mailboxlist' => 'rcmail_mailbox_list',
- 'messages' => 'rcmail_message_list',
- 'messagecountdisplay' => 'rcmail_messagecount_display',
- 'quotadisplay' => 'rcmail_quota_display',
- 'mailboxname' => 'rcmail_mailbox_name_display',
- 'messageheaders' => 'rcmail_message_headers',
- 'messagefullheaders' => 'rcmail_message_full_headers',
- 'messagebody' => 'rcmail_message_body',
- 'messagecontentframe' => 'rcmail_messagecontent_frame',
- 'messagepartframe' => 'rcmail_message_part_frame',
- 'messagepartcontrols' => 'rcmail_message_part_controls',
- 'searchfilter' => 'rcmail_search_filter',
- 'searchform' => array($OUTPUT, 'search_form'),
-));
+function rcmail_message_import_form($attrib = array())
+{
+ global $OUTPUT;
-// register action aliases
-$RCMAIL->register_action_map(array(
- 'refresh' => 'check_recent.inc',
- 'preview' => 'show.inc',
- 'print' => 'show.inc',
- 'moveto' => 'move_del.inc',
- 'delete' => 'move_del.inc',
- 'send' => 'sendmail.inc',
- 'expunge' => 'folders.inc',
- 'purge' => 'folders.inc',
- 'remove-attachment' => 'attachments.inc',
- 'display-attachment' => 'attachments.inc',
- 'upload' => 'attachments.inc',
- 'group-expand' => 'autocomplete.inc',
-));
+ // set defaults
+ $attrib += array('id' => 'rcmImportform', 'buttons' => 'yes');
+
+ // Get filesize, enable upload progress bar
+ $max_filesize = rcube_upload_init();
+
+ $button = new html_inputfield(array('type' => 'button'));
+ $fileinput = new html_inputfield(array(
+ 'type' => 'file',
+ 'name' => '_file[]',
+ 'size' => $attrib['attachmentfieldsize'],
+ 'multiple' => 'multiple',
+ 'accept' => ".eml, .mbox, message/rfc822, text/*",
+ ));
+
+ $out = html::div($attrib,
+ $OUTPUT->form_tag(array('id' => $attrib['id'].'Frm', 'method' => 'post', 'enctype' => 'multipart/form-data'),
+ html::tag('input', array('type' => 'hidden', 'name' => '_unlock', 'value' => '')) .
+ html::div(null, $fileinput->show()) .
+ html::div('hint', rcube_label(array('name' => 'maxuploadsize', 'vars' => array('size' => $max_filesize)))) .
+ (get_boolean($attrib['buttons']) ? html::div('buttons',
+ $button->show(rcube_label('close'), array('class' => 'button', 'onclick' => "$('#$attrib[id]').hide()")) . ' ' .
+ $button->show(rcube_label('upload'), array('class' => 'button mainaction', 'onclick' => JS_OBJECT_NAME . ".command('import-messages', this.form)"))
+ ) : '')
+ )
+ );
+
+ $OUTPUT->add_gui_object('importform', $attrib['id'].'Frm');
+ return $out;
+}
diff --git a/program/steps/mail/get.inc b/program/steps/mail/get.inc
index 372757720..a27e788a3 100644
--- a/program/steps/mail/get.inc
+++ b/program/steps/mail/get.inc
@@ -38,19 +38,34 @@ ob_end_clean();
// similar code as in program/steps/mail/show.inc
if (!empty($_GET['_uid'])) {
+ $uid = get_input_value('_uid', RCUBE_INPUT_GET);
$RCMAIL->config->set('prefer_html', true);
- $MESSAGE = new rcube_message(get_input_value('_uid', RCUBE_INPUT_GET));
+ $MESSAGE = new rcube_message($uid);
}
// check connection status
check_storage_status();
+$part_id = get_input_value('_part', RCUBE_INPUT_GPC);
+
// show part page
if (!empty($_GET['_frame'])) {
- if (($part_id = get_input_value('_part', RCUBE_INPUT_GPC)) && ($part = $MESSAGE->mime_parts[$part_id])) {
- $OUTPUT->set_pagetitle(rcmail_attachment_name($part));
+ if ($part_id && ($part = $MESSAGE->mime_parts[$part_id])) {
+ $filename = rcmail_attachment_name($part);
+ $OUTPUT->set_pagetitle($filename);
}
+ // register UI objects
+ $OUTPUT->add_handlers(array(
+ 'messagepartframe' => 'rcmail_message_part_frame',
+ 'messagepartcontrols' => 'rcmail_message_part_controls',
+ ));
+
+ $OUTPUT->set_env('mailbox', $RCMAIL->storage->get_folder());
+ $OUTPUT->set_env('uid', $uid);
+ $OUTPUT->set_env('part', $part_id);
+ $OUTPUT->set_env('filename', $filename);
+
$OUTPUT->send('messagepart');
exit;
}
@@ -92,9 +107,8 @@ else if ($_GET['_thumb']) {
exit;
}
-else if (strlen($pid = get_input_value('_part', RCUBE_INPUT_GET))) {
-
- if ($part = $MESSAGE->mime_parts[$pid]) {
+else if (strlen($part_id)) {
+ if ($part = $MESSAGE->mime_parts[$part_id]) {
$mimetype = rcmail_fix_mimetype($part->mimetype);
// allow post-processing of the message body
@@ -378,7 +392,9 @@ else {
header('HTTP/1.1 404 Not Found');
exit;
-
+/**
+ * Handles nicely storage connection errors
+ */
function check_storage_status()
{
$error = rcmail::get_instance()->storage->get_error_code();
@@ -410,3 +426,49 @@ function check_storage_status()
exit;
}
}
+
+/**
+ * Attachment properties table
+ */
+function rcmail_message_part_controls($attrib)
+{
+ global $MESSAGE, $RCMAIL;
+
+ $part = asciiwords(get_input_value('_part', RCUBE_INPUT_GPC));
+ if (!is_object($MESSAGE) || !is_array($MESSAGE->parts)
+ || !($_GET['_uid'] && $_GET['_part']) || !$MESSAGE->mime_parts[$part]
+ ) {
+ return '';
+ }
+
+ $part = $MESSAGE->mime_parts[$part];
+ $table = new html_table(array('cols' => 2));
+
+ $table->add('title', Q(rcube_label('namex')).':');
+ $table->add('header', Q(rcmail_attachment_name($part)));
+
+ $table->add('title', Q(rcube_label('type')).':');
+ $table->add('header', Q($part->mimetype));
+
+ $table->add('title', Q(rcube_label('size')).':');
+ $table->add('header', Q($RCMAIL->message_part_size($part)));
+
+ return $table->show($attrib);
+}
+
+/**
+ * Attachment preview frame
+ */
+function rcmail_message_part_frame($attrib)
+{
+ global $MESSAGE, $RCMAIL;
+
+ $part = $MESSAGE->mime_parts[asciiwords(get_input_value('_part', RCUBE_INPUT_GPC))];
+ $ctype_primary = strtolower($part->ctype_primary);
+
+ $attrib['src'] = './?' . str_replace('_frame=', ($ctype_primary=='text' ? '_embed=' : '_preload='), $_SERVER['QUERY_STRING']);
+
+ $RCMAIL->output->add_gui_object('messagepartframe', $attrib['id']);
+
+ return html::iframe($attrib);
+}
diff --git a/program/steps/mail/import.inc b/program/steps/mail/import.inc
new file mode 100644
index 000000000..f7e7a3eb8
--- /dev/null
+++ b/program/steps/mail/import.inc
@@ -0,0 +1,105 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | program/steps/mail/import.inc |
+ | |
+ | This file is part of the Roundcube Webmail client |
+ | Copyright (C) 2005-2013, The Roundcube Dev Team |
+ | |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
+ | |
+ | PURPOSE: |
+ | Save the uploaded file(s) as messages to the current IMAP folder |
+ | |
+ +-----------------------------------------------------------------------+
+ | Author: Thomas Bruederli <roundcube@gmail.com> |
+ +-----------------------------------------------------------------------+
+*/
+
+// clear all stored output properties (like scripts and env vars)
+$OUTPUT->reset();
+
+if (is_array($_FILES['_file'])) {
+ $imported = 0;
+
+ foreach ((array)$_FILES['_file']['tmp_name'] as $i => $filepath) {
+ // Process uploaded file if there is no error
+ $err = $_FILES['_file']['error'][$i];
+
+ if (!$err) {
+ // check file content type first
+ list($mtype_primary,) = explode('/', rc_mime_content_type($filepath, $_FILES['_file']['name'][$i], $_FILES['_file']['type'][$i]));
+ if (!in_array($mtype_primary, array('text','message'))) {
+ $OUTPUT->show_message('importmessageerror', 'error');
+ continue;
+ }
+
+ // read the first few lines to detect header-like structure
+ $fp = fopen($filepath, 'r');
+ do { $line = fgets($fp); }
+ while ($line !== false && trim($line) == '');
+
+ if (!preg_match('/^From\s+-/', $line) && !preg_match('/^[a-z-_]+:\s+.+/i', $line)) {
+ $OUTPUT->show_message('importmessageerror', 'error');
+ continue;
+ }
+
+ $message = $lastline = '';
+ fseek($fp, 0);
+ while (($line = fgets($fp)) !== false) {
+ // importing mbox file, split by From - lines
+ if (preg_match('/^From\s+-/', $line) && $lastline == '') {
+ if (!empty($message)) {
+ if ($RCMAIL->storage->save_message(null, rtrim($message))) {
+ $imported++;
+ }
+ else {
+ rcube::raise_error("Failed to import message to " . $RCMAIL->storage->get_folder(), false, true);
+ }
+ $message = '';
+ }
+ continue;
+ }
+
+ $message .= $line;
+ $lastline = rtrim($line);
+ }
+
+ if (!empty($message) && $RCMAIL->storage->save_message(null, rtrim($message))) {
+ $imported++;
+ }
+ }
+
+ if ($err == UPLOAD_ERR_INI_SIZE || $err == UPLOAD_ERR_FORM_SIZE) {
+ $msg = rcube_label(array('name' => 'filesizeerror', 'vars' => array('size' => show_bytes(parse_bytes(ini_get('upload_max_filesize'))))));
+ }
+ else if ($err) {
+ $OUTPUT->show_message('fileuploaderror', 'error');
+ }
+ } // end foreach
+
+ if ($imported) {
+ $OUTPUT->show_message(rcube_label(array('name' => 'importmessagesuccess', 'nr' => $imported, 'vars' => array('nr' => $imported))), 'confirmation');
+ $OUTPUT->command('command', 'list');
+ }
+ else {
+ $OUTPUT->show_message('importmessageerror', 'error');
+ }
+}
+else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
+ // if filesize exceeds post_max_size then $_FILES array is empty,
+ // show filesizeerror instead of fileuploaderror
+ if ($maxsize = ini_get('post_max_size'))
+ $msg = rcube_label(array('name' => 'filesizeerror', 'vars' => array('size' => show_bytes(parse_bytes($maxsize)))));
+ else
+ $msg = rcube_label('fileuploaderror');
+
+ $OUTPUT->command('display_message', $msg, 'error');
+}
+
+// send html page with JS calls as response
+$OUTPUT->send('iframe');
+
diff --git a/program/steps/mail/list_contacts.inc b/program/steps/mail/list_contacts.inc
index 7e3b349cd..dab146431 100644
--- a/program/steps/mail/list_contacts.inc
+++ b/program/steps/mail/list_contacts.inc
@@ -19,10 +19,10 @@
+-----------------------------------------------------------------------+
*/
-$afields = $RCMAIL->config->get('contactlist_fields');
-$sort_col = $RCMAIL->config->get('addressbook_sort_col', 'name');
-$page_size = $RCMAIL->config->get('addressbook_pagesize', $RCMAIL->config->get('pagesize', 50));
-$page = max(1, intval($_GET['_page']));
+$afields = $RCMAIL->config->get('contactlist_fields');
+$addr_sort_col = $RCMAIL->config->get('addressbook_sort_col', 'name');
+$page_size = $RCMAIL->config->get('addressbook_pagesize', $RCMAIL->config->get('pagesize', 50));
+$list_page = max(1, intval($_GET['_page']));
// Use search result
if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search']])) {
@@ -42,7 +42,7 @@ if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search
while ($row = $result->next()) {
$row['sourceid'] = $s;
- $key = rcube_addressbook::compose_contact_key($row, $sort_col);
+ $key = rcube_addressbook::compose_contact_key($row, $addr_sort_col);
$records[$key] = $row;
}
unset($result);
@@ -53,7 +53,7 @@ if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search
// create resultset object
$count = count($records);
- $first = ($page-1) * $page_size;
+ $first = ($list_page-1) * $page_size;
$result = new rcube_result_set($count, $first);
// we need only records for current page
@@ -71,10 +71,13 @@ else {
if ($CONTACTS && $CONTACTS->ready) {
// set list properties
$CONTACTS->set_pagesize($page_size);
- $CONTACTS->set_page($page);
+ $CONTACTS->set_page($list_page);
+ if ($group_id = get_input_value('_gid', RCUBE_INPUT_GPC)) {
+ $CONTACTS->set_group($group_id);
+ }
// list groups of this source (on page one)
- if ($CONTACTS->groups && $CONTACTS->list_page == 1) {
+ else if ($CONTACTS->groups && $CONTACTS->list_page == 1) {
foreach ($CONTACTS->list_groups() as $group) {
$CONTACTS->reset();
$CONTACTS->set_group($group['ID']);
@@ -89,6 +92,19 @@ else {
'contactgroup' => html::span(array('title' => $email), Q($group['name']))), 'group');
}
}
+ // make virtual groups clickable to list their members
+ else if ($group_prop['virtual']) {
+ $row_id = 'G'.$group['ID'];
+ $OUTPUT->command('add_contact_row', $row_id, array(
+ 'contactgroup' => html::a(array(
+ 'href' => '#list',
+ 'rel' => $row['ID'],
+ 'title' => rcube_label('listgroup'),
+ 'onclick' => sprintf("return %s.command('pushgroup',{'source':'%s','id':'%s'},this,event)", JS_OBJECT_NAME, $source, $group['ID']),
+ ), Q($group['name']) . '&nbsp;' . html::span('action', '&raquo;'))),
+ 'group',
+ array('ID' => $group['ID'], 'name' => $group['name'], 'virtual' => true));
+ }
// show group with count
else if (($result = $CONTACTS->count()) && $result->count) {
$row_id = 'E'.$group['ID'];
@@ -97,10 +113,12 @@ else {
'contactgroup' => Q($group['name'] . ' (' . intval($result->count) . ')')), 'group');
}
}
+
+ $CONTACTS->reset();
+ $CONTACTS->set_group(0);
}
// get contacts for this user
- $CONTACTS->set_group(0);
$result = $CONTACTS->list_records($afields);
}
}
@@ -118,10 +136,13 @@ else if (!empty($result) && $result->count > 0) {
foreach ($emails as $i => $email) {
$row_id = $row['ID'].$i;
$jsresult[$row_id] = format_email_recipient($email, $name);
+ $classname = $row['_type'] == 'group' ? 'group' : 'person';
+ $keyname = $row['_type'] == 'group' ? 'contactgroup' : 'contact';
+
$OUTPUT->command('add_contact_row', $row_id, array(
- 'contact' => html::span(array('title' => $email), Q($name ? $name : $email) .
+ $keyname => html::span(array('title' => $email), Q($name ? $name : $email) .
($name && count($emails) > 1 ? '&nbsp;' . html::span('email', Q($email)) : '')
- )), 'person');
+ )), $classname);
}
}
}
diff --git a/program/steps/mail/move_del.inc b/program/steps/mail/move_del.inc
index e21ba2c6b..f15cd2460 100644
--- a/program/steps/mail/move_del.inc
+++ b/program/steps/mail/move_del.inc
@@ -29,7 +29,7 @@ $old_count = $RCMAIL->storage->count(NULL, $threading ? 'THREADS' : 'ALL');
$old_pages = ceil($old_count / $RCMAIL->storage->get_pagesize());
// move messages
-if ($RCMAIL->action == 'moveto' && !empty($_POST['_uid']) && strlen($_POST['_target_mbox'])) {
+if ($RCMAIL->action == 'move' && !empty($_POST['_uid']) && strlen($_POST['_target_mbox'])) {
$count = sizeof(explode(',', ($uids = get_input_value('_uid', RCUBE_INPUT_POST))));
$target = get_input_value('_target_mbox', RCUBE_INPUT_POST, true);
$mbox = get_input_value('_mbox', RCUBE_INPUT_POST, true);
@@ -126,7 +126,7 @@ else
rcmail_set_unseen_count($mbox, $unseen_count);
}
- if ($RCMAIL->action == 'moveto' && strlen($target)) {
+ if ($RCMAIL->action == 'move' && strlen($target)) {
rcmail_send_unread_count($target, true);
}
diff --git a/program/steps/mail/search_contacts.inc b/program/steps/mail/search_contacts.inc
index 2e6bb12f8..6a30ad1f5 100644
--- a/program/steps/mail/search_contacts.inc
+++ b/program/steps/mail/search_contacts.inc
@@ -19,16 +19,15 @@
+-----------------------------------------------------------------------+
*/
-$search = get_input_value('_q', RCUBE_INPUT_GPC, true);
-$sources = $RCMAIL->get_address_sources();
-$search_mode = (int) $RCMAIL->config->get('addressbook_search_mode');
-$sort_col = $RCMAIL->config->get('addressbook_sort_col', 'name');
-$afields = $RCMAIL->config->get('contactlist_fields');
+$search = get_input_value('_q', RCUBE_INPUT_GPC, true);
+$sources = $RCMAIL->get_address_sources();
+$search_mode = (int) $RCMAIL->config->get('addressbook_search_mode');
+$addr_sort_col = $RCMAIL->config->get('addressbook_sort_col', 'name');
+$afields = $RCMAIL->config->get('contactlist_fields');
+$page_size = $RCMAIL->config->get('addressbook_pagesize', $RCMAIL->config->get('pagesize', 50));
+$records = array();
+$search_set = array();
-$page = 1;
-$page_size = $RCMAIL->config->get('addressbook_pagesize', $RCMAIL->config->get('pagesize', 50));
-
-$records = $search_set = array();
foreach ($sources as $s) {
$source = $RCMAIL->get_address_book($s['id']);
$source->set_page(1);
@@ -46,7 +45,7 @@ foreach ($sources as $s) {
while ($row = $result->next()) {
$row['sourceid'] = $s['id'];
- $key = rcube_addressbook::compose_contact_key($row, $sort_col);
+ $key = rcube_addressbook::compose_contact_key($row, $addr_sort_col);
$records[$key] = $row;
}
diff --git a/program/steps/mail/sendmail.inc b/program/steps/mail/sendmail.inc
index cb3a40524..cf22a2af9 100644
--- a/program/steps/mail/sendmail.inc
+++ b/program/steps/mail/sendmail.inc
@@ -391,10 +391,6 @@ if (!empty($mailcc)) {
if (!empty($mailbcc)) {
$headers['Bcc'] = $mailbcc;
}
-if (!empty($identity_arr['bcc']) && stripos($headers['Bcc'], $identity_arr['bcc']) === false) {
- $headers['Bcc'] = ($headers['Bcc'] ? $headers['Bcc'].', ' : '') . $identity_arr['bcc'];
- $RECIPIENT_COUNT ++;
-}
if (($max_recipients = (int) $RCMAIL->config->get('max_recipients')) > 0) {
if ($RECIPIENT_COUNT > $max_recipients) {
@@ -412,9 +408,6 @@ if (!empty($identity_arr['organization'])) {
if (!empty($_POST['_replyto'])) {
$headers['Reply-To'] = rcmail_email_input_format(get_input_value('_replyto', RCUBE_INPUT_POST, TRUE, $message_charset));
}
-else if (!empty($identity_arr['reply-to'])) {
- $headers['Reply-To'] = rcmail_email_input_format($identity_arr['reply-to'], false, true);
-}
if (!empty($headers['Reply-To'])) {
$headers['Mail-Reply-To'] = $headers['Reply-To'];
}
diff --git a/program/steps/mail/show.inc b/program/steps/mail/show.inc
index d8d4372f9..59f4d55e1 100644
--- a/program/steps/mail/show.inc
+++ b/program/steps/mail/show.inc
@@ -275,9 +275,13 @@ function rcmail_contact_exists($email)
if ($email) {
// @TODO: search in all address books?
$CONTACTS = $RCMAIL->get_address_book(-1, true);
- $existing = $CONTACTS->search('email', $email, true, false);
- if ($existing->count)
- return true;
+
+ if (is_object($CONTACTS)) {
+ $existing = $CONTACTS->search('email', $email, true, false);
+ if ($existing->count) {
+ return true;
+ }
+ }
}
return false;
diff --git a/program/steps/settings/folders.inc b/program/steps/settings/folders.inc
index 34a72dd95..6d116e7d2 100644
--- a/program/steps/settings/folders.inc
+++ b/program/steps/settings/folders.inc
@@ -232,16 +232,16 @@ function rcube_subscription_form($attrib)
// add any necessary "virtual" parent folders
if ($parent_folder && !isset($seen[$parent_folder])) {
for ($i=1; $i<=$level; $i++) {
- $ancestor_folder = join($delimiter, array_slice($foldersplit, 0, $i));
- if ($ancestor_folder && !$seen[$ancestor_folder]++) {
- $ancestor_name = rcube_charset_convert($foldersplit[$i-1], 'UTF7-IMAP');
- $list_folders[] = array(
+ $ancestor_folder = join($delimiter, array_slice($foldersplit, 0, $i));
+ if ($ancestor_folder && !$seen[$ancestor_folder]++) {
+ $ancestor_name = rcube_charset_convert($foldersplit[$i-1], 'UTF7-IMAP');
+ $list_folders[] = array(
'id' => $ancestor_folder,
'name' => $ancestor_name,
'level' => $i-1,
'virtual' => true,
);
- }
+ }
}
}
@@ -291,7 +291,8 @@ function rcube_subscription_form($attrib)
$classes[] = 'virtual';
}
- if (!$protected) {
+ // Check \Noselect flag (of existing folder)
+ if (!$protected && in_array($folder['id'], $a_unsubscribed)) {
$attrs = $STORAGE->folder_attributes($folder['id']);
$noselect = in_array('\\Noselect', $attrs);
}
diff --git a/program/steps/settings/func.inc b/program/steps/settings/func.inc
index ce86b1cd6..dbc9b3ce2 100644
--- a/program/steps/settings/func.inc
+++ b/program/steps/settings/func.inc
@@ -19,926 +19,1175 @@
+-----------------------------------------------------------------------+
*/
-if (!$OUTPUT->ajax_call)
- $OUTPUT->set_pagetitle(rcube_label('preferences'));
-
+if (!$OUTPUT->ajax_call) {
+ $OUTPUT->set_pagetitle(rcube_label('preferences'));
+}
// similar function as /steps/settings/identities.inc::rcmail_identity_frame()
function rcmail_preferences_frame($attrib)
{
- global $OUTPUT;
+ global $OUTPUT;
- if (!$attrib['id'])
- $attrib['id'] = 'rcmprefsframe';
+ if (!$attrib['id']) {
+ $attrib['id'] = 'rcmprefsframe';
+ }
- return $OUTPUT->frame($attrib, true);
+ return $OUTPUT->frame($attrib, true);
}
function rcmail_sections_list($attrib)
{
- global $RCMAIL;
+ global $RCMAIL;
- // add id to message list table if not specified
- if (!strlen($attrib['id']))
- $attrib['id'] = 'rcmsectionslist';
+ // add id to message list table if not specified
+ if (!strlen($attrib['id'])) {
+ $attrib['id'] = 'rcmsectionslist';
+ }
- list($list, $cols) = rcmail_user_prefs();
+ list($list, $cols) = rcmail_user_prefs();
- // create XHTML table
- $out = rcube_table_output($attrib, $list, $cols, 'id');
+ // create XHTML table
+ $out = rcube_table_output($attrib, $list, $cols, 'id');
- // set client env
- $RCMAIL->output->add_gui_object('sectionslist', $attrib['id']);
- $RCMAIL->output->include_script('list.js');
+ // set client env
+ $RCMAIL->output->add_gui_object('sectionslist', $attrib['id']);
+ $RCMAIL->output->include_script('list.js');
- return $out;
+ return $out;
}
function rcmail_identities_list($attrib)
{
- global $OUTPUT, $RCMAIL;
+ global $OUTPUT, $RCMAIL;
- // add id to message list table if not specified
- if (!strlen($attrib['id']))
- $attrib['id'] = 'rcmIdentitiesList';
+ // add id to message list table if not specified
+ if (!strlen($attrib['id'])) {
+ $attrib['id'] = 'rcmIdentitiesList';
+ }
- // get identities list and define 'mail' column
- $list = $RCMAIL->user->list_identities();
- foreach ($list as $idx => $row)
- $list[$idx]['mail'] = trim($row['name'] . ' <' . rcube_idn_to_utf8($row['email']) .'>');
+ // get identities list and define 'mail' column
+ $list = $RCMAIL->user->list_identities();
+ foreach ($list as $idx => $row) {
+ $list[$idx]['mail'] = trim($row['name'] . ' <' . rcube_idn_to_utf8($row['email']) .'>');
+ }
- // get all identites from DB and define list of cols to be displayed
- $plugin = $RCMAIL->plugins->exec_hook('identities_list', array(
- 'list' => $list,
- 'cols' => array('mail')));
+ // get all identites from DB and define list of cols to be displayed
+ $plugin = $RCMAIL->plugins->exec_hook('identities_list', array(
+ 'list' => $list,
+ 'cols' => array('mail')
+ ));
- // @TODO: use <UL> instead of <TABLE> for identities list
- // create XHTML table
- $out = rcube_table_output($attrib, $plugin['list'], $plugin['cols'], 'identity_id');
+ // @TODO: use <UL> instead of <TABLE> for identities list
+ // create XHTML table
+ $out = rcube_table_output($attrib, $plugin['list'], $plugin['cols'], 'identity_id');
- // set client env
- $OUTPUT->add_gui_object('identitieslist', $attrib['id']);
+ // set client env
+ $OUTPUT->add_gui_object('identitieslist', $attrib['id']);
- return $out;
+ return $out;
}
// similar function as in /steps/addressbook/edit.inc
function get_form_tags($attrib, $action, $id = null, $hidden = null)
{
- global $EDIT_FORM, $RCMAIL;
-
- $form_start = $form_end = '';
-
- if (empty($EDIT_FORM)) {
- $request_key = $action . (isset($id) ? '.'.$id : '');
- $form_start = $RCMAIL->output->request_form(array(
- 'name' => 'form',
- 'method' => 'post',
- 'task' => $RCMAIL->task,
- 'action' => $action,
- 'request' => $request_key,
- 'noclose' => true
- ) + $attrib);
-
- if (is_array($hidden)) {
- $hiddenfields = new html_hiddenfield($hidden);
- $form_start .= $hiddenfields->show();
- }
+ global $EDIT_FORM, $RCMAIL;
+
+ $form_start = $form_end = '';
+
+ if (empty($EDIT_FORM)) {
+ $request_key = $action . (isset($id) ? '.'.$id : '');
+ $form_start = $RCMAIL->output->request_form(array(
+ 'name' => 'form',
+ 'method' => 'post',
+ 'task' => $RCMAIL->task,
+ 'action' => $action,
+ 'request' => $request_key,
+ 'noclose' => true
+ ) + $attrib);
+
+ if (is_array($hidden)) {
+ $hiddenfields = new html_hiddenfield($hidden);
+ $form_start .= $hiddenfields->show();
+ }
- $form_end = !strlen($attrib['form']) ? '</form>' : '';
+ $form_end = !strlen($attrib['form']) ? '</form>' : '';
- $EDIT_FORM = !empty($attrib['form']) ? $attrib['form'] : 'form';
- $RCMAIL->output->add_gui_object('editform', $EDIT_FORM);
- }
+ $EDIT_FORM = !empty($attrib['form']) ? $attrib['form'] : 'form';
+ $RCMAIL->output->add_gui_object('editform', $EDIT_FORM);
+ }
- return array($form_start, $form_end);
+ return array($form_start, $form_end);
}
-function rcmail_user_prefs($current=null)
+function rcmail_user_prefs($current = null)
{
- global $RCMAIL;
-
- $sections['general'] = array('id' => 'general', 'section' => rcube_label('uisettings'));
- $sections['mailbox'] = array('id' => 'mailbox', 'section' => rcube_label('mailboxview'));
- $sections['mailview'] = array('id' => 'mailview','section' => rcube_label('messagesdisplaying'));
- $sections['compose'] = array('id' => 'compose', 'section' => rcube_label('messagescomposition'));
- $sections['addressbook'] = array('id' => 'addressbook','section' => rcube_label('addressbook'));
- $sections['folders'] = array('id' => 'folders', 'section' => rcube_label('specialfolders'));
- $sections['server'] = array('id' => 'server', 'section' => rcube_label('serversettings'));
-
- // hook + define list cols
- $plugin = $RCMAIL->plugins->exec_hook('preferences_sections_list',
- array('list' => $sections, 'cols' => array('section')));
-
- $sections = $plugin['list'];
-
- $config = $RCMAIL->config->all();
- $no_override = array_flip($RCMAIL->config->get('dont_override', array()));
-
- foreach ($sections as $idx => $sect) {
-
- if ($current && $sect['id'] != $current)
- continue;
-
- $blocks = array();
-
- switch ($sect['id']) {
- // general
- case 'general':
-
- $blocks = array(
- 'main' => array('name' => Q(rcube_label('mainoptions'))),
- );
-
- // language selection
- if (!isset($no_override['language'])) {
- $a_lang = $RCMAIL->list_languages();
- asort($a_lang);
-
- $field_id = 'rcmfd_lang';
- $select_lang = new html_select(array('name' => '_language', 'id' => $field_id));
- $select_lang->add(array_values($a_lang), array_keys($a_lang));
-
- $blocks['main']['options']['language'] = array(
- 'title' => html::label($field_id, Q(rcube_label('language'))),
- 'content' => $select_lang->show($RCMAIL->user->language),
- );
- }
-
- // timezone selection
- if (!isset($no_override['timezone'])) {
- $field_id = 'rcmfd_timezone';
- $select_timezone = new html_select(array('name' => '_timezone', 'id' => $field_id));
- $select_timezone->add(rcube_label('autodetect'), 'auto');
-
- $zones = array();
- foreach (DateTimeZone::listIdentifiers() as $i => $tzs) {
- try {
- $tz = new DateTimeZone($tzs);
- $date = new DateTime('2012-12-21', $tz);
- $offset = $date->format('Z') + 45000;
- $sortkey = sprintf('%06d.%s', $offset, $tzs);
- $zones[$sortkey] = array($tzs, $date->format('P'));
- }
- catch (Exception $e) {}
- }
-
- ksort($zones);
- foreach ($zones as $zone) {
- list($tzs, $offset) = $zone;
- $select_timezone->add('(GMT ' . $offset . ') ' . strtr($tzs, '_', ' '), $tzs);
- }
-
- $blocks['main']['options']['timezone'] = array(
- 'title' => html::label($field_id, Q(rcube_label('timezone'))),
- 'content' => $select_timezone->show((string)$config['timezone']),
- );
- }
-
- // 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']),
- );
- }
+ global $RCMAIL;
- // MM: Show checkbox for toggling 'pretty dates'
- if (!isset($no_override['prettydate'])) {
- $field_id = 'rcmfd_prettydate';
- $input_prettydate = new html_checkbox(array('name' => '_pretty_date', 'id' => $field_id, 'value' => 1));
+ $sections['general'] = array('id' => 'general', 'section' => rcube_label('uisettings'));
+ $sections['mailbox'] = array('id' => 'mailbox', 'section' => rcube_label('mailboxview'));
+ $sections['mailview'] = array('id' => 'mailview','section' => rcube_label('messagesdisplaying'));
+ $sections['compose'] = array('id' => 'compose', 'section' => rcube_label('messagescomposition'));
+ $sections['addressbook'] = array('id' => 'addressbook','section' => rcube_label('addressbook'));
+ $sections['folders'] = array('id' => 'folders', 'section' => rcube_label('specialfolders'));
+ $sections['server'] = array('id' => 'server', 'section' => rcube_label('serversettings'));
- $blocks['main']['options']['prettydate'] = array(
- 'title' => html::label($field_id, Q(rcube_label('prettydate'))),
- 'content' => $input_prettydate->show($config['prettydate']?1:0),
- );
- }
+ // hook + define list cols
+ $plugin = $RCMAIL->plugins->exec_hook('preferences_sections_list',
+ array('list' => $sections, 'cols' => array('section')));
- if (!isset($no_override['refresh_interval'])) {
- $field_id = 'rcmfd_refresh_interval';
- $select_refresh_interval = new html_select(array('name' => '_refresh_interval', 'id' => $field_id));
+ $sections = $plugin['list'];
+ $config = $RCMAIL->config->all();
+ $no_override = array_flip((array)$RCMAIL->config->get('dont_override'));
- $select_refresh_interval->add(rcube_label('never'), 0);
- foreach (array(1, 3, 5, 10, 15, 30, 60) as $min) {
- if (!$config['min_refresh_interval'] || $config['min_refresh_interval'] <= $min * 60) {
- $label = rcube_label(array('name' => 'everynminutes', 'vars' => array('n' => $min)));
- $select_refresh_interval->add($label, $min);
+ foreach ($sections as $idx => $sect) {
+ if ($current && $sect['id'] != $current) {
+ continue;
}
- }
- $blocks['main']['options']['refresh_interval'] = array(
- 'title' => html::label($field_id, Q(rcube_label('refreshinterval'))),
- 'content' => $select_refresh_interval->show($config['refresh_interval']/60),
- );
- }
-
- // show drop-down for available skins
- if (!isset($no_override['skin'])) {
- $skins = rcmail_get_skins();
-
- if (count($skins) > 1) {
- $field_id = 'rcmfd_skin';
- $input_skin = new html_radiobutton(array('name'=>'_skin'));
-
- $blocks['skin'] = array('name' => Q(rcube_label('skin')),);
-
- foreach($skins as $skin) {
- $thumbnail = "./skins/$skin/thumbnail.png";
- if (!is_file($thumbnail))
- $thumbnail = './program/resources/blank.gif';
-
- $skinname = ucfirst($skin);
- $author_link = $license_link = '';
- $meta = @json_decode(@file_get_contents("./skins/$skin/meta.json"), true);
- if (is_array($meta) && $meta['name']) {
- $skinname = $meta['name'];
- $author_link = $meta['url'] ? html::a(array('href' => $meta['url'], 'target' => '_blank'), Q($meta['author'])) : Q($meta['author']);
- $license_link = $meta['license-url'] ? html::a(array('href' => $meta['license-url'], 'target' => '_blank'), Q($meta['license'])) : Q($meta['license']);
- }
-
- $blocks['skin']['options'][$skin]['content'] = html::label(array('class' => 'skinselection'),
- html::span('skinitem', $input_skin->show($config['skin'], array('value' => $skin, 'id' => $field_id.$skin))) .
- html::span('skinitem', html::img(array('src' => $thumbnail, 'class' => 'skinthumbnail', 'alt' => $skin, 'width' => 64, 'height' => 64))) .
- html::span('skinitem', html::span('skinname', Q($skinname)) . html::br() .
- html::span('skinauthor', $author_link ? 'by ' . $author_link : '') . html::br() .
- html::span('skinlicense', $license_link ? rcube_label('license').':&nbsp;' . $license_link : ''))
- );
+ $blocks = array();
+
+ switch ($sect['id']) {
+
+ // general
+ case 'general':
+ $blocks = array(
+ 'main' => array('name' => Q(rcube_label('mainoptions'))),
+ 'skin' => array('name' => Q(rcube_label('skin'))),
+ 'browser' => array('name' => Q(rcube_label('browseroptions'))),
+ );
+
+ // language selection
+ if (!isset($no_override['language'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $a_lang = $RCMAIL->list_languages();
+ asort($a_lang);
+
+ $field_id = 'rcmfd_lang';
+ $select = new html_select(array('name' => '_language', 'id' => $field_id));
+ $select->add(array_values($a_lang), array_keys($a_lang));
+
+ $blocks['main']['options']['language'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('language'))),
+ 'content' => $select->show($RCMAIL->user->language),
+ );
+ }
+
+ // timezone selection
+ if (!isset($no_override['timezone'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_timezone';
+ $select = new html_select(array('name' => '_timezone', 'id' => $field_id));
+ $select->add(rcube_label('autodetect'), 'auto');
+
+ $zones = array();
+ foreach (DateTimeZone::listIdentifiers() as $i => $tzs) {
+ try {
+ $tz = new DateTimeZone($tzs);
+ $date = new DateTime('2012-12-21', $tz);
+ $offset = $date->format('Z') + 45000;
+ $sortkey = sprintf('%06d.%s', $offset, $tzs);
+ $zones[$sortkey] = array($tzs, $date->format('P'));
+ }
+ catch (Exception $e) {}
+ }
+
+ ksort($zones);
+
+ foreach ($zones as $zone) {
+ list($tzs, $offset) = $zone;
+ $select->add('(GMT ' . $offset . ') ' . strtr($tzs, '_', ' '), $tzs);
+ }
+
+ $blocks['main']['options']['timezone'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('timezone'))),
+ 'content' => $select->show((string)$config['timezone']),
+ );
+ }
+
+ // date/time formatting
+ if (!isset($no_override['time_format'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $reftime = mktime(7,30,0);
+ $defaults = array('G:i', 'H:i', 'g:i a', 'h:i A');
+ $formats = (array)$RCMAIL->config->get('time_formats', $defaults);
+ $field_id = 'rcmfd_time_format';
+ $select = new html_select(array('name' => '_time_format', 'id' => $field_id));
+
+ foreach ($formats as $choice) {
+ $select->add(date($choice, $reftime), $choice);
+ }
+
+ $blocks['main']['options']['time_format'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('timeformat'))),
+ 'content' => $select->show($RCMAIL->config->get('time_format')),
+ );
+ }
+
+ if (!isset($no_override['date_format'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $refdate = mktime(12,30,0,7,24);
+ $defaults = array('Y-m-d','d-m-Y','Y/m/d','m/d/Y','d/m/Y','d.m.Y','j.n.Y');
+ $formats = (array)$RCMAIL->config->get('date_formats', $defaults);
+ $field_id = 'rcmfd_date_format';
+ $select = new html_select(array('name' => '_date_format', 'id' => $field_id));
+
+ foreach ($formats as $choice) {
+ $select->add(date($choice, $refdate), $choice);
+ }
+
+ $blocks['main']['options']['date_format'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('dateformat'))),
+ 'content' => $select->show($config['date_format']),
+ );
+ }
+
+ // Show checkbox for toggling 'pretty dates'
+ if (!isset($no_override['prettydate'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_prettydate';
+ $input = new html_checkbox(array('name' => '_pretty_date', 'id' => $field_id, 'value' => 1));
+
+ $blocks['main']['options']['prettydate'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('prettydate'))),
+ 'content' => $input->show($config['prettydate']?1:0),
+ );
+ }
+
+ if (!isset($no_override['refresh_interval'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_refresh_interval';
+ $select = new html_select(array('name' => '_refresh_interval', 'id' => $field_id));
+
+ $select->add(rcube_label('never'), 0);
+ foreach (array(1, 3, 5, 10, 15, 30, 60) as $min) {
+ if (!$config['min_refresh_interval'] || $config['min_refresh_interval'] <= $min * 60) {
+ $label = rcube_label(array('name' => 'everynminutes', 'vars' => array('n' => $min)));
+ $select->add($label, $min);
+ }
+ }
+
+ $blocks['main']['options']['refresh_interval'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('refreshinterval'))),
+ 'content' => $select->show($config['refresh_interval']/60),
+ );
+ }
+
+ // show drop-down for available skins
+ if (!isset($no_override['skin'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $skins = rcmail_get_skins();
+
+ if (count($skins) > 1) {
+ $field_id = 'rcmfd_skin';
+ $input = new html_radiobutton(array('name'=>'_skin'));
+
+ foreach ($skins as $skin) {
+ $thumbnail = "./skins/$skin/thumbnail.png";
+ if (!is_file($thumbnail))
+ $thumbnail = './program/resources/blank.gif';
+
+ $skinname = ucfirst($skin);
+ $author_link = $license_link = '';
+ $meta = @json_decode(@file_get_contents("./skins/$skin/meta.json"), true);
+
+ if (is_array($meta) && $meta['name']) {
+ $skinname = $meta['name'];
+ $author_link = $meta['url'] ? html::a(array('href' => $meta['url'], 'target' => '_blank'), Q($meta['author'])) : Q($meta['author']);
+ $license_link = $meta['license-url'] ? html::a(array('href' => $meta['license-url'], 'target' => '_blank'), Q($meta['license'])) : Q($meta['license']);
+ }
+
+ $blocks['skin']['options'][$skin]['content'] = html::label(array('class' => 'skinselection'),
+ html::span('skinitem', $input->show($config['skin'], array('value' => $skin, 'id' => $field_id.$skin))) .
+ html::span('skinitem', html::img(array('src' => $thumbnail, 'class' => 'skinthumbnail', 'alt' => $skin, 'width' => 64, 'height' => 64))) .
+ html::span('skinitem', html::span('skinname', Q($skinname)) . html::br() .
+ html::span('skinauthor', $author_link ? 'by ' . $author_link : '') . html::br() .
+ html::span('skinlicense', $license_link ? rcube_label('license').':&nbsp;' . $license_link : ''))
+ );
+ }
+ }
+ }
+
+ // standard_windows option decides if new windows should be
+ // opened as popups or standard windows (which can be handled by browsers as tabs)
+ if (!isset($no_override['standard_windows'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_standard_windows';
+ $checkbox = new html_checkbox(array('name' => '_standard_windows', 'id' => $field_id, 'value' => 1));
+
+ $blocks['browser']['options']['standard_windows'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('standardwindows'))),
+ 'content' => $checkbox->show($config['standard_windows']?1:0),
+ );
+ }
+
+ if ($current) {
+ $product_name = $RCMAIL->config->get('product_name', 'Roundcube Webmail');
+ $RCMAIL->output->add_script(sprintf("%s.check_protocol_handler('%s', '#mailtoprotohandler');",
+ JS_OBJECT_NAME, JQ($product_name)), 'foot');
+ }
+
+ $blocks['browser']['options']['mailtoprotohandler'] = array(
+ 'content' => html::a(array(
+ 'href' => '#',
+ 'id' => 'mailtoprotohandler'), Q(rcube_label('mailtoprotohandler'))),
+ );
+
+ break;
+
+ // Mailbox view (mail screen)
+ case 'mailbox':
+ $blocks = array(
+ 'main' => array('name' => Q(rcube_label('mainoptions'))),
+ 'new_message' => array('name' => Q(rcube_label('newmessage'))),
+ );
+
+ // show config parameter for preview pane
+ if (!isset($no_override['preview_pane'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_preview';
+ $input = new html_checkbox(array('name' => '_preview_pane', 'id' => $field_id, 'value' => 1,
+ 'onchange' => "$('#rcmfd_preview_pane_mark_read').prop('disabled', !this.checked)"));
+
+ $blocks['main']['options']['preview_pane'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('previewpane'))),
+ 'content' => $input->show($config['preview_pane']?1:0),
+ );
+ }
+
+ // show config parameter for preview pane auto mark as read delay
+ if (!isset($no_override['preview_pane_mark_read'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ // apply default if config option is not set at all
+ $config['preview_pane_mark_read'] = $RCMAIL->config->get('preview_pane_mark_read', 0);
+
+ $field_id = 'rcmfd_preview_pane_mark_read';
+ $select = new html_select(array('name' => '_preview_pane_mark_read', 'id' => $field_id,
+ 'disabled' => $config['preview_pane']?0:1));
+
+ $select->add(rcube_label('never'), '-1');
+ $select->add(rcube_label('immediately'), 0);
+
+ foreach (array(5, 10, 20, 30) as $sec) {
+ $label = rcube_label(array('name' => 'afternseconds', 'vars' => array('n' => $sec)));
+ $select->add($label, $sec);
+ }
+
+ $blocks['main']['options']['preview_pane_mark_read'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('previewpanemarkread'))),
+ 'content' => $select->show(intval($config['preview_pane_mark_read'])),
+ );
+ }
+
+ if (!isset($no_override['mdn_requests'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_mdn_requests';
+ $select = new html_select(array('name' => '_mdn_requests', 'id' => $field_id));
+ $select->add(rcube_label('askuser'), 0);
+ $select->add(rcube_label('autosend'), 1);
+ $select->add(rcube_label('autosendknown'), 3);
+ $select->add(rcube_label('autosendknownignore'), 4);
+ $select->add(rcube_label('ignore'), 2);
+
+ $blocks['main']['options']['mdn_requests'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('mdnrequests'))),
+ 'content' => $select->show($config['mdn_requests']),
+ );
+ }
+
+ if (!isset($no_override['autoexpand_threads'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $storage = $RCMAIL->get_storage();
+ $supported = $storage->get_capability('THREAD');
+
+ if ($supported) {
+ $field_id = 'rcmfd_autoexpand_threads';
+ $select = new html_select(array('name' => '_autoexpand_threads', 'id' => $field_id));
+ $select->add(rcube_label('never'), 0);
+ $select->add(rcube_label('do_expand'), 1);
+ $select->add(rcube_label('expand_only_unread'), 2);
+
+ $blocks['main']['options']['autoexpand_threads'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('autoexpand_threads'))),
+ 'content' => $select->show($config['autoexpand_threads']),
+ );
+ }
+ }
+
+ // show page size selection
+ if (!isset($no_override['mail_pagesize'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_mail_pagesize';
+ $input = new html_inputfield(array('name' => '_mail_pagesize', 'id' => $field_id, 'size' => 5));
+ $size = intval($config['mail_pagesize'] ? $config['mail_pagesize'] : $config['pagesize']);
+
+ $blocks['main']['options']['pagesize'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('pagesize'))),
+ 'content' => $input->show($size ? $size : 50),
+ );
+ }
+
+ if (!isset($no_override['check_all_folders'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_check_all_folders';
+ $input = new html_checkbox(array('name' => '_check_all_folders', 'id' => $field_id, 'value' => 1));
+
+ $blocks['new_message']['options']['check_all_folders'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('checkallfolders'))),
+ 'content' => $input->show($config['check_all_folders']?1:0),
+ );
+ }
+ break;
+
+ // Message viewing
+ case 'mailview':
+ $blocks = array(
+ 'main' => array('name' => Q(rcube_label('mainoptions'))),
+ );
+
+ // show checkbox to open message view in new window
+ if (!isset($no_override['message_extwin'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_message_extwin';
+ $input = new html_checkbox(array('name' => '_message_extwin', 'id' => $field_id, 'value' => 1));
+
+ $blocks['main']['options']['message_extwin'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('showinextwin'))),
+ 'content' => $input->show($config['message_extwin']?1:0),
+ );
+ }
+
+ // show checkbox to show email instead of name
+ if (!isset($no_override['message_show_email'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_message_show_email';
+ $input = new html_checkbox(array('name' => '_message_show_email', 'id' => $field_id, 'value' => 1));
+
+ $blocks['main']['options']['message_show_email'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('showemail'))),
+ 'content' => $input->show($config['message_show_email']?1:0),
+ );
+ }
+
+ // show checkbox for HTML/plaintext messages
+ if (!isset($no_override['prefer_html'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_htmlmsg';
+ $input = new html_checkbox(array('name' => '_prefer_html', 'id' => $field_id, 'value' => 1,
+ 'onchange' => "$('#rcmfd_show_images').prop('disabled', !this.checked).val(0)"));
+
+ $blocks['main']['options']['prefer_html'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('preferhtml'))),
+ 'content' => $input->show($config['prefer_html']?1:0),
+ );
+ }
+
+ if (!isset($no_override['default_charset'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_default_charset';
+
+ $blocks['main']['options']['default_charset'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('defaultcharset'))),
+ 'content' => $RCMAIL->output->charset_selector(array(
+ 'name' => '_default_charset', 'selected' => $config['default_charset']
+ )));
+ }
+
+ if (!isset($no_override['show_images'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_show_images';
+ $input = new html_select(array('name' => '_show_images', 'id' => $field_id,
+ 'disabled' => !$config['prefer_html']));
+
+ $input->add(rcube_label('never'), 0);
+ $input->add(rcube_label('fromknownsenders'), 1);
+ $input->add(rcube_label('always'), 2);
+
+ $blocks['main']['options']['show_images'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('showremoteimages'))),
+ 'content' => $input->show($config['prefer_html'] ? $config['show_images'] : 0),
+ );
+ }
+
+ if (!isset($no_override['inline_images'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_inline_images';
+ $input = new html_checkbox(array('name' => '_inline_images', 'id' => $field_id, 'value' => 1));
+
+ $blocks['main']['options']['inline_images'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('showinlineimages'))),
+ 'content' => $input->show($config['inline_images']?1:0),
+ );
+ }
+
+ // "display after delete" checkbox
+ if (!isset($no_override['display_next'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_displaynext';
+ $input = new html_checkbox(array('name' => '_display_next', 'id' => $field_id, 'value' => 1));
+
+ $blocks['main']['options']['display_next'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('displaynext'))),
+ 'content' => $input->show($config['display_next']?1:0),
+ );
+ }
+ break;
+
+ // Mail composition
+ case 'compose':
+ $blocks = array(
+ 'main' => array('name' => Q(rcube_label('mainoptions'))),
+ 'sig' => array('name' => Q(rcube_label('signatureoptions'))),
+ 'spellcheck' => array('name' => Q(rcube_label('spellcheckoptions'))),
+ );
+
+ // show checkbox to compose messages in a new window
+ if (!isset($no_override['compose_extwin'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfdcompose_extwin';
+ $input = new html_checkbox(array('name' => '_compose_extwin', 'id' => $field_id, 'value' => 1));
+
+ $blocks['main']['options']['compose_extwin'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('composeextwin'))),
+ 'content' => $input->show($config['compose_extwin']?1:0),
+ );
+ }
+
+ if (!isset($no_override['htmleditor'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_htmleditor';
+ $select = new html_select(array('name' => '_htmleditor', 'id' => $field_id));
+
+ $select->add(rcube_label('never'), 0);
+ $select->add(rcube_label('always'), 1);
+ $select->add(rcube_label('htmlonreply'), 2);
+ $select->add(rcube_label('htmlonreplyandforward'), 3);
+
+ $blocks['main']['options']['htmleditor'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('htmleditor'))),
+ 'content' => $select->show(intval($config['htmleditor'])),
+ );
+ }
+
+ if (!isset($no_override['draft_autosave'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_autosave';
+ $select = new html_select(array('name' => '_draft_autosave', 'id' => $field_id, 'disabled' => empty($config['drafts_mbox'])));
+
+ $select->add(rcube_label('never'), 0);
+ foreach (array(1, 3, 5, 10) as $i => $min) {
+ $label = rcube_label(array('name' => 'everynminutes', 'vars' => array('n' => $min)));
+ $select->add($label, $min*60);
+ }
+
+ $blocks['main']['options']['draft_autosave'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('autosavedraft'))),
+ 'content' => $select->show($config['draft_autosave']),
+ );
+ }
+
+ if (!isset($no_override['mime_param_folding'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_param_folding';
+ $select = new html_select(array('name' => '_mime_param_folding', 'id' => $field_id));
+
+ $select->add(rcube_label('2231folding'), 0);
+ $select->add(rcube_label('miscfolding'), 1);
+ $select->add(rcube_label('2047folding'), 2);
+
+ $blocks['main']['options']['mime_param_folding'] = array(
+ 'advanced' => true,
+ 'title' => html::label($field_id, Q(rcube_label('mimeparamfolding'))),
+ 'content' => $select->show($config['mime_param_folding']),
+ );
+ }
+
+ if (!isset($no_override['force_7bit'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_force_7bit';
+ $input = new html_checkbox(array('name' => '_force_7bit', 'id' => $field_id, 'value' => 1));
+
+ $blocks['main']['options']['force_7bit'] = array(
+ 'advanced' => true,
+ 'title' => html::label($field_id, Q(rcube_label('force7bit'))),
+ 'content' => $input->show($config['force_7bit']?1:0),
+ );
+ }
+
+ if (!isset($no_override['mdn_default'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_mdn_default';
+ $input = new html_checkbox(array('name' => '_mdn_default', 'id' => $field_id, 'value' => 1));
+
+ $blocks['main']['options']['mdn_default'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('reqmdn'))),
+ 'content' => $input->show($config['mdn_default']?1:0),
+ );
+ }
+
+ if (!isset($no_override['dsn_default'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_dsn_default';
+ $input = new html_checkbox(array('name' => '_dsn_default', 'id' => $field_id, 'value' => 1));
+
+ $blocks['main']['options']['dsn_default'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('reqdsn'))),
+ 'content' => $input->show($config['dsn_default']?1:0),
+ );
+ }
+
+ if (!isset($no_override['reply_same_folder'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_reply_same_folder';
+ $input = new html_checkbox(array('name' => '_reply_same_folder', 'id' => $field_id, 'value' => 1));
+
+ $blocks['main']['options']['reply_same_folder'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('replysamefolder'))),
+ 'content' => $input->show($config['reply_same_folder']?1:0),
+ );
+ }
+
+ if (!isset($no_override['reply_mode'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_reply_mode';
+ $select = new html_select(array('name' => '_reply_mode', 'id' => $field_id));
+
+ $select->add(rcube_label('replyempty'), -1);
+ $select->add(rcube_label('replybottomposting'), 0);
+ $select->add(rcube_label('replytopposting'), 1);
+
+ $blocks['main']['options']['reply_mode'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('whenreplying'))),
+ 'content' => $select->show(intval($config['reply_mode'])),
+ );
+ }
+
+ if (!isset($no_override['spellcheck_before_send']) && $config['enable_spellcheck']) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_spellcheck_before_send';
+ $input = new html_checkbox(array('name' => '_spellcheck_before_send', 'id' => $field_id, 'value' => 1));
+
+ $blocks['spellcheck']['options']['spellcheck_before_send'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('spellcheckbeforesend'))),
+ 'content' => $input->show($config['spellcheck_before_send']?1:0),
+ );
+ }
+
+ if ($config['enable_spellcheck']) {
+ if (!$current) {
+ continue 2;
+ }
+
+ foreach (array('syms', 'nums', 'caps') as $key) {
+ $key = 'spellcheck_ignore_'.$key;
+ if (!isset($no_override[$key])) {
+ $input = 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->show($config[$key]?1:0),
+ );
+ }
+ }
+ }
+
+ if (!isset($no_override['show_sig'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_show_sig';
+ $select = new html_select(array('name' => '_show_sig', 'id' => $field_id));
+
+ $select->add(rcube_label('never'), 0);
+ $select->add(rcube_label('always'), 1);
+ $select->add(rcube_label('newmessageonly'), 2);
+ $select->add(rcube_label('replyandforwardonly'), 3);
+
+ $blocks['sig']['options']['show_sig'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('autoaddsignature'))),
+ 'content' => $select->show($RCMAIL->config->get('show_sig', 1)),
+ );
+ }
+
+ if (!isset($no_override['strip_existing_sig'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_strip_existing_sig';
+ $input = new html_checkbox(array('name' => '_strip_existing_sig', 'id' => $field_id, 'value' => 1));
+
+ $blocks['sig']['options']['strip_existing_sig'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('replyremovesignature'))),
+ 'content' => $input->show($config['strip_existing_sig']?1:0),
+ );
+ }
+
+ if (!isset($no_override['forward_attachment'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_forward_attachment';
+ $select = new html_select(array('name' => '_forward_attachment', 'id' => $field_id));
+
+ $select->add(rcube_label('inline'), 0);
+ $select->add(rcube_label('asattachment'), 1);
+
+ $blocks['main']['options']['forward_attachment'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('forwardmode'))),
+ 'content' => $select->show(intval($config['forward_attachment'])),
+ );
+ }
+
+ if (!isset($no_override['default_font'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_default_font';
+ $fonts = rcube_fontdefs();
+ $selected = $config['default_font'];
+
+ $select = '<select name="_default_font" id="'.$field_id.'">';
+ $select .= '<option value=""' . (!$selected ? ' selected="selected"' : '') . '>---</option>';
+ foreach ($fonts as $fname => $font) {
+ $select .= '<option value="'.$fname.'"'
+ . ($fname == $selected ? ' selected="selected"' : '')
+ . ' style=\'font-family: ' . $font . '\'>'
+ . Q($fname) . '</option>';
+ }
+ $select .= '</select>';
+
+ $blocks['main']['options']['default_font'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('defaultfont'))),
+ 'content' => $select
+ );
+ }
+ break;
+
+ // Addressbook config
+ case 'addressbook':
+ $blocks = array(
+ 'main' => array('name' => Q(rcube_label('mainoptions'))),
+ );
+
+ if (!isset($no_override['default_addressbook'])
+ && (!$current || ($books = $RCMAIL->get_address_sources(true, true)))
+ ) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_default_addressbook';
+ $select = new html_select(array('name' => '_default_addressbook', 'id' => $field_id));
+
+ foreach ($books as $book) {
+ $select->add(html_entity_decode($book['name'], ENT_COMPAT, 'UTF-8'), $book['id']);
+ }
+
+ $blocks['main']['options']['default_addressbook'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('defaultabook'))),
+ 'content' => $select->show($config['default_addressbook']),
+ );
+ }
+
+ // show addressbook listing mode selection
+ if (!isset($no_override['addressbook_name_listing'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_addressbook_name_listing';
+ $select = new html_select(array('name' => '_addressbook_name_listing', 'id' => $field_id));
+
+ $select->add(rcube_label('name'), 0);
+ $select->add(rcube_label('firstname') . ' ' . rcube_label('surname'), 1);
+ $select->add(rcube_label('surname') . ' ' . rcube_label('firstname'), 2);
+ $select->add(rcube_label('surname') . ', ' . rcube_label('firstname'), 3);
+
+ $blocks['main']['options']['list_name_listing'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('listnamedisplay'))),
+ 'content' => $select->show($config['addressbook_name_listing']),
+ );
+ }
+
+ // show addressbook sort column
+ if (!isset($no_override['addressbook_sort_col'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_addressbook_sort_col';
+ $select = new html_select(array('name' => '_addressbook_sort_col', 'id' => $field_id));
+
+ $select->add(rcube_label('name'), 'name');
+ $select->add(rcube_label('firstname'), 'firstname');
+ $select->add(rcube_label('surname'), 'surname');
+
+ $blocks['main']['options']['sort_col'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('listsorting'))),
+ 'content' => $select->show($config['addressbook_sort_col']),
+ );
+ }
+
+ // show addressbook page size selection
+ if (!isset($no_override['addressbook_pagesize'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_addressbook_pagesize';
+ $input = new html_inputfield(array('name' => '_addressbook_pagesize', 'id' => $field_id, 'size' => 5));
+ $size = intval($config['addressbook_pagesize'] ? $config['addressbook_pagesize'] : $config['pagesize']);
+
+ $blocks['main']['options']['pagesize'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('pagesize'))),
+ 'content' => $input->show($size ? $size : 50),
+ );
+ }
+
+ if (!isset($no_override['autocomplete_single'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $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
+ case 'folders':
+ $blocks = array(
+ 'main' => array('name' => Q(rcube_label('mainoptions'))),
+ );
+
+ if (!isset($no_override['show_real_foldernames'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'show_real_foldernames';
+ $input = new html_checkbox(array('name' => '_show_real_foldernames', 'id' => $field_id, 'value' => 1));
+
+ $blocks['main']['options']['show_real_foldernames'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('show_real_foldernames'))),
+ 'content' => $input->show($config['show_real_foldernames']?1:0),
+ );
+ }
+
+ // Configure special folders
+ if (!isset($no_override['default_folders']) && $current) {
+ $select = rcmail_mailbox_select(array(
+ 'noselection' => '---',
+ 'realnames' => true,
+ 'maxlength' => 30,
+ 'folder_filter' => 'mail',
+ 'folder_rights' => 'w',
+ // #1486114, #1488279
+ 'onchange' => "if ($(this).val() == 'INBOX') $(this).val('')",
+ ));
+ }
+
+ if (!isset($no_override['drafts_mbox'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $blocks['main']['options']['drafts_mbox'] = array(
+ 'title' => Q(rcube_label('drafts')),
+ 'content' => $select->show($config['drafts_mbox'], array('name' => "_drafts_mbox")),
+ );
+ }
+
+ if (!isset($no_override['sent_mbox'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $blocks['main']['options']['sent_mbox'] = array(
+ 'title' => Q(rcube_label('sent')),
+ 'content' => $select->show($config['sent_mbox'], array('name' => "_sent_mbox")),
+ );
+ }
+
+ if (!isset($no_override['junk_mbox'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $blocks['main']['options']['junk_mbox'] = array(
+ 'title' => Q(rcube_label('junk')),
+ 'content' => $select->show($config['junk_mbox'], array('name' => "_junk_mbox")),
+ );
+ }
+
+ if (!isset($no_override['trash_mbox'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $blocks['main']['options']['trash_mbox'] = array(
+ 'title' => Q(rcube_label('trash')),
+ 'content' => $select->show($config['trash_mbox'], array('name' => "_trash_mbox")),
+ );
+ }
+ break;
+
+ // Server settings
+ case 'server':
+ $blocks = array(
+ 'main' => array('name' => Q(rcube_label('mainoptions'))),
+ 'maintenance' => array('name' => Q(rcube_label('maintenance'))),
+ );
+
+ if (!isset($no_override['read_when_deleted'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_read_deleted';
+ $input = new html_checkbox(array('name' => '_read_when_deleted', 'id' => $field_id, 'value' => 1));
+
+ $blocks['main']['options']['read_when_deleted'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('readwhendeleted'))),
+ 'content' => $input->show($config['read_when_deleted']?1:0),
+ );
+ }
+
+ if (!isset($no_override['flag_for_deletion'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_flag_for_deletion';
+ $input = new html_checkbox(array('name' => '_flag_for_deletion', 'id' => $field_id, 'value' => 1));
+
+ $blocks['main']['options']['flag_for_deletion'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('flagfordeletion'))),
+ 'content' => $input->show($config['flag_for_deletion']?1:0),
+ );
+ }
+
+ // don't show deleted messages
+ if (!isset($no_override['skip_deleted'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_skip_deleted';
+ $input = new html_checkbox(array('name' => '_skip_deleted', 'id' => $field_id, 'value' => 1));
+
+ $blocks['main']['options']['skip_deleted'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('skipdeleted'))),
+ 'content' => $input->show($config['skip_deleted']?1:0),
+ );
+ }
+
+ if (!isset($no_override['delete_always'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_delete_always';
+ $input = new html_checkbox(array('name' => '_delete_always', 'id' => $field_id, 'value' => 1));
+
+ $blocks['main']['options']['delete_always'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('deletealways'))),
+ 'content' => $input->show($config['delete_always']?1:0),
+ );
+ }
+
+ if (!isset($no_override['delete_junk'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_delete_junk';
+ $input = new html_checkbox(array('name' => '_delete_junk', 'id' => $field_id, 'value' => 1));
+
+ $blocks['main']['options']['delete_junk'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('deletejunk'))),
+ 'content' => $input->show($config['delete_junk']?1:0),
+ );
+ }
+
+ // Trash purging on logout
+ if (!isset($no_override['logout_purge'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_logout_purge';
+ $input = new html_checkbox(array('name' => '_logout_purge', 'id' => $field_id, 'value' => 1));
+
+ $blocks['maintenance']['options']['logout_purge'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('logoutclear'))),
+ 'content' => $input->show($config['logout_purge']?1:0),
+ );
+ }
+
+ // INBOX compacting on logout
+ if (!isset($no_override['logout_expunge'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_logout_expunge';
+ $input = new html_checkbox(array('name' => '_logout_expunge', 'id' => $field_id, 'value' => 1));
+
+ $blocks['maintenance']['options']['logout_expunge'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('logoutcompact'))),
+ 'content' => $input->show($config['logout_expunge']?1:0),
+ );
+ }
}
- }
- }
-
- $product_name = $RCMAIL->config->get('product_name', 'Roundcube Webmail');
- $RCMAIL->output->add_script(sprintf("%s.check_protocol_handler('%s', '#mailtoprotohandler');",
- JS_OBJECT_NAME, JQ($product_name)), 'foot');
-
- $blocks['browser'] = array(
- 'name' => Q(rcube_label('browseroptions')),
- 'options' => array('mailtoprotohandler' => array(
- 'content' => html::a(array(
- 'href' => '#',
- 'id' => 'mailtoprotohandler'), Q(rcube_label('mailtoprotohandler'))),
- )),
- );
-
- break;
-
- // Mailbox view (mail screen)
- case 'mailbox':
-
- $blocks = array(
- 'main' => array('name' => Q(rcube_label('mainoptions'))),
- 'new_message' => array('name' => Q(rcube_label('newmessage'))),
- );
-
- // show config parameter for preview pane
- if (!isset($no_override['preview_pane'])) {
- $field_id = 'rcmfd_preview';
- $input_preview = new html_checkbox(array('name' => '_preview_pane', 'id' => $field_id, 'value' => 1,
- 'onchange' => "$('#rcmfd_preview_pane_mark_read').prop('disabled', !this.checked)"));
-
- $blocks['main']['options']['preview_pane'] = array(
- 'title' => html::label($field_id, Q(rcube_label('previewpane'))),
- 'content' => $input_preview->show($config['preview_pane']?1:0),
- );
- }
-
- // show config parameter for preview pane auto mark as read delay
- if (!isset($no_override['preview_pane_mark_read'])) {
- // apply default if config option is not set at all
- $config['preview_pane_mark_read'] = $RCMAIL->config->get('preview_pane_mark_read', 0);
-
- $field_id = 'rcmfd_preview_pane_mark_read';
- $select_delay = new html_select(array('name' => '_preview_pane_mark_read', 'id' => $field_id,
- 'disabled' => $config['preview_pane']?0:1));
-
- $select_delay->add(rcube_label('never'), '-1');
- $select_delay->add(rcube_label('immediately'), 0);
- foreach(array(5, 10, 20, 30) as $sec)
- $select_delay->add(rcube_label(array('name' => 'afternseconds', 'vars' => array('n' => $sec))), $sec);
-
- $blocks['main']['options']['preview_pane_mark_read'] = array(
- 'title' => html::label($field_id, Q(rcube_label('previewpanemarkread'))),
- 'content' => $select_delay->show(intval($config['preview_pane_mark_read'])),
- );
- }
-
- if (!isset($no_override['mdn_requests'])) {
- $field_id = 'rcmfd_mdn_requests';
- $select_mdn_requests = new html_select(array('name' => '_mdn_requests', 'id' => $field_id));
- $select_mdn_requests->add(rcube_label('askuser'), 0);
- $select_mdn_requests->add(rcube_label('autosend'), 1);
- $select_mdn_requests->add(rcube_label('autosendknown'), 3);
- $select_mdn_requests->add(rcube_label('autosendknownignore'), 4);
- $select_mdn_requests->add(rcube_label('ignore'), 2);
-
- $blocks['main']['options']['mdn_requests'] = array(
- 'title' => html::label($field_id, Q(rcube_label('mdnrequests'))),
- 'content' => $select_mdn_requests->show($config['mdn_requests']),
- );
- }
-
- $storage = $RCMAIL->get_storage();
- $threading_supported = $storage->get_capability('THREAD');
-
- if (!isset($no_override['autoexpand_threads']) && $threading_supported) {
- $field_id = 'rcmfd_autoexpand_threads';
- $select_autoexpand_threads = new html_select(array('name' => '_autoexpand_threads', 'id' => $field_id));
- $select_autoexpand_threads->add(rcube_label('never'), 0);
- $select_autoexpand_threads->add(rcube_label('do_expand'), 1);
- $select_autoexpand_threads->add(rcube_label('expand_only_unread'), 2);
-
- $blocks['main']['options']['autoexpand_threads'] = array(
- 'title' => html::label($field_id, Q(rcube_label('autoexpand_threads'))),
- 'content' => $select_autoexpand_threads->show($config['autoexpand_threads']),
- );
- }
-
- // show page size selection
- if (!isset($no_override['mail_pagesize'])) {
- $field_id = 'rcmfd_mail_pagesize';
- $input_pagesize = new html_inputfield(array('name' => '_mail_pagesize', 'id' => $field_id, 'size' => 5));
-
- $size = intval($config['mail_pagesize'] ? $config['mail_pagesize'] : $config['pagesize']);
-
- $blocks['main']['options']['pagesize'] = array(
- 'title' => html::label($field_id, Q(rcube_label('pagesize'))),
- 'content' => $input_pagesize->show($size ? $size : 50),
- );
- }
- if (!isset($no_override['check_all_folders'])) {
- $field_id = 'rcmfd_check_all_folders';
- $input_check_all = new html_checkbox(array('name' => '_check_all_folders', 'id' => $field_id, 'value' => 1));
-
- $blocks['new_message']['options']['check_all_folders'] = array(
- 'title' => html::label($field_id, Q(rcube_label('checkallfolders'))),
- 'content' => $input_check_all->show($config['check_all_folders']?1:0),
- );
- }
-
- break;
-
- // Message viewing
- case 'mailview':
-
- $blocks = array(
- 'main' => array('name' => Q(rcube_label('mainoptions'))),
- );
-
- // show checkbox to open message view in new window
- if (!isset($no_override['message_extwin'])) {
- $field_id = 'rcmfd_message_extwin';
- $input_msgextwin = new html_checkbox(array('name' => '_message_extwin', 'id' => $field_id, 'value' => 1));
-
- $blocks['main']['options']['message_extwin'] = array(
- 'title' => html::label($field_id, Q(rcube_label('showinextwin'))),
- 'content' => $input_msgextwin->show($config['message_extwin']?1:0),
- );
- }
-
- // show checkbox to show email instead of name
- if (!isset($no_override['message_show_email'])) {
- $field_id = 'rcmfd_message_show_email';
- $input_msgshowemail = new html_checkbox(array('name' => '_message_show_email', 'id' => $field_id, 'value' => 1));
-
- $blocks['main']['options']['message_show_email'] = array(
- 'title' => html::label($field_id, Q(rcube_label('showemail'))),
- 'content' => $input_msgshowemail->show($config['message_show_email']?1:0),
- );
- }
-
- // show checkbox for HTML/plaintext messages
- if (!isset($no_override['prefer_html'])) {
- $field_id = 'rcmfd_htmlmsg';
- $input_preferhtml = new html_checkbox(array('name' => '_prefer_html', 'id' => $field_id, 'value' => 1,
- 'onchange' => "$('#rcmfd_show_images').prop('disabled', !this.checked).val(0)"));
-
- $blocks['main']['options']['prefer_html'] = array(
- 'title' => html::label($field_id, Q(rcube_label('preferhtml'))),
- 'content' => $input_preferhtml->show($config['prefer_html']?1:0),
- );
- }
-
- if (!isset($no_override['default_charset'])) {
- $field_id = 'rcmfd_default_charset';
-
- $blocks['main']['options']['default_charset'] = array(
- 'title' => html::label($field_id, Q(rcube_label('defaultcharset'))),
- 'content' => $RCMAIL->output->charset_selector(array(
- 'name' => '_default_charset', 'selected' => $config['default_charset']
- ))
- );
- }
-
- if (!isset($no_override['show_images'])) {
- $field_id = 'rcmfd_show_images';
- $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'))),
- 'content' => $input_show_images->show($config['prefer_html'] ? $config['show_images'] : 0),
- );
- }
-
- if (!isset($no_override['inline_images'])) {
- $field_id = 'rcmfd_inline_images';
- $input_inline_images = new html_checkbox(array('name' => '_inline_images', 'id' => $field_id, 'value' => 1));
-
- $blocks['main']['options']['inline_images'] = array(
- 'title' => html::label($field_id, Q(rcube_label('showinlineimages'))),
- 'content' => $input_inline_images->show($config['inline_images']?1:0),
- );
- }
-
- // "display after delete" checkbox
- if (!isset($no_override['display_next'])) {
- $field_id = 'rcmfd_displaynext';
- $input_displaynext = new html_checkbox(array('name' => '_display_next', 'id' => $field_id, 'value' => 1));
-
- $blocks['main']['options']['display_next'] = array(
- 'title' => html::label($field_id, Q(rcube_label('displaynext'))),
- 'content' => $input_displaynext->show($config['display_next']?1:0),
- );
- }
-
- break;
-
- // Mail composition
- case 'compose':
-
- $blocks = array(
- 'main' => array('name' => Q(rcube_label('mainoptions'))),
- 'sig' => array('name' => Q(rcube_label('signatureoptions'))),
- 'spellcheck' => array('name' => Q(rcube_label('spellcheckoptions'))),
- );
-
- // show checkbox to compose messages in a new window
- if (!isset($no_override['compose_extwin'])) {
- $field_id = 'rcmfdcompose_extwin';
- $input_compextwin = new html_checkbox(array('name' => '_compose_extwin', 'id' => $field_id, 'value' => 1));
-
- $blocks['main']['options']['compose_extwin'] = array(
- 'title' => html::label($field_id, Q(rcube_label('composeextwin'))),
- 'content' => $input_compextwin->show($config['compose_extwin']?1:0),
- );
- }
-
- if (!isset($no_override['htmleditor'])) {
- $field_id = 'rcmfd_htmleditor';
- $select_htmleditor = new html_select(array('name' => '_htmleditor', 'id' => $field_id));
- $select_htmleditor->add(rcube_label('never'), 0);
- $select_htmleditor->add(rcube_label('always'), 1);
- $select_htmleditor->add(rcube_label('htmlonreply'), 2);
- $select_htmleditor->add(rcube_label('htmlonreplyandforward'), 3);
-
- $blocks['main']['options']['htmleditor'] = array(
- 'title' => html::label($field_id, Q(rcube_label('htmleditor'))),
- 'content' => $select_htmleditor->show(intval($config['htmleditor'])),
- );
- }
-
- if (!isset($no_override['draft_autosave'])) {
- $field_id = 'rcmfd_autosave';
- $select_autosave = new html_select(array('name' => '_draft_autosave', 'id' => $field_id, 'disabled' => empty($config['drafts_mbox'])));
- $select_autosave->add(rcube_label('never'), 0);
- foreach (array(1, 3, 5, 10) as $i => $min)
- $select_autosave->add(rcube_label(array('name' => 'everynminutes', 'vars' => array('n' => $min))), $min*60);
-
- $blocks['main']['options']['draft_autosave'] = array(
- 'title' => html::label($field_id, Q(rcube_label('autosavedraft'))),
- 'content' => $select_autosave->show($config['draft_autosave']),
- );
- }
-
- if (!isset($no_override['mime_param_folding'])) {
- $field_id = 'rcmfd_param_folding';
- $select_param_folding = new html_select(array('name' => '_mime_param_folding', 'id' => $field_id));
- $select_param_folding->add(rcube_label('2231folding'), 0);
- $select_param_folding->add(rcube_label('miscfolding'), 1);
- $select_param_folding->add(rcube_label('2047folding'), 2);
-
- $blocks['main']['options']['mime_param_folding'] = array(
- 'advanced' => true,
- 'title' => html::label($field_id, Q(rcube_label('mimeparamfolding'))),
- 'content' => $select_param_folding->show($config['mime_param_folding']),
- );
- }
-
- if (!isset($no_override['force_7bit'])) {
- $field_id = 'rcmfd_force_7bit';
- $input_7bit = new html_checkbox(array('name' => '_force_7bit', 'id' => $field_id, 'value' => 1));
-
- $blocks['main']['options']['force_7bit'] = array(
- 'title' => html::label($field_id, Q(rcube_label('force7bit'))),
- 'content' => $input_7bit->show($config['force_7bit']?1:0),
- );
- }
-
- if (!isset($no_override['mdn_default'])) {
- $field_id = 'rcmfd_mdn_default';
- $input_mdn = new html_checkbox(array('name' => '_mdn_default', 'id' => $field_id, 'value' => 1));
-
- $blocks['main']['options']['mdn_default'] = array(
- 'title' => html::label($field_id, Q(rcube_label('reqmdn'))),
- 'content' => $input_mdn->show($config['mdn_default']?1:0),
- );
- }
-
- if (!isset($no_override['dsn_default'])) {
- $field_id = 'rcmfd_dsn_default';
- $input_dsn = new html_checkbox(array('name' => '_dsn_default', 'id' => $field_id, 'value' => 1));
-
- $blocks['main']['options']['dsn_default'] = array(
- 'title' => html::label($field_id, Q(rcube_label('reqdsn'))),
- 'content' => $input_dsn->show($config['dsn_default']?1:0),
- );
- }
-
- if (!isset($no_override['reply_same_folder'])) {
- $field_id = 'rcmfd_reply_same_folder';
- $input_reply_same_folder = new html_checkbox(array('name' => '_reply_same_folder', 'id' => $field_id, 'value' => 1));
-
- $blocks['main']['options']['reply_same_folder'] = array(
- 'title' => html::label($field_id, Q(rcube_label('replysamefolder'))),
- 'content' => $input_reply_same_folder->show($config['reply_same_folder']?1:0),
- );
- }
-
- if (!isset($no_override['reply_mode'])) {
- $field_id = 'rcmfd_reply_mode';
- $select_replymode = new html_select(array('name' => '_reply_mode', 'id' => $field_id));
- $select_replymode->add(rcube_label('replyempty'), -1);
- $select_replymode->add(rcube_label('replybottomposting'), 0);
- $select_replymode->add(rcube_label('replytopposting'), 1);
-
- $blocks['main']['options']['reply_mode'] = array(
- 'title' => html::label($field_id, Q(rcube_label('whenreplying'))),
- 'content' => $select_replymode->show(intval($config['reply_mode'])),
- );
- }
- if (!isset($no_override['spellcheck_before_send']) && $config['enable_spellcheck']) {
- $field_id = 'rcmfd_spellcheck_before_send';
- $input_spellcheck = new html_checkbox(array('name' => '_spellcheck_before_send', 'id' => $field_id, 'value' => 1));
+ $found = false;
+ $data = $RCMAIL->plugins->exec_hook('preferences_list',
+ array('section' => $sect['id'], 'blocks' => $blocks, 'current' => $current));
- $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),
- );
- }
-
- 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),
- );
+ // create output
+ foreach ($data['blocks'] as $block) {
+ if (!empty($block['content']) || !empty($block['options'])) {
+ $found = true;
+ break;
+ }
}
- }
- }
- if (!isset($no_override['show_sig'])) {
- $field_id = 'rcmfd_show_sig';
- $select_show_sig = new html_select(array('name' => '_show_sig', 'id' => $field_id));
- $select_show_sig->add(rcube_label('never'), 0);
- $select_show_sig->add(rcube_label('always'), 1);
- $select_show_sig->add(rcube_label('newmessageonly'), 2);
- $select_show_sig->add(rcube_label('replyandforwardonly'), 3);
-
- $blocks['sig']['options']['show_sig'] = array(
- 'title' => html::label($field_id, Q(rcube_label('autoaddsignature'))),
- 'content' => $select_show_sig->show($RCMAIL->config->get('show_sig', 1)),
- );
+ if (!$found)
+ unset($sections[$idx]);
+ else
+ $sections[$idx]['blocks'] = $data['blocks'];
}
- if (!isset($no_override['strip_existing_sig'])) {
- $field_id = 'rcmfd_strip_existing_sig';
- $input_stripexistingsig = new html_checkbox(array('name' => '_strip_existing_sig', 'id' => $field_id, 'value' => 1));
-
- $blocks['sig']['options']['strip_existing_sig'] = array(
- 'title' => html::label($field_id, Q(rcube_label('replyremovesignature'))),
- 'content' => $input_stripexistingsig->show($config['strip_existing_sig']?1:0),
- );
- }
-
- if (!isset($no_override['forward_attachment'])) {
- $field_id = 'rcmfd_forward_attachment';
- $select = new html_select(array('name' => '_forward_attachment', 'id' => $field_id));
- $select->add(rcube_label('inline'), 0);
- $select->add(rcube_label('asattachment'), 1);
-
- $blocks['main']['options']['forward_attachment'] = array(
- 'title' => html::label($field_id, Q(rcube_label('forwardmode'))),
- 'content' => $select->show(intval($config['forward_attachment'])),
- );
- }
-
- if (!isset($no_override['default_font'])) {
- $field_id = 'rcmfd_default_font';
- $fonts = rcube_fontdefs();
- $selected = $config['default_font'];
-
- $select = '<select name="_default_font" id="'.$field_id.'">';
- $select .= '<option value=""' . (!$selected ? ' selected="selected"' : '') . '>---</option>';
- foreach ($fonts as $fname => $font)
- $select .= '<option value="'.$fname.'"'
- . ($fname == $selected ? ' selected="selected"' : '')
- . ' style=\'font-family: ' . $font . '\'>'
- . Q($fname) . '</option>';
- $select .= '</select>';
-
- $blocks['main']['options']['default_font'] = array(
- 'title' => html::label($field_id, Q(rcube_label('defaultfont'))),
- 'content' => $select
- );
- }
-
- break;
-
-
- // Addressbook config
- case 'addressbook':
-
- $blocks = array(
- 'main' => array('name' => Q(rcube_label('mainoptions'))),
- );
-
- if (!isset($no_override['default_addressbook'])
- && ($books = $RCMAIL->get_address_sources(true, true))
- ) {
- $field_id = 'rcmfd_default_addressbook';
- $select_abook = new html_select(array('name' => '_default_addressbook', 'id' => $field_id));
-
- foreach ($books as $book) {
- $select_abook->add(html_entity_decode($book['name'], ENT_COMPAT, 'UTF-8'), $book['id']);
- }
-
- $blocks['main']['options']['default_addressbook'] = array(
- 'title' => html::label($field_id, Q(rcube_label('defaultabook'))),
- 'content' => $select_abook->show($config['default_addressbook']),
- );
- }
-
- // show addressbook listing mode selection
- if (!isset($no_override['addressbook_name_listing'])) {
- $field_id = 'rcmfd_addressbook_name_listing';
- $select_listing = new html_select(array('name' => '_addressbook_name_listing', 'id' => $field_id));
- $select_listing->add(rcube_label('name'), 0);
- $select_listing->add(rcube_label('firstname') . ' ' . rcube_label('surname'), 1);
- $select_listing->add(rcube_label('surname') . ' ' . rcube_label('firstname'), 2);
- $select_listing->add(rcube_label('surname') . ', ' . rcube_label('firstname'), 3);
-
- $blocks['main']['options']['list_name_listing'] = array(
- 'title' => html::label($field_id, Q(rcube_label('listnamedisplay'))),
- 'content' => $select_listing->show($config['addressbook_name_listing']),
- );
- }
-
- // show addressbook sort column
- if (!isset($no_override['addressbook_sort_col'])) {
- $field_id = 'rcmfd_addressbook_sort_col';
- $select_sort = new html_select(array('name' => '_addressbook_sort_col', 'id' => $field_id));
- $select_sort->add(rcube_label('name'), 'name');
- $select_sort->add(rcube_label('firstname'), 'firstname');
- $select_sort->add(rcube_label('surname'), 'surname');
-
- $blocks['main']['options']['sort_col'] = array(
- 'title' => html::label($field_id, Q(rcube_label('listsorting'))),
- 'content' => $select_sort->show($config['addressbook_sort_col']),
- );
- }
-
- // show addressbook page size selection
- if (!isset($no_override['addressbook_pagesize'])) {
- $field_id = 'rcmfd_addressbook_pagesize';
- $input_pagesize = new html_inputfield(array('name' => '_addressbook_pagesize', 'id' => $field_id, 'size' => 5));
-
- $size = intval($config['addressbook_pagesize'] ? $config['addressbook_pagesize'] : $config['pagesize']);
-
- $blocks['main']['options']['pagesize'] = array(
- 'title' => html::label($field_id, Q(rcube_label('pagesize'))),
- 'content' => $input_pagesize->show($size ? $size : 50),
- );
- }
-
- 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
- case 'folders':
-
- $blocks = array(
- 'main' => array('name' => Q(rcube_label('mainoptions'))),
- );
-
- // Configure special folders
- if (!isset($no_override['default_folders'])) {
- // load folders list only when needed
- if ($current) {
- $select = rcmail_mailbox_select(array(
- 'noselection' => '---',
- 'realnames' => true,
- 'maxlength' => 30,
- 'folder_filter' => 'mail',
- 'folder_rights' => 'w',
- // #1486114, #1488279
- 'onchange' => "if ($(this).val() == 'INBOX') $(this).val('')",
- ));
- }
- else // dummy select
- $select = new html_select();
-
- if (!isset($no_override['drafts_mbox']))
- $blocks['main']['options']['drafts_mbox'] = array(
- 'title' => Q(rcube_label('drafts')),
- 'content' => $select->show($config['drafts_mbox'], array('name' => "_drafts_mbox")),
- );
-
- if (!isset($no_override['sent_mbox']))
- $blocks['main']['options']['sent_mbox'] = array(
- 'title' => Q(rcube_label('sent')),
- 'content' => $select->show($config['sent_mbox'], array('name' => "_sent_mbox")),
- );
-
- if (!isset($no_override['junk_mbox']))
- $blocks['main']['options']['junk_mbox'] = array(
- 'title' => Q(rcube_label('junk')),
- 'content' => $select->show($config['junk_mbox'], array('name' => "_junk_mbox")),
- );
-
- if (!isset($no_override['trash_mbox']))
- $blocks['main']['options']['trash_mbox'] = array(
- 'title' => Q(rcube_label('trash')),
- 'content' => $select->show($config['trash_mbox'], array('name' => "_trash_mbox")),
- );
- }
-
- break;
-
- // Server settings
- case 'server':
-
- $blocks = array(
- 'main' => array('name' => Q(rcube_label('mainoptions'))),
- 'maintenance' => array('name' => Q(rcube_label('maintenance'))),
- );
-
- if (!isset($no_override['read_when_deleted'])) {
- $field_id = 'rcmfd_read_deleted';
- $input_readdeleted = new html_checkbox(array('name' => '_read_when_deleted', 'id' => $field_id, 'value' => 1));
-
- $blocks['main']['options']['read_when_deleted'] = array(
- 'title' => html::label($field_id, Q(rcube_label('readwhendeleted'))),
- 'content' => $input_readdeleted->show($config['read_when_deleted']?1:0),
- );
- }
-
- if (!isset($no_override['flag_for_deletion'])) {
- $field_id = 'rcmfd_flag_for_deletion';
- $input_flagfordeletion = new html_checkbox(array('name' => '_flag_for_deletion', 'id' => $field_id, 'value' => 1));
-
- $blocks['main']['options']['flag_for_deletion'] = array(
- 'title' => html::label($field_id, Q(rcube_label('flagfordeletion'))),
- 'content' => $input_flagfordeletion->show($config['flag_for_deletion']?1:0),
- );
- }
-
- // don't show deleted messages
- if (!isset($no_override['skip_deleted'])) {
- $field_id = 'rcmfd_skip_deleted';
- $input_purge = new html_checkbox(array('name' => '_skip_deleted', 'id' => $field_id, 'value' => 1));
-
- $blocks['main']['options']['skip_deleted'] = array(
- 'title' => html::label($field_id, Q(rcube_label('skipdeleted'))),
- 'content' => $input_purge->show($config['skip_deleted']?1:0),
- );
- }
-
- if (!isset($no_override['delete_always'])) {
- $field_id = 'rcmfd_delete_always';
- $input_delete_always = new html_checkbox(array('name' => '_delete_always', 'id' => $field_id, 'value' => 1));
-
- $blocks['main']['options']['delete_always'] = array(
- 'title' => html::label($field_id, Q(rcube_label('deletealways'))),
- 'content' => $input_delete_always->show($config['delete_always']?1:0),
- );
- }
-
- if (!isset($no_override['delete_junk'])) {
- $field_id = 'rcmfd_delete_junk';
- $input_delete_junk = new html_checkbox(array('name' => '_delete_junk', 'id' => $field_id, 'value' => 1));
-
- $blocks['main']['options']['delete_junk'] = array(
- 'title' => html::label($field_id, Q(rcube_label('deletejunk'))),
- 'content' => $input_delete_junk->show($config['delete_junk']?1:0),
- );
- }
-
- // Trash purging on logout
- if (!isset($no_override['logout_purge'])) {
- $field_id = 'rcmfd_logout_purge';
- $input_purge = new html_checkbox(array('name' => '_logout_purge', 'id' => $field_id, 'value' => 1));
-
- $blocks['maintenance']['options']['logout_purge'] = array(
- 'title' => html::label($field_id, Q(rcube_label('logoutclear'))),
- 'content' => $input_purge->show($config['logout_purge']?1:0),
- );
- }
-
- // INBOX compacting on logout
- if (!isset($no_override['logout_expunge'])) {
- $field_id = 'rcmfd_logout_expunge';
- $input_expunge = new html_checkbox(array('name' => '_logout_expunge', 'id' => $field_id, 'value' => 1));
-
- $blocks['maintenance']['options']['logout_expunge'] = array(
- 'title' => html::label($field_id, Q(rcube_label('logoutcompact'))),
- 'content' => $input_expunge->show($config['logout_expunge']?1:0),
- );
- }
-
- break;
- }
-
- $data = $RCMAIL->plugins->exec_hook('preferences_list', array('section' => $sect['id'], 'blocks' => $blocks));
- $found = false;
-
- // create output
- foreach ($data['blocks'] as $block) {
- if (!empty($block['content']) || !empty($block['options'])) {
- $found = true;
- break;
- }
- }
-
- if (!$found)
- unset($sections[$idx]);
- else
- $sections[$idx]['blocks'] = $data['blocks'];
- }
-
- return array($sections, $plugin['cols']);
+ return array($sections, $plugin['cols']);
}
function rcmail_get_skins()
{
- $path = 'skins';
- $skins = array();
-
- $dir = opendir($path);
+ $path = RCUBE_INSTALL_PATH . 'skins';
+ $skins = array();
+ $dir = opendir($path);
- if (!$dir)
- return false;
+ if (!$dir) {
+ return false;
+ }
- while (($file = readdir($dir)) !== false)
- {
- $filename = $path.'/'.$file;
- if (!preg_match('/^\./', $file) && is_dir($filename) && is_readable($filename))
- $skins[] = $file;
- }
+ while (($file = readdir($dir)) !== false) {
+ $filename = $path.'/'.$file;
+ if (!preg_match('/^\./', $file) && is_dir($filename) && is_readable($filename)) {
+ $skins[] = $file;
+ }
+ }
- closedir($dir);
+ closedir($dir);
- return $skins;
+ return $skins;
}
@@ -988,9 +1237,9 @@ function rcmail_update_folder_row($name, $oldname=null, $subscribe=false, $class
// register UI objects
$OUTPUT->add_handlers(array(
- 'prefsframe' => 'rcmail_preferences_frame',
- 'sectionslist' => 'rcmail_sections_list',
- 'identitieslist' => 'rcmail_identities_list',
+ 'prefsframe' => 'rcmail_preferences_frame',
+ 'sectionslist' => 'rcmail_sections_list',
+ 'identitieslist' => 'rcmail_identities_list',
));
// register action aliases
diff --git a/program/steps/settings/save_prefs.inc b/program/steps/settings/save_prefs.inc
index 3bb82aa38..19edb41d4 100644
--- a/program/steps/settings/save_prefs.inc
+++ b/program/steps/settings/save_prefs.inc
@@ -34,6 +34,7 @@ switch ($CURR_SECTION)
'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,
'refresh_interval' => isset($_POST['_refresh_interval']) ? intval($_POST['_refresh_interval'])*60 : $CONFIG['refresh_interval'],
+ 'standard_windows' => isset($_POST['_standard_windows']) ? TRUE : FALSE,
'skin' => isset($_POST['_skin']) ? get_input_value('_skin', RCUBE_INPUT_POST) : $CONFIG['skin'],
);
@@ -119,6 +120,8 @@ switch ($CURR_SECTION)
case 'folders':
$a_user_prefs = array(
+ 'show_real_foldernames' =>
+ isset($_POST['_show_real_foldernames']) ? TRUE : FALSE,
'drafts_mbox' => get_input_value('_drafts_mbox', RCUBE_INPUT_POST, true),
'sent_mbox' => get_input_value('_sent_mbox', RCUBE_INPUT_POST, true),
'junk_mbox' => get_input_value('_junk_mbox', RCUBE_INPUT_POST, true),
diff --git a/skins/classic/addressbook.css b/skins/classic/addressbook.css
index 5afa4592f..415142e0c 100644
--- a/skins/classic/addressbook.css
+++ b/skins/classic/addressbook.css
@@ -224,6 +224,37 @@
-o-text-overflow: ellipsis;
}
+#contacts-table .contact.readonly td
+{
+ font-style: italic;
+}
+
+#contacts-table td.name
+{
+ width: 95%;
+}
+
+#contacts-table td.action
+{
+ width: 12px;
+ padding: 0px 6px 0 4px;
+ text-align: right;
+}
+
+#contacts-table td.action a
+{
+ font-size: 16px;
+ font-weight: bold;
+ font-style: normal;
+ text-decoration: none;
+ color: #333;
+}
+
+#contacts-table .selected td.action a
+{
+ color: #fff;
+}
+
#contacts-box
{
position: absolute;
diff --git a/skins/classic/common.css b/skins/classic/common.css
index 1f62fbe07..3c322f0ed 100644
--- a/skins/classic/common.css
+++ b/skins/classic/common.css
@@ -283,6 +283,15 @@ body > #message a
text-decoration: underline;
}
+body.extwin #closelink
+{
+ position: absolute;
+ top: 5px;
+ right: 20px;
+ text-align: right;
+ z-index:100;
+}
+
.box
{
border: 1px solid #999;
diff --git a/skins/classic/functions.js b/skins/classic/functions.js
index d980627aa..af561c37b 100644
--- a/skins/classic/functions.js
+++ b/skins/classic/functions.js
@@ -94,7 +94,7 @@ function rcube_mail_ui()
messagemenu: {id:'messagemenu'},
attachmentmenu: {id:'attachmentmenu'},
listmenu: {id:'listmenu', editable:1},
- dragmessagemenu:{id:'dragmessagemenu', sticky:1},
+ dragmenu: {id:'dragmenu', sticky:1},
groupmenu: {id:'groupoptionsmenu', above:1},
mailboxmenu: {id:'mailboxoptionsmenu', above:1},
composemenu: {id:'composeoptionsmenu', editable:1, overlap:1},
@@ -162,9 +162,9 @@ show_popupmenu: function(popup, show)
}
},
-dragmessagemenu: function(show)
+dragmenu: function(show)
{
- this.popups.dragmessagemenu.obj[show?'show':'hide']();
+ this.popups.dragmenu.obj[show?'show':'hide']();
},
forwardmenu: function(show)
@@ -492,14 +492,18 @@ switch_preview_pane: function(elem)
/* Message composing */
init_compose_form: function()
{
- var f, field, fields = ['cc', 'bcc', 'replyto', 'followupto'],
+ var f, v, field, fields = ['cc', 'bcc', 'replyto', 'followupto'],
div = document.getElementById('compose-div'),
headers_div = document.getElementById('compose-headers-div');
// Show input elements with non-empty value
for (f=0; f<fields.length; f++) {
- if ((field = $('#_'+fields[f])) && field.length && field.val() != '')
- rcmail_ui.show_header_form(fields[f]);
+ v = fields[f]; field = $('#_'+v);
+ if (field.length) {
+ field.on('change', {v:v}, function(e) { if (this.value) rcmail_ui.show_header_form(e.data.v); });
+ if (field.val() != '')
+ rcmail_ui.show_header_form(v);
+ }
}
// prevent from form data loss when pressing ESC key in IE
@@ -630,9 +634,117 @@ enable_command: function(p)
};
/**
- * Scroller
+ * Roundcube generic layer (floating box) class
+ *
+ * @constructor
*/
+function rcube_layer(id, attributes)
+{
+ this.name = id;
+
+ // create a new layer in the current document
+ this.create = function(arg)
+ {
+ var l = (arg.x) ? arg.x : 0,
+ t = (arg.y) ? arg.y : 0,
+ w = arg.width,
+ h = arg.height,
+ z = arg.zindex,
+ vis = arg.vis,
+ parent = arg.parent,
+ obj = document.createElement('DIV');
+
+ obj.id = this.name;
+ obj.style.position = 'absolute';
+ obj.style.visibility = (vis) ? (vis==2) ? 'inherit' : 'visible' : 'hidden';
+ obj.style.left = l+'px';
+ obj.style.top = t+'px';
+ if (w)
+ obj.style.width = w.toString().match(/\%$/) ? w : w+'px';
+ if (h)
+ obj.style.height = h.toString().match(/\%$/) ? h : h+'px';
+ if (z)
+ obj.style.zIndex = z;
+
+ if (parent)
+ parent.appendChild(obj);
+ else
+ document.body.appendChild(obj);
+
+ this.elm = obj;
+ };
+
+ // create new layer
+ if (attributes != null) {
+ this.create(attributes);
+ this.name = this.elm.id;
+ }
+ else // just refer to the object
+ this.elm = document.getElementById(id);
+
+ if (!this.elm)
+ return false;
+
+ // ********* layer object properties *********
+
+ 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') ? true : false;
+
+
+ // ********* layer object methods *********
+
+ // move the layer to a specific position
+ this.move = function(x, y)
+ {
+ this.x = x;
+ this.y = y;
+ this.css.left = Math.round(this.x)+'px';
+ this.css.top = Math.round(this.y)+'px';
+ };
+
+ // change the layers width and height
+ this.resize = function(w,h)
+ {
+ this.css.width = w+'px';
+ this.css.height = h+'px';
+ this.width = w;
+ this.height = h;
+ };
+
+ // show or hide the layer
+ this.show = function(a)
+ {
+ if(a == 1) {
+ this.css.visibility = 'visible';
+ this.visible = true;
+ }
+ else if(a == 2) {
+ this.css.visibility = 'inherit';
+ this.visible = true;
+ }
+ else {
+ this.css.visibility = 'hidden';
+ this.visible = false;
+ }
+ };
+
+ // write new content into a Layer
+ this.write = function(cont)
+ {
+ this.elm.innerHTML = cont;
+ };
+
+};
+
+/**
+ * Scroller
+ */
function rcmail_scroller(list, top, bottom)
{
var ref = this;
@@ -684,24 +796,25 @@ function iframe_events()
// Abbreviate mailbox names to fit width of the container
function rcube_render_mailboxlist()
{
- var list = $('#mailboxlist > li a, #mailboxlist ul:visible > li a');
+ 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 > (bw.ie ? 25 : 100))
+ if (list.length > (bw.ie && bw.vendver < 9 ? 40 : 100))
return;
- list.each(function(){
+ list.each(function() {
var elem = $(this),
text = elem.data('text');
if (!text) {
- text = elem.text().replace(/\s+\(.+$/, '');
+ text = elem.text().replace(/\s+\([0-9]+\)$/, '');
elem.data('text', text);
}
+
if (text.length < 6)
return;
- var abbrev = fit_string_to_size(text, elem, elem.width() - elem.children('span.unreadcount').width());
+ var abbrev = fit_string_to_size(text, elem, elem.width() - elem.children('span.unreadcount').width() - 16);
if (abbrev != text)
elem.attr('title', text);
elem.contents().filter(function(){ return (this.nodeType == 3); }).get(0).data = abbrev;
@@ -711,19 +824,23 @@ function rcube_render_mailboxlist()
// inspired by https://gist.github.com/24261/7fdb113f1e26111bd78c0c6fe515f6c0bf418af5
function fit_string_to_size(str, elem, len)
{
- var w, span, result = str, ellip = '...';
+ var w, span, $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'})
+ span = $('<b>').css({visibility: 'hidden', padding: '0px',
+ 'font-family': elem.css('font-family'),
+ 'font-size': elem.css('font-size')})
.appendTo($('body', document)).get(0);
rcmail.env.tmp_span = span;
}
else {
span = rcmail.env.tmp_span;
}
- span.innerHTML = result;
+
+ $span = $(span);
+ $span.text(result);
// on first run, check if string fits into the length already.
w = span.offsetWidth;
@@ -736,7 +853,7 @@ function fit_string_to_size(str, elem, len)
while (true) {
offLeft = mid - cut;
offRight = mid + cut;
- span.innerHTML = str.substring(0,offLeft) + ellip + str.substring(offRight);
+ $span.text(str.substring(0,offLeft) + ellip + str.substring(offRight));
// break loop if string fits size
if (offLeft < 3 || span.offsetWidth)
@@ -823,8 +940,8 @@ function percent_indicator(obj, data)
// Optional parameters used by TinyMCE
var rcmail_editor_settings = {
- skin : "default", // "default", "o2k7"
- skin_variant : "" // "", "silver", "black"
+ skin: "default", // "default", "o2k7"
+ skin_variant: "" // "", "silver", "black"
};
var rcmail_ui;
@@ -835,46 +952,52 @@ function rcube_init_mail_ui()
rcube_event.add_listener({ object:rcmail_ui, method:'body_mouseup', event:'mouseup' });
rcube_event.add_listener({ object:rcmail_ui, method:'body_keydown', event:'keydown' });
- if (rcmail.env.quota_content)
- update_quota(rcmail.env.quota_content);
- rcmail.addEventListener('setquota', update_quota);
-
- $('iframe').load(iframe_events)
- .contents().mouseup(function(e){rcmail_ui.body_mouseup(e)});
-
- if (rcmail.env.task == 'mail') {
- rcmail.addEventListener('enable-command', 'enable_command', rcmail_ui);
- rcmail.addEventListener('menu-open', 'menu_open', rcmail_ui);
- rcmail.addEventListener('menu-save', 'menu_save', rcmail_ui);
- rcmail.addEventListener('aftersend-attachment', 'uploadmenu', rcmail_ui);
- rcmail.addEventListener('aftertoggle-editor', 'resize_compose_body_ev', rcmail_ui);
- rcmail.gui_object('message_dragmenu', 'dragmessagemenu');
-
- if (rcmail.gui_objects.mailboxlist) {
- rcmail.addEventListener('responseaftermark', rcube_render_mailboxlist);
- rcmail.addEventListener('responseaftergetunread', rcube_render_mailboxlist);
- rcmail.addEventListener('responseaftercheck-recent', rcube_render_mailboxlist);
- rcmail.addEventListener('aftercollapse-folder', rcube_render_mailboxlist);
+ rcmail.addEventListener('init', function() {
+ if (rcmail.env.quota_content)
+ update_quota(rcmail.env.quota_content);
+ rcmail.addEventListener('setquota', update_quota);
+
+ $('iframe').load(iframe_events)
+ .contents().mouseup(function(e){rcmail_ui.body_mouseup(e)});
+
+ if (rcmail.env.task == 'mail') {
+ rcmail.addEventListener('enable-command', 'enable_command', rcmail_ui);
+ rcmail.addEventListener('menu-open', 'menu_open', rcmail_ui);
+ rcmail.addEventListener('menu-save', 'menu_save', rcmail_ui);
+ rcmail.addEventListener('aftersend-attachment', 'uploadmenu', rcmail_ui);
+ rcmail.addEventListener('aftertoggle-editor', 'resize_compose_body_ev', rcmail_ui);
+ rcmail.gui_object('dragmenu', 'dragmenu');
+
+ if (rcmail.gui_objects.mailboxlist) {
+ rcmail.treelist.addEventListener('expand', rcube_render_mailboxlist);
+ rcmail.addEventListener('responseaftermark', rcube_render_mailboxlist);
+ rcmail.addEventListener('responseaftergetunread', rcube_render_mailboxlist);
+ rcmail.addEventListener('responseaftercheck-recent', rcube_render_mailboxlist);
+ rcmail.addEventListener('responseafterrefresh', rcube_render_mailboxlist);
+ rcmail.addEventListener('afterimport-messages', function(){ rcmail_ui.show_popup('uploadform', false); });
+
+ new rcmail_scroller('#mailboxlist-content', '#mailboxlist-title', '#mailboxlist-footer');
+ }
- new rcmail_scroller('#mailboxlist-content', '#mailboxlist-title', '#mailboxlist-footer');
+ if (rcmail.env.action == 'compose')
+ rcmail_ui.init_compose_form();
+ else if (rcmail.env.action == 'show' || rcmail.env.action == 'preview')
+ // add menu link for each attachment
+ $('#attachment-list > li[id^="attach"]').each(function() {
+ $(this).append($('<a class="drop">').click(function() { rcmail_ui.show_attachmentmenu(this); }));
+ });
}
+ else if (rcmail.env.task == 'addressbook') {
+ rcmail.addEventListener('afterupload-photo', function(){ rcmail_ui.show_popup('uploadform', false); });
- if (rcmail.env.action == 'compose')
- rcmail_ui.init_compose_form();
- else if (rcmail.env.action == 'show' || rcmail.env.action == 'preview')
- // add menu link for each attachment
- $('#attachment-list > li[id^="attach"]').each(function() {
- $(this).append($('<a class="drop">').click(function() { rcmail_ui.show_attachmentmenu(this); }));
- });
- }
- else if (rcmail.env.task == 'addressbook') {
- rcmail.addEventListener('afterupload-photo', function(){ rcmail_ui.show_popup('uploadform', false); });
+ if (rcmail.gui_objects.folderlist)
+ new rcmail_scroller('#directorylist-content', '#directorylist-title', '#directorylist-footer');
- if (rcmail.gui_objects.folderlist)
- new rcmail_scroller('#directorylist-content', '#directorylist-title', '#directorylist-footer');
- }
- else if (rcmail.env.task == 'settings') {
- if (rcmail.gui_objects.subscriptionlist)
- new rcmail_scroller('#folderlist-content', '#folderlist-title', '#folderlist-footer');
- }
+ rcmail.gui_object('dragmenu', 'dragmenu');
+ }
+ else if (rcmail.env.task == 'settings') {
+ if (rcmail.gui_objects.subscriptionlist)
+ new rcmail_scroller('#folderlist-content', '#folderlist-title', '#folderlist-footer');
+ }
+ });
}
diff --git a/skins/classic/images/contactgroup.png b/skins/classic/images/contactgroup.png
new file mode 100644
index 000000000..c46383255
--- /dev/null
+++ b/skins/classic/images/contactgroup.png
Binary files differ
diff --git a/skins/classic/images/mail_toolbar.png b/skins/classic/images/mail_toolbar.png
index e68035da5..4a8431715 100644
--- a/skins/classic/images/mail_toolbar.png
+++ b/skins/classic/images/mail_toolbar.png
Binary files differ
diff --git a/skins/classic/includes/messagetoolbar.html b/skins/classic/includes/messagetoolbar.html
index bd14f490f..8f8efd291 100644
--- a/skins/classic/includes/messagetoolbar.html
+++ b/skins/classic/includes/messagetoolbar.html
@@ -21,7 +21,7 @@
<roundcube:button name="markmenulink" id="markmenulink" type="link" class="button markmessage" title="markmessages" onclick="rcmail_ui.show_popup('markmenu');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:object name="mailboxlist" type="select" noSelection="moveto" maxlength="25" onchange="rcmail.command('move', this.options[this.selectedIndex].value)" class="mboxlist" folder_filter="mail" />
<roundcube:endif />
</div>
diff --git a/skins/classic/mail.css b/skins/classic/mail.css
index 7c350ca3d..b8cc9f351 100644
--- a/skins/classic/mail.css
+++ b/skins/classic/mail.css
@@ -107,6 +107,14 @@
background-position: -192px -32px;
}
+#messagetoolbar a.print {
+ background-position: -224px 0;
+}
+
+#messagetoolbar a.printSel {
+ background-position: -224px -32px;
+}
+
#messagetoolbar a.markmessage {
background-position: -256px 0;
}
@@ -155,6 +163,14 @@
background-position: -416px -32px;
}
+#messagetoolbar a.download {
+ background-position: -480px 0;
+}
+
+#messagetoolbar a.downloadSel {
+ background-position: -480px -32px;
+}
+
#messagetoolbar select.mboxlist
{
position: relative;
@@ -284,10 +300,38 @@
#messagepartcontainer
{
position: absolute;
- top: 80px;
- left: 20px;
- right: 20px;
- bottom: 20px;
+ top: 0;
+ left: 170px;
+ right: 0;
+ bottom: 0;
+}
+
+#messagepartheader
+{
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ width: 160px;
+ border: 1px solid #999999;
+ background-color: #F9F9F9;
+ overflow: hidden;
+}
+
+#messagepartheader table
+{
+ width: 100%;
+ table-layout: fixed;
+}
+
+#messagepartheader table td
+{
+ text-overflow: ellipsis;
+}
+
+#messagepartheader table td.title
+{
+ width: 60px;
}
#mailcontframe
@@ -329,31 +373,7 @@
height: 100%;
min-height: 100%; /* Chrome 14 bug */
border: 1px solid #999999;
- background-color: #F9F9F9;
-}
-
-
-#partheader
-{
- position: absolute;
- top: 10px;
- left: 220px;
- right: 20px;
- height: 40px;
-}
-
-#partheader table td
-{
- padding-left: 2px;
- padding-right: 4px;
- vertical-align: middle;
- font-size: 11px;
-}
-
-#partheader table td.title
-{
- color: #666666;
- font-weight: bold;
+ background-color: #fff;
}
@@ -611,14 +631,22 @@ body.messagelist
background-color: #F9F9F9;
}
-#messagelist
+table.messagelist
{
width: 100%;
display: table;
table-layout: fixed;
+ border-collapse: collapse;
+ border-spacing: 0;
+ z-index: 1;
}
-#messagelist thead tr td
+table.messagelist.fixedcopy
+{
+ z-index: 2;
+}
+
+.messagelist thead tr td
{
height: 20px;
padding: 0 4px 0 2px;
@@ -630,23 +658,23 @@ body.messagelist
font-weight: bold;
}
-#messagelist thead tr td.sortedASC,
-#messagelist thead tr td.sortedDESC
+.messagelist thead tr td.sortedASC,
+.messagelist thead tr td.sortedDESC
{
background-position: 0 -26px;
}
-#messagelist thead tr td.sortedASC a
+.messagelist thead tr td.sortedASC a
{
background: url(images/icons/sort.gif) right 0 no-repeat;
}
-#messagelist thead tr td.sortedDESC a
+.messagelist thead tr td.sortedDESC a
{
background: url(images/icons/sort.gif) right -14px no-repeat;
}
-#messagelist thead tr td a
+.messagelist thead tr td a
{
display: block;
width: auto !important;
@@ -655,18 +683,19 @@ body.messagelist
text-decoration: none;
}
-#messagelist thead tr td.size
+.messagelist thead tr td.size.sortedASC a,
+.messagelist thead tr td.size.sortedDESC a
{
- text-align: left;
+ padding-right: 18px;
}
-#messagelist thead tr td.subject
+.messagelist thead tr td.subject
{
padding-left: 18px;
width: 99%;
}
-#messagelist tbody tr td
+.messagelist tbody tr td
{
height: 20px;
padding: 0;
@@ -680,7 +709,7 @@ body.messagelist
cursor: default;
}
-#messagelist tbody tr td a
+.messagelist tbody tr td a
{
color: #000;
text-decoration: none;
@@ -688,53 +717,53 @@ body.messagelist
cursor: inherit;
}
-#messagelist td img
+.messagelist td img
{
vertical-align: middle;
display: inline-block;
}
-#messagelist tbody tr td.flag,
-#messagelist tbody tr td.status,
-#messagelist tbody tr td.subject span.status
+.messagelist tbody tr td.flag,
+.messagelist tbody tr td.status,
+.messagelist tbody tr td.subject span.status
{
cursor: pointer;
}
-#messagelist tr td.flag span,
-#messagelist tr td.status span,
-#messagelist tr td.attachment span,
-#messagelist tr td.priority span
+.messagelist tr td.flag span,
+.messagelist tr td.status span,
+.messagelist tr td.attachment span,
+.messagelist tr td.priority span
{
display: block;
width: 15px;
}
-#messagelist tr td div.collapsed,
-#messagelist tr td div.expanded,
-#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.status span.status,
-#messagelist tr td.status span.msgicon,
-#messagelist tr td.status span.deleted,
-#messagelist tr td.status span.unread,
-#messagelist tr td.status span.unreadchildren,
-#messagelist tr td.subject span.msgicon,
-#messagelist tr td.subject span.deleted,
-#messagelist tr td.subject span.unread,
-#messagelist tr td.subject span.replied,
-#messagelist tr td.subject span.forwarded,
-#messagelist tr td.subject span.unreadchildren
+.messagelist tr td div.collapsed,
+.messagelist tr td div.expanded,
+.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.status span.status,
+.messagelist tr td.status span.msgicon,
+.messagelist tr td.status span.deleted,
+.messagelist tr td.status span.unread,
+.messagelist tr td.status span.unreadchildren,
+.messagelist tr td.subject span.msgicon,
+.messagelist tr td.subject span.deleted,
+.messagelist tr td.subject span.unread,
+.messagelist tr td.subject span.replied,
+.messagelist tr td.subject span.forwarded,
+.messagelist tr td.subject span.unreadchildren
{
display: inline-block;
vertical-align: middle;
@@ -743,212 +772,212 @@ body.messagelist
background: url(images/messageicons.png) center no-repeat;
}
-#messagelist tr td.attachment span.attachment
+.messagelist tr td.attachment span.attachment
{
background-position: 0 -170px;
}
-#messagelist tr td.attachment span.report
+.messagelist tr td.attachment span.report
{
background-position: 0 -255px;
}
-#messagelist tr td.priority span.priority
+.messagelist tr td.priority span.priority
{
background-position: 0 -309px;
}
-#messagelist tr td.priority span.prio5
+.messagelist tr td.priority span.prio5
{
background-position: 0 -358px;
}
-#messagelist tr td.priority span.prio4
+.messagelist tr td.priority span.prio4
{
background-position: 0 -340px;
}
-#messagelist tr td.priority span.prio3
+.messagelist tr td.priority span.prio3
{
background-position: 0 -324px;
}
-#messagelist tr td.priority span.prio2
+.messagelist tr td.priority span.prio2
{
background-position: 0 -309px;
}
-#messagelist tr td.priority span.prio1
+.messagelist tr td.priority span.prio1
{
background-position: 0 -290px;
}
-#messagelist tr td.flag span.flagged
+.messagelist tr td.flag span.flagged
{
background-position: 0 -153px;
}
-#messagelist tr td.flag span.unflagged:hover
+.messagelist tr td.flag span.unflagged:hover
{
background-position: 0 -136px;
}
-#messagelist tr td.subject span.msgicon,
-#messagelist tr td.subject span.unreadchildren
+.messagelist tr td.subject span.msgicon,
+.messagelist tr td.subject span.unreadchildren
{
background-position: 0 -51px;
margin: 0 2px;
}
-#messagelist tr td.subject span.replied
+.messagelist tr td.subject span.replied
{
background-position: 0 -85px;
}
-#messagelist tr td.subject span.forwarded
+.messagelist tr td.subject span.forwarded
{
background-position: 0 -68px;
}
-#messagelist tr td.subject span.replied.forwarded
+.messagelist tr td.subject span.replied.forwarded
{
background-position: 0 -102px;
}
-#messagelist tr td.status span.msgicon,
-#messagelist tr td.flag span.unflagged,
-#messagelist tr td.status span.unreadchildren
+.messagelist tr td.status span.msgicon,
+.messagelist tr td.flag span.unflagged,
+.messagelist tr td.status span.unreadchildren
{
background-position: 0 17px; /* no icon */
}
-#messagelist tr td.status span.msgicon:hover
+.messagelist tr td.status span.msgicon:hover
{
background-position: 0 -272px;
}
-#messagelist tr td.status span.deleted,
-#messagelist tr td.subject span.deleted
+.messagelist tr td.status span.deleted,
+.messagelist tr td.subject span.deleted
{
background-position: 0 -187px;
}
-#messagelist tr td.status span.status,
-#messagelist tr td.status span.unread,
-#messagelist tr td.subject span.unread
+.messagelist tr td.status span.status,
+.messagelist tr td.status span.unread,
+.messagelist tr td.subject span.unread
{
background-position: 0 -119px;
}
-#messagelist tr td div.collapsed
+.messagelist tr td div.collapsed
{
background-position: 0 -221px;
cursor: pointer;
}
-#messagelist tr td div.expanded
+.messagelist tr td div.expanded
{
background-position: 0 -204px;
cursor: pointer;
}
-#messagelist tr td.threads div.listmenu
+.messagelist tr td.threads div.listmenu
{
background-position: 0 -238px;
cursor: pointer;
}
-#messagelist tbody tr td.subject
+.messagelist tbody tr td.subject
{
width: 99%;
}
-#messagelist tbody tr td.subject a
+.messagelist tbody tr td.subject a
{
cursor: default;
vertical-align: middle; /* #1487091 */
}
/* thread parent message with unread children */
-#messagelist tbody tr.unroot td.subject a
+.messagelist tbody tr.unroot td.subject a
{
text-decoration: underline;
}
-#messagelist tr td.attachment,
-#messagelist tr td.threads,
-#messagelist tr td.status,
-#messagelist tr td.flag,
-#messagelist tr td.priority
+.messagelist tr td.attachment,
+.messagelist tr td.threads,
+.messagelist tr td.status,
+.messagelist tr td.flag,
+.messagelist tr td.priority
{
width: 17px;
padding: 0 0 0 2px;
}
-#messagelist tr td.size
+.messagelist tr td.size
{
width: 60px;
text-align: right;
padding: 0 2px;
}
-#messagelist tr td.fromto,
-#messagelist tr td.from,
-#messagelist tr td.to,
-#messagelist tr td.cc,
-#messagelist tr td.replyto
+.messagelist tr td.fromto,
+.messagelist tr td.from,
+.messagelist tr td.to,
+.messagelist tr td.cc,
+.messagelist tr td.replyto
{
width: 180px;
padding: 0 2px;
}
-#messagelist tr td.date
+.messagelist tr td.date
{
width: 118px;
padding: 0 2px;
}
-#messagelist tr.message
+.messagelist tr.message
{
background-color: #FFF;
}
-#messagelist tr.unread
+.messagelist tr.unread
{
font-weight: bold;
background-color: #FFFFFF;
}
-#messagelist tr.flagged td,
-#messagelist tr.flagged td a
+.messagelist tr.flagged td,
+.messagelist tr.flagged td a
{
color: #CC0000;
}
-#messagelist tr.selected td
+.messagelist tr.selected td
{
color: #FFFFFF;
background-color: #CC3333;
}
-#messagelist tr.unfocused td
+.messagelist tr.unfocused td
{
color: #FFFFFF;
background-color: #929292;
}
-#messagelist tr.selected td a
+.messagelist tr.selected td a
{
color: #FFFFFF;
}
-#messagelist tr.unfocused td a
+.messagelist tr.unfocused td a
{
color: #FFFFFF;
}
-#messagelist tr.deleted td,
-#messagelist tr.deleted td a
+.messagelist tr.deleted td,
+.messagelist tr.deleted td a
{
color: #CCCCCC;
}
@@ -1600,16 +1629,19 @@ input.from_address
vertical-align: middle;
}
+#upload-form,
#attachment-form
{
padding: 6px;
}
+#upload-form div,
#attachment-form div
{
padding: 2px;
}
+#upload-form div.buttons,
#attachment-form div.buttons
{
margin-top: 4px;
@@ -1687,6 +1719,14 @@ input.from_address
-o-text-overflow: ellipsis;
}
+#contacts-table td span.email
+{
+ display: inline;
+ color: #ccc;
+ font-style: italic;
+ margin-left: 0.5em;
+}
+
#abookcountbar
{
margin-top: 4px;
diff --git a/skins/classic/print.css b/skins/classic/print.css
index 34125b0d3..d7e332dba 100644
--- a/skins/classic/print.css
+++ b/skins/classic/print.css
@@ -136,3 +136,32 @@ div.message-part blockquote blockquote blockquote
border-left: 2px solid #bb0000;
border-right: 2px solid #bb0000;
}
+
+p.image-attachment
+{
+ position: relative;
+ padding: 1em;
+ border-top: 1px solid #ccc;
+}
+
+p.image-attachment a.image-link
+{
+ float: left;
+ display: block;
+ margin-right: 2em;
+ min-width: 160px;
+ min-height: 60px;
+ text-align: center;
+}
+
+p.image-attachment .image-filename
+{
+ display: block;
+ line-height: 1.6em;
+}
+
+p.image-attachment .attachment-links
+{
+ display: none;
+}
+
diff --git a/skins/classic/settings.css b/skins/classic/settings.css
index c918e3c18..2433f5040 100644
--- a/skins/classic/settings.css
+++ b/skins/classic/settings.css
@@ -85,6 +85,8 @@
{
font-weight: bold;
text-align: right;
+ width: 1%;
+ white-space: nowrap;
}
#bottomboxes
@@ -253,3 +255,15 @@ div.crop
{
overflow: auto;
}
+
+#rcmfd_signature
+{
+ width: 99%;
+ min-width: 390px;
+}
+
+#rcmfd_signature_toolbar1 td,
+#rcmfd_signature_toolbar2 td
+{
+ width: auto;
+}
diff --git a/skins/classic/templates/about.html b/skins/classic/templates/about.html
index 519acf773..429dfcf5f 100644
--- a/skins/classic/templates/about.html
+++ b/skins/classic/templates/about.html
@@ -7,11 +7,15 @@
</head>
<body>
+<roundcube:if condition="!request:_framed" />
+
<roundcube:include file="/includes/taskbar.html" />
<roundcube:include file="/includes/header.html" />
<roundcube:include file="/includes/settingstabs.html" />
<div id="mainscreen" class="box darkbg crop">
+<roundcube:endif />
+
<div class="readtext">
<div id="license">
<roundcube:object name="aboutcontent" />
@@ -29,7 +33,10 @@ Some <a href="http://roundcube.net/license">exceptions</a> for skins &amp; plugi
<roundcube:object name="pluginlist" id="pluginlist" class="records-table" cellspacing="0" />
</div>
+
+<roundcube:if condition="!request:_framed" />
</div>
+<roundcube:endif />
</body>
</html>
diff --git a/skins/classic/templates/addressbook.html b/skins/classic/templates/addressbook.html
index ba119891c..429b83438 100644
--- a/skins/classic/templates/addressbook.html
+++ b/skins/classic/templates/addressbook.html
@@ -17,7 +17,7 @@
</style>
</head>
-<body onload="rcube_init_mail_ui()">
+<body>
<roundcube:include file="/includes/taskbar.html" />
<roundcube:include file="/includes/header.html" />
@@ -75,7 +75,7 @@
<div id="addressscreen">
<div id="addresslist">
-<div class="boxtitle"><roundcube:label name="contacts" /></div>
+<roundcube:object name="addresslisttitle" label="contacts" tag="div" class="boxtitle" />
<div class="boxlistcontent">
<roundcube:object name="addresslist" id="contacts-table" class="records-table" cellspacing="0" summary="Contacts list" noheader="true" />
</div>
@@ -116,5 +116,16 @@
</ul>
</div>
+<div id="dragmenu" class="popupmenu">
+ <ul>
+ <li><roundcube:button command="move" onclick="return rcmail.drag_menu_action('move')" label="move" classAct="active" /></li>
+ <li><roundcube:button command="copy" onclick="return rcmail.drag_menu_action('copy')" label="copy" classAct="active" /></li>
+ </ul>
+</div>
+
+<script type="text/javascript">
+rcube_init_mail_ui();
+</script>
+
</body>
</html>
diff --git a/skins/classic/templates/compose.html b/skins/classic/templates/compose.html
index 5b0b47924..5e259e11c 100644
--- a/skins/classic/templates/compose.html
+++ b/skins/classic/templates/compose.html
@@ -16,10 +16,10 @@
</style>
</head>
<roundcube:if condition="env:extwin" />
-<body class="extwin" onload="rcube_init_mail_ui()">
+<body class="extwin">
<roundcube:object name="message" id="message" />
<roundcube:else />
-<body onload="rcube_init_mail_ui()">
+<body>
<roundcube:include file="/includes/taskbar.html" />
<roundcube:include file="/includes/header.html" />
<roundcube:endif />
@@ -44,7 +44,7 @@
<roundcube:button name="messageoptions" id="composemenulink" type="link" class="button messagemenu" title="messageoptions" onclick="rcmail_ui.show_popup('composemenu', true);return false" content=" " />
</div>
-<form name="form" action="./" method="post">
+<roundcube:form name="form" method="post">
<div id="mainscreen">
@@ -197,5 +197,9 @@
<roundcube:object name="composeAttachmentForm" id="attachment-form" attachmentFieldSize="40" class="popupmenu" />
+<script type="text/javascript">
+rcube_init_mail_ui();
+</script>
+
</body>
</html>
diff --git a/skins/classic/templates/contact.html b/skins/classic/templates/contact.html
index d74a78b27..8be112b49 100644
--- a/skins/classic/templates/contact.html
+++ b/skins/classic/templates/contact.html
@@ -13,7 +13,7 @@
<div id="sourcename"><roundcube:label name="addressbook" />: <roundcube:var name="env:sourcename" /></div>
<roundcube:endif />
- <div id="contactphoto"><roundcube:object name="contactphoto" id="contactpic" placeholder="/images/contactpic.png" /></div>
+ <div id="contactphoto"><roundcube:object name="contactphoto" id="contactpic" placeholder="/images/contactpic.png" placeholderGroup="/images/contactgroup.png" /></div>
<roundcube:object name="contacthead" id="contacthead" />
<div style="clear:both"></div>
<div id="contacttabs">
diff --git a/skins/classic/templates/contactadd.html b/skins/classic/templates/contactadd.html
index 05cc8aa82..bad6daf28 100644
--- a/skins/classic/templates/contactadd.html
+++ b/skins/classic/templates/contactadd.html
@@ -5,11 +5,11 @@
<roundcube:include file="/includes/links.html" />
<script type="text/javascript" src="/functions.js"></script>
</head>
-<body class="iframe" onload="rcube_init_mail_ui()">
+<body class="iframe">
<div id="contact-title" class="boxtitle"><roundcube:label name="addcontact" /></div>
<div id="contact-details" class="boxcontent">
-<form name="editform" method="post" action="./">
+<roundcube:form name="editform" method="post">
<roundcube:if condition="strlen(env:sourcename)" />
<div id="sourcename"><roundcube:label name="addressbook" />: <roundcube:object name="sourceselector" class="hint" id="sourceselect" /></div>
<roundcube:endif />
@@ -35,7 +35,10 @@
<roundcube:object name="photoUploadForm" id="upload-form" size="30" class="popupmenu" />
<roundcube:object name="fileDropArea" id="contactpic" />
-<script type="text/javascript">rcube_init_tabs('contacttabs')</script>
+<script type="text/javascript">
+rcube_init_tabs('contacttabs');
+rcube_init_mail_ui();
+</script>
</body>
</html>
diff --git a/skins/classic/templates/contactedit.html b/skins/classic/templates/contactedit.html
index db8599ac6..c51cbf296 100644
--- a/skins/classic/templates/contactedit.html
+++ b/skins/classic/templates/contactedit.html
@@ -5,11 +5,11 @@
<roundcube:include file="/includes/links.html" />
<script type="text/javascript" src="/functions.js"></script>
</head>
-<body class="iframe" onload="rcube_init_mail_ui()">
+<body class="iframe">
<div id="contact-title" class="boxtitle"><roundcube:label name="editcontact" /></div>
<div id="contact-details" class="boxcontent">
-<form name="editform" method="post" action="./">
+<roundcube:form name="editform" method="post">
<roundcube:if condition="strlen(env:sourcename)" />
<div id="sourcename"><roundcube:label name="addressbook" />: <roundcube:var name="env:sourcename" /></div>
<roundcube:endif />
@@ -35,7 +35,10 @@
<roundcube:object name="photoUploadForm" id="upload-form" size="30" class="popupmenu" />
<roundcube:object name="fileDropArea" id="contactpic" />
-<script type="text/javascript">rcube_init_tabs('contacttabs')</script>
+<script type="text/javascript">
+rcube_init_tabs('contacttabs');
+rcube_init_mail_ui();
+</script>
</body>
</html>
diff --git a/skins/classic/templates/folders.html b/skins/classic/templates/folders.html
index 1ae8809ec..f86be092b 100644
--- a/skins/classic/templates/folders.html
+++ b/skins/classic/templates/folders.html
@@ -12,7 +12,7 @@
}
</style>
</head>
-<body onload="rcube_init_mail_ui()">
+<body>
<roundcube:include file="/includes/taskbar.html" />
<roundcube:include file="/includes/header.html" />
@@ -58,5 +58,9 @@
</ul>
</div>
+<script type="text/javascript">
+rcube_init_mail_ui();
+</script>
+
</body>
</html>
diff --git a/skins/classic/templates/login.html b/skins/classic/templates/login.html
index cca2bd934..2dacd48ff 100644
--- a/skins/classic/templates/login.html
+++ b/skins/classic/templates/login.html
@@ -15,7 +15,7 @@
<div class="boxtitle"><roundcube:label name="welcome" /></div>
<div class="boxcontent">
-<form name="form" action="./" method="post">
+<roundcube:form name="form" method="post">
<roundcube:object name="loginform" form="form" />
<p style="text-align:center;"><input type="submit" class="button mainaction" value="<roundcube:label name='login' />" /></p>
diff --git a/skins/classic/templates/mail.html b/skins/classic/templates/mail.html
index c7010e87c..10aebc96d 100644
--- a/skins/classic/templates/mail.html
+++ b/skins/classic/templates/mail.html
@@ -18,7 +18,7 @@
}
</style>
</head>
-<body onload="rcube_init_mail_ui()">
+<body>
<roundcube:include file="/includes/taskbar.html" />
<roundcube:include file="/includes/header.html" />
@@ -55,6 +55,7 @@
<div id="messagelistcontainer" class="boxlistcontent" style="top:0">
<roundcube:object name="messages"
id="messagelist"
+ class="messagelist fixedheader"
cellspacing="0"
columns=""
summary="Message list"
@@ -130,9 +131,9 @@
<roundcube:button command="reset-search" id="searchreset" image="/images/icons/reset.gif" title="resetsearch" width="13" height="13" />
</div>
-<div id="dragmessagemenu" class="popupmenu">
+<div id="dragmenu" class="popupmenu">
<ul>
- <li><roundcube:button command="moveto" onclick="return rcmail.drag_menu_action('moveto')" label="move" classAct="active" /></li>
+ <li><roundcube:button command="move" onclick="return rcmail.drag_menu_action('move')" label="move" classAct="active" /></li>
<li><roundcube:button command="copy" onclick="return rcmail.drag_menu_action('copy')" label="copy" classAct="active" /></li>
</ul>
</div>
@@ -140,7 +141,8 @@
<div id="mailboxoptionsmenu" class="popupmenu">
<ul>
<li><roundcube:button command="expunge" type="link" label="compact" classAct="active" /></li>
- <li class="separator_below"><roundcube:button command="purge" type="link" label="empty" classAct="active" /></li>
+ <li><roundcube:button command="purge" type="link" label="empty" classAct="active" /></li>
+ <li class="separator_below"><roundcube:button name="messageimport" type="link" class="active" label="importmessages" id="uploadformlink" onclick="rcmail_ui.show_popup('uploadform', true); return false" /></li>
<li><roundcube:button command="folders" task="settings" type="link" label="managefolders" classAct="active" /></li>
<roundcube:container name="mailboxoptions" id="mailboxoptionsmenu" />
</ul>
@@ -204,5 +206,11 @@
</div>
</div>
+<roundcube:object name="messageimportform" id="upload-form" attachmentFieldSize="40" class="popupmenu" />
+
+<script type="text/javascript">
+rcube_init_mail_ui();
+</script>
+
</body>
</html>
diff --git a/skins/classic/templates/message.html b/skins/classic/templates/message.html
index 11e58c711..757c0a635 100644
--- a/skins/classic/templates/message.html
+++ b/skins/classic/templates/message.html
@@ -13,10 +13,10 @@
</style>
</head>
<roundcube:if condition="env:extwin" />
-<body class="extwin" onload="rcube_init_mail_ui()">
+<body class="extwin">
<roundcube:object name="message" id="message" />
<roundcube:else />
-<body onload="rcube_init_mail_ui()">
+<body>
<roundcube:include file="/includes/taskbar.html" />
<roundcube:include file="/includes/header.html" />
@@ -81,5 +81,9 @@
</ul>
</div>
+<script type="text/javascript">
+rcube_init_mail_ui();
+</script>
+
</body>
</html>
diff --git a/skins/classic/templates/messageerror.html b/skins/classic/templates/messageerror.html
index d02508942..eb8c7e058 100644
--- a/skins/classic/templates/messageerror.html
+++ b/skins/classic/templates/messageerror.html
@@ -27,7 +27,7 @@
</style>
</head>
-<body onload="rcube_init_mail_ui()">
+<body>
<roundcube:include file="/includes/taskbar.html" />
<roundcube:include file="/includes/header.html" />
@@ -61,6 +61,10 @@
rcmail.add_onload('mailviewsplitv.init()');
</script>
+<script type="text/javascript">
+rcube_init_mail_ui();
+</script>
+
</body>
<roundcube:endif />
diff --git a/skins/classic/templates/messagepart.html b/skins/classic/templates/messagepart.html
index ce7dbe2e1..9f2215679 100644
--- a/skins/classic/templates/messagepart.html
+++ b/skins/classic/templates/messagepart.html
@@ -3,23 +3,39 @@
<head>
<title><roundcube:object name="pagetitle" /></title>
<roundcube:include file="/includes/links.html" />
+<script type="text/javascript" src="/splitter.js"></script>
+<script type="text/javascript" src="/functions.js"></script>
+<style type="text/css">
+#messagepartheader { width: <roundcube:exp expression="!empty(cookie:mailpartsplitter) ? cookie:mailpartsplitter-5 : 170" />px; }
+#messagepartcontainer { left: <roundcube:exp expression="!empty(cookie:mailpartsplitter) ? cookie:mailpartsplitter+5 : 180" />px;
+<roundcube:exp expression="browser:ie ? ('width: expression((parseInt(this.parentNode.offsetWidth)-'.(!empty(cookie:mailpartsplitter) ? cookie:mailpartsplitter+5 : 180).')+\\'px\\');') : ''" />
+}
+</style>
</head>
<body class="extwin">
+<roundcube:object name="message" id="message" />
-<roundcube:include file="/includes/header.html" />
-
-<div id="partheader">
-<roundcube:object name="messagePartControls" cellpadding="2" cellspacing="0" />
-
-<div style="position:absolute; top:2px; right:0; width:12em; text-align:right">
- [<a href="#close" class="closelink" onclick="self.close()"><roundcube:label name="close" /></a>]
+<div id="messagetoolbar">
+ <roundcube:button command="download" type="link" class="button download" classAct="button download" classSel="button downloadSel" title="download" content=" " />
+ <roundcube:button command="print" type="link" class="button print" classAct="button print" classSel="button printSel" title="print" content=" " />
+ <roundcube:container name="toolbar" id="messagetoolbar" />
</div>
-</div>
-
-<div id="messagepartcontainer">
-<roundcube:object name="messagePartFrame" id="messagepartframe" width="100%" height="100%" />
+<div id="mainscreen">
+ <div id="messagepartheader">
+ <div class="boxtitle" /><roundcube:label name="properties" /></div>
+ <div class="boxlistcontent">
+ <roundcube:object name="messagePartControls" class="records-table" cellspacing="0" />
+ </div>
+ </div>
+ <div id="messagepartcontainer">
+ <roundcube:object name="messagePartFrame" id="messagepartframe" width="100%" height="100%" />
+ </div>
</div>
+<script type="text/javascript">
+var mailpartsplit = new rcube_splitter({id:'mailpartsplitter', p1: 'messagepartheader', p2: 'messagepartcontainer', orientation: 'v', relative: true, start: 165});
+rcmail.add_onload('mailpartsplit.init()');
+</script>
</body>
</html>
diff --git a/skins/classic/templates/messagepreview.html b/skins/classic/templates/messagepreview.html
index 80dbe381a..b42a06342 100644
--- a/skins/classic/templates/messagepreview.html
+++ b/skins/classic/templates/messagepreview.html
@@ -6,7 +6,7 @@
<script type="text/javascript" src="/splitter.js"></script>
<script type="text/javascript" src="/functions.js"></script>
</head>
-<body class="iframe" onload="rcube_init_mail_ui()">
+<body class="iframe">
<div class="messageheaderbox">
<div id="messagelinks">
@@ -34,5 +34,9 @@
</ul>
</div>
+<script type="text/javascript">
+rcube_init_mail_ui();
+</script>
+
</body>
</html>
diff --git a/skins/larry/addressbook.css b/skins/larry/addressbook.css
index ff3951497..090e54c7b 100644
--- a/skins/larry/addressbook.css
+++ b/skins/larry/addressbook.css
@@ -75,10 +75,6 @@
text-overflow: ellipsis;
}
-#contacts-table .contact.readonly td {
- font-style: italic;
-}
-
#directorylist li.addressbook a {
background-position: 6px -766px;
}
@@ -131,6 +127,28 @@
left: 20px;
}
+#contacts-table .contact.readonly td {
+ font-style: italic;
+}
+
+#contacts-table td.name {
+ width: 95%;
+}
+
+#contacts-table td.action {
+ width: 24px;
+ padding: 4px;
+}
+
+#contacts-table td.action a {
+ display: block;
+ width: 16px;
+ height: 14px;
+ text-indent: -5000px;
+ overflow: hidden;
+ background: url(images/listicons.png) -2px -1180px no-repeat;
+}
+
#contacts-table .contact td.name {
background-position: 6px -1603px;
}
@@ -141,6 +159,29 @@
font-weight: bold;
}
+#contacts-table .group td.name {
+ background-position: 6px -1555px;
+}
+
+#contacts-table .group.selected td.name,
+#contacts-table .group.unfocused td.name {
+ background-position: 6px -1579px;
+ font-weight: bold;
+}
+
+#addresslist .boxtitle {
+ padding-right: 95px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+#addresslist .boxtitle a.poplink {
+ color: #004458;
+ font-size: 14px;
+ line-height: 12px;
+ text-decoration: none;
+}
+
#contact-frame {
position: absolute;
top: 0;
diff --git a/skins/larry/ie7hacks.css b/skins/larry/ie7hacks.css
index 6d7af4787..fc4713361 100644
--- a/skins/larry/ie7hacks.css
+++ b/skins/larry/ie7hacks.css
@@ -41,6 +41,7 @@ a.deletebutton,
.boxfooter .listbutton .inner,
.attachmentslist li a.delete,
.attachmentslist li a.cancelupload,
+#contacts-table td.action a,
.previewheader .iconlink,
.minimal #taskbar .button-inner {
/* workaround for text-indent which also offsets the background image */
diff --git a/skins/larry/images/buttons.png b/skins/larry/images/buttons.png
index 54bee0156..9f8f44536 100644
--- a/skins/larry/images/buttons.png
+++ b/skins/larry/images/buttons.png
Binary files differ
diff --git a/skins/larry/images/contactgroup.png b/skins/larry/images/contactgroup.png
new file mode 100644
index 000000000..8303cf02f
--- /dev/null
+++ b/skins/larry/images/contactgroup.png
Binary files differ
diff --git a/skins/larry/images/listicons.png b/skins/larry/images/listicons.png
index f4505d4fa..e4ffef660 100644
--- a/skins/larry/images/listicons.png
+++ b/skins/larry/images/listicons.png
Binary files differ
diff --git a/skins/larry/includes/header.html b/skins/larry/includes/header.html
index f2efb8e06..c8b3b26f6 100644
--- a/skins/larry/includes/header.html
+++ b/skins/larry/includes/header.html
@@ -2,7 +2,7 @@
<div id="topline">
<div class="topleft">
<roundcube:container name="topline-left" id="topline-left" />
- <roundcube:button name="about" type="link" label="about" class="about-link" onclick="UI.show_about(this);return false" />
+ <roundcube:button name="about" type="link" label="about" class="about-link" onclick="UI.show_about(this);return false" condition="!env:extwin" />
<roundcube:if condition="config:support_url" />
<a href="<roundcube:var name='config:support_url' />" target="_blank" class="support-link" id="supportlink"><roundcube:label name="support" /></a>
<roundcube:endif />
@@ -14,7 +14,7 @@
<span class="username"><roundcube:object name="username" /></span>
<roundcube:button command="logout" label="logout" class="button-logout" />
<roundcube:elseif condition="env:extwin" />
- <roundcube:button command="close" label="close" class="closelink" />
+ <roundcube:button name="close" type="link" label="close" class="closelink" onclick="self.close()" />
<roundcube:endif />
</div>
</div>
@@ -35,5 +35,3 @@
<br style="clear:both" />
</div>
-
-
diff --git a/skins/larry/mail.css b/skins/larry/mail.css
index b2f1d786a..b65b08112 100644
--- a/skins/larry/mail.css
+++ b/skins/larry/mail.css
@@ -2,7 +2,7 @@
* Roundcube webmail styles for the Email section
*
* Copyright (c) 2012, The Roundcube Dev Team
- * Screendesign by FLINT / B�ro f�r Gestaltung, bueroflint.com
+ * Screendesign by FLINT / Büro für Gestaltung, bueroflint.com
*
* The contents are subject to the Creative Commons Attribution-ShareAlike
* License. It is allowed to copy, distribute, transmit and to adapt the work
@@ -54,6 +54,10 @@
border-top: none;
}
+#composeview-right #mailview-bottom {
+ border-radius: 0 0 4px 4px;
+}
+
#folderlist-header {
width: 100%;
height: 12px;
@@ -75,6 +79,12 @@
overflow: auto;
}
+/* Real browsers accept this (not IE) */
+html>/**/body #messagelist {
+ overflow: auto;
+ overflow-x: hidden;
+}
+
#messagelistfooter {
position: absolute;
bottom: 0;
@@ -212,6 +222,46 @@ a.iconbutton.threadmode.selected {
background-position: 6px -1723px;
}
+#mailboxlist li.mailbox ul li.drafts > a {
+ background-position: 23px -238px;
+}
+
+#mailboxlist li.mailbox ul li.drafts.selected > a {
+ background-position: 23px -262px;
+}
+
+#mailboxlist li.mailbox ul li.sent > a {
+ background-position: 23px -286px;
+}
+
+#mailboxlist li.mailbox ul li.sent.selected > a {
+ background-position: 23px -310px;
+}
+
+#mailboxlist li.mailbox ul li.junk > a {
+ background-position: 23px -334px;
+}
+
+#mailboxlist li.mailbox ul li.junk.selected > a {
+ background-position: 23px -358px;
+}
+
+#mailboxlist li.mailbox ul li.trash > a {
+ background-position: 23px -382px;
+}
+
+#mailboxlist li.mailbox ul li.trash.selected > a {
+ background-position: 23px -406px;
+}
+
+#mailboxlist li.mailbox ul li.archive > a {
+ background-position: 23px -1699px;
+}
+
+#mailboxlist li.mailbox ul li.archive.selected > a {
+ background-position: 23px -1723px;
+}
+
#mailboxlist li.unread {
font-weight: bold;
}
@@ -384,7 +434,6 @@ a.iconbutton.threadmode.selected {
position: absolute;
right: 0;
top: 0;
- width: 400px;
}
#mailpreviewtoggle {
@@ -404,141 +453,154 @@ a.iconbutton.threadmode.selected {
/*** message list ***/
-#messagelist thead td:first-child {
+/* this is necessary to make FF3 display borders */
+body:-moz-last-node #messagelist {
+ border-collapse: separate;
+}
+
+table.messagelist {
+ z-index: 1;
+}
+
+table.messagelist.fixedcopy {
+ z-index: 2;
+}
+
+.messagelist thead td:first-child {
border-radius: 4px 0 0 0; /* for Chrome */
}
-#messagelist tr td.attachment,
-#messagelist tr td.threads,
-#messagelist tr td.status,
-#messagelist tr td.flag,
-#messagelist tr td.priority {
+.messagelist tr td.attachment,
+.messagelist tr td.threads,
+.messagelist tr td.status,
+.messagelist tr td.flag,
+.messagelist tr td.priority {
width: 20px;
padding: 2px 3px;
}
-.webkit #messagelist tr td.attachment,
-.webkit #messagelist tr td.threads,
-.webkit #messagelist tr td.status,
-.webkit #messagelist tr td.flag,
-.webkit #messagelist tr td.priority {
+.webkit .messagelist tr td.attachment,
+.webkit .messagelist tr td.threads,
+.webkit .messagelist tr td.status,
+.webkit .messagelist tr td.flag,
+.webkit .messagelist tr td.priority {
width: 26px;
}
-#messagelist tr td.threads {
+.messagelist tr td.threads {
width: 26px;
}
-.webkit #messagelist tr td.threads {
+.webkit .messagelist tr td.threads {
width: 30px;
}
-#messagelist tr td.threads,
-#messagelist tr td.threads + td {
+.messagelist tr td.threads,
+.messagelist tr td.threads + td {
border-left: 0;
}
-#messagelist tr td.size {
+.messagelist tr td.size {
width: 60px;
text-align: right;
}
-#messagelist thead tr td.size {
+.messagelist thead tr td.size {
text-align: left;
}
-#messagelist tr td.fromto,
-#messagelist tr td.from,
-#messagelist tr td.to,
-#messagelist tr td.cc,
-#messagelist tr td.replyto {
+.messagelist tr td.fromto,
+.messagelist tr td.from,
+.messagelist tr td.to,
+.messagelist tr td.cc,
+.messagelist tr td.replyto {
width: 200px;
}
-#messagelist tr td.date {
+.messagelist tr td.date {
width: 135px;
}
-#messagelist tr.message {
+.messagelist tr.message {
/* background-color: #fff; */
}
-#messagelist tr.thread.expanded td {
+.messagelist tr.thread.expanded td {
background-color: #ededed;
}
-#messagelist tr.unread {
+.messagelist tr.unread {
font-weight: bold;
/* background-color: #fff; */
}
-#messagelist tr.flagged td,
-#messagelist tr.flagged td a {
+.messagelist tr.flagged td,
+.messagelist tr.flagged td a {
color: #f30;
}
-#messagelist thead tr td.sortedASC a,
-#messagelist thead tr td.sortedDESC a {
+.messagelist thead tr td.sortedASC a,
+.messagelist thead tr td.sortedDESC a {
color: #004458;
text-decoration: underline;
background: url(images/listicons.png) right -912px no-repeat;
}
-#messagelist thead tr td.sortedASC a {
+.messagelist thead tr td.sortedASC a {
background-position: right -944px;
}
-#messagelist td img {
+.messagelist td img {
vertical-align: middle;
display: inline-block;
}
-#messagelist tbody td a {
+.messagelist tbody td a {
color: #333;
text-decoration: none;
white-space: nowrap;
cursor: default;
}
-#messagelist tbody tr td.flag,
-#messagelist tbody tr td.status,
-#messagelist tbody tr td.subject span.status {
+.messagelist tbody tr td.flag,
+.messagelist tbody tr td.status,
+.messagelist tbody tr td.subject span.status {
cursor: pointer;
}
-#messagelist tr td.flag span,
-#messagelist tr td.status span,
-#messagelist tr td.attachment span,
-#messagelist tr td.priority span {
+.messagelist tr td.flag span,
+.messagelist tr td.status span,
+.messagelist tr td.attachment span,
+.messagelist tr td.priority span {
display: block;
width: 20px;
}
-#messagelist tr td div.collapsed,
-#messagelist tr td div.expanded,
-#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.status span.status,
-#messagelist tr td.status span.msgicon,
-#messagelist tr td.status span.deleted,
-#messagelist tr td.status span.unread,
-#messagelist tr td.status span.unreadchildren,
-#messagelist tr td.subject span.msgicon,
-#messagelist tr td.subject span.deleted,
-#messagelist tr td.subject span.unread,
-#messagelist tr td.subject span.replied,
-#messagelist tr td.subject span.forwarded,
-#messagelist tr td.subject span.unreadchildren {
+.messagelist tr td div.collapsed,
+.messagelist tr td div.expanded,
+.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.status span.status,
+.messagelist tr td.status span.msgicon,
+.messagelist tr td.status span.deleted,
+.messagelist tr td.status span.unread,
+.messagelist tr td.status span.unreadchildren,
+.messagelist tr td.subject span.msgicon,
+.messagelist tr td.subject span.deleted,
+.messagelist tr td.subject span.unread,
+.messagelist tr td.subject span.replied,
+.messagelist tr td.subject span.forwarded,
+.messagelist tr td.subject span.unreadchildren {
display: inline-block;
vertical-align: middle;
height: 18px;
@@ -547,135 +609,135 @@ a.iconbutton.threadmode.selected {
background: url(images/listicons.png) -100px 0 no-repeat;
}
-#messagelist tbody tr td.attachment span.attachment {
+.messagelist tbody tr td.attachment span.attachment {
background-position: 0 -996px;
}
-#messagelist thead tr td.attachment span.attachment {
+.messagelist thead tr td.attachment span.attachment {
background-position: -24px -997px;
}
-#messagelist tbody tr td.attachment span.report {
+.messagelist tbody tr td.attachment span.report {
background-position: -24px -1116px;
}
-#messagelist tr td.priority span.prio5 {
+.messagelist tr td.priority span.prio5 {
background-position: 0 -1905px;
}
-#messagelist tr td.priority span.prio4 {
+.messagelist tr td.priority span.prio4 {
background-position: 0 -1885px;
}
-#messagelist tr td.priority span.prio2 {
+.messagelist tr td.priority span.prio2 {
background-position: 0 -1865px;
}
-#messagelist tr td.priority span.prio1 {
+.messagelist tr td.priority span.prio1 {
background-position: 0 -1845px;
}
-#messagelist tbody tr td.flag span.flagged {
+.messagelist tbody tr td.flag span.flagged {
background-position: 0 -1036px;
}
-#messagelist thead tr td.flag span.flagged {
+.messagelist thead tr td.flag span.flagged {
background-position: -24px -1036px;
}
-#messagelist tr td.status span.msgicon:hover {
+.messagelist tr td.status span.msgicon:hover {
background-position: -23px -1056px;
}
-#messagelist tr td.flag span.unflagged:hover {
+.messagelist tr td.flag span.unflagged:hover {
background-position: -23px -1076px;
}
-#messagelist tr td.subject span.msgicon,
-#messagelist tr td.subject span.unreadchildren {
+.messagelist tr td.subject span.msgicon,
+.messagelist tr td.subject span.unreadchildren {
background-position: 0 -1056px;
margin: 0 1px 0 0;
width: 24px;
}
-#messagelist tr td.subject span.replied {
+.messagelist tr td.subject span.replied {
background-position: 0 -1076px;
}
-#messagelist tr td.subject span.forwarded {
+.messagelist tr td.subject span.forwarded {
background-position: 0 -1096px;
}
-#messagelist tr td.subject span.replied.forwarded {
+.messagelist tr td.subject span.replied.forwarded {
background-position: 0 -1116px;
}
-#messagelist tr td.status span.msgicon,
-#messagelist tr td.flag span.unflagged,
-#messagelist tr td.status span.unreadchildren {
+.messagelist tr td.status span.msgicon,
+.messagelist tr td.flag span.unflagged,
+.messagelist tr td.status span.unreadchildren {
background-position: 0 1056px; /* no icon */
}
/*
-#messagelist tr td.status span.msgicon:hover {
+.messagelist tr td.status span.msgicon:hover {
background-position: 0 -272px;
}
*/
-#messagelist tr td.status span.deleted,
-#messagelist tr td.status span.deleted:hover,
-#messagelist tr td.subject span.deleted {
+.messagelist tr td.status span.deleted,
+.messagelist tr td.status span.deleted:hover,
+.messagelist tr td.subject span.deleted {
background-position: -22px -1096px;
}
-#messagelist tr td.status span.status,
-#messagelist tr td.status span.unread,
-#messagelist tr td.subject span.unread,
-#messagelist tr td.status span.unread:hover {
+.messagelist tr td.status span.status,
+.messagelist tr td.status span.unread,
+.messagelist tr td.subject span.unread,
+.messagelist tr td.status span.unread:hover {
background-position: 0 -1016px;
}
-#messagelist thead tr td.status span.status {
+.messagelist thead tr td.status span.status {
background-position: -24px -1016px;
}
-#messagelist tr td div.collapsed {
+.messagelist tr td div.collapsed {
background-position: 0 -1137px;
cursor: pointer;
}
-#messagelist tr td div.expanded {
+.messagelist tr td div.expanded {
background-position: 0 -1157px;
cursor: pointer;
}
-#messagelist tr td.threads div.listmenu {
+.messagelist tr td.threads div.listmenu {
background-position: 0 -976px;
cursor: pointer;
width: 26px;
}
-#messagelist thead tr td.subject,
-#messagelist tbody tr td.subject {
+.messagelist thead tr td.subject,
+.messagelist tbody tr td.subject {
width: 99%;
white-space: nowrap;
}
-#messagelist tbody tr td.subject a {
+.messagelist tbody tr td.subject a {
cursor: default;
vertical-align: middle; /* #1487091 */
}
/* thread parent message with unread children */
-#messagelist tbody tr.unroot td.subject a {
+.messagelist tbody tr.unroot td.subject a {
text-decoration: underline;
}
/**** tree indicators ****/
-#messagelist tbody tr td span.branch div {
+.messagelist tbody tr td span.branch div {
display: inline-block;
}
-#messagelist tbody tr td span.branch div.tree {
+.messagelist tbody tr td span.branch div.tree {
width: 15px;
}
@@ -709,7 +771,6 @@ a.iconbutton.threadmode.selected {
}
#messageheader,
-#partheader,
#composeheaders {
position: relative;
padding: 3px 0;
@@ -931,6 +992,10 @@ div.hide-headers {
border-radius: 3px;
}
+#messageheader .message-headers {
+ min-height: 60px;
+}
+
#messageheader #contactphoto {
display: block;
position: absolute;
@@ -1140,8 +1205,8 @@ div.message-partheaders .headers-table td.header {
#messagepartcontainer {
position: absolute;
- top: 60px;
- left: 0;
+ top: 42px;
+ left: 232px;
right: 0;
bottom: 0;
}
@@ -1152,6 +1217,30 @@ div.message-partheaders .headers-table td.header {
height: 100%;
}
+#messagepartheader {
+ position: absolute;
+ top: 42px;
+ left: 0;
+ width: 220px;
+ bottom: 0;
+}
+
+#messagepartheader table {
+ table-layout: fixed;
+ overflow: hidden;
+}
+
+#messagepartheader table td {
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+
+#messagepartheader table td.title {
+ width: 60px;
+ padding-right: 0;
+}
+
+
/*** message composition ***/
#composeview-left {
@@ -1230,6 +1319,19 @@ div.message-partheaders .headers-table td.header {
text-overflow: ellipsis;
}
+#contacts-table td.contactgroup a {
+ color: #376572;
+ text-decoration: none;
+}
+
+#contacts-table td.contactgroup a span {
+ display: inline-block;
+ font-size: 16px;
+ font-weight: bold;
+ line-height: 11px;
+ margin-left: 0.3em;
+}
+
#contacts-table tr:first-child td {
border-top: 0;
}
diff --git a/skins/larry/print.css b/skins/larry/print.css
index 6481ea9e6..a56c9b938 100644
--- a/skins/larry/print.css
+++ b/skins/larry/print.css
@@ -123,3 +123,28 @@ div.message-part blockquote blockquote blockquote {
border-left: 2px solid #b00;
border-right: 2px solid #b00;
}
+
+p.image-attachment {
+ position: relative;
+ padding: 1em;
+ border-top: 1px solid #ccc;
+}
+
+p.image-attachment a.image-link {
+ float: left;
+ display: block;
+ margin-right: 2em;
+ min-width: 160px;
+ min-height: 60px;
+ text-align: center;
+}
+
+p.image-attachment .image-filename {
+ display: block;
+ line-height: 1.6em;
+}
+
+p.image-attachment .attachment-links {
+ display: none;
+}
+
diff --git a/skins/larry/settings.css b/skins/larry/settings.css
index 1734b55e5..59037ac76 100644
--- a/skins/larry/settings.css
+++ b/skins/larry/settings.css
@@ -267,3 +267,13 @@ img.skinthumbnail {
.webkit #pluginlist td.source {
width: 9em;
}
+
+#rcmfd_signature {
+ width: 99%;
+ min-width: 390px;
+}
+
+#rcmfd_signature_toolbar1 td,
+#rcmfd_signature_toolbar2 td {
+ width: auto;
+}
diff --git a/skins/larry/styles.css b/skins/larry/styles.css
index cfbf9ac5f..ec4f3047c 100644
--- a/skins/larry/styles.css
+++ b/skins/larry/styles.css
@@ -690,17 +690,6 @@ a.iconlink.upload {
opacity: 0.999;
}
-.partwin #topline {
- position: absolute;
- right: 6px;
- top: 18px;
- width: auto;
- z-index: 100;
- background: transparent;
- background: none;
- border: 0;
-}
-
.minimal #topline a.button-logout {
display: none;
}
@@ -883,10 +872,6 @@ a.iconlink.upload {
top: 102px;
}
-.partwin #mainscreen {
- top: 60px
-}
-
.extwin #mainscreen {
top: 40px;
}
@@ -896,7 +881,7 @@ a.iconlink.upload {
}
#mainscreen .offset {
- margin-top: 42px;
+ top: 42px;
}
.uibox {
@@ -1059,6 +1044,10 @@ table.listing tr.droptarget td {
background-color: #e8e798;
}
+.listbox table.listing {
+ background-color: #d9ecf4;
+}
+
table.listing,
table.layout {
border: 0;
@@ -1813,6 +1802,10 @@ ul.proplist li {
background-position: 0 -1745px;
}
+.toolbar a.button.download {
+ background-position: center -1906px;
+}
+
a.menuselector {
display: inline-block;
border: 1px solid #ababab;
@@ -1858,6 +1851,7 @@ select.decorated {
filter: alpha(opacity=0);
-khtml-appearance: none;
-webkit-appearance: none;
+ border: 0;
}
html.opera select.decorated {
@@ -1873,6 +1867,7 @@ select.decorated option {
text-shadow: 0px 1px 1px #333;
padding: 4px 6px;
outline: none;
+ cursor: default;
}
diff --git a/skins/larry/templates/about.html b/skins/larry/templates/about.html
index 301c301a9..e2bd0b019 100644
--- a/skins/larry/templates/about.html
+++ b/skins/larry/templates/about.html
@@ -4,7 +4,11 @@
<title><roundcube:object name="pagetitle" /></title>
<roundcube:include file="/includes/links.html" />
</head>
+<roundcube:if condition="request:_framed" />
+<body class="iframe fullheight">
+<roundcube:else />
<body class="ui-widget-content">
+<roundcube:endif />
<div class="readtext">
<roundcube:object name="aboutcontent" />
diff --git a/skins/larry/templates/addressbook.html b/skins/larry/templates/addressbook.html
index 401640f1f..b33ebd999 100644
--- a/skins/larry/templates/addressbook.html
+++ b/skins/larry/templates/addressbook.html
@@ -50,7 +50,7 @@
<!-- contacts list -->
<div id="addresslist" class="uibox listbox">
-<h2 class="boxtitle"><roundcube:label name="contacts" /></h2>
+<roundcube:object name="addresslisttitle" label="contacts" tag="h2" class="boxtitle" />
<div class="scroller withfooter">
<roundcube:object name="addresslist" id="contacts-table" class="listing" noheader="true" />
</div>
@@ -106,6 +106,13 @@
</ul>
</div>
+<div id="dragcontactmenu" class="popupmenu">
+ <ul class="toolbarmenu">
+ <li><roundcube:button command="move" onclick="return rcmail.drag_menu_action('move')" label="move" classAct="active" /></li>
+ <li><roundcube:button command="copy" onclick="return rcmail.drag_menu_action('copy')" label="copy" classAct="active" /></li>
+ </ul>
+</div>
+
<roundcube:include file="/includes/footer.html" />
</body>
diff --git a/skins/larry/templates/compose.html b/skins/larry/templates/compose.html
index 9cfe7fe4c..09eafe73b 100644
--- a/skins/larry/templates/compose.html
+++ b/skins/larry/templates/compose.html
@@ -65,7 +65,7 @@
<div id="composeview-right">
-<form name="form" action="./" method="post" id="compose-content" class="uibox">
+<roundcube:form name="form" method="post" id="compose-content" class="uibox">
<!-- message headers -->
<div id="composeheaders">
diff --git a/skins/larry/templates/contact.html b/skins/larry/templates/contact.html
index d252049cd..59fe6f79f 100644
--- a/skins/larry/templates/contact.html
+++ b/skins/larry/templates/contact.html
@@ -13,7 +13,7 @@
<div id="sourcename"><roundcube:label name="addressbook" />: <roundcube:var name="env:sourcename" /></div>
<roundcube:endif />
- <div id="contactphoto"><roundcube:object name="contactphoto" id="contactpic" placeholder="/images/contactpic.png" /></div>
+ <div id="contactphoto"><roundcube:object name="contactphoto" id="contactpic" placeholder="/images/contactpic.png" placeholderGroup="/images/contactgroup.png" /></div>
<roundcube:object name="contacthead" id="contacthead" />
<br style="clear:both" />
diff --git a/skins/larry/templates/contactedit.html b/skins/larry/templates/contactedit.html
index f84936635..3467ebe8e 100644
--- a/skins/larry/templates/contactedit.html
+++ b/skins/larry/templates/contactedit.html
@@ -11,7 +11,7 @@
<roundcube:else /><roundcube:label name="editcontact" />
<roundcube:endif /></h1>
-<form name="editform" method="post" action="./" id="contact-details" class="boxcontent">
+<roundcube:form name="editform" method="post" id="contact-details" class="boxcontent">
<roundcube:if condition="strlen(env:sourcename)" />
<div id="sourcename"><roundcube:label name="addressbook" />: <roundcube:var name="env:sourcename" condition="env:action!='add'" /><roundcube:object name="sourceselector" id="sourceselect" condition="env:action=='add'" /></div>
<roundcube:endif />
diff --git a/skins/larry/templates/login.html b/skins/larry/templates/login.html
index a605eb7fe..6e56ee2fd 100644
--- a/skins/larry/templates/login.html
+++ b/skins/larry/templates/login.html
@@ -11,7 +11,7 @@
<div class="box-inner">
<roundcube:object name="logo" src="/images/roundcube_logo.png" id="logo" border="0" />
-<form name="form" action="./" method="post">
+<roundcube:form name="form" method="post">
<roundcube:object name="loginform" form="form" size="40" />
<p class="formbuttons"><input type="submit" class="button mainaction" value="<roundcube:label name='login' />" /></p>
diff --git a/skins/larry/templates/mail.html b/skins/larry/templates/mail.html
index 85cd5203b..6015054d3 100644
--- a/skins/larry/templates/mail.html
+++ b/skins/larry/templates/mail.html
@@ -70,7 +70,7 @@
<div id="messagelistcontainer" class="boxlistcontent">
<roundcube:object name="messages"
id="messagelist"
- class="records-table sortheader"
+ class="records-table messagelist sortheader fixedheader"
optionsmenuIcon="true" />
</div>
@@ -140,7 +140,7 @@
<div id="dragmessagemenu" class="popupmenu">
<ul class="toolbarmenu">
- <li><roundcube:button command="moveto" onclick="return rcmail.drag_menu_action('moveto')" label="move" classAct="active" /></li>
+ <li><roundcube:button command="move" onclick="return rcmail.drag_menu_action('move')" label="move" classAct="active" /></li>
<li><roundcube:button command="copy" onclick="return rcmail.drag_menu_action('copy')" label="copy" classAct="active" /></li>
</ul>
</div>
@@ -148,7 +148,8 @@
<div id="mailboxmenu" class="popupmenu">
<ul class="toolbarmenu" id="mailboxoptionsmenu">
<li><roundcube:button command="expunge" type="link" label="compact" classAct="active" /></li>
- <li class="separator_below"><roundcube:button command="purge" type="link" label="empty" classAct="active" /></li>
+ <li><roundcube:button command="purge" type="link" label="empty" classAct="active" /></li>
+ <li><roundcube:button name="messageimport" type="link" class="active" label="importmessages" onclick="UI.show_uploadform()" /></li>
<li><roundcube:button command="folders" task="settings" type="link" label="managefolders" classAct="active" /></li>
<roundcube:container name="mailboxoptions" id="mailboxoptionsmenu" />
</ul>
@@ -226,6 +227,14 @@
</div>
</div>
+<div id="upload-dialog" class="propform popupdialog" title="<roundcube:label name='importmessages' />">
+ <roundcube:object name="messageimportform" id="uploadform" attachmentFieldSize="40" buttons="no" />
+ <div class="formbuttons">
+ <roundcube:button command="import-messages" type="input" class="button mainaction" label="upload" />
+ <roundcube:button name="close" type="input" class="button" label="cancel" onclick="UI.show_uploadform()" />
+ </div>
+</div>
+
<roundcube:include file="/includes/footer.html" />
</body>
diff --git a/skins/larry/templates/message.html b/skins/larry/templates/message.html
index ba8fc0f29..6937b00af 100644
--- a/skins/larry/templates/message.html
+++ b/skins/larry/templates/message.html
@@ -17,7 +17,7 @@
<roundcube:endif />
<roundcube:include file="/includes/mailtoolbar.html" />
<div class="toolbarselect">
- <roundcube:object name="mailboxlist" type="select" noSelection="moveto" maxlength="25" onchange="rcmail.command('moveto', this.options[this.selectedIndex].value)" class="mailboxlist decorated" folder_filter="mail" />
+ <roundcube:object name="mailboxlist" type="select" noSelection="moveto" maxlength="25" onchange="rcmail.command('move', this.options[this.selectedIndex].value)" class="mailboxlist decorated" folder_filter="mail" />
</div>
</div>
@@ -44,7 +44,9 @@
<span class="moreheaderstoggle"></span>
<h2 class="subject"><roundcube:object name="messageHeaders" valueOf="subject" /></h2>
+<div class="message-headers">
<roundcube:object name="messageHeaders" class="headers-table" addicon="/images/addcontact.png" exclude="subject" max="20" />
+</div>
<roundcube:object name="messageFullHeaders" id="full-headers" />
<!-- record navigation -->
diff --git a/skins/larry/templates/messagepart.html b/skins/larry/templates/messagepart.html
index dbb4940de..d0e3a808d 100644
--- a/skins/larry/templates/messagepart.html
+++ b/skins/larry/templates/messagepart.html
@@ -4,33 +4,35 @@
<title><roundcube:object name="pagetitle" /></title>
<roundcube:include file="/includes/links.html" />
</head>
-<body class="partwin">
+<body class="extwin noscroll">
-<div id="header">
-<div id="topline">
- <div class="topright">
- <a href="#close" class="closelink" onclick="self.close()"><roundcube:label name="close" /></a>
- </div>
-</div>
+<roundcube:include file="/includes/header.html" />
-<div id="topnav">
- <roundcube:object name="logo" src="/images/roundcube_logo.png" id="toplogo" border="0" alt="Logo" />
-</div>
+<div id="mainscreen">
-<br style="clear:both" />
+<div id="messagetoolbar" class="toolbar fullwidth">
+ <roundcube:button command="download" type="link" class="button download disabled" classAct="button download" classSel="button download pressed" label="download" />
+ <roundcube:button command="print" type="link" class="button print disabled" classAct="button print" classSel="button print pressed" label="print" />
+ <roundcube:container name="toolbar" id="messagetoolbar" />
</div>
-<div id="mainscreen">
-
-<div id="partheader" class="uibox">
-<roundcube:object name="messagePartControls" class="headers-table" />
+<div id="messagepartheader" class="uibox listbox">
+ <h2 class="boxtitle"><roundcube:label name="properties" /></h2>
+ <div class="scroller">
+ <roundcube:object name="messagePartControls" class="listing" />
+ </div>
</div>
<div id="messagepartcontainer" class="uibox">
-<roundcube:object name="messagePartFrame" id="messagepartframe" frameborder="0" />
+ <div class="iframebox">
+ <roundcube:object name="messagePartFrame" id="messagepartframe" frameborder="0" />
+ </div>
+ <roundcube:object name="message" id="message" class="statusbar" />
</div>
</div>
+<roundcube:include file="/includes/footer.html" />
+
</body>
</html>
diff --git a/skins/larry/ui.js b/skins/larry/ui.js
index 693448097..e5733bd23 100644
--- a/skins/larry/ui.js
+++ b/skins/larry/ui.js
@@ -19,7 +19,7 @@ function rcube_mail_ui()
searchmenu: { editable:1, callback:searchmenu },
attachmentmenu: { },
listoptions: { editable:1 },
- dragmessagemenu: { sticky:1 },
+ dragmenu: { sticky:1 },
groupmenu: { above:1 },
mailboxmenu: { above:1 },
spellmenu: { callback: spellmenu },
@@ -43,6 +43,7 @@ function rcube_mail_ui()
this.show_uploadform = show_uploadform;
this.show_header_row = show_header_row;
this.hide_header_row = hide_header_row;
+ this.update_quota = update_quota;
// set minimal mode on small screens (don't wait for document.ready)
@@ -89,8 +90,8 @@ function rcube_mail_ui()
var dragmenu = $('#dragmessagemenu');
if (dragmenu.length) {
- rcmail.gui_object('message_dragmenu', 'dragmessagemenu');
- popups.dragmessagemenu = dragmenu;
+ rcmail.gui_object('dragmenu', 'dragmessagemenu');
+ popups.dragmenu = dragmenu;
}
if (rcmail.env.action == 'show' || rcmail.env.action == 'preview') {
@@ -111,10 +112,14 @@ function rcube_mail_ui()
layout_composeview();
// Show input elements with non-empty value
- var field, fields = ['cc', 'bcc', 'replyto', 'followupto'];
- for (var f=0; f < fields.length; f++) {
- if ((field = $('#_'+fields[f])) && field.length && field.val() != '')
- show_header_row(fields[f], true);
+ var f, v, field, fields = ['cc', 'bcc', 'replyto', 'followupto'];
+ for (f=0; f < fields.length; f++) {
+ v = fields[f]; field = $('#_'+v);
+ if (field.length) {
+ field.on('change', {v: v}, function(e) { if (this.value) show_header_row(e.data.v, true); });
+ if (field.val() != '')
+ show_header_row(v, true);
+ }
}
$('#composeoptionstoggle').click(function(){
@@ -147,6 +152,11 @@ function rcube_mail_ui()
rcmail.addEventListener('setquota', update_quota);
rcmail.addEventListener('enable-command', enable_command);
+ rcmail.addEventListener('afterimport-messages', show_uploadform);
+ }
+ else if (rcmail.env.action == 'get') {
+ new rcube_splitter({ id:'mailpartsplitterv', p1:'#messagepartheader', p2:'#messagepartcontainer',
+ orientation:'v', relative:true, start:226, min:150, size:12}).init();
}
if ($('#mailview-left').length) {
@@ -185,6 +195,8 @@ function rcube_mail_ui()
/*** addressbook task ***/
else if (rcmail.env.task == 'addressbook') {
rcmail.addEventListener('afterupload-photo', show_uploadform);
+ rcmail.addEventListener('beforepushgroup', push_contactgroup);
+ rcmail.addEventListener('beforepopgroup', pop_contactgroup);
if (rcmail.env.action == '') {
new rcube_splitter({ id:'addressviewsplitterd', p1:'#addressview-left', p2:'#addressview-right',
@@ -194,12 +206,12 @@ function rcube_mail_ui()
new rcube_scroller('#directorylist-content', '#directorylist-header', '#directorylist-footer');
}
- }
- // set min-width to show all toolbar buttons
- var screen = $('.minwidth');
- if (screen.length) {
- screen.css('min-width', $('.toolbar').width() + $('#quicksearchbar').parent().width() + 20);
+ var dragmenu = $('#dragcontactmenu');
+ if (dragmenu.length) {
+ rcmail.gui_object('dragmenu', 'dragcontactmenu');
+ popups.dragmenu = dragmenu;
+ }
}
// turn a group of fieldsets into tabs
@@ -213,6 +225,7 @@ function rcube_mail_ui()
}
var select = $(this),
+ parent = select.parent(),
height = Math.max(select.height(), 26) - 2,
width = select.width() - 22,
title = $('option', this).first().text();
@@ -227,19 +240,23 @@ function rcube_mail_ui()
overlay.children().width(width).height(height).css('line-height', (height - 1) + 'px');
- select.change(function() {
- var val = $('option:selected', this).text();
- $(this).next().children().html(val);
- });
-
- var parent = select.parent();
if (parent.css('position') != 'absolute')
parent.css('position', 'relative');
// re-set original select width to fix click action and options width in some browsers
- select.width(overlay.width());
+ select.width(overlay.width())
+ .change(function() {
+ var val = $('option:selected', this).text();
+ $(this).next().children().text(val);
+ });
});
+ // set min-width to show all toolbar buttons
+ var screen = $('body > div.minwidth');
+ if (screen.length) {
+ screen.css('min-width', $('.toolbar').width() + $('#quicksearchbar').width() + $('#searchfilter').width() + 30);
+ }
+
$(document.body)
.bind('mouseup', body_mouseup)
.bind('keyup', function(e){
@@ -583,8 +600,11 @@ function rcube_mail_ui()
mailviewsplit.handle.hide();
}
- if (visible && uid && rcmail.message_list)
- rcmail.message_list.scrollto(uid);
+ if (rcmail.message_list) {
+ if (visible && uid)
+ rcmail.message_list.scrollto(uid);
+ rcmail.message_list.resize();
+ }
rcmail.command('save-pref', { name:'preview_pane', value:(visible?1:0) });
}
@@ -734,8 +754,6 @@ function rcube_mail_ui()
$('input[name="sort_col"][value="'+rcmail.env.sort_col+'"]').prop('checked', true);
$('input[name="sort_ord"][value="DESC"]').prop('checked', rcmail.env.sort_order == 'DESC');
$('input[name="sort_ord"][value="ASC"]').prop('checked', rcmail.env.sort_order != 'DESC');
- $('input[name="view"][value="thread"]').prop('checked', rcmail.env.threading ? true : false);
- $('input[name="view"][value="list"]').prop('checked', rcmail.env.threading ? false : true);
// set checkboxes
$('input[name="list_col[]"]').each(function() {
@@ -750,7 +768,8 @@ function rcube_mail_ui()
close: function() {
$dialog.dialog('destroy').hide();
},
- width: 650
+ minWidth: 500,
+ width: $dialog.width()+25
}).show();
}
@@ -764,11 +783,10 @@ function rcube_mail_ui()
var sort = $('input[name="sort_col"]:checked').val(),
ord = $('input[name="sort_ord"]:checked').val(),
- thread = $('input[name="view"]:checked').val(),
cols = $('input[name="list_col[]"]:checked')
.map(function(){ return this.value; }).get();
- rcmail.set_list_options(cols, sort, ord, thread == 'thread' ? 1 : 0);
+ rcmail.set_list_options(cols, sort, ord, rcmail.env.threading);
}
@@ -820,6 +838,35 @@ function rcube_mail_ui()
});
}
+ function push_contactgroup(p)
+ {
+ // lets the contacts list swipe to the left, nice!
+ var table = $('#contacts-table'),
+ scroller = table.parent().css('overflow', 'hidden');
+
+ table.clone()
+ .css({ position:'absolute', top:'0', left:'0', width:table.width()+'px', 'z-index':10 })
+ .appendTo(scroller)
+ .animate({ left: -(table.width()+5) + 'px' }, 300, 'swing', function(){
+ $(this).remove();
+ scroller.css('overflow', 'auto')
+ });
+ }
+
+ function pop_contactgroup(p)
+ {
+ // lets the contacts list swipe to the left, nice!
+ var table = $('#contacts-table'),
+ scroller = table.parent().css('overflow', 'hidden'),
+ clone = table.clone().appendTo(scroller);
+
+ table.css({ position:'absolute', top:'0', left:-(table.width()+5) + 'px', width:table.width()+'px', height:table.height()+'px', 'z-index':10 })
+ .animate({ left:'0' }, 300, 'linear', function(){
+ clone.remove();
+ $(this).css({ position:'relative', left:'0', width:'100%', height:'auto', 'z-index':1 });
+ scroller.css('overflow', 'auto')
+ });
+ }
function show_uploadform()
{
@@ -830,7 +877,7 @@ function rcube_mail_ui()
$dialog.dialog('close');
return;
}
-
+
// add icons to clone file input field
if (rcmail.env.action == 'compose' && !$dialog.data('extended')) {
$('<a>')
diff --git a/tests/Framework/ImapGeneric.php b/tests/Framework/ImapGeneric.php
index 2f9b6d10f..af73158e5 100644
--- a/tests/Framework/ImapGeneric.php
+++ b/tests/Framework/ImapGeneric.php
@@ -35,4 +35,27 @@ class Framework_ImapGeneric extends PHPUnit_Framework_TestCase
$this->assertSame(array(1, 2, 3), $result);
$this->assertCount(3, $result);
}
+
+ /**
+ * Test for tokenizeResponse
+ */
+ function test_tokenizeResponse()
+ {
+ $response = "test brack[et] {1}\r\na {0}\r\n (item1 item2)";
+
+ $result = rcube_imap_generic::tokenizeResponse($response, 1);
+ $this->assertSame("test", $result);
+
+ $result = rcube_imap_generic::tokenizeResponse($response, 1);
+ $this->assertSame("brack[et]", $result);
+
+ $result = rcube_imap_generic::tokenizeResponse($response, 1);
+ $this->assertSame("a", $result);
+
+ $result = rcube_imap_generic::tokenizeResponse($response, 1);
+ $this->assertSame("", $result);
+
+ $result = rcube_imap_generic::tokenizeResponse($response, 1);
+ $this->assertSame(array('item1', 'item2'), $result);
+ }
}
diff --git a/tests/Framework/Utils.php b/tests/Framework/Utils.php
index 7c1e92ac8..abfb7cb65 100644
--- a/tests/Framework/Utils.php
+++ b/tests/Framework/Utils.php
@@ -195,6 +195,23 @@ class Framework_Utils extends PHPUnit_Framework_TestCase
}
/**
+ * Check rcube_utils::explode_quoted_string()
+ */
+ function test_explode_quoted_string()
+ {
+ $data = array(
+ '"a,b"' => array('"a,b"'),
+ '"a,b","c,d"' => array('"a,b"','"c,d"'),
+ '"a,\\"b",d' => array('"a,\\"b"', 'd'),
+ );
+
+ foreach ($data as $text => $res) {
+ $result = rcube_utils::explode_quoted_string(',', $text);
+ $this->assertSame($res, $result);
+ }
+ }
+
+ /**
* Check rcube_utils::explode_quoted_string() compat. with explode()
*/
function test_explode_quoted_string_compat()
@@ -229,4 +246,52 @@ class Framework_Utils extends PHPUnit_Framework_TestCase
}
}
+ /**
+ * rcube:utils::file2class()
+ */
+ function test_file2class()
+ {
+ $test = array(
+ array('', '', 'unknown'),
+ array('text', 'text', 'text'),
+ array('image/png', 'image.png', 'image png'),
+ );
+
+ foreach ($test as $v) {
+ $result = rcube_utils::file2class($v[0], $v[1]);
+ $this->assertSame($v[2], $result);
+ }
+ }
+
+ /**
+ * rcube:utils::strtotime()
+ */
+ function test_strtotime()
+ {
+ $test = array(
+ '1' => 1,
+ '' => 0,
+ );
+
+ foreach ($test as $datetime => $ts) {
+ $result = rcube_utils::strtotime($datetime);
+ $this->assertSame($ts, $result);
+ }
+ }
+
+ /**
+ * rcube:utils::normalize _string()
+ */
+ function test_normalize_string()
+ {
+ $test = array(
+ '' => '',
+ 'abc def' => 'abc def',
+ );
+
+ foreach ($test as $input => $output) {
+ $result = rcube_utils::normalize_string($input);
+ $this->assertSame($output, $result);
+ }
+ }
}
diff --git a/tests/Framework/Washtml.php b/tests/Framework/Washtml.php
index cd443266f..cb7234314 100644
--- a/tests/Framework/Washtml.php
+++ b/tests/Framework/Washtml.php
@@ -47,7 +47,7 @@ class Framework_Washtml extends PHPUnit_Framework_TestCase
$html = "<!--[if gte mso 10]><p>p1</p><!--><p>p2</p>";
$washed = $washer->wash($html);
- $this->assertEquals('<!-- html ignored --><!-- body ignored --><p>p2</p>', $washed, "HTML conditional comments (#1489004)");
+ $this->assertEquals('<!-- node type 8 --><!-- html ignored --><!-- body ignored --><p>p2</p>', $washed, "HTML conditional comments (#1489004)");
$html = "<!--TestCommentInvalid><p>test</p>";
$washed = $washer->wash($html);
@@ -55,4 +55,17 @@ class Framework_Washtml extends PHPUnit_Framework_TestCase
$this->assertEquals('<!-- html ignored --><!-- body ignored --><p>test</p>', $washed, "HTML invalid comments (#1487759)");
}
+ /**
+ * Test fixing of invalid self-closing elements (#1489137)
+ */
+ function test_self_closing()
+ {
+ $html = "<textarea>test";
+
+ $washer = new rcube_washtml;
+ $washed = $washer->wash($html);
+
+ $this->assertRegExp('|<textarea>test</textarea>|', $washed, "Self-closing textarea (#1489137)");
+ }
+
}
diff --git a/tests/Selenium/bootstrap.php b/tests/Selenium/bootstrap.php
index 6611e8feb..e8b186a1e 100644
--- a/tests/Selenium/bootstrap.php
+++ b/tests/Selenium/bootstrap.php
@@ -27,7 +27,7 @@ if (!defined('INSTALL_PATH')) define('INSTALL_PATH', realpath(dirname(__FILE__)
define('TESTS_DIR', dirname(__FILE__) . '/');
if (@is_dir(TESTS_DIR . 'config')) {
- define('RCMAIL_CONFIG_DIR', TESTS_DIR . 'config');
+ define('RCUBE_CONFIG_DIR', TESTS_DIR . 'config');
}
require_once(INSTALL_PATH . 'program/include/iniset.php');
@@ -38,7 +38,7 @@ if (set_include_path($include_path) === false) {
die("Fatal error: ini_set/set_include_path does not work.");
}
-$rcmail = rcube::get_instance();
+$rcmail = rcube::get_instance('test');
define('TESTS_URL', $rcmail->config->get('tests_url'));
define('TESTS_BROWSER', $rcmail->config->get('tests_browser', 'firefox'));
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
index 40659ebf0..192997d0d 100644
--- a/tests/bootstrap.php
+++ b/tests/bootstrap.php
@@ -27,12 +27,12 @@ if (!defined('INSTALL_PATH')) define('INSTALL_PATH', realpath(dirname(__FILE__)
define('TESTS_DIR', dirname(__FILE__) . '/');
if (@is_dir(TESTS_DIR . 'config')) {
- define('RCMAIL_CONFIG_DIR', TESTS_DIR . 'config');
+ define('RCUBE_CONFIG_DIR', TESTS_DIR . 'config');
}
require_once(INSTALL_PATH . 'program/include/iniset.php');
-rcmail::get_instance()->config->set('devel_mode', false);
+rcmail::get_instance('test')->config->set('devel_mode', false);
// Extend include path so some plugin test won't fail
$include_path = ini_get('include_path') . PATH_SEPARATOR . TESTS_DIR . '..';