tags:

views:

617

answers:

9

I'm a beginner with PHP, I was exposed to processed HTML forms and I'm learning how to use it to do more and more...

I'm using this function (and based on Google so are a lot of people) but I really want to understand what it's doing....

function pt_register()
{
  $num_args = func_num_args();
   $vars = array();

   if ($num_args >= 2) {
       $method = strtoupper(func_get_arg(0));

       if (($method != 'SESSION') && ($method != 'GET') && ($method != 'POST') && ($method != 'SERVER') && ($method != 'COOKIE') && ($method != 'ENV')) {
           die('The first argument of pt_register must be one of the following: GET, POST, SESSION, SERVER, COOKIE, or ENV');
     }

       $varname = "HTTP_{$method}_VARS";
      global ${$varname};

       for ($i = 1; $i < $num_args; $i++) {
           $parameter = func_get_arg($i);

           if (isset(${$varname}[$parameter])) {
               global $$parameter;
               $$parameter = ${$varname}[$parameter];
          }

       }

   } else {
       die('You must specify at least two arguments');
   }

}

Can anyone walk through this in English for me?

+7  A: 

It looks like it's trying to be a replacement for register_globals

function pt_register()
{
  // Look at the arguments passed in...
  $num_args = func_num_args();
   $vars = array();

   // .. we need at least 2 arguments
   if ($num_args >= 2) {

        // $method is the middle part of name of one of PHPs old-style variables
       $method = strtoupper(func_get_arg(0));

       if (($method != 'SESSION') && ($method != 'GET') && ($method != 'POST') && ($method != 'SERVER') && ($method != 'COOKIE') && ($method != 'ENV')) {
           die('The first argument of pt_register must be one of the following: GET, POST, SESSION, SERVER, COOKIE, or ENV');
     }

      // $varname is the whole name of the variable
       $varname = "HTTP_{$method}_VARS";

      // Make the global variable (for example HTTP_SESSION_VARS) accessible from this function
      // ${$varname} is using a technique called "variable variables"
      // If $varname == "HTTP_SESSION_VARS" then $$varname (or ${$varname}) is the same as $HTTP_SESSION_VARS
      global ${$varname};

       // For each argument after the method
       for ($i = 1; $i < $num_args; $i++) {
           $parameter = func_get_arg($i);

        // If the parameter exists in the global variable...
           if (isset(${$varname}[$parameter])) {
            // .. make it global...
               global $$parameter;
         // ... and set its value
               $$parameter = ${$varname}[$parameter];
          }

       }

   } else {
       die('You must specify at least two arguments');
   }

}

So, a for example: pt_register('SESSION', 'foo'); does, in effect

function example()
{
    global $HTTP_SESSION_VARS;
    global $foo;
    $foo = $HTTP_SESSION_VARS['foo'];
}

IMHO, this script is outdated and evil! The superglobals $_SESSION etc mean you shouldn't be doing this

Greg
I was just typing the same and fully agree with you.
Energiequant
+1 for mentioning its evilness.
strager
Is this from the PEAR library?
MrChrister
+1 evil. DO. NOT. USE.
da5id
+1  A: 

It looks like it's extracting variables stored in arrays like $_POST and $_GET and making them global, so instead of accessing a post variable with $_POST['var'], you can just use $var. There isn't really a good reason for doing this, and it opens unnecessary security vulnerabilities if you forget to properly sanitize input. For example:

if (/* some condition */)
  $admin = true;

...

if ($admin)
{
  //do powerful stuff here
}

this could be broken by a malicious user calling the page with something like

page.php?admin=1
TenebrousX
+4  A: 

Ow my,
That looks like a code snipped that replaces the deprecated register_globals setting.

Back in PHP4, all kind over user generated arguments where directly created as variables in your normal variable scope.
In plain English this means that a call to index.php?test=helloWorld would result in

<?php
  echo "$test<br/>";
?>

outputting:

helloWorld<br/>

This is considered to be a mayor chance for programmers to shoot themselves in the foot. it has since been abolished. And for good reason.

Consider the following code:

<?php

if ( isAuthorised($userId, $sessionId) ) {
   $hasAccess = true;
}
// some lines
// of code...

if ( $hasAccess ) {
    echo 'sensitive information';
}

?>

and what whould happen if you would call this with index.php?hasAccess=1
That's right, the evil person calling your script has just gained access to the part that is for authorised users only.

In summary
It is a function that mimics the behaviour of functionality that is no longer used (since PHP5) because it was considered a major security risk.

Instead of using the code above, you should access the user supplied arguments like

<?php
    echo $_GET['test'].'<br />';
?>

Hope this helps :)

Jacco
A: 

I have absolutely no idea why one would want to use this function. It basically copies variables from the session, request or environment to the global namespace.

How are you using it? If you want to access form fields, use $_POST:

$value = $_POST['value'];

Instead of:

pt_register('POST', 'value');
Ferdinand Beyer
A: 

Basically this is a function to take variables out of the predefined global arrays $_SESSION, $_GET, $_POST, $_SERVER, $_COOKIE, and $_ENV and move them into global variables with equivalent names.

For example, if you loaded the page "test.php?value=5" you would normally access that through $_GET['value']. However, you can call:

pt_register('GET', 'value');

And this will create a global variable named $value set to 5. It accepts any number of arguments from the same global array, so for a page "test.php?value=5&another_value=6&yet_another_value=7" you could do:

pt_register('GET', 'value', 'another_value', 'yet_another_value');

To have $value, $another_value, and $yet_another_value all created and assigned to the values they were given in the URL.

As RoBorg said, it's doing a similar job to the old register_globals, but it gives you a little more control over which variables are set.

Chad Birch
A: 
function pt_register()
{
  $num_args = func_num_args(); // Get the number of arguments passed to this function
   $vars = array();

   if ($num_args >= 2) {
       $method = strtoupper(func_get_arg(0)); 
       // if the number of arguments is larger than or equal to 2, get the first one and make it uppercase, assign it to the varible $method

       if (($method != 'SESSION') && ($method != 'GET') && ($method != 'POST') && ($method != 'SERVER') && ($method != 'COOKIE') && ($method != 'ENV')) {
           die('The first argument of pt_register must be one of the following: GET, POST, SESSION, SERVER, COOKIE, or ENV');
     }
       // check if $method = GET, POST, SESSION, SERVER, COOKIE, or ENV' if not, die and kill the script 

       $varname = "HTTP_{$method}_VARS";
       /* assign the method to the var name
       * i.e. HTTP_GET_VARS, HTTP_POST_VARS etc
       */

      global ${$varname};
       // put the varible into the global varibles

       for ($i = 1; $i < $num_args; $i++) { // iterate through the arguments
           $parameter = func_get_arg($i);   // assign to parameter

           if (isset(${$varname}[$parameter])) { 
               // check if a parameter is set in the HTTP var array
               // i.e HTTP_GET_VARS[$parameter]
               global $$parameter;
               //assign the varible name of parameter to the varible name
               // say parameter was 'content', create a varible named 'content' and make it global
               $$parameter = ${$varname}[$parameter];
               // update the parameter to match its value in the HTTP vars array
               // i.e $content = HTTP_GET_VARS['content'];
          }

       }


   } else {
       die('You must specify at least two arguments');
   }

}
Jayrox
A: 

Too many useful answers to comment on all of them so I'll just answer my own questions with a big THANKS.

In my newer forms I wrote my own processing script with the format as suggest by Ferdinand.

$value = $_POST['value'];

I was looking at some older stuff, still in use, and was trying to figure out what it did, and why, to determine if I was taking an unsafe shortcut in my new code. In fact, the opposite is true and I need to update the old code to use the same approach as I use now... and whatever breaks needs to be fixed in some other way. The security issues of Globals are not lost on me.

It's very surprising that in 20 pages of Google results for "pt_register" I found TONS of people using the exact same function (I wonder where it originally came from) and no mention of it's inherent risks/evilness.

Thanks to everyone for the instantaneous answers and useful information. This site has a new fan.

HaArD
Alan Storm
+2  A: 

The folks who said it's a replacement for register globals are on the right track, but that's not quite what's going on.

Way back when dinosaurs roamed the internet, PHP didn't have $_POST, $_GET, $_COOKIE, $_SESSION, $_SERVER, $_ETC super globals. Instead (in addition to the infamous register globals) there were some regular global arrays named

$HTTP_GET_VARS
$HTTP_POST_VARS
$HTTP_SERVER_VARS
etc..

These arrays, in addition to having unweildy long names, needed to be declared global (i.e., they wern't "super/automatic globals like $_POST, $_GET, etc.) before being used.

What pt_regsiter does is allow you export an individual variable from one of these arrays into the global scope. So instead of writing

global   $HTTP_SERVER_VARS
global  $php_self;
$php_self = $HTTP_SERVER_VARS['PHP_SELF']

You could write.

pt_register('SERVER','PHP_SELF');

And you'd have a $php_self variable in the global scope.

Other's have already commented on the specific mechanics, so I'll close with saying it would be stupid to use this function today.

However, it looks like it originated in some GNU code back in 2002. Given that PHP3 was still in wide use (people were transitioning to PHP4), this function actually made sense.

Most of the coding patterns around PHP at the time relied havily on the global namespace to get things done. This function actually helped LIMIT problems with register_globals. According to the notes in the above link, the author wanted you to turn register_globals off, and the use this function to ONLY export those items you needed.

Evil? No. Incredibly stupid to use in this day and age? Yes

Alan Storm
A: 

It may originally have come from elsewhere, but it's included in code generated by phpFormGenerator.

Not sure if the latest version uses different code, but (many?) hosting companies still provide access to the old via Fantastico, which is why it's still widely found.