Location: PHPKode > projects > PhpMySphere > phpMySphere-devel/src/module/Accountfile.php
<?php
/***************************************************************************
 *   Copyright (C) 2003 by Sebastian Hess                                  *
 *   hide@address.com                                               *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 ***************************************************************************/
class AccountFile {

	var $AFile;		// The sphereaccu.scp
	var $BFile; 	// The sphereacct.scp
	var $Data;		// The Array of Accounts
	var $orgCount;	// The count of Data after reading
	var $deleteFlag;// Are we in the need to delete a user ?
	var $dirtyData; // There was an Update on one or more Accounts

    /**
    * Constructor of this Class
    *
    * @param    string  $accountFile    Path to sphereaccu.scp
    * @param    string  $accountTemp	Path to sphereacct.scp
    * @return   void
    */
	function AccountFile($accountFile,$accountTemp) {
		$this->AFile      = $accountFile;
		$this->BFile      = $accountTemp;
		$this->Data       = array();
		$this->deleteFlag = false;
		$this->dirtyData  = false;
		// Init the Datastructures (maybe called more the one time, to check for changes)
		return $this->readUsers();
	}

    /**
    * (re)reads the Accountfile to check for the useraccounts
    *
    * @return   bool	false if file can't be opened
    */
	function readUsers() {

		/*
			Init the Variables
		*/
		$lastAcc = "";
		$i = -1;

		/*
			Open sphereaccu.scp
		*/
		$handle = fopen($this->AFile,"r");


		/*
			The file doesn't exist or isn't readable
		*/
		if(!$handle)
			return false;

		/*
			Read out the file
		*/
		while (!feof($handle) && $handle) {
			$buffer = chop(fgets($handle, 4096));

			/*
				Check if we got a new User Entry
				Don't stop reading at [EOF] because we check for
				bugs/manipulations in the Accountfile later
			*/
			if ($buffer{0} == "[") {

				$i++; // Save a new id (begin at 0)
				$this->Data[$i]["NAME"] = substr($buffer,1,-1);

				/*
					Normal Players don't have a PLEVEL-Entry in sphereaccu.scp
					so set it to player by default!
				*/

				$this->Data[$i]["PLEVEL"] = "Player";
				$this->Data[$i]["PASSWORD"]  = "(none set)";
				$this->Data[$i]["BLOCK"]  = false;
				$this->Data[$i]["CHARCOUNT"]  = 0;
				/*
					Where done with this line
				*/
				continue;
			}

			/*
				Split the lines so that
				PLEVEL=Owner
				will be splittet in
				$Parm = PLEVEL
				and
				$Zuweisung = Owner

				I use strtoupper to use the samewriten index everywhere
			*/
			list($Parm,$Zuweisung) = split("=",$buffer);
			$Parm = strtoupper($Parm);

			/*
				Check is both the Name and the Value are avaible
				if not continue with next line
			*/
			if(empty($Parm) || empty($Zuweisung)) continue; // To avoid Errors on saving

			/*
				Save the Playercharacters in a new Array, because we need
				them in the detail view
			*/
			if($Parm=="CHARUID") {
				$this->Data[$i]["CHAR"][count($this->Data[$i]["CHAR"])] = $Zuweisung;
				$this->Data[$i]["CHARCOUNT"]++;
			} else {
				/*
					Save the data in the Array
				*/
				$this->Data[$i][$Parm] = $Zuweisung;
			}
		}

		/*
			This little setting saves us some CPU Circles later
		*/
		$this->orgCount = count($this->Data);

		@fclose($handle);
		return true;
	}


	/**
    * Find Users that match the Query
    *
	* @param    string  $Query	The param the Name should match
	* @param    bool    $inStr  Default: true 	If true the check is done through
	*											instr otherwise through strcmp (case insensitive)
    * @return   array	Array of the found users, check with count() > 0 for matches
    */
	function findUser($Query,$inStr=true) {
		/*
			Prepare the return Array
		*/
		$accounts = array();

		/*
			Run through all Entries
		*/
		for($i=0;$i < count($this->Data);$i++) {
			if($inStr) {
				if(stristr($this->Data[$i]["NAME"],$Query)) {
					array_push($accounts,$this->Data[$i]);
					$accounts[count($accounts)]["ID"] = $i; // Set the ID, so that we can access directly
				}
			} else { // Use StringCompare beware of the fact, that 0 is true
				if(strcmp(strtolower($this->Data[$i]["NAME"]),strtolower($Query))==0) {
						array_push($accounts,$this->Data[$i]);
						$accounts[count($accounts)]["ID"] = $i; // Set the ID, so that we can access directly
				}
			}
		}
		/*
			Return the found users (if non found, then count of this will be 0)
		*/
		return $accounts;
	}


	/**
    * Add a new User to the sphereacct.scp
    *
	* @param    string  $AccountName	The Name of the Account
	* @param	int		$PLEVEL			The Player Level
	* @param	string	$Password		The Password of the new Account
    * @return   bool	false if the users exists or contains unallowed characters
    */
	function addUser($AccountName,$PLEVEL=1,$Password) {
			/*
				Check for usage of [ and ] in the Name
				also EOF Accounts or empty Accountnames are not
				allowed
			*/
			if(eregi("(^[\]\[\$\\/=)+",$AccountName) || strtoupper($AccountName) == "EOF" || empty($AccountName)) {
				return false;
			}

			/*
				The User does exist, so we can't edit but update it
				Therefor return false and let the main programm check
				for this
			*/
			if(count($this->findUser($AccountName,false)))
				return false;

			$data["NAME"]   = $AccountName;
			$data["PLEVEL"] = $PLEVEL;
			$data["PASSWORD"] = $Password;

			/*
				Add the new Data at the end of Data Array
			*/
			array_push($this->Data,$data);
			return true;
	}

	/**
    * Delete an user
    *
	* @param    mixed   $AccountName	Can be a String or the nummer in the Array
	*									If it's the Sting it will be converted
    * @return   bool	false if the users doesn't exist
    */
	function delUser($AccountName) {

			/*
				Find the nummer of the Array Entrie by using the findUser
				function
			*/
			if(!is_numeric($AccountName)) {
				$erg = $this->findUser($AccountName,false);
				if(!count($erg)) return false;
				$AccountName = $erg[0]["ID"];
			}

			/*
				The given number ist greater then the Array itself ?
				Could not be !
			*/
			if($AccountName > count($this->Data))
				return false;

			/*
				Remove the Dirtyflag, so it will not be added
				to the sphereacct.scp
			*/
			$this->Data[$AccountName]["DIRTY"] = false;
			$this->Data[$AccountName]["DEL"] = true;

			/*
				Tell the system there are users to be deleted
			*/
			$this->deleteFlag = true;
			return true;
	}


	/**
    * Blocks an user
    *
	* @param    mixed   $AccountName	Can be a String or the nummer in the Array
	*									If it's the Sting it will be converted
	* @param	bool	$block			Set the block or unblock the user ?
    * @return   bool	false if the users doesn't exist
    */
	function blockUser($AccountName,$block=true) {

		/*
			Find the nummer of the Array Entry by using the findUser
			function
		*/
		if(!is_numeric($AccountName)) {
			$erg = $this->findUser($AccountName,false);
			if(!count($erg)) return false;
			$AccountName = $erg[count($erg)-1]["ID"];
		}

		/*
			The given number ist greater then the Array itself ?
			Could not be !
		*/
		if($AccountName > count($this->Data))
			return false;

		/*
			Set the dirty data aswell as the status of the blocking
		*/
		$this->Data[$AccountName]["BLOCK"] = (($block==true) ? 1 : 0);
		$this->Data[$AccountName]["DIRTY"] = true;
		/*
			Tell the system there are users to be blocked
		*/
		$this->dirtyData = true;
		return true;
	}

	/**
    * Edit an user, change his PLEVEL set him Blocked, set his password
    *
	* @param    int		$id		The Nummer of the user in the Array
	* @param 	int		$PLEVEL	Change the users PLEVEL
	* @param 	String	$PASSWORD	Set the users password to this
	* @param 	int		$BLOCK		0 => unblock | 1 => block
    * @return   bool	false if the users doesn't exist
    */

	function editUser($id,$PLEVEL=0,$PASSWORD=false,$BLOCK=-1) {

		/*
			Don't run out of Bound
		*/
		if($id < 0 || $id > count($this->Data))
			return false;

  		if($PLEVEL > 0)
			$this->Data[$id]["PLEVEL"] = $PLEVEL;
		if($BLOCK > -1)
			$this->Data[$id]["BLOCK"] = $BLOCK;
		if($PASSWORD != false)
			$this->Data[$id]["PASSWORD"] = $PASSWORD;


		/*
			Mark this record for writing
		*/
		$this->Data[$id]["DIRTY"] = true;

		/*
			Tell the system we need to write to sphereacct.scp
		*/
		$this->dirtyData = true;

		return true;
	}

	// I'm able to add the new Entries, but how do i make changes or even delete entries ??
	function writeAccountFile() {
		/* I will only append the changes, so there is a possible change that the data
			may corrupt, but I don't know better for now */

		$buffer = "";

		if(($this->orgCount == count($this->Data)) && !$this->dirtyData && !$this->deleteFlag) return true; // Nothing to do here

		/* First prepare the buffer to where we later write the Data */
		$AddFileContent  = ""; // to write to the "to-be-added-file" (sphereacct.scp)

		echo nl2br(print_r($this->Data));

		// Loop through the new entries
		if($this->orgCount < count($this->Data)) {
			// Everything over the oldCount is addet newly
			for($i=$this->orgCount; $i < count($this->Data); $i++) {
				$AddFileContent .= "[".$this->Data[$i]["NAME"]."]\n";
				$AddFileContent .= "PLEVEL=".$this->Data[$i]["PLEVEL"]."\n";
				$AddFileContent .= "PASSWORD=".$this->Data[$i]["PASSWORD"]."\n";
			}
		}

		// Loop through the Accounts, which where read, to find the Accounts to update
		if($this->dirtyData) {
			// Everything over the oldCount is addet newly
			for($i=0; $i <= $this->orgCount; $i++) {

				if($this->Data[$i]["DIRTY"] != true) continue;
				if(empty($this->Data[$i]["NAME"])) continue;

				$AddFileContent .= "[".$this->Data[$i]["NAME"]."]\n";
				$AddFileContent .= "PLEVEL=".$this->Data[$i]["PLEVEL"]."\n";
				$AddFileContent .= "PASSWORD=".$this->Data[$i]["PASSWORD"]."\n";
				if(!empty($this->Data[$i]["BLOCK"]))
					$AddFileContent .= "BLOCK=".$this->Data[$i]["BLOCK"]."\n";
			}
		}


		// Checked for locked Files
		if(file_exists($this->BFile.".locked"))
			die('The File '.$this->BFile.' is locked by another process. Please click <a href="javascript:location.reload()">here</a> to retry');

		fopen($this->BFile.".locked","w"); // Create the lock file, to ensure that noone writes to it in the same moment
		$handle_add = fopen($this->BFile,"a");

		if(!$handle_add) {
			die("Could not open ".$this->BFile." for writing (check permissions please)");
			return false;
		}

		fputs($handle_add,$AddFileContent); // Write the data
		fclose($handle_add);
		unlink($this->BFile.".locked"); // Remove the lock file, so we could write again


		// Must we realy go to sphereaccu.scp
		if(!$this->deleteFlag) return true;


		/*
			Ready with the sphereacct.scp. Now continue with the sphereaccu.scp
			We must be carefull about this file, because when we write to it while
			sphere writes to it
		*/

		$handle_ini = fopen($this->AFile,"r");
		$handle_del = fopen($this->AFile.".tmp","w");

		$user="";
		$copy=true;

		while($handle_ini && !feof($handle_ini)) {
			$buffer = chop(fgets($handle_ini, 4096));
			/*
				If the first char is not [ and copy is forbiden
				don't copy anything
			*/
			if((substr($buffer,1)!="[") && !$copy) continue;

			/*
				Reset to normal operation
			*/
			$copy=true;

			$user = substr($buffer,1,-1);

			for($i=0; $i < count($this->Data); $i++) {
				if(!strcmp(strtolower($this->Data[$i]["NAME"]),strtolower($user))
				   && ($this->Data[$i]["DEL"] == true)) {
					$copy=false;
					$buffer="";
					continue;
				}
			}

			/*
				This line isn't blocked, so copy it
			*/
			fputs($handle_del,$buffer."\n",strlen($buffer)+1);
		}

		/*
			Close all file handles
		*/
		fflush($handle_del);
		fclose($handle_del);
		fclose($handle_ini);

		/*
			Use the sphereaccu.scp.tmp as new sphereaccu.scp
		*/

		if(!unlink($this->AFile)){
			echo("Can't remove sphereaccu.scp. Saved my version as sphereaccu.scp.tmp");
			return false;
		}
		if(!rename($this->AFile.".tmp",$this->AFile))
		{
			echo("Can't remove sphereaccu.scp. Saved my version as sphereaccu.scp.tmp");
			return false;
		}
		return true;
	}
}
?>
Return current item: PhpMySphere