views:

70

answers:

2

I have a variable named $data["main_deal"] that has the value $xml->deals->deal[0] (as a string). $xml is a simpleXML object, and the value of main_deal is the selector needed to access the data I want.

When I tried echo "<p><b>Main Deal:</b> ".$data["main_deal"]; it output: Main Deal: $xml->deals->deal[0]

So I went back to where I gave $data["main_deal"] its value, and added eval(). The output is now blank. When I call $data["main_deal"], I want it to output the value of $xml->deals->deal[0], not "$xml->deals->deal[0]". How do I do this?

EDIT: Here is the code I am using to load $data:

foreach($vars as $var) {
$data[$var] = $devOptions[$var];
}

$devOptions[$var] holds a string such as "$xml->deals->deal[0]".

+1  A: 
eval('return '.$data['main_deal'].';');
stillstanding
This outputs nothing. I tried:`echo "<p><b>Main Deal:</b> ".eval("return ".$data['main_deal'].";");`And:`echo "<p><b>Main Deal:</b> ";eval("echo ".$data['main_deal'].";");`
Jarred
i do hope you have that whitespace after "return ". what does a straight `echo $xml->deals->deal[0];` return anyway?
stillstanding
The whitespace appeared when I copied the code here. It is not in my php code. echo $xml->deals->deal[0]; returns the expected xml code (this was the first thing I checked, even before posting here).
Jarred
are you echo'ing within the same scope as the eval code?
stillstanding
In my first comment, I showed that I tried to return in the eval code while echoing, and I tried to echo within the eval. Both return no output.
Jarred
you only showed us the contents $data['main_deal'] which as you say is the string '$xml->deals->deal[0]. but what does echo $xml->deals->deal[0] display within the same scope and context as where you inserted the eval statement?
stillstanding
`echo "<p><b>Main Deal:</b> ".eval("return ".$xml->deals->deal[0].";");` returns nothing.I have also tried doing print_r instead of return, and again nothing. But $xml->deals->deal[0] is holding the data I need. Why would using eval not output it?
Jarred
check your error logs if they display any eval() errors
stillstanding
What if you do `eval('return "'.$xml->deals->deal[0].'";');`. I added double-quotes inside the string.
notJim
Also, are PHP errors set to be displayed (including notices?) It's pretty easy to miss a subtle error in an eval statement.
notJim
i suspect you're trying to output a child/attribute of a simplexml object, which happens to be another simplexml object. try typecasting the result: `eval('return (string)'.$data["main_deal"].';');`
stillstanding
Oh snap! stillstanding has a good idea there, IIRC SimpleXML often needs to be explicitly cast to a string.
notJim
notJim and stillstanding: Both of your suggestions outputted nothing. I think the real problem here is how can I convert a string to a simpleXML object that is selecting a child element?
Jarred
A: 

Please be aware that using eval is dangerous to the point of insanity. What if someone somehow sets $data['main_deal'] to exec("rm -rf .") or mysql_query('drop table users'). You must be absolutely certain that this string cannot be tainted in any way for this to be safe. This is non-trivial, as most filters are geared toward preventing XSS injection, and not this type of attack.

I don't mean to be a jerk, I realize you're just trying to get a job done, but I don't think this can be stressed enough.


I noticed in the comments you asked the question:

Does this make sense, or is there a better way to do it?

There's a good chance there is a better way to do it, but without knowing more about your XML and what your users need, it's difficult to say. You said an example selection might be $xml->deals->deal[0]. Do users just need to be able select the index of that deal? E.g., could you just let them choose from a dropdown which deal to select? Then you could just store the integer they want, and accessing that data would be much safer and simpler, to boot.

If they need more control than that, maybe you could give them a few dropdowns to help them build the "path" to the needed element. For example:

[ Element 1 (v)]  [ Element 2 (v)] [ Field (v)]
 | Deals       |   | Deal        |  | 0       |
 | Steals      |   | Steal       |  | 1       |
 | Wheels      |   | Wheel       |  |_________|
 |_____________|   |_____________|

Then in your code

 $array_of_valid_element1 = array ('Deals', 'Steals', 'Wheels');

 if(
    in_array($_POST['element1'], $array_of_valid_element1)
    &&
    in_array($_POST['element2'], $array_of_valid_element2)
    &&
    in_array($_POST['element3'], $array_of_valid_element3)
 )
 {
     echo $xml->$_POST['element1']->$_POST['element2'][$_POST['element3'];
 }

You can see where the extra validation comes in! By checking against each element, you make sure the user is only doing things they're explicitly allowed to do.

I hope this gives you some ideas or helps you reconsider whether you're taking the best approach. Feel free to ask another question if you'd like more input on this. It's not simple, but that's what makes it fun!

notJim
Only other developers have access to set the value of this variable, so there is no security risk here.
Jarred
Developers are the most dangerous people to give access to something like this, though! Not that *I* do this, but I know of ahem... certain developers who occasionally see a situation like this and ask "Hmm, I wonder if I can...". And again, I don't mean to be a boor, I just think these things are sometimes not emphasized enough.
notJim
I do like the idea of building a dropdown box instead of relying on the developer to know the exact selector for the xml element. Maybe I will try this instead.
Jarred