Liam W
Liam W

Reputation: 1163

Using error_reporting with a string?

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

Upvotes: 2

Views: 987

Answers (3)

Elias Van Ootegem
Elias Van Ootegem

Reputation: 76397

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!

Upvotes: 3

MahanGM
MahanGM

Reputation: 2382

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.

Upvotes: 0

Moein Hosseini
Moein Hosseini

Reputation: 4383

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]);

Upvotes: -1

Related Questions