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 Share Extends Base { |
||
5 | protected $table = 'shares'; |
||
6 | protected $tableArchive = 'shares_archive'; |
||
7 | private $oUpstream; |
||
8 | private $iLastUpstreamId; |
||
9 | // This defines each share |
||
10 | public $rem_host, $username, $our_result, $upstream_result, $reason, $solution, $time, $difficulty; |
||
11 | |||
12 | /** |
||
13 | * Fetch archive tables name for this class |
||
14 | * @param none |
||
15 | * @return data string Table name |
||
16 | **/ |
||
17 | public function getArchiveTableName() { |
||
18 | return $this->tableArchive; |
||
19 | } |
||
20 | |||
21 | /** |
||
22 | * Fetch a single share by ID |
||
23 | * @param id int Share ID |
||
24 | * @return array Share data |
||
25 | **/ |
||
26 | public function getShareById($id) { |
||
27 | return $this->getSingleAssoc($id); |
||
28 | } |
||
29 | |||
30 | /** |
||
31 | * Update an entire shares data |
||
32 | **/ |
||
33 | public function updateShareById($id, $data) { |
||
34 | $this->debug->append("STA " . __METHOD__, 4); |
||
35 | $sql = "UPDATE $this->table SET"; |
||
36 | $start = true; |
||
37 | // Remove ID column |
||
38 | unset($data['id']); |
||
39 | foreach ($data as $column => $value) { |
||
40 | $start == true ? $sql .= " $column = ? " : $sql .= ", $column = ?"; |
||
0 ignored issues
–
show
|
|||
41 | $start = false; |
||
42 | switch($column) { |
||
43 | case 'difficulty': |
||
44 | $this->addParam('d', $value); |
||
45 | break; |
||
46 | default: |
||
47 | $this->addParam('s', $value); |
||
48 | break; |
||
49 | } |
||
50 | } |
||
51 | $sql .= " WHERE id = ? LIMIT 1"; |
||
52 | $this->addParam('i', $id); |
||
53 | $stmt = $this->mysqli->prepare($sql); |
||
54 | View Code Duplication | if ($this->checkStmt($stmt) && call_user_func_array( array($stmt, 'bind_param'), $this->getParam()) && $stmt->execute()) |
|
55 | return true; |
||
56 | return $this->sqlError(); |
||
57 | } |
||
58 | |||
59 | /** |
||
60 | * Get last inserted Share ID from Database |
||
61 | * Used for PPS calculations without moving to archive |
||
62 | **/ |
||
63 | public function getLastInsertedShareId() { |
||
64 | $stmt = $this->mysqli->prepare("SELECT MAX(id) AS id FROM $this->table"); |
||
65 | if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result()) |
||
66 | return $result->fetch_object()->id; |
||
67 | return $this->sqlError(); |
||
68 | } |
||
69 | |||
70 | /** |
||
71 | * Get all valid shares for this round |
||
72 | * @param previous_upstream int Previous found share accepted by upstream to limit results |
||
73 | * @param current_upstream int Current upstream accepted share |
||
74 | * @return data int Total amount of counted shares |
||
75 | **/ |
||
76 | public function getRoundShares($previous_upstream=0, $current_upstream) { |
||
77 | $stmt = $this->mysqli->prepare("SELECT |
||
78 | IFNULL(SUM(IF(s.difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty)), 0) AS total |
||
79 | FROM $this->table AS s |
||
80 | LEFT JOIN " . $this->user->getTableName() . " AS a |
||
81 | ON a.username = SUBSTRING_INDEX( s.username , '.', 1 ) |
||
82 | WHERE s.id > ? AND s.id <= ? AND s.our_result = 'Y' AND a.is_locked != 2 |
||
83 | "); |
||
84 | if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $previous_upstream, $current_upstream) && $stmt->execute() && $result = $stmt->get_result()) |
||
85 | return $result->fetch_object()->total; |
||
86 | return $this->sqlError(); |
||
0 ignored issues
–
show
The return type of
return $this->sqlError(); (boolean ) is incompatible with the return type documented by Share::getRoundShares 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
Loading history...
|
|||
87 | } |
||
88 | |||
89 | /** |
||
90 | * Fetch all shares grouped by accounts to count share per account |
||
91 | * @param previous_upstream int Previous found share accepted by upstream to limit results |
||
92 | * @param current_upstream int Current upstream accepted share |
||
93 | * @param limit int Limit to this amount of shares for PPLNS |
||
94 | * @return data array username, valid and invalid shares from account |
||
95 | **/ |
||
96 | public function getSharesForAccounts($previous_upstream=0, $current_upstream) { |
||
97 | $stmt = $this->mysqli->prepare(" |
||
98 | SELECT |
||
99 | a.id, |
||
100 | SUBSTRING_INDEX( s.username , '.', 1 ) as username, |
||
101 | a.no_fees AS no_fees, |
||
102 | IFNULL(SUM(IF(our_result='Y', IF(s.difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty), 0)), 0) AS valid, |
||
103 | IFNULL(SUM(IF(our_result='N', IF(s.difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty), 0)), 0) AS invalid |
||
104 | FROM $this->table AS s |
||
105 | LEFT JOIN " . $this->user->getTableName() . " AS a |
||
106 | ON a.username = SUBSTRING_INDEX( s.username , '.', 1 ) |
||
107 | WHERE s.id > ? AND s.id <= ? AND a.is_locked != 2 |
||
108 | GROUP BY username DESC |
||
109 | "); |
||
110 | if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $previous_upstream, $current_upstream) && $stmt->execute() && $result = $stmt->get_result()) |
||
111 | return $result->fetch_all(MYSQLI_ASSOC); |
||
112 | return $this->sqlError(); |
||
0 ignored issues
–
show
The return type of
return $this->sqlError(); (boolean ) is incompatible with the return type documented by Share::getSharesForAccounts 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
Loading history...
|
|||
113 | } |
||
114 | |||
115 | /** |
||
116 | * Fetch the highest available share ID from archive |
||
117 | **/ |
||
118 | function getMaxArchiveShareId() { |
||
119 | $stmt = $this->mysqli->prepare("SELECT MAX(share_id) AS share_id FROM $this->tableArchive"); |
||
120 | if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result()) |
||
121 | return $result->fetch_object()->share_id; |
||
122 | return $this->sqlError(); |
||
123 | } |
||
124 | |||
125 | /** |
||
126 | * We need a certain amount of valid archived shares |
||
127 | * param left int Left/lowest share ID |
||
128 | * param right int Right/highest share ID |
||
129 | * return array data Returns an array with usernames as keys for easy access |
||
130 | **/ |
||
131 | function getArchiveShares($iCount) { |
||
132 | $iMaxId = $this->getMaxArchiveShareId(); |
||
133 | $iMinId = $this->getMinArchiveShareId($iCount); |
||
134 | $stmt = $this->mysqli->prepare(" |
||
135 | SELECT |
||
136 | a.id, |
||
137 | SUBSTRING_INDEX( s.username , '.', 1 ) as account, |
||
138 | a.no_fees AS no_fees, |
||
139 | IFNULL(SUM(IF(our_result='Y', IF(s.difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty), 0)), 0) AS valid, |
||
140 | IFNULL(SUM(IF(our_result='N', IF(s.difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty), 0)), 0) AS invalid |
||
141 | FROM $this->tableArchive AS s |
||
142 | LEFT JOIN " . $this->user->getTableName() . " AS a |
||
143 | ON a.username = SUBSTRING_INDEX( s.username , '.', 1 ) |
||
144 | WHERE s.share_id > ? AND s.share_id <= ? AND a.is_locked != 2 |
||
145 | GROUP BY account DESC"); |
||
146 | if ($this->checkStmt($stmt) && $stmt->bind_param("ii", $iMinId, $iMaxId) && $stmt->execute() && $result = $stmt->get_result()) { |
||
147 | $aData = NULL; |
||
148 | while ($row = $result->fetch_assoc()) { |
||
149 | $aData[strtolower($row['account'])] = $row; |
||
150 | } |
||
151 | if (is_array($aData)) return $aData; |
||
152 | } |
||
153 | return $this->sqlError(); |
||
154 | } |
||
155 | |||
156 | /** |
||
157 | * We keep shares only up to a certain point |
||
158 | * This can be configured by the user. |
||
159 | * @return return bool true or false |
||
160 | **/ |
||
161 | public function purgeArchive() { |
||
162 | // Fallbacks if unset |
||
163 | if (!isset($this->config['archive']['purge'])) $this->config['archive']['purge'] = 5; |
||
164 | |||
165 | $stmt = $this->mysqli->prepare("SELECT CEIL(COUNT(id) / 100 * ?) AS count FROM $this->tableArchive"); |
||
166 | View Code Duplication | if ($this->checkStmt($stmt) && $stmt->bind_param('i', $this->config['archive']['purge']) && $stmt->execute() && $result = $stmt->get_result()) { |
|
167 | $limit = $result->fetch_object()->count; |
||
168 | } else { |
||
169 | return $this->sqlError(); |
||
170 | } |
||
171 | $stmt->close(); |
||
172 | $stmt = $this->mysqli->prepare(" |
||
173 | DELETE FROM $this->tableArchive WHERE time < ( |
||
174 | SELECT MIN(time) FROM ( |
||
175 | SELECT MIN(time) AS time |
||
176 | FROM $this->tableArchive |
||
177 | WHERE block_id = ( |
||
178 | SELECT MIN(id) AS minid FROM ( |
||
179 | SELECT id FROM " . $this->block->getTableName() . " ORDER BY height DESC LIMIT ? |
||
180 | ) AS minheight |
||
181 | ) UNION SELECT DATE_SUB(now(), INTERVAL ? MINUTE) AS time |
||
182 | ) AS mintime |
||
183 | ) LIMIT $limit |
||
184 | "); |
||
185 | if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $this->config['archive']['maxrounds'], $this->config['archive']['maxage']) && $stmt->execute()) |
||
186 | return $stmt->affected_rows; |
||
187 | return $this->sqlError(); |
||
188 | } |
||
189 | |||
190 | /** |
||
191 | * Move accounted shares to archive table, this step is optional |
||
192 | * @param previous_upstream int Previous found share accepted by upstream to limit results |
||
193 | * @param current_upstream int Current upstream accepted share |
||
194 | * @param block_id int Block ID to assign shares to a specific block |
||
195 | * @return bool |
||
196 | **/ |
||
197 | public function moveArchive($current_upstream, $block_id, $previous_upstream=0) { |
||
198 | if ($this->config['payout_system'] != 'pplns') { |
||
199 | // We don't need archived shares that much, so only archive as much as configured |
||
200 | $sql = " |
||
201 | INSERT INTO $this->tableArchive (share_id, username, our_result, upstream_result, block_id, time, difficulty) |
||
202 | SELECT id, username, our_result, upstream_result, ?, time, IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty) AS difficulty |
||
203 | FROM $this->table |
||
204 | WHERE id > ? AND id <= ? |
||
205 | AND time >= DATE_SUB(now(), INTERVAL " . $this->config['archive']['maxage'] . " MINUTE)"; |
||
206 | } else { |
||
207 | // PPLNS needs archived shares for later rounds, so we have to copy them all |
||
208 | $sql = " |
||
209 | INSERT INTO $this->tableArchive (share_id, username, our_result, upstream_result, block_id, time, difficulty) |
||
210 | SELECT id, username, our_result, upstream_result, ?, time, IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty) AS difficulty |
||
211 | FROM $this->table |
||
212 | WHERE id > ? AND id <= ?"; |
||
213 | } |
||
214 | $archive_stmt = $this->mysqli->prepare($sql); |
||
215 | if ($this->checkStmt($archive_stmt) && $archive_stmt->bind_param('iii', $block_id, $previous_upstream, $current_upstream) && $archive_stmt->execute()) |
||
216 | return true; |
||
217 | return $this->sqlError(); |
||
218 | } |
||
219 | |||
220 | /** |
||
221 | * Delete accounted shares from shares table |
||
222 | * @param current_upstream int Current highest upstream ID |
||
223 | * @param previous_upstream int Previous upstream ID |
||
224 | * @return bool true or false |
||
225 | **/ |
||
226 | public function deleteAccountedShares($current_upstream, $previous_upstream=0) { |
||
227 | // Fallbacks if unset |
||
228 | if (!isset($this->config['purge']['shares'])) $this->config['purge']['shares'] = 25000; |
||
229 | if (!isset($this->config['purge']['sleep'])) $this->config['purge']['sleep'] = 1; |
||
230 | |||
231 | $affected = 1; |
||
232 | while ($affected > 0) { |
||
233 | // Sleep first to allow any IO to cleanup |
||
234 | sleep($this->config['purge']['sleep']); |
||
235 | $stmt = $this->mysqli->prepare("DELETE FROM $this->table WHERE id > ? AND id <= ? ORDER BY id LIMIT " . $this->config['purge']['shares']); |
||
236 | $start = microtime(true); |
||
237 | View Code Duplication | if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $previous_upstream, $current_upstream) && $stmt->execute()) { |
|
238 | $affected = $stmt->affected_rows; |
||
239 | } else { |
||
240 | return $this->sqlError(); |
||
241 | } |
||
242 | } |
||
243 | return true; |
||
244 | } |
||
245 | |||
246 | /** |
||
247 | * Set/get last found share accepted by upstream: id and accounts |
||
248 | **/ |
||
249 | public function setLastUpstreamId() { |
||
250 | $this->iLastUpstreamId = @$this->oUpstream->id ? $this->oUpstream->id : 0; |
||
251 | } |
||
252 | public function getLastUpstreamId() { |
||
253 | return @$this->iLastUpstreamId ? @$this->iLastUpstreamId : 0; |
||
254 | } |
||
255 | public function getUpstreamFinder() { |
||
256 | return @$this->oUpstream->account; |
||
257 | } |
||
258 | public function getUpstreamWorker() { |
||
259 | return @$this->oUpstream->worker; |
||
260 | } |
||
261 | public function getUpstreamShareId() { |
||
262 | return @$this->oUpstream->id; |
||
263 | } |
||
264 | /** |
||
265 | * Find upstream accepted share that should be valid for a specific block |
||
266 | * Assumptions: |
||
267 | * * Shares are matching blocks in ASC order |
||
268 | * * We can skip all upstream shares of previously found ones used in a block |
||
269 | * @param last int Skips all shares up to last to find new share |
||
270 | * @return bool |
||
271 | **/ |
||
272 | public function findUpstreamShare($aBlock, $last=0) { |
||
273 | // Many use stratum, so we create our stratum check first |
||
274 | $version = pack("I*", sprintf('%08d', $aBlock['version'])); |
||
275 | $previousblockhash = pack("H*", swapEndian($aBlock['previousblockhash'])); |
||
276 | $merkleroot = pack("H*", swapEndian($aBlock['merkleroot']) ); |
||
277 | $time = pack("I*", $aBlock['time']); |
||
278 | $bits = pack("H*", swapEndian($aBlock['bits'])); |
||
279 | $nonce = pack("I*", $aBlock['nonce']); |
||
280 | $header_bin = $version . $previousblockhash . $merkleroot . $time . $bits . $nonce; |
||
281 | $header_hex = implode(unpack("H*", $header_bin)); |
||
282 | |||
283 | // Stratum supported blockhash solution entry |
||
284 | $stmt = $this->mysqli->prepare("SELECT SUBSTRING_INDEX( `username` , '.', 1 ) AS account, username as worker, id FROM $this->table WHERE solution = ? LIMIT 1"); |
||
285 | View Code Duplication | if ($this->checkStmt($stmt) && $stmt->bind_param('s', $aBlock['hash']) && $stmt->execute() && $result = $stmt->get_result()) { |
|
286 | $this->oUpstream = $result->fetch_object(); |
||
287 | $this->share_type = 'stratum_blockhash'; |
||
288 | if (!empty($this->oUpstream->account) && !empty($this->oUpstream->worker) && is_int($this->oUpstream->id)) |
||
289 | return true; |
||
290 | } |
||
291 | |||
292 | // Stratum scrypt hash check |
||
293 | $scrypt_hash = swapEndian(bin2hex(Scrypt::calc($header_bin, $header_bin, 1024, 1, 1, 32))); |
||
294 | $stmt = $this->mysqli->prepare("SELECT SUBSTRING_INDEX( `username` , '.', 1 ) AS account, username as worker, id FROM $this->table WHERE solution = ? LIMIT 1"); |
||
295 | View Code Duplication | if ($this->checkStmt($stmt) && $stmt->bind_param('s', $scrypt_hash) && $stmt->execute() && $result = $stmt->get_result()) { |
|
296 | $this->oUpstream = $result->fetch_object(); |
||
297 | $this->share_type = 'stratum_solution'; |
||
298 | if (!empty($this->oUpstream->account) && !empty($this->oUpstream->worker) && is_int($this->oUpstream->id)) |
||
299 | return true; |
||
300 | } |
||
301 | |||
302 | // Failed to fetch via startum solution, try pushpoold |
||
303 | // Fallback to pushpoold solution type |
||
304 | $ppheader = sprintf('%08d', $aBlock['version']) . word_reverse($aBlock['previousblockhash']) . word_reverse($aBlock['merkleroot']) . dechex($aBlock['time']) . $aBlock['bits'] . dechex($aBlock['nonce']); |
||
305 | $stmt = $this->mysqli->prepare("SELECT SUBSTRING_INDEX( `username` , '.', 1 ) AS account, username as worker, id FROM $this->table WHERE solution LIKE CONCAT(?, '%') LIMIT 1"); |
||
306 | View Code Duplication | if ($this->checkStmt($stmt) && $stmt->bind_param('s', $ppheader) && $stmt->execute() && $result = $stmt->get_result()) { |
|
307 | $this->oUpstream = $result->fetch_object(); |
||
308 | $this->share_type = 'pp_solution'; |
||
309 | if (!empty($this->oUpstream->account) && !empty($this->oUpstream->worker) && is_int($this->oUpstream->id)) |
||
310 | return true; |
||
311 | } |
||
312 | |||
313 | // Still no match, try upstream result with timerange |
||
314 | $stmt = $this->mysqli->prepare(" |
||
315 | SELECT |
||
316 | SUBSTRING_INDEX( `username` , '.', 1 ) AS account, username as worker, id |
||
317 | FROM $this->table |
||
318 | WHERE upstream_result = 'Y' |
||
319 | AND id > ? |
||
320 | AND UNIX_TIMESTAMP(time) >= ? |
||
321 | AND UNIX_TIMESTAMP(time) <= ( ? + 60 ) |
||
322 | ORDER BY id ASC LIMIT 1"); |
||
323 | View Code Duplication | if ($this->checkStmt($stmt) && $stmt->bind_param('iii', $last, $aBlock['time'], $aBlock['time']) && $stmt->execute() && $result = $stmt->get_result()) { |
|
324 | $this->oUpstream = $result->fetch_object(); |
||
325 | $this->share_type = 'upstream_share'; |
||
326 | if (!empty($this->oUpstream->account) && !empty($this->oUpstream->worker) && is_int($this->oUpstream->id)) |
||
327 | return true; |
||
328 | } |
||
329 | |||
330 | // We failed again, now we take ANY result matching the timestamp |
||
331 | $stmt = $this->mysqli->prepare(" |
||
332 | SELECT |
||
333 | SUBSTRING_INDEX( `username` , '.', 1 ) AS account, username as worker, id |
||
334 | FROM $this->table |
||
335 | WHERE our_result = 'Y' |
||
336 | AND id > ? |
||
337 | AND UNIX_TIMESTAMP(time) >= ? |
||
338 | ORDER BY id ASC LIMIT 1"); |
||
339 | View Code Duplication | if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $last, $aBlock['time']) && $stmt->execute() && $result = $stmt->get_result()) { |
|
340 | $this->oUpstream = $result->fetch_object(); |
||
341 | $this->share_type = 'any_share'; |
||
342 | if (!empty($this->oUpstream->account) && !empty($this->oUpstream->worker) && is_int($this->oUpstream->id)) |
||
343 | return true; |
||
344 | } |
||
345 | $this->setErrorMessage($this->getErrorMsg('E0052', $aBlock['height'])); |
||
346 | return false; |
||
347 | } |
||
348 | |||
349 | /** |
||
350 | * Fetch the lowest needed share ID from shares |
||
351 | **/ |
||
352 | View Code Duplication | function getMinimumShareId($iCount, $current_upstream) { |
|
353 | $stmt = $this->mysqli->prepare(" |
||
354 | SELECT MIN(b.id) AS id FROM |
||
355 | ( |
||
356 | SELECT id, @total := @total + IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty) AS total |
||
357 | FROM $this->table, (SELECT @total := 0) AS a |
||
358 | WHERE our_result = 'Y' |
||
359 | AND id <= ? AND @total < ? |
||
360 | ORDER BY id DESC |
||
361 | ) AS b |
||
362 | WHERE total <= ?"); |
||
363 | if ($this->checkStmt($stmt) && $stmt->bind_param('iii', $current_upstream, $iCount, $iCount) && $stmt->execute() && $result = $stmt->get_result()) |
||
364 | return $result->fetch_object()->id; |
||
365 | return $this->sqlError(); |
||
366 | } |
||
367 | |||
368 | /** |
||
369 | * Fetch the lowest needed share ID from archive |
||
370 | **/ |
||
371 | View Code Duplication | function getMinArchiveShareId($iCount) { |
|
372 | $stmt = $this->mysqli->prepare(" |
||
373 | SELECT MIN(b.share_id) AS share_id FROM |
||
374 | ( |
||
375 | SELECT share_id, @total := @total + IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty) AS total |
||
376 | FROM $this->tableArchive, (SELECT @total := 0) AS a |
||
377 | WHERE our_result = 'Y' |
||
378 | AND @total < ? |
||
379 | ORDER BY share_id DESC |
||
380 | ) AS b |
||
381 | WHERE total <= ? |
||
382 | "); |
||
383 | if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $iCount, $iCount) && $stmt->execute() && $result = $stmt->get_result()) |
||
384 | return $result->fetch_object()->share_id; |
||
385 | return $this->sqlError(); |
||
386 | } |
||
387 | } |
||
388 | |||
389 | $share = new Share(); |
||
390 | $share->setDebug($debug); |
||
391 | $share->setMysql($mysqli); |
||
392 | $share->setConfig($config); |
||
393 | $share->setUser($user); |
||
394 | $share->setBlock($block); |
||
395 | $share->setErrorCodes($aErrorCodes); |
||
396 |
When comparing two booleans, it is generally considered safer to use the strict comparison operator.