This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | $defflip = (!cfip()) ? exit(header('HTTP/1.1 401 Unauthorized')) : 1; |
||
3 | |||
4 | class Worker extends Base { |
||
5 | protected $table = 'pool_worker'; |
||
6 | |||
7 | /** |
||
8 | * We allow changing the database for shared accounts across pools |
||
9 | * Load the config on construct so we can assign the DB name |
||
10 | * @param config array MPOS configuration |
||
11 | * @return none |
||
0 ignored issues
–
show
|
|||
12 | **/ |
||
13 | public function __construct($config) { |
||
14 | $this->setConfig($config); |
||
15 | $this->table = $this->config['db']['shared']['workers'] . '.' . $this->table; |
||
0 ignored issues
–
show
The property
config does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
16 | } |
||
17 | |||
18 | /** |
||
19 | * Update worker list for a user |
||
20 | * @param account_id int User ID |
||
21 | * @param data array All workers and their settings |
||
22 | * @return bool |
||
23 | **/ |
||
24 | public function updateWorkers($account_id, $data) { |
||
25 | $this->debug->append("STA " . __METHOD__, 4); |
||
26 | if (!is_array($data)) { |
||
27 | $this->setErrorMessage('No workers to update'); |
||
28 | return false; |
||
29 | } |
||
30 | $username = $this->user->getUserName($account_id); |
||
0 ignored issues
–
show
The property
user does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
31 | $iFailed = 0; |
||
32 | foreach ($data as $key => $value) { |
||
33 | if ('' === $value['username'] || '' === $value['password']) { |
||
34 | $iFailed++; |
||
35 | } else { |
||
36 | // Check worker name first |
||
37 | if (! preg_match("/^[0-9a-zA-Z_\-]*$/", $value['username'])) { |
||
38 | $iFailed++; |
||
39 | continue; |
||
40 | } |
||
41 | // Prefix the WebUser to Worker name |
||
42 | $value['username'] = "$username." . $value['username']; |
||
43 | $stmt = $this->mysqli->prepare("UPDATE $this->table SET password = ?, username = ?, monitor = ? WHERE account_id = ? AND id = ? LIMIT 1"); |
||
44 | if ( ! ( $this->checkStmt($stmt) && $stmt->bind_param('ssiii', $value['password'], $value['username'], $value['monitor'], $account_id, $key) && $stmt->execute()) ) |
||
45 | $iFailed++; |
||
46 | } |
||
47 | } |
||
48 | if ($iFailed == 0) |
||
49 | return true; |
||
50 | return $this->sqlError('E0053', $iFailed); |
||
51 | } |
||
52 | |||
53 | /** |
||
54 | * Fetch all IDLE workers that have monitoring enabled |
||
55 | * @param none |
||
56 | * @return data array Workers in IDLE state and monitoring enabled |
||
57 | **/ |
||
58 | View Code Duplication | public function getAllIdleWorkers($interval=600) { |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
59 | $this->debug->append("STA " . __METHOD__, 4); |
||
60 | $stmt = $this->mysqli->prepare(" |
||
61 | SELECT w.account_id AS account_id, w.id AS id, w.username AS username |
||
62 | FROM |
||
63 | ( |
||
64 | SELECT username AS s_username, MAX(shares_id) AS shares_id, MAX(shares_archive_id) AS shares_archive_id |
||
65 | FROM |
||
66 | ( |
||
67 | SELECT |
||
68 | s.username AS username, MAX(s.id) AS shares_id, NULL AS shares_archive_id |
||
69 | FROM . " . $this->share->getTableName() . " AS s |
||
0 ignored issues
–
show
The property
share does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
70 | WHERE s.time > DATE_SUB(now(), INTERVAL ? SECOND) |
||
71 | AND s.our_result = 'Y' |
||
72 | GROUP BY s.username |
||
73 | UNION |
||
74 | SELECT |
||
75 | sa.username AS username, NULL AS shares_id, MAX(sa.id) AS shares_archive_id |
||
76 | FROM " . $this->share->getArchiveTableName() . " AS sa |
||
77 | WHERE sa.time > DATE_SUB(now(), INTERVAL ? SECOND) |
||
78 | AND sa.our_result = 'Y' |
||
79 | GROUP BY sa.username |
||
80 | ) AS derived0 |
||
81 | GROUP BY s_username |
||
82 | ) AS derived1 |
||
83 | RIGHT JOIN " . $this->getTableName() . " AS w |
||
84 | ON s_username = w.username |
||
85 | WHERE w.monitor = 1 |
||
86 | AND shares_id IS NULL |
||
87 | AND shares_archive_id IS NULL |
||
88 | "); |
||
89 | if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $interval, $interval) && $stmt->execute() && $result = $stmt->get_result()) |
||
90 | return $result->fetch_all(MYSQLI_ASSOC); |
||
91 | return $this->sqlError('E0054'); |
||
0 ignored issues
–
show
The return type of
return $this->sqlError('E0054'); (boolean ) is incompatible with the return type documented by Worker::getAllIdleWorkers of type data .
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design. Let’s take a look at an example: class Author {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
abstract class Post {
public function getAuthor() {
return 'Johannes';
}
}
class BlogPost extends Post {
public function getAuthor() {
return new Author('Johannes');
}
}
class ForumPost extends Post { /* ... */ }
function my_function(Post $post) {
echo strtoupper($post->getAuthor());
}
Our function ![]() |
|||
92 | } |
||
93 | |||
94 | /** |
||
95 | * Fetch a specific worker and its status |
||
96 | * @param id int Worker ID |
||
97 | * @return mixed array Worker details |
||
98 | **/ |
||
99 | public function getWorker($id, $interval=600) { |
||
100 | $this->debug->append("STA " . __METHOD__, 4); |
||
101 | $stmt = $this->mysqli->prepare(" |
||
102 | SELECT id, username, password, monitor, |
||
103 | ( |
||
104 | SELECT COUNT(id) FROM " . $this->share->getTableName() . " WHERE our_result = 'Y' AND username = w.username AND time > DATE_SUB(now(), INTERVAL ? SECOND) |
||
105 | ) + ( |
||
106 | SELECT COUNT(id) FROM " . $this->share->getArchiveTableName() . " WHERE our_result = 'Y' AND username = w.username AND time > DATE_SUB(now(), INTERVAL ? SECOND) |
||
107 | ) AS count_all, |
||
108 | ( |
||
109 | SELECT |
||
110 | IFNULL(SUM(difficulty), 0) |
||
111 | FROM " . $this->share->getTableName() . " |
||
112 | WHERE |
||
113 | username = w.username |
||
114 | AND our_result = 'Y' |
||
115 | AND time > DATE_SUB(now(), INTERVAL ? SECOND) |
||
116 | ) + ( |
||
117 | SELECT |
||
118 | IFNULL(SUM(difficulty), 0) |
||
119 | FROM " . $this->share->getArchiveTableName() . " |
||
120 | WHERE |
||
121 | username = w.username |
||
122 | AND our_result = 'Y' |
||
123 | AND time > DATE_SUB(now(), INTERVAL ? SECOND) |
||
124 | ) AS shares |
||
125 | FROM $this->table AS w |
||
126 | WHERE id = ?"); |
||
127 | if ($this->checkStmt($stmt) && $stmt->bind_param('iiiii', $interval, $interval, $interval, $interval, $id) && $stmt->execute() && ($result = $stmt->get_result()) && ($row = $result->fetch_assoc())) { |
||
128 | $row['hashrate'] = round($this->coin->calcHashrate($row['shares'], $interval), 2); |
||
0 ignored issues
–
show
The property
coin does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
129 | if ($row['count_all'] > 0) { |
||
130 | $row['difficulty'] = round($row['shares'] / $row['count_all'], 2); |
||
131 | } else { |
||
132 | $row['difficulty'] = 0.00; |
||
133 | } |
||
134 | return $row; |
||
135 | } |
||
136 | return $this->sqlError('E0055'); |
||
137 | } |
||
138 | |||
139 | /** |
||
140 | * Fetch all workers for an account |
||
141 | * @param account_id int User ID |
||
142 | * @return mixed array Workers and their settings or false |
||
143 | **/ |
||
144 | public function getWorkers($account_id, $interval=600) { |
||
145 | $this->debug->append("STA " . __METHOD__, 4); |
||
146 | $stmt = $this->mysqli->prepare(" |
||
147 | SELECT id, username, password, monitor, |
||
148 | ( |
||
149 | SELECT COUNT(id) FROM " . $this->share->getTableName() . " WHERE our_result = 'Y' AND username = w.username AND time > DATE_SUB(now(), INTERVAL ? SECOND) |
||
150 | ) + ( |
||
151 | SELECT COUNT(id) FROM " . $this->share->getArchiveTableName() . " WHERE our_result = 'Y' AND username = w.username AND time > DATE_SUB(now(), INTERVAL ? SECOND) |
||
152 | ) AS count_all, |
||
153 | ( |
||
154 | SELECT |
||
155 | IFNULL(SUM(difficulty), 0) |
||
156 | FROM " . $this->share->getTableName() . " |
||
157 | WHERE |
||
158 | username = w.username |
||
159 | AND our_result = 'Y' |
||
160 | AND time > DATE_SUB(now(), INTERVAL ? SECOND) |
||
161 | ) + ( |
||
162 | SELECT |
||
163 | IFNULL(SUM(difficulty), 0) |
||
164 | FROM " . $this->share->getArchiveTableName() . " |
||
165 | WHERE |
||
166 | username = w.username |
||
167 | AND our_result = 'Y' |
||
168 | AND time > DATE_SUB(now(), INTERVAL ? SECOND) |
||
169 | ) AS shares |
||
170 | FROM $this->table AS w |
||
171 | WHERE account_id = ?"); |
||
172 | View Code Duplication | if ($this->checkStmt($stmt) && $stmt->bind_param('iiiii', $interval, $interval, $interval, $interval, $account_id) && $stmt->execute() && $result = $stmt->get_result()) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
173 | $aData = array(); |
||
174 | while ($row = $result->fetch_assoc()) { |
||
175 | $row['hashrate'] = round($this->coin->calcHashrate($row['shares'], $interval), 2); |
||
176 | if ($row['count_all'] > 0) { |
||
177 | $row['difficulty'] = round($row['shares'] / $row['count_all'], $this->coin->getShareDifficultyPrecision()); |
||
178 | } else { |
||
179 | $row['difficulty'] = 0.00; |
||
180 | } |
||
181 | $aData[] = $row; |
||
182 | } |
||
183 | return $aData; |
||
184 | } |
||
185 | return $this->sqlError('E0056'); |
||
186 | } |
||
187 | |||
188 | /** |
||
189 | * Fetch all workers for admin panel |
||
190 | * @param limit int max amount of workers |
||
191 | * @return mixed array Workers and their settings or false |
||
192 | **/ |
||
193 | public function getAllWorkers($iLimit=0, $interval=600, $start=0) { |
||
194 | $this->debug->append("STA " . __METHOD__, 4); |
||
195 | $stmt = $this->mysqli->prepare(" |
||
196 | SELECT id, username, password, monitor, |
||
197 | ( |
||
198 | SELECT COUNT(id) FROM " . $this->share->getTableName() . " WHERE our_result = 'Y' AND username = w.username AND time > DATE_SUB(now(), INTERVAL ? SECOND) |
||
199 | ) + ( |
||
200 | SELECT COUNT(id) FROM " . $this->share->getArchiveTableName() . " WHERE our_result = 'Y' AND username = w.username AND time > DATE_SUB(now(), INTERVAL ? SECOND) |
||
201 | ) AS count_all, |
||
202 | IFNULL(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty), 0) AS difficulty, |
||
203 | ( |
||
204 | SELECT |
||
205 | IFNULL(SUM(difficulty), 0) |
||
206 | FROM " . $this->share->getTableName() . " |
||
207 | WHERE |
||
208 | username = w.username |
||
209 | AND our_result = 'Y' |
||
210 | AND time > DATE_SUB(now(), INTERVAL ? SECOND) |
||
211 | ) + ( |
||
212 | SELECT |
||
213 | IFNULL(SUM(difficulty), 0) |
||
214 | FROM " . $this->share->getArchiveTableName() . " |
||
215 | WHERE |
||
216 | username = w.username |
||
217 | AND our_result = 'Y' |
||
218 | AND time > DATE_SUB(now(), INTERVAL ? SECOND) |
||
219 | ) AS shares |
||
220 | FROM $this->table AS w |
||
221 | ORDER BY shares DESC LIMIT ?,?"); |
||
222 | View Code Duplication | if ($this->checkStmt($stmt) && $stmt->bind_param('iiiiii', $interval, $interval, $interval, $interval, $start, $iLimit) && $stmt->execute() && $result = $stmt->get_result()) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
223 | $aData = array(); |
||
224 | while ($row = $result->fetch_assoc()) { |
||
225 | $row['hashrate'] = round($this->coin->calcHashrate($row['shares'], $interval), 2); |
||
226 | if ($row['count_all'] > 0) { |
||
227 | $row['avg_difficulty'] = round($row['shares'] / $row['count_all'], 2); |
||
228 | } else { |
||
229 | $row['avg_difficulty'] = 0.00; |
||
230 | } |
||
231 | $aData[] = $row; |
||
232 | } |
||
233 | return $aData; |
||
234 | } |
||
235 | return $this->sqlError('E0057'); |
||
236 | } |
||
237 | |||
238 | /** |
||
239 | * Get all currently active workers in the past 2 minutes |
||
240 | * @param none |
||
241 | * @return data mixed int count if any workers are active, false otherwise |
||
242 | **/ |
||
243 | View Code Duplication | public function getCountAllActiveWorkers($interval=120) { |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
244 | $this->debug->append("STA " . __METHOD__, 4); |
||
245 | if ($data = $this->memcache->get(__FUNCTION__)) return $data; |
||
0 ignored issues
–
show
The property
memcache does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
246 | $stmt = $this->mysqli->prepare(" |
||
247 | SELECT COUNT(DISTINCT(username)) AS total |
||
248 | FROM " . $this->share->getTableName() . " |
||
249 | WHERE our_result = 'Y' |
||
250 | AND time > DATE_SUB(now(), INTERVAL ? SECOND)"); |
||
251 | if ($this->checkStmt($stmt) && $stmt->bind_param('i', $interval) && $stmt->execute() && $result = $stmt->get_result()) |
||
252 | return $this->memcache->setCache(__FUNCTION__, $result->fetch_object()->total); |
||
253 | return $this->sqlError(); |
||
0 ignored issues
–
show
The return type of
return $this->sqlError(); (boolean ) is incompatible with the return type documented by Worker::getCountAllActiveWorkers of type data .
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design. Let’s take a look at an example: class Author {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
abstract class Post {
public function getAuthor() {
return 'Johannes';
}
}
class BlogPost extends Post {
public function getAuthor() {
return new Author('Johannes');
}
}
class ForumPost extends Post { /* ... */ }
function my_function(Post $post) {
echo strtoupper($post->getAuthor());
}
Our function ![]() |
|||
254 | } |
||
255 | |||
256 | /** |
||
257 | * Add new worker to an existing web account |
||
258 | * The webuser name is prefixed to the worker name |
||
259 | * Passwords are plain text for pushpoold |
||
260 | * @param account_id int User ID |
||
261 | * @param workerName string Worker name |
||
262 | * @param workerPassword string Worker password |
||
263 | * @return bool |
||
264 | **/ |
||
265 | public function addWorker($account_id, $workerName, $workerPassword) { |
||
266 | $this->debug->append("STA " . __METHOD__, 4); |
||
267 | if ('' === $workerName || '' === $workerPassword) { |
||
268 | $this->setErrorMessage($this->getErrorMsg('E0058')); |
||
269 | return false; |
||
270 | } |
||
271 | if (!preg_match("/^[0-9a-zA-Z_\-]*$/", $workerName)) { |
||
272 | $this->setErrorMessage($this->getErrorMsg('E0072')); |
||
273 | return false; |
||
274 | } |
||
275 | $username = $this->user->getUserName($account_id); |
||
276 | $workerName = "$username.$workerName"; |
||
277 | if (strlen($workerName) > 50) { |
||
278 | $this->setErrorMessage($this->getErrorMsg('E0073')); |
||
279 | return false; |
||
280 | } |
||
281 | $stmt = $this->mysqli->prepare("INSERT INTO $this->table (account_id, username, password) VALUES(?, ?, ?)"); |
||
282 | if ($this->checkStmt($stmt) && $stmt->bind_param('iss', $account_id, $workerName, $workerPassword)) { |
||
283 | if (!$stmt->execute()) { |
||
284 | if ($stmt->sqlstate == '23000') return $this->sqlError('E0059'); |
||
285 | } else { |
||
286 | return true; |
||
287 | } |
||
288 | } |
||
289 | return $this->sqlError('E0060'); |
||
290 | } |
||
291 | |||
292 | /** |
||
293 | * Delete existing worker from account |
||
294 | * @param account_id int User ID |
||
295 | * @param id int Worker ID |
||
296 | * @return bool |
||
297 | **/ |
||
298 | View Code Duplication | public function deleteWorker($account_id, $id) { |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
299 | $this->debug->append("STA " . __METHOD__, 4); |
||
300 | $stmt = $this->mysqli->prepare("DELETE FROM $this->table WHERE account_id = ? AND id = ? LIMIT 1"); |
||
301 | if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $account_id, $id) && $stmt->execute() && $stmt->affected_rows == 1) |
||
302 | return true; |
||
303 | return $this->sqlError('E0061'); |
||
304 | } |
||
305 | } |
||
306 | |||
307 | $worker = new Worker($config); |
||
308 | $worker->setDebug($debug); |
||
309 | $worker->setMysql($mysqli); |
||
310 | $worker->setMemcache($memcache); |
||
311 | $worker->setShare($share); |
||
312 | $worker->setUser($user); |
||
313 | $worker->setErrorCodes($aErrorCodes); |
||
314 | $worker->setCoin($coin); |
||
315 |
Adding a
@return
annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.Please refer to the PHP core documentation on constructors.