]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/pear/File_Passwd.php
trailing_spaces
[SourceForge/phpwiki.git] / lib / pear / File_Passwd.php
1 <?php
2 /* vim: set ts=4 sw=4: */
3 // +----------------------------------------------------------------------+
4 // | PHP Version 4                                                        |
5 // +----------------------------------------------------------------------+
6 // | Copyright (c) 1997-2002 The PHP Group                                |
7 // +----------------------------------------------------------------------+
8 // | This source file is subject to version 2.0 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 // | Author: Rasmus Lerdorf <rasmus@php.net>                              |
17 // +----------------------------------------------------------------------+
18 //
19 // $Id$
20 //
21 // Manipulate standard UNIX passwd,.htpasswd and CVS pserver passwd files
22
23 require_once 'PEAR.php' ;
24
25 /**
26 * Class to manage passwd-style files
27 *
28 * @author Rasmus Lerdorf <rasmus@php.net>
29 */
30 class File_Passwd {
31
32     /**
33     * Passwd file
34     * @var string
35     */
36     var $filename ;
37
38     /**
39     * Hash list of users
40     * @var array
41     */
42     var $users ;
43
44     /**
45     * hash list of csv-users
46     * @var array
47     */
48     var $cvs ;
49
50     /**
51     * filehandle for lockfile
52     * @var int
53     */
54     var $fplock ;
55
56     /**
57     * locking state
58     * @var boolean
59     */
60     var $locked ;
61
62     /**
63     * name of the lockfile
64     * @var string
65     */
66     var $lockfile = './passwd.lock';
67
68     /**
69     * Constructor
70     * Requires the name of the passwd file. This functions opens the file and read it.
71     * Changes to this file will written first in the lock file, so it is still possible
72     * to access the passwd file by another programs. The lock parameter controls the locking
73     * oft the lockfile, not of the passwd file! ( Swapping $lock and $lockfile would
74     * breaks bc to v1.3 and smaller).
75     * Don't forget to call close() to save changes!
76     *
77     * @param $file              name of the passwd file
78     * @param $lock              if 'true' $lockfile will be locked
79     * @param $lockfile  name of the temp file, where changes are saved
80     *
81     * @access public
82     * @see close()
83     */
84
85     function File_Passwd($file, $lock = 0, $lockfile = "") {
86         $this->filename = $file;
87         if( !empty( $lockfile) ) {
88             $this->lockfile = $lockfile;
89         }
90
91         if ($lock) {
92             //check if already locked, on some error or race condition or other user.
93             //FIXME: implement timeout as with dba
94             if (!empty($this->lockfile) and file_exists($this->lockfile)) {
95                 if (isset($GLOBALS['HTTP_GET_VARS']['force_unlock'])) {
96                     $this->fplock = fopen($this->lockfile, 'w');
97                     flock($this->fplock, LOCK_UN);
98                     fclose($this->fplock);
99                 } else {
100                     trigger_error('File_Passwd lock conflict: Try &force_unlock=1',E_USER_NOTICE);
101                 }
102             }
103             $this->fplock = fopen($this->lockfile, 'w');
104             flock($this->fplock, LOCK_EX);
105             $this->locked = true;
106         }
107
108         $fp = fopen($file,'r') ;
109         if( !$fp ) {
110             return new PEAR_Error( "Couldn't open '$file'!", 1, PEAR_ERROR_RETURN) ;
111         }
112         while(!feof($fp)) {
113             $line = fgets($fp, 128);
114             $array = explode(':', $line);
115             if (count($array) and strlen(trim($array[0]))) {
116                 $user = trim($array[0]);
117                 if (in_array(substr($user,0,1),array('#',';'))) continue;
118                 if (empty($array[1])) $array[1]='';
119                 $this->users[$user] = trim($array[1]);
120                 if (count($array) >= 3)
121                     $this->cvs[$user] = trim($array[2]);
122             }
123         }
124         fclose($fp);
125     }
126
127     /**
128     * Adds a user
129     *
130     * @param $user new user id
131     * @param $pass password for new user
132     * @param $cvs  cvs user id (needed for pserver passwd files)
133     *
134     * @return mixed returns PEAR_Error, if the user already exists
135     * @access public
136     */
137     function addUser($user, $pass, $cvsuser = "") {
138         if(!isset($this->users[$user]) && $this->locked) {
139             $this->users[$user] = crypt($pass);
140             $this->cvs[$user] = $cvsuser;
141             return true;
142         } else {
143             return new PEAR_Error( "Couldn't add user '$user', because the user already exists!", 2, PEAR_ERROR_RETURN);
144         }
145     } // end func addUser()
146
147     /**
148     * Modifies a user
149     *
150     * @param $user user id
151     * @param $pass new password for user
152     * @param $cvs  cvs user id (needed for pserver passwd files)
153     *
154     * @return mixed returns PEAR_Error, if the user doesn't exists
155     * @access public
156     */
157
158     function modUser($user, $pass, $cvsuser="") {
159         if(isset($this->users[$user]) && $this->locked) {
160             $this->users[$user] = crypt($pass);
161             $this->cvs[$user] = $cvsuser;
162             return true;
163         } else {
164             return new PEAR_Error( "Couldn't modify user '$user', because the user doesn't exists!", 3, PEAR_ERROR_RETURN) ;
165         }
166     } // end func modUser()
167
168     /**
169     * Deletes a user
170     *
171     * @param $user user id
172     *
173     * @return mixed returns PEAR_Error, if the user doesn't exists
174     * @access public
175     */
176
177     function delUser($user) {
178         if (isset($this->users[$user]) && $this->locked) {
179             unset($this->users[$user]);
180             unset($this->cvs[$user]);
181         } else {
182             return new PEAR_Error( "Couldn't delete user '$user', because the user doesn't exists!", 3, PEAR_ERROR_RETURN) ;
183         }
184     } // end func delUser()
185
186     /**
187     * Verifies a user's password
188     *
189     * @param $user user id
190     * @param $pass password for user
191     *
192     * @return boolean true if password is ok
193     * @access public
194     */
195     function verifyPassword($user, $pass) {
196         //if ($this->users[$user] == crypt($pass, substr($this->users[$user], 0, 2)))
197         //  return true;
198         if (isset($this->users[$user])) {
199             $stored_password = $this->users[$user];
200             if (function_exists('crypt')) {
201                 if (crypt($pass, $stored_password) == $stored_password)
202                     return true; // matches encrypted password
203                 else
204                     return false;
205             } else {
206                 if ($pass == $stored_password)
207                     return true; // matches plaintext password
208                 else {
209                     trigger_error(_("The crypt function is not available in this version of PHP."),
210                                   E_USER_WARNING);
211                     return false;
212                 }
213             }
214         }
215         return false;
216     }
217
218     /**
219     * Return all users from passwd file
220     *
221     * @access public
222     * @return array
223     */
224     function listUsers() {
225         return $this->users;
226     } // end func listUsers()
227
228     /**
229     * Writes changes to passwd file and unlocks it
230     *
231     * @access public
232     */
233     function close() {
234         if ($this->locked) {
235             foreach($this->users as $user => $pass) {
236                 if (isset($this->cvs[$user])) {
237                     fputs($this->fplock, "$user:$pass:" . $this->cvs[$user] . "\n");
238                 } else {
239                     fputs($this->fplock, "$user:$pass\n");
240                 }
241             }
242             @unlink($this->filename.'.bak');
243             if (isWindows()) {
244               // windows doesn't allow renaming of open files
245               flock($this->fplock, LOCK_UN);
246               $this->locked = false;
247               fclose($this->fplock);
248               rename($this->filename,$this->filename.'.bak');
249               rename($this->lockfile, $this->filename);
250             } else {
251               rename($this->filename,$this->filename.'.bak');
252               rename($this->lockfile, $this->filename);
253               flock($this->fplock, LOCK_UN);
254               $this->locked = false;
255               fclose($this->fplock);
256             }
257             if (file_exists($this->filename))
258                 @unlink($this->filename.'.bak');
259             else {
260                 rename($this->filename.'.bak',$this->filename);
261             }
262         }
263     } // end func close()
264 }
265
266 // Local Variables:
267 // mode: php
268 // tab-width: 8
269 // c-basic-offset: 4
270 // c-hanging-comment-ender-p: nil
271 // indent-tabs-mode: nil
272 // End:
273 ?>