[geeklog-cvs] Auth_Enterprise/Client BaseClientProvider.php,NONE,1.1 Client.php,NONE,1.1 ClientConstants.php,NONE,1.1 ClientProviderFactory.php,NONE,1.1 LocalhostClient.php,NONE,1.1 User.php,NONE,1.1 XMLRPCClient.php,NONE,1.1

tony at iowaoutdoors.org tony at iowaoutdoors.org
Sun Jul 4 11:02:58 EDT 2004


Update of /var/cvs/Auth_Enterprise/Client
In directory www:/tmp/cvs-serv23527

Added Files:
	BaseClientProvider.php Client.php ClientConstants.php 
	ClientProviderFactory.php LocalhostClient.php User.php 
	XMLRPCClient.php 
Log Message:
These files existed before as AE<classname>.class.php.  PEAR standards required their class and file names be changed.


--- NEW FILE: XMLRPCClient.php ---
<?php

/**
* Auth_Enterprise
*
* This source file is subject to version 2.02 of the PHP license, that is bundled with this package
* in the file LICENSE, and is available at through the world-wide-web at
* http://www.php.net/license/2_02.txt. If you did not receive a copy of the PHP license and are
* unable to obtain it through the world-wide-web, please send a note to license at php.net so we can
* mail you a copy immediately.
*
* @author Tony Bibbs <tony at geeklog.net>
* @copyright 2004
* @version $Id: XMLRPCClient.php,v 1.1 2004/07/04 15:02:55 tony Exp $
*
*/

/**
* Auth_Enterprise abstract client provider
*/
require_once 'Auth/Enterprise/Client/BaseClientProvider.php';

/**
* Auth_Enterprise constants
*/
require_once 'Auth/Enterprise/Common/Constants.php';

/**
* Auth_Enterprise exceptions
*/
require_once 'Auth/Enterprise/Common/Exceptions.php';

/**
* PEAR's XML RPC Client
*/
require_once 'XML/RPC.php';

/**
* Auth_Enteprise XML RPC Implementation
*
* @author Tony Bibbs <tony at geeklog.net>
* @package net.geeklog.auth_enterprise.client
* @todo Need to implement SSL soon
* 
*/
class Enterprise_XMLRPCClient extends Enterprise_BaseClientProvider {
    /**
    * Instance of PEAR XML RPC Client
    * @access private
    * @var object
    */
    private $XMLRPCClient = null;
    
    /**
    * Array of Auth_Enterprise server provider options
    * @access private
    * @var array
    */
    private $options = null;
    
    /**
    * Constructor
    *
    * Get handle to an instance of XML RPC Client.  This client provider has the following options:
    *   - appId string Auth_Enterprise ID given to an application, REQUIRED
    *   - debug int 1=on, 0=off, OPTIONAL
    *   - path string path on server to send request to, REQUIRED
    *   - server string server to send request to, REQUIRED
    *   - port int port on server to talk over, REQUIRED
    *   - proxy string proxy server to use, OPTIONAL
    *   - proxyPort int port on proxy to talk over, OPTIONAL
    *   - proxyUser string username to authentication to proxy with, OPTIONAL
    *   - proxyPassword string password to authenticate to proxy with, OPTIONAL
    *   - server_method string Can be http or https, http is default, OPTIONAL
    *   - xmlrpc_interface string Can be PEAR or PHP.  PHP requires PHP to be compiled
    *   --with-xmlrpc OPTIONAL
    *   
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @param string $options Array of options for the XML RPC Client
    * @todo refactor to support PHP's native XMLRPC methods as an alternative to using PEAR's
    * implementation.  This can be done without breaking client compatibility so I'm not in any rush yet.
    *
    */
    public function __construct($options)
    {
        if (empty($options['appId']) OR empty($options['path']) OR empty($options['server']) OR
            empty($options['port'])) {
                throw new AEInsufficientClientOptions('Options given to the XMLRPCClient are not
                    sufficient');
        }
        
        // Cache options for later use
        $this->options = $options;
        
        // Default server method to use http
        if (strtolower($options['server_method']) <> 'http' AND strtolower($options['server_method'] <> 'https')) {
            $this->options['server_method'] = 'http';
        } else {
            // Just in case it matters (which it probably doesn't) set method to lower case.
            $this->options['server_method'] = strtolower($this->options['server_method']);
        }
        
        // Call constructor of parent
        try {
            parent::__construct($options);
        } catch (Exception $error) {
            die($error->getMessage());
        }
        
        // Build XMLRPC client
        $this->XMLRPCClient = new XML_RPC_Client($options['path'], $options['server']
            , $options['port'], $options['proxy'], $options['proxyPort'], $options['proxyUser']
            , $options['proxyPassword']);
            
        // Enable debugging if requested.
        if ($options['debug'] == 1) {
            $this->XMLRPCClient->setDebug(true);
        }
    }
    
    /**
    * Authenticates a user to an application
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @param string $userName Username to authenticate with
    * @param string $password Password to authenticate with
    * @return object AEServiceUser object
    *
    */
    public function authenticate($userName, $password)
    {
        $xmlRequest = new XML_RPC_Message('Auth_Enterprise.processRequest'
            , array(new XML_RPC_Value('authenticate','string')
                , new XML_RPC_Value($this->getAppId(), 'string')
                , new XML_RPC_Value($userName, 'string')
                , new XML_RPC_Value($password, 'string')));
        $response = $this->XMLRPCClient->send($xmlRequest, 0, $this->options['server_method']);
        
        // If we got a fault, throw an exception back to the calling
        // application
        if ($response->faultCode()) {
            try {
                $e = $this->faultToException($response->faultCode(), $response->faultString());
                throw $e;
            } catch (AEBaseException $e) {
                throw $e;
            }
        }
        
        $retval = $response->value();
        $retval = XML_RPC_decode($retval);
        $user = new AEUser();
        $user->setUserName($retval['userName']);
        $user->setPassword($retval['password']);
        //$user->setPrivileges($this->arrayToPrivileges($retval['privileges']));
        //$user->setGroups($this->arrayToGroups($retval['groups']));
        
        return $user;
    }
    
    /**
    * Registers a new account with the service
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    *
    */
    public function createAccountByAdmin($adminUserName, $adminPassword, $userName, $userPassword)
    {
        $xmlRequest = new XML_RPC_Message('Auth_Enterprise.processRequest'
            , array(new XML_RPC_Value('createAccount','string')
                , new XML_RPC_Value($this->getAppId(), 'string')
                , new XML_RPC_Value($adminUserName, 'string')
                , new XML_RPC_Value($adminPassword, 'string')
                , new XML_RPC_Value($userName, 'string')
                , new XML_RPC_Value($password, 'string')));
        $response = $this->XMLRPCClient->send($xmlRequest, 0, $this->options['server_method']);
        // If we got a fault, throw an exception back to the calling
        // application
        if ($response->faultCode()) {
            throw $this->faultToException($response->faultCode(), $response->faultString());
        }
        $retval = $response->value();
        $retval = XML_RPC_decode($retval);
    }
    
    /**
    * Changes a user's password
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    *
    */
    public function changePassword($userName, $newPassword)
    {
        $xmlRequest = new XML_RPC_Message('Auth_Enterprise.processRequest'
            , array(new XML_RPC_Value('changePassword','string')
                , new XML_RPC_Value($this->getAppId(), 'string')
                , new XML_RPC_Value($userName, 'string')
                , new XML_RPC_Value($newPassword, 'string')));
        $response = $this->XMLRPCClient->send($xmlRequest, 0, $this->options['server_method']);
        // If we got a fault, throw an exception back to the calling
        // application
        if ($response->faultCode()) {
            throw $this->faultToException($response->faultCode(), $response->faultString());
        }
    }
    
    /**
    * Allows an application level admin to change a
    * user's password
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    *
    */
    public function changePasswordByAdmin($adminUserName, $adminPassword, $userName, $newPassword)
    {
        $xmlRequest = new XML_RPC_Message('Auth_Enterprise.processRequest'
            , array(new XML_RPC_Value('changePasswordByAdmin','string')
                , new XML_RPC_Value($this->getAppId(), 'string')
                , new XML_RPC_Value($adminUserName, 'string')
                , new XML_RPC_Value($adminPassword, 'string')
                , new XML_RPC_Value($userName, 'string')
                , new XML_RPC_Value($newPassword, 'string')));
        $response = $this->XMLRPCClient->send($xmlRequest, 0, $this->options['server_method']);
        // If we got a fault, throw an exception back to the calling
        // application
        if ($response->faultCode()) {
            throw $this->faultToException($response->faultCode(), $response->faultString());
        }
    }
    
    /**
    * Resets a user's password
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    *
    */
    public function resetPassword($userName)
    {
        $xmlRequest = new XML_RPC_Message('Auth_Enterprise.processRequest'
            , array(new XML_RPC_Value('resetPassword','string')
                , new XML_RPC_Value($this->getAppId(), 'string')
                , new XML_RPC_Value($userName, 'string')));
        $response = $this->XMLRPCClient->send($xmlRequest, 0, $this->options['server_method']);
        // If we got a fault, throw an exception back to the calling
        // application
        if ($response->faultCode()) {
            throw $this->faultToException($response->faultCode(), $response->faultString());
        }
        $retval = $response->value();
        $retval = XML_RPC_decode($retval);
    }
    
    /**
    * Gets the application privileges for a given user
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    *
    */
    public function getUserPrivilegesByAdmin($adminUserName, $adminPassword, $userName)
    {
        $xmlRequest = new XML_RPC_Message('Auth_Enterprise.processRequest'
            , array(new XML_RPC_Value('getUserPrivilegesByAdmin','string')
                , new XML_RPC_Value($this->getAppId(), 'string')
                , new XML_RPC_Value($adminUserName, 'string')
                , new XML_RPC_Value($adminPassword, 'string')
                , new XML_RPC_Value($userName, 'string')));
        $response = $this->XMLRPCClient->send($xmlRequest, 0, $this->options['server_method']);
        // If we got a fault, throw an exception back to the calling
        // application
        if ($response->faultCode()) {
            throw $this->faultToException($response->faultCode(), $response->faultString());
        }
        $retval = $response->value();
        $retval = XML_RPC_decode($retval);
        
        $retval = $this->arrayToPrivileges($retval);
        
        return $retval;
    }
    
    /**
    * Sets the application privileges for a given user
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    *
    */
    public function setUserPrivilegesByAdmin($adminUserName, $adminPassword, $userName, $privArray)
    {
        $xmlRequest = new XML_RPC_Message('Auth_Enterprise.processRequest'
            , array(new XML_RPC_Value('setUserPrivilegesByAdmin','string')
                , new XML_RPC_Value($this->getAppId(), 'string')
                , new XML_RPC_Value($adminUserName, 'string')
                , new XML_RPC_Value($adminPassword, 'string')
                , new XML_RPC_Value($userName, 'string')
                , XML_RPC_Encode($this->privilegesToArray($privArray))));
        $response = $this->XMLRPCClient->send($xmlRequest, 0, $this->options['server_method']);
        // If we got a fault, throw an exception back to the calling
        // application
        if ($response->faultCode()) {
            throw $this->faultToException($response->faultCode(), $response->faultString());
        }
    }
    
    /**
    * Lists all available privileges for a given application
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    *
    */
    public function listAppPrivilegesByAdmin($adminUserName, $adminPassword)
    {
        $xmlRequest = new XML_RPC_Message('Auth_Enterprise.processRequest'
            , array(new XML_RPC_Value('listAppPrivilegesByAdmin','string')
                , new XML_RPC_Value($this->getAppId(), 'string')
                , new XML_RPC_Value($adminUserName, 'string')
                , new XML_RPC_Value($adminPassword, 'string')));
        $response = $this->XMLRPCClient->send($xmlRequest, 0, $this->options['server_method']);
        // If we got a fault, throw an exception back to the calling
        // application
        if ($response->faultCode()) {
            throw $this->faultToException($response->faultCode(), $response->faultString());
        }
        $retval = $response->value();
        $retval = XML_RPC_decode($retval);
        $retval = $this->arrayToPrivileges($retval);
        return $retval;
    }
    
    /**
    * Gets the application privileges for a given user
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    *
    */
    public function getUserGroupsByAdmin($adminUserName, $adminPassword, $userName)
    {
        $xmlRequest = new XML_RPC_Message('Auth_Enterprise.processRequest'
            , array(new XML_RPC_Value('getUserGroupsByAdmin','string')
                , new XML_RPC_Value($this->getAppId(), 'string')
                , new XML_RPC_Value($adminUserName, 'string')
                , new XML_RPC_Value($adminPassword, 'string')
                , new XML_RPC_Value($userName, 'string')));
        $response = $this->XMLRPCClient->send($xmlRequest, 0, $this->options['server_method']);
        // If we got a fault, throw an exception back to the calling
        // application
        if ($response->faultCode()) {
            //throw $this->faultToException($response->faultCode(), $response->faultString());
        }
        $retval = $response->value();
        $retval = XML_RPC_decode($retval);
        $retval = $this->arrayToGroups($retval);
        
        return $retval;
    }
    
    /**
    * Sets the application privileges for a given user
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    *
    */
    public function setUserGroupsByAdmin($adminUserName, $adminPassword, $userName, $groupArray)
    {
        $xmlRequest = new XML_RPC_Message('Auth_Enterprise.processRequest'
            , array(new XML_RPC_Value('setUserGroupsByAdmin','string')
                , new XML_RPC_Value($this->getAppId(), 'string')
                , new XML_RPC_Value($adminUserName, 'string')
                , new XML_RPC_Value($adminPassword, 'string')
                , new XML_RPC_Value($userName, 'string')
                , XML_RPC_Encode($this->groupsToArray($groupArray))));
        $response = $this->XMLRPCClient->send($xmlRequest, 0, $this->options['server_method']);
        // If we got a fault, throw an exception back to the calling
        // application
        if ($response->faultCode()) {
            throw $this->faultToException($response->faultCode(), $response->faultString());
        }
    }
    
    /**
    * Copies the group arrays returned from the XML_RPC call
    * into Group objects
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access private
    * @param array $groupArray Array of group arrays
    * @return array Array of AEGroup objects
    *
    */
    private function moveGroupsToObjects($groups)
    {
        $groupArray = array();
        $tmpGroup = new AEGroup();
        foreach ($groups as $curGroup) {
            $tmpGroup->setGroupId($curGroup[_groupId]);
            $tmpGroup->setGroupLogicalName($curGroup['groupLogicalName']);
            $tmpGroup->setGroupDisplayName($curGroup['groupDisplayName']);
            $tmpGroup->setGroupDesc($curGroup[_groupDesc]);
            $groupArray[] = $tmpGroup;
        }
        return $groupArray;
    }
    
    /**
    * Converts an array from an XMLRPC response to an array of privileges objects
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access private
    * @param array $privArray Array representing privilege objects
    * @return array Array of actual AEPrivileges objects
    *
    */
    private function arrayToPrivileges($privArray)
    {
        $retval = array();
        if (is_array($privArray)) {
            foreach ($privArray as $curPriv) {
                $newPriv = new Enterprise_Privilege();
                $newPriv->setPrivilegeCode($curPriv['privilegeCode']);
                $newPriv->setPrivilegeDesc($curPriv['privilegeDesc']);
                $retval[] = $newPriv;
            }
        }
        return $retval;
    }
    
    /**
    * Converts AEPrivilege objects to arrays.
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access private
    * @param array $privArray Array of AEPrivilege objects
    * @return array Array representing AEPrivielge objects
    *
    */
    private function privilegesToArray($privArray)
    {
        $retval = array();
        foreach ($privArray as $curPriv) {
            $tmpArray['privilegeCode'] = $curPriv->getPrivilegeCode();
            $tmpArray['privilegeDesc'] = $curPriv->getPrivilegeDesc();
            $retval[] = $tmpArray;
        }
        return $retval;
    }
    
    /**
    * Converts an array from an XMLRPC response to an array of group objects
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access private
    * @param array $groupArray Array representing group objects
    * @return array Array of actual AEGroup objects
    *
    */
    private function arrayToGroups($groupArray)
    {
        $retval = array();
        if (is_array($groupArray)) {
            foreach ($groupArray as $curGroup) {
                $tmpGroup = new Enterprise_Group();
                $tmpGroup->setGroupId($curGroup['groupId']);
                $tmpGroup->setGroupLogicalName($curGroup['groupLogicalName']);
                $tmpGroup->setGroupDisplayName($curGroup['groupDisplayName']);
                $tmpGroup->setGroupDesc($curGroup['groupDesc']);
                $tmpGroup->setGroupPrivileges($curGroup['priviliges']);
                $retval[] = $tmpGroup;
            }
        }
        return $retval;
    }
    
    /**
    * Converts AEPrivilege objects to arrays.
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access private
    * @param array $privArray Array of AEPrivilege objects
    * @return array Array representing AEPrivielge objects
    *
    */
    private function groupsToArray($groupArray)
    {
        $retval = array();
        foreach ($groupArray as $curGroup) {
            $tmpArray['groupId'] = $curGroup->getGroupId();
            $tmpArray['groupLogicalName'] = $curGroup->getGroupLogicalName();
            $tmpArray['groupDisplayName'] = $curGroup->getGroupDisplayName();
            $tmpArray['groupDesc'] = $curGroup->getGroupDesc();
            $retval[] = $tmpArray;
        }
        return $retval;
    }
    
    /**
    * Converts XML_RPC faults into exceptions
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access private
    * @param int $faultCode XMLRPC fault code
    * @param string $faultMessage XMLRPC fault message
    * @return object PHP5 exception
    *
    */
    private function faultToException($faultCode, $faultMessage)
    {
        switch ($faultCode) {
            case AESQLExceptionResp:
                throw new AESQLException($faultMessage);
                break;
            case AEInvalidUserCredentialsResp:
                throw new AEInvalidUserCredentials($faultMessage);
                break;
            case AEAccountLockedResp:
                throw new AEAccountLocked($faultMessage);
                break;
            case AEPasswordExpiredResp:
                throw new AEPasswordExpired($faultMessage);
                break;
            case AEPasswordInHistoryResp:
                throw new AEPasswordInHistory($faultMessage);
                break;
            case AEPasswordInvalidResp:
                throw new AEPasswordInvalid($faultMessage);
                break;
            case AEUnableToConnectResp:
                throw new AEUnableToConnect($faultMessage);
                break;
            case AEUserNotAuthorizedResp:
                throw new AEUserNotAuthorized($faultMessage);
                break;
            case AEInvalidPrivilegeResp:
                throw new AEInvalidPrivilege($faultMessage);
                break;
            case AEInsufficientClientOptionsResp:
                throw new AEInsufficientClientOptions($faultMessage);
                break;
            case AENoProviderResp:
                throw new AENoProvider($faultMessage);
                break;
            case AELDAPBindErrorResp:
                throw new AELDAPBindError($faultMessage);
                break;
            case AENoAppIdResp:
                throw new AENoAppId($faultMessage);
                break;
            default:
                throw new Exception($faultMessage);
            
        }
    }
}

?> 
--- NEW FILE: LocalhostClient.php ---
<?php

/**
* Auth_Enterprise
*
* This source file is subject to version 2.02 of the PHP license, that is bundled with this package
* in the file LICENSE, and is available at through the world-wide-web at
* http://www.php.net/license/2_02.txt. If you did not receive a copy of the PHP license and are
* unable to obtain it through the world-wide-web, please send a note to license at php.net so we can
* mail you a copy immediately.
*
* @author Tony Bibbs <tony at geeklog.net>
* @copyright 2004
* @version $Id: LocalhostClient.php,v 1.1 2004/07/04 15:02:55 tony Exp $
*
*/

/**
* Abstract client provider
*/
require_once 'Auth/Enterprise/Client/Enterprise_BaseClientProvider.php';

/**
* The servers provider factory
*/
require_once 'Auth/Enterprise/Server/Enterprise_ServerProviderFactory.php';

/**
* Auth_Enteprise Localhost Implementation
*
* If your application is running on the same server as the
* Auth_Enterprise server then your application should be configured
* to use this client provider as it will call methods on the server
* directly.  Most other client providers will communicate to the
* server via sockets which is an expensive and unnecessary.
*
* @author Tony Bibbs <tony at geeklog.net>
* @package net.geeklog.auth_enterprise.client
*
*/
class Enterprise_LocalhostClient extends Enterprise_BaseClientProvider {
    /**
    * Handle to server-side provider for our application
    * @access private
    * @var object
    */
    private $provider = null;
    
    /**
    * Constructor
    *
    * Get handle to an instance of XML RPC Client
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @param array $options Array of options specific to this client provider
    *
    */
    public function __construct($options)
    {
        // Have parent set the app ID for us
        parent::__construct($options);
        
        // Set options for this client provider.
        $this->options = $options;
    }
    
    /**
    * Authenticates a user to an application
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @param string $userName User to authenticate
    * @param string $password Password to use during authentication
    * @return object User object
    * 
    */
    public function authenticate($userName, $password)
    {
        // Authenticate directly against the service
        $provider = $this->getServerProvider();
        try {
            $user = $provider->authenticate($userName, $password);
        } catch (AEInvalidUserCredentials $e) {
            die($e->getMessage());
        }
        
        // Convert service user to a client user object
        $user = $this->serverUserToClientUser($user);
        
        return $user;
    }
    
    /**
    * Registers a new account with the service
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    *
    */
    public function createAccountByAdmin($adminUserName, $adminPassword, $userName, $userPassword)
    {
        $provider = $this->getServerProvider();
        try {
            $provider->createAccountByAdmin($adminUserName, $adminPassword, $userName, $userPassword);
        } catch (Exception $e) {
            die($e->getMessage());
        }
    }
    
    /**
    * Changes a user's password
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    *
    */
    public function changePassword($userName, $newPassword)
    {
        $provider = $this->getServerProvider();
        
        try {
            $provider->changePassword($userName, $newPassword);
        } catch (AEPasswordInvalid $e) {
            die($e->getMessage());
        }
    }
    
    /**
    * Allows an application level admin to change a
    * user's password
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    *
    */
    public function changePasswordByAdmin($adminUserName, $adminPassword, $userName, $newPassword)
    {
        $provider = $this->getServerProvider();
        
        try {
            $provider->changePasswordByAdmin($adminUserName, $adminPassword, $userName, $newPassword);
        } catch (AEPasswordInvalid $e) {
            die($e->getMessage());
        }
    }
    
    public function resetPassword($userName)
    {
        $provider = $this->getServerProvider();
        
        try {
            return $provider->resetPassword($userName);
        } catch (AEPasswordInvalid $e) {
            die($e->getMessage());
        }
    }
    
    /**
    * Gets the application privileges for a given user
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @param string $adminUserName Administrator's username
    * @param string $adminPassword Administrator's password
    * @param string $userName User to get privileges for
    * @return array Array of AEPrivilege objects
    *
    */
    public function getUserPrivilegesByAdmin($adminUserName, $adminPassword, $userName)
    {
        $provider = $this->getServerProvider();
        try {
            return $provider->getUserPrivilegesByAdmin($adminUserName, $adminPassword, $userName);
        } catch (Exception $e) {
            die($e->getMessage());
        }
    }
    
    /**
    * Sets the application privileges for a given user
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @param string $adminUserName Administrator's username
    * @param string $adminPassword Administrator's password
    * @param string $userName User to set privileges for
    * @param array $privArray Array of privileges to give to the user
    *
    */
    public function setUserPrivilegesByAdmin($adminUserName, $adminPassword, $userName, $privArray)
    {
        $provider = $this->getServerProvider();
        try {
            $provider->setUserPrivilegesByAdmin($adminUserName, $adminPassword, $userName, $privArray);
        } catch (Exception $e) {
            die($e->getMessage());
        }
    }
    
    /**
    * Lists all available privileges for a given application
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @param string $adminUserName Administrator's username
    * @param string $adminPassword Administrator's password
    * @return array Array of AEPrivilege objects
    * 
    */
    public function listAppPrivilegesByAdmin($adminUserName, $adminPassword)
    {
        $provider = $this->getServerProvider();
        try {
            return $provider->listAppPrivilegesByAdmin($adminUserName, $adminPassword);
        } catch (Exception $e) {
            die($e->getMessage());
        }
    }
    
    /**
    * Gets the groups the user belongs to
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @param string $adminUserName Administrator's Username
    * @param string $adminPassword Administrator's Password
    * @param string $userName User to get groups for
    * @return array Array of group objects
    *
    */
    public function getUserGroupsByAdmin($adminUserName, $adminPassword, $userName)
    {
        $provider = $this->getServerProvider();
        try {
            return $provider->getUserGroupsByAdmin($adminUserName, $adminPassword, $userName);
        } catch (Exception $e) {
            die($e->getMessage());
        }
    }
    
    /**
    * Sets the groups the user belongs to
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @param string $adminUserName Administrator's username
    * @param string $adminPassword Administrator's password
    * @param string $userName User to set groups for
    * @param array $groupArray Array of groups to give user access to
    *
    */
    public function setUserGroupsByAdmin($adminUserName, $adminPassword, $userName, $groupArray)
    {
        $provider = $this->getServerProvider();
        try {
            $provider->setUserGroupsByAdmin($adminUserName, $adminPassword, $userName, $groupArray);
        } catch (Exception $e) {
            die($e->getMessage());
        }
    }
    
    /**
    * Converts an AEServiceUser to a plan AEUser
    *
    * @access private
    * @param object $serviceUser Instance of an AEServiceUser
    * @return object AEUser instance
    *
    */
    private function serverUserToClientUser($serviceUser)
    {
        $user = new Enterprise_User();
        
        $user->setUserName($serviceUser->getUserName());
        $user->setPassword($serviceUser->getPassword());
        $user->setUserGroups($serviceUser->getGroups());
        $user->setPrivileges($serviceUser->getPrivileges());
        $user->setClientProvider($this);
        
        return $user;
    }
    
    /**
    * To avoid making this object big by serializing the server provider
    * we create, this function will get a handle to once instead on behalf
    * of other class methods.
    *
    * NOTE: this is necessary to avoid doing things that simply won't work
    * like serializing the server provider's database connection
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access private
    * @return object An instance of an Auth_Enterprise server provider
    *
    */
    private function getServerProvider()
    {
        return Enterprise_ServerProviderFactory::getProvider($this->options['appId']);
    }
}

?> 
--- NEW FILE: User.php ---
<?php

/**
* Auth_Enterprise
*
* This source file is subject to version 2.02 of the PHP license, that is bundled with this package
* in the file LICENSE, and is available at through the world-wide-web at
* http://www.php.net/license/2_02.txt. If you did not receive a copy of the PHP license and are
* unable to obtain it through the world-wide-web, please send a note to license at php.net so we can
* mail you a copy immediately.
*
* @author Tony Bibbs <tony at geeklog.net>
* @copyright 2004
* @version $Id: User.php,v 1.1 2004/07/04 15:02:55 tony Exp $
*
*/

/**
* Auth_Enterprise exceptions
*/
require_once 'Auth/Enterprise/Common/Exceptions.php';

/**
* The Auth_Enterprise Group object
*/
require_once 'Auth/Enterprise/Common/Group.php';

/**
* The Auth_Enterprise Privilege object
*/
require_once 'Auth/Enterprise/Common/Privilege.php';

/**
* Auth_Enteprise User object
*
* You should not instantiate this object directly.  Instead you should have received an instance
* using the Client's authenticate method.
*
* @author Tony Bibbs <tony at geeklog.net>
* @package net.geeklog.auth_enterprise.common
*
*/
class Enterprise_User {
    /**
    * Username
    * @access private
    * @var string
    */
    private $userName = null;
    
    /**
    * User's password
    * @access private
    * @var string
    */
    private $password = null;
    
    /**
    * Set of privileges for this user
    * @access private
    * @var array
    */
    private $privileges = null;
    
    /**
    * Groups user belongs to
    * @access private
    * @var array
    */
    private $groups = array();
    
    /**
    * Instance of a client Auth_Enterprise provider
    * @access private
    * @var object
    */
    private $clientProvider = null;
    
    /**
    * Constructor
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    *
    */
    public function __construct()
    {
    }
    
    /**
    * Setter for the Auth_Enterprise client provider instance
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    *
    */
    public function setClientProvider($clientProvider)
    {
        $this->clientProvider = $clientProvider;
    }
    
    /**
    * Getter for the Auth_Enterprise client provider instance
    *
    * @author Tony Bibbs <tony at geekog.net>
    * @access public
    * @return object
    *
    */
    public function getClientProvider()
    {
        return $this->clientProvider;
    }
    
    /**
    * Sets the username
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @param string $userName The user's username
    *
    */
    public function setUserName($userName)
    {
        $this->userName = $userName;
    }
    
    /**
    * Returns the username
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @return string User's username
    *
    */
    public function getUserName()
    {
        return $this->userName;
    }
    
    /**
    * Setter for the user's password
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @param string $password Password to set on object
    *
    */
    public function setPassword($password)
    {
        $this->password = $password;
    }
    
    /**
    * Getter for the user's password
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @return string User's password
    *
    */
    public function getPassword()
    {
        return $this->password;
    }
    
    /**
    * Sets the groups the user belongs to
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @param array $groupArray Array of group objects
    *
    */
    public function setUserGroups($groupArray)
    {
        $this->groups = $groupArray;
    }
    
    /**
    * Getter for user's privileges
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @return array Array of privilege objects
    *
    */
    public function getPrivileges()
    {
        return $this->privileges;
    }
    
    /**
    * Setter for user's privilges
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @param array Array of privilige objects
    *
    */
    public function setPrivileges($privArray)
    {
        $this->privileges = $privArray;
    }
    
    /**
    * Gets the groups the user belongs to
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @return array Array of group objects
    *
    */
    public function getUserGroups()
    {
        return $this->groups;
    }
    
    /**
    * Sets the groups the user belongs to
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @param array Groups to set on user
    *
    */
    public function setGroups($groupArray)
    {
        $this->groups = $groupArray;
    }
    
    /**
    * Changes a user's password
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @param string $newPassword What to set new password to
    * @return null
    *
    */
    public function changePassword($newPassword)
    {
        try {
            $this->clientProvider->changePassword($this->userName, $newPassword);
        } catch (AEBaseException $error) {
            throw $error;
        }
        
        $this->setPassword($newPassword);
    }
    
    /**
    * Allows an application level admin to change a user's password
    *
    * NOTE: this assumes this user is the administrator
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @param string $userName Username to set password for
    * @param string $newPassword Password to set for user
    * @return null
    *
    */
    public function changePasswordByAdmin($userName, $newPassword)
    {
        try {
            $this->clientProvider->changePasswordByAdmin($this->userName, $this->password, $userName, $newPassword);
        } catch (AEBaseException $error) {
            throw $error;
        }
    }
    
    /**
    * Resets a user's password to a randomly generated one
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @return string New randomly generated password
    *
    */
    public function resetPassword()
    {
        try {
            $newPassword = $this->clientProvider->resetPassword($this->userName);
        } catch (AEBaseException $error) {
            throw $error;
        }
        
        $this->setPassword($newPassword);
        
        return $newPassword;
    }
    
    /**
    * Gets the application privileges for a given user
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @param string $userName Username of user to get privileges for
    * @return Array Anarray of privileges
    *
    */
    public function getUserPrivilegesByAdmin($userName)
    {
        try {
            $privArray = $this->clientProvider->getUserPrivilegesByAdmin($this->userName, $this->password, $userName);
        } catch (AEBaseException $error) {
            throw $error;
        }
        return $privArray;
    }
    
    /**
    * Sets the application privileges for a given user
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @param string $userName Username of user to set privileges for
    * @param array $privArray Array of privilege objects
    * @return null
    *
    */
    public function setUserPrivilegesByAdmin($userName, $privArray)
    {
        try {
            $this->clientProvider->setUserPrivilegesByAdmin($this->userName, $this->password, $userName, $privArray);
        } catch (AEBaseException $error) {
            throw $error;
        }
    }
    
    /**
    * Lists all available privileges for a given application
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @return Array Array of privileges
    *
    */
    public function listAppPrivilegesByAdmin()
    {
        try {
            return $this->clientProvider->listAppPrivilegesByAdmin($this->userName, $this->password);
        } catch (AEBaseException $error) {
            throw $error;
        }
    }
    
    /**
    * Gets the groups for a given user on behalf of an adminitrator
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @param string $userName User to get groups for
    * @return array Array of AEGroup objects
    *
    */
    public function getUserGroupsByAdmin($userName)
    {
        try {
            return $this->clientProvider->getUserGroupsByAdmin($this->userName, $this->password, $userName);
        } catch (AEBaseException $error) {
            throw $error;
        }
    }
    
    /**
    * Sets the application privileges for a given user
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @param string $userName Username of user to set groups for
    * @param array $privArray Array of group objects
    * @return null
    *
    */
    public function setUserGroupsByAdmin($userName, $groupArray)
    {
        try {
            $this->clientProvider->setUserGroupsByAdmin($this->userName, $this->password, $userName, $groupArray);
        } catch (AEBaseException $error) {
            throw $error;
        }
    }
    
    /**
    * This method determines if user has privilege to the given
    * authorization code
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @param string $authCode Authorization code to verify
    * @return boolean rue if user has access, otherwise false
    *
    */
    public function isAuthorized($authCode)
    {
        foreach ($this->privileges as $curPriv) {
            if ($curPriv->getPrivilegeCode() == $authCode) {
                return true;
            }
        }
        return false;
    }
}

?> 
--- NEW FILE: BaseClientProvider.php ---
<?php

/**
* Auth_Enterprise
*
* This source file is subject to version 2.02 of the PHP license, that is bundled with this package
* in the file LICENSE, and is available at through the world-wide-web at
* http://www.php.net/license/2_02.txt. If you did not receive a copy of the PHP license and are
* unable to obtain it through the world-wide-web, please send a note to license at php.net so we can
* mail you a copy immediately.
*
* @author Tony Bibbs <tony at geeklog.net>
* @copyright 2004
* @version $Id: BaseClientProvider.php,v 1.1 2004/07/04 15:02:55 tony Exp $
*
*/

/**
* Auth_Enteprise base client provider
*
* All client implementation of the Auth_Enterprise service
* should extend this abstract class
*
* @author Tony Bibbs <tony at geeklog.net>
* @package net.geeklog.auth_enterprise.client
* @todo When converting to PHP5 make this an abstract class
*
*/
abstract class Enterprise_BaseClientProvider implements Enterprise_ServiceInterface {
    /**
    * Application ID
    * @access private
    * @var string
    */
    private $appId = null;
    
    /**
    * Constructor
    *
    * Sets up client properties so that calls to Auth_Enterprise will work. Note, this class takes
    * an array of options but at this abstract of a level all we care about is $options['appId']
    *
    * @author Tony Bibbs <tony.bibbs at iowa.gov>
    * @access public
    * @param string $appId The ID assigned to the application by the
    *
    */
    function __construct($options)
    {
        $this->appId = $options['appId'];
    }
    
    /**
    * Returns the application ID
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @return string Application ID
    *
    */
    protected function getAppId()
    {
        return $this->appId;
    }
}

?> 
--- NEW FILE: Client.php ---
<?php

/**
* Auth_Enterprise
*
* This source file is subject to version 2.02 of the PHP license, that is bundled with this package
* in the file LICENSE, and is available at through the world-wide-web at
* http://www.php.net/license/2_02.txt. If you did not receive a copy of the PHP license and are
* unable to obtain it through the world-wide-web, please send a note to license at php.net so we can
* mail you a copy immediately.
*
* @author Tony Bibbs <tony at geeklog.net>
* @copyright 2004
* @version $Id: Client.php,v 1.1 2004/07/04 15:02:55 tony Exp $
*
*/

/**
* Constants used through out the Auth_Enterprise client
*/
require_once 'Auth/Enterprise/Client/ClientConstants.php';

/**
* The Auth_Enterprise Service Interface
*/
require_once 'Auth/Enterprise/Common/ServiceInterface.php';

/**
* Auth_Enterprise Client User Class
*/
require_once 'Auth/Enterprise/Client/User.php';

/**
* Auth_Enterprise Privilege Class
*/
require_once 'Auth/Enterprise/Common/Privilege.php';

/**
* The Auth_Enterprise Client Provider Factory
*/
require_once 'Auth/Enterprise/Client/ClientProviderFactory.php';

/**
* Set of Auth_Enterprise exceptions
*/
require_once 'Auth/Enterprise/Common/Exceptions.php';

/**
* Auth_Enteprise Client
*
* @author Tony Bibbs <tony at geeklog.net>
* @package net.geeklog.auth_enterprise.client
*
*/
class Enterprise_Client implements Enterprise_ServiceInterface {
    /**
    * Instance of a specific client provider implementation
    * @access private
    * @var object
    */
    private $clientProvider = null;
    
    /**
    * Constructor
    *
    * Creates an instance of the client provider
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @param int $provider Indicates which client implementation to use
    * @param array $providerOptions Options the client provider uses to talk to the service
    *
    */
    public function __construct($provider, $providerOptions)
    {
        $this->clientProvider = Enterprise_ClientProviderFactory::getProvider($provider, $providerOptions);
    }
    
    /**
    * Authenticates a user with the Auth_Enterprise service
    *
    * Uses the instance to the client provider to authenticate a user.  Typically this is the only
    * method in this class you should have to call directly.  After you successfully authentciate
    * you should have a valid AEUser instance and you can call the methods you need from there.
    *
    * NOTE: This method returns a user object that has the same clientProvider handle as this class.
    * Because of this, you should be able to free up an instance of this class after you call this
    * Method.  Obviously this is optional but strongly recommend.
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @param string $userName Username to authenticate to the service with
    * @param string $password Password to authenticate with
    * @return object AEUser Object
    *
    */
    public function authenticate($userName, $password)
    {
        try {
            $userObj = $this->clientProvider->authenticate($userName, $password);
            $userObj->setClientProvider($this->clientProvider);
        } catch (AEBaseException $error) {
            throw $error;
        }
        
        return $userObj;
    }
    
    /**
    * Registers a new account with the service
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @param string $adminUserName Administrator's username
    * @param string $adminPassword Administrator's password
    * @param string $userName User name for new account
    * @param string $userPassowrd Password for new account
    * 
    */
    public function createAccountByAdmin($adminUserName, $adminPassword, $userName, $userPassword)
    {
        try {
            $this->clientProvider->createAccountByAdmin($adminUserName, $adminPassword, $userName, $userPassword);
        } catch (AEBaseException $error) {
            throw $error;
        }
    }
    
    /**
    * Changes a user's password
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @param string $userName Username for user to change password for
    * @param string $newPassword User's new password
    *
    */
    public function changePassword($userName, $newPassword)
    {
        try {
            $this->clientProvider->changePassword($userName, $newPassword);
        } catch (AEBaseException $error) {
            throw $error;
        }
    }
    
    /**
    * Allows an application level admin to change a
    * user's password
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @param string $adminUserName Username of admin user making the request
    * @param string $adminPassword Password of admin user making the request
    * @param string $userName Username of user to change password for
    * @param string $newPassword New password for the given user
    *
    */
    public function changePasswordByAdmin($adminUserName, $adminPassword, $userName, $newPassword)
    {
        try {
            $this->clientProvider->changePasswordByAdmin($adminUserName, $adminPassword, $userName, $newPassword);
        } catch (AEBaseException $error) {
            die($error->getMessage);
        }
    }
    
    /**
    * Resets a user's password to a randomly generated one
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @return string New randomly generated password
    *
    */
    public function resetPassword($userName)
    {
        try {
            return $this->clientProvider->resetPassword($userName);
        } catch (AEBaseException $error) {
            throw $error;
        }
    }
    
    /**
    * Gets the application privileges for a given user
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @param string $adminUserName Admin user making the request
    * @param string $adminPassword Password for admin making the request
    * @param string $userName Username of user to get privileges for
    * @return Array
    *
    */
    public function getUserPrivilegesByAdmin($adminUserName, $adminPassword, $userName)
    {
        try {
            $privArray = $this->clientProvider->getUserPrivileges($adminUserName, $adminPassword, $userName, $newPassword);
        } catch (AEBaseException $error) {
            die($error->getMessage);
        }
        return $privArray;
    }
    
    /**
    * Sets the application privileges for a given user
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @param string $adminUserName Admin user making the request
    * @param string $adminPassword Password for admin making the request
    * @param string $userName Username of user to set privileges for
    * @param array $privArray Array of privileges to give the user
    * @return null
    * 
    */
    public function setUserPrivilegesByAdmin($adminUserName, $adminPassword, $userName, $privArray)
    {
        try {
            $this->clientProvider->setUserPrivilegesByAdmin($adminUserName, $adminPassword, $userName, $privArray);
        } catch (AEBaseException $error) {
            throw $error;
        }
    }
    
    /**
    * Lists all available privileges for a given application
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @param string $adminUserName Admin user making the request
    * @param string $adminPassword Password for admin making the request
    * @return Array An array of privileges
    *
    */
    public function listAppPrivilegesByAdmin($adminUserName, $adminPassword)
    {
        try {
            $privArray = $this->clientProvider->listAppPrivilegesByAdmin($adminUserName, $adminPassword);
        } catch (AEBaseException $error) {
            throw $error;
        }
        return $privArray;
    }
    
    /**
    * Allows an admin to get the groups a user belongs to
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @param string $adminUserName The administrator's username
    * @param string $adminPassword The administrator's password
    * @param string $userName User to get groups for
    * @return array Array of group objects
    *
    */
    public function getUserGroupsByAdmin($adminUserName, $adminPassword, $userName)
    {
        try {
            $groupArray = $this->clientProvider->getUserGroupsByAdmin($adminUserName, $adminPassword, $userName);
        } catch (AEBaseException $error) {
            throw $error;
        }
        return $groupArray;
    }
    
    /**
    * Allows an admin to set the groups a user belongs to
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @param string $adminUserName The administrator's username
    * @param string $adminPassword The administrator's password
    * @param string $userName User to set groups for
    *
    */
    public function setUserGroupsByAdmin($adminUserName, $adminPassword, $userName, $groupArray)
    {
        try {
            $this->clientProvider->setUserGroupsByAdmin($adminUserName, $adminPassword, $userName, $groupArray);
        } catch (AEBaseException $error) {
            throw $error;
        }
    }
}

?>
--- NEW FILE: ClientConstants.php ---
<?php

/**
* Auth_Enterprise
*
* This source file is subject to version 2.02 of the PHP license, that is bundled with this package
* in the file LICENSE, and is available at through the world-wide-web at
* http://www.php.net/license/2_02.txt. If you did not receive a copy of the PHP license and are
* unable to obtain it through the world-wide-web, please send a note to license at php.net so we can
* mail you a copy immediately.
*
* @author Tony Bibbs <tony at geeklog.net>
* @copyright 2004
* @version $Id: ClientConstants.php,v 1.1 2004/07/04 15:02:55 tony Exp $
*
*/

/**
* Indicates client should bypass all network traffic and talk to the Auth_Enterprise Service
* Directly
* @const AE_XMLRPC_CLIENT
*/
define('AE_LOCALHOST_CLIENT', 'LocalhostClient');

/**
* Indicates client should use XMLRPC to talk to the service
* @const AE_XMLRPC_CLIENT
*/
define('AE_XMLRPC_CLIENT', 'XMLRPCClient');

/**
* Indicates client should use SOAP to talk to the service
* @const AE_XMLRPC_CLIENT
*/
define('AE_SOAP_CLIENT', 'SOAPClient');

?>
--- NEW FILE: ClientProviderFactory.php ---
<?php

/**
* Auth_Enterprise
*
* This source file is subject to version 2.02 of the PHP license, that is bundled with this package
* in the file LICENSE, and is available at through the world-wide-web at
* http://www.php.net/license/2_02.txt. If you did not receive a copy of the PHP license and are
* unable to obtain it through the world-wide-web, please send a note to license at php.net so we can
* mail you a copy immediately.
*
* @author Tony Bibbs <tony at geeklog.net>
* @copyright 2004
* @version $Id: ClientProviderFactory.php,v 1.1 2004/07/04 15:02:55 tony Exp $
*
*/
require_once 'Auth/Enterprise/Server/ServerConfig.php';
/**
* Auth_Enteprise Client Provider Factory
*
* All this class does is build instance of client provider objects in a dynamic, as-needed
* fashion
* 
* @author Tony Bibbs <tony at geeklog.net>
* @package net.geeklog.auth_enterprise.client
*
*/
class Enterprise_ClientProviderFactory {
    /**
    * Builds the request provider
    *
    * @author Tony Bibbs <tony at geeklog.net>
    * @access public
    * @param string $provider Implementation of service to use
    * @param Array $providerOptions Configuration options the client provider takes
    * @return object Client provider
    *
    */
    public static function getProvider($provider, $providerOptions)
    {
        $clientFile = 'Auth/Enterprise/Client/' . $provider . '.php';
        
        require_once $clientFile;
        
        return new $provider($providerOptions);
    }
}

?> 



More information about the geeklog-cvs mailing list