Subversion Repositories Sites.obs-saisons.fr

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 aurelien 1
<?php
2
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
3
 
4
/**
5
 * Reduced storage driver for use against PEAR DB
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     Martin Jansen <mj@php.net>
18
 * @author     Adam Ashley <aashley@php.net>
19
 * @copyright  2001-2006 The PHP Group
20
 * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
21
 * @version    CVS: $Id: DBLite.php,v 1.20 2008/04/04 07:57:02 aashley Exp $
22
 * @link       http://pear.php.net/package/Auth
23
 * @since      File available since Release 1.3.0
24
 */
25
 
26
/**
27
 * Include Auth_Container base class
28
 */
29
require_once 'Auth/Container.php';
30
/**
31
 * Include PEAR DB package
32
 */
33
require_once 'DB.php';
34
 
35
/**
36
 * A lighter storage driver for fetching login data from a database
37
 *
38
 * This driver is derived from the DB storage container but
39
 * with the user manipulation function removed for smaller file size
40
 * by the PEAR DB abstraction layer to fetch login data.
41
 *
42
 * @category   Authentication
43
 * @package    Auth
44
 * @author     Martin Jansen <mj@php.net>
45
 * @author     Adam Ashley <aashley@php.net>
46
 * @copyright  2001-2006 The PHP Group
47
 * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
48
 * @version    Release: 1.6.1  File: $Revision: 1.20 $
49
 * @link       http://pear.php.net/package/Auth
50
 * @since      Class available since Release 1.3.0
51
 */
52
class Auth_Container_DBLite extends Auth_Container
53
{
54
 
55
    // {{{ properties
56
 
57
    /**
58
     * Additional options for the storage container
59
     * @var array
60
     */
61
    var $options = array();
62
 
63
    /**
64
     * DB object
65
     * @var object
66
     */
67
    var $db = null;
68
    var $dsn = '';
69
 
70
    /**
71
     * User that is currently selected from the DB.
72
     * @var string
73
     */
74
    var $activeUser = '';
75
 
76
    // }}}
77
    // {{{ Auth_Container_DBLite() [constructor]
78
 
79
    /**
80
     * Constructor of the container class
81
     *
82
     * Initate connection to the database via PEAR::DB
83
     *
84
     * @param  string Connection data or DB object
85
     * @return object Returns an error object if something went wrong
86
     */
87
    function Auth_Container_DBLite($dsn)
88
    {
89
        $this->options['table']       = 'auth';
90
        $this->options['usernamecol'] = 'username';
91
        $this->options['passwordcol'] = 'password';
92
        $this->options['dsn']         = '';
93
        $this->options['db_fields']   = '';
94
        $this->options['cryptType']   = 'md5';
95
        $this->options['db_options']  = array();
96
        $this->options['db_where']    = '';
97
        $this->options['auto_quote']  = true;
98
 
99
        if (is_array($dsn)) {
100
            $this->_parseOptions($dsn);
101
            if (empty($this->options['dsn'])) {
102
                PEAR::raiseError('No connection parameters specified!');
103
            }
104
        } else {
105
            $this->options['dsn'] = $dsn;
106
        }
107
    }
108
 
109
    // }}}
110
    // {{{ _connect()
111
 
112
    /**
113
     * Connect to database by using the given DSN string
114
     *
115
     * @access private
116
     * @param  string DSN string
117
     * @return mixed  Object on error, otherwise bool
118
     */
119
    function _connect(&$dsn)
120
    {
121
        $this->log('Auth_Container_DBLite::_connect() called.', AUTH_LOG_DEBUG);
122
        if (is_string($dsn) || is_array($dsn)) {
123
            $this->db =& DB::connect($dsn, $this->options['db_options']);
124
        } elseif (is_subclass_of($dsn, "db_common")) {
125
            $this->db =& $dsn;
126
        } else {
127
            return PEAR::raiseError("Invalid dsn or db object given");
128
        }
129
 
130
        if (DB::isError($this->db) || PEAR::isError($this->db)) {
131
            return PEAR::raiseError($this->db->getMessage(), $this->db->getCode());
132
        } else {
133
            return true;
134
        }
135
    }
136
 
137
    // }}}
138
    // {{{ _prepare()
139
 
140
    /**
141
     * Prepare database connection
142
     *
143
     * This function checks if we have already opened a connection to
144
     * the database. If that's not the case, a new connection is opened.
145
     *
146
     * @access private
147
     * @return mixed True or a DB error object.
148
     */
149
    function _prepare()
150
    {
151
        if (!DB::isConnection($this->db)) {
152
            $res = $this->_connect($this->options['dsn']);
153
            if (DB::isError($res) || PEAR::isError($res)) {
154
                return $res;
155
            }
156
        }
157
        if ($this->options['auto_quote'] && $this->db->dsn['phptype'] != 'sqlite') {
158
            if (strpos('.', $this->options['table']) === false) {
159
                $this->options['final_table'] = $this->db->quoteIdentifier($this->options['table']);
160
            } else {
161
                $t = explode('.', $this->options['table']);
162
                for ($i = 0, $count = count($t); $i < $count; $i++)
163
                    $t[$i] = $this->db->quoteIdentifier($t[$i]);
164
                $this->options['final_table'] = implode('.', $t);
165
            }
166
            $this->options['final_usernamecol'] = $this->db->quoteIdentifier($this->options['usernamecol']);
167
            $this->options['final_passwordcol'] = $this->db->quoteIdentifier($this->options['passwordcol']);
168
        } else {
169
            $this->options['final_table'] = $this->options['table'];
170
            $this->options['final_usernamecol'] = $this->options['usernamecol'];
171
            $this->options['final_passwordcol'] = $this->options['passwordcol'];
172
        }
173
        return true;
174
    }
175
 
176
    // }}}
177
    // {{{ _parseOptions()
178
 
179
    /**
180
     * Parse options passed to the container class
181
     *
182
     * @access private
183
     * @param  array
184
     */
185
    function _parseOptions($array)
186
    {
187
        foreach ($array as $key => $value) {
188
            if (isset($this->options[$key])) {
189
                $this->options[$key] = $value;
190
            }
191
        }
192
    }
193
 
194
    // }}}
195
    // {{{ _quoteDBFields()
196
 
197
    /**
198
     * Quote the db_fields option to avoid the possibility of SQL injection.
199
     *
200
     * @access private
201
     * @return string A properly quoted string that can be concatenated into a
202
     * SELECT clause.
203
     */
204
    function _quoteDBFields()
205
    {
206
        if (isset($this->options['db_fields'])) {
207
            if (is_array($this->options['db_fields'])) {
208
                if ($this->options['auto_quote']) {
209
                    $fields = array();
210
                    foreach ($this->options['db_fields'] as $field) {
211
                        $fields[] = $this->db->quoteIdentifier($field);
212
                    }
213
                    return implode(', ', $fields);
214
                } else {
215
                    return implode(', ', $this->options['db_fields']);
216
                }
217
            } else {
218
                if (strlen($this->options['db_fields']) > 0) {
219
                    if ($this->options['auto_quote']) {
220
                        return $this->db->quoteIdentifier($this->options['db_fields']);
221
                    } else {
222
                        $this->options['db_fields'];
223
                    }
224
                }
225
            }
226
        }
227
 
228
        return '';
229
    }
230
 
231
    // }}}
232
    // {{{ fetchData()
233
 
234
    /**
235
     * Get user information from database
236
     *
237
     * This function uses the given username to fetch
238
     * the corresponding login data from the database
239
     * table. If an account that matches the passed username
240
     * and password is found, the function returns true.
241
     * Otherwise it returns false.
242
     *
243
     * @param   string Username
244
     * @param   string Password
245
     * @return  mixed  Error object or boolean
246
     */
247
    function fetchData($username, $password)
248
    {
249
        $this->log('Auth_Container_DBLite::fetchData() called.', AUTH_LOG_DEBUG);
250
        // Prepare for a database query
251
        $err = $this->_prepare();
252
        if ($err !== true) {
253
            return PEAR::raiseError($err->getMessage(), $err->getCode());
254
        }
255
 
256
        // Find if db_fields contains a *, if so assume all col are selected
257
        if (is_string($this->options['db_fields'])
258
            && strstr($this->options['db_fields'], '*')) {
259
            $sql_from = "*";
260
        } else {
261
            $sql_from = $this->options['final_usernamecol'].
262
                ", ".$this->options['final_passwordcol'];
263
 
264
            if (strlen($fields = $this->_quoteDBFields()) > 0) {
265
                $sql_from .= ', '.$fields;
266
            }
267
        }
268
 
269
        $query = "SELECT ".$sql_from.
270
                " FROM ".$this->options['final_table'].
271
                " WHERE ".$this->options['final_usernamecol']." = ".$this->db->quoteSmart($username);
272
 
273
        // check if there is an optional parameter db_where
274
        if ($this->options['db_where'] != '') {
275
            // there is one, so add it to the query
276
            $query .= " AND ".$this->options['db_where'];
277
        }
278
 
279
        $this->log('Running SQL against DB: '.$query, AUTH_LOG_DEBUG);
280
 
281
        $res = $this->db->getRow($query, null, DB_FETCHMODE_ASSOC);
282
 
283
        if (DB::isError($res)) {
284
            return PEAR::raiseError($res->getMessage(), $res->getCode());
285
        }
286
        if (!is_array($res)) {
287
            $this->activeUser = '';
288
            return false;
289
        }
290
        if ($this->verifyPassword(trim($password, "\r\n"),
291
                                  trim($res[$this->options['passwordcol']], "\r\n"),
292
                                  $this->options['cryptType'])) {
293
            // Store additional field values in the session
294
            foreach ($res as $key => $value) {
295
                if ($key == $this->options['passwordcol'] ||
296
                    $key == $this->options['usernamecol']) {
297
                    continue;
298
                }
299
 
300
                $this->log('Storing additional field: '.$key, AUTH_LOG_DEBUG);
301
 
302
                // Use reference to the auth object if exists
303
                // This is because the auth session variable can change so a static call to setAuthData does not make sence
304
                if (is_object($this->_auth_obj)) {
305
                    $this->_auth_obj->setAuthData($key, $value);
306
                } else {
307
                    Auth::setAuthData($key, $value);
308
                }
309
            }
310
            $this->activeUser = $res[$this->options['usernamecol']];
311
            return true;
312
        }
313
        $this->activeUser = $res[$this->options['usernamecol']];
314
        return false;
315
    }
316
 
317
    // }}}
318
 
319
}
320
?>