commit
9f02359c4c
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +1,4 @@
|
||||
/public/include/config/global.inc.php
|
||||
/public/templates/compile/*.php
|
||||
/cronjobs/logs/*.txt
|
||||
/public/templates/cache/*.php
|
||||
|
||||
12
POOLS.md
12
POOLS.md
@ -27,7 +27,7 @@ They have succesfully mined blocks on each of those pools listed.
|
||||
All pools are running on Stratum only.
|
||||
|
||||
| Pool URL | Coin | Avg. Hashrate | Avg. Active Workers | Notes |
|
||||
| -------- | ---- | ------------- | ----------------- | ----- |
|
||||
| -------- | ---- | ------------- | -----------------: | ----- |
|
||||
| http://wdc.nordicminers.eu | Worldcoin | n/a | n/a | |
|
||||
| http://lky.nordicminers.eu | Luckycoin | n/a | n/a | |
|
||||
| http://fst.nordicminers.eu | Fastcoin | n/a | n/a | |
|
||||
@ -48,7 +48,7 @@ running more or less without any issues (related to `mmcfe-ng` that is ;-)). He
|
||||
the most powerful pool!
|
||||
|
||||
| Pool URL | Coin | Avg. Hashrate | Avg. Active Workers | Notes |
|
||||
| -------- | ---- | ------------- | ----------------- | ----- |
|
||||
| -------- | ---- | ------------- | ------------------: | ----- |
|
||||
| http://www.ejpool.info | Litecoin | 155 MHash | 120 | |
|
||||
|
||||
### Obigal
|
||||
@ -65,6 +65,12 @@ Small Time Miners are running various stratum only pools for different coins.
|
||||
### Feeleep75
|
||||
|
||||
| Pool URL | Coin | Avg. Hashrate | Avg. Active Workers | Notes |
|
||||
| -------- | ---- | ------------- | ------------------- | ----- |
|
||||
| -------- | ---- | ------------- | ------------------: | ----- |
|
||||
| http://bot.coinmine.pl | Bottlecaps | 3 - 50 MHash | n/a | PoS/PoW type coin |
|
||||
| http://yacp.coinmine.pl | YaCoin | 19 MHash | n/a | |
|
||||
|
||||
### LiteSaber
|
||||
|
||||
| Pool URL | Coin | Avg. Hashrate | Avg. Active Workers | Notes |
|
||||
| -------- | ---- | ------------- | ------------------: | ----- |
|
||||
| http://coinhuntr.com | Litecoin | 200 MHash | 250 | Custom Frontend template |
|
||||
|
||||
13
README.md
13
README.md
@ -32,6 +32,7 @@ These people have supported this project with a donation:
|
||||
* [vias](https://github.com/vias79)
|
||||
* [WKNiGHT](https://github.com/WKNiGHT-)
|
||||
* [ZC](https://github.com/zccopwrx)
|
||||
* Nutnut
|
||||
|
||||
Pools running mmcfe-ng
|
||||
======================
|
||||
@ -68,12 +69,13 @@ Features
|
||||
|
||||
The following feature have been implemented so far:
|
||||
|
||||
* Mobile WebUI **NEW**
|
||||
* Fully re-written GUI with [Smarty][2] templates
|
||||
* Mobile WebUI
|
||||
* Reward Systems
|
||||
* Propotional
|
||||
* PPS
|
||||
* (Planned) PPLNS
|
||||
* Use of memcache for statistics instead of a cronjob
|
||||
* PPLNS **NEW**
|
||||
* Statistics are cached in Memcache by Cronjob for quick data access
|
||||
* Web User accounts
|
||||
* Re-Captcha protected registration form
|
||||
* Worker accounts
|
||||
@ -87,9 +89,11 @@ The following feature have been implemented so far:
|
||||
* Auto payout
|
||||
* Transaction list (confirmed and unconfirmed)
|
||||
* Admin Panel
|
||||
* Cron Monitoring Overview **NEW**
|
||||
* User Listing including statistics
|
||||
* Wallet information
|
||||
* News Posts **NEW**
|
||||
* User Transactions **NEW**
|
||||
* News Posts
|
||||
* Notification system
|
||||
* IDLE Workers
|
||||
* New blocks found in pool
|
||||
@ -139,3 +143,4 @@ limitations under the License.
|
||||
|
||||
|
||||
[1]: https://github.com/TheSerapher/php-mmcfe-ng/issues "Issue"
|
||||
[2]: http://www.smarty.net/docs/en/ "Smarty"
|
||||
|
||||
36
cronjobs/archive_cleanup.php
Executable file
36
cronjobs/archive_cleanup.php
Executable file
@ -0,0 +1,36 @@
|
||||
#!/usr/bin/php
|
||||
<?php
|
||||
|
||||
/*
|
||||
|
||||
Copyright:: 2013, Sebastian Grewe
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
// Include all settings and classes
|
||||
require_once('shared.inc.php');
|
||||
|
||||
// If we don't keep archives, delete some now to release disk space
|
||||
if (!$share->purgeArchive()) {
|
||||
$log->logError("Failed to delete archived shares, not critical but should be checked!");
|
||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
||||
$monitoring->setStatus($cron_name . "_message", "message", "Failed to delete archived shares");
|
||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Cron cleanup and monitoring
|
||||
require_once('cron_end.inc.php');
|
||||
?>
|
||||
@ -22,30 +22,28 @@ limitations under the License.
|
||||
// Include all settings and classes
|
||||
require_once('shared.inc.php');
|
||||
|
||||
verbose("Running auto-payouts ...");
|
||||
|
||||
if ($bitcoin->can_connect() !== true) {
|
||||
verbose(" unable to connect to RPC server, exiting\n");
|
||||
$log->logFatal(" unable to connect to RPC server, exiting");
|
||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
||||
$monitoring->setStatus($cron_name . "_message", "message", "Unable to connect to RPC server");
|
||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Mark this job as active
|
||||
$setting->setValue('auto_payout_active', 1);
|
||||
|
||||
// Fetch all users with setup AP
|
||||
$users = $user->getAllAutoPayout();
|
||||
|
||||
// Quick summary
|
||||
verbose(" found " . count($users) . " queued payout(s)\n");
|
||||
$log->logInfo(" found " . count($users) . " queued payout(s)");
|
||||
|
||||
// Go through users and run transactions
|
||||
if (! empty($users)) {
|
||||
verbose("\tUserID\tUsername\tBalance\tThreshold\tAddress\t\t\t\t\tStatus\n\n");
|
||||
$log->logInfo("\tUserID\tUsername\tBalance\tThreshold\tAddress");
|
||||
|
||||
foreach ($users as $aUserData) {
|
||||
$aBalance = $transaction->getBalance($aUserData['id']);
|
||||
$dBalance = $aBalance['confirmed'];
|
||||
verbose("\t" . $aUserData['id'] . "\t" . $aUserData['username'] . "\t" . $dBalance . "\t" . $aUserData['ap_threshold'] . "\t\t" . $aUserData['coin_address'] . "\t");
|
||||
$log->logInfo("\t" . $aUserData['id'] . "\t" . $aUserData['username'] . "\t" . $dBalance . "\t" . $aUserData['ap_threshold'] . "\t\t" . $aUserData['coin_address']);
|
||||
|
||||
// Only run if balance meets threshold and can pay the potential transaction fee
|
||||
if ($dBalance > $aUserData['ap_threshold'] && $dBalance > $config['txfee']) {
|
||||
@ -53,7 +51,7 @@ if (! empty($users)) {
|
||||
try {
|
||||
$bitcoin->validateaddress($aUserData['coin_address']);
|
||||
} catch (BitcoinClientException $e) {
|
||||
verbose("VERIFY FAILED\n");
|
||||
$log->logError('Failed to verifu this users coin address, skipping payout');
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -61,7 +59,7 @@ if (! empty($users)) {
|
||||
try {
|
||||
$bitcoin->sendtoaddress($aUserData['coin_address'], $dBalance);
|
||||
} catch (BitcoinClientException $e) {
|
||||
verbose("SEND FAILED\n");
|
||||
$log->logError('Failed to send requested balance to coin address, please check payout process');
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -71,24 +69,17 @@ if (! empty($users)) {
|
||||
$aMailData['email'] = $user->getUserEmail($user->getUserName($aUserData['id']));
|
||||
$aMailData['subject'] = 'Auto Payout Completed';
|
||||
$aMailData['amount'] = $dBalance;
|
||||
if (!$notification->sendNotification($aUserData['id'], 'auto_payout', $aMailData)) {
|
||||
verbose("NOTIFY FAILED\n");
|
||||
} else {
|
||||
verbose("OK\n");
|
||||
}
|
||||
if (!$notification->sendNotification($aUserData['id'], 'auto_payout', $aMailData))
|
||||
$log->logError('Failed to send notification email to users address: ' . $aMailData['email']);
|
||||
} else {
|
||||
verbose("FAILED\n");
|
||||
$log->logError('Failed to add new Debit_AP transaction in database for user ' . $user->getUserName($aUserData['id']));
|
||||
}
|
||||
|
||||
} else {
|
||||
verbose("SKIPPED\n");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
verbose(" no user has configured their AP > 0\n");
|
||||
$log->logDebug(" no user has configured their AP > 0");
|
||||
}
|
||||
|
||||
// Mark this job as inactive
|
||||
$setting->setValue('auto_payout_active', 0);
|
||||
|
||||
// Cron cleanup and monitoring
|
||||
require_once('cron_end.inc.php');
|
||||
?>
|
||||
|
||||
@ -23,33 +23,37 @@ limitations under the License.
|
||||
require_once('shared.inc.php');
|
||||
|
||||
if ( $bitcoin->can_connect() !== true ) {
|
||||
verbose("Failed to connect to RPC server\n");
|
||||
$log->logFatal("Failed to connect to RPC server\n");
|
||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
||||
$monitoring->setStatus($cron_name . "_message", "message", "Unable to connect to RPC server");
|
||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Fetch all unconfirmed blocks
|
||||
$aAllBlocks = $block->getAllUnconfirmed($config['confirmations']);
|
||||
|
||||
verbose("ID\tBlockhash\tConfirmations\t\n");
|
||||
$log->logInfo("ID\tHeight\tBlockhash\tConfirmations");
|
||||
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['tx'][0]);
|
||||
verbose($aBlock['id'] . "\t" . $aBlock['blockhash'] . "\t" . $aBlock['confirmations'] . " -> " . $aBlockInfo['confirmations'] . "\t");
|
||||
$log->logInfo($aBlock['id'] . "\t" . $aBlock['height'] . "\t" . $aBlock['blockhash'] . "\t" . $aBlock['confirmations'] . " -> " . $aBlockInfo['confirmations']);
|
||||
if ($aTxDetails['details'][0]['category'] == 'orphan') {
|
||||
// We have an orphaned block, we need to invalidate all transactions for this one
|
||||
if ($transaction->setOrphan($aBlock['id']) && $block->setConfirmations($aBlock['id'], -1)) {
|
||||
verbose("ORPHAN\n");
|
||||
if ($block->setConfirmations($aBlock['id'], -1)) {
|
||||
$log->logInfo(" Block marked as orphan");
|
||||
} else {
|
||||
verbose("ORPHAN_ERR");
|
||||
$log->logError(" Block became orphaned but unable to update database entries");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if ($aBlock['confirmations'] == $aBlockInfo['confirmations']) {
|
||||
verbose("SKIPPED\n");
|
||||
} else if ($block->setConfirmations($aBlock['id'], $aBlockInfo['confirmations'])) {
|
||||
verbose("UPDATED\n");
|
||||
} else {
|
||||
verbose("ERROR\n");
|
||||
$log->logDebug(' No update needed');
|
||||
} else if (!$block->setConfirmations($aBlock['id'], $aBlockInfo['confirmations'])) {
|
||||
$log->logError(' Failed to update block confirmations');
|
||||
}
|
||||
}
|
||||
|
||||
require_once('cron_end.inc.php');
|
||||
?>
|
||||
|
||||
28
cronjobs/cron_end.inc.php
Normal file
28
cronjobs/cron_end.inc.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
|
||||
Copyright:: 2013, Sebastian Grewe
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
// Monitoring cleanup and status update
|
||||
$monitoring->setStatus($cron_name . "_message", "message", "OK");
|
||||
$monitoring->setStatus($cron_name . "_status", "okerror", 0);
|
||||
$monitoring->setStatus($cron_name . "_runtime", "time", microtime(true) - $cron_start[$cron_name]);
|
||||
$monitoring->setStatus($cron_name . "_endtime", "date", time());
|
||||
// Mark cron as running for monitoring
|
||||
$monitoring->setStatus($cron_name . '_active', "yesno", 0);
|
||||
?>
|
||||
@ -25,24 +25,25 @@ require_once('shared.inc.php');
|
||||
// Fetch our last block found from the DB as a starting point
|
||||
$aLastBlock = @$block->getLast();
|
||||
$strLastBlockHash = $aLastBlock['blockhash'];
|
||||
if (!$strLastBlockHash) {
|
||||
$strLastBlockHash = '';
|
||||
}
|
||||
if (!$strLastBlockHash) $strLastBlockHash = '';
|
||||
|
||||
// Fetch all transactions since our last block
|
||||
if ( $bitcoin->can_connect() === true ){
|
||||
$aTransactions = $bitcoin->query('listsinceblock', $strLastBlockHash);
|
||||
} else {
|
||||
verbose("Aborted: " . $bitcoin->can_connect() . "\n");
|
||||
$log->logFatal('Unable to conenct to RPC server backend');
|
||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
||||
$monitoring->setStatus($cron_name . "_message", "message", "Unable to connect to RPC server");
|
||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Nothing to do so bail out
|
||||
if (empty($aTransactions['transactions'])) {
|
||||
verbose("No new RPC transactions since last block\n");
|
||||
$log->logDebug('No new RPC transactions since last block');
|
||||
} else {
|
||||
// Table header
|
||||
verbose("Blockhash\t\tHeight\tAmount\tConfirmations\tDiff\t\tTime\t\t\tStatus\n");
|
||||
$log->logInfo("Blockhash\t\tHeight\tAmount\tConfirmations\tDiff\t\tTime");
|
||||
|
||||
// Let us add those blocks as unaccounted
|
||||
foreach ($aTransactions['transactions'] as $iIndex => $aData) {
|
||||
@ -51,70 +52,67 @@ if (empty($aTransactions['transactions'])) {
|
||||
$config['reward_type'] == 'block' ? $aData['amount'] = $aData['amount'] : $aData['amount'] = $config['reward'];
|
||||
$aData['height'] = $aBlockInfo['height'];
|
||||
$aData['difficulty'] = $aBlockInfo['difficulty'];
|
||||
verbose(substr($aData['blockhash'], 0, 15) . "...\t" .
|
||||
$log->logInfo(substr($aData['blockhash'], 0, 15) . "...\t" .
|
||||
$aData['height'] . "\t" .
|
||||
$aData['amount'] . "\t" .
|
||||
$aData['confirmations'] . "\t\t" .
|
||||
$aData['difficulty'] . "\t" .
|
||||
strftime("%Y-%m-%d %H:%M:%S", $aData['time']) . "\t");
|
||||
if ( $block->addBlock($aData) ) {
|
||||
verbose("Added\n");
|
||||
} else {
|
||||
verbose("Failed" . "\n");
|
||||
strftime("%Y-%m-%d %H:%M:%S", $aData['time']));
|
||||
if (!$block->addBlock($aData) ) {
|
||||
$log->logFatal('Unable to add this block to database: ' . $aData['height']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
verbose("\n");
|
||||
// Now with our blocks added we can scan for their upstream shares
|
||||
$aAllBlocks = $block->getAllUnaccounted('ASC');
|
||||
$aAllBlocks = $block->getAllUnsetShareId('ASC');
|
||||
if (empty($aAllBlocks)) {
|
||||
verbose("No new unaccounted blocks found\n");
|
||||
$log->logDebug('No new blocks without share_id found in database');
|
||||
} else {
|
||||
// Loop through our unaccounted blocks
|
||||
verbose("\nBlock ID\tBlock Height\tAmount\tShare ID\tShares\tFinder\t\t\tStatus\n");
|
||||
$log->logInfo("Block ID\t\tHeight\tAmount\tShare ID\tShares\tFinder\tType");
|
||||
foreach ($aAllBlocks as $iIndex => $aBlock) {
|
||||
if (empty($aBlock['share_id'])) {
|
||||
// Fetch this blocks upstream ID
|
||||
if ($share->setUpstream($block->getLastUpstreamId(), $aBlock['time'])) {
|
||||
$aBlockInfo = $bitcoin->query('getblock', $aBlock['blockhash']);
|
||||
if ($share->setUpstream($aBlockInfo, $block->getLastUpstreamId())) {
|
||||
$iCurrentUpstreamId = $share->getUpstreamId();
|
||||
$iAccountId = $user->getUserId($share->getUpstreamFinder());
|
||||
} else {
|
||||
verbose("\nUnable to fetch blocks upstream share. Aborting!\n");
|
||||
verbose($share->getError() . "\n");
|
||||
$log->logFatal('Unable to fetch blocks upstream share, aborted:' . $share->getError());
|
||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
||||
$monitoring->setStatus($cron_name . "_message", "message", "Unable to fetch blocks " . $aBlock['height'] . " upstream share: " . $share->getError());
|
||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Fetch share information
|
||||
if (!$iPreviousShareId = $block->getLastShareId()) {
|
||||
$iPreviousShareId = 0;
|
||||
verbose("\nUnable to find highest share ID found so far\n");
|
||||
verbose("If this is your first block, this is normal\n\n");
|
||||
$log->logInfo('Unable to find highest share ID found so far, if this is your first block, this is normal.');
|
||||
}
|
||||
$iRoundShares = $share->getRoundShares($iPreviousShareId, $iCurrentUpstreamId);
|
||||
|
||||
// Store new information
|
||||
$strStatus = "OK";
|
||||
if (!$block->setShareId($aBlock['id'], $iCurrentUpstreamId))
|
||||
$strStatus = "Share ID Failed";
|
||||
$log->logError('Failed to update share ID in database for block ' . $aBlock['height']);
|
||||
if (!$block->setFinder($aBlock['id'], $iAccountId))
|
||||
$strStatus = "Finder Failed";
|
||||
$log->logError('Failed to update finder account ID in database for block ' . $aBlock['height']);
|
||||
if (!$block->setShares($aBlock['id'], $iRoundShares))
|
||||
$strStatus = "Shares Failed";
|
||||
$log->logError('Failed to update share count in database for block ' . $aBlock['height']);
|
||||
if ($config['block_bonus'] > 0 && !$transaction->addTransaction($iAccountId, $config['block_bonus'], 'Bonus', $aBlock['id'])) {
|
||||
$strStatus = "Bonus Failed";
|
||||
$log->logError('Failed to create Bonus transaction in database for user ' . $user->getUserName($iAccountId) . ' for block ' . $aBlock['height']);
|
||||
}
|
||||
|
||||
verbose(
|
||||
$log->logInfo(
|
||||
$aBlock['id'] . "\t\t"
|
||||
. $aBlock['height'] . "\t\t"
|
||||
. $aBlock['amount'] . "\t"
|
||||
. $iCurrentUpstreamId . "\t\t"
|
||||
. $iRoundShares . "\t"
|
||||
. "[$iAccountId] " . $user->getUserName($iAccountId) . "\t\t"
|
||||
. $strStatus
|
||||
. "\n"
|
||||
. "[$iAccountId] " . $user->getUserName($iAccountId) . "\t"
|
||||
. $share->share_type
|
||||
);
|
||||
|
||||
// Notify users
|
||||
@ -125,11 +123,13 @@ if (empty($aAllBlocks)) {
|
||||
$aMailData['subject'] = 'New Block';
|
||||
$aMailData['email'] = $user->getUserEmail($user->getUserName($aData['account_id']));
|
||||
$aMailData['shares'] = $iRoundShares;
|
||||
$notification->sendNotification($aData['account_id'], 'new_block', $aMailData);
|
||||
if (!$notification->sendNotification($aData['account_id'], 'new_block', $aMailData))
|
||||
$log->logError('Failed to notify user of new found block: ' . $user->getUserName($aData['account_id']));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
require_once('cron_end.inc.php');
|
||||
?>
|
||||
|
||||
1
cronjobs/logs/README.md
Normal file
1
cronjobs/logs/README.md
Normal file
@ -0,0 +1 @@
|
||||
Logging directory for cronjobs.
|
||||
@ -22,51 +22,49 @@ limitations under the License.
|
||||
// Include all settings and classes
|
||||
require_once('shared.inc.php');
|
||||
|
||||
verbose("Running system notifications\n");
|
||||
|
||||
verbose(" IDLE Worker Notifications ...");
|
||||
$log->logDebug(" IDLE Worker Notifications ...");
|
||||
// Find all IDLE workers
|
||||
$aWorkers = $worker->getAllIdleWorkers();
|
||||
if (empty($aWorkers)) {
|
||||
verbose(" no idle workers found\n");
|
||||
$log->logDebug(" no idle workers found\n");
|
||||
} else {
|
||||
verbose(" found " . count($aWorkers) . " IDLE workers\n");
|
||||
$log->logInfo(" found " . count($aWorkers) . " IDLE workers\n");
|
||||
foreach ($aWorkers as $aWorker) {
|
||||
$aData = $aWorker;
|
||||
$aData['username'] = $user->getUserName($aWorker['account_id']);
|
||||
$aData['subject'] = 'IDLE Worker : ' . $aWorker['username'];
|
||||
$aData['worker'] = $aWorker['username'];
|
||||
$aData['email'] = $user->getUserEmail($aData['username']);
|
||||
verbose(" " . $aWorker['username'] . "...");
|
||||
if (!$notification->sendNotification($aWorker['account_id'], 'idle_worker', $aData)) {
|
||||
verbose(" " . $notification->getError() . "\n");
|
||||
} else {
|
||||
verbose(" sent\n");
|
||||
}
|
||||
$log->logInfo(" " . $aWorker['username'] . "...");
|
||||
if (!$notification->sendNotification($aWorker['account_id'], 'idle_worker', $aData))
|
||||
$log->logError(" Failed sending notifications: " . $notification->getError() . "\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
verbose(" Reset IDLE Worker Notifications ...");
|
||||
$log->logDebug(" Reset IDLE Worker Notifications ...");
|
||||
// We notified, lets check which recovered
|
||||
$aNotifications = $notification->getAllActive('idle_worker');
|
||||
if (!empty($aNotifications)) {
|
||||
verbose(" found " . count($aNotifications) . " active notification(s)\n");
|
||||
$log->logInfo(" found " . count($aNotifications) . " active notification(s)\n");
|
||||
foreach ($aNotifications as $aNotification) {
|
||||
$aData = json_decode($aNotification['data'], true);
|
||||
$aWorker = $worker->getWorker($aData['id']);
|
||||
verbose(" " . $aWorker['username'] . " ...");
|
||||
$log->logInfo(" " . $aWorker['username'] . " ...");
|
||||
if ($aWorker['active'] == 1) {
|
||||
if ($notification->setInactive($aNotification['id'])) {
|
||||
verbose(" updated #" . $aNotification['id'] . " for " . $aWorker['username'] . " as inactive\n");
|
||||
$log->logInfo(" updated #" . $aNotification['id'] . " for " . $aWorker['username'] . " as inactive\n");
|
||||
} else {
|
||||
verbose(" failed to update #" . $aNotification['id'] . " for " . $aWorker['username'] . "\n");
|
||||
$log->logInfo(" failed to update #" . $aNotification['id'] . " for " . $aWorker['username'] . "\n");
|
||||
}
|
||||
} else {
|
||||
verbose(" still inactive\n");
|
||||
$log->logInfo(" still inactive\n");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
verbose(" no active IDLE worker notifications\n");
|
||||
$log->logDebug(" no active IDLE worker notifications\n");
|
||||
}
|
||||
|
||||
require_once('cron_end.inc.php');
|
||||
?>
|
||||
|
||||
187
cronjobs/pplns_payout.php
Executable file
187
cronjobs/pplns_payout.php
Executable file
@ -0,0 +1,187 @@
|
||||
#!/usr/bin/php
|
||||
<?php
|
||||
|
||||
/*
|
||||
|
||||
Copyright:: 2013, Sebastian Grewe
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
// Include all settings and classes
|
||||
require_once('shared.inc.php');
|
||||
|
||||
// Check if we are set as the payout system
|
||||
if ($config['payout_system'] != 'pplns') {
|
||||
$log->logInfo("Please activate this cron in configuration via payout_system = pplns");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Fetch all unaccounted blocks
|
||||
$aAllBlocks = $block->getAllUnaccounted('ASC');
|
||||
if (empty($aAllBlocks)) {
|
||||
$log->logDebug("No new unaccounted blocks found");
|
||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
||||
$monitoring->setStatus($cron_name . "_message", "message", "No new unaccounted blocks");
|
||||
$monitoring->setStatus($cron_name . "_status", "okerror", 0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
$count = 0;
|
||||
foreach ($aAllBlocks as $iIndex => $aBlock) {
|
||||
// We support some dynamic share targets but fall back to our fixed value
|
||||
// Re-calculate after each run due to re-targets in this loop
|
||||
if ($config['pplns']['shares']['type'] == 'blockavg' && $block->getBlockCount() > 0) {
|
||||
$pplns_target = round($block->getAvgBlockShares($config['pplns']['blockavg']['blockcount']));
|
||||
} else {
|
||||
$pplns_target = $config['pplns']['shares']['default'] ;
|
||||
}
|
||||
|
||||
if (!$aBlock['accounted']) {
|
||||
$iPreviousShareId = @$aAllBlocks[$iIndex - 1]['share_id'] ? $aAllBlocks[$iIndex - 1]['share_id'] : 0;
|
||||
$iCurrentUpstreamId = $aBlock['share_id'];
|
||||
if (!is_numeric($iCurrentUpstreamId)) {
|
||||
$log->logFatal("Block " . $aBlock['height'] . " has no share_id associated with it, not going to continue");
|
||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
||||
$monitoring->setStatus($cron_name . "_message", "message", "Block " . $aBlock['height'] . " has no share_id associated with it");
|
||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
||||
exit(1);
|
||||
}
|
||||
$iRoundShares = $share->getRoundShares($iPreviousShareId, $aBlock['share_id']);
|
||||
$iNewRoundShares = 0;
|
||||
$config['reward_type'] == 'block' ? $dReward = $aBlock['amount'] : $dReward = $config['reward'];
|
||||
$aRoundAccountShares = $share->getSharesForAccounts($iPreviousShareId, $aBlock['share_id']);
|
||||
|
||||
if ($iRoundShares >= $pplns_target) {
|
||||
$log->logDebug("Matching or exceeding PPLNS target of $pplns_target with $iRoundShares");
|
||||
$aAccountShares = $share->getSharesForAccounts($aBlock['share_id'] - $pplns_target, $aBlock['share_id']);
|
||||
if (empty($aAccountShares)) {
|
||||
$log->logFatal("No shares found for this block, aborted! Block Height : " . $aBlock['height']);
|
||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
||||
$monitoring->setStatus($cron_name . "_message", "message", "No shares found for this block: " . $aBlock['height']);
|
||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
$log->logDebug("Not able to match PPLNS target of $pplns_target with $iRoundShares");
|
||||
// We need to fill up with archived shares
|
||||
// Grab the full current round shares since we didn't match target
|
||||
$aAccountShares = $aRoundAccountShares;
|
||||
if (empty($aAccountShares)) {
|
||||
$log->logFatal("No shares found for this block, aborted! Block height: " . $aBlock['height']);
|
||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
||||
$monitoring->setStatus($cron_name . "_message", "message", "No shares found for this block: " . $aBlock['height']);
|
||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Grab only the most recent shares from Archive that fill the missing shares
|
||||
$log->logInfo('Fetching ' . ($pplns_target - $iRoundShares) . ' additional shares from archive');
|
||||
if (!$aArchiveShares = $share->getArchiveShares($pplns_target - $iRoundShares)) {
|
||||
$log->logError('Failed to fetch shares from archive, setting target to round total');
|
||||
$pplns_target = $iRoundShares;
|
||||
} else {
|
||||
// Add archived shares to users current shares, if we have any in archive
|
||||
if (is_array($aArchiveShares)) {
|
||||
$log->logDebug('Found shares in archive to match PPLNS target, calculating per-user shares');
|
||||
foreach($aAccountShares as $key => $aData) {
|
||||
if (array_key_exists($aData['username'], $aArchiveShares)) {
|
||||
$log->logDebug('Found user ' . $aData['username'] . ' in archived shares');
|
||||
$log->logDebug(' valid : ' . $aAccountShares[$key]['valid'] . ' + ' . $aArchiveShares[$aData['username']]['valid'] . ' = ' . ($aAccountShares[$key]['valid'] + $aArchiveShares[$aData['username']]['valid']) );
|
||||
$log->logDebug(' invalid : ' . $aAccountShares[$key]['invalid'] . ' + ' . $aArchiveShares[$aData['username']]['invalid'] . ' = ' . ($aAccountShares[$key]['invalid'] + $aArchiveShares[$aData['username']]['invalid']) );
|
||||
$aAccountShares[$key]['valid'] += $aArchiveShares[$aData['username']]['valid'];
|
||||
$aAccountShares[$key]['invalid'] += $aArchiveShares[$aData['username']]['invalid'];
|
||||
}
|
||||
}
|
||||
}
|
||||
// We tried to fill up to PPLNS target, now we need to check the actual shares to properly payout users
|
||||
foreach($aAccountShares as $key => $aData) {
|
||||
$iNewRoundShares += $aData['valid'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We filled from archive but still are not able to match PPLNS target, re-adjust
|
||||
if ($iRoundShares < $iNewRoundShares) {
|
||||
$log->logInfo('Adjusting round target to ' . $iNewRoundShares);
|
||||
$iRoundShares = $iNewRoundShares;
|
||||
}
|
||||
|
||||
// Table header for account shares
|
||||
$log->logInfo("ID\tUsername\tValid\tInvalid\tPercentage\tPayout\t\tDonation\tFee");
|
||||
|
||||
// Loop through all accounts that have found shares for this round
|
||||
foreach ($aAccountShares as $key => $aData) {
|
||||
// Payout based on PPLNS target shares, proportional payout for all users
|
||||
$aData['percentage'] = number_format(round(( 100 / $pplns_target) * $aData['valid'], 8), 8);
|
||||
$aData['payout'] = number_format(round(( $aData['percentage'] / 100 ) * $dReward, 8), 8);
|
||||
// Defaults
|
||||
$aData['fee' ] = 0;
|
||||
$aData['donation'] = 0;
|
||||
|
||||
if ($config['fees'] > 0)
|
||||
$aData['fee'] = number_format(round($config['fees'] / 100 * $aData['payout'], 8), 8);
|
||||
// Calculate donation amount, fees not included
|
||||
$aData['donation'] = number_format(round($user->getDonatePercent($user->getUserId($aData['username'])) / 100 * ( $aData['payout'] - $aData['fee']), 8), 8);
|
||||
|
||||
// Verbose output of this users calculations
|
||||
$log->logInfo($aData['id'] . "\t" .
|
||||
$aData['username'] . "\t" .
|
||||
$aData['valid'] . "\t" .
|
||||
$aData['invalid'] . "\t" .
|
||||
$aData['percentage'] . "\t" .
|
||||
$aData['payout'] . "\t" .
|
||||
$aData['donation'] . "\t" .
|
||||
$aData['fee']);
|
||||
|
||||
// Add full round share statistics, not just PPLNS
|
||||
foreach ($aRoundAccountShares as $key => $aRoundData) {
|
||||
if ($aRoundData['username'] == $aData['username'])
|
||||
if (!$statistics->updateShareStatistics($aRoundData, $aBlock['id']))
|
||||
$log->logError('Failed to update share statistics for ' . $aData['username']);
|
||||
}
|
||||
// Add new credit transaction
|
||||
if (!$transaction->addTransaction($aData['id'], $aData['payout'], 'Credit', $aBlock['id']))
|
||||
$log->logFatal('Failed to insert new Credit transaction to database for ' . $aData['username']);
|
||||
// Add new fee debit for this block
|
||||
if ($aData['fee'] > 0 && $config['fees'] > 0)
|
||||
if (!$transaction->addTransaction($aData['id'], $aData['fee'], 'Fee', $aBlock['id']))
|
||||
$log->logFatal('Failed to insert new Fee transaction to database for ' . $aData['username']);
|
||||
// Add new donation debit
|
||||
if ($aData['donation'] > 0)
|
||||
if (!$transaction->addTransaction($aData['id'], $aData['donation'], 'Donation', $aBlock['id']))
|
||||
$log->logFatal('Failed to insert new Donation transaction to database for ' . $aData['username']);
|
||||
}
|
||||
|
||||
// Move counted shares to archive before this blockhash upstream share
|
||||
if (!$share->moveArchive($iCurrentUpstreamId, $aBlock['id'], $iPreviousShareId))
|
||||
$log->logError('Failed to copy shares to archive table');
|
||||
// Delete all accounted shares
|
||||
if (!$share->deleteAccountedShares($iCurrentUpstreamId, $iPreviousShareId)) {
|
||||
$log->logFatal("Failed to delete accounted shares from $iPreviousShareId to $iCurrentUpstreamId, aborting!");
|
||||
exit(1);
|
||||
}
|
||||
// Mark this block as accounted for
|
||||
if (!$block->setAccounted($aBlock['id'])) {
|
||||
$log->logFatal("Failed to mark block as accounted! Aborting!");
|
||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
||||
$monitoring->setStatus($cron_name . "_message", "message", "Failed to mark block " . $aBlock['height'] . " as accounted");
|
||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
require_once('cron_end.inc.php');
|
||||
?>
|
||||
@ -25,7 +25,7 @@ require_once('shared.inc.php');
|
||||
|
||||
// Check if we are set as the payout system
|
||||
if ($config['payout_system'] != 'pps') {
|
||||
verbose("Please activate this cron in configuration via payout_system = pps\n");
|
||||
$log->logInfo("Please activate this cron in configuration via payout_system = pps\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@ -35,13 +35,16 @@ if ( $bitcoin->can_connect() === true ){
|
||||
if (is_array($dDifficulty) && array_key_exists('proof-of-work', $dDifficulty))
|
||||
$dDifficulty = $dDifficulty['proof-of-work'];
|
||||
} else {
|
||||
verbose("Aborted: " . $bitcoin->can_connect() . "\n");
|
||||
$log->logFatal("Aborted: " . $bitcoin->can_connect() . "\n");
|
||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
||||
$monitoring->setStatus($cron_name . "_message", "message", "Unable to connect to RPC server");
|
||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Value per share calculation
|
||||
if ($config['reward_type'] != 'block') {
|
||||
$pps_value = number_format(round($config['reward'] / (pow(2,32) * $dDifficulty) * pow(2, $config['difficulty']), 12) ,12);
|
||||
$pps_value = number_format(round($config['reward'] / (pow(2,32) * $dDifficulty) * pow(2, $config['difficulty']), 12) ,12);
|
||||
} else {
|
||||
// Try to find the last block value and use that for future payouts, revert to fixed reward if none found
|
||||
if ($aLastBlock = $block->getLast()) {
|
||||
@ -58,7 +61,7 @@ $iLastShareId = $share->getLastInsertedShareId();
|
||||
// Check for all new shares, we start one higher as our last accounted share to avoid duplicates
|
||||
$aAccountShares = $share->getSharesForAccounts($iPreviousShareId + 1, $iLastShareId);
|
||||
|
||||
verbose("ID\tUsername\tInvalid\tValid\t\tPPS Value\t\tPayout\t\tDonation\tFee\t\tStatus\n");
|
||||
$log->logInfo("ID\tUsername\tInvalid\tValid\t\tPPS Value\t\tPayout\t\tDonation\tFee");
|
||||
|
||||
foreach ($aAccountShares as $aData) {
|
||||
// Take our valid shares and multiply by per share value
|
||||
@ -74,65 +77,76 @@ foreach ($aAccountShares as $aData) {
|
||||
// Calculate donation amount
|
||||
$aData['donation'] = number_format(round($user->getDonatePercent($user->getUserId($aData['username'])) / 100 * ( $aData['payout'] - $aData['fee']), 8), 8);
|
||||
|
||||
verbose($aData['id'] . "\t" .
|
||||
$log->logInfo($aData['id'] . "\t" .
|
||||
$aData['username'] . "\t" .
|
||||
$aData['invalid'] . "\t" .
|
||||
$aData['valid'] . "\t*\t" .
|
||||
$pps_value . "\t=\t" .
|
||||
$aData['payout'] . "\t" .
|
||||
$aData['donation'] . "\t" .
|
||||
$aData['fee'] . "\t");
|
||||
$aData['fee']);
|
||||
|
||||
$strStatus = "OK";
|
||||
// Add new credit transaction
|
||||
if (!$transaction->addTransaction($aData['id'], $aData['payout'], 'Credit_PPS'))
|
||||
$strStatus = "Transaction Failed";
|
||||
$log->logError('Failed to add Credit_PPS transaction in database');
|
||||
// Add new fee debit for this block
|
||||
if ($aData['fee'] > 0 && $config['fees'] > 0)
|
||||
if (!$transaction->addTransaction($aData['id'], $aData['fee'], 'Fee_PPS'))
|
||||
$strStatus = "Fee Failed";
|
||||
$log->logError('Failed to add Fee_PPS transaction in database');
|
||||
// Add new donation debit
|
||||
if ($aData['donation'] > 0)
|
||||
if (!$transaction->addTransaction($aData['id'], $aData['donation'], 'Donation_PPS'))
|
||||
$strStatus = "Donation Failed";
|
||||
verbose($strStatus . "\n");
|
||||
$log->logError('Failed to add Donation_PPS transaction in database');
|
||||
}
|
||||
|
||||
// Store our last inserted ID for the next run
|
||||
$setting->setValue('pps_last_share_id', $iLastShareId);
|
||||
|
||||
verbose("\n\n------------------------------------------------------------------------------------\n\n");
|
||||
|
||||
// Fetch all unaccounted blocks
|
||||
$aAllBlocks = $block->getAllUnaccounted('ASC');
|
||||
if (empty($aAllBlocks)) {
|
||||
verbose("No new unaccounted blocks found\n");
|
||||
$log->logDebug("No new unaccounted blocks found");
|
||||
}
|
||||
|
||||
// Go through blocks and archive/delete shares that have been accounted for
|
||||
foreach ($aAllBlocks as $iIndex => $aBlock) {
|
||||
// If we are running through more than one block, check for previous share ID
|
||||
$iLastBlockShare = @$aAllBlocks[$iIndex - 1]['share_id'] ? @$aAllBlocks[$iIndex - 1]['share_id'] : 0;
|
||||
if (!is_numeric($aBlock['share_id'])) {
|
||||
$log->logFatal("Block " . $aBlock['height'] . " has no share_id associated with it, not going to continue");
|
||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
||||
$monitoring->setStatus($cron_name . "_message", "message", "Block " . $aBlock['height'] . " has no share_id associated with it");
|
||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
||||
exit(1);
|
||||
}
|
||||
// Per account statistics
|
||||
$aAccountShares = $share->getSharesForAccounts(@$iLastBlockShare, $aBlock['share_id']);
|
||||
foreach ($aAccountShares as $key => $aData) {
|
||||
if (!$statistics->updateShareStatistics($aData, $aBlock['id']))
|
||||
verbose("Failed to update stats for this block on : " . $aData['username'] . "\n");
|
||||
$log->logError("Failed to update stats for this block on : " . $aData['username']);
|
||||
}
|
||||
// Move shares to archive
|
||||
if ($config['archive_shares'] && $aBlock['share_id'] < $iLastShareId) {
|
||||
if ($aBlock['share_id'] < $iLastShareId) {
|
||||
if (!$share->moveArchive($aBlock['share_id'], $aBlock['id'], @$iLastBlockShare))
|
||||
verbose("Archving failed\n");
|
||||
$log->logError("Archving failed");
|
||||
}
|
||||
// Delete shares
|
||||
if ($aBlock['share_id'] < $iLastShareId && !$share->deleteAccountedShares($aBlock['share_id'], $iLastBlockShare)) {
|
||||
verbose("\nERROR : Failed to delete accounted shares from " . $aBlock['share_id'] . " to " . $iLastBlockShare . ", aborting!\n");
|
||||
$log->logFatal("Failed to delete accounted shares from " . $aBlock['share_id'] . " to " . $iLastBlockShare . ", aborting!");
|
||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
||||
$monitoring->setStatus($cron_name . "_message", "message", "Failed to delete accounted shares from " . $aBlock['share_id'] . " to " . $iLastBlockShare);
|
||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
||||
exit(1);
|
||||
}
|
||||
// Mark this block as accounted for
|
||||
if (!$block->setAccounted($aBlock['id'])) {
|
||||
verbose("\nERROR : Failed to mark block as accounted! Aborting!\n");
|
||||
$log->logFatal("Failed to mark block as accounted! Aborting!");
|
||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
||||
$monitoring->setStatus($cron_name . "_message", "message", "Failed to mark block " . $aBlock['height'] . " as accounted");
|
||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
require_once('cron_end.inc.php');
|
||||
?>
|
||||
|
||||
@ -24,18 +24,23 @@ require_once('shared.inc.php');
|
||||
|
||||
// Check if we are set as the payout system
|
||||
if ($config['payout_system'] != 'prop') {
|
||||
verbose("Please activate this cron in configuration via payout_system = prop\n");
|
||||
$log->logInfo("Please activate this cron in configuration via payout_system = prop");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Fetch all unaccounted blocks
|
||||
$aAllBlocks = $block->getAllUnaccounted('ASC');
|
||||
if (empty($aAllBlocks)) {
|
||||
verbose("No new unaccounted blocks found\n");
|
||||
$log->logDebug('No new unaccounted blocks found in database');
|
||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
||||
$monitoring->setStatus($cron_name . "_message", "message", "No new unaccounted blocks");
|
||||
$monitoring->setStatus($cron_name . "_status", "okerror", 0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
$count = 0;
|
||||
// Table header for account shares
|
||||
$log->logInfo("ID\tUsername\tValid\tInvalid\tPercentage\tPayout\t\tDonation\tFee");
|
||||
foreach ($aAllBlocks as $iIndex => $aBlock) {
|
||||
if (!$aBlock['accounted']) {
|
||||
$iPreviousShareId = @$aAllBlocks[$iIndex - 1]['share_id'] ? $aAllBlocks[$iIndex - 1]['share_id'] : 0;
|
||||
@ -45,14 +50,13 @@ foreach ($aAllBlocks as $iIndex => $aBlock) {
|
||||
$config['reward_type'] == 'block' ? $dReward = $aBlock['amount'] : $dReward = $config['reward'];
|
||||
|
||||
if (empty($aAccountShares)) {
|
||||
verbose("\nNo shares found for this block\n\n");
|
||||
sleep(2);
|
||||
continue;
|
||||
$log->logFatal('No shares found for this block, aborted: ' . $aBlock['height']);
|
||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
||||
$monitoring->setStatus($cron_name . "_message", "message", "No shares found for this block, aborted: " . $aBlock['height']);
|
||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Table header for account shares
|
||||
verbose("ID\tUsername\tValid\tInvalid\tPercentage\tPayout\t\tDonation\tFee\t\tStatus\n");
|
||||
|
||||
// Loop through all accounts that have found shares for this round
|
||||
foreach ($aAccountShares as $key => $aData) {
|
||||
// Payout based on shares, PPS system
|
||||
@ -68,45 +72,52 @@ foreach ($aAllBlocks as $iIndex => $aBlock) {
|
||||
$aData['donation'] = number_format(round($user->getDonatePercent($user->getUserId($aData['username'])) / 100 * ( $aData['payout'] - $aData['fee']), 8), 8);
|
||||
|
||||
// Verbose output of this users calculations
|
||||
verbose($aData['id'] . "\t" .
|
||||
$aData['username'] . "\t" .
|
||||
$aData['valid'] . "\t" .
|
||||
$aData['invalid'] . "\t" .
|
||||
$aData['percentage'] . "\t" .
|
||||
$aData['payout'] . "\t" .
|
||||
$aData['donation'] . "\t" .
|
||||
$aData['fee'] . "\t");
|
||||
$log->logInfo($aData['id'] . "\t" .
|
||||
$aData['username'] . "\t" .
|
||||
$aData['valid'] . "\t" .
|
||||
$aData['invalid'] . "\t" .
|
||||
$aData['percentage'] . "\t" .
|
||||
$aData['payout'] . "\t" .
|
||||
$aData['donation'] . "\t" .
|
||||
$aData['fee']);
|
||||
|
||||
$strStatus = "OK";
|
||||
// Update user share statistics
|
||||
if (!$statistics->updateShareStatistics($aData, $aBlock['id']))
|
||||
$strStatus = "Stats Failed";
|
||||
$log->logFatal('Failed to update share statistics for ' . $aData['username']);
|
||||
// Add new credit transaction
|
||||
if (!$transaction->addTransaction($aData['id'], $aData['payout'], 'Credit', $aBlock['id']))
|
||||
$strStatus = "Transaction Failed";
|
||||
$log->logFatal('Failed to insert new Credit transaction to database for ' . $aData['username']);
|
||||
// Add new fee debit for this block
|
||||
if ($aData['fee'] > 0 && $config['fees'] > 0)
|
||||
if (!$transaction->addTransaction($aData['id'], $aData['fee'], 'Fee', $aBlock['id']))
|
||||
$strStatus = "Fee Failed";
|
||||
$log->logFatal('Failed to insert new Fee transaction to database for ' . $aData['username']);
|
||||
// Add new donation debit
|
||||
if ($aData['donation'] > 0)
|
||||
if (!$transaction->addTransaction($aData['id'], $aData['donation'], 'Donation', $aBlock['id']))
|
||||
$strStatus = "Donation Failed";
|
||||
verbose("\t$strStatus\n");
|
||||
$log->logFatal('Failed to insert new Donation transaction to database for ' . $aData['username']);
|
||||
}
|
||||
|
||||
// Move counted shares to archive before this blockhash upstream share
|
||||
if ($config['archive_shares']) $share->moveArchive($iCurrentUpstreamId, $aBlock['id'], $iPreviousShareId);
|
||||
if (!$share->moveArchive($iCurrentUpstreamId, $aBlock['id'], $iPreviousShareId))
|
||||
$log->logError('Failed to copy shares to archive');
|
||||
// Delete all accounted shares
|
||||
if (!$share->deleteAccountedShares($iCurrentUpstreamId, $iPreviousShareId)) {
|
||||
verbose("\nERROR : Failed to delete accounted shares from $iPreviousShareId to $iCurrentUpstreamId, aborting!\n");
|
||||
$log->logFatal('Failed to delete accounted shares from ' . $iPreviousShareId . ' to ' . $iCurrentUpstreamId . ', aborted');
|
||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
||||
$monitoring->setStatus($cron_name . "_message", "message", "Failed to delete accounted shares from " . $iPreviousShareId . " to " . $iCurrentUpstreamId);
|
||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
||||
exit(1);
|
||||
}
|
||||
// Mark this block as accounted for
|
||||
if (!$block->setAccounted($aBlock['id'])) {
|
||||
verbose("\nERROR : Failed to mark block as accounted! Aborting!\n");
|
||||
$log->logFatal('Failed to mark block as accounted! Aborted.');
|
||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
||||
$monitoring->setStatus($cron_name . "_message", "message", "Failed to mark block " . $aBlock['height'] . " as accounted");
|
||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
verbose("------------------------------------------------------------------------\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
require_once('cron_end.inc.php');
|
||||
?>
|
||||
|
||||
@ -12,14 +12,8 @@ PHP_BIN=$( which php )
|
||||
# Path to PID file, needs to be writable by user running this
|
||||
PIDFILE='/tmp/mmcfe-ng-cron.pid'
|
||||
|
||||
# Location of our cronjobs, assume current directory
|
||||
CRONHOME='.'
|
||||
|
||||
# List of cruns to execute
|
||||
CRONS="findblock.php proportional_payout.php pps_payout.php blockupdate.php auto_payout.php tickerupdate.php notifications.php statistics.php"
|
||||
|
||||
# Additional arguments to pass to cronjobs
|
||||
CRONARGS="-v"
|
||||
CRONS="findblock.php proportional_payout.php pplns_payout.php pps_payout.php blockupdate.php auto_payout.php tickerupdate.php notifications.php statistics.php archive_cleanup.php"
|
||||
|
||||
# Output additional runtime information
|
||||
VERBOSE="0"
|
||||
@ -30,6 +24,29 @@ VERBOSE="0"
|
||||
# #
|
||||
################################################################
|
||||
|
||||
# Overwrite some settings via command line arguments
|
||||
while getopts "hvp:" opt; do
|
||||
case "$opt" in
|
||||
h|\?)
|
||||
echo "Usage: $0 [-v] [-p PHP_BINARY]";
|
||||
exit 0
|
||||
;;
|
||||
v) VERBOSE=1 ;;
|
||||
p) PHP_BIN=$OPTARG ;;
|
||||
:)
|
||||
echo "Option -$OPTARG requires an argument." >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Find scripts path
|
||||
if [[ -L $0 ]]; then
|
||||
CRONHOME=$( dirname $( readlink $0 ) )
|
||||
else
|
||||
CRONHOME=$( dirname $0 )
|
||||
fi
|
||||
|
||||
# Change working director to CRONHOME
|
||||
if ! cd $CRONHOME 2>/dev/null; then
|
||||
echo "Unable to change to working directory \$CRONHOME: $CRONHOME"
|
||||
@ -66,8 +83,8 @@ fi
|
||||
echo $PID > $PIDFILE
|
||||
|
||||
for cron in $CRONS; do
|
||||
[[ $VERBOSE == 1 ]] && echo "Running $cron, see output below for details"
|
||||
$PHP_BIN $cron $CRONARGS
|
||||
[[ $VERBOSE == 1 ]] && echo "Running $cron, check logfile for details"
|
||||
$PHP_BIN $cron
|
||||
done
|
||||
|
||||
# Remove pidfile
|
||||
|
||||
@ -22,6 +22,13 @@ limitations under the License.
|
||||
// We need to find our include files so set this properly
|
||||
define("BASEPATH", "../public/");
|
||||
|
||||
|
||||
/*****************************************************
|
||||
* No need to change beyond this point *
|
||||
*****************************************************/
|
||||
// Our cron name
|
||||
$cron_name = basename($_SERVER['PHP_SELF'], '.php');
|
||||
|
||||
// Our security check
|
||||
define("SECURITY", 1);
|
||||
|
||||
@ -31,16 +38,15 @@ require_once(BASEPATH . 'include/config/global.inc.php');
|
||||
// We include all needed files here, even though our templates could load them themself
|
||||
require_once(INCLUDE_DIR . '/autoloader.inc.php');
|
||||
|
||||
// Parse command line
|
||||
$options = getopt("v");
|
||||
if (array_key_exists('v', $options)) {
|
||||
define("VERBOSE", true);
|
||||
} else {
|
||||
define("VERBOSE", false);
|
||||
}
|
||||
// Load 3rd party logging library for running crons
|
||||
$log = new KLogger ( 'logs/' . $cron_name . '.txt' , KLogger::INFO );
|
||||
$log->LogDebug('Starting ' . $cron_name);
|
||||
|
||||
// Command line cron functions only
|
||||
function verbose($msg) {
|
||||
if (VERBOSE) echo $msg;
|
||||
}
|
||||
// Load the start time for later runtime calculations for monitoring
|
||||
$cron_start[$cron_name] = microtime(true);
|
||||
|
||||
// Mark cron as running for monitoring
|
||||
$log->logDebug('Marking cronjob as running for monitoring');
|
||||
$monitoring->setStatus($cron_name . '_active', 'yesno', 1);
|
||||
$monitoring->setStatus($cron_name . '_starttime', 'date', time());
|
||||
?>
|
||||
|
||||
@ -25,44 +25,38 @@ require_once('shared.inc.php');
|
||||
// Fetch all cachable values but disable fetching from cache
|
||||
$statistics->setGetCache(false);
|
||||
|
||||
// Verbose output
|
||||
verbose("Running statistical cache updates\n");
|
||||
|
||||
// Since fetching from cache is disabled, overwrite our stats
|
||||
verbose(" getRoundShares ...");
|
||||
$start = microtime(true);
|
||||
if (!$statistics->getRoundShares())
|
||||
verbose(" update failed");
|
||||
verbose(" " . number_format(microtime(true) - $start, 2) . " seconds\n");
|
||||
verbose(" getTopContributors shares ...");
|
||||
$log->logError("getRoundShares update failed");
|
||||
$log->logInfo("getRoundShares update " . number_format(microtime(true) - $start, 2) . " seconds");
|
||||
$start = microtime(true);
|
||||
if (!$statistics->getTopContributors('shares'))
|
||||
verbose(" update failed");
|
||||
verbose(" " . number_format(microtime(true) - $start, 2) . " seconds\n");
|
||||
verbose(" getTopContributors hashes ...");
|
||||
$log->logError("getTopContributors shares update failed");
|
||||
$log->logInfo("getTopContributors shares " . number_format(microtime(true) - $start, 2) . " seconds");
|
||||
$start = microtime(true);
|
||||
if (!$statistics->getTopContributors('hashes'))
|
||||
verbose(" update failed");
|
||||
verbose(" " . number_format(microtime(true) - $start, 2) . " seconds\n");
|
||||
verbose(" getCurrentHashrate ...");
|
||||
$log->logError("getTopContributors hashes update failed");
|
||||
$log->logInfo("getTopContributors hashes " . number_format(microtime(true) - $start, 2) . " seconds");
|
||||
$start = microtime(true);
|
||||
if (!$statistics->getCurrentHashrate())
|
||||
verbose(" update failed");
|
||||
verbose(" " . number_format(microtime(true) - $start, 2) . " seconds\n");
|
||||
$log->logError("getCurrentHashrate update failed");
|
||||
$log->logInfo("getCurrentHashrate " . number_format(microtime(true) - $start, 2) . " seconds");
|
||||
/*
|
||||
// Admin specific statistics, we cache the global query due to slowness
|
||||
verbose(" getAllUserStats ...");
|
||||
$start = microtime(true);
|
||||
if (!$statistics->getAllUserStats('%'))
|
||||
verbose(" update failed");
|
||||
verbose(" " . number_format(microtime(true) - $start, 2) . " seconds\n");
|
||||
$log->logError("getAllUserStats update failed");
|
||||
$log->logInfo("getAllUserStats " . number_format(microtime(true) - $start, 2) . " seconds");
|
||||
*/
|
||||
|
||||
// Per user share statistics based on all shares submitted
|
||||
verbose(" getAllUserShares ...");
|
||||
$start = microtime(true);
|
||||
$aUserShares = $statistics->getAllUserShares();
|
||||
verbose(" " . number_format(microtime(true) - $start, 2) . " seconds");
|
||||
$log->logInfo("getAllUserShares " . number_format(microtime(true) - $start, 2) . " seconds");
|
||||
foreach ($aUserShares as $aShares) {
|
||||
$memcache->setCache('getUserShares'. $aShares['id'], $aShares);
|
||||
}
|
||||
verbose("\n");
|
||||
|
||||
require_once('cron_end.inc.php');
|
||||
?>
|
||||
|
||||
@ -25,14 +25,13 @@ require_once('shared.inc.php');
|
||||
// Include additional file not set in autoloader
|
||||
require_once(CLASS_DIR . '/tools.class.php');
|
||||
|
||||
verbose("Running scheduled updates\n");
|
||||
verbose(" Price API Call ... ");
|
||||
if ($price = $tools->getPrice()) {
|
||||
verbose("found $price as price\n");
|
||||
$log->logInfo("Price update: found $price as price");
|
||||
if (!$setting->setValue('price', $price))
|
||||
verbose("unable to update value in settings table\n");
|
||||
$log->logError("unable to update value in settings table");
|
||||
} else {
|
||||
verbose("failed to fetch API data: " . $tools->getError() . "\n");
|
||||
$log->logFatal("failed to fetch API data: " . $tools->getError());
|
||||
}
|
||||
|
||||
require_once('cron_end.inc.php');
|
||||
?>
|
||||
|
||||
@ -17,18 +17,25 @@ 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 . '/lib/KLogger.php');
|
||||
require_once(INCLUDE_DIR . '/database.inc.php');
|
||||
require_once(INCLUDE_DIR . '/smarty.inc.php');
|
||||
// Load classes that need the above as dependencies
|
||||
require_once(CLASS_DIR . '/base.class.php');
|
||||
require_once(CLASS_DIR . '/api.class.php');
|
||||
require_once(CLASS_DIR . '/mail.class.php');
|
||||
require_once(CLASS_DIR . '/tokentype.class.php');
|
||||
require_once(CLASS_DIR . '/token.class.php');
|
||||
require_once(CLASS_DIR . '/block.class.php');
|
||||
require_once(CLASS_DIR . '/setting.class.php');
|
||||
require_once(CLASS_DIR . '/monitoring.class.php');
|
||||
require_once(CLASS_DIR . '/user.class.php');
|
||||
require_once(CLASS_DIR . '/invitation.class.php');
|
||||
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 . '/mail.class.php');
|
||||
require_once(CLASS_DIR . '/notification.class.php');
|
||||
require_once(CLASS_DIR . '/news.class.php');
|
||||
require_once(INCLUDE_DIR . '/lib/Michelf/Markdown.php');
|
||||
require_once(INCLUDE_DIR . '/lib/scrypt.php');
|
||||
|
||||
23
public/include/classes/api.class.php
Normal file
23
public/include/classes/api.class.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
// Make sure we are called from index.php
|
||||
if (!defined('SECURITY')) die('Hacking attempt');
|
||||
|
||||
/**
|
||||
* Helper class for our API
|
||||
**/
|
||||
class Api extends Base {
|
||||
function isActive($error=true) {
|
||||
if (!$this->config['website']['api']['disabled']) {
|
||||
return true;
|
||||
} else {
|
||||
if ($error == true) {
|
||||
header('HTTP/1.1 501 Not implemented');
|
||||
die('501 Not implemented');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$api = new Api();
|
||||
$api->setConfig($config);
|
||||
@ -15,6 +15,9 @@ class Base {
|
||||
public function setMysql($mysqli) {
|
||||
$this->mysqli = $mysqli;
|
||||
}
|
||||
public function setMail($mail) {
|
||||
$this->mail = $mail;
|
||||
}
|
||||
public function setSmarty($smarty) {
|
||||
$this->smarty = $smarty;
|
||||
}
|
||||
@ -24,6 +27,12 @@ class Base {
|
||||
public function setConfig($config) {
|
||||
$this->config = $config;
|
||||
}
|
||||
public function setToken($token) {
|
||||
$this->token = $token;
|
||||
}
|
||||
public function setTokenType($tokentype) {
|
||||
$this->tokentype = $tokentype;
|
||||
}
|
||||
public function setErrorMessage($msg) {
|
||||
$this->sError = $msg;
|
||||
}
|
||||
|
||||
@ -43,6 +43,18 @@ class Block {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specific block, by block height
|
||||
* @param height int Block Height
|
||||
* @return data array Block information from DB
|
||||
**/
|
||||
public function getBlock($height) {
|
||||
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE height = ? LIMIT 1");
|
||||
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $height) && $stmt->execute() && $result = $stmt->get_result())
|
||||
return $result->fetch_assoc();
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get our last, highest share ID inserted for a block
|
||||
* @param none
|
||||
@ -55,6 +67,18 @@ class Block {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch all blocks without a share ID
|
||||
* @param order string Sort order, default ASC
|
||||
* @return data array Array with database fields as keys
|
||||
**/
|
||||
public function getAllUnsetShareId($order='ASC') {
|
||||
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE ISNULL(share_id) ORDER BY height $order");
|
||||
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
|
||||
return $result->fetch_all(MYSQLI_ASSOC);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch all unaccounted blocks
|
||||
* @param order string Sort order, default ASC
|
||||
@ -62,12 +86,32 @@ class Block {
|
||||
**/
|
||||
public function getAllUnaccounted($order='ASC') {
|
||||
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE accounted = 0 ORDER BY height $order");
|
||||
if ($this->checkStmt($stmt)) {
|
||||
$stmt->execute();
|
||||
$result = $stmt->get_result();
|
||||
$stmt->close();
|
||||
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
|
||||
return $result->fetch_all(MYSQLI_ASSOC);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total amount of blocks in our table
|
||||
* @param noone
|
||||
* @return data int Count of rows
|
||||
**/
|
||||
public function getBlockCount() {
|
||||
$stmt = $this->mysqli->prepare("SELECT COUNT(id) AS blocks FROM $this->table");
|
||||
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
|
||||
return (int)$result->fetch_object()->blocks;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch our average share count for the past N blocks
|
||||
* @param limit int Maximum blocks to check
|
||||
* @return data float Float value of average shares
|
||||
**/
|
||||
public function getAvgBlockShares($limit=1) {
|
||||
$stmt = $this->mysqli->prepare("SELECT AVG(x.shares) AS average FROM (SELECT shares FROM $this->table ORDER BY height DESC LIMIT ?) AS x");
|
||||
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $limit) && $stmt->execute() && $result = $stmt->get_result())
|
||||
return (float)$result->fetch_object()->average;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -77,14 +121,9 @@ class Block {
|
||||
* @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)) {
|
||||
$stmt->bind_param("i", $confirmations);
|
||||
$stmt->execute();
|
||||
$result = $stmt->get_result();
|
||||
$stmt->close();
|
||||
$stmt = $this->mysqli->prepare("SELECT id, height, blockhash, confirmations FROM $this->table WHERE confirmations < ? AND confirmations > -1");
|
||||
if ($this->checkStmt($stmt) && $stmt->bind_param("i", $confirmations) && $stmt->execute() && $result = $stmt->get_result())
|
||||
return $result->fetch_all(MYSQLI_ASSOC);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
146
public/include/classes/invitation.class.php
Normal file
146
public/include/classes/invitation.class.php
Normal file
@ -0,0 +1,146 @@
|
||||
<?php
|
||||
|
||||
// Make sure we are called from index.php
|
||||
if (!defined('SECURITY')) die('Hacking attempt');
|
||||
|
||||
class Invitation extends Base {
|
||||
var $table = 'invitations';
|
||||
|
||||
/**
|
||||
* Fetch invitations for one account
|
||||
* @param account_id int Account ID
|
||||
* @return mixed Array on success, bool on failure
|
||||
**/
|
||||
public function getInvitations($account_id) {
|
||||
$this->debug->append("STA " . __METHOD__, 4);
|
||||
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE account_id = ?");
|
||||
if ($stmt && $stmt->bind_param('i', $account_id) && $stmt->execute() && $result = $stmt->get_result())
|
||||
return $result->fetch_all(MYSQLI_ASSOC);
|
||||
$this->setErrorMessage('Unable to fetch invitiations send from your account');
|
||||
$this->debug->append('Failed to fetch invitations from database: ' . $this->mysqli->errro);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count invitations sent by an account_id
|
||||
* @param account_id integer Account ID
|
||||
* @return mixes Integer on success, boolean on failure
|
||||
**/
|
||||
public function getCountInvitations($account_id) {
|
||||
$this->debug->append("STA " . __METHOD__, 4);
|
||||
$stmt = $this->mysqli->prepare("SELECT count(id) AS total FROM $this->table WHERE account_id = ?");
|
||||
if ($stmt && $stmt->bind_param('i', $account_id) && $stmt->execute() && $stmt->bind_result($total) && $stmt->fetch())
|
||||
return $total;
|
||||
$this->setErrorMessage('Unable to fetch invitiations send from your account');
|
||||
$this->debug->append('Failed to fetch invitations from database: ' . $this->mysqli->errro);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specific invitation by email address
|
||||
* Used to ensure no invitation was already sent
|
||||
* @param strEmail string Email address to check for
|
||||
* @return bool boolean true of ralse
|
||||
**/
|
||||
public function getByEmail($strEmail) {
|
||||
$this->debug->append("STA " . __METHOD__, 4);
|
||||
return $this->getSingle($strEmail, 'id', 'email', 's');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specific token by token ID
|
||||
* Used to match an invitation against a token
|
||||
* @param token_id integer Token ID stored in invitation
|
||||
* @return data mixed Invitation ID on success, false on error
|
||||
**/
|
||||
public function getByTokenId($token_id) {
|
||||
$this->debug->append("STA " . __METHOD__, 4);
|
||||
return $this->getSingle($token_id, 'id', 'token_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an invitation as activated by the invitee
|
||||
* @param token_id integer Token to activate
|
||||
* @return bool boolean true or false
|
||||
**/
|
||||
public function setActivated($token_id) {
|
||||
if (!$iInvitationId = $this->getByTokenId($token_id)) {
|
||||
$this->setErrorMessage('Unable to convert token ID to invitation ID');
|
||||
return false;
|
||||
}
|
||||
$field = array('name' => 'is_activated', 'type' => 'i', 'value' => 1);
|
||||
return $this->updateSingle($iInvitationId, $field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a new invitation to the database
|
||||
* @param account_id integer Account ID to bind the invitation to
|
||||
* @param email string Email address the invite was sent to
|
||||
* @param token_id integer Token ID used during invitation
|
||||
* @return bool boolean True of false
|
||||
**/
|
||||
public function createInvitation($account_id, $email, $token_id) {
|
||||
$this->debug->append("STA " . __METHOD__, 4);
|
||||
$stmt = $this->mysqli->prepare("INSERT INTO $this->table ( account_id, email, token_id ) VALUES ( ?, ?, ?)");
|
||||
if ($stmt && $stmt->bind_param('isi', $account_id, $email, $token_id) && $stmt->execute())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Send an invitation out to a user
|
||||
* Uses the mail class to send mails
|
||||
* @param account_id integer Sending account ID
|
||||
* @param aData array Data array including mail information
|
||||
* @return bool boolean True or false
|
||||
**/
|
||||
public function sendInvitation($account_id, $aData) {
|
||||
$this->debug->append("STA " . __METHOD__, 4);
|
||||
// Check data input
|
||||
if (empty($aData['email']) || !filter_var($aData['email'], FILTER_VALIDATE_EMAIL)) {
|
||||
$this->setErrorMessage( 'Invalid e-mail address' );
|
||||
return false;
|
||||
}
|
||||
if (preg_match('/[^a-z_\.\!\?\-0-9 ]/i', $aData['message'])) {
|
||||
$this->setErrorMessage('Message may only contain alphanumeric characters');
|
||||
return false;
|
||||
}
|
||||
// Ensure this invitation does not exist yet nor do we have an account with that email
|
||||
if ($this->user->getEmail($aData['email'])) {
|
||||
$this->setErrorMessage('This email is already registered as an account');
|
||||
return false;
|
||||
}
|
||||
if ($this->getByEmail($aData['email'])) {
|
||||
$this->setErrorMessage('A pending invitation for this address already exists');
|
||||
return false;
|
||||
}
|
||||
if (!$aData['token'] = $this->token->createToken('invitation', $account_id)) {
|
||||
$this->setErrorMessage('Unable to generate invitation token: ' . $this->token->getError());
|
||||
return false;
|
||||
}
|
||||
$aData['username'] = $this->user->getUserName($account_id);
|
||||
$aData['subject'] = 'Pending Invitation';
|
||||
if ($this->mail->sendMail('invitations/body', $aData)) {
|
||||
$aToken = $this->token->getToken($aData['token']);
|
||||
if (!$this->createInvitation($account_id, $aData['email'], $aToken['id'])) {
|
||||
$this->setErrorMessage('Unable to create invitation record');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
$this->setErrorMessage('Unable to send email to recipient');
|
||||
}
|
||||
$this->setErrorMessage('Unable to send invitation');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Instantiate class
|
||||
$invitation = new invitation();
|
||||
$invitation->setDebug($debug);
|
||||
$invitation->setMysql($mysqli);
|
||||
$invitation->setMail($mail);
|
||||
$invitation->setUser($user);
|
||||
$invitation->setToken($oToken);
|
||||
$invitation->setConfig($config);
|
||||
|
||||
?>
|
||||
49
public/include/classes/monitoring.class.php
Normal file
49
public/include/classes/monitoring.class.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
// Make sure we are called from index.php
|
||||
if (!defined('SECURITY'))
|
||||
die('Hacking attempt');
|
||||
|
||||
class Monitoring {
|
||||
public function __construct($debug, $mysqli) {
|
||||
$this->debug = $debug;
|
||||
$this->mysqli = $mysqli;
|
||||
$this->table = 'monitoring';
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a value from our table
|
||||
* @param name string Setting name
|
||||
* @return value string Value
|
||||
**/
|
||||
public function getStatus($name) {
|
||||
$query = $this->mysqli->prepare("SELECT * FROM $this->table WHERE name = ? LIMIT 1");
|
||||
if ($query && $query->bind_param('s', $name) && $query->execute() && $result = $query->get_result()) {
|
||||
return $result->fetch_assoc();
|
||||
} else {
|
||||
$this->debug->append("Failed to fetch variable $name from $this->table");
|
||||
return false;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert or update a setting
|
||||
* @param name string Name of the variable
|
||||
* @param value string Variable value
|
||||
* @return bool
|
||||
**/
|
||||
public function setStatus($name, $type, $value) {
|
||||
$stmt = $this->mysqli->prepare("
|
||||
INSERT INTO $this->table (name, type, value)
|
||||
VALUES (?, ?, ?)
|
||||
ON DUPLICATE KEY UPDATE value = ?
|
||||
");
|
||||
if ($stmt && $stmt->bind_param('ssss', $name, $type, $value, $value) && $stmt->execute())
|
||||
return true;
|
||||
$this->debug->append("Failed to set $name to $value");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$monitoring = new Monitoring($debug, $mysqli);
|
||||
@ -13,9 +13,12 @@ class Share {
|
||||
// This defines each share
|
||||
public $rem_host, $username, $our_result, $upstream_result, $reason, $solution, $time;
|
||||
|
||||
public function __construct($debug, $mysqli, $salt) {
|
||||
public function __construct($debug, $mysqli, $user, $block, $config) {
|
||||
$this->debug = $debug;
|
||||
$this->mysqli = $mysqli;
|
||||
$this->user = $user;
|
||||
$this->config = $config;
|
||||
$this->block = $block;
|
||||
$this->debug->append("Instantiated Share class", 2);
|
||||
}
|
||||
|
||||
@ -70,7 +73,7 @@ class Share {
|
||||
count(id) as total
|
||||
FROM $this->table
|
||||
WHERE our_result = 'Y'
|
||||
AND id BETWEEN ? AND ?
|
||||
AND id > ? AND id <= ?
|
||||
");
|
||||
if ($this->checkStmt($stmt)) {
|
||||
$stmt->bind_param('ii', $previous_upstream, $current_upstream);
|
||||
@ -86,47 +89,94 @@ class Share {
|
||||
* 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
|
||||
* @param limit int Limit to this amount of shares for PPLNS
|
||||
* @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,
|
||||
validT.account AS username,
|
||||
sum(validT.valid) as valid,
|
||||
IFNULL(sum(invalidT.invalid),0) as invalid
|
||||
FROM
|
||||
(
|
||||
SELECT DISTINCT
|
||||
SUBSTRING_INDEX( `username` , '.', 1 ) as account,
|
||||
COUNT(id) AS valid
|
||||
FROM $this->table
|
||||
WHERE id BETWEEN ? AND ?
|
||||
AND our_result = 'Y'
|
||||
GROUP BY account
|
||||
) validT
|
||||
LEFT JOIN
|
||||
(
|
||||
SELECT DISTINCT
|
||||
SUBSTRING_INDEX( `username` , '.', 1 ) as account,
|
||||
COUNT(id) AS invalid
|
||||
FROM $this->table
|
||||
WHERE id BETWEEN ? AND ?
|
||||
AND our_result = 'N'
|
||||
GROUP BY account
|
||||
) invalidT
|
||||
ON validT.account = invalidT.account
|
||||
INNER JOIN accounts a ON a.username = validT.account
|
||||
GROUP BY a.username DESC");
|
||||
if ($this->checkStmt($stmt)) {
|
||||
$stmt->bind_param('iiii', $previous_upstream, $current_upstream, $previous_upstream, $current_upstream);
|
||||
$stmt->execute();
|
||||
$result = $stmt->get_result();
|
||||
$stmt->close();
|
||||
$stmt = $this->mysqli->prepare("
|
||||
SELECT
|
||||
a.id,
|
||||
SUBSTRING_INDEX( s.username , '.', 1 ) as username,
|
||||
IFNULL(SUM(IF(our_result='Y', 1, 0)), 0) AS valid,
|
||||
IFNULL(SUM(IF(our_result='N', 1, 0)), 0) AS invalid
|
||||
FROM $this->table AS s
|
||||
LEFT JOIN " . $this->user->getTableName() . " AS a
|
||||
ON a.username = SUBSTRING_INDEX( s.username , '.', 1 )
|
||||
WHERE s.id > ? AND s.id <= ?
|
||||
GROUP BY username DESC
|
||||
");
|
||||
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $previous_upstream, $current_upstream) && $stmt->execute() && $result = $stmt->get_result())
|
||||
return $result->fetch_all(MYSQLI_ASSOC);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the highest available share ID from archive
|
||||
**/
|
||||
function getMaxArchiveShareId() {
|
||||
$stmt = $this->mysqli->prepare("
|
||||
SELECT MAX(share_id) AS share_id FROM $this->tableArchive
|
||||
");
|
||||
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
|
||||
return $result->fetch_object()->share_id;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* We need a certain amount of valid archived shares
|
||||
* param left int Left/lowest share ID
|
||||
* param right int Right/highest share ID
|
||||
* return array data Returns an array with usernames as keys for easy access
|
||||
**/
|
||||
function getArchiveShares($iCount) {
|
||||
$iMinId = $this->getMaxArchiveShareId() - $iCount;
|
||||
$iMaxId = $this->getMaxArchiveShareId();
|
||||
$stmt = $this->mysqli->prepare("
|
||||
SELECT
|
||||
a.id,
|
||||
SUBSTRING_INDEX( s.username , '.', 1 ) as account,
|
||||
IFNULL(SUM(IF(our_result='Y', 1, 0)), 0) AS valid,
|
||||
IFNULL(SUM(IF(our_result='N', 1, 0)), 0) AS invalid
|
||||
FROM $this->tableArchive AS s
|
||||
LEFT JOIN " . $this->user->getTableName() . " AS a
|
||||
ON a.username = SUBSTRING_INDEX( s.username , '.', 1 )
|
||||
WHERE s.share_id > ? AND s.share_id <= ?
|
||||
GROUP BY account DESC");
|
||||
if ($this->checkStmt($stmt) && $stmt->bind_param("ii", $iMinId, $iMaxId) && $stmt->execute() && $result = $stmt->get_result()) {
|
||||
$aData = NULL;
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$aData[$row['account']] = $row;
|
||||
}
|
||||
if (is_array($aData)) return $aData;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* We keep shares only up to a certain point
|
||||
* This can be configured by the user.
|
||||
* @return return bool true or false
|
||||
**/
|
||||
public function purgeArchive() {
|
||||
if ($this->config['payout_system'] == 'pplns') {
|
||||
// Fetch our last block so we can go back configured rounds
|
||||
$aLastBlock = $this->block->getLast();
|
||||
// Fetch the block we need to find the share_id
|
||||
$aBlock = $this->block->getBlock($aLastBlock['height'] - $this->config['archive']['maxrounds']);
|
||||
// Now that we know our block, remove those shares
|
||||
$stmt = $this->mysqli->prepare("DELETE FROM $this->tableArchive WHERE block_id < ? AND time < DATE_SUB(now(), INTERVAL ? MINUTE)");
|
||||
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $aBlock['id'], $this->config['archive']['maxage']) && $stmt->execute())
|
||||
return true;
|
||||
} else {
|
||||
// We are not running pplns, so we just need to keep shares of the past <interval> minutes
|
||||
$stmt = $this->mysqli->prepare("DELETE FROM $this->tableArchive WHERE time < DATE_SUB(now(), INTERVAL ? MINUTE)");
|
||||
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $this->config['archive']['maxage']) && $stmt->execute())
|
||||
return true;
|
||||
}
|
||||
// Catchall
|
||||
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
|
||||
@ -135,10 +185,11 @@ class Share {
|
||||
* @return bool
|
||||
**/
|
||||
public function moveArchive($current_upstream, $block_id, $previous_upstream=0) {
|
||||
$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
|
||||
FROM $this->table
|
||||
WHERE id BETWEEN ? AND ?");
|
||||
$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
|
||||
FROM $this->table
|
||||
WHERE id > ? AND id <= ?");
|
||||
if ($this->checkStmt($archive_stmt) && $archive_stmt->bind_param('iii', $block_id, $previous_upstream, $current_upstream) && $archive_stmt->execute()) {
|
||||
$archive_stmt->close();
|
||||
return true;
|
||||
@ -148,7 +199,7 @@ class Share {
|
||||
}
|
||||
|
||||
public function deleteAccountedShares($current_upstream, $previous_upstream=0) {
|
||||
$stmt = $this->mysqli->prepare("DELETE FROM $this->table WHERE id BETWEEN ? AND ?");
|
||||
$stmt = $this->mysqli->prepare("DELETE FROM $this->table WHERE id > ? AND id <= ?");
|
||||
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $previous_upstream, $current_upstream) && $stmt->execute())
|
||||
return true;
|
||||
// Catchall
|
||||
@ -177,7 +228,48 @@ class Share {
|
||||
* @param last int Skips all shares up to last to find new share
|
||||
* @return bool
|
||||
**/
|
||||
public function setUpstream($last=0, $time=0) {
|
||||
public function setUpstream($aBlock, $last=0) {
|
||||
// Many use stratum, so we create our stratum check first
|
||||
$version = pack("I*", sprintf('%08d', $aBlock['version']));
|
||||
$previousblockhash = pack("H*", swapEndian($aBlock['previousblockhash']));
|
||||
$merkleroot = pack("H*", swapEndian($aBlock['merkleroot']) );
|
||||
$time = pack("I*", $aBlock['time']);
|
||||
$bits = pack("H*", swapEndian($aBlock['bits']));
|
||||
$nonce = pack("I*", $aBlock['nonce']);
|
||||
$header_bin = $version . $previousblockhash . $merkleroot . $time . $bits . $nonce;
|
||||
$header_hex = implode(unpack("H*", $header_bin));
|
||||
|
||||
// Stratum supported blockhash solution entry
|
||||
$stmt = $this->mysqli->prepare("SELECT SUBSTRING_INDEX( `username` , '.', 1 ) AS account, id FROM $this->table WHERE solution = ? LIMIT 1");
|
||||
if ($this->checkStmt($stmt) && $stmt->bind_param('s', $aBlock['hash']) && $stmt->execute() && $result = $stmt->get_result()) {
|
||||
$this->oUpstream = $result->fetch_object();
|
||||
$this->share_type = 'startum_blockhash';
|
||||
if (!empty($this->oUpstream->account) && is_int($this->oUpstream->id))
|
||||
return true;
|
||||
}
|
||||
|
||||
// Stratum scrypt hash check
|
||||
$scrypt_hash = swapEndian(bin2hex(Scrypt::calc($header_bin, $header_bin, 1024, 1, 1, 32)));
|
||||
$stmt = $this->mysqli->prepare("SELECT SUBSTRING_INDEX( `username` , '.', 1 ) AS account, id FROM $this->table WHERE solution = ? LIMIT 1");
|
||||
if ($this->checkStmt($stmt) && $stmt->bind_param('s', $scrypt_hash) && $stmt->execute() && $result = $stmt->get_result()) {
|
||||
$this->oUpstream = $result->fetch_object();
|
||||
$this->share_type = 'startum_solution';
|
||||
if (!empty($this->oUpstream->account) && is_int($this->oUpstream->id))
|
||||
return true;
|
||||
}
|
||||
|
||||
// Failed to fetch via startum solution, try pushpoold
|
||||
// Fallback to pushpoold solution type
|
||||
$ppheader = sprintf('%08d', $aBlock['version']) . word_reverse($aBlock['previousblockhash']) . word_reverse($aBlock['merkleroot']) . dechex($aBlock['time']) . $aBlock['bits'] . dechex($aBlock['nonce']);
|
||||
$stmt = $this->mysqli->prepare("SELECT SUBSTRING_INDEX( `username` , '.', 1 ) AS account, id FROM $this->table WHERE solution LIKE CONCAT(?, '%') LIMIT 1");
|
||||
if ($this->checkStmt($stmt) && $stmt->bind_param('s', $ppheader) && $stmt->execute() && $result = $stmt->get_result()) {
|
||||
$this->oUpstream = $result->fetch_object();
|
||||
$this->share_type = 'pp_solution';
|
||||
if (!empty($this->oUpstream->account) && is_int($this->oUpstream->id))
|
||||
return true;
|
||||
}
|
||||
|
||||
// Still no match, try upstream result with timerange
|
||||
$stmt = $this->mysqli->prepare("
|
||||
SELECT
|
||||
SUBSTRING_INDEX( `username` , '.', 1 ) AS account, id
|
||||
@ -185,9 +277,27 @@ class Share {
|
||||
WHERE upstream_result = 'Y'
|
||||
AND id > ?
|
||||
AND UNIX_TIMESTAMP(time) >= ?
|
||||
AND UNIX_TIMESTAMP(time) <= ( ? + 60 )
|
||||
ORDER BY id ASC LIMIT 1");
|
||||
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $last, $time) && $stmt->execute() && $result = $stmt->get_result()) {
|
||||
if ($this->checkStmt($stmt) && $stmt->bind_param('iii', $last, $aBlock['time'], $aBlock['time']) && $stmt->execute() && $result = $stmt->get_result()) {
|
||||
$this->oUpstream = $result->fetch_object();
|
||||
$this->share_type = 'upstream_share';
|
||||
if (!empty($this->oUpstream->account) && is_int($this->oUpstream->id))
|
||||
return true;
|
||||
}
|
||||
|
||||
// We failed again, now we take ANY result matching the timestamp
|
||||
$stmt = $this->mysqli->prepare("
|
||||
SELECT
|
||||
SUBSTRING_INDEX( `username` , '.', 1 ) AS account, id
|
||||
FROM $this->table
|
||||
WHERE our_result = 'Y'
|
||||
AND id > ?
|
||||
AND UNIX_TIMESTAMP(time) >= ?
|
||||
ORDER BY id ASC LIMIT 1");
|
||||
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $last, $aBlock['time']) && $stmt->execute() && $result = $stmt->get_result()) {
|
||||
$this->oUpstream = $result->fetch_object();
|
||||
$this->share_type = 'any_share';
|
||||
if (!empty($this->oUpstream->account) && is_int($this->oUpstream->id))
|
||||
return true;
|
||||
}
|
||||
@ -208,4 +318,4 @@ class Share {
|
||||
}
|
||||
}
|
||||
|
||||
$share = new Share($debug, $mysqli, SALT);
|
||||
$share = new Share($debug, $mysqli, $user, $block, $config);
|
||||
|
||||
@ -61,7 +61,10 @@ class Statistics {
|
||||
$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
|
||||
SELECT
|
||||
b.*,
|
||||
a.username AS finder,
|
||||
a.is_anonymous AS is_anonymous
|
||||
FROM " . $this->block->getTableName() . " AS b
|
||||
LEFT JOIN " . $this->user->getTableName() . " AS a
|
||||
ON b.account_id = a.id
|
||||
@ -327,9 +330,13 @@ class Statistics {
|
||||
case 'shares':
|
||||
$stmt = $this->mysqli->prepare("
|
||||
SELECT
|
||||
COUNT(id) AS shares,
|
||||
SUBSTRING_INDEX( username, '.', 1 ) AS account
|
||||
FROM " . $this->share->getTableName() . "
|
||||
a.donate_percent AS donate_percent,
|
||||
a.is_anonymous AS is_anonymous,
|
||||
COUNT(s.id) AS shares,
|
||||
SUBSTRING_INDEX( s.username, '.', 1 ) AS account
|
||||
FROM " . $this->share->getTableName() . " AS s
|
||||
LEFT JOIN " . $this->user->getTableName() . " AS a
|
||||
ON SUBSTRING_INDEX( s.username, '.', 1 ) = a.username
|
||||
WHERE our_result = 'Y'
|
||||
GROUP BY account
|
||||
ORDER BY shares DESC
|
||||
@ -343,14 +350,18 @@ class Statistics {
|
||||
case 'hashes':
|
||||
$stmt = $this->mysqli->prepare("
|
||||
SELECT
|
||||
IFNULL(ROUND(COUNT(id) * POW(2," . $this->config['difficulty'] . ")/600/1000, 2), 0) AS hashrate,
|
||||
SUBSTRING_INDEX( username, '.', 1 ) AS account
|
||||
a.donate_percent AS donate_percent,
|
||||
a.is_anonymous AS is_anonymous,
|
||||
IFNULL(ROUND(COUNT(t1.id) * POW(2," . $this->config['difficulty'] . ")/600/1000, 2), 0) AS hashrate,
|
||||
SUBSTRING_INDEX( t1.username, '.', 1 ) AS account
|
||||
FROM
|
||||
(
|
||||
SELECT id, username FROM " . $this->share->getTableName() . " WHERE time > DATE_SUB(now(), INTERVAL 10 MINUTE) AND our_result = 'Y'
|
||||
UNION
|
||||
SELECT id, username FROM " . $this->share->getArchiveTableName() ." WHERE time > DATE_SUB(now(), INTERVAL 10 MINUTE) AND our_result = 'Y'
|
||||
) AS t1
|
||||
LEFT JOIN " . $this->user->getTableName() . " AS a
|
||||
ON SUBSTRING_INDEX( t1.username, '.', 1 ) = a.username
|
||||
GROUP BY account
|
||||
ORDER BY hashrate DESC LIMIT ?");
|
||||
if ($this->checkStmt($stmt) && $stmt->bind_param("i", $limit) && $stmt->execute() && $result = $stmt->get_result())
|
||||
@ -374,12 +385,22 @@ class Statistics {
|
||||
ROUND(COUNT(s.id) * POW(2, " . $this->config['difficulty'] . ") / 3600 / 1000) AS hashrate,
|
||||
HOUR(s.time) AS hour
|
||||
FROM " . $this->share->getTableName() . " AS s, accounts AS a
|
||||
WHERE time < NOW() - INTERVAL 1 HOUR
|
||||
AND time > NOW() - INTERVAL 25 HOUR
|
||||
AND a.username = SUBSTRING_INDEX( s.username, '.', 1 )
|
||||
AND a.id = ?
|
||||
GROUP BY HOUR(time)
|
||||
UNION ALL
|
||||
SELECT
|
||||
ROUND(COUNT(s.id) * POW(2, " . $this->config['difficulty'] . ") / 3600 / 1000) AS hashrate,
|
||||
HOUR(s.time) AS hour
|
||||
FROM " . $this->share->getArchiveTableName() . " AS s, accounts AS a
|
||||
WHERE time < NOW() - INTERVAL 1 HOUR
|
||||
AND time > NOW() - INTERVAL 25 HOUR
|
||||
AND a.username = SUBSTRING_INDEX( s.username, '.', 1 )
|
||||
AND a.id = ?
|
||||
GROUP BY HOUR(time)");
|
||||
if ($this->checkStmt($stmt) && $stmt->bind_param("i", $account_id) && $stmt->execute() && $result = $stmt->get_result()) {
|
||||
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $account_id, $account_id) && $stmt->execute() && $result = $stmt->get_result()) {
|
||||
$aData = array();
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$aData[$row['hour']] = $row['hashrate'];
|
||||
@ -404,6 +425,14 @@ class Statistics {
|
||||
IFNULL(ROUND(COUNT(s.id) * POW(2, " . $this->config['difficulty'] . ") / 3600 / 1000), 0) AS hashrate,
|
||||
HOUR(s.time) AS hour
|
||||
FROM " . $this->share->getTableName() . " AS s
|
||||
WHERE time < NOW() - INTERVAL 1 HOUR
|
||||
AND time > NOW() - INTERVAL 25 HOUR
|
||||
GROUP BY HOUR(time)
|
||||
UNION ALL
|
||||
SELECT
|
||||
IFNULL(ROUND(COUNT(s.id) * POW(2, " . $this->config['difficulty'] . ") / 3600 / 1000), 0) AS hashrate,
|
||||
HOUR(s.time) AS hour
|
||||
FROM " . $this->share->getArchiveTableName() . " AS s
|
||||
WHERE time < NOW() - INTERVAL 1 HOUR
|
||||
AND time > NOW() - INTERVAL 25 HOUR
|
||||
GROUP BY HOUR(time)");
|
||||
|
||||
@ -9,12 +9,17 @@ if (!defined('SECURITY'))
|
||||
* Can be enabled or disabled through site configuration
|
||||
* Also sets a default time if no time is passed to it to enforce caching
|
||||
**/
|
||||
class StatsCache extends Memcached {
|
||||
class StatsCache {
|
||||
private $cache;
|
||||
|
||||
public function __construct($config, $debug) {
|
||||
$this->config = $config;
|
||||
$this->debug = $debug;
|
||||
if (! $config['memcache']['enabled'] ) $this->debug->append("Not storing any values in memcache");
|
||||
return parent::__construct();
|
||||
if (! $config['memcache']['enabled'] ) {
|
||||
$this->debug->append("Not storing any values in memcache");
|
||||
} else {
|
||||
$this->cache = new Memcached();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -26,7 +31,7 @@ class StatsCache extends Memcached {
|
||||
if (empty($expiration))
|
||||
$expiration = $this->config['memcache']['expiration'] + rand( -$this->config['memcache']['splay'], $this->config['memcache']['splay']);
|
||||
$this->debug->append("Storing " . $this->config['memcache']['keyprefix'] . "$key with expiration $expiration", 3);
|
||||
return parent::set($this->config['memcache']['keyprefix'] . $key, $value, $expiration);
|
||||
return $this->cache->set($this->config['memcache']['keyprefix'] . $key, $value, $expiration);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -36,7 +41,7 @@ class StatsCache extends Memcached {
|
||||
public function get($key, $cache_cb = NULL, &$cas_token = NULL) {
|
||||
if (! $this->config['memcache']['enabled']) return false;
|
||||
$this->debug->append("Trying to fetch key " . $this->config['memcache']['keyprefix'] . "$key from cache", 3);
|
||||
if ($data = parent::get($this->config['memcache']['keyprefix'].$key)) {
|
||||
if ($data = $this->cache->get($this->config['memcache']['keyprefix'].$key)) {
|
||||
$this->debug->append("Found key in cache", 3);
|
||||
return $data;
|
||||
} else {
|
||||
@ -55,7 +60,15 @@ class StatsCache extends Memcached {
|
||||
if ($this->config['memcache']['enabled']) $this->set($key, $data, $expiration);
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method is invoked if the called method was not realised in this class
|
||||
**/
|
||||
public function __call($name, $arguments) {
|
||||
if (! $this->config['memcache']['enabled']) return false;
|
||||
//Invoke method $name of $this->cache class with array of $arguments
|
||||
return call_user_func_array(array($this->cache, $name), $arguments);
|
||||
}
|
||||
}
|
||||
|
||||
$memcache = new StatsCache($config, $debug);
|
||||
|
||||
60
public/include/classes/token.class.php
Normal file
60
public/include/classes/token.class.php
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
// Make sure we are called from index.php
|
||||
if (!defined('SECURITY')) die('Hacking attempt');
|
||||
|
||||
class Token Extends Base {
|
||||
var $table = 'tokens';
|
||||
|
||||
/**
|
||||
* Fetch a token from our table
|
||||
* @param name string Setting name
|
||||
* @return value string Value
|
||||
**/
|
||||
public function getToken($strToken) {
|
||||
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE token = ? LIMIT 1");
|
||||
if ($stmt && $stmt->bind_param('s', $strToken) && $stmt->execute() && $result = $stmt->get_result())
|
||||
return $result->fetch_assoc();
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a new token
|
||||
* @param name string Name of the variable
|
||||
* @param value string Variable value
|
||||
* @return mixed Token string on success, false on failure
|
||||
**/
|
||||
public function createToken($strType, $account_id=NULL) {
|
||||
$strToken = hash('sha256', $account_id.$strType.microtime());
|
||||
if (!$iToken_id = $this->tokentype->getTypeId($strType)) {
|
||||
$this->setErrorMessage('Invalid token type: ' . $strType);
|
||||
return false;
|
||||
}
|
||||
$stmt = $this->mysqli->prepare("
|
||||
INSERT INTO $this->table (token, type, account_id)
|
||||
VALUES (?, ?, ?)
|
||||
");
|
||||
if ($stmt && $stmt->bind_param('sii', $strToken, $iToken_id, $account_id) && $stmt->execute())
|
||||
return $strToken;
|
||||
$this->setErrorMessage('Unable to create new token');
|
||||
$this->debug->append('Failed to create new token in database: ' . $this->mysqli->error);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a used token
|
||||
* @param token string Token name
|
||||
* @return bool
|
||||
**/
|
||||
public function deleteToken($token) {
|
||||
$stmt = $this->mysqli->prepare("DELETE FROM $this->table WHERE token = ? LIMIT 1");
|
||||
if ($stmt && $stmt->bind_param('s', $token) && $stmt->execute())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$oToken = new Token();
|
||||
$oToken->setDebug($debug);
|
||||
$oToken->setMysql($mysqli);
|
||||
$oToken->setTokenType($tokentype);
|
||||
21
public/include/classes/tokentype.class.php
Normal file
21
public/include/classes/tokentype.class.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
// Make sure we are called from index.php
|
||||
if (!defined('SECURITY'))
|
||||
die('Hacking attempt');
|
||||
|
||||
class Token_Type Extends Base {
|
||||
var $table = 'token_types';
|
||||
/**
|
||||
* Return ID for specific token
|
||||
* @param strName string Token Name
|
||||
* @return mixed ID on success, false on failure
|
||||
**/
|
||||
public function getTypeId($strName) {
|
||||
return $this->getSingle($strName, 'id', 'name', 's');
|
||||
}
|
||||
}
|
||||
|
||||
$tokentype = new Token_Type();
|
||||
$tokentype->setDebug($debug);
|
||||
$tokentype->setMysql($mysqli);
|
||||
@ -48,35 +48,6 @@ class Transaction {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sometimes transactions become orphans when a block associated to them is orphaned
|
||||
* Updates the transaction types to Orphan_<type>
|
||||
* @param block_id int Orphaned block ID
|
||||
* @return bool
|
||||
**/
|
||||
public function setOrphan($block_id) {
|
||||
$this->debug->append("STA " . __METHOD__, 4);
|
||||
$aOrphans = array(
|
||||
'Credit' => 'Orphan_Credit',
|
||||
'Fee' => 'Orphan_Fee',
|
||||
'Donation' => 'Orphan_Donation',
|
||||
'Bonus' => 'Orphan_Bonus'
|
||||
);
|
||||
foreach ($aOrphans as $from => $to) {
|
||||
$stmt = $this->mysqli->prepare("
|
||||
UPDATE $this->table
|
||||
SET type = '$to'
|
||||
WHERE type = '$from'
|
||||
AND block_id = ?
|
||||
");
|
||||
if (!($this->checkStmt($stmt) && $stmt->bind_param('i', $block_id) && $stmt->execute())) {
|
||||
$this->debug->append("Failed to set orphan $from => $to transactions for $block_id");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all transactions from start for account_id
|
||||
* @param account_id int Account ID
|
||||
@ -156,6 +127,7 @@ class Transaction {
|
||||
SELECT
|
||||
SUM(t.amount) AS donation,
|
||||
a.username AS username,
|
||||
a.is_anonymous AS is_anonymous,
|
||||
a.donate_percent AS donate_percent
|
||||
FROM $this->table AS t
|
||||
LEFT JOIN " . $this->user->getTableName() . " AS a
|
||||
@ -227,7 +199,8 @@ class Transaction {
|
||||
$stmt = $this->mysqli->prepare("
|
||||
SELECT
|
||||
ROUND(IFNULL(t1.credit, 0) - IFNULL(t2.debit, 0) - IFNULL(t3.other, 0), 8) AS confirmed,
|
||||
ROUND(IFNULL(t4.credit, 0) - IFNULL(t5.other, 0), 8) AS unconfirmed
|
||||
ROUND(IFNULL(t4.credit, 0) - IFNULL(t5.other, 0), 8) AS unconfirmed,
|
||||
ROUND(IFNULL(t6.credit, 0) - IFNULL(t7.other, 0), 8) AS orphaned
|
||||
FROM
|
||||
(
|
||||
SELECT sum(t.amount) AS credit
|
||||
@ -262,7 +235,7 @@ class Transaction {
|
||||
FROM $this->table AS t
|
||||
LEFT JOIN " . $this->block->getTableName() . " AS b ON t.block_id = b.id
|
||||
WHERE
|
||||
t.type IN ('Credit','Bonus') AND b.confirmations < ?
|
||||
t.type IN ('Credit','Bonus') AND b.confirmations < ? AND b.confirmations >= 0
|
||||
AND t.account_id = ?
|
||||
) AS t4,
|
||||
(
|
||||
@ -271,13 +244,31 @@ class Transaction {
|
||||
LEFT JOIN " . $this->block->getTableName() . " AS b ON t.block_id = b.id
|
||||
WHERE
|
||||
(
|
||||
t.type IN ('Donation','Fee') AND b.confirmations < ?
|
||||
t.type IN ('Donation','Fee') AND b.confirmations < ? AND b.confirmations >= 0
|
||||
)
|
||||
AND t.account_id = ?
|
||||
) AS t5
|
||||
) AS t5,
|
||||
(
|
||||
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 IN ('Credit','Bonus') AND b.confirmations = -1
|
||||
AND t.account_id = ?
|
||||
) AS t6,
|
||||
(
|
||||
SELECT sum(t.amount) AS other
|
||||
FROM $this->table AS t
|
||||
LEFT JOIN " . $this->block->getTableName() . " AS b ON t.block_id = b.id
|
||||
WHERE
|
||||
(
|
||||
t.type IN ('Donation','Fee') AND b.confirmations = -1
|
||||
)
|
||||
AND t.account_id = ?
|
||||
) AS t7
|
||||
");
|
||||
if ($this->checkStmt($stmt)) {
|
||||
$stmt->bind_param("iiiiiiiii", $this->config['confirmations'], $account_id, $account_id, $this->config['confirmations'], $account_id, $this->config['confirmations'], $account_id, $this->config['confirmations'], $account_id);
|
||||
$stmt->bind_param("iiiiiiiiiii", $this->config['confirmations'], $account_id, $account_id, $this->config['confirmations'], $account_id, $this->config['confirmations'], $account_id, $this->config['confirmations'], $account_id, $account_id, $account_id);
|
||||
if (!$stmt->execute()) {
|
||||
$this->debug->append("Unable to execute statement: " . $stmt->error);
|
||||
$this->setErrorMessage("Fetching balance failed");
|
||||
|
||||
@ -9,7 +9,6 @@ class User {
|
||||
private $userID = false;
|
||||
private $table = 'accounts';
|
||||
private $user = array();
|
||||
private $tableAccountBalance = 'accountBalance';
|
||||
|
||||
public function __construct($debug, $mysqli, $salt, $config) {
|
||||
$this->debug = $debug;
|
||||
@ -20,6 +19,12 @@ class User {
|
||||
}
|
||||
|
||||
// get and set methods
|
||||
public function setMail($mail) {
|
||||
$this->mail = $mail;
|
||||
}
|
||||
public function setToken($token) {
|
||||
$this->token= $token;
|
||||
}
|
||||
private function setErrorMessage($msg) {
|
||||
$this->sError = $msg;
|
||||
}
|
||||
@ -44,18 +49,15 @@ class User {
|
||||
public function getUserLocked($id) {
|
||||
return $this->getSingle($id, 'is_locked', 'id');
|
||||
}
|
||||
public function getUserToken($id) {
|
||||
return $this->getSingle($id, 'token', 'id');
|
||||
}
|
||||
public function getUserIp($id) {
|
||||
return $this->getSingle($id, 'loggedIp', 'id');
|
||||
}
|
||||
public function getEmail($email) {
|
||||
return $this->getSingle($email, 'email', 'email', 's');
|
||||
}
|
||||
public function getUserFailed($id) {
|
||||
return $this->getSingle($id, 'failed_logins', 'id');
|
||||
}
|
||||
public function getIdFromToken($token) {
|
||||
return $this->getSingle($token, 'id', 'token', 's');
|
||||
}
|
||||
public function isLocked($id) {
|
||||
return $this->getUserLocked($id);
|
||||
}
|
||||
@ -70,10 +72,6 @@ class User {
|
||||
$field = array('name' => 'is_admin', 'type' => 'i', 'value' => !$this->isAdmin($id));
|
||||
return $this->updateSingle($id, $field);
|
||||
}
|
||||
public function setUserToken($id) {
|
||||
$field = array('name' => 'token', 'type' => 's', 'value' => setHash($id.time()));
|
||||
return $this->updateSingle($id, $field);
|
||||
}
|
||||
public function setUserFailed($id, $value) {
|
||||
$field = array( 'name' => 'failed_logins', 'type' => 'i', 'value' => $value);
|
||||
return $this->updateSingle($id, $field);
|
||||
@ -280,7 +278,7 @@ class User {
|
||||
* @param donat float donation % of income
|
||||
* @return bool
|
||||
**/
|
||||
public function updateAccount($userID, $address, $threshold, $donate, $email) {
|
||||
public function updateAccount($userID, $address, $threshold, $donate, $email, $is_anonymous) {
|
||||
$this->debug->append("STA " . __METHOD__, 4);
|
||||
$bUser = false;
|
||||
|
||||
@ -314,8 +312,8 @@ class User {
|
||||
$donate = min(100, max(0, floatval($donate)));
|
||||
|
||||
// We passed all validation checks so update the account
|
||||
$stmt = $this->mysqli->prepare("UPDATE $this->table SET coin_address = ?, ap_threshold = ?, donate_percent = ?, email = ? WHERE id = ?");
|
||||
if ($this->checkStmt($stmt) && $stmt->bind_param('sddsi', $address, $threshold, $donate, $email, $userID) && $stmt->execute())
|
||||
$stmt = $this->mysqli->prepare("UPDATE $this->table SET coin_address = ?, ap_threshold = ?, donate_percent = ?, email = ?, is_anonymous = ? WHERE id = ?");
|
||||
if ($this->checkStmt($stmt) && $stmt->bind_param('sddsii', $address, $threshold, $donate, $email, $is_anonymous, $userID) && $stmt->execute())
|
||||
return true;
|
||||
// Catchall
|
||||
$this->setErrorMessage('Failed to update your account');
|
||||
@ -384,7 +382,16 @@ class User {
|
||||
**/
|
||||
public function logoutUser($redirect="index.php") {
|
||||
$this->debug->append("STA " . __METHOD__, 4);
|
||||
// Unset all of the session variables
|
||||
$_SESSION = array();
|
||||
// As we're killing the sesison, also kill the cookie!
|
||||
if (ini_get("session.use_cookies")) {
|
||||
$params = session_get_cookie_params();
|
||||
setcookie(session_name(), '', time() - 42000, $params["path"], $params["domain"], $params["secure"], $params["httponly"]);
|
||||
}
|
||||
// Destroy the session.
|
||||
session_destroy();
|
||||
// Enforce generation of a new Session ID and delete the old
|
||||
session_regenerate_id(true);
|
||||
// Enforce a page reload
|
||||
header("Location: $redirect");
|
||||
@ -409,7 +416,7 @@ class User {
|
||||
$this->debug->append("Fetching user information for user id: $userID");
|
||||
$stmt = $this->mysqli->prepare("
|
||||
SELECT
|
||||
id, username, pin, api_key, is_admin, email,
|
||||
id, username, pin, api_key, is_admin, is_anonymous, email,
|
||||
IFNULL(donate_percent, '0') as donate_percent, coin_address, ap_threshold
|
||||
FROM $this->table
|
||||
WHERE id = ? LIMIT 0,1");
|
||||
@ -437,8 +444,20 @@ class User {
|
||||
* @param email2 string Email confirmation
|
||||
* @return bool
|
||||
**/
|
||||
public function register($username, $password1, $password2, $pin, $email1='', $email2='') {
|
||||
public function register($username, $password1, $password2, $pin, $email1='', $email2='', $strToken='') {
|
||||
$this->debug->append("STA " . __METHOD__, 4);
|
||||
if (strlen($username > 40)) {
|
||||
$this->setErrorMessage('Username exceeding character limit');
|
||||
return false;
|
||||
}
|
||||
if (preg_match('/[^a-z_\-0-9]/i', $username)) {
|
||||
$this->setErrorMessage('Username may only contain alphanumeric characters');
|
||||
return false;
|
||||
}
|
||||
if ($this->getEmail($email1)) {
|
||||
$this->setErrorMessage( 'This e-mail address is already taken' );
|
||||
return false;
|
||||
}
|
||||
if (strlen($password1) < 8) {
|
||||
$this->setErrorMessage( 'Password is too short, minimum of 8 characters required' );
|
||||
return false;
|
||||
@ -459,15 +478,36 @@ class User {
|
||||
$this->setErrorMessage( 'Invalid PIN' );
|
||||
return false;
|
||||
}
|
||||
if (isset($strToken) && !empty($strToken)) {
|
||||
$aToken = $this->token->getToken($strToken);
|
||||
// Circle dependency, so we create our own object here
|
||||
$invitation = new Invitation();
|
||||
$invitation->setMysql($this->mysqli);
|
||||
$invitation->setDebug($this->debug);
|
||||
$invitation->setUser($this);
|
||||
$invitation->setConfig($this->config);
|
||||
if (!$invitation->setActivated($aToken['id'])) {
|
||||
$this->setErrorMessage('Unable to activate your invitation');
|
||||
return false;
|
||||
}
|
||||
if (!$this->token->deleteToken($strToken)) {
|
||||
$this->setErrorMessage('Unable to remove used token');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ($this->mysqli->query("SELECT id FROM $this->table LIMIT 1")->num_rows > 0) {
|
||||
$this->config['accounts']['confirm_email']['enabled'] ? $is_locked = 1 : $is_locked = 0;
|
||||
$is_admin = 0;
|
||||
$stmt = $this->mysqli->prepare("
|
||||
INSERT INTO $this->table (username, pass, email, pin, api_key)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
INSERT INTO $this->table (username, pass, email, pin, api_key, is_locked)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
");
|
||||
} else {
|
||||
$is_locked = 0;
|
||||
$is_admin = 1;
|
||||
$stmt = $this->mysqli->prepare("
|
||||
INSERT INTO $this->table (username, pass, email, pin, api_key, is_admin)
|
||||
VALUES (?, ?, ?, ?, ?, 1)
|
||||
INSERT INTO $this->table (username, pass, email, pin, api_key, is_admin, is_locked)
|
||||
VALUES (?, ?, ?, ?, ?, 1, ?)
|
||||
");
|
||||
}
|
||||
|
||||
@ -475,15 +515,33 @@ class User {
|
||||
$password_hash = $this->getHash($password1);
|
||||
$pin_hash = $this->getHash($pin);
|
||||
$apikey_hash = $this->getHash($username);
|
||||
$username_clean = strip_tags($username);
|
||||
|
||||
if ($this->checkStmt($stmt) && $stmt->bind_param('sssss', $username, $password_hash, $email1, $pin_hash, $apikey_hash)) {
|
||||
if (!$stmt->execute()) {
|
||||
$this->setErrorMessage( 'Unable to register' );
|
||||
if ($stmt->sqlstate == '23000') $this->setErrorMessage( 'Username already exists' );
|
||||
return false;
|
||||
if ($this->checkStmt($stmt) && $stmt->bind_param('sssssi', $username_clean, $password_hash, $email1, $pin_hash, $apikey_hash, $is_locked) && $stmt->execute()) {
|
||||
if ($this->config['accounts']['confirm_email']['enabled'] && $is_admin != 1) {
|
||||
if ($token = $this->token->createToken('confirm_email', $stmt->insert_id)) {
|
||||
$aData['username'] = $username_clean;
|
||||
$aData['token'] = $token;
|
||||
$aData['email'] = $email1;
|
||||
$aData['subject'] = 'E-Mail verification';
|
||||
if (!$this->mail->sendMail('register/confirm_email', $aData)) {
|
||||
$this->setErrorMessage('Unable to request email confirmation');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
$this->setErrorMessage('Failed to create confirmation token');
|
||||
$this->debug->append('Unable to create confirm_email token: ' . $this->token->getError());
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
$stmt->close();
|
||||
return true;
|
||||
} else {
|
||||
$this->setErrorMessage( 'Unable to register' );
|
||||
$this->debug->append('Failed to insert user into DB: ' . $this->mysqli->error);
|
||||
if ($stmt->sqlstate == '23000') $this->setErrorMessage( 'Username or email already registered' );
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -495,9 +553,9 @@ class User {
|
||||
* @param new2 string New password verification
|
||||
* @return bool
|
||||
**/
|
||||
public function useToken($token, $new1, $new2) {
|
||||
public function resetPassword($token, $new1, $new2) {
|
||||
$this->debug->append("STA " . __METHOD__, 4);
|
||||
if ($id = $this->getIdFromToken($token)) {
|
||||
if ($aToken = $this->token->getToken($token)) {
|
||||
if ($new1 !== $new2) {
|
||||
$this->setErrorMessage( 'New passwords do not match' );
|
||||
return false;
|
||||
@ -507,54 +565,46 @@ class User {
|
||||
return false;
|
||||
}
|
||||
$new_hash = $this->getHash($new1);
|
||||
$stmt = $this->mysqli->prepare("UPDATE $this->table SET pass = ?, token = NULL WHERE id = ? AND token = ?");
|
||||
if ($this->checkStmt($stmt) && $stmt->bind_param('sis', $new_hash, $id, $token) && $stmt->execute() && $stmt->affected_rows === 1) {
|
||||
return true;
|
||||
$stmt = $this->mysqli->prepare("UPDATE $this->table SET pass = ? WHERE id = ?");
|
||||
if ($this->checkStmt($stmt) && $stmt->bind_param('si', $new_hash, $aToken['account_id']) && $stmt->execute() && $stmt->affected_rows === 1) {
|
||||
if ($this->token->deleteToken($aToken['token'])) {
|
||||
return true;
|
||||
} else {
|
||||
$this->setErrorMessage('Unable to invalidate used token');
|
||||
}
|
||||
} else {
|
||||
$this->setErrorMessage('Unable to set new password');
|
||||
}
|
||||
} else {
|
||||
$this->setErrorMessage("Unable find user for your token");
|
||||
return false;
|
||||
$this->setErrorMessage('Invalid token');
|
||||
}
|
||||
$this->debug->append('Failed to update password:' . $this->mysqli->error);
|
||||
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) {
|
||||
public function initResetPassword($username) {
|
||||
$this->debug->append("STA " . __METHOD__, 4);
|
||||
// Fetch the users mail address
|
||||
if (empty($username)) {
|
||||
$this->serErrorMessage("Username must not be empty");
|
||||
return false;
|
||||
}
|
||||
if (!$email = $this->getUserEmail($username)) {
|
||||
if (!$aData['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");
|
||||
if (!$aData['token'] = $this->token->createToken('password_reset', $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;
|
||||
}
|
||||
$smarty->assign('TOKEN', $token);
|
||||
$smarty->assign('USERNAME', $username);
|
||||
$smarty->assign('SUBJECT', 'Password Reset Request');
|
||||
$smarty->assign('WEBSITENAME', $this->config['website']['name']);
|
||||
$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)) {
|
||||
$aData['username'] = $username;
|
||||
$aData['subject'] = 'Password Reset Request';
|
||||
if ($this->mail->sendMail('password/reset', $aData)) {
|
||||
return true;
|
||||
} else {
|
||||
$this->setErrorMessage("Unable to send mail to your address");
|
||||
@ -584,3 +634,5 @@ class User {
|
||||
|
||||
// Make our class available automatically
|
||||
$user = new User($debug, $mysqli, SALT, $config);
|
||||
$user->setMail($mail);
|
||||
$user->setToken($oToken);
|
||||
|
||||
@ -135,15 +135,9 @@ class Worker {
|
||||
**/
|
||||
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()) {
|
||||
return false;
|
||||
}
|
||||
$result = $stmt->get_result();
|
||||
$stmt->close();
|
||||
$stmt = $this->mysqli->prepare("SELECT IFNULL(COUNT(DISTINCT username), 0) AS total FROM " . $this->share->getTableName() . " WHERE time > DATE_SUB(now(), INTERVAL 10 MINUTE)");
|
||||
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
|
||||
return $result->fetch_object()->total;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -96,22 +96,24 @@ $config['ap_threshold']['max'] = 250;
|
||||
* Website specific configuration settings
|
||||
*
|
||||
* Explanation:
|
||||
* title : Website title used in master template
|
||||
* name : The pool name, displayed in the header and mails
|
||||
* slogan : A special slogan, also displayed in the header below name
|
||||
* email : `From` addresses used in notifications
|
||||
* theme : Theme used for desktop browsers
|
||||
* mobile : Enable/Disable mobile theme support
|
||||
* mobile_theme : Theme used for mobile browsers
|
||||
* title : Website title used in master template
|
||||
* name : The pool name, displayed in the header and mails
|
||||
* slogan : A special slogan, also displayed in the header below name
|
||||
* email : `From` addresses used in notifications
|
||||
* theme : Theme used for desktop browsers
|
||||
* mobile : Enable/Disable mobile theme support
|
||||
* mobile_theme : Theme used for mobile browsers
|
||||
* api disabled : Disable the sites API functions
|
||||
*
|
||||
* Defaults:
|
||||
* title = `The Pool - Mining Evolved`
|
||||
* name = `The Pool`
|
||||
* slogan = `Resistance is futile`
|
||||
* email = `test@example.com`
|
||||
* theme = `mmcFE`
|
||||
* mobile = true
|
||||
* mobile_theme = `mobile`
|
||||
* title = `The Pool - Mining Evolved`
|
||||
* name = `The Pool`
|
||||
* slogan = `Resistance is futile`
|
||||
* email = `test@example.com`
|
||||
* theme = `mmcFE`
|
||||
* mobile = true
|
||||
* mobile_theme = `mobile`
|
||||
* api disbabled = false
|
||||
**/
|
||||
$config['website']['title'] = 'The Pool - Mining Evolved';
|
||||
$config['website']['name'] = 'The Pool';
|
||||
@ -120,7 +122,51 @@ $config['website']['email'] = 'test@example.com';
|
||||
$config['website']['theme'] = 'mmcFE';
|
||||
$config['website']['mobile'] = true;
|
||||
$config['website']['mobile_theme'] = 'mobile';
|
||||
$config['website']['api']['disabled'] = false;
|
||||
|
||||
/**
|
||||
* Account specific settings
|
||||
*
|
||||
* Explanation
|
||||
* You can change some defaults on how accounts are created or registered
|
||||
* By default, all newly created accounts will require an email verificaiton.
|
||||
* Only after acitivating an account the user will be able to login
|
||||
*
|
||||
* Invitations will allow your users to invite new members to join the pool.
|
||||
* After sending a mail to the invited user, they can register using the token
|
||||
* created. Invitations can be enabled and disabled through the admin panel.
|
||||
* Sent invitations are listed on the account invitations page.
|
||||
*
|
||||
* You can limit the number of registrations send per account via configuration
|
||||
* variable.
|
||||
*
|
||||
* Options:
|
||||
* confirm_email : Send confirmation mail to user after registration
|
||||
* count : Maximum invitations a user is able to send
|
||||
*
|
||||
* Defaults:
|
||||
* confirm_email : true
|
||||
* count : 5
|
||||
**/
|
||||
$config['accounts']['confirm_email']['enabled'] = true;
|
||||
$config['accounts']['invitations']['count'] = 5;
|
||||
|
||||
/**
|
||||
* Some basic access restrictions on some pages
|
||||
*
|
||||
* Explanation:
|
||||
* Some pools would like to run a few pages for public access instead
|
||||
* of enforcing a login. You can change visibility of some pages here.
|
||||
*
|
||||
* Options:
|
||||
* 'public' : Allow guest access and authenticated user to view page
|
||||
* 'private' : Only allow logged in users access to view page
|
||||
*
|
||||
* Defaults:
|
||||
* 'private' for every page
|
||||
**/
|
||||
$config['website']['acl']['statistics']['pool'] = 'private';
|
||||
$config['website']['acl']['statistics']['blocks'] = 'private';
|
||||
|
||||
/**
|
||||
* Re-Captcha settings
|
||||
@ -133,7 +179,19 @@ $config['recaptcha']['private_key'] = 'YOUR_PRIVATE_RECAPTCHA_KEY';
|
||||
// Currency system used in this pool, default: `LTC`
|
||||
$config['currency'] = 'LTC';
|
||||
|
||||
// Default transaction fee, added by RPC server, default: 0.1
|
||||
/**
|
||||
* Default transaction fee to apply to user transactions
|
||||
*
|
||||
* Explanation
|
||||
* The coin daemon applies transcation fees to young coins.
|
||||
* Since we are unable to find out what the exact fee was we set
|
||||
* a default value here which is applied to both manual and auto payouts.
|
||||
* If this is not set, no fee is applied in the transactions history but
|
||||
* the user might still see them when the coins arrive.
|
||||
*
|
||||
* Default:
|
||||
* txfee = 0.1
|
||||
**/
|
||||
$config['txfee'] = 0.1;
|
||||
|
||||
// Payout a block bonus to block finders, default: 0 (disabled)
|
||||
@ -151,18 +209,47 @@ $config['block_bonus'] = 0;
|
||||
* Available options:
|
||||
* prop: Proportional payout system
|
||||
* pps : Pay Per Share payout system
|
||||
* pplns : Pay Per Last N Shares payout system
|
||||
*
|
||||
* Default:
|
||||
* prop
|
||||
**/
|
||||
$config['payout_system'] = 'prop';
|
||||
|
||||
// For debugging purposes you can archive shares in the archive_shares table, default: true
|
||||
$config['archive_shares'] = true;
|
||||
/**
|
||||
* Archiving configuration for debugging
|
||||
*
|
||||
* Explanation:
|
||||
* By default, we don't need to archive for a long time. PPLNS and Hashrate
|
||||
* calculations rely on this archive, but all shares past a certain point can
|
||||
* safely be deleted.
|
||||
*
|
||||
* To ensure we have enough shares on stack for PPLNS, this
|
||||
* is set to the past 10 rounds. Even with lucky ones in between those should
|
||||
* fit the PPLNS target. On top of that, even if we have more than 10 rounds,
|
||||
* we still keep the last maxage shares to ensure we can calculate hashrates.
|
||||
* Both conditions need to be met in order for shares to be purged from archive.
|
||||
*
|
||||
* Proportional mode will only keep the past 24 hours. These are required for
|
||||
* hashrate calculations to work past a round, hence 24 hours was selected as
|
||||
* the default. You may want to increase the time for debugging, then add any
|
||||
* integer reflecting minutes of shares to keep.
|
||||
*
|
||||
* Availabe Options:
|
||||
* maxrounds : PPLNS, keep shares for maxrounds
|
||||
* maxage : PROP and PPLNS, delete shares older than maxage minutes
|
||||
*
|
||||
* Default:
|
||||
* maxrounds = 10
|
||||
* maxage = 60 * 24 (24h)
|
||||
**/
|
||||
$config['archive']['maxrounds'] = 10;
|
||||
$config['archive']['maxage'] = 60 * 24;
|
||||
|
||||
// URL prefix for block searches, used for block links, default: `http://explorer.litecoin.net/search?q=`
|
||||
// If empty, the block link to the block information page will be removed
|
||||
$config['blockexplorer'] = 'http://explorer.litecoin.net/search?q=';
|
||||
// URL prefix for block searches, used for block links, default: `http://explorer.litecoin.net/block/`
|
||||
// The Blockhash is appended on the templates to this URL
|
||||
// If this config is empty, the block link to the block information page will be removed
|
||||
$config['blockexplorer'] = 'http://explorer.litecoin.net/block/';
|
||||
|
||||
// Link to blockchain information, used for difficulty link, default: `http://allchains.info`
|
||||
// If empty, the difficulty link to the chain information will be removed
|
||||
@ -171,6 +258,48 @@ $config['chaininfo'] = 'http://allchains.info';
|
||||
// Pool fees applied to users in percent, default: 0 (disabled)
|
||||
$config['fees'] = 0;
|
||||
|
||||
/**
|
||||
* PPLNS requires some settings to run properly. First we need to define
|
||||
* a default shares count that is applied if we don't have a proper type set.
|
||||
* Different dynamic types can be applied, or you can run a fixed scheme.
|
||||
*
|
||||
* Explanation
|
||||
*
|
||||
* PPLNS can run on two different payouts: fixed and blockavg. Each one
|
||||
* defines a different PPLNS target.
|
||||
*
|
||||
* Fixed means we will be looking at the shares setup in the default
|
||||
* setting. There is no automatic adjustments to the PPLNS target,
|
||||
* all users will be paid out proportionally to that target.
|
||||
*
|
||||
* Blockavg will look at the last blockcount blocks shares and take
|
||||
* the average as the PPLNS target. This will be automatically adjusted
|
||||
* when difficulty changes and more blocks are available. This keeps the
|
||||
* target dynamic but still traceable.
|
||||
*
|
||||
* If you use the fixed type it will use $config['pplns']['shares']['default']
|
||||
* for target calculations, if you use blockavg type it will use
|
||||
* $config['pplns']['blockavg']['blockcount'] blocks average for target
|
||||
* calculations.
|
||||
*
|
||||
* default : Default target shares for PPLNS
|
||||
* type : Payout type used in PPLNS
|
||||
* blockcount : Amount of blocks to check for avg shares
|
||||
*
|
||||
* Available Options:
|
||||
* default : amount of shares, integeger
|
||||
* type : blockavg or fixed
|
||||
* blockcount : amount of blocks, any integer
|
||||
*
|
||||
* Defaults:
|
||||
* default = 4000000
|
||||
* type = `blockavg`
|
||||
* blockcount = 10
|
||||
**/
|
||||
$config['pplns']['shares']['default'] = 4000000;
|
||||
$config['pplns']['shares']['type'] = 'blockavg';
|
||||
$config['pplns']['blockavg']['blockcount'] = 10;
|
||||
|
||||
// Pool target difficulty as set in pushpoold configuration file
|
||||
// Please also read this for stratum: https://github.com/TheSerapher/php-mmcfe-ng/wiki/FAQ
|
||||
$config['difficulty'] = 20;
|
||||
@ -181,7 +310,7 @@ $config['difficulty'] = 20;
|
||||
*
|
||||
* Explanation:
|
||||
*
|
||||
* Proportional Payout System
|
||||
* Proportional + PPLNS Payout System
|
||||
* When running a pool on fixed mode, each block will be paid
|
||||
* out as defined in `reward`. If you wish to pass transaction
|
||||
* fees inside discovered blocks on to user, set this to `block`.
|
||||
@ -217,11 +346,17 @@ $config['confirmations'] = 120;
|
||||
/**
|
||||
* Memcache configuration
|
||||
*
|
||||
* To disable memcache set option $config['memcache']['enabled'] = false
|
||||
* After disable memcache installation of memcache is not required.
|
||||
*
|
||||
* Please note that a memcache is greatly increasing performance
|
||||
* when combined with the `statistics.php` cronjob. Disabling this
|
||||
* is not recommended in a live environment!
|
||||
*
|
||||
* Explanations
|
||||
* enabled : Disable (false) memcache for debugging or enable (true) it
|
||||
* host : Host IP or hostname
|
||||
* port : memcache port
|
||||
* keyprefix : Must be changed for multiple mmcfe-ng instances on one host
|
||||
* expiration : Default expiration time in seconds of all cached keys.
|
||||
* Increase if caches expire too fast.
|
||||
@ -247,19 +382,77 @@ $config['memcache']['splay'] = 15;
|
||||
/**
|
||||
* Cookie configiration
|
||||
*
|
||||
* For multiple installations of this cookie change the cookie name
|
||||
* You can configure the cookie behaviour to secure your cookies more than the PHP defaults
|
||||
*
|
||||
* For multiple installations of mmcfe-ng on the same domain you must change the cookie path.
|
||||
*
|
||||
* Explanation:
|
||||
* duration:
|
||||
* the amount of time, in seconds, that a cookie should persist in the users browser.
|
||||
* 0 = until closed; 1440 = 24 minutes. Check your php.ini 'session.gc_maxlifetime' value
|
||||
* and ensure that it is at least the duration specified here.
|
||||
*
|
||||
* domain:
|
||||
* the only domain name that may access this cookie in the browser
|
||||
*
|
||||
* path:
|
||||
* the highest path on the domain that can access this cookie; i.e. if running two pools
|
||||
* from a single domain you might set the path /ltc/ and /ftc/ to separate user session
|
||||
* cookies between the two.
|
||||
*
|
||||
* httponly:
|
||||
* marks the cookie as accessible only through the HTTP protocol. The cookie can't be
|
||||
* accessed by scripting languages, such as JavaScript. This can help to reduce identity
|
||||
* theft through XSS attacks in most browsers.
|
||||
*
|
||||
* secure:
|
||||
* marks the cookie as accessible only through the HTTPS protocol. If you have a SSL
|
||||
* certificate installed on your domain name then this will stop a user accidently
|
||||
* accessing the site over a HTTP connection, without SSL, exposing their session cookie.
|
||||
*
|
||||
* Default:
|
||||
* path = '/'
|
||||
* name = 'POOLERCOOKIE'
|
||||
* domain = ''
|
||||
* duration = '1440'
|
||||
* domain = ''
|
||||
* path = '/'
|
||||
* httponly = true
|
||||
* secure = false
|
||||
**/
|
||||
$config['cookie']['path'] = '/';
|
||||
$config['cookie']['name'] = 'POOLERCOOKIE';
|
||||
$config['cookie']['duration'] = '1440';
|
||||
$config['cookie']['domain'] = '';
|
||||
$config['cookie']['path'] = '/';
|
||||
$config['cookie']['httponly'] = true;
|
||||
$config['cookie']['secure'] = false;
|
||||
|
||||
// Disable or enable smarty cache
|
||||
// This is usually not required, default: 0
|
||||
$config['cache'] = 0;
|
||||
|
||||
/**
|
||||
* Enable or disable the Smarty cache
|
||||
*
|
||||
* Explanation:
|
||||
* Smarty implements a file based cache for all HTML output generated
|
||||
* from dynamic scripts. It can be enabled to cache the HTML data on disk,
|
||||
* future request are served from those cache files.
|
||||
*
|
||||
* This may or may not work as expected, in general Memcache is used to cache
|
||||
* all data so rendering the page should not take too long anyway.
|
||||
*
|
||||
* You can test this out and enable (1) this setting but it's not guaranteed to
|
||||
* work with mmcfe-ng.
|
||||
*
|
||||
* Ensure that the folder `templates/cache` is writable by the webserver!
|
||||
*
|
||||
* cache = Enable/Disable the cache
|
||||
* cache_lifetime = Time to keep files in seconds before updating them
|
||||
*
|
||||
* Options:
|
||||
* cache:
|
||||
* 0 = disabled
|
||||
* 1 = enabled
|
||||
* cache_lifetime:
|
||||
* time in seconds
|
||||
*
|
||||
* Defaults:
|
||||
* cache = 0, disabled
|
||||
* cache_lifetime = 30 seconds
|
||||
**/
|
||||
$config['smarty']['cache'] = 0;
|
||||
$config['smarty']['cache_lifetime'] = 30;
|
||||
?>
|
||||
|
||||
148
public/include/lib/KLogger.php
Executable file
148
public/include/lib/KLogger.php
Executable file
@ -0,0 +1,148 @@
|
||||
<?php
|
||||
|
||||
/* Finally, A light, permissions-checking logging class.
|
||||
*
|
||||
* Author : Kenneth Katzgrau < katzgrau@gmail.com >
|
||||
* Date : July 26, 2008
|
||||
* Comments : Originally written for use with wpSearch
|
||||
* Website : http://codefury.net
|
||||
* Version : 1.0
|
||||
*
|
||||
* Usage:
|
||||
* $log = new KLogger ( "log.txt" , KLogger::INFO );
|
||||
* $log->LogInfo("Returned a million search results"); //Prints to the log file
|
||||
* $log->LogFATAL("Oh dear."); //Prints to the log file
|
||||
* $log->LogDebug("x = 5"); //Prints nothing due to priority setting
|
||||
*/
|
||||
|
||||
class KLogger
|
||||
{
|
||||
|
||||
const DEBUG = 1; // Most Verbose
|
||||
const INFO = 2; // ...
|
||||
const WARN = 3; // ...
|
||||
const ERROR = 4; // ...
|
||||
const FATAL = 5; // Least Verbose
|
||||
const OFF = 6; // Nothing at all.
|
||||
|
||||
const LOG_OPEN = 1;
|
||||
const OPEN_FAILED = 2;
|
||||
const LOG_CLOSED = 3;
|
||||
|
||||
/* Public members: Not so much of an example of encapsulation, but that's okay. */
|
||||
public $Log_Status = KLogger::LOG_CLOSED;
|
||||
public $DateFormat = "Y-m-d G:i:s";
|
||||
public $MessageQueue;
|
||||
|
||||
private $log_file;
|
||||
private $priority = KLogger::INFO;
|
||||
|
||||
private $file_handle;
|
||||
|
||||
public function __construct( $filepath , $priority )
|
||||
{
|
||||
if ( $priority == KLogger::OFF ) return;
|
||||
|
||||
$this->log_file = $filepath;
|
||||
$this->MessageQueue = array();
|
||||
$this->priority = $priority;
|
||||
|
||||
if ( file_exists( $this->log_file ) )
|
||||
{
|
||||
if ( !is_writable($this->log_file) )
|
||||
{
|
||||
$this->Log_Status = KLogger::OPEN_FAILED;
|
||||
$this->MessageQueue[] = "The file exists, but could not be opened for writing. Check that appropriate permissions have been set.";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->file_handle = fopen( $this->log_file , "a" ) )
|
||||
{
|
||||
$this->Log_Status = KLogger::LOG_OPEN;
|
||||
$this->MessageQueue[] = "The log file was opened successfully.";
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->Log_Status = KLogger::OPEN_FAILED;
|
||||
$this->MessageQueue[] = "The file could not be opened. Check permissions.";
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
if ( $this->file_handle )
|
||||
fclose( $this->file_handle );
|
||||
}
|
||||
|
||||
public function LogInfo($line)
|
||||
{
|
||||
$this->Log( $line , KLogger::INFO );
|
||||
}
|
||||
|
||||
public function LogDebug($line)
|
||||
{
|
||||
$this->Log( $line , KLogger::DEBUG );
|
||||
}
|
||||
|
||||
public function LogWarn($line)
|
||||
{
|
||||
$this->Log( $line , KLogger::WARN );
|
||||
}
|
||||
|
||||
public function LogError($line)
|
||||
{
|
||||
$this->Log( $line , KLogger::ERROR );
|
||||
}
|
||||
|
||||
public function LogFatal($line)
|
||||
{
|
||||
$this->Log( $line , KLogger::FATAL );
|
||||
}
|
||||
|
||||
public function Log($line, $priority)
|
||||
{
|
||||
if ( $this->priority <= $priority )
|
||||
{
|
||||
$status = $this->getTimeLine( $priority );
|
||||
$this->WriteFreeFormLine ( "$status $line \n" );
|
||||
}
|
||||
}
|
||||
|
||||
public function WriteFreeFormLine( $line )
|
||||
{
|
||||
if ( $this->Log_Status == KLogger::LOG_OPEN && $this->priority != KLogger::OFF )
|
||||
{
|
||||
if (fwrite( $this->file_handle , $line ) === false) {
|
||||
$this->MessageQueue[] = "The file could not be written to. Check that appropriate permissions have been set.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function getTimeLine( $level )
|
||||
{
|
||||
$time = date( $this->DateFormat );
|
||||
|
||||
switch( $level )
|
||||
{
|
||||
case KLogger::INFO:
|
||||
return "$time - INFO -->";
|
||||
case KLogger::WARN:
|
||||
return "$time - WARN -->";
|
||||
case KLogger::DEBUG:
|
||||
return "$time - DEBUG -->";
|
||||
case KLogger::ERROR:
|
||||
return "$time - ERROR -->";
|
||||
case KLogger::FATAL:
|
||||
return "$time - FATAL -->";
|
||||
default:
|
||||
return "$time - LOG -->";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
536
public/include/lib/scrypt.php
Normal file
536
public/include/lib/scrypt.php
Normal file
@ -0,0 +1,536 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework (http://framework.zend.com/)
|
||||
*
|
||||
* @link http://github.com/zendframework/zf2 for the canonical source repository
|
||||
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Scrypt key derivation function
|
||||
*
|
||||
* @see http://www.tarsnap.com/scrypt.html
|
||||
* @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01
|
||||
*/
|
||||
abstract class Scrypt
|
||||
{
|
||||
/**
|
||||
* Execute the scrypt algorithm
|
||||
*
|
||||
* @param string $password
|
||||
* @param string $salt
|
||||
* @param integer $n CPU cost
|
||||
* @param integer $r Memory cost
|
||||
* @param integer $p parallelization cost
|
||||
* @param integer $length size of the output key
|
||||
* @return string
|
||||
*/
|
||||
public static function calc($password, $salt, $n, $r, $p, $length)
|
||||
{
|
||||
if ($n == 0 || ($n & ($n - 1)) != 0) {
|
||||
throw new Exception\InvalidArgumentException("N must be > 0 and a power of 2");
|
||||
}
|
||||
if ($n > PHP_INT_MAX / 128 / $r) {
|
||||
throw new Exception\InvalidArgumentException("Parameter n is too large");
|
||||
}
|
||||
if ($r > PHP_INT_MAX / 128 / $p) {
|
||||
throw new Exception\InvalidArgumentException("Parameter r is too large");
|
||||
}
|
||||
|
||||
if (extension_loaded('Scrypt')) {
|
||||
if ($length < 16) {
|
||||
throw new Exception\InvalidArgumentException("Key length is too low, must be greater or equal to 16");
|
||||
}
|
||||
return self::hex2bin(scrypt($password, $salt, $n, $r, $p, $length));
|
||||
}
|
||||
|
||||
$b = Pbkdf2::calc('sha256', $password, $salt, 1, $p * 128 * $r);
|
||||
|
||||
$s = '';
|
||||
for ($i = 0; $i < $p; $i++) {
|
||||
$s .= self::scryptROMix(substr($b, $i * 128 * $r, 128 * $r), $n, $r);
|
||||
}
|
||||
|
||||
return Pbkdf2::calc('sha256', $password, $s, 1, $length);
|
||||
}
|
||||
|
||||
/**
|
||||
* scryptROMix
|
||||
*
|
||||
* @param string $b
|
||||
* @param integer $n
|
||||
* @param integer $r
|
||||
* @return string
|
||||
* @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-4
|
||||
*/
|
||||
protected static function scryptROMix($b, $n, $r)
|
||||
{
|
||||
$x = $b;
|
||||
$v = array();
|
||||
for ($i = 0; $i < $n; $i++) {
|
||||
$v[$i] = $x;
|
||||
$x = self::scryptBlockMix($x, $r);
|
||||
}
|
||||
for ($i = 0; $i < $n; $i++) {
|
||||
$j = self::integerify($x) % $n;
|
||||
$t = $x ^ $v[$j];
|
||||
$x = self::scryptBlockMix($t, $r);
|
||||
}
|
||||
return $x;
|
||||
}
|
||||
|
||||
/**
|
||||
* scryptBlockMix
|
||||
*
|
||||
* @param string $b
|
||||
* @param integer $r
|
||||
* @return string
|
||||
* @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-3
|
||||
*/
|
||||
protected static function scryptBlockMix($b, $r)
|
||||
{
|
||||
$x = substr($b, -64);
|
||||
$even = '';
|
||||
$odd = '';
|
||||
$len = 2 * $r;
|
||||
|
||||
for ($i = 0; $i < $len; $i++) {
|
||||
if (PHP_INT_SIZE === 4) {
|
||||
$x = self::salsa208Core32($x ^ substr($b, 64 * $i, 64));
|
||||
} else {
|
||||
$x = self::salsa208Core64($x ^ substr($b, 64 * $i, 64));
|
||||
}
|
||||
if ($i % 2 == 0) {
|
||||
$even .= $x;
|
||||
} else {
|
||||
$odd .= $x;
|
||||
}
|
||||
}
|
||||
return $even . $odd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Salsa 20/8 core (32 bit version)
|
||||
*
|
||||
* @param string $b
|
||||
* @return string
|
||||
* @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-2
|
||||
* @see http://cr.yp.to/salsa20.html
|
||||
*/
|
||||
protected static function salsa208Core32($b)
|
||||
{
|
||||
$b32 = array();
|
||||
for ($i = 0; $i < 16; $i++) {
|
||||
list(, $b32[$i]) = unpack("V", substr($b, $i * 4, 4));
|
||||
}
|
||||
|
||||
$x = $b32;
|
||||
for ($i = 0; $i < 8; $i += 2) {
|
||||
$a = ($x[ 0] + $x[12]);
|
||||
$x[ 4] ^= ($a << 7) | ($a >> 25) & 0x7f;
|
||||
$a = ($x[ 4] + $x[ 0]);
|
||||
$x[ 8] ^= ($a << 9) | ($a >> 23) & 0x1ff;
|
||||
$a = ($x[ 8] + $x[ 4]);
|
||||
$x[12] ^= ($a << 13) | ($a >> 19) & 0x1fff;
|
||||
$a = ($x[12] + $x[ 8]);
|
||||
$x[ 0] ^= ($a << 18) | ($a >> 14) & 0x3ffff;
|
||||
$a = ($x[ 5] + $x[ 1]);
|
||||
$x[ 9] ^= ($a << 7) | ($a >> 25) & 0x7f;
|
||||
$a = ($x[ 9] + $x[ 5]);
|
||||
$x[13] ^= ($a << 9) | ($a >> 23) & 0x1ff;
|
||||
$a = ($x[13] + $x[ 9]);
|
||||
$x[ 1] ^= ($a << 13) | ($a >> 19) & 0x1fff;
|
||||
$a = ($x[ 1] + $x[13]);
|
||||
$x[ 5] ^= ($a << 18) | ($a >> 14) & 0x3ffff;
|
||||
$a = ($x[10] + $x[ 6]);
|
||||
$x[14] ^= ($a << 7) | ($a >> 25) & 0x7f;
|
||||
$a = ($x[14] + $x[10]);
|
||||
$x[ 2] ^= ($a << 9) | ($a >> 23) & 0x1ff;
|
||||
$a = ($x[ 2] + $x[14]);
|
||||
$x[ 6] ^= ($a << 13) | ($a >> 19) & 0x1fff;
|
||||
$a = ($x[ 6] + $x[ 2]);
|
||||
$x[10] ^= ($a << 18) | ($a >> 14) & 0x3ffff;
|
||||
$a = ($x[15] + $x[11]);
|
||||
$x[ 3] ^= ($a << 7) | ($a >> 25) & 0x7f;
|
||||
$a = ($x[ 3] + $x[15]);
|
||||
$x[ 7] ^= ($a << 9) | ($a >> 23) & 0x1ff;
|
||||
$a = ($x[ 7] + $x[ 3]);
|
||||
$x[11] ^= ($a << 13) | ($a >> 19) & 0x1fff;
|
||||
$a = ($x[11] + $x[ 7]);
|
||||
$x[15] ^= ($a << 18) | ($a >> 14) & 0x3ffff;
|
||||
$a = ($x[ 0] + $x[ 3]);
|
||||
$x[ 1] ^= ($a << 7) | ($a >> 25) & 0x7f;
|
||||
$a = ($x[ 1] + $x[ 0]);
|
||||
$x[ 2] ^= ($a << 9) | ($a >> 23) & 0x1ff;
|
||||
$a = ($x[ 2] + $x[ 1]);
|
||||
$x[ 3] ^= ($a << 13) | ($a >> 19) & 0x1fff;
|
||||
$a = ($x[ 3] + $x[ 2]);
|
||||
$x[ 0] ^= ($a << 18) | ($a >> 14) & 0x3ffff;
|
||||
$a = ($x[ 5] + $x[ 4]);
|
||||
$x[ 6] ^= ($a << 7) | ($a >> 25) & 0x7f;
|
||||
$a = ($x[ 6] + $x[ 5]);
|
||||
$x[ 7] ^= ($a << 9) | ($a >> 23) & 0x1ff;
|
||||
$a = ($x[ 7] + $x[ 6]);
|
||||
$x[ 4] ^= ($a << 13) | ($a >> 19) & 0x1fff;
|
||||
$a = ($x[ 4] + $x[ 7]);
|
||||
$x[ 5] ^= ($a << 18) | ($a >> 14) & 0x3ffff;
|
||||
$a = ($x[10] + $x[ 9]);
|
||||
$x[11] ^= ($a << 7) | ($a >> 25) & 0x7f;
|
||||
$a = ($x[11] + $x[10]);
|
||||
$x[ 8] ^= ($a << 9) | ($a >> 23) & 0x1ff;
|
||||
$a = ($x[ 8] + $x[11]);
|
||||
$x[ 9] ^= ($a << 13) | ($a >> 19) & 0x1fff;
|
||||
$a = ($x[ 9] + $x[ 8]);
|
||||
$x[10] ^= ($a << 18) | ($a >> 14) & 0x3ffff;
|
||||
$a = ($x[15] + $x[14]);
|
||||
$x[12] ^= ($a << 7) | ($a >> 25) & 0x7f;
|
||||
$a = ($x[12] + $x[15]);
|
||||
$x[13] ^= ($a << 9) | ($a >> 23) & 0x1ff;
|
||||
$a = ($x[13] + $x[12]);
|
||||
$x[14] ^= ($a << 13) | ($a >> 19) & 0x1fff;
|
||||
$a = ($x[14] + $x[13]);
|
||||
$x[15] ^= ($a << 18) | ($a >> 14) & 0x3ffff;
|
||||
}
|
||||
for ($i = 0; $i < 16; $i++) {
|
||||
$b32[$i] = $b32[$i] + $x[$i];
|
||||
}
|
||||
$result = '';
|
||||
for ($i = 0; $i < 16; $i++) {
|
||||
$result .= pack("V", $b32[$i]);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Salsa 20/8 core (64 bit version)
|
||||
*
|
||||
* @param string $b
|
||||
* @return string
|
||||
* @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-2
|
||||
* @see http://cr.yp.to/salsa20.html
|
||||
*/
|
||||
protected static function salsa208Core64($b)
|
||||
{
|
||||
$b32 = array();
|
||||
for ($i = 0; $i < 16; $i++) {
|
||||
list(, $b32[$i]) = unpack("V", substr($b, $i * 4, 4));
|
||||
}
|
||||
|
||||
$x = $b32;
|
||||
for ($i = 0; $i < 8; $i += 2) {
|
||||
$a = ($x[ 0] + $x[12]) & 0xffffffff;
|
||||
$x[ 4] ^= ($a << 7) | ($a >> 25);
|
||||
$a = ($x[ 4] + $x[ 0]) & 0xffffffff;
|
||||
$x[ 8] ^= ($a << 9) | ($a >> 23);
|
||||
$a = ($x[ 8] + $x[ 4]) & 0xffffffff;
|
||||
$x[12] ^= ($a << 13) | ($a >> 19);
|
||||
$a = ($x[12] + $x[ 8]) & 0xffffffff;
|
||||
$x[ 0] ^= ($a << 18) | ($a >> 14);
|
||||
$a = ($x[ 5] + $x[ 1]) & 0xffffffff;
|
||||
$x[ 9] ^= ($a << 7) | ($a >> 25);
|
||||
$a = ($x[ 9] + $x[ 5]) & 0xffffffff;
|
||||
$x[13] ^= ($a << 9) | ($a >> 23);
|
||||
$a = ($x[13] + $x[ 9]) & 0xffffffff;
|
||||
$x[ 1] ^= ($a << 13) | ($a >> 19);
|
||||
$a = ($x[ 1] + $x[13]) & 0xffffffff;
|
||||
$x[ 5] ^= ($a << 18) | ($a >> 14);
|
||||
$a = ($x[10] + $x[ 6]) & 0xffffffff;
|
||||
$x[14] ^= ($a << 7) | ($a >> 25);
|
||||
$a = ($x[14] + $x[10]) & 0xffffffff;
|
||||
$x[ 2] ^= ($a << 9) | ($a >> 23);
|
||||
$a = ($x[ 2] + $x[14]) & 0xffffffff;
|
||||
$x[ 6] ^= ($a << 13) | ($a >> 19);
|
||||
$a = ($x[ 6] + $x[ 2]) & 0xffffffff;
|
||||
$x[10] ^= ($a << 18) | ($a >> 14);
|
||||
$a = ($x[15] + $x[11]) & 0xffffffff;
|
||||
$x[ 3] ^= ($a << 7) | ($a >> 25);
|
||||
$a = ($x[ 3] + $x[15]) & 0xffffffff;
|
||||
$x[ 7] ^= ($a << 9) | ($a >> 23);
|
||||
$a = ($x[ 7] + $x[ 3]) & 0xffffffff;
|
||||
$x[11] ^= ($a << 13) | ($a >> 19);
|
||||
$a = ($x[11] + $x[ 7]) & 0xffffffff;
|
||||
$x[15] ^= ($a << 18) | ($a >> 14);
|
||||
$a = ($x[ 0] + $x[ 3]) & 0xffffffff;
|
||||
$x[ 1] ^= ($a << 7) | ($a >> 25);
|
||||
$a = ($x[ 1] + $x[ 0]) & 0xffffffff;
|
||||
$x[ 2] ^= ($a << 9) | ($a >> 23);
|
||||
$a = ($x[ 2] + $x[ 1]) & 0xffffffff;
|
||||
$x[ 3] ^= ($a << 13) | ($a >> 19);
|
||||
$a = ($x[ 3] + $x[ 2]) & 0xffffffff;
|
||||
$x[ 0] ^= ($a << 18) | ($a >> 14);
|
||||
$a = ($x[ 5] + $x[ 4]) & 0xffffffff;
|
||||
$x[ 6] ^= ($a << 7) | ($a >> 25);
|
||||
$a = ($x[ 6] + $x[ 5]) & 0xffffffff;
|
||||
$x[ 7] ^= ($a << 9) | ($a >> 23);
|
||||
$a = ($x[ 7] + $x[ 6]) & 0xffffffff;
|
||||
$x[ 4] ^= ($a << 13) | ($a >> 19);
|
||||
$a = ($x[ 4] + $x[ 7]) & 0xffffffff;
|
||||
$x[ 5] ^= ($a << 18) | ($a >> 14);
|
||||
$a = ($x[10] + $x[ 9]) & 0xffffffff;
|
||||
$x[11] ^= ($a << 7) | ($a >> 25);
|
||||
$a = ($x[11] + $x[10]) & 0xffffffff;
|
||||
$x[ 8] ^= ($a << 9) | ($a >> 23);
|
||||
$a = ($x[ 8] + $x[11]) & 0xffffffff;
|
||||
$x[ 9] ^= ($a << 13) | ($a >> 19);
|
||||
$a = ($x[ 9] + $x[ 8]) & 0xffffffff;
|
||||
$x[10] ^= ($a << 18) | ($a >> 14);
|
||||
$a = ($x[15] + $x[14]) & 0xffffffff;
|
||||
$x[12] ^= ($a << 7) | ($a >> 25);
|
||||
$a = ($x[12] + $x[15]) & 0xffffffff;
|
||||
$x[13] ^= ($a << 9) | ($a >> 23);
|
||||
$a = ($x[13] + $x[12]) & 0xffffffff;
|
||||
$x[14] ^= ($a << 13) | ($a >> 19);
|
||||
$a = ($x[14] + $x[13]) & 0xffffffff;
|
||||
$x[15] ^= ($a << 18) | ($a >> 14);
|
||||
}
|
||||
for ($i = 0; $i < 16; $i++) {
|
||||
$b32[$i] = ($b32[$i] + $x[$i]) & 0xffffffff;
|
||||
}
|
||||
$result = '';
|
||||
for ($i = 0; $i < 16; $i++) {
|
||||
$result .= pack("V", $b32[$i]);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Integerify
|
||||
*
|
||||
* Integerify (B[0] ... B[2 * r - 1]) is defined as the result
|
||||
* of interpreting B[2 * r - 1] as a little-endian integer.
|
||||
* Each block B is a string of 64 bytes.
|
||||
*
|
||||
* @param string $b
|
||||
* @return integer
|
||||
* @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-4
|
||||
*/
|
||||
protected static function integerify($b)
|
||||
{
|
||||
$v = 'v';
|
||||
if (PHP_INT_SIZE === 8) {
|
||||
$v = 'V';
|
||||
}
|
||||
list(,$n) = unpack($v, substr($b, -64));
|
||||
return $n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert hex string in a binary string
|
||||
*
|
||||
* @param string $hex
|
||||
* @return string
|
||||
*/
|
||||
protected static function hex2bin($hex)
|
||||
{
|
||||
if (version_compare(PHP_VERSION, '5.4') >= 0) {
|
||||
return hex2bin($hex);
|
||||
}
|
||||
$len = strlen($hex);
|
||||
$result = '';
|
||||
for ($i = 0; $i < $len; $i+=2) {
|
||||
$result .= chr(hexdec($hex[$i] . $hex[$i+1]));
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Zend Framework (http://framework.zend.com/)
|
||||
*
|
||||
* @link http://github.com/zendframework/zf2 for the canonical source repository
|
||||
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* PKCS #5 v2.0 standard RFC 2898
|
||||
*/
|
||||
class Pbkdf2
|
||||
{
|
||||
/**
|
||||
* Generate the new key
|
||||
*
|
||||
* @param string $hash The hash algorithm to be used by HMAC
|
||||
* @param string $password The source password/key
|
||||
* @param string $salt
|
||||
* @param integer $iterations The number of iterations
|
||||
* @param integer $length The output size
|
||||
* @throws Exception\InvalidArgumentException
|
||||
* @return string
|
||||
*/
|
||||
public static function calc($hash, $password, $salt, $iterations, $length)
|
||||
{
|
||||
if (!Hmac::isSupported($hash)) {
|
||||
throw new Exception\InvalidArgumentException("The hash algorithm $hash is not supported by " . __CLASS__);
|
||||
}
|
||||
|
||||
$num = ceil($length / Hmac::getOutputSize($hash, Hmac::OUTPUT_BINARY));
|
||||
$result = '';
|
||||
for ($block = 1; $block <= $num; $block++) {
|
||||
$hmac = hash_hmac($hash, $salt . pack('N', $block), $password, Hmac::OUTPUT_BINARY);
|
||||
$mix = $hmac;
|
||||
for ($i = 1; $i < $iterations; $i++) {
|
||||
$hmac = hash_hmac($hash, $hmac, $password, Hmac::OUTPUT_BINARY);
|
||||
$mix ^= $hmac;
|
||||
}
|
||||
$result .= $mix;
|
||||
}
|
||||
return substr($result, 0, $length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Zend Framework (http://framework.zend.com/)
|
||||
*
|
||||
* @link http://github.com/zendframework/zf2 for the canonical source repository
|
||||
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* PHP implementation of the RFC 2104 Hash based Message Authentication Code
|
||||
*/
|
||||
class Hmac
|
||||
{
|
||||
const OUTPUT_STRING = false;
|
||||
const OUTPUT_BINARY = true;
|
||||
|
||||
/**
|
||||
* Last algorithm supported
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
protected static $lastAlgorithmSupported;
|
||||
|
||||
/**
|
||||
* Performs a HMAC computation given relevant details such as Key, Hashing
|
||||
* algorithm, the data to compute MAC of, and an output format of String,
|
||||
* or Binary.
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $hash
|
||||
* @param string $data
|
||||
* @param bool $output
|
||||
* @throws Exception\InvalidArgumentException
|
||||
* @return string
|
||||
*/
|
||||
public static function compute($key, $hash, $data, $output = self::OUTPUT_STRING)
|
||||
{
|
||||
|
||||
if (empty($key)) {
|
||||
throw new Exception\InvalidArgumentException('Provided key is null or empty');
|
||||
}
|
||||
|
||||
if (!$hash || ($hash !== static::$lastAlgorithmSupported && !static::isSupported($hash))) {
|
||||
throw new Exception\InvalidArgumentException(
|
||||
"Hash algorithm is not supported on this PHP installation; provided '{$hash}'"
|
||||
);
|
||||
}
|
||||
|
||||
return hash_hmac($hash, $data, $key, $output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the output size according to the hash algorithm and the output format
|
||||
*
|
||||
* @param string $hash
|
||||
* @param bool $output
|
||||
* @return integer
|
||||
*/
|
||||
public static function getOutputSize($hash, $output = self::OUTPUT_STRING)
|
||||
{
|
||||
return strlen(static::compute('key', $hash, 'data', $output));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the supported algorithm
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getSupportedAlgorithms()
|
||||
{
|
||||
return hash_algos();
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the hash algorithm supported?
|
||||
*
|
||||
* @param string $algorithm
|
||||
* @return bool
|
||||
*/
|
||||
public static function isSupported($algorithm)
|
||||
{
|
||||
if ($algorithm === static::$lastAlgorithmSupported) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (in_array(strtolower($algorithm), hash_algos(), true)) {
|
||||
static::$lastAlgorithmSupported = $algorithm;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the cache of last algorithm supported
|
||||
*/
|
||||
public static function clearLastAlgorithmCache()
|
||||
{
|
||||
static::$lastAlgorithmSupported = null;
|
||||
}
|
||||
}
|
||||
function swapEndian($input){
|
||||
$output = "";
|
||||
for($i=0;$i< strlen($input);$i+=2){
|
||||
$output .= substr($input, -($i+2), 2);
|
||||
|
||||
|
||||
}
|
||||
return $output;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*for($i=0;$i < 200;$i++){
|
||||
$value = Scrypt::calc($i, $i, 1024, 1, 1, 32);
|
||||
echo "scrypt ".$i." hash:". bin2hex($value)."<br/>";
|
||||
}*/
|
||||
/*
|
||||
$i = pack("H*", "01000000f615f7ce3b4fc6b8f61e8f89aedb1d0852507650533a9e3b10b9bbcc30639f279fcaa86746e1ef52d3edb3c4ad8259920d509bd073605c9bf1d59983752a6b06b817bb4ea78e011d012d59d4");
|
||||
|
||||
$value = Scrypt::calc($i, $i, 1024, 1, 1, 32);
|
||||
echo "scrypt ".$i." hash:". bin2hex($value)."<br/>";
|
||||
print_r( swapEndian(bin2hex($value)));
|
||||
*/
|
||||
|
||||
|
||||
// Function used for pushpoold solution checks
|
||||
function word_reverse($str) {
|
||||
$ret = '';
|
||||
while (strlen($str) > 0) {
|
||||
$ret .= substr($str, -8, 8);
|
||||
$str = substr($str, 0, -8);
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
?>
|
||||
17
public/include/pages/account/confirm.inc.php
Normal file
17
public/include/pages/account/confirm.inc.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
// Make sure we are called from index.php
|
||||
if (!defined('SECURITY')) die('Hacking attempt');
|
||||
|
||||
// Confirm an account by token
|
||||
if (!isset($_GET['token']) || empty($_GET['token'])) {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Missing token', 'TYPE' => 'errormsg');
|
||||
} else if (!$aToken = $oToken->getToken($_GET['token'])) {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Unable to activate your account. Invalid token', 'TYPE' => 'errormsg');
|
||||
} else {
|
||||
$user->changeLocked($aToken['account_id']);
|
||||
$oToken->deleteToken($aToken['token']);
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Account activated. Please login.');
|
||||
}
|
||||
$smarty->assign('CONTENT', 'default.tpl');
|
||||
?>
|
||||
@ -30,7 +30,8 @@ if ($user->isAuthenticated()) {
|
||||
if ($continue == true) {
|
||||
// Send balance to address, mind fee for transaction!
|
||||
try {
|
||||
if ($setting->getValue('auto_payout_active') == 0) {
|
||||
$auto_payout = $monitoring->getStatus('auto_payout_active');
|
||||
if ($auto_payout['value'] == 0) {
|
||||
$bitcoin->sendtoaddress($sCoinAddress, $dBalance);
|
||||
} else {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Auto-payout active, please contact site support immidiately to revoke invalid transactions.', 'TYPE' => 'errormsg');
|
||||
@ -53,14 +54,14 @@ if ($user->isAuthenticated()) {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to wallet RPC service', 'TYPE' => 'errormsg');
|
||||
}
|
||||
} else {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Insufficient funds, you need more than ' . $config['txfee'] . ' ' . $conifg['currency'] . ' to cover transaction fees', 'TYPE' => 'errormsg');
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Insufficient funds, you need more than ' . $config['txfee'] . ' ' . $config['currency'] . ' to cover transaction fees', 'TYPE' => 'errormsg');
|
||||
}
|
||||
$setting->setValue('manual_payout_active', 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'updateAccount':
|
||||
if ($user->updateAccount($_SESSION['USERDATA']['id'], $_POST['paymentAddress'], $_POST['payoutThreshold'], $_POST['donatePercent'], $_POST['email'])) {
|
||||
if ($user->updateAccount($_SESSION['USERDATA']['id'], $_POST['paymentAddress'], $_POST['payoutThreshold'], $_POST['donatePercent'], $_POST['email'], $_POST['is_anonymous'])) {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Account details updated', 'TYPE' => 'success');
|
||||
} else {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Failed to update your account: ' . $user->getError(), 'TYPE' => 'errormsg');
|
||||
|
||||
25
public/include/pages/account/invitations.inc.php
Normal file
25
public/include/pages/account/invitations.inc.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
// Make sure we are called from index.php
|
||||
if (!defined('SECURITY')) die('Hacking attempt');
|
||||
|
||||
if ($user->isAuthenticated()) {
|
||||
if (!$setting->getValue('disable_invitations')) {
|
||||
if ($invitation->getCountInvitations($_SESSION['USERDATA']['id']) >= $config['accounts']['invitations']['count']) {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'You have exceeded the allowed invitations of ' . $config['accounts']['invitations']['count'], 'TYPE' => 'errormsg');
|
||||
} else if (isset($_POST['do']) && $_POST['do'] == 'sendInvitation') {
|
||||
if ($invitation->sendInvitation($_SESSION['USERDATA']['id'], $_POST['data'])) {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Invitation sent');
|
||||
} else {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Unable to send invitation to recipient: ' . $invitation->getError(), 'TYPE' => 'errormsg');
|
||||
}
|
||||
}
|
||||
$aInvitations = $invitation->getInvitations($_SESSION['USERDATA']['id']);
|
||||
$smarty->assign('INVITATIONS', $aInvitations);
|
||||
} else {
|
||||
$aInvitations = array();
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Invitations are disabled', 'TYPE' => 'errormsg');
|
||||
}
|
||||
}
|
||||
$smarty->assign('CONTENT', 'default.tpl');
|
||||
?>
|
||||
@ -8,5 +8,6 @@ if ($user->isAuthenticated()) {
|
||||
$user->setUserFailed($_SESSION['USERDATA']['id'], 0);
|
||||
header("Location: " . $_SERVER['HTTP_REFERER']);
|
||||
}
|
||||
|
||||
// Somehow we still need to load this empty template
|
||||
$smarty->assign("CONTENT", "../../global/empty.tpl");
|
||||
?>
|
||||
|
||||
@ -6,6 +6,6 @@ if ($user->isAuthenticated()) {
|
||||
$aTransactions = $transaction->getTransactions($_SESSION['USERDATA']['id']);
|
||||
if (!$aTransactions) $_SESSION['POPUP'][] = array('CONTENT' => 'Could not find any transaction', 'TYPE' => 'errormsg');
|
||||
$smarty->assign('TRANSACTIONS', $aTransactions);
|
||||
$smarty->assign('CONTENT', 'default.tpl');
|
||||
}
|
||||
$smarty->assign('CONTENT', 'default.tpl');
|
||||
?>
|
||||
|
||||
108
public/include/pages/admin/monitoring.inc.php
Normal file
108
public/include/pages/admin/monitoring.inc.php
Normal file
@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
// Make sure we are called from index.php
|
||||
if (!defined('SECURITY')) die('Hacking attempt');
|
||||
|
||||
// Check user to ensure they are admin
|
||||
if (!$user->isAuthenticated() || !$user->isAdmin($_SESSION['USERDATA']['id'])) {
|
||||
header("HTTP/1.1 404 Page not found");
|
||||
die("404 Page not found");
|
||||
}
|
||||
|
||||
// Fetch settings to propagate to template
|
||||
$aCronStatus = array(
|
||||
'statistics' => array (
|
||||
array( 'NAME' => 'Exit Code', 'STATUS' => $monitoring->getStatus('statistics_status') ),
|
||||
array( 'NAME' => 'Active', 'STATUS' => $monitoring->getStatus('statistics_active') ),
|
||||
array( 'NAME' => 'Runtime', 'STATUS' => $monitoring->getStatus('statistics_runtime') ),
|
||||
array( 'NAME' => 'Last Run', 'STATUS' => $monitoring->getStatus('statistics_starttime') ),
|
||||
array( 'NAME' => 'Last Run', 'STATUS' => $monitoring->getStatus('statistics_endtime') ),
|
||||
array( 'NAME' => 'Last Message', 'STATUS' => $monitoring->getStatus('statistics_message') ),
|
||||
),
|
||||
'auto_payout' => array (
|
||||
array( 'NAME' => 'Exit Code', 'STATUS' => $monitoring->getStatus('auto_payout_status') ),
|
||||
array( 'NAME' => 'Active', 'STATUS' => $monitoring->getStatus('auto_payout_active') ),
|
||||
array( 'NAME' => 'Runtime', 'STATUS' => $monitoring->getStatus('auto_payout_runtime') ),
|
||||
array( 'NAME' => 'Last Run', 'STATUS' => $monitoring->getStatus('auto_payout_starttime') ),
|
||||
array( 'NAME' => 'Last Run', 'STATUS' => $monitoring->getStatus('auto_payout_endtime') ),
|
||||
array( 'NAME' => 'Last Message', 'STATUS' => $monitoring->getStatus('auto_payout_message') ),
|
||||
),
|
||||
'archive_cleanup' => array (
|
||||
array( 'NAME' => 'Exit Code', 'STATUS' => $monitoring->getStatus('archive_cleanup_status') ),
|
||||
array( 'NAME' => 'Active', 'STATUS' => $monitoring->getStatus('archive_cleanup_active') ),
|
||||
array( 'NAME' => 'Runtime', 'STATUS' => $monitoring->getStatus('archive_cleanup_runtime') ),
|
||||
array( 'NAME' => 'Last Run', 'STATUS' => $monitoring->getStatus('archive_cleanup_starttime') ),
|
||||
array( 'NAME' => 'Last Run', 'STATUS' => $monitoring->getStatus('archive_cleanup_endtime') ),
|
||||
array( 'NAME' => 'Last Message', 'STATUS' => $monitoring->getStatus('archive_cleanup_message') ),
|
||||
),
|
||||
'blockupdate' => array (
|
||||
array( 'NAME' => 'Exit Code', 'STATUS' => $monitoring->getStatus('blockupdate_status') ),
|
||||
array( 'NAME' => 'Active', 'STATUS' => $monitoring->getStatus('blockupdate_active') ),
|
||||
array( 'NAME' => 'Runtime', 'STATUS' => $monitoring->getStatus('blockupdate_runtime') ),
|
||||
array( 'NAME' => 'Last Run', 'STATUS' => $monitoring->getStatus('blockupdate_starttime') ),
|
||||
array( 'NAME' => 'Last Run', 'STATUS' => $monitoring->getStatus('blockupdate_endtime') ),
|
||||
array( 'NAME' => 'Last Message', 'STATUS' => $monitoring->getStatus('blockupdate_message') ),
|
||||
),
|
||||
'findblock' => array (
|
||||
array( 'NAME' => 'Exit Code', 'STATUS' => $monitoring->getStatus('findblock_status') ),
|
||||
array( 'NAME' => 'Active', 'STATUS' => $monitoring->getStatus('findblock_active') ),
|
||||
array( 'NAME' => 'Runtime', 'STATUS' => $monitoring->getStatus('findblock_runtime') ),
|
||||
array( 'NAME' => 'Last Run', 'STATUS' => $monitoring->getStatus('findblock_starttime') ),
|
||||
array( 'NAME' => 'Last Run', 'STATUS' => $monitoring->getStatus('findblock_endtime') ),
|
||||
array( 'NAME' => 'Last Message', 'STATUS' => $monitoring->getStatus('findblock_message') ),
|
||||
),
|
||||
'notifications' => array (
|
||||
array( 'NAME' => 'Exit Code', 'STATUS' => $monitoring->getStatus('notifications_status') ),
|
||||
array( 'NAME' => 'Active', 'STATUS' => $monitoring->getStatus('notifications_active') ),
|
||||
array( 'NAME' => 'Runtime', 'STATUS' => $monitoring->getStatus('notifications_runtime') ),
|
||||
array( 'NAME' => 'Last Run', 'STATUS' => $monitoring->getStatus('notifications_starttime') ),
|
||||
array( 'NAME' => 'Last Run', 'STATUS' => $monitoring->getStatus('notifications_endtime') ),
|
||||
array( 'NAME' => 'Last Message', 'STATUS' => $monitoring->getStatus('notifications_message') ),
|
||||
),
|
||||
'tickerupdate' => array (
|
||||
array( 'NAME' => 'Exit Code', 'STATUS' => $monitoring->getStatus('tickerupdate_status') ),
|
||||
array( 'NAME' => 'Active', 'STATUS' => $monitoring->getStatus('tickerupdate_active') ),
|
||||
array( 'NAME' => 'Runtime', 'STATUS' => $monitoring->getStatus('tickerupdate_runtime') ),
|
||||
array( 'NAME' => 'Last Run', 'STATUS' => $monitoring->getStatus('tickerupdate_starttime') ),
|
||||
array( 'NAME' => 'Last Run', 'STATUS' => $monitoring->getStatus('tickerupdate_endtime') ),
|
||||
array( 'NAME' => 'Last Message', 'STATUS' => $monitoring->getStatus('tickerupdate_message') ),
|
||||
)
|
||||
);
|
||||
// Payout system specifics
|
||||
switch ($config['payout_system']) {
|
||||
case 'pplns':
|
||||
$aCronStatus['pplns_payout'] = array (
|
||||
array( 'NAME' => 'Exit Code', 'STATUS' => $monitoring->getStatus('pplns_payout_status') ),
|
||||
array( 'NAME' => 'Active', 'STATUS' => $monitoring->getStatus('pplns_payout_active') ),
|
||||
array( 'NAME' => 'Runtime', 'STATUS' => $monitoring->getStatus('pplns_payout_runtime') ),
|
||||
array( 'NAME' => 'Last Run', 'STATUS' => $monitoring->getStatus('pplns_payout_starttime') ),
|
||||
array( 'NAME' => 'Last Run', 'STATUS' => $monitoring->getStatus('pplns_payout_endtime') ),
|
||||
array( 'NAME' => 'Last Message', 'STATUS' => $monitoring->getStatus('pplns_payout_message') ),
|
||||
);
|
||||
break;
|
||||
case 'pps':
|
||||
$aCronStatus['pps_payout'] = array(
|
||||
array( 'NAME' => 'Exit Code', 'STATUS' => $monitoring->getStatus('pps_payout_status') ),
|
||||
array( 'NAME' => 'Active', 'STATUS' => $monitoring->getStatus('pps_payout_active') ),
|
||||
array( 'NAME' => 'Runtime', 'STATUS' => $monitoring->getStatus('pps_payout_runtime') ),
|
||||
array( 'NAME' => 'Last Run', 'STATUS' => $monitoring->getStatus('pps_payout_starttime') ),
|
||||
array( 'NAME' => 'Last Run', 'STATUS' => $monitoring->getStatus('pps_payout_endtime') ),
|
||||
array( 'NAME' => 'Last Message', 'STATUS' => $monitoring->getStatus('pps_payout_message') ),
|
||||
);
|
||||
break;
|
||||
case 'prop':
|
||||
$aCronStatus['proportional_payout'] = array(
|
||||
array( 'NAME' => 'Exit Code', 'STATUS' => $monitoring->getStatus('proportional_payout_status') ),
|
||||
array( 'NAME' => 'Active', 'STATUS' => $monitoring->getStatus('proportional_payout_active') ),
|
||||
array( 'NAME' => 'Runtime', 'STATUS' => $monitoring->getStatus('proportional_payout_runtime') ),
|
||||
array( 'NAME' => 'Last Run', 'STATUS' => $monitoring->getStatus('proportional_payout_starttime') ),
|
||||
array( 'NAME' => 'Last Run', 'STATUS' => $monitoring->getStatus('proportional_payout_endtime') ),
|
||||
array( 'NAME' => 'Last Message', 'STATUS' => $monitoring->getStatus('proportional_payout_message') ),
|
||||
);
|
||||
break;
|
||||
}
|
||||
$smarty->assign("CRONSTATUS", $aCronStatus);
|
||||
|
||||
// Tempalte specifics
|
||||
$smarty->assign("CONTENT", "default.tpl");
|
||||
?>
|
||||
@ -19,6 +19,7 @@ if (@$_REQUEST['do'] == 'save' && !empty($_REQUEST['data'])) {
|
||||
// Fetch settings to propagate to template
|
||||
$smarty->assign("MAINTENANCE", $setting->getValue('maintenance'));
|
||||
$smarty->assign("LOCKREGISTRATION", $setting->getValue('lock_registration'));
|
||||
$smarty->assign("DISABLEINVITATIONS", $setting->getValue('disable_invitations'));
|
||||
|
||||
// Tempalte specifics
|
||||
$smarty->assign("CONTENT", "default.tpl");
|
||||
|
||||
@ -2,10 +2,20 @@
|
||||
|
||||
// Make sure we are called from index.php
|
||||
if (!defined('SECURITY')) die('Hacking attempt');
|
||||
if ($user->isAuthenticated()) {
|
||||
|
||||
// Check user to ensure they are admin
|
||||
if (!$user->isAuthenticated() || !$user->isAdmin($_SESSION['USERDATA']['id'])) {
|
||||
header("HTTP/1.1 404 Page not found");
|
||||
die("404 Page not found");
|
||||
}
|
||||
|
||||
if (!$smarty->isCached('master.tpl', $smarty_cache_key)) {
|
||||
$debug->append('No cached version available, fetching from backend', 3);
|
||||
$aTransactions = $transaction->getAllTransactions(@$_REQUEST['start']);
|
||||
if (!$aTransactions) $_SESSION['POPUP'][] = array('CONTENT' => 'Could not find any transaction', 'TYPE' => 'errormsg');
|
||||
$smarty->assign('TRANSACTIONS', $aTransactions);
|
||||
$smarty->assign('CONTENT', 'default.tpl');
|
||||
} else {
|
||||
$debug->append('Using cached page', 3);
|
||||
}
|
||||
$smarty->assign('TRANSACTIONS', $aTransactions);
|
||||
$smarty->assign('CONTENT', 'default.tpl');
|
||||
?>
|
||||
|
||||
@ -34,10 +34,17 @@ if (@$_POST['query']) {
|
||||
$aBalance = $transaction->getBalance($aUser['id']);
|
||||
$aUser['balance'] = $aBalance['confirmed'];
|
||||
$aUser['hashrate'] = $statistics->getUserHashrate($aUser['id']);
|
||||
$aUser['payout']['est_block'] = round(( (int)$aUser['shares'] / (int)$aRoundShares['valid'] ) * (int)$config['reward'], 3);
|
||||
$aUser['payout']['est_fee'] = round(($config['fees'] / 100) * $aUser['payout']['est_block'], 3);
|
||||
$aUser['payout']['est_donation'] = round((( $aUser['donate_percent'] / 100) * ($aUser['payout']['est_block'] - $aUser['payout']['est_fee'])), 3);
|
||||
$aUser['payout']['est_payout'] = round($aUser['payout']['est_block'] - $aUser['payout']['est_donation'] - $aUser['payout']['est_fee'], 3);
|
||||
if ($aUser['shares'] > 0) {
|
||||
$aUser['payout']['est_block'] = round(( (int)$aUser['shares'] / (int)$aRoundShares['valid'] ) * (int)$config['reward'], 3);
|
||||
$aUser['payout']['est_fee'] = round(($config['fees'] / 100) * $aUser['payout']['est_block'], 3);
|
||||
$aUser['payout']['est_donation'] = round((( $aUser['donate_percent'] / 100) * ($aUser['payout']['est_block'] - $aUser['payout']['est_fee'])), 3);
|
||||
$aUser['payout']['est_payout'] = round($aUser['payout']['est_block'] - $aUser['payout']['est_donation'] - $aUser['payout']['est_fee'], 3);
|
||||
} else {
|
||||
$aUser['payout']['est_block'] = 0;
|
||||
$aUser['payout']['est_fee'] = 0;
|
||||
$aUser['payout']['est_donation'] = 0;
|
||||
$aUser['payout']['est_payout'] = 0;
|
||||
}
|
||||
$aUsers[$iKey] = $aUser;
|
||||
}
|
||||
// Assign our variables
|
||||
|
||||
@ -9,15 +9,22 @@ if (!$user->isAuthenticated() || !$user->isAdmin($_SESSION['USERDATA']['id'])) {
|
||||
die("404 Page not found");
|
||||
}
|
||||
|
||||
if ($bitcoin->can_connect() === true){
|
||||
$dBalance = $bitcoin->query('getbalance');
|
||||
if (!$smarty->isCached('master.tpl', $smarty_cache_key)) {
|
||||
$debug->append('No cached version available, fetching from backend', 3);
|
||||
if ($bitcoin->can_connect() === true){
|
||||
$dBalance = $bitcoin->query('getbalance');
|
||||
} else {
|
||||
$dBalance = 0;
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to wallet RPC service: ' . $bitcoin->can_connect(), 'TYPE' => 'errormsg');
|
||||
}
|
||||
// Fetch locked balance from transactions
|
||||
$dLockedBalance = $transaction->getLockedBalance();
|
||||
} else {
|
||||
$dBalance = 0;
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to wallet RPC service: ' . $bitcoin->can_connect(), 'TYPE' => 'errormsg');
|
||||
$debug->append('Using cached page', 3);
|
||||
}
|
||||
|
||||
$smarty->assign("BALANCE", $dBalance);
|
||||
$smarty->assign("LOCKED", $transaction->getLockedBalance());
|
||||
$smarty->assign("LOCKED", $dLockedBalance);
|
||||
|
||||
// Tempalte specifics
|
||||
$smarty->assign("CONTENT", "default.tpl");
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
<?php
|
||||
|
||||
// Make sure we are called from index.php
|
||||
if (!defined('SECURITY'))
|
||||
die('Hacking attempt');
|
||||
if (!defined('SECURITY')) die('Hacking attempt');
|
||||
|
||||
// Check if the API is activated
|
||||
$api->isActive();
|
||||
|
||||
// Check for valid API key
|
||||
$id = $user->checkApiKey($_REQUEST['api_key']);
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
<?php
|
||||
|
||||
// Make sure we are called from index.php
|
||||
if (!defined('SECURITY'))
|
||||
die('Hacking attempt');
|
||||
if (!defined('SECURITY')) die('Hacking attempt');
|
||||
|
||||
// Check if the API is activated
|
||||
$api->isActive();
|
||||
|
||||
// Check user token
|
||||
$id = $user->checkApiKey($_REQUEST['api_key']);
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
<?php
|
||||
|
||||
// Make sure we are called from index.php
|
||||
if (!defined('SECURITY'))
|
||||
die('Hacking attempt');
|
||||
if (!defined('SECURITY')) die('Hacking attempt');
|
||||
|
||||
// Check if the API is activated
|
||||
$api->isActive();
|
||||
|
||||
// Check user token
|
||||
$id = $user->checkApiKey($_REQUEST['api_key']);
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
<?php
|
||||
|
||||
// Make sure we are called from index.php
|
||||
if (!defined('SECURITY'))
|
||||
die('Hacking attempt');
|
||||
if (!defined('SECURITY')) die('Hacking attempt');
|
||||
|
||||
// Check if the API is activated
|
||||
$api->isActive();
|
||||
|
||||
// Check user token
|
||||
$id = $user->checkApiKey($_REQUEST['api_key']);
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
<?php
|
||||
|
||||
// Make sure we are called from index.php
|
||||
if (!defined('SECURITY'))
|
||||
die('Hacking attempt');
|
||||
if (!defined('SECURITY')) die('Hacking attempt');
|
||||
|
||||
// Check if the API is activated
|
||||
$api->isActive();
|
||||
|
||||
// Check user token
|
||||
$id = $user->checkApiKey($_REQUEST['api_key']);
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
<?php
|
||||
|
||||
// Make sure we are called from index.php
|
||||
if (!defined('SECURITY'))
|
||||
die('Hacking attempt');
|
||||
if (!defined('SECURITY')) die('Hacking attempt');
|
||||
|
||||
// Check if the API is activated
|
||||
$api->isActive();
|
||||
|
||||
// Check user token
|
||||
$id = $user->checkApiKey($_REQUEST['api_key']);
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
<?php
|
||||
|
||||
// Make sure we are called from index.php
|
||||
if (!defined('SECURITY'))
|
||||
die('Hacking attempt');
|
||||
if (!defined('SECURITY')) die('Hacking attempt');
|
||||
|
||||
// Check if the API is activated
|
||||
$api->isActive();
|
||||
|
||||
// Check user token
|
||||
$id = $user->checkApiKey($_REQUEST['api_key']);
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
<?php
|
||||
|
||||
// Make sure we are called from index.php
|
||||
if (!defined('SECURITY'))
|
||||
die('Hacking attempt');
|
||||
if (!defined('SECURITY')) die('Hacking attempt');
|
||||
|
||||
// Check if the API is activated
|
||||
$api->isActive();
|
||||
|
||||
// Check user token
|
||||
$id = $user->checkApiKey($_REQUEST['api_key']);
|
||||
|
||||
@ -3,6 +3,9 @@
|
||||
// Make sure we are called from index.php
|
||||
if (!defined('SECURITY')) die('Hacking attempt');
|
||||
|
||||
// Check if the API is activated
|
||||
$api->isActive();
|
||||
|
||||
// Check user token
|
||||
$user_id = $user->checkApiKey($_REQUEST['api_key']);
|
||||
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
<?php
|
||||
|
||||
// Make sure we are called from index.php
|
||||
if (!defined('SECURITY'))
|
||||
die('Hacking attempt');
|
||||
if (!defined('SECURITY')) die('Hacking attempt');
|
||||
|
||||
// Check if the API is activated
|
||||
$api->isActive();
|
||||
|
||||
// Check user token
|
||||
$id = $user->checkApiKey($_REQUEST['api_key']);
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
<?php
|
||||
|
||||
// Make sure we are called from index.php
|
||||
if (!defined('SECURITY'))
|
||||
die('Hacking attempt');
|
||||
if (!defined('SECURITY')) die('Hacking attempt');
|
||||
|
||||
// Check if the API is activated
|
||||
$api->isActive();
|
||||
|
||||
// Check user token
|
||||
$user_id = $user->checkApiKey($_REQUEST['api_key']);
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
<?php
|
||||
|
||||
// Make sure we are called from index.php
|
||||
if (!defined('SECURITY'))
|
||||
die('Hacking attempt');
|
||||
if (!defined('SECURITY')) die('Hacking attempt');
|
||||
|
||||
// Check if the API is activated
|
||||
$api->isActive();
|
||||
|
||||
// Check user token
|
||||
$user_id = $user->checkApiKey($_REQUEST['api_key']);
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
<?php
|
||||
|
||||
// Make sure we are called from index.php
|
||||
if (!defined('SECURITY'))
|
||||
die('Hacking attempt');
|
||||
if (!defined('SECURITY')) die('Hacking attempt');
|
||||
|
||||
// {"pool_name":"Pool-X.eu","hashrate":"511128.99","workers":"2104","shares_this_round":92450,"last_block":"365294","network_hashrate":17327056.06}
|
||||
// Check if the API is activated
|
||||
$api->isActive();
|
||||
|
||||
// Fetch last block information
|
||||
$aLastBlock = $block->getLast();
|
||||
|
||||
@ -6,16 +6,21 @@ if (!defined('SECURITY')) die('Hacking attempt');
|
||||
// Include markdown library
|
||||
use \Michelf\Markdown;
|
||||
|
||||
// Fetch active news to display
|
||||
$aNews = $news->getAllActive();
|
||||
if (is_array($aNews)) {
|
||||
foreach ($aNews as $key => $aData) {
|
||||
// Transform Markdown content to HTML
|
||||
$aNews[$key]['content'] = Markdown::defaultTransform($aData['content']);
|
||||
if (!$smarty->isCached('master.tpl', $smarty_cache_key)) {
|
||||
$debug->append('No cached version available, fetching from backend', 3);
|
||||
// Fetch active news to display
|
||||
$aNews = $news->getAllActive();
|
||||
if (is_array($aNews)) {
|
||||
foreach ($aNews as $key => $aData) {
|
||||
// Transform Markdown content to HTML
|
||||
$aNews[$key]['content'] = Markdown::defaultTransform($aData['content']);
|
||||
}
|
||||
}
|
||||
$smarty->assign("NEWS", $aNews);
|
||||
} else {
|
||||
$debug->append('Using cached page', 3);
|
||||
}
|
||||
|
||||
// Load news entries for Desktop site and unauthenticated users
|
||||
$smarty->assign("NEWS", $aNews);
|
||||
$smarty->assign("CONTENT", "default.tpl");
|
||||
?>
|
||||
|
||||
@ -4,14 +4,14 @@
|
||||
if (!defined('SECURITY'))
|
||||
die('Hacking attempt');
|
||||
|
||||
if ($_POST['do'] == 'useToken') {
|
||||
if ($user->useToken($_POST['token'], $_POST['newPassword'], $_POST['newPassword2'])) {
|
||||
if (isset($_POST['do']) && $_POST['do'] == 'resetPassword') {
|
||||
if ($user->resetPassword($_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");
|
||||
|
||||
?>
|
||||
|
||||
@ -5,7 +5,7 @@ if (!defined('SECURITY'))
|
||||
die('Hacking attempt');
|
||||
|
||||
// Process password reset request
|
||||
if ($user->resetPassword($_POST['username'], $smarty)) {
|
||||
if ($user->initResetPassword($_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');
|
||||
|
||||
@ -3,9 +3,12 @@
|
||||
// Make sure we are called from index.php
|
||||
if (!defined('SECURITY')) die('Hacking attempt');
|
||||
|
||||
if ($setting->getValue('lock_registration')) {
|
||||
if ($setting->getValue('lock_registration') && $setting->getValue('disable_invitations')) {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Account registration is currently disabled. Please try again later.', 'TYPE' => 'errormsg');
|
||||
$smarty->assign("CONTENT", "disabled.tpl");
|
||||
} else if ($setting->getValue('lock_registration') && !$setting->getValue('disable_invitations') && !isset($_GET['token'])) {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Only invited users are allowed to register.', 'TYPE' => 'errormsg');
|
||||
$smarty->assign("CONTENT", "disabled.tpl");
|
||||
} else {
|
||||
if ($config['recaptcha']['enabled']) {
|
||||
require_once(INCLUDE_DIR . '/lib/recaptchalib.php');
|
||||
|
||||
@ -13,33 +13,37 @@ if ($config['recaptcha']['enabled']) {
|
||||
);
|
||||
}
|
||||
|
||||
// Check if recaptcha is enabled, process form data if valid
|
||||
if($config['recaptcha']['enabled'] && $_POST["recaptcha_response_field"] && $_POST["recaptcha_response_field"]!=''){
|
||||
if ($rsp->is_valid) {
|
||||
$smarty->assign("RECAPTCHA", recaptcha_get_html($config['recaptcha']['public_key']));
|
||||
if ($setting->getValue('lock_registration')) {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Account registration is currently disabled. Please try again later.', 'TYPE' => 'errormsg');
|
||||
} else if ($user->register($_POST['username'], $_POST['password1'], $_POST['password2'], $_POST['pin'], $_POST['email1'], $_POST['email2']) && !$setting->getValue('lock_registration')) {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Account created, please login');
|
||||
if ($setting->getValue('disable_invitations') && $setting->getValue('lock_registration')) {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Account registration is currently disabled. Please try again later.', 'TYPE' => 'errormsg');
|
||||
} else if ($setting->getValue('lock_registration') && !$setting->getValue('disable_invitations') && !isset($_POST['token'])) {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Only invited users are allowed to register.', 'TYPE' => 'errormsg');
|
||||
} else {
|
||||
// Check if recaptcha is enabled, process form data if valid
|
||||
if($config['recaptcha']['enabled'] && $_POST["recaptcha_response_field"] && $_POST["recaptcha_response_field"]!=''){
|
||||
if ($rsp->is_valid) {
|
||||
$smarty->assign("RECAPTCHA", recaptcha_get_html($config['recaptcha']['public_key']));
|
||||
isset($_POST['token']) ? $token = $_POST['token'] : $token = '';
|
||||
if ($user->register($_POST['username'], $_POST['password1'], $_POST['password2'], $_POST['pin'], $_POST['email1'], $_POST['email2'], $token)) {
|
||||
$config['accounts']['confirm_email']['enabled'] ? $_SESSION['POPUP'][] = array('CONTENT' => 'Please check your mailbox to activate this account') : $_SESSION['POPUP'][] = array('CONTENT' => 'Account created, please login');
|
||||
} else {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Unable to create account: ' . $user->getError(), 'TYPE' => 'errormsg');
|
||||
}
|
||||
} else {
|
||||
$smarty->assign("RECAPTCHA", recaptcha_get_html($config['recaptcha']['public_key'], $rsp->error));
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Invalid Captcha, please try again. (' . $rsp->error . ')', 'TYPE' => 'errormsg');
|
||||
}
|
||||
// Empty captcha
|
||||
} else if ($config['recaptcha']['enabled']) {
|
||||
$smarty->assign("RECAPTCHA", recaptcha_get_html($config['recaptcha']['public_key'], $rsp->error));
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Empty Captcha, please try again.', 'TYPE' => 'errormsg');
|
||||
// Captcha disabled
|
||||
} else {
|
||||
isset($_POST['token']) ? $token = $_POST['token'] : $token = '';
|
||||
if ($user->register($_POST['username'], $_POST['password1'], $_POST['password2'], $_POST['pin'], $_POST['email1'], $_POST['email2'], $token)) {
|
||||
$config['accounts']['confirm_email']['enabled'] ? $_SESSION['POPUP'][] = array('CONTENT' => 'Please check your mailbox to activate this account') : $_SESSION['POPUP'][] = array('CONTENT' => 'Account created, please login');
|
||||
} else {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Unable to create account: ' . $user->getError(), 'TYPE' => 'errormsg');
|
||||
}
|
||||
} else {
|
||||
$smarty->assign("RECAPTCHA", recaptcha_get_html($config['recaptcha']['public_key'], $rsp->error));
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Invalid Captcha, please try again. (' . $rsp->error . ')', 'TYPE' => 'errormsg');
|
||||
}
|
||||
// Empty captcha
|
||||
} else if ($config['recaptcha']['enabled']) {
|
||||
$smarty->assign("RECAPTCHA", recaptcha_get_html($config['recaptcha']['public_key'], $rsp->error));
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Empty Captcha, please try again.', 'TYPE' => 'errormsg');
|
||||
// Captcha disabled
|
||||
} else {
|
||||
if ($setting->getValue('lock_registration')) {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Account registration is currently disabled. Please try again later.', 'TYPE' => 'errormsg');
|
||||
} else if ($user->register($_POST['username'], $_POST['password1'], $_POST['password2'], $_POST['pin'], $_POST['email1'], $_POST['email2']) && !$setting->getValue('lock_registration')) {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Account created, please login');
|
||||
} else {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Unable to create account: ' . $user->getError(), 'TYPE' => 'errormsg');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -4,17 +4,23 @@
|
||||
if (!defined('SECURITY'))
|
||||
die('Hacking attempt');
|
||||
|
||||
if ($bitcoin->can_connect() === true){
|
||||
$dDifficulty = $bitcoin->query('getdifficulty');
|
||||
if (is_array($dDifficulty) && array_key_exists('proof-of-work', $dDifficulty))
|
||||
$dDifficulty = $dDifficulty['proof-of-work'];
|
||||
$iBlock = $bitcoin->query('getblockcount');
|
||||
if (!$smarty->isCached('master.tpl', $smarty_cache_key)) {
|
||||
$debug->append('No cached version available, fetching from backend', 3);
|
||||
if ($bitcoin->can_connect() === true){
|
||||
$dDifficulty = $bitcoin->query('getdifficulty');
|
||||
if (is_array($dDifficulty) && array_key_exists('proof-of-work', $dDifficulty))
|
||||
$dDifficulty = $dDifficulty['proof-of-work'];
|
||||
$iBlock = $bitcoin->query('getblockcount');
|
||||
} else {
|
||||
$dDifficulty = 1;
|
||||
$iBlock = 0;
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to litecoind RPC service: ' . $bitcoin->can_connect(), 'TYPE' => 'errormsg');
|
||||
}
|
||||
$smarty->assign("CURRENTBLOCK", $iBlock);
|
||||
$smarty->assign("DIFFICULTY", $dDifficulty);
|
||||
} else {
|
||||
$dDifficulty = 1;
|
||||
$iBlock = 0;
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to litecoind RPC service: ' . $bitcoin->can_connect(), 'TYPE' => 'errormsg');
|
||||
$debug->append('Using cached page', 3);
|
||||
}
|
||||
|
||||
$smarty->assign("CURRENTBLOCK", $iBlock);
|
||||
$smarty->assign("DIFFICULTY", $dDifficulty);
|
||||
$smarty->assign("CONTENT", "default.tpl");
|
||||
?>
|
||||
|
||||
@ -2,15 +2,24 @@
|
||||
|
||||
// Make sure we are called from index.php
|
||||
if (!defined('SECURITY')) die('Hacking attempt');
|
||||
if (!$user->isAuthenticated()) header("Location: index.php?page=home");
|
||||
|
||||
// Grab the last blocks found
|
||||
empty($_REQUEST['limit']) ? $iLimit = 20 : $iLimit = $_REQUEST['limit'];
|
||||
$aBlocksFoundData = $statistics->getBlocksFound($iLimit);
|
||||
if (!$smarty->isCached('master.tpl', $smarty_cache_key)) {
|
||||
$debug->append('No cached version available, fetching from backend', 3);
|
||||
// Grab the last blocks found
|
||||
$iLimit = 20;
|
||||
$aBlocksFoundData = $statistics->getBlocksFound($iLimit);
|
||||
|
||||
// Propagate content our template
|
||||
$smarty->assign("BLOCKSFOUND", $aBlocksFoundData);
|
||||
$smarty->assign("BLOCKLIMIT", $iLimit);
|
||||
// Propagate content our template
|
||||
$smarty->assign("BLOCKSFOUND", $aBlocksFoundData);
|
||||
$smarty->assign("BLOCKLIMIT", $iLimit);
|
||||
} else {
|
||||
$debug->append('Using cached page', 3);
|
||||
}
|
||||
|
||||
$smarty->assign("CONTENT", "default.tpl");
|
||||
if ($config['website']['acl']['statistics']['blocks'] == 'public') {
|
||||
$smarty->assign("CONTENT", "default.tpl");
|
||||
} else if ($user->isAuthenticated()) {
|
||||
$smarty->assign("CONTENT", "default.tpl");
|
||||
}
|
||||
?>
|
||||
|
||||
@ -1,16 +1,19 @@
|
||||
<?php
|
||||
|
||||
// Make sure we are called from index.php
|
||||
if (!defined('SECURITY'))
|
||||
die('Hacking attempt');
|
||||
if (!defined('SECURITY')) die('Hacking attempt');
|
||||
|
||||
if ($user->isAuthenticated()) {
|
||||
$aHourlyHashRates = $statistics->getHourlyHashrateByAccount($_SESSION['USERDATA']['id']);
|
||||
$aPoolHourlyHashRates = $statistics->getHourlyHashrateByPool();
|
||||
if (!$smarty->isCached('master.tpl', $smarty_cache_key)) {
|
||||
$debug->append('No cached version available, fetching from backend', 3);
|
||||
if ($user->isAuthenticated()) {
|
||||
$aHourlyHashRates = $statistics->getHourlyHashrateByAccount($_SESSION['USERDATA']['id']);
|
||||
$aPoolHourlyHashRates = $statistics->getHourlyHashrateByPool();
|
||||
}
|
||||
$smarty->assign("YOURHASHRATES", @$aHourlyHashRates);
|
||||
$smarty->assign("POOLHASHRATES", @$aPoolHourlyHashRates);
|
||||
} else {
|
||||
$debug->append('Using cached page', 3);
|
||||
}
|
||||
|
||||
// Propagate content our template
|
||||
$smarty->assign("YOURHASHRATES", @$aHourlyHashRates);
|
||||
$smarty->assign("POOLHASHRATES", @$aPoolHourlyHashRates);
|
||||
$smarty->assign("CONTENT", "default.tpl");
|
||||
?>
|
||||
|
||||
@ -1,59 +1,74 @@
|
||||
<?php
|
||||
|
||||
// Make sure we are called from index.php
|
||||
if (!defined('SECURITY'))
|
||||
die('Hacking attempt');
|
||||
if (!defined('SECURITY')) die('Hacking attempt');
|
||||
|
||||
// Fetch data from wallet
|
||||
if ($bitcoin->can_connect() === true){
|
||||
$dDifficulty = $bitcoin->getdifficulty();
|
||||
if (is_array($dDifficulty) && array_key_exists('proof-of-work', $dDifficulty))
|
||||
$dDifficulty = $dDifficulty['proof-of-work'];
|
||||
$iBlock = $bitcoin->getblockcount();
|
||||
if (!$smarty->isCached('master.tpl', $smarty_cache_key)) {
|
||||
$debug->append('No cached version available, fetching from backend', 3);
|
||||
// Fetch data from wallet
|
||||
if ($bitcoin->can_connect() === true){
|
||||
$dDifficulty = $bitcoin->getdifficulty();
|
||||
if (is_array($dDifficulty) && array_key_exists('proof-of-work', $dDifficulty))
|
||||
$dDifficulty = $dDifficulty['proof-of-work'];
|
||||
$iBlock = $bitcoin->getblockcount();
|
||||
$sBlockHash = $bitcoin->query('getblockhash', $iBlock);
|
||||
} else {
|
||||
$dDifficulty = 1;
|
||||
$iBlock = 0;
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to wallet RPC service: ' . $bitcoin->can_connect(), 'TYPE' => 'errormsg');
|
||||
}
|
||||
|
||||
// Top share contributors
|
||||
$aContributorsShares = $statistics->getTopContributors('shares', 15);
|
||||
|
||||
// Top hash contributors
|
||||
$aContributorsHashes = $statistics->getTopContributors('hashes', 15);
|
||||
|
||||
// Grab the last 10 blocks found
|
||||
$iLimit = 5;
|
||||
$aBlocksFoundData = $statistics->getBlocksFound($iLimit);
|
||||
count($aBlocksFoundData) > 0 ? $aBlockData = $aBlocksFoundData[0] : $aBlockData = array();
|
||||
|
||||
// Estimated time to find the next block
|
||||
$iCurrentPoolHashrate = $statistics->getCurrentHashrate();
|
||||
|
||||
// Time in seconds, not hours, using modifier in smarty to translate
|
||||
$iCurrentPoolHashrate > 0 ? $iEstTime = $dDifficulty * pow(2,32) / ($iCurrentPoolHashrate * 1000) : $iEstTime = 0;
|
||||
|
||||
// Time since last block
|
||||
$now = new DateTime( "now" );
|
||||
if (!empty($aBlockData)) {
|
||||
$dTimeSinceLast = ($now->getTimestamp() - $aBlockData['time']);
|
||||
if ($dTimeSinceLast < 0) $dTimeSinceLast = 0;
|
||||
} else {
|
||||
$dTimeSinceLast = 0;
|
||||
}
|
||||
|
||||
// Propagate content our template
|
||||
$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);
|
||||
$smarty->assign("CURRENTBLOCKHASH", $sBlockHash);
|
||||
if (count($aBlockData) > 0) {
|
||||
$smarty->assign("LASTBLOCK", $aBlockData['height']);
|
||||
$smarty->assign("LASTBLOCKHASH", $aBlockData['blockhash']);
|
||||
} else {
|
||||
$smarty->assign("LASTBLOCK", 0);
|
||||
}
|
||||
$smarty->assign("DIFFICULTY", $dDifficulty);
|
||||
$smarty->assign("REWARD", $config['reward']);
|
||||
} else {
|
||||
$dDifficulty = 1;
|
||||
$iBlock = 0;
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to wallet RPC service: ' . $bitcoin->can_connect(), 'TYPE' => 'errormsg');
|
||||
$debug->append('Using cached page', 3);
|
||||
}
|
||||
|
||||
// Top share contributors
|
||||
$aContributorsShares = $statistics->getTopContributors('shares', 15);
|
||||
|
||||
// Top hash contributors
|
||||
$aContributorsHashes = $statistics->getTopContributors('hashes', 15);
|
||||
|
||||
// Grab the last 10 blocks found
|
||||
$iLimit = 5;
|
||||
$aBlocksFoundData = $statistics->getBlocksFound($iLimit);
|
||||
count($aBlocksFoundData) > 0 ? $aBlockData = $aBlocksFoundData[0] : $aBlockData = array();
|
||||
|
||||
// Estimated time to find the next block
|
||||
$iCurrentPoolHashrate = $statistics->getCurrentHashrate();
|
||||
|
||||
// Time in seconds, not hours, using modifier in smarty to translate
|
||||
$iCurrentPoolHashrate > 0 ? $iEstTime = $dDifficulty * pow(2,32) / ($iCurrentPoolHashrate * 1000) : $iEstTime = 0;
|
||||
|
||||
// Time since last block
|
||||
$now = new DateTime( "now" );
|
||||
if (!empty($aBlockData)) {
|
||||
$dTimeSinceLast = ($now->getTimestamp() - $aBlockData['time']);
|
||||
} else {
|
||||
$dTimeSinceLast = 0;
|
||||
}
|
||||
|
||||
// Propagate content our template
|
||||
$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);
|
||||
count($aBlockData) > 0 ? $smarty->assign("LASTBLOCK", $aBlockData['height']) : $smarty->assign("LASTBLOCK", 0);
|
||||
$smarty->assign("DIFFICULTY", $dDifficulty);
|
||||
$smarty->assign("REWARD", $config['reward']);
|
||||
|
||||
if ($user->isAuthenticated()) {
|
||||
// Public / private page detection
|
||||
if ($config['website']['acl']['statistics']['pool'] == 'public') {
|
||||
$smarty->assign("CONTENT", "authenticated.tpl");
|
||||
} else if ($user->isAuthenticated() && $config['website']['acl']['statistics']['pool'] == 'private') {
|
||||
$smarty->assign("CONTENT", "authenticated.tpl");
|
||||
} else {
|
||||
$smarty->assign("CONTENT", "../default.tpl");
|
||||
|
||||
@ -18,8 +18,14 @@ $smarty = new Smarty;
|
||||
$debug->append('Define Smarty Paths', 3);
|
||||
$smarty->template_dir = BASEPATH . 'templates/' . THEME . '/';
|
||||
$smarty->compile_dir = BASEPATH . 'templates/compile/';
|
||||
$smarty_cache_key = md5(serialize($_REQUEST) . serialize(@$_SESSION['USERDATA']['id']));
|
||||
|
||||
// Optional smarty caching, check Smarty documentation for details
|
||||
$smarty->caching = $config['cache'];
|
||||
$smarty->cache_dir = BASEPATH . "templates/cache";
|
||||
if ($config['smarty']['cache']) {
|
||||
$debug->append('Enable smarty cache');
|
||||
$smarty->setCaching(Smarty::CACHING_LIFETIME_SAVED);
|
||||
$smarty->cache_lifetime = $config['smarty']['cache_lifetime'];
|
||||
$smarty->cache_dir = BASEPATH . "templates/cache";
|
||||
$smarty->use_sub_dirs = true;
|
||||
}
|
||||
?>
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
<?php
|
||||
|
||||
// Make sure we are called from index.php
|
||||
if (!defined('SECURITY'))
|
||||
die('Hacking attempt');
|
||||
if (!defined('SECURITY')) die('Hacking attempt');
|
||||
|
||||
// Globally available variables
|
||||
$debug->append('Global smarty variables', 3);
|
||||
|
||||
$debug->append('No cached page detected, loading smarty globals', 3);
|
||||
// Defaults to get rid of PHP Notice warnings
|
||||
$dDifficulty = 1;
|
||||
$aRoundShares = 1;
|
||||
@ -24,7 +24,7 @@ if (@$_SESSION['AUTHENTICATED']) {
|
||||
$bitcoin->can_connect() === true ? $dNetworkHashrate = $bitcoin->query('getnetworkhashps') : $dNetworkHashrate = 0;
|
||||
|
||||
// Fetch some data
|
||||
$iCurrentActiveWorkers = $worker->getCountAllActiveWorkers();
|
||||
if (!$iCurrentActiveWorkers = $worker->getCountAllActiveWorkers()) $iCurrentActiveWorkers = 0;
|
||||
$iCurrentPoolHashrate = $statistics->getCurrentHashrate();
|
||||
$iCurrentPoolShareRate = $statistics->getCurrentShareRate();
|
||||
|
||||
@ -47,7 +47,9 @@ $aGlobal = array(
|
||||
'blockexplorer' => $config['blockexplorer'],
|
||||
'chaininfo' => $config['chaininfo'],
|
||||
'config' => array(
|
||||
'website' => array( 'title' => $config['website']['title'] ),
|
||||
'website' => $config['website'],
|
||||
'accounts' => $config['accounts'],
|
||||
'disable_invitations' => $setting->getValue('disable_invitations'),
|
||||
'price' => array( 'currency' => $config['price']['currency'] ),
|
||||
'targetdiff' => $config['difficulty'],
|
||||
'currency' => $config['currency'],
|
||||
@ -83,9 +85,7 @@ if (@$_SESSION['USERDATA']['id']) {
|
||||
$aGlobal['userdata']['sharerate'] = $statistics->getUserSharerate($_SESSION['USERDATA']['id']);
|
||||
|
||||
switch ($config['payout_system']) {
|
||||
case 'pps':
|
||||
break;
|
||||
default:
|
||||
case 'prop' || 'pplns':
|
||||
// Some estimations
|
||||
if (@$aRoundShares['valid'] > 0) {
|
||||
$aGlobal['userdata']['est_block'] = round(( (int)$aGlobal['userdata']['shares']['valid'] / (int)$aRoundShares['valid'] ) * (float)$config['reward'], 8);
|
||||
@ -98,12 +98,20 @@ if (@$_SESSION['USERDATA']['id']) {
|
||||
$aGlobal['userdata']['est_donation'] = 0;
|
||||
$aGlobal['userdata']['est_payout'] = 0;
|
||||
}
|
||||
case 'pplns':
|
||||
if ($iAvgBlockShares = round($block->getAvgBlockShares($config['pplns']['blockavg']['blockcount']))) {
|
||||
$aGlobal['pplns']['target'] = $iAvgBlockShares;
|
||||
} else {
|
||||
$aGlobal['pplns']['target'] = $config['pplns']['shares']['default'];
|
||||
}
|
||||
break;
|
||||
case 'pps':
|
||||
break;
|
||||
}
|
||||
|
||||
// Site-wide notifications, based on user events
|
||||
if ($aGlobal['userdata']['balance']['confirmed'] >= $config['ap_threshold']['max'])
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'You have exceeded your accounts balance. Please transfer some ' . $config['currency'] . "!", 'TYPE' => 'errormsg');
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'You have exceeded the pools configured ' . $config['currency'] . ' warning threshold. Please initiate a transfer!', 'TYPE' => 'errormsg');
|
||||
if ($user->getUserFailed($_SESSION['USERDATA']['id']) > 0)
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'You have ' . $user->getUserFailed($_SESSION['USERDATA']['id']) . ' failed login attempts! <a href="?page=account&action=reset_failed">Reset Counter</a>', 'TYPE' => 'errormsg');
|
||||
}
|
||||
|
||||
@ -24,13 +24,15 @@ define("BASEPATH", "./");
|
||||
// Our security check
|
||||
define("SECURITY", 1);
|
||||
|
||||
// Start a session
|
||||
session_start();
|
||||
$session_id = session_id();
|
||||
|
||||
// Include our configuration (holding defines for the requires)
|
||||
if (!include_once(BASEPATH . 'include/config/global.inc.php')) die('Unable to load site configuration');
|
||||
|
||||
// Start a session
|
||||
session_set_cookie_params(time()+$config['cookie']['duration'], $config['cookie']['path'], $config['cookie']['domain'], $config['cookie']['secure'], $config['cookie']['httponly']);
|
||||
session_start();
|
||||
setcookie(session_name(),session_id(),time()+$config['cookie']['duration'], $config['cookie']['path'], $config['cookie']['domain'], $config['cookie']['secure'], $config['cookie']['httponly']);
|
||||
$session_id = session_id();
|
||||
|
||||
// Load Classes, they name defines the $ variable used
|
||||
// We include all needed files here, even though our templates could load them themself
|
||||
require_once(INCLUDE_DIR . '/autoloader.inc.php');
|
||||
@ -82,7 +84,7 @@ $smarty->assign('DebuggerInfo', $debug->getDebugInfo());
|
||||
|
||||
// Display our page
|
||||
if (!@$supress_master)
|
||||
$smarty->display("master.tpl", md5(serialize($_REQUEST)));
|
||||
$smarty->display("master.tpl", $smarty_cache_key);
|
||||
|
||||
// Unset any temporary values here
|
||||
unset($_SESSION['POPUP']);
|
||||
|
||||
11
public/templates/mail/invitations/body.tpl
Normal file
11
public/templates/mail/invitations/body.tpl
Normal file
@ -0,0 +1,11 @@
|
||||
<html>
|
||||
<body>
|
||||
<p>Hello valued miner,</p><br />
|
||||
<p>{$DATA.username} invited you to participate on this pool:
|
||||
<p>http://{$smarty.server.SERVER_NAME}{$smarty.server.PHP_SELF}?page=register&token={$DATA.token}</p>
|
||||
{if $DATA.message}<p>Personal message:</p><p>{$DATA.message}</p>{/if}
|
||||
<p></p>
|
||||
<p>Cheers,</p>
|
||||
<p>Website Administration</p>
|
||||
</body>
|
||||
</html>
|
||||
@ -1,8 +1,8 @@
|
||||
<html>
|
||||
<body>
|
||||
<p>Hello {$USERNAME},</p><br />
|
||||
<p>Hello {$DATA.username},</p><br />
|
||||
<p>You have requested a password reset through our online form. In order to complete the request please follow this link:</p>
|
||||
<p>http://{$smarty.server.SERVER_NAME}{$smarty.server.PHP_SELF}?page=password&action=change&token={$TOKEN}</p>
|
||||
<p>http://{$smarty.server.SERVER_NAME}{$smarty.server.PHP_SELF}?page=password&action=change&token={$DATA.token}</p>
|
||||
<p>You will be asked to change your password. You can then use this new password to login to your account.</p>
|
||||
<p>Cheers,</p>
|
||||
<p>Website Administration</p>
|
||||
10
public/templates/mail/register/confirm_email.tpl
Normal file
10
public/templates/mail/register/confirm_email.tpl
Normal file
@ -0,0 +1,10 @@
|
||||
<html>
|
||||
<body>
|
||||
<p>Hello {$DATA.username},</p><br />
|
||||
<p>You have create a new account. In order to complete the registration process please follow this link:</p>
|
||||
<p>http://{$smarty.server.SERVER_NAME}{$smarty.server.PHP_SELF}?page=account&action=confirm&token={$DATA.token}</p>
|
||||
<p></p>
|
||||
<p>Cheers,</p>
|
||||
<p>Website Administration</p>
|
||||
</body>
|
||||
</html>
|
||||
@ -12,7 +12,7 @@
|
||||
<tbody>
|
||||
{section name=donor loop=$DONORS}
|
||||
<tr>
|
||||
<td>{$DONORS[donor].username}</td>
|
||||
<td>{if $DONORS[donor].is_anonymous|default:"0" == 1}anonymous{else}{$DONORS[donor].username}{/if}</td>
|
||||
<td class="center">{$DONORS[donor].donate_percent}</td>
|
||||
<td class="right">{$DONORS[donor].donation|number_format:"2"}</td>
|
||||
</tr>
|
||||
|
||||
1
public/templates/mmcFE/account/confirm/default.tpl
Normal file
1
public/templates/mmcFE/account/confirm/default.tpl
Normal file
@ -0,0 +1 @@
|
||||
|
||||
@ -4,13 +4,17 @@
|
||||
<input type="hidden" name="action" value="{$smarty.request.action|escape}">
|
||||
<input type="hidden" name="do" value="updateAccount">
|
||||
<table>
|
||||
<tbody><tr><td>Username: </td><td>{$GLOBAL.userdata.username}</td></tr>
|
||||
<tbody><tr><td>Username: </td><td>{$GLOBAL.userdata.username|escape}</td></tr>
|
||||
<tr><td>User Id: </td><td>{$GLOBAL.userdata.id}</td></tr>
|
||||
<tr><td>API Key: </td><td><a href="{$smarty.server.PHP_SELF}?page=api&action=getuserstatus&api_key={$GLOBAL.userdata.api_key}&id={$GLOBAL.userdata.id}">{$GLOBAL.userdata.api_key}</a></td></tr>
|
||||
<tr><td>E-Mail: </td><td><input type="text" name="email" value="{$GLOBAL.userdata.email|escape}" size="20"></td></tr>
|
||||
<tr><td>Payment Address: </td><td><input type="text" name="paymentAddress" value="{$smarty.request.paymentAddress|default:$GLOBAL.userdata.coin_address|escape}" size="40"></td></tr>
|
||||
<tr><td>Donation %: </td><td><input type="text" name="donatePercent" value="{$smarty.request.donatePercent|default:$GLOBAL.userdata.donate_percent|escape}" size="4"><font size="1"> [donation amount in percent (example: 0.5)]</font></td></tr>
|
||||
{if !$GLOBAL.config.website.api.disabled}<tr><td>API Key: </td><td><a href="{$smarty.server.PHP_SELF}?page=api&action=getuserstatus&api_key={$GLOBAL.userdata.api_key}&id={$GLOBAL.userdata.id}">{$GLOBAL.userdata.api_key}</a></td></tr>{/if}
|
||||
<tr><td>E-Mail: </td><td><input type="text" name="email" value="{nocache}{$GLOBAL.userdata.email|escape}{/nocache}" size="20"></td></tr>
|
||||
<tr><td>Payment Address: </td><td><input type="text" name="paymentAddress" value="{nocache}{$smarty.request.paymentAddress|default:$GLOBAL.userdata.coin_address|escape}{nocache}" size="40"></td></tr>
|
||||
<tr><td>Donation %: </td><td><input type="text" name="donatePercent" value="{nocache}{$smarty.request.donatePercent|default:$GLOBAL.userdata.donate_percent|escape}{nocache}" size="4"><font size="1"> [donation amount in percent (example: 0.5)]</font></td></tr>
|
||||
<tr><td>Automatic Payout Threshold: </td><td valign="top"><input type="text" name="payoutThreshold" value="{$smarty.request.payoutThreshold|default:$GLOBAL.userdata.ap_threshold|escape}" size="5" maxlength="5"> <font size="1">[{$GLOBAL.config.ap_threshold.min}-{$GLOBAL.config.ap_threshold.max} {$GLOBAL.config.currency}. Set to '0' for no auto payout]</font></td></tr>
|
||||
<tr><td>Anonymous Account <span id='tt'><img src='{$PATH}/images/questionmark.png' height='15px' width='15px' title='Will hide your username on the website for others. Only admins can still get your user information.'></span>:</td><td>
|
||||
<input type="checkbox" name="is_anonymous" value="1" id="is_anonymous" {if $GLOBAL.userdata.is_anonymous}checked{/if} />
|
||||
<label for="is_anonymous"></label>
|
||||
</td></tr>
|
||||
<tr><td>4 digit PIN: </td><td><input type="password" name="authPin" size="4" maxlength="4"><font size="1"> [The 4 digit PIN you chose when registering]</font></td></tr>
|
||||
</tbody></table>
|
||||
<input type="submit" class="submit long" value="Update Settings"></form>
|
||||
@ -23,8 +27,8 @@
|
||||
<input type="hidden" name="action" value="{$smarty.request.action|escape}">
|
||||
<input type="hidden" name="do" value="cashOut">
|
||||
<table>
|
||||
<tbody><tr><td>Account Balance: </td><td>{$GLOBAL.userdata.balance.confirmed|escape} {$GLOBAL.config.currency}</td></tr>
|
||||
<tr><td>Payout to: </td><td><h6>{$GLOBAL.userdata.coin_address|escape}</h6></td></tr>
|
||||
<tbody><tr><td>Account Balance: </td><td>{nocache}{$GLOBAL.userdata.balance.confirmed|escape}{/nocache} {$GLOBAL.config.currency}</td></tr>
|
||||
<tr><td>Payout to: </td><td><h6>{nocache}{$GLOBAL.userdata.coin_address|escape}{/nocache}</h6></td></tr>
|
||||
<tr><td>4 digit PIN: </td><td><input type="password" name="authPin" size="4" maxlength="4"></td></tr>
|
||||
</tbody></table>
|
||||
<input type="submit" class="submit mid" value="Cash Out"></form>
|
||||
|
||||
43
public/templates/mmcFE/account/invitations/default.tpl
Normal file
43
public/templates/mmcFE/account/invitations/default.tpl
Normal file
@ -0,0 +1,43 @@
|
||||
{include file="global/block_header.tpl" ALIGN="left" BLOCK_HEADER="Invitations"}
|
||||
<form action="{$smarty.server.PHP_SELF}" method="POST">
|
||||
<input type="hidden" name="page" value="{$smarty.request.page}">
|
||||
<input type="hidden" name="action" value="{$smarty.request.action}">
|
||||
<input type="hidden" name="do" value="sendInvitation">
|
||||
<table>
|
||||
<tr>
|
||||
<td>E-Mail</td>
|
||||
<td><input type="text" name="data[email]" value="{$smarty.request.data.email|escape|default:""}" size="30" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Message</td>
|
||||
<td><textarea name="data[message]">{$smarty.request.data.message|escape|default:"Please accept my invitation to this awesome pool."}</textarea></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" class="center">
|
||||
<input type="submit" class="submit small" value="Send">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
{include file="global/block_footer.tpl"}
|
||||
|
||||
{include file="global/block_header.tpl" ALIGN="right" BLOCK_HEADER="Past Invitations"}
|
||||
<table width="100%">
|
||||
<thead style="font-size:13px;">
|
||||
<tr>
|
||||
<th>E-Mail</th>
|
||||
<th class="center">Sent</th>
|
||||
<th class="center">Activated</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{section name=invite loop=$INVITATIONS}
|
||||
<tr>
|
||||
<td>{$INVITATIONS[invite].email}</td>
|
||||
<td class="center">{$INVITATIONS[invite].time|date_format:"%d/%m/%Y %H:%M:%S"}</td>
|
||||
<td class="center"><img src="{$PATH}/images/{if $INVITATIONS[invite].is_activated}success{else}error{/if}.gif" /></td>
|
||||
</tr>
|
||||
{/section}
|
||||
<tbody>
|
||||
</table>
|
||||
{include file="global/block_footer.tpl"}
|
||||
@ -12,7 +12,7 @@
|
||||
<td class="left">IDLE Worker</td>
|
||||
<td class="center">
|
||||
<input type="hidden" name="data[idle_worker]" value="0" />
|
||||
<input type="checkbox" name="data[idle_worker]" id="data[idle_worker]" value="1"{if $SETTINGS['idle_worker']}checked{/if} />
|
||||
<input type="checkbox" name="data[idle_worker]" id="data[idle_worker]" value="1"{nocache}{if $SETTINGS['idle_worker']}checked{/if}{/nocache} />
|
||||
<label for="data[idle_worker]"></label>
|
||||
</td>
|
||||
</tr>
|
||||
@ -20,7 +20,7 @@
|
||||
<td class="left">New Blocks</td>
|
||||
<td class="center">
|
||||
<input type="hidden" name="data[new_block]" value="0" />
|
||||
<input type="checkbox" name="data[new_block]" id="data[new_block]" value="1"{if $SETTINGS['new_block']}checked{/if} />
|
||||
<input type="checkbox" name="data[new_block]" id="data[new_block]" value="1"{nocache}{if $SETTINGS['new_block']}checked{/if}{/nocache} />
|
||||
<label for="data[new_block]"></label>
|
||||
</td>
|
||||
</tr>
|
||||
@ -28,7 +28,7 @@
|
||||
<td class="left">Auto Payout</td>
|
||||
<td class="center">
|
||||
<input type="hidden" name="data[auto_payout]" value="0" />
|
||||
<input type="checkbox" name="data[auto_payout]" id="data[auto_payout]" value="1"{if $SETTINGS['auto_payout']}checked{/if} />
|
||||
<input type="checkbox" name="data[auto_payout]" id="data[auto_payout]" value="1"{nocache}{if $SETTINGS['auto_payout']}checked{/if}{/nocache} />
|
||||
<label for="data[auto_payout]"></label>
|
||||
</td>
|
||||
</tr>
|
||||
@ -36,7 +36,7 @@
|
||||
<td class="left">Manual Payout</td>
|
||||
<td class="center">
|
||||
<input type="hidden" name="data[manual_payout]" value="0" />
|
||||
<input type="checkbox" name="data[manual_payout]" id="data[manual_payout]" value="1"{if $SETTINGS['manual_payout']}checked{/if} />
|
||||
<input type="checkbox" name="data[manual_payout]" id="data[manual_payout]" value="1"{nocache}{if $SETTINGS['manual_payout']}checked{/if}{/nocache} />
|
||||
<label for="data[manual_payout]"></label>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@ -17,15 +17,9 @@
|
||||
{assign var=has_confirmed value=false}
|
||||
{section transaction $TRANSACTIONS}
|
||||
{if (
|
||||
(($TRANSACTIONS[transaction].type == 'Credit' or $TRANSACTIONS[transaction].type == 'Bonus')and $TRANSACTIONS[transaction].confirmations >= $GLOBAL.confirmations)
|
||||
or ($TRANSACTIONS[transaction].type == 'Donation' and $TRANSACTIONS[transaction].confirmations >= $GLOBAL.confirmations)
|
||||
or ($TRANSACTIONS[transaction].type == 'Fee' and $TRANSACTIONS[transaction].confirmations >= $GLOBAL.confirmations)
|
||||
or $TRANSACTIONS[transaction].type == 'Credit_PPS'
|
||||
or $TRANSACTIONS[transaction].type == 'Fee_PPS'
|
||||
or $TRANSACTIONS[transaction].type == 'Donation_PPS'
|
||||
or $TRANSACTIONS[transaction].type == 'Debit_AP'
|
||||
or $TRANSACTIONS[transaction].type == 'Debit_MP'
|
||||
or $TRANSACTIONS[transaction].type == 'TXFee'
|
||||
( ( $TRANSACTIONS[transaction].type == 'Credit' or $TRANSACTIONS[transaction].type == 'Bonus' or $TRANSACTIONS[transaction].type == 'Donation' or $TRANSACTIONS[transaction].type == 'Fee' ) and $TRANSACTIONS[transaction].confirmations >= $GLOBAL.confirmations )
|
||||
or $TRANSACTIONS[transaction].type == 'Credit_PPS' or $TRANSACTIONS[transaction].type == 'Fee_PPS' or $TRANSACTIONS[transaction].type == 'Donation_PPS'
|
||||
or $TRANSACTIONS[transaction].type == 'Debit_AP' or $TRANSACTIONS[transaction].type == 'Debit_MP' or $TRANSACTIONS[transaction].type == 'TXFee'
|
||||
)}
|
||||
{assign var=has_credits value=true}
|
||||
<tr class="{cycle values="odd,even"}">
|
||||
@ -67,11 +61,9 @@
|
||||
<tbody style="font-size:12px;">
|
||||
{assign var=has_unconfirmed value=false}
|
||||
{section transaction $TRANSACTIONS}
|
||||
{if (
|
||||
($TRANSACTIONS[transaction].type == 'Credit' or $TRANSACTIONS[transaction].type == 'Bonus') and $TRANSACTIONS[transaction].confirmations < $GLOBAL.confirmations
|
||||
or ($TRANSACTIONS[transaction].type == 'Donation' and $TRANSACTIONS[transaction].confirmations < $GLOBAL.confirmations)
|
||||
or ($TRANSACTIONS[transaction].type == 'Fee' and $TRANSACTIONS[transaction].confirmations < $GLOBAL.confirmations)
|
||||
)}
|
||||
{if
|
||||
(($TRANSACTIONS[transaction].type == 'Credit' or $TRANSACTIONS[transaction].type == 'Bonus' or $TRANSACTIONS[transaction].type == 'Donation' or $TRANSACTIONS[transaction].type == 'Fee') and $TRANSACTIONS[transaction].confirmations < $GLOBAL.confirmations and $TRANSACTIONS[transaction].confirmations >= 0)
|
||||
}
|
||||
{assign var=has_unconfirmed value=true}
|
||||
<tr class="{cycle values="odd,even"}">
|
||||
<td>{$TRANSACTIONS[transaction].id}</td>
|
||||
@ -117,21 +109,16 @@
|
||||
<tbody style="font-size:12px;">
|
||||
{assign var=has_orphaned value=false}
|
||||
{section transaction $TRANSACTIONS}
|
||||
{if (
|
||||
$TRANSACTIONS[transaction].type == 'Orphan_Credit'
|
||||
or $TRANSACTIONS[transaction].type == 'Orphan_Donation'
|
||||
or $TRANSACTIONS[transaction].type == 'Orphan_Fee'
|
||||
or $TRANSACTIONS[transaction].type == 'Orphan_Bonus'
|
||||
)}
|
||||
{if ($TRANSACTIONS[transaction].type == 'Credit' or $TRANSACTIONS[transaction].type == 'Fee' or $TRANSACTIONS[transaction].type == 'Donation' or $TRANSACTIONS[transaction].type == 'Bonus') and $TRANSACTIONS[transaction].confirmations == -1}
|
||||
<tr class="{cycle values="odd,even"}">
|
||||
<td>{$TRANSACTIONS[transaction].id}</td>
|
||||
<td>{$TRANSACTIONS[transaction].timestamp}</td>
|
||||
<td>{$TRANSACTIONS[transaction].type}</td>
|
||||
<td>{$TRANSACTIONS[transaction].coin_address}</td>
|
||||
<td>{if $TRANSACTIONS[transaction].height == 0}n/a{else}{$TRANSACTIONS[transaction].height}{/if}</td>
|
||||
<td><font color="{if $TRANSACTIONS[transaction].type == 'Orphan_Credit' or $TRANSACTIONS[transaction].type == 'Orphan_Bonus'}green{else}red{/if}">{$TRANSACTIONS[transaction].amount|number_format:"8"}</td>
|
||||
<td><font color="{if $TRANSACTIONS[transaction].type == 'Credit' or $TRANSACTIONS[transaction].type == 'Bonus'}green{else}red{/if}">{$TRANSACTIONS[transaction].amount|number_format:"8"}</td>
|
||||
</tr>
|
||||
{if $TRANSACTIONS[transaction].type == 'Orphan_Credit' or $TRANSACTIONS[transaction].type == 'Orphan_Bonus'}
|
||||
{if $TRANSACTIONS[transaction].type == 'Credit' or $TRANSACTIONS[transaction].type == 'Bonus'}
|
||||
{assign var="orphan_credits" value="`$orphan_credits|default:"0"+$TRANSACTIONS[transaction].amount`"}
|
||||
{else}
|
||||
{assign var="orphan_debits" value="`$orphan_debits|default:"0"+$TRANSACTIONS[transaction].amount`"}
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
{nocache}
|
||||
{section worker $WORKERS}
|
||||
{assign var="username" value="."|escape|explode:$WORKERS[worker].username:2}
|
||||
<tr>
|
||||
@ -29,6 +30,7 @@
|
||||
<td align="right"><a href="{$smarty.server.PHP_SELF}?page={$smarty.request.page|escape}&action={$smarty.request.action|escape}&do=delete&id={$WORKERS[worker].id|escape}"><button style="padding:5px" type="button">Delete</button></a></td>
|
||||
</tr>
|
||||
{/section}
|
||||
{/nocache}
|
||||
</tbody>
|
||||
</table>
|
||||
<input type="submit" value="Update Workers" style="padding:5px">
|
||||
|
||||
45
public/templates/mmcFE/admin/monitoring/default.tpl
Normal file
45
public/templates/mmcFE/admin/monitoring/default.tpl
Normal file
@ -0,0 +1,45 @@
|
||||
{include file="global/block_header.tpl" BLOCK_HEADER="Monitoring"}
|
||||
<table width="88%">
|
||||
<thead>
|
||||
<th>Cronjob</th>
|
||||
<th>Exit Code</th>
|
||||
<th>Active</th>
|
||||
<th>Runtime</th>
|
||||
<th>Start Time</th>
|
||||
<th>End Time</th>
|
||||
<th>Message</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
{foreach $CRONSTATUS as $cron=>$v}
|
||||
<tr>
|
||||
<td>{$cron}</td>
|
||||
{foreach $v as $event}
|
||||
<td>
|
||||
{if $event.STATUS.type == 'okerror'}
|
||||
{if $event.STATUS.value == 0}
|
||||
<font color="green">OK</font>
|
||||
{else}
|
||||
<font color="red">ERROR</font>
|
||||
{/if}
|
||||
{else if $event.STATUS.type == 'message'}
|
||||
<i>{$event.STATUS.value}</i>
|
||||
{else if $event.STATUS.type == 'yesno'}
|
||||
{if $event.STATUS.value == 1}
|
||||
Yes
|
||||
{else}
|
||||
No
|
||||
{/if}
|
||||
{else if $event.STATUS.type == 'time'}
|
||||
{$event.STATUS.value|default:"0"|number_format:"2"} seconds
|
||||
{else if $event.STATUS.type == 'date'}
|
||||
{$event.STATUS.value|date_format:"%m/%d %H:%M:%S"}
|
||||
{else}
|
||||
{$event.STATUS.value|default:""}
|
||||
{/if}
|
||||
</td>
|
||||
{/foreach}
|
||||
</tr>
|
||||
{/foreach}
|
||||
</tbody>
|
||||
</table>
|
||||
{include file="global/block_footer.tpl"}
|
||||
@ -17,6 +17,7 @@
|
||||
</table>
|
||||
</form>
|
||||
{include file="global/block_footer.tpl"}
|
||||
{nocache}
|
||||
{section name=news loop=$NEWS}
|
||||
{include
|
||||
file="global/block_header.tpl"
|
||||
@ -35,4 +36,5 @@
|
||||
</form>
|
||||
{include file="global/block_footer.tpl"}
|
||||
{/section}
|
||||
{/nocache}
|
||||
{include file="global/block_footer.tpl"}
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
Active
|
||||
</th>
|
||||
<td>
|
||||
<input type="checkbox" name="active" value="1" id="active" {if $NEWS.active}checked{/if} />
|
||||
<input type="checkbox" name="active" value="1" id="active" {nocache}{if $NEWS.active}checked{/if}{/nocache} />
|
||||
<label for="active"></label>
|
||||
</td>
|
||||
</tr>
|
||||
@ -18,13 +18,13 @@
|
||||
<th>
|
||||
Header
|
||||
</th>
|
||||
<td><input name="header" type="text" size="30" value="{$NEWS.header}" required /></td>
|
||||
<td><input name="header" type="text" size="30" value="{nocache}{$NEWS.header}{/nocache}" required /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
Content
|
||||
</th>
|
||||
<td><textarea name="content" rows="500" type="text" required>{$NEWS.content}</textarea></td>
|
||||
<td><textarea name="content" rows="500" type="text" required>{nocache}{$NEWS.content}{/nocache}</textarea></td>
|
||||
</tr>
|
||||
</table>
|
||||
<input type="submit" value="Save" class="submit small" />
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
<td>
|
||||
<select name="data[maintenance]">
|
||||
<option value="1">Yes</option>
|
||||
<option value="0"{if !$MAINTENANCE} selected{/if}>No</option>
|
||||
<option value="0"{nocache}{if !$MAINTENANCE} selected{/if}>{/nocache}No</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
@ -26,7 +26,17 @@
|
||||
<td>
|
||||
<select name="data[lock_registration]">
|
||||
<option value="1">Yes</option>
|
||||
<option value="0"{if !$LOCKREGISTRATION} selected{/if}>No</option>
|
||||
<option value="0"{nocache}{if !$LOCKREGISTRATION} selected{/if}{/nocache}>No</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="left">Disable Invitations</td>
|
||||
<td class="center"><span id='tt'><img src='{$PATH}/images/questionmark.png' height='15px' width='15px' title='Enable or disable users to invite others. Configuration file defines number of allowed invitations.'></span></td>
|
||||
<td>
|
||||
<select name="data[disable_invitations]">
|
||||
<option value="1">Yes</option>
|
||||
<option value="0"{nocache}{if !$DISABLEINVITATIONS} selected{/if}{/nocache}>No</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@ -21,15 +21,9 @@
|
||||
{assign var=confirmed value=0}
|
||||
{section transaction $TRANSACTIONS}
|
||||
{if (
|
||||
(($TRANSACTIONS[transaction].type == 'Credit' or $TRANSACTIONS[transaction].type == 'Bonus')and $TRANSACTIONS[transaction].confirmations >= $GLOBAL.confirmations)
|
||||
or ($TRANSACTIONS[transaction].type == 'Donation' and $TRANSACTIONS[transaction].confirmations >= $GLOBAL.confirmations)
|
||||
or ($TRANSACTIONS[transaction].type == 'Fee' and $TRANSACTIONS[transaction].confirmations >= $GLOBAL.confirmations)
|
||||
or $TRANSACTIONS[transaction].type == 'Credit_PPS'
|
||||
or $TRANSACTIONS[transaction].type == 'Fee_PPS'
|
||||
or $TRANSACTIONS[transaction].type == 'Donation_PPS'
|
||||
or $TRANSACTIONS[transaction].type == 'Debit_AP'
|
||||
or $TRANSACTIONS[transaction].type == 'Debit_MP'
|
||||
or $TRANSACTIONS[transaction].type == 'TXFee'
|
||||
( ( $TRANSACTIONS[transaction].type == 'Credit' or $TRANSACTIONS[transaction].type == 'Bonus' or $TRANSACTIONS[transaction].type == 'Donation' or $TRANSACTIONS[transaction].type == 'Fee' ) and $TRANSACTIONS[transaction].confirmations >= $GLOBAL.confirmations )
|
||||
or $TRANSACTIONS[transaction].type == 'Credit_PPS' or $TRANSACTIONS[transaction].type == 'Fee_PPS' or $TRANSACTIONS[transaction].type == 'Donation_PPS'
|
||||
or $TRANSACTIONS[transaction].type == 'Debit_AP' or $TRANSACTIONS[transaction].type == 'Debit_MP' or $TRANSACTIONS[transaction].type == 'TXFee'
|
||||
)}
|
||||
{assign var=confirmed value=1}
|
||||
<tr class="{cycle values="odd,even"}">
|
||||
@ -74,11 +68,7 @@
|
||||
<tbody style="font-size:12px;">
|
||||
{assign var=unconfirmed value=0}
|
||||
{section transaction $TRANSACTIONS}
|
||||
{if (
|
||||
($TRANSACTIONS[transaction].type == 'Credit' or $TRANSACTIONS[transaction].type == 'Bonus') and $TRANSACTIONS[transaction].confirmations < $GLOBAL.confirmations
|
||||
or ($TRANSACTIONS[transaction].type == 'Donation' and $TRANSACTIONS[transaction].confirmations < $GLOBAL.confirmations)
|
||||
or ($TRANSACTIONS[transaction].type == 'Fee' and $TRANSACTIONS[transaction].confirmations < $GLOBAL.confirmations)
|
||||
)}
|
||||
{if ($TRANSACTIONS[transaction].type == 'Credit' or $TRANSACTIONS[transaction].type == 'Bonus' or $TRANSACTIONS[transaction].type == 'Donation' or $TRANSACTIONS[transaction].type == 'Fee') and $TRANSACTIONS[transaction].confirmations < $GLOBAL.confirmations and $TRANSACTIONS[transaction].confirmations >= 0}
|
||||
{assign var=unconfirmed value=1}
|
||||
<tr class="{cycle values="odd,even"}">
|
||||
<td>{$TRANSACTIONS[transaction].id}</td>
|
||||
@ -118,12 +108,7 @@
|
||||
<tbody style="font-size:12px;">
|
||||
{assign var=orphaned value=0}
|
||||
{section transaction $TRANSACTIONS}
|
||||
{if (
|
||||
$TRANSACTIONS[transaction].type == 'Orphan_Credit'
|
||||
or $TRANSACTIONS[transaction].type == 'Orphan_Donation'
|
||||
or $TRANSACTIONS[transaction].type == 'Orphan_Fee'
|
||||
or $TRANSACTIONS[transaction].type == 'Orphan_Bonus'
|
||||
)}
|
||||
{if ($TRANSACTIONS[transaction].type == 'Credit' or $TRANSACTIONS[transaction].type == 'Fee' or $TRANSACTIONS[transaction].type == 'Donation' or $TRANSACTIONS[transaction].type == 'Bonus') and $TRANSACTIONS[transaction].confirmations == -1}
|
||||
{assign var=orphaned value=1}
|
||||
<tr class="{cycle values="odd,even"}">
|
||||
<td>{$TRANSACTIONS[transaction].id}</td>
|
||||
@ -132,7 +117,7 @@
|
||||
<td>{$TRANSACTIONS[transaction].type}</td>
|
||||
<td>{$TRANSACTIONS[transaction].coin_address}</td>
|
||||
<td>{if $TRANSACTIONS[transaction].height == 0}n/a{else}{$TRANSACTIONS[transaction].height}{/if}</td>
|
||||
<td><font color="{if $TRANSACTIONS[transaction].type == 'Orphan_Credit' or $TRANSACTIONS[transaction].type == 'Orphan_Bonus'}green{else}red{/if}">{$TRANSACTIONS[transaction].amount|number_format:"8"}</td>
|
||||
<td><font color="{if $TRANSACTIONS[transaction].type == 'Credit' or $TRANSACTIONS[transaction].type == 'Bonus'}green{else}red{/if}">{$TRANSACTIONS[transaction].amount|number_format:"8"}</td>
|
||||
</tr>
|
||||
{/if}
|
||||
{/section}
|
||||
|
||||
@ -44,11 +44,12 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{nocache}
|
||||
{section name=user loop=$USERS|default}
|
||||
<tr>
|
||||
<td class="center">{$USERS[user].id}</td>
|
||||
<td>{$USERS[user].username}</td>
|
||||
<td>{$USERS[user].email}</td>
|
||||
<td>{$USERS[user].username|escape}</td>
|
||||
<td>{$USERS[user].email|escape}</td>
|
||||
<td class="right">{$USERS[user].shares}</td>
|
||||
<td class="right">{$USERS[user].hashrate}</td>
|
||||
<td class="right">{$USERS[user].payout.est_donation|number_format:"8"}</td>
|
||||
@ -70,6 +71,7 @@
|
||||
<td colspan="10"></td>
|
||||
</tr>
|
||||
{/section}
|
||||
{/nocache}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
|
||||
0
public/templates/mmcFE/global/empty.tpl
Normal file
0
public/templates/mmcFE/global/empty.tpl
Normal file
@ -4,11 +4,11 @@
|
||||
<div id="ministats">
|
||||
<table border="0">
|
||||
<tr>
|
||||
{if $GLOBAL.config.price.currency}<td><li>{$GLOBAL.config.currency}/{$GLOBAL.config.price.currency}: {$GLOBAL.price|default:"n/a"|number_format:"4"} </li></td>{/if}
|
||||
{if $GLOBAL.config.price.currency}<td><li>{$GLOBAL.config.currency}/{$GLOBAL.config.price.currency}: {$GLOBAL.price|default:"0"|number_format:"4"} </li></td>{/if}
|
||||
<td><li>Network Hashrate: {($GLOBAL.nethashrate / 1000 / 1000 )|default:"0"|number_format:"3"} MH/s </li></td>
|
||||
<td><li>Pool Hashrate: {($GLOBAL.hashrate / 1000)|number_format:"3"} MH/s </li></td>
|
||||
<td><li>Pool Sharerate: {$GLOBAL.sharerate|number_format:"2"} Shares/s </li></td>
|
||||
<td><li>Pool Workers: {$GLOBAL.workers} </li></td>
|
||||
<td><li>Pool Workers: {$GLOBAL.workers|default:"0"} </li></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@ -7,12 +7,14 @@
|
||||
<li><a href="{$smarty.server.PHP_SELF}?page=account&action=workers">My Workers</a></li>
|
||||
<li><a href="{$smarty.server.PHP_SELF}?page=account&action=transactions">Transactions</a></li>
|
||||
<li><a href="{$smarty.server.PHP_SELF}?page=account&action=notifications">Notifications</a></li>
|
||||
{if !$GLOBAL.config.disable_invitations}<li><a href="{$smarty.server.PHP_SELF}?page=account&action=invitations">Invitations</a></li>{/if}
|
||||
</ul>
|
||||
</li>
|
||||
{/if}
|
||||
{if $smarty.session.AUTHENTICATED|default:"0" == 1 && $GLOBAL.userdata.is_admin == 1}
|
||||
<li><a href="{$smarty.server.PHP_SELF}?page=admin">Admin Panel</a>
|
||||
<ul>
|
||||
<li><a href="{$smarty.server.PHP_SELF}?page=admin&action=monitoring">Monitoring</a></li>
|
||||
<li><a href="{$smarty.server.PHP_SELF}?page=admin&action=user">User Info</a></li>
|
||||
<li><a href="{$smarty.server.PHP_SELF}?page=admin&action=wallet">Wallet Info</a></li>
|
||||
<li><a href="{$smarty.server.PHP_SELF}?page=admin&action=transactions">Transactions</a></li>
|
||||
@ -31,13 +33,21 @@
|
||||
</li>
|
||||
{else}
|
||||
<li><a href="{$smarty.server.PHP_SELF}?page=statistics">Statistics</a>
|
||||
<ul>
|
||||
{if $GLOBAL.config.website.acl.statistics.pool == 'public'}
|
||||
<li><a href="{$smarty.server.PHP_SELF}?page=statistics&action=pool">Pool Stats</a></li>
|
||||
{/if}
|
||||
{if $GLOBAL.config.website.acl.statistics.blocks == 'public'}
|
||||
<li><a href="{$smarty.server.PHP_SELF}?page=statistics&action=blocks">Block Stats</a></li>
|
||||
{/if}
|
||||
</ul>
|
||||
{/if}
|
||||
<li><a href="{$smarty.server.PHP_SELF}?page=gettingstarted">Getting Started</a></li>
|
||||
<li><a href="{$smarty.server.PHP_SELF}?page=support">Support</a></li>
|
||||
<li><a href="{$smarty.server.PHP_SELF}?page=about&action=pool">About</a>
|
||||
<ul>
|
||||
<li><a href="{$smarty.server.PHP_SELF}?page=about&action=pool">This Pool</a></li>
|
||||
<li><a href="{$smarty.server.PHP_SELF}?page=about&action=api">API Reference</a></li>
|
||||
{if !$GLOBAL.config.website.api.disabled}<li><a href="{$smarty.server.PHP_SELF}?page=about&action=api">API Reference</a></li>{/if}
|
||||
<li><a href="{$smarty.server.PHP_SELF}?page=about&action=donors">Pool Donors</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
75
public/templates/mmcFE/global/sidebar_pplns.tpl
Normal file
75
public/templates/mmcFE/global/sidebar_pplns.tpl
Normal file
@ -0,0 +1,75 @@
|
||||
<div class="block" style="clear:none; margin-top:15px; margin-left:13px;">
|
||||
<div class="block_head">
|
||||
<div class="bheadl"></div>
|
||||
<div class="bheadr"></div>
|
||||
<h1>Dashboard</h1>
|
||||
</div>
|
||||
<div class="block_content" style="padding-top:10px;">
|
||||
<table class="sidebar" style="width: 196px">
|
||||
<tr>
|
||||
<td><b>PPLNS Target</b></td>
|
||||
<td class="right">{$GLOBAL.pplns.target|number_format}</td>
|
||||
</tr>
|
||||
<tr><td colspan="2"> </td></tr>
|
||||
<tr>
|
||||
<td colspan="2"><b><u>Your Stats</u></b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Hashrate</b></td>
|
||||
<td class="right">{$GLOBAL.userdata.hashrate|number_format} KH/s</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"><b><u>Unpaid Shares</u></b> <span id='tt'><img src='{$PATH}/images/questionmark.png' height='15px' width='15px' title='Submitted shares between the last 120 confirms block until now.'></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Your Valid<b></td>
|
||||
<td class="right"><i>{$GLOBAL.userdata.shares.valid|number_format}</i><font size='1px'></font></b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Pool Valid</td>
|
||||
<td class="right"><i>{$GLOBAL.roundshares.valid|number_format}</i> <font size='1px'></font></b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"><b><u>Round Shares</u></b> <span id='tt'><img src='{$PATH}/images/questionmark.png' height='15px' width='15px' title='Submitted shares since last found block (ie. round shares)'></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Pool Valid</b></td>
|
||||
<td class="right"><i>{$GLOBAL.roundshares.valid|number_format}</i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Pool Invalid</b></td>
|
||||
<td class="right"><i>{$GLOBAL.roundshares.invalid|number_format}</i>{if $GLOBAL.roundshares.valid > 0}<font size='1px'> ({(100 / $GLOBAL.roundshares.valid * $GLOBAL.roundshares.invalid)|number_format:"2"}%)</font>{/if}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Your Invalid</b></td>
|
||||
<td class="right"><i>{$GLOBAL.userdata.shares.invalid|number_format}</i>{if $GLOBAL.roundshares.valid > 0}<font size='1px'> ({(100 / $GLOBAL.roundshares.valid * $GLOBAL.userdata.shares.invalid)|number_format:"2"}%)</font>{/if}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"><b><u>{$GLOBAL.config.currency} Round Estimate</u></b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Block</b></td>
|
||||
<td class="right">{$GLOBAL.userdata.est_block|number_format:"3"}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Fees</b></td>
|
||||
<td class="right">{$GLOBAL.userdata.est_fee|number_format:"3"}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Donation</b></td>
|
||||
<td class="right">{$GLOBAL.userdata.est_donation|number_format:"3"}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Payout</b></td>
|
||||
<td class="right">{$GLOBAL.userdata.est_payout|number_format:"3"}</td>
|
||||
</tr>
|
||||
<tr><td colspan="2"> </td></tr>
|
||||
<tr><td colspan="2"><b><u>{$GLOBAL.config.currency} Account Balance</u></b></td></tr>
|
||||
<tr><td>Confirmed</td><td class="right"><b>{$GLOBAL.userdata.balance.confirmed|default:"0"}</td></tr>
|
||||
<tr><td>Unconfirmed</td><td class="right"><b>{$GLOBAL.userdata.balance.unconfirmed|default:"0"}</td></tr>
|
||||
<tr><td>Orphaned</td><td class="right"><b>{$GLOBAL.userdata.balance.orphaned|default:"0"}</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="bendl"></div>
|
||||
<div class="bendr"></div>
|
||||
</div>
|
||||
@ -62,6 +62,7 @@
|
||||
<tr><td colspan="2"><b><u>{$GLOBAL.config.currency} Account Balance</u></b></td></tr>
|
||||
<tr><td>Confirmed</td><td class="right"><b>{$GLOBAL.userdata.balance.confirmed|default:"0"}</td></tr>
|
||||
<tr><td>Unconfirmed</td><td class="right"><b>{$GLOBAL.userdata.balance.unconfirmed|default:"0"}</td></tr>
|
||||
<tr><td>Orphaned</td><td class="right"><b>{$GLOBAL.userdata.balance.orphaned|default:"0"}</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="bendl"></div>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{if $GLOBAL.userdata.username|default}
|
||||
<h2>Welcome, {$smarty.session.USERDATA.username} <font size='1px'><b>Active Account</b>: <b>{$GLOBAL.fees}%</b> Pool Fee</font> <font size='1px'><i>(You are <a href='{$smarty.server.PHP_SELF}?page=account&action=edit'>donating</a> <b></i>{$GLOBAL.userdata.donate_percent}%</b> <i>of your earnings)</i></font></h2>
|
||||
<h2>Welcome, {$smarty.session.USERDATA.username|escape} <font size='1px'><b>{if $GLOBAL.userdata.is_anonymous}Anonymous{else}Active{/if} Account</b>: <b>{$GLOBAL.fees|escape}%</b> Pool Fee</font> <font size='1px'><i>(You are <a href='{$smarty.server.PHP_SELF}?page=account&action=edit'>donating</a> <b></i>{$GLOBAL.userdata.donate_percent|escape}%</b> <i>of your earnings)</i></font></h2>
|
||||
{else}
|
||||
<h2>Welcome guest, <font size="1px"> please <a href="{$smarty.server.PHP_SELF}?page=register">register</a> to user this pool.</font></h2>
|
||||
{/if}
|
||||
|
||||
@ -69,7 +69,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div id="debug">
|
||||
{include file="system/debugger.tpl"}
|
||||
{nocache}{include file="system/debugger.tpl"}{/nocache}
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<input type="hidden" name="token" value="{$smarty.request.token|escape}">
|
||||
<input type="hidden" name="page" value="{$smarty.request.page|escape}">
|
||||
<input type="hidden" name="action" value="{$smarty.request.action|escape}">
|
||||
<input type="hidden" name="do" value="useToken">
|
||||
<input type="hidden" name="do" value="resetPassword">
|
||||
<table>
|
||||
<tr><td>New Password: </td><td><input type="password" name="newPassword"></td></tr>
|
||||
<tr><td>New Password Repeat: </td><td><input type="password" name="newPassword2"></td></tr>
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
{include file="global/block_header.tpl" BLOCK_HEADER="Join our pool" BLOCK_STYLE="clear:none;"}
|
||||
<form action="{$smarty.server.PHP_SELF}" method="post">
|
||||
<input type="hidden" name="page" value="{$smarty.request.page|escape}">
|
||||
{if $smarty.request.token|default:""}
|
||||
<input type="hidden" name="token" value="{$smarty.request.token|escape}" />
|
||||
{/if}
|
||||
<input type="hidden" name="action" value="register">
|
||||
<table width="90%" border="0">
|
||||
<tbody>
|
||||
|
||||
@ -57,18 +57,18 @@ target and network difficulty and assuming a zero variance scenario.
|
||||
{else if $BLOCKSFOUND[block].confirmations == -1}
|
||||
<font color="red">Orphan</font>
|
||||
{else}{$GLOBAL.confirmations - $BLOCKSFOUND[block].confirmations} left{/if}</td>
|
||||
<td>{$BLOCKSFOUND[block].finder|default:"unknown"}</td>
|
||||
<td>{if $BLOCKSFOUND[block].is_anonymous|default:"0" == 1}anonymous{else}{$BLOCKSFOUND[block].finder|default:"unknown"|escape}{/if}</td>
|
||||
<td class="center">{$BLOCKSFOUND[block].time|date_format:"%d/%m %H:%M:%S"}</td>
|
||||
<td class="right">{$BLOCKSFOUND[block].difficulty|number_format:"2"}</td>
|
||||
<td class="right">{$BLOCKSFOUND[block].amount|number_format:"2"}</td>
|
||||
<td class="right">
|
||||
{math assign="estshares" equation="(pow(2,32 - targetdiff) * blockdiff)" targetdiff=$GLOBAL.config.targetdiff blockdiff=$BLOCKSFOUND[block].difficulty}
|
||||
{$estshares}
|
||||
{$estshares|number_format}
|
||||
</td>
|
||||
<td class="right">{$BLOCKSFOUND[block].shares|number_format}</td>
|
||||
<td class="right">
|
||||
{math assign="percentage" equation="shares / estshares * 100" shares=$BLOCKSFOUND[block].shares estshares=$estshares}
|
||||
<font color="{if ($percentage <= 100)}green{else}red{/if}">{$percentage}</font>
|
||||
<font color="{if ($percentage <= 100)}green{else}red{/if}">{$percentage|number_format:"2"}</font>
|
||||
</td>
|
||||
</tr>
|
||||
{/section}
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
{section block $BLOCKSFOUND}
|
||||
<tr class="{cycle values="odd,even"}">
|
||||
<td class="center"><a href="{$GLOBAL.blockexplorer}{$BLOCKSFOUND[block].height}" target="_blank">{$BLOCKSFOUND[block].height}</a></td>
|
||||
<td>{$BLOCKSFOUND[block].finder|default:"unknown"}</td>
|
||||
<td>{if $BLOCKSFOUND[block].is_anonymous|default:"0" == 1}anonymous{else}{$BLOCKSFOUND[block].finder|default:"unknown"|escape}{/if}</td>
|
||||
<td class="center">{$BLOCKSFOUND[block].time|date_format:"%d/%m %H:%M:%S"}</td>
|
||||
<td class="right">{$BLOCKSFOUND[block].shares|number_format}</td>
|
||||
</tr>
|
||||
|
||||
@ -19,5 +19,5 @@
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<li>These stats are also available in JSON format <a href="{$smarty.server.PHP_SELF}?page=api&action=public" target="_api">HERE</a></li>
|
||||
{if !$GLOBAL.config.website.api.disabled}<li>These stats are also available in JSON format <a href="{$smarty.server.PHP_SELF}?page=api&action=public" target="_api">HERE</a></li>{/if}
|
||||
{include file="global/block_footer.tpl"}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
{if is_array($YOURHASHRATES) && is_array($POOLHASHRATES)}
|
||||
<div class="block_content tab_content" id="both" style="padding-left:30px;">
|
||||
{foreach from=array('area','pie') item=chartType}
|
||||
<table width="60%" class="stats" rel="{$chartType}">
|
||||
<table width="60%" class="stats" rel="area">
|
||||
<caption>Your vs Pool Hashrate</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
@ -30,14 +29,11 @@
|
||||
<td>{$POOLHASHRATES.$i|default:"0"}</td>
|
||||
{/for}
|
||||
{for $i=0 to date('G', time() - 60 * 60)}
|
||||
<td>{$POOLHASHRATES.$i|default:"0"}</td>
|
||||
<td>{$POOLHASHRATES.$i - $YOURHASHRATES.$i|default:"0"}</td>
|
||||
{/for}
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<br />
|
||||
{/foreach}
|
||||
</div>
|
||||
{else}
|
||||
<p><li>No shares available to start calculations</li></p>
|
||||
{/if}
|
||||
|
||||
@ -26,6 +26,4 @@
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{else}
|
||||
<p><li>No shares available to start calculations</li></p>
|
||||
{/if}
|
||||
|
||||
@ -26,6 +26,4 @@
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{else}
|
||||
<p><li>No shares available to start calculations</li></p>
|
||||
{/if}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user