I'm a bit stuck and I hope someone who's more familiar with PHP will be able to help me. Basically I am writing a PHP application that lets you plug in products via an XML file. When I say products I mean like a car-hire or insurance type product, where there are forms to fill out and rates to calculate. I opted for an XML structure to make it easy in future to add new or adapt them without any coding knowledge as the underlying class will do all the work. However I'm now trying to rack my brain for the safest and best way to include rates calculations in the XML file structure and evaluate them in PHP, without any risk of being exploited. So for example the xml file structure I will have for the rates calculation area might look something like
<rates>
<rate name="variable1" type="forminput" relative="form['input1']"></rate>
<rate name="variable2" type="forminput" relative="form['input2']"></rate>
<rate name="calculatedvariable1" type="calculation">[variable1] * [variable2]</rate>
</rates>
Ok so this is a pretty basic example but the idea is that my class then reads the name, creates a php variable based on this using an xml parser, with the value given in the form (or wherever the relative is referencing) and then when it finds a calculation type it plugs the correctly named variables (noted by square brackets or whatever) into the calculation and evaluates it. So in this example the output given by parsing the calculation will be :
$variable1 * $variable2
Which then needs to run as a calculation to get the value of calculatedvariable1. Now I know I can use eval() to achieve this but I'm not convinced this is the only option and perhaps I'm missing something else I could be doing either in my xml structure or in the way my php will parse it. Anyhow I hope I've explained it properly and thanks in advance for any ideas.
Considering you have solved the problem to retrieve the value from the form already in form of a string based on the relative
attribute - naming the implementation here resolve_variable($relative)
.
You can then assign the value to the element itself and formulate your calculation in form of a standard xpath 1.0 expression like:
rate[@name="variable1"] * rate[@name="variable2"]
And that expression inside the XML:
<rates>
<rate name="variable1" type="forminput" relative="form['input1']"></rate>
<rate name="variable2" type="forminput" relative="form['input2']"></rate>
<rate name="calculatedvariable1" type="calculation">
rate[@name="variable1"] * rate[@name="variable2"]
</rate>
</rates>
All you need in PHP is to make use of the DOMXPath
object for your DOMDocument
:
$dom = new DOMDocument();
$dom->loadXML($xml);
$xpath = new DOMXPath($dom);
You can then assign the values to the nodes:
// assign values
foreach ($xpath->query('rate/@relative') as $relative) {
$relative->ownerElement->nodeValue = resolve_variable($relative);
}
Then perform all the calculation(s):
// do calculations
$results = array();
foreach ($xpath->query('rate[@type="calculation"]') as $calculation) {
$results[$calculation->getAttribute('name')]
= $xpath->evaluate($calculation->nodeValue);
}
They then come out nicely in form of the $results
array (in my example I have 3 and 5 as values):
Array
(
[calculatedvariable1] => 15
)
Maybe this is helpful for you.
Take care that if you need precise calculations floating point arithmetics might stand in your way http://www.validlab.com/goldberg/paper.pdf
A working example at a glance for the whole picture / the view from above: http://eval.in/9595
You might be able to do this as well with XSL.