<?php
/* vim: set ai tabstop=4: */
// $Date: 2002/04/09 01:29:38 $
// $Revision: 1.4 $
// +----------------------------------------------------------------------+
// | CONFIG MANAGER 0.1.2 - 09-Apr-2002 |
// +----------------------------------------------------------------------+
// | Author: Keyvan Minoukadeh - keyvan@k1m.com - http://www.k1m.com |
// +----------------------------------------------------------------------+
// | PHP class for managing plain text config files. |
// +----------------------------------------------------------------------+
// | 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. |
// | |
// | This program is distributed in the hope that it will be useful, |
// | but WITHOUT ANY WARRANTY; without even the implied warranty of |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// | GNU General Public License for more details. |
// +----------------------------------------------------------------------+
// define some type constants
define('CONFIGMAN_TYPE_DOUBLE', 'double');
define('CONFIGMAN_TYPE_INTEGER', 'integer');
define('CONFIGMAN_TYPE_STRING', 'string');
define('CONFIGMAN_TYPE_BOOLEAN', 'boolean');
// fetch mode
define('CONFIGMAN_FETCH_ASSOC', 1);
define('CONFIGMAN_FETCH_OBJECT', 2);
/**
* Config manager base class
*
* This is the config manager base class, extensions include:
* - config_reader: Read config files
* - config_writer: Write config files
* - config_webedit: Modify config files through a HTML form
*
* @author Keyvan Minoukadeh <keyvan@k1m.com>
* @version 0.1.2
*/
class config_base
{
/**
* config file
*/
var $config = '';
/**
* config cache directory
*
* Make sure this directory is writable, so the script can save serialized version
* of the config. Leave blank if you'd like the script to attempt to write the
* serialized version to the same location as $this->config
* NOTE: including trailing slash if specifying a directory
*/
var $config_cache_dir = '';
/**
* comment string
*/
var $comment = '#';
/**
* separator used to separate variable names and values
*/
var $separator = '=';
/**
* parameters array
* $array["var"]["section"]["value"] = val
* $array["var"]["section"]["comment"] = comment
*/
var $param = array();
/**
* default section name
*/
var $default_section = 'Main';
/**
* regular expression for valid var name
*/
var $regex_var = '[a-zA-Z_][a-zA-Z0-9_]*';
/**
* regular expression for valid section tag name
*/
var $regex_section = '[a-zA-Z0-9_][a-zA-Z0-9_ ]*';
/**
* regular expression for valid array key name
*/
var $regex_assoc = '[a-zA-Z0-9_]+';
/**
* regular expression for valid type prefix
*/
var $regex_type = '(str_|int_|dbl_|bool_)';
/**
* max config file size (bytes)
*/
var $max_config_size = 50000;
/**
* type prefixes
*/
var $type_prefix = array('str_' => CONFIGMAN_TYPE_STRING,
'int_' => CONFIGMAN_TYPE_INTEGER,
'dbl_' => CONFIGMAN_TYPE_DOUBLE,
'bool_' => CONFIGMAN_TYPE_BOOLEAN);
/**
* default type
*
* auto: determine based on quotes around value or no quotes
* CONFIGMAN_TYPE_STRING: string
* CONFIGMAN_TYPE_INTEGER: integer
* CONFIGMAN_TYPE_DOUBLE: double
* CONFIGMAN_TYPE_BOOLEAN: boolean
*/
var $default_type = 'auto';
/**
* magic_quotes_runtime setting
*
* @access private
*/
var $_magic_quotes_runtime = null;
/**
* debug
*/
var $debug = false;
/////////////
// methods
/////////////
/**
* Constructor
*
* @param string $config config file to use
*/
function config_base($config)
{
$this->config = trim($config);
}
/**
* Strip Slashes
* Strips slashes only if magic_quotes_gpc is on
*
* @param mixed $subject array or string to strip slashes from (passed by ref)
* @return bool true
*/
function strip_magic_slashes(&$subject) {
if ((int)ini_get('magic_quotes_gpc') === 1) {
if (is_string($subject)) {
$subject = stripslashes($subject);
} elseif (is_array($subject)) {
foreach ($subject as $key => $val) {
$this->strip_magic_slashes($subject[$key]);
}
}
}
return true;
}
/**
* Toggle magic_quotes_runtime
*
* If you have magic_quotes_runtime on, call this before any other config function:
* $reader->magic_quotes_runtime();
* to revert back to the previous setting when you've finished with config manager:
* $reader->magic_quotes_runtime(true);
*
* @param bool $action true: restore previous magic quotes runtime setting, false: off
* @return bool true
* @access public
*/
function magic_quotes_runtime($action=false) {
// if first time calling, set current magic quotes runtime setting
if (is_null($this->_magic_quotes_runtime)) {
$this->_magic_quotes_runtime = ini_get('magic_quotes_runtime');
}
if (($action === false) && ((int)ini_get('magic_quotes_runtime') === 1)) {
ini_set('magic_quotes_runtime', '0');
} elseif (($action === true) && (!is_null($this->_magic_quotes_runtime))) {
ini_set('magic_quotes_runtime', $this->_magic_quotes_runtime);
}
return true;
}
/**
* Set
*
* Set class variable value, not config variable (use set_param for that)
*
* @param string $var variable to update
* @param mixed $val value to assign to $var
* @return bool true on success, false otherwise
* @access public
*/
function set($var, $val)
{
if (isset($this->$var)) {
$this->$var = $val;
return true;
} else {
return false;
}
}
/**
* Get
*
* Get class variable value, not config variable
*
* @param string $var variable to update
* @return mixed value, or false if $var does not exist
* @access public
*/
function get($var)
{
if (isset($this->$var)) {
return $this->$var;
} else {
return false;
}
}
/**
* Set param from array
*
* @param string $var var name
* @param array $param array holding parameter details
* @return bool result of calling $this->set_param()
* @access public
*/
function set_param_from_array($var, $param)
{
$func_name = 'set_param_from_array';
$section = key($param);
$val = $param[$section]['value'];
$comment = $param[$section]['comment'];
return $this->set_param($var, $val, $comment, $section);
}
/**
* Var exists
*
* @param string $var variable name to check for
* @param string $section section name (default: null - all sections)
* @return bool true if exists, false otherwise
* @access public
*/
function var_exists($var, $section=null)
{
if (is_null($section)) {
if (isset($this->param["$var"]) && is_array($this->param["$var"])) {
return true;
} else {
return false;
}
} else {
if (isset($this->param["$var"]) && isset($this->param["$var"]["$section"])) {
return true;
} else {
return false;
}
}
}
/**
* Delete param
*
* @param string $var variable name to delete
* @return bool true if deleted, false otherwise
* @access public
*/
function del_param($var)
{
if (isset($this->param["$var"])) {
unset($this->param["$var"]);
return true;
} else {
return false;
}
}
/**
* Clear param
*
* @access public
*/
function clear_param()
{
$this->param = array();
return true;
}
/**
* Set param
*
* @param string $var var
* @param string $val value
* @param string $comment comment
* @param string $section section name
* @return bool true if success, false otherwise
* @access public
*/
function set_param($var, $val, $comment=null, $section=null)
{
$func_name = 'set_param';
if (empty($var)) {
if ($this->debug) $this->_debug("$func_name: Var not specified");
return false;
}
if (is_null($comment)) {
$comment = '';
}
if ($this->default_type != 'auto') {
$type = $this->default_type;
} else {
$type = $this->_get_type($var);
}
if (is_null($section)) {
$section = $this->default_section;
}
// check for valid section name
if (!preg_match('!^'.$this->regex_section.'$!', $section)) {
if ($this->debug) $this->_debug("$func_name: Invalid section name");
return false;
}
// check for valid var name
if (!preg_match('!^'.$this->regex_var.'$!', $var)) {
if ($this->debug) $this->_debug("$func_name: Invalid var name");
return false;
}
// add/update var only if it doesn't already exist OR exists in this section
if (!$this->var_exists($var) || $this->var_exists($var, $section)) {
$this->param["$var"]["$section"]['value'] = $val;
$this->param["$var"]["$section"]['comment'] = trim($comment);
} else {
if ($this->debug) $this->_debug("$func_name: Var '$var' already exists in another section");
return false;
}
return true;
}
/**
* Is file valid
*
* Checks to see if config exists, is readable and not above the filesize limit
*
* @param string $config filename, null: use existing (default: null)
* @return bool
* @access public
*/
function is_file_valid($config=null)
{
$func_name = 'is_file_valid';
if (is_null($config)) {
$config = $this->config;
}
if (!empty($config) && file_exists($config) && is_readable($config)) {
if (filesize($config) > $this->max_config_size) {
if ($this->debug) $this->_debug("$func_name: Config file size is greater than max allowed");
return false;
} else {
return true;
}
}
return false;
}
/**
* Is valid
*
* Checks to see if config is valid
*
* @param array $config array containing each line of config file
* @param bool $return_line_numbers if true will return an array with line numbers which
* contain invalid syntax, if false, will return either
* true (if no problems encountered) or false (default: false)
* @return mixed either bool or array, based on $return_line_numbers
* @access public
*/
function is_valid($config=null, $return_line_numbers=false)
{
$func_name = 'is_valid';
$invalid = array();
if (is_null($config) && $this->is_file_valid()) {
$config = file($this->config);
}
if (!is_array($config)) {
if ($this->debug) $this->_debug("$func_name: Config file not found or not readable or not passed as array");
return false;
}
foreach ($config as $num => $line) {
$line = trim($line);
if (empty($line)) {
continue;
}
// increment $num (array stars at 0)
$num++;
// match comment
if (preg_match('!^'.preg_quote($this->comment).'!', $line)) {
continue;
}
// match var name and val
if (preg_match('!^'.$this->regex_type.'?('.$this->regex_var.')(\.'.$this->regex_assoc.')?\s*'.
preg_quote($this->separator).'\s*(?'.'>(["\'])?)(.*)(?(4)\4)$!i', $line)) {
continue;
}
// match section
if (preg_match('!^\['.$this->regex_section.'\]!', $line)) {
continue;
}
// if it's reached this far, this line is unrecongised
if ($return_line_numbers) {
$invalid[] = $num;
} else {
return false;
}
}
if ($return_line_numbers && (count($invalid) > 0)) {
return $invalid;
} else {
return true;
}
}
///////////////////////
// PRIVATE FUNCTIONS //
///////////////////////
/**
* Debug
*
* Adds debug line to array and echos it if allowed
*
* @param string $msg string to echo or store in debug log
* @access private
*/
function _debug($msg)
{
if ($this->debug) {
echo "# $msg<br>\n";
}
return true;
}
/**
* Error
*
* Outputs error message
*
* @param string $msg string to output
* @access private
*/
function _error($msg)
{
die("\n<br /><b>Error:</b> $msg\n");
}
/**
* Get type
*
* @param mixed $var variable to return type
* @access private
*/
function _get_type($var)
{
switch(gettype($var)) {
case 'boolean':
return CONFIGMAN_TYPE_BOOLEAN;
break;
case 'integer':
return CONFIGMAN_TYPE_INTEGER;
break;
case 'double':
return CONFIGMAN_TYPE_DOUBLE;
break;
case 'string':
return CONFIGMAN_TYPE_STRING;
break;
default:
return (($this->default_type != 'auto') ? $this->default_type : CONFIGMAN_TYPE_STRING);
}
}
/**
* Cast type
*
* @param string $val value to return
* @param string $type type
* @access private
*/
function _cast_type($val, $type)
{
switch($type) {
case CONFIGMAN_TYPE_BOOLEAN:
if (in_array($val, array('true','on','yes','1'))) {
return true;
} elseif (in_array($val, array('false','off','no','0'))) {
return false;
} else {
return (bool)$val;
}
break;
case CONFIGMAN_TYPE_INTEGER:
return (int)$val;
break;
case CONFIGMAN_TYPE_DOUBLE:
return (double)$val;
break;
default:
return (string)$val;
break;
}
}
}
?> |