Browse Source

Merge branch 'master' of github.com:ckolivas/cgminer

nfactor-troky
Con Kolivas 11 years ago
parent
commit
b445f9ce87
  1. 42
      API-README
  2. 160
      miner.php

42
API-README

@ -952,7 +952,9 @@ or in your cgminer.conf
And in miner.php set $mcast = true; And in miner.php set $mcast = true;
This will ignore the value of $rigs and overwrite it with the list of zero or This will ignore the value of $rigs and overwrite it with the list of zero or
more rigs found on the network in the timout specified more rigs found on the network in the timeout specified
A rig will not reply if the API settings would mean it would also ignore an
API request from the web server running miner.php
--------- ---------
@ -1196,6 +1198,14 @@ Set $mcast to true to look for your rigs and ignore $rigs
--------- ---------
Default:
$mcastexpect = 0;
The minimum number of rigs expected to be found when $mcast is true
If fewer are found, an error will be included at the top of the page
---------
Default: Default:
$mcastaddr = '224.0.0.75'; $mcastaddr = '224.0.0.75';
@ -1237,6 +1247,16 @@ N.B. the accuracy of the timing used to wait for the replies is
--------- ---------
Default:
$allowgen = false;
Set $allowgen to true to allow customsummarypages to use 'gen'
false means ignore any 'gen' options
This is disabled by default due to the possible security risk
of using it, see the end of this document for an explanation
---------
Default: Default:
$rigipsecurity = true; $rigipsecurity = true;
@ -1498,6 +1518,7 @@ The example given:
With cgminer 2.10.2 and later, miner.php includes an extension to 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 custom pages that allows you to apply SQL style commands to
the data: where, group, and having 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' As an example, miner.php includes a more complex custom page called 'Pools'
this includes the extension: this includes the extension:
@ -1513,6 +1534,7 @@ $poolsext = array(
'STATS.Bytes Sent' => 'sum', 'STATS.Bytes Sent' => 'sum',
'STATS.Times Recv' => 'sum', 'STATS.Times Recv' => 'sum',
'STATS.Bytes Recv' => 'sum'), 'STATS.Bytes Recv' => 'sum'),
'gen' => array('AvShr', 'POOL.Difficulty Accepted/max(POOL.Accepted,1)),
'having' => array(array('STATS.Bytes Recv', '>', 0))) 'having' => array(array('STATS.Bytes Recv', '>', 0)))
); );
@ -1564,3 +1586,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 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 'any' is effectively random: the field value in the 1st row of the grouped data
An unrecognised 'function' uses 'any' 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

160
miner.php

@ -1,17 +1,20 @@
<?php <?php
session_start(); session_start();
# #
global $title, $miner, $port, $readonly, $notify, $rigs; global $doctype, $title, $miner, $port, $readonly, $notify, $rigs;
global $mcast, $mcastaddr, $mcastport, $mcastcode; global $mcast, $mcastexpect, $mcastaddr, $mcastport, $mcastcode;
global $mcastlistport, $mcasttimeout; global $mcastlistport, $mcasttimeout, $allowgen;
global $rigipsecurity, $rigtotals, $forcerigtotals; global $rigipsecurity, $rigtotals, $forcerigtotals;
global $socksndtimeoutsec, $sockrcvtimeoutsec; global $socksndtimeoutsec, $sockrcvtimeoutsec;
global $checklastshare, $poolinputs, $hidefields; global $checklastshare, $poolinputs, $hidefields;
global $ignorerefresh, $changerefresh, $autorefresh; global $ignorerefresh, $changerefresh, $autorefresh;
global $allowcustompages, $customsummarypages; global $allowcustompages, $customsummarypages;
global $miner_font_family, $miner_font_size; global $miner_font_family, $miner_font_size;
global $bad_font_family, $bad_font_size;
global $colouroverride, $placebuttons, $userlist; global $colouroverride, $placebuttons, $userlist;
# #
$doctype = "<!DOCTYPE html>\n";
#
# See API-README for more details of these variables and how # See API-README for more details of these variables and how
# to configure miner.php # to configure miner.php
# #
@ -48,6 +51,9 @@ $rigs = array('127.0.0.1:4028');
# Set $mcast to true to look for your rigs and ignore $rigs # Set $mcast to true to look for your rigs and ignore $rigs
$mcast = false; $mcast = false;
# #
# Set $mcastexpect to at least how many rigs you expect it to find
$mcastexpect = 0;
#
# API Multicast address all cgminers are listening on # API Multicast address all cgminers are listening on
$mcastaddr = '224.0.0.75'; $mcastaddr = '224.0.0.75';
# #
@ -64,6 +70,10 @@ $mcastlistport = 4027;
# to wait for replies to the Multicast message # to wait for replies to the Multicast message
$mcasttimeout = 1.5; $mcasttimeout = 1.5;
# #
# Set $allowgen to true to allow customsummarypages to use 'gen'
# false means ignore any 'gen' options
$allowgen = false;
#
# Set $rigipsecurity to false to show the IP/Port of the rig # Set $rigipsecurity to false to show the IP/Port of the rig
# in the socket error messages and also show the full socket message # in the socket error messages and also show the full socket message
$rigipsecurity = true; $rigipsecurity = true;
@ -139,7 +149,7 @@ $poolspage = array(
'POOL.Has GBT=GBT', 'STATS.Times Sent=TSent', 'POOL.Has GBT=GBT', 'STATS.Times Sent=TSent',
'STATS.Bytes Sent=BSent', 'STATS.Net Bytes Sent=NSent', 'STATS.Bytes Sent=BSent', 'STATS.Net Bytes Sent=NSent',
'STATS.Times Recv=TRecv', 'STATS.Bytes Recv=BRecv', 'STATS.Times Recv=TRecv', 'STATS.Bytes Recv=BRecv',
'STATS.Net Bytes Recv=NRecv')); 'STATS.Net Bytes Recv=NRecv', 'GEN.AvShr=AvShr'));
# #
$poolssum = array( $poolssum = array(
'SUMMARY' => array('MHS av', 'Found Blocks', 'Accepted', 'SUMMARY' => array('MHS av', 'Found Blocks', 'Accepted',
@ -156,7 +166,9 @@ $poolsext = array(
'calc' => array('POOL.Difficulty Accepted' => 'sum', 'POOL.Difficulty Rejected' => 'sum', 'calc' => array('POOL.Difficulty Accepted' => 'sum', 'POOL.Difficulty Rejected' => 'sum',
'STATS.Times Sent' => 'sum', 'STATS.Bytes Sent' => 'sum', 'STATS.Times Sent' => 'sum', 'STATS.Bytes Sent' => 'sum',
'STATS.Net Bytes Sent' => 'sum', 'STATS.Times Recv' => 'sum', 'STATS.Net Bytes Sent' => 'sum', 'STATS.Times Recv' => 'sum',
'STATS.Bytes Recv' => 'sum', 'STATS.Net Bytes Recv' => 'sum'), 'STATS.Bytes Recv' => 'sum', 'STATS.Net Bytes Recv' => 'sum',
'POOL.Accepted' => 'sum'),
'gen' => array('AvShr' => 'round(POOL.Difficulty Accepted/max(POOL.Accepted,1)*100)/100'),
'having' => array(array('STATS.Bytes Recv', '>', 0))) 'having' => array(array('STATS.Bytes Recv', '>', 0)))
); );
@ -176,9 +188,12 @@ $warnfont = '<font color=red><b>';
$warnoff = '</b></font>'; $warnoff = '</b></font>';
$dfmt = 'H:i:s j-M-Y \U\T\CP'; $dfmt = 'H:i:s j-M-Y \U\T\CP';
# #
$miner_font_family = 'verdana,arial,sans'; $miner_font_family = 'Verdana, Arial, sans-serif, sans';
$miner_font_size = '13pt'; $miner_font_size = '13pt';
# #
$bad_font_family = '"Times New Roman", Times, serif';
$bad_font_size = '18pt';
#
# Edit this or redefine it in myminer.php to change the colour scheme # Edit this or redefine it in myminer.php to change the colour scheme
# See $colourtable below for the list of names # See $colourtable below for the list of names
$colouroverride = array(); $colouroverride = array();
@ -198,7 +213,7 @@ if (file_exists('myminer.php'))
# This is the system default that must always contain all necessary # This is the system default that must always contain all necessary
# colours so it must be a constant # colours so it must be a constant
# You can override these values with $colouroverride # You can override these values with $colouroverride
# The only one missing is in $warnfont # The only one missing is $warnfont
# - which you can override directly anyway # - which you can override directly anyway
global $colourtable; global $colourtable;
$colourtable = array( $colourtable = array(
@ -210,6 +225,8 @@ $colourtable = array(
'td.h background' => '#c4ffff', 'td.h background' => '#c4ffff',
'td.err color' => 'black', 'td.err color' => 'black',
'td.err background' => '#ff3050', 'td.err background' => '#ff3050',
'td.bad color' => 'black',
'td.bad background' => '#ff3050',
'td.warn color' => 'black', 'td.warn color' => 'black',
'td.warn background' => '#ffb050', 'td.warn background' => '#ffb050',
'td.sta color' => 'green', 'td.sta color' => 'green',
@ -269,9 +286,10 @@ function getdom($domname)
return getcss($domname, true); return getcss($domname, true);
} }
# #
function htmlhead($checkapi, $rig, $pg = null, $noscript = false) function htmlhead($mcerr, $checkapi, $rig, $pg = null, $noscript = false)
{ {
global $title, $miner_font_family, $miner_font_size; global $doctype, $title, $miner_font_family, $miner_font_size;
global $bad_font_family, $bad_font_size;
global $error, $readonly, $poolinputs, $here; global $error, $readonly, $poolinputs, $here;
global $ignorerefresh, $autorefresh; global $ignorerefresh, $autorefresh;
@ -300,14 +318,16 @@ function htmlhead($checkapi, $rig, $pg = null, $noscript = false)
$readonly = true; $readonly = true;
} }
$miner_font = "font-family:$miner_font_family; font-size:$miner_font_size;"; $miner_font = "font-family:$miner_font_family; font-size:$miner_font_size;";
$bad_font = "font-family:$bad_font_family; font-size:$bad_font_size;";
echo "<html><head>$refreshmeta echo "$doctype<html><head>$refreshmeta
<title>$title</title> <title>$title</title>
<style type='text/css'> <style type='text/css'>
td { $miner_font ".getcss('td')."} td { $miner_font ".getcss('td')."}
td.two { $miner_font ".getcss('td.two')."} td.two { $miner_font ".getcss('td.two')."}
td.h { $miner_font ".getcss('td.h')."} td.h { $miner_font ".getcss('td.h')."}
td.err { $miner_font ".getcss('td.err')."} td.err { $miner_font ".getcss('td.err')."}
td.bad { $bad_font ".getcss('td.bad')."}
td.warn { $miner_font ".getcss('td.warn')."} td.warn { $miner_font ".getcss('td.warn')."}
td.sta { $miner_font ".getcss('td.sta')."} td.sta { $miner_font ".getcss('td.sta')."}
td.tot { $miner_font ".getcss('td.tot')."} td.tot { $miner_font ".getcss('td.tot')."}
@ -339,6 +359,14 @@ echo "</script>\n";
<tr><td align=center valign=top> <tr><td align=center valign=top>
<table border=0 cellpadding=4 cellspacing=0 summary='Mine'> <table border=0 cellpadding=4 cellspacing=0 summary='Mine'>
<?php <?php
echo $mcerr;
}
#
function minhead($mcerr = '')
{
global $readonly;
$readonly = true;
htmlhead($mcerr, false, null, null, true);
} }
# #
global $haderror, $error; global $haderror, $error;
@ -643,9 +671,14 @@ function newrow()
echo '<tr>'; echo '<tr>';
} }
# #
function othrow($row)
{
return "<tr>$row</tr>";
}
#
function otherrow($row) function otherrow($row)
{ {
echo "<tr>$row</tr>"; echo othrow($row);
} }
# #
function endrow() function endrow()
@ -1810,8 +1843,6 @@ function doOne($rig, $preprocess)
global $haderror, $readonly, $notify, $rigs; global $haderror, $readonly, $notify, $rigs;
global $placebuttons; global $placebuttons;
htmlhead(true, $rig);
if ($placebuttons == 'top' || $placebuttons == 'both') if ($placebuttons == 'top' || $placebuttons == 'both')
pagebuttons($rig, null); pagebuttons($rig, null);
@ -2324,8 +2355,55 @@ function processcompare($which, $ext, $section, $res)
return $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)
{ {
global $allowgen;
$res = processcompare('where', $ext, $section, $res); $res = processcompare('where', $ext, $section, $res);
if (isset($ext[$section]['group'])) if (isset($ext[$section]['group']))
@ -2393,6 +2471,10 @@ function processext($ext, $section, $res)
} }
} }
// Generated fields (functions of other fields)
if ($allowgen === true && isset($ext[$section]['gen']))
dogen($ext, $section, $res, $fields);
return processcompare('having', $ext, $section, $res); return processcompare('having', $ext, $section, $res);
} }
# #
@ -2451,6 +2533,8 @@ function processcustompage($pagename, $sections, $sum, $ext, $namemap)
$results[$cmd][$num] = $process; $results[$cmd][$num] = $process;
} }
} }
else
otherrow('<td class=bad>Bad "$rigs" array</td>');
} }
$shownsomething = false; $shownsomething = false;
@ -2487,7 +2571,8 @@ function processcustompage($pagename, $sections, $sum, $ext, $namemap)
if (isset($results[$sectionmap[$section]])) if (isset($results[$sectionmap[$section]]))
{ {
$rigresults = processext($ext, $section, $results[$sectionmap[$section]]); $rigresults = processext($ext, $section, $results[$sectionmap[$section]], $fields);
$showfields = array(); $showfields = array();
$showhead = array(); $showhead = array();
foreach ($fields as $field) foreach ($fields as $field)
@ -2566,21 +2651,19 @@ function showcustompage($pagename)
global $customsummarypages; global $customsummarypages;
global $placebuttons; global $placebuttons;
htmlhead(false, null, $pagename);
if ($placebuttons == 'top' || $placebuttons == 'both') if ($placebuttons == 'top' || $placebuttons == 'both')
pagebuttons(null, $pagename); pagebuttons(null, $pagename);
if (!isset($customsummarypages[$pagename])) if (!isset($customsummarypages[$pagename]))
{ {
otherrow("<td colspan=100>Unknown custom summary page '$pagename'</td>"); otherrow("<td colspan=100 class=bad>Unknown custom summary page '$pagename'</td>");
return; return;
} }
$c = count($customsummarypages[$pagename]); $c = count($customsummarypages[$pagename]);
if ($c < 2 || $c > 3) if ($c < 2 || $c > 3)
{ {
$rw = "<td colspan=100>Invalid custom summary page '$pagename' ("; $rw = "<td colspan=100 class=bad>Invalid custom summary page '$pagename' (";
$rw .= count($customsummarypages[$pagename]).')</td>'; $rw .= count($customsummarypages[$pagename]).')</td>';
otherrow($rw); otherrow($rw);
return; return;
@ -2625,7 +2708,7 @@ function showcustompage($pagename)
if (count($page) <= 1) if (count($page) <= 1)
{ {
otherrow("<td colspan=100>Invalid custom summary page '$pagename' no content </td>"); otherrow("<td colspan=100 class=bad>Invalid custom summary page '$pagename' no content </td>");
return; return;
} }
@ -2639,7 +2722,7 @@ function onlylogin()
{ {
global $here; global $here;
htmlhead(false, null, null, true); htmlhead('', false, null, null, true);
?> ?>
<tr height=15%><td>&nbsp;</td></tr> <tr height=15%><td>&nbsp;</td></tr>
@ -2739,6 +2822,7 @@ function checklogin()
function display() function display()
{ {
global $miner, $port; global $miner, $port;
global $mcast, $mcastexpect;
global $readonly, $notify, $rigs; global $readonly, $notify, $rigs;
global $ignorerefresh, $autorefresh; global $ignorerefresh, $autorefresh;
global $allowcustompages, $customsummarypages; global $allowcustompages, $customsummarypages;
@ -2750,11 +2834,24 @@ function display()
if ($pagesonly === 'login') if ($pagesonly === 'login')
return; return;
$mcerr = '';
if ($rigs == null or count($rigs) == 0) if ($rigs == null or count($rigs) == 0)
{ {
otherrow("<td>No rigs defined</td>"); if ($mcast === true)
$action = 'found';
else
$action = 'defined';
minhead();
otherrow("<td class=bad>No rigs $action</td>");
return; return;
} }
else
{
if ($mcast === true && count($rigs) < $mcastexpect)
$mcerr = othrow('<td class=bad>Found '.count($rigs)." rigs but expected at least $mcastexpect</td>");
}
if ($ignorerefresh == false) if ($ignorerefresh == false)
{ {
@ -2811,7 +2908,8 @@ function display()
if ($pg !== null && $pg !== '') if ($pg !== null && $pg !== '')
{ {
showcustompage($pg); htmlhead($mcerr, false, null, $pg);
showcustompage($pg, $mcerr);
return; return;
} }
} }
@ -2830,10 +2928,14 @@ function display()
$miner = $parts[0]; $miner = $parts[0];
$port = $parts[1]; $port = $parts[1];
htmlhead($mcerr, true, 0);
doOne(0, $preprocess); doOne(0, $preprocess);
} }
else else
otherrow('<td>Invalid "$rigs" array</td>'); {
minhead($mcerr);
otherrow('<td class=bad>Invalid "$rigs" array</td>');
}
return; return;
} }
@ -2846,15 +2948,19 @@ function display()
$miner = $parts[0]; $miner = $parts[0];
$port = $parts[1]; $port = $parts[1];
htmlhead($mcerr, true, 0);
doOne($rig, $preprocess); doOne($rig, $preprocess);
} }
else else
otherrow('<td>Invalid "$rigs" array</td>'); {
minhead($mcerr);
otherrow('<td class=bad>Invalid "$rigs" array</td>');
}
return; return;
} }
htmlhead(false, null); htmlhead($mcerr, false, null);
if ($placebuttons == 'top' || $placebuttons == 'both') if ($placebuttons == 'top' || $placebuttons == 'both')
pagebuttons(null, null); pagebuttons(null, null);
@ -2880,7 +2986,7 @@ function display()
pagebuttons(null, null); pagebuttons(null, null);
} }
# #
if (isset($mcast) && $mcast === true) if ($mcast === true)
getrigs(); getrigs();
display(); display();
# #

Loading…
Cancel
Save