* @copyright 2003-2005 Michael Wallner * @license http://www.php.net/license/3_0.txt PHP License 3.0 * @version CVS: $Id$ * @link http://pear.php.net/package/File_Passwd */ /** * Requires System */ require_once 'System.php'; /** * Requires File::Passwd */ require_once 'File/Passwd.php'; /** * Baseclass for File_Passwd_* classes. * * * Provides basic operations: * * 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 * @package File_Passwd * @version $Revision: 1.18 $ * @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); } /** * 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) { isset($file) or $file = $this->_file; $dir = dirname($file); $lock = strstr($mode, 'r') ? LOCK_SH : LOCK_EX; 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)) { 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)) { if (!preg_match('/^\s*#/', $line) && $line = trim($line)) { $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 $user 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_E_EXISTS_NOT_STR, 'User ', $user), FILE_PASSWD_E_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 $id, * false if $id wasn't found or PEAR_Error * @param string $file path to passwd file * @param string $id user_id to search for * @param string $sep field separator */ function _auth($file, $id, $sep = ':') { $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; } $cmp = $id . $sep; $len = strlen($cmp); while ($line = fgets($fh)) { if (!strncmp($line, $cmp, $len)) { File_Passwd_Common::_close($fh); return trim($line); } } $e = File_Passwd_Common::_close($fh); if (PEAR::isError($e)) { return $e; } return false; } } ?>