*
* ini_Comment - A comment inside the INI file
* ini_Value - A key/value pair represented by key=value
* ini_Section - A section of an ini file represented by [section]
* ini_File - A collection of ini_Section objects.
*
* Because reading a and parsing an INI file can take some time, you * should not read an parse a file every time a web page is called! PHP * does offer a solution! Sessions. To see how you can use this to your * advantage, Take a look at this example:
*
* @example testpage.php *

* The above example shows you how to parse and output the information.
*
* This is a work in progress and has not been used in a production mode * to manage INI files...yet. Therefore, I am looking for feedback to extend * these objects to include methods that are needed to facilitate managing a * remote INI file from your browser.
*
* The basic purpose of this object was to read an INI file in only once and * perform a single action based on the settings in the INI file, not really * remote INI file editing. But, let's have fun!
*
* * @version 0.9.0b * @author James Barwick * @package ini_File */ define('INI_VALUE_TERMINATOR', 1); define('INI_NEWLINE', 2); define('INI_COMMENT_CHARACTER',3); define('INI_MSG_NOFILE', 4); define('INI_MSG_NOWRITE', 6); define('INI_MSG_CANTWRITE', 7); define('INI_ROOTSECTION', 5); $GLOBALS[INI_ROOTSECTION]="****root****"; $GLOBALS[INI_VALUE_TERMINATOR]=""; $GLOBALS[INI_NEWLINE]="\n"; $GLOBALS[INI_COMMENT_CHARACTER]="#"; $GLOBALS[INI_MSG_NOFILE]="File does not exist: "; $GLOBALS[INI_MSG_NOWRITE]="Error writing file: "; $GLOBALS[INI_MSG_CANTWRITE]="Cannot write to file: "; /** * ini_Comment * * Represent comments within the ini_File as an object. * * @author James Barwick * @package ini_File * @copyright (c) Copyright 2007. James Barwick. All rights reserved. */ class ini_Comment { /** * The comment is an array of strings * @var array() */ private $comment; /** * Contructor * * Contruct the comment passing in at least one comment string * * @param string $comment * @return ini_Comment */ function ini_Comment($comment) { $this->setComment($comment); } /** * setComment * * Set the comment to the string passed in * * @param string $comment * @access public */ function setComment($comment) { $this->comment = array(); $this->addComment($comment); } /** * addComment * * Append a comment line to the array() list of comments. * * @param string $comment * @access public */ function addComment($comment) { $comment = ltrim($comment,"#,;"); array_push($this->comment,$comment); } /** * createComment * * Append a comment to the end of the specified * comment object or create a new object.
*
* This is static so you can call it as:
*
* ini_Comment::createComment($c_obj,$comment);
* * @param ini_Comment $commentObject * @param string $comment * @return ini_Comment A new ini_Coment or the same one passed in * @access public */ static function createComment($commentObject,$comment) { if (empty($commentObject)) { $commentObject = new ini_Comment($comment); return $commentObject; } if ($commentObject instanceof ini_Comment) { $commentObject->addComment($comment); return $commentObject; } return null; } /** * toString * * Return a formatted string representing the comment lines.
*
* The comment is preceeded by $GLOBALS[INI_COMMENT_CHARACTER]
*
* Each comment line is ended with $GLOBALS[INI_NEWLINE]
* * @param integer $line_1_indent * @param integer $line_2_indent * @return string representing the coments * @access public */ function toString($line_1_indent=0,$line_2_indent=0) { $spaces = str_repeat(' ',$line_2_indent); $s=str_repeat(' ',$line_1_indent); $i=0; foreach ($this->comment as $comment_line) { if ($i==0) $i++; else $s.=$spaces; $s.=$GLOBALS[INI_COMMENT_CHARACTER].$comment_line.$GLOBALS[INI_NEWLINE]; } return $s; } } /** * ini_Value * * @author James Barwick * @package ini_File * @copyright (c) Copyright 2007. James Barwick. All rights reserved. */ class ini_Value { /** * Comment for this value. This value must start on the * same line as the key but may contain multple lines.
*
* Example:
*
* mykey=myvalue #comment
* #comment line 2
* #comment line 3
* * @var ini_Comment * @access private */ private $after_comment; /** * Users sometimes put comments above a key value. This * ini_Comment will be associated with with the key. *
* Example:
*
* #comment line 1
* #comment line 2
* key=value
* * @var ini_Comment * @access private */ private $above_comment; /** * The KEY for the VALUE * * @var string * @access private */ private $name; /** * The VALUE for the KEY * * @var string * @access private */ private $content; /** * Constructor for ini_Value * * @param string $name Name of value. This is called a Key * @param string $content The value for the key * @param string $comment The initial comment after the value * @param mixed $parent Optional. ini_Section * @access public */ function ini_Value($name, $content, $comment='') { $this->name = $name; $this->content = $content; $this->above_comment = null; $this->after_comment = null; if ($comment!='') $this->addAfterComment($comment); } // end constructor /** * getName * * Get the key for this value. * * @return string * @access public */ function getName() { return $this->name; } /** * setBeforeComments * * Set the comments to the ini_Comments object.
*
* If the parameter passed is not a ini_Comment object, * this function has no effect. * * @param ini_Comment $comments * @return ini_Comment The comment above the key * @access public */ function setBeforeComments($comments) { if ($comments instanceof ini_Comment) $this->above_comment = $comments; return $this->above_comment; } /** * setBeforComment * * Set the comments above this key to the string identified. * * @param string $comment * @return ini_Comment The comment above the key * @access public */ function setBeforeComment($comment) { $this->above_comment = new ini_Comment($comment); return $this->above_comment; } /** * getComment * * Returns the comment AFTER this key value entry. * * @return ini_Comment object * @access public */ function getComment() { return $this->after_comment; } /** * addBeforeComment * * Add a comment above this value. * * @param string $comment * @return ini_Comment Instance of ini_Comment object or null * @access public */ function addBeforeComment($comment) { if (empty($this->above_comment)) $this->above_comment = new ini_Comment($comment); else $this->above_comment->setComment($comment); return $this->above_comment; } /** * addAfterComment * * Adds a comment to this item. * * @param string $comment The comment to add to this value * @return ini_Comment reference to comment object * @access public */ function addAfterComment($comment) { if (empty($this->after_comment)) $this->after_comment = new ini_Comment($comment); else $this->after_comment->addComment($comment); return $this->after_comment; } /** * setAfterComment * * Set the comments after this key to the comment provided. * * @param string $comment * @return ini_Comment * @access public */ function setAfterComment($comment) { $this->after_comment = new ini_Comment($comment); return $this->after_comment; } /** * setContent * * Set the value for this key * * @param string $content * @access public */ function setContent($content) { $this->content = $content; } /** * getContent * * Get the value for this key * * @return string vlaue for this key * @access public */ function getContent() { return $this->content; } /** * toString * * Format the Value.
*
* This also includes the comments. * * @return string String representing the Value with its comments * @access public */ function toString() { $s=""; if (!empty($this->above_comment)) $s.=$this->above_comment->toString(); $v=$this->name."=".$this->content.$GLOBALS[INI_VALUE_TERMINATOR]; $s.=$v; if (!empty($this->after_comment)) { $p = strlen($v)+1; $s.=$this->after_comment->toString(1,$p); } else $s.=$GLOBALS[INI_NEWLINE]; return $s; } } /** * ini_Section * * @author James Barwick name = $name; $this->content = array(); $this->comment = null; if ($comment=='') $this->addComment($comment); } // end constructor /** * addItem * * Adds an item to this section. * * @param string $name the key for the value * @param string $value the value for the key * @param string $comment Optional comment * @return ini_Value Value modified or created * @access public */ function addItem($name,$value,$comment='') { $key = strtolower($name); if (IsSet($this->content[$key])) { $valueObject = $this->content[$key]; $valueObject->setContent($value); $valueObject->setComment($comment); } else { $valueObject = new ini_Value($name,$value,$comment); $this->content[$key] = $valueObject; } return $valueObject; } /** * setComment * * Set the comment object on this section to the comment provided * * @param ini_Comment $commnet This is the ini_Comment object * @access public */ function setComment($comment) { if ($comment instanceof ini_Comment) $this->comment = $comment; } /** * addComment * * Adds a comment to this item.
* This is a helper method that calls createItem * * @param string $comment The comment for this section * @return ini_Comment The comment object that was created. * @access public */ function addComment($comment) { if (empty($this->comment)) $this->comment = new ini_Comment($comment); else $this->comment->addComment($comment); return $this->comment; } /** * addValue * * Add the value to the Section * * @param ini_Value $value Value to add to this section * @access public */ function addValue($value) { if ($value instanceof ini_Value) { $key = strtolower($value->getName()); $this->content[$key]=$value; } } /** * getItem * * Gets an item from it's key.
*
* Examples:
* $value_object = $section->getItem('key');
* $value = $section->getItem('key')->getValue();
* $value = $inifile->getSection('section')->getItem('key')->getValue();
* * @param string $name The key of the item in this section to retrieve * @return ini_Value The value referenced by this key * @access public */ function getItem($name) { $key = strtolower($name); if (IsSet($this->content[$key])) return $this->content[$key]; return null; } /** * getValues * * Return the values in this section in an associative array indexed by key.
*
* $values = array($key => new ini_Value($key,$value));
* * @return array() of ini_Value objects in an associative array indexed by key * @access public */ function getValues() { return $this->content; } /** * getName * * Get this Section's name. * * @return string item's name * @access public */ function getName() { return $this->name; } /** * toString * * Return a string representation of the section of the ini file. * * @return string Formatted section of the INI file. * @access public */ function toString() { $s=""; if (!empty($this->comment)) $s.=$this->comment->toString(); if ($this->name!=$GLOBALS[INI_ROOTSECTION]) $s.="[".$this->name."]".$GLOBALS[INI_NEWLINE]; foreach ($this->content as $value) $s.=$value->toString(); return $s; } } /** * ini_File * * This class allows for parsing and editing of ini files. * This is meant to be streamlined and overhead elliminated. * * @author James Barwick * @package ini_File * @copyright (c) Copyright 2007. James Barwick. All rights reserved. */ class ini_File { /** * File name of the file to read/write to. * * @var string * @access private */ private $filename; /** * ini_Section list. This is an associative array indexed by * the sections name. *
* Example:
*
* $sections = array($key => new ini_Section($key,$value); * * @var array() of ini_Section objects * @access private */ private $sections; /** * Constructor * * Creates a holder for the ini_File contents. * * @param string $filename * @access public */ function ini_File($filename) { $this->filename = $filename; $this->sections = array(); } /** * getSections * * Get the list of sections. There is always at least one section * called $GLOBALS[INI_ROOTSECTION]. This section may be empty. * * @return array() An associative array of sections in the file. * @access public */ function getSections() { return $this->sections; } /** * getSection * * Get the section object ini_Section from its name. * * @param string $section Name or key of the section to get * @return ini_Section * @access public */ function getSection($section) { $section = strtolower($section); if (IsSet($this->sections[$section])) { return $this->sections[$section]; } return null; } /** * getItem * * Retrieve the value from the section. Use empty string '' for the section name * if the value isn't in a section. * * @param string $section name of the section to retrieve the value * @param string $name name of the value to retreive * @return ini_Value value identified by the name in the specified section * @access public */ function getItem($section,$name) { $section_Object = getSection($section); if (empty($section_Object)) return null; return $section_Object->getItem($name); } /** * getItemValue * * Get the Value of the item in the specified section * * @param string $section Section name in the file * @param string $name value name in the file * @return string the value of the key * @access public */ function getItemValue($section,$name) { $value_object = getItem($section,$name); if (empty($value_object)) return ''; return $value_object->getValue(); } /** * read * * arses the data of the given configuration file * @return string representing an error code or empty string if no error * @access public */ function read() { if (!file_exists($this->filename)) return $GLOBALS[INI_MSG_NOFILE].$this->filename; $lines = file($this->filename); $this->parse($lines); return ""; } /** * write * * Write ini contents to the file * * @return string representing an error code or empty string if no error * @access public */ function write() { $result = ""; if (!is_writable($this->filename)) return $GLOBALS[INI_MSG_CANTWRITE].$this->filename; $fl=fopen($this->filename,"w"); if (fputs($fl,$this->toString())===false) { $result = $GLOBALS[INI_MSG_NOWRITE].$this->filename; } fclose($fl); return $result; } /** * createSection * * Adds the section or replaces the section specified. * * @param string $name * @return ini_Section * @access public */ function createSection($name) { $key = trim(strtolower($name)); $s = new ini_Section($name); $this->sections[$key] = $s; return $s; } /** * parse * * Parse an array() of INI File Lines * * @access public * @param string array() $lines */ function parse($lines) { $this->sections = array(); $currentSection = $this->createSection($GLOBALS[INI_ROOTSECTION]); $currentValue = null; $currentComment = null; foreach ($lines as $line) { if (($line=='')||($line[0]=='\t')||($line[0]==' ')) $beginsWithSpaces=true; else $beginsWithSpaces=false; $line=trim($line,"\x00..\x20"); if ($line=='') { $currentComment=ini_Comment::createComment($currentComment,$line); continue; } if ($line[0]==$GLOBALS[INI_COMMENT_CHARACTER]) { if ($beginsWithSpaces) { if (!empty($currentValue)) { $currentValue->addAfterComment($line); $currentComment=null; continue; } } $currentComment=ini_Comment::createComment($currentComment,$line); continue; } // Are we a section? if it begins with [ assume it is regardless // of an ending ]. Result, fix bad INI section headers. if ($line[0]=='[') { $l=strlen(($line))-1; if ($line[$l]==']') $l--; $name = substr($line,1,$l); $currentSection=$this->createSection($name); $currentSection->setComment($currentComment); $currentComment=null; continue; } // Check for key $i=strpos($line,'='); if ($i==0) { $currentComment=ini_Comment::createComment($currentComment,$line); continue; } $key=trim(substr($line,0,$i)); $line_length=strlen($line); $inquote=false; $value_start = $i+1; $value_end = $value_start; while ($value_end<$line_length) { $c=$line[$value_end]; if ($c=='"') { if (!$inquote) $inquote=true; else $inquote=false; } if (!$inquote) { if (($c==';')||($c=='#')) break; } $value_end++; } $value=substr($line,$value_start,$value_end-$value_start); if ($value_end<$line_length) $comment=ltrim(substr($line,$value_end+1),"#,\x20"); else $comment=""; $currentValue=$currentSection->addItem($key,$value,$comment); if (!empty($currentComment)) { $currentValue->setBeforeComments($currentComment); $currentComment=null; } } } /** * tpString * * Returns a formatted string of the file * * @return string * @access public */ function toString() { $s=""; foreach ($this->sections as $section) { $s.=$section->toString(); } return $s; } } ?>