php parse_ini_string() fix
<?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