From 48e8459231a1efa3e97284d07a328776a5b7485b Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9my=20Bobbio?= Date: Sat, 18 Jun 2011 17:02:10 +0200 Subject: [PATCH] Imported Upstream version 0.2~alpha --- ._INSTALL | Bin 0 -> 187 bytes ._README | Bin 0 -> 184 bytes ._UPGRADING | Bin 0 -> 184 bytes CHANGELOG | 51 + INSTALL | 2 +- README | 5 +- SQL/mysql.initial.sql | 10 +- SQL/mysql.update.sql | 12 +- SQL/mysql5.initial.sql | 8 +- SQL/postgres.initial.sql | 3 + SQL/postgres.update.sql | 3 + SQL/sqlite.initial.sql | 3 + SQL/sqlite.update.sql | 3 + UPGRADING | 27 +- bin/html2text.php | 18 +- bin/modcss.php | 6 +- bin/msgexport.sh | 147 + bin/{msgimport => msgimport.sh} | 9 +- config/main.inc.php.dist | 94 +- index.php | 340 +- installer/._config.php | Bin 0 -> 187 bytes installer/check.php | 17 +- installer/config.php | 89 +- installer/index.php | 39 +- installer/rcube_install.php | 9 +- installer/test.php | 36 +- installer/welcome.html | 2 +- program/include/._main.inc | Bin 0 -> 184 bytes program/include/bugs.inc | 6 +- program/include/html.php | 642 + program/include/iniset.php | 98 + program/include/main.inc | 859 +- program/include/rcmail.php | 825 + program/include/rcmail_template.inc | 948 - program/include/rcube_browser.php | 75 + program/include/rcube_config.php | 181 + ...{rcube_contacts.inc => rcube_contacts.php} | 64 +- .../include/{rcube_db.inc => rcube_db.php} | 13 +- program/include/rcube_html.inc | 667 - program/include/rcube_html_page.php | 255 + .../{rcube_imap.inc => rcube_imap.php} | 203 +- program/include/rcube_json_output.php | 241 + .../{rcube_ldap.inc => rcube_ldap.php} | 199 +- .../rcube_mail_mime.php} | 63 +- .../{rcube_mdb2.inc => rcube_mdb2.php} | 15 +- program/include/rcube_message.php | 398 + program/include/rcube_result_set.php | 74 + program/include/rcube_shared.inc | 187 +- program/include/rcube_smtp.inc | 6 +- program/include/rcube_template.php | 1016 + .../{rcube_user.inc => rcube_user.php} | 127 +- program/include/session.inc | 37 +- program/js/app.js | 385 +- program/js/common.js | 19 +- program/js/editor.js | 56 +- program/js/list.js | 5 +- program/js/tiny_mce/blank.htm | 9 - program/js/tiny_mce/langs/en.js | 195 +- program/js/tiny_mce/langs/readme.txt | 9 - program/js/tiny_mce/license.txt | 1008 +- .../tiny_mce/plugins/cleanup/editor_plugin.js | 0 .../plugins/cleanup/editor_plugin_src.js | 10 - .../js/tiny_mce/plugins/cleanup/readme.txt | 1 - .../plugins/compat2x/editor_plugin.js | 1 + .../plugins/compat2x/editor_plugin_src.js | 613 + .../plugins/contextmenu/editor_plugin.js | 1 + .../plugins/contextmenu/editor_plugin_src.js | 97 + .../plugins/directionality/editor_plugin.js | 1 + .../directionality/editor_plugin_src.js | 79 + .../plugins/emotions/editor_plugin.js | 2 +- .../plugins/emotions/editor_plugin_src.js | 89 +- .../js/tiny_mce/plugins/emotions/emotions.htm | 43 +- .../plugins/emotions/images/emotions.gif | Bin 319 -> 0 bytes .../plugins/emotions/images/readme.txt | 2 - .../emotions/{images => img}/smiley-cool.gif | Bin .../emotions/{images => img}/smiley-cry.gif | Bin .../{images => img}/smiley-embarassed.gif | Bin .../{images => img}/smiley-foot-in-mouth.gif | Bin .../emotions/{images => img}/smiley-frown.gif | Bin .../{images => img}/smiley-innocent.gif | Bin .../emotions/{images => img}/smiley-kiss.gif | Bin .../{images => img}/smiley-laughing.gif | Bin .../{images => img}/smiley-money-mouth.gif | Bin .../{images => img}/smiley-sealed.gif | Bin .../emotions/{images => img}/smiley-smile.gif | Bin .../{images => img}/smiley-surprised.gif | Bin .../{images => img}/smiley-tongue-out.gif | Bin .../{images => img}/smiley-undecided.gif | Bin .../emotions/{images => img}/smiley-wink.gif | Bin .../emotions/{images => img}/smiley-yell.gif | Bin .../tiny_mce/plugins/emotions/js/emotions.js | 22 + .../plugins/emotions/jscripts/functions.js | 21 - .../js/tiny_mce/plugins/emotions/langs/en.js | 22 - .../tiny_mce/plugins/emotions/langs/en_dlg.js | 20 + .../js/tiny_mce/plugins/emotions/readme.txt | 1 - .../js/tiny_mce/plugins/media/css/content.css | 32 +- .../js/tiny_mce/plugins/media/css/media.css | 136 +- .../tiny_mce/plugins/media/editor_plugin.js | 2 +- .../plugins/media/editor_plugin_src.js | 791 +- .../tiny_mce/plugins/media/images/media.gif | Bin 280 -> 0 bytes .../plugins/media/{images => img}/flash.gif | Bin .../tiny_mce/plugins/media/img/flv_player.swf | Bin 0 -> 11668 bytes .../media/{images => img}/quicktime.gif | Bin .../media/{images => img}/realmedia.gif | Bin .../media/{images => img}/shockwave.gif | Bin .../media/img/trans.gif} | Bin .../media/{images => img}/windowsmedia.gif | Bin .../plugins/media/{jscripts => js}/embed.js | 146 +- .../plugins/media/{jscripts => js}/media.js | 1215 +- program/js/tiny_mce/plugins/media/langs/en.js | 94 - .../js/tiny_mce/plugins/media/langs/en_dlg.js | 103 + program/js/tiny_mce/plugins/media/media.htm | 359 +- .../plugins/nonbreaking/editor_plugin.js | 2 +- .../plugins/nonbreaking/editor_plugin_src.js | 96 +- .../nonbreaking/images/nonbreaking.gif | Bin 619 -> 0 bytes .../tiny_mce/plugins/nonbreaking/langs/en.js | 5 - program/js/tiny_mce/plugins/paste/blank.htm | 22 + .../js/tiny_mce/plugins/paste/css/blank.css | 14 + .../tiny_mce/plugins/paste/css/pasteword.css | 3 + .../tiny_mce/plugins/paste/editor_plugin.js | 1 + .../plugins/paste/editor_plugin_src.js | 387 + .../js/tiny_mce/plugins/paste/js/pastetext.js | 42 + .../js/tiny_mce/plugins/paste/js/pasteword.js | 56 + .../js/tiny_mce/plugins/paste/langs/en_dlg.js | 5 + .../js/tiny_mce/plugins/paste/pastetext.htm | 34 + .../js/tiny_mce/plugins/paste/pasteword.htm | 29 + program/js/tiny_mce/plugins/readme.txt | 1 - .../searchreplace/css/searchreplace.css | 24 +- .../plugins/searchreplace/editor_plugin.js | 2 +- .../searchreplace/editor_plugin_src.js | 213 +- .../plugins/searchreplace/images/replace.gif | Bin 125 -> 0 bytes .../images/replace_all_button_bg.gif | Bin 669 -> 0 bytes .../images/replace_button_bg.gif | Bin 669 -> 0 bytes .../plugins/searchreplace/images/search.gif | Bin 191 -> 0 bytes .../plugins/searchreplace/js/searchreplace.js | 117 + .../searchreplace/jscripts/searchreplace.js | 86 - .../plugins/searchreplace/langs/en.js | 21 - .../plugins/searchreplace/langs/en_dlg.js | 16 + .../tiny_mce/plugins/searchreplace/readme.txt | 1 - .../plugins/searchreplace/searchreplace.htm | 56 +- .../tiny_mce/plugins/spellchecker/changelog | 11 - .../classes/TinyGoogleSpell.class.php | 107 - .../spellchecker/classes/TinyPspell.class.php | 64 - .../classes/TinyPspellShell.class.php | 121 - .../tiny_mce/plugins/spellchecker/config.php | 26 - .../plugins/spellchecker/css/content.css | 6 +- .../plugins/spellchecker/css/spellchecker.css | 34 - .../plugins/spellchecker/editor_plugin.js | 2 +- .../plugins/spellchecker/editor_plugin_src.js | 814 +- .../spellchecker/images/spellchecker.gif | Bin 591 -> 0 bytes .../spellchecker/{images => img}/wline.gif | Bin .../tiny_mce/plugins/spellchecker/langs/en.js | 15 - .../plugins/spellchecker/tinyspell.php | 142 - program/js/tiny_mce/plugins/table/cell.htm | 102 +- .../js/tiny_mce/plugins/table/css/cell.css | 32 +- program/js/tiny_mce/plugins/table/css/row.css | 50 +- .../js/tiny_mce/plugins/table/css/table.css | 26 +- .../tiny_mce/plugins/table/editor_plugin.js | 2 +- .../plugins/table/editor_plugin_src.js | 1679 +- .../tiny_mce/plugins/table/images/buttons.gif | Bin 1787 -> 0 bytes .../tiny_mce/plugins/table/images/table.gif | Bin 287 -> 0 bytes .../plugins/table/images/table_cell_props.gif | Bin 189 -> 0 bytes .../plugins/table/images/table_delete.gif | Bin 372 -> 0 bytes .../plugins/table/images/table_delete_col.gif | Bin 153 -> 0 bytes .../plugins/table/images/table_delete_row.gif | Bin 160 -> 0 bytes .../table/images/table_insert_col_after.gif | Bin 165 -> 0 bytes .../table/images/table_insert_col_before.gif | Bin 165 -> 0 bytes .../table/images/table_insert_row_after.gif | Bin 163 -> 0 bytes .../table/images/table_insert_row_before.gif | Bin 159 -> 0 bytes .../table/images/table_merge_cells.gif | Bin 198 -> 0 bytes .../plugins/table/images/table_row_props.gif | Bin 187 -> 0 bytes .../table/images/table_split_cells.gif | Bin 210 -> 0 bytes .../plugins/table/{jscripts => js}/cell.js | 94 +- .../tiny_mce/plugins/table/js/merge_cells.js | 29 + .../plugins/table/{jscripts => js}/row.js | 86 +- .../plugins/table/{jscripts => js}/table.js | 216 +- .../plugins/table/jscripts/merge_cells.js | 24 - program/js/tiny_mce/plugins/table/langs/en.js | 79 - .../js/tiny_mce/plugins/table/langs/en_dlg.js | 74 + .../js/tiny_mce/plugins/table/merge_cells.htm | 28 +- program/js/tiny_mce/plugins/table/readme.txt | 1 - program/js/tiny_mce/plugins/table/row.htm | 90 +- program/js/tiny_mce/plugins/table/table.htm | 131 +- .../plugins/visualchars/editor_plugin.js | 2 +- .../plugins/visualchars/editor_plugin_src.js | 146 +- .../visualchars/images/visualchars.gif | Bin 134 -> 0 bytes .../tiny_mce/plugins/visualchars/langs/en.js | 5 - .../js/tiny_mce/plugins/xhtmlxtras/abbr.htm | 149 + .../tiny_mce/plugins/xhtmlxtras/acronym.htm | 149 + .../plugins/xhtmlxtras/attributes.htm | 154 + .../js/tiny_mce/plugins/xhtmlxtras/cite.htm | 149 + .../plugins/xhtmlxtras/css/attributes.css | 11 + .../tiny_mce/plugins/xhtmlxtras/css/popup.css | 9 + .../plugins/xhtmlxtras/css/xhtmlxtras.css | 24 + .../js/tiny_mce/plugins/xhtmlxtras/del.htm | 170 + .../plugins/xhtmlxtras/editor_plugin.js | 1 + .../plugins/xhtmlxtras/editor_plugin_src.js | 134 + .../js/tiny_mce/plugins/xhtmlxtras/ins.htm | 170 + .../js/tiny_mce/plugins/xhtmlxtras/js/abbr.js | 25 + .../tiny_mce/plugins/xhtmlxtras/js/acronym.js | 25 + .../plugins/xhtmlxtras/js/attributes.js | 123 + .../js/tiny_mce/plugins/xhtmlxtras/js/cite.js | 25 + .../js/tiny_mce/plugins/xhtmlxtras/js/del.js | 50 + .../plugins/xhtmlxtras/js/element_common.js | 221 + .../js/tiny_mce/plugins/xhtmlxtras/js/ins.js | 49 + .../plugins/xhtmlxtras/langs/en_dlg.js | 32 + program/js/tiny_mce/themes/advanced/about.htm | 34 +- .../js/tiny_mce/themes/advanced/anchor.htm | 23 +- .../js/tiny_mce/themes/advanced/charmap.htm | 21 +- .../tiny_mce/themes/advanced/color_picker.htm | 34 +- .../themes/advanced/css/editor_content.css | 58 - .../themes/advanced/css/editor_popup.css | 331 - .../themes/advanced/docs/en/about.htm | 31 - .../advanced/docs/en/common_buttons.htm | 162 - .../docs/en/create_accessible_content.htm | 45 - .../docs/en/images/insert_anchor_window.gif | Bin 5189 -> 0 bytes .../docs/en/images/insert_image_window.gif | Bin 7195 -> 0 bytes .../docs/en/images/insert_link_window.gif | Bin 5658 -> 0 bytes .../docs/en/images/insert_table_window.gif | Bin 7094 -> 0 bytes .../themes/advanced/docs/en/index.htm | 27 - .../advanced/docs/en/insert_anchor_button.htm | 32 - .../advanced/docs/en/insert_image_button.htm | 65 - .../advanced/docs/en/insert_link_button.htm | 33 - .../advanced/docs/en/insert_table_button.htm | 71 - .../themes/advanced/docs/en/style.css | 28 - .../themes/advanced/editor_template.js | 2 +- .../themes/advanced/editor_template_src.js | 2564 +-- program/js/tiny_mce/themes/advanced/image.htm | 186 +- .../themes/advanced/images/anchor.gif | Bin 171 -> 0 bytes .../themes/advanced/images/backcolor.gif | Bin 359 -> 0 bytes .../tiny_mce/themes/advanced/images/bold.gif | Bin 76 -> 0 bytes .../themes/advanced/images/bold_de_se.gif | Bin 73 -> 0 bytes .../themes/advanced/images/bold_es.gif | Bin 80 -> 0 bytes .../themes/advanced/images/bold_fr.gif | Bin 78 -> 0 bytes .../themes/advanced/images/bold_ru.gif | Bin 77 -> 0 bytes .../themes/advanced/images/bold_tw.gif | Bin 207 -> 0 bytes .../themes/advanced/images/browse.gif | Bin 113 -> 0 bytes .../themes/advanced/images/bullist.gif | Bin 108 -> 0 bytes .../themes/advanced/images/button_menu.gif | Bin 57 -> 0 bytes .../themes/advanced/images/buttons.gif | Bin 5662 -> 0 bytes .../advanced/images/cancel_button_bg.gif | Bin 677 -> 0 bytes .../themes/advanced/images/charmap.gif | Bin 245 -> 0 bytes .../themes/advanced/images/cleanup.gif | Bin 256 -> 0 bytes .../tiny_mce/themes/advanced/images/close.gif | Bin 102 -> 0 bytes .../tiny_mce/themes/advanced/images/code.gif | Bin 110 -> 0 bytes .../tiny_mce/themes/advanced/images/color.gif | Bin 125 -> 0 bytes .../tiny_mce/themes/advanced/images/copy.gif | Bin 263 -> 0 bytes .../themes/advanced/images/custom_1.gif | Bin 76 -> 0 bytes .../tiny_mce/themes/advanced/images/cut.gif | Bin 187 -> 0 bytes .../themes/advanced/images/forecolor.gif | Bin 342 -> 0 bytes .../tiny_mce/themes/advanced/images/help.gif | Bin 295 -> 0 bytes .../js/tiny_mce/themes/advanced/images/hr.gif | Bin 63 -> 0 bytes .../tiny_mce/themes/advanced/images/image.gif | Bin 194 -> 0 bytes .../themes/advanced/images/indent.gif | Bin 112 -> 0 bytes .../advanced/images/insert_button_bg.gif | Bin 703 -> 0 bytes .../themes/advanced/images/italic.gif | Bin 79 -> 0 bytes .../themes/advanced/images/italic_de_se.gif | Bin 75 -> 0 bytes .../themes/advanced/images/italic_es.gif | Bin 74 -> 0 bytes .../themes/advanced/images/italic_ru.gif | Bin 78 -> 0 bytes .../themes/advanced/images/italic_tw.gif | Bin 274 -> 0 bytes .../themes/advanced/images/justifycenter.gif | Bin 70 -> 0 bytes .../themes/advanced/images/justifyfull.gif | Bin 71 -> 0 bytes .../themes/advanced/images/justifyleft.gif | Bin 71 -> 0 bytes .../themes/advanced/images/justifyright.gif | Bin 70 -> 0 bytes .../tiny_mce/themes/advanced/images/link.gif | Bin 175 -> 0 bytes .../themes/advanced/images/menu_check.gif | Bin 51 -> 0 bytes .../themes/advanced/images/newdocument.gif | Bin 170 -> 0 bytes .../themes/advanced/images/numlist.gif | Bin 111 -> 0 bytes .../themes/advanced/images/opacity.png | Bin 147 -> 0 bytes .../themes/advanced/images/outdent.gif | Bin 110 -> 0 bytes .../tiny_mce/themes/advanced/images/paste.gif | Bin 286 -> 0 bytes .../tiny_mce/themes/advanced/images/redo.gif | Bin 169 -> 0 bytes .../themes/advanced/images/removeformat.gif | Bin 168 -> 0 bytes .../themes/advanced/images/separator.gif | Bin 57 -> 0 bytes .../advanced/images/statusbar_resize.gif | Bin 79 -> 0 bytes .../themes/advanced/images/strikethrough.gif | Bin 83 -> 0 bytes .../tiny_mce/themes/advanced/images/sub.gif | Bin 148 -> 0 bytes .../tiny_mce/themes/advanced/images/sup.gif | Bin 147 -> 0 bytes .../themes/advanced/images/underline.gif | Bin 88 -> 0 bytes .../themes/advanced/images/underline_es.gif | Bin 79 -> 0 bytes .../themes/advanced/images/underline_fr.gif | Bin 79 -> 0 bytes .../themes/advanced/images/underline_ru.gif | Bin 77 -> 0 bytes .../themes/advanced/images/underline_tw.gif | Bin 245 -> 0 bytes .../tiny_mce/themes/advanced/images/undo.gif | Bin 175 -> 0 bytes .../themes/advanced/images/unlink.gif | Bin 190 -> 0 bytes .../themes/advanced/images/visualaid.gif | Bin 206 -> 0 bytes .../themes/advanced/images/xp/tab_bg.gif | Bin 694 -> 0 bytes .../themes/advanced/images/xp/tab_end.gif | Bin 169 -> 0 bytes .../themes/advanced/images/xp/tab_sel_bg.gif | Bin 428 -> 0 bytes .../themes/advanced/images/xp/tab_sel_end.gif | Bin 101 -> 0 bytes .../themes/advanced/images/xp/tabs_bg.gif | Bin 48 -> 0 bytes .../colors.jpg => img/colorpicker.jpg} | Bin .../js/tiny_mce/themes/advanced/img/icons.gif | Bin 0 -> 11505 bytes .../js/tiny_mce/themes/advanced/js/about.js | 72 + .../js/tiny_mce/themes/advanced/js/anchor.js | 37 + .../advanced/{jscripts => js}/charmap.js | 33 +- .../advanced/{jscripts => js}/color_picker.js | 33 +- .../js/tiny_mce/themes/advanced/js/image.js | 245 + .../js/tiny_mce/themes/advanced/js/link.js | 126 + .../{jscripts => js}/source_editor.js | 33 +- .../themes/advanced/jscripts/about.js | 75 - .../themes/advanced/jscripts/anchor.js | 74 - .../themes/advanced/jscripts/image.js | 81 - .../tiny_mce/themes/advanced/jscripts/link.js | 74 - .../js/tiny_mce/themes/advanced/langs/en.js | 155 +- .../tiny_mce/themes/advanced/langs/en_dlg.js | 51 + program/js/tiny_mce/themes/advanced/link.htm | 93 +- .../themes/advanced/skins/default/content.css | 25 + .../themes/advanced/skins/default/dialog.css | 114 + .../advanced/skins/default/img/buttons.png | Bin 0 -> 3274 bytes .../default/img/items.gif} | Bin .../advanced/skins/default/img/menu_arrow.gif | Bin 0 -> 68 bytes .../advanced/skins/default/img/menu_check.gif | Bin 0 -> 70 bytes .../advanced/skins/default/img/progress.gif | Bin 0 -> 1787 bytes .../advanced/skins/default/img/tabs.gif | Bin 0 -> 1326 bytes .../themes/advanced/skins/default/ui.css | 211 + .../themes/advanced/skins/o2k7/content.css | 25 + .../themes/advanced/skins/o2k7/dialog.css | 113 + .../advanced/skins/o2k7/img/button_bg.png | Bin 0 -> 5859 bytes .../skins/o2k7/img/button_bg_black.png | Bin 0 -> 3736 bytes .../skins/o2k7/img/button_bg_silver.png | Bin 0 -> 5358 bytes .../themes/advanced/skins/o2k7/ui.css | 211 + .../themes/advanced/skins/o2k7/ui_black.css | 8 + .../themes/advanced/skins/o2k7/ui_silver.css | 5 + .../themes/advanced/source_editor.htm | 20 +- .../tiny_mce/themes/simple/editor_template.js | 1 + .../themes/simple/editor_template_src.js | 85 + .../js/tiny_mce/themes/simple/img/icons.gif | Bin 0 -> 1440 bytes program/js/tiny_mce/themes/simple/langs/en.js | 11 + .../themes/simple/skins/default/content.css | 25 + .../themes/simple/skins/default/ui.css | 32 + .../themes/simple/skins/o2k7/content.css | 17 + .../simple/skins/o2k7/img/button_bg.png | Bin 0 -> 5102 bytes .../tiny_mce/themes/simple/skins/o2k7/ui.css | 35 + program/js/tiny_mce/tiny_mce.js | 2 +- program/js/tiny_mce/tiny_mce_popup.js | 569 +- program/js/tiny_mce/tiny_mce_src.js | 17885 +++++++++------- program/js/tiny_mce/utils/editable_selects.js | 122 +- program/js/tiny_mce/utils/form_utils.js | 409 +- program/js/tiny_mce/utils/mclayer.js | 210 - program/js/tiny_mce/utils/mctabs.js | 150 +- program/js/tiny_mce/utils/validate.js | 438 +- program/lib/._enriched.inc | Bin 0 -> 184 bytes program/lib/._utf7.inc | Bin 0 -> 184 bytes program/lib/._washtml.php | Bin 0 -> 184 bytes program/lib/{html2text.inc => html2text.php} | 0 program/lib/imap.inc | 904 +- program/lib/magic | 10810 ---------- program/lib/washtml.php | 196 + program/localization/{ar => ar_SA}/labels.inc | 59 +- .../localization/{ar => ar_SA}/messages.inc | 27 +- program/localization/{bg => bg_BG}/labels.inc | 0 .../localization/{bg => bg_BG}/messages.inc | 0 program/localization/{ca => ca_ES}/labels.inc | 59 +- .../localization/{ca => ca_ES}/messages.inc | 25 +- program/localization/{cz => cs_CZ}/labels.inc | 0 .../localization/{cz => cs_CZ}/messages.inc | 0 program/localization/{da => da_DK}/labels.inc | 0 .../localization/{da => da_DK}/messages.inc | 0 program/localization/de_CH/labels.inc | 44 +- program/localization/de_CH/messages.inc | 3 +- program/localization/de_DE/labels.inc | 39 +- program/localization/de_DE/messages.inc | 3 +- program/localization/{el => el_GR}/labels.inc | 0 .../localization/{el => el_GR}/messages.inc | 0 program/localization/en_GB/labels.inc | 32 +- program/localization/en_US/labels.inc | 43 +- program/localization/en_US/messages.inc | 3 +- program/localization/{es => es_ES}/labels.inc | 66 +- .../localization/{es => es_ES}/messages.inc | 0 program/localization/et_EE/labels.inc | 38 +- program/localization/et_EE/messages.inc | 1 + program/localization/{eu => eu_ES}/labels.inc | 0 .../localization/{eu => eu_ES}/messages.inc | 0 program/localization/{fi => fi_FI}/labels.inc | 63 +- .../localization/{fi => fi_FI}/messages.inc | 27 +- program/localization/{fr => fr_FR}/labels.inc | 0 .../localization/{fr => fr_FR}/messages.inc | 0 program/localization/{gl => gl_ES}/labels.inc | 0 .../localization/{gl => gl_ES}/messages.inc | 0 program/localization/{he => he_IL}/labels.inc | 410 +- .../localization/{he => he_IL}/messages.inc | 157 +- program/localization/{hi => hi_IN}/labels.inc | 0 .../localization/{hi => hi_IN}/messages.inc | 0 program/localization/{hu => hu_HU}/labels.inc | 0 .../localization/{hu => hu_HU}/messages.inc | 2 +- program/localization/{am => hy_AM}/labels.inc | 0 .../localization/{am => hy_AM}/messages.inc | 0 program/localization/index.inc | 181 +- program/localization/{is => is_IS}/labels.inc | 0 .../localization/{is => is_IS}/messages.inc | 0 program/localization/{it => it_IT}/labels.inc | 0 .../localization/{it => it_IT}/messages.inc | 0 program/localization/{ja => ja_JP}/labels.inc | 30 +- .../localization/{ja => ja_JP}/messages.inc | 6 +- program/localization/{ge => ka_GE}/labels.inc | 0 .../localization/{ge => ka_GE}/messages.inc | 0 program/localization/{kr => ko_KR}/labels.inc | 0 .../localization/{kr => ko_KR}/messages.inc | 0 program/localization/{lt => lt_LT}/labels.inc | 59 +- .../localization/{lt => lt_LT}/messages.inc | 0 program/localization/{lv => lv_LV}/labels.inc | 0 .../localization/{lv => lv_LV}/messages.inc | 0 program/localization/{mk => mk_MK}/labels.inc | 0 .../localization/{mk => mk_MK}/messages.inc | 0 program/localization/ms_MY/labels.inc | 319 +- program/localization/ms_MY/messages.inc | 43 +- program/localization/nb_NO/labels.inc | 30 +- program/localization/{ne => ne_NP}/labels.inc | 0 .../localization/{ne => ne_NP}/messages.inc | 0 program/localization/nl_NL/labels.inc | 64 +- program/localization/{pl => pl_PL}/labels.inc | 50 +- .../localization/{pl => pl_PL}/messages.inc | 6 +- program/localization/pt_PT/labels.inc | 61 +- program/localization/{ro => ro_RO}/labels.inc | 0 .../localization/{ro => ro_RO}/messages.inc | 0 program/localization/{ru => ru_RU}/labels.inc | 95 +- .../localization/{ru => ru_RU}/messages.inc | 0 program/localization/{si => si_LK}/labels.inc | 0 .../localization/{si => si_LK}/messages.inc | 0 program/localization/sk/messages.inc | 83 - program/localization/{sk => sk_SK}/labels.inc | 146 +- program/localization/sk_SK/messages.inc | 85 + program/localization/{sl => sl_SI}/labels.inc | 0 .../localization/{sl => sl_SI}/messages.inc | 0 .../{sr_cyrillic => sr_CS}/labels.inc | 0 .../{sr_cyrillic => sr_CS}/messages.inc | 0 program/localization/sr_latin/labels.inc | 217 - program/localization/sr_latin/messages.inc | 66 - program/localization/{se => sv_SE}/labels.inc | 2 +- .../localization/{se => sv_SE}/messages.inc | 0 program/localization/{tr => tr_TR}/labels.inc | 0 .../localization/{tr => tr_TR}/messages.inc | 0 program/localization/{uk => uk_UA}/labels.inc | 0 .../localization/{uk => uk_UA}/messages.inc | 0 program/localization/{vn => vi_VN}/labels.inc | 0 .../localization/{vn => vi_VN}/messages.inc | 0 program/localization/zh_CN/labels.inc | 70 +- program/localization/zh_CN/messages.inc | 3 +- program/localization/zh_TW/labels.inc | 6 +- program/steps/addressbook/delete.inc | 7 +- program/steps/addressbook/edit.inc | 24 +- program/steps/addressbook/func.inc | 65 +- program/steps/addressbook/save.inc | 48 +- program/steps/error.inc | 7 +- program/steps/mail/addcontact.inc | 20 +- program/steps/mail/check_recent.inc | 2 +- program/steps/mail/compose.inc | 380 +- program/steps/mail/folders.inc | 8 +- program/steps/mail/func.inc | 911 +- program/steps/mail/get.inc | 76 +- program/steps/mail/mark.inc | 11 +- program/steps/mail/move_del.inc | 105 +- program/steps/mail/quotadisplay.inc | 28 - program/steps/mail/sendmail.inc | 23 +- program/steps/mail/sendmdn.inc | 2 - program/steps/mail/show.inc | 153 +- program/steps/mail/upload.inc | 16 +- program/steps/mail/viewsource.inc | 2 +- program/steps/settings/edit_identity.inc | 45 +- program/steps/settings/func.inc | 134 +- program/steps/settings/identities.inc | 7 +- program/steps/settings/manage_folders.inc | 159 +- program/steps/settings/save_identity.inc | 14 +- program/steps/settings/save_prefs.inc | 19 +- skins/default/common.css | 7 +- skins/default/editor_ui.css | 97 - skins/default/includes/settingstabs.html | 4 +- skins/default/mail.css | 57 +- skins/default/settings.css | 12 + skins/default/templates/compose.html | 4 +- skins/default/templates/mail.html | 2 +- skins/default/templates/message.html | 3 + skins/default/templates/messagepart.html | 4 + skins/default/templates/settings.html | 2 +- 475 files changed, 29611 insertions(+), 33994 deletions(-) create mode 100644 ._INSTALL create mode 100644 ._README create mode 100644 ._UPGRADING create mode 100755 bin/msgexport.sh rename bin/{msgimport => msgimport.sh} (88%) create mode 100644 installer/._config.php create mode 100644 program/include/._main.inc create mode 100644 program/include/html.php create mode 100755 program/include/iniset.php create mode 100644 program/include/rcmail.php delete mode 100644 program/include/rcmail_template.inc create mode 100644 program/include/rcube_browser.php create mode 100644 program/include/rcube_config.php rename program/include/{rcube_contacts.inc => rcube_contacts.php} (90%) rename program/include/{rcube_db.inc => rcube_db.php} (98%) delete mode 100644 program/include/rcube_html.inc create mode 100644 program/include/rcube_html_page.php rename program/include/{rcube_imap.inc => rcube_imap.php} (95%) create mode 100644 program/include/rcube_json_output.php rename program/include/{rcube_ldap.inc => rcube_ldap.php} (61%) rename program/{lib/rc_mail_mime.inc => include/rcube_mail_mime.php} (85%) rename program/include/{rcube_mdb2.inc => rcube_mdb2.php} (97%) create mode 100644 program/include/rcube_message.php create mode 100644 program/include/rcube_result_set.php create mode 100755 program/include/rcube_template.php rename program/include/{rcube_user.inc => rcube_user.php} (79%) delete mode 100644 program/js/tiny_mce/blank.htm delete mode 100644 program/js/tiny_mce/langs/readme.txt delete mode 100644 program/js/tiny_mce/plugins/cleanup/editor_plugin.js delete mode 100644 program/js/tiny_mce/plugins/cleanup/editor_plugin_src.js delete mode 100644 program/js/tiny_mce/plugins/cleanup/readme.txt create mode 100644 program/js/tiny_mce/plugins/compat2x/editor_plugin.js create mode 100644 program/js/tiny_mce/plugins/compat2x/editor_plugin_src.js create mode 100644 program/js/tiny_mce/plugins/contextmenu/editor_plugin.js create mode 100644 program/js/tiny_mce/plugins/contextmenu/editor_plugin_src.js create mode 100644 program/js/tiny_mce/plugins/directionality/editor_plugin.js create mode 100644 program/js/tiny_mce/plugins/directionality/editor_plugin_src.js delete mode 100644 program/js/tiny_mce/plugins/emotions/images/emotions.gif delete mode 100644 program/js/tiny_mce/plugins/emotions/images/readme.txt rename program/js/tiny_mce/plugins/emotions/{images => img}/smiley-cool.gif (100%) rename program/js/tiny_mce/plugins/emotions/{images => img}/smiley-cry.gif (100%) rename program/js/tiny_mce/plugins/emotions/{images => img}/smiley-embarassed.gif (100%) rename program/js/tiny_mce/plugins/emotions/{images => img}/smiley-foot-in-mouth.gif (100%) rename program/js/tiny_mce/plugins/emotions/{images => img}/smiley-frown.gif (100%) rename program/js/tiny_mce/plugins/emotions/{images => img}/smiley-innocent.gif (100%) rename program/js/tiny_mce/plugins/emotions/{images => img}/smiley-kiss.gif (100%) rename program/js/tiny_mce/plugins/emotions/{images => img}/smiley-laughing.gif (100%) rename program/js/tiny_mce/plugins/emotions/{images => img}/smiley-money-mouth.gif (100%) rename program/js/tiny_mce/plugins/emotions/{images => img}/smiley-sealed.gif (100%) rename program/js/tiny_mce/plugins/emotions/{images => img}/smiley-smile.gif (100%) rename program/js/tiny_mce/plugins/emotions/{images => img}/smiley-surprised.gif (100%) rename program/js/tiny_mce/plugins/emotions/{images => img}/smiley-tongue-out.gif (100%) rename program/js/tiny_mce/plugins/emotions/{images => img}/smiley-undecided.gif (100%) rename program/js/tiny_mce/plugins/emotions/{images => img}/smiley-wink.gif (100%) rename program/js/tiny_mce/plugins/emotions/{images => img}/smiley-yell.gif (100%) create mode 100644 program/js/tiny_mce/plugins/emotions/js/emotions.js delete mode 100644 program/js/tiny_mce/plugins/emotions/jscripts/functions.js delete mode 100644 program/js/tiny_mce/plugins/emotions/langs/en.js create mode 100644 program/js/tiny_mce/plugins/emotions/langs/en_dlg.js delete mode 100644 program/js/tiny_mce/plugins/emotions/readme.txt delete mode 100644 program/js/tiny_mce/plugins/media/images/media.gif rename program/js/tiny_mce/plugins/media/{images => img}/flash.gif (100%) create mode 100644 program/js/tiny_mce/plugins/media/img/flv_player.swf rename program/js/tiny_mce/plugins/media/{images => img}/quicktime.gif (100%) rename program/js/tiny_mce/plugins/media/{images => img}/realmedia.gif (100%) rename program/js/tiny_mce/plugins/media/{images => img}/shockwave.gif (100%) rename program/js/tiny_mce/{themes/advanced/images/spacer.gif => plugins/media/img/trans.gif} (100%) rename program/js/tiny_mce/plugins/media/{images => img}/windowsmedia.gif (100%) rename program/js/tiny_mce/plugins/media/{jscripts => js}/embed.js (96%) rename program/js/tiny_mce/plugins/media/{jscripts => js}/media.js (83%) delete mode 100644 program/js/tiny_mce/plugins/media/langs/en.js create mode 100644 program/js/tiny_mce/plugins/media/langs/en_dlg.js delete mode 100644 program/js/tiny_mce/plugins/nonbreaking/images/nonbreaking.gif delete mode 100644 program/js/tiny_mce/plugins/nonbreaking/langs/en.js create mode 100644 program/js/tiny_mce/plugins/paste/blank.htm create mode 100644 program/js/tiny_mce/plugins/paste/css/blank.css create mode 100644 program/js/tiny_mce/plugins/paste/css/pasteword.css create mode 100644 program/js/tiny_mce/plugins/paste/editor_plugin.js create mode 100644 program/js/tiny_mce/plugins/paste/editor_plugin_src.js create mode 100644 program/js/tiny_mce/plugins/paste/js/pastetext.js create mode 100644 program/js/tiny_mce/plugins/paste/js/pasteword.js create mode 100644 program/js/tiny_mce/plugins/paste/langs/en_dlg.js create mode 100644 program/js/tiny_mce/plugins/paste/pastetext.htm create mode 100644 program/js/tiny_mce/plugins/paste/pasteword.htm delete mode 100644 program/js/tiny_mce/plugins/readme.txt delete mode 100644 program/js/tiny_mce/plugins/searchreplace/images/replace.gif delete mode 100644 program/js/tiny_mce/plugins/searchreplace/images/replace_all_button_bg.gif delete mode 100644 program/js/tiny_mce/plugins/searchreplace/images/replace_button_bg.gif delete mode 100644 program/js/tiny_mce/plugins/searchreplace/images/search.gif create mode 100644 program/js/tiny_mce/plugins/searchreplace/js/searchreplace.js delete mode 100644 program/js/tiny_mce/plugins/searchreplace/jscripts/searchreplace.js delete mode 100644 program/js/tiny_mce/plugins/searchreplace/langs/en.js create mode 100644 program/js/tiny_mce/plugins/searchreplace/langs/en_dlg.js delete mode 100644 program/js/tiny_mce/plugins/searchreplace/readme.txt delete mode 100644 program/js/tiny_mce/plugins/spellchecker/changelog delete mode 100644 program/js/tiny_mce/plugins/spellchecker/classes/TinyGoogleSpell.class.php delete mode 100644 program/js/tiny_mce/plugins/spellchecker/classes/TinyPspell.class.php delete mode 100644 program/js/tiny_mce/plugins/spellchecker/classes/TinyPspellShell.class.php delete mode 100644 program/js/tiny_mce/plugins/spellchecker/config.php delete mode 100644 program/js/tiny_mce/plugins/spellchecker/css/spellchecker.css delete mode 100644 program/js/tiny_mce/plugins/spellchecker/images/spellchecker.gif rename program/js/tiny_mce/plugins/spellchecker/{images => img}/wline.gif (100%) delete mode 100644 program/js/tiny_mce/plugins/spellchecker/langs/en.js delete mode 100644 program/js/tiny_mce/plugins/spellchecker/tinyspell.php delete mode 100644 program/js/tiny_mce/plugins/table/images/buttons.gif delete mode 100644 program/js/tiny_mce/plugins/table/images/table.gif delete mode 100644 program/js/tiny_mce/plugins/table/images/table_cell_props.gif delete mode 100644 program/js/tiny_mce/plugins/table/images/table_delete.gif delete mode 100644 program/js/tiny_mce/plugins/table/images/table_delete_col.gif delete mode 100644 program/js/tiny_mce/plugins/table/images/table_delete_row.gif delete mode 100644 program/js/tiny_mce/plugins/table/images/table_insert_col_after.gif delete mode 100644 program/js/tiny_mce/plugins/table/images/table_insert_col_before.gif delete mode 100644 program/js/tiny_mce/plugins/table/images/table_insert_row_after.gif delete mode 100644 program/js/tiny_mce/plugins/table/images/table_insert_row_before.gif delete mode 100644 program/js/tiny_mce/plugins/table/images/table_merge_cells.gif delete mode 100644 program/js/tiny_mce/plugins/table/images/table_row_props.gif delete mode 100644 program/js/tiny_mce/plugins/table/images/table_split_cells.gif rename program/js/tiny_mce/plugins/table/{jscripts => js}/cell.js (70%) create mode 100644 program/js/tiny_mce/plugins/table/js/merge_cells.js rename program/js/tiny_mce/plugins/table/{jscripts => js}/row.js (66%) rename program/js/tiny_mce/plugins/table/{jscripts => js}/table.js (60%) delete mode 100644 program/js/tiny_mce/plugins/table/jscripts/merge_cells.js delete mode 100644 program/js/tiny_mce/plugins/table/langs/en.js create mode 100644 program/js/tiny_mce/plugins/table/langs/en_dlg.js delete mode 100644 program/js/tiny_mce/plugins/table/readme.txt delete mode 100644 program/js/tiny_mce/plugins/visualchars/images/visualchars.gif delete mode 100644 program/js/tiny_mce/plugins/visualchars/langs/en.js create mode 100644 program/js/tiny_mce/plugins/xhtmlxtras/abbr.htm create mode 100644 program/js/tiny_mce/plugins/xhtmlxtras/acronym.htm create mode 100644 program/js/tiny_mce/plugins/xhtmlxtras/attributes.htm create mode 100644 program/js/tiny_mce/plugins/xhtmlxtras/cite.htm create mode 100644 program/js/tiny_mce/plugins/xhtmlxtras/css/attributes.css create mode 100644 program/js/tiny_mce/plugins/xhtmlxtras/css/popup.css create mode 100644 program/js/tiny_mce/plugins/xhtmlxtras/css/xhtmlxtras.css create mode 100644 program/js/tiny_mce/plugins/xhtmlxtras/del.htm create mode 100644 program/js/tiny_mce/plugins/xhtmlxtras/editor_plugin.js create mode 100644 program/js/tiny_mce/plugins/xhtmlxtras/editor_plugin_src.js create mode 100644 program/js/tiny_mce/plugins/xhtmlxtras/ins.htm create mode 100644 program/js/tiny_mce/plugins/xhtmlxtras/js/abbr.js create mode 100644 program/js/tiny_mce/plugins/xhtmlxtras/js/acronym.js create mode 100644 program/js/tiny_mce/plugins/xhtmlxtras/js/attributes.js create mode 100644 program/js/tiny_mce/plugins/xhtmlxtras/js/cite.js create mode 100644 program/js/tiny_mce/plugins/xhtmlxtras/js/del.js create mode 100644 program/js/tiny_mce/plugins/xhtmlxtras/js/element_common.js create mode 100644 program/js/tiny_mce/plugins/xhtmlxtras/js/ins.js create mode 100644 program/js/tiny_mce/plugins/xhtmlxtras/langs/en_dlg.js delete mode 100644 program/js/tiny_mce/themes/advanced/css/editor_content.css delete mode 100644 program/js/tiny_mce/themes/advanced/css/editor_popup.css delete mode 100644 program/js/tiny_mce/themes/advanced/docs/en/about.htm delete mode 100644 program/js/tiny_mce/themes/advanced/docs/en/common_buttons.htm delete mode 100644 program/js/tiny_mce/themes/advanced/docs/en/create_accessible_content.htm delete mode 100644 program/js/tiny_mce/themes/advanced/docs/en/images/insert_anchor_window.gif delete mode 100644 program/js/tiny_mce/themes/advanced/docs/en/images/insert_image_window.gif delete mode 100644 program/js/tiny_mce/themes/advanced/docs/en/images/insert_link_window.gif delete mode 100644 program/js/tiny_mce/themes/advanced/docs/en/images/insert_table_window.gif delete mode 100644 program/js/tiny_mce/themes/advanced/docs/en/index.htm delete mode 100644 program/js/tiny_mce/themes/advanced/docs/en/insert_anchor_button.htm delete mode 100644 program/js/tiny_mce/themes/advanced/docs/en/insert_image_button.htm delete mode 100644 program/js/tiny_mce/themes/advanced/docs/en/insert_link_button.htm delete mode 100644 program/js/tiny_mce/themes/advanced/docs/en/insert_table_button.htm delete mode 100644 program/js/tiny_mce/themes/advanced/docs/en/style.css delete mode 100644 program/js/tiny_mce/themes/advanced/images/anchor.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/backcolor.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/bold.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/bold_de_se.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/bold_es.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/bold_fr.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/bold_ru.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/bold_tw.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/browse.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/bullist.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/button_menu.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/buttons.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/cancel_button_bg.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/charmap.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/cleanup.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/close.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/code.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/color.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/copy.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/custom_1.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/cut.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/forecolor.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/help.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/hr.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/image.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/indent.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/insert_button_bg.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/italic.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/italic_de_se.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/italic_es.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/italic_ru.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/italic_tw.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/justifycenter.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/justifyfull.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/justifyleft.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/justifyright.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/link.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/menu_check.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/newdocument.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/numlist.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/opacity.png delete mode 100644 program/js/tiny_mce/themes/advanced/images/outdent.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/paste.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/redo.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/removeformat.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/separator.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/statusbar_resize.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/strikethrough.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/sub.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/sup.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/underline.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/underline_es.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/underline_fr.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/underline_ru.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/underline_tw.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/undo.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/unlink.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/visualaid.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/xp/tab_bg.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/xp/tab_end.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/xp/tab_sel_bg.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/xp/tab_sel_end.gif delete mode 100644 program/js/tiny_mce/themes/advanced/images/xp/tabs_bg.gif rename program/js/tiny_mce/themes/advanced/{images/colors.jpg => img/colorpicker.jpg} (100%) create mode 100644 program/js/tiny_mce/themes/advanced/img/icons.gif create mode 100644 program/js/tiny_mce/themes/advanced/js/about.js create mode 100644 program/js/tiny_mce/themes/advanced/js/anchor.js rename program/js/tiny_mce/themes/advanced/{jscripts => js}/charmap.js (90%) rename program/js/tiny_mce/themes/advanced/{jscripts => js}/color_picker.js (91%) create mode 100644 program/js/tiny_mce/themes/advanced/js/image.js create mode 100644 program/js/tiny_mce/themes/advanced/js/link.js rename program/js/tiny_mce/themes/advanced/{jscripts => js}/source_editor.js (51%) delete mode 100644 program/js/tiny_mce/themes/advanced/jscripts/about.js delete mode 100644 program/js/tiny_mce/themes/advanced/jscripts/anchor.js delete mode 100644 program/js/tiny_mce/themes/advanced/jscripts/image.js delete mode 100644 program/js/tiny_mce/themes/advanced/jscripts/link.js create mode 100644 program/js/tiny_mce/themes/advanced/langs/en_dlg.js create mode 100644 program/js/tiny_mce/themes/advanced/skins/default/content.css create mode 100644 program/js/tiny_mce/themes/advanced/skins/default/dialog.css create mode 100644 program/js/tiny_mce/themes/advanced/skins/default/img/buttons.png rename program/js/tiny_mce/themes/advanced/{images/anchor_symbol.gif => skins/default/img/items.gif} (100%) create mode 100644 program/js/tiny_mce/themes/advanced/skins/default/img/menu_arrow.gif create mode 100644 program/js/tiny_mce/themes/advanced/skins/default/img/menu_check.gif create mode 100644 program/js/tiny_mce/themes/advanced/skins/default/img/progress.gif create mode 100644 program/js/tiny_mce/themes/advanced/skins/default/img/tabs.gif create mode 100644 program/js/tiny_mce/themes/advanced/skins/default/ui.css create mode 100644 program/js/tiny_mce/themes/advanced/skins/o2k7/content.css create mode 100644 program/js/tiny_mce/themes/advanced/skins/o2k7/dialog.css create mode 100644 program/js/tiny_mce/themes/advanced/skins/o2k7/img/button_bg.png create mode 100644 program/js/tiny_mce/themes/advanced/skins/o2k7/img/button_bg_black.png create mode 100644 program/js/tiny_mce/themes/advanced/skins/o2k7/img/button_bg_silver.png create mode 100644 program/js/tiny_mce/themes/advanced/skins/o2k7/ui.css create mode 100644 program/js/tiny_mce/themes/advanced/skins/o2k7/ui_black.css create mode 100644 program/js/tiny_mce/themes/advanced/skins/o2k7/ui_silver.css create mode 100644 program/js/tiny_mce/themes/simple/editor_template.js create mode 100644 program/js/tiny_mce/themes/simple/editor_template_src.js create mode 100644 program/js/tiny_mce/themes/simple/img/icons.gif create mode 100644 program/js/tiny_mce/themes/simple/langs/en.js create mode 100644 program/js/tiny_mce/themes/simple/skins/default/content.css create mode 100644 program/js/tiny_mce/themes/simple/skins/default/ui.css create mode 100644 program/js/tiny_mce/themes/simple/skins/o2k7/content.css create mode 100644 program/js/tiny_mce/themes/simple/skins/o2k7/img/button_bg.png create mode 100644 program/js/tiny_mce/themes/simple/skins/o2k7/ui.css delete mode 100644 program/js/tiny_mce/utils/mclayer.js create mode 100644 program/lib/._enriched.inc create mode 100644 program/lib/._utf7.inc create mode 100644 program/lib/._washtml.php rename program/lib/{html2text.inc => html2text.php} (100%) delete mode 100644 program/lib/magic create mode 100644 program/lib/washtml.php rename program/localization/{ar => ar_SA}/labels.inc (79%) rename program/localization/{ar => ar_SA}/messages.inc (83%) rename program/localization/{bg => bg_BG}/labels.inc (100%) rename program/localization/{bg => bg_BG}/messages.inc (100%) rename program/localization/{ca => ca_ES}/labels.inc (76%) rename program/localization/{ca => ca_ES}/messages.inc (81%) rename program/localization/{cz => cs_CZ}/labels.inc (100%) rename program/localization/{cz => cs_CZ}/messages.inc (100%) rename program/localization/{da => da_DK}/labels.inc (100%) rename program/localization/{da => da_DK}/messages.inc (100%) rename program/localization/{el => el_GR}/labels.inc (100%) rename program/localization/{el => el_GR}/messages.inc (100%) rename program/localization/{es => es_ES}/labels.inc (75%) rename program/localization/{es => es_ES}/messages.inc (100%) rename program/localization/{eu => eu_ES}/labels.inc (100%) rename program/localization/{eu => eu_ES}/messages.inc (100%) rename program/localization/{fi => fi_FI}/labels.inc (74%) rename program/localization/{fi => fi_FI}/messages.inc (81%) rename program/localization/{fr => fr_FR}/labels.inc (100%) rename program/localization/{fr => fr_FR}/messages.inc (100%) rename program/localization/{gl => gl_ES}/labels.inc (100%) rename program/localization/{gl => gl_ES}/messages.inc (100%) rename program/localization/{he => he_IL}/labels.inc (65%) rename program/localization/{he => he_IL}/messages.inc (66%) rename program/localization/{hi => hi_IN}/labels.inc (100%) rename program/localization/{hi => hi_IN}/messages.inc (100%) rename program/localization/{hu => hu_HU}/labels.inc (100%) rename program/localization/{hu => hu_HU}/messages.inc (98%) rename program/localization/{am => hy_AM}/labels.inc (100%) rename program/localization/{am => hy_AM}/messages.inc (100%) rename program/localization/{is => is_IS}/labels.inc (100%) rename program/localization/{is => is_IS}/messages.inc (100%) rename program/localization/{it => it_IT}/labels.inc (100%) rename program/localization/{it => it_IT}/messages.inc (100%) rename program/localization/{ja => ja_JP}/labels.inc (89%) rename program/localization/{ja => ja_JP}/messages.inc (96%) rename program/localization/{ge => ka_GE}/labels.inc (100%) rename program/localization/{ge => ka_GE}/messages.inc (100%) rename program/localization/{kr => ko_KR}/labels.inc (100%) rename program/localization/{kr => ko_KR}/messages.inc (100%) rename program/localization/{lt => lt_LT}/labels.inc (77%) rename program/localization/{lt => lt_LT}/messages.inc (100%) rename program/localization/{lv => lv_LV}/labels.inc (100%) rename program/localization/{lv => lv_LV}/messages.inc (100%) rename program/localization/{mk => mk_MK}/labels.inc (100%) rename program/localization/{mk => mk_MK}/messages.inc (100%) rename program/localization/{ne => ne_NP}/labels.inc (100%) rename program/localization/{ne => ne_NP}/messages.inc (100%) rename program/localization/{pl => pl_PL}/labels.inc (82%) rename program/localization/{pl => pl_PL}/messages.inc (94%) rename program/localization/{ro => ro_RO}/labels.inc (100%) rename program/localization/{ro => ro_RO}/messages.inc (100%) rename program/localization/{ru => ru_RU}/labels.inc (83%) rename program/localization/{ru => ru_RU}/messages.inc (100%) rename program/localization/{si => si_LK}/labels.inc (100%) rename program/localization/{si => si_LK}/messages.inc (100%) delete mode 100644 program/localization/sk/messages.inc rename program/localization/{sk => sk_SK}/labels.inc (57%) create mode 100644 program/localization/sk_SK/messages.inc rename program/localization/{sl => sl_SI}/labels.inc (100%) rename program/localization/{sl => sl_SI}/messages.inc (100%) rename program/localization/{sr_cyrillic => sr_CS}/labels.inc (100%) rename program/localization/{sr_cyrillic => sr_CS}/messages.inc (100%) delete mode 100644 program/localization/sr_latin/labels.inc delete mode 100644 program/localization/sr_latin/messages.inc rename program/localization/{se => sv_SE}/labels.inc (99%) rename program/localization/{se => sv_SE}/messages.inc (100%) rename program/localization/{tr => tr_TR}/labels.inc (100%) rename program/localization/{tr => tr_TR}/messages.inc (100%) rename program/localization/{uk => uk_UA}/labels.inc (100%) rename program/localization/{uk => uk_UA}/messages.inc (100%) rename program/localization/{vn => vi_VN}/labels.inc (100%) rename program/localization/{vn => vi_VN}/messages.inc (100%) delete mode 100644 program/steps/mail/quotadisplay.inc delete mode 100644 skins/default/editor_ui.css diff --git a/._INSTALL b/._INSTALL new file mode 100644 index 0000000000000000000000000000000000000000..92935509f1cb5910532bff22645e7db17d206dc7 GIT binary patch literal 187 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDI}aVHRi_`89a2;dkJ62wqdp9EA2(lG;w zmC>{@BE&_L^K$Vqox1Ojhs@R)|o50+1L3ClDI}aT^eW_&b1@2;dkJ62wqdp8!+}(lG;w z6@VBSFakMHana=bT)o`H$Vqox1Ojhs@R)|o50+1L3ClDI}aT^eW_&b1@2;dkJ62wqdoexwB(lG;w z6@VBSFakMHana=bT)o`H tag filtering (#1484391) +- Fixed tag filtering (#1484403) +- Added sections (fieldset+label) in Settings interface +- Mark as read in one action with message preview (#1484972) +- Deleted redundant quota reads (#1484972) +- Added options for empty trash and expunge inbox on logout (#1483863) +- Removed lines wrapping when displaying message +- Fixed month localization +- Changed codebase to PHP5 with autoloader + +RELEASE 0.1.1 + - Clear selection when selecting single item (#1484942) - Remove hard-coded image size in skin templates (#1484893) - Database schema improvements (dropped unnecessary indexes) diff --git a/INSTALL b/INSTALL index 2b8fb2e..e2f9a4e 100644 --- a/INSTALL +++ b/INSTALL @@ -11,7 +11,7 @@ REQUIREMENTS * The Apache or Lighttpd Webserver * .htaccess support allowing overrides for DirectoryIndex -* PHP Version 4.3.1 or greater including +* PHP Version 5.2 or greater including - PCRE (perl compatible regular expression) - Libiconv - Multibyte String (mbstring) diff --git a/README b/README index 7aae054..e23c494 100644 --- a/README +++ b/README @@ -1,5 +1,5 @@ RoundCube Webmail (http://roundcube.net) - +================= Introduction: ------------- @@ -43,6 +43,9 @@ records. If you have 'auto_create_user' set to FALSE only IMAP logins which already have a corresponding entry in the user's table (username and hostname) will be allowed. +Read more at http://trac.roundcube.net/wiki/Howto_Config +and http://trac.roundcube.net/wiki/Dev_Docs + Contact: -------- diff --git a/SQL/mysql.initial.sql b/SQL/mysql.initial.sql index ae195e4..fadc072 100644 --- a/SQL/mysql.initial.sql +++ b/SQL/mysql.initial.sql @@ -50,12 +50,12 @@ CREATE TABLE `identities` ( `user_id` int(10) unsigned NOT NULL default '0', `del` tinyint(1) NOT NULL default '0', `standard` tinyint(1) NOT NULL default '0', - `name` varchar(128) NOT NULL default '', + `name` varchar(128) NOT NULL, `organization` varchar(128) NOT NULL default '', - `email` varchar(128) NOT NULL default '', + `email` varchar(128) NOT NULL, `reply-to` varchar(128) NOT NULL default '', `bcc` varchar(128) NOT NULL default '', - `signature` text NOT NULL, + `signature` text NOT NULL default '', `html_signature` tinyint(1) NOT NULL default '0', PRIMARY KEY (`identity_id`), KEY `user_id` (`user_id`) @@ -91,7 +91,9 @@ CREATE TABLE `users` ( `last_login` datetime NOT NULL default '0000-00-00 00:00:00', `language` varchar(5) NOT NULL default 'en', `preferences` text, - PRIMARY KEY (`user_id`) + PRIMARY KEY (`user_id`), + INDEX `username_index` (`username`), + INDEX `alias_index` (`alias`) ); -- -------------------------------------------------------- diff --git a/SQL/mysql.update.sql b/SQL/mysql.update.sql index 11e744c..2a9603f 100644 --- a/SQL/mysql.update.sql +++ b/SQL/mysql.update.sql @@ -5,7 +5,7 @@ TRUNCATE TABLE `messages`; ALTER TABLE `messages` DROP INDEX `idx`, - DROP INDEX `uid` + DROP INDEX `uid`; ALTER TABLE `cache` DROP INDEX `cache_key`, @@ -15,3 +15,13 @@ ALTER TABLE `cache` ALTER TABLE `users` ADD INDEX `username_index` (`username`), ADD INDEX `alias_index` (`alias`); + +-- Updates from version 0.1.1 + +ALTER TABLE `identities` + MODIFY `signature` text NOT NULL DEFAULT '', + MODIFY `bcc` varchar(128) NOT NULL DEFAULT '', + MODIFY `reply-to` varchar(128) NOT NULL DEFAULT '', + MODIFY `organization` varchar(128) NOT NULL DEFAULT '', + MODIFY `name` varchar(128) NOT NULL, + MODIFY `email` varchar(128) NOT NULL; diff --git a/SQL/mysql5.initial.sql b/SQL/mysql5.initial.sql index 881344b..546eecd 100644 --- a/SQL/mysql5.initial.sql +++ b/SQL/mysql5.initial.sql @@ -107,11 +107,11 @@ CREATE TABLE `identities` ( `del` tinyint(1) NOT NULL DEFAULT '0', `standard` tinyint(1) NOT NULL DEFAULT '0', `name` varchar(128) NOT NULL, - `organization` varchar(128) NOT NULL, + `organization` varchar(128) NOT NULL DEFAULT '', `email` varchar(128) NOT NULL, - `reply-to` varchar(128) NOT NULL, - `bcc` varchar(128) NOT NULL, - `signature` text NOT NULL, + `reply-to` varchar(128) NOT NULL DEFAULT '', + `bcc` varchar(128) NOT NULL DEFAULT '', + `signature` text NOT NULL DEFAULT '', `html_signature` tinyint(1) NOT NULL DEFAULT '0', `user_id` int(10) UNSIGNED NOT NULL DEFAULT '0', PRIMARY KEY(`identity_id`), diff --git a/SQL/postgres.initial.sql b/SQL/postgres.initial.sql index ff239cb..05c6192 100644 --- a/SQL/postgres.initial.sql +++ b/SQL/postgres.initial.sql @@ -25,7 +25,10 @@ CREATE TABLE users ( preferences text DEFAULT ''::text NOT NULL ); +CREATE INDEX users_username_id_idx ON users (username); +CREATE INDEX users_alias_id_idx ON users (alias); + -- -- Table "session" -- Name: session; Type: TABLE; Schema: public; Owner: postgres diff --git a/SQL/postgres.update.sql b/SQL/postgres.update.sql index ff1ce12..e0afa61 100644 --- a/SQL/postgres.update.sql +++ b/SQL/postgres.update.sql @@ -5,6 +5,9 @@ CREATE INDEX cache_user_id_idx ON cache (user_id, cache_key); CREATE INDEX contacts_user_id_idx ON contacts (user_id); CREATE INDEX identities_user_id_idx ON identities (user_id); +CREATE INDEX users_username_id_idx ON users (username); +CREATE INDEX users_alias_id_idx ON users (alias); + -- added ON DELETE/UPDATE actions ALTER TABLE messages DROP CONSTRAINT messages_user_id_fkey; ALTER TABLE messages ADD FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/SQL/sqlite.initial.sql b/SQL/sqlite.initial.sql index 041696b..6adcf4d 100644 --- a/SQL/sqlite.initial.sql +++ b/SQL/sqlite.initial.sql @@ -80,6 +80,9 @@ CREATE TABLE users ( preferences text NOT NULL default '' ); +CREATE INDEX ix_users_username ON users(username); +CREATE INDEX ix_users_alias ON users(alias); + -- -------------------------------------------------------- -- diff --git a/SQL/sqlite.update.sql b/SQL/sqlite.update.sql index f609a36..047fe67 100644 --- a/SQL/sqlite.update.sql +++ b/SQL/sqlite.update.sql @@ -22,3 +22,6 @@ CREATE TABLE messages ( ); CREATE INDEX ix_messages_user_cache_uid ON messages(user_id,cache_key,uid); + +CREATE INDEX ix_users_username ON users(username); +CREATE INDEX ix_users_alias ON users(alias); diff --git a/UPGRADING b/UPGRADING index 9b5ac45..996b4f2 100644 --- a/UPGRADING +++ b/UPGRADING @@ -1,9 +1,25 @@ UPDATE instructions =================== -Follow these instructions if upgrading from a previous version +First you should remove all subfolders from /program/localization/ +because most language codes have changed in 0.2-alpha. This way you +can make sure that no old localization files remain on your disk. + +Then follow these instructions if upgrading from a previous version of RoundCube Webmail. +from version 0.1.1 +---------------------------------------- +* replace index.php +* replace all files in folder /bin/ +* replace all files in folder /program/ +* replace all files in folder /skins/default/ +* run all commands in SQL/[yourdbtype].update.sql + below the line "-- Updates from version 0.1.1" +* check the config/main.inc.php.dist for new configuration + options and add them to your config + + from version 0.1-stable ---------------------------------------- * replace index.php @@ -11,6 +27,8 @@ from version 0.1-stable * replace all files in folder /program/ * replace all files in folder /skins/default/ * run all commands in SQL/[yourdbtype].update.sql +* check the config/main.inc.php.dist for new configuration options + and add them to your config from version 0.1-rc2 @@ -28,7 +46,6 @@ from version 0.1-rc1 * replace all files in folder /bin/ * replace all files in folder /program/ * replace all files in folder /skins/default/ -* run all commands in SQL/[yourdbtype].update.sql * If you have LDAP servers configured you should re-configure the config entries using the template given in /config/main.inc.php.dist @@ -39,7 +56,8 @@ from version 0.1-beta2 * replace all files in folder /bin/ * replace all files in folder /program/ * replace all files in folder /skins/default/ -* re-initalize the database with [yourdbtype].initial.sql +* run all commands in SQL/[yourdbtype].update.sql or + re-initalize the database with [yourdbtype].initial.sql * add these lines to /config/main.inc.php $rcmail_config['draft_autosave'] = 300; $rcmail_config['date_today'] = 'H:i'; @@ -53,7 +71,8 @@ form version 0.1-beta * replace all files in folder /bin/ * replace all files in folder /program/ * replace all files in folder /skins/default/ -* re-initalize the database with [yourdbtype].initial.sql +* run all commands in SQL/[yourdbtype].update.sql or + re-initalize the database with [yourdbtype].initial.sql * add this line to /config/db.inc.php $rcmail_config['db_persistent'] = false; * add these lines to /config/main.inc.php diff --git a/bin/html2text.php b/bin/html2text.php index 7f74ac6..0f0e6ae 100644 --- a/bin/html2text.php +++ b/bin/html2text.php @@ -1,21 +1,11 @@ get_text(); - -$phpver = explode('.', phpversion()); -$vernum = $phpver[0] . $phpver[1] . $phpver[2]; - -# html_entity_decode doesn't handle UTF character sets in PHP 4.x - -if (($vernum >= 500) && function_exists('html_entity_decode')) - print html_entity_decode($plaintext, ENT_COMPAT, 'UTF-8'); -else - print $plaintext; +print html_entity_decode($converter->get_text(), ENT_COMPAT, 'UTF-8'); ?> diff --git a/bin/modcss.php b/bin/modcss.php index e482389..e97b8ec 100644 --- a/bin/modcss.php +++ b/bin/modcss.php @@ -19,10 +19,8 @@ */ -$INSTALL_PATH = realpath("./../") . "/"; -ini_set('include_path', $INSTALL_PATH.PATH_SEPARATOR.$INSTALL_PATH.'program'.PATH_SEPARATOR.ini_get('include_path')); - -require 'include/main.inc'; +define('INSTALL_PATH', realpath('./../') . '/'); +require INSTALL_PATH.'program/include/iniset.php'; $source = ""; if ($url = preg_replace('/[^a-z0-9.-_\?\$&=%]/i', '', $_GET['u'])) diff --git a/bin/msgexport.sh b/bin/msgexport.sh new file mode 100755 index 0000000..890d48a --- /dev/null +++ b/bin/msgexport.sh @@ -0,0 +1,147 @@ +#!/usr/bin/php -qC +', $pos, $max)); +} + + +// get arguments +$args = get_opt(array('h' => 'host', 'u' => 'user', 'p' => 'pass', 'm' => 'mbox', 'f' => 'file')) + array('host' => 'localhost', 'mbox' => 'INBOX'); + +if ($_SERVER['argv'][1] == 'help') +{ + print_usage(); + exit; +} +else if (!$args['host']) +{ + vputs("Missing required parameters.\n"); + print_usage(); + exit; +} + +// prompt for username if not set +if (empty($args['user'])) +{ + vputs("IMAP user: "); + $args['user'] = trim(fgets(STDIN)); +} + +// prompt for password +vputs("Password: "); +$args['pass'] = trim(fgets(STDIN)); + + +// parse $host URL +$a_host = parse_url($args['host']); +if ($a_host['host']) +{ + $host = $a_host['host']; + $imap_ssl = (isset($a_host['scheme']) && in_array($a_host['scheme'], array('ssl','imaps','tls'))) ? TRUE : FALSE; + $imap_port = isset($a_host['port']) ? $a_host['port'] : ($imap_ssl ? 993 : 143); +} +else +{ + $host = $args['host']; + $imap_port = 143; +} + +// instantiate IMAP class +$IMAP = new rcube_imap(null); + +// try to connect to IMAP server +if ($IMAP->connect($host, $args['user'], $args['pass'], $imap_port, $imap_ssl)) +{ + vputs("IMAP login successful.\n"); + + $IMAP->set_mailbox($args['mbox']); + + vputs("Getting message list of {$args['mbox']}..."); + vputs($IMAP->messagecount()." messages\n"); + + if ($args['file']) + { + if (!($out = fopen($args['file'], 'w'))) + { + vputs("Cannot write to output file\n"); + exit; + } + } + else + $out = STDOUT; + + for ($count = $IMAP->messagecount(), $i=1; $i <= $count; $i++) + { + $headers = $IMAP->get_headers($i, null, false); + $from = current($IMAP->decode_address_list($headers->from, 1, false)); + + fwrite($out, sprintf("From %s %s UID %d\n", $from['mailto'], $headers->date, $headers->uid)); + fwrite($out, iil_C_FetchPartHeader($IMAP->conn, $IMAP->mailbox, $i, null)); + fwrite($out, iil_C_HandlePartBody($IMAP->conn, $IMAP->mailbox, $i, null, 1)); + fwrite($out, "\n\n\n"); + + progress_update($i, $count); + } + vputs("\ncomplete.\n"); +} +else +{ + vputs("IMAP login failed.\n"); +} + +?> \ No newline at end of file diff --git a/bin/msgimport b/bin/msgimport.sh similarity index 88% rename from bin/msgimport rename to bin/msgimport.sh index 0ed268f..98a0389 100755 --- a/bin/msgimport +++ b/bin/msgimport.sh @@ -1,13 +1,10 @@ #!/usr/bin/php -qC 'domain' values to support multiple hosts @@ -118,7 +122,7 @@ $rcmail_config['double_auth'] = false; $rcmail_config['des_key'] = 'rcmail-!24ByteDESkey*Str'; // the default locale setting -$rcmail_config['locale_string'] = 'en'; +$rcmail_config['language'] = 'en'; // use this format for short date display $rcmail_config['date_short'] = 'D H:i'; @@ -130,7 +134,7 @@ $rcmail_config['date_long'] = 'd.m.Y H:i'; $rcmail_config['date_today'] = 'H:i'; // add this user-agent to message headers when sending -$rcmail_config['useragent'] = 'RoundCube Webmail/0.1'; +$rcmail_config['useragent'] = 'RoundCube Webmail/0.2a'; // use this name to compose page titles $rcmail_config['product_name'] = 'RoundCube Webmail'; @@ -213,9 +217,29 @@ $rcmail_config['mail_header_delimiter'] = NULL; // session domain: .example.org $rcmail_config['session_domain'] = ''; -// in order to enable public ldap search, create a config array -// like the Verisign example below. if you would like to test, -// simply uncomment the Verisign example. +// This indicates which type of address book to use. Possible choises: +// 'sql' (default) and 'ldap'. +// If set to 'ldap' then it will look at using the first writable LDAP +// address book as the primary address book and it will not display the +// SQL address book in the 'Address Book' view. +$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. +// +// 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. +// +// The recommended directory structure for LDAP is to store all the address book entries +// under the users main entry, e.g.: +// +// o=root +// ou=people +// uid=user@domain +// mail=contact@contactdomain +// +// So the base_dn would be uid=%fu,ou=people,o=root +// The bind_dn would be the same as based_dn or some super user login. /** * example config for Verisign directory * @@ -223,34 +247,57 @@ $rcmail_config['session_domain'] = ''; * 'name' => 'Verisign.com', * 'hosts' => array('directory.verisign.com'), * 'port' => 389, + * 'use_tls' => false, + * '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. + * // %u - The username prior to the '@'. + * // %d - The domain name after the '@'. * 'base_dn' => '', * 'bind_dn' => '', * 'bind_pass' => '', + * 'writable' => 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 + * '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 + * 'global_search' => true, // perform a global search for address auto-completion on compose * 'fuzzy_search' => true); // server allows wildcard search */ // don't allow these settings to be overriden by the user $rcmail_config['dont_override'] = array(); -// list of configuration option names that need to be available in Javascript. -$rcmail_config['javascript_config'] = array('read_when_deleted', 'flag_for_deletion'); - // try to load host-specific configuration +// see http://trac.roundcube.net/wiki/Howto_Config for more details $rcmail_config['include_host_config'] = false; +// don't let users set pagesize to more than this value if set +$rcmail_config['max_pagesize'] = 200; + +// mime magic database +$rcmail_config['mime_magic'] = '/usr/share/misc/magic'; + +// default sort col +$rcmail_config['message_sort_col'] = 'date'; + +// default sort order +$rcmail_config['message_sort_order'] = 'DESC'; + // THIS OPTION WILL ALLOW THE INSTALLER TO RUN AND CAN EXPOSE SENSITIVE CONFIG DATA. // ONLY ENABLE IT IF YOU'RE REALLY SURE WHAT YOU'RE DOING! $rcmail_config['enable_installer'] = false; - /***** these settings can be overwritten by user's preferences *****/ // show up to X items in list view @@ -271,23 +318,32 @@ $rcmail_config['htmleditor'] = FALSE; // show pretty dates as standard $rcmail_config['prettydate'] = TRUE; -// default sort col -$rcmail_config['message_sort_col'] = 'date'; - -// default sort order -$rcmail_config['message_sort_order'] = 'DESC'; - // save compose message every 300 seconds (5min) $rcmail_config['draft_autosave'] = 300; // default setting if preview pane is enabled $rcmail_config['preview_pane'] = FALSE; -// don't let users set pagesize to more than this value if set -$rcmail_config['max_pagesize'] = 200; +// Clear Trash on logout +$rcmail_config['logout_purge'] = FALSE; -// mime magic database -$rcmail_config['mime_magic'] = '/usr/share/misc/magic'; +// Compact INBOX on logout +$rcmail_config['logout_expunge'] = FALSE; + +/** + * 'Delete always' + * This setting reflects if mail should be always marked as deleted, + * even if moving to "Trash" fails. This is necessary in some setups + * because a) people may not have a Trash folder or b) they are over + * quota (and Trash is included in the quota). + * + * This is a failover setting for iil_C_Move when a message is moved + * to the Trash, and not the same as "delete_right_away". + */ +$rcmail_config['delete_always'] = false; + +// Log successful logins +$rcmail_config['log_logins'] = false; // end of config file ?> diff --git a/index.php b/index.php index 02a6201..f40f701 100644 --- a/index.php +++ b/index.php @@ -1,142 +1,61 @@ | - +-----------------------------------------------------------------------+ - - $Id: index.php 1255 2008-04-05 12:49:21Z thomasb $ + +-------------------------------------------------------------------------+ + | RoundCube Webmail IMAP Client | + | Version 0.2-alpha | + | | + | Copyright (C) 2005-2008, RoundCube Dev. - Switzerland | + | | + | This program is free software; you can redistribute it and/or modify | + | it under the terms of the GNU General Public License version 2 | + | as published by the Free Software Foundation. | + | | + | This program is distributed in the hope that it will be useful, | + | but WITHOUT ANY WARRANTY; without even the implied warranty of | + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | + | GNU General Public License for more details. | + | | + | You should have received a copy of the GNU General Public License along | + | with this program; if not, write to the Free Software Foundation, Inc., | + | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | + | | + +-------------------------------------------------------------------------+ + | Author: Thomas Bruederli | + +-------------------------------------------------------------------------+ + + $Id: index.php 1499 2008-06-09 20:57:53Z thomasb $ */ -// application constants -define('RCMAIL_VERSION', '0.1.1'); -define('RCMAIL_CHARSET', 'UTF-8'); -define('JS_OBJECT_NAME', 'rcmail'); +// include environment +require_once 'program/include/iniset.php'; // define global vars $OUTPUT_TYPE = 'html'; -$INSTALL_PATH = dirname(__FILE__); -$MAIN_TASKS = array('mail','settings','addressbook','logout'); - -if (empty($INSTALL_PATH)) - $INSTALL_PATH = './'; -else - $INSTALL_PATH .= '/'; - - -// make sure path_separator is defined -if (!defined('PATH_SEPARATOR')) - define('PATH_SEPARATOR', (eregi('win', PHP_OS) ? ';' : ':')); - - -// RC include folders MUST be included FIRST to avoid other -// possible not compatible libraries (i.e PEAR) to be included -// instead the ones provided by RC -ini_set('include_path', $INSTALL_PATH.PATH_SEPARATOR.$INSTALL_PATH.'program'.PATH_SEPARATOR.$INSTALL_PATH.'program/lib'.PATH_SEPARATOR.ini_get('include_path')); - -ini_set('session.name', 'roundcube_sessid'); -ini_set('session.use_cookies', 1); -ini_set('session.gc_maxlifetime', 21600); -ini_set('session.gc_divisor', 500); -ini_set('error_reporting', E_ALL&~E_NOTICE); -set_magic_quotes_runtime(0); - -// increase maximum execution time for php scripts -// (does not work in safe mode) -if (!ini_get('safe_mode')) @set_time_limit(120); - -// include base files -require_once('include/rcube_shared.inc'); -require_once('include/rcube_imap.inc'); -require_once('include/bugs.inc'); -require_once('include/main.inc'); -require_once('PEAR.php'); - - -// set PEAR error handling -// PEAR::setErrorHandling(PEAR_ERROR_TRIGGER, E_USER_NOTICE); - - -// catch some url/post parameters -$_task = strip_quotes(get_input_value('_task', RCUBE_INPUT_GPC)); -$_action = strip_quotes(get_input_value('_action', RCUBE_INPUT_GPC)); -$_framed = (!empty($_GET['_framed']) || !empty($_POST['_framed'])); - -// use main task if empty or invalid value -if (empty($_task) || !in_array($_task, $MAIN_TASKS)) - $_task = 'mail'; - // set output buffering -if ($_action != 'get' && $_action != 'viewsource') -{ +if ($RCMAIL->action != 'get' && $RCMAIL->action != 'viewsource') { // use gzip compression if supported if (function_exists('ob_gzhandler') - && !ini_get('zlib.output_compression') - && ini_get('output_handler') != 'ob_gzhandler') - { + && !ini_get('zlib.output_compression') + && ini_get('output_handler') != 'ob_gzhandler') { ob_start('ob_gzhandler'); } - else + else { ob_start(); + } } -// start session with requested task -rcmail_startup($_task); +// init application and start session with requested task +$RCMAIL = rcmail::get_instance(); -// set session related variables -$COMM_PATH = sprintf('./?_task=%s', $_task); -$SESS_HIDDEN_FIELD = ''; - - -// add framed parameter -if ($_framed) -{ - $COMM_PATH .= '&_framed=1'; - $SESS_HIDDEN_FIELD .= "\n".''; -} - - -// init necessary objects for GUI -rcmail_load_gui(); +// init output class +$OUTPUT = (!empty($_GET['_remote']) || !empty($_POST['_remote'])) ? $RCMAIL->init_json() : $RCMAIL->load_gui((!empty($_GET['_framed']) || !empty($_POST['_framed']))); // check DB connections and exit on failure -if ($err_str = $DB->is_error()) -{ +if ($err_str = $DB->is_error()) { raise_error(array( 'code' => 603, 'type' => 'db', @@ -145,116 +64,102 @@ if ($err_str = $DB->is_error()) // error steps -if ($_action=='error' && !empty($_GET['_code'])) +if ($RCMAIL->action=='error' && !empty($_GET['_code'])) { raise_error(array('code' => hexdec($_GET['_code'])), FALSE, TRUE); - +} // try to log in -if ($_action=='login' && $_task=='mail') -{ - $host = rcmail_autoselect_host(); +if ($RCMAIL->action=='login' && $RCMAIL->task=='mail') { + $host = $RCMAIL->autoselect_host(); // check if client supports cookies - if (empty($_COOKIE)) - { + if (empty($_COOKIE)) { $OUTPUT->show_message("cookiesdisabled", 'warning'); } else if ($_SESSION['temp'] && !empty($_POST['_user']) && isset($_POST['_pass']) && - rcmail_login(trim(get_input_value('_user', RCUBE_INPUT_POST), ' '), - get_input_value('_pass', RCUBE_INPUT_POST, true, 'ISO-8859-1'), $host)) - { + $RCMAIL->login(trim(get_input_value('_user', RCUBE_INPUT_POST), ' '), + get_input_value('_pass', RCUBE_INPUT_POST, true, 'ISO-8859-1'), $host)) { // create new session ID unset($_SESSION['temp']); sess_regenerate_id(); // send auth cookie if necessary - rcmail_authenticate_session(); + $RCMAIL->authenticate_session(); + + // log successful login + if ($RCMAIL->config->get('log_logins') && $RCMAIL->config->get('debug_level') & 1) + console(sprintf('Successful login for %s (id %d) from %s', + trim(get_input_value('_user', RCUBE_INPUT_POST), ' '), + $_SESSION['user_id'], + $_SERVER['REMOTE_ADDR'])); // send redirect - header("Location: $COMM_PATH"); + header("Location: {$RCMAIL->comm_path}"); exit; } - else - { + else { $OUTPUT->show_message($IMAP->error_code == -1 ? 'imaperror' : 'loginfailed', 'warning'); - rcmail_kill_session(); + $RCMAIL->kill_session(); } } // end session -else if (($_task=='logout' || $_action=='logout') && isset($_SESSION['user_id'])) -{ +else if (($RCMAIL->task=='logout' || $RCMAIL->action=='logout') && isset($_SESSION['user_id'])) { $OUTPUT->show_message('loggedout'); - rcmail_kill_session(); + $RCMAIL->logout_actions(); + $RCMAIL->kill_session(); } // check session and auth cookie -else if ($_action != 'login' && $_SESSION['user_id'] && $_action != 'send') -{ - if (!rcmail_authenticate_session()) - { +else if ($RCMAIL->action != 'login' && $_SESSION['user_id'] && $RCMAIL->action != 'send') { + if (!$RCMAIL->authenticate_session()) { $OUTPUT->show_message('sessionerror', 'error'); - rcmail_kill_session(); + $RCMAIL->kill_session(); } } // log in to imap server -if (!empty($USER->ID) && $_task=='mail') -{ - $conn = $IMAP->connect($_SESSION['imap_host'], $_SESSION['username'], decrypt_passwd($_SESSION['password']), $_SESSION['imap_port'], $_SESSION['imap_ssl']); - if (!$conn) - { - $OUTPUT->show_message($IMAP->error_code == -1 ? 'imaperror' : 'sessionerror', 'error'); - rcmail_kill_session(); +if (!empty($RCMAIL->user->ID) && $RCMAIL->task == 'mail') { + if (!$RCMAIL->imap_connect()) { + $RCMAIL->kill_session(); } - else - rcmail_set_imap_prop(); } // not logged in -> set task to 'login -if (empty($USER->ID)) -{ +if (empty($RCMAIL->user->ID)) { if ($OUTPUT->ajax_call) $OUTPUT->remote_response("setTimeout(\"location.href='\"+this.env.comm_path+\"'\", 2000);"); - $_task = 'login'; + $RCMAIL->set_task('login'); } // check client X-header to verify request origin -if ($OUTPUT->ajax_call) -{ - if (empty($CONFIG['devel_mode']) && !rc_request_header('X-RoundCube-Referer')) - { +if ($OUTPUT->ajax_call) { + if (empty($CONFIG['devel_mode']) && !rc_request_header('X-RoundCube-Referer')) { header('HTTP/1.1 404 Not Found'); die("Invalid Request"); } } -// set task and action to client -$OUTPUT->set_env('task', $_task); -if (!empty($_action)) - $OUTPUT->set_env('action', $_action); - - - // not logged in -> show login page -if (empty($USER->ID)) -{ +if (empty($RCMAIL->user->ID)) { // check if installer is still active - if ($CONFIG['enable_installer'] && is_readable('./installer/index.php')) - $OUTPUT->add_footer(' -
-

Installer script is still accessible

-

The install script of your RoundCube installation is still stored in its default location!

-

Please remove the whole installer folder from the RoundCube directory because - these files may expose sensitive configuration data like server passwords and encryption keys - to the public. Make sure you cannot access the installer script from your browser.

-
'); + if ($CONFIG['enable_installer'] && is_readable('./installer/index.php')) { + $OUTPUT->add_footer(html::div(array('style' => "background:#ef9398; border:2px solid #dc5757; padding:0.5em; margin:2em auto; width:50em"), + html::tag('h2', array('style' => "margin-top:0.2em"), "Installer script is still accessible") . + html::p(null, "The install script of your RoundCube installation is still stored in its default location!") . + html::p(null, "Please remove the whole installer folder from the RoundCube directory because . + these files may expose sensitive configuration data like server passwords and encryption keys + to the public. Make sure you cannot access the installer script from your browser.") + ) + ); + } + $OUTPUT->set_env('task', 'login'); $OUTPUT->task = 'login'; $OUTPUT->send('login'); exit; @@ -262,138 +167,129 @@ if (empty($USER->ID)) // handle keep-alive signal -if ($_action=='keep-alive') -{ +if ($RCMAIL->action=='keep-alive') { $OUTPUT->reset(); $OUTPUT->send(''); exit; } // include task specific files -if ($_task=='mail') -{ +if ($RCMAIL->task=='mail') { include_once('program/steps/mail/func.inc'); - if ($_action=='show' || $_action=='preview' || $_action=='print') + if ($RCMAIL->action=='show' || $RCMAIL->action=='preview' || $RCMAIL->action=='print') include('program/steps/mail/show.inc'); - if ($_action=='get') + if ($RCMAIL->action=='get') include('program/steps/mail/get.inc'); - if ($_action=='moveto' || $_action=='delete') + if ($RCMAIL->action=='moveto' || $RCMAIL->action=='delete') include('program/steps/mail/move_del.inc'); - if ($_action=='mark') + if ($RCMAIL->action=='mark') include('program/steps/mail/mark.inc'); - if ($_action=='viewsource') + if ($RCMAIL->action=='viewsource') include('program/steps/mail/viewsource.inc'); - if ($_action=='sendmdn') + if ($RCMAIL->action=='sendmdn') include('program/steps/mail/sendmdn.inc'); - if ($_action=='send') + if ($RCMAIL->action=='send') include('program/steps/mail/sendmail.inc'); - if ($_action=='upload') + if ($RCMAIL->action=='upload') include('program/steps/mail/upload.inc'); - if ($_action=='compose' || $_action=='remove-attachment' || $_action=='display-attachment') + if ($RCMAIL->action=='compose' || $RCMAIL->action=='remove-attachment' || $RCMAIL->action=='display-attachment') include('program/steps/mail/compose.inc'); - if ($_action=='addcontact') + if ($RCMAIL->action=='addcontact') include('program/steps/mail/addcontact.inc'); - if ($_action=='expunge' || $_action=='purge') + if ($RCMAIL->action=='expunge' || $RCMAIL->action=='purge') include('program/steps/mail/folders.inc'); - if ($_action=='check-recent') + if ($RCMAIL->action=='check-recent') include('program/steps/mail/check_recent.inc'); - if ($_action=='getunread') + if ($RCMAIL->action=='getunread') include('program/steps/mail/getunread.inc'); - if ($_action=='list' && isset($_REQUEST['_remote'])) + if ($RCMAIL->action=='list' && isset($_REQUEST['_remote'])) include('program/steps/mail/list.inc'); - if ($_action=='search') + if ($RCMAIL->action=='search') include('program/steps/mail/search.inc'); - if ($_action=='spell') + if ($RCMAIL->action=='spell') include('program/steps/mail/spell.inc'); - if ($_action=='rss') + if ($RCMAIL->action=='rss') include('program/steps/mail/rss.inc'); - if ($_action=='quotadisplay') - include('program/steps/mail/quotadisplay.inc'); - - // make sure the message count is refreshed - $IMAP->messagecount($_SESSION['mbox'], 'ALL', TRUE); + $IMAP->messagecount($_SESSION['mbox'], 'ALL', true); } // include task specific files -if ($_task=='addressbook') -{ +if ($RCMAIL->task=='addressbook') { include_once('program/steps/addressbook/func.inc'); - if ($_action=='save') + if ($RCMAIL->action=='save') include('program/steps/addressbook/save.inc'); - if ($_action=='edit' || $_action=='add') + if ($RCMAIL->action=='edit' || $RCMAIL->action=='add') include('program/steps/addressbook/edit.inc'); - if ($_action=='delete') + if ($RCMAIL->action=='delete') include('program/steps/addressbook/delete.inc'); - if ($_action=='show') + if ($RCMAIL->action=='show') include('program/steps/addressbook/show.inc'); - if ($_action=='list' && $_REQUEST['_remote']) + if ($RCMAIL->action=='list' && $_REQUEST['_remote']) include('program/steps/addressbook/list.inc'); - if ($_action=='search') + if ($RCMAIL->action=='search') include('program/steps/addressbook/search.inc'); - if ($_action=='copy') + if ($RCMAIL->action=='copy') include('program/steps/addressbook/copy.inc'); - if ($_action=='mailto') + if ($RCMAIL->action=='mailto') include('program/steps/addressbook/mailto.inc'); } // include task specific files -if ($_task=='settings') -{ +if ($RCMAIL->task=='settings') { include_once('program/steps/settings/func.inc'); - if ($_action=='save-identity') + if ($RCMAIL->action=='save-identity') include('program/steps/settings/save_identity.inc'); - if ($_action=='add-identity' || $_action=='edit-identity') + if ($RCMAIL->action=='add-identity' || $RCMAIL->action=='edit-identity') include('program/steps/settings/edit_identity.inc'); - if ($_action=='delete-identity') + if ($RCMAIL->action=='delete-identity') include('program/steps/settings/delete_identity.inc'); - if ($_action=='identities') + if ($RCMAIL->action=='identities') include('program/steps/settings/identities.inc'); - if ($_action=='save-prefs') + if ($RCMAIL->action=='save-prefs') include('program/steps/settings/save_prefs.inc'); - if ($_action=='folders' || $_action=='subscribe' || $_action=='unsubscribe' || - $_action=='create-folder' || $_action=='rename-folder' || $_action=='delete-folder') + if ($RCMAIL->action=='folders' || $RCMAIL->action=='subscribe' || $RCMAIL->action=='unsubscribe' || + $RCMAIL->action=='create-folder' || $RCMAIL->action=='rename-folder' || $RCMAIL->action=='delete-folder') include('program/steps/settings/manage_folders.inc'); - } // parse main template -$OUTPUT->send($_task); +$OUTPUT->send($RCMAIL->task); // if we arrive here, something went wrong @@ -402,6 +298,6 @@ raise_error(array( 'type' => 'php', 'line' => __LINE__, 'file' => __FILE__, - 'message' => "Invalid request"), TRUE, TRUE); + 'message' => "Invalid request"), true, true); ?> diff --git a/installer/._config.php b/installer/._config.php new file mode 100644 index 0000000000000000000000000000000000000000..4ee59dc8f5ca0f1eeda1ea3e9cf4a8482b3f0e5e GIT binary patch literal 187 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDI}aVHRi_`89a2;dkJ62wqd;|){_(lG;w zmC>{@BE&_L^K 'pcre', 'Session' => 'session'); +$required_php_exts = array('PCRE' => 'pcre', 'Session' => 'session', + 'DOM XML' => 'dom'); $optional_php_exts = array('FileInfo' => 'fileinfo', 'Libiconv' => 'iconv', - 'Multibyte' => 'mbstring', 'OpenSSL' => 'openssl', 'Mcrypt' => 'mcrypt', 'GD' => 'gd'); + 'Multibyte' => 'mbstring', 'OpenSSL' => 'openssl', 'Mcrypt' => 'mcrypt', + 'GD' => 'gd'); $required_libs = array('PEAR' => 'PEAR.php', 'DB' => 'DB.php', 'MDB2' => 'MDB2.php', - 'Net_SMTP' => 'Net/SMTP.php', 'Mail_mime' => 'Mail/mime.php', 'iilConnection' => 'lib/imap.inc'); + 'Net_SMTP' => 'Net/SMTP.php', 'Mail_mime' => 'Mail/mime.php', + 'iilConnection' => 'lib/imap.inc'); $supported_dbs = array('MySQL' => 'mysql', 'MySQLi' => 'mysqli', 'PostgreSQL' => 'pgsql', 'SQLite (v2)' => 'sqlite'); @@ -37,11 +40,10 @@ echo ' load_defaults(); @@ -25,16 +22,16 @@ $_SESSION['allowinstaller'] = true; if (!empty($_POST['submit'])) { - echo '

Copy the following configurations and save them in two files (names above the text box)'; - echo ' within the config/ directory of your RoundCube installation.
'; + echo '

Copy or download the following configurations and save them in two files'; + echo ' (names above the text box) within the config/ directory of your RoundCube installation.
'; echo ' Make sure that there are no characters outside the <?php ?> brackets when saving the files.

'; - $textbox = new textarea(array('rows' => 16, 'cols' => 60, 'class' => "configfile")); + $textbox = new html_textarea(array('rows' => 16, 'cols' => 60, 'class' => "configfile")); - echo '
main.inc.php
'; + echo '
main.inc.php (download)
'; echo $textbox->show($RCI->create_config('main')); - echo '
db.inc.php
'; + echo '
db.inc.php (download)
'; echo $textbox->show($RCI->create_config('db')); echo '

Of course there are more options to configure. @@ -56,7 +53,7 @@ if (!empty($_POST['submit'])) { getprop('debug_level'); -$check_debug = new checkbox(array('name' => '_debug_level[]')); +$check_debug = new html_checkbox(array('name' => '_debug_level[]')); echo $check_debug->show(($value & 1) ? 1 : 0 , array('value' => 1, 'id' => 'cfgdebug1')); echo '
'; @@ -74,7 +71,7 @@ echo '
';

'_product_name', 'size' => 30, 'id' => "cfgprodname")); +$input_prodname = new html_inputfield(array('name' => '_product_name', 'size' => 30, 'id' => "cfgprodname")); echo $input_prodname->show($RCI->getprop('product_name')); ?> @@ -85,7 +82,7 @@ echo $input_prodname->show($RCI->getprop('product_name'));
'_skin_path', 'size' => 30, 'id' => "cfgskinpath")); +$input_skinpath = new html_inputfield(array('name' => '_skin_path', 'size' => 30, 'id' => "cfgskinpath")); echo $input_skinpath->show($RCI->getprop('skin_path')); ?> @@ -96,7 +93,7 @@ echo $input_skinpath->show($RCI->getprop('skin_path'));
'_temp_dir', 'size' => 30, 'id' => "cfgtempdir")); +$input_tempdir = new html_inputfield(array('name' => '_temp_dir', 'size' => 30, 'id' => "cfgtempdir")); echo $input_tempdir->show($RCI->getprop('temp_dir')); ?> @@ -107,7 +104,7 @@ echo $input_tempdir->show($RCI->getprop('temp_dir'));
'_log_dir', 'size' => 30, 'id' => "cfglogdir")); +$input_logdir = new html_inputfield(array('name' => '_log_dir', 'size' => 30, 'id' => "cfglogdir")); echo $input_logdir->show($RCI->getprop('log_dir')); ?> @@ -118,7 +115,7 @@ echo $input_logdir->show($RCI->getprop('log_dir'));
'_ip_check', 'id' => "cfgipcheck")); +$check_ipcheck = new html_checkbox(array('name' => '_ip_check', 'id' => "cfgipcheck")); echo $check_ipcheck->show(intval($RCI->getprop('ip_check')), array('value' => 1)); ?> @@ -131,7 +128,7 @@ echo $check_ipcheck->show(intval($RCI->getprop('ip_check')), array('value' => 1)
'_des_key', 'size' => 30, 'id' => "cfgdeskey")); +$input_deskey = new html_inputfield(array('name' => '_des_key', 'size' => 30, 'id' => "cfgdeskey")); echo $input_deskey->show($RCI->getprop('des_key')); ?> @@ -144,7 +141,7 @@ If you enter it manually please provide a string of exactly 24 chars.

'_enable_caching', 'id' => "cfgcache")); +$check_caching = new html_checkbox(array('name' => '_enable_caching', 'id' => "cfgcache")); echo $check_caching->show(intval($RCI->getprop('enable_caching')), array('value' => 1)); ?> @@ -155,7 +152,7 @@ echo $check_caching->show(intval($RCI->getprop('enable_caching')), array('value'
'_enable_spellcheck', 'id' => "cfgspellcheck")); +$check_caching = new html_checkbox(array('name' => '_enable_spellcheck', 'id' => "cfgspellcheck")); echo $check_caching->show(intval($RCI->getprop('enable_spellcheck')), array('value' => 1)); ?> @@ -168,7 +165,7 @@ echo $check_caching->show(intval($RCI->getprop('enable_spellcheck')), array('val
'_mdn_requests', 'id' => "cfgmdnreq")); +$select_mdnreq = new html_select(array('name' => '_mdn_requests', 'id' => "cfgmdnreq")); $select_mdnreq->add(array('ask the user', 'send automatically', 'ignore'), array(0, 1, 2)); echo $select_mdnreq->show(intval($RCI->getprop('mdn_requests'))); @@ -187,24 +184,24 @@ echo $select_mdnreq->show(intval($RCI->getprop('mdn_requests')));

Database settings for read/write operations:

'mysql', 'MySQLi' => 'mysqli', 'PgSQL' => 'pgsql', 'SQLite' => 'sqlite'); -$select_dbtype = new select(array('name' => '_dbtype', 'id' => "cfgdbtype")); +$select_dbtype = new html_select(array('name' => '_dbtype', 'id' => "cfgdbtype")); foreach ($supported_dbs AS $database => $ext) { if (extension_loaded($ext)) { $select_dbtype->add($database, $ext); } } -$input_dbhost = new textfield(array('name' => '_dbhost', 'size' => 20, 'id' => "cfgdbhost")); -$input_dbname = new textfield(array('name' => '_dbname', 'size' => 20, 'id' => "cfgdbname")); -$input_dbuser = new textfield(array('name' => '_dbuser', 'size' => 20, 'id' => "cfgdbuser")); -$input_dbpass = new textfield(array('name' => '_dbpass', 'size' => 20, 'id' => "cfgdbpass")); +$input_dbhost = new html_inputfield(array('name' => '_dbhost', 'size' => 20, 'id' => "cfgdbhost")); +$input_dbname = new html_inputfield(array('name' => '_dbname', 'size' => 20, 'id' => "cfgdbname")); +$input_dbuser = new html_inputfield(array('name' => '_dbuser', 'size' => 20, 'id' => "cfgdbuser")); +$input_dbpass = new html_passwordfield(array('name' => '_dbpass', 'size' => 20, 'id' => "cfgdbpass")); -$dsnw = DB::parseDSN($RCI->getprop('db_dsnw')); +$dsnw = MDB2::parseDSN($RCI->getprop('db_dsnw')); echo $select_dbtype->show($RCI->is_post ? $_POST['_dbtype'] : $dsnw['phptype']); echo '
'; @@ -228,7 +225,7 @@ echo '
'; @include_once 'DB.php'; @include_once 'MDB2.php'; -$select_dbba = new select(array('name' => '_db_backend', 'id' => "cfgdbba")); +$select_dbba = new html_select(array('name' => '_db_backend', 'id' => "cfgdbba")); if (class_exists('DB')) $select_dbba->add('DB', 'db'); @@ -254,7 +251,7 @@ echo $select_dbba->show($RCI->getprop('db_backend'));
'_default_host[]', 'size' => 30)); +$text_imaphost = new html_inputfield(array('name' => '_default_host[]', 'size' => 30)); $default_hosts = $RCI->get_hostlist(); if (empty($default_hosts)) @@ -279,7 +276,7 @@ foreach ($default_hosts as $host) {
'_default_port', 'size' => 6, 'id' => "cfgimapport")); +$text_imapport = new html_inputfield(array('name' => '_default_port', 'size' => 6, 'id' => "cfgimapport")); echo $text_imapport->show($RCI->getprop('default_port')); ?> @@ -290,7 +287,7 @@ echo $text_imapport->show($RCI->getprop('default_port'));
'_username_domain', 'size' => 30, 'id' => "cfguserdomain")); +$text_userdomain = new html_inputfield(array('name' => '_username_domain', 'size' => 30, 'id' => "cfguserdomain")); echo $text_userdomain->show($RCI->getprop('username_domain')); ?> @@ -303,7 +300,7 @@ echo $text_userdomain->show($RCI->getprop('username_domain'));
'_auto_create_user', 'id' => "cfgautocreate")); +$check_autocreate = new html_checkbox(array('name' => '_auto_create_user', 'id' => "cfgautocreate")); echo $check_autocreate->show(intval($RCI->getprop('auto_create_user')), array('value' => 1)); ?> @@ -320,7 +317,7 @@ what means that you have to create those records manually or disable this option
'_sent_mbox', 'size' => 20, 'id' => "cfgsentmbox")); +$text_sentmbox = new html_inputfield(array('name' => '_sent_mbox', 'size' => 20, 'id' => "cfgsentmbox")); echo $text_sentmbox->show($RCI->getprop('sent_mbox')); ?> @@ -333,7 +330,7 @@ echo $text_sentmbox->show($RCI->getprop('sent_mbox'));
'_trash_mbox', 'size' => 20, 'id' => "cfgtrashmbox")); +$text_trashmbox = new html_inputfield(array('name' => '_trash_mbox', 'size' => 20, 'id' => "cfgtrashmbox")); echo $text_trashmbox->show($RCI->getprop('trash_mbox')); ?> @@ -346,7 +343,7 @@ echo $text_trashmbox->show($RCI->getprop('trash_mbox'));
'_drafts_mbox', 'size' => 20, 'id' => "cfgdraftsmbox")); +$text_draftsmbox = new html_inputfield(array('name' => '_drafts_mbox', 'size' => 20, 'id' => "cfgdraftsmbox")); echo $text_draftsmbox->show($RCI->getprop('drafts_mbox')); ?> @@ -364,7 +361,7 @@ echo $text_draftsmbox->show($RCI->getprop('drafts_mbox'));
'_smtp_server', 'size' => 30, 'id' => "cfgsmtphost")); +$text_smtphost = new html_inputfield(array('name' => '_smtp_server', 'size' => 30, 'id' => "cfgsmtphost")); echo $text_smtphost->show($RCI->getprop('smtp_server')); ?> @@ -377,7 +374,7 @@ echo $text_smtphost->show($RCI->getprop('smtp_server'));
'_smtp_port', 'size' => 6, 'id' => "cfgsmtpport")); +$text_smtpport = new html_inputfield(array('name' => '_smtp_port', 'size' => 6, 'id' => "cfgsmtpport")); echo $text_smtpport->show($RCI->getprop('smtp_port')); ?> @@ -388,8 +385,8 @@ echo $text_smtpport->show($RCI->getprop('smtp_port'));
'_smtp_user', 'size' => 20, 'id' => "cfgsmtpuser")); -$text_smtppass = new textfield(array('name' => '_smtp_pass', 'size' => 20, 'id' => "cfgsmtppass")); +$text_smtpuser = new html_inputfield(array('name' => '_smtp_user', 'size' => 20, 'id' => "cfgsmtpuser")); +$text_smtppass = new html_passwordfield(array('name' => '_smtp_pass', 'size' => 20, 'id' => "cfgsmtppass")); echo $text_smtpuser->show($RCI->getprop('smtp_user')); echo $text_smtppass->show($RCI->getprop('smtp_pass')); @@ -398,7 +395,7 @@ echo $text_smtppass->show($RCI->getprop('smtp_pass'));

'_smtp_user_u', 'id' => "cfgsmtpuseru")); +$check_smtpuser = new html_checkbox(array('name' => '_smtp_user_u', 'id' => "cfgsmtpuseru")); echo $check_smtpuser->show($RCI->getprop('smtp_user') == '%u' || $_POST['_smtp_user_u'] ? 1 : 0, array('value' => 1)); ?> @@ -410,7 +407,7 @@ echo $check_smtpuser->show($RCI->getprop('smtp_user') == '%u' || $_POST['_smtp_u

'_smtp_auth_type', 'id' => "cfgsmtpauth")); +$select_smtpauth = new html_select(array('name' => '_smtp_auth_type', 'id' => "cfgsmtpauth")); $select_smtpauth->add(array('(auto)', 'PLAIN', 'DIGEST-MD5', 'CRAM-MD5', 'LOGIN'), array('0', 'PLAIN', 'DIGEST-MD5', 'CRAM-MD5', 'LOGIN')); echo $select_smtpauth->show(intval($RCI->getprop('smtp_auth_type'))); */ @@ -422,7 +419,7 @@ echo $select_smtpauth->show(intval($RCI->getprop('smtp_auth_type')));
'_smtp_log', 'id' => "cfgsmtplog")); +$check_smtplog = new html_checkbox(array('name' => '_smtp_log', 'id' => "cfgsmtplog")); echo $check_smtplog->show(intval($RCI->getprop('smtp_log')), array('value' => 1)); ?> @@ -441,7 +438,7 @@ echo $check_smtplog->show(intval($RCI->getprop('smtp_log')), array('value' => 1)
'_locale_string', 'size' => 6, 'id' => "cfglocale")); +$input_locale = new html_inputfield(array('name' => '_locale_string', 'size' => 6, 'id' => "cfglocale")); echo $input_locale->show($RCI->getprop('locale_string')); ?> @@ -453,7 +450,7 @@ echo $input_locale->show($RCI->getprop('locale_string'));
'_pagesize', 'size' => 6, 'id' => "cfgpagesize")); +$input_pagesize = new html_inputfield(array('name' => '_pagesize', 'size' => 6, 'id' => "cfgpagesize")); echo $input_pagesize->show($RCI->getprop('pagesize')); ?> @@ -464,7 +461,7 @@ echo $input_pagesize->show($RCI->getprop('pagesize'));
'_prefer_html', 'id' => "cfghtmlview", 'value' => 1)); +$check_htmlview = new html_checkbox(array('name' => '_prefer_html', 'id' => "cfghtmlview", 'value' => 1)); echo $check_htmlview->show(intval($RCI->getprop('prefer_html'))); ?> @@ -475,7 +472,7 @@ echo $check_htmlview->show(intval($RCI->getprop('prefer_html')));
'_preview_pane', 'id' => "cfgprevpane", 'value' => 1)); +$check_prevpane = new html_checkbox(array('name' => '_preview_pane', 'id' => "cfgprevpane", 'value' => 1)); echo $check_prevpane->show(intval($RCI->getprop('preview_pane'))); ?> @@ -486,7 +483,7 @@ echo $check_prevpane->show(intval($RCI->getprop('preview_pane')));
'_htmleditor', 'id' => "cfghtmlcompose", 'value' => 1)); +$check_htmlcomp = new html_checkbox(array('name' => '_htmleditor', 'id' => "cfghtmlcompose", 'value' => 1)); echo $check_htmlcomp->show(intval($RCI->getprop('htmleditor'))); ?> @@ -498,7 +495,7 @@ echo $check_htmlcomp->show(intval($RCI->getprop('htmleditor'))); '_draft_autosave', 'id' => 'cfgautosave')); +$select_autosave = new html_select(array('name' => '_draft_autosave', 'id' => 'cfgautosave')); $select_autosave->add('never', 0); foreach (array(3, 5, 10) as $i => $min) $select_autosave->add("$min min", $min*60); diff --git a/installer/index.php b/installer/index.php index 69e33f8..4bd37f3 100644 --- a/installer/index.php +++ b/installer/index.php @@ -1,3 +1,31 @@ + @@ -23,22 +51,13 @@
load_config(); // exit if installation is complete if ($RCI->configured && !$RCI->getprop('enable_installer') && !$_SESSION['allowinstaller']) { - header("HTTP/1.0 404 Not Found"); + // header("HTTP/1.0 404 Not Found"); echo '

The installer is disabled!

'; echo '

To enable it again, set $rcmail_config[\'enable_installer\'] = true; in config/main.inc.php

'; echo '
'; diff --git a/installer/rcube_install.php b/installer/rcube_install.php index 12cd5c1..0240467 100644 --- a/installer/rcube_install.php +++ b/installer/rcube_install.php @@ -102,7 +102,7 @@ class rcube_install { $value = $this->is_post && (isset($_POST["_$name"]) || $this->config_props[$name]) ? $_POST["_$name"] : $this->config[$name]; - if ($name == 'des_key' && !isset($_REQUEST["_$name"])) + if ($name == 'des_key' && !$this->configured && !isset($_REQUEST["_$name"])) $value = rcube_install::random_key(24); return $value !== null && $value !== '' ? $value : $default; @@ -137,7 +137,9 @@ class rcube_install if ($_POST['_dbtype'] == 'sqlite') $value = sprintf('%s://%s?mode=0646', $_POST['_dbtype'], $_POST['_dbname']{0} == '/' ? '/' . $_POST['_dbname'] : $_POST['_dbname']); else - $value = sprintf('%s://%s:%s@%s/%s', $_POST['_dbtype'], $_POST['_dbuser'], $_POST['_dbpass'], $_POST['_dbhost'], $_POST['_dbname']); + $value = sprintf('%s://%s:%s@%s/%s', $_POST['_dbtype'], + rawurlencode($_POST['_dbuser']), rawurlencode($_POST['_dbpass']), + $_POST['_dbhost'], $_POST['_dbname']); } else if ($prop == 'smtp_auth_type' && $value == '0') { $value = ''; @@ -147,6 +149,9 @@ class rcube_install if (count($value) <= 1) $value = $value[0]; } + else if ($prop == 'pagesize') { + $value = max(2, intval($value)); + } else if ($prop == 'smtp_user' && !empty($_POST['_smtp_user_u'])) { $value = '%u'; } diff --git a/installer/test.php b/installer/test.php index 5be343a..bdaf3ee 100644 --- a/installer/test.php +++ b/installer/test.php @@ -3,10 +3,8 @@

Check config files

config)) { $RCI->pass('main.inc.php'); @@ -38,7 +36,7 @@ else if (!$read_db) { if ($RCI->configured) { $pass = false; foreach (array($RCI->config['temp_dir'],$RCI->config['log_dir']) as $dir) { - $dirpath = $dir{0} == '/' ? $dir : $docroot . '/' . $dir; + $dirpath = $dir{0} == '/' ? $dir : INSTALL_PATH . $dir; if (is_writable(realpath($dirpath))) { $RCI->pass($dir); $pass = true; @@ -68,10 +66,9 @@ if ($RCI->configured) { echo 'Backend: '; echo 'PEAR::' . strtoupper($RCI->config['db_backend']) . '
'; - $_class = 'rcube_' . strtolower($RCI->config['db_backend']); - require_once 'include/' . $_class . '.inc'; + $dbclass = 'rcube_' . strtolower($RCI->config['db_backend']); - $DB = new $_class($RCI->config['db_dsnw'], '', false); + $DB = new $dbclass($RCI->config['db_dsnw'], '', false); $DB->db_connect('w'); if (!($db_error_msg = $DB->is_error())) { $RCI->pass('DSN (write)'); @@ -164,11 +161,11 @@ if ($RCI->getprop('smtp_server')) { $pass = $RCI->getprop('smtp_pass', '(none)'); if ($user == '%u') { - $user_field = new textfield(array('name' => '_smtp_user')); + $user_field = new html_inputfield(array('name' => '_smtp_user')); $user = $user_field->show($_POST['_smtp_user']); } if ($pass == '%p') { - $pass_field = new passwordfield(array('name' => '_smtp_pass')); + $pass_field = new html_passwordfield(array('name' => '_smtp_pass')); $pass = $pass_field->show(); } @@ -176,8 +173,8 @@ if ($RCI->getprop('smtp_server')) { echo "Password: $pass
"; } -$from_field = new textfield(array('name' => '_from', 'id' => 'sendmailfrom')); -$to_field = new textfield(array('name' => '_to', 'id' => 'sendmailto')); +$from_field = new html_inputfield(array('name' => '_from', 'id' => 'sendmailfrom')); +$to_field = new html_inputfield(array('name' => '_to', 'id' => 'sendmailto')); ?>

@@ -186,8 +183,7 @@ $to_field = new textfield(array('name' => '_to', 'id' => 'sendmailto')); if (isset($_POST['sendmail']) && !empty($_POST['_from']) && !empty($_POST['_to'])) { - require_once 'lib/rc_mail_mime.inc'; - require_once 'include/rcube_smtp.inc'; + require_once 'rcube_smtp.inc'; echo '

Trying to send email...
'; @@ -214,7 +210,7 @@ if (isset($_POST['sendmail']) && !empty($_POST['_from']) && !empty($_POST['_to'] $CONFIG['smtp_pass'] = $_POST['_smtp_pass']; } - $mail_object = new rc_mail_mime(); + $mail_object = new rcube_mail_mime(); $send_headers = $mail_object->headers($headers); $status = smtp_mail($headers['From'], $headers['To'], @@ -271,15 +267,15 @@ echo '

'; $default_hosts = $RCI->get_hostlist(); if (!empty($default_hosts)) { - $host_field = new select(array('name' => '_host', 'id' => 'imaphost')); + $host_field = new html_select(array('name' => '_host', 'id' => 'imaphost')); $host_field->add($default_hosts); } else { - $host_field = new textfield(array('name' => '_host', 'id' => 'imaphost')); + $host_field = new html_inputfield(array('name' => '_host', 'id' => 'imaphost')); } -$user_field = new textfield(array('name' => '_user', 'id' => 'imapuser')); -$pass_field = new passwordfield(array('name' => '_pass', 'id' => 'imappass')); +$user_field = new html_inputfield(array('name' => '_user', 'id' => 'imapuser')); +$pass_field = new html_passwordfield(array('name' => '_pass', 'id' => 'imappass')); ?> @@ -308,8 +304,6 @@ $pass_field = new passwordfield(array('name' => '_pass', 'id' => 'imappass')); if (isset($_POST['imaptest']) && !empty($_POST['_host']) && !empty($_POST['_user'])) { - require_once 'include/rcube_imap.inc'; - echo '

Connecting to ' . Q($_POST['_host']) . '...
'; $a_host = parse_url($_POST['_host']); diff --git a/installer/welcome.html b/installer/welcome.html index 200f680..bfec233 100644 --- a/installer/welcome.html +++ b/installer/welcome.html @@ -6,7 +6,7 @@

The basic requirements are:

    -
  • PHP Version 4.3.1 or greater including +
  • PHP Version 5.2.0 or greater including
    • PCRE (perl compatible regular expression)
    • Session support
    • diff --git a/program/include/._main.inc b/program/include/._main.inc new file mode 100644 index 0000000000000000000000000000000000000000..f28074c1631f8a79186138eefe895b2e3d79b795 GIT binary patch literal 184 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDI}aT^eW_&b1@2;dkJ62wqdpA1wA(lG;w z6@VBSFakMHana=bT)o`H | +-----------------------------------------------------------------------+ - $Id: bugs.inc 666 2007-08-07 21:02:12Z thomasb $ + $Id: bugs.inc 1291 2008-04-12 13:54:45Z thomasb $ */ @@ -66,7 +66,7 @@ function raise_error($arg=array(), $log=false, $terminate=false) */ function log_bug($arg_arr) { - global $CONFIG, $INSTALL_PATH; + global $CONFIG; $program = $arg_arr['type']=='xpath' ? 'XPath' : strtoupper($arg_arr['type']); // write error to local log file @@ -81,7 +81,7 @@ function log_bug($arg_arr) $arg_arr['line']); if (empty($CONFIG['log_dir'])) - $CONFIG['log_dir'] = $INSTALL_PATH.'logs'; + $CONFIG['log_dir'] = INSTALL_PATH.'logs'; // try to open specific log file for writing if ($fp = @fopen($CONFIG['log_dir'].'/errors', 'a')) diff --git a/program/include/html.php b/program/include/html.php new file mode 100644 index 0000000..d0ab976 --- /dev/null +++ b/program/include/html.php @@ -0,0 +1,642 @@ + | + +-----------------------------------------------------------------------+ + + $Id: $ + + */ + + +/** + * Class for HTML code creation + * + * @package HTML + */ +class html +{ + protected $tagname; + protected $attrib = array(); + protected $allowed; + protected $content; + + public static $common_attrib = array('id','class','style','title','align'); + public static $containers = array('div','span','p','h1','h2','h3','form','textarea'); + public static $lc_tags = true; + + /** + * Constructor + * + * @param array Hash array with tag attributes + */ + public function __construct($attrib = array()) + { + if (is_array($attrib)) { + $this->attrib = $attrib; + } + } + + /** + * Return the tag code + * + * @return string The finally composed HTML tag + */ + public function show() + { + return self::tag($this->tagname, $this->attrib, $this->content, $this->allowed); + } + + /****** STATIC METHODS *******/ + + /** + * Generic method to create a HTML tag + * + * @param string Tag name + * @param array Tag attributes as key/value pairs + * @param string Optinal Tag content (creates a container tag) + * @param array List with allowed attributes, omit to allow all + * @return string The XHTML tag + */ + public static function tag($tagname, $attrib = array(), $content = null, $allowed_attrib = null) + { + $inline_tags = array('a','span','img'); + $suffix = $attrib['nl'] || ($content && $attrib['nl'] !== false && !in_array($tagname, $inline_tags)) ? "\n" : ''; + + $tagname = self::$lc_tags ? strtolower($tagname) : $tagname; + if ($content || in_array($tagname, self::$containers)) { + $templ = $attrib['noclose'] ? "<%s%s>%s" : "<%s%s>%s%s"; + unset($attrib['noclose']); + return sprintf($templ, $tagname, self::attrib_string($attrib, $allowed_attrib), $content, $tagname, $suffix); + } + else { + return sprintf("<%s%s />%s", $tagname, self::attrib_string($attrib, $allowed_attrib), $suffix); + } + } + + /** + * Derrived method for
      containers + * + * @param mixed Hash array with tag attributes or string with class name + * @param string Div content + * @return string HTML code + * @see html::tag() + */ + public static function div($attr = null, $cont = null) + { + if (is_string($attr)) { + $attr = array('class' => $attr); + } + return self::tag('div', $attr, $cont, self::$common_attrib); + } + + /** + * Derrived method for

      blocks + * + * @param mixed Hash array with tag attributes or string with class name + * @param string Paragraph content + * @return string HTML code + * @see html::tag() + */ + public static function p($attr = null, $cont = null) + { + if (is_string($attr)) { + $attr = array('class' => $attr); + } + return self::tag('p', $attr, $cont, self::$common_attrib); + } + + /** + * Derrived method to create + * + * @param mixed Hash array with tag attributes or string with image source (src) + * @return string HTML code + * @see html::tag() + */ + public static function img($attr = null) + { + if (is_string($attr)) { + $attr = array('src' => $attr); + } + return self::tag('img', $attr + array('alt' => ''), null, array_merge(self::$common_attrib, array('src','alt','width','height','border','usemap'))); + } + + /** + * Derrived method for link tags + * + * @param mixed Hash array with tag attributes or string with link location (href) + * @param string Link content + * @return string HTML code + * @see html::tag() + */ + public static function a($attr, $cont) + { + if (is_string($attr)) { + $attr = array('href' => $attr); + } + return self::tag('a', $attr, $cont, array_merge(self::$common_attrib, array('href','target','name','onclick','onmouseover','onmouseout'))); + } + + /** + * Derrived method for inline span tags + * + * @param mixed Hash array with tag attributes or string with class name + * @param string Tag content + * @return string HTML code + * @see html::tag() + */ + public static function span($attr, $cont) + { + if (is_string($attr)) { + $attr = array('class' => $attr); + } + return self::tag('span', $attr, $cont, self::$common_attrib); + } + + /** + * Derrived method for form element labels + * + * @param mixed Hash array with tag attributes or string with 'for' attrib + * @param string Tag content + * @return string HTML code + * @see html::tag() + */ + public static function label($attr, $cont) + { + if (is_string($attr)) { + $attr = array('for' => $attr); + } + return self::tag('label', $attr, $cont, array_merge(self::$common_attrib, array('for'))); + } + + /** + * Derrived method for line breaks + * + * @return string HTML code + * @see html::tag() + */ + public static function br() + { + return self::tag('br'); + } + + /** + * Create string with attributes + * + * @param array Associative arry with tag attributes + * @param array List of allowed attributes + * @return string Valid attribute string + */ + public static function attrib_string($attrib = array(), $allowed = null) + { + if (empty($attrib)) { + return ''; + } + + $allowed_f = array_flip((array)$allowed); + $attrib_arr = array(); + foreach ($attrib as $key => $value) { + // skip size if not numeric + if (($key=='size' && !is_numeric($value))) { + continue; + } + + // ignore "internal" or not allowed attributes + if ($key == 'nl' || ($allowed && !isset($allowed_f[$key])) || $value === null) { + continue; + } + + // skip empty eventhandlers + if (preg_match('/^on[a-z]+/', $key) && !$value) { + continue; + } + + // attributes with no value + if (in_array($key, array('checked', 'multiple', 'disabled', 'selected'))) { + if ($value) { + $attrib_arr[] = sprintf('%s="%s"', $key, $key); + } + } + else if ($key=='value') { + $attrib_arr[] = sprintf('%s="%s"', $key, Q($value, 'strict', false)); + } + else { + $attrib_arr[] = sprintf('%s="%s"', $key, Q($value)); + } + } + return count($attrib_arr) ? ' '.implode(' ', $attrib_arr) : ''; + } +} + +/** + * Class to create an HTML input field + * + * @package HTML + */ +class html_inputfield extends html +{ + protected $tagname = 'input'; + protected $type = 'text'; + + public function __construct($attrib = array()) + { + if (is_array($attrib)) { + $this->attrib = $attrib; + } + + if ($attrib['type']) { + $this->type = $attrib['type']; + } + + if ($attrib['newline']) { + $this->newline = true; + } + } + + /** + * Compose input tag + * + * @param string Field value + * @param array Additional attributes to override + * @return string HTML output + */ + public function show($value = null, $attrib = null) + { + // overwrite object attributes + if (is_array($attrib)) { + $this->attrib = array_merge($this->attrib, $attrib); + } + + // set value attribute + if ($value !== null) { + $this->attrib['value'] = $value; + } + // set type + $this->attrib['type'] = $this->type; + return parent::show(); + } +} + +/** + * Class to create an HTML password field + * + * @package HTML + */ +class html_passwordfield extends html_inputfield +{ + protected $type = 'password'; +} + +/** + * Class to create an hidden HTML input field + * + * @package HTML + */ + +class html_hiddenfield extends html_inputfield +{ + protected $type = 'hidden'; + protected $fields_arr = array(); + protected $newline = true; + + /** + * Constructor + * + * @param array Named tag attributes + */ + public function __construct($attrib = null) + { + if (is_array($attrib)) { + $this->add($attrib); + } + } + + /** + * Add a hidden field to this instance + * + * @param array Named tag attributes + */ + public function add($attrib) + { + $this->fields_arr[] = $attrib; + } + + /** + * Create HTML code for the hidden fields + * + * @return string Final HTML code + */ + public function show() + { + $out = ''; + foreach ($this->fields_arr as $attrib) { + $out .= self::tag($this->tagname, array('type' => $this->type) + $attrib); + } + return $out; + } +} + +/** + * Class to create HTML radio buttons + * + * @package HTML + */ +class html_radiobutton extends html_inputfield +{ + protected $type = 'radio'; + + /** + * Get HTML code for this object + * + * @param string Value of the checked field + * @param array Additional attributes to override + * @return string HTML output + */ + public function show($value = '', $attrib = null) + { + // overwrite object attributes + if (is_array($attrib)) { + $this->attrib = array_merge($this->attrib, $attrib); + } + + // set value attribute + $this->attrib['checked'] = ((string)$value == (string)$this->attrib['value']); + + return parent::show(); + } +} + +/** + * Class to create HTML checkboxes + * + * @package HTML + */ +class html_checkbox extends html_inputfield +{ + protected $type = 'checkbox'; + + /** + * Get HTML code for this object + * + * @param string Value of the checked field + * @param array Additional attributes to override + * @return string HTML output + */ + public function show($value = '', $attrib = null) + { + // overwrite object attributes + if (is_array($attrib)) { + $this->attrib = array_merge($this->attrib, $attrib); + } + + // set value attribute + $this->attrib['checked'] = ((string)$value == (string)$this->attrib['value']); + + return parent::show(); + } +} + +/** + * Class to create an HTML textarea + * + * @package HTML + */ +class html_textarea extends html +{ + protected $tagname = 'textarea'; + protected $allowed_attrib = array('name','rows','cols','wrap','tabindex'); + + /** + * Get HTML code for this object + * + * @param string Textbox value + * @param array Additional attributes to override + * @return string HTML output + */ + public function show($value = '', $attrib = null) + { + // overwrite object attributes + if (is_array($attrib)) { + $this->attrib = array_merge($this->attrib, $attrib); + } + + // take value attribute as content + if (empty($value) && !empty($this->attrib['value'])) { + $value = $this->attrib['value']; + } + + // make shure we don't print the value attribute + if (isset($this->attrib['value'])) { + unset($this->attrib['value']); + } + + if (!empty($value) && !isset($this->attrib['mce_editable'])) { + $value = Q($value, 'strict', false); + } + return self::tag($this->tagname, $this->attrib, $value, array_merge(self::$common_attrib, $this->allowed_attrib)); + } +} + +/** + * Builder for HTML drop-down menus + * Syntax:

      + * // create instance. arguments are used to set attributes of select-tag
      + * $select = new html_select(array('name' => 'fieldname'));
      + *
      + * // add one option
      + * $select->add('Switzerland', 'CH');
      + *
      + * // add multiple options
      + * $select->add(array('Switzerland','Germany'), array('CH','DE'));
      + *
      + * // generate pulldown with selection 'Switzerland'  and return html-code
      + * // as second argument the same attributes available to instanciate can be used
      + * print $select->show('CH');
      + * 
      + * + * @package HTML + */ +class html_select extends html +{ + protected $tagname = 'select'; + protected $options = array(); + + /** + * Add a new option to this drop-down + * + * @param mixed Option name or array with option names + * @param mixed Option value or array with option values + */ + public function add($names, $values = null) + { + if (is_array($names)) { + foreach ($names as $i => $text) { + $this->options[] = array('text' => $text, 'value' => $values[$i]); + } + } + else { + $this->options[] = array('text' => $names, 'value' => $values); + } + } + + + /** + * Get HTML code for this object + * + * @param string Value of the selection option + * @param array Additional attributes to override + * @return string HTML output + */ + public function show($select = array(), $attrib = null) + { + // overwrite object attributes + if (is_array($attrib)) { + $this->attrib = array_merge($this->attrib, $attrib); + } + + $this->content = "\n"; + $select = (array)$select; + foreach ($this->options as $option) { + $attr = array( + 'value' => $option['value'], + 'selected' => (in_array($option['value'], $select, true) || + in_array($option['text'], $select, true)) ? 1 : null); + + $this->content .= self::tag('option', $attr, Q($option['text'])); + } + return parent::show(); + } +} + + +/** + * Class to build an HTML table + * + * @package HTML + */ +class html_table extends html +{ + protected $tagname = 'table'; + protected $allowed = array('id','class','style','width','summary','cellpadding','cellspacing','border'); + private $header = array(); + private $rows = array(); + private $rowindex = 0; + private $colindex = 0; + + + public function __construct($attrib = array()) + { + $this->attrib = array_merge($attrib, array('summary' => '', 'border' => 0)); + } + + /** + * Add a table cell + * + * @param array Cell attributes + * @param string Cell content + */ + public function add($attr, $cont) + { + if (is_string($attr)) { + $attr = array('class' => $attr); + } + + $cell = new stdClass; + $cell->attrib = $attr; + $cell->content = $cont; + + $this->rows[$this->rowindex]->cells[$this->colindex] = $cell; + $this->colindex++; + + if ($this->attrib['cols'] && $this->colindex == $this->attrib['cols']) { + $this->add_row(); + } + } + + /** + * Add a table header cell + * + * @param array Cell attributes + * @param string Cell content + */ + private function add_header($attr, $cont) + { + if (is_string($attr)) + $attr = array('class' => $attr); + + $cell = new stdClass; + $cell->attrib = $attr; + $cell->content = $cont; + $this->header[] = $cell; + } + + /** + * Jump to next row + * + * @param array Row attributes + */ + private function add_row($attr = array()) + { + $this->rowindex++; + $this->colindex = 0; + $this->rows[$this->rowindex] = new stdClass; + $this->rows[$this->rowindex]->attrib = $attr; + $this->rows[$this->rowindex]->cells = array(); + } + + + /** + * Build HTML output of the table data + * + * @param array Table attributes + * @return string The final table HTML code + */ + public function show($attr = array()) + { + $this->attrib = array_merge($this->attrib, $attr); + $thead = $tbody = ""; + + // include + if (!empty($this->header)) { + $rowcontent = ''; + foreach ($this->header as $c => $col) { + $rowcontent .= self::tag('th', $col->attrib, $col->content); + } + $thead = self::tag('thead', null, self::tag('tr', null, $rowcontent)); + } + + foreach ($this->rows as $r => $row) { + $rowcontent = ''; + foreach ($row->cells as $c => $col) { + $rowcontent .= self::tag('td', $col->attrib, $col->content); + } + + if ($r < $this->rowindex || count($row->cells)) { + $tbody .= self::tag('tr', $rows->attrib, $rowcontent); + } + } + + if ($this->attrib['rowsonly']) { + return $tbody; + } + + // add + $this->content = $thead . self::tag('tbody', null, $tbody); + + unset($this->attrib['cols'], $this->attrib['rowsonly']); + return parent::show(); + } +} + +?> \ No newline at end of file diff --git a/program/include/iniset.php b/program/include/iniset.php new file mode 100755 index 0000000..b718393 --- /dev/null +++ b/program/include/iniset.php @@ -0,0 +1,98 @@ + | + | Thomas Bruederli | + +-----------------------------------------------------------------------+ + + $Id: cache.inc 88 2005-12-03 16:54:12Z roundcube $ + +*/ + + +// application constants +define('RCMAIL_VERSION', '0.2-alpha'); +define('RCMAIL_CHARSET', 'UTF-8'); +define('JS_OBJECT_NAME', 'rcmail'); + +if (!defined('INSTALL_PATH')) { + define('INSTALL_PATH', dirname($_SERVER['SCRIPT_FILENAME']).'/'); +} + +// make sure path_separator is defined +if (!defined('PATH_SEPARATOR')) { + define('PATH_SEPARATOR', (eregi('win', PHP_OS) ? ';' : ':')); +} + +// RC include folders MUST be included FIRST to avoid other +// possible not compatible libraries (i.e PEAR) to be included +// instead the ones provided by RC +$include_path = INSTALL_PATH . PATH_SEPARATOR; +$include_path.= INSTALL_PATH . 'program' . PATH_SEPARATOR; +$include_path.= INSTALL_PATH . 'program/lib' . PATH_SEPARATOR; +$include_path.= INSTALL_PATH . 'program/include' . PATH_SEPARATOR; +$include_path.= ini_get('include_path'); + +if (set_include_path($include_path) === false) { + die('Fatal error: ini_set/set_include_path does not work.'); +} + +ini_set('session.name', 'roundcube_sessid'); +ini_set('session.use_cookies', 1); +ini_set('session.gc_maxlifetime', 21600); +ini_set('session.gc_divisor', 500); +ini_set('error_reporting', E_ALL&~E_NOTICE); +set_magic_quotes_runtime(0); + +// increase maximum execution time for php scripts +// (does not work in safe mode) +if (!ini_get('safe_mode')) { + set_time_limit(120); +} + +/** + * Use PHP5 autoload for dynamic class loading + * + * @todo Make Zend, PEAR etc play with this + */ +function __autoload($classname) +{ + $filename = preg_replace( + array('/MDB2_(.+)/', '/Mail_(.+)/', '/^html_.+/', '/^utf8$/'), + array('MDB2/\\1', 'Mail/\\1', 'html', 'utf8.class'), + $classname + ); + include_once $filename. '.php'; +} + +/** + * Local callback function for PEAR errors + */ +function rcube_pear_error($err) +{ + error_log(sprintf("%s (%s): %s", + $err->getMessage(), + $err->getCode(), + $err->getUserinfo()), 0); +} + +// include global functions +require_once 'include/bugs.inc'; +require_once 'include/main.inc'; +require_once 'include/rcube_shared.inc'; + + +// set PEAR error handling (will also load the PEAR main class) +PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'rcube_pear_error'); + diff --git a/program/include/main.inc b/program/include/main.inc index 446780c..c6b4168 100644 --- a/program/include/main.inc +++ b/program/include/main.inc @@ -15,7 +15,7 @@ | Author: Thomas Bruederli | +-----------------------------------------------------------------------+ - $Id: main.inc 1255 2008-04-05 12:49:21Z thomasb $ + $Id: main.inc 1459 2008-05-30 19:55:28Z alec $ */ @@ -27,9 +27,7 @@ */ require_once('lib/utf7.inc'); -require_once('include/rcube_user.inc'); require_once('include/rcube_shared.inc'); -require_once('include/rcmail_template.inc'); // define constannts for input reading define('RCUBE_INPUT_GET', 0x0101); @@ -37,313 +35,6 @@ define('RCUBE_INPUT_POST', 0x0102); define('RCUBE_INPUT_GPC', 0x0103); -/** - * Initial startup function - * to register session, create database and imap connections - * - * @param string Current task - */ -function rcmail_startup($task='mail') - { - global $sess_id, $sess_user_lang; - global $CONFIG, $INSTALL_PATH, $BROWSER, $OUTPUT, $_SESSION, $IMAP, $DB, $USER; - - // check client - $BROWSER = rcube_browser(); - - // load configuration - $CONFIG = rcmail_load_config(); - - // set session domain - if (isset($CONFIG['session_domain']) && !empty($CONFIG['session_domain'])) { - ini_set('session.cookie_domain', $CONFIG['session_domain']); - } - - // set session garbage collecting time according to session_lifetime - if (!empty($CONFIG['session_lifetime'])) - ini_set('session.gc_maxlifetime', ($CONFIG['session_lifetime']) * 120); - - // prepare DB connection - $dbwrapper = empty($CONFIG['db_backend']) ? 'db' : $CONFIG['db_backend']; - $dbclass = "rcube_" . $dbwrapper; - require_once("include/$dbclass.inc"); - - $DB = new $dbclass($CONFIG['db_dsnw'], $CONFIG['db_dsnr'], $CONFIG['db_persistent']); - $DB->sqlite_initials = $INSTALL_PATH.'SQL/sqlite.initial.sql'; - $DB->set_debug((bool)$CONFIG['sql_debug']); - $DB->db_connect('w'); - - // use database for storing session data - include_once('include/session.inc'); - - // init session - session_start(); - $sess_id = session_id(); - - // create session and set session vars - if (!isset($_SESSION['auth_time'])) - { - $_SESSION['user_lang'] = rcube_language_prop($CONFIG['locale_string']); - $_SESSION['auth_time'] = time(); - $_SESSION['temp'] = true; - } - - // set session vars global - $sess_user_lang = rcube_language_prop($_SESSION['user_lang']); - - // create user object - $USER = new rcube_user($_SESSION['user_id']); - - // overwrite config with user preferences - $CONFIG = array_merge($CONFIG, (array)$USER->get_prefs()); - - - // reset some session parameters when changing task - if ($_SESSION['task'] != $task) - unset($_SESSION['page']); - - // set current task to session - $_SESSION['task'] = $task; - - // create IMAP object - if ($task=='mail') - rcmail_imap_init(); - - - // set localization - if ($CONFIG['locale_string']) - setlocale(LC_ALL, $CONFIG['locale_string']); - else if ($sess_user_lang) - setlocale(LC_ALL, $sess_user_lang); - - - register_shutdown_function('rcmail_shutdown'); - } - - -/** - * Load roundcube configuration array - * - * @return array Named configuration parameters - */ -function rcmail_load_config() - { - global $INSTALL_PATH; - - // load config file - include_once('config/main.inc.php'); - $conf = is_array($rcmail_config) ? $rcmail_config : array(); - - // load host-specific configuration - rcmail_load_host_config($conf); - - $conf['skin_path'] = $conf['skin_path'] ? unslashify($conf['skin_path']) : 'skins/default'; - - // load db conf - include_once('config/db.inc.php'); - $conf = array_merge($conf, $rcmail_config); - - if (empty($conf['log_dir'])) - $conf['log_dir'] = $INSTALL_PATH.'logs'; - else - $conf['log_dir'] = unslashify($conf['log_dir']); - - // set PHP error logging according to config - if ($conf['debug_level'] & 1) - { - ini_set('log_errors', 1); - ini_set('error_log', $conf['log_dir'].'/errors'); - } - if ($conf['debug_level'] & 4) - ini_set('display_errors', 1); - else - ini_set('display_errors', 0); - - return $conf; - } - - -/** - * Load a host-specific config file if configured - * This will merge the host specific configuration with the given one - * - * @param array Global configuration parameters - */ -function rcmail_load_host_config(&$config) - { - $fname = NULL; - - if (is_array($config['include_host_config'])) - $fname = $config['include_host_config'][$_SERVER['HTTP_HOST']]; - else if (!empty($config['include_host_config'])) - $fname = preg_replace('/[^a-z0-9\.\-_]/i', '', $_SERVER['HTTP_HOST']) . '.inc.php'; - - if ($fname && is_file('config/'.$fname)) - { - include('config/'.$fname); - $config = array_merge($config, $rcmail_config); - } - } - - -/** - * Create unique authorization hash - * - * @param string Session ID - * @param int Timestamp - * @return string The generated auth hash - */ -function rcmail_auth_hash($sess_id, $ts) - { - global $CONFIG; - - $auth_string = sprintf('rcmail*sess%sR%s*Chk:%s;%s', - $sess_id, - $ts, - $CONFIG['ip_check'] ? $_SERVER['REMOTE_ADDR'] : '***.***.***.***', - $_SERVER['HTTP_USER_AGENT']); - - if (function_exists('sha1')) - return sha1($auth_string); - else - return md5($auth_string); - } - - -/** - * Check the auth hash sent by the client against the local session credentials - * - * @return boolean True if valid, False if not - */ -function rcmail_authenticate_session() - { - global $CONFIG, $SESS_CLIENT_IP, $SESS_CHANGED; - - // advanced session authentication - if ($CONFIG['double_auth']) - { - $now = time(); - $valid = ($_COOKIE['sessauth'] == rcmail_auth_hash(session_id(), $_SESSION['auth_time']) || - $_COOKIE['sessauth'] == rcmail_auth_hash(session_id(), $_SESSION['last_auth'])); - - // renew auth cookie every 5 minutes (only for GET requests) - if (!$valid || ($_SERVER['REQUEST_METHOD']!='POST' && $now-$_SESSION['auth_time'] > 300)) - { - $_SESSION['last_auth'] = $_SESSION['auth_time']; - $_SESSION['auth_time'] = $now; - setcookie('sessauth', rcmail_auth_hash(session_id(), $now)); - } - } - else - $valid = $CONFIG['ip_check'] ? $_SERVER['REMOTE_ADDR'] == $SESS_CLIENT_IP : true; - - // check session filetime - if (!empty($CONFIG['session_lifetime']) && isset($SESS_CHANGED) - && $SESS_CHANGED + $CONFIG['session_lifetime']*60 < time()) - $valid = false; - - return $valid; - } - - -/** - * Create global IMAP object and connect to server - * - * @param boolean True if connection should be established - */ -function rcmail_imap_init($connect=FALSE) - { - global $CONFIG, $DB, $IMAP, $OUTPUT; - - $IMAP = new rcube_imap($DB); - $IMAP->debug_level = $CONFIG['debug_level']; - $IMAP->skip_deleted = $CONFIG['skip_deleted']; - - - // connect with stored session data - if ($connect) - { - if (!($conn = $IMAP->connect($_SESSION['imap_host'], $_SESSION['username'], decrypt_passwd($_SESSION['password']), $_SESSION['imap_port'], $_SESSION['imap_ssl']))) - $OUTPUT->show_message('imaperror', 'error'); - - rcmail_set_imap_prop(); - } - - // enable caching of imap data - if ($CONFIG['enable_caching']===TRUE) - $IMAP->set_caching(TRUE); - - // set pagesize from config - if (isset($CONFIG['pagesize'])) - $IMAP->set_pagesize($CONFIG['pagesize']); - } - - -/** - * Set root dir and last stored mailbox - * This must be done AFTER connecting to the server! - */ -function rcmail_set_imap_prop() - { - global $CONFIG, $IMAP; - - if (!empty($CONFIG['default_charset'])) - $IMAP->set_charset($CONFIG['default_charset']); - - // set root dir from config - if (!empty($CONFIG['imap_root'])) - $IMAP->set_rootdir($CONFIG['imap_root']); - - if (is_array($CONFIG['default_imap_folders'])) - $IMAP->set_default_mailboxes($CONFIG['default_imap_folders']); - - if (!empty($_SESSION['mbox'])) - $IMAP->set_mailbox($_SESSION['mbox']); - if (isset($_SESSION['page'])) - $IMAP->set_page($_SESSION['page']); - } - - -/** - * Do these things on script shutdown - */ -function rcmail_shutdown() - { - global $IMAP, $CONTACTS; - - if (is_object($IMAP)) - { - $IMAP->close(); - $IMAP->write_cache(); - } - - if (is_object($CONTACTS)) - $CONTACTS->close(); - - // before closing the database connection, write session data - session_write_close(); - } - - -/** - * Destroy session data and remove cookie - */ -function rcmail_kill_session() - { - global $USER; - - if ((isset($_SESSION['sort_col']) && $_SESSION['sort_col']!=$a_user_prefs['message_sort_col']) || - (isset($_SESSION['sort_order']) && $_SESSION['sort_order']!=$a_user_prefs['message_sort_order'])) - { - $a_user_prefs = array('message_sort_col' => $_SESSION['sort_col'], 'message_sort_order' => $_SESSION['sort_order']); - $USER->save_prefs($a_user_prefs); - } - - $_SESSION = array('user_lang' => $GLOBALS['sess_user_lang'], 'auth_time' => time(), 'temp' => true); - setcookie('sessauth', '-del-', time()-60); - $USER->reset(); - } - /** * Return correct name for a specific database table @@ -354,319 +45,59 @@ function rcmail_kill_session() function get_table_name($table) { global $CONFIG; - + // return table name if configured $config_key = 'db_table_'.$table; if (strlen($CONFIG[$config_key])) return $CONFIG[$config_key]; - + return $table; } /** * Return correct name for a specific database sequence - * (used for Postres only) + * (used for Postgres only) * * @param string Secuence name * @return string Translated sequence name */ function get_sequence_name($sequence) { - global $CONFIG; - // return table name if configured $config_key = 'db_sequence_'.$sequence; + $opt = rcmail::get_instance()->config->get($config_key); - if (strlen($CONFIG[$config_key])) - return $CONFIG[$config_key]; - - return $sequence; - } - - -/** - * Check the given string and returns language properties - * - * @param string Language code - * @param string Peropert name - * @return string Property value - */ -function rcube_language_prop($lang, $prop='lang') - { - global $INSTALL_PATH; - static $rcube_languages, $rcube_language_aliases, $rcube_charsets; - - if (empty($rcube_languages)) - @include($INSTALL_PATH.'program/localization/index.inc'); - - // check if we have an alias for that language - if (!isset($rcube_languages[$lang]) && isset($rcube_language_aliases[$lang])) - $lang = $rcube_language_aliases[$lang]; - - // try the first two chars - if (!isset($rcube_languages[$lang]) && strlen($lang)>2) + if (!empty($opt)) { - $lang = substr($lang, 0, 2); - $lang = rcube_language_prop($lang); - } - - if (!isset($rcube_languages[$lang])) - $lang = 'en_US'; - - // language has special charset configured - if (isset($rcube_charsets[$lang])) - $charset = $rcube_charsets[$lang]; - else - $charset = 'UTF-8'; - - - if ($prop=='charset') - return $charset; - else - return $lang; - } - - -/** - * Init output object for GUI and add common scripts. - * This will instantiate a rcmail_template object and set - * environment vars according to the current session and configuration - */ -function rcmail_load_gui() - { - global $CONFIG, $OUTPUT, $sess_user_lang; - - // init output page - $OUTPUT = new rcmail_template($CONFIG, $GLOBALS['_task']); - $OUTPUT->set_env('comm_path', $GLOBALS['COMM_PATH']); - - if (is_array($CONFIG['javascript_config'])) - { - foreach ($CONFIG['javascript_config'] as $js_config_var) - $OUTPUT->set_env($js_config_var, $CONFIG[$js_config_var]); - } - - if (!empty($GLOBALS['_framed'])) - $OUTPUT->set_env('framed', true); + $db = &rcmail::get_instance()->db; - // set locale setting - rcmail_set_locale($sess_user_lang); - - // set user-selected charset - if (!empty($CONFIG['charset'])) - $OUTPUT->set_charset($CONFIG['charset']); - - // register common UI objects - $OUTPUT->add_handlers(array( - 'loginform' => 'rcmail_login_form', - 'username' => 'rcmail_current_username', - 'message' => 'rcmail_message_container', - 'charsetselector' => 'rcmail_charset_selector', - )); - - // add some basic label to client - if (!$OUTPUT->ajax_call) - rcube_add_label('loading', 'movingmessage'); - } - - -/** - * Set localization charset based on the given language. - * This also creates a global property for mbstring usage. - */ -function rcmail_set_locale($lang) - { - global $OUTPUT, $MBSTRING; - static $s_mbstring_loaded = NULL; - - // settings for mbstring module (by Tadashi Jokagi) - if (is_null($s_mbstring_loaded)) - $MBSTRING = $s_mbstring_loaded = extension_loaded("mbstring"); - else - $MBSTRING = $s_mbstring_loaded = FALSE; - - if ($MBSTRING) - mb_internal_encoding(RCMAIL_CHARSET); - - $OUTPUT->set_charset(rcube_language_prop($lang, 'charset')); - } - - -/** - * Auto-select IMAP host based on the posted login information - * - * @return string Selected IMAP host - */ -function rcmail_autoselect_host() - { - global $CONFIG; - - $host = isset($_POST['_host']) ? get_input_value('_host', RCUBE_INPUT_POST) : $CONFIG['default_host']; - if (is_array($host)) - { - list($user, $domain) = explode('@', get_input_value('_user', RCUBE_INPUT_POST)); - if (!empty($domain)) + if($db->db_provider=='pgsql') // just for sure { - foreach ($host as $imap_host => $mail_domains) - if (is_array($mail_domains) && in_array($domain, $mail_domains)) - { - $host = $imap_host; - break; - } - } - - // take the first entry if $host is still an array - if (is_array($host)) - $host = array_shift($host); - } + $db->db_handle->setOption('disable_smart_seqname', true); + $db->db_handle->setOption('seqname_format', '%s'); + } - return $host; + return $CONFIG[$opt]; + } + + return $sequence; } /** - * Perfom login to the IMAP server and to the webmail service. - * This will also create a new user entry if auto_create_user is configured. + * Get localized text in the desired language + * It's a global wrapper for rcmail::gettext() * - * @param string IMAP user name - * @param string IMAP password - * @param string IMAP host - * @return boolean True on success, False on failure + * @param mixed Named parameters array or label name + * @return string Localized text + * @see rcmail::gettext() */ -function rcmail_login($user, $pass, $host=NULL) - { - global $CONFIG, $IMAP, $DB, $USER, $sess_user_lang; - $user_id = NULL; - - if (!$host) - $host = $CONFIG['default_host']; - - // Validate that selected host is in the list of configured hosts - if (is_array($CONFIG['default_host'])) - { - $allowed = FALSE; - foreach ($CONFIG['default_host'] as $key => $host_allowed) - { - if (!is_numeric($key)) - $host_allowed = $key; - if ($host == $host_allowed) - { - $allowed = TRUE; - break; - } - } - if (!$allowed) - return FALSE; - } - else if (!empty($CONFIG['default_host']) && $host != $CONFIG['default_host']) - return FALSE; - - // parse $host URL - $a_host = parse_url($host); - if ($a_host['host']) - { - $host = $a_host['host']; - $imap_ssl = (isset($a_host['scheme']) && in_array($a_host['scheme'], array('ssl','imaps','tls'))) ? $a_host['scheme'] : null; - $imap_port = isset($a_host['port']) ? $a_host['port'] : ($imap_ssl ? 993 : $CONFIG['default_port']); - } - else - $imap_port = $CONFIG['default_port']; - - - /* Modify username with domain if required - Inspired by Marco - */ - // Check if we need to add domain - if (!empty($CONFIG['username_domain']) && !strpos($user, '@')) - { - if (is_array($CONFIG['username_domain']) && isset($CONFIG['username_domain'][$host])) - $user .= '@'.$CONFIG['username_domain'][$host]; - else if (is_string($CONFIG['username_domain'])) - $user .= '@'.$CONFIG['username_domain']; - } - - // try to resolve email address from virtuser table - if (!empty($CONFIG['virtuser_file']) && strpos($user, '@')) - $user = rcube_user::email2user($user); - - // lowercase username if it's an e-mail address (#1484473) - if (strpos($user, '@')) - $user = strtolower($user); - - // query if user already registered - if ($existing = rcube_user::query($user, $host)) - $USER = $existing; - - // user already registered -> overwrite username - if ($USER->ID) - { - $user_id = $USER->ID; - $user = $USER->data['username']; - } - - // exit if IMAP login failed - if (!($imap_login = $IMAP->connect($host, $user, $pass, $imap_port, $imap_ssl))) - return false; - - // user already registered - if ($USER->ID) - { - // get user prefs - $CONFIG = array_merge($CONFIG, (array)$USER->get_prefs()); - - // set user specific language - if (!empty($USER->data['language'])) - $sess_user_lang = $_SESSION['user_lang'] = $USER->data['language']; - - // update user's record - $USER->touch(); - } - // create new system user - else if ($CONFIG['auto_create_user']) - { - if ($created = rcube_user::create($user, $host)) - { - $USER = $created; - - // get existing mailboxes - $a_mailboxes = $IMAP->list_mailboxes(); - } - } - else - { - raise_error(array( - 'code' => 600, - 'type' => 'php', - 'file' => "config/main.inc.php", - 'message' => "Acces denied for new user $user. 'auto_create_user' is disabled" - ), true, false); - } - - if ($USER->ID) - { - $_SESSION['user_id'] = $USER->ID; - $_SESSION['username'] = $USER->data['username']; - $_SESSION['imap_host'] = $host; - $_SESSION['imap_port'] = $imap_port; - $_SESSION['imap_ssl'] = $imap_ssl; - $_SESSION['user_lang'] = $sess_user_lang; - $_SESSION['password'] = encrypt_passwd($pass); - $_SESSION['login_time'] = mktime(); - - // force reloading complete list of subscribed mailboxes - rcmail_set_imap_prop(); - $IMAP->clear_cache('mailboxes'); - - if ($CONFIG['create_default_folders']) - $IMAP->create_default_folders(); - - return TRUE; - } - - return FALSE; - } +function rcube_label($p) +{ + return rcmail::get_instance()->gettext($p); +} /** @@ -721,9 +152,9 @@ function rcmail_findinvirtual($pattern) */ function rcmail_overwrite_action($action) { - global $OUTPUT; - $GLOBALS['_action'] = $action; - $OUTPUT->set_env('action', $action); + $app = rcmail::get_instance(); + $app->action = $action; + $app->output->set_env('action', $action); } @@ -737,12 +168,13 @@ function rcmail_overwrite_action($action) */ function rcmail_url($action, $p=array(), $task=null) { - global $MAIN_TASKS, $COMM_PATH; + $app = rcmail::get_instance(); + $qstring = ''; - $base = $COMM_PATH; + $base = $app->comm_path; - if ($task && in_array($task, $MAIN_TASKS)) - $base = ereg_replace('_task=[a-z]+', '_task='.$task, $COMM_PATH); + if ($task && in_array($task, rcmail::$main_tasks)) + $base = ereg_replace('_task=[a-z]+', '_task='.$task, $app->comm_path); if (is_array($p)) foreach ($p as $key => $val) @@ -752,126 +184,9 @@ function rcmail_url($action, $p=array(), $task=null) } -// @deprecated -function show_message($message, $type='notice', $vars=NULL) - { - global $OUTPUT; - $OUTPUT->show_message($message, $type, $vars); - } - - -/** - * Encrypt IMAP password using DES encryption - * - * @param string Password to encrypt - * @return string Encryprted string - */ -function encrypt_passwd($pass) -{ - if (function_exists('mcrypt_module_open') && ($td = mcrypt_module_open(MCRYPT_TripleDES, "", MCRYPT_MODE_ECB, ""))) { - $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND); - mcrypt_generic_init($td, get_des_key(), $iv); - $cypher = mcrypt_generic($td, $pass); - mcrypt_generic_deinit($td); - mcrypt_module_close($td); - } - else if (function_exists('des')) { - $cypher = des(get_des_key(), $pass, 1, 0, NULL); - } - else { - $cypher = $pass; - - raise_error(array( - 'code' => 500, - 'type' => 'php', - 'file' => __FILE__, - 'message' => "Could not convert encrypt password. Make sure Mcrypt is installed or lib/des.inc is available" - ), true, false); - } - - return base64_encode($cypher); -} - - -/** - * Decrypt IMAP password using DES encryption - * - * @param string Encrypted password - * @return string Plain password - */ -function decrypt_passwd($cypher) -{ - if (function_exists('mcrypt_module_open') && ($td = mcrypt_module_open(MCRYPT_TripleDES, "", MCRYPT_MODE_ECB, ""))) { - $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND); - mcrypt_generic_init($td, get_des_key(), $iv); - $pass = mdecrypt_generic($td, base64_decode($cypher)); - mcrypt_generic_deinit($td); - mcrypt_module_close($td); - } - else if (function_exists('des')) { - $pass = des(get_des_key(), base64_decode($cypher), 0, 0, NULL); - } - else { - $pass = base64_decode($cypher); - } - - return preg_replace('/\x00/', '', $pass); - } - - -/** - * Return a 24 byte key for the DES encryption - * - * @return string DES encryption key - */ -function get_des_key() - { - $key = !empty($GLOBALS['CONFIG']['des_key']) ? $GLOBALS['CONFIG']['des_key'] : 'rcmail?24BitPwDkeyF**ECB'; - $len = strlen($key); - - // make sure the key is exactly 24 chars long - if ($len<24) - $key .= str_repeat('_', 24-$len); - else if ($len>24) - substr($key, 0, 24); - - return $key; - } - - -/** - * Read directory program/localization and return a list of available languages - * - * @return array List of available localizations - */ -function rcube_list_languages() - { - global $CONFIG, $INSTALL_PATH; - static $sa_languages = array(); - - if (!sizeof($sa_languages)) - { - @include($INSTALL_PATH.'program/localization/index.inc'); - - if ($dh = @opendir($INSTALL_PATH.'program/localization')) - { - while (($name = readdir($dh)) !== false) - { - if ($name{0}=='.' || !is_dir($INSTALL_PATH.'program/localization/'.$name)) - continue; - - if ($label = $rcube_languages[$name]) - $sa_languages[$name] = $label ? $label : $name; - } - closedir($dh); - } - } - return $sa_languages; - } - - /** * Add a localized label to the client environment + * @deprecated */ function rcube_add_label() { @@ -879,7 +194,7 @@ function rcube_add_label() $arg_list = func_get_args(); foreach ($arg_list as $i => $name) - $OUTPUT->command('add_label', $name, rcube_label($name)); + $OUTPUT->add_label($name); } @@ -939,8 +254,7 @@ function rcmail_message_cache_gc() */ function rcube_charset_convert($str, $from, $to=NULL) { - global $MBSTRING; - static $convert_warning = false; + static $mbstring_loaded = null, $convert_warning = false; $from = strtoupper($from); $to = $to==NULL ? strtoupper(RCMAIL_CHARSET) : strtoupper($to); @@ -961,11 +275,21 @@ function rcube_charset_convert($str, $from, $to=NULL) if (function_exists('iconv') && $from != 'UTF-7' && $to != 'UTF-7') { $aliases['GB2312'] = 'GB18030'; - return iconv(($aliases[$from] ? $aliases[$from] : $from), ($aliases[$to] ? $aliases[$to] : $to) . "//IGNORE", $str); + $_iconv = iconv(($aliases[$from] ? $aliases[$from] : $from), ($aliases[$to] ? $aliases[$to] : $to) . "//IGNORE", $str); + if ($_iconv !== false) + { + return $_iconv; + } } - // convert charset using mbstring module - if ($MBSTRING) + // settings for mbstring module (by Tadashi Jokagi) + if (is_null($mbstring_loaded)) { + if ($mbstring_loaded = extension_loaded("mbstring")) + mb_internal_encoding(RCMAIL_CHARSET); + } + + // convert charset using mbstring module + if ($mbstring_loaded) { $aliases['UTF-7'] = 'UTF7-IMAP'; $aliases['WINDOWS-1257'] = 'ISO-8859-13'; @@ -1034,9 +358,16 @@ function rcube_charset_convert($str, $from, $to=NULL) */ function rep_specialchars_output($str, $enctype='', $mode='', $newlines=TRUE) { - global $OUTPUT_TYPE, $OUTPUT; - static $html_encode_arr, $js_rep_table, $xml_rep_table; - + global $OUTPUT; + static $html_encode_arr = false; + static $js_rep_table = false; + static $xml_rep_table = false; + + $charset = $OUTPUT->get_charset(); + $is_iso_8859_1 = false; + if ($charset == 'ISO-8859-1') { + $is_iso_8859_1 = true; + } if (!$enctype) $enctype = $GLOBALS['OUTPUT_TYPE']; @@ -1077,7 +408,7 @@ function rep_specialchars_output($str, $enctype='', $mode='', $newlines=TRUE) return rawurlencode($str); // if the replace tables for XML and JS are not yet defined - if (!$js_rep_table) + if ($js_rep_table===false) { $js_rep_table = $xml_rep_table = array(); $xml_rep_table['&'] = '&'; @@ -1086,7 +417,7 @@ function rep_specialchars_output($str, $enctype='', $mode='', $newlines=TRUE) { $xml_rep_table[Chr($c)] = "&#$c;"; - if ($OUTPUT->get_charset()=='ISO-8859-1') + if ($is_iso_8859_1) $js_rep_table[Chr($c)] = sprintf("\\u%04x", $c); } @@ -1100,10 +431,10 @@ function rep_specialchars_output($str, $enctype='', $mode='', $newlines=TRUE) // encode for javascript use if ($enctype=='js') { - if ($OUTPUT->get_charset()!='UTF-8') - $str = rcube_charset_convert($str, RCMAIL_CHARSET, $OUTPUT->get_charset()); + if ($charset!='UTF-8') + $str = rcube_charset_convert($str, RCMAIL_CHARSET,$charset); - return preg_replace(array("/\r?\n/", "/\r/"), array('\n', '\n'), addslashes(strtr($str, $js_rep_table))); + return preg_replace(array("/\r?\n/", "/\r/", '/<\\//'), array('\n', '\n', '<\\/'), addslashes(strtr($str, $js_rep_table))); } // no encoding given -> return original string @@ -1228,16 +559,6 @@ function template_exists($name) } -/** - * Wrapper for rcmail_template::parse() - * @deprecated - */ -function parse_template($name='main', $exit=true) - { - $GLOBALS['OUTPUT']->parse($name, $exit); - } - - /** * Create a HTML table based on the given data * @@ -1290,7 +611,7 @@ function rcube_table_output($attrib, $table_data, $a_show_cols, $id_col) { $zebra_class = $c%2 ? 'even' : 'odd'; - $table .= sprintf(''."\n", $row_data[$id_col]); + $table .= sprintf(''."\n", $row_data[$id_col]); // format each col foreach ($a_show_cols as $col) @@ -1328,15 +649,15 @@ function rcmail_get_edit_field($col, $value, $attrib, $type='text') if ($type=='checkbox') { $attrib['value'] = '1'; - $input = new checkbox($attrib); + $input = new html_checkbox($attrib); } else if ($type=='textarea') { $attrib['cols'] = $attrib['size']; - $input = new textarea($attrib); + $input = new html_textarea($attrib); } else - $input = new textfield($attrib); + $input = new html_inputfield($attrib); // use value from post if (!empty($_POST[$fname])) @@ -1468,12 +789,14 @@ function create_attrib_string($attrib, $allowed_attribs=array('id', 'class', 'st function parse_attrib_string($str) { $attrib = array(); - preg_match_all('/\s*([-_a-z]+)=(["\'])([^"]+)\2/Ui', stripslashes($str), $regs, PREG_SET_ORDER); + preg_match_all('/\s*([-_a-z]+)=(["\'])??(?(2)([^\2]+)\2|(\S+?))/Ui', stripslashes($str), $regs, PREG_SET_ORDER); // convert attributes to an associative array (name => value) if ($regs) foreach ($regs as $attr) - $attrib[strtolower($attr[1])] = $attr[3]; + { + $attrib[strtolower($attr[1])] = $attr[3] . $attr[4]; + } return $attrib; } @@ -1489,15 +812,25 @@ function parse_attrib_string($str) */ function format_date($date, $format=NULL) { - global $CONFIG, $sess_user_lang; + global $CONFIG; $ts = NULL; - + if (is_numeric($date)) $ts = $date; else if (!empty($date)) - $ts = @strtotime($date); - + { + while (($ts = @strtotime($date))===false) + { + // if we have a date in non-rfc format + // remove token from the end and try again + $d = explode(' ', $date); + array_pop($d); + if (!$d) break; + $date = implode(' ', $d); + } + } + if (empty($ts)) return ''; @@ -1549,7 +882,7 @@ function format_date($date, $format=NULL) $out .= rcube_label(strtolower(date('M', $timestamp))); // month name (long) else if ($format{$i}=='F') - $out .= rcube_label(strtolower(date('F', $timestamp))); + $out .= rcube_label('long'.strtolower(date('M', $timestamp))); else $out .= date($format{$i}, $timestamp); } @@ -1593,7 +926,7 @@ function console($msg) if (!($GLOBALS['CONFIG']['debug_level'] & 4)) write_log('console', $msg); - else if ($GLOBALS['REMOTE_REQUEST']) + else if ($GLOBALS['OUTPUT']->ajax_call) print "/*\n $msg \n*/\n"; else { @@ -1608,12 +941,12 @@ function console($msg) * Append a line to a logfile in the logs directory. * Date will be added automatically to the line. * - * @param $name Name of logfile - * @param $line Line to append + * @param $name name of log file + * @param line Line to append */ function write_log($name, $line) { - global $CONFIG, $INSTALL_PATH; + global $CONFIG; if (!is_string($line)) $line = var_export($line, true); @@ -1623,7 +956,7 @@ function write_log($name, $line) $line); if (empty($CONFIG['log_dir'])) - $CONFIG['log_dir'] = $INSTALL_PATH.'logs'; + $CONFIG['log_dir'] = INSTALL_PATH.'logs'; // try to open specific log file for writing if ($fp = @fopen($CONFIG['log_dir'].'/'.$name, 'a')) @@ -1811,7 +1144,7 @@ function rcmail_render_folder_tree_html(&$arrFolders, &$mbox_name, $maxlength, $ $class_name = 'junk'; $js_name = htmlspecialchars(JQ($folder['id'])); - $out .= sprintf('
    • $folder['id']))), JS_OBJECT_NAME, @@ -1848,7 +1180,7 @@ function rcmail_render_folder_tree_html(&$arrFolders, &$mbox_name, $maxlength, $ * Return html for a flat list
    • '); - - $this->write(trim($this->parse_with_globals($output)), $skin_path); - - if ($exit) - exit; - } - - - /** - * Return executable javascript code for all registered commands - * @access private - */ - function get_js_commands() - { - $out = ''; - if (!$this->framed && !empty($this->js_env)) - $out .= ($this->ajax_call ? 'this' : JS_OBJECT_NAME) . '.set_env('.json_serialize($this->js_env).");\n"; - - // add command to set page title - if ($this->ajax_call && !empty($this->pagetitle)) - $out .= sprintf( - "this.set_pagetitle('%s');\n", - JQ((!empty($this->config['product_name']) ? $this->config['product_name'].' :: ' : '') . $this->pagetitle) - ); - - foreach ($this->js_commands as $i => $args) - { - $method = array_shift($args); - foreach ($args as $i => $arg) - $args[$i] = json_serialize($arg); - - $parent = $this->framed || preg_match('/^parent\./', $method); - $out .= sprintf( - "%s.%s(%s);\n", - $this->ajax_call ? 'this' : ($parent ? 'parent.' : '') . JS_OBJECT_NAME, - preg_replace('/^parent\./', '', $method), - join(',', $args)); - } - - - - return $out; - } - - /** - * Make URLs starting with a slash point to skin directory - * @access private - */ - function abs_url($str) - { - return preg_replace('/^\//', $this->config['skin_path'].'/', $str); - } - - - - /***** Template parsing methods *****/ - - /** - * Replace all strings ($varname) - * with the content of the according global variable. - * @access private - */ - function parse_with_globals($input) - { - $GLOBALS['__comm_path'] = Q($GLOBALS['COMM_PATH']); - return preg_replace('/\$(__[a-z0-9_\-]+)/e', '$GLOBALS["\\1"]', $input); - } - - - /** - * Parse for conditional tags - * @access private - */ - function parse_conditions($input) - { - if (($matches = preg_split('/]+)>/is', $input, 2, PREG_SPLIT_DELIM_CAPTURE)) && count($matches)==4) - { - if (preg_match('/^(else|endif)$/i', $matches[1])) - return $matches[0] . $this->parse_conditions($matches[3]); - else - { - $attrib = parse_attrib_string($matches[2]); - if (isset($attrib['condition'])) - { - $condmet = $this->check_condition($attrib['condition']); - $submatches = preg_split('/]+)>/is', $matches[3], 2, PREG_SPLIT_DELIM_CAPTURE); - - if ($condmet) - $result = $submatches[0] . ($submatches[1] != 'endif' ? preg_replace('/.*]+>/Uis', '', $submatches[3], 1) : $submatches[3]); - else - $result = "" . $submatches[3]; - - return $matches[0] . $this->parse_conditions($result); - } - else - { - raise_error(array('code' => 500, 'type' => 'php', 'line' => __LINE__, 'file' => __FILE__, - 'message' => "Unable to parse conditional tag " . $matches[2]), TRUE, FALSE); - } - } - } - - return $input; - } - - - /** - * Determines if a given condition is met - * - * @return True if condition is valid, False is not - * @access private - */ - function check_condition($condition) - { - $condition = preg_replace( - array('/session:([a-z0-9_]+)/i', '/config:([a-z0-9_]+)/i', '/env:([a-z0-9_]+)/i', '/request:([a-z0-9_]+)/ie'), - array("\$_SESSION['\\1']", "\$this->config['\\1']", "\$this->env['\\1']", "get_input_value('\\1', RCUBE_INPUT_GPC)"), - $condition); - - return @eval("return (".$condition.");"); - } - - - /** - * Search for special tags in input and replace them - * with the appropriate content - * - * @param string Input string to parse - * @return Altered input string - * @access private - */ - function parse_xml($input) - { - return preg_replace('/]+)>/Uie', "\$this->xml_command('\\1', '\\2')", $input); - } - - - /** - * Convert a xml command tag into real content - * - * @param string Tag command: object,button,label, etc. - * @param string Attribute string - * @return Tag/Object content string - * @access private - */ - function xml_command($command, $str_attrib, $add_attrib=array()) - { - $command = strtolower($command); - $attrib = parse_attrib_string($str_attrib) + $add_attrib; - - // empty output if required condition is not met - if (!empty($attrib['condition']) && !$this->check_condition($attrib['condition'])) - return ''; - - // execute command - switch ($command) - { - // return a button - case 'button': - return $this->button($attrib); - break; - - // show a label - case 'label': - if ($attrib['name'] || $attrib['command']) - return Q(rcube_label($attrib + array('vars' => array('product' => $this->config['product_name'])))); - break; - - // include a file - case 'include': - $path = realpath($this->config['skin_path'].$attrib['file']); - if (filesize($path)) - { - if ($this->config['skin_include_php']) - $incl = $this->include_php($path); - else if ($fp = @fopen($path, 'r')) - { - $incl = fread($fp, filesize($path)); - fclose($fp); - } - return $this->parse_xml($incl); - } - break; - - // return code for a specific application object - case 'object': - $object = strtolower($attrib['name']); - - // execute object handler function - if ($this->object_handlers[$object] && function_exists($this->object_handlers[$object])) - return call_user_func($this->object_handlers[$object], $attrib); - - else if ($object=='productname') - { - $name = !empty($this->config['product_name']) ? $this->config['product_name'] : 'RoundCube Webmail'; - return Q($name); - } - else if ($object=='version') - { - return (string)RCMAIL_VERSION; - } - else if ($object=='pagetitle') - { - $task = $this->task; - $title = !empty($this->config['product_name']) ? $this->config['product_name'].' :: ' : ''; - - if (!empty($this->pagetitle)) - $title .= $this->pagetitle; - else if ($task == 'login') - $title = rcube_label(array('name' => 'welcome', 'vars' => array('product' => $this->config['product_name']))); - else - $title .= ucfirst($task); - - return Q($title); - } - - break; - - // return variable - case 'var': - $var = explode(':', $attrib['name']); - $name = $var[1]; - $value = ''; - - switch ($var[0]) - { - case 'env': - $value = $this->env[$name]; - break; - case 'config': - $value = $this->config[$name]; - if (is_array($value) && $value[$_SESSION['imap_host']]) - $value = $value[$_SESSION['imap_host']]; - break; - case 'request': - $value = get_input_value($name, RCUBE_INPUT_GPC); - break; - case 'session': - $value = $_SESSION[$name]; - break; - } - - if (is_array($value)) - $value = join(", ", $value); - - return Q($value); - } - - return ''; - } - - - /** - * Include a specific file and return it's contents - * - * @param string File path - * @return string Contents of the processed file - */ - function include_php($file) - { - ob_start(); - @include($file); - $out = ob_get_contents(); - ob_end_clean(); - - return $out; - } - - - /** - * Create and register a button - * - * @param array Button attributes - * @return HTML button - * @access private - */ - function button($attrib) - { - global $CONFIG, $OUTPUT, $BROWSER, $MAIN_TASKS; - static $sa_buttons = array(); - static $s_button_count = 100; - - // these commands can be called directly via url - $a_static_commands = array('compose', 'list'); - - $skin_path = $this->config['skin_path']; - - if (!($attrib['command'] || $attrib['name'] || $attrib['onclick'])) - return ''; - - // try to find out the button type - if ($attrib['type']) - $attrib['type'] = strtolower($attrib['type']); - else - $attrib['type'] = ($attrib['image'] || $attrib['imagepas'] || $attrib['imageact']) ? 'image' : 'link'; - - $command = $attrib['command']; - - // take the button from the stack - if($attrib['name'] && $sa_buttons[$attrib['name']]) - $attrib = $sa_buttons[$attrib['name']]; - - // add button to button stack - else if($attrib['image'] || $attrib['imageact'] || $attrib['imagepas'] || $attrib['class']) - { - if (!$attrib['name']) - $attrib['name'] = $command; - - if (!$attrib['image']) - $attrib['image'] = $attrib['imagepas'] ? $attrib['imagepas'] : $attrib['imageact']; - - $sa_buttons[$attrib['name']] = $attrib; - } - - // get saved button for this command/name - else if ($command && $sa_buttons[$command]) - $attrib = $sa_buttons[$command]; - - //else - // return ''; - - - // set border to 0 because of the link arround the button - if ($attrib['type']=='image' && !isset($attrib['border'])) - $attrib['border'] = 0; - - if (!$attrib['id']) - $attrib['id'] = sprintf('rcmbtn%d', $s_button_count++); - - // get localized text for labels and titles - if ($attrib['title']) - $attrib['title'] = Q(rcube_label($attrib['title'])); - if ($attrib['label']) - $attrib['label'] = Q(rcube_label($attrib['label'])); - - if ($attrib['alt']) - $attrib['alt'] = Q(rcube_label($attrib['alt'])); - - // set title to alt attribute for IE browsers - if ($BROWSER['ie'] && $attrib['title'] && !$attrib['alt']) - { - $attrib['alt'] = $attrib['title']; - unset($attrib['title']); - } - - // add empty alt attribute for XHTML compatibility - if (!isset($attrib['alt'])) - $attrib['alt'] = ''; - - - // register button in the system - if ($attrib['command']) - { - $this->add_script(sprintf( - "%s.register_button('%s', '%s', '%s', '%s', '%s', '%s');", - JS_OBJECT_NAME, - $command, - $attrib['id'], - $attrib['type'], - $attrib['imageact'] ? $skin_path.$attrib['imageact'] : $attrib['classact'], - $attrib['imagesel'] ? $skin_path.$attrib['imagesel'] : $attrib['classsel'], - $attrib['imageover'] ? $skin_path.$attrib['imageover'] : '') - ); - - // make valid href to specific buttons - if (in_array($attrib['command'], $MAIN_TASKS)) - $attrib['href'] = Q(rcmail_url(null, null, $attrib['command'])); - else if (in_array($attrib['command'], $a_static_commands)) - $attrib['href'] = Q(rcmail_url($attrib['command'])); - } - - // overwrite attributes - if (!$attrib['href']) - $attrib['href'] = '#'; - - if ($command) - $attrib['onclick'] = sprintf("return %s.command('%s','%s',this)", JS_OBJECT_NAME, $command, $attrib['prop']); - - if ($command && $attrib['imageover']) - { - $attrib['onmouseover'] = sprintf("return %s.button_over('%s','%s')", JS_OBJECT_NAME, $command, $attrib['id']); - $attrib['onmouseout'] = sprintf("return %s.button_out('%s','%s')", JS_OBJECT_NAME, $command, $attrib['id']); - } - - if ($command && $attrib['imagesel']) - { - $attrib['onmousedown'] = sprintf("return %s.button_sel('%s','%s')", JS_OBJECT_NAME, $command, $attrib['id']); - $attrib['onmouseup'] = sprintf("return %s.button_out('%s','%s')", JS_OBJECT_NAME, $command, $attrib['id']); - } - - $out = ''; - - // generate image tag - if ($attrib['type']=='image') - { - $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id', 'width', 'height', 'border', 'hspace', 'vspace', 'align', 'alt')); - $img_tag = sprintf('', $attrib_str); - $btn_content = sprintf($img_tag, $skin_path.$attrib['image']); - if ($attrib['label']) - $btn_content .= ' '.$attrib['label']; - - $link_attrib = array('href', 'onclick', 'onmouseover', 'onmouseout', 'onmousedown', 'onmouseup', 'title'); - } - else if ($attrib['type']=='link') - { - $btn_content = $attrib['label'] ? $attrib['label'] : $attrib['command']; - $link_attrib = array('href', 'onclick', 'title', 'id', 'class', 'style'); - } - else if ($attrib['type']=='input') - { - $attrib['type'] = 'button'; - - if ($attrib['label']) - $attrib['value'] = $attrib['label']; - - $attrib_str = create_attrib_string($attrib, array('type', 'value', 'onclick', 'id', 'class', 'style')); - $out = sprintf('', $attrib_str); - } - - // generate html code for button - if ($btn_content) - { - $attrib_str = create_attrib_string($attrib, $link_attrib); - $out = sprintf('%s', $attrib_str, $btn_content); - } - - return $out; - } - -} // end class rcmail_template - - - -// ************** common functions delivering gui objects ************** - - -/** - * Builder for GUI object 'message' - * - * @param array Named tag parameters - * @return string HTML code for the gui object - */ -function rcmail_message_container($attrib) - { - global $OUTPUT; - - if (!$attrib['id']) - $attrib['id'] = 'rcmMessageContainer'; - - // allow the following attributes to be added to the tag - $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id')); - $out = '"; - - $OUTPUT->add_gui_object('message', $attrib['id']); - - return $out; - } - - -/** - * GUI object 'username' - * Showing IMAP username of the current session - * - * @param array Named tag parameters (currently not used) - * @return string HTML code for the gui object - */ -function rcmail_current_username($attrib) - { - global $USER; - static $s_username; - - // alread fetched - if (!empty($s_username)) - return $s_username; - - if ($sql_arr = $USER->get_identity()) - $s_username = $sql_arr['email']; - else if (strstr($_SESSION['username'], '@')) - $s_username = $_SESSION['username']; - else - $s_username = $_SESSION['username'].'@'.$_SESSION['imap_host']; - - return $s_username; - } - - -/** - * GUI object 'loginform' - * Returns code for the webmail login form - * - * @param array Named parameters - * @return string HTML code for the gui object - */ -function rcmail_login_form($attrib) - { - global $CONFIG, $OUTPUT, $SESS_HIDDEN_FIELD; - - $labels = array(); - $labels['user'] = rcube_label('username'); - $labels['pass'] = rcube_label('password'); - $labels['host'] = rcube_label('server'); - - $input_user = new textfield(array('name' => '_user', 'id' => 'rcmloginuser', 'size' => 30) + $attrib); - $input_pass = new passwordfield(array('name' => '_pass', 'id' => 'rcmloginpwd', 'size' => 30) + $attrib); - $input_action = new hiddenfield(array('name' => '_action', 'value' => 'login')); - - $fields = array(); - $fields['user'] = $input_user->show(get_input_value('_user', RCUBE_INPUT_POST)); - $fields['pass'] = $input_pass->show(); - $fields['action'] = $input_action->show(); - - if (is_array($CONFIG['default_host'])) - { - $select_host = new select(array('name' => '_host', 'id' => 'rcmloginhost')); - - foreach ($CONFIG['default_host'] as $key => $value) - { - if (!is_array($value)) - $select_host->add($value, (is_numeric($key) ? $value : $key)); - else - { - unset($select_host); - break; - } - } - - $fields['host'] = isset($select_host) ? $select_host->show(get_input_value('_host', RCUBE_INPUT_POST)) : null; - } - else if (!strlen($CONFIG['default_host'])) - { - $input_host = new textfield(array('name' => '_host', 'id' => 'rcmloginhost', 'size' => 30)); - $fields['host'] = $input_host->show(get_input_value('_host', RCUBE_INPUT_POST)); - } - - $form_name = strlen($attrib['form']) ? $attrib['form'] : 'form'; - $form_start = !strlen($attrib['form']) ? '
      ' : ''; - $form_end = !strlen($attrib['form']) ? '' : ''; - - if ($fields['host']) - $form_host = <<
      - - - - -EOF; - - $OUTPUT->add_gui_object('loginform', $form_name); - - $out = << - - - - - - - - -$form_host -
      $fields[host]
      $fields[user]
      $fields[pass]
      -$form_end -EOF; - - return $out; - } - - -/** - * GUI object 'charsetselector' - * - * @param array Named parameters for the select tag - * @return string HTML code for the gui object - */ -function rcmail_charset_selector($attrib) - { - global $OUTPUT; - - // pass the following attributes to the form class - $field_attrib = array('name' => '_charset'); - foreach ($attrib as $attr => $value) - if (in_array($attr, array('id', 'class', 'style', 'size', 'tabindex'))) - $field_attrib[$attr] = $value; - - $charsets = array( - 'US-ASCII' => 'ASCII (English)', - 'EUC-JP' => 'EUC-JP (Japanese)', - 'EUC-KR' => 'EUC-KR (Korean)', - 'BIG5' => 'BIG5 (Chinese)', - 'GB2312' => 'GB2312 (Chinese)', - 'ISO-2022-JP' => 'ISO-2022-JP (Japanese)', - 'ISO-8859-1' => 'ISO-8859-1 (Latin-1)', - 'ISO-8859-2' => 'ISO-8895-2 (Central European)', - 'ISO-8859-7' => 'ISO-8859-7 (Greek)', - 'ISO-8859-9' => 'ISO-8859-9 (Turkish)', - 'Windows-1251' => 'Windows-1251 (Cyrillic)', - 'Windows-1252' => 'Windows-1252 (Western)', - 'Windows-1255' => 'Windows-1255 (Hebrew)', - 'Windows-1256' => 'Windows-1256 (Arabic)', - 'Windows-1257' => 'Windows-1257 (Baltic)', - 'UTF-8' => 'UTF-8' - ); - - $select = new select($field_attrib); - $select->add(array_values($charsets), array_keys($charsets)); - - $set = $_POST['_charset'] ? $_POST['_charset'] : $OUTPUT->get_charset(); - return $select->show($set); - } - - -/** - * GUI object 'searchform' - * Returns code for search function - * - * @param array Named parameters - * @return string HTML code for the gui object - */ -function rcmail_search_form($attrib) - { - global $OUTPUT; - - // add some labels to client - rcube_add_label('searching'); - - $attrib['name'] = '_q'; - - if (empty($attrib['id'])) - $attrib['id'] = 'rcmqsearchbox'; - - $input_q = new textfield($attrib); - $out = $input_q->show(); - - $OUTPUT->add_gui_object('qsearchbox', $attrib['id']); - - // add form tag around text field - if (empty($attrib['form'])) - $out = sprintf( - '
      %s
      ', - JS_OBJECT_NAME, - $out); - - return $out; - } - - -?> diff --git a/program/include/rcube_browser.php b/program/include/rcube_browser.php new file mode 100644 index 0000000..af393d6 --- /dev/null +++ b/program/include/rcube_browser.php @@ -0,0 +1,75 @@ + | + +-----------------------------------------------------------------------+ + + $Id: rcube_browser.php 328 2006-08-30 17:41:21Z thomasb $ + +*/ + +/** + * rcube_browser + * + * Provide details about the client's browser based on the User-Agent header + * + * @package Core + */ +class rcube_browser +{ + function __construct() + { + $HTTP_USER_AGENT = $_SERVER['HTTP_USER_AGENT']; + + $this->ver = 0; + $this->win = stristr($HTTP_USER_AGENT, 'win'); + $this->mac = stristr($HTTP_USER_AGENT, 'mac'); + $this->linux = stristr($HTTP_USER_AGENT, 'linux'); + $this->unix = stristr($HTTP_USER_AGENT, 'unix'); + + $this->ns4 = stristr($HTTP_USER_AGENT, 'mozilla/4') && !stristr($HTTP_USER_AGENT, 'msie'); + $this->ns = ($this->ns4 || stristr($HTTP_USER_AGENT, 'netscape')); + $this->ie = stristr($HTTP_USER_AGENT, 'msie'); + $this->mz = stristr($HTTP_USER_AGENT, 'mozilla/5'); + $this->opera = stristr($HTTP_USER_AGENT, 'opera'); + $this->safari = stristr($HTTP_USER_AGENT, 'safari'); + + if ($this->ns) { + $test = eregi("mozilla\/([0-9\.]+)", $HTTP_USER_AGENT, $regs); + $this->ver = $test ? (float)$regs[1] : 0; + } + if ($this->mz) { + $test = ereg("rv:([0-9\.]+)", $HTTP_USER_AGENT, $regs); + $this->ver = $test ? (float)$regs[1] : 0; + } + if($this->ie) { + $test = eregi("msie ([0-9\.]+)", $HTTP_USER_AGENT, $regs); + $this->ver = $test ? (float)$regs[1] : 0; + } + if ($this->opera) { + $test = eregi("opera ([0-9\.]+)", $HTTP_USER_AGENT, $regs); + $this->ver = $test ? (float)$regs[1] : 0; + } + + if (eregi(" ([a-z]{2})-([a-z]{2})", $HTTP_USER_AGENT, $regs)) + $this->lang = $regs[1]; + else + $this->lang = 'en'; + + $this->dom = ($this->mz || $this->safari || ($this->ie && $this->ver>=5) || ($this->opera && $this->ver>=7)); + $this->pngalpha = $this->mz || $this->safari || ($this->ie && $this->ver>=5.5) || + ($this->ie && $this->ver>=5 && $this->mac) || ($this->opera && $this->ver>=7) ? true : false; + } + } + diff --git a/program/include/rcube_config.php b/program/include/rcube_config.php new file mode 100644 index 0000000..8e956de --- /dev/null +++ b/program/include/rcube_config.php @@ -0,0 +1,181 @@ + | + +-----------------------------------------------------------------------+ + + $Id: $ + +*/ + +/** + * Configuration class for RoundCube + * + * @package Core + */ +class rcube_config +{ + private $prop = array(); + + + /** + * Object constructor + */ + public function __construct() + { + $this->load(); + } + + + /** + * Load config from local config file + * + * @todo Remove global $CONFIG + */ + private function load() + { + // start output buffering, we don't need any output yet, + // it'll be cleared after reading of config files, etc. + ob_start(); + + // load main config file + include_once(INSTALL_PATH . 'config/main.inc.php'); + $this->prop = (array)$rcmail_config; + + // load database config + include_once(INSTALL_PATH . 'config/db.inc.php'); + $this->prop += (array)$rcmail_config; + + // load host-specific configuration + $this->load_host_config(); + + // fix paths + $this->prop['skin_path'] = $this->prop['skin_path'] ? unslashify($this->prop['skin_path']) : 'skins/default'; + $this->prop['log_dir'] = $this->prop['log_dir'] ? unslashify($this->prop['log_dir']) : INSTALL_PATH . 'logs'; + + // handle aliases + if (isset($this->prop['locale_string']) && empty($this->prop['language'])) + $this->prop['language'] = $this->prop['locale_string']; + + // set PHP error logging according to config + if ($this->prop['debug_level'] & 1) { + ini_set('log_errors', 1); + ini_set('error_log', $this->prop['log_dir'] . '/errors'); + } + if ($this->prop['debug_level'] & 4) { + ini_set('display_errors', 1); + } + else { + ini_set('display_errors', 0); + } + + // clear output buffer + ob_end_clean(); + + // export config data + $GLOBALS['CONFIG'] = &$this->prop; + } + + + /** + * Load a host-specific config file if configured + * This will merge the host specific configuration with the given one + */ + private function load_host_config() + { + $fname = null; + + if (is_array($this->prop['include_host_config'])) { + $fname = $this->prop['include_host_config'][$_SERVER['HTTP_HOST']]; + } + else if (!empty($this->prop['include_host_config'])) { + $fname = preg_replace('/[^a-z0-9\.\-_]/i', '', $_SERVER['HTTP_HOST']) . '.inc.php'; + } + + if ($fname && is_file(INSTALL_PATH . 'config/' . $fname)) { + include(INSTALL_PATH . 'config/' . $fname); + $this->prop = array_merge($this->prop, (array)$rcmail_config); + } + } + + + /** + * Getter for a specific config parameter + * + * @param string Parameter name + * @param mixed Default value if not set + * @return mixed The requested config value + */ + public function get($name, $def = null) + { + return isset($this->prop[$name]) ? $this->prop[$name] : $def; + } + + + /** + * Setter for a config parameter + * + * @param string Parameter name + * @param mixed Parameter value + */ + public function set($name, $value) + { + $this->prop[$name] = $value; + } + + + /** + * Override config options with the given values (eg. user prefs) + * + * @param array Hash array with config props to merge over + */ + public function merge($prefs) + { + $this->prop = array_merge($this->prop, $prefs); + } + + + /** + * Getter for all config options + * + * @return array Hash array containg all config properties + */ + public function all() + { + return $this->prop; + } + + + /** + * Return a 24 byte key for the DES encryption + * + * @return string DES encryption key + */ + public function get_des_key() + { + $key = !empty($this->prop['des_key']) ? $this->prop['des_key'] : 'rcmail?24BitPwDkeyF**ECB'; + $len = strlen($key); + + // make sure the key is exactly 24 chars long + if ($len<24) + $key .= str_repeat('_', 24-$len); + else if ($len>24) + substr($key, 0, 24); + + return $key; + } + + +} + diff --git a/program/include/rcube_contacts.inc b/program/include/rcube_contacts.php similarity index 90% rename from program/include/rcube_contacts.inc rename to program/include/rcube_contacts.php index 6a48656..913f04f 100644 --- a/program/include/rcube_contacts.inc +++ b/program/include/rcube_contacts.php @@ -2,10 +2,10 @@ /* +-----------------------------------------------------------------------+ - | program/include/rcube_contacts.inc | + | program/include/rcube_contacts.php | | | | This file is part of the RoundCube Webmail client | - | Copyright (C) 2006-2007, RoundCube Dev. - Switzerland | + | Copyright (C) 2006-2008, RoundCube Dev. - Switzerland | | Licensed under the GNU GPL | | | | PURPOSE: | @@ -393,66 +393,8 @@ class rcube_contacts */ function delete_all() { - if (is_array($ids)) - $ids = join(',', $ids); - - $this->db->query("DELETE FROM {$this->db_name} WHERE user_id=?", $this->user_id); + $this->db->query("DELETE FROM {$this->db_name} WHERE user_id=?", $this->user_id); return $this->db->affected_rows(); } } - - -/** - * RoundCube result set class. - * Representing an address directory result set. - */ -class rcube_result_set -{ - var $count = 0; - var $first = 0; - var $current = 0; - var $records = array(); - - function __construct($c=0, $f=0) - { - $this->count = (int)$c; - $this->first = (int)$f; - } - - function rcube_result_set($c=0, $f=0) - { - $this->__construct($c, $f); - } - - function add($rec) - { - $this->records[] = $rec; - } - - function iterate() - { - return $this->records[$this->current++]; - } - - function first() - { - $this->current = 0; - return $this->records[$this->current++]; - } - - // alias - function next() - { - return $this->iterate(); - } - - function seek($i) - { - $this->current = $i; - } - -} - - -?> \ No newline at end of file diff --git a/program/include/rcube_db.inc b/program/include/rcube_db.php similarity index 98% rename from program/include/rcube_db.inc rename to program/include/rcube_db.php index c84dd84..1b0a19e 100644 --- a/program/include/rcube_db.inc +++ b/program/include/rcube_db.php @@ -2,10 +2,10 @@ /* +-----------------------------------------------------------------------+ - | program/include/rcube_db.inc | + | program/include/rcube_db.php | | | | This file is part of the RoundCube Webmail client | - | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland | + | Copyright (C) 2005-2008, RoundCube Dev. - Switzerland | | Licensed under the GNU GPL | | | | PURPOSE: | @@ -17,16 +17,11 @@ | Thomas Bruederli | +-----------------------------------------------------------------------+ - $Id: rcube_db.inc 1255 2008-04-05 12:49:21Z thomasb $ + $Id: rcube_db.php 1291 2008-04-12 13:54:45Z thomasb $ */ -/** - * Obtain the PEAR::DB class that is used for abstraction - */ -require_once 'DB.php'; - /** * Database independent query interface * @@ -605,4 +600,4 @@ class rcube_db } // end class rcube_db -?> + diff --git a/program/include/rcube_html.inc b/program/include/rcube_html.inc deleted file mode 100644 index d23760a..0000000 --- a/program/include/rcube_html.inc +++ /dev/null @@ -1,667 +0,0 @@ - | - +-----------------------------------------------------------------------+ - - $Id: $ - -*/ - - -/** - * HTML page builder class - * - * @package HTML - */ -class rcube_html_page -{ - var $scripts_path = ''; - var $script_files = array(); - var $scripts = array(); - var $charset = 'UTF-8'; - - var $script_tag_file = "\n"; - var $script_tag = "\n"; - var $default_template = "\n\n\n"; - - var $title = 'RoundCube Mail'; - var $header = ''; - var $footer = ''; - var $body = ''; - var $body_attrib = array(); - var $meta_tags = array(); - - - /** - * Link an external script file - * - * @param string File URL - * @param string Target position [head|foot] - */ - function include_script($file, $position='head') - { - static $sa_files = array(); - - if (in_array($file, $sa_files)) - return; - - if (!is_array($this->script_files[$position])) - $this->script_files[$position] = array(); - - $this->script_files[$position][] = $file; - } - - /** - * Add inline javascript code - * - * @param string JS code snippet - * @param string Target position [head|head_top|foot] - */ - function add_script($script, $position='head') - { - if (!isset($this->scripts[$position])) - $this->scripts[$position] = "\n".rtrim($script); - else - $this->scripts[$position] .= "\n".rtrim($script); - } - - /** - * Add HTML code to the page header - */ - function add_header($str) - { - $this->header .= "\n".$str; - } - - /** - * Add HTML code to the page footer - * To be added right befor - */ - function add_footer($str) - { - $this->footer .= "\n".$str; - } - - /** - * Setter for page title - */ - function set_title($t) - { - $this->title = $t; - } - - - /** - * Setter for output charset. - * To be specified in a meta tag and sent as http-header - */ - function set_charset($charset) - { - global $MBSTRING; - - $this->charset = $charset; - - if ($MBSTRING && function_exists("mb_internal_encoding")) - { - if(!@mb_internal_encoding($charset)) - $MBSTRING = FALSE; - } - } - - /** - * Getter for output charset - */ - function get_charset() - { - return $this->charset; - } - - - /** - * Reset all saved properties - */ - function reset() - { - $this->script_files = array(); - $this->scripts = array(); - $this->title = ''; - $this->header = ''; - $this->footer = ''; - } - - - /** - * Process template and write to stdOut - * - * @param string HTML template - * @param string Base for absolute paths - */ - function write($templ='', $base_path='') - { - $output = empty($templ) ? $this->default_template : trim($templ); - - // replace specialchars in content - $__page_title = Q($this->title, 'show', FALSE); - $__page_header = $__page_body = $__page_footer = ''; - - - // include meta tag with charset - if (!empty($this->charset)) - { - header('Content-Type: text/html; charset='.$this->charset, true); - $__page_header = ''."\n"; - } - - - // definition of the code to be placed in the document header and footer - if (is_array($this->script_files['head'])) - foreach ($this->script_files['head'] as $file) - $__page_header .= sprintf($this->script_tag_file, $this->scripts_path, $file); - - $head_script = $this->scripts['head_top'] . $this->scripts['head']; - if (!empty($head_script)) - $__page_header .= sprintf($this->script_tag, $head_script); - - if (!empty($this->header)) - $__page_header .= $this->header; - - if (is_array($this->script_files['foot'])) - foreach ($this->script_files['foot'] as $file) - $__page_footer .= sprintf($this->script_tag_file, $this->scripts_path, $file); - - if (!empty($this->scripts['foot'])) - $__page_footer .= sprintf($this->script_tag, $this->scripts['foot']); - - if (!empty($this->footer)) - $__page_footer .= $this->footer; - - // find page header - if ($hpos = strpos(strtolower($output), '')) - $__page_header .= "\n"; - else - { - if (!is_numeric($hpos)) - $hpos = strpos(strtolower($output), '')+7; - - // add page body - if($bpos && $__page_body) - $output = substr($output,0,$bpos) . "\n$__page_body\n" . substr($output,$bpos,strlen($output)); - - - // find and add page footer - $output_lc = strtolower($output); - if(($fpos = strrstr($output_lc, '')) || - ($fpos = strrstr($output_lc, ''))) - $output = substr($output, 0, $fpos) . "$__page_footer\n" . substr($output, $fpos); - else - $output .= "\n$__page_footer"; - - - // reset those global vars - $__page_header = $__page_footer = ''; - - - // correct absolute paths in images and other tags - $output = preg_replace('/(src|href|background)=(["\']?)(\/[a-z0-9_\-]+)/Ui', "\\1=\\2$base_path\\3", $output); - $output = str_replace('$__skin_path', $base_path, $output); - - print rcube_charset_convert($output, 'UTF-8', $this->charset); - } - -} // end class rcube_html_page - - - -/** - * Base class to build a HTML for element - * - * @package HTML - */ -class rcube_form_element - { - var $uppertags = FALSE; - var $upperattribs = FALSE; - var $upperprops = FALSE; - var $newline = FALSE; - - var $attrib = array(); - - - /** - * Create string with saved attributes - * - * @return string HTML formatted tag attributes - */ - function create_attrib_string() - { - if (!sizeof($this->attrib)) - return ''; - - if ($this->name!='') - $this->attrib['name'] = $this->name; - - $attrib_arr = array(); - foreach ($this->attrib as $key => $value) - { - // don't output some internally used attributes - if (in_array($key, array('form', 'quicksearch'))) - continue; - - // skip if size if not numeric - if (($key=='size' && !is_numeric($value))) - continue; - - // skip empty eventhandlers - if ((strpos($key,'on')===0 && $value=='')) - continue; - - // attributes with no value - if (in_array($key, array('checked', 'multiple', 'disabled', 'selected', 'nowrap'))) - { - if ($value) - $attrib_arr[] = sprintf('%s="%s"', $this->_conv_case($key, 'attrib'), $key); - } - // don't convert size of value attribute - else if ($key=='value') - $attrib_arr[] = sprintf('%s="%s"', $this->_conv_case($key, 'attrib'), Q($value, 'strict', false)); - - // regular tag attributes - else - $attrib_arr[] = sprintf('%s="%s"', $this->_conv_case($key, 'attrib'), $this->_conv_case(Q($value), 'value')); - } - - return sizeof($attrib_arr) ? ' '.implode(' ', $attrib_arr) : ''; - } - - - /** - * Convert tags and attributes to upper-/lowercase - * - * @param string Input string - * @param string Value type (can either be "tag" or "attrib") - * @return string Converted output string - * @access private - */ - function _conv_case($str, $type='attrib') - { - if ($type == 'tag') - return $this->uppertags ? strtoupper($str) : strtolower($str); - else if ($type == 'attrib') - return $this->upperattribs ? strtoupper($str) : strtolower($str); - else if ($type == 'value') - return $this->upperprops ? strtoupper($str) : strtolower($str); - } - } - - -/** - * Builder for an field - * - * @package HTML - */ -class input_field extends rcube_form_element -{ - var $type = 'text'; - - /** - * Constructor - * @param array Named tag attributes - */ - function input_field($attrib=array()) - { - if (is_array($attrib)) - $this->attrib = $attrib; - - if ($attrib['type']) - $this->type = $attrib['type']; - - if ($attrib['newline']) - $this->newline = TRUE; - } - - /** - * Compose input tag - * - * @param string Field value - * @param array Additional tag attributes - * @return string Final HTML code - */ - function show($value=NULL, $attrib=NULL) - { - // overwrite object attributes - if (is_array($attrib)) - $this->attrib = array_merge($this->attrib, $attrib); - - // set value attribute - if ($value!==NULL) - $this->attrib['value'] = $value; - - $this->attrib['type'] = $this->type; - - // return final tag - return sprintf( - '<%s%s />%s', - $this->_conv_case('input', 'tag'), - $this->create_attrib_string(), - ($this->newline ? "\n" : "")); - } -} - - -/** - * Builder for a field - * - * @package HTML - */ -class textfield extends input_field -{ - var $type = 'text'; -} - -/** - * Builder for a field - * - * @package HTML - */ -class passwordfield extends input_field -{ - var $type = 'password'; -} - -/** - * Builder for fields - * - * @package HTML - */ -class radiobutton extends input_field -{ - var $type = 'radio'; -} - -/** - * Builder for fields - * - * @package HTML - */ -class checkbox extends input_field -{ - var $type = 'checkbox'; - - - /** - * Compose input tag - * - * @param string Field value - * @param array Additional tag attributes - * @return string Final HTML code - */ - function show($value='', $attrib=NULL) - { - // overwrite object attributes - if (is_array($attrib)) - $this->attrib = array_merge($this->attrib, $attrib); - - $this->attrib['type'] = $this->type; - - if ($value && (string)$value==(string)$this->attrib['value']) - $this->attrib['checked'] = TRUE; - else - $this->attrib['checked'] = FALSE; - - // return final tag - return sprintf( - '<%s%s />%s', - $this->_conv_case('input', 'tag'), - $this->create_attrib_string(), - ($this->newline ? "\n" : "")); - } -} - - -/** - * Builder for a ' + ); + } + $output = $this->parse_with_globals($output); + $this->write(trim($output), $skin_path); + if ($exit) { + exit; + } + } + + + /** + * Return executable javascript code for all registered commands + * + * @return string $out + */ + private function get_js_commands() + { + $out = ''; + if (!$this->framed && !empty($this->js_env)) { + $out .= JS_OBJECT_NAME . '.set_env('.json_serialize($this->js_env).");\n"; + } + foreach ($this->js_commands as $i => $args) { + $method = array_shift($args); + foreach ($args as $i => $arg) { + $args[$i] = json_serialize($arg); + } + $parent = $this->framed || preg_match('/^parent\./', $method); + $out .= sprintf( + "%s.%s(%s);\n", + ($parent ? 'parent.' : '') . JS_OBJECT_NAME, + preg_replace('/^parent\./', '', $method), + implode(',', $args) + ); + } + // add command to set page title + if ($this->ajax_call && !empty($this->pagetitle)) { + $out .= sprintf( + "this.set_pagetitle('%s');\n", + JQ((!empty($this->config['product_name']) ? $this->config['product_name'].' :: ' : '') . $this->pagetitle) + ); + } + return $out; + } + + /** + * Make URLs starting with a slash point to skin directory + * + * @param string Input string + * @return string + */ + public function abs_url($str) + { + return preg_replace('/^\//', $this->config['skin_path'].'/', $str); + } + + + /***** Template parsing methods *****/ + + /** + * Replace all strings ($varname) + * with the content of the according global variable. + */ + private function parse_with_globals($input) + { + $GLOBALS['__comm_path'] = Q($this->app->comm_path); + return preg_replace('/\$(__[a-z0-9_\-]+)/e', '$GLOBALS["\\1"]', $input); + } + + /** + * Public wrapper to dipp into template parsing. + * + * @param string $input + * @return string + * @uses rcube_template::parse_xml() + * @since 0.1-rc1 + */ + public function just_parse($input) + { + return $this->parse_xml($input); + } + + /** + * Parse for conditional tags + * + * @param string $input + * @return string + */ + private function parse_conditions($input) + { + $matches = preg_split('/]+)>/is', $input, 2, PREG_SPLIT_DELIM_CAPTURE); + if ($matches && count($matches) == 4) { + if (preg_match('/^(else|endif)$/i', $matches[1])) { + return $matches[0] . $this->parse_conditions($matches[3]); + } + $attrib = parse_attrib_string($matches[2]); + if (isset($attrib['condition'])) { + $condmet = $this->check_condition($attrib['condition']); + $submatches = preg_split('/]+)>/is', $matches[3], 2, PREG_SPLIT_DELIM_CAPTURE); + if ($condmet) { + $result = $submatches[0]; + $result.= ($submatches[1] != 'endif' ? preg_replace('/.*]+>/Uis', '', $submatches[3], 1) : $submatches[3]); + } + else { + $result = "" . $submatches[3]; + } + return $matches[0] . $this->parse_conditions($result); + } + raise_error(array( + 'code' => 500, + 'type' => 'php', + 'line' => __LINE__, + 'file' => __FILE__, + 'message' => "Unable to parse conditional tag " . $matches[2] + ), true, false); + } + return $input; + } + + + /** + * Determines if a given condition is met + * + * @todo Get rid off eval() once I understand what this does. + * @todo Extend this to allow real conditions, not just "set" + * @param string Condition statement + * @return boolean True if condition is met, False is not + */ + private function check_condition($condition) + { + $condition = preg_replace( + array( + '/session:([a-z0-9_]+)/i', + '/config:([a-z0-9_]+)/i', + '/env:([a-z0-9_]+)/i', + '/request:([a-z0-9_]+)/ie' + ), + array( + "\$_SESSION['\\1']", + "\$this->config['\\1']", + "\$this->env['\\1']", + "get_input_value('\\1', RCUVE_INPUT_GPC)" + ), + $condition); + + return eval("return (".$condition.");"); + } + + + /** + * Search for special tags in input and replace them + * with the appropriate content + * + * @param string Input string to parse + * @return string Altered input string + * @todo Maybe a cache. + */ + private function parse_xml($input) + { + return preg_replace('/]+)>/Uie', "\$this->xml_command('\\1', '\\2')", $input); + } + + + /** + * Convert a xml command tag into real content + * + * @param string Tag command: object,button,label, etc. + * @param string Attribute string + * @return string Tag/Object content + */ + private function xml_command($command, $str_attrib, $add_attrib = array()) + { + $command = strtolower($command); + $attrib = parse_attrib_string($str_attrib) + $add_attrib; + + // empty output if required condition is not met + if (!empty($attrib['condition']) && !$this->check_condition($attrib['condition'])) { + return ''; + } + + // execute command + switch ($command) { + // return a button + case 'button': + if ($attrib['name'] || $attrib['command']) { + return $this->button($attrib); + } + break; + + // show a label + case 'label': + if ($attrib['name'] || $attrib['command']) { + return Q(rcube_label($attrib + array('vars' => array('product' => $this->config['product_name'])))); + } + break; + + // include a file + case 'include': + $path = realpath($this->config['skin_path'].$attrib['file']); + if ($fsize = filesize($path)) { + if ($this->config['skin_include_php']) { + $incl = $this->include_php($path); + } + else if ($fp = fopen($path, 'r')) { + $incl = fread($fp, $fsize); + fclose($fp); + } + return $this->parse_xml($incl); + } + break; + + case 'plugin.include': + //rcube::tfk_debug(var_export($this->config['skin_path'], true)); + $path = realpath($this->config['skin_path'].$attrib['file']); + if (!$path) { + //rcube::tfk_debug("Does not exist:"); + //rcube::tfk_debug($this->config['skin_path']); + //rcube::tfk_debug($attrib['file']); + //rcube::tfk_debug($path); + } + $incl = file_get_contents($path); + if ($incl) { + return $this->parse_xml($incl); + } + break; + + // return code for a specific application object + case 'object': + $object = strtolower($attrib['name']); + + // we are calling a class/method + if (($handler = $this->object_handlers[$object]) && is_array($handler)) { + if ((is_object($handler[0]) && method_exists($handler[0], $handler[1])) || + (is_string($handler[0]) && class_exists($handler[0]))) + return call_user_func($handler, $attrib); + } + else if (function_exists($handler)) { + // execute object handler function + return call_user_func($handler, $attrib); + } + + if ($object=='productname') { + $name = !empty($this->config['product_name']) ? $this->config['product_name'] : 'RoundCube Webmail'; + return Q($name); + } + if ($object=='version') { + $ver = (string)RCMAIL_VERSION; + if (is_file(INSTALL_PATH . '.svn/entries')) { + if (preg_match('/Revision:\s(\d+)/', @shell_exec('svn info'), $regs)) + $ver .= ' [SVN r'.$regs[1].']'; + } + return $ver; + } + if ($object=='pagetitle') { + $task = $this->task; + $title = !empty($this->config['product_name']) ? $this->config['product_name'].' :: ' : ''; + + if (!empty($this->pagetitle)) { + $title .= $this->pagetitle; + } + else if ($task == 'login') { + $title = rcube_label(array('name' => 'welcome', 'vars' => array('product' => $this->config['product_name']))); + } + else { + $title .= ucfirst($task); + } + + return Q($title); + } + break; + + // return variable + case 'var': + $var = explode(':', $attrib['name']); + $name = $var[1]; + $value = ''; + + switch ($var[0]) { + case 'env': + $value = $this->env[$name]; + break; + case 'config': + $value = $this->config[$name]; + if (is_array($value) && $value[$_SESSION['imap_host']]) { + $value = $value[$_SESSION['imap_host']]; + } + break; + case 'request': + $value = get_input_value($name, RCUBE_INPUT_GPC); + break; + case 'session': + $value = $_SESSION[$name]; + break; + } + + if (is_array($value)) { + $value = implode(', ', $value); + } + + return Q($value); + break; + } + return ''; + } + + /** + * Include a specific file and return it's contents + * + * @param string File path + * @return string Contents of the processed file + */ + private function include_php($file) + { + ob_start(); + include $file; + $out = ob_get_contents(); + ob_end_clean(); + + return $out; + } + + /** + * Create and register a button + * + * @param array Named button attributes + * @return string HTML button + * @todo Remove all inline JS calls and use jQuery instead. + * @todo Remove all sprintf()'s - they are pretty, but also slow. + */ + private function button($attrib) + { + static $sa_buttons = array(); + static $s_button_count = 100; + + // these commands can be called directly via url + $a_static_commands = array('compose', 'list'); + + if (!($attrib['command'] || $attrib['name'])) { + return ''; + } + + $browser = new rcube_browser(); + + // try to find out the button type + if ($attrib['type']) { + $attrib['type'] = strtolower($attrib['type']); + } + else { + $attrib['type'] = ($attrib['image'] || $attrib['imagepas'] || $attrib['imageact']) ? 'image' : 'link'; + } + $command = $attrib['command']; + + // take the button from the stack + if ($attrib['name'] && $sa_buttons[$attrib['name']]) { + $attrib = $sa_buttons[$attrib['name']]; + } + else if($attrib['image'] || $attrib['imageact'] || $attrib['imagepas'] || $attrib['class']) { + // add button to button stack + if (!$attrib['name']) { + $attrib['name'] = $command; + } + if (!$attrib['image']) { + $attrib['image'] = $attrib['imagepas'] ? $attrib['imagepas'] : $attrib['imageact']; + } + $sa_buttons[$attrib['name']] = $attrib; + } + else if ($command && $sa_buttons[$command]) { + // get saved button for this command/name + $attrib = $sa_buttons[$command]; + } + + // set border to 0 because of the link arround the button + if ($attrib['type']=='image' && !isset($attrib['border'])) { + $attrib['border'] = 0; + } + if (!$attrib['id']) { + $attrib['id'] = sprintf('rcmbtn%d', $s_button_count++); + } + // get localized text for labels and titles + if ($attrib['title']) { + $attrib['title'] = Q(rcube_label($attrib['title'])); + } + if ($attrib['label']) { + $attrib['label'] = Q(rcube_label($attrib['label'])); + } + if ($attrib['alt']) { + $attrib['alt'] = Q(rcube_label($attrib['alt'])); + } + // set title to alt attribute for IE browsers + if ($browser->ie && $attrib['title'] && !$attrib['alt']) { + $attrib['alt'] = $attrib['title']; + unset($attrib['title']); + } + + // add empty alt attribute for XHTML compatibility + if (!isset($attrib['alt'])) { + $attrib['alt'] = ''; + } + + // register button in the system + if ($attrib['command']) { + $this->add_script(sprintf( + "%s.register_button('%s', '%s', '%s', '%s', '%s', '%s');", + JS_OBJECT_NAME, + $command, + $attrib['id'], + $attrib['type'], + $attrib['imageact'] ? $this->abs_url($attrib['imageact']) : $attrib['classact'], + $attrib['imagesel'] ? $this->abs_url($attrib['imagesel']) : $attrib['classsel'], + $attrib['imageover'] ? $this->abs_url($attrib['imageover']) : '' + )); + + // make valid href to specific buttons + if (in_array($attrib['command'], rcmail::$main_tasks)) { + $attrib['href'] = Q(rcmail_url(null, null, $attrib['command'])); + } + else if (in_array($attrib['command'], $a_static_commands)) { + $attrib['href'] = Q(rcmail_url($attrib['command'])); + } + } + + // overwrite attributes + if (!$attrib['href']) { + $attrib['href'] = '#'; + } + if ($command) { + $attrib['onclick'] = sprintf( + "return %s.command('%s','%s',this)", + JS_OBJECT_NAME, + $command, + $attrib['prop'] + ); + } + if ($command && $attrib['imageover']) { + $attrib['onmouseover'] = sprintf( + "return %s.button_over('%s','%s')", + JS_OBJECT_NAME, + $command, + $attrib['id'] + ); + $attrib['onmouseout'] = sprintf( + "return %s.button_out('%s','%s')", + JS_OBJECT_NAME, + $command, + $attrib['id'] + ); + } + + if ($command && $attrib['imagesel']) { + $attrib['onmousedown'] = sprintf( + "return %s.button_sel('%s','%s')", + JS_OBJECT_NAME, + $command, + $attrib['id'] + ); + $attrib['onmouseup'] = sprintf( + "return %s.button_out('%s','%s')", + JS_OBJECT_NAME, + $command, + $attrib['id'] + ); + } + + $out = ''; + + // generate image tag + if ($attrib['type']=='image') { + $attrib_str = html::attrib_string( + $attrib, + array( + 'style', 'class', 'id', 'width', + 'height', 'border', 'hspace', + 'vspace', 'align', 'alt', + ) + ); + $btn_content = sprintf('', $this->abs_url($attrib['image']), $attrib_str); + if ($attrib['label']) { + $btn_content .= ' '.$attrib['label']; + } + $link_attrib = array('href', 'onclick', 'onmouseover', 'onmouseout', 'onmousedown', 'onmouseup', 'title'); + } + else if ($attrib['type']=='link') { + $btn_content = $attrib['label'] ? $attrib['label'] : $attrib['command']; + $link_attrib = array('href', 'onclick', 'title', 'id', 'class', 'style'); + } + else if ($attrib['type']=='input') { + $attrib['type'] = 'button'; + + if ($attrib['label']) { + $attrib['value'] = $attrib['label']; + } + + $attrib_str = html::attrib_string( + $attrib, + array( + 'type', 'value', 'onclick', + 'id', 'class', 'style' + ) + ); + $out = sprintf('', $attrib_str); + } + + // generate html code for button + if ($btn_content) { + $attrib_str = html::attrib_string($attrib, $link_attrib); + $out = sprintf('%s', $attrib_str, $btn_content); + } + + return $out; + } + + + /* ************* common functions delivering gui objects ************** */ + + + /** + * Create a form tag with the necessary hidden fields + * + * @param array Named tag parameters + * @return string HTML code for the form + */ + public function form_tag($attrib, $content = null) + { + if ($this->framed) { + $hiddenfield = new html_hiddenfield(array('name' => '_framed', 'value' => '1')); + $hidden = $hiddenfield->show(); + } + + if (!$content) + $attrib['noclose'] = true; + + return html::tag('form', + $attrib + array('action' => "./", 'method' => "get"), + $hidden . $content); + } + + + /** + * GUI object 'username' + * Showing IMAP username of the current session + * + * @param array Named tag parameters (currently not used) + * @return string HTML code for the gui object + */ + public function current_username($attrib) + { + static $username; + + // alread fetched + if (!empty($username)) { + return $username; + } + + // get e-mail address form default identity + if ($sql_arr = $this->app->user->get_identity()) { + $username = $sql_arr['email']; + } + else { + $username = $this->app->user->get_username(); + } + + return $username; + } + + + /** + * GUI object 'loginform' + * Returns code for the webmail login form + * + * @param array Named parameters + * @return string HTML code for the gui object + */ + private function login_form($attrib) + { + $default_host = $this->config['default_host']; + + $_SESSION['temp'] = true; + + $input_user = new html_inputfield(array('name' => '_user', 'id' => 'rcmloginuser', 'size' => 30, 'autocomplete' => 'off')); + $input_pass = new html_passwordfield(array('name' => '_pass', 'id' => 'rcmloginpwd', 'size' => 30)); + $input_action = new html_hiddenfield(array('name' => '_action', 'value' => 'login')); + $input_host = null; + + if (is_array($default_host)) { + $input_host = new html_select(array('name' => '_host', 'id' => 'rcmloginhost')); + + foreach ($default_host as $key => $value) { + if (!is_array($value)) { + $input_host->add($value, (is_numeric($key) ? $value : $key)); + } + else { + $input_host = null; + break; + } + } + } + else if (!strlen($default_host)) { + $input_host = new html_inputfield(array('name' => '_host', 'id' => 'rcmloginhost', 'size' => 30)); + } + + $form_name = !empty($attrib['form']) ? $attrib['form'] : 'form'; + $this->add_gui_object('loginform', $form_name); + + // create HTML table with two cols + $table = new html_table(array('cols' => 2)); + + $table->add('title', html::label('rcmloginuser', Q(rcube_label('username')))); + $table->add(null, $input_user->show(get_input_value('_user', RCUVE_INPUT_POST))); + + $table->add('title', html::label('rcmloginpwd', Q(rcube_label('password')))); + $table->add(null, $input_pass->show()); + + // add host selection row + if (is_object($input_host)) { + $table->add('title', html::label('rcmloginhost', Q(rcube_label('server')))); + $table->add(null, $input_host->show(get_input_value('_host', RCUVE_INPUT_POST))); + } + + $out = $input_action->show(); + $out .= $table->show(); + + // surround html output with a form tag + if (empty($attrib['form'])) { + $out = $this->form_tag(array('name' => $form_name, 'method' => "post"), $out); + } + + return $out; + } + + + /** + * GUI object 'searchform' + * Returns code for search function + * + * @param array Named parameters + * @return string HTML code for the gui object + */ + private function search_form($attrib) + { + // add some labels to client + $this->add_label('searching'); + + $attrib['name'] = '_q'; + + if (empty($attrib['id'])) { + $attrib['id'] = 'rcmqsearchbox'; + } + $input_q = new html_inputfield($attrib); + $out = $input_q->show(); + + $this->add_gui_object('qsearchbox', $attrib['id']); + + // add form tag around text field + if (empty($attrib['form'])) { + $out = $this->form_tag(array( + 'name' => "rcmqsearchform", + 'onsubmit' => JS_OBJECT_NAME . ".command('search');return false;", + 'style' => "display:inline"), + $out); + } + + return $out; + } + + + /** + * Builder for GUI object 'message' + * + * @param array Named tag parameters + * @return string HTML code for the gui object + */ + private function message_container($attrib) + { + if (isset($attrib['id']) === false) { + $attrib['id'] = 'rcmMessageContainer'; + } + + $this->add_gui_object('message', $attrib['id']); + return html::div($attrib, ""); + } + + + /** + * GUI object 'charsetselector' + * + * @param array Named parameters for the select tag + * @return string HTML code for the gui object + */ + static function charset_selector($attrib) + { + // pass the following attributes to the form class + $field_attrib = array('name' => '_charset'); + foreach ($attrib as $attr => $value) { + if (in_array($attr, array('id', 'class', 'style', 'size', 'tabindex'))) { + $field_attrib[$attr] = $value; + } + } + $charsets = array( + 'US-ASCII' => 'ASCII (English)', + 'EUC-JP' => 'EUC-JP (Japanese)', + 'EUC-KR' => 'EUC-KR (Korean)', + 'BIG5' => 'BIG5 (Chinese)', + 'GB2312' => 'GB2312 (Chinese)', + 'ISO-2022-JP' => 'ISO-2022-JP (Japanese)', + 'ISO-8859-1' => 'ISO-8859-1 (Latin-1)', + 'ISO-8859-2' => 'ISO-8895-2 (Central European)', + 'ISO-8859-7' => 'ISO-8859-7 (Greek)', + 'ISO-8859-9' => 'ISO-8859-9 (Turkish)', + 'Windows-1251' => 'Windows-1251 (Cyrillic)', + 'Windows-1252' => 'Windows-1252 (Western)', + 'Windows-1255' => 'Windows-1255 (Hebrew)', + 'Windows-1256' => 'Windows-1256 (Arabic)', + 'Windows-1257' => 'Windows-1257 (Baltic)', + 'UTF-8' => 'UTF-8' + ); + + $select = new html_select($field_attrib); + $select->add(array_values($charsets), array_keys($charsets)); + + $set = $_POST['_charset'] ? $_POST['_charset'] : $this->get_charset(); + return $select->show($set); + } + +} // end class rcube_template + + diff --git a/program/include/rcube_user.inc b/program/include/rcube_user.php similarity index 79% rename from program/include/rcube_user.inc rename to program/include/rcube_user.php index e748758..c808d07 100644 --- a/program/include/rcube_user.inc +++ b/program/include/rcube_user.php @@ -24,13 +24,16 @@ /** * Class representing a system user * - * @package core + * @package Core * @author Thomas Bruederli */ class rcube_user { - var $ID = null; - var $data = null; + public $ID = null; + public $data = null; + public $language = 'en_US'; + + private $db = null; /** @@ -40,18 +43,19 @@ class rcube_user */ function __construct($id = null, $sql_arr = null) { - global $DB; + $this->db = rcmail::get_instance()->get_dbh(); if ($id && !$sql_arr) { - $sql_result = $DB->query("SELECT * FROM ".get_table_name('users')." WHERE user_id=?", $id); - $sql_arr = $DB->fetch_assoc($sql_result); + $sql_result = $this->db->query("SELECT * FROM ".get_table_name('users')." WHERE user_id=?", $id); + $sql_arr = $this->db->fetch_assoc($sql_result); } if (!empty($sql_arr)) { $this->ID = $sql_arr['user_id']; $this->data = $sql_arr; + $this->language = $sql_arr['language']; } } @@ -85,7 +89,7 @@ class rcube_user function get_prefs() { if ($this->ID && $this->data['preferences']) - return unserialize($this->data['preferences']); + return array('language' => $this->language) + unserialize($this->data['preferences']); else return array(); } @@ -99,26 +103,26 @@ class rcube_user */ function save_prefs($a_user_prefs) { - global $DB, $CONFIG, $sess_user_lang; - if (!$this->ID) return false; // merge (partial) prefs array with existing settings $a_user_prefs += (array)$this->get_prefs(); + unset($a_user_prefs['language']); - $DB->query( + $this->db->query( "UPDATE ".get_table_name('users')." SET preferences=?, language=? WHERE user_id=?", serialize($a_user_prefs), - $sess_user_lang, + $_SESSION['language'], $this->ID); - if ($DB->affected_rows()) + $this->language = $_SESSION['language']; + if ($this->db->affected_rows()) { - $CONFIG = array_merge($CONFIG, $a_user_prefs); + rcmail::get_instance()->config->merge($a_user_prefs); return true; } @@ -134,10 +138,8 @@ class rcube_user */ function get_identity($id = null) { - global $DB; - $sql_result = $this->list_identities($id ? sprintf('AND identity_id=%d', $id) : ''); - return $DB->fetch_assoc($sql_result); + return $this->db->fetch_assoc($sql_result); } @@ -148,15 +150,13 @@ class rcube_user */ function list_identities($sql_add = '') { - global $DB; - // get contacts from DB - $sql_result = $DB->query( + $sql_result = $this->db->query( "SELECT * FROM ".get_table_name('identities')." WHERE del<>1 AND user_id=? $sql_add - ORDER BY ".$DB->quoteIdentifier('standard')." DESC, name ASC", + ORDER BY ".$this->db->quoteIdentifier('standard')." DESC, name ASC", $this->ID); return $sql_result; @@ -172,8 +172,6 @@ class rcube_user */ function update_identity($iid, $data) { - global $DB; - if (!$this->ID) return false; @@ -182,11 +180,11 @@ class rcube_user foreach ((array)$data as $col => $value) { $write_sql[] = sprintf("%s=%s", - $DB->quoteIdentifier($col), - $DB->quote($value)); + $this->db->quoteIdentifier($col), + $this->db->quote($value)); } - $DB->query( + $this->db->query( "UPDATE ".get_table_name('identities')." SET ".join(', ', $write_sql)." WHERE identity_id=? @@ -195,7 +193,7 @@ class rcube_user $iid, $this->ID); - return $DB->affected_rows(); + return $this->db->affected_rows(); } @@ -207,25 +205,23 @@ class rcube_user */ function insert_identity($data) { - global $DB; - if (!$this->ID) return false; $insert_cols = $insert_values = array(); foreach ((array)$data as $col => $value) { - $insert_cols[] = $DB->quoteIdentifier($col); - $insert_values[] = $DB->quote($value); + $insert_cols[] = $this->db->quoteIdentifier($col); + $insert_values[] = $this->db->quote($value); } - $DB->query( + $this->db->query( "INSERT INTO ".get_table_name('identities')." (user_id, ".join(', ', $insert_cols).") VALUES (?, ".join(', ', $insert_values).")", $this->ID); - return $DB->insert_id(get_sequence_name('identities')); + return $this->db->insert_id(get_sequence_name('identities')); } @@ -237,24 +233,22 @@ class rcube_user */ function delete_identity($iid) { - global $DB; - if (!$this->ID) return false; if (!$this->ID || $this->ID == '') return false; - $sql_result = $DB->query("SELECT count(*) AS ident_count FROM " . + $sql_result = $this->db->query("SELECT count(*) AS ident_count FROM " . get_table_name('identities') . " WHERE user_id = ? AND del <> 1", $this->ID); - $sql_arr = $DB->fetch_assoc($sql_result); + $sql_arr = $this->db->fetch_assoc($sql_result); if ($sql_arr['ident_count'] <= 1) return false; - $DB->query( + $this->db->query( "UPDATE ".get_table_name('identities')." SET del=1 WHERE user_id=? @@ -262,7 +256,7 @@ class rcube_user $this->ID, $iid); - return $DB->affected_rows(); + return $this->db->affected_rows(); } @@ -273,13 +267,11 @@ class rcube_user */ function set_default($iid) { - global $DB; - if ($this->ID && $iid) { - $DB->query( + $this->db->query( "UPDATE ".get_table_name('identities')." - SET ".$DB->quoteIdentifier('standard')."='0' + SET ".$this->db->quoteIdentifier('standard')."='0' WHERE user_id=? AND identity_id<>? AND del<>1", @@ -294,13 +286,11 @@ class rcube_user */ function touch() { - global $DB; - if ($this->ID) { - $DB->query( + $this->db->query( "UPDATE ".get_table_name('users')." - SET last_login=".$DB->now()." + SET last_login=".$this->db->now()." WHERE user_id=?", $this->ID); } @@ -323,14 +313,13 @@ class rcube_user * @param string IMAP user name * @param string IMAP host name * @return object rcube_user New user instance - * @static */ - function query($user, $host) + static function query($user, $host) { - global $DB; + $dbh = rcmail::get_instance()->get_dbh(); // query if user already registered - $sql_result = $DB->query( + $sql_result = $dbh->query( "SELECT * FROM ".get_table_name('users')." WHERE mail_host=? AND (username=? OR alias=?)", $host, @@ -338,7 +327,7 @@ class rcube_user $user); // user already registered -> overwrite username - if ($sql_arr = $DB->fetch_assoc($sql_result)) + if ($sql_arr = $dbh->fetch_assoc($sql_result)) return new rcube_user($sql_arr['user_id'], $sql_arr); else return false; @@ -351,28 +340,27 @@ class rcube_user * @param string IMAP user name * @param string IMAP host * @return object rcube_user New user instance - * @static */ - function create($user, $host) + static function create($user, $host) { - global $DB, $CONFIG; - $user_email = ''; + $rcmail = rcmail::get_instance(); + $dbh = $rcmail->get_dbh(); // try to resolve user in virtusertable - if (!empty($CONFIG['virtuser_file']) && !strpos($user, '@')) + if ($rcmail->config->get('virtuser_file') && !strpos($user, '@')) $user_email = rcube_user::user2email($user); - $DB->query( + $dbh->query( "INSERT INTO ".get_table_name('users')." (created, last_login, username, mail_host, alias, language) - VALUES (".$DB->now().", ".$DB->now().", ?, ?, ?, ?)", + VALUES (".$dbh->now().", ".$dbh->now().", ?, ?, ?, ?)", strip_newlines($user), strip_newlines($host), strip_newlines($user_email), - $_SESSION['user_lang']); + $_SESSION['language']); - if ($user_id = $DB->insert_id(get_sequence_name('users'))) + if ($user_id = $dbh->insert_id(get_sequence_name('users'))) { $mail_domain = rcmail_mail_domain($host); @@ -382,13 +370,13 @@ class rcube_user $user_name = $user != $user_email ? $user : ''; // try to resolve the e-mail address from the virtuser table - if (!empty($CONFIG['virtuser_query']) && - ($sql_result = $DB->query(preg_replace('/%u/', $DB->escapeSimple($user), $CONFIG['virtuser_query']))) && - ($DB->num_rows()>0)) + if ($virtuser_query = $rcmail->config->get('virtuser_query') && + ($sql_result = $dbh->query(preg_replace('/%u/', $dbh->escapeSimple($user), $virtuser_query))) && + ($dbh->num_rows() > 0)) { - while ($sql_arr = $DB->fetch_array($sql_result)) + while ($sql_arr = $dbh->fetch_array($sql_result)) { - $DB->query( + $dbh->query( "INSERT INTO ".get_table_name('identities')." (user_id, del, standard, name, email) VALUES (?, 0, 1, ?, ?)", @@ -400,7 +388,7 @@ class rcube_user else { // also create new identity records - $DB->query( + $dbh->query( "INSERT INTO ".get_table_name('identities')." (user_id, del, standard, name, email) VALUES (?, 0, 1, ?, ?)", @@ -428,9 +416,8 @@ class rcube_user * * @param string E-mail address to resolve * @return string Resolved IMAP username - * @static */ - function email2user($email) + static function email2user($email) { $user = $email; $r = rcmail_findinvirtual("^$email"); @@ -455,9 +442,8 @@ class rcube_user * * @param string User name * @return string Resolved e-mail address - * @static */ - function user2email($user) + static function user2email($user) { $email = ""; $r = rcmail_findinvirtual("$user$"); @@ -479,4 +465,3 @@ class rcube_user } -?> diff --git a/program/include/session.inc b/program/include/session.inc index 6b0eeab..60ae9e1 100644 --- a/program/include/session.inc +++ b/program/include/session.inc @@ -15,7 +15,7 @@ | Author: Thomas Bruederli | +-----------------------------------------------------------------------+ - $Id: session.inc 1063 2008-02-13 05:26:47Z till $ + $Id: session.inc 1400 2008-05-17 17:46:43Z thomasb $ */ @@ -26,7 +26,6 @@ function sess_open($save_path, $session_name) } - function sess_close() { return TRUE; @@ -89,9 +88,7 @@ function sess_write($key, $vars) VALUES (?, ?, ?, ".$DB->now().", ".$DB->now().")", $key, $vars, - $_SERVER['REMOTE_ADDR']); - - + (string)$_SERVER['REMOTE_ADDR']); } return TRUE; @@ -101,15 +98,18 @@ function sess_write($key, $vars) // handler for session_destroy() function sess_destroy($key) { - global $DB; + global $DB, $CONFIG; if ($DB->is_error()) return FALSE; - - // delete session entries in cache table - $DB->query("DELETE FROM ".get_table_name('cache')." - WHERE session_id=?", + + if ($CONFIG['enable_caching']) + { + // delete session entries in cache table + $DB->query("DELETE FROM ".get_table_name('cache')." + WHERE session_id=?", $key); + } $DB->query("DELETE FROM ".get_table_name('session')." WHERE sess_id=?", @@ -122,7 +122,7 @@ function sess_destroy($key) // garbage collecting function function sess_gc($maxlifetime) { - global $DB; + global $DB, $CONFIG; if ($DB->is_error()) return FALSE; @@ -137,20 +137,23 @@ function sess_gc($maxlifetime) while ($sql_arr = $DB->fetch_assoc($sql_result)) $a_exp_sessions[] = $sql_arr['sess_id']; - if (sizeof($a_exp_sessions)) { - // delete session cache records - $DB->query("DELETE FROM ".get_table_name('cache')." - WHERE session_id IN ('".join("','", $a_exp_sessions)."')"); - + if ($CONFIG['enable_caching']) + { + // delete session cache records + $DB->query("DELETE FROM ".get_table_name('cache')." + WHERE session_id IN ('".join("','", $a_exp_sessions)."')"); + } + // delete session records $DB->query("DELETE FROM ".get_table_name('session')." WHERE sess_id IN ('".join("','", $a_exp_sessions)."')"); } // also run message cache GC - rcmail_message_cache_gc(); + if ($CONFIG['enable_caching']) + rcmail_message_cache_gc(); rcmail_temp_gc(); return TRUE; diff --git a/program/js/app.js b/program/js/app.js index 1ddb6da..de250c5 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -13,7 +13,7 @@ | Requires: common.js, list.js | +-----------------------------------------------------------------------+ - $Id: app.js 1255 2008-04-05 12:49:21Z thomasb $ + $Id: app.js 1464 2008-06-02 12:24:31Z alec $ */ @@ -179,7 +179,6 @@ function rcube_webmail() { this.enable_command('compose', 'add-contact', false); parent.rcmail.show_contentframe(true); - parent.rcmail.mark_message('read', this.env.uid); } if ((this.env.action=='show' || this.env.action=='preview') && this.env.blockedobjects) @@ -356,7 +355,7 @@ function rcube_webmail() // start interval for keep-alive/recent_check signal this.start_keepalive = function() { - if (this.env.keep_alive && !this.env.framed && this.task=='mail' && this.gui_objects.messagelist) + if (this.env.keep_alive && !this.env.framed && this.task=='mail' && this.gui_objects.mailboxlist) this._int = setInterval(function(){ ref.check_for_recent(); }, this.env.keep_alive * 1000); else if (this.env.keep_alive && !this.env.framed && this.task!='login') this._int = setInterval(function(){ ref.send_keep_alive(); }, this.env.keep_alive * 1000); @@ -406,7 +405,7 @@ function rcube_webmail() this.init_address_input_events(input_cc); if (input_bcc) this.init_address_input_events(input_bcc); - + // add signature according to selected identity if (input_from && input_from.type=='select-one') this.change_identity(input_from); @@ -488,7 +487,7 @@ function rcube_webmail() break; case 'logout': - this.goto_url('logout', true); + this.goto_url('logout', '', true); break; // commands to switch task @@ -631,7 +630,7 @@ function rcube_webmail() var input_email = rcube_find_object('_email'); // user prefs - if (input_pagesize && isNaN(input_pagesize.value)) + if (input_pagesize && isNaN(parseInt(input_pagesize.value))) { alert(this.get_label('nopagesizewarning')); input_pagesize.focus(); @@ -722,7 +721,7 @@ function rcube_webmail() this.attachment_win = window.open(this.env.comm_path+'&_action=get&'+qstring+'&_frame=1', 'rcubemailattachment'); if (this.attachment_win) { - setTimeout(function(){ ref.attachment_win.focus(); }, 10); + window.setTimeout(function(){ ref.attachment_win.focus(); }, 10); break; } } @@ -890,7 +889,7 @@ function rcube_webmail() ref.printwin = window.open(this.env.comm_path+'&_action=print&_uid='+uid+'&_mbox='+urlencode(this.env.mailbox)+(this.env.safemode ? '&_safe=1' : '')); if (this.printwin) { - setTimeout(function(){ ref.printwin.focus(); }, 20); + window.setTimeout(function(){ ref.printwin.focus(); }, 20); if (this.env.action != 'show') this.mark_message('read', uid); } @@ -903,7 +902,7 @@ function rcube_webmail() { ref.sourcewin = window.open(this.env.comm_path+'&_action=viewsource&_uid='+this.env.uid+'&_mbox='+urlencode(this.env.mailbox)); if (this.sourcewin) - setTimeout(function(){ ref.sourcewin.focus(); }, 20); + window.setTimeout(function(){ ref.sourcewin.focus(); }, 20); } break; @@ -1020,7 +1019,7 @@ function rcube_webmail() // set timer for requests if (a && this.env.request_timeout) - this.request_timer = setTimeout(function(){ ref.request_timed_out(); }, this.env.request_timeout * 1000); + this.request_timer = window.setTimeout(function(){ ref.request_timed_out(); }, this.env.request_timeout * 1000); }; @@ -1139,7 +1138,7 @@ function rcube_webmail() // start timer for message preview (wait for double click) if (selected && this.env.contentframe && !list.multi_selecting) - this.preview_timer = setTimeout(function(){ ref.msglist_get_preview(); }, this.dblclick_time + 10); + this.preview_timer = window.setTimeout(function(){ ref.msglist_get_preview(); }, this.dblclick_time + 10); else if (this.env.contentframe) this.show_contentframe(false); }; @@ -1233,9 +1232,12 @@ function rcube_webmail() var frm; if (this.env.contentframe && (frm = rcube_find_object(this.env.contentframe))) { - if (!show && window.frames[this.env.contentframe] && frames[this.env.contentframe].location.href.indexOf(this.env.blankpage)<0) - frames[this.env.contentframe].location.href = this.env.blankpage; - if (!bw.safari) + if (!show && window.frames[this.env.contentframe]) + { + if (window.frames[this.env.contentframe].location.href.indexOf(this.env.blankpage)<0) + window.frames[this.env.contentframe].location.href = this.env.blankpage; + } + else if (!bw.safari) frm.style.display = show ? 'block' : 'none'; } @@ -1408,7 +1410,7 @@ function rcube_webmail() this.delete_messages = function() { var selection = this.message_list ? this.message_list.get_selection() : new Array(); - + // exit if no mailbox specified or if selection is empty if (!this.env.uid && !selection.length) return; @@ -1459,8 +1461,9 @@ function rcube_webmail() this._with_selected_messages = function(action, lock, add_url) { var a_uids = new Array(); + if (this.env.uid) - a_uids[a_uids.length] = this.env.uid; + a_uids[0] = this.env.uid; else { var selection = this.message_list.get_selection(); @@ -1469,10 +1472,11 @@ function rcube_webmail() { id = selection[n]; a_uids[a_uids.length] = id; + this.message_list.remove_row(id, (n == selection.length-1)); } } - + // also send search request to get the right messages if (this.env.search_request) add_url += '&_search='+this.env.search_request; @@ -1488,20 +1492,23 @@ function rcube_webmail() var a_uids = new Array(); var r_uids = new Array(); var selection = this.message_list ? this.message_list.get_selection() : new Array(); - + if (uid) a_uids[0] = uid; else if (this.env.uid) a_uids[0] = this.env.uid; else if (this.message_list) { - for (var id, n=0; n