<?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;
}
}
?>