Issues (1020)

Security Analysis    no vulnerabilities found

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

models/Player.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * @property integer $uid
4
 * @property string $user
5
 * @property string $registered
6
 * @property integer $level
7
 * @property integer $status_points
8
 * @property integer $energy
9
 * @property integer $energy_max
10
 * @property integer $energy_missing
11
 * @property integer $energyRequiredForDuel
12
 * @property integer $skill
13
 * @property integer $strength
14
 * @property integer $dollar
15
 * @property integer $gold
16
 * @property integer $xp_all
17
 * @property integer $xp_delta
18
 * @property integer $xp_remaining
19
 * @property integer $last_location
20
 * @property integer $owned_items
21
 * @property integer $owned_baits
22
 * @property string $found_setitem_time
23
 * @property integer $found_setitem_xp
24
 * @property integer $tutorial_mission
25
 * @property integer $in_club
26
 * @property integer $level_percent
27
 * @property integer $refillPerInterval
28
 * @property integer $energyRefillPerInterval
29
 * @property integer $remainingTimeToRefill
30
 * @property integer $justAdvanced
31
 * @property integer $freeSlots
32
 * @property boolean $black_market
33
 * @property integer $skill_extended
34
 * @property string $clubName
35
 */
36
class Player extends CModel implements ISubject
37
{
38
    const ENERGY_REFILL_INTERVAL = 300; //5min
39
40
    private $uid;
41
    private $user;
42
    private $registered;
43
    private $xp_all;
44
    private $xp_delta;
45
    private $xp_recommended;
46
    private $level;
47
    private $status_points;
48
    private $energy_max;
49
    private $energy_incr_at;
50
    private $energy;
51
    private $skill;
52
    private $skill_extended;
53
    private $strength;
54
    private $dollar;
55
    private $gold;
56
    private $last_location;
57
    private $owned_items;
58
    private $owned_baits;
59
    private $found_setitem_time;
60
    private $found_setitem_xp;
61
    private $duel_points;
62
    private $tutorial_mission;
63
    private $in_club;
64
    private $black_market;
65
66
    private $justAdvanced;
67
68
    public function attributeNames()
69
    {
70
        return [];
71
    }
72
73
    public function getUid()
74
    {
75
        return (int)$this->uid;
76
    }
77
78
    public function getUser()
79
    {
80
        return $this->user;
81
    }
82
83
    public function getRegistered()
84
    {
85
        return $this->registered;
86
    }
87
88
    public function getLevel()
89
    {
90
        return (int)$this->level;
91
    }
92
93
    public function getStatus_points()
94
    {
95
        return $this->itsMe() ? (int)$this->status_points : 0;
96
    }
97
98
    public function getEnergy()
99
    {
100
        return (int)$this->energy;
101
    }
102
103
    public function getEnergy_max()
104
    {
105
        return (int)$this->energy_max;
106
    }
107
108
    public function getEnergy_missing()
109
    {
110
        return $this->energy_max - $this->energy;
111
    }
112
113
    public function getEnergyRequiredForDuel()
114
    {
115
        return round($this->energy_max / 10);
116
    }
117
118
    public function getSkill()
119
    {
120
        return (int)$this->skill;
121
    }
122
123
    public function getStrength()
124
    {
125
        return (int)$this->strength;
126
    }
127
128
    public function getDollar()
129
    {
130
        return (int)$this->dollar;
131
    }
132
133
    public function getGold()
134
    {
135
        return (int)$this->gold;
136
    }
137
138
    public function getXp_all()
139
    {
140
        return (int)$this->xp_all;
141
    }
142
143
    public function getXp_delta()
144
    {
145
        return (int)$this->xp_delta;
146
    }
147
148
    public function getXp_remaining()
149
    {
150
        return (int)$this->xp_recommended - (int)$this->xp_delta;
151
    }
152
153
    public function getLast_location()
154
    {
155
        return (int)$this->last_location;
156
    }
157
158
    public function getOwned_items()
159
    {
160
        return (int)$this->owned_items;
161
    }
162
163
    public function getOwned_baits()
164
    {
165
        return (int)$this->owned_baits;
166
    }
167
168
    public function getFound_setitem_time()
169
    {
170
        return $this->found_setitem_time > $this->registered ? $this->found_setitem_time : $this->registered;
171
    }
172
173
    public function getFound_setitem_xp()
174
    {
175
        return (int)$this->found_setitem_xp;
176
    }
177
178
    public function getTutorial_mission()
179
    {
180
        return (int)$this->tutorial_mission;
181
    }
182
183
    public function getIn_club()
184
    {
185
        return (int)$this->in_club;
186
    }
187
188
    public function getLevel_percent()
189
    {
190
        if (!$this->xp_recommended) {
191
            return 0;
192
        }
193
        $percent = (int)$this->xp_delta / ((int)$this->xp_recommended / 100);
194
195
        if ($percent < 0) {
196
            $percent = 0;
197
        }
198
        if ($percent > 100) {
199
            $percent = 100;
200
        }
201
        return $percent;
202
    }
203
204
    public function getRefillPerInterval()
205
    {
206
        return round($this->energy_max / 10);
207
    }
208
209
    public function getEnergyRefillInterval()
210
    {
211
        return self::ENERGY_REFILL_INTERVAL;
212
    }
213
214
    public function getRemainingTimeToRefill()
215
    {
216
        $last = strtotime($this->energy_incr_at);
217
        if ($last < 0) {
218
            $last = 0;
219
        }
220
221
        $remaining = self::ENERGY_REFILL_INTERVAL - (time() - $last);
222
        if ($remaining < 0) {
223
            $remaining = 0;
224
        }
225
226
        return $remaining;
227
    }
228
229
    public function getJustAdvanced()
230
    {
231
        return (int)$this->justAdvanced;
232
    }
233
234
    public function getFreeSlots()
235
    {
236
        return $this->strength - ($this->owned_items + $this->owned_baits);
237
    }
238
239
    public function getBlack_market()
240
    {
241
        return (bool)(strtotime($this->black_market) >= time());
242
    }
243
244
    public function itsMe()
245
    {
246
        return $this->uid == @$_SESSION['uid'];
247
    }
248
249
    public function getSkill_extended()
250
    {
251
        return $this->skill_extended>0 ? $this->skill_extended : 1;
252
    }
253
254
    public function getClubName()
255
    {
256
        if (!$this->in_club) {
257
            return false;
258
        }
259
260
        $club = new Club;
261
        $club->id = $this->in_club;
262
        $club->fetchName();
263
        return $club->name;
264
    }
265
266
    public function setSubjectId($id)
267
    {
268
        $this->uid = (int)$id;
269
    }
270
271
    public function setOwned_baits($baits)
272
    {
273
        $this->owned_baits = (int)$baits;
274
    }
275
276
    public function setOwned_items($items)
277
    {
278
        $this->owned_items = (int)$items;
279
    }
280
281
    public function activateDuelShield()
282
    {
283
        Yii::trace($this->uid . ': activate duelShield.');
284
        $this->energy = 0;
285
    }
286
287
    public function fetchUser()
288
    {
289
        $user = Yii::app()->db->cache(86400)->createCommand()
290
            ->select('user')
291
            ->from('main')
292
            ->where('uid=:uid', [':uid'=>$this->uid])
293
            ->queryScalar();
294
        if (!$user) {
295
            $user = '???';
296
        }
297
        $this->user = $user;
298
    }
299
300 View Code Duplication
    public function getSubjectName()
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.

Loading history...
301
    {
302
        $name = Yii::app()->db->cache(86400)->createCommand()
303
            ->select('user')
304
            ->from('main')
305
            ->where('uid=:uid', [':uid'=>$this->uid])
306
            ->queryScalar();
307
        if (!$name) {
308
            $name = '???';
309
        }
310
        return $name;
311
    }
312
313
    public function setAllAttributes($uid = 0)
314
    {
315
        $this->setSubjectId( $uid ? $uid : @$_SESSION['uid'] );
316
317
        if (!$this->uid) {
318
            return false;
319
        }
320
321
        //read all from db
322
        $res = Yii::app()->db->createCommand()
323
            ->select('*')
324
            ->from('main')
325
            ->where('uid=:uid', [':uid'=>$this->uid])
326
            ->queryRow();
327
328
        if (!is_array($res)) {
329
            $this->uid = 0;
330
            return false;
331
        }
332
333
        foreach ($res as $k => $v) {
334
            $this->$k = $v;
335
        }
336
    }
337
338
    public function rest()
339
    {
340
        $refillable = $this->energy_max - $this->energy;
341
        if (!$refillable) {
342
            return false; //don't need to rest
343
        }
344
345
        $now = time();
346
        $last = strtotime($this->energy_incr_at);
347
        if ($last<0) {
348
            $last = 0;
349
        }
350
351
        $interval = $now - $last;
352
        if ($interval < self::ENERGY_REFILL_INTERVAL) {
353
            return false;
354
        }
355
356
        $refillMultiplier = floor($interval / self::ENERGY_REFILL_INTERVAL); //incement energy every 5 minutes
357
358
        $refillSum = $refillMultiplier * $this->refillPerInterval;
359
        if ($refillSum > $refillable) {
360
            $refillSum = $refillable;
361
        }
362
363
        if ($refillSum < 1) {
364
            return false; //don't need to rest
365
        }
366
367
        $this->energy += $refillSum;
368
369
        $remain = 0;
370
        if ($interval <= self::ENERGY_REFILL_INTERVAL * 5) {
371
            $remain = $interval - ($refillMultiplier * self::ENERGY_REFILL_INTERVAL);
372
        }
373
374
        $this->energy_incr_at = date("Y-m-d H:i:s", $now-$remain);
375
376
        Yii::app()->db->createCommand()
377
            ->update('main', ['energy'=>$this->energy, 'energy_incr_at'=>$this->energy_incr_at], 'uid=:uid', [':uid'=>(int)$this->uid]);
378
    }
379
380
    public function updateAttributes($toIncrement, $toDecrement)
381
    {
382
        $this->logEnergyUsage($toDecrement);
383
        $attributes = [];
384
385
        $toIncrement = $this->incrementLevel($toIncrement);
386
387
        foreach ($toIncrement as $k => $v) {
388
            $newValue = $this->$k + $v;
389
            $attributes[$k] = $newValue;
390
            $this->$k = $newValue;
391
392
            if ($k=='dollar') {
393
                (new ProfileBadgeActivator())->triggerDollar($this->uid, $newValue);
394
            }
395
        }
396
397
        //level advance, reset energy
398
        if (isset($attributes['level'])) {
399
            unset($toDecrement['energy']);
400
            Yii::app()->gameLogger->log(['type'=>'level_up']);
401
        }
402
403
        foreach ($toDecrement as $k => $v) {
404
            if ($v > $this->$k) {
405
                $v = $this->$k;
406
            }
407
408
            $newValue = $this->$k - $v;
409
            $attributes[$k] = $newValue;
410
            $this->$k = $newValue;
411
        }
412
413
414
        if (!empty($attributes)) {
415
            Yii::app()->db->createCommand()
416
            ->update('main', $attributes, 'uid=:uid', [':uid'=>(int)$this->uid]);
417
        }
418
    }
419
420
    protected function logEnergyUsage($attributes)
421
    {
422
        if (!isset($attributes['energy'])) {
423
            return false;
424
        }
425
426
        //todo: implement redis log
427
        $used = $attributes['energy'];
428
        $percent = round($used / ($this->energy_max / 100), 2) * 100;
429
430
        $redis = Yii::app()->redis->getClient();
431
        $key = 'counter:activity:' . date('Ymd');
432
        $redis->hIncrBy($key, $this->uid, $percent);
433
    }
434
435
    public function rewriteAttributes($attributes)
436
    {
437
        foreach ($attributes as $k => $v) {
438
            $this->$k = $v;
439
        }
440
441
        Yii::app()->db->createCommand()
442
            ->update('main', $attributes, 'uid=:uid', [':uid'=>(int)$this->uid]);
443
    }
444
445
    private function incrementLevel($incr)
446
    {
447
        if (!isset($incr['xp_delta']) || $incr['xp_delta'] < 1) {
448
            return $incr; //do not touch level
449
        }
450
451
        $remaining = $this->getXp_remaining();
452
        if ($incr['xp_delta'] < $remaining) {
453
            return $incr; //don't advance to next level
454
        }
455
456
        //advance
457
        $incr['level'] = 1;
458
        $this->xp_delta = $incr['xp_delta'] - $remaining; //set delta
459
        $incr['xp_delta'] = 0; //do not increase further
460
        $incr['xp_recommended'] = $this->nextXpRecommended();
461
        $incr['status_points'] = 4;
462
463
        $this->energy = $this->energy_max;
464
        $incr['energy'] = 0;
465
466
        $this->justAdvanced = true;
467
468
        (new ProfileBadgeActivator())->triggerLevel($this->uid, $this->level+1);
469
        return $incr;
470
    }
471
472
    private function nextXpRecommended()
473
    {
474
        $recommendations = [
475
            //fromLevel => recommended xp gain to the NEXT level
476
            1 => 3,
477
            5 => 5,
478
            10 => 10,
479
            20 => 15,
480
            30 => 20,
481
            40 => 30,
482
            50 => 10,
483
            80 => 15,
484
            90 => 20,
485
            100 => 20,
486
            120 => 35,
487
            140 => 40,
488
            160 => 30,
489
            180 => 45,
490
            200 => 50,
491
            ];
492
        $search = $this->level+1;
493
        for ($i=$search; $i>0; $i--) {
494
            if (isset($recommendations[$i])) {
495
                return $recommendations[$i];
496
            }
497
        }
498
        return 0;
499
    }
500
}
501