PHP
downloads | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

pathinfo> <move_uploaded_file
Last updated: Fri, 05 Sep 2008

view this page in

parse_ini_file

(PHP 4, PHP 5)

parse_ini_fileParse a configuration file

Description

array parse_ini_file ( string $filename [, bool $process_sections ] )

parse_ini_file() loads in the ini file specified in filename , and returns the settings in it in an associative array.

The structure of the ini file is the same as the php.ini's.

Parameters

filename

The filename of the ini file being parsed.

process_sections

By setting the last process_sections parameter to TRUE, you get a multidimensional array, with the section names and settings included. The default for process_sections is FALSE

Return Values

The settings are returned as an associative array.

ChangeLog

Version Description
5.2.4 Keys and section names consisting of numbers are now evaluated as PHP integers thus numbers starting by 0 are evaluated as octals and numbers starting by 0x are evaluated as hexadecimals.
5.0.0 Values enclosed in double quotes can contain new lines.
4.2.1 This function is now affected by safe mode and open_basedir.

Examples

Example #1 Contents of sample.ini

; This is a sample configuration file
; Comments start with ';', as in php.ini

[first_section]
one = 1
five = 5
animal = BIRD

[second_section]
path = "/usr/local/bin"
URL = "http://www.example.com/~username"

Example #2 parse_ini_file() example

Constants may also be parsed in the ini file so if you define a constant as an ini value before running parse_ini_file(), it will be integrated into the results. Only ini values are evaluated. For example:

<?php

define
('BIRD''Dodo bird');

// Parse without sections
$ini_array parse_ini_file("sample.ini");
print_r($ini_array);

// Parse with sections
$ini_array parse_ini_file("sample.ini"true);
print_r($ini_array);

?>

The above example will output something similar to:

Array
(
    [one] => 1
    [five] => 5
    [animal] => Dodo bird
    [path] => /usr/local/bin
    [URL] => http://www.example.com/~username
)
Array
(
    [first_section] => Array
        (
            [one] => 1
            [five] => 5
            [animal] = Dodo bird
        )

    [second_section] => Array
        (
            [path] => /usr/local/bin
            [URL] => http://www.example.com/~username
        )

)

Notes

Note: This function has nothing to do with the php.ini file. It is already processed, the time you run your script. This function can be used to read in your own application's configuration files.

Note: If a value in the ini file contains any non-alphanumeric characters it needs to be enclosed in double-quotes (").

Note: There are reserved words which must not be used as keys for ini files. These include: null, yes, no, true, and false. Values null, no and false results in "", yes and true results in "1". Characters {}|&~![()" must not be used anywhere in the key and have a special meaning in the value.



pathinfo> <move_uploaded_file
Last updated: Fri, 05 Sep 2008
 
add a note add a note User Contributed Notes
parse_ini_file
david dot dyess at gmail dot com
04-Aug-2008 09:12
Here is another way to group values in the ini:

my.ini:

[singles]
test = a test
test2 = another test
test3 = this is a test too

[multiples]
tests[] = a test
tests[] = another test
tests[] = this is a test too

my.php:

$init = parse_ini_file('my.ini');

The same as:

$init['test'] = 'a test';
$init['test2'] = 'another test';
$init['test3'] = 'this is a test too';
$init['tests'][0] = 'a test';
$init['tests'][1] = 'another test';
$init['tests'][2] = 'this is a test too';

This works with the bool set to true also, can be useful with loops. Works with the bool set to true as well.
another_user at example dot com
25-Jul-2008 01:43
yarco dot w at gmail dot com:  Constants can be concatenated with strings, but the string segments must be enclosed in quotes.  Note to users, no joining symbol is used:

+++
; Start config.ini file here

output = "bla bla bla "TEST_TXT" bla bla bla"

; end
+++

<?php

define
("TEST_TXT","something something");
$the_array = parse_ini_file("/www/includes/config.ini");
echo
$the_array["output"];

?>

outputs...
bla bla bla something something bla bla bla
juampii_4 at hotmail dot com
10-Jul-2008 05:24
class.parseini.php
<?php
##By juan pablo tosso
class Parser
{

    public function
printini($file, $sector, $var)
    {
       
$file=$file.".ini";
       
$is=array();
       
$is= parse_ini_file($file, true);
       
trim($is);
        if(
is_array($is) && file_exists($file))
        {
            return
$is[$sector][$var];
        }else{
            return
"error";
        }
       
    }
   
   
}

?>

Ini.ini:
[test]
foo=bar

[test2]
foo1=bar1
foo2=bar2
foo bar=something else

just in another file write:

include("class.parseini.php");
$new= new Parser();
echo $new->printini("ini", "test2", "foo1");
tim {at} tim {hyphen} ryan {dot} com
02-Jul-2008 09:14
I whipped up an alternate, small (4kb) INI reader/writer class, implementing most of the features below:

 - [] array support
 - dot (.) notation heirarchies
 - sections (and non-section mode)
 - proper comment (;) parsing
 - parsing literal values (booleans, numbers, constants)
 - file reading/writing

Check it out here: http://tim-ryan.com/labs/parseINI/
asohn ~at~ aircanopy ~dot~ net
01-May-2008 12:27
Comments don't have to have an entire line dedicated to them. You can put a comment on the same line as a section or variable/value declaration and the built-in parse_ini_file() function will omit them. This being the case I took the liberty of revising goulven.ch AT gmail DOT com 's parse_ini() function. I also added the $process_sections argument to better reflect PHP's built-in parse_ini_file(). As soon as a semicolon is found in a line everything from that position to the end of the line is omitted so as to not become part of the value. However, any semicolon found that occurs between a single-quote or double-quote will be left alone to become part of the value.

<?php
function _parse_ini_file($file, $process_sections = false) {
 
$process_sections = ($process_sections !== true) ? false : true;

 
$ini = file($file);
  if (
count($ini) == 0) {return array();}

 
$sections = array();
 
$values = array();
 
$result = array();
 
$globals = array();
 
$i = 0;
  foreach (
$ini as $line) {
   
$line = trim($line);
   
$line = str_replace("\t", " ", $line);

   
// Comments
   
if (!preg_match('/^[a-zA-Z0-9[]/', $line)) {continue;}

   
// Sections
   
if ($line{0} == '[') {
     
$tmp = explode(']', $line);
     
$sections[] = trim(substr($tmp[0], 1));
     
$i++;
      continue;
    }

   
// Key-value pair
   
list($key, $value) = explode('=', $line, 2);
   
$key = trim($key);
   
$value = trim($value);
    if (
strstr($value, ";")) {
     
$tmp = explode(';', $value);
      if (
count($tmp) == 2) {
        if (((
$value{0} != '"') && ($value{0} != "'")) ||
           
preg_match('/^".*"\s*;/', $value) || preg_match('/^".*;[^"]*$/', $value) ||
           
preg_match("/^'.*'\s*;/", $value) || preg_match("/^'.*;[^']*$/", $value) ){
         
$value = $tmp[0];
        }
      } else {
        if (
$value{0} == '"') {
         
$value = preg_replace('/^"(.*)".*/', '$1', $value);
        } elseif (
$value{0} == "'") {
         
$value = preg_replace("/^'(.*)'.*/", '$1', $value);
        } else {
         
$value = $tmp[0];
        }
      }
    }
   
$value = trim($value);
   
$value = trim($value, "'\"");

    if (
$i == 0) {
      if (
substr($line, -1, 2) == '[]') {
       
$globals[$key][] = $value;
      } else {
       
$globals[$key] = $value;
      }
    } else {
      if (
substr($line, -1, 2) == '[]') {
       
$values[$i-1][$key][] = $value;
      } else {
       
$values[$i-1][$key] = $value;
      }
    }
  }

  for(
$j = 0; $j < $i; $j++) {
    if (
$process_sections === true) {
     
$result[$sections[$j]] = $values[$j];
    } else {
     
$result[] = $values[$j];
    }
  }

  return
$result + $globals;
}
?>

usage regarding semicolons:
<?php
;sample.ini

variable1  
= v1;v1
variable 2 
= "v2;v2"
variable_3  = "v3;v3;v3"
variable4   = "v4;v4" ;v4
variable 5 
= "v5;v5;v5" ;v5
variable_6 
= "v6;v6" ;v6;;
variable7   = "v7;;v7"
variable 8  = 'v8;v8'
variable_9  = 'v9;v9;v9'
variable10  = 'v10;v10' ;v10
variable 11
= 'v11;v11;v11' ;v11
variable_12
= 'v12;v12' ;v2;;
variable13  = 'v13;;v13'
variable 14 = "v14
variable_15 = 'v15
variable16  = "
v16;v16
variable 17
= 'v17;v17
?>
<?php
//example.php
print_r(_parse_ini_file("sample.ini"));
?>
<?php
//example.php output
Array
(
    [variable1] => v1
    [variable 2] => v2;v2
    [variable_3] => v3;v3;v3
    [variable4] => v4;v4
    [variable 5] => v5;v5;v5
    [variable_6] => v6;v6
    [variable7] => v7;;v7
    [variable 8] => v8;v8
    [variable_9] => v9;v9;v9
    [variable10] => v10;v10
    [variable 11] => v11;v11;v11
    [variable_12] => v12;v12
    [variable13] => v13;;v13
    [variable 14] => v14
    [variable_15] => v15
    [variable16] => v16
    [variable 17] => v17
)
?>
goulven.ch AT gmail DOT com
29-Oct-2007 03:33
Warning: parse_ini_files cannot cope with values containing the equal sign (=).

The following function supports sections, comments, arrays, and key-value pairs outside of any section.
Beware that similar keys will overwrite one another (unless in different sections).

<?php
function parse_ini ( $filepath ) {
   
$ini = file( $filepath );
    if (
count( $ini ) == 0 ) { return array(); }
   
$sections = array();
   
$values = array();
   
$globals = array();
   
$i = 0;
    foreach(
$ini as $line ){
       
$line = trim( $line );
       
// Comments
       
if ( $line == '' || $line{0} == ';' ) { continue; }
       
// Sections
       
if ( $line{0} == '[' ) {
           
$sections[] = substr( $line, 1, -1 );
           
$i++;
            continue;
        }
       
// Key-value pair
       
list( $key, $value ) = explode( '=', $line, 2 );
       
$key = trim( $key );
       
$value = trim( $value );
        if (
$i == 0 ) {
           
// Array values
           
if ( substr( $line, -1, 2 ) == '[]' ) {
               
$globals[ $key ][] = $value;
            } else {
               
$globals[ $key ] = $value;
            }
        } else {
           
// Array values
           
if ( substr( $line, -1, 2 ) == '[]' ) {
               
$values[ $i - 1 ][ $key ][] = $value;
            } else {
               
$values[ $i - 1 ][ $key ] = $value;
            }
        }
    }
    for(
$j=0; $j<$i; $j++ ) {
       
$result[ $sections[ $j ] ] = $values[ $j ];
    }
    return
$result + $globals;
}
?>

Example usage:
<?php
$stores
= parse_ini('stores.ini');
print_r( $stores );
?>

An example ini file:
<?php
/*
;Commented line start with ';'
global_value1 = a string value
global_value1 = another string value

; empty lines are discarded
[Section1]
key = value
; whitespace around keys and values is discarded too
otherkey=other value
otherkey=yet another value
; this key-value pair will overwrite the former.
*/
?>
www.onphp5.com
24-Oct-2007 10:26
Looks like in PHP 5.3.0 special characters like \n are extrapolated into real newlines. Gotta use \\n.
arnapou
03-Oct-2007 03:51
I didn't find a simple ini class so I wrote that class to read and write ini files.
I hope it could help you.

Read file : $ini = INI::read('myfile.ini');
Write file : INI::write('myfile.ini', $ini);

Features :
- support [] syntax for arrays
- support . in keys like bar.foo.something = value
- true and false string are automatically converted in booleans
- integers strings are automatically converted in integers
- keys are sorted when writing
- constants are replaced but they should be written in the ini file between braces : {MYCONSTANT}

<?php

class INI {
   
/**
     *  WRITE
     */
   
static function write($filename, $ini) {
       
$string = '';
        foreach(
array_keys($ini) as $key) {
           
$string .= '['.$key."]\n";
           
$string .= INI::write_get_string($ini[$key], '')."\n";
        }
       
file_put_contents($filename, $string);
    }
   
/**
     *  write get string
     */
   
static function write_get_string(& $ini, $prefix) {
       
$string = '';
       
ksort($ini);
        foreach(
$ini as $key => $val) {
            if (
is_array($val)) {
               
$string .= INI::write_get_string($ini[$key], $prefix.$key.'.');
            } else {
               
$string .= $prefix.$key.' = '.str_replace("\n", "\\\n", INI::set_value($val))."\n";
            }
        }
        return
$string;
    }
   
/**
     *  manage keys
     */
   
static function set_value($val) {
        if (
$val === true) { return 'true'; }
        else if (
$val === false) { return 'false'; }
        return
$val;
    }
   
/**
     *  READ
     */
   
static function read($filename) {
       
$ini = array();
       
$lines = file($filename);
       
$section = 'default';
       
$multi = '';
        foreach(
$lines as $line) {
            if (
substr($line, 0, 1) !== ';') {
               
$line = str_replace("\r", "", str_replace("\n", "", $line));
                if (
preg_match('/^\[(.*)\]/', $line, $m)) {
                   
$section = $m[1];
                } else if (
$multi === '' && preg_match('/^([a-z0-9_.\[\]-]+)\s*=\s*(.*)$/i', $line, $m)) {
                   
$key = $m[1];
                   
$val = $m[2];
                    if (
substr($val, -1) !== "\\") {
                       
$val = trim($val);
                       
INI::manage_keys($ini[$section], $key, $val);
                       
$multi = '';
                    } else {
                       
$multi = substr($val, 0, -1)."\n";
                    }
                } else if (
$multi !== '') {
                    if (
substr($line, -1) === "\\") {
                       
$multi .= substr($line, 0, -1)."\n";
                    } else {
                       
INI::manage_keys($ini[$section], $key, $multi.$line);
                       
$multi = '';
                    }
                }
            }
        }
       
       
$buf = get_defined_constants(true);
       
$consts = array();
        foreach(
$buf['user'] as $key => $val) {
           
$consts['{'.$key.'}'] = $val;
        }
       
array_walk_recursive($ini, array('INI', 'replace_consts'), $consts);
        return
$ini;
    }
   
/**
     *  manage keys
     */
   
static function get_value($val) {
        if (
preg_match('/^-?[0-9]$/i', $val)) { return intval($val); }
        else if (
strtolower($val) === 'true') { return true; }
        else if (
strtolower($val) === 'false') { return false; }
        else if (
preg_match('/^"(.*)"$/i', $val, $m)) { return $m[1]; }
        else if (
preg_match('/^\'(.*)\'$/i', $val, $m)) { return $m[1]; }
        return
$val;
    }
   
/**
     *  manage keys
     */
   
static function get_key($val) {
        if (
preg_match('/^[0-9]$/i', $val)) { return intval($val); }
        return
$val;
    }
   
/**
     *  manage keys
     */
   
static function manage_keys(& $ini, $key, $val) {
        if (
preg_match('/^([a-z0-9_-]+)\.(.*)$/i', $key, $m)) {
           
INI::manage_keys($ini[$m[1]], $m[2], $val);
        } else if (
preg_match('/^([a-z0-9_-]+)\[(.*)\]$/i', $key, $m)) {
            if (
$m[2] !== '') {
               
$ini[$m[1]][INI::get_key($m[2])] = INI::get_value($val);
            } else {
               
$ini[$m[1]][] = INI::get_value($val);
            }
        } else {
           
$ini[INI::get_key($key)] = INI::get_value($val);
        }
    }
   
/**
     *  replace utility
     */
   
static function replace_consts(& $item, $key, $consts) {
        if (
is_string($item)) {
           
$item = strtr($item, $consts);
        }
    }
}

?>
thuylnt
26-Sep-2007 11:09
I need to read a ini file, modify some values in some sections, and save it. But the important thing is, i want to keep all the comments, the new lines in the right order. So i modified function parse_ini_file_quotes_safe and write_ini_file.
I think they work fine.

    function read_ini_file($f, &$r)
    {
        $null = "";
        $r=$null;
        $first_char = "";
        $sec=$null;
        $comment_chars=";#";
        $num_comments = "0";
        $num_newline = "0";

        //Read to end of file with the newlines still attached into $f
        $f = @file($f);
        if ($f === false) {
            return -2;
        }
        // Process all lines from 0 to count($f)
        for ($i=0; $i<@count($f); $i++)
        {
            $w=@trim($f[$i]);
            $first_char = @substr($w,0,1);
            if ($w)
            {
                if ((@substr($w,0,1)=="[") and (@substr($w,-1,1))=="]") {
                    $sec=@substr($w,1,@strlen($w)-2);
                    $num_comments = 0;
                    $num_newline = 0;
                }
                else if ((stristr($comment_chars, $first_char) == true)) {
                    $r[$sec]["Comment_".$num_comments]=$w;
                    $num_comments = $num_comments +1;
                }               
                else {
                    // Look for the = char to allow us to split the section into key and value
                    $w=@explode("=",$w);
                    $k=@trim($w[0]);
                    unset($w[0]);
                    $v=@trim(@implode("=",$w));
                    // look for the new lines
                    if ((@substr($v,0,1)=="\"") and (@substr($v,-1,1)=="\"")) {
                        $v=@substr($v,1,@strlen($v)-2);
                    }
                   
                    $r[$sec][$k]=$v;
                   
                }
            }
            else {
                $r[$sec]["Newline_".$num_newline]=$w;
                $num_newline = $num_newline +1;
            }
        }
        return 1;
    }

    function write_ini_file($path, $assoc_arr) {
        $content = "";

        foreach ($assoc_arr as $key=>$elem) {
            if (is_array($elem)) {
                if ($key != '') {
                    $content .= "[".$key."]\r\n";                   
                }
               
                foreach ($elem as $key2=>$elem2) {
                    if ($this->beginsWith($key2,'Comment_') == 1 && $this->beginsWith($elem2,';')) {
                        $content .= $elem2."\r\n";
                    }
                    else if ($this->beginsWith($key2,'Newline_') == 1 && ($elem2 == '')) {
                        $content .= $elem2."\r\n";
                    }
                    else {
                        $content .= $key2." = ".$elem2."\r\n";
                    }
                }
            }
            else {
                $content .= $key." = ".$elem."\r\n";
            }
        }

        if (!$handle = fopen($path, 'w')) {
            return -2;
        }
        if (!fwrite($handle, $content)) {
            return -2;
        }
        fclose($handle);
        return 1;
    }

    function beginsWith( $str, $sub ) {
        return ( substr( $str, 0, strlen( $sub ) ) === $sub );
    }
yarco dot w at gmail dot com
29-Jun-2007 10:46
parse_ini_file can't deal with const which cancate a string. For example, if test.ini file is

classPath = ROOT/lib

If you:
<?php
define
('ROOT', dirname(__FILE__));

$buf = parse_ini_file('test.ini');
?>

const ROOT would't be parsed.

But my version could work find.

<?php
// array parse_ini_file ( string $filename [, bool $process_sections] )
function parse_ini($filename, $process_sections = false)
{
  function
replace_process(& $item, $key, $consts)
  {
   
$item = str_replace(array_keys($consts), array_values($consts), $item);
  }

 
$buf = get_defined_constants(true); // PHP version > 5.0
 
$consts = $buf['user'];
 
$ini = parse_ini_file($filename, $process_sections);

 
array_walk_recursive($ini, 'replace_process', $consts);
  return
$ini;
}

define('ROOT', '/test');
print_r(parse_ini(dirname(__FILE__).'/test.ini'));

?>
Adam
25-Jun-2007 07:45
Arrays can be defined in the ini file by adding '[]' at the end of a key name. For example:

value1 = 17
value2 = 13

value3[] = a
value3[] = b
value3[] = c

Will return:
Array
(
    [value1] => 17
    [value2] => 13
    [value3] => Array
        (
            [0] => a
            [1] => b
            [2] => c
        )
)
Mildred
25-May-2007 09:42
I wrote few functions to work with ini files.

The function make_ini_file($array, &$errors)
The function read_ini($file)
The function prepare_ini($array, $maxdepth=NULL)

The function prepare_ini($array, $maxdepth=NULL)
This function will take an array as returned by the function read_ini() and will return an array as needed by the function make_ini_file() so that you can write extanded ini files easily.
If maxdepth is not given (or if maxdepth is NULL), this function will try to create sections so the keys in the sections do not have dots. if maxdepth is given, it will create sections with $maxdepth members in them (or less if it is not possible). It won't use the special key name "."

<?php

function prepare_ini($arr, $maxdepth=NULL){
   
$res = array();
   
prepare_ini__1($res, $arr, $maxdepth);
    return
$res;
}

function
prepare_ini__1(
    &
$res, $arr, $maxdepth,
   
$prefix1="", $prefix2="", $depth=0,
   
$self='prepare_ini__1')
{
    foreach(
$arr as $key=>$val){
        if(
is_array($val)){
            if(
is_null($maxdepth) or $depth < $maxdepth){
               
$newprefix = $prefix1 ? "$prefix1.$key" : $key;
               
$self($res, $val, $maxdepth, $newprefix, $prefix2, $depth+1);
            }else{
               
$newprefix = $prefix2 ? "$prefix1.$key" : $key;
               
$self($res, $val, $maxdepth, $prefix1, $newprefix, $depth+1);
            }
        }else{
           
$newprefix = $prefix2 ? "$prefix2.$key" : $key;
            if(!isset(
$res[$prefix1])) $res[$prefix1] = array();
           
$res[$prefix1][$newprefix] = $val;
        }
    }
}

// kate: indent-width 4; tab-width 8; space-indent on;
// kate: replace-tabs off; remove-trailing-space on;
?>
mark at hostcobalt dot com
27-Mar-2007 10:39
or to prevent the file being viewed you can just use a .htaccess file and add this line

<files *.ini>
order deny,allow
deny from all
</files>

i use a similar thing to prevent my config files being accessed
mhall at lakeland dot net
02-Feb-2007 07:22
I modified phpcoder's readINIFile function to allow multi-lined values. Adding a backslash (\) to the end of a line indicates that the whole of the next line should be appended to the value.  Leading whitespace is ignored on continues lines, whitespace before the backslash is preserved. This is the same as the Java Properties spec: http://java.sun.com/j2se/1.4.2/docs/api/java/util/Properties.html

<?php
function readINIfile ($filename, $commentchar) {
 
$array1 = file($filename);
 
$section = '';
  for (
$line_num = 0; $line_num <= sizeof($array1); $line_num++) {
  
$filedata = $array1[$line_num];
  
$dataline = trim($filedata);
  
$firstchar = substr($dataline, 0, 1);
   if (
$firstchar!=$commentchar && $dataline!='') {
    
//It's an entry (not a comment and not a blank line)
    
if ($firstchar == '[' && substr($dataline, -1, 1) == ']') {
      
//It's a section
      
$section = strtolower(substr($dataline, 1, -1));
     }else{
      
//It's a key...
      
$delimiter = strpos($dataline, '=');
       if (
$delimiter > 0) {
        
//...with a value
        
$key = strtolower(trim(substr($dataline, 0, $delimiter)));
        
$array2[$section][$key] = '';
        
$value = trim(substr($dataline, $delimiter + 1));
         while (
substr($value, -1, 1) == '\\') {
            
//...value continues on the next line
            
$value = substr($value, 0, strlen($value)-1);
            
$array2[$section][$key] .= stripcslashes($value);
            
$line_num++;
            
$value = trim($array1[$line_num]);
         }
        
$array2[$section][$key] .= stripcslashes($value);
        
$array2[$section][$key] = trim($array2[$section][$key]);
         if (
substr($array2[$section][$key], 0, 1) == '"' && substr($array2[$section][$key], -1, 1) == '"') {
           
$array2[$section][$key] = substr($array2[$section][$key], 1, -1);
         }
       }else{
        
//...without a value
        
$array2[$section][strtolower(trim($dataline))]='';
       }
     }
   }else{
    
//It's a comment or blank line.  Ignore.
  
}
  }
  return
$array2;
}
?>
fantasysportswire at yahoo dot com
03-Jan-2007 04:54
The ahull version of the parse_ini_file_quotes_safe can not handle unicode... the original version from Julio L Garbayo can.
ant at loadtrax dot com
15-Nov-2006 06:09
A number of posts mention using pear::Config as a replacement for this function. Note however that internally it uses parse_ini_file to read the ini file, so it suffers from the same limitations.
Justin Hall
31-Oct-2006 08:46
This is a simple (but slightly hackish) way of avoiding the character limitations (in values):

<?php
define
('QUOTE', '"');
$test = parse_ini_file('test.ini');

echo
"<pre>";
print_r($test);
?>

contents of test.ini:

park yesterday = "I (walked) | {to} " QUOTE"the"QUOTE " park yesterday & saw ~three~ dogs!"

output:

<?php
Array
(
    [
park yesterday] => I (walked) | {to} "the" park yesterday & saw ~three~ dogs!
)
?>
23-Oct-2006 11:16
this function won't parse a remote INI file, even with allow_url_fopen turned on.
judas dot iscariote at gmail dot com
01-Oct-2006 09:26
If you are looking for an OOP way to parse ini files, take a look at Marcus Boerger's  IniGroups  class available here :

http://www.php.net/~helly/php/ext/spl/classIniGroups.html
parksto at gmail dot com
18-Sep-2006 02:46
or better

on first line :
;<?php exit(' you won\'t see my ini file'); ?>
19-Apr-2006 09:45
upgrade of "mauder[remove] at [remove]gmail[remove] dot com" idea of hiding ini content from being seen.

file.ini.php

first line:
;<?/*

last line:
;*/
?>

will result ";" in browser, not "pharse error: (...)".
sam at viveka dot net dot au
24-Mar-2006 05:27
In addition to the note that "Parsing an ini file stops at a key named 'none'".

Values of 'none' do not return as the string 'none'. They return nothing at all, however this does not halt the processing of the ini file.
tertillian at yahoo dot com
22-Feb-2006 02:12
I ran into a snag where I wanted to have an INI file for a library. All attempts to parse the file from the library, apart from hardcoded path qualification, failed because it couldn't find the INI file. Some of the php functions will optionally use the include path. Adding this to the parse_ini_file() function would permit its use in this way and would encourage not putting INI files in document root.
nbraczek at bsds dot de
16-Feb-2006 01:29
Beside the mentioned reserved words 'null', 'yes', 'no', 'true', and 'false', also 'none' seems to be a reserved word. Parsing an ini file stops at a key named 'none'.
mauder[remove] at [remove]gmail[remove] dot com
14-Feb-2006 01:31
Be careful if you put any .ini file in your readable directories, if somebody would know the name (e.g. if your application is widely used), the webserver might return it as plain text.

For example : your database username and password could be exposed, if it is stored in that file !

To prevent this from happening :
- give the file .php extension :  "my.ini.php"
- put ';<?php' (without quotes and without X between X and php) on first line
- put '
;?>' on last line

The server would run the ini file as being PHP-code, but will do nothing due to bad syntax, preventing the content from being exosed.
On the other hand, it is still a valid .ini file...

HTH !
ahull at clydemarine dot com
26-Jan-2006 10:33
I had a look at the code for function parse_ini_file_quotes_safe(
and added in the ability to preserve comments.

<?php
// Parse a file into an array following the rules for ini files as follows
//
// Looks for [] characters to mark section headings and = chars to mark the break between the key and its values.
// Also keeps comments delimited by any of the characters in $comments_chars in the array numbered as they are found.
//
// Note writing back the array will necessarily move the comments to the beginning of the section,
// even if they are found within
// a section simply because there is no exact place-holder information stored in the array.
// This could of course be a problem.
// Also the Write array routine will have to be modified
// to correctly write back comments otherwise they will appear as blank sections called [comment{x}]

function parse_ini_file_quotes_safe($f)
{
 
$newline = "<br>";
 
$null = "";
 
$r=$null;
 
$first_char = "";
 
$sec=$null;
 
$comment_chars="/*<;#?>";
 
$num_comments = "0";
 
$header_section = "";

 
//Read to end of file with the newlines still attached into $f
 
$f=@file($f);
 
// Process all lines from 0 to count($f)
 
for ($i=0;$i<@count($f);$i++)
 {
 
$newsec=0;
 
$w=@trim($f[$i]);
 
$first_char = @substr($w,0,1);
  if (
$w)
  {
   if ((!
$r) or ($sec))
   {
  
// Look for [] chars round section headings
  
if ((@substr($w,0,1)=="[") and (@substr($w,-1,1))=="]") {$sec=@substr($w,1,@strlen($w)-2);$newsec=1;}
  
// Look for comments and number into array
  
if ((stristr($comment_chars, $first_char) === FALSE)) {} else {$sec=$w;$k="Comment".$num_comments;$num_comments = $num_comments +1;$v=$w;$newsec=1;$r[$k]=$v;echo "comment".$w.$newline;}
  
//
  
}
   if (!
$newsec)
   {
  
//
   // Look for the = char to allow us to split the section into key and value
  
$w=@explode("=",$w);$k=@trim($w[0]);unset($w[0]); $v=@trim(@implode("=",$w));
  
// look for the new lines
  
if ((@substr($v,0,1)=="\"") and (@substr($v,-1,1)=="\"")) {$v=@substr($v,1,@strlen($v)-2);}
   if (
$sec) {$r[$sec][$k]=$v;} else {$r[$k]=$v;}
   }
  }
 }
 return
$r;
}

?>
dewi at morganalley dot net
21-Oct-2005 08:45
[A feature request for a third parameter, to turn off the following insecure behaviour has been submitted: http://bugs.php.net/bug.php?id=34949 - I'm just documenting it here so that people are aware that they need to take the insecurity of the current behaviour into consideration when programming.]

Be warned that, in its current (2-argument) form, this function should be avoided when processing user-provided ini files, as data leakage may occur if the user provides an ini file with unquoted string values.

To avoid this problem, it's vital that if your program stores any sensitive data in constants, that you either pre-scan the ini file for unquoted strings, or that you do not use this function.

A suitable pre-parse parser might be as follows.

This assumes that there are no non-word (a-zA-Z0-9_) characters in your keys, and minimises whitespace.

It tries to convert intelligently, like so:
   value1 = value  ; this is a comment
   value2 = value; with semicolon in
to
   value1 = "value"  ; this is a comment
   value2 = "value; with semicolon in"

<?php
$file
= file_get_contents('user_provided.ini');

$file2 = preg_replace('/^
(\s*\w+\s*=\s*)        # Part \1 - the key and initial whitespace.
(                      # Part \2 - the value to be quoted
  (?:(?!\s;)[^"\r\n])  # Anything but \r, ", \s;, \n
         *?            # As little as possible of that, minimise whitespace.
)
(                      # Part \3 - everything after the value
  \s*                  # Optional whitespace.
  (?:\s;.*)?           # Optional comment preceded by a space
)
$/mx'
, '\1"\2"\3', $file);

file_put_contents('user_provided.ini2', $file2);
?>
Julio López Garbayo <sinedeo at gmail dot com>
22-Sep-2005 10:53
I wrote a replacement function with following changes:
-It allows quotes and double quotes.
-It detects wether your .ini file has sections or not.
-It will read until eof in any case, even if a line contains errors.

I know it can be improved a lot, so feel free to work on it and, please, notify me if you do.

<?php
function parse_ini_file_quotes_safe($f)
{
 
$r=$null;
 
$sec=$null;
 
$f=@file