php parse_ini_string() fix
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
php parse_ini_string() extension | |
With function below you can: | |
- fix unvalued fields ('key' (invalid) ==> 'key=' (OK) ) | |
- fix unquotted values with equal sign '=' ('key=value_part1=value_part2' ==> 'key="value_part1=value_part2"') | |
- fix (solve) multidimensional arrays (makes 'key[key1][key2]=value' valid) | |
- fix any reading errors (wrong lines, they may be later rawurldecoded with md5 checking) | |
*/ | |
function parse_ini_stringM($str, $process_sections = FALSE, $scanner_mode = INI_SCANNER_NORMAL) { | |
$str = explode("\n", | |
str_replace( | |
array("\r\n", "\n\r", "\r"), | |
array("\n".($rep['rn']=md5(rand().rand().rand()))."\n", | |
"\n".($rep['nr']=md5(rand().rand().rand()))."\n", | |
"\n".($rep['r']=md5(rand().rand().rand()))."\n"), | |
$str) | |
); | |
$rep['multi']=md5(rand().rand().rand()); | |
foreach ($str as &$line_) { | |
$line = explode('=', $line_, 2); | |
if ( (strpos($line_, "\0")!==FALSE) || ( (($tilde=strpos($line_, '~'))!==FALSE) && ($tilde<strpos($line_, '=')) ) ) { | |
// Fix reading errors! (wrong lines) | |
$line_ = str_replace('~', '%7e', rawurlencode($line_)).'='.md5($line_); // (tilde '~' may cause FALSE) | |
} else { | |
if ($line[0]!='') { | |
if (!isset($line[1])) { | |
// Fix unvalued options (e.g. 'key' ==> 'key=') | |
if ((!in_array($line[0], $rep, TRUE))&&(substr(trim($line[0]), 0, 1)!='[')) $line[1]=''; | |
} else { | |
$value = trim($line[1]); | |
// Fix unquotted strings (e.g. 'key=value' ==> 'key="value"') | |
//if (defined($value)) ; | |
//else if (is_numeric($value)) ; | |
//else | |
// Fix unquotted strings with equal sign '=' (e.g. 'key=value_part1=value_part2' ==> 'key="value_part1=value_part2"') | |
if (strpos($line[1],'=')!==FALSE) | |
if (($value!='')&&($value[0]!='"')&&($value[0]!="'")) $line[1]='"'.$line[1].'"'; | |
} | |
} | |
// Prepare multidimensional arrays: lock "multi-keys" (e.g. key[key1][key2][key3] ==> key[key1####key2####key3], where #### is delimiter string $rep['multi']) | |
$line[0]=preg_replace('/\]\s*\[/', $rep['multi'].md5(rand().rand().rand()), $line[0]); | |
$line = implode('=', $line); | |
// Last checking of this line | |
if (parse_ini_string("[a]\n".$line)===FALSE) { | |
$line_ = str_replace('~', '%7e', rawurlencode($line_)).'='.md5($line_); // (tilde '~' may cause FALSE) | |
} else $line_ = $line; | |
} | |
} | |
unset($line_); | |
$str = | |
str_replace( | |
array("\n".$rep['rn']."\n", "\n".$rep['nr']."\n", "\n".$rep['r']."\n"), | |
array("\r\n", "\n\r", "\r"), | |
implode("\n", $str) | |
); | |
// Parse prepared string | |
$str = parse_ini_string($str, $process_sections, $scanner_mode); | |
// Solve multidimensional arrays | |
foreach ($str as &$section) { | |
if (is_array($section)) { | |
foreach ($section as &$key) { | |
if (is_array($key)) { | |
// 2-dimensional array | |
foreach ($key as $multikey => $value) { | |
if (strpos($multikey, $rep['multi'])!==FALSE) { | |
// Multidimensional array - resolving ! | |
$mkey=-1;$line=$multikey;while (($mkey=strpos($line, $rep['multi'], $mkey+1))!==FALSE) $line=substr_replace($line, '', $mkey+32, 32); | |
$mkey = explode($rep['multi'], $line); | |
if (!function_exists('parse_ini_stringM_mult')) { | |
function parse_ini_stringM_mult($mkey /* key(s) to create */, $value /* final value */, &$key /* base */, $delimiter) { | |
//checking for "empty key" ( key[]=... ) and integers | |
if (trim($mkey[0])=='') $new=$key[$delimiter]+0; | |
elseif (ctype_digit(strval($mkey[0]))) $new=(int)$mkey[0]; // see http://php.net/manual/en/function.is-int.php#82857 and below, https://stackoverflow.com/questions/6416763/checking-if-a-variable-is-an-integer-in-php | |
if (isset($new)) $key[$delimiter]=$new+1; //setting (saving counter) for next "empty key" | |
else $new=$mkey[0]; | |
if (count($mkey)==1) $key[$new] = $value; | |
else { | |
if (!isset($key[$new])) $key[$new]=array(); | |
parse_ini_stringM_mult(array_slice($mkey, 1), $value, $key[$new], $delimiter); | |
} | |
} | |
} | |
parse_ini_stringM_mult($mkey, $value, $key, $rep['multi']); | |
unset($key[$multikey]); | |
} | |
} | |
// Removing key[$delimiter] (used as counter) | |
if (!function_exists('parse_ini_stringM_del')) { | |
function parse_ini_stringM_del(&$key, $delimiter) { | |
foreach ($key as $mkey => &$value) | |
if ($mkey===$delimiter) unset($key[$mkey]); | |
else if (is_array($value)) parse_ini_stringM_del($value, $delimiter); | |
else if (strpos($value, $delimiter)!==FALSE) $value=str_replace($delimiter, '', $value);// @TODO: checking int vs. string of int... | |
} | |
} | |
parse_ini_stringM_del($key, $rep['multi']); | |
} | |
} | |
unset($key); | |
} | |
} | |
unset($section); | |
return $str; | |
} | |
// ----------------------------------------------------- | |
// Example: | |
$ini = '[a] | |
%hello | |
b | |
c=d | |
e='; | |
var_export(parse_ini_string($ini, TRUE)); /* array ( | |
'a' => | |
array ( | |
'c' => 'd', | |
'e' => '', | |
), | |
) | |
*/ | |
$ini .= ' | |
f[g][2]=h | |
f[g][i]=j | |
f[g][][]=k | |
m=n=o | |
pq=r=s'.chr(1).chr(0).chr(255).' | |
f[g][[=t | |
' | |
.implode('',array_map('chr', range(0, 255))) | |
.' | |
pq=rs'.chr(1).chr(0).chr(255).' | |
u=~v | |
x=y~z | |
bye'; | |
var_export(parse_ini_string($ini, TRUE)); // false | |
var_export(parse_ini_stringM($ini, TRUE)); /* array ( | |
'a' => | |
array ( | |
'%hello' => '', | |
'b' => '', | |
'c' => 'd', | |
'e' => '', | |
'f' => | |
array ( | |
'g' => | |
array ( | |
2 => 'h', | |
'i' => 'j', | |
3 => | |
array ( | |
0 => 'k', | |
), | |
), | |
), | |
'm' => 'n=o', | |
'pq%3Dr%3Ds%01%00%FF' => '78eb5730c13ec3dc2ac1fc7500538994', | |
'f%5Bg%5D%5B%5B%3Dt' => 'b22e0e464a28518d270c7f446bc5923d', | |
'%00%01%02%03%04%05%06%07%08%09' => 'c56bd5480f6e5413cb62a0ad9666613a', | |
"\x0b\x0c" => '', | |
'%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D%7e%7F%80%81%82%83%84%85%86%87%88%89%8A%8B%8C%8D%8E%8F%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F%A0%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF%B0%B1%B2%B3%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF' => '1704281b8f7975a90eac3dec1916c364', | |
'pq%3Drs%01%00%FF' => '8c989cdc972a8c093f07d7acfd43dac5', | |
'u' => '-1', | |
'x%3Dy%7ez' => 'c5fb15f7ed0c5bca9dc8819b8b2c8918', | |
'bye' => '', | |
), | |
) | |
*/ | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment