From 1bdf5e3156bfbc26837b9f416955dbe8d7ffac19 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Thu, 23 May 2013 10:02:11 +0200 Subject: [PATCH 01/59] added some more debug output for profiling --- public/include/classes/statistics.class.php | 9 +++++++++ public/include/classes/transaction.class.php | 5 ++--- public/include/classes/user.class.php | 17 ++++++++++++++++- public/include/classes/worker.class.php | 5 +++++ 4 files changed, 32 insertions(+), 4 deletions(-) diff --git a/public/include/classes/statistics.class.php b/public/include/classes/statistics.class.php index 853e854a..a38fb14e 100644 --- a/public/include/classes/statistics.class.php +++ b/public/include/classes/statistics.class.php @@ -62,6 +62,7 @@ class Statistics { * @return array **/ public function getBlocksFound($limit=10) { + $this->debug->append("STA " . __METHOD__, 4); if ($data = $this->memcache->get(__FUNCTION__ . $limit)) return $data; $stmt = $this->mysqli->prepare(" SELECT b.*, a.username as finder @@ -84,6 +85,7 @@ class Statistics { * @return bool **/ public function updateShareStatistics($aStats, $iBlockId) { + $this->debug->append("STA " . __METHOD__, 4); $stmt = $this->mysqli->prepare("INSERT INTO $this->table (account_id, valid, invalid, block_id) VALUES (?, ?, ?, ?)"); if ($this->checkStmt($stmt) && $stmt->bind_param('iiii', $aStats['id'], $aStats['valid'], $aStats['invalid'], $iBlockId) && $stmt->execute()) return true; // Catchall @@ -98,6 +100,7 @@ class Statistics { * @return data object Return our hashrateas an object **/ public function getCurrentHashrate() { + $this->debug->append("STA " . __METHOD__, 4); if ($data = $this->memcache->get(__FUNCTION__)) return $data; $stmt = $this->mysqli->prepare(" SELECT SUM(hashrate) AS hashrate FROM @@ -118,6 +121,7 @@ class Statistics { * @return data object Our share rate in shares per second **/ public function getCurrentShareRate() { + $this->debug->append("STA " . __METHOD__, 4); if ($data = $this->memcache->get(__FUNCTION__)) return $data; $stmt = $this->mysqli->prepare(" SELECT ROUND(SUM(sharerate) / 600, 2) AS sharerate FROM @@ -138,6 +142,7 @@ class Statistics { * @return data array invalid and valid shares **/ public function getRoundShares() { + $this->debug->append("STA " . __METHOD__, 4); if ($data = $this->memcache->get(__FUNCTION__)) return $data; $stmt = $this->mysqli->prepare(" SELECT @@ -162,6 +167,7 @@ class Statistics { * @return data array invalid and valid share counts **/ public function getUserShares($account_id) { + $this->debug->append("STA " . __METHOD__, 4); if ($data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data; $stmt = $this->mysqli->prepare(" SELECT @@ -217,6 +223,7 @@ class Statistics { * @return data int Current hashrate in khash/s **/ public function getWorkerHashrate($worker_id) { + $this->debug->append("STA " . __METHOD__, 4); if ($data = $this->memcache->get(__FUNCTION__ . $worker_id)) return $data; $stmt = $this->mysqli->prepare(" SELECT ROUND(COUNT(s.id) * POW(2,21)/600/1000) AS hashrate @@ -239,6 +246,7 @@ class Statistics { * @return data array Users with shares, account or hashrate, account **/ public function getTopContributors($type='shares', $limit=15) { + $this->debug->append("STA " . __METHOD__, 4); if ($data = $this->memcache->get(__FUNCTION__ . $type . $limit)) return $data; switch ($type) { case 'shares': @@ -280,6 +288,7 @@ class Statistics { * @return data array NOT FINISHED YET **/ public function getHourlyHashrateByAccount($account_id) { + $this->debug->append("STA " . __METHOD__, 4); if ($data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data; $stmt = $this->mysqli->prepare(" SELECT diff --git a/public/include/classes/transaction.class.php b/public/include/classes/transaction.class.php index 7f8cd76d..ee4bbc21 100644 --- a/public/include/classes/transaction.class.php +++ b/public/include/classes/transaction.class.php @@ -38,10 +38,8 @@ class Transaction { return false; } - public function addDebit($account_id, $amount, $type='AP') { - } - public function getTransactions($account_id, $start=0) { + $this->debug->append("STA " . __METHOD__, 4); $stmt = $this->mysqli->prepare(" SELECT t.id AS id, @@ -75,6 +73,7 @@ class Transaction { } public function getBalance($account_id) { + $this->debug->append("STA " . __METHOD__, 4); $stmt = $this->mysqli->prepare(" SELECT ROUND(IFNULL(t1.credit, 0) - IFNULL(t2.debit, 0) - IFNULL(t3.other, 0), 8) AS balance FROM diff --git a/public/include/classes/user.class.php b/public/include/classes/user.class.php index a2b7c07e..e33b8c7c 100644 --- a/public/include/classes/user.class.php +++ b/public/include/classes/user.class.php @@ -41,6 +41,7 @@ class User { * @return bool **/ public function checkLogin($username, $password) { + $this->debug->append("STA " . __METHOD__, 4); $this->debug->append("Checking login for $username with password $password", 2); if ( $this->checkUserPassword($username, $password) ) { $this->createSession($username); @@ -56,6 +57,7 @@ class User { * @return bool **/ public function checkPin($userId, $pin=false) { + $this->debug->append("STA " . __METHOD__, 4); $this->debug->append("Confirming PIN for $userId and pin $pin", 2); $stmt = $this->mysqli->prepare("SELECT pin FROM $this->table WHERE id=? AND pin=? LIMIT 1"); $pin_hash = hash('sha256', $pin.$this->salt); @@ -76,6 +78,7 @@ class User { * @return array Return result **/ private function getSingle($value, $search='id', $field='id', $type="i") { + $this->debug->append("STA " . __METHOD__, 4); $stmt = $this->mysqli->prepare("SELECT $search FROM $this->table WHERE $field = ? LIMIT 1"); if ($this->checkStmt($stmt)) { $stmt->bind_param($type, $value); @@ -94,6 +97,7 @@ class User { * @return data array All users with payout setup **/ public function getAllAutoPayout() { + $this->debug->append("STA " . __METHOD__, 4); $stmt = $this->mysqli->prepare(" SELECT id, username, coin_address, ap_threshold @@ -115,6 +119,7 @@ class User { * @return data string Coin Address **/ public function getCoinAddress($userID) { + $this->debug->append("STA " . __METHOD__, 4); return $this->getSingle($userID, 'coin_address', 'id'); } @@ -124,6 +129,7 @@ class User { * @return data string Coin Address **/ public function getDonatePercent($userID) { + $this->debug->append("STA " . __METHOD__, 4); $dPercent = $this->getSingle($userID, 'donate_percent', 'id'); if ($dPercent > 100) $dPercent = 100; if ($dPercent < 0) $dPercent = 0; @@ -137,6 +143,7 @@ class User { * @return bool **/ private function updateSingle($userID, $field) { + $this->debug->append("STA " . __METHOD__, 4); $stmt = $this->mysqli->prepare("UPDATE $this->table SET " . $field['name'] . " = ? WHERE userId = ? LIMIT 1"); if ($this->checkStmt($stmt)) { $stmt->bind_param($field['type'].'i', $field['value'], $userID); @@ -148,6 +155,7 @@ class User { } private function checkStmt($bState) { + $this->debug->append("STA " . __METHOD__, 4); if ($bState ===! true) { $this->debug->append("Failed to prepare statement: " . $this->mysqli->error); $this->setErrorMessage('Internal application Error'); @@ -157,6 +165,7 @@ class User { } public function updatePassword($userID, $current, $new1, $new2) { + $this->debug->append("STA " . __METHOD__, 4); if ($new1 !== $new2) { $this->setErrorMessage( 'New passwords do not match' ); return false; @@ -181,6 +190,7 @@ class User { } public function updateAccount($userID, $address, $threshold, $donate) { + $this->debug->append("STA " . __METHOD__, 4); $bUser = false; $threshold = min(250, max(0, floatval($threshold))); if ($threshold < 1) $threshold = 0.0; @@ -197,6 +207,7 @@ class User { } private function checkUserPassword($username, $password) { + $this->debug->append("STA " . __METHOD__, 4); $user = array(); $stmt = $this->mysqli->prepare("SELECT username, id FROM $this->table WHERE username=? AND pass=? LIMIT 1"); if ($this->checkStmt($stmt)) { @@ -213,6 +224,7 @@ class User { } private function createSession($username) { + $this->debug->append("STA " . __METHOD__, 4); $this->debug->append("Log in user to _SESSION", 2); session_regenerate_id(true); $_SESSION['AUTHENTICATED'] = '1'; @@ -221,16 +233,19 @@ class User { } public function logoutUser() { + $this->debug->append("STA " . __METHOD__, 4); session_destroy(); session_regenerate_id(true); return true; } public function getTableName() { + $this->debug->append("STA " . __METHOD__, 4); return $this->table; } public function getUserData($userID) { + $this->debug->append("STA " . __METHOD__, 4); $this->debug->append("Fetching user information for user id: $userID"); $stmt = $this->mysqli->prepare(" SELECT @@ -238,7 +253,6 @@ class User { IFNULL(donate_percent, '0') as donate_percent, coin_address, ap_threshold FROM $this->table WHERE id = ? LIMIT 0,1"); - echo $this->mysqli->error; if ($this->checkStmt($stmt)) { $stmt->bind_param('i', $userID); if (!$stmt->execute()) { @@ -254,6 +268,7 @@ class User { } public function register($username, $password1, $password2, $pin, $email1='', $email2='') { + $this->debug->append("STA " . __METHOD__, 4); if (strlen($password1) < 8) { $this->setErrorMessage( 'Password is too short, minimum of 8 characters required' ); return false; diff --git a/public/include/classes/worker.class.php b/public/include/classes/worker.class.php index 85254900..0637609a 100644 --- a/public/include/classes/worker.class.php +++ b/public/include/classes/worker.class.php @@ -41,6 +41,7 @@ class Worker { * @return bool **/ public function updateWorkers($account_id, $data) { + $this->debug->append("STA " . __METHOD__, 4); $username = $this->user->getUserName($account_id); foreach ($data as $key => $value) { // Prefix the WebUser to Worker name @@ -61,6 +62,7 @@ class Worker { * @return mixed array Workers and their settings or false **/ public function getWorkers($account_id) { + $this->debug->append("STA " . __METHOD__, 4); $stmt = $this->mysqli->prepare(" SELECT id, username, password, ( SELECT SIGN(COUNT(id)) FROM " . $this->share->getTableName() . " WHERE username = $this->table.username AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)) AS active, @@ -81,6 +83,7 @@ class Worker { * @return data mixed int count if any workers are active, false otherwise **/ public function getCountAllActiveWorkers() { + $this->debug->append("STA " . __METHOD__, 4); $stmt = $this->mysqli->prepare("SELECT COUNT(DISTINCT username) AS total FROM " . $this->share->getTableName() . " WHERE time > DATE_SUB(now(), INTERVAL 10 MINUTE)"); if ($this->checkStmt($stmt)) { if (!$stmt->execute()) { @@ -103,6 +106,7 @@ class Worker { * @return bool **/ public function addWorker($account_id, $workerName, $workerPassword) { + $this->debug->append("STA " . __METHOD__, 4); $username = $this->user->getUserName($account_id); $workerName = "$username.$workerName"; $stmt = $this->mysqli->prepare("INSERT INTO $this->table (account_id, username, password) VALUES(?, ?, ?)"); @@ -125,6 +129,7 @@ class Worker { * @return bool **/ public function deleteWorker($account_id, $id) { + $this->debug->append("STA " . __METHOD__, 4); $stmt = $this->mysqli->prepare("DELETE FROM $this->table WHERE account_id = ? AND id = ?"); if ($this->checkStmt($stmt)) { $stmt->bind_param('ii', $account_id, $id); From 128e09cd5db316c5e97e4c137f6d85fa51fb1f0d Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Thu, 23 May 2013 11:10:17 +0200 Subject: [PATCH 02/59] initial work on password reset, not working fully yet --- public/include/classes/user.class.php | 61 ++++++++++++++++++--- public/include/pages/password.inc.php | 9 +++ public/include/pages/password/reset.inc.php | 15 +++++ public/templates/mmcFE/global/login.tpl | 2 +- public/templates/mmcFE/password/default.tpl | 8 +++ 5 files changed, 85 insertions(+), 10 deletions(-) create mode 100644 public/include/pages/password.inc.php create mode 100644 public/include/pages/password/reset.inc.php create mode 100644 public/templates/mmcFE/password/default.tpl diff --git a/public/include/classes/user.class.php b/public/include/classes/user.class.php index e33b8c7c..3ec72546 100644 --- a/public/include/classes/user.class.php +++ b/public/include/classes/user.class.php @@ -11,10 +11,11 @@ class User { private $user = array(); private $tableAccountBalance = 'accountBalance'; - public function __construct($debug, $mysqli, $salt) { + public function __construct($debug, $mysqli, $salt, $config) { $this->debug = $debug; $this->mysqli = $mysqli; $this->salt = $salt; + $this->config = $config; $this->debug->append("Instantiated User class", 2); } @@ -34,6 +35,23 @@ class User { return $this->getSingle($username, 'id', 'username', 's'); } + public function getUserEmail($username) { + return $this->getSingle($username, 'email', 'username', 's'); + } + + public function getUserToken($id) { + return $this->getSingle($id, 'token', 'id'); + } + + public function setUserToken($id) { + $field = array( + 'name' => 'token', + 'type' => 's', + 'value' => hash('sha256', $id.time().$this->salt) + ); + return $this->updateSingle($id, $field); + } + /** * Check user login * @param username string Username @@ -142,15 +160,12 @@ class User { * @param field string Field to update * @return bool **/ - private function updateSingle($userID, $field) { + private function updateSingle($id, $field) { $this->debug->append("STA " . __METHOD__, 4); - $stmt = $this->mysqli->prepare("UPDATE $this->table SET " . $field['name'] . " = ? WHERE userId = ? LIMIT 1"); - if ($this->checkStmt($stmt)) { - $stmt->bind_param($field['type'].'i', $field['value'], $userID); - $stmt->execute(); - $stmt->close(); + $stmt = $this->mysqli->prepare("UPDATE $this->table SET " . $field['name'] . " = ? WHERE id = ? LIMIT 1"); + if ($this->checkStmt($stmt) && $stmt->bind_param($field['type'].'i', $field['value'], $id) && $stmt->execute()) return true; - } + $this->debug->append("Unable to update " . $field['name'] . " with " . $field['value'] . " for ID $id"); return false; } @@ -306,6 +321,34 @@ class User { } return false; } + + public function resetPassword($username) { + $this->debug->append("STA " . __METHOD__, 4); + // Fetch the users mail address + if (!$email = $this->getUserEmail($username)) { + $this->setErrorMessage("Unable to find a mail address for user $username"); + return false; + } + if (!$this->setUserToken($this->getUserId($username))) { + $this->setErrorMessage("Unable to setup token for password reset"); + return false; + } + // Send password reset link + if (!$token = $this->getUserToken($this->getUserId($username))) { + $this->setErrorMessage("Unable fetch token for password reset"); + return false; + } + $subject = "[" . $this->config['website']['name'] . "] Password Reset Request"; + $header = "From: " . $this->config['website']['email']; + $message = "Please follow the link to reset your password\n\n" . $this->config['website']['url']['password_reset'] . "/index.php?page=password&action=change&token=$token"; + if (mail($email, 'Password Reset Request', $message)) { + return true; + } else { + $this->setErrorMessage("Unable to send mail to your address"); + return false; + } + return false; + } } -$user = new User($debug, $mysqli, SALT); +$user = new User($debug, $mysqli, SALT, $config); diff --git a/public/include/pages/password.inc.php b/public/include/pages/password.inc.php new file mode 100644 index 00000000..aecab054 --- /dev/null +++ b/public/include/pages/password.inc.php @@ -0,0 +1,9 @@ +assign("CONTENT", "default.tpl"); +?> diff --git a/public/include/pages/password/reset.inc.php b/public/include/pages/password/reset.inc.php new file mode 100644 index 00000000..532eb67c --- /dev/null +++ b/public/include/pages/password/reset.inc.php @@ -0,0 +1,15 @@ +resetPassword($_POST['username'])) { + $_SESSION['POPUP'][] = array('CONTENT' => 'Please check your mail account to finish your password reset'); +} else { + $_SESSION['POPUP'][] = array('CONTENT' => $user->getError(), 'TYPE' => 'errormsg'); +} + +// Tempalte specifics, user default template by parent page +$smarty->assign("CONTENT", "../default.tpl"); +?> diff --git a/public/templates/mmcFE/global/login.tpl b/public/templates/mmcFE/global/login.tpl index 0247c665..d411d39a 100644 --- a/public/templates/mmcFE/global/login.tpl +++ b/public/templates/mmcFE/global/login.tpl @@ -4,5 +4,5 @@

-

Forgot your password?

+

Forgot your password?

{include file="global/block_footer.tpl"} diff --git a/public/templates/mmcFE/password/default.tpl b/public/templates/mmcFE/password/default.tpl new file mode 100644 index 00000000..35b4a0eb --- /dev/null +++ b/public/templates/mmcFE/password/default.tpl @@ -0,0 +1,8 @@ +{include file="global/block_header.tpl" BLOCK_HEADER="Reset Password" BLOCK_STYLE="clear:none;"} +
+ + +

If you have an email set for your account, enter your username to get your password reset

+

+
+{include file="global/block_footer.tpl"} From 89f9673ec0457abac26d6a1dccaec94426400ad5 Mon Sep 17 00:00:00 2001 From: WKNiGHT- Date: Thu, 23 May 2013 15:43:14 -0500 Subject: [PATCH 03/59] fix common link backs for register and worker --- public/templates/mmcFE/gettingstarted/default.tpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/templates/mmcFE/gettingstarted/default.tpl b/public/templates/mmcFE/gettingstarted/default.tpl index 6e63157e..ac1bafce 100644 --- a/public/templates/mmcFE/gettingstarted/default.tpl +++ b/public/templates/mmcFE/gettingstarted/default.tpl @@ -11,8 +11,8 @@
  • Create account.
      -
    • Register here, or login if you already have account
    • -
    • Create a worker that will be used by the miner to login
    • +
    • Register here, or login if you already have account
    • +
    • Create a worker that will be used by the miner to login
  • Download a miner. From 5e8df562fcad4273456ec1c2b6136acb6c733368 Mon Sep 17 00:00:00 2001 From: WKNiGHT- Date: Thu, 23 May 2013 15:48:29 -0500 Subject: [PATCH 04/59] Fix broken link for workers --- public/templates/mmcFE/gettingstarted/default.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/templates/mmcFE/gettingstarted/default.tpl b/public/templates/mmcFE/gettingstarted/default.tpl index 6e63157e..1098b2cd 100644 --- a/public/templates/mmcFE/gettingstarted/default.tpl +++ b/public/templates/mmcFE/gettingstarted/default.tpl @@ -49,7 +49,7 @@ Start your miner using the following parameters: If you use a command-line miner, type:
    	./minerd --url http://pool.grewe.ca:8337/ --userpass Weblogin.Worker:Worker password
     
    - If you want, you can create additional slaves with usernames and passwords of your choice Here

    + If you want, you can create additional workers with usernames and passwords of your choice Here

  • Create a Litecoin address to recieve payments.
      From 1c5bd1464629bed137ca9244af106f055b65e678 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Fri, 24 May 2013 08:51:25 +0200 Subject: [PATCH 05/59] removed hard link to index.php --- public/templates/mmcFE/gettingstarted/default.tpl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/public/templates/mmcFE/gettingstarted/default.tpl b/public/templates/mmcFE/gettingstarted/default.tpl index 26233b6c..7defdb1a 100644 --- a/public/templates/mmcFE/gettingstarted/default.tpl +++ b/public/templates/mmcFE/gettingstarted/default.tpl @@ -11,8 +11,8 @@
    • Create account.
        -
      • Register here, or login if you already have account
      • -
      • Create a worker that will be used by the miner to login
      • +
      • Register here, or login if you already have account
      • +
      • Create a worker that will be used by the miner to login
    • Download a miner. @@ -49,7 +49,7 @@ Start your miner using the following parameters: If you use a command-line miner, type:
      	./minerd --url http://pool.grewe.ca:8337/ --userpass Weblogin.Worker:Worker password
       
      - If you want, you can create additional workers with usernames and passwords of your choice Here

      + If you want, you can create additional workers with usernames and passwords of your choice Here

    • Create a Litecoin address to recieve payments.
        From 9cf193c53913536fd7139775ef650e4d1a055f9c Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Fri, 24 May 2013 08:57:08 +0200 Subject: [PATCH 06/59] Update README.md --- README.md | 102 ++++++------------------------------------------------ 1 file changed, 10 insertions(+), 92 deletions(-) diff --git a/README.md b/README.md index 5ad2e71a..848af075 100644 --- a/README.md +++ b/README.md @@ -63,102 +63,18 @@ The following feature have been implemented so far: Installation ============ -Please ensure you fullfill the minimal installation requirements listed above -and install any missing packages or software. +Please take a look at the [Quick Start Guide](https://github.com/TheSerapher/php-mmcfe-ng/wiki/Quick-Start-Guide). This will give you +an idea how to setup `mmcfe-ng`. -Download Source ---------------- +Contributing +============ -Download the (stable) master branch from Github: +You can contribute to this project in different ways: -``` -git clone -b master git://github.com/TheSerapher/php-mmcfe-ng.git mmcfe-ng -``` +* Report outstanding issues and bugs by creating an [Issue][1] +* Suggest feature enhancements also via [Issues][1] +* Fork the project, create a branch and file a pull request to improve the code itself -Or, if you are not using git, use the ZIP file provided: - -``` -wget https://github.com/TheSerapher/php-mmcfe-ng/archive/master.zip -unzip master.zip -mv php-mmcfe-ng-master mmcfe-ng -``` - -Permissions ------------ - -Please ensure your webuser (e.g. `www-data`, `apache`) has write access to -the `mmcfe-ng/public/templates/compile` folder! Otherwise compiled -templates can not be stored: - -``` -sudo chown www-data mmcfe-ng/public/templates/compile -``` - -Apache2 Configuration ---------------------- - -Please point your website document root to the `mmcfe-ng/public` folder -and enable auto-index for `index.php`. - -Memcache --------- - -Please install and start a default memcache instance. Not only would you -need one for `pushpoold` but the statistics page is storing data in -`memcache` as well to improve performance. Your memcache can be -configured in the global configuration file (see below). - -Configuration -------------- - -Please create the `mmcfe-ng/public/include/config/global.inc.php` -configuration from the supplied template -`mmcfe-ng/public/include/config/global.inc.dist.php`. - -Pushpoold ---------- - -Please ensure the passwords are read from the proper table by adding this to your configuration: - -``` - # database settings - "database" : { - "engine" : "mysql", - "port" : "3306", - "name" : "mmcfeng_database_name", - "username" : "someuser", - "password" : "somepass", - "sharelog" : true, - "stmt.pwdb":"SELECT `password` FROM `workers` WHERE `username` = ?", - "stmt.sharelog":"INSERT INTO shares (rem_host, username, our_result, upstream_result, reason, solution) VALUES (?, ?, ?, ?, ?, ?)" - }, - -``` - -Database -======== - -Now that the software is ready we need to import the database. -You will find the SQL file in the `mmcfe-ng/sql` folder. -Import this file into an existing database and you should -have the proper structure ready. - -TODO -==== - -I tried to cover most features available in mmcFE. There might be some missing still -(like graphs, some stats) but if you figure there is a core function missing please let -me know by creating an [Issue][1] marked as `Feature Request`. - -Disclaimer -========== - -This is a **WIP Project**. Most functionality is now added, the core -features are available and the backend cronjobs are working. I would not recommend -running this on a live pool yet. You can play around and test basic functionality but -wait for any live deployment for at least a stable Release Candidate. - - [1]: https://github.com/TheSerapher/php-mmcfe-ng/issues "Issue" License and Author ================== @@ -177,3 +93,5 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + + [1]: https://github.com/TheSerapher/php-mmcfe-ng/issues "Issue" From 8220e7ebb96ad7ebd419190821171890047bcaf0 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Fri, 24 May 2013 09:21:02 +0200 Subject: [PATCH 07/59] Create CONTRIBUTING.md Adding a contribution guide --- CONTRIBUTING.md | 60 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..60b3c3b5 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,60 @@ +# How to contribute + +Third-party patches are much appreciated. This is a rather large project +and a single person can not work on it 24/7 to address all issues and +feature requests. If you feel comfortable with PHP and Smarty you should +consider following this contribution guide! + +## Getting Started + +* Make sure you have a [GitHub account][4]. +* Submit an [Issue][1] for your issue, assuming one does not already exist. + * Clearly describe the issue including steps to reproduce when it is a bug. + * Make sure you fill in the earliest version that you know has the issue. +* Fork the repository into your GitHub account + +## Making Changes + +* Create a topic branch from where you want to base your work. + * This is usually the `next` branch. + * Only target release branches if you are certain your fix must be on that + branch. + * To quickly create a topic branch based on `next`; `git branch + fix/next/my_contribution next` then checkout the new branch with `git + checkout fix/next/my_contribution`. Please avoid working directly on the + `next` branch. +* Make commits of logical units. +* Check for unnecessary whitespace with `git diff --check` before committing. +* Make sure your commit messages are in the proper format. + +```` + (#99999) Make the example in CONTRIBUTING imperative and concrete + + Without this patch applied the example commit message in the CONTRIBUTING + document is not a concrete example. This is a problem because the + contributor is left to imagine what the commit message should look like + based on a description rather than an example. This patch fixes the + problem by making the example concrete and imperative. + + The first line is a real life imperative statement with an issue number + from our issue tracker. The body describes the behavior without the patch, + why this is a problem, and how the patch fixes the problem when applied. +```` + +## Submitting Changes + +* Push your changes to a topic branch in your fork of the repository. +* Submit a pull request to the origin repository. +* Update your issue that you have submitted code and are ready for it to be reviewed. + * Include a link to the pull request in the ticket + +# Additional Resources + +* [Issue Tracker][1] +* [General GitHub documentation][2] +* [GitHub pull request documentation][3] + +[1]: https://github.com/~/issues "Issue" +[2]: http://help.github.com/ "GitHub documentation" +[3]: http://help.github.com/send-pull-requests/ "GitHub pull request documentation" +[4]: https://github.com/signup/free "GitHub account" From 31b4c3829f26b57443e5d670843e07b96918e3a4 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Fri, 24 May 2013 09:32:43 +0200 Subject: [PATCH 08/59] Update CONTRIBUTING.md Fixed wrong issue link --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 60b3c3b5..d0187d0a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -54,7 +54,7 @@ consider following this contribution guide! * [General GitHub documentation][2] * [GitHub pull request documentation][3] -[1]: https://github.com/~/issues "Issue" +[1]: https://github.com/TheSerapher/php-mmcfe-ng/issues "Issue" [2]: http://help.github.com/ "GitHub documentation" [3]: http://help.github.com/send-pull-requests/ "GitHub pull request documentation" [4]: https://github.com/signup/free "GitHub account" From 93fa758ab6504733733a5d923ebadf80f00d0d8b Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Fri, 24 May 2013 15:31:29 +0200 Subject: [PATCH 09/59] increase timerange for upstream share to cope with slower db writes --- public/include/classes/share.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/include/classes/share.class.php b/public/include/classes/share.class.php index f9e7c869..bb4a7d5b 100644 --- a/public/include/classes/share.class.php +++ b/public/include/classes/share.class.php @@ -125,7 +125,7 @@ class Share { SUBSTRING_INDEX( `username` , '.', 1 ) AS account, id FROM $this->table WHERE upstream_result = 'Y' - AND UNIX_TIMESTAMP(time) BETWEEN ? AND (? + 1) + AND UNIX_TIMESTAMP(time) BETWEEN ? AND (? + 5) ORDER BY id ASC LIMIT 1"); if ($this->checkStmt($stmt)) { $stmt->bind_param('ii', $time, $time); From a5cca8b54a976534556a91a31bdd86b02e4da549 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Fri, 24 May 2013 16:32:55 +0300 Subject: [PATCH 10/59] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 848af075..3a0ab83a 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Description =========== -mmcFE-ng is a web frontend for Pooled LTC Mining. +mmcFE-ng is a web frontend for Pooled LTC Mining. A pool using this interface is running at http://pool.grewe.ca The web frontend layout is based on mmcFE, the original work by Greedi: https://github.com/Greedi/mmcFE From b771920210311f2c85aefaed1845851d5c42d7e0 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Fri, 24 May 2013 15:57:14 +0200 Subject: [PATCH 11/59] adding block status page for past 30 blocks, no graphs yet --- .../include/pages/statistics/blocks.inc.php | 22 +++++++++++++++++++ public/include/pages/statistics/pool.inc.php | 4 +++- public/templates/mmcFE/global/navigation.tpl | 2 +- .../mmcFE/statistics/blocks/blocks_found.tpl | 2 +- 4 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 public/include/pages/statistics/blocks.inc.php diff --git a/public/include/pages/statistics/blocks.inc.php b/public/include/pages/statistics/blocks.inc.php new file mode 100644 index 00000000..7ba0bfdd --- /dev/null +++ b/public/include/pages/statistics/blocks.inc.php @@ -0,0 +1,22 @@ +getBlocksFound($iLimit); +$aBlockData = $aBlocksFoundData[0]; + +// Propagate content our template +$smarty->assign("BLOCKSFOUND", $aBlocksFoundData); +$smarty->assign("BLOCKLIMIT", $iLimit); + +if ($_SESSION['AUTHENTICATED']) { + $smarty->assign("CONTENT", "blocks_found.tpl"); +} else { + $smarty->assign("CONTENT", "default.tpl"); +} +?> diff --git a/public/include/pages/statistics/pool.inc.php b/public/include/pages/statistics/pool.inc.php index af0a4ebf..238b00b5 100644 --- a/public/include/pages/statistics/pool.inc.php +++ b/public/include/pages/statistics/pool.inc.php @@ -27,7 +27,8 @@ $aContributorsShares = $statistics->getTopContributors('shares', 15); $aContributorsHashes = $statistics->getTopContributors('hashes', 15); // Grab the last 10 blocks found -$aBlocksFoundData = $statistics->getBlocksFound(10); +$iLimit = 10; +$aBlocksFoundData = $statistics->getBlocksFound($iLimit); $aBlockData = $aBlocksFoundData[0]; // Estimated time to find the next block @@ -47,6 +48,7 @@ if (!empty($aBlockData)) { $smarty->assign("ESTTIME", $iEstTime); $smarty->assign("TIMESINCELAST", $dTimeSinceLast); $smarty->assign("BLOCKSFOUND", $aBlocksFoundData); +$smarty->assign("BLOCKLIMIT", $iLimit); $smarty->assign("CONTRIBSHARES", $aContributorsShares); $smarty->assign("CONTRIBHASHES", $aContributorsHashes); $smarty->assign("CURRENTBLOCK", $iBlock); diff --git a/public/templates/mmcFE/global/navigation.tpl b/public/templates/mmcFE/global/navigation.tpl index 83400cae..52b99a3f 100644 --- a/public/templates/mmcFE/global/navigation.tpl +++ b/public/templates/mmcFE/global/navigation.tpl @@ -14,7 +14,7 @@
      • Statistics
      • Getting Started
      • diff --git a/public/templates/mmcFE/statistics/blocks/blocks_found.tpl b/public/templates/mmcFE/statistics/blocks/blocks_found.tpl index a8f9686f..7f6c27bf 100644 --- a/public/templates/mmcFE/statistics/blocks/blocks_found.tpl +++ b/public/templates/mmcFE/statistics/blocks/blocks_found.tpl @@ -1,4 +1,4 @@ -{include file="global/block_header.tpl" BLOCK_HEADER="Last 10 Blocks Found" BLOCK_STYLE="clear:none;" BUTTONS=array(More)} +{include file="global/block_header.tpl" BLOCK_HEADER="Last $BLOCKLIMIT Blocks Found" BLOCK_STYLE="clear:none;" BUTTONS=array(More)}
        From 30a46979b9b4d934e99720c2057daefb0bbfc98d Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Fri, 24 May 2013 16:16:53 +0200 Subject: [PATCH 12/59] adding configurable block explorer and chain info URLs --- public/include/smarty_globals.inc.php | 4 +++- public/templates/mmcFE/statistics/blocks/blocks_found.tpl | 2 +- public/templates/mmcFE/statistics/pool/authenticated.tpl | 6 +++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/public/include/smarty_globals.inc.php b/public/include/smarty_globals.inc.php index e17f82be..c383dfb0 100644 --- a/public/include/smarty_globals.inc.php +++ b/public/include/smarty_globals.inc.php @@ -22,7 +22,9 @@ $aGlobal = array( 'roundshares' => $aRoundShares, 'fees' => $config['fees'], 'confirmations' => $config['confirmations'], - 'reward' => $config['reward'] + 'reward' => $config['reward'], + 'blockexplorer' => 'http://explorer.litecoin.net/search?q=', + 'chaininfo' => 'http://allchains.info' ); // We don't want these session infos cached diff --git a/public/templates/mmcFE/statistics/blocks/blocks_found.tpl b/public/templates/mmcFE/statistics/blocks/blocks_found.tpl index 7f6c27bf..1bab7966 100644 --- a/public/templates/mmcFE/statistics/blocks/blocks_found.tpl +++ b/public/templates/mmcFE/statistics/blocks/blocks_found.tpl @@ -15,7 +15,7 @@ {assign var=rank value=1} {section block $BLOCKSFOUND} - + diff --git a/public/templates/mmcFE/statistics/pool/authenticated.tpl b/public/templates/mmcFE/statistics/pool/authenticated.tpl index 7bddd421..9a5a593c 100644 --- a/public/templates/mmcFE/statistics/pool/authenticated.tpl +++ b/public/templates/mmcFE/statistics/pool/authenticated.tpl @@ -17,15 +17,15 @@ - + - + - + From 841d9867269004216025f16c74bd8ea4930f7975 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Thu, 23 May 2013 11:10:17 +0200 Subject: [PATCH 13/59] initial work on password reset, not working fully yet --- public/include/classes/user.class.php | 61 ++++++++++++++++++--- public/include/pages/password.inc.php | 9 +++ public/include/pages/password/reset.inc.php | 15 +++++ public/templates/mmcFE/global/login.tpl | 2 +- public/templates/mmcFE/password/default.tpl | 8 +++ 5 files changed, 85 insertions(+), 10 deletions(-) create mode 100644 public/include/pages/password.inc.php create mode 100644 public/include/pages/password/reset.inc.php create mode 100644 public/templates/mmcFE/password/default.tpl diff --git a/public/include/classes/user.class.php b/public/include/classes/user.class.php index e33b8c7c..3ec72546 100644 --- a/public/include/classes/user.class.php +++ b/public/include/classes/user.class.php @@ -11,10 +11,11 @@ class User { private $user = array(); private $tableAccountBalance = 'accountBalance'; - public function __construct($debug, $mysqli, $salt) { + public function __construct($debug, $mysqli, $salt, $config) { $this->debug = $debug; $this->mysqli = $mysqli; $this->salt = $salt; + $this->config = $config; $this->debug->append("Instantiated User class", 2); } @@ -34,6 +35,23 @@ class User { return $this->getSingle($username, 'id', 'username', 's'); } + public function getUserEmail($username) { + return $this->getSingle($username, 'email', 'username', 's'); + } + + public function getUserToken($id) { + return $this->getSingle($id, 'token', 'id'); + } + + public function setUserToken($id) { + $field = array( + 'name' => 'token', + 'type' => 's', + 'value' => hash('sha256', $id.time().$this->salt) + ); + return $this->updateSingle($id, $field); + } + /** * Check user login * @param username string Username @@ -142,15 +160,12 @@ class User { * @param field string Field to update * @return bool **/ - private function updateSingle($userID, $field) { + private function updateSingle($id, $field) { $this->debug->append("STA " . __METHOD__, 4); - $stmt = $this->mysqli->prepare("UPDATE $this->table SET " . $field['name'] . " = ? WHERE userId = ? LIMIT 1"); - if ($this->checkStmt($stmt)) { - $stmt->bind_param($field['type'].'i', $field['value'], $userID); - $stmt->execute(); - $stmt->close(); + $stmt = $this->mysqli->prepare("UPDATE $this->table SET " . $field['name'] . " = ? WHERE id = ? LIMIT 1"); + if ($this->checkStmt($stmt) && $stmt->bind_param($field['type'].'i', $field['value'], $id) && $stmt->execute()) return true; - } + $this->debug->append("Unable to update " . $field['name'] . " with " . $field['value'] . " for ID $id"); return false; } @@ -306,6 +321,34 @@ class User { } return false; } + + public function resetPassword($username) { + $this->debug->append("STA " . __METHOD__, 4); + // Fetch the users mail address + if (!$email = $this->getUserEmail($username)) { + $this->setErrorMessage("Unable to find a mail address for user $username"); + return false; + } + if (!$this->setUserToken($this->getUserId($username))) { + $this->setErrorMessage("Unable to setup token for password reset"); + return false; + } + // Send password reset link + if (!$token = $this->getUserToken($this->getUserId($username))) { + $this->setErrorMessage("Unable fetch token for password reset"); + return false; + } + $subject = "[" . $this->config['website']['name'] . "] Password Reset Request"; + $header = "From: " . $this->config['website']['email']; + $message = "Please follow the link to reset your password\n\n" . $this->config['website']['url']['password_reset'] . "/index.php?page=password&action=change&token=$token"; + if (mail($email, 'Password Reset Request', $message)) { + return true; + } else { + $this->setErrorMessage("Unable to send mail to your address"); + return false; + } + return false; + } } -$user = new User($debug, $mysqli, SALT); +$user = new User($debug, $mysqli, SALT, $config); diff --git a/public/include/pages/password.inc.php b/public/include/pages/password.inc.php new file mode 100644 index 00000000..aecab054 --- /dev/null +++ b/public/include/pages/password.inc.php @@ -0,0 +1,9 @@ +assign("CONTENT", "default.tpl"); +?> diff --git a/public/include/pages/password/reset.inc.php b/public/include/pages/password/reset.inc.php new file mode 100644 index 00000000..532eb67c --- /dev/null +++ b/public/include/pages/password/reset.inc.php @@ -0,0 +1,15 @@ +resetPassword($_POST['username'])) { + $_SESSION['POPUP'][] = array('CONTENT' => 'Please check your mail account to finish your password reset'); +} else { + $_SESSION['POPUP'][] = array('CONTENT' => $user->getError(), 'TYPE' => 'errormsg'); +} + +// Tempalte specifics, user default template by parent page +$smarty->assign("CONTENT", "../default.tpl"); +?> diff --git a/public/templates/mmcFE/global/login.tpl b/public/templates/mmcFE/global/login.tpl index 0247c665..d411d39a 100644 --- a/public/templates/mmcFE/global/login.tpl +++ b/public/templates/mmcFE/global/login.tpl @@ -4,5 +4,5 @@

        -

        Forgot your password?

        +

        Forgot your password?

        {include file="global/block_footer.tpl"} diff --git a/public/templates/mmcFE/password/default.tpl b/public/templates/mmcFE/password/default.tpl new file mode 100644 index 00000000..35b4a0eb --- /dev/null +++ b/public/templates/mmcFE/password/default.tpl @@ -0,0 +1,8 @@ +{include file="global/block_header.tpl" BLOCK_HEADER="Reset Password" BLOCK_STYLE="clear:none;"} +
        + + +

        If you have an email set for your account, enter your username to get your password reset

        +

        + +{include file="global/block_footer.tpl"} From 787942b6f90ebab0eef8e4e2f7b1a73d4fe2a397 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Sat, 25 May 2013 12:08:51 +0200 Subject: [PATCH 14/59] working version of password reset with one time token --- public/include/classes/user.class.php | 37 ++++++++++++++++--- public/include/config/global.inc.dist.php | 1 + public/include/pages/password/change.inc.php | 17 +++++++++ public/include/pages/password/reset.inc.php | 3 +- public/templates/mail/body.tpl | 13 +++++++ public/templates/mail/subject.tpl | 1 + .../mmcFE/password/change/default.tpl | 12 ++++++ 7 files changed, 78 insertions(+), 6 deletions(-) create mode 100644 public/include/pages/password/change.inc.php create mode 100644 public/templates/mail/body.tpl create mode 100644 public/templates/mail/subject.tpl create mode 100644 public/templates/mmcFE/password/change/default.tpl diff --git a/public/include/classes/user.class.php b/public/include/classes/user.class.php index 3ec72546..3e373ab7 100644 --- a/public/include/classes/user.class.php +++ b/public/include/classes/user.class.php @@ -43,6 +43,10 @@ class User { return $this->getSingle($id, 'token', 'id'); } + public function getIdFromToken($token) { + return $this->getSingle($token, 'id', 'token', 's'); + } + public function setUserToken($id) { $field = array( 'name' => 'token', @@ -322,7 +326,30 @@ class User { return false; } - public function resetPassword($username) { + public function useToken($token, $new1, $new2) { + $this->debug->append("STA " . __METHOD__, 4); + if ($id = $this->getIdFromToken($token)) { + if ($new1 !== $new2) { + $this->setErrorMessage( 'New passwords do not match' ); + return false; + } + if ( strlen($new1) < 8 ) { + $this->setErrorMessage( 'New password is too short, please use more than 8 chars' ); + return false; + } + $new = hash('sha256', $new1.$this->salt); + $stmt = $this->mysqli->prepare("UPDATE $this->table SET pass = ?, token = NULL WHERE id = ? AND token = ?"); + if ($this->checkStmt($stmt) && $stmt->bind_param('sis', $new, $id, $token) && $stmt->execute() && $stmt->affected_rows === 1) { + return true; + } + } else { + $this->setErrorMessage("Unable find user for your token"); + return false; + } + return false; + } + + public function resetPassword($username, $smarty) { $this->debug->append("STA " . __METHOD__, 4); // Fetch the users mail address if (!$email = $this->getUserEmail($username)) { @@ -338,10 +365,10 @@ class User { $this->setErrorMessage("Unable fetch token for password reset"); return false; } - $subject = "[" . $this->config['website']['name'] . "] Password Reset Request"; - $header = "From: " . $this->config['website']['email']; - $message = "Please follow the link to reset your password\n\n" . $this->config['website']['url']['password_reset'] . "/index.php?page=password&action=change&token=$token"; - if (mail($email, 'Password Reset Request', $message)) { + $smarty->assign('TOKEN', $token); + $smarty->assign('USERNAME', $username); + $smarty->assign('WEBSITENAME', $this->config['website']['name']); + if (mail($email, $smarty->fetch('templates/mail/subject.tpl'), $smarty->fetch('templates/mail/body.tpl'))) { return true; } else { $this->setErrorMessage("Unable to send mail to your address"); diff --git a/public/include/config/global.inc.dist.php b/public/include/config/global.inc.dist.php index 37d39c3f..f684c2bb 100644 --- a/public/include/config/global.inc.dist.php +++ b/public/include/config/global.inc.dist.php @@ -24,6 +24,7 @@ $config = array( 'website' => array( 'name' => 'The Pool', 'slogan' => 'Resistance is futile', + 'email' => 'test@example.com', // Mail address used for notifications ), 'fees' => 0, 'difficulty' => '31', // Target difficulty for this pool as set in pushpoold json diff --git a/public/include/pages/password/change.inc.php b/public/include/pages/password/change.inc.php new file mode 100644 index 00000000..8b5f4064 --- /dev/null +++ b/public/include/pages/password/change.inc.php @@ -0,0 +1,17 @@ +useToken($_POST['token'], $_POST['newPassword'], $_POST['newPassword2'])) { + $_SESSION['POPUP'][] = array('CONTENT' => 'Password reset complete! Please login.'); + } else { + $_SESSION['POPUP'][] = array('CONTENT' => $user->getError(), 'TYPE' => 'errormsg'); + } +} + +// Tempalte specifics +$smarty->assign("CONTENT", "default.tpl"); +?> diff --git a/public/include/pages/password/reset.inc.php b/public/include/pages/password/reset.inc.php index 532eb67c..796f5811 100644 --- a/public/include/pages/password/reset.inc.php +++ b/public/include/pages/password/reset.inc.php @@ -4,7 +4,8 @@ if (!defined('SECURITY')) die('Hacking attempt'); -if ($user->resetPassword($_POST['username'])) { +// Process password reset request +if ($user->resetPassword($_POST['username'], $smarty)) { $_SESSION['POPUP'][] = array('CONTENT' => 'Please check your mail account to finish your password reset'); } else { $_SESSION['POPUP'][] = array('CONTENT' => $user->getError(), 'TYPE' => 'errormsg'); diff --git a/public/templates/mail/body.tpl b/public/templates/mail/body.tpl new file mode 100644 index 00000000..ad36501d --- /dev/null +++ b/public/templates/mail/body.tpl @@ -0,0 +1,13 @@ +Hello {$USERNAME}, + +You have requested a password reset through our online form. +In order to complete the request please follow this link + +http://{$smarty.server.SERVER_NAME}{$smarty.server.PHP_SELF}?page=password&action=change&token={$TOKEN} + +You will be asked to change your password. You can then use this new +password to login to your account. + + +Cheers, +Website Administration diff --git a/public/templates/mail/subject.tpl b/public/templates/mail/subject.tpl new file mode 100644 index 00000000..665e26f5 --- /dev/null +++ b/public/templates/mail/subject.tpl @@ -0,0 +1 @@ +[ {$WEBSITENAME} ] Password Reset Request diff --git a/public/templates/mmcFE/password/change/default.tpl b/public/templates/mmcFE/password/change/default.tpl new file mode 100644 index 00000000..0d254677 --- /dev/null +++ b/public/templates/mmcFE/password/change/default.tpl @@ -0,0 +1,12 @@ +{include file="global/block_header.tpl" BLOCK_HEADER="Change Password"} +
        + + + + +
        {$BLOCKSFOUND[block].height}{$BLOCKSFOUND[block].height} {if $BLOCKSFOUND[block].confirmations >= $GLOBAL.confirmations}Confirmed{else}{$GLOBAL.confirmations - $BLOCKSFOUND[block].confirmations} left{/if} {$BLOCKSFOUND[block].finder|default:"unknown"} {$BLOCKSFOUND[block].time|date_format:"%d/%m/%Y %H:%M:%S"}
        Next Network Block{$CURRENTBLOCK + 1}    (Current: {$CURRENTBLOCK}){$CURRENTBLOCK + 1}    (Current: {$CURRENTBLOCK})
        Last Block Found{$LASTBLOCK|default:"0"}{$LASTBLOCK|default:"0"}
        Current Difficulty{$DIFFICULTY}{$DIFFICULTY}
        Est. Avg. Time per Round
        + + +
        New Password:
        New Password Repeat:
        + +{include file="global/block_footer.tpl"} From 93d0ec06a66b56bea205c9626300bc4e31ec4614 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Sat, 25 May 2013 12:25:41 +0200 Subject: [PATCH 15/59] adding proper headers for HTML mail --- public/include/classes/user.class.php | 8 +++++++- public/templates/mail/body.tpl | 23 ++++++++++------------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/public/include/classes/user.class.php b/public/include/classes/user.class.php index 3e373ab7..d54b2da5 100644 --- a/public/include/classes/user.class.php +++ b/public/include/classes/user.class.php @@ -368,7 +368,13 @@ class User { $smarty->assign('TOKEN', $token); $smarty->assign('USERNAME', $username); $smarty->assign('WEBSITENAME', $this->config['website']['name']); - if (mail($email, $smarty->fetch('templates/mail/subject.tpl'), $smarty->fetch('templates/mail/body.tpl'))) { + $headers = 'From: Website Administration <' . $this->config['website']['email'] . ">\n"; + $headers .= "MIME-Version: 1.0\n"; + $headers .= "Content-Type: text/html; charset=ISO-8859-1\r\n"; + if (mail($email, + $smarty->fetch('templates/mail/subject.tpl'), + $smarty->fetch('templates/mail/body.tpl'), + $headers)) { return true; } else { $this->setErrorMessage("Unable to send mail to your address"); diff --git a/public/templates/mail/body.tpl b/public/templates/mail/body.tpl index ad36501d..a80b579a 100644 --- a/public/templates/mail/body.tpl +++ b/public/templates/mail/body.tpl @@ -1,13 +1,10 @@ -Hello {$USERNAME}, - -You have requested a password reset through our online form. -In order to complete the request please follow this link - -http://{$smarty.server.SERVER_NAME}{$smarty.server.PHP_SELF}?page=password&action=change&token={$TOKEN} - -You will be asked to change your password. You can then use this new -password to login to your account. - - -Cheers, -Website Administration + + +

        Hello {$USERNAME},


        +

        You have requested a password reset through our online form. In order to complete the request please follow this link:

        +

        http://{$smarty.server.SERVER_NAME}{$smarty.server.PHP_SELF}?page=password&action=change&token={$TOKEN}

        +

        You will be asked to change your password. You can then use this new password to login to your account.

        +

        Cheers,

        +

        Website Administration

        + + From b8bd2b904e15b54594aceeb584db2a9cdd0eb5de Mon Sep 17 00:00:00 2001 From: Fred Date: Sat, 25 May 2013 12:58:37 -0400 Subject: [PATCH 16/59] Fix to over lapping stats on sidebar --- public/site_assets/mmcFE/css/style.css | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/public/site_assets/mmcFE/css/style.css b/public/site_assets/mmcFE/css/style.css index a2cc7ac1..2cf130bb 100644 --- a/public/site_assets/mmcFE/css/style.css +++ b/public/site_assets/mmcFE/css/style.css @@ -1,4 +1,3 @@ - * { padding:0; margin:0; } body { @@ -854,7 +853,7 @@ a:hover { /* Block sidebar */ .block.withsidebar .bendl { - /* width: 171px; */ + width: 191px; background: url(../images/bendsb.gif) bottom left no-repeat; } @@ -865,7 +864,7 @@ a:hover { } .block.withsidebar .block_content .sidebar { - width: 190px; + width: 210px; float: left; font-size: 11px; } From 587e5ba9a726b5e42de5205ab67236a8f66b040c Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Sun, 26 May 2013 20:23:38 +0200 Subject: [PATCH 17/59] better alignment of numbers in some tables --- public/site_assets/mmcFE/css/style.css | 8 +++++++ public/templates/mmcFE/global/sidebar.tpl | 24 +++++++++---------- .../mmcFE/statistics/blocks/blocks_found.tpl | 8 +++---- .../statistics/pool/contributors_hashrate.tpl | 12 +++++----- .../statistics/pool/contributors_shares.tpl | 8 +++---- 5 files changed, 34 insertions(+), 26 deletions(-) diff --git a/public/site_assets/mmcFE/css/style.css b/public/site_assets/mmcFE/css/style.css index 2cf130bb..a41aef4c 100644 --- a/public/site_assets/mmcFE/css/style.css +++ b/public/site_assets/mmcFE/css/style.css @@ -459,6 +459,14 @@ a:hover { font-size: 11px; } +.block table tr td.right{ + text-align: right; +} +.block table tr th.right{ + text-align: right; +} + + .block table tr td.delete a { color: #666; } .block table tr td.delete a:hover { color: #dd0000; } diff --git a/public/templates/mmcFE/global/sidebar.tpl b/public/templates/mmcFE/global/sidebar.tpl index b19710a2..db05979f 100644 --- a/public/templates/mmcFE/global/sidebar.tpl +++ b/public/templates/mmcFE/global/sidebar.tpl @@ -7,55 +7,55 @@
        - + - + - + - + - + - + - + - + - + - + - + - +
        diff --git a/public/templates/mmcFE/statistics/blocks/blocks_found.tpl b/public/templates/mmcFE/statistics/blocks/blocks_found.tpl index 1bab7966..6751ad64 100644 --- a/public/templates/mmcFE/statistics/blocks/blocks_found.tpl +++ b/public/templates/mmcFE/statistics/blocks/blocks_found.tpl @@ -7,8 +7,8 @@ Validity Finder Date / Time - Difficulty - Shares + Difficulty + Shares @@ -19,8 +19,8 @@ {if $BLOCKSFOUND[block].confirmations >= $GLOBAL.confirmations}Confirmed{else}{$GLOBAL.confirmations - $BLOCKSFOUND[block].confirmations} left{/if} {$BLOCKSFOUND[block].finder|default:"unknown"} {$BLOCKSFOUND[block].time|date_format:"%d/%m/%Y %H:%M:%S"} - {$BLOCKSFOUND[block].difficulty|number_format:"8"} - {$BLOCKSFOUND[block].shares|number_format} + {$BLOCKSFOUND[block].difficulty|number_format:"8"} + {$BLOCKSFOUND[block].shares|number_format} {/section} diff --git a/public/templates/mmcFE/statistics/pool/contributors_hashrate.tpl b/public/templates/mmcFE/statistics/pool/contributors_hashrate.tpl index 30dbf416..b97c1515 100644 --- a/public/templates/mmcFE/statistics/pool/contributors_hashrate.tpl +++ b/public/templates/mmcFE/statistics/pool/contributors_hashrate.tpl @@ -5,8 +5,8 @@ Rank User Name - KH/s - Ł/Day (est) + KH/s + Ł/Day (est) @@ -16,16 +16,16 @@ {$rank++} {$CONTRIBHASHES[contrib].account} - {$CONTRIBHASHES[contrib].hashrate|number_format} - {math equation="round(reward / ( diff * pow(2,32) / ( hashrate * 1000 ) / 3600 / 24), 3)" diff=$DIFFICULTY reward=$REWARD hashrate=$CONTRIBHASHES[contrib].hashrate} + {$CONTRIBHASHES[contrib].hashrate|number_format} + {math equation="round(reward / ( diff * pow(2,32) / ( hashrate * 1000 ) / 3600 / 24), 3)" diff=$DIFFICULTY reward=$REWARD hashrate=$CONTRIBHASHES[contrib].hashrate} {/section} {if $listed != 1} n/a {$GLOBAL.userdata.username} - {$GLOBAL.userdata.hashrate} - {math equation="round(reward / ( diff * pow(2,32) / ( hashrate * 1000 ) / 3600 / 24), 3)" diff=$DIFFICULTY reward=$REWARD hashrate=$GLOBAL.userdata.hashrate} + {$GLOBAL.userdata.hashrate} + {math equation="round(reward / ( diff * pow(2,32) / ( hashrate * 1000 ) / 3600 / 24), 3)" diff=$DIFFICULTY reward=$REWARD hashrate=$GLOBAL.userdata.hashrate} {/if} diff --git a/public/templates/mmcFE/statistics/pool/contributors_shares.tpl b/public/templates/mmcFE/statistics/pool/contributors_shares.tpl index 02f33283..04e9c3e0 100644 --- a/public/templates/mmcFE/statistics/pool/contributors_shares.tpl +++ b/public/templates/mmcFE/statistics/pool/contributors_shares.tpl @@ -4,8 +4,8 @@ Rank - User Name - Shares + User Name + Shares @@ -15,14 +15,14 @@ {$rank++} {$CONTRIBSHARES[hashrate].account} - {$CONTRIBSHARES[hashrate].shares|number_format} + {$CONTRIBSHARES[hashrate].shares|number_format} {/section} {if $listed != 1} n/a {$GLOBAL.userdata.username} - {$GLOBAL.userdata.shares.valid} + {$GLOBAL.userdata.shares.valid} {/if} From 34de1ae36e3b4772decaa88e486ee81160e3c125 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Sun, 26 May 2013 20:29:05 +0200 Subject: [PATCH 18/59] removing PPLNS about page since pool is running propotional system for now --- public/templates/mmcFE/global/navigation.tpl | 1 - 1 file changed, 1 deletion(-) diff --git a/public/templates/mmcFE/global/navigation.tpl b/public/templates/mmcFE/global/navigation.tpl index 52b99a3f..04c85553 100644 --- a/public/templates/mmcFE/global/navigation.tpl +++ b/public/templates/mmcFE/global/navigation.tpl @@ -21,7 +21,6 @@
      • Support
      • About
      • From 510d366a9ef870b9ad349efd264d5d1c0a472f45 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Sun, 26 May 2013 20:30:29 +0200 Subject: [PATCH 19/59] removing PPLNS references since pool runs propotional system for now --- public/templates/mmcFE/global/navigation.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/templates/mmcFE/global/navigation.tpl b/public/templates/mmcFE/global/navigation.tpl index 04c85553..62c24dbd 100644 --- a/public/templates/mmcFE/global/navigation.tpl +++ b/public/templates/mmcFE/global/navigation.tpl @@ -19,7 +19,7 @@
      • Getting Started
      • Support
      • -
      • About +
      • About From 3d5eddecb89f1b5f6acf39a106ba3e1de42920f2 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Sun, 26 May 2013 20:44:34 +0200 Subject: [PATCH 20/59] added more number formatting in sidear --- public/templates/mmcFE/global/sidebar.tpl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/public/templates/mmcFE/global/sidebar.tpl b/public/templates/mmcFE/global/sidebar.tpl index db05979f..1bc41932 100644 --- a/public/templates/mmcFE/global/sidebar.tpl +++ b/public/templates/mmcFE/global/sidebar.tpl @@ -7,51 +7,51 @@
        - + - + - + - + - + - + - + - + - + - + From 436aed65f1a06f12d83d7cfc1a7ccc3950d8cb69 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Mon, 27 May 2013 12:45:22 +0200 Subject: [PATCH 21/59] fixing margin between sidebar and content --- public/templates/mmcFE/master.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/templates/mmcFE/master.tpl b/public/templates/mmcFE/master.tpl index 6348c119..14aa2e56 100644 --- a/public/templates/mmcFE/master.tpl +++ b/public/templates/mmcFE/master.tpl @@ -51,7 +51,7 @@ {include file="global/login.tpl"} {/if} - @@ -84,4 +84,48 @@

        Listed are your estimated rewards and donations/fees for all blocks awaiting {$GLOBAL.confirmations} confirmations.

        +
        +
        +
        + + + + + + + + + + + +{section transaction $TRANSACTIONS} + {if ( + $TRANSACTIONS[transaction].type == 'Orphan_Credit' + or $TRANSACTIONS[transaction].type == 'Orphan_Donation' + or $TRANSACTIONS[transaction].type == 'Orphan_Fee' + )} + + + + + + + + + {if $TRANSACTIONS[transaction].type == Orphan_Credit} + {assign var="orphan_credits" value="`$orphan_credits+$TRANSACTIONS[transaction].amount`"} + {else} + {assign var="orphan_debits" value="`$orphan_debits+$TRANSACTIONS[transaction].amount`"} + {/if} + {/if} +{/section} + + + + + +
        TX #DateTX TypePayment AddressBlock #Amount
        {$TRANSACTIONS[transaction].id}{$TRANSACTIONS[transaction].timestamp}{$TRANSACTIONS[transaction].type}{$TRANSACTIONS[transaction].coin_address}{if $TRANSACTIONS[transaction].height == 0}n/a{else}{$TRANSACTIONS[transaction].height}{/if}{$TRANSACTIONS[transaction].amount}
        Orphaned Totals:{$orphan_credits - $orphan_debits}
        +

        Listed are your orphaned transactions for blocks not part of the main blockchain.

        +
      • + {include file="global/block_footer.tpl"} diff --git a/public/templates/mmcFE/statistics/blocks/blocks_found.tpl b/public/templates/mmcFE/statistics/blocks/blocks_found.tpl index 6751ad64..db1d79ab 100644 --- a/public/templates/mmcFE/statistics/blocks/blocks_found.tpl +++ b/public/templates/mmcFE/statistics/blocks/blocks_found.tpl @@ -16,7 +16,12 @@ {section block $BLOCKSFOUND} {$BLOCKSFOUND[block].height} - {if $BLOCKSFOUND[block].confirmations >= $GLOBAL.confirmations}Confirmed{else}{$GLOBAL.confirmations - $BLOCKSFOUND[block].confirmations} left{/if} + + {if $BLOCKSFOUND[block].confirmations >= $GLOBAL.confirmations} + Confirmed + {else if $BLOCKSFOUND[block].confirmations == -1} + Orphan + {else}{$GLOBAL.confirmations - $BLOCKSFOUND[block].confirmations} left{/if} {$BLOCKSFOUND[block].finder|default:"unknown"} {$BLOCKSFOUND[block].time|date_format:"%d/%m/%Y %H:%M:%S"} {$BLOCKSFOUND[block].difficulty|number_format:"8"} From 798e5b21f755696828f0cdc325cfd7690e87c01c Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Mon, 27 May 2013 14:48:57 +0200 Subject: [PATCH 23/59] added latest DB layout * Added support for account tokens to reset password * Added support for orphan transactions * Added support for negative block confirmations --- sql/mmcfe_ng_structure.sql | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sql/mmcfe_ng_structure.sql b/sql/mmcfe_ng_structure.sql index 52639bbc..6b961382 100644 --- a/sql/mmcfe_ng_structure.sql +++ b/sql/mmcfe_ng_structure.sql @@ -3,7 +3,7 @@ -- http://www.phpmyadmin.net -- -- Host: localhost --- Generation Time: May 20, 2013 at 07:35 PM +-- Generation Time: May 27, 2013 at 02:39 PM -- Server version: 5.5.31-0ubuntu0.13.04.1 -- PHP Version: 5.4.9-4ubuntu2 @@ -36,6 +36,7 @@ CREATE TABLE IF NOT EXISTS `accounts` ( `sessionTimeoutStamp` int(255) DEFAULT NULL, `pin` varchar(255) NOT NULL COMMENT 'four digit pin to allow account changes', `api_key` varchar(255) DEFAULT NULL, + `token` varchar(65) DEFAULT NULL, `donate_percent` float DEFAULT '0', `ap_threshold` float DEFAULT '0', `coin_address` varchar(255) DEFAULT NULL, @@ -53,7 +54,7 @@ CREATE TABLE IF NOT EXISTS `blocks` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `height` int(10) unsigned NOT NULL, `blockhash` char(65) NOT NULL, - `confirmations` int(10) unsigned NOT NULL, + `confirmations` int(10) NOT NULL, `amount` double NOT NULL, `difficulty` double NOT NULL, `time` int(11) NOT NULL, @@ -112,9 +113,10 @@ CREATE TABLE IF NOT EXISTS `shares_archive` ( `our_result` enum('Y','N') DEFAULT NULL, `upstream_result` enum('Y','N') DEFAULT NULL, `block_id` int(10) unsigned NOT NULL, - `time` datetime DEFAULT NULL, + `time` datetime NOT NULL, PRIMARY KEY (`id`), - UNIQUE KEY `share_id` (`share_id`) + UNIQUE KEY `share_id` (`share_id`), + KEY `time` (`time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Archive shares for potential later debugging purposes'; -- -------------------------------------------------------- @@ -143,7 +145,7 @@ CREATE TABLE IF NOT EXISTS `statistics_shares` ( CREATE TABLE IF NOT EXISTS `transactions` ( `id` int(255) NOT NULL AUTO_INCREMENT, `account_id` int(255) unsigned NOT NULL, - `type` enum('Credit','Debit_MP','Debit_AP','Fee','Donation') DEFAULT NULL, + `type` enum('Credit','Debit_MP','Debit_AP','Donation','Fee','Orphan_Credit','Orphan_Fee','Orphan_Donation') DEFAULT NULL, `coin_address` varchar(255) DEFAULT NULL, `amount` double DEFAULT '0', `block_id` int(255) DEFAULT NULL, From e1f92218a312f29988df048fc43f1406188efa7d Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Mon, 27 May 2013 14:55:13 +0200 Subject: [PATCH 24/59] addressing #66 with higher timerange for upstream shares --- public/include/classes/share.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/include/classes/share.class.php b/public/include/classes/share.class.php index bb4a7d5b..9a14aeeb 100644 --- a/public/include/classes/share.class.php +++ b/public/include/classes/share.class.php @@ -125,7 +125,7 @@ class Share { SUBSTRING_INDEX( `username` , '.', 1 ) AS account, id FROM $this->table WHERE upstream_result = 'Y' - AND UNIX_TIMESTAMP(time) BETWEEN ? AND (? + 5) + AND UNIX_TIMESTAMP(time) BETWEEN (? - 5) AND (? + 5) ORDER BY id ASC LIMIT 1"); if ($this->checkStmt($stmt)) { $stmt->bind_param('ii', $time, $time); From 75bee6ed60d7bb678bf83aee0ab4c47f25ab37c5 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Mon, 27 May 2013 15:51:20 +0200 Subject: [PATCH 25/59] fetch account balance across all users * Used later for admin panel to show total amount of credits locked for users * Used later for liquid asset calculations --- public/include/classes/transaction.class.php | 37 ++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/public/include/classes/transaction.class.php b/public/include/classes/transaction.class.php index 207081bd..27871655 100644 --- a/public/include/classes/transaction.class.php +++ b/public/include/classes/transaction.class.php @@ -107,6 +107,43 @@ class Transaction { return true; } + /** + * Get total balance for all users locked in wallet + * @param none + * @return data double Amount locked for users + **/ + public function getLockedBalance() { + $this->debug->append("STA " . __METHOD__, 4); + $stmt = $this->mysqli->prepare(" + SELECT ROUND(IFNULL(t1.credit, 0) - IFNULL(t2.debit, 0) - IFNULL(t3.other, 0), 8) AS balance + FROM + ( + SELECT sum(t.amount) AS credit + FROM $this->table AS t + LEFT JOIN " . $this->block->getTableName() . " AS b ON t.block_id = b.id + WHERE t.type = 'Credit' + AND b.confirmations >= ? + ) AS t1, + ( + SELECT sum(t.amount) AS debit + FROM $this->table AS t + WHERE t.type IN ('Debit_MP', 'Debit_AP') + ) AS t2, + ( + SELECT sum(t.amount) AS other + FROM transactions AS t + LEFT JOIN " . $this->block->getTableName() . " AS b ON t.block_id = b.id + WHERE t.type IN ('Donation','Fee') + AND b.confirmations >= ? + ) AS t3"); + if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $this->config['confirmations'], $this->config['confirmations']) && $stmt->execute() && $stmt->bind_result($dBalance) && $stmt->fetch()) + return $dBalance; + // Catchall + $this->setErrorMessage('Unable to find locked credits for all users'); + $this->debug->append('MySQL query failed : ' . $this->mysqli->error); + return false; + } + public function getBalance($account_id) { $this->debug->append("STA " . __METHOD__, 4); $stmt = $this->mysqli->prepare(" From 376bae1e2d056512b8ac49be40af5499fe77c254 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Tue, 28 May 2013 10:09:57 +0200 Subject: [PATCH 26/59] Moved setCache method into StatsCacheClass * Allow calling method via memcache wrapping call * Make it available to all classes using StatsCache --- public/include/classes/statistics.class.php | 33 +++++++-------------- public/include/classes/statscache.class.php | 13 ++++++++ 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/public/include/classes/statistics.class.php b/public/include/classes/statistics.class.php index a38fb14e..8b12391e 100644 --- a/public/include/classes/statistics.class.php +++ b/public/include/classes/statistics.class.php @@ -43,19 +43,6 @@ class Statistics { return true; } - /** - * Another wrapper, we want to store data in memcache and return the actual data - * for further processing - * @param key string Our memcache key - * @param data mixed Our data to store in Memcache - * @param expiration time Our expiration time, see Memcached documentation - * @return data mixed Return our stored data unchanged - **/ - public function setCache($key, $data, $expiration=NULL) { - if ($this->config['memcache']['enabled']) $this->memcache->set($key, $data, $expiration); - return $data; - } - /** * Get our last $limit blocks found * @param limit int Last limit blocks @@ -71,7 +58,7 @@ class Statistics { ON b.account_id = a.id ORDER BY height DESC LIMIT ?"); if ($this->checkStmt($stmt) && $stmt->bind_param("i", $limit) && $stmt->execute() && $result = $stmt->get_result()) - return $this->setCache(__FUNCTION__ . $limit, $result->fetch_all(MYSQLI_ASSOC), 5); + return $this->memcache->setCache(__FUNCTION__ . $limit, $result->fetch_all(MYSQLI_ASSOC), 5); // Catchall $this->debug->append("Failed to find blocks:" . $this->mysqli->error); return false; @@ -110,7 +97,7 @@ class Statistics { SELECT ROUND(COUNT(id) * POW(2, " . $this->config['difficulty'] . ")/600/1000) AS hashrate FROM " . $this->share->getArchiveTableName() . " WHERE time > DATE_SUB(now(), INTERVAL 10 MINUTE) ) AS sum"); // Catchall - if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result() ) return $this->setCache(__FUNCTION__, $result->fetch_object()->hashrate); + if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result() ) return $this->memcache->setCache(__FUNCTION__, $result->fetch_object()->hashrate); $this->debug->append("Failed to get hashrate: " . $this->mysqli->error); return false; } @@ -130,7 +117,7 @@ class Statistics { UNION ALL SELECT COUNT(id) AS sharerate FROM " . $this->share->getArchiveTableName() . " WHERE time > DATE_SUB(now(), INTERVAL 10 MINUTE) ) AS sum"); - if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result() ) return $this->setCache(__FUNCTION__, $result->fetch_object()->sharerate); + if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result() ) return $this->memcache->setCache(__FUNCTION__, $result->fetch_object()->sharerate); // Catchall $this->debug->append("Failed to fetch share rate: " . $this->mysqli->error); return false; @@ -155,7 +142,7 @@ class Statistics { WHERE UNIX_TIMESTAMP(time) >IFNULL((SELECT MAX(time) FROM blocks),0) AND our_result = 'N' ) as invalid"); if ( $this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result() ) - return $this->setCache(__FUNCTION__, $result->fetch_assoc()); + return $this->memcache->setCache(__FUNCTION__, $result->fetch_assoc()); // Catchall $this->debug->append("Failed to fetch round shares: " . $this->mysqli->error); return false; @@ -190,7 +177,7 @@ class Statistics { AND u.id = ? ) AS invalid"); if ($stmt && $stmt->bind_param("ii", $account_id, $account_id) && $stmt->execute() && $result = $stmt->get_result()) - return $this->setCache(__FUNCTION__ . $account_id, $result->fetch_assoc()); + return $this->memcache->setCache(__FUNCTION__ . $account_id, $result->fetch_assoc()); // Catchall $this->debug->append("Unable to fetch user round shares: " . $this->mysqli->error); return false; @@ -211,7 +198,7 @@ class Statistics { AND s.time > DATE_SUB(now(), INTERVAL 10 MINUTE) AND u.id = ?"); if ($this->checkStmt($stmt) && $stmt->bind_param("i", $account_id) && $stmt->execute() && $result = $stmt->get_result() ) - return $this->setCache(__FUNCTION__ . $account_id, $result->fetch_object()->hashrate); + return $this->memcache->setCache(__FUNCTION__ . $account_id, $result->fetch_object()->hashrate); // Catchall $this->debug->append("Failed to fetch hashrate: " . $this->mysqli->error); return false; @@ -233,7 +220,7 @@ class Statistics { AND s.time > DATE_SUB(now(), INTERVAL 10 MINUTE) AND u.id = ?"); if ($this->checkStmt($stmt) && $stmt->bind_param("i", $account_id) && $stmt->execute() && $result = $stmt->get_result() ) - return $this->setCache(__FUNCTION__ . $worker_id, $result->fetch_object()->hashrate); + return $this->memcache->setCache(__FUNCTION__ . $worker_id, $result->fetch_object()->hashrate); // Catchall $this->debug->append("Failed to fetch hashrate: " . $this->mysqli->error); return false; @@ -259,7 +246,7 @@ class Statistics { ORDER BY shares DESC LIMIT ?"); if ($this->checkStmt($stmt) && $stmt->bind_param("i", $limit) && $stmt->execute() && $result = $stmt->get_result()) - return $this->setCache(__FUNCTION__ . $type . $limit, $result->fetch_all(MYSQLI_ASSOC)); + return $this->memcache->setCache(__FUNCTION__ . $type . $limit, $result->fetch_all(MYSQLI_ASSOC)); $this->debug->append("Fetching shares failed: "); return false; break; @@ -274,7 +261,7 @@ class Statistics { GROUP BY account ORDER BY hashrate DESC LIMIT ?"); if ($this->checkStmt($stmt) && $stmt->bind_param("i", $limit) && $stmt->execute() && $result = $stmt->get_result()) - return $this->setCache(__FUNCTION__ . $type . $limit, $result->fetch_all(MYSQLI_ASSOC)); + return $this->memcache->setCache(__FUNCTION__ . $type . $limit, $result->fetch_all(MYSQLI_ASSOC)); $this->debug->append("Fetching shares failed: "); return false; break; @@ -309,7 +296,7 @@ class Statistics { AND a.id = ? GROUP BY HOUR(time)"); if ($this->checkStmt($stmt) && $stmt->bind_param("ii", $account_id, $account_id) && $stmt->execute() && $result = $stmt->get_result()) - return $this->setCache(__FUNCTION__ . $account_id, $result->fetch_all(MYSQLI_ASSOC), 3600); + return $this->memcache->setCache(__FUNCTION__ . $account_id, $result->fetch_all(MYSQLI_ASSOC), 3600); // Catchall $this->debug->append("Failed to fetch hourly hashrate: " . $this->mysqli->error); return false; diff --git a/public/include/classes/statscache.class.php b/public/include/classes/statscache.class.php index b6884d61..e84386da 100644 --- a/public/include/classes/statscache.class.php +++ b/public/include/classes/statscache.class.php @@ -43,6 +43,19 @@ class StatsCache extends Memcached { $this->debug->append("Key not found", 3); } } + /** + * Another wrapper, we want to store data in memcache and return the actual data + * for further processing + * @param key string Our memcache key + * @param data mixed Our data to store in Memcache + * @param expiration time Our expiration time, see Memcached documentation + * @return data mixed Return our stored data unchanged + **/ + public function setCache($key, $data, $expiration=NULL) { + if ($this->config['memcache']['enabled']) $this->set($key, $data, $expiration); + return $data; + } + } $memcache = new StatsCache($config, $debug); From 1e54a1a2d6695963c3be9b06d5a48655526fe5a0 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Sun, 26 May 2013 19:33:19 +0200 Subject: [PATCH 27/59] initial commit of a working API page --- public/include/classes/user.class.php | 13 ++++++ public/include/pages/api.inc.php | 57 +++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 public/include/pages/api.inc.php diff --git a/public/include/classes/user.class.php b/public/include/classes/user.class.php index d54b2da5..a8067a17 100644 --- a/public/include/classes/user.class.php +++ b/public/include/classes/user.class.php @@ -225,6 +225,19 @@ class User { return false; } + /** + * Check API key for authentication + * @param key string API key hash + * @return bool + **/ + public function checkApiKey($key) { + $this->debug->append("STA " . __METHOD__, 4); + $stmt = $this->mysqli->prepare("SELECT api_key FROM $this->table WHERE api_key = ?"); + if ($this->checkStmt($stmt) && $stmt->bind_param("s", $key) && $stmt->execute() && $stmt->bind_result($api_key) && $stmt->fetch()) + return $key === $api_key; + return false; + } + private function checkUserPassword($username, $password) { $this->debug->append("STA " . __METHOD__, 4); $user = array(); diff --git a/public/include/pages/api.inc.php b/public/include/pages/api.inc.php new file mode 100644 index 00000000..23332c3a --- /dev/null +++ b/public/include/pages/api.inc.php @@ -0,0 +1,57 @@ +checkApiKey($_REQUEST['api_key'])) { + header("HTTP/1.1 401 Unauthorized"); + die(); +} + +// Fetch data from litecoind +if ($bitcoin->can_connect() === true){ + if (!$dDifficulty = $memcache->get('dDifficulty')) { + $dDifficulty = $bitcoin->query('getdifficulty'); + $memcache->set('dDifficulty', $dDifficulty); + } + if (!$iBlock = $memcache->get('iBlock')) { + $iBlock = $bitcoin->query('getblockcount'); + $memcache->set('iBlock', $iBlock); + } +} else { + $iDifficulty = 1; + $iBlock = 0; + $_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to pushpool service: ' . $bitcoin->can_connect(), 'TYPE' => 'errormsg'); +} + +// Grab the last 10 blocks found +$iLimit = 10; +$aBlocksFoundData = $statistics->getBlocksFound($iLimit); +$aBlockData = $aBlocksFoundData[0]; + +// Estimated time to find the next block +$iCurrentPoolHashrate = $statistics->getCurrentHashrate(); +// Time in seconds, not hours, using modifier in smarty to translate +$iEstTime = $dDifficulty * pow(2,32) / ($iCurrentPoolHashrate * 1000); + +// Time since last block +$now = new DateTime( "now" ); +if (!empty($aBlockData)) { + $dTimeSinceLast = ($now->getTimestamp() - $aBlockData['time']); +} else { + $dTimeSinceLast = 0; +} + +$aData = array( + 'est_time' => $iEstTime, + 'time_last' => $dTimeSinceLast, + 'blocks_found' => $aBlocksFoundData, + 'cur_block' => $iBlock, + 'last_block' => $aBlockData['height'], + 'difficulty' => $iDifficulty, +); + +$supress_master = 1; +echo json_encode($aData); +?> From d4331ed8dcfc5d8f75bc8932029f7e12e9a3258f Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Tue, 28 May 2013 10:50:16 +0200 Subject: [PATCH 28/59] Adding more actions for API page * getblockcount * getblocksfound (with limit support) * getcurrentworkers * getdifficulty * getestimatedtime * getpoolhashrate * getpoolsharerate * gettimesincelastblock --- public/include/autoloader.inc.php | 1 + public/include/classes/bitcoin.class.php | 3 -- .../include/classes/bitcoinwrapper.class.php | 37 +++++++++++++++++++ .../include/pages/api/getblockcount.inc.php | 24 ++++++++++++ .../include/pages/api/getblocksfound.inc.php | 20 ++++++++++ .../pages/api/getcurrentworkers.inc.php | 15 ++++++++ .../include/pages/api/getdifficulty.inc.php | 25 +++++++++++++ .../pages/api/getestimatedtime.inc.php | 18 +++++++++ .../include/pages/api/getpoolhashrate.inc.php | 15 ++++++++ .../pages/api/getpoolsharerate.inc.php | 15 ++++++++ .../pages/api/gettimesincelastblock.inc.php | 26 +++++++++++++ 11 files changed, 196 insertions(+), 3 deletions(-) create mode 100644 public/include/classes/bitcoinwrapper.class.php create mode 100644 public/include/pages/api/getblockcount.inc.php create mode 100644 public/include/pages/api/getblocksfound.inc.php create mode 100644 public/include/pages/api/getcurrentworkers.inc.php create mode 100644 public/include/pages/api/getdifficulty.inc.php create mode 100644 public/include/pages/api/getestimatedtime.inc.php create mode 100644 public/include/pages/api/getpoolhashrate.inc.php create mode 100644 public/include/pages/api/getpoolsharerate.inc.php create mode 100644 public/include/pages/api/gettimesincelastblock.inc.php diff --git a/public/include/autoloader.inc.php b/public/include/autoloader.inc.php index 0da83b59..0671a34e 100644 --- a/public/include/autoloader.inc.php +++ b/public/include/autoloader.inc.php @@ -3,6 +3,7 @@ require_once(CLASS_DIR . '/debug.class.php'); require_once(CLASS_DIR . '/bitcoin.class.php'); require_once(CLASS_DIR . '/statscache.class.php'); +require_once(CLASS_DIR . '/bitcoinwrapper.class.php'); require_once(INCLUDE_DIR . '/database.inc.php'); require_once(INCLUDE_DIR . '/smarty.inc.php'); // Load classes that need the above as dependencies diff --git a/public/include/classes/bitcoin.class.php b/public/include/classes/bitcoin.class.php index 9a901be6..fa88d415 100644 --- a/public/include/classes/bitcoin.class.php +++ b/public/include/classes/bitcoin.class.php @@ -898,6 +898,3 @@ class BitcoinClient extends jsonrpc_client { return $this->query("getaddressesbyaccount", $account); } } - -// Auto-load this class -$bitcoin = new BitcoinClient($config['wallet']['type'], $config['wallet']['username'], $config['wallet']['password'], $config['wallet']['host']); diff --git a/public/include/classes/bitcoinwrapper.class.php b/public/include/classes/bitcoinwrapper.class.php new file mode 100644 index 00000000..7231c252 --- /dev/null +++ b/public/include/classes/bitcoinwrapper.class.php @@ -0,0 +1,37 @@ +type = $type; + $this->username = $username; + $this->password = $password; + $this->host = $host; + $this->memcache = $memcache; + return parent::__construct($this->type, $this->username, $this->password, $this->host); + } + /** + * Wrap variouns methods to add caching + **/ + public function getblockcount() { + if ($data = $this->memcache->get(__FUNCTION__)) return $data; + return $this->memcache->setCache(__FUNCTION__, parent::getblockcount()); + } + public function getdifficulty() { + if ($data = $this->memcache->get(__FUNCTION__)) return $data; + return $this->memcache->setCache(__FUNCTION__, parent::getdifficulty()); + } + public function getestimatedtime($iCurrentPoolHashrate) { + if ($iCurrentPoolHashrate == 0) return 0; + if ($data = $this->memcache->get(__FUNCTION__)) return $data; + $dDifficulty = parent::getdifficulty(); + return $this->memcache->setCache(__FUNCTION__, $dDifficulty * pow(2,32) / $iCurrentPoolHashrate); + } +} + +// Load this wrapper +$bitcoin = new BitcoinWrapper($config['wallet']['type'], $config['wallet']['username'], $config['wallet']['password'], $config['wallet']['host'], $memcache); diff --git a/public/include/pages/api/getblockcount.inc.php b/public/include/pages/api/getblockcount.inc.php new file mode 100644 index 00000000..f3a6779f --- /dev/null +++ b/public/include/pages/api/getblockcount.inc.php @@ -0,0 +1,24 @@ +checkApiKey($_REQUEST['api_key']); + +if ($bitcoin->can_connect() === true){ + if (!$iBlock = $memcache->get('iBlock')) { + $iBlock = $bitcoin->query('getblockcount'); + $memcache->set('iBlock', $iBlock); + } +} else { + $iBlock = 0; +} + +// Output JSON format +echo json_encode(array('getblockcount' => $iBlock)); + +// Supress master template +$supress_master = 1; +?> diff --git a/public/include/pages/api/getblocksfound.inc.php b/public/include/pages/api/getblocksfound.inc.php new file mode 100644 index 00000000..67cd6ab7 --- /dev/null +++ b/public/include/pages/api/getblocksfound.inc.php @@ -0,0 +1,20 @@ +checkApiKey($_REQUEST['api_key']); + +// Set a sane limit, overwrite with URL parameter +$iLimit = 10; +if (@$_REQUEST['limit']) + $iLimit = $_REQUEST['limit']; + +// Output JSON format +echo json_encode(array('getblocksfound' => $statistics->getBlocksFound($iLimit))); + +// Supress master template +$supress_master = 1; +?> diff --git a/public/include/pages/api/getcurrentworkers.inc.php b/public/include/pages/api/getcurrentworkers.inc.php new file mode 100644 index 00000000..2f0a3241 --- /dev/null +++ b/public/include/pages/api/getcurrentworkers.inc.php @@ -0,0 +1,15 @@ +checkApiKey($_REQUEST['api_key']); + +// Output JSON format +echo json_encode(array('getcurrentworkers' => $worker->getCountAllActiveWorkers())); + +// Supress master template +$supress_master = 1; +?> diff --git a/public/include/pages/api/getdifficulty.inc.php b/public/include/pages/api/getdifficulty.inc.php new file mode 100644 index 00000000..60c0f111 --- /dev/null +++ b/public/include/pages/api/getdifficulty.inc.php @@ -0,0 +1,25 @@ +checkApiKey($_REQUEST['api_key']); + +// Fetch data from litecoind +if ($bitcoin->can_connect() === true){ + if (!$dDifficulty = $memcache->get('dDifficulty')) { + $memcache->set('dDifficulty', $dDifficulty); + $dDifficulty = $bitcoin->query('getdifficulty'); + } +} else { + $iDifficulty = 1; +} + +// Output JSON format +echo json_encode(array('getdifficulty' => $dDifficulty)); + +// Supress master template +$supress_master = 1; +?> diff --git a/public/include/pages/api/getestimatedtime.inc.php b/public/include/pages/api/getestimatedtime.inc.php new file mode 100644 index 00000000..6bc76881 --- /dev/null +++ b/public/include/pages/api/getestimatedtime.inc.php @@ -0,0 +1,18 @@ +checkApiKey($_REQUEST['api_key']); + +// Estimated time to find the next block +$iCurrentPoolHashrate = $statistics->getCurrentHashrate() * 1000; + +// Output JSON format +echo json_encode(array('getestimatedtime' => $bitcoin->getestimatedtime($iCurrentPoolHashrate))); + +// Supress master template +$supress_master = 1; +?> diff --git a/public/include/pages/api/getpoolhashrate.inc.php b/public/include/pages/api/getpoolhashrate.inc.php new file mode 100644 index 00000000..996d1ce2 --- /dev/null +++ b/public/include/pages/api/getpoolhashrate.inc.php @@ -0,0 +1,15 @@ +checkApiKey($_REQUEST['api_key']); + +// Output JSON format +echo json_encode(array('getpoolhashrate' => $statistics->getCurrentHashrate())); + +// Supress master template +$supress_master = 1; +?> diff --git a/public/include/pages/api/getpoolsharerate.inc.php b/public/include/pages/api/getpoolsharerate.inc.php new file mode 100644 index 00000000..980c0ba3 --- /dev/null +++ b/public/include/pages/api/getpoolsharerate.inc.php @@ -0,0 +1,15 @@ +checkApiKey($_REQUEST['api_key']); + +// Output JSON format +echo json_encode(array('getpoolsharerate' => $statistics->getCurrentShareRate())); + +// Supress master template +$supress_master = 1; +?> diff --git a/public/include/pages/api/gettimesincelastblock.inc.php b/public/include/pages/api/gettimesincelastblock.inc.php new file mode 100644 index 00000000..f80c55ce --- /dev/null +++ b/public/include/pages/api/gettimesincelastblock.inc.php @@ -0,0 +1,26 @@ +checkApiKey($_REQUEST['api_key']); + +// Fetch our last block found +$aBlocksFoundData = $statistics->getBlocksFound(1); + +// Time since last block +$now = new DateTime( "now" ); +if (!empty($aBlocksFoundData)) { + $dTimeSinceLast = ($now->getTimestamp() - $aBlocksFoundData[0]['time']); +} else { + $dTimeSinceLast = 0; +} + +// Output JSON format +echo json_encode(array('gettimesincelastblock' => $dTimeSinceLast)); + +// Supress master template +$supress_master = 1; +?> From f4a423556247b48951938cd679d0ba4a1f90fee5 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Tue, 28 May 2013 10:55:29 +0200 Subject: [PATCH 29/59] remove generic api page --- public/include/pages/api.inc.php | 53 +++----------------------------- 1 file changed, 4 insertions(+), 49 deletions(-) diff --git a/public/include/pages/api.inc.php b/public/include/pages/api.inc.php index 23332c3a..3b4d3858 100644 --- a/public/include/pages/api.inc.php +++ b/public/include/pages/api.inc.php @@ -4,54 +4,9 @@ if (!defined('SECURITY')) die('Hacking attempt'); -if (!$user->checkApiKey($_REQUEST['api_key'])) { - header("HTTP/1.1 401 Unauthorized"); - die(); -} +// Check for valid API key +$user->checkApiKey($_REQUEST['api_key']); -// Fetch data from litecoind -if ($bitcoin->can_connect() === true){ - if (!$dDifficulty = $memcache->get('dDifficulty')) { - $dDifficulty = $bitcoin->query('getdifficulty'); - $memcache->set('dDifficulty', $dDifficulty); - } - if (!$iBlock = $memcache->get('iBlock')) { - $iBlock = $bitcoin->query('getblockcount'); - $memcache->set('iBlock', $iBlock); - } -} else { - $iDifficulty = 1; - $iBlock = 0; - $_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to pushpool service: ' . $bitcoin->can_connect(), 'TYPE' => 'errormsg'); -} - -// Grab the last 10 blocks found -$iLimit = 10; -$aBlocksFoundData = $statistics->getBlocksFound($iLimit); -$aBlockData = $aBlocksFoundData[0]; - -// Estimated time to find the next block -$iCurrentPoolHashrate = $statistics->getCurrentHashrate(); -// Time in seconds, not hours, using modifier in smarty to translate -$iEstTime = $dDifficulty * pow(2,32) / ($iCurrentPoolHashrate * 1000); - -// Time since last block -$now = new DateTime( "now" ); -if (!empty($aBlockData)) { - $dTimeSinceLast = ($now->getTimestamp() - $aBlockData['time']); -} else { - $dTimeSinceLast = 0; -} - -$aData = array( - 'est_time' => $iEstTime, - 'time_last' => $dTimeSinceLast, - 'blocks_found' => $aBlocksFoundData, - 'cur_block' => $iBlock, - 'last_block' => $aBlockData['height'], - 'difficulty' => $iDifficulty, -); - -$supress_master = 1; -echo json_encode($aData); +header('HTTP/1.1 400 Bad Request'); +die('400 Bad Request'); ?> From 510ce893383c198daeabd2496e811872201ea0ce Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Tue, 28 May 2013 11:50:37 +0200 Subject: [PATCH 30/59] Use new BitcoinWrapper class, remove memcache calls --- public/include/classes/bitcoinwrapper.class.php | 10 +++++++--- public/include/pages/statistics/pool.inc.php | 12 +++--------- public/include/pages/statistics/user.inc.php | 10 ++-------- 3 files changed, 12 insertions(+), 20 deletions(-) diff --git a/public/include/classes/bitcoinwrapper.class.php b/public/include/classes/bitcoinwrapper.class.php index 7231c252..9f2ad861 100644 --- a/public/include/classes/bitcoinwrapper.class.php +++ b/public/include/classes/bitcoinwrapper.class.php @@ -5,12 +5,13 @@ if (!defined('SECURITY')) die('Hacking attempt'); class BitcoinWrapper extends BitcoinClient { - var $type, $username, $password, $host, $memcache; - public function __construct($type, $username, $password, $host, $memcache) { + public function __construct($type, $username, $password, $host, $debug, $memcache) { $this->type = $type; $this->username = $username; $this->password = $password; $this->host = $host; + // $this->debug is already used + $this->oDebug = $debug; $this->memcache = $memcache; return parent::__construct($this->type, $this->username, $this->password, $this->host); } @@ -18,14 +19,17 @@ class BitcoinWrapper extends BitcoinClient { * Wrap variouns methods to add caching **/ public function getblockcount() { + $this->oDebug->append("STA " . __METHOD__, 4); if ($data = $this->memcache->get(__FUNCTION__)) return $data; return $this->memcache->setCache(__FUNCTION__, parent::getblockcount()); } public function getdifficulty() { + $this->oDebug->append("STA " . __METHOD__, 4); if ($data = $this->memcache->get(__FUNCTION__)) return $data; return $this->memcache->setCache(__FUNCTION__, parent::getdifficulty()); } public function getestimatedtime($iCurrentPoolHashrate) { + $this->oDebug->append("STA " . __METHOD__, 4); if ($iCurrentPoolHashrate == 0) return 0; if ($data = $this->memcache->get(__FUNCTION__)) return $data; $dDifficulty = parent::getdifficulty(); @@ -34,4 +38,4 @@ class BitcoinWrapper extends BitcoinClient { } // Load this wrapper -$bitcoin = new BitcoinWrapper($config['wallet']['type'], $config['wallet']['username'], $config['wallet']['password'], $config['wallet']['host'], $memcache); +$bitcoin = new BitcoinWrapper($config['wallet']['type'], $config['wallet']['username'], $config['wallet']['password'], $config['wallet']['host'], $debug, $memcache); diff --git a/public/include/pages/statistics/pool.inc.php b/public/include/pages/statistics/pool.inc.php index 238b00b5..a256d2cf 100644 --- a/public/include/pages/statistics/pool.inc.php +++ b/public/include/pages/statistics/pool.inc.php @@ -6,14 +6,8 @@ if (!defined('SECURITY')) // Fetch data from litecoind if ($bitcoin->can_connect() === true){ - if (!$dDifficulty = $memcache->get('dDifficulty')) { - $dDifficulty = $bitcoin->query('getdifficulty'); - $memcache->set('dDifficulty', $dDifficulty); - } - if (!$iBlock = $memcache->get('iBlock')) { - $iBlock = $bitcoin->query('getblockcount'); - $memcache->set('iBlock', $iBlock); - } + $dDifficulty = $bitcoin->getdifficulty(); + $iBlock = $bitcoin->getblockcount(); } else { $iDifficulty = 1; $iBlock = 0; @@ -24,7 +18,7 @@ if ($bitcoin->can_connect() === true){ $aContributorsShares = $statistics->getTopContributors('shares', 15); // Top hash contributors - $aContributorsHashes = $statistics->getTopContributors('hashes', 15); +$aContributorsHashes = $statistics->getTopContributors('hashes', 15); // Grab the last 10 blocks found $iLimit = 10; diff --git a/public/include/pages/statistics/user.inc.php b/public/include/pages/statistics/user.inc.php index 41316beb..3a344c70 100644 --- a/public/include/pages/statistics/user.inc.php +++ b/public/include/pages/statistics/user.inc.php @@ -6,14 +6,8 @@ if (!defined('SECURITY')) // Fetch data from litecoind if ($bitcoin->can_connect() === true){ - if (!$dDifficulty = $memcache->get('dDifficulty')) { - $dDifficulty = $bitcoin->query('getdifficulty'); - $memcache->set('dDifficulty', $dDifficulty); - } - if (!$iBlock = $memcache->get('iBlock')) { - $iBlock = $bitcoin->query('getblockcount'); - $memcache->set('iBlock', $iBlock); - } + $dDifficulty = $bitcoin->getdifficulty(); + $iBlock = $bitcoin->getblockcount(); } else { $iDifficulty = 1; $iBlock = 0; From a2eb5cc7b3085ccfb34f68fe8ecf90eff5501a6c Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Tue, 28 May 2013 14:33:03 +0200 Subject: [PATCH 31/59] Register first user as admin This commit fixes #50 and is needed for the admin panel --- public/include/classes/user.class.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/public/include/classes/user.class.php b/public/include/classes/user.class.php index a8067a17..b6c03818 100644 --- a/public/include/classes/user.class.php +++ b/public/include/classes/user.class.php @@ -322,15 +322,23 @@ class User { return false; } $apikey = hash("sha256",$username.$salt); - $stmt = $this->mysqli->prepare(" - INSERT INTO $this->table (username, pass, email, pin, api_key) - VALUES (?, ?, ?, ?, ?) + if ($this->mysqli->query("SELECT id FROM $this->table LIMIT 1")->num_rows > 0) { + $stmt = $this->mysqli->prepare(" + INSERT INTO $this->table (username, pass, email, pin, api_key) + VALUES (?, ?, ?, ?, ?) "); + } else { + $stmt = $this->mysqli->prepare(" + INSERT INTO $this->table (username, pass, email, pin, api_key, admin) + VALUES (?, ?, ?, ?, ?, 1) + "); + } if ($this->checkStmt($stmt)) { $stmt->bind_param('sssss', $username, hash("sha256", $password1.$this->salt), $email1, hash("sha256", $pin.$this->salt), $apikey); if (!$stmt->execute()) { $this->setErrorMessage( 'Unable to register' ); if ($stmt->sqlstate == '23000') $this->setErrorMessage( 'Username already exists' ); + echo $this->mysqli->error; return false; } $stmt->close(); From 422e22dc3f2970f702d0022d3990ac000f54fea6 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Tue, 28 May 2013 16:20:28 +0300 Subject: [PATCH 32/59] Update README.md Added Freenode IRC Chat contact information --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3a0ab83a..30adcf1f 100644 --- a/README.md +++ b/README.md @@ -75,11 +75,15 @@ You can contribute to this project in different ways: * Suggest feature enhancements also via [Issues][1] * Fork the project, create a branch and file a pull request to improve the code itself +Contact +======= + +You can find me on Freenode.net, #mmcfe-ng. License and Author ================== -Copyright 2012, Sebastian Grewe +Copyright 2012, Sebastian Grewe Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From c258a4860a716f3d1907c8ea72a6d2a487d7ceae Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Tue, 28 May 2013 15:24:16 +0200 Subject: [PATCH 33/59] updated support information --- public/templates/mmcFE/support/default.tpl | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/public/templates/mmcFE/support/default.tpl b/public/templates/mmcFE/support/default.tpl index ecd92295..4a3e6eb4 100644 --- a/public/templates/mmcFE/support/default.tpl +++ b/public/templates/mmcFE/support/default.tpl @@ -6,10 +6,8 @@
        -

        - -

        As mentioned in various places this site is experimental and does not come with any support nor warranty.

        -

        Nevertheless, you can find contact information on my main website: http://www.grewe.ca

        +

        This product comes 'as-is' without any warranty. Please check the Apache License, Version 2.0, for details.

        +

        If you would like to get in touch you can find me on Freenode IRC @ #mmcfe-ng.

        From 2548d4b03d37ae33987a4256edd4ecd3d88d4c33 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Tue, 28 May 2013 15:35:28 +0200 Subject: [PATCH 34/59] add API key back to account details Fixes #73. --- public/include/classes/user.class.php | 2 +- public/include/pages/account/edit.inc.php | 1 + public/templates/mmcFE/account/edit/default.tpl | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/public/include/classes/user.class.php b/public/include/classes/user.class.php index b6c03818..abae79d4 100644 --- a/public/include/classes/user.class.php +++ b/public/include/classes/user.class.php @@ -281,7 +281,7 @@ class User { $this->debug->append("Fetching user information for user id: $userID"); $stmt = $this->mysqli->prepare(" SELECT - id, username, pin, pass, admin, + id, username, pin, api_key, admin, IFNULL(donate_percent, '0') as donate_percent, coin_address, ap_threshold FROM $this->table WHERE id = ? LIMIT 0,1"); diff --git a/public/include/pages/account/edit.inc.php b/public/include/pages/account/edit.inc.php index c8c9f6fc..884f6b6b 100644 --- a/public/include/pages/account/edit.inc.php +++ b/public/include/pages/account/edit.inc.php @@ -61,6 +61,7 @@ if ( ! $user->checkPin($_SESSION['USERDATA']['id'], $_POST['authPin']) && $_POST break; } } + // Tempalte specifics $smarty->assign("CONTENT", "default.tpl"); ?> diff --git a/public/templates/mmcFE/account/edit/default.tpl b/public/templates/mmcFE/account/edit/default.tpl index c57fe6f4..9d885b16 100644 --- a/public/templates/mmcFE/account/edit/default.tpl +++ b/public/templates/mmcFE/account/edit/default.tpl @@ -6,6 +6,7 @@ + From ddc1446a2b0d71608064033589e663cc022f6a0b Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Tue, 28 May 2013 16:01:53 +0200 Subject: [PATCH 35/59] removing API reference since it is split into many methods now --- public/templates/mmcFE/statistics/pool/authenticated.tpl | 3 --- 1 file changed, 3 deletions(-) diff --git a/public/templates/mmcFE/statistics/pool/authenticated.tpl b/public/templates/mmcFE/statistics/pool/authenticated.tpl index 9a5a593c..9113ebae 100644 --- a/public/templates/mmcFE/statistics/pool/authenticated.tpl +++ b/public/templates/mmcFE/statistics/pool/authenticated.tpl @@ -37,9 +37,6 @@
        Username: {$GLOBAL.userdata.username}
        User Id: {$GLOBAL.userdata.id}
        API Key: {$GLOBAL.userdata.api_key}
        Payment Address:
        Donation %: [donation amount in percent (example: 0.5)]
        Automatic Payout Threshold: [1-250 LTC. Set to '0' for no auto payout]
        -
          -
        • Server stats are also available in JSON format HERE
        • -
        {include file="global/block_footer.tpl"} From 44851cf82b0ab8ba269cd957720ee72b0f43e86d Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Wed, 29 May 2013 07:01:39 +0200 Subject: [PATCH 36/59] Update README.md Added existing and planned future payout systems as features --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 30adcf1f..f14cd425 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,10 @@ Features The following feature have been implemented so far: +* Reward Systems + * Propotional + * (Planned) PPS + * (Planned) PPLNS * Use of memcache for statistics instead of a cronjob * Web User accounts * Worker accounts From cdfb0740762f989bc7a27bae1397573d22e032bf Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Wed, 29 May 2013 10:56:08 +0200 Subject: [PATCH 37/59] Re-adding LTC/usd to website ministats header * Use tickerupdate.php cron to update setting value * Added new configuration variables for ticket updates * Added some missing configuration vars for some URLs --- cronjobs/tickerupdate.php | 36 ++++++++++++++++ public/include/autoloader.inc.php | 2 +- .../{settings.class.php => setting.class.php} | 19 +++++++-- public/include/classes/tools.class.php | 41 +++++++++++++++++++ public/include/config/global.inc.dist.php | 6 +++ public/include/smarty_globals.inc.php | 5 ++- public/templates/mmcFE/global/header.tpl | 1 + 7 files changed, 104 insertions(+), 6 deletions(-) create mode 100755 cronjobs/tickerupdate.php rename public/include/classes/{settings.class.php => setting.class.php} (57%) create mode 100644 public/include/classes/tools.class.php diff --git a/cronjobs/tickerupdate.php b/cronjobs/tickerupdate.php new file mode 100755 index 00000000..b806654d --- /dev/null +++ b/cronjobs/tickerupdate.php @@ -0,0 +1,36 @@ +#!/usr/bin/php +getApi($config['price']['url'], $config['price']['target'])) { + if (!$setting->setValue('price', $aData['ticker']['avg'])) + verbose("ERR Table update failed"); +} else { + verbose("ERR Failed download JSON data from " . $config['price']['url'].$config['price']['target'] . "\n"); +} + +?> diff --git a/public/include/autoloader.inc.php b/public/include/autoloader.inc.php index 0671a34e..ea16564e 100644 --- a/public/include/autoloader.inc.php +++ b/public/include/autoloader.inc.php @@ -13,4 +13,4 @@ require_once(CLASS_DIR . '/share.class.php'); require_once(CLASS_DIR . '/worker.class.php'); require_once(CLASS_DIR . '/statistics.class.php'); require_once(CLASS_DIR . '/transaction.class.php'); -require_once(CLASS_DIR . '/settings.class.php'); +require_once(CLASS_DIR . '/setting.class.php'); diff --git a/public/include/classes/settings.class.php b/public/include/classes/setting.class.php similarity index 57% rename from public/include/classes/settings.class.php rename to public/include/classes/setting.class.php index 3c8f9dc0..44ef8315 100644 --- a/public/include/classes/settings.class.php +++ b/public/include/classes/setting.class.php @@ -4,7 +4,7 @@ if (!defined('SECURITY')) die('Hacking attempt'); -class Settings { +class Setting { public function __construct($debug, $mysqli, $salt) { $this->debug = $debug; $this->mysqli = $mysqli; @@ -13,7 +13,7 @@ class Settings { } public function getValue($name) { - $query = $this->mysqli->prepare("SELECT value FROM $this->table WHERE setting=? LIMIT 1"); + $query = $this->mysqli->prepare("SELECT value FROM $this->table WHERE name=? LIMIT 1"); if ($query) { $query->bind_param('s', $name); $query->execute(); @@ -26,6 +26,19 @@ class Settings { } return $value; } + + public function setValue($name, $value) { + $stmt = $this->mysqli->prepare(" + INSERT INTO $this->table (name, value) + VALUES (?, ?) + ON DUPLICATE KEY UPDATE value = ? + "); + if ($stmt && $stmt->bind_param('sss', $name, $value, $value) && $stmt->execute()) + return true; + $this->debug->append("Failed to set $name to $value"); + echo $this->mysqli->error; + return false; + } } -$settings = new Settings($debug, $mysqli, SALT); +$setting = new Setting($debug, $mysqli, SALT); diff --git a/public/include/classes/tools.class.php b/public/include/classes/tools.class.php new file mode 100644 index 00000000..530316e6 --- /dev/null +++ b/public/include/classes/tools.class.php @@ -0,0 +1,41 @@ +debug = $debug; + } + + /** + * Fetch JSON data from an API + * @param url string API URL + * @param target string API method + * @param auth array Optional authentication data to be sent with + * @return dec array JSON decoded PHP array + **/ + public function getApi($url, $target, $auth=NULL) { + static $ch = null; + static $ch = null; + if (is_null($ch)) { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; BTCE PHP client; '.php_uname('s').'; PHP/'.phpversion().')'); + } + curl_setopt($ch, CURLOPT_URL, $url . $target); + // curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); + + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); + + // run the query + $res = curl_exec($ch); + if ($res === false) throw new Exception('Could not get reply: '.curl_error($ch)); + $dec = json_decode($res, true); + if (!$dec) throw new Exception('Invalid data received, please make sure connection is working and requested API exists'); + return $dec; + } +} + +$tools = new Tools($debug); diff --git a/public/include/config/global.inc.dist.php b/public/include/config/global.inc.dist.php index f684c2bb..f4b8b245 100644 --- a/public/include/config/global.inc.dist.php +++ b/public/include/config/global.inc.dist.php @@ -21,11 +21,17 @@ define('DEBUG', 0); define('SALT', 'PLEASEMAKEMESOMETHINGRANDOM'); $config = array( + 'price' => array( + 'url' => 'https://btc-e.com/api/2', + 'target' => '/ltc_usd/ticker' + ), 'website' => array( 'name' => 'The Pool', 'slogan' => 'Resistance is futile', 'email' => 'test@example.com', // Mail address used for notifications ), + 'blockexplorer' => 'http://explorer.litecoin.net/search?q=', // URL for block searches, prefixed to each block number + 'chaininfo' => 'http://allchains.info', // Link to Allchains for Difficulty information 'fees' => 0, 'difficulty' => '31', // Target difficulty for this pool as set in pushpoold json 'reward' => '50', // Reward for finding blocks, fixed value but changes someday diff --git a/public/include/smarty_globals.inc.php b/public/include/smarty_globals.inc.php index c383dfb0..8c7891e6 100644 --- a/public/include/smarty_globals.inc.php +++ b/public/include/smarty_globals.inc.php @@ -23,8 +23,9 @@ $aGlobal = array( 'fees' => $config['fees'], 'confirmations' => $config['confirmations'], 'reward' => $config['reward'], - 'blockexplorer' => 'http://explorer.litecoin.net/search?q=', - 'chaininfo' => 'http://allchains.info' + 'price' => $setting->getValue('price'), + 'blockexplorer' => $config['blockexplorer'], + 'chaininfo' => $config['chaininfo'] ); // We don't want these session infos cached diff --git a/public/templates/mmcFE/global/header.tpl b/public/templates/mmcFE/global/header.tpl index 1f08a366..89948e71 100644 --- a/public/templates/mmcFE/global/header.tpl +++ b/public/templates/mmcFE/global/header.tpl @@ -4,6 +4,7 @@
        + From 2376c82c7963a50727e18339434f47c4c9f45679 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Wed, 29 May 2013 10:59:10 +0200 Subject: [PATCH 38/59] default to n/a on template if no value is stored yet --- public/templates/mmcFE/global/header.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/templates/mmcFE/global/header.tpl b/public/templates/mmcFE/global/header.tpl index 89948e71..19f1a788 100644 --- a/public/templates/mmcFE/global/header.tpl +++ b/public/templates/mmcFE/global/header.tpl @@ -4,7 +4,7 @@
      • LTC/usd: {$GLOBAL.price}    
      • Pool Hashrate: {$GLOBAL.hashrate / 1000} MH/s    
      • Pool Sharerate: {$GLOBAL.sharerate} Shares/s    
      • Pool Workers: {$GLOBAL.workers}    
      • - + From 6b5245b489a0844011a16f5e2323016e9c6abc8d Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Wed, 29 May 2013 11:00:48 +0200 Subject: [PATCH 39/59] new DB strucutre to change setting table to column name --- sql/mmcfe_ng_structure.sql | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/sql/mmcfe_ng_structure.sql b/sql/mmcfe_ng_structure.sql index 6b961382..233e1308 100644 --- a/sql/mmcfe_ng_structure.sql +++ b/sql/mmcfe_ng_structure.sql @@ -3,7 +3,7 @@ -- http://www.phpmyadmin.net -- -- Host: localhost --- Generation Time: May 27, 2013 at 02:39 PM +-- Generation Time: May 29, 2013 at 11:00 AM -- Server version: 5.5.31-0ubuntu0.13.04.1 -- PHP Version: 5.4.9-4ubuntu2 @@ -64,7 +64,7 @@ CREATE TABLE IF NOT EXISTS `blocks` ( PRIMARY KEY (`id`), UNIQUE KEY `height` (`height`,`blockhash`), KEY `time` (`time`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Discovered blocks persisted from Litecoin Service'; +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Discovered blocks persisted from Litecoin Service'; -- -------------------------------------------------------- @@ -73,9 +73,10 @@ CREATE TABLE IF NOT EXISTS `blocks` ( -- CREATE TABLE IF NOT EXISTS `settings` ( - `setting` varchar(255) NOT NULL, + `name` varchar(255) NOT NULL, `value` varchar(255) DEFAULT NULL, - PRIMARY KEY (`setting`) + PRIMARY KEY (`name`), + UNIQUE KEY `setting` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- -------------------------------------------------------- @@ -98,7 +99,7 @@ CREATE TABLE IF NOT EXISTS `shares` ( KEY `upstream_result` (`upstream_result`), KEY `our_result` (`our_result`), KEY `username` (`username`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- -------------------------------------------------------- @@ -117,7 +118,7 @@ CREATE TABLE IF NOT EXISTS `shares_archive` ( PRIMARY KEY (`id`), UNIQUE KEY `share_id` (`share_id`), KEY `time` (`time`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Archive shares for potential later debugging purposes'; +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Archive shares for potential later debugging purposes'; -- -------------------------------------------------------- @@ -134,7 +135,7 @@ CREATE TABLE IF NOT EXISTS `statistics_shares` ( PRIMARY KEY (`id`), KEY `account_id` (`account_id`), KEY `block_id` (`block_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- -------------------------------------------------------- @@ -154,7 +155,7 @@ CREATE TABLE IF NOT EXISTS `transactions` ( KEY `block_id` (`block_id`), KEY `account_id` (`account_id`), KEY `type` (`type`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- -------------------------------------------------------- @@ -171,7 +172,7 @@ CREATE TABLE IF NOT EXISTS `workers` ( PRIMARY KEY (`id`), UNIQUE KEY `username` (`username`), KEY `account_id` (`account_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; From 36bfcf6b6b679b93dd018376c1e5b9c5f1b88aee Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Wed, 29 May 2013 12:14:30 +0200 Subject: [PATCH 40/59] change tx detection to check for orphaned blocks --- cronjobs/blockupdate.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cronjobs/blockupdate.php b/cronjobs/blockupdate.php index 1f74e68c..65779a3a 100755 --- a/cronjobs/blockupdate.php +++ b/cronjobs/blockupdate.php @@ -34,7 +34,7 @@ verbose("ID\tBlockhash\tConfirmations\t\n"); foreach ($aAllBlocks as $iIndex => $aBlock) { $aBlockInfo = $bitcoin->query('getblock', $aBlock['blockhash']); // Fetch this blocks transaction details to find orphan blocks - $aTxDetails = $bitcoin->query('gettransaction', $aBlockInfo['merkleroot']); + $aTxDetails = $bitcoin->query('gettransaction', $aBlockInfo['tx'][0]); verbose($aBlock['id'] . "\t" . $aBlock['blockhash'] . "\t" . $aBlock['confirmations'] . " -> " . $aBlockInfo['confirmations'] . "\t"); if ($aTxDetails['details'][0]['category'] == 'orphan') { // We have an orphaned block, we need to invalidate all transactions for this one From 69b2c2f517d6cb450e8ebfc151ff7233a97b5a5e Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Wed, 29 May 2013 12:41:53 +0200 Subject: [PATCH 41/59] Properly abort API calls if api_key is invalid * Fixes an issue where any api_key would be validated * Now returns user ID upon success, aborts script processing with error on fail --- public/include/classes/user.class.php | 31 ++++++++++--------- public/include/pages/api.inc.php | 2 +- .../include/pages/api/getblockcount.inc.php | 2 +- .../include/pages/api/getblocksfound.inc.php | 2 +- .../pages/api/getcurrentworkers.inc.php | 2 +- .../include/pages/api/getdifficulty.inc.php | 2 +- .../pages/api/getestimatedtime.inc.php | 2 +- .../include/pages/api/getpoolhashrate.inc.php | 2 +- .../pages/api/getpoolsharerate.inc.php | 2 +- .../pages/api/gettimesincelastblock.inc.php | 2 +- 10 files changed, 26 insertions(+), 23 deletions(-) diff --git a/public/include/classes/user.class.php b/public/include/classes/user.class.php index abae79d4..120014e4 100644 --- a/public/include/classes/user.class.php +++ b/public/include/classes/user.class.php @@ -232,10 +232,13 @@ class User { **/ public function checkApiKey($key) { $this->debug->append("STA " . __METHOD__, 4); - $stmt = $this->mysqli->prepare("SELECT api_key FROM $this->table WHERE api_key = ?"); - if ($this->checkStmt($stmt) && $stmt->bind_param("s", $key) && $stmt->execute() && $stmt->bind_result($api_key) && $stmt->fetch()) - return $key === $api_key; - return false; + $stmt = $this->mysqli->prepare("SELECT api_key, id FROM $this->table WHERE api_key = ? LIMIT 1"); + if ($this->checkStmt($stmt) && $stmt->bind_param("s", $key) && $stmt->execute() && $stmt->bind_result($api_key, $id) && $stmt->fetch()) { + if ($api_key === $key) + return $id; + } + header("HTTP/1.1 401 Unauthorized"); + die('Access denied'); } private function checkUserPassword($username, $password) { @@ -326,12 +329,12 @@ class User { $stmt = $this->mysqli->prepare(" INSERT INTO $this->table (username, pass, email, pin, api_key) VALUES (?, ?, ?, ?, ?) - "); + "); } else { $stmt = $this->mysqli->prepare(" INSERT INTO $this->table (username, pass, email, pin, api_key, admin) VALUES (?, ?, ?, ?, ?, 1) - "); + "); } if ($this->checkStmt($stmt)) { $stmt->bind_param('sssss', $username, hash("sha256", $password1.$this->salt), $email1, hash("sha256", $pin.$this->salt), $apikey); @@ -393,14 +396,14 @@ class User { $headers .= "MIME-Version: 1.0\n"; $headers .= "Content-Type: text/html; charset=ISO-8859-1\r\n"; if (mail($email, - $smarty->fetch('templates/mail/subject.tpl'), - $smarty->fetch('templates/mail/body.tpl'), - $headers)) { - return true; - } else { - $this->setErrorMessage("Unable to send mail to your address"); - return false; - } + $smarty->fetch('templates/mail/subject.tpl'), + $smarty->fetch('templates/mail/body.tpl'), + $headers)) { + return true; + } else { + $this->setErrorMessage("Unable to send mail to your address"); + return false; + } return false; } } diff --git a/public/include/pages/api.inc.php b/public/include/pages/api.inc.php index 3b4d3858..c2e64a60 100644 --- a/public/include/pages/api.inc.php +++ b/public/include/pages/api.inc.php @@ -5,7 +5,7 @@ if (!defined('SECURITY')) die('Hacking attempt'); // Check for valid API key -$user->checkApiKey($_REQUEST['api_key']); +$id = $user->checkApiKey($_REQUEST['api_key']); header('HTTP/1.1 400 Bad Request'); die('400 Bad Request'); diff --git a/public/include/pages/api/getblockcount.inc.php b/public/include/pages/api/getblockcount.inc.php index f3a6779f..2cbd06a5 100644 --- a/public/include/pages/api/getblockcount.inc.php +++ b/public/include/pages/api/getblockcount.inc.php @@ -5,7 +5,7 @@ if (!defined('SECURITY')) die('Hacking attempt'); // Check user token -$user->checkApiKey($_REQUEST['api_key']); +$id = $user->checkApiKey($_REQUEST['api_key']); if ($bitcoin->can_connect() === true){ if (!$iBlock = $memcache->get('iBlock')) { diff --git a/public/include/pages/api/getblocksfound.inc.php b/public/include/pages/api/getblocksfound.inc.php index 67cd6ab7..00883dad 100644 --- a/public/include/pages/api/getblocksfound.inc.php +++ b/public/include/pages/api/getblocksfound.inc.php @@ -5,7 +5,7 @@ if (!defined('SECURITY')) die('Hacking attempt'); // Check user token -$user->checkApiKey($_REQUEST['api_key']); +$id = $user->checkApiKey($_REQUEST['api_key']); // Set a sane limit, overwrite with URL parameter $iLimit = 10; diff --git a/public/include/pages/api/getcurrentworkers.inc.php b/public/include/pages/api/getcurrentworkers.inc.php index 2f0a3241..4e26cc1c 100644 --- a/public/include/pages/api/getcurrentworkers.inc.php +++ b/public/include/pages/api/getcurrentworkers.inc.php @@ -5,7 +5,7 @@ if (!defined('SECURITY')) die('Hacking attempt'); // Check user token -$user->checkApiKey($_REQUEST['api_key']); +$id = $user->checkApiKey($_REQUEST['api_key']); // Output JSON format echo json_encode(array('getcurrentworkers' => $worker->getCountAllActiveWorkers())); diff --git a/public/include/pages/api/getdifficulty.inc.php b/public/include/pages/api/getdifficulty.inc.php index 60c0f111..9d2aa7a2 100644 --- a/public/include/pages/api/getdifficulty.inc.php +++ b/public/include/pages/api/getdifficulty.inc.php @@ -5,7 +5,7 @@ if (!defined('SECURITY')) die('Hacking attempt'); // Check user token -$user->checkApiKey($_REQUEST['api_key']); +$id = $user->checkApiKey($_REQUEST['api_key']); // Fetch data from litecoind if ($bitcoin->can_connect() === true){ diff --git a/public/include/pages/api/getestimatedtime.inc.php b/public/include/pages/api/getestimatedtime.inc.php index 6bc76881..a48393fa 100644 --- a/public/include/pages/api/getestimatedtime.inc.php +++ b/public/include/pages/api/getestimatedtime.inc.php @@ -5,7 +5,7 @@ if (!defined('SECURITY')) die('Hacking attempt'); // Check user token -$user->checkApiKey($_REQUEST['api_key']); +$id = $user->checkApiKey($_REQUEST['api_key']); // Estimated time to find the next block $iCurrentPoolHashrate = $statistics->getCurrentHashrate() * 1000; diff --git a/public/include/pages/api/getpoolhashrate.inc.php b/public/include/pages/api/getpoolhashrate.inc.php index 996d1ce2..6f6763ec 100644 --- a/public/include/pages/api/getpoolhashrate.inc.php +++ b/public/include/pages/api/getpoolhashrate.inc.php @@ -5,7 +5,7 @@ if (!defined('SECURITY')) die('Hacking attempt'); // Check user token -$user->checkApiKey($_REQUEST['api_key']); +$id = $user->checkApiKey($_REQUEST['api_key']); // Output JSON format echo json_encode(array('getpoolhashrate' => $statistics->getCurrentHashrate())); diff --git a/public/include/pages/api/getpoolsharerate.inc.php b/public/include/pages/api/getpoolsharerate.inc.php index 980c0ba3..8e9117f1 100644 --- a/public/include/pages/api/getpoolsharerate.inc.php +++ b/public/include/pages/api/getpoolsharerate.inc.php @@ -5,7 +5,7 @@ if (!defined('SECURITY')) die('Hacking attempt'); // Check user token -$user->checkApiKey($_REQUEST['api_key']); +$id = $user->checkApiKey($_REQUEST['api_key']); // Output JSON format echo json_encode(array('getpoolsharerate' => $statistics->getCurrentShareRate())); diff --git a/public/include/pages/api/gettimesincelastblock.inc.php b/public/include/pages/api/gettimesincelastblock.inc.php index f80c55ce..532da6bd 100644 --- a/public/include/pages/api/gettimesincelastblock.inc.php +++ b/public/include/pages/api/gettimesincelastblock.inc.php @@ -5,7 +5,7 @@ if (!defined('SECURITY')) die('Hacking attempt'); // Check user token -$user->checkApiKey($_REQUEST['api_key']); +$id = $user->checkApiKey($_REQUEST['api_key']); // Fetch our last block found $aBlocksFoundData = $statistics->getBlocksFound(1); From bdc42c58c1f38bd0e33b1813356d199c6d548930 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Wed, 29 May 2013 20:54:34 +0200 Subject: [PATCH 42/59] fetch last value from API instead of average * Added curl as dependency in README --- README.md | 1 + cronjobs/tickerupdate.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f14cd425..54ad3831 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ in the appropriate forums. * PHP 5.4+ * php5-mysqlnd * php5-memcached + * php5-curl * MySQL Server * mysql-server * memcached diff --git a/cronjobs/tickerupdate.php b/cronjobs/tickerupdate.php index b806654d..0d11e4eb 100755 --- a/cronjobs/tickerupdate.php +++ b/cronjobs/tickerupdate.php @@ -27,7 +27,7 @@ require_once(BASEPATH . CLASS_DIR . '/tools.class.php'); verbose("Running ticket updates\n"); if ($aData = $tools->getApi($config['price']['url'], $config['price']['target'])) { - if (!$setting->setValue('price', $aData['ticker']['avg'])) + if (!$setting->setValue('price', $aData['ticker']['last'])) verbose("ERR Table update failed"); } else { verbose("ERR Failed download JSON data from " . $config['price']['url'].$config['price']['target'] . "\n"); From 10266959a52838898ea1c3d215ff358079d18167 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Wed, 29 May 2013 20:59:08 +0200 Subject: [PATCH 43/59] removed More button for blocks --- public/templates/mmcFE/statistics/blocks/blocks_found.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/templates/mmcFE/statistics/blocks/blocks_found.tpl b/public/templates/mmcFE/statistics/blocks/blocks_found.tpl index db1d79ab..474fd87c 100644 --- a/public/templates/mmcFE/statistics/blocks/blocks_found.tpl +++ b/public/templates/mmcFE/statistics/blocks/blocks_found.tpl @@ -1,4 +1,4 @@ -{include file="global/block_header.tpl" BLOCK_HEADER="Last $BLOCKLIMIT Blocks Found" BLOCK_STYLE="clear:none;" BUTTONS=array(More)} +{include file="global/block_header.tpl" BLOCK_HEADER="Last $BLOCKLIMIT Blocks Found" BLOCK_STYLE="clear:none;"}
      • LTC/usd: {$GLOBAL.price}    
      • LTC/usd: {$GLOBAL.price|default:"n/a"}    
      • Pool Hashrate: {$GLOBAL.hashrate / 1000} MH/s    
      • Pool Sharerate: {$GLOBAL.sharerate} Shares/s    
      • Pool Workers: {$GLOBAL.workers}    
      • From 61658b76f483d5c1582400f5283f4cc6fb9a0724 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Wed, 29 May 2013 21:18:24 +0200 Subject: [PATCH 44/59] changed error message for RPC errors --- public/include/pages/account/edit.inc.php | 2 +- public/include/pages/statistics.inc.php | 2 +- public/include/pages/statistics/pool.inc.php | 2 +- public/include/pages/statistics/user.inc.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/public/include/pages/account/edit.inc.php b/public/include/pages/account/edit.inc.php index 884f6b6b..bb29cace 100644 --- a/public/include/pages/account/edit.inc.php +++ b/public/include/pages/account/edit.inc.php @@ -37,7 +37,7 @@ if ( ! $user->checkPin($_SESSION['USERDATA']['id'], $_POST['authPin']) && $_POST if ($continue == true && $transaction->addTransaction($_SESSION['USERDATA']['id'], $dBalance, 'Debit_MP', NULL, $sCoinAddress)) $_SESSION['POPUP'][] = array('CONTENT' => 'Transaction completed', 'TYPE' => 'success'); } else { - $_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to pushpool service', 'TYPE' => 'errormsg'); + $_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to litecoind RPC service', 'TYPE' => 'errormsg'); } } else { $_SESSION['POPUP'][] = array('CONTENT' => 'Insufficient funds, you need more than 0.1 LTC to cover transaction fees', 'TYPE' => 'errormsg'); diff --git a/public/include/pages/statistics.inc.php b/public/include/pages/statistics.inc.php index c3f1e298..c465f091 100644 --- a/public/include/pages/statistics.inc.php +++ b/public/include/pages/statistics.inc.php @@ -10,7 +10,7 @@ if ($bitcoin->can_connect() === true){ } else { $iDifficulty = 1; $iBlock = 0; - $_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to pushpool service: ' . $bitcoin->can_connect(), 'TYPE' => 'errormsg'); + $_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to litecoind RPC service: ' . $bitcoin->can_connect(), 'TYPE' => 'errormsg'); } $smarty->assign("CURRENTBLOCK", $iBlock); diff --git a/public/include/pages/statistics/pool.inc.php b/public/include/pages/statistics/pool.inc.php index a256d2cf..e5212938 100644 --- a/public/include/pages/statistics/pool.inc.php +++ b/public/include/pages/statistics/pool.inc.php @@ -11,7 +11,7 @@ if ($bitcoin->can_connect() === true){ } else { $iDifficulty = 1; $iBlock = 0; - $_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to pushpool service: ' . $bitcoin->can_connect(), 'TYPE' => 'errormsg'); + $_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to litecoind RPC service: ' . $bitcoin->can_connect(), 'TYPE' => 'errormsg'); } // Top share contributors diff --git a/public/include/pages/statistics/user.inc.php b/public/include/pages/statistics/user.inc.php index 3a344c70..41440b99 100644 --- a/public/include/pages/statistics/user.inc.php +++ b/public/include/pages/statistics/user.inc.php @@ -11,7 +11,7 @@ if ($bitcoin->can_connect() === true){ } else { $iDifficulty = 1; $iBlock = 0; - $_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to pushpool service: ' . $bitcoin->can_connect(), 'TYPE' => 'errormsg'); + $_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to litecoind RPC service: ' . $bitcoin->can_connect(), 'TYPE' => 'errormsg'); } $aHourlyHashRates = $statistics->getHourlyHashrateByAccount($_SESSION['USERDATA']['id']); From b5ab1a02fb9fef4b33c65e87753763744208737d Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Thu, 30 May 2013 09:55:21 +0200 Subject: [PATCH 45/59] Adding more in-line documentation and some cleanup --- .../include/classes/bitcoinwrapper.class.php | 4 ++ public/include/classes/block.class.php | 61 ++++++++++++++++- public/include/classes/setting.class.php | 11 ++++ public/include/classes/share.class.php | 41 ++++++++++++ public/include/classes/tools.class.php | 5 ++ public/include/classes/transaction.class.php | 26 ++++++++ public/include/classes/user.class.php | 65 +++++++++++++++++++ 7 files changed, 212 insertions(+), 1 deletion(-) diff --git a/public/include/classes/bitcoinwrapper.class.php b/public/include/classes/bitcoinwrapper.class.php index 9f2ad861..eb6d55e0 100644 --- a/public/include/classes/bitcoinwrapper.class.php +++ b/public/include/classes/bitcoinwrapper.class.php @@ -4,6 +4,10 @@ if (!defined('SECURITY')) die('Hacking attempt'); +/** + * We use a wrapper class around BitcoinClient to add + * some basic caching functionality and some debugging + **/ class BitcoinWrapper extends BitcoinClient { public function __construct($type, $username, $password, $host, $debug, $memcache) { $this->type = $type; diff --git a/public/include/classes/block.class.php b/public/include/classes/block.class.php index cd5e0456..cfafc85f 100644 --- a/public/include/classes/block.class.php +++ b/public/include/classes/block.class.php @@ -27,17 +27,27 @@ class Block { return $this->table; } + /** + * Specific method to fetch the latest block found + * @param none + * @return data array Array with database fields as keys + **/ public function getLast() { $stmt = $this->mysqli->prepare("SELECT * FROM $this->table ORDER BY height DESC LIMIT 1"); if ($this->checkStmt($stmt)) { $stmt->execute(); $result = $stmt->get_result(); $stmt->close(); - return $result->fetch_object(); + return $result->fetch_assoc(); } return false; } + /** + * Fetch all unaccounted blocks + * @param order string Sort order, default ASC + * @return data array Array with database fields as keys + **/ public function getAllUnaccounted($order='ASC') { $stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE accounted = 0 ORDER BY height $order"); if ($this->checkStmt($stmt)) { @@ -49,6 +59,11 @@ class Block { return false; } + /** + * Fetch all unconfirmed blocks from table + * @param confirmations int Required confirmations to consider block confirmed + * @return data array Array with database fields as keys + **/ public function getAllUnconfirmed($confirmations='120') { $stmt = $this->mysqli->prepare("SELECT id, blockhash, confirmations FROM $this->table WHERE confirmations < ? AND confirmations > -1"); if ($this->checkStmt($stmt)) { @@ -61,6 +76,12 @@ class Block { return false; } + /** + * Update confirmations for an existing block + * @param block_id int Block ID to update + * @param confirmations int New confirmations value + * @return bool + **/ public function setConfirmations($block_id, $confirmations) { $stmt = $this->mysqli->prepare("UPDATE $this->table SET confirmations = ? WHERE id = ?"); if ($this->checkStmt($stmt)) { @@ -72,6 +93,11 @@ class Block { return false; } + /** + * Fetch all blocks ordered by DESC height + * @param order string ASC or DESC ordering + * @return data array Array with database fields as keys + **/ public function getAll($order='DESC') { $stmt = $this->mysqli->prepare("SELECT * FROM $this->table ORDER BY height $order"); if ($this->checkStmt($stmt)) { @@ -83,6 +109,11 @@ class Block { return false; } + /** + * Add new new block to the database + * @param block array Block data as an array, see bind_param + * @return bool + **/ public function addBlock($block) { $stmt = $this->mysqli->prepare("INSERT INTO $this->table (height, blockhash, confirmations, amount, difficulty, time) VALUES (?, ?, ?, ?, ?, ?)"); if ($this->checkStmt($stmt)) { @@ -99,6 +130,13 @@ class Block { return false; } + /** + * Update a single column within a single row + * @param block_id int Block ID to update + * @param field string Column name to update + * @param value string Value to insert + * @return bool + **/ private function updateSingle($block_id, $field, $value) { $stmt = $this->mysqli->prepare("UPDATE $this->table SET $field = ? WHERE id = ?"); if ($this->checkStmt($stmt)) { @@ -114,19 +152,39 @@ class Block { return false; } + /** + * Set finder of a block + * @param block_id int Block ID + * @param account_id int Account ID of finder + * @return bool + **/ public function setFinder($block_id, $account_id=NULL) { return $this->updateSingle($block_id, 'account_id', $account_id); } + /** + * Set counted shares for a block + * @param block_id int Block ID + * @param shares int Share count + * @return bool + **/ public function setShares($block_id, $shares=NULL) { return $this->updateSingle($block_id, 'shares', $shares); } + /** + * Set block to be accounted for + * @param block_id int Block ID + * @return bool + **/ public function setAccounted($block_id=NULL) { if (empty($block_id)) return false; return $this->updateSingle($block_id, 'accounted', 1); } + /** + * Helper function + **/ private function checkStmt($bState) { if ($bState ===! true) { $this->debug->append("Failed to prepare statement: " . $this->mysqli->error); @@ -137,4 +195,5 @@ class Block { } } +// Automatically load our class for furhter usage $block = new Block($debug, $mysqli, SALT); diff --git a/public/include/classes/setting.class.php b/public/include/classes/setting.class.php index 44ef8315..f2c1cbea 100644 --- a/public/include/classes/setting.class.php +++ b/public/include/classes/setting.class.php @@ -12,6 +12,11 @@ class Setting { $this->table = 'settings'; } + /** + * Fetch a value from our table + * @param name string Setting name + * @return value string Value + **/ public function getValue($name) { $query = $this->mysqli->prepare("SELECT value FROM $this->table WHERE name=? LIMIT 1"); if ($query) { @@ -27,6 +32,12 @@ class Setting { return $value; } + /** + * Insert or update a setting + * @param name string Name of the variable + * @param value string Variable value + * @return bool + **/ public function setValue($name, $value) { $stmt = $this->mysqli->prepare(" INSERT INTO $this->table (name, value) diff --git a/public/include/classes/share.class.php b/public/include/classes/share.class.php index 9a14aeeb..1fb195e0 100644 --- a/public/include/classes/share.class.php +++ b/public/include/classes/share.class.php @@ -27,13 +27,29 @@ class Share { return $this->sError; } + /** + * Fetch archive tables name for this class + * @param none + * @return data string Table name + **/ public function getArchiveTableName() { return $this->tableArchive; } + /** + * Fetch normal table name for this class + * @param none + * @return data string Table name + **/ public function getTableName() { return $this->table; } + /** + * Get all valid shares for this round + * @param previous_upstream int Previous found share accepted by upstream to limit results + * @param current_upstream int Current upstream accepted share + * @return data int Total amount of counted shares + **/ public function getRoundShares($previous_upstream=0, $current_upstream) { $stmt = $this->mysqli->prepare("SELECT count(id) as total @@ -51,6 +67,12 @@ class Share { return false; } + /** + * Fetch all shares grouped by accounts to count share per account + * @param previous_upstream int Previous found share accepted by upstream to limit results + * @param current_upstream int Current upstream accepted share + * @return data array username, valid and invalid shares from account + **/ public function getSharesForAccounts($previous_upstream=0, $current_upstream) { $stmt = $this->mysqli->prepare("SELECT a.id, @@ -90,6 +112,13 @@ class Share { return false; } + /** + * Move accounted shares to archive table, this step is optional + * @param previous_upstream int Previous found share accepted by upstream to limit results + * @param current_upstream int Current upstream accepted share + * @param block_id int Block ID to assign shares to a specific block + * @return bool + **/ public function moveArchive($previous_upstream=0, $current_upstream,$block_id) { $archive_stmt = $this->mysqli->prepare("INSERT INTO $this->tableArchive (share_id, username, our_result, upstream_result, block_id, time) SELECT id, username, our_result, upstream_result, ?, time @@ -108,6 +137,9 @@ class Share { return false; } + /** + * Set/get last found share accepted by upstream: id and accounts + **/ public function setLastUpstreamId() { $this->iLastUpstreamId = @$this->oUpstream->id ? $this->oUpstream->id : 0; } @@ -120,6 +152,12 @@ class Share { public function getUpstreamId() { return @$this->oUpstream->id; } + /** + * Find upstream accepted share that should be valid for a specific block + * We allow for +/- 5 seconds here to ensure we find a share + * @param time timestamp Time of when the block was found + * @return bool + **/ public function setUpstream($time='') { $stmt = $this->mysqli->prepare("SELECT SUBSTRING_INDEX( `username` , '.', 1 ) AS account, id @@ -141,6 +179,9 @@ class Share { return false; } + /** + * Helper function + **/ private function checkStmt($bState) { if ($bState ===! true) { $this->debug->append("Failed to prepare statement: " . $this->mysqli->error); diff --git a/public/include/classes/tools.class.php b/public/include/classes/tools.class.php index 530316e6..e97b3746 100644 --- a/public/include/classes/tools.class.php +++ b/public/include/classes/tools.class.php @@ -4,6 +4,11 @@ if (!defined('SECURITY')) die('Hacking attempt'); +/** + * Helper class for our cronjobs + * Implements some common cron tasks outside + * the scope of our web application + **/ class Tools { public function __construct($debug) { $this->debug = $debug; diff --git a/public/include/classes/transaction.class.php b/public/include/classes/transaction.class.php index 27871655..15f29c77 100644 --- a/public/include/classes/transaction.class.php +++ b/public/include/classes/transaction.class.php @@ -25,6 +25,15 @@ class Transaction { return $this->sError; } + /** + * Add a new transaction to our class table + * @param account_id int Account ID to book transaction for + * @param amount float Coin amount + * @param type string Transaction type [Credit, Debit_AP, Debit_MP, Fee, Donation, Orphan_Credit, Orphan_Fee, Orphan_Donation] + * @param block_id int Block ID to link transaction to [optional] + * @param coin_address string Coin address for this transaction [optional] + * @return bool + **/ public function addTransaction($account_id, $amount, $type='Credit', $block_id=NULL, $coin_address=NULL) { $stmt = $this->mysqli->prepare("INSERT INTO $this->table (account_id, amount, block_id, type, coin_address) VALUES (?, ?, ?, ?, ?)"); if ($this->checkStmt($stmt)) { @@ -38,6 +47,12 @@ class Transaction { return false; } + /** + * Sometimes transactions become orphans when a block associated to them is orphaned + * Updates the transaction types to Orphan_ + * @param block_id int Orphaned block ID + * @return bool + **/ public function setOrphan($block_id) { $this->debug->append("STA " . __METHOD__, 4); $stmt = $this->mysqli->prepare(" @@ -73,6 +88,12 @@ class Transaction { return true; } + /** + * Get all transactions from start for account_id + * @param account_id int Account ID + * @param start int Starting point, id of transaction + * @return data array Database fields as defined in SELECT + **/ public function getTransactions($account_id, $start=0) { $this->debug->append("STA " . __METHOD__, 4); $stmt = $this->mysqli->prepare(" @@ -144,6 +165,11 @@ class Transaction { return false; } + /** + * Get an accounts total balance + * @param account_id int Account ID + * @return data float Credit - Debit - Fees - Donation + **/ public function getBalance($account_id) { $this->debug->append("STA " . __METHOD__, 4); $stmt = $this->mysqli->prepare(" diff --git a/public/include/classes/user.class.php b/public/include/classes/user.class.php index 120014e4..d6582676 100644 --- a/public/include/classes/user.class.php +++ b/public/include/classes/user.class.php @@ -183,6 +183,14 @@ class User { return true; } + /** + * Update the accounts password + * @param userID int User ID + * @param current string Current password + * @param new1 string New password + * @param new2 string New password confirmation + * @return bool + **/ public function updatePassword($userID, $current, $new1, $new2) { $this->debug->append("STA " . __METHOD__, 4); if ($new1 !== $new2) { @@ -208,6 +216,14 @@ class User { return false; } + /** + * Update account information from the edit account page + * @param userID int User ID + * @param address string new coin address + * @param threshold float auto payout threshold + * @param donat float donation % of income + * @return bool + **/ public function updateAccount($userID, $address, $threshold, $donate) { $this->debug->append("STA " . __METHOD__, 4); $bUser = false; @@ -241,6 +257,12 @@ class User { die('Access denied'); } + /** + * Check a password for a user + * @param username string Username + * @param password string Password + * @return bool + **/ private function checkUserPassword($username, $password) { $this->debug->append("STA " . __METHOD__, 4); $user = array(); @@ -258,6 +280,11 @@ class User { return false; } + /** + * Create a PHP session for a user + * @param username string Username to create session for + * @return none + **/ private function createSession($username) { $this->debug->append("STA " . __METHOD__, 4); $this->debug->append("Log in user to _SESSION", 2); @@ -267,6 +294,11 @@ class User { $_SESSION['USERDATA'] = $this->user; } + /** + * Log out current user, destroy the session + * @param none + * @return true + **/ public function logoutUser() { $this->debug->append("STA " . __METHOD__, 4); session_destroy(); @@ -274,11 +306,20 @@ class User { return true; } + /** + * Fetch this classes table name + * @return table string This classes table name + **/ public function getTableName() { $this->debug->append("STA " . __METHOD__, 4); return $this->table; } + /** + * Fetch some basic user information to store for later user + * @param userID int User ID + * return data array Database fields as used in SELECT + **/ public function getUserData($userID) { $this->debug->append("STA " . __METHOD__, 4); $this->debug->append("Fetching user information for user id: $userID"); @@ -302,6 +343,16 @@ class User { return false; } + /** + * Register a new user in the system + * @param username string Username + * @param password1 string Password + * @param password2 string Password verification + * @param pin int 4 digit PIN code + * @param email1 string Email address + * @param email2 string Email confirmation + * @return bool + **/ public function register($username, $password1, $password2, $pin, $email1='', $email2='') { $this->debug->append("STA " . __METHOD__, 4); if (strlen($password1) < 8) { @@ -350,6 +401,13 @@ class User { return false; } + /** + * User a one time token to reset a password + * @param token string one time token + * @param new1 string New password + * @param new2 string New password verification + * @return bool + **/ public function useToken($token, $new1, $new2) { $this->debug->append("STA " . __METHOD__, 4); if ($id = $this->getIdFromToken($token)) { @@ -373,6 +431,12 @@ class User { return false; } + /** + * Reset a password by sending a password reset mail + * @param username string Username to reset password for + * @param smarty object Smarty object for mail templating + * @return bool + **/ public function resetPassword($username, $smarty) { $this->debug->append("STA " . __METHOD__, 4); // Fetch the users mail address @@ -408,4 +472,5 @@ class User { } } +// Make our class available automatically $user = new User($debug, $mysqli, SALT, $config); From b2725fbce5856c81db2a40279857521bbc87cd7e Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Fri, 31 May 2013 11:56:56 +0200 Subject: [PATCH 46/59] Getting rid of various PHP notice warnings * Assigned empty defaults on templates * Added some variable checking --- public/include/pages/statistics/pool.inc.php | 2 +- public/include/smarty_globals.inc.php | 22 ++++++++++--------- .../mmcFE/account/transactions/default.tpl | 4 ++-- .../templates/mmcFE/global/block_header.tpl | 6 ++--- public/templates/mmcFE/global/motd.tpl | 2 +- public/templates/mmcFE/global/navigation.tpl | 8 +++---- public/templates/mmcFE/global/userinfo.tpl | 2 +- public/templates/mmcFE/master.tpl | 6 ++--- 8 files changed, 27 insertions(+), 25 deletions(-) diff --git a/public/include/pages/statistics/pool.inc.php b/public/include/pages/statistics/pool.inc.php index e5212938..0c9c2eb7 100644 --- a/public/include/pages/statistics/pool.inc.php +++ b/public/include/pages/statistics/pool.inc.php @@ -9,7 +9,7 @@ if ($bitcoin->can_connect() === true){ $dDifficulty = $bitcoin->getdifficulty(); $iBlock = $bitcoin->getblockcount(); } else { - $iDifficulty = 1; + $dDifficulty = 1; $iBlock = 0; $_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to litecoind RPC service: ' . $bitcoin->can_connect(), 'TYPE' => 'errormsg'); } diff --git a/public/include/smarty_globals.inc.php b/public/include/smarty_globals.inc.php index 8c7891e6..f34b3b4a 100644 --- a/public/include/smarty_globals.inc.php +++ b/public/include/smarty_globals.inc.php @@ -29,18 +29,20 @@ $aGlobal = array( ); // We don't want these session infos cached -$aGlobal['userdata'] = $_SESSION['USERDATA']['id'] ? $user->getUserData($_SESSION['USERDATA']['id']) : array(); -$aGlobal['userdata']['balance'] = $transaction->getBalance($_SESSION['USERDATA']['id']); +if (@$_SESSION['USERDATA']['id']) { + $aGlobal['userdata'] = $_SESSION['USERDATA']['id'] ? $user->getUserData($_SESSION['USERDATA']['id']) : array(); + $aGlobal['userdata']['balance'] = $transaction->getBalance($_SESSION['USERDATA']['id']); -// Other userdata that we can cache savely -$aGlobal['userdata']['shares'] = $statistics->getUserShares($_SESSION['USERDATA']['id']); -$aGlobal['userdata']['hashrate'] = $statistics->getUserHashrate($_SESSION['USERDATA']['id']); + // Other userdata that we can cache savely + $aGlobal['userdata']['shares'] = $statistics->getUserShares($_SESSION['USERDATA']['id']); + $aGlobal['userdata']['hashrate'] = $statistics->getUserHashrate($_SESSION['USERDATA']['id']); -// Some estimations -$aGlobal['userdata']['est_block'] = round(( (int)$aGlobal['userdata']['shares']['valid'] / (int)$aRoundShares['valid'] ) * (int)$config['reward'], 3); -$aGlobal['userdata']['est_fee'] = round(($config['fees'] / 100) * $aGlobal['userdata']['est_block'], 3); -$aGlobal['userdata']['est_donation'] = round((( $aGlobal['userdata']['donate_percent'] / 100) * ($aGlobal['userdata']['est_block'] - $aGlobal['userdata']['est_fee'])), 3); -$aGlobal['userdata']['est_payout'] = round($aGlobal['userdata']['est_block'] - $aGlobal['userdata']['est_donation'] - $aGlobal['userdata']['est_fee'], 3); + // Some estimations + $aGlobal['userdata']['est_block'] = round(( (int)$aGlobal['userdata']['shares']['valid'] / (int)$aRoundShares['valid'] ) * (int)$config['reward'], 3); + $aGlobal['userdata']['est_fee'] = round(($config['fees'] / 100) * $aGlobal['userdata']['est_block'], 3); + $aGlobal['userdata']['est_donation'] = round((( $aGlobal['userdata']['donate_percent'] / 100) * ($aGlobal['userdata']['est_block'] - $aGlobal['userdata']['est_fee'])), 3); + $aGlobal['userdata']['est_payout'] = round($aGlobal['userdata']['est_block'] - $aGlobal['userdata']['est_donation'] - $aGlobal['userdata']['est_fee'], 3); +} // Make it available in Smarty $smarty->assign('PATH', 'site_assets/' . THEME); diff --git a/public/templates/mmcFE/account/transactions/default.tpl b/public/templates/mmcFE/account/transactions/default.tpl index ed523e54..8f5282e1 100644 --- a/public/templates/mmcFE/account/transactions/default.tpl +++ b/public/templates/mmcFE/account/transactions/default.tpl @@ -77,7 +77,7 @@ {/section} - +
        Unconfirmed Totals:{$credits - $debits}{$credits|default - $debits|default}
        @@ -121,7 +121,7 @@ {/section} Orphaned Totals: - {$orphan_credits - $orphan_debits} + {$orphan_credits|default - $orphan_debits|default} diff --git a/public/templates/mmcFE/global/block_header.tpl b/public/templates/mmcFE/global/block_header.tpl index b6b85403..49eed72d 100644 --- a/public/templates/mmcFE/global/block_header.tpl +++ b/public/templates/mmcFE/global/block_header.tpl @@ -1,9 +1,9 @@ -
        +

        {$BLOCK_HEADER|default:"UNKNOWN BLOCK"}

        - {if $BUTTONS} + {if $BUTTONS|default}
          {foreach from=$BUTTONS item=name}
        • {$name}
        • @@ -11,4 +11,4 @@
        {/if}
        -
        +
        diff --git a/public/templates/mmcFE/global/motd.tpl b/public/templates/mmcFE/global/motd.tpl index c95e7278..cbb918cd 100644 --- a/public/templates/mmcFE/global/motd.tpl +++ b/public/templates/mmcFE/global/motd.tpl @@ -1,4 +1,4 @@ -{if $GLOBAL.motd} +{if $GLOBAL.motd|default}
        ***Message of the Day***
        {$GLOBAL.motd|escape:'html'} diff --git a/public/templates/mmcFE/global/navigation.tpl b/public/templates/mmcFE/global/navigation.tpl index 62c24dbd..3830006b 100644 --- a/public/templates/mmcFE/global/navigation.tpl +++ b/public/templates/mmcFE/global/navigation.tpl @@ -1,6 +1,6 @@
      • News
      • - {if $smarty.session.AUTHENTICATED == 1}
      • Logout
      • {else}
      • Register
      • {/if} + {if $smarty.session.AUTHENTICATED|default == 1}
      • Logout
      • {else}
      • Register
      • {/if}
      diff --git a/public/templates/mmcFE/global/userinfo.tpl b/public/templates/mmcFE/global/userinfo.tpl index b4836be3..01b095f2 100644 --- a/public/templates/mmcFE/global/userinfo.tpl +++ b/public/templates/mmcFE/global/userinfo.tpl @@ -1,4 +1,4 @@ -{if $GLOBAL.userdata.username} +{if $GLOBAL.userdata.username|default}

      Welcome, {$smarty.session.USERDATA.username} Active Account: {$GLOBAL.fees}% Pool Fee (You are donating {$GLOBAL.userdata.donate_percent}% of your earnings)

      {else}

      Welcome guest, please register to user this pool.

      diff --git a/public/templates/mmcFE/master.tpl b/public/templates/mmcFE/master.tpl index 14aa2e56..aff628f4 100644 --- a/public/templates/mmcFE/master.tpl +++ b/public/templates/mmcFE/master.tpl @@ -4,7 +4,7 @@ ThePool - + @@ -45,14 +45,14 @@
      - - + + - diff --git a/public/templates/mmcFE/global/userinfo.tpl b/public/templates/mmcFE/global/userinfo.tpl index 01b095f2..92105bdc 100644 --- a/public/templates/mmcFE/global/userinfo.tpl +++ b/public/templates/mmcFE/global/userinfo.tpl @@ -1,5 +1,5 @@ {if $GLOBAL.userdata.username|default} -

      Welcome, {$smarty.session.USERDATA.username} Active Account: {$GLOBAL.fees}% Pool Fee (You are donating {$GLOBAL.userdata.donate_percent}% of your earnings)

      +

      Welcome, {$smarty.session.USERDATA.username} Active Account: {$GLOBAL.fees}% Pool Fee (You are donating {$GLOBAL.userdata.donate_percent}% of your earnings)

      {else}

      Welcome guest, please register to user this pool.

      {/if}