From a2dd2e41259a5e90016efcd7d083020b95e25527 Mon Sep 17 00:00:00 2001 From: Vincent Bernat Date: Sun, 2 Oct 2011 15:18:48 +0200 Subject: [PATCH] Imported Upstream version 0.6+dfsg --- .htaccess | 6 +- CHANGELOG | 275 +- INSTALL | 2 + INSTALL.orig | 231 -- SQL/mssql.initial.sql | 5 +- SQL/mssql.upgrade.sql | 15 +- SQL/mysql.initial.sql | 6 +- SQL/mysql.update.sql | 11 + SQL/postgres.initial.sql | 7 +- SQL/postgres.update.sql | 11 + SQL/sqlite.initial.sql | 5 +- SQL/sqlite.update.sql | 44 + UPGRADING | 45 +- bin/cleandb.sh | 11 +- bin/decrypt.sh | 11 +- bin/indexcontacts.sh | 54 + bin/installto.sh | 70 + bin/jsshrink.sh | 5 - bin/jsunshrink.sh | 10 - bin/msgimport.sh | 2 +- bin/update.sh | 62 +- config/db.inc.php.dist | 2 +- config/main.inc.php.dist | 183 +- index.php | 81 +- installer/check.php | 1 + installer/config.php | 25 +- installer/images/banner_bg.gif | Bin 587 -> 0 bytes installer/images/banner_gradient.gif | Bin 0 -> 506 bytes installer/images/banner_logo.gif | Bin 4345 -> 0 bytes installer/images/banner_right.gif | Bin 433 -> 0 bytes installer/images/banner_schraffur.gif | Bin 0 -> 12454 bytes installer/images/rcube_logo.gif | Bin 0 -> 4526 bytes installer/index.php | 47 +- installer/rcube_install.php | 212 +- installer/styles.css | 71 +- installer/test.php | 21 +- installer/utils.php | 48 +- plugins/acl/acl.js | 338 +++ plugins/acl/acl.php | 696 +++++ plugins/acl/config.inc.php.dist | 19 + plugins/acl/localization/de_DE.inc | 83 + plugins/acl/localization/en_US.inc | 83 + plugins/acl/localization/pl_PL.inc | 83 + plugins/acl/skins/default/acl.css | 94 + plugins/acl/skins/default/images/enabled.png | Bin 0 -> 674 bytes plugins/acl/skins/default/images/partial.png | Bin 0 -> 389 bytes .../acl/skins/default/templates/table.html | 54 + plugins/archive/localization/gl_ES.inc | 10 + plugins/archive/localization/pt_BR.inc | 8 + .../database_attachments.php | 44 +- plugins/enigma/README | 35 + plugins/enigma/config.inc.php | 14 + plugins/enigma/enigma.js | 206 ++ plugins/enigma/enigma.php | 475 +++ plugins/enigma/home/.htaccess | 2 + plugins/enigma/lib/Crypt/GPG.php | 2542 +++++++++++++++++ .../lib/Crypt/GPG/DecryptStatusHandler.php | 336 +++ plugins/enigma/lib/Crypt/GPG/Engine.php | 1758 ++++++++++++ plugins/enigma/lib/Crypt/GPG/Exceptions.php | 473 +++ plugins/enigma/lib/Crypt/GPG/Key.php | 223 ++ plugins/enigma/lib/Crypt/GPG/Signature.php | 428 +++ plugins/enigma/lib/Crypt/GPG/SubKey.php | 649 +++++ plugins/enigma/lib/Crypt/GPG/UserId.php | 373 +++ .../lib/Crypt/GPG/VerifyStatusHandler.php | 216 ++ plugins/enigma/lib/enigma_driver.php | 106 + plugins/enigma/lib/enigma_driver_gnupg.php | 305 ++ plugins/enigma/lib/enigma_engine.php | 547 ++++ plugins/enigma/lib/enigma_error.php | 62 + plugins/enigma/lib/enigma_key.php | 129 + plugins/enigma/lib/enigma_signature.php | 34 + plugins/enigma/lib/enigma_subkey.php | 57 + plugins/enigma/lib/enigma_ui.php | 459 +++ plugins/enigma/lib/enigma_userid.php | 31 + plugins/enigma/localization/en_US.inc | 53 + plugins/enigma/localization/ja_JP.inc | 55 + plugins/enigma/localization/ru_RU.inc | 65 + plugins/enigma/skins/default/enigma.css | 182 ++ plugins/enigma/skins/default/enigma.png | Bin 0 -> 1592 bytes plugins/enigma/skins/default/enigma_error.png | Bin 0 -> 1960 bytes plugins/enigma/skins/default/key.png | Bin 0 -> 1743 bytes plugins/enigma/skins/default/key_add.png | Bin 0 -> 1967 bytes plugins/enigma/skins/default/keys_toolbar.png | Bin 0 -> 14977 bytes .../skins/default/templates/keyimport.html | 20 + .../skins/default/templates/keyinfo.html | 17 + .../enigma/skins/default/templates/keys.html | 76 + .../example_addressbook.php | 19 +- .../example_addressbook_backend.php | 25 +- .../filesystem_attachments.php | 22 +- plugins/help/help.php | 2 +- plugins/help/localization/gl_ES.inc | 8 + plugins/help/localization/pt_BR.inc | 8 + .../http_authentication.php | 29 +- plugins/http_authentication/logout.html | 29 + plugins/jqueryui/README | 29 + plugins/jqueryui/config.inc.php.dist | 11 + plugins/jqueryui/jqueryui.php | 54 + plugins/jqueryui/js/i18n/jquery-ui-i18n.js | 1242 ++++++++ .../js/i18n/jquery.ui.datepicker-af.js | 23 + .../js/i18n/jquery.ui.datepicker-ar.js | 24 + .../js/i18n/jquery.ui.datepicker-az.js | 23 + .../js/i18n/jquery.ui.datepicker-bg.js | 24 + .../js/i18n/jquery.ui.datepicker-bs.js | 23 + .../js/i18n/jquery.ui.datepicker-ca.js | 23 + .../js/i18n/jquery.ui.datepicker-cs.js | 23 + .../js/i18n/jquery.ui.datepicker-da.js | 23 + .../js/i18n/jquery.ui.datepicker-de-CH.js | 23 + .../js/i18n/jquery.ui.datepicker-de.js | 23 + .../js/i18n/jquery.ui.datepicker-el.js | 23 + .../js/i18n/jquery.ui.datepicker-en-GB.js | 23 + .../js/i18n/jquery.ui.datepicker-eo.js | 23 + .../js/i18n/jquery.ui.datepicker-es.js | 23 + .../js/i18n/jquery.ui.datepicker-et.js | 23 + .../js/i18n/jquery.ui.datepicker-eu.js | 23 + .../js/i18n/jquery.ui.datepicker-fa.js | 23 + .../js/i18n/jquery.ui.datepicker-fi.js | 23 + .../js/i18n/jquery.ui.datepicker-fo.js | 23 + .../js/i18n/jquery.ui.datepicker-fr-CH.js | 23 + .../js/i18n/jquery.ui.datepicker-fr.js | 23 + .../js/i18n/jquery.ui.datepicker-gl.js | 23 + .../js/i18n/jquery.ui.datepicker-he.js | 23 + .../js/i18n/jquery.ui.datepicker-hr.js | 23 + .../js/i18n/jquery.ui.datepicker-hu.js | 23 + .../js/i18n/jquery.ui.datepicker-hy.js | 23 + .../js/i18n/jquery.ui.datepicker-id.js | 23 + .../js/i18n/jquery.ui.datepicker-is.js | 23 + .../js/i18n/jquery.ui.datepicker-it.js | 23 + .../js/i18n/jquery.ui.datepicker-ja.js | 23 + .../js/i18n/jquery.ui.datepicker-ko.js | 23 + .../js/i18n/jquery.ui.datepicker-kz.js | 23 + .../js/i18n/jquery.ui.datepicker-lt.js | 23 + .../js/i18n/jquery.ui.datepicker-lv.js | 23 + .../js/i18n/jquery.ui.datepicker-ms.js | 23 + .../js/i18n/jquery.ui.datepicker-nl-BE.js | 23 + .../js/i18n/jquery.ui.datepicker-nl.js | 23 + .../js/i18n/jquery.ui.datepicker-no.js | 23 + .../js/i18n/jquery.ui.datepicker-pl.js | 23 + .../js/i18n/jquery.ui.datepicker-pt-BR.js | 23 + .../js/i18n/jquery.ui.datepicker-pt.js | 22 + .../js/i18n/jquery.ui.datepicker-ro.js | 26 + .../js/i18n/jquery.ui.datepicker-ru.js | 23 + .../js/i18n/jquery.ui.datepicker-sk.js | 23 + .../js/i18n/jquery.ui.datepicker-sl.js | 24 + .../js/i18n/jquery.ui.datepicker-sq.js | 23 + .../js/i18n/jquery.ui.datepicker-sr-SR.js | 23 + .../js/i18n/jquery.ui.datepicker-sr.js | 23 + .../js/i18n/jquery.ui.datepicker-sv.js | 23 + .../js/i18n/jquery.ui.datepicker-ta.js | 23 + .../js/i18n/jquery.ui.datepicker-th.js | 23 + .../js/i18n/jquery.ui.datepicker-tr.js | 23 + .../js/i18n/jquery.ui.datepicker-uk.js | 23 + .../js/i18n/jquery.ui.datepicker-vi.js | 23 + .../js/i18n/jquery.ui.datepicker-zh-CN.js | 23 + .../js/i18n/jquery.ui.datepicker-zh-HK.js | 23 + .../js/i18n/jquery.ui.datepicker-zh-TW.js | 23 + .../js/jquery-ui-1.8.14.custom.min.js | 789 +++++ .../themes/default/images/buttongradient.png | Bin 0 -> 193 bytes .../themes/default/images/listheader.png | Bin 0 -> 356 bytes .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin 0 -> 180 bytes .../images/ui-bg_flat_75_ffffff_40x100.png | Bin 0 -> 178 bytes .../images/ui-bg_flat_90_cc3333_40x100.png | Bin 0 -> 212 bytes .../images/ui-bg_glass_95_fef1ec_1x400.png | Bin 0 -> 119 bytes .../ui-bg_highlight-hard_90_a3a3a3_1x100.png | Bin 0 -> 114 bytes .../ui-bg_highlight-hard_90_e6e6e7_1x100.png | Bin 0 -> 101 bytes .../ui-bg_highlight-hard_90_f4f4f4_1x100.png | Bin 0 -> 122 bytes .../images/ui-icons_000000_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_333333_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_666666_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_cc3333_256x240.png | Bin 0 -> 5355 bytes .../images/ui-icons_dddddd_256x240.png | Bin 0 -> 4369 bytes .../default/jquery-ui-1.8.14.custom.css | 580 ++++ .../themes/default/roundcube-custom.diff | 124 + .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin 0 -> 180 bytes .../images/ui-bg_flat_55_fbec88_40x100.png | Bin 0 -> 182 bytes .../images/ui-bg_glass_75_d0e5f5_1x400.png | Bin 0 -> 124 bytes .../images/ui-bg_glass_85_dfeffc_1x400.png | Bin 0 -> 123 bytes .../images/ui-bg_glass_95_fef1ec_1x400.png | Bin 0 -> 119 bytes .../ui-bg_gloss-wave_55_5c9ccc_500x100.png | Bin 0 -> 3457 bytes .../ui-bg_inset-hard_100_f5f8f9_1x100.png | Bin 0 -> 104 bytes .../ui-bg_inset-hard_100_fcfdfd_1x100.png | Bin 0 -> 88 bytes .../images/ui-icons_217bc0_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_2e83ff_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_469bdd_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_6da8d5_256x240.png | Bin 0 -> 5355 bytes .../images/ui-icons_cd0a0a_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_d8e7f3_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_f9bd01_256x240.png | Bin 0 -> 4369 bytes .../redmond/jquery-ui-1.8.14.custom.css | 568 ++++ plugins/managesieve/Changelog | 28 +- plugins/managesieve/lib/Net/Sieve.php | 13 + plugins/managesieve/lib/rcube_sieve.php | 730 +---- .../managesieve/lib/rcube_sieve_script.php | 731 +++++ plugins/managesieve/localization/en_US.inc | 13 + plugins/managesieve/localization/fr_FR.inc | 10 +- plugins/managesieve/localization/gl_ES.inc | 81 + plugins/managesieve/localization/hr_HR.inc | 105 + plugins/managesieve/localization/pl_PL.inc | 17 +- plugins/managesieve/localization/pt_PT.inc | 227 +- plugins/managesieve/localization/ru_RU.inc | 26 +- plugins/managesieve/managesieve.js | 74 +- plugins/managesieve/managesieve.php | 177 +- .../skins/default/templates/filteredit.html | 87 - plugins/managesieve/tests/parser.phpt | 17 +- plugins/managesieve/tests/tokenize.phpt | 2 +- plugins/markasjunk/localization/gl_ES.inc | 7 + plugins/markasjunk/localization/it_IT.inc | 7 + plugins/new_user_dialog/new_user_dialog.php | 27 +- plugins/new_user_dialog/newuserdialog.css | 3 +- .../new_user_identity/new_user_identity.php | 55 +- plugins/newmail_notifier/config.inc.php.dist | 9 + plugins/newmail_notifier/favicon.ico | Bin 0 -> 1734 bytes .../newmail_notifier/localization/en_US.inc | 6 + .../newmail_notifier/localization/pl_PL.inc | 6 + plugins/newmail_notifier/newmail_notifier.js | 66 + plugins/newmail_notifier/newmail_notifier.php | 145 + plugins/newmail_notifier/sound.wav | Bin 0 -> 10444 bytes plugins/password/README | 14 +- plugins/password/config.inc.php.dist | 5 +- plugins/password/drivers/directadmin.php | 36 +- plugins/password/drivers/ldap.php | 4 +- plugins/password/drivers/sql.php | 7 +- plugins/password/localization/gl_ES.inc | 21 + plugins/password/localization/hr_HR.inc | 21 + plugins/password/localization/pt_BR.inc | 9 +- plugins/password/package.xml | 48 +- plugins/password/password.php | 15 +- .../redundant_attachments/config.inc.php.dist | 13 + .../redundant_attachments.php | 232 ++ .../localization/gl_ES.inc | 6 + .../subscriptions_option.php | 4 +- plugins/userinfo/localization/gl_ES.inc | 9 + plugins/userinfo/localization/pt_BR.inc | 9 + .../vcard_attachments/localization/gl_ES.inc | 7 + .../vcard_attachments/localization/pt_BR.inc | 7 + program/.htaccess | 4 + program/include/clisetup.php | 6 +- program/include/html.php | 72 +- program/include/iniset.php | 21 +- program/include/main.inc | 1102 ++++--- program/include/main.inc.orig | 2023 ------------- program/include/rcmail.php | 552 +++- program/include/rcmail.php.orig | 1325 --------- program/include/rcube_addressbook.php | 234 +- program/include/rcube_browser.php | 9 +- program/include/rcube_cache.php | 529 ++++ program/include/rcube_config.php | 54 +- program/include/rcube_contacts.php | 361 ++- program/include/rcube_html_page.php | 45 +- program/include/rcube_imap.php | 1072 +++---- program/include/rcube_imap_generic.php | 107 +- program/include/rcube_json_output.php | 13 +- program/include/rcube_ldap.php | 2125 +++++++++----- program/include/rcube_mdb2.php | 122 +- program/include/rcube_message.php | 53 +- program/include/rcube_mime_struct.php | 81 +- program/include/rcube_plugin.php | 23 +- program/include/rcube_plugin_api.php | 172 +- program/include/rcube_result_set.php | 14 +- program/include/rcube_session.php | 444 ++- program/include/rcube_shared.inc | 34 +- program/include/rcube_smtp.php | 9 +- program/include/rcube_spellchecker.php | 416 +++ program/include/rcube_sqlite.inc | 4 +- program/include/rcube_string_replacer.php | 8 +- program/include/rcube_template.php | 89 +- program/include/rcube_user.php | 69 +- program/include/rcube_vcard.php | 433 ++- program/js/app.js | 386 +-- program/js/app.js.src | 1790 ++++++++---- program/js/common.js | 34 +- program/js/common.js.src | 102 +- program/js/editor.js | 51 +- program/js/editor_images.js | 2 +- program/js/googiespell.js | 68 +- program/js/googiespell.js.src | 101 +- program/js/jquery-1.4.min.js | 167 -- program/js/jquery.min.js | 4 + program/js/list.js | 12 +- program/js/list.js.src | 6 +- program/js/tiny_mce/langs/ar.js | 171 +- program/js/tiny_mce/langs/az.js | 172 +- program/js/tiny_mce/langs/bg.js | 171 +- program/js/tiny_mce/langs/bn.js | 171 +- program/js/tiny_mce/langs/br.js | 171 +- program/js/tiny_mce/langs/bs.js | 171 +- program/js/tiny_mce/langs/ca.js | 171 +- program/js/tiny_mce/langs/cs.js | 177 +- program/js/tiny_mce/langs/cy.js | 171 +- program/js/tiny_mce/langs/da.js | 172 +- program/js/tiny_mce/langs/de.js | 172 +- program/js/tiny_mce/langs/el.js | 175 +- program/js/tiny_mce/langs/es.js | 173 +- program/js/tiny_mce/langs/et.js | 171 +- program/js/tiny_mce/langs/fa.js | 171 +- program/js/tiny_mce/langs/fi.js | 172 +- program/js/tiny_mce/langs/fr.js | 171 +- program/js/tiny_mce/langs/gl.js | 171 +- program/js/tiny_mce/langs/he.js | 171 +- program/js/tiny_mce/langs/hi.js | 171 +- program/js/tiny_mce/langs/hr.js | 172 +- program/js/tiny_mce/langs/hu.js | 171 +- program/js/tiny_mce/langs/hy.js | 174 +- program/js/tiny_mce/langs/ia.js | 171 +- program/js/tiny_mce/langs/id.js | 171 +- program/js/tiny_mce/langs/is.js | 171 +- program/js/tiny_mce/langs/it.js | 207 +- program/js/tiny_mce/langs/ja.js | 171 +- program/js/tiny_mce/langs/ka.js | 174 +- program/js/tiny_mce/langs/ko.js | 171 +- program/js/tiny_mce/langs/lt.js | 189 +- program/js/tiny_mce/langs/lv.js | 171 +- program/js/tiny_mce/langs/mk.js | 171 +- program/js/tiny_mce/langs/ms.js | 171 +- program/js/tiny_mce/langs/nb.js | 171 +- program/js/tiny_mce/langs/nl.js | 171 +- program/js/tiny_mce/langs/nn.js | 171 +- program/js/tiny_mce/langs/no.js | 171 +- program/js/tiny_mce/langs/pl.js | 171 +- program/js/tiny_mce/langs/ps.js | 171 +- program/js/tiny_mce/langs/pt.js | 171 +- program/js/tiny_mce/langs/ro.js | 171 +- program/js/tiny_mce/langs/ru.js | 174 +- program/js/tiny_mce/langs/si.js | 171 +- program/js/tiny_mce/langs/sk.js | 177 +- program/js/tiny_mce/langs/sl.js | 172 +- program/js/tiny_mce/langs/sq.js | 171 +- program/js/tiny_mce/langs/sr.js | 171 +- program/js/tiny_mce/langs/sv.js | 171 +- program/js/tiny_mce/langs/ta.js | 171 +- program/js/tiny_mce/langs/te.js | 171 +- program/js/tiny_mce/langs/th.js | 171 +- program/js/tiny_mce/langs/tr.js | 171 +- program/js/tiny_mce/langs/tw.js | 179 +- program/js/tiny_mce/langs/uk.js | 174 +- program/js/tiny_mce/langs/vi.js | 171 +- program/js/tiny_mce/langs/zh.js | 179 +- .../tiny_mce/plugins/emotions/langs/ar_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/az_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/be_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/bg_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/bn_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/br_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/bs_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/ca_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/cs_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/cy_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/da_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/de_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/el_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/es_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/et_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/fa_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/fi_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/fr_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/gl_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/he_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/hi_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/hr_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/hu_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/hy_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/ia_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/id_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/is_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/it_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/ja_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/ka_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/ko_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/lt_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/lv_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/mk_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/ms_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/nb_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/nl_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/nn_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/no_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/pl_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/ps_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/pt_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/ro_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/ru_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/si_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/sk_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/sl_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/sq_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/sr_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/sv_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/ta_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/te_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/th_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/tr_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/tw_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/uk_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/vi_dlg.js | 21 +- .../tiny_mce/plugins/emotions/langs/zh_dlg.js | 21 +- .../js/tiny_mce/plugins/media/css/content.css | 6 - .../js/tiny_mce/plugins/media/langs/ar_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/az_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/be_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/bg_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/bn_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/br_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/bs_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/ca_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/cs_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/cy_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/da_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/de_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/el_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/es_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/et_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/fa_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/fi_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/fr_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/gl_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/he_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/hi_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/hr_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/hu_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/hy_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/ia_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/id_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/is_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/it_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/ja_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/ka_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/ko_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/lt_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/lv_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/mk_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/ms_dlg.js | 103 +- .../js/tiny_mce/plugins/media/langs/nb_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/nl_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/nn_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/no_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/pl_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/ps_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/pt_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/ro_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/ru_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/si_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/sk_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/sl_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/sq_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/sr_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/sv_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/ta_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/te_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/th_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/tr_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/tw_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/uk_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/vi_dlg.js | 104 +- .../js/tiny_mce/plugins/media/langs/zh_dlg.js | 104 +- .../js/tiny_mce/plugins/paste/langs/ar_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/az_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/be_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/bg_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/bn_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/br_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/bs_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/ca_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/cs_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/cy_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/da_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/de_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/el_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/es_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/et_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/fa_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/fi_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/fr_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/gl_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/he_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/hi_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/hr_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/hu_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/hy_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/ia_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/id_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/is_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/it_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/ja_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/ka_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/ko_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/lt_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/lv_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/mk_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/ms_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/nb_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/nl_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/nn_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/no_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/pl_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/ps_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/pt_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/ro_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/ru_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/si_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/sk_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/sl_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/sq_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/sr_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/sv_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/ta_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/te_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/th_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/tr_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/tw_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/uk_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/vi_dlg.js | 6 +- .../js/tiny_mce/plugins/paste/langs/zh_dlg.js | 6 +- .../plugins/searchreplace/langs/ar_dlg.js | 17 +- .../plugins/searchreplace/langs/az_dlg.js | 17 +- .../plugins/searchreplace/langs/be_dlg.js | 17 +- .../plugins/searchreplace/langs/bg_dlg.js | 17 +- .../plugins/searchreplace/langs/bn_dlg.js | 17 +- .../plugins/searchreplace/langs/br_dlg.js | 17 +- .../plugins/searchreplace/langs/bs_dlg.js | 17 +- .../plugins/searchreplace/langs/ca_dlg.js | 17 +- .../plugins/searchreplace/langs/cs_dlg.js | 17 +- .../plugins/searchreplace/langs/cy_dlg.js | 17 +- .../plugins/searchreplace/langs/da_dlg.js | 17 +- .../plugins/searchreplace/langs/de_dlg.js | 17 +- .../plugins/searchreplace/langs/el_dlg.js | 17 +- .../plugins/searchreplace/langs/es_dlg.js | 17 +- .../plugins/searchreplace/langs/et_dlg.js | 17 +- .../plugins/searchreplace/langs/fa_dlg.js | 17 +- .../plugins/searchreplace/langs/fi_dlg.js | 17 +- .../plugins/searchreplace/langs/fr_dlg.js | 17 +- .../plugins/searchreplace/langs/gl_dlg.js | 17 +- .../plugins/searchreplace/langs/he_dlg.js | 17 +- .../plugins/searchreplace/langs/hi_dlg.js | 17 +- .../plugins/searchreplace/langs/hr_dlg.js | 17 +- .../plugins/searchreplace/langs/hu_dlg.js | 17 +- .../plugins/searchreplace/langs/hy_dlg.js | 17 +- .../plugins/searchreplace/langs/ia_dlg.js | 17 +- .../plugins/searchreplace/langs/id_dlg.js | 17 +- .../plugins/searchreplace/langs/is_dlg.js | 17 +- .../plugins/searchreplace/langs/it_dlg.js | 17 +- .../plugins/searchreplace/langs/ja_dlg.js | 17 +- .../plugins/searchreplace/langs/ka_dlg.js | 17 +- .../plugins/searchreplace/langs/ko_dlg.js | 17 +- .../plugins/searchreplace/langs/lt_dlg.js | 17 +- .../plugins/searchreplace/langs/lv_dlg.js | 17 +- .../plugins/searchreplace/langs/mk_dlg.js | 17 +- .../plugins/searchreplace/langs/ms_dlg.js | 17 +- .../plugins/searchreplace/langs/nb_dlg.js | 17 +- .../plugins/searchreplace/langs/nl_dlg.js | 17 +- .../plugins/searchreplace/langs/nn_dlg.js | 17 +- .../plugins/searchreplace/langs/no_dlg.js | 17 +- .../plugins/searchreplace/langs/pl_dlg.js | 17 +- .../plugins/searchreplace/langs/ps_dlg.js | 17 +- .../plugins/searchreplace/langs/pt_dlg.js | 17 +- .../plugins/searchreplace/langs/ro_dlg.js | 17 +- .../plugins/searchreplace/langs/ru_dlg.js | 17 +- .../plugins/searchreplace/langs/si_dlg.js | 17 +- .../plugins/searchreplace/langs/sk_dlg.js | 17 +- .../plugins/searchreplace/langs/sl_dlg.js | 17 +- .../plugins/searchreplace/langs/sq_dlg.js | 17 +- .../plugins/searchreplace/langs/sr_dlg.js | 17 +- .../plugins/searchreplace/langs/sv_dlg.js | 17 +- .../plugins/searchreplace/langs/ta_dlg.js | 17 +- .../plugins/searchreplace/langs/te_dlg.js | 17 +- .../plugins/searchreplace/langs/th_dlg.js | 17 +- .../plugins/searchreplace/langs/tr_dlg.js | 17 +- .../plugins/searchreplace/langs/tw_dlg.js | 17 +- .../plugins/searchreplace/langs/uk_dlg.js | 17 +- .../plugins/searchreplace/langs/vi_dlg.js | 17 +- .../plugins/searchreplace/langs/zh_dlg.js | 17 +- .../js/tiny_mce/plugins/table/langs/ar_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/az_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/be_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/bg_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/bn_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/br_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/bs_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/ca_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/cs_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/cy_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/da_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/de_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/el_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/es_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/et_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/fa_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/fi_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/fr_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/gl_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/he_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/hi_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/hr_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/hu_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/hy_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/ia_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/id_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/is_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/it_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/ja_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/ka_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/ko_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/lt_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/lv_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/mk_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/ms_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/nb_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/nl_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/nn_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/no_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/pl_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/ps_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/pt_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/ro_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/ru_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/si_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/sk_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/sl_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/sq_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/sr_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/sv_dlg.js | 74 +- .../js/tiny_mce/plugins/table/langs/ta_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/te_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/th_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/tr_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/tw_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/uk_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/vi_dlg.js | 75 +- .../js/tiny_mce/plugins/table/langs/zh_dlg.js | 75 +- .../media => themes/advanced}/img/flash.gif | Bin .../tiny_mce/themes/advanced/img/iframe.gif | Bin 0 -> 600 bytes .../themes/advanced/img/pagebreak.gif | Bin 0 -> 325 bytes .../advanced}/img/quicktime.gif | Bin .../advanced}/img/realmedia.gif | Bin .../advanced}/img/shockwave.gif | Bin .../media => themes/advanced}/img/trans.gif | Bin .../js/tiny_mce/themes/advanced/img/video.gif | Bin 0 -> 597 bytes .../advanced}/img/windowsmedia.gif | Bin .../js/tiny_mce/themes/advanced/langs/ar.js | 63 +- .../tiny_mce/themes/advanced/langs/ar_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/az.js | 64 +- .../tiny_mce/themes/advanced/langs/az_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/be.js | 63 +- .../tiny_mce/themes/advanced/langs/be_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/bg.js | 63 +- .../tiny_mce/themes/advanced/langs/bg_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/bn.js | 63 +- .../tiny_mce/themes/advanced/langs/bn_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/br.js | 63 +- .../tiny_mce/themes/advanced/langs/br_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/bs.js | 63 +- .../tiny_mce/themes/advanced/langs/bs_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/ca.js | 63 +- .../tiny_mce/themes/advanced/langs/ca_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/cs.js | 63 +- .../tiny_mce/themes/advanced/langs/cs_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/cy.js | 63 +- .../tiny_mce/themes/advanced/langs/cy_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/da.js | 63 +- .../tiny_mce/themes/advanced/langs/da_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/de.js | 64 +- .../tiny_mce/themes/advanced/langs/de_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/el.js | 65 +- .../tiny_mce/themes/advanced/langs/el_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/es.js | 63 +- .../tiny_mce/themes/advanced/langs/es_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/et.js | 63 +- .../tiny_mce/themes/advanced/langs/et_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/fa.js | 63 +- .../tiny_mce/themes/advanced/langs/fa_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/fi.js | 63 +- .../tiny_mce/themes/advanced/langs/fi_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/fr.js | 63 +- .../tiny_mce/themes/advanced/langs/fr_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/gl.js | 63 +- .../tiny_mce/themes/advanced/langs/gl_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/he.js | 63 +- .../tiny_mce/themes/advanced/langs/he_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/hi.js | 63 +- .../tiny_mce/themes/advanced/langs/hi_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/hr.js | 63 +- .../tiny_mce/themes/advanced/langs/hr_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/hu.js | 63 +- .../tiny_mce/themes/advanced/langs/hu_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/hy.js | 63 +- .../tiny_mce/themes/advanced/langs/hy_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/ia.js | 63 +- .../tiny_mce/themes/advanced/langs/ia_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/id.js | 63 +- .../tiny_mce/themes/advanced/langs/id_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/is.js | 63 +- .../tiny_mce/themes/advanced/langs/is_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/it.js | 73 +- .../tiny_mce/themes/advanced/langs/it_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/ja.js | 63 +- .../tiny_mce/themes/advanced/langs/ja_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/ka.js | 63 +- .../tiny_mce/themes/advanced/langs/ka_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/ko.js | 63 +- .../tiny_mce/themes/advanced/langs/ko_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/lt.js | 64 +- .../tiny_mce/themes/advanced/langs/lt_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/lv.js | 63 +- .../tiny_mce/themes/advanced/langs/lv_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/mk.js | 63 +- .../tiny_mce/themes/advanced/langs/mk_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/ms.js | 63 +- .../tiny_mce/themes/advanced/langs/ms_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/nb.js | 63 +- .../tiny_mce/themes/advanced/langs/nb_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/nl.js | 63 +- .../tiny_mce/themes/advanced/langs/nl_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/nn.js | 63 +- .../tiny_mce/themes/advanced/langs/nn_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/no.js | 63 +- .../tiny_mce/themes/advanced/langs/no_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/pl.js | 63 +- .../tiny_mce/themes/advanced/langs/pl_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/ps.js | 63 +- .../tiny_mce/themes/advanced/langs/ps_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/pt.js | 63 +- .../tiny_mce/themes/advanced/langs/pt_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/ro.js | 63 +- .../tiny_mce/themes/advanced/langs/ro_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/ru.js | 63 +- .../tiny_mce/themes/advanced/langs/ru_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/si.js | 62 +- .../tiny_mce/themes/advanced/langs/si_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/sk.js | 63 +- .../tiny_mce/themes/advanced/langs/sk_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/sl.js | 63 +- .../tiny_mce/themes/advanced/langs/sl_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/sq.js | 63 +- .../tiny_mce/themes/advanced/langs/sq_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/sr.js | 63 +- .../tiny_mce/themes/advanced/langs/sr_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/sv.js | 61 +- .../tiny_mce/themes/advanced/langs/sv_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/ta.js | 63 +- .../tiny_mce/themes/advanced/langs/ta_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/te.js | 63 +- .../tiny_mce/themes/advanced/langs/te_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/th.js | 63 +- .../tiny_mce/themes/advanced/langs/th_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/tr.js | 63 +- .../tiny_mce/themes/advanced/langs/tr_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/tw.js | 65 +- .../tiny_mce/themes/advanced/langs/tw_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/uk.js | 63 +- .../tiny_mce/themes/advanced/langs/uk_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/vi.js | 63 +- .../tiny_mce/themes/advanced/langs/vi_dlg.js | 52 +- .../js/tiny_mce/themes/advanced/langs/zh.js | 65 +- .../tiny_mce/themes/advanced/langs/zh_dlg.js | 52 +- program/js/tiny_mce/tiny_mce.js | 389 +-- program/localization/ar_SA/labels.inc | 71 +- program/localization/ar_SA/messages.inc | 18 +- program/localization/ast/labels.inc | 4 +- program/localization/ast/messages.inc | 4 +- program/localization/az_AZ/labels.inc | 21 +- program/localization/az_AZ/messages.inc | 3 +- program/localization/bg_BG/labels.inc | 4 +- program/localization/bg_BG/messages.inc | 4 +- program/localization/bn_BD/labels.inc | 2 +- program/localization/bn_BD/messages.inc | 2 +- program/localization/br/labels.inc | 4 +- program/localization/br/messages.inc | 4 +- program/localization/bs_BA/labels.inc | 517 ++-- program/localization/bs_BA/messages.inc | 150 +- program/localization/ca_ES/labels.inc | 80 +- program/localization/ca_ES/messages.inc | 24 +- program/localization/cs_CZ/labels.inc | 83 +- program/localization/cs_CZ/messages.inc | 20 +- program/localization/cy_GB/labels.inc | 70 +- program/localization/cy_GB/messages.inc | 16 +- program/localization/da_DK/labels.inc | 4 +- program/localization/da_DK/messages.inc | 4 +- program/localization/de_CH/labels.inc | 74 +- program/localization/de_CH/messages.inc | 24 +- program/localization/de_DE/labels.inc | 14 +- program/localization/de_DE/messages.inc | 32 +- program/localization/el_GR/labels.inc | 33 +- program/localization/el_GR/messages.inc | 9 +- program/localization/en_GB/labels.inc | 83 +- program/localization/en_GB/messages.inc | 176 +- program/localization/en_US/labels.inc | 99 +- program/localization/en_US/messages.inc | 180 +- program/localization/eo/labels.inc | 2 +- program/localization/eo/messages.inc | 2 +- program/localization/es_AR/labels.inc | 4 +- program/localization/es_AR/messages.inc | 4 +- program/localization/es_ES/labels.inc | 54 +- program/localization/es_ES/messages.inc | 6 +- program/localization/et_EE/labels.inc | 61 +- program/localization/et_EE/messages.inc | 9 +- program/localization/eu_ES/labels.inc | 4 +- program/localization/eu_ES/messages.inc | 4 +- program/localization/fa/labels.inc | 4 +- program/localization/fa/messages.inc | 4 +- program/localization/fi_FI/labels.inc | 4 +- program/localization/fi_FI/messages.inc | 4 +- program/localization/fr_FR/labels.inc | 102 +- program/localization/fr_FR/messages.inc | 18 +- program/localization/ga_IE/labels.inc | 4 +- program/localization/ga_IE/messages.inc | 4 +- program/localization/gl_ES/labels.inc | 58 +- program/localization/gl_ES/messages.inc | 8 +- program/localization/he_IL/labels.inc | 41 +- program/localization/he_IL/messages.inc | 17 +- program/localization/hi_IN/labels.inc | 4 +- program/localization/hi_IN/messages.inc | 4 +- program/localization/hr_HR/labels.inc | 95 +- program/localization/hr_HR/messages.inc | 48 +- program/localization/hu_HU/labels.inc | 108 +- program/localization/hu_HU/messages.inc | 39 +- program/localization/hy_AM/labels.inc | 4 +- program/localization/hy_AM/messages.inc | 4 +- program/localization/id_ID/labels.inc | 78 +- program/localization/id_ID/messages.inc | 26 +- program/localization/index.inc | 4 +- program/localization/is_IS/labels.inc | 4 +- program/localization/is_IS/messages.inc | 4 +- program/localization/it_IT/labels.inc | 43 +- program/localization/it_IT/messages.inc | 33 +- program/localization/ja_JP/labels.inc | 231 +- program/localization/ja_JP/messages.inc | 89 +- program/localization/ka_GE/labels.inc | 2 +- program/localization/ka_GE/messages.inc | 2 +- program/localization/kh_KH/labels.inc | 792 ++--- program/localization/kh_KH/messages.inc | 284 +- program/localization/ko_KR/labels.inc | 4 +- program/localization/ko_KR/messages.inc | 4 +- program/localization/ku/labels.inc | 2 +- program/localization/ku/messages.inc | 2 +- program/localization/lt_LT/labels.inc | 68 +- program/localization/lt_LT/messages.inc | 180 +- program/localization/lv_LV/labels.inc | 163 +- program/localization/lv_LV/messages.inc | 54 +- program/localization/mk_MK/labels.inc | 4 +- program/localization/mk_MK/messages.inc | 4 +- program/localization/mr_IN/labels.inc | 2 +- program/localization/mr_IN/messages.inc | 2 +- program/localization/ms_MY/labels.inc | 4 +- program/localization/ms_MY/messages.inc | 4 +- program/localization/nb_NO/labels.inc | 4 +- program/localization/nb_NO/messages.inc | 4 +- program/localization/ne_NP/labels.inc | 2 +- program/localization/ne_NP/messages.inc | 2 +- program/localization/nl_BE/labels.inc | 4 +- program/localization/nl_BE/messages.inc | 4 +- program/localization/nl_NL/labels.inc | 45 +- program/localization/nl_NL/messages.inc | 13 +- program/localization/nn_NO/labels.inc | 4 +- program/localization/nn_NO/messages.inc | 4 +- program/localization/pl_PL/labels.inc | 91 +- program/localization/pl_PL/messages.inc | 106 +- program/localization/pt_BR/labels.inc | 119 +- program/localization/pt_BR/messages.inc | 33 +- program/localization/pt_PT/labels.inc | 41 +- program/localization/pt_PT/messages.inc | 17 +- program/localization/ro_RO/labels.inc | 4 +- program/localization/ro_RO/messages.inc | 4 +- program/localization/ru_RU/labels.inc | 41 +- program/localization/ru_RU/messages.inc | 17 +- program/localization/si_LK/labels.inc | 4 +- program/localization/si_LK/messages.inc | 4 +- program/localization/sk_SK/labels.inc | 70 +- program/localization/sk_SK/messages.inc | 12 +- program/localization/sl_SI/labels.inc | 70 +- program/localization/sl_SI/messages.inc | 7 +- program/localization/sq_AL/labels.inc | 4 +- program/localization/sq_AL/messages.inc | 4 +- program/localization/sr_CS/labels.inc | 218 +- program/localization/sr_CS/messages.inc | 84 +- program/localization/sv_SE/labels.inc | 39 +- program/localization/sv_SE/messages.inc | 17 +- program/localization/ta_IN/labels.inc | 2 +- program/localization/ta_IN/messages.inc | 2 +- program/localization/th_TH/labels.inc | 4 +- program/localization/th_TH/messages.inc | 4 +- program/localization/tr_TR/labels.inc | 74 +- program/localization/tr_TR/messages.inc | 26 +- program/localization/uk_UA/labels.inc | 54 +- program/localization/uk_UA/messages.inc | 6 +- program/localization/vi_VN/labels.inc | 4 +- program/localization/vi_VN/messages.inc | 4 +- program/localization/zh_CN/labels.inc | 108 +- program/localization/zh_CN/messages.inc | 2 +- program/localization/zh_TW/labels.inc | 23 +- program/localization/zh_TW/messages.inc | 5 +- program/steps/addressbook/copy.inc | 124 +- program/steps/addressbook/delete.inc | 149 +- program/steps/addressbook/edit.inc | 226 +- program/steps/addressbook/export.inc | 83 +- program/steps/addressbook/func.inc | 627 +++- program/steps/addressbook/groups.inc | 21 +- program/steps/addressbook/import.inc | 110 +- program/steps/addressbook/list.inc | 68 +- program/steps/addressbook/mailto.inc | 41 +- program/steps/addressbook/save.inc | 164 +- program/steps/addressbook/search.inc | 256 +- program/steps/addressbook/show.inc | 163 +- program/steps/addressbook/undo.inc | 87 + program/steps/addressbook/upload_photo.inc | 89 + program/steps/mail/addcontact.inc | 26 +- program/steps/mail/attachments.inc | 44 +- program/steps/mail/autocomplete.inc | 52 +- program/steps/mail/check_recent.inc | 10 +- program/steps/mail/compose.inc | 543 ++-- program/steps/mail/copy.inc | 4 +- program/steps/mail/folders.inc | 4 +- program/steps/mail/func.inc | 245 +- program/steps/mail/get.inc | 23 +- program/steps/mail/getunread.inc | 6 +- program/steps/mail/headers.inc | 4 +- program/steps/mail/list.inc | 4 +- program/steps/mail/mark.inc | 4 +- program/steps/mail/move_del.inc | 4 +- program/steps/mail/pagenav.inc | 4 +- program/steps/mail/search.inc | 9 +- program/steps/mail/sendmail.inc | 44 +- program/steps/mail/sendmdn.inc | 4 +- program/steps/mail/show.inc | 10 +- program/steps/mail/viewsource.inc | 4 +- program/steps/settings/delete_identity.inc | 8 +- program/steps/settings/edit_folder.inc | 160 +- program/steps/settings/edit_identity.inc | 6 +- program/steps/settings/edit_prefs.inc | 2 +- program/steps/settings/folders.inc | 152 +- program/steps/settings/func.inc | 103 +- program/steps/settings/identities.inc | 4 +- program/steps/settings/save_folder.inc | 40 +- program/steps/settings/save_identity.inc | 10 +- program/steps/settings/save_prefs.inc | 28 +- program/steps/utils/error.inc | 4 +- program/steps/utils/html2text.inc | 4 +- program/steps/utils/killcache.inc | 4 +- program/steps/utils/modcss.inc | 4 +- program/steps/utils/save_pref.inc | 4 +- program/steps/utils/spell.inc | 28 +- program/steps/utils/spell_googie.inc | 75 - program/steps/utils/spell_html.inc | 53 + program/steps/utils/spell_html_googie.inc | 110 - program/steps/utils/spell_html_pspell.inc | 76 - program/steps/utils/spell_pspell.inc | 75 - skins/default/addressbook.css | 197 +- skins/default/common.css | 70 +- skins/default/functions.js | 205 +- skins/default/ie6hacks.css | 19 +- skins/default/iehacks.css | 85 +- skins/default/images/abook_toolbar.gif | Bin 6087 -> 5753 bytes skins/default/images/abook_toolbar.png | Bin 13586 -> 16395 bytes skins/default/images/contactpic.png | Bin 0 -> 375 bytes skins/default/images/listheader.gif | Bin 470 -> 322 bytes skins/default/images/mailbox_list.gif | Bin 207 -> 0 bytes skins/default/images/mailbox_selected.gif | Bin 158 -> 0 bytes skins/default/images/quota-colors.png | Bin 0 -> 492 bytes skins/default/images/quota.png | Bin 0 -> 216 bytes skins/default/includes/header.html | 2 +- skins/default/includes/links.html | 2 +- skins/default/includes/messagemenu.html | 10 - skins/default/includes/messagetoolbar.html | 71 + skins/default/includes/replyallmenu.html | 7 - skins/default/includes/taskbar.html | 2 +- skins/default/mail.css | 48 +- skins/default/settings.css | 7 + skins/default/splitter.js | 4 + skins/default/templates/addressbook.html | 37 +- skins/default/templates/contact.html | 13 +- skins/default/templates/contactadd.html | 25 +- skins/default/templates/contactedit.html | 26 +- skins/default/templates/contactsearch.html | 18 + skins/default/templates/error.html | 2 +- skins/default/templates/folderedit.html | 2 +- skins/default/templates/folders.html | 2 +- skins/default/templates/identityedit.html | 4 +- skins/default/templates/login.html | 2 +- skins/default/templates/mail.html | 42 +- skins/default/templates/message.html | 18 +- skins/default/templates/messageerror.html | 2 +- skins/default/templates/messageprint.html | 2 +- 978 files changed, 35109 insertions(+), 41301 deletions(-) delete mode 100644 INSTALL.orig create mode 100755 bin/indexcontacts.sh create mode 100755 bin/installto.sh delete mode 100644 installer/images/banner_bg.gif create mode 100644 installer/images/banner_gradient.gif delete mode 100644 installer/images/banner_logo.gif delete mode 100644 installer/images/banner_right.gif create mode 100644 installer/images/banner_schraffur.gif create mode 100644 installer/images/rcube_logo.gif create mode 100644 plugins/acl/acl.js create mode 100644 plugins/acl/acl.php create mode 100644 plugins/acl/config.inc.php.dist create mode 100644 plugins/acl/localization/de_DE.inc create mode 100644 plugins/acl/localization/en_US.inc create mode 100644 plugins/acl/localization/pl_PL.inc create mode 100644 plugins/acl/skins/default/acl.css create mode 100644 plugins/acl/skins/default/images/enabled.png create mode 100644 plugins/acl/skins/default/images/partial.png create mode 100644 plugins/acl/skins/default/templates/table.html create mode 100644 plugins/archive/localization/gl_ES.inc create mode 100644 plugins/archive/localization/pt_BR.inc create mode 100644 plugins/enigma/README create mode 100644 plugins/enigma/config.inc.php create mode 100644 plugins/enigma/enigma.js create mode 100644 plugins/enigma/enigma.php create mode 100644 plugins/enigma/home/.htaccess create mode 100644 plugins/enigma/lib/Crypt/GPG.php create mode 100644 plugins/enigma/lib/Crypt/GPG/DecryptStatusHandler.php create mode 100644 plugins/enigma/lib/Crypt/GPG/Engine.php create mode 100644 plugins/enigma/lib/Crypt/GPG/Exceptions.php create mode 100644 plugins/enigma/lib/Crypt/GPG/Key.php create mode 100644 plugins/enigma/lib/Crypt/GPG/Signature.php create mode 100644 plugins/enigma/lib/Crypt/GPG/SubKey.php create mode 100644 plugins/enigma/lib/Crypt/GPG/UserId.php create mode 100644 plugins/enigma/lib/Crypt/GPG/VerifyStatusHandler.php create mode 100644 plugins/enigma/lib/enigma_driver.php create mode 100644 plugins/enigma/lib/enigma_driver_gnupg.php create mode 100644 plugins/enigma/lib/enigma_engine.php create mode 100644 plugins/enigma/lib/enigma_error.php create mode 100644 plugins/enigma/lib/enigma_key.php create mode 100644 plugins/enigma/lib/enigma_signature.php create mode 100644 plugins/enigma/lib/enigma_subkey.php create mode 100644 plugins/enigma/lib/enigma_ui.php create mode 100644 plugins/enigma/lib/enigma_userid.php create mode 100644 plugins/enigma/localization/en_US.inc create mode 100644 plugins/enigma/localization/ja_JP.inc create mode 100644 plugins/enigma/localization/ru_RU.inc create mode 100644 plugins/enigma/skins/default/enigma.css create mode 100644 plugins/enigma/skins/default/enigma.png create mode 100644 plugins/enigma/skins/default/enigma_error.png create mode 100644 plugins/enigma/skins/default/key.png create mode 100644 plugins/enigma/skins/default/key_add.png create mode 100644 plugins/enigma/skins/default/keys_toolbar.png create mode 100644 plugins/enigma/skins/default/templates/keyimport.html create mode 100644 plugins/enigma/skins/default/templates/keyinfo.html create mode 100644 plugins/enigma/skins/default/templates/keys.html create mode 100644 plugins/help/localization/gl_ES.inc create mode 100644 plugins/help/localization/pt_BR.inc create mode 100644 plugins/http_authentication/logout.html create mode 100644 plugins/jqueryui/README create mode 100644 plugins/jqueryui/config.inc.php.dist create mode 100644 plugins/jqueryui/jqueryui.php create mode 100644 plugins/jqueryui/js/i18n/jquery-ui-i18n.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-af.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-ar.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-az.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-bg.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-bs.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-ca.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-cs.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-da.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-de-CH.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-de.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-el.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-en-GB.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-eo.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-es.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-et.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-eu.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-fa.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-fi.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-fo.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-fr-CH.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-fr.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-gl.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-he.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-hr.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-hu.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-hy.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-id.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-is.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-it.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-ja.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-ko.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-kz.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-lt.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-lv.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-ms.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-nl-BE.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-nl.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-no.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-pl.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-pt-BR.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-pt.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-ro.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-ru.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-sk.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-sl.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-sq.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-sr-SR.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-sr.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-sv.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-ta.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-th.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-tr.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-uk.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-vi.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-zh-CN.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-zh-HK.js create mode 100644 plugins/jqueryui/js/i18n/jquery.ui.datepicker-zh-TW.js create mode 100755 plugins/jqueryui/js/jquery-ui-1.8.14.custom.min.js create mode 100644 plugins/jqueryui/themes/default/images/buttongradient.png create mode 100644 plugins/jqueryui/themes/default/images/listheader.png create mode 100755 plugins/jqueryui/themes/default/images/ui-bg_flat_0_aaaaaa_40x100.png create mode 100755 plugins/jqueryui/themes/default/images/ui-bg_flat_75_ffffff_40x100.png create mode 100755 plugins/jqueryui/themes/default/images/ui-bg_flat_90_cc3333_40x100.png create mode 100755 plugins/jqueryui/themes/default/images/ui-bg_glass_95_fef1ec_1x400.png create mode 100755 plugins/jqueryui/themes/default/images/ui-bg_highlight-hard_90_a3a3a3_1x100.png create mode 100755 plugins/jqueryui/themes/default/images/ui-bg_highlight-hard_90_e6e6e7_1x100.png create mode 100755 plugins/jqueryui/themes/default/images/ui-bg_highlight-hard_90_f4f4f4_1x100.png create mode 100755 plugins/jqueryui/themes/default/images/ui-icons_000000_256x240.png create mode 100755 plugins/jqueryui/themes/default/images/ui-icons_333333_256x240.png create mode 100755 plugins/jqueryui/themes/default/images/ui-icons_666666_256x240.png create mode 100755 plugins/jqueryui/themes/default/images/ui-icons_cc3333_256x240.png create mode 100755 plugins/jqueryui/themes/default/images/ui-icons_dddddd_256x240.png create mode 100755 plugins/jqueryui/themes/default/jquery-ui-1.8.14.custom.css create mode 100644 plugins/jqueryui/themes/default/roundcube-custom.diff create mode 100755 plugins/jqueryui/themes/redmond/images/ui-bg_flat_0_aaaaaa_40x100.png create mode 100755 plugins/jqueryui/themes/redmond/images/ui-bg_flat_55_fbec88_40x100.png create mode 100755 plugins/jqueryui/themes/redmond/images/ui-bg_glass_75_d0e5f5_1x400.png create mode 100755 plugins/jqueryui/themes/redmond/images/ui-bg_glass_85_dfeffc_1x400.png create mode 100755 plugins/jqueryui/themes/redmond/images/ui-bg_glass_95_fef1ec_1x400.png create mode 100755 plugins/jqueryui/themes/redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png create mode 100755 plugins/jqueryui/themes/redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png create mode 100755 plugins/jqueryui/themes/redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png create mode 100755 plugins/jqueryui/themes/redmond/images/ui-icons_217bc0_256x240.png create mode 100755 plugins/jqueryui/themes/redmond/images/ui-icons_2e83ff_256x240.png create mode 100755 plugins/jqueryui/themes/redmond/images/ui-icons_469bdd_256x240.png create mode 100755 plugins/jqueryui/themes/redmond/images/ui-icons_6da8d5_256x240.png create mode 100755 plugins/jqueryui/themes/redmond/images/ui-icons_cd0a0a_256x240.png create mode 100755 plugins/jqueryui/themes/redmond/images/ui-icons_d8e7f3_256x240.png create mode 100755 plugins/jqueryui/themes/redmond/images/ui-icons_f9bd01_256x240.png create mode 100755 plugins/jqueryui/themes/redmond/jquery-ui-1.8.14.custom.css create mode 100644 plugins/managesieve/lib/rcube_sieve_script.php create mode 100644 plugins/managesieve/localization/gl_ES.inc create mode 100644 plugins/managesieve/localization/hr_HR.inc create mode 100644 plugins/markasjunk/localization/gl_ES.inc create mode 100644 plugins/markasjunk/localization/it_IT.inc create mode 100644 plugins/newmail_notifier/config.inc.php.dist create mode 100644 plugins/newmail_notifier/favicon.ico create mode 100644 plugins/newmail_notifier/localization/en_US.inc create mode 100644 plugins/newmail_notifier/localization/pl_PL.inc create mode 100644 plugins/newmail_notifier/newmail_notifier.js create mode 100644 plugins/newmail_notifier/newmail_notifier.php create mode 100644 plugins/newmail_notifier/sound.wav create mode 100644 plugins/password/localization/gl_ES.inc create mode 100644 plugins/password/localization/hr_HR.inc create mode 100644 plugins/redundant_attachments/config.inc.php.dist create mode 100644 plugins/redundant_attachments/redundant_attachments.php create mode 100644 plugins/subscriptions_option/localization/gl_ES.inc create mode 100644 plugins/userinfo/localization/gl_ES.inc create mode 100644 plugins/userinfo/localization/pt_BR.inc create mode 100644 plugins/vcard_attachments/localization/gl_ES.inc create mode 100644 plugins/vcard_attachments/localization/pt_BR.inc create mode 100644 program/.htaccess delete mode 100644 program/include/main.inc.orig delete mode 100644 program/include/rcmail.php.orig create mode 100644 program/include/rcube_cache.php create mode 100644 program/include/rcube_spellchecker.php delete mode 100644 program/js/jquery-1.4.min.js create mode 100644 program/js/jquery.min.js delete mode 100644 program/js/tiny_mce/plugins/media/css/content.css rename program/js/tiny_mce/{plugins/media => themes/advanced}/img/flash.gif (100%) create mode 100644 program/js/tiny_mce/themes/advanced/img/iframe.gif create mode 100644 program/js/tiny_mce/themes/advanced/img/pagebreak.gif rename program/js/tiny_mce/{plugins/media => themes/advanced}/img/quicktime.gif (100%) rename program/js/tiny_mce/{plugins/media => themes/advanced}/img/realmedia.gif (100%) rename program/js/tiny_mce/{plugins/media => themes/advanced}/img/shockwave.gif (100%) rename program/js/tiny_mce/{plugins/media => themes/advanced}/img/trans.gif (100%) create mode 100644 program/js/tiny_mce/themes/advanced/img/video.gif rename program/js/tiny_mce/{plugins/media => themes/advanced}/img/windowsmedia.gif (100%) create mode 100644 program/steps/addressbook/undo.inc create mode 100644 program/steps/addressbook/upload_photo.inc delete mode 100644 program/steps/utils/spell_googie.inc create mode 100644 program/steps/utils/spell_html.inc delete mode 100644 program/steps/utils/spell_html_googie.inc delete mode 100644 program/steps/utils/spell_html_pspell.inc delete mode 100644 program/steps/utils/spell_pspell.inc create mode 100644 skins/default/images/contactpic.png delete mode 100644 skins/default/images/mailbox_list.gif delete mode 100644 skins/default/images/mailbox_selected.gif create mode 100644 skins/default/images/quota-colors.png create mode 100644 skins/default/images/quota.png delete mode 100644 skins/default/includes/messagemenu.html create mode 100644 skins/default/includes/messagetoolbar.html delete mode 100644 skins/default/includes/replyallmenu.html create mode 100644 skins/default/templates/contactsearch.html diff --git a/.htaccess b/.htaccess index 704779e..2bc9f95 100644 --- a/.htaccess +++ b/.htaccess @@ -29,6 +29,9 @@ php_value mbstring.func_overload 0 RewriteEngine On RewriteRule ^favicon.ico$ skins/default/images/favicon.ico +# security rules +RewriteRule .svn/ - [F] +RewriteRule ^README|INSTALL|LICENSE|SQL|bin|CHANGELOG$ - [F] @@ -46,5 +49,4 @@ ExpiresDefault "access plus 1 month" FileETag MTime Size - - +Options -Indexes diff --git a/CHANGELOG b/CHANGELOG index c56a199..f4daec4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,193 +1,96 @@ CHANGELOG Roundcube Webmail =========================== -- Fix XSS vulnerability in UI messages (#1488030) -- Fix identities "reply-to" and "bcc" fields have a bogus value when left empty (#1487943) -- Fix issue which cases IMAP disconnection when encrypt() method was used (#1487900) -- Fix some CSS issues in Settings for Internet Explorer -- Fixed handling of folder with name "0" in folder selector -- Fix bug where messages were deleted instead moved to trash folder after Shift key was used (#1487902) -- Fix relative URLs handling according to a in HTML (#1487889) -- Fix handling of top-level domains with more than 5 chars or unicode chars (#1487883) -- Fix usage of non-standard HTTP error codes (#1487797) -- Fix PHP warning on mistaken in_array() usage (#1487901) +- Fix bug where the last identity is used on reply (#1488101) +- Fix locked folder rename option on servers supporting RFC2086 only (#1488089) +- Fix encoding of LDAP contacts identifiers (#1488079) +- Fix session race conditions when composing new messages +- jQuery 1.6.4 +- Fix handling of binary attachments encoded with quoted-printable (#1488065) +- Fix text-overflow:ellipsis issues on messages list in FF7 and Webkit (#1488061) +- Fix handling of links with IP address +- Fix bug where message list filter was reset on folder compacting (#1488076) -RELEASE 0.5.2 -------------- -- TinyMCE 3.4.2 now compatible with IE9 -- PEAR::Net_SMTP 1.5.2, fixed timeout issue (#1487843) -- Fix bug where template name without plugin prefix was used in render_page hook -- Support 'abort' and 'result' response in 'preferences_save' hook, add error handling -- Fix bug where some content would cause hang on html2text conversion (#1487863) -- Improve space-stuffing handling in format=flowed messages (#1487861) -- Fix bug where some dates would produce SQL error in MySQL (#1487856) -- Added workaround for some IMAP server with broken STATUS response (#1487859) -- Fix bug where default_charset was not used for text messages (#1487836) -- Stateless request tokens. No keep-alive necessary on login page (#1487829) -- Force names of unique constraints in PostgreSQL DDL -- Add code for prevention from IMAP connection hangs when server closes socket unexpectedly -- Remove redundant DELETE query (for old session deletion) on login -- Get around unreliable rand() and mt_rand() in session ID generation (#1486281) -- Fix some emails are not shown using Cyrus IMAP (#1487820) -- Fix handling of mime-encoded words with non-integral number of octets in a word (#1487801) -- Fix parsing links with non-printable characters inside (#1487805) -- Fixed de_CH/de_DE localization bugs (#1487773) -- Add variable for 'Today' label in date_today option (#1486120) -- Applied plugin changes since 0.5-stable release -- Fix SQL query in rcube_user::query() so it uses index on MySQL again -- Use only one from IMAP authentication methods to prevent login delays (1487784) -- Fix strftime format support in date_today option -- Removed redundant tags from contact add/edit pages -- Fix CSS error in contact details screen on IE7 (#1487775) - -RELEASE 0.5.1 -------------- -- Fix handling of attachments with invalid content type (#1487767) -- Add workaround for DBMail's bug http://www.dbmail.org/mantis/view.php?id=881 (#1487766) -- Use IMAP's ID extension (RFC2971) to print more info into debug log -- Security: add optional referer check to prevent CSRF in GET requests -- Fix email_dns_check setting not used for identities/contacts (#1487740) -- Fix ICANN example addresses doesn't validate (#1487742) -- Security: protect login form submission from CSRF -- Security: prevent from relaying malicious requests through modcss.inc -- Fix handling of non-image attachments in multipart/related messages (#1487750) -- Fix IDNA support when IDN/INTL modules are in use (#1487742) -- Fix handling of invalid HTML comments in messages (#1487759) -- Fix parsing FETCH response for very long headers (#1487753) -- Fix add/remove columns in message list when message_sort_order isn't set (#1487751) -- Fix settings UI on IE 6 (#1487724) -- Remove double borders in folder listing (#1487713) -- Separate full message headers UI element from headers table (#1487715) -- Add part MIME ID to message_part_* hooks (#1487718) -- Updated PEAR::Net_Socket to 1.0.10 -- Updated PEAR::Net_IDNA2 to 0.1.1 -- Fix handling of comments inside an email address spec. (#1487673) -- Show full mail subject as title when hovering a cut subject link (#1487128) -- Fix randomly disappearing folders list in IE (#1487704) -- Fix list column add/removal in IE (#1487703) -- Fix login redirect issues (#1487686) -- Require PHP 5.2.1 or greater -- Fix %h/%z variables in username_domain option (#1487701) -- Workaround for setting charset in case of malformed bodystructure response (#1487700) -- Fix impossible to subscribe to protected folders (#1487656) -- Fix setting timezone in Preferences (#1487705) - -RELEASE 0.5 ------------ -- Fix double-login/session issue (#1487104) -- Wrap HTML parts with and add Doctype declaration (#1487098) -- Make rcube_autoload silently skip unknown classes (#1487109) -- Fix charset detection in vcards with encoded values (#1485542) -- Better CSS cursors for splitters (#1486874) -- Show the same message only once (#1487641) -- Fix namespaces handling (#1487649) -- Add handling of multifolder METADATA/ANNOTATION responses -- Fix handling of INBOX when personal namespace prefix is non-empty (#1487657) -- Fix handling square brackets in links (#1487672) -- Add description of 'use_https' option in main.inc.php.dist file - -RELEASE 0.5-RC +RELEASE 0.6-RC -------------- -- Plugin API: Add 'pass' argument in 'authenticate' hook (#1487134) -- Fix attachments of type message/rfc822 are not listed on attachments list -- Add 'login_lc' config option for case-insensitive authentication (#1487113) -- Fix window is blur'ed in IE when selecting a message (#1487316) -- Fix cursor position on compose form in Webkit browsers (#1486674) -- Fix setting charset of attachment filenames (#1487122) -- Allow setting autocomplete attribute for all inputs separately (#1487313) -- New Folder Manager UI -- Fix invalid Request when creating a folder (#1487443) -- Add folder size and quota indicator in folder manager (#1485780) -- Add possibility to move a subfolder into root folder (#1486791) -- Fix copying all messages in a folder copies only messages from current page -- Improve performance of moving or copying of all messages in a folder -- Fix plaintext versions of HTML messages don't contain placeholders for emotions (#1485206) -- Improve performance of folder rename and delete actions -- Better support for READ-ONLY and NOPERM responses handling (#1487083) -- Add confirmation message on purge/expunge command response -- Fix handling of untagged responses for AUTHENTICATE command (#1487450) -- Add username and IP address to log message on unsuccessful login (#1487626) -- Improved Mail-Followup-To and Mail-Reply-To headers handling -- Fix charset conversion for text attachments without charset specification (#1487634) +- jQuery 1.6.3 +- Fallback to mail_domain in LDAP variable replacements; added 'host' to 'user_create' hook arguments (#1488024) +- Fixed wrong vCard type parameter mobile (#1488067) +- Fixed vCard WORKFAX issue (#1488046) +- Add vCard's Profile URL support (#1488062) +- Fix imap_cache setting to values other than 'db' (#1488060) +- Fix handling of attachments inside message/rfc822 parts (#1488026) +- Make list of mimetypes that open in preview window configurable (#1487625) +- Added plugin hook 'message_part_get' for attachment downloads +- Fixed selecting identity on reply/forward (#1487981) +- Fix image type check for contact photo uploads -RELEASE 0.5-BETA +RELEASE 0.6-beta ---------------- -- Make session data storage more robust against garbage session data (#1487136) -- Config option for autocomplete on login screen -- Allow plugin templates to include local files (#1487133) -- List groups in address detail view and allow to subscribe/unsubscribe from there (#1486753) -- Messages caching: performance improvements, fixed syncing, fixes related with #1486748 -- Add link to identities in compose window (#1486729) -- Add Internationalized Domain Name (IDNA) support (#1483894) -- Add option to automatically send read notifications for known senders (#1485883) -- Add option to "Return receipt" will be always checked (#1486352) -- Fix HTML to plain text conversion doesn't handle citation blocks (#1486921) -- Use custom sorting when SORT is disabled by IMAP admin (#1486959) -- Allow setting some washtml options from plugin (#1486578) -- Add option do bind for an individual LDAP address book (#1486997) -- Change reply prefix to display email address only if sender name doesn't exist (#1486550) -- Plugin API: improved 'abort' flag handling, added 'result' item in some hooks (#1486914) -- Fix mailto optional params in plain text messages aren't handled (#1487026) -- Add Reply-to-List feature (#1484252) -- Add Mail-Followup-To/Mail-Reply-To support (#1485547) -- Fix confirmation message isn't displayed after sending mail on Chrome (#1486177) -- Fix keyboard doesn't work with autocomplete list with Chrome (#1487029) -- Improve tabs to fixed width and add tabs in identities info (#1486974) -- Add unique index on users.username+users.mail_host -- Make htmleditor option more consistent and add option to use HTML on reply to HTML message (#1485840) -- Use empty envelope sender address for message disposition notifications (RFC 2298.3) -- Support SMTP Delivery Status Notifications - RFC 3461 (#1486142) -- Use css sprite image for messages list -- Add (different) attachment icon for messages of type multipart/report (#1486165) -- Prevent from inserting empty link when composing HTML message (#1486944) -- Add caching support in id2uid and uid2id functions (#1487019) -- Add SASL proxy authentication for SMTP (#1486693) -- Improve displaying of UI messages (#1486977) -- Fix double e-mail filed in identity form (#1487054) -- Display IMAP errors for LIST/THREAD/SEARCH commands (#1486905) -- Add LITERAL+ (IMAP4 non-synchronizing literals) support (RFC 2088) -- Add separate column for message status icon (#1486665) -- Add ACL extension support into IMAP classes (RFC 4314) -- Add ANNOTATEMORE extension support into IMAP classes (draft-daboo-imap-annotatemore) -- Add METADATA extension support into IMAP classes (RFC 5464) -- Fix decoding of e-mail address strings in message headers (#1487068) -- Fix handling of attachments when Content-Disposition is not inline nor attachment (#1487051) -- Improve performance of unseen messages counting (#1487058) -- Improve performance of messages counting using ESEARCH extension (RFC4731) -- Add LIST-STATUS support in rcube_imap_generic class (RFC 5819) -- Add SASL-IR support in IMAP (RFC 4959) -- Add LOGINDISABLED support (RFC 2595) -- Add support for AUTH=PLAIN in IMAP authentication -- Re-implemented SMTP proxy authentication support -- Add support for IMAP proxy authentication (#1486690) -- Add support for AUTH=DIGEST-MD5 in IMAP (RFC 2831) -- Fix parent folder with unread subfolder not bold when message is open (#1487078) -- Add basic IMAP LIST's \Noselect option support -- Add support for selection options from LIST-EXTENDED extension (RFC 5258) -- Don't list subscribed but non-existent folders (#1486225) -- Fix handling of URLs with tilde (~) or semicolon (;) character (#1487087, #1487088) -- Plugin API: added 'contact_form' hook -- Add SORT=DISPLAY support (RFC 5957) -- Plugin API: add possibility to disable plugin in AJAX mode, 'noajax' property -- Plugin API: add possibility to disable plugin in framed mode, 'noframe' property -- Improve performance of setting IMAP flags using .SILENT suffix -- Improve performance of message cache status checking with skip_disabled=true -- Support contact's email addresses up to 255 characters long (#1487095) -- Add option to place replies in the folder of the message being replied to (#1485945) -- Add missing confirmation/error messages on contact/group/message actions (#1486845) -- Add 'loading' message on message move/copy/delete/mark actions -- Improve responsiveness of messages displaying (#1486986) -- Add option for minimum length of autocomplete's string (#1486428) -- Fix operations on messages in unsubscribed folder (#1487107) -- Add support for shared folders (#1403507) -- Fix handling of folders with name "0" (#1487119) -- Fix handling of folders with "<>" characters in name -- jQuery 1.4.4 -- Fix handling of HTML entity strings in plain text messages -- Fix focused elements aren't unfocused when clicking on the list (#1487123) -- Fix error in MSSQL DDL scripts (#1487112) -- Lock submit button in onsubmit event on login page (#1487036) -- Don't set attachment's charset in Content-type header (#1487122) -- Fix handling of message bodies (quoted-printable encoded) with NULL characters (#1486189) -- Add workaround for MSOE's multipart/related messages with non-related attachments - +- Added unique connection identifier to IMAP debug messages +- Add option to hide selected LDAP addressbook on the list +- Add client-side checking of uploaded files size +- Add newlines between organization, department, jobtitle (#1488028) +- Recalculate date when replying to a message and localize the cite header (#1487675) +- Fix handling of email addresses with quoted local part (#1487939) +- Fix EOL character in vCard exports (#1487873) +- Added optional "multithreading" autocomplete feature +- Plugin API: Added 'config_get' hook +- Fixed new_user_identity plugin to work with updated rcube_ldap class (#1487994) +- Plugin API: added folder_delete and folder_rename hooks +- Added possibility to undo last contact delete operation +- Fix sorting of contact groups after group create (#1487747) +- Add optional textual upload progress indicator (#1486039) +- Fix parsing URLs containing commas (#1487970) +- Added vertical splitter for books/groups list in addressbook (#1487923) +- Improved namespace roots handling in folder manager +- Added searching in all addressbook sources +- Added addressbook source selection in contacts import +- Implement LDAPv3 Virtual List View (VLV) for paged results listing +- Use 'address_template' config option when adding a new address block (#1487944) +- Added addressbook advanced search +- Add popup with basic fields selection for addressbook search +- Case-insensitive matching in autocompletion (#1487933) +- Added option to force spellchecking before sending a message (#1485458) +- Fix handling of "<" character in contact data, search fields and folder names (#1487864) +- Fix saving "<" character in identity name and organization fields (#1487864) +- Added option to specify to which address book add new contacts +- Added plugin hook for keep-alive requests +- Store user preferences in session when write-master is not available and session is stored in memcache, write them later +- Improve performence of folder manager operations +- Fix default_port option handling in Installer when config.inc.php file exists (#1487925) +- Removed option focus_on_new_message, added newmail_notifier plugin +- Added general rcube_cache class with Memcache and APC support +- Improved caching performance by skipping writes of unchanged data +- Option enable_caching replaced by imap_cache and messages_cache options +- Fix WORKFAX saving in address book (#1487910) +- Add forward-as-attachment feature +- jQuery-1.6.2 (#1487913, #1487144) +- Improve display name composition when saving contacts (#1487143) +- Fix problems with subfolders of INBOX folder on some IMAP servers (#1487725) +- Fix handling of folders that doesn't belong to any namespace (#1487637) +- Enable multiselection for attachments uploading in capable browsers (#1485969) +- Add possibility to change HTML editor configuration by skin +- Fix a bug where selecting too many contacts would produce too large URI request (#1487892) +- Improve performance by including files with absolute path (#1487849) +- Move folder name truncation to client/skin (#1485412) +- Added plugin hook for request token creation +- Replace LDAP vars in group queries (#1487837) +- Fix vcard folding with uncode characters (#1487868) +- Keep all submitted data if contact form validation fails (#1487865) +- Handle uncode strings in rcube_addressbook::normalize_string() (#1487866) +- Fix handling of debug_level=4 in ajax requests (#1487831) +- Enable TinyMCE's contextmenu (#1487014) +- Allow multiple concurrent compose sessions +- New config option for custom logo +- Allow skins to define/override texts with +- Add simple ACL rights/namespace handling in folder manager +- Force IE to send referers (#1487806) +- Better display of vcard import results (#1485457) +- Improved vcard import +- Interactive update script with improved DB schema check +- Fix problem with contactgroupmembers table creation on MySQL 4.x, add index on contact_id column +- Add LDAP SASL bind and proxy authentication (#1486692) +- Replying to a sent message puts the old recipient as the new recipient (#1487074) +- Fulltext search over (almost) all data for contacts +- Extend address book with rich contact information diff --git a/INSTALL b/INSTALL index ed51b13..9b07b2b 100644 --- a/INSTALL +++ b/INSTALL @@ -22,6 +22,7 @@ REQUIREMENTS - MDB2 2.5.0 or newer - Mail_Mime 1.8.1 or newer - Net_SMTP 1.4.2 or newer + - Net_IDNA2 0.1.1 or newer - Auth_SASL 1.0.3 or newer * php.ini options (see .htaccess file): - error_reporting E_ALL & ~E_NOTICE (or lower) @@ -31,6 +32,7 @@ REQUIREMENTS - zend.ze1_compatibility_mode disabled - suhosin.session.encrypt disabled - mbstring.func_overload disabled + - magic_quotes_runtime disabled * PHP compiled with OpenSSL to connect to IMAPS and to use the spell checker * A MySQL (4.0.8 or newer), PostgreSQL, MSSQL database engine or the SQLite extension for PHP diff --git a/INSTALL.orig b/INSTALL.orig deleted file mode 100644 index 49aae92..0000000 --- a/INSTALL.orig +++ /dev/null @@ -1,231 +0,0 @@ -INTRODUCTION -============ - -This file describes the basic steps to install Roundcube Webmail on your -web server. For additional information, please also consult the project's -wiki page at http://trac.roundcube.net/wiki - - -REQUIREMENTS -============ - -* The Apache or Lighttpd Webserver -* .htaccess support allowing overrides for DirectoryIndex -* PHP Version 5.2.1 or greater including - - PCRE, DOM, JSON, XML, Session, Sockets (required) - - libiconv (recommended) - - mbstring, fileinfo, mcrypt (optional) -* PEAR packages distributed with Roundcube or external: - - MDB2 2.5.0 or newer - - Mail_Mime 1.8.1 or newer - - Net_SMTP 1.4.2 or newer - - Auth_SASL 1.0.3 or newer -* php.ini options (see .htaccess file): - - error_reporting E_ALL & ~E_NOTICE (or lower) - - memory_limit > 16MB (increase as suitable to support large attachments) - - file_uploads enabled (for attachment upload features) - - session.auto_start disabled - - zend.ze1_compatibility_mode disabled - - suhosin.session.encrypt disabled - - mbstring.func_overload disabled -* PHP compiled with OpenSSL to connect to IMAPS and to use the spell checker -* A MySQL (4.0.8 or newer), PostgreSQL, MSSQL database engine - or the SQLite extension for PHP -* One of the above databases with permission to create tables -* An SMTP server (recommended) or PHP configured for mail delivery - - -INSTALLATION -============ - -1. Decompress and put this folder somewhere inside your document root -2. Make sure that the following directories (and the files within) - are writable by the webserver - - /temp - - /logs -3. Create a new database and a database user for Roundcube (see DATABASE SETUP) -4. Point your browser to http://url-to-roundcube/installer/ -5. Follow the instructions of the install script (or see MANUAL CONFIGURATION) -6. After creating and testing the configuration, remove the installer directory -7. Done! - - -CONFIGURATION HINTS -=================== - -Roundcube writes internal errors to the 'errors' log file located in the logs -directory which can be configured in config/main.inc.php. If you want ordinary -PHP errors to be logged there as well, enable the 'php_value error_log' line -in the .htaccess file and set the path to the log file accordingly. - -By default the session_path settings of PHP are not modified by Roundcube. -However if you want to limit the session cookies to the directory where -Roundcube resides you can uncomment and configure the according line -in the .htaccess file. - - -DATABASE SETUP -============== - -Note: Database for Roundcube must use UTF-8 character set. - -* MySQL -------- -Setting up the mysql database can be done by creating an empty database, -importing the table layout and granting the proper permissions to the -roundcube user. Here is an example of that procedure: - -# mysql -> CREATE DATABASE roundcubemail /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */; -> GRANT ALL PRIVILEGES ON roundcubemail.* TO roundcube@localhost - IDENTIFIED BY 'password'; -> quit - -# mysql roundcubemail < SQL/mysql.initial.sql - -Note 1: 'password' is the master password for the roundcube user. It is strongly -recommended you replace this with a more secure password. Please keep in -mind: You need to specify this password later in 'config/db.inc.php'. - - -* SQLite --------- -You need sqlite 2 (preferably 2.8) to setup the sqlite db -(sqlite 3.x also doesn't work at the moment). Here is -an example how you can setup the sqlite.db for roundcube: - -# sqlite -init SQL/sqlite.initial.sql sqlite.db -Loading resources from SQL/sqlite.initial.sql -SQLite version 2.8.16 -Enter ".help" for instructions -sqlite> .exit -# chmod o+rw sqlite.db - -Make sure your configuration points to the sqlite.db file and that the -webserver can write to the file and the directory containing the file. - - -* PostgreSQL ------------- -To use Roundcube with PostgreSQL support you have to follow these -simple steps, which have to be done as the postgres system user (or -which ever is the database superuser): - -$ createuser roundcube -$ createdb -O roundcube -E UNICODE roundcubemail -$ psql roundcubemail - -roundcubemail =# ALTER USER roundcube WITH PASSWORD 'the_new_password'; -roundcubemail =# \c - roundcube -roundcubemail => \i SQL/postgres.initial.sql - -All this has been tested with PostgreSQL 8.x and 7.4.x. Older -versions don't have a -O option for the createdb, so if you are -using that version you'll have to change ownership of the DB later. - - -Database cleaning ------------------ -Do keep your database slick and clean we recommend to periodically execute -bin/cleandb.sh which finally removes all records that are marked as deleted. -Best solution is to install a cronjob running this script daily. - - - -MANUAL CONFIGURATION -==================== - -First of all, rename the files config/*.inc.php.dist to config/*.inc.php. -You can then change these files according to your environment and your needs. -Details about the config parameters can be found in the config files. -See http://trac.roundcube.net/wiki/Howto_Install for even more guidance. - -You can also modify the default .htaccess file. This is necessary to -increase the allowed size of file attachments, for example: - php_value upload_max_filesize 2M - - -UPGRADING -========= - -If you already have a previous version of Roundcube installed, -please refer to the instructions in UPGRADING guide. - - -OPTIMISING -========== - -There are two forms of optimisation here, compression and caching, both aimed -at increasing an end user's experience using Roundcube Webmail. Compression -allows the static web pages to be delivered with less bandwidth. The index.php -of Roundcube Webmail already enables compression on its output. The settings -below allow compression to occur for all static files. Caching sets HTTP -response headers that enable a user's web client to understand what is static -and how to cache it. - -The caching directives used are: - * Etags - sets at tag so the client can request is the page has changed - * Cache-control - defines the age of the page and that the page is 'public' - This enables clients to cache javascript files that don't have private - information between sessions even if using HTTPS. It also allows proxies - to share the same cached page between users. - * Expires - provides another hint to increase the lifetime of static pages. - -For more information refer to RFC 2616. - -Side effects: -------------- -These directives are designed for production use. If you are using this in -a development environment you may get horribly confused if your webclient -is caching stuff that you changed on the server. Disabling the expires -parts below should save you some grief. - -If you are changing the skins, it is recommended that you copy content to -a different directory apart from 'default'. - -Apache: -------- -To enable these features in apache the following modules need to be enabled: - * mod_deflate - * mod_expires - * mod_headers - -The optimisation is already included in the .htaccess file in the top -directory of your installation. - -If you are using Apache version 2.2.9 and later, in the .htaccess file -change the 'append' word to 'merge' for a more correct response. Keeping -as 'append' shouldn't cause any problems though changing to merge will -eliminate the possibility of duplicate 'public' headers in Cache-control. - -Lighttpd: ---------- -With Lightty the addition of Expire: tags by mod_expire is incompatible with -the addition of "Cache-control: public". Using Cache-control 'public' is -used below as it is assumed to give a better caching result. - -Enable modules in server.modules: - "mod_setenv" - "mod_compress" - -Mod_compress is a server side cache of compressed files to improve its performance. - -$HTTP["host"] == "www.example.com" { - - static-file.etags = "enable" - # http://redmine.lighttpd.net/projects/lighttpd/wiki/Etag.use-mtimeDetails - etag.use-mtime = "enable" - - # http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs:ModSetEnv - $HTTP["url"] =~ "^/roundcubemail/(plugins|skins|program)" { - setenv.add-response-header = ( "Cache-Control" => "public, max-age=2592000") - } - - # http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs:ModCompress - # set compress.cache-dir to somewhere outside the docroot. - compress.cache-dir = var.statedir + "/cache/compress" - - compress.filetype = ("text/plain", "text/html", "text/javascript", "text/css", "text/xml", "image/gif", "image/png") -} - - diff --git a/SQL/mssql.initial.sql b/SQL/mssql.initial.sql index 823d1b3..4aa6fc9 100644 --- a/SQL/mssql.initial.sql +++ b/SQL/mssql.initial.sql @@ -16,7 +16,8 @@ CREATE TABLE [dbo].[contacts] ( [email] [varchar] (255) COLLATE Latin1_General_CI_AI NOT NULL , [firstname] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL , [surname] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL , - [vcard] [text] COLLATE Latin1_General_CI_AI NULL + [vcard] [text] COLLATE Latin1_General_CI_AI NULL , + [words] [text] COLLATE Latin1_General_CI_AI NULL ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO @@ -194,6 +195,8 @@ ALTER TABLE [dbo].[contactgroupmembers] ADD CONSTRAINT [DF_contactgroupmembers_created] DEFAULT (getdate()) FOR [created] GO +CREATE INDEX [IX_contactgroupmembers_contact_id] ON [dbo].[contactgroupmembers]([contact_id]) ON [PRIMARY] +GO ALTER TABLE [dbo].[identities] ADD CONSTRAINT [DF_identities_user] DEFAULT ('0') FOR [user_id], diff --git a/SQL/mssql.upgrade.sql b/SQL/mssql.upgrade.sql index 4072c25..606db60 100644 --- a/SQL/mssql.upgrade.sql +++ b/SQL/mssql.upgrade.sql @@ -96,4 +96,17 @@ CREATE UNIQUE INDEX [IX_users_username] ON [dbo].[users]([username],[mail_host]) GO ALTER TABLE [dbo].[contacts] ALTER COLUMN [email] [varchar] (255) COLLATE Latin1_General_CI_AI NOT NULL GO - + +-- Updates from version 0.5.1 +-- Updates from version 0.5.2 +-- Updates from version 0.5.3 +-- Updates from version 0.5.4 + +ALTER TABLE [dbo].[contacts] ADD [words] [text] COLLATE Latin1_General_CI_AI NULL +GO +CREATE INDEX [IX_contactgroupmembers_contact_id] ON [dbo].[contactgroupmembers]([contact_id]) ON [PRIMARY] +GO +DELETE FROM [dbo].[messages] +GO +DELETE FROM [dbo].[cache] +GO diff --git a/SQL/mysql.initial.sql b/SQL/mysql.initial.sql index 6e2c247..14bbb96 100644 --- a/SQL/mysql.initial.sql +++ b/SQL/mysql.initial.sql @@ -86,7 +86,8 @@ CREATE TABLE `contacts` ( `email` varchar(255) NOT NULL, `firstname` varchar(128) NOT NULL DEFAULT '', `surname` varchar(128) NOT NULL DEFAULT '', - `vcard` text NULL, + `vcard` longtext NULL, + `words` text NULL, `user_id` int(10) UNSIGNED NOT NULL DEFAULT '0', PRIMARY KEY(`contact_id`), CONSTRAINT `user_id_fk_contacts` FOREIGN KEY (`user_id`) @@ -116,7 +117,8 @@ CREATE TABLE `contactgroupmembers` ( CONSTRAINT `contactgroup_id_fk_contactgroups` FOREIGN KEY (`contactgroup_id`) REFERENCES `contactgroups`(`contactgroup_id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `contact_id_fk_contacts` FOREIGN KEY (`contact_id`) - REFERENCES `contacts`(`contact_id`) ON DELETE CASCADE ON UPDATE CASCADE + REFERENCES `contacts`(`contact_id`) ON DELETE CASCADE ON UPDATE CASCADE, + INDEX `contactgroupmembers_contact_index` (`contact_id`) ) /*!40000 ENGINE=INNODB */; diff --git a/SQL/mysql.update.sql b/SQL/mysql.update.sql index aaab43f..ed21bda 100644 --- a/SQL/mysql.update.sql +++ b/SQL/mysql.update.sql @@ -133,3 +133,14 @@ ALTER TABLE `contacts` MODIFY `email` varchar(255) NOT NULL; TRUNCATE TABLE `messages`; +-- Updates from version 0.5.1 +-- Updates from version 0.5.2 +-- Updates from version 0.5.3 +-- Updates from version 0.5.4 + +ALTER TABLE `contacts` ADD `words` TEXT NULL AFTER `vcard`; +ALTER TABLE `contacts` CHANGE `vcard` `vcard` LONGTEXT /*!40101 CHARACTER SET utf8 */ NULL DEFAULT NULL; +ALTER TABLE `contactgroupmembers` ADD INDEX `contactgroupmembers_contact_index` (`contact_id`); + +TRUNCATE TABLE `messages`; +TRUNCATE TABLE `cache`; diff --git a/SQL/postgres.initial.sql b/SQL/postgres.initial.sql index d6f4db7..5350e79 100644 --- a/SQL/postgres.initial.sql +++ b/SQL/postgres.initial.sql @@ -103,14 +103,15 @@ CREATE SEQUENCE contact_ids CREATE TABLE contacts ( contact_id integer DEFAULT nextval('contact_ids'::text) PRIMARY KEY, user_id integer NOT NULL - REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE, + REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE, changed timestamp with time zone DEFAULT now() NOT NULL, del smallint DEFAULT 0 NOT NULL, name varchar(128) DEFAULT '' NOT NULL, email varchar(255) DEFAULT '' NOT NULL, firstname varchar(128) DEFAULT '' NOT NULL, surname varchar(128) DEFAULT '' NOT NULL, - vcard text + vcard text, + words text ); CREATE INDEX contacts_user_id_idx ON contacts (user_id, email); @@ -156,6 +157,8 @@ CREATE TABLE contactgroupmembers ( PRIMARY KEY (contactgroup_id, contact_id) ); +CREATE INDEX contactgroupmembers_contact_id_idx ON contactgroupmembers (contact_id); + -- -- Sequence "cache_ids" -- Name: cache_ids; Type: SEQUENCE; Schema: public; Owner: postgres diff --git a/SQL/postgres.update.sql b/SQL/postgres.update.sql index 0ae8d3f..94513c5 100644 --- a/SQL/postgres.update.sql +++ b/SQL/postgres.update.sql @@ -89,3 +89,14 @@ ALTER TABLE users ADD CONSTRAINT users_username_key UNIQUE (username, mail_host) ALTER TABLE contacts ALTER email TYPE varchar(255); TRUNCATE messages; + +-- Updates from version 0.5.1 +-- Updates from version 0.5.2 +-- Updates from version 0.5.3 +-- Updates from version 0.5.4 + +ALTER TABLE contacts ADD words TEXT NULL; +CREATE INDEX contactgroupmembers_contact_id_idx ON contactgroupmembers (contact_id); + +TRUNCATE messages; +TRUNCATE cache; diff --git a/SQL/sqlite.initial.sql b/SQL/sqlite.initial.sql index 875b3cb..d2885e9 100644 --- a/SQL/sqlite.initial.sql +++ b/SQL/sqlite.initial.sql @@ -31,7 +31,8 @@ CREATE TABLE contacts ( email varchar(255) NOT NULL default '', firstname varchar(128) NOT NULL default '', surname varchar(128) NOT NULL default '', - vcard text NOT NULL default '' + vcard text NOT NULL default '', + words text NOT NULL default '' ); CREATE INDEX ix_contacts_user_id ON contacts(user_id, email); @@ -55,6 +56,8 @@ CREATE TABLE contactgroupmembers ( PRIMARY KEY (contactgroup_id, contact_id) ); +CREATE INDEX ix_contactgroupmembers_contact_id ON contactgroupmembers (contact_id); + -- -------------------------------------------------------- diff --git a/SQL/sqlite.update.sql b/SQL/sqlite.update.sql index 6f2acf9..30c3ae9 100644 --- a/SQL/sqlite.update.sql +++ b/SQL/sqlite.update.sql @@ -182,3 +182,47 @@ DROP TABLE contacts_tmp; DELETE FROM messages; + +-- Updates from version 0.5.1 +-- Updates from version 0.5.2 +-- Updates from version 0.5.3 +-- Updates from version 0.5.4 + +CREATE TABLE contacts_tmp ( + contact_id integer NOT NULL PRIMARY KEY, + user_id integer NOT NULL default '0', + changed datetime NOT NULL default '0000-00-00 00:00:00', + del tinyint NOT NULL default '0', + name varchar(128) NOT NULL default '', + email varchar(255) NOT NULL default '', + firstname varchar(128) NOT NULL default '', + surname varchar(128) NOT NULL default '', + vcard text NOT NULL default '' +); + +INSERT INTO contacts_tmp (contact_id, user_id, changed, del, name, email, firstname, surname, vcard) + SELECT contact_id, user_id, changed, del, name, email, firstname, surname, vcard FROM contacts; + +DROP TABLE contacts; +CREATE TABLE contacts ( + contact_id integer NOT NULL PRIMARY KEY, + user_id integer NOT NULL default '0', + changed datetime NOT NULL default '0000-00-00 00:00:00', + del tinyint NOT NULL default '0', + name varchar(128) NOT NULL default '', + email varchar(255) NOT NULL default '', + firstname varchar(128) NOT NULL default '', + surname varchar(128) NOT NULL default '', + vcard text NOT NULL default '', + words text NOT NULL default '' +); + +INSERT INTO contacts (contact_id, user_id, changed, del, name, email, firstname, surname, vcard) + SELECT contact_id, user_id, changed, del, name, email, firstname, surname, vcard FROM contacts_tmp; + +CREATE INDEX ix_contacts_user_id ON contacts(user_id, email); +DROP TABLE contacts_tmp; + +DELETE FROM messages; +DELETE FROM cache; +CREATE INDEX ix_contactgroupmembers_contact_id ON contactgroupmembers (contact_id); diff --git a/UPGRADING b/UPGRADING index 329983d..ce951d1 100644 --- a/UPGRADING +++ b/UPGRADING @@ -3,7 +3,30 @@ UPGRADING instructions Follow these instructions if upgrading from a previous version of Roundcube Webmail. We recommend to carefully backup the existing -installation as well as the database before executig the following steps. +installation as well as the database before going through the following steps. + +Using the update script +----------------------- +There is a shell script (for unix based systems) that does the job for you. +To use it, unpack the archive of the new Roundcube version to a temporary location +(don't replace the Roundcube installation you want to update) +and cd into that directory. From there, run the following command in a shell: + + ./bin/installto.sh + +For you specify the path to the Roundcube installation +which should be updated. The update script will then copy all new files to the +target location and check and update the configuration and database schema. +After all is done, the temporary folder with the new Roundcube files can be +removed again. + +Please also see Post-Upgrade Activities section. + + +Updating manually +----------------- +If you don't have shell access to the Roundcube installation or if not running +it on a unix system, you need to do the following operations by hand: 1. Replace index.php and all files in - ./bin/ @@ -14,14 +37,18 @@ installation as well as the database before executig the following steps. - ./plugins/ 2. 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 enable the latter one, you have to temporary set 'enable_installer' + to true in your local config/main.inc.php file. 3. Let the update script/installer check your configuration and - update your config files as suggested by the updater. -4. If suggested by the update script, run all commands in - ./SQL/[yourdbtype].update.sql that are superscribed with the - currently installed version number. -5. Make sure 'enable_installer' is set to false again. -6. Check .htaccess settings (some php settings could become required) + update your config files and database schema as suggested by the updater. +4. Make sure 'enable_installer' is set to false again. +5. See Post-Upgrade Activities section. +Post-Upgrade Activities +----------------------- +1. Check .htaccess settings (some php settings could become required) +2. If you're using build-in addressbook, run indexing script /bin/indexcontacts.sh. +3. When upgrading from version older than 0.6-beta you should make sure + your folder settings contain namespace prefix. For example Courier users + should add INBOX. prefix to folder names in main configuration file. diff --git a/bin/cleandb.sh b/bin/cleandb.sh index 4d699cc..a1b38d0 100755 --- a/bin/cleandb.sh +++ b/bin/cleandb.sh @@ -6,7 +6,7 @@ | bin/cleandb.sh | | | | This file is part of the Roundcube Webmail client | - | Copyright (C) 2010, Roundcube Dev. - Switzerland | + | Copyright (C) 2010, The Roundcube Dev Team | | Licensed under the GNU GPL | | | | PURPOSE: | @@ -16,16 +16,13 @@ | Author: Thomas Bruederli | +-----------------------------------------------------------------------+ - $Id: cleandb.sh 4164 2010-10-31 10:38:16Z thomasb $ + $Id: cleandb.sh 4677 2011-04-20 13:10:45Z alec $ */ -if (php_sapi_name() != 'cli') { - die('Not on the "shell" (php-cli).'); -} - define('INSTALL_PATH', realpath(dirname(__FILE__) . '/..') . '/' ); -require INSTALL_PATH.'program/include/iniset.php'; + +require INSTALL_PATH.'program/include/clisetup.php'; // mapping for table name => primary key $primary_keys = array( diff --git a/bin/decrypt.sh b/bin/decrypt.sh index 8d6ff5e..75269ef 100755 --- a/bin/decrypt.sh +++ b/bin/decrypt.sh @@ -6,7 +6,7 @@ | bin/decrypt.sh | | | | This file is part of the Roundcube Webmail client | - | Copyright (C) 2005-2009, Roundcube Dev. - Switzerland | + | Copyright (C) 2005-2009, The Roundcube Dev Team | | Licensed under the GNU GPL | | | | PURPOSE: | @@ -16,7 +16,7 @@ | Author: Tomas Tevesz | +-----------------------------------------------------------------------+ - $Id: decrypt.sh 3989 2010-09-25 13:03:53Z alec $ + $Id: decrypt.sh 4677 2011-04-20 13:10:45Z alec $ */ /*- @@ -52,12 +52,9 @@ * - you are dealing with counterfeit header data. */ -if (php_sapi_name() != 'cli') { - die("Not on the 'shell' (php-cli).\n"); -} - define('INSTALL_PATH', realpath(dirname(__FILE__).'/..') . '/'); -require INSTALL_PATH . 'program/include/iniset.php'; + +require INSTALL_PATH . 'program/include/clisetup.php'; if ($argc < 2) { die("Usage: " . basename($argv[0]) . " encrypted-hdr-part [encrypted-hdr-part ...]\n"); diff --git a/bin/indexcontacts.sh b/bin/indexcontacts.sh new file mode 100755 index 0000000..d552be6 --- /dev/null +++ b/bin/indexcontacts.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env php + | + +-----------------------------------------------------------------------+ + + $Id: indexcontacts.sh 4623 2011-03-28 06:49:02Z alec $ + +*/ + +define('INSTALL_PATH', realpath(dirname(__FILE__) . '/..') . '/' ); + +require_once INSTALL_PATH.'program/include/clisetup.php'; + + +// connect to DB +$RCMAIL = rcmail::get_instance(); + +$db = $RCMAIL->get_dbh(); +$db->db_connect('w'); + +if (!$db->is_connected() || $db->is_error()) + die("No DB connection\n"); + +// iterate over all users +$sql_result = $db->query("SELECT user_id FROM " . $RCMAIL->config->get('db_table_users', 'users')." WHERE 1=1"); +while ($sql_result && ($sql_arr = $db->fetch_assoc($sql_result))) { + echo "Indexing contacts for user " . $sql_arr['user_id'] . "..."; + + $contacts = new rcube_contacts($db, $sql_arr['user_id']); + $contacts->set_pagesize(9999); + + $result = $contacts->list_records(); + while ($result->count && ($row = $result->next())) { + unset($row['words']); + $contacts->update($row['ID'], $row); + } + + echo "done.\n"; +} + +?> diff --git a/bin/installto.sh b/bin/installto.sh new file mode 100755 index 0000000..33652dc --- /dev/null +++ b/bin/installto.sh @@ -0,0 +1,70 @@ +#!/usr/bin/env php + | + +-----------------------------------------------------------------------+ + + $Id: installto.sh 4677 2011-04-20 13:10:45Z alec $ + +*/ + +define('INSTALL_PATH', realpath(dirname(__FILE__) . '/..') . '/' ); + +require_once INSTALL_PATH . 'program/include/clisetup.php'; + +$target_dir = unslashify($_SERVER['argv'][1]); + +if (empty($target_dir) || !is_dir(realpath($target_dir))) + die("Invalid target: not a directory\nUsage: installto.sh \n"); + +// read version from iniset.php +$iniset = @file_get_contents($target_dir . '/program/include/iniset.php'); +if (!preg_match('/define\(.RCMAIL_VERSION.,\s*.([0-9.]+[a-z-]*)/', $iniset, $m)) + die("No valid Roundcube installation found at $target_dir\n"); + +$oldversion = $m[1]; + +if (version_compare($oldversion, RCMAIL_VERSION, '>=')) + die("Installation at target location is up-to-date!\n"); + +echo "Upgrading from $oldversion. Do you want to continue? (y/N)\n"; +$input = trim(fgets(STDIN)); + +if (strtolower($input) == 'y') { + $err = false; + echo "Copying files to target location..."; + foreach (array('program','installer','bin','SQL','plugins','skins/default') as $dir) { + if (!system("rsync -avuC " . INSTALL_PATH . "$dir/* $target_dir/$dir/")) { + $err = true; + break; + } + } + foreach (array('index.php','.htaccess','config/main.inc.php.dist','config/db.inc.php.dist','CHANGELOG','README','UPGRADING') as $file) { + if (!system("rsync -avu " . INSTALL_PATH . "$file $target_dir/$file")) { + $err = true; + break; + } + } + echo "done.\n\n"; + + if (!$err) { + echo "Running update script at target...\n"; + system("cd $target_dir && bin/update.sh --version=$oldversion"); + echo "All done.\n"; + } +} +else + echo "Update cancelled. See ya!\n"; + +?> diff --git a/bin/jsshrink.sh b/bin/jsshrink.sh index b85f517..be5aad1 100755 --- a/bin/jsshrink.sh +++ b/bin/jsshrink.sh @@ -41,8 +41,3 @@ for fn in app common googiespell list; do echo "Shrinking $JS_DIR/${fn}.js" do_shrink "$JS_DIR/${fn}.js.src" "$JS_DIR/${fn}.js" done - -for fn in tiny_mce/tiny_mce; do - echo "Shrinking $JS_DIR/${fn}.js" - do_shrink "$JS_DIR/${fn}_src.js" "$JS_DIR/${fn}.js" -done diff --git a/bin/jsunshrink.sh b/bin/jsunshrink.sh index 90c3ea5..9d77550 100755 --- a/bin/jsunshrink.sh +++ b/bin/jsunshrink.sh @@ -12,13 +12,3 @@ for fn in app common googiespell list; do echo "Reverted $JS_DIR/${fn}.js" fi done - -for fn in tiny_mce/tiny_mce; do - if [ -d "$JS_DIR/.svn" ] && which svn >/dev/null 2>&1; then - rm -f "$JS_DIR/${fn}.js" - svn revert "$JS_DIR/${fn}.js" - else - cp "$JS_DIR/${fn}_src.js" "$JS_DIR/${fn}.js" - echo "Reverted $JS_DIR/${fn}.js" - fi -done diff --git a/bin/msgimport.sh b/bin/msgimport.sh index 74dc816..845c585 100755 --- a/bin/msgimport.sh +++ b/bin/msgimport.sh @@ -79,7 +79,7 @@ if ($IMAP->connect($host, $args['user'], $args['pass'], $imap_port, $imap_ssl)) $fp = fopen($args['file'], 'r'); while (($line = fgets($fp)) !== false) { - if (preg_match('/^From\s+/', $line) && $lastline == '') + if (preg_match('/^From\s+-/', $line) && $lastline == '') { if (!empty($message)) { diff --git a/bin/update.sh b/bin/update.sh index a298887..52ac637 100755 --- a/bin/update.sh +++ b/bin/update.sh @@ -1,13 +1,43 @@ #!/usr/bin/env php | + +-----------------------------------------------------------------------+ + + $Id$ + +*/ + define('INSTALL_PATH', realpath(dirname(__FILE__) . '/..') . '/' ); -require_once INSTALL_PATH . 'program/include/iniset.php'; +require_once INSTALL_PATH . 'program/include/clisetup.php'; require_once INSTALL_PATH . 'installer/rcube_install.php'; +// get arguments +$opts = get_opt(array('v' => 'version')); + +// ask user if no version is specified +if (!$opts['version']) { + echo "What version are you upgrading from? Type '?' if you don't know.\n"; + if (($input = trim(fgets(STDIN))) && preg_match('/^[0-9.]+[a-z-]*$/', $input)) + $opts['version'] = $input; +} + +if ($opts['version'] && version_compare($opts['version'], RCMAIL_VERSION, '>')) + die("Nothing to be done here. Bye!\n"); + + $RCI = rcube_install::get_instance(); $RCI->load_config(); @@ -88,7 +118,7 @@ if ($RCI->configured) { } } else { - echo "Please update your config files manually according to the above messages.\n"; + echo "Please update your config files manually according to the above messages.\n\n"; } } @@ -113,15 +143,29 @@ if ($RCI->configured) { echo "Error connecting to database: $db_error_msg\n"; $success = false; } - else if ($RCI->db_schema_check($DB, false)) { - $db_map = array('pgsql' => 'postgres', 'mysqli' => 'mysql', 'sqlsrv' => 'mssql'); - $updatefile = INSTALL_PATH . 'SQL/' . (isset($db_map[$DB->db_provider]) ? $db_map[$DB->db_provider] : $DB->db_provider) . '.update.sql'; + else if ($err = $RCI->db_schema_check($DB, false)) { + $updatefile = INSTALL_PATH . 'SQL/' . (isset($RCI->db_map[$DB->db_provider]) ? $RCI->db_map[$DB->db_provider] : $DB->db_provider) . '.update.sql'; echo "WARNING: Database schema needs to be updated!\n"; - echo "Open $updatefile and execute all queries that are superscribed with the currently installed version number\n"; + echo join("\n", $err) . "\n\n"; $success = false; + + if ($opts['version']) { + echo "Do you want to run the update queries to get the schmea fixed? (y/N)\n"; + $input = trim(fgets(STDIN)); + if (strtolower($input) == 'y') { + $success = $RCI->update_db($DB, $opts['version']); + } + } + + if (!$success) + echo "Open $updatefile and execute all queries below the comment with the currently installed version number.\n"; } } + // index contacts for fulltext searching + if (version_compare($opts['version'], '0.6', '<')) { + system(INSTALL_PATH . 'bin/indexcontacts.sh'); + } if ($success) { echo "This instance of Roundcube is up-to-date.\n"; diff --git a/config/db.inc.php.dist b/config/db.inc.php.dist index e8938a1..78cd968 100644 --- a/config/db.inc.php.dist +++ b/config/db.inc.php.dist @@ -5,7 +5,7 @@ | Configuration file for database access | | | | This file is part of the Roundcube Webmail client | - | Copyright (C) 2005-2009, Roundcube Dev. - Switzerland | + | Copyright (C) 2005-2009, The Roundcube Dev Team | | Licensed under the GNU GPL | | | +-----------------------------------------------------------------------+ diff --git a/config/main.inc.php.dist b/config/main.inc.php.dist index f00bfa8..824085c 100644 --- a/config/main.inc.php.dist +++ b/config/main.inc.php.dist @@ -5,7 +5,7 @@ | Main configuration file | | | | This file is part of the Roundcube Webmail client | - | Copyright (C) 2005-2010, Roundcube Dev. - Switzerland | + | Copyright (C) 2005-2010, The Roundcube Dev Team | | Licensed under the GNU GPL | | | +-----------------------------------------------------------------------+ @@ -41,6 +41,9 @@ $rcmail_config['smtp_log'] = true; // Log successful logins to /userlogins or to syslog $rcmail_config['log_logins'] = false; +// Log session authentication errors to /session or to syslog +$rcmail_config['log_session'] = false; + // Log SQL queries to /sql or to syslog $rcmail_config['sql_debug'] = false; @@ -64,6 +67,7 @@ $rcmail_config['smtp_debug'] = false; // Supported replacement variables: // %n - http hostname ($_SERVER['SERVER_NAME']) // %d - domain (http hostname without the first part) +// %s - domain name after the '@' from e-mail address provided at login screen // For example %n = mail.domain.tld, %d = domain.tld $rcmail_config['default_host'] = ''; @@ -108,6 +112,13 @@ $rcmail_config['imap_auth_cid'] = null; // Optional IMAP authentication password to be used for imap_auth_cid $rcmail_config['imap_auth_pw'] = null; +// Type of IMAP indexes cache. Supported values: 'db', 'apc' and 'memcache'. +$rcmail_config['imap_cache'] = null; + +// Enables messages cache. Only 'db' cache is supported. +$rcmail_config['messages_cache'] = false; + + // ---------------------------------- // SMTP // ---------------------------------- @@ -168,10 +179,6 @@ $rcmail_config['log_dir'] = 'logs/'; // use this folder to store temp files (must be writeable for apache user) $rcmail_config['temp_dir'] = 'temp/'; -// enable caching of messages and mailbox data in the local database. -// this is recommended if the IMAP server does not run on the same machine -$rcmail_config['enable_caching'] = false; - // lifetime of message cache // possible units: s, m, h, d, w $rcmail_config['message_cache_lifetime'] = '10d'; @@ -192,6 +199,8 @@ $rcmail_config['login_autocomplete'] = 0; // If users authentication is not case sensitive this must be enabled. // You can also use it to force conversion of logins to lower case. +// After enabling it all user records need to be updated, e.g. with query: +// UPDATE users SET username = LOWER(username); $rcmail_config['login_lc'] = false; // automatically create a new Roundcube user when log-in the first time. @@ -199,6 +208,10 @@ $rcmail_config['login_lc'] = false; // set to false if only registered users can use this service $rcmail_config['auto_create_user'] = true; +// replace Roundcube logo with this image +// specify an URL relative to the document root of this Roundcube installation +$rcmail_config['skin_logo'] = null; + // Includes should be interpreted as PHP files $rcmail_config['skin_include_php'] = false; @@ -206,16 +219,28 @@ $rcmail_config['skin_include_php'] = false; // must be greater than 'keep_alive'/60 $rcmail_config['session_lifetime'] = 10; +// session domain: .example.org +$rcmail_config['session_domain'] = ''; + +// Backend to use for session storage. Can either be 'db' (default) or 'memcache' +// If set to memcache, a list of servers need to be specified in 'memcache_hosts' +// Make sure the Memcache extension (http://pecl.php.net/package/memcache) version >= 2.0.0 is installed +$rcmail_config['session_storage'] = 'db'; + +// Use these hosts for accessing memcached +// Define any number of hosts in the form hostname:port +$rcmail_config['memcache_hosts'] = null; // e.g. array( 'localhost:11211', '192.168.1.12:11211' ); + // check client IP in session athorization $rcmail_config['ip_check'] = false; -// Use an additional frequently changing cookie to athenticate user sessions. -// There have been problems reported with this feature. -$rcmail_config['double_auth'] = false; - // check referer of incoming requests $rcmail_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'; + // 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. @@ -295,9 +320,6 @@ $rcmail_config['line_length'] = 72; // send plaintext messages as format=flowed $rcmail_config['send_format_flowed'] = true; -// session domain: .example.org -$rcmail_config['session_domain'] = ''; - // don't allow these settings to be overriden by the user $rcmail_config['dont_override'] = array(); @@ -308,9 +330,23 @@ $rcmail_config['dont_override'] = array(); // 3 - one identity with possibility to edit all params but not email address $rcmail_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 + // mime magic database $rcmail_config['mime_magic'] = '/usr/share/misc/magic'; +// path to imagemagick identify binary +$rcmail_config['im_identify_path'] = null; + +// path to imagemagick convert binary +$rcmail_config['im_convert_path'] = null; + +// maximum size of uploaded contact photos in pixel +$rcmail_config['contact_photo_size'] = 160; + // Enable DNS checking for e-mail address validation $rcmail_config['email_dns_check'] = false; @@ -350,23 +386,31 @@ $rcmail_config['date_long'] = 'd.m.Y H:i'; // Note: $ character will be replaced with 'Today' label $rcmail_config['date_today'] = 'H:i'; +// use this format for date display without time (date or strftime format) +$rcmail_config['date_format'] = 'Y-m-d'; + // 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'; // store spam messages in this mailbox +// NOTE: Use folder names with namespace prefix (INBOX. on Courier-IMAP) $rcmail_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'; // 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'; // 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_imap_folders'] = array('INBOX', 'Drafts', 'Sent', 'Junk', 'Trash'); // automatically create the above listed default folders on login @@ -405,6 +449,16 @@ $rcmail_config['max_pagesize'] = 200; // Must be less than 'session_lifetime' $rcmail_config['min_keep_alive'] = 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; + +// 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; + // ---------------------------------- // ADDRESSBOOK SETTINGS // ---------------------------------- @@ -418,9 +472,9 @@ $rcmail_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(); -// // 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. // @@ -448,6 +502,7 @@ $rcmail_config['ldap_public']['Verisign'] = array( 'hosts' => array('directory.verisign.com'), 'port' => 389, 'use_tls' => false, + 'ldap_version' => 3, // using LDAPv3 'user_specific' => false, // If true the base_dn, bind_dn and bind_pass default to the user's IMAP login. // %fu - The full username provided, assumes the username is an email // address, uses the username_domain value if not an email address. @@ -462,25 +517,65 @@ $rcmail_config['ldap_public']['Verisign'] = array( // The login name is used to search for the DN to bind with 'search_base_dn' => '', 'search_filter' => '', // e.g. '(&(objectClass=posixAccount)(uid=%u))' - - 'writable' => false, // Indicates if we can write to the LDAP directory or not. + // Optional authentication identifier to be used as SASL authorization proxy + // bind_dn need to be empty + 'auth_cid' => '', + // SASL authentication method (for proxy auth), e.g. DIGEST-MD5 + 'auth_method' => '', + // Indicates if the addressbook shall be displayed on the list. + // With this option enabled you can still search/view contacts. + 'hidden' => false, + // Indicates if we can write to the LDAP directory or not. // If writable is true then these fields need to be populated: // LDAP_Object_Classes, required_fields, LDAP_rdn - 'LDAP_Object_Classes' => array("top", "inetOrgPerson"), // To create a new contact these are the object classes to specify (or any other classes you wish to use). - 'required_fields' => array("cn", "sn", "mail"), // The required fields needed to build a new contact as required by the object classes (can include additional fields not required by the object classes). - 'LDAP_rdn' => 'mail', // The RDN field that is used for new entries, this field needs to be one of the search_fields, the base of base_dn is appended to the RDN to insert into the LDAP directory. - 'ldap_version' => 3, // using LDAPv3 - 'search_fields' => array('mail', 'cn'), // fields to search in - 'name_field' => 'cn', // this field represents the contact's name - 'email_field' => 'mail', // this field represents the contact's e-mail - 'surname_field' => 'sn', // this field represents the contact's last name - 'firstname_field' => 'gn', // this field represents the contact's first name + 'writable' => false, + // To create a new contact these are the object classes to specify + // (or any other classes you wish to use). + 'LDAP_Object_Classes' => array('top', 'inetOrgPerson'), + // The RDN field that is used for new entries, this field needs + // to be one of the search_fields, the base of base_dn is appended + // to the RDN to insert into the LDAP directory. + 'LDAP_rdn' => 'mail', + // The required fields needed to build a new contact as required by + // the object classes (can include additional fields not required by the object classes). + 'required_fields' => array('cn', 'sn', 'mail'), + 'search_fields' => array('mail', 'cn'), // fields to search in + // mapping of contact fields to directory attributes + 'fieldmap' => array( + // Roundcube => LDAP + 'name' => 'cn', + 'surname' => 'sn', + 'firstname' => 'givenName', + 'email' => 'mail', + 'phone:home' => 'homePhone', + 'phone:work' => 'telephoneNumber', + 'phone:mobile' => 'mobile', + 'street' => 'street', + 'zipcode' => 'postalCode', + 'locality' => 'l', + 'country' => 'c', + 'organization' => 'o', + ), 'sort' => 'cn', // The field to sort the listing by. 'scope' => 'sub', // search mode: sub|base|list - 'filter' => '', // used for basic listing (if not empty) and will be &'d with search queries. example: status=act + '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 - '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. + '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. + + // 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' => '', + 'filter' => '(objectClass=groupOfNames)', + 'object_classes' => array("top", "groupOfNames"), + // name of the member attribute, e.g. uniqueMember + 'member_attr' => 'member', + ), ); */ @@ -493,6 +588,19 @@ $rcmail_config['autocomplete_addressbooks'] = array('sql'); // may need to do lengthy results building given overly-broad searches $rcmail_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; + +// Max. numer of entries in autocomplete popup. Default: 15. +$rcmail_config['autocomplete_max'] = 15; + +// show address fields in this order +// available placeholders: {street}, {locality}, {zipcode}, {country}, {region} +$rcmail_config['address_template'] = '{street}
{locality} {zipcode}
{country} {region}'; + // ---------------------------------- // USER PREFERENCES // ---------------------------------- @@ -538,9 +646,6 @@ $rcmail_config['preview_pane'] = false; // Set to -1 if messages in preview pane should not be marked as read $rcmail_config['preview_pane_mark_read'] = 0; -// focus new window if new message arrives -$rcmail_config['focus_on_new_message'] = true; - // Clear Trash on logout $rcmail_config['logout_purge'] = false; @@ -564,8 +669,8 @@ $rcmail_config['skip_deleted'] = false; // False means that a message's read status is not affected by marking it as deleted $rcmail_config['read_when_deleted'] = true; -// Set to true to newer delete messages immediately -// Use 'Purge' to remove messages marked as deleted +// Set to true to never delete messages immediately +// Use 'Purge' to remove messages marked as deleted $rcmail_config['flag_for_deletion'] = false; // Default interval for keep-alive/check-recent requests (in seconds) @@ -608,6 +713,9 @@ $rcmail_config['force_7bit'] = false; // Please note that folder names should to be in sync with $rcmail_config['default_imap_folders'] $rcmail_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); + // 'Delete always' // This setting reflects if mail should be always deleted // when moving to Trash fails. This is necessary in some setups @@ -629,4 +737,15 @@ $rcmail_config['dsn_default'] = 0; // Place replies in the folder of the message being replied to $rcmail_config['reply_same_folder'] = false; +// Sets default mode of Forward feature to "forward as attachment" +$rcmail_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; + +// Enables spell checking before sending a message. +$rcmail_config['spellcheck_before_send'] = false; + // end of config file diff --git a/index.php b/index.php index f73e4f8..e3e55d7 100644 --- a/index.php +++ b/index.php @@ -2,9 +2,9 @@ /* +-------------------------------------------------------------------------+ | Roundcube Webmail IMAP Client | - | Version 0.5.3 | + | Version 0.6 | | | - | Copyright (C) 2005-2011, Roundcube Dev. - Switzerland | + | Copyright (C) 2005-2011, 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 version 2 | @@ -23,7 +23,7 @@ | Author: Thomas Bruederli | +-------------------------------------------------------------------------+ - $Id: index.php 4831 2011-06-02 13:36:57Z thomasb $ + $Id: index.php 5292 2011-09-28 19:16:41Z thomasb $ */ @@ -103,7 +103,7 @@ if ($RCMAIL->task == 'login' && $RCMAIL->action == 'login') { $RCMAIL->session->regenerate_id(false); // send auth cookie if necessary - $RCMAIL->authenticate_session(); + $RCMAIL->session->set_auth_cookie(); // log successful login rcmail_log_login(); @@ -120,7 +120,7 @@ if ($RCMAIL->task == 'login' && $RCMAIL->action == 'login') { // allow plugins to control the redirect url after login success $redir = $RCMAIL->plugins->exec_hook('login_after', $query + array('_task' => 'mail')); - unset($redir['abort']); + unset($redir['abort'], $redir['_err']); // send redirect $OUTPUT->redirect($redir); @@ -146,19 +146,25 @@ else if ($RCMAIL->task == 'logout' && isset($_SESSION['user_id']) && (!$RCMAIL-> // check session and auth cookie else if ($RCMAIL->task != 'login' && $_SESSION['user_id'] && $RCMAIL->action != 'send') { - if (!$RCMAIL->authenticate_session()) { - $OUTPUT->show_message('sessionerror', 'error'); + if (!$RCMAIL->session->check_auth()) { $RCMAIL->kill_session(); + $session_error = true; } } // not logged in -> show login page if (empty($RCMAIL->user->ID)) { + // log session failures + if (($task = get_input_value('_task', RCUBE_INPUT_GPC)) && !in_array($task, array('login','logout')) && !$session_error && ($sess_id = $_COOKIE[ini_get('session.name')])) { + $RCMAIL->session->log("Aborted session " . $sess_id . "; no valid session data found"); + $session_error = true; + } + if ($OUTPUT->ajax_call) - $OUTPUT->redirect(array(), 2000); + $OUTPUT->redirect(array('_err' => 'session'), 2000); if (!empty($_REQUEST['_framed'])) - $OUTPUT->command('redirect', '?'); + $OUTPUT->command('redirect', $RCMAIL->url(array('_err' => 'session'))); // check if installer is still active if ($RCMAIL->config->get('enable_installer') && is_readable('./installer/index.php')) { @@ -171,6 +177,9 @@ if (empty($RCMAIL->user->ID)) { ) ); } + + if ($session_error || $_REQUEST['_err'] == 'session') + $OUTPUT->show_message('sessionerror', 'error', null, true, -1); $RCMAIL->set_task('login'); $OUTPUT->send('login'); @@ -205,62 +214,24 @@ else { // handle special actions if ($RCMAIL->action == 'keep-alive') { $OUTPUT->reset(); + $RCMAIL->plugins->exec_hook('keep_alive', array()); $OUTPUT->send(); } else if ($RCMAIL->action == 'save-pref') { - include 'steps/utils/save_pref.inc'; + include INSTALL_PATH . 'program/steps/utils/save_pref.inc'; } -// map task/action to a certain include file -$action_map = array( - 'mail' => array( - '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', - ), - - 'addressbook' => array( - 'add' => 'edit.inc', - 'group-create' => 'groups.inc', - 'group-rename' => 'groups.inc', - 'group-delete' => 'groups.inc', - 'group-addmembers' => 'groups.inc', - 'group-delmembers' => 'groups.inc', - ), - - 'settings' => array( - 'folders' => 'folders.inc', - 'rename-folder' => 'folders.inc', - 'delete-folder' => 'folders.inc', - 'subscribe' => 'folders.inc', - 'unsubscribe' => 'folders.inc', - 'purge' => 'folders.inc', - 'folder-size' => 'folders.inc', - 'add-identity' => 'edit_identity.inc', - ) -); - // include task specific functions -if (is_file($incfile = 'program/steps/'.$RCMAIL->task.'/func.inc')) - include_once($incfile); +if (is_file($incfile = INSTALL_PATH . 'program/steps/'.$RCMAIL->task.'/func.inc')) + include_once $incfile; // allow 5 "redirects" to another action $redirects = 0; $incstep = null; while ($redirects < 5) { - $stepfile = !empty($action_map[$RCMAIL->task][$RCMAIL->action]) ? - $action_map[$RCMAIL->task][$RCMAIL->action] : strtr($RCMAIL->action, '-', '_') . '.inc'; - // execute a plugin action if ($RCMAIL->plugins->is_plugin_task($RCMAIL->task)) { + if (!$RCMAIL->action) $RCMAIL->action = 'index'; $RCMAIL->plugins->exec_action($RCMAIL->task.'.'.$RCMAIL->action); break; } @@ -269,8 +240,10 @@ while ($redirects < 5) { break; } // try to include the step file - else if (is_file($incfile = 'program/steps/'.$RCMAIL->task.'/'.$stepfile)) { - include($incfile); + else if (($stepfile = $RCMAIL->get_action_file()) + && is_file($incfile = INSTALL_PATH . 'program/steps/'.$RCMAIL->task.'/'.$stepfile) + ) { + include $incfile; $redirects++; } else { diff --git a/installer/check.php b/installer/check.php index 0ba5f58..944d384 100644 --- a/installer/check.php +++ b/installer/check.php @@ -22,6 +22,7 @@ $required_libs = array( 'PEAR' => 'PEAR.php', 'MDB2' => 'MDB2.php', 'Net_SMTP' => 'Net/SMTP.php', + 'Net_IDNA2' => 'Net/IDNA2.php', 'Mail_mime' => 'Mail/mime.php', ); diff --git a/installer/config.php b/installer/config.php index 6b52407..dabc478 100644 --- a/installer/config.php +++ b/installer/config.php @@ -361,7 +361,7 @@ echo $text_sentmbox->show($RCI->getprop('sent_mbox')); ?>
Store sent messages in this folder
-

Leave blank if sent messages should not be stored

+

Leave blank if sent messages should not be stored. Note: folder must include namespace prefix if any.

trash_mbox
@@ -374,7 +374,7 @@ echo $text_trashmbox->show($RCI->getprop('trash_mbox')); ?>
Move messages to this folder when deleting them
-

Leave blank if they should be deleted directly

+

Leave blank if they should be deleted directly. Note: folder must include namespace prefix if any.

drafts_mbox
@@ -387,7 +387,7 @@ echo $text_draftsmbox->show($RCI->getprop('drafts_mbox')); ?>
Store draft messages in this folder
-

Leave blank if they should not be stored

+

Leave blank if they should not be stored. Note: folder must include namespace prefix if any.

junk_mbox
@@ -399,6 +399,10 @@ echo $text_junkmbox->show($RCI->getprop('junk_mbox')); ?>
Store spam messages in this folder
+ +

Note: folder must include namespace prefix if any.

+ + @@ -500,13 +504,26 @@ echo $input_locale->show($RCI->getprop('language'));
'_skin', 'size' => 30, 'id' => "cfgskin")); +$input_skin = new html_select(array('name' => '_skin', 'id' => "cfgskin")); +$input_skin->add($RCI->list_skins()); echo $input_skin->show($RCI->getprop('skin')); ?>
Name of interface skin (folder in /skins)
+
skin_logo
+
+ '_skin_logo', 'size' => 50, 'id' => "cfgskinlogo")); +echo $input_skin->show($RCI->getprop('skin_logo')); + +?> +
Custom image to display instead of the Roundcube logo.
+

Enter a URL relative to the document root of this Roundcube installation.

+
+
pagesize *
6`Yik=A7#JKJoSK>%9UWa-T3TLS-q6tC z=H?a|8Ch9bnUs`dWo6~)=vYutP+VMGS67#lljGy#)6~?|-rj!k;>E12tk%|6PfySE z^z@pVnz*<)XJ_Y*jt)ORzm}Gk?(S}5W8?q-|1(ezDE?#t8>RyyL4IOj`|mKhz(Yr> z|HP7_lQ~xNFRUo>S{t?g#+tIzXDaqT*ii9Cb>{gOTdL0H?Y{qEM~&a~_IE$_)Scg- z{I8+0skxbtGlONxqrgMNt37ai%*|1bJpxR)4As_Sh#5MlKCRbSFBvMdd+gV z^&2*B+Pq~w-}W6lckSM@oooMrgNF_u+0S|W#K}{q&m0#%f8pY#%U8||UB7Yj*6lmj zMejd&_~`MI`%=$eynOZg&2!oJA3lEi{N+9S_a8rh{r>Zv|33pWmyE}U`|Zsf!dfvW zJ}5M`3n+Wd@%Wh7+$~|8b?3y#MGgH5&RsH|pB6Vx)(Bn|bMjM4<8*`MQ*%5&FYTCZ zQT*!8${uPKIqUAJuUReY6ApLD zdVkAq*qm{BRqW|+I*r>49-o@){av?Zcg5#dcTa!UYuMkw%q{2h<9);74q@%MGd~JC Vk55qcp6BzkaOvq8imZ$b)&Mnv1#AES diff --git a/installer/images/banner_gradient.gif b/installer/images/banner_gradient.gif new file mode 100644 index 0000000000000000000000000000000000000000..8ab1b06304d35a8ca4cec9d2822b535eed434d2c GIT binary patch literal 506 zcmVh}HS^!@Mn{p0fe-SGY2@crBF{o(TcmPE2?5Q_&dklu0SL?#*wGXT*xlRQ z+Y|%c*W=#e1LNuG78dCg?E~%b^6>5P_ZA2D`|bS)2Qp*;I56Nqfd~^S3}`T60fY|~ zW+?EmLWPJEGg#bsaic~89794N0J5Y>kPt?9l3baxWl91sN4|uq!KF->HFM@Puv3Fi z4LpBpxF8g0P@V=Z@Vr2j>4gnLH$0u{)G1V}8?tKE`cx|i1spbn&C22H*9{8Neg#`r w0ot%>)hhVV7VL+)W!I+tK({Pk4t((f4$QZ(;lqd%D_+dF@!`CX^M(KbJEvw58UO$Q literal 0 HcmV?d00001 diff --git a/installer/images/banner_logo.gif b/installer/images/banner_logo.gif deleted file mode 100644 index a7dd1142621ad02bdb995206f48b2fc58935b512..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4345 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 diff --git a/installer/images/banner_right.gif b/installer/images/banner_right.gif deleted file mode 100644 index 3248668ac0f8ede8adbc5631eec5dc68270a9c5e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 433 zcmV;i0Z#r$Nk%w1VF~~^0M!5hR#sM1Q&V?$cYJ(&aBy&dfPiIXWj{YZSy@?vf`Uv; zOi@u$TU%RaXJ>3|Y-(z1etv#+b#+NeNn&DRPEJmFd3kelb4Er+US3{9Lqmv&h=+%V zg@uJZJv~7|K{`4*H#avmH8nFcGttq}tE;Q#=H~bJ_kDeRkdTnx-rk0WhPAb|)z#Jf z{QNvTJn!%C@$vD}($eDM;*ye*o12^0*VnhVw~vpHMMXuiv9ZR+#`^mDgoK2Pi;MsN z{{R30A^8LV00000EC2ui015y&000KgK%a0(EEC#q0b334wxx1%-x(5Q&P51C5T46_JvY0+p7R z5t*8s7M-4-1fim%4yC5252>oF4Xv)P2C=fU6ScOt7`eK;486X;2*JX`0L8|~0m;hC z3(d~Y6w%Vt3f0!v64~0@7v0|98R6pMI3DKb=K%-n?Cb&^@bU3EANBV206QT2{2(qY bK0*i_ctD2`5eN~UkTIkW2^%nq1OWg$I9Jky diff --git a/installer/images/banner_schraffur.gif b/installer/images/banner_schraffur.gif new file mode 100644 index 0000000000000000000000000000000000000000..50182b4d6a6ddcb5c70c98f91e8e321daf408081 GIT binary patch literal 12454 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

s2rMFxXF$Z6qem7Doswy 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 literal 0 HcmV?d00001 diff --git a/installer/index.php b/installer/index.php index 1c157da..7ed5224 100644 --- a/installer/index.php +++ b/installer/index.php @@ -1,5 +1,33 @@ | + +-------------------------------------------------------------------------+ + + $Id$ + +*/ + ini_set('error_reporting', E_ALL&~E_NOTICE); ini_set('display_errors', 1); @@ -41,7 +69,7 @@ if ($RCI->configured && ($RCI->getprop('enable_installer') || $_SESSION['allowin header('Content-type: text/plain'); header('Content-Disposition: attachment; filename="'.$filename.'"'); - + $RCI->merge_config(); echo $RCI->create_config($_GET['_mergeconfig'], true); exit; @@ -68,14 +96,13 @@ if ($RCI->configured && empty($_REQUEST['_step'])) {

+ + + + +
@@ -120,7 +147,7 @@ else {
diff --git a/installer/rcube_install.php b/installer/rcube_install.php index 69be025..ff3f7a4 100644 --- a/installer/rcube_install.php +++ b/installer/rcube_install.php @@ -5,7 +5,7 @@ | rcube_install.php | | | | This file is part of the Roundcube Webmail package | - | Copyright (C) 2008-2009, Roundcube Dev. - Switzerland | + | Copyright (C) 2008-2011, The Roundcube Dev Team | | Licensed under the GNU Public License | +-----------------------------------------------------------------------+ @@ -29,10 +29,11 @@ class rcube_install var $config = array(); var $configured = false; var $last_error = null; + var $db_map = array('pgsql' => 'postgres', 'mysqli' => 'mysql', 'sqlsrv' => 'mssql'); var $email_pattern = '([a-z0-9][a-z0-9\-\.\+\_]*@[a-z0-9]([a-z0-9\-][.]?)*[a-z0-9])'; var $bool_config_props = array(); - var $obsolete_config = array('db_backend'); + var $obsolete_config = array('db_backend', 'double_auth'); var $replaced_config = array( 'skin_path' => 'skin', 'locale_string' => 'language', @@ -42,7 +43,10 @@ class rcube_install ); // these config options are required for a working system - var $required_config = array('db_dsnw', 'db_table_contactgroups', 'db_table_contactgroupmembers', 'des_key'); + var $required_config = array( + 'db_dsnw', 'db_table_contactgroups', 'db_table_contactgroupmembers', + 'des_key', 'session_lifetime', + ); /** * Constructor @@ -91,14 +95,15 @@ class rcube_install */ function _load_config($suffix) { - @include RCMAIL_CONFIG_DIR . '/main.inc' . $suffix; - if (is_array($rcmail_config)) { - $this->config += $rcmail_config; + if (is_readable($main_inc = RCMAIL_CONFIG_DIR . '/main.inc' . $suffix)) { + include($main_inc); + if (is_array($rcmail_config)) + $this->config += $rcmail_config; } - - @include RCMAIL_CONFIG_DIR . '/db.inc'. $suffix; - if (is_array($rcmail_config)) { - $this->config += $rcmail_config; + if (is_readable($db_inc = RCMAIL_CONFIG_DIR . '/db.inc'. $suffix)) { + include($db_inc); + if (is_array($rcmail_config)) + $this->config += $rcmail_config; } } @@ -119,8 +124,8 @@ class rcube_install return $value !== null && $value !== '' ? $value : $default; } - - + + /** * Take the default config file and replace the parameters * with the submitted form data @@ -131,13 +136,14 @@ class rcube_install function create_config($which, $force = false) { $out = @file_get_contents(RCMAIL_CONFIG_DIR . "/{$which}.inc.php.dist"); - + if (!$out) return '[Warning: could not read the config template file]'; foreach ($this->config as $prop => $default) { + $value = (isset($_POST["_$prop"]) || $this->bool_config_props[$prop]) ? $_POST["_$prop"] : $default; - + // convert some form data if ($prop == 'debug_level') { $val = 0; @@ -189,9 +195,9 @@ class rcube_install else if (is_numeric($value)) { $value = intval($value); } - + // skip this property - if (!$force && ($value == $default)) + if (!$force && !$this->configured && ($value == $default)) continue; // save change @@ -294,7 +300,7 @@ class rcube_install $this->config = array(); $this->load_defaults(); - foreach ($this->replaced_config as $prop => $replacement) + foreach ($this->replaced_config as $prop => $replacement) { if (isset($current[$prop])) { if ($prop == 'skin_path') $this->config[$replacement] = preg_replace('#skins/(\w+)/?$#', '\\1', $current[$prop]); @@ -302,8 +308,8 @@ class rcube_install $this->config[$replacement] = $current[$prop] ? 2 : 0; else $this->config[$replacement] = $current[$prop]; - - unset($current[$prop]); + } + unset($current[$prop]); } foreach ($this->obsolete_config as $prop) { @@ -320,6 +326,9 @@ class rcube_install } } + if ($current['keep_alive'] && $current['session_lifetime'] < $current['keep_alive']) + $current['session_lifetime'] = max(10, ceil($current['keep_alive'] / 60) * 2); + $this->config = array_merge($this->config, $current); foreach ((array)$current['ldap_public'] as $key => $values) { @@ -339,18 +348,8 @@ class rcube_install if (!$this->configured) return false; - // simple ad hand-made db schema - $db_schema = array( - 'users' => array(), - 'identities' => array(), - 'contacts' => array(), - 'contactgroups' => array(), - 'contactgroupmembers' => array(), - 'cache' => array(), - 'messages' => array(), - 'session' => array(), - ); - + // read reference schema from mysql.initial.sql + $db_schema = $this->db_read_schema(INSTALL_PATH . 'SQL/mysql.initial.sql'); $errors = array(); // check list of tables @@ -358,13 +357,43 @@ class rcube_install foreach ($db_schema as $table => $cols) { $table = !empty($this->config['db_table_'.$table]) ? $this->config['db_table_'.$table] : $table; - if (!in_array($table, $existing_tables)) - $errors[] = "Missing table ".$table; - // TODO: check cols and indices + if (!in_array($table, $existing_tables)) { + $errors[] = "Missing table '".$table."'"; + } + else { // compare cols + $db_cols = $DB->list_cols($table); + $diff = array_diff(array_keys($cols), $db_cols); + if (!empty($diff)) + $errors[] = "Missing columns in table '$table': " . join(',', $diff); + } } return !empty($errors) ? $errors : false; } + + /** + * Utility function to read database schema from an .sql file + */ + private function db_read_schema($schemafile) + { + $lines = file($schemafile); + $table_block = false; + $schema = array(); + foreach ($lines as $line) { + if (preg_match('/^\s*create table `?([a-z0-9_]+)`?/i', $line, $m)) { + $table_block = $m[1]; + } + else if ($table_block && preg_match('/^\s*`?([a-z0-9_-]+)`?\s+([a-z]+)/', $line, $m)) { + $col = $m[1]; + if (!in_array(strtoupper($col), array('PRIMARY','KEY','INDEX','UNIQUE','CONSTRAINT','REFERENCES','FOREIGN'))) { + $schema[$table_block][$col] = $m[2]; + } + } + } + + return $schema; + } + /** * Compare the local database schema with the reference schema @@ -474,6 +503,30 @@ class rcube_install return $out; } + /** + * Create a HTML dropdown to select a previous version of Roundcube + */ + function versions_select($attrib = array()) + { + $select = new html_select($attrib); + $select->add(array('0.1-stable', '0.1.1', '0.2-alpha', '0.2-beta', '0.2-stable', '0.3-stable', '0.3.1', '0.4-beta', '0.4.2', '0.5-beta', '0.5', '0.5.1')); + return $select; + } + + /** + * Return a list with available subfolders of the skin directory + */ + function list_skins() + { + $skins = array(); + $skindir = INSTALL_PATH . 'skins/'; + foreach (glob($skindir . '*') as $path) { + if (is_dir($path) && is_readable($path)) { + $skins[] = substr($path, strlen($skindir)); + } + } + return $skins; + } /** * Display OK status @@ -592,39 +645,98 @@ class rcube_install */ function init_db($DB) { - $db_map = array('pgsql' => 'postgres', 'mysqli' => 'mysql'); - $engine = isset($db_map[$DB->db_provider]) ? $db_map[$DB->db_provider] : $DB->db_provider; + $engine = isset($this->db_map[$DB->db_provider]) ? $this->db_map[$DB->db_provider] : $DB->db_provider; // read schema file from /SQL/* - $fname = "../SQL/$engine.initial.sql"; + $fname = INSTALL_PATH . "SQL/$engine.initial.sql"; + if ($sql = @file_get_contents($fname)) { + $this->exec_sql($sql, $DB); + } + else { + $this->fail('DB Schema', "Cannot read the schema file: $fname"); + return false; + } + + if ($err = $this->get_error()) { + $this->fail('DB Schema', "Error creating database schema: $err"); + return false; + } + + return true; + } + + + /** + * Update database with SQL statements from SQL/*.update.sql + * + * @param object rcube_db Database connection + * @param string Version to update from + * @return boolen True on success, False on error + */ + function update_db($DB, $version) + { + $version = strtolower($version); + $engine = isset($this->db_map[$DB->db_provider]) ? $this->db_map[$DB->db_provider] : $DB->db_provider; + + // read schema file from /SQL/* + $fname = INSTALL_PATH . "SQL/$engine.update.sql"; if ($lines = @file($fname, FILE_SKIP_EMPTY_LINES)) { - $buff = ''; - foreach ($lines as $i => $line) { - if (preg_match('/^--/', $line)) - continue; - - $buff .= $line . "\n"; - if (preg_match('/;$/', trim($line))) { - $DB->query($buff); - $buff = ''; - if ($this->get_error()) - break; + $from = false; $sql = ''; + foreach ($lines as $line) { + $is_comment = preg_match('/^--/', $line); + if (!$from && $is_comment && preg_match('/from version\s([0-9.]+[a-z-]*)/', $line, $m)) { + $v = strtolower($m[1]); + if ($v == $version || version_compare($version, $v, '<=')) + $from = true; } + if ($from && !$is_comment) + $sql .= $line. "\n"; } + + if ($sql) + $this->exec_sql($sql, $DB); } else { - $this->fail('DB Schema', "Cannot read the schema file: $fname"); + $this->fail('DB Schema', "Cannot read the update file: $fname"); return false; } if ($err = $this->get_error()) { - $this->fail('DB Schema', "Error creating database schema: $err"); + $this->fail('DB Schema', "Error updating database: $err"); return false; } return true; } + + /** + * Execute the given SQL queries on the database connection + * + * @param string SQL queries to execute + * @param object rcube_db Database connection + * @return boolen True on success, False on error + */ + function exec_sql($sql, $DB) + { + $buff = ''; + foreach (explode("\n", $sql) as $line) { + if (preg_match('/^--/', $line) || trim($line) == '') + continue; + + $buff .= $line . "\n"; + if (preg_match('/(;|^GO)$/', trim($line))) { + $DB->query($buff); + $buff = ''; + if ($DB->is_error()) + break; + } + } + + return !$DB->is_error(); + } + + /** * Handler for Roundcube errors */ diff --git a/installer/styles.css b/installer/styles.css index 1acdc9c..06f49e3 100644 --- a/installer/styles.css +++ b/installer/styles.css @@ -1,62 +1,53 @@ - body { - margin: 1em 2em 2em 2em; - background-color: #fff; -} - -body, td, th, div, p { - font-family: "Lucida Grande", Verdana, Arial, Helvetica, sans-serif; - font-size: small; - color: #000; + background: white; + font-family: "Lucida Grande", Verdana, Arial, Helvetica, sans-serif; + font-size: small; + color: black; + margin: 0; } #banner { - position: relative; + position: relative; + height: 58px; + margin: 0 0 1em 0; + padding: 10px 20px; + background: url('images/banner_gradient.gif') top left repeat-x #d8edfd; + overflow: hidden; } -#header { - position: relative; - height: 56px; - background: url('images/banner_bg.gif') top left repeat-x #fff; +#banner .banner-bg { + position: absolute; + top: 0; + right: 0; + width: 630px; + height: 78px; + background: url('images/banner_schraffur.gif') top right no-repeat; + z-index: 0; } -#header div.banner-logo { - position: absolute; - top: 0px; - left: 0px; - width: 200px; - height: 56px; +#banner .banner-logo { + position: absolute; + top: 10px; + left: 20px; + z-index: 4; } -#header div.banner-right { - position: absolute; - right: 0px; - top: 0px; - width: 10px; - height: 56px; +#banner .banner-logo a { + border: 0; } #topnav { - position: absolute; - right: 20px; - bottom: 8px; - text-align: right; - color: #ebebeb; - font-size: smaller; + position: absolute; + top: 3.6em; + right: 20px; } #topnav a { - color: #ebebeb; - font-size: 11px; - text-decoration: none; -} - -#topnav a:hover { - text-decoration: underline; + color: #666; } #content { - margin: 8px 20px; + margin: 2em 20px; } #footer { diff --git a/installer/test.php b/installer/test.php index 713edfb..02a1ceb 100644 --- a/installer/test.php +++ b/installer/test.php @@ -156,6 +156,14 @@ if ($db_working && $_POST['initdb']) { } } +else if ($db_working && $_POST['updatedb']) { + if (!($success = $RCI->update_db($DB, $_POST['version']))) { + $updatefile = INSTALL_PATH . 'SQL/' . (isset($RCI->db_map[$DB->db_provider]) ? $RCI->db_map[$DB->db_provider] : $DB->db_provider) . '.update.sql'; + echo '

Please manually execute the SQL statements from '.$updatefile.' on your database.
'; + echo 'See comments in the file and execute queries below the comment with the currently installed version number.

'; + } +} + // test database if ($db_working) { $db_read = $DB->query("SELECT count(*) FROM {$RCI->config['db_table_users']}"); @@ -164,12 +172,13 @@ if ($db_working) { echo '

'; $db_working = false; } - else if ($RCI->db_schema_check($DB, $update = !empty($_POST['updatedb']))) { + else if ($err = $RCI->db_schema_check($DB, $update = !empty($_POST['updatedb']))) { $RCI->fail('DB Schema', "Database schema differs"); - $db_map = array('pgsql' => 'postgres', 'mysqli' => 'mysql', 'sqlsrv' => 'mssql'); - $updatefile = INSTALL_PATH . 'SQL/' . (isset($db_map[$DB->db_provider]) ? $db_map[$DB->db_provider] : $DB->db_provider) . '.update.sql'; - echo '

Please manually execute the SQL statements from '.$updatefile.' on your database.
'; - echo 'See comments in the file and execute queries that are superscribed with the currently installed version number.

'; + echo '
  • ' . join("
  • \n
  • ", $err) . "
"; + $select = $RCI->versions_select(array('name' => 'version')); + echo '

You should run the update queries to get the schmea fixed.

Version to update from: ' . $select->show() . ' 

'; +// echo '

Please manually execute the SQL statements from '.$updatefile.' on your database.
'; +// echo 'See comments in the file and execute queries that are superscribed with the currently installed version number.

'; $db_working = false; } else { @@ -412,7 +421,7 @@ if (isset($_POST['imaptest']) && !empty($_POST['_host']) && !empty($_POST['_user After completing the installation and the final tests please remove the whole installer folder from the document root of the webserver or make sure that -enable_installer option in main.inc.php is disabled.
+enable_installer option in config/main.inc.php is disabled.

These files may expose sensitive configuration data like server passwords and encryption keys diff --git a/installer/utils.php b/installer/utils.php index 4294f79..a7521b9 100644 --- a/installer/utils.php +++ b/installer/utils.php @@ -2,9 +2,9 @@ /* +-------------------------------------------------------------------------+ | Roundcube Webmail IMAP Client | - | Version 0.3-20090702 | + | Version 0.6 | | | - | Copyright (C) 2005-2009, Roundcube Dev. - Switzerland | + | Copyright (C) 2005-2011, 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 version 2 | @@ -33,12 +33,26 @@ */ function __autoload($classname) { - $filename = preg_replace( - array('/MDB2_(.+)/', '/Mail_(.+)/', '/Net_(.+)/', '/^html_.+/', '/^utf8$/'), - array('MDB2/\\1', 'Mail/\\1', 'Net/\\1', 'html', 'utf8.class'), - $classname - ); - include_once $filename. '.php'; + $filename = preg_replace( + array( + '/MDB2_(.+)/', + '/Mail_(.+)/', + '/Net_(.+)/', + '/Auth_(.+)/', + '/^html_.+/', + '/^utf8$/' + ), + array( + 'MDB2/\\1', + 'Mail/\\1', + 'Net/\\1', + 'Auth/\\1', + 'html', + 'utf8.class' + ), + $classname + ); + include_once $filename. '.php'; } @@ -47,6 +61,20 @@ function __autoload($classname) */ function raise_error($p) { - $rci = rcube_install::get_instance(); - $rci->raise_error($p); + $rci = rcube_install::get_instance(); + $rci->raise_error($p); } + +/** + * Local callback function for PEAR errors + */ +function rcube_pear_error($err) +{ + raise_error(array( + 'code' => $err->getCode(), + 'message' => $err->getMessage(), + )); +} + +// set PEAR error handling (will also load the PEAR main class) +PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'rcube_pear_error'); diff --git a/plugins/acl/acl.js b/plugins/acl/acl.js new file mode 100644 index 0000000..4b1431a --- /dev/null +++ b/plugins/acl/acl.js @@ -0,0 +1,338 @@ +/** + * ACL plugin script + * + * @version 0.6.1 + * @author Aleksander Machniak + */ + +if (window.rcmail) { + rcmail.addEventListener('init', function() { + if (rcmail.gui_objects.acltable) { + rcmail.acl_list_init(); + // enable autocomplete on user input + if (rcmail.env.acl_users_source) { + rcmail.init_address_input_events($('#acluser'), {action:'settings/plugin.acl-autocomplete'}); + // fix inserted value + rcmail.addEventListener('autocomplete_insert', function(e) { + if (e.field.id != 'acluser') + return; + + var value = e.insert; + // get UID from the entry value + if (value.match(/\s*\(([^)]+)\)[, ]*$/)) + value = RegExp.$1; + e.field.value = value; + }); + } + } + + rcmail.enable_command('acl-create', 'acl-save', 'acl-cancel', 'acl-mode-switch', true); + rcmail.enable_command('acl-delete', 'acl-edit', false); + }); +} + +// Display new-entry form +rcube_webmail.prototype.acl_create = function() +{ + this.acl_init_form(); +} + +// Display ACL edit form +rcube_webmail.prototype.acl_edit = function() +{ + // @TODO: multi-row edition + var id = this.acl_list.get_single_selection(); + if (id) + this.acl_init_form(id); +} + +// ACL entry delete +rcube_webmail.prototype.acl_delete = function() +{ + var users = this.acl_get_usernames(); + + if (users && users.length && confirm(this.get_label('acl.deleteconfirm'))) { + this.http_request('settings/plugin.acl', '_act=delete&_user='+urlencode(users.join(',')) + + '&_mbox='+urlencode(this.env.mailbox), + this.set_busy(true, 'acl.deleting')); + } +} + +// Save ACL data +rcube_webmail.prototype.acl_save = function() +{ + var user = $('#acluser').val(), rights = '', type; + + $(':checkbox', this.env.acl_advanced ? $('#advancedrights') : sim_ul = $('#simplerights')).map(function() { + if (this.checked) + rights += this.value; + }); + + if (type = $('input:checked[name=usertype]').val()) { + if (type != 'user') + user = type; + } + + if (!user) { + alert(this.get_label('acl.nouser')); + return; + } + if (!rights) { + alert(this.get_label('acl.norights')); + return; + } + + this.http_request('settings/plugin.acl', '_act=save' + + '&_user='+urlencode(user) + + '&_acl=' +rights + + '&_mbox='+urlencode(this.env.mailbox) + + (this.acl_id ? '&_old='+this.acl_id : ''), + this.set_busy(true, 'acl.saving')); +} + +// Cancel/Hide form +rcube_webmail.prototype.acl_cancel = function() +{ + this.ksearch_blur(); + this.acl_form.hide(); +} + +// Update data after save (and hide form) +rcube_webmail.prototype.acl_update = function(o) +{ + // delete old row + if (o.old) + this.acl_remove_row(o.old); + // make sure the same ID doesn't exist + else if (this.env.acl[o.id]) + this.acl_remove_row(o.id); + + // add new row + this.acl_add_row(o, true); + // hide autocomplete popup + this.ksearch_blur(); + // hide form + this.acl_form.hide(); +} + +// Switch table display mode +rcube_webmail.prototype.acl_mode_switch = function(elem) +{ + this.env.acl_advanced = !this.env.acl_advanced; + this.enable_command('acl-delete', 'acl-edit', false); + this.http_request('settings/plugin.acl', '_act=list' + + '&_mode='+(this.env.acl_advanced ? 'advanced' : 'simple') + + '&_mbox='+urlencode(this.env.mailbox), + this.set_busy(true, 'loading')); +} + +// ACL table initialization +rcube_webmail.prototype.acl_list_init = function() +{ + this.acl_list = new rcube_list_widget(this.gui_objects.acltable, + {multiselect:true, draggable:false, keyboard:true, toggleselect:true}); + this.acl_list.addEventListener('select', function(o) { rcmail.acl_list_select(o); }); + this.acl_list.addEventListener('dblclick', function(o) { rcmail.acl_list_dblclick(o); }); + this.acl_list.addEventListener('keypress', function(o) { rcmail.acl_list_keypress(o); }); + this.acl_list.init(); +} + +// ACL table row selection handler +rcube_webmail.prototype.acl_list_select = function(list) +{ + rcmail.enable_command('acl-delete', list.selection.length > 0); + rcmail.enable_command('acl-edit', list.selection.length == 1); + list.focus(); +} + +// ACL table double-click handler +rcube_webmail.prototype.acl_list_dblclick = function(list) +{ + this.acl_edit(); +} + +// ACL table keypress handler +rcube_webmail.prototype.acl_list_keypress = function(list) +{ + if (list.key_pressed == list.ENTER_KEY) + this.command('acl-edit'); + else if (list.key_pressed == list.DELETE_KEY || list.key_pressed == list.BACKSPACE_KEY) + if (!this.acl_form || !this.acl_form.is(':visible')) + this.command('acl-delete'); +} + +// Reloads ACL table +rcube_webmail.prototype.acl_list_update = function(html) +{ + $(this.gui_objects.acltable).html(html); + this.acl_list_init(); +} + +// Returns names of users in selected rows +rcube_webmail.prototype.acl_get_usernames = function() +{ + var users = [], n, len, cell, row, + list = this.acl_list, + selection = list.get_selection(); + + for (n=0, len=selection.length; n= 0) { + users.push(selection[n]); + } + else { + row = list.rows[selection[n]].obj; + cell = $('td.user', row); + if (cell.length == 1) + users.push(cell.text()); + } + } + + return users; +} + +// Removes ACL table row +rcube_webmail.prototype.acl_remove_row = function(id) +{ + this.acl_list.remove_row(id); + // we don't need it anymore (remove id conflict) + $('#rcmrow'+id).remove(); + this.env.acl[id] = null; +} + +// Adds ACL table row +rcube_webmail.prototype.acl_add_row = function(o, sel) +{ + var n, len, ids = [], spec = [], id = o.id, list = this.acl_list, + items = this.env.acl_advanced ? [] : this.env.acl_items, + table = this.gui_objects.acltable, + row = $('thead > tr', table).clone(); + + // Update new row + $('td', row).map(function() { + var r, cl = this.className.replace(/^acl/, ''); + + if (items && items[cl]) + cl = items[cl]; + + if (cl == 'user') + $(this).text(o.username); + else + $(this).addClass(rcmail.acl_class(o.acl, cl)).text(''); + }); + + row.attr('id', 'rcmrow'+id); + row = row.get(0); + + this.env.acl[id] = o.acl; + + // sorting... (create an array of user identifiers, then sort it) + for (n in this.env.acl) { + if (this.env.acl[n]) { + if (this.env.acl_specials.length && $.inArray(n, this.env.acl_specials) >= 0) + spec.push(n); + else + ids.push(n); + } + } + ids.sort(); + // specials on the top + ids = spec.concat(ids); + + // find current id + for (n=0, len=ids.length; n= mw) + this.acl_form.css({left: parseInt((bw - mw)/2)+'px'}); + + // display it + this.acl_form.show(); + if (type == 'user') + name_input.focus(); +} + +// Returns class name according to ACL comparision result +rcube_webmail.prototype.acl_class = function(acl1, acl2) +{ + var i, len, found = 0; + + acl1 = String(acl1); + acl2 = String(acl2); + + for (i=0, len=acl2.length; i -1) + found++; + + if (found == len) + return 'enabled'; + else if (found) + return 'partial'; + + return 'disabled'; +} diff --git a/plugins/acl/acl.php b/plugins/acl/acl.php new file mode 100644 index 0000000..976b362 --- /dev/null +++ b/plugins/acl/acl.php @@ -0,0 +1,696 @@ + + * + * + * Copyright (C) 2011, Kolab Systems AG + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +class acl extends rcube_plugin +{ + public $task = 'settings|addressbook|calendar'; + + private $rc; + private $supported = null; + private $mbox; + private $ldap; + private $specials = array('anyone', 'anonymous'); + + /** + * Plugin initialization + */ + function init() + { + $this->rc = rcmail::get_instance(); + + // Register hooks + $this->add_hook('folder_form', array($this, 'folder_form')); + // kolab_addressbook plugin + $this->add_hook('addressbook_form', array($this, 'folder_form')); + $this->add_hook('calendar_form_kolab', array($this, 'folder_form')); + // Plugin actions + $this->register_action('plugin.acl', array($this, 'acl_actions')); + $this->register_action('plugin.acl-autocomplete', array($this, 'acl_autocomplete')); + } + + /** + * Handler for plugin actions (AJAX) + */ + function acl_actions() + { + $action = trim(get_input_value('_act', RCUBE_INPUT_GPC)); + + // Connect to IMAP + $this->rc->imap_init(); + $this->rc->imap_connect(); + + // Load localization and configuration + $this->add_texts('localization/'); + $this->load_config(); + + if ($action == 'save') { + $this->action_save(); + } + else if ($action == 'delete') { + $this->action_delete(); + } + else if ($action == 'list') { + $this->action_list(); + } + + // Only AJAX actions + $this->rc->output->send(); + } + + /** + * Handler for user login autocomplete request + */ + function acl_autocomplete() + { + $this->load_config(); + + $search = get_input_value('_search', RCUBE_INPUT_GPC, true); + $users = array(); + + if ($this->init_ldap()) { + $this->ldap->set_pagesize(15); + $result = $this->ldap->search('*', $search); + + foreach ($result->records as $record) { + $user = $record['uid']; + + if (is_array($user)) { + $user = array_filter($user); + $user = $user[0]; + } + + if ($user) { + if ($record['name']) + $user = $record['name'] . ' (' . $user . ')'; + + $users[] = $user; + } + } + } + + sort($users, SORT_LOCALE_STRING); + + $this->rc->output->command('ksearch_query_results', $users, $search); + $this->rc->output->send(); + } + + /** + * Handler for 'folder_form' hook + * + * @param array $args Hook arguments array (form data) + * + * @return array Hook arguments array + */ + function folder_form($args) + { + // Edited folder name (empty in create-folder mode) + $mbox_imap = $args['options']['name']; + if (!strlen($mbox_imap)) { + return $args; + } +/* + // Do nothing on protected folders (?) + if ($args['options']['protected']) { + return $args; + } +*/ + // Namespace root + if ($args['options']['is_root']) { + return $args; + } + + // Get MYRIGHTS + if (!($myrights = $args['options']['rights'])) { + return $args; + } + + // Do nothing if no ACL support + if (!$this->rc->imap->get_capability('ACL')) { + return $args; + } + + // Load localization and include scripts + $this->load_config(); + $this->add_texts('localization/', array('deleteconfirm', 'norights', + 'nouser', 'deleting', 'saving')); + $this->include_script('acl.js'); + $this->rc->output->include_script('list.js'); + $this->include_stylesheet($this->local_skin_path().'/acl.css'); + + // add Info fieldset if it doesn't exist + if (!isset($args['form']['props']['fieldsets']['info'])) + $args['form']['props']['fieldsets']['info'] = array( + 'name' => rcube_label('info'), + 'content' => array()); + + // Display folder rights to 'Info' fieldset + $args['form']['props']['fieldsets']['info']['content']['myrights'] = array( + 'label' => Q($this->gettext('myrights')), + 'value' => $this->acl2text($myrights) + ); + + // Return if not folder admin + if (!in_array('a', $myrights)) { + return $args; + } + + // The 'Sharing' tab + $this->mbox = $mbox_imap; + $this->rc->output->set_env('acl_users_source', (bool) $this->rc->config->get('acl_users_source')); + $this->rc->output->set_env('mailbox', $mbox_imap); + $this->rc->output->add_handlers(array( + 'acltable' => array($this, 'templ_table'), + 'acluser' => array($this, 'templ_user'), + 'aclrights' => array($this, 'templ_rights'), + )); + + $args['form']['sharing'] = array( + 'name' => Q($this->gettext('sharing')), + 'content' => $this->rc->output->parse('acl.table', false, false), + ); + + return $args; + } + + /** + * Creates ACL rights table + * + * @param array $attrib Template object attributes + * + * @return string HTML Content + */ + function templ_table($attrib) + { + if (empty($attrib['id'])) + $attrib['id'] = 'acl-table'; + + $out = $this->list_rights($attrib); + + $this->rc->output->add_gui_object('acltable', $attrib['id']); + + return $out; + } + + /** + * Creates ACL rights form (rights list part) + * + * @param array $attrib Template object attributes + * + * @return string HTML Content + */ + function templ_rights($attrib) + { + // Get supported rights + $supported = $this->rights_supported(); + + // depending on server capability either use 'te' or 'd' for deleting msgs + $deleteright = implode(array_intersect(str_split('ted'), $supported)); + + $out = ''; + $ul = ''; + $input = new html_checkbox(); + + // Advanced rights + $attrib['id'] = 'advancedrights'; + foreach ($supported as $val) { + $id = "acl$val"; + $ul .= html::tag('li', null, + $input->show('', array( + 'name' => "acl[$val]", 'value' => $val, 'id' => $id)) + . html::label(array('for' => $id, 'title' => $this->gettext('longacl'.$val)), + $this->gettext('acl'.$val))); + } + + $out = html::tag('ul', $attrib, $ul, html::$common_attrib); + + // Simple rights + $ul = ''; + $attrib['id'] = 'simplerights'; + $items = array( + 'read' => 'lrs', + 'write' => 'wi', + 'delete' => $deleteright, + 'other' => preg_replace('/[lrswi'.$deleteright.']/', '', implode($supported)), + ); + + foreach ($items as $key => $val) { + $id = "acl$key"; + $ul .= html::tag('li', null, + $input->show('', array( + 'name' => "acl[$val]", 'value' => $val, 'id' => $id)) + . html::label(array('for' => $id, 'title' => $this->gettext('longacl'.$key)), + $this->gettext('acl'.$key))); + } + + $out .= "\n" . html::tag('ul', $attrib, $ul, html::$common_attrib); + + $this->rc->output->set_env('acl_items', $items); + + return $out; + } + + /** + * Creates ACL rights form (user part) + * + * @param array $attrib Template object attributes + * + * @return string HTML Content + */ + function templ_user($attrib) + { + // Create username input + $attrib['name'] = 'acluser'; + + $textfield = new html_inputfield($attrib); + + $fields['user'] = html::label(array('for' => 'iduser'), $this->gettext('username')) + . ' ' . $textfield->show(); + + // Add special entries + if (!empty($this->specials)) { + foreach ($this->specials as $key) { + $fields[$key] = html::label(array('for' => 'id'.$key), $this->gettext($key)); + } + } + + $this->rc->output->set_env('acl_specials', $this->specials); + + // Create list with radio buttons + if (count($fields) > 1) { + $ul = ''; + $radio = new html_radiobutton(array('name' => 'usertype')); + foreach ($fields as $key => $val) { + $ul .= html::tag('li', null, $radio->show($key == 'user' ? 'user' : '', + array('value' => $key, 'id' => 'id'.$key)) + . $val); + } + + $out = html::tag('ul', array('id' => 'usertype'), $ul, html::$common_attrib); + } + // Display text input alone + else { + $out = $fields['user']; + } + + return $out; + } + + /** + * Creates ACL rights table + * + * @param array $attrib Template object attributes + * + * @return string HTML Content + */ + private function list_rights($attrib=array()) + { + // Get ACL for the folder + $acl = $this->rc->imap->get_acl($this->mbox); + + if (!is_array($acl)) { + $acl = array(); + } + + // Keep special entries (anyone/anonymous) on top of the list + if (!empty($this->specials) && !empty($acl)) { + foreach ($this->specials as $key) { + if (isset($acl[$key])) { + $acl_special[$key] = $acl[$key]; + unset($acl[$key]); + } + } + } + + // Sort the list by username + uksort($acl, 'strnatcasecmp'); + + if (!empty($acl_special)) { + $acl = array_merge($acl_special, $acl); + } + + // Get supported rights and build column names + $supported = $this->rights_supported(); + + // depending on server capability either use 'te' or 'd' for deleting msgs + $deleteright = implode(array_intersect(str_split('ted'), $supported)); + + // Use advanced or simple (grouped) rights + $advanced = $this->rc->config->get('acl_advanced_mode'); + + if ($advanced) { + $items = array(); + foreach ($supported as $sup) { + $items[$sup] = $sup; + } + } + else { + $items = array( + 'read' => 'lrs', + 'write' => 'wi', + 'delete' => $deleteright, + 'other' => preg_replace('/[lrswi'.$deleteright.']/', '', implode($supported)), + ); + } + + // Create the table + $attrib['noheader'] = true; + $table = new html_table($attrib); + + // Create table header + $table->add_header('user', $this->gettext('identifier')); + foreach (array_keys($items) as $key) { + $table->add_header('acl'.$key, $this->gettext('shortacl'.$key)); + } + + $i = 1; + $js_table = array(); + foreach ($acl as $user => $rights) { + if ($this->rc->imap->conn->user == $user) { + continue; + } + + // filter out virtual rights (c or d) the server may return + $userrights = array_intersect($rights, $supported); + $userid = html_identifier($user); + + if (!empty($this->specials) && in_array($user, $this->specials)) { + $user = $this->gettext($user); + } + + $table->add_row(array('id' => 'rcmrow'.$userid)); + $table->add('user', Q($user)); + + foreach ($items as $key => $right) { + $in = $this->acl_compare($userrights, $right); + switch ($in) { + case 2: $class = 'enabled'; break; + case 1: $class = 'partial'; break; + default: $class = 'disabled'; break; + } + $table->add('acl' . $key . ' ' . $class, ''); + } + + $js_table[$userid] = implode($userrights); + } + + $this->rc->output->set_env('acl', $js_table); + $this->rc->output->set_env('acl_advanced', $advanced); + + $out = $table->show(); + + return $out; + } + + /** + * Handler for ACL update/create action + */ + private function action_save() + { + $mbox = trim(get_input_value('_mbox', RCUBE_INPUT_GPC, true)); // UTF7-IMAP + $user = trim(get_input_value('_user', RCUBE_INPUT_GPC)); + $acl = trim(get_input_value('_acl', RCUBE_INPUT_GPC)); + $oldid = trim(get_input_value('_old', RCUBE_INPUT_GPC)); + + $acl = array_intersect(str_split($acl), $this->rights_supported()); + + if (!empty($this->specials) && in_array($user, $this->specials)) { + $username = $this->gettext($user); + } + else { + if (!strpos($user, '@') && ($realm = $this->get_realm())) { + $user .= '@' . rcube_idn_to_ascii(preg_replace('/^@/', '', $realm)); + } + $username = $user; + } + + if ($acl && $user && $user != $_SESSION['username'] && strlen($mbox)) { + $result = $this->rc->imap->set_acl($mbox, $user, $acl); + } + + if ($result) { + $ret = array('id' => html_identifier($user), + 'username' => $username, 'acl' => implode($acl), 'old' => $oldid); + $this->rc->output->command('acl_update', $ret); + $this->rc->output->show_message($oldid ? 'acl.updatesuccess' : 'acl.createsuccess', 'confirmation'); + } + else { + $this->rc->output->show_message($oldid ? 'acl.updateerror' : 'acl.createerror', 'error'); + } + } + + /** + * Handler for ACL delete action + */ + private function action_delete() + { + $mbox = trim(get_input_value('_mbox', RCUBE_INPUT_GPC, true)); //UTF7-IMAP + $user = trim(get_input_value('_user', RCUBE_INPUT_GPC)); + + $user = explode(',', $user); + + foreach ($user as $u) { + if ($this->rc->imap->delete_acl($mbox, $u)) { + $this->rc->output->command('acl_remove_row', html_identifier($u)); + } + else { + $error = true; + } + } + + if (!$error) { + $this->rc->output->show_message('acl.deletesuccess', 'confirmation'); + } + else { + $this->rc->output->show_message('acl.deleteerror', 'error'); + } + } + + /** + * Handler for ACL list update action (with display mode change) + */ + private function action_list() + { + if (in_array('acl_advanced_mode', (array)$this->rc->config->get('dont_override'))) { + return; + } + + $this->mbox = trim(get_input_value('_mbox', RCUBE_INPUT_GPC, true)); // UTF7-IMAP + $advanced = trim(get_input_value('_mode', RCUBE_INPUT_GPC)); + $advanced = $advanced == 'advanced' ? true : false; + + // Save state in user preferences + $this->rc->user->save_prefs(array('acl_advanced_mode' => $advanced)); + + $out = $this->list_rights(); + + $out = preg_replace(array('/^]+>/', '/<\/table>$/'), '', $out); + + $this->rc->output->command('acl_list_update', $out); + } + + /** + * Creates