Issues (273)

Security Analysis    not enabled

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/Server.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
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 15 and the first side effect is on line 9.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/**
3
 * This file contains functionality relating to the official BZFlag match servers for the league
4
 *
5
 * @package    BZiON\Models
6
 * @license    https://github.com/allejo/bzion/blob/master/LICENSE.md GNU General Public License Version 3
7
 */
8
9
include_once DOC_ROOT . "/includes/bzfquery.php";
10
11
/**
12
 * A BZFlag server
13
 * @package    BZiON\Models
14
 */
15
class Server extends UrlModel implements NamedModel
16
{
17
    /**
18
     * The name of the server
19
     * @var string
20
     */
21
    protected $name;
22
23
    /**
24
     * The domain of the server
25
     * @var string
26
     */
27
    protected $domain;
28
29
    /**
30
     * The port of the server
31
     * @var int
32
     */
33
    protected $port;
34
35
    /**
36
     * The id of the country the server is located in
37
     * @var int
38
     */
39
    protected $country;
40
41
    /**
42
     * The id of the owner of the server
43
     * @var int
44
     */
45
    protected $owner;
46
47
    /**
48
     * Whether the server is listed on the public list server
49
     * @var bool
50
     */
51
    protected $online;
52
53
    /**
54
     * The server's bzfquery information
55
     * @var array
56
     */
57
    protected $info;
58
59
    /**
60
     * The ID of the API key assigned to this server
61
     * @var ApiKey
62
     */
63
    protected $api_key;
64
65
    /**
66
     * The date of the last bzfquery of the server
67
     * @var TimeDate
68
     */
69
    protected $updated;
70
71
    /**
72
     * The name of the database table used for queries
73
     */
74
    const TABLE = "servers";
75
76
    const CREATE_PERMISSION = Permission::ADD_SERVER;
77
    const EDIT_PERMISSION = Permission::EDIT_SERVER;
78
    const SOFT_DELETE_PERMISSION = Permission::SOFT_DELETE_SERVER;
79
    const HARD_DELETE_PERMISSION = Permission::HARD_DELETE_SERVER;
80
81
    /**
82
     * {@inheritdoc}
83
     */
84
    protected function assignResult($server)
85
    {
86
        $this->name = $server['name'];
87
        $this->domain = $server['domain'];
88
        $this->port = $server['port'];
89
        $this->country = $server['country'];
90
        $this->owner = $server['owner'];
91
        $this->online = $server['online'];
92
        $this->info = unserialize($server['info']);
93
        $this->api_key = ApiKey::get($server['api_key']);
94
        $this->updated = TimeDate::fromMysql($server['updated']);
95
        $this->status = $server['status'];
96
    }
97
98
    /**
99
     * Add a new server
100
     *
101
     * @param string $name    The name of the server
102
     * @param string $domain  The domain of the server (e.g. server.com)
103
     * @param string $port    The port of the server (e.g. 5154)
104
     * @param int    $country The ID of the country
105
     * @param int    $owner   The ID of the server owner
106
     *
107
     * @return Server An object that represents the sent message
108
     */
109
    public static function addServer($name, $domain, $port, $country, $owner)
110
    {
111
        $key = ApiKey::getKeyByOwner($owner);
112
113
        $server = self::create(array(
114
            'name'    => $name,
115
            'domain'  => $domain,
116
            'port'    => $port,
117
            'country' => $country,
118
            'owner'   => $owner,
119
            'api_key' => $key->getId(),
120
            'status'  => 'active',
121
        ), 'updated');
122
        $server->forceUpdate();
123
124
        return $server;
125
    }
126
127
    /**
128
     * Update the server with current bzfquery information
129
     * return self
130
     */
131
    public function forceUpdate()
132
    {
133
        $this->info = bzfquery($this->getAddress());
134
        $this->updated = TimeDate::now();
135
        $this->online = !isset($this->info['error']);
136
137
        $this->db->execute(
138
        "UPDATE servers SET info = ?, online = ?, updated = UTC_TIMESTAMP() WHERE id = ?",
139
        array(serialize($this->info), $this->online, $this->id)
140
    );
141
142
    // If a server is offline, log it
143
        if (!$this->online) {
144
            if ($logger = \Service::getContainer()->get('logger')) {
145
                $id = $this->getId();
146
                $address = $this->getAddress();
147
                $reason = $this->info['error'];
148
149
                $logger->notice("Connection to server #$id ($address) failed: $reason");
150
            }
151
        }
152
153
        return $this;
154
    }
155
156
    /**
157
     * Checks if the server is online (listed on the public list server)
158
     * @return bool Whether the server is online
159
     */
160
    public function isOnline()
161
    {
162
        return $this->online;
163
    }
164
165
    /**
166
     * Checks if the server has players
167
     * @return bool Whether the server has any players
168
     */
169
    public function hasPlayers()
170
    {
171
        return $this->info['numPlayers'] > 0;
172
    }
173
174
    /**
175
     * Gets the number of players on the server
176
     * @return int The number of players
177
     */
178
    public function numPlayers()
179
    {
180
        return (isset($this->info['numPlayers'])) ? $this->info['numPlayers'] : 0;
181
    }
182
183
    /**
184
     * Gets the players on the server
185
     * @return array The players on the server
186
     */
187
    public function getPlayers()
188
    {
189
        if (isset($this->info['player'])) {
190
            return $this->info['player'];
191
        }
192
193
        return array();
194
    }
195
196
    /**
197
     * Checks if the last update is older than or equal to the update interval
198
     * @return bool Whether the information is older than the update interval
199
     */
200
    public function staleInfo()
201
    {
202
        $update_time = $this->updated->copy();
203
        $update_time->modify(Service::getParameter('bzion.miscellaneous.update_interval'));
204
205
        return TimeDate::now() >= $update_time;
206
    }
207
208
    /**
209
     * The ApiKey assigned to this server
210
     *
211
     * @return \CachedModel|int|null|static
212
     */
213
    public function getApiKey()
214
    {
215
        return $this->api_key;
216
    }
217
218
    /**
219
     * Gets the server's ip address
220
     * @return string The server's ip address
221
     */
222
    public function getServerIp()
223
    {
224
        return $this->info['ip'];
225
    }
226
227
    /**
228
     * Get the server's name
229
     * @return string
230
     */
231
    public function getName()
232
    {
233
        return $this->name;
234
    }
235
236
    /**
237
     * Get the domain of the server
238
     *
239
     * @return string The server's domain
240
     */
241
    public function getDomain()
242
    {
243
        return $this->domain;
244
    }
245
246
    /**
247
     * Get the port of the server
248
     *
249
     * @return int The port number
250
     */
251
    public function getPort()
252
    {
253
        return $this->port;
254
    }
255
256
    /**
257
     * Get the server's IP address or hostname
258
     * @return string
259
     */
260
    public function getAddress()
261
    {
262
        return $this->domain . ":" . $this->port;
263
    }
264
265
    /**
266
     * Get when the server information was last updated
267
     * @return TimeDate
268
     */
269
    public function getUpdated()
270
    {
271
        return $this->updated->copy();
272
    }
273
274
    /**
275
     * Get the country the server is in
276
     * @return Country The country the server is located in
277
     */
278
    public function getCountry()
279
    {
280
        return Country::get($this->country);
281
    }
282
283
    /**
284
     * Get the owner of the server
285
     * @return Player
286
     */
287
    public function getOwner()
288
    {
289
        return Player::get($this->owner);
290
    }
291
292
    /**
293
     * Get the number of matches that have occurred on this server
294
     *
295
     * @return int
296
     */
297
    public function getMatchCount()
298
    {
299
        $qb = new MatchQueryBuilder('Match', [
300
            'columns' => [
301
                'server' => 'server_id'
302
            ]
303
        ]);
304
        $query = $qb
305
            ->where('server')->equals($this->getId())
306
            ->active()
307
            ->count()
308
        ;
309
310
        return $query;
311
    }
312
313
    /**
314
     * Returns the amount of time passed since the server was last updated
315
     * @return TimeDate
316
     */
317
    public function getLastUpdate()
318
    {
319
        return $this->updated;
320
    }
321
322
    /**
323
     * Set the name of the server
324
     *
325
     * @param string $name The new name of the server
326
     *
327
     * @return self
328
     */
329
    public function setName($name)
330
    {
331
        return $this->updateProperty($this->name, 'name', $name);
332
    }
333
334
    /**
335
     * Set the address of the server
336
     *
337
     * @param string $address The new address of the server
338
     *
339
     * @deprecated Use setDomain() and setPort() instead
340
     *
341
     * @return self
342
     */
343
    public function setAddress($address)
344
    {
345
        list($domain, $port) = explode(":", $address);
346
347
        $this->setDomain($domain);
348
        $this->setPort($port);
349
350
        return $this;
351
    }
352
353
    /**
354
     * Set the domain of the server
355
     *
356
     * @param $domain string The new domain of the server
357
     *
358
     * @return self
359
     */
360
    public function setDomain($domain)
361
    {
362
        return $this->updateProperty($this->domain, 'domain', $domain);
363
    }
364
365
    /**
366
     * Set the port of the server
367
     *
368
     * @param $port int The new port of the server
369
     *
370
     * @return self
371
     */
372
    public function setPort($port)
373
    {
374
        return $this->updateProperty($this->port, 'port', $port);
375
    }
376
377
    /**
378
     * Set the id of the owner of the server
379
     *
380
     * @param int $ownerId The ID of the new owner of the server
381
     *
382
     * @return self
383
     */
384
    public function setOwner($ownerId)
385
    {
386
        return $this->updateProperty($this->owner, 'owner', $ownerId);
387
    }
388
389
    /**
390
     * Set the id of the country of the server
391
     *
392
     * @param int $countryId The ID of the new country of the server
393
     *
394
     * @return self
395
     */
396
    public function setCountry($countryId)
397
    {
398
        return $this->updateProperty($this->country, 'country', $countryId);
399
    }
400
401
    /**
402
     * Get all the servers in the database that have an active status
403
     * @return Server[] An array of server objects
404
     */
405
    public static function getServers()
406
    {
407
        return self::arrayIdToModel(self::fetchIdsFrom("status", array("active"), false, "ORDER BY name"));
408
    }
409
410
    /**
411
     * Get a query builder for servers
412
     * @return QueryBuilder
413
     */
414
    public static function getQueryBuilder()
415
    {
416
        return new QueryBuilder('Server', array(
417
            'columns' => array(
418
                'name'   => 'name',
419
                'domain' => 'domain',
420
                'port'   => 'port',
421
                'status' => 'status',
422
            ),
423
            'name' => 'name'
424
        ));
425
    }
426
427
    /**
428
     * Get the Server model with the respective address
429
     *
430
     * @param  string $address The address in the format of `domain:port`
431
     *
432
     * @return static
433
     */
434
    public static function fetchFromAddress($address)
435
    {
436
        if (strpos($address, ':') === false) {
437
            return Server::get(0);
438
        }
439
440
        list($domain, $port) = explode(':', $address);
441
442
        $qb = self::getQueryBuilder();
443
        $query = $qb
444
            ->where('domain')->equals($domain)
445
            ->where('port')->equals($port)
446
            ->active()
447
            ->getModels($fast = true)
448
        ;
449
450
        if (count($query) > 0) {
451
            return $query[0];
452
        }
453
454
        return Server::get(0);
455
    }
456
}
457