Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Update branch for 0.5-rc release

  • Loading branch information...
commit db1a87cd6c506f2afbd1a37c64cb56ae11120b49 1 parent acd5200
@thomascube thomascube authored
Showing with 4,251 additions and 3,424 deletions.
  1. +24 −0 CHANGELOG
  2. +2 −1  INSTALL
  3. +0 −3  README
  4. +3 −2 UPGRADING
  5. +1 −1  bin/update.sh
  6. +8 −2 config/main.inc.php.dist
  7. +12 −15 index.php
  8. +30 −33 plugins/emoticons/emoticons.php
  9. +2 −0  plugins/managesieve/localization/fr_FR.inc
  10. +28 −5 plugins/managesieve/localization/ru_RU.inc
  11. +2 −2 plugins/new_user_dialog/localization/es_ES.inc
  12. +1 −0  plugins/new_user_dialog/new_user_dialog.php
  13. +22 −4 plugins/new_user_dialog/package.xml
  14. +2 −0  plugins/password/config.inc.php.dist
  15. +1 −1  plugins/password/drivers/chpasswd.php
  16. +21 −17 plugins/password/drivers/ldap.php
  17. +19 −16 plugins/password/drivers/ldap_simple.php
  18. +6 −2 plugins/password/drivers/sql.php
  19. +4 −0 plugins/password/package.xml
  20. +1 −1  program/include/iniset.php
  21. +162 −16 program/include/main.inc
  22. +25 −7 program/include/rcmail.php
  23. +205 −122 program/include/rcube_imap.php
  24. +1,490 −1,333 program/include/rcube_imap_generic.php
  25. +5 −1 program/include/rcube_message.php
  26. +14 −6 program/include/rcube_template.php
  27. +6 −2 program/include/rcube_user.php
  28. +119 −210 program/js/app.js
  29. +3 −1 program/js/editor.js
  30. +5 −4 program/js/list.js
  31. +34 −23 program/lib/Mail/mime.php
  32. +40 −64 program/lib/Mail/mimePart.php
  33. +56 −36 program/localization/ar_SA/labels.inc
  34. +24 −4 program/localization/ar_SA/messages.inc
  35. +0 −3  program/localization/ast/labels.inc
  36. +0 −3  program/localization/ast/messages.inc
  37. +0 −3  program/localization/az_AZ/labels.inc
  38. +0 −3  program/localization/az_AZ/messages.inc
  39. +2 −7 program/localization/bg_BG/labels.inc
  40. +1 −4 program/localization/bg_BG/messages.inc
  41. +1 −4 program/localization/bn_BD/labels.inc
  42. +0 −3  program/localization/bn_BD/messages.inc
  43. +0 −3  program/localization/br/labels.inc
  44. +0 −3  program/localization/bs_BA/labels.inc
  45. +0 −3  program/localization/ca_ES/labels.inc
  46. +0 −3  program/localization/ca_ES/messages.inc
  47. +0 −3  program/localization/cs_CZ/labels.inc
  48. +17 −6 program/localization/cs_CZ/messages.inc
  49. +16 −10 program/localization/cy_GB/labels.inc
  50. +26 −3 program/localization/cy_GB/messages.inc
  51. +0 −3  program/localization/da_DK/labels.inc
  52. +0 −3  program/localization/da_DK/messages.inc
  53. +9 −7 program/localization/de_CH/labels.inc
  54. +12 −3 program/localization/de_CH/messages.inc
  55. +9 −7 program/localization/de_DE/labels.inc
  56. +12 −3 program/localization/de_DE/messages.inc
  57. +0 −3  program/localization/el_GR/labels.inc
  58. +0 −3  program/localization/el_GR/messages.inc
  59. +15 −9 program/localization/en_GB/labels.inc
  60. +20 −9 program/localization/en_GB/messages.inc
  61. +9 −12 program/localization/en_US/labels.inc
  62. +12 −3 program/localization/en_US/messages.inc
  63. +0 −3  program/localization/eo/labels.inc
  64. +0 −1  program/localization/eo/messages.inc
  65. +0 −3  program/localization/es_AR/labels.inc
  66. +0 −3  program/localization/es_AR/messages.inc
  67. +17 −4 program/localization/es_ES/labels.inc
  68. +14 −3 program/localization/es_ES/messages.inc
  69. +9 −7 program/localization/et_EE/labels.inc
  70. +12 −6 program/localization/et_EE/messages.inc
  71. +0 −3  program/localization/eu_ES/labels.inc
  72. +0 −1  program/localization/eu_ES/messages.inc
  73. +0 −4 program/localization/fa/labels.inc
  74. +0 −3  program/localization/fa/messages.inc
  75. +0 −3  program/localization/fa_AF/labels.inc
  76. +0 −3  program/localization/fa_AF/messages.inc
  77. +0 −3  program/localization/fi_FI/labels.inc
  78. +0 −3  program/localization/fi_FI/messages.inc
  79. +16 −3 program/localization/fr_FR/labels.inc
  80. +15 −4 program/localization/fr_FR/messages.inc
  81. +0 −3  program/localization/ga_IE/labels.inc
  82. +27 −14 program/localization/gl_ES/labels.inc
  83. +19 −8 program/localization/gl_ES/messages.inc
  84. +10 −11 program/localization/he_IL/labels.inc
  85. +13 −4 program/localization/he_IL/messages.inc
  86. +0 −3  program/localization/hi_IN/labels.inc
  87. +78 −10 program/localization/hr_HR/labels.inc
  88. +0 −3  program/localization/hr_HR/messages.inc
  89. +4 −9 program/localization/hu_HU/labels.inc
  90. +0 −3  program/localization/hu_HU/messages.inc
  91. +0 −3  program/localization/hy_AM/labels.inc
  92. +0 −3  program/localization/hy_AM/messages.inc
  93. +19 −6 program/localization/id_ID/labels.inc
  94. +16 −5 program/localization/id_ID/messages.inc
  95. +0 −3  program/localization/is_IS/labels.inc
  96. +4 −9 program/localization/it_IT/labels.inc
  97. +0 −3  program/localization/it_IT/messages.inc
  98. +110 −170 program/localization/ja_JP/labels.inc
  99. +26 −20 program/localization/ja_JP/messages.inc
  100. +0 −3  program/localization/ka_GE/labels.inc
  101. +0 −3  program/localization/ka_GE/messages.inc
  102. +0 −3  program/localization/kh_KH/labels.inc
  103. +0 −3  program/localization/kh_KH/messages.inc
  104. +0 −3  program/localization/ko_KR/labels.inc
  105. +0 −3  program/localization/ko_KR/messages.inc
  106. +0 −3  program/localization/ku/labels.inc
  107. +0 −1  program/localization/ku/messages.inc
  108. +22 −12 program/localization/lt_LT/labels.inc
  109. +25 −5 program/localization/lt_LT/messages.inc
  110. +0 −3  program/localization/lv_LV/labels.inc
  111. +0 −3  program/localization/lv_LV/messages.inc
  112. +0 −3  program/localization/mk_MK/labels.inc
  113. +0 −3  program/localization/mk_MK/messages.inc
  114. +0 −3  program/localization/mr_IN/labels.inc
  115. +0 −3  program/localization/mr_IN/messages.inc
  116. +0 −3  program/localization/ms_MY/labels.inc
  117. +0 −1  program/localization/ms_MY/messages.inc
  118. +0 −3  program/localization/nb_NO/labels.inc
  119. +0 −3  program/localization/nb_NO/messages.inc
  120. +0 −3  program/localization/ne_NP/labels.inc
  121. +0 −3  program/localization/nl_BE/labels.inc
  122. +0 −3  program/localization/nl_BE/messages.inc
  123. +6 −9 program/localization/nl_NL/labels.inc
  124. +0 −3  program/localization/nl_NL/messages.inc
  125. +0 −3  program/localization/nn_NO/labels.inc
  126. +0 −3  program/localization/nn_NO/messages.inc
  127. +10 −11 program/localization/pl_PL/labels.inc
  128. +12 −3 program/localization/pl_PL/messages.inc
  129. +0 −3  program/localization/ps/labels.inc
  130. +0 −3  program/localization/ps/messages.inc
  131. +0 −3  program/localization/pt_BR/labels.inc
  132. +0 −3  program/localization/pt_BR/messages.inc
  133. +10 −8 program/localization/pt_PT/labels.inc
  134. +10 −4 program/localization/pt_PT/messages.inc
  135. +0 −3  program/localization/ro_RO/labels.inc
  136. +0 −3  program/localization/ro_RO/messages.inc
  137. +7 −6 program/localization/ru_RU/labels.inc
  138. +0 −3  program/localization/ru_RU/messages.inc
  139. +0 −3  program/localization/si_LK/labels.inc
  140. +0 −1  program/localization/si_LK/messages.inc
  141. +0 −3  program/localization/sk_SK/labels.inc
  142. +0 −3  program/localization/sk_SK/messages.inc
  143. +4 −9 program/localization/sl_SI/labels.inc
  144. +0 −3  program/localization/sl_SI/messages.inc
  145. +0 −3  program/localization/sq_AL/labels.inc
  146. +0 −1  program/localization/sq_AL/messages.inc
  147. +0 −3  program/localization/sr_CS/labels.inc
  148. +0 −1  program/localization/sr_CS/messages.inc
  149. +5 −7 program/localization/sv_SE/labels.inc
  150. +12 −3 program/localization/sv_SE/messages.inc
  151. +0 −3  program/localization/ta_IN/labels.inc
  152. +0 −3  program/localization/ta_IN/messages.inc
  153. +0 −3  program/localization/th_TH/labels.inc
  154. +0 −3  program/localization/tr_TR/labels.inc
  155. +0 −3  program/localization/tr_TR/messages.inc
  156. +7 −9 program/localization/uk_UA/labels.inc
  157. +13 −3 program/localization/uk_UA/messages.inc
  158. +0 −3  program/localization/vi_VN/labels.inc
  159. +0 −3  program/localization/zh_CN/labels.inc
  160. +0 −3  program/localization/zh_CN/messages.inc
  161. +2 −7 program/localization/zh_TW/labels.inc
  162. +1 −3 program/localization/zh_TW/messages.inc
  163. +7 −15 program/steps/mail/compose.inc
  164. +1 −3 program/steps/mail/copy.inc
  165. +45 −39 program/steps/mail/folders.inc
  166. +29 −64 program/steps/mail/func.inc
  167. +8 −5 program/steps/mail/getunread.inc
  168. +1 −2  program/steps/mail/list.inc
  169. +3 −3 program/steps/mail/mark.inc
  170. +5 −5 program/steps/mail/move_del.inc
  171. +1 −2  program/steps/mail/search.inc
  172. +41 −28 program/steps/mail/sendmail.inc
  173. +5 −2 program/steps/mail/show.inc
  174. +294 −0 program/steps/settings/edit_folder.inc
  175. +2 −1  program/steps/settings/edit_identity.inc
  176. +377 −0 program/steps/settings/folders.inc
  177. +0 −443 program/steps/settings/manage_folders.inc
  178. +176 −0 program/steps/settings/save_folder.inc
  179. +6 −1 program/steps/utils/html2text.inc
  180. +19 −0 skins/default/common.css
  181. +1 −1  skins/default/functions.js
  182. +2 −6 skins/default/iehacks.css
  183. +1 −21 skins/default/mail.css
  184. +39 −79 skins/default/settings.css
  185. +3 −3 skins/default/splitter.js
  186. +5 −13 skins/default/templates/compose.html
  187. +24 −0 skins/default/templates/folderedit.html
  188. +62 −0 skins/default/templates/folders.html
  189. +1 −1  skins/default/templates/identityedit.html
  190. +0 −41 skins/default/templates/managefolders.html
View
24 CHANGELOG
@@ -1,6 +1,30 @@
CHANGELOG Roundcube Webmail
===========================
+- Plugin API: Add 'pass' argument in 'authenticate' hook (#1487134)
+- Fix attachments of type message/rfc822 are not listed on attachments list
+- Add 'login_lc' config option for case-insensitive authentication (#1487113)
+- Fix window is blur'ed in IE when selecting a message (#1487316)
+- Fix cursor position on compose form in Webkit browsers (#1486674)
+- Fix setting charset of attachment filenames (#1487122)
+- Allow setting autocomplete attribute for all inputs separately (#1487313)
+- New Folder Manager UI
+- Fix invalid Request when creating a folder (#1487443)
+- Add folder size and quota indicator in folder manager (#1485780)
+- Add possibility to move a subfolder into root folder (#1486791)
+- Fix copying all messages in a folder copies only messages from current page
+- Improve performance of moving or copying of all messages in a folder
+- Fix plaintext versions of HTML messages don't contain placeholders for emotions (#1485206)
+- Improve performance of folder rename and delete actions
+- Better support for READ-ONLY and NOPERM responses handling (#1487083)
+- Add confirmation message on purge/expunge command response
+- Fix handling of untagged responses for AUTHENTICATE command (#1487450)
+- Add username and IP address to log message on unsuccessful login (#1487626)
+- Improved Mail-Followup-To and Mail-Reply-To headers handling
+- Fix charset conversion for text attachments without charset specification (#1487634)
+
+RELEASE 0.5-BETA
+----------------
- Make session data storage more robust against garbage session data (#1487136)
- Config option for autocomplete on login screen
- Allow plugin templates to include local files (#1487133)
View
3  INSTALL
@@ -17,8 +17,9 @@ REQUIREMENTS
- mbstring, fileinfo, mcrypt (optional)
* PEAR packages distributed with Roundcube or external:
- MDB2 2.5.0 or newer
- - Mail_Mime 1.7.0 or newer
+ - Mail_Mime 1.8.1 or newer
- Net_SMTP 1.4.2 or newer
+ - Auth_SASL 1.0.3 or newer
* php.ini options (see .htaccess file):
- error_reporting E_ALL & ~E_NOTICE (or lower)
- memory_limit > 16MB (increase as suitable to support large attachments)
View
3  README
@@ -25,9 +25,6 @@ Installation:
For detailed instructions on how to install Roundcube webmail on your server,
please refer to the INSTALL document in the same directory as this document.
-If you're updating an older version of Roundcube please follow the steps
-described in the UPGRADING file.
-
Licensing:
----------
View
5 UPGRADING
@@ -22,6 +22,7 @@ installation as well as the database before executig the following steps.
./SQL/[yourdbtype].update.sql that are superscribed with the
currently installed version number.
5. Make sure 'enable_installer' is set to false again.
-6. IMPORTANT: clear all records from the sessions table in your database.
- The session storage format has changed so all existing data cannot be read anymore.
+6. IMPORTANT (when upgrading from 0.4.x): clear all records from the sessions
+ table in your database. The session storage format has changed so all
+ existing data cannot be read anymore.
View
2  bin/update.sh
@@ -80,7 +80,7 @@ if ($RCI->configured) {
// Success!
if ($write1 && $write2) {
echo "Done.\n";
- echo "Your configuration files are now up-tp-date!\n";
+ echo "Your configuration files are now up-to-date!\n";
}
else {
echo "Failed to write config files!\n";
View
10 config/main.inc.php.dist
@@ -83,6 +83,7 @@ $rcmail_config['imap_delimiter'] = null;
// set these options. All can be strings or arrays of strings.
// Folders need to be ended with directory separator, e.g. "INBOX."
// (special directory "~" is an exception to this rule)
+// These can be used also to overwrite server's namespaces
$rcmail_config['imap_ns_personal'] = null;
$rcmail_config['imap_ns_other'] = null;
$rcmail_config['imap_ns_shared'] = null;
@@ -180,8 +181,13 @@ $rcmail_config['message_cache_lifetime'] = '10d';
// set the port for the ssl connection as value of this option if it differs from the default 443
$rcmail_config['force_https'] = false;
-// Allow browser-autocompletion on login form
-$rcmail_config['login_autocomplete'] = false;
+// Allow browser-autocompletion on login form.
+// 0 - disabled, 1 - username and host only, 2 - username, host, password
+$rcmail_config['login_autocomplete'] = 0;
+
+// If users authentication is not case sensitive this must be enabled.
+// You can also use it to force conversion of logins to lower case.
+$rcmail_config['login_lc'] = false;
// automatically create a new Roundcube user when log-in the first time.
// a new user will be created once the IMAP login succeeds.
View
27 index.php
@@ -2,7 +2,7 @@
/*
+-------------------------------------------------------------------------+
| Roundcube Webmail IMAP Client |
- | Version 0.5-beta |
+ | Version 0.5-rc |
| |
| Copyright (C) 2005-2010, Roundcube Dev. - Switzerland |
| |
@@ -77,16 +77,14 @@
if ($RCMAIL->task == 'login' && $RCMAIL->action == 'login') {
// purge the session in case of new login when a session already exists
$RCMAIL->kill_session();
-
+
$auth = $RCMAIL->plugins->exec_hook('authenticate', array(
'host' => $RCMAIL->autoselect_host(),
'user' => trim(get_input_value('_user', RCUBE_INPUT_POST)),
+ 'pass' => get_input_value('_pass', RCUBE_INPUT_POST, true,
+ $RCMAIL->config->get('password_charset', 'ISO-8859-1')),
'cookiecheck' => true,
));
-
- if (!isset($auth['pass']))
- $auth['pass'] = get_input_value('_pass', RCUBE_INPUT_POST, true,
- $RCMAIL->config->get('password_charset', 'ISO-8859-1'));
// check if client supports cookies
if ($auth['cookiecheck'] && empty($_COOKIE)) {
@@ -220,16 +218,15 @@
'group-addmembers' => 'groups.inc',
'group-delmembers' => 'groups.inc',
),
-
+
'settings' => array(
- 'folders' => 'manage_folders.inc',
- 'create-folder' => 'manage_folders.inc',
- 'rename-folder' => 'manage_folders.inc',
- 'delete-folder' => 'manage_folders.inc',
- 'subscribe' => 'manage_folders.inc',
- 'unsubscribe' => 'manage_folders.inc',
- 'enable-threading' => 'manage_folders.inc',
- 'disable-threading' => 'manage_folders.inc',
+ 'folders' => 'folders.inc',
+ 'rename-folder' => 'folders.inc',
+ 'delete-folder' => 'folders.inc',
+ 'subscribe' => 'folders.inc',
+ 'unsubscribe' => 'folders.inc',
+ 'purge' => 'folders.inc',
+ 'folder-size' => 'folders.inc',
'add-identity' => 'edit_identity.inc',
)
);
View
63 plugins/emoticons/emoticons.php
@@ -5,7 +5,7 @@
*
* Sample plugin to replace emoticons in plain text message body with real icons
*
- * @version 1.2.0
+ * @version 1.3
* @author Thomas Bruederli
* @author Aleksander Machniak
* @website http://roundcube.net
@@ -35,38 +35,30 @@ function replace($args)
// map of emoticon replacements
$map = array(
- '/:\)/' => html::img(array(
- 'src' => './program/js/tiny_mce/plugins/emotions/img/smiley-smile.gif',
- 'title' => ':)'
- )),
- '/:-\)/' => html::img(array(
- 'src' => './program/js/tiny_mce/plugins/emotions/img/smiley-smile.gif',
- 'title' => ':-)'
- )),
- '/(?<!mailto):D/' => html::img(array(
- 'src' => './program/js/tiny_mce/plugins/emotions/img/smiley-laughing.gif',
- 'title' => ':D'
- )),
- '/:-D/' => html::img(array(
- 'src' => './program/js/tiny_mce/plugins/emotions/img/smiley-laughing.gif',
- 'title' => ':-D'
- )),
- '/:\(/' => html::img(array(
- 'src' => './program/js/tiny_mce/plugins/emotions/img/smiley-frown.gif',
- 'title' => ':('
- )),
- '/:-\(/' => html::img(array(
- 'src' => './program/js/tiny_mce/plugins/emotions/img/smiley-frown.gif',
- 'title' => ':-('
- )),
- '/'.$entity.';\)/' => html::img(array(
- 'src' => './program/js/tiny_mce/plugins/emotions/img/smiley-wink.gif',
- 'title' => ';)'
- )),
- '/'.$entity.';-\)/' => html::img(array(
- 'src' => './program/js/tiny_mce/plugins/emotions/img/smiley-wink.gif',
- 'title' => ';-)'
- )),
+ '/:\)/' => $this->img_tag('smiley-smile.gif', ':)' ),
+ '/:-\)/' => $this->img_tag('smiley-smile.gif', ':-)' ),
+ '/(?<!mailto):D/' => $this->img_tag('smiley-laughing.gif', ':D' ),
+ '/:-D/' => $this->img_tag('smiley-laughing.gif', ':-D' ),
+ '/:\(/' => $this->img_tag('smiley-frown.gif', ':(' ),
+ '/:-\(/' => $this->img_tag('smiley-frown.gif', ':-(' ),
+ '/'.$entity.';\)/' => $this->img_tag('smiley-wink.gif', ';)' ),
+ '/'.$entity.';-\)/' => $this->img_tag('smiley-wink.gif', ';-)' ),
+ '/8\)/' => $this->img_tag('smiley-cool.gif', '8)' ),
+ '/8-\)/' => $this->img_tag('smiley-cool.gif', '8-)' ),
+ '/(?<!mailto):O/i' => $this->img_tag('smiley-surprised.gif', ':O' ),
+ '/(?<!mailto):-O/i' => $this->img_tag('smiley-surprised.gif', ':-O' ),
+ '/(?<!mailto):P/i' => $this->img_tag('smiley-tongue-out.gif', ':P' ),
+ '/(?<!mailto):-P/i' => $this->img_tag('smiley-tongue-out.gif', ':-P' ),
+ '/(?<!mailto):@/i' => $this->img_tag('smiley-yell.gif', ':@' ),
+ '/(?<!mailto):-@/i' => $this->img_tag('smiley-yell.gif', ':-@' ),
+ '/O:\)/i' => $this->img_tag('smiley-innocent.gif', 'O:)' ),
+ '/O:-\)/i' => $this->img_tag('smiley-innocent.gif', 'O:-)' ),
+ '/(?<!mailto):$/' => $this->img_tag('smiley-embarassed.gif', ':$' ),
+ '/(?<!mailto):-$/' => $this->img_tag('smiley-embarassed.gif', ':-$' ),
+ '/(?<!mailto):\*/i' => $this->img_tag('smiley-kiss.gif', ':*' ),
+ '/(?<!mailto):-\*/i' => $this->img_tag('smiley-kiss.gif', ':-*' ),
+ '/(?<!mailto):S/i' => $this->img_tag('smiley-undecided.gif', ':S' ),
+ '/(?<!mailto):-S/i' => $this->img_tag('smiley-undecided.gif', ':-S' ),
);
if ($args['type'] == 'plain') {
@@ -77,4 +69,9 @@ function replace($args)
return $args;
}
+ private function img_tag($ico, $title)
+ {
+ $path = './program/js/tiny_mce/plugins/emotions/img/';
+ return html::img(array('src' => $path.$ico, 'title' => $title));
+ }
}
View
2  plugins/managesieve/localization/fr_FR.inc
@@ -26,6 +26,8 @@ $labels['messageredirect'] = 'Transférer le message à';
$labels['messagereply'] = 'Répondre avec le message';
$labels['messagedelete'] = 'Supprimer le message';
$labels['messagediscard'] = 'Rejeter avec le message';
+$labels['messagecopyto'] = 'Copier le message vers';
+$labels['messagesendcopy'] = 'Envoyer une copie du message à';
$labels['messagesrules'] = 'Pour les mails entrants:';
$labels['messagesactions'] = '...exécuter les actions suivantes:';
$labels['add'] = 'Ajouter';
View
33 plugins/managesieve/localization/ru_RU.inc
@@ -1,4 +1,22 @@
<?php
+/*
+
++-----------------------------------------------------------------------+
+| plugins/managesieve/localization/ru_RU.inc |
+| |
+| Russian translation for roundcube/managesieve plugin |
+| Copyright (C) 2008-2010 |
+| Licensed under the GNU GPL |
+| |
++-----------------------------------------------------------------------+
+| Author: |
+| Updates: Sergey Dukachev <iam@dukess.ru> |
++-----------------------------------------------------------------------+
+
+@version 2010-10-11
+
+*/
+
$labels['filters'] = 'Фильтры';
$labels['managefilters'] = 'Управление фильтрами для входящей почты';
$labels['filtername'] = 'Название фильтра';
@@ -21,7 +39,9 @@ $labels['filterover'] = 'на';
$labels['addrule'] = 'Добавить правило';
$labels['delrule'] = 'Удалить правило';
$labels['messagemoveto'] = 'Переместить сообщение в';
-$labels['messageredirect'] = 'Перенаправить сообщение на ';
+$labels['messageredirect'] = 'Перенаправить сообщение на';
+$labels['messagecopyto'] = 'Скопировать сообщение в';
+$labels['messagesendcopy'] = 'Отправить копию сообщения на';
$labels['messagereply'] = 'Ответить с сообщением';
$labels['messagedelete'] = 'Удалить сообщение';
$labels['messagediscard'] = 'Отбросить с сообщением';
@@ -38,12 +58,13 @@ $labels['rulestop'] = 'Закончить выполнение';
$labels['filterset'] = 'Набор фильтров';
$labels['filtersetadd'] = 'Добавить набор фильтров';
$labels['filtersetdel'] = 'Удалить текущий набор фильтров';
-$labels['filtersetact'] = 'Активировать текущий набор фильтров';
+$labels['filtersetact'] = 'Включить текущий набор фильтров';
+$labels['filtersetdeact'] = 'Отключить текущий набор фильтров';
$labels['filtersetget'] = 'Скачать набор фильтров в виде текста';
$labels['filterdef'] = 'Описание фильтра';
$labels['filtersetname'] = 'Название набора фильтров';
$labels['newfilterset'] = 'Новый набор фильтров';
-$labels['active'] = 'активный';
+$labels['active'] = 'используется';
$labels['none'] = 'пустой';
$labels['fromset'] = 'из набора';
$labels['fromfile'] = 'из файла';
@@ -61,9 +82,11 @@ $messages['ruledeleteconfirm'] = 'Вы уверенны, что хотите у
$messages['actiondeleteconfirm'] = 'Вы уверенны, что хотите удалить это действие?';
$messages['forbiddenchars'] = 'Недопустимые символы в поле';
$messages['cannotbeempty'] = 'Поле не может быть пустым';
-$messages['setactivateerror'] = 'Невозможно активировать выбранный набор фильтров. Ошибка сервера';
+$messages['setactivateerror'] = 'Невозможно включить выбранный набор фильтров. Ошибка сервера';
+$messages['setdeactivateerror'] = 'Невозможно отключить выбранный набор фильтров. Ошибка сервера';
$messages['setdeleteerror'] = 'Невозможно удалить выбранный набор фильтров. Ошибка сервера';
-$messages['setactivated'] = 'Набор фильтров успешно активирован';
+$messages['setactivated'] = 'Набор фильтров успешно включён';
+$messages['setdeactivated'] = 'Набор фильтров успешно отключён';
$messages['setdeleted'] = 'Набор фильтров успешно удалён';
$messages['setdeleteconfirm'] = 'Вы уверены в том, что хотите удалить выбранный набор фильтров?';
$messages['setcreateerror'] = 'Невозможно создать набор фильтров. Ошибка сервера';
View
4 plugins/new_user_dialog/localization/es_ES.inc
@@ -1,7 +1,7 @@
<?php
$labels = array();
-$labels['identitydialogtitle'] = 'Por favor completa tus datos';
-$labels['identitydialoghint'] = 'Este diálogo sólo aparece la primera vez que te conectas.';
+$labels['identitydialogtitle'] = 'Por favor, complete sus datos personales';
+$labels['identitydialoghint'] = 'Este diálogo sólo aparecerá la primera vez que se conecte al correo.';
?>
View
1  plugins/new_user_dialog/new_user_dialog.php
@@ -85,6 +85,7 @@ function render_page($p)
"$(document).ready(function () {
rcmail.message_list.key_press = function(){};
rcmail.message_list.key_down = function(){};
+ $('input[name=_name]').focus();
});", 'foot');
$this->include_stylesheet('newuserdialog.css');
View
26 plugins/new_user_dialog/package.xml
@@ -13,10 +13,10 @@
<email>roundcube@gmail.com</email>
<active>yes</active>
</lead>
- <date>2010-05-27</date>
+ <date>2010-12-02</date>
<time>12:00:00</time>
<version>
- <release>1.2</release>
+ <release>1.3</release>
<api>1.0</api>
</version>
<stability>
@@ -25,8 +25,8 @@
</stability>
<license uri="http://www.gnu.org/licenses/gpl-2.0.html">GNU GPLv2</license>
<notes>
-- Add overlay box only to mail task main template
-- Fix possible error on form submission (#1486103)
+- Added setting of focus on name input
+- Added gl_ES translation
</notes>
<contents>
<dir baseinstalldir="/" name="/">
@@ -45,6 +45,7 @@
<file name="de_DE.inc" role="data" />
<file name="es_ES.inc" role="data" />
<file name="et_EE.inc" role="data" />
+ <file name="gl_ES.inc" role="data" />
<file name="it_IT.inc" role="data" />
<file name="ja_JP.inc" role="data" />
<file name="nl_NL.inc" role="data" />
@@ -101,5 +102,22 @@
- Fix space bar and backspace buttons not working (#1486726)
</notes>
</release>
+ <release>
+ <date>2010-05-27</date>
+ <time>12:00:00</time>
+ <version>
+ <release>1.2</release>
+ <api>1.0</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <license uri="http://www.gnu.org/licenses/gpl-2.0.html">GNU GPLv2</license>
+ <notes>
+- Add overlay box only to mail task main template
+- Fix possible error on form submission (#1486103)
+ </notes>
+ </release>
</changelog>
</package>
View
2  plugins/password/config.inc.php.dist
@@ -127,6 +127,7 @@ $rcmail_config['password_ldap_adminPW'] = null;
// '%login' will be replaced by the current roundcube user's login
// '%name' will be replaced by the current roundcube user's name part
// '%domain' will be replaced by the current roundcube user's domain part
+// '%dc' will be replaced by domain name hierarchal string e.g. "dc=test,dc=domain,dc=com"
// Exemple: 'uid=%login,ou=people,dc=exemple,dc=com'
$rcmail_config['password_ldap_userDN_mask'] = 'uid=%login,ou=people,dc=exemple,dc=com';
@@ -164,6 +165,7 @@ $rcmail_config['password_ldap_search_base'] = 'ou=people,dc=example,dc=com';
// '%login' will be replaced by the current roundcube user's login
// '%name' will be replaced by the current roundcube user's name part
// '%domain' will be replaced by the current roundcube user's domain part
+// '%dc' will be replaced by domain name hierarchal string e.g. "dc=test,dc=domain,dc=com"
// Example: '(uid=%login)'
// Example: '(&(objectClass=posixAccount)(uid=%login))'
$rcmail_config['password_ldap_search_filter'] = '(uid=%login)';
View
2  plugins/password/drivers/chpasswd.php
@@ -18,7 +18,7 @@ function password_save($currpass, $newpass)
$username = $_SESSION['username'];
$handle = popen($cmd, "w");
- fwrite($handle, "$username:$newpass");
+ fwrite($handle, "$username:$newpass\n");
if (pclose($handle) == 0) {
return PASSWORD_SUCCESS;
View
38 plugins/password/drivers/ldap.php
@@ -18,18 +18,18 @@ function password_save($curpass, $passwd)
{
$rcmail = rcmail::get_instance();
require_once ('Net/LDAP2.php');
-
+
// Building user DN
if ($userDN = $rcmail->config->get('password_ldap_userDN_mask')) {
$userDN = substitute_vars($userDN);
} else {
$userDN = search_userdn($rcmail);
}
-
+
if (empty($userDN)) {
return PASSWORD_CONNECT_ERROR;
}
-
+
// Connection Method
switch($rcmail->config->get('password_ldap_method')) {
case 'admin':
@@ -42,7 +42,7 @@ function password_save($curpass, $passwd)
$bindpw = $curpass;
break;
}
-
+
// Configuration array
$ldapConfig = array (
'binddn' => $binddn,
@@ -53,27 +53,27 @@ function password_save($curpass, $passwd)
'starttls' => $rcmail->config->get('password_ldap_starttls'),
'version' => $rcmail->config->get('password_ldap_version'),
);
-
+
// Connecting using the configuration array
$ldap = Net_LDAP2::connect($ldapConfig);
-
+
// Checking for connection error
if (PEAR::isError($ldap)) {
return PASSWORD_CONNECT_ERROR;
}
-
+
// Crypting new password
$newCryptedPassword = hashPassword($passwd, $rcmail->config->get('password_ldap_encodage'));
if (!$newCryptedPassword) {
return PASSWORD_CRYPT_ERROR;
}
-
+
// Writing new crypted password to LDAP
$userEntry = $ldap->getEntry($userDN);
if (Net_LDAP2::isError($userEntry)) {
return PASSWORD_CONNECT_ERROR;
}
-
+
$pwattr = $rcmail->config->get('password_ldap_pwattr');
$force = $rcmail->config->get('password_ldap_force_replace');
@@ -132,25 +132,30 @@ function search_userdn($rcmail)
if (PEAR::isError($result) || ($result->count() != 1)) {
return '';
}
-
+
return $result->current()->dn();
}
/**
- * Substitute %login, %name and %domain in $str.
+ * Substitute %login, %name, %domain, %dc in $str.
* See plugin config for details.
*/
function substitute_vars($str)
{
$rcmail = rcmail::get_instance();
+ $domain = $rcmail->user->get_username('domain');
+ $dc = 'dc='.strtr($domain, array('.' => ',dc=')); // hierarchal domain string
+
$str = str_replace(array(
'%login',
'%name',
'%domain',
+ '%dc',
), array(
$_SESSION['username'],
$rcmail->user->get_username('local'),
- $rcmail->user->get_username('domain'),
+ $domain,
+ $dc,
), $str
);
@@ -178,7 +183,7 @@ function hashPassword( $passwordClear, $encodageType )
case 'crypt':
$cryptedPassword = '{CRYPT}' . crypt($passwordClear,randomSalt(2));
break;
-
+
case 'ext_des':
// extended des crypt. see OpenBSD crypt man page.
if ( ! defined( 'CRYPT_EXT_DES' ) || CRYPT_EXT_DES == 0 ) {
@@ -263,8 +268,7 @@ function hashPassword( $passwordClear, $encodageType )
* @param int $length The length of the salt string to generate.
* @return string The generated salt string.
*/
-
-function randomSalt( $length )
+function randomSalt( $length )
{
$possible = '0123456789'.
'abcdefghijklmnopqrstuvwxyz'.
@@ -273,8 +277,8 @@ function randomSalt( $length )
$str = '';
// mt_srand((double)microtime() * 1000000);
- while( strlen( $str ) < $length )
- $str .= substr( $possible, ( rand() % strlen( $possible ) ), 1 );
+ while (strlen($str) < $length)
+ $str .= substr($possible, (rand() % strlen($possible)), 1);
return $str;
}
View
35 plugins/password/drivers/ldap_simple.php
@@ -20,7 +20,7 @@ function password_save($curpass, $passwd)
return PASSWORD_CONNECT_ERROR;
}
- /* Set protocol version */
+ /* Set protocol version */
if (!ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, $rcmail->config->get('password_ldap_version'))) {
ldap_unbind($ds);
return PASSWORD_CONNECT_ERROR;
@@ -40,12 +40,12 @@ function password_save($curpass, $passwd)
} else {
$user_dn = ldap_simple_search_userdn($rcmail, $ds);
}
-
+
if (empty($user_dn)) {
ldap_unbind($ds);
return PASSWORD_CONNECT_ERROR;
}
-
+
/* Connection method */
switch ($rcmail->config->get('password_ldap_method')) {
case 'admin':
@@ -64,27 +64,27 @@ function password_save($curpass, $passwd)
ldap_unbind($ds);
return PASSWORD_CONNECT_ERROR;
}
-
+
/* Crypting new password */
$passwd = ldap_simple_hash_password($passwd, $rcmail->config->get('password_ldap_encodage'));
if (!$passwd) {
ldap_unbind($ds);
return PASSWORD_CRYPT_ERROR;
}
-
+
$entree[$rcmail->config->get('password_ldap_pwattr')] = $passwd;
/* Updating PasswordLastChange Attribute if desired */
if ($lchattr = $rcmail->config->get('password_ldap_lchattr')) {
- $entree[$lchattr] = (int)(time() / 86400)
+ $entree[$lchattr] = (int)(time() / 86400);
}
-
+
if (!ldap_modify($ds, $user_dn, $entree)) {
ldap_unbind($ds);
return PASSWORD_CONNECT_ERROR;
}
-
+
/* All done, no error */
ldap_unbind($ds);
return PASSWORD_SUCCESS;
@@ -101,34 +101,37 @@ function ldap_simple_search_userdn($rcmail, $ds)
if (!ldap_bind($ds, $rcmail->config->get('password_ldap_searchDN'), $rcmail->config->get('password_ldap_searchPW'))) {
return false;
}
-
+
/* Search for the DN */
if (!$sr = ldap_search($ds, $rcmail->config->get('password_ldap_search_base'), ldap_simple_substitute_vars($rcmail->config->get('password_ldap_search_filter')))) {
return false;
}
-
+
/* If no or more entries were found, return false */
if (ldap_count_entries($ds, $sr) != 1) {
return false;
}
-
+
return ldap_get_dn($ds, ldap_first_entry($ds, $sr));
}
/**
- * Substitute %login, %name and %domain in $str
+ * Substitute %login, %name, %domain, %dc in $str
* See plugin config for details
*/
function ldap_simple_substitute_vars($str)
{
$str = str_replace('%login', $_SESSION['username'], $str);
$str = str_replace('%l', $_SESSION['username'], $str);
-
+
$parts = explode('@', $_SESSION['username']);
+
if (count($parts) == 2) {
+ $dc = 'dc='.strtr($parts[1], array('.' => ',dc=')); // hierarchal domain string
+
$str = str_replace('%name', $parts[0], $str);
- $str = str_replace('%n', $parts[0], $str);
-
+ $str = str_replace('%n', $parts[0], $str);
+ $str = str_replace('%dc', $dc, $str);
$str = str_replace('%domain', $parts[1], $str);
$str = str_replace('%d', $parts[1], $str);
}
@@ -228,6 +231,6 @@ function ldap_simple_random_salt($length)
while (strlen($str) < $length) {
$str .= substr($possible, (rand() % strlen($possible)), 1);
}
-
+
return $str;
}
View
8 plugins/password/drivers/sql.php
@@ -33,7 +33,7 @@ function password_save($curpass, $passwd)
if ($err = $db->is_error())
return PASSWORD_ERROR;
-
+
// crypted password
if (strpos($sql, '%c') !== FALSE) {
$salt = '';
@@ -56,7 +56,11 @@ function password_save($curpass, $passwd)
$dovecotpw = 'dovecotpw';
if (!($method = $rcmail->config->get('password_dovecotpw_method')))
$method = 'CRAM-MD5';
- $tmpfile = tempnam('/tmp', 'roundcube-');
+
+ // use common temp dir
+ $tmp_dir = $rcmail->config->get('temp_dir');
+ $tmpfile = tempnam($tmp_dir, 'roundcube-');
+
$pipe = popen("'$dovecotpw' -s '$method' > '$tmpfile'", "w");
if (!$pipe) {
unlink($tmpfile);
View
4 plugins/password/package.xml
@@ -29,6 +29,10 @@
<notes>
- hMail driver: add username_domain detection (#1487100)
- hMail driver: HTML tags in logged messages should be stripped off (#1487099)
+- Chpasswd driver: add newline at end of input to chpasswd binary (#1487141)
+- Fix usage of configured temp_dir instead of /tmp (#1487447)
+- ldap_simple driver: fix parse error
+- ldap/ldap_simple drivers: support %dc variable in config
</notes>
<contents>
<dir baseinstalldir="/" name="/">
View
2  program/include/iniset.php
@@ -36,7 +36,7 @@
}
// application constants
-define('RCMAIL_VERSION', '0.5-beta');
+define('RCMAIL_VERSION', '0.5-rc');
define('RCMAIL_CHARSET', 'UTF-8');
define('JS_OBJECT_NAME', 'rcmail');
define('RCMAIL_START', microtime(true));
View
178 program/include/main.inc
@@ -1193,21 +1193,33 @@ function rcmail_log_login()
if (!$RCMAIL->config->get('log_logins') || !$RCMAIL->user)
return;
- $address = $_SERVER['REMOTE_ADDR'];
- // append the NGINX X-Real-IP header, if set
- if (!empty($_SERVER['HTTP_X_REAL_IP'])) {
- $remote_ip[] = 'X-Real-IP: ' . $_SERVER['HTTP_X_REAL_IP'];
- }
- // append the X-Forwarded-For header, if set
- if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
- $remote_ip[] = 'X-Forwarded-For: ' . $_SERVER['HTTP_X_FORWARDED_FOR'];
- }
+ write_log('userlogins', sprintf('Successful login for %s (ID: %d) from %s',
+ $RCMAIL->user->get_username(), $RCMAIL->user->ID, rcmail_remote_ip()));
+}
- if (!empty($remote_ip))
- $address .= '(' . implode(',', $remote_ip) . ')';
- write_log('userlogins', sprintf('Successful login for %s (ID: %d) from %s',
- $RCMAIL->user->get_username(), $RCMAIL->user->ID, $address));
+/**
+ * Returns remote IP address and forwarded addresses if found
+ *
+ * @return string Remote IP address(es)
+ */
+function rcmail_remote_ip()
+{
+ $address = $_SERVER['REMOTE_ADDR'];
+
+ // append the NGINX X-Real-IP header, if set
+ if (!empty($_SERVER['HTTP_X_REAL_IP'])) {
+ $remote_ip[] = 'X-Real-IP: ' . $_SERVER['HTTP_X_REAL_IP'];
+ }
+ // append the X-Forwarded-For header, if set
+ if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
+ $remote_ip[] = 'X-Forwarded-For: ' . $_SERVER['HTTP_X_FORWARDED_FOR'];
+ }
+
+ if (!empty($remote_ip))
+ $address .= '(' . implode(',', $remote_ip) . ')';
+
+ return $address;
}
@@ -1219,7 +1231,7 @@ function rcube_timer()
{
return microtime(true);
}
-
+
/**
* @access private
@@ -1314,8 +1326,13 @@ function rcmail_mailbox_select($p = array())
$p += array('maxlength' => 100, 'realnames' => false);
$a_mailboxes = array();
-
- foreach ($RCMAIL->imap->list_mailboxes() as $folder)
+
+ if ($p['unsubscribed'])
+ $list = $RCMAIL->imap->list_unsubscribed();
+ else
+ $list = $RCMAIL->imap->list_mailboxes();
+
+ foreach ($list as $folder)
if (empty($p['exceptions']) || !in_array($folder, $p['exceptions']))
rcmail_build_folder_tree($a_mailboxes, $folder, $RCMAIL->imap->get_hierarchy_delimiter());
@@ -1551,6 +1568,97 @@ function rcmail_localize_foldername($name)
}
+function rcmail_quota_display($attrib)
+{
+ global $OUTPUT;
+
+ if (!$attrib['id'])
+ $attrib['id'] = 'rcmquotadisplay';
+
+ if(isset($attrib['display']))
+ $_SESSION['quota_display'] = $attrib['display'];
+
+ $OUTPUT->add_gui_object('quotadisplay', $attrib['id']);
+
+ $quota = rcmail_quota_content($attrib);
+
+ $OUTPUT->add_script('$(document).ready(function(){
+ rcmail.set_quota('.json_serialize($quota).')});', 'foot');
+
+ return html::span($attrib, '');
+}
+
+
+function rcmail_quota_content($attrib=NULL)
+{
+ global $RCMAIL;
+
+ $quota = $RCMAIL->imap->get_quota();
+ $quota = $RCMAIL->plugins->exec_hook('quota', $quota);
+
+ $quota_result = (array) $quota;
+ $quota_result['type'] = isset($_SESSION['quota_display']) ? $_SESSION['quota_display'] : '';
+
+ if (!$quota['total'] && $RCMAIL->config->get('quota_zero_as_unlimited')) {
+ $quota_result['title'] = rcube_label('unlimited');
+ $quota_result['percent'] = 0;
+ }
+ else if ($quota['total']) {
+ if (!isset($quota['percent']))
+ $quota_result['percent'] = min(100, round(($quota['used']/max(1,$quota['total']))*100));
+
+ $title = sprintf('%s / %s (%.0f%%)',
+ show_bytes($quota['used'] * 1024), show_bytes($quota['total'] * 1024),
+ $quota_result['percent']);
+
+ $quota_result['title'] = $title;
+
+ if ($attrib['width'])
+ $quota_result['width'] = $attrib['width'];
+ if ($attrib['height'])
+ $quota_result['height'] = $attrib['height'];
+ }
+ else {
+ $quota_result['title'] = rcube_label('unknown');
+ $quota_result['percent'] = 0;
+ }
+
+ return $quota_result;
+}
+
+
+/**
+ * Outputs error message according to server error/response codes
+ *
+ * @param string Fallback message label
+ * @param string Fallback message label arguments
+ *
+ * @return void
+ */
+function rcmail_display_server_error($fallback=null, $fallback_args=null)
+{
+ global $RCMAIL;
+
+ $err_code = $RCMAIL->imap->get_error_code();
+ $res_code = $RCMAIL->imap->get_response_code();
+
+ if ($res_code == rcube_imap::NOPERM) {
+ $RCMAIL->output->show_message('errornoperm', 'error');
+ }
+ else if ($res_code == rcube_imap::READONLY) {
+ $RCMAIL->output->show_message('errorreadonly', 'error');
+ }
+ else if ($err_code && ($err_str = $RCMAIL->imap->get_error_str())) {
+ $RCMAIL->output->show_message('servererrormsg', 'error', array('msg' => $err_str));
+ }
+ else if ($fallback) {
+ $RCMAIL->output->show_message($fallback, 'error', $fallback_args);
+ }
+
+ return true;
+}
+
+
/**
* Output HTML editor scripts
*
@@ -1583,6 +1691,43 @@ function rcube_html_editor($mode='')
/**
+ * Replaces TinyMCE's emoticon images with plain-text representation
+ *
+ * @param string HTML content
+ * @return string HTML content
+ */
+function rcmail_replace_emoticons($html)
+{
+ $emoticons = array(
+ '8-)' => 'smiley-cool',
+ ':-#' => 'smiley-foot-in-mouth',
+ ':-*' => 'smiley-kiss',
+ ':-X' => 'smiley-sealed',
+ ':-P' => 'smiley-tongue-out',
+ ':-@' => 'smiley-yell',
+ ":'(" => 'smiley-cry',
+ ':-(' => 'smiley-frown',
+ ':-D' => 'smiley-laughing',
+ ':-)' => 'smiley-smile',
+ ':-S' => 'smiley-undecided',
+ ':-$' => 'smiley-embarassed',
+ 'O:-)' => 'smiley-innocent',
+ ':-|' => 'smiley-money-mouth',
+ ':-O' => 'smiley-surprised',
+ ';-)' => 'smiley-wink',
+ );
+
+ foreach ($emoticons as $idx => $file) {
+ // <img title="Cry" src="http://.../program/js/tiny_mce/plugins/emotions/img/smiley-cry.gif" border="0" alt="Cry" />
+ $search[] = '/<img title="[a-z ]+" src="https?:\/\/[a-z0-9_.\/-]+\/tiny_mce\/plugins\/emotions\/img\/'.$file.'.gif"[^>]+\/>/i';
+ $replace[] = $idx;
+ }
+
+ return preg_replace($search, $replace, $html);
+}
+
+
+/**
* Check if working in SSL mode
*
* @param integer HTTPS port number
@@ -1817,3 +1962,4 @@ function log_bug($arg_arr)
flush();
}
}
+
View
32 program/include/rcmail.php
@@ -678,10 +678,16 @@ function login($username, $pass, $host=NULL)
$username .= '@'.rcube_parse_host($config['username_domain']);
}
+ // Convert username to lowercase. If IMAP backend
+ // is case-insensitive we need to store always the same username (#1487113)
+ if ($config['login_lc']) {
+ $username = mb_strtolower($username);
+ }
+
// try to resolve email address from virtuser table
- if (strpos($username, '@'))
- if ($virtuser = rcube_user::email2user($username))
- $username = $virtuser;
+ if (strpos($username, '@') && ($virtuser = rcube_user::email2user($username))) {
+ $username = $virtuser;
+ }
// Here we need IDNA ASCII
// Only rcube_contacts class is using domain names in Unicode
@@ -704,8 +710,14 @@ function login($username, $pass, $host=NULL)
if (!($imap_login = $this->imap->connect($host, $username, $pass, $imap_port, $imap_ssl))) {
// try with lowercase
$username_lc = mb_strtolower($username);
- if ($username_lc != $username && ($imap_login = $this->imap->connect($host, $username_lc, $pass, $imap_port, $imap_ssl)))
- $username = $username_lc;
+ if ($username_lc != $username) {
+ // try to find user record again -> overwrite username
+ if (!$user && ($user = rcube_user::query($username_lc, $host)))
+ $username_lc = $user->data['username'];
+
+ if ($imap_login = $this->imap->connect($host, $username_lc, $pass, $imap_port, $imap_ssl))
+ $username = $username_lc;
+ }
}
// exit if IMAP login failed
@@ -1203,8 +1215,14 @@ public function decrypt($cipher, $key = 'des_key', $base64 = true)
if (function_exists('mcrypt_module_open') &&
($td = mcrypt_module_open(MCRYPT_TripleDES, "", MCRYPT_MODE_CBC, "")))
{
- $iv = substr($cipher, 0, mcrypt_enc_get_iv_size($td));
- $cipher = substr($cipher, mcrypt_enc_get_iv_size($td));
+ $iv_size = mcrypt_enc_get_iv_size($td);
+ $iv = substr($cipher, 0, $iv_size);
+
+ // session corruption? (#1485970)
+ if (strlen($iv) < $iv_size)
+ return '';
+
+ $cipher = substr($cipher, $iv_size);
mcrypt_generic_init($td, $this->config->get_crypto_key($key), $iv);
$clear = mdecrypt_generic($td, $cipher);
mcrypt_generic_deinit($td);
View
327 program/include/rcube_imap.php
@@ -100,6 +100,16 @@ class rcube_imap
'RETURN-PATH',
);
+ const UNKNOWN = 0;
+ const NOPERM = 1;
+ const READONLY = 2;
+ const TRYCREATE = 3;
+ const INUSE = 4;
+ const OVERQUOTA = 5;
+ const ALREADYEXISTS = 6;
+ const NONEXISTENT = 7;
+ const CONTACTADMIN = 8;
+
/**
* Object constructor
@@ -156,21 +166,20 @@ function connect($host, $user, $pass, $port=143, $use_ssl=null)
$this->ssl = $use_ssl;
if ($this->conn->connected()) {
- // print trace messages
- if ($this->conn->message && ($this->debug_level & 8)) {
- console($this->conn->message);
- }
// get namespace and delimiter
$this->set_env();
-
return true;
}
// write error log
else if ($this->conn->error) {
- if ($pass && $user)
+ if ($pass && $user) {
+ $message = sprintf("Login failed for %s from %s. %s",
+ $user, rcmail_remote_ip(), $this->conn->error);
+
raise_error(array('code' => 403, 'type' => 'imap',
'file' => __FILE__, 'line' => __LINE__,
- 'message' => $this->conn->error), true, false);
+ 'message' => $message), true, false);
+ }
}
return false;
@@ -185,7 +194,7 @@ function connect($host, $user, $pass, $port=143, $use_ssl=null)
*/
function close()
{
- $this->conn->close();
+ $this->conn->closeConnection();
$this->write_cache();
}
@@ -198,11 +207,11 @@ function close()
*/
function reconnect()
{
- $this->close();
- $this->connect($this->host, $this->user, $this->pass, $this->port, $this->ssl);
+ $this->conn->closeConnection();
+ $connected = $this->connect($this->host, $this->user, $this->pass, $this->port, $this->ssl);
// issue SELECT command to restore connection status
- if ($this->mailbox)
+ if ($connected && strlen($this->mailbox))
$this->conn->select($this->mailbox);
}
@@ -225,7 +234,51 @@ function get_error_code()
*/
function get_error_str()
{
- return ($this->conn) ? $this->conn->error : '';
+ return ($this->conn) ? $this->conn->error : null;
+ }
+
+
+ /**
+ * Returns code of last command response
+ *
+ * @return int Response code
+ */
+ function get_response_code()
+ {
+ if (!$this->conn)
+ return self::UNKNOWN;
+
+ switch ($this->conn->resultcode) {
+ case 'NOPERM':
+ return self::NOPERM;
+ case 'READ-ONLY':
+ return self::READONLY;
+ case 'TRYCREATE':
+ return self::TRYCREATE;
+ case 'INUSE':
+ return self::INUSE;
+ case 'OVERQUOTA':
+ return self::OVERQUOTA;
+ case 'ALREADYEXISTS':
+ return self::ALREADYEXISTS;
+ case 'NONEXISTENT':
+ return self::NONEXISTENT;
+ case 'CONTACTADMIN':
+ return self::CONTACTADMIN;
+ default:
+ return self::UNKNOWN;
+ }
+ }
+
+
+ /**
+ * Returns last command response
+ *
+ * @return string Response
+ */
+ function get_response_str()
+ {
+ return ($this->conn) ? $this->conn->result : null;
}
@@ -300,9 +353,9 @@ function set_mailbox($new_mbox)
* @param string $mailbox Mailbox/Folder name
* @access public
*/
- function select_mailbox($mailbox)
+ function select_mailbox($mailbox=null)
{
- $mailbox = $this->mod_mailbox($mailbox);
+ $mailbox = strlen($mailbox) ? $this->mod_mailbox($mailbox) : $this->mailbox;
$selected = $this->conn->select($mailbox);
@@ -493,56 +546,56 @@ private function set_env()
$imap_shared = $config->get('imap_ns_shared');
$imap_delimiter = $config->get('imap_delimiter');
- if ($imap_delimiter) {
- $this->delimiter = $imap_delimiter;
- }
-
if (!$this->conn)
return;
$ns = $this->conn->getNamespace();
- // NAMESPACE supported
+ // Set namespaces (NAMESPACE supported)
if (is_array($ns)) {
$this->namespace = $ns;
-
- if (empty($this->delimiter))
- $this->delimiter = $ns['personal'][0][1];
- if (empty($this->delimiter))
- $this->delimiter = $this->conn->getHierarchyDelimiter();
- if (empty($this->delimiter))
- $this->delimiter = '/';
}
- // not supported, get namespace from config
- else if ($imap_personal !== null || $imap_shared !== null || $imap_other !== null) {
- if (empty($this->delimiter))
- $this->delimiter = $this->conn->getHierarchyDelimiter();
- if (empty($this->delimiter))
- $this->delimiter = '/';
-
+ else {
$this->namespace = array(
'personal' => NULL,
'other' => NULL,
'shared' => NULL,
);
+ }
- if ($imap_personal !== null) {
- foreach ((array)$imap_personal as $dir) {
- $this->namespace['personal'][] = array($dir, $this->delimiter);
- }
+ if ($imap_delimiter) {
+ $this->delimiter = $imap_delimiter;
+ }
+ if (empty($this->delimiter)) {
+ $this->delimiter = $this->namespace['personal'][0][1];
+ }
+ if (empty($this->delimiter)) {
+ $this->delimiter = $this->conn->getHierarchyDelimiter();
+ }
+ if (empty($this->delimiter)) {
+ $this->delimiter = '/';
+ }
+
+ // Overwrite namespaces
+ if ($imap_personal !== null) {
+ $this->namespace['personal'] = NULL;
+ foreach ((array)$imap_personal as $dir) {
+ $this->namespace['personal'][] = array($dir, $this->delimiter);
}
- if ($imap_other !== null) {
- foreach ((array)$imap_other as $dir) {
- if ($dir) {
- $this->namespace['other'][] = array($dir, $this->delimiter);
- }
+ }
+ if ($imap_other !== null) {
+ $this->namespace['other'] = NULL;
+ foreach ((array)$imap_other as $dir) {
+ if ($dir) {
+ $this->namespace['other'][] = array($dir, $this->delimiter);
}
}
- if ($imap_shared !== null) {
- foreach ((array)$imap_shared as $dir) {
- if ($dir) {
- $this->namespace['shared'][] = array($dir, $this->delimiter);
- }
+ }
+ if ($imap_shared !== null) {
+ $this->namespace['shared'] = NULL;
+ foreach ((array)$imap_shared as $dir) {
+ if ($dir) {
+ $this->namespace['shared'][] = array($dir, $this->delimiter);
}
}
}
@@ -617,7 +670,7 @@ private function _messagecount($mailbox='', $mode='ALL', $force=false, $status=t
}
// RECENT count is fetched a bit different
else if ($mode == 'RECENT') {
- $count = $this->conn->checkForRecent($mailbox);
+ $count = $this->conn->countRecent($mailbox);
}
// use SEARCH for message counting
else if ($this->skip_deleted) {
@@ -2376,20 +2429,21 @@ function &get_message_part($uid, $part=1, $o_part=NULL, $print=NULL, $fp=NULL)
// TODO: Add caching for message parts
- if (!$part) $part = 'TEXT';
+ if (!$part) {
+ $part = 'TEXT';
+ }
$body = $this->conn->handlePartBody($this->mailbox, $uid, true, $part,
$o_part->encoding, $print, $fp);
- if ($fp || $print)
+ if ($fp || $print) {
return true;
+ }
- // convert charset (if text or message part)
- if ($body && ($o_part->ctype_primary == 'text' || $o_part->ctype_primary == 'message')) {
- // assume default if no charset specified
- if (empty($o_part->charset) || strtolower($o_part->charset) == 'us-ascii')
- $o_part->charset = $this->default_charset;
-
+ // convert charset (if text or message part) and part's charset is specified
+ if ($body && $o_part->charset
+ && preg_match('/^(text|message)$/', $o_part->ctype_primary)
+ ) {
$body = rcube_charset_convert($body, $o_part->charset);
}
@@ -2553,6 +2607,9 @@ function move_message($uids, $to_mbox, $from_mbox='')
$to_mbox = $this->mod_mailbox($to_mbox);
$from_mbox = strlen($from_mbox) ? $this->mod_mailbox($from_mbox) : $this->mailbox;
+ if ($to_mbox === $from_mbox)
+ return false;
+
list($uids, $all_mode) = $this->_parse_uids($uids, $from_mbox);
// exit if no message uids are specified
@@ -2771,7 +2828,23 @@ private function _expunge($mailbox, $clear_cache=true, $uids=NULL)
else
$a_uids = NULL;
- $result = $this->conn->expunge($mailbox, $a_uids);
+ // force mailbox selection and check if mailbox is writeable
+ // to prevent a situation when CLOSE is executed on closed
+ // or EXPUNGE on read-only mailbox
+ $result = $this->conn->select($mailbox);
+ if (!$result) {
+ return false;
+ }
+ if (!$this->conn->data['READ-WRITE']) {
+ $this->conn->setError(rcube_imap_generic::ERROR_READONLY, "Mailbox is read-only");
+ return false;
+ }
+
+ // CLOSE(+SELECT) should be faster than EXPUNGE
+ if (empty($a_uids) || $a_uids == '1:*')
+ $result = $this->conn->close();
+ else
+ $result = $this->conn->expunge($mailbox, $a_uids);
if ($result && $clear_cache) {
$this->clear_message_cache($mailbox.'.msg');
@@ -3009,6 +3082,26 @@ function get_quota()
/**
+ * Get mailbox size (size of all messages in a mailbox)
+ *
+ * @param string $name Mailbox name
+ * @return int Mailbox size in bytes, False on error
+ */
+ function get_mailbox_size($name)
+ {
+ $name = $this->mod_mailbox($name);
+
+ // @TODO: could we try to use QUOTA here?
+ $result = $this->conn->fetchHeaderIndex($name, '1:*', 'SIZE', false);
+
+ if (is_array($result))
+ $result = array_sum($result);
+
+ return $result;
+ }
+
+
+ /**
* Subscribe to a specific mailbox(es)
*
* @param array $a_mboxes Mailbox name(s)
@@ -3043,130 +3136,120 @@ function unsubscribe($a_mboxes)
/**
* Create a new mailbox on the server and register it in local cache
*
- * @param string $name New mailbox name (as utf-7 string)
+ * @param string $name New mailbox name
* @param boolean $subscribe True if the new mailbox should be subscribed
- * @param string Name of the created mailbox, false on error
+ * @param boolean True on success
*/
function create_mailbox($name, $subscribe=false)
{
- $result = false;
-
- // reduce mailbox name to 100 chars
- $name = substr($name, 0, 100);
+ $result = false;
$abs_name = $this->mod_mailbox($name);
- $result = $this->conn->createFolder($abs_name);
+ $result = $this->conn->createFolder($abs_name);
// try to subscribe it
if ($result && $subscribe)
$this->subscribe($name);
- return $result ? $name : false;
+ return $result;
}
/**
* Set a new name to an existing mailbox
*
- * @param string $mbox_name Mailbox to rename (as utf-7 string)
- * @param string $new_name New mailbox name (as utf-7 string)
- * @return string Name of the renames mailbox, False on error
+ * @param string $mbox_name Mailbox to rename
+ * @param string $new_name New mailbox name
+ *
+ * @return boolean True on success
*/
function rename_mailbox($mbox_name, $new_name)
{
$result = false;
- // encode mailbox name and reduce it to 100 chars
- $name = substr($new_name, 0, 100);
-
// make absolute path
- $mailbox = $this->mod_mailbox($mbox_name);
- $abs_name = $this->mod_mailbox($name);
-
- // check if mailbox is subscribed
- $a_subscribed = $this->_list_mailboxes();
- $subscribed = in_array($mailbox, $a_subscribed);
+ $mailbox = $this->mod_mailbox($mbox_name);
+ $abs_name = $this->mod_mailbox($new_name);
+ $delm = $this->get_hierarchy_delimiter();
- // unsubscribe folder
- if ($subscribed)
- $this->conn->unsubscribe($mailbox);
+ // get list of subscribed folders
+ if ((strpos($mailbox, '%') === false) && (strpos($mailbox, '*') === false)) {
+ $a_subscribed = $this->_list_mailboxes('', $mbox_name . $delm . '*');
+ $subscribed = $this->mailbox_exists($mbox_name, true);
+ }
+ else {
+ $a_subscribed = $this->_list_mailboxes();
+ $subscribed = in_array($mailbox, $a_subscribed);
+ }
if (strlen($abs_name))
$result = $this->conn->renameFolder($mailbox, $abs_name);
if ($result) {
- $delm = $this->get_hierarchy_delimiter();
+ // unsubscribe the old folder, subscribe the new one
+ if ($subscribed) {
+ $this->conn->unsubscribe($mailbox);
+ $this->conn->subscribe($abs_name);
+ }
// check if mailbox children are subscribed
- foreach ($a_subscribed as $c_subscribed)
+ foreach ($a_subscribed as $c_subscribed) {
if (preg_match('/^'.preg_quote($mailbox.$delm, '/').'/', $c_subscribed)) {
$this->conn->unsubscribe($c_subscribed);
$this->conn->subscribe(preg_replace('/^'.preg_quote($mailbox, '/').'/',
$abs_name, $c_subscribed));
}
+ }
// clear cache
$this->clear_message_cache($mailbox.'.msg');
$this->clear_cache('mailboxes');
}
- // try to subscribe it
- if ($result && $subscribed)
- $this->conn->subscribe($abs_name);
-
- return $result ? $name : false;
+ return $result;
}
/**
- * Remove mailboxes from server
+ * Remove mailbox from server
+ *
+ * @param string $mbox_name Mailbox name
*
- * @param string|array $mbox_name sMailbox name(s) string/array
* @return boolean True on success
*/
function delete_mailbox($mbox_name)
{
- $deleted = false;
+ $result = false;
+ $mailbox = $this->mod_mailbox($mbox_name);
+ $delm = $this->get_hierarchy_delimiter();
- if (is_array($mbox_name))
- $a_mboxes = $mbox_name;
- else if (is_string($mbox_name) && strlen($mbox_name))
- $a_mboxes = explode(',', $mbox_name);
+ // get list of folders
+ if ((strpos($mailbox, '%') === false) && (strpos($mailbox, '*') === false))
+ $sub_mboxes = $this->list_unsubscribed('', $mailbox . $delm . '*');
+ else
+ $sub_mboxes = $this->list_unsubscribed();
- if (is_array($a_mboxes)) {
- $delimiter = $this->get_hierarchy_delimiter();
-
- foreach ($a_mboxes as $mbox_name) {
- $mailbox = $this->mod_mailbox($mbox_name);
- $sub_mboxes = $this->conn->listMailboxes('', $mbox_name . $delimiter . '*');
+ // send delete command to server
+ $result = $this->conn->deleteFolder($mailbox);
- // unsubscribe mailbox before deleting
- $this->conn->unsubscribe($mailbox);
+ if ($result) {
+ // unsubscribe mailbox
+ $this->conn->unsubscribe($mailbox);
- // send delete command to server
- $result = $this->conn->deleteFolder($mailbox);
- if ($result) {
- $deleted = true;
- $this->clear_message_cache($mailbox.'.msg');
- }
-
- foreach ($sub_mboxes as $c_mbox) {
- if ($c_mbox != 'INBOX') {
- $this->conn->unsubscribe($c_mbox);
- $result = $this->conn->deleteFolder($c_mbox);
- if ($result) {
- $deleted = true;
- $this->clear_message_cache($c_mbox.'.msg');
- }
+ foreach ($sub_mboxes as $c_mbox) {
+ if (preg_match('/^'.preg_quote($mailbox.$delm, '/').'/', $c_mbox)) {
+ $this->conn->unsubscribe($c_mbox);
+ if ($this->conn->deleteFolder($c_mbox)) {
+ $this->clear_message_cache($c_mbox.'.msg');
}
}
}
- }
- // clear mailboxlist cache
- if ($deleted)
+ // clear mailbox-related cache
+ $this->clear_message_cache($mailbox.'.msg');
$this->clear_cache('mailboxes');
+ }
- return $deleted;
+ return $result;
}
@@ -3208,7 +3291,7 @@ function mailbox_exists($mbox_name, $subscription=false)
}
else {
$a_folders = $this->conn->listMailboxes('', $mbox);
- }
+ }
if (is_array($a_folders) && in_array($mbox, $a_folders)) {
$this->icache[$key][] = $mbox;
View
2,823 program/include/rcube_imap_generic.php
1,490 additions, 1,333 deletions not shown
View
6 program/include/rcube_message.php
@@ -426,7 +426,7 @@ private function parse_structure($structure, $recursive = false)
$mail_part->type = 'content';
$this->parts[] = $mail_part;
}
-
+
// list as attachment as well
if (!empty($mail_part->filename))
$this->attachments[] = $mail_part;
@@ -473,6 +473,10 @@ private function parse_structure($structure, $recursive = false)
// attachment encapsulated within message/rfc822 part needs further decoding (#1486743)
else if ($part_orig_mimetype == 'message/rfc822') {
$this->parse_structure($mail_part, true);
+
+ // list as attachment as well (mostly .eml)
+ if (!empty($mail_part->filename))
+ $this->attachments[] = $mail_part;
}
// is a regular attachment (content-type name regexp according to RFC4288.4.2)
else if (preg_match('/^[a-z0-9!#$&.+^_-]+\/[a-z0-9!#$&.+^_-]+$/i', $part_mimetype)) {
View
20 program/include/rcube_template.php
@@ -1045,7 +1045,7 @@ public function current_username($attrib)
private function login_form($attrib)
{
$default_host = $this->config['default_host'];
- $attrib['autocomplete'] = $this->config['login_autocomplete'] ? null : 'off';
+ $autocomplete = (int) $this->config['login_autocomplete'];
$_SESSION['temp'] = true;
@@ -1054,11 +1054,18 @@ private function login_form($attrib)
if (empty($url) && !preg_match('/_(task|action)=logout/', $_SERVER['QUERY_STRING']))
$url = $_SERVER['QUERY_STRING'];
- $input_user = new html_inputfield(array('name' => '_user', 'id' => 'rcmloginuser') + $attrib);
- $input_pass = new html_passwordfield(array('name' => '_pass', 'id' => 'rcmloginpwd') + $attrib);
+ // set atocomplete attribute
+ $user_attrib = $autocomplete > 0 ? array() : array('autocomplete' => 'off');
+ $host_attrib = $autocomplete > 0 ? array() : array('autocomplete' => 'off');
+ $pass_attrib = $autocomplete > 1 ? array() : array('autocomplete' => 'off');
+
$input_action = new html_hiddenfield(array('name' => '_action', 'value' => 'login'));
$input_tzone = new html_hiddenfield(array('name' => '_timezone', 'id' => 'rcmlogintz', 'value' => '_default_'));
$input_url = new html_hiddenfield(array('name' => '_url', 'id' => 'rcmloginurl', 'value' => $url));
+ $input_user = new html_inputfield(array('name' => '_user', 'id' => 'rcmloginuser')
+ + $attrib + $user_attrib);
+ $input_pass = new html_passwordfield(array('name' => '_pass', 'id' => 'rcmloginpwd')
+ + $attrib + $pass_attrib);
$input_host = null;
if (is_array($default_host) && count($default_host) > 1) {
@@ -1080,7 +1087,8 @@ private function login_form($attrib)
'name' => '_host', 'id' => 'rcmloginhost', 'value' => $host) + $attrib);
}