<?
// --------------------------------------------------------
//
// XML Configuration Class
//
// --------------------------------------------------------
//
// Author: Kaloyan Kirilov Tzvetkov
//
// Email: hide@address.com
// hide@address.com
// hide@address.com
//
// Description:
// This class uses an XML file to build
// a data structure for keeping
// different kind of settings. The XML
// file has different element for
// various data types, which are
// validated when read or set.
//
// --------------------------------------------------------
class mrsnk_Basic {
// basic class for the application
//
var $error;
// text string contining the last error, occured
// with the config object
// function error()
// saves the last error in this->error,
// and formats it to be passed to trigger_error()
//
function error($error) {
$this->error = $error;
return "<B><I>CONFIG</I> Class Error</B>: $error";
}
}
// ----------------------------------------------
//
// ELEMENT DECLARATION
//
// ----------------------------------------------
class mrsnk_Settings extends mrsnk_Basic {
// basic class for all settings
// used for storing data from:
// <alias>,
// <password>,
// <email>,
// <value>,
// <string>,
// <url>,
// <int>,
// <boolean>,
// <float>,
// <date>
//
var $description;
//description of the setting, corresponding
//to the <description> tag
var $type;
//type of the tag
var $name;
//original name of the setting
var $Name;
//capitalized name of the setting
var $value;
//value of the setting
var $default;
// default value for the setting
// constructor mrsnk_Setting()
// parametetrs:
// TYPE of the tag - int, string, etc.
// ATTRIBUTES of the element
// PARENT of the element
//
// function mrsnk_Settings($_type, $_ATTR) {
function mrsnk_Settings($_type, $_ATTR) {
$ATTR = array();
while(list($k, $v) = each($_ATTR)) {
$_k = strToUpper($k);
switch ($_k) {
case 'NAME' :
$_name = $v;
$ATTR[] = $_k;
break;
case 'SELECTED' :
case 'VALUE' :
$_value = $v;
$ATTR[] = $_k;
break;
case 'DEFAULT' :
$_default = $v;
$ATTR[] = $_k;
break;
default :
// Error - Unrecognized attributes
trigger_error($this->error(sprintf("Unrecognized attribute [%s] for [%s=%s]",
$_type, $k, $v)));
break;
}
}
// type contraints
$_type = strToUpper($_type);
switch ($_type) {
case '~' : //unregonized attributes - there are no
//checks made for this type of elements
break;
case 'ALIAS' :
//username, variables
$CHECK = array(
'NAME',
'VALUE',
'DEFAULT'
);
//unrecognized attribute
if ($CHK = array_diff($ATTR, $CHECK)) {
trigger_error($this->error(
sprintf("Unrecognized attributes [%s] for [%s - %s]",
join(", ", $CHK), $_type, $_name)));
}
//check format
if (!eregi('^[a-z]+[a-z0-9_]+$', $_value)) {
trigger_error($this->error(
sprintf("Invalid data format for attribute %s-VALUE [%s]=[%s]",
$_type, $_name, $_value)));
}
if (!eregi('^[a-z_]+[a-z0-9_]+$', $_default)) {
trigger_error($this->error(
sprintf("Invalid data format for attribute %s-DEFAULT [%s]=[%s]",
$_type, $_name, $_default)));
}
break;
case 'PASSWORD' :
//md5 hash
$CHECK = array(
'NAME',
'VALUE',
'DEFAULT'
);
//unrecognized attribute
if ($CHK = array_diff($ATTR, $CHECK)) {
trigger_error($this->error(
sprintf("Unrecognized attributes [%s] for [%s - %s]",
join(", ", $CHK), $_type, $_name)));
}
//check format
if (!eregi('^[a-f0-9]{32}$', $_value)) {
trigger_error($this->error(
sprintf("Invalid data format for attribute %s-VALUE [%s]=[%s]",
$_type, $_name, $_value)));
}
if (!eregi('^[a-f0-9]{32}$', $_default)) {
trigger_error($this->error(
sprintf("Invalid data format for attribute %s-DEFAULT [%s]=[%s]",
$_type, $_name, $_default)));
}
break;
case 'EMAIL' :
//email address
$CHECK = array(
'NAME',
'VALUE',
'DEFAULT'
);
//unrecognized attribute
if ($CHK = array_diff($ATTR, $CHECK)) {
trigger_error($this->error(
sprintf("Unrecognized attributes [%s] for [%s - %s]",
join(", ", $CHK), $_type, $_name)));
}
//check format
if (!ereg('^[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+'. '@'. '[-!#$%&\'*+\\/0-9=?A-Z^_`a-z{|}~]+\.' . '[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+$', $_value)) {
trigger_error($this->error(
sprintf("Invalid data format for attribute %s-VALUE [%s]=[%s]",
$_type, $_name, $_value)));
}
if (!ereg('^[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+'. '@'. '[-!#$%&\'*+\\/0-9=?A-Z^_`a-z{|}~]+\.' . '[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+$', $_default)) {
trigger_error($this->error(
sprintf("Invalid data format for attribute %s-DEFAULT [%s]=[%s]",
$_type, $_name, $_default)));
}
break;
case 'VALUE' :
//options values
$CHECK = array(
'NAME',
'SELECTED',
'DEFAULT'
);
//unrecognized attribute
if ($CHK = array_diff($ATTR, $CHECK)) {
trigger_error($this->error(
sprintf("Unrecognized attributes [%s] for [%s - %s]",
join(", ", $CHK), $_type, $_name)));
}
//check format
if (!eregi('^true|false|on|off|0+|0*1$', $_value)) {
trigger_error($this->error(
sprintf("Invalid data format for attribute %s-SELECTED [%s]=[%s]",
$_type, $_name, $_value)));
} else {
$_value = (eregi('^true|on|0*1$', $_value))?'ON':'OFF';
}
if (!eregi('^true|false|on|off|0+|0*1$', $_default)) {
trigger_error($this->error(
sprintf("Invalid data format for attribute %s-DEFAULT [%s]=[%s]",
$_type, $_name, $_default)));
} else {
$_default = (eregi('^true|on|0*1$', $_default))?'ON':'OFF';
}
break;
case 'STRING' :
//string attributes
$CHECK = array(
'NAME',
'VALUE',
'DEFAULT'
);
//unrecognized attribute
if ($CHK = array_diff($ATTR, $CHECK)) {
trigger_error($this->error(
sprintf("Unrecognized attributes [%s] for [%s - %s]",
join(", ", $CHK), $_type, $_name)));
}
break;
case 'URL' :
//URLs
$CHECK = array(
'NAME',
'VALUE',
'DEFAULT'
);
//unrecognized attribute
if ($CHK = array_diff($ATTR, $CHECK)) {
trigger_error($this->error(
sprintf("Unrecognized attributes [%s] for [%s - %s]",
join(", ", $CHK), $_type, $_name)));
}
//check format
if (!preg_match('`^((http|https|ftp)://)(([a-z0-9_]+):([a-z0-9-_]*)@)?(([a-z0-9_-]+\.)*)([a-z0-9-]{3,})\.(com|net|org|edu|gov|mil|int|arpa|aero|biz|coop|info|museum|name|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cf|cd|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|fi|fj|fk|fm|fo|fr|fx|ga|gb|gd|ge|gf|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|in|io|iq|ir|is|it|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nt|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|pt|pw|py|qa|re|ro|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sy|sz|tc|td|tf|tg|th|tj|tk|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|um|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zr|zw)(:(\d+))?((/[a-z0-9-_.%~]*)*)?(\?[^? ]*)?$`iU', $_value)) {
trigger_error($this->error(
sprintf("Invalid data format for attribute %s-VALUE [%s]=[%s]",
$_type, $_name, $_value)));
}
if (!preg_match('`^((http|https|ftp)://)(([a-z0-9_]+):([a-z0-9-_]*)@)?(([a-z0-9_-]+\.)*)([a-z0-9-]{3,})\.(com|net|org|edu|gov|mil|int|arpa|aero|biz|coop|info|museum|name|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cf|cd|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|fi|fj|fk|fm|fo|fr|fx|ga|gb|gd|ge|gf|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|in|io|iq|ir|is|it|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nt|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|pt|pw|py|qa|re|ro|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sy|sz|tc|td|tf|tg|th|tj|tk|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|um|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zr|zw)(:(\d+))?((/[a-z0-9-_.%~]*)*)?(\?[^? ]*)?$`iU', $_default)) {
trigger_error($this->error(
sprintf("Invalid data format for attribute %s-DEFAULT [%s]=[%s]",
$_type, $_name, $_default)));
}
break;
case 'INT' :
//inteeger values
$CHECK = array(
'NAME',
'VALUE',
'DEFAULT'
);
//unrecognized attribute
if ($CHK = array_diff($ATTR, $CHECK)) {
trigger_error($this->error(
sprintf("Unrecognized attributes [%s] for [%s - %s]",
join(", ", $CHK), $_type, $_name)));
}
//check format
if (!ereg('^[0-9]+$', $_value)) {
trigger_error($this->error(
sprintf("Invalid data format for attribute %s-VALUE [%s]=[%s]",
$_type, $_name, $_value)));
} else {
$_value = intval($_value);
}
if (!ereg('^[0-9]+$', $_default)) {
trigger_error($this->error(
sprintf("Invalid data format for attribute %s-DEFAULT [%s]=[%s]",
$_type, $_name, $_default)));
} else {
$_default = intval($_default);
}
break;
case 'BOOLEAN' :
//boolean settings
$CHECK = array(
'NAME',
'VALUE',
'DEFAULT'
);
//unrecognized attribute
if ($CHK = array_diff($ATTR, $CHECK)) {
trigger_error($this->error(
sprintf("Unrecognized attributes [%s] for [%s - %s]",
join(", ", $CHK), $_type, $_name)));
}
//check format
if (!eregi('^true|false|on|off|0+|0*1$', $_value)) {
trigger_error($this->error(
sprintf("Invalid data format for attribute %s-VALUE [%s]=[%s]",
$_type, $_name, $_value)));
} else {
$_value = (eregi('^true|on|0*1$', $_value))?'ON':'OFF';
}
if (!eregi('^true|false|on|off|0+|0*1$', $_default)) {
trigger_error($this->error(
sprintf("Invalid data format for attribute %s-DEFAULT [%s]=[%s]",
$_type, $_name, $_default)));
} else {
$_default = (eregi('^true|on|0*1$', $_default))?'ON':'OFF';
}
break;
case 'FLOAT' :
//float values
$CHECK = array(
'NAME',
'VALUE',
'DEFAULT'
);
//unrecognized attribute
if ($CHK = array_diff($ATTR, $CHECK)) {
trigger_error($this->error(
sprintf("Unrecognized attributes [%s] for [%s - %s]",
join(", ", $CHK), $_type, $_name)));
}
//check format
if (!is_float($_value)) {
trigger_error($this->error(
sprintf("Invalid data format for attribute %s-VALUE [%s]=[%s]",
$_type, $_name, $_value)));
}
if (!is_float($_default)) {
trigger_error($this->error(
sprintf("Invalid data format for attribute %s-DEFAULT [%s]=[%s]",
$_type, $_name, $_default)));
}
break;
case 'DATE' :
//dates
$CHECK = array(
'NAME',
'VALUE',
'DEFAULT'
);
//unrecognized attribute
if ($CHK = array_diff($ATTR, $CHECK)) {
trigger_error($this->error(
sprintf("Unrecognized attributes [%s] for [%s - %s]",
join(", ", $CHK), $_type, $_name)));
}
//check format
if ($_value && (strToTime($_value) == -1)) {
trigger_error($this->error(
sprintf("Invalid data format for attribute %s-VALUE [%s]=[%s]",
$_type, $_name, $_value)));
} else {
$_value = ($_value)?date('Y-M-d H:i:s', strToTime($_value)):NULL;
}
if ($_default && (strToTime($_default) == -1)) {
trigger_error($this->error(
sprintf("Invalid data format for attribute %s-DEFAULT [%s]=[%s]",
$_type, $_name, $_default)));
} else {
$_default = ($_default)?date('Y-M-d H:i:s', strToTime($_default)):NULL;
}
break;
default : //some error
trigger_error($this->error(sprintf("Unrecognized SETTING type [%s]", $_type)));
return;
break;
}
$this->type = $_type;
$this->name = $_name;
$this->Name = strToUpper($_name);
$this->value = $_value;
$this->default = $_default;
}
}
class mrsnk_Root extends mrsnk_Basic {
// This is the root element of the XML
// configuration file - "<config>"
var $saveDate;
// "saveDate" is the date on which the config
// was was altered for the last time.
var $authorAdmin;
// "authorAdmin" is the administrator account,
// that was the last to alter the configuration
// file. This is either the master-administrator
// account from <administrationSettings>, or
// any of the application administrators.
var $authorIP;
// "authorIP" is the IP address, from which
// the configuration file was altered for the
// last time.
var $GROUPS;
// Repository for the stored groups of settings
// constructor mrsnk_Root()
// parameters:
// ATTRIBUTES - an array with the
// attributes of the <config> element
//
function mrsnk_Root($_ATTR) {
$this->GROUPS = array();
while(list($k, $v) = each($_ATTR)) {
$_k = strToUpper($k);
switch ($_k) {
case 'SAVEDATE' :
$this->saveDate = $v;
break;
case 'AUTHORADMIN' :
$this->authorAdmin = $v;
break;
case 'AUTHORIP' :
$this->authorIP = $v;
break;
default :
// Unrecognized attributes will be added
// to GROUPS as settings;
$this->GROUPS[] = new mrsnk_Settings(
'~', //type - unregocnized
array(
'name'=>$k,
'value'=>$v,
'default'=>NULL
));
break;
}
}
}
}
class mrsnk_Group extends mrsnk_Basic {
// This is for the groups tags in the configuration
// file, which are <*Settings> (
// <administrationSettings>,
// <debugSettings>,
// <fileSettings>,
// <sessionSettings>,
// <phpSettings>,
// <applicationSettings>,
// <miscellaneousSettings>,
// <customSettings>
// <databaseSettings>) and
// <group>,
// <options>,
// <session>
var $type;
//type of the group - name of the tag
var $name;
//name of the group
var $description;
//description of the group
var $SETTINGS;
// Repository for the stored settings
// constructor mrsnk_Group()
// parametetrs:
// TYPE of the tag - int, string, etc.
// ATTRIBUTES for the tag
//
function mrsnk_Group($_type, $_ATTR) {
$_Type = strToUpper($_type);
//check type constraints
switch ($_Type) {
case 'DEBUGSETTINGS' :
case 'FILESETTINGS' :
case 'SESSIONSETTINGS' :
case 'PHPSETTINGS' :
case 'APPLICATIONSETTINGS' :
case 'MISCELLANEOUSSETTINGS' :
case 'CUSTOMSETTINGS' :
case 'DATABASESETTINGS' :
case 'ADMINISTRATIONSETTINGS' :
// setting groups
$_name = $_type;
break;
case 'GROUP' :
case 'OPTIONS' :
case 'SESSION' :
//group elements
$ATTR = array();
while(list($k, $v) = each($_ATTR)) {
$_k = strToUpper($k);
switch ($_k) {
case 'NAME' :
$_name = $v;
break;
default: $ATTR[$k] = $v;
break;
}
}
$_ATTR = $ATTR;
break;
}
//create properties
$this->type = $_Type;
$this->name = $_name;
$this->SETTINGS = array();
//add attribtes
while(list($k, $v) = each($_ATTR)) {
$_k = strToUpper($k);
$this->SETTINGS[] = new mrsnk_Settings(
'~', //type - unregocnized
array(
'name' => $k,
'value' => $v,
'default' => NULL));
}
}
}
class mrsnk_Administrator extends mrsnk_Basic {
// class for master-administor(s), stored as
// <administrator> tags in the configuration
var $name;
var $Name;
//configuration name for the super-adminstrator
var $description;
//description of the group
var $lastLoginDate;
//"lastLoginDate" is the date, on which this
//master-administrator logged in for the last time.
var $lastLoginIP;
// "lastLoginIP" is the IP address, from which this
// master-administrator logged in for the last time.
var $ATTRIBUTES;
// repository for the attributes of this
// master-admin. This also can be used to add your
// custom data to the master-administrator
// accounts
// constructor mrsnk_Administrator()
// parametetrs:
// ATTRIBUTES for the administrator
//
function mrsnk_Administrator($_ATTR) {
while(list($k, $v) = each($_ATTR)) {
$_k = strToUpper($k);
switch ($_k) {
case 'NAME':
$this->name = $v;
$this->Name = strToUpper($v);
break;
case 'LASTLOGINDATE' :
$this->lastLoginDate = $v;
break;
case 'LASTLOGINIP' :
$this->lastLoginIP = $v;
break;
default :
// Unrecognized attributes will be added
// to GROUPS as settings;
$this->ATTRIBUTES[] = new mrsnk_Settings(
'~', //type - unregocnized
$k, //name
$v, //value
NULL, //default
NULL //description
);
break;
}
}
}
}
class mrsnk_Directory extends mrsnk_Settings {
// this class is for the <directory> tags
var $type = 'DIRECTORY';
var $permissions;
// this is the file premissions of that directory (or file,
// because mrsnk_File class extends this one). This
// attribute is used when the application is installed,
// and all the neceseary directories and files are
// created.
// constructor mrsnk_Directory()
// parametetrs:
// ATTRIBUTES for the tag
//
function mrsnk_Directory($_ATTR) {
while(list($k, $v) = each($_ATTR)) {
$_k = strToUpper($k);
switch ($_k) {
case 'NAME' :
$_name = $v;
break;
case 'VALUE' :
$_value = $v;
break;
case 'DEFAULT' :
$_default = $v;
break;
case 'PERMISSIONS' :
$_permissions = $v;
break;
default :
// Error - Unrecognized attributes
trigger_error($this->error(
sprintf("Unrecognized attribute for DIRECTORY [%s=%s]",
$k, $v)));
break;
}
}
//check format
if (!eregi("^[^ ?*]+$", $_value)) {
trigger_error($this->error(sprintf("Wrong format for DIRECTORY-VALUE [%s]",
$_value)));
}
if (!eregi("^[^ ?*]+$", $_default)) {
trigger_error($this->error(sprintf("Wrong format for DIRECTORY-DEFAULT [%s]",
$_default)));
}
//check permissions
if (!ereg('^0?[0-7]{3}$', $_permissions)) {
trigger_error($this->error(sprintf("Wrong format for DIRECTORY-PERMISSIONS [%s]",
$_permissions)));
}
//fix directory w/o trailing slash
$_value .= (!ereg('/$', $_value))?'/':'';
$_default .= (!ereg('/$', $_default))?'/':'';
//initialize
$this->name = $_name;
$this->Name = strToUpper($_name);
$this->value = $_value;
$this->default = $_default;
$this->permissions = $_permissions;
}
}
class mrsnk_File extends mrsnk_Directory {
// class, coressponding to the <file> tag
var $type = 'FILE';
// constructor mrsnk_File()
// parametetrs:
// ATTRIBUTES for the tag
//
function mrsnk_File($_ATTR) {
while(list($k, $v) = each($_ATTR)) {
$_k = strToUpper($k);
switch ($_k) {
case 'NAME' :
$_name = $v;
break;
case 'VALUE' :
$_value = $v;
break;
case 'DEFAULT' :
$_default = $v;
break;
case 'PERMISSIONS' :
$_permissions = $v;
break;
default :
// Error - Unrecognized attributes
trigger_error($this->error(
sprintf("Unrecognized attribute for FILE [%s=%s]",
$k, $v)));
break;
}
}
//check format
if (!eregi("^[^ ?*]+$", $_value)) {
trigger_error($this->error(sprintf("Wrong format for FILE-VALUE [%s]",
$_value)));
}
if (!eregi("^[^ ?*]+$", $_default)) {
trigger_error($this->error(sprintf("Wrong format for FILE-DEFAULT [%s]",
$_default)));
}
//check permissions
if (!ereg('^0?[0-7]{3}$', $_permissions)) {
trigger_error($this->error(sprintf("Wrong format for FILE-PERMISSIONS [%s]",
$_permissions)));
}
//initialize
$this->name = $_name;
$this->Name = strToUpper($_name);
$this->value = $_value;
$this->default = $_default;
$this->permissions = $_permissions;
}
}
// ----------------------------------------------
//
// CONFIG CLASS DECLARATION
//
// ----------------------------------------------
class Config extends mrsnk_Basic{
var $path;
// this is the path to the config.xml
var $default_path = 'config.xml';
//default path to the config file
var $CONFIG;
// repository for the settings, extracted
// from config.xml
var $data;
// contents of the XML file
var $STACK;
// stack for parsing XML file
// constructor Config()
// paremeters:
// path - where the config.xml is stored. If none,
// current folder is searched for 'config.xml' file
//
function Config() {
//check for path
if ($this->path = @func_get_arg(0)) {
if (!file_exists($this->path)) {
trigger_error($this->error(sprintf("XML Configuration file [%s] not found",
$this->path)));
return;
}
} else {
//path not present, use default_path
unset($this->path);
if (!file_exists($this->default_path)) {
trigger_error($this->error(sprintf("XML Configuration file [%s] not found",
$this->default_path)));
return;
}
$this->path = $this->default_path;
}
//load the config.xml
$this->load();
}
// function load()
// loads the contents of the config.xml
//
function load() {
if (!file_exists($this->path)) {
trigger_error($this->error(sprintf("XML Configuration file [%s] not found ",$this->path)));
return;
}
if (!$file = @file($this->path)) {
trigger_error($this->error(sprintf("XML Configuration file [%s] is empty or can not be read ",
$this->path)));
return;
}
$file = join('' , $file);
$this->data = $file;
$this->parse();
}
// function lastStack()
// returns reference to
// the last element in STACK
//
function &lastStack() {
return @$this->STACK[@count($this->STACK)-1];
}
//start-element function
function _start($_xml, $_name, $_attr) {
$_Name = strToUpper($_name);
switch ($_Name) {
case 'CONFIG' :
// The root element for the configuration file.
$this->CONFIG = new mrsnk_Root($_attr);
$this->STACK[] = &$this->CONFIG;
break;
case 'ADMINISTRATIONSETTINGS' :
case 'DEBUGSETTINGS' :
case 'FILESETTINGS' :
case 'SESSIONSETTINGS' :
case 'PHPSETTINGS' :
case 'APPLICATIONSETTINGS' :
case 'MISCELLANEOUSSETTINGS' :
case 'CUSTOMSETTINGS' :
case 'DATABASESETTINGS' :
//settings groups
// find where to add it
$_last = &$this->lastStack();
if (get_class($_last) != 'mrsnk_root') {
//parent element has to be the root element
trigger_error($this->error(
sprintf("Parent element is not <config> for element [%s] ",
$_name)));
} else {
$parent = &$_last->GROUPS;
}
// there can be only element of this type
if (in_array($_Name, $parent)) {
//duplicate settings-group element
trigger_error($this->error(
sprintf("There can be only element of type [%s] ",
$_name)));
}
//add it
$parent[] = new mrsnk_Group($_name, $_attr);
$this->STACK[] = &$parent[count($parent)-1];
break;
case 'GROUP' :
case 'OPTIONS' :
case 'SESSION' :
//special group elements
// find where to add it
$_last = &$this->lastStack();
if (!in_array(get_class($_last), array(
'mrsnk_administrator',
'mrsnk_group'
))) {
//parent element has to be group element
trigger_error($this->error(sprintf("Parent element is not a group-type for element [%s] ",
$_name)));
} else {
switch (get_class($_last)) {
case 'mrsnk_administrator':
$parent = &$_last->ATTRIBUTES;
break;
case 'mrsnk_group':
$parent = &$_last->SETTINGS;
break;
}
}
//add it
$parent[] = new mrsnk_Group($_name, $_attr);
$this->STACK[] = &$parent[count($parent)-1];
break;
case 'ADMINISTRATOR' :
//master-administrator
// find where to add it
$_last = &$this->lastStack();
if ((get_class($_last) != 'mrsnk_group')
|| ($_last->type != 'ADMINISTRATIONSETTINGS')) {
//parent element has to be the admin-settings element
trigger_error($this->error(sprintf("Parent element is not <adminSettings> for element [%s] ",
$_name)));
} else {
$parent = &$_last->SETTINGS;
}
//add it
$parent[] = new mrsnk_Administrator($_attr);
$this->STACK[] = &$parent[count($parent)-1];
break;
case 'DESCRIPTION' :
//element description
$_last = &$this->lastStack();
$VARS = array_keys(get_class_vars(get_class($_last)));
if (in_array('description', $VARS)) {
$this->STACK[] = &$_last->description;
} else {
trigger_error($this->error(sprintf("Description not allowed in tag [%s] ",
get_class($_last))));
}
break;
case 'VALUE':
//option values
// find where to add it
$_last = &$this->lastStack();
if ((get_class($_last) != 'mrsnk_group') ||
($_last->type != 'OPTIONS')) {
//parent element has to be OPTIONS element
trigger_error($this->error(sprintf("Parent element is not OPTIONS for element [%s] [%s]",
$_name,
get_class($_last))));
} else {
$parent = &$_last->SETTINGS;
}
//add it
$parent[] = new mrsnk_Settings($_name, $_attr);
$this->STACK[] = &$parent[count($parent)-1];
//$this->STACK[] = &$parent[count($parent)-1]->name;
break;
case 'ALIAS':
case 'PASSWORD':
case 'EMAIL':
case 'STRING':
case 'URL':
case 'INT':
case 'BOOLEAN':
case 'FLOAT':
case 'DATE' :
//settings elements
// find where to add it
$_last = &$this->lastStack();
if (!in_array(get_class($_last), array(
'mrsnk_administrator',
'mrsnk_group'
))) {
//parent element has to be the group element
trigger_error($this->error(sprintf("Parent element is not a group-type for element [%s] [%s]",
$_name,
get_class($_last))));
} else {
switch (get_class($_last)) {
case 'mrsnk_administrator':
$parent = &$_last->ATTRIBUTES;
break;
case 'mrsnk_group':
$parent = &$_last->SETTINGS;
break;
}
}
//add it
$parent[] = new mrsnk_Settings($_name, $_attr);
$this->STACK[] = &$parent[count($parent)-1];
break;
case 'DIRECTORY' :
//settings for directories
// find where to add it
$_last = &$this->lastStack();
if (get_class($_last) != 'mrsnk_group') {
//parent element has to be the group element
trigger_error($this->error(sprintf("Parent element is not a group-type for element [%s] [%s]",
$_name,
get_class($_last))));
} else {
$parent = &$_last->SETTINGS;
}
//add it
$parent[] = new mrsnk_Directory($_attr);
$this->STACK[] = &$parent[count($parent)-1];
break;
case 'FILE' :
//settings for files
// find where to add it
$_last = &$this->lastStack();
if (get_class($_last) != 'mrsnk_group') {
//parent element has to be the group element
trigger_error($this->error(sprintf("Parent element is not a group-type for element [%s] [%s]",
$_name,
get_class($_last))));
} else {
$parent = &$_last->SETTINGS;
}
//add it
$parent[] = new mrsnk_File($_attr);
$this->STACK[] = &$parent[count($parent)-1];
break;
default : //there isn't such a tag
trigger_error($this->error(sprintf("Unrecognized tag [%s] ", $_name)));
break;
}
}
//end-element function
function _end($_xml, $_name) {
$this->STACK = array_slice($this->STACK, 0, count($this->STACK)-1);
if (empty($this->STACK)) {
$this->STACK = NULL;
}
}
//CDTATA function
function _CData($_xml, $cdata) {
$_last = &$this->lastStack();
if ($_class = get_class($_last)) {
switch ($_class) {
case 'mrsnk_settings' :
if ($_last->type == 'VALUE'){
$_last->name .= $cdata;
$_last->Name = strToUpper($_last->name);
} else {
if (trim($cdata)) {
trigger_error($this->error(sprintf("Data between tags is not supported for [%s]",
$_class)));
}
}
break;
default : //error
if (trim($cdata)) {
trigger_error($this->error(sprintf("Data between tags is not supported for [%s]",
$_class)));
}
break;
}
} else {
$_last .= $cdata;
}
}
// parses the contents of the config.xml
function parse() {
//create parser
$_xml = xml_parser_create();
// parser settings
xml_set_object($_xml, $this);
xml_parser_set_option($_xml, XML_OPTION_CASE_FOLDING, 0);
xml_set_element_handler($_xml, "_start", "_end");
xml_set_character_data_handler($_xml, "_CData");
if (!xml_parse($_xml, $this->data, TRUE)) {
trigger_error($this->error(sprintf("XML parse error [%s] at line [%d] ",
xml_error_string(xml_get_error_code($_xml)),
xml_get_current_line_number($_xml))));
}
//release parser
xml_parser_free($_xml);
}
// returns object from configuration
// parameters:
// PATH is where the setting is located
// in the Configuration, visualized using
// array with all the elements.
//
function &Find($_path){
//translate the path
$SECTIONS = array();
while (list(,$v)=each($_path)) {
$SECTIONS[] = array(
name=>$v,
Name=>trim(strToUpper($v))
);
}
// load default data for explore cell
$explore = &$this->CONFIG->GROUPS;
reset($explore);
$level = 0;
//explore all the elements
while(list($k, $v) = each($explore)) {
$start = $level;
//getelement by class_name
switch (get_class($v)) {
case 'mrsnk_administrator' :
if (@in_array($v->name, $SECTIONS[$start])
|| @in_array($v->Name, $SECTIONS[$start])) {
$explore = &$explore[$k]->ATTRIBUTES;
$level++;
reset($explore);
}
break;
case 'mrsnk_group' :
if (($v->type == 'OPTIONS')
&& (@in_array($v->name, $SECTIONS[$start])
||@in_array($v->Name, $SECTIONS[$start])
)) {
//there are no more elements left.
//this means that the element we
//searched for is found, and it is
//an OPTIONS element
if (++$start == count($SECTIONS)) {
return $explore[$k]->SETTINGS;
} else {
//this is not the last element,
//which means that the path
//is invalid, or there's a reference
//to an exact element of the options
$explore = &$explore[$k]->SETTINGS;
$level++;
reset($explore);
}
} else {
//other than OPTIONS
if (@in_array($v->name, $SECTIONS[$start])
|| @in_array($v->type, $SECTIONS[$start])) {
$explore = &$explore[$k]->SETTINGS;
$level++;
reset($explore);
}
}
break;
case 'mrsnk_directory' :
case 'mrsnk_file' :
case 'mrsnk_settings' :
if (@in_array(trim($v->name), $SECTIONS[$start])
|| @in_array(trim($v->Name), $SECTIONS[$start])) {
//there are no more elements left.
//this means that the element we
//searched for is found
if (++$start == count($SECTIONS)) {
return $explore[$k];
} else {
//this is not the last element,
//which means that the path
//is invalid
trigger_error($this->error(sprintf("Configuration element
path [%s] is invalid",
join(".", $_path))));
}
}
break;
default : //error
trigger_error($this->error(sprintf("Unknown class [%s]", get_class($v))));
return;
break;
}
//make another loop
if ($level > $start) {
continue;
}
}
//element isn't found
trigger_error($this->error(sprintf("Configuration element [%s] not found", join(".", $_path))));
}
// returns object from configuration
// parameters:
// PATH is where the setting is located
// in the Configuration, visualized using
// array with all the elements.
//
function Get(){
$_path = array();
for ($i=0; $i<func_num_args(); $i++) {
$_path[] = func_get_arg($i);
}
$_rslt = $this->Find($_path);
switch (gettype($_rslt)) {
case 'array' :
$_RSLT = array();
reset($_rslt);
while(list($k, $v) = each($_rslt)) {
$_RSLT[trim($v->name)]=$v->value;
}
return $_RSLT;
break;
default :
return $_rslt->value;
break;
}
}
// sets value for an object from configuration
// parameters:
// VALUE is the value to be set
// PATH is where the setting is located
// in the Configuration, visualized using
// array with all the elements.
//
function Set(){
// first parameter is the value
$_value = func_get_arg(0);
//the rest are for the path
$_path = array();
for ($i=1; $i<func_num_args(); $i++) {
$_path[] = func_get_arg($i);
}
// element isn't found
if (!$_rslt = &$this->Find($_path)) {
return FALSE;
}
$_type = $_rslt->type;
$_name = join("." , $_path);
switch ($_type) {
case 'ALIAS':
if (!eregi('^[a-z]+[a-z0-9_]+$', $_value)) {
trigger_error($this->error(
sprintf("Invalid data format for attribute %s-VALUE [%s]=[%s]",
$_type, $_name, $_value)));
}
$_rslt->value = $_value;
break;
case 'PASSWORD':
if (!eregi('^[a-f0-9]{32}$', $_value)) {
trigger_error($this->error(
sprintf("Invalid data format for attribute %s-VALUE [%s]=[%s]",
$_type, $_name, $_value)));
}
$_rslt->value = $_value;
break;
case 'EMAIL' :
if ($_value && !ereg('^[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+'. '@'. '[-!#$%&\'*+\\/0-9=?A-Z^_`a-z{|}~]+\.' . '[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+$', $_value)) {
trigger_error($this->error(
sprintf("Invalid data format for attribute %s-VALUE [%s]=[%s]",
$_type, $_name, $_value)));
}
$_rslt->value = $_value;
break;
case 'VALUE' :
if (!eregi('^true|false|on|off|0+|0*1$', $_value)) {
trigger_error($this->error(
sprintf("Invalid data format for attribute %s-SELECTED [%s]=[%s]",
$_type, $_name, $_value)));
} else {
$_rslt->value = (eregi('^true|on|0*1$', $_value))?'ON':'OFF';
}
break;
case 'URL' :
if ($_value && !preg_match('`^((http|https|ftp)://)(([a-z0-9_]+):([a-z0-9-_]*)@)?(([a-z0-9_-]+\.)*)([a-z0-9-]{3,})\.(com|net|org|edu|gov|mil|int|arpa|aero|biz|coop|info|museum|name|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cf|cd|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|fi|fj|fk|fm|fo|fr|fx|ga|gb|gd|ge|gf|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|in|io|iq|ir|is|it|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nt|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|pt|pw|py|qa|re|ro|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sy|sz|tc|td|tf|tg|th|tj|tk|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|um|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zr|zw)(:(\d+))?((/[a-z0-9-_.%~]*)*)?(\?[^? ]*)?$`iU', $_value)) {
trigger_error($this->error(
sprintf("Invalid data format for attribute %s-VALUE [%s]=[%s]",
$_type, $_name, $_value)));
}
$_rslt->value = $_value;
break;
case 'INT' :
if (!ereg('^[0-9]+$', $_value)) {
trigger_error($this->error(
sprintf("Invalid data format for attribute %s-VALUE [%s]=[%s]",
$_type, $_name, $_value)));
} else {
$_rslt->value = intval($_value);
}
break;
case 'BOOLEAN' :
if (!eregi('^true|false|on|off|0+|0*1$', $_value)) {
trigger_error($this->error(
sprintf("Invalid data format for attribute %s-VALUE [%s]=[%s]",
$_type, $_name, $_value)));
} else {
$_rslt->value = (eregi('^true|on|0*1$', $_value))?'ON':'OFF';
}
break;
case 'FLOAT' :
if (!is_float($_value)) {
trigger_error($this->error(
sprintf("Invalid data format for attribute %s-VALUE [%s]=[%s]",
$_type, $_name, $_value)));
}
$_rslt->value = $_value;
break;
case 'DATE' :
if ($_value && (strToTime($_value) == -1)) {
trigger_error($this->error(
sprintf("Invalid data format for attribute %s-VALUE [%s]=[%s]",
$_type, $_name, $_value)));
} else {
$_rslt->value = ($_value)?date('Y-M-d H:i:s', strToTime($_value)):NULL;
}
break;
case 'STRING' :
default :
if (ereg('["<>]', $_value)) {
$_rslt->value = htmlSpecialChars($_value);
} else {
$_rslt->value = $_value;
}
break;
}
return TRUE;
}
// returns object with all its details
// and attributes from
// configuration
//
// parameters:
// PATH is where the setting is located
// in the Configuration, visualized using
// array with all the elements.
//
function Details(){
$_path = array();
for ($i=0; $i<func_num_args(); $i++) {
$_path[] = func_get_arg($i);
}
return $this->Find($_path);
}
//saves the configration structure to the
// configuration XML file, appling
// the differences.
//
// parameters:
// ACCOUNT is the alias for the
// user, or administration account,
// that saves the new configuration
//
function Save($_account){
// save the author
$this->CONFIG->authorAdmin = $_account;
// check for the original XML file and
// then create a backup copy with
// the old configurtions
$_original = $this->path."~ORIGINAL";
$_backup = $this->path."~BACKUP".date("-Ymd_His");
if (file_exists($_original)) {
// make a backup copy
if ($fp = fopen($_backup, 'w')) {
fwrite($fp, $this->data);
fclose($fp);
}
} else {
// create the original
if ($fp = fopen($_original, 'w')) {
fwrite($fp, $this->data);
fclose($fp);
}
}
// write the new settings
$_write = "<?xml version=\"1.0\"?>\n";
// recursively searches through the
// object, and returns its contents
//
function _write(&$__p, $__t=0) {
// indent
$__i = str_repeat("\t", $__t++);
//description
if ($__p->description) {
$__p->description = wordwrap(
ereg_replace("[[:space:]]+", ' ', $__p->description),
30 + (4 - $__t)*3,
"\n$__i\t\t");
}
switch (get_class($__p)) {
case 'mrsnk_root' :
for ($i=0; $i<count($__p->GROUPS); $i++) {
$__r .= _write(&$__p->GROUPS[$i], $__t);
}
//get the remote IP
if (!$_ip = $_SERVER[REMOTE_ADDR]) {
global $HTTP_SERVER_VARS;
$_ip = $HTTP_SERVER_VARS[REMOTE_ADDR];
}
return "<config"
.sprintf(" saveDate=\"%s\"",
date("Y-m-d H:i:s"))
.sprintf("\n\t authorAdmin=\"%s\"",
htmlSpecialChars($__p->authorAdmin))
.sprintf("\n\t authorIP=\"%s\"",
$_ip)
.">"
.$__r
."</config>";
break;
case 'mrsnk_group':
for ($i=0; $i<count($__p->SETTINGS); $i++) {
$__r .= _write(&$__p->SETTINGS[$i], $__t);
}
switch ($__p->type) {
case 'SESSION' :
return "\n$__i<session"
.sprintf(" name=\"%s\"",
$__p->name)
.">"
.((!$__p->description)?"\n" :
"\n$__i\t<description>"
.sprintf("%s</description>\n\t",
htmlSpecialChars(
$__p->description)))
.$__r
."\n$__i</session>\n";
break;
case 'OPTIONS' :
return "\n$__i<options"
.sprintf(" name=\"%s\"",
$__p->name)
.">"
.((!$__p->description)?"\n" :
"\n$__i\t<description>"
.sprintf("%s</description>\n",
htmlSpecialChars(
$__p->description)))
.$__r
."\n$__i</options>\n";
break;
case 'GROUP' :
return "\n$__i<group"
.sprintf(" name=\"%s\"",
$__p->name)
.">"
.((!$__p->description)?"\n" :
"\n$__i\t<description>"
.sprintf("%s</description>\n",
htmlSpecialChars(
$__p->description)))
.$__r
."\n$__i</group>";
break;
case 'ADMINISTRATIONSETTINGS':
case 'APPLICATIONSETTINGS':
case 'PHPSETTINGS':
case 'SESSIONSETTINGS':
case 'FILESETTINGS':
case 'DEBUGSETTINGS':
case 'MISCELLANEOUSSETTINGS':
case 'CUSTOMSETTINGS':
case 'DATABASESETTINGS':
return "\n$__i<$__p->name>"
.((!$__p->description)?"\n" :
"\n$__i\t<description>"
.sprintf("%s</description>\n\t",
htmlSpecialChars(
$__p->description)))
.$__r
."\n$__i</$__p->name>\n";
break;
}
break;
case 'mrsnk_administrator':
for ($i=0; $i<count($__p->ATTRIBUTES); $i++) {
$__r .= _write(&$__p->ATTRIBUTES[$i], $__t);
}
return "\n$__i<administrator"
.sprintf("\n$__i\tname=\"%s\"",
$__p->name)
.sprintf("\n$__i\tlastLoginDate=\"%s\"",
$__p->lastLoginDate)
.sprintf("\n$__i\tlastLoginIP=\"%s\"",
$__p->lastLoginIP)
.">"
.((!$__p->description)?'' :
"\n$__i\t<description>"
.sprintf("%s</description>\n",
htmlSpecialChars(
$__p->description)))
.$__r
."\n$__i</administrator>\n";
;
break;
case 'mrsnk_settings' :
switch ($__p->type) {
case 'ALIAS' :
case 'PASSWORD':
case 'EMAIL':
case 'STRING':
case 'URL':
case 'BOOLEAN':
case 'INT':
case 'FLOAT':
case 'DATE':
return "\n$__i<"
.strToLower($__p->type)
.sprintf(" name=\"%s\"",
$__p->name)
.sprintf("\n$__i\tvalue=\"%s\"",
$__p->value)
.sprintf("\n$__i\tdefault=\"%s\"",
$__p->default)
.">"
.((!$__p->description)?'' :
"\n$__i\t<description>"
.sprintf("%s</description>",
htmlSpecialChars(
$__p->description)))
."\n$__i</"
.strToLower($__p->type)
.">\n";
break;
case 'VALUE':
return "\n$__i<value"
.sprintf(" selected=\"%s\"",
$__p->value)
.sprintf(" default=\"%s\"",
$__p->default)
.">"
.((!$__p->description)?'' :
"\n$__i\t<description>"
.sprintf("%s</description>",
htmlSpecialChars(
$__p->description)))
."\n$__i\t"
.trim($__p->name)
."</value>\n";
break;
}
break;
case 'mrsnk_file' :
case 'mrsnk_directory' :
return "\n$__i<"
.strToLower($__p->type)
.sprintf(" name=\"%s\"",
$__p->name)
.sprintf("\n$__i\tvalue=\"%s\"",
$__p->value)
.sprintf("\n$__i\tdefault=\"%s\"",
$__p->default)
.sprintf("\n$__i\tpermissions=\"%s\"",
$__p->permissions)
.">"
.((!$__p->description)?'' :
"\n$__i\t<description>"
.sprintf("%s</description>",
htmlSpecialChars(
$__p->description)))
."\n$__i</"
.strToLower($__p->type)
.">\n";
break;
}
}
$_write .= _write(&$this->CONFIG);
$_write = str_replace("\n", "\r\n", $_write);
if ($fp = fopen($this->path, 'w')) {
fwrite($fp, $_write);
fclose($fp);
}
}
}
?>