miner.php allow formula generation of new fields
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
diff --git a/API-README b/API-README
index 2d7110c..0701750 100644
--- a/API-README
+++ b/API-README
@@ -1508,6 +1508,7 @@ The example given:
With cgminer 2.10.2 and later, miner.php includes an extension to
the custom pages that allows you to apply SQL style commands to
the data: where, group, and having
+cgminer 3.4.2 also includes another option 'gen'
As an example, miner.php includes a more complex custom page called 'Pools'
this includes the extension:
@@ -1523,6 +1524,7 @@ $poolsext = array(
'STATS.Bytes Sent' => 'sum',
'STATS.Times Recv' => 'sum',
'STATS.Bytes Recv' => 'sum'),
+ 'gen' => array('AvShr', 'POOL.Difficulty Accepted/max(POOL.Accepted,1)),
'having' => array(array('STATS.Bytes Recv', '>', 0)))
);
@@ -1574,3 +1576,21 @@ The first 4 are as expected - the numerical sum, average, minimum or maximum
of course any valid 'DEVS.Xyz' would give the same 'count' value
'any' is effectively random: the field value in the 1st row of the grouped data
An unrecognised 'function' uses 'any'
+
+A 'gen' allows you to generate new fields from any php valid function of any
+of the other fields
+ e.g. 'gen' => array('AvShr', 'POOL.Difficulty Accepted/max(POOL.Accepted,1)),
+will generate a new field called GEN.AvShr that is the function shown, which
+in this case is the average difficulty of each share submitted
+
+THERE IS A SECURITY RISK WITH HOW GEN WORKS
+It simply replaces all the variables with their values and then requests PHP
+the execute the formula - thus if a field value returned from a cgminer API
+request contained PHP code, it could be executed by your web server
+Of course cgminer doesn't do this, but if you do not control the cgminer that
+returns the data in the API calls, someone could modify cgminer to return a
+PHP string in a field you use in 'gen'
+Thus use 'gen' at your own risk
+If someone feels the urge to write a mathematical interpreter in PHP to get
+around this risk, feel free to write one and submit it to the API author for
+consideration
diff --git a/miner.php b/miner.php
index 89f3cba..89b6bef 100644
--- a/miner.php
+++ b/miner.php
@@ -2349,7 +2349,52 @@ function processcompare($which, $ext, $section, $res)
return $res;
}
#
-function processext($ext, $section, $res)
+function ss($a, $b)
+{
+ $la = strlen(a);
+ $lb = strlen(b);
+ if ($la != $lb)
+ return $la - $lb;
+ return strcmp($a, $b);
+}
+#
+function genfld($row, $calc)
+{
+ uksort($row, "ss");
+
+ foreach ($row as $name => $value)
+ if (strstr($calc, $name) !== FALSE)
+ $calc = str_replace($name, $value, $calc);
+
+ eval("\$val = $calc;");
+
+ return $val;
+}
+#
+function dogen($ext, $section, &$res, &$fields)
+{
+ $gen = $ext[$section]['gen'];
+
+ foreach ($gen as $fld => $calc)
+ $fields[] = "GEN.$fld";
+
+ foreach ($res as $rig => $result)
+ foreach ($result as $sec => $row)
+ {
+ $secname = preg_replace('/\d/', '', $sec);
+ if (secmatch($section, $secname))
+ foreach ($gen as $fld => $calc)
+ {
+ $name = "GEN.$fld";
+
+ $val = genfld($row, $calc);
+
+ $res[$rig][$sec][$name] = $val;
+ }
+ }
+}
+#
+function processext($ext, $section, $res, &$fields)
{
$res = processcompare('where', $ext, $section, $res);
@@ -2418,6 +2463,10 @@ function processext($ext, $section, $res)
}
}
+ // Generated fields (functions of other fields)
+ if (isset($ext[$section]['gen']))
+ dogen($ext, $section, $res, $fields);
+
return processcompare('having', $ext, $section, $res);
}
#
@@ -2514,7 +2563,8 @@ function processcustompage($pagename, $sections, $sum, $ext, $namemap)
if (isset($results[$sectionmap[$section]]))
{
- $rigresults = processext($ext, $section, $results[$sectionmap[$section]]);
+ $rigresults = processext($ext, $section, $results[$sectionmap[$section]], $fields);
+
$showfields = array();
$showhead = array();
foreach ($fields as $field)