These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | |||
| 3 | /* |
||
| 4 | * This file is part of the puli/installer package. |
||
| 5 | * |
||
| 6 | * (c) Bernhard Schussek <[email protected]> |
||
| 7 | * |
||
| 8 | * For the full copyright and license information, please view the LICENSE |
||
| 9 | * file that was distributed with this source code. |
||
| 10 | */ |
||
| 11 | |||
| 12 | namespace Puli\Installer; |
||
| 13 | |||
| 14 | use RuntimeException; |
||
| 15 | |||
| 16 | /** |
||
| 17 | * Downloads files. |
||
| 18 | * |
||
| 19 | * This file was adapted from the installer file bundled with Composer. For the |
||
| 20 | * original file, authors and copyright information see |
||
| 21 | * |
||
| 22 | * https://github.com/composer/getcomposer.org/blob/master/web/installer |
||
| 23 | * |
||
| 24 | * @author Nils Adermann <[email protected]> |
||
| 25 | * @author Jordi Boggiano <[email protected]> |
||
| 26 | * @author Thomas Rudolph <[email protected]> |
||
| 27 | * @author Bernhard Schussek <[email protected]> |
||
| 28 | */ |
||
| 29 | class HttpClient |
||
| 30 | { |
||
| 31 | /** |
||
| 32 | * @var array |
||
| 33 | */ |
||
| 34 | private $headers = array( |
||
| 35 | "Connection: close\r\n", |
||
| 36 | "User-Agent: Puli Installer\r\n", |
||
| 37 | ); |
||
| 38 | |||
| 39 | /** |
||
| 40 | * @var bool |
||
| 41 | */ |
||
| 42 | private $tls = false; |
||
| 43 | |||
| 44 | /** |
||
| 45 | * Creates the HTTP client. |
||
| 46 | * |
||
| 47 | * @param bool $disableTls Whether to disable TLS. |
||
| 48 | */ |
||
| 49 | 5 | public function __construct($disableTls = false) |
|
| 50 | { |
||
| 51 | 5 | $this->tls = !$disableTls; |
|
| 52 | |||
| 53 | 5 | if (extension_loaded('zlib')) { |
|
| 54 | 5 | $this->headers[] = "Accept-Encoding: gzip\r\n"; |
|
| 55 | 5 | } |
|
| 56 | 5 | } |
|
| 57 | |||
| 58 | /** |
||
| 59 | * Downloads a file. |
||
| 60 | * |
||
| 61 | * @param string $url The URL of the file to download. |
||
| 62 | * |
||
| 63 | * @return string The downloaded file body. |
||
| 64 | */ |
||
| 65 | 5 | public function download($url) |
|
| 66 | { |
||
| 67 | 5 | if ($this->tls) { |
|
| 68 | 5 | humbug_set_headers($this->headers); |
|
| 69 | 5 | $result = humbug_get_contents($url); |
|
| 70 | 5 | } else { |
|
| 71 | $context = $this->getNonSslStreamContext($url); |
||
| 72 | $result = file_get_contents($url, null, $context); |
||
| 73 | } |
||
| 74 | |||
| 75 | 5 | if ($result && extension_loaded('zlib')) { |
|
| 76 | 5 | $decode = false; |
|
| 77 | 5 | $responseHeaders = $this->tls ? humbug_get_headers() : $http_response_header; |
|
|
0 ignored issues
–
show
|
|||
| 78 | |||
| 79 | 5 | foreach ($responseHeaders as $header) { |
|
| 80 | 5 | if (preg_match('{^content-encoding: *gzip *$}i', $header)) { |
|
| 81 | $decode = true; |
||
| 82 | continue; |
||
| 83 | 5 | } elseif (preg_match('{^HTTP/}i', $header)) { |
|
| 84 | 5 | $decode = false; |
|
| 85 | 5 | } |
|
| 86 | 5 | } |
|
| 87 | |||
| 88 | 5 | if ($decode) { |
|
| 89 | $result = version_compare(PHP_VERSION, '5.4.0', '>=') |
||
| 90 | ? zlib_decode($result) |
||
| 91 | // work around issue with gzuncompress & co that do not work with all gzip checksums |
||
| 92 | : file_get_contents('compress.zlib://data:application/octet-stream;base64,'.base64_encode($result)); |
||
| 93 | |||
| 94 | if (!$result) { |
||
| 95 | throw new RuntimeException('Failed to decode zlib stream'); |
||
| 96 | } |
||
| 97 | } |
||
| 98 | 5 | } |
|
| 99 | |||
| 100 | 5 | return $result; |
|
| 101 | } |
||
| 102 | |||
| 103 | private function getNonSslStreamContext($url) |
||
|
0 ignored issues
–
show
getNonSslStreamContext uses the super-global variable $_SERVER which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
Loading history...
|
|||
| 104 | { |
||
| 105 | // Handle system proxy |
||
| 106 | if (!empty($_SERVER['HTTP_PROXY']) || !empty($_SERVER['http_proxy'])) { |
||
| 107 | // Some systems seem to rely on a lowercased version instead... |
||
| 108 | $proxy = parse_url(!empty($_SERVER['http_proxy']) ? $_SERVER['http_proxy'] : $_SERVER['HTTP_PROXY']); |
||
| 109 | } |
||
| 110 | |||
| 111 | if (!empty($proxy)) { |
||
| 112 | $proxyURL = isset($proxy['scheme']) ? $proxy['scheme'].'://' : ''; |
||
| 113 | $proxyURL .= isset($proxy['host']) ? $proxy['host'] : ''; |
||
| 114 | |||
| 115 | if (isset($proxy['port'])) { |
||
| 116 | $proxyURL .= ':'.$proxy['port']; |
||
| 117 | } elseif ('http://' === substr($proxyURL, 0, 7)) { |
||
| 118 | $proxyURL .= ':80'; |
||
| 119 | } elseif ('https://' === substr($proxyURL, 0, 8)) { |
||
| 120 | $proxyURL .= ':443'; |
||
| 121 | } |
||
| 122 | |||
| 123 | // http(s):// is not supported in proxy |
||
| 124 | $proxyURL = str_replace(array('http://', 'https://'), array('tcp://', 'ssl://'), $proxyURL); |
||
| 125 | |||
| 126 | if (0 === strpos($proxyURL, 'ssl:') && !extension_loaded('openssl')) { |
||
| 127 | throw new RuntimeException('You must enable the openssl extension to use a proxy over https'); |
||
| 128 | } |
||
| 129 | |||
| 130 | $options['http'] = array( |
||
|
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
$options was never initialized. Although not strictly required by PHP, it is generally a good practice to add $options = array(); before regardless.
Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code. Let’s take a look at an example: foreach ($collection as $item) {
$myArray['foo'] = $item->getFoo();
if ($item->hasBar()) {
$myArray['bar'] = $item->getBar();
}
// do something with $myArray
}
As you can see in this example, the array This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop. Loading history...
|
|||
| 131 | 'proxy' => $proxyURL, |
||
| 132 | ); |
||
| 133 | |||
| 134 | // enabled request_fulluri unless it is explicitly disabled |
||
| 135 | switch (parse_url($url, PHP_URL_SCHEME)) { |
||
| 136 | View Code Duplication | case 'http': // default request_fulluri to true |
|
| 137 | $reqFullUriEnv = getenv('HTTP_PROXY_REQUEST_FULLURI'); |
||
| 138 | if ($reqFullUriEnv === false || $reqFullUriEnv === '' || (strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv)) { |
||
| 139 | $options['http']['request_fulluri'] = true; |
||
| 140 | } |
||
| 141 | break; |
||
| 142 | View Code Duplication | case 'https': // default request_fulluri to true |
|
| 143 | $reqFullUriEnv = getenv('HTTPS_PROXY_REQUEST_FULLURI'); |
||
| 144 | if ($reqFullUriEnv === false || $reqFullUriEnv === '' || (strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv)) { |
||
| 145 | $options['http']['request_fulluri'] = true; |
||
| 146 | } |
||
| 147 | break; |
||
| 148 | } |
||
| 149 | |||
| 150 | if (isset($proxy['user'])) { |
||
| 151 | $auth = urldecode($proxy['user']); |
||
| 152 | if (isset($proxy['pass'])) { |
||
| 153 | $auth .= ':'.urldecode($proxy['pass']); |
||
| 154 | } |
||
| 155 | $auth = base64_encode($auth); |
||
| 156 | |||
| 157 | $options['http']['header'] = "Proxy-Authorization: Basic {$auth}\r\n"; |
||
| 158 | } |
||
| 159 | } |
||
| 160 | |||
| 161 | if (isset($options['http']['header'])) { |
||
| 162 | $options['http']['header'] .= implode('', $this->headers); |
||
| 163 | } else { |
||
| 164 | $options['http']['header'] = implode('', $this->headers); |
||
|
0 ignored issues
–
show
The variable
$options does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
Loading history...
|
|||
| 165 | } |
||
| 166 | |||
| 167 | $options['http']['protocol_version'] = 1.1; |
||
| 168 | |||
| 169 | return stream_context_create($options); |
||
| 170 | } |
||
| 171 | } |
||
| 172 |
If you define a variable conditionally, it can happen that it is not defined for all execution paths.
Let’s take a look at an example:
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.
Available Fixes
Check for existence of the variable explicitly:
Define a default value for the variable:
Add a value for the missing path: