From e1ac217397bfc23a5c059aaa12bba8c1fc018cbb Mon Sep 17 00:00:00 2001
From: alecpl <alec@alec.pl>
Date: Wed, 03 Feb 2010 06:16:18 -0500
Subject: [PATCH] - Fix inconsistency when not using default table names (#1486467)

---
 program/include/rcube_mdb2.php |  184 +++++++++++++++++++++++++++++++++++-----------
 1 files changed, 140 insertions(+), 44 deletions(-)

diff --git a/program/include/rcube_mdb2.php b/program/include/rcube_mdb2.php
index b5767e3..aca44c9 100644
--- a/program/include/rcube_mdb2.php
+++ b/program/include/rcube_mdb2.php
@@ -5,7 +5,7 @@
  | program/include/rcube_mdb2.php                                        |
  |                                                                       |
  | This file is part of the RoundCube Webmail client                     |
- | Copyright (C) 2005-2008, RoundCube Dev. - Switzerland                 |
+ | Copyright (C) 2005-2009, RoundCube Dev. - Switzerland                 |
  | Licensed under the GNU GPL                                            |
  |                                                                       |
  | PURPOSE:                                                              |
@@ -106,7 +106,7 @@
       if (!filesize($dsn_array['database']) && !empty($this->sqlite_initials))
         $this->_sqlite_create_database($dbh, $this->sqlite_initials);
       }
-    else
+    else if ($this->db_provider!='mssql' && $this->db_provider!='sqlsrv')
       $dbh->setCharset('utf8');
 
     return $dbh;
@@ -178,6 +178,17 @@
     
 
   /**
+   * Connection state checker
+   *
+   * @param  boolean  True if in connected state
+   */
+  function is_connected()
+    {
+    return PEAR::isError($this->db_handle) ? false : true;
+    }
+
+
+  /**
    * Execute a SQL query
    *
    * @param  string  SQL query to execute
@@ -187,6 +198,9 @@
    */
   function query()
     {
+    if (!$this->is_connected())
+      return NULL;
+    
     $params = func_get_args();
     $query = array_shift($params);
 
@@ -228,7 +242,7 @@
   function _query($query, $offset, $numrows, $params)
     {
     // Read or write ?
-    if (strtolower(trim(substr($query,0,6)))=='select')
+    if (strtolower(substr(trim($query),0,6))=='select')
       $mode='r';
     else
       $mode='w';
@@ -242,18 +256,19 @@
       $result = $this->db_handle->setLimit($numrows,$offset);
 
     if (empty($params))
-        $result = $this->db_handle->query($query);
+      $result = $mode=='r' ? $this->db_handle->query($query) : $this->db_handle->exec($query);
     else
       {
       $params = (array)$params;
-      $q = $this->db_handle->prepare($query);
+      $q = $this->db_handle->prepare($query, null, $mode=='w' ? MDB2_PREPARE_MANIP : null);
       if ($this->db_handle->isError($q))
         {
         $this->db_error = TRUE;
         $this->db_error_msg = $q->userinfo;
 
-        raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__,
-                          'message' => $this->db_error_msg), TRUE, TRUE);
+        raise_error(array('code' => 500, 'type' => 'db',
+	  'line' => __LINE__, 'file' => __FILE__,
+          'message' => $this->db_error_msg), TRUE, TRUE);
         }
       else
         {
@@ -288,17 +303,18 @@
 
 
   /**
-   * Get number of affected rows fort he last query
+   * Get number of affected rows for the last query
    *
+   * @param  number  Optional query handle identifier
    * @return mixed   Number of rows or FALSE on failure
    * @access public
    */
-  function affected_rows($result = null)
+  function affected_rows($res_id = null)
     {
     if (!$this->db_handle)
       return FALSE;
 
-    return $this->_get_result($result);
+    return (int) $this->_get_result($res_id);
     }
 
 
@@ -306,16 +322,27 @@
    * Get last inserted record ID
    * For Postgres databases, a sequence name is required
    *
-   * @param  string  Sequence name for increment
+   * @param  string  Table name (to find the incremented sequence)
    * @return mixed   ID or FALSE on failure
    * @access public
    */
-  function insert_id($sequence = '')
+  function insert_id($table = '')
     {
     if (!$this->db_handle || $this->db_mode=='r')
       return FALSE;
 
-    return $this->db_handle->lastInsertID($sequence);
+    if ($table) {
+      if ($this->db_provider == 'pgsql')
+        // find sequence name
+        $table = get_sequence_name($table);
+      else
+        // resolve table name
+        $table = get_table_name($table);
+    }
+    
+    $id = $this->db_handle->lastInsertID($table);
+    
+    return $this->db_handle->isError($id) ? null : $id;
     }
 
 
@@ -350,7 +377,7 @@
 
 
   /**
-   * Get co values for a result row
+   * Get col values for a result row
    *
    * @param  object  Query result handle
    * @param  number  Fetch mode identifier
@@ -359,12 +386,8 @@
    */
   function _fetch_row($result, $mode)
     {
-    if (PEAR::isError($result))
-      {
-      raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__,
-                        'message' => $this->db_link->getMessage()), TRUE, FALSE);
+    if ($result === FALSE || PEAR::isError($result) || !$this->is_connected())
       return FALSE;
-      }
 
     return $result->fetchRow($mode);
     }
@@ -398,13 +421,13 @@
    * @param  string  Value to quote
    * @return string  Quoted string for use in query
    * @deprecated     Replaced by rcube_MDB2::quote_identifier
-   * @see            rcube_MDB2::quote_identifier
+   * @see            rcube_mdb2::quote_identifier
    * @access public
    */
   function quoteIdentifier($str)
-	{
+    {
     return $this->quote_identifier($str);
-	}
+    }
 
 
   /**
@@ -450,11 +473,32 @@
     switch($this->db_provider)
       {
       case 'mssql':
+      case 'sqlsrv':
         return "getdate()";
 
       default:
         return "now()";
       }
+    }
+
+
+  /**
+   * Return list of elements for use with SQL's IN clause
+   *
+   * @param  string Input array
+   * @return string Elements list string
+   * @access public
+   */
+  function array2list($arr, $type=null)
+    {
+    if (!is_array($arr))
+      return $this->quote($arr, $type);
+    
+    $res = array();
+    foreach ($arr as $item)
+      $res[] = $this->quote($item, $type);
+
+    return implode(',', $res);
     }
 
 
@@ -474,7 +518,8 @@
         break;
 
       case 'mssql':
-        return "datediff(s, '1970-01-01 00:00:00', $field)";
+      case 'sqlsrv':
+	return "DATEDIFF(second, '19700101', $field) + DATEDIFF(second, GETDATE(), GETUTCDATE())";
 
       default:
         return "UNIX_TIMESTAMP($field)";
@@ -526,10 +571,58 @@
 
 
   /**
+   * Encodes non-UTF-8 characters in string/array/object (recursive)
+   *
+   * @param  mixed  Data to fix
+   * @return mixed  Properly UTF-8 encoded data
+   * @access public
+   */
+  function encode($input)
+    {
+    if (is_object($input)) {
+      foreach (get_object_vars($input) as $idx => $value)
+        $input->$idx = $this->encode($value);
+      return $input;
+      }
+    else if (is_array($input)) {
+      foreach ($input as $idx => $value)
+        $input[$idx] = $this->encode($value);
+      return $input;	
+      }
+
+    return utf8_encode($input);
+    }
+
+
+  /**
+   * Decodes encoded UTF-8 string/object/array (recursive)
+   *
+   * @param  mixed  Input data
+   * @return mixed  Decoded data
+   * @access public
+   */
+  function decode($input)
+    {
+    if (is_object($input)) {
+      foreach (get_object_vars($input) as $idx => $value)
+        $input->$idx = $this->decode($value);
+      return $input;
+      }
+    else if (is_array($input)) {
+      foreach ($input as $idx => $value)
+        $input[$idx] = $this->decode($value);
+      return $input;	
+      }
+
+    return utf8_decode($input);
+    }
+
+
+  /**
    * Adds a query result and returns a handle ID
    *
    * @param  object  Query handle
-   * @return mixed   Handle ID or FALE on failure
+   * @return mixed   Handle ID
    * @access private
    */
   function _add_result($res)
@@ -537,26 +630,28 @@
     // sql error occured
     if (PEAR::isError($res))
       {
-      raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__,
-                        'message' => $res->getMessage() . " Query: " . substr(preg_replace('/[\r\n]+\s*/', ' ', $res->userinfo), 0, 512)), TRUE, FALSE);
-      return FALSE;
+      $this->db_error = TRUE;
+      $this->db_error_msg = $res->getMessage();
+      raise_error(array('code' => 500, 'type' => 'db',
+    	    'line' => __LINE__, 'file' => __FILE__,
+    	    'message' => $res->getMessage() . " Query: " 
+	    . substr(preg_replace('/[\r\n]+\s*/', ' ', $res->userinfo), 0, 512)),
+	    TRUE, FALSE);
       }
-    else
-      {
-      $res_id = sizeof($this->a_query_results);
-      $this->a_query_results[$res_id] = $res;
-      $this->last_res_id = $res_id;
-      return $res_id;
-      }
+    
+    $res_id = sizeof($this->a_query_results);
+    $this->last_res_id = $res_id;
+    $this->a_query_results[$res_id] = $res;
+    return $res_id;
     }
 
 
   /**
    * Resolves a given handle ID and returns the according query handle
-   * If no ID is specified, the last ressource handle will be returned
+   * If no ID is specified, the last resource handle will be returned
    *
    * @param  number  Handle ID
-   * @return mixed   Ressource handle or FALE on failure
+   * @return mixed   Resource handle or FALSE on failure
    * @access private
    */
   function _get_result($res_id=NULL)
@@ -564,10 +659,11 @@
     if ($res_id==NULL)
       $res_id = $this->last_res_id;
 
-     if ($res_id && isset($this->a_query_results[$res_id]))
-       return $this->a_query_results[$res_id];
-     else
-       return FALSE;
+    if (isset($this->a_query_results[$res_id]))
+      if (!PEAR::isError($this->a_query_results[$res_id]))
+        return $this->a_query_results[$res_id];
+    
+    return FALSE;
     }
 
 
@@ -586,7 +682,9 @@
     $data = file_get_contents($file_name);
 
     if (strlen($data))
-      sqlite_exec($dbh->connection, $data);
+      if (!sqlite_exec($dbh->connection, $data, $error) || MDB2::isError($dbh)) 
+        raise_error(array('code' => 500, 'type' => 'db',
+	    'line' => __LINE__, 'file' => __FILE__, 'message' => $error), TRUE, FALSE); 
     }
 
 
@@ -618,8 +716,6 @@
   {
     $debug_output = $scope . '('.$db->db_index.'): ';
     $debug_output .= $message . $db->getOption('log_line_break');
-    write_log('sqllog', $debug_output);
+    write_log('sql', $debug_output);
   }
 }
-
-

--
Gitblit v1.9.1