Location: PHPKode > projects > ZZ/OSS Installer > zic-1.1.0dev1/installer/lib/File/Passwd.php
<?php
// +----------------------------------------------------------------------+
// | PHP Version 4                                                        |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 The PHP Group                                |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.0 of the PHP license,       |
// | that is bundled with this package in the file LICENSE, and is        |
// | available at through the world-wide-web at                           |
// | http://www.php.net/license/2_02.txt.                                 |
// | If you did not receive a copy of the PHP license and are unable to   |
// | obtain it through the world-wide-web, please send a note to          |
// | hide@address.com so we can mail you a copy immediately.               |
// +----------------------------------------------------------------------+
// | Author: Rasmus Lerdorf <hide@address.com>                              |
// +----------------------------------------------------------------------+
//
// $Id: Passwd.php,v 1.9 2003/10/01 13:25:38 mike Exp $

/**
* Manipulate many kinds of passwd files.
* 
* @author       Rasmus Lerdorf <hide@address.com>
* @package      File_Passwd
* @category     FileSystem
*/

/**
* Requires PEAR.
*/
require_once('PEAR.php');

/**
* Undefined error.
*/
define('FILE_PASSWD_E_UNDEFINED',                   0);
/**
* Invalid file format.
*/
define('FILE_PASSWD_E_INVALID_FORMAT',              1);
define('FILE_PASSWD_E_INVALID_FORMAT_STR',          'Passwd file has invalid format.');
/**
* Invalid extra property.
*/
define('FILE_PASSWD_E_INVALID_PROPERTY',            2);
define('FILE_PASSWD_E_INVALID_PROPERTY_STR',        'Invalid property \'%s\'.');
/**
* Invalid characters.
*/
define('FILE_PASSWD_E_INVALID_CHARS',               3);
define('FILE_PASSWD_E_INVALID_CHARS_STR',           '%s\'%s\' contains illegal characters.');
/**
* Invalid encryption mode.
*/
define('FILE_PASSWD_E_INVALID_ENC_MODE',            4);
define('FILE_PASSWD_E_INVALID_ENC_MODE_STR',        'Encryption mode \'%s\' not supported.');
/**
* Exists already.
*/
define('FILE_PASSWD_E_EXISTS_ALREADY',              5);
define('FILE_PASSWD_E_EXISTS_ALREADY_STR',          '%s\'%s\' already exists.');
/**
* Exists not.
*/
define('FILE_PASSWD_E_EXISTS_NOT',                  6);
define('FILE_PASSWD_E_EXISTS_NOT_STR',              '%s\'%s\' doesn\'t exist.');
/**
* User not in group.
*/
define('FILE_PASSWD_E_USER_NOT_IN_GROUP',           7);
define('FILE_PASSWD_E_USER_NOT_IN_GROUP_STR',       'User \'%s\' doesn\'t exist in group \'%s\'.');
/**
* User not in realm.
*/
define('FILE_PASSWD_E_USER_NOT_IN_REALM',           8);
define('FILE_PASSWD_E_USER_NOT_IN_REALM_STR',       'User \'%s\' doesn\'t exist in realm \'%s\'.');
/**
* Parameter must be of type array.
*/
define('FILE_PASSWD_E_PARAM_MUST_BE_ARRAY',         9);
define('FILE_PASSWD_E_PARAM_MUST_BE_ARRAY_STR',     'Parameter %s must be of type array.');
/**
* Method not implemented.
*/
define('FILE_PASSWD_E_METHOD_NOT_IMPLEMENTED',      10);
define('FILE_PASSWD_E_METHOD_NOT_IMPLEMENTED_STR',  'Method \'%s()\' not implemented.');
/**
* Directory couldn't be created.
*/
define('FILE_PASSWD_E_DIR_NOT_CREATED',             11);
define('FILE_PASSWD_E_DIR_NOT_CREATED_STR',         'Couldn\'t create directory \'%s\'.');
/**
* File couldn't be opened.
*/
define('FILE_PASSWD_E_FILE_NOT_OPENED',             12);
define('FILE_PASSWD_E_FILE_NOT_OPENED_STR',         'Couldn\'t open file \'%s\'.');
/**
* File coudn't be locked.
*/
define('FILE_PASSWD_E_FILE_NOT_LOCKED',             13);
define('FILE_PASSWD_E_FILE_NOT_LOCKED_STR',         'Couldn\'t lock file \'%s\'.');
/**
* File couldn't be unlocked.
*/
define('FILE_PASSWD_E_FILE_NOT_UNLOCKED',           14);
define('FILE_PASSWD_E_FILE_NOT_UNLOCKED_STR',       'Couldn\'t unlock file.');
/**
* File couldn't be closed.
*/
define('FILE_PASSWD_E_FILE_NOT_CLOSED',             15);
define('FILE_PASSWD_E_FILE_NOT_CLOSED_STR',         'Couldn\'t close file.');

/**
* Class to manage passwd-style files
*
* @author       Rasmus Lerdorf <hide@address.com>
* @package      File_Passwd
* @category     FileSystem
* @version      $Revision: 1.9 $
* @deprecated   <b>Please use the provided factory instead!</b>
* 
* <code>
*  $passwd = &File_Passwd::factory('Unix');
* </code>
*/
class File_Passwd {

    /**
    * Passwd file
    * @var string
    */
    var $filename;

    /**
    * Hash list of users
    * @var array
    */
    var $users;
    
    /**
    * hash list of csv-users
    * @var array
    */
    var $cvs;
    
    /**
    * filehandle for lockfile
    * @var int
    */
    var $fplock;
    
    /**
    * locking state
    * @var boolean
    */
    var $locked;
    
    /**
    * name of the lockfile
    * @var string    
    */ 
    var $lockfile = './passwd.lock';

    /**
    * Constructor
    * 
    * Requires the name of the passwd file. This functions opens the file and 
    * read it. Changes to this file will written first in the lock file, 
    * so it is still possible to access the passwd file by another programs. 
    * The lock parameter controls the locking oft the lockfile, not of the 
    * passwd file! (Swapping $lock and $lockfile would break BC).
    * Don't forget to call close() to save changes!
    * 
    * @param $file		name of the passwd file
    * @param $lock		if 'true' $lockfile will be locked
    * @param $lockfile	name of the temp file, where changes are saved
    *
    * @access public
    * @see close() 
    */

    function File_Passwd($file, $lock = 0, $lockfile = "") {
        $this->filename = $file;
        if( !empty( $lockfile) ) {
            $this->lockfile = $lockfile ;
        }

        if($lock) {
            $this->fplock = fopen($this->lockfile, 'w');
            flock($this->fplock, LOCK_EX);
            $this->locked = true;
        }
    
        $fp = fopen($file,'r') ;
        if( !$fp) {
            return PEAR::raiseError( "Couldn't open '$file'!", 1) ;
        }
        while(!feof($fp)) {
            $line = fgets($fp, 128);
            if (!strlen($line)) {
                continue;
            }
            @list($user, $pass, $cvsuser) = explode(':', $line);
            if(strlen($user)) {
                $this->users[$user] = trim($pass);
                $this->cvs[$user] = trim($cvsuser);	
            }
        }
        fclose($fp);
    } // end func File_Passwd()

    /**
    * Adds a user
    *
    * @param $user new user id
    * @param $pass password for new user
    * @param $cvs  cvs user id (needed for pserver passwd files)
    *
    * @return mixed returns PEAR_Error, if the user already exists
    * @access public
    */
    function addUser($user, $pass, $cvsuser = "") {
        if(!isset($this->users[$user]) && $this->locked) {
            $this->users[$user] = crypt($pass);
            $this->cvs[$user] = $cvsuser;
            return true;
        } else {
            return PEAR::raiseError(
                "Couldn't add user '$user', because the user already exists!", 
                2
            );
        }
    } // end func addUser()

    /**
    * Modifies a user
    *
    * @param $user user id
    * @param $pass new password for user
    * @param $cvs  cvs user id (needed for pserver passwd files)
    *
    * @return mixed returns PEAR_Error, if the user doesn't exists
    * @access public
    */

    function modUser($user, $pass, $cvsuser="") {
        if(isset($this->users[$user]) && $this->locked) {
            $this->users[$user] = crypt($pass);
            $this->cvs[$user] = $cvsuser;
            return true;
        } else {
            return PEAR::raiseError(
                "Couldn't modify user '$user', because the user doesn't exists!",
                3
            );
        }
    } // end func modUser()

    /**
    * Deletes a user
    *
    * @param $user user id
    *
    * @return mixed returns PEAR_Error, if the user doesn't exists
    * @access public	
    */
    
    function delUser($user) {
        if(isset($this->users[$user]) && $this->locked) {
            unset($this->users[$user]);
            unset($this->cvs[$user]);
        } else {
            return PEAR::raiseError(
                "Couldn't delete user '$user', because the user doesn't exists!",
                3
            ); 
        }
    } // end func delUser()

    /**
    * Verifies a user's password
    *
    * @param $user user id
    * @param $pass password for user
    *
    * @return boolean true if password is ok
    * @access public		
    */
    function verifyPassword($user, $pass) {
        if(isset($this->users[$user])) {
            return (
                $this->users[$user] == crypt(
                    $pass, 
                    substr($this->users[$user], 0, CRYPT_SALT_LENGTH)
                )
            );
        }
        return false;
    } // end func verifyPassword()

    /**
    * Return all users from passwd file
    *
    * @access public
    * @return array
    */
    function listUsers() {
        return $this->users;
    } // end func listUsers()

    /**
    * Writes changes to passwd file and unlocks it
    *
    * @access public
    */
    function close() {
        if($this->locked) {
            foreach($this->users as $user => $pass) {
                if($this->cvs[$user]) {
                    fputs($this->fplock, "$user:$pass:" . $this->cvs[$user] . "\n");
                } else {
                    fputs($this->fplock, "$user:$pass\n");
                }
            }
            rename($this->lockfile, $this->filename);
            flock($this->fplock, LOCK_UN);
            $this->locked = false;
            fclose($this->fplock);
        }
    } // end func close()


    /**
    * Lock the lockfile
    *
    * @access public
    */
    function lock() {
        $this->fplock = fopen($this->lockfile, 'w');
        flock($this->fplock, LOCK_EX);
        $this->locked = true;
    }

    /**
    * Unlock the lockfile
    *
    * @access public
    */
    function unlock() {
        flock($this->fplock, LOCK_UN);
        $this->locked = false;
        fclose($this->fplock);
    }

    /**
    * Determine if lockfile is locked
    *
    * @return boolean
    * @access public
    */
    function isLocked() {
        return($this->locked);
    }

    /**
    * Get the CVS username 
    *
    * @param  string username
    * @return string
    * @access public
    */
    function getCvsUser($user) {
       return($this->cvs[$user]);
    }

    /**
    * Get API version
    *
    * @author   Michael Wallner <hide@address.com>
    * 
    * @static
    * @access   public
    * @return   string          API version
    */
    function apiVersion(){
    	return '@API_VERSION@';
    }
    
    /**
    * Factory for new extensions
    * 
    * o Unix        for standard Unix passwd files
    * o CVS         for CVS pserver passwd files
    * o SMB         for SMB server passwd files
    * o Authbasic   for AuthUserFiles
    * o Authdigest  for AuthDigestFiles
    * 
    * Returns a PEAR_Error if the desired class/file couldn't be loaded.
    * 
    * @author   Michael Wallner <hide@address.com>
    * 
    * @static   use &File_Passwd::factory() for instantiating you passwd object
    * 
    * @throws   PEAR_Error
    * @access   public
    * @return   object    File_Passwd_$class - desired Passwd object
    * @param    string    $class the desired subclass of File_Passwd
    */
    function &factory($class){
        $class = ucFirst(strToLower($class));
        if (!@include_once("File/Passwd/$class.php")) {
            return PEAR::raiseError("Couldn't load file Passwd/$class.php", 0);
        }
        $class = 'File_Passwd_'.$class;
        if (!class_exists($class)) {
            return PEAR::raiseError("Couldn't load class $class.", 0);
        }
        $instance = &new $class();
        return $instance;
    }
    
    /**
    * Fast authentication of a certain user
    * 
    * Returns a PEAR_Error if:
    *   o file doesn't exist
    *   o file couldn't be opened in read mode
    *   o file couldn't be locked exclusively
    *   o file couldn't be unlocked (only if auth fails)
    *   o file couldn't be closed (only if auth fails)
    *   o invalid <var>$type</var> was provided
    *   o invalid <var>$opt</var> was provided
    * 
    * Depending on <var>$type</var>, <var>$opt</var> should be:
    *   o Smb:          encryption method (NT or LM)
    *   o Unix:         encryption method (des or md5)
    *   o Authdigest:   the realm the user is in
    *   o Authbasic:    n/a (empty) (*)
    *   o Cvs:          n/a (empty)
    * 
    *   (*) The File_Passwd_Authbasic facility can verify
    *       only DES enrypted passwords when called statically.
    *
    * @author   Michael Wallner <hide@address.com>
    * 
    * @static   call this method statically for a reasonable fast authentication
    * 
    * @throws   PEAR_Error
    * @access   public
    * @return   return      mixed   true if authenticated, 
    *                               false if not or PEAR_error
    * @param    string      $type   Unix, Cvs, Smb, Authbasic or Authdigest
    * @param    string      $file   path to passwd file
    * @param    string      $user   the user to authenticate
    * @param    string      $pass   the plaintext password
    * @param    string      $opt    o Smb:          NT or LM
    *                               o Unix:         des or md5
    *                               o Authbasic     des, sha or md5
    *                               o Authdigest    realm the user is in
    */
    function staticAuth($type, $file, $user, $pass, $opt = ''){
        $type = ucFirst(strToLower($type));
        if (!@include_once("File/Passwd/$type.php")) {
            return PEAR::raiseError("Coudn't load file Passwd/$type.php", 0);
        }
        switch($type){
        	case 'Unix': 
        		return File_Passwd_Unix::staticAuth(
                    $file, $user, $pass, $opt
                );
        		break;
        	case 'Cvs': 
        		return File_Passwd_Cvs::staticAuth(
                    $file, $user, $pass
                );
        		break;
            case 'Smb':
                return File_Passwd_Smb::StaticAuth(
                    $file, $user, $pass, $opt
                );
                break;
            case 'Authbasic':
                return File_Passwd_Authbasic::staticAuth(
                    $file, $user, $pass, $opt
                );
                break;
            case 'Authdigest':
                return File_Passwd_Authdigest::staticAuth(
                    $file, $user, $pass, $opt
                );
                break;
        }
        return false;
    }
    
}
?>
Return current item: ZZ/OSS Installer