1<?php
2/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
3
4/**
5 * Storage driver for use against a generic password file
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     Stefan Ekman <stekman@sedata.org>
18 * @author     Martin Jansen <mj@php.net>
19 * @author     Mika Tuupola <tuupola@appelsiini.net>
20 * @author     Michael Wallner <mike@php.net>
21 * @author     Adam Ashley <aashley@php.net>
22 * @copyright  2001-2006 The PHP Group
23 * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
24 * @version    CVS: $Id: File.php 237449 2007-06-12 03:11:27Z aashley $
25 * @link       http://pear.php.net/package/Auth
26 */
27
28/**
29 * Include PEAR File_Passwd package
30 */
31require_once "File/Passwd.php";
32/**
33 * Include Auth_Container base class
34 */
35require_once "Auth/Container.php";
36/**
37 * Include PEAR package for error handling
38 */
39require_once "PEAR.php";
40
41/**
42 * Storage driver for fetching login data from an encrypted password file.
43 *
44 * This storage container can handle CVS pserver style passwd files.
45 *
46 * @category   Authentication
47 * @package    Auth
48 * @author     Stefan Ekman <stekman@sedata.org>
49 * @author     Martin Jansen <mj@php.net>
50 * @author     Mika Tuupola <tuupola@appelsiini.net>
51 * @author     Michael Wallner <mike@php.net>
52 * @author     Adam Ashley <aashley@php.net>
53 * @copyright  2001-2006 The PHP Group
54 * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
55 * @version    Release: @package_version@  File: $Revision: 237449 $
56 * @link       http://pear.php.net/package/Auth
57 */
58class Auth_Container_File extends Auth_Container
59{
60
61    // {{{ properties
62
63    /**
64     * Path to passwd file
65     *
66     * @var string
67     */
68    var $pwfile = '';
69
70    /**
71     * Options for container
72     *
73     * @var array
74     */
75    var $options = array();
76
77    // }}}
78    // {{{ Auth_Container_File() [constructor]
79
80    /**
81     * Constructor of the container class
82     *
83     * @param  string $filename             path to passwd file
84     * @return object Auth_Container_File   new Auth_Container_File object
85     */
86    function Auth_Container_File($filename) {
87        $this->_setDefaults();
88
89        // Only file is a valid option here
90        if(is_array($filename)) {
91            $this->pwfile = $filename['file'];
92            $this->_parseOptions($filename);
93        } else {
94            $this->pwfile = $filename;
95        }
96    }
97
98    // }}}
99    // {{{ fetchData()
100
101    /**
102     * Authenticate an user
103     *
104     * @param   string  username
105     * @param   string  password
106     * @return  mixed   boolean|PEAR_Error
107     */
108    function fetchData($user, $pass)
109    {
110        $this->log('Auth_Container_File::fetchData() called.', AUTH_LOG_DEBUG);
111        return File_Passwd::staticAuth($this->options['type'], $this->pwfile, $user, $pass);
112    }
113
114    // }}}
115    // {{{ listUsers()
116
117    /**
118     * List all available users
119     *
120     * @return   array
121     */
122    function listUsers()
123    {
124        $this->log('Auth_Container_File::listUsers() called.', AUTH_LOG_DEBUG);
125
126        $pw_obj = &$this->_load();
127        if (PEAR::isError($pw_obj)) {
128            return array();
129        }
130
131        $users  = $pw_obj->listUser();
132        if (!is_array($users)) {
133            return array();
134        }
135
136        foreach ($users as $key => $value) {
137            $retVal[] = array("username" => $key,
138                              "password" => $value['passwd'],
139                              "cvsuser"  => $value['system']);
140        }
141
142        $this->log('Found '.count($retVal).' users.', AUTH_LOG_DEBUG);
143
144        return $retVal;
145    }
146
147    // }}}
148    // {{{ addUser()
149
150    /**
151     * Add a new user to the storage container
152     *
153     * @param string username
154     * @param string password
155     * @param mixed  Additional parameters to File_Password_*::addUser()
156     *
157     * @return boolean
158     */
159    function addUser($user, $pass, $additional='')
160    {
161        $this->log('Auth_Container_File::addUser() called.', AUTH_LOG_DEBUG);
162        $params = array($user, $pass);
163        if (is_array($additional)) {
164            foreach ($additional as $item) {
165                $params[] = $item;
166            }
167        } else {
168            $params[] = $additional;
169        }
170
171        $pw_obj = &$this->_load();
172        if (PEAR::isError($pw_obj)) {
173            return false;
174        }
175
176        $res = call_user_func_array(array(&$pw_obj, 'addUser'), $params);
177        if (PEAR::isError($res)) {
178            return false;
179        }
180
181        $res = $pw_obj->save();
182        if (PEAR::isError($res)) {
183            return false;
184        }
185
186        return true;
187    }
188
189    // }}}
190    // {{{ removeUser()
191
192    /**
193     * Remove user from the storage container
194     *
195     * @param   string  Username
196     * @return  boolean
197     */
198    function removeUser($user)
199    {
200        $this->log('Auth_Container_File::removeUser() called.', AUTH_LOG_DEBUG);
201        $pw_obj = &$this->_load();
202        if (PEAR::isError($pw_obj)) {
203            return false;
204        }
205
206        $res = $pw_obj->delUser($user);
207        if (PEAR::isError($res)) {
208            return false;
209        }
210
211        $res = $pw_obj->save();
212        if (PEAR::isError($res)) {
213            return false;
214        }
215
216        return true;
217    }
218
219    // }}}
220    // {{{ changePassword()
221
222    /**
223     * Change password for user in the storage container
224     *
225     * @param string Username
226     * @param string The new password
227     */
228    function changePassword($username, $password)
229    {
230        $this->log('Auth_Container_File::changePassword() called.', AUTH_LOG_DEBUG);
231        $pw_obj = &$this->_load();
232        if (PEAR::isError($pw_obj)) {
233            return false;
234        }
235
236        $res = $pw_obj->changePasswd($username, $password);
237        if (PEAR::isError($res)) {
238            return false;
239        }
240
241        $res = $pw_obj->save();
242        if (PEAR::isError($res)) {
243            return false;
244        }
245
246        return true;
247    }
248
249    // }}}
250    // {{{ _load()
251
252    /**
253     * Load and initialize the File_Passwd object
254     *
255     * @return  object  File_Passwd_Cvs|PEAR_Error
256     */
257    function &_load()
258    {
259        static $pw_obj;
260
261        if (!isset($pw_obj)) {
262            $this->log('Instanciating File_Password object of type '.$this->options['type'], AUTH_LOG_DEBUG);
263            $pw_obj = File_Passwd::factory($this->options['type']);
264            if (PEAR::isError($pw_obj)) {
265                return $pw_obj;
266            }
267
268            $pw_obj->setFile($this->pwfile);
269
270            $res = $pw_obj->load();
271            if (PEAR::isError($res)) {
272                return $res;
273            }
274        }
275
276        return $pw_obj;
277    }
278
279    // }}}
280    // {{{ _setDefaults()
281
282    /**
283     * Set some default options
284     *
285     * @access private
286     * @return void
287     */
288    function _setDefaults()
289    {
290        $this->options['type']       = 'Cvs';
291    }
292
293    // }}}
294    // {{{ _parseOptions()
295
296    /**
297     * Parse options passed to the container class
298     *
299     * @access private
300     * @param  array
301     */
302    function _parseOptions($array)
303    {
304        foreach ($array as $key => $value) {
305            if (isset($this->options[$key])) {
306                $this->options[$key] = $value;
307            }
308        }
309    }
310
311    // }}}
312
313}
314?>
315