Issues (23)

Security Analysis    no request data  

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.

src/Http/Uri.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
 * Veto.
4
 * PHP Microframework.
5
 *
6
 * @author Damien Walsh <[email protected]>
7
 * @copyright Damien Walsh 2013-2014
8
 * @version 0.1
9
 * @package veto
10
 */
11
namespace Veto\Http;
12
13
use Psr\Http\Message\UriInterface;
14
use Veto\Collection\Bag;
15
16
/**
17
 * HTTP URI Value Type
18
 *
19
 * Substantially based on Slim Framework's URI implementation.
20
 *
21
 * @link https://github.com/slimphp/Slim/
22
 */
23
class Uri implements UriInterface
24
{
25
    /**
26
     * The URI scheme (without "://" suffix)
27
     *
28
     * @var string
29
     */
30
    protected $scheme = '';
31
32
    /**
33
     * The user info encoded in the url (for URLS like http://user@password:example.com
34
     *
35
     * @var string Either empty or encoded in form username[:password]
36
     */
37
    protected $userInfo = '';
38
39
    /**
40
     * The URI host
41
     *
42
     * @var string
43
     */
44
    protected $host = '';
45
46
    /**
47
     * The URI port number
48
     *
49
     * @var int
50
     */
51
    protected $port;
52
53
    /**
54
     * The URI path
55
     *
56
     * @var string
57
     */
58
    protected $path = '';
59
60
    /**
61
     * The URI query string (without "?" prefix)
62
     *
63
     * @var string
64
     */
65
    protected $query = '';
66
67
    /**
68
     * The URI fragment string (without "#" prefix)
69
     *
70
     * @var string
71
     */
72
    protected $fragment = '';
73
74
    /**
75
     * Create a new URI
76
     *
77
     * @param string $scheme URI scheme
78
     * @param string $host URI host
79
     * @param int|null $port URI port number
80
     * @param string $path URI path
81
     * @param string $query URI query string
82
     * @param string $fragment
83
     * @param string $userInfo (optional) username & password encoded in URI
84
     */
85
    public function __construct($scheme, $host, $port = null, $path = '/', $query = '', $fragment = '', $userInfo = '')
86
    {
87
        $this->scheme = $scheme;
88
        $this->host = $host;
89
        $this->path = empty($path) ? '/' : $path;
90
        $this->query = $query;
91
        $this->fragment = $fragment;
92
        $this->userInfo = $userInfo;
93
94
        // Default ports SHOULD be null
95
        $this->port = $port;
96
        if ($this->isStandardPort($port, $scheme)) {
97
            $this->port = null;
98
        }
99
    }
100
101
    /**
102
     * Create new Uri from string
103
     *
104
     * Substantially based on Slim Framework's URI implementation.
105
     *
106
     * @param  string $uri Complete Uri string (i.e., https://user:pass@host:443/path?query)
107
     * @link https://github.com/slimphp/Slim/
108
     * @throws \InvalidArgumentException
109
     * @return self
110
     */
111
    public static function createFromString($uri)
112
    {
113
        // Check for valid argument type
114
        if (!is_string($uri) && !method_exists($uri, '__toString')) {
115
            throw new \InvalidArgumentException(
116
                '\Veto\Http\Uri::createFromString() argument must be a string'
117
            );
118
        }
119
120
        // Normalize URL before validation as filter_var requires this for a valid url
121
        $mungedUri = $uri;
122
        if (!array_key_exists('scheme', parse_url($uri))) {
123
            $mungedUri = 'http://' . $uri;
124
        }
125
126
        $parts = parse_url($mungedUri);
127
128
        // Ensure that the URL is valid
129
        if (!filter_var($mungedUri, FILTER_VALIDATE_URL) || !strlen($parts['host'])) {
130
            throw new \InvalidArgumentException(
131
                'Call to \\' . __METHOD__ . '() with invalid URI "' . $uri . '"'
132
            );
133
        }
134
135
        $scheme = $parts['scheme'];
136
        $user = isset($parts['user']) ? $parts['user'] : '';
137
        $pass = isset($parts['pass']) ? $parts['pass'] : '';
138
        $host = $parts['host'];
139
        $port = isset($parts['port']) ? $parts['port'] : null;
140
        $path = isset($parts['path']) ? $parts['path'] : '';
141
        $query = isset($parts['query']) ? $parts['query'] : '';
142
        $fragment = isset($parts['fragment']) ? $parts['fragment'] : '';
143
        $userInfo = static::buildUserInfo($user, $pass);
144
145
        return new static($scheme, $host, $port, $path, $query, $fragment, $userInfo);
146
    }
147
148
    /**
149
     * Create new URI from the provided environment
150
     *
151
     * Substantially based on Slim Framework's URI implementation.
152
     *
153
     * @param Bag $environment
154
     * @link https://github.com/slimphp/Slim/
155
     * @return self
156
     */
157
    public static function createFromEnvironment(Bag $environment)
158
    {
159
        // Scheme
160
        if ($environment->has('HTTP_X_FORWARDED_PROTO') === true) {
161
            $scheme = $environment->get('HTTP_X_FORWARDED_PROTO');
162
        } else {
163
            $https = $environment->get('HTTPS', '');
164
            $scheme = empty($https) || $https === 'off' ? 'http' : 'https';
165
        }
166
167
        // Authority
168
        $user = $environment->get('PHP_AUTH_USER', '');
169
        $password = $environment->get('PHP_AUTH_PW', '');
170
        $host = $environment->get('HTTP_HOST', $environment->get('SERVER_NAME'));
171
        $port = (int)$environment->get('SERVER_PORT', null);
172
173
        // Path
174
        $requestUri = parse_url($environment->get('REQUEST_URI'), PHP_URL_PATH);
175
        $path = '/' . ltrim($requestUri, '/');
176
177
        // Query string
178
        $queryString = $environment->get('QUERY_STRING', '');
179
180
        // Fragment
181
        $fragment = '';
182
183
        $userInfo = static::buildUserInfo($user, $password);
184
185
        // Build Uri
186
        return new static($scheme, $host, $port, $path, $queryString, $fragment, $userInfo);
187
    }
188
189
    /**
190
     * Build user info string from username/password components.
191
     *
192
     * @param string $username
193
     * @param string $password
194
     * @return string
195
     */
196
    protected static function buildUserInfo($username, $password)
197
    {
198
        $userInfo = '';
199
        if (strlen($username)) {
200
            $userInfo = $username;
201
202
            if (strlen($password)) {
203
                $userInfo .= ':' . $password;
204
            }
205
        }
206
207
        return $userInfo;
208
    }
209
210
    /**
211
     * Retrieve the URI scheme.
212
     *
213
     * Implementations SHOULD restrict values to "http", "https", or an empty
214
     * string but MAY accommodate other schemes if required.
215
     *
216
     * If no scheme is present, this method MUST return an empty string.
217
     *
218
     * The string returned MUST omit the trailing "://" delimiter if present.
219
     *
220
     * @return string The scheme of the URI.
221
     */
222
    public function getScheme()
223
    {
224
        return $this->scheme;
225
    }
226
227
    /**
228
     * Retrieve the authority portion of the URI.
229
     *
230
     * The authority portion of the URI is:
231
     *
232
     * <pre>
233
     * [user-info@]host[:port]
234
     * </pre>
235
     *
236
     * If the port component is not set or is the standard port for the current
237
     * scheme, it SHOULD NOT be included.
238
     *
239
     * This method MUST return an empty string if no authority information is
240
     * present.
241
     *
242
     * @return string Authority portion of the URI, in "[user-info@]host[:port]"
243
     *     format.
244
     */
245
    public function getAuthority()
246
    {
247
        $userInfo = $this->getUserInfo();
248
        $host = $this->getHost();
249
        $port = $this->getPort();
250
        $showPort = !$this->isStandardPort($port, $this->scheme);
251
252
        return ($userInfo ? $userInfo . '@' : '') . $host . ($port && $showPort ? ':' . $port : '');
0 ignored issues
show
Bug Best Practice introduced by
The expression $port of type null|integer is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
253
    }
254
255
    /**
256
     * Retrieve the user information portion of the URI, if present.
257
     *
258
     * If a user is present in the URI, this will return that value;
259
     * additionally, if the password is also present, it will be appended to the
260
     * user value, with a colon (":") separating the values.
261
     *
262
     * Implementations MUST NOT return the "@" suffix when returning this value.
263
     *
264
     * @return string User information portion of the URI, if present, in
265
     *     "username[:password]" format.
266
     */
267
    public function getUserInfo()
268
    {
269
        return $this->userInfo;
270
    }
271
272
    /**
273
     * Retrieve the host segment of the URI.
274
     *
275
     * This method MUST return a string; if no host segment is present, an
276
     * empty string MUST be returned.
277
     *
278
     * @return string Host segment of the URI.
279
     */
280
    public function getHost()
281
    {
282
        return $this->host;
283
    }
284
285
    /**
286
     * Retrieve the port segment of the URI.
287
     *
288
     * If a port is present, and it is non-standard for the current scheme,
289
     * this method MUST return it as an integer. If the port is the standard port
290
     * used with the current scheme, this method SHOULD return null.
291
     *
292
     * If no port is present, and no scheme is present, this method MUST return
293
     * a null value.
294
     *
295
     * If no port is present, but a scheme is present, this method MAY return
296
     * the standard port for that scheme, but SHOULD return null.
297
     *
298
     * @return null|int The port for the URI.
299
     */
300
    public function getPort()
301
    {
302
        return $this->port;
303
    }
304
305
    /**
306
     * Retrieve the path segment of the URI.
307
     *
308
     * This method MUST return a string; if no path is present it MUST return
309
     * the string "/".
310
     *
311
     * @return string The path segment of the URI.
312
     */
313
    public function getPath()
314
    {
315
        return $this->path;
316
    }
317
318
    /**
319
     * Retrieve the query string of the URI.
320
     *
321
     * This method MUST return a string; if no query string is present, it MUST
322
     * return an empty string.
323
     *
324
     * The string returned MUST omit the leading "?" character.
325
     *
326
     * @return string The URI query string.
327
     */
328
    public function getQuery()
329
    {
330
        return $this->query;
331
    }
332
333
    /**
334
     * Retrieve the fragment segment of the URI.
335
     *
336
     * This method MUST return a string; if no fragment is present, it MUST
337
     * return an empty string.
338
     *
339
     * The string returned MUST omit the leading "#" character.
340
     *
341
     * @return string The URI fragment.
342
     */
343
    public function getFragment()
344
    {
345
        return $this->fragment;
346
    }
347
348
    /**
349
     * Create a new instance with the specified scheme.
350
     *
351
     * This method MUST retain the state of the current instance, and return
352
     * a new instance that contains the specified scheme. If the scheme
353
     * provided includes the "://" delimiter, it MUST be removed.
354
     *
355
     * Implementations SHOULD restrict values to "http", "https", or an empty
356
     * string but MAY accommodate other schemes if required.
357
     *
358
     * An empty scheme is equivalent to removing the scheme.
359
     *
360
     * @param string $scheme The scheme to use with the new instance.
361
     * @return self A new instance with the specified scheme.
362
     * @throws \InvalidArgumentException for invalid or unsupported schemes.
363
     */
364
    public function withScheme($scheme)
365
    {
366
        $clone = clone $this;
367
        $clone->scheme = $scheme;
368
369
        return $clone;
370
    }
371
372
    /**
373
     * Create a new instance with the specified user information.
374
     *
375
     * This method MUST retain the state of the current instance, and return
376
     * a new instance that contains the specified user information.
377
     *
378
     * Password is optional, but the user information MUST include the
379
     * user; an empty string for the user is equivalent to removing user
380
     * information.
381
     *
382
     * @param string $user User name to use for authority.
383
     * @param null|string $password Password associated with $user.
384
     * @return self A new instance with the specified user information.
385
     */
386
    public function withUserInfo($user, $password = null)
387
    {
388
        $clone = clone $this;
389
390
        $clone->userInfo = static::buildUserInfo($user, $password);
391
392
        return $clone;
393
    }
394
395
    /**
396
     * Create a new instance with the specified host.
397
     *
398
     * This method MUST retain the state of the current instance, and return
399
     * a new instance that contains the specified host.
400
     *
401
     * An empty host value is equivalent to removing the host.
402
     *
403
     * @param string $host Hostname to use with the new instance.
404
     * @return self A new instance with the specified host.
405
     * @throws \InvalidArgumentException for invalid hostnames.
406
     */
407
    public function withHost($host)
408
    {
409
        $clone = clone $this;
410
        $clone->host = $host;
411
412
        return $clone;
413
    }
414
415
    /**
416
     * Create a new instance with the specified port.
417
     *
418
     * This method MUST retain the state of the current instance, and return
419
     * a new instance that contains the specified port.
420
     *
421
     * Implementations MUST raise an exception for ports outside the
422
     * established TCP and UDP port ranges.
423
     *
424
     * A null value provided for the port is equivalent to removing the port
425
     * information.
426
     *
427
     * @param null|int $port Port to use with the new instance; a null value
428
     *     removes the port information.
429
     * @return self A new instance with the specified port.
430
     * @throws \InvalidArgumentException for invalid ports.
431
     */
432
    public function withPort($port)
433
    {
434
        $clone = clone $this;
435
        $clone->port = $port;
436
437
        return $clone;
438
    }
439
440
    /**
441
     * Create a new instance with the specified path.
442
     *
443
     * This method MUST retain the state of the current instance, and return
444
     * a new instance that contains the specified path.
445
     *
446
     * The path MUST be prefixed with "/"; if not, the implementation MAY
447
     * provide the prefix itself.
448
     *
449
     * The implementation MUST percent-encode reserved characters as
450
     * specified in RFC 3986, Section 2, but MUST NOT double-encode any
451
     * characters.
452
     *
453
     * An empty path value is equivalent to removing the path.
454
     *
455
     * @param string $path The path to use with the new instance.
456
     * @return self A new instance with the specified path.
457
     * @throws \InvalidArgumentException for invalid paths.
458
     */
459
    public function withPath($path)
460
    {
461
        $clone = clone $this;
462
        $clone->path = $path;
463
464
        return $clone;
465
    }
466
467
    /**
468
     * Create a new instance with the specified query string.
469
     *
470
     * This method MUST retain the state of the current instance, and return
471
     * a new instance that contains the specified query string.
472
     *
473
     * If the query string is prefixed by "?", that character MUST be removed.
474
     * Additionally, the query string SHOULD be parseable by parse_str() in
475
     * order to be valid.
476
     *
477
     * The implementation MUST percent-encode reserved characters as
478
     * specified in RFC 3986, Section 2, but MUST NOT double-encode any
479
     * characters.
480
     *
481
     * An empty query string value is equivalent to removing the query string.
482
     *
483
     * @param string $query The query string to use with the new instance.
484
     * @return self A new instance with the specified query string.
485
     * @throws \InvalidArgumentException for invalid query strings.
486
     */
487
    public function withQuery($query)
488
    {
489
        $clone = clone $this;
490
        $clone->query = $query;
491
492
        return $clone;
493
    }
494
495
    /**
496
     * Create a new instance with the specified URI fragment.
497
     *
498
     * This method MUST retain the state of the current instance, and return
499
     * a new instance that contains the specified URI fragment.
500
     *
501
     * If the fragment is prefixed by "#", that character MUST be removed.
502
     *
503
     * An empty fragment value is equivalent to removing the fragment.
504
     *
505
     * @param string $fragment The URI fragment to use with the new instance.
506
     * @return self A new instance with the specified URI fragment.
507
     */
508
    public function withFragment($fragment)
509
    {
510
        $clone = clone $this;
511
        $clone->fragment = $fragment;
512
513
        return $clone;
514
    }
515
516
    /**
517
     * Convert this URI to the string representation.
518
     *
519
     * @return string
520
     */
521
    public function __toString()
522
    {
523
        $scheme = $this->getScheme();
524
        $authority = $this->getAuthority();
525
        $path = $this->getPath();
526
        $query = $this->getQuery();
527
        $fragment = $this->getFragment();
528
529
        return ($scheme ? $scheme . '://' : '') . $authority . $path . ($query ? '?' . $query : '') . ($fragment ? '#' . $fragment : '');
530
    }
531
532
    /**
533
     * Does this URI use a standard port?
534
     *
535
     * @param int|null $port
536
     * @param string $scheme
537
     *
538
     * @return bool
539
     */
540
    protected function isStandardPort($port, $scheme)
541
    {
542
        return ($scheme === 'http' && $port === 80) ||
543
            ($scheme === 'https' && $port === 443);
544
    }
545
}
546