1<?php
2/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
3
4/**
5 * Storage driver for using multiple storage drivers in a fall through fashion
6 *
7 * PHP versions 4 and 5
8 *
9 * LICENSE: This source file is subject to version 3.01 of the PHP license
10 * that is available through the world-wide-web at the following URI:
11 * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
12 * the PHP License and are unable to obtain it through the web, please
13 * send a note to license@php.net so we can mail you a copy immediately.
14 *
15 * @category   Authentication
16 * @package    Auth
17 * @author     Adam Ashley <aashley@php.net>
18 * @copyright  2001-2006 The PHP Group
19 * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
20 * @version    CVS: $Id: Multiple.php 289653 2009-10-15 04:50:43Z aashley $
21 * @since      File available since Release 1.5.0
22 */
23
24/**
25 * Include Auth_Container base class
26 */
27require_once "Auth/Container.php";
28/**
29 * Include PEAR package for error handling
30 */
31require_once "PEAR.php";
32
33/**
34 * Storage driver for using multiple storage drivers in a fall through fashion
35 *
36 * This storage driver provides a mechanism for working through multiple
37 * storage drivers until either one allows successful login or the list is
38 * exhausted.
39 *
40 * This container takes an array of options of the following form:
41 *
42 * array(
43 *   array(
44 *     'type'    => <standard container type name>,
45 *     'options' => <normal array of options for container>,
46 *   ),
47 * );
48 *
49 * Full example:
50 *
51 * $options = array(
52 *   array(
53 *     'type'    => 'DB',
54 *     'options' => array(
55 *       'dsn' => "mysql://user:password@localhost/database",
56 *     ),
57 *   ),
58 *   array(
59 *     'type'    => 'Array',
60 *     'options' => array(
61 *       'cryptType' => 'md5',
62 *       'users'     => array(
63 *         'admin' => md5('password'),
64 *       ),
65 *     ),
66 *   ),
67 * );
68 *
69 * $auth = new Auth('Multiple', $options);
70 *
71 * @category   Authentication
72 * @package    Auth
73 * @author     Adam Ashley <aashley@php.net>
74 * @copyright  2001-2006 The PHP Group
75 * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
76 * @version    Release: @package_version@  File: $Revision: 289653 $
77 * @since      File available since Release 1.5.0
78 */
79
80class Auth_Container_Multiple extends Auth_Container {
81
82    // {{{ properties
83
84    /**
85     * The options for each container
86     *
87     * @var array $options
88     */
89    var $options = array();
90
91    /**
92     * The instanciated containers
93     *
94     * @var array $containers
95     */
96    var $containers = array();
97
98    // }}}
99    // {{{ Auth_Container_Multiple()
100
101    /**
102     * Constructor for Array Container
103     *
104     * @param array $data Options for the container
105     * @return void
106     */
107    function Auth_Container_Multiple($options)
108    {
109        if (!is_array($options)) {
110            PEAR::raiseError('The options for Auth_Container_Multiple must be an array');
111        }
112        if (count($options) < 1) {
113            PEAR::raiseError('You must define at least one sub container to use in Auth_Container_Multiple');
114        }
115        foreach ($options as $option) {
116            if (!isset($option['type'])) {
117                PEAR::raiseError('No type defined for sub container');
118            }
119        }
120        $this->options = $options;
121    }
122
123    // }}}
124    // {{{ fetchData()
125
126    /**
127     * Get user information from array
128     *
129     * This function uses the given username to fetch the corresponding
130     * login data from the array. If an account that matches the passed
131     * username and password is found, the function returns true.
132     * Otherwise it returns false.
133     *
134     * @param  string Username
135     * @param  string Password
136     * @return boolean|PEAR_Error Error object or boolean
137     */
138    function fetchData($user, $pass)
139    {
140        $this->log('Auth_Container_Multiple::fetchData() called.', AUTH_LOG_DEBUG);
141
142        foreach ($this->options as $key => $options) {
143
144            $this->log('Using Container '.$key.' of type '.$options['type'].'.', AUTH_LOG_DEBUG);
145
146            if (isset($this->containers[$key]) && is_a($this->containers[$key], 'Auth_Container')) {
147
148                $container = &$this->containers[$key];
149
150            } else {
151
152                $this->containers[$key] = &$this->_auth_obj->_factory($options['type'], $options['options']);
153                $this->containers[$key]->_auth_obj = &$this->_auth_obj;
154                $container = &$this->containers[$key];
155
156            }
157
158            $result = $container->fetchData($user, $pass);
159
160            if (PEAR::isError($result)) {
161
162                $this->log('Container '.$key.': '.$result->getMessage(), AUTH_LOG_DEBUG);
163                return $result;
164
165            } elseif ($result == true) {
166
167                $this->log('Container '.$key.': Authentication successful.', AUTH_LOG_DEBUG);
168                return true;
169
170            } else {
171
172                $this->log('Container '.$key.': Authentication failed.', AUTH_LOG_DEBUG);
173
174            }
175
176        }
177
178        $this->log('Auth_Container_Multiple: All containers rejected user credentials.', AUTH_LOG_DEBUG);
179
180        return false;
181
182    }
183
184    // }}}
185
186}
187
188?>
189