This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
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 contains the UrlQuery class which is a wrapper for cURL |
||
5 | * |
||
6 | * @copyright 2015 Vladimir Jimenez |
||
7 | * @license https://github.com/allejo/PhpSoda/blob/master/LICENSE.md MIT |
||
8 | */ |
||
9 | |||
10 | namespace allejo\Socrata\Utilities; |
||
11 | |||
12 | use allejo\Socrata\Exceptions\CurlException; |
||
13 | use allejo\Socrata\Exceptions\HttpException; |
||
14 | use allejo\Socrata\Exceptions\SodaException; |
||
15 | |||
16 | /** |
||
17 | * A wrapper class for working with cURL requests. |
||
18 | * |
||
19 | * This class configures cURL with all of the appropriate authentication information and proper cURL configuration for |
||
20 | * processing requests. |
||
21 | * |
||
22 | * There's no need to access this class outside of this library as the appropriate functionality is properly wrapped in |
||
23 | * the SodaDataset class. |
||
24 | * |
||
25 | * @package allejo\Socrata\Utilities |
||
26 | * @since 0.1.0 |
||
27 | */ |
||
28 | class UrlQuery |
||
29 | { |
||
30 | /** |
||
31 | * The default protocol the Soda API expects |
||
32 | */ |
||
33 | const DEFAULT_PROTOCOL = "https"; |
||
34 | |||
35 | /** |
||
36 | * The API endpoint that will be used in all requests |
||
37 | * |
||
38 | * @var string |
||
39 | */ |
||
40 | private $url; |
||
41 | |||
42 | /** |
||
43 | * The cURL object this class is a wrapper for |
||
44 | * |
||
45 | * @var resource |
||
46 | */ |
||
47 | private $cURL; |
||
48 | |||
49 | /** |
||
50 | * The Socrata API token |
||
51 | * |
||
52 | * @var string |
||
53 | */ |
||
54 | private $token; |
||
55 | |||
56 | /** |
||
57 | * HTTP headers sent in all requests |
||
58 | * |
||
59 | * @var string[] |
||
60 | */ |
||
61 | private $headers; |
||
62 | |||
63 | /** |
||
64 | * The OAuth 2.0 token sent in all requests |
||
65 | * |
||
66 | * @var string |
||
67 | */ |
||
68 | private $oAuth2Token; |
||
69 | |||
70 | /** |
||
71 | * Configure all of the authentication needed for cURL requests and the API endpoint |
||
72 | * |
||
73 | * **Note** If OAuth 2.0 is used for authentication, do not give values to the $email and $password parameters; |
||
74 | * instead, use the `setOAuth2Token()` function. An API token will still be required to bypass throttling. |
||
75 | * |
||
76 | * @param string $url The API endpoint this instance will be calling |
||
77 | * @param string $token The API token used in order to bypass throttling |
||
78 | * @param string $email The email address of the user being authenticated through Basic Authentication |
||
79 | * @param string $password The password for the user being authenticated through Basic Authentication |
||
80 | * |
||
81 | * @see setOAuth2Token |
||
82 | * |
||
83 | * @since 0.1.0 |
||
84 | */ |
||
85 | public function __construct ($url, $token = "", $email = "", $password = "") |
||
86 | { |
||
87 | $this->url = $url; |
||
88 | $this->token = $token; |
||
89 | $this->cURL = curl_init(); |
||
90 | |||
91 | // Build up the headers we'll need to pass |
||
92 | $this->headers = array( |
||
93 | 'Accept: application/json', |
||
94 | 'Content-type: application/json', |
||
95 | 'X-App-Token: ' . $this->token |
||
96 | ); |
||
97 | |||
98 | $this->configureCurl($email, $password); |
||
99 | } |
||
100 | |||
101 | /** |
||
102 | * Clean up after ourselves; clean up the cURL object. |
||
103 | */ |
||
104 | public function __destruct () |
||
105 | { |
||
106 | curl_close($this->cURL); |
||
107 | } |
||
108 | |||
109 | /** |
||
110 | * Set the OAuth 2.0 token that requests will be using. This function does **not** retrieve a token, it simply uses |
||
111 | * the existing token and sends it as authentication. |
||
112 | * |
||
113 | * @param string $token The OAuth 2.0 token used in requests |
||
114 | * |
||
115 | * @since 0.1.2 |
||
116 | */ |
||
117 | public function setOAuth2Token ($token) |
||
118 | { |
||
119 | if (!StringUtilities::isNullOrEmpty($token)) |
||
120 | { |
||
121 | $this->oAuth2Token = $token; |
||
122 | $this->headers[] = "Authorization: OAuth " . $this->oAuth2Token; |
||
123 | } |
||
124 | } |
||
125 | |||
126 | /** |
||
127 | * Send a GET request |
||
128 | * |
||
129 | * @param string $params The GET parameters to be appended to the API endpoint |
||
130 | * @param bool $associativeArray When true, the returned data will be associative arrays; otherwise, it'll be an |
||
131 | * StdClass object. |
||
132 | * @param array $headers An array where the return HTTP headers will be stored |
||
0 ignored issues
–
show
|
|||
133 | * |
||
134 | * @see SodaClient::enableAssociativeArrays |
||
135 | * |
||
136 | * @since 0.1.0 |
||
137 | * |
||
138 | * @return mixed An associative array matching the returned JSON result or an StdClass object |
||
139 | */ |
||
140 | public function sendGet ($params, $associativeArray, &$headers = NULL) |
||
141 | { |
||
142 | if (is_array($params)) |
||
143 | { |
||
144 | $parameters = self::formatParameters($params); |
||
145 | $full_url = self::buildQuery($this->url, $parameters); |
||
146 | } |
||
147 | else if (!empty($params)) |
||
148 | { |
||
149 | $full_url = $this->url . "?" . $params; |
||
150 | } |
||
151 | else |
||
152 | { |
||
153 | $full_url = $this->url; |
||
154 | } |
||
155 | |||
156 | curl_setopt($this->cURL, CURLOPT_URL, $full_url); |
||
157 | |||
158 | return $this->handleQuery($associativeArray, $headers); |
||
0 ignored issues
–
show
It seems like
$headers defined by parameter $headers on line 140 can also be of type null ; however, allejo\Socrata\Utilities\UrlQuery::handleQuery() does only seem to accept array , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble. ![]() |
|||
159 | } |
||
160 | |||
161 | /** |
||
162 | * Send a POST request |
||
163 | * |
||
164 | * @param string $dataAsJson The data that will be sent to Socrata as JSON |
||
165 | * @param bool $associativeArray When true, the returned data will be associative arrays; otherwise, it'll be an |
||
166 | * StdClass object. |
||
167 | * @param array $headers An array where the return HTTP headers will be stored |
||
0 ignored issues
–
show
Should the type for parameter
$headers not be array|null ? Also, consider making the array more specific, something like array<String> , or String[] .
This check looks for It makes a suggestion as to what type it considers more descriptive. In addition it
looks for parameters that have the generic type Most often this is a case of a parameter that can be null in addition to its declared types. ![]() |
|||
168 | * |
||
169 | * @see SodaClient::enableAssociativeArrays |
||
170 | * |
||
171 | * @since 0.1.0 |
||
172 | * |
||
173 | * @return mixed An associative array matching the returned JSON result or an StdClass object |
||
174 | */ |
||
175 | public function sendPost ($dataAsJson, $associativeArray, &$headers = NULL) |
||
176 | { |
||
177 | $this->setPostFields($dataAsJson); |
||
178 | |||
179 | curl_setopt_array($this->cURL, array( |
||
180 | CURLOPT_POST => true, |
||
181 | CURLOPT_CUSTOMREQUEST => "POST" |
||
182 | )); |
||
183 | |||
184 | return $this->handleQuery($associativeArray, $headers); |
||
0 ignored issues
–
show
It seems like
$headers defined by parameter $headers on line 175 can also be of type null ; however, allejo\Socrata\Utilities\UrlQuery::handleQuery() does only seem to accept array , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble. ![]() |
|||
185 | } |
||
186 | |||
187 | /** |
||
188 | * Send a PUT request |
||
189 | * |
||
190 | * @param string $dataAsJson The data that will be sent to Socrata as JSON |
||
191 | * @param bool $associativeArray When true, the returned data will be associative arrays; otherwise, it'll be an |
||
192 | * StdClass object. |
||
193 | * @param array $headers An array where the return HTTP headers will be stored |
||
0 ignored issues
–
show
Should the type for parameter
$headers not be array|null ? Also, consider making the array more specific, something like array<String> , or String[] .
This check looks for It makes a suggestion as to what type it considers more descriptive. In addition it
looks for parameters that have the generic type Most often this is a case of a parameter that can be null in addition to its declared types. ![]() |
|||
194 | * |
||
195 | * @see SodaClient::enableAssociativeArrays |
||
196 | * |
||
197 | * @since 0.1.0 |
||
198 | * |
||
199 | * @return mixed An associative array matching the returned JSON result or an StdClass object |
||
200 | */ |
||
201 | public function sendPut ($dataAsJson, $associativeArray, &$headers = NULL) |
||
202 | { |
||
203 | $this->setPostFields($dataAsJson); |
||
204 | |||
205 | curl_setopt($this->cURL, CURLOPT_CUSTOMREQUEST, "PUT"); |
||
206 | |||
207 | return $this->handleQuery($associativeArray, $headers); |
||
0 ignored issues
–
show
It seems like
$headers defined by parameter $headers on line 201 can also be of type null ; however, allejo\Socrata\Utilities\UrlQuery::handleQuery() does only seem to accept array , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble. ![]() |
|||
208 | } |
||
209 | |||
210 | /** |
||
211 | * Send a DELETE request |
||
212 | * |
||
213 | * @param bool $associativeArray When true, the returned data will be associative arrays; otherwise, it'll be an |
||
214 | * StdClass object. |
||
215 | * @param array $headers An array where the return HTTP headers will be stored |
||
0 ignored issues
–
show
Should the type for parameter
$headers not be array|null ? Also, consider making the array more specific, something like array<String> , or String[] .
This check looks for It makes a suggestion as to what type it considers more descriptive. In addition it
looks for parameters that have the generic type Most often this is a case of a parameter that can be null in addition to its declared types. ![]() |
|||
216 | * |
||
217 | * @see SodaClient::enableAssociativeArrays |
||
218 | * |
||
219 | * @since 0.1.2 |
||
220 | * |
||
221 | * @return mixed An associative array matching the returned JSON result or an StdClass object |
||
222 | */ |
||
223 | public function sendDelete ($associativeArray, &$headers = NULL) |
||
224 | { |
||
225 | curl_setopt($this->cURL, CURLOPT_CUSTOMREQUEST, "DELETE"); |
||
226 | |||
227 | $this->handleQuery($associativeArray, $headers, true); |
||
0 ignored issues
–
show
It seems like
$headers defined by parameter $headers on line 223 can also be of type null ; however, allejo\Socrata\Utilities\UrlQuery::handleQuery() does only seem to accept array , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble. ![]() |
|||
228 | } |
||
229 | |||
230 | /** |
||
231 | * Set the POST fields that will be submitted in the cURL request |
||
232 | * |
||
233 | * @param string $dataAsJson The data that will be sent to Socrata as JSON |
||
234 | * |
||
235 | * @since 0.1.0 |
||
236 | */ |
||
237 | private function setPostFields ($dataAsJson) |
||
238 | { |
||
239 | curl_setopt($this->cURL, CURLOPT_POSTFIELDS, $dataAsJson); |
||
240 | } |
||
241 | |||
242 | /** |
||
243 | * Handle the execution of the cURL request. This function will also save the returned HTTP headers and handle them |
||
244 | * appropriately. |
||
245 | * |
||
246 | * @param bool $associativeArray When true, the returned data will be associative arrays; otherwise, it'll be an |
||
247 | * StdClass object. |
||
248 | * @param array $headers The reference to the array where the returned HTTP headers will be stored |
||
249 | * @param bool $ignoreReturn True if the returned body should be ignored |
||
250 | * |
||
251 | * @since 0.1.0 |
||
252 | * |
||
253 | * @throws \allejo\Socrata\Exceptions\CurlException If cURL is misconfigured or encounters an error |
||
254 | * @throws \allejo\Socrata\Exceptions\HttpException An HTTP status of something other 200 is returned |
||
255 | * @throws \allejo\Socrata\Exceptions\SodaException A SODA API error is returned |
||
256 | * |
||
257 | * @return mixed|NULL |
||
258 | */ |
||
259 | private function handleQuery ($associativeArray, &$headers, $ignoreReturn = false) |
||
260 | { |
||
261 | $result = $this->executeCurl(); |
||
262 | |||
263 | // Ignore "100 Continue" headers |
||
264 | $continueHeader = "HTTP/1.1 100 Continue\r\n\r\n"; |
||
265 | |||
266 | if (strpos($result, $continueHeader) === 0) |
||
267 | { |
||
268 | $result = str_replace($continueHeader, '', $result); |
||
269 | } |
||
270 | |||
271 | list($header, $body) = explode("\r\n\r\n", $result, 2); |
||
272 | |||
273 | $this->saveHeaders($header, $headers); |
||
274 | |||
275 | if ($ignoreReturn) |
||
276 | { |
||
277 | return NULL; |
||
278 | } |
||
279 | |||
280 | $resultArray = $this->handleResponseBody($body, $result); |
||
281 | |||
282 | return ($associativeArray) ? $resultArray : json_decode($body, false); |
||
283 | } |
||
284 | |||
285 | /** |
||
286 | * Configure the cURL instance and its credentials for Basic Authentication that this instance will be working with |
||
287 | * |
||
288 | * @param string $email The email for the user with Basic Authentication |
||
289 | * @param string $password The password for the user with Basic Authentication |
||
290 | * |
||
291 | * @since 0.1.0 |
||
292 | */ |
||
293 | private function configureCurl ($email, $password) |
||
294 | { |
||
295 | curl_setopt_array($this->cURL, array( |
||
296 | CURLOPT_URL => $this->url, |
||
297 | CURLOPT_HEADER => true, |
||
298 | CURLOPT_HTTPHEADER => $this->headers, |
||
299 | CURLOPT_RETURNTRANSFER => true, |
||
300 | CURLOPT_SSLVERSION => 6 |
||
301 | )); |
||
302 | |||
303 | if (!StringUtilities::isNullOrEmpty($email) && !StringUtilities::isNullOrEmpty($password)) |
||
304 | { |
||
305 | curl_setopt_array($this->cURL, array( |
||
306 | CURLOPT_HTTPAUTH => CURLAUTH_BASIC, |
||
307 | CURLOPT_USERPWD => $email . ":" . $password |
||
308 | )); |
||
309 | } |
||
310 | } |
||
311 | |||
312 | /** |
||
313 | * Execute the finalized cURL object that has already been configured |
||
314 | * |
||
315 | * @since 0.1.0 |
||
316 | * |
||
317 | * @throws \allejo\Socrata\Exceptions\CurlException If cURL is misconfigured or encounters an error |
||
318 | * |
||
319 | * @return mixed |
||
320 | */ |
||
321 | private function executeCurl () |
||
322 | { |
||
323 | $result = curl_exec($this->cURL); |
||
324 | |||
325 | if (!$result) |
||
326 | { |
||
327 | throw new CurlException($this->cURL); |
||
328 | } |
||
329 | |||
330 | return $result; |
||
331 | } |
||
332 | |||
333 | /** |
||
334 | * Check for unexpected errors or SODA API errors |
||
335 | * |
||
336 | * @param string $body The body of the response |
||
337 | * @param string $result The unfiltered result cURL received |
||
338 | * |
||
339 | * @since 0.1.0 |
||
340 | * |
||
341 | * @throws \allejo\Socrata\Exceptions\HttpException If the $body returned was not a JSON object |
||
342 | * @throws \allejo\Socrata\Exceptions\SodaException The returned JSON object in the $body was a SODA API error |
||
343 | * |
||
344 | * @return mixed An associative array of the decoded JSON response |
||
345 | */ |
||
346 | private function handleResponseBody ($body, $result) |
||
347 | { |
||
348 | // We somehow got a server error from Socrata without a JSON object with details |
||
349 | if (!StringUtilities::isJson($body)) |
||
350 | { |
||
351 | $httpCode = curl_getinfo($this->cURL, CURLINFO_HTTP_CODE); |
||
352 | |||
353 | throw new HttpException($httpCode, $result); |
||
354 | } |
||
355 | |||
356 | $resultArray = json_decode($body, true); |
||
357 | |||
358 | // We got an error JSON object back from Socrata |
||
359 | if (array_key_exists('error', $resultArray) && $resultArray['error']) |
||
360 | { |
||
361 | throw new SodaException($resultArray); |
||
362 | } |
||
363 | |||
364 | return $resultArray; |
||
365 | } |
||
366 | |||
367 | /** |
||
368 | * Handle the returned HTTP headers and save them into an array |
||
369 | * |
||
370 | * @param string $header The returned HTTP headers |
||
371 | * @param array $headers The reference to the array where our headers will be saved |
||
372 | * |
||
373 | * @since 0.1.0 |
||
374 | */ |
||
375 | private function saveHeaders ($header, &$headers) |
||
376 | { |
||
377 | if ($headers === NULL) |
||
378 | { |
||
379 | return; |
||
380 | } |
||
381 | |||
382 | $header = explode("\r\n", $header); |
||
383 | $headers = array(); |
||
384 | $headerLength = count($header); |
||
385 | |||
386 | // The 1st element is the HTTP code, so we can safely skip it |
||
387 | for ($i = 1; $i < $headerLength; $i++) |
||
388 | { |
||
389 | list($key, $val) = explode(":", $header[$i]); |
||
390 | $headers[$key] = trim($val); |
||
391 | } |
||
392 | } |
||
393 | |||
394 | /** |
||
395 | * Build a URL with GET parameters formatted into the URL |
||
396 | * |
||
397 | * @param string $url The base URL |
||
398 | * @param array $params The GET parameters that need to be appended to the base URL |
||
399 | * |
||
400 | * @since 0.1.0 |
||
401 | * |
||
402 | * @return string A URL with GET parameters |
||
403 | */ |
||
404 | private static function buildQuery ($url, $params = array()) |
||
405 | { |
||
406 | $full_url = $url; |
||
407 | |||
408 | if (count($params) > 0) |
||
409 | { |
||
410 | $full_url .= "?" . implode("&", $params); |
||
411 | } |
||
412 | |||
413 | return $full_url; |
||
414 | } |
||
415 | |||
416 | /** |
||
417 | * Format an array into a URL encoded values to be submitted in cURL requests |
||
418 | * |
||
419 | * **Input** |
||
420 | * |
||
421 | * ```php |
||
422 | * array( |
||
423 | * "foo" => "bar", |
||
424 | * "param" => "value" |
||
425 | * ) |
||
426 | * ``` |
||
427 | * |
||
428 | * **Output** |
||
429 | * |
||
430 | * ```php |
||
431 | * array( |
||
432 | * "foo=bar", |
||
433 | * "param=value" |
||
434 | * ) |
||
435 | * ``` |
||
436 | * |
||
437 | * @param array $params An array containing parameter names as keys and parameter values as values in the array. |
||
438 | * |
||
439 | * @return string[] A URL encoded and combined array of GET parameters to be sent |
||
440 | */ |
||
441 | private static function formatParameters ($params) |
||
442 | { |
||
443 | $parameters = array(); |
||
444 | |||
445 | foreach ($params as $key => $value) |
||
446 | { |
||
447 | $parameters[] = rawurlencode($key) . "=" . rawurlencode($value); |
||
448 | } |
||
449 | |||
450 | return $parameters; |
||
451 | } |
||
452 | } |
||
453 |
This check looks for
@param
annotations where the type inferred by our type inference engine differs from the declared type.It makes a suggestion as to what type it considers more descriptive. In addition it looks for parameters that have the generic type
array
and suggests a stricter type likearray<String>
.Most often this is a case of a parameter that can be null in addition to its declared types.