2

I am making a modification for a PHP software I use and I am wanting to allow users to enter a custom error reporting level, such as E_ALL & ~E_NOTICE.

The issue is that the value they specifiy is saved as a string - and therefore I cannot reference it in the error_reporting() function.

Is there anyway I could convert the string into the value needed by the error_reporting() function? I have already tried the constant() function, however it says that the constant cannot be found.

Liam

3
  • 3
    Why would anyone like to do that? Commented Mar 17, 2013 at 21:32
  • that's not an explanation. There is a chance you're doing something in a terribly wrong way Commented Mar 17, 2013 at 21:40
  • 3
    @LiamW - I agree with zerkms; that's a really bizarre thing to want to do. I can't imagine any use-case where it would be sensible. The only reason for displaying errors is to assist developers working on the site. Typically therefore, on a dev system, you'd display all the errors, and on a live system you'd hide them all. To debug a live system, you should really be using the error log instead, but even if you do have a setting to view the errors, it should be single debug mode, rather than an open-ended ability to change core PHP flags, because that has "security hole" written all over it. Commented Mar 17, 2013 at 21:41

3 Answers 3

3

AFAIK, the main reason why constant isn't working for you here is because the string 'E_ALL & ~E_NOTICE' isn't a constant, but it's two constants and some bitwise operators. So what you could do here is use the eval function. However... be careful, be very careful.

An other way of going at it is getting all constants used in the string. You could use a regular expression for this:

$string = 'E_ALL & ~E_NOTICE';
$intval = 0;
preg_match_all('/[A-Z_]+/',$string, $constants);
//$constants looks like: array(array('E_ALL', 'E_NOTICE'))
foreach ($constants[0] as $key => $const)
{
    //either converts them to their value
    $constants[0][$key] = constant($const);
    //or replace them in the initial string
    //you can do this using preg_replace_callback, too of course
    $string = replace($const, constant($const), $string);
}

If you choose to replace the constant names with their values, you can at least make sure you're passing a slightly more secure string to eval:

$string = preg_replace('/[^0-9&!|\^]/','',$string);//remove anything that isn't a number or bitwise operator.
error_reporting(eval($string));

However, if you don't want to use eval at all, you'll probably end up writing a switch in a function somewhere. That's not something I feel like doing for you, bit if you want to give it a shot:

//Get the constants
preg_match_all('/[A-Z_]/',$string,$constants);
//Get the bitwise operators
preg_match_all('[&|~^\s]', $string, $bitOps);

//eg:
$string= 'E_ALL& ~E_NOTICE ^FOOBAR';
//~~>
$constants = array( array ('E_ALL', 'E_NOTICE', 'FOOBAR'));
$bitops = array( array( ' & ~', ' ^'));//pay close attention to the spaces!

Conclusion/My opinion:
Why go through all this? It's slow, it's expensive, and insecure. A safer, simpler and easier solution IMHO would be to store the int value, instead of a string.
You want your clients to choose the error_reporting level (I can't see why...), why not create a select and give them a number of predefined options.

If you want to give them full control, allow them to use their own ini-file, but frankly: your goal should be to write your code in such a way that it runs under E_STRICT | E_ALL. If you do, there's not a lot of incentive to change error_reporting...
If you're allowing your clients to run their own code, and it's raising warnings or errors, please point out to them that they shouldn't suppress, but FIX them!

Sign up to request clarification or add additional context in comments.

1 Comment

Very nice solution. The script is vBulletin, which uses eval() too much anyway. Also, this would be a back end option.
0

I don't know about the splitting part but I think you're able to do something like this:

$level = NULL;

// Modifications
$level = E_ALL;
$level &= ~E_NOTICE;

error_reporting($level);

And with putting conditions you can add preferred constants to your variable.

Comments

-1

you can do it simply by array:

        $string = "E_ALL";
        $errorLevel = array("E_ALL"     => E_ALL,
                            "E_NOTICE"  => E_NOTICE,
                            "E_ERROR"   => E_ERROR,
                            "E_WARNING" => E_WARNING,
                            "E_PARSE"   => E_PARSE);
        error_reporting($errorLevel[$string]);

1 Comment

And how would you handle E_ALL & ~E_NOTICE input?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.