function array_key_search(&$search, $key, $replace = NULL) { if (isset($search[$key]) || array_key_exists($key, $search)) { if ($replace === NULL) { return $search[$key]; } else { $search[$key] = $replace; return true; } } foreach ($search as $k => $v) { if (is_array($v) && count($v) > 0) { return array_key_search($search[$k], $key, $replace); } } return false; }
/** * Iterates over an array containing PHP and handles calls to enabled functions and executes them. * @param {phpObj} array A JSON decoded array of representational PHP. * @return {*} Will return the results of the last function call passed in through phpObj. */ function parse_php_object($arr, $config) { // We define a pointer array that contains reference names to parameter placeholders // that will be replaced by real data. $pointers = array(); // We store a list of all PHP defined constants. We use this array to match against arguments // sent from JavaScript that will naturally be in string form but are intended to represent // constants. $constants = get_defined_constants(true); foreach ($arr as $k => $v) { // Create variable definition with our first level array keys ${$k} = $v; // Populate our pointers index $pointers[$k] = $k; // When a value is an object we attempt to call functions defined within if (is_object(${$k})) { // Convert our function object to an array $funcArr = (array) ${$k}; // Use the first key of the function array as our function name to call $func_name = array_keys($funcArr); $func_name = $func_name[0]; // Get the array of arguments to parse to our arguments array $func_args = $funcArr[$func_name]; // Create an array to store the arguments to pass to our function call $args_arr = array(); // Now we iterate over our function arguments looking for reference strings foreach ($func_args as $arg) { // We compare against the keys in our pointers index which was created above if (array_key_exists($arg, $pointers)) { // This is now a reference to ${$k}, the originally defined definition, the returned // result of the last sucessful function call $p = ${$arg}; // We push our arguments onto the args_array which will be passed to our function call array_push($args_arr, $p); } else { // We push our arguments onto the args_array which will be passed to our function call array_push($args_arr, $arg); } } // Create our final cleaned array $args_clean_arr = array(); // Iterate over function parameters foreach ($args_arr as $arg) { // Test if any function arguments are function calls themselves print $arg; if (function_exists($arg)) { } // At this point we test if a function argument is a literal. If it is we replace the // literal string with its value. if (is_string($arg)) { $constant = array_key_search($arg, $constants); if (isset($constant)) { $arg = $constant; } } array_push($args_clean_arr, $arg); } // Based on the security mode selected, use either our blacklist or whitelist. switch ($config['SEC_MODE']) { case 'blacklist': if (function_exists($func_name) && !in_array($func_name, $config['LISTS']['blacklist'])) { $function_allowed = true; } else { $function_allowed = false; } break; case 'whitelist': if (function_exists($func_name) && in_array($func_name, $config['LISTS']['whitelist'])) { $function_allowed = true; } else { $function_allowed = false; } break; } // Call the requested function if permitted if ($function_allowed === true) { // Reassign our variable the returned value of a function call so that further function calls can // search for the existence of pointers and then use the updated variable definitions. This logic // takes advantage of the procedural nature of PHP and the order of the sub-blocks in the php object. ${$k} = call_user_func_array($func_name, $args_clean_arr); } else { return "Function you requested {$func_name} has been disabled by backend configuration."; } } else { // Handle any recursive objects in arrays, cast them to arrays if (is_array(${$k})) { array_walk_recursive(${$k}, 'object_to_array'); } // Handle any type casting of arrays and objects if (json_decode(${$k}) !== NULL) { ${$k} = json_decode(${$k}); if (is_object(${$k})) { ${$k} = (array) ${$k}; } } } } // Return the returned result from our final function call return ${$k}; }
function array_key_search($needle, $haystack) { if (isset($haystack[$needle])) { return $haystack[$needle]; } else { foreach ($haystack as $key => $value) { if (is_array($value) && ($return = array_key_search($needle, $haystack))) { return $return; } } } return null; }