1 <?php
2 /**
3 * @package FrameworkOnFramework
4 * @subpackage utils
5 * @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved.
6 * @license GNU General Public License version 2 or later; see LICENSE.txt
7 */
8
9 defined('FOF_INCLUDED') or die;
10
11 /**
12 * A utility class to parse INI files. This monstrosity is only required because some impossibly misguided individuals
13 * who misrepresent themselves as hosts have disabled PHP's parse_ini_file() function for "security reasons". Apparently
14 * their blatant ignorance doesn't allow them to discern between the innocuous parse_ini_file and the _potentially_
15 * dangerous ini_set functions, leading them to disable the former and let the latter enabled. In other words, THIS
16 * CLASS IS HERE TO FIX STUPID.
17 */
18 class FOFUtilsIniParser
19 {
20 /**
21 * Parse an INI file and return an associative array.
22 *
23 * @param string $file The file to process
24 * @param bool $process_sections True to also process INI sections
25 *
26 * @return array An associative array of sections, keys and values
27 */
28 public static function parse_ini_file($file, $process_sections, $rawdata = false)
29 {
30 $isMoronHostFile = !function_exists('parse_ini_file');
31 $isMoronHostString = !function_exists('parse_ini_string');
32
33 if ($rawdata)
34 {
35 if ($isMoronHostString)
36 {
37 return self::parse_ini_file_php($file, $process_sections, $rawdata);
38 }
39 else
40 {
41 return parse_ini_string($file, $process_sections);
42 }
43 }
44 else
45 {
46 if ($isMoronHostFile)
47 {
48 return self::parse_ini_file_php($file, $process_sections);
49 }
50 else
51 {
52 return parse_ini_file($file, $process_sections);
53 }
54 }
55 }
56
57 /**
58 * A PHP based INI file parser.
59 *
60 * Thanks to asohn ~at~ aircanopy ~dot~ net for posting this handy function on
61 * the parse_ini_file page on http://gr.php.net/parse_ini_file
62 *
63 * @param string $file Filename to process
64 * @param bool $process_sections True to also process INI sections
65 * @param bool $rawdata If true, the $file contains raw INI data, not a filename
66 *
67 * @return array An associative array of sections, keys and values
68 */
69 static function parse_ini_file_php($file, $process_sections = false, $rawdata = false)
70 {
71 $process_sections = ($process_sections !== true) ? false : true;
72
73 if (!$rawdata)
74 {
75 $ini = file($file);
76 }
77 else
78 {
79 $file = str_replace("\r", "", $file);
80 $ini = explode("\n", $file);
81 }
82
83 if (count($ini) == 0)
84 {
85 return array();
86 }
87
88 $sections = array();
89 $values = array();
90 $result = array();
91 $globals = array();
92 $i = 0;
93 foreach ($ini as $line)
94 {
95 $line = trim($line);
96 $line = str_replace("\t", " ", $line);
97
98 // Comments
99 if (!preg_match('/^[a-zA-Z0-9[]/', $line))
100 {
101 continue;
102 }
103
104 // Sections
105 if ($line{0} == '[')
106 {
107 $tmp = explode(']', $line);
108 $sections[] = trim(substr($tmp[0], 1));
109 $i++;
110 continue;
111 }
112
113 // Key-value pair
114 $lineParts = explode('=', $line, 2);
115 if (count($lineParts) != 2)
116 {
117 continue;
118 }
119 $key = trim($lineParts[0]);
120 $value = trim($lineParts[1]);
121 unset($lineParts);
122
123 if (strstr($value, ";"))
124 {
125 $tmp = explode(';', $value);
126 if (count($tmp) == 2)
127 {
128 if ((($value{0} != '"') && ($value{0} != "'")) ||
129 preg_match('/^".*"\s*;/', $value) || preg_match('/^".*;[^"]*$/', $value) ||
130 preg_match("/^'.*'\s*;/", $value) || preg_match("/^'.*;[^']*$/", $value)
131 )
132 {
133 $value = $tmp[0];
134 }
135 }
136 else
137 {
138 if ($value{0} == '"')
139 {
140 $value = preg_replace('/^"(.*)".*/', '$1', $value);
141 }
142 elseif ($value{0} == "'")
143 {
144 $value = preg_replace("/^'(.*)'.*/", '$1', $value);
145 }
146 else
147 {
148 $value = $tmp[0];
149 }
150 }
151 }
152 $value = trim($value);
153 $value = trim($value, "'\"");
154
155 if ($i == 0)
156 {
157 if (substr($line, -1, 2) == '[]')
158 {
159 $globals[$key][] = $value;
160 }
161 else
162 {
163 $globals[$key] = $value;
164 }
165 }
166 else
167 {
168 if (substr($line, -1, 2) == '[]')
169 {
170 $values[$i - 1][$key][] = $value;
171 }
172 else
173 {
174 $values[$i - 1][$key] = $value;
175 }
176 }
177 }
178
179 for ($j = 0; $j < $i; $j++)
180 {
181 if ($process_sections === true)
182 {
183 if (isset($sections[$j]) && isset($values[$j]))
184 {
185 $result[$sections[$j]] = $values[$j];
186 }
187 }
188 else
189 {
190 if (isset($values[$j]))
191 {
192 $result[] = $values[$j];
193 }
194 }
195 }
196
197 return $result + $globals;
198 }
199 }