Horde_Token cleanups.
authorMichael M Slusarz <slusarz@curecanti.org>
Thu, 13 May 2010 08:15:11 +0000 (02:15 -0600)
committerMichael M Slusarz <slusarz@curecanti.org>
Thu, 13 May 2010 17:44:56 +0000 (11:44 -0600)
Horde 4 fixes.  Move DB init out of class.  Use Horde_Token_Exception.
Add Null driver.  Split Driver code into separate class.

framework/Core/lib/Horde/Core/Binder/Token.php
framework/Token/lib/Horde/Token.php
framework/Token/lib/Horde/Token/Driver.php [new file with mode: 0644]
framework/Token/lib/Horde/Token/Exception.php [new file with mode: 0644]
framework/Token/lib/Horde/Token/File.php
framework/Token/lib/Horde/Token/Null.php [new file with mode: 0644]
framework/Token/lib/Horde/Token/Sql.php
framework/Token/package.xml
horde/config/conf.xml
imp/compose.php

index db046f9..32e59d7 100644 (file)
@@ -9,16 +9,71 @@ class Horde_Core_Binder_Token implements Horde_Injector_Binder
     {
         $driver = isset($GLOBALS['conf']['token'])
             ? $GLOBALS['conf']['token']['driver']
-            : 'file';
+            : 'Null';
         $params = isset($GLOBALS['conf']['token'])
             ? Horde::getDriverConfig('token', $GLOBALS['conf']['token']['driver'])
             : array();
+
+        if (strcasecmp($driver, 'Sql') === 0) {
+            Horde_Util::assertDriverConfig($params, array('phptype'), 'token SQL');
+
+            $params = array_merge(array(
+                'database' => '',
+                'hostspec' => '',
+                'password' => '',
+                'table' => 'horde_tokens',
+                'username' => ''
+            ), $params);
+
+            /* Connect to the SQL server using the supplied parameters. */
+            $write_db = $this->_createDb($params);
+
+            /* Check if we need to set up the read DB connection
+             * separately. */
+            if (empty($params['splitread'])) {
+                $params['db'] = $write_db;
+            } else {
+                $params['write_db'] = $write_db;
+                $params['db'] = $this->_createDb(array_merge($params, $params['read']));
+            }
+        } elseif (strcasecmp($driver, 'None') === 0) {
+            $driver = 'Null';
+        }
+
         $params['logger'] = $injector->getInstance('Horde_Log_Logger');
-        return Horde_Token::singleton($driver, $params);
+
+        return Horde_Token::factory($driver, $params);
     }
 
     public function equals(Horde_Injector_Binder $binder)
     {
         return false;
     }
+
+    protected function _createDb($params)
+    {
+        /* Connect to the SQL server using the supplied parameters. */
+        $db = DB::connect($params, array(
+            'persistent' => !empty($params['persistent']),
+            'ssl' => !empty($params['ssl'])
+        ));
+
+        if ($db instanceof PEAR_Error) {
+            throw new Horde_Exception($db);
+        }
+
+        // Set DB portability options.
+        switch ($db->phptype) {
+        case 'mssql':
+            $db->setOption('portability', DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS | DB_PORTABILITY_RTRIM);
+            break;
+
+        default:
+            $db->setOption('portability', DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS);
+            break;
+        }
+
+        return $db;
+    }
+
 }
index 2bc92d0..85df078 100644 (file)
@@ -9,44 +9,25 @@
  * See the enclosed file COPYING for license information (LGPL). If you
  * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
  *
- * @author  Max Kalika <max@horde.org>
- * @author  Chuck Hagenbuch <chuck@horde.org>
- * @package Horde_Token
+ * @author   Max Kalika <max@horde.org>
+ * @author   Chuck Hagenbuch <chuck@horde.org>
+ * @category Horde
+ * @package  Token
  */
 class Horde_Token
 {
     /**
-     * Singleton instances.
+     * Attempts to return a concrete instance based on $driver.
      *
-     * @var array
-     */
-    static protected $_instances = array();
-
-    /**
-     * Logger.
-     *
-     * @var Horde_Log_Logger
-     */
-    protected $_logger;
-
-    /**
-     * Hash of parameters necessary to use the chosen backend.
-     *
-     * @var array
-     */
-    protected $_params = array();
-
-    /**
-     * Attempts to return a concrete Horde_Token instance based on $driver.
-     *
-     * @param mixed $driver  The type of concrete Horde_Token subclass to
-     *                       return. If $driver is an array, then we will look
+     * @param mixed $driver  The type of concrete subclass to return.
+     *                       If $driver is an array, then we will look
      *                       in $driver[0]/lib/Token/ for the subclass
      *                       implementation named $driver[1].php.
      * @param array $params  A hash containing any additional configuration or
      *                       connection parameters a subclass might need.
      *
-     * @return Horde_Token  The newly created concrete Horde_Token instance.
+     * @return Horde_Token_Driver  The newly created concrete instance.
+     * @throws Horde_Token_Exception
      */
     static public function factory($driver, $params = array())
     {
@@ -60,133 +41,11 @@ class Horde_Token
             $class .= '_' . ucfirst($driver);
         }
 
-        if (!class_exists($class)) {
-            /* If driver class doesn't exist or the driver is not
-             * available just default to the parent class, and it is
-             * not necessary to warn about degraded service. */
-            $class = __CLASS__;
-        }
-
-        return new $class($params);
-    }
-
-    /**
-     * Attempts to return a reference to a concrete Horde_Token instance based
-     * on $driver.
-     *
-     * It will only create a new instance if no Horde_Token instance with the
-     * same parameters currently exists.
-     *
-     * This should be used if multiple types of token generators (and, thus,
-     * multiple Horde_Token instances) are required.
-     *
-     * This method must be invoked as:
-     * <code>$var = Horde_Token::singleton();</code>
-     *
-     * @param mixed $driver  The type of concrete Horde_Token subclass to
-     *                       return. If $driver is an array, then we will look
-     *                       in $driver[0]/lib/Token/ for the subclass
-     *                       implementation named $driver[1].php.
-     * @param array $params  A hash containing any additional configuration or
-     *                       connection parameters a subclass might need.
-     *
-     * @return Horde_Token  The concrete Horde_Token reference.
-     */
-    static public function singleton($driver, $params = array())
-    {
-        ksort($params);
-        $sig = hash('md5', serialize(array($driver, $params)));
-
-        if (!isset(self::$_instances[$sig])) {
-            self::$_instances[$sig] = self::factory($driver, $params);
-        }
-
-        return self::$_instances[$sig];
-    }
-
-    /**
-     * Constructor.
-     *
-     * @param array $params  Configuration parameters:
-     * <pre>
-     * 'logger' - (Horde_Log_Logger) A logger object.
-     * </pre>
-     */
-    protected function __construct($params)
-    {
-        if (isset($params['logger'])) {
-            $this->_logger = $params['logger'];
-            unset($params['logger']);
-        }
-
-        $this->_params = $params;
-    }
-
-    /**
-     * TODO
-     */
-    public function encodeRemoteAddress()
-    {
-        return isset($_SERVER['REMOTE_ADDR'])
-            ? base64_encode($_SERVER['REMOTE_ADDR'])
-            : '';
-    }
-
-    /**
-     * Checks if the given token has been previously used. First
-     * purges all expired tokens. Then retrieves current tokens for
-     * the given ip address. If the specified token was not found,
-     * adds it.
-     *
-     * @param string $token  The value of the token to check.
-     *
-     * @return boolean  True if the token has not been used, false otherwise.
-     * @throws Horde_Exception
-     */
-    public function verify($token)
-    {
-        $this->purge();
-
-        if ($this->exists($token)) {
-            return false;
+        if (class_exists($class)) {
+            return new $class($params);
         }
 
-        $this->add($token);
-        return true;
-    }
-
-    /**
-     * This is an abstract method that should be overridden by a
-     * subclass implementation. The base implementation allows all
-     * token values.
-     *
-     * @throws Horde_Exception
-     */
-    public function exists()
-    {
-        return false;
-    }
-
-    /**
-     * This is an abstract method that should be overridden by a
-     * subclass implementation. The base implementation allows all
-     * token values.
-     *
-     * @throws Horde_Exception
-     */
-    public function add()
-    {
-    }
-
-    /**
-     * This is an abstract method that should be overridden by a
-     * subclass implementation. The base implementation allows all
-     * token values.
-     *
-     * @throws Horde_Exception
-     */
-    public function purge()
-    {
+        throw new Horde_Token_Exception('Driver ' . $driver . ' not found.');
     }
 
     /**
diff --git a/framework/Token/lib/Horde/Token/Driver.php b/framework/Token/lib/Horde/Token/Driver.php
new file mode 100644 (file)
index 0000000..d6407f5
--- /dev/null
@@ -0,0 +1,112 @@
+<?php
+/**
+ * The Horde_Token_Driver:: class provides a common abstracted interface for
+ * a token driver.
+ *
+ * Copyright 2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author   Max Kalika <max@horde.org>
+ * @author   Chuck Hagenbuch <chuck@horde.org>
+ * @category Horde
+ * @package  Token
+ */
+abstract class Horde_Token_Driver
+{
+    /**
+     * Logger.
+     *
+     * @var Horde_Log_Logger
+     */
+    protected $_logger;
+
+    /**
+     * Hash of parameters necessary to use the chosen backend.
+     *
+     * @var array
+     */
+    protected $_params = array();
+
+    /**
+     * Constructor.
+     *
+     * @param array $params  Optional parameters:
+     * <pre>
+     * 'logger' - (Horde_Log_Logger) A logger object.
+     * </pre>
+     */
+    public function __construct($params)
+    {
+        if (isset($params['logger'])) {
+            $this->_logger = $params['logger'];
+            unset($params['logger']);
+        }
+
+        $this->_params = $params;
+    }
+
+    /**
+     * Checks if the given token has been previously used. First
+     * purges all expired tokens. Then retrieves current tokens for
+     * the given ip address. If the specified token was not found,
+     * adds it.
+     *
+     * @param string $token  The value of the token to check.
+     *
+     * @return boolean  True if the token has not been used, false otherwise.
+     * @throws Horde_Token_Exception
+     */
+    public function verify($token)
+    {
+        $this->purge();
+
+        if ($this->exists($token)) {
+            return false;
+        }
+
+        $this->add($token);
+        return true;
+    }
+
+    /**
+     * Does the token exist?
+     *
+     * @param string $tokenID  Token ID.
+     *
+     * @return boolean  True if the token exists.
+     * @throws Horde_Token_Exception
+     */
+    abstract public function exists($tokenID);
+
+    /**
+     * Add a token ID.
+     *
+     * @param string $tokenID  Token ID to add.
+     *
+     * @throws Horde_Token_Exception
+     */
+    abstract public function add($tokenID);
+
+    /**
+     * Delete all expired connection IDs.
+     *
+     * @throws Horde_Token_Exception
+     */
+    abstract public function purge();
+
+    /**
+     * Encodes the remote address.
+     *
+     * @return string  Encoded address.
+     */
+    protected function _encodeRemoteAddress()
+    {
+        return isset($_SERVER['REMOTE_ADDR'])
+            ? base64_encode($_SERVER['REMOTE_ADDR'])
+            : '';
+    }
+
+
+}
diff --git a/framework/Token/lib/Horde/Token/Exception.php b/framework/Token/lib/Horde/Token/Exception.php
new file mode 100644 (file)
index 0000000..97cedc0
--- /dev/null
@@ -0,0 +1,16 @@
+<?php
+/**
+ * Exception handler for the Horde_Token package.
+ *
+ * Copyright 2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author   Michael Slusarz <slusarz@horde.org>
+ * @category Horde
+ * @package  Token
+ */
+class Horde_Token_Exception extends Horde_Exception_Prior
+{
+}
index d90c51a..13a4ded 100644 (file)
@@ -2,20 +2,16 @@
 /**
  * Token tracking implementation for local files.
  *
- * Optional parameters:<pre>
- *   'token_dir'  The directory where to keep token files.
- *   'timeout'    The period (in seconds) after which an id is purged.
- *                Defaults to 86400 (i.e. 24 hours).</pre>
- *
  * Copyright 1999-2010 The Horde Project (http://www.horde.org/)
  *
  * See the enclosed file COPYING for license information (LGPL). If you
  * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
  *
- * @author  Max Kalika <max@horde.org>
- * @package Horde_Token
+ * @author   Max Kalika <max@horde.org>
+ * @category Horde
+ * @package  Token
  */
-class Horde_Token_File extends Horde_Token
+class Horde_Token_File extends Horde_Token_Driver
 {
     /**
      * Handle for the open file descriptor.
@@ -32,23 +28,25 @@ class Horde_Token_File extends Horde_Token
     protected $_connected = false;
 
     /**
-     * Create a new file based token-tracking container.
+     * Constructor.
      *
-     * @param array $params  A hash containing storage parameters.
+     * @param array $params  Optional parameters:
+     * <pre>
+     * 'timeout' - (integer) The period (in seconds) after which an id is
+     *             purged.
+     *             DEFAULT: 86400 (24 hours)
+     * 'token_dir' - (string)  The directory where to keep token files.
+     *               DEFAULT: System temporary directory
+     * </pre>
      */
-    protected function __construct($params = array())
+    public function __construct($params = array())
     {
-        parent::__construct($params);
-
-        /* Choose the directory to save the stub files. */
-        if (!isset($this->_params['token_dir'])) {
-            $this->_params['token_dir'] = Horde_Util::getTempDir();
-        }
+        $params = array_merge(array(
+            'timeout' => 86400,
+            'token_dir' => Horde_Util::getTempDir()
+        ), $params);
 
-        /* Set timeout to 24 hours if not specified. */
-        if (!isset($this->_params['timeout'])) {
-            $this->_params['timeout'] = 86400;
-        }
+        parent::__construct($params);
     }
 
     /**
@@ -56,32 +54,30 @@ class Horde_Token_File extends Horde_Token
      */
     public function __destruct()
     {
-        $this->_disconnect();
+        $this->_disconnect(false);
     }
 
     /**
-     * Deletes all expired connection id's from the SQL server.
+     * Delete all expired connection IDs.
      *
-     * @throws Horde_Exception
+     * @throws Horde_Token_Exception
      */
     public function purge()
     {
         // Make sure we have no open file descriptors before unlinking
         // files.
-        if (!$this->_disconnect()) {
-            throw new Horde_Exception('Unable to close file descriptors');
-        }
+        $this->_disconnect();
 
         /* Build stub file list. */
         if (!($dir = opendir($this->_params['token_dir']))) {
-            throw new Horde_Exception('Unable to open token directory');
+            throw new Horde_Token_Exception('Unable to open token directory');
         }
 
         /* Find expired stub files */
         while (($dirEntry = readdir($dir)) != '') {
             if (preg_match('|^conn_\w{8}$|', $dirEntry) && (time() - filemtime($this->_params['token_dir'] . '/' . $dirEntry) >= $this->_params['timeout']) &&
                 !@unlink($this->_params['token_dir'] . '/' . $dirEntry)) {
-                throw new Horde_Exception('Unable to purge token file.');
+                throw new Horde_Token_Exception('Unable to purge token file.');
             }
         }
 
@@ -89,20 +85,21 @@ class Horde_Token_File extends Horde_Token
     }
 
     /**
-     * TODO
+     * Does the token exist?
+     *
+     * @param string $tokenID  Token ID.
      *
-     * @return boolean  TODO
-     * @throws Horde_Exception
+     * @return boolean  True if the token exists.
+     * @throws Horde_Token_Exception
      */
     public function exists($tokenID)
     {
-        $this->_connect($tokenID);
+        $this->_connect();
 
         /* Find already used IDs. */
-        $fileContents = file($this->_params['token_dir'] . '/conn_' . $this->encodeRemoteAddress());
+        $fileContents = file($this->_params['token_dir'] . '/conn_' . $this->_encodeRemoteAddress());
         if ($fileContents) {
-            $iMax = count($fileContents);
-            for ($i = 0; $i < $iMax; $i++) {
+            for ($i = 0, $iMax = count($fileContents); $i < $iMax; ++$i) {
                 if (chop($fileContents[$i]) == $tokenID) {
                     return true;
                 }
@@ -113,38 +110,37 @@ class Horde_Token_File extends Horde_Token
     }
 
     /**
-     * TODO
+     * Add a token ID.
      *
-     * @throws Horde_Exception
+     * @param string $tokenID  Token ID to add.
+     *
+     * @throws Horde_Token_Exception
      */
     public function add($tokenID)
     {
-        $this->_connect($tokenID);
+        $this->_connect();
 
         /* Write the entry. */
-        fwrite($this->_fd, "$tokenID\n");
+        fwrite($this->_fd, $tokenID . "\n");
 
-        /* Return an error if the update fails, too. */
-        if (!$this->_disconnect()) {
-            throw new Horde_Exception('Failed to close token file cleanly.');
-        }
+        $this->_disconnect();
     }
 
     /**
      * Opens a file descriptor to a new or existing file.
      *
-     * @throws Horde_Exception
+     * @throws Horde_Token_Exception
      */
-    protected function _connect($tokenID)
+    protected function _connect()
     {
         if ($this->_connected) {
             return;
         }
 
         // Open a file descriptor to the token stub file.
-        $this->_fd = @fopen($this->_params['token_dir'] . '/conn_' . $this->encodeRemoteAddress(), 'a');
+        $this->_fd = @fopen($this->_params['token_dir'] . '/conn_' . $this->_encodeRemoteAddress(), 'a');
         if (!$this->_fd) {
-            throw new Horde_Exception('Failed to open token file.');
+            throw new Horde_Token_Exception('Failed to open token file.');
         }
 
         $this->_connected = true;
@@ -153,16 +149,18 @@ class Horde_Token_File extends Horde_Token
     /**
      * Closes the file descriptor.
      *
-     * @return boolean  True on success, false on failure.
+     * @param boolean $error  Throw exception on error?
+     *
+     * @throws Horde_Token_Exception
      */
-    protected function _disconnect()
+    protected function _disconnect($error = true)
     {
         if ($this->_connected) {
             $this->_connected = false;
-            return fclose($this->_fd);
+            if (!fclose($this->_fd) && $error) {
+                throw new Horde_Token_Exception('Unable to close file descriptors');
+            }
         }
-
-        return true;
     }
 
 }
diff --git a/framework/Token/lib/Horde/Token/Null.php b/framework/Token/lib/Horde/Token/Null.php
new file mode 100644 (file)
index 0000000..1c4c2e7
--- /dev/null
@@ -0,0 +1,43 @@
+<?php
+/**
+ * The Horde_Token_Null:: class provides a null implementation of the token
+ * driver.
+ *
+ * Copyright 2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author   Michael Slusarz <slusarz@horde.org>
+ * @category Horde
+ * @package  Token
+ */
+class Horde_Token_Null extends Horde_Token_Driver
+{
+    /**
+     * Does the token exist?
+     *
+     * @return boolean  True if the token exists.
+     */
+    public function exists($tokenID)
+    {
+        return false;
+    }
+
+    /**
+     * Add a token ID.
+     *
+     * @param string $tokenID  Token ID to add.
+     */
+    public function add($tokenID)
+    {
+    }
+
+    /**
+     * Delete all expired connection IDs.
+     */
+    public function purge()
+    {
+    }
+
+}
index bb19223..5202609 100644 (file)
@@ -2,33 +2,7 @@
 /**
  * Token tracking implementation for PHP's PEAR database abstraction layer.
  *
- * Required parameters:<pre>
- *   'phptype'      The database type (ie. 'pgsql', 'mysql', etc.).</pre>
- *
- * Required by some database implementations:<pre>
- *   'database'     The name of the database.
- *   'hostspec'     The hostname of the database server.
- *   'username'     The username with which to connect to the database.
- *   'password'     The password associated with 'username'.
- *   'options'      Additional options to pass to the database.
- *   'tty'          The TTY on which to connect to the database.
- *   'port'         The port on which to connect to the database.</pre>
- *
- * Optional parameters:<pre>
- *   'table'        The name of the tokens table in 'database'.
- *                  Defaults to 'horde_tokens'.
- *   'timeout'      The period (in seconds) after which an id is purged.
- *                  Defaults to 86400 (i.e. 24 hours).</pre>
- *
- * Optional values when using separate reading and writing servers, for example
- * in replication settings:<pre>
- *   'splitread'   Boolean, whether to implement the separation or not.
- *   'read'        Array containing the parameters which are different for
- *                 the read database connection, currently supported
- *                 only 'hostspec' and 'port' parameters.</pre>
- *
  * The table structure for the tokens is as follows:
- *
  * <pre>
  * CREATE TABLE horde_tokens (
  *     token_address    VARCHAR(100) NOT NULL,
  * See the enclosed file COPYING for license information (LGPL). If you
  * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
  *
- * @author  Max Kalika <max@horde.org>
- * @package Horde_Token
+ * @author   Max Kalika <max@horde.org>
+ * @category Horde
+ * @package  Token
  */
-class Horde_Token_Sql extends Horde_Token
+class Horde_Token_Sql extends Horde_Token_Driver
 {
     /**
      * Handle for the current database connection.
@@ -65,37 +40,49 @@ class Horde_Token_Sql extends Horde_Token
     protected $_write_db;
 
     /**
-     * Boolean indicating whether or not we're connected to the SQL
-     * server.
+     * Constructor.
      *
-     * @var boolean
-     */
-    protected $_connected = false;
-
-    /**
-     * Constructs a new SQL connection object.
+     * @param array $params  Parameters:
+     * <pre>
+     * 'db' - (DB) [REQUIRED] The DB instance.
+     * 'table' - (string) The name of the tokens table in 'database'.
+     *           DEFAULT: 'horde_tokens'
+     * 'timeout' - (integer) The period (in seconds) after which an id is
+     *             purged.
+     *             DEFAULT: 86400 (24 hours)
+     * 'write_db' - (DB) The write DB instance.
+     * </pre>
      *
-     * @param array $params  A hash containing connection parameters.
+     * @throws Horde_Token_Exception
      */
-    protected function __construct($params = array())
+    public function __construct($params = array())
     {
-        parent::__construct($params);
+        if (!isset($params['db'])) {
+            throw new Horde_Token_Exception('Missing db parameter.');
+        }
+        $this->_db = $params['db'];
 
-        /* Set timeout to 24 hours if not specified. */
-        if (!isset($this->_params['timeout'])) {
-            $this->_params['timeout'] = 86400;
+        if (isset($params['write_db'])) {
+            $this->_write_db = $params['write_db'];
         }
+
+        unset($params['db'], $params['write_db']);
+
+        $params = array_merge(array(
+            'table' => 'horde_tokens',
+            'timeout' => 86400
+        ), $params);
+
+        parent::__construct($params);
     }
 
     /**
-     * Deletes all expired connection id's from the SQL server.
+     * Delete all expired connection IDs.
      *
-     * @throws Horde_Exception
+     * @throws Horde_Token_Exception
      */
     public function purge()
     {
-        $this->_connect();
-
         /* Build SQL query. */
         $query = 'DELETE FROM ' . $this->_params['table']
             . ' WHERE token_timestamp < ?';
@@ -108,28 +95,25 @@ class Horde_Token_Sql extends Horde_Token
             if ($this->_logger) {
                 $this->_logger->log($result, 'ERR');
             }
-            throw new Horde_Exception_Prior($result);
+            throw new Horde_Token_Exception($result);
         }
     }
 
     /**
-     * TODO
+     * Does the token exist?
+     *
+     * @param string $tokenID  Token ID.
      *
-     * @return boolean  TODO
+     * @return boolean  True if the token exists.
+     * @throws Horde_Token_Exception
      */
     public function exists($tokenID)
     {
-        try {
-            $this->_connect();
-        } catch (Horde_Exception $e) {
-            return false;
-        }
-
         /* Build SQL query. */
         $query = 'SELECT token_id FROM ' . $this->_params['table']
             . ' WHERE token_address = ? AND token_id = ?';
 
-        $values = array($this->encodeRemoteAddress(), $tokenID);
+        $values = array($this->_encodeRemoteAddress(), $tokenID);
 
         $result = $this->_db->getOne($query, $values);
         if ($result instanceof PEAR_Error) {
@@ -137,112 +121,34 @@ class Horde_Token_Sql extends Horde_Token
                 $this->_logger->log($result, 'ERR');
             }
             return false;
-        } else {
-            return !empty($result);
         }
+
+        return !empty($result);
     }
 
     /**
-     * TODO
+     * Add a token ID.
+     *
+     * @param string $tokenID  Token ID to add.
      *
-     * @throws Horde_Exception
+     * @throws Horde_Token_Exception
      */
     public function add($tokenID)
     {
-        $this->_connect();
-
         /* Build SQL query. */
         $query = 'INSERT INTO ' . $this->_params['table']
             . ' (token_address, token_id, token_timestamp)'
             . ' VALUES (?, ?, ?)';
 
-        $values = array($this->encodeRemoteAddress(), $tokenID, time());
+        $values = array($this->_encodeRemoteAddress(), $tokenID, time());
 
         $result = $this->_write_db->query($query, $values);
         if ($result instanceof PEAR_Error) {
             if ($this->_logger) {
                 $this->_logger->log($result, 'ERR');
             }
-            throw new Horde_Exception_Prior($result);
+            throw new Horde_Token_Exception($result);
         }
     }
 
-    /**
-     * Opens a connection to the SQL server.
-     *
-     * @throws Horde_Exception
-     */
-    protected function _connect()
-    {
-        if ($this->_connected) {
-            return;
-        }
-
-        Horde_Util::assertDriverConfig($this->_params, array('phptype'), 'token SQL');
-
-        if (!isset($this->_params['database'])) {
-            $this->_params['database'] = '';
-        }
-        if (!isset($this->_params['username'])) {
-            $this->_params['username'] = '';
-        }
-        if (!isset($this->_params['password'])) {
-            $this->_params['password'] = '';
-        }
-        if (!isset($this->_params['hostspec'])) {
-            $this->_params['hostspec'] = '';
-        }
-        if (!isset($this->_params['table'])) {
-            $this->_params['table'] = 'horde_tokens';
-        }
-
-        /* Connect to the SQL server using the supplied parameters. */
-        $this->_write_db = DB::connect($this->_params,
-                                 array('persistent' => !empty($this->_params['persistent']),
-                                       'ssl' => !empty($this->_params['ssl'])));
-        if ($this->_write_db instanceof PEAR_Error) {
-            throw new Horde_Exception_Prior($this->_write_db);
-        }
-
-        // Set DB portability options.
-        switch ($this->_write_db->phptype) {
-        case 'mssql':
-            $this->_write_db->setOption('portability', DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS | DB_PORTABILITY_RTRIM);
-            break;
-
-        default:
-            $this->_write_db->setOption('portability', DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS);
-            break;
-        }
-
-        /* Check if we need to set up the read DB connection
-         * seperately. */
-        if (!empty($this->_params['splitread'])) {
-            $params = array_merge($this->_params, $this->_params['read']);
-            $this->_db = DB::connect($params,
-                                     array('persistent' => !empty($params['persistent']),
-                                           'ssl' => !empty($params['ssl'])));
-            if ($this->_db instanceof PEAR_Error) {
-                throw new Horde_Exception_Prior($this->_db);
-            }
-
-            // Set DB portability options.
-            switch ($this->_db->phptype) {
-            case 'mssql':
-                $this->_db->setOption('portability', DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS | DB_PORTABILITY_RTRIM);
-                break;
-
-            default:
-                $this->_db->setOption('portability', DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS);
-                break;
-            }
-
-        } else {
-            /* Default to the same DB handle for read. */
-            $this->_db = $this->_write_db;
-        }
-
-        $this->_connected = true;
-    }
-
 }
index 117c69a..a4256ad 100644 (file)
@@ -26,7 +26,9 @@ http://pear.php.net/dtd/package-2.0.xsd">
   <api>beta</api>
  </stability>
  <license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
- <notes>* Use exceptions, not PEAR_Errors.
+ <notes>* Add Horde_Token_Exception::.
+ * Move driver code into Horde_Token_Driver::.
+ * Use exceptions, not PEAR_Errors.
  * Initial Horde 4 package.
  </notes>
  <contents>
@@ -34,7 +36,10 @@ http://pear.php.net/dtd/package-2.0.xsd">
    <dir name="lib">
     <dir name="Horde">
      <dir name="Token">
+      <file name="Driver.php" role="php" />
+      <file name="Exception.php" role="php" />
       <file name="File.php" role="php" />
+      <file name="Null.php" role="php" />
       <file name="Sql.php" role="php" />
      </dir> <!-- /lib/Horde/Token -->
      <file name="Token.php" role="php" />
@@ -48,7 +53,7 @@ http://pear.php.net/dtd/package-2.0.xsd">
     <min>5.2.0</min>
    </php>
    <pearinstaller>
-    <min>1.5.0</min>
+    <min>1.7.0</min>
    </pearinstaller>
    <package>
     <name>Exception</name>
@@ -65,6 +70,10 @@ http://pear.php.net/dtd/package-2.0.xsd">
   </required>
   <optional>
    <package>
+    <name>DB</name>
+    <channel>pear.php.net</channel>
+   </package>
+   <package>
     <name>Log</name>
     <channel>pear.horde.org</channel>
    </package>
@@ -72,7 +81,10 @@ http://pear.php.net/dtd/package-2.0.xsd">
  </dependencies>
  <phprelease>
   <filelist>
+   <install name="lib/Horde/Token/Driver.php" as="Horde/Token/Driver.php" />
+   <install name="lib/Horde/Token/Exception.php" as="Horde/Token/Exception.php" />
    <install name="lib/Horde/Token/File.php" as="Horde/Token/File.php" />
+   <install name="lib/Horde/Token/Null.php" as="Horde/Token/Null.php" />
    <install name="lib/Horde/Token/Sql.php" as="Horde/Token/Sql.php" />
    <install name="lib/Horde/Token.php" as="Horde/Token.php" />
   </filelist>
index 47e43e3..2264545 100644 (file)
    <configswitch name="driver" desc="If you want to enable Form Tokens, select
    a driver here. This is used by the Horde::Form:: API and some other parts
    of Horde to ensure that a form can only be submitted once.">none
-    <case name="none" desc="Disable Form Tokens"/>
-    <case name="file" desc="Local filesystem token storage">
+    <case name="Null" desc="Disable Form Tokens"/>
+    <case name="File" desc="Local filesystem token storage">
      <configsection name="params">
       <configstring name="token_dir" required="false" desc="The directory where
       to keep token files"/>
      </configsection>
     </case>
-    <case name="sql" desc="SQL-based token storage">
+    <case name="Sql" desc="SQL-based token storage">
      <configsection name="params">
       <configsql switchname="driverconfig">
        <configstring name="table" required="false" desc="The name of the
index 20ca606..782cc62 100644 (file)
@@ -85,7 +85,7 @@ if ($vars->compose_formToken) {
             $notification->push(_("You have already submitted this page."), 'horde.error');
             $vars->actionID = null;
         }
-    } catch (Horde_Exception $e) {
+    } catch (Horde_Token_Exception $e) {
         $notification->push($e->getMessage());
         $vars->actionID = null;
     }