Skip to content

Commit 1dfb7e9

Browse files
committed
Merge pull request #673 from TheSerapher/issue-444-theserapher
Issue 444 theserapher
2 parents 0af2b90 + de9220e commit 1dfb7e9

File tree

220 files changed

+22209
-165
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

220 files changed

+22209
-165
lines changed

cronjobs/shared.inc.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,13 @@
2222
// We need to find our include files so set this properly
2323
define("BASEPATH", "../public/");
2424

25-
2625
/*****************************************************
2726
* No need to change beyond this point *
2827
*****************************************************/
28+
29+
// Used in autoloading of API class, adding it to stop PHP warnings
30+
$dStartTime = microtime(true);
31+
2932
// Our cron name
3033
$cron_name = basename($_SERVER['PHP_SELF'], '.php');
3134

public/include/autoloader.inc.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
require_once(INCLUDE_DIR . '/smarty.inc.php');
2828

2929
// Load everything else in proper order
30-
require_once(CLASS_DIR . '/api.class.php');
3130
require_once(CLASS_DIR . '/mail.class.php');
3231
require_once(CLASS_DIR . '/tokentype.class.php');
3332
require_once(CLASS_DIR . '/token.class.php');
@@ -49,6 +48,7 @@
4948
require_once(CLASS_DIR . '/transaction.class.php');
5049
require_once(CLASS_DIR . '/notification.class.php');
5150
require_once(CLASS_DIR . '/news.class.php');
51+
require_once(CLASS_DIR . '/api.class.php');
5252
require_once(INCLUDE_DIR . '/lib/Michelf/Markdown.php');
5353
require_once(INCLUDE_DIR . '/lib/scrypt.php');
5454

public/include/classes/api.class.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77
* Helper class for our API
88
**/
99
class Api extends Base {
10+
private $api_version = '1.0.0';
11+
12+
function setStartTime($dStartTime) {
13+
$this->dStartTime = $dStartTime;
14+
}
1015
function isActive($error=true) {
1116
if (!$this->setting->getValue('disable_api')) {
1217
return true;
@@ -17,8 +22,45 @@ function isActive($error=true) {
1722
}
1823
}
1924
}
25+
26+
/**
27+
* Create API json object from input array
28+
* @param data Array data to create JSON for
29+
* @param force bool Enforce a JSON object
30+
* @return string JSON object
31+
**/
32+
function get_json($data, $force=false) {
33+
return json_encode(
34+
array( $_REQUEST['action'] => array(
35+
'version' => $this->api_version,
36+
'runtime' => (microtime(true) - $this->dStartTime) * 1000,
37+
'data' => $data
38+
)), $force ? JSON_FORCE_OBJECT : 0
39+
);
40+
}
41+
42+
/**
43+
* Check user access level to the API call
44+
**/
45+
function checkAccess($user_id, $get_id=NULL) {
46+
if ( ! $this->user->isAdmin($user_id) && (!empty($get_id) && $get_id != $user_id)) {
47+
// User is NOT admin and tries to access an ID that is not their own
48+
header("HTTP/1.1 401 Unauthorized");
49+
die("Access denied");
50+
} else if ($this->user->isAdmin($user_id) && !empty($get_id)) {
51+
// User is an admin and tries to fetch another users data
52+
$id = $get_id;
53+
// Is it a username or a user ID
54+
ctype_digit($_REQUEST['id']) ? $id = $get_id : $id = $this->user->getUserId($get_id);
55+
} else {
56+
$id = $user_id;
57+
}
58+
return $id;
59+
}
2060
}
2161

2262
$api = new Api();
2363
$api->setConfig($config);
64+
$api->setUser($user);
2465
$api->setSetting($setting);
66+
$api->setStartTime($dStartTime);

public/include/classes/mail.class.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,49 @@ function checkStmt($bState) {
1515
return true;
1616
}
1717

18+
/**
19+
* Mail form contact site admin
20+
* @param senderName string senderName
21+
* @param senderEmail string senderEmail
22+
* @param senderSubject string senderSubject
23+
* @param senderMessage string senderMessage
24+
* @param email string config Email address
25+
* @param subject string header subject
26+
* @return bool
27+
**/
28+
public function contactform($senderName, $senderEmail, $senderSubject, $senderMessage) {
29+
$this->debug->append("STA " . __METHOD__, 4);
30+
if (preg_match('/[^a-z_\.\!\?\-0-9\\s ]/i', $senderName)) {
31+
$this->setErrorMessage('Username may only contain alphanumeric characters');
32+
return false;
33+
}
34+
if (empty($senderEmail) || !filter_var($senderEmail, FILTER_VALIDATE_EMAIL)) {
35+
$this->setErrorMessage( 'Invalid e-mail address' );
36+
return false;
37+
}
38+
if (preg_match('/[^a-z_\.\!\?\-0-9\\s ]/i', $senderSubject)) {
39+
$this->setErrorMessage('Subject may only contain alphanumeric characters');
40+
return false;
41+
}
42+
if (strlen(strip_tags($senderMessage)) < strlen($senderMessage)) {
43+
$this->setErrorMessage('Your message may only contain alphanumeric characters');
44+
return false;
45+
}
46+
$aData['senderName'] = $senderName;
47+
$aData['senderEmail'] = $senderEmail;
48+
$aData['senderSubject'] = $senderSubject;
49+
$aData['senderMessage'] = $senderMessage;
50+
$aData['email'] = $this->setting->getValue('website_email');
51+
$aData['subject'] = 'Contact From';
52+
if ($this->sendMail('contactform/body', $aData)) {
53+
return true;
54+
} else {
55+
$this->setErrorMessage( 'Unable to send email' );
56+
return false;
57+
}
58+
return false;
59+
}
60+
1861
public function sendMail($template, $aData) {
1962
$this->smarty->assign('WEBSITENAME', $this->setting->getValue('website_name'));
2063
$this->smarty->assign('SUBJECT', $aData['subject']);

public/include/classes/roundstats.class.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,20 +102,20 @@ public function getRoundStatsForAccounts($iHeight=0, $isAdmin=0) {
102102
* @param height int Block Height
103103
* @return data array Block round transactions
104104
**/
105-
public function getAllRoundTransactions($iHeight=0) {
105+
public function getAllRoundTransactions($iHeight=0, $admin) {
106106
$this->debug->append("STA " . __METHOD__, 4);
107107
$stmt = $this->mysqli->prepare("
108108
SELECT
109109
t.id AS id,
110-
a.username AS username,
110+
IF(a.is_anonymous, IF( ? , a.username, 'anonymous'), a.username) AS username,
111111
t.type AS type,
112112
t.amount AS amount
113113
FROM $this->tableTrans AS t
114114
LEFT JOIN $this->tableBlocks AS b ON t.block_id = b.id
115115
LEFT JOIN $this->tableUsers AS a ON t.account_id = a.id
116116
WHERE b.height = ?
117117
ORDER BY id ASC");
118-
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $iHeight) && $stmt->execute() && $result = $stmt->get_result())
118+
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $admin, $iHeight) && $stmt->execute() && $result = $stmt->get_result())
119119
return $result->fetch_all(MYSQLI_ASSOC);
120120
$this->debug->append('Unable to fetch transactions');
121121
return false;

public/include/classes/statistics.class.php

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -99,25 +99,25 @@ public function updateShareStatistics($aStats, $iBlockId) {
9999
* @param none
100100
* @return data object Return our hashrateas an object
101101
**/
102-
public function getCurrentHashrate() {
102+
public function getCurrentHashrate($interval=600) {
103103
$this->debug->append("STA " . __METHOD__, 4);
104104
if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__)) return $data;
105105
$stmt = $this->mysqli->prepare("
106106
SELECT
107107
(
108108
(
109-
SELECT IFNULL(ROUND(SUM(IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * 65536 / 600 / 1000), 0) AS hashrate
109+
SELECT IFNULL(ROUND(SUM(IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * 65536 / ? / 1000), 0) AS hashrate
110110
FROM " . $this->share->getTableName() . "
111-
WHERE time > DATE_SUB(now(), INTERVAL 600 SECOND)
111+
WHERE time > DATE_SUB(now(), INTERVAL ? SECOND)
112112
) + (
113-
SELECT IFNULL(ROUND(SUM(IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * 65536 / 600 / 1000), 0) AS hashrate
113+
SELECT IFNULL(ROUND(SUM(IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * 65536 / ? / 1000), 0) AS hashrate
114114
FROM " . $this->share->getArchiveTableName() . "
115-
WHERE time > DATE_SUB(now(), INTERVAL 600 SECOND)
115+
WHERE time > DATE_SUB(now(), INTERVAL ? SECOND)
116116
)
117117
) AS hashrate
118118
FROM DUAL");
119119
// Catchall
120-
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result() ) return $this->memcache->setCache(__FUNCTION__, $result->fetch_object()->hashrate);
120+
if ($this->checkStmt($stmt) && $stmt->bind_param('iiii', $interval, $interval, $interval, $interval) && $stmt->execute() && $result = $stmt->get_result() ) return $this->memcache->setCache(__FUNCTION__, $result->fetch_object()->hashrate);
121121
$this->debug->append("Failed to get hashrate: " . $this->mysqli->error);
122122
return false;
123123
}
@@ -222,6 +222,8 @@ public function getAllUserShares() {
222222
} else {
223223
$data['data'][$row['id']]['valid'] += $row['valid'];
224224
$data['data'][$row['id']]['invalid'] += $row['invalid'];
225+
$data['data'][$row['id']]['donate_percent'] = $row['donate_percent'];
226+
$data['data'][$row['id']]['is_anonymous'] = $row['is_anonymous'];
225227
}
226228
}
227229
$data['share_id'] = $this->share->getMaxShareId();
@@ -293,28 +295,28 @@ public function getAllUserStats($filter='%') {
293295
* @param account_id integer User ID
294296
* @return data integer Current Hashrate in khash/s
295297
**/
296-
public function getUserHashrate($account_id) {
298+
public function getUserHashrate($account_id, $interval=600) {
297299
$this->debug->append("STA " . __METHOD__, 4);
298-
if ($data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data;
300+
if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data;
299301
$stmt = $this->mysqli->prepare("
300302
SELECT
301303
(
302-
SELECT IFNULL(ROUND(SUM(IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * 65536 / 600 / 1000), 0) AS hashrate
304+
SELECT IFNULL(ROUND(SUM(IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * 65536 / ? / 1000), 0) AS hashrate
303305
FROM " . $this->share->getTableName() . " AS s,
304306
" . $this->user->getTableName() . " AS u
305307
WHERE u.username = SUBSTRING_INDEX( s.username, '.', 1 )
306-
AND s.time > DATE_SUB(now(), INTERVAL 600 SECOND)
308+
AND s.time > DATE_SUB(now(), INTERVAL ? SECOND)
307309
AND u.id = ?
308310
) + (
309-
SELECT IFNULL(ROUND(SUM(IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * 65536 / 600 / 1000), 0) AS hashrate
311+
SELECT IFNULL(ROUND(SUM(IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * 65536 / ? / 1000), 0) AS hashrate
310312
FROM " . $this->share->getArchiveTableName() . " AS s,
311313
" . $this->user->getTableName() . " AS u
312314
WHERE u.username = SUBSTRING_INDEX( s.username, '.', 1 )
313-
AND s.time > DATE_SUB(now(), INTERVAL 600 SECOND)
315+
AND s.time > DATE_SUB(now(), INTERVAL ? SECOND)
314316
AND u.id = ?
315317
) AS hashrate
316318
FROM DUAL");
317-
if ($this->checkStmt($stmt) && $stmt->bind_param("ii", $account_id, $account_id) && $stmt->execute() && $result = $stmt->get_result() )
319+
if ($this->checkStmt($stmt) && $stmt->bind_param("iiiiii", $interval, $interval, $account_id, $interval, $interval, $account_id) && $stmt->execute() && $result = $stmt->get_result() )
318320
return $this->memcache->setCache(__FUNCTION__ . $account_id, $result->fetch_object()->hashrate);
319321
// Catchall
320322
$this->debug->append("Failed to fetch hashrate: " . $this->mysqli->error);
@@ -328,7 +330,7 @@ public function getUserHashrate($account_id) {
328330
**/
329331
public function getUserSharerate($account_id, $interval=600) {
330332
$this->debug->append("STA " . __METHOD__, 4);
331-
if ($data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data;
333+
if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data;
332334
$stmt = $this->mysqli->prepare("
333335
SELECT
334336
(
@@ -400,6 +402,8 @@ public function getTopContributors($type='shares', $limit=15) {
400402
foreach ($data['data'] as $key => $aUser) {
401403
$data_new[$key]['shares'] = $aUser['valid'];
402404
$data_new[$key]['account'] = $aUser['username'];
405+
$data_new[$key]['donate_percent'] = $aUser['donate_percent'];
406+
$data_new[$key]['is_anonymous'] = $aUser['is_anonymous'];
403407
}
404408
return $data_new;
405409
}

public/include/classes/transaction.class.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -251,19 +251,19 @@ public function getBalance($account_id) {
251251
$this->debug->append("STA " . __METHOD__, 4);
252252
$stmt = $this->mysqli->prepare("
253253
SELECT
254-
ROUND((
254+
IFNULL(ROUND((
255255
SUM( IF( ( t.type IN ('Credit','Bonus') AND b.confirmations >= ? ) OR t.type = 'Credit_PPS', t.amount, 0 ) ) -
256256
SUM( IF( t.type IN ('Debit_MP', 'Debit_AP'), t.amount, 0 ) ) -
257257
SUM( IF( ( t.type IN ('Donation','Fee') AND b.confirmations >= ? ) OR ( t.type IN ('Donation_PPS', 'Fee_PPS', 'TXFee') ), t.amount, 0 ) )
258-
), 8) AS confirmed,
259-
ROUND((
258+
), 8), 0) AS confirmed,
259+
IFNULL(ROUND((
260260
SUM( IF( t.type IN ('Credit','Bonus') AND b.confirmations < ? AND b.confirmations >= 0, t.amount, 0 ) ) -
261261
SUM( IF( t.type IN ('Donation','Fee') AND b.confirmations < ? AND b.confirmations >= 0, t.amount, 0 ) )
262-
), 8) AS unconfirmed,
263-
ROUND((
262+
), 8), 0) AS unconfirmed,
263+
IFNULL(ROUND((
264264
SUM( IF( t.type IN ('Credit','Bonus') AND b.confirmations = -1, t.amount, 0) ) -
265265
SUM( IF( t.type IN ('Donation','Fee') AND b.confirmations = -1, t.amount, 0) )
266-
), 8) AS orphaned
266+
), 8), 0) AS orphaned
267267
FROM $this->table AS t
268268
LEFT JOIN " . $this->block->getTableName() . " AS b
269269
ON t.block_id = b.id

public/include/classes/user.class.php

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ private function getHash($string) {
4343
public function getUserName($id) {
4444
return $this->getSingle($id, 'username', 'id');
4545
}
46+
public function getUserNameByEmail($email) {
47+
return $this->getSingle($email, 'username', 'email', 's');
48+
}
4649
public function getUserId($username) {
4750
return $this->getSingle($username, 'id', 'username', 's');
4851
}
@@ -126,6 +129,13 @@ public function checkLogin($username, $password) {
126129
$this->setErrorMessage("Invalid username or password.");
127130
return false;
128131
}
132+
if (filter_var($username, FILTER_VALIDATE_EMAIL)) {
133+
$this->debug->append("Username is an e-mail", 2);
134+
if (!$username = $this->getUserNameByEmail($username)) {
135+
$this->setErrorMessage("Invalid username or password.");
136+
return false;
137+
}
138+
}
129139
if ($this->isLocked($this->getUserId($username))) {
130140
$this->setErrorMessage("Account is locked. Please contact site support.");
131141
return false;
@@ -411,7 +421,7 @@ private function createSession($username) {
411421
* @param none
412422
* @return true
413423
**/
414-
public function logoutUser($redirect="index.php") {
424+
public function logoutUser($from="") {
415425
$this->debug->append("STA " . __METHOD__, 4);
416426
// Unset all of the session variables
417427
$_SESSION = array();
@@ -424,8 +434,11 @@ public function logoutUser($redirect="index.php") {
424434
session_destroy();
425435
// Enforce generation of a new Session ID and delete the old
426436
session_regenerate_id(true);
427-
// Enforce a page reload
428-
header("Location: $redirect");
437+
// Enforce a page reload and point towards login with referrer included, if supplied
438+
$location = @$_SERVER['HTTPS'] ? 'https' . '://' . $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF'] : 'http' . '://' . $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF'];
439+
if (!empty($from)) $location .= '?page=login&to=' . urlencode($from);
440+
// if (!headers_sent()) header('Location: ' . $location);
441+
exit('<meta http-equiv="refresh" content="0; url=' . $location . '"/>');
429442
}
430443

431444
/**
@@ -651,14 +664,14 @@ public function initResetPassword($username) {
651664
* @param none
652665
* @return bool
653666
**/
654-
public function isAuthenticated() {
667+
public function isAuthenticated($logout=true) {
655668
$this->debug->append("STA " . __METHOD__, 4);
656669
if (@$_SESSION['AUTHENTICATED'] == true &&
657670
!$this->isLocked($_SESSION['USERDATA']['id']) &&
658671
$this->getUserIp($_SESSION['USERDATA']['id']) == $_SERVER['REMOTE_ADDR']
659672
) return true;
660673
// Catchall
661-
$this->logoutUser();
674+
if ($logout == true) $this->logoutUser($_SERVER['REQUEST_URI']);
662675
return false;
663676
}
664677
}

public/include/config/admin_settings.inc.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,20 @@
102102
'name' => 'wallet_cold_coins', 'value' => $setting->getValue('wallet_cold_coins'),
103103
'tooltip' => 'Amount of coins held in a pools cold wallet.'
104104
);
105+
$aSettings['statistics'][] = array(
106+
'display' => 'Ajax Refresh Interval', 'type' => 'select',
107+
'options' => array('5' => '5', '10' => '10', '15' => '15', '30' => '30', '60' => '60' ),
108+
'default' => 10,
109+
'name' => 'statistics_ajax_refresh_interval', 'value' => $setting->getValue('statistics_ajax_refresh_interval'),
110+
'tooltip' => 'How often to refresh data via ajax in seconds.'
111+
);
112+
$aSettings['statistics'][] = array(
113+
'display' => 'Ajax Data Interval', 'type' => 'select',
114+
'options' => array('60' => '1', '300' => '5', '600' => '10'),
115+
'default' => 300,
116+
'name' => 'statistics_ajax_data_interval', 'value' => $setting->getValue('statistics_ajax_data_interval'),
117+
'tooltip' => 'Time in minutes, interval for hashrate and sharerate calculations. Higher intervals allow for better accuracy at a higer server load.'
118+
);
105119
$aSettings['statistics'][] = array(
106120
'display' => 'Block Statistics Count', 'type' => 'text',
107121
'size' => 25,
@@ -151,6 +165,13 @@
151165
'name' => 'acl_round_statistics', 'value' => $setting->getValue('acl_round_statistics'),
152166
'tooltip' => 'Make the round statistics page private (users only) or public.'
153167
);
168+
$aSettings['acl'][] = array(
169+
'display' => 'Round Transactions', 'type' => 'select',
170+
'options' => array( 0 => 'Admins', 1 => 'Public'),
171+
'default' => 0,
172+
'name' => 'acl_round_transactions', 'value' => $setting->getValue('acl_round_transactions'),
173+
'tooltip' => 'Display all transactions regardless of admin status.'
174+
);
154175
$aSettings['system'][] = array(
155176
'display' => 'Disable e-mail confirmations', 'type' => 'select',
156177
'options' => array( 0 => 'No', 1 => 'Yes' ),
@@ -200,6 +221,13 @@
200221
'name' => 'disable_api', 'value' => $setting->getValue('disable_api'),
201222
'tooltip' => 'Enable or Disable the pool wide API functions. See API reference on Github for details.'
202223
);
224+
$aSettings['system'][] = array(
225+
'display' => 'Disable Contactform', 'type' => 'select',
226+
'options' => array( 0 => 'No', 1 => 'Yes' ),
227+
'default' => 0,
228+
'name' => 'disable_contactform', 'value' => $setting->getValue('disable_contactform'),
229+
'tooltip' => 'Enable or Disable Contactform. Users will not be able to use the contact form.'
230+
);
203231
$aSettings['recaptcha'][] = array(
204232
'display' => 'Enable re-Captcha', 'type' => 'select',
205233
'options' => array( 0 => 'No', 1 => 'Yes' ),

0 commit comments

Comments
 (0)