<?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: Michael Wallner <hide@address.com> |
// +----------------------------------------------------------------------+
//
// $Id: Common.php,v 1.5 2003/10/01 13:26:06 mike Exp $
/**
* Baseclass for File_Passwd_* classes.
*
* @author Michael Wallner <hide@address.com>
* @package File_Passwd
*/
/**
* Requires System
*/
require_once('System.php');
/**
* Requires File::Passwd
*/
require_once('File/Passwd.php');
/**
* SHA encryption
*/
define('FILE_PASSWD_SHA', 'sha');
/**
* MD5 encryption
*/
define('FILE_PASSWD_MD5', 'md5');
/**
* DES encryption
*/
define('FILE_PASSWD_DES', 'des');
/**
* Baseclass for File_Passwd_* classes.
*
* <kbd><u>
* Provides basic operations:
* </u></kbd>
* o opening & closing
* o locking & unlocking
* o loading & saving
* o check if user exist
* o delete a certain user
* o list users
*
* @author Michael Wallner <hide@address.com>
* @package File_Passwd
* @version $Revision: 1.5 $
* @access protected
* @internal extend this class for your File_Passwd_* class
*/
class File_Passwd_Common {
/**
* passwd file
*
* @var string
* @access protected
*/
var $_file = 'passwd';
/**
* file content
*
* @var aray
* @access protected
*/
var $_contents = array();
/**
* users
*
* @var array
* @access protected
*/
var $_users = array();
/**
* PCRE for valid chars
*
* @var string
* @access protected
*/
var $_pcre = '/^[a-z]+[a-z0-9_-]*$/i';
/**
* Constructor (ZE2)
*
* @access protected
* @param string $file path to passwd file
*/
function __construct($file = 'passwd'){
$this->setFile($file);
}
/**
* Get Copy of this object (ZE2)
*
* @access public
* @return object copy of this opject
*/
function __clone(){
return $this;
}
/**
* Parse the content of the file
*
* You must overwrite this method in your File_Passwd_* class.
*
* @abstract
* @internal
* @access public
* @return object PEAR_Error
*/
function parse(){
return PEAR::raiseError(
sprintf(FILE_PASSWD_E_METHOD_NOT_IMPLEMENTED_STR, 'parse'),
FILE_PASSWD_E_METHOD_NOT_IMPLEMENTED
);
}
/**
* Apply changes and rewrite passwd file
*
* You must overwrite this method in your File_Passwd_* class.
*
* @abstract
* @internal
* @access public
* @return object PEAR_Error
*/
function save(){
return PEAR::raiseError(
sprintf(FILE_PASSWD_E_METHOD_NOT_IMPLEMENTED_STR, 'save'),
FILE_PASSWD_E_METHOD_NOT_IMPLEMENTED
);
}
/**
* Opens a file, locks it exclusively and returns the filehandle
*
* Returns a PEAR_Error if:
* o directory in which the file should reside couldn't be created
* o file couldn't be opened in the desired mode
* o file couldn't be locked exclusively
*
* @throws PEAR_Error
* @access protected
* @return mixed resource of type file handle or PEAR_Error
* @param string $mode the mode to open the file with
*/
function &_open($mode, $file = null){
$file = realpath( is_null($file) ? $this->_file : $file );
$dir = dirname($file);
if (!is_dir($dir) && !System::mkDir('-p -m 0755 ' . $dir)) {
return PEAR::raiseError(
sprintf(FILE_PASSWD_E_DIR_NOT_CREATED_STR, $dir),
FILE_PASSWD_E_DIR_NOT_CREATED
);
}
if (!is_resource($fh = @fopen($file, $mode))) {
return PEAR::raiseError(
sprintf(FILE_PASSWD_E_FILE_NOT_OPENED_STR, $file),
FILE_PASSWD_E_FILE_NOT_OPENED
);
}
if (!@flock($fh, LOCK_EX)) {
fclose($fh);
return PEAR::raiseError(
sprintf(FILE_PASSWD_E_FILE_NOT_LOCKED_STR, $file),
FILE_PASSWD_E_FILE_NOT_LOCKED
);
}
return $fh;
}
/**
* Closes a prior opened and locked file handle
*
* Returns a PEAR_Error if:
* o file couldn't be unlocked
* o file couldn't be closed
*
* @throws PEAR_Error
* @access protected
* @return mixed true on success or PEAR_Error
* @param resource $file_handle the file handle to operate on
*/
function _close(&$file_handle){
if (!@flock($file_handle, LOCK_UN)) {
return PEAR::raiseError(
FILE_PASSWD_E_FILE_NOT_UNLOCKED_STR,
FILE_PASSWD_E_FILE_NOT_UNLOCKED
);
}
if (!@fclose($file_handle)) {
return PEAR::raiseError(
FILE_PASSWD_E_FILE_NOT_CLOSED_STR,
FILE_PASSWD_E_FILE_NOT_CLOSED
);
}
return true;
}
/**
* Loads the file
*
* Returns a PEAR_Error if:
* o directory in which the file should reside couldn't be created
* o file couldn't be opened in read mode
* o file couldn't be locked exclusively
* o file couldn't be unlocked
* o file couldn't be closed
*
* @throws PEAR_Error
* @access public
* @return mixed true on success or PEAR_Error
*/
function load(){
$fh = &$this->_open('r');
if (PEAR::isError($fh)) {
return $fh;
}
$this->_contents = array();
while ($line = fgets($fh)){
$line = trim(preg_replace('/^(\S*.*)#.*$/', '\\1', $line));
if (empty($line)) {
continue;
}
$this->_contents[] = $line;
}
$e = $this->_close($fh);
if (PEAR::isError($e)) {
return $e;
}
return $this->parse();
}
/**
* Save the modified content to the passwd file
*
* Returns a PEAR_Error if:
* o directory in which the file should reside couldn't be created
* o file couldn't be opened in write mode
* o file couldn't be locked exclusively
* o file couldn't be unlocked
* o file couldn't be closed
*
* @throws PEAR_Error
* @access protected
* @return mixed true on success or PEAR_Error
*/
function _save($content){
$fh = &$this->_open('w');
if (PEAR::isError($fh)) {
return $fh;
}
fputs($fh, $content);
return $this->_close($fh);
}
/**
* Set path to passwd file
*
* @access public
* @return void
*/
function setFile($file){
$this->_file = $file;
}
/**
* Get path of passwd file
*
* @access public
* @return string
*/
function getFile(){
return $this->_file;
}
/**
* Check if a certain user already exists
*
* @access public
* @return bool
* @param string $user the name of the user to check if already exists
*/
function userExists($user){
return isset($this->_users[$user]);
}
/**
* Delete a certain user
*
* Returns a PEAR_Error if user doesn't exist.
*
* @throws PEAR_Error
* @access public
* @return mixed true on success or PEAR_Error
* @param string
*/
function delUser($user){
if (!$this->userExists($user)) {
return PEAR::raiseError(
sprintf(FILE_PASSWD_E_EXISTS_NOT_STR, 'User ', $user),
FILE_PASSWD_E_EXISTS_NOT
);
}
unset($this->_users[$user]);
return true;
}
/**
* List user
*
* Returns a PEAR_Error if <var>$user</var> doesn't exist.
*
* @throws PEAR_Error
* @access public
* @return mixed array of a/all user(s) or PEAR_Error
* @param string $user the user to list or all users if empty
*/
function listUser($user = ''){
if (empty($user)) {
return $this->_users;
}
if (!$this->userExists($user)) {
return PEAR::raiseError(
sprintf(FILE_PASSWD_EXISTS_NOT_STR, 'User ', $user),
FILE_PASSWD_EXISTS_NOT
);
}
return $this->_users[$user];
}
/**
* Base method for File_Passwd::staticAuth()
*
* 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)
*
* @throws PEAR_Error
* @access protected
* @return mixed line of passwd file containing <var>$id</var>,
* false if <var>$id</var> wasn't found or PEAR_Error
* @param string $file path to passwd file
* @param string $id user_id to search for
*/
function _auth($file, $id){
$file = realpath($file);
if (!is_file($file)) {
return PEAR::raiseError("File '$file' couldn't be found.", 0);
}
$fh = &File_Passwd_Common::_open('r', $file);
if (PEAR::isError($fh)) {
return $fh;
}
while($line = fgets($fh)){
if (strstr($line, $id)) {
File_Passwd_Common::_close($fh);
return trim($line);
}
}
$e = File_Passwd_Common::_close($fh);
if (PEAR::isError($e)) {
return $e;
}
return false;
}
}
?>