Subversion Repositories Applications.papyrus

Rev

Rev 1713 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1173 jp_milcent 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
2150 mathias 21
 * @version    CVS: $Id: DBLite.php,v 1.18 2007/06/12 03:11:26 aashley Exp $
1173 jp_milcent 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
2150 mathias 48
 * @version    Release: 1.5.4  File: $Revision: 1.18 $
1173 jp_milcent 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();
1713 jp_milcent 96
        $this->options['db_where']    = '';
1173 jp_milcent 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
    {
1713 jp_milcent 121
        $this->log('Auth_Container_DBLite::_connect() called.', AUTH_LOG_DEBUG);
1173 jp_milcent 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
            $this->options['final_table'] = $this->db->quoteIdentifier($this->options['table']);
159
            $this->options['final_usernamecol'] = $this->db->quoteIdentifier($this->options['usernamecol']);
160
            $this->options['final_passwordcol'] = $this->db->quoteIdentifier($this->options['passwordcol']);
161
        } else {
162
            $this->options['final_table'] = $this->options['table'];
163
            $this->options['final_usernamecol'] = $this->options['usernamecol'];
164
            $this->options['final_passwordcol'] = $this->options['passwordcol'];
165
        }
166
        return true;
167
    }
168
 
169
    // }}}
170
    // {{{ _parseOptions()
171
 
172
    /**
173
     * Parse options passed to the container class
174
     *
175
     * @access private
176
     * @param  array
177
     */
178
    function _parseOptions($array)
179
    {
180
        foreach ($array as $key => $value) {
181
            if (isset($this->options[$key])) {
182
                $this->options[$key] = $value;
183
            }
184
        }
185
    }
186
 
187
    // }}}
188
    // {{{ _quoteDBFields()
189
 
190
    /**
191
     * Quote the db_fields option to avoid the possibility of SQL injection.
192
     *
193
     * @access private
194
     * @return string A properly quoted string that can be concatenated into a
195
     * SELECT clause.
196
     */
197
    function _quoteDBFields()
198
    {
199
        if (isset($this->options['db_fields'])) {
200
            if (is_array($this->options['db_fields'])) {
201
                if ($this->options['auto_quote']) {
202
                    $fields = array();
203
                    foreach ($this->options['db_fields'] as $field) {
204
                        $fields[] = $this->db->quoteIdentifier($field);
205
                    }
206
                    return implode(', ', $fields);
207
                } else {
208
                    return implode(', ', $this->options['db_fields']);
209
                }
210
            } else {
211
                if (strlen($this->options['db_fields']) > 0) {
212
                    if ($this->options['auto_quote']) {
213
                        return $this->db->quoteIdentifier($this->options['db_fields']);
214
                    } else {
215
                        $this->options['db_fields'];
216
                    }
217
                }
218
            }
219
        }
220
 
221
        return '';
222
    }
1713 jp_milcent 223
 
1173 jp_milcent 224
    // }}}
225
    // {{{ fetchData()
226
 
227
    /**
228
     * Get user information from database
229
     *
230
     * This function uses the given username to fetch
231
     * the corresponding login data from the database
232
     * table. If an account that matches the passed username
233
     * and password is found, the function returns true.
234
     * Otherwise it returns false.
235
     *
236
     * @param   string Username
237
     * @param   string Password
238
     * @return  mixed  Error object or boolean
239
     */
240
    function fetchData($username, $password)
241
    {
1713 jp_milcent 242
        $this->log('Auth_Container_DBLite::fetchData() called.', AUTH_LOG_DEBUG);
1173 jp_milcent 243
        // Prepare for a database query
244
        $err = $this->_prepare();
245
        if ($err !== true) {
246
            return PEAR::raiseError($err->getMessage(), $err->getCode());
247
        }
248
 
249
        // Find if db_fields contains a *, if so assume all col are selected
250
        if (is_string($this->options['db_fields'])
251
            && strstr($this->options['db_fields'], '*')) {
252
            $sql_from = "*";
253
        } else {
254
            $sql_from = $this->options['final_usernamecol'].
255
                ", ".$this->options['final_passwordcol'];
256
 
257
            if (strlen($fields = $this->_quoteDBFields()) > 0) {
258
                $sql_from .= ', '.$fields;
259
            }
260
        }
1713 jp_milcent 261
 
1173 jp_milcent 262
        $query = "SELECT ".$sql_from.
263
                " FROM ".$this->options['final_table'].
264
                " WHERE ".$this->options['final_usernamecol']." = ".$this->db->quoteSmart($username);
1713 jp_milcent 265
 
266
        // check if there is an optional parameter db_where
267
        if ($this->options['db_where'] != '') {
268
            // there is one, so add it to the query
269
            $query .= " AND ".$this->options['db_where'];
270
        }
271
 
272
        $this->log('Running SQL against DB: '.$query, AUTH_LOG_DEBUG);
273
 
1173 jp_milcent 274
        $res = $this->db->getRow($query, null, DB_FETCHMODE_ASSOC);
275
 
276
        if (DB::isError($res)) {
277
            return PEAR::raiseError($res->getMessage(), $res->getCode());
278
        }
279
        if (!is_array($res)) {
280
            $this->activeUser = '';
281
            return false;
282
        }
283
        if ($this->verifyPassword(trim($password, "\r\n"),
284
                                  trim($res[$this->options['passwordcol']], "\r\n"),
285
                                  $this->options['cryptType'])) {
286
            // Store additional field values in the session
287
            foreach ($res as $key => $value) {
288
                if ($key == $this->options['passwordcol'] ||
289
                    $key == $this->options['usernamecol']) {
290
                    continue;
291
                }
1713 jp_milcent 292
 
293
                $this->log('Storing additional field: '.$key, AUTH_LOG_DEBUG);
294
 
1173 jp_milcent 295
                // Use reference to the auth object if exists
296
                // This is because the auth session variable can change so a static call to setAuthData does not make sence
297
                if (is_object($this->_auth_obj)) {
298
                    $this->_auth_obj->setAuthData($key, $value);
299
                } else {
300
                    Auth::setAuthData($key, $value);
301
                }
302
            }
303
            $this->activeUser = $res[$this->options['usernamecol']];
304
            return true;
305
        }
306
        $this->activeUser = $res[$this->options['usernamecol']];
307
        return false;
308
    }
309
 
310
    // }}}
311
 
312
}
313
?>