[Pkg-php-commits] r1300 - in pear/php-auth/branches/upstream/current: . Auth-1.6.2 Auth-1.6.2/Auth Auth-1.6.2/Container Auth-1.6.2/Frontend Auth-1.6.2/examples Auth-1.6.2/tests

Gregory Colpart reg at alioth.debian.org
Sun Nov 8 16:12:19 UTC 2009


Author: reg
Date: 2009-11-08 16:12:17 +0000 (Sun, 08 Nov 2009)
New Revision: 1300

Added:
   pear/php-auth/branches/upstream/current/Auth-1.6.2/
   pear/php-auth/branches/upstream/current/Auth-1.6.2/Auth.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/Auth/
   pear/php-auth/branches/upstream/current/Auth-1.6.2/Auth/Anonymous.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/Auth/Auth.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/Auth/Controller.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/Container.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/
   pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/Array.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/DB.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/DBLite.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/File.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/IMAP.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/KADM5.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/LDAP.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/MDB.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/MDB2.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/Multiple.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/NetVPOPMaild.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/PEAR.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/POP3.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/RADIUS.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/SAP.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/SMBPasswd.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/SOAP.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/SOAP5.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/vpopmail.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/Frontend/
   pear/php-auth/branches/upstream/current/Auth-1.6.2/Frontend/Html.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/Frontend/md5.js
   pear/php-auth/branches/upstream/current/Auth-1.6.2/README.AdvancedSecurity
   pear/php-auth/branches/upstream/current/Auth-1.6.2/README.Auth
   pear/php-auth/branches/upstream/current/Auth-1.6.2/examples/
   pear/php-auth/branches/upstream/current/Auth-1.6.2/examples/logging.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/examples/multi-container.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/
   pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/DBContainer.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/FileContainer.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/MDB2Container.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/MDBContainer.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/POP3Container.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/POP3aContainer.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/TestAuthContainer.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/auth_container_db_options.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/auth_container_file_options.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/auth_container_mdb2_options.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/auth_container_mdb_options.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/auth_container_pop3_options.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/auth_container_pop3a_options.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/bug8735.passwd
   pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/bug8735.phpt
   pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/mysql_test_db.sql
   pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/tests.php
   pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/users
Removed:
   pear/php-auth/branches/upstream/current/Auth-1.6.1/
Modified:
   pear/php-auth/branches/upstream/current/package.xml
Log:
[svn-upgrade] Integrating new upstream version, php-auth (1.6.2)

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/Auth/Anonymous.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/Auth/Anonymous.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/Auth/Anonymous.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,138 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
+
+/**
+ * Anonymous authentication support
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.01 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license at php.net so we can mail you a copy immediately.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Yavor Shahpasov <yavo at netsmart.com.cy>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    CVS: $Id: Anonymous.php 289651 2009-10-15 04:39:07Z aashley $
+ * @link       http://pear.php.net/package/Auth
+ * @since      File available since Release 1.3.0
+ */
+
+/**
+ * Include Auth package
+ */
+require_once 'Auth.php';
+
+/**
+ * Anonymous Authentication
+ *
+ * This class provides anonymous authentication if username and password
+ * were not supplied
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Yavor Shahpasov <yavo at netsmart.com.cy>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    Release: 1.6.2  File: $Revision: 289651 $
+ * @link       http://pear.php.net/package/Auth
+ * @since      Class available since Release 1.3.0
+ */
+class Auth_Anonymous extends Auth
+{
+
+    // {{{ properties
+
+    /**
+     * Whether to allow anonymous authentication
+     *
+     * @var boolean
+     */
+    var $allow_anonymous = true;
+
+    /**
+     * Username to use for anonymous user
+     *
+     * @var string
+     */
+    var $anonymous_username = 'anonymous';
+
+    // }}}
+    // {{{ Auth_Anonymous() [constructor]
+
+    /**
+     * Pass all parameters to Parent Auth class
+     *
+     * Set up the storage driver.
+     *
+     * @param string    Type of the storage driver
+     * @param mixed     Additional options for the storage driver
+     *                  (example: if you are using DB as the storage
+     *                   driver, you have to pass the dsn string here)
+     *
+     * @param string    Name of the function that creates the login form
+     * @param boolean   Should the login form be displayed if necessary?
+     * @return void
+     * @see Auth::Auth()
+     */
+    function Auth_Anonymous($storageDriver, $options = '', $loginFunction = '', $showLogin = true) {
+        parent::Auth($storageDriver, $options, $loginFunction, $showLogin);
+    }
+
+    // }}}
+    // {{{ login()
+
+    /**
+     * Login function
+     *
+     * If no username & password is passed then login as the username
+     * provided in $this->anonymous_username else call standard login()
+     * function.
+     *
+     * @return void
+     * @access private
+     * @see Auth::login()
+     */
+    function login() {
+        if (   $this->allow_anonymous
+            && empty($this->username)
+            && empty($this->password) ) {
+            $this->setAuth($this->anonymous_username);
+            if (is_callable($this->loginCallback)) {
+                call_user_func_array($this->loginCallback, array($this->username, $this) );
+            }
+        } else {
+            // Call normal login system
+            parent::login();
+        }
+    }
+
+    // }}}
+    // {{{ forceLogin()
+
+    /**
+     * Force the user to login
+     *
+     * Calling this function forces the user to provide a real username and
+     * password before continuing.
+     *
+     * @return void
+     */
+    function forceLogin() {
+        $this->allow_anonymous = false;
+        if( !empty($this->session['username']) && $this->session['username'] == $this->anonymous_username ) {
+            $this->logout();
+        }
+    }
+
+    // }}}
+
+}
+
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/Auth/Auth.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/Auth/Auth.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/Auth/Auth.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,30 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
+
+/**
+ * Provide compatibility with previous Auth include location.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.01 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license at php.net so we can mail you a copy immediately.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Martin Jansen <mj at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    CVS: $Id: Auth.php 208437 2006-03-02 06:53:08Z aashley $
+ * @link       http://pear.php.net/package/Auth
+ * @deprecated File deprecated since Release 1.2.0
+ */
+
+/**
+ * Include Auth package
+ */
+require_once 'Auth.php';
+
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/Auth/Controller.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/Auth/Controller.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/Auth/Controller.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,302 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
+
+/**
+ * Auth Controller
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.01 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license at php.net so we can mail you a copy immediately.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Yavor Shahpasov <yavo at netsmart.com.cy>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    CVS: $Id: Controller.php 237449 2007-06-12 03:11:27Z aashley $
+ * @link       http://pear.php.net/package/Auth
+ * @since      File available since Release 1.3.0
+ */
+
+/**
+ * Controlls access to a group of php access
+ * and redirects to a predefined login page as
+ * needed
+ *
+ * In all pages
+ * <code>
+ * include_once('Auth.php');
+ * include_once('Auth/Controller.php');
+ * $_auth = new Auth('File', 'passwd');
+ * $authController = new Auth_Controller($_auth, 'login.php', 'index.php');
+ * $authController->start();
+ * </code>
+ *
+ * In login.php
+ * <code>
+ * include_once('Auth.php');
+ * include_once('Auth/Controller.php');
+ * $_auth = new Auth('File', 'passwd');
+ * $authController = new Auth_Controller($_auth, 'login.php', 'index.php');
+ * $authController->start();
+ * if( $authController->isAuthorised() ){
+ *   $authController->redirectBack();
+ * }
+ * </code>
+ *
+ * @category   Authentication
+ * @author     Yavor Shahpasov <yavo at netsmart.com.cy>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    Release: 1.6.2  File: $Revision: 237449 $
+ * @link       http://pear.php.net/package/Auth
+ * @since      Class available since Release 1.3.0
+ */
+class Auth_Controller
+{
+
+    // {{{ properties
+
+    /**
+     * The Auth instance this controller is managing
+     *
+     * @var object Auth
+     */
+    var $auth = null;
+
+    /**
+     * The login URL
+     * @var string
+     * */
+    var $login = null;
+
+    /**
+     * The default index page to use when the caller page is not set
+     *
+     * @var string
+     */
+    var $default = null;
+
+    /**
+     * If this is set to true after a succesfull login the
+     * Auth_Controller::redirectBack() is invoked automatically
+     *
+     * @var boolean
+     */
+    var $autoRedirectBack = false;
+
+    // }}}
+    // {{{ Auth_Controller() [constructor]
+
+    /**
+     * Constructor
+     *
+     * @param Auth An auth instance
+     * @param string The login page
+     * @param string The default page to go to if return page is not set
+     * @param array Some rules about which urls need to be sent to the login page
+     * @return void
+     * @todo Add a list of urls which need redirection
+     */
+    function Auth_Controller(&$auth_obj, $login='login.php', $default='index.php', $accessList=array())
+    {
+        $this->auth =& $auth_obj;
+        $this->_loginPage = $login;
+        $this->_defaultPage = $default;
+        @session_start();
+        if (!empty($_GET['return']) && $_GET['return'] && !strstr($_GET['return'], $this->_loginPage)) {
+            $this->auth->setAuthData('returnUrl', $_GET['return']);
+        }
+
+        if(!empty($_GET['authstatus']) && $this->auth->status == '') {
+            $this->auth->status = $_GET['authstatus'];
+        }
+    }
+
+    // }}}
+    // {{{ setAutoRedirectBack()
+
+    /**
+     * Enables auto redirection when login is done
+     *
+     * @param bool Sets the autoRedirectBack flag to this
+     * @see Auth_Controller::autoRedirectBack
+     * @return void
+     */
+    function setAutoRedirectBack($flag = true)
+    {
+        $this->autoRedirectBack = $flag;
+    }
+
+    // }}}
+    // {{{ redirectBack()
+
+    /**
+     * Redirects Back to the calling page
+     *
+     * @return void
+     */
+    function redirectBack()
+    {
+        // If redirectback go there
+        // else go to the default page
+
+        $returnUrl = $this->auth->getAuthData('returnUrl');
+        if(!$returnUrl) {
+            $returnUrl = $this->_defaultPage;
+        }
+
+        // Add some entropy to the return to make it unique
+        // avoind problems with cached pages and proxies
+        if(strpos($returnUrl, '?') === false) {
+            $returnUrl .= '?';
+        }
+        $returnUrl .= uniqid('');
+
+        // Track the auth status
+        if($this->auth->status != '') {
+            $url .= '&authstatus='.$this->auth->status;
+        }
+        header('Location:'.$returnUrl);
+        print("You could not be redirected to <a href=\"$returnUrl\">$returnUrl</a>");
+    }
+
+    // }}}
+    // {{{ redirectLogin()
+
+    /**
+      * Redirects to the login Page if not authorised
+      *
+      * put return page on the query or in auth
+      *
+      * @return void
+      */
+    function redirectLogin()
+    {
+        // Go to the login Page
+
+        // For Auth, put some check to avoid infinite redirects, this should at least exclude
+        // the login page
+
+        $url = $this->_loginPage;
+        if(strpos($url, '?') === false) {
+            $url .= '?';
+        }
+
+        if(!strstr($_SERVER['PHP_SELF'], $this->_loginPage)) {
+            $url .= 'return='.urlencode($_SERVER['PHP_SELF']);
+        }
+
+        // Track the auth status
+        if($this->auth->status != '') {
+            $url .= '&authstatus='.$this->auth->status;
+        }
+
+        header('Location:'.$url);
+        print("You could not be redirected to <a href=\"$url\">$url</a>");
+    }
+
+    // }}}
+    // {{{ start()
+
+    /**
+      * Starts the Auth Procedure
+      *
+      * If the page requires login the user is redirected to the login page
+      * otherwise the Auth::start is called to initialize Auth
+      *
+      * @return void
+      * @todo Implement an access list which specifies which urls/pages need login and which do not
+      */
+    function start()
+    {
+        // Check the accessList here
+        // ACL should be a list of urls with allow/deny
+        // If allow set allowLogin to false
+        // Some wild card matching should be implemented ?,*
+        if(!strstr($_SERVER['PHP_SELF'], $this->_loginPage) && !$this->auth->checkAuth()) {
+            $this->redirectLogin();
+        } else {
+            $this->auth->start();
+            // Logged on and on login page
+            if(strstr($_SERVER['PHP_SELF'], $this->_loginPage) && $this->auth->checkAuth()){
+                $this->autoRedirectBack ?
+                    $this->redirectBack() :
+                    null ;
+            }
+        }
+
+
+    }
+
+    // }}}
+    // {{{ isAuthorised()
+
+    /**
+      * Checks is the user is logged on
+      * @see Auth::checkAuth()
+      */
+    function isAuthorised()
+    {
+        return($this->auth->checkAuth());
+    }
+
+    // }}}
+    // {{{ checkAuth()
+
+    /**
+      * Proxy call to auth
+      * @see Auth::checkAuth()
+      */
+    function checkAuth()
+    {
+        return($this->auth->checkAuth());
+    }
+
+    // }}}
+    // {{{ logout()
+
+    /**
+      * Proxy call to auth
+      * @see Auth::logout()
+      */
+    function logout()
+    {
+        return($this->auth->logout());
+    }
+
+    // }}}
+    // {{{ getUsername()
+
+    /**
+      * Proxy call to auth
+      * @see Auth::getUsername()
+      */
+    function getUsername()
+    {
+        return($this->auth->getUsername());
+    }
+
+    // }}}
+    // {{{ getStatus()
+
+    /**
+      * Proxy call to auth
+      * @see Auth::getStatus()
+      */
+    function getStatus()
+    {
+        return($this->auth->getStatus());
+    }
+
+    // }}}
+
+}
+
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/Auth.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/Auth.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/Auth.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,1365 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
+
+/**
+ * The main include file for Auth package
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.01 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license at php.net so we can mail you a copy immediately.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Martin Jansen <mj at php.net>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    CVS: $Id: Auth.php 289651 2009-10-15 04:39:07Z aashley $
+ * @link       http://pear.php.net/package/Auth
+ */
+
+/**
+ * Returned if session exceeds idle time
+ */
+define('AUTH_IDLED',                    -1);
+/**
+ * Returned if session has expired
+ */
+define('AUTH_EXPIRED',                  -2);
+/**
+ * Returned if container is unable to authenticate user/password pair
+ */
+define('AUTH_WRONG_LOGIN',              -3);
+/**
+ * Returned if a container method is not supported.
+ */
+define('AUTH_METHOD_NOT_SUPPORTED',     -4);
+/**
+ * Returned if new Advanced security system detects a breach
+ */
+define('AUTH_SECURITY_BREACH',          -5);
+/**
+ * Returned if checkAuthCallback says session should not continue.
+ */
+define('AUTH_CALLBACK_ABORT',           -6);
+
+/**
+ * Auth Log level - INFO
+ */
+define('AUTH_LOG_INFO',     6);
+/**
+ * Auth Log level - DEBUG
+ */
+define('AUTH_LOG_DEBUG',    7);
+
+/**
+ * Auth Advanced Security - IP Checks
+ */
+define('AUTH_ADV_IPCHECK', 1);
+/**
+ * Auth Advanced Security - User Agent Checks
+ */
+define('AUTH_ADV_USERAGENT', 2);
+/**
+ * Auth Advanced Security - Challenge Response
+ */
+define('AUTH_ADV_CHALLENGE', 3);
+
+
+/**
+ * PEAR::Auth
+ *
+ * The PEAR::Auth class provides methods for creating an
+ * authentication system using PHP.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Martin Jansen <mj at php.net>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    Release: 1.6.2  File: $Revision: 289651 $
+ * @link       http://pear.php.net/package/Auth
+ */
+class Auth {
+
+    // {{{ properties
+
+    /**
+     * Auth lifetime in seconds
+     *
+     * If this variable is set to 0, auth never expires
+     *
+     * @var  integer
+     * @see  setExpire(), checkAuth()
+     */
+    var $expire = 0;
+
+    /**
+     * Has the auth session expired?
+     *
+     * @var   bool
+     * @see   checkAuth()
+     */
+    var $expired = false;
+
+    /**
+     * Maximum idletime in seconds
+     *
+     * The difference to $expire is, that the idletime gets
+     * refreshed each time checkAuth() is called. If this
+     * variable is set to 0, idletime is never checked.
+     *
+     * @var integer
+     * @see setIdle(), checkAuth()
+     */
+    var $idle = 0;
+
+    /**
+     * Is the maximum idletime over?
+     *
+     * @var boolean
+     * @see checkAuth()
+     */
+    var $idled = false;
+
+    /**
+     * Storage object
+     *
+     * @var object
+     * @see Auth(), validateLogin()
+     */
+    var $storage = '';
+
+    /**
+     * User-defined function that creates the login screen
+     *
+     * @var string
+     */
+    var $loginFunction = '';
+
+    /**
+     * Should the login form be displayed
+     *
+     * @var   bool
+     * @see   setShowlogin()
+     */
+    var $showLogin = true;
+
+    /**
+      * Is Login Allowed from this page
+      *
+      * @var  bool
+      * @see setAllowLogin
+      */
+    var $allowLogin = true;
+
+    /**
+     * Current authentication status
+     *
+     * @var string
+     */
+    var $status = '';
+
+    /**
+     * Username
+     *
+     * @var string
+     */
+    var $username = '';
+
+    /**
+     * Password
+     *
+     * @var string
+     */
+    var $password = '';
+
+    /**
+     * checkAuth callback function name
+     *
+     * @var string
+     * @see setCheckAuthCallback()
+     */
+    var $checkAuthCallback = '';
+
+    /**
+     * Login callback function name
+     *
+     * @var string
+     * @see setLoginCallback()
+     */
+    var $loginCallback = '';
+
+    /**
+     * Failed Login callback function name
+     *
+     * @var string
+     * @see setFailedLoginCallback()
+     */
+    var $loginFailedCallback = '';
+
+    /**
+     * Logout callback function name
+     *
+     * @var string
+     * @see setLogoutCallback()
+     */
+    var $logoutCallback = '';
+
+    /**
+     * Auth session-array name
+     *
+     * @var string
+     */
+    var $_sessionName = '_authsession';
+
+    /**
+     * Package Version
+     *
+     * @var string
+     */
+    var $version = "@version@";
+
+    /**
+     * Flag to use advanced security
+     * When set extra checks will be made to see if the
+     * user's IP or useragent have changed across requests.
+     * Turned off by default to preserve BC.
+     *
+     * @var mixed Boolean to turn all advanced security options on or off
+     *            Array containing named values turning specific advanced
+     *            security features on or off individually
+     *              array(
+     *                  AUTH_ADV_IPCHECK    => true,
+     *                  AUTH_ADV_USERAGENT  => true,
+     *                  AUTH_ADV_CHALLENGE  => true,
+     *              );
+     */
+    var $advancedsecurity = false;
+
+    /**
+     * Username key in POST array
+     *
+     * @var string
+     */
+    var $_postUsername = 'username';
+
+    /**
+     * Password key in POST array
+     *
+     * @var string
+     */
+    var $_postPassword = 'password';
+
+    /**
+     * Holds a reference to the session auth variable
+     * @var array
+     */
+    var $session;
+
+    /**
+     * Holds a reference to the global server variable
+     * @var array
+     */
+    var $server;
+
+    /**
+     * Holds a reference to the global post variable
+     * @var array
+     */
+    var $post;
+
+    /**
+     * Holds a reference to the global cookie variable
+     * @var array
+     */
+    var $cookie;
+
+    /**
+     * A hash to hold various superglobals as reference
+     * @var array
+     */
+    var $authdata;
+
+    /**
+      * How many times has checkAuth been called
+      * @var int
+      */
+    var $authChecks = 0;
+
+    /**
+     * PEAR::Log object
+     *
+     * @var object Log
+     */
+    var $logger = null;
+
+    /**
+     * Whether to enable logging of behaviour
+     *
+     * @var boolean
+     */
+    var $enableLogging = false;
+
+    /**
+     * Whether to regenerate session id everytime start is called
+     *
+     * @var boolean
+     */
+    var $regenerateSessionId = false;
+
+    // }}}
+    // {{{ Auth() [constructor]
+
+    /**
+     * Constructor
+     *
+     * Set up the storage driver.
+     *
+     * @param string    Type of the storage driver
+     * @param mixed     Additional options for the storage driver
+     *                  (example: if you are using DB as the storage
+     *                   driver, you have to pass the dsn string here)
+     *
+     * @param string    Name of the function that creates the login form
+     * @param boolean   Should the login form be displayed if necessary?
+     * @return void
+     */
+    function Auth($storageDriver, $options = '', $loginFunction = '', $showLogin = true)
+    {
+        $this->applyAuthOptions($options);
+
+        // Start the session suppress error if already started
+        if(!session_id()){
+            @session_start();
+            if(!session_id()) {
+                // Throw error
+                include_once 'PEAR.php';
+                PEAR::throwError('Session could not be started by Auth, '
+                        .'possibly headers are already sent, try putting '
+                        .'ob_start in the beginning of your script');
+            }
+        }
+
+        // Make Sure Auth session variable is there
+        if(!isset($_SESSION[$this->_sessionName])) {
+            $_SESSION[$this->_sessionName] = array();
+        }
+
+        // Assign Some globals to internal references, this will replace _importGlobalVariable
+        $this->session =& $_SESSION[$this->_sessionName];
+        $this->server =& $_SERVER;
+        $this->post =& $_POST;
+        $this->cookie =& $_COOKIE;
+
+        if ($loginFunction != '' && is_callable($loginFunction)) {
+            $this->loginFunction = $loginFunction;
+        }
+
+        if (is_bool($showLogin)) {
+            $this->showLogin = $showLogin;
+        }
+
+        if (is_object($storageDriver)) {
+            $this->storage =& $storageDriver;
+            // Pass a reference to auth to the container, ugly but works
+            // this is used by the DB container to use method setAuthData not staticaly.
+            $this->storage->_auth_obj =& $this;
+        } else {
+            // $this->storage = $this->_factory($storageDriver, $options);
+            //
+            $this->storage_driver = $storageDriver;
+            $this->storage_options =& $options;
+        }
+    }
+
+    // }}}
+    // {{{ applyAuthOptions()
+
+    /**
+      * Set the Auth options
+      *
+      * Some options which are Auth specific will be applied
+      * the rest will be left for usage by the container
+      *
+      * @param array    An array of Auth options
+      * @return array   The options which were not applied
+      * @access private
+      */
+    function &applyAuthOptions(&$options)
+    {
+        if(is_array($options)){
+            if (!empty($options['sessionName'])) {
+                $this->_sessionName = $options['sessionName'];
+                unset($options['sessionName']);
+            }
+            if (isset($options['allowLogin'])) {
+                $this->allowLogin = $options['allowLogin'];
+                unset($options['allowLogin']);
+            }
+            if (!empty($options['postUsername'])) {
+                $this->_postUsername = $options['postUsername'];
+                unset($options['postUsername']);
+            }
+            if (!empty($options['postPassword'])) {
+                $this->_postPassword = $options['postPassword'];
+                unset($options['postPassword']);
+            }
+            if (isset($options['advancedsecurity'])) {
+                $this->advancedsecurity = $options['advancedsecurity'];
+                unset($options['advancedsecurity']);
+            }
+            if (isset($options['enableLogging'])) {
+                $this->enableLogging = $options['enableLogging'];
+                unset($options['enableLogging']);
+            }
+            if (isset($options['regenerateSessionId']) && is_bool($options['regenerateSessionId'])) {
+                $this->regenerateSessionId = $options['regenerateSessionId'];
+            }
+        }
+        return($options);
+    }
+
+    // }}}
+    // {{{ _loadStorage()
+
+    /**
+      * Load Storage Driver if not already loaded
+      *
+      * Suspend storage instantiation to make Auth lighter to use
+      * for calls which do not require login
+      *
+      * @return bool    True if the conainer is loaded, false if the container
+      *                 is already loaded
+      * @access private
+      */
+    function _loadStorage()
+    {
+        if(!is_object($this->storage)) {
+            $this->storage =& $this->_factory($this->storage_driver,
+                    $this->storage_options);
+            $this->storage->_auth_obj =& $this;
+            $this->log('Loaded storage container ('.$this->storage_driver.')', AUTH_LOG_DEBUG);
+            return(true);
+        }
+        return(false);
+    }
+
+    // }}}
+    // {{{ _factory()
+
+    /**
+     * Return a storage driver based on $driver and $options
+     *
+     * @static
+     * @param  string $driver  Type of storage class to return
+     * @param  string $options Optional parameters for the storage class
+     * @return object Object   Storage object
+     * @access private
+     */
+    function &_factory($driver, $options = '')
+    {
+        $storage_class = 'Auth_Container_' . $driver;
+        include_once 'Auth/Container/' . $driver . '.php';
+        $obj =& new $storage_class($options);
+        return $obj;
+    }
+
+    // }}}
+    // {{{ assignData()
+
+    /**
+     * Assign data from login form to internal values
+     *
+     * This function takes the values for username and password
+     * from $HTTP_POST_VARS/$_POST and assigns them to internal variables.
+     * If you wish to use another source apart from $HTTP_POST_VARS/$_POST,
+     * you have to derive this function.
+     *
+     * @global $HTTP_POST_VARS, $_POST
+     * @see    Auth
+     * @return void
+     * @access private
+     */
+    function assignData()
+    {
+        $this->log('Auth::assignData() called.', AUTH_LOG_DEBUG);
+
+        if (   isset($this->post[$this->_postUsername])
+            && $this->post[$this->_postUsername] != '') {
+            $this->username = (get_magic_quotes_gpc() == 1
+                    ? stripslashes($this->post[$this->_postUsername])
+                    : $this->post[$this->_postUsername]);
+        }
+        if (   isset($this->post[$this->_postPassword])
+            && $this->post[$this->_postPassword] != '') {
+            $this->password = (get_magic_quotes_gpc() == 1
+                    ? stripslashes($this->post[$this->_postPassword])
+                    : $this->post[$this->_postPassword] );
+        }
+    }
+
+    // }}}
+    // {{{ start()
+
+    /**
+     * Start new auth session
+     *
+     * @return void
+     * @access public
+     */
+    function start()
+    {
+        $this->log('Auth::start() called.', AUTH_LOG_DEBUG);
+
+        // #10729 - Regenerate session id here if we are generating it on every
+        //          page load.
+        if ($this->regenerateSessionId) {
+            session_regenerate_id(true);
+        }
+
+        $this->assignData();
+        if (!$this->checkAuth() && $this->allowLogin) {
+            $this->login();
+        }
+    }
+
+    // }}}
+    // {{{ login()
+
+    /**
+     * Login function
+     *
+     * @return void
+     * @access private
+     */
+    function login()
+    {
+        $this->log('Auth::login() called.', AUTH_LOG_DEBUG);
+
+        $login_ok = false;
+        $this->_loadStorage();
+
+        // Check if using challenge response
+        (isset($this->post['authsecret']) && $this->post['authsecret'] == 1)
+            ? $usingChap = true
+            : $usingChap = false;
+
+
+        // When the user has already entered a username, we have to validate it.
+        if (!empty($this->username)) {
+            if (true === $this->storage->fetchData($this->username, $this->password, $usingChap)) {
+                $this->session['challengekey'] = md5($this->username.$this->password);
+                $login_ok = true;
+                $this->log('Successful login.', AUTH_LOG_INFO);
+            }
+        }
+
+        if (!empty($this->username) && $login_ok) {
+            $this->setAuth($this->username);
+            if (is_callable($this->loginCallback)) {
+                $this->log('Calling loginCallback ('.$this->loginCallback.').', AUTH_LOG_DEBUG);
+                call_user_func_array($this->loginCallback, array($this->username, &$this));
+            }
+        }
+
+        // If the login failed or the user entered no username,
+        // output the login screen again.
+        if (!empty($this->username) && !$login_ok) {
+            $this->log('Incorrect login.', AUTH_LOG_INFO);
+            $this->status = AUTH_WRONG_LOGIN;
+            if (is_callable($this->loginFailedCallback)) {
+                $this->log('Calling loginFailedCallback ('.$this->loginFailedCallback.').', AUTH_LOG_DEBUG);
+                call_user_func_array($this->loginFailedCallback, array($this->username, &$this));
+            }
+        }
+
+        if ((empty($this->username) || !$login_ok) && $this->showLogin) {
+            $this->log('Rendering Login Form.', AUTH_LOG_INFO);
+            if (is_callable($this->loginFunction)) {
+                $this->log('Calling loginFunction ('.$this->loginFunction.').', AUTH_LOG_DEBUG);
+                call_user_func_array($this->loginFunction, array($this->username, $this->status, &$this));
+            } else {
+                // BC fix Auth used to use drawLogin for this
+                // call is sub classes implement this
+                if (is_callable(array($this, 'drawLogin'))) {
+                    $this->log('Calling Auth::drawLogin()', AUTH_LOG_DEBUG);
+                    return $this->drawLogin($this->username, $this);
+                }
+
+                $this->log('Using default Auth_Frontend_Html', AUTH_LOG_DEBUG);
+
+                // New Login form
+                include_once 'Auth/Frontend/Html.php';
+                return Auth_Frontend_Html::render($this, $this->username);
+            }
+        } else {
+            return;
+        }
+    }
+
+    // }}}
+    // {{{ setExpire()
+
+    /**
+     * Set the maximum expire time
+     *
+     * @param  integer time in seconds
+     * @param  bool    add time to current expire time or not
+     * @return void
+     * @access public
+     */
+    function setExpire($time, $add = false)
+    {
+        $add ? $this->expire += $time : $this->expire = $time;
+    }
+
+    // }}}
+    // {{{ setIdle()
+
+    /**
+     * Set the maximum idle time
+     *
+     * @param  integer time in seconds
+     * @param  bool    add time to current maximum idle time or not
+     * @return void
+     * @access public
+     */
+    function setIdle($time, $add = false)
+    {
+        $add ? $this->idle += $time : $this->idle = $time;
+    }
+
+    // }}}
+    // {{{ setSessionName()
+
+    /**
+     * Set name of the session to a customized value.
+     *
+     * If you are using multiple instances of PEAR::Auth
+     * on the same domain, you can change the name of
+     * session per application via this function.
+     * This will chnage the name of the session variable
+     * auth uses to store it's data in the session
+     *
+     * @param  string New name for the session
+     * @return void
+     * @access public
+     */
+    function setSessionName($name = 'session')
+    {
+        $this->_sessionName = '_auth_'.$name;
+        // Make Sure Auth session variable is there
+        if(!isset($_SESSION[$this->_sessionName])) {
+            $_SESSION[$this->_sessionName] = array();
+        }
+        $this->session =& $_SESSION[$this->_sessionName];
+    }
+
+    // }}}
+    // {{{ setShowLogin()
+
+    /**
+     * Should the login form be displayed if necessary?
+     *
+     * @param  bool    show login form or not
+     * @return void
+     * @access public
+     */
+    function setShowLogin($showLogin = true)
+    {
+        $this->showLogin = $showLogin;
+    }
+
+    // }}}
+    // {{{ setAllowLogin()
+
+    /**
+     * Is Login Allowed from this page?
+     *
+     * @param  bool    allow login from this page or not
+     * @return void
+     * @access public
+     */
+    function setAllowLogin($allowLogin = true)
+    {
+        $this->allowLogin = $allowLogin;
+    }
+
+    // }}}
+    // {{{ setCheckAuthCallback()
+
+    /**
+     * Register a callback function to be called whenever the validity of the login is checked
+     * The function will receive two parameters, the username and a reference to the auth object.
+     *
+     * @param  string  callback function name
+     * @return void
+     * @access public
+     * @since Method available since Release 1.4.3
+     */
+    function setCheckAuthCallback($checkAuthCallback)
+    {
+        $this->checkAuthCallback = $checkAuthCallback;
+    }
+
+    // }}}
+    // {{{ setLoginCallback()
+
+    /**
+     * Register a callback function to be called on user login.
+     * The function will receive two parameters, the username and a reference to the auth object.
+     *
+     * @param  string  callback function name
+     * @return void
+     * @see    setLogoutCallback()
+     * @access public
+     */
+    function setLoginCallback($loginCallback)
+    {
+        $this->loginCallback = $loginCallback;
+    }
+
+    // }}}
+    // {{{ setFailedLoginCallback()
+
+    /**
+     * Register a callback function to be called on failed user login.
+     * The function will receive two parameters, the username and a reference to the auth object.
+     *
+     * @param  string  callback function name
+     * @return void
+     * @access public
+     */
+    function setFailedLoginCallback($loginFailedCallback)
+    {
+        $this->loginFailedCallback = $loginFailedCallback;
+    }
+
+    // }}}
+    // {{{ setLogoutCallback()
+
+    /**
+     * Register a callback function to be called on user logout.
+     * The function will receive three parameters, the username and a reference to the auth object.
+     *
+     * @param  string  callback function name
+     * @return void
+     * @see    setLoginCallback()
+     * @access public
+     */
+    function setLogoutCallback($logoutCallback)
+    {
+        $this->logoutCallback = $logoutCallback;
+    }
+
+    // }}}
+    // {{{ setAuthData()
+
+    /**
+     * Register additional information that is to be stored
+     * in the session.
+     *
+     * @param  string  Name of the data field
+     * @param  mixed   Value of the data field
+     * @param  boolean Should existing data be overwritten? (default
+     *                 is true)
+     * @return void
+     * @access public
+     */
+    function setAuthData($name, $value, $overwrite = true)
+    {
+        if (!empty($this->session['data'][$name]) && $overwrite == false) {
+            return;
+        }
+        $this->session['data'][$name] = $value;
+    }
+
+    // }}}
+    // {{{ getAuthData()
+
+    /**
+     * Get additional information that is stored in the session.
+     *
+     * If no value for the first parameter is passed, the method will
+     * return all data that is currently stored.
+     *
+     * @param  string Name of the data field
+     * @return mixed  Value of the data field.
+     * @access public
+     */
+    function getAuthData($name = null)
+    {
+        if (!isset($this->session['data'])) {
+            return null;
+        }
+        if(!isset($name)) {
+            return $this->session['data'];
+        }
+        if (isset($name) && isset($this->session['data'][$name])) {
+            return $this->session['data'][$name];
+        }
+        return null;
+    }
+
+    // }}}
+    // {{{ setAuth()
+
+    /**
+     * Register variable in a session telling that the user
+     * has logged in successfully
+     *
+     * @param  string Username
+     * @return void
+     * @access public
+     */
+    function setAuth($username)
+    {
+        $this->log('Auth::setAuth() called.', AUTH_LOG_DEBUG);
+
+        // #10729 - Regenerate session id here only if generating at login only
+        //          Don't do it if we are regenerating on every request so we don't
+        //          regenerate it twice in one request.
+        if (!$this->regenerateSessionId) {
+            // #2021 - Change the session id to avoid session fixation attacks php 4.3.3 >
+            session_regenerate_id(true);
+        }
+
+        if (!isset($this->session) || !is_array($this->session)) {
+            $this->session = array();
+        }
+
+        if (!isset($this->session['data'])) {
+            $this->session['data'] = array();
+        }
+
+        $this->session['sessionip'] = isset($this->server['REMOTE_ADDR'])
+            ? $this->server['REMOTE_ADDR']
+            : '';
+        $this->session['sessionuseragent'] = isset($this->server['HTTP_USER_AGENT'])
+            ? $this->server['HTTP_USER_AGENT']
+            : '';
+        $this->session['sessionforwardedfor'] = isset($this->server['HTTP_X_FORWARDED_FOR'])
+            ? $this->server['HTTP_X_FORWARDED_FOR']
+            : '';
+
+        // This should be set by the container to something more safe
+        // Like md5(passwd.microtime)
+        if(empty($this->session['challengekey'])) {
+            $this->session['challengekey'] = md5($username.microtime());
+        }
+
+        $this->session['challengecookie'] = md5($this->session['challengekey'].microtime());
+        setcookie('authchallenge', $this->session['challengecookie'], 0, '/');
+
+        $this->session['registered'] = true;
+        $this->session['username']   = $username;
+        $this->session['timestamp']  = time();
+        $this->session['idle']       = time();
+    }
+
+    // }}}
+    // {{{ setAdvancedSecurity()
+
+    /**
+      * Enables advanced security checks
+      *
+      * Currently only ip change and useragent change
+      * are detected
+      * @todo Add challenge cookies - Create a cookie which changes every time
+      *       and contains some challenge key which the server can verify with
+      *       a session var cookie might need to be crypted (user pass)
+      * @param bool Enable or disable
+      * @return void
+      * @access public
+      */
+    function setAdvancedSecurity($flag=true)
+    {
+        $this->advancedsecurity = $flag;
+    }
+
+    // }}}
+    // {{{ checkAuth()
+
+    /**
+     * Checks if there is a session with valid auth information.
+     *
+     * @access public
+     * @return boolean  Whether or not the user is authenticated.
+     */
+    function checkAuth()
+    {
+        $this->log('Auth::checkAuth() called.', AUTH_LOG_DEBUG);
+        $this->authChecks++;
+        if (isset($this->session)) {
+            // Check if authentication session is expired
+            if (   $this->expire > 0
+                && isset($this->session['timestamp'])
+                && ($this->session['timestamp'] + $this->expire) < time()) {
+                $this->log('Session Expired', AUTH_LOG_INFO);
+                $this->expired = true;
+                $this->status = AUTH_EXPIRED;
+                $this->logout();
+                return false;
+            }
+
+            // Check if maximum idle time is reached
+            if (   $this->idle > 0
+                && isset($this->session['idle'])
+                && ($this->session['idle'] + $this->idle) < time()) {
+                $this->log('Session Idle Time Reached', AUTH_LOG_INFO);
+                $this->idled = true;
+                $this->status = AUTH_IDLED;
+                $this->logout();
+                return false;
+            }
+
+            if (   isset($this->session['registered'])
+                && isset($this->session['username'])
+                && $this->session['registered'] == true
+                && $this->session['username'] != '') {
+                Auth::updateIdle();
+
+                if ($this->_isAdvancedSecurityEnabled()) {
+                    $this->log('Advanced Security Mode Enabled.', AUTH_LOG_DEBUG);
+
+                    // Only Generate the challenge once
+                    if (   $this->authChecks == 1
+                        && $this->_isAdvancedSecurityEnabled(AUTH_ADV_CHALLENGE)) {
+                        $this->log('Generating new Challenge Cookie.', AUTH_LOG_DEBUG);
+                        $this->session['challengecookieold'] = $this->session['challengecookie'];
+                        $this->session['challengecookie'] = md5($this->session['challengekey'].microtime());
+                        setcookie('authchallenge', $this->session['challengecookie'], 0, '/');
+                    }
+
+                    // Check for ip change
+                    if (   $this->_isAdvancedSecurityEnabled(AUTH_ADV_IPCHECK)
+                        && isset($this->server['REMOTE_ADDR'])
+                        && $this->session['sessionip'] != $this->server['REMOTE_ADDR']) {
+                        $this->log('Security Breach. Remote IP Address changed.', AUTH_LOG_INFO);
+                        // Check if the IP of the user has changed, if so we
+                        // assume a man in the middle attack and log him out
+                        $this->expired = true;
+                        $this->status = AUTH_SECURITY_BREACH;
+                        $this->logout();
+                        return false;
+                    }
+
+                    // Check for ip change (if connected via proxy)
+                    if (   $this->_isAdvancedSecurityEnabled(AUTH_ADV_IPCHECK)
+                        && isset($this->server['HTTP_X_FORWARDED_FOR'])
+                        && $this->session['sessionforwardedfor'] != $this->server['HTTP_X_FORWARDED_FOR']) {
+                        $this->log('Security Breach. Forwarded For IP Address changed.', AUTH_LOG_INFO);
+                        // Check if the IP of the user connecting via proxy has
+                        // changed, if so we assume a man in the middle attack
+                        // and log him out.
+                        $this->expired = true;
+                        $this->status = AUTH_SECURITY_BREACH;
+                        $this->logout();
+                        return false;
+                    }
+
+                    // Check for useragent change
+                    if (   $this->_isAdvancedSecurityEnabled(AUTH_ADV_USERAGENT)
+                        && isset($this->server['HTTP_USER_AGENT'])
+                        && $this->session['sessionuseragent'] != $this->server['HTTP_USER_AGENT']) {
+                        $this->log('Security Breach. User Agent changed.', AUTH_LOG_INFO);
+                        // Check if the User-Agent of the user has changed, if
+                        // so we assume a man in the middle attack and log him out
+                        $this->expired = true;
+                        $this->status = AUTH_SECURITY_BREACH;
+                        $this->logout();
+                        return false;
+                    }
+
+                    // Check challenge cookie here, if challengecookieold is not set
+                    // this is the first time and check is skipped
+                    // TODO when user open two pages similtaneuly (open in new window,open
+                    // in tab) auth breach is caused find out a way around that if possible
+                    if (   $this->_isAdvancedSecurityEnabled(AUTH_ADV_CHALLENGE)
+                        && isset($this->session['challengecookieold'])
+                        && $this->session['challengecookieold'] != $this->cookie['authchallenge']) {
+                        $this->log('Security Breach. Challenge Cookie mismatch.', AUTH_LOG_INFO);
+                        $this->expired = true;
+                        $this->status = AUTH_SECURITY_BREACH;
+                        $this->logout();
+                        $this->login();
+                        return false;
+                    }
+                }
+
+                if (is_callable($this->checkAuthCallback)) {
+                    $this->log('Calling checkAuthCallback ('.$this->checkAuthCallback.').', AUTH_LOG_DEBUG);
+                    $checkCallback = call_user_func_array($this->checkAuthCallback, array($this->username, &$this));
+                    if ($checkCallback == false) {
+                        $this->log('checkAuthCallback failed.', AUTH_LOG_INFO);
+                        $this->expired = true;
+                        $this->status = AUTH_CALLBACK_ABORT;
+                        $this->logout();
+                        return false;
+                    }
+                }
+
+                $this->log('Session OK.', AUTH_LOG_INFO);
+                return true;
+            }
+        } else {
+            $this->log('Unable to locate session storage.', AUTH_LOG_DEBUG);
+            return false;
+        }
+        $this->log('No login session.', AUTH_LOG_DEBUG);
+        return false;
+    }
+
+    // }}}
+    // {{{ staticCheckAuth() [static]
+
+    /**
+     * Statically checks if there is a session with valid auth information.
+     *
+     * @access public
+     * @see checkAuth
+     * @return boolean  Whether or not the user is authenticated.
+     * @static
+     */
+    function staticCheckAuth($options = null)
+    {
+        static $staticAuth;
+        if(!isset($staticAuth)) {
+            $staticAuth = new Auth('null', $options);
+        }
+        $staticAuth->log('Auth::staticCheckAuth() called', AUTH_LOG_DEBUG);
+        return $staticAuth->checkAuth();
+    }
+
+    // }}}
+    // {{{ getAuth()
+
+    /**
+     * Has the user been authenticated?
+     *
+     * Is there a valid login session. Previously this was different from
+     * checkAuth() but now it is just an alias.
+     *
+     * @access public
+     * @return bool  True if the user is logged in, otherwise false.
+     */
+    function getAuth()
+    {
+        $this->log('Auth::getAuth() called.', AUTH_LOG_DEBUG);
+        return $this->checkAuth();
+    }
+
+    // }}}
+    // {{{ logout()
+
+    /**
+     * Logout function
+     *
+     * This function clears any auth tokens in the currently
+     * active session and executes the logout callback function,
+     * if any
+     *
+     * @access public
+     * @return void
+     */
+    function logout()
+    {
+        $this->log('Auth::logout() called.', AUTH_LOG_DEBUG);
+
+        if (is_callable($this->logoutCallback) && isset($this->session['username'])) {
+            $this->log('Calling logoutCallback ('.$this->logoutCallback.').', AUTH_LOG_DEBUG);
+            call_user_func_array($this->logoutCallback, array($this->session['username'], &$this));
+        }
+
+        $this->username = '';
+        $this->password = '';
+
+        $this->session = null;
+    }
+
+    // }}}
+    // {{{ updateIdle()
+
+    /**
+     * Update the idletime
+     *
+     * @access private
+     * @return void
+     */
+    function updateIdle()
+    {
+        $this->session['idle'] = time();
+    }
+
+    // }}}
+    // {{{ getUsername()
+
+    /**
+     * Get the username
+     *
+     * @return string
+     * @access public
+     */
+    function getUsername()
+    {
+        if (isset($this->session['username'])) {
+            return($this->session['username']);
+        }
+        return('');
+    }
+
+    // }}}
+    // {{{ getStatus()
+
+    /**
+     * Get the current status
+     *
+     * @return string
+     * @access public
+     */
+    function getStatus()
+    {
+        return $this->status;
+    }
+
+    // }}}
+    // {{{ getPostUsernameField()
+
+    /**
+     * Gets the post varible used for the username
+     *
+     * @return string
+     * @access public
+     */
+    function getPostUsernameField()
+    {
+        return($this->_postUsername);
+    }
+
+    // }}}
+    // {{{ getPostPasswordField()
+
+    /**
+     * Gets the post varible used for the username
+     *
+     * @return string
+     * @access public
+     */
+    function getPostPasswordField()
+    {
+        return($this->_postPassword);
+    }
+
+    // }}}
+    // {{{ sessionValidThru()
+
+    /**
+     * Returns the time up to the session is valid
+     *
+     * @access public
+     * @return integer
+     */
+    function sessionValidThru()
+    {
+        if (!isset($this->session['idle'])) {
+            return 0;
+        }
+        if ($this->idle == 0) {
+            return 0;
+        }
+        return ($this->session['idle'] + $this->idle);
+    }
+
+    // }}}
+    // {{{ listUsers()
+
+    /**
+     * List all users that are currently available in the storage
+     * container
+     *
+     * @access public
+     * @return array
+     */
+    function listUsers()
+    {
+        $this->log('Auth::listUsers() called.', AUTH_LOG_DEBUG);
+        $this->_loadStorage();
+        return $this->storage->listUsers();
+    }
+
+    // }}}
+    // {{{ addUser()
+
+    /**
+     * Add user to the storage container
+     *
+     * @access public
+     * @param  string Username
+     * @param  string Password
+     * @param  mixed  Additional parameters
+     * @return mixed  True on success, PEAR error object on error
+     *                and AUTH_METHOD_NOT_SUPPORTED otherwise.
+     */
+    function addUser($username, $password, $additional = '')
+    {
+        $this->log('Auth::addUser() called.', AUTH_LOG_DEBUG);
+        $this->_loadStorage();
+        return $this->storage->addUser($username, $password, $additional);
+    }
+
+    // }}}
+    // {{{ removeUser()
+
+    /**
+     * Remove user from the storage container
+     *
+     * @access public
+     * @param  string Username
+     * @return mixed  True on success, PEAR error object on error
+     *                and AUTH_METHOD_NOT_SUPPORTED otherwise.
+     */
+    function removeUser($username)
+    {
+        $this->log('Auth::removeUser() called.', AUTH_LOG_DEBUG);
+        $this->_loadStorage();
+        return $this->storage->removeUser($username);
+    }
+
+    // }}}
+    // {{{ changePassword()
+
+    /**
+     * Change password for user in the storage container
+     *
+     * @access public
+     * @param string Username
+     * @param string The new password
+     * @return mixed True on success, PEAR error object on error
+     *               and AUTH_METHOD_NOT_SUPPORTED otherwise.
+     */
+    function changePassword($username, $password)
+    {
+        $this->log('Auth::changePassword() called', AUTH_LOG_DEBUG);
+        $this->_loadStorage();
+        return $this->storage->changePassword($username, $password);
+    }
+
+    // }}}
+    // {{{ log()
+
+    /**
+     * Log a message from the Auth system
+     *
+     * @access public
+     * @param string The message to log
+     * @param string The log level to log the message under. See the Log documentation for more info.
+     * @return boolean
+     */
+    function log($message, $level = AUTH_LOG_DEBUG)
+    {
+        if (!$this->enableLogging) return false;
+
+        $this->_loadLogger();
+
+        $this->logger->log('AUTH: '.$message, $level);
+    }
+
+    // }}}
+    // {{{ _loadLogger()
+
+    /**
+      * Load Log object if not already loaded
+      *
+      * Suspend logger instantiation to make Auth lighter to use
+      * for calls which do not require logging
+      *
+      * @return bool    True if the logger is loaded, false if the logger
+      *                 is already loaded
+      * @access private
+      */
+    function _loadLogger()
+    {
+        if(is_null($this->logger)) {
+            if (!class_exists('Log')) {
+                include_once 'Log.php';
+            }
+            $this->logger =& Log::singleton('null',
+                    null,
+                    'auth['.getmypid().']',
+                    array(),
+                    AUTH_LOG_DEBUG);
+            return(true);
+        }
+        return(false);
+    }
+
+    // }}}
+    // {{{ attachLogObserver()
+
+    /**
+     * Attach an Observer to the Auth Log Source
+     *
+     * @param object Log_Observer A Log Observer instance
+     * @return boolean
+     */
+    function attachLogObserver(&$observer) {
+
+        $this->_loadLogger();
+
+        return $this->logger->attach($observer);
+
+    }
+
+    // }}}
+    // {{{ _isAdvancedSecurityEnabled()
+
+    /**
+     * Is advanced security enabled?
+     *
+     * Pass one of the Advanced Security constants as the first parameter
+     * to check if that advanced security check is enabled.
+     *
+     * @param integer
+     * @return boolean
+     */
+    function _isAdvancedSecurityEnabled($feature = null) {
+
+        if (is_null($feature)) {
+
+            if ($this->advancedsecurity === true)
+                return true;
+
+            if (   is_array($this->advancedsecurity)
+                && in_array(true, $this->advancedsecurity, true))
+                return true;
+
+            return false;
+
+        } else {
+
+            if (is_array($this->advancedsecurity)) {
+
+                if (   isset($this->advancedsecurity[$feature])
+                    && $this->advancedsecurity[$feature] == true)
+                    return true;
+
+                return false;
+
+            }
+
+            return (bool)$this->advancedsecurity;
+
+        }
+
+    }
+
+    // }}}
+
+}
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/Array.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/Array.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/Array.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,161 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
+
+/**
+ * Storage driver for use against a PHP Array
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.01 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license at php.net so we can mail you a copy immediately.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     georg_1 at have2 dot com
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    CVS: $Id: Array.php 237449 2007-06-12 03:11:27Z aashley $
+ * @since      File available since Release 1.4.0
+ */
+
+/**
+ * Include Auth_Container base class
+ */
+require_once "Auth/Container.php";
+/**
+ * Include PEAR package for error handling
+ */
+require_once "PEAR.php";
+
+/**
+ * Storage driver for fetching authentication data from a PHP Array
+ *
+ * This container takes two options when configuring:
+ *
+ * cryptType:   The crypt used to store the password. Currently recognised
+ *              are: none, md5 and crypt. default: none
+ * users:       A named array of usernames and passwords.
+ *              Ex:
+ *              array(
+ *                  'guest' => '084e0343a0486ff05530df6c705c8bb4', // password guest
+ *                  'georg' => 'fc77dba827fcc88e0243404572c51325'  // password georg
+ *              )
+ *
+ * Usage Example:
+ * <?php
+ * $AuthOptions = array(
+ *      'users' => array(
+ *          'guest' => '084e0343a0486ff05530df6c705c8bb4', // password guest
+ *          'georg' => 'fc77dba827fcc88e0243404572c51325'  // password georg
+ *      ),
+ *      'cryptType'=>'md5',
+ *  );
+ *
+ * $auth = new Auth("Array", $AuthOptions);
+ * ?>
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     georg_1 at have2 dot com
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    Release: 1.6.2  File: $Revision: 237449 $
+ * @since      File available since Release 1.4.0
+ */
+
+class Auth_Container_Array extends Auth_Container {
+
+    // {{{ properties
+
+    /**
+     * The users and their password to authenticate against
+     *
+     * @var array $users
+     */
+    var $users;
+
+    /**
+     * The cryptType used on the passwords
+     *
+     * @var string $cryptType
+     */
+    var $cryptType = 'none';
+
+    // }}}
+    // {{{ Auth_Container_Array()
+
+    /**
+     * Constructor for Array Container
+     *
+     * @param array $data Options for the container
+     * @return void
+     */
+    function Auth_Container_Array($data)
+    {
+        if (!is_array($data)) {
+            PEAR::raiseError('The options for Auth_Container_Array must be an array');
+        }
+        if (isset($data['users']) && is_array($data['users'])) {
+            $this->users = $data['users'];
+        } else {
+            $this->users = array();
+            PEAR::raiseError('Auth_Container_Array: no user data found in options array');
+        }
+        if (isset($data['cryptType'])) {
+            $this->cryptType = $data['cryptType'];
+        }
+    }
+
+    // }}}
+    // {{{ fetchData()
+
+    /**
+     * Get user information from array
+     *
+     * This function uses the given username to fetch the corresponding
+     * login data from the array. If an account that matches the passed
+     * username and password is found, the function returns true.
+     * Otherwise it returns false.
+     *
+     * @param  string Username
+     * @param  string Password
+     * @return boolean|PEAR_Error Error object or boolean
+     */
+    function fetchData($user, $pass)
+    {
+        $this->log('Auth_Container_Array::fetchData() called.', AUTH_LOG_DEBUG);
+        if (   isset($this->users[$user])
+            && $this->verifyPassword($pass, $this->users[$user], $this->cryptType)) {
+            return true;
+        }
+        return false;
+    }
+
+    // }}}
+    // {{{ listUsers()
+
+    /**
+     * Returns a list of users available within the container
+     *
+     * @return array
+     */
+    function listUsers()
+    {
+        $this->log('Auth_Container_Array::listUsers() called.', AUTH_LOG_DEBUG);
+        $ret = array();
+        foreach ($this->users as $username => $password) {
+            $ret[]['username'] = $username;
+        }
+        return $ret;
+    }
+
+    // }}}
+
+}
+
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/DB.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/DB.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/DB.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,639 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
+
+/**
+ * Storage driver for use against PEAR DB
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.01 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license at php.net so we can mail you a copy immediately.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Martin Jansen <mj at php.net>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    CVS: $Id: DB.php 256753 2008-04-04 07:57:02Z aashley $
+ * @link       http://pear.php.net/package/Auth
+ */
+
+/**
+ * Include Auth_Container base class
+ */
+require_once 'Auth/Container.php';
+/**
+ * Include PEAR DB
+ */
+require_once 'DB.php';
+
+/**
+ * Storage driver for fetching login data from a database
+ *
+ * This storage driver can use all databases which are supported
+ * by the PEAR DB abstraction layer to fetch login data.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Martin Jansen <mj at php.net>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    Release: 1.6.2  File: $Revision: 256753 $
+ * @link       http://pear.php.net/package/Auth
+ */
+class Auth_Container_DB extends Auth_Container
+{
+
+    // {{{ properties
+
+    /**
+     * Additional options for the storage container
+     * @var array
+     */
+    var $options = array();
+
+    /**
+     * DB object
+     * @var object
+     */
+    var $db = null;
+    var $dsn = '';
+
+    /**
+     * User that is currently selected from the DB.
+     * @var string
+     */
+    var $activeUser = '';
+
+    // }}}
+    // {{{ Auth_Container_DB [constructor]
+
+    /**
+     * Constructor of the container class
+     *
+     * Save the initial options passed to the container. Initiation of the DB
+     * connection is no longer performed here and is only done when needed.
+     *
+     * @param  string Connection data or DB object
+     * @return object Returns an error object if something went wrong
+     */
+    function Auth_Container_DB($dsn)
+    {
+        $this->_setDefaults();
+
+        if (is_array($dsn)) {
+            $this->_parseOptions($dsn);
+
+            if (empty($this->options['dsn'])) {
+                PEAR::raiseError('No connection parameters specified!');
+            }
+        } else {
+            $this->options['dsn'] = $dsn;
+        }
+    }
+
+    // }}}
+    // {{{ _connect()
+
+    /**
+     * Connect to database by using the given DSN string
+     *
+     * @access private
+     * @param  string DSN string
+     * @return mixed  Object on error, otherwise bool
+     */
+    function _connect($dsn)
+    {
+        $this->log('Auth_Container_DB::_connect() called.', AUTH_LOG_DEBUG);
+
+        if (is_string($dsn) || is_array($dsn)) {
+            $this->db = DB::Connect($dsn, $this->options['db_options']);
+        } elseif (is_subclass_of($dsn, 'db_common')) {
+            $this->db = $dsn;
+        } elseif (DB::isError($dsn)) {
+            return PEAR::raiseError($dsn->getMessage(), $dsn->getCode());
+        } else {
+            return PEAR::raiseError('The given dsn was not valid in file ' . __FILE__ . ' at line ' . __LINE__,
+                                    41,
+                                    PEAR_ERROR_RETURN,
+                                    null,
+                                    null
+                                    );
+        }
+
+        if (DB::isError($this->db) || PEAR::isError($this->db)) {
+            return PEAR::raiseError($this->db->getMessage(), $this->db->getCode());
+        } else {
+            return true;
+        }
+    }
+
+    // }}}
+    // {{{ _prepare()
+
+    /**
+     * Prepare database connection
+     *
+     * This function checks if we have already opened a connection to
+     * the database. If that's not the case, a new connection is opened.
+     *
+     * @access private
+     * @return mixed True or a DB error object.
+     */
+    function _prepare()
+    {
+        if (!DB::isConnection($this->db)) {
+            $res = $this->_connect($this->options['dsn']);
+            if (DB::isError($res) || PEAR::isError($res)) {
+                return $res;
+            }
+        }
+        if ($this->options['auto_quote'] && $this->db->dsn['phptype'] != 'sqlite') {
+            if (strpos('.', $this->options['table']) === false) {
+                $this->options['final_table'] = $this->db->quoteIdentifier($this->options['table']);
+            } else {
+                $t = explode('.', $this->options['table']);
+                for ($i = 0, $count = count($t); $i < $count; $i++)
+                    $t[$i] = $this->db->quoteIdentifier($t[$i]);
+                $this->options['final_table'] = implode('.', $t);
+            }
+            $this->options['final_usernamecol'] = $this->db->quoteIdentifier($this->options['usernamecol']);
+            $this->options['final_passwordcol'] = $this->db->quoteIdentifier($this->options['passwordcol']);
+        } else {
+            $this->options['final_table'] = $this->options['table'];
+            $this->options['final_usernamecol'] = $this->options['usernamecol'];
+            $this->options['final_passwordcol'] = $this->options['passwordcol'];
+        }
+        return true;
+    }
+
+    // }}}
+    // {{{ query()
+
+    /**
+     * Prepare query to the database
+     *
+     * This function checks if we have already opened a connection to
+     * the database. If that's not the case, a new connection is opened.
+     * After that the query is passed to the database.
+     *
+     * @access public
+     * @param  string Query string
+     * @return mixed  a DB_result object or DB_OK on success, a DB
+     *                or PEAR error on failure
+     */
+    function query($query)
+    {
+        $err = $this->_prepare();
+        if ($err !== true) {
+            return $err;
+        }
+        return $this->db->query($query);
+    }
+
+    // }}}
+    // {{{ _setDefaults()
+
+    /**
+     * Set some default options
+     *
+     * @access private
+     * @return void
+     */
+    function _setDefaults()
+    {
+        $this->options['table']       = 'auth';
+        $this->options['usernamecol'] = 'username';
+        $this->options['passwordcol'] = 'password';
+        $this->options['dsn']         = '';
+        $this->options['db_fields']   = '';
+        $this->options['cryptType']   = 'md5';
+        $this->options['db_options']  = array();
+        $this->options['db_where']    = '';
+        $this->options['auto_quote']  = true;
+    }
+
+    // }}}
+    // {{{ _parseOptions()
+
+    /**
+     * Parse options passed to the container class
+     *
+     * @access private
+     * @param  array
+     */
+    function _parseOptions($array)
+    {
+        foreach ($array as $key => $value) {
+            if (isset($this->options[$key])) {
+                $this->options[$key] = $value;
+            }
+        }
+    }
+
+    // }}}
+    // {{{ _quoteDBFields()
+
+    /**
+     * Quote the db_fields option to avoid the possibility of SQL injection.
+     *
+     * @access private
+     * @return string A properly quoted string that can be concatenated into a
+     * SELECT clause.
+     */
+    function _quoteDBFields()
+    {
+        if (isset($this->options['db_fields'])) {
+            if (is_array($this->options['db_fields'])) {
+                if ($this->options['auto_quote']) {
+                    $fields = array();
+                    foreach ($this->options['db_fields'] as $field) {
+                        $fields[] = $this->db->quoteIdentifier($field);
+                    }
+                    return implode(', ', $fields);
+                } else {
+                    return implode(', ', $this->options['db_fields']);
+                }
+            } else {
+                if (strlen($this->options['db_fields']) > 0) {
+                    if ($this->options['auto_quote']) {
+                        return $this->db->quoteIdentifier($this->options['db_fields']);
+                    } else {
+                        return $this->options['db_fields'];
+                    }
+                }
+            }
+        }
+
+        return '';
+    }
+
+    // }}}
+    // {{{ fetchData()
+
+    /**
+     * Get user information from database
+     *
+     * This function uses the given username to fetch
+     * the corresponding login data from the database
+     * table. If an account that matches the passed username
+     * and password is found, the function returns true.
+     * Otherwise it returns false.
+     *
+     * @param   string Username
+     * @param   string Password
+     * @param   boolean If true password is secured using a md5 hash
+     *                  the frontend and auth are responsible for making sure the container supports
+     *                  challenge response password authentication
+     * @return  mixed  Error object or boolean
+     */
+    function fetchData($username, $password, $isChallengeResponse=false)
+    {
+        $this->log('Auth_Container_DB::fetchData() called.', AUTH_LOG_DEBUG);
+        // Prepare for a database query
+        $err = $this->_prepare();
+        if ($err !== true) {
+            return PEAR::raiseError($err->getMessage(), $err->getCode());
+        }
+
+        // Find if db_fields contains a *, if so assume all columns are selected
+        if (is_string($this->options['db_fields'])
+            && strstr($this->options['db_fields'], '*')) {
+            $sql_from = "*";
+        } else {
+            $sql_from = $this->options['final_usernamecol'].
+                ", ".$this->options['final_passwordcol'];
+
+            if (strlen($fields = $this->_quoteDBFields()) > 0) {
+                $sql_from .= ', '.$fields;
+            }
+        }
+
+        $query = "SELECT ".$sql_from.
+                " FROM ".$this->options['final_table'].
+                " WHERE ".$this->options['final_usernamecol']." = ".$this->db->quoteSmart($username);
+
+        // check if there is an optional parameter db_where
+        if ($this->options['db_where'] != '') {
+            // there is one, so add it to the query
+            $query .= " AND ".$this->options['db_where'];
+        }
+
+        $this->log('Running SQL against DB: '.$query, AUTH_LOG_DEBUG);
+
+        $res = $this->db->getRow($query, null, DB_FETCHMODE_ASSOC);
+
+        if (DB::isError($res)) {
+            return PEAR::raiseError($res->getMessage(), $res->getCode());
+        }
+
+        if (!is_array($res)) {
+            $this->activeUser = '';
+            return false;
+        }
+
+        // Perform trimming here before the hashihg
+        $password = trim($password, "\r\n");
+        $res[$this->options['passwordcol']] = trim($res[$this->options['passwordcol']], "\r\n");
+
+        // If using Challenge Response md5 the pass with the secret
+        if ($isChallengeResponse) {
+            $res[$this->options['passwordcol']] = md5($res[$this->options['passwordcol']]
+                    .$this->_auth_obj->session['loginchallenege']);
+
+            // UGLY cannot avoid without modifying verifyPassword
+            if ($this->options['cryptType'] == 'md5') {
+                $res[$this->options['passwordcol']] = md5($res[$this->options['passwordcol']]);
+            }
+
+            //print " Hashed Password [{$res[$this->options['passwordcol']]}]<br/>\n";
+        }
+
+        if ($this->verifyPassword($password,
+                                  $res[$this->options['passwordcol']],
+                                  $this->options['cryptType'])) {
+            // Store additional field values in the session
+            foreach ($res as $key => $value) {
+                if ($key == $this->options['passwordcol'] ||
+                    $key == $this->options['usernamecol']) {
+                    continue;
+                }
+
+                $this->log('Storing additional field: '.$key, AUTH_LOG_DEBUG);
+
+                // Use reference to the auth object if exists
+                // This is because the auth session variable can change so a
+                // static call to setAuthData does not make sence
+                $this->_auth_obj->setAuthData($key, $value);
+            }
+            return true;
+        }
+        $this->activeUser = $res[$this->options['usernamecol']];
+        return false;
+    }
+
+    // }}}
+    // {{{ listUsers()
+
+    /**
+     * Returns a list of users from the container
+     *
+     * @return mixed
+     * @access public
+     */
+    function listUsers()
+    {
+        $this->log('Auth_Container_DB::listUsers() called.', AUTH_LOG_DEBUG);
+        $err = $this->_prepare();
+        if ($err !== true) {
+            return PEAR::raiseError($err->getMessage(), $err->getCode());
+        }
+
+        $retVal = array();
+
+        // Find if db_fields contains a *, if so assume all col are selected
+        if (   is_string($this->options['db_fields'])
+            && strstr($this->options['db_fields'], '*')) {
+            $sql_from = "*";
+        } else {
+            $sql_from = $this->options['final_usernamecol'].
+                ", ".$this->options['final_passwordcol'];
+
+            if (strlen($fields = $this->_quoteDBFields()) > 0) {
+                $sql_from .= ', '.$fields;
+            }
+        }
+
+        $query = sprintf("SELECT %s FROM %s",
+                         $sql_from,
+                         $this->options['final_table']
+                         );
+
+        // check if there is an optional parameter db_where
+        if ($this->options['db_where'] != '') {
+            // there is one, so add it to the query
+            $query .= " WHERE ".$this->options['db_where'];
+        }
+
+        $this->log('Running SQL against DB: '.$query, AUTH_LOG_DEBUG);
+
+        $res = $this->db->getAll($query, null, DB_FETCHMODE_ASSOC);
+
+        if (DB::isError($res)) {
+            return PEAR::raiseError($res->getMessage(), $res->getCode());
+        } else {
+            foreach ($res as $user) {
+                $user['username'] = $user[$this->options['usernamecol']];
+                $retVal[] = $user;
+            }
+        }
+        $this->log('Found '.count($retVal).' users.', AUTH_LOG_DEBUG);
+        return $retVal;
+    }
+
+    // }}}
+    // {{{ addUser()
+
+    /**
+     * Add user to the storage container
+     *
+     * @access public
+     * @param  string Username
+     * @param  string Password
+     * @param  mixed  Additional information that are stored in the DB
+     *
+     * @return mixed True on success, otherwise error object
+     */
+    function addUser($username, $password, $additional = "")
+    {
+        $this->log('Auth_Container_DB::addUser() called.', AUTH_LOG_DEBUG);
+        $err = $this->_prepare();
+        if ($err !== true) {
+            return PEAR::raiseError($err->getMessage(), $err->getCode());
+        }
+
+        if (   isset($this->options['cryptType'])
+            && $this->options['cryptType'] == 'none') {
+            $cryptFunction = 'strval';
+        } elseif (   isset($this->options['cryptType'])
+                  && function_exists($this->options['cryptType'])) {
+            $cryptFunction = $this->options['cryptType'];
+        } else {
+            $cryptFunction = 'md5';
+        }
+
+        $password = $cryptFunction($password);
+
+        $additional_key   = '';
+        $additional_value = '';
+
+        if (is_array($additional)) {
+            foreach ($additional as $key => $value) {
+                if ($this->options['auto_quote']) {
+                    $additional_key .= ', ' . $this->db->quoteIdentifier($key);
+                } else {
+                    $additional_key .= ', ' . $key;
+                }
+                $additional_value .= ", " . $this->db->quoteSmart($value);
+            }
+        }
+
+        $query = sprintf("INSERT INTO %s (%s, %s%s) VALUES (%s, %s%s)",
+                         $this->options['final_table'],
+                         $this->options['final_usernamecol'],
+                         $this->options['final_passwordcol'],
+                         $additional_key,
+                         $this->db->quoteSmart($username),
+                         $this->db->quoteSmart($password),
+                         $additional_value
+                         );
+
+        $this->log('Running SQL against DB: '.$query, AUTH_LOG_DEBUG);
+
+        $res = $this->query($query);
+
+        if (DB::isError($res)) {
+            return PEAR::raiseError($res->getMessage(), $res->getCode());
+        } else {
+            return true;
+        }
+    }
+
+    // }}}
+    // {{{ removeUser()
+
+    /**
+     * Remove user from the storage container
+     *
+     * @access public
+     * @param  string Username
+     *
+     * @return mixed True on success, otherwise error object
+     */
+    function removeUser($username)
+    {
+        $this->log('Auth_Container_DB::removeUser() called.', AUTH_LOG_DEBUG);
+
+        $err = $this->_prepare();
+        if ($err !== true) {
+            return PEAR::raiseError($err->getMessage(), $err->getCode());
+        }
+
+        // check if there is an optional parameter db_where
+        if ($this->options['db_where'] != '') {
+            // there is one, so add it to the query
+            $where = " AND ".$this->options['db_where'];
+        } else {
+            $where = '';
+        }
+
+        $query = sprintf("DELETE FROM %s WHERE %s = %s %s",
+                         $this->options['final_table'],
+                         $this->options['final_usernamecol'],
+                         $this->db->quoteSmart($username),
+                         $where
+                         );
+
+        $this->log('Running SQL against DB: '.$query, AUTH_LOG_DEBUG);
+
+        $res = $this->query($query);
+
+        if (DB::isError($res)) {
+           return PEAR::raiseError($res->getMessage(), $res->getCode());
+        } else {
+          return true;
+        }
+    }
+
+    // }}}
+    // {{{ changePassword()
+
+    /**
+     * Change password for user in the storage container
+     *
+     * @param string Username
+     * @param string The new password (plain text)
+     */
+    function changePassword($username, $password)
+    {
+        $this->log('Auth_Container_DB::changePassword() called.', AUTH_LOG_DEBUG);
+        $err = $this->_prepare();
+        if ($err !== true) {
+            return PEAR::raiseError($err->getMessage(), $err->getCode());
+        }
+
+        if (   isset($this->options['cryptType'])
+            && $this->options['cryptType'] == 'none') {
+            $cryptFunction = 'strval';
+        } elseif (   isset($this->options['cryptType'])
+                  && function_exists($this->options['cryptType'])) {
+            $cryptFunction = $this->options['cryptType'];
+        } else {
+            $cryptFunction = 'md5';
+        }
+
+        $password = $cryptFunction($password);
+
+        // check if there is an optional parameter db_where
+        if ($this->options['db_where'] != '') {
+            // there is one, so add it to the query
+            $where = " AND ".$this->options['db_where'];
+        } else {
+            $where = '';
+        }
+
+        $query = sprintf("UPDATE %s SET %s = %s WHERE %s = %s %s",
+                         $this->options['final_table'],
+                         $this->options['final_passwordcol'],
+                         $this->db->quoteSmart($password),
+                         $this->options['final_usernamecol'],
+                         $this->db->quoteSmart($username),
+                         $where
+                         );
+
+        $this->log('Running SQL against DB: '.$query, AUTH_LOG_DEBUG);
+
+        $res = $this->query($query);
+
+        if (DB::isError($res)) {
+            return PEAR::raiseError($res->getMessage(), $res->getCode());
+        } else {
+            return true;
+        }
+    }
+
+    // }}}
+    // {{{ supportsChallengeResponse()
+
+    /**
+     * Determine if this container supports
+     * password authentication with challenge response
+     *
+     * @return bool
+     * @access public
+     */
+    function supportsChallengeResponse()
+    {
+        return in_array($this->options['cryptType'], array('md5', 'none', ''));
+    }
+
+    // }}}
+    // {{{ getCryptType()
+
+    /**
+      * Returns the selected crypt type for this container
+      */
+    function getCryptType()
+    {
+        return($this->options['cryptType']);
+    }
+
+    // }}}
+
+}
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/DBLite.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/DBLite.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/DBLite.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,320 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
+
+/**
+ * Reduced storage driver for use against PEAR DB
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.01 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license at php.net so we can mail you a copy immediately.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Martin Jansen <mj at php.net>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    CVS: $Id: DBLite.php 256753 2008-04-04 07:57:02Z aashley $
+ * @link       http://pear.php.net/package/Auth
+ * @since      File available since Release 1.3.0
+ */
+
+/**
+ * Include Auth_Container base class
+ */
+require_once 'Auth/Container.php';
+/**
+ * Include PEAR DB package
+ */
+require_once 'DB.php';
+
+/**
+ * A lighter storage driver for fetching login data from a database
+ *
+ * This driver is derived from the DB storage container but
+ * with the user manipulation function removed for smaller file size
+ * by the PEAR DB abstraction layer to fetch login data.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Martin Jansen <mj at php.net>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    Release: 1.6.2  File: $Revision: 256753 $
+ * @link       http://pear.php.net/package/Auth
+ * @since      Class available since Release 1.3.0
+ */
+class Auth_Container_DBLite extends Auth_Container
+{
+
+    // {{{ properties
+
+    /**
+     * Additional options for the storage container
+     * @var array
+     */
+    var $options = array();
+
+    /**
+     * DB object
+     * @var object
+     */
+    var $db = null;
+    var $dsn = '';
+
+    /**
+     * User that is currently selected from the DB.
+     * @var string
+     */
+    var $activeUser = '';
+
+    // }}}
+    // {{{ Auth_Container_DBLite() [constructor]
+
+    /**
+     * Constructor of the container class
+     *
+     * Initate connection to the database via PEAR::DB
+     *
+     * @param  string Connection data or DB object
+     * @return object Returns an error object if something went wrong
+     */
+    function Auth_Container_DBLite($dsn)
+    {
+        $this->options['table']       = 'auth';
+        $this->options['usernamecol'] = 'username';
+        $this->options['passwordcol'] = 'password';
+        $this->options['dsn']         = '';
+        $this->options['db_fields']   = '';
+        $this->options['cryptType']   = 'md5';
+        $this->options['db_options']  = array();
+        $this->options['db_where']    = '';
+        $this->options['auto_quote']  = true;
+
+        if (is_array($dsn)) {
+            $this->_parseOptions($dsn);
+            if (empty($this->options['dsn'])) {
+                PEAR::raiseError('No connection parameters specified!');
+            }
+        } else {
+            $this->options['dsn'] = $dsn;
+        }
+    }
+
+    // }}}
+    // {{{ _connect()
+
+    /**
+     * Connect to database by using the given DSN string
+     *
+     * @access private
+     * @param  string DSN string
+     * @return mixed  Object on error, otherwise bool
+     */
+    function _connect(&$dsn)
+    {
+        $this->log('Auth_Container_DBLite::_connect() called.', AUTH_LOG_DEBUG);
+        if (is_string($dsn) || is_array($dsn)) {
+            $this->db =& DB::connect($dsn, $this->options['db_options']);
+        } elseif (is_subclass_of($dsn, "db_common")) {
+            $this->db =& $dsn;
+        } else {
+            return PEAR::raiseError("Invalid dsn or db object given");
+        }
+
+        if (DB::isError($this->db) || PEAR::isError($this->db)) {
+            return PEAR::raiseError($this->db->getMessage(), $this->db->getCode());
+        } else {
+            return true;
+        }
+    }
+
+    // }}}
+    // {{{ _prepare()
+
+    /**
+     * Prepare database connection
+     *
+     * This function checks if we have already opened a connection to
+     * the database. If that's not the case, a new connection is opened.
+     *
+     * @access private
+     * @return mixed True or a DB error object.
+     */
+    function _prepare()
+    {
+        if (!DB::isConnection($this->db)) {
+            $res = $this->_connect($this->options['dsn']);
+            if (DB::isError($res) || PEAR::isError($res)) {
+                return $res;
+            }
+        }
+        if ($this->options['auto_quote'] && $this->db->dsn['phptype'] != 'sqlite') {
+            if (strpos('.', $this->options['table']) === false) {
+                $this->options['final_table'] = $this->db->quoteIdentifier($this->options['table']);
+            } else {
+                $t = explode('.', $this->options['table']);
+                for ($i = 0, $count = count($t); $i < $count; $i++)
+                    $t[$i] = $this->db->quoteIdentifier($t[$i]);
+                $this->options['final_table'] = implode('.', $t);
+            }
+            $this->options['final_usernamecol'] = $this->db->quoteIdentifier($this->options['usernamecol']);
+            $this->options['final_passwordcol'] = $this->db->quoteIdentifier($this->options['passwordcol']);
+        } else {
+            $this->options['final_table'] = $this->options['table'];
+            $this->options['final_usernamecol'] = $this->options['usernamecol'];
+            $this->options['final_passwordcol'] = $this->options['passwordcol'];
+        }
+        return true;
+    }
+
+    // }}}
+    // {{{ _parseOptions()
+
+    /**
+     * Parse options passed to the container class
+     *
+     * @access private
+     * @param  array
+     */
+    function _parseOptions($array)
+    {
+        foreach ($array as $key => $value) {
+            if (isset($this->options[$key])) {
+                $this->options[$key] = $value;
+            }
+        }
+    }
+
+    // }}}
+    // {{{ _quoteDBFields()
+
+    /**
+     * Quote the db_fields option to avoid the possibility of SQL injection.
+     *
+     * @access private
+     * @return string A properly quoted string that can be concatenated into a
+     * SELECT clause.
+     */
+    function _quoteDBFields()
+    {
+        if (isset($this->options['db_fields'])) {
+            if (is_array($this->options['db_fields'])) {
+                if ($this->options['auto_quote']) {
+                    $fields = array();
+                    foreach ($this->options['db_fields'] as $field) {
+                        $fields[] = $this->db->quoteIdentifier($field);
+                    }
+                    return implode(', ', $fields);
+                } else {
+                    return implode(', ', $this->options['db_fields']);
+                }
+            } else {
+                if (strlen($this->options['db_fields']) > 0) {
+                    if ($this->options['auto_quote']) {
+                        return $this->db->quoteIdentifier($this->options['db_fields']);
+                    } else {
+                        $this->options['db_fields'];
+                    }
+                }
+            }
+        }
+
+        return '';
+    }
+
+    // }}}
+    // {{{ fetchData()
+
+    /**
+     * Get user information from database
+     *
+     * This function uses the given username to fetch
+     * the corresponding login data from the database
+     * table. If an account that matches the passed username
+     * and password is found, the function returns true.
+     * Otherwise it returns false.
+     *
+     * @param   string Username
+     * @param   string Password
+     * @return  mixed  Error object or boolean
+     */
+    function fetchData($username, $password)
+    {
+        $this->log('Auth_Container_DBLite::fetchData() called.', AUTH_LOG_DEBUG);
+        // Prepare for a database query
+        $err = $this->_prepare();
+        if ($err !== true) {
+            return PEAR::raiseError($err->getMessage(), $err->getCode());
+        }
+
+        // Find if db_fields contains a *, if so assume all col are selected
+        if (is_string($this->options['db_fields'])
+            && strstr($this->options['db_fields'], '*')) {
+            $sql_from = "*";
+        } else {
+            $sql_from = $this->options['final_usernamecol'].
+                ", ".$this->options['final_passwordcol'];
+
+            if (strlen($fields = $this->_quoteDBFields()) > 0) {
+                $sql_from .= ', '.$fields;
+            }
+        }
+
+        $query = "SELECT ".$sql_from.
+                " FROM ".$this->options['final_table'].
+                " WHERE ".$this->options['final_usernamecol']." = ".$this->db->quoteSmart($username);
+
+        // check if there is an optional parameter db_where
+        if ($this->options['db_where'] != '') {
+            // there is one, so add it to the query
+            $query .= " AND ".$this->options['db_where'];
+        }
+
+        $this->log('Running SQL against DB: '.$query, AUTH_LOG_DEBUG);
+
+        $res = $this->db->getRow($query, null, DB_FETCHMODE_ASSOC);
+
+        if (DB::isError($res)) {
+            return PEAR::raiseError($res->getMessage(), $res->getCode());
+        }
+        if (!is_array($res)) {
+            $this->activeUser = '';
+            return false;
+        }
+        if ($this->verifyPassword(trim($password, "\r\n"),
+                                  trim($res[$this->options['passwordcol']], "\r\n"),
+                                  $this->options['cryptType'])) {
+            // Store additional field values in the session
+            foreach ($res as $key => $value) {
+                if ($key == $this->options['passwordcol'] ||
+                    $key == $this->options['usernamecol']) {
+                    continue;
+                }
+
+                $this->log('Storing additional field: '.$key, AUTH_LOG_DEBUG);
+
+                // Use reference to the auth object if exists
+                // This is because the auth session variable can change so a static call to setAuthData does not make sence
+                if (is_object($this->_auth_obj)) {
+                    $this->_auth_obj->setAuthData($key, $value);
+                } else {
+                    Auth::setAuthData($key, $value);
+                }
+            }
+            $this->activeUser = $res[$this->options['usernamecol']];
+            return true;
+        }
+        $this->activeUser = $res[$this->options['usernamecol']];
+        return false;
+    }
+
+    // }}}
+
+}
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/File.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/File.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/File.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,314 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
+
+/**
+ * Storage driver for use against a generic password file
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.01 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license at php.net so we can mail you a copy immediately.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Stefan Ekman <stekman at sedata.org>
+ * @author     Martin Jansen <mj at php.net>
+ * @author     Mika Tuupola <tuupola at appelsiini.net>
+ * @author     Michael Wallner <mike at php.net>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    CVS: $Id: File.php 237449 2007-06-12 03:11:27Z aashley $
+ * @link       http://pear.php.net/package/Auth
+ */
+
+/**
+ * Include PEAR File_Passwd package
+ */
+require_once "File/Passwd.php";
+/**
+ * Include Auth_Container base class
+ */
+require_once "Auth/Container.php";
+/**
+ * Include PEAR package for error handling
+ */
+require_once "PEAR.php";
+
+/**
+ * Storage driver for fetching login data from an encrypted password file.
+ *
+ * This storage container can handle CVS pserver style passwd files.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Stefan Ekman <stekman at sedata.org>
+ * @author     Martin Jansen <mj at php.net>
+ * @author     Mika Tuupola <tuupola at appelsiini.net>
+ * @author     Michael Wallner <mike at php.net>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    Release: 1.6.2  File: $Revision: 237449 $
+ * @link       http://pear.php.net/package/Auth
+ */
+class Auth_Container_File extends Auth_Container
+{
+
+    // {{{ properties
+
+    /**
+     * Path to passwd file
+     *
+     * @var string
+     */
+    var $pwfile = '';
+
+    /**
+     * Options for container
+     *
+     * @var array
+     */
+    var $options = array();
+
+    // }}}
+    // {{{ Auth_Container_File() [constructor]
+
+    /**
+     * Constructor of the container class
+     *
+     * @param  string $filename             path to passwd file
+     * @return object Auth_Container_File   new Auth_Container_File object
+     */
+    function Auth_Container_File($filename) {
+        $this->_setDefaults();
+
+        // Only file is a valid option here
+        if(is_array($filename)) {
+            $this->pwfile = $filename['file'];
+            $this->_parseOptions($filename);
+        } else {
+            $this->pwfile = $filename;
+        }
+    }
+
+    // }}}
+    // {{{ fetchData()
+
+    /**
+     * Authenticate an user
+     *
+     * @param   string  username
+     * @param   string  password
+     * @return  mixed   boolean|PEAR_Error
+     */
+    function fetchData($user, $pass)
+    {
+        $this->log('Auth_Container_File::fetchData() called.', AUTH_LOG_DEBUG);
+        return File_Passwd::staticAuth($this->options['type'], $this->pwfile, $user, $pass);
+    }
+
+    // }}}
+    // {{{ listUsers()
+
+    /**
+     * List all available users
+     *
+     * @return   array
+     */
+    function listUsers()
+    {
+        $this->log('Auth_Container_File::listUsers() called.', AUTH_LOG_DEBUG);
+
+        $pw_obj = &$this->_load();
+        if (PEAR::isError($pw_obj)) {
+            return array();
+        }
+
+        $users  = $pw_obj->listUser();
+        if (!is_array($users)) {
+            return array();
+        }
+
+        foreach ($users as $key => $value) {
+            $retVal[] = array("username" => $key,
+                              "password" => $value['passwd'],
+                              "cvsuser"  => $value['system']);
+        }
+
+        $this->log('Found '.count($retVal).' users.', AUTH_LOG_DEBUG);
+
+        return $retVal;
+    }
+
+    // }}}
+    // {{{ addUser()
+
+    /**
+     * Add a new user to the storage container
+     *
+     * @param string username
+     * @param string password
+     * @param mixed  Additional parameters to File_Password_*::addUser()
+     *
+     * @return boolean
+     */
+    function addUser($user, $pass, $additional='')
+    {
+        $this->log('Auth_Container_File::addUser() called.', AUTH_LOG_DEBUG);
+        $params = array($user, $pass);
+        if (is_array($additional)) {
+            foreach ($additional as $item) {
+                $params[] = $item;
+            }
+        } else {
+            $params[] = $additional;
+        }
+
+        $pw_obj = &$this->_load();
+        if (PEAR::isError($pw_obj)) {
+            return false;
+        }
+
+        $res = call_user_func_array(array(&$pw_obj, 'addUser'), $params);
+        if (PEAR::isError($res)) {
+            return false;
+        }
+
+        $res = $pw_obj->save();
+        if (PEAR::isError($res)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    // }}}
+    // {{{ removeUser()
+
+    /**
+     * Remove user from the storage container
+     *
+     * @param   string  Username
+     * @return  boolean
+     */
+    function removeUser($user)
+    {
+        $this->log('Auth_Container_File::removeUser() called.', AUTH_LOG_DEBUG);
+        $pw_obj = &$this->_load();
+        if (PEAR::isError($pw_obj)) {
+            return false;
+        }
+
+        $res = $pw_obj->delUser($user);
+        if (PEAR::isError($res)) {
+            return false;
+        }
+
+        $res = $pw_obj->save();
+        if (PEAR::isError($res)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    // }}}
+    // {{{ changePassword()
+
+    /**
+     * Change password for user in the storage container
+     *
+     * @param string Username
+     * @param string The new password
+     */
+    function changePassword($username, $password)
+    {
+        $this->log('Auth_Container_File::changePassword() called.', AUTH_LOG_DEBUG);
+        $pw_obj = &$this->_load();
+        if (PEAR::isError($pw_obj)) {
+            return false;
+        }
+
+        $res = $pw_obj->changePasswd($username, $password);
+        if (PEAR::isError($res)) {
+            return false;
+        }
+
+        $res = $pw_obj->save();
+        if (PEAR::isError($res)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    // }}}
+    // {{{ _load()
+
+    /**
+     * Load and initialize the File_Passwd object
+     *
+     * @return  object  File_Passwd_Cvs|PEAR_Error
+     */
+    function &_load()
+    {
+        static $pw_obj;
+
+        if (!isset($pw_obj)) {
+            $this->log('Instanciating File_Password object of type '.$this->options['type'], AUTH_LOG_DEBUG);
+            $pw_obj = File_Passwd::factory($this->options['type']);
+            if (PEAR::isError($pw_obj)) {
+                return $pw_obj;
+            }
+
+            $pw_obj->setFile($this->pwfile);
+
+            $res = $pw_obj->load();
+            if (PEAR::isError($res)) {
+                return $res;
+            }
+        }
+
+        return $pw_obj;
+    }
+
+    // }}}
+    // {{{ _setDefaults()
+
+    /**
+     * Set some default options
+     *
+     * @access private
+     * @return void
+     */
+    function _setDefaults()
+    {
+        $this->options['type']       = 'Cvs';
+    }
+
+    // }}}
+    // {{{ _parseOptions()
+
+    /**
+     * Parse options passed to the container class
+     *
+     * @access private
+     * @param  array
+     */
+    function _parseOptions($array)
+    {
+        foreach ($array as $key => $value) {
+            if (isset($this->options[$key])) {
+                $this->options[$key] = $value;
+            }
+        }
+    }
+
+    // }}}
+
+}
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/IMAP.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/IMAP.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/IMAP.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,210 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
+
+/**
+ * Storage driver for use against IMAP servers
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.01 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license at php.net so we can mail you a copy immediately.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Jeroen Houben <jeroen at terena.nl>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    CVS: $Id: IMAP.php 237449 2007-06-12 03:11:27Z aashley $
+ * @link       http://pear.php.net/package/Auth
+ * @since      File available since Release 1.2.0
+ */
+
+/**
+ * Include Auth_Container base class
+ */
+require_once "Auth/Container.php";
+
+/**
+ * Include PEAR class for error handling
+ */
+require_once "PEAR.php";
+
+/**
+ * Storage driver for fetching login data from an IMAP server
+ *
+ * This class is based on LDAP containers, but it very simple.
+ * By default it connects to localhost:143
+ * The constructor will first check if the host:port combination is
+ * actually reachable. This behaviour can be disabled.
+ * It then tries to create an IMAP stream (without opening a mailbox)
+ * If you wish to pass extended options to the connections, you may
+ * do so by specifying protocol options.
+ *
+ * To use this storage containers, you have to use the
+ * following syntax:
+ *
+ * <?php
+ * ...
+ * $params = array(
+ * 'host'       => 'mail.example.com',
+ * 'port'       => 143,
+ * );
+ * $myAuth = new Auth('IMAP', $params);
+ * ...
+ *
+ * By default we connect without any protocol options set. However, some
+ * servers require you to connect with the notls or norsh options set.
+ * To do this you need to add the following value to the params array:
+ * 'baseDSN'   => '/imap/notls/norsh'
+ *
+ * To connect to an SSL IMAP server:
+ * 'baseDSN'   => '/imap/ssl'
+ *
+ * To connect to an SSL IMAP server with a self-signed certificate:
+ * 'baseDSN'   => '/imap/ssl/novalidate-cert'
+ *
+ * Further options may be available and can be found on the php site at
+ * http://www.php.net/manual/function.imap-open.php
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Jeroen Houben <jeroen at terena.nl>
+ * @author     Cipriano Groenendal <cipri at campai.nl>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    Release: 1.6.2  File: $Revision: 237449 $
+ * @link       http://pear.php.net/package/Auth
+ * @since      Class available since Release 1.2.0
+ */
+class Auth_Container_IMAP extends Auth_Container
+{
+
+    // {{{ properties
+
+    /**
+     * Options for the class
+     * @var array
+     */
+    var $options = array();
+
+    // }}}
+    // {{{ Auth_Container_IMAP() [constructor]
+
+    /**
+     * Constructor of the container class
+     *
+     * @param  $params  associative array with host, port, baseDSN, checkServer
+     *                  and userattr key
+     * @return object Returns an error object if something went wrong
+     * @todo Use PEAR Net_IMAP if IMAP extension not loaded
+     */
+    function Auth_Container_IMAP($params)
+    {
+        if (!extension_loaded('imap')) {
+            return PEAR::raiseError('Cannot use IMAP authentication, '
+                    .'IMAP extension not loaded!', 41, PEAR_ERROR_DIE);
+        }
+        $this->_setDefaults();
+
+        // set parameters (if any)
+        if (is_array($params)) {
+            $this->_parseOptions($params);
+        }
+
+        if ($this->options['checkServer']) {
+            $this->_checkServer($this->options['timeout']);
+        }
+        return true;
+    }
+
+    // }}}
+    // {{{ _setDefaults()
+
+    /**
+     * Set some default options
+     *
+     * @access private
+     */
+    function _setDefaults()
+    {
+        $this->options['host'] = 'localhost';
+        $this->options['port'] = 143;
+        $this->options['baseDSN'] = '';
+        $this->options['checkServer'] = true;
+        $this->options['timeout'] = 20;
+    }
+
+    // }}}
+    // {{{ _checkServer()
+
+    /**
+     * Check if the given server and port are reachable
+     *
+     * @access private
+     */
+    function _checkServer() {
+        $this->log('Auth_Container_IMAP::_checkServer() called.', AUTH_LOG_DEBUG);
+        $fp = @fsockopen ($this->options['host'], $this->options['port'],
+                          $errno, $errstr, $this->options['timeout']);
+        if (is_resource($fp)) {
+            @fclose($fp);
+        } else {
+            $message = "Error connecting to IMAP server "
+                . $this->options['host']
+                . ":" . $this->options['port'];
+            return PEAR::raiseError($message, 41);
+        }
+    }
+
+    // }}}
+    // {{{ _parseOptions()
+
+    /**
+     * Parse options passed to the container class
+     *
+     * @access private
+     * @param  array
+     */
+    function _parseOptions($array)
+    {
+        foreach ($array as $key => $value) {
+            $this->options[$key] = $value;
+        }
+    }
+
+    // }}}
+    // {{{ fetchData()
+
+    /**
+     * Try to open a IMAP stream using $username / $password
+     *
+     * @param  string Username
+     * @param  string Password
+     * @return boolean
+     */
+    function fetchData($username, $password)
+    {
+        $this->log('Auth_Container_IMAP::fetchData() called.', AUTH_LOG_DEBUG);
+        $dsn = '{'.$this->options['host'].':'.$this->options['port'].$this->options['baseDSN'].'}';
+        $conn = @imap_open ($dsn, $username, $password, OP_HALFOPEN);
+        if (is_resource($conn)) {
+            $this->log('Successfully connected to IMAP server.', AUTH_LOG_DEBUG);
+            $this->activeUser = $username;
+            @imap_close($conn);
+            return true;
+        } else {
+            $this->log('Connection to IMAP server failed.', AUTH_LOG_DEBUG);
+            $this->activeUser = '';
+            return false;
+        }
+    }
+
+    // }}}
+
+}
+?>


Property changes on: pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/IMAP.php
___________________________________________________________________
Added: svn:executable
   + *

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/KADM5.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/KADM5.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/KADM5.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,171 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
+
+/**
+ * Storage driver for Authentication on a Kerberos V server.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.01 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license at php.net so we can mail you a copy immediately.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Andrew Teixeira <ateixeira at gmail.com>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    CVS: $Id: KADM5.php 237449 2007-06-12 03:11:27Z aashley $
+ * @link       http://pear.php.net/package/Auth
+ * @since      File available since Release 1.4.0
+ */
+
+/**
+ * Include Auth_Container base class
+ */
+require_once 'Auth/Container.php';
+/**
+ * Include PEAR for error handling
+ */
+require_once 'PEAR.php';
+
+/**
+ * Storage driver for Authentication on a Kerberos V server.
+ *
+ * Available options:
+ * hostname:        The hostname of the kerberos server
+ * realm:           The Kerberos V realm
+ * timeout:         The timeout for checking the server
+ * checkServer:     Set to true to check if the server is running when
+ *                  constructing the object
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Andrew Teixeira <ateixeira at gmail.com>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    Release: 1.6.2  File: $Revision: 237449 $
+ * @link       http://pear.php.net/package/Auth
+ * @since      Class available since Release 1.4.0
+ */
+class Auth_Container_KADM5 extends Auth_Container {
+
+    // {{{ properties
+
+    /**
+     * Options for the class
+     * @var string
+     */
+    var $options = array();
+
+    // }}}
+    // {{{ Auth_Container_KADM5()
+
+    /**
+     * Constructor of the container class
+     *
+     * $options can have these keys:
+     * 'hostname'    The hostname of the kerberos server
+     * 'realm'       The Kerberos V realm
+     * 'timeout'     The timeout for checking the server
+     * 'checkServer' Set to true to check if the server is running when
+     *               constructing the object
+     *
+     * @param  $options associative array
+     * @return object Returns an error object if something went wrong
+     */
+    function Auth_Container_KADM5($options) {
+        if (!extension_loaded('kadm5')) {
+            return PEAR::raiseError("Cannot use Kerberos V authentication, KADM5 extension not loaded!", 41, PEAR_ERROR_DIE);
+        }
+
+        $this->_setDefaults();
+
+        if (isset($options['hostname'])) {
+            $this->options['hostname'] = $options['hostname'];
+        }
+        if (isset($options['realm'])) {
+            $this->options['realm'] = $options['realm'];
+        }
+        if (isset($options['timeout'])) {
+            $this->options['timeout'] = $options['timeout'];
+        }
+        if (isset($options['checkServer'])) {
+            $this->options['checkServer'] = $options['checkServer'];
+        }
+
+        if ($this->options['checkServer']) {
+            $this->_checkServer();
+        }
+    }
+
+    // }}}
+    // {{{ fetchData()
+
+    /**
+     * Try to login to the KADM5 server
+     *
+     * @param   string Username
+     * @param   string Password
+     * @return  boolean
+     */
+    function fetchData($username, $password) {
+        $this->log('Auth_Container_KADM5::fetchData() called.', AUTH_LOG_DEBUG);
+        if ( ($username == NULL) || ($password == NULL) ) {
+            return false;
+        }
+
+        $server = $this->options['hostname'];
+        $realm = $this->options['realm'];
+        $check = @kadm5_init_with_password($server, $realm, $username, $password);
+
+        if ($check == false) {
+            return false;
+        } else {
+            return true;
+        }
+    }
+
+    // }}}
+    // {{{ _setDefaults()
+
+    /**
+     * Set some default options
+     *
+     * @access private
+     */
+    function _setDefaults() {
+        $this->options['hostname'] = 'localhost';
+        $this->options['realm'] = NULL;
+        $this->options['timeout'] = 10;
+        $this->options['checkServer'] = false;
+    }
+
+    // }}}
+    // {{{ _checkServer()
+
+    /**
+     * Check if the given server and port are reachable
+     *
+     * @access private
+     */
+    function _checkServer() {
+        $fp = @fsockopen ($this->options['hostname'], 88, $errno, $errstr, $this->options['timeout']);
+        if (is_resource($fp)) {
+            @fclose($fp);
+        } else {
+            $message = "Error connecting to Kerberos V server "
+                .$this->options['hostname'].":".$this->options['port'];
+            return PEAR::raiseError($message, 41, PEAR_ERROR_DIE);
+        }
+    }
+
+    // }}}
+
+}
+
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/LDAP.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/LDAP.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/LDAP.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,766 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
+
+/**
+ * Storage driver for use against an LDAP server
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.01 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license at php.net so we can mail you a copy immediately.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Jan Wagner <wagner at netsols.de>
+ * @author     Adam Ashley <aashley at php.net>
+ * @author     Hugues Peeters <hugues.peeters at claroline.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    CVS: $Id: LDAP.php 237449 2007-06-12 03:11:27Z aashley $
+ * @link       http://pear.php.net/package/Auth
+ */
+
+/**
+ * Include Auth_Container base class
+ */
+require_once "Auth/Container.php";
+/**
+ * Include PEAR package for error handling
+ */
+require_once "PEAR.php";
+
+/**
+ * Storage driver for fetching login data from LDAP
+ *
+ * This class is heavily based on the DB and File containers. By default it
+ * connects to localhost:389 and searches for uid=$username with the scope
+ * "sub". If no search base is specified, it will try to determine it via
+ * the namingContexts attribute. It takes its parameters in a hash, connects
+ * to the ldap server, binds anonymously, searches for the user, and tries
+ * to bind as the user with the supplied password. When a group was set, it
+ * will look for group membership of the authenticated user. If all goes
+ * well the authentication was successful.
+ *
+ * Parameters:
+ *
+ * host:        localhost (default), ldap.netsols.de or 127.0.0.1
+ * port:        389 (default) or 636 or whereever your server runs
+ * url:         ldap://localhost:389/
+ *              useful for ldaps://, works only with openldap2 ?
+ *              it will be preferred over host and port
+ * version:     LDAP version to use, ususally 2 (default) or 3,
+ *              must be an integer!
+ * referrals:   If set, determines whether the LDAP library automatically
+ *              follows referrals returned by LDAP servers or not. Possible
+ *              values are true (default) or false.
+ * binddn:      If set, searching for user will be done after binding
+ *              as this user, if not set the bind will be anonymous.
+ *              This is reported to make the container work with MS
+ *              Active Directory, but should work with any server that
+ *              is configured this way.
+ *              This has to be a complete dn for now (basedn and
+ *              userdn will not be appended).
+ * bindpw:      The password to use for binding with binddn
+ * basedn:      the base dn of your server
+ * userdn:      gets prepended to basedn when searching for user
+ * userscope:   Scope for user searching: one, sub (default), or base
+ * userattr:    the user attribute to search for (default: uid)
+ * userfilter:  filter that will be added to the search filter
+ *              this way: (&(userattr=username)(userfilter))
+ *              default: (objectClass=posixAccount)
+ * attributes:  array of additional attributes to fetch from entry.
+ *              these will added to auth data and can be retrieved via
+ *              Auth::getAuthData(). An empty array will fetch all attributes,
+ *              array('') will fetch no attributes at all (default)
+ *              If you add 'dn' as a value to this array, the users DN that was
+ *              used for binding will be added to auth data as well.
+ * attrformat:  The returned format of the additional data defined in the
+ *              'attributes' option. Two formats are available.
+ *              LDAP returns data formatted in a
+ *              multidimensional array where each array starts with a
+ *              'count' element providing the number of attributes in the
+ *              entry, or the number of values for attributes. When set
+ *              to this format, the only way to retrieve data from the
+ *              Auth object is by calling getAuthData('attributes').
+ *              AUTH returns data formatted in a
+ *              structure more compliant with other Auth Containers,
+ *              where each attribute element can be directly called by
+ *              getAuthData() method from Auth.
+ *              For compatibily with previous LDAP container versions,
+ *              the default format is LDAP.
+ * groupdn:     gets prepended to basedn when searching for group
+ * groupattr:   the group attribute to search for (default: cn)
+ * groupfilter: filter that will be added to the search filter when
+ *              searching for a group:
+ *              (&(groupattr=group)(memberattr=username)(groupfilter))
+ *              default: (objectClass=groupOfUniqueNames)
+ * memberattr : the attribute of the group object where the user dn
+ *              may be found (default: uniqueMember)
+ * memberisdn:  whether the memberattr is the dn of the user (default)
+ *              or the value of userattr (usually uid)
+ * group:       the name of group to search for
+ * groupscope:  Scope for group searching: one, sub (default), or base
+ * start_tls:   enable/disable the use of START_TLS encrypted connection
+ *              (default: false)
+ * debug:       Enable/Disable debugging output (default: false)
+ * try_all:     Whether to try all user accounts returned from the search
+ *              or just the first one. (default: false)
+ *
+ * To use this storage container, you have to use the following syntax:
+ *
+ * <?php
+ * ...
+ *
+ * $a1 = new Auth("LDAP", array(
+ *       'host' => 'localhost',
+ *       'port' => '389',
+ *       'version' => 3,
+ *       'basedn' => 'o=netsols,c=de',
+ *       'userattr' => 'uid'
+ *       'binddn' => 'cn=admin,o=netsols,c=de',
+ *       'bindpw' => 'password'));
+ *
+ * $a2 = new Auth('LDAP', array(
+ *       'url' => 'ldaps://ldap.netsols.de',
+ *       'basedn' => 'o=netsols,c=de',
+ *       'userscope' => 'one',
+ *       'userdn' => 'ou=People',
+ *       'groupdn' => 'ou=Groups',
+ *       'groupfilter' => '(objectClass=posixGroup)',
+ *       'memberattr' => 'memberUid',
+ *       'memberisdn' => false,
+ *       'group' => 'admin'
+ *       ));
+ *
+ * $a3 = new Auth('LDAP', array(
+ *       'host' => 'ldap.netsols.de',
+ *       'port' => 389,
+ *       'version' => 3,
+ *       'referrals' => false,
+ *       'basedn' => 'dc=netsols,dc=de',
+ *       'binddn' => 'cn=Jan Wagner,cn=Users,dc=netsols,dc=de',
+ *       'bindpw' => 'password',
+ *       'userattr' => 'samAccountName',
+ *       'userfilter' => '(objectClass=user)',
+ *       'attributes' => array(''),
+ *       'group' => 'testing',
+ *       'groupattr' => 'samAccountName',
+ *       'groupfilter' => '(objectClass=group)',
+ *       'memberattr' => 'member',
+ *       'memberisdn' => true,
+ *       'groupdn' => 'cn=Users',
+ *       'groupscope' => 'one',
+ *       'debug' => true);
+ *
+ * The parameter values have to correspond
+ * to the ones for your LDAP server of course.
+ *
+ * When talking to a Microsoft ActiveDirectory server you have to
+ * use 'samaccountname' as the 'userattr' and follow special rules
+ * to translate the ActiveDirectory directory names into 'basedn'.
+ * The 'basedn' for the default 'Users' folder on an ActiveDirectory
+ * server for the ActiveDirectory Domain (which is not related to
+ * its DNS name) "win2000.example.org" would be:
+ * "CN=Users, DC=win2000, DC=example, DC=org'
+ * where every component of the domain name becomes a DC attribute
+ * of its own. If you want to use a custom users folder you have to
+ * replace "CN=Users" with a sequence of "OU" attributes that specify
+ * the path to your custom folder in reverse order.
+ * So the ActiveDirectory folder
+ *   "win2000.example.org\Custom\Accounts"
+ * would become
+ *   "OU=Accounts, OU=Custom, DC=win2000, DC=example, DC=org'
+ *
+ * It seems that binding anonymously to an Active Directory
+ * is not allowed, so you have to set binddn and bindpw for
+ * user searching.
+ *
+ * LDAP Referrals need to be set to false for AD to work sometimes.
+ *
+ * Example a3 shows a full blown and tested example for connection to
+ * Windows 2000 Active Directory with group mebership checking
+ *
+ * Note also that if you want an encrypted connection to an MS LDAP
+ * server, then, on your webserver, you must specify
+ *        TLS_REQCERT never
+ * in /etc/ldap/ldap.conf or in the webserver user's ~/.ldaprc (which
+ * may or may not be read depending on your configuration).
+ *
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Jan Wagner <wagner at netsols.de>
+ * @author     Adam Ashley <aashley at php.net>
+ * @author     Hugues Peeters <hugues.peeters at claroline.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    Release: 1.6.2  File: $Revision: 237449 $
+ * @link       http://pear.php.net/package/Auth
+ */
+class Auth_Container_LDAP extends Auth_Container
+{
+
+    // {{{ properties
+
+    /**
+     * Options for the class
+     * @var array
+     */
+    var $options = array();
+
+    /**
+     * Connection ID of LDAP Link
+     * @var string
+     */
+    var $conn_id = false;
+
+    // }}}
+
+    // {{{ Auth_Container_LDAP() [constructor]
+
+    /**
+     * Constructor of the container class
+     *
+     * @param  $params, associative hash with host,port,basedn and userattr key
+     * @return object Returns an error object if something went wrong
+     */
+    function Auth_Container_LDAP($params)
+    {
+        if (false === extension_loaded('ldap')) {
+            return PEAR::raiseError('Auth_Container_LDAP: LDAP Extension not loaded',
+                    41, PEAR_ERROR_DIE);
+        }
+
+        $this->_setDefaults();
+
+        if (is_array($params)) {
+            $this->_parseOptions($params);
+        }
+    }
+
+    // }}}
+    // {{{ _prepare()
+
+    /**
+     * Prepare LDAP connection
+     *
+     * This function checks if we have already opened a connection to
+     * the LDAP server. If that's not the case, a new connection is opened.
+     *
+     * @access private
+     * @return mixed True or a PEAR error object.
+     */
+    function _prepare()
+    {
+        if (!$this->_isValidLink()) {
+            $res = $this->_connect();
+            if (PEAR::isError($res)) {
+                return $res;
+            }
+        }
+        return true;
+    }
+
+    // }}}
+    // {{{ _connect()
+
+    /**
+     * Connect to the LDAP server using the global options
+     *
+     * @access private
+     * @return object  Returns a PEAR error object if an error occurs.
+     */
+    function _connect()
+    {
+        $this->log('Auth_Container_LDAP::_connect() called.', AUTH_LOG_DEBUG);
+        // connect
+        if (isset($this->options['url']) && $this->options['url'] != '') {
+            $this->log('Connecting with URL', AUTH_LOG_DEBUG);
+            $conn_params = array($this->options['url']);
+        } else {
+            $this->log('Connecting with host:port', AUTH_LOG_DEBUG);
+            $conn_params = array($this->options['host'], $this->options['port']);
+        }
+
+        if (($this->conn_id = @call_user_func_array('ldap_connect', $conn_params)) === false) {
+            $this->log('Connection to server failed.', AUTH_LOG_DEBUG);
+            $this->log('LDAP ERROR: '.ldap_errno($this->conn_id).': '.ldap_error($this->conn_id), AUTH_LOG_DEBUG);
+            return PEAR::raiseError('Auth_Container_LDAP: Could not connect to server.', 41);
+        }
+        $this->log('Successfully connected to server', AUTH_LOG_DEBUG);
+
+        // switch LDAP version
+        if (is_numeric($this->options['version']) && $this->options['version'] > 2) {
+            $this->log("Switching to LDAP version {$this->options['version']}", AUTH_LOG_DEBUG);
+            @ldap_set_option($this->conn_id, LDAP_OPT_PROTOCOL_VERSION, $this->options['version']);
+
+            // start TLS if available
+            if (isset($this->options['start_tls']) && $this->options['start_tls']) {
+                $this->log("Starting TLS session", AUTH_LOG_DEBUG);
+                if (@ldap_start_tls($this->conn_id) === false) {
+                    $this->log('Could not start TLS session', AUTH_LOG_DEBUG);
+                    $this->log('LDAP ERROR: '.ldap_errno($this->conn_id).': '.ldap_error($this->conn_id), AUTH_LOG_DEBUG);
+                    return PEAR::raiseError('Auth_Container_LDAP: Could not start tls.', 41);
+                }
+            }
+        }
+
+        // switch LDAP referrals
+        if (is_bool($this->options['referrals'])) {
+            $this->log("Switching LDAP referrals to " . (($this->options['referrals']) ? 'true' : 'false'), AUTH_LOG_DEBUG);
+            if (@ldap_set_option($this->conn_id, LDAP_OPT_REFERRALS, $this->options['referrals']) === false) {
+                $this->log('Could not change LDAP referrals options', AUTH_LOG_DEBUG);
+                $this->log('LDAP ERROR: '.ldap_errno($this->conn_id).': '.ldap_error($this->conn_id), AUTH_LOG_DEBUG);
+            }
+        }
+
+        // bind with credentials or anonymously
+        if (strlen($this->options['binddn']) && strlen($this->options['bindpw'])) {
+            $this->log('Binding with credentials', AUTH_LOG_DEBUG);
+            $bind_params = array($this->conn_id, $this->options['binddn'], $this->options['bindpw']);
+        } else {
+            $this->log('Binding anonymously', AUTH_LOG_DEBUG);
+            $bind_params = array($this->conn_id);
+        }
+
+        // bind for searching
+        if ((@call_user_func_array('ldap_bind', $bind_params)) === false) {
+            $this->log('Bind failed', AUTH_LOG_DEBUG);
+            $this->log('LDAP ERROR: '.ldap_errno($this->conn_id).': '.ldap_error($this->conn_id), AUTH_LOG_DEBUG);
+            $this->_disconnect();
+            return PEAR::raiseError("Auth_Container_LDAP: Could not bind to LDAP server.", 41);
+        }
+        $this->log('Binding was successful', AUTH_LOG_DEBUG);
+
+        return true;
+    }
+
+    // }}}
+    // {{{ _disconnect()
+
+    /**
+     * Disconnects (unbinds) from ldap server
+     *
+     * @access private
+     */
+    function _disconnect()
+    {
+        $this->log('Auth_Container_LDAP::_disconnect() called.', AUTH_LOG_DEBUG);
+        if ($this->_isValidLink()) {
+            $this->log('disconnecting from server');
+            @ldap_unbind($this->conn_id);
+        }
+    }
+
+    // }}}
+    // {{{ _getBaseDN()
+
+    /**
+     * Tries to find Basedn via namingContext Attribute
+     *
+     * @access private
+     */
+    function _getBaseDN()
+    {
+        $this->log('Auth_Container_LDAP::_getBaseDN() called.', AUTH_LOG_DEBUG);
+        $err = $this->_prepare();
+        if ($err !== true) {
+            return PEAR::raiseError($err->getMessage(), $err->getCode());
+        }
+
+        if ($this->options['basedn'] == "" && $this->_isValidLink()) {
+            $this->log("basedn not set, searching via namingContexts.", AUTH_LOG_DEBUG);
+
+            $result_id = @ldap_read($this->conn_id, "", "(objectclass=*)", array("namingContexts"));
+
+            if (@ldap_count_entries($this->conn_id, $result_id) == 1) {
+
+                $this->log("got result for namingContexts", AUTH_LOG_DEBUG);
+
+                $entry_id = @ldap_first_entry($this->conn_id, $result_id);
+                $attrs = @ldap_get_attributes($this->conn_id, $entry_id);
+                $basedn = $attrs['namingContexts'][0];
+
+                if ($basedn != "") {
+                    $this->log("result for namingContexts was $basedn", AUTH_LOG_DEBUG);
+                    $this->options['basedn'] = $basedn;
+                }
+            }
+            @ldap_free_result($result_id);
+        }
+
+        // if base ist still not set, raise error
+        if ($this->options['basedn'] == "") {
+            return PEAR::raiseError("Auth_Container_LDAP: LDAP search base not specified!", 41);
+        }
+        return true;
+    }
+
+    // }}}
+    // {{{ _isValidLink()
+
+    /**
+     * determines whether there is a valid ldap conenction or not
+     *
+     * @accessd private
+     * @return boolean
+     */
+    function _isValidLink()
+    {
+        if (is_resource($this->conn_id)) {
+            if (get_resource_type($this->conn_id) == 'ldap link') {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    // }}}
+    // {{{ _setDefaults()
+
+    /**
+     * Set some default options
+     *
+     * @access private
+     */
+    function _setDefaults()
+    {
+        $this->options['url']         = '';
+        $this->options['host']        = 'localhost';
+        $this->options['port']        = '389';
+        $this->options['version']     = 2;
+        $this->options['referrals']   = true;
+        $this->options['binddn']      = '';
+        $this->options['bindpw']      = '';
+        $this->options['basedn']      = '';
+        $this->options['userdn']      = '';
+        $this->options['userscope']   = 'sub';
+        $this->options['userattr']    = 'uid';
+        $this->options['userfilter']  = '(objectClass=posixAccount)';
+        $this->options['attributes']  = array(''); // no attributes
+        $this->options['attrformat']  = 'AUTH'; // returns attribute like other Auth containers
+        $this->options['group']       = '';
+        $this->options['groupdn']     = '';
+        $this->options['groupscope']  = 'sub';
+        $this->options['groupattr']   = 'cn';
+        $this->options['groupfilter'] = '(objectClass=groupOfUniqueNames)';
+        $this->options['memberattr']  = 'uniqueMember';
+        $this->options['memberisdn']  = true;
+        $this->options['start_tls']   = false;
+        $this->options['debug']       = false;
+        $this->options['try_all']     = false; // Try all user ids returned not just the first one
+    }
+
+    // }}}
+    // {{{ _parseOptions()
+
+    /**
+     * Parse options passed to the container class
+     *
+     * @access private
+     * @param  array
+     */
+    function _parseOptions($array)
+    {
+        $array = $this->_setV12OptionsToV13($array);
+
+        foreach ($array as $key => $value) {
+            if (array_key_exists($key, $this->options)) {
+                if ($key == 'attributes') {
+                    if (is_array($value)) {
+                        $this->options[$key] = $value;
+                    } else {
+                        $this->options[$key] = explode(',', $value);
+                    }
+                } else {
+                    $this->options[$key] = $value;
+                }
+            }
+        }
+    }
+
+    // }}}
+    // {{{ _setV12OptionsToV13()
+
+    /**
+     * Adapt deprecated options from Auth 1.2 LDAP to Auth 1.3 LDAP
+     *
+     * @author Hugues Peeters <hugues.peeters at claroline.net>
+     * @access private
+     * @param array
+     * @return array
+     */
+    function _setV12OptionsToV13($array)
+    {
+        if (isset($array['useroc']))
+            $array['userfilter'] = "(objectClass=".$array['useroc'].")";
+        if (isset($array['groupoc']))
+            $array['groupfilter'] = "(objectClass=".$array['groupoc'].")";
+        if (isset($array['scope']))
+            $array['userscope'] = $array['scope'];
+
+        return $array;
+    }
+
+    // }}}
+    // {{{ _scope2function()
+
+    /**
+     * Get search function for scope
+     *
+     * @param  string scope
+     * @return string ldap search function
+     */
+    function _scope2function($scope)
+    {
+        switch($scope) {
+        case 'one':
+            $function = 'ldap_list';
+            break;
+        case 'base':
+            $function = 'ldap_read';
+            break;
+        default:
+            $function = 'ldap_search';
+            break;
+        }
+        return $function;
+    }
+
+    // }}}
+    // {{{ fetchData()
+
+    /**
+     * Fetch data from LDAP server
+     *
+     * Searches the LDAP server for the given username/password
+     * combination.  Escapes all LDAP meta characters in username
+     * before performing the query.
+     *
+     * @param  string Username
+     * @param  string Password
+     * @return boolean
+     */
+    function fetchData($username, $password)
+    {
+        $this->log('Auth_Container_LDAP::fetchData() called.', AUTH_LOG_DEBUG);
+        $err = $this->_prepare();
+        if ($err !== true) {
+            return PEAR::raiseError($err->getMessage(), $err->getCode());
+        }
+
+        $err = $this->_getBaseDN();
+        if ($err !== true) {
+            return PEAR::raiseError($err->getMessage(), $err->getCode());
+        }
+
+        // UTF8 Encode username for LDAPv3
+        if (@ldap_get_option($this->conn_id, LDAP_OPT_PROTOCOL_VERSION, $ver) && $ver == 3) {
+            $this->log('UTF8 encoding username for LDAPv3', AUTH_LOG_DEBUG);
+            $username = utf8_encode($username);
+        }
+
+        // make search filter
+        $filter = sprintf('(&(%s=%s)%s)',
+                          $this->options['userattr'],
+                          $this->_quoteFilterString($username),
+                          $this->options['userfilter']);
+
+        // make search base dn
+        $search_basedn = $this->options['userdn'];
+        if ($search_basedn != '' && substr($search_basedn, -1) != ',') {
+            $search_basedn .= ',';
+        }
+        $search_basedn .= $this->options['basedn'];
+
+        // attributes
+        $searchAttributes = $this->options['attributes'];
+
+        // make functions params array
+        $func_params = array($this->conn_id, $search_basedn, $filter, $searchAttributes);
+
+        // search function to use
+        $func_name = $this->_scope2function($this->options['userscope']);
+
+        $this->log("Searching with $func_name and filter $filter in $search_basedn", AUTH_LOG_DEBUG);
+
+        // search
+        if (($result_id = @call_user_func_array($func_name, $func_params)) === false) {
+            $this->log('User not found', AUTH_LOG_DEBUG);
+        } elseif (@ldap_count_entries($this->conn_id, $result_id) >= 1) { // did we get some possible results?
+
+            $this->log('User(s) found', AUTH_LOG_DEBUG);
+
+            $first = true;
+            $entry_id = null;
+
+            do {
+
+                // then get the user dn
+                if ($first) {
+                    $entry_id = @ldap_first_entry($this->conn_id, $result_id);
+                    $first = false;
+                } else {
+                    $entry_id = @ldap_next_entry($this->conn_id, $entry_id);
+                    if ($entry_id === false)
+                        break;
+                }
+                $user_dn  = @ldap_get_dn($this->conn_id, $entry_id);
+
+                // as the dn is not fetched as an attribute, we save it anyway
+                if (is_array($searchAttributes) && in_array('dn', $searchAttributes)) {
+                    $this->log('Saving DN to AuthData', AUTH_LOG_DEBUG);
+                    $this->_auth_obj->setAuthData('dn', $user_dn);
+                }
+
+                // fetch attributes
+                if ($attributes = @ldap_get_attributes($this->conn_id, $entry_id)) {
+
+                    if (is_array($attributes) && isset($attributes['count']) &&
+                         $attributes['count'] > 0) {
+
+                        // ldap_get_attributes() returns a specific multi dimensional array
+                        // format containing all the attributes and where each array starts
+                        // with a 'count' element providing the number of attributes in the
+                        // entry, or the number of values for attribute. For compatibility
+                        // reasons, it remains the default format returned by LDAP container
+                        // setAuthData().
+                        // The code below optionally returns attributes in another format,
+                        // more compliant with other Auth containers, where each attribute
+                        // element are directly set in the 'authData' list. This option is
+                        // enabled by setting 'attrformat' to
+                        // 'AUTH' in the 'options' array.
+                        // eg. $this->options['attrformat'] = 'AUTH'
+
+                        if ( strtoupper($this->options['attrformat']) == 'AUTH' ) {
+                            $this->log('Saving attributes to Auth data in AUTH format', AUTH_LOG_DEBUG);
+                            unset ($attributes['count']);
+                            foreach ($attributes as $attributeName => $attributeValue ) {
+                                if (is_int($attributeName)) continue;
+                                if (is_array($attributeValue) && isset($attributeValue['count'])) {
+                                    unset ($attributeValue['count']);
+                                }
+                                if (count($attributeValue)<=1) $attributeValue = $attributeValue[0];
+                                $this->log('Storing additional field: '.$attributeName, AUTH_LOG_DEBUG);
+                                $this->_auth_obj->setAuthData($attributeName, $attributeValue);
+                            }
+                        }
+                        else
+                        {
+                            $this->log('Saving attributes to Auth data in LDAP format', AUTH_LOG_DEBUG);
+                            $this->_auth_obj->setAuthData('attributes', $attributes);
+                        }
+                    }
+                }
+                @ldap_free_result($result_id);
+
+                // need to catch an empty password as openldap seems to return TRUE
+                // if anonymous binding is allowed
+                if ($password != "") {
+                    $this->log("Bind as $user_dn", AUTH_LOG_DEBUG);
+
+                    // try binding as this user with the supplied password
+                    if (@ldap_bind($this->conn_id, $user_dn, $password)) {
+                        $this->log('Bind successful', AUTH_LOG_DEBUG);
+
+                        // check group if appropiate
+                        if (strlen($this->options['group'])) {
+                            // decide whether memberattr value is a dn or the username
+                            $this->log('Checking group membership', AUTH_LOG_DEBUG);
+                            $return = $this->checkGroup(($this->options['memberisdn']) ? $user_dn : $username);
+                            $this->_disconnect();
+                            return $return;
+                        } else {
+                            $this->log('Authenticated', AUTH_LOG_DEBUG);
+                            $this->_disconnect();
+                            return true; // user authenticated
+                        } // checkGroup
+                    } // bind
+                } // non-empty password
+            } while ($this->options['try_all'] == true); // interate through entries
+        } // get results
+        // default
+        $this->log('NOT authenticated!', AUTH_LOG_DEBUG);
+        $this->_disconnect();
+        return false;
+    }
+
+    // }}}
+    // {{{ checkGroup()
+
+    /**
+     * Validate group membership
+     *
+     * Searches the LDAP server for group membership of the
+     * supplied username.  Quotes all LDAP filter meta characters in
+     * the user name before querying the LDAP server.
+     *
+     * @param  string Distinguished Name of the authenticated User
+     * @return boolean
+     */
+    function checkGroup($user)
+    {
+        $this->log('Auth_Container_LDAP::checkGroup() called.', AUTH_LOG_DEBUG);
+        $err = $this->_prepare();
+        if ($err !== true) {
+            return PEAR::raiseError($err->getMessage(), $err->getCode());
+        }
+
+        // make filter
+        $filter = sprintf('(&(%s=%s)(%s=%s)%s)',
+                          $this->options['groupattr'],
+                          $this->options['group'],
+                          $this->options['memberattr'],
+                          $this->_quoteFilterString($user),
+                          $this->options['groupfilter']);
+
+        // make search base dn
+        $search_basedn = $this->options['groupdn'];
+        if ($search_basedn != '' && substr($search_basedn, -1) != ',') {
+            $search_basedn .= ',';
+        }
+        $search_basedn .= $this->options['basedn'];
+
+        $func_params = array($this->conn_id, $search_basedn, $filter,
+                             array($this->options['memberattr']));
+        $func_name = $this->_scope2function($this->options['groupscope']);
+
+        $this->log("Searching with $func_name and filter $filter in $search_basedn", AUTH_LOG_DEBUG);
+
+        // search
+        if (($result_id = @call_user_func_array($func_name, $func_params)) != false) {
+            if (@ldap_count_entries($this->conn_id, $result_id) == 1) {
+                @ldap_free_result($result_id);
+                $this->log('User is member of group', AUTH_LOG_DEBUG);
+                return true;
+            }
+        }
+        // default
+        $this->log('User is NOT member of group', AUTH_LOG_DEBUG);
+        return false;
+    }
+
+    // }}}
+    // {{{ _quoteFilterString()
+
+    /**
+     * Escapes LDAP filter special characters as defined in RFC 2254.
+     *
+     * @access private
+     * @param string Filter String
+     */
+    function _quoteFilterString($filter_str)
+    {
+        $metas        = array(  '\\',  '*',  '(',  ')',   "\x00");
+        $quoted_metas = array('\\\\', '\*', '\(', '\)', "\\\x00");
+        return str_replace($metas, $quoted_metas, $filter_str);
+    }
+
+    // }}}
+
+}
+
+?>


Property changes on: pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/LDAP.php
___________________________________________________________________
Added: svn:executable
   + *

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/MDB.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/MDB.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/MDB.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,625 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
+
+/**
+ * Storage driver for use against PEAR MDB
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.01 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license at php.net so we can mail you a copy immediately.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Lorenzo Alberton <l.alberton at quipo.it>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    CVS: $Id: MDB.php 256753 2008-04-04 07:57:02Z aashley $
+ * @link       http://pear.php.net/package/Auth
+ * @since      File available since Release 1.2.3
+ */
+
+/**
+ * Include Auth_Container base class
+ */
+require_once 'Auth/Container.php';
+/**
+ * Include PEAR MDB package
+ */
+require_once 'MDB.php';
+
+/**
+ * Storage driver for fetching login data from a database
+ *
+ * This storage driver can use all databases which are supported
+ * by the PEAR MDB abstraction layer to fetch login data.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Lorenzo Alberton <l.alberton at quipo.it>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    Release: 1.6.2  File: $Revision: 256753 $
+ * @link       http://pear.php.net/package/Auth
+ * @since      Class available since Release 1.2.3
+ */
+class Auth_Container_MDB extends Auth_Container
+{
+
+    // {{{ properties
+
+    /**
+     * Additional options for the storage container
+     * @var array
+     */
+    var $options = array();
+
+    /**
+     * MDB object
+     * @var object
+     */
+    var $db = null;
+    var $dsn = '';
+
+    /**
+     * User that is currently selected from the DB.
+     * @var string
+     */
+    var $activeUser = '';
+
+    // }}}
+    // {{{ Auth_Container_MDB() [constructor]
+
+    /**
+     * Constructor of the container class
+     *
+     * Initate connection to the database via PEAR::MDB
+     *
+     * @param  string Connection data or MDB object
+     * @return object Returns an error object if something went wrong
+     */
+    function Auth_Container_MDB($dsn)
+    {
+        $this->_setDefaults();
+
+        if (is_array($dsn)) {
+            $this->_parseOptions($dsn);
+            if (empty($this->options['dsn'])) {
+                PEAR::raiseError('No connection parameters specified!');
+            }
+        } else {
+            $this->options['dsn'] = $dsn;
+        }
+    }
+
+    // }}}
+    // {{{ _connect()
+
+    /**
+     * Connect to database by using the given DSN string
+     *
+     * @access private
+     * @param  mixed DSN string | array | mdb object
+     * @return mixed  Object on error, otherwise bool
+     */
+    function _connect($dsn)
+    {
+        $this->log('Auth_Container_MDB::_connect() called.', AUTH_LOG_DEBUG);
+        if (is_string($dsn) || is_array($dsn)) {
+            $this->db =& MDB::connect($dsn, $this->options['db_options']);
+        } elseif (is_subclass_of($dsn, 'mdb_common')) {
+            $this->db = $dsn;
+        } elseif (is_object($dsn) && MDB::isError($dsn)) {
+            return PEAR::raiseError($dsn->getMessage(), $dsn->code);
+        } else {
+            return PEAR::raiseError('The given dsn was not valid in file ' . __FILE__ . ' at line ' . __LINE__,
+                                    41,
+                                    PEAR_ERROR_RETURN,
+                                    null,
+                                    null
+                                    );
+
+        }
+
+        if (MDB::isError($this->db) || PEAR::isError($this->db)) {
+            return PEAR::raiseError($this->db->getMessage(), $this->db->code);
+        }
+
+        if ($this->options['auto_quote']) {
+            if (strpos('.', $this->options['table']) === false) {
+                $this->options['final_table'] = $this->db->quoteIdentifier($this->options['table']);
+            } else {
+                $t = explode('.', $this->options['table']);
+                for ($i = 0, $count = count($t); $i < $count; $i++)
+                    $t[$i] = $this->db->quoteIdentifier($t[$i]);
+                $this->options['final_table'] = implode('.', $t);
+            }
+            $this->options['final_usernamecol'] = $this->db->quoteIdentifier($this->options['usernamecol']);
+            $this->options['final_passwordcol'] = $this->db->quoteIdentifier($this->options['passwordcol']);
+        } else {
+            $this->options['final_table'] = $this->options['table'];
+            $this->options['final_usernamecol'] = $this->options['usernamecol'];
+            $this->options['final_passwordcol'] = $this->options['passwordcol'];
+        }
+
+        return true;
+    }
+
+    // }}}
+    // {{{ _prepare()
+
+    /**
+     * Prepare database connection
+     *
+     * This function checks if we have already opened a connection to
+     * the database. If that's not the case, a new connection is opened.
+     *
+     * @access private
+     * @return mixed True or a MDB error object.
+     */
+    function _prepare()
+    {
+        if (is_subclass_of($this->db, 'mdb_common')) {
+            return true;
+        }
+        return $this->_connect($this->options['dsn']);
+    }
+
+    // }}}
+    // {{{ query()
+
+    /**
+     * Prepare query to the database
+     *
+     * This function checks if we have already opened a connection to
+     * the database. If that's not the case, a new connection is opened.
+     * After that the query is passed to the database.
+     *
+     * @access public
+     * @param  string Query string
+     * @return mixed  a MDB_result object or MDB_OK on success, a MDB
+     *                or PEAR error on failure
+     */
+    function query($query)
+    {
+        $this->log('Auth_Container_MDB::query() called.', AUTH_LOG_DEBUG);
+        $err = $this->_prepare();
+        if ($err !== true) {
+            return $err;
+        }
+        return $this->db->query($query);
+    }
+
+    // }}}
+    // {{{ _setDefaults()
+
+    /**
+     * Set some default options
+     *
+     * @access private
+     * @return void
+     */
+    function _setDefaults()
+    {
+        $this->options['table']       = 'auth';
+        $this->options['usernamecol'] = 'username';
+        $this->options['passwordcol'] = 'password';
+        $this->options['dsn']         = '';
+        $this->options['db_fields']   = '';
+        $this->options['cryptType']   = 'md5';
+        $this->options['db_options']  = array();
+        $this->options['db_where']    = '';
+        $this->options['auto_quote']  = true;
+    }
+
+    // }}}
+    // {{{ _parseOptions()
+
+    /**
+     * Parse options passed to the container class
+     *
+     * @access private
+     * @param  array
+     */
+    function _parseOptions($array)
+    {
+        foreach ($array as $key => $value) {
+            if (isset($this->options[$key])) {
+                $this->options[$key] = $value;
+            }
+        }
+    }
+
+    // }}}
+    // {{{ _quoteDBFields()
+
+    /**
+     * Quote the db_fields option to avoid the possibility of SQL injection.
+     *
+     * @access private
+     * @return string A properly quoted string that can be concatenated into a
+     * SELECT clause.
+     */
+    function _quoteDBFields()
+    {
+        if (isset($this->options['db_fields'])) {
+            if (is_array($this->options['db_fields'])) {
+                if ($this->options['auto_quote']) {
+                    $fields = array();
+                    foreach ($this->options['db_fields'] as $field) {
+                        $fields[] = $this->db->quoteIdentifier($field);
+                    }
+                    return implode(', ', $fields);
+                } else {
+                    return implode(', ', $this->options['db_fields']);
+                }
+            } else {
+                if (strlen($this->options['db_fields']) > 0) {
+                    if ($this->options['auto_quote']) {
+                        return $this->db->quoteIdentifier($this->options['db_fields']);
+                    } else {
+                        return $this->options['db_fields'];
+                    }
+                }
+            }
+        }
+
+        return '';
+    }
+
+    // }}}
+    // {{{ fetchData()
+
+    /**
+     * Get user information from database
+     *
+     * This function uses the given username to fetch
+     * the corresponding login data from the database
+     * table. If an account that matches the passed username
+     * and password is found, the function returns true.
+     * Otherwise it returns false.
+     *
+     * @param   string Username
+     * @param   string Password
+     * @param   boolean If true password is secured using a md5 hash
+     *                  the frontend and auth are responsible for making sure the container supports
+     *                  challenge response password authentication
+     * @return  mixed  Error object or boolean
+     */
+    function fetchData($username, $password, $isChallengeResponse=false)
+    {
+        $this->log('Auth_Container_MDB::fetchData() called.', AUTH_LOG_DEBUG);
+        // Prepare for a database query
+        $err = $this->_prepare();
+        if ($err !== true) {
+            return PEAR::raiseError($err->getMessage(), $err->getCode());
+        }
+
+        //Check if db_fields contains a *, if so assume all columns are selected
+        if (is_string($this->options['db_fields'])
+            && strstr($this->options['db_fields'], '*')) {
+            $sql_from = '*';
+        } else {
+            $sql_from = $this->options['final_usernamecol'].
+                ", ".$this->options['final_passwordcol'];
+
+            if (strlen($fields = $this->_quoteDBFields()) > 0) {
+                $sql_from .= ', '.$fields;
+            }
+        }
+
+        $query = sprintf("SELECT %s FROM %s WHERE %s = %s",
+                         $sql_from,
+                         $this->options['final_table'],
+                         $this->options['final_usernamecol'],
+                         $this->db->getTextValue($username)
+                         );
+
+        // check if there is an optional parameter db_where
+        if ($this->options['db_where'] != '') {
+            // there is one, so add it to the query
+            $query .= " AND ".$this->options['db_where'];
+        }
+
+        $this->log('Running SQL against MDB: '.$query, AUTH_LOG_DEBUG);
+
+        $res = $this->db->getRow($query, null, null, null, MDB_FETCHMODE_ASSOC);
+
+        if (MDB::isError($res) || PEAR::isError($res)) {
+            return PEAR::raiseError($res->getMessage(), $res->getCode());
+        }
+        if (!is_array($res)) {
+            $this->activeUser = '';
+            return false;
+        }
+
+        // Perform trimming here before the hashing
+        $password = trim($password, "\r\n");
+        $res[$this->options['passwordcol']] = trim($res[$this->options['passwordcol']], "\r\n");
+
+        // If using Challenge Response md5 the pass with the secret
+        if ($isChallengeResponse) {
+            $res[$this->options['passwordcol']] =
+                md5($res[$this->options['passwordcol']].$this->_auth_obj->session['loginchallenege']);
+            // UGLY cannot avoid without modifying verifyPassword
+            if ($this->options['cryptType'] == 'md5') {
+                $res[$this->options['passwordcol']] = md5($res[$this->options['passwordcol']]);
+            }
+        }
+
+        if ($this->verifyPassword($password,
+                                  $res[$this->options['passwordcol']],
+                                  $this->options['cryptType'])) {
+            // Store additional field values in the session
+            foreach ($res as $key => $value) {
+                if ($key == $this->options['passwordcol'] ||
+                    $key == $this->options['usernamecol']) {
+                    continue;
+                }
+
+                $this->log('Storing additional field: '.$key, AUTH_LOG_DEBUG);
+                // Use reference to the auth object if exists
+                // This is because the auth session variable can change so a static
+                // call to setAuthData does not make sense
+                $this->_auth_obj->setAuthData($key, $value);
+            }
+            return true;
+        }
+
+        $this->activeUser = $res[$this->options['usernamecol']];
+        return false;
+    }
+
+    // }}}
+    // {{{ listUsers()
+
+    /**
+     * Returns a list of users from the container
+     *
+     * @return mixed array|PEAR_Error
+     * @access public
+     */
+    function listUsers()
+    {
+        $this->log('Auth_Container_MDB::listUsers() called.', AUTH_LOG_DEBUG);
+        $err = $this->_prepare();
+        if ($err !== true) {
+            return PEAR::raiseError($err->getMessage(), $err->getCode());
+        }
+
+        $retVal = array();
+
+        //Check if db_fields contains a *, if so assume all columns are selected
+        if (   is_string($this->options['db_fields'])
+            && strstr($this->options['db_fields'], '*')) {
+            $sql_from = '*';
+        } else {
+            $sql_from = $this->options['final_usernamecol']
+                .', '.$this->options['final_passwordcol'];
+
+            if (strlen($fields = $this->_quoteDBFields()) > 0) {
+                $sql_from .= ', '.$fields;
+            }
+        }
+
+        $query = sprintf('SELECT %s FROM %s',
+                         $sql_from,
+                         $this->options['final_table']
+                         );
+
+        // check if there is an optional parameter db_where
+        if ($this->options['db_where'] != '') {
+            // there is one, so add it to the query
+            $query .= " WHERE ".$this->options['db_where'];
+        }
+
+        $this->log('Running SQL against MDB: '.$query, AUTH_LOG_DEBUG);
+
+        $res = $this->db->getAll($query, null, null, null, MDB_FETCHMODE_ASSOC);
+
+        if (MDB::isError($res)) {
+            return PEAR::raiseError($res->getMessage(), $res->getCode());
+        } else {
+            foreach ($res as $user) {
+                $user['username'] = $user[$this->options['usernamecol']];
+                $retVal[] = $user;
+            }
+        }
+        $this->log('Found '.count($retVal).' users.', AUTH_LOG_DEBUG);
+        return $retVal;
+    }
+
+    // }}}
+    // {{{ addUser()
+
+    /**
+     * Add user to the storage container
+     *
+     * @access public
+     * @param  string Username
+     * @param  string Password
+     * @param  mixed  Additional information that are stored in the DB
+     *
+     * @return mixed True on success, otherwise error object
+     */
+    function addUser($username, $password, $additional = "")
+    {
+        $this->log('Auth_Container_MDB::addUser() called.', AUTH_LOG_DEBUG);
+        $err = $this->_prepare();
+        if ($err !== true) {
+            return PEAR::raiseError($err->getMessage(), $err->getCode());
+        }
+
+        if (isset($this->options['cryptType']) && $this->options['cryptType'] == 'none') {
+            $cryptFunction = 'strval';
+        } elseif (isset($this->options['cryptType']) && function_exists($this->options['cryptType'])) {
+            $cryptFunction = $this->options['cryptType'];
+        } else {
+            $cryptFunction = 'md5';
+        }
+
+        $password = $cryptFunction($password);
+
+        $additional_key   = '';
+        $additional_value = '';
+
+        if (is_array($additional)) {
+            foreach ($additional as $key => $value) {
+                if ($this->options['auto_quote']) {
+                    $additional_key   .= ', ' . $this->db->quoteIdentifier($key);
+                } else {
+                    $additional_key   .= ', ' . $key;
+                }
+                $additional_value .= ', ' . $this->db->getTextValue($value);
+            }
+        }
+
+        $query = sprintf("INSERT INTO %s (%s, %s%s) VALUES (%s, %s%s)",
+                         $this->options['final_table'],
+                         $this->options['final_usernamecol'],
+                         $this->options['final_passwordcol'],
+                         $additional_key,
+                         $this->db->getTextValue($username),
+                         $this->db->getTextValue($password),
+                         $additional_value
+                         );
+
+        $this->log('Running SQL against MDB: '.$query, AUTH_LOG_DEBUG);
+
+        $res = $this->query($query);
+
+        if (MDB::isError($res)) {
+            return PEAR::raiseError($res->getMessage(), $res->code);
+        }
+        return true;
+    }
+
+    // }}}
+    // {{{ removeUser()
+
+    /**
+     * Remove user from the storage container
+     *
+     * @access public
+     * @param  string Username
+     *
+     * @return mixed True on success, otherwise error object
+     */
+    function removeUser($username)
+    {
+        $this->log('Auth_Container_MDB::removeUser() called.', AUTH_LOG_DEBUG);
+        $err = $this->_prepare();
+        if ($err !== true) {
+            return PEAR::raiseError($err->getMessage(), $err->getCode());
+        }
+
+        $query = sprintf("DELETE FROM %s WHERE %s = %s",
+                         $this->options['final_table'],
+                         $this->options['final_usernamecol'],
+                         $this->db->getTextValue($username)
+                         );
+
+        // check if there is an optional parameter db_where
+        if ($this->options['db_where'] != '') {
+            // there is one, so add it to the query
+            $query .= " AND ".$this->options['db_where'];
+        }
+
+        $this->log('Running SQL against MDB: '.$query, AUTH_LOG_DEBUG);
+
+        $res = $this->query($query);
+
+        if (MDB::isError($res)) {
+            return PEAR::raiseError($res->getMessage(), $res->code);
+        }
+        return true;
+    }
+
+    // }}}
+    // {{{ changePassword()
+
+    /**
+     * Change password for user in the storage container
+     *
+     * @param string Username
+     * @param string The new password (plain text)
+     */
+    function changePassword($username, $password)
+    {
+        $this->log('Auth_Container_MDB::changePassword() called.', AUTH_LOG_DEBUG);
+        $err = $this->_prepare();
+        if ($err !== true) {
+            return PEAR::raiseError($err->getMessage(), $err->getCode());
+        }
+
+        if (isset($this->options['cryptType']) && $this->options['cryptType'] == 'none') {
+            $cryptFunction = 'strval';
+        } elseif (isset($this->options['cryptType']) && function_exists($this->options['cryptType'])) {
+            $cryptFunction = $this->options['cryptType'];
+        } else {
+            $cryptFunction = 'md5';
+        }
+
+        $password = $cryptFunction($password);
+
+        $query = sprintf("UPDATE %s SET %s = %s WHERE %s = %s",
+                         $this->options['final_table'],
+                         $this->options['final_passwordcol'],
+                         $this->db->getTextValue($password),
+                         $this->options['final_usernamecol'],
+                         $this->db->getTextValue($username)
+                         );
+
+        // check if there is an optional parameter db_where
+        if ($this->options['db_where'] != '') {
+            // there is one, so add it to the query
+            $query .= " AND ".$this->options['db_where'];
+        }
+
+        $this->log('Running SQL against MDB: '.$query, AUTH_LOG_DEBUG);
+
+        $res = $this->query($query);
+
+        if (MDB::isError($res)) {
+            return PEAR::raiseError($res->getMessage(), $res->code);
+        }
+        return true;
+    }
+
+    // }}}
+    // {{{ supportsChallengeResponse()
+
+    /**
+     * Determine if this container supports
+     * password authentication with challenge response
+     *
+     * @return bool
+     * @access public
+     */
+    function supportsChallengeResponse()
+    {
+        return in_array($this->options['cryptType'], array('md5', 'none', ''));
+    }
+
+    // }}}
+    // {{{ getCryptType()
+
+    /**
+     * Returns the selected crypt type for this container
+     *
+     * @return string Function used to crypt the password
+     */
+    function getCryptType()
+    {
+        return $this->options['cryptType'];
+    }
+
+    // }}}
+
+}
+?>


Property changes on: pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/MDB.php
___________________________________________________________________
Added: svn:executable
   + *

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/MDB2.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/MDB2.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/MDB2.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,624 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
+
+/**
+ * Storage driver for use against PEAR MDB2
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.01 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license at php.net so we can mail you a copy immediately.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Lorenzo Alberton <l.alberton at quipo.it>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    CVS: $Id: MDB2.php 256753 2008-04-04 07:57:02Z aashley $
+ * @link       http://pear.php.net/package/Auth
+ * @since      File available since Release 1.3.0
+ */
+
+/**
+ * Include Auth_Container base class
+ */
+require_once 'Auth/Container.php';
+/**
+ * Include PEAR MDB2 package
+ */
+require_once 'MDB2.php';
+
+/**
+ * Storage driver for fetching login data from a database
+ *
+ * This storage driver can use all databases which are supported
+ * by the PEAR MDB2 abstraction layer to fetch login data.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Lorenzo Alberton <l.alberton at quipo.it>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    Release: 1.6.2  File: $Revision: 256753 $
+ * @link       http://pear.php.net/package/Auth
+ * @since      Class available since Release 1.3.0
+ */
+class Auth_Container_MDB2 extends Auth_Container
+{
+
+    // {{{ properties
+
+    /**
+     * Additional options for the storage container
+     * @var array
+     */
+    var $options = array();
+
+    /**
+     * MDB object
+     * @var object
+     */
+    var $db = null;
+    var $dsn = '';
+
+    /**
+     * User that is currently selected from the DB.
+     * @var string
+     */
+    var $activeUser = '';
+
+    // }}}
+    // {{{ Auth_Container_MDB2() [constructor]
+
+    /**
+     * Constructor of the container class
+     *
+     * Initate connection to the database via PEAR::MDB2
+     *
+     * @param  string Connection data or MDB2 object
+     * @return object Returns an error object if something went wrong
+     */
+    function Auth_Container_MDB2($dsn)
+    {
+        $this->_setDefaults();
+
+        if (is_array($dsn)) {
+            $this->_parseOptions($dsn);
+            if (empty($this->options['dsn'])) {
+                PEAR::raiseError('No connection parameters specified!');
+            }
+        } else {
+            $this->options['dsn'] = $dsn;
+        }
+    }
+
+    // }}}
+    // {{{ _connect()
+
+    /**
+     * Connect to database by using the given DSN string
+     *
+     * @access private
+     * @param  mixed DSN string | array | mdb object
+     * @return mixed  Object on error, otherwise bool
+     */
+    function _connect($dsn)
+    {
+        $this->log('Auth_Container_MDB2::_connect() called.', AUTH_LOG_DEBUG);
+        if (is_string($dsn) || is_array($dsn)) {
+            $this->db =& MDB2::connect($dsn, $this->options['db_options']);
+        } elseif (is_subclass_of($dsn, 'MDB2_Driver_Common')) {
+            $this->db = $dsn;
+        } elseif (is_object($dsn) && MDB2::isError($dsn)) {
+            return PEAR::raiseError($dsn->getMessage(), $dsn->code);
+        } else {
+            return PEAR::raiseError('The given dsn was not valid in file ' . __FILE__ . ' at line ' . __LINE__,
+                                    41,
+                                    PEAR_ERROR_RETURN,
+                                    null,
+                                    null
+                                    );
+
+        }
+
+        if (MDB2::isError($this->db) || PEAR::isError($this->db)) {
+            return PEAR::raiseError($this->db->getMessage(), $this->db->code);
+        }
+
+        if ($this->options['auto_quote']) {
+            if (strpos('.', $this->options['table']) === false) {
+                $this->options['final_table'] = $this->db->quoteIdentifier($this->options['table'], true);
+            } else {
+                $t = explode('.', $this->options['table']);
+                for ($i = 0, $count = count($t); $i < $count; $i++)
+                    $t[$i] = $this->db->quoteIdentifier($t[$i], true);
+                $this->options['final_table'] = implode('.', $t);
+            }
+            $this->options['final_usernamecol'] = $this->db->quoteIdentifier($this->options['usernamecol'], true);
+            $this->options['final_passwordcol'] = $this->db->quoteIdentifier($this->options['passwordcol'], true);
+        } else {
+            $this->options['final_table'] = $this->options['table'];
+            $this->options['final_usernamecol'] = $this->options['usernamecol'];
+            $this->options['final_passwordcol'] = $this->options['passwordcol'];
+        }
+
+        return true;
+    }
+
+    // }}}
+    // {{{ _prepare()
+
+    /**
+     * Prepare database connection
+     *
+     * This function checks if we have already opened a connection to
+     * the database. If that's not the case, a new connection is opened.
+     *
+     * @access private
+     * @return mixed True or a MDB error object.
+     */
+    function _prepare()
+    {
+        if (is_subclass_of($this->db, 'MDB2_Driver_Common')) {
+            return true;
+        }
+        return $this->_connect($this->options['dsn']);
+    }
+
+    // }}}
+    // {{{ query()
+
+    /**
+     * Prepare query to the database
+     *
+     * This function checks if we have already opened a connection to
+     * the database. If that's not the case, a new connection is opened.
+     * After that the query is passed to the database.
+     *
+     * @access public
+     * @param  string Query string
+     * @return mixed  a MDB_result object or MDB_OK on success, a MDB
+     *                or PEAR error on failure
+     */
+    function query($query)
+    {
+        $this->log('Auth_Container_MDB2::query() called.', AUTH_LOG_DEBUG);
+        $err = $this->_prepare();
+        if ($err !== true) {
+            return $err;
+        }
+        return $this->db->exec($query);
+    }
+
+    // }}}
+    // {{{ _setDefaults()
+
+    /**
+     * Set some default options
+     *
+     * @access private
+     * @return void
+     */
+    function _setDefaults()
+    {
+        $this->options['table']       = 'auth';
+        $this->options['usernamecol'] = 'username';
+        $this->options['passwordcol'] = 'password';
+        $this->options['dsn']         = '';
+        $this->options['db_fields']   = '';
+        $this->options['cryptType']   = 'md5';
+        $this->options['db_options']  = array();
+        $this->options['db_where']    = '';
+        $this->options['auto_quote']  = true;
+    }
+
+    // }}}
+    // {{{ _parseOptions()
+
+    /**
+     * Parse options passed to the container class
+     *
+     * @access private
+     * @param  array
+     */
+    function _parseOptions($array)
+    {
+        foreach ($array as $key => $value) {
+            if (isset($this->options[$key])) {
+                $this->options[$key] = $value;
+            }
+        }
+    }
+
+    // }}}
+    // {{{ _quoteDBFields()
+
+    /**
+     * Quote the db_fields option to avoid the possibility of SQL injection.
+     *
+     * @access private
+     * @return string A properly quoted string that can be concatenated into a
+     * SELECT clause.
+     */
+    function _quoteDBFields()
+    {
+        if (isset($this->options['db_fields'])) {
+            if (is_array($this->options['db_fields'])) {
+                if ($this->options['auto_quote']) {
+                    $fields = array();
+                    foreach ($this->options['db_fields'] as $field) {
+                        $fields[] = $this->db->quoteIdentifier($field, true);
+                    }
+                    return implode(', ', $fields);
+                } else {
+                    return implode(', ', $this->options['db_fields']);
+                }
+            } else {
+                if (strlen($this->options['db_fields']) > 0) {
+                    if ($this->options['auto_quote']) {
+                        return $this->db->quoteIdentifier($this->options['db_fields'], true);
+                    } else {
+                        return $this->options['db_fields'];
+                    }
+                }
+            }
+        }
+
+        return '';
+    }
+
+    // }}}
+    // {{{ fetchData()
+
+    /**
+     * Get user information from database
+     *
+     * This function uses the given username to fetch
+     * the corresponding login data from the database
+     * table. If an account that matches the passed username
+     * and password is found, the function returns true.
+     * Otherwise it returns false.
+     *
+     * @param   string Username
+     * @param   string Password
+     * @param   boolean If true password is secured using a md5 hash
+     *                  the frontend and auth are responsible for making sure the container supports
+     *                  challenge response password authentication
+     * @return  mixed  Error object or boolean
+     */
+    function fetchData($username, $password, $isChallengeResponse=false)
+    {
+        $this->log('Auth_Container_MDB2::fetchData() called.', AUTH_LOG_DEBUG);
+        // Prepare for a database query
+        $err = $this->_prepare();
+        if ($err !== true) {
+            return PEAR::raiseError($err->getMessage(), $err->getCode());
+        }
+
+        //Check if db_fields contains a *, if so assume all columns are selected
+        if (is_string($this->options['db_fields'])
+            && strstr($this->options['db_fields'], '*')) {
+            $sql_from = '*';
+        } else {
+            $sql_from = $this->options['final_usernamecol'].
+                ", ".$this->options['final_passwordcol'];
+
+            if (strlen($fields = $this->_quoteDBFields()) > 0) {
+                $sql_from .= ', '.$fields;
+            }
+        }
+        $query = sprintf("SELECT %s FROM %s WHERE %s = %s",
+                         $sql_from,
+                         $this->options['final_table'],
+                         $this->options['final_usernamecol'],
+                         $this->db->quote($username, 'text')
+                         );
+
+        // check if there is an optional parameter db_where
+        if ($this->options['db_where'] != '') {
+            // there is one, so add it to the query
+            $query .= " AND ".$this->options['db_where'];
+        }
+
+        $this->log('Running SQL against MDB2: '.$query, AUTH_LOG_DEBUG);
+
+        $res = $this->db->queryRow($query, null, MDB2_FETCHMODE_ASSOC);
+        if (MDB2::isError($res) || PEAR::isError($res)) {
+            return PEAR::raiseError($res->getMessage(), $res->getCode());
+        }
+        if (!is_array($res)) {
+            $this->activeUser = '';
+            return false;
+        }
+
+        // Perform trimming here before the hashing
+        $password = trim($password, "\r\n");
+        $res[$this->options['passwordcol']] = trim($res[$this->options['passwordcol']], "\r\n");
+        // If using Challenge Response md5 the pass with the secret
+        if ($isChallengeResponse) {
+            $res[$this->options['passwordcol']] =
+                md5($res[$this->options['passwordcol']].$this->_auth_obj->session['loginchallenege']);
+            // UGLY cannot avoid without modifying verifyPassword
+            if ($this->options['cryptType'] == 'md5') {
+                $res[$this->options['passwordcol']] = md5($res[$this->options['passwordcol']]);
+            }
+        }
+        if ($this->verifyPassword($password,
+                                  $res[$this->options['passwordcol']],
+                                  $this->options['cryptType'])) {
+            // Store additional field values in the session
+            foreach ($res as $key => $value) {
+                if ($key == $this->options['passwordcol'] ||
+                    $key == $this->options['usernamecol']) {
+                    continue;
+                }
+
+                $this->log('Storing additional field: '.$key, AUTH_LOG_DEBUG);
+
+                // Use reference to the auth object if exists
+                // This is because the auth session variable can change so a static call to setAuthData does not make sense
+                $this->_auth_obj->setAuthData($key, $value);
+            }
+            return true;
+        }
+
+        $this->activeUser = $res[$this->options['usernamecol']];
+        return false;
+    }
+
+    // }}}
+    // {{{ listUsers()
+
+    /**
+     * Returns a list of users from the container
+     *
+     * @return mixed array|PEAR_Error
+     * @access public
+     */
+    function listUsers()
+    {
+        $this->log('Auth_Container_MDB2::listUsers() called.', AUTH_LOG_DEBUG);
+        $err = $this->_prepare();
+        if ($err !== true) {
+            return PEAR::raiseError($err->getMessage(), $err->getCode());
+        }
+
+        $retVal = array();
+
+        //Check if db_fields contains a *, if so assume all columns are selected
+        if (   is_string($this->options['db_fields'])
+            && strstr($this->options['db_fields'], '*')) {
+            $sql_from = '*';
+        } else {
+            $sql_from = $this->options['final_usernamecol'].
+                ", ".$this->options['final_passwordcol'];
+
+            if (strlen($fields = $this->_quoteDBFields()) > 0) {
+                $sql_from .= ', '.$fields;
+            }
+        }
+
+        $query = sprintf('SELECT %s FROM %s',
+                         $sql_from,
+                         $this->options['final_table']
+                         );
+
+        // check if there is an optional parameter db_where
+        if ($this->options['db_where'] != '') {
+            // there is one, so add it to the query
+            $query .= " WHERE ".$this->options['db_where'];
+        }
+
+        $this->log('Running SQL against MDB2: '.$query, AUTH_LOG_DEBUG);
+
+        $res = $this->db->queryAll($query, null, MDB2_FETCHMODE_ASSOC);
+        if (MDB2::isError($res)) {
+            return PEAR::raiseError($res->getMessage(), $res->getCode());
+        } else {
+            foreach ($res as $user) {
+                $user['username'] = $user[$this->options['usernamecol']];
+                $retVal[] = $user;
+            }
+        }
+        $this->log('Found '.count($retVal).' users.', AUTH_LOG_DEBUG);
+        return $retVal;
+    }
+
+    // }}}
+    // {{{ addUser()
+
+    /**
+     * Add user to the storage container
+     *
+     * @access public
+     * @param  string Username
+     * @param  string Password
+     * @param  mixed  Additional information that are stored in the DB
+     *
+     * @return mixed True on success, otherwise error object
+     */
+    function addUser($username, $password, $additional = "")
+    {
+        $this->log('Auth_Container_MDB2::addUser() called.', AUTH_LOG_DEBUG);
+
+        // Prepare for a database query
+        $err = $this->_prepare();
+        if ($err !== true) {
+            return PEAR::raiseError($err->getMessage(), $err->getCode());
+        }
+
+        if (isset($this->options['cryptType']) && $this->options['cryptType'] == 'none') {
+            $cryptFunction = 'strval';
+        } elseif (isset($this->options['cryptType']) && function_exists($this->options['cryptType'])) {
+            $cryptFunction = $this->options['cryptType'];
+        } else {
+            $cryptFunction = 'md5';
+        }
+
+        $password = $cryptFunction($password);
+
+        $additional_key   = '';
+        $additional_value = '';
+
+        if (is_array($additional)) {
+            foreach ($additional as $key => $value) {
+                if ($this->options['auto_quote']) {
+                    $additional_key   .= ', ' . $this->db->quoteIdentifier($key, true);
+                } else {
+                    $additional_key   .= ', ' . $key;
+                }
+                $additional_value .= ', ' . $this->db->quote($value, 'text');
+            }
+        }
+
+        $query = sprintf("INSERT INTO %s (%s, %s%s) VALUES (%s, %s%s)",
+                         $this->options['final_table'],
+                         $this->options['final_usernamecol'],
+                         $this->options['final_passwordcol'],
+                         $additional_key,
+                         $this->db->quote($username, 'text'),
+                         $this->db->quote($password, 'text'),
+                         $additional_value
+                         );
+
+        $this->log('Running SQL against MDB2: '.$query, AUTH_LOG_DEBUG);
+
+        $res = $this->query($query);
+
+        if (MDB2::isError($res)) {
+            return PEAR::raiseError($res->getMessage(), $res->code);
+        }
+        return true;
+    }
+
+    // }}}
+    // {{{ removeUser()
+
+    /**
+     * Remove user from the storage container
+     *
+     * @access public
+     * @param  string Username
+     *
+     * @return mixed True on success, otherwise error object
+     */
+    function removeUser($username)
+    {
+        $this->log('Auth_Container_MDB2::removeUser() called.', AUTH_LOG_DEBUG);
+        // Prepare for a database query
+        $err = $this->_prepare();
+        if ($err !== true) {
+            return PEAR::raiseError($err->getMessage(), $err->getCode());
+        }
+
+        $query = sprintf("DELETE FROM %s WHERE %s = %s",
+                         $this->options['final_table'],
+                         $this->options['final_usernamecol'],
+                         $this->db->quote($username, 'text')
+                         );
+
+        // check if there is an optional parameter db_where
+        if ($this->options['db_where'] != '') {
+            // there is one, so add it to the query
+            $query .= " AND ".$this->options['db_where'];
+        }
+
+        $this->log('Running SQL against MDB2: '.$query, AUTH_LOG_DEBUG);
+
+        $res = $this->query($query);
+
+        if (MDB2::isError($res)) {
+            return PEAR::raiseError($res->getMessage(), $res->code);
+        }
+        return true;
+    }
+
+    // }}}
+    // {{{ changePassword()
+
+    /**
+     * Change password for user in the storage container
+     *
+     * @param string Username
+     * @param string The new password (plain text)
+     */
+    function changePassword($username, $password)
+    {
+        $this->log('Auth_Container_MDB2::changePassword() called.', AUTH_LOG_DEBUG);
+        // Prepare for a database query
+        $err = $this->_prepare();
+        if ($err !== true) {
+            return PEAR::raiseError($err->getMessage(), $err->getCode());
+        }
+
+        if (isset($this->options['cryptType']) && $this->options['cryptType'] == 'none') {
+            $cryptFunction = 'strval';
+        } elseif (isset($this->options['cryptType']) && function_exists($this->options['cryptType'])) {
+            $cryptFunction = $this->options['cryptType'];
+        } else {
+            $cryptFunction = 'md5';
+        }
+
+        $password = $cryptFunction($password);
+
+        $query = sprintf("UPDATE %s SET %s = %s WHERE %s = %s",
+                         $this->options['final_table'],
+                         $this->options['final_passwordcol'],
+                         $this->db->quote($password, 'text'),
+                         $this->options['final_usernamecol'],
+                         $this->db->quote($username, 'text')
+                         );
+
+        // check if there is an optional parameter db_where
+        if ($this->options['db_where'] != '') {
+            // there is one, so add it to the query
+            $query .= " AND ".$this->options['db_where'];
+        }
+
+        $this->log('Running SQL against MDB2: '.$query, AUTH_LOG_DEBUG);
+
+        $res = $this->query($query);
+
+        if (MDB2::isError($res)) {
+            return PEAR::raiseError($res->getMessage(), $res->code);
+        }
+        return true;
+    }
+
+    // }}}
+    // {{{ supportsChallengeResponse()
+
+    /**
+     * Determine if this container supports
+     * password authentication with challenge response
+     *
+     * @return bool
+     * @access public
+     */
+    function supportsChallengeResponse()
+    {
+        return in_array($this->options['cryptType'], array('md5', 'none', ''));
+    }
+
+    // }}}
+    // {{{ getCryptType()
+
+    /**
+     * Returns the selected crypt type for this container
+     *
+     * @return string Function used to crypt the password
+     */
+    function getCryptType()
+    {
+        return $this->options['cryptType'];
+    }
+
+    // }}}
+
+}
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/Multiple.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/Multiple.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/Multiple.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,188 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
+
+/**
+ * Storage driver for using multiple storage drivers in a fall through fashion
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.01 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license at php.net so we can mail you a copy immediately.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    CVS: $Id: Multiple.php 289653 2009-10-15 04:50:43Z aashley $
+ * @since      File available since Release 1.5.0
+ */
+
+/**
+ * Include Auth_Container base class
+ */
+require_once "Auth/Container.php";
+/**
+ * Include PEAR package for error handling
+ */
+require_once "PEAR.php";
+
+/**
+ * Storage driver for using multiple storage drivers in a fall through fashion
+ *
+ * This storage driver provides a mechanism for working through multiple
+ * storage drivers until either one allows successful login or the list is
+ * exhausted.
+ *
+ * This container takes an array of options of the following form:
+ *
+ * array(
+ *   array(
+ *     'type'    => <standard container type name>,
+ *     'options' => <normal array of options for container>,
+ *   ),
+ * );
+ *
+ * Full example:
+ *
+ * $options = array(
+ *   array(
+ *     'type'    => 'DB',
+ *     'options' => array(
+ *       'dsn' => "mysql://user:password@localhost/database",
+ *     ),
+ *   ),
+ *   array(
+ *     'type'    => 'Array',
+ *     'options' => array(
+ *       'cryptType' => 'md5',
+ *       'users'     => array(
+ *         'admin' => md5('password'),
+ *       ),
+ *     ),
+ *   ),
+ * );
+ *
+ * $auth = new Auth('Multiple', $options);
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    Release: 1.6.2  File: $Revision: 289653 $
+ * @since      File available since Release 1.5.0
+ */
+
+class Auth_Container_Multiple extends Auth_Container {
+
+    // {{{ properties
+
+    /**
+     * The options for each container
+     *
+     * @var array $options
+     */
+    var $options = array();
+
+    /**
+     * The instanciated containers
+     *
+     * @var array $containers
+     */
+    var $containers = array();
+
+    // }}}
+    // {{{ Auth_Container_Multiple()
+
+    /**
+     * Constructor for Array Container
+     *
+     * @param array $data Options for the container
+     * @return void
+     */
+    function Auth_Container_Multiple($options)
+    {
+        if (!is_array($options)) {
+            PEAR::raiseError('The options for Auth_Container_Multiple must be an array');
+        }
+        if (count($options) < 1) {
+            PEAR::raiseError('You must define at least one sub container to use in Auth_Container_Multiple');
+        }
+        foreach ($options as $option) {
+            if (!isset($option['type'])) {
+                PEAR::raiseError('No type defined for sub container');
+            }
+        }
+        $this->options = $options;
+    }
+
+    // }}}
+    // {{{ fetchData()
+
+    /**
+     * Get user information from array
+     *
+     * This function uses the given username to fetch the corresponding
+     * login data from the array. If an account that matches the passed
+     * username and password is found, the function returns true.
+     * Otherwise it returns false.
+     *
+     * @param  string Username
+     * @param  string Password
+     * @return boolean|PEAR_Error Error object or boolean
+     */
+    function fetchData($user, $pass)
+    {
+        $this->log('Auth_Container_Multiple::fetchData() called.', AUTH_LOG_DEBUG);
+
+        foreach ($this->options as $key => $options) {
+
+            $this->log('Using Container '.$key.' of type '.$options['type'].'.', AUTH_LOG_DEBUG);
+
+            if (isset($this->containers[$key]) && is_a($this->containers[$key], 'Auth_Container')) {
+
+                $container = &$this->containers[$key];
+
+            } else {
+
+                $this->containers[$key] = &$this->_auth_obj->_factory($options['type'], $options['options']);
+                $this->containers[$key]->_auth_obj = &$this->_auth_obj;
+                $container = &$this->containers[$key];
+
+            }
+
+            $result = $container->fetchData($user, $pass);
+
+            if (PEAR::isError($result)) {
+
+                $this->log('Container '.$key.': '.$result->getMessage(), AUTH_LOG_DEBUG);
+                return $result;
+
+            } elseif ($result == true) {
+
+                $this->log('Container '.$key.': Authentication successful.', AUTH_LOG_DEBUG);
+                return true;
+
+            } else {
+
+                $this->log('Container '.$key.': Authentication failed.', AUTH_LOG_DEBUG);
+
+            }
+
+        }
+
+        $this->log('Auth_Container_Multiple: All containers rejected user credentials.', AUTH_LOG_DEBUG);
+
+        return false;
+
+    }
+
+    // }}}
+
+}
+
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/NetVPOPMaild.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/NetVPOPMaild.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/NetVPOPMaild.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,129 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
+
+/**
+ * Storage driver for use with a Vpopmaild server
+ *
+ * PHP versions 5
+ *
+ * LICENSE: This source file is subject to version 3.01 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license at php.net so we can mail you a copy immediately.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Bill Shupp <hostmaster at shupp.org>
+ * @author     Stefan Ekman <stekman at sedata.org>
+ * @author     Martin Jansen <mj at php.net>
+ * @author     Mika Tuupola <tuupola at appelsiini.net>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @link       http://pear.php.net/package/Auth
+ * @since      File available since Release 1.2.0
+ */
+
+/**
+ * Include Auth_Container base class
+ */
+require_once 'Auth/Container.php';
+/**
+ * Include PEAR package for error handling
+ */
+require_once 'PEAR.php';
+/**
+ * Include PEAR Net_Vpopmaild package
+ */
+require_once 'Net/Vpopmaild.php';
+
+/**
+ * Storage driver for Authentication on a Vpopmaild server.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Martin Jansen <mj at php.net>
+ * @author     Mika Tuupola <tuupola at appelsiini.net>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    Release: 1.5.4  File: $Revision: 256741 $
+ * @link       http://pear.php.net/package/Auth
+ * @since      Class available since Release 1.6.0
+ */
+class Auth_Container_Vpopmaild extends Auth_Container
+{
+
+    /**
+     * Vpopmaild Server
+     * @var string
+     */
+    var $server = 'localhost';
+
+    /**
+     * Vpopmaild Server port
+     * @var string
+     */
+    var $port = 89;
+
+    /**
+     * Constructor of the container class
+     *
+     * @param  $server string server or server:port combination
+     * @return object Returns an error object if something went wrong
+     */
+    function Auth_Container_Vpopmaild($server=null)
+    {
+        if (isset($server) && !is_null($server)) {
+            if (is_array($server)) {
+                if (isset($server['host'])) {
+                    $this->server = $server['host'];
+                }
+                if (isset($server['port'])) {
+                    $this->port = $server['port'];
+                }
+            } else {
+                if (strstr($server, ':')) {
+                    $serverparts = explode(':', trim($server));
+                    $this->server = $serverparts[0];
+                    $this->port   = $serverparts[1];
+                } else {
+                    $this->server = $server;
+                }
+            }
+        }
+    }
+
+    /**
+     * fetchData()
+     *
+     * Try to login to the Vpopmaild server
+     *
+     * @param  string username
+     * @param  string password
+     *
+     * @return boolean
+     */
+    function fetchData($username, $password)
+    {
+        $this->log('Auth_Container_Vpopmaild::fetchData() called.', AUTH_LOG_DEBUG);
+        $vpopmaild =& new Net_Vpopmaild();
+        // Connect
+        try {
+            $res = $vpopmaild->connect($this->server, $this->port, $this->method);
+        } catch (Net_Vpopmaild_FatalException $e) {
+            $this->log('Connection to Vpopmaild server failed.', AUTH_LOG_DEBUG);
+            return PEAR::raiseError($e->getMessage(), $e->getCode());
+        }
+        // Authenticate
+        try {
+            $result = $vpopmaild->clogin($username, $password);
+            $vpopmaild->quit();
+        } catch (Net_Vpopmaild_Exception $e) {
+            return PEAR::raiseError($e->getMessage(), $e->getCode());
+        }
+        return $result;
+    }
+}
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/PEAR.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/PEAR.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/PEAR.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,165 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
+
+/**
+ * Storage driver for use against PEAR website
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.01 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license at php.net so we can mail you a copy immediately.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Yavor Shahpasov <yavo at netsmart.com.cy>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    CVS: $Id: PEAR.php 289652 2009-10-15 04:42:18Z aashley $
+ * @link       http://pear.php.net/package/Auth
+ * @since      File available since Release 1.3.0
+ */
+
+/**
+ * Include PEAR HTTP_Client.
+ */
+require_once 'HTTP/Client.php';
+/**
+ * Include Auth_Container base class
+ */
+require_once 'Auth/Container.php';
+
+/**
+ * Storage driver for authenticating against PEAR website
+ *
+ * This driver provides a method for authenticating against the pear.php.net
+ * authentication system.
+ *
+ * Supports two options:
+ * - "url": The base URL with schema to authenticate against
+ * - "karma": An array of karma levels which the user needs one of.
+ *            When empty, no karma level is required.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Yavor Shahpasov <yavo at netsmart.com.cy>
+ * @author     Adam Ashley <aashley at php.net>
+ * @author     Adam Harvey <aharvey at php.net>
+ * @copyright  2001-2007 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    Release: 1.6.2  File: $Revision: 289652 $
+ * @link       http://pear.php.net/package/Auth
+ * @since      Class available since Release 1.3.0
+ */
+class Auth_Container_Pear extends Auth_Container
+{
+    // {{{ properties
+
+    /**
+     * URL to connect to, with schema
+     *
+     * @var string
+     */
+    var $url = 'https://pear.php.net/rest-login.php/';
+
+    /**
+     * Array of karma levels the user can have.
+     * A user needs only one of the levels to succeed login.
+     * No levels mean that only username and password need to match
+     *
+     * @var array
+     */
+    var $karma = array();
+
+    // }}}
+    // {{{ Auth_Container_Pear() [constructor]
+
+    /**
+     * Constructor
+     *
+     * Accepts options "url" and "karma", see class docs.
+     *
+     * @param array $data Array of options
+     *
+     * @return void
+     */
+    function Auth_Container_Pear($data = null)
+    {
+        if (!is_array($data)) {
+            PEAR::raiseError('The options for Auth_Container_Pear must be an array');
+        }
+        if (isset($data['karma'])) {
+            if (is_array($data['karma'])) {
+                $this->karma = $data['karma'];
+            } else {
+                $this->karma = array($data['karma']);
+            }
+        }
+
+        if (isset($data['url'])) {
+            $this->url = $data['url'];
+        }
+    }
+
+    // }}}
+    // {{{ fetchData()
+
+    /**
+     * Get user information from pear.php.net
+     *
+     * This function uses the given username and password to authenticate
+     * against the pear.php.net website
+     *
+     * @param string    Username
+     * @param string    Password
+     * @return mixed    Error object or boolean
+     */
+    function fetchData($username, $password)
+    {
+        $this->log('Auth_Container_PEAR::fetchData() called.', AUTH_LOG_DEBUG);
+
+        $client = new HTTP_Client;
+
+        $this->log('Auth_Container_PEAR::fetchData() getting salt.', AUTH_LOG_DEBUG);
+        $code = $client->get($this->url . '/getsalt');
+        if ($code instanceof PEAR_Error) {
+            return $code;
+        }
+        if ($code != 200) {
+            return PEAR::raiseError('Bad response to salt request.', $code);
+        }
+        $resp = $client->currentResponse();
+        $salt = $resp['body'];
+
+        $this->log('Auth_Container_PEAR::fetchData() calling validate.', AUTH_LOG_DEBUG);
+        $postOptions = array(
+            'username' => $username,
+            'password' => md5($salt . md5($password))
+        );
+        if (is_array($this->karma) && count($this->karma) > 0) {
+            $postOptions['karma'] = implode(',', $this->karma);
+        }
+
+        $code = $client->post($this->url . '/validate', $postOptions);
+        if ($code instanceof PEAR_Error) {
+            return $code;
+        }
+        if ($code != 200) {
+            return PEAR::raiseError('Bad response to validate request.', $code);
+        }
+        $resp = $client->currentResponse();
+
+        list($code, $message) = explode(' ', $resp['body'], 2);
+        if ($code != 8) {
+            return PEAR::raiseError($message, $code);
+        }
+        return true;
+    }
+
+    // }}}
+
+}
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/POP3.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/POP3.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/POP3.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,145 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
+
+/**
+ * Storage driver for use against a POP3 server
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.01 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license at php.net so we can mail you a copy immediately.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Stefan Ekman <stekman at sedata.org>
+ * @author     Martin Jansen <mj at php.net>
+ * @author     Mika Tuupola <tuupola at appelsiini.net>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    CVS: $Id: POP3.php 237449 2007-06-12 03:11:27Z aashley $
+ * @link       http://pear.php.net/package/Auth
+ * @since      File available since Release 1.2.0
+ */
+
+/**
+ * Include Auth_Container base class
+ */
+require_once 'Auth/Container.php';
+/**
+ * Include PEAR package for error handling
+ */
+require_once 'PEAR.php';
+/**
+ * Include PEAR Net_POP3 package
+ */
+require_once 'Net/POP3.php';
+
+/**
+ * Storage driver for Authentication on a POP3 server.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Martin Jansen <mj at php.net>
+ * @author     Mika Tuupola <tuupola at appelsiini.net>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    Release: 1.6.2  File: $Revision: 237449 $
+ * @link       http://pear.php.net/package/Auth
+ * @since      Class available since Release 1.2.0
+ */
+class Auth_Container_POP3 extends Auth_Container
+{
+
+    // {{{ properties
+
+    /**
+     * POP3 Server
+     * @var string
+     */
+    var $server='localhost';
+
+    /**
+     * POP3 Server port
+     * @var string
+     */
+    var $port='110';
+
+    /**
+     * POP3 Authentication method
+     *
+     * Prefered POP3 authentication method. Acceptable values:
+     *      Boolean TRUE    - Use Net_POP3's autodetection
+     *      String 'DIGEST-MD5','CRAM-MD5','LOGIN','PLAIN','APOP','USER'
+     *                      - Attempt this authentication style first
+     *                        then fallback to autodetection.
+     * @var mixed
+     */
+    var $method=true;
+
+    // }}}
+    // {{{ Auth_Container_POP3() [constructor]
+
+    /**
+     * Constructor of the container class
+     *
+     * @param  $server string server or server:port combination
+     * @return object Returns an error object if something went wrong
+     */
+    function Auth_Container_POP3($server=null)
+    {
+        if (isset($server) && !is_null($server)) {
+            if (is_array($server)) {
+                if (isset($server['host'])) {
+                    $this->server = $server['host'];
+                }
+                if (isset($server['port'])) {
+                    $this->port = $server['port'];
+                }
+                if (isset($server['method'])) {
+                    $this->method = $server['method'];
+                }
+            } else {
+                if (strstr($server, ':')) {
+                    $serverparts = explode(':', trim($server));
+                    $this->server = $serverparts[0];
+                    $this->port = $serverparts[1];
+                } else {
+                    $this->server = $server;
+                }
+            }
+        }
+    }
+
+    // }}}
+    // {{{ fetchData()
+
+    /**
+     * Try to login to the POP3 server
+     *
+     * @param   string Username
+     * @param   string Password
+     * @return  boolean
+     */
+    function fetchData($username, $password)
+    {
+        $this->log('Auth_Container_POP3::fetchData() called.', AUTH_LOG_DEBUG);
+        $pop3 =& new Net_POP3();
+        $res = $pop3->connect($this->server, $this->port, $this->method);
+        if (!$res) {
+            $this->log('Connection to POP3 server failed.', AUTH_LOG_DEBUG);
+            return $res;
+        }
+        $result = $pop3->login($username, $password);
+        $pop3->disconnect();
+        return $result;
+    }
+
+    // }}}
+
+}
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/RADIUS.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/RADIUS.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/RADIUS.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,182 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
+
+/**
+ * Storage driver for use against RADIUS servers
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.01 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license at php.net so we can mail you a copy immediately.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Michael Bretterklieber <michael at bretterklieber.com>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    CVS: $Id: RADIUS.php 237449 2007-06-12 03:11:27Z aashley $
+ * @link       http://pear.php.net/package/Auth
+ * @since      File available since Release 1.2.0
+ */
+
+/**
+ * Include Auth_Container base class
+ */
+require_once "Auth/Container.php";
+/**
+ * Include PEAR Auth_RADIUS package
+ */
+require_once "Auth/RADIUS.php";
+
+/**
+ * Storage driver for authenticating users against RADIUS servers.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Michael Bretterklieber <michael at bretterklieber.com>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    Release: 1.6.2  File: $Revision: 237449 $
+ * @link       http://pear.php.net/package/Auth
+ * @since      Class available since Release 1.2.0
+ */
+class Auth_Container_RADIUS extends Auth_Container
+{
+
+    // {{{ properties
+
+    /**
+     * Contains a RADIUS object
+     * @var object
+     */
+    var $radius;
+
+    /**
+     * Contains the authentication type
+     * @var string
+     */
+    var $authtype;
+
+    // }}}
+    // {{{ Auth_Container_RADIUS() [constructor]
+
+    /**
+     * Constructor of the container class.
+     *
+     * $options can have these keys:
+     * 'servers'    an array containing an array: servername, port,
+     *              sharedsecret, timeout, maxtries
+     * 'configfile' The filename of the configuration file
+     * 'authtype'   The type of authentication, one of: PAP, CHAP_MD5,
+     *              MSCHAPv1, MSCHAPv2, default is PAP
+     *
+     * @param  $options associative array
+     * @return object Returns an error object if something went wrong
+     */
+    function Auth_Container_RADIUS($options)
+    {
+        $this->authtype = 'PAP';
+        if (isset($options['authtype'])) {
+            $this->authtype = $options['authtype'];
+        }
+        $classname = 'Auth_RADIUS_' . $this->authtype;
+        if (!class_exists($classname)) {
+            PEAR::raiseError("Unknown Authtype, please use one of: "
+                    ."PAP, CHAP_MD5, MSCHAPv1, MSCHAPv2!", 41, PEAR_ERROR_DIE);
+        }
+
+        $this->radius = new $classname;
+
+        if (isset($options['configfile'])) {
+            $this->radius->setConfigfile($options['configfile']);
+        }
+
+        $servers = $options['servers'];
+        if (is_array($servers)) {
+            foreach ($servers as $server) {
+                $servername     = $server[0];
+                $port           = isset($server[1]) ? $server[1] : 0;
+                $sharedsecret   = isset($server[2]) ? $server[2] : 'testing123';
+                $timeout        = isset($server[3]) ? $server[3] : 3;
+                $maxtries       = isset($server[4]) ? $server[4] : 3;
+                $this->radius->addServer($servername, $port, $sharedsecret, $timeout, $maxtries);
+            }
+        }
+
+        if (!$this->radius->start()) {
+            PEAR::raiseError($this->radius->getError(), 41, PEAR_ERROR_DIE);
+        }
+    }
+
+    // }}}
+    // {{{ fetchData()
+
+    /**
+     * Authenticate
+     *
+     * @param  string Username
+     * @param  string Password
+     * @return bool   true on success, false on reject
+     */
+    function fetchData($username, $password, $challenge = null)
+    {
+        $this->log('Auth_Container_RADIUS::fetchData() called.', AUTH_LOG_DEBUG);
+
+        switch($this->authtype) {
+            case 'CHAP_MD5':
+            case 'MSCHAPv1':
+                if (isset($challenge)) {
+                    $this->radius->challenge = $challenge;
+                    $this->radius->chapid    = 1;
+                    $this->radius->response  = pack('H*', $password);
+                } else {
+                    require_once 'Crypt/CHAP.php';
+                    $classname = 'Crypt_' . $this->authtype;
+                    $crpt = new $classname;
+                    $crpt->password = $password;
+                    $this->radius->challenge = $crpt->challenge;
+                    $this->radius->chapid    = $crpt->chapid;
+                    $this->radius->response  = $crpt->challengeResponse();
+                }
+                break;
+
+            case 'MSCHAPv2':
+                require_once 'Crypt/CHAP.php';
+                $crpt = new Crypt_MSCHAPv2;
+                $crpt->username = $username;
+                $crpt->password = $password;
+                $this->radius->challenge     = $crpt->authChallenge;
+                $this->radius->peerChallenge = $crpt->peerChallenge;
+                $this->radius->chapid        = $crpt->chapid;
+                $this->radius->response      = $crpt->challengeResponse();
+                break;
+
+            default:
+                $this->radius->password = $password;
+                break;
+        }
+
+        $this->radius->username = $username;
+
+        $this->radius->putAuthAttributes();
+        $result = $this->radius->send();
+        if (PEAR::isError($result)) {
+            return false;
+        }
+
+        $this->radius->getAttributes();
+//      just for debugging
+//      $this->radius->dumpAttributes();
+
+        return $result;
+    }
+
+    // }}}
+
+}
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/SAP.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/SAP.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/SAP.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,179 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
+
+/**
+ * Storage driver for use against a SAP system using the SAPRFC PHP extension.
+ *
+ * Requires the SAPRFC ext available at http://saprfc.sourceforge.net/
+ *
+ * PHP version 5
+ *
+ * LICENSE: This source file is subject to version 3.01 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license at php.net so we can mail you a copy immediately.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Stoyan Stefanov <ssttoo at gmail.com>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    CVS: $Id: SAP.php 289654 2009-10-15 04:52:48Z aashley $
+ * @link       http://pear.php.net/package/Auth
+ * @since      File available since Release 1.4.0
+ */
+
+/**
+ * Include Auth_Container base class
+ */
+require_once 'Auth/Container.php';
+/**
+ * Include PEAR for error handling
+ */
+require_once 'PEAR.php';
+
+/**
+ * Performs authentication against a SAP system using the SAPRFC PHP extension.
+ *
+ * When the option GETSSO2 is TRUE (default)
+ * the Single Sign-On (SSO) ticket is retrieved
+ * and stored as an Auth attribute called 'sap'
+ * in order to be reused for consecutive connections.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Stoyan Stefanov <ssttoo at gmail.com>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    Release: 1.6.2  File: $Revision: 289654 $
+ * @since      Class available since Release 1.4.0
+ */
+class Auth_Container_SAP extends Auth_Container {
+
+    // {{{ properties
+
+    /**
+     * @var array Default options
+     */
+    var $options = array(
+        'CLIENT'    => '000',
+        'LANG'      => 'EN',
+        'GETSSO2'   => true,
+    );
+
+    // }}}
+    // {{{ Auth_Container_SAP()
+
+    /**
+     * Class constructor. Checks that required options
+     * are present and that the SAPRFC extension is loaded
+     *
+     * Options that can be passed and their defaults:
+     * <pre>
+     * array(
+     *   'ASHOST' => "",
+     *   'SYSNR'  => "",
+     *   'CLIENT' => "000",
+     *   'GWHOST' =>"",
+     *   'GWSERV' =>"",
+     *   'MSHOST' =>"",
+     *   'R3NAME' =>"",
+     *   'GROUP'  =>"",
+     *   'LANG'   =>"EN",
+     *   'TRACE'  =>"",
+     *   'GETSSO2'=> true
+     * )
+     * </pre>
+     *
+     * @param array array of options.
+     * @return void
+     */
+    function Auth_Container_SAP($options)
+    {
+        $saprfc_loaded = PEAR::loadExtension('saprfc');
+        if (!$saprfc_loaded) {
+            return PEAR::raiseError('Cannot use SAP authentication, '
+                    .'SAPRFC extension not loaded!');
+        }
+        if (empty($options['R3NAME']) && empty($options['ASHOST'])) {
+            return PEAR::raiseError('R3NAME or ASHOST required for authentication');
+        }
+        $this->options = array_merge($this->options, $options);
+    }
+
+    // }}}
+    // {{{ fetchData()
+
+    /**
+     * Performs username and password check
+     *
+     * @param string Username
+     * @param string Password
+     * @return boolean TRUE on success (valid user), FALSE otherwise
+     */
+    function fetchData($username, $password)
+    {
+        $this->log('Auth_Container_SAP::fetchData() called.', AUTH_LOG_DEBUG);
+        $connection_options = $this->options;
+        $connection_options['USER'] = $username;
+        $connection_options['PASSWD'] = $password;
+        $rfc = saprfc_open($connection_options);
+        if (!$rfc) {
+            $message = "Couldn't connect to the SAP system.";
+            $error = $this->getError();
+            if ($error['message']) {
+                $message .= ': ' . $error['message'];
+            }
+            PEAR::raiseError($message, null, null, null, @$error['all']);
+            return false;
+        } else {
+            if (!empty($this->options['GETSSO2'])) {
+                $this->log('Attempting to retrieve SSO2 ticket.', AUTH_LOG_DEBUG);
+                if ($ticket = @saprfc_get_ticket($rfc)) {
+                    $this->options['MYSAPSSO2'] = $ticket;
+                    unset($this->options['GETSSO2']);
+                    $this->_auth_obj->setAuthData('sap', $this->options);
+                } else {
+                    PEAR::raiseError("SSO ticket retrieval failed");
+                }
+            }
+            @saprfc_close($rfc);
+            return true;
+        }
+
+    }
+
+    // }}}
+    // {{{ getError()
+
+    /**
+     * Retrieves the last error from the SAP connection
+     * and returns it as an array.
+     *
+     * @return array Array of error information
+     */
+    function getError()
+    {
+
+        $error = array();
+        $sap_error = saprfc_error();
+        if (empty($err)) {
+            return $error;
+        }
+        $err = explode("n", $sap_error);
+        foreach ($err AS $line) {
+            $item = split(':', $line);
+            $error[strtolower(trim($item[0]))] = trim($item[1]);
+        }
+        $error['all'] = $sap_error;
+        return $error;
+    }
+
+    // }}}
+
+}
+
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/SMBPasswd.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/SMBPasswd.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/SMBPasswd.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,182 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
+
+/**
+ * Storage driver for use against Samba password files
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.01 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license at php.net so we can mail you a copy immediately.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Michael Bretterklieber <michael at bretterklieber.com>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    CVS: $Id: SMBPasswd.php 237449 2007-06-12 03:11:27Z aashley $
+ * @link       http://pear.php.net/package/Auth
+ * @since      File available since Release 1.2.3
+ */
+
+/**
+ * Include PEAR File_SMBPasswd
+ */
+require_once "File/SMBPasswd.php";
+/**
+ * Include Auth_Container Base file
+ */
+require_once "Auth/Container.php";
+/**
+ * Include PEAR class for error handling
+ */
+require_once "PEAR.php";
+
+/**
+ * Storage driver for fetching login data from an SAMBA smbpasswd file.
+ *
+ * This storage container can handle SAMBA smbpasswd files.
+ *
+ * Example:
+ * $a = new Auth("SMBPasswd", '/usr/local/private/smbpasswd');
+ * $a->start();
+ * if ($a->getAuth()) {
+ *     printf ("AUTH OK<br>\n");
+ *     $a->logout();
+ * }
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Michael Bretterklieber <michael at bretterklieber.com>
+ * @author     Adam Ashley <aashley at php.net>
+ * @package    Auth
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    Release: 1.6.2  File: $Revision: 237449 $
+ * @link       http://pear.php.net/package/Auth
+ * @since      Class available since Release 1.2.3
+ */
+class Auth_Container_SMBPasswd extends Auth_Container
+{
+
+    // {{{ properties
+
+    /**
+     * File_SMBPasswd object
+     * @var object
+     */
+    var $pwfile;
+
+    // }}}
+
+    // {{{ Auth_Container_SMBPasswd() [constructor]
+
+    /**
+     * Constructor of the container class
+     *
+     * @param  $filename   string filename for a passwd type file
+     * @return object Returns an error object if something went wrong
+     */
+    function Auth_Container_SMBPasswd($filename)
+    {
+        $this->pwfile = new File_SMBPasswd($filename,0);
+
+        if (!$this->pwfile->load()) {
+            PEAR::raiseError("Error while reading file contents.", 41, PEAR_ERROR_DIE);
+            return;
+        }
+
+    }
+
+    // }}}
+    // {{{ fetchData()
+
+    /**
+     * Get user information from pwfile
+     *
+     * @param   string Username
+     * @param   string Password
+     * @return  boolean
+     */
+    function fetchData($username, $password)
+    {
+        $this->log('Auth_Container_SMBPasswd::fetchData() called.', AUTH_LOG_DEBUG);
+        return $this->pwfile->verifyAccount($username, $password);
+    }
+
+    // }}}
+    // {{{ listUsers()
+
+    function listUsers()
+    {
+        $this->log('Auth_Container_SMBPasswd::fetchData() called.', AUTH_LOG_DEBUG);
+        return $this->pwfile->getAccounts();
+    }
+
+    // }}}
+    // {{{ addUser()
+
+    /**
+     * Add a new user to the storage container
+     *
+     * @param string Username
+     * @param string Password
+     * @param array  Additional information
+     *
+     * @return boolean
+     */
+    function addUser($username, $password, $additional = '')
+    {
+        $this->log('Auth_Container_SMBPasswd::addUser() called.', AUTH_LOG_DEBUG);
+        $res = $this->pwfile->addUser($user, $additional['userid'], $pass);
+        if ($res === true) {
+            return $this->pwfile->save();
+        }
+        return $res;
+    }
+
+    // }}}
+    // {{{ removeUser()
+
+    /**
+     * Remove user from the storage container
+     *
+     * @param string Username
+     */
+    function removeUser($username)
+    {
+        $this->log('Auth_Container_SMBPasswd::removeUser() called.', AUTH_LOG_DEBUG);
+        $res = $this->pwfile->delUser($username);
+        if ($res === true) {
+            return $this->pwfile->save();
+        }
+        return $res;
+    }
+
+    // }}}
+    // {{{ changePassword()
+
+    /**
+     * Change password for user in the storage container
+     *
+     * @param string Username
+     * @param string The new password
+     */
+    function changePassword($username, $password)
+    {
+        $this->log('Auth_Container_SMBPasswd::changePassword() called.', AUTH_LOG_DEBUG);
+        $res = $this->pwfile->modUser($username, '', $password);
+        if ($res === true) {
+            return $this->pwfile->save();
+        }
+        return $res;
+    }
+
+    // }}}
+
+}
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/SOAP.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/SOAP.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/SOAP.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,229 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
+
+/**
+ * Storage driver for use against a SOAP service
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.01 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license at php.net so we can mail you a copy immediately.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Bruno Pedro <bpedro at co.sapo.pt>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    CVS: $Id: SOAP.php 237449 2007-06-12 03:11:27Z aashley $
+ * @link       http://pear.php.net/package/Auth
+ * @since      File available since Release 1.2.0
+ */
+
+/**
+ * Include Auth_Container base class
+ */
+require_once "Auth/Container.php";
+/**
+ * Include PEAR package for error handling
+ */
+require_once "PEAR.php";
+/**
+ * Include PEAR SOAP_Client
+ */
+require_once 'SOAP/Client.php';
+
+/**
+ * Storage driver for fetching login data from SOAP
+ *
+ * This class takes one parameter (options), where
+ * you specify the following fields: endpoint, namespace,
+ * method, encoding, usernamefield and passwordfield.
+ *
+ * You can use specify features of your SOAP service
+ * by providing its parameters in an associative manner by
+ * using the '_features' array through the options parameter.
+ *
+ * The 'matchpassword' option should be set to false if your
+ * webservice doesn't return (username,password) pairs, but
+ * instead returns error when the login is invalid.
+ *
+ * Example usage:
+ *
+ * <?php
+ *
+ * ...
+ *
+ * $options = array (
+ *             'endpoint' => 'http://your.soap.service/endpoint',
+ *             'namespace' => 'urn:/Your/Namespace',
+ *             'method' => 'get',
+ *             'encoding' => 'UTF-8',
+ *             'usernamefield' => 'login',
+ *             'passwordfield' => 'password',
+ *             'matchpasswords' => false,
+ *             '_features' => array (
+ *                             'example_feature' => 'example_value',
+ *                             'another_example'  => ''
+ *                             )
+ *             );
+ * $auth = new Auth('SOAP', $options, 'loginFunction');
+ * $auth->start();
+ *
+ * ...
+ *
+ * ?>
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Bruno Pedro <bpedro at co.sapo.pt>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    Release: 1.6.2  File: $Revision: 237449 $
+ * @link       http://pear.php.net/package/Auth
+ * @since      Class available since Release 1.2.0
+ */
+class Auth_Container_SOAP extends Auth_Container
+{
+
+    // {{{ properties
+
+    /**
+     * Required options for the class
+     * @var array
+     * @access private
+     */
+    var $_requiredOptions = array(
+            'endpoint',
+            'namespace',
+            'method',
+            'encoding',
+            'usernamefield',
+            'passwordfield',
+            );
+
+    /**
+     * Options for the class
+     * @var array
+     * @access private
+     */
+    var $_options = array();
+
+    /**
+     * Optional SOAP features
+     * @var array
+     * @access private
+     */
+    var $_features = array();
+
+    /**
+     * The SOAP response
+     * @var array
+     * @access public
+     */
+     var $soapResponse = array();
+
+    /**
+     * The SOAP client
+     * @var mixed
+     * @access public
+     */
+     var $soapClient = null;
+
+    // }}}
+    // {{{ Auth_Container_SOAP() [constructor]
+
+    /**
+     * Constructor of the container class
+     *
+     * @param  $options, associative array with endpoint, namespace, method,
+     *                   usernamefield, passwordfield and optional features
+     */
+    function Auth_Container_SOAP($options)
+    {
+        $this->_options = $options;
+        if (!isset($this->_options['matchpasswords'])) {
+            $this->_options['matchpasswords'] = true;
+        }
+        if (!empty($this->_options['_features'])) {
+            $this->_features = $this->_options['_features'];
+            unset($this->_options['_features']);
+        }
+    }
+
+    // }}}
+    // {{{ fetchData()
+
+    /**
+     * Fetch data from SOAP service
+     *
+     * Requests the SOAP service for the given username/password
+     * combination.
+     *
+     * @param  string Username
+     * @param  string Password
+     * @return mixed Returns the SOAP response or false if something went wrong
+     */
+    function fetchData($username, $password)
+    {
+        $this->log('Auth_Container_SOAP::fetchData() called.', AUTH_LOG_DEBUG);
+        // check if all required options are set
+        if (array_intersect($this->_requiredOptions, array_keys($this->_options)) != $this->_requiredOptions) {
+            return false;
+        } else {
+            // create a SOAP client and set encoding
+            $this->soapClient = new SOAP_Client($this->_options['endpoint']);
+            $this->soapClient->setEncoding($this->_options['encoding']);
+        }
+
+        // set the trace option if requested
+        if (isset($this->_options['trace'])) {
+            $this->soapClient->__options['trace'] = true;
+        }
+
+        // set the timeout option if requested
+        if (isset($this->_options['timeout'])) {
+            $this->soapClient->__options['timeout'] = $this->_options['timeout'];
+        }
+
+        // assign username and password fields
+        $usernameField = new SOAP_Value($this->_options['usernamefield'],'string', $username);
+        $passwordField = new SOAP_Value($this->_options['passwordfield'],'string', $password);
+        $SOAPParams = array($usernameField, $passwordField);
+
+        // assign optional features
+        foreach ($this->_features as $fieldName => $fieldValue) {
+            $SOAPParams[] = new SOAP_Value($fieldName, 'string', $fieldValue);
+        }
+
+        // make SOAP call
+        $this->soapResponse = $this->soapClient->call(
+                $this->_options['method'],
+                $SOAPParams,
+                array('namespace' => $this->_options['namespace'])
+                );
+
+        if (!PEAR::isError($this->soapResponse)) {
+            if ($this->_options['matchpasswords']) {
+                // check if passwords match
+                if ($password == $this->soapResponse->{$this->_options['passwordfield']}) {
+                    return true;
+                } else {
+                    return false;
+                }
+            } else {
+                return true;
+            }
+        } else {
+            return false;
+        }
+    }
+
+    // }}}
+
+}
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/SOAP5.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/SOAP5.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/SOAP5.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,268 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
+
+/**
+ * Storage driver for use against a SOAP service using PHP5 SoapClient
+ *
+ * PHP version 5
+ *
+ * LICENSE: This source file is subject to version 3.01 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license at php.net so we can mail you a copy immediately.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Based upon Auth_Container_SOAP by Bruno Pedro <bpedro at co.sapo.pt>
+ * @author     Marcel Oelke <puRe at rednoize.com>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    CVS: $Id: SOAP5.php 238999 2007-07-02 08:25:41Z aashley $
+ * @since      File available since Release 1.4.0
+ */
+
+/**
+ * Include Auth_Container base class
+ */
+require_once "Auth/Container.php";
+/**
+ * Include PEAR package for error handling
+ */
+require_once "PEAR.php";
+
+/**
+ * Storage driver for fetching login data from SOAP using the PHP5 Builtin SOAP
+ * functions. This is a modification of the SOAP Storage driver from Bruno Pedro
+ * thats using the PEAR SOAP Package.
+ *
+ * This class takes one parameter (options), where
+ * you specify the following fields:
+ *  * location and uri, or wsdl file
+ *  * method to call on the SOAP service
+ *  * usernamefield, the name of the parameter where the username is supplied
+ *  * passwordfield, the name of the parameter where the password is supplied
+ *  * matchpassword, whether to look for the password in the response from
+ *                   the function call or assume that no errors means user
+ *                   authenticated.
+ *
+ * See http://www.php.net/manual/en/ref.soap.php for further details
+ * on options for the PHP5 SoapClient which are passed through.
+ *
+ * Example usage without WSDL:
+ *
+ * <?php
+ *
+ * $options = array (
+ *       'wsdl'           => NULL,
+ *       'location'       => 'http://your.soap.service/endpoint',
+ *       'uri'            => 'urn:/Your/Namespace',
+ *       'method'         => 'checkAuth',
+ *       'usernamefield'  => 'username',
+ *       'passwordfield'  => 'password',
+ *       'matchpasswords' => false,
+ *       '_features' => array (
+ *           'extra_parameter'    => 'example_value',
+ *           'another_parameter'  => 'foobar'
+ *       )
+ *   );
+ *
+ * $auth = new Auth('SOAP5', $options);
+ * $auth->start();
+ *
+ * ?>
+ *
+ * Example usage with WSDL:
+ *
+ * <?php
+ *
+ * $options = array (
+ *       'wsdl'           => 'http://your.soap.service/wsdl',
+ *       'method'         => 'checkAuth',
+ *       'usernamefield'  => 'username',
+ *       'passwordfield'  => 'password',
+ *       'matchpasswords' => false,
+ *       '_features' => array (
+ *           'extra_parameter'    => 'example_value',
+ *           'another_parameter'  => 'foobar'
+ *       )
+ *   );
+ *
+ * $auth = new Auth('SOAP5', $options);
+ * $auth->start();
+ *
+ * ?>
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Based upon Auth_Container_SOAP by Bruno Pedro <bpedro at co.sapo.pt>
+ * @author     Marcel Oelke <puRe at rednoize.com>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    Release: 1.6.2  File: $Revision: 238999 $
+ * @since      Class available since Release 1.4.0
+ */
+class Auth_Container_SOAP5 extends Auth_Container
+{
+
+    // {{{ properties
+
+    /**
+     * Required options for the class
+     * @var array
+     * @access private
+     */
+    var $_requiredOptions = array(
+            'location',
+            'uri',
+            'method',
+            'usernamefield',
+            'passwordfield',
+            'wsdl',
+            );
+
+    /**
+     * Options for the class
+     * @var array
+     * @access private
+     */
+    var $_options = array();
+
+    /**
+     * Optional SOAP features
+     * @var array
+     * @access private
+     */
+    var $_features = array();
+
+    /**
+     * The SOAP response
+     * @var array
+     * @access public
+     */
+    var $soapResponse = array();
+
+    // }}}
+    // {{{ Auth_Container_SOAP5()
+
+    /**
+     * Constructor of the container class
+     *
+     * @param  $options, associative array with endpoint, namespace, method,
+     *                   usernamefield, passwordfield and optional features
+     */
+    function Auth_Container_SOAP5($options)
+    {
+        $this->_setDefaults();
+
+        foreach ($options as $name => $value) {
+            $this->_options[$name] = $value;
+        }
+
+        if (!empty($this->_options['_features'])) {
+            $this->_features = $this->_options['_features'];
+            unset($this->_options['_features']);
+        }
+    }
+
+    // }}}
+    // {{{ fetchData()
+
+    /**
+     * Fetch data from SOAP service
+     *
+     * Requests the SOAP service for the given username/password
+     * combination.
+     *
+     * @param  string Username
+     * @param  string Password
+     * @return mixed Returns the SOAP response or false if something went wrong
+     */
+    function fetchData($username, $password)
+    {
+        $this->log('Auth_Container_SOAP5::fetchData() called.', AUTH_LOG_DEBUG);
+        $result = $this->_validateOptions();
+        if (PEAR::isError($result))
+            return $result;
+
+        // create a SOAP client
+        $soapClient = new SoapClient($this->_options["wsdl"], $this->_options);
+
+        $params = array();
+        // first, assign the optional features
+        foreach ($this->_features as $fieldName => $fieldValue) {
+            $params[$fieldName] = $fieldValue;
+        }
+        // assign username and password ...
+        $params[$this->_options['usernamefield']] = $username;
+        $params[$this->_options['passwordfield']] = $password;
+
+        try {
+            $this->soapResponse = $soapClient->__soapCall($this->_options['method'], $params);
+
+            if ($this->_options['matchpasswords']) {
+                // check if passwords match
+                if ($password == $this->soapResponse[$this->_options['passwordfield']]) {
+                    return true;
+                } else {
+                    return false;
+                }
+            } else {
+                return true;
+            }
+        } catch (SoapFault $e) {
+            return PEAR::raiseError("Error retrieving authentication data. Received SOAP Fault: ".$e->faultstring, $e->faultcode);
+        }
+    }
+
+    // }}}
+    // {{{ _validateOptions()
+
+    /**
+     * Validate that the options passed to the container class are enough for us to proceed
+     *
+     * @access private
+     * @param  array
+     */
+    function _validateOptions()
+    {
+        if (   (   is_null($this->_options['wsdl'])
+                && is_null($this->_options['location'])
+                && is_null($this->_options['uri']))
+            || (   is_null($this->_options['wsdl'])
+                && (   is_null($this->_options['location'])
+                    || is_null($this->_options['uri'])))) {
+            return PEAR::raiseError('Either a WSDL file or a location/uri pair must be specified.');
+        }
+        if (is_null($this->_options['method'])) {
+            return PEAR::raiseError('A method to call on the soap service must be specified.');
+        }
+        return true;
+    }
+
+    // }}}
+    // {{{ _setDefaults()
+
+    /**
+     * Set some default options
+     *
+     * @access private
+     * @return void
+     */
+    function _setDefaults()
+    {
+        $this->_options['wsdl']           = null;
+        $this->_options['location']       = null;
+        $this->_options['uri']            = null;
+        $this->_options['method']         = null;
+        $this->_options['usernamefield']  = 'username';
+        $this->_options['passwordfield']  = 'password';
+        $this->_options['matchpasswords'] = true;
+    }
+
+    // }}}
+
+}
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/vpopmail.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/vpopmail.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/vpopmail.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,88 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
+
+/**
+ * Storage driver for use against vpopmail setups
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.01 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license at php.net so we can mail you a copy immediately.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Stanislav Grozev <tacho at orbitel.bg>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    CVS: $Id: vpopmail.php 237449 2007-06-12 03:11:27Z aashley $
+ * @link       http://pear.php.net/package/Auth
+ * @since      File available since Release 1.2.0
+ */
+
+/**
+ * Include Auth_Container base class
+ */
+require_once "Auth/Container.php";
+/**
+ * Include PEAR package for error handling
+ */
+require_once "PEAR.php";
+
+/**
+ * Storage driver for fetching login data from vpopmail
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Stanislav Grozev <tacho at orbitel.bg>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    Release: 1.6.2  File: $Revision: 237449 $
+ * @link       http://pear.php.net/package/Auth
+ * @since      Class available since Release 1.2.0
+ */
+class Auth_Container_vpopmail extends Auth_Container {
+
+    // {{{ Constructor
+
+    /**
+     * Constructor of the container class
+     *
+     * @return void
+     */
+    function Auth_Container_vpopmail()
+    {
+        if (!extension_loaded('vpopmail')) {
+            return PEAR::raiseError('Cannot use VPOPMail authentication, '
+                    .'VPOPMail extension not loaded!', 41, PEAR_ERROR_DIE);
+        }
+    }
+
+    // }}}
+    // {{{ fetchData()
+
+    /**
+     * Get user information from vpopmail
+     *
+     * @param   string Username - has to be valid email address
+     * @param   string Password
+     * @return  boolean
+     */
+    function fetchData($username, $password)
+    {
+        $this->log('Auth_Container_vpopmail::fetchData() called.', AUTH_LOG_DEBUG);
+        $userdata = array();
+        $userdata = preg_split("/@/", $username, 2);
+        $result = @vpopmail_auth_user($userdata[0], $userdata[1], $password);
+
+        return $result;
+    }
+
+    // }}}
+
+}
+?>


Property changes on: pear/php-auth/branches/upstream/current/Auth-1.6.2/Container/vpopmail.php
___________________________________________________________________
Added: svn:executable
   + *

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/Container.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/Container.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/Container.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,262 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
+
+/**
+ * Auth_Container Base Class
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.01 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license at php.net so we can mail you a copy immediately.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Martin Jansen <mj at php.net>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    CVS: $Id: Container.php 237449 2007-06-12 03:11:27Z aashley $
+ * @link       http://pear.php.net/package/Auth
+ */
+
+/**
+ * Storage class for fetching login data
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Martin Jansen <mj at php.net>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    Release: 1.6.2  File: $Revision: 237449 $
+ * @link       http://pear.php.net/package/Auth
+ */
+class Auth_Container
+{
+
+    // {{{ properties
+
+    /**
+     * User that is currently selected from the storage container.
+     *
+     * @access public
+     */
+    var $activeUser = "";
+
+    /**
+     * The Auth object this container is attached to.
+     *
+     * @access public
+     */
+    var $_auth_obj = null;
+
+    // }}}
+    // {{{ Auth_Container() [constructor]
+
+    /**
+     * Constructor
+     *
+     * Has to be overwritten by each storage class
+     *
+     * @access public
+     */
+    function Auth_Container()
+    {
+    }
+
+    // }}}
+    // {{{ fetchData()
+
+    /**
+     * Fetch data from storage container
+     *
+     * Has to be overwritten by each storage class
+     *
+     * @access public
+     */
+    function fetchData($username, $password, $isChallengeResponse=false)
+    {
+        $this->log('Auth_Container::fetchData() called.', AUTH_LOG_DEBUG);
+    }
+
+    // }}}
+    // {{{ verifyPassword()
+
+    /**
+     * Crypt and verfiy the entered password
+     *
+     * @param  string Entered password
+     * @param  string Password from the data container (usually this password
+     *                is already encrypted.
+     * @param  string Type of algorithm with which the password from
+     *                the container has been crypted. (md5, crypt etc.)
+     *                Defaults to "md5".
+     * @return bool   True, if the passwords match
+     */
+    function verifyPassword($password1, $password2, $cryptType = "md5")
+    {
+        $this->log('Auth_Container::verifyPassword() called.', AUTH_LOG_DEBUG);
+        switch ($cryptType) {
+            case "crypt" :
+                return ((string)crypt($password1, $password2) === (string)$password2);
+                break;
+            case "none" :
+            case "" :
+                return ((string)$password1 === (string)$password2);
+                break;
+            case "md5" :
+                return ((string)md5($password1) === (string)$password2);
+                break;
+            default :
+                if (function_exists($cryptType)) {
+                    return ((string)$cryptType($password1) === (string)$password2);
+                } elseif (method_exists($this,$cryptType)) {
+                    return ((string)$this->$cryptType($password1) === (string)$password2);
+                } else {
+                    return false;
+                }
+                break;
+        }
+    }
+
+    // }}}
+    // {{{ supportsChallengeResponse()
+
+    /**
+      * Returns true if the container supports Challenge Response
+      * password authentication
+      */
+    function supportsChallengeResponse()
+    {
+        return(false);
+    }
+
+    // }}}
+    // {{{ getCryptType()
+
+    /**
+      * Returns the crypt current crypt type of the container
+      *
+      * @return string
+      */
+    function getCryptType()
+    {
+        return('');
+    }
+
+    // }}}
+    // {{{ listUsers()
+
+    /**
+     * List all users that are available from the storage container
+     */
+    function listUsers()
+    {
+        $this->log('Auth_Container::listUsers() called.', AUTH_LOG_DEBUG);
+        return AUTH_METHOD_NOT_SUPPORTED;
+    }
+
+    // }}}
+    // {{{ getUser()
+
+    /**
+     * Returns a user assoc array
+     *
+     * Containers which want should overide this
+     *
+     * @param string The username
+     */
+    function getUser($username)
+    {
+        $this->log('Auth_Container::getUser() called.', AUTH_LOG_DEBUG);
+        $users = $this->listUsers();
+        if ($users === AUTH_METHOD_NOT_SUPPORTED) {
+            return AUTH_METHOD_NOT_SUPPORTED;
+        }
+        for ($i=0; $c = count($users), $i<$c; $i++) {
+            if ($users[$i]['username'] == $username) {
+                return $users[$i];
+            }
+        }
+        return false;
+    }
+
+    // }}}
+    // {{{ addUser()
+
+    /**
+     * Add a new user to the storage container
+     *
+     * @param string Username
+     * @param string Password
+     * @param array  Additional information
+     *
+     * @return boolean
+     */
+    function addUser($username, $password, $additional=null)
+    {
+        $this->log('Auth_Container::addUser() called.', AUTH_LOG_DEBUG);
+        return AUTH_METHOD_NOT_SUPPORTED;
+    }
+
+    // }}}
+    // {{{ removeUser()
+
+    /**
+     * Remove user from the storage container
+     *
+     * @param string Username
+     */
+    function removeUser($username)
+    {
+        $this->log('Auth_Container::removeUser() called.', AUTH_LOG_DEBUG);
+        return AUTH_METHOD_NOT_SUPPORTED;
+    }
+
+    // }}}
+    // {{{ changePassword()
+
+    /**
+     * Change password for user in the storage container
+     *
+     * @param string Username
+     * @param string The new password
+     */
+    function changePassword($username, $password)
+    {
+        $this->log('Auth_Container::changePassword() called.', AUTH_LOG_DEBUG);
+        return AUTH_METHOD_NOT_SUPPORTED;
+    }
+
+    // }}}
+    // {{{ log()
+
+    /**
+     * Log a message to the Auth log
+     *
+     * @param string The message
+     * @param int
+     * @return boolean
+     */
+    function log($message, $level = AUTH_LOG_DEBUG) {
+
+        if (is_null($this->_auth_obj)) {
+
+            return false;
+
+        } else {
+
+            return $this->_auth_obj->log($message, $level);
+
+        }
+
+    }
+
+    // }}}
+
+}
+
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/Frontend/Html.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/Frontend/Html.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/Frontend/Html.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,142 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
+
+/**
+ * Standard Html Login form
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.01 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license at php.net so we can mail you a copy immediately.
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Martin Jansen <mj at php.net>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    CVS: $Id: Html.php 237449 2007-06-12 03:11:27Z aashley $
+ * @link       http://pear.php.net/package/Auth
+ * @since      File available since Release 1.3.0
+ */
+
+/**
+ * Standard Html Login form
+ *
+ * @category   Authentication
+ * @package    Auth
+ * @author     Yavor Shahpasov <yavo at netsmart.com.cy>
+ * @author     Adam Ashley <aashley at php.net>
+ * @copyright  2001-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    Release: 1.6.2  File: $Revision: 237449 $
+ * @link       http://pear.php.net/package/Auth
+ * @since      Class available since Release 1.3.0
+ */
+class Auth_Frontend_Html {
+
+    // {{{ render()
+
+    /**
+     * Displays the login form
+     *
+     * @param object The calling auth instance
+     * @param string The previously used username
+     * @return void
+     */
+    function render(&$caller, $username = '') {
+        $loginOnClick = 'return true;';
+
+        // Try To Use Challene response
+        // TODO javascript might need some improvement for work on other browsers
+        if($caller->advancedsecurity && $caller->storage->supportsChallengeResponse() ) {
+
+            // Init the secret cookie
+            $caller->session['loginchallenege'] = md5(microtime());
+
+            print "\n";
+            print '<script language="JavaScript">'."\n";
+
+            include 'Auth/Frontend/md5.js';
+
+            print "\n";
+            print ' function securePassword() { '."\n";
+            print '   var pass = document.getElementById(\''.$caller->getPostPasswordField().'\');'."\n";
+            print '   var secret = document.getElementById(\'authsecret\')'."\n";
+            //print '   alert(pass);alert(secret); '."\n";
+
+            // If using md5 for password storage md5 the password before
+            // we hash it with the secret
+            // print '   alert(pass.value);';
+            if ($caller->storage->getCryptType() == 'md5' ) {
+                print '   pass.value = hex_md5(pass.value); '."\n";
+                #print '   alert(pass.value);';
+            }
+
+            print '   pass.value = hex_md5(pass.value+\''.$caller->session['loginchallenege'].'\'); '."\n";
+            // print '   alert(pass.value);';
+            print '   secret.value = 1;'."\n";
+            print '   var doLogin = document.getElementById(\'doLogin\')'."\n";
+            print '   doLogin.disabled = true;'."\n";
+            print '   return true;';
+            print ' } '."\n";
+            print '</script>'."\n";;
+            print "\n";
+
+            $loginOnClick = ' return securePassword(); ';
+        }
+
+        print '<center>'."\n";
+
+        $status = '';
+        if (!empty($caller->status) && $caller->status == AUTH_EXPIRED) {
+            $status = '<i>Your session has expired. Please login again!</i>'."\n";
+        } else if (!empty($caller->status) && $caller->status == AUTH_IDLED) {
+            $status = '<i>You have been idle for too long. Please login again!</i>'."\n";
+        } else if (!empty ($caller->status) && $caller->status == AUTH_WRONG_LOGIN) {
+            $status = '<i>Wrong login data!</i>'."\n";
+        } else if (!empty ($caller->status) && $caller->status == AUTH_SECURITY_BREACH) {
+            $status = '<i>Security problem detected. </i>'."\n";
+        }
+
+        print '<form method="post" action="'.$caller->server['PHP_SELF'].'" '
+            .'onSubmit="'.$loginOnClick.'">'."\n";
+        print '<table border="0" cellpadding="2" cellspacing="0" '
+            .'summary="login form" align="center" >'."\n";
+        print '<tr>'."\n";
+        print '    <td colspan="2" bgcolor="#eeeeee"><strong>Login </strong>'
+            .$status.'</td>'."\n";
+        print '</tr>'."\n";
+        print '<tr>'."\n";
+        print '    <td>Username:</td>'."\n";
+        print '    <td><input type="text" id="'.$caller->getPostUsernameField()
+            .'" name="'.$caller->getPostUsernameField().'" value="' . $username
+            .'" /></td>'."\n";
+        print '</tr>'."\n";
+        print '<tr>'."\n";
+        print '    <td>Password:</td>'."\n";
+        print '    <td><input type="password" id="'.$caller->getPostPasswordField()
+            .'" name="'.$caller->getPostPasswordField().'" /></td>'."\n";
+        print '</tr>'."\n";
+        print '<tr>'."\n";
+
+        //onClick=" '.$loginOnClick.' "
+        print '    <td colspan="2" bgcolor="#eeeeee"><input value="Login" '
+            .'id="doLogin" name="doLogin" type="submit" /></td>'."\n";
+        print '</tr>'."\n";
+        print '</table>'."\n";
+
+        // Might be a good idea to make the variable name variable
+        print '<input type="hidden" id="authsecret" name="authsecret" value="" />';
+        print '</form>'."\n";
+        print '</center>'."\n";
+    }
+
+    // }}}
+
+}
+
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/Frontend/md5.js
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/Frontend/md5.js	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/Frontend/md5.js	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,256 @@
+/*
+ * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
+ * Digest Algorithm, as defined in RFC 1321.
+ * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * Distributed under the BSD License
+ * See http://pajhome.org.uk/crypt/md5 for more info.
+ */
+
+/*
+ * Configurable variables. You may need to tweak these to be compatible with
+ * the server-side, but the defaults work in most cases.
+ */
+var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
+var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
+var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */
+
+/*
+ * These are the functions you'll usually want to call
+ * They take string arguments and return either hex or base-64 encoded strings
+ */
+function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
+function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
+function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
+function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
+function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
+function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }
+
+/*
+ * Perform a simple self-test to see if the VM is working
+ */
+function md5_vm_test()
+{
+  return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
+}
+
+/*
+ * Calculate the MD5 of an array of little-endian words, and a bit length
+ */
+function core_md5(x, len)
+{
+  /* append padding */
+  x[len >> 5] |= 0x80 << ((len) % 32);
+  x[(((len + 64) >>> 9) << 4) + 14] = len;
+
+  var a =  1732584193;
+  var b = -271733879;
+  var c = -1732584194;
+  var d =  271733878;
+
+  for(var i = 0; i < x.length; i += 16)
+  {
+    var olda = a;
+    var oldb = b;
+    var oldc = c;
+    var oldd = d;
+
+    a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
+    d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
+    c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
+    b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
+    a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
+    d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
+    c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
+    b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
+    a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
+    d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
+    c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
+    b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
+    a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
+    d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
+    c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
+    b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);
+
+    a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
+    d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
+    c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
+    b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
+    a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
+    d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
+    c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
+    b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
+    a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
+    d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
+    c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
+    b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
+    a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
+    d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
+    c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
+    b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
+
+    a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
+    d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
+    c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
+    b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
+    a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
+    d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
+    c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
+    b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
+    a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
+    d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
+    c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
+    b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
+    a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
+    d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
+    c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
+    b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
+
+    a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
+    d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
+    c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
+    b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
+    a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
+    d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
+    c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
+    b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
+    a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
+    d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
+    c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
+    b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
+    a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
+    d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
+    c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
+    b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
+
+    a = safe_add(a, olda);
+    b = safe_add(b, oldb);
+    c = safe_add(c, oldc);
+    d = safe_add(d, oldd);
+  }
+  return Array(a, b, c, d);
+
+}
+
+/*
+ * These functions implement the four basic operations the algorithm uses.
+ */
+function md5_cmn(q, a, b, x, s, t)
+{
+  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
+}
+function md5_ff(a, b, c, d, x, s, t)
+{
+  return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
+}
+function md5_gg(a, b, c, d, x, s, t)
+{
+  return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
+}
+function md5_hh(a, b, c, d, x, s, t)
+{
+  return md5_cmn(b ^ c ^ d, a, b, x, s, t);
+}
+function md5_ii(a, b, c, d, x, s, t)
+{
+  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
+}
+
+/*
+ * Calculate the HMAC-MD5, of a key and some data
+ */
+function core_hmac_md5(key, data)
+{
+  var bkey = str2binl(key);
+  if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
+
+  var ipad = Array(16), opad = Array(16);
+  for(var i = 0; i < 16; i++)
+  {
+    ipad[i] = bkey[i] ^ 0x36363636;
+    opad[i] = bkey[i] ^ 0x5C5C5C5C;
+  }
+
+  var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
+  return core_md5(opad.concat(hash), 512 + 128);
+}
+
+/*
+ * Add integers, wrapping at 2^32. This uses 16-bit operations internally
+ * to work around bugs in some JS interpreters.
+ */
+function safe_add(x, y)
+{
+  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
+  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+  return (msw << 16) | (lsw & 0xFFFF);
+}
+
+/*
+ * Bitwise rotate a 32-bit number to the left.
+ */
+function bit_rol(num, cnt)
+{
+  return (num << cnt) | (num >>> (32 - cnt));
+}
+
+/*
+ * Convert a string to an array of little-endian words
+ * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
+ */
+function str2binl(str)
+{
+  var bin = Array();
+  var mask = (1 << chrsz) - 1;
+  for(var i = 0; i < str.length * chrsz; i += chrsz)
+    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
+  return bin;
+}
+
+/*
+ * Convert an array of little-endian words to a string
+ */
+function binl2str(bin)
+{
+  var str = "";
+  var mask = (1 << chrsz) - 1;
+  for(var i = 0; i < bin.length * 32; i += chrsz)
+    str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
+  return str;
+}
+
+/*
+ * Convert an array of little-endian words to a hex string.
+ */
+function binl2hex(binarray)
+{
+  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
+  var str = "";
+  for(var i = 0; i < binarray.length * 4; i++)
+  {
+    str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
+           hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF);
+  }
+  return str;
+}
+
+/*
+ * Convert an array of little-endian words to a base-64 string
+ */
+function binl2b64(binarray)
+{
+  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+  var str = "";
+  for(var i = 0; i < binarray.length * 4; i += 3)
+  {
+    var triplet = (((binarray[i   >> 2] >> 8 * ( i   %4)) & 0xFF) << 16)
+                | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
+                |  ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
+    for(var j = 0; j < 4; j++)
+    {
+      if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
+      else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
+    }
+  }
+  return str;
+}

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/README.AdvancedSecurity
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/README.AdvancedSecurity	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/README.AdvancedSecurity	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,63 @@
+03 July 2004
+
+TODO 
+ * Session fixation attack (BUG #2021)
+ * Fix multiple open windows and challenge responce cookies (use a list of cookies which are allowed)
+
+Since Auth 1.3 new security functionality has been added.
+The main purpose for these advanced security checks is to avoid man-in-the-middle attacks and
+session hijacking.
+
+
+Session hijacking example 
+  - Login to an Auth protected page. Write down the session id (should be something like PHPSESSID=36916b0aa1180386010f304b6160e3e8)
+  - Open a different browser (FireFox <> IE), or a browser on a different computer
+  - Type down the address of the secure page and add ?PHPSESSID=36916b0aa1180386010f304b6160e3e8 where
+    PHPSESSID is the php session name and 36916b0aa1180386010f304b6160e3e8 is the valid session id which you wrote down earlier
+  - You should be logged in with the same creditentials
+  
+
+
+To enable the advanced scurity checks you have to call
+$auth->setAdvancedSecurity();
+
+If this has been enabled the following security checks will be performed
+
+  - Login screen will use md5 when submitting the password if java script is enabled in the browser
+  - If user ip address has been changed betwin requests the user will be logged out
+  - If user User-Agent string has been changed the user will be logged out
+  - If user does not provide a valid auth challenge cookied he will be logged out (read below for explanation)
+  
+Limitations
+ * Challenge responce cookies would not allow a user to open multiple windows of the same page (Open in new window/tab). If 
+ the user accesses the protected area from two browser windows he will be logged out. It can also create a problem if you
+ create dynamic images with php and that code passes through the auth layer. One way to avoid it is to disable advanced security for 
+ those pages only selectively.
+ * Password saving does not work with login screens which use challenge responce (md5 hashing) of password
+ * Challenge responce on login only works with DB container and plain or md5 hashing
+
+ 
+
+
+Challenge Responce cookies
+
+ 
+ The challenge responce cookies provide a way to avoid most of the session hijacking problems. Since User-Agent headers
+ and IP address can be spoofed, or in the case of IP a proxy can be used an extra security step has been added using a 
+ challenge cookie.
+ 
+ After the user is authenthicated by Auth he is presented with a challenge cookie. For his next request to be succesfull 
+ he must present that cookie on his next request. If that is successfull he will be presented with a new 
+ challenge cookie. This will be reapeated for each request the user makes.
+ 
+ While this method is not fool proof it does limit the possibilities for an attack.
+ First the attacker must must obtain the challenge cookie and use it before the user does.
+ If the user makes a request after the attacker the session will be logged out and both of them 
+ will need to login again.
+ 
+ A problem which this scheme does not address well is users leaving their sessions without preforming a logout
+ in this case the attacker is free to abuse the user session (provided he has met all the prerequisites). 
+ 
+ Ideas and sujestions for improvements are more than welcome.
+ send to yavo at siava.org
+ 

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/README.Auth
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/README.Auth	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/README.Auth	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,3 @@
+The documentation for PEAR::Auth is available at
+
+    http://pear.php.net/manual/


Property changes on: pear/php-auth/branches/upstream/current/Auth-1.6.2/README.Auth
___________________________________________________________________
Added: svn:executable
   + *

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/examples/logging.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/examples/logging.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/examples/logging.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,75 @@
+<?php
+
+require_once "Auth.php";
+require_once 'Log.php';
+require_once 'Log/observer.php';
+
+// Callback function to display login form
+function loginFunction($username = null, $status = null, &$auth = null)
+{
+	/*
+	 * Change the HTML output so that it fits to your
+	 * application.
+	 */
+	echo "<form method=\"post\" action=\"".$_SERVER['PHP_SELF']."\">";
+	echo "Username: <input type=\"text\" name=\"username\"><br/>";
+	echo "Password: <input type=\"password\" name=\"password\"><br/>";
+	echo "<input type=\"submit\">";
+	echo "</form>";
+}
+
+class Auth_Log_Observer extends Log_observer {
+
+	var $messages = array();
+
+	function notify($event) {
+
+		$this->messages[] = $event;
+
+	}
+
+}
+
+$options = array(
+		'enableLogging' => true,
+		'cryptType' => 'md5',
+		'users' => array(
+			'guest' => md5('password'),
+			),
+		);
+$a = new Auth("Array", $options, "loginFunction");
+
+$infoObserver = new Auth_Log_Observer(AUTH_LOG_INFO);
+
+$a->attachLogObserver($infoObserver);
+
+$debugObserver = new Auth_Log_Observer(AUTH_LOG_DEBUG);
+
+$a->attachLogObserver($debugObserver);
+
+$a->start();
+
+if ($a->checkAuth()) {
+	/*
+	 * The output of your site goes here.
+	 */
+	print "Authentication Successful.<br/>";
+}
+
+print '<h3>Logging Output:</h3>'
+	.'<b>AUTH_LOG_INFO level messages:</b><br/>';
+
+foreach ($infoObserver->messages as $event) {
+	print $event['priority'].': '.$event['message'].'<br/>';
+}
+
+print '<br/>'
+	.'<b>AUTH_LOG_DEBUG level messages:</b><br/>';
+
+foreach ($debugObserver->messages as $event) {
+	print $event['priority'].': '.$event['message'].'<br/>';
+}
+
+print '<br/>';
+
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/examples/multi-container.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/examples/multi-container.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/examples/multi-container.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,89 @@
+<?php
+
+require_once "Auth.php";
+require_once 'Log.php';
+require_once 'Log/observer.php';
+
+// Callback function to display login form
+function loginFunction($username = null, $status = null, &$auth = null)
+{
+	/*
+	 * Change the HTML output so that it fits to your
+	 * application.
+	 */
+	echo "<form method=\"post\" action=\"".$_SERVER['PHP_SELF']."\">";
+	echo "Username: <input type=\"text\" name=\"username\"><br/>";
+	echo "Password: <input type=\"password\" name=\"password\"><br/>";
+	echo "<input type=\"submit\">";
+	echo "</form>";
+}
+
+class Auth_Log_Observer extends Log_observer {
+
+	var $messages = array();
+
+	function notify($event) {
+
+		$this->messages[] = $event;
+
+	}
+
+}
+
+$options = array(
+	'enableLogging' => true,
+	array(
+		'type' => 'Array',
+		'options' => array(
+			'cryptType' => 'md5',
+			'users' => array(
+				'guest' => md5('password'),
+			),
+		),
+	),
+	array(
+		'type' => 'Array',
+		'options' => array(
+			'cryptType' => 'md5',
+			'users' => array(
+				'admin' => md5('password'),
+			),
+		),
+	),
+);
+$a = new Auth("Multiple", $options, "loginFunction");
+
+$infoObserver = new Auth_Log_Observer(AUTH_LOG_INFO);
+
+$a->attachLogObserver($infoObserver);
+
+$debugObserver = new Auth_Log_Observer(AUTH_LOG_DEBUG);
+
+$a->attachLogObserver($debugObserver);
+
+$a->start();
+
+if ($a->checkAuth()) {
+	/*
+	 * The output of your site goes here.
+	 */
+	print "Authentication Successful.<br/>";
+}
+
+print '<h3>Logging Output:</h3>'
+	.'<b>AUTH_LOG_INFO level messages:</b><br/>';
+
+foreach ($infoObserver->messages as $event) {
+	print $event['priority'].': '.$event['message'].'<br/>';
+}
+
+print '<br/>'
+	.'<b>AUTH_LOG_DEBUG level messages:</b><br/>';
+
+foreach ($debugObserver->messages as $event) {
+	print $event['priority'].': '.$event['message'].'<br/>';
+}
+
+print '<br/>';
+
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/DBContainer.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/DBContainer.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/DBContainer.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,36 @@
+<?php
+
+include_once 'TestAuthContainer.php';
+include_once 'Auth/Container/DB.php';
+
+
+class DBContainer extends TestAuthContainer {
+
+
+    function &getContainer() {
+        static $container;
+
+        if(!isset($container)){
+            include 'auth_container_db_options.php';
+            $container = new Auth_Container_DB($options);
+            // Catch if DB connection cannot be made
+            $res = $container->_prepare();
+        }
+
+        if (!DB::isConnection($container->db)) {
+            $this->markTestSkipped("DB is not a connection object, check dsn");
+        }
+
+        return($container);
+    }
+
+    function &getExtraOptions() {
+        include 'auth_container_db_options.php';
+        return($extra_options);
+    }
+}
+
+
+
+
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/FileContainer.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/FileContainer.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/FileContainer.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,27 @@
+<?php
+
+include_once 'TestAuthContainer.php';
+include_once 'Auth/Container/File.php';
+
+class FileContainer extends TestAuthContainer {
+
+
+    function &getContainer() {
+        static $container;
+        if(!isset($container)){
+            include 'auth_container_file_options.php';
+            $container = new Auth_Container_File($options);
+        }
+        return($container);
+    }
+
+    function &getExtraOptions() {
+        include 'auth_container_file_options.php';
+        return($extra_options);
+    }
+}
+
+
+
+
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/MDB2Container.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/MDB2Container.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/MDB2Container.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,31 @@
+<?php
+
+require_once 'TestAuthContainer.php';
+require_once 'Auth/Container/MDB2.php';
+
+
+class MDB2Container extends TestAuthContainer {
+
+    function &getContainer() {
+        static $container;
+
+        if (!isset($container)) {
+            include 'auth_container_mdb2_options.php';
+            $container = new Auth_Container_MDB2($options);
+            // Catch if DB connection cannot be made
+            $res = $container->_prepare();
+        }
+
+        if (!MDB2::isConnection($container->db)) {
+            $this->markTestSkipped("MDB2 is not a connection object, check dsn");
+        }
+
+        return $container;
+    }
+
+    function &getExtraOptions() {
+        include 'auth_container_mdb2_options.php';
+        return $extra_options;
+    }
+}
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/MDBContainer.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/MDBContainer.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/MDBContainer.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,35 @@
+<?php
+
+include_once 'TestAuthContainer.php';
+include_once 'Auth/Container/MDB.php';
+
+
+class MDBContainer extends TestAuthContainer {
+
+
+    function &getContainer() {
+        static $container;
+        #print "In MDBContainer::getContainer {$this->skip_tests}\n";
+        if(!isset($container)){
+            include 'auth_container_mdb_options.php';
+            $container = new Auth_Container_MDB($options);
+            // Catch if DB connection cannot be made
+            $res = $container->_prepare();
+        }
+
+        if (!MDB::isConnection($container->db)) {
+            $this->markTestSkipped("MDB is not a connection object, check dsn");
+        }
+        return $container;
+    }
+
+    function &getExtraOptions() {
+        include 'auth_container_mdb_options.php';
+        return $extra_options;
+    }
+}
+
+
+
+
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/POP3Container.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/POP3Container.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/POP3Container.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,27 @@
+<?php
+
+include_once 'TestAuthContainer.php';
+include_once 'Auth/Container/POP3.php';
+
+
+class POP3Container extends TestAuthContainer {
+
+    function &getContainer() {
+        static $container;
+        if(!isset($container)){
+            include 'auth_container_pop3_options.php';
+            $container = new Auth_Container_POP3($options);
+        }
+        return($container);
+    }
+
+    function &getExtraOptions() {
+        include 'auth_container_pop3_options.php';
+        return($extra_options);
+    }
+}
+
+
+
+
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/POP3aContainer.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/POP3aContainer.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/POP3aContainer.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,28 @@
+<?php
+
+include_once 'TestAuthContainer.php';
+include_once 'Auth/Container/POP3.php';
+
+
+class POP3aContainer extends TestAuthContainer {
+
+
+    function &getContainer() {
+        static $container;
+        if(!isset($container)){
+            include 'auth_container_pop3a_options.php';
+            $container = new Auth_Container_POP3($options);
+        }
+        return($container);
+    }
+
+    function &getExtraOptions() {
+        include 'auth_container_pop3a_options.php';
+        return($extra_options);
+    }
+}
+
+
+
+
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/TestAuthContainer.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/TestAuthContainer.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/TestAuthContainer.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,133 @@
+<?php
+require_once 'PHPUnit/Framework/TestCase.php';
+require_once 'Auth.php';
+
+class TestAuthContainer extends PHPUnit_Framework_TestCase
+{
+
+    // Abstract
+    function getContainer() {}
+    function getExtraOptions() {}
+
+    function setUp()
+    {
+        $this->container =& $this->getContainer();
+        $this->user = 'joe';
+        $this->pass = 'doe';
+        $this->opt = 'VeryCoolUser';
+        // Nedded since lazy loading of container was introduced
+        $this->container->_auth_obj =& new Auth(&$this);
+
+        $opt = $this->getExtraOptions();
+        // Add the default user to be used for some testing
+        $this->container->addUser($opt['username'], $opt['passwd']);
+    }
+
+    function tearDown()
+    {
+        $opt = $this->getExtraOptions();
+        // Remove default user
+        $this->container->removeUser($opt['username']);
+    }
+
+    function testListUsers()
+    {
+
+        $users = $this->container->listUsers();
+        if (AUTH_METHOD_NOT_SUPPORTED === $users) {
+            $this->markTestSkipped('This operation is not supported by '.get_class($this->container));
+        }
+
+        $opt = $this->getExtraOptions();
+        $this->assertTrue(is_array($users[0]), 'First array element from result was not an array');
+        $this->assertTrue($users[0]['username'] == $opt['username'], sprintf('First username was not equal to default username "%s" ', $opt['username']));
+    }
+
+    function testAddUser()
+    {
+        $cb = count($this->container->listUsers());
+        $res = $this->container->addUser($this->user, $this->pass, $this->opt);
+        if (AUTH_METHOD_NOT_SUPPORTED === $res) {
+            $this->markTestSkipped("This operation is not supported by ".get_class($this->container));
+        }
+
+        if (PEAR::isError($res)) {
+            $error = $res->getMessage().' ['.$res->getUserInfo().']';
+        } else {
+            $error = '';
+        }
+        $this->assertTrue(!PEAR::isError($res), 'error:'.$error);
+        $ca = count($this->container->listUsers());
+        $users = $this->container->listUsers();
+        $last_username = $users[$ca-1]['username'];
+        $this->assertTrue( ($cb === $ca-1) , sprintf('Count of users before (%s) and after (%s) does not differ by one', $cb, $ca));
+        $this->assertTrue( $this->container->fetchData($this->user, $this->pass) , sprintf('Could not verify with the newly created user %s',$this->user));
+
+        // Remove the user we just added, assumes removeUser works
+        $this->container->removeUser($this->user);
+    }
+
+    function testFetchData()
+    {
+        $opt = $this->getExtraOptions();
+        $fetch_res = $this->container->fetchData($opt['username'], $opt['passwd']);
+        if (AUTH_METHOD_NOT_SUPPORTED === $fetch_res) {
+            $this->markTestSkipped("This operation is not supported by ".get_class($this->container));
+        }
+
+        $this->assertTrue($fetch_res,sprintf('Could not verify with the default username (%s) and passwd (%s)', $opt['username'], $opt['passwd']));
+
+        // Test for fail fetchData
+        $opt = $this->getExtraOptions();
+        $this->assertFalse(
+            $this->container->fetchData(md5($opt['username']), $opt['passwd']),
+            "fetchData returned true with invalid username and pass"
+        );
+
+    }
+
+
+    /**
+     * Tjis test depends on add user & remove user to work
+     */
+    function testFetchDataSpaceInPassword()
+    {
+        $user = uniqid('user');
+        $pass = 'Some Pass ';
+
+        $res = $this->container->addUser($user, $pass, array());
+        if (AUTH_METHOD_NOT_SUPPORTED === $res) {
+            $this->markTestSkipped("This operation is not supported by ".get_class($this->container));
+        }
+
+        $fetch_res = $this->container->fetchData($user, $pass);
+        if (AUTH_METHOD_NOT_SUPPORTED === $fetch_res) {
+            $this->markTestSkipped("This operation is not supported by ".get_class($this->container));
+        }
+
+        $this->assertTrue($fetch_res, 'Could not verify user with space password');
+
+        $remove_res = $this->container->removeUser($user);
+    }
+
+
+
+
+    function testRemoveUser()
+    {
+        // Add a user to be removed when testing removeUuser method
+        // Assume add user works
+        $this->container->addUser('for_remove', 'for_remove');
+        $cb = count($this->container->listUsers());
+        $remove_res = $this->container->removeUser('for_remove');
+        if (AUTH_METHOD_NOT_SUPPORTED === $remove_res) {
+            $this->markTestSkipped("This operation is not supported by ".get_class($this->container));
+        }
+
+        $ca = count($this->container->listUsers());
+        $this->assertTrue($cb === $ca+1, sprintf('Could not remove user "%s", count before:%s count after:%s ', 'for_remove', $cb, $ca));
+    }
+
+}
+
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/auth_container_db_options.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/auth_container_db_options.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/auth_container_db_options.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,23 @@
+<?php
+
+/*
+        $this->options['table']       = "auth";
+        $this->options['usernamecol'] = "username";
+        $this->options['passwordcol'] = "password";
+        $this->options['dsn']         = "";
+        $this->options['db_fields']   = "";
+        $this->options['cryptType']   = "md5";
+*/
+$options = array(
+    'dsn'=>'mysql://root:@localhost/authtest',
+    'table'=>'temp',
+    'usernamecol'=>'username',
+    'passwordcol'=>'password',
+    'cryptType'=>'md5',
+    'db_fields'=>'*'
+);
+
+$extra_options['username'] = 'test_user';
+$extra_options['passwd'] = 'test_user';
+
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/auth_container_file_options.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/auth_container_file_options.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/auth_container_file_options.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,8 @@
+<?php
+
+$options = 'users';
+
+$extra_options['username'] = 'test_user';
+$extra_options['passwd'] = 'test_user';
+
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/auth_container_mdb2_options.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/auth_container_mdb2_options.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/auth_container_mdb2_options.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,25 @@
+<?php
+/*
+//TEST DATABASE:
+-----------------------------------------------
+DROP TABLE IF EXISTS temp;
+CREATE TABLE temp (
+  username varchar(150) NOT NULL,
+  password varchar(200) NOT NULL
+);
+-----------------------------------------------
+*/
+
+$options = array(
+    'dsn'         => 'mysql://root:@localhost/authtest',
+    'table'       => 'temp',
+    'usernamecol' => 'username',
+    'passwordcol' => 'password',
+    'db_fields'   => '*',
+    'cryptType' => 'md5'
+);
+
+$extra_options['username'] = 'test_user';
+$extra_options['passwd'] = 'test_user';
+
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/auth_container_mdb_options.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/auth_container_mdb_options.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/auth_container_mdb_options.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,25 @@
+<?php
+/*
+//TEST DATABASE:
+-----------------------------------------------
+DROP TABLE IF EXISTS temp;
+CREATE TABLE temp (
+  username varchar(150) NOT NULL,
+  password varchar(200) NOT NULL
+);
+-----------------------------------------------
+*/
+
+$options = array(
+    'dsn'         => 'mysql://root:@localhost/authtest',
+    'table'       => 'temp',
+    'usernamecol' => 'username',
+    'passwordcol' => 'password',
+    'db_fields'   => '*',
+    'cryptType' => 'md5'
+);
+
+$extra_options['username'] = 'test_user';
+$extra_options['passwd'] = 'test_user';
+
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/auth_container_pop3_options.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/auth_container_pop3_options.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/auth_container_pop3_options.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,11 @@
+<?php
+
+$options = array(
+    'host'=>'mail.example.com',
+    'port'=>'110'
+);
+
+$extra_options['username'] = 'test_user';
+$extra_options['passwd'] = 'test_user';
+
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/auth_container_pop3a_options.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/auth_container_pop3a_options.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/auth_container_pop3a_options.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,8 @@
+<?php
+
+$options = 'mail.example.com:110';
+
+$extra_options['username'] = 'test_user';
+$extra_options['passwd'] = 'test_user';
+
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/bug8735.passwd
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/bug8735.passwd	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/bug8735.passwd	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1 @@
+test:fcfKBtvEwG4g.

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/bug8735.phpt
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/bug8735.phpt	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/bug8735.phpt	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,44 @@
+--TEST--
+Regression test for bug #8735
+--FILE--
+<?php
+set_include_path(dirname(dirname(__FILE__)) . ':' . get_include_path());
+$datasrc = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'bug8735.passwd';
+
+require_once 'PEAR.php';
+require_once 'Auth.php';
+
+$a = new Auth('File', 
+		array('file' => $datasrc, 
+			'type' => 'AuthBasic'),
+		'displayLogin');
+if (PEAR::isError($a)) {
+	print $a->getMessage();
+	exit;
+}
+
+$error = $a->removeUser('username');
+if (PEAR::isError($error)) {
+	print $error->getMessage();
+	exit;
+}
+
+readfile($datasrc);
+print "-- cut --\n";
+
+$error = $a->addUser('username', 'password');
+if (PEAR::isError($error) || $error === false) {
+	print "Error happened when adding.\n";
+	print $error->getMessage();
+	exit;
+}
+
+readfile($datasrc);
+
+$a->removeUser('username');
+?>
+--EXPECT--
+test:fcfKBtvEwG4g.
+-- cut --
+test:fcfKBtvEwG4g.
+username:{SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/mysql_test_db.sql
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/mysql_test_db.sql	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/mysql_test_db.sql	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,4 @@
+CREATE TABLE `temp` (
+    `username` varchar(150) NOT NULL default '',
+    `password` varchar(200) NOT NULL default ''
+    ) ENGINE=MyISAM DEFAULT CHARSET=latin1;

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/tests.php
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/tests.php	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/tests.php	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1,48 @@
+<?php
+
+include_once 'Auth.php';
+include_once 'TestAuthContainer.php';
+include_once 'FileContainer.php';
+include_once 'DBContainer.php';
+include_once 'DBLiteContainer.php';
+include_once 'MDBContainer.php';
+include_once 'MDB2Container.php';
+include_once 'POP3Container.php';
+include_once 'POP3aContainer.php';
+include_once 'IMAPContainer.php';
+include_once 'PHPUnit.php';
+
+
+function error($err){
+    print "Error\n";
+    print "Code:".trim($err->getCode())."\n";
+    print "Message:".trim($err->getMessage())."\n";
+    #print "UserInfo:".trim($err->getUserInfo())."\n";
+    #print "DebugInfo:".trim($err->getDebugInfo())."\n";
+
+}
+
+#error_reporting(0);
+PEAR::setErrorHandling(PEAR_ERROR_PRINT, "\nPear Error:%s \n");
+#PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, "error");
+
+set_time_limit(0);
+
+$suite = new PHPUnit_TestSuite();
+
+// File Container
+#$suite->addTest(new PHPUnit_TestSuite('IMAPContainer'));
+$suite->addTest(new PHPUnit_TestSuite('FileContainer'));
+$suite->addTest(new PHPUnit_TestSuite('DBContainer'));
+//$suite->addTest(new PHPUnit_TestSuite('DBLiteContainer'));
+// MDB Container
+$suite->addTest(new PHPUnit_TestSuite('MDBContainer'));
+// MDB2 Container
+$suite->addTest(new PHPUnit_TestSuite('MDB2Container'));
+// POP3 Container
+$suite->addTest(new PHPUnit_TestSuite('POP3Container'));
+
+$result = PHPUnit::run($suite);
+echo $result->toString();
+
+?>

Added: pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/users
===================================================================
--- pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/users	                        (rev 0)
+++ pear/php-auth/branches/upstream/current/Auth-1.6.2/tests/users	2009-11-08 16:12:17 UTC (rev 1300)
@@ -0,0 +1 @@
+

Modified: pear/php-auth/branches/upstream/current/package.xml
===================================================================
--- pear/php-auth/branches/upstream/current/package.xml	2009-10-18 21:54:34 UTC (rev 1299)
+++ pear/php-auth/branches/upstream/current/package.xml	2009-11-08 16:12:17 UTC (rev 1300)
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<package packagerversion="1.7.1" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
+<package packagerversion="1.9.0" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
  <name>Auth</name>
  <channel>pear.php.net</channel>
  <summary>Creating an authentication system.</summary>
@@ -53,10 +53,10 @@
   <email>aharvey at php.net</email>
   <active>yes</active>
  </developer>
- <date>2008-04-04</date>
- <time>15:57:23</time>
+ <date>2009-10-15</date>
+ <time>12:57:29</time>
  <version>
-  <release>1.6.1</release>
+  <release>1.6.2</release>
   <api>1.5.0</api>
  </version>
  <stability>
@@ -64,78 +64,81 @@
   <api>stable</api>
  </stability>
  <license uri="http://www.php.net/license">PHP License</license>
- <notes>* Actually included the new NetVPOPMaild container file.
-	  *mutter*grumble*stupid package.xml*grumble*mutter*
-* Fix Bug #13578: Parse errors in DB Containers</notes>
+ <notes>
+* Fix Bug #13756: Variable name mispelling in SAP container
+* Fix Bug #13757: AUTH_LOG_ERR used but not defined
+* Fix Bug #14248: Typo and documentation fixes
+* Fix Bug #16676: Notices in PEAR container (cweiske)
+ </notes>
  <contents>
   <dir name="/">
-   <file baseinstalldir="" md5sum="7ddc0ffcb8b92481e3167da27f3e2996" name="Auth/Anonymous.php" role="php">
+   <file baseinstalldir="" md5sum="0e46561c1ff408c6e6e634f2b2f2cc04" name="Auth/Anonymous.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
-   <file baseinstalldir="" md5sum="3db4bed05ee42a45064360c185babcfc" name="Auth/Auth.php" role="php">
+   <file baseinstalldir="" md5sum="8c1951eaf366f8c9b55687db0c66a305" name="Auth/Auth.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
-   <file baseinstalldir="" md5sum="4cd779a507fd8a196f5c40fdc8ac2321" name="Auth/Controller.php" role="php">
+   <file baseinstalldir="" md5sum="02c7977d9b7d6b9e11c85047cf561ecb" name="Auth/Controller.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
-   <file baseinstalldir="Auth" md5sum="425ad2bfe23c78222e067260bba148c9" name="Container/Array.php" role="php">
+   <file baseinstalldir="Auth" md5sum="63f18075ee3f6233c9b303ae77672902" name="Container/Array.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
-   <file baseinstalldir="Auth" md5sum="f65dbd589c96909e015adbb5e84c816b" name="Container/DB.php" role="php">
+   <file baseinstalldir="Auth" md5sum="7e0cfb35c21152ee81972bca23315ac6" name="Container/DB.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
-   <file baseinstalldir="Auth" md5sum="c4d18739394aa954b957a3c3b217a6be" name="Container/DBLite.php" role="php">
+   <file baseinstalldir="Auth" md5sum="b1c6144776ea96d4011d7087ecd5c9bb" name="Container/DBLite.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
-   <file baseinstalldir="Auth" md5sum="ec960928f512703c94b3a5a443699431" name="Container/File.php" role="php">
+   <file baseinstalldir="Auth" md5sum="de5d5ee2bf0c9a2a4ca9e0d614748788" name="Container/File.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
-   <file baseinstalldir="Auth" md5sum="71c4887d6077628a0c8ab2ae23b1dd2b" name="Container/IMAP.php" role="php">
+   <file baseinstalldir="Auth" md5sum="e90761733d05e29117e00a4c56896b18" name="Container/IMAP.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
-   <file baseinstalldir="Auth" md5sum="71928f157342e34eaa8a873ed389a502" name="Container/KADM5.php" role="php">
+   <file baseinstalldir="Auth" md5sum="276222108b78dabf1f926103b316068b" name="Container/KADM5.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
-   <file baseinstalldir="Auth" md5sum="51ce4915d7f0b740539703260388f8e7" name="Container/LDAP.php" role="php">
+   <file baseinstalldir="Auth" md5sum="b2dc649908699fa3015d7b62eddafe57" name="Container/LDAP.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
-   <file baseinstalldir="Auth" md5sum="36c94238dbf7fb795ed454e04667c47b" name="Container/MDB.php" role="php">
+   <file baseinstalldir="Auth" md5sum="bfe6fa1723805a65533f110a2abe47ac" name="Container/MDB.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
-   <file baseinstalldir="Auth" md5sum="201ce32581bb1b4071ed8aa5cdf7599b" name="Container/MDB2.php" role="php">
+   <file baseinstalldir="Auth" md5sum="d6ff509fc7151e6d2e3f8704a5b1240a" name="Container/MDB2.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
-   <file baseinstalldir="Auth" md5sum="75d308e264d4cbc2060b5600762d37ff" name="Container/Multiple.php" role="php">
+   <file baseinstalldir="Auth" md5sum="a3291f65304b56a516f41fc5558c365d" name="Container/Multiple.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
-   <file baseinstalldir="Auth" md5sum="e926c315a6e8d8e9b6a199f16b423bcd" name="Container/PEAR.php" role="php">
+   <file baseinstalldir="Auth" md5sum="e1ffa79db2ef0acecb29b4f0dcd8acb9" name="Container/PEAR.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
-   <file baseinstalldir="Auth" md5sum="42aa53e04e98ccd3595e102d5ab375c1" name="Container/POP3.php" role="php">
+   <file baseinstalldir="Auth" md5sum="44fc0dc99da47214e21208d7ac0ebb68" name="Container/POP3.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
-   <file baseinstalldir="Auth" md5sum="b1335e1986b737436445295cf5f32a4a" name="Container/RADIUS.php" role="php">
+   <file baseinstalldir="Auth" md5sum="7d857e0c76c4ab4021800f71a81d200c" name="Container/RADIUS.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
-   <file baseinstalldir="Auth" md5sum="4728846b74290332eceee0502b17a055" name="Container/SAP.php" role="php">
+   <file baseinstalldir="Auth" md5sum="aedab52c671c71c30f60ada445e7ab11" name="Container/SAP.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
-   <file baseinstalldir="Auth" md5sum="22b8425b8dee653e415498815eca3986" name="Container/SMBPasswd.php" role="php">
+   <file baseinstalldir="Auth" md5sum="ff30a661ea13b5c331cbdc8bce2e9862" name="Container/SMBPasswd.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
-   <file baseinstalldir="Auth" md5sum="850962e77d4d2b07eca687a685200c78" name="Container/SOAP.php" role="php">
+   <file baseinstalldir="Auth" md5sum="9ed230ff062caa5f3d5a8731c7ef8077" name="Container/SOAP.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
-   <file baseinstalldir="Auth" md5sum="70c6c480ea673bc1e06aed12c312f869" name="Container/SOAP5.php" role="php">
+   <file baseinstalldir="Auth" md5sum="59b1bce6be5c1e4ddc5d34be614d7894" name="Container/SOAP5.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
-   <file baseinstalldir="Auth" md5sum="d3278589849381774ab0057daae4404c" name="Container/vpopmail.php" role="php">
+   <file baseinstalldir="Auth" md5sum="d17eff041f7fc5a18767b774b409f653" name="Container/vpopmail.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
-   <file baseinstalldir="Auth" md5sum="a14679c2f26af6708b3de87320c92ccd" name="Container/NetVPOPMaild.php" role="php">
+   <file baseinstalldir="Auth" md5sum="8a2fec942b6662f0794e2de1fc5515be" name="Container/NetVPOPMaild.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
-   <file baseinstalldir="Auth" md5sum="970cb92d4da66781cfd2aca6d171f3ff" name="Frontend/Html.php" role="php">
+   <file baseinstalldir="Auth" md5sum="c2e77d1f76160cf03f3613a60d743878" name="Frontend/Html.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
    <file baseinstalldir="Auth" md5sum="6d03025f455869185b57b5c138fd1c01" name="Frontend/md5.js" role="php" />
@@ -145,27 +148,27 @@
    <file baseinstalldir="Auth" md5sum="2070e2661d33de660a39837ecdec8ca7" name="tests/auth_container_mdb_options.php" role="test" />
    <file baseinstalldir="Auth" md5sum="7e41dc017dbc7f9c3841f205736cf2ab" name="tests/auth_container_pop3a_options.php" role="test" />
    <file baseinstalldir="Auth" md5sum="f2884c6ddc8f0405364aad909105f0d5" name="tests/auth_container_pop3_options.php" role="test" />
-   <file baseinstalldir="Auth" md5sum="4bc05df7b07e19894d09f091e09a374d" name="tests/DBContainer.php" role="test" />
-   <file baseinstalldir="Auth" md5sum="86f699d5ac6ca6ea13286e073e95be3e" name="tests/FileContainer.php" role="test" />
-   <file baseinstalldir="Auth" md5sum="cce1cc136b4b2e7a01d84486b0490336" name="tests/MDB2Container.php" role="test" />
-   <file baseinstalldir="Auth" md5sum="42fafd76f8ffc6bab8b3fe852e1aa7aa" name="tests/MDBContainer.php" role="test" />
+   <file baseinstalldir="Auth" md5sum="ad27a7b244511da0c2c75674033c3745" name="tests/DBContainer.php" role="test" />
+   <file baseinstalldir="Auth" md5sum="3b6bb4b847b756f4f25e003ad086bb79" name="tests/FileContainer.php" role="test" />
+   <file baseinstalldir="Auth" md5sum="8c8aaae73d38c31f9fcd0e40759b8794" name="tests/MDB2Container.php" role="test" />
+   <file baseinstalldir="Auth" md5sum="ac86dc743cdd78c350605f4ba4d890d2" name="tests/MDBContainer.php" role="test" />
    <file baseinstalldir="Auth" md5sum="c0ea6513ca30793404fa300c1f82995e" name="tests/mysql_test_db.sql" role="test" />
-   <file baseinstalldir="Auth" md5sum="86d9d9def200d6a967af5aa08badae17" name="tests/POP3aContainer.php" role="test" />
-   <file baseinstalldir="Auth" md5sum="e5f33effb6e18ec52e2aad46f2cf9dc7" name="tests/POP3Container.php" role="test" />
-   <file baseinstalldir="Auth" md5sum="133ab03f3bafa896cd827f059eb8f20b" name="tests/TestAuthContainer.php" role="test" />
+   <file baseinstalldir="Auth" md5sum="470101473f5dc9ab8d0ef35a0f343185" name="tests/POP3aContainer.php" role="test" />
+   <file baseinstalldir="Auth" md5sum="fd933ecf46e31034adc522b7a40aeaa4" name="tests/POP3Container.php" role="test" />
+   <file baseinstalldir="Auth" md5sum="9793164f8f5ef5c8ea538fb4ecc702aa" name="tests/TestAuthContainer.php" role="test" />
    <file baseinstalldir="Auth" md5sum="db9782123c381f0d638ed9ace4f6d42d" name="tests/tests.php" role="test" />
-   <file baseinstalldir="Auth" md5sum="81051bcc2cf1bedf378224b0a93e2877" name="tests/users" role="test" />
+   <file baseinstalldir="Auth" md5sum="68b329da9893e34099c7d8ad5cb9c940" name="tests/users" role="test" />
    <file baseinstalldir="Auth" md5sum="3796a67d8c5d3f281ceb414638f60cfa" name="tests/bug8735.passwd" role="test" />
    <file baseinstalldir="Auth" md5sum="7a5ca7c595123a06d18543b803355158" name="tests/bug8735.phpt" role="test" />
    <file baseinstalldir="Auth" md5sum="797b51ba0f58858ab014771aa1b26fd6" name="examples/logging.php" role="doc" />
    <file baseinstalldir="Auth" md5sum="c0234bbeeb10e24cdb6f64272e5e9831" name="examples/multi-container.php" role="doc" />
-   <file baseinstalldir="" md5sum="289fa024b2d1eda68b7b1b0c9f877493" name="Auth.php" role="php">
+   <file baseinstalldir="" md5sum="bc968f3ae2988c01ba3942a6adcd2396" name="Auth.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
-   <file baseinstalldir="Auth" md5sum="b1dc665b8f34b2c0743b8065f0afedbf" name="Container.php" role="php">
+   <file baseinstalldir="Auth" md5sum="95df5c9be54212acd608698daa8abc86" name="Container.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
-   <file baseinstalldir="Auth" md5sum="f5632fbe6d758b2da9af3f54485d0398" name="README.Auth" role="doc" />
+   <file baseinstalldir="Auth" md5sum="38eac955611c0458f057799e6160a361" name="README.Auth" role="doc" />
    <file baseinstalldir="Auth" md5sum="14012d9f7ed31ca900dc177cc37df9b5" name="README.AdvancedSecurity" role="doc" />
   </dir>
  </contents>
@@ -264,6 +267,24 @@
  <changelog>
   <release>
    <date>2008-04-04</date>
+   <time>15:33:00</time>
+   <version>
+    <release>1.6.1</release>
+    <api>1.5.0</api>
+   </version>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <license uri="http://www.php.net/license">PHP License</license>
+   <notes>
+* Actually included the new NetVPOPMaild container file.
+	  *mutter*grumble*stupid package.xml*grumble*mutter*
+* Fix Bug #13578: Parse errors in DB Containers
+   </notes>
+  </release>
+  <release>
+   <date>2008-04-04</date>
    <time>10:35:00</time>
    <version>
     <release>1.6.0</release>
@@ -274,7 +295,8 @@
     <api>stable</api>
    </stability>
    <license uri="http://www.php.net/license">PHP License</license>
-   <notes>* Fixed Bug #12112: Advanced Security Cookie has different settings to
+   <notes>
+* Fixed Bug #12112: Advanced Security Cookie has different settings to
   session cookie.
 * Implemented Request #13337: New vpopmail container utilising Net_Vpopmaild.
   Patch supplied by Bill Shupp (shupp)
@@ -287,7 +309,8 @@
 * Implemented Request #12087: Ability to select which Advanced Security options
   are used.
 * Fixed Doc Bug #12156: Correction to doc page for Auth::setSessionName() by
-  Adam Harvey (aharvey)</notes>
+  Adam Harvey (aharvey)
+   </notes>
   </release>
   <release>
    <date>2007-07-02</date>
@@ -301,8 +324,10 @@
     <api>stable</api>
    </stability>
    <license uri="http://www.php.net/license">PHP License</license>
-   <notes>* Fixed Bug #11499: Redundant parameter in Auth_Container_SOAP5::_validateOptions()
-  definition. Thanks to Koles Mihaly for spotting this.</notes>
+   <notes>
+* Fixed Bug #11499: Redundant parameter in Auth_Container_SOAP5::_validateOptions()
+  definition. Thanks to Koles Mihaly for spotting this.
+   </notes>
   </release>
   <release>
    <date>2007-07-02</date>
@@ -316,13 +341,15 @@
     <api>stable</api>
    </stability>
    <license uri="http://www.php.net/license">PHP License</license>
-   <notes>* Fixed Bug: If Auth::setSessionName() is called new session name variable is
+   <notes>
+* Fixed Bug: If Auth::setSessionName() is called new session name variable is
   not initialised so checks for session storage fail.
 * Fixed Bug #11396: Auth_Container_Pear doesn&apos;t work with latest changes to
   pear.php.net. Fix by Adam Harvey.
 * Fixed Bug #11476: SOAP5 container&apos;s _validateOptions() and _setDefaults()
   functions where setting options into the wrong object parameter. Thanks to
-  Köles Mihály for fix.</notes>
+  Köles Mihály for fix.
+   </notes>
   </release>
   <release>
    <date>2007-06-12</date>
@@ -336,10 +363,12 @@
     <api>stable</api>
    </stability>
    <license uri="http://www.php.net/license">PHP License</license>
-   <notes>* Feature Request #10729: Optionally regenerate session id on every page request.
+   <notes>
+* Feature Request #10729: Optionally regenerate session id on every page request.
   Thanks to Bernhard for patch.
 * Fixed Bug #10785: Notice when Auth::logout() called with a login callback
-  defined but no user logged in. Suggested fix thanks to Sascha Grossenbacher.</notes>
+  defined but no user logged in. Suggested fix thanks to Sascha Grossenbacher.
+   </notes>
   </release>
   <release>
    <date>2007-03-23</date>
@@ -353,9 +382,11 @@
     <api>stable</api>
    </stability>
    <license uri="http://www.php.net/license">PHP License</license>
-   <notes>* Added missing optional dependancy on PEAR Log to package.xml
+   <notes>
+* Added missing optional dependancy on PEAR Log to package.xml
 * Fixed Bug #10125: Auth_Container_LDAP::fetchData only fetching attributes for
-  first entry.</notes>
+  first entry.
+   </notes>
   </release>
   <release>
    <date>2007-02-13</date>
@@ -369,7 +400,8 @@
     <api>stable</api>
    </stability>
    <license uri="http://www.php.net/license">PHP License</license>
-   <notes>* Completed Request #2229: Ability to attach fall through containers. This
+   <notes>
+* Completed Request #2229: Ability to attach fall through containers. This
   is implemented through the use of a new container Auth_Container_Multiple.
   See multi-container.php in examples directory.
 * Completed Request #4126: Enhancements to Advanced Security Mode. Thanks
@@ -381,7 +413,8 @@
 * Fixed Bug #9944: Logging constants not defined when logging disabled.
 * Fixed Bug #10000: Stupid developer didn&apos;t stop to look what he was doing
   and broke things.
-* Fixed Bug #10004: Logging of connection failures in LDAP container missing.</notes>
+* Fixed Bug #10004: Logging of connection failures in LDAP container missing.
+   </notes>
   </release>
   <release>
    <date>2007-02-02</date>
@@ -395,10 +428,12 @@
     <api>stable</api>
    </stability>
    <license uri="http://www.php.net/license">PHP License</license>
-   <notes>* Fixed Bug #9944: Logging constants not defined when logging disabled.
+   <notes>
+* Fixed Bug #9944: Logging constants not defined when logging disabled.
 * Fixed Bug #10000: Stupid developer didn&apos;t stop to look what he was doing
   and broke things.
-* Fixed Bug #10004: Logging of connection failures in LDAP container missing.</notes>
+* Fixed Bug #10004: Logging of connection failures in LDAP container missing.
+   </notes>
   </release>
   <release>
    <date>2007-01-17</date>
@@ -412,7 +447,8 @@
     <api>stable</api>
    </stability>
    <license uri="http://www.php.net/license">PHP License</license>
-   <notes>* Completed Request #2229: Ability to attach fall through containers. This
+   <notes>
+* Completed Request #2229: Ability to attach fall through containers. This
   is implemented through the use of a new container Auth_Container_Multiple.
   See multi-container.php in examples directory.
 * Completed Request #4126: Enhancements to Advanced Security Mode. Thanks
@@ -422,7 +458,8 @@
 * Completed Request #7089: Add optional extra WHERE options to DB and MDB(2) 
   containers.
 * Add ability to pass an instanciated DB, MDB or MDB2 database connection to each
-  of the respective Auth Containers.</notes>
+  of the respective Auth Containers.
+   </notes>
   </release>
   <release>
    <date>2006-12-06</date>
@@ -436,11 +473,13 @@
     <api>stable</api>
    </stability>
    <license uri="http://www.php.net/license">PHP License</license>
-   <notes>* Fixed Bug #9380: Default Auth_Container_POP3 configuration not 
+   <notes>
+* Fixed Bug #9380: Default Auth_Container_POP3 configuration not 
   working.
 * Fixed Bug #9407: Add callback in checkAuth() process.
 * Fixed Bug #9479: Typo in Auth_Container_KADM5::_checkServer causes
-  failure. Thanks to Matt T. Proud (khanreaper at nerp dot net).</notes>
+  failure. Thanks to Matt T. Proud (khanreaper at nerp dot net).
+   </notes>
   </release>
   <release>
    <date>2006-11-10</date>
@@ -454,10 +493,12 @@
     <api>stable</api>
    </stability>
    <license uri="http://www.php.net/license">PHP License</license>
-   <notes>* Fixed Bug #9241: Callback functions where being passed a copy of
+   <notes>
+* Fixed Bug #9241: Callback functions where being passed a copy of
   the login object instead of a reference to it under PHP4.
 * Fixed Bug #9286: Comparison of passwords and their hashes could give
-  false positive.</notes>
+  false positive.
+   </notes>
   </release>
   <release>
    <date>2006-10-28</date>
@@ -471,7 +512,9 @@
     <api>stable</api>
    </stability>
    <license uri="http://www.php.net/license">PHP License</license>
-   <notes>* Forgot to add Auth/Container/Array.php to package2.xml.</notes>
+   <notes>
+* Forgot to add Auth/Container/Array.php to package2.xml.
+   </notes>
   </release>
   <release>
    <date>2006-10-20</date>
@@ -485,7 +528,8 @@
     <api>stable</api>
    </stability>
    <license uri="http://www.php.net/license">PHP License</license>
-   <notes>* Added new SOAP container that makes use of the PHP5 SOAP Client. Thanks to
+   <notes>
+* Added new SOAP container that makes use of the PHP5 SOAP Client. Thanks to
   Marcel Oelke &lt;puRe at rednoize dot com&gt;. Fixes #2612.
 * Added support for trying all the user accounts returned from an LDAP server
   not just the first one so as to support authenticating against Lotus Notes
@@ -508,7 +552,8 @@
   SQLite returns the name of quoted field names including the quotes instead
   of stripping the quotes like all other DBs.
 * Fix Bug #8735: Auth_Container_File::addUser() working on different instances
-  of File_Passwrd object.</notes>
+  of File_Passwrd object.
+   </notes>
   </release>
   <release>
    <date>2006-09-21</date>
@@ -522,11 +567,13 @@
     <api>stable</api>
    </stability>
    <license uri="http://www.php.net/license">PHP License</license>
-   <notes>* Fix Bug #8732: Auth_Container_DB having problems with SQLite databases.
+   <notes>
+* Fix Bug #8732: Auth_Container_DB having problems with SQLite databases.
   SQLite returns the name of quoted field names including the quotes instead
   of stripping the quotes like all other DBs.
 * Fix Bug #8735: Auth_Container_File::addUser() working on different instances
-  of File_Passwrd object.</notes>
+  of File_Passwrd object.
+   </notes>
   </release>
   <release>
    <date>2006-09-11</date>
@@ -540,7 +587,8 @@
     <api>stable</api>
    </stability>
    <license uri="http://www.php.net/license">PHP License</license>
-   <notes>* Added new SOAP container that makes use of the PHP5 SOAP Client. Thanks to
+   <notes>
+* Added new SOAP container that makes use of the PHP5 SOAP Client. Thanks to
   Marcel Oelke &lt;puRe at rednoize dot com&gt;. Fixes #2612.
 * Added support for trying all the user accounts returned from an LDAP server
   not just the first one so as to support authenticating against Lotus Notes
@@ -558,7 +606,8 @@
   http://saprfc.sourceforge.net/. Thanks to Stoyan Stefanov &lt;ssttoo at gmail dot com&gt;.
   Fixes #8637.
 * Fix #8599. Allow identifier quoting in DB, DBLite, MDB and MDB2 backends to 
-  be switched off by developer.</notes>
+  be switched off by developer.
+   </notes>
   </release>
   <release>
    <version>
@@ -571,12 +620,14 @@
    </stability>
    <date>2006-08-31</date>
    <license uri="http://www.php.net/license">PHP License</license>
-   <notes>* Fixed Bug #8524: Notice from attempting to perform string operation on what
+   <notes>
+* Fixed Bug #8524: Notice from attempting to perform string operation on what
   might be an array in DB, DBLite, MDB and MDB2. Thanks to dozoyousan at gmail
   dot com.
 * Remove debug message from RADIUS Container when using CHAP_MD5 or MSCHAPv1
   style passwords. Thanks to Stoyan Stefanov &lt;ssttoo at gmail dot com&gt; for
-  pointing out this 3yr old bug.</notes>
+  pointing out this 3yr old bug.
+   </notes>
   </release>
   <release>
    <version>
@@ -589,7 +640,8 @@
    </stability>
    <date>2006-08-21</date>
    <license uri="http://www.php.net/license">PHP License</license>
-   <notes>* Fixed Bug #7031: session_regenerate_id() not cleaning up old session storage.
+   <notes>
+* Fixed Bug #7031: session_regenerate_id() not cleaning up old session storage.
   Fix for this bug in PHP5.1.0+ has been done, still a problem in older versions
   of PHP.
 * Fixed Bug #7421: Allow false to be passed in for allowLogin and advancedSecurity
@@ -609,7 +661,8 @@
   set function.
 * Fixed Bug #8406: Error message updates by Adam Harvey &lt;pear at adamharvey.name&gt;
 * Fixed Bug #8407: Database containers don&apos;t quote table/field names by Adam
-  Harvey &lt;pear at adamharvey.name&gt;</notes>
+  Harvey &lt;pear at adamharvey.name&gt;
+   </notes>
   </release>
   <release>
    <version>
@@ -622,7 +675,8 @@
    </stability>
    <date>2006-08-11</date>
    <license uri="http://www.php.net/license">PHP License</license>
-   <notes>This release candidate is test the numerous fixes described below. It is also
+   <notes>
+This release candidate is test the numerous fixes described below. It is also
 to get feedback on the change made for Bug #8407. Bug #8407 adds automatic 
 quoting of table and field names used in SQL in the Database backends.
 
@@ -646,7 +700,8 @@
    set function.
  * Fixed Bug #8406: Error message updates by Adam Harvey &lt;pear at adamharvey.name&gt;
  * Fixed Bug #8407: Database containers don&apos;t quote table/field names by Adam
-   Harvey &lt;pear at adamharvey.name&gt;</notes>
+   Harvey &lt;pear at adamharvey.name&gt;
+   </notes>
   </release>
   <release>
    <version>
@@ -659,7 +714,8 @@
    </stability>
    <date>2006-03-03</date>
    <license uri="http://www.php.net/license">PHP License</license>
-   <notes>This is the final stable release of Auth 1.3.0. This version contains many new
+   <notes>
+This is the final stable release of Auth 1.3.0. This version contains many new
 features over previous versions. Summary of changes:
 
  * New MDB2 container [30/March/2004 - quipo]
@@ -676,7 +732,8 @@
 to the following people: Matt Eaton, Jeroen Houben, Cipriano Groenendal,
 Markku Turunen, Matthew Van Gundy, marc at practeo dot ch and I&apos;m sure many
 others that have contributed over the years it&apos;s taken to get this release
-out.</notes>
+out.
+   </notes>
   </release>
   <release>
    <version>
@@ -689,7 +746,8 @@
    </stability>
    <date>2006-03-01</date>
    <license uri="http://www.php.net/license">PHP License</license>
-   <notes>This release is primarily a coding standard clean-up before the 1.3.0 final
+   <notes>
+This release is primarily a coding standard clean-up before the 1.3.0 final
 release.
 
 In addition the following improvements to the LDAP Container where supplied
@@ -701,7 +759,8 @@
    as array the same as db_fields in the DB, MDB and MDB2 backends.
 
 Finally there are additional checks that the relevant PHP module is loaded
-when loading the IMAP and VPOPMail Containers.</notes>
+when loading the IMAP and VPOPMail Containers.
+   </notes>
   </release>
   <release>
    <version>
@@ -714,7 +773,9 @@
    </stability>
    <date>2006-02-22</date>
    <license uri="http://www.php.net/license">PHP License</license>
-   <notes />
+   <notes>
+
+   </notes>
   </release>
   <release>
    <version>
@@ -727,7 +788,8 @@
    </stability>
    <date>2006-02-21</date>
    <license uri="http://www.php.net/license">PHP License</license>
-   <notes>* Fixed Bug #2873: Allow calling programs to gracefully handle being unable
+   <notes>
+* Fixed Bug #2873: Allow calling programs to gracefully handle being unable
   to connect/bind to LDAP server.
 * Fixed Bug #4918: Added support to specify which authentication method to 
   prefer when authenticating against a POP3 backend.
@@ -738,7 +800,8 @@
 * Fixed Bug #6803: depreciated DB function. Now requires DB &gt;= 1.6.0
 * Fixed Bug #6808: Whenever Auth_Container_DB attempts to change the database 
   make sure the connection/DB object exists and is correct before attempting to
-  use the DB quoting features.</notes>
+  use the DB quoting features.
+   </notes>
   </release>
   <release>
    <version>
@@ -751,7 +814,8 @@
    </stability>
    <date>2006-02-14</date>
    <license uri="http://www.php.net/license">PHP License</license>
-   <notes>This release fixes a security issue that allows an attacker to perform
+   <notes>
+This release fixes a security issue that allows an attacker to perform
 injection attacks against the underlying storage containers.  Upgrading
 is strongly recommended if you are using beta releases of the Auth
 package.
@@ -770,7 +834,8 @@
   supportsChallengeResponce(). Also all containers already
   supportsChallengeResponse() instead of supportsChallengeResponce() and
   therefore the call in Auth_Frontend_Html always called the default
-  implementation and not the container implementation.</notes>
+  implementation and not the container implementation.
+   </notes>
   </release>
   <release>
    <version>
@@ -783,7 +848,8 @@
    </stability>
    <date>2004-08-07</date>
    <license uri="http://www.php.net/license">PHP License</license>
-   <notes>* Moved login screen generation code to Auth/Frontend/Html.php 
+   <notes>
+* Moved login screen generation code to Auth/Frontend/Html.php 
   In the future the frontend will be configurable.
 * Implemented support for Challenge / Responce password authenthication
   have to enable advanced security $auth-&gt;setAdvancedSecurity
@@ -798,7 +864,8 @@
 * Auth::importGlobalVariable method was removed and replaced by references to global variables
 * Removed all calls to $session[$this-&gt;_sessionName], made local reference session point to that instead
 * Changed call_user_func to call_user_func_array for the callbacks, to avoid using @ for passing variables by reference
-* Code Cleanup, removed most vi comments</notes>
+* Code Cleanup, removed most vi comments
+   </notes>
   </release>
   <release>
    <version>
@@ -811,7 +878,8 @@
    </stability>
    <date>2004-06-04</date>
    <license uri="http://www.php.net/license">PHP License</license>
-   <notes>* Changes to LDAP container:
+   <notes>
+* Changes to LDAP container:
   - check for loaded ldap extension at startup as suggested by Markku Turunen
   - make ldap version configurable via config array
   - documentation fix for active directory default user container
@@ -839,7 +907,8 @@
 * Fixed bug noted by Jeroen Houben &lt;jeroen at terena.nl&gt;, calling loginFailedCallback
   would not have the proper status set [16/Jan/2004 - yavo]
 * Added PEAR container, authenticate the user against the pear web site
-  (probably php.net also) [16/Dec/2003 - yavo]</notes>
+  (probably php.net also) [16/Dec/2003 - yavo]
+   </notes>
   </release>
   <release>
    <version>
@@ -852,7 +921,8 @@
    </stability>
    <date>2003-09-08</date>
    <license uri="http://www.php.net/license">PHP License</license>
-   <notes>* new Method to auth_container getUser()
+   <notes>
+* new Method to auth_container getUser()
 * New Auth_Container_File, using new File_Passwd class. Provided by Michael Wallner &lt;mike at php.net&gt;
 * Login/Logout callbacks now get a reference to auth
 * New Login Failed Callback added (method setFailedLoginCallback)
@@ -863,7 +933,8 @@
 *Some patches from the pear-dev list bellow
     -maka3d at yahoo.com.br - Patch to use a method of the container in Auth_Container::verifyPassword
     -Lorenzo Alberton &lt;l.alberton at quipo.it&gt; - Patch to use variable session variable name, untill now the variable auth was used
-    -Marcos Neves &lt;maka3d at yahoo.com.br&gt; - Avaoid error when calling getAuthData() before the login</notes>
+    -Marcos Neves &lt;maka3d at yahoo.com.br&gt; - Avaoid error when calling getAuthData() before the login
+   </notes>
   </release>
   <release>
    <version>
@@ -876,13 +947,15 @@
    </stability>
    <date>2003-07-29</date>
    <license uri="http://www.php.net/license">PHP License</license>
-   <notes>* Added support for passing contaner as an object
+   <notes>
+* Added support for passing contaner as an object
 * Added fix when db_fileds is *
 * Added Test Suite (experimental)
 * Added generic support for arbitrary password crypting functions
   different than MD5, DES and plain text. (Patch by Tom Anderson)
 * Added new MDB storage container written by Lorenzo Alberton
-* Added new Container for SAMBA password files (SMBPasswd)</notes>
+* Added new Container for SAMBA password files (SMBPasswd)
+   </notes>
   </release>
  </changelog>
 </package>




More information about the Pkg-php-commits mailing list