views:

945

answers:

2

Hello, all SO users!

I have a bit of PHP code (for the module feature of my CMS (not drupal) which allows people to view pages, comments, forum posts, blog posts, etc...):

if(isset($_GET["m"]))
{
    //Does the module exist and activated, and has it a function called view?
    if(isset($module_exists[$_GET["m"]]) && method_exists($_GET["m"], "view"))//Yep
    {
     //Load view (should be an array)
     eval("$module_view = ".$_GET["m"]."::view();");
     if(!is_array($module_view))//Not an array :(
     {
      error::e500module($_GET["m"], $_SERVER["REQUEST_URI"]);
     }
    }
    else//Nope, so display error
    {
     error::e404($_SERVER['REQUEST_URI']);
    }
}

Now, I get this errors when parsing the page:

Notice: Undefined variable: module_view in C:\wamp\www\SYSTEM\start.php on line 34

Parse error: parse error in C:\wamp\www\SYSTEM\start.php(34) : eval()'d code on line 1

Notice: Undefined variable: module_view in C:\wamp\www\SYSTEM\start.php on line 35

But when I do:

eval("print_r(".$_GET["m"]."::view());");

instead of:

eval("$module_view = ".$_GET["m"]."::view();");

I don't get any error, but simply the array printed. Does anyone know what I do wrong? I don't understand it. Please don't tell me that eval() is not safe, I know.

Thanks.

+2  A: 

You should never do any eval. Here is the correct way to do this:

$class = $_GET["m"];
$module_view = $class::view();

But even here, you should have an array and check that $class is an authorized module before executing any code containing it, as it's user input and user input can't be trusted:

$class = $_GET["m"];
if (!in_array($class, $authorized_modules))
{
    header("HTTP/1.1 404 Not Found"); // always good to send a 404 in these cases, so search engines won't index the url
    die("Content not found");
}
$module_view = $class::view();

Just so you know, your error is because you have to escape your variable in the eval:

eval("\$module_view = ".$_GET["m"]."::view();");

Else it's evaluated before it's given as a string to the eval().

FWH
Thanx I didn't know that I must escape it.
Time Machine
The other option is to use single quotes instead.
Chacha102
But I like double quotes ;-)
Time Machine
I hate em, unexpected things happen with double quotes. Unexpected behavior = bad programming.
Chacha102
$class = $_GET["m"];$module_view = $class::view();does not work for me, it gives errors.
Time Machine
A: 

You could use call_user_func() instead of eval()

$module_view = call_user_func(array($_GET["m"], 'view'));

See the docs for the callback pseudo-type

Tom Haigh