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