Skip to content
This repository
Browse code

Merge branch 'master' of github.com:roundcube/roundcubemail

  • Loading branch information...
commit fe847dfe092408c6f3c79bcab4c661ccf57f4646 2 parents 09efab3 + 7c15137
Katie Poskaitis katiepru authored

Showing 140 changed files with 2,080 additions and 28,100 deletions. Show diff stats Hide diff stats

  1. +1 1  .htaccess
  2. +40 24 CHANGELOG
  3. +3 4 INSTALL
  4. +1 1  bin/update.sh
  5. +3 3 config/main.inc.php.dist
  6. +20 19 index.php
  7. +12 13 installer/check.php
  8. +2 7 installer/config.php
  9. +14 82 installer/rcube_install.php
  10. +3 3 installer/test.php
  11. +0 2  installer/utils.php
  12. +1 1  plugins/acl/acl.php
  13. +1 1  plugins/enigma/enigma.php
  14. +2 0  plugins/managesieve/Changelog
  15. +3 1 plugins/managesieve/lib/Net/Sieve.php
  16. +10 13 plugins/new_user_identity/new_user_identity.php
  17. +3 3 plugins/new_user_identity/package.xml
  18. +1 1  plugins/password/drivers/sql.php
  19. +0 4 plugins/password/drivers/virtualmin.php
  20. +1 1  plugins/squirrelmail_usercopy/config.inc.php.dist
  21. +3 3 plugins/squirrelmail_usercopy/squirrelmail_usercopy.php
  22. +1 1  plugins/subscriptions_option/subscriptions_option.php
  23. +1 1  plugins/vcard_attachments/vcard_attachments.php
  24. +26 23 program/include/clisetup.php
  25. +16 12 program/include/html.php
  26. +4 6 program/include/rcube.php
  27. +10 7 program/include/rcube_cache.php
  28. +7 5 program/include/rcube_config.php
  29. +6 5 program/include/rcube_contacts.php
  30. +1,002 0 program/include/rcube_db.php
  31. +155 0 program/include/rcube_db_mssql.php
  32. +154 0 program/include/rcube_db_mysql.php
  33. +135 0 program/include/rcube_db_pgsql.php
  34. +178 0 program/include/rcube_db_sqlite.php
  35. +156 0 program/include/rcube_db_sqlsrv.php
  36. +18 15 program/include/rcube_imap.php
  37. +2 2 program/include/rcube_imap_cache.php
  38. +2 2 program/include/rcube_imap_generic.php
  39. +11 6 program/include/rcube_ldap.php
  40. +0 935 program/include/rcube_mdb2.php
  41. +1 1  program/include/rcube_message.php
  42. +4 1 program/include/rcube_output_html.php
  43. +2 2 program/include/rcube_plugin_api.php
  44. +8 6 program/include/rcube_session.php
  45. +24 1 program/include/rcube_shared.inc
  46. +1 1  program/include/rcube_smtp.php
  47. +6 6 program/include/rcube_spellchecker.php
  48. +4 1 program/include/rcube_storage.php
  49. +4 5 program/include/rcube_user.php
  50. +5 5 program/include/rcube_utils.php
  51. +1 1  program/include/rcube_vcard.php
  52. +11 33 program/js/app.js
  53. +1 1  program/js/list.js
  54. +0 4,270 program/lib/MDB2.php
  55. +0 183 program/lib/MDB2/Date.php
  56. +0 1,838 program/lib/MDB2/Driver/Datatype/Common.php
  57. +0 496 program/lib/MDB2/Driver/Datatype/mssql.php
  58. +0 562 program/lib/MDB2/Driver/Datatype/mysql.php
  59. +0 599 program/lib/MDB2/Driver/Datatype/mysqli.php
  60. +0 579 program/lib/MDB2/Driver/Datatype/pgsql.php
  61. +0 418 program/lib/MDB2/Driver/Datatype/sqlite.php
  62. +0 451 program/lib/MDB2/Driver/Datatype/sqlsrv.php
  63. +0 293 program/lib/MDB2/Driver/Function/Common.php
  64. +0 193 program/lib/MDB2/Driver/Function/mssql.php
  65. +0 136 program/lib/MDB2/Driver/Function/mysql.php
  66. +0 144 program/lib/MDB2/Driver/Function/mysqli.php
  67. +0 115 program/lib/MDB2/Driver/Function/pgsql.php
  68. +0 162 program/lib/MDB2/Driver/Function/sqlite.php
  69. +0 189 program/lib/MDB2/Driver/Function/sqlsrv.php
  70. +0 1,014 program/lib/MDB2/Driver/Manager/Common.php
  71. +0 1,129 program/lib/MDB2/Driver/Manager/mssql.php
  72. +0 1,438 program/lib/MDB2/Driver/Manager/mysql.php
  73. +0 1,438 program/lib/MDB2/Driver/Manager/mysqli.php
  74. +0 948 program/lib/MDB2/Driver/Manager/pgsql.php
  75. +0 1,362 program/lib/MDB2/Driver/Manager/sqlite.php
  76. +0 1,383 program/lib/MDB2/Driver/Manager/sqlsrv.php
  77. +0 61 program/lib/MDB2/Driver/Native/Common.php
  78. +0 60 program/lib/MDB2/Driver/Native/mssql.php
  79. +0 60 program/lib/MDB2/Driver/Native/mysql.php
  80. +0 60 program/lib/MDB2/Driver/Native/mysqli.php
  81. +0 88 program/lib/MDB2/Driver/Native/pgsql.php
  82. +0 60 program/lib/MDB2/Driver/Native/sqlite.php
  83. +0 57 program/lib/MDB2/Driver/Native/sqlsrv.php
  84. +0 517 program/lib/MDB2/Driver/Reverse/Common.php
  85. +0 653 program/lib/MDB2/Driver/Reverse/mssql.php
  86. +0 546 program/lib/MDB2/Driver/Reverse/mysql.php
  87. +0 610 program/lib/MDB2/Driver/Reverse/mysqli.php
  88. +0 574 program/lib/MDB2/Driver/Reverse/pgsql.php
  89. +0 609 program/lib/MDB2/Driver/Reverse/sqlite.php
  90. +0 653 program/lib/MDB2/Driver/Reverse/sqlsrv.php
  91. +0 1,172 program/lib/MDB2/Driver/mssql.php
  92. +0 1,709 program/lib/MDB2/Driver/mysql.php
Sorry, we could not display the entire diff because it was too big.
2  .htaccess
@@ -28,7 +28,7 @@ php_value mbstring.func_overload 0
28 28
29 29 <IfModule mod_rewrite.c>
30 30 RewriteEngine On
31   -RewriteRule ^favicon\.ico$ skins/default/images/favicon.ico
  31 +RewriteRule ^favicon\.ico$ skins/larry/images/favicon.ico
32 32 # security rules
33 33 RewriteRule .git - [F]
34 34 RewriteRule ^/?(README(.md)?|INSTALL|LICENSE|SQL|bin|CHANGELOG)$ - [F]
64 CHANGELOG
... ... @@ -1,10 +1,48 @@
1 1 CHANGELOG Roundcube Webmail
2 2 ===========================
3 3
  4 +- Rewritten test scripts for PHPUnit
  5 +- Fix lower-casing email address on replies (#1488598)
  6 +- Fix line separator in exported messages (#1488603)
  7 +- Fix XSS issue where plain signatures wasn't secured in HTML mode (#1488613)
  8 +- Fix XSS issue where href="javascript:" wasn't secured (#1488613)
  9 +- Fix impossible to create message with empty plain text part (#1488610)
  10 +- Fix stripped apostrophes when replying in plain text to HTML message (#1488606)
  11 +- Fix inactive Save search option after advanced search (#1488607)
  12 +- Fix Remove from group option is active for contact search result (#1488608)
  13 +- Disable autocapitalization in login form on iPad/iPhone (#1488609)
  14 +- Fix focus on the list when list row is clicked (#1488600)
  15 +- Added separate From and To columns apart from smart From/To column (#1486891)
  16 +- Fix fallback to Larry skin when configured skin isn't available (#1488591)
  17 +- Fix (workaround) delete operations with some versions of memcache (#1488592)
  18 +- Fix (disable) request validation for spell and spell_html actions
  19 +- Add new DB abstraction layer based on PHP PDO, supporting SQLite3 (#1488332)
  20 +- Removed PEAR::MDB2 package
4 21 - Removed users.alias column, added option ('user_aliases')
5 22 to use email address from identities as username (#1488581)
6 23 - Removed redundant cache.cache_id column (#1488528)
7 24 - Fix order of attachments in sent mail (#1488423)
  25 +- Fix Shift + delete button does not permanently delete messages (#1488243)
  26 +- Add Content-Length for attachments where possible (#1485478)
  27 +- Fix attachment sizes in message print page and attachment preview page (#1488515)
  28 +- Add mail attachments using drag & drop on HTML5 enabled browsers
  29 +- Add workaround for invalid BODYSTRUCTURE response - parse message with Mail_mimeDecode package (#1485585)
  30 +- Display Tiff as Jpeg in browsers without Tiff support (#1488452)
  31 +- Don't display Pdf/Tiff/Flash attachments inline without browser support (#1488452, #1487929)
  32 +- Add is_escaped attribute for html_select and html_textarea (#1488485)
  33 +- Fix issue where draft auto-save wasn't executed after some inactivity time
  34 +- Add vCard import from multiple files at once (#1488015)
  35 +- Roundcube Framework:
  36 + Add possibility to replace IMAP driver with custom class
  37 + Add IMAP auto-connection feature, improving performance with caching enabled
  38 + Replace imap_init hook with storage_init (with additional 'driver' argument)
  39 + Improved performance by caching IMAP server's capabilities in session
  40 + Unified global functions naming (rcube_ prefix)
  41 + Move global functions from main.inc and rcube_shared.inc into classes
  42 + Better classes separation
  43 +
  44 +RELEASE 0.8.0
  45 +-------------
8 46 - Don't show product version on login screen (can be enabled by config)
9 47 - Renamed old default skin to 'classic'. Larry is the new default skin.
10 48 - Support connections to memcached socket file (#1488577)
@@ -26,23 +64,16 @@ CHANGELOG Roundcube Webmail
26 64 - Fix removing contact photo using LDAP addressbook (#1488420)
27 65 - Fix storing X-ANNIVERSARY date in vCard format (#1488527)
28 66 - Update to Mail_Mime-1.8.5 (#1488521)
29   -- Fix Shift + delete button does not permanently delete messages (#1488243)
30   -- Add Content-Length for attachments where possible (#1485478)
31   -- Fix attachment sizes in message print page and attachment preview page (#1488515)
32 67 - Fix XSS vulnerability in message subject handling using Larry skin (#1488519)
33 68 - Fix handling of links with various URI schemes e.g. "skype:" (#1488106)
34 69 - Fix handling of links inside PRE elements on html to text conversion
35 70 - Fix indexing of links on html to text conversion
36   -- Add mail attachments using drag & drop on HTML5 enabled browsers
37   -- Add workaround for invalid BODYSTRUCTURE response - parse message with Mail_mimeDecode package (#1485585)
38 71 - Decode header value in rcube_mime::get() by default (#1488511)
39 72 - Fix errors with enabled PHP magic_quotes_sybase option (#1488506)
40 73 - Fix SQL query for contacts listing on MS SQL Server (#1488505)
41   -- Update to TinyMCE 3.5.2
42 74 - Fix window.resize handler on IE8 and Opera (#1488453)
43 75 - Don't let error message popups cover the login form (#1488500)
44   -- Display Tiff as Jpeg in browsers without Tiff support (#1488452)
45   -- Don't display Pdf/Tiff/Flash attachments inline without browser support (#1488452, #1487929)
  76 +- Update to TinyMCE 3.5.2
46 77 - Don't show errors when moving contacts into groups they are already in (#1488493)
47 78 - Make folders with unread messages in subfolders bold again (#1486793)
48 79 - Abbreviate long attachment file names with ellipsis (#1488499)
@@ -50,19 +81,8 @@ CHANGELOG Roundcube Webmail
50 81 - Add listcontrols template container in Larry skin (#1488498)
51 82 - Fix host autoselection when default_host is an array (#1488495)
52 83 - Move messages forwarding mode setting into Preferences
53   -- Add is_escaped attribute for html_select and html_textarea (#1488485)
54 84 - Fix HTML entities handling in HTML editor (#1488483)
55 85 - Fix listing shared folders on Courier IMAP (#1488466)
56   -- Fix issue where draft auto-save wasn't executed after some inactivity time
57   -- Add vCard import from multiple files at once (#1488015)
58   -- Roundcube Framework:
59   - Add possibility to replace IMAP driver with custom class
60   - Add IMAP auto-connection feature, improving performance with caching enabled
61   - Replace imap_init hook with storage_init (with additional 'driver' argument)
62   - Improved performance by caching IMAP server's capabilities in session
63   - Unified global functions naming (rcube_ prefix)
64   - Move global functions from main.inc and rcube_shared.inc into classes
65   - Better classes separation
66 86
67 87 RELEASE 0.8-rc
68 88 --------------
@@ -181,7 +201,7 @@ RELEASE 0.7
181 201 - Fix handling contact photo url with https:// prefix (#1488202)
182 202 - Fix possible infinite redirect on attachment preview (#1488199)
183 203 - Improved clickjacking protection for browsers which don't support X-Frame-Options headers
184   -- Fixed bug where similiar folder names were highlighted wrong (#1487860)
  204 +- Fixed bug where similar folder names were highlighted wrong (#1487860)
185 205 - Fixed bug in handling link with '!' character in it (#1488195)
186 206 - Fixed bug where session ID's length was limited to 40 characters (#1488196)
187 207 - TinyMCE security issue: removed moxieplayer (embedding flv and mp4 is not supported anymore)
@@ -1384,7 +1404,3 @@ RELEASE 0.1-RC1
1384 1404 Now based on the message structure delivered by the IMAP server.
1385 1405 - Fixed some XSS and SQL injection issues
1386 1406 - Fixed charset problems with folder renaming
1387   -
1388   -
1389   -
1390   -
7 INSTALL
@@ -12,14 +12,13 @@ REQUIREMENTS
12 12 * The Apache, Lighttpd, Cherokee or Hiawatha web server
13 13 * .htaccess support allowing overrides for DirectoryIndex
14 14 * PHP Version 5.2.1 or greater including
15   - - PCRE, DOM, JSON, XML, Session, Sockets (required)
  15 + - PDO, PCRE, DOM, JSON, XML, Session, Sockets (required)
16 16 - libiconv (recommended)
17 17 - mbstring, fileinfo, mcrypt (optional)
18 18 * PEAR packages distributed with Roundcube or external:
19   - - MDB2 2.5.0 or newer
20 19 - Mail_Mime 1.8.1 or newer
21 20 - Mail_mimeDecode 1.5.5 or newer
22   - - Net_SMTP 1.4.2 or newer
  21 + - Net_SMTP (latest from https://github.com/pear/Net_SMTP/)
23 22 - Net_IDNA2 0.1.1 or newer
24 23 - Auth_SASL 1.0.6 or newer
25 24 * php.ini options (see .htaccess file):
@@ -34,7 +33,7 @@ REQUIREMENTS
34 33 - magic_quotes_sybase disabled
35 34 * PHP compiled with OpenSSL to connect to IMAPS and to use the spell checker
36 35 * A MySQL (4.0.8 or newer), PostgreSQL, MSSQL database engine
37   - or the SQLite extension for PHP
  36 + or SQLite support in PHP
38 37 * One of the above databases with permission to create tables
39 38 * An SMTP server (recommended) or PHP configured for mail delivery
40 39
2  bin/update.sh
@@ -143,7 +143,7 @@ if ($RCI->configured) {
143 143
144 144 // check database schema
145 145 if ($RCI->config['db_dsnw']) {
146   - $DB = new rcube_mdb2($RCI->config['db_dsnw'], '', false);
  146 + $DB = rcube_db::factory($RCI->config['db_dsnw'], '', false);
147 147 $DB->db_connect('w');
148 148 if ($db_error_msg = $DB->is_error()) {
149 149 echo "Error connecting to database: $db_error_msg\n";
6 config/main.inc.php.dist
@@ -387,15 +387,15 @@ $rcmail_config['plugins'] = array();
387 387 // ----------------------------------
388 388
389 389 // default messages sort column. Use empty value for default server's sorting,
390   -// or 'arrival', 'date', 'subject', 'from', 'to', 'size', 'cc'
  390 +// or 'arrival', 'date', 'subject', 'from', 'to', 'fromto', 'size', 'cc'
391 391 $rcmail_config['message_sort_col'] = '';
392 392
393 393 // default messages sort order
394 394 $rcmail_config['message_sort_order'] = 'DESC';
395 395
396 396 // These cols are shown in the message list. Available cols are:
397   -// subject, from, to, cc, replyto, date, size, status, flag, attachment, 'priority'
398   -$rcmail_config['list_cols'] = array('subject', 'status', 'from', 'date', 'size', 'flag', 'attachment');
  397 +// subject, from, to, fromto, cc, replyto, date, size, status, flag, attachment, 'priority'
  398 +$rcmail_config['list_cols'] = array('subject', 'status', 'fromto', 'date', 'size', 'flag', 'attachment');
399 399
400 400 // the default locale setting (leave empty for auto-detection)
401 401 // RFC1766 formatted language name like en_US, de_DE, de_CH, fr_FR, pt_BR
39 index.php
@@ -219,27 +219,28 @@
219 219 // CSRF prevention
220 220 else {
221 221 // don't check for valid request tokens in these actions
222   - $request_check_whitelist = array('login'=>1, 'spell'=>1);
223   -
224   - // check client X-header to verify request origin
225   - if ($OUTPUT->ajax_call) {
226   - if (rcube_utils::request_header('X-Roundcube-Request') != $RCMAIL->get_request_token() && !$RCMAIL->config->get('devel_mode')) {
227   - header('HTTP/1.1 403 Forbidden');
228   - die("Invalid Request");
  222 + $request_check_whitelist = array('login'=>1, 'spell'=>1, 'spell_html'=>1);
  223 +
  224 + if (!$request_check_whitelist[$RCMAIL->action]) {
  225 + // check client X-header to verify request origin
  226 + if ($OUTPUT->ajax_call) {
  227 + if (rcube_utils::request_header('X-Roundcube-Request') != $RCMAIL->get_request_token()) {
  228 + header('HTTP/1.1 403 Forbidden');
  229 + die("Invalid Request");
  230 + }
  231 + }
  232 + // check request token in POST form submissions
  233 + else if (!empty($_POST) && !$RCMAIL->check_request()) {
  234 + $OUTPUT->show_message('invalidrequest', 'error');
  235 + $OUTPUT->send($RCMAIL->task);
229 236 }
230   - }
231   - // check request token in POST form submissions
232   - else if (!empty($_POST) && !$request_check_whitelist[$RCMAIL->action] && !$RCMAIL->check_request()) {
233   - $OUTPUT->show_message('invalidrequest', 'error');
234   - $OUTPUT->send($RCMAIL->task);
235   - }
236 237
237   - // check referer if configured
238   - if (!$request_check_whitelist[$RCMAIL->action] && $RCMAIL->config->get('referer_check') && !rcmail::check_referer()) {
239   - raise_error(array(
240   - 'code' => 403,
241   - 'type' => 'php',
242   - 'message' => "Referer check failed"), true, true);
  238 + // check referer if configured
  239 + if ($RCMAIL->config->get('referer_check') && !rcmail::check_referer()) {
  240 + raise_error(array(
  241 + 'code' => 403, 'type' => 'php',
  242 + 'message' => "Referer check failed"), true, true);
  243 + }
243 244 }
244 245 }
245 246
25 installer/check.php
@@ -6,7 +6,8 @@
6 6 'DOM' => 'dom',
7 7 'Session' => 'session',
8 8 'XML' => 'xml',
9   - 'JSON' => 'json'
  9 + 'JSON' => 'json',
  10 + 'PDO' => 'PDO',
10 11 );
11 12
12 13 $optional_php_exts = array(
@@ -21,19 +22,11 @@
21 22
22 23 $required_libs = array(
23 24 'PEAR' => 'PEAR.php',
24   - 'MDB2' => 'MDB2.php',
25 25 'Net_SMTP' => 'Net/SMTP.php',
26 26 'Net_IDNA2' => 'Net/IDNA2.php',
27 27 'Mail_mime' => 'Mail/mime.php',
28 28 );
29 29
30   -$supported_dbs = array(
31   - 'MySQL' => 'mysql',
32   - 'MySQLi' => 'mysqli',
33   - 'PostgreSQL' => 'pgsql',
34   - 'SQLite (v2)' => 'sqlite',
35   -);
36   -
37 30 $ini_checks = array(
38 31 'file_uploads' => 1,
39 32 'session.auto_start' => 0,
@@ -63,8 +56,14 @@
63 56 'DOM' => 'http://www.php.net/manual/en/book.dom.php',
64 57 'Intl' => 'http://www.php.net/manual/en/book.intl.php',
65 58 'Exif' => 'http://www.php.net/manual/en/book.exif.php',
  59 + 'PDO' => 'http://www.php.net/manual/en/book.pdo.php',
  60 + 'pdo_mysql' => 'http://www.php.net/manual/en/book.pdo-mysql.php',
  61 + 'pdo_pgsql' => 'http://www.php.net/manual/en/book.pdo-pgsql.php',
  62 + 'pdo_sqlite' => 'http://www.php.net/manual/en/book.pdo-sqlite.php',
  63 + 'pdo_sqlite2' => 'http://www.php.net/manual/en/book.pdo-sqlite.php',
  64 + 'pdo_sqlsrv' => 'http://www.php.net/manual/en/book.pdo-sqlsrv.php',
  65 + 'pdo_dblib' => 'http://www.php.net/manual/en/book.pdo-dblib.php',
66 66 'PEAR' => 'http://pear.php.net',
67   - 'MDB2' => 'http://pear.php.net/package/MDB2',
68 67 'Net_SMTP' => 'http://pear.php.net/package/Net_SMTP',
69 68 'Mail_mime' => 'http://pear.php.net/package/Mail_mime',
70 69 'Net_IDNA2' => 'http://pear.php.net/package/Net_IDNA2',
@@ -129,14 +128,14 @@
129 128 <?php
130 129
131 130 $prefix = (PHP_SHLIB_SUFFIX === 'dll') ? 'php_' : '';
132   -foreach ($supported_dbs as $database => $ext) {
  131 +foreach ($RCI->supported_dbs as $database => $ext) {
133 132 if (extension_loaded($ext)) {
134 133 $RCI->pass($database);
135 134 }
136 135 else {
137 136 $_ext = $ext_dir . '/' . $prefix . $ext . '.' . PHP_SHLIB_SUFFIX;
138   - $msg = @is_readable($_ext) ? 'Could be loaded. Please add in php.ini' : 'Not installed';
139   - $RCI->na($database, $msg, $source_urls[$database]);
  137 + $msg = @is_readable($_ext) ? 'Could be loaded. Please add in php.ini' : '';
  138 + $RCI->na($database, $msg, $source_urls[$ext]);
140 139 }
141 140 echo '<br />';
142 141 }
9 installer/config.php
@@ -267,13 +267,8 @@
267 267 <p>Database settings for read/write operations:</p>
268 268 <?php
269 269
270   -require_once 'MDB2.php';
271   -
272   -$supported_dbs = array('MySQL' => 'mysql', 'MySQLi' => 'mysqli',
273   - 'PgSQL' => 'pgsql', 'SQLite' => 'sqlite');
274   -
275 270 $select_dbtype = new html_select(array('name' => '_dbtype', 'id' => "cfgdbtype"));
276   -foreach ($supported_dbs AS $database => $ext) {
  271 +foreach ($RCI->supported_dbs as $database => $ext) {
277 272 if (extension_loaded($ext)) {
278 273 $select_dbtype->add($database, $ext);
279 274 }
@@ -284,7 +279,7 @@
284 279 $input_dbuser = new html_inputfield(array('name' => '_dbuser', 'size' => 20, 'id' => "cfgdbuser"));
285 280 $input_dbpass = new html_passwordfield(array('name' => '_dbpass', 'size' => 20, 'id' => "cfgdbpass"));
286 281
287   -$dsnw = MDB2::parseDSN($RCI->getprop('db_dsnw'));
  282 +$dsnw = rcube_db::parse_dsn($RCI->getprop('db_dsnw'));
288 283
289 284 echo $select_dbtype->show($RCI->is_post ? $_POST['_dbtype'] : $dsnw['phptype']);
290 285 echo '<label for="cfgdbtype">Database type</label><br />';
96 installer/rcube_install.php
@@ -50,6 +50,17 @@ class rcube_install
50 50 'des_key', 'session_lifetime', 'support_url',
51 51 );
52 52
  53 + // list of supported database drivers
  54 + var $supported_dbs = array(
  55 + 'MySQL' => 'pdo_mysql',
  56 + 'PostgreSQL' => 'pdo_pgsql',
  57 + 'SQLite' => 'pdo_sqlite',
  58 + 'SQLite (v2)' => 'pdo_sqlite2',
  59 + 'SQL Server (SQLSRV)' => 'pdo_sqlsrv',
  60 + 'SQL Server (DBLIB)' => 'pdo_dblib',
  61 + );
  62 +
  63 +
53 64 /**
54 65 * Constructor
55 66 */
@@ -371,7 +382,7 @@ function db_schema_check($DB, $update = false)
371 382 $errors[] = "Missing columns in table '$table': " . join(',', $diff);
372 383 }
373 384 }
374   -
  385 +
375 386 return !empty($errors) ? $errors : false;
376 387 }
377 388
@@ -394,87 +405,8 @@ private function db_read_schema($schemafile)
394 405 }
395 406 }
396 407 }
397   -
398   - return $schema;
399   - }
400   -
401   -
402   - /**
403   - * Compare the local database schema with the reference schema
404   - * required for this version of Roundcube
405   - *
406   - * @param boolean True if the schema schould be updated
407   - * @return boolean True if the schema is up-to-date, false if not or an error occured
408   - */
409   - function mdb2_schema_check($update = false)
410   - {
411   - if (!$this->configured)
412   - return false;
413   -
414   - $options = array(
415   - 'use_transactions' => false,
416   - 'log_line_break' => "\n",
417   - 'idxname_format' => '%s',
418   - 'debug' => false,
419   - 'quote_identifier' => true,
420   - 'force_defaults' => false,
421   - 'portability' => true
422   - );
423   -
424   - $dsnw = $this->config['db_dsnw'];
425   - $schema = MDB2_Schema::factory($dsnw, $options);
426   - $schema->db->supported['transactions'] = false;
427   -
428   - if (PEAR::isError($schema)) {
429   - $this->raise_error(array('code' => $schema->getCode(), 'message' => $schema->getMessage() . ' ' . $schema->getUserInfo()));
430   - return false;
431   - }
432   - else {
433   - $definition = $schema->getDefinitionFromDatabase();
434   - $definition['charset'] = 'utf8';
435   -
436   - if (PEAR::isError($definition)) {
437   - $this->raise_error(array('code' => $definition->getCode(), 'message' => $definition->getMessage() . ' ' . $definition->getUserInfo()));
438   - return false;
439   - }
440   -
441   - // load reference schema
442   - $dsn_arr = MDB2::parseDSN($this->config['db_dsnw']);
443   -
444   - $ref_schema = INSTALL_PATH . 'SQL/' . $dsn_arr['phptype'] . '.schema.xml';
445   -
446   - if (is_readable($ref_schema)) {
447   - $reference = $schema->parseDatabaseDefinition($ref_schema, false, array(), $schema->options['fail_on_invalid_names']);
448   -
449   - if (PEAR::isError($reference)) {
450   - $this->raise_error(array('code' => $reference->getCode(), 'message' => $reference->getMessage() . ' ' . $reference->getUserInfo()));
451   - }
452   - else {
453   - $diff = $schema->compareDefinitions($reference, $definition);
454   -
455   - if (empty($diff)) {
456   - return true;
457   - }
458   - else if ($update) {
459   - // update database schema with the diff from the above check
460   - $success = $schema->alterDatabase($reference, $definition, $diff);
461   -
462   - if (PEAR::isError($success)) {
463   - $this->raise_error(array('code' => $success->getCode(), 'message' => $success->getMessage() . ' ' . $success->getUserInfo()));
464   - }
465   - else
466   - return true;
467   - }
468   - echo '<pre>'; var_dump($diff); echo '</pre>';
469   - return false;
470   - }
471   - }
472   - else
473   - $this->raise_error(array('message' => "Could not find reference schema file ($ref_schema)"));
474   - return false;
475   - }
476 408
477   - return false;
  409 + return $schema;
478 410 }
479 411
480 412
@@ -521,7 +453,7 @@ function versions_select($attrib = array())
521 453 '0.5-beta', '0.5', '0.5.1',
522 454 '0.6-beta', '0.6',
523 455 '0.7-beta', '0.7', '0.7.1', '0.7.2',
524   - '0.8-beta', '0.8-rc',
  456 + '0.8-beta', '0.8-rc', '0.8.0',
525 457 ));
526 458 return $select;
527 459 }
6 installer/test.php
@@ -125,9 +125,9 @@
125 125 $db_working = false;
126 126 if ($RCI->configured) {
127 127 if (!empty($RCI->config['db_dsnw'])) {
128   -
129   - $DB = new rcube_mdb2($RCI->config['db_dsnw'], '', false);
  128 + $DB = rcube_db::factory($RCI->config['db_dsnw'], '', false);
130 129 $DB->db_connect('w');
  130 +
131 131 if (!($db_error_msg = $DB->is_error())) {
132 132 $RCI->pass('DSN (write)');
133 133 echo '<br />';
@@ -167,7 +167,7 @@
167 167 // test database
168 168 if ($db_working) {
169 169 $db_read = $DB->query("SELECT count(*) FROM {$RCI->config['db_table_users']}");
170   - if ($DB->db_error) {
  170 + if ($DB->is_error()) {
171 171 $RCI->fail('DB Schema', "Database not initialized");
172 172 echo '<p><input type="submit" name="initdb" value="Initialize database" /></p>';
173 173 $db_working = false;
2  installer/utils.php
@@ -23,7 +23,6 @@ function __autoload($classname)
23 23 {
24 24 $filename = preg_replace(
25 25 array(
26   - '/MDB2_(.+)/',
27 26 '/Mail_(.+)/',
28 27 '/Net_(.+)/',
29 28 '/Auth_(.+)/',
@@ -31,7 +30,6 @@ function __autoload($classname)
31 30 '/^utf8$/'
32 31 ),
33 32 array(
34   - 'MDB2/\\1',
35 33 'Mail/\\1',
36 34 'Net/\\1',
37 35 'Auth/\\1',
2  plugins/acl/acl.php
@@ -615,7 +615,7 @@ function rights_supported()
615 615 private function get_realm()
616 616 {
617 617 // When user enters a username without domain part, realm
618   - // alows to add it to the username (and display correct username in the table)
  618 + // allows to add it to the username (and display correct username in the table)
619 619
620 620 if (isset($_SESSION['acl_username_realm'])) {
621 621 return $_SESSION['acl_username_realm'];
2  plugins/enigma/enigma.php
@@ -429,7 +429,7 @@ function message_output($p)
429 429 $style = "margin:0 1em; padding:0.2em 0.5em; border:1px solid #999; width: auto"
430 430 ." border-radius:4px; -moz-border-radius:4px; -webkit-border-radius:4px";
431 431
432   - // add box below messsage body
  432 + // add box below message body
433 433 $p['content'] .= html::p(array('style' => $style),
434 434 html::a(array(
435 435 'href' => "#",
2  plugins/managesieve/Changelog
... ... @@ -1,3 +1,5 @@
  1 +- Fixed issue with DBMail bug [http://pear.php.net/bugs/bug.php?id=19077] (#1488594)
  2 +
1 3 * version 5.2 [2012-07-24]
2 4 -----------------------------------------------------------
3 5 - Added GUI for variables setting - RFC5229 (patch from Paweł Słowik)
4 plugins/managesieve/lib/Net/Sieve.php
@@ -1098,7 +1098,9 @@ function _doCmd($cmd = '', $auth = false)
1098 1098 return PEAR::raiseError(trim($response . $line), 6);
1099 1099 }
1100 1100
1101   - if (preg_match('/^{([0-9]+)}/i', $line, $matches)) {
  1101 + // "\+?" is added in the regexp to workaround DBMail bug
  1102 + // http://dbmail.org/mantis/view.php?id=963
  1103 + if (preg_match('/^{([0-9]+)\+?}/i', $line, $matches)) {
1102 1104 // Matches literal string responses.
1103 1105 $line = $this->_recvBytes($matches[1] + 2);
1104 1106
23 plugins/new_user_identity/new_user_identity.php
@@ -19,10 +19,6 @@
19 19 * // When automatically setting a new users's full name in their
20 20 * // new identity, match the user's login name against this field.
21 21 * $rcmail_config['new_user_identity_match'] = 'uid';
22   - *
23   - * // Use this field (from fieldmap configuration) to fill alias col of
24   - * // the new user record.
25   - * $rcmail_config['new_user_identity_alias'] = 'alias';
26 22 */
27 23 class new_user_identity extends rcube_plugin
28 24 {
@@ -38,16 +34,16 @@ function init()
38 34 function lookup_user_name($args)
39 35 {
40 36 $rcmail = rcmail::get_instance();
41   -
  37 +
42 38 if ($this->init_ldap($args['host'])) {
43   - $results = $this->ldap->search('*', $args['user'], TRUE);
  39 + $results = $this->ldap->search('*', $args['user'], true);
44 40 if (count($results->records) == 1) {
45   - $args['user_name'] = $results->records[0]['name'];
46   - if (!$args['user_email'] && strpos($results->records[0]['email'], '@')) {
47   - $args['user_email'] = rcube_idn_to_ascii($results->records[0]['email']);
48   - }
49   - if (($alias_col = $rcmail->config->get('new_user_identity_alias')) && $results->records[0][$alias_col]) {
50   - $args['alias'] = $results->records[0][$alias_col];
  41 + $user_name = is_array($results->records[0]['name']) ? $results->records[0]['name'][0] : $results->records[0]['name'];
  42 + $user_email = is_array($results->records[0]['email']) ? $results->records[0]['email'][0] : $results->records[0]['email'];
  43 +
  44 + $args['user_name'] = $user_name;
  45 + if (!$args['user_email'] && strpos($user_email, '@')) {
  46 + $args['user_email'] = rcube_idn_to_ascii($user_email);
51 47 }
52 48 }
53 49 }
@@ -56,8 +52,9 @@ function lookup_user_name($args)
56 52
57 53 private function init_ldap($host)
58 54 {
59   - if ($this->ldap)
  55 + if ($this->ldap) {
60 56 return $this->ldap->ready;
  57 + }
61 58
62 59 $rcmail = rcmail::get_instance();
63 60
6 plugins/new_user_identity/package.xml
@@ -15,10 +15,10 @@
15 15 <email>alec@alec.pl</email>
16 16 <active>yes</active>
17 17 </lead>
18   - <date>2011-11-21</date>
  18 + <date>2012-08-13</date>
19 19 <version>
20   - <release>1.0.5</release>
21   - <api>1.0</api>
  20 + <release>1.0.7</release>
  21 + <api>1.1</api>
22 22 </version>
23 23 <stability>
24 24 <release>stable</release>
2  plugins/password/drivers/sql.php
@@ -26,7 +26,7 @@ function save($curpass, $passwd)
26 26 else if (!is_array($dsn) && !preg_match('/\?new_link=true/', $dsn))
27 27 $dsn .= '?new_link=true';
28 28
29   - $db = new rcube_mdb2($dsn, '', FALSE);
  29 + $db = rcube_db::factory($dsn, '', false);
30 30 $db->set_debug((bool)$rcmail->config->get('sql_debug'));
31 31 $db->db_connect('w');
32 32 }
4 plugins/password/drivers/virtualmin.php
@@ -48,10 +48,6 @@ function save($currpass, $newpass)
48 48 $pieces = explode("_", $username);
49 49 $domain = $pieces[0];
50 50 break;
51   - case 8: // domain taken from alias, username left as it was
52   - $email = $rcmail->user->data['alias'];
53   - $domain = substr(strrchr($email, "@"), 1);
54   - break
55 51 default: // username@domain
56 52 $domain = substr(strrchr($username, "@"), 1);
57 53 }
2  plugins/squirrelmail_usercopy/config.inc.php.dist
@@ -22,4 +22,4 @@ $rcmail_config['squirrelmail_identities_level'] = null;
22 22 // Set to false if you don't want the email address of the default identity
23 23 // (squirrelmail preference "email_address") to be saved as alias.
24 24 // Recommended: set to false if your squirrelmail config setting $edit_identity has been true.
25   -$rcmail_config['squirrelmail_set_alias'] = true;
  25 +$rcmail_config['squirrelmail_set_alias'] = true;
6 plugins/squirrelmail_usercopy/squirrelmail_usercopy.php
@@ -151,10 +151,10 @@ private function read_squirrel_prefs($uname)
151 151 $this->prefs = array();
152 152
153 153 /* connect to squirrelmail database */
154   - $db = new rcube_mdb2($rcmail->config->get('squirrelmail_dsn'));
155   - $db->db_connect('r'); // connect in read mode
  154 + $db = rcube_db::factory($rcmail->config->get('squirrelmail_dsn'));
156 155
157   - // $db->set_debug(true);
  156 + $db->set_debug($rcmail->config->get('sql_debug'));
  157 + $db->db_connect('r'); // connect in read mode
158 158
159 159 /* retrieve prefs */
160 160 $userprefs_table = $rcmail->config->get('squirrelmail_userprefs_table');
2  plugins/subscriptions_option/subscriptions_option.php
@@ -9,7 +9,7 @@
9 9 *
10 10 * Add it to the plugins list in config/main.inc.php to enable the user option
11 11 * The user option can be hidden and set globally by adding 'use_subscriptions'
12   - * to the the 'dont_override' configure line:
  12 + * to the 'dont_override' configure line:
13 13 * $rcmail_config['dont_override'] = array('use_subscriptions');
14 14 * and then set the global preference
15 15 * $rcmail_config['use_subscriptions'] = true; // or false
2  plugins/vcard_attachments/vcard_attachments.php
@@ -81,7 +81,7 @@ function html_output($p)
81 81 if ($vcard->email[0])
82 82 $display .= ' <'.$vcard->email[0].'>';
83 83
84   - // add box below messsage body
  84 + // add box below message body
85 85 $p['content'] .= html::p(array('class' => 'vcardattachment'),
86 86 html::a(array(
87 87 'href' => "#",
49 program/include/clisetup.php
@@ -33,33 +33,36 @@
33 33 */
34 34 function get_opt($aliases = array())
35 35 {
36   - $args = array();
37   - for ($i=1; $i < count($_SERVER['argv']); $i++) {
38   - $arg = $_SERVER['argv'][$i];
39   - $value = true;
40   - $key = null;
  36 + $args = array();
41 37
42   - if ($arg[0] == '-') {
43   - $key = preg_replace('/^-+/', '', $arg);
44   - $sp = strpos($arg, '=');
45   - if ($sp > 0) {
46   - $key = substr($key, 0, $sp - 2);
47   - $value = substr($arg, $sp+1);
48   - }
49   - else if (strlen($_SERVER['argv'][$i+1]) && $_SERVER['argv'][$i+1][0] != '-') {
50   - $value = $_SERVER['argv'][++$i];
51   - }
  38 + for ($i=1; $i < count($_SERVER['argv']); $i++) {
  39 + $arg = $_SERVER['argv'][$i];
  40 + $value = true;
  41 + $key = null;
52 42
53   - $args[$key] = is_string($value) ? preg_replace(array('/^["\']/', '/["\']$/'), '', $value) : $value;
54   - }
55   - else
56   - $args[] = $arg;
  43 + if ($arg[0] == '-') {
  44 + $key = preg_replace('/^-+/', '', $arg);
  45 + $sp = strpos($arg, '=');
  46 + if ($sp > 0) {
  47 + $key = substr($key, 0, $sp - 2);
  48 + $value = substr($arg, $sp+1);
  49 + }
  50 + else if (strlen($_SERVER['argv'][$i+1]) && $_SERVER['argv'][$i+1][0] != '-') {
  51 + $value = $_SERVER['argv'][++$i];
  52 + }
57 53
58   - if ($alias = $aliases[$key])
59   - $args[$alias] = $args[$key];
60   - }
  54 + $args[$key] = is_string($value) ? preg_replace(array('/^["\']/', '/["\']$/'), '', $value) : $value;
  55 + }
  56 + else {
  57 + $args[] = $arg;
  58 + }
61 59
62   - return $args;
  60 + if ($alias = $aliases[$key]) {
  61 + $args[$alias] = $args[$key];
  62 + }
  63 + }
  64 +
  65 + return $args;
63 66 }
64 67
65 68
28 program/include/html.php
@@ -171,7 +171,7 @@ public static function a($attr, $cont)
171 171 $attr = array('href' => $attr);
172 172 }
173 173 return self::tag('a', $attr, $cont, array_merge(self::$common_attrib,
174   - array('href','target','name','rel','onclick','onmouseover','onmouseout','onmousedown','onmouseup')));
  174 + array('href','target','name','rel','onclick','onmouseover','onmouseout','onmousedown','onmouseup')));
175 175 }
176 176
177 177 /**
@@ -358,7 +358,7 @@ class html_inputfield extends html
358 358 protected $tagname = 'input';
359 359 protected $type = 'text';
360 360 protected $allowed = array(
361   - 'type','name','value','size','tabindex',
  361 + 'type','name','value','size','tabindex','autocapitalize',
362 362 'autocomplete','checked','onchange','onclick','disabled','readonly',
363 363 'spellcheck','results','maxlength','src','multiple','placeholder',
364 364 );
@@ -532,7 +532,7 @@ class html_textarea extends html
532 532 {
533 533 protected $tagname = 'textarea';
534 534 protected $allowed = array('name','rows','cols','wrap','tabindex',
535   - 'onchange','disabled','readonly','spellcheck');
  535 + 'onchange','disabled','readonly','spellcheck');
536 536
537 537 /**
538 538 * Get HTML code for this object
@@ -563,7 +563,7 @@ public function show($value = '', $attrib = null)
563 563 }
564 564
565 565 return self::tag($this->tagname, $this->attrib, $value,
566   - array_merge(self::$common_attrib, $this->allowed));
  566 + array_merge(self::$common_attrib, $this->allowed));
567 567 }
568 568 }
569 569
@@ -591,7 +591,7 @@ class html_select extends html
591 591 protected $tagname = 'select';
592 592 protected $options = array();
593 593 protected $allowed = array('name','size','tabindex','autocomplete',
594   - 'multiple','onchange','disabled','rel');
  594 + 'multiple','onchange','disabled','rel');
595 595
596 596 /**
597 597 * Add a new option to this drop-down
@@ -655,7 +655,7 @@ class html_table extends html
655 655 {
656 656 protected $tagname = 'table';
657 657 protected $allowed = array('id','class','style','width','summary',
658   - 'cellpadding','cellspacing','border');
  658 + 'cellpadding','cellspacing','border');
659 659
660 660 private $header = array();
661 661 private $rows = array();
@@ -705,8 +705,9 @@ public function add($attr, $cont)
705 705 */
706 706 public function add_header($attr, $cont)
707 707 {
708   - if (is_string($attr))
709   - $attr = array('class' => $attr);
  708 + if (is_string($attr)) {
  709 + $attr = array('class' => $attr);
  710 + }
710 711
711 712 $cell = new stdClass;
712 713 $cell->attrib = $attr;
@@ -763,11 +764,13 @@ public function add_row($attr = array())
763 764 */
764 765 public function set_row_attribs($attr = array(), $index = null)
765 766 {
766   - if (is_string($attr))
767   - $attr = array('class' => $attr);
  767 + if (is_string($attr)) {
  768 + $attr = array('class' => $attr);
  769 + }
768 770
769   - if ($index === null)
  771 + if ($index === null) {
770 772 $index = $this->rowindex;
  773 + }
771 774
772 775 $this->rows[$index]->attrib = $attr;
773 776 }
@@ -781,8 +784,9 @@ public function set_row_attribs($attr = array(), $index = null)
781 784 */
782 785 public function get_row_attribs($index = null)
783 786 {
784   - if ($index === null)
  787 + if ($index === null) {
785 788 $index = $this->rowindex;
  789 + }
786 790
787 791 return $this->rows[$index] ? $this->rows[$index]->attrib : null;
788 792 }
10 program/include/rcube.php
@@ -49,14 +49,14 @@ class rcube
49 49 /**
50 50 * Instace of database class.
51 51 *
52   - * @var rcube_mdb2
  52 + * @var rcube_pdo
53 53 */
54 54 public $db;
55 55
56 56 /**
57 57 * Instace of Memcache class.
58 58 *
59   - * @var rcube_mdb2
  59 + * @var Memcache
60 60 */
61 61 public $memcache;
62 62
@@ -160,15 +160,13 @@ protected function init($mode = 0)
160 160 /**
161 161 * Get the current database connection
162 162 *
163   - * @return rcube_mdb2 Database connection object
  163 + * @return rcube_pdo Database connection object
164 164 */
165 165 public function get_dbh()
166 166 {
167 167 if (!$this->db) {
168 168 $config_all = $this->config->all();
169   -
170   - $this->db = new rcube_mdb2($config_all['db_dsnw'], $config_all['db_dsnr'], $config_all['db_persistent']);
171   - $this->db->sqlite_initials = INSTALL_PATH . 'SQL/sqlite.initial.sql';
  169 + $this->db = rcube_db::factory($config_all['db_dsnw'], $config_all['db_dsnr'], $config_all['db_persistent']);
172 170 $this->db->set_debug((bool)$config_all['sql_debug']);
173 171 }
174 172
17 program/include/rcube_cache.php
@@ -33,9 +33,9 @@
33 33 class rcube_cache
34 34 {
35 35 /**
36   - * Instance of rcube_mdb2 or Memcache class
  36 + * Instance of database handler
37 37 *
38   - * @var rcube_mdb2/Memcache
  38 + * @var rcube_db|Memcache|bool
39 39 */
40 40 private $db;
41 41 private $type;
@@ -254,7 +254,7 @@ private function read_record($key, $nostore=false)
254 254 }
255 255 else if ($this->type == 'apc') {
256 256 $data = apc_fetch($this->ckey($key));
257   - }
  257 + }
258 258
259 259 if ($data) {
260 260 $md5sum = md5($data);
@@ -294,7 +294,7 @@ private function read_record($key, $nostore=false)
294 294 }
295 295
296 296 $this->cache[$key] = $data;
297   - $this->cache_sums[$key] = $md5sum;
  297 + $this->cache_sums[$key] = $md5sum;
298 298 }
299 299 else {
300 300 $this->cache[$key] = null;
@@ -463,10 +463,13 @@ private function add_record($key, $data, $index=false)
463 463 */
464 464 private function delete_record($key, $index=true)
465 465 {
466   - if ($this->type == 'memcache')
467   - $this->db->delete($this->ckey($key));
468   - else
  466 + if ($this->type == 'memcache') {
  467 + // #1488592: use 2nd argument
  468 + $this->db->delete($this->ckey($key), 0);
  469 + }
  470 + else {
469 471 apc_delete($this->ckey($key));
  472 + }
470 473
471 474 if ($index) {
472 475 if (($idx = array_search($key, $this->index)) !== false) {
12 program/include/rcube_config.php
@@ -26,6 +26,8 @@
26 26 */
27 27 class rcube_config
28 28 {
  29 + const DEFAULT_SKIN = 'larry';
  30 +
29 31 private $prop = array();
30 32 private $errors = array();
31 33 private $userprefs = array();
@@ -81,13 +83,13 @@ private function load()
81 83 $this->prop['skin'] = str_replace('skins/', '', unslashify($this->prop['skin_path']));
82 84 }
83 85 else {
84   - $this->prop['skin'] = 'larry';
  86 + $this->prop['skin'] = self::DEFAULT_SKIN;
85 87 }
86 88 }
87 89
88 90 // larry is the new default skin :-)
89 91 if ($this->prop['skin'] == 'default')
90   - $this->prop['skin'] = 'larry';
  92 + $this->prop['skin'] = self::DEFAULT_SKIN;
91 93
92 94 // fix paths
93 95 $this->prop['log_dir'] = $this->prop['log_dir'] ? realpath(unslashify($this->prop['log_dir'])) : INSTALL_PATH . 'logs';
@@ -254,7 +256,7 @@ public function set_user_prefs($prefs)
254 256
255 257 // larry is the new default skin :-)
256 258 if ($prefs['skin'] == 'default') {
257   - $prefs['skin'] = 'larry';
  259 + $prefs['skin'] = self::DEFAULT_SKIN;
258 260 }
259 261
260 262 $this->userprefs = $prefs;
@@ -322,7 +324,7 @@ public function get_crypto_key($key)
322 324 if (strlen($key) != 24) {
323 325 rcube::raise_error(array(
324 326 'code' => 500, 'type' => 'php',
325   - 'file' => __FILE__, 'line' => __LINE__,
  327 + 'file' => __FILE__, 'line' => __LINE__,
326 328 'message' => "Configured crypto key '$key' is not exactly 24 bytes long"
327 329 ), true, true);
328 330 }
@@ -346,7 +348,7 @@ public function header_delimiter()
346 348 else
347 349 rcube::raise_error(array(
348 350 'code' => 500, 'type' => 'php',
349   - 'file' => __FILE__, 'line' => __LINE__,
  351 + 'file' => __FILE__, 'line' => __LINE__,
350 352 'message' => "Invalid mail_header_delimiter setting"
351 353 ), true, false);
352 354 }
11 program/include/rcube_contacts.php
@@ -36,7 +36,7 @@ class rcube_contacts extends rcube_addressbook
36 36 /**
37 37 * Store database connection.
38 38 *
39   - * @var rcube_mdb2
  39 + * @var rcube_db
40 40 */
41 41 private $db = null;
42 42 private $user_id = 0;
@@ -934,8 +934,8 @@ function add_to_group($group_id, $ids)
934 934 $contact_id
935 935 );
936 936
937   - if ($this->db->db_error)
938   - $this->set_error(self::ERROR_SAVING, $this->db->db_error_msg);
  937 + if ($error = $this->db->is_error())
  938 + $this->set_error(self::ERROR_SAVING, $error);
939 939 else
940 940 $added++;
941 941 }
@@ -990,9 +990,10 @@ private function unique_groupname($name)
990 990 $checkname);
991 991
992 992 // append number to make name unique
993   - if ($hit = $this->db->num_rows($sql_result))
  993 + if ($hit = $this->db->fetch_array($sql_result)) {
994 994 $checkname = $name . ' ' . $num++;
995   - } while ($hit > 0);
  995 + }
  996 + } while ($hit);
996 997
997 998 return $checkname;
998 999 }
1,002 program/include/rcube_db.php
... ... @@ -0,0 +1,1002 @@
  1 +<?php
  2 +
  3 +/**
  4 + +-----------------------------------------------------------------------+
  5 + | program/include/rcube_db.php |
  6 + | |
  7 + | This file is part of the Roundcube Webmail client |
  8 + | Copyright (C) 2005-2012, The Roundcube Dev Team |
  9 + | |
  10 + | Licensed under the GNU General Public License version 3 or |
  11 + | any later version with exceptions for skins & plugins. |
  12 + | See the README file for a full license statement. |
  13 + | |
  14 + | PURPOSE: |
  15 + | Database wrapper class that implements PHP PDO functions |
  16 + | |
  17 + +-----------------------------------------------------------------------+
  18 + | Author: Aleksander Machniak <alec@alec.pl> |
  19 + +-----------------------------------------------------------------------+
  20 +*/
  21 +
  22 +
  23 +/**
  24 + * Database independent query interface
  25 + *
  26 + * This is a wrapper for the PHP PDO
  27 + *
  28 + * @package Database
  29 + * @version 1.0
  30 + */
  31 +class rcube_db
  32 +{
  33 + protected $db_dsnw; // DSN for write operations
  34 + protected $db_dsnr; // DSN for read operations
  35 + protected $db_connected = false; // Already connected ?
  36 + protected $db_mode; // Connection mode
  37 + protected $dbh; // Connection handle
  38 +
  39 + protected $db_error = false;
  40 + protected $db_error_msg = '';
  41 + protected $conn_failure = false;
  42 + protected $a_query_results = array('dummy');
  43 + protected $last_res_id = 0;
  44 + protected $db_index = 0;
  45 + protected $tables;
  46 + protected $variables;
  47 +
  48 + protected $options = array(
  49 + // column/table quotes
  50 + 'identifier_start' => '"',
  51 + 'identifier_end' => '"',
  52 + );
  53 +
  54 +
  55 + /**
  56 + * Factory, returns driver-specific instance of the class
  57 + *
  58 + * @param string $db_dsnw DSN for read/write operations
  59 + * @param string $db_dsnr Optional DSN for read only operations
  60 + * @param bool $pconn Enables persistent connections
  61 + *
  62 + * @return rcube_db Object instance
  63 + */
  64 + public static function factory($db_dsnw, $db_dsnr = '', $pconn = false)
  65 + {
  66 + $driver = strtolower(substr($db_dsnw, 0, strpos($db_dsnw, ':')));
  67 + $driver_map = array(
  68 + 'sqlite2' => 'sqlite',
  69 + 'sybase' => 'mssql',
  70 + 'dblib' => 'mssql',
  71 + 'mysqli' => 'mysql',
  72 + );
  73 +
  74 + $driver = isset($driver_map[$driver]) ? $driver_map[$driver] : $driver;
  75 + $class = "rcube_db_$driver";
  76 +
  77 + if (!class_exists($class)) {
  78 + rcube::raise_error(array('code' => 600, 'type' => 'db',
  79 + 'line' => __LINE__, 'file' => __FILE__,
  80 + 'message' => "Configuration error. Unsupported database driver: $driver"),
  81 + true, true);
  82 + }
  83 +
  84 + return new $class($db_dsnw, $db_dsnr, $pconn);
  85 + }
  86 +
  87 + /**
  88 + * Object constructor
  89 + *
  90 + * @param string $db_dsnw DSN for read/write operations
  91 + * @param string $db_dsnr Optional DSN for read only operations
  92 + * @param bool $pconn Enables persistent connections
  93 + */
  94 + public function __construct($db_dsnw, $db_dsnr = '', $pconn = false)
  95 + {
  96 + if (empty($db_dsnr)) {
  97 + $db_dsnr = $db_dsnw;
  98