[ Index ] |
|
Code source de PHP PEAR 1.4.5 |
1 <?php 2 // +----------------------------------------------------------------------+ 3 // | PHP Version 4 | 4 // +----------------------------------------------------------------------+ 5 // | Copyright (c) 1997-2003 The PHP Group | 6 // +----------------------------------------------------------------------+ 7 // | This source file is subject to version 2.0 of the PHP license, | 8 // | that is bundled with this package in the file LICENSE, and is | 9 // | available at through the world-wide-web at | 10 // | http://www.php.net/license/2_02.txt. | 11 // | If you did not receive a copy of the PHP license and are unable to | 12 // | obtain it through the world-wide-web, please send a note to | 13 // | license@php.net so we can mail you a copy immediately. | 14 // +----------------------------------------------------------------------+ 15 // | Author: Bertrand Mansion <bmansion@mamasam.com> | 16 // +----------------------------------------------------------------------+ 17 // 18 // $Id: IniCommented.php,v 1.26 2006/05/30 06:51:05 aashley Exp $ 19 20 /** 21 * Config parser for PHP .ini files with comments 22 * 23 * @author Bertrand Mansion <bmansion@mamasam.com> 24 * @package Config 25 */ 26 class Config_Container_IniCommented { 27 28 /** 29 * This class options 30 * Not used at the moment 31 * 32 * @var array 33 */ 34 var $options = array(); 35 36 /** 37 * Constructor 38 * 39 * @access public 40 * @param string $options (optional)Options to be used by renderer 41 */ 42 function Config_Container_IniCommented($options = array()) 43 { 44 $this->options = $options; 45 } // end constructor 46 47 /** 48 * Parses the data of the given configuration file 49 * 50 * @access public 51 * @param string $datasrc path to the configuration file 52 * @param object $obj reference to a config object 53 * @return mixed returns a PEAR_ERROR, if error occurs or true if ok 54 */ 55 function &parseDatasrc($datasrc, &$obj) 56 { 57 $return = true; 58 if (!file_exists($datasrc)) { 59 return PEAR::raiseError("Datasource file does not exist.", null, PEAR_ERROR_RETURN); 60 } 61 $lines = file($datasrc); 62 $n = 0; 63 $lastline = ''; 64 $currentSection =& $obj->container; 65 foreach ($lines as $line) { 66 $n++; 67 if (preg_match('/^\s*;(.*?)\s*$/', $line, $match)) { 68 // a comment 69 $currentSection->createComment($match[1]); 70 } elseif (preg_match('/^\s*$/', $line)) { 71 // a blank line 72 $currentSection->createBlank(); 73 } elseif (preg_match('/^\s*([a-zA-Z0-9_\-\.\s:]*)\s*=\s*(.*)\s*$/', $line, $match)) { 74 // a directive 75 76 $values = $this->_quoteAndCommaParser($match[2]); 77 if (PEAR::isError($values)) { 78 return PEAR::raiseError($values); 79 } 80 81 if (count($values)) { 82 foreach($values as $value) { 83 if ($value[0] == 'normal') { 84 $currentSection->createDirective(trim($match[1]), $value[1]); 85 } 86 if ($value[0] == 'comment') { 87 $currentSection->createComment(substr($value[1], 1)); 88 } 89 } 90 } 91 } elseif (preg_match('/^\s*\[\s*(.*)\s*\]\s*$/', $line, $match)) { 92 // a section 93 $currentSection =& $obj->container->createSection($match[1]); 94 } else { 95 return PEAR::raiseError("Syntax error in '$datasrc' at line $n.", null, PEAR_ERROR_RETURN); 96 } 97 } 98 return $return; 99 } // end func parseDatasrc 100 101 /** 102 * Quote and Comma Parser for INI files 103 * 104 * This function allows complex values such as: 105 * 106 * <samp> 107 * mydirective = "Item, number \"1\"", Item 2 ; "This" is really, really tricky 108 * </samp> 109 * @param string $text value of a directive to parse for quotes/multiple values 110 * @return array The array returned contains multiple values, if any (unquoted literals 111 * to be used as is), and a comment, if any. The format of the array is: 112 * 113 * <pre> 114 * array(array('normal', 'first value'), 115 * array('normal', 'next value'),... 116 * array('comment', '; comment with leading ;')) 117 * </pre> 118 * @author Greg Beaver <cellog@users.sourceforge.net> 119 * @access private 120 */ 121 function _quoteAndCommaParser($text) 122 { 123 $text = trim($text); 124 if ($text == '') { 125 $emptyNode = array(); 126 $emptyNode[0][0] = 'normal'; 127 $emptyNode[0][1] = ''; 128 return $emptyNode; 129 } 130 131 // tokens 132 $tokens['normal'] = array('"', ';', ','); 133 $tokens['quote'] = array('"', '\\'); 134 $tokens['escape'] = false; // cycle 135 $tokens['after_quote'] = array(',', ';'); 136 137 // events 138 $events['normal'] = array('"' => 'quote', ';' => 'comment', ',' => 'normal'); 139 $events['quote'] = array('"' => 'after_quote', '\\' => 'escape'); 140 $events['after_quote'] = array(',' => 'normal', ';' => 'comment'); 141 142 // state stack 143 $stack = array(); 144 145 // return information 146 $return = array(); 147 $returnpos = 0; 148 $returntype = 'normal'; 149 150 // initialize 151 array_push($stack, 'normal'); 152 $pos = 0; // position in $text 153 154 do { 155 $char = $text{$pos}; 156 $state = $this->_getQACEvent($stack); 157 158 if ($tokens[$state]) { 159 if (in_array($char, $tokens[$state])) { 160 switch($events[$state][$char]) { 161 case 'quote' : 162 if ($state == 'normal' && 163 isset($return[$returnpos]) && 164 !empty($return[$returnpos][1])) { 165 return PEAR::raiseError("invalid ini syntax, quotes cannot follow text '$text'", 166 null, PEAR_ERROR_RETURN); 167 } 168 if ($returnpos >= 0 && isset($return[$returnpos])) { 169 // trim any unnecessary whitespace in earlier entries 170 $return[$returnpos][1] = trim($return[$returnpos][1]); 171 } else { 172 $returnpos++; 173 } 174 $return[$returnpos] = array('normal', ''); 175 array_push($stack, 'quote'); 176 continue 2; 177 break; 178 case 'comment' : 179 // comments go to the end of the line, so we are done 180 $return[++$returnpos] = array('comment', substr($text, $pos)); 181 return $return; 182 break; 183 case 'after_quote' : 184 array_push($stack, 'after_quote'); 185 break; 186 case 'escape' : 187 // don't save the first slash 188 array_push($stack, 'escape'); 189 continue 2; 190 break; 191 case 'normal' : 192 // start a new segment 193 if ($state == 'normal') { 194 $returnpos++; 195 continue 2; 196 } else { 197 while ($state != 'normal') { 198 array_pop($stack); 199 $state = $this->_getQACEvent($stack); 200 } 201 $returnpos++; 202 } 203 break; 204 default : 205 PEAR::raiseError("::_quoteAndCommaParser oops, state missing", null, PEAR_ERROR_DIE); 206 break; 207 } 208 } else { 209 if ($state != 'after_quote') { 210 if (!isset($return[$returnpos])) { 211 $return[$returnpos] = array('normal', ''); 212 } 213 // add this character to the current ini segment if non-empty, or if in a quote 214 if ($state == 'quote') { 215 $return[$returnpos][1] .= $char; 216 } elseif (!empty($return[$returnpos][1]) || 217 (empty($return[$returnpos][1]) && trim($char) != '')) { 218 if (!isset($return[$returnpos])) { 219 $return[$returnpos] = array('normal', ''); 220 } 221 $return[$returnpos][1] .= $char; 222 if (strcasecmp('true', $return[$returnpos][1]) == 0) { 223 $return[$returnpos][1] = '1'; 224 } elseif (strcasecmp('false', $return[$returnpos][1]) == 0) { 225 $return[$returnpos][1] = ''; 226 } 227 } 228 } else { 229 if (trim($char) != '') { 230 return PEAR::raiseError("invalid ini syntax, text after a quote not allowed '$text'", 231 null, PEAR_ERROR_RETURN); 232 } 233 } 234 } 235 } else { 236 // no tokens, so add this one and cycle to previous state 237 $return[$returnpos][1] .= $char; 238 array_pop($stack); 239 } 240 } while (++$pos < strlen($text)); 241 return $return; 242 } // end func _quoteAndCommaParser 243 244 /** 245 * Retrieve the state off of a state stack for the Quote and Comma Parser 246 * @param array $stack The parser state stack 247 * @author Greg Beaver <cellog@users.sourceforge.net> 248 * @access private 249 */ 250 function _getQACEvent($stack) 251 { 252 return array_pop($stack); 253 } // end func _getQACEvent 254 255 /** 256 * Returns a formatted string of the object 257 * @param object $obj Container object to be output as string 258 * @access public 259 * @return string 260 */ 261 function toString(&$obj) 262 { 263 static $childrenCount, $commaString; 264 265 if (!isset($string)) { 266 $string = ''; 267 } 268 switch ($obj->type) { 269 case 'blank': 270 $string = "\n"; 271 break; 272 case 'comment': 273 $string = ';'.$obj->content."\n"; 274 break; 275 case 'directive': 276 $count = $obj->parent->countChildren('directive', $obj->name); 277 $content = $obj->content; 278 if ($content === false) { 279 $content = '0'; 280 } elseif ($content === true) { 281 $content = '1'; 282 } elseif (strlen(trim($content)) < strlen($content) || 283 strpos($content, ',') !== false || 284 strpos($content, ';') !== false || 285 strpos($content, '=') !== false || 286 strpos($content, '"') !== false || 287 strpos($content, '%') !== false || 288 strpos($content, '~') !== false) { 289 $content = '"'.addslashes($content).'"'; 290 } 291 if ($count > 1) { 292 // multiple values for a directive are separated by a comma 293 if (isset($childrenCount[$obj->name])) { 294 $childrenCount[$obj->name]++; 295 } else { 296 $childrenCount[$obj->name] = 0; 297 $commaString[$obj->name] = $obj->name.' = '; 298 } 299 if ($childrenCount[$obj->name] == $count-1) { 300 // Clean the static for future calls to toString 301 $string .= $commaString[$obj->name].$content."\n"; 302 unset($childrenCount[$obj->name]); 303 unset($commaString[$obj->name]); 304 } else { 305 $commaString[$obj->name] .= $content.', '; 306 } 307 } else { 308 $string = $obj->name.' = '.$content."\n"; 309 } 310 break; 311 case 'section': 312 if (!$obj->isRoot()) { 313 $string = '['.$obj->name."]\n"; 314 } 315 if (count($obj->children) > 0) { 316 for ($i = 0; $i < count($obj->children); $i++) { 317 $string .= $this->toString($obj->getChild($i)); 318 } 319 } 320 break; 321 default: 322 $string = ''; 323 } 324 return $string; 325 } // end func toString 326 } // end class Config_Container_IniCommented 327 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 14:08:00 2007 | par Balluche grâce à PHPXref 0.7 |