diff --git a/cronjobs/payouts.php b/cronjobs/payouts.php index b390fb38..87b5e119 100755 --- a/cronjobs/payouts.php +++ b/cronjobs/payouts.php @@ -68,7 +68,7 @@ if ($setting->getValue('disable_manual_payouts') != 1) { try { $txid = $bitcoin->sendtoaddress($aData['coin_address'], $dBalance - $config['txfee_manual']); } catch (Exception $e) { - $log->logError('Failed to send requested balance to coin address, please check payout process. Does the wallet cover the amount?'); + $log->logError('Failed to send requested balance to coin address, please check payout process. Does the wallet cover the amount? Error:' . $e->getMessage()); continue; } diff --git a/public/include/classes/bitcoin.class.php b/public/include/classes/bitcoin.class.php index d91d5fc2..f1512c70 100644 --- a/public/include/classes/bitcoin.class.php +++ b/public/include/classes/bitcoin.class.php @@ -229,24 +229,7 @@ class Bitcoin { } } -/** - * Exception class for BitcoinClient - * - * @author Mike Gogulski - * http://www.gogulski.com/ http://www.nostate.com/ - */ -class BitcoinClientException extends ErrorException { - // Redefine the exception so message isn't optional - public function __construct($message, $code = 0, $severity = E_USER_NOTICE, Exception $previous = null) { - parent::__construct($message, $code, $severity, $previous); - } - - public function __toString() { - return __CLASS__ . ": [{$this->code}]: {$this->message}\n"; - } -} - -require_once(INCLUDE_DIR . "/jsonRPCClient.php"); +require_once(INCLUDE_DIR . "/lib/jsonRPCClient.php"); /** * Bitcoin client class for access to a Bitcoin server via JSON-RPC-HTTP[S] @@ -283,21 +266,18 @@ class BitcoinClient extends jsonRPCClient { * @access public * @throws BitcoinClientException */ - public function __construct($scheme, $username, $password, $address = "localhost", $port = 8332, $certificate_path = '', $debug_level = 0) { + public function __construct($scheme, $username, $password, $address = "localhost", $certificate_path = '', $debug = false) { $scheme = strtolower($scheme); if ($scheme != "http" && $scheme != "https") - throw new BitcoinClientException("Scheme must be http or https"); + throw new Exception("Scheme must be http or https"); if (empty($username)) - throw new BitcoinClientException("Username must be non-blank"); + throw new Exception("Username must be non-blank"); if (empty($password)) - throw new BitcoinClientException("Password must be non-blank"); - $port = (string) $port; - if (!$port || empty($port) || !is_numeric($port) || $port < 1 || $port > 65535 || floatval($port) != intval($port)) - throw new BitcoinClientException("Port must be an integer and between 1 and 65535"); + throw new Exception("Password must be non-blank"); if (!empty($certificate_path) && !is_readable($certificate_path)) - throw new BitcoinClientException("Certificate file " . $certificate_path . " is not readable"); + throw new Exception("Certificate file " . $certificate_path . " is not readable"); $uri = $scheme . "://" . $username . ":" . $password . "@" . $address . "/"; - parent::__construct($uri); + parent::__construct($uri, $debug); } /** diff --git a/public/include/classes/bitcoinwrapper.class.php b/public/include/classes/bitcoinwrapper.class.php index ed4c09a8..b2167611 100644 --- a/public/include/classes/bitcoinwrapper.class.php +++ b/public/include/classes/bitcoinwrapper.class.php @@ -9,15 +9,16 @@ if (!defined('SECURITY')) * some basic caching functionality and some debugging **/ class BitcoinWrapper extends BitcoinClient { - public function __construct($type, $username, $password, $host, $debug, $memcache) { + public function __construct($type, $username, $password, $host, $debug_level, $debug_object, $memcache) { $this->type = $type; $this->username = $username; $this->password = $password; $this->host = $host; // $this->debug is already used - $this->oDebug = $debug; + $this->oDebug = $debug_object; $this->memcache = $memcache; - return parent::__construct($this->type, $this->username, $this->password, $this->host); + $debug_level > 0 ? $debug_level = true : $debug_level = false; + return parent::__construct($this->type, $this->username, $this->password, $this->host, '', $debug_level); } /** * Wrap variouns methods to add caching @@ -75,4 +76,4 @@ class BitcoinWrapper extends BitcoinClient { } // Load this wrapper -$bitcoin = new BitcoinWrapper($config['wallet']['type'], $config['wallet']['username'], $config['wallet']['password'], $config['wallet']['host'], $debug, $memcache); +$bitcoin = new BitcoinWrapper($config['wallet']['type'], $config['wallet']['username'], $config['wallet']['password'], $config['wallet']['host'], DEBUG, $debug, $memcache); diff --git a/public/include/jsonRPCClient.php b/public/include/jsonRPCClient.php deleted file mode 100644 index 2100578f..00000000 --- a/public/include/jsonRPCClient.php +++ /dev/null @@ -1,167 +0,0 @@ - - -This file is part of JSON-RPC PHP. - -JSON-RPC PHP is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -JSON-RPC PHP is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with JSON-RPC PHP; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -/** - * The object of this class are generic jsonRPC 1.0 clients - * http://json-rpc.org/wiki/specification - * - * @author sergio - */ -class jsonRPCClient { - - /** - * Debug state - * - * @var boolean - */ - private $debug; - - /** - * The server URL - * - * @var string - */ - private $url; - /** - * The request id - * - * @var integer - */ - private $id; - /** - * If true, notifications are performed instead of requests - * - * @var boolean - */ - private $notification = false; - - /** - * Takes the connection parameters - * - * @param string $url - * @param boolean $debug - */ - public function __construct($url,$debug = false) { - // server URL - $this->url = $url; - // proxy - empty($proxy) ? $this->proxy = '' : $this->proxy = $proxy; - // debug state - empty($debug) ? $this->debug = false : $this->debug = true; - // message id - $this->id = 1; - } - - /** - * Sets the notification state of the object. In this state, notifications are performed, instead of requests. - * - * @param boolean $notification - */ - public function setRPCNotification($notification) { - empty($notification) ? - $this->notification = false - : - $this->notification = true; - } - - /** - * Performs a jsonRCP request and gets the results as an array - * - * @param string $method - * @param array $params - * @return array - */ - public function __call($method,$params) { - - // check - if (!is_scalar($method)) { - throw new Exception('Method name has no scalar value'); - } - - // check - if (is_array($params)) { - // no keys - $params = array_values($params); - } else { - throw new Exception('Params must be given as array'); - } - - // sets notification or request task - if ($this->notification) { - $currentId = NULL; - } else { - $currentId = $this->id; - } - - // prepares the request - $request = array( - 'method' => $method, - 'params' => $params, - 'id' => $currentId - ); - $request = json_encode($request); - $this->debug && $this->debug.='***** Request *****'."\n".$request."\n".'***** End Of request *****'."\n\n"; - - // performs the HTTP POST - $opts = array ('http' => array ( - 'method' => 'POST', - 'header' => 'Content-type: application/json', - 'content' => $request - )); - $context = stream_context_create($opts); - if ($fp = @fopen($this->url, 'r', false, $context)) { - $response = ''; - while($row = fgets($fp)) { - $response.= trim($row)."\n"; - } - $this->debug && $this->debug.='***** Server response *****'."\n".$response.'***** End of server response *****'."\n"; - $response = json_decode($response,true); - } else { - $error = error_get_last(); - $error = explode(']: ', $error['message']); - throw new Exception('Unable to connect: ' . $error[1]); - } - - // debug output - if ($this->debug) { - echo nl2br($debug); - } - - // final checks and return - if (!$this->notification) { - // check - if ($response['id'] != $currentId) { - throw new Exception('Incorrect response id (request id: '.$currentId.', response id: '.$response['id'].')'); - } - if (!is_null($response['error'])) { - throw new Exception('Request error: '.$response['error']); - } - - return $response['result']; - - } else { - return true; - } - } -} -?> diff --git a/public/include/lib/jsonRPCClient.php b/public/include/lib/jsonRPCClient.php new file mode 100644 index 00000000..f25fb0b9 --- /dev/null +++ b/public/include/lib/jsonRPCClient.php @@ -0,0 +1,127 @@ + + +This file is part of JSON-RPC PHP. + +JSON-RPC PHP is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +JSON-RPC PHP is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with JSON-RPC PHP; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * The object of this class are generic jsonRPC 1.0 clients + * http://json-rpc.org/wiki/specification + * + * @author sergio + */ +class jsonRPCClient { + + /** + * Debug state + * + * @var boolean + */ + private $debug; + private $debug_output = NULL; + + /** + * The server URL + * + * @var string + */ + private $url; + /** + * The request id + * + * @var integer + */ + private $id; + + /** + * Takes the connection parameters + * + * @param string $url + * @param boolean $debug + */ + public function __construct($url, $debug = false) { + $this->url = $url; + $this->debug = $debug; + $this->debug_output = ''; + $this->id = rand(1, 100); + } + + /** + * Fetch debug information + * @param none + * @return array Debug data + **/ + public function getDebugData() { + if ($this->debug) return $this->debug_output; + return false; + } + + /** + * Performs a jsonRCP request and gets the results as an array + * + * @param string $method + * @param array $params + * @return array + */ + public function __call($method, $params) { + if (!is_scalar($method)) throw new Exception('Method name has no scalar value'); + + if (is_array($params)) { + // no keys + $params = array_values($params); + } else { + throw new Exception('Params must be given as array'); + } + + // prepares the request + $request = array( + 'method' => $method, + 'params' => $params, + 'id' => $this->id + ); + $request = json_encode($request); + if ($this->debug) $this->debug_output[] = 'Request: '.$request; + + // performs the HTTP POST + // extract information from URL for proper authentication + $url = parse_url($this->url); + $ch = curl_init($url['scheme'].'://'.$url['host'].':'.$url['port'].$url['path']); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/json')); + curl_setopt($ch, CURLOPT_USERPWD, $url['user'] . ":" . $url['pass']); + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $request); + $response = curl_exec($ch); + if ($this->debug) $this->debug_output[] = 'Response: ' . $response; + $response = json_decode($response, true); + $resultStatus = curl_getinfo($ch); + if ($resultStatus['http_code'] != '200') { + if ($resultStatus['http_code'] == '401') throw new Exception('RPC call did not return 200: Authentication failed'); + throw new Exception('RPC call did not return 200: HTTP error: ' . $resultStatus['http_code']); + } + if (curl_errno($ch)) throw new Exception('RPC call failed: ' . curl_error($ch)); + curl_close($ch); + + // final checks and return + if (!is_null($response['error']) || is_null($response)) throw new Exception('Response error or empty: ' . @$response['error']); + if ($response['id'] != $this->id) throw new Exception('Incorrect response id (request id: ' . $this->id . ', response id: ' . $response['id'] . ')'); + return $response['result']; + } +} diff --git a/public/include/pages/statistics/pool.inc.php b/public/include/pages/statistics/pool.inc.php index 84fb3d54..ae42aebc 100644 --- a/public/include/pages/statistics/pool.inc.php +++ b/public/include/pages/statistics/pool.inc.php @@ -3,20 +3,21 @@ // Make sure we are called from index.php if (!defined('SECURITY')) die('Hacking attempt'); +// Fetch data from wallet, always run this check +if ($bitcoin->can_connect() === true){ + $dDifficulty = $bitcoin->getdifficulty(); + $dNetworkHashrate = $bitcoin->getnetworkhashps(); + $iBlock = $bitcoin->getblockcount(); + is_int($iBlock) && $iBlock > 0 ? $sBlockHash = $bitcoin->getblockhash($iBlock) : $sBlockHash = ''; +} else { + $dDifficulty = 1; + $dNetworkHashrate = 1; + $iBlock = 0; + $_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to wallet RPC service: ' . $bitcoin->can_connect(), 'TYPE' => 'errormsg'); +} + if (!$smarty->isCached('master.tpl', $smarty_cache_key)) { $debug->append('No cached version available, fetching from backend', 3); - // Fetch data from wallet - if ($bitcoin->can_connect() === true){ - $dDifficulty = $bitcoin->getdifficulty(); - $dNetworkHashrate = $bitcoin->getnetworkhashps(); - $iBlock = $bitcoin->getblockcount(); - is_int($iBlock) && $iBlock > 0 ? $sBlockHash = $bitcoin->getblockhash($iBlock) : $sBlockHash = ''; - } else { - $dDifficulty = 1; - $dNetworkHashrate = 1; - $iBlock = 0; - $_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to wallet RPC service: ' . $bitcoin->can_connect(), 'TYPE' => 'errormsg'); - } // Top share contributors $aContributorsShares = $statistics->getTopContributors('shares', 15);