views:

505

answers:

5

It may sound strange, but in my PHP application I need to check if the same variable name has been declared more than once in the query string or POST variables, and return an error value if this is the case. If my application doesn't return an error in this case, it fails a compliance check.

When accessing vars using $_GET, $_POST, etc, PHP only returns the last value given for each variable name. I can't find a way to tell if any variable appeared more than once.

I simply need to find out if the query string or the variables in the POST body contained the same variable name more than once, whatever the values.

Example

My application is supposed to return an error for this query string:

verb=ListIdentifiers&metadataPrefix=oai_dc&metadataPrefix=oai_dc

Note that "metadataPrefix" is defined twice.

My application should not return an error for this query string:

verb=ListIdentifiers&metadataPrefix=oai_dc
A: 

If you expect multiple values named the variable with square brackets in the end. This way you get an array for that variable. If multiple values are set, the array will have multiple entries.

<input type="checkbox" name="my_var[]" value="a">
<input type="checkbox" name="my_var[]" value="b">

$_POST['my_var'] will be an array with either 'a' or 'b', both, or none depending on the checkboxes used.

mlemos
+6  A: 

POST Requests

$input = file_get_contents('php://input');

(Or $HTTP_RAW_POST_DATA (docs))

GET Requests

$input = $_SERVER['QUERY_STRING'];

Processing
explode('&', $input) and maintain an array - $foundKeys - of keys (the part of each item from explode() before the = character). If you hit a key already defined in $foundKeys, throw the error.

jensgram
Concerning the "Processing" part: If you known the possibly duplicated argument in advance - say: "metadataPrefix" - you can just look for several matches on "metadataPrefix=" in the beginning of each `explode()`'ed item.
jensgram
... or use `substr_count()` as proposed in @Christopher Nadeau's answer, eliminating the need to `explode()` in the first place :)
jensgram
thomasrutter
Then on each value in the array you can use list($name) = explode('=', $thisval) to get the part before the "=" sign
thomasrutter
+1  A: 

For GET data, check out $_SERVER['QUERY_STRING']. For POST data, you'll need to read the raw POST data from the php://input stream.

So something like this:

// GET data:
$raw = $_SERVER['QUERY_STRING'];

// Or for POST data:
// $raw = file_get_contents("php://input");

if (substr_count('&'.$raw, '&metadataPrefix=') > 1) die('Error');
Christopher Nadeau
A: 

PHP $_POST will always set only one value per variable unless the request variable name ends with [].

If you have no control over the variables that are sent, you may try using $_SERVER['RAW_HTTP_POST_DATA'] to get the original POST request data before parsed, then you can use the parse_str() function to parse that string.

Just be careful that PHP configuration may have disabled setting the RAW_HTTP_POST_DATA value. In that case, you cannot do anything to solve your problem.

mlemos
A: 

Not completely foolproof but this might work

$occurrences = substr_count($_SERVER['QUERY_STRING'], 'metadataPrefix=');
ChrisR