diff --git a/thirdparty/pear/Config.php b/thirdparty/pear/Config.php new file mode 100644 index 0000000..3f297e1 --- /dev/null +++ b/thirdparty/pear/Config.php @@ -0,0 +1,230 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id$ + +require_once('PEAR.php'); +require_once('Config/Container.php'); + +$GLOBALS['CONFIG_TYPES'] = + array( + 'apache' =>array('Config/Container/Apache.php','Config_Container_Apache'), + 'genericconf' =>array('Config/Container/GenericConf.php','Config_Container_GenericConf'), + 'inifile' =>array('Config/Container/IniFile.php','Config_Container_IniFile'), + 'inicommented' =>array('Config/Container/IniCommented.php','Config_Container_IniCommented'), + 'phparray' =>array('Config/Container/PHPArray.php','Config_Container_PHPArray'), + 'xml' =>array('Config/Container/XML.php','Config_Container_XML') + ); + +/** +* Config +* +* This class allows for parsing and editing of configuration datasources. +* Do not use this class only to read datasources because of the overhead +* it creates to keep track of the configuration structure. +* +* @author Bertrand Mansion +* @package Config +*/ +class Config { + + /** + * Datasource + * Can be a file url, a dsn, an object... + * @var mixed + */ + var $datasrc; + + /** + * Type of datasource for config + * Ex: IniCommented, Apache... + * @var string + */ + var $configType = ''; + + /** + * Options for parser + * @var string + */ + var $parserOptions = array(); + + /** + * Container object + * @var object + */ + var $container; + + /** + * Constructor + * Creates a root container + * + * @access public + */ + function Config() + { + $this->container =& new Config_Container('section', 'root'); + } // end constructor + + /** + * Returns true if container is registered + * + * @param string $configType Type of config + * @access public + * @return bool + */ + function isConfigTypeRegistered($configType) + { + return isset($GLOBALS['CONFIG_TYPES'][strtolower($configType)]); + } // end func isConfigTypeRegistered + + /** + * Register a new container + * + * @param string $configType Type of config + * @param array|false $configInfo Array of format: + * array('path/to/Name.php', + * 'Config_Container_Class_Name'). + * + * If left false, defaults to: + * array('Config/Container/$configType.php', + * 'Config_Container_$configType') + * @access public + * @static + * @author Greg Beaver + * @return true|PEAR_Error true on success + */ + function registerConfigType($configType, $configInfo = false) + { + if (Config::isConfigTypeRegistered($configType)) { + $info = $GLOBALS['CONFIG_TYPES'][strtolower($configType)]; + if ($info[0] == $configInfo[0] && + $info[1] == $configInfo[1]) { + return true; + } else { + return PEAR::raiseError("Config::registerConfigType registration of existing $configType failed.", null, PEAR_ERROR_RETURN); + } + } + if (!is_array($configInfo)) { + // make the normal assumption, that this is a standard config container added in at runtime + $configInfo = array('Config/Container/' . $configType . '.php', + 'Config_Container_'. $configType); + } + $file_exists = @include_once($configInfo[0]); + if ($file_exists) { + if (!class_exists($configInfo[1])) { + return PEAR::raiseError("Config::registerConfigType class '$configInfo[1]' not found in $configInfo[0]", null, PEAR_ERROR_RETURN); + } + } else { + return PEAR::raiseError("Config::registerConfigType file $configInfo[0] not found", null, PEAR_ERROR_RETURN); + } + $GLOBALS['CONFIG_TYPES'][strtolower($configType)] = $configInfo; + return true; + } // end func registerConfigType + + /** + * Returns the root container for this config object + * + * @access public + * @return object reference to config's root container object + */ + function &getRoot() + { + return $this->container; + } // end func getRoot + + /** + * Sets the content of the root Config_container object. + * + * This method will replace the current child of the root + * Config_Container object by the given object. + * + * @param object $rootContainer container to be used as the first child to root + * @access public + * @return mixed true on success or PEAR_Error + */ + function setRoot(&$rootContainer) + { + if (is_object($rootContainer) && strtolower(get_class($rootContainer)) === 'config_container') { + if ($rootContainer->getName() === 'root' && $rootContainer->getType() === 'section') { + $this->container =& $rootContainer; + } else { + $this->container =& new Config_Container('section', 'root'); + $this->container->addItem($rootContainer); + } + return true; + } else { + return PEAR::raiseError("Config::setRoot only accepts object of Config_Container type.", null, PEAR_ERROR_RETURN); + } + } // end func setRoot + + /** + * Parses the datasource contents + * + * This method will parse the datasource given and fill the root + * Config_Container object with other Config_Container objects. + * + * @param mixed $datasrc Datasource to parse + * @param string $configType Type of configuration + * @param array $options Options for the parser + * @access public + * @return mixed PEAR_Error on error or Config_Container object + */ + function &parseConfig($datasrc, $configType, $options = array()) + { + $configType = strtolower($configType); + if (!$this->isConfigTypeRegistered($configType)) { + return PEAR::raiseError("Configuration type '$configType' is not registered in Config::parseConfig.", null, PEAR_ERROR_RETURN); + } + $includeFile = $GLOBALS['CONFIG_TYPES'][$configType][0]; + $className = $GLOBALS['CONFIG_TYPES'][$configType][1]; + include_once($includeFile); + + $parser = new $className($options); + $error = $parser->parseDatasrc($datasrc, $this); + if ($error !== true) { + return $error; + } + $this->parserOptions = $parser->options; + $this->datasrc = $datasrc; + $this->configType = $configType; + return $this->container; + } // end func &parseConfig + + /** + * Writes the container contents to the datasource. + * + * @param mixed $datasrc Datasource to write to + * @param string $configType Type of configuration + * @param array $options Options for config container + * @access public + * @return mixed PEAR_Error on error or true if ok + */ + function writeConfig($datasrc = null, $configType = null, $options = array()) + { + if (empty($datasrc)) { + $datasrc = $this->datasrc; + } + if (empty($configType)) { + $configType = $this->configType; + } + if (empty($options)) { + $options = $this->parserOptions; + } + return $this->container->writeDatasrc($datasrc, $configType, $options); + } // end func writeConfig +} // end class Config +?> \ No newline at end of file diff --git a/thirdparty/pear/Config/Container.php b/thirdparty/pear/Config/Container.php new file mode 100644 index 0000000..5609c86 --- /dev/null +++ b/thirdparty/pear/Config/Container.php @@ -0,0 +1,763 @@ + | +// +---------------------------------------------------------------------+ +// +// $Id$ + +require_once 'Config.php'; + +/** +* Interface for Config containers +* +* @author Bertrand Mansion +* @package Config +*/ +class Config_Container { + + /** + * Container object type + * Ex: section, directive, comment, blank + * @var string + */ + var $type; + + /** + * Container object name + * @var string + */ + var $name = ''; + + /** + * Container object content + * @var string + */ + var $content = ''; + + /** + * Container object children + * @var array + */ + var $children = array(); + + /** + * Reference to container object's parent + * @var object + */ + var $parent; + + /** + * Array of attributes for this item + * @var array + */ + var $attributes; + + /** + * Unique id to differenciate nodes + * + * This is used to compare nodes + * Will not be needed anymore when this class will use ZendEngine 2 + * + * @var int + */ + var $_id; + + /** + * Constructor + * + * @param string $type Type of container object + * @param string $name Name of container object + * @param string $content Content of container object + * @param array $attributes Array of attributes for container object + */ + function Config_Container($type = 'section', $name = '', $content = '', $attributes = null) + { + $this->type = $type; + $this->name = $name; + $this->content = $content; + $this->attributes = $attributes; + $this->parent = null; + $this->_id = uniqid($name.$type, true); + } // end constructor + + /** + * Create a child for this item. + * @param string $type type of item: directive, section, comment, blank... + * @param mixed $item item name + * @param string $content item content + * @param array $attributes item attributes + * @param string $where choose a position 'bottom', 'top', 'after', 'before' + * @param object $target needed if you choose 'before' or 'after' for where + * @return object reference to new item or Pear_Error + */ + function &createItem($type, $name, $content, $attributes = null, $where = 'bottom', $target = null) + { + $item =& new Config_Container($type, $name, $content, $attributes); + $result =& $this->addItem($item, $where, $target); + return $result; + } // end func &createItem + + /** + * Adds an item to this item. + * @param object $item a container object + * @param string $where choose a position 'bottom', 'top', 'after', 'before' + * @param object $target needed if you choose 'before' or 'after' in $where + * @return mixed reference to added container on success, Pear_Error on error + */ + function &addItem(&$item, $where = 'bottom', $target = null) + { + if ($this->type != 'section') { + return PEAR::raiseError('Config_Container::addItem must be called on a section type object.', null, PEAR_ERROR_RETURN); + } + if (is_null($target)) { + $target =& $this; + } + if (strtolower(get_class($target)) != 'config_container') { + return PEAR::raiseError('Target must be a Config_Container object in Config_Container::addItem.', null, PEAR_ERROR_RETURN); + } + + switch ($where) { + case 'before': + $index = $target->getItemIndex(); + break; + case 'after': + $index = $target->getItemIndex()+1; + break; + case 'top': + $index = 0; + break; + case 'bottom': + $index = -1; + break; + default: + return PEAR::raiseError('Use only top, bottom, before or after in Config_Container::addItem.', null, PEAR_ERROR_RETURN); + } + if (isset($index) && $index >= 0) { + array_splice($this->children, $index, 0, 'tmp'); + } else { + $index = count($this->children); + } + $this->children[$index] =& $item; + $this->children[$index]->parent =& $this; + + return $item; + } // end func addItem + + /** + * Adds a comment to this item. + * This is a helper method that calls createItem + * + * @param string $content Object content + * @param string $where Position : 'top', 'bottom', 'before', 'after' + * @param object $target Needed when $where is 'before' or 'after' + * @return object reference to new item or Pear_Error + */ + function &createComment($content = '', $where = 'bottom', $target = null) + { + return $this->createItem('comment', null, $content, null, $where, $target); + } // end func &createComment + + /** + * Adds a blank line to this item. + * This is a helper method that calls createItem + * + * @return object reference to new item or Pear_Error + */ + function &createBlank($where = 'bottom', $target = null) + { + return $this->createItem('blank', null, null, null, $where, $target); + } // end func &createBlank + + /** + * Adds a directive to this item. + * This is a helper method that calls createItem + * + * @param string $name Name of new directive + * @param string $content Content of new directive + * @param mixed $attributes Directive attributes + * @param string $where Position : 'top', 'bottom', 'before', 'after' + * @param object $target Needed when $where is 'before' or 'after' + * @return object reference to new item or Pear_Error + */ + function &createDirective($name, $content, $attributes = null, $where = 'bottom', $target = null) + { + return $this->createItem('directive', $name, $content, $attributes, $where, $target); + } // end func &createDirective + + /** + * Adds a section to this item. + * + * This is a helper method that calls createItem + * If the section already exists, it won't create a new one. + * It will return reference to existing item. + * + * @param string $name Name of new section + * @param array $attributes Section attributes + * @param string $where Position : 'top', 'bottom', 'before', 'after' + * @param object $target Needed when $where is 'before' or 'after' + * @return object reference to new item or Pear_Error + */ + function &createSection($name, $attributes = null, $where = 'bottom', $target = null) + { + return $this->createItem('section', $name, null, $attributes, $where, $target); + } // end func &createSection + + /** + * Tries to find the specified item(s) and returns the objects. + * + * Examples: + * $directives =& $obj->getItem('directive'); + * $directive_bar_4 =& $obj->getItem('directive', 'bar', null, 4); + * $section_foo =& $obj->getItem('section', 'foo'); + * + * This method can only be called on an object of type 'section'. + * Note that root is a section. + * This method is not recursive and tries to keep the current structure. + * For a deeper search, use searchPath() + * + * @param string $type Type of item: directive, section, comment, blank... + * @param mixed $name Item name + * @param mixed $content Find item with this content + * @param array $attributes Find item with attribute set to the given value + * @param int $index Index of the item in the returned object list. If it is not set, will try to return the last item with this name. + * @return mixed reference to item found or false when not found + * @see &searchPath() + */ + function &getItem($type = null, $name = null, $content = null, $attributes = null, $index = -1) + { + if ($this->type != 'section') { + return PEAR::raiseError('Config_Container::getItem must be called on a section type object.', null, PEAR_ERROR_RETURN); + } + if (!is_null($type)) { + $testFields[] = 'type'; + } + if (!is_null($name)) { + $testFields[] = 'name'; + } + if (!is_null($content)) { + $testFields[] = 'content'; + } + if (!is_null($attributes) && is_array($attributes)) { + $testFields[] = 'attributes'; + } + + $itemsArr = array(); + $fieldsToMatch = count($testFields); + for ($i = 0, $count = count($this->children); $i < $count; $i++) { + $match = 0; + reset($testFields); + foreach ($testFields as $field) { + if ($field != 'attributes') { + if ($this->children[$i]->$field == ${$field}) { + $match++; + } + } else { + // Look for attributes in array + $attrToMatch = count($attributes); + $attrMatch = 0; + foreach ($attributes as $key => $value) { + if (isset($this->children[$i]->attributes[$key]) && + $this->children[$i]->attributes[$key] == $value) { + $attrMatch++; + } + } + if ($attrMatch == $attrToMatch) { + $match++; + } + } + } + if ($match == $fieldsToMatch) { + $itemsArr[] =& $this->children[$i]; + } + } + if ($index >= 0) { + if (isset($itemsArr[$index])) { + return $itemsArr[$index]; + } else { + return false; + } + } else { + if ($count = count($itemsArr)) { + return $itemsArr[$count-1]; + } else { + return false; + } + } + } // end func &getItem + + /** + * Finds a node using XPATH like format. + * + * The search format is an array: + * array(item1, item2, item3, ...) + * + * Each item can be defined as the following: + * item = 'string' : will match the container named 'string' + * item = array('string', array('name' => 'xyz')) + * will match the container name 'string' whose attribute name is equal to "xyz" + * For example : + * + * @param mixed Search path and attributes + * + * @return mixed Config_Container object, array of Config_Container objects or false on failure. + * @access public + */ + function &searchPath($args) + { + if ($this->type != 'section') { + return PEAR::raiseError('Config_Container::searchPath must be called on a section type object.', null, PEAR_ERROR_RETURN); + } + + $arg = array_shift($args); + + if (is_array($arg)) { + $name = $arg[0]; + $attributes = $arg[1]; + } else { + $name = $arg; + $attributes = null; + } + // find all the matches for first.. + $match =& $this->getItem(null, $name, null, $attributes); + + if (!$match) { + return false; + } + if (!empty($args)) { + return $match->searchPath($args); + } + return $match; + } // end func &searchPath + + /** + * Return a child directive's content. + * + * This method can use two different search approach, depending on + * the parameter it is given. If the parameter is an array, it will use + * the {@link Config_Container::searchPath()} method. If it is a string, + * it will use the {@link Config_Container::getItem()} method. + * + * Example: + * + * require_once 'Config.php'; + * $ini = new Config(); + * $conf =& $ini->parseConfig('/path/to/config.ini', 'inicommented'); + * + * // Will return the value found at : + * // [Database] + * // host=localhost + * echo $conf->directiveContent(array('Database', 'host'))); + * + * // Will return the value found at : + * // date="dec-2004" + * echo $conf->directiveContent('date'); + * + * + * + * @param mixed Search path and attributes or a directive name + * @param int Index of the item in the returned directive list. + * Eventually used if args is a string. + * + * @return mixed Content of directive or false if not found. + * @access public + */ + function directiveContent($args, $index = -1) + { + if (is_array($args)) { + $item =& $this->searchPath($args); + } else { + $item =& $this->getItem('directive', $args, null, null, $index); + } + if ($item) { + return $item->getContent(); + } + return false; + } // end func getDirectiveContent + + /** + * Returns how many children this container has + * + * @param string $type type of children counted + * @param string $name name of children counted + * @return int number of children found + */ + function countChildren($type = null, $name = null) + { + if (is_null($type) && is_null($name)) { + return count($this->children); + } + $count = 0; + if (isset($name) && isset($type)) { + for ($i = 0, $children = count($this->children); $i < $children; $i++) { + if ($this->children[$i]->name == $name && + $this->children[$i]->type == $type) { + $count++; + } + } + return $count; + } + if (isset($type)) { + for ($i = 0, $children = count($this->children); $i < $children; $i++) { + if ($this->children[$i]->type == $type) { + $count++; + } + } + return $count; + } + if (isset($name)) { + // Some directives can have the same name + for ($i = 0, $children = count($this->children); $i < $children; $i++) { + if ($this->children[$i]->name == $name) { + $count++; + } + } + return $count; + } + } // end func &countChildren + + /** + * Deletes an item (section, directive, comment...) from the current object + * TODO: recursive remove in sub-sections + * @return mixed true if object was removed, false if not, or PEAR_Error if root + */ + function removeItem() + { + if ($this->isRoot()) { + return PEAR::raiseError('Cannot remove root item in Config_Container::removeItem.', null, PEAR_ERROR_RETURN); + } + $index = $this->getItemIndex(); + if (!is_null($index)) { + array_splice($this->parent->children, $index, 1); + return true; + } + return false; + } // end func removeItem + + /** + * Returns the item index in its parent children array. + * @return int returns int or null if root object + */ + function getItemIndex() + { + if (is_object($this->parent)) { + // This will be optimized with Zend Engine 2 + $pchildren =& $this->parent->children; + for ($i = 0, $count = count($pchildren); $i < $count; $i++) { + if ($pchildren[$i]->_id == $this->_id) { + return $i; + } + } + } + return; + } // end func getItemIndex + + /** + * Returns the item rank in its parent children array + * according to other items with same type and name. + * @return int returns int or null if root object + */ + function getItemPosition() + { + if (is_object($this->parent)) { + $pchildren =& $this->parent->children; + for ($i = 0, $count = count($pchildren); $i < $count; $i++) { + if ($pchildren[$i]->name == $this->name && + $pchildren[$i]->type == $this->type) { + $obj[] =& $pchildren[$i]; + } + } + for ($i = 0, $count = count($obj); $i < $count; $i++) { + if ($obj[$i]->_id == $this->_id) { + return $i; + } + } + } + return; + } // end func getItemPosition + + /** + * Returns the item parent object. + * @return object returns reference to parent object or null if root object + */ + function &getParent() + { + return $this->parent; + } // end func &getParent + + /** + * Returns the item parent object. + * @return mixed returns reference to child object or false if child does not exist + */ + function &getChild($index = 0) + { + if (!empty($this->children[$index])) { + return $this->children[$index]; + } else { + return false; + } + } // end func &getChild + + /** + * Set this item's name. + * @return void + */ + function setName($name) + { + $this->name = $name; + } // end func setName + + /** + * Get this item's name. + * @return string item's name + */ + function getName() + { + return $this->name; + } // end func getName + + /** + * Set this item's content. + * @return void + */ + function setContent($content) + { + $this->content = $content; + } // end func setContent + + /** + * Get this item's content. + * @return string item's content + */ + function getContent() + { + return $this->content; + } // end func getContent + + /** + * Set this item's type. + * @return void + */ + function setType($type) + { + $this->type = $type; + } // end func setType + + /** + * Get this item's type. + * @return string item's type + */ + function getType() + { + return $this->type; + } // end func getType + + /** + * Set this item's attributes. + * @param array $attributes Array of attributes + * @return void + */ + function setAttributes($attributes) + { + $this->attributes = $attributes; + } // end func setAttributes + + /** + * Set this item's attributes. + * @param array $attributes Array of attributes + * @return void + */ + function updateAttributes($attributes) + { + if (is_array($attributes)) { + foreach ($attributes as $key => $value) { + $this->attributes[$key] = $value; + } + } + } // end func updateAttributes + + /** + * Get this item's attributes. + * @return array item's attributes + */ + function getAttributes() + { + return $this->attributes; + } // end func getAttributes + + /** + * Get one attribute value of this item + * @param string $attribute Attribute key + * @return mixed item's attribute value + */ + function getAttribute($attribute) + { + if (isset($this->attributes[$attribute])) { + return $this->attributes[$attribute]; + } + return null; + } // end func getAttribute + + /** + * Set a children directive content. + * This is an helper method calling getItem and addItem or setContent for you. + * If the directive does not exist, it will be created at the bottom. + * + * @param string $name Name of the directive to look for + * @param mixed $content New content + * @param int $index Index of the directive to set, + * in case there are more than one directive + * with the same name + * @return object newly set directive + */ + function &setDirective($name, $content, $index = -1) + { + $item =& $this->getItem('directive', $name, null, null, $index); + if ($item === false || PEAR::isError($item)) { + // Directive does not exist, will create one + unset($item); + return $this->createDirective($name, $content, null); + } else { + // Change existing directive value + $item->setContent($content); + return $item; + } + } // end func setDirective + + /** + * Is this item root, in a config container object + * @return bool true if item is root + */ + function isRoot() + { + if (is_null($this->parent)) { + return true; + } + return false; + } // end func isRoot + + /** + * Call the toString methods in the container plugin + * @param string $configType Type of configuration used to generate the string + * @param array $options Specify special options used by the parser + * @return mixed true on success or PEAR_ERROR + */ + function toString($configType, $options = array()) + { + $configType = strtolower($configType); + if (!isset($GLOBALS['CONFIG_TYPES'][$configType])) { + return PEAR::raiseError("Configuration type '$configType' is not registered in Config_Container::toString.", null, PEAR_ERROR_RETURN); + } + $includeFile = $GLOBALS['CONFIG_TYPES'][$configType][0]; + $className = $GLOBALS['CONFIG_TYPES'][$configType][1]; + include_once($includeFile); + $renderer = new $className($options); + return $renderer->toString($this); + } // end func toString + + /** + * Returns a key/value pair array of the container and its children. + * + * Format : section[directive][index] = value + * If the container has attributes, it will use '@' and '#' + * index is here because multiple directives can have the same name. + * + * @param bool $useAttr Whether to return the attributes too + * @return array + */ + function toArray($useAttr = true) + { + $array[$this->name] = array(); + switch ($this->type) { + case 'directive': + if ($useAttr && count($this->attributes) > 0) { + $array[$this->name]['#'] = $this->content; + $array[$this->name]['@'] = $this->attributes; + } else { + $array[$this->name] = $this->content; + } + break; + case 'section': + if ($useAttr && count($this->attributes) > 0) { + $array[$this->name]['@'] = $this->attributes; + } + if ($count = count($this->children)) { + for ($i = 0; $i < $count; $i++) { + $newArr = $this->children[$i]->toArray($useAttr); + if (!is_null($newArr)) { + foreach ($newArr as $key => $value) { + if (isset($array[$this->name][$key])) { + // duplicate name/type + if (!is_array($array[$this->name][$key]) || + !isset($array[$this->name][$key][0])) { + $old = $array[$this->name][$key]; + unset($array[$this->name][$key]); + $array[$this->name][$key][0] = $old; + } + $array[$this->name][$key][] = $value; + } else { + $array[$this->name][$key] = $value; + } + } + } + } + } + break; + default: + return null; + } + return $array; + } // end func toArray + + /** + * Writes the configuration to a file + * + * @param mixed $datasrc Info on datasource such as path to the configuraton file or dsn... + * @param string $configType Type of configuration + * @param array $options Options for writer + * @access public + * @return mixed true on success or PEAR_ERROR + */ + function writeDatasrc($datasrc, $configType, $options = array()) + { + $configType = strtolower($configType); + if (!isset($GLOBALS['CONFIG_TYPES'][$configType])) { + return PEAR::raiseError("Configuration type '$configType' is not registered in Config_Container::writeDatasrc.", null, PEAR_ERROR_RETURN); + } + $includeFile = $GLOBALS['CONFIG_TYPES'][$configType][0]; + $className = $GLOBALS['CONFIG_TYPES'][$configType][1]; + include_once($includeFile); + + $writeMethodName = (version_compare(phpversion(), '5', '<')) ? 'writedatasrc' : 'writeDatasrc'; + if (in_array($writeMethodName, get_class_methods($className))) { + $writer = new $className($options); + return $writer->writeDatasrc($datasrc, $this); + } + + // Default behaviour + $fp = @fopen($datasrc, 'w'); + if ($fp) { + $string = $this->toString($configType, $options); + $len = strlen($string); + @flock($fp, LOCK_EX); + @fwrite($fp, $string, $len); + @flock($fp, LOCK_UN); + @fclose($fp); + return true; + } else { + return PEAR::raiseError('Cannot open datasource for writing.', 1, PEAR_ERROR_RETURN); + } + } // end func writeDatasrc +} // end class Config_Container +?> diff --git a/thirdparty/pear/Config/Container/Apache.php b/thirdparty/pear/Config/Container/Apache.php new file mode 100644 index 0000000..4ac2439 --- /dev/null +++ b/thirdparty/pear/Config/Container/Apache.php @@ -0,0 +1,168 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id$ + +/** +* Simple config parser for apache httpd.conf files +* A more complex version could handle directives as +* associative arrays. +* +* @author Bertrand Mansion +* @package Config +*/ +class Config_Container_Apache { + + /** + * This class options + * Not used at the moment + * + * @var array + */ + var $options = array(); + + /** + * Constructor + * + * @access public + * @param string $options (optional)Options to be used by renderer + */ + function Config_Container_Apache($options = array()) + { + $this->options = $options; + } // end constructor + + /** + * Parses the data of the given configuration file + * + * @access public + * @param string $datasrc path to the configuration file + * @param object $obj reference to a config object + * @return mixed returns a PEAR_ERROR, if error occurs or true if ok + */ + function &parseDatasrc($datasrc, &$obj) + { + if (!is_readable($datasrc)) { + return PEAR::raiseError("Datasource file cannot be read.", null, PEAR_ERROR_RETURN); + } + $lines = file($datasrc); + $n = 0; + $lastline = ''; + $sections[0] =& $obj->container; + foreach ($lines as $line) { + $n++; + if (!preg_match('/^\s*#/', $line) && + preg_match('/^\s*(.*)\s+\\\$/', $line, $match)) { + // directive on more than one line + $lastline .= $match[1].' '; + continue; + } + if ($lastline != '') { + $line = $lastline.trim($line); + $lastline = ''; + } + if (preg_match('/^\s*#+\s*(.*?)\s*$/', $line, $match)) { + // a comment + $currentSection =& $sections[count($sections)-1]; + $currentSection->createComment($match[1]); + } elseif (trim($line) == '') { + // a blank line + $currentSection =& $sections[count($sections)-1]; + $currentSection->createBlank(); + } elseif (preg_match('/^\s*(\w+)(?:\s+(.*?)|)\s*$/', $line, $match)) { + // a directive + $currentSection =& $sections[count($sections)-1]; + $currentSection->createDirective($match[1], $match[2]); + } elseif (preg_match('/^\s*<(\w+)(?:\s+([^>]*)|\s*)>\s*$/', $line, $match)) { + // a section opening + if (!isset($match[2])) + $match[2] = ''; + $currentSection =& $sections[count($sections)-1]; + $attributes = explode(' ', $match[2]); + $sections[] =& $currentSection->createSection($match[1], $attributes); + } elseif (preg_match('/^\s*<\/(\w+)\s*>\s*$/', $line, $match)) { + // a section closing + $currentSection =& $sections[count($sections)-1]; + if ($currentSection->name != $match[1]) { + return PEAR::raiseError("Section not closed in '$datasrc' at line $n.", null, PEAR_ERROR_RETURN); + } + array_pop($sections); + } else { + return PEAR::raiseError("Syntax error in '$datasrc' at line $n.", null, PEAR_ERROR_RETURN); + } + } + return true; + } // end func parseDatasrc + + /** + * Returns a formatted string of the object + * @param object $obj Container object to be output as string + * @access public + * @return string + */ + function toString(&$obj) + { + static $deep = -1; + $ident = ''; + if (!$obj->isRoot()) { + // no indent for root + $deep++; + $ident = str_repeat(' ', $deep); + } + if (!isset($string)) { + $string = ''; + } + switch ($obj->type) { + case 'blank': + $string = "\n"; + break; + case 'comment': + $string = $ident.'# '.$obj->content."\n"; + break; + case 'directive': + $string = $ident.$obj->name.' '.$obj->content."\n"; + break; + case 'section': + if (!$obj->isRoot()) { + $string = $ident.'<'.$obj->name; + if (is_array($obj->attributes) && count($obj->attributes) > 0) { + while (list(,$val) = each($obj->attributes)) { + $string .= ' '.$val; + } + } + $string .= ">\n"; + } + if (count($obj->children) > 0) { + for ($i = 0; $i < count($obj->children); $i++) { + $string .= $this->toString($obj->getChild($i)); + } + } + if (!$obj->isRoot()) { + // object is not root + $string .= $ident.'name.">\n"; + } + break; + default: + $string = ''; + } + if (!$obj->isRoot()) { + $deep--; + } + return $string; + } // end func toString +} // end class Config_Container_Apache +?> \ No newline at end of file diff --git a/thirdparty/pear/Config/Container/GenericConf.php b/thirdparty/pear/Config/Container/GenericConf.php new file mode 100644 index 0000000..f6d5797 --- /dev/null +++ b/thirdparty/pear/Config/Container/GenericConf.php @@ -0,0 +1,138 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id$ + +/** +* Config parser for generic .conf files like +* htdig.conf... +* +* @author Bertrand Mansion +* @package Config +*/ +class Config_Container_GenericConf { + + /** + * This class options: + * Ex: $options['comment'] = '#'; + * Ex: $options['equals'] = ':'; + * Ex: $options['newline'] = '\\'; + * + * @var array + */ + var $options = array(); + + /** + * Constructor + * + * @access public + * @param string $options (optional)Options to be used by renderer + */ + function Config_Container_GenericConf($options = array()) + { + if (empty($options['comment'])) { + $options['comment'] = '#'; + } + if (empty($options['equals'])) { + $options['equals'] = ':'; + } + if (empty($options['newline'])) { + $options['newline'] = '\\'; + } + $this->options = $options; + } // end constructor + + /** + * Parses the data of the given configuration file + * + * @access public + * @param string $datasrc path to the configuration file + * @param object $obj reference to a config object + * @return mixed returns a PEAR_ERROR, if error occurs or true if ok + */ + function &parseDatasrc($datasrc, &$obj) + { + if (!is_readable($datasrc)) { + return PEAR::raiseError("Datasource file cannot be read.", null, PEAR_ERROR_RETURN); + } + + $lines = file($datasrc); + $n = 0; + $lastline = ''; + $currentSection =& $obj->container; + foreach ($lines as $line) { + $n++; + if (!preg_match('/^\s*'.$this->options['comment'].'/', $line) && + preg_match('/^\s*(.*)\s+'.$this->options['newline'].'\s*$/', $line, $match)) { + // directive on more than one line + $lastline .= $match[1].' '; + continue; + } + if ($lastline != '') { + $line = $lastline.trim($line); + $lastline = ''; + } + if (preg_match('/^\s*'.$this->options['comment'].'+\s*(.*?)\s*$/', $line, $match)) { + // a comment + $currentSection->createComment($match[1]); + } elseif (preg_match('/^\s*$/', $line)) { + // a blank line + $currentSection->createBlank(); + } elseif (preg_match('/^\s*(\w+)'.$this->options['equals'].'\s*((.*?)|)\s*$/', $line, $match)) { + // a directive + $currentSection->createDirective($match[1], $match[2]); + } else { + return PEAR::raiseError("Syntax error in '$datasrc' at line $n.", null, PEAR_ERROR_RETURN); + } + } + return true; + } // end func parseDatasrc + + /** + * Returns a formatted string of the object + * @param object $obj Container object to be output as string + * @access public + * @return string + */ + function toString(&$obj) + { + $string = ''; + switch ($obj->type) { + case 'blank': + $string = "\n"; + break; + case 'comment': + $string = $this->options['comment'].$obj->content."\n"; + break; + case 'directive': + $string = $obj->name.$this->options['equals'].$obj->content."\n"; + break; + case 'section': + // How to deal with sections ??? + if (count($obj->children) > 0) { + for ($i = 0; $i < count($obj->children); $i++) { + $string .= $this->toString($obj->getChild($i)); + } + } + break; + default: + $string = ''; + } + return $string; + } // end func toString +} // end class Config_Container_GenericConf +?> \ No newline at end of file diff --git a/thirdparty/pear/Config/Container/IniCommented.php b/thirdparty/pear/Config/Container/IniCommented.php new file mode 100644 index 0000000..f9acf26 --- /dev/null +++ b/thirdparty/pear/Config/Container/IniCommented.php @@ -0,0 +1,315 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id$ + +/** +* Config parser for PHP .ini files with comments +* +* @author Bertrand Mansion +* @package Config +*/ +class Config_Container_IniCommented { + + /** + * This class options + * Not used at the moment + * + * @var array + */ + var $options = array(); + + /** + * Constructor + * + * @access public + * @param string $options (optional)Options to be used by renderer + */ + function Config_Container_IniCommented($options = array()) + { + $this->options = $options; + } // end constructor + + /** + * Parses the data of the given configuration file + * + * @access public + * @param string $datasrc path to the configuration file + * @param object $obj reference to a config object + * @return mixed returns a PEAR_ERROR, if error occurs or true if ok + */ + function &parseDatasrc($datasrc, &$obj) + { + if (!file_exists($datasrc)) { + return PEAR::raiseError("Datasource file does not exist.", null, PEAR_ERROR_RETURN); + } + $lines = file($datasrc); + $n = 0; + $lastline = ''; + $currentSection =& $obj->container; + foreach ($lines as $line) { + $n++; + if (preg_match('/^\s*;(.*?)\s*$/', $line, $match)) { + // a comment + $currentSection->createComment($match[1]); + } elseif (preg_match('/^\s*$/', $line)) { + // a blank line + $currentSection->createBlank(); + } elseif (preg_match('/^\s*([a-zA-Z0-9_\-\.\s]*)\s*=\s*(.*)\s*$/', $line, $match)) { + // a directive + + $values = $this->_quoteAndCommaParser($match[2]); + if (PEAR::isError($values)) { + return PEAR::raiseError($values); + } + + if (count($values)) { + foreach($values as $value) { + if ($value[0] == 'normal') { + $currentSection->createDirective(trim($match[1]), $value[1]); + } + if ($value[0] == 'comment') { + $currentSection->createComment(substr($value[1], 1)); + } + } + } + } elseif (preg_match('/^\s*\[\s*(.*)\s*\]\s*$/', $line, $match)) { + // a section + $currentSection =& $obj->container->createSection($match[1]); + } else { + return PEAR::raiseError("Syntax error in '$datasrc' at line $n.", null, PEAR_ERROR_RETURN); + } + } + return true; + } // end func parseDatasrc + + /** + * Quote and Comma Parser for INI files + * + * This function allows complex values such as: + * + * + * mydirective = "Item, number \"1\"", Item 2 ; "This" is really, really tricky + * + * @param string $text value of a directive to parse for quotes/multiple values + * @return array The array returned contains multiple values, if any (unquoted literals + * to be used as is), and a comment, if any. The format of the array is: + * + *
+     * array(array('normal', 'first value'),
+     *       array('normal', 'next value'),...
+     *       array('comment', '; comment with leading ;'))
+     * 
+ * @author Greg Beaver + * @access private + */ + function _quoteAndCommaParser($text) + { + $text = trim($text); + if ($text == '') { + return array(); + } + + // tokens + $tokens['normal'] = array('"', ';', ','); + $tokens['quote'] = array('"', '\\'); + $tokens['escape'] = false; // cycle + $tokens['after_quote'] = array(',', ';'); + + // events + $events['normal'] = array('"' => 'quote', ';' => 'comment', ',' => 'normal'); + $events['quote'] = array('"' => 'after_quote', '\\' => 'escape'); + $events['after_quote'] = array(',' => 'normal', ';' => 'comment'); + + // state stack + $stack = array(); + + // return information + $return = array(); + $returnpos = 0; + $returntype = 'normal'; + + // initialize + array_push($stack, 'normal'); + $pos = 0; // position in $text + + do { + $char = $text{$pos}; + $state = $this->_getQACEvent($stack); + + if ($tokens[$state]) { + if (in_array($char, $tokens[$state])) { + switch($events[$state][$char]) { + case 'quote' : + if ($state == 'normal' && + isset($return[$returnpos]) && + !empty($return[$returnpos][1])) { + return PEAR::raiseError("invalid ini syntax, quotes cannot follow text '$text'", + null, PEAR_ERROR_RETURN); + } + if ($returnpos >= 0 && isset($return[$returnpos])) { + // trim any unnecessary whitespace in earlier entries + $return[$returnpos][1] = trim($return[$returnpos][1]); + } else { + $returnpos++; + } + $return[$returnpos] = array('normal', ''); + array_push($stack, 'quote'); + continue 2; + break; + case 'comment' : + // comments go to the end of the line, so we are done + $return[++$returnpos] = array('comment', substr($text, $pos)); + return $return; + break; + case 'after_quote' : + array_push($stack, 'after_quote'); + break; + case 'escape' : + // don't save the first slash + array_push($stack, 'escape'); + continue 2; + break; + case 'normal' : + // start a new segment + if ($state == 'normal') { + $returnpos++; + continue 2; + } else { + while ($state != 'normal') { + array_pop($stack); + $state = $this->_getQACEvent($stack); + } + } + break; + default : + PEAR::raiseError("::_quoteAndCommaParser oops, state missing", null, PEAR_ERROR_DIE); + break; + } + } else { + if ($state != 'after_quote') { + if (!isset($return[$returnpos])) { + $return[$returnpos] = array('normal', ''); + } + // add this character to the current ini segment if non-empty, or if in a quote + if ($state == 'quote') { + $return[$returnpos][1] .= $char; + } elseif (!empty($return[$returnpos][1]) || + (empty($return[$returnpos][1]) && trim($char) != '')) { + if (!isset($return[$returnpos])) { + $return[$returnpos] = array('normal', ''); + } + $return[$returnpos][1] .= $char; + } + } else { + if (trim($char) != '') { + return PEAR::raiseError("invalid ini syntax, text after a quote not allowed '$text'", + null, PEAR_ERROR_RETURN); + } + } + } + } else { + // no tokens, so add this one and cycle to previous state + $return[$returnpos][1] .= $char; + array_pop($stack); + } + } while (++$pos < strlen($text)); + return $return; + } // end func _quoteAndCommaParser + + /** + * Retrieve the state off of a state stack for the Quote and Comma Parser + * @param array $stack The parser state stack + * @author Greg Beaver + * @access private + */ + function _getQACEvent($stack) + { + return array_pop($stack); + } // end func _getQACEvent + + /** + * Returns a formatted string of the object + * @param object $obj Container object to be output as string + * @access public + * @return string + */ + function toString(&$obj) + { + static $childrenCount, $commaString; + + if (!isset($string)) { + $string = ''; + } + switch ($obj->type) { + case 'blank': + $string = "\n"; + break; + case 'comment': + $string = ';'.$obj->content."\n"; + break; + case 'directive': + $count = $obj->parent->countChildren('directive', $obj->name); + $content = $obj->content; + if ($content === false) { + $content = '0'; + } elseif ($content === true) { + $content = '1'; + } elseif (strlen(trim($content)) < strlen($content) || + strpos($content, ',') !== false || + strpos($content, ';') !== false || + strpos($content, '"') !== false || + strpos($content, '%') !== false) { + $content = '"'.addslashes($content).'"'; + } + if ($count > 1) { + // multiple values for a directive are separated by a comma + if (isset($childrenCount[$obj->name])) { + $childrenCount[$obj->name]++; + } else { + $childrenCount[$obj->name] = 0; + $commaString[$obj->name] = $obj->name.' = '; + } + if ($childrenCount[$obj->name] == $count-1) { + // Clean the static for future calls to toString + $string .= $commaString[$obj->name].$content."\n"; + unset($childrenCount[$obj->name]); + unset($commaString[$obj->name]); + } else { + $commaString[$obj->name] .= $content.', '; + } + } else { + $string = $obj->name.' = '.$content."\n"; + } + break; + case 'section': + if (!$obj->isRoot()) { + $string = '['.$obj->name."]\n"; + } + if (count($obj->children) > 0) { + for ($i = 0; $i < count($obj->children); $i++) { + $string .= $this->toString($obj->getChild($i)); + } + } + break; + default: + $string = ''; + } + return $string; + } // end func toString +} // end class Config_Container_IniCommented +?> diff --git a/thirdparty/pear/Config/Container/IniFile.php b/thirdparty/pear/Config/Container/IniFile.php new file mode 100644 index 0000000..0086a1d --- /dev/null +++ b/thirdparty/pear/Config/Container/IniFile.php @@ -0,0 +1,163 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id$ + +/** +* Config parser for PHP .ini files +* Faster because it uses parse_ini_file() but get rid of comments, +* quotes, types and converts On, Off, True, False, Yes, No to 0 and 1. +* +* @author Bertrand Mansion +* @package Config +*/ +class Config_Container_IniFile { + + /** + * This class options + * Not used at the moment + * + * @var array + */ + var $options = array(); + + /** + * Constructor + * + * @access public + * @param string $options (optional)Options to be used by renderer + */ + function Config_Container_IniFile($options = array()) + { + $this->options = $options; + } // end constructor + + /** + * Parses the data of the given configuration file + * + * @access public + * @param string $datasrc path to the configuration file + * @param object $obj reference to a config object + * @return mixed returns a PEAR_ERROR, if error occurs or true if ok + */ + function &parseDatasrc($datasrc, &$obj) + { + if (!file_exists($datasrc)) { + return PEAR::raiseError("Datasource file does not exist.", null, PEAR_ERROR_RETURN); + } + $currentSection =& $obj->container; + $confArray = parse_ini_file($datasrc, true); + if (!$confArray) { + return PEAR::raiseError("File '$datasrc' does not contain configuration data.", null, PEAR_ERROR_RETURN); + } + foreach ($confArray as $key => $value) { + if (is_array($value)) { + $currentSection =& $obj->container->createSection($key); + foreach ($value as $directive => $content) { + // try to split the value if comma found + if (strpos($content, '"') === false) { + $values = preg_split('/\s*,\s+/', $content); + if (count($values) > 1) { + foreach ($values as $k => $v) { + $currentSection->createDirective($directive, $v); + } + } else { + $currentSection->createDirective($directive, $content); + } + } else { + $currentSection->createDirective($directive, $content); + } + } + } else { + $currentSection->createDirective($key, $value); + } + } + return true; + } // end func parseDatasrc + + /** + * Returns a formatted string of the object + * @param object $obj Container object to be output as string + * @access public + * @return string + */ + function toString(&$obj) + { + static $childrenCount, $commaString; + + if (!isset($string)) { + $string = ''; + } + switch ($obj->type) { + case 'blank': + $string = "\n"; + break; + case 'comment': + $string = ';'.$obj->content."\n"; + break; + case 'directive': + $count = $obj->parent->countChildren('directive', $obj->name); + $content = $obj->content; + if ($content === false) { + $content = '0'; + } elseif ($content === true) { + $content = '1'; + } elseif (strlen(trim($content)) < strlen($content) || + strpos($content, ',') !== false || + strpos($content, ';') !== false || + strpos($content, '"') !== false || + strpos($content, '%') !== false || + strpos($content, '~') !== false) { + $content = '"'.addslashes($content).'"'; + } + if ($count > 1) { + // multiple values for a directive are separated by a comma + if (isset($childrenCount[$obj->name])) { + $childrenCount[$obj->name]++; + } else { + $childrenCount[$obj->name] = 0; + $commaString[$obj->name] = $obj->name.'='; + } + if ($childrenCount[$obj->name] == $count-1) { + // Clean the static for future calls to toString + $string .= $commaString[$obj->name].$content."\n"; + unset($childrenCount[$obj->name]); + unset($commaString[$obj->name]); + } else { + $commaString[$obj->name] .= $content.', '; + } + } else { + $string = $obj->name.'='.$content."\n"; + } + break; + case 'section': + if (!$obj->isRoot()) { + $string = '['.$obj->name."]\n"; + } + if (count($obj->children) > 0) { + for ($i = 0; $i < count($obj->children); $i++) { + $string .= $this->toString($obj->getChild($i)); + } + } + break; + default: + $string = ''; + } + return $string; + } // end func toString +} // end class Config_Container_IniFile +?> \ No newline at end of file diff --git a/thirdparty/pear/Config/Container/PHPArray.php b/thirdparty/pear/Config/Container/PHPArray.php new file mode 100644 index 0000000..9619433 --- /dev/null +++ b/thirdparty/pear/Config/Container/PHPArray.php @@ -0,0 +1,252 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id$ + +/** +* Config parser for common PHP configuration array +* such as found in the horde project. +* +* Options expected is: +* 'name' => 'conf' +* Name of the configuration array. +* Default is $conf[]. +* 'useAttr' => true +* Whether we render attributes +* +* @author Bertrand Mansion +* @package Config +*/ +class Config_Container_PHPArray { + + /** + * This class options: + * - name of the config array to parse/output + * Ex: $options['name'] = 'myconf'; + * - Whether to add attributes to the array + * Ex: $options['useAttr'] = false; + * + * @var array + */ + var $options = array('name' => 'conf', + 'useAttr' => true); + + /** + * Constructor + * + * @access public + * @param string $options Options to be used by renderer + */ + function Config_Container_PHPArray($options = array()) + { + foreach ($options as $key => $value) { + $this->options[$key] = $value; + } + } // end constructor + + /** + * Parses the data of the given configuration file + * + * @access public + * @param string $datasrc path to the configuration file + * @param object $obj reference to a config object + * @return mixed returns a PEAR_ERROR, if error occurs or true if ok + */ + function &parseDatasrc($datasrc, &$obj) + { + if (empty($datasrc)) { + return PEAR::raiseError("Datasource file path is empty.", null, PEAR_ERROR_RETURN); + } + if (is_array($datasrc)) { + $this->_parseArray($datasrc, $obj->container); + } else { + if (!file_exists($datasrc)) { + return PEAR::raiseError("Datasource file does not exist.", null, PEAR_ERROR_RETURN); + } else { + include($datasrc); + if (!isset(${$this->options['name']}) || !is_array(${$this->options['name']})) { + return PEAR::raiseError("File '$datasrc' does not contain a required '".$this->options['name']."' array.", null, PEAR_ERROR_RETURN); + } + } + $this->_parseArray(${$this->options['name']}, $obj->container); + } + return true; + } // end func parseDatasrc + + /** + * Parses the PHP array recursively + * @param array $array array values from the config file + * @param object $container reference to the container object + * @access private + * @return void + */ + function _parseArray($array, &$container) + { + foreach ($array as $key => $value) { + switch ((string)$key) { + case '@': + $container->setAttributes($value); + break; + case '#': + $container->setType('directive'); + $container->setContent($value); + break; + default: +/* if (is_array($value)) { + $section =& $container->createSection($key); + $this->_parseArray($value, $section); + } else { + $container->createDirective($key, $value); + }*/ + + if (is_array($value)) { + if (is_integer(key($value))) { + foreach ($value as $nestedValue) { + $section =& $container->createSection($key); + $this->_parseArray($nestedValue, $section); + } + } else { + + $section =& $container->createSection($key); + $this->_parseArray($value, $section); + } + } else { + $container->createDirective($key, $value); + } + + } + } + } // end func _parseArray + + /** + * Returns a formatted string of the object + * @param object $obj Container object to be output as string + * @access public + * @return string + */ + function toString(&$obj) + { + if (!isset($string)) { + $string = ''; + } + switch ($obj->type) { + case 'blank': + $string .= "\n"; + break; + case 'comment': + $string .= '// '.$obj->content."\n"; + break; + case 'directive': + $attrString = ''; + $parentString = $this->_getParentString($obj); + $attributes = $obj->getAttributes(); + if ($this->options['useAttr'] && is_array($attributes) && count($attributes) > 0) { + // Directive with attributes '@' and value '#' + $string .= $parentString."['#']"; + foreach ($attributes as $attr => $val) { + $attrString .= $parentString."['@']" + ."['".$attr."'] = '".addslashes($val)."';\n"; + } + } else { + $string .= $parentString; + } + $string .= ' = '; + if (is_string($obj->content)) { + $string .= "'".addslashes($obj->content)."'"; + } elseif (is_int($obj->content) || is_float($obj->content)) { + $string .= $obj->content; + } elseif (is_bool($obj->content)) { + $string .= ($obj->content) ? 'true' : 'false'; + } + $string .= ";\n"; + $string .= $attrString; + break; + case 'section': + $attrString = ''; + $attributes = $obj->getAttributes(); + if ($this->options['useAttr'] && is_array($attributes) && count($attributes) > 0) { + $parentString = $this->_getParentString($obj); + foreach ($attributes as $attr => $val) { + $attrString .= $parentString."['@']" + ."['".$attr."'] = '".addslashes($val)."';\n"; + } + } + $string .= $attrString; + if ($count = count($obj->children)) { + for ($i = 0; $i < $count; $i++) { + $string .= $this->toString($obj->getChild($i)); + } + } + break; + default: + $string = ''; + } + return $string; + } // end func toString + + /** + * Returns a formatted string of the object parents + * @access private + * @return string + */ + function _getParentString(&$obj) + { + $string = ''; + if (!$obj->isRoot()) { + if (!$obj->parent->isRoot()) { + $string = is_int($obj->name) ? "[".$obj->name."]" : "['".$obj->name."']"; + } else { + if (empty($this->options['name'])) { + $string .= '$'.$obj->name; + } else { + $string .= '$'.$this->options['name']."['".$obj->name."']"; + } + } + $string = $this->_getParentString($obj->parent).$string; + $count = $obj->parent->countChildren(null, $obj->name); + if ($count > 1) { + $string .= '['.$obj->getItemPosition().']'; + } + } + return $string; + } // end func _getParentString + + /** + * Writes the configuration to a file + * + * @param mixed datasrc info on datasource such as path to the configuraton file + * @param string configType (optional)type of configuration + * @access public + * @return string + */ + function writeDatasrc($datasrc, &$obj) + { + $fp = @fopen($datasrc, 'w'); + if ($fp) { + $string = "toString($obj) ."?>"; // diff --git a/thirdparty/pear/Config/Container/PHPConstants.php b/thirdparty/pear/Config/Container/PHPConstants.php new file mode 100644 index 0000000..23914e2 --- /dev/null +++ b/thirdparty/pear/Config/Container/PHPConstants.php @@ -0,0 +1,197 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id$ + +/** +* Config parser for PHP constant files +* +* @author Phillip Oertel +* @package Config +* @version 0.1 (not submitted) +*/ + +require_once 'Config/Container.php'; + +class Config_Container_PHPConstants extends Config_Container { + + /** + * This class options + * Not used at the moment + * + * @var array + */ + var $options = array(); + + /** + * Constructor + * + * @access public + * @param string $options (optional)Options to be used by renderer + */ + function Config_Container_PHPConstants($options = array()) + { + $this->options = $options; + } // end constructor + + /** + * Parses the data of the given configuration file + * + * @access public + * @param string $datasrc path to the configuration file + * @param object $obj reference to a config object + * @return mixed returns a PEAR_ERROR, if error occurs or true if ok + */ + function &parseDatasrc($datasrc, &$obj) + { + if (!file_exists($datasrc)) { + return PEAR::raiseError("Datasource file does not exist.", null, + PEAR_ERROR_RETURN); + } + + $fileContent = file_get_contents($datasrc, true); + + if (!$fileContent) { + return PEAR::raiseError("File '$datasrc' could not be read.", null, + PEAR_ERROR_RETURN); + } + + $rows = explode("\n", $fileContent); + for ($i=0, $max=count($rows); $i<$max; $i++) { + $line = $rows[$i]; + + //blanks? + + // sections + if (preg_match("/^\/\/\s*$/", $line)) { + preg_match("/^\/\/\s*(.+)$/", $rows[$i+1], $matches); + $obj->container->createSection(trim($matches[1])); + $i += 2; + continue; + } + + // comments + if (preg_match("/^\/\/\s*(.+)$/", $line, $matches) || + preg_match("/^#\s*(.+)$/", $line, $matches)) { + $obj->container->createComment(trim($matches[1])); + continue; + } + + // directives + $regex = "/^\s*define\s*\('([A-Z1-9_]+)',\s*'*(.[^\']*)'*\)/"; + preg_match($regex, $line, $matches); + if (!empty($matches)) { + $obj->container->createDirective(trim($matches[1]), + trim($matches[2])); + } + } + + return true; + + } // end func parseDatasrc + + /** + * Returns a formatted string of the object + * @param object $obj Container object to be output as string + * @access public + * @return string + */ + function toString(&$obj) + { + $string = ''; + + switch ($obj->type) + { + case 'blank': + $string = "\n"; + break; + + case 'comment': + $string = '// '.$obj->content."\n"; + break; + + case 'directive': + $content = $obj->content; + // don't quote numeric values, true/false and constants + if (!is_numeric($content) && !in_array($content, array('false', + 'true')) && !preg_match('/^[A-Z_]+$/', $content)) { + $content = "'".$content."'"; + } + $string = 'define(\''.$obj->name.'\', '.$content.');'.chr(10); + break; + + case 'section': + if (!$obj->isRoot()) { + $string = chr(10); + $string .= '//'.chr(10); + $string .= '// '.$obj->name.chr(10); + $string .= '//'.chr(10); + } + if (count($obj->children) > 0) { + for ($i = 0, $max = count($obj->children); $i < $max; $i++) { + $string .= $this->toString($obj->getChild($i)); + } + } + break; + default: + $string = ''; + } + return $string; + } // end func toString + + /** + * Writes the configuration to a file + * + * @param mixed datasrc info on datasource such as path to the file + * @param string configType (optional)type of configuration + * @access public + * @return string + */ + function writeDatasrc($datasrc, &$obj) + { + $fp = @fopen($datasrc, 'w'); + if ($fp) { + $string = "toString($obj); + $string .= "\n?>"; // diff --git a/thirdparty/pear/Config/Container/XML.php b/thirdparty/pear/Config/Container/XML.php new file mode 100644 index 0000000..aea8b16 --- /dev/null +++ b/thirdparty/pear/Config/Container/XML.php @@ -0,0 +1,251 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id$ + +require_once('XML/Parser.php'); +require_once('XML/Util.php'); + +/** +* Config parser for XML Files +* +* @author Bertrand Mansion +* @package Config +*/ +class Config_Container_XML extends XML_Parser +{ + /** + * Deep level used for indentation + * + * @var int + * @access private + */ + var $_deep = -1; + + /** + * This class options: + * version (1.0) : XML version + * encoding (ISO-8859-1) : XML content encoding + * name : like in phparray, name of your config global entity + * indent : char used for indentation + * linebreak : char used for linebreak + * addDecl : whether to add the xml declaration at beginning or not + * useAttr : whether to use the attributes + * isFile : whether the given content is a file or an XML string + * useCData : whether to surround data with + * + * @var array + */ + var $options = array('version' => '1.0', + 'encoding' => 'ISO-8859-1', + 'name' => '', + 'indent' => ' ', + 'linebreak' => "\n", + 'addDecl' => true, + 'useAttr' => true, + 'isFile' => true, + 'useCData' => false); + + /** + * Container objects + * + * @var array + */ + var $containers = array(); + + /** + * Constructor + * + * @access public + * @param string $options Options to be used by renderer + * version : (1.0) XML version + * encoding : (ISO-8859-1) XML content encoding + * name : like in phparray, name of your config global entity + * indent : char used for indentation + * linebreak : char used for linebreak + * addDecl : whether to add the xml declaration at beginning or not + * useAttr : whether to use the attributes + * isFile : whether the given content is a file or an XML string + */ + function Config_Container_XML($options = array()) + { + foreach ($options as $key => $value) { + $this->options[$key] = $value; + } + } // end constructor + + /** + * Parses the data of the given configuration file + * + * @access public + * @param string $datasrc path to the configuration file + * @param object $obj reference to a config object + * @return mixed returns a PEAR_ERROR, if error occurs or true if ok + */ + function &parseDatasrc($datasrc, &$obj) + { + $this->folding = false; + $this->cdata = null; + $this->XML_Parser($this->options['encoding'], 'event'); + $this->containers[0] =& $obj->container; + if (is_string($datasrc)) { + if ($this->options['isFile']) { + $err = $this->setInputFile($datasrc); + if (PEAR::isError($err)) { + return $err; + } + $err = $this->parse(); + } else { + $err = $this->parseString($datasrc, true); + } + } else { + $this->setInput($datasrc); + $err = $this->parse(); + } + if (PEAR::isError($err)) { + return $err; + } + return true; + } // end func parseDatasrc + + /** + * Handler for the xml-data + * + * @param mixed $xp ignored + * @param string $elem name of the element + * @param array $attribs attributes for the generated node + * + * @access private + */ + function startHandler($xp, $elem, &$attribs) + { + $container =& new Config_Container('section', $elem, null, $attribs); + $this->containers[] =& $container; + return null; + } // end func startHandler + + /** + * Handler for the xml-data + * + * @param mixed $xp ignored + * @param string $elem name of the element + * + * @access private + */ + function endHandler($xp, $elem) + { + $count = count($this->containers); + $container =& $this->containers[$count-1]; + $currentSection =& $this->containers[$count-2]; + if (count($container->children) == 0) { + $container->setType('directive'); + $container->setContent(trim($this->cdata)); + } + $currentSection->addItem($container); + array_pop($this->containers); + $this->cdata = null; + return null; + } // end func endHandler + + /* + * The xml character data handler + * + * @param mixed $xp ignored + * @param string $data PCDATA between tags + * + * @access private + */ + function cdataHandler($xp, $cdata) + { + $this->cdata .= $cdata; + } // end func cdataHandler + + /** + * Returns a formatted string of the object + * @param object $obj Container object to be output as string + * @access public + * @return string + */ + function toString(&$obj) + { + $indent = ''; + if (!$obj->isRoot()) { + // no indent for root + $this->_deep++; + $indent = str_repeat($this->options['indent'], $this->_deep); + } else { + // Initialize string with xml declaration + $string = ''; + if ($this->options['addDecl']) { + $string .= XML_Util::getXMLDeclaration($this->options['version'], $this->options['encoding']); + $string .= $this->options['linebreak']; + } + if (!empty($this->options['name'])) { + $string .= '<'.$this->options['name'].'>'.$this->options['linebreak']; + $this->_deep++; + $indent = str_repeat($this->options['indent'], $this->_deep); + } + } + if (!isset($string)) { + $string = ''; + } + switch ($obj->type) { + case 'directive': + $attributes = ($this->options['useAttr']) ? $obj->attributes : array(); + $string .= $indent.XML_Util::createTag($obj->name, $attributes, $obj->content, null, + ($this->options['useCData'] ? XML_UTIL_CDATA_SECTION : XML_UTIL_REPLACE_ENTITIES)); + $string .= $this->options['linebreak']; + break; + case 'comment': + $string .= $indent.''; + $string .= $this->options['linebreak']; + break; + case 'section': + if (!$obj->isRoot()) { + $string = $indent.'<'.$obj->name; + $string .= ($this->options['useAttr']) ? XML_Util::attributesToString($obj->attributes) : ''; + } + if ($children = count($obj->children)) { + if (!$obj->isRoot()) { + $string .= '>'.$this->options['linebreak']; + } + for ($i = 0; $i < $children; $i++) { + $string .= $this->toString($obj->getChild($i)); + } + } + if (!$obj->isRoot()) { + if ($children) { + $string .= $indent.'name.'>'.$this->options['linebreak']; + } else { + $string .= '/>'.$this->options['linebreak']; + } + } else { + if (!empty($this->options['name'])) { + $string .= 'options['name'].'>'.$this->options['linebreak']; + } + } + break; + default: + $string = ''; + } + if (!$obj->isRoot()) { + $this->_deep--; + } + return $string; + } // end func toString +} // end class Config_Container_XML +?> \ No newline at end of file