PHP sukcs.

Suppose you want to pass an argument in an URL, named openid.trust_root. Well, it's an actual name for an argument in OpenID 1.1, which will be passed via GET.

But what happens if gets passed to an php file? You get $_GET['openid.trust_root']?
Nooo... it would be too logical for php to just give us the name passed to an url. So what will we get? $_GET['openid_trust_root'].

Why?
Because we can't have $openid.trust_root (well, we can, but that's another thing). And why would we want such variable? Simply, we don't, but register_globals does. And php modifies name of the parameters to mantain compatibility with something deprecated as of PHP 5.3.0 and defaulting to off since PHP 4.2.0.

But how do I know that? Where to find such information?
Nowhere in the official documentation. Well, there is a description of what is changed in parameters' names (namely, that they're passed through urldecode), but it fails to mention the substitution from . to _. The information however is avaiable in a comment, quoting:

The full list of field-name characters that PHP converts to _ (underscore) is the following (not just dot): chr(32) ( ) (space) chr(46) (.) (dot) chr(91) ([) (open square bracket) chr(128) - chr(159) (various) PHP irreversibly modifies field names containing these characters in an attempt to maintain compatibility with the deprecated register_globals feature.

Of course, parse_str (which is used to parse query strings according to php's rules) behaves the same. At least it's consistent.

Again, php proved to be an illogical, and what's more important, annoying language. Too bad it's the most popular one for the web.

Comments:
Name:
Website (not required):
Text: