miner.php 73 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179
  1. <?php
  2. session_start();
  3. #
  4. global $doctype, $title, $miner, $port, $readonly, $notify;
  5. global $rigport, $rigs, $rignames, $rigbuttons;
  6. global $mcast, $mcastexpect, $mcastaddr, $mcastport, $mcastcode;
  7. global $mcastlistport, $mcasttimeout, $mcastretries, $allowgen;
  8. global $rigipsecurity, $rigtotals, $forcerigtotals;
  9. global $socksndtimeoutsec, $sockrcvtimeoutsec;
  10. global $checklastshare, $poolinputs, $hidefields;
  11. global $ignorerefresh, $changerefresh, $autorefresh;
  12. global $allowcustompages, $customsummarypages, $user_pages;
  13. global $miner_font_family, $miner_font_size;
  14. global $bad_font_family, $bad_font_size, $add_css_names;
  15. global $colouroverride, $placebuttons, $userlist;
  16. #
  17. $doctype = "<!DOCTYPE html>\n";
  18. #
  19. # See API-README for more details of these variables and how
  20. # to configure miner.php
  21. #
  22. # Web page title
  23. $title = 'Mine';
  24. #
  25. # Set $readonly to true to force miner.php to be readonly
  26. # Set $readonly to false then it will check cgminer 'privileged'
  27. $readonly = false;
  28. #
  29. # Set $userlist to null to allow anyone access or read API-README
  30. $userlist = null;
  31. #
  32. # Set $notify to false to NOT attempt to display the notify command
  33. # Set $notify to true to attempt to display the notify command
  34. $notify = true;
  35. #
  36. # Set $checklastshare to true to do the following checks:
  37. # If a device's last share is 12x expected ago then display as an error
  38. # If a device's last share is 8x expected ago then display as a warning
  39. # If either of the above is true, also display the whole line highlighted
  40. # This assumes shares are 1 difficulty shares
  41. $checklastshare = true;
  42. #
  43. # Set $poolinputs to true to show the input fields for adding a pool
  44. # and changing the pool priorities
  45. # N.B. also if $readonly is true, it will not display the fields
  46. $poolinputs = false;
  47. #
  48. # Default port to use if any $rigs entries don't specify the port number
  49. $rigport = 4028;
  50. #
  51. # Set $rigs to an array of your cgminer rigs that are running
  52. # format: 'IP' or 'Host' or 'IP:Port' or 'Host:Port' or 'Host:Port:Name'
  53. $rigs = array('127.0.0.1:4028');
  54. #
  55. # Set $rignames to false, or one of 'ip' or 'ipx'
  56. # this says what to use if $rigs doesn't have a 'name'
  57. $rignames = false;
  58. #
  59. # Set $rigbuttons to false to display a link rather than a button
  60. $rigbuttons = true;
  61. #
  62. # Set $mcast to true to look for your rigs and ignore $rigs
  63. $mcast = false;
  64. #
  65. # Set $mcastexpect to at least how many rigs you expect it to find
  66. $mcastexpect = 0;
  67. #
  68. # API Multicast address all cgminers are listening on
  69. $mcastaddr = '224.0.0.75';
  70. #
  71. # API Multicast UDP port all cgminers are listening on
  72. $mcastport = 4028;
  73. #
  74. # The code all cgminers expect in the Multicast message sent
  75. $mcastcode = 'FTW';
  76. #
  77. # UDP port cgminers are to reply on (by request)
  78. $mcastlistport = 4027;
  79. #
  80. # Set $mcasttimeout to the number of seconds (floating point)
  81. # to wait for replies to the Multicast message
  82. $mcasttimeout = 1.5;
  83. #
  84. # Set $mcastretries to the number of times to retry the multicast
  85. $mcastretries = 0;
  86. #
  87. # Set $allowgen to true to allow customsummarypages to use 'gen'
  88. # false means ignore any 'gen' options
  89. $allowgen = false;
  90. #
  91. # Set $rigipsecurity to false to show the IP/Port of the rig
  92. # in the socket error messages and also show the full socket message
  93. $rigipsecurity = true;
  94. #
  95. # Set $rigtotals to true to display totals on the single rig page
  96. # 'false' means no totals (and ignores $forcerigtotals)
  97. # You can force it to always show rig totals when there is only
  98. # one line by setting $forcerigtotals = true;
  99. $rigtotals = true;
  100. $forcerigtotals = false;
  101. #
  102. # These should be OK for most cases
  103. $socksndtimeoutsec = 10;
  104. $sockrcvtimeoutsec = 40;
  105. #
  106. # List of fields NOT to be displayed
  107. # This example would hide the slightly more sensitive pool information
  108. #$hidefields = array('POOL.URL' => 1, 'POOL.User' => 1);
  109. $hidefields = array();
  110. #
  111. # Auto-refresh of the page (in seconds) - integers only
  112. # $ignorerefresh = true/false always ignore refresh parameters
  113. # $changerefresh = true/false show buttons to change the value
  114. # $autorefresh = default value, 0 means dont auto-refresh
  115. $ignorerefresh = false;
  116. $changerefresh = true;
  117. $autorefresh = 0;
  118. #
  119. # Should we allow custom pages?
  120. # (or just completely ignore them and don't display the buttons)
  121. $allowcustompages = true;
  122. #
  123. # OK this is a bit more complex item: Custom Summary Pages
  124. # As mentioned above, see API-README
  125. # see the example below (if there is no matching data, no total will show)
  126. $mobilepage = array(
  127. 'DATE' => null,
  128. 'RIGS' => null,
  129. 'SUMMARY' => array('Elapsed', 'MHS av', 'MHS 5m', 'Found Blocks=Blks',
  130. 'Difficulty Accepted=DiffA',
  131. 'Difficulty Rejected=DiffR',
  132. 'Hardware Errors=HW',
  133. 'Work Utility=WU'),
  134. 'DEVS+NOTIFY' => array('DEVS.Name=Name', 'DEVS.ID=ID', 'DEVS.Status=Status',
  135. 'DEVS.Temperature=Temp', 'DEVS.MHS av=MHS av',
  136. 'DEVS.MHS 5m=MHS 5m', 'DEVS.Difficulty Accepted=DiffA',
  137. 'DEVS.Difficulty Rejected=DiffR',
  138. 'DEVS.Work Utility=WU',
  139. 'NOTIFY.Last Not Well=Not Well'),
  140. 'POOL' => array('POOL', 'Status', 'Difficulty Accepted=DiffA',
  141. 'Difficulty Rejected=DiffR', 'Last Share Time=LST'));
  142. $mobilesum = array(
  143. 'SUMMARY' => array('MHS av', 'MHS 5m', 'Found Blocks', 'Difficulty Accepted',
  144. 'Difficulty Rejected', 'Hardware Errors',
  145. 'Work Utility'),
  146. 'DEVS+NOTIFY' => array('DEVS.MHS av', 'DEVS.Difficulty Accepted',
  147. 'DEVS.Difficulty Rejected'),
  148. 'POOL' => array('Difficulty Accepted', 'Difficulty Rejected'));
  149. #
  150. $statspage = array(
  151. 'DATE' => null,
  152. 'RIGS' => null,
  153. 'SUMMARY' => array('Elapsed', 'MHS av', 'MHS 5m', 'Found Blocks=Blks',
  154. 'Difficulty Accepted=DiffA',
  155. 'Difficulty Rejected=DiffR',
  156. 'Work Utility=WU', 'Hardware Errors=HW Errs',
  157. 'Network Blocks=Net Blks'),
  158. 'COIN' => array('*'),
  159. 'STATS' => array('*'));
  160. #
  161. $statssum = array(
  162. 'SUMMARY' => array('MHS av', 'MHS 5m', 'Found Blocks',
  163. 'Difficulty Accepted', 'Difficulty Rejected',
  164. 'Work Utility', 'Hardware Errors'));
  165. #
  166. $poolspage = array(
  167. 'DATE' => null,
  168. 'RIGS' => null,
  169. 'SUMMARY' => array('Elapsed', 'MHS av', 'MHS 5m', 'Found Blocks=Blks',
  170. 'Difficulty Accepted=DiffA',
  171. 'Difficulty Rejected=DiffR',
  172. 'Work Utility', 'Hardware Errors=HW',
  173. 'Network Blocks=Net Blks', 'Best Share'),
  174. 'POOL+STATS' => array('STATS.ID=ID', 'POOL.URL=URL',
  175. 'POOL.Difficulty Accepted=DiffA',
  176. 'POOL.Difficulty Rejected=DiffR',
  177. 'POOL.Has Stratum=Stratum',
  178. 'POOL.Stratum Active=StrAct',
  179. 'POOL.Has GBT=GBT', 'STATS.Times Sent=TSent',
  180. 'STATS.Bytes Sent=BSent', 'STATS.Net Bytes Sent=NSent',
  181. 'STATS.Times Recv=TRecv', 'STATS.Bytes Recv=BRecv',
  182. 'STATS.Net Bytes Recv=NRecv', 'GEN.AvShr=AvShr'));
  183. #
  184. $poolssum = array(
  185. 'SUMMARY' => array('MHS av', 'MHS 5m', 'Found Blocks',
  186. 'Difficulty Accepted', 'Difficulty Rejected',
  187. 'Work Utility', 'Hardware Errors'),
  188. 'POOL+STATS' => array('POOL.Difficulty Accepted', 'POOL.Difficulty Rejected',
  189. 'STATS.Times Sent', 'STATS.Bytes Sent',
  190. 'STATS.Net Bytes Sent', 'STATS.Times Recv',
  191. 'STATS.Bytes Recv', 'STATS.Net Bytes Recv'));
  192. #
  193. $poolsext = array(
  194. 'POOL+STATS' => array(
  195. 'where' => null,
  196. 'group' => array('POOL.URL', 'POOL.Has Stratum',
  197. 'POOL.Stratum Active', 'POOL.Has GBT'),
  198. 'calc' => array('POOL.Difficulty Accepted' => 'sum',
  199. 'POOL.Difficulty Rejected' => 'sum',
  200. 'STATS.Times Sent' => 'sum',
  201. 'STATS.Bytes Sent' => 'sum',
  202. 'STATS.Net Bytes Sent' => 'sum',
  203. 'STATS.Times Recv' => 'sum',
  204. 'STATS.Bytes Recv' => 'sum',
  205. 'STATS.Net Bytes Recv' => 'sum',
  206. 'POOL.Accepted' => 'sum'),
  207. 'gen' => array('AvShr' =>
  208. 'round(POOL.Difficulty Accepted/'.
  209. 'max(POOL.Accepted,1)*100)/100'),
  210. 'having' => array(array('STATS.Bytes Recv', '>', 0)))
  211. );
  212. #
  213. $devnotpage = array(
  214. 'DATE' => null,
  215. 'RIGS' => null,
  216. 'DEVS+NOTIFY' => array('DEVS.Name=Name', 'DEVS.ID=ID',
  217. 'DEVS.Temperature=Temp', 'DEVS.MHS av=MHS av',
  218. 'DEVS.Difficulty Accepted=DiffA',
  219. 'DEVS.Difficulty Rejected=DiffR',
  220. 'NOTIFY.Last Not Well=Last Not Well'));
  221. $devnotsum = array(
  222. 'DEVS+NOTIFY' => array('DEVS.MHS av', 'DEVS.Difficulty Accepted',
  223. 'DEVS.Difficulty Rejected'));
  224. #
  225. $devdetpage = array(
  226. 'DATE' => null,
  227. 'RIGS' => null,
  228. 'DEVS+DEVDETAILS' => array('DEVS.Name=Name', 'DEVS.ID=ID',
  229. 'DEVS.Temperature=Temp',
  230. 'DEVS.MHS av=MHS av',
  231. 'DEVS.Difficulty Accepted=DiffA',
  232. 'DEVS.Difficulty Rejected=DiffR',
  233. 'DEVDETAILS.Device Path=Device'));
  234. $devdetsum = array(
  235. 'DEVS+DEVDETAILS' => array('DEVS.MHS av', 'DEVS.Difficulty Accepted',
  236. 'DEVS.Difficulty Rejected'));
  237. #
  238. $protopage = array(
  239. 'DATE' => null,
  240. 'RIGS' => null,
  241. 'CONFIG' => array('ASC Count=ASCs', 'PGA Count=PGAs', 'Pool Count=Pools',
  242. 'Strategy', 'Device Code', 'OS', 'Failover-Only'),
  243. 'SUMMARY' => array('Elapsed', 'MHS av', 'Found Blocks=Blks',
  244. 'Difficulty Accepted=Diff Acc',
  245. 'Difficulty Rejected=Diff Rej',
  246. 'Hardware Errors=HW Errs',
  247. 'Network Blocks=Net Blks', 'Utility', 'Work Utility'),
  248. 'POOL+STATS' => array('STATS.ID=ID', 'POOL.URL=URL', 'POOL.Accepted=Acc',
  249. 'POOL.Difficulty Accepted=DiffA',
  250. 'POOL.Difficulty Rejected=DiffR', 'POOL.Has GBT=GBT',
  251. 'STATS.Max Diff=Max Work Diff',
  252. 'STATS.Times Sent=#Sent', 'STATS.Bytes Sent=Byte Sent',
  253. 'STATS.Net Bytes Sent=Net Sent',
  254. 'STATS.Times Recv=#Recv',
  255. 'STATS.Bytes Recv=Byte Recv',
  256. 'STATS.Net Bytes Recv=Net Recv'));
  257. $protosum = array(
  258. 'SUMMARY' => array('MHS av', 'Found Blocks', 'Difficulty Accepted',
  259. 'Difficulty Rejected', 'Hardware Errors',
  260. 'Utility', 'Work Utility'),
  261. 'POOL+STATS' => array('POOL.Accepted', 'POOL.Difficulty Accepted',
  262. 'POOL.Difficulty Rejected',
  263. 'STATS.Times Sent', 'STATS.Bytes Sent',
  264. 'STATS.Net Bytes Sent', 'STATS.Times Recv',
  265. 'STATS.Bytes Recv', 'STATS.Net Bytes Recv'));
  266. $protoext = array(
  267. 'POOL+STATS' => array(
  268. 'where' => null,
  269. 'group' => array('POOL.URL', 'POOL.Has GBT'),
  270. 'calc' => array('POOL.Accepted' => 'sum',
  271. 'POOL.Difficulty Accepted' => 'sum',
  272. 'POOL.Difficulty Rejected' => 'sum',
  273. 'STATS.Max Diff' => 'max',
  274. 'STATS.Times Sent' => 'sum',
  275. 'STATS.Bytes Sent' => 'sum',
  276. 'STATS.Net Bytes Sent' => 'sum',
  277. 'STATS.Times Recv' => 'sum',
  278. 'STATS.Bytes Recv' => 'sum',
  279. 'STATS.Net Bytes Recv' => 'sum'),
  280. 'having' => array(array('STATS.Bytes Recv', '>', 0)))
  281. );
  282. #
  283. # If 'gen' isn't enabled, the 'GEN' fields won't show but
  284. # where present, will be replaced with the ||SUMMARY fields
  285. $kanogenpage = array(
  286. 'DATE' => null,
  287. 'RIGS' => null,
  288. 'SUMMARY+COIN' => array('SUMMARY.Elapsed=Elapsed',
  289. 'GEN.Mined=Block%', 'GEN.GHS Acc=GH/s Acc',
  290. 'GEN.GHS av=GH/s av||SUMMARY.MHS av=MHS av',
  291. 'GEN.GHS 5m=GH/s 5m||SUMMARY.MHS 5m=MHS 5m',
  292. 'GEN.GHS WU=GH/s WU||SUMMARY.Work Utility=WU',
  293. 'SUMMARY.Found Blocks=Blks',
  294. 'SUMMARY.Difficulty Accepted=DiffA',
  295. 'SUMMARY.Difficulty Rejected=DiffR',
  296. 'SUMMARY.Hardware Errors=HW',
  297. 'SUMMARY.Difficulty Stale=DiffS',
  298. 'SUMMARY.Best Share=Best Share',
  299. 'SUMMARY.Device Hardware%=Dev HW%',
  300. 'SUMMARY.Device Rejected%=Dev Rej%',
  301. 'SUMMARY.Pool Rejected%=Pool Rej%',
  302. 'SUMMARY.Pool Stale%=Pool Stale%'),
  303. 'POOL' => array('URL', 'Diff1 Shares=Diff Work',
  304. 'Difficulty Accepted=DiffA',
  305. 'Difficulty Rejected=DiffR',
  306. 'Difficulty Stale=DiffS',
  307. 'Best Share', 'GEN.Acc=Pool Acc%', 'GEN.Rej=Pool Rej%')
  308. );
  309. # sum should list all fields seperately including GEN/BGEN || replacements
  310. $kanogensum = array(
  311. 'SUMMARY+COIN' => array('GEN.Mined', 'GEN.GHS Acc', 'GEN.GHS av',
  312. 'GEN.GHS 5m', 'GEN.GHS WU',
  313. 'SUMMARY.MHS av', 'SUMMARY.MHS 5m',
  314. 'SUMMARY.Work Utility',
  315. 'SUMMARY.Found Blocks',
  316. 'SUMMARY.Difficulty Accepted',
  317. 'SUMMARY.Difficulty Rejected',
  318. 'SUMMARY.Hardware Errors',
  319. 'SUMMARY.Difficulty Stale'),
  320. 'POOL' => array('Diff1 Shares', 'Difficulty Accepted',
  321. 'Difficulty Rejected', 'Difficulty Stale')
  322. );
  323. # 'where', 'calc' and 'having' should list GEN/BGEN || replacements seperately
  324. # 'group' must use the 'name1||name2' format for GEN/BGEN fields
  325. $kanogenext = array(
  326. 'SUMMARY+COIN' => array(
  327. 'gen' => array('GHS Acc' =>
  328. 'round(pow(2,32) * SUMMARY.Difficulty Accepted / '.
  329. 'SUMMARY.Elapsed / 10000000) / 100',
  330. 'Mined' =>
  331. 'SUMMARY.Elapsed * SUMMARY.Work Utility / 60 / '.
  332. 'COIN.Network Difficulty',
  333. 'GHS av' =>
  334. 'SUMMARY.MHS av / 1000.0',
  335. 'GHS 5m' =>
  336. 'SUMMARY.MHS 5m / 1000.0',
  337. 'GHS WU' =>
  338. 'round(pow(2,32) * SUMMARY.Work Utility / 60 / '.
  339. '10000000 ) / 100')),
  340. 'POOL' => array(
  341. 'group' => array('URL'),
  342. 'calc' => array('Diff1 Shares' => 'sum', 'Difficulty Accepted' => 'sum',
  343. 'Difficulty Rejected' => 'sum',
  344. 'Difficulty Stale' => 'sum', 'Best Share' => 'max'),
  345. 'gen' => array('Rej' => 'Difficulty Rejected / '.
  346. 'max(1,Difficulty Accepted+Difficulty Rejected)',
  347. 'Acc' => 'Difficulty Accepted / '.
  348. 'max(1,Difficulty Accepted+Difficulty Rejected)'))
  349. );
  350. #
  351. $syspage = array(
  352. 'DATE' => null,
  353. 'RIGS' => null,
  354. 'SUMMARY' => array('#', 'Elapsed', 'MHS av', 'MHS 5m', 'Found Blocks=Blks',
  355. 'Difficulty Accepted=DiffA',
  356. 'Difficulty Rejected=DiffR',
  357. 'Difficulty Stale=DiffS', 'Hardware Errors=HW',
  358. 'Work Utility', 'Network Blocks=Net Blks', 'Total MH',
  359. 'Best Share', 'Device Hardware%=Dev HW%',
  360. 'Device Rejected%=Dev Rej%',
  361. 'Pool Rejected%=Pool Rej%', 'Pool Stale%',
  362. 'Last getwork'),
  363. 'DEVS' => array('#', 'ID', 'Name', 'ASC', 'Device Elapsed', 'Enabled',
  364. 'Status', 'No Device', 'Temperature=Temp',
  365. 'MHS av', 'MHS 5s', 'MHS 5m', 'Diff1 Work',
  366. 'Difficulty Accepted=DiffA',
  367. 'Difficulty Rejected=DiffR',
  368. 'Hardware Errors=HW', 'Work Utility',
  369. 'Last Valid Work', 'Last Share Pool',
  370. 'Last Share Time', 'Total MH',
  371. 'Device Hardware%=Dev HW%',
  372. 'Device Rejected%=Dev Rej%'),
  373. 'POOL' => array('POOL', 'URL', 'Status', 'Priority', 'Quota',
  374. 'Getworks', 'Diff1 Shares',
  375. 'Difficulty Accepted=DiffA',
  376. 'Difficulty Rejected=DiffR',
  377. 'Difficulty Stale=DiffS',
  378. 'Last Share Difficulty',
  379. 'Last Share Time',
  380. 'Best Share', 'Pool Rejected%=Pool Rej%',
  381. 'Pool Stale%')
  382. );
  383. $syssum = array(
  384. 'SUMMARY' => array('MHS av', 'MHS 5m', 'Found Blocks',
  385. 'Difficulty Accepted', 'Difficulty Rejected',
  386. 'Difficulty Stale', 'Hardware Errors',
  387. 'Work Utility', 'Total MH'),
  388. 'DEVS' => array('MHS av', 'MHS 5s', 'MHS 5m', 'Diff1 Work',
  389. 'Difficulty Accepted', 'Difficulty Rejected',
  390. 'Hardware Errors', 'Total MH'),
  391. 'POOL' => array('Getworks', 'Diff1 Shares', 'Difficulty Accepted',
  392. 'Difficulty Rejected', 'Difficulty Stale')
  393. );
  394. #
  395. # $customsummarypages is an array of these Custom Summary Pages
  396. # that you can override in myminer.php
  397. # It can be 'Name' => 1 with 'Name' in any of $user_pages or $sys_pages
  398. # and it can be a fully defined 'Name' => array(...) like in $sys_pages below
  399. $customsummarypages = array(
  400. 'Kano' => 1,
  401. 'Mobile' => 1,
  402. 'Stats' => 1,
  403. 'Pools' => 1
  404. );
  405. #
  406. # $user_pages are the myminer.php definable version of $sys_pages
  407. # It should contain a set of 'Name' => array(...) like in $sys_pages
  408. # that $customsummarypages can refer to by 'Name'
  409. # If a 'Name' is in both $user_pages and $sys_pages, then the one
  410. # in $user_pages will override the one in $sys_pages
  411. $user_pages = array();
  412. #
  413. $here = $_SERVER['PHP_SELF'];
  414. #
  415. global $tablebegin, $tableend, $warnfont, $warnoff, $dfmt;
  416. #
  417. $tablebegin = '<tr><td><table border=1 cellpadding=5 cellspacing=0>';
  418. $tableend = '</table></td></tr>';
  419. $warnfont = '<font color=red><b>';
  420. $warnoff = '</b></font>';
  421. $dfmt = 'H:i:s j-M-Y \U\T\CP';
  422. #
  423. $miner_font_family = 'Verdana, Arial, sans-serif, sans';
  424. $miner_font_size = '13pt';
  425. #
  426. $bad_font_family = '"Times New Roman", Times, serif';
  427. $bad_font_size = '18pt';
  428. #
  429. # List of css names to add to the css style object
  430. # e.g. array('td.cool' => false);
  431. # true/false to not include the default $miner_font
  432. # The css name/value pairs must be defined in $colouroverride below
  433. $add_css_names = array();
  434. #
  435. # Edit this or redefine it in myminer.php to change the colour scheme
  436. # See $colourtable below for the list of names
  437. $colouroverride = array();
  438. #
  439. # Where to place the buttons: 'top' 'bot' 'both'
  440. # anything else means don't show them - case sensitive
  441. $placebuttons = 'top';
  442. #
  443. # This below allows you to put your own settings into a seperate file
  444. # so you don't need to update miner.php with your preferred settings
  445. # every time a new version is released
  446. # Just create the file 'myminer.php' in the same directory as
  447. # 'miner.php' - and put your own settings in there
  448. if (file_exists('myminer.php'))
  449. include_once('myminer.php');
  450. #
  451. # This is the system default that must always contain all necessary
  452. # colours so it must be a constant
  453. # You can override these values with $colouroverride
  454. # The only one missing is $warnfont
  455. # - which you can override directly anyway
  456. global $colourtable;
  457. $colourtable = array(
  458. 'body bgcolor' => '#ecffff',
  459. 'td color' => 'blue',
  460. 'td.two color' => 'blue',
  461. 'td.two background' => '#ecffff',
  462. 'td.h color' => 'blue',
  463. 'td.h background' => '#c4ffff',
  464. 'td.err color' => 'black',
  465. 'td.err background' => '#ff3050',
  466. 'td.bad color' => 'black',
  467. 'td.bad background' => '#ff3050',
  468. 'td.warn color' => 'black',
  469. 'td.warn background' => '#ffb050',
  470. 'td.sta color' => 'green',
  471. 'td.tot color' => 'blue',
  472. 'td.tot background' => '#fff8f2',
  473. 'td.lst color' => 'blue',
  474. 'td.lst background' => '#ffffdd',
  475. 'td.hi color' => 'blue',
  476. 'td.hi background' => '#f6ffff',
  477. 'td.lo color' => 'blue',
  478. 'td.lo background' => '#deffff'
  479. );
  480. #
  481. # A list of system default summary pages (defined further above)
  482. # that you can use by 'Name' in $customsummarypages
  483. global $sys_pages;
  484. $sys_pages = array(
  485. 'Mobile' => array($mobilepage, $mobilesum),
  486. 'Stats' => array($statspage, $statssum),
  487. 'Pools' => array($poolspage, $poolssum, $poolsext),
  488. 'DevNot' => array($devnotpage, $devnotsum),
  489. 'DevDet' => array($devdetpage, $devdetsum),
  490. 'Proto' => array($protopage, $protosum, $protoext),
  491. 'Kano' => array($kanogenpage, $kanogensum, $kanogenext),
  492. 'Summary' => array($syspage, $syssum)
  493. );
  494. #
  495. # Don't touch these 2
  496. $miner = null;
  497. $port = null;
  498. #
  499. global $rigips;
  500. $rigips = array();
  501. #
  502. # Ensure it is only ever shown once
  503. global $showndate;
  504. $showndate = false;
  505. #
  506. global $rownum;
  507. $rownum = 0;
  508. #
  509. // Login
  510. global $ses;
  511. $ses = 'rutroh';
  512. #
  513. function getcsp($name, $systempage = false)
  514. {
  515. global $customsummarypages, $user_pages, $sys_pages;
  516. if ($systempage === false)
  517. {
  518. if (!isset($customsummarypages[$name]))
  519. return false;
  520. $csp = $customsummarypages[$name];
  521. if (is_array($csp))
  522. {
  523. if (count($csp) < 2 || count($csp) > 3)
  524. return false;
  525. else
  526. return $csp;
  527. }
  528. }
  529. if (isset($user_pages[$name]))
  530. {
  531. $csp = $user_pages[$name];
  532. if (!is_array($csp) || count($csp) < 2 || count($csp) > 3)
  533. return false;
  534. else
  535. return $csp;
  536. }
  537. if (isset($sys_pages[$name]))
  538. {
  539. $csp = $sys_pages[$name];
  540. if (!is_array($csp) || count($csp) < 2 || count($csp) > 3)
  541. return false;
  542. else
  543. return $csp;
  544. }
  545. return false;
  546. }
  547. #
  548. function degenfields(&$sec, $name, $fields)
  549. {
  550. global $allowgen;
  551. if (!is_array($fields))
  552. return;
  553. foreach ($fields as $num => $fld)
  554. if (substr($fld, 0, 5) == 'BGEN.' || substr($fld, 0, 4) == 'GEN.')
  555. {
  556. $opts = explode('||', $fld, 2);
  557. if ($allowgen)
  558. {
  559. if (count($opts) > 1)
  560. $sec[$name][$num] = $opts[0];
  561. }
  562. else
  563. {
  564. if (count($opts) > 1)
  565. $sec[$name][$num] = $opts[1];
  566. else
  567. unset($sec[$name][$num]);
  568. }
  569. }
  570. }
  571. #
  572. # Allow BGEN/GEN fields to have a '||' replacement when gen is disabled
  573. # N.B. if gen is disabled and all page fields are GBEN/GEN without '||' then
  574. # the table will disappear
  575. # Replacements can be in the page fields and then also the ext group fields
  576. # All other $csp sections should list both separately
  577. function degen(&$csp)
  578. {
  579. $page = 0;
  580. if (isset($csp[$page]) && is_array($csp[$page]))
  581. foreach ($csp[$page] as $sec => $fields)
  582. degenfields($csp[$page], $sec, $fields);
  583. $ext = 2;
  584. if (isset($csp[$ext]) && is_array($csp[$ext]))
  585. foreach ($csp[$ext] as $sec => $types)
  586. if (is_array($types) && isset($types['group']))
  587. degenfields($types, 'group', $types['group']);
  588. }
  589. #
  590. function getcss($cssname, $dom = false)
  591. {
  592. global $colourtable, $colouroverride;
  593. $css = '';
  594. foreach ($colourtable as $cssdata => $value)
  595. {
  596. $cssobj = explode(' ', $cssdata, 2);
  597. if ($cssobj[0] == $cssname)
  598. {
  599. if (isset($colouroverride[$cssdata]))
  600. $value = $colouroverride[$cssdata];
  601. if ($dom == true)
  602. $css .= ' '.$cssobj[1].'='.$value;
  603. else
  604. $css .= $cssobj[1].':'.$value.'; ';
  605. }
  606. }
  607. return $css;
  608. }
  609. #
  610. function getdom($domname)
  611. {
  612. return getcss($domname, true);
  613. }
  614. #
  615. # N.B. don't call this before calling htmlhead()
  616. function php_pr($cmd)
  617. {
  618. global $here, $autorefresh;
  619. return "$here?ref=$autorefresh$cmd";
  620. }
  621. #
  622. function htmlhead($mcerr, $checkapi, $rig, $pg = null, $noscript = false)
  623. {
  624. global $doctype, $title, $miner_font_family, $miner_font_size;
  625. global $bad_font_family, $bad_font_size, $add_css_names;
  626. global $error, $readonly, $poolinputs, $here;
  627. global $ignorerefresh, $autorefresh;
  628. $extraparams = '';
  629. if ($rig != null && $rig != '')
  630. $extraparams = "&rig=$rig";
  631. else
  632. if ($pg != null && $pg != '')
  633. $extraparams = "&pg=$pg";
  634. if ($ignorerefresh == true || $autorefresh == 0)
  635. $refreshmeta = '';
  636. else
  637. {
  638. $url = "$here?ref=$autorefresh$extraparams";
  639. $refreshmeta = "\n<meta http-equiv='refresh' content='$autorefresh;url=$url'>";
  640. }
  641. if ($readonly === false && $checkapi === true)
  642. {
  643. $error = null;
  644. $access = api($rig, 'privileged');
  645. if ($error != null
  646. || !isset($access['STATUS']['STATUS'])
  647. || $access['STATUS']['STATUS'] != 'S')
  648. $readonly = true;
  649. }
  650. $miner_font = "font-family:$miner_font_family; font-size:$miner_font_size;";
  651. $bad_font = "font-family:$bad_font_family; font-size:$bad_font_size;";
  652. echo "$doctype<html><head>$refreshmeta
  653. <title>$title</title>
  654. <style type='text/css'>
  655. td { $miner_font ".getcss('td')."}
  656. td.two { $miner_font ".getcss('td.two')."}
  657. td.h { $miner_font ".getcss('td.h')."}
  658. td.err { $miner_font ".getcss('td.err')."}
  659. td.bad { $bad_font ".getcss('td.bad')."}
  660. td.warn { $miner_font ".getcss('td.warn')."}
  661. td.sta { $miner_font ".getcss('td.sta')."}
  662. td.tot { $miner_font ".getcss('td.tot')."}
  663. td.lst { $miner_font ".getcss('td.lst')."}
  664. td.hi { $miner_font ".getcss('td.hi')."}
  665. td.lo { $miner_font ".getcss('td.lo')."}\n";
  666. if (isset($add_css_names))
  667. foreach ($add_css_names as $css_name => $no_miner_font)
  668. {
  669. echo "$css_name { ";
  670. if ($no_miner_font !== true)
  671. echo "$miner_font ";
  672. echo getcss("$css_name")."}\n";
  673. }
  674. echo "</style>
  675. </head><body".getdom('body').">\n";
  676. if ($noscript === false)
  677. {
  678. echo "<script type='text/javascript'>
  679. function pr(a,m){if(m!=null){if(!confirm(m+'?'))return}window.location='$here?ref=$autorefresh'+a}\n";
  680. if ($ignorerefresh == false)
  681. echo "function prr(a){if(a){v=document.getElementById('refval').value}else{v=0}window.location='$here?ref='+v+'$extraparams'}\n";
  682. if ($readonly === false && $checkapi === true)
  683. {
  684. echo "function prc(a,m){pr('&arg='+a,m)}
  685. function prs(a,r){var c=a.substr(3);var z=c.split('|',2);var m=z[0].substr(0,1).toUpperCase()+z[0].substr(1)+' GPU '+z[1];prc(a+'&rig='+r,m)}
  686. function prs2(a,n,r){var v=document.getElementById('gi'+n).value;var c=a.substr(3);var z=c.split('|',2);var m='Set GPU '+z[1]+' '+z[0].substr(0,1).toUpperCase()+z[0].substr(1)+' to '+v;prc(a+','+v+'&rig='+r,m)}\n";
  687. if ($poolinputs === true)
  688. echo "function cbs(s){var t=s.replace(/\\\\/g,'\\\\\\\\'); return t.replace(/,/g, '\\\\,')}\nfunction pla(r){var u=document.getElementById('purl').value;var w=document.getElementById('pwork').value;var p=document.getElementById('ppass').value;pr('&rig='+r+'&arg=addpool|'+cbs(u)+','+cbs(w)+','+cbs(p),'Add Pool '+u)}\nfunction psp(r){var p=document.getElementById('prio').value;pr('&rig='+r+'&arg=poolpriority|'+p,'Set Pool Priorities to '+p)}\n";
  689. }
  690. echo "</script>\n";
  691. }
  692. ?>
  693. <table width=100% height=100% border=0 cellpadding=0 cellspacing=0 summary='Mine'>
  694. <tr><td align=center valign=top>
  695. <table border=0 cellpadding=4 cellspacing=0 summary='Mine'>
  696. <?php
  697. echo $mcerr;
  698. }
  699. #
  700. function minhead($mcerr = '')
  701. {
  702. global $readonly;
  703. $readonly = true;
  704. htmlhead($mcerr, false, null, null, true);
  705. }
  706. #
  707. global $haderror, $error;
  708. $haderror = false;
  709. $error = null;
  710. #
  711. function mcastrigs()
  712. {
  713. global $rigs, $mcastexpect, $mcastaddr, $mcastport, $mcastcode;
  714. global $mcastlistport, $mcasttimeout, $mcastretries, $error;
  715. $listname = "0.0.0.0";
  716. $rigs = array();
  717. $rep_soc = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
  718. if ($rep_soc === false || $rep_soc == null)
  719. {
  720. $msg = "ERR: mcast listen socket create(UDP) failed";
  721. if ($rigipsecurity === false)
  722. {
  723. $error = socket_strerror(socket_last_error());
  724. $error = "$msg '$error'\n";
  725. }
  726. else
  727. $error = "$msg\n";
  728. return;
  729. }
  730. $res = socket_bind($rep_soc, $listname, $mcastlistport);
  731. if ($res === false)
  732. {
  733. $msg1 = "ERR: mcast listen socket bind(";
  734. $msg2 = ") failed";
  735. if ($rigipsecurity === false)
  736. {
  737. $error = socket_strerror(socket_last_error());
  738. $error = "$msg1$listname,$mcastlistport$msg2 '$error'\n";
  739. }
  740. else
  741. $error = "$msg1$msg2\n";
  742. socket_close($rep_soc);
  743. return;
  744. }
  745. $retries = $mcastretries;
  746. $doretry = ($retries > 0);
  747. do
  748. {
  749. $mcast_soc = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
  750. if ($mcast_soc === false || $mcast_soc == null)
  751. {
  752. $msg = "ERR: mcast send socket create(UDP) failed";
  753. if ($rigipsecurity === false)
  754. {
  755. $error = socket_strerror(socket_last_error());
  756. $error = "$msg '$error'\n";
  757. }
  758. else
  759. $error = "$msg\n";
  760. socket_close($rep_soc);
  761. return;
  762. }
  763. $buf = "cgminer-$mcastcode-$mcastlistport";
  764. socket_sendto($mcast_soc, $buf, strlen($buf), 0, $mcastaddr, $mcastport);
  765. socket_close($mcast_soc);
  766. $stt = microtime(true);
  767. while (true)
  768. {
  769. $got = @socket_recvfrom($rep_soc, $buf, 32, MSG_DONTWAIT, $ip, $p);
  770. if ($got !== false && $got > 0)
  771. {
  772. $ans = explode('-', $buf, 4);
  773. if (count($ans) >= 3 && $ans[0] == 'cgm' && $ans[1] == 'FTW')
  774. {
  775. $rp = intval($ans[2]);
  776. if (count($ans) > 3)
  777. $mdes = str_replace("\0", '', $ans[3]);
  778. else
  779. $mdes = '';
  780. if (strlen($mdes) > 0)
  781. $rig = "$ip:$rp:$mdes";
  782. else
  783. $rig = "$ip:$rp";
  784. if (!in_array($rig, $rigs))
  785. $rigs[] = $rig;
  786. }
  787. }
  788. if ((microtime(true) - $stt) >= $mcasttimeout)
  789. break;
  790. usleep(100000);
  791. }
  792. if ($mcastexpect > 0 && count($rigs) >= $mcastexpect)
  793. $doretry = false;
  794. } while ($doretry && --$retries > 0);
  795. socket_close($rep_soc);
  796. }
  797. #
  798. function getrigs()
  799. {
  800. global $rigs;
  801. mcastrigs();
  802. sort($rigs);
  803. }
  804. #
  805. function getsock($rig, $addr, $port)
  806. {
  807. global $rigport, $rigips, $rignames, $rigipsecurity;
  808. global $haderror, $error, $socksndtimeoutsec, $sockrcvtimeoutsec;
  809. $port = trim($port);
  810. if (strlen($port) == 0)
  811. $port = $rigport;
  812. $error = null;
  813. $socket = null;
  814. $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
  815. if ($socket === false || $socket === null)
  816. {
  817. $haderror = true;
  818. if ($rigipsecurity === false)
  819. {
  820. $error = socket_strerror(socket_last_error());
  821. $msg = "socket create(TCP) failed";
  822. $error = "ERR: $msg '$error'\n";
  823. }
  824. else
  825. $error = "ERR: socket create(TCP) failed\n";
  826. return null;
  827. }
  828. // Ignore if this fails since the socket connect may work anyway
  829. // and nothing is gained by aborting if the option cannot be set
  830. // since we don't know in advance if it can connect
  831. socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, array('sec' => $socksndtimeoutsec, 'usec' => 0));
  832. socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array('sec' => $sockrcvtimeoutsec, 'usec' => 0));
  833. $res = socket_connect($socket, $addr, $port);
  834. if ($res === false)
  835. {
  836. $haderror = true;
  837. if ($rigipsecurity === false)
  838. {
  839. $error = socket_strerror(socket_last_error());
  840. $msg = "socket connect($addr,$port) failed";
  841. $error = "ERR: $msg '$error'\n";
  842. }
  843. else
  844. $error = "ERR: socket connect($rig) failed\n";
  845. socket_close($socket);
  846. return null;
  847. }
  848. if ($rignames !== false && !isset($rigips[$addr]))
  849. if (socket_getpeername($socket, $ip) == true)
  850. $rigips[$addr] = $ip;
  851. return $socket;
  852. }
  853. #
  854. function readsockline($socket)
  855. {
  856. $line = '';
  857. while (true)
  858. {
  859. $byte = socket_read($socket, 1);
  860. if ($byte === false || $byte === '')
  861. break;
  862. if ($byte === "\0")
  863. break;
  864. $line .= $byte;
  865. }
  866. return $line;
  867. }
  868. #
  869. function api_convert_escape($str)
  870. {
  871. $res = '';
  872. $len = strlen($str);
  873. for ($i = 0; $i < $len; $i++)
  874. {
  875. $ch = substr($str, $i, 1);
  876. if ($ch != '\\' || $i == ($len-1))
  877. $res .= $ch;
  878. else
  879. {
  880. $i++;
  881. $ch = substr($str, $i, 1);
  882. switch ($ch)
  883. {
  884. case '|':
  885. $res .= "\1";
  886. break;
  887. case '\\':
  888. $res .= "\2";
  889. break;
  890. case '=':
  891. $res .= "\3";
  892. break;
  893. case ',':
  894. $res .= "\4";
  895. break;
  896. default:
  897. $res .= $ch;
  898. }
  899. }
  900. }
  901. return $res;
  902. }
  903. #
  904. function revert($str)
  905. {
  906. return str_replace(array("\1", "\2", "\3", "\4"), array("|", "\\", "=", ","), $str);
  907. }
  908. #
  909. function api($rig, $cmd)
  910. {
  911. global $haderror, $error;
  912. global $miner, $port, $hidefields;
  913. $socket = getsock($rig, $miner, $port);
  914. if ($socket != null)
  915. {
  916. socket_write($socket, $cmd, strlen($cmd));
  917. $line = readsockline($socket);
  918. socket_close($socket);
  919. if (strlen($line) == 0)
  920. {
  921. $haderror = true;
  922. $error = "WARN: '$cmd' returned nothing\n";
  923. return $line;
  924. }
  925. # print "$cmd returned '$line'\n";
  926. $line = api_convert_escape($line);
  927. $data = array();
  928. $objs = explode('|', $line);
  929. foreach ($objs as $obj)
  930. {
  931. if (strlen($obj) > 0)
  932. {
  933. $items = explode(',', $obj);
  934. $item = $items[0];
  935. $id = explode('=', $items[0], 2);
  936. if (count($id) == 1 or !ctype_digit($id[1]))
  937. $name = $id[0];
  938. else
  939. $name = $id[0].$id[1];
  940. if (strlen($name) == 0)
  941. $name = 'null';
  942. $sectionname = preg_replace('/\d/', '', $name);
  943. if (isset($data[$name]))
  944. {
  945. $num = 1;
  946. while (isset($data[$name.$num]))
  947. $num++;
  948. $name .= $num;
  949. }
  950. $counter = 0;
  951. foreach ($items as $item)
  952. {
  953. $id = explode('=', $item, 2);
  954. if (isset($hidefields[$sectionname.'.'.$id[0]]))
  955. continue;
  956. if (count($id) == 2)
  957. $data[$name][$id[0]] = revert($id[1]);
  958. else
  959. $data[$name][$counter] = $id[0];
  960. $counter++;
  961. }
  962. }
  963. }
  964. return $data;
  965. }
  966. return null;
  967. }
  968. #
  969. function getparam($name, $both = false)
  970. {
  971. $a = null;
  972. if (isset($_POST[$name]))
  973. $a = $_POST[$name];
  974. if (($both === true) and ($a === null))
  975. {
  976. if (isset($_GET[$name]))
  977. $a = $_GET[$name];
  978. }
  979. if ($a == '' || $a == null)
  980. return null;
  981. // limit to 1K just to be safe
  982. return substr($a, 0, 1024);
  983. }
  984. #
  985. function newtable()
  986. {
  987. global $tablebegin, $rownum;
  988. echo $tablebegin;
  989. $rownum = 0;
  990. }
  991. #
  992. function newrow()
  993. {
  994. echo '<tr>';
  995. }
  996. #
  997. function othrow($row)
  998. {
  999. return "<tr>$row</tr>";
  1000. }
  1001. #
  1002. function otherrow($row)
  1003. {
  1004. echo othrow($row);
  1005. }
  1006. #
  1007. function endrow()
  1008. {
  1009. global $rownum;
  1010. echo '</tr>';
  1011. $rownum++;
  1012. }
  1013. #
  1014. function endtable()
  1015. {
  1016. global $tableend;
  1017. echo $tableend;
  1018. }
  1019. #
  1020. function classlastshare($when, $alldata, $warnclass, $errorclass)
  1021. {
  1022. global $checklastshare;
  1023. if ($checklastshare === false)
  1024. return '';
  1025. if ($when == 0)
  1026. return '';
  1027. if (!isset($alldata['MHS av']))
  1028. return '';
  1029. if ($alldata['MHS av'] == 0)
  1030. return '';
  1031. if (!isset($alldata['Last Share Time']))
  1032. return '';
  1033. if (!isset($alldata['Last Share Difficulty']))
  1034. return '';
  1035. $expected = pow(2, 32) / ($alldata['MHS av'] * pow(10, 6));
  1036. // If the share difficulty changes while waiting on a share,
  1037. // this calculation will of course be incorrect
  1038. $expected *= $alldata['Last Share Difficulty'];
  1039. $howlong = $when - $alldata['Last Share Time'];
  1040. if ($howlong < 1)
  1041. $howlong = 1;
  1042. if ($howlong > ($expected * 12))
  1043. return $errorclass;
  1044. if ($howlong > ($expected * 8))
  1045. return $warnclass;
  1046. return '';
  1047. }
  1048. #
  1049. function endzero($num)
  1050. {
  1051. $rep = preg_replace('/0*$/', '', $num);
  1052. if ($rep === '')
  1053. $rep = '0';
  1054. return $rep;
  1055. }
  1056. #
  1057. function fmt($section, $name, $value, $when, $alldata, $cf = NULL)
  1058. {
  1059. global $dfmt, $rownum;
  1060. if ($alldata == null)
  1061. $alldata = array();
  1062. $errorclass = 'err';
  1063. $warnclass = 'warn';
  1064. $lstclass = 'lst';
  1065. $hiclass = 'hi';
  1066. $loclass = 'lo';
  1067. $c2class = 'two';
  1068. $totclass = 'tot';
  1069. $b = '&nbsp;';
  1070. $class = '';
  1071. $nams = explode('.', $name);
  1072. if (count($nams) > 1)
  1073. $name = $nams[count($nams)-1];
  1074. $done = false;
  1075. if ($value === null)
  1076. {
  1077. $ret = $b;
  1078. $done = true;
  1079. }
  1080. else
  1081. if ($cf != NULL and function_exists($cf))
  1082. {
  1083. list($ret, $class) = $cf($section, $name, $value, $when, $alldata,
  1084. $warnclass, $errorclass, $hiclass, $loclass, $totclass);
  1085. if ($ret !== '')
  1086. $done = true;
  1087. }
  1088. if ($done === false)
  1089. {
  1090. $ret = $value;
  1091. /*
  1092. * To speed up the PHP, the case statement is just $name
  1093. * It used to be $section.'.'.$name
  1094. * If any names clash, the case code will need to check the value of
  1095. * $section to resolve the clash - as with 'Last Share Time' below
  1096. * If the code picks up a field that you wish to format differently,
  1097. * then you'll need a customsummarypage 'fmt' extension
  1098. */
  1099. switch ($name)
  1100. {
  1101. case '0':
  1102. break;
  1103. case 'Last Share Time':
  1104. if ($section == 'total')
  1105. break;
  1106. if ($section == 'POOL')
  1107. {
  1108. if ($value == 0)
  1109. $ret = 'Never';
  1110. else
  1111. $ret = date('H:i:s d-M', $value);
  1112. }
  1113. else
  1114. {
  1115. if ($value == 0
  1116. || (isset($alldata['Last Share Pool']) && $alldata['Last Share Pool'] == -1))
  1117. {
  1118. $ret = 'Never';
  1119. $class = $warnclass;
  1120. }
  1121. else
  1122. {
  1123. $ret = date('H:i:s', $value);
  1124. $class = classlastshare($when, $alldata, $warnclass, $errorclass);
  1125. }
  1126. }
  1127. break;
  1128. case 'Last getwork':
  1129. case 'Last Valid Work':
  1130. if ($section == 'total')
  1131. break;
  1132. if ($value == 0)
  1133. $ret = 'Never';
  1134. else
  1135. $ret = ($value - $when) . 's';
  1136. break;
  1137. case 'Last Share Pool':
  1138. if ($section == 'total')
  1139. break;
  1140. if ($value == -1)
  1141. {
  1142. $ret = 'None';
  1143. $class = $warnclass;
  1144. }
  1145. break;
  1146. case 'Elapsed':
  1147. case 'Device Elapsed':
  1148. if ($section == 'total')
  1149. break;
  1150. $s = $value % 60;
  1151. $value -= $s;
  1152. $value /= 60;
  1153. if ($value == 0)
  1154. $ret = $s.'s';
  1155. else
  1156. {
  1157. $m = $value % 60;
  1158. $value -= $m;
  1159. $value /= 60;
  1160. if ($value == 0)
  1161. $ret = sprintf("%dm$b%02ds", $m, $s);
  1162. else
  1163. {
  1164. $h = $value % 24;
  1165. $value -= $h;
  1166. $value /= 24;
  1167. if ($value == 0)
  1168. $ret = sprintf("%dh$b%02dm$b%02ds", $h, $m, $s);
  1169. else
  1170. {
  1171. if ($value == 1)
  1172. $days = '';
  1173. else
  1174. $days = 's';
  1175. $ret = sprintf("%dday$days$b%02dh$b%02dm$b%02ds", $value, $h, $m, $s);
  1176. }
  1177. }
  1178. }
  1179. break;
  1180. case 'Last Well':
  1181. if ($section == 'total')
  1182. break;
  1183. if ($value == '0')
  1184. {
  1185. $ret = 'Never';
  1186. $class = $warnclass;
  1187. }
  1188. else
  1189. $ret = date('H:i:s', $value);
  1190. break;
  1191. case 'Last Not Well':
  1192. if ($section == 'total')
  1193. break;
  1194. if ($value == '0')
  1195. $ret = 'Never';
  1196. else
  1197. {
  1198. $ret = date('H:i:s', $value);
  1199. $class = $errorclass;
  1200. }
  1201. break;
  1202. case 'Reason Not Well':
  1203. if ($section == 'total')
  1204. break;
  1205. if ($value != 'None')
  1206. $class = $errorclass;
  1207. break;
  1208. case 'Utility':
  1209. $ret = number_format($value, 2).'/m';
  1210. if ($value == 0)
  1211. $class = $errorclass;
  1212. else
  1213. if (isset($alldata['Difficulty Accepted'])
  1214. && isset($alldata['Accepted'])
  1215. && isset($alldata['MHS av'])
  1216. && ($alldata['Difficulty Accepted'] > 0)
  1217. && ($alldata['Accepted'] > 0))
  1218. {
  1219. $expected = 60 * $alldata['MHS av'] * (pow(10, 6) / pow(2, 32));
  1220. if ($expected == 0)
  1221. $expected = 0.000001; // 1 H/s
  1222. $da = $alldata['Difficulty Accepted'];
  1223. $a = $alldata['Accepted'];
  1224. $expected /= ($da / $a);
  1225. $ratio = $value / $expected;
  1226. if ($ratio < 0.9)
  1227. $class = $loclass;
  1228. else
  1229. if ($ratio > 1.1)
  1230. $class = $hiclass;
  1231. }
  1232. break;
  1233. case 'Work Utility':
  1234. $ret = number_format($value, 2).'/m';
  1235. break;
  1236. case 'Temperature':
  1237. if ($section == 'total')
  1238. break;
  1239. $ret = $value.'&deg;C';
  1240. if ($value == 0)
  1241. $ret = '&nbsp;';
  1242. break;
  1243. case 'Fan Percent':
  1244. if ($section == 'total')
  1245. break;
  1246. if ($value == 0)
  1247. $class = $warnclass;
  1248. else
  1249. {
  1250. if ($value == 100)
  1251. $class = $errorclass;
  1252. else
  1253. if ($value > 85)
  1254. $class = $warnclass;
  1255. }
  1256. break;
  1257. case 'Fan Speed':
  1258. if ($section == 'total')
  1259. break;
  1260. if ($value == 0)
  1261. $class = $warnclass;
  1262. else
  1263. if (isset($alldata['Fan Percent']))
  1264. {
  1265. $test = $alldata['Fan Percent'];
  1266. if ($test == 100)
  1267. $class = $errorclass;
  1268. else
  1269. if ($test > 85)
  1270. $class = $warnclass;
  1271. }
  1272. break;
  1273. case 'MHS av':
  1274. case 'MHS 5s':
  1275. case 'MHS 1m':
  1276. case 'MHS 5m':
  1277. case 'MHS 15m':
  1278. $parts = explode('.', $value, 2);
  1279. if (count($parts) == 1)
  1280. $dec = '';
  1281. else
  1282. $dec = '.'.$parts[1];
  1283. $ret = number_format((float)$parts[0]).$dec;
  1284. if ($value == 0)
  1285. $class = $errorclass;
  1286. else
  1287. if (isset($alldata['Difficulty Accepted'])
  1288. && isset($alldata['Accepted'])
  1289. && isset($alldata['Utility'])
  1290. && ($alldata['Difficulty Accepted'] > 0)
  1291. && ($alldata['Accepted'] > 0))
  1292. {
  1293. $expected = 60 * $value * (pow(10, 6) / pow(2, 32));
  1294. if ($expected == 0)
  1295. $expected = 0.000001; // 1 H/s
  1296. $da = $alldata['Difficulty Accepted'];
  1297. $a = $alldata['Accepted'];
  1298. $expected /= ($da / $a);
  1299. $ratio = $alldata['Utility'] / $expected;
  1300. if ($ratio < 0.9)
  1301. $class = $hiclass;
  1302. else
  1303. if ($ratio > 1.1)
  1304. $class = $loclass;
  1305. }
  1306. break;
  1307. case 'Total MH':
  1308. case 'Getworks':
  1309. case 'Works':
  1310. case 'Accepted':
  1311. case 'Rejected':
  1312. case 'Local Work':
  1313. case 'Discarded':
  1314. case 'Diff1 Shares':
  1315. case 'Diff1 Work':
  1316. case 'Times Sent':
  1317. case 'Bytes Sent':
  1318. case 'Net Bytes Sent':
  1319. case 'Times Recv':
  1320. case 'Bytes Recv':
  1321. case 'Net Bytes Recv':
  1322. $parts = explode('.', $value, 2);
  1323. if (count($parts) == 1)
  1324. $dec = '';
  1325. else
  1326. $dec = '.'.$parts[1];
  1327. $ret = number_format((float)$parts[0]).$dec;
  1328. break;
  1329. case 'Hs':
  1330. case 'W':
  1331. case 'history_time':
  1332. case 'Pool Wait':
  1333. case 'Pool Max':
  1334. case 'Pool Min':
  1335. case 'Pool Av':
  1336. case 'Min Diff':
  1337. case 'Max Diff':
  1338. case 'Work Diff':
  1339. $parts = explode('.', $value, 2);
  1340. if (count($parts) == 1)
  1341. $dec = '';
  1342. else
  1343. $dec = '.'.endzero($parts[1]);
  1344. $ret = number_format((float)$parts[0]).$dec;
  1345. break;
  1346. case 'Status':
  1347. if ($section == 'total')
  1348. break;
  1349. if ($value != 'Alive')
  1350. $class = $errorclass;
  1351. break;
  1352. case 'Enabled':
  1353. if ($section == 'total')
  1354. break;
  1355. if ($value != 'Y')
  1356. $class = $warnclass;
  1357. break;
  1358. case 'No Device':
  1359. if ($section == 'total')
  1360. break;
  1361. if ($value != 'false')
  1362. $class = $errorclass;
  1363. break;
  1364. case 'When':
  1365. case 'Current Block Time':
  1366. if ($section == 'total')
  1367. break;
  1368. $ret = date($dfmt, $value);
  1369. break;
  1370. case 'Last Share Difficulty':
  1371. if ($section == 'total')
  1372. break;
  1373. case 'Difficulty Accepted':
  1374. case 'Difficulty Rejected':
  1375. case 'Difficulty Stale':
  1376. if ($value != '')
  1377. $ret = number_format((float)$value, 2);
  1378. break;
  1379. case 'Device Hardware%':
  1380. case 'Device Rejected%':
  1381. case 'Pool Rejected%':
  1382. case 'Pool Stale%':
  1383. if ($section == 'total')
  1384. break;
  1385. if ($value != '')
  1386. $ret = number_format((float)$value, 2) . '%';
  1387. break;
  1388. case 'Best Share':
  1389. if ($section == 'total')
  1390. break;
  1391. case 'Hardware Errors':
  1392. if ($value != '')
  1393. $ret = number_format((float)$value);
  1394. break;
  1395. // BUTTON.
  1396. case 'Rig':
  1397. case 'Pool':
  1398. // Sample GEN fields
  1399. case 'Mined':
  1400. if ($value != '')
  1401. $ret = number_format((float)$value * 100.0, 3) . '%';
  1402. break;
  1403. case 'Acc':
  1404. case 'Rej':
  1405. if ($value != '')
  1406. $ret = number_format((float)$value * 100.0, 2) . '%';
  1407. break;
  1408. case 'GHS av':
  1409. case 'GHS 5m':
  1410. case 'GHS WU':
  1411. case 'GHS Acc':
  1412. if ($value != '')
  1413. $ret = number_format((float)$value, 2);
  1414. break;
  1415. case 'AvShr':
  1416. if ($section == 'total')
  1417. break;
  1418. if ($value != '')
  1419. $ret = number_format((float)$value, 2);
  1420. if ($value == 0)
  1421. $class = $warnclass;
  1422. break;
  1423. }
  1424. }
  1425. if ($section == 'NOTIFY' && substr($name, 0, 1) == '*' && $value != '0')
  1426. $class = $errorclass;
  1427. if ($class == '' && $section != 'POOL')
  1428. $class = classlastshare($when, $alldata, $lstclass, $lstclass);
  1429. if ($class == '' && $section == 'total')
  1430. $class = $totclass;
  1431. if ($class == '' && ($rownum % 2) == 0)
  1432. $class = $c2class;
  1433. if ($ret === '')
  1434. $ret = $b;
  1435. if ($class !== '')
  1436. $class = " class=$class";
  1437. return array($ret, $class);
  1438. }
  1439. #
  1440. global $poolcmd;
  1441. $poolcmd = array( 'Switch to' => 'switchpool',
  1442. 'Enable' => 'enablepool',
  1443. 'Disable' => 'disablepool',
  1444. 'Remove' => 'removepool' );
  1445. #
  1446. function showhead($cmd, $values, $justnames = false)
  1447. {
  1448. global $poolcmd, $readonly;
  1449. newrow();
  1450. foreach ($values as $name => $value)
  1451. {
  1452. if ($name == '0' or $name == '')
  1453. $name = '&nbsp;';
  1454. echo "<td valign=bottom class=h>$name</td>";
  1455. }
  1456. if ($justnames === false && $cmd == 'pools' && $readonly === false)
  1457. foreach ($poolcmd as $name => $pcmd)
  1458. echo "<td valign=bottom class=h>$name</td>";
  1459. endrow();
  1460. }
  1461. #
  1462. function showdatetime()
  1463. {
  1464. global $dfmt;
  1465. otherrow('<td class=sta>Date: '.date($dfmt).'</td>');
  1466. }
  1467. #
  1468. global $singlerigsum;
  1469. $singlerigsum = array(
  1470. 'devs' => array('MHS av' => 1, 'MHS 5s' => 1, 'MHS 1m' => 1, 'MHS 5m' => 1,
  1471. 'MHS 15m' => 1, 'Accepted' => 1, 'Rejected' => 1,
  1472. 'Hardware Errors' => 1, 'Utility' => 1, 'Total MH' => 1,
  1473. 'Diff1 Shares' => 1, 'Diff1 Work' => 1,
  1474. 'Difficulty Accepted' => 1, 'Difficulty Rejected' => 1),
  1475. 'pools' => array('Getworks' => 1, 'Accepted' => 1, 'Rejected' => 1, 'Discarded' => 1,
  1476. 'Stale' => 1, 'Get Failures' => 1, 'Remote Failures' => 1,
  1477. 'Diff1 Shares' => 1, 'Diff1 Work' => 1,
  1478. 'Difficulty Accepted' => 1, 'Difficulty Rejected' => 1,
  1479. 'Difficulty Stale' => 1),
  1480. 'notify' => array('*' => 1));
  1481. #
  1482. function showtotal($total, $when, $oldvalues)
  1483. {
  1484. global $rigtotals;
  1485. list($showvalue, $class) = fmt('total', '', 'Total:', $when, null);
  1486. echo "<td$class align=right>$showvalue</td>";
  1487. $skipfirst = true;
  1488. foreach ($oldvalues as $name => $value)
  1489. {
  1490. if ($skipfirst === true)
  1491. {
  1492. $skipfirst = false;
  1493. continue;
  1494. }
  1495. if (isset($total[$name]))
  1496. $newvalue = $total[$name];
  1497. else
  1498. $newvalue = '';
  1499. list($showvalue, $class) = fmt('total', $name, $newvalue, $when, null);
  1500. echo "<td$class";
  1501. if ($rigtotals === true)
  1502. echo ' align=right';
  1503. echo ">$showvalue</td>";
  1504. }
  1505. }
  1506. #
  1507. function details($cmd, $list, $rig)
  1508. {
  1509. global $dfmt, $poolcmd, $readonly, $showndate;
  1510. global $rownum, $rigtotals, $forcerigtotals, $singlerigsum;
  1511. $when = 0;
  1512. $stas = array('S' => 'Success', 'W' => 'Warning', 'I' => 'Informational', 'E' => 'Error', 'F' => 'Fatal');
  1513. newtable();
  1514. if ($showndate === false)
  1515. {
  1516. showdatetime();
  1517. endtable();
  1518. newtable();
  1519. $showndate = true;
  1520. }
  1521. if (isset($list['STATUS']))
  1522. {
  1523. newrow();
  1524. echo '<td>Computer: '.$list['STATUS']['Description'].'</td>';
  1525. if (isset($list['STATUS']['When']))
  1526. {
  1527. echo '<td>When: '.date($dfmt, $list['STATUS']['When']).'</td>';
  1528. $when = $list['STATUS']['When'];
  1529. }
  1530. $sta = $list['STATUS']['STATUS'];
  1531. echo '<td>Status: '.$stas[$sta].'</td>';
  1532. echo '<td>Message: '.$list['STATUS']['Msg'].'</td>';
  1533. endrow();
  1534. }
  1535. if ($rigtotals === true && isset($singlerigsum[$cmd]))
  1536. $dototal = $singlerigsum[$cmd];
  1537. else
  1538. $dototal = array();
  1539. $total = array();
  1540. $section = '';
  1541. $oldvalues = null;
  1542. foreach ($list as $item => $values)
  1543. {
  1544. if ($item == 'STATUS')
  1545. continue;
  1546. $sectionname = preg_replace('/\d/', '', $item);
  1547. // Handle 'devs' possibly containing >1 table
  1548. if ($sectionname != $section)
  1549. {
  1550. if ($oldvalues != null && count($total) > 0
  1551. && ($rownum > 2 || $forcerigtotals === true))
  1552. showtotal($total, $when, $oldvalues);
  1553. endtable();
  1554. newtable();
  1555. showhead($cmd, $values);
  1556. $section = $sectionname;
  1557. }
  1558. newrow();
  1559. foreach ($values as $name => $value)
  1560. {
  1561. list($showvalue, $class) = fmt($section, $name, $value, $when, $values);
  1562. echo "<td$class";
  1563. if ($rigtotals === true)
  1564. echo ' align=right';
  1565. echo ">$showvalue</td>";
  1566. if (isset($dototal[$name])
  1567. || (isset($dototal['*']) and substr($name, 0, 1) == '*'))
  1568. {
  1569. if (isset($total[$name]))
  1570. $total[$name] += $value;
  1571. else
  1572. $total[$name] = $value;
  1573. }
  1574. }
  1575. if ($cmd == 'pools' && $readonly === false)
  1576. {
  1577. reset($values);
  1578. $pool = current($values);
  1579. foreach ($poolcmd as $name => $pcmd)
  1580. {
  1581. list($ignore, $class) = fmt('BUTTON', 'Pool', '', $when, $values);
  1582. echo "<td$class>";
  1583. if ($pool === false)
  1584. echo '&nbsp;';
  1585. else
  1586. {
  1587. echo "<input type=button value='Pool $pool'";
  1588. echo " onclick='prc(\"$pcmd|$pool&rig=$rig\",\"$name Pool $pool\")'>";
  1589. }
  1590. echo '</td>';
  1591. }
  1592. }
  1593. endrow();
  1594. $oldvalues = $values;
  1595. }
  1596. if ($oldvalues != null && count($total) > 0
  1597. && ($rownum > 2 || $forcerigtotals === true))
  1598. showtotal($total, $when, $oldvalues);
  1599. endtable();
  1600. }
  1601. #
  1602. global $devs;
  1603. $devs = null;
  1604. #
  1605. function showpoolinputs($rig, $ans)
  1606. {
  1607. global $readonly, $poolinputs;
  1608. if ($readonly === true || $poolinputs === false)
  1609. return;
  1610. newtable();
  1611. newrow();
  1612. $inps = array('Pool URL' => array('purl', 20),
  1613. 'Worker Name' => array('pwork', 10),
  1614. 'Worker Password' => array('ppass', 10));
  1615. $b = '&nbsp;';
  1616. echo "<td align=right class=h> Add a pool: </td><td>";
  1617. foreach ($inps as $text => $name)
  1618. echo "$text: <input name='".$name[0]."' id='".$name[0]."' value='' type=text size=".$name[1]."> ";
  1619. echo "</td><td align=middle><input type=button value='Add' onclick='pla($rig)'></td>";
  1620. endrow();
  1621. if (count($ans) > 1)
  1622. {
  1623. newrow();
  1624. echo '<td align=right class=h> Set pool priorities: </td>';
  1625. echo "<td> Comma list of pool numbers: <input type=text name=prio id=prio size=20>";
  1626. echo "</td><td align=middle><input type=button value='Set' onclick='psp($rig)'></td>";
  1627. endrow();
  1628. }
  1629. endtable();
  1630. }
  1631. #
  1632. function process($cmds, $rig)
  1633. {
  1634. global $error, $devs;
  1635. global $warnfont, $warnoff;
  1636. $count = count($cmds);
  1637. foreach ($cmds as $cmd => $des)
  1638. {
  1639. $process = api($rig, $cmd);
  1640. if ($error != null)
  1641. {
  1642. otherrow("<td colspan=100>Error getting $des: $warnfont$error$warnoff</td>");
  1643. break;
  1644. }
  1645. else
  1646. {
  1647. details($cmd, $process, $rig);
  1648. if ($cmd == 'devs')
  1649. $devs = $process;
  1650. if ($cmd == 'pools')
  1651. showpoolinputs($rig, $process);
  1652. # Not after the last one
  1653. if (--$count > 0)
  1654. otherrow('<td><br><br></td>');
  1655. }
  1656. }
  1657. }
  1658. #
  1659. function rigname($rig, $rigname)
  1660. {
  1661. global $rigs, $rignames, $rigips;
  1662. if (isset($rigs[$rig]))
  1663. {
  1664. $parts = explode(':', $rigs[$rig], 3);
  1665. if (count($parts) == 3)
  1666. $rigname = $parts[2];
  1667. else
  1668. if ($rignames !== false)
  1669. {
  1670. switch ($rignames)
  1671. {
  1672. case 'ip':
  1673. if (isset($parts[0]) && isset($rigips[$parts[0]]))
  1674. {
  1675. $ip = explode('.', $rigips[$parts[0]]);
  1676. if (count($ip) == 4)
  1677. $rigname = intval($ip[3]);
  1678. }
  1679. break;
  1680. case 'ipx':
  1681. if (isset($parts[0]) && isset($rigips[$parts[0]]))
  1682. {
  1683. $ip = explode('.', $rigips[$parts[0]]);
  1684. if (count($ip) == 4)
  1685. $rigname = intval($ip[3], 16);
  1686. }
  1687. break;
  1688. }
  1689. }
  1690. }
  1691. return $rigname;
  1692. }
  1693. #
  1694. function riginput($rig, $rigname, $usebuttons)
  1695. {
  1696. $rigname = rigname($rig, $rigname);
  1697. if ($usebuttons === true)
  1698. return "<input type=button value='$rigname' onclick='pr(\"&rig=$rig\",null)'>";
  1699. else
  1700. return "<a href='".php_pr("&rig=$rig")."'>$rigname</a>";
  1701. }
  1702. #
  1703. function rigbutton($rig, $rigname, $when, $row, $usebuttons)
  1704. {
  1705. list($value, $class) = fmt('BUTTON', 'Rig', '', $when, $row);
  1706. if ($rig === '')
  1707. $ri = '&nbsp;';
  1708. else
  1709. $ri = riginput($rig, $rigname, $usebuttons);
  1710. return "<td align=middle$class>$ri</td>";
  1711. }
  1712. #
  1713. function showrigs($anss, $headname, $rigname)
  1714. {
  1715. global $rigbuttons;
  1716. $dthead = array($headname => 1, 'STATUS' => 1, 'Description' => 1, 'When' => 1, 'API' => 1, 'CGMiner' => 1);
  1717. showhead('', $dthead);
  1718. foreach ($anss as $rig => $ans)
  1719. {
  1720. if ($ans == null)
  1721. continue;
  1722. newrow();
  1723. $when = 0;
  1724. if (isset($ans['STATUS']['When']))
  1725. $when = $ans['STATUS']['When'];
  1726. foreach ($ans as $item => $row)
  1727. {
  1728. if ($item != 'STATUS' && $item != 'VERSION')
  1729. continue;
  1730. foreach ($dthead as $name => $x)
  1731. {
  1732. if ($item == 'STATUS' && $name == $headname)
  1733. echo rigbutton($rig, $rigname.$rig, $when, null, $rigbuttons);
  1734. else
  1735. {
  1736. if (isset($row[$name]))
  1737. {
  1738. list($showvalue, $class) = fmt('STATUS', $name, $row[$name], $when, null);
  1739. echo "<td$class align=right>$showvalue</td>";
  1740. }
  1741. }
  1742. }
  1743. }
  1744. endrow();
  1745. }
  1746. }
  1747. #
  1748. function refreshbuttons()
  1749. {
  1750. global $ignorerefresh, $changerefresh, $autorefresh;
  1751. if ($ignorerefresh == false && $changerefresh == true)
  1752. {
  1753. echo '&nbsp;&nbsp;&nbsp;&nbsp;';
  1754. echo "<input type=button value='Auto Refresh:' onclick='prr(true)'>";
  1755. echo "<input type=text name='refval' id='refval' size=2 value='$autorefresh'>";
  1756. echo "<input type=button value='Off' onclick='prr(false)'>";
  1757. }
  1758. }
  1759. #
  1760. function pagebuttons($rig, $pg)
  1761. {
  1762. global $readonly, $rigs, $rigbuttons, $userlist, $ses;
  1763. global $allowcustompages, $customsummarypages;
  1764. if ($rig === null)
  1765. {
  1766. $prev = null;
  1767. $next = null;
  1768. if ($pg === null)
  1769. $refresh = '';
  1770. else
  1771. $refresh = "&pg=$pg";
  1772. }
  1773. else
  1774. {
  1775. switch (count($rigs))
  1776. {
  1777. case 0:
  1778. case 1:
  1779. $prev = null;
  1780. $next = null;
  1781. break;
  1782. case 2:
  1783. $prev = null;
  1784. $next = ($rig + 1) % count($rigs);
  1785. break;
  1786. default:
  1787. $prev = ($rig - 1) % count($rigs);
  1788. $next = ($rig + 1) % count($rigs);
  1789. break;
  1790. }
  1791. $refresh = "&rig=$rig";
  1792. }
  1793. echo '<tr><td><table cellpadding=0 cellspacing=0 border=0><tr><td nowrap>';
  1794. if ($userlist === null || isset($_SESSION[$ses]))
  1795. {
  1796. if ($prev !== null)
  1797. echo riginput($prev, 'Prev', true).'&nbsp;';
  1798. echo "<input type=button value='Refresh' onclick='pr(\"$refresh\",null)'>&nbsp;";
  1799. if ($next !== null)
  1800. echo riginput($next, 'Next', true).'&nbsp;';
  1801. echo '&nbsp;';
  1802. if (count($rigs) > 1 and getcsp('Summary', true) !== false)
  1803. echo "<input type=button value='Summary' onclick='pr(\"\",null)'>&nbsp;";
  1804. }
  1805. if ($allowcustompages === true)
  1806. {
  1807. if ($userlist === null || isset($_SESSION[$ses]))
  1808. $list = $customsummarypages;
  1809. else
  1810. {
  1811. if ($userlist !== null && isset($userlist['def']))
  1812. $list = array_flip($userlist['def']);
  1813. else
  1814. $list = array();
  1815. }
  1816. foreach ($list as $pagename => $data)
  1817. if (getcsp($pagename) !== false)
  1818. echo "<input type=button value='$pagename' onclick='pr(\"&pg=$pagename\",null)'>&nbsp;";
  1819. }
  1820. echo '</td><td width=100%>&nbsp;</td><td nowrap>';
  1821. if ($rig !== null && $readonly === false)
  1822. {
  1823. $rg = '';
  1824. if (count($rigs) > 1)
  1825. $rg = " Rig $rig";
  1826. echo "<input type=button value='Restart' onclick='prc(\"restart&rig=$rig\",\"Restart CGMiner$rg\")'>";
  1827. echo "&nbsp;<input type=button value='Quit' onclick='prc(\"quit&rig=$rig\",\"Quit CGMiner$rg\")'>";
  1828. }
  1829. refreshbuttons();
  1830. if (isset($_SESSION[$ses]))
  1831. echo "&nbsp;<input type=button value='Logout' onclick='pr(\"&logout=1\",null)'>";
  1832. else
  1833. if ($userlist !== null)
  1834. echo "&nbsp;<input type=button value='Login' onclick='pr(\"&login=1\",null)'>";
  1835. echo "</td></tr></table></td></tr>";
  1836. }
  1837. #
  1838. function doOne($rig, $preprocess)
  1839. {
  1840. global $haderror, $readonly, $notify, $rigs;
  1841. global $placebuttons;
  1842. if ($placebuttons == 'top' || $placebuttons == 'both')
  1843. pagebuttons($rig, null);
  1844. if ($preprocess != null)
  1845. process(array($preprocess => $preprocess), $rig);
  1846. $cmds = array( 'devs' => 'device list',
  1847. 'summary' => 'summary information',
  1848. 'pools' => 'pool list');
  1849. if ($notify)
  1850. $cmds['notify'] = 'device status';
  1851. $cmds['config'] = 'cgminer config';
  1852. process($cmds, $rig);
  1853. if ($placebuttons == 'bot' || $placebuttons == 'both')
  1854. pagebuttons($rig, null);
  1855. }
  1856. #
  1857. global $sectionmap;
  1858. # map sections to their api command
  1859. # DEVS is a special case that will match PGA or ASC
  1860. # so you can have a single table with both in it
  1861. # DATE is hard coded so not in here
  1862. $sectionmap = array(
  1863. 'RIGS' => 'version',
  1864. 'SUMMARY' => 'summary',
  1865. 'POOL' => 'pools',
  1866. 'DEVS' => 'devs',
  1867. 'EDEVS' => 'edevs',
  1868. 'PGA' => 'devs', // You would normally use DEVS
  1869. 'ASC' => 'devs', // You would normally use DEVS
  1870. 'NOTIFY' => 'notify',
  1871. 'DEVDETAILS' => 'devdetails',
  1872. 'STATS' => 'stats',
  1873. 'ESTATS' => 'estats',
  1874. 'CONFIG' => 'config',
  1875. 'COIN' => 'coin',
  1876. 'USBSTATS' => 'usbstats');
  1877. #
  1878. function joinfields($section1, $section2, $join, $results)
  1879. {
  1880. global $sectionmap;
  1881. $name1 = $sectionmap[$section1];
  1882. $name2 = $sectionmap[$section2];
  1883. $newres = array();
  1884. // foreach rig in section1
  1885. foreach ($results[$name1] as $rig => $result)
  1886. {
  1887. $status = null;
  1888. // foreach answer section in the rig api call
  1889. foreach ($result as $name1b => $fields1b)
  1890. {
  1891. if ($name1b == 'STATUS')
  1892. {
  1893. // remember the STATUS from section1
  1894. $status = $result[$name1b];
  1895. continue;
  1896. }
  1897. // foreach answer section in the rig api call (for the other api command)
  1898. foreach ($results[$name2][$rig] as $name2b => $fields2b)
  1899. {
  1900. if ($name2b == 'STATUS')
  1901. continue;
  1902. // If match the same field values of fields in $join
  1903. $match = true;
  1904. foreach ($join as $field)
  1905. if ($fields1b[$field] != $fields2b[$field])
  1906. {
  1907. $match = false;
  1908. break;
  1909. }
  1910. if ($match === true)
  1911. {
  1912. if ($status != null)
  1913. {
  1914. $newres[$rig]['STATUS'] = $status;
  1915. $status = null;
  1916. }
  1917. $subsection = $section1.'+'.$section2;
  1918. $subsection .= preg_replace('/[^0-9]/', '', $name1b.$name2b);
  1919. foreach ($fields1b as $nam => $val)
  1920. $newres[$rig][$subsection]["$section1.$nam"] = $val;
  1921. foreach ($fields2b as $nam => $val)
  1922. $newres[$rig][$subsection]["$section2.$nam"] = $val;
  1923. }
  1924. }
  1925. }
  1926. }
  1927. return $newres;
  1928. }
  1929. #
  1930. function joinlr($section1, $section2, $join, $results)
  1931. {
  1932. global $sectionmap;
  1933. $name1 = $sectionmap[$section1];
  1934. $name2 = $sectionmap[$section2];
  1935. $newres = array();
  1936. // foreach rig in section1
  1937. foreach ($results[$name1] as $rig => $result)
  1938. {
  1939. $status = null;
  1940. // foreach answer section in the rig api call
  1941. foreach ($result as $name1b => $fields1b)
  1942. {
  1943. if ($name1b == 'STATUS')
  1944. {
  1945. // remember the STATUS from section1
  1946. $status = $result[$name1b];
  1947. continue;
  1948. }
  1949. // Build L string to be matched
  1950. // : means a string constant otherwise it's a field name
  1951. $Lval = '';
  1952. foreach ($join['L'] as $field)
  1953. {
  1954. if (substr($field, 0, 1) == ':')
  1955. $Lval .= substr($field, 1);
  1956. else
  1957. $Lval .= $fields1b[$field];
  1958. }
  1959. // foreach answer section in the rig api call (for the other api command)
  1960. foreach ($results[$name2][$rig] as $name2b => $fields2b)
  1961. {
  1962. if ($name2b == 'STATUS')
  1963. continue;
  1964. // Build R string and compare
  1965. // : means a string constant otherwise it's a field name
  1966. $Rval = '';
  1967. foreach ($join['R'] as $field)
  1968. {
  1969. if (substr($field, 0, 1) == ':')
  1970. $Rval .= substr($field, 1);
  1971. else
  1972. $Rval .= $fields2b[$field];
  1973. }
  1974. if ($Lval === $Rval)
  1975. {
  1976. if ($status != null)
  1977. {
  1978. $newres[$rig]['STATUS'] = $status;
  1979. $status = null;
  1980. }
  1981. $subsection = $section1.'+'.$section2;
  1982. $subsection .= preg_replace('/[^0-9]/', '', $name1b.$name2b);
  1983. foreach ($fields1b as $nam => $val)
  1984. $newres[$rig][$subsection]["$section1.$nam"] = $val;
  1985. foreach ($fields2b as $nam => $val)
  1986. $newres[$rig][$subsection]["$section2.$nam"] = $val;
  1987. }
  1988. }
  1989. }
  1990. }
  1991. return $newres;
  1992. }
  1993. #
  1994. function joinall($section1, $section2, $results)
  1995. {
  1996. global $sectionmap;
  1997. $name1 = $sectionmap[$section1];
  1998. $name2 = $sectionmap[$section2];
  1999. $newres = array();
  2000. // foreach rig in section1
  2001. foreach ($results[$name1] as $rig => $result)
  2002. {
  2003. // foreach answer section in the rig api call
  2004. foreach ($result as $name1b => $fields1b)
  2005. {
  2006. if ($name1b == 'STATUS')
  2007. {
  2008. // copy the STATUS from section1
  2009. $newres[$rig][$name1b] = $result[$name1b];
  2010. continue;
  2011. }
  2012. // foreach answer section in the rig api call (for the other api command)
  2013. foreach ($results[$name2][$rig] as $name2b => $fields2b)
  2014. {
  2015. if ($name2b == 'STATUS')
  2016. continue;
  2017. $subsection = $section1.'+'.$section2;
  2018. $subsection .= preg_replace('/[^0-9]/', '', $name1b.$name2b);
  2019. foreach ($fields1b as $nam => $val)
  2020. $newres[$rig][$subsection]["$section1.$nam"] = $val;
  2021. foreach ($fields2b as $nam => $val)
  2022. $newres[$rig][$subsection]["$section2.$nam"] = $val;
  2023. }
  2024. }
  2025. }
  2026. return $newres;
  2027. }
  2028. #
  2029. function joinsections($sections, $results, $errors)
  2030. {
  2031. global $sectionmap;
  2032. foreach ($sections as $section => $fields)
  2033. if ($section != 'DATE' && !isset($sectionmap[$section]))
  2034. {
  2035. $both = explode('+', $section, 2);
  2036. if (count($both) > 1)
  2037. {
  2038. switch($both[0])
  2039. {
  2040. case 'SUMMARY':
  2041. switch($both[1])
  2042. {
  2043. case 'POOL':
  2044. case 'DEVS':
  2045. case 'EDEVS':
  2046. case 'CONFIG':
  2047. case 'COIN':
  2048. $sectionmap[$section] = $section;
  2049. $results[$section] = joinall($both[0], $both[1], $results);
  2050. break;
  2051. default:
  2052. $errors[] = "Error: Invalid section '$section'";
  2053. break;
  2054. }
  2055. break;
  2056. case 'DEVS':
  2057. case 'EDEVS':
  2058. switch($both[1])
  2059. {
  2060. case 'NOTIFY':
  2061. case 'DEVDETAILS':
  2062. case 'USBSTATS':
  2063. $join = array('Name', 'ID');
  2064. $sectionmap[$section] = $section;
  2065. $results[$section] = joinfields($both[0], $both[1], $join, $results);
  2066. break;
  2067. case 'STATS':
  2068. case 'ESTATS':
  2069. $join = array('L' => array('Name','ID'), 'R' => array('ID'));
  2070. $sectionmap[$section] = $section;
  2071. $results[$section] = joinlr($both[0], $both[1], $join, $results);
  2072. break;
  2073. default:
  2074. $errors[] = "Error: Invalid section '$section'";
  2075. break;
  2076. }
  2077. break;
  2078. case 'POOL':
  2079. switch($both[1])
  2080. {
  2081. case 'STATS':
  2082. $join = array('L' => array(':POOL','POOL'), 'R' => array('ID'));
  2083. $sectionmap[$section] = $section;
  2084. $results[$section] = joinlr($both[0], $both[1], $join, $results);
  2085. break;
  2086. default:
  2087. $errors[] = "Error: Invalid section '$section'";
  2088. break;
  2089. }
  2090. break;
  2091. default:
  2092. $errors[] = "Error: Invalid section '$section'";
  2093. break;
  2094. }
  2095. }
  2096. else
  2097. $errors[] = "Error: Invalid section '$section'";
  2098. }
  2099. return array($results, $errors);
  2100. }
  2101. #
  2102. function secmatch($section, $field)
  2103. {
  2104. if ($section == $field)
  2105. return true;
  2106. if (($section == 'DEVS' || $section == 'EDEVS')
  2107. && ($field == 'PGA' || $field == 'ASC'))
  2108. return true;
  2109. return false;
  2110. }
  2111. #
  2112. function customset($showfields, $sum, $section, $rig, $isbutton, $result, $total, $cf = NULL)
  2113. {
  2114. global $rigbuttons;
  2115. $rn = 0;
  2116. foreach ($result as $sec => $row)
  2117. {
  2118. $secname = preg_replace('/\d/', '', $sec);
  2119. if ($sec != 'total')
  2120. if (!secmatch($section, $secname))
  2121. continue;
  2122. newrow();
  2123. $when = 0;
  2124. if (isset($result['STATUS']['When']))
  2125. $when = $result['STATUS']['When'];
  2126. if ($isbutton)
  2127. echo rigbutton($rig, $rig, $when, $row, $rigbuttons);
  2128. else
  2129. {
  2130. list($ignore, $class) = fmt('total', '', '', $when, $row, $cf);
  2131. echo "<td align=middle$class>$rig</td>";
  2132. }
  2133. foreach ($showfields as $name => $one)
  2134. {
  2135. if ($name === '#' and $sec != 'total')
  2136. {
  2137. $rn++;
  2138. $value = $rn;
  2139. if (isset($total[$name]))
  2140. $total[$name]++;
  2141. else
  2142. $total[$name] = 1;
  2143. }
  2144. elseif (isset($row[$name]))
  2145. {
  2146. $value = $row[$name];
  2147. if (isset($sum[$section][$name]))
  2148. {
  2149. if (isset($total[$name]))
  2150. $total[$name] += $value;
  2151. else
  2152. $total[$name] = $value;
  2153. }
  2154. }
  2155. else
  2156. {
  2157. if ($sec == 'total' && isset($total[$name]))
  2158. $value = $total[$name];
  2159. else
  2160. $value = null;
  2161. }
  2162. if (strpos($secname, '+') === false)
  2163. list($showvalue, $class) = fmt($secname, $name, $value, $when, $row, $cf);
  2164. else
  2165. {
  2166. if ($name != '#')
  2167. $parts = explode('.', $name, 2);
  2168. else
  2169. $parts[0] = $parts[1] = '#';
  2170. list($showvalue, $class) = fmt($parts[0], $parts[1], $value, $when, $row, $cf);
  2171. }
  2172. echo "<td$class align=right>$showvalue</td>";
  2173. }
  2174. endrow();
  2175. }
  2176. return $total;
  2177. }
  2178. #
  2179. function docalc($func, $data)
  2180. {
  2181. switch ($func)
  2182. {
  2183. case 'sum':
  2184. $tot = 0;
  2185. foreach ($data as $val)
  2186. $tot += $val;
  2187. return $tot;
  2188. case 'avg':
  2189. $tot = 0;
  2190. foreach ($data as $val)
  2191. $tot += $val;
  2192. return ($tot / count($data));
  2193. case 'min':
  2194. $ans = null;
  2195. foreach ($data as $val)
  2196. if ($ans === null)
  2197. $ans = $val;
  2198. else
  2199. if ($val < $ans)
  2200. $ans = $val;
  2201. return $ans;
  2202. case 'max':
  2203. $ans = null;
  2204. foreach ($data as $val)
  2205. if ($ans === null)
  2206. $ans = $val;
  2207. else
  2208. if ($val > $ans)
  2209. $ans = $val;
  2210. return $ans;
  2211. case 'lo':
  2212. $ans = null;
  2213. foreach ($data as $val)
  2214. if ($ans === null)
  2215. $ans = $val;
  2216. else
  2217. if (strcasecmp($val, $ans) < 0)
  2218. $ans = $val;
  2219. return $ans;
  2220. case 'hi':
  2221. $ans = null;
  2222. foreach ($data as $val)
  2223. if ($ans === null)
  2224. $ans = $val;
  2225. else
  2226. if (strcasecmp($val, $ans) > 0)
  2227. $ans = $val;
  2228. return $ans;
  2229. case 'count':
  2230. return count($data);
  2231. case 'any':
  2232. default:
  2233. return $data[0];
  2234. }
  2235. }
  2236. #
  2237. function docompare($row, $test)
  2238. {
  2239. // invalid $test data means true
  2240. if (count($test) < 2)
  2241. return true;
  2242. if (isset($row[$test[0]]))
  2243. $val = $row[$test[0]];
  2244. else
  2245. $val = null;
  2246. if ($test[1] == 'set')
  2247. return ($val !== null);
  2248. if ($val === null || count($test) < 3)
  2249. return true;
  2250. switch($test[1])
  2251. {
  2252. case '=':
  2253. return ($val == $test[2]);
  2254. case '<':
  2255. return ($val < $test[2]);
  2256. case '<=':
  2257. return ($val <= $test[2]);
  2258. case '>':
  2259. return ($val > $test[2]);
  2260. case '>=':
  2261. return ($val >= $test[2]);
  2262. case 'eq':
  2263. return (strcasecmp($val, $test[2]) == 0);
  2264. case 'lt':
  2265. return (strcasecmp($val, $test[2]) < 0);
  2266. case 'le':
  2267. return (strcasecmp($val, $test[2]) <= 0);
  2268. case 'gt':
  2269. return (strcasecmp($val, $test[2]) > 0);
  2270. case 'ge':
  2271. return (strcasecmp($val, $test[2]) >= 0);
  2272. default:
  2273. return true;
  2274. }
  2275. }
  2276. #
  2277. function processcompare($which, $ext, $section, $res)
  2278. {
  2279. if (isset($ext[$section][$which]))
  2280. {
  2281. $proc = $ext[$section][$which];
  2282. if ($proc !== null)
  2283. {
  2284. $res2 = array();
  2285. foreach ($res as $rig => $result)
  2286. foreach ($result as $sec => $row)
  2287. {
  2288. $secname = preg_replace('/\d/', '', $sec);
  2289. if (!secmatch($section, $secname))
  2290. $res2[$rig][$sec] = $row;
  2291. else
  2292. {
  2293. $keep = true;
  2294. foreach ($proc as $test)
  2295. if (!docompare($row, $test))
  2296. {
  2297. $keep = false;
  2298. break;
  2299. }
  2300. if ($keep)
  2301. $res2[$rig][$sec] = $row;
  2302. }
  2303. }
  2304. $res = $res2;
  2305. }
  2306. }
  2307. return $res;
  2308. }
  2309. #
  2310. function ss($a, $b)
  2311. {
  2312. $la = strlen($a);
  2313. $lb = strlen($b);
  2314. if ($la != $lb)
  2315. return $lb - $la;
  2316. return strcmp($a, $b);
  2317. }
  2318. #
  2319. # If you are developing a customsummarypage that uses BGEN or GEN,
  2320. # you may want to remove the '@' in front of '@eval()' to help with debugging
  2321. # The '@' removes php comments from the web log about missing fields
  2322. # Since there are many forks of cgminer that break the API or do not
  2323. # keep their fork up to date with current cgminer, the addition of
  2324. # '@' solves the problem of generating unnecessary and excessive web logs
  2325. # about the eval()
  2326. function genfld($row, $calc)
  2327. {
  2328. uksort($row, "ss");
  2329. foreach ($row as $name => $value)
  2330. if (strstr($calc, $name) !== FALSE)
  2331. $calc = str_replace($name, $value, $calc);
  2332. @eval("\$val = $calc;");
  2333. if (!isset($val))
  2334. return '';
  2335. else
  2336. return $val;
  2337. }
  2338. #
  2339. function dogen($ext, $wg, $gname, $section, &$res, &$fields)
  2340. {
  2341. $gen = $ext[$section][$wg];
  2342. foreach ($gen as $fld => $calc)
  2343. $fields[] = "$gname.$fld";
  2344. foreach ($res as $rig => $result)
  2345. foreach ($result as $sec => $row)
  2346. {
  2347. $secname = preg_replace('/\d/', '', $sec);
  2348. if (secmatch($section, $secname))
  2349. foreach ($gen as $fld => $calc)
  2350. {
  2351. $name = "$gname.$fld";
  2352. $val = genfld($row, $calc);
  2353. $res[$rig][$sec][$name] = $val;
  2354. }
  2355. }
  2356. }
  2357. #
  2358. function processext($ext, $section, $res, &$fields)
  2359. {
  2360. global $allowgen;
  2361. $res = processcompare('where', $ext, $section, $res);
  2362. // Generated fields (functions of other fields before grouping)
  2363. if ($allowgen === true && isset($ext[$section]['bgen']))
  2364. dogen($ext, 'bgen', 'BGEN', $section, $res, $fields);
  2365. if (isset($ext[$section]['group']))
  2366. {
  2367. $grp = $ext[$section]['group'];
  2368. $calc = $ext[$section]['calc'];
  2369. if ($grp !== null)
  2370. {
  2371. $interim = array();
  2372. $res2 = array();
  2373. $cou = 0;
  2374. foreach ($res as $rig => $result)
  2375. foreach ($result as $sec => $row)
  2376. {
  2377. $secname = preg_replace('/\d/', '', $sec);
  2378. if (!secmatch($section, $secname))
  2379. {
  2380. // STATUS may be problematic ...
  2381. if (!isset($res2[$sec]))
  2382. $res2[$sec] = $row;
  2383. }
  2384. else
  2385. {
  2386. $grpkey = '';
  2387. $newrow = array();
  2388. foreach ($grp as $field)
  2389. {
  2390. if (isset($row[$field]))
  2391. {
  2392. $grpkey .= $row[$field].'.';
  2393. $newrow[$field] = $row[$field];
  2394. }
  2395. else
  2396. $grpkey .= '.';
  2397. }
  2398. if (!isset($interim[$grpkey]))
  2399. {
  2400. $interim[$grpkey]['grp'] = $newrow;
  2401. $interim[$grpkey]['sec'] = $secname.$cou;
  2402. $cou++;
  2403. }
  2404. if ($calc !== null)
  2405. foreach ($calc as $field => $func)
  2406. {
  2407. if (isset($row[$field]))
  2408. {
  2409. if (!isset($interim[$grpkey]['cal'][$field]))
  2410. $interim[$grpkey]['cal'][$field] = array();
  2411. $interim[$grpkey]['cal'][$field][] = $row[$field];
  2412. }
  2413. }
  2414. }
  2415. }
  2416. // Build the rest of $res2 from $interim
  2417. foreach ($interim as $rowkey => $row)
  2418. {
  2419. $key = $row['sec'];
  2420. foreach ($row['grp'] as $field => $value)
  2421. $res2[$key][$field] = $value;
  2422. foreach ($row['cal'] as $field => $data)
  2423. $res2[$key][$field] = docalc($calc[$field], $data);
  2424. }
  2425. $res = array('' => $res2);
  2426. }
  2427. }
  2428. // Generated fields (functions of other fields after grouping)
  2429. if ($allowgen === true && isset($ext[$section]['gen']))
  2430. dogen($ext, 'gen', 'GEN', $section, $res, $fields);
  2431. return processcompare('having', $ext, $section, $res);
  2432. }
  2433. #
  2434. function processcustompage($pagename, $sections, $sum, $ext, $namemap)
  2435. {
  2436. global $sectionmap;
  2437. global $miner, $port;
  2438. global $rigs, $error;
  2439. global $warnfont, $warnoff;
  2440. global $dfmt;
  2441. global $readonly, $showndate;
  2442. $cmds = array();
  2443. $errors = array();
  2444. foreach ($sections as $section => $fields)
  2445. {
  2446. $all = explode('+', $section);
  2447. foreach ($all as $section)
  2448. {
  2449. if (isset($sectionmap[$section]))
  2450. {
  2451. $cmd = $sectionmap[$section];
  2452. if (!isset($cmds[$cmd]))
  2453. $cmds[$cmd] = 1;
  2454. }
  2455. else
  2456. if ($section != 'DATE')
  2457. $errors[] = "Error: unknown section '$section' in custom summary page '$pagename'";
  2458. }
  2459. }
  2460. $results = array();
  2461. foreach ($rigs as $num => $rig)
  2462. {
  2463. $parts = explode(':', $rig, 3);
  2464. if (count($parts) >= 1)
  2465. {
  2466. $miner = $parts[0];
  2467. if (count($parts) >= 2)
  2468. $port = $parts[1];
  2469. else
  2470. $port = '';
  2471. if (count($parts) > 2)
  2472. $name = $parts[2];
  2473. else
  2474. $name = $rig;
  2475. foreach ($cmds as $cmd => $one)
  2476. {
  2477. $process = api($name, $cmd);
  2478. if ($error != null)
  2479. {
  2480. $errors[] = "Error getting $cmd for $name $warnfont$error$warnoff";
  2481. break;
  2482. }
  2483. else
  2484. $results[$cmd][$num] = $process;
  2485. }
  2486. }
  2487. else
  2488. otherrow('<td class=bad>Bad "$rigs" array</td>');
  2489. }
  2490. // Show API errors at the top
  2491. if (count($errors) > 0)
  2492. {
  2493. foreach ($errors as $err)
  2494. otherrow("<td colspan=100>$err</td>");
  2495. $errors = array();
  2496. }
  2497. $shownsomething = false;
  2498. if (count($results) > 0)
  2499. {
  2500. list($results, $errors) = joinsections($sections, $results, $errors);
  2501. $first = true;
  2502. foreach ($sections as $section => $fields)
  2503. {
  2504. if ($section === 'DATE')
  2505. {
  2506. if ($shownsomething)
  2507. otherrow('<td>&nbsp;</td>');
  2508. newtable();
  2509. showdatetime();
  2510. endtable();
  2511. // On top of the next table
  2512. $shownsomething = false;
  2513. continue;
  2514. }
  2515. if ($section === 'RIGS')
  2516. {
  2517. if ($shownsomething)
  2518. otherrow('<td>&nbsp;</td>');
  2519. newtable();
  2520. showrigs($results['version'], 'Rig', '');
  2521. endtable();
  2522. $shownsomething = true;
  2523. continue;
  2524. }
  2525. if (isset($results[$sectionmap[$section]]))
  2526. {
  2527. if (isset($ext[$section]['fmt']))
  2528. $cf = $ext[$section]['fmt'];
  2529. else
  2530. $cf = NULL;
  2531. $rigresults = processext($ext, $section, $results[$sectionmap[$section]], $fields);
  2532. $showfields = array();
  2533. $showhead = array();
  2534. foreach ($fields as $field)
  2535. foreach ($rigresults as $result)
  2536. foreach ($result as $sec => $row)
  2537. {
  2538. $secname = preg_replace('/\d/', '', $sec);
  2539. if (secmatch($section, $secname))
  2540. {
  2541. if ($field === '*')
  2542. {
  2543. foreach ($row as $f => $v)
  2544. {
  2545. $showfields[$f] = 1;
  2546. $map = $section.'.'.$f;
  2547. if (isset($namemap[$map]))
  2548. $showhead[$namemap[$map]] = 1;
  2549. else
  2550. $showhead[$f] = 1;
  2551. }
  2552. }
  2553. elseif ($field === '#')
  2554. {
  2555. $showfields[$field] = 1;
  2556. $showhead[$field] = 1;
  2557. }
  2558. elseif (isset($row[$field]))
  2559. {
  2560. $showfields[$field] = 1;
  2561. $map = $section.'.'.$field;
  2562. if (isset($namemap[$map]))
  2563. $showhead[$namemap[$map]] = 1;
  2564. else
  2565. $showhead[$field] = 1;
  2566. }
  2567. }
  2568. }
  2569. if (count($showfields) > 0)
  2570. {
  2571. if ($shownsomething)
  2572. otherrow('<td>&nbsp;</td>');
  2573. newtable();
  2574. if (count($rigresults) == 1 && isset($rigresults['']))
  2575. $ri = array('' => 1) + $showhead;
  2576. else
  2577. $ri = array('Rig' => 1) + $showhead;
  2578. showhead('', $ri, true);
  2579. $total = array();
  2580. $add = array('total' => array());
  2581. foreach ($rigresults as $num => $result)
  2582. $total = customset($showfields, $sum, $section, $num, true, $result, $total, $cf);
  2583. if (count($total) > 0)
  2584. customset($showfields, $sum, $section, '&Sigma;', false, $add, $total, $cf);
  2585. $first = false;
  2586. endtable();
  2587. $shownsomething = true;
  2588. }
  2589. }
  2590. }
  2591. }
  2592. if (count($errors) > 0)
  2593. {
  2594. if (count($results) > 0)
  2595. otherrow('<td>&nbsp;</td>');
  2596. foreach ($errors as $err)
  2597. otherrow("<td colspan=100>$err</td>");
  2598. }
  2599. }
  2600. #
  2601. function showcustompage($pagename, $systempage = false)
  2602. {
  2603. global $customsummarypages;
  2604. global $placebuttons;
  2605. if ($placebuttons == 'top' || $placebuttons == 'both')
  2606. pagebuttons(null, $pagename);
  2607. if ($systempage === false && !isset($customsummarypages[$pagename]))
  2608. {
  2609. otherrow("<td colspan=100 class=bad>Unknown custom summary page '$pagename'</td>");
  2610. return;
  2611. }
  2612. $csp = getcsp($pagename, $systempage);
  2613. if ($csp === false)
  2614. {
  2615. otherrow("<td colspan=100 class=bad>Invalid custom summary page '$pagename'</td>");
  2616. return;
  2617. }
  2618. degen($csp);
  2619. $page = $csp[0];
  2620. $namemap = array();
  2621. foreach ($page as $name => $fields)
  2622. {
  2623. if ($fields === null)
  2624. $page[$name] = array();
  2625. else
  2626. foreach ($fields as $num => $field)
  2627. {
  2628. $pos = strpos($field, '=');
  2629. if ($pos !== false)
  2630. {
  2631. $names = explode('=', $field, 2);
  2632. if (strlen($names[1]) > 0)
  2633. $namemap[$name.'.'.$names[0]] = $names[1];
  2634. $page[$name][$num] = $names[0];
  2635. }
  2636. }
  2637. }
  2638. $ext = null;
  2639. if (isset($csp[2]))
  2640. $ext = $csp[2];
  2641. $sum = $csp[1];
  2642. if ($sum === null)
  2643. $sum = array();
  2644. // convert them to searchable via isset()
  2645. foreach ($sum as $section => $fields)
  2646. {
  2647. $newfields = array();
  2648. foreach ($fields as $field)
  2649. $newfields[$field] = 1;
  2650. $sum[$section] = $newfields;
  2651. }
  2652. if (count($page) <= 1)
  2653. {
  2654. otherrow("<td colspan=100 class=bad>Invalid custom summary page '$pagename' no content </td>");
  2655. return;
  2656. }
  2657. processcustompage($pagename, $page, $sum, $ext, $namemap);
  2658. if ($placebuttons == 'bot' || $placebuttons == 'both')
  2659. pagebuttons(null, $pagename);
  2660. }
  2661. #
  2662. function onlylogin()
  2663. {
  2664. global $here;
  2665. htmlhead('', false, null, null, true);
  2666. ?>
  2667. <tr height=15%><td>&nbsp;</td></tr>
  2668. <tr><td>
  2669. <center>
  2670. <table width=384 height=368 cellpadding=0 cellspacing=0 border=0>
  2671. <tr><td>
  2672. <table width=100% height=100% border=0 align=center cellpadding=5 cellspacing=0>
  2673. <tr><td><form action='<?php echo $here; ?>' method=post>
  2674. <table width=200 border=0 align=center cellpadding=5 cellspacing=0>
  2675. <tr><td height=120 colspan=2>&nbsp;</td></tr>
  2676. <tr><td colspan=2 align=center valign=middle>
  2677. <h2>LOGIN</h2></td></tr>
  2678. <tr><td align=center valign=middle><div align=right>Username:</div></td>
  2679. <td height=33 align=center valign=middle>
  2680. <input type=text name=rut size=18></td></tr>
  2681. <tr><td align=center valign=middle><div align=right>Password:</div></td>
  2682. <td height=33 align=center valign=middle>
  2683. <input type=password name=roh size=18></td></tr>
  2684. <tr valign=top><td></td><td><input type=submit value=Login>
  2685. </td></tr>
  2686. </table></form></td></tr>
  2687. </table></td></tr>
  2688. </table></center>
  2689. </td></tr>
  2690. <?php
  2691. }
  2692. #
  2693. function checklogin()
  2694. {
  2695. global $allowcustompages;
  2696. global $readonly, $userlist, $ses;
  2697. $out = trim(getparam('logout', true));
  2698. if ($out !== null && $out !== '' && isset($_SESSION[$ses]))
  2699. unset($_SESSION[$ses]);
  2700. $login = trim(getparam('login', true));
  2701. if ($login !== null && $login !== '')
  2702. {
  2703. if (isset($_SESSION[$ses]))
  2704. unset($_SESSION[$ses]);
  2705. onlylogin();
  2706. return 'login';
  2707. }
  2708. if ($userlist === null)
  2709. return false;
  2710. $rut = trim(getparam('rut', true));
  2711. $roh = trim(getparam('roh', true));
  2712. if (($rut !== null && $rut !== '') || ($roh !== null && $roh !== ''))
  2713. {
  2714. if (isset($_SESSION[$ses]))
  2715. unset($_SESSION[$ses]);
  2716. if ($rut !== null && $rut !== '' && $roh !== null && $roh !== '')
  2717. {
  2718. if (isset($userlist['sys']) && isset($userlist['sys'][$rut])
  2719. && ($userlist['sys'][$rut] === $roh))
  2720. {
  2721. $_SESSION[$ses] = true;
  2722. return false;
  2723. }
  2724. if (isset($userlist['usr']) && isset($userlist['usr'][$rut])
  2725. && ($userlist['usr'][$rut] === $roh))
  2726. {
  2727. $_SESSION[$ses] = false;
  2728. $readonly = true;
  2729. return false;
  2730. }
  2731. }
  2732. }
  2733. if (isset($_SESSION[$ses]))
  2734. {
  2735. if ($_SESSION[$ses] == false)
  2736. $readonly = true;
  2737. return false;
  2738. }
  2739. if (isset($userlist['def']) && $allowcustompages === true)
  2740. {
  2741. // Ensure at least one exists
  2742. foreach ($userlist['def'] as $pg)
  2743. if (getcsp($pg) !== false)
  2744. return true;
  2745. }
  2746. onlylogin();
  2747. return 'login';
  2748. }
  2749. #
  2750. function display()
  2751. {
  2752. global $miner, $port;
  2753. global $mcast, $mcastexpect;
  2754. global $readonly, $notify, $rigs;
  2755. global $ignorerefresh, $autorefresh;
  2756. global $allowcustompages;
  2757. global $placebuttons;
  2758. global $userlist, $ses;
  2759. $pagesonly = checklogin();
  2760. if ($pagesonly === 'login')
  2761. return;
  2762. $mcerr = '';
  2763. if ($rigs == null or count($rigs) == 0)
  2764. {
  2765. if ($mcast === true)
  2766. $action = 'found';
  2767. else
  2768. $action = 'defined';
  2769. minhead();
  2770. otherrow("<td class=bad>No rigs $action</td>");
  2771. return;
  2772. }
  2773. else
  2774. {
  2775. if ($mcast === true && count($rigs) < $mcastexpect)
  2776. $mcerr = othrow('<td class=bad>Found '.count($rigs)." rigs but expected at least $mcastexpect</td>");
  2777. }
  2778. if ($ignorerefresh == false)
  2779. {
  2780. $ref = trim(getparam('ref', true));
  2781. if ($ref != null && $ref != '')
  2782. $autorefresh = intval($ref);
  2783. }
  2784. if ($pagesonly !== true)
  2785. {
  2786. $rig = trim(getparam('rig', true));
  2787. $arg = trim(getparam('arg', true));
  2788. $preprocess = null;
  2789. if ($arg != null and $arg != '')
  2790. {
  2791. if ($rig != null and $rig != '' and $rig >= 0 and $rig < count($rigs))
  2792. {
  2793. $parts = explode(':', $rigs[$rig], 3);
  2794. if (count($parts) >= 1)
  2795. {
  2796. $miner = $parts[0];
  2797. if (count($parts) >= 2)
  2798. $port = $parts[1];
  2799. else
  2800. $port = '';
  2801. if ($readonly !== true)
  2802. $preprocess = $arg;
  2803. }
  2804. }
  2805. }
  2806. }
  2807. if ($allowcustompages === true)
  2808. {
  2809. $pg = urlencode(trim(getparam('pg', true)));
  2810. if ($pagesonly === true)
  2811. {
  2812. if ($pg !== null && $pg !== '')
  2813. {
  2814. if ($userlist !== null && isset($userlist['def'])
  2815. && !in_array($pg, $userlist['def']))
  2816. $pg = null;
  2817. }
  2818. else
  2819. {
  2820. if ($userlist !== null && isset($userlist['def']))
  2821. foreach ($userlist['def'] as $pglook)
  2822. if (getcsp($pglook) !== false)
  2823. {
  2824. $pg = $pglook;
  2825. break;
  2826. }
  2827. }
  2828. }
  2829. if ($pg !== null && $pg !== '')
  2830. {
  2831. htmlhead($mcerr, false, null, $pg);
  2832. showcustompage($pg);
  2833. return;
  2834. }
  2835. }
  2836. if ($pagesonly === true)
  2837. {
  2838. onlylogin();
  2839. return;
  2840. }
  2841. if (count($rigs) == 1)
  2842. {
  2843. $parts = explode(':', $rigs[0], 3);
  2844. if (count($parts) >= 1)
  2845. {
  2846. $miner = $parts[0];
  2847. if (count($parts) >= 2)
  2848. $port = $parts[1];
  2849. else
  2850. $port = '';
  2851. htmlhead($mcerr, true, 0);
  2852. doOne(0, $preprocess);
  2853. }
  2854. else
  2855. {
  2856. minhead($mcerr);
  2857. otherrow('<td class=bad>Invalid "$rigs" array</td>');
  2858. }
  2859. return;
  2860. }
  2861. if ($rig != null and $rig != '' and $rig >= 0 and $rig < count($rigs))
  2862. {
  2863. $parts = explode(':', $rigs[$rig], 3);
  2864. if (count($parts) >= 1)
  2865. {
  2866. $miner = $parts[0];
  2867. if (count($parts) >= 2)
  2868. $port = $parts[1];
  2869. else
  2870. $port = '';
  2871. htmlhead($mcerr, true, 0);
  2872. doOne($rig, $preprocess);
  2873. }
  2874. else
  2875. {
  2876. minhead($mcerr);
  2877. otherrow('<td class=bad>Invalid "$rigs" array</td>');
  2878. }
  2879. return;
  2880. }
  2881. htmlhead($mcerr, false, null);
  2882. if ($preprocess != null)
  2883. process(array($preprocess => $preprocess), $rig);
  2884. if (getcsp('Summary', true) !== false)
  2885. showcustompage('Summary', true);
  2886. }
  2887. #
  2888. if ($mcast === true)
  2889. getrigs();
  2890. display();
  2891. #
  2892. ?>
  2893. </table></td></tr></table>
  2894. </body></html>