/** * Turns a query string into a dictionary * @param string $query_string * @return dict {<key>: <val>, <key2>: <val2>, ...} * * Since parse_str uses magic quotes and works by mutating an * existing array, this function is useful to get a noslashes * version of a fresh array, which is what we usually want. * */ function qs_vars($query_string) { $dict = array(); parse_str($query_string, $dict); $no_slashes_dict = array(); foreach ($dict as $key => $val) { $no_slashes_dict[$key] = noslashes($val); } return $no_slashes_dict; }
function _param_handle($source, $def, $prefix = null, &$scope = null) { extract(param_constants()); $_PARAM_NULLOK = $PARAM_UINT ^ $PARAM_SINT ^ $PARAM_FLOAT ^ $PARAM_BOOL ^ $PARAM_HEX; $errors = array(); // keep track of PARAM_ERROR failures if (!is_array($scope)) { $scope = $GLOBALS; } if (!is_array($def)) { _param_error('PARAM: invalid definition provided'); } foreach ($def as $var => $flags) { $sourcevar = $var; // var name in source if ($flags & $PARAM_HASHVAR && isset($GLOBALS['user'])) { $sourcevar = md5($user . $var . $GLOBALS['post_md5key']); } if (isset($source[$sourcevar])) { // do no change without accounting for $PARAM_EXISTS $ref = $source[$sourcevar]; // current var requested // raw param if ($flags & $PARAM_RAW) { $scope[$prefix . $var] = $ref; continue; } // support array type from forms if ($flags & $PARAM_ARRAY) { if (is_array($ref)) { foreach ($ref as $key => $r) { $ret = array(); // call param_handle recursively on each array element to validate value if (!_param_handle(array('a' => $r), array('a' => $flags & ~$PARAM_ARRAY), 'a_', $ret)) { // don't continue if there's a failure return false; } if (isset($ret['a_a'])) { $scope[$prefix . $var][$key] = $ret['a_a']; } } continue; } } if ($flags & $_PARAM_NULLOK) { if ($ref == '') { $scope[$prefix . $var] = null; continue; } } if ($flags & $PARAM_UINT) { // unsigned (non-negative integer) if (ctype_digit($ref) || is_int($ref)) { if ($flags & $PARAM_OBJID && !is_fbobj((int) $ref)) { _param_error("PARAM: invalid value for {$var}, expected OBJID. [{$ref}]", $var, $flags, $ref, $errors); } if ($flags & $PARAM_USERID && !is_user_id((int) $ref)) { _param_error("PARAM: invalid value for {$var}, expected USERID. [{$ref}]", $var, $flags, $ref, $errors); } $scope[$prefix . $var] = (int) $ref; } else { if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 7.0') !== false && preg_match('/[0-9]+[0-9a-f]{8}$/', $ref) == 1) { _param_fail(); // don't spew on detectible ie7b2 junk, a char hex is appended to int get var exit; } _param_error("PARAM: invalid content for {$var}, expected INT. [{$ref}]", $var, $flags, $ref, $errors); } } elseif ($flags & $PARAM_SINT) { // signed (negative ok integer) if (ctype_digit($ref) || is_int($ref)) { $scope[$prefix . $var] = (int) $ref; } else { if ($ref[0] == '-' && ctype_digit(substr($ref, 1))) { // allow negative numbers for int $scope[$prefix . $var] = (int) $ref; } else { if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 7.0') !== false && preg_match('/[0-9]+[0-9a-f]{8}$/', $ref) == 1) { _param_fail(); // don't spew on detectible ie7b2 junk, a char hex is appended to int get var exit; } _param_error("PARAM: invalid content for {$var}, expected INT. [{$ref}]", $var, $flags, $ref, $errors); } } } elseif ($flags & $PARAM_FLOAT) { if (preg_match('/^[0-9\\.]*$/i', $ref)) { $scope[$prefix . $var] = (double) $ref; } else { _param_error("PARAM: invalid content for {$var}, expected FLOAT. [{$ref}]", $var, $flags, $ref, $errors); } } elseif ($flags & $PARAM_BOOL) { switch (strtolower($ref)) { case '0': case '1': $scope[$prefix . $var] = (bool) $ref; break; case 'true': case 'on': case 'yes': $scope[$prefix . $var] = true; break; case 'false': case 'off': case 'no': $scope[$prefix . $var] = false; break; default: _param_error("PARAM: invalid content for {$var}, expected BOOL. [{$ref}]", $var, $flags, $ref, $errors); break; } } elseif ($flags & $PARAM_EXISTS) { // already passed isset above $scope[$prefix . $var] = true; } elseif ($flags & $PARAM_HEX) { if (ctype_xdigit($ref)) { // NOTE: (int) cast because hexdec can return a float if the hex // string is above INT_MAX. In those cases this will return 0, so // that is_int($result) will always be true if $result came from // $PARAM_HEX $scope[$prefix . $var] = (int) hexdec($ref); } else { _param_error("PARAM: invalid content for {$var}, expected HEX. [{$ref}]", $var, $flags, $ref, $errors); } } elseif ($flags & $PARAM_STRING) { if ($flags & $PARAM_MD5) { if (!url_checkmd5($GLOBALS['url_md5key'], $var)) { _param_error("PARAM: failed url_md5 check for {$var}.", $var, $flags, $ref, $errors); } } $ref = noslashes($ref); if ($flags & $PARAM_STRIPTAGS) { $allowtags = ''; if ($flags & $PARAM_ALLOW_A) { $allowtags .= '<a>'; } if ($flags & $PARAM_ALLOW_B) { $allowtags .= '<b>'; } $ref = strip_tags($ref, $allowtags); // entity protection if ($allowtags && strpos($ref, '=') !== false) { // is there an entitity we need to protect? // um, sorry this is ugly but should get most xss entities $exprs = array('/( on[a-z]{1,}|style|class|id|target)="(.*?)"/i', '/( on[a-z]{1,}|style|class|id|target)=\'(.*?)\'/i', '/( on[a-z]{1,}|style|class|id|target)=(.*?)( |>)/i', '/([a-z]{1,})="(( |\\t)*?)(javascript|vbscript|about):(.*?)"/i', '/([a-z]{1,})=\'(( |\\t)*?)(javascript|vbscript|about):(.*?)\'/i', '/([a-z]{1,})=(( |\\t)*?)(javascript|vbscript|about):(.*?)( |>)/i'); $reps = array('', '', '$3', '$1=""', '$1=""', '$1=""$6'); $ref = preg_replace($exprs, $reps, $ref); } } // strip out any \r characters. all we need is \n $ref = str_replace("\r", "", $ref); $scope[$prefix . $var] = (string) $ref; } elseif ($flags == 0) { error_log("PARAM: var ({$var}) has invalid type, undefined (0)"); return false; } } else { // exists in source if ($flags & $PARAM_EXISTS) { $scope[$prefix . $var] = false; } else { $scope[$prefix . $var] = null; } } } // each def if (count($errors) > 0) { // do any callbacks for PARAM_ERROR types foreach ($errors as $error) { // callback w/ params varname, flags, user entered value call_user_func_array('param_callback_error', $error); } } return true; }
// it is useful to verify these cookies' hashes so as to prevent // requests masquerading as an incorrect user. $user = 1240077; param_post(array('appid' => $PARAM_INT, 'query' => $PARAM_RAW, 'type' => $PARAM_INT, 'url' => $PARAM_STRING, 'fb_mockajax_context' => $PARAM_STRING, 'fb_mockajax_context_hash' => $PARAM_STRING)); $app_id = $post_appid; if (!$app_id) { error_log('No app_id specified in fbjs_ajax_proxy'); exit; } if (is_array($post_query)) { // PARAM_RAW needs noslashes $post_query = $post_query ? noslashes_recursive($post_query) : array(); } else { if ($post_query) { // PARAM_RAW needs noslashes $post_query = parse_querystring(noslashes($post_query)); } else { $post_query = array(); } } $FBJS_TYPES = array('RAW' => 0, 'JSON' => 1, 'FBML' => 2); function render_fbjs_ajax_fbml_recursive($impl, &$array) { foreach ($array as $key => $value) { if (substr($key, 0, 5) == 'fbml_') { $array[$key] = fbml_sample_parse($value, $impl); } else { if (is_array($value)) { render_fbjs_ajax_fbml_recursive($impl, $array[$key]); } }