From 35c97ac107a26a8590259d82c77d042ebde7efcd Mon Sep 17 00:00:00 2001 From: pdontthink Date: Fri, 27 May 2022 21:33:27 +0000 Subject: [PATCH] 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 git-svn-id: https://svn.code.sf.net/p/squirrelmail/code/trunk/squirrelmail@14969 7612ce4b-ef26-0410-bec9-ea0150e637f0 --- config/config_local.example.php | 8 +++++++ functions/abook_database.php | 40 ++++++++++++++++++++++++++++++--- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/config/config_local.example.php b/config/config_local.example.php index d87bfa0e..57a05ff7 100644 --- a/config/config_local.example.php +++ b/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 diff --git a/functions/abook_database.php b/functions/abook_database.php index d3b6a481..7558a3dc 100644 --- a/functions/abook_database.php +++ b/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): *
- *   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;
     }
 
-- 
2.25.1