Issues (3)

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/HttpClientLocationCreator.php (2 issues)

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
namespace Germania\ClientIpLocation;
3
4
use Psr\Http\Client\ClientInterface;
5
use Psr\Http\Client\ClientExceptionInterface;
6
7
use Psr\Http\Message\RequestInterface;
8
use Psr\Http\Message\RequestFactoryInterface;
9
use Psr\Http\Message\ResponseInterface;
10
11
use Psr\Log\LoggerInterface;
12
use Psr\Log\NullLogger;
13
use Psr\Log\LogLevel;
14
use Psr\Log\LoggerAwareTrait;
15
16
class HttpClientLocationCreator
17
{
18
    use LoggerAwareTrait;
19 1
20
    /**
21
     * @var ClientInterface
22
     */
23
    protected $client;
24
25
26
    /**
27
     * @var RequestFactoryInterface
28
     */
29
    public $request_factory;
30
31
32
    /**
33
     * Geocoder API endpoint.
34
     *
35
     * @var string
36
     */
37
    public $api;
38
39
40
    /**
41
     * IP adress query parameter
42
     *
43
     * @var string
44
     */
45
    public $ip_var_name = "ip";
46
47
48
    /**
49
     * @var callable
50
     */
51
    public $response_decoder;
52
53
54
    /**
55
     * @var mixed
56
     */
57
    public $default_location;
58
59
60
    /**
61
     * @var string
62
     */
63
    protected $error_loglevel = LogLevel::ERROR;
64
65
66
    /**
67
     * @var string
68
     */
69
    protected $client_exception_loglevel = LogLevel::NOTICE;
70
71
72
    /**
73 2
     * @param string                  $api              Geocoder API endpoint
74
     * @param ClientInterface         $client           PSR-18 HTTP Client
75 2
     * @param RequestFactoryInterface $request_factory  PSR-17 Request factory
76 2
     * @param callable|null           $response_decoder Optional: PSR-7 Response decoder callable
77 2
     */
78 2
    public function __construct( string $api, ClientInterface $client, RequestFactoryInterface $request_factory, callable $response_decoder = null, LoggerInterface $logger = null)
79 2
    {
80 2
        $this->setApiEndpoint( $api )
81
             ->setClient($client)
82
             ->setRequestFactory($request_factory)
83
             ->setResponseDecoder($response_decoder)
84
             ->setLogger( $logger ?: new NullLogger);
85
    }
86
87 2
88
89 2
    /**
90
     * @param  string $client_ip Client IP address
91
     */
92 2
    public function __invoke( string $client_ip )
93 2
    {
94
        $request = $this->createRequest($client_ip);
95
96
        try {
97
            $response = $this->client->sendRequest( $request);
98
            $response_status = $response->getStatusCode();
99
100
            switch($response_status):
101
                case 200:
102
                    return $this->decodeResponse($response);
103
                    break;
0 ignored issues
show
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
104
105
                case 404:
106
                    $msg = sprintf("Could not find location for IP address");
107
                    throw new ClientException($msg, $response_status);
108
                    break;
0 ignored issues
show
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
109
110
                default:
111
                    $msg = sprintf("Error response with error status code: '%s'", $response_status);
112
                    throw new ClientException($msg, $response_status);
113
114
            endswitch;
115 4
        }
116
        catch (ClientExceptionInterface $e) {
117 4
            $msg_location = sprintf("%s:%s", $e->getFile(), $e->getLine());
118 4
119
            $this->logger->log( $this->client_exception_loglevel, $e->getMessage(), [
120 4
                'type' => get_class($e),
121
                'code' => $e->getCode(),
122 4
                'request' => $request->getUri()->__toString(),
123
                'location' => $msg_location,
124
                'apiEndpoint' => $this->api,
125
                'clientIp' => $client_ip
126
            ]);
127
128
            return $this->default_location;
129
        }
130
        catch (\Throwable $e) {
131 4
            $msg = sprintf("Exception caught in HttpClientLocationCreator: %s", $e->getMessage());
132
            $msg_location = sprintf("%s:%s", $e->getFile(), $e->getLine());
133 4
            $this->logger->log( $this->error_loglevel, $msg, [
134 4
                'type' => get_class($e),
135 4
                'code' => $e->getCode(),
136
                'request' => $request->getUri()->__toString(),
137
                'location' => $msg_location,
138
                'apiEndpoint' => $this->api,
139
                'clientIp' => $client_ip
140
            ]);
141
142
            return $this->default_location;
143
        }
144
    }
145 2
146
147 2
148 2
    /**
149
     * @param  string $client_ip Client IP address
150
     * @return RequestInterface
151
     */
152
    public function createRequest( string $client_ip ) : RequestInterface
153
    {
154
        $client_ip_urlencoded = urlencode($client_ip);
155
        $query_parameter_field = "{{" . $this->ip_var_name . "}}";
156
157
        $api = str_replace($query_parameter_field, $client_ip_urlencoded, $this->api);
158 4
159
        return $this->request_factory->createRequest("GET", $api);
160 4
    }
161 4
162
163
164
    /**
165
     * @param  ResponseInterface $response
166
     * @return mixed
167
     */
168
    public function decodeResponse(ResponseInterface $response)
169
    {
170
        return $this->response_decoder
171 6
        ? ($this->response_decoder)($response)
172
        : json_decode($response->getBody(), "assoc");
173 6
    }
174 6
175
176
177
    /**
178
     * Sets the default location to return on error
179
     *
180
     * @param mixed $location
181
     */
182
    public function setDefaultLocation( $location ) : self
183 4
    {
184
        $this->default_location = $location;
185 4
        return $this;
186 4
    }
187
188
189
    /**
190
     * @param string $error_loglevel PSR-3 Loglevel name
191
     */
192
    public function setErrorLoglevel( string $error_loglevel ) {
193
        $this->error_loglevel = $error_loglevel;
194
        return $this;
195 4
    }
196
197 4
198 4
199
    /**
200
     * @param string $client_exception_loglevel PSR-3 Loglevel name
201
     */
202
    public function setClientExceptionLoglevel( string $client_exception_loglevel ) {
203
        $this->client_exception_loglevel = $client_exception_loglevel;
204
        return $this;
205
    }
206
207
208
    /**
209
     * Sets the API endpoint
210
     *
211
     * @param string $api
212
     */
213
    public function setApiEndpoint( string $api ) : self
214
    {
215
        $this->api = $api;
216
        return $this;
217
    }
218
219
220
221
    /**
222
     * Sets the HTTP Client to use.
223
     *
224
     * @param ClientInterface $client
225
     */
226
    public function setClient( ClientInterface $client ) : self
227
    {
228
        $this->client = $client;
229
        return $this;
230
    }
231
232
233
    /**
234
     * Sets the PSR-17 Request factory
235
     *
236
     * @param RequestFactoryInterface $request_factory
237
     */
238
    public function setRequestFactory( RequestFactoryInterface $request_factory ) : self
239
    {
240
        $this->request_factory = $request_factory;
241
        return $this;
242
    }
243
244
245
    /**
246
     * Sets the PSR-7 Response decoder callable.
247
     *
248
     * @param callable $response_decoder
249
     */
250
    public function setResponseDecoder( callable $response_decoder = null ) : self
251
    {
252
        $this->response_decoder = $response_decoder;
253
        return $this;
254
    }
255
256
}
257