Subversion Repositories Applications.papyrus

Rev

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

Rev Author Line No. Line
320 jpm 1
<?php
2
//
3
// +----------------------------------------------------------------------+
4
// | PHP Version 4                                                        |
5
// +----------------------------------------------------------------------+
6
// |                                                                      |
7
// +----------------------------------------------------------------------+
8
// | This source file is subject to version 2.02 of the PHP license,      |
9
// | that is bundled with this package in the file LICENSE, and is        |
10
// | available at through the world-wide-web at                           |
11
// | http://www.php.net/license/2_02.txt.                                 |
12
// | If you did not receive a copy of the PHP license and are unable to   |
13
// | obtain it through the world-wide-web, please send a note to          |
14
// | license@php.net so we can mail you a copy immediately.               |
15
// +----------------------------------------------------------------------+
16
// | Authors: Martin Jansen <mj@php.net>                                  |
17
// +----------------------------------------------------------------------+
18
//
19
// $Id: DB.php,v 1.1 2005-03-30 08:50:33 jpm Exp $
20
//
21
 
22
require_once 'Auth/Container.php';
23
require_once 'DB.php';
24
 
25
/**
26
 * Storage driver for fetching login data from a database
27
 *
28
 * This storage driver can use all databases which are supported
29
 * by the PEAR DB abstraction layer to fetch login data.
30
 *
31
 * @author   Martin Jansen <mj@php.net>
32
 * @package  Auth
33
 * @version  $Revision: 1.1 $
34
 */
35
class Auth_Container_DB extends Auth_Container
36
{
37
 
38
    /**
39
     * Additional options for the storage container
40
     * @var array
41
     */
42
    var $options = array();
43
 
44
    /**
45
     * DB object
46
     * @var object
47
     */
48
    var $db = null;
49
    var $dsn = '';
50
 
51
    /**
52
     * User that is currently selected from the DB.
53
     * @var string
54
     */
55
    var $activeUser = '';
56
 
57
    // {{{ Constructor
58
 
59
    /**
60
     * Constructor of the container class
61
     *
62
     * Initate connection to the database via PEAR::DB
63
     *
64
     * @param  string Connection data or DB object
65
     * @return object Returns an error object if something went wrong
66
     */
67
    function Auth_Container_DB($dsn)
68
    {
69
        $this->_setDefaults();
70
 
71
        if (is_array($dsn)) {
72
            $this->_parseOptions($dsn);
73
 
74
            if (empty($this->options['dsn'])) {
75
                PEAR::raiseError('No connection parameters specified!');
76
            }
77
        } else {
78
            $this->options['dsn'] = $dsn;
79
        }
80
    }
81
 
82
    // }}}
83
    // {{{ _connect()
84
 
85
    /**
86
     * Connect to database by using the given DSN string
87
     *
88
     * @access private
89
     * @param  string DSN string
90
     * @return mixed  Object on error, otherwise bool
91
     */
92
    function _connect($dsn)
93
    {
94
        if (is_string($dsn) || is_array($dsn)) {
95
            $this->db = DB::Connect($dsn);
96
        } elseif (get_parent_class($dsn) == "db_common") {
97
            $this->db = $dsn;
98
        } elseif (DB::isError($dsn)) {
99
            return PEAR::raiseError($dsn->getMessage(), $dsn->getCode());
100
        } else {
101
            return PEAR::raiseError('The given dsn was not valid in file ' . __FILE__ . ' at line ' . __LINE__,
102
                                    41,
103
                                    PEAR_ERROR_RETURN,
104
                                    null,
105
                                    null
106
                                    );
107
        }
108
 
109
        if (DB::isError($this->db) || PEAR::isError($this->db)) {
110
            return PEAR::raiseError($this->db->getMessage(), $this->db->getCode());
111
        } else {
112
            return true;
113
        }
114
    }
115
 
116
    // }}}
117
    // {{{ _prepare()
118
 
119
    /**
120
     * Prepare database connection
121
     *
122
     * This function checks if we have already opened a connection to
123
     * the database. If that's not the case, a new connection is opened.
124
     *
125
     * @access private
126
     * @return mixed True or a DB error object.
127
     */
128
    function _prepare()
129
    {
130
        if (!DB::isConnection($this->db)) {
131
            $res = $this->_connect($this->options['dsn']);
132
            if(DB::isError($res) || PEAR::isError($res)){
133
                return $res;
134
            }
135
        }
136
        return true;
137
    }
138
 
139
    // }}}
140
    // {{{ query()
141
 
142
    /**
143
     * Prepare query to the database
144
     *
145
     * This function checks if we have already opened a connection to
146
     * the database. If that's not the case, a new connection is opened.
147
     * After that the query is passed to the database.
148
     *
149
     * @access public
150
     * @param  string Query string
151
     * @return mixed  a DB_result object or DB_OK on success, a DB
152
     *                or PEAR error on failure
153
     */
154
    function query($query)
155
    {
156
        $err = $this->_prepare();
157
        if ($err !== true) {
158
            return $err;
159
        }
160
        return $this->db->query($query);
161
    }
162
 
163
    // }}}
164
    // {{{ _setDefaults()
165
 
166
    /**
167
     * Set some default options
168
     *
169
     * @access private
170
     * @return void
171
     */
172
    function _setDefaults()
173
    {
174
        $this->options['table']       = 'auth';
175
        $this->options['usernamecol'] = 'username';
176
        $this->options['passwordcol'] = 'password';
177
        $this->options['dsn']         = '';
178
        $this->options['db_fields']   = '';
179
        $this->options['cryptType']   = 'md5';
180
    }
181
 
182
    // }}}
183
    // {{{ _parseOptions()
184
 
185
    /**
186
     * Parse options passed to the container class
187
     *
188
     * @access private
189
     * @param  array
190
     */
191
    function _parseOptions($array)
192
    {
193
        foreach ($array as $key => $value) {
194
            if (isset($this->options[$key])) {
195
                $this->options[$key] = $value;
196
            }
197
        }
198
 
199
        /* Include additional fields if they exist */
200
        if(!empty($this->options['db_fields'])){
201
            if(is_array($this->options['db_fields'])){
202
                $this->options['db_fields'] = join($this->options['db_fields'], ', ');
203
            }
204
            $this->options['db_fields'] = ', '.$this->options['db_fields'];
205
        }
206
    }
207
 
208
    // }}}
209
    // {{{ fetchData()
210
 
211
    /**
212
     * Get user information from database
213
     *
214
     * This function uses the given username to fetch
215
     * the corresponding login data from the database
216
     * table. If an account that matches the passed username
217
     * and password is found, the function returns true.
218
     * Otherwise it returns false.
219
     *
220
     * @param   string Username
221
     * @param   string Password
222
     * @return  mixed  Error object or boolean
223
     */
224
    function fetchData($username, $password)
225
    {
226
        // Prepare for a database query
227
        $err = $this->_prepare();
228
        if ($err !== true) {
229
            return PEAR::raiseError($err->getMessage(), $err->getCode());
230
        }
231
 
232
        // Find if db_fileds contains a *, i so assume all col are selected
233
        if(strstr($this->options['db_fields'], '*')){
234
            $sql_from = "*";
235
        }
236
        else{
237
            $sql_from = $this->options['usernamecol'] . ", ".$this->options['passwordcol'].$this->options['db_fields'];
238
        }
239
        /**
240
         Old Style, removed to go around the oci8
241
         problem
242
         See bug 206
243
         http://pear.php.net/bugs/bug.php?id=206
244
 
245
        $query = "SELECT ! FROM ! WHERE ! = ?";
246
        $query_params = array(
247
                         $sql_from,
248
                         $this->options['table'],
249
                         $this->options['usernamecol'],
250
                         $username
251
                         );
252
        */
253
 
254
        $query = "SELECT ".$sql_from.
255
                " FROM ".$this->options['table'].
256
                " WHERE ".$this->options['usernamecol']." = '".$this->db->quoteString($username)."'";
257
 
258
        $res = $this->db->getRow($query, null, DB_FETCHMODE_ASSOC);
259
 
260
        if (DB::isError($res)) {
261
            return PEAR::raiseError($res->getMessage(), $res->getCode());
262
        }
263
        if (!is_array($res)) {
264
            $this->activeUser = '';
265
            return false;
266
        }
267
        if ($this->verifyPassword(trim($password, "\r\n"),
268
                                  trim($res[$this->options['passwordcol']], "\r\n"),
269
                                  $this->options['cryptType'])) {
270
            // Store additional field values in the session
271
            foreach ($res as $key => $value) {
272
                if ($key == $this->options['passwordcol'] ||
273
                    $key == $this->options['usernamecol']) {
274
                    continue;
275
                }
276
                // Use reference to the auth object if exists
277
                // This is because the auth session variable can change so a static call to setAuthData does not make sence
278
                if(is_object($this->_auth_obj)){
279
                    $this->_auth_obj->setAuthData($key, $value);
280
                } else {
281
                    Auth::setAuthData($key, $value);
282
                }
283
            }
284
 
285
            return true;
286
        }
287
 
288
        $this->activeUser = $res[$this->options['usernamecol']];
289
        return false;
290
    }
291
 
292
    // }}}
293
    // {{{ listUsers()
294
 
295
    function listUsers()
296
    {
297
        $err = $this->_prepare();
298
        if ($err !== true) {
299
            return PEAR::raiseError($err->getMessage(), $err->getCode());
300
        }
301
 
302
        $retVal = array();
303
 
304
        // Find if db_fileds contains a *, i so assume all col are selected
305
        if(strstr($this->options['db_fields'], '*')){
306
            $sql_from = "*";
307
        }
308
        else{
309
            $sql_from = $this->options['usernamecol'] . ", ".$this->options['passwordcol'].$this->options['db_fields'];
310
        }
311
 
312
        $query = sprintf("SELECT %s FROM %s",
313
                         $sql_from,
314
                         $this->options['table']
315
                         );
316
        $res = $this->db->getAll($query, null, DB_FETCHMODE_ASSOC);
317
 
318
        if (DB::isError($res)) {
319
            return PEAR::raiseError($res->getMessage(), $res->getCode());
320
        } else {
321
            foreach ($res as $user) {
322
                $user['username'] = $user[$this->options['usernamecol']];
323
                $retVal[] = $user;
324
            }
325
        }
326
        return $retVal;
327
    }
328
 
329
    // }}}
330
    // {{{ addUser()
331
 
332
    /**
333
     * Add user to the storage container
334
     *
335
     * @access public
336
     * @param  string Username
337
     * @param  string Password
338
     * @param  mixed  Additional information that are stored in the DB
339
     *
340
     * @return mixed True on success, otherwise error object
341
     */
342
    function addUser($username, $password, $additional = "")
343
    {
344
        if (function_exists($this->options['cryptType'])) {
345
            $cryptFunction = $this->options['cryptType'];
346
        } else {
347
            $cryptFunction = 'md5';
348
        }
349
 
350
        $additional_key   = '';
351
        $additional_value = '';
352
 
353
        if (is_array($additional)) {
354
            foreach ($additional as $key => $value) {
355
                $additional_key .= ', ' . $key;
356
                $additional_value .= ", '" . $value . "'";
357
            }
358
        }
359
 
360
        $query = sprintf("INSERT INTO %s (%s, %s%s) VALUES ('%s', '%s'%s)",
361
                         $this->options['table'],
362
                         $this->options['usernamecol'],
363
                         $this->options['passwordcol'],
364
                         $additional_key,
365
                         $username,
366
                         $cryptFunction($password),
367
                         $additional_value
368
                         );
369
 
370
        $res = $this->query($query);
371
 
372
        if (DB::isError($res)) {
373
           return PEAR::raiseError($res->getMessage(), $res->getCode());
374
        } else {
375
          return true;
376
        }
377
    }
378
 
379
    // }}}
380
    // {{{ removeUser()
381
 
382
    /**
383
     * Remove user from the storage container
384
     *
385
     * @access public
386
     * @param  string Username
387
     *
388
     * @return mixed True on success, otherwise error object
389
     */
390
    function removeUser($username)
391
    {
392
        $query = sprintf("DELETE FROM %s WHERE %s = '%s'",
393
                         $this->options['table'],
394
                         $this->options['usernamecol'],
395
                         $username
396
                         );
397
 
398
        $res = $this->query($query);
399
 
400
        if (DB::isError($res)) {
401
           return PEAR::raiseError($res->getMessage(), $res->getCode());
402
        } else {
403
          return true;
404
        }
405
    }
406
 
407
    // }}}
408
}
409
?>