miner.php 89 KB

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