Sfoglia il codice sorgente

Add ability to explicitly set address book DB connection charset, though usually if database defaults are sensible this is not something to be concerned with in configuring SquirrelMail

pdontthink 3 anni fa
parent
commit
139a9f97a6
2 ha cambiato i file con 45 aggiunte e 3 eliminazioni
  1. 8 0
      config/config_local.example.php
  2. 37 3
      functions/abook_database.php

+ 8 - 0
config/config_local.example.php

@@ -133,6 +133,14 @@
  * the selection as needed, for example:
  * $prefs_db_charset = 'utf8mb4';
  *
+ * $addrbook_db_charset (string) allows you to explicitly
+ * set the address book (SQL) database connection character
+ * set.  In most cases, system defaults should be sufficient,
+ * even for UTF-8 contact names and so forth, but this
+ * allows you to specifically make the selection as needed,
+ * for example:
+ * $addrbook_db_charset = 'utf8mb4';
+ *
  * $use_expiring_security_tokens (boolean) allows you to
  * make SquirrelMail use short-lived anti-CSRF security
  * tokens that expire as desired (not recommended, can

+ 37 - 3
functions/abook_database.php

@@ -48,8 +48,8 @@ if (!$use_pdo)
  * An array with the following elements must be passed to
  * the class constructor (elements marked ? are optional):
  * <pre>
- *   dsn       => database DNS (see PEAR for syntax, but more or
- *                less it is:  mysql://user:pass@hostname/dbname)
+ *   dsn       => database DNS (see PEAR for syntax, but basically
+ *                it is:  mysql://user:pass@hostname/dbname)
  *   table     => table to store addresses in (must exist)
  *   owner     => current user (owner of address data)
  * ? name      => name of address book
@@ -88,6 +88,13 @@ if (!$use_pdo)
  *                                      NOT to quote identifiers by setting
  *                                      this to "none"
  *
+ *
+ * If needed, you can also set $addrbook_db_charset as a string
+ * (such as "utf8mb4") in config/config_local.php if your system
+ * does not default the SQL connection character set as expected
+ * (most sensible systems will do the right thing transparently).
+ * TODO: make this specific to each backend and not a global?
+ *
  * @package squirrelmail
  * @subpackage addressbook
  */
@@ -220,7 +227,7 @@ class abook_database extends addressbook_backend {
      * @return bool
      */
     function open($new = false) {
-        global $use_pdo;
+        global $use_pdo, $addrbook_db_charset;
         $this->error = '';
 
         /* Return true is file is open and $new is unset */
@@ -276,6 +283,8 @@ class abook_database extends addressbook_backend {
                 $pdo_prefs_dsn = $matches[1] . ':unix_socket=' . $matches[9] . ';dbname=' . $matches[5];
             else
                 $pdo_prefs_dsn = $matches[1] . ':host=' . $matches[4] . (!empty($matches[6]) ? ';port=' . $matches[6] : '') . ';dbname=' . $matches[5];
+            if (!empty($addrbook_db_charset))
+                $pdo_prefs_dsn .= ';charset=' . $addrbook_db_charset;
             try {
                 $dbh = new PDO($pdo_prefs_dsn, $matches[2], $matches[3]);
             } catch (Exception $e) {
@@ -300,6 +309,31 @@ class abook_database extends addressbook_backend {
         }
 
         $this->dbh = $dbh;
+
+        // Older versions of PHP are buggy with setting charset on the dsn so we also issue a SET NAMES
+        if (!empty($addrbook_db_charset)) {
+            if ($use_pdo) {
+                $res = $dbh->exec('SET NAMES \'' . $addrbook_db_charset . '\'');
+                /* Purposefully not checking for errors; some setups reportedly botch it on queries like this
+                if ($res === FALSE) {
+                    if ($pdo_show_sql_errors)
+                        $this->error = implode(' - ', $sth->errorInfo());
+                    else
+                        $this->error = _("Could not execute query");
+                }
+                $this->failQuery();
+                */
+            }
+            else {
+                $res = $this->dbh->simpleQuery('SET NAMES \'' . $addrbook_db_charset . '\'');
+                /* Purposefully not checking for errors; some setups reportedly botch it on queries like this
+                if(DB::isError($res)) {
+                    $this->failQuery($res);
+                }
+                */
+            }
+        }
+
         return true;
     }